diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-22 12:30:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-22 12:30:52 -0400 |
commit | b324c67d4800e59171f48d9ddab6cbfb59110482 (patch) | |
tree | a16509a710e76fa24c01514b60aed06b7db13716 /arch/arm/mach-mmp/time.c | |
parent | 8dca6010d44cc722a94dc6da96560f9083dac782 (diff) | |
parent | 396d81cd0fe12ce5d1f6d159f093f9315d2837bc (diff) |
Merge tag 'dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull device tree conversions for arm-soc, part 1, from Olof Johansson:
"The spear3xx, lpc32xx, shmobile and mmp platforms are joining the game
of booting using device trees, which is a great step forward for them.
at91 and spear have pretty much completed this process with a huge
amount of work being put into at91. The other platforms are
continuing the process.
We finally start to see the payback on this investment, as new
machines are getting supported purely by adding a .dts source file
that can be completely independent of the kernel source."
Fix up trivial conflict in arch/arm/Kconfig
* tag 'dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (83 commits)
ARM: at91: Add ADC driver to at91sam9260/at91sam9g20 dtsi files
arm/dts: omap4-panda: Add LEDs support
arm/dts: omap4-sdp: Add LEDs support
arm/dts: twl4030: Add twl4030-gpio node
OMAP4: devices: Do not create mcpdm device if the dtb has been provided
OMAP4: devices: Do not create dmic device if the dtb has been provided
Documentation: update docs for mmp dt
ARM: dts: refresh dts file for arch mmp
ARM: mmp: support pxa910 with device tree
ARM: mmp: support mmp2 with device tree
gpio: pxa: parse gpio from DTS file
ARM: mmp: support DT in timer
ARM: mmp: support DT in irq
ARM: mmp: append CONFIG_MACH_MMP2_DT
ARM: mmp: fix build issue on mmp with device tree
ARM: ux500: Enable PRCMU Timer 4 (clocksource) for Device Tree
ARM: ux500: Disable SMSC911x platform code registration when DT is enabled
ARM: ux500: Fork cpu-db8500 platform_devs for sequential DT enablement
ARM: ux500: Do not attempt to register non-existent i2c devices on Snowball
ARM: SPEAr3xx: Correct keyboard data passed from DT
...
Diffstat (limited to 'arch/arm/mach-mmp/time.c')
-rw-r--r-- | arch/arm/mach-mmp/time.c | 81 |
1 files changed, 60 insertions, 21 deletions
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 71fc4ee4602..936447c7097 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c | |||
@@ -25,6 +25,9 @@ | |||
25 | 25 | ||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/irq.h> | 27 | #include <linux/irq.h> |
28 | #include <linux/of.h> | ||
29 | #include <linux/of_address.h> | ||
30 | #include <linux/of_irq.h> | ||
28 | 31 | ||
29 | #include <asm/sched_clock.h> | 32 | #include <asm/sched_clock.h> |
30 | #include <mach/addr-map.h> | 33 | #include <mach/addr-map.h> |
@@ -41,6 +44,8 @@ | |||
41 | #define MAX_DELTA (0xfffffffe) | 44 | #define MAX_DELTA (0xfffffffe) |
42 | #define MIN_DELTA (16) | 45 | #define MIN_DELTA (16) |
43 | 46 | ||
47 | static void __iomem *mmp_timer_base = TIMERS_VIRT_BASE; | ||
48 | |||
44 | /* | 49 | /* |
45 | * FIXME: the timer needs some delay to stablize the counter capture | 50 | * FIXME: the timer needs some delay to stablize the counter capture |
46 | */ | 51 | */ |
@@ -48,12 +53,12 @@ static inline uint32_t timer_read(void) | |||
48 | { | 53 | { |
49 | int delay = 100; | 54 | int delay = 100; |
50 | 55 | ||
51 | __raw_writel(1, TIMERS_VIRT_BASE + TMR_CVWR(1)); | 56 | __raw_writel(1, mmp_timer_base + TMR_CVWR(1)); |
52 | 57 | ||
53 | while (delay--) | 58 | while (delay--) |
54 | cpu_relax(); | 59 | cpu_relax(); |
55 | 60 | ||
56 | return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(1)); | 61 | return __raw_readl(mmp_timer_base + TMR_CVWR(1)); |
57 | } | 62 | } |
58 | 63 | ||
59 | static u32 notrace mmp_read_sched_clock(void) | 64 | static u32 notrace mmp_read_sched_clock(void) |
@@ -68,12 +73,12 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
68 | /* | 73 | /* |
69 | * Clear pending interrupt status. | 74 | * Clear pending interrupt status. |
70 | */ | 75 | */ |
71 | __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0)); | 76 | __raw_writel(0x01, mmp_timer_base + TMR_ICR(0)); |
72 | 77 | ||
73 | /* | 78 | /* |
74 | * Disable timer 0. | 79 | * Disable timer 0. |
75 | */ | 80 | */ |
76 | __raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER); | 81 | __raw_writel(0x02, mmp_timer_base + TMR_CER); |
77 | 82 | ||
78 | c->event_handler(c); | 83 | c->event_handler(c); |
79 | 84 | ||
@@ -90,23 +95,23 @@ static int timer_set_next_event(unsigned long delta, | |||
90 | /* | 95 | /* |
91 | * Disable timer 0. | 96 | * Disable timer 0. |
92 | */ | 97 | */ |
93 | __raw_writel(0x02, TIMERS_VIRT_BASE + TMR_CER); | 98 | __raw_writel(0x02, mmp_timer_base + TMR_CER); |
94 | 99 | ||
95 | /* | 100 | /* |
96 | * Clear and enable timer match 0 interrupt. | 101 | * Clear and enable timer match 0 interrupt. |
97 | */ | 102 | */ |
98 | __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_ICR(0)); | 103 | __raw_writel(0x01, mmp_timer_base + TMR_ICR(0)); |
99 | __raw_writel(0x01, TIMERS_VIRT_BASE + TMR_IER(0)); | 104 | __raw_writel(0x01, mmp_timer_base + TMR_IER(0)); |
100 | 105 | ||
101 | /* | 106 | /* |
102 | * Setup new clockevent timer value. | 107 | * Setup new clockevent timer value. |
103 | */ | 108 | */ |
104 | __raw_writel(delta - 1, TIMERS_VIRT_BASE + TMR_TN_MM(0, 0)); | 109 | __raw_writel(delta - 1, mmp_timer_base + TMR_TN_MM(0, 0)); |
105 | 110 | ||
106 | /* | 111 | /* |
107 | * Enable timer 0. | 112 | * Enable timer 0. |
108 | */ | 113 | */ |
109 | __raw_writel(0x03, TIMERS_VIRT_BASE + TMR_CER); | 114 | __raw_writel(0x03, mmp_timer_base + TMR_CER); |
110 | 115 | ||
111 | local_irq_restore(flags); | 116 | local_irq_restore(flags); |
112 | 117 | ||
@@ -124,7 +129,7 @@ static void timer_set_mode(enum clock_event_mode mode, | |||
124 | case CLOCK_EVT_MODE_UNUSED: | 129 | case CLOCK_EVT_MODE_UNUSED: |
125 | case CLOCK_EVT_MODE_SHUTDOWN: | 130 | case CLOCK_EVT_MODE_SHUTDOWN: |
126 | /* disable the matching interrupt */ | 131 | /* disable the matching interrupt */ |
127 | __raw_writel(0x00, TIMERS_VIRT_BASE + TMR_IER(0)); | 132 | __raw_writel(0x00, mmp_timer_base + TMR_IER(0)); |
128 | break; | 133 | break; |
129 | case CLOCK_EVT_MODE_RESUME: | 134 | case CLOCK_EVT_MODE_RESUME: |
130 | case CLOCK_EVT_MODE_PERIODIC: | 135 | case CLOCK_EVT_MODE_PERIODIC: |
@@ -157,27 +162,27 @@ static struct clocksource cksrc = { | |||
157 | 162 | ||
158 | static void __init timer_config(void) | 163 | static void __init timer_config(void) |
159 | { | 164 | { |
160 | uint32_t ccr = __raw_readl(TIMERS_VIRT_BASE + TMR_CCR); | 165 | uint32_t ccr = __raw_readl(mmp_timer_base + TMR_CCR); |
161 | 166 | ||
162 | __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_CER); /* disable */ | 167 | __raw_writel(0x0, mmp_timer_base + TMR_CER); /* disable */ |
163 | 168 | ||
164 | ccr &= (cpu_is_mmp2()) ? (TMR_CCR_CS_0(0) | TMR_CCR_CS_1(0)) : | 169 | ccr &= (cpu_is_mmp2()) ? (TMR_CCR_CS_0(0) | TMR_CCR_CS_1(0)) : |
165 | (TMR_CCR_CS_0(3) | TMR_CCR_CS_1(3)); | 170 | (TMR_CCR_CS_0(3) | TMR_CCR_CS_1(3)); |
166 | __raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR); | 171 | __raw_writel(ccr, mmp_timer_base + TMR_CCR); |
167 | 172 | ||
168 | /* set timer 0 to periodic mode, and timer 1 to free-running mode */ | 173 | /* set timer 0 to periodic mode, and timer 1 to free-running mode */ |
169 | __raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CMR); | 174 | __raw_writel(0x2, mmp_timer_base + TMR_CMR); |
170 | 175 | ||
171 | __raw_writel(0x1, TIMERS_VIRT_BASE + TMR_PLCR(0)); /* periodic */ | 176 | __raw_writel(0x1, mmp_timer_base + TMR_PLCR(0)); /* periodic */ |
172 | __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(0)); /* clear status */ | 177 | __raw_writel(0x7, mmp_timer_base + TMR_ICR(0)); /* clear status */ |
173 | __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(0)); | 178 | __raw_writel(0x0, mmp_timer_base + TMR_IER(0)); |
174 | 179 | ||
175 | __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_PLCR(1)); /* free-running */ | 180 | __raw_writel(0x0, mmp_timer_base + TMR_PLCR(1)); /* free-running */ |
176 | __raw_writel(0x7, TIMERS_VIRT_BASE + TMR_ICR(1)); /* clear status */ | 181 | __raw_writel(0x7, mmp_timer_base + TMR_ICR(1)); /* clear status */ |
177 | __raw_writel(0x0, TIMERS_VIRT_BASE + TMR_IER(1)); | 182 | __raw_writel(0x0, mmp_timer_base + TMR_IER(1)); |
178 | 183 | ||
179 | /* enable timer 1 counter */ | 184 | /* enable timer 1 counter */ |
180 | __raw_writel(0x2, TIMERS_VIRT_BASE + TMR_CER); | 185 | __raw_writel(0x2, mmp_timer_base + TMR_CER); |
181 | } | 186 | } |
182 | 187 | ||
183 | static struct irqaction timer_irq = { | 188 | static struct irqaction timer_irq = { |
@@ -203,3 +208,37 @@ void __init timer_init(int irq) | |||
203 | clocksource_register_hz(&cksrc, CLOCK_TICK_RATE); | 208 | clocksource_register_hz(&cksrc, CLOCK_TICK_RATE); |
204 | clockevents_register_device(&ckevt); | 209 | clockevents_register_device(&ckevt); |
205 | } | 210 | } |
211 | |||
212 | #ifdef CONFIG_OF | ||
213 | static struct of_device_id mmp_timer_dt_ids[] = { | ||
214 | { .compatible = "mrvl,mmp-timer", }, | ||
215 | {} | ||
216 | }; | ||
217 | |||
218 | void __init mmp_dt_init_timer(void) | ||
219 | { | ||
220 | struct device_node *np; | ||
221 | int irq, ret; | ||
222 | |||
223 | np = of_find_matching_node(NULL, mmp_timer_dt_ids); | ||
224 | if (!np) { | ||
225 | ret = -ENODEV; | ||
226 | goto out; | ||
227 | } | ||
228 | |||
229 | irq = irq_of_parse_and_map(np, 0); | ||
230 | if (!irq) { | ||
231 | ret = -EINVAL; | ||
232 | goto out; | ||
233 | } | ||
234 | mmp_timer_base = of_iomap(np, 0); | ||
235 | if (!mmp_timer_base) { | ||
236 | ret = -ENOMEM; | ||
237 | goto out; | ||
238 | } | ||
239 | timer_init(irq); | ||
240 | return; | ||
241 | out: | ||
242 | pr_err("Failed to get timer from device tree with error:%d\n", ret); | ||
243 | } | ||
244 | #endif | ||