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 */ 83struct 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 */ 99static 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 */ 112static 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 */ 129static 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 */ 154static 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 188out: 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 */ 197static 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 */ 212static 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 225static 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 */ 242static 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 */ 267static 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 296static 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 */ 307static 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 */ 357static 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 */ 372static 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 rc = clk_prepare_enable(imxdi->clk); 405 if (rc) 406 return rc; 407 408 /* 409 * Initialize dryice hardware 410 */ 411 412 /* mask all interrupts */ 413 __raw_writel(0, imxdi->ioaddr + DIER); 414 415 rc = devm_request_irq(&pdev->dev, imxdi->irq, dryice_norm_irq, 416 IRQF_SHARED, pdev->name, imxdi); 417 if (rc) { 418 dev_warn(&pdev->dev, "interrupt not available.\n"); 419 goto err; 420 } 421 422 /* put dryice into valid state */ 423 if (__raw_readl(imxdi->ioaddr + DSR) & DSR_NVF) { 424 rc = di_write_wait(imxdi, DSR_NVF | DSR_SVF, DSR); 425 if (rc) 426 goto err; 427 } 428 429 /* initialize alarm */ 430 rc = di_write_wait(imxdi, DCAMR_UNSET, DCAMR); 431 if (rc) 432 goto err; 433 rc = di_write_wait(imxdi, 0, DCALR); 434 if (rc) 435 goto err; 436 437 /* clear alarm flag */ 438 if (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) { 439 rc = di_write_wait(imxdi, DSR_CAF, DSR); 440 if (rc) 441 goto err; 442 } 443 444 /* the timer won't count if it has never been written to */ 445 if (__raw_readl(imxdi->ioaddr + DTCMR) == 0) { 446 rc = di_write_wait(imxdi, 0, DTCMR); 447 if (rc) 448 goto err; 449 } 450 451 /* start keeping time */ 452 if (!(__raw_readl(imxdi->ioaddr + DCR) & DCR_TCE)) { 453 rc = di_write_wait(imxdi, 454 __raw_readl(imxdi->ioaddr + DCR) | DCR_TCE, 455 DCR); 456 if (rc) 457 goto err; 458 } 459 460 platform_set_drvdata(pdev, imxdi); 461 imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 462 &dryice_rtc_ops, THIS_MODULE); 463 if (IS_ERR(imxdi->rtc)) { 464 rc = PTR_ERR(imxdi->rtc); 465 goto err; 466 } 467 468 return 0; 469 470err: 471 clk_disable_unprepare(imxdi->clk); 472 473 return rc; 474} 475 476static int __exit dryice_rtc_remove(struct platform_device *pdev) 477{ 478 struct imxdi_dev *imxdi = platform_get_drvdata(pdev); 479 480 flush_work(&imxdi->work); 481 482 /* mask all interrupts */ 483 __raw_writel(0, imxdi->ioaddr + DIER); 484 485 clk_disable_unprepare(imxdi->clk); 486 487 return 0; 488} 489 490#ifdef CONFIG_OF 491static const struct of_device_id dryice_dt_ids[] = { 492 { .compatible = "fsl,imx25-rtc" }, 493 { /* sentinel */ } 494}; 495 496MODULE_DEVICE_TABLE(of, dryice_dt_ids); 497#endif 498 499static struct platform_driver dryice_rtc_driver = { 500 .driver = { 501 .name = "imxdi_rtc", 502 .owner = THIS_MODULE, 503 .of_match_table = of_match_ptr(dryice_dt_ids), 504 }, 505 .remove = __exit_p(dryice_rtc_remove), 506}; 507 508module_platform_driver_probe(dryice_rtc_driver, dryice_rtc_probe); 509 510MODULE_AUTHOR("Freescale Semiconductor, Inc."); 511MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); 512MODULE_DESCRIPTION("IMX DryIce Realtime Clock Driver (RTC)"); 513MODULE_LICENSE("GPL"); 514