1 /* 2 * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. 3 * Copyright 2010 Orex Computed Radiography 4 */ 5 6 /* 7 * The code contained herein is licensed under the GNU General Public 8 * License. You may obtain a copy of the GNU General Public License 9 * Version 2 or later at the following locations: 10 * 11 * http://www.opensource.org/licenses/gpl-license.html 12 * http://www.gnu.org/copyleft/gpl.html 13 */ 14 15 /* based on rtc-mc13892.c */ 16 17 /* 18 * This driver uses the 47-bit 32 kHz counter in the Freescale DryIce block 19 * to implement a Linux RTC. Times and alarms are truncated to seconds. 20 * Since the RTC framework performs API locking via rtc->ops_lock the 21 * only simultaneous accesses we need to deal with is updating DryIce 22 * registers while servicing an alarm. 23 * 24 * Note that reading the DSR (DryIce Status Register) automatically clears 25 * the WCF (Write Complete Flag). All DryIce writes are synchronized to the 26 * LP (Low Power) domain and set the WCF upon completion. Writes to the 27 * DIER (DryIce Interrupt Enable Register) are the only exception. These 28 * occur at normal bus speeds and do not set WCF. Periodic interrupts are 29 * not supported by the hardware. 30 */ 31 32 #include <linux/io.h> 33 #include <linux/clk.h> 34 #include <linux/delay.h> 35 #include <linux/module.h> 36 #include <linux/platform_device.h> 37 #include <linux/rtc.h> 38 #include <linux/sched.h> 39 #include <linux/spinlock.h> 40 #include <linux/workqueue.h> 41 #include <linux/of.h> 42 43 /* DryIce Register Definitions */ 44 45 #define DTCMR 0x00 /* Time Counter MSB Reg */ 46 #define DTCLR 0x04 /* Time Counter LSB Reg */ 47 48 #define DCAMR 0x08 /* Clock Alarm MSB Reg */ 49 #define DCALR 0x0c /* Clock Alarm LSB Reg */ 50 #define DCAMR_UNSET 0xFFFFFFFF /* doomsday - 1 sec */ 51 52 #define DCR 0x10 /* Control Reg */ 53 #define DCR_TCE (1 << 3) /* Time Counter Enable */ 54 55 #define DSR 0x14 /* Status Reg */ 56 #define DSR_WBF (1 << 10) /* Write Busy Flag */ 57 #define DSR_WNF (1 << 9) /* Write Next Flag */ 58 #define DSR_WCF (1 << 8) /* Write Complete Flag */ 59 #define DSR_WEF (1 << 7) /* Write Error Flag */ 60 #define DSR_CAF (1 << 4) /* Clock Alarm Flag */ 61 #define DSR_NVF (1 << 1) /* Non-Valid Flag */ 62 #define DSR_SVF (1 << 0) /* Security Violation Flag */ 63 64 #define DIER 0x18 /* Interrupt Enable Reg */ 65 #define DIER_WNIE (1 << 9) /* Write Next Interrupt Enable */ 66 #define DIER_WCIE (1 << 8) /* Write Complete Interrupt Enable */ 67 #define DIER_WEIE (1 << 7) /* Write Error Interrupt Enable */ 68 #define DIER_CAIE (1 << 4) /* Clock Alarm Interrupt Enable */ 69 70 /** 71 * struct imxdi_dev - private imxdi rtc data 72 * @pdev: pionter to platform dev 73 * @rtc: pointer to rtc struct 74 * @ioaddr: IO registers pointer 75 * @irq: dryice normal interrupt 76 * @clk: input reference clock 77 * @dsr: copy of the DSR register 78 * @irq_lock: interrupt enable register (DIER) lock 79 * @write_wait: registers write complete queue 80 * @write_mutex: serialize registers write 81 * @work: schedule alarm work 82 */ 83 struct imxdi_dev { 84 struct platform_device *pdev; 85 struct rtc_device *rtc; 86 void __iomem *ioaddr; 87 int irq; 88 struct clk *clk; 89 u32 dsr; 90 spinlock_t irq_lock; 91 wait_queue_head_t write_wait; 92 struct mutex write_mutex; 93 struct work_struct work; 94 }; 95 96 /* 97 * enable a dryice interrupt 98 */ 99 static void di_int_enable(struct imxdi_dev *imxdi, u32 intr) 100 { 101 unsigned long flags; 102 103 spin_lock_irqsave(&imxdi->irq_lock, flags); 104 __raw_writel(__raw_readl(imxdi->ioaddr + DIER) | intr, 105 imxdi->ioaddr + DIER); 106 spin_unlock_irqrestore(&imxdi->irq_lock, flags); 107 } 108 109 /* 110 * disable a dryice interrupt 111 */ 112 static void di_int_disable(struct imxdi_dev *imxdi, u32 intr) 113 { 114 unsigned long flags; 115 116 spin_lock_irqsave(&imxdi->irq_lock, flags); 117 __raw_writel(__raw_readl(imxdi->ioaddr + DIER) & ~intr, 118 imxdi->ioaddr + DIER); 119 spin_unlock_irqrestore(&imxdi->irq_lock, flags); 120 } 121 122 /* 123 * This function attempts to clear the dryice write-error flag. 124 * 125 * A dryice write error is similar to a bus fault and should not occur in 126 * normal operation. Clearing the flag requires another write, so the root 127 * cause of the problem may need to be fixed before the flag can be cleared. 128 */ 129 static void clear_write_error(struct imxdi_dev *imxdi) 130 { 131 int cnt; 132 133 dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n"); 134 135 /* clear the write error flag */ 136 __raw_writel(DSR_WEF, imxdi->ioaddr + DSR); 137 138 /* wait for it to take effect */ 139 for (cnt = 0; cnt < 1000; cnt++) { 140 if ((__raw_readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0) 141 return; 142 udelay(10); 143 } 144 dev_err(&imxdi->pdev->dev, 145 "ERROR: Cannot clear write-error flag!\n"); 146 } 147 148 /* 149 * Write a dryice register and wait until it completes. 150 * 151 * This function uses interrupts to determine when the 152 * write has completed. 153 */ 154 static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg) 155 { 156 int ret; 157 int rc = 0; 158 159 /* serialize register writes */ 160 mutex_lock(&imxdi->write_mutex); 161 162 /* enable the write-complete interrupt */ 163 di_int_enable(imxdi, DIER_WCIE); 164 165 imxdi->dsr = 0; 166 167 /* do the register write */ 168 __raw_writel(val, imxdi->ioaddr + reg); 169 170 /* wait for the write to finish */ 171 ret = wait_event_interruptible_timeout(imxdi->write_wait, 172 imxdi->dsr & (DSR_WCF | DSR_WEF), msecs_to_jiffies(1)); 173 if (ret < 0) { 174 rc = ret; 175 goto out; 176 } else if (ret == 0) { 177 dev_warn(&imxdi->pdev->dev, 178 "Write-wait timeout " 179 "val = 0x%08x reg = 0x%08x\n", val, reg); 180 } 181 182 /* check for write error */ 183 if (imxdi->dsr & DSR_WEF) { 184 clear_write_error(imxdi); 185 rc = -EIO; 186 } 187 188 out: 189 mutex_unlock(&imxdi->write_mutex); 190 191 return rc; 192 } 193 194 /* 195 * read the seconds portion of the current time from the dryice time counter 196 */ 197 static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm) 198 { 199 struct imxdi_dev *imxdi = dev_get_drvdata(dev); 200 unsigned long now; 201 202 now = __raw_readl(imxdi->ioaddr + DTCMR); 203 rtc_time_to_tm(now, tm); 204 205 return 0; 206 } 207 208 /* 209 * set the seconds portion of dryice time counter and clear the 210 * fractional part. 211 */ 212 static int dryice_rtc_set_mmss(struct device *dev, unsigned long secs) 213 { 214 struct imxdi_dev *imxdi = dev_get_drvdata(dev); 215 int rc; 216 217 /* zero the fractional part first */ 218 rc = di_write_wait(imxdi, 0, DTCLR); 219 if (rc == 0) 220 rc = di_write_wait(imxdi, secs, DTCMR); 221 222 return rc; 223 } 224 225 static int dryice_rtc_alarm_irq_enable(struct device *dev, 226 unsigned int enabled) 227 { 228 struct imxdi_dev *imxdi = dev_get_drvdata(dev); 229 230 if (enabled) 231 di_int_enable(imxdi, DIER_CAIE); 232 else 233 di_int_disable(imxdi, DIER_CAIE); 234 235 return 0; 236 } 237 238 /* 239 * read the seconds portion of the alarm register. 240 * the fractional part of the alarm register is always zero. 241 */ 242 static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) 243 { 244 struct imxdi_dev *imxdi = dev_get_drvdata(dev); 245 u32 dcamr; 246 247 dcamr = __raw_readl(imxdi->ioaddr + DCAMR); 248 rtc_time_to_tm(dcamr, &alarm->time); 249 250 /* alarm is enabled if the interrupt is enabled */ 251 alarm->enabled = (__raw_readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0; 252 253 /* don't allow the DSR read to mess up DSR_WCF */ 254 mutex_lock(&imxdi->write_mutex); 255 256 /* alarm is pending if the alarm flag is set */ 257 alarm->pending = (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0; 258 259 mutex_unlock(&imxdi->write_mutex); 260 261 return 0; 262 } 263 264 /* 265 * set the seconds portion of dryice alarm register 266 */ 267 static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) 268 { 269 struct imxdi_dev *imxdi = dev_get_drvdata(dev); 270 unsigned long now; 271 unsigned long alarm_time; 272 int rc; 273 274 rc = rtc_tm_to_time(&alarm->time, &alarm_time); 275 if (rc) 276 return rc; 277 278 /* don't allow setting alarm in the past */ 279 now = __raw_readl(imxdi->ioaddr + DTCMR); 280 if (alarm_time < now) 281 return -EINVAL; 282 283 /* write the new alarm time */ 284 rc = di_write_wait(imxdi, (u32)alarm_time, DCAMR); 285 if (rc) 286 return rc; 287 288 if (alarm->enabled) 289 di_int_enable(imxdi, DIER_CAIE); /* enable alarm intr */ 290 else 291 di_int_disable(imxdi, DIER_CAIE); /* disable alarm intr */ 292 293 return 0; 294 } 295 296 static struct rtc_class_ops dryice_rtc_ops = { 297 .read_time = dryice_rtc_read_time, 298 .set_mmss = dryice_rtc_set_mmss, 299 .alarm_irq_enable = dryice_rtc_alarm_irq_enable, 300 .read_alarm = dryice_rtc_read_alarm, 301 .set_alarm = dryice_rtc_set_alarm, 302 }; 303 304 /* 305 * dryice "normal" interrupt handler 306 */ 307 static irqreturn_t dryice_norm_irq(int irq, void *dev_id) 308 { 309 struct imxdi_dev *imxdi = dev_id; 310 u32 dsr, dier; 311 irqreturn_t rc = IRQ_NONE; 312 313 dier = __raw_readl(imxdi->ioaddr + DIER); 314 315 /* handle write complete and write error cases */ 316 if ((dier & DIER_WCIE)) { 317 /*If the write wait queue is empty then there is no pending 318 operations. It means the interrupt is for DryIce -Security. 319 IRQ must be returned as none.*/ 320 if (list_empty_careful(&imxdi->write_wait.task_list)) 321 return rc; 322 323 /* DSR_WCF clears itself on DSR read */ 324 dsr = __raw_readl(imxdi->ioaddr + DSR); 325 if ((dsr & (DSR_WCF | DSR_WEF))) { 326 /* mask the interrupt */ 327 di_int_disable(imxdi, DIER_WCIE); 328 329 /* save the dsr value for the wait queue */ 330 imxdi->dsr |= dsr; 331 332 wake_up_interruptible(&imxdi->write_wait); 333 rc = IRQ_HANDLED; 334 } 335 } 336 337 /* handle the alarm case */ 338 if ((dier & DIER_CAIE)) { 339 /* DSR_WCF clears itself on DSR read */ 340 dsr = __raw_readl(imxdi->ioaddr + DSR); 341 if (dsr & DSR_CAF) { 342 /* mask the interrupt */ 343 di_int_disable(imxdi, DIER_CAIE); 344 345 /* finish alarm in user context */ 346 schedule_work(&imxdi->work); 347 rc = IRQ_HANDLED; 348 } 349 } 350 return rc; 351 } 352 353 /* 354 * post the alarm event from user context so it can sleep 355 * on the write completion. 356 */ 357 static void dryice_work(struct work_struct *work) 358 { 359 struct imxdi_dev *imxdi = container_of(work, 360 struct imxdi_dev, work); 361 362 /* dismiss the interrupt (ignore error) */ 363 di_write_wait(imxdi, DSR_CAF, DSR); 364 365 /* pass the alarm event to the rtc framework. */ 366 rtc_update_irq(imxdi->rtc, 1, RTC_AF | RTC_IRQF); 367 } 368 369 /* 370 * probe for dryice rtc device 371 */ 372 static int __init dryice_rtc_probe(struct platform_device *pdev) 373 { 374 struct resource *res; 375 struct imxdi_dev *imxdi; 376 int rc; 377 378 imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL); 379 if (!imxdi) 380 return -ENOMEM; 381 382 imxdi->pdev = pdev; 383 384 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 385 imxdi->ioaddr = devm_ioremap_resource(&pdev->dev, res); 386 if (IS_ERR(imxdi->ioaddr)) 387 return PTR_ERR(imxdi->ioaddr); 388 389 spin_lock_init(&imxdi->irq_lock); 390 391 imxdi->irq = platform_get_irq(pdev, 0); 392 if (imxdi->irq < 0) 393 return imxdi->irq; 394 395 init_waitqueue_head(&imxdi->write_wait); 396 397 INIT_WORK(&imxdi->work, dryice_work); 398 399 mutex_init(&imxdi->write_mutex); 400 401 imxdi->clk = devm_clk_get(&pdev->dev, NULL); 402 if (IS_ERR(imxdi->clk)) 403 return PTR_ERR(imxdi->clk); 404 clk_prepare_enable(imxdi->clk); 405 406 /* 407 * Initialize dryice hardware 408 */ 409 410 /* mask all interrupts */ 411 __raw_writel(0, imxdi->ioaddr + DIER); 412 413 rc = devm_request_irq(&pdev->dev, imxdi->irq, dryice_norm_irq, 414 IRQF_SHARED, pdev->name, imxdi); 415 if (rc) { 416 dev_warn(&pdev->dev, "interrupt not available.\n"); 417 goto err; 418 } 419 420 /* put dryice into valid state */ 421 if (__raw_readl(imxdi->ioaddr + DSR) & DSR_NVF) { 422 rc = di_write_wait(imxdi, DSR_NVF | DSR_SVF, DSR); 423 if (rc) 424 goto err; 425 } 426 427 /* initialize alarm */ 428 rc = di_write_wait(imxdi, DCAMR_UNSET, DCAMR); 429 if (rc) 430 goto err; 431 rc = di_write_wait(imxdi, 0, DCALR); 432 if (rc) 433 goto err; 434 435 /* clear alarm flag */ 436 if (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) { 437 rc = di_write_wait(imxdi, DSR_CAF, DSR); 438 if (rc) 439 goto err; 440 } 441 442 /* the timer won't count if it has never been written to */ 443 if (__raw_readl(imxdi->ioaddr + DTCMR) == 0) { 444 rc = di_write_wait(imxdi, 0, DTCMR); 445 if (rc) 446 goto err; 447 } 448 449 /* start keeping time */ 450 if (!(__raw_readl(imxdi->ioaddr + DCR) & DCR_TCE)) { 451 rc = di_write_wait(imxdi, 452 __raw_readl(imxdi->ioaddr + DCR) | DCR_TCE, 453 DCR); 454 if (rc) 455 goto err; 456 } 457 458 platform_set_drvdata(pdev, imxdi); 459 imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 460 &dryice_rtc_ops, THIS_MODULE); 461 if (IS_ERR(imxdi->rtc)) { 462 rc = PTR_ERR(imxdi->rtc); 463 goto err; 464 } 465 466 return 0; 467 468 err: 469 clk_disable_unprepare(imxdi->clk); 470 471 return rc; 472 } 473 474 static int __exit dryice_rtc_remove(struct platform_device *pdev) 475 { 476 struct imxdi_dev *imxdi = platform_get_drvdata(pdev); 477 478 flush_work(&imxdi->work); 479 480 /* mask all interrupts */ 481 __raw_writel(0, imxdi->ioaddr + DIER); 482 483 clk_disable_unprepare(imxdi->clk); 484 485 return 0; 486 } 487 488 #ifdef CONFIG_OF 489 static const struct of_device_id dryice_dt_ids[] = { 490 { .compatible = "fsl,imx25-rtc" }, 491 { /* sentinel */ } 492 }; 493 494 MODULE_DEVICE_TABLE(of, dryice_dt_ids); 495 #endif 496 497 static struct platform_driver dryice_rtc_driver = { 498 .driver = { 499 .name = "imxdi_rtc", 500 .owner = THIS_MODULE, 501 .of_match_table = of_match_ptr(dryice_dt_ids), 502 }, 503 .remove = __exit_p(dryice_rtc_remove), 504 }; 505 506 module_platform_driver_probe(dryice_rtc_driver, dryice_rtc_probe); 507 508 MODULE_AUTHOR("Freescale Semiconductor, Inc."); 509 MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); 510 MODULE_DESCRIPTION("IMX DryIce Realtime Clock Driver (RTC)"); 511 MODULE_LICENSE("GPL"); 512