diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 31 | ||||
-rw-r--r-- | drivers/rtc/Makefile | 3 | ||||
-rw-r--r-- | drivers/rtc/class.c | 24 | ||||
-rw-r--r-- | drivers/rtc/rtc-as3722.c | 19 | ||||
-rw-r--r-- | drivers/rtc/rtc-cmos.c | 60 | ||||
-rw-r--r-- | drivers/rtc/rtc-ds1305.c | 1 | ||||
-rw-r--r-- | drivers/rtc/rtc-ds1742.c | 10 | ||||
-rw-r--r-- | drivers/rtc/rtc-hym8563.c | 606 | ||||
-rw-r--r-- | drivers/rtc/rtc-isl12057.c | 310 | ||||
-rw-r--r-- | drivers/rtc/rtc-max8907.c | 11 | ||||
-rw-r--r-- | drivers/rtc/rtc-mxc.c | 10 | ||||
-rw-r--r-- | drivers/rtc/rtc-pcf2127.c | 5 | ||||
-rw-r--r-- | drivers/rtc/rtc-rx8581.c | 81 | ||||
-rw-r--r-- | drivers/rtc/rtc-s3c.c | 17 | ||||
-rw-r--r-- | drivers/rtc/rtc-s5m.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-sunxi.c | 523 | ||||
-rw-r--r-- | drivers/rtc/rtc-twl.c | 38 | ||||
-rw-r--r-- | drivers/rtc/rtc-vr41xx.c | 50 |
18 files changed, 1676 insertions, 125 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 007730222116..db933decc39c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -212,6 +212,17 @@ config RTC_DRV_DS3232 | |||
212 | This driver can also be built as a module. If so, the module | 212 | This driver can also be built as a module. If so, the module |
213 | will be called rtc-ds3232. | 213 | will be called rtc-ds3232. |
214 | 214 | ||
215 | config RTC_DRV_HYM8563 | ||
216 | tristate "Haoyu Microelectronics HYM8563" | ||
217 | depends on I2C && OF | ||
218 | help | ||
219 | Say Y to enable support for the HYM8563 I2C RTC chip. Apart | ||
220 | from the usual rtc functions it provides a clock output of | ||
221 | up to 32kHz. | ||
222 | |||
223 | This driver can also be built as a module. If so, the module | ||
224 | will be called rtc-hym8563. | ||
225 | |||
215 | config RTC_DRV_LP8788 | 226 | config RTC_DRV_LP8788 |
216 | tristate "TI LP8788 RTC driver" | 227 | tristate "TI LP8788 RTC driver" |
217 | depends on MFD_LP8788 | 228 | depends on MFD_LP8788 |
@@ -304,6 +315,17 @@ config RTC_DRV_ISL12022 | |||
304 | This driver can also be built as a module. If so, the module | 315 | This driver can also be built as a module. If so, the module |
305 | will be called rtc-isl12022. | 316 | will be called rtc-isl12022. |
306 | 317 | ||
318 | config RTC_DRV_ISL12057 | ||
319 | depends on I2C | ||
320 | select REGMAP_I2C | ||
321 | tristate "Intersil ISL12057" | ||
322 | help | ||
323 | If you say yes here you get support for the Intersil ISL12057 | ||
324 | I2C RTC chip. | ||
325 | |||
326 | This driver can also be built as a module. If so, the module | ||
327 | will be called rtc-isl12057. | ||
328 | |||
307 | config RTC_DRV_X1205 | 329 | config RTC_DRV_X1205 |
308 | tristate "Xicor/Intersil X1205" | 330 | tristate "Xicor/Intersil X1205" |
309 | help | 331 | help |
@@ -626,7 +648,7 @@ comment "Platform RTC drivers" | |||
626 | 648 | ||
627 | config RTC_DRV_CMOS | 649 | config RTC_DRV_CMOS |
628 | tristate "PC-style 'CMOS'" | 650 | tristate "PC-style 'CMOS'" |
629 | depends on X86 || ARM || M32R || ATARI || PPC || MIPS || SPARC64 | 651 | depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 |
630 | default y if X86 | 652 | default y if X86 |
631 | help | 653 | help |
632 | Say "yes" here to get direct support for the real time clock | 654 | Say "yes" here to get direct support for the real time clock |
@@ -1104,6 +1126,13 @@ config RTC_DRV_SUN4V | |||
1104 | If you say Y here you will get support for the Hypervisor | 1126 | If you say Y here you will get support for the Hypervisor |
1105 | based RTC on SUN4V systems. | 1127 | based RTC on SUN4V systems. |
1106 | 1128 | ||
1129 | config RTC_DRV_SUNXI | ||
1130 | tristate "Allwinner sun4i/sun7i RTC" | ||
1131 | depends on ARCH_SUNXI | ||
1132 | help | ||
1133 | If you say Y here you will get support for the RTC found on | ||
1134 | Allwinner A10/A20. | ||
1135 | |||
1107 | config RTC_DRV_STARFIRE | 1136 | config RTC_DRV_STARFIRE |
1108 | bool "Starfire RTC" | 1137 | bool "Starfire RTC" |
1109 | depends on SPARC64 | 1138 | depends on SPARC64 |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 27b4bd884066..b427bf7dd20d 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -55,9 +55,11 @@ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | |||
55 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 55 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
56 | obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o | 56 | obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o |
57 | obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o | 57 | obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o |
58 | obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o | ||
58 | obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o | 59 | obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o |
59 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 60 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
60 | obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o | 61 | obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o |
62 | obj-$(CONFIG_RTC_DRV_ISL12057) += rtc-isl12057.o | ||
61 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o | 63 | obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o |
62 | obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o | 64 | obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o |
63 | obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o | 65 | obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o |
@@ -117,6 +119,7 @@ obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o | |||
117 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o | 119 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o |
118 | obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o | 120 | obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o |
119 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o | 121 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o |
122 | obj-$(CONFIG_RTC_DRV_SUNXI) += rtc-sunxi.o | ||
120 | obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o | 123 | obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o |
121 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | 124 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o |
122 | obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o | 125 | obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 02426812bebc..589351ef75d0 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/of.h> | ||
17 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
18 | #include <linux/kdev_t.h> | 19 | #include <linux/kdev_t.h> |
19 | #include <linux/idr.h> | 20 | #include <linux/idr.h> |
@@ -157,12 +158,27 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
157 | { | 158 | { |
158 | struct rtc_device *rtc; | 159 | struct rtc_device *rtc; |
159 | struct rtc_wkalrm alrm; | 160 | struct rtc_wkalrm alrm; |
160 | int id, err; | 161 | int of_id = -1, id = -1, err; |
162 | |||
163 | if (dev->of_node) | ||
164 | of_id = of_alias_get_id(dev->of_node, "rtc"); | ||
165 | else if (dev->parent && dev->parent->of_node) | ||
166 | of_id = of_alias_get_id(dev->parent->of_node, "rtc"); | ||
167 | |||
168 | if (of_id >= 0) { | ||
169 | id = ida_simple_get(&rtc_ida, of_id, of_id + 1, | ||
170 | GFP_KERNEL); | ||
171 | if (id < 0) | ||
172 | dev_warn(dev, "/aliases ID %d not available\n", | ||
173 | of_id); | ||
174 | } | ||
161 | 175 | ||
162 | id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL); | ||
163 | if (id < 0) { | 176 | if (id < 0) { |
164 | err = id; | 177 | id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL); |
165 | goto exit; | 178 | if (id < 0) { |
179 | err = id; | ||
180 | goto exit; | ||
181 | } | ||
166 | } | 182 | } |
167 | 183 | ||
168 | rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); | 184 | rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); |
diff --git a/drivers/rtc/rtc-as3722.c b/drivers/rtc/rtc-as3722.c index 9cfa8170a2d6..4af016985890 100644 --- a/drivers/rtc/rtc-as3722.c +++ b/drivers/rtc/rtc-as3722.c | |||
@@ -198,7 +198,7 @@ static int as3722_rtc_probe(struct platform_device *pdev) | |||
198 | 198 | ||
199 | device_init_wakeup(&pdev->dev, 1); | 199 | device_init_wakeup(&pdev->dev, 1); |
200 | 200 | ||
201 | as3722_rtc->rtc = rtc_device_register("as3722", &pdev->dev, | 201 | as3722_rtc->rtc = devm_rtc_device_register(&pdev->dev, "as3722-rtc", |
202 | &as3722_rtc_ops, THIS_MODULE); | 202 | &as3722_rtc_ops, THIS_MODULE); |
203 | if (IS_ERR(as3722_rtc->rtc)) { | 203 | if (IS_ERR(as3722_rtc->rtc)) { |
204 | ret = PTR_ERR(as3722_rtc->rtc); | 204 | ret = PTR_ERR(as3722_rtc->rtc); |
@@ -209,28 +209,16 @@ static int as3722_rtc_probe(struct platform_device *pdev) | |||
209 | as3722_rtc->alarm_irq = platform_get_irq(pdev, 0); | 209 | as3722_rtc->alarm_irq = platform_get_irq(pdev, 0); |
210 | dev_info(&pdev->dev, "RTC interrupt %d\n", as3722_rtc->alarm_irq); | 210 | dev_info(&pdev->dev, "RTC interrupt %d\n", as3722_rtc->alarm_irq); |
211 | 211 | ||
212 | ret = request_threaded_irq(as3722_rtc->alarm_irq, NULL, | 212 | ret = devm_request_threaded_irq(&pdev->dev, as3722_rtc->alarm_irq, NULL, |
213 | as3722_alarm_irq, IRQF_ONESHOT | IRQF_EARLY_RESUME, | 213 | as3722_alarm_irq, IRQF_ONESHOT | IRQF_EARLY_RESUME, |
214 | "rtc-alarm", as3722_rtc); | 214 | "rtc-alarm", as3722_rtc); |
215 | if (ret < 0) { | 215 | if (ret < 0) { |
216 | dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", | 216 | dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", |
217 | as3722_rtc->alarm_irq, ret); | 217 | as3722_rtc->alarm_irq, ret); |
218 | goto scrub; | 218 | return ret; |
219 | } | 219 | } |
220 | disable_irq(as3722_rtc->alarm_irq); | 220 | disable_irq(as3722_rtc->alarm_irq); |
221 | return 0; | 221 | return 0; |
222 | scrub: | ||
223 | rtc_device_unregister(as3722_rtc->rtc); | ||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | static int as3722_rtc_remove(struct platform_device *pdev) | ||
228 | { | ||
229 | struct as3722_rtc *as3722_rtc = platform_get_drvdata(pdev); | ||
230 | |||
231 | free_irq(as3722_rtc->alarm_irq, as3722_rtc); | ||
232 | rtc_device_unregister(as3722_rtc->rtc); | ||
233 | return 0; | ||
234 | } | 222 | } |
235 | 223 | ||
236 | #ifdef CONFIG_PM_SLEEP | 224 | #ifdef CONFIG_PM_SLEEP |
@@ -260,7 +248,6 @@ static const struct dev_pm_ops as3722_rtc_pm_ops = { | |||
260 | 248 | ||
261 | static struct platform_driver as3722_rtc_driver = { | 249 | static struct platform_driver as3722_rtc_driver = { |
262 | .probe = as3722_rtc_probe, | 250 | .probe = as3722_rtc_probe, |
263 | .remove = as3722_rtc_remove, | ||
264 | .driver = { | 251 | .driver = { |
265 | .name = "as3722-rtc", | 252 | .name = "as3722-rtc", |
266 | .pm = &as3722_rtc_pm_ops, | 253 | .pm = &as3722_rtc_pm_ops, |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index f14876256a4a..cae212f30d65 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -34,11 +34,11 @@ | |||
34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
35 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/mod_devicetable.h> | ||
38 | #include <linux/log2.h> | 37 | #include <linux/log2.h> |
39 | #include <linux/pm.h> | 38 | #include <linux/pm.h> |
40 | #include <linux/of.h> | 39 | #include <linux/of.h> |
41 | #include <linux/of_platform.h> | 40 | #include <linux/of_platform.h> |
41 | #include <linux/dmi.h> | ||
42 | 42 | ||
43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
44 | #include <asm-generic/rtc.h> | 44 | #include <asm-generic/rtc.h> |
@@ -377,6 +377,51 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
377 | return 0; | 377 | return 0; |
378 | } | 378 | } |
379 | 379 | ||
380 | /* | ||
381 | * Do not disable RTC alarm on shutdown - workaround for b0rked BIOSes. | ||
382 | */ | ||
383 | static bool alarm_disable_quirk; | ||
384 | |||
385 | static int __init set_alarm_disable_quirk(const struct dmi_system_id *id) | ||
386 | { | ||
387 | alarm_disable_quirk = true; | ||
388 | pr_info("rtc-cmos: BIOS has alarm-disable quirk. "); | ||
389 | pr_info("RTC alarms disabled\n"); | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static const struct dmi_system_id rtc_quirks[] __initconst = { | ||
394 | /* https://bugzilla.novell.com/show_bug.cgi?id=805740 */ | ||
395 | { | ||
396 | .callback = set_alarm_disable_quirk, | ||
397 | .ident = "IBM Truman", | ||
398 | .matches = { | ||
399 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
400 | DMI_MATCH(DMI_PRODUCT_NAME, "4852570"), | ||
401 | }, | ||
402 | }, | ||
403 | /* https://bugzilla.novell.com/show_bug.cgi?id=812592 */ | ||
404 | { | ||
405 | .callback = set_alarm_disable_quirk, | ||
406 | .ident = "Gigabyte GA-990XA-UD3", | ||
407 | .matches = { | ||
408 | DMI_MATCH(DMI_SYS_VENDOR, | ||
409 | "Gigabyte Technology Co., Ltd."), | ||
410 | DMI_MATCH(DMI_PRODUCT_NAME, "GA-990XA-UD3"), | ||
411 | }, | ||
412 | }, | ||
413 | /* http://permalink.gmane.org/gmane.linux.kernel/1604474 */ | ||
414 | { | ||
415 | .callback = set_alarm_disable_quirk, | ||
416 | .ident = "Toshiba Satellite L300", | ||
417 | .matches = { | ||
418 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
419 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), | ||
420 | }, | ||
421 | }, | ||
422 | {} | ||
423 | }; | ||
424 | |||
380 | static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) | 425 | static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) |
381 | { | 426 | { |
382 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 427 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
@@ -385,6 +430,9 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
385 | if (!is_valid_irq(cmos->irq)) | 430 | if (!is_valid_irq(cmos->irq)) |
386 | return -EINVAL; | 431 | return -EINVAL; |
387 | 432 | ||
433 | if (alarm_disable_quirk) | ||
434 | return 0; | ||
435 | |||
388 | spin_lock_irqsave(&rtc_lock, flags); | 436 | spin_lock_irqsave(&rtc_lock, flags); |
389 | 437 | ||
390 | if (enabled) | 438 | if (enabled) |
@@ -708,11 +756,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
708 | irq_handler_t rtc_cmos_int_handler; | 756 | irq_handler_t rtc_cmos_int_handler; |
709 | 757 | ||
710 | if (is_hpet_enabled()) { | 758 | if (is_hpet_enabled()) { |
711 | int err; | ||
712 | |||
713 | rtc_cmos_int_handler = hpet_rtc_interrupt; | 759 | rtc_cmos_int_handler = hpet_rtc_interrupt; |
714 | err = hpet_register_irq_handler(cmos_interrupt); | 760 | retval = hpet_register_irq_handler(cmos_interrupt); |
715 | if (err != 0) { | 761 | if (retval) { |
716 | dev_warn(dev, "hpet_register_irq_handler " | 762 | dev_warn(dev, "hpet_register_irq_handler " |
717 | " failed in rtc_init()."); | 763 | " failed in rtc_init()."); |
718 | goto cleanup1; | 764 | goto cleanup1; |
@@ -1127,7 +1173,7 @@ static struct platform_driver cmos_platform_driver = { | |||
1127 | .remove = __exit_p(cmos_platform_remove), | 1173 | .remove = __exit_p(cmos_platform_remove), |
1128 | .shutdown = cmos_platform_shutdown, | 1174 | .shutdown = cmos_platform_shutdown, |
1129 | .driver = { | 1175 | .driver = { |
1130 | .name = (char *) driver_name, | 1176 | .name = driver_name, |
1131 | #ifdef CONFIG_PM | 1177 | #ifdef CONFIG_PM |
1132 | .pm = &cmos_pm_ops, | 1178 | .pm = &cmos_pm_ops, |
1133 | #endif | 1179 | #endif |
@@ -1157,6 +1203,8 @@ static int __init cmos_init(void) | |||
1157 | platform_driver_registered = true; | 1203 | platform_driver_registered = true; |
1158 | } | 1204 | } |
1159 | 1205 | ||
1206 | dmi_check_system(rtc_quirks); | ||
1207 | |||
1160 | if (retval == 0) | 1208 | if (retval == 0) |
1161 | return 0; | 1209 | return 0; |
1162 | 1210 | ||
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 80f323731ee2..2dd586a19b59 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c | |||
@@ -787,7 +787,6 @@ static int ds1305_remove(struct spi_device *spi) | |||
787 | cancel_work_sync(&ds1305->work); | 787 | cancel_work_sync(&ds1305->work); |
788 | } | 788 | } |
789 | 789 | ||
790 | spi_set_drvdata(spi, NULL); | ||
791 | return 0; | 790 | return 0; |
792 | } | 791 | } |
793 | 792 | ||
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 17b73fdc3b6e..5a1f3b2a8f1e 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
@@ -13,12 +13,13 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
16 | #include <linux/init.h> | ||
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/gfp.h> | 17 | #include <linux/gfp.h> |
19 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
20 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
21 | #include <linux/rtc.h> | 20 | #include <linux/rtc.h> |
21 | #include <linux/of.h> | ||
22 | #include <linux/of_device.h> | ||
22 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
23 | #include <linux/io.h> | 24 | #include <linux/io.h> |
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
@@ -215,12 +216,19 @@ static int ds1742_rtc_remove(struct platform_device *pdev) | |||
215 | return 0; | 216 | return 0; |
216 | } | 217 | } |
217 | 218 | ||
219 | static struct of_device_id __maybe_unused ds1742_rtc_of_match[] = { | ||
220 | { .compatible = "maxim,ds1742", }, | ||
221 | { } | ||
222 | }; | ||
223 | MODULE_DEVICE_TABLE(of, ds1742_rtc_of_match); | ||
224 | |||
218 | static struct platform_driver ds1742_rtc_driver = { | 225 | static struct platform_driver ds1742_rtc_driver = { |
219 | .probe = ds1742_rtc_probe, | 226 | .probe = ds1742_rtc_probe, |
220 | .remove = ds1742_rtc_remove, | 227 | .remove = ds1742_rtc_remove, |
221 | .driver = { | 228 | .driver = { |
222 | .name = "rtc-ds1742", | 229 | .name = "rtc-ds1742", |
223 | .owner = THIS_MODULE, | 230 | .owner = THIS_MODULE, |
231 | .of_match_table = ds1742_rtc_of_match, | ||
224 | }, | 232 | }, |
225 | }; | 233 | }; |
226 | 234 | ||
diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c new file mode 100644 index 000000000000..bd628a6f981d --- /dev/null +++ b/drivers/rtc/rtc-hym8563.c | |||
@@ -0,0 +1,606 @@ | |||
1 | /* | ||
2 | * Haoyu HYM8563 RTC driver | ||
3 | * | ||
4 | * Copyright (C) 2013 MundoReader S.L. | ||
5 | * Author: Heiko Stuebner <heiko@sntech.de> | ||
6 | * | ||
7 | * based on rtc-HYM8563 | ||
8 | * Copyright (C) 2010 ROCKCHIP, Inc. | ||
9 | * | ||
10 | * This software is licensed under the terms of the GNU General Public | ||
11 | * License version 2, as published by the Free Software Foundation, and | ||
12 | * may be copied, distributed, and modified under those terms. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/clk-provider.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/bcd.h> | ||
24 | #include <linux/rtc.h> | ||
25 | |||
26 | #define HYM8563_CTL1 0x00 | ||
27 | #define HYM8563_CTL1_TEST BIT(7) | ||
28 | #define HYM8563_CTL1_STOP BIT(5) | ||
29 | #define HYM8563_CTL1_TESTC BIT(3) | ||
30 | |||
31 | #define HYM8563_CTL2 0x01 | ||
32 | #define HYM8563_CTL2_TI_TP BIT(4) | ||
33 | #define HYM8563_CTL2_AF BIT(3) | ||
34 | #define HYM8563_CTL2_TF BIT(2) | ||
35 | #define HYM8563_CTL2_AIE BIT(1) | ||
36 | #define HYM8563_CTL2_TIE BIT(0) | ||
37 | |||
38 | #define HYM8563_SEC 0x02 | ||
39 | #define HYM8563_SEC_VL BIT(7) | ||
40 | #define HYM8563_SEC_MASK 0x7f | ||
41 | |||
42 | #define HYM8563_MIN 0x03 | ||
43 | #define HYM8563_MIN_MASK 0x7f | ||
44 | |||
45 | #define HYM8563_HOUR 0x04 | ||
46 | #define HYM8563_HOUR_MASK 0x3f | ||
47 | |||
48 | #define HYM8563_DAY 0x05 | ||
49 | #define HYM8563_DAY_MASK 0x3f | ||
50 | |||
51 | #define HYM8563_WEEKDAY 0x06 | ||
52 | #define HYM8563_WEEKDAY_MASK 0x07 | ||
53 | |||
54 | #define HYM8563_MONTH 0x07 | ||
55 | #define HYM8563_MONTH_CENTURY BIT(7) | ||
56 | #define HYM8563_MONTH_MASK 0x1f | ||
57 | |||
58 | #define HYM8563_YEAR 0x08 | ||
59 | |||
60 | #define HYM8563_ALM_MIN 0x09 | ||
61 | #define HYM8563_ALM_HOUR 0x0a | ||
62 | #define HYM8563_ALM_DAY 0x0b | ||
63 | #define HYM8563_ALM_WEEK 0x0c | ||
64 | |||
65 | /* Each alarm check can be disabled by setting this bit in the register */ | ||
66 | #define HYM8563_ALM_BIT_DISABLE BIT(7) | ||
67 | |||
68 | #define HYM8563_CLKOUT 0x0d | ||
69 | #define HYM8563_CLKOUT_DISABLE BIT(7) | ||
70 | #define HYM8563_CLKOUT_32768 0 | ||
71 | #define HYM8563_CLKOUT_1024 1 | ||
72 | #define HYM8563_CLKOUT_32 2 | ||
73 | #define HYM8563_CLKOUT_1 3 | ||
74 | #define HYM8563_CLKOUT_MASK 3 | ||
75 | |||
76 | #define HYM8563_TMR_CTL 0x0e | ||
77 | #define HYM8563_TMR_CTL_ENABLE BIT(7) | ||
78 | #define HYM8563_TMR_CTL_4096 0 | ||
79 | #define HYM8563_TMR_CTL_64 1 | ||
80 | #define HYM8563_TMR_CTL_1 2 | ||
81 | #define HYM8563_TMR_CTL_1_60 3 | ||
82 | #define HYM8563_TMR_CTL_MASK 3 | ||
83 | |||
84 | #define HYM8563_TMR_CNT 0x0f | ||
85 | |||
86 | struct hym8563 { | ||
87 | struct i2c_client *client; | ||
88 | struct rtc_device *rtc; | ||
89 | bool valid; | ||
90 | #ifdef CONFIG_COMMON_CLK | ||
91 | struct clk_hw clkout_hw; | ||
92 | #endif | ||
93 | }; | ||
94 | |||
95 | /* | ||
96 | * RTC handling | ||
97 | */ | ||
98 | |||
99 | static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
100 | { | ||
101 | struct i2c_client *client = to_i2c_client(dev); | ||
102 | struct hym8563 *hym8563 = i2c_get_clientdata(client); | ||
103 | u8 buf[7]; | ||
104 | int ret; | ||
105 | |||
106 | if (!hym8563->valid) { | ||
107 | dev_warn(&client->dev, "no valid clock/calendar values available\n"); | ||
108 | return -EPERM; | ||
109 | } | ||
110 | |||
111 | ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf); | ||
112 | |||
113 | tm->tm_sec = bcd2bin(buf[0] & HYM8563_SEC_MASK); | ||
114 | tm->tm_min = bcd2bin(buf[1] & HYM8563_MIN_MASK); | ||
115 | tm->tm_hour = bcd2bin(buf[2] & HYM8563_HOUR_MASK); | ||
116 | tm->tm_mday = bcd2bin(buf[3] & HYM8563_DAY_MASK); | ||
117 | tm->tm_wday = bcd2bin(buf[4] & HYM8563_WEEKDAY_MASK); /* 0 = Sun */ | ||
118 | tm->tm_mon = bcd2bin(buf[5] & HYM8563_MONTH_MASK) - 1; /* 0 = Jan */ | ||
119 | tm->tm_year = bcd2bin(buf[6]) + 100; | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
125 | { | ||
126 | struct i2c_client *client = to_i2c_client(dev); | ||
127 | struct hym8563 *hym8563 = i2c_get_clientdata(client); | ||
128 | u8 buf[7]; | ||
129 | int ret; | ||
130 | |||
131 | /* Years >= 2100 are to far in the future, 19XX is to early */ | ||
132 | if (tm->tm_year < 100 || tm->tm_year >= 200) | ||
133 | return -EINVAL; | ||
134 | |||
135 | buf[0] = bin2bcd(tm->tm_sec); | ||
136 | buf[1] = bin2bcd(tm->tm_min); | ||
137 | buf[2] = bin2bcd(tm->tm_hour); | ||
138 | buf[3] = bin2bcd(tm->tm_mday); | ||
139 | buf[4] = bin2bcd(tm->tm_wday); | ||
140 | buf[5] = bin2bcd(tm->tm_mon + 1); | ||
141 | |||
142 | /* | ||
143 | * While the HYM8563 has a century flag in the month register, | ||
144 | * it does not seem to carry it over a subsequent write/read. | ||
145 | * So we'll limit ourself to 100 years, starting at 2000 for now. | ||
146 | */ | ||
147 | buf[6] = tm->tm_year - 100; | ||
148 | |||
149 | /* | ||
150 | * CTL1 only contains TEST-mode bits apart from stop, | ||
151 | * so no need to read the value first | ||
152 | */ | ||
153 | ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, | ||
154 | HYM8563_CTL1_STOP); | ||
155 | if (ret < 0) | ||
156 | return ret; | ||
157 | |||
158 | ret = i2c_smbus_write_i2c_block_data(client, HYM8563_SEC, 7, buf); | ||
159 | if (ret < 0) | ||
160 | return ret; | ||
161 | |||
162 | ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0); | ||
163 | if (ret < 0) | ||
164 | return ret; | ||
165 | |||
166 | hym8563->valid = true; | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static int hym8563_rtc_alarm_irq_enable(struct device *dev, | ||
172 | unsigned int enabled) | ||
173 | { | ||
174 | struct i2c_client *client = to_i2c_client(dev); | ||
175 | int data; | ||
176 | |||
177 | data = i2c_smbus_read_byte_data(client, HYM8563_CTL2); | ||
178 | if (data < 0) | ||
179 | return data; | ||
180 | |||
181 | if (enabled) | ||
182 | data |= HYM8563_CTL2_AIE; | ||
183 | else | ||
184 | data &= ~HYM8563_CTL2_AIE; | ||
185 | |||
186 | return i2c_smbus_write_byte_data(client, HYM8563_CTL2, data); | ||
187 | }; | ||
188 | |||
189 | static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
190 | { | ||
191 | struct i2c_client *client = to_i2c_client(dev); | ||
192 | struct rtc_time *alm_tm = &alm->time; | ||
193 | u8 buf[4]; | ||
194 | int ret; | ||
195 | |||
196 | ret = i2c_smbus_read_i2c_block_data(client, HYM8563_ALM_MIN, 4, buf); | ||
197 | if (ret < 0) | ||
198 | return ret; | ||
199 | |||
200 | /* The alarm only has a minute accuracy */ | ||
201 | alm_tm->tm_sec = -1; | ||
202 | |||
203 | alm_tm->tm_min = (buf[0] & HYM8563_ALM_BIT_DISABLE) ? | ||
204 | -1 : | ||
205 | bcd2bin(buf[0] & HYM8563_MIN_MASK); | ||
206 | alm_tm->tm_hour = (buf[1] & HYM8563_ALM_BIT_DISABLE) ? | ||
207 | -1 : | ||
208 | bcd2bin(buf[1] & HYM8563_HOUR_MASK); | ||
209 | alm_tm->tm_mday = (buf[2] & HYM8563_ALM_BIT_DISABLE) ? | ||
210 | -1 : | ||
211 | bcd2bin(buf[2] & HYM8563_DAY_MASK); | ||
212 | alm_tm->tm_wday = (buf[3] & HYM8563_ALM_BIT_DISABLE) ? | ||
213 | -1 : | ||
214 | bcd2bin(buf[3] & HYM8563_WEEKDAY_MASK); | ||
215 | |||
216 | alm_tm->tm_mon = -1; | ||
217 | alm_tm->tm_year = -1; | ||
218 | |||
219 | ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2); | ||
220 | if (ret < 0) | ||
221 | return ret; | ||
222 | |||
223 | if (ret & HYM8563_CTL2_AIE) | ||
224 | alm->enabled = 1; | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int hym8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
230 | { | ||
231 | struct i2c_client *client = to_i2c_client(dev); | ||
232 | struct rtc_time *alm_tm = &alm->time; | ||
233 | u8 buf[4]; | ||
234 | int ret; | ||
235 | |||
236 | /* | ||
237 | * The alarm has no seconds so deal with it | ||
238 | */ | ||
239 | if (alm_tm->tm_sec) { | ||
240 | alm_tm->tm_sec = 0; | ||
241 | alm_tm->tm_min++; | ||
242 | if (alm_tm->tm_min >= 60) { | ||
243 | alm_tm->tm_min = 0; | ||
244 | alm_tm->tm_hour++; | ||
245 | if (alm_tm->tm_hour >= 24) { | ||
246 | alm_tm->tm_hour = 0; | ||
247 | alm_tm->tm_mday++; | ||
248 | if (alm_tm->tm_mday > 31) | ||
249 | alm_tm->tm_mday = 0; | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | |||
254 | ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2); | ||
255 | if (ret < 0) | ||
256 | return ret; | ||
257 | |||
258 | ret &= ~HYM8563_CTL2_AIE; | ||
259 | |||
260 | ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret); | ||
261 | if (ret < 0) | ||
262 | return ret; | ||
263 | |||
264 | buf[0] = (alm_tm->tm_min < 60 && alm_tm->tm_min >= 0) ? | ||
265 | bin2bcd(alm_tm->tm_min) : HYM8563_ALM_BIT_DISABLE; | ||
266 | |||
267 | buf[1] = (alm_tm->tm_hour < 24 && alm_tm->tm_hour >= 0) ? | ||
268 | bin2bcd(alm_tm->tm_hour) : HYM8563_ALM_BIT_DISABLE; | ||
269 | |||
270 | buf[2] = (alm_tm->tm_mday <= 31 && alm_tm->tm_mday >= 1) ? | ||
271 | bin2bcd(alm_tm->tm_mday) : HYM8563_ALM_BIT_DISABLE; | ||
272 | |||
273 | buf[3] = (alm_tm->tm_wday < 7 && alm_tm->tm_wday >= 0) ? | ||
274 | bin2bcd(alm_tm->tm_wday) : HYM8563_ALM_BIT_DISABLE; | ||
275 | |||
276 | ret = i2c_smbus_write_i2c_block_data(client, HYM8563_ALM_MIN, 4, buf); | ||
277 | if (ret < 0) | ||
278 | return ret; | ||
279 | |||
280 | return hym8563_rtc_alarm_irq_enable(dev, alm->enabled); | ||
281 | } | ||
282 | |||
283 | static const struct rtc_class_ops hym8563_rtc_ops = { | ||
284 | .read_time = hym8563_rtc_read_time, | ||
285 | .set_time = hym8563_rtc_set_time, | ||
286 | .alarm_irq_enable = hym8563_rtc_alarm_irq_enable, | ||
287 | .read_alarm = hym8563_rtc_read_alarm, | ||
288 | .set_alarm = hym8563_rtc_set_alarm, | ||
289 | }; | ||
290 | |||
291 | /* | ||
292 | * Handling of the clkout | ||
293 | */ | ||
294 | |||
295 | #ifdef CONFIG_COMMON_CLK | ||
296 | #define clkout_hw_to_hym8563(_hw) container_of(_hw, struct hym8563, clkout_hw) | ||
297 | |||
298 | static int clkout_rates[] = { | ||
299 | 32768, | ||
300 | 1024, | ||
301 | 32, | ||
302 | 1, | ||
303 | }; | ||
304 | |||
305 | static unsigned long hym8563_clkout_recalc_rate(struct clk_hw *hw, | ||
306 | unsigned long parent_rate) | ||
307 | { | ||
308 | struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw); | ||
309 | struct i2c_client *client = hym8563->client; | ||
310 | int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT); | ||
311 | |||
312 | if (ret < 0 || ret & HYM8563_CLKOUT_DISABLE) | ||
313 | return 0; | ||
314 | |||
315 | ret &= HYM8563_CLKOUT_MASK; | ||
316 | return clkout_rates[ret]; | ||
317 | } | ||
318 | |||
319 | static long hym8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate, | ||
320 | unsigned long *prate) | ||
321 | { | ||
322 | int i; | ||
323 | |||
324 | for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) | ||
325 | if (clkout_rates[i] <= rate) | ||
326 | return clkout_rates[i]; | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static int hym8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate, | ||
332 | unsigned long parent_rate) | ||
333 | { | ||
334 | struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw); | ||
335 | struct i2c_client *client = hym8563->client; | ||
336 | int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT); | ||
337 | int i; | ||
338 | |||
339 | if (ret < 0) | ||
340 | return ret; | ||
341 | |||
342 | for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) | ||
343 | if (clkout_rates[i] == rate) { | ||
344 | ret &= ~HYM8563_CLKOUT_MASK; | ||
345 | ret |= i; | ||
346 | return i2c_smbus_write_byte_data(client, | ||
347 | HYM8563_CLKOUT, ret); | ||
348 | } | ||
349 | |||
350 | return -EINVAL; | ||
351 | } | ||
352 | |||
353 | static int hym8563_clkout_control(struct clk_hw *hw, bool enable) | ||
354 | { | ||
355 | struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw); | ||
356 | struct i2c_client *client = hym8563->client; | ||
357 | int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT); | ||
358 | |||
359 | if (ret < 0) | ||
360 | return ret; | ||
361 | |||
362 | if (enable) | ||
363 | ret &= ~HYM8563_CLKOUT_DISABLE; | ||
364 | else | ||
365 | ret |= HYM8563_CLKOUT_DISABLE; | ||
366 | |||
367 | return i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, ret); | ||
368 | } | ||
369 | |||
370 | static int hym8563_clkout_prepare(struct clk_hw *hw) | ||
371 | { | ||
372 | return hym8563_clkout_control(hw, 1); | ||
373 | } | ||
374 | |||
375 | static void hym8563_clkout_unprepare(struct clk_hw *hw) | ||
376 | { | ||
377 | hym8563_clkout_control(hw, 0); | ||
378 | } | ||
379 | |||
380 | static int hym8563_clkout_is_prepared(struct clk_hw *hw) | ||
381 | { | ||
382 | struct hym8563 *hym8563 = clkout_hw_to_hym8563(hw); | ||
383 | struct i2c_client *client = hym8563->client; | ||
384 | int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT); | ||
385 | |||
386 | if (ret < 0) | ||
387 | return ret; | ||
388 | |||
389 | return !(ret & HYM8563_CLKOUT_DISABLE); | ||
390 | } | ||
391 | |||
392 | static const struct clk_ops hym8563_clkout_ops = { | ||
393 | .prepare = hym8563_clkout_prepare, | ||
394 | .unprepare = hym8563_clkout_unprepare, | ||
395 | .is_prepared = hym8563_clkout_is_prepared, | ||
396 | .recalc_rate = hym8563_clkout_recalc_rate, | ||
397 | .round_rate = hym8563_clkout_round_rate, | ||
398 | .set_rate = hym8563_clkout_set_rate, | ||
399 | }; | ||
400 | |||
401 | static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563) | ||
402 | { | ||
403 | struct i2c_client *client = hym8563->client; | ||
404 | struct device_node *node = client->dev.of_node; | ||
405 | struct clk *clk; | ||
406 | struct clk_init_data init; | ||
407 | int ret; | ||
408 | |||
409 | ret = i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, | ||
410 | HYM8563_CLKOUT_DISABLE); | ||
411 | if (ret < 0) | ||
412 | return ERR_PTR(ret); | ||
413 | |||
414 | init.name = "hym8563-clkout"; | ||
415 | init.ops = &hym8563_clkout_ops; | ||
416 | init.flags = CLK_IS_ROOT; | ||
417 | init.parent_names = NULL; | ||
418 | init.num_parents = 0; | ||
419 | hym8563->clkout_hw.init = &init; | ||
420 | |||
421 | /* register the clock */ | ||
422 | clk = clk_register(&client->dev, &hym8563->clkout_hw); | ||
423 | |||
424 | if (!IS_ERR(clk)) | ||
425 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
426 | |||
427 | return clk; | ||
428 | } | ||
429 | #endif | ||
430 | |||
431 | /* | ||
432 | * The alarm interrupt is implemented as a level-low interrupt in the | ||
433 | * hym8563, while the timer interrupt uses a falling edge. | ||
434 | * We don't use the timer at all, so the interrupt is requested to | ||
435 | * use the level-low trigger. | ||
436 | */ | ||
437 | static irqreturn_t hym8563_irq(int irq, void *dev_id) | ||
438 | { | ||
439 | struct hym8563 *hym8563 = (struct hym8563 *)dev_id; | ||
440 | struct i2c_client *client = hym8563->client; | ||
441 | struct mutex *lock = &hym8563->rtc->ops_lock; | ||
442 | int data, ret; | ||
443 | |||
444 | mutex_lock(lock); | ||
445 | |||
446 | /* Clear the alarm flag */ | ||
447 | |||
448 | data = i2c_smbus_read_byte_data(client, HYM8563_CTL2); | ||
449 | if (data < 0) { | ||
450 | dev_err(&client->dev, "%s: error reading i2c data %d\n", | ||
451 | __func__, data); | ||
452 | goto out; | ||
453 | } | ||
454 | |||
455 | data &= ~HYM8563_CTL2_AF; | ||
456 | |||
457 | ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, data); | ||
458 | if (ret < 0) { | ||
459 | dev_err(&client->dev, "%s: error writing i2c data %d\n", | ||
460 | __func__, ret); | ||
461 | } | ||
462 | |||
463 | out: | ||
464 | mutex_unlock(lock); | ||
465 | return IRQ_HANDLED; | ||
466 | } | ||
467 | |||
468 | static int hym8563_init_device(struct i2c_client *client) | ||
469 | { | ||
470 | int ret; | ||
471 | |||
472 | /* Clear stop flag if present */ | ||
473 | ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0); | ||
474 | if (ret < 0) | ||
475 | return ret; | ||
476 | |||
477 | ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2); | ||
478 | if (ret < 0) | ||
479 | return ret; | ||
480 | |||
481 | /* Disable alarm and timer interrupts */ | ||
482 | ret &= ~HYM8563_CTL2_AIE; | ||
483 | ret &= ~HYM8563_CTL2_TIE; | ||
484 | |||
485 | /* Clear any pending alarm and timer flags */ | ||
486 | if (ret & HYM8563_CTL2_AF) | ||
487 | ret &= ~HYM8563_CTL2_AF; | ||
488 | |||
489 | if (ret & HYM8563_CTL2_TF) | ||
490 | ret &= ~HYM8563_CTL2_TF; | ||
491 | |||
492 | ret &= ~HYM8563_CTL2_TI_TP; | ||
493 | |||
494 | return i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret); | ||
495 | } | ||
496 | |||
497 | #ifdef CONFIG_PM_SLEEP | ||
498 | static int hym8563_suspend(struct device *dev) | ||
499 | { | ||
500 | struct i2c_client *client = to_i2c_client(dev); | ||
501 | int ret; | ||
502 | |||
503 | if (device_may_wakeup(dev)) { | ||
504 | ret = enable_irq_wake(client->irq); | ||
505 | if (ret) { | ||
506 | dev_err(dev, "enable_irq_wake failed, %d\n", ret); | ||
507 | return ret; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static int hym8563_resume(struct device *dev) | ||
515 | { | ||
516 | struct i2c_client *client = to_i2c_client(dev); | ||
517 | |||
518 | if (device_may_wakeup(dev)) | ||
519 | disable_irq_wake(client->irq); | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | #endif | ||
524 | |||
525 | static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume); | ||
526 | |||
527 | static int hym8563_probe(struct i2c_client *client, | ||
528 | const struct i2c_device_id *id) | ||
529 | { | ||
530 | struct hym8563 *hym8563; | ||
531 | int ret; | ||
532 | |||
533 | hym8563 = devm_kzalloc(&client->dev, sizeof(*hym8563), GFP_KERNEL); | ||
534 | if (!hym8563) | ||
535 | return -ENOMEM; | ||
536 | |||
537 | hym8563->client = client; | ||
538 | i2c_set_clientdata(client, hym8563); | ||
539 | |||
540 | device_set_wakeup_capable(&client->dev, true); | ||
541 | |||
542 | ret = hym8563_init_device(client); | ||
543 | if (ret) { | ||
544 | dev_err(&client->dev, "could not init device, %d\n", ret); | ||
545 | return ret; | ||
546 | } | ||
547 | |||
548 | ret = devm_request_threaded_irq(&client->dev, client->irq, | ||
549 | NULL, hym8563_irq, | ||
550 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
551 | client->name, hym8563); | ||
552 | if (ret < 0) { | ||
553 | dev_err(&client->dev, "irq %d request failed, %d\n", | ||
554 | client->irq, ret); | ||
555 | return ret; | ||
556 | } | ||
557 | |||
558 | /* check state of calendar information */ | ||
559 | ret = i2c_smbus_read_byte_data(client, HYM8563_SEC); | ||
560 | if (ret < 0) | ||
561 | return ret; | ||
562 | |||
563 | hym8563->valid = !(ret & HYM8563_SEC_VL); | ||
564 | dev_dbg(&client->dev, "rtc information is %s\n", | ||
565 | hym8563->valid ? "valid" : "invalid"); | ||
566 | |||
567 | hym8563->rtc = devm_rtc_device_register(&client->dev, client->name, | ||
568 | &hym8563_rtc_ops, THIS_MODULE); | ||
569 | if (IS_ERR(hym8563->rtc)) | ||
570 | return PTR_ERR(hym8563->rtc); | ||
571 | |||
572 | #ifdef CONFIG_COMMON_CLK | ||
573 | hym8563_clkout_register_clk(hym8563); | ||
574 | #endif | ||
575 | |||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | static const struct i2c_device_id hym8563_id[] = { | ||
580 | { "hym8563", 0 }, | ||
581 | {}, | ||
582 | }; | ||
583 | MODULE_DEVICE_TABLE(i2c, hym8563_id); | ||
584 | |||
585 | static struct of_device_id hym8563_dt_idtable[] = { | ||
586 | { .compatible = "haoyu,hym8563" }, | ||
587 | {}, | ||
588 | }; | ||
589 | MODULE_DEVICE_TABLE(of, hym8563_dt_idtable); | ||
590 | |||
591 | static struct i2c_driver hym8563_driver = { | ||
592 | .driver = { | ||
593 | .name = "rtc-hym8563", | ||
594 | .owner = THIS_MODULE, | ||
595 | .pm = &hym8563_pm_ops, | ||
596 | .of_match_table = hym8563_dt_idtable, | ||
597 | }, | ||
598 | .probe = hym8563_probe, | ||
599 | .id_table = hym8563_id, | ||
600 | }; | ||
601 | |||
602 | module_i2c_driver(hym8563_driver); | ||
603 | |||
604 | MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); | ||
605 | MODULE_DESCRIPTION("HYM8563 RTC driver"); | ||
606 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c new file mode 100644 index 000000000000..7854a656628f --- /dev/null +++ b/drivers/rtc/rtc-isl12057.c | |||
@@ -0,0 +1,310 @@ | |||
1 | /* | ||
2 | * rtc-isl12057 - Driver for Intersil ISL12057 I2C Real Time Clock | ||
3 | * | ||
4 | * Copyright (C) 2013, Arnaud EBALARD <arno@natisbad.org> | ||
5 | * | ||
6 | * This work is largely based on Intersil ISL1208 driver developed by | ||
7 | * Hebert Valerio Riedel <hvr@gnu.org>. | ||
8 | * | ||
9 | * Detailed datasheet on which this development is based is available here: | ||
10 | * | ||
11 | * http://natisbad.org/NAS2/refs/ISL12057.pdf | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/rtc.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/bcd.h> | ||
29 | #include <linux/rtc.h> | ||
30 | #include <linux/of.h> | ||
31 | #include <linux/of_device.h> | ||
32 | #include <linux/regmap.h> | ||
33 | |||
34 | #define DRV_NAME "rtc-isl12057" | ||
35 | |||
36 | /* RTC section */ | ||
37 | #define ISL12057_REG_RTC_SC 0x00 /* Seconds */ | ||
38 | #define ISL12057_REG_RTC_MN 0x01 /* Minutes */ | ||
39 | #define ISL12057_REG_RTC_HR 0x02 /* Hours */ | ||
40 | #define ISL12057_REG_RTC_HR_PM BIT(5) /* AM/PM bit in 12h format */ | ||
41 | #define ISL12057_REG_RTC_HR_MIL BIT(6) /* 24h/12h format */ | ||
42 | #define ISL12057_REG_RTC_DW 0x03 /* Day of the Week */ | ||
43 | #define ISL12057_REG_RTC_DT 0x04 /* Date */ | ||
44 | #define ISL12057_REG_RTC_MO 0x05 /* Month */ | ||
45 | #define ISL12057_REG_RTC_YR 0x06 /* Year */ | ||
46 | #define ISL12057_RTC_SEC_LEN 7 | ||
47 | |||
48 | /* Alarm 1 section */ | ||
49 | #define ISL12057_REG_A1_SC 0x07 /* Alarm 1 Seconds */ | ||
50 | #define ISL12057_REG_A1_MN 0x08 /* Alarm 1 Minutes */ | ||
51 | #define ISL12057_REG_A1_HR 0x09 /* Alarm 1 Hours */ | ||
52 | #define ISL12057_REG_A1_HR_PM BIT(5) /* AM/PM bit in 12h format */ | ||
53 | #define ISL12057_REG_A1_HR_MIL BIT(6) /* 24h/12h format */ | ||
54 | #define ISL12057_REG_A1_DWDT 0x0A /* Alarm 1 Date / Day of the week */ | ||
55 | #define ISL12057_REG_A1_DWDT_B BIT(6) /* DW / DT selection bit */ | ||
56 | #define ISL12057_A1_SEC_LEN 4 | ||
57 | |||
58 | /* Alarm 2 section */ | ||
59 | #define ISL12057_REG_A2_MN 0x0B /* Alarm 2 Minutes */ | ||
60 | #define ISL12057_REG_A2_HR 0x0C /* Alarm 2 Hours */ | ||
61 | #define ISL12057_REG_A2_DWDT 0x0D /* Alarm 2 Date / Day of the week */ | ||
62 | #define ISL12057_A2_SEC_LEN 3 | ||
63 | |||
64 | /* Control/Status registers */ | ||
65 | #define ISL12057_REG_INT 0x0E | ||
66 | #define ISL12057_REG_INT_A1IE BIT(0) /* Alarm 1 interrupt enable bit */ | ||
67 | #define ISL12057_REG_INT_A2IE BIT(1) /* Alarm 2 interrupt enable bit */ | ||
68 | #define ISL12057_REG_INT_INTCN BIT(2) /* Interrupt control enable bit */ | ||
69 | #define ISL12057_REG_INT_RS1 BIT(3) /* Freq out control bit 1 */ | ||
70 | #define ISL12057_REG_INT_RS2 BIT(4) /* Freq out control bit 2 */ | ||
71 | #define ISL12057_REG_INT_EOSC BIT(7) /* Oscillator enable bit */ | ||
72 | |||
73 | #define ISL12057_REG_SR 0x0F | ||
74 | #define ISL12057_REG_SR_A1F BIT(0) /* Alarm 1 interrupt bit */ | ||
75 | #define ISL12057_REG_SR_A2F BIT(1) /* Alarm 2 interrupt bit */ | ||
76 | #define ISL12057_REG_SR_OSF BIT(7) /* Oscillator failure bit */ | ||
77 | |||
78 | /* Register memory map length */ | ||
79 | #define ISL12057_MEM_MAP_LEN 0x10 | ||
80 | |||
81 | struct isl12057_rtc_data { | ||
82 | struct regmap *regmap; | ||
83 | struct mutex lock; | ||
84 | }; | ||
85 | |||
86 | static void isl12057_rtc_regs_to_tm(struct rtc_time *tm, u8 *regs) | ||
87 | { | ||
88 | tm->tm_sec = bcd2bin(regs[ISL12057_REG_RTC_SC]); | ||
89 | tm->tm_min = bcd2bin(regs[ISL12057_REG_RTC_MN]); | ||
90 | |||
91 | if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_MIL) { /* AM/PM */ | ||
92 | tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x0f); | ||
93 | if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_PM) | ||
94 | tm->tm_hour += 12; | ||
95 | } else { /* 24 hour mode */ | ||
96 | tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x3f); | ||
97 | } | ||
98 | |||
99 | tm->tm_mday = bcd2bin(regs[ISL12057_REG_RTC_DT]); | ||
100 | tm->tm_wday = bcd2bin(regs[ISL12057_REG_RTC_DW]) - 1; /* starts at 1 */ | ||
101 | tm->tm_mon = bcd2bin(regs[ISL12057_REG_RTC_MO]) - 1; /* starts at 1 */ | ||
102 | tm->tm_year = bcd2bin(regs[ISL12057_REG_RTC_YR]) + 100; | ||
103 | } | ||
104 | |||
105 | static int isl12057_rtc_tm_to_regs(u8 *regs, struct rtc_time *tm) | ||
106 | { | ||
107 | /* | ||
108 | * The clock has an 8 bit wide bcd-coded register for the year. | ||
109 | * tm_year is an offset from 1900 and we are interested in the | ||
110 | * 2000-2099 range, so any value less than 100 is invalid. | ||
111 | */ | ||
112 | if (tm->tm_year < 100) | ||
113 | return -EINVAL; | ||
114 | |||
115 | regs[ISL12057_REG_RTC_SC] = bin2bcd(tm->tm_sec); | ||
116 | regs[ISL12057_REG_RTC_MN] = bin2bcd(tm->tm_min); | ||
117 | regs[ISL12057_REG_RTC_HR] = bin2bcd(tm->tm_hour); /* 24-hour format */ | ||
118 | regs[ISL12057_REG_RTC_DT] = bin2bcd(tm->tm_mday); | ||
119 | regs[ISL12057_REG_RTC_MO] = bin2bcd(tm->tm_mon + 1); | ||
120 | regs[ISL12057_REG_RTC_YR] = bin2bcd(tm->tm_year - 100); | ||
121 | regs[ISL12057_REG_RTC_DW] = bin2bcd(tm->tm_wday + 1); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Try and match register bits w/ fixed null values to see whether we | ||
128 | * are dealing with an ISL12057. Note: this function is called early | ||
129 | * during init and hence does need mutex protection. | ||
130 | */ | ||
131 | static int isl12057_i2c_validate_chip(struct regmap *regmap) | ||
132 | { | ||
133 | u8 regs[ISL12057_MEM_MAP_LEN]; | ||
134 | static const u8 mask[ISL12057_MEM_MAP_LEN] = { 0x80, 0x80, 0x80, 0xf8, | ||
135 | 0xc0, 0x60, 0x00, 0x00, | ||
136 | 0x00, 0x00, 0x00, 0x00, | ||
137 | 0x00, 0x00, 0x60, 0x7c }; | ||
138 | int ret, i; | ||
139 | |||
140 | ret = regmap_bulk_read(regmap, 0, regs, ISL12057_MEM_MAP_LEN); | ||
141 | if (ret) | ||
142 | return ret; | ||
143 | |||
144 | for (i = 0; i < ISL12057_MEM_MAP_LEN; ++i) { | ||
145 | if (regs[i] & mask[i]) /* check if bits are cleared */ | ||
146 | return -ENODEV; | ||
147 | } | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int isl12057_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
153 | { | ||
154 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); | ||
155 | u8 regs[ISL12057_RTC_SEC_LEN]; | ||
156 | int ret; | ||
157 | |||
158 | mutex_lock(&data->lock); | ||
159 | ret = regmap_bulk_read(data->regmap, ISL12057_REG_RTC_SC, regs, | ||
160 | ISL12057_RTC_SEC_LEN); | ||
161 | mutex_unlock(&data->lock); | ||
162 | |||
163 | if (ret) { | ||
164 | dev_err(dev, "%s: RTC read failed\n", __func__); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | isl12057_rtc_regs_to_tm(tm, regs); | ||
169 | |||
170 | return rtc_valid_tm(tm); | ||
171 | } | ||
172 | |||
173 | static int isl12057_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
174 | { | ||
175 | struct isl12057_rtc_data *data = dev_get_drvdata(dev); | ||
176 | u8 regs[ISL12057_RTC_SEC_LEN]; | ||
177 | int ret; | ||
178 | |||
179 | ret = isl12057_rtc_tm_to_regs(regs, tm); | ||
180 | if (ret) | ||
181 | return ret; | ||
182 | |||
183 | mutex_lock(&data->lock); | ||
184 | ret = regmap_bulk_write(data->regmap, ISL12057_REG_RTC_SC, regs, | ||
185 | ISL12057_RTC_SEC_LEN); | ||
186 | mutex_unlock(&data->lock); | ||
187 | |||
188 | if (ret) | ||
189 | dev_err(dev, "%s: RTC write failed\n", __func__); | ||
190 | |||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * Check current RTC status and enable/disable what needs to be. Return 0 if | ||
196 | * everything went ok and a negative value upon error. Note: this function | ||
197 | * is called early during init and hence does need mutex protection. | ||
198 | */ | ||
199 | static int isl12057_check_rtc_status(struct device *dev, struct regmap *regmap) | ||
200 | { | ||
201 | int ret; | ||
202 | |||
203 | /* Enable oscillator if not already running */ | ||
204 | ret = regmap_update_bits(regmap, ISL12057_REG_INT, | ||
205 | ISL12057_REG_INT_EOSC, 0); | ||
206 | if (ret < 0) { | ||
207 | dev_err(dev, "Unable to enable oscillator\n"); | ||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | /* Clear oscillator failure bit if needed */ | ||
212 | ret = regmap_update_bits(regmap, ISL12057_REG_SR, | ||
213 | ISL12057_REG_SR_OSF, 0); | ||
214 | if (ret < 0) { | ||
215 | dev_err(dev, "Unable to clear oscillator failure bit\n"); | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | /* Clear alarm bit if needed */ | ||
220 | ret = regmap_update_bits(regmap, ISL12057_REG_SR, | ||
221 | ISL12057_REG_SR_A1F, 0); | ||
222 | if (ret < 0) { | ||
223 | dev_err(dev, "Unable to clear alarm bit\n"); | ||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static const struct rtc_class_ops rtc_ops = { | ||
231 | .read_time = isl12057_rtc_read_time, | ||
232 | .set_time = isl12057_rtc_set_time, | ||
233 | }; | ||
234 | |||
235 | static struct regmap_config isl12057_rtc_regmap_config = { | ||
236 | .reg_bits = 8, | ||
237 | .val_bits = 8, | ||
238 | }; | ||
239 | |||
240 | static int isl12057_probe(struct i2c_client *client, | ||
241 | const struct i2c_device_id *id) | ||
242 | { | ||
243 | struct device *dev = &client->dev; | ||
244 | struct isl12057_rtc_data *data; | ||
245 | struct rtc_device *rtc; | ||
246 | struct regmap *regmap; | ||
247 | int ret; | ||
248 | |||
249 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | | ||
250 | I2C_FUNC_SMBUS_BYTE_DATA | | ||
251 | I2C_FUNC_SMBUS_I2C_BLOCK)) | ||
252 | return -ENODEV; | ||
253 | |||
254 | regmap = devm_regmap_init_i2c(client, &isl12057_rtc_regmap_config); | ||
255 | if (IS_ERR(regmap)) { | ||
256 | ret = PTR_ERR(regmap); | ||
257 | dev_err(dev, "regmap allocation failed: %d\n", ret); | ||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | ret = isl12057_i2c_validate_chip(regmap); | ||
262 | if (ret) | ||
263 | return ret; | ||
264 | |||
265 | ret = isl12057_check_rtc_status(dev, regmap); | ||
266 | if (ret) | ||
267 | return ret; | ||
268 | |||
269 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); | ||
270 | if (!data) | ||
271 | return -ENOMEM; | ||
272 | |||
273 | mutex_init(&data->lock); | ||
274 | data->regmap = regmap; | ||
275 | dev_set_drvdata(dev, data); | ||
276 | |||
277 | rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops, THIS_MODULE); | ||
278 | if (IS_ERR(rtc)) | ||
279 | return PTR_ERR(rtc); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | #ifdef CONFIG_OF | ||
285 | static struct of_device_id isl12057_dt_match[] = { | ||
286 | { .compatible = "isl,isl12057" }, | ||
287 | { }, | ||
288 | }; | ||
289 | #endif | ||
290 | |||
291 | static const struct i2c_device_id isl12057_id[] = { | ||
292 | { "isl12057", 0 }, | ||
293 | { } | ||
294 | }; | ||
295 | MODULE_DEVICE_TABLE(i2c, isl12057_id); | ||
296 | |||
297 | static struct i2c_driver isl12057_driver = { | ||
298 | .driver = { | ||
299 | .name = DRV_NAME, | ||
300 | .owner = THIS_MODULE, | ||
301 | .of_match_table = of_match_ptr(isl12057_dt_match), | ||
302 | }, | ||
303 | .probe = isl12057_probe, | ||
304 | .id_table = isl12057_id, | ||
305 | }; | ||
306 | module_i2c_driver(isl12057_driver); | ||
307 | |||
308 | MODULE_AUTHOR("Arnaud EBALARD <arno@natisbad.org>"); | ||
309 | MODULE_DESCRIPTION("Intersil ISL12057 RTC driver"); | ||
310 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-max8907.c b/drivers/rtc/rtc-max8907.c index 8e45b3c4aa2f..3032178bd9e6 100644 --- a/drivers/rtc/rtc-max8907.c +++ b/drivers/rtc/rtc-max8907.c | |||
@@ -51,7 +51,7 @@ static irqreturn_t max8907_irq_handler(int irq, void *data) | |||
51 | { | 51 | { |
52 | struct max8907_rtc *rtc = data; | 52 | struct max8907_rtc *rtc = data; |
53 | 53 | ||
54 | regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x7f, 0); | 54 | regmap_write(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0); |
55 | 55 | ||
56 | rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); | 56 | rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); |
57 | 57 | ||
@@ -64,7 +64,7 @@ static void regs_to_tm(u8 *regs, struct rtc_time *tm) | |||
64 | bcd2bin(regs[RTC_YEAR1]) - 1900; | 64 | bcd2bin(regs[RTC_YEAR1]) - 1900; |
65 | tm->tm_mon = bcd2bin(regs[RTC_MONTH] & 0x1f) - 1; | 65 | tm->tm_mon = bcd2bin(regs[RTC_MONTH] & 0x1f) - 1; |
66 | tm->tm_mday = bcd2bin(regs[RTC_DATE] & 0x3f); | 66 | tm->tm_mday = bcd2bin(regs[RTC_DATE] & 0x3f); |
67 | tm->tm_wday = (regs[RTC_WEEKDAY] & 0x07) - 1; | 67 | tm->tm_wday = (regs[RTC_WEEKDAY] & 0x07); |
68 | if (regs[RTC_HOUR] & HOUR_12) { | 68 | if (regs[RTC_HOUR] & HOUR_12) { |
69 | tm->tm_hour = bcd2bin(regs[RTC_HOUR] & 0x01f); | 69 | tm->tm_hour = bcd2bin(regs[RTC_HOUR] & 0x01f); |
70 | if (tm->tm_hour == 12) | 70 | if (tm->tm_hour == 12) |
@@ -88,7 +88,7 @@ static void tm_to_regs(struct rtc_time *tm, u8 *regs) | |||
88 | regs[RTC_YEAR1] = bin2bcd(low); | 88 | regs[RTC_YEAR1] = bin2bcd(low); |
89 | regs[RTC_MONTH] = bin2bcd(tm->tm_mon + 1); | 89 | regs[RTC_MONTH] = bin2bcd(tm->tm_mon + 1); |
90 | regs[RTC_DATE] = bin2bcd(tm->tm_mday); | 90 | regs[RTC_DATE] = bin2bcd(tm->tm_mday); |
91 | regs[RTC_WEEKDAY] = tm->tm_wday + 1; | 91 | regs[RTC_WEEKDAY] = tm->tm_wday; |
92 | regs[RTC_HOUR] = bin2bcd(tm->tm_hour); | 92 | regs[RTC_HOUR] = bin2bcd(tm->tm_hour); |
93 | regs[RTC_MIN] = bin2bcd(tm->tm_min); | 93 | regs[RTC_MIN] = bin2bcd(tm->tm_min); |
94 | regs[RTC_SEC] = bin2bcd(tm->tm_sec); | 94 | regs[RTC_SEC] = bin2bcd(tm->tm_sec); |
@@ -153,7 +153,7 @@ static int max8907_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
153 | tm_to_regs(&alrm->time, regs); | 153 | tm_to_regs(&alrm->time, regs); |
154 | 154 | ||
155 | /* Disable alarm while we update the target time */ | 155 | /* Disable alarm while we update the target time */ |
156 | ret = regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x7f, 0); | 156 | ret = regmap_write(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0); |
157 | if (ret < 0) | 157 | if (ret < 0) |
158 | return ret; | 158 | return ret; |
159 | 159 | ||
@@ -163,8 +163,7 @@ static int max8907_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
163 | return ret; | 163 | return ret; |
164 | 164 | ||
165 | if (alrm->enabled) | 165 | if (alrm->enabled) |
166 | ret = regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, | 166 | ret = regmap_write(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x77); |
167 | 0x7f, 0x7f); | ||
168 | 167 | ||
169 | return ret; | 168 | return ret; |
170 | } | 169 | } |
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 50c572645546..419874fefa4b 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
@@ -391,11 +391,13 @@ static int mxc_rtc_probe(struct platform_device *pdev) | |||
391 | pdata->clk = devm_clk_get(&pdev->dev, NULL); | 391 | pdata->clk = devm_clk_get(&pdev->dev, NULL); |
392 | if (IS_ERR(pdata->clk)) { | 392 | if (IS_ERR(pdata->clk)) { |
393 | dev_err(&pdev->dev, "unable to get clock!\n"); | 393 | dev_err(&pdev->dev, "unable to get clock!\n"); |
394 | ret = PTR_ERR(pdata->clk); | 394 | return PTR_ERR(pdata->clk); |
395 | goto exit_free_pdata; | ||
396 | } | 395 | } |
397 | 396 | ||
398 | clk_prepare_enable(pdata->clk); | 397 | ret = clk_prepare_enable(pdata->clk); |
398 | if (ret) | ||
399 | return ret; | ||
400 | |||
399 | rate = clk_get_rate(pdata->clk); | 401 | rate = clk_get_rate(pdata->clk); |
400 | 402 | ||
401 | if (rate == 32768) | 403 | if (rate == 32768) |
@@ -447,8 +449,6 @@ static int mxc_rtc_probe(struct platform_device *pdev) | |||
447 | exit_put_clk: | 449 | exit_put_clk: |
448 | clk_disable_unprepare(pdata->clk); | 450 | clk_disable_unprepare(pdata->clk); |
449 | 451 | ||
450 | exit_free_pdata: | ||
451 | |||
452 | return ret; | 452 | return ret; |
453 | } | 453 | } |
454 | 454 | ||
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 1ee514a3972c..9bd842e97749 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c | |||
@@ -197,10 +197,7 @@ static int pcf2127_probe(struct i2c_client *client, | |||
197 | pcf2127_driver.driver.name, | 197 | pcf2127_driver.driver.name, |
198 | &pcf2127_rtc_ops, THIS_MODULE); | 198 | &pcf2127_rtc_ops, THIS_MODULE); |
199 | 199 | ||
200 | if (IS_ERR(pcf2127->rtc)) | 200 | return PTR_ERR_OR_ZERO(pcf2127->rtc); |
201 | return PTR_ERR(pcf2127->rtc); | ||
202 | |||
203 | return 0; | ||
204 | } | 201 | } |
205 | 202 | ||
206 | static const struct i2c_device_id pcf2127_id[] = { | 203 | static const struct i2c_device_id pcf2127_id[] = { |
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c index 00b0eb7fe166..de8d9c427782 100644 --- a/drivers/rtc/rtc-rx8581.c +++ b/drivers/rtc/rtc-rx8581.c | |||
@@ -52,8 +52,45 @@ | |||
52 | #define RX8581_CTRL_STOP 0x02 /* STOP bit */ | 52 | #define RX8581_CTRL_STOP 0x02 /* STOP bit */ |
53 | #define RX8581_CTRL_RESET 0x01 /* RESET bit */ | 53 | #define RX8581_CTRL_RESET 0x01 /* RESET bit */ |
54 | 54 | ||
55 | struct rx8581 { | ||
56 | struct i2c_client *client; | ||
57 | struct rtc_device *rtc; | ||
58 | s32 (*read_block_data)(const struct i2c_client *client, u8 command, | ||
59 | u8 length, u8 *values); | ||
60 | s32 (*write_block_data)(const struct i2c_client *client, u8 command, | ||
61 | u8 length, const u8 *values); | ||
62 | }; | ||
63 | |||
55 | static struct i2c_driver rx8581_driver; | 64 | static struct i2c_driver rx8581_driver; |
56 | 65 | ||
66 | static int rx8581_read_block_data(const struct i2c_client *client, u8 command, | ||
67 | u8 length, u8 *values) | ||
68 | { | ||
69 | s32 i, data; | ||
70 | |||
71 | for (i = 0; i < length; i++) { | ||
72 | data = i2c_smbus_read_byte_data(client, command + i); | ||
73 | if (data < 0) | ||
74 | return data; | ||
75 | values[i] = data; | ||
76 | } | ||
77 | return i; | ||
78 | } | ||
79 | |||
80 | static int rx8581_write_block_data(const struct i2c_client *client, u8 command, | ||
81 | u8 length, const u8 *values) | ||
82 | { | ||
83 | s32 i, ret; | ||
84 | |||
85 | for (i = 0; i < length; i++) { | ||
86 | ret = i2c_smbus_write_byte_data(client, command + i, | ||
87 | values[i]); | ||
88 | if (ret < 0) | ||
89 | return ret; | ||
90 | } | ||
91 | return length; | ||
92 | } | ||
93 | |||
57 | /* | 94 | /* |
58 | * In the routines that deal directly with the rx8581 hardware, we use | 95 | * In the routines that deal directly with the rx8581 hardware, we use |
59 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | 96 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. |
@@ -62,6 +99,7 @@ static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
62 | { | 99 | { |
63 | unsigned char date[7]; | 100 | unsigned char date[7]; |
64 | int data, err; | 101 | int data, err; |
102 | struct rx8581 *rx8581 = i2c_get_clientdata(client); | ||
65 | 103 | ||
66 | /* First we ensure that the "update flag" is not set, we read the | 104 | /* First we ensure that the "update flag" is not set, we read the |
67 | * time and date then re-read the "update flag". If the update flag | 105 | * time and date then re-read the "update flag". If the update flag |
@@ -80,14 +118,13 @@ static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
80 | err = i2c_smbus_write_byte_data(client, | 118 | err = i2c_smbus_write_byte_data(client, |
81 | RX8581_REG_FLAG, (data & ~RX8581_FLAG_UF)); | 119 | RX8581_REG_FLAG, (data & ~RX8581_FLAG_UF)); |
82 | if (err != 0) { | 120 | if (err != 0) { |
83 | dev_err(&client->dev, "Unable to write device " | 121 | dev_err(&client->dev, "Unable to write device flags\n"); |
84 | "flags\n"); | ||
85 | return -EIO; | 122 | return -EIO; |
86 | } | 123 | } |
87 | } | 124 | } |
88 | 125 | ||
89 | /* Now read time and date */ | 126 | /* Now read time and date */ |
90 | err = i2c_smbus_read_i2c_block_data(client, RX8581_REG_SC, | 127 | err = rx8581->read_block_data(client, RX8581_REG_SC, |
91 | 7, date); | 128 | 7, date); |
92 | if (err < 0) { | 129 | if (err < 0) { |
93 | dev_err(&client->dev, "Unable to read date\n"); | 130 | dev_err(&client->dev, "Unable to read date\n"); |
@@ -140,6 +177,7 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
140 | { | 177 | { |
141 | int data, err; | 178 | int data, err; |
142 | unsigned char buf[7]; | 179 | unsigned char buf[7]; |
180 | struct rx8581 *rx8581 = i2c_get_clientdata(client); | ||
143 | 181 | ||
144 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | 182 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " |
145 | "mday=%d, mon=%d, year=%d, wday=%d\n", | 183 | "mday=%d, mon=%d, year=%d, wday=%d\n", |
@@ -176,7 +214,7 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
176 | } | 214 | } |
177 | 215 | ||
178 | /* write register's data */ | 216 | /* write register's data */ |
179 | err = i2c_smbus_write_i2c_block_data(client, RX8581_REG_SC, 7, buf); | 217 | err = rx8581->write_block_data(client, RX8581_REG_SC, 7, buf); |
180 | if (err < 0) { | 218 | if (err < 0) { |
181 | dev_err(&client->dev, "Unable to write to date registers\n"); | 219 | dev_err(&client->dev, "Unable to write to date registers\n"); |
182 | return -EIO; | 220 | return -EIO; |
@@ -231,22 +269,39 @@ static const struct rtc_class_ops rx8581_rtc_ops = { | |||
231 | static int rx8581_probe(struct i2c_client *client, | 269 | static int rx8581_probe(struct i2c_client *client, |
232 | const struct i2c_device_id *id) | 270 | const struct i2c_device_id *id) |
233 | { | 271 | { |
234 | struct rtc_device *rtc; | 272 | struct rx8581 *rx8581; |
235 | 273 | ||
236 | dev_dbg(&client->dev, "%s\n", __func__); | 274 | dev_dbg(&client->dev, "%s\n", __func__); |
237 | 275 | ||
238 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | 276 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA) |
239 | return -ENODEV; | 277 | && !i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) |
278 | return -EIO; | ||
240 | 279 | ||
241 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 280 | rx8581 = devm_kzalloc(&client->dev, sizeof(struct rx8581), GFP_KERNEL); |
281 | if (!rx8581) | ||
282 | return -ENOMEM; | ||
242 | 283 | ||
243 | rtc = devm_rtc_device_register(&client->dev, rx8581_driver.driver.name, | 284 | i2c_set_clientdata(client, rx8581); |
244 | &rx8581_rtc_ops, THIS_MODULE); | 285 | rx8581->client = client; |
245 | 286 | ||
246 | if (IS_ERR(rtc)) | 287 | if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { |
247 | return PTR_ERR(rtc); | 288 | rx8581->read_block_data = i2c_smbus_read_i2c_block_data; |
289 | rx8581->write_block_data = i2c_smbus_write_i2c_block_data; | ||
290 | } else { | ||
291 | rx8581->read_block_data = rx8581_read_block_data; | ||
292 | rx8581->write_block_data = rx8581_write_block_data; | ||
293 | } | ||
248 | 294 | ||
249 | i2c_set_clientdata(client, rtc); | 295 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
296 | |||
297 | rx8581->rtc = devm_rtc_device_register(&client->dev, | ||
298 | rx8581_driver.driver.name, &rx8581_rtc_ops, THIS_MODULE); | ||
299 | |||
300 | if (IS_ERR(rx8581->rtc)) { | ||
301 | dev_err(&client->dev, | ||
302 | "unable to register the class device\n"); | ||
303 | return PTR_ERR(rx8581->rtc); | ||
304 | } | ||
250 | 305 | ||
251 | return 0; | 306 | return 0; |
252 | } | 307 | } |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 7afd373b9595..c4cde9c08f1f 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -580,10 +580,12 @@ static int s3c_rtc_suspend(struct device *dev) | |||
580 | 580 | ||
581 | clk_enable(rtc_clk); | 581 | clk_enable(rtc_clk); |
582 | /* save TICNT for anyone using periodic interrupts */ | 582 | /* save TICNT for anyone using periodic interrupts */ |
583 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | ||
584 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 583 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
585 | ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON); | 584 | ticnt_en_save = readw(s3c_rtc_base + S3C2410_RTCCON); |
586 | ticnt_en_save &= S3C64XX_RTCCON_TICEN; | 585 | ticnt_en_save &= S3C64XX_RTCCON_TICEN; |
586 | ticnt_save = readl(s3c_rtc_base + S3C2410_TICNT); | ||
587 | } else { | ||
588 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | ||
587 | } | 589 | } |
588 | s3c_rtc_enable(pdev, 0); | 590 | s3c_rtc_enable(pdev, 0); |
589 | 591 | ||
@@ -605,10 +607,15 @@ static int s3c_rtc_resume(struct device *dev) | |||
605 | 607 | ||
606 | clk_enable(rtc_clk); | 608 | clk_enable(rtc_clk); |
607 | s3c_rtc_enable(pdev, 1); | 609 | s3c_rtc_enable(pdev, 1); |
608 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | 610 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
609 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { | 611 | writel(ticnt_save, s3c_rtc_base + S3C2410_TICNT); |
610 | tmp = readw(s3c_rtc_base + S3C2410_RTCCON); | 612 | if (ticnt_en_save) { |
611 | writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); | 613 | tmp = readw(s3c_rtc_base + S3C2410_RTCCON); |
614 | writew(tmp | ticnt_en_save, | ||
615 | s3c_rtc_base + S3C2410_RTCCON); | ||
616 | } | ||
617 | } else { | ||
618 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | ||
612 | } | 619 | } |
613 | 620 | ||
614 | if (device_may_wakeup(dev) && wake_en) { | 621 | if (device_may_wakeup(dev) && wake_en) { |
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index ae8119dc2846..476af93543f6 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c | |||
@@ -639,6 +639,7 @@ static void s5m_rtc_shutdown(struct platform_device *pdev) | |||
639 | s5m_rtc_enable_smpl(info, false); | 639 | s5m_rtc_enable_smpl(info, false); |
640 | } | 640 | } |
641 | 641 | ||
642 | #ifdef CONFIG_PM_SLEEP | ||
642 | static int s5m_rtc_resume(struct device *dev) | 643 | static int s5m_rtc_resume(struct device *dev) |
643 | { | 644 | { |
644 | struct s5m_rtc_info *info = dev_get_drvdata(dev); | 645 | struct s5m_rtc_info *info = dev_get_drvdata(dev); |
@@ -660,6 +661,7 @@ static int s5m_rtc_suspend(struct device *dev) | |||
660 | 661 | ||
661 | return ret; | 662 | return ret; |
662 | } | 663 | } |
664 | #endif /* CONFIG_PM_SLEEP */ | ||
663 | 665 | ||
664 | static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume); | 666 | static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume); |
665 | 667 | ||
diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c new file mode 100644 index 000000000000..68a35284e5ad --- /dev/null +++ b/drivers/rtc/rtc-sunxi.c | |||
@@ -0,0 +1,523 @@ | |||
1 | /* | ||
2 | * An RTC driver for Allwinner A10/A20 | ||
3 | * | ||
4 | * Copyright (c) 2013, Carlo Caione <carlo.caione@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/delay.h> | ||
22 | #include <linux/err.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/of.h> | ||
30 | #include <linux/of_address.h> | ||
31 | #include <linux/of_device.h> | ||
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/rtc.h> | ||
34 | #include <linux/types.h> | ||
35 | |||
36 | #define SUNXI_LOSC_CTRL 0x0000 | ||
37 | #define SUNXI_LOSC_CTRL_RTC_HMS_ACC BIT(8) | ||
38 | #define SUNXI_LOSC_CTRL_RTC_YMD_ACC BIT(7) | ||
39 | |||
40 | #define SUNXI_RTC_YMD 0x0004 | ||
41 | |||
42 | #define SUNXI_RTC_HMS 0x0008 | ||
43 | |||
44 | #define SUNXI_ALRM_DHMS 0x000c | ||
45 | |||
46 | #define SUNXI_ALRM_EN 0x0014 | ||
47 | #define SUNXI_ALRM_EN_CNT_EN BIT(8) | ||
48 | |||
49 | #define SUNXI_ALRM_IRQ_EN 0x0018 | ||
50 | #define SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN BIT(0) | ||
51 | |||
52 | #define SUNXI_ALRM_IRQ_STA 0x001c | ||
53 | #define SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND BIT(0) | ||
54 | |||
55 | #define SUNXI_MASK_DH 0x0000001f | ||
56 | #define SUNXI_MASK_SM 0x0000003f | ||
57 | #define SUNXI_MASK_M 0x0000000f | ||
58 | #define SUNXI_MASK_LY 0x00000001 | ||
59 | #define SUNXI_MASK_D 0x00000ffe | ||
60 | #define SUNXI_MASK_M 0x0000000f | ||
61 | |||
62 | #define SUNXI_GET(x, mask, shift) (((x) & ((mask) << (shift))) \ | ||
63 | >> (shift)) | ||
64 | |||
65 | #define SUNXI_SET(x, mask, shift) (((x) & (mask)) << (shift)) | ||
66 | |||
67 | /* | ||
68 | * Get date values | ||
69 | */ | ||
70 | #define SUNXI_DATE_GET_DAY_VALUE(x) SUNXI_GET(x, SUNXI_MASK_DH, 0) | ||
71 | #define SUNXI_DATE_GET_MON_VALUE(x) SUNXI_GET(x, SUNXI_MASK_M, 8) | ||
72 | #define SUNXI_DATE_GET_YEAR_VALUE(x, mask) SUNXI_GET(x, mask, 16) | ||
73 | |||
74 | /* | ||
75 | * Get time values | ||
76 | */ | ||
77 | #define SUNXI_TIME_GET_SEC_VALUE(x) SUNXI_GET(x, SUNXI_MASK_SM, 0) | ||
78 | #define SUNXI_TIME_GET_MIN_VALUE(x) SUNXI_GET(x, SUNXI_MASK_SM, 8) | ||
79 | #define SUNXI_TIME_GET_HOUR_VALUE(x) SUNXI_GET(x, SUNXI_MASK_DH, 16) | ||
80 | |||
81 | /* | ||
82 | * Get alarm values | ||
83 | */ | ||
84 | #define SUNXI_ALRM_GET_SEC_VALUE(x) SUNXI_GET(x, SUNXI_MASK_SM, 0) | ||
85 | #define SUNXI_ALRM_GET_MIN_VALUE(x) SUNXI_GET(x, SUNXI_MASK_SM, 8) | ||
86 | #define SUNXI_ALRM_GET_HOUR_VALUE(x) SUNXI_GET(x, SUNXI_MASK_DH, 16) | ||
87 | |||
88 | /* | ||
89 | * Set date values | ||
90 | */ | ||
91 | #define SUNXI_DATE_SET_DAY_VALUE(x) SUNXI_DATE_GET_DAY_VALUE(x) | ||
92 | #define SUNXI_DATE_SET_MON_VALUE(x) SUNXI_SET(x, SUNXI_MASK_M, 8) | ||
93 | #define SUNXI_DATE_SET_YEAR_VALUE(x, mask) SUNXI_SET(x, mask, 16) | ||
94 | #define SUNXI_LEAP_SET_VALUE(x, shift) SUNXI_SET(x, SUNXI_MASK_LY, shift) | ||
95 | |||
96 | /* | ||
97 | * Set time values | ||
98 | */ | ||
99 | #define SUNXI_TIME_SET_SEC_VALUE(x) SUNXI_TIME_GET_SEC_VALUE(x) | ||
100 | #define SUNXI_TIME_SET_MIN_VALUE(x) SUNXI_SET(x, SUNXI_MASK_SM, 8) | ||
101 | #define SUNXI_TIME_SET_HOUR_VALUE(x) SUNXI_SET(x, SUNXI_MASK_DH, 16) | ||
102 | |||
103 | /* | ||
104 | * Set alarm values | ||
105 | */ | ||
106 | #define SUNXI_ALRM_SET_SEC_VALUE(x) SUNXI_ALRM_GET_SEC_VALUE(x) | ||
107 | #define SUNXI_ALRM_SET_MIN_VALUE(x) SUNXI_SET(x, SUNXI_MASK_SM, 8) | ||
108 | #define SUNXI_ALRM_SET_HOUR_VALUE(x) SUNXI_SET(x, SUNXI_MASK_DH, 16) | ||
109 | #define SUNXI_ALRM_SET_DAY_VALUE(x) SUNXI_SET(x, SUNXI_MASK_D, 21) | ||
110 | |||
111 | /* | ||
112 | * Time unit conversions | ||
113 | */ | ||
114 | #define SEC_IN_MIN 60 | ||
115 | #define SEC_IN_HOUR (60 * SEC_IN_MIN) | ||
116 | #define SEC_IN_DAY (24 * SEC_IN_HOUR) | ||
117 | |||
118 | /* | ||
119 | * The year parameter passed to the driver is usually an offset relative to | ||
120 | * the year 1900. This macro is used to convert this offset to another one | ||
121 | * relative to the minimum year allowed by the hardware. | ||
122 | */ | ||
123 | #define SUNXI_YEAR_OFF(x) ((x)->min - 1900) | ||
124 | |||
125 | /* | ||
126 | * min and max year are arbitrary set considering the limited range of the | ||
127 | * hardware register field | ||
128 | */ | ||
129 | struct sunxi_rtc_data_year { | ||
130 | unsigned int min; /* min year allowed */ | ||
131 | unsigned int max; /* max year allowed */ | ||
132 | unsigned int mask; /* mask for the year field */ | ||
133 | unsigned char leap_shift; /* bit shift to get the leap year */ | ||
134 | }; | ||
135 | |||
136 | static struct sunxi_rtc_data_year data_year_param[] = { | ||
137 | [0] = { | ||
138 | .min = 2010, | ||
139 | .max = 2073, | ||
140 | .mask = 0x3f, | ||
141 | .leap_shift = 22, | ||
142 | }, | ||
143 | [1] = { | ||
144 | .min = 1970, | ||
145 | .max = 2225, | ||
146 | .mask = 0xff, | ||
147 | .leap_shift = 24, | ||
148 | }, | ||
149 | }; | ||
150 | |||
151 | struct sunxi_rtc_dev { | ||
152 | struct rtc_device *rtc; | ||
153 | struct device *dev; | ||
154 | struct sunxi_rtc_data_year *data_year; | ||
155 | void __iomem *base; | ||
156 | int irq; | ||
157 | }; | ||
158 | |||
159 | static irqreturn_t sunxi_rtc_alarmirq(int irq, void *id) | ||
160 | { | ||
161 | struct sunxi_rtc_dev *chip = (struct sunxi_rtc_dev *) id; | ||
162 | u32 val; | ||
163 | |||
164 | val = readl(chip->base + SUNXI_ALRM_IRQ_STA); | ||
165 | |||
166 | if (val & SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND) { | ||
167 | val |= SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND; | ||
168 | writel(val, chip->base + SUNXI_ALRM_IRQ_STA); | ||
169 | |||
170 | rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); | ||
171 | |||
172 | return IRQ_HANDLED; | ||
173 | } | ||
174 | |||
175 | return IRQ_NONE; | ||
176 | } | ||
177 | |||
178 | static void sunxi_rtc_setaie(int to, struct sunxi_rtc_dev *chip) | ||
179 | { | ||
180 | u32 alrm_val = 0; | ||
181 | u32 alrm_irq_val = 0; | ||
182 | |||
183 | if (to) { | ||
184 | alrm_val = readl(chip->base + SUNXI_ALRM_EN); | ||
185 | alrm_val |= SUNXI_ALRM_EN_CNT_EN; | ||
186 | |||
187 | alrm_irq_val = readl(chip->base + SUNXI_ALRM_IRQ_EN); | ||
188 | alrm_irq_val |= SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN; | ||
189 | } else { | ||
190 | writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND, | ||
191 | chip->base + SUNXI_ALRM_IRQ_STA); | ||
192 | } | ||
193 | |||
194 | writel(alrm_val, chip->base + SUNXI_ALRM_EN); | ||
195 | writel(alrm_irq_val, chip->base + SUNXI_ALRM_IRQ_EN); | ||
196 | } | ||
197 | |||
198 | static int sunxi_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) | ||
199 | { | ||
200 | struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); | ||
201 | struct rtc_time *alrm_tm = &wkalrm->time; | ||
202 | u32 alrm; | ||
203 | u32 alrm_en; | ||
204 | u32 date; | ||
205 | |||
206 | alrm = readl(chip->base + SUNXI_ALRM_DHMS); | ||
207 | date = readl(chip->base + SUNXI_RTC_YMD); | ||
208 | |||
209 | alrm_tm->tm_sec = SUNXI_ALRM_GET_SEC_VALUE(alrm); | ||
210 | alrm_tm->tm_min = SUNXI_ALRM_GET_MIN_VALUE(alrm); | ||
211 | alrm_tm->tm_hour = SUNXI_ALRM_GET_HOUR_VALUE(alrm); | ||
212 | |||
213 | alrm_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date); | ||
214 | alrm_tm->tm_mon = SUNXI_DATE_GET_MON_VALUE(date); | ||
215 | alrm_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date, | ||
216 | chip->data_year->mask); | ||
217 | |||
218 | alrm_tm->tm_mon -= 1; | ||
219 | |||
220 | /* | ||
221 | * switch from (data_year->min)-relative offset to | ||
222 | * a (1900)-relative one | ||
223 | */ | ||
224 | alrm_tm->tm_year += SUNXI_YEAR_OFF(chip->data_year); | ||
225 | |||
226 | alrm_en = readl(chip->base + SUNXI_ALRM_IRQ_EN); | ||
227 | if (alrm_en & SUNXI_ALRM_EN_CNT_EN) | ||
228 | wkalrm->enabled = 1; | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int sunxi_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | ||
234 | { | ||
235 | struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); | ||
236 | u32 date, time; | ||
237 | |||
238 | /* | ||
239 | * read again in case it changes | ||
240 | */ | ||
241 | do { | ||
242 | date = readl(chip->base + SUNXI_RTC_YMD); | ||
243 | time = readl(chip->base + SUNXI_RTC_HMS); | ||
244 | } while ((date != readl(chip->base + SUNXI_RTC_YMD)) || | ||
245 | (time != readl(chip->base + SUNXI_RTC_HMS))); | ||
246 | |||
247 | rtc_tm->tm_sec = SUNXI_TIME_GET_SEC_VALUE(time); | ||
248 | rtc_tm->tm_min = SUNXI_TIME_GET_MIN_VALUE(time); | ||
249 | rtc_tm->tm_hour = SUNXI_TIME_GET_HOUR_VALUE(time); | ||
250 | |||
251 | rtc_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date); | ||
252 | rtc_tm->tm_mon = SUNXI_DATE_GET_MON_VALUE(date); | ||
253 | rtc_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date, | ||
254 | chip->data_year->mask); | ||
255 | |||
256 | rtc_tm->tm_mon -= 1; | ||
257 | |||
258 | /* | ||
259 | * switch from (data_year->min)-relative offset to | ||
260 | * a (1900)-relative one | ||
261 | */ | ||
262 | rtc_tm->tm_year += SUNXI_YEAR_OFF(chip->data_year); | ||
263 | |||
264 | return rtc_valid_tm(rtc_tm); | ||
265 | } | ||
266 | |||
267 | static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm) | ||
268 | { | ||
269 | struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); | ||
270 | struct rtc_time *alrm_tm = &wkalrm->time; | ||
271 | struct rtc_time tm_now; | ||
272 | u32 alrm = 0; | ||
273 | unsigned long time_now = 0; | ||
274 | unsigned long time_set = 0; | ||
275 | unsigned long time_gap = 0; | ||
276 | unsigned long time_gap_day = 0; | ||
277 | unsigned long time_gap_hour = 0; | ||
278 | unsigned long time_gap_min = 0; | ||
279 | int ret = 0; | ||
280 | |||
281 | ret = sunxi_rtc_gettime(dev, &tm_now); | ||
282 | if (ret < 0) { | ||
283 | dev_err(dev, "Error in getting time\n"); | ||
284 | return -EINVAL; | ||
285 | } | ||
286 | |||
287 | rtc_tm_to_time(alrm_tm, &time_set); | ||
288 | rtc_tm_to_time(&tm_now, &time_now); | ||
289 | if (time_set <= time_now) { | ||
290 | dev_err(dev, "Date to set in the past\n"); | ||
291 | return -EINVAL; | ||
292 | } | ||
293 | |||
294 | time_gap = time_set - time_now; | ||
295 | time_gap_day = time_gap / SEC_IN_DAY; | ||
296 | time_gap -= time_gap_day * SEC_IN_DAY; | ||
297 | time_gap_hour = time_gap / SEC_IN_HOUR; | ||
298 | time_gap -= time_gap_hour * SEC_IN_HOUR; | ||
299 | time_gap_min = time_gap / SEC_IN_MIN; | ||
300 | time_gap -= time_gap_min * SEC_IN_MIN; | ||
301 | |||
302 | if (time_gap_day > 255) { | ||
303 | dev_err(dev, "Day must be in the range 0 - 255\n"); | ||
304 | return -EINVAL; | ||
305 | } | ||
306 | |||
307 | sunxi_rtc_setaie(0, chip); | ||
308 | writel(0, chip->base + SUNXI_ALRM_DHMS); | ||
309 | usleep_range(100, 300); | ||
310 | |||
311 | alrm = SUNXI_ALRM_SET_SEC_VALUE(time_gap) | | ||
312 | SUNXI_ALRM_SET_MIN_VALUE(time_gap_min) | | ||
313 | SUNXI_ALRM_SET_HOUR_VALUE(time_gap_hour) | | ||
314 | SUNXI_ALRM_SET_DAY_VALUE(time_gap_day); | ||
315 | writel(alrm, chip->base + SUNXI_ALRM_DHMS); | ||
316 | |||
317 | writel(0, chip->base + SUNXI_ALRM_IRQ_EN); | ||
318 | writel(SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN, chip->base + SUNXI_ALRM_IRQ_EN); | ||
319 | |||
320 | sunxi_rtc_setaie(wkalrm->enabled, chip); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int sunxi_rtc_wait(struct sunxi_rtc_dev *chip, int offset, | ||
326 | unsigned int mask, unsigned int ms_timeout) | ||
327 | { | ||
328 | const unsigned long timeout = jiffies + msecs_to_jiffies(ms_timeout); | ||
329 | u32 reg; | ||
330 | |||
331 | do { | ||
332 | reg = readl(chip->base + offset); | ||
333 | reg &= mask; | ||
334 | |||
335 | if (reg == mask) | ||
336 | return 0; | ||
337 | |||
338 | } while (time_before(jiffies, timeout)); | ||
339 | |||
340 | return -ETIMEDOUT; | ||
341 | } | ||
342 | |||
343 | static int sunxi_rtc_settime(struct device *dev, struct rtc_time *rtc_tm) | ||
344 | { | ||
345 | struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); | ||
346 | u32 date = 0; | ||
347 | u32 time = 0; | ||
348 | int year; | ||
349 | |||
350 | /* | ||
351 | * the input rtc_tm->tm_year is the offset relative to 1900. We use | ||
352 | * the SUNXI_YEAR_OFF macro to rebase it with respect to the min year | ||
353 | * allowed by the hardware | ||
354 | */ | ||
355 | |||
356 | year = rtc_tm->tm_year + 1900; | ||
357 | if (year < chip->data_year->min || year > chip->data_year->max) { | ||
358 | dev_err(dev, "rtc only supports year in range %d - %d\n", | ||
359 | chip->data_year->min, chip->data_year->max); | ||
360 | return -EINVAL; | ||
361 | } | ||
362 | |||
363 | rtc_tm->tm_year -= SUNXI_YEAR_OFF(chip->data_year); | ||
364 | rtc_tm->tm_mon += 1; | ||
365 | |||
366 | date = SUNXI_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | | ||
367 | SUNXI_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | | ||
368 | SUNXI_DATE_SET_YEAR_VALUE(rtc_tm->tm_year, | ||
369 | chip->data_year->mask); | ||
370 | |||
371 | if (is_leap_year(year)) | ||
372 | date |= SUNXI_LEAP_SET_VALUE(1, chip->data_year->leap_shift); | ||
373 | |||
374 | time = SUNXI_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | | ||
375 | SUNXI_TIME_SET_MIN_VALUE(rtc_tm->tm_min) | | ||
376 | SUNXI_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour); | ||
377 | |||
378 | writel(0, chip->base + SUNXI_RTC_HMS); | ||
379 | writel(0, chip->base + SUNXI_RTC_YMD); | ||
380 | |||
381 | writel(time, chip->base + SUNXI_RTC_HMS); | ||
382 | |||
383 | /* | ||
384 | * After writing the RTC HH-MM-SS register, the | ||
385 | * SUNXI_LOSC_CTRL_RTC_HMS_ACC bit is set and it will not | ||
386 | * be cleared until the real writing operation is finished | ||
387 | */ | ||
388 | |||
389 | if (sunxi_rtc_wait(chip, SUNXI_LOSC_CTRL, | ||
390 | SUNXI_LOSC_CTRL_RTC_HMS_ACC, 50)) { | ||
391 | dev_err(dev, "Failed to set rtc time.\n"); | ||
392 | return -1; | ||
393 | } | ||
394 | |||
395 | writel(date, chip->base + SUNXI_RTC_YMD); | ||
396 | |||
397 | /* | ||
398 | * After writing the RTC YY-MM-DD register, the | ||
399 | * SUNXI_LOSC_CTRL_RTC_YMD_ACC bit is set and it will not | ||
400 | * be cleared until the real writing operation is finished | ||
401 | */ | ||
402 | |||
403 | if (sunxi_rtc_wait(chip, SUNXI_LOSC_CTRL, | ||
404 | SUNXI_LOSC_CTRL_RTC_YMD_ACC, 50)) { | ||
405 | dev_err(dev, "Failed to set rtc time.\n"); | ||
406 | return -1; | ||
407 | } | ||
408 | |||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | static int sunxi_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
413 | { | ||
414 | struct sunxi_rtc_dev *chip = dev_get_drvdata(dev); | ||
415 | |||
416 | if (!enabled) | ||
417 | sunxi_rtc_setaie(enabled, chip); | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static const struct rtc_class_ops sunxi_rtc_ops = { | ||
423 | .read_time = sunxi_rtc_gettime, | ||
424 | .set_time = sunxi_rtc_settime, | ||
425 | .read_alarm = sunxi_rtc_getalarm, | ||
426 | .set_alarm = sunxi_rtc_setalarm, | ||
427 | .alarm_irq_enable = sunxi_rtc_alarm_irq_enable | ||
428 | }; | ||
429 | |||
430 | static const struct of_device_id sunxi_rtc_dt_ids[] = { | ||
431 | { .compatible = "allwinner,sun4i-rtc", .data = &data_year_param[0] }, | ||
432 | { .compatible = "allwinner,sun7i-a20-rtc", .data = &data_year_param[1] }, | ||
433 | { /* sentinel */ }, | ||
434 | }; | ||
435 | MODULE_DEVICE_TABLE(of, sunxi_rtc_dt_ids); | ||
436 | |||
437 | static int sunxi_rtc_probe(struct platform_device *pdev) | ||
438 | { | ||
439 | struct sunxi_rtc_dev *chip; | ||
440 | struct resource *res; | ||
441 | const struct of_device_id *of_id; | ||
442 | int ret; | ||
443 | |||
444 | chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); | ||
445 | if (!chip) | ||
446 | return -ENOMEM; | ||
447 | |||
448 | platform_set_drvdata(pdev, chip); | ||
449 | chip->dev = &pdev->dev; | ||
450 | |||
451 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
452 | chip->base = devm_ioremap_resource(&pdev->dev, res); | ||
453 | if (IS_ERR(chip->base)) | ||
454 | return PTR_ERR(chip->base); | ||
455 | |||
456 | chip->irq = platform_get_irq(pdev, 0); | ||
457 | if (chip->irq < 0) { | ||
458 | dev_err(&pdev->dev, "No IRQ resource\n"); | ||
459 | return chip->irq; | ||
460 | } | ||
461 | ret = devm_request_irq(&pdev->dev, chip->irq, sunxi_rtc_alarmirq, | ||
462 | 0, dev_name(&pdev->dev), chip); | ||
463 | if (ret) { | ||
464 | dev_err(&pdev->dev, "Could not request IRQ\n"); | ||
465 | return ret; | ||
466 | } | ||
467 | |||
468 | of_id = of_match_device(sunxi_rtc_dt_ids, &pdev->dev); | ||
469 | if (!of_id) { | ||
470 | dev_err(&pdev->dev, "Unable to setup RTC data\n"); | ||
471 | return -ENODEV; | ||
472 | } | ||
473 | chip->data_year = (struct sunxi_rtc_data_year *) of_id->data; | ||
474 | |||
475 | /* clear the alarm count value */ | ||
476 | writel(0, chip->base + SUNXI_ALRM_DHMS); | ||
477 | |||
478 | /* disable alarm, not generate irq pending */ | ||
479 | writel(0, chip->base + SUNXI_ALRM_EN); | ||
480 | |||
481 | /* disable alarm week/cnt irq, unset to cpu */ | ||
482 | writel(0, chip->base + SUNXI_ALRM_IRQ_EN); | ||
483 | |||
484 | /* clear alarm week/cnt irq pending */ | ||
485 | writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + | ||
486 | SUNXI_ALRM_IRQ_STA); | ||
487 | |||
488 | chip->rtc = rtc_device_register("rtc-sunxi", &pdev->dev, | ||
489 | &sunxi_rtc_ops, THIS_MODULE); | ||
490 | if (IS_ERR(chip->rtc)) { | ||
491 | dev_err(&pdev->dev, "unable to register device\n"); | ||
492 | return PTR_ERR(chip->rtc); | ||
493 | } | ||
494 | |||
495 | dev_info(&pdev->dev, "RTC enabled\n"); | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static int sunxi_rtc_remove(struct platform_device *pdev) | ||
501 | { | ||
502 | struct sunxi_rtc_dev *chip = platform_get_drvdata(pdev); | ||
503 | |||
504 | rtc_device_unregister(chip->rtc); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static struct platform_driver sunxi_rtc_driver = { | ||
510 | .probe = sunxi_rtc_probe, | ||
511 | .remove = sunxi_rtc_remove, | ||
512 | .driver = { | ||
513 | .name = "sunxi-rtc", | ||
514 | .owner = THIS_MODULE, | ||
515 | .of_match_table = sunxi_rtc_dt_ids, | ||
516 | }, | ||
517 | }; | ||
518 | |||
519 | module_platform_driver(sunxi_rtc_driver); | ||
520 | |||
521 | MODULE_DESCRIPTION("sunxi RTC driver"); | ||
522 | MODULE_AUTHOR("Carlo Caione <carlo.caione@gmail.com>"); | ||
523 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index c2e80d7ca5e2..1915464e4cd6 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c | |||
@@ -479,7 +479,7 @@ static int twl_rtc_probe(struct platform_device *pdev) | |||
479 | u8 rd_reg; | 479 | u8 rd_reg; |
480 | 480 | ||
481 | if (irq <= 0) | 481 | if (irq <= 0) |
482 | goto out1; | 482 | return ret; |
483 | 483 | ||
484 | /* Initialize the register map */ | 484 | /* Initialize the register map */ |
485 | if (twl_class_is_4030()) | 485 | if (twl_class_is_4030()) |
@@ -489,7 +489,7 @@ static int twl_rtc_probe(struct platform_device *pdev) | |||
489 | 489 | ||
490 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); | 490 | ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); |
491 | if (ret < 0) | 491 | if (ret < 0) |
492 | goto out1; | 492 | return ret; |
493 | 493 | ||
494 | if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) | 494 | if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) |
495 | dev_warn(&pdev->dev, "Power up reset detected.\n"); | 495 | dev_warn(&pdev->dev, "Power up reset detected.\n"); |
@@ -500,7 +500,7 @@ static int twl_rtc_probe(struct platform_device *pdev) | |||
500 | /* Clear RTC Power up reset and pending alarm interrupts */ | 500 | /* Clear RTC Power up reset and pending alarm interrupts */ |
501 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); | 501 | ret = twl_rtc_write_u8(rd_reg, REG_RTC_STATUS_REG); |
502 | if (ret < 0) | 502 | if (ret < 0) |
503 | goto out1; | 503 | return ret; |
504 | 504 | ||
505 | if (twl_class_is_6030()) { | 505 | if (twl_class_is_6030()) { |
506 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, | 506 | twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, |
@@ -512,7 +512,7 @@ static int twl_rtc_probe(struct platform_device *pdev) | |||
512 | dev_info(&pdev->dev, "Enabling TWL-RTC\n"); | 512 | dev_info(&pdev->dev, "Enabling TWL-RTC\n"); |
513 | ret = twl_rtc_write_u8(BIT_RTC_CTRL_REG_STOP_RTC_M, REG_RTC_CTRL_REG); | 513 | ret = twl_rtc_write_u8(BIT_RTC_CTRL_REG_STOP_RTC_M, REG_RTC_CTRL_REG); |
514 | if (ret < 0) | 514 | if (ret < 0) |
515 | goto out1; | 515 | return ret; |
516 | 516 | ||
517 | /* ensure interrupts are disabled, bootloaders can be strange */ | 517 | /* ensure interrupts are disabled, bootloaders can be strange */ |
518 | ret = twl_rtc_write_u8(0, REG_RTC_INTERRUPTS_REG); | 518 | ret = twl_rtc_write_u8(0, REG_RTC_INTERRUPTS_REG); |
@@ -522,34 +522,29 @@ static int twl_rtc_probe(struct platform_device *pdev) | |||
522 | /* init cached IRQ enable bits */ | 522 | /* init cached IRQ enable bits */ |
523 | ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); | 523 | ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); |
524 | if (ret < 0) | 524 | if (ret < 0) |
525 | goto out1; | 525 | return ret; |
526 | 526 | ||
527 | device_init_wakeup(&pdev->dev, 1); | 527 | device_init_wakeup(&pdev->dev, 1); |
528 | 528 | ||
529 | rtc = rtc_device_register(pdev->name, | 529 | rtc = devm_rtc_device_register(&pdev->dev, pdev->name, |
530 | &pdev->dev, &twl_rtc_ops, THIS_MODULE); | 530 | &twl_rtc_ops, THIS_MODULE); |
531 | if (IS_ERR(rtc)) { | 531 | if (IS_ERR(rtc)) { |
532 | ret = PTR_ERR(rtc); | ||
533 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | 532 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", |
534 | PTR_ERR(rtc)); | 533 | PTR_ERR(rtc)); |
535 | goto out1; | 534 | return PTR_ERR(rtc); |
536 | } | 535 | } |
537 | 536 | ||
538 | ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt, | 537 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
539 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | 538 | twl_rtc_interrupt, |
540 | dev_name(&rtc->dev), rtc); | 539 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
540 | dev_name(&rtc->dev), rtc); | ||
541 | if (ret < 0) { | 541 | if (ret < 0) { |
542 | dev_err(&pdev->dev, "IRQ is not free.\n"); | 542 | dev_err(&pdev->dev, "IRQ is not free.\n"); |
543 | goto out2; | 543 | return ret; |
544 | } | 544 | } |
545 | 545 | ||
546 | platform_set_drvdata(pdev, rtc); | 546 | platform_set_drvdata(pdev, rtc); |
547 | return 0; | 547 | return 0; |
548 | |||
549 | out2: | ||
550 | rtc_device_unregister(rtc); | ||
551 | out1: | ||
552 | return ret; | ||
553 | } | 548 | } |
554 | 549 | ||
555 | /* | 550 | /* |
@@ -559,9 +554,6 @@ out1: | |||
559 | static int twl_rtc_remove(struct platform_device *pdev) | 554 | static int twl_rtc_remove(struct platform_device *pdev) |
560 | { | 555 | { |
561 | /* leave rtc running, but disable irqs */ | 556 | /* leave rtc running, but disable irqs */ |
562 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
563 | int irq = platform_get_irq(pdev, 0); | ||
564 | |||
565 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); | 557 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); |
566 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); | 558 | mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); |
567 | if (twl_class_is_6030()) { | 559 | if (twl_class_is_6030()) { |
@@ -571,10 +563,6 @@ static int twl_rtc_remove(struct platform_device *pdev) | |||
571 | REG_INT_MSK_STS_A); | 563 | REG_INT_MSK_STS_A); |
572 | } | 564 | } |
573 | 565 | ||
574 | |||
575 | free_irq(irq, rtc); | ||
576 | |||
577 | rtc_device_unregister(rtc); | ||
578 | return 0; | 566 | return 0; |
579 | } | 567 | } |
580 | 568 | ||
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index aabc22c587fb..88c9c92e89fd 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
@@ -293,7 +293,7 @@ static int rtc_probe(struct platform_device *pdev) | |||
293 | if (!res) | 293 | if (!res) |
294 | return -EBUSY; | 294 | return -EBUSY; |
295 | 295 | ||
296 | rtc1_base = ioremap(res->start, resource_size(res)); | 296 | rtc1_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); |
297 | if (!rtc1_base) | 297 | if (!rtc1_base) |
298 | return -EBUSY; | 298 | return -EBUSY; |
299 | 299 | ||
@@ -303,13 +303,14 @@ static int rtc_probe(struct platform_device *pdev) | |||
303 | goto err_rtc1_iounmap; | 303 | goto err_rtc1_iounmap; |
304 | } | 304 | } |
305 | 305 | ||
306 | rtc2_base = ioremap(res->start, resource_size(res)); | 306 | rtc2_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); |
307 | if (!rtc2_base) { | 307 | if (!rtc2_base) { |
308 | retval = -EBUSY; | 308 | retval = -EBUSY; |
309 | goto err_rtc1_iounmap; | 309 | goto err_rtc1_iounmap; |
310 | } | 310 | } |
311 | 311 | ||
312 | rtc = rtc_device_register(rtc_name, &pdev->dev, &vr41xx_rtc_ops, THIS_MODULE); | 312 | rtc = devm_rtc_device_register(&pdev->dev, rtc_name, &vr41xx_rtc_ops, |
313 | THIS_MODULE); | ||
313 | if (IS_ERR(rtc)) { | 314 | if (IS_ERR(rtc)) { |
314 | retval = PTR_ERR(rtc); | 315 | retval = PTR_ERR(rtc); |
315 | goto err_iounmap_all; | 316 | goto err_iounmap_all; |
@@ -330,24 +331,24 @@ static int rtc_probe(struct platform_device *pdev) | |||
330 | aie_irq = platform_get_irq(pdev, 0); | 331 | aie_irq = platform_get_irq(pdev, 0); |
331 | if (aie_irq <= 0) { | 332 | if (aie_irq <= 0) { |
332 | retval = -EBUSY; | 333 | retval = -EBUSY; |
333 | goto err_device_unregister; | 334 | goto err_iounmap_all; |
334 | } | 335 | } |
335 | 336 | ||
336 | retval = request_irq(aie_irq, elapsedtime_interrupt, 0, | 337 | retval = devm_request_irq(&pdev->dev, aie_irq, elapsedtime_interrupt, 0, |
337 | "elapsed_time", pdev); | 338 | "elapsed_time", pdev); |
338 | if (retval < 0) | 339 | if (retval < 0) |
339 | goto err_device_unregister; | 340 | goto err_iounmap_all; |
340 | 341 | ||
341 | pie_irq = platform_get_irq(pdev, 1); | 342 | pie_irq = platform_get_irq(pdev, 1); |
342 | if (pie_irq <= 0) { | 343 | if (pie_irq <= 0) { |
343 | retval = -EBUSY; | 344 | retval = -EBUSY; |
344 | goto err_free_irq; | 345 | goto err_iounmap_all; |
345 | } | 346 | } |
346 | 347 | ||
347 | retval = request_irq(pie_irq, rtclong1_interrupt, 0, | 348 | retval = devm_request_irq(&pdev->dev, pie_irq, rtclong1_interrupt, 0, |
348 | "rtclong1", pdev); | 349 | "rtclong1", pdev); |
349 | if (retval < 0) | 350 | if (retval < 0) |
350 | goto err_free_irq; | 351 | goto err_iounmap_all; |
351 | 352 | ||
352 | platform_set_drvdata(pdev, rtc); | 353 | platform_set_drvdata(pdev, rtc); |
353 | 354 | ||
@@ -358,47 +359,20 @@ static int rtc_probe(struct platform_device *pdev) | |||
358 | 359 | ||
359 | return 0; | 360 | return 0; |
360 | 361 | ||
361 | err_free_irq: | ||
362 | free_irq(aie_irq, pdev); | ||
363 | |||
364 | err_device_unregister: | ||
365 | rtc_device_unregister(rtc); | ||
366 | |||
367 | err_iounmap_all: | 362 | err_iounmap_all: |
368 | iounmap(rtc2_base); | ||
369 | rtc2_base = NULL; | 363 | rtc2_base = NULL; |
370 | 364 | ||
371 | err_rtc1_iounmap: | 365 | err_rtc1_iounmap: |
372 | iounmap(rtc1_base); | ||
373 | rtc1_base = NULL; | 366 | rtc1_base = NULL; |
374 | 367 | ||
375 | return retval; | 368 | return retval; |
376 | } | 369 | } |
377 | 370 | ||
378 | static int rtc_remove(struct platform_device *pdev) | ||
379 | { | ||
380 | struct rtc_device *rtc; | ||
381 | |||
382 | rtc = platform_get_drvdata(pdev); | ||
383 | if (rtc) | ||
384 | rtc_device_unregister(rtc); | ||
385 | |||
386 | free_irq(aie_irq, pdev); | ||
387 | free_irq(pie_irq, pdev); | ||
388 | if (rtc1_base) | ||
389 | iounmap(rtc1_base); | ||
390 | if (rtc2_base) | ||
391 | iounmap(rtc2_base); | ||
392 | |||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | /* work with hotplug and coldplug */ | 371 | /* work with hotplug and coldplug */ |
397 | MODULE_ALIAS("platform:RTC"); | 372 | MODULE_ALIAS("platform:RTC"); |
398 | 373 | ||
399 | static struct platform_driver rtc_platform_driver = { | 374 | static struct platform_driver rtc_platform_driver = { |
400 | .probe = rtc_probe, | 375 | .probe = rtc_probe, |
401 | .remove = rtc_remove, | ||
402 | .driver = { | 376 | .driver = { |
403 | .name = rtc_name, | 377 | .name = rtc_name, |
404 | .owner = THIS_MODULE, | 378 | .owner = THIS_MODULE, |