1 // SPDX-License-Identifier: GPL-2.0 2 3 /* 4 * Copyright 2019 Cadence 5 * 6 * Authors: 7 * Jan Kotas <jank@cadence.com> 8 */ 9 10 #include <linux/module.h> 11 #include <linux/platform_device.h> 12 #include <linux/of.h> 13 #include <linux/io.h> 14 #include <linux/rtc.h> 15 #include <linux/clk.h> 16 #include <linux/bcd.h> 17 #include <linux/bitfield.h> 18 #include <linux/interrupt.h> 19 #include <linux/pm_wakeirq.h> 20 21 /* Registers */ 22 #define CDNS_RTC_CTLR 0x00 23 #define CDNS_RTC_HMR 0x04 24 #define CDNS_RTC_TIMR 0x08 25 #define CDNS_RTC_CALR 0x0C 26 #define CDNS_RTC_TIMAR 0x10 27 #define CDNS_RTC_CALAR 0x14 28 #define CDNS_RTC_AENR 0x18 29 #define CDNS_RTC_EFLR 0x1C 30 #define CDNS_RTC_IENR 0x20 31 #define CDNS_RTC_IDISR 0x24 32 #define CDNS_RTC_IMSKR 0x28 33 #define CDNS_RTC_STSR 0x2C 34 #define CDNS_RTC_KRTCR 0x30 35 36 /* Control */ 37 #define CDNS_RTC_CTLR_TIME BIT(0) 38 #define CDNS_RTC_CTLR_CAL BIT(1) 39 #define CDNS_RTC_CTLR_TIME_CAL (CDNS_RTC_CTLR_TIME | CDNS_RTC_CTLR_CAL) 40 41 /* Status */ 42 #define CDNS_RTC_STSR_VT BIT(0) 43 #define CDNS_RTC_STSR_VC BIT(1) 44 #define CDNS_RTC_STSR_VTA BIT(2) 45 #define CDNS_RTC_STSR_VCA BIT(3) 46 #define CDNS_RTC_STSR_VT_VC (CDNS_RTC_STSR_VT | CDNS_RTC_STSR_VC) 47 #define CDNS_RTC_STSR_VTA_VCA (CDNS_RTC_STSR_VTA | CDNS_RTC_STSR_VCA) 48 49 /* Keep RTC */ 50 #define CDNS_RTC_KRTCR_KRTC BIT(0) 51 52 /* Alarm, Event, Interrupt */ 53 #define CDNS_RTC_AEI_HOS BIT(0) 54 #define CDNS_RTC_AEI_SEC BIT(1) 55 #define CDNS_RTC_AEI_MIN BIT(2) 56 #define CDNS_RTC_AEI_HOUR BIT(3) 57 #define CDNS_RTC_AEI_DATE BIT(4) 58 #define CDNS_RTC_AEI_MNTH BIT(5) 59 #define CDNS_RTC_AEI_ALRM BIT(6) 60 61 /* Time */ 62 #define CDNS_RTC_TIME_H GENMASK(7, 0) 63 #define CDNS_RTC_TIME_S GENMASK(14, 8) 64 #define CDNS_RTC_TIME_M GENMASK(22, 16) 65 #define CDNS_RTC_TIME_HR GENMASK(29, 24) 66 #define CDNS_RTC_TIME_PM BIT(30) 67 #define CDNS_RTC_TIME_CH BIT(31) 68 69 /* Calendar */ 70 #define CDNS_RTC_CAL_DAY GENMASK(2, 0) 71 #define CDNS_RTC_CAL_M GENMASK(7, 3) 72 #define CDNS_RTC_CAL_D GENMASK(13, 8) 73 #define CDNS_RTC_CAL_Y GENMASK(23, 16) 74 #define CDNS_RTC_CAL_C GENMASK(29, 24) 75 #define CDNS_RTC_CAL_CH BIT(31) 76 77 #define CDNS_RTC_MAX_REGS_TRIES 3 78 79 struct cdns_rtc { 80 struct rtc_device *rtc_dev; 81 struct clk *pclk; 82 struct clk *ref_clk; 83 void __iomem *regs; 84 int irq; 85 }; 86 87 static void cdns_rtc_set_enabled(struct cdns_rtc *crtc, bool enabled) 88 { 89 u32 reg = enabled ? 0x0 : CDNS_RTC_CTLR_TIME_CAL; 90 91 writel(reg, crtc->regs + CDNS_RTC_CTLR); 92 } 93 94 static bool cdns_rtc_get_enabled(struct cdns_rtc *crtc) 95 { 96 return !(readl(crtc->regs + CDNS_RTC_CTLR) & CDNS_RTC_CTLR_TIME_CAL); 97 } 98 99 static irqreturn_t cdns_rtc_irq_handler(int irq, void *id) 100 { 101 struct device *dev = id; 102 struct cdns_rtc *crtc = dev_get_drvdata(dev); 103 104 /* Reading the register clears it */ 105 if (!(readl(crtc->regs + CDNS_RTC_EFLR) & CDNS_RTC_AEI_ALRM)) 106 return IRQ_NONE; 107 108 rtc_update_irq(crtc->rtc_dev, 1, RTC_IRQF | RTC_AF); 109 return IRQ_HANDLED; 110 } 111 112 static u32 cdns_rtc_time2reg(struct rtc_time *tm) 113 { 114 return FIELD_PREP(CDNS_RTC_TIME_S, bin2bcd(tm->tm_sec)) 115 | FIELD_PREP(CDNS_RTC_TIME_M, bin2bcd(tm->tm_min)) 116 | FIELD_PREP(CDNS_RTC_TIME_HR, bin2bcd(tm->tm_hour)); 117 } 118 119 static void cdns_rtc_reg2time(u32 reg, struct rtc_time *tm) 120 { 121 tm->tm_sec = bcd2bin(FIELD_GET(CDNS_RTC_TIME_S, reg)); 122 tm->tm_min = bcd2bin(FIELD_GET(CDNS_RTC_TIME_M, reg)); 123 tm->tm_hour = bcd2bin(FIELD_GET(CDNS_RTC_TIME_HR, reg)); 124 } 125 126 static int cdns_rtc_read_time(struct device *dev, struct rtc_time *tm) 127 { 128 struct cdns_rtc *crtc = dev_get_drvdata(dev); 129 u32 reg; 130 131 /* If the RTC is disabled, assume the values are invalid */ 132 if (!cdns_rtc_get_enabled(crtc)) 133 return -EINVAL; 134 135 cdns_rtc_set_enabled(crtc, false); 136 137 reg = readl(crtc->regs + CDNS_RTC_TIMR); 138 cdns_rtc_reg2time(reg, tm); 139 140 reg = readl(crtc->regs + CDNS_RTC_CALR); 141 tm->tm_mday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_D, reg)); 142 tm->tm_mon = bcd2bin(FIELD_GET(CDNS_RTC_CAL_M, reg)) - 1; 143 tm->tm_year = bcd2bin(FIELD_GET(CDNS_RTC_CAL_Y, reg)) 144 + bcd2bin(FIELD_GET(CDNS_RTC_CAL_C, reg)) * 100 - 1900; 145 tm->tm_wday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_DAY, reg)) - 1; 146 147 cdns_rtc_set_enabled(crtc, true); 148 return 0; 149 } 150 151 static int cdns_rtc_set_time(struct device *dev, struct rtc_time *tm) 152 { 153 struct cdns_rtc *crtc = dev_get_drvdata(dev); 154 u32 timr, calr, stsr; 155 int ret = -EIO; 156 int year = tm->tm_year + 1900; 157 int tries; 158 159 cdns_rtc_set_enabled(crtc, false); 160 161 timr = cdns_rtc_time2reg(tm); 162 163 calr = FIELD_PREP(CDNS_RTC_CAL_D, bin2bcd(tm->tm_mday)) 164 | FIELD_PREP(CDNS_RTC_CAL_M, bin2bcd(tm->tm_mon + 1)) 165 | FIELD_PREP(CDNS_RTC_CAL_Y, bin2bcd(year % 100)) 166 | FIELD_PREP(CDNS_RTC_CAL_C, bin2bcd(year / 100)) 167 | FIELD_PREP(CDNS_RTC_CAL_DAY, tm->tm_wday + 1); 168 169 /* Update registers, check valid flags */ 170 for (tries = 0; tries < CDNS_RTC_MAX_REGS_TRIES; tries++) { 171 writel(timr, crtc->regs + CDNS_RTC_TIMR); 172 writel(calr, crtc->regs + CDNS_RTC_CALR); 173 stsr = readl(crtc->regs + CDNS_RTC_STSR); 174 175 if ((stsr & CDNS_RTC_STSR_VT_VC) == CDNS_RTC_STSR_VT_VC) { 176 ret = 0; 177 break; 178 } 179 } 180 181 cdns_rtc_set_enabled(crtc, true); 182 return ret; 183 } 184 185 static int cdns_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) 186 { 187 struct cdns_rtc *crtc = dev_get_drvdata(dev); 188 189 if (enabled) { 190 writel((CDNS_RTC_AEI_SEC | CDNS_RTC_AEI_MIN | CDNS_RTC_AEI_HOUR 191 | CDNS_RTC_AEI_DATE | CDNS_RTC_AEI_MNTH), 192 crtc->regs + CDNS_RTC_AENR); 193 writel(CDNS_RTC_AEI_ALRM, crtc->regs + CDNS_RTC_IENR); 194 } else { 195 writel(0, crtc->regs + CDNS_RTC_AENR); 196 writel(CDNS_RTC_AEI_ALRM, crtc->regs + CDNS_RTC_IDISR); 197 } 198 199 return 0; 200 } 201 202 static int cdns_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) 203 { 204 struct cdns_rtc *crtc = dev_get_drvdata(dev); 205 u32 reg; 206 207 reg = readl(crtc->regs + CDNS_RTC_TIMAR); 208 cdns_rtc_reg2time(reg, &alarm->time); 209 210 reg = readl(crtc->regs + CDNS_RTC_CALAR); 211 alarm->time.tm_mday = bcd2bin(FIELD_GET(CDNS_RTC_CAL_D, reg)); 212 alarm->time.tm_mon = bcd2bin(FIELD_GET(CDNS_RTC_CAL_M, reg)) - 1; 213 214 return 0; 215 } 216 217 static int cdns_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) 218 { 219 struct cdns_rtc *crtc = dev_get_drvdata(dev); 220 int ret = -EIO; 221 int tries; 222 u32 timar, calar, stsr; 223 224 cdns_rtc_alarm_irq_enable(dev, 0); 225 226 timar = cdns_rtc_time2reg(&alarm->time); 227 calar = FIELD_PREP(CDNS_RTC_CAL_D, bin2bcd(alarm->time.tm_mday)) 228 | FIELD_PREP(CDNS_RTC_CAL_M, bin2bcd(alarm->time.tm_mon + 1)); 229 230 /* Update registers, check valid alarm flags */ 231 for (tries = 0; tries < CDNS_RTC_MAX_REGS_TRIES; tries++) { 232 writel(timar, crtc->regs + CDNS_RTC_TIMAR); 233 writel(calar, crtc->regs + CDNS_RTC_CALAR); 234 stsr = readl(crtc->regs + CDNS_RTC_STSR); 235 236 if ((stsr & CDNS_RTC_STSR_VTA_VCA) == CDNS_RTC_STSR_VTA_VCA) { 237 ret = 0; 238 break; 239 } 240 } 241 242 if (!ret) 243 cdns_rtc_alarm_irq_enable(dev, alarm->enabled); 244 return ret; 245 } 246 247 static const struct rtc_class_ops cdns_rtc_ops = { 248 .read_time = cdns_rtc_read_time, 249 .set_time = cdns_rtc_set_time, 250 .read_alarm = cdns_rtc_read_alarm, 251 .set_alarm = cdns_rtc_set_alarm, 252 .alarm_irq_enable = cdns_rtc_alarm_irq_enable, 253 }; 254 255 static int cdns_rtc_probe(struct platform_device *pdev) 256 { 257 struct cdns_rtc *crtc; 258 struct resource *res; 259 int ret; 260 unsigned long ref_clk_freq; 261 262 crtc = devm_kzalloc(&pdev->dev, sizeof(*crtc), GFP_KERNEL); 263 if (!crtc) 264 return -ENOMEM; 265 266 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 267 crtc->regs = devm_ioremap_resource(&pdev->dev, res); 268 if (IS_ERR(crtc->regs)) 269 return PTR_ERR(crtc->regs); 270 271 crtc->irq = platform_get_irq(pdev, 0); 272 if (crtc->irq < 0) 273 return -EINVAL; 274 275 crtc->pclk = devm_clk_get(&pdev->dev, "pclk"); 276 if (IS_ERR(crtc->pclk)) { 277 ret = PTR_ERR(crtc->pclk); 278 dev_err(&pdev->dev, 279 "Failed to retrieve the peripheral clock, %d\n", ret); 280 return ret; 281 } 282 283 crtc->ref_clk = devm_clk_get(&pdev->dev, "ref_clk"); 284 if (IS_ERR(crtc->ref_clk)) { 285 ret = PTR_ERR(crtc->ref_clk); 286 dev_err(&pdev->dev, 287 "Failed to retrieve the reference clock, %d\n", ret); 288 return ret; 289 } 290 291 crtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); 292 if (IS_ERR(crtc->rtc_dev)) { 293 ret = PTR_ERR(crtc->rtc_dev); 294 dev_err(&pdev->dev, 295 "Failed to allocate the RTC device, %d\n", ret); 296 return ret; 297 } 298 299 platform_set_drvdata(pdev, crtc); 300 301 ret = clk_prepare_enable(crtc->pclk); 302 if (ret) { 303 dev_err(&pdev->dev, 304 "Failed to enable the peripheral clock, %d\n", ret); 305 return ret; 306 } 307 308 ret = clk_prepare_enable(crtc->ref_clk); 309 if (ret) { 310 dev_err(&pdev->dev, 311 "Failed to enable the reference clock, %d\n", ret); 312 goto err_disable_pclk; 313 } 314 315 ref_clk_freq = clk_get_rate(crtc->ref_clk); 316 if ((ref_clk_freq != 1) && (ref_clk_freq != 100)) { 317 dev_err(&pdev->dev, 318 "Invalid reference clock frequency %lu Hz.\n", 319 ref_clk_freq); 320 ret = -EINVAL; 321 goto err_disable_ref_clk; 322 } 323 324 ret = devm_request_irq(&pdev->dev, crtc->irq, 325 cdns_rtc_irq_handler, 0, 326 dev_name(&pdev->dev), &pdev->dev); 327 if (ret) { 328 dev_err(&pdev->dev, 329 "Failed to request interrupt for the device, %d\n", 330 ret); 331 goto err_disable_ref_clk; 332 } 333 334 /* The RTC supports 01.01.1900 - 31.12.2999 */ 335 crtc->rtc_dev->range_min = mktime64(1900, 1, 1, 0, 0, 0); 336 crtc->rtc_dev->range_max = mktime64(2999, 12, 31, 23, 59, 59); 337 338 crtc->rtc_dev->ops = &cdns_rtc_ops; 339 device_init_wakeup(&pdev->dev, true); 340 341 /* Always use 24-hour mode and keep the RTC values */ 342 writel(0, crtc->regs + CDNS_RTC_HMR); 343 writel(CDNS_RTC_KRTCR_KRTC, crtc->regs + CDNS_RTC_KRTCR); 344 345 ret = rtc_register_device(crtc->rtc_dev); 346 if (ret) { 347 dev_err(&pdev->dev, 348 "Failed to register the RTC device, %d\n", ret); 349 goto err_disable_wakeup; 350 } 351 352 return 0; 353 354 err_disable_wakeup: 355 device_init_wakeup(&pdev->dev, false); 356 357 err_disable_ref_clk: 358 clk_disable_unprepare(crtc->ref_clk); 359 360 err_disable_pclk: 361 clk_disable_unprepare(crtc->pclk); 362 363 return ret; 364 } 365 366 static int cdns_rtc_remove(struct platform_device *pdev) 367 { 368 struct cdns_rtc *crtc = platform_get_drvdata(pdev); 369 370 cdns_rtc_alarm_irq_enable(&pdev->dev, 0); 371 device_init_wakeup(&pdev->dev, 0); 372 373 clk_disable_unprepare(crtc->pclk); 374 clk_disable_unprepare(crtc->ref_clk); 375 376 return 0; 377 } 378 379 #ifdef CONFIG_PM_SLEEP 380 static int cdns_rtc_suspend(struct device *dev) 381 { 382 struct cdns_rtc *crtc = dev_get_drvdata(dev); 383 384 if (device_may_wakeup(dev)) 385 enable_irq_wake(crtc->irq); 386 387 return 0; 388 } 389 390 static int cdns_rtc_resume(struct device *dev) 391 { 392 struct cdns_rtc *crtc = dev_get_drvdata(dev); 393 394 if (device_may_wakeup(dev)) 395 disable_irq_wake(crtc->irq); 396 397 return 0; 398 } 399 #endif 400 401 static SIMPLE_DEV_PM_OPS(cdns_rtc_pm_ops, cdns_rtc_suspend, cdns_rtc_resume); 402 403 static const struct of_device_id cdns_rtc_of_match[] = { 404 { .compatible = "cdns,rtc-r109v3" }, 405 { }, 406 }; 407 MODULE_DEVICE_TABLE(of, cdns_rtc_of_match); 408 409 static struct platform_driver cdns_rtc_driver = { 410 .driver = { 411 .name = "cdns-rtc", 412 .of_match_table = cdns_rtc_of_match, 413 .pm = &cdns_rtc_pm_ops, 414 }, 415 .probe = cdns_rtc_probe, 416 .remove = cdns_rtc_remove, 417 }; 418 module_platform_driver(cdns_rtc_driver); 419 420 MODULE_AUTHOR("Jan Kotas <jank@cadence.com>"); 421 MODULE_DESCRIPTION("Cadence RTC driver"); 422 MODULE_LICENSE("GPL v2"); 423 MODULE_ALIAS("platform:cdns-rtc"); 424