Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1365913 > unrolled thread

[PATCH 0/8] rtc: m41t80: update and add functionalities

Started byMylène Josserand <mylene.josserand@free-electrons.com>
First post2016-03-29 09:00 +0200
Last post2016-03-29 09:00 +0200
Articles 7 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [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

#1365913 — [PATCH 0/8] rtc: m41t80: update and add functionalities

FromMylène Josserand <mylene.josserand@free-electrons.com>
Date2016-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]


#1365916 — [PATCH 1/8] rtc: m41t80: update sysfs entries export

FromMylène Josserand <mylene.josserand@free-electrons.com>
Date2016-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]


#1365917 — [PATCH 8/8] rtc: m41t80: handle oscillator failure bit

FromMylène Josserand <mylene.josserand@free-electrons.com>
Date2016-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]


#1365919 — [PATCH 6/8] rtc: m41t80: add alarm functionality

FromMylène Josserand <mylene.josserand@free-electrons.com>
Date2016-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]


#1365920 — [PATCH 4/8] rtc: m41t80: add the use of 'BIT' macro

FromMylène Josserand <mylene.josserand@free-electrons.com>
Date2016-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]


#1365921 — [PATCH 2/8] rtc: m41t80: remove proc macro

FromMylène Josserand <mylene.josserand@free-electrons.com>
Date2016-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]


#1365922 — [PATCH 3/8] rtc: m41t80: replace i2c functions to smbus ones

FromMylène Josserand <mylene.josserand@free-electrons.com>
Date2016-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