sh_cmt.c 22.0 KB
Newer Older
M
Magnus Damm 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 * SuperH Timer Support - CMT
 *
 *  Copyright (C) 2008 Magnus Damm
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/err.h>
29
#include <linux/delay.h>
M
Magnus Damm 已提交
30 31
#include <linux/clocksource.h>
#include <linux/clockchips.h>
32
#include <linux/sh_timer.h>
33
#include <linux/slab.h>
34
#include <linux/module.h>
35
#include <linux/pm_domain.h>
36
#include <linux/pm_runtime.h>
M
Magnus Damm 已提交
37

38
struct sh_cmt_device;
39 40

struct sh_cmt_channel {
41
	struct sh_cmt_device *cmt;
M
Magnus Damm 已提交
42 43 44 45 46 47

	unsigned long flags;
	unsigned long match_value;
	unsigned long next_match_value;
	unsigned long max_match_value;
	unsigned long rate;
48
	raw_spinlock_t lock;
M
Magnus Damm 已提交
49
	struct clock_event_device ced;
50
	struct clocksource cs;
M
Magnus Damm 已提交
51
	unsigned long total_cycles;
52
	bool cs_enabled;
53 54
};

55
struct sh_cmt_device {
56 57 58 59 60 61 62 63 64 65 66
	struct platform_device *pdev;

	void __iomem *mapbase;
	void __iomem *mapbase_str;
	struct clk *clk;

	struct sh_cmt_channel channel;

	unsigned long width; /* 16 or 32 bit version of hardware block */
	unsigned long overflow_bit;
	unsigned long clear_bits;
67

68 69 70 71 72
	/* callbacks for CMSTR and CMCSR access */
	unsigned long (*read_control)(void __iomem *base, unsigned long offs);
	void (*write_control)(void __iomem *base, unsigned long offs,
			      unsigned long value);

73 74 75 76
	/* callbacks for CMCNT and CMCOR access */
	unsigned long (*read_count)(void __iomem *base, unsigned long offs);
	void (*write_count)(void __iomem *base, unsigned long offs,
			    unsigned long value);
M
Magnus Damm 已提交
77 78
};

79 80 81 82 83 84 85 86 87 88 89 90 91
/* Examples of supported CMT timer register layouts and I/O access widths:
 *
 * "16-bit counter and 16-bit control" as found on sh7263:
 * CMSTR 0xfffec000 16-bit
 * CMCSR 0xfffec002 16-bit
 * CMCNT 0xfffec004 16-bit
 * CMCOR 0xfffec006 16-bit
 *
 * "32-bit counter and 16-bit control" as found on sh7372, sh73a0, r8a7740:
 * CMSTR 0xffca0000 16-bit
 * CMCSR 0xffca0060 16-bit
 * CMCNT 0xffca0064 32-bit
 * CMCOR 0xffca0068 32-bit
92 93 94 95 96 97
 *
 * "32-bit counter and 32-bit control" as found on r8a73a4 and r8a7790:
 * CMSTR 0xffca0500 32-bit
 * CMCSR 0xffca0510 32-bit
 * CMCNT 0xffca0514 32-bit
 * CMCOR 0xffca0518 32-bit
98 99
 */

100
static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
101 102 103 104
{
	return ioread16(base + (offs << 1));
}

105 106 107 108 109 110 111
static unsigned long sh_cmt_read32(void __iomem *base, unsigned long offs)
{
	return ioread32(base + (offs << 2));
}

static void sh_cmt_write16(void __iomem *base, unsigned long offs,
			   unsigned long value)
112 113 114
{
	iowrite16(value, base + (offs << 1));
}
M
Magnus Damm 已提交
115

116 117 118 119 120 121
static void sh_cmt_write32(void __iomem *base, unsigned long offs,
			   unsigned long value)
{
	iowrite32(value, base + (offs << 2));
}

M
Magnus Damm 已提交
122 123 124 125
#define CMCSR 0 /* channel register */
#define CMCNT 1 /* channel register */
#define CMCOR 2 /* channel register */

126
static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
127
{
128
	return ch->cmt->read_control(ch->cmt->mapbase_str, 0);
129 130
}

131
static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
132
{
133
	return ch->cmt->read_control(ch->cmt->mapbase, CMCSR);
134 135
}

