0001
0002
0003
0004
0005
0006
0007 #include <linux/module.h>
0008 #include <linux/rtc.h>
0009 #include <linux/init.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/amba/bus.h>
0012 #include <linux/io.h>
0013 #include <linux/slab.h>
0014
0015 #define RTC_DR (0)
0016 #define RTC_MR (4)
0017 #define RTC_STAT (8)
0018 #define RTC_EOI (8)
0019 #define RTC_LR (12)
0020 #define RTC_CR (16)
0021 #define RTC_CR_MIE (1 << 0)
0022
0023 struct pl030_rtc {
0024 struct rtc_device *rtc;
0025 void __iomem *base;
0026 };
0027
0028 static irqreturn_t pl030_interrupt(int irq, void *dev_id)
0029 {
0030 struct pl030_rtc *rtc = dev_id;
0031 writel(0, rtc->base + RTC_EOI);
0032 return IRQ_HANDLED;
0033 }
0034
0035 static int pl030_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
0036 {
0037 struct pl030_rtc *rtc = dev_get_drvdata(dev);
0038
0039 rtc_time64_to_tm(readl(rtc->base + RTC_MR), &alrm->time);
0040 return 0;
0041 }
0042
0043 static int pl030_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
0044 {
0045 struct pl030_rtc *rtc = dev_get_drvdata(dev);
0046
0047 writel(rtc_tm_to_time64(&alrm->time), rtc->base + RTC_MR);
0048
0049 return 0;
0050 }
0051
0052 static int pl030_read_time(struct device *dev, struct rtc_time *tm)
0053 {
0054 struct pl030_rtc *rtc = dev_get_drvdata(dev);
0055
0056 rtc_time64_to_tm(readl(rtc->base + RTC_DR), tm);
0057
0058 return 0;
0059 }
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 static int pl030_set_time(struct device *dev, struct rtc_time *tm)
0070 {
0071 struct pl030_rtc *rtc = dev_get_drvdata(dev);
0072
0073 writel(rtc_tm_to_time64(tm) + 1, rtc->base + RTC_LR);
0074
0075 return 0;
0076 }
0077
0078 static const struct rtc_class_ops pl030_ops = {
0079 .read_time = pl030_read_time,
0080 .set_time = pl030_set_time,
0081 .read_alarm = pl030_read_alarm,
0082 .set_alarm = pl030_set_alarm,
0083 };
0084
0085 static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
0086 {
0087 struct pl030_rtc *rtc;
0088 int ret;
0089
0090 ret = amba_request_regions(dev, NULL);
0091 if (ret)
0092 goto err_req;
0093
0094 rtc = devm_kzalloc(&dev->dev, sizeof(*rtc), GFP_KERNEL);
0095 if (!rtc) {
0096 ret = -ENOMEM;
0097 goto err_rtc;
0098 }
0099
0100 rtc->rtc = devm_rtc_allocate_device(&dev->dev);
0101 if (IS_ERR(rtc->rtc)) {
0102 ret = PTR_ERR(rtc->rtc);
0103 goto err_rtc;
0104 }
0105
0106 rtc->rtc->ops = &pl030_ops;
0107 rtc->rtc->range_max = U32_MAX;
0108 rtc->base = ioremap(dev->res.start, resource_size(&dev->res));
0109 if (!rtc->base) {
0110 ret = -ENOMEM;
0111 goto err_rtc;
0112 }
0113
0114 __raw_writel(0, rtc->base + RTC_CR);
0115 __raw_writel(0, rtc->base + RTC_EOI);
0116
0117 amba_set_drvdata(dev, rtc);
0118
0119 ret = request_irq(dev->irq[0], pl030_interrupt, 0,
0120 "rtc-pl030", rtc);
0121 if (ret)
0122 goto err_irq;
0123
0124 ret = devm_rtc_register_device(rtc->rtc);
0125 if (ret)
0126 goto err_reg;
0127
0128 return 0;
0129
0130 err_reg:
0131 free_irq(dev->irq[0], rtc);
0132 err_irq:
0133 iounmap(rtc->base);
0134 err_rtc:
0135 amba_release_regions(dev);
0136 err_req:
0137 return ret;
0138 }
0139
0140 static void pl030_remove(struct amba_device *dev)
0141 {
0142 struct pl030_rtc *rtc = amba_get_drvdata(dev);
0143
0144 writel(0, rtc->base + RTC_CR);
0145
0146 free_irq(dev->irq[0], rtc);
0147 iounmap(rtc->base);
0148 amba_release_regions(dev);
0149 }
0150
0151 static struct amba_id pl030_ids[] = {
0152 {
0153 .id = 0x00041030,
0154 .mask = 0x000fffff,
0155 },
0156 { 0, 0 },
0157 };
0158
0159 MODULE_DEVICE_TABLE(amba, pl030_ids);
0160
0161 static struct amba_driver pl030_driver = {
0162 .drv = {
0163 .name = "rtc-pl030",
0164 },
0165 .probe = pl030_probe,
0166 .remove = pl030_remove,
0167 .id_table = pl030_ids,
0168 };
0169
0170 module_amba_driver(pl030_driver);
0171
0172 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
0173 MODULE_DESCRIPTION("ARM AMBA PL030 RTC Driver");
0174 MODULE_LICENSE("GPL");