DS3232 RTC has 236 bytes of persistent memory. Add RTC SRAM read and write access using the NVMEM Framework. Signed-off-by: Nandor Han <nandor.han@xxxxxxxxxxx> --- Description ----------- Provides DS3232 RTC SRAM access using NVMEM framework. Testing ------- The test was done on a custom board which contains a DS3232 RTC device. Kernel Version: 4.14.60 (Just for clarity, the patch is against master) 1. Verify that SRAM is accessible using NVMEM interface: PASS ` # hexdump /sys/bus/nvmem/devices/ds3232_sram0/nvmem 0000000 0000 0000 0000 0000 0000 0000 0000 0000 * 00000e0 ` 2. Modify the content. ` # echo testing > /sys/bus/nvmem/devices/ds3232_sram0/nvmem # ` 3. Power cycle the board and verify that contents are preserved: PASS ` # hexdump -n 10 -C /sys/bus/nvmem/devices/ds3232_sram0/nvmem 00000000 74 65 73 74 69 6e 67 0a 00 00 |testing...| 0000000a ` Testing on Kernel v5.1.0-rc3 1. Update `arch/arm/configs/imx_v6_v7_defconfig` to contain `CONFIG_RTC_DRV_DS3232=y` 2. Verify that building the kernel is successful: PASS ` make ARCH=arm CROSS_COMPILE=arm-linux-gnu- imx_v6_v7_defconfig zImage ... CC drivers/rtc/rtc-ds3232.o ... Kernel: arch/arm/boot/zImage is ready ` Changes since v1 ---------------- - remove the unnecessary header "rtc-core.h" - use nvmem_config from the stack - configure the nvmem type - remove the `of_node` configuration Changes since v2 ---------------- - init unused struct nvmem_cfg members to 0 - use regmap as private data to nvmem struct drivers/rtc/rtc-ds3232.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 7184e5145f12..1e9312f96021 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -48,6 +48,10 @@ # define DS3232_REG_SR_A1F 0x01 #define DS3232_REG_TEMPERATURE 0x11 +#define DS3232_REG_SRAM_START 0x14 +#define DS3232_REG_SRAM_END 0xFF + +#define DS3232_REG_SRAM_SIZE 236 struct ds3232 { struct device *dev; @@ -461,11 +465,39 @@ static const struct rtc_class_ops ds3232_rtc_ops = { .alarm_irq_enable = ds3232_alarm_irq_enable, }; +static int ds3232_nvmem_read(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct regmap *ds3232_regmap = (struct regmap *)priv; + + return regmap_bulk_read(ds3232_regmap, DS3232_REG_SRAM_START + offset, + val, bytes); +} + +static int ds3232_nvmem_write(void *priv, unsigned int offset, void *val, + size_t bytes) +{ + struct regmap *ds3232_regmap = (struct regmap *)priv; + + return regmap_bulk_write(ds3232_regmap, DS3232_REG_SRAM_START + offset, + val, bytes); +} + static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, const char *name) { struct ds3232 *ds3232; int ret; + struct nvmem_config nvmem_cfg = { + .name = "ds3232_sram", + .stride = 1, + .size = DS3232_REG_SRAM_SIZE, + .word_size = 1, + .reg_read = ds3232_nvmem_read, + .reg_write = ds3232_nvmem_write, + .priv = regmap, + .type = NVMEM_TYPE_BATTERY_BACKED + }; ds3232 = devm_kzalloc(dev, sizeof(*ds3232), GFP_KERNEL); if (!ds3232) @@ -490,6 +522,10 @@ static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq, if (IS_ERR(ds3232->rtc)) return PTR_ERR(ds3232->rtc); + ret = rtc_nvmem_register(ds3232->rtc, &nvmem_cfg); + if(ret) + return ret; + if (ds3232->irq > 0) { ret = devm_request_threaded_irq(dev, ds3232->irq, NULL, ds3232_irq, @@ -542,7 +578,7 @@ static int ds3232_i2c_probe(struct i2c_client *client, static const struct regmap_config config = { .reg_bits = 8, .val_bits = 8, - .max_register = 0x13, + .max_register = DS3232_REG_SRAM_END, }; regmap = devm_regmap_init_i2c(client, &config); @@ -609,7 +645,7 @@ static int ds3234_probe(struct spi_device *spi) static const struct regmap_config config = { .reg_bits = 8, .val_bits = 8, - .max_register = 0x13, + .max_register = DS3232_REG_SRAM_END, .write_flag_mask = 0x80, }; struct regmap *regmap; -- 2.17.2