1 /* 2 * An RTC driver for Allwinner A31/A23 3 * 4 * Copyright (c) 2014, Chen-Yu Tsai <wens@csie.org> 5 * 6 * based on rtc-sunxi.c 7 * 8 * An RTC driver for Allwinner A10/A20 9 * 10 * Copyright (c) 2013, Carlo Caione <carlo.caione@gmail.com> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, but WITHOUT 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 20 * more details. 21 */ 22 23 #include <linux/delay.h> 24 #include <linux/err.h> 25 #include <linux/fs.h> 26 #include <linux/init.h> 27 #include <linux/interrupt.h> 28 #include <linux/io.h> 29 #include <linux/kernel.h> 30 #include <linux/module.h> 31 #include <linux/of.h> 32 #include <linux/of_address.h> 33 #include <linux/of_device.h> 34 #include <linux/platform_device.h> 35 #include <linux/rtc.h> 36 #include <linux/types.h> 37 38 /* Control register */ 39 #define SUN6I_LOSC_CTRL 0x0000 40 #define SUN6I_LOSC_CTRL_ALM_DHMS_ACC BIT(9) 41 #define SUN6I_LOSC_CTRL_RTC_HMS_ACC BIT(8) 42 #define SUN6I_LOSC_CTRL_RTC_YMD_ACC BIT(7) 43 #define SUN6I_LOSC_CTRL_ACC_MASK GENMASK(9, 7) 44 45 /* RTC */ 46 #define SUN6I_RTC_YMD 0x0010 47 #define SUN6I_RTC_HMS 0x0014 48 49 /* Alarm 0 (counter) */ 50 #define SUN6I_ALRM_COUNTER 0x0020 51 #define SUN6I_ALRM_CUR_VAL 0x0024 52 #define SUN6I_ALRM_EN 0x0028 53 #define SUN6I_ALRM_EN_CNT_EN BIT(0) 54 #define SUN6I_ALRM_IRQ_EN 0x002c 55 #define SUN6I_ALRM_IRQ_EN_CNT_IRQ_EN BIT(0) 56 #define SUN6I_ALRM_IRQ_STA 0x0030 57 #define SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND BIT(0) 58 59 /* Alarm 1 (wall clock) */ 60 #define SUN6I_ALRM1_EN 0x0044 61 #define SUN6I_ALRM1_IRQ_EN 0x0048 62 #define SUN6I_ALRM1_IRQ_STA 0x004c 63 #define SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND BIT(0) 64 65 /* Alarm config */ 66 #define SUN6I_ALARM_CONFIG 0x0050 67 #define SUN6I_ALARM_CONFIG_WAKEUP BIT(0) 68 69 /* 70 * Get date values 71 */ 72 #define SUN6I_DATE_GET_DAY_VALUE(x) ((x) & 0x0000001f) 73 #define SUN6I_DATE_GET_MON_VALUE(x) (((x) & 0x00000f00) >> 8) 74 #define SUN6I_DATE_GET_YEAR_VALUE(x) (((x) & 0x003f0000) >> 16) 75 #define SUN6I_LEAP_GET_VALUE(x) (((x) & 0x00400000) >> 22) 76 77 /* 78 * Get time values 79 */ 80 #define SUN6I_TIME_GET_SEC_VALUE(x) ((x) & 0x0000003f) 81 #define SUN6I_TIME_GET_MIN_VALUE(x) (((x) & 0x00003f00) >> 8) 82 #define SUN6I_TIME_GET_HOUR_VALUE(x) (((x) & 0x001f0000) >> 16) 83 84 /* 85 * Set date values 86 */ 87 #define SUN6I_DATE_SET_DAY_VALUE(x) ((x) & 0x0000001f) 88 #define SUN6I_DATE_SET_MON_VALUE(x) ((x) << 8 & 0x00000f00) 89 #define SUN6I_DATE_SET_YEAR_VALUE(x) ((x) << 16 & 0x003f0000) 90 #define SUN6I_LEAP_SET_VALUE(x) ((x) << 22 & 0x00400000) 91 92 /* 93 * Set time values 94 */ 95 #define SUN6I_TIME_SET_SEC_VALUE(x) ((x) & 0x0000003f) 96 #define SUN6I_TIME_SET_MIN_VALUE(x) ((x) << 8 & 0x00003f00) 97 #define SUN6I_TIME_SET_HOUR_VALUE(x) ((x) << 16 & 0x001f0000) 98 99 /* 100 * The year parameter passed to the driver is usually an offset relative to 101 * the year 1900. This macro is used to convert this offset to another one 102 * relative to the minimum year allowed by the hardware. 103 * 104 * The year range is 1970 - 2033. This range is selected to match Allwinner's 105 * driver, even though it is somewhat limited. 106 */ 107 #define SUN6I_YEAR_MIN 1970 108 #define SUN6I_YEAR_MAX 2033 109 #define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900) 110 111 struct sun6i_rtc_dev { 112 struct rtc_device *rtc; 113 struct device *dev; 114 void __iomem *base; 115 int irq; 116 unsigned long alarm; 117 }; 118 119 static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id) 120 { 121 struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id; 122 u32 val; 123 124 val = readl(chip->base + SUN6I_ALRM_IRQ_STA); 125 126 if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) { 127 val |= SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND; 128 writel(val, chip->base + SUN6I_ALRM_IRQ_STA); 129 130 rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); 131 132 return IRQ_HANDLED; 133 } 134 135 return IRQ_NONE; 136 } 137 138 static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip) 139 { 140 u32 alrm_val = 0; 141 u32 alrm_irq_val = 0; 142 u32 alrm_wake_val = 0; 143 144 if (to) { 145 alrm_val = SUN6I_ALRM_EN_CNT_EN; 146 alrm_irq_val = SUN6I_ALRM_IRQ_EN_CNT_IRQ_EN; 147 alrm_wake_val = SUN6I_ALARM_CONFIG_WAKEUP; 148 } else { 149 writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, 150 chip->base + SUN6I_ALRM_IRQ_STA); 151 } 152 153 writel(alrm_val, chip->base + SUN6I_ALRM_EN); 154 writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN); 155 writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG); 156 } 157 158 static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) 159 { 160 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); 161 u32 date, time; 162 163 /* 164 * read again in case it changes 165 */ 166 do { 167 date = readl(chip->base + SUN6I_RTC_YMD); 168 time = readl(chip->base + SUN6I_RTC_HMS); 169 } while ((date != readl(chip->base + SUN6I_RTC_YMD)) || 170 (time != readl(chip->base + SUN6I_RTC_HMS))); 171 172 rtc_tm->tm_sec = SUN6I_TIME_GET_SEC_VALUE(time); 173 rtc_tm->tm_min = SUN6I_TIME_GET_MIN_VALUE(time); 174 rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time); 175 176 rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date); 177 rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date); 178 rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date); 179 180 rtc_tm->tm_mon -= 1; 181 182 /* 183 * switch from (data_year->min)-relative offset to 184 * a (1900)-relative one 185 */ 186 rtc_tm->tm_year += SUN6I_YEAR_OFF; 187 188 return rtc_valid_tm(rtc_tm); 189 } 190 191 static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm) 192 { 193 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); 194 u32 alrm_st; 195 u32 alrm_en; 196 197 alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN); 198 alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA); 199 wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN); 200 wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN); 201 rtc_time_to_tm(chip->alarm, &wkalrm->time); 202 203 return 0; 204 } 205 206 static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm) 207 { 208 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); 209 struct rtc_time *alrm_tm = &wkalrm->time; 210 struct rtc_time tm_now; 211 unsigned long time_now = 0; 212 unsigned long time_set = 0; 213 unsigned long time_gap = 0; 214 int ret = 0; 215 216 ret = sun6i_rtc_gettime(dev, &tm_now); 217 if (ret < 0) { 218 dev_err(dev, "Error in getting time\n"); 219 return -EINVAL; 220 } 221 222 rtc_tm_to_time(alrm_tm, &time_set); 223 rtc_tm_to_time(&tm_now, &time_now); 224 if (time_set <= time_now) { 225 dev_err(dev, "Date to set in the past\n"); 226 return -EINVAL; 227 } 228 229 time_gap = time_set - time_now; 230 231 if (time_gap > U32_MAX) { 232 dev_err(dev, "Date too far in the future\n"); 233 return -EINVAL; 234 } 235 236 sun6i_rtc_setaie(0, chip); 237 writel(0, chip->base + SUN6I_ALRM_COUNTER); 238 usleep_range(100, 300); 239 240 writel(time_gap, chip->base + SUN6I_ALRM_COUNTER); 241 chip->alarm = time_set; 242 243 sun6i_rtc_setaie(wkalrm->enabled, chip); 244 245 return 0; 246 } 247 248 static int sun6i_rtc_wait(struct sun6i_rtc_dev *chip, int offset, 249 unsigned int mask, unsigned int ms_timeout) 250 { 251 const unsigned long timeout = jiffies + msecs_to_jiffies(ms_timeout); 252 u32 reg; 253 254 do { 255 reg = readl(chip->base + offset); 256 reg &= mask; 257 258 if (!reg) 259 return 0; 260 261 } while (time_before(jiffies, timeout)); 262 263 return -ETIMEDOUT; 264 } 265 266 static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm) 267 { 268 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); 269 u32 date = 0; 270 u32 time = 0; 271 int year; 272 273 year = rtc_tm->tm_year + 1900; 274 if (year < SUN6I_YEAR_MIN || year > SUN6I_YEAR_MAX) { 275 dev_err(dev, "rtc only supports year in range %d - %d\n", 276 SUN6I_YEAR_MIN, SUN6I_YEAR_MAX); 277 return -EINVAL; 278 } 279 280 rtc_tm->tm_year -= SUN6I_YEAR_OFF; 281 rtc_tm->tm_mon += 1; 282 283 date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | 284 SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | 285 SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); 286 287 if (is_leap_year(year)) 288 date |= SUN6I_LEAP_SET_VALUE(1); 289 290 time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | 291 SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min) | 292 SUN6I_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour); 293 294 /* Check whether registers are writable */ 295 if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, 296 SUN6I_LOSC_CTRL_ACC_MASK, 50)) { 297 dev_err(dev, "rtc is still busy.\n"); 298 return -EBUSY; 299 } 300 301 writel(time, chip->base + SUN6I_RTC_HMS); 302 303 /* 304 * After writing the RTC HH-MM-SS register, the 305 * SUN6I_LOSC_CTRL_RTC_HMS_ACC bit is set and it will not 306 * be cleared until the real writing operation is finished 307 */ 308 309 if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, 310 SUN6I_LOSC_CTRL_RTC_HMS_ACC, 50)) { 311 dev_err(dev, "Failed to set rtc time.\n"); 312 return -ETIMEDOUT; 313 } 314 315 writel(date, chip->base + SUN6I_RTC_YMD); 316 317 /* 318 * After writing the RTC YY-MM-DD register, the 319 * SUN6I_LOSC_CTRL_RTC_YMD_ACC bit is set and it will not 320 * be cleared until the real writing operation is finished 321 */ 322 323 if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, 324 SUN6I_LOSC_CTRL_RTC_YMD_ACC, 50)) { 325 dev_err(dev, "Failed to set rtc time.\n"); 326 return -ETIMEDOUT; 327 } 328 329 return 0; 330 } 331 332 static int sun6i_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) 333 { 334 struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); 335 336 if (!enabled) 337 sun6i_rtc_setaie(enabled, chip); 338 339 return 0; 340 } 341 342 static const struct rtc_class_ops sun6i_rtc_ops = { 343 .read_time = sun6i_rtc_gettime, 344 .set_time = sun6i_rtc_settime, 345 .read_alarm = sun6i_rtc_getalarm, 346 .set_alarm = sun6i_rtc_setalarm, 347 .alarm_irq_enable = sun6i_rtc_alarm_irq_enable 348 }; 349 350 static int sun6i_rtc_probe(struct platform_device *pdev) 351 { 352 struct sun6i_rtc_dev *chip; 353 struct resource *res; 354 int ret; 355 356 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); 357 if (!chip) 358 return -ENOMEM; 359 360 platform_set_drvdata(pdev, chip); 361 chip->dev = &pdev->dev; 362 363 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 364 chip->base = devm_ioremap_resource(&pdev->dev, res); 365 if (IS_ERR(chip->base)) 366 return PTR_ERR(chip->base); 367 368 chip->irq = platform_get_irq(pdev, 0); 369 if (chip->irq < 0) { 370 dev_err(&pdev->dev, "No IRQ resource\n"); 371 return chip->irq; 372 } 373 374 ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, 375 0, dev_name(&pdev->dev), chip); 376 if (ret) { 377 dev_err(&pdev->dev, "Could not request IRQ\n"); 378 return ret; 379 } 380 381 /* clear the alarm counter value */ 382 writel(0, chip->base + SUN6I_ALRM_COUNTER); 383 384 /* disable counter alarm */ 385 writel(0, chip->base + SUN6I_ALRM_EN); 386 387 /* disable counter alarm interrupt */ 388 writel(0, chip->base + SUN6I_ALRM_IRQ_EN); 389 390 /* disable week alarm */ 391 writel(0, chip->base + SUN6I_ALRM1_EN); 392 393 /* disable week alarm interrupt */ 394 writel(0, chip->base + SUN6I_ALRM1_IRQ_EN); 395 396 /* clear counter alarm pending interrupts */ 397 writel(SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND, 398 chip->base + SUN6I_ALRM_IRQ_STA); 399 400 /* clear week alarm pending interrupts */ 401 writel(SUN6I_ALRM1_IRQ_STA_WEEK_IRQ_PEND, 402 chip->base + SUN6I_ALRM1_IRQ_STA); 403 404 /* disable alarm wakeup */ 405 writel(0, chip->base + SUN6I_ALARM_CONFIG); 406 407 chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev, 408 &sun6i_rtc_ops, THIS_MODULE); 409 if (IS_ERR(chip->rtc)) { 410 dev_err(&pdev->dev, "unable to register device\n"); 411 return PTR_ERR(chip->rtc); 412 } 413 414 dev_info(&pdev->dev, "RTC enabled\n"); 415 416 return 0; 417 } 418 419 static int sun6i_rtc_remove(struct platform_device *pdev) 420 { 421 struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev); 422 423 rtc_device_unregister(chip->rtc); 424 425 return 0; 426 } 427 428 static const struct of_device_id sun6i_rtc_dt_ids[] = { 429 { .compatible = "allwinner,sun6i-a31-rtc" }, 430 { /* sentinel */ }, 431 }; 432 MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); 433 434 static struct platform_driver sun6i_rtc_driver = { 435 .probe = sun6i_rtc_probe, 436 .remove = sun6i_rtc_remove, 437 .driver = { 438 .name = "sun6i-rtc", 439 .of_match_table = sun6i_rtc_dt_ids, 440 }, 441 }; 442 443 module_platform_driver(sun6i_rtc_driver); 444 445 MODULE_DESCRIPTION("sun6i RTC driver"); 446 MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>"); 447 MODULE_LICENSE("GPL"); 448