Patchwork Re: rtc driver for ds1307 chip like devices

login
register
mail settings
Submitter Thomas Nemeth
Date Aug. 13, 2011, 12:30 p.m.
Message ID <CANyLDZ2UJ98HURb2rMXhdQfsjWaGK0wJC4+FG=1QRyiBy=pNJA@mail.gmail.com>
Download mbox | patch
Permalink /patch/109931/
State New
Headers show

Comments

Thomas Nemeth - Aug. 13, 2011, 12:30 p.m.
2011/8/13 Alessandro Zummo <a.zummo@towertech.it>:
> Sure! Please send it to me and Cc the etc mailing list. Ty.
>
> --
>  Best regards,
>  Alessandro Zummo
>     Tower Technologies
>
> Sent from my iPhone, please excuse my brevity.

    No problem :)
    Here it is, in attachment. Please note that this is a work in
progress as I plan to add
    another chip (ds32c35). I also found out that some other chips
which have standalone
    drivers could have their support integrated.

    Of course, every comment is welcome.


> On 13/ago/2011, at 11:54, Thomas Nemeth <nemeth.thomas@gmail.com> wrote:
>
>>
>>    Hi Alessandro.
>>
>>    You're listed as the still active maintainer of the RTC subsystem,
>>    that's why I'm emailing you. I have made a little modification to
>>    the ds1307 driver so that it can support devices that have also a
>>    temperature sensor included. That seems to be more and more common
>>    since it can be used by the device itself to correct the internal
>>    crystal frequency.
>>
>>    Is it worth sending this to you for review in order to have it
>>    included in the official kernel ?
Alessandro Zummo - Aug. 13, 2011, 1:11 p.m.
On Sat, 13 Aug 2011 14:30:54 +0200
Thomas Nemeth <nemeth.thomas@gmail.com> wrote:

>     No problem :)
>     Here it is, in attachment. Please note that this is a work in
> progress as I plan to add
>     another chip (ds32c35). I also found out that some other chips
> which have standalone
>     drivers could have their support integrated.
> 
>     Of course, every comment is welcome.

 what happens if I have two ds1307 compatible devices on the bus,
 each one with a different ram size?
Thomas Nemeth - Aug. 13, 2011, 1:23 p.m.
2011/8/13 Alessandro Zummo <a.zummo@towertech.it>:
>
>  what happens if I have two ds1307 compatible devices on the bus,
>  each one with a different ram size?

     Argl.

     I should have followed my first idea. I wanted to have the nvram56
     (renamed nvram) field of the chip_desc structure be used as a
     configuration size copied in a field of the ds1307 structure. However
     I'm not familiar with sysfs files and the presence of the .size field
     in static struct bin_attribute nvram puzzles me.

     I could not find a what-to-(not)-do document about such sysfs
     structures.

     Do you have a pointer where I could get more information ? It would
     also help me fix a misbehavior when reading the temperature : I get
     it twice when I cat the temperature file.

Thomas.
AustinMarton - Aug. 14, 2011, 11:21 p.m.
Hi Thomas,

Did you take a look at the patch I recently submitted to make the
NVRAM size part of the ds1307 structure that is set on a per chip
basis?
https://groups.google.com/d/topic/rtc-linux/aiEG7ju0icA/discussion

Would that work for you?

Cheers,
Austin.

On Aug 14, 1:23 am, Thomas Nemeth <nemeth.tho...@gmail.com> wrote:
> 2011/8/13 Alessandro Zummo <a.zu...@towertech.it>:
>
>
>
> >  what happens if I have two ds1307 compatible devices on the bus,
> >  each one with a different ram size?
>
>      Argl.
>
>      I should have followed my first idea. I wanted to have the nvram56
>      (renamed nvram) field of the chip_desc structure be used as a
>      configuration size copied in a field of the ds1307 structure. However
>      I'm not familiar with sysfs files and the presence of the .size field
>      in static struct bin_attribute nvram puzzles me.
>
>      I could not find a what-to-(not)-do document about such sysfs
>      structures.
>
>      Do you have a pointer where I could get more information ? It would
>      also help me fix a misbehavior when reading the temperature : I get
>      it twice when I cat the temperature file.
>
> Thomas.

Patch

diff -Naurp a/Kconfig b/Kconfig
--- a/Kconfig	2011-08-13 12:21:54.266820478 +0200
+++ b/Kconfig	2011-08-13 13:58:54.655682228 +0200
@@ -146,6 +146,14 @@  config RTC_DRV_DS1307
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-ds1307.
 
