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

Configure Feed

Select the types of activity you want to include in your feed.

at v4.7 386 lines 10 kB view raw
1/* 2 * Marvell Armada 370/XP SoC timer handling. 3 * 4 * Copyright (C) 2012 Marvell 5 * 6 * Lior Amsalem <alior@marvell.com> 7 * Gregory CLEMENT <gregory.clement@free-electrons.com> 8 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> 9 * 10 * This file is licensed under the terms of the GNU General Public 11 * License version 2. This program is licensed "as is" without any 12 * warranty of any kind, whether express or implied. 13 * 14 * Timer 0 is used as free-running clocksource, while timer 1 is 15 * used as clock_event_device. 16 * 17 * --- 18 * Clocksource driver for Armada 370 and Armada XP SoC. 19 * This driver implements one compatible string for each SoC, given 20 * each has its own characteristics: 21 * 22 * * Armada 370 has no 25 MHz fixed timer. 23 * 24 * * Armada XP cannot work properly without such 25 MHz fixed timer as 25 * doing otherwise leads to using a clocksource whose frequency varies 26 * when doing cpufreq frequency changes. 27 * 28 * See Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt 29 */ 30 31#include <linux/init.h> 32#include <linux/platform_device.h> 33#include <linux/kernel.h> 34#include <linux/clk.h> 35#include <linux/cpu.h> 36#include <linux/timer.h> 37#include <linux/clockchips.h> 38#include <linux/interrupt.h> 39#include <linux/of.h> 40#include <linux/of_irq.h> 41#include <linux/of_address.h> 42#include <linux/irq.h> 43#include <linux/module.h> 44#include <linux/sched_clock.h> 45#include <linux/percpu.h> 46#include <linux/syscore_ops.h> 47 48#include <asm/delay.h> 49 50/* 51 * Timer block registers. 52 */ 53#define TIMER_CTRL_OFF 0x0000 54#define TIMER0_EN BIT(0) 55#define TIMER0_RELOAD_EN BIT(1) 56#define TIMER0_25MHZ BIT(11) 57#define TIMER0_DIV(div) ((div) << 19) 58#define TIMER1_EN BIT(2) 59#define TIMER1_RELOAD_EN BIT(3) 60#define TIMER1_25MHZ BIT(12) 61#define TIMER1_DIV(div) ((div) << 22) 62#define TIMER_EVENTS_STATUS 0x0004 63#define TIMER0_CLR_MASK (~0x1) 64#define TIMER1_CLR_MASK (~0x100) 65#define TIMER0_RELOAD_OFF 0x0010 66#define TIMER0_VAL_OFF 0x0014 67#define TIMER1_RELOAD_OFF 0x0018 68#define TIMER1_VAL_OFF 0x001c 69 70#define LCL_TIMER_EVENTS_STATUS 0x0028 71/* Global timers are connected to the coherency fabric clock, and the 72 below divider reduces their incrementing frequency. */ 73#define TIMER_DIVIDER_SHIFT 5 74#define TIMER_DIVIDER (1 << TIMER_DIVIDER_SHIFT) 75 76/* 77 * SoC-specific data. 78 */ 79static void __iomem *timer_base, *local_base; 80static unsigned int timer_clk; 81static bool timer25Mhz = true; 82static u32 enable_mask; 83 84/* 85 * Number of timer ticks per jiffy. 86 */ 87static u32 ticks_per_jiffy; 88 89static struct clock_event_device __percpu *armada_370_xp_evt; 90 91static void local_timer_ctrl_clrset(u32 clr, u32 set) 92{ 93 writel((readl(local_base + TIMER_CTRL_OFF) & ~clr) | set, 94 local_base + TIMER_CTRL_OFF); 95} 96 97static u64 notrace armada_370_xp_read_sched_clock(void) 98{ 99 return ~readl(timer_base + TIMER0_VAL_OFF); 100} 101 102/* 103 * Clockevent handling. 104 */ 105static int 106armada_370_xp_clkevt_next_event(unsigned long delta, 107 struct clock_event_device *dev) 108{ 109 /* 110 * Clear clockevent timer interrupt. 111 */ 112 writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); 113 114 /* 115 * Setup new clockevent timer value. 116 */ 117 writel(delta, local_base + TIMER0_VAL_OFF); 118 119 /* 120 * Enable the timer. 121 */ 122 local_timer_ctrl_clrset(TIMER0_RELOAD_EN, enable_mask); 123 return 0; 124} 125 126static int armada_370_xp_clkevt_shutdown(struct clock_event_device *evt) 127{ 128 /* 129 * Disable timer. 130 */ 131 local_timer_ctrl_clrset(TIMER0_EN, 0); 132 133 /* 134 * ACK pending timer interrupt. 135 */ 136 writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); 137 return 0; 138} 139 140static int armada_370_xp_clkevt_set_periodic(struct clock_event_device *evt) 141{ 142 /* 143 * Setup timer to fire at 1/HZ intervals. 144 */ 145 writel(ticks_per_jiffy - 1, local_base + TIMER0_RELOAD_OFF); 146 writel(ticks_per_jiffy - 1, local_base + TIMER0_VAL_OFF); 147 148 /* 149 * Enable timer. 150 */ 151 local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); 152 return 0; 153} 154 155static int armada_370_xp_clkevt_irq; 156 157static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id) 158{ 159 /* 160 * ACK timer interrupt and call event handler. 161 */ 162 struct clock_event_device *evt = dev_id; 163 164 writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); 165 evt->event_handler(evt); 166 167 return IRQ_HANDLED; 168} 169 170/* 171 * Setup the local clock events for a CPU. 172 */ 173static int armada_370_xp_timer_setup(struct clock_event_device *evt) 174{ 175 u32 clr = 0, set = 0; 176 int cpu = smp_processor_id(); 177 178 if (timer25Mhz) 179 set = TIMER0_25MHZ; 180 else 181 clr = TIMER0_25MHZ; 182 local_timer_ctrl_clrset(clr, set); 183 184 evt->name = "armada_370_xp_per_cpu_tick", 185 evt->features = CLOCK_EVT_FEAT_ONESHOT | 186 CLOCK_EVT_FEAT_PERIODIC; 187 evt->shift = 32, 188 evt->rating = 300, 189 evt->set_next_event = armada_370_xp_clkevt_next_event, 190 evt->set_state_shutdown = armada_370_xp_clkevt_shutdown; 191 evt->set_state_periodic = armada_370_xp_clkevt_set_periodic; 192 evt->set_state_oneshot = armada_370_xp_clkevt_shutdown; 193 evt->tick_resume = armada_370_xp_clkevt_shutdown; 194 evt->irq = armada_370_xp_clkevt_irq; 195 evt->cpumask = cpumask_of(cpu); 196 197 clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe); 198 enable_percpu_irq(evt->irq, 0); 199 200 return 0; 201} 202 203static void armada_370_xp_timer_stop(struct clock_event_device *evt) 204{ 205 evt->set_state_shutdown(evt); 206 disable_percpu_irq(evt->irq); 207} 208 209static int armada_370_xp_timer_cpu_notify(struct notifier_block *self, 210 unsigned long action, void *hcpu) 211{ 212 /* 213 * Grab cpu pointer in each case to avoid spurious 214 * preemptible warnings 215 */ 216 switch (action & ~CPU_TASKS_FROZEN) { 217 case CPU_STARTING: 218 armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt)); 219 break; 220 case CPU_DYING: 221 armada_370_xp_timer_stop(this_cpu_ptr(armada_370_xp_evt)); 222 break; 223 } 224 225 return NOTIFY_OK; 226} 227 228static struct notifier_block armada_370_xp_timer_cpu_nb = { 229 .notifier_call = armada_370_xp_timer_cpu_notify, 230}; 231 232static u32 timer0_ctrl_reg, timer0_local_ctrl_reg; 233 234static int armada_370_xp_timer_suspend(void) 235{ 236 timer0_ctrl_reg = readl(timer_base + TIMER_CTRL_OFF); 237 timer0_local_ctrl_reg = readl(local_base + TIMER_CTRL_OFF); 238 return 0; 239} 240 241static void armada_370_xp_timer_resume(void) 242{ 243 writel(0xffffffff, timer_base + TIMER0_VAL_OFF); 244 writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); 245 writel(timer0_ctrl_reg, timer_base + TIMER_CTRL_OFF); 246 writel(timer0_local_ctrl_reg, local_base + TIMER_CTRL_OFF); 247} 248 249struct syscore_ops armada_370_xp_timer_syscore_ops = { 250 .suspend = armada_370_xp_timer_suspend, 251 .resume = armada_370_xp_timer_resume, 252}; 253 254static unsigned long armada_370_delay_timer_read(void) 255{ 256 return ~readl(timer_base + TIMER0_VAL_OFF); 257} 258 259static struct delay_timer armada_370_delay_timer = { 260 .read_current_timer = armada_370_delay_timer_read, 261}; 262 263static void __init armada_370_xp_timer_common_init(struct device_node *np) 264{ 265 u32 clr = 0, set = 0; 266 int res; 267 268 timer_base = of_iomap(np, 0); 269 WARN_ON(!timer_base); 270 local_base = of_iomap(np, 1); 271 272 if (timer25Mhz) { 273 set = TIMER0_25MHZ; 274 enable_mask = TIMER0_EN; 275 } else { 276 clr = TIMER0_25MHZ; 277 enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT); 278 } 279 atomic_io_modify(timer_base + TIMER_CTRL_OFF, clr | set, set); 280 local_timer_ctrl_clrset(clr, set); 281 282 /* 283 * We use timer 0 as clocksource, and private(local) timer 0 284 * for clockevents 285 */ 286 armada_370_xp_clkevt_irq = irq_of_parse_and_map(np, 4); 287 288 ticks_per_jiffy = (timer_clk + HZ / 2) / HZ; 289 290 /* 291 * Setup free-running clocksource timer (interrupts 292 * disabled). 293 */ 294 writel(0xffffffff, timer_base + TIMER0_VAL_OFF); 295 writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF); 296 297 atomic_io_modify(timer_base + TIMER_CTRL_OFF, 298 TIMER0_RELOAD_EN | enable_mask, 299 TIMER0_RELOAD_EN | enable_mask); 300 301 armada_370_delay_timer.freq = timer_clk; 302 register_current_timer_delay(&armada_370_delay_timer); 303 304 /* 305 * Set scale and timer for sched_clock. 306 */ 307 sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk); 308 309 clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, 310 "armada_370_xp_clocksource", 311 timer_clk, 300, 32, clocksource_mmio_readl_down); 312 313 register_cpu_notifier(&armada_370_xp_timer_cpu_nb); 314 315 armada_370_xp_evt = alloc_percpu(struct clock_event_device); 316 317 318 /* 319 * Setup clockevent timer (interrupt-driven). 320 */ 321 res = request_percpu_irq(armada_370_xp_clkevt_irq, 322 armada_370_xp_timer_interrupt, 323 "armada_370_xp_per_cpu_tick", 324 armada_370_xp_evt); 325 /* Immediately configure the timer on the boot CPU */ 326 if (!res) 327 armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt)); 328 329 register_syscore_ops(&armada_370_xp_timer_syscore_ops); 330} 331 332static void __init armada_xp_timer_init(struct device_node *np) 333{ 334 struct clk *clk = of_clk_get_by_name(np, "fixed"); 335 336 /* The 25Mhz fixed clock is mandatory, and must always be available */ 337 BUG_ON(IS_ERR(clk)); 338 clk_prepare_enable(clk); 339 timer_clk = clk_get_rate(clk); 340 341 armada_370_xp_timer_common_init(np); 342} 343CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer", 344 armada_xp_timer_init); 345 346static void __init armada_375_timer_init(struct device_node *np) 347{ 348 struct clk *clk; 349 350 clk = of_clk_get_by_name(np, "fixed"); 351 if (!IS_ERR(clk)) { 352 clk_prepare_enable(clk); 353 timer_clk = clk_get_rate(clk); 354 } else { 355 356 /* 357 * This fallback is required in order to retain proper 358 * devicetree backwards compatibility. 359 */ 360 clk = of_clk_get(np, 0); 361 362 /* Must have at least a clock */ 363 BUG_ON(IS_ERR(clk)); 364 clk_prepare_enable(clk); 365 timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; 366 timer25Mhz = false; 367 } 368 369 armada_370_xp_timer_common_init(np); 370} 371CLOCKSOURCE_OF_DECLARE(armada_375, "marvell,armada-375-timer", 372 armada_375_timer_init); 373 374static void __init armada_370_timer_init(struct device_node *np) 375{ 376 struct clk *clk = of_clk_get(np, 0); 377 378 BUG_ON(IS_ERR(clk)); 379 clk_prepare_enable(clk); 380 timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; 381 timer25Mhz = false; 382 383 armada_370_xp_timer_common_init(np); 384} 385CLOCKSOURCE_OF_DECLARE(armada_370, "marvell,armada-370-timer", 386 armada_370_timer_init);