Skip to content

Commit

Permalink
rtc-ds1307 exports NVRAM
Browse files Browse the repository at this point in the history
Export the NVRAM on DS1307 and DS1338 chips, like several of the
other drivers do for such combination RTC-and-NVRAM chips.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Acked-by: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
David Brownell authored and Linus Torvalds committed Nov 15, 2007
1 parent a4b1d50 commit 682d73f
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 2 deletions.
4 changes: 2 additions & 2 deletions drivers/rtc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ config RTC_DRV_DS1307

The first seven registers on these chips hold an RTC, and other
registers may add features such as NVRAM, a trickle charger for
the RTC/NVRAM backup power, and alarms. This driver may not
expose all those available chip features.
the RTC/NVRAM backup power, and alarms. NVRAM is visible in
sysfs, but other chip features may not be available.

This driver can also be built as a module. If so, the module
will be called rtc-ds1307.
Expand Down
93 changes: 93 additions & 0 deletions drivers/rtc/rtc-ds1307.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ enum ds_type {

struct ds1307 {
u8 reg_addr;
bool has_nvram;
u8 regs[8];
enum ds_type type;
struct i2c_msg msg[2];
Expand Down Expand Up @@ -242,6 +243,87 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
.set_time = ds1307_set_time,
};

/*----------------------------------------------------------------------*/

#define NVRAM_SIZE 56

static ssize_t
ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
struct i2c_client *client;
struct ds1307 *ds1307;
struct i2c_msg msg[2];
int result;

client = to_i2c_client(container_of(kobj, struct device, kobj));
ds1307 = i2c_get_clientdata(client);

if (unlikely(off >= NVRAM_SIZE))
return 0;
if ((off + count) > NVRAM_SIZE)
count = NVRAM_SIZE - off;
if (unlikely(!count))
return count;

msg[0].addr = client->addr;
msg[0].flags = 0;
msg[0].len = 1;
msg[0].buf = buf;

buf[0] = 8 + off;

msg[1].addr = client->addr;
msg[1].flags = I2C_M_RD;
msg[1].len = count;
msg[1].buf = buf;

result = i2c_transfer(to_i2c_adapter(client->dev.parent), msg, 2);
if (result != 2) {
dev_err(&client->dev, "%s error %d\n", "nvram read", result);
return -EIO;
}
return count;
}

static ssize_t
ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
struct i2c_client *client;
u8 buffer[NVRAM_SIZE + 1];
int ret;

client = to_i2c_client(container_of(kobj, struct device, kobj));

if (unlikely(off >= NVRAM_SIZE))
return -EFBIG;
if ((off + count) > NVRAM_SIZE)
count = NVRAM_SIZE - off;
if (unlikely(!count))
return count;

buffer[0] = 8 + off;
memcpy(buffer + 1, buf, count);

ret = i2c_master_send(client, buffer, count + 1);
return (ret < 0) ? ret : (ret - 1);
}

static struct bin_attribute nvram = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUSR,
.owner = THIS_MODULE,
},

.read = ds1307_nvram_read,
.write = ds1307_nvram_write,
.size = NVRAM_SIZE,
};

/*----------------------------------------------------------------------*/

static struct i2c_driver ds1307_driver;

static int __devinit ds1307_probe(struct i2c_client *client)
Expand Down Expand Up @@ -413,6 +495,14 @@ static int __devinit ds1307_probe(struct i2c_client *client)
goto exit_free;
}

if (chip->nvram56) {
err = sysfs_create_bin_file(&client->dev.kobj, &nvram);
if (err == 0) {
ds1307->has_nvram = true;
dev_info(&client->dev, "56 bytes nvram\n");
}
}

return 0;

exit_bad:
Expand All @@ -432,6 +522,9 @@ static int __devexit ds1307_remove(struct i2c_client *client)
{
struct ds1307 *ds1307 = i2c_get_clientdata(client);

if (ds1307->has_nvram)
sysfs_remove_bin_file(&client->dev.kobj, &nvram);

rtc_device_unregister(ds1307->rtc);
kfree(ds1307);
return 0;
Expand Down

0 comments on commit 682d73f

Please sign in to comment.