136
static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
137
{
138
	return ch->cmt->read_count(ch->cmt->mapbase, CMCNT);
M
Magnus Damm 已提交
139 140
}

141
static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
142 143
				      unsigned long value)
{
144
	ch->cmt->write_control(ch->cmt->mapbase_str, 0, value);
145 146
}

147
static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch,
148 149
				      unsigned long value)
{
150
	ch->cmt->write_control(ch->cmt->mapbase, CMCSR, value);
151 152
}

153
static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch,
154 155
				      unsigned long value)
{
156
	ch->cmt->write_count(ch->cmt->mapbase, CMCNT, value);
157 158
}

159
static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch,
160 161
				      unsigned long value)
{
162
	ch->cmt->write_count(ch->cmt->mapbase, CMCOR, value);
163 164
}

165
static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
M
Magnus Damm 已提交
166 167 168
					int *has_wrapped)
{
	unsigned long v1, v2, v3;
169 170
	int o1, o2;

171
	o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->overflow_bit;
M
Magnus Damm 已提交
172 173 174

	/* Make sure the timer value is stable. Stolen from acpi_pm.c */
	do {
175
		o2 = o1;
176 177 178 179
		v1 = sh_cmt_read_cmcnt(ch);
		v2 = sh_cmt_read_cmcnt(ch);
		v3 = sh_cmt_read_cmcnt(ch);
		o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->overflow_bit;
180 181
	} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
			  || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
M
Magnus Damm 已提交
182

183
	*has_wrapped = o1;
M
Magnus Damm 已提交
184 185 186
	return v2;
}

187
static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
M
Magnus Damm 已提交
188

189
static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
M
Magnus Damm 已提交
190
{
191
	struct sh_timer_config *cfg = ch->cmt->pdev->dev.platform_data;
M
Magnus Damm 已提交
192 193 194
	unsigned long flags, value;

	/* start stop register shared by multiple timer channels */
195
	raw_spin_lock_irqsave(&sh_cmt_lock, flags);
196
	value = sh_cmt_read_cmstr(ch);
M
Magnus Damm 已提交
197 198 199 200 201 202

	if (start)
		value |= 1 << cfg->timer_bit;
	else
		value &= ~(1 << cfg->timer_bit);

203
	sh_cmt_write_cmstr(ch, value);
204
	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
M
Magnus Damm 已提交
205 206
}

207
static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate)
M
Magnus Damm 已提交
208
{
209
	int k, ret;
M
Magnus Damm 已提交
210

211 212
	pm_runtime_get_sync(&ch->cmt->pdev->dev);
	dev_pm_syscore_device(&ch->cmt->pdev->dev, true);
213

214
	/* enable clock */
215
	ret = clk_enable(ch->cmt->clk);
M
Magnus Damm 已提交
216
	if (ret) {
217
		dev_err(&ch->cmt->pdev->dev, "cannot enable clock\n");
218
		goto err0;
M
Magnus Damm 已提交
219 220 221
	}

	/* make sure channel is disabled */
222
	sh_cmt_start_stop_ch(ch, 0);
M
Magnus Damm 已提交
223 224

	/* configure channel, periodic mode and maximum timeout */
225 226 227
	if (ch->cmt->width == 16) {
		*rate = clk_get_rate(ch->cmt->clk) / 512;
		sh_cmt_write_cmcsr(ch, 0x43);
M
Magnus Damm 已提交
228
	} else {
229 230
		*rate = clk_get_rate(ch->cmt->clk) / 8;
		sh_cmt_write_cmcsr(ch, 0x01a4);
M
Magnus Damm 已提交
231
	}
M
Magnus Damm 已提交
232

233 234
	sh_cmt_write_cmcor(ch, 0xffffffff);
	sh_cmt_write_cmcnt(ch, 0);
M
Magnus Damm 已提交
235

236 237 238 239 240 241 242 243 244 245 246 247
	/*
	 * According to the sh73a0 user's manual, as CMCNT can be operated
	 * only by the RCLK (Pseudo 32 KHz), there's one restriction on
	 * modifying CMCNT register; two RCLK cycles are necessary before
	 * this register is either read or any modification of the value
	 * it holds is reflected in the LSI's actual operation.
	 *
	 * While at it, we're supposed to clear out the CMCNT as of this
	 * moment, so make sure it's processed properly here.  This will
	 * take RCLKx2 at maximum.
	 */
	for (k = 0; k < 100; k++) {
248
		if (!sh_cmt_read_cmcnt(ch))
249 250 251 252
			break;
		udelay(1);
	}

253 254
	if (sh_cmt_read_cmcnt(ch)) {
		dev_err(&ch->cmt->pdev->dev, "cannot clear CMCNT\n");
255 256 257 258
		ret = -ETIMEDOUT;
		goto err1;
	}

M
Magnus Damm 已提交
259
	/* enable channel */
260
	sh_cmt_start_stop_ch(ch, 1);
M
Magnus Damm 已提交
261
	return 0;
262 263
 err1:
	/* stop clock */
264
	clk_disable(ch->cmt->clk);
265 266 267

 err0:
	return ret;
M
Magnus Damm 已提交
268 269
}

