| 1 | |
| 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 |
|
| 31 | enum sh_tmu_model {
|
| 32 | SH_TMU,
|
| 33 | SH_TMU_SH3,
|
| 34 | };
|
| 35 |
|
| 36 | struct sh_tmu_device;
|
| 37 |
|
| 38 | struct 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 |
|
| 52 | struct 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;
|
| 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
|
| 71 | #define TCOR 0
|
| 72 | #define TCNT 1
|
| 73 | #define TCR 2
|
| 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 |
|
| 84 | static 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 |
|
| 105 | static 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 |
|
| 127 | static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start)
|
| 128 | {
|
| 129 | unsigned long flags, value;
|
| 130 |
|
| 131 |
|
| 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 |
|
| 144 | static int __sh_tmu_enable(struct sh_tmu_channel *ch)
|
| 145 | {
|
| 146 |
|
| 147 | sh_tmu_start_stop_ch(ch, 0);
|
| 148 |
|
| 149 |
|
| 150 | sh_tmu_write(ch, TCOR, 0xffffffff);
|
| 151 | sh_tmu_write(ch, TCNT, 0xffffffff);
|
| 152 |
|
| 153 |
|
| 154 | sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);
|
| 155 |
|
| 156 |
|
| 157 | sh_tmu_start_stop_ch(ch, 1);
|
| 158 |
|
| 159 | return 0;
|
| 160 | }
|
| 161 |
|
| 162 | static 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 |
|
| 172 | static void __sh_tmu_disable(struct sh_tmu_channel *ch)
|
| 173 | {
|
| 174 |
|
| 175 | sh_tmu_start_stop_ch(ch, 0);
|
| 176 |
|
| 177 |
|
| 178 | sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);
|
| 179 | }
|
| 180 |
|
| 181 | static 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 |
|
| 194 | static void sh_tmu_set_next(struct sh_tmu_channel *ch, unsigned long delta,
|
| 195 | int periodic)
|
| 196 | {
|
| 197 |
|
| 198 | sh_tmu_start_stop_ch(ch, 0);
|
| 199 |
|
| 200 |
|
| 201 | sh_tmu_read(ch, TCR);
|
| 202 |
|
| 203 |
|
| 204 | sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4);
|
| 205 |
|
| 206 |
|
| 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 |
|
| 215 | sh_tmu_start_stop_ch(ch, 1);
|
| 216 | }
|
| 217 |
|
| 218 | static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id)
|
| 219 | {
|
| 220 | struct sh_tmu_channel *ch = dev_id;
|
| 221 |
|
| 222 |
|
| 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 |
|
| 229 | ch->ced.event_handler(&ch->ced);
|
| 230 | return IRQ_HANDLED;
|
| 231 | }
|
| 232 |
|
| 233 | static struct sh_tmu_channel *cs_to_sh_tmu(struct clocksource *cs)
|
| 234 | {
|
| 235 | return container_of(cs, struct sh_tmu_channel, cs);
|
| 236 | }
|
| 237 |
|
| 238 | static 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 |
|
| 245 | static 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 |
|
| 260 | static 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 |
|
| 271 | static 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 |
|
| 284 | static 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 |
|
| 297 | static 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 |
|
| 319 | static 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 |
|
| 324 | static 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 |
|
| 334 | static 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 |
|
| 343 | static 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 |
|
| 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 |
|
| 358 | static 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 |
|
| 363 | static 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 |
|
| 368 | static 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 |
|
| 376 | sh_tmu_set_next(ch, delta, 0);
|
| 377 | return 0;
|
| 378 | }
|
| 379 |
|
| 380 | static 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 |
|
| 385 | static 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 |
|
| 390 | static 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 |
|
| 423 | static 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 |
|
| 437 | static 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 |
|
| 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 |
|
| 464 | static 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 |
|
| 481 | static 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 |
|
| 499 | static 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 570 | err_unmap:
|
| 571 | kfree(tmu->channels);
|
| 572 | iounmap(tmu->mapbase);
|
| 573 | err_clk_unprepare:
|
| 574 | clk_unprepare(tmu->clk);
|
| 575 | err_clk_put:
|
| 576 | clk_put(tmu->clk);
|
| 577 | return ret;
|
| 578 | }
|
| 579 |
|
| 580 | static 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 |
|
| 616 | static const struct platform_device_id sh_tmu_id_table[] = {
|
| 617 | { .name = "sh-tmu", .driver_data = SH_TMU },
|
| 618 | { .name = "sh-tmu-sh3", .driver_data = SH_TMU_SH3 },
|
| 619 | { }
|
| 620 | };
|
| 621 | MODULE_DEVICE_TABLE(platform, sh_tmu_id_table);
|
| 622 |
|
| 623 | static const struct of_device_id sh_tmu_of_table[] __maybe_unused = {
|
| 624 | { .compatible = "renesas,tmu" },
|
| 625 | { }
|
| 626 | };
|
| 627 | MODULE_DEVICE_TABLE(of, sh_tmu_of_table);
|
| 628 |
|
| 629 | static 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 |
|
| 639 | static int __init sh_tmu_init(void)
|
| 640 | {
|
| 641 | return platform_driver_register(&sh_tmu_device_driver);
|
| 642 | }
|
| 643 |
|
| 644 | static void __exit sh_tmu_exit(void)
|
| 645 | {
|
| 646 | platform_driver_unregister(&sh_tmu_device_driver);
|
| 647 | }
|
| 648 |
|
| 649 | #ifdef CONFIG_SUPERH
|
| 650 | sh_early_platform_init("earlytimer", &sh_tmu_device_driver);
|
| 651 | #endif
|
| 652 |
|
| 653 | subsys_initcall(sh_tmu_init);
|
| 654 | module_exit(sh_tmu_exit);
|
| 655 |
|
| 656 | MODULE_AUTHOR("Magnus Damm");
|
| 657 | MODULE_DESCRIPTION("SuperH TMU Timer Driver");
|