Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2016 Oleksij Rempel <linux@rempel-privat.de>
0004  */
0005 
0006 #include <linux/clk.h>
0007 #include <linux/interrupt.h>
0008 #include <linux/io.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/rtc.h>
0013 
0014 /* Miscellaneous registers */
0015 /* Interrupt Location Register */
0016 #define HW_ILR          0x00
0017 #define BM_RTCALF       BIT(1)
0018 #define BM_RTCCIF       BIT(0)
0019 
0020 /* Clock Control Register */
0021 #define HW_CCR          0x08
0022 /* Calibration counter disable */
0023 #define BM_CCALOFF      BIT(4)
0024 /* Reset internal oscillator divider */
0025 #define BM_CTCRST       BIT(1)
0026 /* Clock Enable */
0027 #define BM_CLKEN        BIT(0)
0028 
0029 /* Counter Increment Interrupt Register */
0030 #define HW_CIIR         0x0C
0031 #define BM_CIIR_IMYEAR      BIT(7)
0032 #define BM_CIIR_IMMON       BIT(6)
0033 #define BM_CIIR_IMDOY       BIT(5)
0034 #define BM_CIIR_IMDOW       BIT(4)
0035 #define BM_CIIR_IMDOM       BIT(3)
0036 #define BM_CIIR_IMHOUR      BIT(2)
0037 #define BM_CIIR_IMMIN       BIT(1)
0038 #define BM_CIIR_IMSEC       BIT(0)
0039 
0040 /* Alarm Mask Register */
0041 #define HW_AMR          0x10
0042 #define BM_AMR_IMYEAR       BIT(7)
0043 #define BM_AMR_IMMON        BIT(6)
0044 #define BM_AMR_IMDOY        BIT(5)
0045 #define BM_AMR_IMDOW        BIT(4)
0046 #define BM_AMR_IMDOM        BIT(3)
0047 #define BM_AMR_IMHOUR       BIT(2)
0048 #define BM_AMR_IMMIN        BIT(1)
0049 #define BM_AMR_IMSEC        BIT(0)
0050 #define BM_AMR_OFF      0xff
0051 
0052 /* Consolidated time registers */
0053 #define HW_CTIME0       0x14
0054 #define BM_CTIME0_DOW_S     24
0055 #define BM_CTIME0_DOW_M     0x7
0056 #define BM_CTIME0_HOUR_S    16
0057 #define BM_CTIME0_HOUR_M    0x1f
0058 #define BM_CTIME0_MIN_S     8
0059 #define BM_CTIME0_MIN_M     0x3f
0060 #define BM_CTIME0_SEC_S     0
0061 #define BM_CTIME0_SEC_M     0x3f
0062 
0063 #define HW_CTIME1       0x18
0064 #define BM_CTIME1_YEAR_S    16
0065 #define BM_CTIME1_YEAR_M    0xfff
0066 #define BM_CTIME1_MON_S     8
0067 #define BM_CTIME1_MON_M     0xf
0068 #define BM_CTIME1_DOM_S     0
0069 #define BM_CTIME1_DOM_M     0x1f
0070 
0071 #define HW_CTIME2       0x1C
0072 #define BM_CTIME2_DOY_S     0
0073 #define BM_CTIME2_DOY_M     0xfff
0074 
0075 /* Time counter registers */
0076 #define HW_SEC          0x20
0077 #define HW_MIN          0x24
0078 #define HW_HOUR         0x28
0079 #define HW_DOM          0x2C
0080 #define HW_DOW          0x30
0081 #define HW_DOY          0x34
0082 #define HW_MONTH        0x38
0083 #define HW_YEAR         0x3C
0084 
0085 #define HW_CALIBRATION      0x40
0086 #define BM_CALDIR_BACK      BIT(17)
0087 #define BM_CALVAL_M     0x1ffff
0088 
0089 /* General purpose registers */
0090 #define HW_GPREG0       0x44
0091 #define HW_GPREG1       0x48
0092 #define HW_GPREG2       0x4C
0093 #define HW_GPREG3       0x50
0094 #define HW_GPREG4       0x54
0095 
0096 /* Alarm register group */
0097 #define HW_ALSEC        0x60
0098 #define HW_ALMIN        0x64
0099 #define HW_ALHOUR       0x68
0100 #define HW_ALDOM        0x6C
0101 #define HW_ALDOW        0x70
0102 #define HW_ALDOY        0x74
0103 #define HW_ALMON        0x78
0104 #define HW_ALYEAR       0x7C
0105 
0106 struct asm9260_rtc_priv {
0107     struct device       *dev;
0108     void __iomem        *iobase;
0109     struct rtc_device   *rtc;
0110     struct clk      *clk;
0111 };
0112 
0113 static irqreturn_t asm9260_rtc_irq(int irq, void *dev_id)
0114 {
0115     struct asm9260_rtc_priv *priv = dev_id;
0116     u32 isr;
0117     unsigned long events = 0;
0118 
0119     rtc_lock(priv->rtc);
0120     isr = ioread32(priv->iobase + HW_CIIR);
0121     if (!isr) {
0122         rtc_unlock(priv->rtc);
0123         return IRQ_NONE;
0124     }
0125 
0126     iowrite32(0, priv->iobase + HW_CIIR);
0127     rtc_unlock(priv->rtc);
0128 
0129     events |= RTC_AF | RTC_IRQF;
0130 
0131     rtc_update_irq(priv->rtc, 1, events);
0132 
0133     return IRQ_HANDLED;
0134 }
0135 
0136 static int asm9260_rtc_read_time(struct device *dev, struct rtc_time *tm)
0137 {
0138     struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
0139     u32 ctime0, ctime1, ctime2;
0140 
0141     ctime0 = ioread32(priv->iobase + HW_CTIME0);
0142     ctime1 = ioread32(priv->iobase + HW_CTIME1);
0143     ctime2 = ioread32(priv->iobase + HW_CTIME2);
0144 
0145     if (ctime1 != ioread32(priv->iobase + HW_CTIME1)) {
0146         /*
0147          * woops, counter flipped right now. Now we are safe
0148          * to reread.
0149          */
0150         ctime0 = ioread32(priv->iobase + HW_CTIME0);
0151         ctime1 = ioread32(priv->iobase + HW_CTIME1);
0152         ctime2 = ioread32(priv->iobase + HW_CTIME2);
0153     }
0154 
0155     tm->tm_sec  = (ctime0 >> BM_CTIME0_SEC_S)  & BM_CTIME0_SEC_M;
0156     tm->tm_min  = (ctime0 >> BM_CTIME0_MIN_S)  & BM_CTIME0_MIN_M;
0157     tm->tm_hour = (ctime0 >> BM_CTIME0_HOUR_S) & BM_CTIME0_HOUR_M;
0158     tm->tm_wday = (ctime0 >> BM_CTIME0_DOW_S)  & BM_CTIME0_DOW_M;
0159 
0160     tm->tm_mday = (ctime1 >> BM_CTIME1_DOM_S)  & BM_CTIME1_DOM_M;
0161     tm->tm_mon  = (ctime1 >> BM_CTIME1_MON_S)  & BM_CTIME1_MON_M;
0162     tm->tm_year = (ctime1 >> BM_CTIME1_YEAR_S) & BM_CTIME1_YEAR_M;
0163 
0164     tm->tm_yday = (ctime2 >> BM_CTIME2_DOY_S)  & BM_CTIME2_DOY_M;
0165 
0166     return 0;
0167 }
0168 
0169 static int asm9260_rtc_set_time(struct device *dev, struct rtc_time *tm)
0170 {
0171     struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
0172 
0173     /*
0174      * make sure SEC counter will not flip other counter on write time,
0175      * real value will be written at the enf of sequence.
0176      */
0177     iowrite32(0, priv->iobase + HW_SEC);
0178 
0179     iowrite32(tm->tm_year, priv->iobase + HW_YEAR);
0180     iowrite32(tm->tm_mon,  priv->iobase + HW_MONTH);
0181     iowrite32(tm->tm_mday, priv->iobase + HW_DOM);
0182     iowrite32(tm->tm_wday, priv->iobase + HW_DOW);
0183     iowrite32(tm->tm_yday, priv->iobase + HW_DOY);
0184     iowrite32(tm->tm_hour, priv->iobase + HW_HOUR);
0185     iowrite32(tm->tm_min,  priv->iobase + HW_MIN);
0186     iowrite32(tm->tm_sec,  priv->iobase + HW_SEC);
0187 
0188     return 0;
0189 }
0190 
0191 static int asm9260_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
0192 {
0193     struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
0194 
0195     alrm->time.tm_year = ioread32(priv->iobase + HW_ALYEAR);
0196     alrm->time.tm_mon  = ioread32(priv->iobase + HW_ALMON);
0197     alrm->time.tm_mday = ioread32(priv->iobase + HW_ALDOM);
0198     alrm->time.tm_wday = ioread32(priv->iobase + HW_ALDOW);
0199     alrm->time.tm_yday = ioread32(priv->iobase + HW_ALDOY);
0200     alrm->time.tm_hour = ioread32(priv->iobase + HW_ALHOUR);
0201     alrm->time.tm_min  = ioread32(priv->iobase + HW_ALMIN);
0202     alrm->time.tm_sec  = ioread32(priv->iobase + HW_ALSEC);
0203 
0204     alrm->enabled = ioread32(priv->iobase + HW_AMR) ? 1 : 0;
0205     alrm->pending = ioread32(priv->iobase + HW_CIIR) ? 1 : 0;
0206 
0207     return rtc_valid_tm(&alrm->time);
0208 }
0209 
0210 static int asm9260_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
0211 {
0212     struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
0213 
0214     iowrite32(alrm->time.tm_year, priv->iobase + HW_ALYEAR);
0215     iowrite32(alrm->time.tm_mon,  priv->iobase + HW_ALMON);
0216     iowrite32(alrm->time.tm_mday, priv->iobase + HW_ALDOM);
0217     iowrite32(alrm->time.tm_wday, priv->iobase + HW_ALDOW);
0218     iowrite32(alrm->time.tm_yday, priv->iobase + HW_ALDOY);
0219     iowrite32(alrm->time.tm_hour, priv->iobase + HW_ALHOUR);
0220     iowrite32(alrm->time.tm_min,  priv->iobase + HW_ALMIN);
0221     iowrite32(alrm->time.tm_sec,  priv->iobase + HW_ALSEC);
0222 
0223     iowrite32(alrm->enabled ? 0 : BM_AMR_OFF, priv->iobase + HW_AMR);
0224 
0225     return 0;
0226 }
0227 
0228 static int asm9260_alarm_irq_enable(struct device *dev, unsigned int enabled)
0229 {
0230     struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
0231 
0232     iowrite32(enabled ? 0 : BM_AMR_OFF, priv->iobase + HW_AMR);
0233     return 0;
0234 }
0235 
0236 static const struct rtc_class_ops asm9260_rtc_ops = {
0237     .read_time      = asm9260_rtc_read_time,
0238     .set_time       = asm9260_rtc_set_time,
0239     .read_alarm     = asm9260_rtc_read_alarm,
0240     .set_alarm      = asm9260_rtc_set_alarm,
0241     .alarm_irq_enable   = asm9260_alarm_irq_enable,
0242 };
0243 
0244 static int asm9260_rtc_probe(struct platform_device *pdev)
0245 {
0246     struct asm9260_rtc_priv *priv;
0247     struct device *dev = &pdev->dev;
0248     int irq_alarm, ret;
0249     u32 ccr;
0250 
0251     priv = devm_kzalloc(dev, sizeof(struct asm9260_rtc_priv), GFP_KERNEL);
0252     if (!priv)
0253         return -ENOMEM;
0254 
0255     priv->dev = &pdev->dev;
0256     platform_set_drvdata(pdev, priv);
0257 
0258     irq_alarm = platform_get_irq(pdev, 0);
0259     if (irq_alarm < 0)
0260         return irq_alarm;
0261 
0262     priv->iobase = devm_platform_ioremap_resource(pdev, 0);
0263     if (IS_ERR(priv->iobase))
0264         return PTR_ERR(priv->iobase);
0265 
0266     priv->clk = devm_clk_get(dev, "ahb");
0267     if (IS_ERR(priv->clk))
0268         return PTR_ERR(priv->clk);
0269 
0270     ret = clk_prepare_enable(priv->clk);
0271     if (ret) {
0272         dev_err(dev, "Failed to enable clk!\n");
0273         return ret;
0274     }
0275 
0276     ccr = ioread32(priv->iobase + HW_CCR);
0277     /* if dev is not enabled, reset it */
0278     if ((ccr & (BM_CLKEN | BM_CTCRST)) != BM_CLKEN) {
0279         iowrite32(BM_CTCRST, priv->iobase + HW_CCR);
0280         ccr = 0;
0281     }
0282 
0283     iowrite32(BM_CLKEN | ccr, priv->iobase + HW_CCR);
0284     iowrite32(0, priv->iobase + HW_CIIR);
0285     iowrite32(BM_AMR_OFF, priv->iobase + HW_AMR);
0286 
0287     priv->rtc = devm_rtc_device_register(dev, dev_name(dev),
0288                          &asm9260_rtc_ops, THIS_MODULE);
0289     if (IS_ERR(priv->rtc)) {
0290         ret = PTR_ERR(priv->rtc);
0291         dev_err(dev, "Failed to register RTC device: %d\n", ret);
0292         goto err_return;
0293     }
0294 
0295     ret = devm_request_threaded_irq(dev, irq_alarm, NULL,
0296                     asm9260_rtc_irq, IRQF_ONESHOT,
0297                     dev_name(dev), priv);
0298     if (ret < 0) {
0299         dev_err(dev, "can't get irq %i, err %d\n",
0300             irq_alarm, ret);
0301         goto err_return;
0302     }
0303 
0304     return 0;
0305 
0306 err_return:
0307     clk_disable_unprepare(priv->clk);
0308     return ret;
0309 }
0310 
0311 static int asm9260_rtc_remove(struct platform_device *pdev)
0312 {
0313     struct asm9260_rtc_priv *priv = platform_get_drvdata(pdev);
0314 
0315     /* Disable alarm matching */
0316     iowrite32(BM_AMR_OFF, priv->iobase + HW_AMR);
0317     clk_disable_unprepare(priv->clk);
0318     return 0;
0319 }
0320 
0321 static const struct of_device_id asm9260_dt_ids[] = {
0322     { .compatible = "alphascale,asm9260-rtc", },
0323     {}
0324 };
0325 MODULE_DEVICE_TABLE(of, asm9260_dt_ids);
0326 
0327 static struct platform_driver asm9260_rtc_driver = {
0328     .probe      = asm9260_rtc_probe,
0329     .remove     = asm9260_rtc_remove,
0330     .driver     = {
0331         .name   = "asm9260-rtc",
0332         .of_match_table = asm9260_dt_ids,
0333     },
0334 };
0335 
0336 module_platform_driver(asm9260_rtc_driver);
0337 
0338 MODULE_AUTHOR("Oleksij Rempel <linux@rempel-privat.de>");
0339 MODULE_DESCRIPTION("Alphascale asm9260 SoC Realtime Clock Driver (RTC)");
0340 MODULE_LICENSE("GPL");