Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  linux/drivers/rtc/rtc-pl030.c
0004  *
0005  *  Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
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  * Set the RTC time.  Unfortunately, we can't accurately set
0063  * the point at which the counter updates.
0064  *
0065  * Also, since RTC_LR is transferred to RTC_CR on next rising
0066  * edge of the 1Hz clock, we must write the time one second
0067  * in advance.
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");