Skip to content

Commit

Permalink
rtc: pxa: convert to use shared sa1100 functions
Browse files Browse the repository at this point in the history
Currently, the rtc-sa1100 and rtc-pxa drivers co-exist as rtc-pxa has a
superset of functionality. Having 2 drivers sharing the same memory
resource is not allowed by the driver model if resources are properly
declared. This problem was avoided by not adding memory resources to the
SA1100 RTC driver, but that prevents clean-up of the SA1100 driver.

This commit converts the PXA RTC to use the exported SA1100 RTC
functions. Now the sa1100-rtc and pxa-rtc devices are mutually
exclusive, so we must remove the sa1100-rtc from pxa27x and pxa3xx.

Signed-off-by: Rob Herring <robh@kernel.org>
Cc: Daniel Mack <daniel@zonque.org>
Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Robert Jarzmik <robert.jarzmik@free.fr>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: rtc-linux@googlegroups.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
  • Loading branch information
Rob Herring authored and Alexandre Belloni committed Sep 5, 2015
1 parent 8c0961b commit 3cdf4ad
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 34 deletions.
1 change: 0 additions & 1 deletion arch/arm/mach-pxa/pxa27x.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,6 @@ static struct platform_device *devices[] __initdata = {
&pxa_device_asoc_ssp2,
&pxa_device_asoc_ssp3,
&pxa_device_asoc_platform,
&sa1100_device_rtc,
&pxa_device_rtc,
&pxa27x_device_ssp1,
&pxa27x_device_ssp2,
Expand Down
1 change: 0 additions & 1 deletion arch/arm/mach-pxa/pxa3xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,6 @@ static struct platform_device *devices[] __initdata = {
&pxa_device_asoc_ssp3,
&pxa_device_asoc_ssp4,
&pxa_device_asoc_platform,
&sa1100_device_rtc,
&pxa_device_rtc,
&pxa3xx_device_ssp1,
&pxa3xx_device_ssp2,
Expand Down
12 changes: 7 additions & 5 deletions drivers/rtc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1306,11 +1306,13 @@ config RTC_DRV_GENERIC
just say Y.

config RTC_DRV_PXA
tristate "PXA27x/PXA3xx"
depends on ARCH_PXA
help
If you say Y here you will get access to the real time clock
built into your PXA27x or PXA3xx CPU.
tristate "PXA27x/PXA3xx"
depends on ARCH_PXA
select RTC_DRV_SA1100
help
If you say Y here you will get access to the real time clock
built into your PXA27x or PXA3xx CPU. This RTC is actually 2 RTCs
consisting of an SA1100 compatible RTC and the extended PXA RTC.

This RTC driver uses PXA RTC registers available since pxa27x
series (RDxR, RYxR) instead of legacy RCNR, RTAR.
Expand Down
51 changes: 24 additions & 27 deletions drivers/rtc/rtc-pxa.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

#include <mach/hardware.h>

#include "rtc-sa1100.h"

#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
#define MAXFREQ_PERIODIC 1000
Expand Down Expand Up @@ -86,10 +88,9 @@
__raw_writel((value), (pxa_rtc)->base + (reg))

struct pxa_rtc {
struct sa1100_rtc sa1100_rtc;
struct resource *ress;
void __iomem *base;
int irq_1Hz;
int irq_Alrm;
struct rtc_device *rtc;
spinlock_t lock; /* Protects this structure */
};
Expand Down Expand Up @@ -184,25 +185,25 @@ static int pxa_rtc_open(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
int ret;

ret = request_irq(pxa_rtc->irq_1Hz, pxa_rtc_irq, 0,
ret = request_irq(pxa_rtc->sa1100_rtc.irq_1hz, pxa_rtc_irq, 0,
"rtc 1Hz", dev);
if (ret < 0) {
dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_1Hz,
ret);
dev_err(dev, "can't get irq %i, err %d\n",
pxa_rtc->sa1100_rtc.irq_1hz, ret);
goto err_irq_1Hz;
}
ret = request_irq(pxa_rtc->irq_Alrm, pxa_rtc_irq, 0,
ret = request_irq(pxa_rtc->sa1100_rtc.irq_alarm, pxa_rtc_irq, 0,
"rtc Alrm", dev);
if (ret < 0) {
dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_Alrm,
ret);
dev_err(dev, "can't get irq %i, err %d\n",
pxa_rtc->sa1100_rtc.irq_alarm, ret);
goto err_irq_Alrm;
}

return 0;

err_irq_Alrm:
free_irq(pxa_rtc->irq_1Hz, dev);
free_irq(pxa_rtc->sa1100_rtc.irq_1hz, dev);
err_irq_1Hz:
return ret;
}
Expand All @@ -215,8 +216,8 @@ static void pxa_rtc_release(struct device *dev)
rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE);
spin_unlock_irq(&pxa_rtc->lock);

free_irq(pxa_rtc->irq_Alrm, dev);
free_irq(pxa_rtc->irq_1Hz, dev);
free_irq(pxa_rtc->sa1100_rtc.irq_1hz, dev);
free_irq(pxa_rtc->sa1100_rtc.irq_alarm, dev);
}

static int pxa_alarm_irq_enable(struct device *dev, unsigned int enabled)
Expand Down Expand Up @@ -320,12 +321,13 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct pxa_rtc *pxa_rtc;
struct sa1100_rtc *sa1100_rtc;
int ret;
u32 rttr;

pxa_rtc = devm_kzalloc(dev, sizeof(*pxa_rtc), GFP_KERNEL);
if (!pxa_rtc)
return -ENOMEM;
sa1100_rtc = &pxa_rtc->sa1100_rtc;

spin_lock_init(&pxa_rtc->lock);
platform_set_drvdata(pdev, pxa_rtc);
Expand All @@ -336,13 +338,13 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
return -ENXIO;
}

pxa_rtc->irq_1Hz = platform_get_irq(pdev, 0);
if (pxa_rtc->irq_1Hz < 0) {
sa1100_rtc->irq_1hz = platform_get_irq(pdev, 0);
if (sa1100_rtc->irq_1hz < 0) {
dev_err(dev, "No 1Hz IRQ resource defined\n");
return -ENXIO;
}
pxa_rtc->irq_Alrm = platform_get_irq(pdev, 1);
if (pxa_rtc->irq_Alrm < 0) {
sa1100_rtc->irq_alarm = platform_get_irq(pdev, 1);
if (sa1100_rtc->irq_alarm < 0) {
dev_err(dev, "No alarm IRQ resource defined\n");
return -ENXIO;
}
Expand All @@ -354,15 +356,10 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
}

/*
* If the clock divider is uninitialized then reset it to the
* default value to get the 1Hz clock.
*/
if (rtc_readl(pxa_rtc, RTTR) == 0) {
rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
rtc_writel(pxa_rtc, RTTR, rttr);
dev_warn(dev, "warning: initializing default clock"
" divider/trim value\n");
ret = sa1100_rtc_init(pdev, sa1100_rtc);
if (!ret) {
dev_err(dev, "Unable to init SA1100 RTC sub-device\n");
return ret;
}

rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE);
Expand Down Expand Up @@ -402,7 +399,7 @@ static int pxa_rtc_suspend(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);

if (device_may_wakeup(dev))
enable_irq_wake(pxa_rtc->irq_Alrm);
enable_irq_wake(pxa_rtc->sa1100_rtc.irq_alarm);
return 0;
}

Expand All @@ -411,7 +408,7 @@ static int pxa_rtc_resume(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);

if (device_may_wakeup(dev))
disable_irq_wake(pxa_rtc->irq_Alrm);
disable_irq_wake(pxa_rtc->sa1100_rtc.irq_alarm);
return 0;
}
#endif
Expand Down

0 comments on commit 3cdf4ad

Please sign in to comment.