270
static void sh_cmt_disable(struct sh_cmt_channel *ch)
M
Magnus Damm 已提交
271 272
{
	/* disable channel */
273
	sh_cmt_start_stop_ch(ch, 0);
M
Magnus Damm 已提交
274

275
	/* disable interrupts in CMT block */
276
	sh_cmt_write_cmcsr(ch, 0);
277

278
	/* stop clock */
279
	clk_disable(ch->cmt->clk);
280

281 282
	dev_pm_syscore_device(&ch->cmt->pdev->dev, false);
	pm_runtime_put(&ch->cmt->pdev->dev);
M
Magnus Damm 已提交
283 284 285 286 287 288 289 290 291
}

/* private flags */
#define FLAG_CLOCKEVENT (1 << 0)
#define FLAG_CLOCKSOURCE (1 << 1)
#define FLAG_REPROGRAM (1 << 2)
#define FLAG_SKIPEVENT (1 << 3)
#define FLAG_IRQCONTEXT (1 << 4)

292
static void sh_cmt_clock_event_program_verify(struct sh_cmt_channel *ch,
M
Magnus Damm 已提交
293 294 295
					      int absolute)
{
	unsigned long new_match;
296
	unsigned long value = ch->next_match_value;
M
Magnus Damm 已提交
297 298 299 300
	unsigned long delay = 0;
	unsigned long now = 0;
	int has_wrapped;

301 302
	now = sh_cmt_get_counter(ch, &has_wrapped);
	ch->flags |= FLAG_REPROGRAM; /* force reprogram */
M
Magnus Damm 已提交
303 304 305 306 307 308

	if (has_wrapped) {
		/* we're competing with the interrupt handler.
		 *  -> let the interrupt handler reprogram the timer.
		 *  -> interrupt number two handles the event.
		 */
309
		ch->flags |= FLAG_SKIPEVENT;
M
Magnus Damm 已提交
310 311 312 313 314 315 316 317 318 319 320
		return;
	}

	if (absolute)
		now = 0;

	do {
		/* reprogram the timer hardware,
		 * but don't save the new match value yet.
		 */
		new_match = now + value + delay;
321 322
		if (new_match > ch->max_match_value)
			new_match = ch->max_match_value;
M
Magnus Damm 已提交
323

324
		sh_cmt_write_cmcor(ch, new_match);
M
Magnus Damm 已提交
325

326 327
		now = sh_cmt_get_counter(ch, &has_wrapped);
		if (has_wrapped && (new_match > ch->match_value)) {
M
Magnus Damm 已提交
328 329 330 331 332 333
			/* we are changing to a greater match value,
			 * so this wrap must be caused by the counter
			 * matching the old value.
			 * -> first interrupt reprograms the timer.
			 * -> interrupt number two handles the event.
			 */
334
			ch->flags |= FLAG_SKIPEVENT;
M
Magnus Damm 已提交
335 336 337 338 339 340 341 342 343 344
			break;
		}

		if (has_wrapped) {
			/* we are changing to a smaller match value,
			 * so the wrap must be caused by the counter
			 * matching the new value.
			 * -> save programmed match value.
			 * -> let isr handle the event.
			 */
345
			ch->match_value = new_match;
M
Magnus Damm 已提交
346 347 348 349 350 351 352 353 354 355
			break;
		}

		/* be safe: verify hardware settings */
		if (now < new_match) {
			/* timer value is below match value, all good.
			 * this makes sure we won't miss any match events.
			 * -> save programmed match value.
			 * -> let isr handle the event.
			 */
356
			ch->match_value = new_match;
M
Magnus Damm 已提交
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
			break;
		}

		/* the counter has reached a value greater
		 * than our new match value. and since the
		 * has_wrapped flag isn't set we must have
		 * programmed a too close event.
		 * -> increase delay and retry.
		 */
		if (delay)
			delay <<= 1;
		else
			delay = 1;

		if (!delay)
372
			dev_warn(&ch->cmt->pdev->dev, "too long delay\n");
M
Magnus Damm 已提交
373 374 375 376

	} while (delay);
}

