aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-02-28 07:38:46 -0500
committerArnd Bergmann <arnd@arndb.de>2012-02-28 07:38:46 -0500
commit7169ff4a0942adf524f25713eaed30599d438926 (patch)
tree08e7077a48d2d5acd4008fec28a913e1d6ee29ee
parente135e4506c6d3e9b196890877a9a2815f71b04ac (diff)
parent4128e27584f58bce9f56a9a0346650c94a651332 (diff)
Merge branch 'rtc-sa1100' of git://github.com/hzhuang1/linux into next/drivers
* 'rtc-sa1100' of git://github.com/hzhuang1/linux: ARM: mmp: enable rtc in pxa910 rtc: sa1100: enable clk support ARM: pxa: add rtc dummy clock ARM: sa1100: clean up clock support rtc: sa1100: declare irq in resource rtc: sa1100: remove verification code of alarm rtc: sa1100: remove periodic code
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/mach-mmp/include/mach/pxa910.h1
-rw-r--r--arch/arm/mach-mmp/include/mach/regs-apbc.h1
-rw-r--r--arch/arm/mach-mmp/include/mach/regs-rtc.h23
-rw-r--r--arch/arm/mach-mmp/pxa910.c27
-rw-r--r--arch/arm/mach-mmp/ttc_dkb.c1
-rw-r--r--arch/arm/mach-pxa/devices.c28
-rw-r--r--arch/arm/mach-pxa/pxa25x.c1
-rw-r--r--arch/arm/mach-pxa/pxa27x.c1
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c1
-rw-r--r--arch/arm/mach-pxa/pxa95x.c1
-rw-r--r--arch/arm/mach-sa1100/clock.c82
-rw-r--r--arch/arm/mach-sa1100/generic.c8
-rw-r--r--drivers/rtc/Kconfig4
-rw-r--r--drivers/rtc/rtc-sa1100.c198
15 files changed, 234 insertions, 145 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 92c9c79c140c..baf6dc6e9a1b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -754,7 +754,7 @@ config ARCH_SA1100
754 select ARCH_HAS_CPUFREQ 754 select ARCH_HAS_CPUFREQ
755 select CPU_FREQ 755 select CPU_FREQ
756 select GENERIC_CLOCKEVENTS 756 select GENERIC_CLOCKEVENTS
757 select HAVE_CLK 757 select CLKDEV_LOOKUP
758 select HAVE_SCHED_CLOCK 758 select HAVE_SCHED_CLOCK
759 select TICK_ONESHOT 759 select TICK_ONESHOT
760 select ARCH_REQUIRE_GPIOLIB 760 select ARCH_REQUIRE_GPIOLIB
diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h
index 4de13abef7bb..e2e1f1e5e124 100644
--- a/arch/arm/mach-mmp/include/mach/pxa910.h
+++ b/arch/arm/mach-mmp/include/mach/pxa910.h
@@ -22,6 +22,7 @@ extern struct pxa_device_desc pxa910_device_pwm4;
22extern struct pxa_device_desc pxa910_device_nand; 22extern struct pxa_device_desc pxa910_device_nand;
23 23
24extern struct platform_device pxa910_device_gpio; 24extern struct platform_device pxa910_device_gpio;
25extern struct platform_device pxa910_device_rtc;
25 26
26static inline int pxa910_add_uart(int id) 27static inline int pxa910_add_uart(int id)
27{ 28{
diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h
index 1a96585336ba..8a37fb003655 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apbc.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h
@@ -57,6 +57,7 @@
57#define APBC_PXA910_SSP1 APBC_REG(0x01c) 57#define APBC_PXA910_SSP1 APBC_REG(0x01c)
58#define APBC_PXA910_SSP2 APBC_REG(0x020) 58#define APBC_PXA910_SSP2 APBC_REG(0x020)
59#define APBC_PXA910_IPC APBC_REG(0x024) 59#define APBC_PXA910_IPC APBC_REG(0x024)
60#define APBC_PXA910_RTC APBC_REG(0x028)
60#define APBC_PXA910_TWSI0 APBC_REG(0x02c) 61#define APBC_PXA910_TWSI0 APBC_REG(0x02c)
61#define APBC_PXA910_KPC APBC_REG(0x030) 62#define APBC_PXA910_KPC APBC_REG(0x030)
62#define APBC_PXA910_TIMERS APBC_REG(0x034) 63#define APBC_PXA910_TIMERS APBC_REG(0x034)
diff --git a/arch/arm/mach-mmp/include/mach/regs-rtc.h b/arch/arm/mach-mmp/include/mach/regs-rtc.h
new file mode 100644
index 000000000000..5bff886a3941
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/regs-rtc.h
@@ -0,0 +1,23 @@
1#ifndef __ASM_MACH_REGS_RTC_H
2#define __ASM_MACH_REGS_RTC_H
3
4#include <mach/addr-map.h>
5
6#define RTC_VIRT_BASE (APB_VIRT_BASE + 0x10000)
7#define RTC_REG(x) (*((volatile u32 __iomem *)(RTC_VIRT_BASE + (x))))
8
9/*
10 * Real Time Clock
11 */
12
13#define RCNR RTC_REG(0x00) /* RTC Count Register */
14#define RTAR RTC_REG(0x04) /* RTC Alarm Register */
15#define RTSR RTC_REG(0x08) /* RTC Status Register */
16#define RTTR RTC_REG(0x0C) /* RTC Timer Trim Register */
17
18#define RTSR_HZE (1 << 3) /* HZ interrupt enable */
19#define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */
20#define RTSR_HZ (1 << 1) /* HZ rising-edge detected */
21#define RTSR_AL (1 << 0) /* RTC alarm detected */
22
23#endif /* __ASM_MACH_REGS_RTC_H */
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index 3241a25784d0..b6e152723974 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -92,6 +92,7 @@ static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000);
92static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000); 92static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000);
93static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000); 93static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000);
94static APBC_CLK(gpio, PXA910_GPIO, 0, 13000000); 94static APBC_CLK(gpio, PXA910_GPIO, 0, 13000000);
95static APBC_CLK(rtc, PXA910_RTC, 8, 32768);
95 96
96static APMU_CLK(nand, NAND, 0x19b, 156000000); 97static APMU_CLK(nand, NAND, 0x19b, 156000000);
97static APMU_CLK(u2o, USB, 0x1b, 480000000); 98static APMU_CLK(u2o, USB, 0x1b, 480000000);
@@ -109,6 +110,7 @@ static struct clk_lookup pxa910_clkregs[] = {
109 INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL), 110 INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
110 INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL), 111 INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL),
111 INIT_CLKREG(&clk_u2o, "pxa-u2o", "U2OCLK"), 112 INIT_CLKREG(&clk_u2o, "pxa-u2o", "U2OCLK"),
113 INIT_CLKREG(&clk_rtc, "sa1100-rtc", NULL),
112}; 114};
113 115
114static int __init pxa910_init(void) 116static int __init pxa910_init(void)
@@ -183,3 +185,28 @@ struct platform_device pxa910_device_gpio = {
183 .num_resources = ARRAY_SIZE(pxa910_resource_gpio), 185 .num_resources = ARRAY_SIZE(pxa910_resource_gpio),
184 .resource = pxa910_resource_gpio, 186 .resource = pxa910_resource_gpio,
185}; 187};
188
189static struct resource pxa910_resource_rtc[] = {
190 {
191 .start = 0xd4010000,
192 .end = 0xd401003f,
193 .flags = IORESOURCE_MEM,
194 }, {
195 .start = IRQ_PXA910_RTC_INT,
196 .end = IRQ_PXA910_RTC_INT,
197 .name = "rtc 1Hz",
198 .flags = IORESOURCE_IRQ,
199 }, {
200 .start = IRQ_PXA910_RTC_ALARM,
201 .end = IRQ_PXA910_RTC_ALARM,
202 .name = "rtc alarm",
203 .flags = IORESOURCE_IRQ,
204 },
205};
206
207struct platform_device pxa910_device_rtc = {
208 .name = "sa1100-rtc",
209 .id = -1,
210 .num_resources = ARRAY_SIZE(pxa910_resource_rtc),
211 .resource = pxa910_resource_rtc,
212};
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index 5ac5d5832e45..e72c709da44f 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -124,6 +124,7 @@ static struct platform_device ttc_dkb_device_onenand = {
124 124
125static struct platform_device *ttc_dkb_devices[] = { 125static struct platform_device *ttc_dkb_devices[] = {
126 &pxa910_device_gpio, 126 &pxa910_device_gpio,
127 &pxa910_device_rtc,
127 &ttc_dkb_device_onenand, 128 &ttc_dkb_device_onenand,
128}; 129};
129 130
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 5bc13121eac5..84f2d7015cfe 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -406,20 +406,17 @@ static struct resource pxa_rtc_resources[] = {
406 [1] = { 406 [1] = {
407 .start = IRQ_RTC1Hz, 407 .start = IRQ_RTC1Hz,
408 .end = IRQ_RTC1Hz, 408 .end = IRQ_RTC1Hz,
409 .name = "rtc 1Hz",
409 .flags = IORESOURCE_IRQ, 410 .flags = IORESOURCE_IRQ,
410 }, 411 },
411 [2] = { 412 [2] = {
412 .start = IRQ_RTCAlrm, 413 .start = IRQ_RTCAlrm,
413 .end = IRQ_RTCAlrm, 414 .end = IRQ_RTCAlrm,
415 .name = "rtc alarm",
414 .flags = IORESOURCE_IRQ, 416 .flags = IORESOURCE_IRQ,
415 }, 417 },
416}; 418};
417 419
418struct platform_device sa1100_device_rtc = {
419 .name = "sa1100-rtc",
420 .id = -1,
421};
422
423struct platform_device pxa_device_rtc = { 420struct platform_device pxa_device_rtc = {
424 .name = "pxa-rtc", 421 .name = "pxa-rtc",
425 .id = -1, 422 .id = -1,
@@ -427,6 +424,27 @@ struct platform_device pxa_device_rtc = {
427 .resource = pxa_rtc_resources, 424 .resource = pxa_rtc_resources,
428}; 425};
429 426
427static struct resource sa1100_rtc_resources[] = {
428 {
429 .start = IRQ_RTC1Hz,
430 .end = IRQ_RTC1Hz,
431 .name = "rtc 1Hz",
432 .flags = IORESOURCE_IRQ,
433 }, {
434 .start = IRQ_RTCAlrm,
435 .end = IRQ_RTCAlrm,
436 .name = "rtc alarm",
437 .flags = IORESOURCE_IRQ,
438 },
439};
440
441struct platform_device sa1100_device_rtc = {
442 .name = "sa1100-rtc",
443 .id = -1,
444 .num_resources = ARRAY_SIZE(sa1100_rtc_resources),
445 .resource = sa1100_rtc_resources,
446};
447
430static struct resource pxa_ac97_resources[] = { 448static struct resource pxa_ac97_resources[] = {
431 [0] = { 449 [0] = {
432 .start = 0x40500000, 450 .start = 0x40500000,
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 91e4f6c03766..d43c1a7a7fd9 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -209,6 +209,7 @@ static struct clk_lookup pxa25x_clkregs[] = {
209 INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"), 209 INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"),
210 INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"), 210 INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"),
211 INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL), 211 INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL),
212 INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
212}; 213};
213 214
214static struct clk_lookup pxa25x_hwuart_clkreg = 215static struct clk_lookup pxa25x_hwuart_clkreg =
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index aed6cbcf3866..cf2f9d14a80c 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -230,6 +230,7 @@ static struct clk_lookup pxa27x_clkregs[] = {
230 INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"), 230 INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"),
231 INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"), 231 INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"),
232 INIT_CLKREG(&clk_pxa27x_mem, "pxa2xx-pcmcia", NULL), 232 INIT_CLKREG(&clk_pxa27x_mem, "pxa2xx-pcmcia", NULL),
233 INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
233}; 234};
234 235
235#ifdef CONFIG_PM 236#ifdef CONFIG_PM
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 4f402afa6609..881934899bda 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -89,6 +89,7 @@ static struct clk_lookup pxa3xx_clkregs[] = {
89 INIT_CLKREG(&clk_pxa3xx_mmc2, "pxa2xx-mci.1", NULL), 89 INIT_CLKREG(&clk_pxa3xx_mmc2, "pxa2xx-mci.1", NULL),
90 INIT_CLKREG(&clk_pxa3xx_smemc, "pxa2xx-pcmcia", NULL), 90 INIT_CLKREG(&clk_pxa3xx_smemc, "pxa2xx-pcmcia", NULL),
91 INIT_CLKREG(&clk_pxa3xx_gpio, "pxa-gpio", NULL), 91 INIT_CLKREG(&clk_pxa3xx_gpio, "pxa-gpio", NULL),
92 INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
92}; 93};
93 94
94#ifdef CONFIG_PM 95#ifdef CONFIG_PM
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
index d082a583df78..35023d7d3cd4 100644
--- a/arch/arm/mach-pxa/pxa95x.c
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -231,6 +231,7 @@ static struct clk_lookup pxa95x_clkregs[] = {
231 INIT_CLKREG(&clk_pxa95x_pwm0, "pxa27x-pwm.0", NULL), 231 INIT_CLKREG(&clk_pxa95x_pwm0, "pxa27x-pwm.0", NULL),
232 INIT_CLKREG(&clk_pxa95x_pwm1, "pxa27x-pwm.1", NULL), 232 INIT_CLKREG(&clk_pxa95x_pwm1, "pxa27x-pwm.1", NULL),
233 INIT_CLKREG(&clk_pxa95x_gpio, "pxa-gpio", NULL), 233 INIT_CLKREG(&clk_pxa95x_gpio, "pxa-gpio", NULL),
234 INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
234}; 235};
235 236
236void __init pxa95x_init_irq(void) 237void __init pxa95x_init_irq(void)
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
index dab3c6347a8f..172ebd0ee0a2 100644
--- a/arch/arm/mach-sa1100/clock.c
+++ b/arch/arm/mach-sa1100/clock.c
@@ -11,17 +11,29 @@
11#include <linux/clk.h> 11#include <linux/clk.h>
12#include <linux/spinlock.h> 12#include <linux/spinlock.h>
13#include <linux/mutex.h> 13#include <linux/mutex.h>
14#include <linux/io.h>
15#include <linux/clkdev.h>
14 16
15#include <mach/hardware.h> 17#include <mach/hardware.h>
16 18
17/* 19struct clkops {
18 * Very simple clock implementation - we only have one clock to deal with. 20 void (*enable)(struct clk *);
19 */ 21 void (*disable)(struct clk *);
22};
23
20struct clk { 24struct clk {
25 const struct clkops *ops;
21 unsigned int enabled; 26 unsigned int enabled;
22}; 27};
23 28
24static void clk_gpio27_enable(void) 29#define DEFINE_CLK(_name, _ops) \
30struct clk clk_##_name = { \
31 .ops = _ops, \
32 }
33
34static DEFINE_SPINLOCK(clocks_lock);
35
36static void clk_gpio27_enable(struct clk *clk)
25{ 37{
26 /* 38 /*
27 * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: 39 * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
@@ -32,38 +44,24 @@ static void clk_gpio27_enable(void)
32 TUCR = TUCR_3_6864MHz; 44 TUCR = TUCR_3_6864MHz;
33} 45}
34 46
35static void clk_gpio27_disable(void) 47static void clk_gpio27_disable(struct clk *clk)
36{ 48{
37 TUCR = 0; 49 TUCR = 0;
38 GPDR &= ~GPIO_32_768kHz; 50 GPDR &= ~GPIO_32_768kHz;
39 GAFR &= ~GPIO_32_768kHz; 51 GAFR &= ~GPIO_32_768kHz;
40} 52}
41 53
42static struct clk clk_gpio27;
43
44static DEFINE_SPINLOCK(clocks_lock);
45
46struct clk *clk_get(struct device *dev, const char *id)
47{
48 const char *devname = dev_name(dev);
49
50 return strcmp(devname, "sa1111.0") ? ERR_PTR(-ENOENT) : &clk_gpio27;
51}
52EXPORT_SYMBOL(clk_get);
53
54void clk_put(struct clk *clk)
55{
56}
57EXPORT_SYMBOL(clk_put);
58
59int clk_enable(struct clk *clk) 54int clk_enable(struct clk *clk)
60{ 55{
61 unsigned long flags; 56 unsigned long flags;
62 57
63 spin_lock_irqsave(&clocks_lock, flags); 58 if (clk) {
64 if (clk->enabled++ == 0) 59 spin_lock_irqsave(&clocks_lock, flags);
65 clk_gpio27_enable(); 60 if (clk->enabled++ == 0)
66 spin_unlock_irqrestore(&clocks_lock, flags); 61 clk->ops->enable(clk);
62 spin_unlock_irqrestore(&clocks_lock, flags);
63 }
64
67 return 0; 65 return 0;
68} 66}
69EXPORT_SYMBOL(clk_enable); 67EXPORT_SYMBOL(clk_enable);
@@ -72,17 +70,31 @@ void clk_disable(struct clk *clk)
72{ 70{
73 unsigned long flags; 71 unsigned long flags;
74 72
75 WARN_ON(clk->enabled == 0); 73 if (clk) {
76 74 WARN_ON(clk->enabled == 0);
77 spin_lock_irqsave(&clocks_lock, flags); 75 spin_lock_irqsave(&clocks_lock, flags);
78 if (--clk->enabled == 0) 76 if (--clk->enabled == 0)
79 clk_gpio27_disable(); 77 clk->ops->disable(clk);
80 spin_unlock_irqrestore(&clocks_lock, flags); 78 spin_unlock_irqrestore(&clocks_lock, flags);
79 }
81} 80}
82EXPORT_SYMBOL(clk_disable); 81EXPORT_SYMBOL(clk_disable);
83 82
84unsigned long clk_get_rate(struct clk *clk) 83const struct clkops clk_gpio27_ops = {
84 .enable = clk_gpio27_enable,
85 .disable = clk_gpio27_disable,
86};
87
88static DEFINE_CLK(gpio27, &clk_gpio27_ops);
89
90static struct clk_lookup sa11xx_clkregs[] = {
91 CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27),
92 CLKDEV_INIT("sa1100-rtc", NULL, NULL),
93};
94
95static int __init sa11xx_clk_init(void)
85{ 96{
86 return 3686400; 97 clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
98 return 0;
87} 99}
88EXPORT_SYMBOL(clk_get_rate); 100core_initcall(sa11xx_clk_init);
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index bb10ee2cb89f..7c1ebf4a7920 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -345,9 +345,17 @@ void sa11x0_register_irda(struct irda_platform_data *irda)
345 sa11x0_register_device(&sa11x0ir_device, irda); 345 sa11x0_register_device(&sa11x0ir_device, irda);
346} 346}
347 347
348static struct resource sa1100_rtc_resources[] = {
349 DEFINE_RES_MEM(0x90010000, 0x9001003f),
350 DEFINE_RES_IRQ_NAMED(IRQ_RTC1Hz, "rtc 1Hz"),
351 DEFINE_RES_IRQ_NAMED(IRQ_RTCAlrm, "rtc alarm"),
352};
353
348static struct platform_device sa11x0rtc_device = { 354static struct platform_device sa11x0rtc_device = {
349 .name = "sa1100-rtc", 355 .name = "sa1100-rtc",
350 .id = -1, 356 .id = -1,
357 .num_resources = ARRAY_SIZE(sa1100_rtc_resources),
358 .resource = sa1100_rtc_resources,
351}; 359};
352 360
353static struct platform_device *sa11x0_devices[] __initdata = { 361static struct platform_device *sa11x0_devices[] __initdata = {
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 3a125b835546..59efc63c4e48 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -773,8 +773,8 @@ config RTC_DRV_EP93XX
773 will be called rtc-ep93xx. 773 will be called rtc-ep93xx.
774 774
775config RTC_DRV_SA1100 775config RTC_DRV_SA1100
776 tristate "SA11x0/PXA2xx" 776 tristate "SA11x0/PXA2xx/PXA910"
777 depends on ARCH_SA1100 || ARCH_PXA 777 depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP
778 help 778 help
779 If you say Y here you will get access to the real time clock 779 If you say Y here you will get access to the real time clock
780 built into your SA11x0 or PXA2xx CPU. 780 built into your SA11x0 or PXA2xx CPU.
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index cb9a585312cc..962510cf726f 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -23,10 +23,12 @@
23 23
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/clk.h>
26#include <linux/rtc.h> 27#include <linux/rtc.h>
27#include <linux/init.h> 28#include <linux/init.h>
28#include <linux/fs.h> 29#include <linux/fs.h>
29#include <linux/interrupt.h> 30#include <linux/interrupt.h>
31#include <linux/slab.h>
30#include <linux/string.h> 32#include <linux/string.h>
31#include <linux/pm.h> 33#include <linux/pm.h>
32#include <linux/bitops.h> 34#include <linux/bitops.h>
@@ -34,83 +36,30 @@
34#include <mach/hardware.h> 36#include <mach/hardware.h>
35#include <asm/irq.h> 37#include <asm/irq.h>
36 38
37#ifdef CONFIG_ARCH_PXA 39#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
38#include <mach/regs-rtc.h> 40#include <mach/regs-rtc.h>
39#endif 41#endif
40 42
41#define RTC_DEF_DIVIDER (32768 - 1) 43#define RTC_DEF_DIVIDER (32768 - 1)
42#define RTC_DEF_TRIM 0 44#define RTC_DEF_TRIM 0
43 45#define RTC_FREQ 1024
44static const unsigned long RTC_FREQ = 1024; 46
45static struct rtc_time rtc_alarm; 47struct sa1100_rtc {
46static DEFINE_SPINLOCK(sa1100_rtc_lock); 48 spinlock_t lock;
47 49 int irq_1hz;
48static inline int rtc_periodic_alarm(struct rtc_time *tm) 50 int irq_alarm;
49{ 51 struct rtc_device *rtc;
50 return (tm->tm_year == -1) || 52 struct clk *clk;
51 ((unsigned)tm->tm_mon >= 12) || 53};
52 ((unsigned)(tm->tm_mday - 1) >= 31) ||
53 ((unsigned)tm->tm_hour > 23) ||
54 ((unsigned)tm->tm_min > 59) ||
55 ((unsigned)tm->tm_sec > 59);
56}
57
58/*
59 * Calculate the next alarm time given the requested alarm time mask
60 * and the current time.
61 */
62static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
63 struct rtc_time *alrm)
64{
65 unsigned long next_time;
66 unsigned long now_time;
67
68 next->tm_year = now->tm_year;
69 next->tm_mon = now->tm_mon;
70 next->tm_mday = now->tm_mday;
71 next->tm_hour = alrm->tm_hour;
72 next->tm_min = alrm->tm_min;
73 next->tm_sec = alrm->tm_sec;
74
75 rtc_tm_to_time(now, &now_time);
76 rtc_tm_to_time(next, &next_time);
77
78 if (next_time < now_time) {
79 /* Advance one day */
80 next_time += 60 * 60 * 24;
81 rtc_time_to_tm(next_time, next);
82 }
83}
84
85static int rtc_update_alarm(struct rtc_time *alrm)
86{
87 struct rtc_time alarm_tm, now_tm;
88 unsigned long now, time;
89 int ret;
90
91 do {
92 now = RCNR;
93 rtc_time_to_tm(now, &now_tm);
94 rtc_next_alarm_time(&alarm_tm, &now_tm, alrm);
95 ret = rtc_tm_to_time(&alarm_tm, &time);
96 if (ret != 0)
97 break;
98
99 RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
100 RTAR = time;
101 } while (now != RCNR);
102
103 return ret;
104}
105 54
106static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) 55static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
107{ 56{
108 struct platform_device *pdev = to_platform_device(dev_id); 57 struct sa1100_rtc *info = dev_get_drvdata(dev_id);
109 struct rtc_device *rtc = platform_get_drvdata(pdev); 58 struct rtc_device *rtc = info->rtc;
110 unsigned int rtsr; 59 unsigned int rtsr;
111 unsigned long events = 0; 60 unsigned long events = 0;
112 61
113 spin_lock(&sa1100_rtc_lock); 62 spin_lock(&info->lock);
114 63
115 rtsr = RTSR; 64 rtsr = RTSR;
116 /* clear interrupt sources */ 65 /* clear interrupt sources */
@@ -146,30 +95,30 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
146 95
147 rtc_update_irq(rtc, 1, events); 96 rtc_update_irq(rtc, 1, events);
148 97
149 if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) 98 spin_unlock(&info->lock);
150 rtc_update_alarm(&rtc_alarm);
151
152 spin_unlock(&sa1100_rtc_lock);
153 99
154 return IRQ_HANDLED; 100 return IRQ_HANDLED;
155} 101}
156 102
157static int sa1100_rtc_open(struct device *dev) 103static int sa1100_rtc_open(struct device *dev)
158{ 104{
105 struct sa1100_rtc *info = dev_get_drvdata(dev);
106 struct rtc_device *rtc = info->rtc;
159 int ret; 107 int ret;
160 struct platform_device *plat_dev = to_platform_device(dev);
161 struct rtc_device *rtc = platform_get_drvdata(plat_dev);
162 108
163 ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, 109 ret = clk_prepare_enable(info->clk);
110 if (ret)
111 goto fail_clk;
112 ret = request_irq(info->irq_1hz, sa1100_rtc_interrupt, IRQF_DISABLED,
164 "rtc 1Hz", dev); 113 "rtc 1Hz", dev);
165 if (ret) { 114 if (ret) {
166 dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); 115 dev_err(dev, "IRQ %d already in use.\n", info->irq_1hz);
167 goto fail_ui; 116 goto fail_ui;
168 } 117 }
169 ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED, 118 ret = request_irq(info->irq_alarm, sa1100_rtc_interrupt, IRQF_DISABLED,
170 "rtc Alrm", dev); 119 "rtc Alrm", dev);
171 if (ret) { 120 if (ret) {
172 dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); 121 dev_err(dev, "IRQ %d already in use.\n", info->irq_alarm);
173 goto fail_ai; 122 goto fail_ai;
174 } 123 }
175 rtc->max_user_freq = RTC_FREQ; 124 rtc->max_user_freq = RTC_FREQ;
@@ -178,29 +127,36 @@ static int sa1100_rtc_open(struct device *dev)
178 return 0; 127 return 0;
179 128
180 fail_ai: 129 fail_ai:
181 free_irq(IRQ_RTC1Hz, dev); 130 free_irq(info->irq_1hz, dev);
182 fail_ui: 131 fail_ui:
132 clk_disable_unprepare(info->clk);
133 fail_clk:
183 return ret; 134 return ret;
184} 135}
185 136
186static void sa1100_rtc_release(struct device *dev) 137static void sa1100_rtc_release(struct device *dev)
187{ 138{
188 spin_lock_irq(&sa1100_rtc_lock); 139 struct sa1100_rtc *info = dev_get_drvdata(dev);
140
141 spin_lock_irq(&info->lock);
189 RTSR = 0; 142 RTSR = 0;
190 spin_unlock_irq(&sa1100_rtc_lock); 143 spin_unlock_irq(&info->lock);
191 144
192 free_irq(IRQ_RTCAlrm, dev); 145 free_irq(info->irq_alarm, dev);
193 free_irq(IRQ_RTC1Hz, dev); 146 free_irq(info->irq_1hz, dev);
147 clk_disable_unprepare(info->clk);
194} 148}
195 149
196static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) 150static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
197{ 151{
198 spin_lock_irq(&sa1100_rtc_lock); 152 struct sa1100_rtc *info = dev_get_drvdata(dev);
153
154 spin_lock_irq(&info->lock);
199 if (enabled) 155 if (enabled)
200 RTSR |= RTSR_ALE; 156 RTSR |= RTSR_ALE;
201 else 157 else
202 RTSR &= ~RTSR_ALE; 158 RTSR &= ~RTSR_ALE;
203 spin_unlock_irq(&sa1100_rtc_lock); 159 spin_unlock_irq(&info->lock);
204 return 0; 160 return 0;
205} 161}
206 162
@@ -225,7 +181,6 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
225{ 181{
226 u32 rtsr; 182 u32 rtsr;
227 183
228 memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
229 rtsr = RTSR; 184 rtsr = RTSR;
230 alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0; 185 alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
231 alrm->pending = (rtsr & RTSR_AL) ? 1 : 0; 186 alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
@@ -234,17 +189,22 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
234 189
235static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 190static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
236{ 191{
192 struct sa1100_rtc *info = dev_get_drvdata(dev);
193 unsigned long time;
237 int ret; 194 int ret;
238 195
239 spin_lock_irq(&sa1100_rtc_lock); 196 spin_lock_irq(&info->lock);
240 ret = rtc_update_alarm(&alrm->time); 197 ret = rtc_tm_to_time(&alrm->time, &time);
241 if (ret == 0) { 198 if (ret != 0)
242 if (alrm->enabled) 199 goto out;
243 RTSR |= RTSR_ALE; 200 RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
244 else 201 RTAR = time;
245 RTSR &= ~RTSR_ALE; 202 if (alrm->enabled)
246 } 203 RTSR |= RTSR_ALE;
247 spin_unlock_irq(&sa1100_rtc_lock); 204 else
205 RTSR &= ~RTSR_ALE;
206out:
207 spin_unlock_irq(&info->lock);
248 208
249 return ret; 209 return ret;
250} 210}
@@ -271,6 +231,27 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
271static int sa1100_rtc_probe(struct platform_device *pdev) 231static int sa1100_rtc_probe(struct platform_device *pdev)
272{ 232{
273 struct rtc_device *rtc; 233 struct rtc_device *rtc;
234 struct sa1100_rtc *info;
235 int irq_1hz, irq_alarm, ret = 0;
236
237 irq_1hz = platform_get_irq_byname(pdev, "rtc 1Hz");
238 irq_alarm = platform_get_irq_byname(pdev, "rtc alarm");
239 if (irq_1hz < 0 || irq_alarm < 0)
240 return -ENODEV;
241
242 info = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL);
243 if (!info)
244 return -ENOMEM;
245 info->clk = clk_get(&pdev->dev, NULL);
246 if (IS_ERR(info->clk)) {
247 dev_err(&pdev->dev, "failed to find rtc clock source\n");
248 ret = PTR_ERR(info->clk);
249 goto err_clk;
250 }
251 info->irq_1hz = irq_1hz;
252 info->irq_alarm = irq_alarm;
253 spin_lock_init(&info->lock);
254 platform_set_drvdata(pdev, info);
274 255
275 /* 256 /*
276 * According to the manual we should be able to let RTTR be zero 257 * According to the manual we should be able to let RTTR be zero
@@ -292,10 +273,11 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
292 rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, 273 rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
293 THIS_MODULE); 274 THIS_MODULE);
294 275
295 if (IS_ERR(rtc)) 276 if (IS_ERR(rtc)) {
296 return PTR_ERR(rtc); 277 ret = PTR_ERR(rtc);
297 278 goto err_dev;
298 platform_set_drvdata(pdev, rtc); 279 }
280 info->rtc = rtc;
299 281
300 /* Fix for a nasty initialization problem the in SA11xx RTSR register. 282 /* Fix for a nasty initialization problem the in SA11xx RTSR register.
301 * See also the comments in sa1100_rtc_interrupt(). 283 * See also the comments in sa1100_rtc_interrupt().
@@ -322,14 +304,24 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
322 RTSR = RTSR_AL | RTSR_HZ; 304 RTSR = RTSR_AL | RTSR_HZ;
323 305
324 return 0; 306 return 0;
307err_dev:
308 platform_set_drvdata(pdev, NULL);
309 clk_put(info->clk);
310err_clk:
311 kfree(info);
312 return ret;
325} 313}
326 314
327static int sa1100_rtc_remove(struct platform_device *pdev) 315static int sa1100_rtc_remove(struct platform_device *pdev)
328{ 316{
329 struct rtc_device *rtc = platform_get_drvdata(pdev); 317 struct sa1100_rtc *info = platform_get_drvdata(pdev);
330 318
331 if (rtc) 319 if (info) {
332 rtc_device_unregister(rtc); 320 rtc_device_unregister(info->rtc);
321 clk_put(info->clk);
322 platform_set_drvdata(pdev, NULL);
323 kfree(info);
324 }
333 325
334 return 0; 326 return 0;
335} 327}
@@ -337,15 +329,17 @@ static int sa1100_rtc_remove(struct platform_device *pdev)
337#ifdef CONFIG_PM 329#ifdef CONFIG_PM
338static int sa1100_rtc_suspend(struct device *dev) 330static int sa1100_rtc_suspend(struct device *dev)
339{ 331{
332 struct sa1100_rtc *info = dev_get_drvdata(dev);
340 if (device_may_wakeup(dev)) 333 if (device_may_wakeup(dev))
341 enable_irq_wake(IRQ_RTCAlrm); 334 enable_irq_wake(info->irq_alarm);
342 return 0; 335 return 0;
343} 336}
344 337
345static int sa1100_rtc_resume(struct device *dev) 338static int sa1100_rtc_resume(struct device *dev)
346{ 339{
340 struct sa1100_rtc *info = dev_get_drvdata(dev);
347 if (device_may_wakeup(dev)) 341 if (device_may_wakeup(dev))
348 disable_irq_wake(IRQ_RTCAlrm); 342 disable_irq_wake(info->irq_alarm);
349 return 0; 343 return 0;
350} 344}
351 345