19aa449beSKevin Wells /* 29aa449beSKevin Wells * Copyright (C) 2010 NXP Semiconductors 39aa449beSKevin Wells * 49aa449beSKevin Wells * This program is free software; you can redistribute it and/or modify 59aa449beSKevin Wells * it under the terms of the GNU General Public License as published by 69aa449beSKevin Wells * the Free Software Foundation; either version 2 of the License, or 79aa449beSKevin Wells * (at your option) any later version. 89aa449beSKevin Wells * 99aa449beSKevin Wells * You should have received a copy of the GNU General Public License along 109aa449beSKevin Wells * with this program; if not, write to the Free Software Foundation, Inc., 119aa449beSKevin Wells * 675 Mass Ave, Cambridge, MA 02139, USA. 129aa449beSKevin Wells */ 139aa449beSKevin Wells 149aa449beSKevin Wells #include <linux/kernel.h> 159aa449beSKevin Wells #include <linux/module.h> 169aa449beSKevin Wells #include <linux/init.h> 179aa449beSKevin Wells #include <linux/platform_device.h> 189aa449beSKevin Wells #include <linux/spinlock.h> 199aa449beSKevin Wells #include <linux/rtc.h> 209aa449beSKevin Wells #include <linux/slab.h> 219aa449beSKevin Wells #include <linux/io.h> 229aa449beSKevin Wells 239aa449beSKevin Wells /* 249aa449beSKevin Wells * Clock and Power control register offsets 259aa449beSKevin Wells */ 269aa449beSKevin Wells #define LPC32XX_RTC_UCOUNT 0x00 279aa449beSKevin Wells #define LPC32XX_RTC_DCOUNT 0x04 289aa449beSKevin Wells #define LPC32XX_RTC_MATCH0 0x08 299aa449beSKevin Wells #define LPC32XX_RTC_MATCH1 0x0C 309aa449beSKevin Wells #define LPC32XX_RTC_CTRL 0x10 319aa449beSKevin Wells #define LPC32XX_RTC_INTSTAT 0x14 329aa449beSKevin Wells #define LPC32XX_RTC_KEY 0x18 339aa449beSKevin Wells #define LPC32XX_RTC_SRAM 0x80 349aa449beSKevin Wells 359aa449beSKevin Wells #define LPC32XX_RTC_CTRL_MATCH0 (1 << 0) 369aa449beSKevin Wells #define LPC32XX_RTC_CTRL_MATCH1 (1 << 1) 379aa449beSKevin Wells #define LPC32XX_RTC_CTRL_ONSW_MATCH0 (1 << 2) 389aa449beSKevin Wells #define LPC32XX_RTC_CTRL_ONSW_MATCH1 (1 << 3) 399aa449beSKevin Wells #define LPC32XX_RTC_CTRL_SW_RESET (1 << 4) 409aa449beSKevin Wells #define LPC32XX_RTC_CTRL_CNTR_DIS (1 << 6) 419aa449beSKevin Wells #define LPC32XX_RTC_CTRL_ONSW_FORCE_HI (1 << 7) 429aa449beSKevin Wells 439aa449beSKevin Wells #define LPC32XX_RTC_INTSTAT_MATCH0 (1 << 0) 449aa449beSKevin Wells #define LPC32XX_RTC_INTSTAT_MATCH1 (1 << 1) 459aa449beSKevin Wells #define LPC32XX_RTC_INTSTAT_ONSW (1 << 2) 469aa449beSKevin Wells 479aa449beSKevin Wells #define LPC32XX_RTC_KEY_ONSW_LOADVAL 0xB5C13F27 489aa449beSKevin Wells 499aa449beSKevin Wells #define RTC_NAME "rtc-lpc32xx" 509aa449beSKevin Wells 519aa449beSKevin Wells #define rtc_readl(dev, reg) \ 529aa449beSKevin Wells __raw_readl((dev)->rtc_base + (reg)) 539aa449beSKevin Wells #define rtc_writel(dev, reg, val) \ 549aa449beSKevin Wells __raw_writel((val), (dev)->rtc_base + (reg)) 559aa449beSKevin Wells 569aa449beSKevin Wells struct lpc32xx_rtc { 579aa449beSKevin Wells void __iomem *rtc_base; 589aa449beSKevin Wells int irq; 599aa449beSKevin Wells unsigned char alarm_enabled; 609aa449beSKevin Wells struct rtc_device *rtc; 619aa449beSKevin Wells spinlock_t lock; 629aa449beSKevin Wells }; 639aa449beSKevin Wells 649aa449beSKevin Wells static int lpc32xx_rtc_read_time(struct device *dev, struct rtc_time *time) 659aa449beSKevin Wells { 669aa449beSKevin Wells unsigned long elapsed_sec; 679aa449beSKevin Wells struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 689aa449beSKevin Wells 699aa449beSKevin Wells elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT); 709aa449beSKevin Wells rtc_time_to_tm(elapsed_sec, time); 719aa449beSKevin Wells 729aa449beSKevin Wells return rtc_valid_tm(time); 739aa449beSKevin Wells } 749aa449beSKevin Wells 759aa449beSKevin Wells static int lpc32xx_rtc_set_mmss(struct device *dev, unsigned long secs) 769aa449beSKevin Wells { 779aa449beSKevin Wells struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 789aa449beSKevin Wells u32 tmp; 799aa449beSKevin Wells 809aa449beSKevin Wells spin_lock_irq(&rtc->lock); 819aa449beSKevin Wells 829aa449beSKevin Wells /* RTC must be disabled during count update */ 839aa449beSKevin Wells tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); 849aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | LPC32XX_RTC_CTRL_CNTR_DIS); 859aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_UCOUNT, secs); 869aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_DCOUNT, 0xFFFFFFFF - secs); 879aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp &= ~LPC32XX_RTC_CTRL_CNTR_DIS); 889aa449beSKevin Wells 899aa449beSKevin Wells spin_unlock_irq(&rtc->lock); 909aa449beSKevin Wells 919aa449beSKevin Wells return 0; 929aa449beSKevin Wells } 939aa449beSKevin Wells 949aa449beSKevin Wells static int lpc32xx_rtc_read_alarm(struct device *dev, 959aa449beSKevin Wells struct rtc_wkalrm *wkalrm) 969aa449beSKevin Wells { 979aa449beSKevin Wells struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 989aa449beSKevin Wells 999aa449beSKevin Wells rtc_time_to_tm(rtc_readl(rtc, LPC32XX_RTC_MATCH0), &wkalrm->time); 1009aa449beSKevin Wells wkalrm->enabled = rtc->alarm_enabled; 1019aa449beSKevin Wells wkalrm->pending = !!(rtc_readl(rtc, LPC32XX_RTC_INTSTAT) & 1029aa449beSKevin Wells LPC32XX_RTC_INTSTAT_MATCH0); 1039aa449beSKevin Wells 1049aa449beSKevin Wells return rtc_valid_tm(&wkalrm->time); 1059aa449beSKevin Wells } 1069aa449beSKevin Wells 1079aa449beSKevin Wells static int lpc32xx_rtc_set_alarm(struct device *dev, 1089aa449beSKevin Wells struct rtc_wkalrm *wkalrm) 1099aa449beSKevin Wells { 1109aa449beSKevin Wells struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 1119aa449beSKevin Wells unsigned long alarmsecs; 1129aa449beSKevin Wells u32 tmp; 1139aa449beSKevin Wells int ret; 1149aa449beSKevin Wells 1159aa449beSKevin Wells ret = rtc_tm_to_time(&wkalrm->time, &alarmsecs); 1169aa449beSKevin Wells if (ret < 0) { 1179aa449beSKevin Wells dev_warn(dev, "Failed to convert time: %d\n", ret); 1189aa449beSKevin Wells return ret; 1199aa449beSKevin Wells } 1209aa449beSKevin Wells 1219aa449beSKevin Wells spin_lock_irq(&rtc->lock); 1229aa449beSKevin Wells 1239aa449beSKevin Wells /* Disable alarm during update */ 1249aa449beSKevin Wells tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); 1259aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp & ~LPC32XX_RTC_CTRL_MATCH0); 1269aa449beSKevin Wells 1279aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_MATCH0, alarmsecs); 1289aa449beSKevin Wells 1299aa449beSKevin Wells rtc->alarm_enabled = wkalrm->enabled; 1309aa449beSKevin Wells if (wkalrm->enabled) { 1319aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_INTSTAT, 1329aa449beSKevin Wells LPC32XX_RTC_INTSTAT_MATCH0); 1339aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | 1349aa449beSKevin Wells LPC32XX_RTC_CTRL_MATCH0); 1359aa449beSKevin Wells } 1369aa449beSKevin Wells 1379aa449beSKevin Wells spin_unlock_irq(&rtc->lock); 1389aa449beSKevin Wells 1399aa449beSKevin Wells return 0; 1409aa449beSKevin Wells } 1419aa449beSKevin Wells 1429aa449beSKevin Wells static int lpc32xx_rtc_alarm_irq_enable(struct device *dev, 1439aa449beSKevin Wells unsigned int enabled) 1449aa449beSKevin Wells { 1459aa449beSKevin Wells struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 1469aa449beSKevin Wells u32 tmp; 1479aa449beSKevin Wells 1489aa449beSKevin Wells spin_lock_irq(&rtc->lock); 1499aa449beSKevin Wells tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); 1509aa449beSKevin Wells 1519aa449beSKevin Wells if (enabled) { 1529aa449beSKevin Wells rtc->alarm_enabled = 1; 1539aa449beSKevin Wells tmp |= LPC32XX_RTC_CTRL_MATCH0; 1549aa449beSKevin Wells } else { 1559aa449beSKevin Wells rtc->alarm_enabled = 0; 1569aa449beSKevin Wells tmp &= ~LPC32XX_RTC_CTRL_MATCH0; 1579aa449beSKevin Wells } 1589aa449beSKevin Wells 1599aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); 1609aa449beSKevin Wells spin_unlock_irq(&rtc->lock); 1619aa449beSKevin Wells 1629aa449beSKevin Wells return 0; 1639aa449beSKevin Wells } 1649aa449beSKevin Wells 1659aa449beSKevin Wells static irqreturn_t lpc32xx_rtc_alarm_interrupt(int irq, void *dev) 1669aa449beSKevin Wells { 1679aa449beSKevin Wells struct lpc32xx_rtc *rtc = dev; 1689aa449beSKevin Wells 1699aa449beSKevin Wells spin_lock(&rtc->lock); 1709aa449beSKevin Wells 1719aa449beSKevin Wells /* Disable alarm interrupt */ 1729aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_CTRL, 1739aa449beSKevin Wells rtc_readl(rtc, LPC32XX_RTC_CTRL) & 1749aa449beSKevin Wells ~LPC32XX_RTC_CTRL_MATCH0); 1759aa449beSKevin Wells rtc->alarm_enabled = 0; 1769aa449beSKevin Wells 1779aa449beSKevin Wells /* 1789aa449beSKevin Wells * Write a large value to the match value so the RTC won't 1799aa449beSKevin Wells * keep firing the match status 1809aa449beSKevin Wells */ 1819aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); 1829aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_INTSTAT, LPC32XX_RTC_INTSTAT_MATCH0); 1839aa449beSKevin Wells 1849aa449beSKevin Wells spin_unlock(&rtc->lock); 1859aa449beSKevin Wells 1869aa449beSKevin Wells rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); 1879aa449beSKevin Wells 1889aa449beSKevin Wells return IRQ_HANDLED; 1899aa449beSKevin Wells } 1909aa449beSKevin Wells 1919aa449beSKevin Wells static const struct rtc_class_ops lpc32xx_rtc_ops = { 1929aa449beSKevin Wells .read_time = lpc32xx_rtc_read_time, 1939aa449beSKevin Wells .set_mmss = lpc32xx_rtc_set_mmss, 1949aa449beSKevin Wells .read_alarm = lpc32xx_rtc_read_alarm, 1959aa449beSKevin Wells .set_alarm = lpc32xx_rtc_set_alarm, 1969aa449beSKevin Wells .alarm_irq_enable = lpc32xx_rtc_alarm_irq_enable, 1979aa449beSKevin Wells }; 1989aa449beSKevin Wells 1999aa449beSKevin Wells static int __devinit lpc32xx_rtc_probe(struct platform_device *pdev) 2009aa449beSKevin Wells { 2019aa449beSKevin Wells struct resource *res; 2029aa449beSKevin Wells struct lpc32xx_rtc *rtc; 2039aa449beSKevin Wells resource_size_t size; 2049aa449beSKevin Wells int rtcirq; 2059aa449beSKevin Wells u32 tmp; 2069aa449beSKevin Wells 2079aa449beSKevin Wells res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2089aa449beSKevin Wells if (!res) { 2099aa449beSKevin Wells dev_err(&pdev->dev, "Can't get memory resource\n"); 2109aa449beSKevin Wells return -ENOENT; 2119aa449beSKevin Wells } 2129aa449beSKevin Wells 2139aa449beSKevin Wells rtcirq = platform_get_irq(pdev, 0); 2149aa449beSKevin Wells if (rtcirq < 0 || rtcirq >= NR_IRQS) { 2159aa449beSKevin Wells dev_warn(&pdev->dev, "Can't get interrupt resource\n"); 2169aa449beSKevin Wells rtcirq = -1; 2179aa449beSKevin Wells } 2189aa449beSKevin Wells 2199aa449beSKevin Wells rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); 2209aa449beSKevin Wells if (unlikely(!rtc)) { 2219aa449beSKevin Wells dev_err(&pdev->dev, "Can't allocate memory\n"); 2229aa449beSKevin Wells return -ENOMEM; 2239aa449beSKevin Wells } 2249aa449beSKevin Wells rtc->irq = rtcirq; 2259aa449beSKevin Wells 2269aa449beSKevin Wells size = resource_size(res); 2279aa449beSKevin Wells 2289aa449beSKevin Wells if (!devm_request_mem_region(&pdev->dev, res->start, size, 2299aa449beSKevin Wells pdev->name)) { 2309aa449beSKevin Wells dev_err(&pdev->dev, "RTC registers are not free\n"); 2319aa449beSKevin Wells return -EBUSY; 2329aa449beSKevin Wells } 2339aa449beSKevin Wells 2349aa449beSKevin Wells rtc->rtc_base = devm_ioremap(&pdev->dev, res->start, size); 2359aa449beSKevin Wells if (!rtc->rtc_base) { 2369aa449beSKevin Wells dev_err(&pdev->dev, "Can't map memory\n"); 2379aa449beSKevin Wells return -ENOMEM; 2389aa449beSKevin Wells } 2399aa449beSKevin Wells 2409aa449beSKevin Wells spin_lock_init(&rtc->lock); 2419aa449beSKevin Wells 2429aa449beSKevin Wells /* 243*25985edcSLucas De Marchi * The RTC is on a separate power domain and can keep it's state 2449aa449beSKevin Wells * across a chip power cycle. If the RTC has never been previously 2459aa449beSKevin Wells * setup, then set it up now for the first time. 2469aa449beSKevin Wells */ 2479aa449beSKevin Wells tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); 2489aa449beSKevin Wells if (rtc_readl(rtc, LPC32XX_RTC_KEY) != LPC32XX_RTC_KEY_ONSW_LOADVAL) { 2499aa449beSKevin Wells tmp &= ~(LPC32XX_RTC_CTRL_SW_RESET | 2509aa449beSKevin Wells LPC32XX_RTC_CTRL_CNTR_DIS | 2519aa449beSKevin Wells LPC32XX_RTC_CTRL_MATCH0 | 2529aa449beSKevin Wells LPC32XX_RTC_CTRL_MATCH1 | 2539aa449beSKevin Wells LPC32XX_RTC_CTRL_ONSW_MATCH0 | 2549aa449beSKevin Wells LPC32XX_RTC_CTRL_ONSW_MATCH1 | 2559aa449beSKevin Wells LPC32XX_RTC_CTRL_ONSW_FORCE_HI); 2569aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); 2579aa449beSKevin Wells 2589aa449beSKevin Wells /* Clear latched interrupt states */ 2599aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); 2609aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_INTSTAT, 2619aa449beSKevin Wells LPC32XX_RTC_INTSTAT_MATCH0 | 2629aa449beSKevin Wells LPC32XX_RTC_INTSTAT_MATCH1 | 2639aa449beSKevin Wells LPC32XX_RTC_INTSTAT_ONSW); 2649aa449beSKevin Wells 2659aa449beSKevin Wells /* Write key value to RTC so it won't reload on reset */ 2669aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_KEY, 2679aa449beSKevin Wells LPC32XX_RTC_KEY_ONSW_LOADVAL); 2689aa449beSKevin Wells } else { 2699aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_CTRL, 2709aa449beSKevin Wells tmp & ~LPC32XX_RTC_CTRL_MATCH0); 2719aa449beSKevin Wells } 2729aa449beSKevin Wells 2739aa449beSKevin Wells platform_set_drvdata(pdev, rtc); 2749aa449beSKevin Wells 2759aa449beSKevin Wells rtc->rtc = rtc_device_register(RTC_NAME, &pdev->dev, &lpc32xx_rtc_ops, 2769aa449beSKevin Wells THIS_MODULE); 2779aa449beSKevin Wells if (IS_ERR(rtc->rtc)) { 2789aa449beSKevin Wells dev_err(&pdev->dev, "Can't get RTC\n"); 2799aa449beSKevin Wells platform_set_drvdata(pdev, NULL); 2809aa449beSKevin Wells return PTR_ERR(rtc->rtc); 2819aa449beSKevin Wells } 2829aa449beSKevin Wells 2839aa449beSKevin Wells /* 2849aa449beSKevin Wells * IRQ is enabled after device registration in case alarm IRQ 2859aa449beSKevin Wells * is pending upon suspend exit. 2869aa449beSKevin Wells */ 2879aa449beSKevin Wells if (rtc->irq >= 0) { 2889aa449beSKevin Wells if (devm_request_irq(&pdev->dev, rtc->irq, 2899aa449beSKevin Wells lpc32xx_rtc_alarm_interrupt, 2909aa449beSKevin Wells IRQF_DISABLED, pdev->name, rtc) < 0) { 2919aa449beSKevin Wells dev_warn(&pdev->dev, "Can't request interrupt.\n"); 2929aa449beSKevin Wells rtc->irq = -1; 2939aa449beSKevin Wells } else { 2949aa449beSKevin Wells device_init_wakeup(&pdev->dev, 1); 2959aa449beSKevin Wells } 2969aa449beSKevin Wells } 2979aa449beSKevin Wells 2989aa449beSKevin Wells return 0; 2999aa449beSKevin Wells } 3009aa449beSKevin Wells 3019aa449beSKevin Wells static int __devexit lpc32xx_rtc_remove(struct platform_device *pdev) 3029aa449beSKevin Wells { 3039aa449beSKevin Wells struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); 3049aa449beSKevin Wells 3059aa449beSKevin Wells if (rtc->irq >= 0) 3069aa449beSKevin Wells device_init_wakeup(&pdev->dev, 0); 3079aa449beSKevin Wells 3089aa449beSKevin Wells platform_set_drvdata(pdev, NULL); 3099aa449beSKevin Wells rtc_device_unregister(rtc->rtc); 3109aa449beSKevin Wells 3119aa449beSKevin Wells return 0; 3129aa449beSKevin Wells } 3139aa449beSKevin Wells 3149aa449beSKevin Wells #ifdef CONFIG_PM 3159aa449beSKevin Wells static int lpc32xx_rtc_suspend(struct device *dev) 3169aa449beSKevin Wells { 3179aa449beSKevin Wells struct platform_device *pdev = to_platform_device(dev); 3189aa449beSKevin Wells struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); 3199aa449beSKevin Wells 3209aa449beSKevin Wells if (rtc->irq >= 0) { 3219aa449beSKevin Wells if (device_may_wakeup(&pdev->dev)) 3229aa449beSKevin Wells enable_irq_wake(rtc->irq); 3239aa449beSKevin Wells else 3249aa449beSKevin Wells disable_irq_wake(rtc->irq); 3259aa449beSKevin Wells } 3269aa449beSKevin Wells 3279aa449beSKevin Wells return 0; 3289aa449beSKevin Wells } 3299aa449beSKevin Wells 3309aa449beSKevin Wells static int lpc32xx_rtc_resume(struct device *dev) 3319aa449beSKevin Wells { 3329aa449beSKevin Wells struct platform_device *pdev = to_platform_device(dev); 3339aa449beSKevin Wells struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); 3349aa449beSKevin Wells 3359aa449beSKevin Wells if (rtc->irq >= 0 && device_may_wakeup(&pdev->dev)) 3369aa449beSKevin Wells disable_irq_wake(rtc->irq); 3379aa449beSKevin Wells 3389aa449beSKevin Wells return 0; 3399aa449beSKevin Wells } 3409aa449beSKevin Wells 3419aa449beSKevin Wells /* Unconditionally disable the alarm */ 3429aa449beSKevin Wells static int lpc32xx_rtc_freeze(struct device *dev) 3439aa449beSKevin Wells { 3449aa449beSKevin Wells struct platform_device *pdev = to_platform_device(dev); 3459aa449beSKevin Wells struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); 3469aa449beSKevin Wells 3479aa449beSKevin Wells spin_lock_irq(&rtc->lock); 3489aa449beSKevin Wells 3499aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_CTRL, 3509aa449beSKevin Wells rtc_readl(rtc, LPC32XX_RTC_CTRL) & 3519aa449beSKevin Wells ~LPC32XX_RTC_CTRL_MATCH0); 3529aa449beSKevin Wells 3539aa449beSKevin Wells spin_unlock_irq(&rtc->lock); 3549aa449beSKevin Wells 3559aa449beSKevin Wells return 0; 3569aa449beSKevin Wells } 3579aa449beSKevin Wells 3589aa449beSKevin Wells static int lpc32xx_rtc_thaw(struct device *dev) 3599aa449beSKevin Wells { 3609aa449beSKevin Wells struct platform_device *pdev = to_platform_device(dev); 3619aa449beSKevin Wells struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev); 3629aa449beSKevin Wells 3639aa449beSKevin Wells if (rtc->alarm_enabled) { 3649aa449beSKevin Wells spin_lock_irq(&rtc->lock); 3659aa449beSKevin Wells 3669aa449beSKevin Wells rtc_writel(rtc, LPC32XX_RTC_CTRL, 3679aa449beSKevin Wells rtc_readl(rtc, LPC32XX_RTC_CTRL) | 3689aa449beSKevin Wells LPC32XX_RTC_CTRL_MATCH0); 3699aa449beSKevin Wells 3709aa449beSKevin Wells spin_unlock_irq(&rtc->lock); 3719aa449beSKevin Wells } 3729aa449beSKevin Wells 3739aa449beSKevin Wells return 0; 3749aa449beSKevin Wells } 3759aa449beSKevin Wells 3769aa449beSKevin Wells static const struct dev_pm_ops lpc32xx_rtc_pm_ops = { 3779aa449beSKevin Wells .suspend = lpc32xx_rtc_suspend, 3789aa449beSKevin Wells .resume = lpc32xx_rtc_resume, 3799aa449beSKevin Wells .freeze = lpc32xx_rtc_freeze, 3809aa449beSKevin Wells .thaw = lpc32xx_rtc_thaw, 3819aa449beSKevin Wells .restore = lpc32xx_rtc_resume 3829aa449beSKevin Wells }; 3839aa449beSKevin Wells 3849aa449beSKevin Wells #define LPC32XX_RTC_PM_OPS (&lpc32xx_rtc_pm_ops) 3859aa449beSKevin Wells #else 3869aa449beSKevin Wells #define LPC32XX_RTC_PM_OPS NULL 3879aa449beSKevin Wells #endif 3889aa449beSKevin Wells 3899aa449beSKevin Wells static struct platform_driver lpc32xx_rtc_driver = { 3909aa449beSKevin Wells .probe = lpc32xx_rtc_probe, 3919aa449beSKevin Wells .remove = __devexit_p(lpc32xx_rtc_remove), 3929aa449beSKevin Wells .driver = { 3939aa449beSKevin Wells .name = RTC_NAME, 3949aa449beSKevin Wells .owner = THIS_MODULE, 3959aa449beSKevin Wells .pm = LPC32XX_RTC_PM_OPS 3969aa449beSKevin Wells }, 3979aa449beSKevin Wells }; 3989aa449beSKevin Wells 3999aa449beSKevin Wells static int __init lpc32xx_rtc_init(void) 4009aa449beSKevin Wells { 4019aa449beSKevin Wells return platform_driver_register(&lpc32xx_rtc_driver); 4029aa449beSKevin Wells } 4039aa449beSKevin Wells module_init(lpc32xx_rtc_init); 4049aa449beSKevin Wells 4059aa449beSKevin Wells static void __exit lpc32xx_rtc_exit(void) 4069aa449beSKevin Wells { 4079aa449beSKevin Wells platform_driver_unregister(&lpc32xx_rtc_driver); 4089aa449beSKevin Wells } 4099aa449beSKevin Wells module_exit(lpc32xx_rtc_exit); 4109aa449beSKevin Wells 4119aa449beSKevin Wells MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com"); 4129aa449beSKevin Wells MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC"); 4139aa449beSKevin Wells MODULE_LICENSE("GPL"); 4149aa449beSKevin Wells MODULE_ALIAS("platform:rtc-lpc32xx"); 415