377
static void __sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta)
M
Magnus Damm 已提交
378
{
379 380
	if (delta > ch->max_match_value)
		dev_warn(&ch->cmt->pdev->dev, "delta out of range\n");
M
Magnus Damm 已提交
381

382 383
	ch->next_match_value = delta;
	sh_cmt_clock_event_program_verify(ch, 0);
384 385
}

386
static void sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta)
387 388 389
{
	unsigned long flags;

390 391 392
	raw_spin_lock_irqsave(&ch->lock, flags);
	__sh_cmt_set_next(ch, delta);
	raw_spin_unlock_irqrestore(&ch->lock, flags);
M
Magnus Damm 已提交
393 394 395 396
}

static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
{
397
	struct sh_cmt_channel *ch = dev_id;
M
Magnus Damm 已提交
398 399

	/* clear flags */
400
	sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) & ch->cmt->clear_bits);
M
Magnus Damm 已提交
401 402 403 404 405

	/* update clock source counter to begin with if enabled
	 * the wrap flag should be cleared by the timer specific
	 * isr before we end up here.
	 */
406 407
	if (ch->flags & FLAG_CLOCKSOURCE)
		ch->total_cycles += ch->match_value + 1;
M
Magnus Damm 已提交
408

409 410
	if (!(ch->flags & FLAG_REPROGRAM))
		ch->next_match_value = ch->max_match_value;
M
Magnus Damm 已提交
411

412
	ch->flags |= FLAG_IRQCONTEXT;
M
Magnus Damm 已提交
413

414 415 416 417 418
	if (ch->flags & FLAG_CLOCKEVENT) {
		if (!(ch->flags & FLAG_SKIPEVENT)) {
			if (ch->ced.mode == CLOCK_EVT_MODE_ONESHOT) {
				ch->next_match_value = ch->max_match_value;
				ch->flags |= FLAG_REPROGRAM;
M
Magnus Damm 已提交
419 420
			}

421
			ch->ced.event_handler(&ch->ced);
M
Magnus Damm 已提交
422 423 424
		}
	}

425
	ch->flags &= ~FLAG_SKIPEVENT;
M
Magnus Damm 已提交
426

427 428 429
	if (ch->flags & FLAG_REPROGRAM) {
		ch->flags &= ~FLAG_REPROGRAM;
		sh_cmt_clock_event_program_verify(ch, 1);
M
Magnus Damm 已提交
430

431 432 433 434
		if (ch->flags & FLAG_CLOCKEVENT)
			if ((ch->ced.mode == CLOCK_EVT_MODE_SHUTDOWN)
			    || (ch->match_value == ch->next_match_value))
				ch->flags &= ~FLAG_REPROGRAM;
M
Magnus Damm 已提交
435 436
	}

437
	ch->flags &= ~FLAG_IRQCONTEXT;
M
Magnus Damm 已提交
438 439 440 441

	return IRQ_HANDLED;
}

442
static int sh_cmt_start(struct sh_cmt_channel *ch, unsigned long flag)
M
Magnus Damm 已提交
443 444 445 446
{
	int ret = 0;
	unsigned long flags;

447
	raw_spin_lock_irqsave(&ch->lock, flags);
M
Magnus Damm 已提交
448

449 450
	if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
		ret = sh_cmt_enable(ch, &ch->rate);
M
Magnus Damm 已提交
451 452 453

	if (ret)
		goto out;
454
	ch->flags |= flag;
M
Magnus Damm 已提交
455 456

	/* setup timeout if no clockevent */
457 458
	if ((flag == FLAG_CLOCKSOURCE) && (!(ch->flags & FLAG_CLOCKEVENT)))
		__sh_cmt_set_next(ch, ch->max_match_value);
M
Magnus Damm 已提交
459
 out:
460
	raw_spin_unlock_irqrestore(&ch->lock, flags);
M
Magnus Damm 已提交
461 462 463 464

	return ret;
}

