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.20-rc2 433 lines 12 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2#include <linux/init.h> 3#include <linux/clocksource.h> 4#include <linux/clockchips.h> 5#include <linux/interrupt.h> 6#include <linux/irq.h> 7 8#include <linux/clk.h> 9#include <linux/err.h> 10#include <linux/ioport.h> 11#include <linux/io.h> 12#include <linux/platform_device.h> 13#include <linux/syscore_ops.h> 14#include <linux/atmel_tc.h> 15 16 17/* 18 * We're configured to use a specific TC block, one that's not hooked 19 * up to external hardware, to provide a time solution: 20 * 21 * - Two channels combine to create a free-running 32 bit counter 22 * with a base rate of 5+ MHz, packaged as a clocksource (with 23 * resolution better than 200 nsec). 24 * - Some chips support 32 bit counter. A single channel is used for 25 * this 32 bit free-running counter. the second channel is not used. 26 * 27 * - The third channel may be used to provide a 16-bit clockevent 28 * source, used in either periodic or oneshot mode. This runs 29 * at 32 KiHZ, and can handle delays of up to two seconds. 30 * 31 * A boot clocksource and clockevent source are also currently needed, 32 * unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so 33 * this code can be used when init_timers() is called, well before most 34 * devices are set up. (Some low end AT91 parts, which can run uClinux, 35 * have only the timers in one TC block... they currently don't support 36 * the tclib code, because of that initialization issue.) 37 * 38 * REVISIT behavior during system suspend states... we should disable 39 * all clocks and save the power. Easily done for clockevent devices, 40 * but clocksources won't necessarily get the needed notifications. 41 * For deeper system sleep states, this will be mandatory... 42 */ 43 44static void __iomem *tcaddr; 45static struct 46{ 47 u32 cmr; 48 u32 imr; 49 u32 rc; 50 bool clken; 51} tcb_cache[3]; 52static u32 bmr_cache; 53 54static u64 tc_get_cycles(struct clocksource *cs) 55{ 56 unsigned long flags; 57 u32 lower, upper; 58 59 raw_local_irq_save(flags); 60 do { 61 upper = readl_relaxed(tcaddr + ATMEL_TC_REG(1, CV)); 62 lower = readl_relaxed(tcaddr + ATMEL_TC_REG(0, CV)); 63 } while (upper != readl_relaxed(tcaddr + ATMEL_TC_REG(1, CV))); 64 65 raw_local_irq_restore(flags); 66 return (upper << 16) | lower; 67} 68 69static u64 tc_get_cycles32(struct clocksource *cs) 70{ 71 return readl_relaxed(tcaddr + ATMEL_TC_REG(0, CV)); 72} 73 74void tc_clksrc_suspend(struct clocksource *cs) 75{ 76 int i; 77 78 for (i = 0; i < ARRAY_SIZE(tcb_cache); i++) { 79 tcb_cache[i].cmr = readl(tcaddr + ATMEL_TC_REG(i, CMR)); 80 tcb_cache[i].imr = readl(tcaddr + ATMEL_TC_REG(i, IMR)); 81 tcb_cache[i].rc = readl(tcaddr + ATMEL_TC_REG(i, RC)); 82 tcb_cache[i].clken = !!(readl(tcaddr + ATMEL_TC_REG(i, SR)) & 83 ATMEL_TC_CLKSTA); 84 } 85 86 bmr_cache = readl(tcaddr + ATMEL_TC_BMR); 87} 88 89void tc_clksrc_resume(struct clocksource *cs) 90{ 91 int i; 92 93 for (i = 0; i < ARRAY_SIZE(tcb_cache); i++) { 94 /* Restore registers for the channel, RA and RB are not used */ 95 writel(tcb_cache[i].cmr, tcaddr + ATMEL_TC_REG(i, CMR)); 96 writel(tcb_cache[i].rc, tcaddr + ATMEL_TC_REG(i, RC)); 97 writel(0, tcaddr + ATMEL_TC_REG(i, RA)); 98 writel(0, tcaddr + ATMEL_TC_REG(i, RB)); 99 /* Disable all the interrupts */ 100 writel(0xff, tcaddr + ATMEL_TC_REG(i, IDR)); 101 /* Reenable interrupts that were enabled before suspending */ 102 writel(tcb_cache[i].imr, tcaddr + ATMEL_TC_REG(i, IER)); 103 /* Start the clock if it was used */ 104 if (tcb_cache[i].clken) 105 writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(i, CCR)); 106 } 107 108 /* Dual channel, chain channels */ 109 writel(bmr_cache, tcaddr + ATMEL_TC_BMR); 110 /* Finally, trigger all the channels*/ 111 writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR); 112} 113 114static struct clocksource clksrc = { 115 .name = "tcb_clksrc", 116 .rating = 200, 117 .read = tc_get_cycles, 118 .mask = CLOCKSOURCE_MASK(32), 119 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 120 .suspend = tc_clksrc_suspend, 121 .resume = tc_clksrc_resume, 122}; 123 124#ifdef CONFIG_GENERIC_CLOCKEVENTS 125 126struct tc_clkevt_device { 127 struct clock_event_device clkevt; 128 struct clk *clk; 129 void __iomem *regs; 130}; 131 132static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt) 133{ 134 return container_of(clkevt, struct tc_clkevt_device, clkevt); 135} 136 137/* For now, we always use the 32K clock ... this optimizes for NO_HZ, 138 * because using one of the divided clocks would usually mean the 139 * tick rate can never be less than several dozen Hz (vs 0.5 Hz). 140 * 141 * A divided clock could be good for high resolution timers, since 142 * 30.5 usec resolution can seem "low". 143 */ 144static u32 timer_clock; 145 146static int tc_shutdown(struct clock_event_device *d) 147{ 148 struct tc_clkevt_device *tcd = to_tc_clkevt(d); 149 void __iomem *regs = tcd->regs; 150 151 writel(0xff, regs + ATMEL_TC_REG(2, IDR)); 152 writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR)); 153 if (!clockevent_state_detached(d)) 154 clk_disable(tcd->clk); 155 156 return 0; 157} 158 159static int tc_set_oneshot(struct clock_event_device *d) 160{ 161 struct tc_clkevt_device *tcd = to_tc_clkevt(d); 162 void __iomem *regs = tcd->regs; 163 164 if (clockevent_state_oneshot(d) || clockevent_state_periodic(d)) 165 tc_shutdown(d); 166 167 clk_enable(tcd->clk); 168 169 /* slow clock, count up to RC, then irq and stop */ 170 writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE | 171 ATMEL_TC_WAVESEL_UP_AUTO, regs + ATMEL_TC_REG(2, CMR)); 172 writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER)); 173 174 /* set_next_event() configures and starts the timer */ 175 return 0; 176} 177 178static int tc_set_periodic(struct clock_event_device *d) 179{ 180 struct tc_clkevt_device *tcd = to_tc_clkevt(d); 181 void __iomem *regs = tcd->regs; 182 183 if (clockevent_state_oneshot(d) || clockevent_state_periodic(d)) 184 tc_shutdown(d); 185 186 /* By not making the gentime core emulate periodic mode on top 187 * of oneshot, we get lower overhead and improved accuracy. 188 */ 189 clk_enable(tcd->clk); 190 191 /* slow clock, count up to RC, then irq and restart */ 192 writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO, 193 regs + ATMEL_TC_REG(2, CMR)); 194 writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC)); 195 196 /* Enable clock and interrupts on RC compare */ 197 writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER)); 198 199 /* go go gadget! */ 200 writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, regs + 201 ATMEL_TC_REG(2, CCR)); 202 return 0; 203} 204 205static int tc_next_event(unsigned long delta, struct clock_event_device *d) 206{ 207 writel_relaxed(delta, tcaddr + ATMEL_TC_REG(2, RC)); 208 209 /* go go gadget! */ 210 writel_relaxed(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, 211 tcaddr + ATMEL_TC_REG(2, CCR)); 212 return 0; 213} 214 215static struct tc_clkevt_device clkevt = { 216 .clkevt = { 217 .name = "tc_clkevt", 218 .features = CLOCK_EVT_FEAT_PERIODIC | 219 CLOCK_EVT_FEAT_ONESHOT, 220 /* Should be lower than at91rm9200's system timer */ 221 .rating = 125, 222 .set_next_event = tc_next_event, 223 .set_state_shutdown = tc_shutdown, 224 .set_state_periodic = tc_set_periodic, 225 .set_state_oneshot = tc_set_oneshot, 226 }, 227}; 228 229static irqreturn_t ch2_irq(int irq, void *handle) 230{ 231 struct tc_clkevt_device *dev = handle; 232 unsigned int sr; 233 234 sr = readl_relaxed(dev->regs + ATMEL_TC_REG(2, SR)); 235 if (sr & ATMEL_TC_CPCS) { 236 dev->clkevt.event_handler(&dev->clkevt); 237 return IRQ_HANDLED; 238 } 239 240 return IRQ_NONE; 241} 242 243static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx) 244{ 245 int ret; 246 struct clk *t2_clk = tc->clk[2]; 247 int irq = tc->irq[2]; 248 249 ret = clk_prepare_enable(tc->slow_clk); 250 if (ret) 251 return ret; 252 253 /* try to enable t2 clk to avoid future errors in mode change */ 254 ret = clk_prepare_enable(t2_clk); 255 if (ret) { 256 clk_disable_unprepare(tc->slow_clk); 257 return ret; 258 } 259 260 clk_disable(t2_clk); 261 262 clkevt.regs = tc->regs; 263 clkevt.clk = t2_clk; 264 265 timer_clock = clk32k_divisor_idx; 266 267 clkevt.clkevt.cpumask = cpumask_of(0); 268 269 ret = request_irq(irq, ch2_irq, IRQF_TIMER, "tc_clkevt", &clkevt); 270 if (ret) { 271 clk_unprepare(t2_clk); 272 clk_disable_unprepare(tc->slow_clk); 273 return ret; 274 } 275 276 clockevents_config_and_register(&clkevt.clkevt, 32768, 1, 0xffff); 277 278 return ret; 279} 280 281#else /* !CONFIG_GENERIC_CLOCKEVENTS */ 282 283static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx) 284{ 285 /* NOTHING */ 286 return 0; 287} 288 289#endif 290 291static void __init tcb_setup_dual_chan(struct atmel_tc *tc, int mck_divisor_idx) 292{ 293 /* channel 0: waveform mode, input mclk/8, clock TIOA0 on overflow */ 294 writel(mck_divisor_idx /* likely divide-by-8 */ 295 | ATMEL_TC_WAVE 296 | ATMEL_TC_WAVESEL_UP /* free-run */ 297 | ATMEL_TC_ACPA_SET /* TIOA0 rises at 0 */ 298 | ATMEL_TC_ACPC_CLEAR, /* (duty cycle 50%) */ 299 tcaddr + ATMEL_TC_REG(0, CMR)); 300 writel(0x0000, tcaddr + ATMEL_TC_REG(0, RA)); 301 writel(0x8000, tcaddr + ATMEL_TC_REG(0, RC)); 302 writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */ 303 writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR)); 304 305 /* channel 1: waveform mode, input TIOA0 */ 306 writel(ATMEL_TC_XC1 /* input: TIOA0 */ 307 | ATMEL_TC_WAVE 308 | ATMEL_TC_WAVESEL_UP, /* free-run */ 309 tcaddr + ATMEL_TC_REG(1, CMR)); 310 writel(0xff, tcaddr + ATMEL_TC_REG(1, IDR)); /* no irqs */ 311 writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(1, CCR)); 312 313 /* chain channel 0 to channel 1*/ 314 writel(ATMEL_TC_TC1XC1S_TIOA0, tcaddr + ATMEL_TC_BMR); 315 /* then reset all the timers */ 316 writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR); 317} 318 319static void __init tcb_setup_single_chan(struct atmel_tc *tc, int mck_divisor_idx) 320{ 321 /* channel 0: waveform mode, input mclk/8 */ 322 writel(mck_divisor_idx /* likely divide-by-8 */ 323 | ATMEL_TC_WAVE 324 | ATMEL_TC_WAVESEL_UP, /* free-run */ 325 tcaddr + ATMEL_TC_REG(0, CMR)); 326 writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */ 327 writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR)); 328 329 /* then reset all the timers */ 330 writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR); 331} 332 333static int __init tcb_clksrc_init(void) 334{ 335 static char bootinfo[] __initdata 336 = KERN_DEBUG "%s: tc%d at %d.%03d MHz\n"; 337 338 struct platform_device *pdev; 339 struct atmel_tc *tc; 340 struct clk *t0_clk; 341 u32 rate, divided_rate = 0; 342 int best_divisor_idx = -1; 343 int clk32k_divisor_idx = -1; 344 int i; 345 int ret; 346 347 tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK); 348 if (!tc) { 349 pr_debug("can't alloc TC for clocksource\n"); 350 return -ENODEV; 351 } 352 tcaddr = tc->regs; 353 pdev = tc->pdev; 354 355 t0_clk = tc->clk[0]; 356 ret = clk_prepare_enable(t0_clk); 357 if (ret) { 358 pr_debug("can't enable T0 clk\n"); 359 goto err_free_tc; 360 } 361 362 /* How fast will we be counting? Pick something over 5 MHz. */ 363 rate = (u32) clk_get_rate(t0_clk); 364 for (i = 0; i < 5; i++) { 365 unsigned divisor = atmel_tc_divisors[i]; 366 unsigned tmp; 367 368 /* remember 32 KiHz clock for later */ 369 if (!divisor) { 370 clk32k_divisor_idx = i; 371 continue; 372 } 373 374 tmp = rate / divisor; 375 pr_debug("TC: %u / %-3u [%d] --> %u\n", rate, divisor, i, tmp); 376 if (best_divisor_idx > 0) { 377 if (tmp < 5 * 1000 * 1000) 378 continue; 379 } 380 divided_rate = tmp; 381 best_divisor_idx = i; 382 } 383 384 385 printk(bootinfo, clksrc.name, CONFIG_ATMEL_TCB_CLKSRC_BLOCK, 386 divided_rate / 1000000, 387 ((divided_rate % 1000000) + 500) / 1000); 388 389 if (tc->tcb_config && tc->tcb_config->counter_width == 32) { 390 /* use apropriate function to read 32 bit counter */ 391 clksrc.read = tc_get_cycles32; 392 /* setup ony channel 0 */ 393 tcb_setup_single_chan(tc, best_divisor_idx); 394 } else { 395 /* tclib will give us three clocks no matter what the 396 * underlying platform supports. 397 */ 398 ret = clk_prepare_enable(tc->clk[1]); 399 if (ret) { 400 pr_debug("can't enable T1 clk\n"); 401 goto err_disable_t0; 402 } 403 /* setup both channel 0 & 1 */ 404 tcb_setup_dual_chan(tc, best_divisor_idx); 405 } 406 407 /* and away we go! */ 408 ret = clocksource_register_hz(&clksrc, divided_rate); 409 if (ret) 410 goto err_disable_t1; 411 412 /* channel 2: periodic and oneshot timer support */ 413 ret = setup_clkevents(tc, clk32k_divisor_idx); 414 if (ret) 415 goto err_unregister_clksrc; 416 417 return 0; 418 419err_unregister_clksrc: 420 clocksource_unregister(&clksrc); 421 422err_disable_t1: 423 if (!tc->tcb_config || tc->tcb_config->counter_width != 32) 424 clk_disable_unprepare(tc->clk[1]); 425 426err_disable_t0: 427 clk_disable_unprepare(t0_clk); 428 429err_free_tc: 430 atmel_tc_free(tc); 431 return ret; 432} 433arch_initcall(tcb_clksrc_init);