diff options
Diffstat (limited to 'arch/arm/mach-zynq/timer.c')
-rw-r--r-- | arch/arm/mach-zynq/timer.c | 150 |
1 files changed, 71 insertions, 79 deletions
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c index de3df283da74..f9fbc9c1e7a6 100644 --- a/arch/arm/mach-zynq/timer.c +++ b/arch/arm/mach-zynq/timer.c | |||
@@ -15,39 +15,29 @@ | |||
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
21 | #include <linux/irq.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/clocksource.h> | ||
24 | #include <linux/clockchips.h> | 19 | #include <linux/clockchips.h> |
25 | #include <linux/io.h> | ||
26 | #include <linux/of.h> | ||
27 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
28 | #include <linux/of_irq.h> | 21 | #include <linux/of_irq.h> |
29 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
30 | #include <linux/clk-provider.h> | 23 | #include <linux/clk-provider.h> |
31 | |||
32 | #include "common.h" | 24 | #include "common.h" |
33 | 25 | ||
34 | /* | 26 | /* |
35 | * Timer Register Offset Definitions of Timer 1, Increment base address by 4 | 27 | * Timer Register Offset Definitions of Timer 1, Increment base address by 4 |
36 | * and use same offsets for Timer 2 | 28 | * and use same offsets for Timer 2 |
37 | */ | 29 | */ |
38 | #define XTTCPSS_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */ | 30 | #define XTTCPS_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */ |
39 | #define XTTCPSS_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */ | 31 | #define XTTCPS_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */ |
40 | #define XTTCPSS_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */ | 32 | #define XTTCPS_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */ |
41 | #define XTTCPSS_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */ | 33 | #define XTTCPS_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */ |
42 | #define XTTCPSS_MATCH_1_OFFSET 0x30 /* Match 1 Value Reg, RW */ | 34 | #define XTTCPS_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */ |
43 | #define XTTCPSS_MATCH_2_OFFSET 0x3C /* Match 2 Value Reg, RW */ | 35 | #define XTTCPS_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */ |
44 | #define XTTCPSS_MATCH_3_OFFSET 0x48 /* Match 3 Value Reg, RW */ | 36 | |
45 | #define XTTCPSS_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */ | 37 | #define XTTCPS_CNT_CNTRL_DISABLE_MASK 0x1 |
46 | #define XTTCPSS_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */ | 38 | |
47 | 39 | /* | |
48 | #define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1 | 40 | * Setup the timers to use pre-scaling, using a fixed value for now that will |
49 | |||
50 | /* Setup the timers to use pre-scaling, using a fixed value for now that will | ||
51 | * work across most input frequency, but it may need to be more dynamic | 41 | * work across most input frequency, but it may need to be more dynamic |
52 | */ | 42 | */ |
53 | #define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */ | 43 | #define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */ |
@@ -57,72 +47,73 @@ | |||
57 | #define CNT_CNTRL_RESET (1<<4) | 47 | #define CNT_CNTRL_RESET (1<<4) |
58 | 48 | ||
59 | /** | 49 | /** |
60 | * struct xttcpss_timer - This definition defines local timer structure | 50 | * struct xttcps_timer - This definition defines local timer structure |
61 | * | 51 | * |
62 | * @base_addr: Base address of timer | 52 | * @base_addr: Base address of timer |
63 | **/ | 53 | **/ |
64 | struct xttcpss_timer { | 54 | struct xttcps_timer { |
65 | void __iomem *base_addr; | 55 | void __iomem *base_addr; |
66 | }; | 56 | }; |
67 | 57 | ||
68 | struct xttcpss_timer_clocksource { | 58 | struct xttcps_timer_clocksource { |
69 | struct xttcpss_timer xttc; | 59 | struct xttcps_timer xttc; |
70 | struct clocksource cs; | 60 | struct clocksource cs; |
71 | }; | 61 | }; |
72 | 62 | ||
73 | #define to_xttcpss_timer_clksrc(x) \ | 63 | #define to_xttcps_timer_clksrc(x) \ |
74 | container_of(x, struct xttcpss_timer_clocksource, cs) | 64 | container_of(x, struct xttcps_timer_clocksource, cs) |
75 | 65 | ||
76 | struct xttcpss_timer_clockevent { | 66 | struct xttcps_timer_clockevent { |
77 | struct xttcpss_timer xttc; | 67 | struct xttcps_timer xttc; |
78 | struct clock_event_device ce; | 68 | struct clock_event_device ce; |
79 | struct clk *clk; | 69 | struct clk *clk; |
80 | }; | 70 | }; |
81 | 71 | ||
82 | #define to_xttcpss_timer_clkevent(x) \ | 72 | #define to_xttcps_timer_clkevent(x) \ |
83 | container_of(x, struct xttcpss_timer_clockevent, ce) | 73 | container_of(x, struct xttcps_timer_clockevent, ce) |
84 | 74 | ||
85 | /** | 75 | /** |
86 | * xttcpss_set_interval - Set the timer interval value | 76 | * xttcps_set_interval - Set the timer interval value |
87 | * | 77 | * |
88 | * @timer: Pointer to the timer instance | 78 | * @timer: Pointer to the timer instance |
89 | * @cycles: Timer interval ticks | 79 | * @cycles: Timer interval ticks |
90 | **/ | 80 | **/ |
91 | static void xttcpss_set_interval(struct xttcpss_timer *timer, | 81 | static void xttcps_set_interval(struct xttcps_timer *timer, |
92 | unsigned long cycles) | 82 | unsigned long cycles) |
93 | { | 83 | { |
94 | u32 ctrl_reg; | 84 | u32 ctrl_reg; |
95 | 85 | ||
96 | /* Disable the counter, set the counter value and re-enable counter */ | 86 | /* Disable the counter, set the counter value and re-enable counter */ |
97 | ctrl_reg = __raw_readl(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); | 87 | ctrl_reg = __raw_readl(timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET); |
98 | ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK; | 88 | ctrl_reg |= XTTCPS_CNT_CNTRL_DISABLE_MASK; |
99 | __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); | 89 | __raw_writel(ctrl_reg, timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET); |
100 | 90 | ||
101 | __raw_writel(cycles, timer->base_addr + XTTCPSS_INTR_VAL_OFFSET); | 91 | __raw_writel(cycles, timer->base_addr + XTTCPS_INTR_VAL_OFFSET); |
102 | 92 | ||
103 | /* Reset the counter (0x10) so that it starts from 0, one-shot | 93 | /* |
104 | mode makes this needed for timing to be right. */ | 94 | * Reset the counter (0x10) so that it starts from 0, one-shot |
95 | * mode makes this needed for timing to be right. | ||
96 | */ | ||
105 | ctrl_reg |= CNT_CNTRL_RESET; | 97 | ctrl_reg |= CNT_CNTRL_RESET; |
106 | ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK; | 98 | ctrl_reg &= ~XTTCPS_CNT_CNTRL_DISABLE_MASK; |
107 | __raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); | 99 | __raw_writel(ctrl_reg, timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET); |
108 | } | 100 | } |
109 | 101 | ||
110 | /** | 102 | /** |
111 | * xttcpss_clock_event_interrupt - Clock event timer interrupt handler | 103 | * xttcps_clock_event_interrupt - Clock event timer interrupt handler |
112 | * | 104 | * |
113 | * @irq: IRQ number of the Timer | 105 | * @irq: IRQ number of the Timer |
114 | * @dev_id: void pointer to the xttcpss_timer instance | 106 | * @dev_id: void pointer to the xttcps_timer instance |
115 | * | 107 | * |
116 | * returns: Always IRQ_HANDLED - success | 108 | * returns: Always IRQ_HANDLED - success |
117 | **/ | 109 | **/ |
118 | static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id) | 110 | static irqreturn_t xttcps_clock_event_interrupt(int irq, void *dev_id) |
119 | { | 111 | { |
120 | struct xttcpss_timer_clockevent *xttce = dev_id; | 112 | struct xttcps_timer_clockevent *xttce = dev_id; |
121 | struct xttcpss_timer *timer = &xttce->xttc; | 113 | struct xttcps_timer *timer = &xttce->xttc; |
122 | 114 | ||
123 | /* Acknowledge the interrupt and call event handler */ | 115 | /* Acknowledge the interrupt and call event handler */ |
124 | __raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET), | 116 | __raw_readl(timer->base_addr + XTTCPS_ISR_OFFSET); |
125 | timer->base_addr + XTTCPSS_ISR_OFFSET); | ||
126 | 117 | ||
127 | xttce->ce.event_handler(&xttce->ce); | 118 | xttce->ce.event_handler(&xttce->ce); |
128 | 119 | ||
@@ -136,46 +127,46 @@ static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id) | |||
136 | **/ | 127 | **/ |
137 | static cycle_t __xttc_clocksource_read(struct clocksource *cs) | 128 | static cycle_t __xttc_clocksource_read(struct clocksource *cs) |
138 | { | 129 | { |
139 | struct xttcpss_timer *timer = &to_xttcpss_timer_clksrc(cs)->xttc; | 130 | struct xttcps_timer *timer = &to_xttcps_timer_clksrc(cs)->xttc; |
140 | 131 | ||
141 | return (cycle_t)__raw_readl(timer->base_addr + | 132 | return (cycle_t)__raw_readl(timer->base_addr + |
142 | XTTCPSS_COUNT_VAL_OFFSET); | 133 | XTTCPS_COUNT_VAL_OFFSET); |
143 | } | 134 | } |
144 | 135 | ||
145 | /** | 136 | /** |
146 | * xttcpss_set_next_event - Sets the time interval for next event | 137 | * xttcps_set_next_event - Sets the time interval for next event |
147 | * | 138 | * |
148 | * @cycles: Timer interval ticks | 139 | * @cycles: Timer interval ticks |
149 | * @evt: Address of clock event instance | 140 | * @evt: Address of clock event instance |
150 | * | 141 | * |
151 | * returns: Always 0 - success | 142 | * returns: Always 0 - success |
152 | **/ | 143 | **/ |
153 | static int xttcpss_set_next_event(unsigned long cycles, | 144 | static int xttcps_set_next_event(unsigned long cycles, |
154 | struct clock_event_device *evt) | 145 | struct clock_event_device *evt) |
155 | { | 146 | { |
156 | struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt); | 147 | struct xttcps_timer_clockevent *xttce = to_xttcps_timer_clkevent(evt); |
157 | struct xttcpss_timer *timer = &xttce->xttc; | 148 | struct xttcps_timer *timer = &xttce->xttc; |
158 | 149 | ||
159 | xttcpss_set_interval(timer, cycles); | 150 | xttcps_set_interval(timer, cycles); |
160 | return 0; | 151 | return 0; |
161 | } | 152 | } |
162 | 153 | ||
163 | /** | 154 | /** |
164 | * xttcpss_set_mode - Sets the mode of timer | 155 | * xttcps_set_mode - Sets the mode of timer |
165 | * | 156 | * |
166 | * @mode: Mode to be set | 157 | * @mode: Mode to be set |
167 | * @evt: Address of clock event instance | 158 | * @evt: Address of clock event instance |
168 | **/ | 159 | **/ |
169 | static void xttcpss_set_mode(enum clock_event_mode mode, | 160 | static void xttcps_set_mode(enum clock_event_mode mode, |
170 | struct clock_event_device *evt) | 161 | struct clock_event_device *evt) |
171 | { | 162 | { |
172 | struct xttcpss_timer_clockevent *xttce = to_xttcpss_timer_clkevent(evt); | 163 | struct xttcps_timer_clockevent *xttce = to_xttcps_timer_clkevent(evt); |
173 | struct xttcpss_timer *timer = &xttce->xttc; | 164 | struct xttcps_timer *timer = &xttce->xttc; |
174 | u32 ctrl_reg; | 165 | u32 ctrl_reg; |
175 | 166 | ||
176 | switch (mode) { | 167 | switch (mode) { |
177 | case CLOCK_EVT_MODE_PERIODIC: | 168 | case CLOCK_EVT_MODE_PERIODIC: |
178 | xttcpss_set_interval(timer, | 169 | xttcps_set_interval(timer, |
179 | DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk), | 170 | DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk), |
180 | PRESCALE * HZ)); | 171 | PRESCALE * HZ)); |
181 | break; | 172 | break; |
@@ -183,17 +174,17 @@ static void xttcpss_set_mode(enum clock_event_mode mode, | |||
183 | case CLOCK_EVT_MODE_UNUSED: | 174 | case CLOCK_EVT_MODE_UNUSED: |
184 | case CLOCK_EVT_MODE_SHUTDOWN: | 175 | case CLOCK_EVT_MODE_SHUTDOWN: |
185 | ctrl_reg = __raw_readl(timer->base_addr + | 176 | ctrl_reg = __raw_readl(timer->base_addr + |
186 | XTTCPSS_CNT_CNTRL_OFFSET); | 177 | XTTCPS_CNT_CNTRL_OFFSET); |
187 | ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK; | 178 | ctrl_reg |= XTTCPS_CNT_CNTRL_DISABLE_MASK; |
188 | __raw_writel(ctrl_reg, | 179 | __raw_writel(ctrl_reg, |
189 | timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); | 180 | timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET); |
190 | break; | 181 | break; |
191 | case CLOCK_EVT_MODE_RESUME: | 182 | case CLOCK_EVT_MODE_RESUME: |
192 | ctrl_reg = __raw_readl(timer->base_addr + | 183 | ctrl_reg = __raw_readl(timer->base_addr + |
193 | XTTCPSS_CNT_CNTRL_OFFSET); | 184 | XTTCPS_CNT_CNTRL_OFFSET); |
194 | ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK; | 185 | ctrl_reg &= ~XTTCPS_CNT_CNTRL_DISABLE_MASK; |
195 | __raw_writel(ctrl_reg, | 186 | __raw_writel(ctrl_reg, |
196 | timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET); | 187 | timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET); |
197 | break; | 188 | break; |
198 | } | 189 | } |
199 | } | 190 | } |
@@ -201,7 +192,7 @@ static void xttcpss_set_mode(enum clock_event_mode mode, | |||
201 | static void __init zynq_ttc_setup_clocksource(struct device_node *np, | 192 | static void __init zynq_ttc_setup_clocksource(struct device_node *np, |
202 | void __iomem *base) | 193 | void __iomem *base) |
203 | { | 194 | { |
204 | struct xttcpss_timer_clocksource *ttccs; | 195 | struct xttcps_timer_clocksource *ttccs; |
205 | struct clk *clk; | 196 | struct clk *clk; |
206 | int err; | 197 | int err; |
207 | u32 reg; | 198 | u32 reg; |
@@ -230,11 +221,11 @@ static void __init zynq_ttc_setup_clocksource(struct device_node *np, | |||
230 | ttccs->cs.mask = CLOCKSOURCE_MASK(16); | 221 | ttccs->cs.mask = CLOCKSOURCE_MASK(16); |
231 | ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; | 222 | ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; |
232 | 223 | ||
233 | __raw_writel(0x0, ttccs->xttc.base_addr + XTTCPSS_IER_OFFSET); | 224 | __raw_writel(0x0, ttccs->xttc.base_addr + XTTCPS_IER_OFFSET); |
234 | __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, | 225 | __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, |
235 | ttccs->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET); | 226 | ttccs->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET); |
236 | __raw_writel(CNT_CNTRL_RESET, | 227 | __raw_writel(CNT_CNTRL_RESET, |
237 | ttccs->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET); | 228 | ttccs->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET); |
238 | 229 | ||
239 | err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE); | 230 | err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE); |
240 | if (WARN_ON(err)) | 231 | if (WARN_ON(err)) |
@@ -244,7 +235,7 @@ static void __init zynq_ttc_setup_clocksource(struct device_node *np, | |||
244 | static void __init zynq_ttc_setup_clockevent(struct device_node *np, | 235 | static void __init zynq_ttc_setup_clockevent(struct device_node *np, |
245 | void __iomem *base) | 236 | void __iomem *base) |
246 | { | 237 | { |
247 | struct xttcpss_timer_clockevent *ttcce; | 238 | struct xttcps_timer_clockevent *ttcce; |
248 | int err, irq; | 239 | int err, irq; |
249 | u32 reg; | 240 | u32 reg; |
250 | 241 | ||
@@ -272,17 +263,18 @@ static void __init zynq_ttc_setup_clockevent(struct device_node *np, | |||
272 | 263 | ||
273 | ttcce->ce.name = np->name; | 264 | ttcce->ce.name = np->name; |
274 | ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 265 | ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
275 | ttcce->ce.set_next_event = xttcpss_set_next_event; | 266 | ttcce->ce.set_next_event = xttcps_set_next_event; |
276 | ttcce->ce.set_mode = xttcpss_set_mode; | 267 | ttcce->ce.set_mode = xttcps_set_mode; |
277 | ttcce->ce.rating = 200; | 268 | ttcce->ce.rating = 200; |
278 | ttcce->ce.irq = irq; | 269 | ttcce->ce.irq = irq; |
270 | ttcce->ce.cpumask = cpu_possible_mask; | ||
279 | 271 | ||
280 | __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPSS_CNT_CNTRL_OFFSET); | 272 | __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET); |
281 | __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, | 273 | __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, |
282 | ttcce->xttc.base_addr + XTTCPSS_CLK_CNTRL_OFFSET); | 274 | ttcce->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET); |
283 | __raw_writel(0x1, ttcce->xttc.base_addr + XTTCPSS_IER_OFFSET); | 275 | __raw_writel(0x1, ttcce->xttc.base_addr + XTTCPS_IER_OFFSET); |
284 | 276 | ||
285 | err = request_irq(irq, xttcpss_clock_event_interrupt, IRQF_TIMER, | 277 | err = request_irq(irq, xttcps_clock_event_interrupt, IRQF_TIMER, |
286 | np->name, ttcce); | 278 | np->name, ttcce); |
287 | if (WARN_ON(err)) | 279 | if (WARN_ON(err)) |
288 | return; | 280 | return; |
@@ -301,12 +293,12 @@ static const __initconst struct of_device_id zynq_ttc_match[] = { | |||
301 | }; | 293 | }; |
302 | 294 | ||
303 | /** | 295 | /** |
304 | * xttcpss_timer_init - Initialize the timer | 296 | * xttcps_timer_init - Initialize the timer |
305 | * | 297 | * |
306 | * Initializes the timer hardware and register the clock source and clock event | 298 | * Initializes the timer hardware and register the clock source and clock event |
307 | * timers with Linux kernal timer framework | 299 | * timers with Linux kernal timer framework |
308 | **/ | 300 | **/ |
309 | void __init xttcpss_timer_init(void) | 301 | void __init xttcps_timer_init(void) |
310 | { | 302 | { |
311 | struct device_node *np; | 303 | struct device_node *np; |
312 | 304 | ||