465
static void sh_cmt_stop(struct sh_cmt_channel *ch, unsigned long flag)
M
Magnus Damm 已提交
466 467 468 469
{
	unsigned long flags;
	unsigned long f;

470
	raw_spin_lock_irqsave(&ch->lock, flags);
M
Magnus Damm 已提交
471

472 473
	f = ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE);
	ch->flags &= ~flag;
M
Magnus Damm 已提交
474

475 476
	if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
		sh_cmt_disable(ch);
M
Magnus Damm 已提交
477 478

	/* adjust the timeout to maximum if only clocksource left */
479 480
	if ((flag == FLAG_CLOCKEVENT) && (ch->flags & FLAG_CLOCKSOURCE))
		__sh_cmt_set_next(ch, ch->max_match_value);
M
Magnus Damm 已提交
481

482
	raw_spin_unlock_irqrestore(&ch->lock, flags);
M
Magnus Damm 已提交
483 484
}

485
static struct sh_cmt_channel *cs_to_sh_cmt(struct clocksource *cs)
486
{
487
	return container_of(cs, struct sh_cmt_channel, cs);
488 489 490 491
}

static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
{
492
	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
493 494 495 496
	unsigned long flags, raw;
	unsigned long value;
	int has_wrapped;

497 498 499
	raw_spin_lock_irqsave(&ch->lock, flags);
	value = ch->total_cycles;
	raw = sh_cmt_get_counter(ch, &has_wrapped);
500 501

	if (unlikely(has_wrapped))
502 503
		raw += ch->match_value + 1;
	raw_spin_unlock_irqrestore(&ch->lock, flags);
504 505 506 507 508 509

	return value + raw;
}

static int sh_cmt_clocksource_enable(struct clocksource *cs)
{
510
	int ret;
511
	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
512

513
	WARN_ON(ch->cs_enabled);
514

515
	ch->total_cycles = 0;
516

517
	ret = sh_cmt_start(ch, FLAG_CLOCKSOURCE);
518
	if (!ret) {
519 520
		__clocksource_updatefreq_hz(cs, ch->rate);
		ch->cs_enabled = true;
521
	}
522
	return ret;
523 524 525 526
}

static void sh_cmt_clocksource_disable(struct clocksource *cs)
{
527
	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
528

529
	WARN_ON(!ch->cs_enabled);
530

531 532
	sh_cmt_stop(ch, FLAG_CLOCKSOURCE);
	ch->cs_enabled = false;
533 534
}

535 536
static void sh_cmt_clocksource_suspend(struct clocksource *cs)
{
537
	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
538

539 540
	sh_cmt_stop(ch, FLAG_CLOCKSOURCE);
	pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev);
541 542
}

543 544
static void sh_cmt_clocksource_resume(struct clocksource *cs)
{
545
	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
546

547 548
	pm_genpd_syscore_poweron(&ch->cmt->pdev->dev);
	sh_cmt_start(ch, FLAG_CLOCKSOURCE);
549 550
}

551
static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch,
552 553
				       char *name, unsigned long rating)
{
554
	struct clocksource *cs = &ch->cs;
555 556 557 558 559 560

	cs->name = name;
	cs->rating = rating;
	cs->read = sh_cmt_clocksource_read;
	cs->enable = sh_cmt_clocksource_enable;
	cs->disable = sh_cmt_clocksource_disable;
561
	cs->suspend = sh_cmt_clocksource_suspend;
562
	cs->resume = sh_cmt_clocksource_resume;
563 564
	cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
565

566
	dev_info(&ch->cmt->pdev->dev, "used as clock source\n");
567

568 569
	/* Register with dummy 1 Hz value, gets updated in ->enable() */
	clocksource_register_hz(cs, 1);
570 571 572
	return 0;
}

573
static struct sh_cmt_channel *ced_to_sh_cmt(struct clock_event_device *ced)
M
Magnus Damm 已提交
574
{
575
	return container_of(ced, struct sh_cmt_channel, ced);
M
Magnus Damm 已提交
576 577
}

