rtc-davinci.c (13614B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * DaVinci Power Management and Real Time Clock Driver for TI platforms 4 * 5 * Copyright (C) 2009 Texas Instruments, Inc 6 * 7 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> 8 */ 9#include <linux/kernel.h> 10#include <linux/init.h> 11#include <linux/module.h> 12#include <linux/ioport.h> 13#include <linux/delay.h> 14#include <linux/spinlock.h> 15#include <linux/rtc.h> 16#include <linux/bcd.h> 17#include <linux/platform_device.h> 18#include <linux/io.h> 19#include <linux/slab.h> 20 21/* 22 * The DaVinci RTC is a simple RTC with the following 23 * Sec: 0 - 59 : BCD count 24 * Min: 0 - 59 : BCD count 25 * Hour: 0 - 23 : BCD count 26 * Day: 0 - 0x7FFF(32767) : Binary count ( Over 89 years ) 27 */ 28 29/* PRTC interface registers */ 30#define DAVINCI_PRTCIF_PID 0x00 31#define PRTCIF_CTLR 0x04 32#define PRTCIF_LDATA 0x08 33#define PRTCIF_UDATA 0x0C 34#define PRTCIF_INTEN 0x10 35#define PRTCIF_INTFLG 0x14 36 37/* PRTCIF_CTLR bit fields */ 38#define PRTCIF_CTLR_BUSY BIT(31) 39#define PRTCIF_CTLR_SIZE BIT(25) 40#define PRTCIF_CTLR_DIR BIT(24) 41#define PRTCIF_CTLR_BENU_MSB BIT(23) 42#define PRTCIF_CTLR_BENU_3RD_BYTE BIT(22) 43#define PRTCIF_CTLR_BENU_2ND_BYTE BIT(21) 44#define PRTCIF_CTLR_BENU_LSB BIT(20) 45#define PRTCIF_CTLR_BENU_MASK (0x00F00000) 46#define PRTCIF_CTLR_BENL_MSB BIT(19) 47#define PRTCIF_CTLR_BENL_3RD_BYTE BIT(18) 48#define PRTCIF_CTLR_BENL_2ND_BYTE BIT(17) 49#define PRTCIF_CTLR_BENL_LSB BIT(16) 50#define PRTCIF_CTLR_BENL_MASK (0x000F0000) 51 52/* PRTCIF_INTEN bit fields */ 53#define PRTCIF_INTEN_RTCSS BIT(1) 54#define PRTCIF_INTEN_RTCIF BIT(0) 55#define PRTCIF_INTEN_MASK (PRTCIF_INTEN_RTCSS \ 56 | PRTCIF_INTEN_RTCIF) 57 58/* PRTCIF_INTFLG bit fields */ 59#define PRTCIF_INTFLG_RTCSS BIT(1) 60#define PRTCIF_INTFLG_RTCIF BIT(0) 61#define PRTCIF_INTFLG_MASK (PRTCIF_INTFLG_RTCSS \ 62 | PRTCIF_INTFLG_RTCIF) 63 64/* PRTC subsystem registers */ 65#define PRTCSS_RTC_INTC_EXTENA1 (0x0C) 66#define PRTCSS_RTC_CTRL (0x10) 67#define PRTCSS_RTC_WDT (0x11) 68#define PRTCSS_RTC_TMR0 (0x12) 69#define PRTCSS_RTC_TMR1 (0x13) 70#define PRTCSS_RTC_CCTRL (0x14) 71#define PRTCSS_RTC_SEC (0x15) 72#define PRTCSS_RTC_MIN (0x16) 73#define PRTCSS_RTC_HOUR (0x17) 74#define PRTCSS_RTC_DAY0 (0x18) 75#define PRTCSS_RTC_DAY1 (0x19) 76#define PRTCSS_RTC_AMIN (0x1A) 77#define PRTCSS_RTC_AHOUR (0x1B) 78#define PRTCSS_RTC_ADAY0 (0x1C) 79#define PRTCSS_RTC_ADAY1 (0x1D) 80#define PRTCSS_RTC_CLKC_CNT (0x20) 81 82/* PRTCSS_RTC_INTC_EXTENA1 */ 83#define PRTCSS_RTC_INTC_EXTENA1_MASK (0x07) 84 85/* PRTCSS_RTC_CTRL bit fields */ 86#define PRTCSS_RTC_CTRL_WDTBUS BIT(7) 87#define PRTCSS_RTC_CTRL_WEN BIT(6) 88#define PRTCSS_RTC_CTRL_WDRT BIT(5) 89#define PRTCSS_RTC_CTRL_WDTFLG BIT(4) 90#define PRTCSS_RTC_CTRL_TE BIT(3) 91#define PRTCSS_RTC_CTRL_TIEN BIT(2) 92#define PRTCSS_RTC_CTRL_TMRFLG BIT(1) 93#define PRTCSS_RTC_CTRL_TMMD BIT(0) 94 95/* PRTCSS_RTC_CCTRL bit fields */ 96#define PRTCSS_RTC_CCTRL_CALBUSY BIT(7) 97#define PRTCSS_RTC_CCTRL_DAEN BIT(5) 98#define PRTCSS_RTC_CCTRL_HAEN BIT(4) 99#define PRTCSS_RTC_CCTRL_MAEN BIT(3) 100#define PRTCSS_RTC_CCTRL_ALMFLG BIT(2) 101#define PRTCSS_RTC_CCTRL_AIEN BIT(1) 102#define PRTCSS_RTC_CCTRL_CAEN BIT(0) 103 104static DEFINE_SPINLOCK(davinci_rtc_lock); 105 106struct davinci_rtc { 107 struct rtc_device *rtc; 108 void __iomem *base; 109 int irq; 110}; 111 112static inline void rtcif_write(struct davinci_rtc *davinci_rtc, 113 u32 val, u32 addr) 114{ 115 writel(val, davinci_rtc->base + addr); 116} 117 118static inline u32 rtcif_read(struct davinci_rtc *davinci_rtc, u32 addr) 119{ 120 return readl(davinci_rtc->base + addr); 121} 122 123static inline void rtcif_wait(struct davinci_rtc *davinci_rtc) 124{ 125 while (rtcif_read(davinci_rtc, PRTCIF_CTLR) & PRTCIF_CTLR_BUSY) 126 cpu_relax(); 127} 128 129static inline void rtcss_write(struct davinci_rtc *davinci_rtc, 130 unsigned long val, u8 addr) 131{ 132 rtcif_wait(davinci_rtc); 133 134 rtcif_write(davinci_rtc, PRTCIF_CTLR_BENL_LSB | addr, PRTCIF_CTLR); 135 rtcif_write(davinci_rtc, val, PRTCIF_LDATA); 136 137 rtcif_wait(davinci_rtc); 138} 139 140static inline u8 rtcss_read(struct davinci_rtc *davinci_rtc, u8 addr) 141{ 142 rtcif_wait(davinci_rtc); 143 144 rtcif_write(davinci_rtc, PRTCIF_CTLR_DIR | PRTCIF_CTLR_BENL_LSB | addr, 145 PRTCIF_CTLR); 146 147 rtcif_wait(davinci_rtc); 148 149 return rtcif_read(davinci_rtc, PRTCIF_LDATA); 150} 151 152static inline void davinci_rtcss_calendar_wait(struct davinci_rtc *davinci_rtc) 153{ 154 while (rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL) & 155 PRTCSS_RTC_CCTRL_CALBUSY) 156 cpu_relax(); 157} 158 159static irqreturn_t davinci_rtc_interrupt(int irq, void *class_dev) 160{ 161 struct davinci_rtc *davinci_rtc = class_dev; 162 unsigned long events = 0; 163 u32 irq_flg; 164 u8 alm_irq, tmr_irq; 165 u8 rtc_ctrl, rtc_cctrl; 166 int ret = IRQ_NONE; 167 168 irq_flg = rtcif_read(davinci_rtc, PRTCIF_INTFLG) & 169 PRTCIF_INTFLG_RTCSS; 170 171 alm_irq = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL) & 172 PRTCSS_RTC_CCTRL_ALMFLG; 173 174 tmr_irq = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL) & 175 PRTCSS_RTC_CTRL_TMRFLG; 176 177 if (irq_flg) { 178 if (alm_irq) { 179 events |= RTC_IRQF | RTC_AF; 180 rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); 181 rtc_cctrl |= PRTCSS_RTC_CCTRL_ALMFLG; 182 rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); 183 } else if (tmr_irq) { 184 events |= RTC_IRQF | RTC_PF; 185 rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL); 186 rtc_ctrl |= PRTCSS_RTC_CTRL_TMRFLG; 187 rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); 188 } 189 190 rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, 191 PRTCIF_INTFLG); 192 rtc_update_irq(davinci_rtc->rtc, 1, events); 193 194 ret = IRQ_HANDLED; 195 } 196 197 return ret; 198} 199 200static int 201davinci_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) 202{ 203 struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); 204 u8 rtc_ctrl; 205 unsigned long flags; 206 int ret = 0; 207 208 spin_lock_irqsave(&davinci_rtc_lock, flags); 209 210 rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL); 211 212 switch (cmd) { 213 case RTC_WIE_ON: 214 rtc_ctrl |= PRTCSS_RTC_CTRL_WEN | PRTCSS_RTC_CTRL_WDTFLG; 215 break; 216 case RTC_WIE_OFF: 217 rtc_ctrl &= ~PRTCSS_RTC_CTRL_WEN; 218 break; 219 default: 220 ret = -ENOIOCTLCMD; 221 } 222 223 rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); 224 225 spin_unlock_irqrestore(&davinci_rtc_lock, flags); 226 227 return ret; 228} 229 230static void convertfromdays(u16 days, struct rtc_time *tm) 231{ 232 int tmp_days, year, mon; 233 234 for (year = 2000;; year++) { 235 tmp_days = rtc_year_days(1, 12, year); 236 if (days >= tmp_days) 237 days -= tmp_days; 238 else { 239 for (mon = 0;; mon++) { 240 tmp_days = rtc_month_days(mon, year); 241 if (days >= tmp_days) { 242 days -= tmp_days; 243 } else { 244 tm->tm_year = year - 1900; 245 tm->tm_mon = mon; 246 tm->tm_mday = days + 1; 247 break; 248 } 249 } 250 break; 251 } 252 } 253} 254 255static void convert2days(u16 *days, struct rtc_time *tm) 256{ 257 int i; 258 *days = 0; 259 260 for (i = 2000; i < 1900 + tm->tm_year; i++) 261 *days += rtc_year_days(1, 12, i); 262 263 *days += rtc_year_days(tm->tm_mday, tm->tm_mon, 1900 + tm->tm_year); 264} 265 266static int davinci_rtc_read_time(struct device *dev, struct rtc_time *tm) 267{ 268 struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); 269 u16 days = 0; 270 u8 day0, day1; 271 unsigned long flags; 272 273 spin_lock_irqsave(&davinci_rtc_lock, flags); 274 275 davinci_rtcss_calendar_wait(davinci_rtc); 276 tm->tm_sec = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_SEC)); 277 278 davinci_rtcss_calendar_wait(davinci_rtc); 279 tm->tm_min = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_MIN)); 280 281 davinci_rtcss_calendar_wait(davinci_rtc); 282 tm->tm_hour = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_HOUR)); 283 284 davinci_rtcss_calendar_wait(davinci_rtc); 285 day0 = rtcss_read(davinci_rtc, PRTCSS_RTC_DAY0); 286 287 davinci_rtcss_calendar_wait(davinci_rtc); 288 day1 = rtcss_read(davinci_rtc, PRTCSS_RTC_DAY1); 289 290 spin_unlock_irqrestore(&davinci_rtc_lock, flags); 291 292 days |= day1; 293 days <<= 8; 294 days |= day0; 295 296 convertfromdays(days, tm); 297 298 return 0; 299} 300 301static int davinci_rtc_set_time(struct device *dev, struct rtc_time *tm) 302{ 303 struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); 304 u16 days; 305 u8 rtc_cctrl; 306 unsigned long flags; 307 308 convert2days(&days, tm); 309 310 spin_lock_irqsave(&davinci_rtc_lock, flags); 311 312 davinci_rtcss_calendar_wait(davinci_rtc); 313 rtcss_write(davinci_rtc, bin2bcd(tm->tm_sec), PRTCSS_RTC_SEC); 314 315 davinci_rtcss_calendar_wait(davinci_rtc); 316 rtcss_write(davinci_rtc, bin2bcd(tm->tm_min), PRTCSS_RTC_MIN); 317 318 davinci_rtcss_calendar_wait(davinci_rtc); 319 rtcss_write(davinci_rtc, bin2bcd(tm->tm_hour), PRTCSS_RTC_HOUR); 320 321 davinci_rtcss_calendar_wait(davinci_rtc); 322 rtcss_write(davinci_rtc, days & 0xFF, PRTCSS_RTC_DAY0); 323 324 davinci_rtcss_calendar_wait(davinci_rtc); 325 rtcss_write(davinci_rtc, (days & 0xFF00) >> 8, PRTCSS_RTC_DAY1); 326 327 rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); 328 rtc_cctrl |= PRTCSS_RTC_CCTRL_CAEN; 329 rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); 330 331 spin_unlock_irqrestore(&davinci_rtc_lock, flags); 332 333 return 0; 334} 335 336static int davinci_rtc_alarm_irq_enable(struct device *dev, 337 unsigned int enabled) 338{ 339 struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); 340 unsigned long flags; 341 u8 rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); 342 343 spin_lock_irqsave(&davinci_rtc_lock, flags); 344 345 if (enabled) 346 rtc_cctrl |= PRTCSS_RTC_CCTRL_DAEN | 347 PRTCSS_RTC_CCTRL_HAEN | 348 PRTCSS_RTC_CCTRL_MAEN | 349 PRTCSS_RTC_CCTRL_ALMFLG | 350 PRTCSS_RTC_CCTRL_AIEN; 351 else 352 rtc_cctrl &= ~PRTCSS_RTC_CCTRL_AIEN; 353 354 davinci_rtcss_calendar_wait(davinci_rtc); 355 rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); 356 357 spin_unlock_irqrestore(&davinci_rtc_lock, flags); 358 359 return 0; 360} 361 362static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) 363{ 364 struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); 365 u16 days = 0; 366 u8 day0, day1; 367 unsigned long flags; 368 369 alm->time.tm_sec = 0; 370 371 spin_lock_irqsave(&davinci_rtc_lock, flags); 372 373 davinci_rtcss_calendar_wait(davinci_rtc); 374 alm->time.tm_min = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_AMIN)); 375 376 davinci_rtcss_calendar_wait(davinci_rtc); 377 alm->time.tm_hour = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_AHOUR)); 378 379 davinci_rtcss_calendar_wait(davinci_rtc); 380 day0 = rtcss_read(davinci_rtc, PRTCSS_RTC_ADAY0); 381 382 davinci_rtcss_calendar_wait(davinci_rtc); 383 day1 = rtcss_read(davinci_rtc, PRTCSS_RTC_ADAY1); 384 385 spin_unlock_irqrestore(&davinci_rtc_lock, flags); 386 days |= day1; 387 days <<= 8; 388 days |= day0; 389 390 convertfromdays(days, &alm->time); 391 392 alm->pending = !!(rtcss_read(davinci_rtc, 393 PRTCSS_RTC_CCTRL) & 394 PRTCSS_RTC_CCTRL_AIEN); 395 alm->enabled = alm->pending && device_may_wakeup(dev); 396 397 return 0; 398} 399 400static int davinci_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 401{ 402 struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); 403 unsigned long flags; 404 u16 days; 405 406 convert2days(&days, &alm->time); 407 408 spin_lock_irqsave(&davinci_rtc_lock, flags); 409 410 davinci_rtcss_calendar_wait(davinci_rtc); 411 rtcss_write(davinci_rtc, bin2bcd(alm->time.tm_min), PRTCSS_RTC_AMIN); 412 413 davinci_rtcss_calendar_wait(davinci_rtc); 414 rtcss_write(davinci_rtc, bin2bcd(alm->time.tm_hour), PRTCSS_RTC_AHOUR); 415 416 davinci_rtcss_calendar_wait(davinci_rtc); 417 rtcss_write(davinci_rtc, days & 0xFF, PRTCSS_RTC_ADAY0); 418 419 davinci_rtcss_calendar_wait(davinci_rtc); 420 rtcss_write(davinci_rtc, (days & 0xFF00) >> 8, PRTCSS_RTC_ADAY1); 421 422 spin_unlock_irqrestore(&davinci_rtc_lock, flags); 423 424 return 0; 425} 426 427static const struct rtc_class_ops davinci_rtc_ops = { 428 .ioctl = davinci_rtc_ioctl, 429 .read_time = davinci_rtc_read_time, 430 .set_time = davinci_rtc_set_time, 431 .alarm_irq_enable = davinci_rtc_alarm_irq_enable, 432 .read_alarm = davinci_rtc_read_alarm, 433 .set_alarm = davinci_rtc_set_alarm, 434}; 435 436static int __init davinci_rtc_probe(struct platform_device *pdev) 437{ 438 struct device *dev = &pdev->dev; 439 struct davinci_rtc *davinci_rtc; 440 int ret = 0; 441 442 davinci_rtc = devm_kzalloc(&pdev->dev, sizeof(struct davinci_rtc), GFP_KERNEL); 443 if (!davinci_rtc) 444 return -ENOMEM; 445 446 davinci_rtc->irq = platform_get_irq(pdev, 0); 447 if (davinci_rtc->irq < 0) 448 return davinci_rtc->irq; 449 450 davinci_rtc->base = devm_platform_ioremap_resource(pdev, 0); 451 if (IS_ERR(davinci_rtc->base)) 452 return PTR_ERR(davinci_rtc->base); 453 454 platform_set_drvdata(pdev, davinci_rtc); 455 456 davinci_rtc->rtc = devm_rtc_allocate_device(&pdev->dev); 457 if (IS_ERR(davinci_rtc->rtc)) 458 return PTR_ERR(davinci_rtc->rtc); 459 460 davinci_rtc->rtc->ops = &davinci_rtc_ops; 461 davinci_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; 462 davinci_rtc->rtc->range_max = RTC_TIMESTAMP_BEGIN_2000 + (1 << 16) * 86400ULL - 1; 463 464 rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG); 465 rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); 466 rtcss_write(davinci_rtc, 0, PRTCSS_RTC_INTC_EXTENA1); 467 468 rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CTRL); 469 rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CCTRL); 470 471 ret = devm_request_irq(dev, davinci_rtc->irq, davinci_rtc_interrupt, 472 0, "davinci_rtc", davinci_rtc); 473 if (ret < 0) { 474 dev_err(dev, "unable to register davinci RTC interrupt\n"); 475 return ret; 476 } 477 478 /* Enable interrupts */ 479 rtcif_write(davinci_rtc, PRTCIF_INTEN_RTCSS, PRTCIF_INTEN); 480 rtcss_write(davinci_rtc, PRTCSS_RTC_INTC_EXTENA1_MASK, 481 PRTCSS_RTC_INTC_EXTENA1); 482 483 rtcss_write(davinci_rtc, PRTCSS_RTC_CCTRL_CAEN, PRTCSS_RTC_CCTRL); 484 485 device_init_wakeup(&pdev->dev, 0); 486 487 return devm_rtc_register_device(davinci_rtc->rtc); 488} 489 490static int __exit davinci_rtc_remove(struct platform_device *pdev) 491{ 492 struct davinci_rtc *davinci_rtc = platform_get_drvdata(pdev); 493 494 device_init_wakeup(&pdev->dev, 0); 495 496 rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); 497 498 return 0; 499} 500 501static struct platform_driver davinci_rtc_driver = { 502 .remove = __exit_p(davinci_rtc_remove), 503 .driver = { 504 .name = "rtc_davinci", 505 }, 506}; 507 508module_platform_driver_probe(davinci_rtc_driver, davinci_rtc_probe); 509 510MODULE_AUTHOR("Miguel Aguilar <miguel.aguilar@ridgerun.com>"); 511MODULE_DESCRIPTION("Texas Instruments DaVinci PRTC Driver"); 512MODULE_LICENSE("GPL");