Loading arch/arm/mach-integrator/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ # Object file lists. obj-y := clock.o core.o lm.o time.o obj-y := clock.o core.o lm.o obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o Loading drivers/rtc/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -458,6 +458,16 @@ config RTC_DRV_VR41XX To compile this driver as a module, choose M here: the module will be called rtc-vr41xx. config RTC_DRV_PL030 tristate "ARM AMBA PL030 RTC" depends on ARM_AMBA help If you say Y here you will get access to ARM AMBA PrimeCell PL030 RTC found on certain ARM SOCs. To compile this driver as a module, choose M here: the module will be called rtc-pl030. config RTC_DRV_PL031 tristate "ARM AMBA PL031 RTC" depends on ARM_AMBA Loading drivers/rtc/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o Loading arch/arm/mach-integrator/time.c→drivers/rtc/rtc-pl030.c +217 −0 Original line number Diff line number Diff line /* * linux/arch/arm/mach-integrator/time.c * linux/drivers/rtc/rtc-pl030.c * * Copyright (C) 2000-2001 Deep Blue Solutions Ltd. * Loading @@ -8,20 +8,11 @@ * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/time.h> #include <linux/mc146818rtc.h> #include <linux/interrupt.h> #include <linux/rtc.h> #include <linux/init.h> #include <linux/device.h> #include <linux/interrupt.h> #include <linux/amba/bus.h> #include <asm/hardware.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/rtc.h> #include <asm/mach/time.h> #include <linux/io.h> #define RTC_DR (0) #define RTC_MR (4) Loading @@ -31,23 +22,43 @@ #define RTC_CR (16) #define RTC_CR_MIE (1 << 0) extern int (*set_rtc)(void); static void __iomem *rtc_base; struct pl030_rtc { struct rtc_device *rtc; void __iomem *base; }; static irqreturn_t pl030_interrupt(int irq, void *dev_id) { struct pl030_rtc *rtc = dev_id; writel(0, rtc->base + RTC_EOI); return IRQ_HANDLED; } static int pl030_open(struct device *dev) { return 0; } static void pl030_release(struct device *dev) { } static int integrator_set_rtc(void) static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { __raw_writel(xtime.tv_sec, rtc_base + RTC_LR); return 1; return -ENOIOCTLCMD; } static int integrator_rtc_read_alarm(struct rtc_wkalrm *alrm) static int pl030_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { rtc_time_to_tm(readl(rtc_base + RTC_MR), &alrm->time); struct pl030_rtc *rtc = dev_get_drvdata(dev); rtc_time_to_tm(readl(rtc->base + RTC_MR), &alrm->time); return 0; } static inline int integrator_rtc_set_alarm(struct rtc_wkalrm *alrm) static int pl030_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct pl030_rtc *rtc = dev_get_drvdata(dev); unsigned long time; int ret; Loading @@ -58,13 +69,16 @@ static inline int integrator_rtc_set_alarm(struct rtc_wkalrm *alrm) if (ret == 0) ret = rtc_tm_to_time(&alrm->time, &time); if (ret == 0) writel(time, rtc_base + RTC_MR); writel(time, rtc->base + RTC_MR); return ret; } static int integrator_rtc_read_time(struct rtc_time *tm) static int pl030_read_time(struct device *dev, struct rtc_time *tm) { rtc_time_to_tm(readl(rtc_base + RTC_DR), tm); struct pl030_rtc *rtc = dev_get_drvdata(dev); rtc_time_to_tm(readl(rtc->base + RTC_DR), tm); return 0; } Loading @@ -76,121 +90,99 @@ static int integrator_rtc_read_time(struct rtc_time *tm) * edge of the 1Hz clock, we must write the time one second * in advance. */ static inline int integrator_rtc_set_time(struct rtc_time *tm) static int pl030_set_time(struct device *dev, struct rtc_time *tm) { struct pl030_rtc *rtc = dev_get_drvdata(dev); unsigned long time; int ret; ret = rtc_tm_to_time(tm, &time); if (ret == 0) writel(time + 1, rtc_base + RTC_LR); writel(time + 1, rtc->base + RTC_LR); return ret; } static struct rtc_ops rtc_ops = { .owner = THIS_MODULE, .read_time = integrator_rtc_read_time, .set_time = integrator_rtc_set_time, .read_alarm = integrator_rtc_read_alarm, .set_alarm = integrator_rtc_set_alarm, static const struct rtc_class_ops pl030_ops = { .open = pl030_open, .release = pl030_release, .ioctl = pl030_ioctl, .read_time = pl030_read_time, .set_time = pl030_set_time, .read_alarm = pl030_read_alarm, .set_alarm = pl030_set_alarm, }; static irqreturn_t arm_rtc_interrupt(int irq, void *dev_id) { writel(0, rtc_base + RTC_EOI); return IRQ_HANDLED; } static int rtc_probe(struct amba_device *dev, void *id) static int pl030_probe(struct amba_device *dev, void *id) { struct pl030_rtc *rtc; int ret; if (rtc_base) return -EBUSY; ret = amba_request_regions(dev, NULL); if (ret) goto out; goto err_req; rtc_base = ioremap(dev->res.start, SZ_4K); if (!rtc_base) { rtc = kmalloc(sizeof(*rtc), GFP_KERNEL); if (!rtc) { ret = -ENOMEM; goto res_out; goto err_rtc; } __raw_writel(0, rtc_base + RTC_CR); __raw_writel(0, rtc_base + RTC_EOI); rtc->base = ioremap(dev->res.start, SZ_4K); if (!rtc->base) { ret = -ENOMEM; goto err_map; } xtime.tv_sec = __raw_readl(rtc_base + RTC_DR); __raw_writel(0, rtc->base + RTC_CR); __raw_writel(0, rtc->base + RTC_EOI); /* note that 'dev' is merely used for irq disambiguation; * it is not actually referenced in the irq handler */ ret = request_irq(dev->irq[0], arm_rtc_interrupt, IRQF_DISABLED, "rtc-pl030", dev); if (ret) goto map_out; amba_set_drvdata(dev, rtc); ret = register_rtc(&rtc_ops); ret = request_irq(dev->irq[0], pl030_interrupt, IRQF_DISABLED, "rtc-pl030", rtc); if (ret) goto irq_out; goto err_irq; rtc->rtc = rtc_device_register("pl030", &dev->dev, &pl030_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); goto err_reg; } set_rtc = integrator_set_rtc; return 0; irq_out: free_irq(dev->irq[0], dev); map_out: iounmap(rtc_base); rtc_base = NULL; res_out: err_reg: free_irq(dev->irq[0], rtc); err_irq: iounmap(rtc->base); err_map: kfree(rtc); err_rtc: amba_release_regions(dev); out: err_req: return ret; } static int rtc_remove(struct amba_device *dev) static int pl030_remove(struct amba_device *dev) { set_rtc = NULL; struct pl030_rtc *rtc = amba_get_drvdata(dev); writel(0, rtc_base + RTC_CR); amba_set_drvdata(dev, NULL); free_irq(dev->irq[0], dev); unregister_rtc(&rtc_ops); writel(0, rtc->base + RTC_CR); iounmap(rtc_base); rtc_base = NULL; free_irq(dev->irq[0], rtc); rtc_device_unregister(rtc->rtc); iounmap(rtc->base); kfree(rtc); amba_release_regions(dev); return 0; } static struct timespec rtc_delta; static int rtc_suspend(struct amba_device *dev, pm_message_t state) { struct timespec rtc; rtc.tv_sec = readl(rtc_base + RTC_DR); rtc.tv_nsec = 0; save_time_delta(&rtc_delta, &rtc); return 0; } static int rtc_resume(struct amba_device *dev) { struct timespec rtc; rtc.tv_sec = readl(rtc_base + RTC_DR); rtc.tv_nsec = 0; restore_time_delta(&rtc_delta, &rtc); return 0; } static struct amba_id rtc_ids[] = { static struct amba_id pl030_ids[] = { { .id = 0x00041030, .mask = 0x000fffff, Loading @@ -198,26 +190,28 @@ static struct amba_id rtc_ids[] = { { 0, 0 }, }; static struct amba_driver rtc_driver = { static struct amba_driver pl030_driver = { .drv = { .name = "rtc-pl030", }, .probe = rtc_probe, .remove = rtc_remove, .suspend = rtc_suspend, .resume = rtc_resume, .id_table = rtc_ids, .probe = pl030_probe, .remove = pl030_remove, .id_table = pl030_ids, }; static int __init integrator_rtc_init(void) static int __init pl030_init(void) { return amba_driver_register(&rtc_driver); return amba_driver_register(&pl030_driver); } static void __exit integrator_rtc_exit(void) static void __exit pl030_exit(void) { amba_driver_unregister(&rtc_driver); amba_driver_unregister(&pl030_driver); } module_init(integrator_rtc_init); module_exit(integrator_rtc_exit); module_init(pl030_init); module_exit(pl030_exit); MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); MODULE_DESCRIPTION("ARM AMBA PL030 RTC Driver"); MODULE_LICENSE("GPL"); Loading
arch/arm/mach-integrator/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ # Object file lists. obj-y := clock.o core.o lm.o time.o obj-y := clock.o core.o lm.o obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o Loading
drivers/rtc/Kconfig +10 −0 Original line number Diff line number Diff line Loading @@ -458,6 +458,16 @@ config RTC_DRV_VR41XX To compile this driver as a module, choose M here: the module will be called rtc-vr41xx. config RTC_DRV_PL030 tristate "ARM AMBA PL030 RTC" depends on ARM_AMBA help If you say Y here you will get access to ARM AMBA PrimeCell PL030 RTC found on certain ARM SOCs. To compile this driver as a module, choose M here: the module will be called rtc-pl030. config RTC_DRV_PL031 tristate "ARM AMBA PL031 RTC" depends on ARM_AMBA Loading
drivers/rtc/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o Loading
arch/arm/mach-integrator/time.c→drivers/rtc/rtc-pl030.c +217 −0 Original line number Diff line number Diff line /* * linux/arch/arm/mach-integrator/time.c * linux/drivers/rtc/rtc-pl030.c * * Copyright (C) 2000-2001 Deep Blue Solutions Ltd. * Loading @@ -8,20 +8,11 @@ * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/time.h> #include <linux/mc146818rtc.h> #include <linux/interrupt.h> #include <linux/rtc.h> #include <linux/init.h> #include <linux/device.h> #include <linux/interrupt.h> #include <linux/amba/bus.h> #include <asm/hardware.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/rtc.h> #include <asm/mach/time.h> #include <linux/io.h> #define RTC_DR (0) #define RTC_MR (4) Loading @@ -31,23 +22,43 @@ #define RTC_CR (16) #define RTC_CR_MIE (1 << 0) extern int (*set_rtc)(void); static void __iomem *rtc_base; struct pl030_rtc { struct rtc_device *rtc; void __iomem *base; }; static irqreturn_t pl030_interrupt(int irq, void *dev_id) { struct pl030_rtc *rtc = dev_id; writel(0, rtc->base + RTC_EOI); return IRQ_HANDLED; } static int pl030_open(struct device *dev) { return 0; } static void pl030_release(struct device *dev) { } static int integrator_set_rtc(void) static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { __raw_writel(xtime.tv_sec, rtc_base + RTC_LR); return 1; return -ENOIOCTLCMD; } static int integrator_rtc_read_alarm(struct rtc_wkalrm *alrm) static int pl030_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { rtc_time_to_tm(readl(rtc_base + RTC_MR), &alrm->time); struct pl030_rtc *rtc = dev_get_drvdata(dev); rtc_time_to_tm(readl(rtc->base + RTC_MR), &alrm->time); return 0; } static inline int integrator_rtc_set_alarm(struct rtc_wkalrm *alrm) static int pl030_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct pl030_rtc *rtc = dev_get_drvdata(dev); unsigned long time; int ret; Loading @@ -58,13 +69,16 @@ static inline int integrator_rtc_set_alarm(struct rtc_wkalrm *alrm) if (ret == 0) ret = rtc_tm_to_time(&alrm->time, &time); if (ret == 0) writel(time, rtc_base + RTC_MR); writel(time, rtc->base + RTC_MR); return ret; } static int integrator_rtc_read_time(struct rtc_time *tm) static int pl030_read_time(struct device *dev, struct rtc_time *tm) { rtc_time_to_tm(readl(rtc_base + RTC_DR), tm); struct pl030_rtc *rtc = dev_get_drvdata(dev); rtc_time_to_tm(readl(rtc->base + RTC_DR), tm); return 0; } Loading @@ -76,121 +90,99 @@ static int integrator_rtc_read_time(struct rtc_time *tm) * edge of the 1Hz clock, we must write the time one second * in advance. */ static inline int integrator_rtc_set_time(struct rtc_time *tm) static int pl030_set_time(struct device *dev, struct rtc_time *tm) { struct pl030_rtc *rtc = dev_get_drvdata(dev); unsigned long time; int ret; ret = rtc_tm_to_time(tm, &time); if (ret == 0) writel(time + 1, rtc_base + RTC_LR); writel(time + 1, rtc->base + RTC_LR); return ret; } static struct rtc_ops rtc_ops = { .owner = THIS_MODULE, .read_time = integrator_rtc_read_time, .set_time = integrator_rtc_set_time, .read_alarm = integrator_rtc_read_alarm, .set_alarm = integrator_rtc_set_alarm, static const struct rtc_class_ops pl030_ops = { .open = pl030_open, .release = pl030_release, .ioctl = pl030_ioctl, .read_time = pl030_read_time, .set_time = pl030_set_time, .read_alarm = pl030_read_alarm, .set_alarm = pl030_set_alarm, }; static irqreturn_t arm_rtc_interrupt(int irq, void *dev_id) { writel(0, rtc_base + RTC_EOI); return IRQ_HANDLED; } static int rtc_probe(struct amba_device *dev, void *id) static int pl030_probe(struct amba_device *dev, void *id) { struct pl030_rtc *rtc; int ret; if (rtc_base) return -EBUSY; ret = amba_request_regions(dev, NULL); if (ret) goto out; goto err_req; rtc_base = ioremap(dev->res.start, SZ_4K); if (!rtc_base) { rtc = kmalloc(sizeof(*rtc), GFP_KERNEL); if (!rtc) { ret = -ENOMEM; goto res_out; goto err_rtc; } __raw_writel(0, rtc_base + RTC_CR); __raw_writel(0, rtc_base + RTC_EOI); rtc->base = ioremap(dev->res.start, SZ_4K); if (!rtc->base) { ret = -ENOMEM; goto err_map; } xtime.tv_sec = __raw_readl(rtc_base + RTC_DR); __raw_writel(0, rtc->base + RTC_CR); __raw_writel(0, rtc->base + RTC_EOI); /* note that 'dev' is merely used for irq disambiguation; * it is not actually referenced in the irq handler */ ret = request_irq(dev->irq[0], arm_rtc_interrupt, IRQF_DISABLED, "rtc-pl030", dev); if (ret) goto map_out; amba_set_drvdata(dev, rtc); ret = register_rtc(&rtc_ops); ret = request_irq(dev->irq[0], pl030_interrupt, IRQF_DISABLED, "rtc-pl030", rtc); if (ret) goto irq_out; goto err_irq; rtc->rtc = rtc_device_register("pl030", &dev->dev, &pl030_ops, THIS_MODULE); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); goto err_reg; } set_rtc = integrator_set_rtc; return 0; irq_out: free_irq(dev->irq[0], dev); map_out: iounmap(rtc_base); rtc_base = NULL; res_out: err_reg: free_irq(dev->irq[0], rtc); err_irq: iounmap(rtc->base); err_map: kfree(rtc); err_rtc: amba_release_regions(dev); out: err_req: return ret; } static int rtc_remove(struct amba_device *dev) static int pl030_remove(struct amba_device *dev) { set_rtc = NULL; struct pl030_rtc *rtc = amba_get_drvdata(dev); writel(0, rtc_base + RTC_CR); amba_set_drvdata(dev, NULL); free_irq(dev->irq[0], dev); unregister_rtc(&rtc_ops); writel(0, rtc->base + RTC_CR); iounmap(rtc_base); rtc_base = NULL; free_irq(dev->irq[0], rtc); rtc_device_unregister(rtc->rtc); iounmap(rtc->base); kfree(rtc); amba_release_regions(dev); return 0; } static struct timespec rtc_delta; static int rtc_suspend(struct amba_device *dev, pm_message_t state) { struct timespec rtc; rtc.tv_sec = readl(rtc_base + RTC_DR); rtc.tv_nsec = 0; save_time_delta(&rtc_delta, &rtc); return 0; } static int rtc_resume(struct amba_device *dev) { struct timespec rtc; rtc.tv_sec = readl(rtc_base + RTC_DR); rtc.tv_nsec = 0; restore_time_delta(&rtc_delta, &rtc); return 0; } static struct amba_id rtc_ids[] = { static struct amba_id pl030_ids[] = { { .id = 0x00041030, .mask = 0x000fffff, Loading @@ -198,26 +190,28 @@ static struct amba_id rtc_ids[] = { { 0, 0 }, }; static struct amba_driver rtc_driver = { static struct amba_driver pl030_driver = { .drv = { .name = "rtc-pl030", }, .probe = rtc_probe, .remove = rtc_remove, .suspend = rtc_suspend, .resume = rtc_resume, .id_table = rtc_ids, .probe = pl030_probe, .remove = pl030_remove, .id_table = pl030_ids, }; static int __init integrator_rtc_init(void) static int __init pl030_init(void) { return amba_driver_register(&rtc_driver); return amba_driver_register(&pl030_driver); } static void __exit integrator_rtc_exit(void) static void __exit pl030_exit(void) { amba_driver_unregister(&rtc_driver); amba_driver_unregister(&pl030_driver); } module_init(integrator_rtc_init); module_exit(integrator_rtc_exit); module_init(pl030_init); module_exit(pl030_exit); MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); MODULE_DESCRIPTION("ARM AMBA PL030 RTC Driver"); MODULE_LICENSE("GPL");