578
static void sh_cmt_clock_event_start(struct sh_cmt_channel *ch, int periodic)
M
Magnus Damm 已提交
579
{
580
	struct clock_event_device *ced = &ch->ced;
M
Magnus Damm 已提交
581

582
	sh_cmt_start(ch, FLAG_CLOCKEVENT);
M
Magnus Damm 已提交
583 584 585 586

	/* TODO: calculate good shift from rate and counter bit width */

	ced->shift = 32;
587 588
	ced->mult = div_sc(ch->rate, NSEC_PER_SEC, ced->shift);
	ced->max_delta_ns = clockevent_delta2ns(ch->max_match_value, ced);
M
Magnus Damm 已提交
589 590 591
	ced->min_delta_ns = clockevent_delta2ns(0x1f, ced);

	if (periodic)
592
		sh_cmt_set_next(ch, ((ch->rate + HZ/2) / HZ) - 1);
M
Magnus Damm 已提交
593
	else
594
		sh_cmt_set_next(ch, ch->max_match_value);
M
Magnus Damm 已提交
595 596 597 598 599
}

static void sh_cmt_clock_event_mode(enum clock_event_mode mode,
				    struct clock_event_device *ced)
{
600
	struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
M
Magnus Damm 已提交
601 602 603 604 605

	/* deal with old setting first */
	switch (ced->mode) {
	case CLOCK_EVT_MODE_PERIODIC:
	case CLOCK_EVT_MODE_ONESHOT:
606
		sh_cmt_stop(ch, FLAG_CLOCKEVENT);
M
Magnus Damm 已提交
607 608 609 610 611 612 613
		break;
	default:
		break;
	}

	switch (mode) {
	case CLOCK_EVT_MODE_PERIODIC:
614 615 616
		dev_info(&ch->cmt->pdev->dev,
			 "used for periodic clock events\n");
		sh_cmt_clock_event_start(ch, 1);
M
Magnus Damm 已提交
617 618
		break;
	case CLOCK_EVT_MODE_ONESHOT:
619 620 621
		dev_info(&ch->cmt->pdev->dev,
			 "used for oneshot clock events\n");
		sh_cmt_clock_event_start(ch, 0);
M
Magnus Damm 已提交
622 623 624
		break;
	case CLOCK_EVT_MODE_SHUTDOWN:
	case CLOCK_EVT_MODE_UNUSED:
625
		sh_cmt_stop(ch, FLAG_CLOCKEVENT);
M
Magnus Damm 已提交
626 627 628 629 630 631 632 633 634
		break;
	default:
		break;
	}
}

static int sh_cmt_clock_event_next(unsigned long delta,
				   struct clock_event_device *ced)
{
635
	struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
M
Magnus Damm 已提交
636 637

	BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
638 639
	if (likely(ch->flags & FLAG_IRQCONTEXT))
		ch->next_match_value = delta - 1;
M
Magnus Damm 已提交
640
	else
641
		sh_cmt_set_next(ch, delta - 1);
M
Magnus Damm 已提交
642 643 644 645

	return 0;
}

646 647
static void sh_cmt_clock_event_suspend(struct clock_event_device *ced)
{
648
	struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
649

650 651
	pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev);
	clk_unprepare(ch->cmt->clk);
652 653 654 655
}

static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
{
656
	struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
657

658 659
	clk_prepare(ch->cmt->clk);
	pm_genpd_syscore_poweron(&ch->cmt->pdev->dev);
660 661
}

662
static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
M
Magnus Damm 已提交
663 664
				       char *name, unsigned long rating)
{
665
	struct clock_event_device *ced = &ch->ced;
M
Magnus Damm 已提交
666 667 668 669 670 671 672 673 674 675

	memset(ced, 0, sizeof(*ced));

	ced->name = name;
	ced->features = CLOCK_EVT_FEAT_PERIODIC;
	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
	ced->rating = rating;
	ced->cpumask = cpumask_of(0);
	ced->set_next_event = sh_cmt_clock_event_next;
	ced->set_mode = sh_cmt_clock_event_mode;
676 677
	ced->suspend = sh_cmt_clock_event_suspend;
	ced->resume = sh_cmt_clock_event_resume;
M
Magnus Damm 已提交
678

679
	dev_info(&ch->cmt->pdev->dev, "used for clock events\n");
M
Magnus Damm 已提交
680 681 682
	clockevents_register_device(ced);
}

