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 %ptR\n", rtc_tm); 174 175 clk_disable(pdata->clk); 176 return 0; 177 } 178 179 static int pic32_rtc_settime(struct device *dev, struct rtc_time *tm) 180 { 181 struct pic32_rtc_dev *pdata = dev_get_drvdata(dev); 182 void __iomem *base = pdata->reg_base; 183 int year = tm->tm_year - 100; 184 185 dev_dbg(dev, "set time %ptR\n", tm); 186 187 if (year < 0 || year >= 100) { 188 dev_err(dev, "rtc only supports 100 years\n"); 189 return -EINVAL; 190 } 191 192 clk_enable(pdata->clk); 193 writeb(bin2bcd(tm->tm_sec), base + PIC32_RTCSEC); 194 writeb(bin2bcd(tm->tm_min), base + PIC32_RTCMIN); 195 writeb(bin2bcd(tm->tm_hour), base + PIC32_RTCHOUR); 196 writeb(bin2bcd(tm->tm_mday), base + PIC32_RTCDAY); 197 writeb(bin2bcd(tm->tm_mon + 1), base + PIC32_RTCMON); 198 writeb(bin2bcd(year), base + PIC32_RTCYEAR); 199 clk_disable(pdata->clk); 200 201 return 0; 202 } 203 204 static int pic32_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) 205 { 206 struct pic32_rtc_dev *pdata = dev_get_drvdata(dev); 207 struct rtc_time *alm_tm = &alrm->time; 208 void __iomem *base = pdata->reg_base; 209 unsigned int alm_en; 210 211 clk_enable(pdata->clk); 212 alm_tm->tm_sec = readb(base + PIC32_ALRMSEC); 213 alm_tm->tm_min = readb(base + PIC32_ALRMMIN); 214 alm_tm->tm_hour = readb(base + PIC32_ALRMHOUR); 215 alm_tm->tm_mon = readb(base + PIC32_ALRMMON); 216 alm_tm->tm_mday = readb(base + PIC32_ALRMDAY); 217 alm_tm->tm_year = readb(base + PIC32_ALRMYEAR); 218 219 alm_en = readb(base + PIC32_RTCALRM); 220 221 alrm->enabled = (alm_en & PIC32_RTCALRM_ALRMEN) ? 1 : 0; 222 223 dev_dbg(dev, "getalarm: %d, %ptR\n", alm_en, alm_tm); 224 225 alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec); 226 alm_tm->tm_min = bcd2bin(alm_tm->tm_min); 227 alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); 228 alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday); 229 alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon) - 1; 230 alm_tm->tm_year = bcd2bin(alm_tm->tm_year); 231 232 clk_disable(pdata->clk); 233 return 0; 234 } 235 236 static int pic32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) 237 { 238 struct pic32_rtc_dev *pdata = dev_get_drvdata(dev); 239 struct rtc_time *tm = &alrm->time; 240 void __iomem *base = pdata->reg_base; 241 242 clk_enable(pdata->clk); 243 dev_dbg(dev, "setalarm: %d, %ptR\n", alrm->enabled, tm); 244 245 writel(0x00, base + PIC32_ALRMTIME); 246 writel(0x00, base + PIC32_ALRMDATE); 247 248 pic32_rtc_setaie(dev, alrm->enabled); 249 250 clk_disable(pdata->clk); 251 return 0; 252 } 253 254 static int pic32_rtc_proc(struct device *dev, struct seq_file *seq) 255 { 256 struct pic32_rtc_dev *pdata = dev_get_drvdata(dev); 257 void __iomem *base = pdata->reg_base; 258 unsigned int repeat; 259 260 clk_enable(pdata->clk); 261 262 repeat = readw(base + PIC32_RTCALRM); 263 repeat &= PIC32_RTCALRM_ARPT; 264 seq_printf(seq, "periodic_IRQ\t: %s\n", repeat ? "yes" : "no"); 265 266 clk_disable(pdata->clk); 267 return 0; 268 } 269 270 static const struct rtc_class_ops pic32_rtcops = { 271 .read_time = pic32_rtc_gettime, 272 .set_time = pic32_rtc_settime, 273 .read_alarm = pic32_rtc_getalarm, 274 .set_alarm = pic32_rtc_setalarm, 275 .proc = pic32_rtc_proc, 276 .alarm_irq_enable = pic32_rtc_setaie, 277 }; 278 279 static void pic32_rtc_enable(struct pic32_rtc_dev *pdata, int en) 280 { 281 void __iomem *base = pdata->reg_base; 282 283 if (!base) 284 return; 285 286 clk_enable(pdata->clk); 287 if (!en) { 288 writel(PIC32_RTCCON_ON, base + PIC32_CLR(PIC32_RTCCON)); 289 } else { 290 pic32_syskey_unlock(); 291 292 writel(PIC32_RTCCON_RTCWREN, base + PIC32_SET(PIC32_RTCCON)); 293 writel(3 << 9, base + PIC32_CLR(PIC32_RTCCON)); 294 295 if (!(readl(base + PIC32_RTCCON) & PIC32_RTCCON_ON)) 296 writel(PIC32_RTCCON_ON, base + PIC32_SET(PIC32_RTCCON)); 297 } 298 clk_disable(pdata->clk); 299 } 300 301 static int pic32_rtc_remove(struct platform_device *pdev) 302 { 303 struct pic32_rtc_dev *pdata = platform_get_drvdata(pdev); 304 305 pic32_rtc_setaie(&pdev->dev, 0); 306 clk_unprepare(pdata->clk); 307 pdata->clk = NULL; 308 309 return 0; 310 } 311 312 static int pic32_rtc_probe(struct platform_device *pdev) 313 { 314 struct pic32_rtc_dev *pdata; 315 struct resource *res; 316 int ret; 317 318 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 319 if (!pdata) 320 return -ENOMEM; 321 322 platform_set_drvdata(pdev, pdata); 323 324 pdata->alarm_irq = platform_get_irq(pdev, 0); 325 if (pdata->alarm_irq < 0) { 326 dev_err(&pdev->dev, "no irq for alarm\n"); 327 return pdata->alarm_irq; 328 } 329 330 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 331 pdata->reg_base = devm_ioremap_resource(&pdev->dev, res); 332 if (IS_ERR(pdata->reg_base)) 333 return PTR_ERR(pdata->reg_base); 334 335 pdata->clk = devm_clk_get(&pdev->dev, NULL); 336 if (IS_ERR(pdata->clk)) { 337 dev_err(&pdev->dev, "failed to find rtc clock source\n"); 338 ret = PTR_ERR(pdata->clk); 339 pdata->clk = NULL; 340 return ret; 341 } 342 343 spin_lock_init(&pdata->alarm_lock); 344 345 clk_prepare_enable(pdata->clk); 346 347 pic32_rtc_enable(pdata, 1); 348 349 device_init_wakeup(&pdev->dev, 1); 350 351 pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, 352 &pic32_rtcops, 353 THIS_MODULE); 354 if (IS_ERR(pdata->rtc)) { 355 ret = PTR_ERR(pdata->rtc); 356 goto err_nortc; 357 } 358 359 pdata->rtc->max_user_freq = 128; 360 361 pic32_rtc_setfreq(&pdev->dev, 1); 362 ret = devm_request_irq(&pdev->dev, pdata->alarm_irq, 363 pic32_rtc_alarmirq, 0, 364 dev_name(&pdev->dev), pdata); 365 if (ret) { 366 dev_err(&pdev->dev, 367 "IRQ %d error %d\n", pdata->alarm_irq, ret); 368 goto err_nortc; 369 } 370 371 clk_disable(pdata->clk); 372 373 return 0; 374 375 err_nortc: 376 pic32_rtc_enable(pdata, 0); 377 clk_disable_unprepare(pdata->clk); 378 379 return ret; 380 } 381 382 static const struct of_device_id pic32_rtc_dt_ids[] = { 383 { .compatible = "microchip,pic32mzda-rtc" }, 384 { /* sentinel */ } 385 }; 386 MODULE_DEVICE_TABLE(of, pic32_rtc_dt_ids); 387 388 static struct platform_driver pic32_rtc_driver = { 389 .probe = pic32_rtc_probe, 390 .remove = pic32_rtc_remove, 391 .driver = { 392 .name = "pic32-rtc", 393 .of_match_table = of_match_ptr(pic32_rtc_dt_ids), 394 }, 395 }; 396 module_platform_driver(pic32_rtc_driver); 397 398 MODULE_DESCRIPTION("Microchip PIC32 RTC Driver"); 399 MODULE_AUTHOR("Joshua Henderson <joshua.henderson@microchip.com>"); 400 MODULE_LICENSE("GPL"); 401