Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * drivers/rtc/rtc-spear.c
0004  *
0005  * Copyright (C) 2010 ST Microelectronics
0006  * Rajeev Kumar<rajeev-dlh.kumar@st.com>
0007  */
0008 
0009 #include <linux/bcd.h>
0010 #include <linux/clk.h>
0011 #include <linux/delay.h>
0012 #include <linux/init.h>
0013 #include <linux/io.h>
0014 #include <linux/irq.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/rtc.h>
0019 #include <linux/slab.h>
0020 #include <linux/spinlock.h>
0021 
0022 /* RTC registers */
0023 #define TIME_REG        0x00
0024 #define DATE_REG        0x04
0025 #define ALARM_TIME_REG      0x08
0026 #define ALARM_DATE_REG      0x0C
0027 #define CTRL_REG        0x10
0028 #define STATUS_REG      0x14
0029 
0030 /* TIME_REG & ALARM_TIME_REG */
0031 #define SECONDS_UNITS       (0xf<<0)    /* seconds units position */
0032 #define SECONDS_TENS        (0x7<<4)    /* seconds tens position */
0033 #define MINUTES_UNITS       (0xf<<8)    /* minutes units position */
0034 #define MINUTES_TENS        (0x7<<12)   /* minutes tens position */
0035 #define HOURS_UNITS     (0xf<<16)   /* hours units position */
0036 #define HOURS_TENS      (0x3<<20)   /* hours tens position */
0037 
0038 /* DATE_REG & ALARM_DATE_REG */
0039 #define DAYS_UNITS      (0xf<<0)    /* days units position */
0040 #define DAYS_TENS       (0x3<<4)    /* days tens position */
0041 #define MONTHS_UNITS        (0xf<<8)    /* months units position */
0042 #define MONTHS_TENS     (0x1<<12)   /* months tens position */
0043 #define YEARS_UNITS     (0xf<<16)   /* years units position */
0044 #define YEARS_TENS      (0xf<<20)   /* years tens position */
0045 #define YEARS_HUNDREDS      (0xf<<24)   /* years hundereds position */
0046 #define YEARS_MILLENIUMS    (0xf<<28)   /* years millenium position */
0047 
0048 /* MASK SHIFT TIME_REG & ALARM_TIME_REG*/
0049 #define SECOND_SHIFT        0x00        /* seconds units */
0050 #define MINUTE_SHIFT        0x08        /* minutes units position */
0051 #define HOUR_SHIFT      0x10        /* hours units position */
0052 #define MDAY_SHIFT      0x00        /* Month day shift */
0053 #define MONTH_SHIFT     0x08        /* Month shift */
0054 #define YEAR_SHIFT      0x10        /* Year shift */
0055 
0056 #define SECOND_MASK     0x7F
0057 #define MIN_MASK        0x7F
0058 #define HOUR_MASK       0x3F
0059 #define DAY_MASK        0x3F
0060 #define MONTH_MASK      0x7F
0061 #define YEAR_MASK       0xFFFF
0062 
0063 /* date reg equal to time reg, for debug only */
0064 #define TIME_BYP        (1<<9)
0065 #define INT_ENABLE      (1<<31)     /* interrupt enable */
0066 
0067 /* STATUS_REG */
0068 #define CLK_UNCONNECTED     (1<<0)
0069 #define PEND_WR_TIME        (1<<2)
0070 #define PEND_WR_DATE        (1<<3)
0071 #define LOST_WR_TIME        (1<<4)
0072 #define LOST_WR_DATE        (1<<5)
0073 #define RTC_INT_MASK        (1<<31)
0074 #define STATUS_BUSY     (PEND_WR_TIME | PEND_WR_DATE)
0075 #define STATUS_FAIL     (LOST_WR_TIME | LOST_WR_DATE)
0076 
0077 struct spear_rtc_config {
0078     struct rtc_device *rtc;
0079     struct clk *clk;
0080     spinlock_t lock;
0081     void __iomem *ioaddr;
0082     unsigned int irq_wake;
0083 };
0084 
0085 static inline void spear_rtc_clear_interrupt(struct spear_rtc_config *config)
0086 {
0087     unsigned int val;
0088     unsigned long flags;
0089 
0090     spin_lock_irqsave(&config->lock, flags);
0091     val = readl(config->ioaddr + STATUS_REG);
0092     val |= RTC_INT_MASK;
0093     writel(val, config->ioaddr + STATUS_REG);
0094     spin_unlock_irqrestore(&config->lock, flags);
0095 }
0096 
0097 static inline void spear_rtc_enable_interrupt(struct spear_rtc_config *config)
0098 {
0099     unsigned int val;
0100 
0101     val = readl(config->ioaddr + CTRL_REG);
0102     if (!(val & INT_ENABLE)) {
0103         spear_rtc_clear_interrupt(config);
0104         val |= INT_ENABLE;
0105         writel(val, config->ioaddr + CTRL_REG);
0106     }
0107 }
0108 
0109 static inline void spear_rtc_disable_interrupt(struct spear_rtc_config *config)
0110 {
0111     unsigned int val;
0112 
0113     val = readl(config->ioaddr + CTRL_REG);
0114     if (val & INT_ENABLE) {
0115         val &= ~INT_ENABLE;
0116         writel(val, config->ioaddr + CTRL_REG);
0117     }
0118 }
0119 
0120 static inline int is_write_complete(struct spear_rtc_config *config)
0121 {
0122     int ret = 0;
0123     unsigned long flags;
0124 
0125     spin_lock_irqsave(&config->lock, flags);
0126     if ((readl(config->ioaddr + STATUS_REG)) & STATUS_FAIL)
0127         ret = -EIO;
0128     spin_unlock_irqrestore(&config->lock, flags);
0129 
0130     return ret;
0131 }
0132 
0133 static void rtc_wait_not_busy(struct spear_rtc_config *config)
0134 {
0135     int status, count = 0;
0136     unsigned long flags;
0137 
0138     /* Assuming BUSY may stay active for 80 msec) */
0139     for (count = 0; count < 80; count++) {
0140         spin_lock_irqsave(&config->lock, flags);
0141         status = readl(config->ioaddr + STATUS_REG);
0142         spin_unlock_irqrestore(&config->lock, flags);
0143         if ((status & STATUS_BUSY) == 0)
0144             break;
0145         /* check status busy, after each msec */
0146         msleep(1);
0147     }
0148 }
0149 
0150 static irqreturn_t spear_rtc_irq(int irq, void *dev_id)
0151 {
0152     struct spear_rtc_config *config = dev_id;
0153     unsigned long events = 0;
0154     unsigned int irq_data;
0155 
0156     spin_lock(&config->lock);
0157     irq_data = readl(config->ioaddr + STATUS_REG);
0158     spin_unlock(&config->lock);
0159 
0160     if ((irq_data & RTC_INT_MASK)) {
0161         spear_rtc_clear_interrupt(config);
0162         events = RTC_IRQF | RTC_AF;
0163         rtc_update_irq(config->rtc, 1, events);
0164         return IRQ_HANDLED;
0165     } else
0166         return IRQ_NONE;
0167 
0168 }
0169 
0170 static void tm2bcd(struct rtc_time *tm)
0171 {
0172     tm->tm_sec = bin2bcd(tm->tm_sec);
0173     tm->tm_min = bin2bcd(tm->tm_min);
0174     tm->tm_hour = bin2bcd(tm->tm_hour);
0175     tm->tm_mday = bin2bcd(tm->tm_mday);
0176     tm->tm_mon = bin2bcd(tm->tm_mon + 1);
0177     tm->tm_year = bin2bcd(tm->tm_year);
0178 }
0179 
0180 static void bcd2tm(struct rtc_time *tm)
0181 {
0182     tm->tm_sec = bcd2bin(tm->tm_sec);
0183     tm->tm_min = bcd2bin(tm->tm_min);
0184     tm->tm_hour = bcd2bin(tm->tm_hour);
0185     tm->tm_mday = bcd2bin(tm->tm_mday);
0186     tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
0187     /* epoch == 1900 */
0188     tm->tm_year = bcd2bin(tm->tm_year);
0189 }
0190 
0191 /*
0192  * spear_rtc_read_time - set the time
0193  * @dev: rtc device in use
0194  * @tm: holds date and time
0195  *
0196  * This function read time and date. On success it will return 0
0197  * otherwise -ve error is returned.
0198  */
0199 static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm)
0200 {
0201     struct spear_rtc_config *config = dev_get_drvdata(dev);
0202     unsigned int time, date;
0203 
0204     /* we don't report wday/yday/isdst ... */
0205     rtc_wait_not_busy(config);
0206 
0207     do {
0208         time = readl(config->ioaddr + TIME_REG);
0209         date = readl(config->ioaddr + DATE_REG);
0210     } while (time == readl(config->ioaddr + TIME_REG));
0211     tm->tm_sec = (time >> SECOND_SHIFT) & SECOND_MASK;
0212     tm->tm_min = (time >> MINUTE_SHIFT) & MIN_MASK;
0213     tm->tm_hour = (time >> HOUR_SHIFT) & HOUR_MASK;
0214     tm->tm_mday = (date >> MDAY_SHIFT) & DAY_MASK;
0215     tm->tm_mon = (date >> MONTH_SHIFT) & MONTH_MASK;
0216     tm->tm_year = (date >> YEAR_SHIFT) & YEAR_MASK;
0217 
0218     bcd2tm(tm);
0219     return 0;
0220 }
0221 
0222 /*
0223  * spear_rtc_set_time - set the time
0224  * @dev: rtc device in use
0225  * @tm: holds date and time
0226  *
0227  * This function set time and date. On success it will return 0
0228  * otherwise -ve error is returned.
0229  */
0230 static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm)
0231 {
0232     struct spear_rtc_config *config = dev_get_drvdata(dev);
0233     unsigned int time, date;
0234 
0235     tm2bcd(tm);
0236 
0237     rtc_wait_not_busy(config);
0238     time = (tm->tm_sec << SECOND_SHIFT) | (tm->tm_min << MINUTE_SHIFT) |
0239         (tm->tm_hour << HOUR_SHIFT);
0240     date = (tm->tm_mday << MDAY_SHIFT) | (tm->tm_mon << MONTH_SHIFT) |
0241         (tm->tm_year << YEAR_SHIFT);
0242     writel(time, config->ioaddr + TIME_REG);
0243     writel(date, config->ioaddr + DATE_REG);
0244 
0245     return is_write_complete(config);
0246 }
0247 
0248 /*
0249  * spear_rtc_read_alarm - read the alarm time
0250  * @dev: rtc device in use
0251  * @alm: holds alarm date and time
0252  *
0253  * This function read alarm time and date. On success it will return 0
0254  * otherwise -ve error is returned.
0255  */
0256 static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
0257 {
0258     struct spear_rtc_config *config = dev_get_drvdata(dev);
0259     unsigned int time, date;
0260 
0261     rtc_wait_not_busy(config);
0262 
0263     time = readl(config->ioaddr + ALARM_TIME_REG);
0264     date = readl(config->ioaddr + ALARM_DATE_REG);
0265     alm->time.tm_sec = (time >> SECOND_SHIFT) & SECOND_MASK;
0266     alm->time.tm_min = (time >> MINUTE_SHIFT) & MIN_MASK;
0267     alm->time.tm_hour = (time >> HOUR_SHIFT) & HOUR_MASK;
0268     alm->time.tm_mday = (date >> MDAY_SHIFT) & DAY_MASK;
0269     alm->time.tm_mon = (date >> MONTH_SHIFT) & MONTH_MASK;
0270     alm->time.tm_year = (date >> YEAR_SHIFT) & YEAR_MASK;
0271 
0272     bcd2tm(&alm->time);
0273     alm->enabled = readl(config->ioaddr + CTRL_REG) & INT_ENABLE;
0274 
0275     return 0;
0276 }
0277 
0278 /*
0279  * spear_rtc_set_alarm - set the alarm time
0280  * @dev: rtc device in use
0281  * @alm: holds alarm date and time
0282  *
0283  * This function set alarm time and date. On success it will return 0
0284  * otherwise -ve error is returned.
0285  */
0286 static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
0287 {
0288     struct spear_rtc_config *config = dev_get_drvdata(dev);
0289     unsigned int time, date;
0290     int err;
0291 
0292     tm2bcd(&alm->time);
0293 
0294     rtc_wait_not_busy(config);
0295 
0296     time = (alm->time.tm_sec << SECOND_SHIFT) | (alm->time.tm_min <<
0297             MINUTE_SHIFT) | (alm->time.tm_hour << HOUR_SHIFT);
0298     date = (alm->time.tm_mday << MDAY_SHIFT) | (alm->time.tm_mon <<
0299             MONTH_SHIFT) | (alm->time.tm_year << YEAR_SHIFT);
0300 
0301     writel(time, config->ioaddr + ALARM_TIME_REG);
0302     writel(date, config->ioaddr + ALARM_DATE_REG);
0303     err = is_write_complete(config);
0304     if (err < 0)
0305         return err;
0306 
0307     if (alm->enabled)
0308         spear_rtc_enable_interrupt(config);
0309     else
0310         spear_rtc_disable_interrupt(config);
0311 
0312     return 0;
0313 }
0314 
0315 static int spear_alarm_irq_enable(struct device *dev, unsigned int enabled)
0316 {
0317     struct spear_rtc_config *config = dev_get_drvdata(dev);
0318     int ret = 0;
0319 
0320     spear_rtc_clear_interrupt(config);
0321 
0322     switch (enabled) {
0323     case 0:
0324         /* alarm off */
0325         spear_rtc_disable_interrupt(config);
0326         break;
0327     case 1:
0328         /* alarm on */
0329         spear_rtc_enable_interrupt(config);
0330         break;
0331     default:
0332         ret = -EINVAL;
0333         break;
0334     }
0335 
0336     return ret;
0337 }
0338 
0339 static const struct rtc_class_ops spear_rtc_ops = {
0340     .read_time = spear_rtc_read_time,
0341     .set_time = spear_rtc_set_time,
0342     .read_alarm = spear_rtc_read_alarm,
0343     .set_alarm = spear_rtc_set_alarm,
0344     .alarm_irq_enable = spear_alarm_irq_enable,
0345 };
0346 
0347 static int spear_rtc_probe(struct platform_device *pdev)
0348 {
0349     struct spear_rtc_config *config;
0350     int status = 0;
0351     int irq;
0352 
0353     config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
0354     if (!config)
0355         return -ENOMEM;
0356 
0357     config->rtc = devm_rtc_allocate_device(&pdev->dev);
0358     if (IS_ERR(config->rtc))
0359         return PTR_ERR(config->rtc);
0360 
0361     /* alarm irqs */
0362     irq = platform_get_irq(pdev, 0);
0363     if (irq < 0)
0364         return irq;
0365 
0366     status = devm_request_irq(&pdev->dev, irq, spear_rtc_irq, 0, pdev->name,
0367             config);
0368     if (status) {
0369         dev_err(&pdev->dev, "Alarm interrupt IRQ%d already claimed\n",
0370                 irq);
0371         return status;
0372     }
0373 
0374     config->ioaddr = devm_platform_ioremap_resource(pdev, 0);
0375     if (IS_ERR(config->ioaddr))
0376         return PTR_ERR(config->ioaddr);
0377 
0378     config->clk = devm_clk_get(&pdev->dev, NULL);
0379     if (IS_ERR(config->clk))
0380         return PTR_ERR(config->clk);
0381 
0382     status = clk_prepare_enable(config->clk);
0383     if (status < 0)
0384         return status;
0385 
0386     spin_lock_init(&config->lock);
0387     platform_set_drvdata(pdev, config);
0388 
0389     config->rtc->ops = &spear_rtc_ops;
0390     config->rtc->range_min = RTC_TIMESTAMP_BEGIN_0000;
0391     config->rtc->range_max = RTC_TIMESTAMP_END_9999;
0392 
0393     status = devm_rtc_register_device(config->rtc);
0394     if (status)
0395         goto err_disable_clock;
0396 
0397     if (!device_can_wakeup(&pdev->dev))
0398         device_init_wakeup(&pdev->dev, 1);
0399 
0400     return 0;
0401 
0402 err_disable_clock:
0403     clk_disable_unprepare(config->clk);
0404 
0405     return status;
0406 }
0407 
0408 static int spear_rtc_remove(struct platform_device *pdev)
0409 {
0410     struct spear_rtc_config *config = platform_get_drvdata(pdev);
0411 
0412     spear_rtc_disable_interrupt(config);
0413     clk_disable_unprepare(config->clk);
0414     device_init_wakeup(&pdev->dev, 0);
0415 
0416     return 0;
0417 }
0418 
0419 #ifdef CONFIG_PM_SLEEP
0420 static int spear_rtc_suspend(struct device *dev)
0421 {
0422     struct platform_device *pdev = to_platform_device(dev);
0423     struct spear_rtc_config *config = platform_get_drvdata(pdev);
0424     int irq;
0425 
0426     irq = platform_get_irq(pdev, 0);
0427     if (device_may_wakeup(&pdev->dev)) {
0428         if (!enable_irq_wake(irq))
0429             config->irq_wake = 1;
0430     } else {
0431         spear_rtc_disable_interrupt(config);
0432         clk_disable(config->clk);
0433     }
0434 
0435     return 0;
0436 }
0437 
0438 static int spear_rtc_resume(struct device *dev)
0439 {
0440     struct platform_device *pdev = to_platform_device(dev);
0441     struct spear_rtc_config *config = platform_get_drvdata(pdev);
0442     int irq;
0443 
0444     irq = platform_get_irq(pdev, 0);
0445 
0446     if (device_may_wakeup(&pdev->dev)) {
0447         if (config->irq_wake) {
0448             disable_irq_wake(irq);
0449             config->irq_wake = 0;
0450         }
0451     } else {
0452         clk_enable(config->clk);
0453         spear_rtc_enable_interrupt(config);
0454     }
0455 
0456     return 0;
0457 }
0458 #endif
0459 
0460 static SIMPLE_DEV_PM_OPS(spear_rtc_pm_ops, spear_rtc_suspend, spear_rtc_resume);
0461 
0462 static void spear_rtc_shutdown(struct platform_device *pdev)
0463 {
0464     struct spear_rtc_config *config = platform_get_drvdata(pdev);
0465 
0466     spear_rtc_disable_interrupt(config);
0467     clk_disable(config->clk);
0468 }
0469 
0470 #ifdef CONFIG_OF
0471 static const struct of_device_id spear_rtc_id_table[] = {
0472     { .compatible = "st,spear600-rtc" },
0473     {}
0474 };
0475 MODULE_DEVICE_TABLE(of, spear_rtc_id_table);
0476 #endif
0477 
0478 static struct platform_driver spear_rtc_driver = {
0479     .probe = spear_rtc_probe,
0480     .remove = spear_rtc_remove,
0481     .shutdown = spear_rtc_shutdown,
0482     .driver = {
0483         .name = "rtc-spear",
0484         .pm = &spear_rtc_pm_ops,
0485         .of_match_table = of_match_ptr(spear_rtc_id_table),
0486     },
0487 };
0488 
0489 module_platform_driver(spear_rtc_driver);
0490 
0491 MODULE_ALIAS("platform:rtc-spear");
0492 MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
0493 MODULE_DESCRIPTION("ST SPEAr Realtime Clock Driver (RTC)");
0494 MODULE_LICENSE("GPL");