diff options
author | Arnd Bergmann <arnd@arndb.de> | 2012-02-28 07:38:46 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2012-02-28 07:38:46 -0500 |
commit | 7169ff4a0942adf524f25713eaed30599d438926 (patch) | |
tree | 08e7077a48d2d5acd4008fec28a913e1d6ee29ee | |
parent | e135e4506c6d3e9b196890877a9a2815f71b04ac (diff) | |
parent | 4128e27584f58bce9f56a9a0346650c94a651332 (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/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-mmp/include/mach/pxa910.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-mmp/include/mach/regs-apbc.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-mmp/include/mach/regs-rtc.h | 23 | ||||
-rw-r--r-- | arch/arm/mach-mmp/pxa910.c | 27 | ||||
-rw-r--r-- | arch/arm/mach-mmp/ttc_dkb.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/devices.c | 28 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa25x.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa3xx.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa95x.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/clock.c | 82 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/generic.c | 8 | ||||
-rw-r--r-- | drivers/rtc/Kconfig | 4 | ||||
-rw-r--r-- | drivers/rtc/rtc-sa1100.c | 198 |
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; | |||
22 | extern struct pxa_device_desc pxa910_device_nand; | 22 | extern struct pxa_device_desc pxa910_device_nand; |
23 | 23 | ||
24 | extern struct platform_device pxa910_device_gpio; | 24 | extern struct platform_device pxa910_device_gpio; |
25 | extern struct platform_device pxa910_device_rtc; | ||
25 | 26 | ||
26 | static inline int pxa910_add_uart(int id) | 27 | static 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); | |||
92 | static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000); | 92 | static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000); |
93 | static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000); | 93 | static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000); |
94 | static APBC_CLK(gpio, PXA910_GPIO, 0, 13000000); | 94 | static APBC_CLK(gpio, PXA910_GPIO, 0, 13000000); |
95 | static APBC_CLK(rtc, PXA910_RTC, 8, 32768); | ||
95 | 96 | ||
96 | static APMU_CLK(nand, NAND, 0x19b, 156000000); | 97 | static APMU_CLK(nand, NAND, 0x19b, 156000000); |
97 | static APMU_CLK(u2o, USB, 0x1b, 480000000); | 98 | static 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 | ||
114 | static int __init pxa910_init(void) | 116 | static 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 | |||
189 | static 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 | |||
207 | struct 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 | ||
125 | static struct platform_device *ttc_dkb_devices[] = { | 125 | static 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 | ||
418 | struct platform_device sa1100_device_rtc = { | ||
419 | .name = "sa1100-rtc", | ||
420 | .id = -1, | ||
421 | }; | ||
422 | |||
423 | struct platform_device pxa_device_rtc = { | 420 | struct 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 | ||
427 | static 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 | |||
441 | struct 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 | |||
430 | static struct resource pxa_ac97_resources[] = { | 448 | static 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 | ||
214 | static struct clk_lookup pxa25x_hwuart_clkreg = | 215 | static 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 | ||
236 | void __init pxa95x_init_irq(void) | 237 | void __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 | /* | 19 | struct 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 | |||
20 | struct clk { | 24 | struct clk { |
25 | const struct clkops *ops; | ||
21 | unsigned int enabled; | 26 | unsigned int enabled; |
22 | }; | 27 | }; |
23 | 28 | ||
24 | static void clk_gpio27_enable(void) | 29 | #define DEFINE_CLK(_name, _ops) \ |
30 | struct clk clk_##_name = { \ | ||
31 | .ops = _ops, \ | ||
32 | } | ||
33 | |||
34 | static DEFINE_SPINLOCK(clocks_lock); | ||
35 | |||
36 | static 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 | ||
35 | static void clk_gpio27_disable(void) | 47 | static 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 | ||
42 | static struct clk clk_gpio27; | ||
43 | |||
44 | static DEFINE_SPINLOCK(clocks_lock); | ||
45 | |||
46 | struct 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 | } | ||
52 | EXPORT_SYMBOL(clk_get); | ||
53 | |||
54 | void clk_put(struct clk *clk) | ||
55 | { | ||
56 | } | ||
57 | EXPORT_SYMBOL(clk_put); | ||
58 | |||
59 | int clk_enable(struct clk *clk) | 54 | int 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 | } |
69 | EXPORT_SYMBOL(clk_enable); | 67 | EXPORT_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 | } |
82 | EXPORT_SYMBOL(clk_disable); | 81 | EXPORT_SYMBOL(clk_disable); |
83 | 82 | ||
84 | unsigned long clk_get_rate(struct clk *clk) | 83 | const struct clkops clk_gpio27_ops = { |
84 | .enable = clk_gpio27_enable, | ||
85 | .disable = clk_gpio27_disable, | ||
86 | }; | ||
87 | |||
88 | static DEFINE_CLK(gpio27, &clk_gpio27_ops); | ||
89 | |||
90 | static struct clk_lookup sa11xx_clkregs[] = { | ||
91 | CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27), | ||
92 | CLKDEV_INIT("sa1100-rtc", NULL, NULL), | ||
93 | }; | ||
94 | |||
95 | static 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 | } |
88 | EXPORT_SYMBOL(clk_get_rate); | 100 | core_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 | ||
348 | static 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 | |||
348 | static struct platform_device sa11x0rtc_device = { | 354 | static 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 | ||
353 | static struct platform_device *sa11x0_devices[] __initdata = { | 361 | static 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 | ||
775 | config RTC_DRV_SA1100 | 775 | config 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 | |
44 | static const unsigned long RTC_FREQ = 1024; | 46 | |
45 | static struct rtc_time rtc_alarm; | 47 | struct sa1100_rtc { |
46 | static DEFINE_SPINLOCK(sa1100_rtc_lock); | 48 | spinlock_t lock; |
47 | 49 | int irq_1hz; | |
48 | static 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 | */ | ||
62 | static 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 | |||
85 | static 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 | ||
106 | static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) | 55 | static 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 | ||
157 | static int sa1100_rtc_open(struct device *dev) | 103 | static 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 | ||
186 | static void sa1100_rtc_release(struct device *dev) | 137 | static 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 | ||
196 | static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 150 | static 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 | ||
235 | static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 190 | static 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; | ||
206 | out: | ||
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 = { | |||
271 | static int sa1100_rtc_probe(struct platform_device *pdev) | 231 | static 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; |
307 | err_dev: | ||
308 | platform_set_drvdata(pdev, NULL); | ||
309 | clk_put(info->clk); | ||
310 | err_clk: | ||
311 | kfree(info); | ||
312 | return ret; | ||
325 | } | 313 | } |
326 | 314 | ||
327 | static int sa1100_rtc_remove(struct platform_device *pdev) | 315 | static 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 |
338 | static int sa1100_rtc_suspend(struct device *dev) | 330 | static 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 | ||
345 | static int sa1100_rtc_resume(struct device *dev) | 338 | static 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 | ||