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:
committed by
Linus Torvalds
parent
a4b1d50e61
commit
682d73f685
@@ -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.
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user