aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mmp/time.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-22 12:30:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-22 12:30:52 -0400
commitb324c67d4800e59171f48d9ddab6cbfb59110482 (patch)
treea16509a710e76fa24c01514b60aed06b7db13716 /arch/arm/mach-mmp/time.c
parent8dca6010d44cc722a94dc6da96560f9083dac782 (diff)
parent396d81cd0fe12ce5d1f6d159f093f9315d2837bc (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.c81
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
47static 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
59static u32 notrace mmp_read_sched_clock(void) 64static 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
158static void __init timer_config(void) 163static 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
183static struct irqaction timer_irq = { 188static 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
213static struct of_device_id mmp_timer_dt_ids[] = {
214 { .compatible = "mrvl,mmp-timer", },
215 {}
216};
217
218void __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;
241out:
242 pr_err("Failed to get timer from device tree with error:%d\n", ret);
243}
244#endif