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:
parent
a4b1d50e61
commit
682d73f685
|
@ -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.
|
||||
|
|
|
@ -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];
|
||||
|
@ -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)
|
||||
|
@ -413,6 +495,14 @@ read_rtc:
|
|||
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:
|
||||
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue