lkml.org 
[lkml]   [2012]   [Nov]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3/4] rtc: pxa: add pxa95x rtc support
    Date
    the pxa95x rtc need access PBSR register before write to
    RTTR, RCNR, RDCR, and RYCR registers.

    Signed-off-by: Chao Xie <chao.xie@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())
    return platform_driver_probe(&pxa_rtc_driver, pxa_rtc_probe);

    return -ENODEV;
    --
    1.7.4.1


    \
     
     \ /
      Last update: 2012-11-29 04:01    [W:2.696 / U:0.796 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site