1 /* 2 * PIC32 RTC driver 3 * 4 * Joshua Henderson <joshua.henderson@microchip.com> 5 * Copyright (C) 2016 Microchip Technology Inc. All rights reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 */ 17 #include <linux/init.h> 18 #include <linux/module.h> 19 #include <linux/of.h> 20 #include <linux/platform_device.h> 21 #include <linux/io.h> 22 #include <linux/slab.h> 23 #include <linux/clk.h> 24 #include <linux/rtc.h> 25 #include <linux/bcd.h> 26 27 #include <asm/mach-pic32/pic32.h> 28 29 #define PIC32_RTCCON 0x00 30 #define PIC32_RTCCON_ON BIT(15) 31 #define PIC32_RTCCON_SIDL BIT(13) 32 #define PIC32_RTCCON_RTCCLKSEL (3 << 9) 33 #define PIC32_RTCCON_RTCCLKON BIT(6) 34 #define PIC32_RTCCON_RTCWREN BIT(3) 35 #define PIC32_RTCCON_RTCSYNC BIT(2) 36 #define PIC32_RTCCON_HALFSEC BIT(1) 37 #define PIC32_RTCCON_RTCOE BIT(0) 38 39 #define PIC32_RTCALRM 0x10 40 #define PIC32_RTCALRM_ALRMEN BIT(15) 41 #define PIC32_RTCALRM_CHIME BIT(14) 42 #define PIC32_RTCALRM_PIV BIT(13) 43 #define PIC32_RTCALRM_ALARMSYNC BIT(12) 44 #define PIC32_RTCALRM_AMASK 0x0F00 45 #define PIC32_RTCALRM_ARPT 0xFF 46 47 #define PIC32_RTCHOUR 0x23 48 #define PIC32_RTCMIN 0x22 49 #define PIC32_RTCSEC 0x21 50 #define PIC32_RTCYEAR 0x33 51 #define PIC32_RTCMON 0x32 52 #define PIC32_RTCDAY 0x31 53 54 #define PIC32_ALRMTIME 0x40 55 #define PIC32_ALRMDATE 0x50 56 57 #define PIC32_ALRMHOUR 0x43 58 #define PIC32_ALRMMIN 0x42 59 #define PIC32_ALRMSEC 0x41 60 #define PIC32_ALRMYEAR 0x53 61 #define PIC32_ALRMMON 0x52 62 #define PIC32_ALRMDAY 0x51 63 64 struct pic32_rtc_dev { 65 struct rtc_device *rtc; 66 void __iomem *reg_base; 67 struct clk *clk; 68 spinlock_t alarm_lock; 69 int alarm_irq; 70 bool alarm_clk_enabled; 71 }; 72 73 static void pic32_rtc_alarm_clk_enable(struct pic32_rtc_dev *pdata, 74 bool enable) 75 { 76 unsigned long flags; 77 78 spin_lock_irqsave(&pdata->alarm_lock, flags); 79 if (enable) { 80 if (!pdata->alarm_clk_enabled) { 81 clk_enable(pdata->clk); 82 pdata->alarm_clk_enabled = true; 83 } 84 } else { 85 if (pdata->alarm_clk_enabled) { 86 clk_disable(pdata->clk); 87 pdata->alarm_clk_enabled = false; 88 } 89 } 90 spin_unlock_irqrestore(&pdata->alarm_lock, flags); 91 } 92 93 static irqreturn_t pic32_rtc_alarmirq(int irq, void *id) 94 { 95 struct pic32_rtc_dev *pdata = (struct pic32_rtc_dev *)id; 96 97 clk_enable(pdata->clk); 98 rtc_update_irq(pdata->rtc, 1, RTC_AF | RTC_IRQF); 99 clk_disable(pdata->clk); 100 101 pic32_rtc_alarm_clk_enable(pdata, false); 102 103 return IRQ_HANDLED; 104 } 105 106 static int pic32_rtc_setaie(struct device *dev, unsigned int enabled) 107 { 108 struct pic32_rtc_dev *pdata = dev_get_drvdata(dev); 109 void __iomem *base = pdata->reg_base; 110 111 clk_enable(pdata->clk); 112 113 writel(PIC32_RTCALRM_ALRMEN, 114 base + (enabled ? PIC32_SET(PIC32_RTCALRM) : 115 PIC32_CLR(PIC32_RTCALRM))); 116 117 clk_disable(pdata->clk); 118 119 pic32_rtc_alarm_clk_enable(pdata, enabled); 120 121 return 0; 122 } 123 124 static int pic32_rtc_setfreq(struct device *dev, int freq) 125 { 126 struct pic32_rtc_dev *pdata = dev_get_drvdata(dev); 127 void __iomem *base = pdata->reg_base; 128 129 clk_enable(pdata->clk); 130 131 writel(PIC32_RTCALRM_AMASK, base + PIC32_CLR(PIC32_RTCALRM)); 132 writel(freq << 8, base + PIC32_SET(PIC32_RTCALRM)); 133 writel(PIC32_RTCALRM_CHIME, base + PIC32_SET(PIC32_RTCALRM)); 134 135 clk_disable(pdata->clk); 136 137 return 0; 138 } 139 140 static int pic32_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) 141 { 142 struct pic32_rtc_dev *pdata = dev_get_drvdata(dev); 143 void __iomem *base = pdata->reg_base; 144 unsigned int tries = 0; 145 146 clk_enable(pdata->clk); 147 148 do { 149 rtc_tm->tm_hour = readb(base + PIC32_RTCHOUR); 150 rtc_tm->tm_min = readb(base + PIC32_RTCMIN); 151 rtc_tm->tm_mon = readb(base + PIC32_RTCMON); 152 rtc_tm->tm_mday = readb(base + PIC32_RTCDAY); 153 rtc_tm->tm_year = readb(base + PIC32_RTCYEAR); 154 rtc_tm->tm_sec = readb(base + PIC32_RTCSEC); 155 156 /* 157 * The only way to work out whether the system was mid-update 158 * when we read it is to check the second counter, and if it 159 * is zero, then we re-try the entire read. 160 */ 161 tries += 1; 162 } while (rtc_tm->tm_sec == 0 && tries < 2); 163 164 rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); 165 rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); 166 rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); 167 rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday); 168 rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon) - 1; 169 rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); 170 171 rtc_tm->tm_year += 100; 172 173 dev_dbg(dev, "read time %04d.%02d.%02d %02d:%02d:%02d\n", 174 1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, 175 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); 176 177 clk_disable(pdata->clk); 178 return rtc_valid_tm(rtc_tm); 179 } 180 181 static int pic32_rtc_settime(struct device *dev, struct rtc_time *tm) 182 { 183 struct pic32_rtc_dev *pdata = dev_get_drvdata(dev); 184 void __iomem *base = pdata->reg_base; 185 int year = tm->tm_year - 100; 186 187 dev_dbg(dev, "set time %04d.%02d.%02d %02d:%02d:%02d\n", 188 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, 189 tm->tm_hour, tm->tm_min, tm->tm_sec); 190 191 if (year < 0 || year >= 100) { 192 dev_err(dev, "rtc only supports 100 years\n"); 193 return -EINVAL; 194 } 195 196 clk_enable(pdata->clk); 197 writeb(bin2bcd(tm->tm_sec), base + PIC32_RTCSEC); 198 writeb(bin2bcd(tm->tm_min), base + PIC32_RTCMIN); 199 writeb(bin2bcd(tm->tm_hour), base + PIC32_RTCHOUR); 200 writeb(bin2bcd(tm->tm_mday), base + PIC32_RTCDAY); 201 writeb(bin2bcd(tm->tm_mon + 1), base + PIC32_RTCMON); 202 writeb(bin2bcd(year), base + PIC32_RTCYEAR); 203 clk_disable(pdata->clk); 204 205 return 0; 206 } 207 208 static int pic32_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) 209 { 210 struct pic32_rtc_dev *pdata = dev_get_drvdata(dev); 211 struct rtc_time *alm_tm = &alrm->time; 212 void __iomem *base = pdata->reg_base; 213 unsigned int alm_en; 214 215 clk_enable(pdata->clk); 216 alm_tm->tm_sec = readb(base + PIC32_ALRMSEC); 217 alm_tm->tm_min = readb(base + PIC32_ALRMMIN); 218 alm_tm->tm_hour = readb(base + PIC32_ALRMHOUR); 219 alm_tm->tm_mon = readb(base + PIC32_ALRMMON); 220 alm_tm->tm_mday = readb(base + PIC32_ALRMDAY); 221 alm_tm->tm_year = readb(base + PIC32_ALRMYEAR); 222 223 alm_en = readb(base + PIC32_RTCALRM); 224 225 alrm->enabled = (alm_en & PIC32_RTCALRM_ALRMEN) ? 1 : 0; 226 227 dev_dbg(dev, "getalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", 228 alm_en, 229 1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, 230 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); 231 232 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); 233 alm_tm->tm_min = bcd2bin(alm_tm->tm_min); 234 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); 235 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); 236 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon) - 1; 237 alm_tm->tm_year = bcd2bin(alm_tm->tm_year); 238 239 clk_disable(pdata->clk); 240 return 0; 241 } 242 243 static int pic32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) 244 { 245 struct pic32_rtc_dev *pdata = dev_get_drvdata(dev); 246 struct rtc_time *tm = &alrm->time; 247 void __iomem *base = pdata->reg_base; 248 249 clk_enable(pdata->clk); 250 dev_dbg(dev, "setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", 251 alrm->enabled, 252 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, 253 tm->tm_hour, tm->tm_min, tm->tm_sec); 254 255 writel(0x00, base + PIC32_ALRMTIME); 256 writel(0x00, base + PIC32_ALRMDATE); 257 258 pic32_rtc_setaie(dev, alrm->enabled); 259 260 clk_disable(pdata->clk); 261 return 0; 262 } 263 264 static int pic32_rtc_proc(struct device *dev, struct seq_file *seq) 265 { 266 struct pic32_rtc_dev *pdata = dev_get_drvdata(dev); 267 void __iomem *base = pdata->reg_base; 268 unsigned int repeat; 269 270 clk_enable(pdata->clk); 271 272 repeat = readw(base + PIC32_RTCALRM); 273 repeat &= PIC32_RTCALRM_ARPT; 274 seq_printf(seq, "periodic_IRQ\t: %s\n", repeat ? "yes" : "no"); 275 276 clk_disable(pdata->clk); 277 return 0; 278 } 279 280 static const struct rtc_class_ops pic32_rtcops = { 281 .read_time = pic32_rtc_gettime, 282 .set_time = pic32_rtc_settime, 283 .read_alarm = pic32_rtc_getalarm, 284 .set_alarm = pic32_rtc_setalarm, 285 .proc = pic32_rtc_proc, 286 .alarm_irq_enable = pic32_rtc_setaie, 287 }; 288 289 static void pic32_rtc_enable(struct pic32_rtc_dev *pdata, int en) 290 { 291 void __iomem *base = pdata->reg_base; 292 293 if (!base) 294 return; 295 296 clk_enable(pdata->clk); 297 if (!en) { 298 writel(PIC32_RTCCON_ON, base + PIC32_CLR(PIC32_RTCCON)); 299 } else { 300 pic32_syskey_unlock(); 301 302 writel(PIC32_RTCCON_RTCWREN, base + PIC32_SET(PIC32_RTCCON)); 303 writel(3 << 9, base + PIC32_CLR(PIC32_RTCCON)); 304 305 if (!(readl(base + PIC32_RTCCON) & PIC32_RTCCON_ON)) 306 writel(PIC32_RTCCON_ON, base + PIC32_SET(PIC32_RTCCON)); 307 } 308 clk_disable(pdata->clk); 309 } 310 311 static int pic32_rtc_remove(struct platform_device *pdev) 312 { 313 struct pic32_rtc_dev *pdata = platform_get_drvdata(pdev); 314 315 pic32_rtc_setaie(&pdev->dev, 0); 316 clk_unprepare(pdata->clk); 317 pdata->clk = NULL; 318 319 return 0; 320 } 321 322 static int pic32_rtc_probe(struct platform_device *pdev) 323 { 324 struct pic32_rtc_dev *pdata; 325 struct resource *res; 326 int ret; 327 328 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 329 if (!pdata) 330 return -ENOMEM; 331 332 platform_set_drvdata(pdev, pdata); 333 334 pdata->alarm_irq = platform_get_irq(pdev, 0); 335 if (pdata->alarm_irq < 0) { 336 dev_err(&pdev->dev, "no irq for alarm\n"); 337 return pdata->alarm_irq; 338 } 339 340 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 341 pdata->reg_base = devm_ioremap_resource(&pdev->dev, res); 342 if (IS_ERR(pdata->reg_base)) 343 return PTR_ERR(pdata->reg_base); 344 345 pdata->clk = devm_clk_get(&pdev->dev, NULL); 346 if (IS_ERR(pdata->clk)) { 347 dev_err(&pdev->dev, "failed to find rtc clock source\n"); 348 ret = PTR_ERR(pdata->clk); 349 pdata->clk = NULL; 350 return ret; 351 } 352 353 spin_lock_init(&pdata->alarm_lock); 354 355 clk_prepare_enable(pdata->clk); 356 357 pic32_rtc_enable(pdata, 1); 358 359 device_init_wakeup(&pdev->dev, 1); 360 361 pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 362 &pic32_rtcops, 363 THIS_MODULE); 364 if (IS_ERR(pdata->rtc)) { 365 ret = PTR_ERR(pdata->rtc); 366 goto err_nortc; 367 } 368 369 pdata->rtc->max_user_freq = 128; 370 371 pic32_rtc_setfreq(&pdev->dev, 1); 372 ret = devm_request_irq(&pdev->dev, pdata->alarm_irq, 373 pic32_rtc_alarmirq, 0, 374 dev_name(&pdev->dev), pdata); 375 if (ret) { 376 dev_err(&pdev->dev, 377 "IRQ %d error %d\n", pdata->alarm_irq, ret); 378 goto err_nortc; 379 } 380 381 clk_disable(pdata->clk); 382 383 return 0; 384 385 err_nortc: 386 pic32_rtc_enable(pdata, 0); 387 clk_disable_unprepare(pdata->clk); 388 389 return ret; 390 } 391 392 static const struct of_device_id pic32_rtc_dt_ids[] = { 393 { .compatible = "microchip,pic32mzda-rtc" }, 394 { /* sentinel */ } 395 }; 396 MODULE_DEVICE_TABLE(of, pic32_rtc_dt_ids); 397 398 static struct platform_driver pic32_rtc_driver = { 399 .probe = pic32_rtc_probe, 400 .remove = pic32_rtc_remove, 401 .driver = { 402 .name = "pic32-rtc", 403 .owner = THIS_MODULE, 404 .of_match_table = of_match_ptr(pic32_rtc_dt_ids), 405 }, 406 }; 407 module_platform_driver(pic32_rtc_driver); 408 409 MODULE_DESCRIPTION("Microchip PIC32 RTC Driver"); 410 MODULE_AUTHOR("Joshua Henderson <joshua.henderson@microchip.com>"); 411 MODULE_LICENSE("GPL"); 412