rtc-ds1307 exports NVRAM

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>
This commit is contained in:
David Brownell
2007-11-14 16:58:32 -08:00
committed by Linus Torvalds
parent a4b1d50e61
commit 682d73f685
2 changed files with 95 additions and 2 deletions

View File

@@ -135,8 +135,8 @@ config RTC_DRV_DS1307
The first seven registers on these chips hold an RTC, and other The first seven registers on these chips hold an RTC, and other
registers may add features such as NVRAM, a trickle charger for registers may add features such as NVRAM, a trickle charger for
the RTC/NVRAM backup power, and alarms. This driver may not the RTC/NVRAM backup power, and alarms. NVRAM is visible in
expose all those available chip features. sysfs, but other chip features may not be available.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-ds1307. will be called rtc-ds1307.

View File

@@ -89,6 +89,7 @@ enum ds_type {
struct ds1307 { struct ds1307 {
u8 reg_addr; u8 reg_addr;
bool has_nvram;
u8 regs[8]; u8 regs[8];
enum ds_type type; enum ds_type type;
struct i2c_msg msg[2]; struct i2c_msg msg[2];
@@ -242,6 +243,87 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
.set_time = ds1307_set_time, .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 struct i2c_driver ds1307_driver;
static int __devinit ds1307_probe(struct i2c_client *client) static int __devinit ds1307_probe(struct i2c_client *client)
@@ -413,6 +495,14 @@ read_rtc:
goto exit_free; 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; return 0;
exit_bad: exit_bad:
@@ -432,6 +522,9 @@ static int __devexit ds1307_remove(struct i2c_client *client)
{ {
struct ds1307 *ds1307 = i2c_get_clientdata(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); rtc_device_unregister(ds1307->rtc);
kfree(ds1307); kfree(ds1307);
return 0; return 0;