0001
0002
0003
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
0015
0016 #define HW_ILR 0x00
0017 #define BM_RTCALF BIT(1)
0018 #define BM_RTCCIF BIT(0)
0019
0020
0021 #define HW_CCR 0x08
0022
0023 #define BM_CCALOFF BIT(4)
0024
0025 #define BM_CTCRST BIT(1)
0026
0027 #define BM_CLKEN BIT(0)
0028
0029
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
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
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
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
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
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
0148
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
0175
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
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
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");