Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * An RTC driver for Allwinner A10/A20
0004  *
0005  * Copyright (c) 2013, Carlo Caione <carlo.caione@gmail.com>
0006  */
0007 
0008 #include <linux/delay.h>
0009 #include <linux/err.h>
0010 #include <linux/fs.h>
0011 #include <linux/init.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/io.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 #include <linux/of_address.h>
0018 #include <linux/of_device.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/rtc.h>
0021 #include <linux/types.h>
0022 
0023 #define SUNXI_LOSC_CTRL             0x0000
0024 #define SUNXI_LOSC_CTRL_RTC_HMS_ACC     BIT(8)
0025 #define SUNXI_LOSC_CTRL_RTC_YMD_ACC     BIT(7)
0026 
0027 #define SUNXI_RTC_YMD               0x0004
0028 
0029 #define SUNXI_RTC_HMS               0x0008
0030 
0031 #define SUNXI_ALRM_DHMS             0x000c
0032 
0033 #define SUNXI_ALRM_EN               0x0014
0034 #define SUNXI_ALRM_EN_CNT_EN            BIT(8)
0035 
0036 #define SUNXI_ALRM_IRQ_EN           0x0018
0037 #define SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN        BIT(0)
0038 
0039 #define SUNXI_ALRM_IRQ_STA          0x001c
0040 #define SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND     BIT(0)
0041 
0042 #define SUNXI_MASK_DH               0x0000001f
0043 #define SUNXI_MASK_SM               0x0000003f
0044 #define SUNXI_MASK_M                0x0000000f
0045 #define SUNXI_MASK_LY               0x00000001
0046 #define SUNXI_MASK_D                0x00000ffe
0047 #define SUNXI_MASK_M                0x0000000f
0048 
0049 #define SUNXI_GET(x, mask, shift)       (((x) & ((mask) << (shift))) \
0050                             >> (shift))
0051 
0052 #define SUNXI_SET(x, mask, shift)       (((x) & (mask)) << (shift))
0053 
0054 /*
0055  * Get date values
0056  */
0057 #define SUNXI_DATE_GET_DAY_VALUE(x)     SUNXI_GET(x, SUNXI_MASK_DH, 0)
0058 #define SUNXI_DATE_GET_MON_VALUE(x)     SUNXI_GET(x, SUNXI_MASK_M, 8)
0059 #define SUNXI_DATE_GET_YEAR_VALUE(x, mask)  SUNXI_GET(x, mask, 16)
0060 
0061 /*
0062  * Get time values
0063  */
0064 #define SUNXI_TIME_GET_SEC_VALUE(x)     SUNXI_GET(x, SUNXI_MASK_SM, 0)
0065 #define SUNXI_TIME_GET_MIN_VALUE(x)     SUNXI_GET(x, SUNXI_MASK_SM, 8)
0066 #define SUNXI_TIME_GET_HOUR_VALUE(x)        SUNXI_GET(x, SUNXI_MASK_DH, 16)
0067 
0068 /*
0069  * Get alarm values
0070  */
0071 #define SUNXI_ALRM_GET_SEC_VALUE(x)     SUNXI_GET(x, SUNXI_MASK_SM, 0)
0072 #define SUNXI_ALRM_GET_MIN_VALUE(x)     SUNXI_GET(x, SUNXI_MASK_SM, 8)
0073 #define SUNXI_ALRM_GET_HOUR_VALUE(x)        SUNXI_GET(x, SUNXI_MASK_DH, 16)
0074 
0075 /*
0076  * Set date values
0077  */
0078 #define SUNXI_DATE_SET_DAY_VALUE(x)     SUNXI_DATE_GET_DAY_VALUE(x)
0079 #define SUNXI_DATE_SET_MON_VALUE(x)     SUNXI_SET(x, SUNXI_MASK_M, 8)
0080 #define SUNXI_DATE_SET_YEAR_VALUE(x, mask)  SUNXI_SET(x, mask, 16)
0081 #define SUNXI_LEAP_SET_VALUE(x, shift)      SUNXI_SET(x, SUNXI_MASK_LY, shift)
0082 
0083 /*
0084  * Set time values
0085  */
0086 #define SUNXI_TIME_SET_SEC_VALUE(x)     SUNXI_TIME_GET_SEC_VALUE(x)
0087 #define SUNXI_TIME_SET_MIN_VALUE(x)     SUNXI_SET(x, SUNXI_MASK_SM, 8)
0088 #define SUNXI_TIME_SET_HOUR_VALUE(x)        SUNXI_SET(x, SUNXI_MASK_DH, 16)
0089 
0090 /*
0091  * Set alarm values
0092  */
0093 #define SUNXI_ALRM_SET_SEC_VALUE(x)     SUNXI_ALRM_GET_SEC_VALUE(x)
0094 #define SUNXI_ALRM_SET_MIN_VALUE(x)     SUNXI_SET(x, SUNXI_MASK_SM, 8)
0095 #define SUNXI_ALRM_SET_HOUR_VALUE(x)        SUNXI_SET(x, SUNXI_MASK_DH, 16)
0096 #define SUNXI_ALRM_SET_DAY_VALUE(x)     SUNXI_SET(x, SUNXI_MASK_D, 21)
0097 
0098 /*
0099  * Time unit conversions
0100  */
0101 #define SEC_IN_MIN              60
0102 #define SEC_IN_HOUR             (60 * SEC_IN_MIN)
0103 #define SEC_IN_DAY              (24 * SEC_IN_HOUR)
0104 
0105 /*
0106  * The year parameter passed to the driver is usually an offset relative to
0107  * the year 1900. This macro is used to convert this offset to another one
0108  * relative to the minimum year allowed by the hardware.
0109  */
0110 #define SUNXI_YEAR_OFF(x)           ((x)->min - 1900)
0111 
0112 /*
0113  * min and max year are arbitrary set considering the limited range of the
0114  * hardware register field
0115  */
0116 struct sunxi_rtc_data_year {
0117     unsigned int min;       /* min year allowed */
0118     unsigned int max;       /* max year allowed */
0119     unsigned int mask;      /* mask for the year field */
0120     unsigned char leap_shift;   /* bit shift to get the leap year */
0121 };
0122 
0123 static const struct sunxi_rtc_data_year data_year_param[] = {
0124     [0] = {
0125         .min        = 2010,
0126         .max        = 2073,
0127         .mask       = 0x3f,
0128         .leap_shift = 22,
0129     },
0130     [1] = {
0131         .min        = 1970,
0132         .max        = 2225,
0133         .mask       = 0xff,
0134         .leap_shift = 24,
0135     },
0136 };
0137 
0138 struct sunxi_rtc_dev {
0139     struct rtc_device *rtc;
0140     struct device *dev;
0141     const struct sunxi_rtc_data_year *data_year;
0142     void __iomem *base;
0143     int irq;
0144 };
0145 
0146 static irqreturn_t sunxi_rtc_alarmirq(int irq, void *id)
0147 {
0148     struct sunxi_rtc_dev *chip = (struct sunxi_rtc_dev *) id;
0149     u32 val;
0150 
0151     val = readl(chip->base + SUNXI_ALRM_IRQ_STA);
0152 
0153     if (val & SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND) {
0154         val |= SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND;
0155         writel(val, chip->base + SUNXI_ALRM_IRQ_STA);
0156 
0157         rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF);
0158 
0159         return IRQ_HANDLED;
0160     }
0161 
0162     return IRQ_NONE;
0163 }
0164 
0165 static void sunxi_rtc_setaie(unsigned int to, struct sunxi_rtc_dev *chip)
0166 {
0167     u32 alrm_val = 0;
0168     u32 alrm_irq_val = 0;
0169 
0170     if (to) {
0171         alrm_val = readl(chip->base + SUNXI_ALRM_EN);
0172         alrm_val |= SUNXI_ALRM_EN_CNT_EN;
0173 
0174         alrm_irq_val = readl(chip->base + SUNXI_ALRM_IRQ_EN);
0175         alrm_irq_val |= SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN;
0176     } else {
0177         writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND,
0178                 chip->base + SUNXI_ALRM_IRQ_STA);
0179     }
0180 
0181     writel(alrm_val, chip->base + SUNXI_ALRM_EN);
0182     writel(alrm_irq_val, chip->base + SUNXI_ALRM_IRQ_EN);
0183 }
0184 
0185 static int sunxi_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
0186 {
0187     struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
0188     struct rtc_time *alrm_tm = &wkalrm->time;
0189     u32 alrm;
0190     u32 alrm_en;
0191     u32 date;
0192 
0193     alrm = readl(chip->base + SUNXI_ALRM_DHMS);
0194     date = readl(chip->base + SUNXI_RTC_YMD);
0195 
0196     alrm_tm->tm_sec = SUNXI_ALRM_GET_SEC_VALUE(alrm);
0197     alrm_tm->tm_min = SUNXI_ALRM_GET_MIN_VALUE(alrm);
0198     alrm_tm->tm_hour = SUNXI_ALRM_GET_HOUR_VALUE(alrm);
0199 
0200     alrm_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date);
0201     alrm_tm->tm_mon = SUNXI_DATE_GET_MON_VALUE(date);
0202     alrm_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date,
0203             chip->data_year->mask);
0204 
0205     alrm_tm->tm_mon -= 1;
0206 
0207     /*
0208      * switch from (data_year->min)-relative offset to
0209      * a (1900)-relative one
0210      */
0211     alrm_tm->tm_year += SUNXI_YEAR_OFF(chip->data_year);
0212 
0213     alrm_en = readl(chip->base + SUNXI_ALRM_IRQ_EN);
0214     if (alrm_en & SUNXI_ALRM_EN_CNT_EN)
0215         wkalrm->enabled = 1;
0216 
0217     return 0;
0218 }
0219 
0220 static int sunxi_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
0221 {
0222     struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
0223     u32 date, time;
0224 
0225     /*
0226      * read again in case it changes
0227      */
0228     do {
0229         date = readl(chip->base + SUNXI_RTC_YMD);
0230         time = readl(chip->base + SUNXI_RTC_HMS);
0231     } while ((date != readl(chip->base + SUNXI_RTC_YMD)) ||
0232          (time != readl(chip->base + SUNXI_RTC_HMS)));
0233 
0234     rtc_tm->tm_sec  = SUNXI_TIME_GET_SEC_VALUE(time);
0235     rtc_tm->tm_min  = SUNXI_TIME_GET_MIN_VALUE(time);
0236     rtc_tm->tm_hour = SUNXI_TIME_GET_HOUR_VALUE(time);
0237 
0238     rtc_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date);
0239     rtc_tm->tm_mon  = SUNXI_DATE_GET_MON_VALUE(date);
0240     rtc_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date,
0241                     chip->data_year->mask);
0242 
0243     rtc_tm->tm_mon  -= 1;
0244 
0245     /*
0246      * switch from (data_year->min)-relative offset to
0247      * a (1900)-relative one
0248      */
0249     rtc_tm->tm_year += SUNXI_YEAR_OFF(chip->data_year);
0250 
0251     return 0;
0252 }
0253 
0254 static int sunxi_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
0255 {
0256     struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
0257     struct rtc_time *alrm_tm = &wkalrm->time;
0258     struct rtc_time tm_now;
0259     u32 alrm;
0260     time64_t diff;
0261     unsigned long time_gap;
0262     unsigned long time_gap_day;
0263     unsigned long time_gap_hour;
0264     unsigned long time_gap_min;
0265     int ret;
0266 
0267     ret = sunxi_rtc_gettime(dev, &tm_now);
0268     if (ret < 0) {
0269         dev_err(dev, "Error in getting time\n");
0270         return -EINVAL;
0271     }
0272 
0273     diff = rtc_tm_sub(alrm_tm, &tm_now);
0274     if (diff <= 0) {
0275         dev_err(dev, "Date to set in the past\n");
0276         return -EINVAL;
0277     }
0278 
0279     if (diff > 255 * SEC_IN_DAY) {
0280         dev_err(dev, "Day must be in the range 0 - 255\n");
0281         return -EINVAL;
0282     }
0283 
0284     time_gap = diff;
0285     time_gap_day = time_gap / SEC_IN_DAY;
0286     time_gap -= time_gap_day * SEC_IN_DAY;
0287     time_gap_hour = time_gap / SEC_IN_HOUR;
0288     time_gap -= time_gap_hour * SEC_IN_HOUR;
0289     time_gap_min = time_gap / SEC_IN_MIN;
0290     time_gap -= time_gap_min * SEC_IN_MIN;
0291 
0292     sunxi_rtc_setaie(0, chip);
0293     writel(0, chip->base + SUNXI_ALRM_DHMS);
0294     usleep_range(100, 300);
0295 
0296     alrm = SUNXI_ALRM_SET_SEC_VALUE(time_gap) |
0297         SUNXI_ALRM_SET_MIN_VALUE(time_gap_min) |
0298         SUNXI_ALRM_SET_HOUR_VALUE(time_gap_hour) |
0299         SUNXI_ALRM_SET_DAY_VALUE(time_gap_day);
0300     writel(alrm, chip->base + SUNXI_ALRM_DHMS);
0301 
0302     writel(0, chip->base + SUNXI_ALRM_IRQ_EN);
0303     writel(SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN, chip->base + SUNXI_ALRM_IRQ_EN);
0304 
0305     sunxi_rtc_setaie(wkalrm->enabled, chip);
0306 
0307     return 0;
0308 }
0309 
0310 static int sunxi_rtc_wait(struct sunxi_rtc_dev *chip, int offset,
0311               unsigned int mask, unsigned int ms_timeout)
0312 {
0313     const unsigned long timeout = jiffies + msecs_to_jiffies(ms_timeout);
0314     u32 reg;
0315 
0316     do {
0317         reg = readl(chip->base + offset);
0318         reg &= mask;
0319 
0320         if (reg == mask)
0321             return 0;
0322 
0323     } while (time_before(jiffies, timeout));
0324 
0325     return -ETIMEDOUT;
0326 }
0327 
0328 static int sunxi_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
0329 {
0330     struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
0331     u32 date = 0;
0332     u32 time = 0;
0333     unsigned int year;
0334 
0335     /*
0336      * the input rtc_tm->tm_year is the offset relative to 1900. We use
0337      * the SUNXI_YEAR_OFF macro to rebase it with respect to the min year
0338      * allowed by the hardware
0339      */
0340 
0341     year = rtc_tm->tm_year + 1900;
0342     if (year < chip->data_year->min || year > chip->data_year->max) {
0343         dev_err(dev, "rtc only supports year in range %u - %u\n",
0344             chip->data_year->min, chip->data_year->max);
0345         return -EINVAL;
0346     }
0347 
0348     rtc_tm->tm_year -= SUNXI_YEAR_OFF(chip->data_year);
0349     rtc_tm->tm_mon += 1;
0350 
0351     date = SUNXI_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) |
0352         SUNXI_DATE_SET_MON_VALUE(rtc_tm->tm_mon)  |
0353         SUNXI_DATE_SET_YEAR_VALUE(rtc_tm->tm_year,
0354                 chip->data_year->mask);
0355 
0356     if (is_leap_year(year))
0357         date |= SUNXI_LEAP_SET_VALUE(1, chip->data_year->leap_shift);
0358 
0359     time = SUNXI_TIME_SET_SEC_VALUE(rtc_tm->tm_sec)  |
0360         SUNXI_TIME_SET_MIN_VALUE(rtc_tm->tm_min)  |
0361         SUNXI_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour);
0362 
0363     writel(0, chip->base + SUNXI_RTC_HMS);
0364     writel(0, chip->base + SUNXI_RTC_YMD);
0365 
0366     writel(time, chip->base + SUNXI_RTC_HMS);
0367 
0368     /*
0369      * After writing the RTC HH-MM-SS register, the
0370      * SUNXI_LOSC_CTRL_RTC_HMS_ACC bit is set and it will not
0371      * be cleared until the real writing operation is finished
0372      */
0373 
0374     if (sunxi_rtc_wait(chip, SUNXI_LOSC_CTRL,
0375                 SUNXI_LOSC_CTRL_RTC_HMS_ACC, 50)) {
0376         dev_err(dev, "Failed to set rtc time.\n");
0377         return -1;
0378     }
0379 
0380     writel(date, chip->base + SUNXI_RTC_YMD);
0381 
0382     /*
0383      * After writing the RTC YY-MM-DD register, the
0384      * SUNXI_LOSC_CTRL_RTC_YMD_ACC bit is set and it will not
0385      * be cleared until the real writing operation is finished
0386      */
0387 
0388     if (sunxi_rtc_wait(chip, SUNXI_LOSC_CTRL,
0389                 SUNXI_LOSC_CTRL_RTC_YMD_ACC, 50)) {
0390         dev_err(dev, "Failed to set rtc time.\n");
0391         return -1;
0392     }
0393 
0394     return 0;
0395 }
0396 
0397 static int sunxi_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
0398 {
0399     struct sunxi_rtc_dev *chip = dev_get_drvdata(dev);
0400 
0401     if (!enabled)
0402         sunxi_rtc_setaie(enabled, chip);
0403 
0404     return 0;
0405 }
0406 
0407 static const struct rtc_class_ops sunxi_rtc_ops = {
0408     .read_time      = sunxi_rtc_gettime,
0409     .set_time       = sunxi_rtc_settime,
0410     .read_alarm     = sunxi_rtc_getalarm,
0411     .set_alarm      = sunxi_rtc_setalarm,
0412     .alarm_irq_enable   = sunxi_rtc_alarm_irq_enable
0413 };
0414 
0415 static const struct of_device_id sunxi_rtc_dt_ids[] = {
0416     { .compatible = "allwinner,sun4i-a10-rtc", .data = &data_year_param[0] },
0417     { .compatible = "allwinner,sun7i-a20-rtc", .data = &data_year_param[1] },
0418     { /* sentinel */ },
0419 };
0420 MODULE_DEVICE_TABLE(of, sunxi_rtc_dt_ids);
0421 
0422 static int sunxi_rtc_probe(struct platform_device *pdev)
0423 {
0424     struct sunxi_rtc_dev *chip;
0425     int ret;
0426 
0427     chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
0428     if (!chip)
0429         return -ENOMEM;
0430 
0431     platform_set_drvdata(pdev, chip);
0432     chip->dev = &pdev->dev;
0433 
0434     chip->rtc = devm_rtc_allocate_device(&pdev->dev);
0435     if (IS_ERR(chip->rtc))
0436         return PTR_ERR(chip->rtc);
0437 
0438     chip->base = devm_platform_ioremap_resource(pdev, 0);
0439     if (IS_ERR(chip->base))
0440         return PTR_ERR(chip->base);
0441 
0442     chip->irq = platform_get_irq(pdev, 0);
0443     if (chip->irq < 0)
0444         return chip->irq;
0445     ret = devm_request_irq(&pdev->dev, chip->irq, sunxi_rtc_alarmirq,
0446             0, dev_name(&pdev->dev), chip);
0447     if (ret) {
0448         dev_err(&pdev->dev, "Could not request IRQ\n");
0449         return ret;
0450     }
0451 
0452     chip->data_year = of_device_get_match_data(&pdev->dev);
0453     if (!chip->data_year) {
0454         dev_err(&pdev->dev, "Unable to setup RTC data\n");
0455         return -ENODEV;
0456     }
0457 
0458     /* clear the alarm count value */
0459     writel(0, chip->base + SUNXI_ALRM_DHMS);
0460 
0461     /* disable alarm, not generate irq pending */
0462     writel(0, chip->base + SUNXI_ALRM_EN);
0463 
0464     /* disable alarm week/cnt irq, unset to cpu */
0465     writel(0, chip->base + SUNXI_ALRM_IRQ_EN);
0466 
0467     /* clear alarm week/cnt irq pending */
0468     writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base +
0469             SUNXI_ALRM_IRQ_STA);
0470 
0471     chip->rtc->ops = &sunxi_rtc_ops;
0472 
0473     return devm_rtc_register_device(chip->rtc);
0474 }
0475 
0476 static struct platform_driver sunxi_rtc_driver = {
0477     .probe      = sunxi_rtc_probe,
0478     .driver     = {
0479         .name       = "sunxi-rtc",
0480         .of_match_table = sunxi_rtc_dt_ids,
0481     },
0482 };
0483 
0484 module_platform_driver(sunxi_rtc_driver);
0485 
0486 MODULE_DESCRIPTION("sunxi RTC driver");
0487 MODULE_AUTHOR("Carlo Caione <carlo.caione@gmail.com>");
0488 MODULE_LICENSE("GPL");