diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-at91rm9200.c | 50 | ||||
-rw-r--r-- | drivers/rtc/rtc-at91rm9200.h | 1 | ||||
-rw-r--r-- | drivers/rtc/rtc-da9052.c | 8 | ||||
-rw-r--r-- | drivers/rtc/rtc-mv.c | 28 |
4 files changed, 58 insertions, 29 deletions
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 434ebc3a99dc..0a9f27e094ea 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
@@ -44,6 +44,7 @@ static DECLARE_COMPLETION(at91_rtc_updated); | |||
44 | static unsigned int at91_alarm_year = AT91_RTC_EPOCH; | 44 | static unsigned int at91_alarm_year = AT91_RTC_EPOCH; |
45 | static void __iomem *at91_rtc_regs; | 45 | static void __iomem *at91_rtc_regs; |
46 | static int irq; | 46 | static int irq; |
47 | static u32 at91_rtc_imr; | ||
47 | 48 | ||
48 | /* | 49 | /* |
49 | * Decode time/date into rtc_time structure | 50 | * Decode time/date into rtc_time structure |
@@ -108,9 +109,11 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
108 | cr = at91_rtc_read(AT91_RTC_CR); | 109 | cr = at91_rtc_read(AT91_RTC_CR); |
109 | at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); | 110 | at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); |
110 | 111 | ||
112 | at91_rtc_imr |= AT91_RTC_ACKUPD; | ||
111 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ACKUPD); | 113 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ACKUPD); |
112 | wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */ | 114 | wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */ |
113 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); | 115 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); |
116 | at91_rtc_imr &= ~AT91_RTC_ACKUPD; | ||
114 | 117 | ||
115 | at91_rtc_write(AT91_RTC_TIMR, | 118 | at91_rtc_write(AT91_RTC_TIMR, |
116 | bin2bcd(tm->tm_sec) << 0 | 119 | bin2bcd(tm->tm_sec) << 0 |
@@ -142,7 +145,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
142 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | 145 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); |
143 | tm->tm_year = at91_alarm_year - 1900; | 146 | tm->tm_year = at91_alarm_year - 1900; |
144 | 147 | ||
145 | alrm->enabled = (at91_rtc_read(AT91_RTC_IMR) & AT91_RTC_ALARM) | 148 | alrm->enabled = (at91_rtc_imr & AT91_RTC_ALARM) |
146 | ? 1 : 0; | 149 | ? 1 : 0; |
147 | 150 | ||
148 | dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, | 151 | dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, |
@@ -168,6 +171,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
168 | tm.tm_sec = alrm->time.tm_sec; | 171 | tm.tm_sec = alrm->time.tm_sec; |
169 | 172 | ||
170 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); | 173 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); |
174 | at91_rtc_imr &= ~AT91_RTC_ALARM; | ||
171 | at91_rtc_write(AT91_RTC_TIMALR, | 175 | at91_rtc_write(AT91_RTC_TIMALR, |
172 | bin2bcd(tm.tm_sec) << 0 | 176 | bin2bcd(tm.tm_sec) << 0 |
173 | | bin2bcd(tm.tm_min) << 8 | 177 | | bin2bcd(tm.tm_min) << 8 |
@@ -180,6 +184,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
180 | 184 | ||
181 | if (alrm->enabled) { | 185 | if (alrm->enabled) { |
182 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | 186 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); |
187 | at91_rtc_imr |= AT91_RTC_ALARM; | ||
183 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); | 188 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); |
184 | } | 189 | } |
185 | 190 | ||
@@ -196,9 +201,12 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
196 | 201 | ||
197 | if (enabled) { | 202 | if (enabled) { |
198 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | 203 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); |
204 | at91_rtc_imr |= AT91_RTC_ALARM; | ||
199 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); | 205 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); |
200 | } else | 206 | } else { |
201 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); | 207 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); |
208 | at91_rtc_imr &= ~AT91_RTC_ALARM; | ||
209 | } | ||
202 | 210 | ||
203 | return 0; | 211 | return 0; |
204 | } | 212 | } |
@@ -207,12 +215,10 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
207 | */ | 215 | */ |
208 | static int at91_rtc_proc(struct device *dev, struct seq_file *seq) | 216 | static int at91_rtc_proc(struct device *dev, struct seq_file *seq) |
209 | { | 217 | { |
210 | unsigned long imr = at91_rtc_read(AT91_RTC_IMR); | ||
211 | |||
212 | seq_printf(seq, "update_IRQ\t: %s\n", | 218 | seq_printf(seq, "update_IRQ\t: %s\n", |
213 | (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); | 219 | (at91_rtc_imr & AT91_RTC_ACKUPD) ? "yes" : "no"); |
214 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 220 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
215 | (imr & AT91_RTC_SECEV) ? "yes" : "no"); | 221 | (at91_rtc_imr & AT91_RTC_SECEV) ? "yes" : "no"); |
216 | 222 | ||
217 | return 0; | 223 | return 0; |
218 | } | 224 | } |
@@ -227,7 +233,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id) | |||
227 | unsigned int rtsr; | 233 | unsigned int rtsr; |
228 | unsigned long events = 0; | 234 | unsigned long events = 0; |
229 | 235 | ||
230 | rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read(AT91_RTC_IMR); | 236 | rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_imr; |
231 | if (rtsr) { /* this interrupt is shared! Is it ours? */ | 237 | if (rtsr) { /* this interrupt is shared! Is it ours? */ |
232 | if (rtsr & AT91_RTC_ALARM) | 238 | if (rtsr & AT91_RTC_ALARM) |
233 | events |= (RTC_AF | RTC_IRQF); | 239 | events |= (RTC_AF | RTC_IRQF); |
@@ -291,6 +297,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) | |||
291 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | | 297 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | |
292 | AT91_RTC_SECEV | AT91_RTC_TIMEV | | 298 | AT91_RTC_SECEV | AT91_RTC_TIMEV | |
293 | AT91_RTC_CALEV); | 299 | AT91_RTC_CALEV); |
300 | at91_rtc_imr = 0; | ||
294 | 301 | ||
295 | ret = request_irq(irq, at91_rtc_interrupt, | 302 | ret = request_irq(irq, at91_rtc_interrupt, |
296 | IRQF_SHARED, | 303 | IRQF_SHARED, |
@@ -329,6 +336,7 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) | |||
329 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | | 336 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | |
330 | AT91_RTC_SECEV | AT91_RTC_TIMEV | | 337 | AT91_RTC_SECEV | AT91_RTC_TIMEV | |
331 | AT91_RTC_CALEV); | 338 | AT91_RTC_CALEV); |
339 | at91_rtc_imr = 0; | ||
332 | free_irq(irq, pdev); | 340 | free_irq(irq, pdev); |
333 | 341 | ||
334 | rtc_device_unregister(rtc); | 342 | rtc_device_unregister(rtc); |
@@ -341,31 +349,35 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) | |||
341 | 349 | ||
342 | /* AT91RM9200 RTC Power management control */ | 350 | /* AT91RM9200 RTC Power management control */ |
343 | 351 | ||
344 | static u32 at91_rtc_imr; | 352 | static u32 at91_rtc_bkpimr; |
353 | |||
345 | 354 | ||
346 | static int at91_rtc_suspend(struct device *dev) | 355 | static int at91_rtc_suspend(struct device *dev) |
347 | { | 356 | { |
348 | /* this IRQ is shared with DBGU and other hardware which isn't | 357 | /* this IRQ is shared with DBGU and other hardware which isn't |
349 | * necessarily doing PM like we are... | 358 | * necessarily doing PM like we are... |
350 | */ | 359 | */ |
351 | at91_rtc_imr = at91_rtc_read(AT91_RTC_IMR) | 360 | at91_rtc_bkpimr = at91_rtc_imr & (AT91_RTC_ALARM|AT91_RTC_SECEV); |
352 | & (AT91_RTC_ALARM|AT91_RTC_SECEV); | 361 | if (at91_rtc_bkpimr) { |
353 | if (at91_rtc_imr) { | 362 | if (device_may_wakeup(dev)) { |
354 | if (device_may_wakeup(dev)) | ||
355 | enable_irq_wake(irq); | 363 | enable_irq_wake(irq); |
356 | else | 364 | } else { |
357 | at91_rtc_write(AT91_RTC_IDR, at91_rtc_imr); | 365 | at91_rtc_write(AT91_RTC_IDR, at91_rtc_bkpimr); |
358 | } | 366 | at91_rtc_imr &= ~at91_rtc_bkpimr; |
367 | } | ||
368 | } | ||
359 | return 0; | 369 | return 0; |
360 | } | 370 | } |
361 | 371 | ||
362 | static int at91_rtc_resume(struct device *dev) | 372 | static int at91_rtc_resume(struct device *dev) |
363 | { | 373 | { |
364 | if (at91_rtc_imr) { | 374 | if (at91_rtc_bkpimr) { |
365 | if (device_may_wakeup(dev)) | 375 | if (device_may_wakeup(dev)) { |
366 | disable_irq_wake(irq); | 376 | disable_irq_wake(irq); |
367 | else | 377 | } else { |
368 | at91_rtc_write(AT91_RTC_IER, at91_rtc_imr); | 378 | at91_rtc_imr |= at91_rtc_bkpimr; |
379 | at91_rtc_write(AT91_RTC_IER, at91_rtc_bkpimr); | ||
380 | } | ||
369 | } | 381 | } |
370 | return 0; | 382 | return 0; |
371 | } | 383 | } |
diff --git a/drivers/rtc/rtc-at91rm9200.h b/drivers/rtc/rtc-at91rm9200.h index da1945e5f714..5f940b6844cb 100644 --- a/drivers/rtc/rtc-at91rm9200.h +++ b/drivers/rtc/rtc-at91rm9200.h | |||
@@ -64,7 +64,6 @@ | |||
64 | #define AT91_RTC_SCCR 0x1c /* Status Clear Command Register */ | 64 | #define AT91_RTC_SCCR 0x1c /* Status Clear Command Register */ |
65 | #define AT91_RTC_IER 0x20 /* Interrupt Enable Register */ | 65 | #define AT91_RTC_IER 0x20 /* Interrupt Enable Register */ |
66 | #define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */ | 66 | #define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */ |
67 | #define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */ | ||
68 | 67 | ||
69 | #define AT91_RTC_VER 0x2c /* Valid Entry Register */ | 68 | #define AT91_RTC_VER 0x2c /* Valid Entry Register */ |
70 | #define AT91_RTC_NVTIM (1 << 0) /* Non valid Time */ | 69 | #define AT91_RTC_NVTIM (1 << 0) /* Non valid Time */ |
diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index 0dde688ca09b..969abbad7fe3 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c | |||
@@ -239,11 +239,9 @@ static int da9052_rtc_probe(struct platform_device *pdev) | |||
239 | 239 | ||
240 | rtc->da9052 = dev_get_drvdata(pdev->dev.parent); | 240 | rtc->da9052 = dev_get_drvdata(pdev->dev.parent); |
241 | platform_set_drvdata(pdev, rtc); | 241 | platform_set_drvdata(pdev, rtc); |
242 | rtc->irq = platform_get_irq_byname(pdev, "ALM"); | 242 | rtc->irq = DA9052_IRQ_ALARM; |
243 | ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, | 243 | ret = da9052_request_irq(rtc->da9052, rtc->irq, "ALM", |
244 | da9052_rtc_irq, | 244 | da9052_rtc_irq, rtc); |
245 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
246 | "ALM", rtc); | ||
247 | if (ret != 0) { | 245 | if (ret != 0) { |
248 | rtc_err(rtc->da9052, "irq registration failed: %d\n", ret); | 246 | rtc_err(rtc->da9052, "irq registration failed: %d\n", ret); |
249 | return ret; | 247 | return ret; |
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index 57233c885998..8f87fec27ce7 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/clk.h> | ||
17 | #include <linux/gfp.h> | 18 | #include <linux/gfp.h> |
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | 20 | ||
@@ -41,6 +42,7 @@ struct rtc_plat_data { | |||
41 | struct rtc_device *rtc; | 42 | struct rtc_device *rtc; |
42 | void __iomem *ioaddr; | 43 | void __iomem *ioaddr; |
43 | int irq; | 44 | int irq; |
45 | struct clk *clk; | ||
44 | }; | 46 | }; |
45 | 47 | ||
46 | static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm) | 48 | static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -221,6 +223,7 @@ static int mv_rtc_probe(struct platform_device *pdev) | |||
221 | struct rtc_plat_data *pdata; | 223 | struct rtc_plat_data *pdata; |
222 | resource_size_t size; | 224 | resource_size_t size; |
223 | u32 rtc_time; | 225 | u32 rtc_time; |
226 | int ret = 0; | ||
224 | 227 | ||
225 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 228 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
226 | if (!res) | 229 | if (!res) |
@@ -239,11 +242,17 @@ static int mv_rtc_probe(struct platform_device *pdev) | |||
239 | if (!pdata->ioaddr) | 242 | if (!pdata->ioaddr) |
240 | return -ENOMEM; | 243 | return -ENOMEM; |
241 | 244 | ||
245 | pdata->clk = devm_clk_get(&pdev->dev, NULL); | ||
246 | /* Not all SoCs require a clock.*/ | ||
247 | if (!IS_ERR(pdata->clk)) | ||
248 | clk_prepare_enable(pdata->clk); | ||
249 | |||
242 | /* make sure the 24 hours mode is enabled */ | 250 | /* make sure the 24 hours mode is enabled */ |
243 | rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS); | 251 | rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS); |
244 | if (rtc_time & RTC_HOURS_12H_MODE) { | 252 | if (rtc_time & RTC_HOURS_12H_MODE) { |
245 | dev_err(&pdev->dev, "24 Hours mode not supported.\n"); | 253 | dev_err(&pdev->dev, "24 Hours mode not supported.\n"); |
246 | return -EINVAL; | 254 | ret = -EINVAL; |
255 | goto out; | ||
247 | } | 256 | } |
248 | 257 | ||
249 | /* make sure it is actually functional */ | 258 | /* make sure it is actually functional */ |
@@ -252,7 +261,8 @@ static int mv_rtc_probe(struct platform_device *pdev) | |||
252 | rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS); | 261 | rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS); |
253 | if (rtc_time == 0x01000000) { | 262 | if (rtc_time == 0x01000000) { |
254 | dev_err(&pdev->dev, "internal RTC not ticking\n"); | 263 | dev_err(&pdev->dev, "internal RTC not ticking\n"); |
255 | return -ENODEV; | 264 | ret = -ENODEV; |
265 | goto out; | ||
256 | } | 266 | } |
257 | } | 267 | } |
258 | 268 | ||
@@ -268,8 +278,10 @@ static int mv_rtc_probe(struct platform_device *pdev) | |||
268 | } else | 278 | } else |
269 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, | 279 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, |
270 | &mv_rtc_ops, THIS_MODULE); | 280 | &mv_rtc_ops, THIS_MODULE); |
271 | if (IS_ERR(pdata->rtc)) | 281 | if (IS_ERR(pdata->rtc)) { |
272 | return PTR_ERR(pdata->rtc); | 282 | ret = PTR_ERR(pdata->rtc); |
283 | goto out; | ||
284 | } | ||
273 | 285 | ||
274 | if (pdata->irq >= 0) { | 286 | if (pdata->irq >= 0) { |
275 | writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | 287 | writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); |
@@ -282,6 +294,11 @@ static int mv_rtc_probe(struct platform_device *pdev) | |||
282 | } | 294 | } |
283 | 295 | ||
284 | return 0; | 296 | return 0; |
297 | out: | ||
298 | if (!IS_ERR(pdata->clk)) | ||
299 | clk_disable_unprepare(pdata->clk); | ||
300 | |||
301 | return ret; | ||
285 | } | 302 | } |
286 | 303 | ||
287 | static int __exit mv_rtc_remove(struct platform_device *pdev) | 304 | static int __exit mv_rtc_remove(struct platform_device *pdev) |
@@ -292,6 +309,9 @@ static int __exit mv_rtc_remove(struct platform_device *pdev) | |||
292 | device_init_wakeup(&pdev->dev, 0); | 309 | device_init_wakeup(&pdev->dev, 0); |
293 | 310 | ||
294 | rtc_device_unregister(pdata->rtc); | 311 | rtc_device_unregister(pdata->rtc); |
312 | if (!IS_ERR(pdata->clk)) | ||
313 | clk_disable_unprepare(pdata->clk); | ||
314 | |||
295 | return 0; | 315 | return 0; |
296 | } | 316 | } |
297 | 317 | ||