Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2019 MediaTek Inc.
0004  * Author: Ran Bi <ran.bi@mediatek.com>
0005  */
0006 
0007 #include <linux/delay.h>
0008 #include <linux/init.h>
0009 #include <linux/io.h>
0010 #include <linux/irqdomain.h>
0011 #include <linux/module.h>
0012 #include <linux/of_address.h>
0013 #include <linux/of_irq.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/rtc.h>
0016 
0017 #define MT2712_BBPU     0x0000
0018 #define MT2712_BBPU_CLRPKY  BIT(4)
0019 #define MT2712_BBPU_RELOAD  BIT(5)
0020 #define MT2712_BBPU_CBUSY   BIT(6)
0021 #define MT2712_BBPU_KEY     (0x43 << 8)
0022 
0023 #define MT2712_IRQ_STA      0x0004
0024 #define MT2712_IRQ_STA_AL   BIT(0)
0025 #define MT2712_IRQ_STA_TC   BIT(1)
0026 
0027 #define MT2712_IRQ_EN       0x0008
0028 #define MT2712_IRQ_EN_AL    BIT(0)
0029 #define MT2712_IRQ_EN_TC    BIT(1)
0030 #define MT2712_IRQ_EN_ONESHOT   BIT(2)
0031 
0032 #define MT2712_CII_EN       0x000c
0033 
0034 #define MT2712_AL_MASK      0x0010
0035 #define MT2712_AL_MASK_DOW  BIT(4)
0036 
0037 #define MT2712_TC_SEC       0x0014
0038 #define MT2712_TC_MIN       0x0018
0039 #define MT2712_TC_HOU       0x001c
0040 #define MT2712_TC_DOM       0x0020
0041 #define MT2712_TC_DOW       0x0024
0042 #define MT2712_TC_MTH       0x0028
0043 #define MT2712_TC_YEA       0x002c
0044 
0045 #define MT2712_AL_SEC       0x0030
0046 #define MT2712_AL_MIN       0x0034
0047 #define MT2712_AL_HOU       0x0038
0048 #define MT2712_AL_DOM       0x003c
0049 #define MT2712_AL_DOW       0x0040
0050 #define MT2712_AL_MTH       0x0044
0051 #define MT2712_AL_YEA       0x0048
0052 
0053 #define MT2712_SEC_MASK     0x003f
0054 #define MT2712_MIN_MASK     0x003f
0055 #define MT2712_HOU_MASK     0x001f
0056 #define MT2712_DOM_MASK     0x001f
0057 #define MT2712_DOW_MASK     0x0007
0058 #define MT2712_MTH_MASK     0x000f
0059 #define MT2712_YEA_MASK     0x007f
0060 
0061 #define MT2712_POWERKEY1    0x004c
0062 #define MT2712_POWERKEY2    0x0050
0063 #define MT2712_POWERKEY1_KEY    0xa357
0064 #define MT2712_POWERKEY2_KEY    0x67d2
0065 
0066 #define MT2712_CON0     0x005c
0067 #define MT2712_CON1     0x0060
0068 
0069 #define MT2712_PROT     0x0070
0070 #define MT2712_PROT_UNLOCK1 0x9136
0071 #define MT2712_PROT_UNLOCK2 0x586a
0072 
0073 #define MT2712_WRTGR        0x0078
0074 
0075 #define MT2712_RTC_TIMESTAMP_END_2127   4985971199LL
0076 
0077 struct mt2712_rtc {
0078     struct rtc_device   *rtc;
0079     void __iomem        *base;
0080     int         irq;
0081     u8          irq_wake_enabled;
0082     u8          powerlost;
0083 };
0084 
0085 static inline u32 mt2712_readl(struct mt2712_rtc *mt2712_rtc, u32 reg)
0086 {
0087     return readl(mt2712_rtc->base + reg);
0088 }
0089 
0090 static inline void mt2712_writel(struct mt2712_rtc *mt2712_rtc,
0091                  u32 reg, u32 val)
0092 {
0093     writel(val, mt2712_rtc->base + reg);
0094 }
0095 
0096 static void mt2712_rtc_write_trigger(struct mt2712_rtc *mt2712_rtc)
0097 {
0098     unsigned long timeout = jiffies + HZ / 10;
0099 
0100     mt2712_writel(mt2712_rtc, MT2712_WRTGR, 1);
0101     while (1) {
0102         if (!(mt2712_readl(mt2712_rtc, MT2712_BBPU)
0103                     & MT2712_BBPU_CBUSY))
0104             break;
0105 
0106         if (time_after(jiffies, timeout)) {
0107             dev_err(&mt2712_rtc->rtc->dev,
0108                 "%s time out!\n", __func__);
0109             break;
0110         }
0111         cpu_relax();
0112     }
0113 }
0114 
0115 static void mt2712_rtc_writeif_unlock(struct mt2712_rtc *mt2712_rtc)
0116 {
0117     mt2712_writel(mt2712_rtc, MT2712_PROT, MT2712_PROT_UNLOCK1);
0118     mt2712_rtc_write_trigger(mt2712_rtc);
0119     mt2712_writel(mt2712_rtc, MT2712_PROT, MT2712_PROT_UNLOCK2);
0120     mt2712_rtc_write_trigger(mt2712_rtc);
0121 }
0122 
0123 static irqreturn_t rtc_irq_handler_thread(int irq, void *data)
0124 {
0125     struct mt2712_rtc *mt2712_rtc = data;
0126     u16 irqsta;
0127 
0128     /* Clear interrupt */
0129     irqsta = mt2712_readl(mt2712_rtc, MT2712_IRQ_STA);
0130     if (irqsta & MT2712_IRQ_STA_AL) {
0131         rtc_update_irq(mt2712_rtc->rtc, 1, RTC_IRQF | RTC_AF);
0132         return IRQ_HANDLED;
0133     }
0134 
0135     return IRQ_NONE;
0136 }
0137 
0138 static void __mt2712_rtc_read_time(struct mt2712_rtc *mt2712_rtc,
0139                    struct rtc_time *tm, int *sec)
0140 {
0141     tm->tm_sec  = mt2712_readl(mt2712_rtc, MT2712_TC_SEC)
0142             & MT2712_SEC_MASK;
0143     tm->tm_min  = mt2712_readl(mt2712_rtc, MT2712_TC_MIN)
0144             & MT2712_MIN_MASK;
0145     tm->tm_hour = mt2712_readl(mt2712_rtc, MT2712_TC_HOU)
0146             & MT2712_HOU_MASK;
0147     tm->tm_mday = mt2712_readl(mt2712_rtc, MT2712_TC_DOM)
0148             & MT2712_DOM_MASK;
0149     tm->tm_mon  = (mt2712_readl(mt2712_rtc, MT2712_TC_MTH) - 1)
0150             & MT2712_MTH_MASK;
0151     tm->tm_year = (mt2712_readl(mt2712_rtc, MT2712_TC_YEA) + 100)
0152             & MT2712_YEA_MASK;
0153 
0154     *sec = mt2712_readl(mt2712_rtc, MT2712_TC_SEC) & MT2712_SEC_MASK;
0155 }
0156 
0157 static int mt2712_rtc_read_time(struct device *dev, struct rtc_time *tm)
0158 {
0159     struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
0160     int sec;
0161 
0162     if (mt2712_rtc->powerlost)
0163         return -EINVAL;
0164 
0165     do {
0166         __mt2712_rtc_read_time(mt2712_rtc, tm, &sec);
0167     } while (sec < tm->tm_sec); /* SEC has carried */
0168 
0169     return 0;
0170 }
0171 
0172 static int mt2712_rtc_set_time(struct device *dev, struct rtc_time *tm)
0173 {
0174     struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
0175 
0176     mt2712_writel(mt2712_rtc, MT2712_TC_SEC, tm->tm_sec  & MT2712_SEC_MASK);
0177     mt2712_writel(mt2712_rtc, MT2712_TC_MIN, tm->tm_min  & MT2712_MIN_MASK);
0178     mt2712_writel(mt2712_rtc, MT2712_TC_HOU, tm->tm_hour & MT2712_HOU_MASK);
0179     mt2712_writel(mt2712_rtc, MT2712_TC_DOM, tm->tm_mday & MT2712_DOM_MASK);
0180     mt2712_writel(mt2712_rtc, MT2712_TC_MTH,
0181               (tm->tm_mon + 1) & MT2712_MTH_MASK);
0182     mt2712_writel(mt2712_rtc, MT2712_TC_YEA,
0183               (tm->tm_year - 100) & MT2712_YEA_MASK);
0184 
0185     mt2712_rtc_write_trigger(mt2712_rtc);
0186 
0187     if (mt2712_rtc->powerlost)
0188         mt2712_rtc->powerlost = false;
0189 
0190     return 0;
0191 }
0192 
0193 static int mt2712_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
0194 {
0195     struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
0196     struct rtc_time *tm = &alm->time;
0197     u16 irqen;
0198 
0199     irqen = mt2712_readl(mt2712_rtc, MT2712_IRQ_EN);
0200     alm->enabled = !!(irqen & MT2712_IRQ_EN_AL);
0201 
0202     tm->tm_sec  = mt2712_readl(mt2712_rtc, MT2712_AL_SEC) & MT2712_SEC_MASK;
0203     tm->tm_min  = mt2712_readl(mt2712_rtc, MT2712_AL_MIN) & MT2712_MIN_MASK;
0204     tm->tm_hour = mt2712_readl(mt2712_rtc, MT2712_AL_HOU) & MT2712_HOU_MASK;
0205     tm->tm_mday = mt2712_readl(mt2712_rtc, MT2712_AL_DOM) & MT2712_DOM_MASK;
0206     tm->tm_mon  = (mt2712_readl(mt2712_rtc, MT2712_AL_MTH) - 1)
0207               & MT2712_MTH_MASK;
0208     tm->tm_year = (mt2712_readl(mt2712_rtc, MT2712_AL_YEA) + 100)
0209               & MT2712_YEA_MASK;
0210 
0211     return 0;
0212 }
0213 
0214 static int mt2712_rtc_alarm_irq_enable(struct device *dev,
0215                        unsigned int enabled)
0216 {
0217     struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
0218     u16 irqen;
0219 
0220     irqen = mt2712_readl(mt2712_rtc, MT2712_IRQ_EN);
0221     if (enabled)
0222         irqen |= MT2712_IRQ_EN_AL;
0223     else
0224         irqen &= ~MT2712_IRQ_EN_AL;
0225     mt2712_writel(mt2712_rtc, MT2712_IRQ_EN, irqen);
0226     mt2712_rtc_write_trigger(mt2712_rtc);
0227 
0228     return 0;
0229 }
0230 
0231 static int mt2712_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
0232 {
0233     struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
0234     struct rtc_time *tm = &alm->time;
0235 
0236     dev_dbg(&mt2712_rtc->rtc->dev, "set al time: %ptR, alm en: %d\n",
0237         tm, alm->enabled);
0238 
0239     mt2712_writel(mt2712_rtc, MT2712_AL_SEC,
0240               (mt2712_readl(mt2712_rtc, MT2712_AL_SEC)
0241                & ~(MT2712_SEC_MASK)) | (tm->tm_sec  & MT2712_SEC_MASK));
0242     mt2712_writel(mt2712_rtc, MT2712_AL_MIN,
0243               (mt2712_readl(mt2712_rtc, MT2712_AL_MIN)
0244                & ~(MT2712_MIN_MASK)) | (tm->tm_min  & MT2712_MIN_MASK));
0245     mt2712_writel(mt2712_rtc, MT2712_AL_HOU,
0246               (mt2712_readl(mt2712_rtc, MT2712_AL_HOU)
0247                & ~(MT2712_HOU_MASK)) | (tm->tm_hour & MT2712_HOU_MASK));
0248     mt2712_writel(mt2712_rtc, MT2712_AL_DOM,
0249               (mt2712_readl(mt2712_rtc, MT2712_AL_DOM)
0250                & ~(MT2712_DOM_MASK)) | (tm->tm_mday & MT2712_DOM_MASK));
0251     mt2712_writel(mt2712_rtc, MT2712_AL_MTH,
0252               (mt2712_readl(mt2712_rtc, MT2712_AL_MTH)
0253                & ~(MT2712_MTH_MASK))
0254               | ((tm->tm_mon + 1) & MT2712_MTH_MASK));
0255     mt2712_writel(mt2712_rtc, MT2712_AL_YEA,
0256               (mt2712_readl(mt2712_rtc, MT2712_AL_YEA)
0257                & ~(MT2712_YEA_MASK))
0258               | ((tm->tm_year - 100) & MT2712_YEA_MASK));
0259 
0260     /* mask day of week */
0261     mt2712_writel(mt2712_rtc, MT2712_AL_MASK, MT2712_AL_MASK_DOW);
0262     mt2712_rtc_write_trigger(mt2712_rtc);
0263 
0264     mt2712_rtc_alarm_irq_enable(dev, alm->enabled);
0265 
0266     return 0;
0267 }
0268 
0269 /* Init RTC register */
0270 static void mt2712_rtc_hw_init(struct mt2712_rtc *mt2712_rtc)
0271 {
0272     u32 p1, p2;
0273 
0274     mt2712_writel(mt2712_rtc, MT2712_BBPU,
0275               MT2712_BBPU_KEY | MT2712_BBPU_RELOAD);
0276 
0277     mt2712_writel(mt2712_rtc, MT2712_CII_EN, 0);
0278     mt2712_writel(mt2712_rtc, MT2712_AL_MASK, 0);
0279     /* necessary before set MT2712_POWERKEY */
0280     mt2712_writel(mt2712_rtc, MT2712_CON0, 0x4848);
0281     mt2712_writel(mt2712_rtc, MT2712_CON1, 0x0048);
0282 
0283     mt2712_rtc_write_trigger(mt2712_rtc);
0284 
0285     p1 = mt2712_readl(mt2712_rtc, MT2712_POWERKEY1);
0286     p2 = mt2712_readl(mt2712_rtc, MT2712_POWERKEY2);
0287     if (p1 != MT2712_POWERKEY1_KEY || p2 != MT2712_POWERKEY2_KEY) {
0288         mt2712_rtc->powerlost = true;
0289         dev_dbg(&mt2712_rtc->rtc->dev,
0290             "powerkey not set (lost power)\n");
0291     } else {
0292         mt2712_rtc->powerlost = false;
0293     }
0294 
0295     /* RTC need POWERKEY1/2 match, then goto normal work mode */
0296     mt2712_writel(mt2712_rtc, MT2712_POWERKEY1, MT2712_POWERKEY1_KEY);
0297     mt2712_writel(mt2712_rtc, MT2712_POWERKEY2, MT2712_POWERKEY2_KEY);
0298     mt2712_rtc_write_trigger(mt2712_rtc);
0299 
0300     mt2712_rtc_writeif_unlock(mt2712_rtc);
0301 }
0302 
0303 static const struct rtc_class_ops mt2712_rtc_ops = {
0304     .read_time  = mt2712_rtc_read_time,
0305     .set_time   = mt2712_rtc_set_time,
0306     .read_alarm = mt2712_rtc_read_alarm,
0307     .set_alarm  = mt2712_rtc_set_alarm,
0308     .alarm_irq_enable = mt2712_rtc_alarm_irq_enable,
0309 };
0310 
0311 static int mt2712_rtc_probe(struct platform_device *pdev)
0312 {
0313     struct mt2712_rtc *mt2712_rtc;
0314     int ret;
0315 
0316     mt2712_rtc = devm_kzalloc(&pdev->dev,
0317                   sizeof(struct mt2712_rtc), GFP_KERNEL);
0318     if (!mt2712_rtc)
0319         return -ENOMEM;
0320 
0321     mt2712_rtc->base = devm_platform_ioremap_resource(pdev, 0);
0322     if (IS_ERR(mt2712_rtc->base))
0323         return PTR_ERR(mt2712_rtc->base);
0324 
0325     /* rtc hw init */
0326     mt2712_rtc_hw_init(mt2712_rtc);
0327 
0328     mt2712_rtc->irq = platform_get_irq(pdev, 0);
0329     if (mt2712_rtc->irq < 0)
0330         return mt2712_rtc->irq;
0331 
0332     platform_set_drvdata(pdev, mt2712_rtc);
0333 
0334     mt2712_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
0335     if (IS_ERR(mt2712_rtc->rtc))
0336         return PTR_ERR(mt2712_rtc->rtc);
0337 
0338     ret = devm_request_threaded_irq(&pdev->dev, mt2712_rtc->irq, NULL,
0339                     rtc_irq_handler_thread,
0340                     IRQF_ONESHOT | IRQF_TRIGGER_LOW,
0341                     dev_name(&mt2712_rtc->rtc->dev),
0342                     mt2712_rtc);
0343     if (ret) {
0344         dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
0345             mt2712_rtc->irq, ret);
0346         return ret;
0347     }
0348 
0349     device_init_wakeup(&pdev->dev, true);
0350 
0351     mt2712_rtc->rtc->ops = &mt2712_rtc_ops;
0352     mt2712_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
0353     mt2712_rtc->rtc->range_max = MT2712_RTC_TIMESTAMP_END_2127;
0354 
0355     return devm_rtc_register_device(mt2712_rtc->rtc);
0356 }
0357 
0358 #ifdef CONFIG_PM_SLEEP
0359 static int mt2712_rtc_suspend(struct device *dev)
0360 {
0361     int wake_status = 0;
0362     struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
0363 
0364     if (device_may_wakeup(dev)) {
0365         wake_status = enable_irq_wake(mt2712_rtc->irq);
0366         if (!wake_status)
0367             mt2712_rtc->irq_wake_enabled = true;
0368     }
0369 
0370     return 0;
0371 }
0372 
0373 static int mt2712_rtc_resume(struct device *dev)
0374 {
0375     int wake_status = 0;
0376     struct mt2712_rtc *mt2712_rtc = dev_get_drvdata(dev);
0377 
0378     if (device_may_wakeup(dev) && mt2712_rtc->irq_wake_enabled) {
0379         wake_status = disable_irq_wake(mt2712_rtc->irq);
0380         if (!wake_status)
0381             mt2712_rtc->irq_wake_enabled = false;
0382     }
0383 
0384     return 0;
0385 }
0386 
0387 static SIMPLE_DEV_PM_OPS(mt2712_pm_ops, mt2712_rtc_suspend,
0388              mt2712_rtc_resume);
0389 #endif
0390 
0391 static const struct of_device_id mt2712_rtc_of_match[] = {
0392     { .compatible = "mediatek,mt2712-rtc", },
0393     { },
0394 };
0395 
0396 MODULE_DEVICE_TABLE(of, mt2712_rtc_of_match);
0397 
0398 static struct platform_driver mt2712_rtc_driver = {
0399     .driver = {
0400         .name = "mt2712-rtc",
0401         .of_match_table = mt2712_rtc_of_match,
0402 #ifdef CONFIG_PM_SLEEP
0403         .pm = &mt2712_pm_ops,
0404 #endif
0405     },
0406     .probe  = mt2712_rtc_probe,
0407 };
0408 
0409 module_platform_driver(mt2712_rtc_driver);
0410 
0411 MODULE_DESCRIPTION("MediaTek MT2712 SoC based RTC Driver");
0412 MODULE_AUTHOR("Ran Bi <ran.bi@mediatek.com>");
0413 MODULE_LICENSE("GPL");