diff options
author | Akinobu Mita <akinobu.mita@gmail.com> | 2016-03-14 10:45:00 -0400 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2016-03-14 12:08:41 -0400 |
commit | 9408ec1af875a83ad75f3dac1aa18d2337a809fe (patch) | |
tree | 42fae0b42985bf19de9921915984f5a7e873789e /drivers/rtc | |
parent | 907b3262583c700ef48f6a45b2b48878b524b2ef (diff) |
rtc: pcf2127: add support for spi interface
pcf2127 has selectable I2C-bus and SPI-bus interface support.
This adds support for SPI interface.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 19 | ||||
-rw-r--r-- | drivers/rtc/rtc-pcf2127.c | 118 |
2 files changed, 126 insertions, 11 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index d2cd206d2965..544bd3493852 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -379,15 +379,6 @@ config RTC_DRV_X1205 | |||
379 | This driver can also be built as a module. If so, the module | 379 | This driver can also be built as a module. If so, the module |
380 | will be called rtc-x1205. | 380 | will be called rtc-x1205. |
381 | 381 | ||
382 | config RTC_DRV_PCF2127 | ||
383 | tristate "NXP PCF2127" | ||
384 | help | ||
385 | If you say yes here you get support for the NXP PCF2127/29 RTC | ||
386 | chips. | ||
387 | |||
388 | This driver can also be built as a module. If so, the module | ||
389 | will be called rtc-pcf2127. | ||
390 | |||
391 | config RTC_DRV_PCF8523 | 382 | config RTC_DRV_PCF8523 |
392 | tristate "NXP PCF8523" | 383 | tristate "NXP PCF8523" |
393 | help | 384 | help |
@@ -776,6 +767,16 @@ config RTC_DRV_DS3232 | |||
776 | This driver can also be built as a module. If so, the module | 767 | This driver can also be built as a module. If so, the module |
777 | will be called rtc-ds3232. | 768 | will be called rtc-ds3232. |
778 | 769 | ||
770 | config RTC_DRV_PCF2127 | ||
771 | tristate "NXP PCF2127" | ||
772 | depends on RTC_I2C_AND_SPI | ||
773 | help | ||
774 | If you say yes here you get support for the NXP PCF2127/29 RTC | ||
775 | chips. | ||
776 | |||
777 | This driver can also be built as a module. If so, the module | ||
778 | will be called rtc-pcf2127. | ||
779 | |||
779 | comment "Platform RTC drivers" | 780 | comment "Platform RTC drivers" |
780 | 781 | ||
781 | # this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h> | 782 | # this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h> |
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index fa492cd84e2a..194c440f15d3 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * An I2C driver for the NXP PCF2127 RTC | 2 | * An I2C and SPI driver for the NXP PCF2127 RTC |
3 | * Copyright 2013 Til-Technologies | 3 | * Copyright 2013 Til-Technologies |
4 | * | 4 | * |
5 | * Author: Renaud Cerrato <r.cerrato@til-technologies.fr> | 5 | * Author: Renaud Cerrato <r.cerrato@til-technologies.fr> |
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
17 | #include <linux/spi/spi.h> | ||
17 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
18 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
@@ -200,6 +201,8 @@ static const struct of_device_id pcf2127_of_match[] = { | |||
200 | MODULE_DEVICE_TABLE(of, pcf2127_of_match); | 201 | MODULE_DEVICE_TABLE(of, pcf2127_of_match); |
201 | #endif | 202 | #endif |
202 | 203 | ||
204 | #if IS_ENABLED(CONFIG_I2C) | ||
205 | |||
203 | static int pcf2127_i2c_write(void *context, const void *data, size_t count) | 206 | static int pcf2127_i2c_write(void *context, const void *data, size_t count) |
204 | { | 207 | { |
205 | struct device *dev = context; | 208 | struct device *dev = context; |
@@ -311,7 +314,118 @@ static struct i2c_driver pcf2127_i2c_driver = { | |||
311 | .probe = pcf2127_i2c_probe, | 314 | .probe = pcf2127_i2c_probe, |
312 | .id_table = pcf2127_i2c_id, | 315 | .id_table = pcf2127_i2c_id, |
313 | }; | 316 | }; |
314 | module_i2c_driver(pcf2127_i2c_driver); | 317 | |
318 | static int pcf2127_i2c_register_driver(void) | ||
319 | { | ||
320 | return i2c_add_driver(&pcf2127_i2c_driver); | ||
321 | } | ||
322 | |||
323 | static void pcf2127_i2c_unregister_driver(void) | ||
324 | { | ||
325 | i2c_del_driver(&pcf2127_i2c_driver); | ||
326 | } | ||
327 | |||
328 | #else | ||
329 | |||
330 | static int pcf2127_i2c_register_driver(void) | ||
331 | { | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static void pcf2127_i2c_unregister_driver(void) | ||
336 | { | ||
337 | } | ||
338 | |||
339 | #endif | ||
340 | |||
341 | #if IS_ENABLED(CONFIG_SPI_MASTER) | ||
342 | |||
343 | static struct spi_driver pcf2127_spi_driver; | ||
344 | |||
345 | static int pcf2127_spi_probe(struct spi_device *spi) | ||
346 | { | ||
347 | static const struct regmap_config config = { | ||
348 | .reg_bits = 8, | ||
349 | .val_bits = 8, | ||
350 | .read_flag_mask = 0xa0, | ||
351 | .write_flag_mask = 0x20, | ||
352 | }; | ||
353 | struct regmap *regmap; | ||
354 | |||
355 | regmap = devm_regmap_init_spi(spi, &config); | ||
356 | if (IS_ERR(regmap)) { | ||
357 | dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n", | ||
358 | __func__, PTR_ERR(regmap)); | ||
359 | return PTR_ERR(regmap); | ||
360 | } | ||
361 | |||
362 | return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name); | ||
363 | } | ||
364 | |||
365 | static const struct spi_device_id pcf2127_spi_id[] = { | ||
366 | { "pcf2127", 0 }, | ||
367 | { } | ||
368 | }; | ||
369 | MODULE_DEVICE_TABLE(spi, pcf2127_spi_id); | ||
370 | |||
371 | static struct spi_driver pcf2127_spi_driver = { | ||
372 | .driver = { | ||
373 | .name = "rtc-pcf2127-spi", | ||
374 | .of_match_table = of_match_ptr(pcf2127_of_match), | ||
375 | }, | ||
376 | .probe = pcf2127_spi_probe, | ||
377 | .id_table = pcf2127_spi_id, | ||
378 | }; | ||
379 | |||
380 | static int pcf2127_spi_register_driver(void) | ||
381 | { | ||
382 | return spi_register_driver(&pcf2127_spi_driver); | ||
383 | } | ||
384 | |||
385 | static void pcf2127_spi_unregister_driver(void) | ||
386 | { | ||
387 | spi_unregister_driver(&pcf2127_spi_driver); | ||
388 | } | ||
389 | |||
390 | #else | ||
391 | |||
392 | static int pcf2127_spi_register_driver(void) | ||
393 | { | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | static void pcf2127_spi_unregister_driver(void) | ||
398 | { | ||
399 | } | ||
400 | |||
401 | #endif | ||
402 | |||
403 | static int __init pcf2127_init(void) | ||
404 | { | ||
405 | int ret; | ||
406 | |||
407 | ret = pcf2127_i2c_register_driver(); | ||
408 | if (ret) { | ||
409 | pr_err("Failed to register pcf2127 i2c driver: %d\n", ret); | ||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | ret = pcf2127_spi_register_driver(); | ||
414 | if (ret) { | ||
415 | pr_err("Failed to register pcf2127 spi driver: %d\n", ret); | ||
416 | pcf2127_i2c_unregister_driver(); | ||
417 | } | ||
418 | |||
419 | return ret; | ||
420 | } | ||
421 | module_init(pcf2127_init) | ||
422 | |||
423 | static void __exit pcf2127_exit(void) | ||
424 | { | ||
425 | pcf2127_spi_unregister_driver(); | ||
426 | pcf2127_i2c_unregister_driver(); | ||
427 | } | ||
428 | module_exit(pcf2127_exit) | ||
315 | 429 | ||
316 | MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>"); | 430 | MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>"); |
317 | MODULE_DESCRIPTION("NXP PCF2127 RTC driver"); | 431 | MODULE_DESCRIPTION("NXP PCF2127 RTC driver"); |