683
static int sh_cmt_register(struct sh_cmt_channel *ch, char *name,
684 685
			   unsigned long clockevent_rating,
			   unsigned long clocksource_rating)
M
Magnus Damm 已提交
686 687
{
	if (clockevent_rating)
688
		sh_cmt_register_clockevent(ch, name, clockevent_rating);
M
Magnus Damm 已提交
689

690
	if (clocksource_rating)
691
		sh_cmt_register_clocksource(ch, name, clocksource_rating);
692

M
Magnus Damm 已提交
693 694 695
	return 0;
}

696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
static int sh_cmt_setup_channel(struct sh_cmt_channel *ch,
				struct sh_cmt_device *cmt)
{
	struct sh_timer_config *cfg = cmt->pdev->dev.platform_data;
	int irq;
	int ret;

	memset(ch, 0, sizeof(*ch));
	ch->cmt = cmt;

	irq = platform_get_irq(cmt->pdev, 0);
	if (irq < 0) {
		dev_err(&cmt->pdev->dev, "failed to get irq\n");
		return irq;
	}

	if (cmt->width == (sizeof(ch->max_match_value) * 8))
		ch->max_match_value = ~0;
	else
		ch->max_match_value = (1 << cmt->width) - 1;

	ch->match_value = ch->max_match_value;
	raw_spin_lock_init(&ch->lock);

	ret = sh_cmt_register(ch, (char *)dev_name(&cmt->pdev->dev),
			      cfg->clockevent_rating,
			      cfg->clocksource_rating);
	if (ret) {
		dev_err(&cmt->pdev->dev, "registration failed\n");
		return ret;
	}
	ch->cs_enabled = false;

	ret = request_irq(irq, sh_cmt_interrupt,
			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
			  dev_name(&cmt->pdev->dev), ch);
	if (ret) {
		dev_err(&cmt->pdev->dev, "failed to request irq %d\n", irq);
		return ret;
	}

	return 0;
}

740
static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
M
Magnus Damm 已提交
741
{
742
	struct sh_timer_config *cfg = pdev->dev.platform_data;
743
	struct resource *res, *res2;
744
	int ret;
M
Magnus Damm 已提交
745 746
	ret = -ENXIO;

747 748
	memset(cmt, 0, sizeof(*cmt));
	cmt->pdev = pdev;
M
Magnus Damm 已提交
749 750

	if (!cfg) {
751
		dev_err(&cmt->pdev->dev, "missing platform data\n");
M
Magnus Damm 已提交
752 753 754
		goto err0;
	}

755
	res = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 0);
M
Magnus Damm 已提交
756
	if (!res) {
757
		dev_err(&cmt->pdev->dev, "failed to get I/O memory\n");
M
Magnus Damm 已提交
758 759 760
		goto err0;
	}

761
	/* optional resource for the shared timer start/stop register */
762
	res2 = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 1);
763

M
Magnus Damm 已提交
764
	/* map memory, let mapbase point to our channel */
765 766 767
	cmt->mapbase = ioremap_nocache(res->start, resource_size(res));
	if (cmt->mapbase == NULL) {
		dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n");
M
Magnus Damm 已提交
768 769 770
		goto err0;
	}

771
	/* map second resource for CMSTR */
772 773 774 775 776
	cmt->mapbase_str = ioremap_nocache(res2 ? res2->start :
					   res->start - cfg->channel_offset,
					   res2 ? resource_size(res2) : 2);
	if (cmt->mapbase_str == NULL) {
		dev_err(&cmt->pdev->dev, "failed to remap I/O second memory\n");
777 778 779
		goto err1;
	}

M
Magnus Damm 已提交
780
	/* get hold of clock */
781 782 783 784
	cmt->clk = clk_get(&cmt->pdev->dev, "cmt_fck");
	if (IS_ERR(cmt->clk)) {
		dev_err(&cmt->pdev->dev, "cannot get clock\n");
		ret = PTR_ERR(cmt->clk);
785
		goto err2;
M
Magnus Damm 已提交
786 787
	}

788
	ret = clk_prepare(cmt->clk);
789 790 791
	if (ret < 0)
		goto err3;

