Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm: zynq: Use standard timer binding

Use cdns,ttc because this driver is Cadence Rev06
Triple Timer Counter and everybody can use it
without xilinx specific function name or probing.

Also use standard dt description for timer
and also prepare for moving to clocksource
initialization.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>

+196 -123
+6 -39
arch/arm/boot/dts/zynq-7000.dtsi
··· 111 111 }; 112 112 113 113 ttc0: ttc0@f8001000 { 114 - #address-cells = <1>; 115 - #size-cells = <0>; 116 - compatible = "xlnx,ttc"; 114 + interrupt-parent = <&intc>; 115 + interrupts = < 0 10 4 0 11 4 0 12 4 >; 116 + compatible = "cdns,ttc"; 117 117 reg = <0xF8001000 0x1000>; 118 118 clocks = <&cpu_clk 3>; 119 119 clock-names = "cpu_1x"; 120 120 clock-ranges; 121 - 122 - ttc0_0: ttc0.0 { 123 - status = "disabled"; 124 - reg = <0>; 125 - interrupts = <0 10 4>; 126 - }; 127 - ttc0_1: ttc0.1 { 128 - status = "disabled"; 129 - reg = <1>; 130 - interrupts = <0 11 4>; 131 - }; 132 - ttc0_2: ttc0.2 { 133 - status = "disabled"; 134 - reg = <2>; 135 - interrupts = <0 12 4>; 136 - }; 137 121 }; 138 122 139 123 ttc1: ttc1@f8002000 { 140 - #interrupt-parent = <&intc>; 141 - #address-cells = <1>; 142 - #size-cells = <0>; 143 - compatible = "xlnx,ttc"; 124 + interrupt-parent = <&intc>; 125 + interrupts = < 0 37 4 0 38 4 0 39 4 >; 126 + compatible = "cdns,ttc"; 144 127 reg = <0xF8002000 0x1000>; 145 128 clocks = <&cpu_clk 3>; 146 129 clock-names = "cpu_1x"; 147 130 clock-ranges; 148 - 149 - ttc1_0: ttc1.0 { 150 - status = "disabled"; 151 - reg = <0>; 152 - interrupts = <0 37 4>; 153 - }; 154 - ttc1_1: ttc1.1 { 155 - status = "disabled"; 156 - reg = <1>; 157 - interrupts = <0 38 4>; 158 - }; 159 - ttc1_2: ttc1.2 { 160 - status = "disabled"; 161 - reg = <2>; 162 - interrupts = <0 39 4>; 163 - }; 164 131 }; 165 132 }; 166 133 };
-10
arch/arm/boot/dts/zynq-zc702.dts
··· 32 32 &ps_clk { 33 33 clock-frequency = <33333330>; 34 34 }; 35 - 36 - &ttc0_0 { 37 - status = "ok"; 38 - compatible = "xlnx,ttc-counter-clocksource"; 39 - }; 40 - 41 - &ttc0_1 { 42 - status = "ok"; 43 - compatible = "xlnx,ttc-counter-clockevent"; 44 - };
+1
arch/arm/mach-zynq/common.c
··· 20 20 #include <linux/platform_device.h> 21 21 #include <linux/clk.h> 22 22 #include <linux/clk/zynq.h> 23 + #include <linux/clocksource.h> 23 24 #include <linux/of_address.h> 24 25 #include <linux/of_irq.h> 25 26 #include <linux/of_platform.h>
+189 -74
arch/arm/mach-zynq/timer.c
··· 1 1 /* 2 2 * This file contains driver for the Xilinx PS Timer Counter IP. 3 3 * 4 - * Copyright (C) 2011 Xilinx 4 + * Copyright (C) 2011-2013 Xilinx 5 5 * 6 6 * based on arch/mips/kernel/time.c timer driver 7 7 * ··· 15 15 * GNU General Public License for more details. 16 16 */ 17 17 18 + #include <linux/clk.h> 18 19 #include <linux/interrupt.h> 19 20 #include <linux/clockchips.h> 20 21 #include <linux/of_address.h> ··· 23 22 #include <linux/slab.h> 24 23 #include <linux/clk-provider.h> 25 24 #include "common.h" 25 + 26 + /* 27 + * This driver configures the 2 16-bit count-up timers as follows: 28 + * 29 + * T1: Timer 1, clocksource for generic timekeeping 30 + * T2: Timer 2, clockevent source for hrtimers 31 + * T3: Timer 3, <unused> 32 + * 33 + * The input frequency to the timer module for emulation is 2.5MHz which is 34 + * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32, 35 + * the timers are clocked at 78.125KHz (12.8 us resolution). 36 + 37 + * The input frequency to the timer module in silicon is configurable and 38 + * obtained from device tree. The pre-scaler of 32 is used. 39 + */ 26 40 27 41 /* 28 42 * Timer Register Offset Definitions of Timer 1, Increment base address by 4 ··· 60 44 #define PRESCALE 2048 /* The exponent must match this */ 61 45 #define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1) 62 46 #define CLK_CNTRL_PRESCALE_EN 1 63 - #define CNT_CNTRL_RESET (1<<4) 47 + #define CNT_CNTRL_RESET (1 << 4) 64 48 65 49 /** 66 50 * struct xttcps_timer - This definition defines local timer structure 67 51 * 68 52 * @base_addr: Base address of timer 69 - **/ 53 + * @clk: Associated clock source 54 + * @clk_rate_change_nb Notifier block for clock rate changes 55 + */ 70 56 struct xttcps_timer { 71 - void __iomem *base_addr; 57 + void __iomem *base_addr; 58 + struct clk *clk; 59 + struct notifier_block clk_rate_change_nb; 72 60 }; 61 + 62 + #define to_xttcps_timer(x) \ 63 + container_of(x, struct xttcps_timer, clk_rate_change_nb) 73 64 74 65 struct xttcps_timer_clocksource { 75 66 struct xttcps_timer xttc; ··· 89 66 struct xttcps_timer_clockevent { 90 67 struct xttcps_timer xttc; 91 68 struct clock_event_device ce; 92 - struct clk *clk; 93 69 }; 94 70 95 71 #define to_xttcps_timer_clkevent(x) \ ··· 189 167 switch (mode) { 190 168 case CLOCK_EVT_MODE_PERIODIC: 191 169 xttcps_set_interval(timer, 192 - DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk), 193 - PRESCALE * HZ)); 170 + DIV_ROUND_CLOSEST(clk_get_rate(xttce->xttc.clk), 171 + PRESCALE * HZ)); 194 172 break; 195 173 case CLOCK_EVT_MODE_ONESHOT: 196 174 case CLOCK_EVT_MODE_UNUSED: ··· 211 189 } 212 190 } 213 191 214 - static void __init zynq_ttc_setup_clocksource(struct device_node *np, 215 - void __iomem *base) 192 + static int xttcps_rate_change_clocksource_cb(struct notifier_block *nb, 193 + unsigned long event, void *data) 194 + { 195 + struct clk_notifier_data *ndata = data; 196 + struct xttcps_timer *xttcps = to_xttcps_timer(nb); 197 + struct xttcps_timer_clocksource *xttccs = container_of(xttcps, 198 + struct xttcps_timer_clocksource, xttc); 199 + 200 + switch (event) { 201 + case POST_RATE_CHANGE: 202 + /* 203 + * Do whatever is necessary to maintain a proper time base 204 + * 205 + * I cannot find a way to adjust the currently used clocksource 206 + * to the new frequency. __clocksource_updatefreq_hz() sounds 207 + * good, but does not work. Not sure what's that missing. 208 + * 209 + * This approach works, but triggers two clocksource switches. 210 + * The first after unregister to clocksource jiffies. And 211 + * another one after the register to the newly registered timer. 212 + * 213 + * Alternatively we could 'waste' another HW timer to ping pong 214 + * between clock sources. That would also use one register and 215 + * one unregister call, but only trigger one clocksource switch 216 + * for the cost of another HW timer used by the OS. 217 + */ 218 + clocksource_unregister(&xttccs->cs); 219 + clocksource_register_hz(&xttccs->cs, 220 + ndata->new_rate / PRESCALE); 221 + /* fall through */ 222 + case PRE_RATE_CHANGE: 223 + case ABORT_RATE_CHANGE: 224 + default: 225 + return NOTIFY_DONE; 226 + } 227 + } 228 + 229 + static void __init xttc_setup_clocksource(struct clk *clk, void __iomem *base) 216 230 { 217 231 struct xttcps_timer_clocksource *ttccs; 218 - struct clk *clk; 219 232 int err; 220 - u32 reg; 221 233 222 234 ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL); 223 235 if (WARN_ON(!ttccs)) 224 236 return; 225 237 226 - err = of_property_read_u32(np, "reg", &reg); 238 + ttccs->xttc.clk = clk; 239 + 240 + err = clk_prepare_enable(ttccs->xttc.clk); 227 241 if (WARN_ON(err)) 228 242 return; 229 243 230 - clk = of_clk_get_by_name(np, "cpu_1x"); 231 - if (WARN_ON(IS_ERR(clk))) 232 - return; 244 + ttccs->xttc.clk_rate_change_nb.notifier_call = 245 + xttcps_rate_change_clocksource_cb; 246 + ttccs->xttc.clk_rate_change_nb.next = NULL; 247 + if (clk_notifier_register(ttccs->xttc.clk, 248 + &ttccs->xttc.clk_rate_change_nb)) 249 + pr_warn("Unable to register clock notifier.\n"); 233 250 234 - err = clk_prepare_enable(clk); 235 - if (WARN_ON(err)) 236 - return; 237 - 238 - ttccs->xttc.base_addr = base + reg * 4; 239 - 240 - ttccs->cs.name = np->name; 251 + ttccs->xttc.base_addr = base; 252 + ttccs->cs.name = "xttcps_clocksource"; 241 253 ttccs->cs.rating = 200; 242 254 ttccs->cs.read = __xttc_clocksource_read; 243 255 ttccs->cs.mask = CLOCKSOURCE_MASK(16); 244 256 ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; 245 257 258 + /* 259 + * Setup the clock source counter to be an incrementing counter 260 + * with no interrupt and it rolls over at 0xFFFF. Pre-scale 261 + * it by 32 also. Let it start running now. 262 + */ 246 263 __raw_writel(0x0, ttccs->xttc.base_addr + XTTCPS_IER_OFFSET); 247 264 __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, 248 265 ttccs->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET); 249 266 __raw_writel(CNT_CNTRL_RESET, 250 267 ttccs->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET); 251 268 252 - err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE); 269 + err = clocksource_register_hz(&ttccs->cs, 270 + clk_get_rate(ttccs->xttc.clk) / PRESCALE); 253 271 if (WARN_ON(err)) 254 272 return; 273 + 255 274 } 256 275 257 - static void __init zynq_ttc_setup_clockevent(struct device_node *np, 258 - void __iomem *base) 276 + static int xttcps_rate_change_clockevent_cb(struct notifier_block *nb, 277 + unsigned long event, void *data) 278 + { 279 + struct clk_notifier_data *ndata = data; 280 + struct xttcps_timer *xttcps = to_xttcps_timer(nb); 281 + struct xttcps_timer_clockevent *xttcce = container_of(xttcps, 282 + struct xttcps_timer_clockevent, xttc); 283 + 284 + switch (event) { 285 + case POST_RATE_CHANGE: 286 + { 287 + unsigned long flags; 288 + 289 + /* 290 + * clockevents_update_freq should be called with IRQ disabled on 291 + * the CPU the timer provides events for. The timer we use is 292 + * common to both CPUs, not sure if we need to run on both 293 + * cores. 294 + */ 295 + local_irq_save(flags); 296 + clockevents_update_freq(&xttcce->ce, 297 + ndata->new_rate / PRESCALE); 298 + local_irq_restore(flags); 299 + 300 + /* fall through */ 301 + } 302 + case PRE_RATE_CHANGE: 303 + case ABORT_RATE_CHANGE: 304 + default: 305 + return NOTIFY_DONE; 306 + } 307 + } 308 + 309 + static void __init xttc_setup_clockevent(struct clk *clk, 310 + void __iomem *base, u32 irq) 259 311 { 260 312 struct xttcps_timer_clockevent *ttcce; 261 - int err, irq; 262 - u32 reg; 313 + int err; 263 314 264 315 ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL); 265 316 if (WARN_ON(!ttcce)) 266 317 return; 267 318 268 - err = of_property_read_u32(np, "reg", &reg); 319 + ttcce->xttc.clk = clk; 320 + 321 + err = clk_prepare_enable(ttcce->xttc.clk); 269 322 if (WARN_ON(err)) 270 323 return; 271 324 272 - ttcce->xttc.base_addr = base + reg * 4; 325 + ttcce->xttc.clk_rate_change_nb.notifier_call = 326 + xttcps_rate_change_clockevent_cb; 327 + ttcce->xttc.clk_rate_change_nb.next = NULL; 328 + if (clk_notifier_register(ttcce->xttc.clk, 329 + &ttcce->xttc.clk_rate_change_nb)) 330 + pr_warn("Unable to register clock notifier.\n"); 273 331 274 - ttcce->clk = of_clk_get_by_name(np, "cpu_1x"); 275 - if (WARN_ON(IS_ERR(ttcce->clk))) 276 - return; 277 - 278 - err = clk_prepare_enable(ttcce->clk); 279 - if (WARN_ON(err)) 280 - return; 281 - 282 - irq = irq_of_parse_and_map(np, 0); 283 - if (WARN_ON(!irq)) 284 - return; 285 - 286 - ttcce->ce.name = np->name; 332 + ttcce->xttc.base_addr = base; 333 + ttcce->ce.name = "xttcps_clockevent"; 287 334 ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; 288 335 ttcce->ce.set_next_event = xttcps_set_next_event; 289 336 ttcce->ce.set_mode = xttcps_set_mode; ··· 360 269 ttcce->ce.irq = irq; 361 270 ttcce->ce.cpumask = cpu_possible_mask; 362 271 272 + /* 273 + * Setup the clock event timer to be an interval timer which 274 + * is prescaled by 32 using the interval interrupt. Leave it 275 + * disabled for now. 276 + */ 363 277 __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET); 364 278 __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, 365 279 ttcce->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET); 366 280 __raw_writel(0x1, ttcce->xttc.base_addr + XTTCPS_IER_OFFSET); 367 281 368 - err = request_irq(irq, xttcps_clock_event_interrupt, IRQF_TIMER, 369 - np->name, ttcce); 282 + err = request_irq(irq, xttcps_clock_event_interrupt, 283 + IRQF_DISABLED | IRQF_TIMER, 284 + ttcce->ce.name, ttcce); 370 285 if (WARN_ON(err)) 371 286 return; 372 287 373 288 clockevents_config_and_register(&ttcce->ce, 374 - clk_get_rate(ttcce->clk) / PRESCALE, 375 - 1, 0xfffe); 289 + clk_get_rate(ttcce->xttc.clk) / PRESCALE, 1, 0xfffe); 376 290 } 377 - 378 - static const __initconst struct of_device_id zynq_ttc_match[] = { 379 - { .compatible = "xlnx,ttc-counter-clocksource", 380 - .data = zynq_ttc_setup_clocksource, }, 381 - { .compatible = "xlnx,ttc-counter-clockevent", 382 - .data = zynq_ttc_setup_clockevent, }, 383 - {} 384 - }; 385 291 386 292 /** 387 293 * xttcps_timer_init - Initialize the timer 388 294 * 389 295 * Initializes the timer hardware and register the clock source and clock event 390 296 * timers with Linux kernal timer framework 391 - **/ 297 + */ 298 + static void __init xttcps_timer_init_of(struct device_node *timer) 299 + { 300 + unsigned int irq; 301 + void __iomem *timer_baseaddr; 302 + struct clk *clk; 303 + 304 + /* 305 + * Get the 1st Triple Timer Counter (TTC) block from the device tree 306 + * and use it. Note that the event timer uses the interrupt and it's the 307 + * 2nd TTC hence the irq_of_parse_and_map(,1) 308 + */ 309 + timer_baseaddr = of_iomap(timer, 0); 310 + if (!timer_baseaddr) { 311 + pr_err("ERROR: invalid timer base address\n"); 312 + BUG(); 313 + } 314 + 315 + irq = irq_of_parse_and_map(timer, 1); 316 + if (irq <= 0) { 317 + pr_err("ERROR: invalid interrupt number\n"); 318 + BUG(); 319 + } 320 + 321 + clk = of_clk_get_by_name(timer, "cpu_1x"); 322 + if (IS_ERR(clk)) { 323 + pr_err("ERROR: timer input clock not found\n"); 324 + BUG(); 325 + } 326 + 327 + xttc_setup_clocksource(clk, timer_baseaddr); 328 + xttc_setup_clockevent(clk, timer_baseaddr + 4, irq); 329 + 330 + pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq); 331 + } 332 + 392 333 void __init xttcps_timer_init(void) 393 334 { 394 - struct device_node *np; 335 + const char * const timer_list[] = { 336 + "cdns,ttc", 337 + NULL 338 + }; 339 + struct device_node *timer; 395 340 396 - for_each_compatible_node(np, NULL, "xlnx,ttc") { 397 - struct device_node *np_chld; 398 - void __iomem *base; 399 - 400 - base = of_iomap(np, 0); 401 - if (WARN_ON(!base)) 402 - return; 403 - 404 - for_each_available_child_of_node(np, np_chld) { 405 - int (*cb)(struct device_node *np, void __iomem *base); 406 - const struct of_device_id *match; 407 - 408 - match = of_match_node(zynq_ttc_match, np_chld); 409 - if (match) { 410 - cb = match->data; 411 - cb(np_chld, base); 412 - } 413 - } 341 + timer = of_find_compatible_node(NULL, NULL, timer_list[0]); 342 + if (!timer) { 343 + pr_err("ERROR: no compatible timer found\n"); 344 + BUG(); 414 345 } 346 + 347 + xttcps_timer_init_of(timer); 415 348 }