rtc-lpc32xx.c (8785B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2010 NXP Semiconductors 4 */ 5 6#include <linux/kernel.h> 7#include <linux/module.h> 8#include <linux/init.h> 9#include <linux/platform_device.h> 10#include <linux/spinlock.h> 11#include <linux/rtc.h> 12#include <linux/slab.h> 13#include <linux/io.h> 14#include <linux/of.h> 15 16/* 17 * Clock and Power control register offsets 18 */ 19#define LPC32XX_RTC_UCOUNT 0x00 20#define LPC32XX_RTC_DCOUNT 0x04 21#define LPC32XX_RTC_MATCH0 0x08 22#define LPC32XX_RTC_MATCH1 0x0C 23#define LPC32XX_RTC_CTRL 0x10 24#define LPC32XX_RTC_INTSTAT 0x14 25#define LPC32XX_RTC_KEY 0x18 26#define LPC32XX_RTC_SRAM 0x80 27 28#define LPC32XX_RTC_CTRL_MATCH0 (1 << 0) 29#define LPC32XX_RTC_CTRL_MATCH1 (1 << 1) 30#define LPC32XX_RTC_CTRL_ONSW_MATCH0 (1 << 2) 31#define LPC32XX_RTC_CTRL_ONSW_MATCH1 (1 << 3) 32#define LPC32XX_RTC_CTRL_SW_RESET (1 << 4) 33#define LPC32XX_RTC_CTRL_CNTR_DIS (1 << 6) 34#define LPC32XX_RTC_CTRL_ONSW_FORCE_HI (1 << 7) 35 36#define LPC32XX_RTC_INTSTAT_MATCH0 (1 << 0) 37#define LPC32XX_RTC_INTSTAT_MATCH1 (1 << 1) 38#define LPC32XX_RTC_INTSTAT_ONSW (1 << 2) 39 40#define LPC32XX_RTC_KEY_ONSW_LOADVAL 0xB5C13F27 41 42#define rtc_readl(dev, reg) \ 43 __raw_readl((dev)->rtc_base + (reg)) 44#define rtc_writel(dev, reg, val) \ 45 __raw_writel((val), (dev)->rtc_base + (reg)) 46 47struct lpc32xx_rtc { 48 void __iomem *rtc_base; 49 int irq; 50 unsigned char alarm_enabled; 51 struct rtc_device *rtc; 52 spinlock_t lock; 53}; 54 55static int lpc32xx_rtc_read_time(struct device *dev, struct rtc_time *time) 56{ 57 unsigned long elapsed_sec; 58 struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 59 60 elapsed_sec = rtc_readl(rtc, LPC32XX_RTC_UCOUNT); 61 rtc_time64_to_tm(elapsed_sec, time); 62 63 return 0; 64} 65 66static int lpc32xx_rtc_set_time(struct device *dev, struct rtc_time *time) 67{ 68 struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 69 u32 secs = rtc_tm_to_time64(time); 70 u32 tmp; 71 72 spin_lock_irq(&rtc->lock); 73 74 /* RTC must be disabled during count update */ 75 tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); 76 rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | LPC32XX_RTC_CTRL_CNTR_DIS); 77 rtc_writel(rtc, LPC32XX_RTC_UCOUNT, secs); 78 rtc_writel(rtc, LPC32XX_RTC_DCOUNT, 0xFFFFFFFF - secs); 79 rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp &= ~LPC32XX_RTC_CTRL_CNTR_DIS); 80 81 spin_unlock_irq(&rtc->lock); 82 83 return 0; 84} 85 86static int lpc32xx_rtc_read_alarm(struct device *dev, 87 struct rtc_wkalrm *wkalrm) 88{ 89 struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 90 91 rtc_time64_to_tm(rtc_readl(rtc, LPC32XX_RTC_MATCH0), &wkalrm->time); 92 wkalrm->enabled = rtc->alarm_enabled; 93 wkalrm->pending = !!(rtc_readl(rtc, LPC32XX_RTC_INTSTAT) & 94 LPC32XX_RTC_INTSTAT_MATCH0); 95 96 return rtc_valid_tm(&wkalrm->time); 97} 98 99static int lpc32xx_rtc_set_alarm(struct device *dev, 100 struct rtc_wkalrm *wkalrm) 101{ 102 struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 103 unsigned long alarmsecs; 104 u32 tmp; 105 106 alarmsecs = rtc_tm_to_time64(&wkalrm->time); 107 108 spin_lock_irq(&rtc->lock); 109 110 /* Disable alarm during update */ 111 tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); 112 rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp & ~LPC32XX_RTC_CTRL_MATCH0); 113 114 rtc_writel(rtc, LPC32XX_RTC_MATCH0, alarmsecs); 115 116 rtc->alarm_enabled = wkalrm->enabled; 117 if (wkalrm->enabled) { 118 rtc_writel(rtc, LPC32XX_RTC_INTSTAT, 119 LPC32XX_RTC_INTSTAT_MATCH0); 120 rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp | 121 LPC32XX_RTC_CTRL_MATCH0); 122 } 123 124 spin_unlock_irq(&rtc->lock); 125 126 return 0; 127} 128 129static int lpc32xx_rtc_alarm_irq_enable(struct device *dev, 130 unsigned int enabled) 131{ 132 struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 133 u32 tmp; 134 135 spin_lock_irq(&rtc->lock); 136 tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); 137 138 if (enabled) { 139 rtc->alarm_enabled = 1; 140 tmp |= LPC32XX_RTC_CTRL_MATCH0; 141 } else { 142 rtc->alarm_enabled = 0; 143 tmp &= ~LPC32XX_RTC_CTRL_MATCH0; 144 } 145 146 rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); 147 spin_unlock_irq(&rtc->lock); 148 149 return 0; 150} 151 152static irqreturn_t lpc32xx_rtc_alarm_interrupt(int irq, void *dev) 153{ 154 struct lpc32xx_rtc *rtc = dev; 155 156 spin_lock(&rtc->lock); 157 158 /* Disable alarm interrupt */ 159 rtc_writel(rtc, LPC32XX_RTC_CTRL, 160 rtc_readl(rtc, LPC32XX_RTC_CTRL) & 161 ~LPC32XX_RTC_CTRL_MATCH0); 162 rtc->alarm_enabled = 0; 163 164 /* 165 * Write a large value to the match value so the RTC won't 166 * keep firing the match status 167 */ 168 rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); 169 rtc_writel(rtc, LPC32XX_RTC_INTSTAT, LPC32XX_RTC_INTSTAT_MATCH0); 170 171 spin_unlock(&rtc->lock); 172 173 rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); 174 175 return IRQ_HANDLED; 176} 177 178static const struct rtc_class_ops lpc32xx_rtc_ops = { 179 .read_time = lpc32xx_rtc_read_time, 180 .set_time = lpc32xx_rtc_set_time, 181 .read_alarm = lpc32xx_rtc_read_alarm, 182 .set_alarm = lpc32xx_rtc_set_alarm, 183 .alarm_irq_enable = lpc32xx_rtc_alarm_irq_enable, 184}; 185 186static int lpc32xx_rtc_probe(struct platform_device *pdev) 187{ 188 struct lpc32xx_rtc *rtc; 189 int err; 190 u32 tmp; 191 192 rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); 193 if (unlikely(!rtc)) 194 return -ENOMEM; 195 196 rtc->rtc_base = devm_platform_ioremap_resource(pdev, 0); 197 if (IS_ERR(rtc->rtc_base)) 198 return PTR_ERR(rtc->rtc_base); 199 200 spin_lock_init(&rtc->lock); 201 202 /* 203 * The RTC is on a separate power domain and can keep it's state 204 * across a chip power cycle. If the RTC has never been previously 205 * setup, then set it up now for the first time. 206 */ 207 tmp = rtc_readl(rtc, LPC32XX_RTC_CTRL); 208 if (rtc_readl(rtc, LPC32XX_RTC_KEY) != LPC32XX_RTC_KEY_ONSW_LOADVAL) { 209 tmp &= ~(LPC32XX_RTC_CTRL_SW_RESET | 210 LPC32XX_RTC_CTRL_CNTR_DIS | 211 LPC32XX_RTC_CTRL_MATCH0 | 212 LPC32XX_RTC_CTRL_MATCH1 | 213 LPC32XX_RTC_CTRL_ONSW_MATCH0 | 214 LPC32XX_RTC_CTRL_ONSW_MATCH1 | 215 LPC32XX_RTC_CTRL_ONSW_FORCE_HI); 216 rtc_writel(rtc, LPC32XX_RTC_CTRL, tmp); 217 218 /* Clear latched interrupt states */ 219 rtc_writel(rtc, LPC32XX_RTC_MATCH0, 0xFFFFFFFF); 220 rtc_writel(rtc, LPC32XX_RTC_INTSTAT, 221 LPC32XX_RTC_INTSTAT_MATCH0 | 222 LPC32XX_RTC_INTSTAT_MATCH1 | 223 LPC32XX_RTC_INTSTAT_ONSW); 224 225 /* Write key value to RTC so it won't reload on reset */ 226 rtc_writel(rtc, LPC32XX_RTC_KEY, 227 LPC32XX_RTC_KEY_ONSW_LOADVAL); 228 } else { 229 rtc_writel(rtc, LPC32XX_RTC_CTRL, 230 tmp & ~LPC32XX_RTC_CTRL_MATCH0); 231 } 232 233 platform_set_drvdata(pdev, rtc); 234 235 rtc->rtc = devm_rtc_allocate_device(&pdev->dev); 236 if (IS_ERR(rtc->rtc)) 237 return PTR_ERR(rtc->rtc); 238 239 rtc->rtc->ops = &lpc32xx_rtc_ops; 240 rtc->rtc->range_max = U32_MAX; 241 242 err = devm_rtc_register_device(rtc->rtc); 243 if (err) 244 return err; 245 246 /* 247 * IRQ is enabled after device registration in case alarm IRQ 248 * is pending upon suspend exit. 249 */ 250 rtc->irq = platform_get_irq(pdev, 0); 251 if (rtc->irq < 0) { 252 dev_warn(&pdev->dev, "Can't get interrupt resource\n"); 253 } else { 254 if (devm_request_irq(&pdev->dev, rtc->irq, 255 lpc32xx_rtc_alarm_interrupt, 256 0, pdev->name, rtc) < 0) { 257 dev_warn(&pdev->dev, "Can't request interrupt.\n"); 258 rtc->irq = -1; 259 } else { 260 device_init_wakeup(&pdev->dev, 1); 261 } 262 } 263 264 return 0; 265} 266 267#ifdef CONFIG_PM 268static int lpc32xx_rtc_suspend(struct device *dev) 269{ 270 struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 271 272 if (rtc->irq >= 0) { 273 if (device_may_wakeup(dev)) 274 enable_irq_wake(rtc->irq); 275 else 276 disable_irq_wake(rtc->irq); 277 } 278 279 return 0; 280} 281 282static int lpc32xx_rtc_resume(struct device *dev) 283{ 284 struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 285 286 if (rtc->irq >= 0 && device_may_wakeup(dev)) 287 disable_irq_wake(rtc->irq); 288 289 return 0; 290} 291 292/* Unconditionally disable the alarm */ 293static int lpc32xx_rtc_freeze(struct device *dev) 294{ 295 struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 296 297 spin_lock_irq(&rtc->lock); 298 299 rtc_writel(rtc, LPC32XX_RTC_CTRL, 300 rtc_readl(rtc, LPC32XX_RTC_CTRL) & 301 ~LPC32XX_RTC_CTRL_MATCH0); 302 303 spin_unlock_irq(&rtc->lock); 304 305 return 0; 306} 307 308static int lpc32xx_rtc_thaw(struct device *dev) 309{ 310 struct lpc32xx_rtc *rtc = dev_get_drvdata(dev); 311 312 if (rtc->alarm_enabled) { 313 spin_lock_irq(&rtc->lock); 314 315 rtc_writel(rtc, LPC32XX_RTC_CTRL, 316 rtc_readl(rtc, LPC32XX_RTC_CTRL) | 317 LPC32XX_RTC_CTRL_MATCH0); 318 319 spin_unlock_irq(&rtc->lock); 320 } 321 322 return 0; 323} 324 325static const struct dev_pm_ops lpc32xx_rtc_pm_ops = { 326 .suspend = lpc32xx_rtc_suspend, 327 .resume = lpc32xx_rtc_resume, 328 .freeze = lpc32xx_rtc_freeze, 329 .thaw = lpc32xx_rtc_thaw, 330 .restore = lpc32xx_rtc_resume 331}; 332 333#define LPC32XX_RTC_PM_OPS (&lpc32xx_rtc_pm_ops) 334#else 335#define LPC32XX_RTC_PM_OPS NULL 336#endif 337 338#ifdef CONFIG_OF 339static const struct of_device_id lpc32xx_rtc_match[] = { 340 { .compatible = "nxp,lpc3220-rtc" }, 341 { } 342}; 343MODULE_DEVICE_TABLE(of, lpc32xx_rtc_match); 344#endif 345 346static struct platform_driver lpc32xx_rtc_driver = { 347 .probe = lpc32xx_rtc_probe, 348 .driver = { 349 .name = "rtc-lpc32xx", 350 .pm = LPC32XX_RTC_PM_OPS, 351 .of_match_table = of_match_ptr(lpc32xx_rtc_match), 352 }, 353}; 354 355module_platform_driver(lpc32xx_rtc_driver); 356 357MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com"); 358MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC"); 359MODULE_LICENSE("GPL"); 360MODULE_ALIAS("platform:rtc-lpc32xx");