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 master 657 lines 15 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * SuperH Timer Support - TMU 4 * 5 * Copyright (C) 2009 Magnus Damm 6 */ 7 8#include <linux/clk.h> 9#include <linux/clockchips.h> 10#include <linux/clocksource.h> 11#include <linux/delay.h> 12#include <linux/err.h> 13#include <linux/init.h> 14#include <linux/interrupt.h> 15#include <linux/io.h> 16#include <linux/ioport.h> 17#include <linux/irq.h> 18#include <linux/module.h> 19#include <linux/of.h> 20#include <linux/platform_device.h> 21#include <linux/pm_domain.h> 22#include <linux/pm_runtime.h> 23#include <linux/sh_timer.h> 24#include <linux/slab.h> 25#include <linux/spinlock.h> 26 27#ifdef CONFIG_SUPERH 28#include <asm/platform_early.h> 29#endif 30 31enum sh_tmu_model { 32 SH_TMU, 33 SH_TMU_SH3, 34}; 35 36struct sh_tmu_device; 37 38struct sh_tmu_channel { 39 struct sh_tmu_device *tmu; 40 unsigned int index; 41 42 void __iomem *base; 43 int irq; 44 45 unsigned long periodic; 46 struct clock_event_device ced; 47 struct clocksource cs; 48 bool cs_enabled; 49 unsigned int enable_count; 50}; 51 52struct sh_tmu_device { 53 struct platform_device *pdev; 54 55 void __iomem *mapbase; 56 struct clk *clk; 57 unsigned long rate; 58 59 enum sh_tmu_model model; 60 61 raw_spinlock_t lock; /* Protect the shared start/stop register */ 62 63 struct sh_tmu_channel *channels; 64 unsigned int num_channels; 65 66 bool has_clockevent; 67 bool has_clocksource; 68}; 69 70#define TSTR -1 /* shared register */ 71#define TCOR 0 /* channel register */ 72#define TCNT 1 /* channel register */ 73#define TCR 2 /* channel register */ 74 75#define TCR_UNF (1 << 8) 76#define TCR_UNIE (1 << 5) 77#define TCR_TPSC_CLK4 (0 << 0) 78#define TCR_TPSC_CLK16 (1 << 0) 79#define TCR_TPSC_CLK64 (2 << 0) 80#define TCR_TPSC_CLK256 (3 << 0) 81#define TCR_TPSC_CLK1024 (4 << 0) 82#define TCR_TPSC_MASK (7 << 0) 83 84static inline unsigned long sh_tmu_read(struct sh_tmu_channel *ch, int reg_nr) 85{ 86 unsigned long offs; 87 88 if (reg_nr == TSTR) { 89 switch (ch->tmu->model) { 90 case SH_TMU_SH3: 91 return ioread8(ch->tmu->mapbase + 2); 92 case SH_TMU: 93 return ioread8(ch->tmu->mapbase + 4); 94 } 95 } 96 97 offs = reg_nr << 2; 98 99 if (reg_nr == TCR) 100 return ioread16(ch->base + offs); 101 else 102 return ioread32(ch->base + offs); 103} 104 105static inline void sh_tmu_write(struct sh_tmu_channel *ch, int reg_nr, 106 unsigned long value) 107{ 108 unsigned long offs; 109 110 if (reg_nr == TSTR) { 111 switch (ch->tmu->model) { 112 case SH_TMU_SH3: 113 return iowrite8(value, ch->tmu->mapbase + 2); 114 case SH_TMU: 115 return iowrite8(value, ch->tmu->mapbase + 4); 116 } 117 } 118 119 offs = reg_nr << 2; 120 121 if (reg_nr == TCR) 122 iowrite16(value, ch->base + offs); 123 else 124 iowrite32(value, ch->base + offs); 125} 126 127static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start) 128{ 129 unsigned long flags, value; 130 131 /* start stop register shared by multiple timer channels */ 132 raw_spin_lock_irqsave(&ch->tmu->lock, flags); 133 value = sh_tmu_read(ch, TSTR); 134 135 if (start) 136 value |= 1 << ch->index; 137 else 138 value &= ~(1 << ch->index); 139 140 sh_tmu_write(ch, TSTR, value); 141 raw_spin_unlock_irqrestore(&ch->tmu->lock, flags); 142} 143 144static int __sh_tmu_enable(struct sh_tmu_channel *ch) 145{ 146 /* make sure channel is disabled */ 147 sh_tmu_start_stop_ch(ch, 0); 148 149 /* maximum timeout */ 150 sh_tmu_write(ch, TCOR, 0xffffffff); 151 sh_tmu_write(ch, TCNT, 0xffffffff); 152 153 /* configure channel to parent clock / 4, irq off */ 154 sh_tmu_write(ch, TCR, TCR_TPSC_CLK4); 155 156 /* enable channel */ 157 sh_tmu_start_stop_ch(ch, 1); 158 159 return 0; 160} 161 162static int sh_tmu_enable(struct sh_tmu_channel *ch) 163{ 164 if (ch->enable_count++ > 0) 165 return 0; 166 167 dev_pm_syscore_device(&ch->tmu->pdev->dev, true); 168 169 return __sh_tmu_enable(ch); 170} 171 172static void __sh_tmu_disable(struct sh_tmu_channel *ch) 173{ 174 /* disable channel */ 175 sh_tmu_start_stop_ch(ch, 0); 176 177 /* disable interrupts in TMU block */ 178 sh_tmu_write(ch, TCR, TCR_TPSC_CLK4); 179} 180 181static void sh_tmu_disable(struct sh_tmu_channel *ch) 182{ 183 if (WARN_ON(ch->enable_count == 0)) 184 return; 185 186 if (--ch->enable_count > 0) 187 return; 188 189 __sh_tmu_disable(ch); 190 191 dev_pm_syscore_device(&ch->tmu->pdev->dev, false); 192} 193 194static void sh_tmu_set_next(struct sh_tmu_channel *ch, unsigned long delta, 195 int periodic) 196{ 197 /* stop timer */ 198 sh_tmu_start_stop_ch(ch, 0); 199 200 /* acknowledge interrupt */ 201 sh_tmu_read(ch, TCR); 202 203 /* enable interrupt */ 204 sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4); 205 206 /* reload delta value in case of periodic timer */ 207 if (periodic) 208 sh_tmu_write(ch, TCOR, delta); 209 else 210 sh_tmu_write(ch, TCOR, 0xffffffff); 211 212 sh_tmu_write(ch, TCNT, delta); 213 214 /* start timer */ 215 sh_tmu_start_stop_ch(ch, 1); 216} 217 218static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id) 219{ 220 struct sh_tmu_channel *ch = dev_id; 221 222 /* disable or acknowledge interrupt */ 223 if (clockevent_state_oneshot(&ch->ced)) 224 sh_tmu_write(ch, TCR, TCR_TPSC_CLK4); 225 else 226 sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4); 227 228 /* notify clockevent layer */ 229 ch->ced.event_handler(&ch->ced); 230 return IRQ_HANDLED; 231} 232 233static struct sh_tmu_channel *cs_to_sh_tmu(struct clocksource *cs) 234{ 235 return container_of(cs, struct sh_tmu_channel, cs); 236} 237 238static u64 sh_tmu_clocksource_read(struct clocksource *cs) 239{ 240 struct sh_tmu_channel *ch = cs_to_sh_tmu(cs); 241 242 return sh_tmu_read(ch, TCNT) ^ 0xffffffff; 243} 244 245static int sh_tmu_clocksource_enable(struct clocksource *cs) 246{ 247 struct sh_tmu_channel *ch = cs_to_sh_tmu(cs); 248 int ret; 249 250 if (WARN_ON(ch->cs_enabled)) 251 return 0; 252 253 ret = sh_tmu_enable(ch); 254 if (!ret) 255 ch->cs_enabled = true; 256 257 return ret; 258} 259 260static void sh_tmu_clocksource_disable(struct clocksource *cs) 261{ 262 struct sh_tmu_channel *ch = cs_to_sh_tmu(cs); 263 264 if (WARN_ON(!ch->cs_enabled)) 265 return; 266 267 sh_tmu_disable(ch); 268 ch->cs_enabled = false; 269} 270 271static void sh_tmu_clocksource_suspend(struct clocksource *cs) 272{ 273 struct sh_tmu_channel *ch = cs_to_sh_tmu(cs); 274 275 if (!ch->cs_enabled) 276 return; 277 278 if (--ch->enable_count == 0) { 279 __sh_tmu_disable(ch); 280 dev_pm_genpd_suspend(&ch->tmu->pdev->dev); 281 } 282} 283 284static void sh_tmu_clocksource_resume(struct clocksource *cs) 285{ 286 struct sh_tmu_channel *ch = cs_to_sh_tmu(cs); 287 288 if (!ch->cs_enabled) 289 return; 290 291 if (ch->enable_count++ == 0) { 292 dev_pm_genpd_resume(&ch->tmu->pdev->dev); 293 __sh_tmu_enable(ch); 294 } 295} 296 297static int sh_tmu_register_clocksource(struct sh_tmu_channel *ch, 298 const char *name) 299{ 300 struct clocksource *cs = &ch->cs; 301 302 cs->name = name; 303 cs->rating = 200; 304 cs->read = sh_tmu_clocksource_read; 305 cs->enable = sh_tmu_clocksource_enable; 306 cs->disable = sh_tmu_clocksource_disable; 307 cs->suspend = sh_tmu_clocksource_suspend; 308 cs->resume = sh_tmu_clocksource_resume; 309 cs->mask = CLOCKSOURCE_MASK(32); 310 cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; 311 312 dev_info(&ch->tmu->pdev->dev, "ch%u: used as clock source\n", 313 ch->index); 314 315 clocksource_register_hz(cs, ch->tmu->rate); 316 return 0; 317} 318 319static struct sh_tmu_channel *ced_to_sh_tmu(struct clock_event_device *ced) 320{ 321 return container_of(ced, struct sh_tmu_channel, ced); 322} 323 324static void sh_tmu_clock_event_start(struct sh_tmu_channel *ch, int periodic) 325{ 326 sh_tmu_enable(ch); 327 328 if (periodic) { 329 ch->periodic = (ch->tmu->rate + HZ/2) / HZ; 330 sh_tmu_set_next(ch, ch->periodic, 1); 331 } 332} 333 334static int sh_tmu_clock_event_shutdown(struct clock_event_device *ced) 335{ 336 struct sh_tmu_channel *ch = ced_to_sh_tmu(ced); 337 338 if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced)) 339 sh_tmu_disable(ch); 340 return 0; 341} 342 343static int sh_tmu_clock_event_set_state(struct clock_event_device *ced, 344 int periodic) 345{ 346 struct sh_tmu_channel *ch = ced_to_sh_tmu(ced); 347 348 /* deal with old setting first */ 349 if (clockevent_state_oneshot(ced) || clockevent_state_periodic(ced)) 350 sh_tmu_disable(ch); 351 352 dev_info(&ch->tmu->pdev->dev, "ch%u: used for %s clock events\n", 353 ch->index, periodic ? "periodic" : "oneshot"); 354 sh_tmu_clock_event_start(ch, periodic); 355 return 0; 356} 357 358static int sh_tmu_clock_event_set_oneshot(struct clock_event_device *ced) 359{ 360 return sh_tmu_clock_event_set_state(ced, 0); 361} 362 363static int sh_tmu_clock_event_set_periodic(struct clock_event_device *ced) 364{ 365 return sh_tmu_clock_event_set_state(ced, 1); 366} 367 368static int sh_tmu_clock_event_next(unsigned long delta, 369 struct clock_event_device *ced) 370{ 371 struct sh_tmu_channel *ch = ced_to_sh_tmu(ced); 372 373 BUG_ON(!clockevent_state_oneshot(ced)); 374 375 /* program new delta value */ 376 sh_tmu_set_next(ch, delta, 0); 377 return 0; 378} 379 380static void sh_tmu_clock_event_suspend(struct clock_event_device *ced) 381{ 382 dev_pm_genpd_suspend(&ced_to_sh_tmu(ced)->tmu->pdev->dev); 383} 384 385static void sh_tmu_clock_event_resume(struct clock_event_device *ced) 386{ 387 dev_pm_genpd_resume(&ced_to_sh_tmu(ced)->tmu->pdev->dev); 388} 389 390static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch, 391 const char *name) 392{ 393 struct clock_event_device *ced = &ch->ced; 394 int ret; 395 396 ced->name = name; 397 ced->features = CLOCK_EVT_FEAT_PERIODIC; 398 ced->features |= CLOCK_EVT_FEAT_ONESHOT; 399 ced->rating = 200; 400 ced->cpumask = cpu_possible_mask; 401 ced->set_next_event = sh_tmu_clock_event_next; 402 ced->set_state_shutdown = sh_tmu_clock_event_shutdown; 403 ced->set_state_periodic = sh_tmu_clock_event_set_periodic; 404 ced->set_state_oneshot = sh_tmu_clock_event_set_oneshot; 405 ced->suspend = sh_tmu_clock_event_suspend; 406 ced->resume = sh_tmu_clock_event_resume; 407 408 dev_info(&ch->tmu->pdev->dev, "ch%u: used for clock events\n", 409 ch->index); 410 411 clockevents_config_and_register(ced, ch->tmu->rate, 0x300, 0xffffffff); 412 413 ret = request_irq(ch->irq, sh_tmu_interrupt, 414 IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, 415 dev_name(&ch->tmu->pdev->dev), ch); 416 if (ret) { 417 dev_err(&ch->tmu->pdev->dev, "ch%u: failed to request irq %d\n", 418 ch->index, ch->irq); 419 return; 420 } 421} 422 423static int sh_tmu_register(struct sh_tmu_channel *ch, const char *name, 424 bool clockevent, bool clocksource) 425{ 426 if (clockevent) { 427 ch->tmu->has_clockevent = true; 428 sh_tmu_register_clockevent(ch, name); 429 } else if (clocksource) { 430 ch->tmu->has_clocksource = true; 431 sh_tmu_register_clocksource(ch, name); 432 } 433 434 return 0; 435} 436 437static int sh_tmu_channel_setup(struct sh_tmu_channel *ch, unsigned int index, 438 bool clockevent, bool clocksource, 439 struct sh_tmu_device *tmu) 440{ 441 /* Skip unused channels. */ 442 if (!clockevent && !clocksource) 443 return 0; 444 445 ch->tmu = tmu; 446 ch->index = index; 447 448 if (tmu->model == SH_TMU_SH3) 449 ch->base = tmu->mapbase + 4 + ch->index * 12; 450 else 451 ch->base = tmu->mapbase + 8 + ch->index * 12; 452 453 ch->irq = platform_get_irq(tmu->pdev, index); 454 if (ch->irq < 0) 455 return ch->irq; 456 457 ch->cs_enabled = false; 458 ch->enable_count = 0; 459 460 return sh_tmu_register(ch, dev_name(&tmu->pdev->dev), 461 clockevent, clocksource); 462} 463 464static int sh_tmu_map_memory(struct sh_tmu_device *tmu) 465{ 466 struct resource *res; 467 468 res = platform_get_resource(tmu->pdev, IORESOURCE_MEM, 0); 469 if (!res) { 470 dev_err(&tmu->pdev->dev, "failed to get I/O memory\n"); 471 return -ENXIO; 472 } 473 474 tmu->mapbase = ioremap(res->start, resource_size(res)); 475 if (tmu->mapbase == NULL) 476 return -ENXIO; 477 478 return 0; 479} 480 481static int sh_tmu_parse_dt(struct sh_tmu_device *tmu) 482{ 483 struct device_node *np = tmu->pdev->dev.of_node; 484 485 tmu->model = SH_TMU; 486 tmu->num_channels = 3; 487 488 of_property_read_u32(np, "#renesas,channels", &tmu->num_channels); 489 490 if (tmu->num_channels != 2 && tmu->num_channels != 3) { 491 dev_err(&tmu->pdev->dev, "invalid number of channels %u\n", 492 tmu->num_channels); 493 return -EINVAL; 494 } 495 496 return 0; 497} 498 499static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev) 500{ 501 unsigned int i; 502 int ret; 503 504 tmu->pdev = pdev; 505 506 raw_spin_lock_init(&tmu->lock); 507 508 if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { 509 ret = sh_tmu_parse_dt(tmu); 510 if (ret < 0) 511 return ret; 512 } else if (pdev->dev.platform_data) { 513 const struct platform_device_id *id = pdev->id_entry; 514 struct sh_timer_config *cfg = pdev->dev.platform_data; 515 516 tmu->model = id->driver_data; 517 tmu->num_channels = hweight8(cfg->channels_mask); 518 } else { 519 dev_err(&tmu->pdev->dev, "missing platform data\n"); 520 return -ENXIO; 521 } 522 523 /* Get hold of clock. */ 524 tmu->clk = clk_get(&tmu->pdev->dev, "fck"); 525 if (IS_ERR(tmu->clk)) { 526 dev_err(&tmu->pdev->dev, "cannot get clock\n"); 527 return PTR_ERR(tmu->clk); 528 } 529 530 ret = clk_prepare(tmu->clk); 531 if (ret < 0) 532 goto err_clk_put; 533 534 /* Determine clock rate. */ 535 ret = clk_enable(tmu->clk); 536 if (ret < 0) 537 goto err_clk_unprepare; 538 539 tmu->rate = clk_get_rate(tmu->clk) / 4; 540 541 /* Map the memory resource. */ 542 ret = sh_tmu_map_memory(tmu); 543 if (ret < 0) { 544 dev_err(&tmu->pdev->dev, "failed to remap I/O memory\n"); 545 goto err_clk_unprepare; 546 } 547 548 /* Allocate and setup the channels. */ 549 tmu->channels = kzalloc_objs(*tmu->channels, tmu->num_channels); 550 if (tmu->channels == NULL) { 551 ret = -ENOMEM; 552 goto err_unmap; 553 } 554 555 /* 556 * Use the first channel as a clock event device and the second channel 557 * as a clock source. 558 */ 559 for (i = 0; i < tmu->num_channels; ++i) { 560 ret = sh_tmu_channel_setup(&tmu->channels[i], i, 561 i == 0, i == 1, tmu); 562 if (ret < 0) 563 goto err_unmap; 564 } 565 566 platform_set_drvdata(pdev, tmu); 567 568 return 0; 569 570err_unmap: 571 kfree(tmu->channels); 572 iounmap(tmu->mapbase); 573err_clk_unprepare: 574 clk_unprepare(tmu->clk); 575err_clk_put: 576 clk_put(tmu->clk); 577 return ret; 578} 579 580static int sh_tmu_probe(struct platform_device *pdev) 581{ 582 struct sh_tmu_device *tmu = platform_get_drvdata(pdev); 583 int ret; 584 585 if (!is_sh_early_platform_device(pdev)) { 586 pm_runtime_set_active(&pdev->dev); 587 pm_runtime_enable(&pdev->dev); 588 } 589 590 if (tmu) { 591 dev_info(&pdev->dev, "kept as earlytimer\n"); 592 goto out; 593 } 594 595 tmu = kzalloc_obj(*tmu); 596 if (tmu == NULL) 597 return -ENOMEM; 598 599 ret = sh_tmu_setup(tmu, pdev); 600 if (ret) { 601 kfree(tmu); 602 pm_runtime_idle(&pdev->dev); 603 return ret; 604 } 605 606 if (is_sh_early_platform_device(pdev)) 607 return 0; 608 609 out: 610 if (tmu->has_clockevent || tmu->has_clocksource) 611 pm_runtime_irq_safe(&pdev->dev); 612 613 return 0; 614} 615 616static const struct platform_device_id sh_tmu_id_table[] = { 617 { "sh-tmu", SH_TMU }, 618 { "sh-tmu-sh3", SH_TMU_SH3 }, 619 { } 620}; 621MODULE_DEVICE_TABLE(platform, sh_tmu_id_table); 622 623static const struct of_device_id sh_tmu_of_table[] __maybe_unused = { 624 { .compatible = "renesas,tmu" }, 625 { } 626}; 627MODULE_DEVICE_TABLE(of, sh_tmu_of_table); 628 629static struct platform_driver sh_tmu_device_driver = { 630 .probe = sh_tmu_probe, 631 .driver = { 632 .name = "sh_tmu", 633 .of_match_table = of_match_ptr(sh_tmu_of_table), 634 .suppress_bind_attrs = true, 635 }, 636 .id_table = sh_tmu_id_table, 637}; 638 639static int __init sh_tmu_init(void) 640{ 641 return platform_driver_register(&sh_tmu_device_driver); 642} 643 644static void __exit sh_tmu_exit(void) 645{ 646 platform_driver_unregister(&sh_tmu_device_driver); 647} 648 649#ifdef CONFIG_SUPERH 650sh_early_platform_init("earlytimer", &sh_tmu_device_driver); 651#endif 652 653subsys_initcall(sh_tmu_init); 654module_exit(sh_tmu_exit); 655 656MODULE_AUTHOR("Magnus Damm"); 657MODULE_DESCRIPTION("SuperH TMU Timer Driver");