Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1365913 > unrolled thread
| Started by | Mylène Josserand <mylene.josserand@free-electrons.com> |
|---|---|
| First post | 2016-03-29 09:00 +0200 |
| Last post | 2016-03-29 09:00 +0200 |
| Articles | 7 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH 0/8] rtc: m41t80: update and add functionalities Mylène Josserand <mylene.josserand@free-electrons.com> - 2016-03-29 09:00 +0200
[PATCH 1/8] rtc: m41t80: update sysfs entries export Mylène Josserand <mylene.josserand@free-electrons.com> - 2016-03-29 09:00 +0200
[PATCH 8/8] rtc: m41t80: handle oscillator failure bit Mylène Josserand <mylene.josserand@free-electrons.com> - 2016-03-29 09:00 +0200
[PATCH 6/8] rtc: m41t80: add alarm functionality Mylène Josserand <mylene.josserand@free-electrons.com> - 2016-03-29 09:00 +0200
[PATCH 4/8] rtc: m41t80: add the use of 'BIT' macro Mylène Josserand <mylene.josserand@free-electrons.com> - 2016-03-29 09:00 +0200
[PATCH 2/8] rtc: m41t80: remove proc macro Mylène Josserand <mylene.josserand@free-electrons.com> - 2016-03-29 09:00 +0200
[PATCH 3/8] rtc: m41t80: replace i2c functions to smbus ones Mylène Josserand <mylene.josserand@free-electrons.com> - 2016-03-29 09:00 +0200
| From | Mylène Josserand <mylene.josserand@free-electrons.com> |
|---|---|
| Date | 2016-03-29 09:00 +0200 |
| Subject | [PATCH 0/8] rtc: m41t80: update and add functionalities |
| Message-ID | <rhVN7-2iO-5@gated-at.bofh.it> |
This patchset updates the m41t80 driver :
- update the sysfs entries export to use DEVICE_ATTR_XX
- remove some unnecessary macro
- replace old i2c functions to smbus ones
- use BIT macro
- remove some warnings
- replace obsolete functions
It adds also some functionalities :
- alarm IRQ which was previously removed because it was not working
- wakealarm to use the RTC and set an alarm to wakeup the system
- Oscillator failure to print an error if it is set
Mylène Josserand (8):
rtc: m41t80: update sysfs entries export
rtc: m41t80: remove proc macro
rtc: m41t80: replace i2c functions to smbus ones
rtc: m41t80: add the use of 'BIT' macro
rtc: m41t80: remove warnings and replace obsolete function
rtc: m41t80: add alarm functionality
rtc: m41t80: add wakealarm functionality
rtc: m41t80: handle oscillator failure bit
drivers/rtc/rtc-m41t80.c | 443 +++++++++++++++++++++++++++++++----------------
1 file changed, 289 insertions(+), 154 deletions(-)
--
2.8.0.rc3
[toc] | [next] | [standalone]
| From | Mylène Josserand <mylene.josserand@free-electrons.com> |
|---|---|
| Date | 2016-03-29 09:00 +0200 |
| Subject | [PATCH 1/8] rtc: m41t80: update sysfs entries export |
| Message-ID | <rhVN8-2iO-25@gated-at.bofh.it> |
| In reply to | #1365913 |
The driver used an old sysfs entry export.
Update it to use the DEVICE_ATTR_XX macro and remove the unnecessary
CONFIG_RTC_INTF_SYSFS macro.
Signed-off-by: Mylène Josserand <mylene.josserand@free-electrons.com>
---
drivers/rtc/rtc-m41t80.c | 56 +++++++++++++++++++++++++++---------------------
1 file changed, 32 insertions(+), 24 deletions(-)
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index d107a8e..2721789 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -230,9 +230,8 @@ static struct rtc_class_ops m41t80_rtc_ops = {
.proc = m41t80_rtc_proc,
};
-#if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE)
-static ssize_t m41t80_sysfs_show_flags(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t flags_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
int val;
@@ -242,10 +241,10 @@ static ssize_t m41t80_sysfs_show_flags(struct device *dev,
return val;
return sprintf(buf, "%#x\n", val);
}
-static DEVICE_ATTR(flags, S_IRUGO, m41t80_sysfs_show_flags, NULL);
+static DEVICE_ATTR_RO(flags);
-static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t sqwfreq_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct m41t80_data *clientdata = i2c_get_clientdata(client);
@@ -272,9 +271,10 @@ static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev,
}
return sprintf(buf, "%d\n", val);
}
-static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+
+static ssize_t sqwfreq_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct m41t80_data *clientdata = i2c_get_clientdata(client);
@@ -324,8 +324,7 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev,
}
return count;
}
-static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR,
- m41t80_sysfs_show_sqwfreq, m41t80_sysfs_set_sqwfreq);
+static DEVICE_ATTR_RW(sqwfreq);
static struct attribute *attrs[] = {
&dev_attr_flags.attr,
@@ -336,17 +335,6 @@ static struct attribute_group attr_group = {
.attrs = attrs,
};
-static int m41t80_sysfs_register(struct device *dev)
-{
- return sysfs_create_group(&dev->kobj, &attr_group);
-}
-#else
-static int m41t80_sysfs_register(struct device *dev)
-{
- return 0;
-}
-#endif
-
#ifdef CONFIG_RTC_DRV_M41T80_WDT
/*
*****************************************************************************
@@ -636,6 +624,14 @@ static struct notifier_block wdt_notifier = {
*
*****************************************************************************
*/
+
+static void m41t80_remove_sysfs_group(void *_dev)
+{
+ struct device *dev = _dev;
+
+ sysfs_remove_group(&dev->kobj, &attr_group);
+}
+
static int m41t80_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -697,9 +693,21 @@ static int m41t80_probe(struct i2c_client *client,
return rc;
}
- rc = m41t80_sysfs_register(&client->dev);
- if (rc)
+ /* Export sysfs entries */
+ rc = sysfs_create_group(&(&client->dev)->kobj, &attr_group);
+ if (rc) {
+ dev_err(&client->dev, "Failed to create sysfs group: %d\n", rc);
return rc;
+ }
+
+ rc = devm_add_action(&client->dev, m41t80_remove_sysfs_group,
+ &client->dev);
+ if (rc) {
+ m41t80_remove_sysfs_group(&client->dev);
+ dev_err(&client->dev,
+ "Failed to add sysfs cleanup action: %d\n", rc);
+ return rc;
+ }
#ifdef CONFIG_RTC_DRV_M41T80_WDT
if (clientdata->features & M41T80_FEATURE_HT) {
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Mylène Josserand <mylene.josserand@free-electrons.com> |
|---|---|
| Date | 2016-03-29 09:00 +0200 |
| Subject | [PATCH 8/8] rtc: m41t80: handle oscillator failure bit |
| Message-ID | <rhVN8-2iO-23@gated-at.bofh.it> |
| In reply to | #1365913 |
Handle the Oscillator Failure (OF) bit on each read of date-time.
If the OF is set, an error is returned (-EINVAL) instead of the date-time.
The OF bit is cleared each time the date is set.
Signed-off-by: Mylène Josserand <mylene.josserand@free-electrons.com>
---
drivers/rtc/rtc-m41t80.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 660a734..64d66a9 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -56,6 +56,7 @@
#define M41T80_ALMON_AFE BIT(7) /* AFE: AF Enable Bit */
#define M41T80_ALMON_SQWE BIT(6) /* SQWE: SQW Enable Bit */
#define M41T80_ALHOUR_HT BIT(6) /* HT: Halt Update Bit */
+#define M41T80_FLAGS_OF BIT(2) /* OF: Oscillator Failure Bit */
#define M41T80_FLAGS_AF BIT(6) /* AF: Alarm Flag Bit */
#define M41T80_FLAGS_BATT_LOW BIT(4) /* BL: Battery Low Bit */
#define M41T80_WATCHDOG_RB2 BIT(7) /* RB: Watchdog resolution */
@@ -130,7 +131,16 @@ static int m41t80_get_datetime(struct i2c_client *client,
struct rtc_time *tm)
{
unsigned char buf[8];
- int err;
+ int err, flags;
+
+ flags = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+ if (flags < 0)
+ return flags;
+
+ if (flags & M41T80_FLAGS_OF) {
+ dev_err(&client->dev, "Oscillator failure, data is invalid.\n");
+ return -EINVAL;
+ }
err = i2c_smbus_read_i2c_block_data(client, M41T80_REG_SSEC,
sizeof(buf), buf);
@@ -155,7 +165,7 @@ static int m41t80_get_datetime(struct i2c_client *client,
static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
unsigned char buf[8];
- int err;
+ int err, flags;
if (tm->tm_year < 100 || tm->tm_year > 199)
return -EINVAL;
@@ -176,6 +186,17 @@ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return err;
}
+ /* Clear the OF bit of Flags Register */
+ flags = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+ if (flags < 0)
+ return flags;
+
+ if (i2c_smbus_write_byte_data(client, M41T80_REG_FLAGS,
+ flags & ~M41T80_FLAGS_OF)) {
+ dev_err(&client->dev, "Unable to write flags register\n");
+ return -EIO;
+ }
+
return err;
}
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Mylène Josserand <mylene.josserand@free-electrons.com> |
|---|---|
| Date | 2016-03-29 09:00 +0200 |
| Subject | [PATCH 6/8] rtc: m41t80: add alarm functionality |
| Message-ID | <rhVN8-2iO-27@gated-at.bofh.it> |
| In reply to | #1365913 |
Previous 'commit c3b79770e51a ("Expire alarms after the time is set")'
and 'commit 48e9766726eb ("remove disabled alarm functionality")' removed
the alarm support because the alarm irq was not functional.
Add the alarm IRQ functionality with newer functions than previous
code. Tested with 'rtctest' and the alarm is functional.
Signed-off-by: Mylène Josserand <mylene.josserand@free-electrons.com>
---
drivers/rtc/rtc-m41t80.c | 176 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 163 insertions(+), 13 deletions(-)
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 1575b08..4255449 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -90,6 +90,42 @@ struct m41t80_data {
struct rtc_device *rtc;
};
+static irqreturn_t m41t80_handle_irq(int irq, void *dev_id)
+{
+ struct i2c_client *client = dev_id;
+ struct m41t80_data *m41t80 = i2c_get_clientdata(client);
+ struct mutex *lock = &m41t80->rtc->ops_lock;
+ unsigned long events = 0;
+ int flags, flags_afe;
+
+ mutex_lock(lock);
+
+ flags_afe = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
+ if (flags_afe < 0)
+ return IRQ_NONE;
+
+ flags = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+ if (flags <= 0)
+ return IRQ_NONE;
+
+ if (flags & M41T80_FLAGS_AF) {
+ flags &= ~M41T80_FLAGS_AF;
+ flags_afe &= ~M41T80_ALMON_AFE;
+ events |= RTC_AF;
+ }
+
+ if (events) {
+ rtc_update_irq(m41t80->rtc, 1, events);
+ i2c_smbus_write_byte_data(client, M41T80_REG_FLAGS, flags);
+ i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+ flags_afe);
+ }
+
+ mutex_unlock(lock);
+
+ return IRQ_HANDLED;
+}
+
static int m41t80_get_datetime(struct i2c_client *client,
struct rtc_time *tm)
{
@@ -167,10 +203,109 @@ static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm)
return m41t80_set_datetime(to_i2c_client(dev), tm);
}
-/*
- * XXX - m41t80 alarm functionality is reported broken.
- * until it is fixed, don't register alarm functions.
- */
+static int m41t80_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int flags, retval;
+
+ flags = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
+ if (flags < 0)
+ return flags;
+
+ if (enabled)
+ flags |= M41T80_ALMON_AFE;
+ else
+ flags &= ~M41T80_ALMON_AFE;
+
+ retval = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, flags);
+ if (retval < 0) {
+ dev_info(dev, "Unable to enable alarm IRQ %d\n", retval);
+ return retval;
+ }
+ return 0;
+}
+
+static int m41t80_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ u8 alarmvals[5];
+ int ret, err;
+
+ alarmvals[0] = bin2bcd(alrm->time.tm_mon + 1);
+ alarmvals[1] = bin2bcd(alrm->time.tm_mday);
+ alarmvals[2] = bin2bcd(alrm->time.tm_hour);
+ alarmvals[3] = bin2bcd(alrm->time.tm_min);
+ alarmvals[4] = bin2bcd(alrm->time.tm_sec);
+
+ /* Clear AF and AFE flags */
+ ret = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
+ if (ret < 0)
+ return ret;
+ err = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+ ret & ~(M41T80_ALMON_AFE));
+ if (err < 0) {
+ dev_err(dev, "Unable to clear AFE bit\n");
+ return err;
+ }
+
+ ret = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+ if (ret < 0)
+ return ret;
+
+ err = i2c_smbus_write_byte_data(client, M41T80_REG_FLAGS,
+ ret & ~(M41T80_FLAGS_AF));
+ if (err < 0) {
+ dev_err(dev, "Unable to clear AF bit\n");
+ return err;
+ }
+
+ /* Write the alarm */
+ err = i2c_smbus_write_i2c_block_data(client, M41T80_REG_ALARM_MON,
+ 5, alarmvals);
+ if (err)
+ return err;
+
+ /* Enable the alarm interrupt */
+ if (alrm->enabled) {
+ alarmvals[0] |= M41T80_ALMON_AFE;
+ err = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
+ alarmvals[0]);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int m41t80_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ u8 alarmvals[5];
+ int flags, ret;
+
+ ret = i2c_smbus_read_i2c_block_data(client, M41T80_REG_ALARM_MON,
+ 5, alarmvals);
+ if (ret != 5)
+ return ret < 0 ? ret : -EIO;
+
+ flags = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
+ if (flags < 0)
+ return flags;
+
+ alrm->time.tm_sec = bcd2bin(alarmvals[4] & 0x7f);
+ alrm->time.tm_min = bcd2bin(alarmvals[3] & 0x7f);
+ alrm->time.tm_hour = bcd2bin(alarmvals[2] & 0x3f);
+ alrm->time.tm_wday = -1;
+ alrm->time.tm_mday = bcd2bin(alarmvals[1] & 0x3f);
+ alrm->time.tm_mon = bcd2bin(alarmvals[0] & 0x3f);
+ alrm->time.tm_year = -1;
+
+ alrm->enabled = !!(alarmvals[0] & M41T80_ALMON_AFE);
+ alrm->pending = (flags & M41T80_FLAGS_AF) && alrm->enabled;
+
+ return 0;
+}
+
static struct rtc_class_ops m41t80_rtc_ops = {
.read_time = m41t80_rtc_read_time,
.set_time = m41t80_rtc_set_time,
@@ -591,7 +726,7 @@ static int m41t80_probe(struct i2c_client *client,
int rc = 0;
struct rtc_device *rtc = NULL;
struct rtc_time tm;
- struct m41t80_data *clientdata = NULL;
+ struct m41t80_data *m41t80_data = NULL;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -599,26 +734,41 @@ static int m41t80_probe(struct i2c_client *client,
return -ENODEV;
}
- clientdata = devm_kzalloc(&client->dev, sizeof(*clientdata),
- GFP_KERNEL);
- if (!clientdata)
+ m41t80_data = devm_kzalloc(&client->dev, sizeof(*m41t80_data),
+ GFP_KERNEL);
+ if (!m41t80_data)
return -ENOMEM;
- clientdata->features = id->driver_data;
- i2c_set_clientdata(client, clientdata);
+ m41t80_data->features = id->driver_data;
+ i2c_set_clientdata(client, m41t80_data);
+
+ if (client->irq > 0) {
+ rc = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, m41t80_handle_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "m41t80", client);
+ if (rc) {
+ dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
+ client->irq = 0;
+ } else {
+ m41t80_rtc_ops.read_alarm = m41t80_read_alarm;
+ m41t80_rtc_ops.set_alarm = m41t80_set_alarm;
+ m41t80_rtc_ops.alarm_irq_enable = m41t80_alarm_irq_enable;
+ }
+ }
rtc = devm_rtc_device_register(&client->dev, client->name,
&m41t80_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
- clientdata->rtc = rtc;
+ m41t80_data->rtc = rtc;
/* Make sure HT (Halt Update) bit is cleared */
rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR);
if (rc >= 0 && rc & M41T80_ALHOUR_HT) {
- if (clientdata->features & M41T80_FEATURE_HT) {
+ if (m41t80_data->features & M41T80_FEATURE_HT) {
m41t80_get_datetime(client, &tm);
dev_info(&client->dev, "HT bit was set!\n");
dev_info(&client->dev,
@@ -664,7 +814,7 @@ static int m41t80_probe(struct i2c_client *client,
}
#ifdef CONFIG_RTC_DRV_M41T80_WDT
- if (clientdata->features & M41T80_FEATURE_HT) {
+ if (m41t80_data->features & M41T80_FEATURE_HT) {
save_client = client;
rc = misc_register(&wdt_dev);
if (rc)
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Mylène Josserand <mylene.josserand@free-electrons.com> |
|---|---|
| Date | 2016-03-29 09:00 +0200 |
| Subject | [PATCH 4/8] rtc: m41t80: add the use of 'BIT' macro |
| Message-ID | <rhVN8-2iO-33@gated-at.bofh.it> |
| In reply to | #1365913 |
Replace bit shifts by BIT macro.
Signed-off-by: Mylène Josserand <mylene.josserand@free-electrons.com>
---
drivers/rtc/rtc-m41t80.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 1a76927..f991433 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -52,21 +52,21 @@
#define M41T80_ALARM_REG_SIZE \
(M41T80_REG_ALARM_SEC + 1 - M41T80_REG_ALARM_MON)
-#define M41T80_SEC_ST (1 << 7) /* ST: Stop Bit */
-#define M41T80_ALMON_AFE (1 << 7) /* AFE: AF Enable Bit */
-#define M41T80_ALMON_SQWE (1 << 6) /* SQWE: SQW Enable Bit */
-#define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */
-#define M41T80_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */
-#define M41T80_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */
-#define M41T80_WATCHDOG_RB2 (1 << 7) /* RB: Watchdog resolution */
-#define M41T80_WATCHDOG_RB1 (1 << 1) /* RB: Watchdog resolution */
-#define M41T80_WATCHDOG_RB0 (1 << 0) /* RB: Watchdog resolution */
-
-#define M41T80_FEATURE_HT (1 << 0) /* Halt feature */
-#define M41T80_FEATURE_BL (1 << 1) /* Battery low indicator */
-#define M41T80_FEATURE_SQ (1 << 2) /* Squarewave feature */
-#define M41T80_FEATURE_WD (1 << 3) /* Extra watchdog resolution */
-#define M41T80_FEATURE_SQ_ALT (1 << 4) /* RSx bits are in reg 4 */
+#define M41T80_SEC_ST BIT(7) /* ST: Stop Bit */
+#define M41T80_ALMON_AFE BIT(7) /* AFE: AF Enable Bit */
+#define M41T80_ALMON_SQWE BIT(6) /* SQWE: SQW Enable Bit */
+#define M41T80_ALHOUR_HT BIT(6) /* HT: Halt Update Bit */
+#define M41T80_FLAGS_AF BIT(6) /* AF: Alarm Flag Bit */
+#define M41T80_FLAGS_BATT_LOW BIT(4) /* BL: Battery Low Bit */
+#define M41T80_WATCHDOG_RB2 BIT(7) /* RB: Watchdog resolution */
+#define M41T80_WATCHDOG_RB1 BIT(1) /* RB: Watchdog resolution */
+#define M41T80_WATCHDOG_RB0 BIT(0) /* RB: Watchdog resolution */
+
+#define M41T80_FEATURE_HT BIT(0) /* Halt feature */
+#define M41T80_FEATURE_BL BIT(1) /* Battery low indicator */
+#define M41T80_FEATURE_SQ BIT(2) /* Squarewave feature */
+#define M41T80_FEATURE_WD BIT(3) /* Extra watchdog resolution */
+#define M41T80_FEATURE_SQ_ALT BIT(4) /* RSx bits are in reg 4 */
static DEFINE_MUTEX(m41t80_rtc_mutex);
static const struct i2c_device_id m41t80_id[] = {
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Mylène Josserand <mylene.josserand@free-electrons.com> |
|---|---|
| Date | 2016-03-29 09:00 +0200 |
| Subject | [PATCH 2/8] rtc: m41t80: remove proc macro |
| Message-ID | <rhVN8-2iO-31@gated-at.bofh.it> |
| In reply to | #1365913 |
Remove the CONFIG_RTC_INTF_PROC and CONFIG_RTC_INTF_PROC_MODULE macro
which is not necessary anymore.
Signed-off-by: Mylène Josserand <mylene.josserand@free-electrons.com>
---
drivers/rtc/rtc-m41t80.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 2721789..cc8b93d 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -192,7 +192,6 @@ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return 0;
}
-#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -206,9 +205,6 @@ static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
}
return 0;
}
-#else
-#define m41t80_rtc_proc NULL
-#endif
static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
--
2.8.0.rc3
[toc] | [prev] | [next] | [standalone]
| From | Mylène Josserand <mylene.josserand@free-electrons.com> |
|---|---|
| Date | 2016-03-29 09:00 +0200 |
| Subject | [PATCH 3/8] rtc: m41t80: replace i2c functions to smbus ones |
| Message-ID | <rhVN9-2iO-35@gated-at.bofh.it> |
| In reply to | #1365913 |
The driver used i2c_transfer methods to read and set date/time.
The smbus methods should be used.
This commit replaces i2c_transfer functions by i2c_smbus_XX_i2c_block_data
for reading and setting the datetime.
Signed-off-by: Mylène Josserand <mylene.josserand@free-electrons.com>
---
drivers/rtc/rtc-m41t80.c | 134 ++++++++++++++++-------------------------------
1 file changed, 44 insertions(+), 90 deletions(-)
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index cc8b93d..1a76927 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -32,21 +32,21 @@
#include <linux/watchdog.h>
#endif
-#define M41T80_REG_SSEC 0
-#define M41T80_REG_SEC 1
-#define M41T80_REG_MIN 2
-#define M41T80_REG_HOUR 3
-#define M41T80_REG_WDAY 4
-#define M41T80_REG_DAY 5
-#define M41T80_REG_MON 6
-#define M41T80_REG_YEAR 7
-#define M41T80_REG_ALARM_MON 0xa
-#define M41T80_REG_ALARM_DAY 0xb
-#define M41T80_REG_ALARM_HOUR 0xc
-#define M41T80_REG_ALARM_MIN 0xd
-#define M41T80_REG_ALARM_SEC 0xe
-#define M41T80_REG_FLAGS 0xf
-#define M41T80_REG_SQW 0x13
+#define M41T80_REG_SSEC 0x00
+#define M41T80_REG_SEC 0x01
+#define M41T80_REG_MIN 0x02
+#define M41T80_REG_HOUR 0x03
+#define M41T80_REG_WDAY 0x04
+#define M41T80_REG_DAY 0x05
+#define M41T80_REG_MON 0x06
+#define M41T80_REG_YEAR 0x07
+#define M41T80_REG_ALARM_MON 0x0a
+#define M41T80_REG_ALARM_DAY 0x0b
+#define M41T80_REG_ALARM_HOUR 0x0c
+#define M41T80_REG_ALARM_MIN 0x0d
+#define M41T80_REG_ALARM_SEC 0x0e
+#define M41T80_REG_FLAGS 0x0f
+#define M41T80_REG_SQW 0x13
#define M41T80_DATETIME_REG_SIZE (M41T80_REG_YEAR + 1)
#define M41T80_ALARM_REG_SIZE \
@@ -93,24 +93,13 @@ struct m41t80_data {
static int m41t80_get_datetime(struct i2c_client *client,
struct rtc_time *tm)
{
- u8 buf[M41T80_DATETIME_REG_SIZE], dt_addr[1] = { M41T80_REG_SEC };
- struct i2c_msg msgs[] = {
- {
- .addr = client->addr,
- .flags = 0,
- .len = 1,
- .buf = dt_addr,
- },
- {
- .addr = client->addr,
- .flags = I2C_M_RD,
- .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC,
- .buf = buf + M41T80_REG_SEC,
- },
- };
+ unsigned char buf[8];
+ int err;
- if (i2c_transfer(client->adapter, msgs, 2) < 0) {
- dev_err(&client->dev, "read error\n");
+ err = i2c_smbus_read_i2c_block_data(client, M41T80_REG_SSEC,
+ sizeof(buf), buf);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to read date\n");
return -EIO;
}
@@ -129,67 +118,29 @@ static int m41t80_get_datetime(struct i2c_client *client,
/* Sets the given date and time to the real time clock. */
static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
- u8 wbuf[1 + M41T80_DATETIME_REG_SIZE];
- u8 *buf = &wbuf[1];
- u8 dt_addr[1] = { M41T80_REG_SEC };
- struct i2c_msg msgs_in[] = {
- {
- .addr = client->addr,
- .flags = 0,
- .len = 1,
- .buf = dt_addr,
- },
- {
- .addr = client->addr,
- .flags = I2C_M_RD,
- .len = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC,
- .buf = buf + M41T80_REG_SEC,
- },
- };
- struct i2c_msg msgs[] = {
- {
- .addr = client->addr,
- .flags = 0,
- .len = 1 + M41T80_DATETIME_REG_SIZE,
- .buf = wbuf,
- },
- };
+ unsigned char buf[8];
+ int err;
- /* Read current reg values into buf[1..7] */
- if (i2c_transfer(client->adapter, msgs_in, 2) < 0) {
- dev_err(&client->dev, "read error\n");
- return -EIO;
- }
+ if (tm->tm_year < 100 || tm->tm_year > 199)
+ return -EINVAL;
- wbuf[0] = 0; /* offset into rtc's regs */
- /* Merge time-data and register flags into buf[0..7] */
buf[M41T80_REG_SSEC] = 0;
- buf[M41T80_REG_SEC] =
- bin2bcd(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f);
- buf[M41T80_REG_MIN] =
- bin2bcd(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f);
- buf[M41T80_REG_HOUR] =
- bin2bcd(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f);
- buf[M41T80_REG_WDAY] =
- (tm->tm_wday & 0x07) | (buf[M41T80_REG_WDAY] & ~0x07);
- buf[M41T80_REG_DAY] =
- bin2bcd(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f);
- buf[M41T80_REG_MON] =
- bin2bcd(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f);
-
- /* assume 20YY not 19YY */
- if (tm->tm_year < 100 || tm->tm_year > 199) {
- dev_err(&client->dev, "Year must be between 2000 and 2099. It's %d.\n",
- tm->tm_year + 1900);
- return -EINVAL;
+ buf[M41T80_REG_SEC] = bin2bcd(tm->tm_sec);
+ buf[M41T80_REG_MIN] = bin2bcd(tm->tm_min);
+ buf[M41T80_REG_HOUR] = bin2bcd(tm->tm_hour);
+ buf[M41T80_REG_DAY] = bin2bcd(tm->tm_mday);
+ buf[M41T80_REG_MON] = bin2bcd(tm->tm_mon + 1);
+ buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year - 100);
+ buf[M41T80_REG_WDAY] = tm->tm_wday;
+
+ err = i2c_smbus_write_i2c_block_data(client, M41T80_REG_SSEC,
+ sizeof(buf), buf);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to write to date registers\n");
+ return err;
}
- buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year % 100);
- if (i2c_transfer(client->adapter, msgs, 1) != 1) {
- dev_err(&client->dev, "write error\n");
- return -EIO;
- }
- return 0;
+ return err;
}
static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
@@ -631,14 +582,17 @@ static void m41t80_remove_sysfs_group(void *_dev)
static int m41t80_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
int rc = 0;
struct rtc_device *rtc = NULL;
struct rtc_time tm;
struct m41t80_data *clientdata = NULL;
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
- | I2C_FUNC_SMBUS_BYTE_DATA))
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
+ I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_err(&adapter->dev, "doesn't support I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK\n");
return -ENODEV;
+ }
clientdata = devm_kzalloc(&client->dev, sizeof(*clientdata),
GFP_KERNEL);
--
2.8.0.rc3
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web