diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-03-01 02:55:20 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-03-01 02:55:20 -0500 |
commit | 35858adbfca13678af99fb31618ef4428d6dedb0 (patch) | |
tree | 3336feaa61324486945816cb52c347733e7c0821 /drivers/rtc | |
parent | 197d4db752e67160d79fed09968c2140376a80a3 (diff) | |
parent | 4b70858ba8d4537daf782defebe5f2ff80ccef2b (diff) |
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/rtc')
33 files changed, 1372 insertions, 471 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 71fbd6e8edf7..8167e9e6827a 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -242,6 +242,15 @@ config RTC_DRV_M41T80_WDT | |||
242 | If you say Y here you will get support for the | 242 | If you say Y here you will get support for the |
243 | watchdog timer in the ST M41T60 and M41T80 RTC chips series. | 243 | watchdog timer in the ST M41T60 and M41T80 RTC chips series. |
244 | 244 | ||
245 | config RTC_DRV_BQ32K | ||
246 | tristate "TI BQ32000" | ||
247 | help | ||
248 | If you say Y here you will get support for the TI | ||
249 | BQ32000 I2C RTC chip. | ||
250 | |||
251 | This driver can also be built as a module. If so, the module | ||
252 | will be called rtc-bq32k. | ||
253 | |||
245 | config RTC_DRV_DM355EVM | 254 | config RTC_DRV_DM355EVM |
246 | tristate "TI DaVinci DM355 EVM RTC" | 255 | tristate "TI DaVinci DM355 EVM RTC" |
247 | depends on MFD_DM355EVM_MSP | 256 | depends on MFD_DM355EVM_MSP |
@@ -592,15 +601,22 @@ config RTC_DRV_AB3100 | |||
592 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC | 601 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC |
593 | support. This chip contains a battery- and capacitor-backed RTC. | 602 | support. This chip contains a battery- and capacitor-backed RTC. |
594 | 603 | ||
604 | config RTC_DRV_NUC900 | ||
605 | tristate "NUC910/NUC920 RTC driver" | ||
606 | depends on RTC_CLASS && ARCH_W90X900 | ||
607 | help | ||
608 | If you say yes here you get support for the RTC subsystem of the | ||
609 | NUC910/NUC920 used in embedded systems. | ||
595 | 610 | ||
596 | comment "on-CPU RTC drivers" | 611 | comment "on-CPU RTC drivers" |
597 | 612 | ||
598 | config RTC_DRV_OMAP | 613 | config RTC_DRV_OMAP |
599 | tristate "TI OMAP1" | 614 | tristate "TI OMAP1" |
600 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 | 615 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX |
601 | help | 616 | help |
602 | Say "yes" here to support the real time clock on TI OMAP1 chips. | 617 | Say "yes" here to support the real time clock on TI OMAP1 and |
603 | This driver can also be built as a module called rtc-omap. | 618 | DA8xx/OMAP-L13x chips. This driver can also be built as a |
619 | module called rtc-omap. | ||
604 | 620 | ||
605 | config RTC_DRV_S3C | 621 | config RTC_DRV_S3C |
606 | tristate "Samsung S3C series SoC RTC" | 622 | tristate "Samsung S3C series SoC RTC" |
@@ -846,4 +862,10 @@ config RTC_DRV_PCAP | |||
846 | If you say Y here you will get support for the RTC found on | 862 | If you say Y here you will get support for the RTC found on |
847 | the PCAP2 ASIC used on some Motorola phones. | 863 | the PCAP2 ASIC used on some Motorola phones. |
848 | 864 | ||
865 | config RTC_DRV_MC13783 | ||
866 | depends on MFD_MC13783 | ||
867 | tristate "Freescale MC13783 RTC" | ||
868 | help | ||
869 | This enables support for the Freescale MC13783 PMIC RTC | ||
870 | |||
849 | endif # RTC_CLASS | 871 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 7da6efb3e953..e5160fddc446 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o | |||
23 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | 23 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o |
24 | obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o | 24 | obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o |
25 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o | 25 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o |
26 | obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o | ||
26 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o | 27 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o |
27 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 28 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
28 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o | 29 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o |
@@ -52,8 +53,10 @@ obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | |||
52 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o | 53 | obj-$(CONFIG_RTC_MXC) += rtc-mxc.o |
53 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 54 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
54 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 55 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
56 | obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o | ||
55 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o | 57 | obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o |
56 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | 58 | obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o |
59 | obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o | ||
57 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | 60 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o |
58 | obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o | 61 | obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o |
59 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | 62 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o |
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index e1ec33e40e38..8825695777df 100644 --- a/drivers/rtc/rtc-at32ap700x.c +++ b/drivers/rtc/rtc-at32ap700x.c | |||
@@ -256,6 +256,8 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | |||
256 | goto out_iounmap; | 256 | goto out_iounmap; |
257 | } | 257 | } |
258 | 258 | ||
259 | platform_set_drvdata(pdev, rtc); | ||
260 | |||
259 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | 261 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, |
260 | &at32_rtc_ops, THIS_MODULE); | 262 | &at32_rtc_ops, THIS_MODULE); |
261 | if (IS_ERR(rtc->rtc)) { | 263 | if (IS_ERR(rtc->rtc)) { |
@@ -264,7 +266,6 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | |||
264 | goto out_free_irq; | 266 | goto out_free_irq; |
265 | } | 267 | } |
266 | 268 | ||
267 | platform_set_drvdata(pdev, rtc); | ||
268 | device_init_wakeup(&pdev->dev, 1); | 269 | device_init_wakeup(&pdev->dev, 1); |
269 | 270 | ||
270 | dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n", | 271 | dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n", |
@@ -273,6 +274,7 @@ static int __init at32_rtc_probe(struct platform_device *pdev) | |||
273 | return 0; | 274 | return 0; |
274 | 275 | ||
275 | out_free_irq: | 276 | out_free_irq: |
277 | platform_set_drvdata(pdev, NULL); | ||
276 | free_irq(irq, rtc); | 278 | free_irq(irq, rtc); |
277 | out_iounmap: | 279 | out_iounmap: |
278 | iounmap(rtc->regs); | 280 | iounmap(rtc->regs); |
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c new file mode 100644 index 000000000000..408cc8f735be --- /dev/null +++ b/drivers/rtc/rtc-bq32k.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* | ||
2 | * Driver for TI BQ32000 RTC. | ||
3 | * | ||
4 | * Copyright (C) 2009 Semihalf. | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/rtc.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/bcd.h> | ||
17 | |||
18 | #define BQ32K_SECONDS 0x00 /* Seconds register address */ | ||
19 | #define BQ32K_SECONDS_MASK 0x7F /* Mask over seconds value */ | ||
20 | #define BQ32K_STOP 0x80 /* Oscillator Stop flat */ | ||
21 | |||
22 | #define BQ32K_MINUTES 0x01 /* Minutes register address */ | ||
23 | #define BQ32K_MINUTES_MASK 0x7F /* Mask over minutes value */ | ||
24 | #define BQ32K_OF 0x80 /* Oscillator Failure flag */ | ||
25 | |||
26 | #define BQ32K_HOURS_MASK 0x3F /* Mask over hours value */ | ||
27 | #define BQ32K_CENT 0x40 /* Century flag */ | ||
28 | #define BQ32K_CENT_EN 0x80 /* Century flag enable bit */ | ||
29 | |||
30 | struct bq32k_regs { | ||
31 | uint8_t seconds; | ||
32 | uint8_t minutes; | ||
33 | uint8_t cent_hours; | ||
34 | uint8_t day; | ||
35 | uint8_t date; | ||
36 | uint8_t month; | ||
37 | uint8_t years; | ||
38 | }; | ||
39 | |||
40 | static struct i2c_driver bq32k_driver; | ||
41 | |||
42 | static int bq32k_read(struct device *dev, void *data, uint8_t off, uint8_t len) | ||
43 | { | ||
44 | struct i2c_client *client = to_i2c_client(dev); | ||
45 | struct i2c_msg msgs[] = { | ||
46 | { | ||
47 | .addr = client->addr, | ||
48 | .flags = 0, | ||
49 | .len = 1, | ||
50 | .buf = &off, | ||
51 | }, { | ||
52 | .addr = client->addr, | ||
53 | .flags = I2C_M_RD, | ||
54 | .len = len, | ||
55 | .buf = data, | ||
56 | } | ||
57 | }; | ||
58 | |||
59 | if (i2c_transfer(client->adapter, msgs, 2) == 2) | ||
60 | return 0; | ||
61 | |||
62 | return -EIO; | ||
63 | } | ||
64 | |||
65 | static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len) | ||
66 | { | ||
67 | struct i2c_client *client = to_i2c_client(dev); | ||
68 | uint8_t buffer[len + 1]; | ||
69 | |||
70 | buffer[0] = off; | ||
71 | memcpy(&buffer[1], data, len); | ||
72 | |||
73 | if (i2c_master_send(client, buffer, len + 1) == len + 1) | ||
74 | return 0; | ||
75 | |||
76 | return -EIO; | ||
77 | } | ||
78 | |||
79 | static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
80 | { | ||
81 | struct bq32k_regs regs; | ||
82 | int error; | ||
83 | |||
84 | error = bq32k_read(dev, ®s, 0, sizeof(regs)); | ||
85 | if (error) | ||
86 | return error; | ||
87 | |||
88 | tm->tm_sec = bcd2bin(regs.seconds & BQ32K_SECONDS_MASK); | ||
89 | tm->tm_min = bcd2bin(regs.minutes & BQ32K_SECONDS_MASK); | ||
90 | tm->tm_hour = bcd2bin(regs.cent_hours & BQ32K_HOURS_MASK); | ||
91 | tm->tm_mday = bcd2bin(regs.date); | ||
92 | tm->tm_wday = bcd2bin(regs.day) - 1; | ||
93 | tm->tm_mon = bcd2bin(regs.month) - 1; | ||
94 | tm->tm_year = bcd2bin(regs.years) + | ||
95 | ((regs.cent_hours & BQ32K_CENT) ? 100 : 0); | ||
96 | |||
97 | return rtc_valid_tm(tm); | ||
98 | } | ||
99 | |||
100 | static int bq32k_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
101 | { | ||
102 | struct bq32k_regs regs; | ||
103 | |||
104 | regs.seconds = bin2bcd(tm->tm_sec); | ||
105 | regs.minutes = bin2bcd(tm->tm_min); | ||
106 | regs.cent_hours = bin2bcd(tm->tm_hour) | BQ32K_CENT_EN; | ||
107 | regs.day = bin2bcd(tm->tm_wday + 1); | ||
108 | regs.date = bin2bcd(tm->tm_mday); | ||
109 | regs.month = bin2bcd(tm->tm_mon + 1); | ||
110 | |||
111 | if (tm->tm_year >= 100) { | ||
112 | regs.cent_hours |= BQ32K_CENT; | ||
113 | regs.years = bin2bcd(tm->tm_year - 100); | ||
114 | } else | ||
115 | regs.years = bin2bcd(tm->tm_year); | ||
116 | |||
117 | return bq32k_write(dev, ®s, 0, sizeof(regs)); | ||
118 | } | ||
119 | |||
120 | static const struct rtc_class_ops bq32k_rtc_ops = { | ||
121 | .read_time = bq32k_rtc_read_time, | ||
122 | .set_time = bq32k_rtc_set_time, | ||
123 | }; | ||
124 | |||
125 | static int bq32k_probe(struct i2c_client *client, | ||
126 | const struct i2c_device_id *id) | ||
127 | { | ||
128 | struct device *dev = &client->dev; | ||
129 | struct rtc_device *rtc; | ||
130 | uint8_t reg; | ||
131 | int error; | ||
132 | |||
133 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
134 | return -ENODEV; | ||
135 | |||
136 | /* Check Oscillator Stop flag */ | ||
137 | error = bq32k_read(dev, ®, BQ32K_SECONDS, 1); | ||
138 | if (!error && (reg & BQ32K_STOP)) { | ||
139 | dev_warn(dev, "Oscillator was halted. Restarting...\n"); | ||
140 | reg &= ~BQ32K_STOP; | ||
141 | error = bq32k_write(dev, ®, BQ32K_SECONDS, 1); | ||
142 | } | ||
143 | if (error) | ||
144 | return error; | ||
145 | |||
146 | /* Check Oscillator Failure flag */ | ||
147 | error = bq32k_read(dev, ®, BQ32K_MINUTES, 1); | ||
148 | if (!error && (reg & BQ32K_OF)) { | ||
149 | dev_warn(dev, "Oscillator Failure. Check RTC battery.\n"); | ||
150 | reg &= ~BQ32K_OF; | ||
151 | error = bq32k_write(dev, ®, BQ32K_MINUTES, 1); | ||
152 | } | ||
153 | if (error) | ||
154 | return error; | ||
155 | |||
156 | rtc = rtc_device_register(bq32k_driver.driver.name, &client->dev, | ||
157 | &bq32k_rtc_ops, THIS_MODULE); | ||
158 | if (IS_ERR(rtc)) | ||
159 | return PTR_ERR(rtc); | ||
160 | |||
161 | i2c_set_clientdata(client, rtc); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static int __devexit bq32k_remove(struct i2c_client *client) | ||
167 | { | ||
168 | struct rtc_device *rtc = i2c_get_clientdata(client); | ||
169 | |||
170 | rtc_device_unregister(rtc); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static const struct i2c_device_id bq32k_id[] = { | ||
175 | { "bq32000", 0 }, | ||
176 | { } | ||
177 | }; | ||
178 | MODULE_DEVICE_TABLE(i2c, bq32k_id); | ||
179 | |||
180 | static struct i2c_driver bq32k_driver = { | ||
181 | .driver = { | ||
182 | .name = "bq32k", | ||
183 | .owner = THIS_MODULE, | ||
184 | }, | ||
185 | .probe = bq32k_probe, | ||
186 | .remove = __devexit_p(bq32k_remove), | ||
187 | .id_table = bq32k_id, | ||
188 | }; | ||
189 | |||
190 | static __init int bq32k_init(void) | ||
191 | { | ||
192 | return i2c_add_driver(&bq32k_driver); | ||
193 | } | ||
194 | module_init(bq32k_init); | ||
195 | |||
196 | static __exit void bq32k_exit(void) | ||
197 | { | ||
198 | i2c_del_driver(&bq32k_driver); | ||
199 | } | ||
200 | module_exit(bq32k_exit); | ||
201 | |||
202 | MODULE_AUTHOR("Semihalf, Piotr Ziecik <kosmo@semihalf.com>"); | ||
203 | MODULE_DESCRIPTION("TI BQ32000 I2C RTC driver"); | ||
204 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c index d00a274df8fc..280fe48ada0b 100644 --- a/drivers/rtc/rtc-bq4802.c +++ b/drivers/rtc/rtc-bq4802.c | |||
@@ -169,6 +169,8 @@ static int __devinit bq4802_probe(struct platform_device *pdev) | |||
169 | goto out_free; | 169 | goto out_free; |
170 | } | 170 | } |
171 | 171 | ||
172 | platform_set_drvdata(pdev, p); | ||
173 | |||
172 | p->rtc = rtc_device_register("bq4802", &pdev->dev, | 174 | p->rtc = rtc_device_register("bq4802", &pdev->dev, |
173 | &bq4802_ops, THIS_MODULE); | 175 | &bq4802_ops, THIS_MODULE); |
174 | if (IS_ERR(p->rtc)) { | 176 | if (IS_ERR(p->rtc)) { |
@@ -176,7 +178,6 @@ static int __devinit bq4802_probe(struct platform_device *pdev) | |||
176 | goto out_iounmap; | 178 | goto out_iounmap; |
177 | } | 179 | } |
178 | 180 | ||
179 | platform_set_drvdata(pdev, p); | ||
180 | err = 0; | 181 | err = 0; |
181 | out: | 182 | out: |
182 | return err; | 183 | return err; |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index f7a4701bf863..e9aa814ddd23 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -420,49 +420,43 @@ static int cmos_irq_set_state(struct device *dev, int enabled) | |||
420 | return 0; | 420 | return 0; |
421 | } | 421 | } |
422 | 422 | ||
423 | #if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE) | 423 | static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) |
424 | |||
425 | static int | ||
426 | cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
427 | { | 424 | { |
428 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 425 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
429 | unsigned long flags; | 426 | unsigned long flags; |
430 | 427 | ||
431 | switch (cmd) { | 428 | if (!is_valid_irq(cmos->irq)) |
432 | case RTC_AIE_OFF: | 429 | return -EINVAL; |
433 | case RTC_AIE_ON: | ||
434 | case RTC_UIE_OFF: | ||
435 | case RTC_UIE_ON: | ||
436 | if (!is_valid_irq(cmos->irq)) | ||
437 | return -EINVAL; | ||
438 | break; | ||
439 | /* PIE ON/OFF is handled by cmos_irq_set_state() */ | ||
440 | default: | ||
441 | return -ENOIOCTLCMD; | ||
442 | } | ||
443 | 430 | ||
444 | spin_lock_irqsave(&rtc_lock, flags); | 431 | spin_lock_irqsave(&rtc_lock, flags); |
445 | switch (cmd) { | 432 | |
446 | case RTC_AIE_OFF: /* alarm off */ | 433 | if (enabled) |
447 | cmos_irq_disable(cmos, RTC_AIE); | ||
448 | break; | ||
449 | case RTC_AIE_ON: /* alarm on */ | ||
450 | cmos_irq_enable(cmos, RTC_AIE); | 434 | cmos_irq_enable(cmos, RTC_AIE); |
451 | break; | 435 | else |
452 | case RTC_UIE_OFF: /* update off */ | 436 | cmos_irq_disable(cmos, RTC_AIE); |
453 | cmos_irq_disable(cmos, RTC_UIE); | 437 | |
454 | break; | ||
455 | case RTC_UIE_ON: /* update on */ | ||
456 | cmos_irq_enable(cmos, RTC_UIE); | ||
457 | break; | ||
458 | } | ||
459 | spin_unlock_irqrestore(&rtc_lock, flags); | 438 | spin_unlock_irqrestore(&rtc_lock, flags); |
460 | return 0; | 439 | return 0; |
461 | } | 440 | } |
462 | 441 | ||
463 | #else | 442 | static int cmos_update_irq_enable(struct device *dev, unsigned int enabled) |
464 | #define cmos_rtc_ioctl NULL | 443 | { |
465 | #endif | 444 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
445 | unsigned long flags; | ||
446 | |||
447 | if (!is_valid_irq(cmos->irq)) | ||
448 | return -EINVAL; | ||
449 | |||
450 | spin_lock_irqsave(&rtc_lock, flags); | ||
451 | |||
452 | if (enabled) | ||
453 | cmos_irq_enable(cmos, RTC_UIE); | ||
454 | else | ||
455 | cmos_irq_disable(cmos, RTC_UIE); | ||
456 | |||
457 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
458 | return 0; | ||
459 | } | ||
466 | 460 | ||
467 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) | 461 | #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) |
468 | 462 | ||
@@ -503,14 +497,15 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq) | |||
503 | #endif | 497 | #endif |
504 | 498 | ||
505 | static const struct rtc_class_ops cmos_rtc_ops = { | 499 | static const struct rtc_class_ops cmos_rtc_ops = { |
506 | .ioctl = cmos_rtc_ioctl, | 500 | .read_time = cmos_read_time, |
507 | .read_time = cmos_read_time, | 501 | .set_time = cmos_set_time, |
508 | .set_time = cmos_set_time, | 502 | .read_alarm = cmos_read_alarm, |
509 | .read_alarm = cmos_read_alarm, | 503 | .set_alarm = cmos_set_alarm, |
510 | .set_alarm = cmos_set_alarm, | 504 | .proc = cmos_procfs, |
511 | .proc = cmos_procfs, | 505 | .irq_set_freq = cmos_irq_set_freq, |
512 | .irq_set_freq = cmos_irq_set_freq, | 506 | .irq_set_state = cmos_irq_set_state, |
513 | .irq_set_state = cmos_irq_set_state, | 507 | .alarm_irq_enable = cmos_alarm_irq_enable, |
508 | .update_irq_enable = cmos_update_irq_enable, | ||
514 | }; | 509 | }; |
515 | 510 | ||
516 | /*----------------------------------------------------------------*/ | 511 | /*----------------------------------------------------------------*/ |
@@ -691,7 +686,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
691 | */ | 686 | */ |
692 | #if defined(CONFIG_ATARI) | 687 | #if defined(CONFIG_ATARI) |
693 | address_space = 64; | 688 | address_space = 64; |
694 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__sparc__) | 689 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ |
690 | || defined(__sparc__) || defined(__mips__) | ||
695 | address_space = 128; | 691 | address_space = 128; |
696 | #else | 692 | #else |
697 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | 693 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. |
@@ -871,8 +867,9 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) | |||
871 | mask = RTC_IRQMASK; | 867 | mask = RTC_IRQMASK; |
872 | tmp &= ~mask; | 868 | tmp &= ~mask; |
873 | CMOS_WRITE(tmp, RTC_CONTROL); | 869 | CMOS_WRITE(tmp, RTC_CONTROL); |
874 | hpet_mask_rtc_irq_bit(mask); | ||
875 | 870 | ||
871 | /* shut down hpet emulation - we don't need it for alarm */ | ||
872 | hpet_mask_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE); | ||
876 | cmos_checkintr(cmos, tmp); | 873 | cmos_checkintr(cmos, tmp); |
877 | } | 874 | } |
878 | spin_unlock_irq(&rtc_lock); | 875 | spin_unlock_irq(&rtc_lock); |
@@ -1099,9 +1096,9 @@ static int cmos_pnp_resume(struct pnp_dev *pnp) | |||
1099 | #define cmos_pnp_resume NULL | 1096 | #define cmos_pnp_resume NULL |
1100 | #endif | 1097 | #endif |
1101 | 1098 | ||
1102 | static void cmos_pnp_shutdown(struct device *pdev) | 1099 | static void cmos_pnp_shutdown(struct pnp_dev *pnp) |
1103 | { | 1100 | { |
1104 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(pdev)) | 1101 | if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev)) |
1105 | return; | 1102 | return; |
1106 | 1103 | ||
1107 | cmos_do_shutdown(); | 1104 | cmos_do_shutdown(); |
@@ -1120,15 +1117,12 @@ static struct pnp_driver cmos_pnp_driver = { | |||
1120 | .id_table = rtc_ids, | 1117 | .id_table = rtc_ids, |
1121 | .probe = cmos_pnp_probe, | 1118 | .probe = cmos_pnp_probe, |
1122 | .remove = __exit_p(cmos_pnp_remove), | 1119 | .remove = __exit_p(cmos_pnp_remove), |
1120 | .shutdown = cmos_pnp_shutdown, | ||
1123 | 1121 | ||
1124 | /* flag ensures resume() gets called, and stops syslog spam */ | 1122 | /* flag ensures resume() gets called, and stops syslog spam */ |
1125 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, | 1123 | .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, |
1126 | .suspend = cmos_pnp_suspend, | 1124 | .suspend = cmos_pnp_suspend, |
1127 | .resume = cmos_pnp_resume, | 1125 | .resume = cmos_pnp_resume, |
1128 | .driver = { | ||
1129 | .name = (char *)driver_name, | ||
1130 | .shutdown = cmos_pnp_shutdown, | ||
1131 | } | ||
1132 | }; | 1126 | }; |
1133 | 1127 | ||
1134 | #endif /* CONFIG_PNP */ | 1128 | #endif /* CONFIG_PNP */ |
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index 1e73c8f42e38..532acf9b05d8 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c | |||
@@ -143,7 +143,6 @@ static int ds1302_rtc_ioctl(struct device *dev, unsigned int cmd, | |||
143 | #ifdef RTC_SET_CHARGE | 143 | #ifdef RTC_SET_CHARGE |
144 | case RTC_SET_CHARGE: | 144 | case RTC_SET_CHARGE: |
145 | { | 145 | { |
146 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
147 | int tcs_val; | 146 | int tcs_val; |
148 | 147 | ||
149 | if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) | 148 | if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) |
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 2736b11a1b1e..9630e7d3314e 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c | |||
@@ -617,7 +617,6 @@ static struct bin_attribute nvram = { | |||
617 | static int __devinit ds1305_probe(struct spi_device *spi) | 617 | static int __devinit ds1305_probe(struct spi_device *spi) |
618 | { | 618 | { |
619 | struct ds1305 *ds1305; | 619 | struct ds1305 *ds1305; |
620 | struct rtc_device *rtc; | ||
621 | int status; | 620 | int status; |
622 | u8 addr, value; | 621 | u8 addr, value; |
623 | struct ds1305_platform_data *pdata = spi->dev.platform_data; | 622 | struct ds1305_platform_data *pdata = spi->dev.platform_data; |
@@ -756,14 +755,13 @@ static int __devinit ds1305_probe(struct spi_device *spi) | |||
756 | dev_dbg(&spi->dev, "AM/PM\n"); | 755 | dev_dbg(&spi->dev, "AM/PM\n"); |
757 | 756 | ||
758 | /* register RTC ... from here on, ds1305->ctrl needs locking */ | 757 | /* register RTC ... from here on, ds1305->ctrl needs locking */ |
759 | rtc = rtc_device_register("ds1305", &spi->dev, | 758 | ds1305->rtc = rtc_device_register("ds1305", &spi->dev, |
760 | &ds1305_ops, THIS_MODULE); | 759 | &ds1305_ops, THIS_MODULE); |
761 | if (IS_ERR(rtc)) { | 760 | if (IS_ERR(ds1305->rtc)) { |
762 | status = PTR_ERR(rtc); | 761 | status = PTR_ERR(ds1305->rtc); |
763 | dev_dbg(&spi->dev, "register rtc --> %d\n", status); | 762 | dev_dbg(&spi->dev, "register rtc --> %d\n", status); |
764 | goto fail0; | 763 | goto fail0; |
765 | } | 764 | } |
766 | ds1305->rtc = rtc; | ||
767 | 765 | ||
768 | /* Maybe set up alarm IRQ; be ready to handle it triggering right | 766 | /* Maybe set up alarm IRQ; be ready to handle it triggering right |
769 | * away. NOTE that we don't share this. The signal is active low, | 767 | * away. NOTE that we don't share this. The signal is active low, |
@@ -774,12 +772,14 @@ static int __devinit ds1305_probe(struct spi_device *spi) | |||
774 | if (spi->irq) { | 772 | if (spi->irq) { |
775 | INIT_WORK(&ds1305->work, ds1305_work); | 773 | INIT_WORK(&ds1305->work, ds1305_work); |
776 | status = request_irq(spi->irq, ds1305_irq, | 774 | status = request_irq(spi->irq, ds1305_irq, |
777 | 0, dev_name(&rtc->dev), ds1305); | 775 | 0, dev_name(&ds1305->rtc->dev), ds1305); |
778 | if (status < 0) { | 776 | if (status < 0) { |
779 | dev_dbg(&spi->dev, "request_irq %d --> %d\n", | 777 | dev_dbg(&spi->dev, "request_irq %d --> %d\n", |
780 | spi->irq, status); | 778 | spi->irq, status); |
781 | goto fail1; | 779 | goto fail1; |
782 | } | 780 | } |
781 | |||
782 | device_set_wakeup_capable(&spi->dev, 1); | ||
783 | } | 783 | } |
784 | 784 | ||
785 | /* export NVRAM */ | 785 | /* export NVRAM */ |
@@ -794,7 +794,7 @@ static int __devinit ds1305_probe(struct spi_device *spi) | |||
794 | fail2: | 794 | fail2: |
795 | free_irq(spi->irq, ds1305); | 795 | free_irq(spi->irq, ds1305); |
796 | fail1: | 796 | fail1: |
797 | rtc_device_unregister(rtc); | 797 | rtc_device_unregister(ds1305->rtc); |
798 | fail0: | 798 | fail0: |
799 | kfree(ds1305); | 799 | kfree(ds1305); |
800 | return status; | 800 | return status; |
@@ -802,7 +802,7 @@ fail0: | |||
802 | 802 | ||
803 | static int __devexit ds1305_remove(struct spi_device *spi) | 803 | static int __devexit ds1305_remove(struct spi_device *spi) |
804 | { | 804 | { |
805 | struct ds1305 *ds1305 = spi_get_drvdata(spi); | 805 | struct ds1305 *ds1305 = spi_get_drvdata(spi); |
806 | 806 | ||
807 | sysfs_remove_bin_file(&spi->dev.kobj, &nvram); | 807 | sysfs_remove_bin_file(&spi->dev.kobj, &nvram); |
808 | 808 | ||
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index eb99ee4fa0f5..c4ec5c158aa1 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -874,13 +874,15 @@ read_rtc: | |||
874 | } | 874 | } |
875 | 875 | ||
876 | if (want_irq) { | 876 | if (want_irq) { |
877 | err = request_irq(client->irq, ds1307_irq, 0, | 877 | err = request_irq(client->irq, ds1307_irq, IRQF_SHARED, |
878 | ds1307->rtc->name, client); | 878 | ds1307->rtc->name, client); |
879 | if (err) { | 879 | if (err) { |
880 | dev_err(&client->dev, | 880 | dev_err(&client->dev, |
881 | "unable to request IRQ!\n"); | 881 | "unable to request IRQ!\n"); |
882 | goto exit_irq; | 882 | goto exit_irq; |
883 | } | 883 | } |
884 | |||
885 | device_set_wakeup_capable(&client->dev, 1); | ||
884 | set_bit(HAS_ALARM, &ds1307->flags); | 886 | set_bit(HAS_ALARM, &ds1307->flags); |
885 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); | 887 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); |
886 | } | 888 | } |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 713f7bf5afb3..5317bbcbc7a0 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
@@ -383,6 +383,8 @@ static int ds1374_probe(struct i2c_client *client, | |||
383 | dev_err(&client->dev, "unable to request IRQ\n"); | 383 | dev_err(&client->dev, "unable to request IRQ\n"); |
384 | goto out_free; | 384 | goto out_free; |
385 | } | 385 | } |
386 | |||
387 | device_set_wakeup_capable(&client->dev, 1); | ||
386 | } | 388 | } |
387 | 389 | ||
388 | ds1374->rtc = rtc_device_register(client->name, &client->dev, | 390 | ds1374->rtc = rtc_device_register(client->name, &client->dev, |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 539676e25fd8..4166b84cb514 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -87,7 +87,6 @@ enum ds1511reg { | |||
87 | struct rtc_plat_data { | 87 | struct rtc_plat_data { |
88 | struct rtc_device *rtc; | 88 | struct rtc_device *rtc; |
89 | void __iomem *ioaddr; /* virtual base address */ | 89 | void __iomem *ioaddr; /* virtual base address */ |
90 | unsigned long baseaddr; /* physical base address */ | ||
91 | int size; /* amount of memory mapped */ | 90 | int size; /* amount of memory mapped */ |
92 | int irq; | 91 | int irq; |
93 | unsigned int irqen; | 92 | unsigned int irqen; |
@@ -95,6 +94,7 @@ struct rtc_plat_data { | |||
95 | int alrm_min; | 94 | int alrm_min; |
96 | int alrm_hour; | 95 | int alrm_hour; |
97 | int alrm_mday; | 96 | int alrm_mday; |
97 | spinlock_t lock; | ||
98 | }; | 98 | }; |
99 | 99 | ||
100 | static DEFINE_SPINLOCK(ds1511_lock); | 100 | static DEFINE_SPINLOCK(ds1511_lock); |
@@ -302,7 +302,7 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
302 | { | 302 | { |
303 | unsigned long flags; | 303 | unsigned long flags; |
304 | 304 | ||
305 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); | 305 | spin_lock_irqsave(&pdata->lock, flags); |
306 | rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | 306 | rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? |
307 | 0x80 : bin2bcd(pdata->alrm_mday) & 0x3f, | 307 | 0x80 : bin2bcd(pdata->alrm_mday) & 0x3f, |
308 | RTC_ALARM_DATE); | 308 | RTC_ALARM_DATE); |
@@ -317,7 +317,7 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
317 | RTC_ALARM_SEC); | 317 | RTC_ALARM_SEC); |
318 | rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD); | 318 | rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD); |
319 | rtc_read(RTC_CMD1); /* clear interrupts */ | 319 | rtc_read(RTC_CMD1); /* clear interrupts */ |
320 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); | 320 | spin_unlock_irqrestore(&pdata->lock, flags); |
321 | } | 321 | } |
322 | 322 | ||
323 | static int | 323 | static int |
@@ -362,61 +362,63 @@ ds1511_interrupt(int irq, void *dev_id) | |||
362 | { | 362 | { |
363 | struct platform_device *pdev = dev_id; | 363 | struct platform_device *pdev = dev_id; |
364 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 364 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
365 | unsigned long events = RTC_IRQF; | 365 | unsigned long events = 0; |
366 | 366 | ||
367 | spin_lock(&pdata->lock); | ||
367 | /* | 368 | /* |
368 | * read and clear interrupt | 369 | * read and clear interrupt |
369 | */ | 370 | */ |
370 | if (!(rtc_read(RTC_CMD1) & DS1511_IRQF)) { | 371 | if (rtc_read(RTC_CMD1) & DS1511_IRQF) { |
371 | return IRQ_NONE; | 372 | events = RTC_IRQF; |
372 | } | 373 | if (rtc_read(RTC_ALARM_SEC) & 0x80) |
373 | if (rtc_read(RTC_ALARM_SEC) & 0x80) { | 374 | events |= RTC_UF; |
374 | events |= RTC_UF; | 375 | else |
375 | } else { | 376 | events |= RTC_AF; |
376 | events |= RTC_AF; | 377 | if (likely(pdata->rtc)) |
377 | } | 378 | rtc_update_irq(pdata->rtc, 1, events); |
378 | rtc_update_irq(pdata->rtc, 1, events); | 379 | } |
379 | return IRQ_HANDLED; | 380 | spin_unlock(&pdata->lock); |
381 | return events ? IRQ_HANDLED : IRQ_NONE; | ||
380 | } | 382 | } |
381 | 383 | ||
382 | static int | 384 | static int ds1511_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
383 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
384 | { | 385 | { |
385 | struct platform_device *pdev = to_platform_device(dev); | 386 | struct platform_device *pdev = to_platform_device(dev); |
386 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 387 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
387 | 388 | ||
388 | if (pdata->irq <= 0) { | 389 | if (pdata->irq <= 0) |
389 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | 390 | return -EINVAL; |
390 | } | 391 | if (enabled) |
391 | switch (cmd) { | ||
392 | case RTC_AIE_OFF: | ||
393 | pdata->irqen &= ~RTC_AF; | ||
394 | ds1511_rtc_update_alarm(pdata); | ||
395 | break; | ||
396 | case RTC_AIE_ON: | ||
397 | pdata->irqen |= RTC_AF; | 392 | pdata->irqen |= RTC_AF; |
398 | ds1511_rtc_update_alarm(pdata); | 393 | else |
399 | break; | 394 | pdata->irqen &= ~RTC_AF; |
400 | case RTC_UIE_OFF: | 395 | ds1511_rtc_update_alarm(pdata); |
401 | pdata->irqen &= ~RTC_UF; | 396 | return 0; |
402 | ds1511_rtc_update_alarm(pdata); | 397 | } |
403 | break; | 398 | |
404 | case RTC_UIE_ON: | 399 | static int ds1511_rtc_update_irq_enable(struct device *dev, |
400 | unsigned int enabled) | ||
401 | { | ||
402 | struct platform_device *pdev = to_platform_device(dev); | ||
403 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
404 | |||
405 | if (pdata->irq <= 0) | ||
406 | return -EINVAL; | ||
407 | if (enabled) | ||
405 | pdata->irqen |= RTC_UF; | 408 | pdata->irqen |= RTC_UF; |
406 | ds1511_rtc_update_alarm(pdata); | 409 | else |
407 | break; | 410 | pdata->irqen &= ~RTC_UF; |
408 | default: | 411 | ds1511_rtc_update_alarm(pdata); |
409 | return -ENOIOCTLCMD; | ||
410 | } | ||
411 | return 0; | 412 | return 0; |
412 | } | 413 | } |
413 | 414 | ||
414 | static const struct rtc_class_ops ds1511_rtc_ops = { | 415 | static const struct rtc_class_ops ds1511_rtc_ops = { |
415 | .read_time = ds1511_rtc_read_time, | 416 | .read_time = ds1511_rtc_read_time, |
416 | .set_time = ds1511_rtc_set_time, | 417 | .set_time = ds1511_rtc_set_time, |
417 | .read_alarm = ds1511_rtc_read_alarm, | 418 | .read_alarm = ds1511_rtc_read_alarm, |
418 | .set_alarm = ds1511_rtc_set_alarm, | 419 | .set_alarm = ds1511_rtc_set_alarm, |
419 | .ioctl = ds1511_rtc_ioctl, | 420 | .alarm_irq_enable = ds1511_rtc_alarm_irq_enable, |
421 | .update_irq_enable = ds1511_rtc_update_irq_enable, | ||
420 | }; | 422 | }; |
421 | 423 | ||
422 | static ssize_t | 424 | static ssize_t |
@@ -492,29 +494,23 @@ ds1511_rtc_probe(struct platform_device *pdev) | |||
492 | { | 494 | { |
493 | struct rtc_device *rtc; | 495 | struct rtc_device *rtc; |
494 | struct resource *res; | 496 | struct resource *res; |
495 | struct rtc_plat_data *pdata = NULL; | 497 | struct rtc_plat_data *pdata; |
496 | int ret = 0; | 498 | int ret = 0; |
497 | 499 | ||
498 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 500 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
499 | if (!res) { | 501 | if (!res) { |
500 | return -ENODEV; | 502 | return -ENODEV; |
501 | } | 503 | } |
502 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 504 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
503 | if (!pdata) { | 505 | if (!pdata) |
504 | return -ENOMEM; | 506 | return -ENOMEM; |
505 | } | ||
506 | pdata->size = res->end - res->start + 1; | 507 | pdata->size = res->end - res->start + 1; |
507 | if (!request_mem_region(res->start, pdata->size, pdev->name)) { | 508 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, |
508 | ret = -EBUSY; | 509 | pdev->name)) |
509 | goto out; | 510 | return -EBUSY; |
510 | } | 511 | ds1511_base = devm_ioremap(&pdev->dev, res->start, pdata->size); |
511 | pdata->baseaddr = res->start; | 512 | if (!ds1511_base) |
512 | pdata->size = pdata->size; | 513 | return -ENOMEM; |
513 | ds1511_base = ioremap(pdata->baseaddr, pdata->size); | ||
514 | if (!ds1511_base) { | ||
515 | ret = -ENOMEM; | ||
516 | goto out; | ||
517 | } | ||
518 | pdata->ioaddr = ds1511_base; | 514 | pdata->ioaddr = ds1511_base; |
519 | pdata->irq = platform_get_irq(pdev, 0); | 515 | pdata->irq = platform_get_irq(pdev, 0); |
520 | 516 | ||
@@ -540,13 +536,15 @@ ds1511_rtc_probe(struct platform_device *pdev) | |||
540 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 536 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
541 | } | 537 | } |
542 | 538 | ||
539 | spin_lock_init(&pdata->lock); | ||
540 | platform_set_drvdata(pdev, pdata); | ||
543 | /* | 541 | /* |
544 | * if the platform has an interrupt in mind for this device, | 542 | * if the platform has an interrupt in mind for this device, |
545 | * then by all means, set it | 543 | * then by all means, set it |
546 | */ | 544 | */ |
547 | if (pdata->irq > 0) { | 545 | if (pdata->irq > 0) { |
548 | rtc_read(RTC_CMD1); | 546 | rtc_read(RTC_CMD1); |
549 | if (request_irq(pdata->irq, ds1511_interrupt, | 547 | if (devm_request_irq(&pdev->dev, pdata->irq, ds1511_interrupt, |
550 | IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { | 548 | IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { |
551 | 549 | ||
552 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 550 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
@@ -556,33 +554,13 @@ ds1511_rtc_probe(struct platform_device *pdev) | |||
556 | 554 | ||
557 | rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops, | 555 | rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops, |
558 | THIS_MODULE); | 556 | THIS_MODULE); |
559 | if (IS_ERR(rtc)) { | 557 | if (IS_ERR(rtc)) |
560 | ret = PTR_ERR(rtc); | 558 | return PTR_ERR(rtc); |
561 | goto out; | ||
562 | } | ||
563 | pdata->rtc = rtc; | 559 | pdata->rtc = rtc; |
564 | platform_set_drvdata(pdev, pdata); | 560 | |
565 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | 561 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); |
566 | if (ret) { | 562 | if (ret) |
567 | goto out; | ||
568 | } | ||
569 | return 0; | ||
570 | out: | ||
571 | if (pdata->rtc) { | ||
572 | rtc_device_unregister(pdata->rtc); | 563 | rtc_device_unregister(pdata->rtc); |
573 | } | ||
574 | if (pdata->irq > 0) { | ||
575 | free_irq(pdata->irq, pdev); | ||
576 | } | ||
577 | if (ds1511_base) { | ||
578 | iounmap(ds1511_base); | ||
579 | ds1511_base = NULL; | ||
580 | } | ||
581 | if (pdata->baseaddr) { | ||
582 | release_mem_region(pdata->baseaddr, pdata->size); | ||
583 | } | ||
584 | |||
585 | kfree(pdata); | ||
586 | return ret; | 564 | return ret; |
587 | } | 565 | } |
588 | 566 | ||
@@ -593,19 +571,13 @@ ds1511_rtc_remove(struct platform_device *pdev) | |||
593 | 571 | ||
594 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | 572 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); |
595 | rtc_device_unregister(pdata->rtc); | 573 | rtc_device_unregister(pdata->rtc); |
596 | pdata->rtc = NULL; | ||
597 | if (pdata->irq > 0) { | 574 | if (pdata->irq > 0) { |
598 | /* | 575 | /* |
599 | * disable the alarm interrupt | 576 | * disable the alarm interrupt |
600 | */ | 577 | */ |
601 | rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD); | 578 | rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD); |
602 | rtc_read(RTC_CMD1); | 579 | rtc_read(RTC_CMD1); |
603 | free_irq(pdata->irq, pdev); | ||
604 | } | 580 | } |
605 | iounmap(pdata->ioaddr); | ||
606 | ds1511_base = NULL; | ||
607 | release_mem_region(pdata->baseaddr, pdata->size); | ||
608 | kfree(pdata); | ||
609 | return 0; | 581 | return 0; |
610 | } | 582 | } |
611 | 583 | ||
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 717288527c6b..ed1ef7c9cc06 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | 20 | ||
21 | #define DRV_VERSION "0.2" | 21 | #define DRV_VERSION "0.3" |
22 | 22 | ||
23 | #define RTC_REG_SIZE 0x2000 | 23 | #define RTC_REG_SIZE 0x2000 |
24 | #define RTC_OFFSET 0x1ff0 | 24 | #define RTC_OFFSET 0x1ff0 |
@@ -61,7 +61,6 @@ | |||
61 | struct rtc_plat_data { | 61 | struct rtc_plat_data { |
62 | struct rtc_device *rtc; | 62 | struct rtc_device *rtc; |
63 | void __iomem *ioaddr; | 63 | void __iomem *ioaddr; |
64 | resource_size_t baseaddr; | ||
65 | unsigned long last_jiffies; | 64 | unsigned long last_jiffies; |
66 | int irq; | 65 | int irq; |
67 | unsigned int irqen; | 66 | unsigned int irqen; |
@@ -69,6 +68,7 @@ struct rtc_plat_data { | |||
69 | int alrm_min; | 68 | int alrm_min; |
70 | int alrm_hour; | 69 | int alrm_hour; |
71 | int alrm_mday; | 70 | int alrm_mday; |
71 | spinlock_t lock; | ||
72 | }; | 72 | }; |
73 | 73 | ||
74 | static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) | 74 | static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -139,7 +139,7 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
139 | void __iomem *ioaddr = pdata->ioaddr; | 139 | void __iomem *ioaddr = pdata->ioaddr; |
140 | unsigned long flags; | 140 | unsigned long flags; |
141 | 141 | ||
142 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); | 142 | spin_lock_irqsave(&pdata->lock, flags); |
143 | writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | 143 | writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? |
144 | 0x80 : bin2bcd(pdata->alrm_mday), | 144 | 0x80 : bin2bcd(pdata->alrm_mday), |
145 | ioaddr + RTC_DATE_ALARM); | 145 | ioaddr + RTC_DATE_ALARM); |
@@ -154,7 +154,7 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
154 | ioaddr + RTC_SECONDS_ALARM); | 154 | ioaddr + RTC_SECONDS_ALARM); |
155 | writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS); | 155 | writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS); |
156 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ | 156 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ |
157 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); | 157 | spin_unlock_irqrestore(&pdata->lock, flags); |
158 | } | 158 | } |
159 | 159 | ||
160 | static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 160 | static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
@@ -194,64 +194,69 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id) | |||
194 | struct platform_device *pdev = dev_id; | 194 | struct platform_device *pdev = dev_id; |
195 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 195 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
196 | void __iomem *ioaddr = pdata->ioaddr; | 196 | void __iomem *ioaddr = pdata->ioaddr; |
197 | unsigned long events = RTC_IRQF; | 197 | unsigned long events = 0; |
198 | 198 | ||
199 | spin_lock(&pdata->lock); | ||
199 | /* read and clear interrupt */ | 200 | /* read and clear interrupt */ |
200 | if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF)) | 201 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF) { |
201 | return IRQ_NONE; | 202 | events = RTC_IRQF; |
202 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) | 203 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) |
203 | events |= RTC_UF; | 204 | events |= RTC_UF; |
204 | else | 205 | else |
205 | events |= RTC_AF; | 206 | events |= RTC_AF; |
206 | rtc_update_irq(pdata->rtc, 1, events); | 207 | if (likely(pdata->rtc)) |
207 | return IRQ_HANDLED; | 208 | rtc_update_irq(pdata->rtc, 1, events); |
209 | } | ||
210 | spin_unlock(&pdata->lock); | ||
211 | return events ? IRQ_HANDLED : IRQ_NONE; | ||
208 | } | 212 | } |
209 | 213 | ||
210 | static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, | 214 | static int ds1553_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
211 | unsigned long arg) | ||
212 | { | 215 | { |
213 | struct platform_device *pdev = to_platform_device(dev); | 216 | struct platform_device *pdev = to_platform_device(dev); |
214 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 217 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
215 | 218 | ||
216 | if (pdata->irq <= 0) | 219 | if (pdata->irq <= 0) |
217 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | 220 | return -EINVAL; |
218 | switch (cmd) { | 221 | if (enabled) |
219 | case RTC_AIE_OFF: | ||
220 | pdata->irqen &= ~RTC_AF; | ||
221 | ds1553_rtc_update_alarm(pdata); | ||
222 | break; | ||
223 | case RTC_AIE_ON: | ||
224 | pdata->irqen |= RTC_AF; | 222 | pdata->irqen |= RTC_AF; |
225 | ds1553_rtc_update_alarm(pdata); | 223 | else |
226 | break; | 224 | pdata->irqen &= ~RTC_AF; |
227 | case RTC_UIE_OFF: | 225 | ds1553_rtc_update_alarm(pdata); |
228 | pdata->irqen &= ~RTC_UF; | 226 | return 0; |
229 | ds1553_rtc_update_alarm(pdata); | 227 | } |
230 | break; | 228 | |
231 | case RTC_UIE_ON: | 229 | static int ds1553_rtc_update_irq_enable(struct device *dev, |
230 | unsigned int enabled) | ||
231 | { | ||
232 | struct platform_device *pdev = to_platform_device(dev); | ||
233 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
234 | |||
235 | if (pdata->irq <= 0) | ||
236 | return -EINVAL; | ||
237 | if (enabled) | ||
232 | pdata->irqen |= RTC_UF; | 238 | pdata->irqen |= RTC_UF; |
233 | ds1553_rtc_update_alarm(pdata); | 239 | else |
234 | break; | 240 | pdata->irqen &= ~RTC_UF; |
235 | default: | 241 | ds1553_rtc_update_alarm(pdata); |
236 | return -ENOIOCTLCMD; | ||
237 | } | ||
238 | return 0; | 242 | return 0; |
239 | } | 243 | } |
240 | 244 | ||
241 | static const struct rtc_class_ops ds1553_rtc_ops = { | 245 | static const struct rtc_class_ops ds1553_rtc_ops = { |
242 | .read_time = ds1553_rtc_read_time, | 246 | .read_time = ds1553_rtc_read_time, |
243 | .set_time = ds1553_rtc_set_time, | 247 | .set_time = ds1553_rtc_set_time, |
244 | .read_alarm = ds1553_rtc_read_alarm, | 248 | .read_alarm = ds1553_rtc_read_alarm, |
245 | .set_alarm = ds1553_rtc_set_alarm, | 249 | .set_alarm = ds1553_rtc_set_alarm, |
246 | .ioctl = ds1553_rtc_ioctl, | 250 | .alarm_irq_enable = ds1553_rtc_alarm_irq_enable, |
251 | .update_irq_enable = ds1553_rtc_update_irq_enable, | ||
247 | }; | 252 | }; |
248 | 253 | ||
249 | static ssize_t ds1553_nvram_read(struct kobject *kobj, | 254 | static ssize_t ds1553_nvram_read(struct kobject *kobj, |
250 | struct bin_attribute *bin_attr, | 255 | struct bin_attribute *bin_attr, |
251 | char *buf, loff_t pos, size_t size) | 256 | char *buf, loff_t pos, size_t size) |
252 | { | 257 | { |
253 | struct platform_device *pdev = | 258 | struct device *dev = container_of(kobj, struct device, kobj); |
254 | to_platform_device(container_of(kobj, struct device, kobj)); | 259 | struct platform_device *pdev = to_platform_device(dev); |
255 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 260 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
256 | void __iomem *ioaddr = pdata->ioaddr; | 261 | void __iomem *ioaddr = pdata->ioaddr; |
257 | ssize_t count; | 262 | ssize_t count; |
@@ -265,8 +270,8 @@ static ssize_t ds1553_nvram_write(struct kobject *kobj, | |||
265 | struct bin_attribute *bin_attr, | 270 | struct bin_attribute *bin_attr, |
266 | char *buf, loff_t pos, size_t size) | 271 | char *buf, loff_t pos, size_t size) |
267 | { | 272 | { |
268 | struct platform_device *pdev = | 273 | struct device *dev = container_of(kobj, struct device, kobj); |
269 | to_platform_device(container_of(kobj, struct device, kobj)); | 274 | struct platform_device *pdev = to_platform_device(dev); |
270 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 275 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
271 | void __iomem *ioaddr = pdata->ioaddr; | 276 | void __iomem *ioaddr = pdata->ioaddr; |
272 | ssize_t count; | 277 | ssize_t count; |
@@ -291,26 +296,23 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev) | |||
291 | struct rtc_device *rtc; | 296 | struct rtc_device *rtc; |
292 | struct resource *res; | 297 | struct resource *res; |
293 | unsigned int cen, sec; | 298 | unsigned int cen, sec; |
294 | struct rtc_plat_data *pdata = NULL; | 299 | struct rtc_plat_data *pdata; |
295 | void __iomem *ioaddr = NULL; | 300 | void __iomem *ioaddr; |
296 | int ret = 0; | 301 | int ret = 0; |
297 | 302 | ||
298 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 303 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
299 | if (!res) | 304 | if (!res) |
300 | return -ENODEV; | 305 | return -ENODEV; |
301 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 306 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
302 | if (!pdata) | 307 | if (!pdata) |
303 | return -ENOMEM; | 308 | return -ENOMEM; |
304 | if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { | 309 | if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE, |
305 | ret = -EBUSY; | 310 | pdev->name)) |
306 | goto out; | 311 | return -EBUSY; |
307 | } | 312 | |
308 | pdata->baseaddr = res->start; | 313 | ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE); |
309 | ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); | 314 | if (!ioaddr) |
310 | if (!ioaddr) { | 315 | return -ENOMEM; |
311 | ret = -ENOMEM; | ||
312 | goto out; | ||
313 | } | ||
314 | pdata->ioaddr = ioaddr; | 316 | pdata->ioaddr = ioaddr; |
315 | pdata->irq = platform_get_irq(pdev, 0); | 317 | pdata->irq = platform_get_irq(pdev, 0); |
316 | 318 | ||
@@ -326,9 +328,13 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev) | |||
326 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF) | 328 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF) |
327 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 329 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
328 | 330 | ||
331 | spin_lock_init(&pdata->lock); | ||
332 | pdata->last_jiffies = jiffies; | ||
333 | platform_set_drvdata(pdev, pdata); | ||
329 | if (pdata->irq > 0) { | 334 | if (pdata->irq > 0) { |
330 | writeb(0, ioaddr + RTC_INTERRUPTS); | 335 | writeb(0, ioaddr + RTC_INTERRUPTS); |
331 | if (request_irq(pdata->irq, ds1553_rtc_interrupt, | 336 | if (devm_request_irq(&pdev->dev, pdata->irq, |
337 | ds1553_rtc_interrupt, | ||
332 | IRQF_DISABLED, pdev->name, pdev) < 0) { | 338 | IRQF_DISABLED, pdev->name, pdev) < 0) { |
333 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 339 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
334 | pdata->irq = 0; | 340 | pdata->irq = 0; |
@@ -337,27 +343,13 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev) | |||
337 | 343 | ||
338 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 344 | rtc = rtc_device_register(pdev->name, &pdev->dev, |
339 | &ds1553_rtc_ops, THIS_MODULE); | 345 | &ds1553_rtc_ops, THIS_MODULE); |
340 | if (IS_ERR(rtc)) { | 346 | if (IS_ERR(rtc)) |
341 | ret = PTR_ERR(rtc); | 347 | return PTR_ERR(rtc); |
342 | goto out; | ||
343 | } | ||
344 | pdata->rtc = rtc; | 348 | pdata->rtc = rtc; |
345 | pdata->last_jiffies = jiffies; | 349 | |
346 | platform_set_drvdata(pdev, pdata); | ||
347 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); | 350 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); |
348 | if (ret) | 351 | if (ret) |
349 | goto out; | 352 | rtc_device_unregister(rtc); |
350 | return 0; | ||
351 | out: | ||
352 | if (pdata->rtc) | ||
353 | rtc_device_unregister(pdata->rtc); | ||
354 | if (pdata->irq > 0) | ||
355 | free_irq(pdata->irq, pdev); | ||
356 | if (ioaddr) | ||
357 | iounmap(ioaddr); | ||
358 | if (pdata->baseaddr) | ||
359 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
360 | kfree(pdata); | ||
361 | return ret; | 353 | return ret; |
362 | } | 354 | } |
363 | 355 | ||
@@ -367,13 +359,8 @@ static int __devexit ds1553_rtc_remove(struct platform_device *pdev) | |||
367 | 359 | ||
368 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); | 360 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); |
369 | rtc_device_unregister(pdata->rtc); | 361 | rtc_device_unregister(pdata->rtc); |
370 | if (pdata->irq > 0) { | 362 | if (pdata->irq > 0) |
371 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); | 363 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); |
372 | free_irq(pdata->irq, pdev); | ||
373 | } | ||
374 | iounmap(pdata->ioaddr); | ||
375 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
376 | kfree(pdata); | ||
377 | return 0; | 364 | return 0; |
378 | } | 365 | } |
379 | 366 | ||
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 09249459e9a4..a1273360a44e 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | 23 | ||
24 | #define DRV_VERSION "0.3" | 24 | #define DRV_VERSION "0.4" |
25 | 25 | ||
26 | #define RTC_SIZE 8 | 26 | #define RTC_SIZE 8 |
27 | 27 | ||
@@ -55,7 +55,6 @@ struct rtc_plat_data { | |||
55 | void __iomem *ioaddr_rtc; | 55 | void __iomem *ioaddr_rtc; |
56 | size_t size_nvram; | 56 | size_t size_nvram; |
57 | size_t size; | 57 | size_t size; |
58 | resource_size_t baseaddr; | ||
59 | unsigned long last_jiffies; | 58 | unsigned long last_jiffies; |
60 | struct bin_attribute nvram_attr; | 59 | struct bin_attribute nvram_attr; |
61 | }; | 60 | }; |
@@ -132,8 +131,8 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, | |||
132 | struct bin_attribute *bin_attr, | 131 | struct bin_attribute *bin_attr, |
133 | char *buf, loff_t pos, size_t size) | 132 | char *buf, loff_t pos, size_t size) |
134 | { | 133 | { |
135 | struct platform_device *pdev = | 134 | struct device *dev = container_of(kobj, struct device, kobj); |
136 | to_platform_device(container_of(kobj, struct device, kobj)); | 135 | struct platform_device *pdev = to_platform_device(dev); |
137 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 136 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
138 | void __iomem *ioaddr = pdata->ioaddr_nvram; | 137 | void __iomem *ioaddr = pdata->ioaddr_nvram; |
139 | ssize_t count; | 138 | ssize_t count; |
@@ -147,8 +146,8 @@ static ssize_t ds1742_nvram_write(struct kobject *kobj, | |||
147 | struct bin_attribute *bin_attr, | 146 | struct bin_attribute *bin_attr, |
148 | char *buf, loff_t pos, size_t size) | 147 | char *buf, loff_t pos, size_t size) |
149 | { | 148 | { |
150 | struct platform_device *pdev = | 149 | struct device *dev = container_of(kobj, struct device, kobj); |
151 | to_platform_device(container_of(kobj, struct device, kobj)); | 150 | struct platform_device *pdev = to_platform_device(dev); |
152 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 151 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
153 | void __iomem *ioaddr = pdata->ioaddr_nvram; | 152 | void __iomem *ioaddr = pdata->ioaddr_nvram; |
154 | ssize_t count; | 153 | ssize_t count; |
@@ -163,27 +162,24 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev) | |||
163 | struct rtc_device *rtc; | 162 | struct rtc_device *rtc; |
164 | struct resource *res; | 163 | struct resource *res; |
165 | unsigned int cen, sec; | 164 | unsigned int cen, sec; |
166 | struct rtc_plat_data *pdata = NULL; | 165 | struct rtc_plat_data *pdata; |
167 | void __iomem *ioaddr = NULL; | 166 | void __iomem *ioaddr; |
168 | int ret = 0; | 167 | int ret = 0; |
169 | 168 | ||
170 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 169 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
171 | if (!res) | 170 | if (!res) |
172 | return -ENODEV; | 171 | return -ENODEV; |
173 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 172 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
174 | if (!pdata) | 173 | if (!pdata) |
175 | return -ENOMEM; | 174 | return -ENOMEM; |
176 | pdata->size = res->end - res->start + 1; | 175 | pdata->size = res->end - res->start + 1; |
177 | if (!request_mem_region(res->start, pdata->size, pdev->name)) { | 176 | if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size, |
178 | ret = -EBUSY; | 177 | pdev->name)) |
179 | goto out; | 178 | return -EBUSY; |
180 | } | 179 | ioaddr = devm_ioremap(&pdev->dev, res->start, pdata->size); |
181 | pdata->baseaddr = res->start; | 180 | if (!ioaddr) |
182 | ioaddr = ioremap(pdata->baseaddr, pdata->size); | 181 | return -ENOMEM; |
183 | if (!ioaddr) { | 182 | |
184 | ret = -ENOMEM; | ||
185 | goto out; | ||
186 | } | ||
187 | pdata->ioaddr_nvram = ioaddr; | 183 | pdata->ioaddr_nvram = ioaddr; |
188 | pdata->size_nvram = pdata->size - RTC_SIZE; | 184 | pdata->size_nvram = pdata->size - RTC_SIZE; |
189 | pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; | 185 | pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; |
@@ -207,31 +203,19 @@ static int __devinit ds1742_rtc_probe(struct platform_device *pdev) | |||
207 | if (!(readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG)) | 203 | if (!(readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG)) |
208 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 204 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
209 | 205 | ||
206 | pdata->last_jiffies = jiffies; | ||
207 | platform_set_drvdata(pdev, pdata); | ||
210 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 208 | rtc = rtc_device_register(pdev->name, &pdev->dev, |
211 | &ds1742_rtc_ops, THIS_MODULE); | 209 | &ds1742_rtc_ops, THIS_MODULE); |
212 | if (IS_ERR(rtc)) { | 210 | if (IS_ERR(rtc)) |
213 | ret = PTR_ERR(rtc); | 211 | return PTR_ERR(rtc); |
214 | goto out; | ||
215 | } | ||
216 | pdata->rtc = rtc; | 212 | pdata->rtc = rtc; |
217 | pdata->last_jiffies = jiffies; | ||
218 | platform_set_drvdata(pdev, pdata); | ||
219 | 213 | ||
220 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); | 214 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); |
221 | if (ret) { | 215 | if (ret) { |
222 | dev_err(&pdev->dev, "creating nvram file in sysfs failed\n"); | 216 | dev_err(&pdev->dev, "creating nvram file in sysfs failed\n"); |
223 | goto out; | 217 | rtc_device_unregister(rtc); |
224 | } | 218 | } |
225 | |||
226 | return 0; | ||
227 | out: | ||
228 | if (pdata->rtc) | ||
229 | rtc_device_unregister(pdata->rtc); | ||
230 | if (pdata->ioaddr_nvram) | ||
231 | iounmap(pdata->ioaddr_nvram); | ||
232 | if (pdata->baseaddr) | ||
233 | release_mem_region(pdata->baseaddr, pdata->size); | ||
234 | kfree(pdata); | ||
235 | return ret; | 219 | return ret; |
236 | } | 220 | } |
237 | 221 | ||
@@ -241,9 +225,6 @@ static int __devexit ds1742_rtc_remove(struct platform_device *pdev) | |||
241 | 225 | ||
242 | sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); | 226 | sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); |
243 | rtc_device_unregister(pdata->rtc); | 227 | rtc_device_unregister(pdata->rtc); |
244 | iounmap(pdata->ioaddr_nvram); | ||
245 | release_mem_region(pdata->baseaddr, pdata->size); | ||
246 | kfree(pdata); | ||
247 | return 0; | 228 | return 0; |
248 | } | 229 | } |
249 | 230 | ||
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index 0b2197559940..8cb5b8959e5b 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c | |||
@@ -142,7 +142,6 @@ static const struct rtc_class_ops m48t35_ops = { | |||
142 | 142 | ||
143 | static int __devinit m48t35_probe(struct platform_device *pdev) | 143 | static int __devinit m48t35_probe(struct platform_device *pdev) |
144 | { | 144 | { |
145 | struct rtc_device *rtc; | ||
146 | struct resource *res; | 145 | struct resource *res; |
147 | struct m48t35_priv *priv; | 146 | struct m48t35_priv *priv; |
148 | int ret = 0; | 147 | int ret = 0; |
@@ -171,20 +170,21 @@ static int __devinit m48t35_probe(struct platform_device *pdev) | |||
171 | ret = -ENOMEM; | 170 | ret = -ENOMEM; |
172 | goto out; | 171 | goto out; |
173 | } | 172 | } |
173 | |||
174 | spin_lock_init(&priv->lock); | 174 | spin_lock_init(&priv->lock); |
175 | rtc = rtc_device_register("m48t35", &pdev->dev, | 175 | |
176 | platform_set_drvdata(pdev, priv); | ||
177 | |||
178 | priv->rtc = rtc_device_register("m48t35", &pdev->dev, | ||
176 | &m48t35_ops, THIS_MODULE); | 179 | &m48t35_ops, THIS_MODULE); |
177 | if (IS_ERR(rtc)) { | 180 | if (IS_ERR(priv->rtc)) { |
178 | ret = PTR_ERR(rtc); | 181 | ret = PTR_ERR(priv->rtc); |
179 | goto out; | 182 | goto out; |
180 | } | 183 | } |
181 | priv->rtc = rtc; | 184 | |
182 | platform_set_drvdata(pdev, priv); | ||
183 | return 0; | 185 | return 0; |
184 | 186 | ||
185 | out: | 187 | out: |
186 | if (priv->rtc) | ||
187 | rtc_device_unregister(priv->rtc); | ||
188 | if (priv->reg) | 188 | if (priv->reg) |
189 | iounmap(priv->reg); | 189 | iounmap(priv->reg); |
190 | if (priv->baseaddr) | 190 | if (priv->baseaddr) |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 33921a6b1707..ede43b846859 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
@@ -481,6 +481,9 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
481 | goto out; | 481 | goto out; |
482 | } | 482 | } |
483 | 483 | ||
484 | spin_lock_init(&m48t59->lock); | ||
485 | platform_set_drvdata(pdev, m48t59); | ||
486 | |||
484 | m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE); | 487 | m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE); |
485 | if (IS_ERR(m48t59->rtc)) { | 488 | if (IS_ERR(m48t59->rtc)) { |
486 | ret = PTR_ERR(m48t59->rtc); | 489 | ret = PTR_ERR(m48t59->rtc); |
@@ -490,16 +493,14 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
490 | m48t59_nvram_attr.size = pdata->offset; | 493 | m48t59_nvram_attr.size = pdata->offset; |
491 | 494 | ||
492 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 495 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
493 | if (ret) | 496 | if (ret) { |
497 | rtc_device_unregister(m48t59->rtc); | ||
494 | goto out; | 498 | goto out; |
499 | } | ||
495 | 500 | ||
496 | spin_lock_init(&m48t59->lock); | ||
497 | platform_set_drvdata(pdev, m48t59); | ||
498 | return 0; | 501 | return 0; |
499 | 502 | ||
500 | out: | 503 | out: |
501 | if (!IS_ERR(m48t59->rtc)) | ||
502 | rtc_device_unregister(m48t59->rtc); | ||
503 | if (m48t59->irq != NO_IRQ) | 504 | if (m48t59->irq != NO_IRQ) |
504 | free_irq(m48t59->irq, &pdev->dev); | 505 | free_irq(m48t59->irq, &pdev->dev); |
505 | if (m48t59->ioaddr) | 506 | if (m48t59->ioaddr) |
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c new file mode 100644 index 000000000000..850f983c039c --- /dev/null +++ b/drivers/rtc/rtc-mc13783.c | |||
@@ -0,0 +1,262 @@ | |||
1 | /* | ||
2 | * Real Time Clock driver for Freescale MC13783 PMIC | ||
3 | * | ||
4 | * (C) 2009 Sascha Hauer, Pengutronix | ||
5 | * (C) 2009 Uwe Kleine-Koenig, Pengutronix | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/mfd/mc13783.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/rtc.h> | ||
17 | |||
18 | #define DRIVER_NAME "mc13783-rtc" | ||
19 | |||
20 | #define MC13783_RTCTOD 20 | ||
21 | #define MC13783_RTCTODA 21 | ||
22 | #define MC13783_RTCDAY 22 | ||
23 | #define MC13783_RTCDAYA 23 | ||
24 | |||
25 | struct mc13783_rtc { | ||
26 | struct rtc_device *rtc; | ||
27 | struct mc13783 *mc13783; | ||
28 | int valid; | ||
29 | }; | ||
30 | |||
31 | static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
32 | { | ||
33 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
34 | unsigned int seconds, days1, days2; | ||
35 | unsigned long s1970; | ||
36 | int ret; | ||
37 | |||
38 | mc13783_lock(priv->mc13783); | ||
39 | |||
40 | if (!priv->valid) { | ||
41 | ret = -ENODATA; | ||
42 | goto out; | ||
43 | } | ||
44 | |||
45 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days1); | ||
46 | if (unlikely(ret)) | ||
47 | goto out; | ||
48 | |||
49 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTOD, &seconds); | ||
50 | if (unlikely(ret)) | ||
51 | goto out; | ||
52 | |||
53 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days2); | ||
54 | out: | ||
55 | mc13783_unlock(priv->mc13783); | ||
56 | |||
57 | if (ret) | ||
58 | return ret; | ||
59 | |||
60 | if (days2 == days1 + 1) { | ||
61 | if (seconds >= 86400 / 2) | ||
62 | days2 = days1; | ||
63 | else | ||
64 | days1 = days2; | ||
65 | } | ||
66 | |||
67 | if (days1 != days2) | ||
68 | return -EIO; | ||
69 | |||
70 | s1970 = days1 * 86400 + seconds; | ||
71 | |||
72 | rtc_time_to_tm(s1970, tm); | ||
73 | |||
74 | return rtc_valid_tm(tm); | ||
75 | } | ||
76 | |||
77 | static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
78 | { | ||
79 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
80 | unsigned int seconds, days; | ||
81 | int ret; | ||
82 | |||
83 | seconds = secs % 86400; | ||
84 | days = secs / 86400; | ||
85 | |||
86 | mc13783_lock(priv->mc13783); | ||
87 | |||
88 | /* | ||
89 | * first write seconds=0 to prevent a day switch between writing days | ||
90 | * and seconds below | ||
91 | */ | ||
92 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0); | ||
93 | if (unlikely(ret)) | ||
94 | goto out; | ||
95 | |||
96 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAY, days); | ||
97 | if (unlikely(ret)) | ||
98 | goto out; | ||
99 | |||
100 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, seconds); | ||
101 | if (unlikely(ret)) | ||
102 | goto out; | ||
103 | |||
104 | ret = mc13783_ackirq(priv->mc13783, MC13783_IRQ_RTCRST); | ||
105 | if (unlikely(ret)) | ||
106 | goto out; | ||
107 | |||
108 | ret = mc13783_unmask(priv->mc13783, MC13783_IRQ_RTCRST); | ||
109 | out: | ||
110 | priv->valid = !ret; | ||
111 | |||
112 | mc13783_unlock(priv->mc13783); | ||
113 | |||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) | ||
118 | { | ||
119 | struct mc13783_rtc *priv = dev; | ||
120 | struct mc13783 *mc13783 = priv->mc13783; | ||
121 | |||
122 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | ||
123 | |||
124 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | ||
125 | |||
126 | mc13783_ackirq(mc13783, irq); | ||
127 | |||
128 | return IRQ_HANDLED; | ||
129 | } | ||
130 | |||
131 | static int mc13783_rtc_update_irq_enable(struct device *dev, | ||
132 | unsigned int enabled) | ||
133 | { | ||
134 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
135 | int ret = -ENODATA; | ||
136 | |||
137 | mc13783_lock(priv->mc13783); | ||
138 | if (!priv->valid) | ||
139 | goto out; | ||
140 | |||
141 | ret = (enabled ? mc13783_unmask : mc13783_mask)(priv->mc13783, | ||
142 | MC13783_IRQ_1HZ); | ||
143 | out: | ||
144 | mc13783_unlock(priv->mc13783); | ||
145 | |||
146 | return ret; | ||
147 | } | ||
148 | |||
149 | static const struct rtc_class_ops mc13783_rtc_ops = { | ||
150 | .read_time = mc13783_rtc_read_time, | ||
151 | .set_mmss = mc13783_rtc_set_mmss, | ||
152 | .update_irq_enable = mc13783_rtc_update_irq_enable, | ||
153 | }; | ||
154 | |||
155 | static irqreturn_t mc13783_rtc_reset_handler(int irq, void *dev) | ||
156 | { | ||
157 | struct mc13783_rtc *priv = dev; | ||
158 | struct mc13783 *mc13783 = priv->mc13783; | ||
159 | |||
160 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | ||
161 | priv->valid = 0; | ||
162 | |||
163 | mc13783_mask(mc13783, irq); | ||
164 | |||
165 | return IRQ_HANDLED; | ||
166 | } | ||
167 | |||
168 | static int __devinit mc13783_rtc_probe(struct platform_device *pdev) | ||
169 | { | ||
170 | int ret; | ||
171 | struct mc13783_rtc *priv; | ||
172 | |||
173 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
174 | if (!priv) | ||
175 | return -ENOMEM; | ||
176 | |||
177 | priv->mc13783 = dev_get_drvdata(pdev->dev.parent); | ||
178 | platform_set_drvdata(pdev, priv); | ||
179 | |||
180 | priv->valid = 1; | ||
181 | |||
182 | mc13783_lock(priv->mc13783); | ||
183 | |||
184 | ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST, | ||
185 | mc13783_rtc_reset_handler, DRIVER_NAME, priv); | ||
186 | if (ret) | ||
187 | goto err_reset_irq_request; | ||
188 | |||
189 | ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ, | ||
190 | mc13783_rtc_update_handler, DRIVER_NAME, priv); | ||
191 | if (ret) | ||
192 | goto err_update_irq_request; | ||
193 | |||
194 | mc13783_unlock(priv->mc13783); | ||
195 | |||
196 | priv->rtc = rtc_device_register(pdev->name, | ||
197 | &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); | ||
198 | |||
199 | if (IS_ERR(priv->rtc)) { | ||
200 | ret = PTR_ERR(priv->rtc); | ||
201 | |||
202 | mc13783_lock(priv->mc13783); | ||
203 | |||
204 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | ||
205 | err_update_irq_request: | ||
206 | |||
207 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | ||
208 | err_reset_irq_request: | ||
209 | |||
210 | mc13783_unlock(priv->mc13783); | ||
211 | |||
212 | platform_set_drvdata(pdev, NULL); | ||
213 | kfree(priv); | ||
214 | } | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | static int __devexit mc13783_rtc_remove(struct platform_device *pdev) | ||
220 | { | ||
221 | struct mc13783_rtc *priv = platform_get_drvdata(pdev); | ||
222 | |||
223 | rtc_device_unregister(priv->rtc); | ||
224 | |||
225 | mc13783_lock(priv->mc13783); | ||
226 | |||
227 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | ||
228 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | ||
229 | |||
230 | mc13783_unlock(priv->mc13783); | ||
231 | |||
232 | platform_set_drvdata(pdev, NULL); | ||
233 | |||
234 | kfree(priv); | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static struct platform_driver mc13783_rtc_driver = { | ||
240 | .remove = __devexit_p(mc13783_rtc_remove), | ||
241 | .driver = { | ||
242 | .name = DRIVER_NAME, | ||
243 | .owner = THIS_MODULE, | ||
244 | }, | ||
245 | }; | ||
246 | |||
247 | static int __init mc13783_rtc_init(void) | ||
248 | { | ||
249 | return platform_driver_probe(&mc13783_rtc_driver, &mc13783_rtc_probe); | ||
250 | } | ||
251 | module_init(mc13783_rtc_init); | ||
252 | |||
253 | static void __exit mc13783_rtc_exit(void) | ||
254 | { | ||
255 | platform_driver_unregister(&mc13783_rtc_driver); | ||
256 | } | ||
257 | module_exit(mc13783_rtc_exit); | ||
258 | |||
259 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
260 | MODULE_DESCRIPTION("RTC driver for Freescale MC13783 PMIC"); | ||
261 | MODULE_LICENSE("GPL v2"); | ||
262 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index e0263d2005ee..dc052ce6e63a 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c | |||
@@ -27,10 +27,17 @@ | |||
27 | #define RTC_MONTH_OFFS 8 | 27 | #define RTC_MONTH_OFFS 8 |
28 | #define RTC_YEAR_OFFS 16 | 28 | #define RTC_YEAR_OFFS 16 |
29 | 29 | ||
30 | #define RTC_ALARM_TIME_REG_OFFS 8 | ||
31 | #define RTC_ALARM_DATE_REG_OFFS 0xc | ||
32 | #define RTC_ALARM_VALID (1 << 7) | ||
33 | |||
34 | #define RTC_ALARM_INTERRUPT_MASK_REG_OFFS 0x10 | ||
35 | #define RTC_ALARM_INTERRUPT_CASUE_REG_OFFS 0x14 | ||
30 | 36 | ||
31 | struct rtc_plat_data { | 37 | struct rtc_plat_data { |
32 | struct rtc_device *rtc; | 38 | struct rtc_device *rtc; |
33 | void __iomem *ioaddr; | 39 | void __iomem *ioaddr; |
40 | int irq; | ||
34 | }; | 41 | }; |
35 | 42 | ||
36 | static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm) | 43 | static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -84,12 +91,134 @@ static int mv_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
84 | return rtc_valid_tm(tm); | 91 | return rtc_valid_tm(tm); |
85 | } | 92 | } |
86 | 93 | ||
94 | static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
95 | { | ||
96 | struct rtc_plat_data *pdata = dev_get_drvdata(dev); | ||
97 | void __iomem *ioaddr = pdata->ioaddr; | ||
98 | u32 rtc_time, rtc_date; | ||
99 | unsigned int year, month, day, hour, minute, second, wday; | ||
100 | |||
101 | rtc_time = readl(ioaddr + RTC_ALARM_TIME_REG_OFFS); | ||
102 | rtc_date = readl(ioaddr + RTC_ALARM_DATE_REG_OFFS); | ||
103 | |||
104 | second = rtc_time & 0x7f; | ||
105 | minute = (rtc_time >> RTC_MINUTES_OFFS) & 0x7f; | ||
106 | hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hours mode */ | ||
107 | wday = (rtc_time >> RTC_WDAY_OFFS) & 0x7; | ||
108 | |||
109 | day = rtc_date & 0x3f; | ||
110 | month = (rtc_date >> RTC_MONTH_OFFS) & 0x3f; | ||
111 | year = (rtc_date >> RTC_YEAR_OFFS) & 0xff; | ||
112 | |||
113 | alm->time.tm_sec = bcd2bin(second); | ||
114 | alm->time.tm_min = bcd2bin(minute); | ||
115 | alm->time.tm_hour = bcd2bin(hour); | ||
116 | alm->time.tm_mday = bcd2bin(day); | ||
117 | alm->time.tm_wday = bcd2bin(wday); | ||
118 | alm->time.tm_mon = bcd2bin(month) - 1; | ||
119 | /* hw counts from year 2000, but tm_year is relative to 1900 */ | ||
120 | alm->time.tm_year = bcd2bin(year) + 100; | ||
121 | |||
122 | if (rtc_valid_tm(&alm->time) < 0) { | ||
123 | dev_err(dev, "retrieved alarm date/time is not valid.\n"); | ||
124 | rtc_time_to_tm(0, &alm->time); | ||
125 | } | ||
126 | |||
127 | alm->enabled = !!readl(ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
132 | { | ||
133 | struct rtc_plat_data *pdata = dev_get_drvdata(dev); | ||
134 | void __iomem *ioaddr = pdata->ioaddr; | ||
135 | u32 rtc_reg = 0; | ||
136 | |||
137 | if (alm->time.tm_sec >= 0) | ||
138 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_sec)) | ||
139 | << RTC_SECONDS_OFFS; | ||
140 | if (alm->time.tm_min >= 0) | ||
141 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_min)) | ||
142 | << RTC_MINUTES_OFFS; | ||
143 | if (alm->time.tm_hour >= 0) | ||
144 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_hour)) | ||
145 | << RTC_HOURS_OFFS; | ||
146 | |||
147 | writel(rtc_reg, ioaddr + RTC_ALARM_TIME_REG_OFFS); | ||
148 | |||
149 | if (alm->time.tm_mday >= 0) | ||
150 | rtc_reg = (RTC_ALARM_VALID | bin2bcd(alm->time.tm_mday)) | ||
151 | << RTC_MDAY_OFFS; | ||
152 | else | ||
153 | rtc_reg = 0; | ||
154 | |||
155 | if (alm->time.tm_mon >= 0) | ||
156 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_mon + 1)) | ||
157 | << RTC_MONTH_OFFS; | ||
158 | |||
159 | if (alm->time.tm_year >= 0) | ||
160 | rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_year % 100)) | ||
161 | << RTC_YEAR_OFFS; | ||
162 | |||
163 | writel(rtc_reg, ioaddr + RTC_ALARM_DATE_REG_OFFS); | ||
164 | writel(0, ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS); | ||
165 | writel(alm->enabled ? 1 : 0, | ||
166 | ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static int mv_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
172 | unsigned long arg) | ||
173 | { | ||
174 | struct platform_device *pdev = to_platform_device(dev); | ||
175 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
176 | void __iomem *ioaddr = pdata->ioaddr; | ||
177 | |||
178 | if (pdata->irq < 0) | ||
179 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | ||
180 | switch (cmd) { | ||
181 | case RTC_AIE_OFF: | ||
182 | writel(0, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
183 | break; | ||
184 | case RTC_AIE_ON: | ||
185 | writel(1, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
186 | break; | ||
187 | default: | ||
188 | return -ENOIOCTLCMD; | ||
189 | } | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static irqreturn_t mv_rtc_interrupt(int irq, void *data) | ||
194 | { | ||
195 | struct rtc_plat_data *pdata = data; | ||
196 | void __iomem *ioaddr = pdata->ioaddr; | ||
197 | |||
198 | /* alarm irq? */ | ||
199 | if (!readl(ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS)) | ||
200 | return IRQ_NONE; | ||
201 | |||
202 | /* clear interrupt */ | ||
203 | writel(0, ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS); | ||
204 | rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF); | ||
205 | return IRQ_HANDLED; | ||
206 | } | ||
207 | |||
87 | static const struct rtc_class_ops mv_rtc_ops = { | 208 | static const struct rtc_class_ops mv_rtc_ops = { |
88 | .read_time = mv_rtc_read_time, | 209 | .read_time = mv_rtc_read_time, |
89 | .set_time = mv_rtc_set_time, | 210 | .set_time = mv_rtc_set_time, |
90 | }; | 211 | }; |
91 | 212 | ||
92 | static int __init mv_rtc_probe(struct platform_device *pdev) | 213 | static const struct rtc_class_ops mv_rtc_alarm_ops = { |
214 | .read_time = mv_rtc_read_time, | ||
215 | .set_time = mv_rtc_set_time, | ||
216 | .read_alarm = mv_rtc_read_alarm, | ||
217 | .set_alarm = mv_rtc_set_alarm, | ||
218 | .ioctl = mv_rtc_ioctl, | ||
219 | }; | ||
220 | |||
221 | static int __devinit mv_rtc_probe(struct platform_device *pdev) | ||
93 | { | 222 | { |
94 | struct resource *res; | 223 | struct resource *res; |
95 | struct rtc_plat_data *pdata; | 224 | struct rtc_plat_data *pdata; |
@@ -130,12 +259,31 @@ static int __init mv_rtc_probe(struct platform_device *pdev) | |||
130 | } | 259 | } |
131 | } | 260 | } |
132 | 261 | ||
262 | pdata->irq = platform_get_irq(pdev, 0); | ||
263 | |||
133 | platform_set_drvdata(pdev, pdata); | 264 | platform_set_drvdata(pdev, pdata); |
134 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, | 265 | |
135 | &mv_rtc_ops, THIS_MODULE); | 266 | if (pdata->irq >= 0) { |
267 | device_init_wakeup(&pdev->dev, 1); | ||
268 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
269 | &mv_rtc_alarm_ops, | ||
270 | THIS_MODULE); | ||
271 | } else | ||
272 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
273 | &mv_rtc_ops, THIS_MODULE); | ||
136 | if (IS_ERR(pdata->rtc)) | 274 | if (IS_ERR(pdata->rtc)) |
137 | return PTR_ERR(pdata->rtc); | 275 | return PTR_ERR(pdata->rtc); |
138 | 276 | ||
277 | if (pdata->irq >= 0) { | ||
278 | writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | ||
279 | if (devm_request_irq(&pdev->dev, pdata->irq, mv_rtc_interrupt, | ||
280 | IRQF_DISABLED | IRQF_SHARED, | ||
281 | pdev->name, pdata) < 0) { | ||
282 | dev_warn(&pdev->dev, "interrupt not available.\n"); | ||
283 | pdata->irq = -1; | ||
284 | } | ||
285 | } | ||
286 | |||
139 | return 0; | 287 | return 0; |
140 | } | 288 | } |
141 | 289 | ||
@@ -143,6 +291,9 @@ static int __exit mv_rtc_remove(struct platform_device *pdev) | |||
143 | { | 291 | { |
144 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 292 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
145 | 293 | ||
294 | if (pdata->irq >= 0) | ||
295 | device_init_wakeup(&pdev->dev, 0); | ||
296 | |||
146 | rtc_device_unregister(pdata->rtc); | 297 | rtc_device_unregister(pdata->rtc); |
147 | return 0; | 298 | return 0; |
148 | } | 299 | } |
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c new file mode 100644 index 000000000000..bf59c9c586b2 --- /dev/null +++ b/drivers/rtc/rtc-nuc900.c | |||
@@ -0,0 +1,342 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Nuvoton technology corporation. | ||
3 | * | ||
4 | * Wan ZongShun <mcuos.com@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;version 2 of the License. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/bcd.h> | ||
19 | |||
20 | /* RTC Control Registers */ | ||
21 | #define REG_RTC_INIR 0x00 | ||
22 | #define REG_RTC_AER 0x04 | ||
23 | #define REG_RTC_FCR 0x08 | ||
24 | #define REG_RTC_TLR 0x0C | ||
25 | #define REG_RTC_CLR 0x10 | ||
26 | #define REG_RTC_TSSR 0x14 | ||
27 | #define REG_RTC_DWR 0x18 | ||
28 | #define REG_RTC_TAR 0x1C | ||
29 | #define REG_RTC_CAR 0x20 | ||
30 | #define REG_RTC_LIR 0x24 | ||
31 | #define REG_RTC_RIER 0x28 | ||
32 | #define REG_RTC_RIIR 0x2C | ||
33 | #define REG_RTC_TTR 0x30 | ||
34 | |||
35 | #define RTCSET 0x01 | ||
36 | #define AERRWENB 0x10000 | ||
37 | #define INIRRESET 0xa5eb1357 | ||
38 | #define AERPOWERON 0xA965 | ||
39 | #define AERPOWEROFF 0x0000 | ||
40 | #define LEAPYEAR 0x0001 | ||
41 | #define TICKENB 0x80 | ||
42 | #define TICKINTENB 0x0002 | ||
43 | #define ALARMINTENB 0x0001 | ||
44 | #define MODE24 0x0001 | ||
45 | |||
46 | struct nuc900_rtc { | ||
47 | int irq_num; | ||
48 | void __iomem *rtc_reg; | ||
49 | struct rtc_device *rtcdev; | ||
50 | }; | ||
51 | |||
52 | struct nuc900_bcd_time { | ||
53 | int bcd_sec; | ||
54 | int bcd_min; | ||
55 | int bcd_hour; | ||
56 | int bcd_mday; | ||
57 | int bcd_mon; | ||
58 | int bcd_year; | ||
59 | }; | ||
60 | |||
61 | static irqreturn_t nuc900_rtc_interrupt(int irq, void *_rtc) | ||
62 | { | ||
63 | struct nuc900_rtc *rtc = _rtc; | ||
64 | unsigned long events = 0, rtc_irq; | ||
65 | |||
66 | rtc_irq = __raw_readl(rtc->rtc_reg + REG_RTC_RIIR); | ||
67 | |||
68 | if (rtc_irq & ALARMINTENB) { | ||
69 | rtc_irq &= ~ALARMINTENB; | ||
70 | __raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR); | ||
71 | events |= RTC_AF | RTC_IRQF; | ||
72 | } | ||
73 | |||
74 | if (rtc_irq & TICKINTENB) { | ||
75 | rtc_irq &= ~TICKINTENB; | ||
76 | __raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR); | ||
77 | events |= RTC_UF | RTC_IRQF; | ||
78 | } | ||
79 | |||
80 | rtc_update_irq(rtc->rtcdev, 1, events); | ||
81 | |||
82 | return IRQ_HANDLED; | ||
83 | } | ||
84 | |||
85 | static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) | ||
86 | { | ||
87 | unsigned int i; | ||
88 | __raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR); | ||
89 | |||
90 | mdelay(10); | ||
91 | |||
92 | __raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER); | ||
93 | |||
94 | for (i = 0; i < 1000; i++) { | ||
95 | if (__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | if ((__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) == 0x0) | ||
100 | return ERR_PTR(-ENODEV); | ||
101 | |||
102 | return ERR_PTR(-EPERM); | ||
103 | } | ||
104 | |||
105 | static void nuc900_rtc_bcd2bin(unsigned int timereg, | ||
106 | unsigned int calreg, struct rtc_time *tm) | ||
107 | { | ||
108 | tm->tm_mday = bcd2bin(calreg >> 0); | ||
109 | tm->tm_mon = bcd2bin(calreg >> 8); | ||
110 | tm->tm_year = bcd2bin(calreg >> 16) + 100; | ||
111 | |||
112 | tm->tm_sec = bcd2bin(timereg >> 0); | ||
113 | tm->tm_min = bcd2bin(timereg >> 8); | ||
114 | tm->tm_hour = bcd2bin(timereg >> 16); | ||
115 | |||
116 | rtc_valid_tm(tm); | ||
117 | } | ||
118 | |||
119 | static void nuc900_rtc_bin2bcd(struct rtc_time *settm, | ||
120 | struct nuc900_bcd_time *gettm) | ||
121 | { | ||
122 | gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0; | ||
123 | gettm->bcd_mon = bin2bcd(settm->tm_mon) << 8; | ||
124 | gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16; | ||
125 | |||
126 | gettm->bcd_sec = bin2bcd(settm->tm_sec) << 0; | ||
127 | gettm->bcd_min = bin2bcd(settm->tm_min) << 8; | ||
128 | gettm->bcd_hour = bin2bcd(settm->tm_hour) << 16; | ||
129 | } | ||
130 | |||
131 | static int nuc900_update_irq_enable(struct device *dev, unsigned int enabled) | ||
132 | { | ||
133 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
134 | |||
135 | if (enabled) | ||
136 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)| | ||
137 | (TICKINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
138 | else | ||
139 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)& | ||
140 | (~TICKINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int nuc900_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
146 | { | ||
147 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
148 | |||
149 | if (enabled) | ||
150 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)| | ||
151 | (ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
152 | else | ||
153 | __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)& | ||
154 | (~ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER); | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
160 | { | ||
161 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
162 | unsigned int timeval, clrval; | ||
163 | |||
164 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); | ||
165 | clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); | ||
166 | |||
167 | nuc900_rtc_bcd2bin(timeval, clrval, tm); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
173 | { | ||
174 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
175 | struct nuc900_bcd_time gettm; | ||
176 | unsigned long val; | ||
177 | int *err; | ||
178 | |||
179 | nuc900_rtc_bin2bcd(tm, &gettm); | ||
180 | |||
181 | err = check_rtc_access_enable(rtc); | ||
182 | if (IS_ERR(err)) | ||
183 | return PTR_ERR(err); | ||
184 | |||
185 | val = gettm.bcd_mday | gettm.bcd_mon | gettm.bcd_year; | ||
186 | __raw_writel(val, rtc->rtc_reg + REG_RTC_CLR); | ||
187 | |||
188 | val = gettm.bcd_sec | gettm.bcd_min | gettm.bcd_hour; | ||
189 | __raw_writel(val, rtc->rtc_reg + REG_RTC_TLR); | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
195 | { | ||
196 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
197 | unsigned int timeval, carval; | ||
198 | |||
199 | timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); | ||
200 | carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); | ||
201 | |||
202 | nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
208 | { | ||
209 | struct nuc900_rtc *rtc = dev_get_drvdata(dev); | ||
210 | struct nuc900_bcd_time tm; | ||
211 | unsigned long val; | ||
212 | int *err; | ||
213 | |||
214 | nuc900_rtc_bin2bcd(&alrm->time, &tm); | ||
215 | |||
216 | err = check_rtc_access_enable(rtc); | ||
217 | if (IS_ERR(err)) | ||
218 | return PTR_ERR(err); | ||
219 | |||
220 | val = tm.bcd_mday | tm.bcd_mon | tm.bcd_year; | ||
221 | __raw_writel(val, rtc->rtc_reg + REG_RTC_CAR); | ||
222 | |||
223 | val = tm.bcd_sec | tm.bcd_min | tm.bcd_hour; | ||
224 | __raw_writel(val, rtc->rtc_reg + REG_RTC_TAR); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static struct rtc_class_ops nuc900_rtc_ops = { | ||
230 | .read_time = nuc900_rtc_read_time, | ||
231 | .set_time = nuc900_rtc_set_time, | ||
232 | .read_alarm = nuc900_rtc_read_alarm, | ||
233 | .set_alarm = nuc900_rtc_set_alarm, | ||
234 | .alarm_irq_enable = nuc900_alarm_irq_enable, | ||
235 | .update_irq_enable = nuc900_update_irq_enable, | ||
236 | }; | ||
237 | |||
238 | static int __devinit nuc900_rtc_probe(struct platform_device *pdev) | ||
239 | { | ||
240 | struct resource *res; | ||
241 | struct nuc900_rtc *nuc900_rtc; | ||
242 | int err = 0; | ||
243 | |||
244 | nuc900_rtc = kzalloc(sizeof(struct nuc900_rtc), GFP_KERNEL); | ||
245 | if (!nuc900_rtc) { | ||
246 | dev_err(&pdev->dev, "kzalloc nuc900_rtc failed\n"); | ||
247 | return -ENOMEM; | ||
248 | } | ||
249 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
250 | if (!res) { | ||
251 | dev_err(&pdev->dev, "platform_get_resource failed\n"); | ||
252 | err = -ENXIO; | ||
253 | goto fail1; | ||
254 | } | ||
255 | |||
256 | if (!request_mem_region(res->start, resource_size(res), | ||
257 | pdev->name)) { | ||
258 | dev_err(&pdev->dev, "request_mem_region failed\n"); | ||
259 | err = -EBUSY; | ||
260 | goto fail1; | ||
261 | } | ||
262 | |||
263 | nuc900_rtc->rtc_reg = ioremap(res->start, resource_size(res)); | ||
264 | if (!nuc900_rtc->rtc_reg) { | ||
265 | dev_err(&pdev->dev, "ioremap rtc_reg failed\n"); | ||
266 | err = -ENOMEM; | ||
267 | goto fail2; | ||
268 | } | ||
269 | |||
270 | nuc900_rtc->irq_num = platform_get_irq(pdev, 0); | ||
271 | if (request_irq(nuc900_rtc->irq_num, nuc900_rtc_interrupt, | ||
272 | IRQF_DISABLED, "nuc900rtc", nuc900_rtc)) { | ||
273 | dev_err(&pdev->dev, "NUC900 RTC request irq failed\n"); | ||
274 | err = -EBUSY; | ||
275 | goto fail3; | ||
276 | } | ||
277 | |||
278 | nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, | ||
279 | &nuc900_rtc_ops, THIS_MODULE); | ||
280 | if (IS_ERR(nuc900_rtc->rtcdev)) { | ||
281 | dev_err(&pdev->dev, "rtc device register faild\n"); | ||
282 | err = PTR_ERR(nuc900_rtc->rtcdev); | ||
283 | goto fail4; | ||
284 | } | ||
285 | |||
286 | platform_set_drvdata(pdev, nuc900_rtc); | ||
287 | __raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24, | ||
288 | nuc900_rtc->rtc_reg + REG_RTC_TSSR); | ||
289 | |||
290 | return 0; | ||
291 | |||
292 | fail4: free_irq(nuc900_rtc->irq_num, nuc900_rtc); | ||
293 | fail3: iounmap(nuc900_rtc->rtc_reg); | ||
294 | fail2: release_mem_region(res->start, resource_size(res)); | ||
295 | fail1: kfree(nuc900_rtc); | ||
296 | return err; | ||
297 | } | ||
298 | |||
299 | static int __devexit nuc900_rtc_remove(struct platform_device *pdev) | ||
300 | { | ||
301 | struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev); | ||
302 | struct resource *res; | ||
303 | |||
304 | rtc_device_unregister(nuc900_rtc->rtcdev); | ||
305 | free_irq(nuc900_rtc->irq_num, nuc900_rtc); | ||
306 | iounmap(nuc900_rtc->rtc_reg); | ||
307 | |||
308 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
309 | release_mem_region(res->start, resource_size(res)); | ||
310 | |||
311 | kfree(nuc900_rtc); | ||
312 | |||
313 | platform_set_drvdata(pdev, NULL); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static struct platform_driver nuc900_rtc_driver = { | ||
319 | .remove = __devexit_p(nuc900_rtc_remove), | ||
320 | .driver = { | ||
321 | .name = "nuc900-rtc", | ||
322 | .owner = THIS_MODULE, | ||
323 | }, | ||
324 | }; | ||
325 | |||
326 | static int __init nuc900_rtc_init(void) | ||
327 | { | ||
328 | return platform_driver_probe(&nuc900_rtc_driver, nuc900_rtc_probe); | ||
329 | } | ||
330 | |||
331 | static void __exit nuc900_rtc_exit(void) | ||
332 | { | ||
333 | platform_driver_unregister(&nuc900_rtc_driver); | ||
334 | } | ||
335 | |||
336 | module_init(nuc900_rtc_init); | ||
337 | module_exit(nuc900_rtc_exit); | ||
338 | |||
339 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
340 | MODULE_DESCRIPTION("nuc910/nuc920 RTC driver"); | ||
341 | MODULE_LICENSE("GPL"); | ||
342 | MODULE_ALIAS("platform:nuc900-rtc"); | ||
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 0587d53987fe..64d9727b7229 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
@@ -87,9 +87,10 @@ | |||
87 | #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) | 87 | #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) |
88 | #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) | 88 | #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) |
89 | 89 | ||
90 | static void __iomem *rtc_base; | ||
90 | 91 | ||
91 | #define rtc_read(addr) omap_readb(OMAP_RTC_BASE + (addr)) | 92 | #define rtc_read(addr) __raw_readb(rtc_base + (addr)) |
92 | #define rtc_write(val, addr) omap_writeb(val, OMAP_RTC_BASE + (addr)) | 93 | #define rtc_write(val, addr) __raw_writeb(val, rtc_base + (addr)) |
93 | 94 | ||
94 | 95 | ||
95 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), | 96 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), |
@@ -330,32 +331,31 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
330 | return -ENOENT; | 331 | return -ENOENT; |
331 | } | 332 | } |
332 | 333 | ||
333 | /* NOTE: using static mapping for RTC registers */ | ||
334 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 334 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
335 | if (res && res->start != OMAP_RTC_BASE) { | 335 | if (!res) { |
336 | pr_debug("%s: RTC registers at %08x, expected %08x\n", | 336 | pr_debug("%s: RTC resource data missing\n", pdev->name); |
337 | pdev->name, (unsigned) res->start, OMAP_RTC_BASE); | ||
338 | return -ENOENT; | 337 | return -ENOENT; |
339 | } | 338 | } |
340 | 339 | ||
341 | if (res) | 340 | mem = request_mem_region(res->start, resource_size(res), pdev->name); |
342 | mem = request_mem_region(res->start, | ||
343 | res->end - res->start + 1, | ||
344 | pdev->name); | ||
345 | else | ||
346 | mem = NULL; | ||
347 | if (!mem) { | 341 | if (!mem) { |
348 | pr_debug("%s: RTC registers at %08x are not free\n", | 342 | pr_debug("%s: RTC registers at %08x are not free\n", |
349 | pdev->name, OMAP_RTC_BASE); | 343 | pdev->name, res->start); |
350 | return -EBUSY; | 344 | return -EBUSY; |
351 | } | 345 | } |
352 | 346 | ||
347 | rtc_base = ioremap(res->start, resource_size(res)); | ||
348 | if (!rtc_base) { | ||
349 | pr_debug("%s: RTC registers can't be mapped\n", pdev->name); | ||
350 | goto fail; | ||
351 | } | ||
352 | |||
353 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 353 | rtc = rtc_device_register(pdev->name, &pdev->dev, |
354 | &omap_rtc_ops, THIS_MODULE); | 354 | &omap_rtc_ops, THIS_MODULE); |
355 | if (IS_ERR(rtc)) { | 355 | if (IS_ERR(rtc)) { |
356 | pr_debug("%s: can't register RTC device, err %ld\n", | 356 | pr_debug("%s: can't register RTC device, err %ld\n", |
357 | pdev->name, PTR_ERR(rtc)); | 357 | pdev->name, PTR_ERR(rtc)); |
358 | goto fail; | 358 | goto fail0; |
359 | } | 359 | } |
360 | platform_set_drvdata(pdev, rtc); | 360 | platform_set_drvdata(pdev, rtc); |
361 | dev_set_drvdata(&rtc->dev, mem); | 361 | dev_set_drvdata(&rtc->dev, mem); |
@@ -380,13 +380,14 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
380 | dev_name(&rtc->dev), rtc)) { | 380 | dev_name(&rtc->dev), rtc)) { |
381 | pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", | 381 | pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", |
382 | pdev->name, omap_rtc_timer); | 382 | pdev->name, omap_rtc_timer); |
383 | goto fail0; | 383 | goto fail1; |
384 | } | 384 | } |
385 | if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED, | 385 | if ((omap_rtc_timer != omap_rtc_alarm) && |
386 | dev_name(&rtc->dev), rtc)) { | 386 | (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED, |
387 | dev_name(&rtc->dev), rtc))) { | ||
387 | pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", | 388 | pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", |
388 | pdev->name, omap_rtc_alarm); | 389 | pdev->name, omap_rtc_alarm); |
389 | goto fail1; | 390 | goto fail2; |
390 | } | 391 | } |
391 | 392 | ||
392 | /* On boards with split power, RTC_ON_NOFF won't reset the RTC */ | 393 | /* On boards with split power, RTC_ON_NOFF won't reset the RTC */ |
@@ -419,10 +420,12 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
419 | 420 | ||
420 | return 0; | 421 | return 0; |
421 | 422 | ||
422 | fail1: | 423 | fail2: |
423 | free_irq(omap_rtc_timer, NULL); | 424 | free_irq(omap_rtc_timer, NULL); |
424 | fail0: | 425 | fail1: |
425 | rtc_device_unregister(rtc); | 426 | rtc_device_unregister(rtc); |
427 | fail0: | ||
428 | iounmap(rtc_base); | ||
426 | fail: | 429 | fail: |
427 | release_resource(mem); | 430 | release_resource(mem); |
428 | return -EIO; | 431 | return -EIO; |
@@ -438,7 +441,9 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) | |||
438 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); | 441 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); |
439 | 442 | ||
440 | free_irq(omap_rtc_timer, rtc); | 443 | free_irq(omap_rtc_timer, rtc); |
441 | free_irq(omap_rtc_alarm, rtc); | 444 | |
445 | if (omap_rtc_timer != omap_rtc_alarm) | ||
446 | free_irq(omap_rtc_alarm, rtc); | ||
442 | 447 | ||
443 | release_resource(dev_get_drvdata(&rtc->dev)); | 448 | release_resource(dev_get_drvdata(&rtc->dev)); |
444 | rtc_device_unregister(rtc); | 449 | rtc_device_unregister(rtc); |
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index 9b74e9c9151c..854c3cb365a1 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c | |||
@@ -58,6 +58,7 @@ struct pcf50633_time { | |||
58 | struct pcf50633_rtc { | 58 | struct pcf50633_rtc { |
59 | int alarm_enabled; | 59 | int alarm_enabled; |
60 | int second_enabled; | 60 | int second_enabled; |
61 | int alarm_pending; | ||
61 | 62 | ||
62 | struct pcf50633 *pcf; | 63 | struct pcf50633 *pcf; |
63 | struct rtc_device *rtc_dev; | 64 | struct rtc_device *rtc_dev; |
@@ -209,6 +210,7 @@ static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
209 | rtc = dev_get_drvdata(dev); | 210 | rtc = dev_get_drvdata(dev); |
210 | 211 | ||
211 | alrm->enabled = rtc->alarm_enabled; | 212 | alrm->enabled = rtc->alarm_enabled; |
213 | alrm->pending = rtc->alarm_pending; | ||
212 | 214 | ||
213 | ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA, | 215 | ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA, |
214 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); | 216 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); |
@@ -244,6 +246,8 @@ static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
244 | /* Returns 0 on success */ | 246 | /* Returns 0 on success */ |
245 | ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA, | 247 | ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA, |
246 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); | 248 | PCF50633_TI_EXTENT, &pcf_tm.time[0]); |
249 | if (!alrm->enabled) | ||
250 | rtc->alarm_pending = 0; | ||
247 | 251 | ||
248 | if (!alarm_masked || alrm->enabled) | 252 | if (!alarm_masked || alrm->enabled) |
249 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); | 253 | pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM); |
@@ -268,6 +272,7 @@ static void pcf50633_rtc_irq(int irq, void *data) | |||
268 | switch (irq) { | 272 | switch (irq) { |
269 | case PCF50633_IRQ_ALARM: | 273 | case PCF50633_IRQ_ALARM: |
270 | rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); | 274 | rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); |
275 | rtc->alarm_pending = 1; | ||
271 | break; | 276 | break; |
272 | case PCF50633_IRQ_SECOND: | 277 | case PCF50633_IRQ_SECOND: |
273 | rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); | 278 | rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); |
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index b725913ccbe8..65f346b2fbae 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
@@ -212,6 +212,8 @@ static int pcf8563_probe(struct i2c_client *client, | |||
212 | 212 | ||
213 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 213 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
214 | 214 | ||
215 | i2c_set_clientdata(client, pcf8563); | ||
216 | |||
215 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, | 217 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, |
216 | &client->dev, &pcf8563_rtc_ops, THIS_MODULE); | 218 | &client->dev, &pcf8563_rtc_ops, THIS_MODULE); |
217 | 219 | ||
@@ -220,8 +222,6 @@ static int pcf8563_probe(struct i2c_client *client, | |||
220 | goto exit_kfree; | 222 | goto exit_kfree; |
221 | } | 223 | } |
222 | 224 | ||
223 | i2c_set_clientdata(client, pcf8563); | ||
224 | |||
225 | return 0; | 225 | return 0; |
226 | 226 | ||
227 | exit_kfree: | 227 | exit_kfree: |
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index 7d33cda3f8f6..2d201afead3b 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c | |||
@@ -277,6 +277,8 @@ static int pcf8583_probe(struct i2c_client *client, | |||
277 | if (!pcf8583) | 277 | if (!pcf8583) |
278 | return -ENOMEM; | 278 | return -ENOMEM; |
279 | 279 | ||
280 | i2c_set_clientdata(client, pcf8583); | ||
281 | |||
280 | pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name, | 282 | pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name, |
281 | &client->dev, &pcf8583_rtc_ops, THIS_MODULE); | 283 | &client->dev, &pcf8583_rtc_ops, THIS_MODULE); |
282 | 284 | ||
@@ -285,7 +287,6 @@ static int pcf8583_probe(struct i2c_client *client, | |||
285 | goto exit_kfree; | 287 | goto exit_kfree; |
286 | } | 288 | } |
287 | 289 | ||
288 | i2c_set_clientdata(client, pcf8583); | ||
289 | return 0; | 290 | return 0; |
290 | 291 | ||
291 | exit_kfree: | 292 | exit_kfree: |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index f41873f98f66..0264b117893b 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -51,10 +51,10 @@ static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
51 | 51 | ||
52 | switch (cmd) { | 52 | switch (cmd) { |
53 | case RTC_AIE_OFF: | 53 | case RTC_AIE_OFF: |
54 | __raw_writel(1, ldata->base + RTC_MIS); | 54 | writel(1, ldata->base + RTC_MIS); |
55 | return 0; | 55 | return 0; |
56 | case RTC_AIE_ON: | 56 | case RTC_AIE_ON: |
57 | __raw_writel(0, ldata->base + RTC_MIS); | 57 | writel(0, ldata->base + RTC_MIS); |
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
@@ -65,7 +65,7 @@ static int pl031_read_time(struct device *dev, struct rtc_time *tm) | |||
65 | { | 65 | { |
66 | struct pl031_local *ldata = dev_get_drvdata(dev); | 66 | struct pl031_local *ldata = dev_get_drvdata(dev); |
67 | 67 | ||
68 | rtc_time_to_tm(__raw_readl(ldata->base + RTC_DR), tm); | 68 | rtc_time_to_tm(readl(ldata->base + RTC_DR), tm); |
69 | 69 | ||
70 | return 0; | 70 | return 0; |
71 | } | 71 | } |
@@ -76,7 +76,7 @@ static int pl031_set_time(struct device *dev, struct rtc_time *tm) | |||
76 | struct pl031_local *ldata = dev_get_drvdata(dev); | 76 | struct pl031_local *ldata = dev_get_drvdata(dev); |
77 | 77 | ||
78 | rtc_tm_to_time(tm, &time); | 78 | rtc_tm_to_time(tm, &time); |
79 | __raw_writel(time, ldata->base + RTC_LR); | 79 | writel(time, ldata->base + RTC_LR); |
80 | 80 | ||
81 | return 0; | 81 | return 0; |
82 | } | 82 | } |
@@ -85,9 +85,9 @@ static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
85 | { | 85 | { |
86 | struct pl031_local *ldata = dev_get_drvdata(dev); | 86 | struct pl031_local *ldata = dev_get_drvdata(dev); |
87 | 87 | ||
88 | rtc_time_to_tm(__raw_readl(ldata->base + RTC_MR), &alarm->time); | 88 | rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time); |
89 | alarm->pending = __raw_readl(ldata->base + RTC_RIS); | 89 | alarm->pending = readl(ldata->base + RTC_RIS); |
90 | alarm->enabled = __raw_readl(ldata->base + RTC_IMSC); | 90 | alarm->enabled = readl(ldata->base + RTC_IMSC); |
91 | 91 | ||
92 | return 0; | 92 | return 0; |
93 | } | 93 | } |
@@ -99,8 +99,8 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
99 | 99 | ||
100 | rtc_tm_to_time(&alarm->time, &time); | 100 | rtc_tm_to_time(&alarm->time, &time); |
101 | 101 | ||
102 | __raw_writel(time, ldata->base + RTC_MR); | 102 | writel(time, ldata->base + RTC_MR); |
103 | __raw_writel(!alarm->enabled, ldata->base + RTC_MIS); | 103 | writel(!alarm->enabled, ldata->base + RTC_MIS); |
104 | 104 | ||
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
@@ -180,8 +180,9 @@ err_req: | |||
180 | 180 | ||
181 | static struct amba_id pl031_ids[] __initdata = { | 181 | static struct amba_id pl031_ids[] __initdata = { |
182 | { | 182 | { |
183 | .id = 0x00041031, | 183 | .id = 0x00041031, |
184 | .mask = 0x000fffff, }, | 184 | .mask = 0x000fffff, |
185 | }, | ||
185 | {0, 0}, | 186 | {0, 0}, |
186 | }; | 187 | }; |
187 | 188 | ||
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index 747ca194fad4..e6351b743da6 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c | |||
@@ -456,7 +456,7 @@ static int pxa_rtc_resume(struct device *dev) | |||
456 | return 0; | 456 | return 0; |
457 | } | 457 | } |
458 | 458 | ||
459 | static struct dev_pm_ops pxa_rtc_pm_ops = { | 459 | static const struct dev_pm_ops pxa_rtc_pm_ops = { |
460 | .suspend = pxa_rtc_suspend, | 460 | .suspend = pxa_rtc_suspend, |
461 | .resume = pxa_rtc_resume, | 461 | .resume = pxa_rtc_resume, |
462 | }; | 462 | }; |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 29f98a70586e..e4a44b641702 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -407,7 +407,7 @@ static int sa1100_rtc_resume(struct device *dev) | |||
407 | return 0; | 407 | return 0; |
408 | } | 408 | } |
409 | 409 | ||
410 | static struct dev_pm_ops sa1100_rtc_pm_ops = { | 410 | static const struct dev_pm_ops sa1100_rtc_pm_ops = { |
411 | .suspend = sa1100_rtc_suspend, | 411 | .suspend = sa1100_rtc_suspend, |
412 | .resume = sa1100_rtc_resume, | 412 | .resume = sa1100_rtc_resume, |
413 | }; | 413 | }; |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index e6ed5404bca0..e95cc6f8d61e 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
@@ -826,7 +826,7 @@ static int sh_rtc_resume(struct device *dev) | |||
826 | return 0; | 826 | return 0; |
827 | } | 827 | } |
828 | 828 | ||
829 | static struct dev_pm_ops sh_rtc_dev_pm_ops = { | 829 | static const struct dev_pm_ops sh_rtc_dev_pm_ops = { |
830 | .suspend = sh_rtc_suspend, | 830 | .suspend = sh_rtc_suspend, |
831 | .resume = sh_rtc_resume, | 831 | .resume = sh_rtc_resume, |
832 | }; | 832 | }; |
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index d491eb265c38..67700831b5c9 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c | |||
@@ -62,7 +62,6 @@ | |||
62 | struct rtc_plat_data { | 62 | struct rtc_plat_data { |
63 | struct rtc_device *rtc; | 63 | struct rtc_device *rtc; |
64 | void __iomem *ioaddr; | 64 | void __iomem *ioaddr; |
65 | unsigned long baseaddr; | ||
66 | unsigned long last_jiffies; | 65 | unsigned long last_jiffies; |
67 | int irq; | 66 | int irq; |
68 | unsigned int irqen; | 67 | unsigned int irqen; |
@@ -70,6 +69,7 @@ struct rtc_plat_data { | |||
70 | int alrm_min; | 69 | int alrm_min; |
71 | int alrm_hour; | 70 | int alrm_hour; |
72 | int alrm_mday; | 71 | int alrm_mday; |
72 | spinlock_t lock; | ||
73 | }; | 73 | }; |
74 | 74 | ||
75 | static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm) | 75 | static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -142,7 +142,7 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
142 | unsigned long irqflags; | 142 | unsigned long irqflags; |
143 | u8 flags; | 143 | u8 flags; |
144 | 144 | ||
145 | spin_lock_irqsave(&pdata->rtc->irq_lock, irqflags); | 145 | spin_lock_irqsave(&pdata->lock, irqflags); |
146 | 146 | ||
147 | flags = readb(ioaddr + RTC_FLAGS); | 147 | flags = readb(ioaddr + RTC_FLAGS); |
148 | writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS); | 148 | writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS); |
@@ -162,7 +162,7 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata) | |||
162 | writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS); | 162 | writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS); |
163 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ | 163 | readb(ioaddr + RTC_FLAGS); /* clear interrupts */ |
164 | writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS); | 164 | writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS); |
165 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, irqflags); | 165 | spin_unlock_irqrestore(&pdata->lock, irqflags); |
166 | } | 166 | } |
167 | 167 | ||
168 | static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 168 | static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
@@ -202,56 +202,53 @@ static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id) | |||
202 | struct platform_device *pdev = dev_id; | 202 | struct platform_device *pdev = dev_id; |
203 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 203 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
204 | void __iomem *ioaddr = pdata->ioaddr; | 204 | void __iomem *ioaddr = pdata->ioaddr; |
205 | unsigned long events = RTC_IRQF; | 205 | unsigned long events = 0; |
206 | 206 | ||
207 | spin_lock(&pdata->lock); | ||
207 | /* read and clear interrupt */ | 208 | /* read and clear interrupt */ |
208 | if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF)) | 209 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF) { |
209 | return IRQ_NONE; | 210 | events = RTC_IRQF; |
210 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) | 211 | if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) |
211 | events |= RTC_UF; | 212 | events |= RTC_UF; |
212 | else | 213 | else |
213 | events |= RTC_AF; | 214 | events |= RTC_AF; |
214 | rtc_update_irq(pdata->rtc, 1, events); | 215 | if (likely(pdata->rtc)) |
215 | return IRQ_HANDLED; | 216 | rtc_update_irq(pdata->rtc, 1, events); |
217 | } | ||
218 | spin_unlock(&pdata->lock); | ||
219 | return events ? IRQ_HANDLED : IRQ_NONE; | ||
216 | } | 220 | } |
217 | 221 | ||
218 | static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd, | 222 | static int stk17ta8_rtc_alarm_irq_enable(struct device *dev, |
219 | unsigned long arg) | 223 | unsigned int enabled) |
220 | { | 224 | { |
221 | struct platform_device *pdev = to_platform_device(dev); | 225 | struct platform_device *pdev = to_platform_device(dev); |
222 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 226 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
223 | 227 | ||
224 | if (pdata->irq <= 0) | 228 | if (pdata->irq <= 0) |
225 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | 229 | return -EINVAL; |
226 | switch (cmd) { | 230 | if (enabled) |
227 | case RTC_AIE_OFF: | ||
228 | pdata->irqen &= ~RTC_AF; | ||
229 | stk17ta8_rtc_update_alarm(pdata); | ||
230 | break; | ||
231 | case RTC_AIE_ON: | ||
232 | pdata->irqen |= RTC_AF; | 231 | pdata->irqen |= RTC_AF; |
233 | stk17ta8_rtc_update_alarm(pdata); | 232 | else |
234 | break; | 233 | pdata->irqen &= ~RTC_AF; |
235 | default: | 234 | stk17ta8_rtc_update_alarm(pdata); |
236 | return -ENOIOCTLCMD; | ||
237 | } | ||
238 | return 0; | 235 | return 0; |
239 | } | 236 | } |
240 | 237 | ||
241 | static const struct rtc_class_ops stk17ta8_rtc_ops = { | 238 | static const struct rtc_class_ops stk17ta8_rtc_ops = { |
242 | .read_time = stk17ta8_rtc_read_time, | 239 | .read_time = stk17ta8_rtc_read_time, |
243 | .set_time = stk17ta8_rtc_set_time, | 240 | .set_time = stk17ta8_rtc_set_time, |
244 | .read_alarm = stk17ta8_rtc_read_alarm, | 241 | .read_alarm = stk17ta8_rtc_read_alarm, |
245 | .set_alarm = stk17ta8_rtc_set_alarm, | 242 | .set_alarm = stk17ta8_rtc_set_alarm, |
246 | .ioctl = stk17ta8_rtc_ioctl, | 243 | .alarm_irq_enable = stk17ta8_rtc_alarm_irq_enable, |
247 | }; | 244 | }; |
248 | 245 | ||
249 | static ssize_t stk17ta8_nvram_read(struct kobject *kobj, | 246 | static ssize_t stk17ta8_nvram_read(struct kobject *kobj, |
250 | struct bin_attribute *attr, char *buf, | 247 | struct bin_attribute *attr, char *buf, |
251 | loff_t pos, size_t size) | 248 | loff_t pos, size_t size) |
252 | { | 249 | { |
253 | struct platform_device *pdev = | 250 | struct device *dev = container_of(kobj, struct device, kobj); |
254 | to_platform_device(container_of(kobj, struct device, kobj)); | 251 | struct platform_device *pdev = to_platform_device(dev); |
255 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 252 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
256 | void __iomem *ioaddr = pdata->ioaddr; | 253 | void __iomem *ioaddr = pdata->ioaddr; |
257 | ssize_t count; | 254 | ssize_t count; |
@@ -265,8 +262,8 @@ static ssize_t stk17ta8_nvram_write(struct kobject *kobj, | |||
265 | struct bin_attribute *attr, char *buf, | 262 | struct bin_attribute *attr, char *buf, |
266 | loff_t pos, size_t size) | 263 | loff_t pos, size_t size) |
267 | { | 264 | { |
268 | struct platform_device *pdev = | 265 | struct device *dev = container_of(kobj, struct device, kobj); |
269 | to_platform_device(container_of(kobj, struct device, kobj)); | 266 | struct platform_device *pdev = to_platform_device(dev); |
270 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 267 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
271 | void __iomem *ioaddr = pdata->ioaddr; | 268 | void __iomem *ioaddr = pdata->ioaddr; |
272 | ssize_t count; | 269 | ssize_t count; |
@@ -288,31 +285,26 @@ static struct bin_attribute stk17ta8_nvram_attr = { | |||
288 | 285 | ||
289 | static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev) | 286 | static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev) |
290 | { | 287 | { |
291 | struct rtc_device *rtc; | ||
292 | struct resource *res; | 288 | struct resource *res; |
293 | unsigned int cal; | 289 | unsigned int cal; |
294 | unsigned int flags; | 290 | unsigned int flags; |
295 | struct rtc_plat_data *pdata; | 291 | struct rtc_plat_data *pdata; |
296 | void __iomem *ioaddr = NULL; | 292 | void __iomem *ioaddr; |
297 | int ret = 0; | 293 | int ret = 0; |
298 | 294 | ||
299 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 295 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
300 | if (!res) | 296 | if (!res) |
301 | return -ENODEV; | 297 | return -ENODEV; |
302 | 298 | ||
303 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 299 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
304 | if (!pdata) | 300 | if (!pdata) |
305 | return -ENOMEM; | 301 | return -ENOMEM; |
306 | if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { | 302 | if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE, |
307 | ret = -EBUSY; | 303 | pdev->name)) |
308 | goto out; | 304 | return -EBUSY; |
309 | } | 305 | ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE); |
310 | pdata->baseaddr = res->start; | 306 | if (!ioaddr) |
311 | ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); | 307 | return -ENOMEM; |
312 | if (!ioaddr) { | ||
313 | ret = -ENOMEM; | ||
314 | goto out; | ||
315 | } | ||
316 | pdata->ioaddr = ioaddr; | 308 | pdata->ioaddr = ioaddr; |
317 | pdata->irq = platform_get_irq(pdev, 0); | 309 | pdata->irq = platform_get_irq(pdev, 0); |
318 | 310 | ||
@@ -328,9 +320,13 @@ static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev) | |||
328 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF) | 320 | if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF) |
329 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | 321 | dev_warn(&pdev->dev, "voltage-low detected.\n"); |
330 | 322 | ||
323 | spin_lock_init(&pdata->lock); | ||
324 | pdata->last_jiffies = jiffies; | ||
325 | platform_set_drvdata(pdev, pdata); | ||
331 | if (pdata->irq > 0) { | 326 | if (pdata->irq > 0) { |
332 | writeb(0, ioaddr + RTC_INTERRUPTS); | 327 | writeb(0, ioaddr + RTC_INTERRUPTS); |
333 | if (request_irq(pdata->irq, stk17ta8_rtc_interrupt, | 328 | if (devm_request_irq(&pdev->dev, pdata->irq, |
329 | stk17ta8_rtc_interrupt, | ||
334 | IRQF_DISABLED | IRQF_SHARED, | 330 | IRQF_DISABLED | IRQF_SHARED, |
335 | pdev->name, pdev) < 0) { | 331 | pdev->name, pdev) < 0) { |
336 | dev_warn(&pdev->dev, "interrupt not available.\n"); | 332 | dev_warn(&pdev->dev, "interrupt not available.\n"); |
@@ -338,29 +334,14 @@ static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev) | |||
338 | } | 334 | } |
339 | } | 335 | } |
340 | 336 | ||
341 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 337 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, |
342 | &stk17ta8_rtc_ops, THIS_MODULE); | 338 | &stk17ta8_rtc_ops, THIS_MODULE); |
343 | if (IS_ERR(rtc)) { | 339 | if (IS_ERR(pdata->rtc)) |
344 | ret = PTR_ERR(rtc); | 340 | return PTR_ERR(pdata->rtc); |
345 | goto out; | 341 | |
346 | } | ||
347 | pdata->rtc = rtc; | ||
348 | pdata->last_jiffies = jiffies; | ||
349 | platform_set_drvdata(pdev, pdata); | ||
350 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); | 342 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); |
351 | if (ret) | 343 | if (ret) |
352 | goto out; | ||
353 | return 0; | ||
354 | out: | ||
355 | if (pdata->rtc) | ||
356 | rtc_device_unregister(pdata->rtc); | 344 | rtc_device_unregister(pdata->rtc); |
357 | if (pdata->irq > 0) | ||
358 | free_irq(pdata->irq, pdev); | ||
359 | if (ioaddr) | ||
360 | iounmap(ioaddr); | ||
361 | if (pdata->baseaddr) | ||
362 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
363 | kfree(pdata); | ||
364 | return ret; | 345 | return ret; |
365 | } | 346 | } |
366 | 347 | ||
@@ -370,13 +351,8 @@ static int __devexit stk17ta8_rtc_remove(struct platform_device *pdev) | |||
370 | 351 | ||
371 | sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); | 352 | sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr); |
372 | rtc_device_unregister(pdata->rtc); | 353 | rtc_device_unregister(pdata->rtc); |
373 | if (pdata->irq > 0) { | 354 | if (pdata->irq > 0) |
374 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); | 355 | writeb(0, pdata->ioaddr + RTC_INTERRUPTS); |
375 | free_irq(pdata->irq, pdev); | ||
376 | } | ||
377 | iounmap(pdata->ioaddr); | ||
378 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | ||
379 | kfree(pdata); | ||
380 | return 0; | 356 | return 0; |
381 | } | 357 | } |
382 | 358 | ||
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 4a6ed1104fbb..9ee81d8aa7c0 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c | |||
@@ -17,6 +17,7 @@ | |||
17 | struct tx4939rtc_plat_data { | 17 | struct tx4939rtc_plat_data { |
18 | struct rtc_device *rtc; | 18 | struct rtc_device *rtc; |
19 | struct tx4939_rtc_reg __iomem *rtcreg; | 19 | struct tx4939_rtc_reg __iomem *rtcreg; |
20 | spinlock_t lock; | ||
20 | }; | 21 | }; |
21 | 22 | ||
22 | static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev) | 23 | static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev) |
@@ -52,14 +53,14 @@ static int tx4939_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
52 | buf[3] = secs >> 8; | 53 | buf[3] = secs >> 8; |
53 | buf[4] = secs >> 16; | 54 | buf[4] = secs >> 16; |
54 | buf[5] = secs >> 24; | 55 | buf[5] = secs >> 24; |
55 | spin_lock_irq(&pdata->rtc->irq_lock); | 56 | spin_lock_irq(&pdata->lock); |
56 | __raw_writel(0, &rtcreg->adr); | 57 | __raw_writel(0, &rtcreg->adr); |
57 | for (i = 0; i < 6; i++) | 58 | for (i = 0; i < 6; i++) |
58 | __raw_writel(buf[i], &rtcreg->dat); | 59 | __raw_writel(buf[i], &rtcreg->dat); |
59 | ret = tx4939_rtc_cmd(rtcreg, | 60 | ret = tx4939_rtc_cmd(rtcreg, |
60 | TX4939_RTCCTL_COMMAND_SETTIME | | 61 | TX4939_RTCCTL_COMMAND_SETTIME | |
61 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 62 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
62 | spin_unlock_irq(&pdata->rtc->irq_lock); | 63 | spin_unlock_irq(&pdata->lock); |
63 | return ret; | 64 | return ret; |
64 | } | 65 | } |
65 | 66 | ||
@@ -71,18 +72,18 @@ static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
71 | unsigned long sec; | 72 | unsigned long sec; |
72 | unsigned char buf[6]; | 73 | unsigned char buf[6]; |
73 | 74 | ||
74 | spin_lock_irq(&pdata->rtc->irq_lock); | 75 | spin_lock_irq(&pdata->lock); |
75 | ret = tx4939_rtc_cmd(rtcreg, | 76 | ret = tx4939_rtc_cmd(rtcreg, |
76 | TX4939_RTCCTL_COMMAND_GETTIME | | 77 | TX4939_RTCCTL_COMMAND_GETTIME | |
77 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 78 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
78 | if (ret) { | 79 | if (ret) { |
79 | spin_unlock_irq(&pdata->rtc->irq_lock); | 80 | spin_unlock_irq(&pdata->lock); |
80 | return ret; | 81 | return ret; |
81 | } | 82 | } |
82 | __raw_writel(2, &rtcreg->adr); | 83 | __raw_writel(2, &rtcreg->adr); |
83 | for (i = 2; i < 6; i++) | 84 | for (i = 2; i < 6; i++) |
84 | buf[i] = __raw_readl(&rtcreg->dat); | 85 | buf[i] = __raw_readl(&rtcreg->dat); |
85 | spin_unlock_irq(&pdata->rtc->irq_lock); | 86 | spin_unlock_irq(&pdata->lock); |
86 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; | 87 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; |
87 | rtc_time_to_tm(sec, tm); | 88 | rtc_time_to_tm(sec, tm); |
88 | return rtc_valid_tm(tm); | 89 | return rtc_valid_tm(tm); |
@@ -110,13 +111,13 @@ static int tx4939_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
110 | buf[3] = sec >> 8; | 111 | buf[3] = sec >> 8; |
111 | buf[4] = sec >> 16; | 112 | buf[4] = sec >> 16; |
112 | buf[5] = sec >> 24; | 113 | buf[5] = sec >> 24; |
113 | spin_lock_irq(&pdata->rtc->irq_lock); | 114 | spin_lock_irq(&pdata->lock); |
114 | __raw_writel(0, &rtcreg->adr); | 115 | __raw_writel(0, &rtcreg->adr); |
115 | for (i = 0; i < 6; i++) | 116 | for (i = 0; i < 6; i++) |
116 | __raw_writel(buf[i], &rtcreg->dat); | 117 | __raw_writel(buf[i], &rtcreg->dat); |
117 | ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM | | 118 | ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM | |
118 | (alrm->enabled ? TX4939_RTCCTL_ALME : 0)); | 119 | (alrm->enabled ? TX4939_RTCCTL_ALME : 0)); |
119 | spin_unlock_irq(&pdata->rtc->irq_lock); | 120 | spin_unlock_irq(&pdata->lock); |
120 | return ret; | 121 | return ret; |
121 | } | 122 | } |
122 | 123 | ||
@@ -129,12 +130,12 @@ static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
129 | unsigned char buf[6]; | 130 | unsigned char buf[6]; |
130 | u32 ctl; | 131 | u32 ctl; |
131 | 132 | ||
132 | spin_lock_irq(&pdata->rtc->irq_lock); | 133 | spin_lock_irq(&pdata->lock); |
133 | ret = tx4939_rtc_cmd(rtcreg, | 134 | ret = tx4939_rtc_cmd(rtcreg, |
134 | TX4939_RTCCTL_COMMAND_GETALARM | | 135 | TX4939_RTCCTL_COMMAND_GETALARM | |
135 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); | 136 | (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME)); |
136 | if (ret) { | 137 | if (ret) { |
137 | spin_unlock_irq(&pdata->rtc->irq_lock); | 138 | spin_unlock_irq(&pdata->lock); |
138 | return ret; | 139 | return ret; |
139 | } | 140 | } |
140 | __raw_writel(2, &rtcreg->adr); | 141 | __raw_writel(2, &rtcreg->adr); |
@@ -143,7 +144,7 @@ static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
143 | ctl = __raw_readl(&rtcreg->ctl); | 144 | ctl = __raw_readl(&rtcreg->ctl); |
144 | alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0; | 145 | alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0; |
145 | alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0; | 146 | alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0; |
146 | spin_unlock_irq(&pdata->rtc->irq_lock); | 147 | spin_unlock_irq(&pdata->lock); |
147 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; | 148 | sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; |
148 | rtc_time_to_tm(sec, &alrm->time); | 149 | rtc_time_to_tm(sec, &alrm->time); |
149 | return rtc_valid_tm(&alrm->time); | 150 | return rtc_valid_tm(&alrm->time); |
@@ -153,11 +154,11 @@ static int tx4939_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
153 | { | 154 | { |
154 | struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); | 155 | struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev); |
155 | 156 | ||
156 | spin_lock_irq(&pdata->rtc->irq_lock); | 157 | spin_lock_irq(&pdata->lock); |
157 | tx4939_rtc_cmd(pdata->rtcreg, | 158 | tx4939_rtc_cmd(pdata->rtcreg, |
158 | TX4939_RTCCTL_COMMAND_NOP | | 159 | TX4939_RTCCTL_COMMAND_NOP | |
159 | (enabled ? TX4939_RTCCTL_ALME : 0)); | 160 | (enabled ? TX4939_RTCCTL_ALME : 0)); |
160 | spin_unlock_irq(&pdata->rtc->irq_lock); | 161 | spin_unlock_irq(&pdata->lock); |
161 | return 0; | 162 | return 0; |
162 | } | 163 | } |
163 | 164 | ||
@@ -167,13 +168,14 @@ static irqreturn_t tx4939_rtc_interrupt(int irq, void *dev_id) | |||
167 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 168 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
168 | unsigned long events = RTC_IRQF; | 169 | unsigned long events = RTC_IRQF; |
169 | 170 | ||
170 | spin_lock(&pdata->rtc->irq_lock); | 171 | spin_lock(&pdata->lock); |
171 | if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) { | 172 | if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) { |
172 | events |= RTC_AF; | 173 | events |= RTC_AF; |
173 | tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP); | 174 | tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP); |
174 | } | 175 | } |
175 | spin_unlock(&pdata->rtc->irq_lock); | 176 | spin_unlock(&pdata->lock); |
176 | rtc_update_irq(pdata->rtc, 1, events); | 177 | if (likely(pdata->rtc)) |
178 | rtc_update_irq(pdata->rtc, 1, events); | ||
177 | return IRQ_HANDLED; | 179 | return IRQ_HANDLED; |
178 | } | 180 | } |
179 | 181 | ||
@@ -194,13 +196,13 @@ static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, | |||
194 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 196 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
195 | ssize_t count; | 197 | ssize_t count; |
196 | 198 | ||
197 | spin_lock_irq(&pdata->rtc->irq_lock); | 199 | spin_lock_irq(&pdata->lock); |
198 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; | 200 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; |
199 | count++, size--) { | 201 | count++, size--) { |
200 | __raw_writel(pos++, &rtcreg->adr); | 202 | __raw_writel(pos++, &rtcreg->adr); |
201 | *buf++ = __raw_readl(&rtcreg->dat); | 203 | *buf++ = __raw_readl(&rtcreg->dat); |
202 | } | 204 | } |
203 | spin_unlock_irq(&pdata->rtc->irq_lock); | 205 | spin_unlock_irq(&pdata->lock); |
204 | return count; | 206 | return count; |
205 | } | 207 | } |
206 | 208 | ||
@@ -213,13 +215,13 @@ static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj, | |||
213 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; | 215 | struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg; |
214 | ssize_t count; | 216 | ssize_t count; |
215 | 217 | ||
216 | spin_lock_irq(&pdata->rtc->irq_lock); | 218 | spin_lock_irq(&pdata->lock); |
217 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; | 219 | for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE; |
218 | count++, size--) { | 220 | count++, size--) { |
219 | __raw_writel(pos++, &rtcreg->adr); | 221 | __raw_writel(pos++, &rtcreg->adr); |
220 | __raw_writel(*buf++, &rtcreg->dat); | 222 | __raw_writel(*buf++, &rtcreg->dat); |
221 | } | 223 | } |
222 | spin_unlock_irq(&pdata->rtc->irq_lock); | 224 | spin_unlock_irq(&pdata->lock); |
223 | return count; | 225 | return count; |
224 | } | 226 | } |
225 | 227 | ||
@@ -259,6 +261,7 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) | |||
259 | if (!pdata->rtcreg) | 261 | if (!pdata->rtcreg) |
260 | return -EBUSY; | 262 | return -EBUSY; |
261 | 263 | ||
264 | spin_lock_init(&pdata->lock); | ||
262 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | 265 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); |
263 | if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, | 266 | if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt, |
264 | IRQF_DISABLED, pdev->name, &pdev->dev) < 0) | 267 | IRQF_DISABLED, pdev->name, &pdev->dev) < 0) |
@@ -277,14 +280,12 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev) | |||
277 | static int __exit tx4939_rtc_remove(struct platform_device *pdev) | 280 | static int __exit tx4939_rtc_remove(struct platform_device *pdev) |
278 | { | 281 | { |
279 | struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev); | 282 | struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev); |
280 | struct rtc_device *rtc = pdata->rtc; | ||
281 | 283 | ||
282 | spin_lock_irq(&rtc->irq_lock); | ||
283 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | ||
284 | spin_unlock_irq(&rtc->irq_lock); | ||
285 | sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); | 284 | sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr); |
286 | rtc_device_unregister(rtc); | 285 | rtc_device_unregister(pdata->rtc); |
287 | platform_set_drvdata(pdev, NULL); | 286 | spin_lock_irq(&pdata->lock); |
287 | tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP); | ||
288 | spin_unlock_irq(&pdata->lock); | ||
288 | return 0; | 289 | return 0; |
289 | } | 290 | } |
290 | 291 | ||
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index ad741afd47d8..bed4cab07043 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c | |||
@@ -304,7 +304,6 @@ static int rtc_probe(struct platform_device *pdev) | |||
304 | { | 304 | { |
305 | struct v3020_platform_data *pdata = pdev->dev.platform_data; | 305 | struct v3020_platform_data *pdata = pdev->dev.platform_data; |
306 | struct v3020 *chip; | 306 | struct v3020 *chip; |
307 | struct rtc_device *rtc; | ||
308 | int retval = -EBUSY; | 307 | int retval = -EBUSY; |
309 | int i; | 308 | int i; |
310 | int temp; | 309 | int temp; |
@@ -353,13 +352,12 @@ static int rtc_probe(struct platform_device *pdev) | |||
353 | 352 | ||
354 | platform_set_drvdata(pdev, chip); | 353 | platform_set_drvdata(pdev, chip); |
355 | 354 | ||
356 | rtc = rtc_device_register("v3020", | 355 | chip->rtc = rtc_device_register("v3020", |
357 | &pdev->dev, &v3020_rtc_ops, THIS_MODULE); | 356 | &pdev->dev, &v3020_rtc_ops, THIS_MODULE); |
358 | if (IS_ERR(rtc)) { | 357 | if (IS_ERR(chip->rtc)) { |
359 | retval = PTR_ERR(rtc); | 358 | retval = PTR_ERR(chip->rtc); |
360 | goto err_io; | 359 | goto err_io; |
361 | } | 360 | } |
362 | chip->rtc = rtc; | ||
363 | 361 | ||
364 | return 0; | 362 | return 0; |
365 | 363 | ||
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index fadddac1e5a4..c3244244e8cf 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
@@ -327,7 +327,7 @@ static int __devinit rtc_probe(struct platform_device *pdev) | |||
327 | if (!res) | 327 | if (!res) |
328 | return -EBUSY; | 328 | return -EBUSY; |
329 | 329 | ||
330 | rtc1_base = ioremap(res->start, res->end - res->start + 1); | 330 | rtc1_base = ioremap(res->start, resource_size(res)); |
331 | if (!rtc1_base) | 331 | if (!rtc1_base) |
332 | return -EBUSY; | 332 | return -EBUSY; |
333 | 333 | ||
@@ -337,7 +337,7 @@ static int __devinit rtc_probe(struct platform_device *pdev) | |||
337 | goto err_rtc1_iounmap; | 337 | goto err_rtc1_iounmap; |
338 | } | 338 | } |
339 | 339 | ||
340 | rtc2_base = ioremap(res->start, res->end - res->start + 1); | 340 | rtc2_base = ioremap(res->start, resource_size(res)); |
341 | if (!rtc2_base) { | 341 | if (!rtc2_base) { |
342 | retval = -EBUSY; | 342 | retval = -EBUSY; |
343 | goto err_rtc1_iounmap; | 343 | goto err_rtc1_iounmap; |
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 79795cdf6ed8..000c7e481e59 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c | |||
@@ -485,7 +485,7 @@ static int __devexit wm831x_rtc_remove(struct platform_device *pdev) | |||
485 | return 0; | 485 | return 0; |
486 | } | 486 | } |
487 | 487 | ||
488 | static struct dev_pm_ops wm831x_rtc_pm_ops = { | 488 | static const struct dev_pm_ops wm831x_rtc_pm_ops = { |
489 | .suspend = wm831x_rtc_suspend, | 489 | .suspend = wm831x_rtc_suspend, |
490 | .resume = wm831x_rtc_resume, | 490 | .resume = wm831x_rtc_resume, |
491 | 491 | ||
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index f16486635a8e..f1e440521c54 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c | |||
@@ -354,8 +354,9 @@ static const struct rtc_class_ops wm8350_rtc_ops = { | |||
354 | }; | 354 | }; |
355 | 355 | ||
356 | #ifdef CONFIG_PM | 356 | #ifdef CONFIG_PM |
357 | static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 357 | static int wm8350_rtc_suspend(struct device *dev) |
358 | { | 358 | { |
359 | struct platform_device *pdev = to_platform_device(dev); | ||
359 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); | 360 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); |
360 | int ret = 0; | 361 | int ret = 0; |
361 | u16 reg; | 362 | u16 reg; |
@@ -373,8 +374,9 @@ static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
373 | return ret; | 374 | return ret; |
374 | } | 375 | } |
375 | 376 | ||
376 | static int wm8350_rtc_resume(struct platform_device *pdev) | 377 | static int wm8350_rtc_resume(struct device *dev) |
377 | { | 378 | { |
379 | struct platform_device *pdev = to_platform_device(dev); | ||
378 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); | 380 | struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); |
379 | int ret; | 381 | int ret; |
380 | 382 | ||
@@ -484,13 +486,17 @@ static int __devexit wm8350_rtc_remove(struct platform_device *pdev) | |||
484 | return 0; | 486 | return 0; |
485 | } | 487 | } |
486 | 488 | ||
489 | static struct dev_pm_ops wm8350_rtc_pm_ops = { | ||
490 | .suspend = wm8350_rtc_suspend, | ||
491 | .resume = wm8350_rtc_resume, | ||
492 | }; | ||
493 | |||
487 | static struct platform_driver wm8350_rtc_driver = { | 494 | static struct platform_driver wm8350_rtc_driver = { |
488 | .probe = wm8350_rtc_probe, | 495 | .probe = wm8350_rtc_probe, |
489 | .remove = __devexit_p(wm8350_rtc_remove), | 496 | .remove = __devexit_p(wm8350_rtc_remove), |
490 | .suspend = wm8350_rtc_suspend, | ||
491 | .resume = wm8350_rtc_resume, | ||
492 | .driver = { | 497 | .driver = { |
493 | .name = "wm8350-rtc", | 498 | .name = "wm8350-rtc", |
499 | .pm = &wm8350_rtc_pm_ops, | ||
494 | }, | 500 | }, |
495 | }; | 501 | }; |
496 | 502 | ||
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 6583c1a8b070..9aae49139a0a 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c | |||
@@ -155,11 +155,11 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr) | |||
155 | } | 155 | } |
156 | 156 | ||
157 | static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | 157 | static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, |
158 | int datetoo, u8 reg_base, unsigned char alm_enable) | 158 | u8 reg_base, unsigned char alm_enable) |
159 | { | 159 | { |
160 | int i, xfer, nbytes; | 160 | int i, xfer; |
161 | unsigned char buf[8]; | ||
162 | unsigned char rdata[10] = { 0, reg_base }; | 161 | unsigned char rdata[10] = { 0, reg_base }; |
162 | unsigned char *buf = rdata + 2; | ||
163 | 163 | ||
164 | static const unsigned char wel[3] = { 0, X1205_REG_SR, | 164 | static const unsigned char wel[3] = { 0, X1205_REG_SR, |
165 | X1205_SR_WEL }; | 165 | X1205_SR_WEL }; |
@@ -170,9 +170,9 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
170 | static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; | 170 | static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; |
171 | 171 | ||
172 | dev_dbg(&client->dev, | 172 | dev_dbg(&client->dev, |
173 | "%s: secs=%d, mins=%d, hours=%d\n", | 173 | "%s: sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d\n", |
174 | __func__, | 174 | __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, |
175 | tm->tm_sec, tm->tm_min, tm->tm_hour); | 175 | tm->tm_mon, tm->tm_year, tm->tm_wday); |
176 | 176 | ||
177 | buf[CCR_SEC] = bin2bcd(tm->tm_sec); | 177 | buf[CCR_SEC] = bin2bcd(tm->tm_sec); |
178 | buf[CCR_MIN] = bin2bcd(tm->tm_min); | 178 | buf[CCR_MIN] = bin2bcd(tm->tm_min); |
@@ -180,23 +180,15 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
180 | /* set hour and 24hr bit */ | 180 | /* set hour and 24hr bit */ |
181 | buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL; | 181 | buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL; |
182 | 182 | ||
183 | /* should we also set the date? */ | 183 | buf[CCR_MDAY] = bin2bcd(tm->tm_mday); |
184 | if (datetoo) { | ||
185 | dev_dbg(&client->dev, | ||
186 | "%s: mday=%d, mon=%d, year=%d, wday=%d\n", | ||
187 | __func__, | ||
188 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
189 | 184 | ||
190 | buf[CCR_MDAY] = bin2bcd(tm->tm_mday); | 185 | /* month, 1 - 12 */ |
186 | buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1); | ||
191 | 187 | ||
192 | /* month, 1 - 12 */ | 188 | /* year, since the rtc epoch*/ |
193 | buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1); | 189 | buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100); |
194 | 190 | buf[CCR_WDAY] = tm->tm_wday & 0x07; | |
195 | /* year, since the rtc epoch*/ | 191 | buf[CCR_Y2K] = bin2bcd((tm->tm_year + 1900) / 100); |
196 | buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100); | ||
197 | buf[CCR_WDAY] = tm->tm_wday & 0x07; | ||
198 | buf[CCR_Y2K] = bin2bcd((tm->tm_year + 1900) / 100); | ||
199 | } | ||
200 | 192 | ||
201 | /* If writing alarm registers, set compare bits on registers 0-4 */ | 193 | /* If writing alarm registers, set compare bits on registers 0-4 */ |
202 | if (reg_base < X1205_CCR_BASE) | 194 | if (reg_base < X1205_CCR_BASE) |
@@ -214,17 +206,8 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
214 | return -EIO; | 206 | return -EIO; |
215 | } | 207 | } |
216 | 208 | ||
217 | 209 | xfer = i2c_master_send(client, rdata, sizeof(rdata)); | |
218 | /* write register's data */ | 210 | if (xfer != sizeof(rdata)) { |
219 | if (datetoo) | ||
220 | nbytes = 8; | ||
221 | else | ||
222 | nbytes = 3; | ||
223 | for (i = 0; i < nbytes; i++) | ||
224 | rdata[2+i] = buf[i]; | ||
225 | |||
226 | xfer = i2c_master_send(client, rdata, nbytes+2); | ||
227 | if (xfer != nbytes+2) { | ||
228 | dev_err(&client->dev, | 211 | dev_err(&client->dev, |
229 | "%s: result=%d addr=%02x, data=%02x\n", | 212 | "%s: result=%d addr=%02x, data=%02x\n", |
230 | __func__, | 213 | __func__, |
@@ -282,7 +265,7 @@ static int x1205_fix_osc(struct i2c_client *client) | |||
282 | 265 | ||
283 | memset(&tm, 0, sizeof(tm)); | 266 | memset(&tm, 0, sizeof(tm)); |
284 | 267 | ||
285 | err = x1205_set_datetime(client, &tm, 1, X1205_CCR_BASE, 0); | 268 | err = x1205_set_datetime(client, &tm, X1205_CCR_BASE, 0); |
286 | if (err < 0) | 269 | if (err < 0) |
287 | dev_err(&client->dev, "unable to restart the oscillator\n"); | 270 | dev_err(&client->dev, "unable to restart the oscillator\n"); |
288 | 271 | ||
@@ -481,7 +464,7 @@ static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
481 | static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 464 | static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
482 | { | 465 | { |
483 | return x1205_set_datetime(to_i2c_client(dev), | 466 | return x1205_set_datetime(to_i2c_client(dev), |
484 | &alrm->time, 1, X1205_ALM0_BASE, alrm->enabled); | 467 | &alrm->time, X1205_ALM0_BASE, alrm->enabled); |
485 | } | 468 | } |
486 | 469 | ||
487 | static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) | 470 | static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) |
@@ -493,7 +476,7 @@ static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
493 | static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm) | 476 | static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm) |
494 | { | 477 | { |
495 | return x1205_set_datetime(to_i2c_client(dev), | 478 | return x1205_set_datetime(to_i2c_client(dev), |
496 | tm, 1, X1205_CCR_BASE, 0); | 479 | tm, X1205_CCR_BASE, 0); |
497 | } | 480 | } |
498 | 481 | ||
499 | static int x1205_rtc_proc(struct device *dev, struct seq_file *seq) | 482 | static int x1205_rtc_proc(struct device *dev, struct seq_file *seq) |