+config RTC_NVRAM_SIZE
+	int "Size of embedded NVRAM in DS1307 compatible chips"
+	depends on RTC_DRV_DS1307
+	default 56
+	help
+	  Size of the embedded NVRAM in DS1307 compatible chips. Defaults
+	  to 56 bytes.
+
 config RTC_DRV_DS1374
 	tristate "Dallas/Maxim DS1374"
 	depends on RTC_CLASS && I2C
diff -Naurp a/rtc-ds1307.c b/rtc-ds1307.c
--- a/rtc-ds1307.c	2011-08-13 11:56:48.499353786 +0200
+++ b/rtc-ds1307.c	2011-08-13 14:25:50.731695914 +0200
@@ -33,6 +33,7 @@  enum ds_type {
 	ds_1340,
 	ds_1388,
 	ds_3231,
+	ds_32b35,
 	m41t00,
 	rx_8025,
 	// rs5c372 too?  different address...
@@ -69,6 +70,7 @@  enum ds_type {
 #	define DS1337_BIT_nEOSC		0x80
 #	define DS1339_BIT_BBSQI		0x20
 #	define DS3231_BIT_BBSQW		0x40 /* same as BBSQI */
+#	define DS3235_BIT_CONV		0x20
 #	define DS1337_BIT_RS2		0x10
 #	define DS1337_BIT_RS1		0x08
 #	define DS1337_BIT_INTCN		0x04
@@ -83,6 +85,7 @@  enum ds_type {
 #	define DS1340_BIT_OSF		0x80
 #define DS1337_REG_STATUS	0x0f
 #	define DS1337_BIT_OSF		0x80
+#	define DS3235_BIT_BSY		0x04
 #	define DS1337_BIT_A2I		0x02
 #	define DS1337_BIT_A1I		0x01
 #define DS1339_REG_ALARM1_SECS	0x07
@@ -95,6 +98,8 @@  enum ds_type {
 #	define RX8025_BIT_VDET		0x40
 #	define RX8025_BIT_XST		0x20
 
+#define DS3235_REG_TEMP_MSB	0x11
+
 
 struct ds1307 {
 	u8			offset; /* register's offset */
@@ -103,6 +108,7 @@  struct ds1307 {
 	unsigned long		flags;
 #define HAS_NVRAM	0		/* bit 0 == sysfs file active */
 #define HAS_ALARM	1		/* bit 1 == irq claimed */
+#define HAS_SENSOR	2		/* bit 2 == sensor sysfs file active */
 	struct i2c_client	*client;
 	struct rtc_device	*rtc;
 	struct work_struct	work;
@@ -113,19 +119,20 @@  struct ds1307 {
 };
 
 struct chip_desc {
-	unsigned		nvram56:1;
+	unsigned		nvram:1;
 	unsigned		alarm:1;
+	unsigned		temp_sensor:1;
 };
 
 static const struct chip_desc chips[] = {
 [ds_1307] = {
-	.nvram56	= 1,
+	.nvram	= 1,
 },
 [ds_1337] = {
 	.alarm		= 1,
 },
 [ds_1338] = {
-	.nvram56	= 1,
+	.nvram	= 1,
 },
 [ds_1339] = {
 	.alarm		= 1,
@@ -135,6 +142,11 @@  static const struct chip_desc chips[] =
 [ds_3231] = {
 	.alarm		= 1,
 },
+[ds_32b35] = {
+	.nvram	= 1,
+	.alarm		= 1,
+	.temp_sensor	= 1,
+},
 [m41t00] = {
 },
 [rx_8025] = {
@@ -148,6 +160,7 @@  static const struct i2c_device_id ds1307
 	{ "ds1388", ds_1388 },
 	{ "ds1340", ds_1340 },
 	{ "ds3231", ds_3231 },
+	{ "ds32b35", ds_32b35 },
 	{ "m41t00", m41t00 },
 	{ "rx8025", rx_8025 },
 	{ }
@@ -358,6 +371,7 @@  static int ds1307_set_time(struct device
 	case ds_1337:
 	case ds_1339:
 	case ds_3231:
+	case ds_32b35:
 		buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
 		break;
 	case ds_1340:
@@ -553,7 +567,11 @@  static const struct rtc_class_ops ds13xx
 
 /*----------------------------------------------------------------------*/
 
-#define NVRAM_SIZE	56
+#ifdef CONFIG_RTC_NVRAM_SIZE
+#  define NVRAM_SIZE	CONFIG_RTC_NVRAM_SIZE
+#else
+#  define NVRAM_SIZE	56
+#endif
 
 static ssize_t
 ds1307_nvram_read(struct file *filp, struct kobject *kobj,
@@ -620,6 +638,58 @@  static struct bin_attribute nvram = {
 
 /*----------------------------------------------------------------------*/
 
+#define check_read_block(r, s)						\
+	result = ds1307->read_block_data(client, r, s, temp);		\
+	if (result < 0)							\
+		goto err
+
+static ssize_t
+ds1307_temp_read(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *attr,
+		char *buf, loff_t off, size_t count)
+{
+	struct i2c_client	*client;
+	struct ds1307		*ds1307;
+	int			result;
+	u8			temp[2];
+	int			value = 0;
+
+	client = kobj_to_i2c_client(kobj);
+	ds1307 = i2c_get_clientdata(client);
+
+	/* start new conversion if possible. */
+	check_read_block(DS1337_REG_STATUS, 1);
+	if (!(temp[0] & DS3235_BIT_BSY)) {
+		check_read_block(DS1337_REG_CONTROL, 1);
+		temp[0] |= DS3235_BIT_CONV;
+		result = ds1307->write_block_data(client, DS1337_REG_CONTROL, 1, temp);
+		if (result < 0)
+			goto err;
+	}
+
+	check_read_block(DS3235_REG_TEMP_MSB, 2);
+	value = (temp[1] >> 6) | (temp[0] & 0x7F) << 2;
+	if (temp[0] & 0x80)
+		value -= 512;
+
+err:
+	if (result < 0)
+		dev_err(&client->dev, "%s error %d\n", "temp read", result);
+
+	return sprintf(buf, "% 2d.%02ld\n", value / 4, abs((value % 4) * 25));
+}
+
+static struct bin_attribute ds1307_sensor = {
+	.attr = {
+		.name	= "temperature",
+		.mode	= S_IRUGO,
+	},
+	.read	= ds1307_temp_read,
+	.size	= 8,
+};
+
+/*----------------------------------------------------------------------*/
+
 static struct i2c_driver ds1307_driver;
 
 static int __devinit ds1307_probe(struct i2c_client *client,
@@ -636,6 +706,7 @@  static int __devinit ds1307_probe(struct
 		[ds_1337] = 0,
 		[ds_1339] = DS1339_BIT_BBSQI,
 		[ds_3231] = DS3231_BIT_BBSQW,
+		[ds_32b35] = DS3231_BIT_BBSQW,
 	};
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)
@@ -664,6 +735,7 @@  static int __devinit ds1307_probe(struct
 	case ds_1337:
 	case ds_1339:
 	case ds_3231:
+	case ds_32b35:
 		/* has IRQ? */
 		if (ds1307->client->irq > 0 && chip->alarm) {
 			INIT_WORK(&ds1307->work, ds1307_work);
@@ -836,6 +908,7 @@  read_rtc:
 	case ds_1339:
 	case ds_1388:
 	case ds_3231:
+	case ds_32b35:
 		break;
 	}
 
@@ -889,11 +962,18 @@  read_rtc:
 		dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
 	}
 
-	if (chip->nvram56) {
+	if (chip->nvram) {
 		err = sysfs_create_bin_file(&client->dev.kobj, &nvram);
 		if (err == 0) {
 			set_bit(HAS_NVRAM, &ds1307->flags);
-			dev_info(&client->dev, "56 bytes nvram\n");
+			dev_info(&client->dev, "%d bytes nvram\n", NVRAM_SIZE);
+		}
+	}
+	if (chip->temp_sensor) {
+		err = sysfs_create_bin_file(&client->dev.kobj, &ds1307_sensor);
+		if (err == 0) {
+			set_bit(HAS_SENSOR, &ds1307->flags);
+			dev_info(&client->dev, "temperature sensor\n");
 		}
 	}
 
@@ -915,6 +995,9 @@  static int __devexit ds1307_remove(struc
 		cancel_work_sync(&ds1307->work);
 	}
 
+	if (test_and_clear_bit(HAS_SENSOR, &ds1307->flags))
+		sysfs_remove_bin_file(&client->dev.kobj, &ds1307_sensor);
+
 	if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags))
 		sysfs_remove_bin_file(&client->dev.kobj, &nvram);