diff options
Diffstat (limited to 'drivers/rtc/rtc-mxc.c')
-rw-r--r-- | drivers/rtc/rtc-mxc.c | 86 |
1 files changed, 36 insertions, 50 deletions
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 878c6ee82901..e697e96612bb 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
9 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
10 | #include <linux/platform_device.h> | 10 | #include <linux/platform_device.h> |
11 | #include <linux/pm_wakeirq.h> | ||
11 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
12 | #include <linux/of.h> | 13 | #include <linux/of.h> |
13 | #include <linux/of_device.h> | 14 | #include <linux/of_device.h> |
@@ -253,20 +254,9 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
253 | /* | 254 | /* |
254 | * This function sets the internal RTC time based on tm in Gregorian date. | 255 | * This function sets the internal RTC time based on tm in Gregorian date. |
255 | */ | 256 | */ |
256 | static int mxc_rtc_set_mmss(struct device *dev, time64_t time) | 257 | static int mxc_rtc_set_time(struct device *dev, struct rtc_time *tm) |
257 | { | 258 | { |
258 | struct rtc_plat_data *pdata = dev_get_drvdata(dev); | 259 | time64_t time = rtc_tm_to_time64(tm); |
259 | |||
260 | /* | ||
261 | * TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only | ||
262 | */ | ||
263 | if (is_imx1_rtc(pdata)) { | ||
264 | struct rtc_time tm; | ||
265 | |||
266 | rtc_time64_to_tm(time, &tm); | ||
267 | tm.tm_year = 70; | ||
268 | time = rtc_tm_to_time64(&tm); | ||
269 | } | ||
270 | 260 | ||
271 | /* Avoid roll-over from reading the different registers */ | 261 | /* Avoid roll-over from reading the different registers */ |
272 | do { | 262 | do { |
@@ -310,7 +300,7 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
310 | /* RTC layer */ | 300 | /* RTC layer */ |
311 | static const struct rtc_class_ops mxc_rtc_ops = { | 301 | static const struct rtc_class_ops mxc_rtc_ops = { |
312 | .read_time = mxc_rtc_read_time, | 302 | .read_time = mxc_rtc_read_time, |
313 | .set_mmss64 = mxc_rtc_set_mmss, | 303 | .set_time = mxc_rtc_set_time, |
314 | .read_alarm = mxc_rtc_read_alarm, | 304 | .read_alarm = mxc_rtc_read_alarm, |
315 | .set_alarm = mxc_rtc_set_alarm, | 305 | .set_alarm = mxc_rtc_set_alarm, |
316 | .alarm_irq_enable = mxc_rtc_alarm_irq_enable, | 306 | .alarm_irq_enable = mxc_rtc_alarm_irq_enable, |
@@ -318,7 +308,6 @@ static const struct rtc_class_ops mxc_rtc_ops = { | |||
318 | 308 | ||
319 | static int mxc_rtc_probe(struct platform_device *pdev) | 309 | static int mxc_rtc_probe(struct platform_device *pdev) |
320 | { | 310 | { |
321 | struct resource *res; | ||
322 | struct rtc_device *rtc; | 311 | struct rtc_device *rtc; |
323 | struct rtc_plat_data *pdata = NULL; | 312 | struct rtc_plat_data *pdata = NULL; |
324 | u32 reg; | 313 | u32 reg; |
@@ -336,11 +325,34 @@ static int mxc_rtc_probe(struct platform_device *pdev) | |||
336 | else | 325 | else |
337 | pdata->devtype = pdev->id_entry->driver_data; | 326 | pdata->devtype = pdev->id_entry->driver_data; |
338 | 327 | ||
339 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 328 | pdata->ioaddr = devm_platform_ioremap_resource(pdev, 0); |
340 | pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res); | ||
341 | if (IS_ERR(pdata->ioaddr)) | 329 | if (IS_ERR(pdata->ioaddr)) |
342 | return PTR_ERR(pdata->ioaddr); | 330 | return PTR_ERR(pdata->ioaddr); |
343 | 331 | ||
332 | rtc = devm_rtc_allocate_device(&pdev->dev); | ||
333 | if (IS_ERR(rtc)) | ||
334 | return PTR_ERR(rtc); | ||
335 | |||
336 | pdata->rtc = rtc; | ||
337 | rtc->ops = &mxc_rtc_ops; | ||
338 | if (is_imx1_rtc(pdata)) { | ||
339 | struct rtc_time tm; | ||
340 | |||
341 | /* 9bit days + hours minutes seconds */ | ||
342 | rtc->range_max = (1 << 9) * 86400 - 1; | ||
343 | |||
344 | /* | ||
345 | * Set the start date as beginning of the current year. This can | ||
346 | * be overridden using device tree. | ||
347 | */ | ||
348 | rtc_time64_to_tm(ktime_get_real_seconds(), &tm); | ||
349 | rtc->start_secs = mktime64(tm.tm_year, 1, 1, 0, 0, 0); | ||
350 | rtc->set_start_time = true; | ||
351 | } else { | ||
352 | /* 16bit days + hours minutes seconds */ | ||
353 | rtc->range_max = (1 << 16) * 86400ULL - 1; | ||
354 | } | ||
355 | |||
344 | pdata->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); | 356 | pdata->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); |
345 | if (IS_ERR(pdata->clk_ipg)) { | 357 | if (IS_ERR(pdata->clk_ipg)) { |
346 | dev_err(&pdev->dev, "unable to get ipg clock!\n"); | 358 | dev_err(&pdev->dev, "unable to get ipg clock!\n"); |
@@ -396,17 +408,16 @@ static int mxc_rtc_probe(struct platform_device *pdev) | |||
396 | pdata->irq = -1; | 408 | pdata->irq = -1; |
397 | } | 409 | } |
398 | 410 | ||
399 | if (pdata->irq >= 0) | 411 | if (pdata->irq >= 0) { |
400 | device_init_wakeup(&pdev->dev, 1); | 412 | device_init_wakeup(&pdev->dev, 1); |
401 | 413 | ret = dev_pm_set_wake_irq(&pdev->dev, pdata->irq); | |
402 | rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &mxc_rtc_ops, | 414 | if (ret) |
403 | THIS_MODULE); | 415 | dev_err(&pdev->dev, "failed to enable irq wake\n"); |
404 | if (IS_ERR(rtc)) { | ||
405 | ret = PTR_ERR(rtc); | ||
406 | goto exit_put_clk_ref; | ||
407 | } | 416 | } |
408 | 417 | ||
409 | pdata->rtc = rtc; | 418 | ret = rtc_register_device(rtc); |
419 | if (ret) | ||
420 | goto exit_put_clk_ref; | ||
410 | 421 | ||
411 | return 0; | 422 | return 0; |
412 | 423 | ||
@@ -428,35 +439,10 @@ static int mxc_rtc_remove(struct platform_device *pdev) | |||
428 | return 0; | 439 | return 0; |
429 | } | 440 | } |
430 | 441 | ||
431 | #ifdef CONFIG_PM_SLEEP | ||
432 | static int mxc_rtc_suspend(struct device *dev) | ||
433 | { | ||
434 | struct rtc_plat_data *pdata = dev_get_drvdata(dev); | ||
435 | |||
436 | if (device_may_wakeup(dev)) | ||
437 | enable_irq_wake(pdata->irq); | ||
438 | |||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | static int mxc_rtc_resume(struct device *dev) | ||
443 | { | ||
444 | struct rtc_plat_data *pdata = dev_get_drvdata(dev); | ||
445 | |||
446 | if (device_may_wakeup(dev)) | ||
447 | disable_irq_wake(pdata->irq); | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | #endif | ||
452 | |||
453 | static SIMPLE_DEV_PM_OPS(mxc_rtc_pm_ops, mxc_rtc_suspend, mxc_rtc_resume); | ||
454 | |||
455 | static struct platform_driver mxc_rtc_driver = { | 442 | static struct platform_driver mxc_rtc_driver = { |
456 | .driver = { | 443 | .driver = { |
457 | .name = "mxc_rtc", | 444 | .name = "mxc_rtc", |
458 | .of_match_table = of_match_ptr(imx_rtc_dt_ids), | 445 | .of_match_table = of_match_ptr(imx_rtc_dt_ids), |
459 | .pm = &mxc_rtc_pm_ops, | ||
460 | }, | 446 | }, |
461 | .id_table = imx_rtc_devtype, | 447 | .id_table = imx_rtc_devtype, |
462 | .probe = mxc_rtc_probe, | 448 | .probe = mxc_rtc_probe, |