[PATCH 3/4] rtc: pxa: add pxa95x rtc support
Haojian Zhuang
haojian.zhuang at gmail.com
Tue Dec 4 02:03:31 EST 2012
On Thu, Nov 29, 2012 at 10:21 AM, Chao Xie <chao.xie at marvell.com> wrote:
> the pxa95x rtc need access PBSR register before write to
> RTTR, RCNR, RDCR, and RYCR registers.
>
> Signed-off-by: Chao Xie <chao.xie at marvell.com>
> ---
> drivers/rtc/rtc-pxa.c | 97 +++++++++++++++++++++++++++++++++++++++++++------
> 1 files changed, 85 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
> index 22ea4f5..29646af 100644
> --- a/drivers/rtc/rtc-pxa.c
> +++ b/drivers/rtc/rtc-pxa.c
> @@ -29,6 +29,7 @@
> #include <linux/slab.h>
> #include <linux/of.h>
> #include <linux/of_device.h>
> +#include <linux/delay.h>
>
> #include <mach/hardware.h>
>
> @@ -81,14 +82,28 @@
> #define RTCPICR 0x34
> #define PIAR 0x38
>
> +#define PSBR_RTC 0x00
> +
> #define rtc_readl(pxa_rtc, reg) \
> __raw_readl((pxa_rtc)->base + (reg))
> #define rtc_writel(pxa_rtc, reg, value) \
> __raw_writel((value), (pxa_rtc)->base + (reg))
> +#define rtc_readl_psbr(pxa_rtc, reg) \
> + __raw_readl((pxa_rtc)->base_psbr + (reg))
> +#define rtc_writel_psbr(pxa_rtc, reg, value) \
> + __raw_writel((value), (pxa_rtc)->base_psbr + (reg))
> +
> +enum {
> + RTC_PXA27X,
> + RTC_PXA95X,
> +};
>
> struct pxa_rtc {
> struct resource *ress;
> + struct resource *ress_psbr;
> + unsigned int id;
> void __iomem *base;
> + void __iomem *base_psbr;
> int irq_1Hz;
> int irq_Alrm;
> struct rtc_device *rtc;
> @@ -250,9 +265,26 @@ static int pxa_rtc_set_time(struct device *dev, struct rtc_time *tm)
> {
> struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
>
> + /*
> + * sequence to wirte pxa rtc register RCNR RDCR RYCR is
> + * 1. set PSBR[RWE] bit, take 2x32-khz to complete
> + * 2. write to RTC register,take 2x32-khz to complete
> + * 3. clear PSBR[RWE] bit,take 2x32-khz to complete
> + */
> + if (pxa_rtc->id == RTC_PXA95X) {
> + rtc_writel_psbr(pxa_rtc, PSBR_RTC, 0x01);
> + udelay(100);
> + }
> +
> rtc_writel(pxa_rtc, RYCR, ryxr_calc(tm));
> rtc_writel(pxa_rtc, RDCR, rdxr_calc(tm));
>
> + if (pxa_rtc->id == RTC_PXA95X) {
> + udelay(100);
> + rtc_writel_psbr(pxa_rtc, PSBR_RTC, 0x00);
> + udelay(100);
> + }
> +
> return 0;
> }
>
> @@ -318,6 +350,20 @@ static const struct rtc_class_ops pxa_rtc_ops = {
> .proc = pxa_rtc_proc,
> };
>
> +static struct of_device_id pxa_rtc_dt_ids[] = {
> + { .compatible = "marvell,pxa-rtc", .data = (void *)RTC_PXA27X },
> + { .compatible = "marvell,pxa95x-rtc", .data = (void *)RTC_PXA95X },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, pxa_rtc_dt_ids);
> +
> +static const struct platform_device_id pxa_rtc_id_table[] = {
> + { "pxa-rtc", RTC_PXA27X },
> + { "pxa95x-rtc", RTC_PXA95X },
> + { },
> +};
> +MODULE_DEVICE_TABLE(platform, pxa_rtc_id_table);
> +
> static int __init pxa_rtc_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> @@ -332,13 +378,34 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
> spin_lock_init(&pxa_rtc->lock);
> platform_set_drvdata(pdev, pxa_rtc);
>
> + if (pdev->dev.of_node) {
> + const struct of_device_id *of_id =
> + of_match_device(pxa_rtc_dt_ids, &pdev->dev);
> +
> + pxa_rtc->id = (unsigned int)(of_id->data);
> + } else {
> + const struct platform_device_id *id =
> + platform_get_device_id(pdev);
> +
> + pxa_rtc->id = id->driver_data;
> + }
> +
> ret = -ENXIO;
> pxa_rtc->ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> if (!pxa_rtc->ress) {
> - dev_err(dev, "No I/O memory resource defined\n");
> + dev_err(dev, "No I/O memory resource(id=0) defined\n");
> goto err_ress;
> }
>
> + if (pxa_rtc->id == RTC_PXA95X) {
> + pxa_rtc->ress_psbr =
> + platform_get_resource(pdev, IORESOURCE_MEM, 1);
> + if (!pxa_rtc->ress_psbr) {
> + dev_err(dev, "No I/O memory resource(id=1) defined\n");
> + goto err_ress;
> + }
> + }
> +
> pxa_rtc->irq_1Hz = platform_get_irq(pdev, 0);
> if (pxa_rtc->irq_1Hz < 0) {
> dev_err(dev, "No 1Hz IRQ resource defined\n");
> @@ -355,7 +422,17 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
> resource_size(pxa_rtc->ress));
> if (!pxa_rtc->base) {
> dev_err(&pdev->dev, "Unable to map pxa RTC I/O memory\n");
> - goto err_map;
> + goto err_map_base;
> + }
> +
> + if (pxa_rtc->id == RTC_PXA95X) {
> + pxa_rtc->base_psbr = ioremap(pxa_rtc->ress_psbr->start,
> + resource_size(pxa_rtc->ress_psbr));
> + if (!pxa_rtc->base_psbr) {
> + dev_err(&pdev->dev,
> + "Unable to map pxa RTC PSBR I/O memory\n");
> + goto err_map_base_psbr;
> + }
> }
>
> /*
> @@ -384,9 +461,12 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
> return 0;
>
> err_rtc_reg:
> + if (pxa_rtc->id == RTC_PXA95X)
> + iounmap(pxa_rtc->base_psbr);
> +err_map_base_psbr:
> iounmap(pxa_rtc->base);
> +err_map_base:
> err_ress:
> -err_map:
> kfree(pxa_rtc);
> return ret;
> }
> @@ -406,14 +486,6 @@ static int __exit pxa_rtc_remove(struct platform_device *pdev)
> return 0;
> }
>
> -#ifdef CONFIG_OF
> -static struct of_device_id pxa_rtc_dt_ids[] = {
> - { .compatible = "marvell,pxa-rtc" },
> - {}
> -};
> -MODULE_DEVICE_TABLE(of, pxa_rtc_dt_ids);
> -#endif
> -
> #ifdef CONFIG_PM
> static int pxa_rtc_suspend(struct device *dev)
> {
> @@ -448,11 +520,12 @@ static struct platform_driver pxa_rtc_driver = {
> .pm = &pxa_rtc_pm_ops,
> #endif
> },
> + .id_table = pxa_rtc_id_table,
> };
>
> static int __init pxa_rtc_init(void)
> {
> - if (cpu_is_pxa27x() || cpu_is_pxa3xx())
> + if (cpu_is_pxa27x() || cpu_is_pxa3xx() || cpu_is_pxa95x())
Don't use cpu_is_xxx() any more. If there's some different thing, we
should parse it
from DTS.
> return platform_driver_probe(&pxa_rtc_driver, pxa_rtc_probe);
>
> return -ENODEV;
> --
> 1.7.4.1
>
More information about the linux-arm-kernel
mailing list