summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2018-05-20 09:37:23 -0400
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2018-07-11 14:41:22 -0400
commitd6c3029f32f72db7ba7b4183b0423cce2267ca3d (patch)
treef5d0bea6e73a4a4de1a4292a3c1f07806489f711
parentcd7f3a249dbed2858e6c2f30e5be7f1f7a709ee2 (diff)
rtc: pcf2127: add support for accessing internal static RAM
The PCF2127 has 512 bytes of internal static RAM and this patch expands the driver to access this memory. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
-rw-r--r--drivers/rtc/rtc-pcf2127.c68
1 files changed, 62 insertions, 6 deletions
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index e83be1852c2f..9f99a0966550 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -36,6 +36,11 @@
36#define PCF2127_REG_MO (0x08) 36#define PCF2127_REG_MO (0x08)
37#define PCF2127_REG_YR (0x09) 37#define PCF2127_REG_YR (0x09)
38 38
39/* the pcf2127 has 512 bytes nvmem, pcf2129 doesn't */
40#define PCF2127_REG_RAM_addr_MSB 0x1a
41#define PCF2127_REG_RAM_wrt_cmd 0x1c
42#define PCF2127_REG_RAM_rd_cmd 0x1d
43
39#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */ 44#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */
40 45
41struct pcf2127 { 46struct pcf2127 {
@@ -183,10 +188,47 @@ static const struct rtc_class_ops pcf2127_rtc_ops = {
183 .set_time = pcf2127_rtc_set_time, 188 .set_time = pcf2127_rtc_set_time,
184}; 189};
185 190
191static int pcf2127_nvmem_read(void *priv, unsigned int offset,
192 void *val, size_t bytes)
193{
194 struct pcf2127 *pcf2127 = priv;
195 int ret;
196 unsigned char offsetbuf[] = { offset >> 8, offset };
197
198 ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
199 offsetbuf, 2);
200 if (ret)
201 return ret;
202
203 ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_rd_cmd,
204 val, bytes);
205
206 return ret ?: bytes;
207}
208
209static int pcf2127_nvmem_write(void *priv, unsigned int offset,
210 void *val, size_t bytes)
211{
212 struct pcf2127 *pcf2127 = priv;
213 int ret;
214 unsigned char offsetbuf[] = { offset >> 8, offset };
215
216 ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
217 offsetbuf, 2);
218 if (ret)
219 return ret;
220
221 ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_wrt_cmd,
222 val, bytes);
223
224 return ret ?: bytes;
225}
226
186static int pcf2127_probe(struct device *dev, struct regmap *regmap, 227static int pcf2127_probe(struct device *dev, struct regmap *regmap,
187 const char *name) 228 const char *name, bool has_nvmem)
188{ 229{
189 struct pcf2127 *pcf2127; 230 struct pcf2127 *pcf2127;
231 int ret = 0;
190 232
191 dev_dbg(dev, "%s\n", __func__); 233 dev_dbg(dev, "%s\n", __func__);
192 234
@@ -200,8 +242,21 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
200 242
201 pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops, 243 pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops,
202 THIS_MODULE); 244 THIS_MODULE);
245 if (IS_ERR(pcf2127->rtc))
246 return PTR_ERR(pcf2127->rtc);
247
248 if (has_nvmem) {
249 struct nvmem_config nvmem_cfg = {
250 .priv = pcf2127,
251 .reg_read = pcf2127_nvmem_read,
252 .reg_write = pcf2127_nvmem_write,
253 .size = 512,
254 };
255
256 ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
257 }
203 258
204 return PTR_ERR_OR_ZERO(pcf2127->rtc); 259 return ret;
205} 260}
206 261
207#ifdef CONFIG_OF 262#ifdef CONFIG_OF
@@ -309,11 +364,11 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
309 } 364 }
310 365
311 return pcf2127_probe(&client->dev, regmap, 366 return pcf2127_probe(&client->dev, regmap,
312 pcf2127_i2c_driver.driver.name); 367 pcf2127_i2c_driver.driver.name, id->driver_data);
313} 368}
314 369
315static const struct i2c_device_id pcf2127_i2c_id[] = { 370static const struct i2c_device_id pcf2127_i2c_id[] = {
316 { "pcf2127", 0 }, 371 { "pcf2127", 1 },
317 { "pcf2129", 0 }, 372 { "pcf2129", 0 },
318 { } 373 { }
319}; 374};
@@ -372,11 +427,12 @@ static int pcf2127_spi_probe(struct spi_device *spi)
372 return PTR_ERR(regmap); 427 return PTR_ERR(regmap);
373 } 428 }
374 429
375 return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name); 430 return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name,
431 spi_get_device_id(spi)->driver_data);
376} 432}
377 433
378static const struct spi_device_id pcf2127_spi_id[] = { 434static const struct spi_device_id pcf2127_spi_id[] = {
379 { "pcf2127", 0 }, 435 { "pcf2127", 1 },
380 { "pcf2129", 0 }, 436 { "pcf2129", 0 },
381 { } 437 { }
382}; 438};