Lines Matching +full:sun4i +full:- +full:a10 +full:- +full:rtc

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * An RTC driver for Allwinner A10/A20
20 #include <linux/rtc.h>
110 #define SUNXI_YEAR_OFF(x) ((x)->min - 1900)
139 struct rtc_device *rtc; member
151 val = readl(chip->base + SUNXI_ALRM_IRQ_STA); in sunxi_rtc_alarmirq()
155 writel(val, chip->base + SUNXI_ALRM_IRQ_STA); in sunxi_rtc_alarmirq()
157 rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF); in sunxi_rtc_alarmirq()
171 alrm_val = readl(chip->base + SUNXI_ALRM_EN); in sunxi_rtc_setaie()
174 alrm_irq_val = readl(chip->base + SUNXI_ALRM_IRQ_EN); in sunxi_rtc_setaie()
178 chip->base + SUNXI_ALRM_IRQ_STA); in sunxi_rtc_setaie()
181 writel(alrm_val, chip->base + SUNXI_ALRM_EN); in sunxi_rtc_setaie()
182 writel(alrm_irq_val, chip->base + SUNXI_ALRM_IRQ_EN); in sunxi_rtc_setaie()
188 struct rtc_time *alrm_tm = &wkalrm->time; in sunxi_rtc_getalarm()
193 alrm = readl(chip->base + SUNXI_ALRM_DHMS); in sunxi_rtc_getalarm()
194 date = readl(chip->base + SUNXI_RTC_YMD); in sunxi_rtc_getalarm()
196 alrm_tm->tm_sec = SUNXI_ALRM_GET_SEC_VALUE(alrm); in sunxi_rtc_getalarm()
197 alrm_tm->tm_min = SUNXI_ALRM_GET_MIN_VALUE(alrm); in sunxi_rtc_getalarm()
198 alrm_tm->tm_hour = SUNXI_ALRM_GET_HOUR_VALUE(alrm); in sunxi_rtc_getalarm()
200 alrm_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date); in sunxi_rtc_getalarm()
201 alrm_tm->tm_mon = SUNXI_DATE_GET_MON_VALUE(date); in sunxi_rtc_getalarm()
202 alrm_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date, in sunxi_rtc_getalarm()
203 chip->data_year->mask); in sunxi_rtc_getalarm()
205 alrm_tm->tm_mon -= 1; in sunxi_rtc_getalarm()
208 * switch from (data_year->min)-relative offset to in sunxi_rtc_getalarm()
209 * a (1900)-relative one in sunxi_rtc_getalarm()
211 alrm_tm->tm_year += SUNXI_YEAR_OFF(chip->data_year); in sunxi_rtc_getalarm()
213 alrm_en = readl(chip->base + SUNXI_ALRM_IRQ_EN); in sunxi_rtc_getalarm()
215 wkalrm->enabled = 1; in sunxi_rtc_getalarm()
229 date = readl(chip->base + SUNXI_RTC_YMD); in sunxi_rtc_gettime()
230 time = readl(chip->base + SUNXI_RTC_HMS); in sunxi_rtc_gettime()
231 } while ((date != readl(chip->base + SUNXI_RTC_YMD)) || in sunxi_rtc_gettime()
232 (time != readl(chip->base + SUNXI_RTC_HMS))); in sunxi_rtc_gettime()
234 rtc_tm->tm_sec = SUNXI_TIME_GET_SEC_VALUE(time); in sunxi_rtc_gettime()
235 rtc_tm->tm_min = SUNXI_TIME_GET_MIN_VALUE(time); in sunxi_rtc_gettime()
236 rtc_tm->tm_hour = SUNXI_TIME_GET_HOUR_VALUE(time); in sunxi_rtc_gettime()
238 rtc_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date); in sunxi_rtc_gettime()
239 rtc_tm->tm_mon = SUNXI_DATE_GET_MON_VALUE(date); in sunxi_rtc_gettime()
240 rtc_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date, in sunxi_rtc_gettime()
241 chip->data_year->mask); in sunxi_rtc_gettime()
243 rtc_tm->tm_mon -= 1; in sunxi_rtc_gettime()
246 * switch from (data_year->min)-relative offset to in sunxi_rtc_gettime()
247 * a (1900)-relative one in sunxi_rtc_gettime()
249 rtc_tm->tm_year += SUNXI_YEAR_OFF(chip->data_year); in sunxi_rtc_gettime()
257 struct rtc_time *alrm_tm = &wkalrm->time; in sunxi_rtc_setalarm()
270 return -EINVAL; in sunxi_rtc_setalarm()
276 return -EINVAL; in sunxi_rtc_setalarm()
280 dev_err(dev, "Day must be in the range 0 - 255\n"); in sunxi_rtc_setalarm()
281 return -EINVAL; in sunxi_rtc_setalarm()
286 time_gap -= time_gap_day * SEC_IN_DAY; in sunxi_rtc_setalarm()
288 time_gap -= time_gap_hour * SEC_IN_HOUR; in sunxi_rtc_setalarm()
290 time_gap -= time_gap_min * SEC_IN_MIN; in sunxi_rtc_setalarm()
293 writel(0, chip->base + SUNXI_ALRM_DHMS); in sunxi_rtc_setalarm()
300 writel(alrm, chip->base + SUNXI_ALRM_DHMS); in sunxi_rtc_setalarm()
302 writel(0, chip->base + SUNXI_ALRM_IRQ_EN); in sunxi_rtc_setalarm()
303 writel(SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN, chip->base + SUNXI_ALRM_IRQ_EN); in sunxi_rtc_setalarm()
305 sunxi_rtc_setaie(wkalrm->enabled, chip); in sunxi_rtc_setalarm()
317 reg = readl(chip->base + offset); in sunxi_rtc_wait()
325 return -ETIMEDOUT; in sunxi_rtc_wait()
336 * the input rtc_tm->tm_year is the offset relative to 1900. We use in sunxi_rtc_settime()
341 year = rtc_tm->tm_year + 1900; in sunxi_rtc_settime()
342 if (year < chip->data_year->min || year > chip->data_year->max) { in sunxi_rtc_settime()
343 dev_err(dev, "rtc only supports year in range %u - %u\n", in sunxi_rtc_settime()
344 chip->data_year->min, chip->data_year->max); in sunxi_rtc_settime()
345 return -EINVAL; in sunxi_rtc_settime()
348 rtc_tm->tm_year -= SUNXI_YEAR_OFF(chip->data_year); in sunxi_rtc_settime()
349 rtc_tm->tm_mon += 1; in sunxi_rtc_settime()
351 date = SUNXI_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | in sunxi_rtc_settime()
352 SUNXI_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | in sunxi_rtc_settime()
353 SUNXI_DATE_SET_YEAR_VALUE(rtc_tm->tm_year, in sunxi_rtc_settime()
354 chip->data_year->mask); in sunxi_rtc_settime()
357 date |= SUNXI_LEAP_SET_VALUE(1, chip->data_year->leap_shift); in sunxi_rtc_settime()
359 time = SUNXI_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | in sunxi_rtc_settime()
360 SUNXI_TIME_SET_MIN_VALUE(rtc_tm->tm_min) | in sunxi_rtc_settime()
361 SUNXI_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour); in sunxi_rtc_settime()
363 writel(0, chip->base + SUNXI_RTC_HMS); in sunxi_rtc_settime()
364 writel(0, chip->base + SUNXI_RTC_YMD); in sunxi_rtc_settime()
366 writel(time, chip->base + SUNXI_RTC_HMS); in sunxi_rtc_settime()
369 * After writing the RTC HH-MM-SS register, the in sunxi_rtc_settime()
376 dev_err(dev, "Failed to set rtc time.\n"); in sunxi_rtc_settime()
377 return -1; in sunxi_rtc_settime()
380 writel(date, chip->base + SUNXI_RTC_YMD); in sunxi_rtc_settime()
383 * After writing the RTC YY-MM-DD register, the in sunxi_rtc_settime()
390 dev_err(dev, "Failed to set rtc time.\n"); in sunxi_rtc_settime()
391 return -1; in sunxi_rtc_settime()
416 { .compatible = "allwinner,sun4i-a10-rtc", .data = &data_year_param[0] },
417 { .compatible = "allwinner,sun7i-a20-rtc", .data = &data_year_param[1] },
427 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); in sunxi_rtc_probe()
429 return -ENOMEM; in sunxi_rtc_probe()
432 chip->dev = &pdev->dev; in sunxi_rtc_probe()
434 chip->rtc = devm_rtc_allocate_device(&pdev->dev); in sunxi_rtc_probe()
435 if (IS_ERR(chip->rtc)) in sunxi_rtc_probe()
436 return PTR_ERR(chip->rtc); in sunxi_rtc_probe()
438 chip->base = devm_platform_ioremap_resource(pdev, 0); in sunxi_rtc_probe()
439 if (IS_ERR(chip->base)) in sunxi_rtc_probe()
440 return PTR_ERR(chip->base); in sunxi_rtc_probe()
442 chip->irq = platform_get_irq(pdev, 0); in sunxi_rtc_probe()
443 if (chip->irq < 0) in sunxi_rtc_probe()
444 return chip->irq; in sunxi_rtc_probe()
445 ret = devm_request_irq(&pdev->dev, chip->irq, sunxi_rtc_alarmirq, in sunxi_rtc_probe()
446 0, dev_name(&pdev->dev), chip); in sunxi_rtc_probe()
448 dev_err(&pdev->dev, "Could not request IRQ\n"); in sunxi_rtc_probe()
452 chip->data_year = of_device_get_match_data(&pdev->dev); in sunxi_rtc_probe()
453 if (!chip->data_year) { in sunxi_rtc_probe()
454 dev_err(&pdev->dev, "Unable to setup RTC data\n"); in sunxi_rtc_probe()
455 return -ENODEV; in sunxi_rtc_probe()
459 writel(0, chip->base + SUNXI_ALRM_DHMS); in sunxi_rtc_probe()
462 writel(0, chip->base + SUNXI_ALRM_EN); in sunxi_rtc_probe()
465 writel(0, chip->base + SUNXI_ALRM_IRQ_EN); in sunxi_rtc_probe()
468 writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base + in sunxi_rtc_probe()
471 chip->rtc->ops = &sunxi_rtc_ops; in sunxi_rtc_probe()
473 return devm_rtc_register_device(chip->rtc); in sunxi_rtc_probe()
479 .name = "sunxi-rtc",
486 MODULE_DESCRIPTION("sunxi RTC driver");