[PATCH] rtc-ds1307 : add sysfs support for trickle charger

From: frederic RODO
Date: Wed Jan 16 2008 - 11:28:07 EST


this patch add two callbacks (show and store) to support the trickle charger for ds_1339 and ds_1340 (it can also be used for the ds1388).

I'm not sure if it'is the right way for adding this support. Can someone explain me a better way?

It was test on a custom board with a ds_1340. The ds_1339 support was not tested.

If you have any comments, please CC me


log from test

Linux version 2.6.24-rc7 (fredo@srv-devhard) (gcc version 3.4.6) #14 Wed Jan 16 15:40:55 CET 2008
..........
i2c /dev entries driver
rtc-ds1307 0-0068: rtc core: registered ds1340 as rtc0
rtc-ds1307 0-0068: trickle charger
i2c-gpio i2c-gpio: using pins 55 (SDA) and 56 (SCL)
....
# cd /sys/class/rtc/rtc0/device/
# cat trickle
0xaa (trickle charger enabled)
# echo 0 > trickle
# cat trickle
0x00 (trickle charger disabled)


Signed-off-by: Frederic RODO <f.rodo@xxxxxxxxxxxxxxxxxxx>

diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 3a86898..4564238 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -77,6 +77,7 @@ enum ds_type {
# define DS1340_BIT_FT 0x40
# define DS1340_BIT_CALIB_SIGN 0x20
# define DS1340_M_CALIBRATION 0x1f
+#define DS1340_REG_TRICKLE 0x08
#define DS1340_REG_FLAG 0x09
# define DS1340_BIT_OSF 0x80
#define DS1337_REG_STATUS 0x0f
@@ -90,6 +91,7 @@ enum ds_type {
struct ds1307 {
u8 reg_addr;
bool has_nvram;
+ bool has_trickle;
u8 regs[8];
enum ds_type type;
struct i2c_msg msg[2];
@@ -102,6 +104,7 @@ struct chip_desc {
char name[9];
unsigned nvram56:1;
unsigned alarm:1;
+ unsigned trickle:1;
enum ds_type type;
};

@@ -121,9 +124,11 @@ static const struct chip_desc chips[] = { {
.name = "ds1339",
.type = ds_1339,
.alarm = 1,
+ .trickle = 1,
}, {
.name = "ds1340",
.type = ds_1340,
+ .trickle = 1,
}, {
.name = "m41t00",
.type = m41t00,
@@ -322,6 +327,72 @@ static struct bin_attribute nvram = {
.size = NVRAM_SIZE,
};

+static ssize_t ds1307_sysfs_show_trickle(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ struct i2c_client *client = to_i2c_client(dev);
+ int trickle;
+
+ switch (ds1307->type) {
+ case ds_1339:
+ trickle = i2c_smbus_read_byte_data(client, DS1339_REG_TRICKLE);
+ break;
+ case ds_1340:
+ trickle = i2c_smbus_read_byte_data(client, DS1340_REG_TRICKLE);
+ break;
+ default: return -EIO;
+ }
+
+ if (trickle < 0)
+ return trickle;
+
+ return sprintf(buf, "0x%02x (trickle charger %s)\n", (u8) trickle,
+ (((trickle & 0xf0) != 0xa0) ||
+ ((trickle & 0x0c) == 0x0c) ||
+ ((trickle & 0x0c) == 0) ||
+ ((trickle & 0x03) == 0))
+ ? "disabled" : "enabled");
+}
+
+static ssize_t ds1307_sysfs_store_trickle(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ struct i2c_client *client = to_i2c_client(dev);
+ int err;
+ int trickle = -1;
+
+ if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) {
+ if (sscanf(buf, "%x", &trickle) != 1)
+ return -EINVAL;
+ } else {
+ if (sscanf(buf, "%d", &trickle) != 1)
+ return -EINVAL;
+ }
+
+ if (trickle < 0 || trickle > 0xff)
+ return -EINVAL;
+
+ switch (ds1307->type) {
+ case ds_1339:
+ err = i2c_smbus_write_byte_data(client, DS1339_REG_TRICKLE,
+ trickle);
+ break;
+ case ds_1340:
+ err = i2c_smbus_write_byte_data(client, DS1340_REG_TRICKLE,
+ trickle);
+ break;
+ default: return -EIO;
+ }
+
+ return (err < 0) ? -EIO : 1;
+}
+static DEVICE_ATTR(trickle, S_IRUGO | S_IWUSR, ds1307_sysfs_show_trickle,
+ ds1307_sysfs_store_trickle);
+
/*----------------------------------------------------------------------*/

static struct i2c_driver ds1307_driver;
@@ -526,6 +597,14 @@ read_rtc:
}
}

+ if (chip->trickle) {
+ err = device_create_file(&client->dev, &dev_attr_trickle);
+ if (err == 0) {
+ ds1307->has_trickle = true;
+ dev_info(&client->dev, "trickle charger\n");
+ }
+ }
+
return 0;

exit_bad:
@@ -548,6 +627,9 @@ static int __devexit ds1307_remove(struct i2c_client *client)
if (ds1307->has_nvram)
sysfs_remove_bin_file(&client->dev.kobj, &nvram);

+ if (ds1307->has_trickle)
+ device_remove_file(&client->dev, &dev_attr_trickle);
+
rtc_device_unregister(ds1307->rtc);
kfree(ds1307);
return 0;


-------------------------------------------------------------------------
Les informations précédentes peuvent être confidentielles ou privilégiées.
Si vous n'êtes pas le destinataire prévu de ce mail, veuillez en notifier l'expéditeur en répondant à ce message puis supprimez-en toute trace de vos systèmes.

TIL Technologies
Parc du Golf, Bat 43
350 rue J.R Guilibert Gautier de la Lauzière 13856 AIX EN PROVENCE
Tel. : +33 4 42 37 11 77
-------------------------------------------------------------------------


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/