792 793
	if (res2 && (resource_size(res2) == 4)) {
		/* assume both CMSTR and CMCSR to be 32-bit */
794 795
		cmt->read_control = sh_cmt_read32;
		cmt->write_control = sh_cmt_write32;
796
	} else {
797 798
		cmt->read_control = sh_cmt_read16;
		cmt->write_control = sh_cmt_write16;
799
	}
800

M
Magnus Damm 已提交
801
	if (resource_size(res) == 6) {
802 803 804 805 806
		cmt->width = 16;
		cmt->read_count = sh_cmt_read16;
		cmt->write_count = sh_cmt_write16;
		cmt->overflow_bit = 0x80;
		cmt->clear_bits = ~0x80;
M
Magnus Damm 已提交
807
	} else {
808 809 810 811 812
		cmt->width = 32;
		cmt->read_count = sh_cmt_read32;
		cmt->write_count = sh_cmt_write32;
		cmt->overflow_bit = 0x8000;
		cmt->clear_bits = ~0xc000;
M
Magnus Damm 已提交
813 814
	}

815 816
	ret = sh_cmt_setup_channel(&cmt->channel, cmt);
	if (ret < 0)
817
		goto err4;
818

819
	platform_set_drvdata(pdev, cmt);
820

821
	return 0;
822
err4:
823
	clk_unprepare(cmt->clk);
824
err3:
825
	clk_put(cmt->clk);
826
err2:
827
	iounmap(cmt->mapbase_str);
828
err1:
829
	iounmap(cmt->mapbase);
830
err0:
M
Magnus Damm 已提交
831 832 833
	return ret;
}

834
static int sh_cmt_probe(struct platform_device *pdev)
M
Magnus Damm 已提交
835
{
836
	struct sh_cmt_device *cmt = platform_get_drvdata(pdev);
837
	struct sh_timer_config *cfg = pdev->dev.platform_data;
M
Magnus Damm 已提交
838 839
	int ret;

840
	if (!is_early_platform_device(pdev)) {
841 842
		pm_runtime_set_active(&pdev->dev);
		pm_runtime_enable(&pdev->dev);
843
	}
844

845
	if (cmt) {
846
		dev_info(&pdev->dev, "kept as earlytimer\n");
847
		goto out;
848 849
	}

850 851
	cmt = kmalloc(sizeof(*cmt), GFP_KERNEL);
	if (cmt == NULL) {
M
Magnus Damm 已提交
852 853 854 855
		dev_err(&pdev->dev, "failed to allocate driver data\n");
		return -ENOMEM;
	}

856
	ret = sh_cmt_setup(cmt, pdev);
M
Magnus Damm 已提交
857
	if (ret) {
858
		kfree(cmt);
859 860
		pm_runtime_idle(&pdev->dev);
		return ret;
M
Magnus Damm 已提交
861
	}
862 863 864 865 866 867 868 869 870 871
	if (is_early_platform_device(pdev))
		return 0;

 out:
	if (cfg->clockevent_rating || cfg->clocksource_rating)
		pm_runtime_irq_safe(&pdev->dev);
	else
		pm_runtime_idle(&pdev->dev);

	return 0;
M
Magnus Damm 已提交
872 873
}

874
static int sh_cmt_remove(struct platform_device *pdev)
M
Magnus Damm 已提交
875 876 877 878 879 880
{
	return -EBUSY; /* cannot unregister clockevent and clocksource */
}

static struct platform_driver sh_cmt_device_driver = {
	.probe		= sh_cmt_probe,
881
	.remove		= sh_cmt_remove,
M
Magnus Damm 已提交
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
	.driver		= {
		.name	= "sh_cmt",
	}
};

static int __init sh_cmt_init(void)
{
	return platform_driver_register(&sh_cmt_device_driver);
}

static void __exit sh_cmt_exit(void)
{
	platform_driver_unregister(&sh_cmt_device_driver);
}

897
early_platform_init("earlytimer", &sh_cmt_device_driver);
898
subsys_initcall(sh_cmt_init);
M
Magnus Damm 已提交
899 900 901 902 903
module_exit(sh_cmt_exit);

MODULE_AUTHOR("Magnus Damm");
MODULE_DESCRIPTION("SuperH CMT Timer Driver");
MODULE_LICENSE("GPL v2");