[PATCH 00/27] Renesas CMT (Compare Match Timer) DT bindings

STALE4551d

56 messages, 8 authors, 2014-02-18 · open the first message on its own page

[PATCH 00/27] Renesas CMT (Compare Match Timer) DT bindings

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 00:59:08

Hello,

This patch set adds DT support to the Renesas CMT driver.

The first 14 patches are a bunch of necessary cleanups that reorganize the
driver, its platform data, and the memory, interrupt and clock resources it
expects. As a result the driver accepts a new platform data model close to the
hardware with supports for all the timer channels using a single device.

The next 7 patches (15 to 21) move all platforms from the old to the new
platform data model. Patch 22 then drops support for the old model, and patch
23 finally adds DT support.

Patches 24 to 27 then add the CMT devices to the r8a7790 and r8a7791 device
trees, and enable them for the lager-reference and koelsch-reference boards.

The patches are based on top of Simon's latest devel branch with the
"[PATCH v4 0/2] [RESEND] Lager and Koelsch reference serial port support"
series applied.

Laurent Pinchart (27):
  clocksource: sh_cmt: Split channel fields from sh_cmt_priv
  clocksource: sh_cmt: Rename struct sh_cmt_priv to sh_cmt_device
  clocksource: sh_cmt: Split channel setup to separate function
  clocksource: sh_cmt: Rename mapbase/mapbase_str to mapbase_ch/mapbase
  clocksource: sh_cmt: Add memory base to sh_cmt_channel structure
  clocksource: sh_cmt: Add index to struct sh_cmt_channel
  clocksource: sh_cmt: Replace kmalloc + memset with kzalloc
  clocksource: sh_cmt: Allocate channels dynamically
  clocksource: sh_cmt: Split static information from sh_cmt_device
  clocksource: sh_cmt: Replace hardcoded register values with macros
  clocksource: sh_cmt: Add support for multiple channels per device
  clocksource: sh_cmt: Acquire default clock in the non-legacy case
  clocksource: sh_cmt: Remove FSF mail address from GPL notice
  clocksource: sh_cmt: Sort headers alphabetically
  sh: Switch to new style CMT device
  ARM: shmobile: sh7372: Switch to new style CMT device
  ARM: shmobile: sh73a0: Switch to new style CMT device
  ARM: shmobile: r8a73a4: Switch to new style CMT device
  ARM: shmobile: r8a7740: Switch to new style CMT device
  ARM: shmobile: r8a7790: Switch to new style CMT device
  ARM: shmobile: r8a7791: Switch to new style CMT device
  clocksource: sh_cmt: Drop support for legacy platform data
  clocksource: sh_cmt: Add DT support
  ARM: shmobile: r8a7790: Add CMT devices to DT
  ARM: shmobile: r8a7791: Add CMT devices to DT
  ARM: shmobile: lager-reference: Enable CMT0 in device tree
  ARM: shmobile: koelsch-reference: Enable CMT0 in device tree

 .../devicetree/bindings/timer/renesas,cmt.txt      |  75 ++
 arch/arm/boot/dts/r8a7790-lager.dts                |   9 +
 arch/arm/boot/dts/r8a7790.dtsi                     |  38 +
 arch/arm/boot/dts/r8a7791-koelsch.dts              |   9 +
 arch/arm/boot/dts/r8a7791.dtsi                     |  38 +
 arch/arm/mach-shmobile/board-koelsch-reference.c   |  15 +-
 arch/arm/mach-shmobile/board-lager-reference.c     |  15 +-
 arch/arm/mach-shmobile/clock-r8a73a4.c             |   2 +-
 arch/arm/mach-shmobile/clock-r8a7740.c             |   2 +-
 arch/arm/mach-shmobile/clock-r8a7790.c             |   2 +-
 arch/arm/mach-shmobile/clock-r8a7791.c             |   2 +-
 arch/arm/mach-shmobile/clock-sh7372.c              |   6 +-
 arch/arm/mach-shmobile/clock-sh73a0.c              |   2 +-
 arch/arm/mach-shmobile/include/mach/r8a7790.h      |   1 -
 arch/arm/mach-shmobile/include/mach/r8a7791.h      |   1 -
 arch/arm/mach-shmobile/setup-r8a73a4.c             |  25 +-
 arch/arm/mach-shmobile/setup-r8a7740.c             |  45 +-
 arch/arm/mach-shmobile/setup-r8a7790.c             |  31 +-
 arch/arm/mach-shmobile/setup-r8a7791.c             |  31 +-
 arch/arm/mach-shmobile/setup-sh7372.c              |  30 +-
 arch/arm/mach-shmobile/setup-sh73a0.c              |  45 +-
 arch/sh/kernel/cpu/clock-cpg.c                     |   3 +-
 arch/sh/kernel/cpu/sh2/setup-sh7619.c              |  73 +-
 arch/sh/kernel/cpu/sh2a/clock-sh7264.c             |   2 +-
 arch/sh/kernel/cpu/sh2a/clock-sh7269.c             |   2 +-
 arch/sh/kernel/cpu/sh2a/setup-sh7203.c             |  73 +-
 arch/sh/kernel/cpu/sh2a/setup-sh7206.c             |  73 +-
 arch/sh/kernel/cpu/sh2a/setup-sh7264.c             |  76 +-
 arch/sh/kernel/cpu/sh2a/setup-sh7269.c             |  73 +-
 arch/sh/kernel/cpu/sh3/setup-sh7720.c              | 155 +---
 arch/sh/kernel/cpu/sh4a/clock-sh7343.c             |   2 +-
 arch/sh/kernel/cpu/sh4a/clock-sh7366.c             |   2 +-
 arch/sh/kernel/cpu/sh4a/clock-sh7722.c             |   2 +-
 arch/sh/kernel/cpu/sh4a/clock-sh7723.c             |   2 +-
 arch/sh/kernel/cpu/sh4a/clock-sh7724.c             |   2 +-
 arch/sh/kernel/cpu/sh4a/setup-sh7343.c             |  28 +-
 arch/sh/kernel/cpu/sh4a/setup-sh7366.c             |  27 +-
 arch/sh/kernel/cpu/sh4a/setup-sh7722.c             |  28 +-
 arch/sh/kernel/cpu/sh4a/setup-sh7723.c             |  28 +-
 arch/sh/kernel/cpu/sh4a/setup-sh7724.c             |  28 +-
 drivers/clocksource/sh_cmt.c                       | 903 +++++++++++++--------
 include/linux/sh_timer.h                           |   9 +
 42 files changed, 1078 insertions(+), 937 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/renesas,cmt.txt

-- 
Regards,

Laurent Pinchart

[PATCH 01/27] clocksource: sh_cmt: Split channel fields from sh_cmt_priv

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 00:59:46

Create a new sh_cmt_channel structure to hold the channel-specific
field in preparation for multiple channels per device support.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 393 ++++++++++++++++++++++---------------------
 1 file changed, 204 insertions(+), 189 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 0b1836a..12ccd11 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -35,15 +35,12 @@
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 
-struct sh_cmt_priv {
-	void __iomem *mapbase;
-	void __iomem *mapbase_str;
-	struct clk *clk;
-	unsigned long width; /* 16 or 32 bit version of hardware block */
-	unsigned long overflow_bit;
-	unsigned long clear_bits;
+struct sh_cmt_priv;
+
+struct sh_cmt_channel {
+	struct sh_cmt_priv *cmt;
+
 	struct irqaction irqaction;
-	struct platform_device *pdev;
 
 	unsigned long flags;
 	unsigned long match_value;
@@ -55,6 +52,20 @@ struct sh_cmt_priv {
 	struct clocksource cs;
 	unsigned long total_cycles;
 	bool cs_enabled;
+};
+
+struct sh_cmt_priv {
+	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;
 
 	/* callbacks for CMSTR and CMCSR access */
 	unsigned long (*read_control)(void __iomem *base, unsigned long offs);
@@ -114,60 +125,60 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
 #define CMCNT 1 /* channel register */
 #define CMCOR 2 /* channel register */
 
-static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
+static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
 {
-	return p->read_control(p->mapbase_str, 0);
+	return ch->cmt->read_control(ch->cmt->mapbase_str, 0);
 }
 
-static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
+static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
 {
-	return p->read_control(p->mapbase, CMCSR);
+	return ch->cmt->read_control(ch->cmt->mapbase, CMCSR);
 }
 
-static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
+static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
 {
-	return p->read_count(p->mapbase, CMCNT);
+	return ch->cmt->read_count(ch->cmt->mapbase, CMCNT);
 }
 
-static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
+static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	p->write_control(p->mapbase_str, 0, value);
+	ch->cmt->write_control(ch->cmt->mapbase_str, 0, value);
 }
 
-static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
+static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	p->write_control(p->mapbase, CMCSR, value);
+	ch->cmt->write_control(ch->cmt->mapbase, CMCSR, value);
 }
 
-static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p,
+static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	p->write_count(p->mapbase, CMCNT, value);
+	ch->cmt->write_count(ch->cmt->mapbase, CMCNT, value);
 }
 
-static inline void sh_cmt_write_cmcor(struct sh_cmt_priv *p,
+static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	p->write_count(p->mapbase, CMCOR, value);
+	ch->cmt->write_count(ch->cmt->mapbase, CMCOR, value);
 }
 
-static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
+static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
 					int *has_wrapped)
 {
 	unsigned long v1, v2, v3;
 	int o1, o2;
 
-	o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit;
+	o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->overflow_bit;
 
 	/* Make sure the timer value is stable. Stolen from acpi_pm.c */
 	do {
 		o2 = o1;
-		v1 = sh_cmt_read_cmcnt(p);
-		v2 = sh_cmt_read_cmcnt(p);
-		v3 = sh_cmt_read_cmcnt(p);
-		o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit;
+		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;
 	} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
 			  || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
 
@@ -177,52 +188,52 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
 
 static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
 
-static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
+static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+	struct sh_timer_config *cfg = ch->cmt->pdev->dev.platform_data;
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
 	raw_spin_lock_irqsave(&sh_cmt_lock, flags);
-	value = sh_cmt_read_cmstr(p);
+	value = sh_cmt_read_cmstr(ch);
 
 	if (start)
 		value |= 1 << cfg->timer_bit;
 	else
 		value &= ~(1 << cfg->timer_bit);
 
-	sh_cmt_write_cmstr(p, value);
+	sh_cmt_write_cmstr(ch, value);
 	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
 }
 
-static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
+static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate)
 {
 	int k, ret;
 
-	pm_runtime_get_sync(&p->pdev->dev);
-	dev_pm_syscore_device(&p->pdev->dev, true);
+	pm_runtime_get_sync(&ch->cmt->pdev->dev);
+	dev_pm_syscore_device(&ch->cmt->pdev->dev, true);
 
 	/* enable clock */
-	ret = clk_enable(p->clk);
+	ret = clk_enable(ch->cmt->clk);
 	if (ret) {
-		dev_err(&p->pdev->dev, "cannot enable clock\n");
+		dev_err(&ch->cmt->pdev->dev, "cannot enable clock\n");
 		goto err0;
 	}
 
 	/* make sure channel is disabled */
-	sh_cmt_start_stop_ch(p, 0);
+	sh_cmt_start_stop_ch(ch, 0);
 
 	/* configure channel, periodic mode and maximum timeout */
-	if (p->width == 16) {
-		*rate = clk_get_rate(p->clk) / 512;
-		sh_cmt_write_cmcsr(p, 0x43);
+	if (ch->cmt->width == 16) {
+		*rate = clk_get_rate(ch->cmt->clk) / 512;
+		sh_cmt_write_cmcsr(ch, 0x43);
 	} else {
-		*rate = clk_get_rate(p->clk) / 8;
-		sh_cmt_write_cmcsr(p, 0x01a4);
+		*rate = clk_get_rate(ch->cmt->clk) / 8;
+		sh_cmt_write_cmcsr(ch, 0x01a4);
 	}
 
-	sh_cmt_write_cmcor(p, 0xffffffff);
-	sh_cmt_write_cmcnt(p, 0);
+	sh_cmt_write_cmcor(ch, 0xffffffff);
+	sh_cmt_write_cmcnt(ch, 0);
 
 	/*
 	 * According to the sh73a0 user's manual, as CMCNT can be operated
@@ -236,41 +247,41 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
 	 * take RCLKx2 at maximum.
 	 */
 	for (k = 0; k < 100; k++) {
-		if (!sh_cmt_read_cmcnt(p))
+		if (!sh_cmt_read_cmcnt(ch))
 			break;
 		udelay(1);
 	}
 
-	if (sh_cmt_read_cmcnt(p)) {
-		dev_err(&p->pdev->dev, "cannot clear CMCNT\n");
+	if (sh_cmt_read_cmcnt(ch)) {
+		dev_err(&ch->cmt->pdev->dev, "cannot clear CMCNT\n");
 		ret = -ETIMEDOUT;
 		goto err1;
 	}
 
 	/* enable channel */
-	sh_cmt_start_stop_ch(p, 1);
+	sh_cmt_start_stop_ch(ch, 1);
 	return 0;
  err1:
 	/* stop clock */
-	clk_disable(p->clk);
+	clk_disable(ch->cmt->clk);
 
  err0:
 	return ret;
 }
 
-static void sh_cmt_disable(struct sh_cmt_priv *p)
+static void sh_cmt_disable(struct sh_cmt_channel *ch)
 {
 	/* disable channel */
-	sh_cmt_start_stop_ch(p, 0);
+	sh_cmt_start_stop_ch(ch, 0);
 
 	/* disable interrupts in CMT block */
-	sh_cmt_write_cmcsr(p, 0);
+	sh_cmt_write_cmcsr(ch, 0);
 
 	/* stop clock */
-	clk_disable(p->clk);
+	clk_disable(ch->cmt->clk);
 
-	dev_pm_syscore_device(&p->pdev->dev, false);
-	pm_runtime_put(&p->pdev->dev);
+	dev_pm_syscore_device(&ch->cmt->pdev->dev, false);
+	pm_runtime_put(&ch->cmt->pdev->dev);
 }
 
 /* private flags */
@@ -280,24 +291,24 @@ static void sh_cmt_disable(struct sh_cmt_priv *p)
 #define FLAG_SKIPEVENT (1 << 3)
 #define FLAG_IRQCONTEXT (1 << 4)
 
-static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
+static void sh_cmt_clock_event_program_verify(struct sh_cmt_channel *ch,
 					      int absolute)
 {
 	unsigned long new_match;
-	unsigned long value = p->next_match_value;
+	unsigned long value = ch->next_match_value;
 	unsigned long delay = 0;
 	unsigned long now = 0;
 	int has_wrapped;
 
-	now = sh_cmt_get_counter(p, &has_wrapped);
-	p->flags |= FLAG_REPROGRAM; /* force reprogram */
+	now = sh_cmt_get_counter(ch, &has_wrapped);
+	ch->flags |= FLAG_REPROGRAM; /* force reprogram */
 
 	if (has_wrapped) {
 		/* we're competing with the interrupt handler.
 		 *  -> let the interrupt handler reprogram the timer.
 		 *  -> interrupt number two handles the event.
 		 */
-		p->flags |= FLAG_SKIPEVENT;
+		ch->flags |= FLAG_SKIPEVENT;
 		return;
 	}
 
@@ -309,20 +320,20 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
 		 * but don't save the new match value yet.
 		 */
 		new_match = now + value + delay;
-		if (new_match > p->max_match_value)
-			new_match = p->max_match_value;
+		if (new_match > ch->max_match_value)
+			new_match = ch->max_match_value;
 
-		sh_cmt_write_cmcor(p, new_match);
+		sh_cmt_write_cmcor(ch, new_match);
 
-		now = sh_cmt_get_counter(p, &has_wrapped);
-		if (has_wrapped && (new_match > p->match_value)) {
+		now = sh_cmt_get_counter(ch, &has_wrapped);
+		if (has_wrapped && (new_match > ch->match_value)) {
 			/* 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.
 			 */
-			p->flags |= FLAG_SKIPEVENT;
+			ch->flags |= FLAG_SKIPEVENT;
 			break;
 		}
 
@@ -333,7 +344,7 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
 			 * -> save programmed match value.
 			 * -> let isr handle the event.
 			 */
-			p->match_value = new_match;
+			ch->match_value = new_match;
 			break;
 		}
 
@@ -344,7 +355,7 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
 			 * -> save programmed match value.
 			 * -> let isr handle the event.
 			 */
-			p->match_value = new_match;
+			ch->match_value = new_match;
 			break;
 		}
 
@@ -360,138 +371,138 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
 			delay = 1;
 
 		if (!delay)
-			dev_warn(&p->pdev->dev, "too long delay\n");
+			dev_warn(&ch->cmt->pdev->dev, "too long delay\n");
 
 	} while (delay);
 }
 
-static void __sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
+static void __sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta)
 {
-	if (delta > p->max_match_value)
-		dev_warn(&p->pdev->dev, "delta out of range\n");
+	if (delta > ch->max_match_value)
+		dev_warn(&ch->cmt->pdev->dev, "delta out of range\n");
 
-	p->next_match_value = delta;
-	sh_cmt_clock_event_program_verify(p, 0);
+	ch->next_match_value = delta;
+	sh_cmt_clock_event_program_verify(ch, 0);
 }
 
-static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
+static void sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta)
 {
 	unsigned long flags;
 
-	raw_spin_lock_irqsave(&p->lock, flags);
-	__sh_cmt_set_next(p, delta);
-	raw_spin_unlock_irqrestore(&p->lock, flags);
+	raw_spin_lock_irqsave(&ch->lock, flags);
+	__sh_cmt_set_next(ch, delta);
+	raw_spin_unlock_irqrestore(&ch->lock, flags);
 }
 
 static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
 {
-	struct sh_cmt_priv *p = dev_id;
+	struct sh_cmt_channel *ch = dev_id;
 
 	/* clear flags */
-	sh_cmt_write_cmcsr(p, sh_cmt_read_cmcsr(p) & p->clear_bits);
+	sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) & ch->cmt->clear_bits);
 
 	/* 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.
 	 */
-	if (p->flags & FLAG_CLOCKSOURCE)
-		p->total_cycles += p->match_value + 1;
+	if (ch->flags & FLAG_CLOCKSOURCE)
+		ch->total_cycles += ch->match_value + 1;
 
-	if (!(p->flags & FLAG_REPROGRAM))
-		p->next_match_value = p->max_match_value;
+	if (!(ch->flags & FLAG_REPROGRAM))
+		ch->next_match_value = ch->max_match_value;
 
-	p->flags |= FLAG_IRQCONTEXT;
+	ch->flags |= FLAG_IRQCONTEXT;
 
-	if (p->flags & FLAG_CLOCKEVENT) {
-		if (!(p->flags & FLAG_SKIPEVENT)) {
-			if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT) {
-				p->next_match_value = p->max_match_value;
-				p->flags |= FLAG_REPROGRAM;
+	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;
 			}
 
-			p->ced.event_handler(&p->ced);
+			ch->ced.event_handler(&ch->ced);
 		}
 	}
 
-	p->flags &= ~FLAG_SKIPEVENT;
+	ch->flags &= ~FLAG_SKIPEVENT;
 
-	if (p->flags & FLAG_REPROGRAM) {
-		p->flags &= ~FLAG_REPROGRAM;
-		sh_cmt_clock_event_program_verify(p, 1);
+	if (ch->flags & FLAG_REPROGRAM) {
+		ch->flags &= ~FLAG_REPROGRAM;
+		sh_cmt_clock_event_program_verify(ch, 1);
 
-		if (p->flags & FLAG_CLOCKEVENT)
-			if ((p->ced.mode == CLOCK_EVT_MODE_SHUTDOWN)
-			    || (p->match_value == p->next_match_value))
-				p->flags &= ~FLAG_REPROGRAM;
+		if (ch->flags & FLAG_CLOCKEVENT)
+			if ((ch->ced.mode == CLOCK_EVT_MODE_SHUTDOWN)
+			    || (ch->match_value == ch->next_match_value))
+				ch->flags &= ~FLAG_REPROGRAM;
 	}
 
-	p->flags &= ~FLAG_IRQCONTEXT;
+	ch->flags &= ~FLAG_IRQCONTEXT;
 
 	return IRQ_HANDLED;
 }
 
-static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)
+static int sh_cmt_start(struct sh_cmt_channel *ch, unsigned long flag)
 {
 	int ret = 0;
 	unsigned long flags;
 
-	raw_spin_lock_irqsave(&p->lock, flags);
+	raw_spin_lock_irqsave(&ch->lock, flags);
 
-	if (!(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
-		ret = sh_cmt_enable(p, &p->rate);
+	if (!(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
+		ret = sh_cmt_enable(ch, &ch->rate);
 
 	if (ret)
 		goto out;
-	p->flags |= flag;
+	ch->flags |= flag;
 
 	/* setup timeout if no clockevent */
-	if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
-		__sh_cmt_set_next(p, p->max_match_value);
+	if ((flag == FLAG_CLOCKSOURCE) && (!(ch->flags & FLAG_CLOCKEVENT)))
+		__sh_cmt_set_next(ch, ch->max_match_value);
  out:
-	raw_spin_unlock_irqrestore(&p->lock, flags);
+	raw_spin_unlock_irqrestore(&ch->lock, flags);
 
 	return ret;
 }
 
-static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
+static void sh_cmt_stop(struct sh_cmt_channel *ch, unsigned long flag)
 {
 	unsigned long flags;
 	unsigned long f;
 
-	raw_spin_lock_irqsave(&p->lock, flags);
+	raw_spin_lock_irqsave(&ch->lock, flags);
 
-	f = p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE);
-	p->flags &= ~flag;
+	f = ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE);
+	ch->flags &= ~flag;
 
-	if (f && !(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
-		sh_cmt_disable(p);
+	if (f && !(ch->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE)))
+		sh_cmt_disable(ch);
 
 	/* adjust the timeout to maximum if only clocksource left */
-	if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
-		__sh_cmt_set_next(p, p->max_match_value);
+	if ((flag == FLAG_CLOCKEVENT) && (ch->flags & FLAG_CLOCKSOURCE))
+		__sh_cmt_set_next(ch, ch->max_match_value);
 
-	raw_spin_unlock_irqrestore(&p->lock, flags);
+	raw_spin_unlock_irqrestore(&ch->lock, flags);
 }
 
-static struct sh_cmt_priv *cs_to_sh_cmt(struct clocksource *cs)
+static struct sh_cmt_channel *cs_to_sh_cmt(struct clocksource *cs)
 {
-	return container_of(cs, struct sh_cmt_priv, cs);
+	return container_of(cs, struct sh_cmt_channel, cs);
 }
 
 static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
 {
-	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
 	unsigned long flags, raw;
 	unsigned long value;
 	int has_wrapped;
 
-	raw_spin_lock_irqsave(&p->lock, flags);
-	value = p->total_cycles;
-	raw = sh_cmt_get_counter(p, &has_wrapped);
+	raw_spin_lock_irqsave(&ch->lock, flags);
+	value = ch->total_cycles;
+	raw = sh_cmt_get_counter(ch, &has_wrapped);
 
 	if (unlikely(has_wrapped))
-		raw += p->match_value + 1;
-	raw_spin_unlock_irqrestore(&p->lock, flags);
+		raw += ch->match_value + 1;
+	raw_spin_unlock_irqrestore(&ch->lock, flags);
 
 	return value + raw;
 }
@@ -499,50 +510,50 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
 static int sh_cmt_clocksource_enable(struct clocksource *cs)
 {
 	int ret;
-	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
 
-	WARN_ON(p->cs_enabled);
+	WARN_ON(ch->cs_enabled);
 
-	p->total_cycles = 0;
+	ch->total_cycles = 0;
 
-	ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
+	ret = sh_cmt_start(ch, FLAG_CLOCKSOURCE);
 	if (!ret) {
-		__clocksource_updatefreq_hz(cs, p->rate);
-		p->cs_enabled = true;
+		__clocksource_updatefreq_hz(cs, ch->rate);
+		ch->cs_enabled = true;
 	}
 	return ret;
 }
 
 static void sh_cmt_clocksource_disable(struct clocksource *cs)
 {
-	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
 
-	WARN_ON(!p->cs_enabled);
+	WARN_ON(!ch->cs_enabled);
 
-	sh_cmt_stop(p, FLAG_CLOCKSOURCE);
-	p->cs_enabled = false;
+	sh_cmt_stop(ch, FLAG_CLOCKSOURCE);
+	ch->cs_enabled = false;
 }
 
 static void sh_cmt_clocksource_suspend(struct clocksource *cs)
 {
-	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
 
-	sh_cmt_stop(p, FLAG_CLOCKSOURCE);
-	pm_genpd_syscore_poweroff(&p->pdev->dev);
+	sh_cmt_stop(ch, FLAG_CLOCKSOURCE);
+	pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev);
 }
 
 static void sh_cmt_clocksource_resume(struct clocksource *cs)
 {
-	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
 
-	pm_genpd_syscore_poweron(&p->pdev->dev);
-	sh_cmt_start(p, FLAG_CLOCKSOURCE);
+	pm_genpd_syscore_poweron(&ch->cmt->pdev->dev);
+	sh_cmt_start(ch, FLAG_CLOCKSOURCE);
 }
 
-static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
+static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch,
 				       char *name, unsigned long rating)
 {
-	struct clocksource *cs = &p->cs;
+	struct clocksource *cs = &ch->cs;
 
 	cs->name = name;
 	cs->rating = rating;
@@ -554,47 +565,47 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
 	cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
 	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
 
-	dev_info(&p->pdev->dev, "used as clock source\n");
+	dev_info(&ch->cmt->pdev->dev, "used as clock source\n");
 
 	/* Register with dummy 1 Hz value, gets updated in ->enable() */
 	clocksource_register_hz(cs, 1);
 	return 0;
 }
 
-static struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced)
+static struct sh_cmt_channel *ced_to_sh_cmt(struct clock_event_device *ced)
 {
-	return container_of(ced, struct sh_cmt_priv, ced);
+	return container_of(ced, struct sh_cmt_channel, ced);
 }
 
-static void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic)
+static void sh_cmt_clock_event_start(struct sh_cmt_channel *ch, int periodic)
 {
-	struct clock_event_device *ced = &p->ced;
+	struct clock_event_device *ced = &ch->ced;
 
-	sh_cmt_start(p, FLAG_CLOCKEVENT);
+	sh_cmt_start(ch, FLAG_CLOCKEVENT);
 
 	/* TODO: calculate good shift from rate and counter bit width */
 
 	ced->shift = 32;
-	ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift);
-	ced->max_delta_ns = clockevent_delta2ns(p->max_match_value, ced);
+	ced->mult = div_sc(ch->rate, NSEC_PER_SEC, ced->shift);
+	ced->max_delta_ns = clockevent_delta2ns(ch->max_match_value, ced);
 	ced->min_delta_ns = clockevent_delta2ns(0x1f, ced);
 
 	if (periodic)
-		sh_cmt_set_next(p, ((p->rate + HZ/2) / HZ) - 1);
+		sh_cmt_set_next(ch, ((ch->rate + HZ/2) / HZ) - 1);
 	else
-		sh_cmt_set_next(p, p->max_match_value);
+		sh_cmt_set_next(ch, ch->max_match_value);
 }
 
 static void sh_cmt_clock_event_mode(enum clock_event_mode mode,
 				    struct clock_event_device *ced)
 {
-	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
+	struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
 
 	/* deal with old setting first */
 	switch (ced->mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 	case CLOCK_EVT_MODE_ONESHOT:
-		sh_cmt_stop(p, FLAG_CLOCKEVENT);
+		sh_cmt_stop(ch, FLAG_CLOCKEVENT);
 		break;
 	default:
 		break;
@@ -602,16 +613,18 @@ static void sh_cmt_clock_event_mode(enum clock_event_mode mode,
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		dev_info(&p->pdev->dev, "used for periodic clock events\n");
-		sh_cmt_clock_event_start(p, 1);
+		dev_info(&ch->cmt->pdev->dev,
+			 "used for periodic clock events\n");
+		sh_cmt_clock_event_start(ch, 1);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
-		dev_info(&p->pdev->dev, "used for oneshot clock events\n");
-		sh_cmt_clock_event_start(p, 0);
+		dev_info(&ch->cmt->pdev->dev,
+			 "used for oneshot clock events\n");
+		sh_cmt_clock_event_start(ch, 0);
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	case CLOCK_EVT_MODE_UNUSED:
-		sh_cmt_stop(p, FLAG_CLOCKEVENT);
+		sh_cmt_stop(ch, FLAG_CLOCKEVENT);
 		break;
 	default:
 		break;
@@ -621,37 +634,37 @@ static void sh_cmt_clock_event_mode(enum clock_event_mode mode,
 static int sh_cmt_clock_event_next(unsigned long delta,
 				   struct clock_event_device *ced)
 {
-	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
+	struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
 
 	BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
-	if (likely(p->flags & FLAG_IRQCONTEXT))
-		p->next_match_value = delta - 1;
+	if (likely(ch->flags & FLAG_IRQCONTEXT))
+		ch->next_match_value = delta - 1;
 	else
-		sh_cmt_set_next(p, delta - 1);
+		sh_cmt_set_next(ch, delta - 1);
 
 	return 0;
 }
 
 static void sh_cmt_clock_event_suspend(struct clock_event_device *ced)
 {
-	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
+	struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
 
-	pm_genpd_syscore_poweroff(&p->pdev->dev);
-	clk_unprepare(p->clk);
+	pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev);
+	clk_unprepare(ch->cmt->clk);
 }
 
 static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
 {
-	struct sh_cmt_priv *p = ced_to_sh_cmt(ced);
+	struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
 
-	clk_prepare(p->clk);
-	pm_genpd_syscore_poweron(&p->pdev->dev);
+	clk_prepare(ch->cmt->clk);
+	pm_genpd_syscore_poweron(&ch->cmt->pdev->dev);
 }
 
-static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
+static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
 				       char *name, unsigned long rating)
 {
-	struct clock_event_device *ced = &p->ced;
+	struct clock_event_device *ced = &ch->ced;
 
 	memset(ced, 0, sizeof(*ced));
 
@@ -665,19 +678,19 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
 	ced->suspend = sh_cmt_clock_event_suspend;
 	ced->resume = sh_cmt_clock_event_resume;
 
-	dev_info(&p->pdev->dev, "used for clock events\n");
+	dev_info(&ch->cmt->pdev->dev, "used for clock events\n");
 	clockevents_register_device(ced);
 }
 
-static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
+static int sh_cmt_register(struct sh_cmt_channel *ch, char *name,
 			   unsigned long clockevent_rating,
 			   unsigned long clocksource_rating)
 {
 	if (clockevent_rating)
-		sh_cmt_register_clockevent(p, name, clockevent_rating);
+		sh_cmt_register_clockevent(ch, name, clockevent_rating);
 
 	if (clocksource_rating)
-		sh_cmt_register_clocksource(p, name, clocksource_rating);
+		sh_cmt_register_clocksource(ch, name, clocksource_rating);
 
 	return 0;
 }
@@ -685,6 +698,7 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
 static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	struct sh_cmt_channel *ch = &p->channel;
 	struct resource *res, *res2;
 	int irq, ret;
 	ret = -ENXIO;
@@ -729,10 +743,10 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 	}
 
 	/* request irq using setup_irq() (too early for request_irq()) */
-	p->irqaction.name = dev_name(&p->pdev->dev);
-	p->irqaction.handler = sh_cmt_interrupt;
-	p->irqaction.dev_id = p;
-	p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
+	ch->irqaction.name = dev_name(&p->pdev->dev);
+	ch->irqaction.handler = sh_cmt_interrupt;
+	ch->irqaction.dev_id = ch;
+	ch->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
 
 	/* get hold of clock */
 	p->clk = clk_get(&p->pdev->dev, "cmt_fck");
@@ -769,24 +783,25 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 		p->clear_bits = ~0xc000;
 	}
 
-	if (p->width == (sizeof(p->max_match_value) * 8))
-		p->max_match_value = ~0;
+	if (p->width == (sizeof(ch->max_match_value) * 8))
+		ch->max_match_value = ~0;
 	else
-		p->max_match_value = (1 << p->width) - 1;
+		ch->max_match_value = (1 << p->width) - 1;
 
-	p->match_value = p->max_match_value;
-	raw_spin_lock_init(&p->lock);
+	ch->cmt = p;
+	ch->match_value = ch->max_match_value;
+	raw_spin_lock_init(&ch->lock);
 
-	ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev),
+	ret = sh_cmt_register(ch, (char *)dev_name(&p->pdev->dev),
 			      cfg->clockevent_rating,
 			      cfg->clocksource_rating);
 	if (ret) {
 		dev_err(&p->pdev->dev, "registration failed\n");
 		goto err4;
 	}
-	p->cs_enabled = false;
+	ch->cs_enabled = false;
 
-	ret = setup_irq(irq, &p->irqaction);
+	ret = setup_irq(irq, &ch->irqaction);
 	if (ret) {
 		dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
 		goto err4;
-- 
1.8.3.2

[PATCH 04/27] clocksource: sh_cmt: Rename mapbase/mapbase_str to mapbase_ch/mapbase

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 00:59:49

The mapbase variable points to the mapped base address of the channel,
rename it to mapbase_sh. mapbase_str points to the mapped base address
of the CMT device, rename it to mapbase.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 3a3cc83..1ac84ff 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -57,8 +57,8 @@ struct sh_cmt_channel {
 struct sh_cmt_device {
 	struct platform_device *pdev;
 
+	void __iomem *mapbase_ch;
 	void __iomem *mapbase;
-	void __iomem *mapbase_str;
 	struct clk *clk;
 
 	struct sh_cmt_channel channel;
@@ -127,41 +127,41 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
 
 static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
 {
-	return ch->cmt->read_control(ch->cmt->mapbase_str, 0);
+	return ch->cmt->read_control(ch->cmt->mapbase, 0);
 }
 
 static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
 {
-	return ch->cmt->read_control(ch->cmt->mapbase, CMCSR);
+	return ch->cmt->read_control(ch->cmt->mapbase_ch, CMCSR);
 }
 
 static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
 {
-	return ch->cmt->read_count(ch->cmt->mapbase, CMCNT);
+	return ch->cmt->read_count(ch->cmt->mapbase_ch, CMCNT);
 }
 
 static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->write_control(ch->cmt->mapbase_str, 0, value);
+	ch->cmt->write_control(ch->cmt->mapbase, 0, value);
 }
 
 static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->write_control(ch->cmt->mapbase, CMCSR, value);
+	ch->cmt->write_control(ch->cmt->mapbase_ch, CMCSR, value);
 }
 
 static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->write_count(ch->cmt->mapbase, CMCNT, value);
+	ch->cmt->write_count(ch->cmt->mapbase_ch, CMCNT, value);
 }
 
 static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->write_count(ch->cmt->mapbase, CMCOR, value);
+	ch->cmt->write_count(ch->cmt->mapbase_ch, CMCOR, value);
 }
 
 static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
@@ -767,18 +767,18 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 	/* optional resource for the shared timer start/stop register */
 	res2 = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 1);
 
-	/* map memory, let mapbase point to our channel */
-	cmt->mapbase = ioremap_nocache(res->start, resource_size(res));
-	if (cmt->mapbase == NULL) {
+	/* map memory, let mapbase_ch point to our channel */
+	cmt->mapbase_ch = ioremap_nocache(res->start, resource_size(res));
+	if (cmt->mapbase_ch == NULL) {
 		dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n");
 		goto err0;
 	}
 
 	/* map second resource for CMSTR */
-	cmt->mapbase_str = ioremap_nocache(res2 ? res2->start :
-					   res->start - cfg->channel_offset,
-					   res2 ? resource_size(res2) : 2);
-	if (cmt->mapbase_str == NULL) {
+	cmt->mapbase = ioremap_nocache(res2 ? res2->start :
+				       res->start - cfg->channel_offset,
+				       res2 ? resource_size(res2) : 2);
+	if (cmt->mapbase == NULL) {
 		dev_err(&cmt->pdev->dev, "failed to remap I/O second memory\n");
 		goto err1;
 	}
@@ -830,9 +830,9 @@ err4:
 err3:
 	clk_put(cmt->clk);
 err2:
-	iounmap(cmt->mapbase_str);
-err1:
 	iounmap(cmt->mapbase);
+err1:
+	iounmap(cmt->mapbase_ch);
 err0:
 	return ret;
 }
-- 
1.8.3.2

[PATCH 05/27] clocksource: sh_cmt: Add memory base to sh_cmt_channel structure

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 00:59:51

The channel memory base is channel-specific, add it to the channel
structure in preparation for support of multiple channels per device.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 1ac84ff..ec10cf4 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -40,6 +40,7 @@ struct sh_cmt_device;
 struct sh_cmt_channel {
 	struct sh_cmt_device *cmt;
 
+	void __iomem *base;
 	struct irqaction irqaction;
 
 	unsigned long flags;
@@ -132,12 +133,12 @@ static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
 
 static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
 {
-	return ch->cmt->read_control(ch->cmt->mapbase_ch, CMCSR);
+	return ch->cmt->read_control(ch->base, CMCSR);
 }
 
 static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
 {
-	return ch->cmt->read_count(ch->cmt->mapbase_ch, CMCNT);
+	return ch->cmt->read_count(ch->base, CMCNT);
 }
 
 static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
@@ -149,19 +150,19 @@ static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
 static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->write_control(ch->cmt->mapbase_ch, CMCSR, value);
+	ch->cmt->write_control(ch->base, CMCSR, value);
 }
 
 static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->write_count(ch->cmt->mapbase_ch, CMCNT, value);
+	ch->cmt->write_count(ch->base, CMCNT, value);
 }
 
 static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->write_count(ch->cmt->mapbase_ch, CMCOR, value);
+	ch->cmt->write_count(ch->base, CMCOR, value);
 }
 
 static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
@@ -704,6 +705,7 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch,
 
 	memset(ch, 0, sizeof(*ch));
 	ch->cmt = cmt;
+	ch->base = cmt->mapbase_ch;
 
 	/* Request irq using setup_irq() (too early for request_irq()). */
 	irq = platform_get_irq(cmt->pdev, 0);
-- 
1.8.3.2

[PATCH 06/27] clocksource: sh_cmt: Add index to struct sh_cmt_channel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 00:59:53

Use the index when printing messages to identify the channel.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index ec10cf4..0796460 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -39,6 +39,7 @@ struct sh_cmt_device;
 
 struct sh_cmt_channel {
 	struct sh_cmt_device *cmt;
+	unsigned int index;
 
 	void __iomem *base;
 	struct irqaction irqaction;
@@ -217,7 +218,8 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate)
 	/* enable clock */
 	ret = clk_enable(ch->cmt->clk);
 	if (ret) {
-		dev_err(&ch->cmt->pdev->dev, "cannot enable clock\n");
+		dev_err(&ch->cmt->pdev->dev, "ch%u: cannot enable clock\n",
+			ch->index);
 		goto err0;
 	}
 
@@ -254,7 +256,8 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate)
 	}
 
 	if (sh_cmt_read_cmcnt(ch)) {
-		dev_err(&ch->cmt->pdev->dev, "cannot clear CMCNT\n");
+		dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n",
+			ch->index);
 		ret = -ETIMEDOUT;
 		goto err1;
 	}
@@ -372,7 +375,8 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_channel *ch,
 			delay = 1;
 
 		if (!delay)
-			dev_warn(&ch->cmt->pdev->dev, "too long delay\n");
+			dev_warn(&ch->cmt->pdev->dev, "ch%u: too long delay\n",
+				 ch->index);
 
 	} while (delay);
 }
@@ -380,7 +384,8 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_channel *ch,
 static void __sh_cmt_set_next(struct sh_cmt_channel *ch, unsigned long delta)
 {
 	if (delta > ch->max_match_value)
-		dev_warn(&ch->cmt->pdev->dev, "delta out of range\n");
+		dev_warn(&ch->cmt->pdev->dev, "ch%u: delta out of range\n",
+			 ch->index);
 
 	ch->next_match_value = delta;
 	sh_cmt_clock_event_program_verify(ch, 0);
@@ -566,7 +571,8 @@ static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch,
 	cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
 	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
 
-	dev_info(&ch->cmt->pdev->dev, "used as clock source\n");
+	dev_info(&ch->cmt->pdev->dev, "ch%u: used as clock source\n",
+		 ch->index);
 
 	/* Register with dummy 1 Hz value, gets updated in ->enable() */
 	clocksource_register_hz(cs, 1);
@@ -615,12 +621,12 @@ static void sh_cmt_clock_event_mode(enum clock_event_mode mode,
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		dev_info(&ch->cmt->pdev->dev,
-			 "used for periodic clock events\n");
+			 "ch%u: used for periodic clock events\n", ch->index);
 		sh_cmt_clock_event_start(ch, 1);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		dev_info(&ch->cmt->pdev->dev,
-			 "used for oneshot clock events\n");
+			 "ch%u: used for oneshot clock events\n", ch->index);
 		sh_cmt_clock_event_start(ch, 0);
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
@@ -679,7 +685,8 @@ static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
 	ced->suspend = sh_cmt_clock_event_suspend;
 	ced->resume = sh_cmt_clock_event_resume;
 
-	dev_info(&ch->cmt->pdev->dev, "used for clock events\n");
+	dev_info(&ch->cmt->pdev->dev, "ch%u: used for clock events\n",
+		 ch->index);
 	clockevents_register_device(ced);
 }
 
@@ -696,7 +703,7 @@ static int sh_cmt_register(struct sh_cmt_channel *ch, char *name,
 	return 0;
 }
 
-static int sh_cmt_setup_channel(struct sh_cmt_channel *ch,
+static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 				struct sh_cmt_device *cmt)
 {
 	struct sh_timer_config *cfg = cmt->pdev->dev.platform_data;
@@ -706,6 +713,7 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch,
 	memset(ch, 0, sizeof(*ch));
 	ch->cmt = cmt;
 	ch->base = cmt->mapbase_ch;
+	ch->index = index;
 
 	/* Request irq using setup_irq() (too early for request_irq()). */
 	irq = platform_get_irq(cmt->pdev, 0);
@@ -820,7 +828,7 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 		cmt->clear_bits = ~0xc000;
 	}
 
-	ret = sh_cmt_setup_channel(&cmt->channel, cmt);
+	ret = sh_cmt_setup_channel(&cmt->channel, cfg->timer_bit, cmt);
 	if (ret < 0)
 		goto err4;
 
-- 
1.8.3.2

[PATCH 07/27] clocksource: sh_cmt: Replace kmalloc + memset with kzalloc

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 00:59:55

One kzalloc a day keeps the bugs away.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 0796460..cd3121d 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -673,8 +673,6 @@ static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
 {
 	struct clock_event_device *ced = &ch->ced;
 
-	memset(ced, 0, sizeof(*ced));
-
 	ced->name = name;
 	ced->features = CLOCK_EVT_FEAT_PERIODIC;
 	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
@@ -710,7 +708,6 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 	int irq;
 	int ret;
 
-	memset(ch, 0, sizeof(*ch));
 	ch->cmt = cmt;
 	ch->base = cmt->mapbase_ch;
 	ch->index = index;
@@ -760,7 +757,6 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 	int ret;
 	ret = -ENXIO;
 
-	memset(cmt, 0, sizeof(*cmt));
 	cmt->pdev = pdev;
 
 	if (!cfg) {
@@ -863,7 +859,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	cmt = kmalloc(sizeof(*cmt), GFP_KERNEL);
+	cmt = kzalloc(sizeof(*cmt), GFP_KERNEL);
 	if (cmt == NULL) {
 		dev_err(&pdev->dev, "failed to allocate driver data\n");
 		return -ENOMEM;
-- 
1.8.3.2

[PATCH 08/27] clocksource: sh_cmt: Allocate channels dynamically

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 00:59:56

This prepares the driver for multi-channel support.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index cd3121d..7a65d64 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -63,7 +63,8 @@ struct sh_cmt_device {
 	void __iomem *mapbase;
 	struct clk *clk;
 
-	struct sh_cmt_channel channel;
+	struct sh_cmt_channel *channels;
+	unsigned int num_channels;
 
 	unsigned long width; /* 16 or 32 bit version of hardware block */
 	unsigned long overflow_bit;
@@ -824,7 +825,15 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 		cmt->clear_bits = ~0xc000;
 	}
 
-	ret = sh_cmt_setup_channel(&cmt->channel, cfg->timer_bit, cmt);
+	cmt->channels = kzalloc(sizeof(*cmt->channels), GFP_KERNEL);
+	if (cmt->channels == NULL) {
+		ret = -ENOMEM;
+		goto err4;
+	}
+
+	cmt->num_channels = 1;
+
+	ret = sh_cmt_setup_channel(&cmt->channels[0], cfg->timer_bit, cmt);
 	if (ret < 0)
 		goto err4;
 
@@ -832,6 +841,7 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 
 	return 0;
 err4:
+	kfree(cmt->channels);
 	clk_unprepare(cmt->clk);
 err3:
 	clk_put(cmt->clk);
-- 
1.8.3.2

[PATCH 09/27] clocksource: sh_cmt: Split static information from sh_cmt_device

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 00:59:57

Create a new sh_cmt_info structure to hold static information about the
device model and reference that structure from the sh_cmt_device
structure.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 192 +++++++++++++++++++++++++++----------------
 1 file changed, 122 insertions(+), 70 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 7a65d64..3946c14 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -37,6 +37,52 @@
 
 struct sh_cmt_device;
 
+/*
+ * The CMT comes in 5 different identified flavours, depending not only on the
+ * SoC but also on the particular instance. The following table lists the main
+ * characteristics of those flavours.
+ *
+ *			16B	32B	32B-F	48B	48B-2
+ * -----------------------------------------------------------------------------
+ * Channels		2	1/4	1	6	2/8
+ * Control Width	16	16	16	16	32
+ * Counter Width	16	32	32	32/48	32/48
+ * Shared Start/Stop	Y	Y	Y	Y	N
+ *
+ * The 48-bit gen2 version has a per-channel start/stop register located in the
+ * channel registers block. All other versions have a shared start/stop register
+ * located in the global space.
+ *
+ * Note that CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing 32-bit
+ * channels only, is a 48-bit gen2 CMT with the 48-bit channels unavailable.
+ */
+
+enum sh_cmt_model {
+	SH_CMT_16BIT,
+	SH_CMT_32BIT,
+	SH_CMT_32BIT_FAST,
+	SH_CMT_48BIT,
+	SH_CMT_48BIT_GEN2,
+};
+
+struct sh_cmt_info {
+	enum sh_cmt_model model;
+
+	unsigned long width; /* 16 or 32 bit version of hardware block */
+	unsigned long overflow_bit;
+	unsigned long clear_bits;
+
+	/* 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);
+
+	/* 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);
+};
+
 struct sh_cmt_channel {
 	struct sh_cmt_device *cmt;
 	unsigned int index;
@@ -59,49 +105,16 @@ struct sh_cmt_channel {
 struct sh_cmt_device {
 	struct platform_device *pdev;
 
+	const struct sh_cmt_info *info;
+
 	void __iomem *mapbase_ch;
 	void __iomem *mapbase;
 	struct clk *clk;
 
 	struct sh_cmt_channel *channels;
 	unsigned int num_channels;
-
-	unsigned long width; /* 16 or 32 bit version of hardware block */
-	unsigned long overflow_bit;
-	unsigned long clear_bits;
-
-	/* 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);
-
-	/* 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);
 };
 
-/* 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
- *
- * "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
- */
-
 static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
 {
 	return ioread16(base + (offs << 1));
@@ -124,47 +137,100 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
 	iowrite32(value, base + (offs << 2));
 }
 
+static const struct sh_cmt_info sh_cmt_info[] = {
+	[SH_CMT_16BIT] = {
+		.model = SH_CMT_16BIT,
+		.width = 16,
+		.overflow_bit = 0x80,
+		.clear_bits = ~0x80,
+		.read_control = sh_cmt_read16,
+		.write_control = sh_cmt_write16,
+		.read_count = sh_cmt_read16,
+		.write_count = sh_cmt_write16,
+	},
+	[SH_CMT_32BIT] = {
+		.model = SH_CMT_32BIT,
+		.width = 32,
+		.overflow_bit = 0x8000,
+		.clear_bits = ~0xc000,
+		.read_control = sh_cmt_read16,
+		.write_control = sh_cmt_write16,
+		.read_count = sh_cmt_read32,
+		.write_count = sh_cmt_write32,
+	},
+	[SH_CMT_32BIT_FAST] = {
+		.model = SH_CMT_32BIT_FAST,
+		.width = 32,
+		.overflow_bit = 0x8000,
+		.clear_bits = ~0xc000,
+		.read_control = sh_cmt_read16,
+		.write_control = sh_cmt_write16,
+		.read_count = sh_cmt_read32,
+		.write_count = sh_cmt_write32,
+	},
+	[SH_CMT_48BIT] = {
+		.model = SH_CMT_48BIT,
+		.width = 32,
+		.overflow_bit = 0x8000,
+		.clear_bits = ~0xc000,
+		.read_control = sh_cmt_read32,
+		.write_control = sh_cmt_write32,
+		.read_count = sh_cmt_read32,
+		.write_count = sh_cmt_write32,
+	},
+	[SH_CMT_48BIT_GEN2] = {
+		.model = SH_CMT_48BIT_GEN2,
+		.width = 32,
+		.overflow_bit = 0x8000,
+		.clear_bits = ~0xc000,
+		.read_control = sh_cmt_read32,
+		.write_control = sh_cmt_write32,
+		.read_count = sh_cmt_read32,
+		.write_count = sh_cmt_write32,
+	},
+};
+
 #define CMCSR 0 /* channel register */
 #define CMCNT 1 /* channel register */
 #define CMCOR 2 /* channel register */
 
 static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
 {
-	return ch->cmt->read_control(ch->cmt->mapbase, 0);
+	return ch->cmt->info->read_control(ch->cmt->mapbase, 0);
 }
 
 static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
 {
-	return ch->cmt->read_control(ch->base, CMCSR);
+	return ch->cmt->info->read_control(ch->base, CMCSR);
 }
 
 static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
 {
-	return ch->cmt->read_count(ch->base, CMCNT);
+	return ch->cmt->info->read_count(ch->base, CMCNT);
 }
 
 static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->write_control(ch->cmt->mapbase, 0, value);
+	ch->cmt->info->write_control(ch->cmt->mapbase, 0, value);
 }
 
 static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->write_control(ch->base, CMCSR, value);
+	ch->cmt->info->write_control(ch->base, CMCSR, value);
 }
 
 static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->write_count(ch->base, CMCNT, value);
+	ch->cmt->info->write_count(ch->base, CMCNT, value);
 }
 
 static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->write_count(ch->base, CMCOR, value);
+	ch->cmt->info->write_count(ch->base, CMCOR, value);
 }
 
 static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
@@ -173,7 +239,7 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
 	unsigned long v1, v2, v3;
 	int o1, o2;
 
-	o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->overflow_bit;
+	o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit;
 
 	/* Make sure the timer value is stable. Stolen from acpi_pm.c */
 	do {
@@ -181,7 +247,7 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
 		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;
+		o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit;
 	} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
 			  || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
 
@@ -228,7 +294,7 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate)
 	sh_cmt_start_stop_ch(ch, 0);
 
 	/* configure channel, periodic mode and maximum timeout */
-	if (ch->cmt->width == 16) {
+	if (ch->cmt->info->width == 16) {
 		*rate = clk_get_rate(ch->cmt->clk) / 512;
 		sh_cmt_write_cmcsr(ch, 0x43);
 	} else {
@@ -406,7 +472,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
 	struct sh_cmt_channel *ch = dev_id;
 
 	/* clear flags */
-	sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) & ch->cmt->clear_bits);
+	sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) &
+			   ch->cmt->info->clear_bits);
 
 	/* update clock source counter to begin with if enabled
 	 * the wrap flag should be cleared by the timer specific
@@ -725,10 +792,10 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 	ch->irqaction.dev_id = ch;
 	ch->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
 
-	if (cmt->width == (sizeof(ch->max_match_value) * 8))
+	if (cmt->info->width == (sizeof(ch->max_match_value) * 8))
 		ch->max_match_value = ~0;
 	else
-		ch->max_match_value = (1 << cmt->width) - 1;
+		ch->max_match_value = (1 << cmt->info->width) - 1;
 
 	ch->match_value = ch->max_match_value;
 	raw_spin_lock_init(&ch->lock);
@@ -802,28 +869,13 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 	if (ret < 0)
 		goto err3;
 
-	if (res2 && (resource_size(res2) == 4)) {
-		/* assume both CMSTR and CMCSR to be 32-bit */
-		cmt->read_control = sh_cmt_read32;
-		cmt->write_control = sh_cmt_write32;
-	} else {
-		cmt->read_control = sh_cmt_read16;
-		cmt->write_control = sh_cmt_write16;
-	}
-
-	if (resource_size(res) == 6) {
-		cmt->width = 16;
-		cmt->read_count = sh_cmt_read16;
-		cmt->write_count = sh_cmt_write16;
-		cmt->overflow_bit = 0x80;
-		cmt->clear_bits = ~0x80;
-	} else {
-		cmt->width = 32;
-		cmt->read_count = sh_cmt_read32;
-		cmt->write_count = sh_cmt_write32;
-		cmt->overflow_bit = 0x8000;
-		cmt->clear_bits = ~0xc000;
-	}
+	/* identify the model based on the resources */
+	if (resource_size(res) == 6)
+		cmt->info = &sh_cmt_info[SH_CMT_16BIT];
+	else if (res2 && (resource_size(res2) == 4))
+		cmt->info = &sh_cmt_info[SH_CMT_48BIT_GEN2];
+	else
+		cmt->info = &sh_cmt_info[SH_CMT_32BIT];
 
 	cmt->channels = kzalloc(sizeof(*cmt->channels), GFP_KERNEL);
 	if (cmt->channels == NULL) {
-- 
1.8.3.2

[PATCH 10/27] clocksource: sh_cmt: Replace hardcoded register values with macros

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:00

Define symbolic macros for all used registers bits.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 56 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 44 insertions(+), 12 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 3946c14..5280231 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -115,6 +115,34 @@ struct sh_cmt_device {
 	unsigned int num_channels;
 };
 
+#define SH_CMT16_CMCSR_CMF		(1 << 7)
+#define SH_CMT16_CMCSR_CMIE		(1 << 6)
+#define SH_CMT16_CMCSR_CKS8		(0 << 0)
+#define SH_CMT16_CMCSR_CKS32		(1 << 0)
+#define SH_CMT16_CMCSR_CKS128		(2 << 0)
+#define SH_CMT16_CMCSR_CKS512		(3 << 0)
+#define SH_CMT16_CMCSR_CKS_MASK		(3 << 0)
+
+#define SH_CMT32_CMCSR_CMF		(1 << 15)
+#define SH_CMT32_CMCSR_OVF		(1 << 14)
+#define SH_CMT32_CMCSR_WRFLG		(1 << 13)
+#define SH_CMT32_CMCSR_STTF		(1 << 12)
+#define SH_CMT32_CMCSR_STPF		(1 << 11)
+#define SH_CMT32_CMCSR_SSIE		(1 << 10)
+#define SH_CMT32_CMCSR_CMS		(1 << 9)
+#define SH_CMT32_CMCSR_CMM		(1 << 8)
+#define SH_CMT32_CMCSR_CMTOUT_IE	(1 << 7)
+#define SH_CMT32_CMCSR_CMR_NONE		(0 << 4)
+#define SH_CMT32_CMCSR_CMR_DMA		(1 << 4)
+#define SH_CMT32_CMCSR_CMR_IRQ		(2 << 4)
+#define SH_CMT32_CMCSR_CMR_MASK		(3 << 4)
+#define SH_CMT32_CMCSR_DBGIVD		(1 << 3)
+#define SH_CMT32_CMCSR_CKS_RCLK8	(4 << 0)
+#define SH_CMT32_CMCSR_CKS_RCLK32	(5 << 0)
+#define SH_CMT32_CMCSR_CKS_RCLK128	(6 << 0)
+#define SH_CMT32_CMCSR_CKS_RCLK1	(7 << 0)
+#define SH_CMT32_CMCSR_CKS_MASK		(7 << 0)
+
 static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
 {
 	return ioread16(base + (offs << 1));
@@ -141,8 +169,8 @@ static const struct sh_cmt_info sh_cmt_info[] = {
 	[SH_CMT_16BIT] = {
 		.model = SH_CMT_16BIT,
 		.width = 16,
-		.overflow_bit = 0x80,
-		.clear_bits = ~0x80,
+		.overflow_bit = SH_CMT16_CMCSR_CMF,
+		.clear_bits = ~SH_CMT16_CMCSR_CMF,
 		.read_control = sh_cmt_read16,
 		.write_control = sh_cmt_write16,
 		.read_count = sh_cmt_read16,
@@ -151,8 +179,8 @@ static const struct sh_cmt_info sh_cmt_info[] = {
 	[SH_CMT_32BIT] = {
 		.model = SH_CMT_32BIT,
 		.width = 32,
-		.overflow_bit = 0x8000,
-		.clear_bits = ~0xc000,
+		.overflow_bit = SH_CMT32_CMCSR_CMF,
+		.clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF),
 		.read_control = sh_cmt_read16,
 		.write_control = sh_cmt_write16,
 		.read_count = sh_cmt_read32,
@@ -161,8 +189,8 @@ static const struct sh_cmt_info sh_cmt_info[] = {
 	[SH_CMT_32BIT_FAST] = {
 		.model = SH_CMT_32BIT_FAST,
 		.width = 32,
-		.overflow_bit = 0x8000,
-		.clear_bits = ~0xc000,
+		.overflow_bit = SH_CMT32_CMCSR_CMF,
+		.clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF),
 		.read_control = sh_cmt_read16,
 		.write_control = sh_cmt_write16,
 		.read_count = sh_cmt_read32,
@@ -171,8 +199,8 @@ static const struct sh_cmt_info sh_cmt_info[] = {
 	[SH_CMT_48BIT] = {
 		.model = SH_CMT_48BIT,
 		.width = 32,
-		.overflow_bit = 0x8000,
-		.clear_bits = ~0xc000,
+		.overflow_bit = SH_CMT32_CMCSR_CMF,
+		.clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF),
 		.read_control = sh_cmt_read32,
 		.write_control = sh_cmt_write32,
 		.read_count = sh_cmt_read32,
@@ -181,8 +209,8 @@ static const struct sh_cmt_info sh_cmt_info[] = {
 	[SH_CMT_48BIT_GEN2] = {
 		.model = SH_CMT_48BIT_GEN2,
 		.width = 32,
-		.overflow_bit = 0x8000,
-		.clear_bits = ~0xc000,
+		.overflow_bit = SH_CMT32_CMCSR_CMF,
+		.clear_bits = ~(SH_CMT32_CMCSR_CMF | SH_CMT32_CMCSR_OVF),
 		.read_control = sh_cmt_read32,
 		.write_control = sh_cmt_write32,
 		.read_count = sh_cmt_read32,
@@ -296,10 +324,14 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate)
 	/* configure channel, periodic mode and maximum timeout */
 	if (ch->cmt->info->width == 16) {
 		*rate = clk_get_rate(ch->cmt->clk) / 512;
-		sh_cmt_write_cmcsr(ch, 0x43);
+		sh_cmt_write_cmcsr(ch, SH_CMT16_CMCSR_CMIE |
+				   SH_CMT16_CMCSR_CKS512);
 	} else {
 		*rate = clk_get_rate(ch->cmt->clk) / 8;
-		sh_cmt_write_cmcsr(ch, 0x01a4);
+		sh_cmt_write_cmcsr(ch, SH_CMT32_CMCSR_CMM |
+				   SH_CMT32_CMCSR_CMTOUT_IE |
+				   SH_CMT32_CMCSR_CMR_IRQ |
+				   SH_CMT32_CMCSR_CKS_RCLK8);
 	}
 
 	sh_cmt_write_cmcor(ch, 0xffffffff);
-- 
1.8.3.2

[PATCH 11/27] clocksource: sh_cmt: Add support for multiple channels per device

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:01

CMT hardware devices can support multiple channels, with global
registers and per-channel registers. The sh_cmt driver currently models
the hardware with one Linux device per channel. This model makes it
difficult to handle global registers in a clean way.

Add support for a new model that uses one Linux device per timer with
multiple channels per device. This requires changes to platform data,
add new channel configuration fields.

Support for the legacy model is kept and will be removed after all
platforms switch to the new model.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 299 +++++++++++++++++++++++++++++++++----------
 include/linux/sh_timer.h     |   9 ++
 2 files changed, 239 insertions(+), 69 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 5280231..8390f0f 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -53,7 +53,16 @@ struct sh_cmt_device;
  * channel registers block. All other versions have a shared start/stop register
  * located in the global space.
  *
- * Note that CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing 32-bit
+ * Channels are indexed from 0 to N-1 in the documentation. The channel index
+ * infers the start/stop bit position in the control register and the channel
+ * registers block address. Some CMT instances have a subset of channels
+ * available, in which case the index in the documentation doesn't match the
+ * "real" index as implemented in hardware. This is for instance the case with
+ * CMT0 on r8a7740, which is a 32-bit variant with a single channel numbered 0
+ * in the documentation but using start/stop bit 5 and having its registers
+ * block at 0x60.
+ *
+ * Similarly CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing 32-bit
  * channels only, is a 48-bit gen2 CMT with the 48-bit channels unavailable.
  */
 
@@ -85,11 +94,15 @@ struct sh_cmt_info {
 
 struct sh_cmt_channel {
 	struct sh_cmt_device *cmt;
-	unsigned int index;
 
-	void __iomem *base;
+	unsigned int index;	/* Index in the documentation */
+	unsigned int hwidx;	/* Real hardware index */
+
+	void __iomem *iostart;
+	void __iomem *ioctrl;
 	struct irqaction irqaction;
 
+	unsigned int timer_bit;
 	unsigned long flags;
 	unsigned long match_value;
 	unsigned long next_match_value;
@@ -106,6 +119,7 @@ struct sh_cmt_device {
 	struct platform_device *pdev;
 
 	const struct sh_cmt_info *info;
+	bool legacy;
 
 	void __iomem *mapbase_ch;
 	void __iomem *mapbase;
@@ -113,6 +127,10 @@ struct sh_cmt_device {
 
 	struct sh_cmt_channel *channels;
 	unsigned int num_channels;
+	unsigned int hw_channels;
+
+	bool has_clockevent;
+	bool has_clocksource;
 };
 
 #define SH_CMT16_CMCSR_CMF		(1 << 7)
@@ -224,41 +242,47 @@ static const struct sh_cmt_info sh_cmt_info[] = {
 
 static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
 {
-	return ch->cmt->info->read_control(ch->cmt->mapbase, 0);
+	if (ch->iostart)
+		return ch->cmt->info->read_control(ch->iostart, 0);
+	else
+		return ch->cmt->info->read_control(ch->cmt->mapbase, 0);
 }
 
-static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
+static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
+				      unsigned long value)
 {
-	return ch->cmt->info->read_control(ch->base, CMCSR);
+	if (ch->iostart)
+		ch->cmt->info->write_control(ch->iostart, 0, value);
+	else
+		ch->cmt->info->write_control(ch->cmt->mapbase, 0, value);
 }
 
-static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
+static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
 {
-	return ch->cmt->info->read_count(ch->base, CMCNT);
+	return ch->cmt->info->read_control(ch->ioctrl, CMCSR);
 }
 
-static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
+static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->info->write_control(ch->cmt->mapbase, 0, value);
+	ch->cmt->info->write_control(ch->ioctrl, CMCSR, value);
 }
 
-static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch,
-				      unsigned long value)
+static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
 {
-	ch->cmt->info->write_control(ch->base, CMCSR, value);
+	return ch->cmt->info->read_count(ch->ioctrl, CMCNT);
 }
 
 static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->info->write_count(ch->base, CMCNT, value);
+	ch->cmt->info->write_count(ch->ioctrl, CMCNT, value);
 }
 
 static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch,
 				      unsigned long value)
 {
-	ch->cmt->info->write_count(ch->base, CMCOR, value);
+	ch->cmt->info->write_count(ch->ioctrl, CMCOR, value);
 }
 
 static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
@@ -287,7 +311,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
 
 static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
 {
-	struct sh_timer_config *cfg = ch->cmt->pdev->dev.platform_data;
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
@@ -295,9 +318,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
 	value = sh_cmt_read_cmstr(ch);
 
 	if (start)
-		value |= 1 << cfg->timer_bit;
+		value |= 1 << ch->timer_bit;
 	else
-		value &= ~(1 << cfg->timer_bit);
+		value &= ~(1 << ch->timer_bit);
 
 	sh_cmt_write_cmstr(ch, value);
 	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
@@ -792,28 +815,71 @@ static int sh_cmt_register(struct sh_cmt_channel *ch, char *name,
 			   unsigned long clockevent_rating,
 			   unsigned long clocksource_rating)
 {
-	if (clockevent_rating)
+	if (clockevent_rating) {
+		ch->cmt->has_clockevent = true;
 		sh_cmt_register_clockevent(ch, name, clockevent_rating);
+	}
 
-	if (clocksource_rating)
+	if (clocksource_rating) {
+		ch->cmt->has_clocksource = true;
 		sh_cmt_register_clocksource(ch, name, clocksource_rating);
+	}
 
 	return 0;
 }
 
 static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
-				struct sh_cmt_device *cmt)
+				const struct sh_timer_channel_config *ch_cfg,
+				unsigned int hwidx, struct sh_cmt_device *cmt)
 {
-	struct sh_timer_config *cfg = cmt->pdev->dev.platform_data;
+	unsigned long clockevent_rating;
+	unsigned long clocksource_rating;
 	int irq;
 	int ret;
 
 	ch->cmt = cmt;
-	ch->base = cmt->mapbase_ch;
-	ch->index = index;
+	ch->index = ch_cfg ? ch_cfg->index : index;
+	ch->hwidx = hwidx;
+
+	/*
+	 * Compute the address of the channel control register block. For the
+	 * timers with a per-channel start/stop register, compute its address
+	 * as well.
+	 *
+	 * For legacy configuration the address has been mapped explicitly.
+	 */
+	if (cmt->legacy) {
+		ch->ioctrl = cmt->mapbase_ch;
+	} else {
+		switch (cmt->info->model) {
+		case SH_CMT_16BIT:
+			ch->ioctrl = cmt->mapbase + 2 + ch->hwidx * 6;
+			break;
+		case SH_CMT_32BIT:
+		case SH_CMT_48BIT:
+			ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10;
+			break;
+		case SH_CMT_32BIT_FAST:
+			/*
+			 * The 32-bit "fast" timer has a single channel at hwidx
+			 * 5 but is located at offset 0x40 instead of 0x60 for
+			 * some reason.
+			 */
+			ch->ioctrl = cmt->mapbase + 0x40;
+			break;
+		case SH_CMT_48BIT_GEN2:
+			ch->iostart = cmt->mapbase + ch->hwidx * 0x100;
+			ch->ioctrl = ch->iostart + 0x10;
+			break;
+		}
+	}
 
 	/* Request irq using setup_irq() (too early for request_irq()). */
-	irq = platform_get_irq(cmt->pdev, 0);
+	if (cmt->legacy)
+		irq = platform_get_irq(cmt->pdev, 0);
+	else
+		irq = platform_get_irq(cmt->pdev, ch->index);
+
 	if (irq < 0) {
 		dev_err(&cmt->pdev->dev, "failed to get irq\n");
 		return irq;
@@ -832,9 +898,20 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 	ch->match_value = ch->max_match_value;
 	raw_spin_lock_init(&ch->lock);
 
+	if (ch_cfg) {
+		ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2
+			      ? 0 : ch->hwidx;
+		clockevent_rating = ch_cfg->clockevent_rating;
+		clocksource_rating = ch_cfg->clocksource_rating;
+	} else {
+		struct sh_timer_config *cfg = cmt->pdev->dev.platform_data;
+		ch->timer_bit = cfg->timer_bit;
+		clockevent_rating = cfg->clockevent_rating;
+		clocksource_rating = cfg->clocksource_rating;
+	}
+
 	ret = sh_cmt_register(ch, (char *)dev_name(&cmt->pdev->dev),
-			      cfg->clockevent_rating,
-			      cfg->clocksource_rating);
+			      clockevent_rating, clocksource_rating);
 	if (ret) {
 		dev_err(&cmt->pdev->dev, "registration failed\n");
 		return ret;
@@ -850,97 +927,169 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 	return 0;
 }
 
-static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
+static int sh_cmt_map_memory(struct sh_cmt_device *cmt)
 {
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
-	struct resource *res, *res2;
-	int ret;
-	ret = -ENXIO;
+	struct resource *mem;
 
-	cmt->pdev = pdev;
+	mem = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&cmt->pdev->dev, "failed to get I/O memory\n");
+		return -ENXIO;
+	}
 
-	if (!cfg) {
-		dev_err(&cmt->pdev->dev, "missing platform data\n");
-		goto err0;
+	cmt->mapbase = ioremap_nocache(mem->start, resource_size(mem));
+	if (cmt->mapbase == NULL) {
+		dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n");
+		return -ENXIO;
 	}
 
+	return 0;
+}
+
+static int sh_cmt_map_memory_legacy(struct sh_cmt_device *cmt)
+{
+	struct sh_timer_config *cfg = cmt->pdev->dev.platform_data;
+	struct resource *res, *res2;
+
+	/* map memory, let mapbase_ch point to our channel */
 	res = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(&cmt->pdev->dev, "failed to get I/O memory\n");
-		goto err0;
+		return -ENXIO;
 	}
 
-	/* optional resource for the shared timer start/stop register */
-	res2 = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 1);
-
-	/* map memory, let mapbase_ch point to our channel */
 	cmt->mapbase_ch = ioremap_nocache(res->start, resource_size(res));
 	if (cmt->mapbase_ch == NULL) {
 		dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n");
-		goto err0;
+		return -ENXIO;
 	}
 
+	/* optional resource for the shared timer start/stop register */
+	res2 = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 1);
+
 	/* map second resource for CMSTR */
 	cmt->mapbase = ioremap_nocache(res2 ? res2->start :
 				       res->start - cfg->channel_offset,
 				       res2 ? resource_size(res2) : 2);
 	if (cmt->mapbase == NULL) {
 		dev_err(&cmt->pdev->dev, "failed to remap I/O second memory\n");
-		goto err1;
+		iounmap(cmt->mapbase_ch);
+		return -ENXIO;
 	}
 
-	/* get hold of clock */
+	/* identify the model based on the resources */
+	if (resource_size(res) == 6)
+		cmt->info = &sh_cmt_info[SH_CMT_16BIT];
+	else if (res2 && (resource_size(res2) == 4))
+		cmt->info = &sh_cmt_info[SH_CMT_48BIT_GEN2];
+	else
+		cmt->info = &sh_cmt_info[SH_CMT_32BIT];
+
+	return 0;
+}
+
+static void sh_cmt_unmap_memory(struct sh_cmt_device *cmt)
+{
+	iounmap(cmt->mapbase);
+	if (cmt->mapbase_ch)
+		iounmap(cmt->mapbase_ch);
+}
+
+static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
+{
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	const struct platform_device_id *id = pdev->id_entry;
+	int ret;
+
+	memset(cmt, 0, sizeof(*cmt));
+	cmt->pdev = pdev;
+
+	if (!cfg) {
+		dev_err(&cmt->pdev->dev, "missing platform data\n");
+		return -ENXIO;
+	}
+
+	cmt->info = (const struct sh_cmt_info *)id->driver_data;
+	cmt->legacy = cmt->info ? false : true;
+
+	/* Get hold of clock. */
 	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);
-		goto err2;
+		return PTR_ERR(cmt->clk);
 	}
 
 	ret = clk_prepare(cmt->clk);
 	if (ret < 0)
-		goto err3;
+		goto err_clk_put;
 
-	/* identify the model based on the resources */
-	if (resource_size(res) == 6)
-		cmt->info = &sh_cmt_info[SH_CMT_16BIT];
-	else if (res2 && (resource_size(res2) == 4))
-		cmt->info = &sh_cmt_info[SH_CMT_48BIT_GEN2];
+	/*
+	 * Map the memory resource(s). We need to support both the legacy
+	 * platform device configuration (with one device per channel) and the
+	 * new version (with multiple channels per device).
+	 */
+	if (cmt->legacy)
+		ret = sh_cmt_map_memory_legacy(cmt);
 	else
-		cmt->info = &sh_cmt_info[SH_CMT_32BIT];
+		ret = sh_cmt_map_memory(cmt);
 
-	cmt->channels = kzalloc(sizeof(*cmt->channels), GFP_KERNEL);
+	if (ret < 0)
+		goto err_clk_unprepare;
+
+	/* Allocate and setup the channels. */
+	if (cmt->legacy) {
+		cmt->num_channels = 1;
+	} else {
+		cmt->num_channels = cfg->num_channels;
+		cmt->hw_channels = ~cfg->channels_mask;
+	}
+
+	cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels),
+				GFP_KERNEL);
 	if (cmt->channels == NULL) {
 		ret = -ENOMEM;
-		goto err4;
+		goto err_unmap;
 	}
 
-	cmt->num_channels = 1;
+	if (cmt->legacy) {
+		ret = sh_cmt_setup_channel(&cmt->channels[0], cfg->timer_bit,
+					   NULL, cfg->timer_bit, cmt);
+		if (ret < 0)
+			goto err_unmap;
+	} else {
+		const struct sh_timer_channel_config *ch_cfg = cfg->channels;
+		unsigned int mask = cmt->hw_channels;
+		unsigned int i;
+
+		for (i = 0; i < cmt->num_channels; ++i) {
+			unsigned int hwidx = ffs(mask) - 1;
 
-	ret = sh_cmt_setup_channel(&cmt->channels[0], cfg->timer_bit, cmt);
-	if (ret < 0)
-		goto err4;
+			ret = sh_cmt_setup_channel(&cmt->channels[i], 0, ch_cfg,
+						   hwidx, cmt);
+			if (ret < 0)
+				goto err_unmap;
+
+			mask &= ~(1 << hwidx);
+		}
+	}
 
 	platform_set_drvdata(pdev, cmt);
 
 	return 0;
-err4:
+
+err_unmap:
 	kfree(cmt->channels);
+	sh_cmt_unmap_memory(cmt);
+err_clk_unprepare:
 	clk_unprepare(cmt->clk);
-err3:
+err_clk_put:
 	clk_put(cmt->clk);
-err2:
-	iounmap(cmt->mapbase);
-err1:
-	iounmap(cmt->mapbase_ch);
-err0:
 	return ret;
 }
 
 static int sh_cmt_probe(struct platform_device *pdev)
 {
 	struct sh_cmt_device *cmt = platform_get_drvdata(pdev);
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	int ret;
 
 	if (!is_early_platform_device(pdev)) {
@@ -969,7 +1118,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
 		return 0;
 
  out:
-	if (cfg->clockevent_rating || cfg->clocksource_rating)
+	if (cmt->has_clockevent || cmt->has_clocksource)
 		pm_runtime_irq_safe(&pdev->dev);
 	else
 		pm_runtime_idle(&pdev->dev);
@@ -982,12 +1131,24 @@ static int sh_cmt_remove(struct platform_device *pdev)
 	return -EBUSY; /* cannot unregister clockevent and clocksource */
 }
 
+static const struct platform_device_id sh_cmt_id_table[] = {
+	{ "sh_cmt", 0 },
+	{ "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
+	{ "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
+	{ "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] },
+	{ "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] },
+	{ "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
+
 static struct platform_driver sh_cmt_device_driver = {
 	.probe		= sh_cmt_probe,
 	.remove		= sh_cmt_remove,
 	.driver		= {
 		.name	= "sh_cmt",
-	}
+	},
+	.id_table	= sh_cmt_id_table,
 };
 
 static int __init sh_cmt_init(void)
diff --git a/include/linux/sh_timer.h b/include/linux/sh_timer.h
index 4d9dcd1..b8273e2 100644
--- a/include/linux/sh_timer.h
+++ b/include/linux/sh_timer.h
@@ -1,12 +1,21 @@
 #ifndef __SH_TIMER_H__
 #define __SH_TIMER_H__
 
+struct sh_timer_channel_config {
+	unsigned int index;
+	unsigned long clockevent_rating;
+	unsigned long clocksource_rating;
+};
+
 struct sh_timer_config {
 	char *name;
 	long channel_offset;
 	int timer_bit;
 	unsigned long clockevent_rating;
 	unsigned long clocksource_rating;
+	const struct sh_timer_channel_config *channels;
+	unsigned int num_channels;
+	unsigned int channels_mask;
 };
 
 #endif /* __SH_TIMER_H__ */
-- 
1.8.3.2

[PATCH 12/27] clocksource: sh_cmt: Acquire default clock in the non-legacy case

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:04

The sh_cmt driver gets the CMT functional clock using a connection ID of
"cmt_fck". While all SH SoCs create clock lookup entries with a NULL
device ID and a "cmt_fck" connection ID, the ARM SoCs use the device ID
only with a NULL connection ID. This works on legacy platforms but will
break on ARM with DT boot.

Fix the situation by using a NULL connection ID in the non-legacy
platform data case. Clock lookup entries will be renamed as platforms
get moved to new platform data. The legacy code will eventually be
dropped, leaving us with device ID based clock lookup only, compatible
with DT boot.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 8390f0f..2389e33 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -1013,7 +1013,7 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 	cmt->legacy = cmt->info ? false : true;
 
 	/* Get hold of clock. */
-	cmt->clk = clk_get(&cmt->pdev->dev, "cmt_fck");
+	cmt->clk = clk_get(&cmt->pdev->dev, cmt->legacy ? "cmt_fck" : NULL);
 	if (IS_ERR(cmt->clk)) {
 		dev_err(&cmt->pdev->dev, "cannot get clock\n");
 		return PTR_ERR(cmt->clk);
-- 
1.8.3.2

[PATCH 13/27] clocksource: sh_cmt: Remove FSF mail address from GPL notice

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:06

Do not include the paragraph about writing to the Free Software
Foundation's mailing address from the sample GPL notice. The FSF has
changed addresses in the past, and may do so again. Linux already
includes a copy of the GPL.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 4 ----
 1 file changed, 4 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 2389e33..9f5616b 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -11,10 +11,6 @@
  * 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>
-- 
1.8.3.2

[PATCH 14/27] clocksource: sh_cmt: Sort headers alphabetically

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:07

This helps locating duplicates and inserting new headers.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 9f5616b..077879b 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -13,23 +13,23 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/delay.h>
+#include <linux/err.h>
 #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/ioport.h>
 #include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-#include <linux/sh_timer.h>
-#include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
+#include <linux/sh_timer.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
 
 struct sh_cmt_device;
 
-- 
1.8.3.2

[PATCH 16/27] ARM: shmobile: sh7372: Switch to new style CMT device

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:09

The CMT (Compare Match Timer) driver implements a new style of platform
data that handles the timer as a single device with multiple channel.
Switch from the old-style platform data to the new-style platform data.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/mach-shmobile/clock-sh7372.c |  6 +++---
 arch/arm/mach-shmobile/setup-sh7372.c | 30 ++++++++++++++----------------
 2 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index 2848997..5557b3d 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -565,10 +565,10 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */
 	CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */
 	CLKDEV_DEV_ID("renesas_usbhs.1", &mstp_clks[MSTP406]), /* USB1 */
-	CLKDEV_DEV_ID("sh_cmt.4", &mstp_clks[MSTP405]), /* CMT4 */
-	CLKDEV_DEV_ID("sh_cmt.3", &mstp_clks[MSTP404]), /* CMT3 */
+	CLKDEV_DEV_ID("sh-cmt-32-fast.4", &mstp_clks[MSTP405]), /* CMT4 */
+	CLKDEV_DEV_ID("sh-cmt-32-fast.3", &mstp_clks[MSTP404]), /* CMT3 */
 	CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
-	CLKDEV_DEV_ID("sh_cmt.2", &mstp_clks[MSTP400]), /* CMT2 */
+	CLKDEV_DEV_ID("sh-cmt-32-fast.2", &mstp_clks[MSTP400]), /* CMT2 */
 
 	/* ICK */
 	CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 2730127..3e524d5 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -118,29 +118,27 @@ SH7372_SCIF(PORT_SCIFA, 5, 0xe6cb0000, evt2irq(0x0d40));
 SH7372_SCIF(PORT_SCIFB, 6, 0xe6c30000, evt2irq(0x0d60));
 
 /* CMT */
+static struct sh_timer_channel_config cmt2_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+		.clocksource_rating = 125,
+	},
+};
+
 static struct sh_timer_config cmt2_platform_data = {
-	.name = "CMT2",
-	.channel_offset = 0x40,
-	.timer_bit = 5,
-	.clockevent_rating = 125,
-	.clocksource_rating = 125,
+	.channels = cmt2_channels,
+	.num_channels = ARRAY_SIZE(cmt2_channels),
+	.channels_mask = 0x1f,
 };
 
 static struct resource cmt2_resources[] = {
-	[0] = {
-		.name	= "CMT2",
-		.start	= 0xe6130040,
-		.end	= 0xe613004b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0x0b80), /* CMT2 */
-		.flags	= IORESOURCE_IRQ,
-	},
+	DEFINE_RES_MEM(0xe6130000, 0x50),
+	DEFINE_RES_IRQ(evt2irq(0x0b80)),
 };
 
 static struct platform_device cmt2_device = {
-	.name		= "sh_cmt",
+	.name		= "sh-cmt-32-fast",
 	.id		= 2,
 	.dev = {
 		.platform_data	= &cmt2_platform_data,
-- 
1.8.3.2

[PATCH 03/27] clocksource: sh_cmt: Split channel setup to separate function

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:10

Move the channel setup code from sh_cmt_setup to a new
sh_cmt_setup_channel function and call it from sh_cmt_setup.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 87 ++++++++++++++++++++++++++------------------
 1 file changed, 51 insertions(+), 36 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 68cca0a..3a3cc83 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -695,12 +695,59 @@ static int sh_cmt_register(struct sh_cmt_channel *ch, char *name,
 	return 0;
 }
 
+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;
+
+	/* Request irq using setup_irq() (too early for request_irq()). */
+	irq = platform_get_irq(cmt->pdev, 0);
+	if (irq < 0) {
+		dev_err(&cmt->pdev->dev, "failed to get irq\n");
+		return irq;
+	}
+
+	ch->irqaction.name = dev_name(&cmt->pdev->dev);
+	ch->irqaction.handler = sh_cmt_interrupt;
+	ch->irqaction.dev_id = ch;
+	ch->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
+
+	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 = setup_irq(irq, &ch->irqaction);
+	if (ret) {
+		dev_err(&cmt->pdev->dev, "failed to request irq %d\n", irq);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
-	struct sh_cmt_channel *ch = &cmt->channel;
 	struct resource *res, *res2;
-	int irq, ret;
+	int ret;
 	ret = -ENXIO;
 
 	memset(cmt, 0, sizeof(*cmt));
@@ -720,12 +767,6 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 	/* optional resource for the shared timer start/stop register */
 	res2 = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 1);
 
-	irq = platform_get_irq(cmt->pdev, 0);
-	if (irq < 0) {
-		dev_err(&cmt->pdev->dev, "failed to get irq\n");
-		goto err0;
-	}
-
 	/* map memory, let mapbase point to our channel */
 	cmt->mapbase = ioremap_nocache(res->start, resource_size(res));
 	if (cmt->mapbase == NULL) {
@@ -742,12 +783,6 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 		goto err1;
 	}
 
-	/* request irq using setup_irq() (too early for request_irq()) */
-	ch->irqaction.name = dev_name(&cmt->pdev->dev);
-	ch->irqaction.handler = sh_cmt_interrupt;
-	ch->irqaction.dev_id = ch;
-	ch->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
-
 	/* get hold of clock */
 	cmt->clk = clk_get(&cmt->pdev->dev, "cmt_fck");
 	if (IS_ERR(cmt->clk)) {
@@ -783,29 +818,9 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 		cmt->clear_bits = ~0xc000;
 	}
 
-	if (cmt->width == (sizeof(ch->max_match_value) * 8))
-		ch->max_match_value = ~0;
-	else
-		ch->max_match_value = (1 << cmt->width) - 1;
-
-	ch->cmt = cmt;
-	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");
-		goto err4;
-	}
-	ch->cs_enabled = false;
-
-	ret = setup_irq(irq, &ch->irqaction);
-	if (ret) {
-		dev_err(&cmt->pdev->dev, "failed to request irq %d\n", irq);
+	ret = sh_cmt_setup_channel(&cmt->channel, cmt);
+	if (ret < 0)
 		goto err4;
-	}
 
 	platform_set_drvdata(pdev, cmt);
 
-- 
1.8.3.2

[PATCH 20/27] ARM: shmobile: r8a7790: Switch to new style CMT device

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:12

The CMT (Compare Match Timer) driver implements a new style of platform
data that handles the timer as a single device with multiple channel.
Switch from the old-style platform data to the new-style platform data.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/mach-shmobile/board-lager-reference.c |  2 +-
 arch/arm/mach-shmobile/clock-r8a7790.c         |  2 +-
 arch/arm/mach-shmobile/setup-r8a7790.c         | 26 ++++++++++++++++----------
 3 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index 35fc0f2..4dd43b1 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -38,7 +38,7 @@ static void __init lager_add_standard_devices(void)
 
 	clk = clk_get(NULL, "cmt0");
 	if (!IS_ERR(clk)) {
-		clk_register_clkdev(clk, NULL, "sh_cmt.0");
+		clk_register_clkdev(clk, NULL, "sh-cmt-48-gen2.0");
 		clk_put(clk);
 	}
 #else
diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
index 4b276ef..780466e 100644
--- a/arch/arm/mach-shmobile/clock-r8a7790.c
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -357,7 +357,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP311]),
 	CLKDEV_DEV_ID("ee220000.mmc", &mstp_clks[MSTP305]),
 	CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
-	CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]),
+	CLKDEV_DEV_ID("sh-cmt-48-gen2.0", &mstp_clks[MSTP124]),
 	CLKDEV_DEV_ID("qspi.0", &mstp_clks[MSTP917]),
 	CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP704]),
 	CLKDEV_DEV_ID("pci-rcar-gen2.0", &mstp_clks[MSTP703]),
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
index b237268..3e5813f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -269,20 +269,26 @@ static const struct resource thermal_resources[] __initconst = {
 					thermal_resources,		\
 					ARRAY_SIZE(thermal_resources))
 
-static const struct sh_timer_config cmt00_platform_data __initconst = {
-	.name = "CMT00",
-	.timer_bit = 0,
-	.clockevent_rating = 80,
+static struct sh_timer_channel_config cmt0_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 80,
+	},
 };
 
-static const struct resource cmt00_resources[] __initconst = {
-	DEFINE_RES_MEM(0xffca0510, 0x0c),
-	DEFINE_RES_MEM(0xffca0500, 0x04),
-	DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */
+static struct sh_timer_config cmt0_platform_data = {
+	.channels = cmt0_channels,
+	.num_channels = ARRAY_SIZE(cmt0_channels),
+	.channels_mask = 0x1f,
+};
+
+static struct resource cmt0_resources[] = {
+	DEFINE_RES_MEM(0xffca0000, 0x1004),
+	DEFINE_RES_IRQ(gic_spi(142)),
 };
 
 #define r8a7790_register_cmt(idx)					\
-	platform_device_register_resndata(&platform_bus, "sh_cmt",	\
+	platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
 					  idx, cmt##idx##_resources,	\
 					  ARRAY_SIZE(cmt##idx##_resources), \
 					  &cmt##idx##_platform_data,	\
@@ -290,7 +296,7 @@ static const struct resource cmt00_resources[] __initconst = {
 
 void __init r8a7790_add_dt_devices(void)
 {
-	r8a7790_register_cmt(00);
+	r8a7790_register_cmt(0);
 }
 
 void __init r8a7790_add_standard_devices(void)
-- 
1.8.3.2

[PATCH 15/27] sh: Switch to new style CMT device

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:13

The CMT (Compare Match Timer) driver implements a new style of platform
data that handles the timer as a single device with multiple channel.
Switch from the old-style platform data to the new-style platform data.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/sh/kernel/cpu/clock-cpg.c         |   3 +-
 arch/sh/kernel/cpu/sh2/setup-sh7619.c  |  73 +++++-----------
 arch/sh/kernel/cpu/sh2a/clock-sh7264.c |   2 +-
 arch/sh/kernel/cpu/sh2a/clock-sh7269.c |   2 +-
 arch/sh/kernel/cpu/sh2a/setup-sh7203.c |  73 +++++-----------
 arch/sh/kernel/cpu/sh2a/setup-sh7206.c |  73 +++++-----------
 arch/sh/kernel/cpu/sh2a/setup-sh7264.c |  76 +++++-----------
 arch/sh/kernel/cpu/sh2a/setup-sh7269.c |  73 +++++-----------
 arch/sh/kernel/cpu/sh3/setup-sh7720.c  | 155 ++++-----------------------------
 arch/sh/kernel/cpu/sh4a/clock-sh7343.c |   2 +-
 arch/sh/kernel/cpu/sh4a/clock-sh7366.c |   2 +-
 arch/sh/kernel/cpu/sh4a/clock-sh7722.c |   2 +-
 arch/sh/kernel/cpu/sh4a/clock-sh7723.c |   2 +-
 arch/sh/kernel/cpu/sh4a/clock-sh7724.c |   2 +-
 arch/sh/kernel/cpu/sh4a/setup-sh7343.c |  28 +++---
 arch/sh/kernel/cpu/sh4a/setup-sh7366.c |  27 +++---
 arch/sh/kernel/cpu/sh4a/setup-sh7722.c |  28 +++---
 arch/sh/kernel/cpu/sh4a/setup-sh7723.c |  28 +++---
 arch/sh/kernel/cpu/sh4a/setup-sh7724.c |  28 +++---
 19 files changed, 207 insertions(+), 472 deletions(-)
diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c
index f59b1f3..3f425f5 100644
--- a/arch/sh/kernel/cpu/clock-cpg.c
+++ b/arch/sh/kernel/cpu/clock-cpg.c
@@ -58,7 +58,8 @@ int __init __deprecated cpg_clk_init(void)
 
 	clk_add_alias("tmu_fck", NULL, "peripheral_clk", NULL);
 	clk_add_alias("mtu2_fck", NULL, "peripheral_clk", NULL);
-	clk_add_alias("cmt_fck", NULL, "peripheral_clk", NULL);
+	clk_add_alias(NULL, "sh-cmt-16.0", "peripheral_clk", NULL);
+	clk_add_alias(NULL, "sh-cmt-32.0", "peripheral_clk", NULL);
 	clk_add_alias("sci_ick", NULL, "peripheral_clk", NULL);
 
 	return ret;
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index 3860b0b..73bdf66 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -152,62 +152,35 @@ static struct platform_device eth_device = {
 	.resource = eth_resources,
 };
 
-static struct sh_timer_config cmt0_platform_data = {
-	.channel_offset = 0x02,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 0, /* disabled due to code generation issues */
-};
-
-static struct resource cmt0_resources[] = {
-	[0] = {
-		.start	= 0xf84a0072,
-		.end	= 0xf84a0077,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 86,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt0_device = {
-	.name		= "sh_cmt",
-	.id		= 0,
-	.dev = {
-		.platform_data	= &cmt0_platform_data,
+static struct sh_timer_channel_config cmt_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+	}, {
+		.index = 1,
+		.clockevent_rating = 125,
 	},
-	.resource	= cmt0_resources,
-	.num_resources	= ARRAY_SIZE(cmt0_resources),
 };
 
-static struct sh_timer_config cmt1_platform_data = {
-	.channel_offset = 0x08,
-	.timer_bit = 1,
-	.clockevent_rating = 125,
-	.clocksource_rating = 0, /* disabled due to code generation issues */
+static struct sh_timer_config cmt_platform_data = {
+	.channels = cmt_channels,
+	.num_channels = ARRAY_SIZE(cmt_channels),
 };
 
-static struct resource cmt1_resources[] = {
-	[0] = {
-		.start	= 0xf84a0078,
-		.end	= 0xf84a007d,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 87,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct resource cmt_resources[] = {
+	DEFINE_RES_MEM(0xf84a0078, 0x10),
+	DEFINE_RES_IRQ(86),
+	DEFINE_RES_IRQ(87),
 };
 
-static struct platform_device cmt1_device = {
-	.name		= "sh_cmt",
-	.id		= 1,
+static struct platform_device cmt_device = {
+	.name		= "sh-cmt-16",
+	.id		= 0,
 	.dev = {
-		.platform_data	= &cmt1_platform_data,
+		.platform_data	= &cmt_platform_data,
 	},
-	.resource	= cmt1_resources,
-	.num_resources	= ARRAY_SIZE(cmt1_resources),
+	.resource	= cmt_resources,
+	.num_resources	= ARRAY_SIZE(cmt_resources),
 };
 
 static struct platform_device *sh7619_devices[] __initdata = {
@@ -215,8 +188,7 @@ static struct platform_device *sh7619_devices[] __initdata = {
 	&scif1_device,
 	&scif2_device,
 	&eth_device,
-	&cmt0_device,
-	&cmt1_device,
+	&cmt_device,
 };
 
 static int __init sh7619_devices_setup(void)
@@ -235,8 +207,7 @@ static struct platform_device *sh7619_early_devices[] __initdata = {
 	&scif0_device,
 	&scif1_device,
 	&scif2_device,
-	&cmt0_device,
-	&cmt1_device,
+	&cmt_device,
 };
 
 #define STBCR3 0xf80a0000
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7264.c b/arch/sh/kernel/cpu/sh2a/clock-sh7264.c
index fdf585c..b8dcd34 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7264.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7264.c
@@ -117,7 +117,7 @@ static struct clk_lookup lookups[] = {
 	/* MSTP clocks */
 	CLKDEV_CON_ID("sci_ick", &mstp_clks[MSTP77]),
 	CLKDEV_CON_ID("vdc3", &mstp_clks[MSTP74]),
-	CLKDEV_CON_ID("cmt_fck", &mstp_clks[MSTP72]),
+	CLKDEV_DEV_ID("sh-cmt-16.0", &mstp_clks[MSTP72]),
 	CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),
 	CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP35]),
 	CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP34]),
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7269.c b/arch/sh/kernel/cpu/sh2a/clock-sh7269.c
index 6b78762..f7346b4 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7269.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7269.c
@@ -158,7 +158,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP42]),
 	CLKDEV_ICK_ID("sci_fck", "sh-sci.6", &mstp_clks[MSTP41]),
 	CLKDEV_ICK_ID("sci_fck", "sh-sci.7", &mstp_clks[MSTP40]),
-	CLKDEV_CON_ID("cmt_fck", &mstp_clks[MSTP72]),
+	CLKDEV_DEV_ID("sh-cmt-16.0", &mstp_clks[MSTP72]),
 	CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),
 	CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP35]),
 	CLKDEV_CON_ID("adc0", &mstp_clks[MSTP32]),
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
index d55a0f3..ef9d37a 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
@@ -265,62 +265,35 @@ static struct platform_device scif3_device = {
 	},
 };
 
-static struct sh_timer_config cmt0_platform_data = {
-	.channel_offset = 0x02,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 0, /* disabled due to code generation issues */
-};
-
-static struct resource cmt0_resources[] = {
-	[0] = {
-		.start	= 0xfffec002,
-		.end	= 0xfffec007,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 142,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt0_device = {
-	.name		= "sh_cmt",
-	.id		= 0,
-	.dev = {
-		.platform_data	= &cmt0_platform_data,
+static struct sh_timer_channel_config cmt_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+	}, {
+		.index = 1,
+		.clockevent_rating = 125,
 	},
-	.resource	= cmt0_resources,
-	.num_resources	= ARRAY_SIZE(cmt0_resources),
 };
 
-static struct sh_timer_config cmt1_platform_data = {
-	.channel_offset = 0x08,
-	.timer_bit = 1,
-	.clockevent_rating = 125,
-	.clocksource_rating = 0, /* disabled due to code generation issues */
+static struct sh_timer_config cmt_platform_data = {
+	.channels = cmt_channels,
+	.num_channels = ARRAY_SIZE(cmt_channels),
 };
 
-static struct resource cmt1_resources[] = {
-	[0] = {
-		.start	= 0xfffec008,
-		.end	= 0xfffec00d,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 143,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct resource cmt_resources[] = {
+	DEFINE_RES_MEM(0xfffec000, 0x10),
+	DEFINE_RES_IRQ(142),
+	DEFINE_RES_IRQ(143),
 };
 
-static struct platform_device cmt1_device = {
-	.name		= "sh_cmt",
-	.id		= 1,
+static struct platform_device cmt_device = {
+	.name		= "sh-cmt-16",
+	.id		= 0,
 	.dev = {
-		.platform_data	= &cmt1_platform_data,
+		.platform_data	= &cmt_platform_data,
 	},
-	.resource	= cmt1_resources,
-	.num_resources	= ARRAY_SIZE(cmt1_resources),
+	.resource	= cmt_resources,
+	.num_resources	= ARRAY_SIZE(cmt_resources),
 };
 
 static struct sh_timer_config mtu2_0_platform_data = {
@@ -404,8 +377,7 @@ static struct platform_device *sh7203_devices[] __initdata = {
 	&scif1_device,
 	&scif2_device,
 	&scif3_device,
-	&cmt0_device,
-	&cmt1_device,
+	&cmt_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
 	&rtc_device,
@@ -428,8 +400,7 @@ static struct platform_device *sh7203_early_devices[] __initdata = {
 	&scif1_device,
 	&scif2_device,
 	&scif3_device,
-	&cmt0_device,
-	&cmt1_device,
+	&cmt_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
 };
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index 241e745..f8c93a4 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -217,62 +217,35 @@ static struct platform_device scif3_device = {
 	},
 };
 
-static struct sh_timer_config cmt0_platform_data = {
-	.channel_offset = 0x02,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 0, /* disabled due to code generation issues */
-};
-
-static struct resource cmt0_resources[] = {
-	[0] = {
-		.start	= 0xfffec002,
-		.end	= 0xfffec007,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 140,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt0_device = {
-	.name		= "sh_cmt",
-	.id		= 0,
-	.dev = {
-		.platform_data	= &cmt0_platform_data,
+static struct sh_timer_channel_config cmt_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+	}, {
+		.index = 1,
+		.clockevent_rating = 125,
 	},
-	.resource	= cmt0_resources,
-	.num_resources	= ARRAY_SIZE(cmt0_resources),
 };
 
-static struct sh_timer_config cmt1_platform_data = {
-	.channel_offset = 0x08,
-	.timer_bit = 1,
-	.clockevent_rating = 125,
-	.clocksource_rating = 0, /* disabled due to code generation issues */
+static struct sh_timer_config cmt_platform_data = {
+	.channels = cmt_channels,
+	.num_channels = ARRAY_SIZE(cmt_channels),
 };
 
-static struct resource cmt1_resources[] = {
-	[0] = {
-		.start	= 0xfffec008,
-		.end	= 0xfffec00d,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 144,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct resource cmt_resources[] = {
+	DEFINE_RES_MEM(0xfffec000, 0x10),
+	DEFINE_RES_IRQ(140),
+	DEFINE_RES_IRQ(144),
 };
 
-static struct platform_device cmt1_device = {
-	.name		= "sh_cmt",
-	.id		= 1,
+static struct platform_device cmt_device = {
+	.name		= "sh-cmt-16",
+	.id		= 0,
 	.dev = {
-		.platform_data	= &cmt1_platform_data,
+		.platform_data	= &cmt_platform_data,
 	},
-	.resource	= cmt1_resources,
-	.num_resources	= ARRAY_SIZE(cmt1_resources),
+	.resource	= cmt_resources,
+	.num_resources	= ARRAY_SIZE(cmt_resources),
 };
 
 static struct sh_timer_config mtu2_0_platform_data = {
@@ -364,8 +337,7 @@ static struct platform_device *sh7206_devices[] __initdata = {
 	&scif1_device,
 	&scif2_device,
 	&scif3_device,
-	&cmt0_device,
-	&cmt1_device,
+	&cmt_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
 	&mtu2_2_device,
@@ -388,8 +360,7 @@ static struct platform_device *sh7206_early_devices[] __initdata = {
 	&scif1_device,
 	&scif2_device,
 	&scif3_device,
-	&cmt0_device,
-	&cmt1_device,
+	&cmt_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
 	&mtu2_2_device,
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7264.c b/arch/sh/kernel/cpu/sh2a/setup-sh7264.c
index ad5b0f4..838d05f 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7264.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7264.c
@@ -433,65 +433,35 @@ static struct platform_device scif7_device = {
 	},
 };
 
-static struct sh_timer_config cmt0_platform_data = {
-	.channel_offset = 0x02,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 0, /* disabled due to code generation issues */
-};
-
-static struct resource cmt0_resources[] = {
-	[0] = {
-		.name	= "CMT0",
-		.start	= 0xfffec002,
-		.end	= 0xfffec007,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 175,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt0_device = {
-	.name		= "sh_cmt",
-	.id		= 0,
-	.dev = {
-		.platform_data	= &cmt0_platform_data,
+static struct sh_timer_channel_config cmt_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+	}, {
+		.index = 1,
+		.clockevent_rating = 125,
 	},
-	.resource	= cmt0_resources,
-	.num_resources	= ARRAY_SIZE(cmt0_resources),
 };
 
-static struct sh_timer_config cmt1_platform_data = {
-	.name = "CMT1",
-	.channel_offset = 0x08,
-	.timer_bit = 1,
-	.clockevent_rating = 125,
-	.clocksource_rating = 0, /* disabled due to code generation issues */
+static struct sh_timer_config cmt_platform_data = {
+	.channels = cmt_channels,
+	.num_channels = ARRAY_SIZE(cmt_channels),
 };
 
-static struct resource cmt1_resources[] = {
-	[0] = {
-		.name	= "CMT1",
-		.start	= 0xfffec008,
-		.end	= 0xfffec00d,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 176,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct resource cmt_resources[] = {
+	DEFINE_RES_MEM(0xfffec000, 0x10),
+	DEFINE_RES_IRQ(175),
+	DEFINE_RES_IRQ(176),
 };
 
-static struct platform_device cmt1_device = {
-	.name		= "sh_cmt",
-	.id		= 1,
+static struct platform_device cmt_device = {
+	.name		= "sh-cmt-16",
+	.id		= 0,
 	.dev = {
-		.platform_data	= &cmt1_platform_data,
+		.platform_data	= &cmt_platform_data,
 	},
-	.resource	= cmt1_resources,
-	.num_resources	= ARRAY_SIZE(cmt1_resources),
+	.resource	= cmt_resources,
+	.num_resources	= ARRAY_SIZE(cmt_resources),
 };
 
 static struct sh_timer_config mtu2_0_platform_data = {
@@ -620,8 +590,7 @@ static struct platform_device *sh7264_devices[] __initdata = {
 	&scif5_device,
 	&scif6_device,
 	&scif7_device,
-	&cmt0_device,
-	&cmt1_device,
+	&cmt_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
 	&rtc_device,
@@ -649,8 +618,7 @@ static struct platform_device *sh7264_early_devices[] __initdata = {
 	&scif5_device,
 	&scif6_device,
 	&scif7_device,
-	&cmt0_device,
-	&cmt1_device,
+	&cmt_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
 };
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7269.c b/arch/sh/kernel/cpu/sh2a/setup-sh7269.c
index 3995119..3e66297 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7269.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7269.c
@@ -455,62 +455,35 @@ static struct platform_device scif7_device = {
 	},
 };
 
-static struct sh_timer_config cmt0_platform_data = {
-	.channel_offset = 0x02,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 0, /* disabled due to code generation issues */
-};
-
-static struct resource cmt0_resources[] = {
-	[0] = {
-		.start	= 0xfffec002,
-		.end	= 0xfffec007,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 188,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt0_device = {
-	.name		= "sh_cmt",
-	.id		= 0,
-	.dev = {
-		.platform_data	= &cmt0_platform_data,
+static struct sh_timer_channel_config cmt_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+	}, {
+		.index = 1,
+		.clockevent_rating = 125,
 	},
-	.resource	= cmt0_resources,
-	.num_resources	= ARRAY_SIZE(cmt0_resources),
 };
 
-static struct sh_timer_config cmt1_platform_data = {
-	.channel_offset = 0x08,
-	.timer_bit = 1,
-	.clockevent_rating = 125,
-	.clocksource_rating = 0, /* disabled due to code generation issues */
+static struct sh_timer_config cmt_platform_data = {
+	.channels = cmt_channels,
+	.num_channels = ARRAY_SIZE(cmt_channels),
 };
 
-static struct resource cmt1_resources[] = {
-	[0] = {
-		.start	= 0xfffec008,
-		.end	= 0xfffec00d,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= 189,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct resource cmt_resources[] = {
+	DEFINE_RES_MEM(0xfffec000, 0x10),
+	DEFINE_RES_IRQ(188),
+	DEFINE_RES_IRQ(189),
 };
 
-static struct platform_device cmt1_device = {
-	.name		= "sh_cmt",
-	.id		= 1,
+static struct platform_device cmt_device = {
+	.name		= "sh-cmt-16",
+	.id		= 0,
 	.dev = {
-		.platform_data	= &cmt1_platform_data,
+		.platform_data	= &cmt_platform_data,
 	},
-	.resource	= cmt1_resources,
-	.num_resources	= ARRAY_SIZE(cmt1_resources),
+	.resource	= cmt_resources,
+	.num_resources	= ARRAY_SIZE(cmt_resources),
 };
 
 static struct sh_timer_config mtu2_0_platform_data = {
@@ -629,8 +602,7 @@ static struct platform_device *sh7269_devices[] __initdata = {
 	&scif5_device,
 	&scif6_device,
 	&scif7_device,
-	&cmt0_device,
-	&cmt1_device,
+	&cmt_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
 	&rtc_device,
@@ -658,8 +630,7 @@ static struct platform_device *sh7269_early_devices[] __initdata = {
 	&scif5_device,
 	&scif6_device,
 	&scif7_device,
-	&cmt0_device,
-	&cmt1_device,
+	&cmt_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
 };
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
index 1d5729d..3cafd93 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
@@ -152,141 +152,32 @@ static struct platform_device usbf_device = {
 	.resource	= usbf_resources,
 };
 
-static struct sh_timer_config cmt0_platform_data = {
-	.channel_offset = 0x10,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 125,
-};
-
-static struct resource cmt0_resources[] = {
-	[0] = {
-		.start	= 0x044a0010,
-		.end	= 0x044a001b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xf00),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt0_device = {
-	.name		= "sh_cmt",
-	.id		= 0,
-	.dev = {
-		.platform_data	= &cmt0_platform_data,
-	},
-	.resource	= cmt0_resources,
-	.num_resources	= ARRAY_SIZE(cmt0_resources),
-};
-
-static struct sh_timer_config cmt1_platform_data = {
-	.channel_offset = 0x20,
-	.timer_bit = 1,
-};
-
-static struct resource cmt1_resources[] = {
-	[0] = {
-		.start	= 0x044a0020,
-		.end	= 0x044a002b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xf00),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt1_device = {
-	.name		= "sh_cmt",
-	.id		= 1,
-	.dev = {
-		.platform_data	= &cmt1_platform_data,
-	},
-	.resource	= cmt1_resources,
-	.num_resources	= ARRAY_SIZE(cmt1_resources),
-};
-
-static struct sh_timer_config cmt2_platform_data = {
-	.channel_offset = 0x30,
-	.timer_bit = 2,
-};
-
-static struct resource cmt2_resources[] = {
-	[0] = {
-		.start	= 0x044a0030,
-		.end	= 0x044a003b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xf00),
-		.flags	= IORESOURCE_IRQ,
+static struct sh_timer_channel_config cmt_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+		.clocksource_rating = 125,
 	},
 };
 
-static struct platform_device cmt2_device = {
-	.name		= "sh_cmt",
-	.id		= 2,
-	.dev = {
-		.platform_data	= &cmt2_platform_data,
-	},
-	.resource	= cmt2_resources,
-	.num_resources	= ARRAY_SIZE(cmt2_resources),
+static struct sh_timer_config cmt_platform_data = {
+	.channels = cmt_channels,
+	.num_channels = ARRAY_SIZE(cmt_channels),
 };
 
-static struct sh_timer_config cmt3_platform_data = {
-	.channel_offset = 0x40,
-	.timer_bit = 3,
+static struct resource cmt_resources[] = {
+	DEFINE_RES_MEM(0x044a0000, 0x60),
+	DEFINE_RES_IRQ(evt2irq(0xf00)),
 };
 
-static struct resource cmt3_resources[] = {
-	[0] = {
-		.start	= 0x044a0040,
-		.end	= 0x044a004b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xf00),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt3_device = {
-	.name		= "sh_cmt",
-	.id		= 3,
-	.dev = {
-		.platform_data	= &cmt3_platform_data,
-	},
-	.resource	= cmt3_resources,
-	.num_resources	= ARRAY_SIZE(cmt3_resources),
-};
-
-static struct sh_timer_config cmt4_platform_data = {
-	.channel_offset = 0x50,
-	.timer_bit = 4,
-};
-
-static struct resource cmt4_resources[] = {
-	[0] = {
-		.start	= 0x044a0050,
-		.end	= 0x044a005b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xf00),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt4_device = {
-	.name		= "sh_cmt",
-	.id		= 4,
+static struct platform_device cmt_device = {
+	.name		= "sh-cmt-32",
+	.id		= 0,
 	.dev = {
-		.platform_data	= &cmt4_platform_data,
+		.platform_data	= &cmt_platform_data,
 	},
-	.resource	= cmt4_resources,
-	.num_resources	= ARRAY_SIZE(cmt4_resources),
+	.resource	= cmt_resources,
+	.num_resources	= ARRAY_SIZE(cmt_resources),
 };
 
 static struct sh_timer_config tmu0_platform_data = {
@@ -375,11 +266,7 @@ static struct platform_device tmu2_device = {
 static struct platform_device *sh7720_devices[] __initdata = {
 	&scif0_device,
 	&scif1_device,
-	&cmt0_device,
-	&cmt1_device,
-	&cmt2_device,
-	&cmt3_device,
-	&cmt4_device,
+	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
@@ -398,11 +285,7 @@ arch_initcall(sh7720_devices_setup);
 static struct platform_device *sh7720_early_devices[] __initdata = {
 	&scif0_device,
 	&scif1_device,
-	&cmt0_device,
-	&cmt1_device,
-	&cmt2_device,
-	&cmt3_device,
-	&cmt4_device,
+	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
index 53638e2..1628f82 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
@@ -227,7 +227,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]),
 	CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP017]),
 	CLKDEV_CON_ID("tmu_fck", &mstp_clks[MSTP015]),
-	CLKDEV_CON_ID("cmt_fck", &mstp_clks[MSTP014]),
+	CLKDEV_DEV_ID("sh-cmt-32.0k", &mstp_clks[MSTP014]),
 	CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
 	CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
 	CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
index 22e485d..8a9e8af 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
@@ -225,7 +225,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]),
 	CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP017]),
 	CLKDEV_CON_ID("tmu_fck", &mstp_clks[MSTP015]),
-	CLKDEV_CON_ID("cmt_fck", &mstp_clks[MSTP014]),
+	CLKDEV_DEV_ID("sh-cmt-32.0", &mstp_clks[MSTP014]),
 	CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
 	CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
 	CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index c4cb740..e40bd2a 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -207,7 +207,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[HWBLK_TMU]),
 	CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[HWBLK_TMU]),
 
-	CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]),
+	CLKDEV_DEV_ID("sh-cmt-32.0", &mstp_clks[HWBLK_CMT]),
 	CLKDEV_DEV_ID("sh-wdt.0", &mstp_clks[HWBLK_RWDT]),
 	CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]),
 
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
index 37c41c7..3e0a6d8 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
@@ -236,7 +236,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_CON_ID("sh0", &mstp_clks[HWBLK_SHYWAY]),
 	CLKDEV_CON_ID("hudi0", &mstp_clks[HWBLK_HUDI]),
 	CLKDEV_CON_ID("ubc0", &mstp_clks[HWBLK_UBC]),
-	CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]),
+	CLKDEV_DEV_ID("sh-cmt-32.0", &mstp_clks[HWBLK_CMT]),
 	CLKDEV_DEV_ID("sh-wdt.0", &mstp_clks[HWBLK_RWDT]),
 	CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[HWBLK_DMAC1]),
 	CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]),
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
index 0128af3..e836d64 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
@@ -309,7 +309,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[HWBLK_TMU0]),
 	CLKDEV_ICK_ID("tmu_fck", "sh_tmu.3", &mstp_clks[HWBLK_TMU1]),
 
-	CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]),
+	CLKDEV_DEV_ID("sh-cmt-16.0", &mstp_clks[HWBLK_CMT]),
 	CLKDEV_DEV_ID("sh-wdt.0", &mstp_clks[HWBLK_RWDT]),
 	CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[HWBLK_DMAC1]),
 
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index 245d192..820ce40 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
@@ -227,27 +227,27 @@ static struct platform_device jpu_device = {
 	.num_resources	= ARRAY_SIZE(jpu_resources),
 };
 
+static struct sh_timer_channel_config cmt_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+		.clocksource_rating = 200,
+	},
+};
+
 static struct sh_timer_config cmt_platform_data = {
-	.channel_offset = 0x60,
-	.timer_bit = 5,
-	.clockevent_rating = 125,
-	.clocksource_rating = 200,
+	.channels = cmt_channels,
+	.num_channels = ARRAY_SIZE(cmt_channels),
+	.channels_mask = 0x1f,
 };
 
 static struct resource cmt_resources[] = {
-	[0] = {
-		.start	= 0x044a0060,
-		.end	= 0x044a006b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xf00),
-		.flags	= IORESOURCE_IRQ,
-	},
+	DEFINE_RES_MEM(0x044a0000, 0x70),
+	DEFINE_RES_IRQ(evt2irq(0xf00)),
 };
 
 static struct platform_device cmt_device = {
-	.name		= "sh_cmt",
+	.name		= "sh-cmt-32",
 	.id		= 0,
 	.dev = {
 		.platform_data	= &cmt_platform_data,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index 6f56cbd..c878686 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -175,27 +175,26 @@ static struct platform_device veu1_device = {
 	.num_resources	= ARRAY_SIZE(veu1_resources),
 };
 
+static struct sh_timer_channel_config cmt_channels[] = {
+	{
+		.index = 5,
+		.clockevent_rating = 125,
+		.clocksource_rating = 200,
+	},
+};
+
 static struct sh_timer_config cmt_platform_data = {
-	.channel_offset = 0x60,
-	.timer_bit = 5,
-	.clockevent_rating = 125,
-	.clocksource_rating = 200,
+	.channels = cmt_channels,
+	.num_channels = ARRAY_SIZE(cmt_channels),
 };
 
 static struct resource cmt_resources[] = {
-	[0] = {
-		.start	= 0x044a0060,
-		.end	= 0x044a006b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xf00),
-		.flags	= IORESOURCE_IRQ,
-	},
+	DEFINE_RES_MEM(0x044a0000, 0x70),
+	DEFINE_RES_IRQ(evt2irq(0xf00)),
 };
 
 static struct platform_device cmt_device = {
-	.name		= "sh_cmt",
+	.name		= "sh-cmt-32",
 	.id		= 0,
 	.dev = {
 		.platform_data	= &cmt_platform_data,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 5a94efc..1c0e14b 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -412,27 +412,27 @@ static struct platform_device jpu_device = {
 	.num_resources	= ARRAY_SIZE(jpu_resources),
 };
 
+static struct sh_timer_channel_config cmt_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+		.clocksource_rating = 125,
+	},
+};
+
 static struct sh_timer_config cmt_platform_data = {
-	.channel_offset = 0x60,
-	.timer_bit = 5,
-	.clockevent_rating = 125,
-	.clocksource_rating = 125,
+	.channels = cmt_channels,
+	.num_channels = ARRAY_SIZE(cmt_channels),
+	.channels_mask = 0x1f,
 };
 
 static struct resource cmt_resources[] = {
-	[0] = {
-		.start	= 0x044a0060,
-		.end	= 0x044a006b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xf00),
-		.flags	= IORESOURCE_IRQ,
-	},
+	DEFINE_RES_MEM(0x044a0000, 0x70),
+	DEFINE_RES_IRQ(evt2irq(0xf00)),
 };
 
 static struct platform_device cmt_device = {
-	.name		= "sh_cmt",
+	.name		= "sh-cmt-32",
 	.id		= 0,
 	.dev = {
 		.platform_data	= &cmt_platform_data,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index 3c5eb09..9c08917 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -244,27 +244,27 @@ static struct platform_device veu1_device = {
 	.num_resources	= ARRAY_SIZE(veu1_resources),
 };
 
+static struct sh_timer_channel_config cmt_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+		.clocksource_rating = 125,
+	},
+};
+
 static struct sh_timer_config cmt_platform_data = {
-	.channel_offset = 0x60,
-	.timer_bit = 5,
-	.clockevent_rating = 125,
-	.clocksource_rating = 125,
+	.channels = cmt_channels,
+	.num_channels = ARRAY_SIZE(cmt_channels),
+	.channels_mask = 0x1f,
 };
 
 static struct resource cmt_resources[] = {
-	[0] = {
-		.start	= 0x044a0060,
-		.end	= 0x044a006b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xf00),
-		.flags	= IORESOURCE_IRQ,
-	},
+	DEFINE_RES_MEM(0x044a0000, 0x70),
+	DEFINE_RES_IRQ(evt2irq(0xf00)),
 };
 
 static struct platform_device cmt_device = {
-	.name		= "sh_cmt",
+	.name		= "sh-cmt-32",
 	.id		= 0,
 	.dev = {
 		.platform_data	= &cmt_platform_data,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index 60ebbc6..be587a9 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -647,27 +647,27 @@ static struct platform_device beu1_device = {
 	.num_resources	= ARRAY_SIZE(beu1_resources),
 };
 
+static struct sh_timer_channel_config cmt_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+		.clocksource_rating = 200,
+	},
+};
+
 static struct sh_timer_config cmt_platform_data = {
-	.channel_offset = 0x60,
-	.timer_bit = 5,
-	.clockevent_rating = 125,
-	.clocksource_rating = 200,
+	.channels = cmt_channels,
+	.num_channels = ARRAY_SIZE(cmt_channels),
+	.channels_mask = 0x1f,
 };
 
 static struct resource cmt_resources[] = {
-	[0] = {
-		.start	= 0x044a0060,
-		.end	= 0x044a006b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0xf00),
-		.flags	= IORESOURCE_IRQ,
-	},
+	DEFINE_RES_MEM(0x044a0000, 0x70),
+	DEFINE_RES_IRQ(evt2irq(0xf00)),
 };
 
 static struct platform_device cmt_device = {
-	.name		= "sh_cmt",
+	.name		= "sh-cmt-32",
 	.id		= 0,
 	.dev = {
 		.platform_data	= &cmt_platform_data,
-- 
1.8.3.2

[PATCH 17/27] ARM: shmobile: sh73a0: Switch to new style CMT device

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:14

The CMT (Compare Match Timer) driver implements a new style of platform
data that handles the timer as a single device with multiple channel.
Switch from the old-style platform data to the new-style platform data.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/mach-shmobile/clock-sh73a0.c |  2 +-
 arch/arm/mach-shmobile/setup-sh73a0.c | 45 ++++++++++++++++-------------------
 2 files changed, 22 insertions(+), 25 deletions(-)
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index 23edf83..723c5c5 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -650,7 +650,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
 	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
-	CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
+	CLKDEV_DEV_ID("sh-cmt-48.1", &mstp_clks[MSTP329]), /* CMT1 */
 	CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */
 	CLKDEV_DEV_ID("ec230000.sound", &mstp_clks[MSTP328]), /* FSI */
 	CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index f74ab53..738bbe4 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -104,35 +104,32 @@ SH73A0_SCIF(PORT_SCIFA, 6, 0xe6cc0000, gic_spi(156));
 SH73A0_SCIF(PORT_SCIFA, 7, 0xe6cd0000, gic_spi(143));
 SH73A0_SCIF(PORT_SCIFB, 8, 0xe6c30000, gic_spi(80));
 
-static struct sh_timer_config cmt10_platform_data = {
-	.name = "CMT10",
-	.channel_offset = 0x10,
-	.timer_bit = 0,
-	.clockevent_rating = 80,
-	.clocksource_rating = 125,
+static struct sh_timer_channel_config cmt1_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 80,
+		.clocksource_rating = 125,
+	},
 };
 
-static struct resource cmt10_resources[] = {
-	[0] = {
-		.name	= "CMT10",
-		.start	= 0xe6138010,
-		.end	= 0xe613801b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= gic_spi(65),
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct sh_timer_config cmt1_platform_data = {
+	.channels = cmt1_channels,
+	.num_channels = ARRAY_SIZE(cmt1_channels),
 };
 
-static struct platform_device cmt10_device = {
-	.name		= "sh_cmt",
-	.id		= 10,
+static struct resource cmt1_resources[] = {
+	DEFINE_RES_MEM(0xe6138010, 0x200),
+	DEFINE_RES_IRQ(gic_spi(65)),
+};
+
+static struct platform_device cmt1_device = {
+	.name		= "sh-cmt-48",
+	.id		= 1,
 	.dev = {
-		.platform_data	= &cmt10_platform_data,
+		.platform_data	= &cmt1_platform_data,
 	},
-	.resource	= cmt10_resources,
-	.num_resources	= ARRAY_SIZE(cmt10_resources),
+	.resource	= cmt1_resources,
+	.num_resources	= ARRAY_SIZE(cmt1_resources),
 };
 
 /* TMU */
@@ -746,7 +743,7 @@ static struct platform_device *sh73a0_devices_dt[] __initdata = {
 	&scif6_device,
 	&scif7_device,
 	&scif8_device,
-	&cmt10_device,
+	&cmt1_device,
 };
 
 static struct platform_device *sh73a0_early_devices[] __initdata = {
-- 
1.8.3.2

[PATCH 18/27] ARM: shmobile: r8a73a4: Switch to new style CMT device

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:16

The CMT (Compare Match Timer) driver implements a new style of platform
data that handles the timer as a single device with multiple channel.
Switch from the old-style platform data to the new-style platform data.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/mach-shmobile/clock-r8a73a4.c |  2 +-
 arch/arm/mach-shmobile/setup-r8a73a4.c | 25 +++++++++++++++----------
 2 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-shmobile/clock-r8a73a4.c b/arch/arm/mach-shmobile/clock-r8a73a4.c
index 7348d58..cd75821 100644
--- a/arch/arm/mach-shmobile/clock-r8a73a4.c
+++ b/arch/arm/mach-shmobile/clock-r8a73a4.c
@@ -597,7 +597,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("e6560000.i2c", &mstp_clks[MSTP317]),
 	CLKDEV_DEV_ID("e6500000.i2c", &mstp_clks[MSTP318]),
 	CLKDEV_DEV_ID("e6510000.i2c", &mstp_clks[MSTP323]),
-	CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]),
+	CLKDEV_DEV_ID("sh-cmt-48-gen2.1", &mstp_clks[MSTP329]),
 	CLKDEV_DEV_ID("e60b0000.i2c", &mstp_clks[MSTP409]),
 	CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP410]),
 	CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP411]),
diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c
index cd36f80..5794229 100644
--- a/arch/arm/mach-shmobile/setup-r8a73a4.c
+++ b/arch/arm/mach-shmobile/setup-r8a73a4.c
@@ -169,20 +169,25 @@ static const struct resource thermal0_resources[] = {
 					thermal0_resources,		\
 					ARRAY_SIZE(thermal0_resources))
 
-static struct sh_timer_config cmt10_platform_data = {
-	.name = "CMT10",
-	.timer_bit = 0,
-	.clockevent_rating = 80,
+static struct sh_timer_channel_config cmt1_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 80,
+	},
+};
+
+static struct sh_timer_config cmt1_platform_data = {
+	.channels = cmt1_channels,
+	.num_channels = ARRAY_SIZE(cmt1_channels),
 };
 
-static struct resource cmt10_resources[] = {
-	DEFINE_RES_MEM(0xe6130010, 0x0c),
-	DEFINE_RES_MEM(0xe6130000, 0x04),
-	DEFINE_RES_IRQ(gic_spi(120)), /* CMT1_0 */
+static struct resource cmt1_resources[] = {
+	DEFINE_RES_MEM(0xe6130000, 0x1004),
+	DEFINE_RES_IRQ(gic_spi(120)),
 };
 
 #define r8a7790_register_cmt(idx)					\
-	platform_device_register_resndata(&platform_bus, "sh_cmt",	\
+	platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
 					  idx, cmt##idx##_resources,	\
 					  ARRAY_SIZE(cmt##idx##_resources), \
 					  &cmt##idx##_platform_data,	\
@@ -196,7 +201,7 @@ void __init r8a73a4_add_dt_devices(void)
 	r8a73a4_register_scif(3);
 	r8a73a4_register_scif(4);
 	r8a73a4_register_scif(5);
-	r8a7790_register_cmt(10);
+	r8a7790_register_cmt(1);
 }
 
 /* DMA */
-- 
1.8.3.2

[PATCH 19/27] ARM: shmobile: r8a7740: Switch to new style CMT device

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:18

The CMT (Compare Match Timer) driver implements a new style of platform
data that handles the timer as a single device with multiple channel.
Switch from the old-style platform data to the new-style platform data.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/mach-shmobile/clock-r8a7740.c |  2 +-
 arch/arm/mach-shmobile/setup-r8a7740.c | 45 ++++++++++++++++------------------
 2 files changed, 22 insertions(+), 25 deletions(-)
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index dd989f9..50d3073 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -583,7 +583,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh-sci.6",		&mstp_clks[MSTP230]),
 	CLKDEV_DEV_ID("e6cc0000.sci",		&mstp_clks[MSTP230]),
 
-	CLKDEV_DEV_ID("sh_cmt.10",		&mstp_clks[MSTP329]),
+	CLKDEV_DEV_ID("sh-cmt-48.1",		&mstp_clks[MSTP329]),
 	CLKDEV_DEV_ID("sh_fsi2",		&mstp_clks[MSTP328]),
 	CLKDEV_DEV_ID("fe1f0000.sound",		&mstp_clks[MSTP328]),
 	CLKDEV_DEV_ID("i2c-sh_mobile.1",	&mstp_clks[MSTP323]),
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 8f3c681..f88856e 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -237,35 +237,32 @@ R8A7740_SCIF(PORT_SCIFA, 7, 0xe6cd0000, gic_spi(107));
 R8A7740_SCIF(PORT_SCIFB, 8, 0xe6c30000, gic_spi(108));
 
 /* CMT */
-static struct sh_timer_config cmt10_platform_data = {
-	.name = "CMT10",
-	.channel_offset = 0x10,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 125,
+static struct sh_timer_channel_config cmt1_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 125,
+		.clocksource_rating = 125,
+	},
 };
 
-static struct resource cmt10_resources[] = {
-	[0] = {
-		.name	= "CMT10",
-		.start	= 0xe6138010,
-		.end	= 0xe613801b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= gic_spi(58),
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct sh_timer_config cmt1_platform_data = {
+	.channels = cmt1_channels,
+	.num_channels = ARRAY_SIZE(cmt1_channels),
 };
 
-static struct platform_device cmt10_device = {
-	.name		= "sh_cmt",
-	.id		= 10,
+static struct resource cmt1_resources[] = {
+	DEFINE_RES_MEM(0xe6138000, 0x170),
+	DEFINE_RES_IRQ(gic_spi(58)),
+};
+
+static struct platform_device cmt1_device = {
+	.name		= "sh-cmt-48",
+	.id		= 1,
 	.dev = {
-		.platform_data	= &cmt10_platform_data,
+		.platform_data	= &cmt1_platform_data,
 	},
-	.resource	= cmt10_resources,
-	.num_resources	= ARRAY_SIZE(cmt10_resources),
+	.resource	= cmt1_resources,
+	.num_resources	= ARRAY_SIZE(cmt1_resources),
 };
 
 /* TMU */
@@ -400,7 +397,7 @@ static struct platform_device *r8a7740_devices_dt[] __initdata = {
 	&scif6_device,
 	&scif7_device,
 	&scif8_device,
-	&cmt10_device,
+	&cmt1_device,
 };
 
 static struct platform_device *r8a7740_early_devices[] __initdata = {
-- 
1.8.3.2

[PATCH 21/27] ARM: shmobile: r8a7791: Switch to new style CMT device

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:19

The CMT (Compare Match Timer) driver implements a new style of platform
data that handles the timer as a single device with multiple channel.
Switch from the old-style platform data to the new-style platform data.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/mach-shmobile/board-koelsch-reference.c |  2 +-
 arch/arm/mach-shmobile/clock-r8a7791.c           |  2 +-
 arch/arm/mach-shmobile/setup-r8a7791.c           | 26 +++++++++++++++---------
 3 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
index 46879d6..e67a4be7 100644
--- a/arch/arm/mach-shmobile/board-koelsch-reference.c
+++ b/arch/arm/mach-shmobile/board-koelsch-reference.c
@@ -39,7 +39,7 @@ static void __init koelsch_add_standard_devices(void)
 
 	clk = clk_get(NULL, "cmt0");
 	if (!IS_ERR(clk)) {
-		clk_register_clkdev(clk, NULL, "sh_cmt.0");
+		clk_register_clkdev(clk, NULL, "sh-cmt-48-gen2.0");
 		clk_put(clk);
 	}
 #else
diff --git a/arch/arm/mach-shmobile/clock-r8a7791.c b/arch/arm/mach-shmobile/clock-r8a7791.c
index fc9248d..4dac973 100644
--- a/arch/arm/mach-shmobile/clock-r8a7791.c
+++ b/arch/arm/mach-shmobile/clock-r8a7791.c
@@ -224,7 +224,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh-sci.12", &mstp_clks[MSTP1105]), /* SCIFA3 */
 	CLKDEV_DEV_ID("sh-sci.13", &mstp_clks[MSTP1106]), /* SCIFA4 */
 	CLKDEV_DEV_ID("sh-sci.14", &mstp_clks[MSTP1107]), /* SCIFA5 */
-	CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]),
+	CLKDEV_DEV_ID("sh-cmt-48-gen2.0", &mstp_clks[MSTP124]),
 	CLKDEV_DEV_ID("qspi.0", &mstp_clks[MSTP917]),
 	CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]),
 	CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
diff --git a/arch/arm/mach-shmobile/setup-r8a7791.c b/arch/arm/mach-shmobile/setup-r8a7791.c
index 605f4cf..a17ebb8 100644
--- a/arch/arm/mach-shmobile/setup-r8a7791.c
+++ b/arch/arm/mach-shmobile/setup-r8a7791.c
@@ -128,20 +128,26 @@ R8A7791_SCIFA(14, 0xe6c80000, gic_spi(31)); /* SCIFA5 */
 					  &scif##index##_platform_data,	       \
 					  sizeof(scif##index##_platform_data))
 
-static const struct sh_timer_config cmt00_platform_data __initconst = {
-	.name = "CMT00",
-	.timer_bit = 0,
-	.clockevent_rating = 80,
+static struct sh_timer_channel_config cmt0_channels[] = {
+	{
+		.index = 0,
+		.clockevent_rating = 80,
+	},
 };
 
-static const struct resource cmt00_resources[] __initconst = {
-	DEFINE_RES_MEM(0xffca0510, 0x0c),
-	DEFINE_RES_MEM(0xffca0500, 0x04),
-	DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */
+static struct sh_timer_config cmt0_platform_data = {
+	.channels = cmt0_channels,
+	.num_channels = ARRAY_SIZE(cmt0_channels),
+	.channels_mask = 0x1f,
+};
+
+static struct resource cmt0_resources[] = {
+	DEFINE_RES_MEM(0xffca0000, 0x1004),
+	DEFINE_RES_IRQ(gic_spi(142)),
 };
 
 #define r8a7791_register_cmt(idx)					\
-	platform_device_register_resndata(&platform_bus, "sh_cmt",	\
+	platform_device_register_resndata(&platform_bus, "sh-cmt-48-gen2", \
 					  idx, cmt##idx##_resources,	\
 					  ARRAY_SIZE(cmt##idx##_resources), \
 					  &cmt##idx##_platform_data,	\
@@ -185,7 +191,7 @@ static const struct resource thermal_resources[] __initconst = {
 
 void __init r8a7791_add_dt_devices(void)
 {
-	r8a7791_register_cmt(00);
+	r8a7791_register_cmt(0);
 }
 
 void __init r8a7791_add_standard_devices(void)
-- 
1.8.3.2

[PATCH 22/27] clocksource: sh_cmt: Drop support for legacy platform data

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:21

Now that all platforms have switched to the new-style platform data,
drop support for the legacy version.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 174 ++++++++++---------------------------------
 1 file changed, 39 insertions(+), 135 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 077879b..fe9694b 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -115,9 +115,7 @@ struct sh_cmt_device {
 	struct platform_device *pdev;
 
 	const struct sh_cmt_info *info;
-	bool legacy;
 
-	void __iomem *mapbase_ch;
 	void __iomem *mapbase;
 	struct clk *clk;
 
@@ -824,58 +822,45 @@ static int sh_cmt_register(struct sh_cmt_channel *ch, char *name,
 	return 0;
 }
 
-static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
+static int sh_cmt_setup_channel(struct sh_cmt_channel *ch,
 				const struct sh_timer_channel_config *ch_cfg,
 				unsigned int hwidx, struct sh_cmt_device *cmt)
 {
-	unsigned long clockevent_rating;
-	unsigned long clocksource_rating;
 	int irq;
 	int ret;
 
 	ch->cmt = cmt;
-	ch->index = ch_cfg ? ch_cfg->index : index;
+	ch->index = ch_cfg->index;
 	ch->hwidx = hwidx;
 
 	/*
 	 * Compute the address of the channel control register block. For the
 	 * timers with a per-channel start/stop register, compute its address
 	 * as well.
-	 *
-	 * For legacy configuration the address has been mapped explicitly.
 	 */
-	if (cmt->legacy) {
-		ch->ioctrl = cmt->mapbase_ch;
-	} else {
-		switch (cmt->info->model) {
-		case SH_CMT_16BIT:
-			ch->ioctrl = cmt->mapbase + 2 + ch->hwidx * 6;
-			break;
-		case SH_CMT_32BIT:
-		case SH_CMT_48BIT:
-			ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10;
-			break;
-		case SH_CMT_32BIT_FAST:
-			/*
-			 * The 32-bit "fast" timer has a single channel at hwidx
-			 * 5 but is located at offset 0x40 instead of 0x60 for
-			 * some reason.
-			 */
-			ch->ioctrl = cmt->mapbase + 0x40;
-			break;
-		case SH_CMT_48BIT_GEN2:
-			ch->iostart = cmt->mapbase + ch->hwidx * 0x100;
-			ch->ioctrl = ch->iostart + 0x10;
-			break;
-		}
+	switch (cmt->info->model) {
+	case SH_CMT_16BIT:
+		ch->ioctrl = cmt->mapbase + 2 + ch->hwidx * 6;
+		break;
+	case SH_CMT_32BIT:
+	case SH_CMT_48BIT:
+		ch->ioctrl = cmt->mapbase + 0x10 + ch->hwidx * 0x10;
+		break;
+	case SH_CMT_32BIT_FAST:
+		/*
+		 * The 32-bit "fast" timer has a single channel at hwidx 5 but
+		 * is located at offset 0x40 instead of 0x60 for some reason.
+		 */
+		ch->ioctrl = cmt->mapbase + 0x40;
+		break;
+	case SH_CMT_48BIT_GEN2:
+		ch->iostart = cmt->mapbase + ch->hwidx * 0x100;
+		ch->ioctrl = ch->iostart + 0x10;
+		break;
 	}
 
 	/* Request irq using setup_irq() (too early for request_irq()). */
-	if (cmt->legacy)
-		irq = platform_get_irq(cmt->pdev, 0);
-	else
-		irq = platform_get_irq(cmt->pdev, ch->index);
-
+	irq = platform_get_irq(cmt->pdev, ch->index);
 	if (irq < 0) {
 		dev_err(&cmt->pdev->dev, "failed to get irq\n");
 		return irq;
@@ -894,20 +879,11 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 	ch->match_value = ch->max_match_value;
 	raw_spin_lock_init(&ch->lock);
 
-	if (ch_cfg) {
-		ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2
-			      ? 0 : ch->hwidx;
-		clockevent_rating = ch_cfg->clockevent_rating;
-		clocksource_rating = ch_cfg->clocksource_rating;
-	} else {
-		struct sh_timer_config *cfg = cmt->pdev->dev.platform_data;
-		ch->timer_bit = cfg->timer_bit;
-		clockevent_rating = cfg->clockevent_rating;
-		clocksource_rating = cfg->clocksource_rating;
-	}
+	ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2 ? 0 : ch->hwidx;
 
 	ret = sh_cmt_register(ch, (char *)dev_name(&cmt->pdev->dev),
-			      clockevent_rating, clocksource_rating);
+			      ch_cfg->clockevent_rating,
+			      ch_cfg->clocksource_rating);
 	if (ret) {
 		dev_err(&cmt->pdev->dev, "registration failed\n");
 		return ret;
@@ -942,59 +918,12 @@ static int sh_cmt_map_memory(struct sh_cmt_device *cmt)
 	return 0;
 }
 
-static int sh_cmt_map_memory_legacy(struct sh_cmt_device *cmt)
-{
-	struct sh_timer_config *cfg = cmt->pdev->dev.platform_data;
-	struct resource *res, *res2;
-
-	/* map memory, let mapbase_ch point to our channel */
-	res = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&cmt->pdev->dev, "failed to get I/O memory\n");
-		return -ENXIO;
-	}
-
-	cmt->mapbase_ch = ioremap_nocache(res->start, resource_size(res));
-	if (cmt->mapbase_ch == NULL) {
-		dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n");
-		return -ENXIO;
-	}
-
-	/* optional resource for the shared timer start/stop register */
-	res2 = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 1);
-
-	/* map second resource for CMSTR */
-	cmt->mapbase = ioremap_nocache(res2 ? res2->start :
-				       res->start - cfg->channel_offset,
-				       res2 ? resource_size(res2) : 2);
-	if (cmt->mapbase == NULL) {
-		dev_err(&cmt->pdev->dev, "failed to remap I/O second memory\n");
-		iounmap(cmt->mapbase_ch);
-		return -ENXIO;
-	}
-
-	/* identify the model based on the resources */
-	if (resource_size(res) == 6)
-		cmt->info = &sh_cmt_info[SH_CMT_16BIT];
-	else if (res2 && (resource_size(res2) == 4))
-		cmt->info = &sh_cmt_info[SH_CMT_48BIT_GEN2];
-	else
-		cmt->info = &sh_cmt_info[SH_CMT_32BIT];
-
-	return 0;
-}
-
-static void sh_cmt_unmap_memory(struct sh_cmt_device *cmt)
-{
-	iounmap(cmt->mapbase);
-	if (cmt->mapbase_ch)
-		iounmap(cmt->mapbase_ch);
-}
-
 static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	const struct platform_device_id *id = pdev->id_entry;
+	unsigned int mask;
+	unsigned int i;
 	int ret;
 
 	memset(cmt, 0, sizeof(*cmt));
@@ -1006,10 +935,9 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 	}
 
 	cmt->info = (const struct sh_cmt_info *)id->driver_data;
-	cmt->legacy = cmt->info ? false : true;
 
 	/* Get hold of clock. */
-	cmt->clk = clk_get(&cmt->pdev->dev, cmt->legacy ? "cmt_fck" : NULL);
+	cmt->clk = clk_get(&cmt->pdev->dev, NULL);
 	if (IS_ERR(cmt->clk)) {
 		dev_err(&cmt->pdev->dev, "cannot get clock\n");
 		return PTR_ERR(cmt->clk);
@@ -1019,26 +947,14 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 	if (ret < 0)
 		goto err_clk_put;
 
-	/*
-	 * Map the memory resource(s). We need to support both the legacy
-	 * platform device configuration (with one device per channel) and the
-	 * new version (with multiple channels per device).
-	 */
-	if (cmt->legacy)
-		ret = sh_cmt_map_memory_legacy(cmt);
-	else
-		ret = sh_cmt_map_memory(cmt);
-
+	/* Map the memory resource(s). */
+	ret = sh_cmt_map_memory(cmt);
 	if (ret < 0)
 		goto err_clk_unprepare;
 
 	/* Allocate and setup the channels. */
-	if (cmt->legacy) {
-		cmt->num_channels = 1;
-	} else {
-		cmt->num_channels = cfg->num_channels;
-		cmt->hw_channels = ~cfg->channels_mask;
-	}
+	cmt->num_channels = cfg->num_channels;
+	cmt->hw_channels = ~cfg->channels_mask;
 
 	cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels),
 				GFP_KERNEL);
@@ -1047,26 +963,15 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 		goto err_unmap;
 	}
 
-	if (cmt->legacy) {
-		ret = sh_cmt_setup_channel(&cmt->channels[0], cfg->timer_bit,
-					   NULL, cfg->timer_bit, cmt);
+	for (i = 0, mask = cmt->hw_channels; i < cmt->num_channels; ++i) {
+		unsigned int hwidx = ffs(mask) - 1;
+
+		ret = sh_cmt_setup_channel(&cmt->channels[i], &cfg->channels[i],
+					   hwidx, cmt);
 		if (ret < 0)
 			goto err_unmap;
-	} else {
-		const struct sh_timer_channel_config *ch_cfg = cfg->channels;
-		unsigned int mask = cmt->hw_channels;
-		unsigned int i;
-
-		for (i = 0; i < cmt->num_channels; ++i) {
-			unsigned int hwidx = ffs(mask) - 1;
 
-			ret = sh_cmt_setup_channel(&cmt->channels[i], 0, ch_cfg,
-						   hwidx, cmt);
-			if (ret < 0)
-				goto err_unmap;
-
-			mask &= ~(1 << hwidx);
-		}
+		mask &= ~(1 << hwidx);
 	}
 
 	platform_set_drvdata(pdev, cmt);
@@ -1075,7 +980,7 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 
 err_unmap:
 	kfree(cmt->channels);
-	sh_cmt_unmap_memory(cmt);
+	iounmap(cmt->mapbase);
 err_clk_unprepare:
 	clk_unprepare(cmt->clk);
 err_clk_put:
@@ -1128,7 +1033,6 @@ static int sh_cmt_remove(struct platform_device *pdev)
 }
 
 static const struct platform_device_id sh_cmt_id_table[] = {
-	{ "sh_cmt", 0 },
 	{ "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
 	{ "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
 	{ "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] },
-- 
1.8.3.2

[PATCH 25/27] ARM: shmobile: r8a7791: Add CMT devices to DT

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:22

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/boot/dts/r8a7791.dtsi | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 240c4ec..bcfb998 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -162,6 +162,44 @@
 			     <1 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
 	};
 
+	cmt0: timer at ffca0000 {
+		compatible = "renesas,cmt-48-gen2";
+		reg = <0 0xffca0000 0 0x1004>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 142 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp1_clks R8A7791_CLK_CMT0>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		renesas,channels-mask = <0x60>;
+
+		status = "disabled";
+	};
+
+	cmt1: timer at e6130000 {
+		compatible = "renesas,cmt-48-gen2";
+		reg = <0 0xe6130000 0 0x1004>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 120 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 121 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 122 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 123 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 124 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 125 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 126 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 127 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7791_CLK_CMT1>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		renesas,channels-mask = <0xff>;
+
+		status = "disabled";
+	};
+
 	irqc0: interrupt-controller at e61c0000 {
 		compatible = "renesas,irqc-r8a7791", "renesas,irqc";
 		#interrupt-cells = <2>;
-- 
1.8.3.2

[PATCH 24/27] ARM: shmobile: r8a7790: Add CMT devices to DT

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:24

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/boot/dts/r8a7790.dtsi | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 54ab318..a236c7e 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -179,6 +179,44 @@
 			     <1 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
 	};
 
+	cmt0: timer at ffca0000 {
+		compatible = "renesas,cmt-48-gen2";
+		reg = <0 0xffca0000 0 0x1004>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 142 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp1_clks R8A7790_CLK_CMT0>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		renesas,channels-mask = <0x60>;
+
+		status = "disabled";
+	};
+
+	cmt1: timer at e6130000 {
+		compatible = "renesas,cmt-48-gen2";
+		reg = <0 0xe6130000 0 0x1004>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 120 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 121 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 122 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 123 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 124 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 125 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 126 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 127 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7790_CLK_CMT1>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		renesas,channels-mask = <0xff>;
+
+		status = "disabled";
+	};
+
 	irqc0: interrupt-controller at e61c0000 {
 		compatible = "renesas,irqc-r8a7790", "renesas,irqc";
 		#interrupt-cells = <2>;
-- 
1.8.3.2

[PATCH 26/27] ARM: shmobile: lager-reference: Enable CMT0 in device tree

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:25

Enable the CMT0 device and configure channel 0 as a clock event
provider.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/boot/dts/r8a7790-lager.dts            |  9 +++++++++
 arch/arm/mach-shmobile/board-lager-reference.c | 15 +--------------
 arch/arm/mach-shmobile/include/mach/r8a7790.h  |  1 -
 arch/arm/mach-shmobile/setup-r8a7790.c         |  7 +------
 4 files changed, 11 insertions(+), 21 deletions(-)
diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index 4199ae4..54ab17d 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -84,6 +84,15 @@
 	};
 };
 
+&cmt0 {
+	status = "ok";
+
+	channel at 0 {
+		reg = <0>;
+		clock-event-rating = <80>;
+	};
+};
+
 &mmcif1 {
 	pinctrl-0 = <&mmc1_pins>;
 	pinctrl-names = "default";
diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index 4dd43b1..ee95a8c 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -29,23 +29,10 @@
 
 static void __init lager_add_standard_devices(void)
 {
-#ifdef CONFIG_COMMON_CLK
-	/*
-	 * This is a really crude hack to provide clkdev support to the CMT
-	 * device until it gets moved to DT.
-	 */
-	struct clk *clk;
-
-	clk = clk_get(NULL, "cmt0");
-	if (!IS_ERR(clk)) {
-		clk_register_clkdev(clk, NULL, "sh-cmt-48-gen2.0");
-		clk_put(clk);
-	}
-#else
+#ifndef CONFIG_COMMON_CLK
 	r8a7790_clock_init();
 #endif
 
-	r8a7790_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h
index 0b95bab..62b31f3 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -29,7 +29,6 @@ enum {
 };
 
 void r8a7790_add_standard_devices(void);
-void r8a7790_add_dt_devices(void);
 void r8a7790_clock_init(void);
 void r8a7790_pinmux_init(void);
 void r8a7790_pm_init(void);
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
index 3e5813f..462c81f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -294,11 +294,6 @@ static struct resource cmt0_resources[] = {
 					  &cmt##idx##_platform_data,	\
 					  sizeof(struct sh_timer_config))
 
-void __init r8a7790_add_dt_devices(void)
-{
-	r8a7790_register_cmt(0);
-}
-
 void __init r8a7790_add_standard_devices(void)
 {
 	r8a7790_register_scif(0);
@@ -311,7 +306,7 @@ void __init r8a7790_add_standard_devices(void)
 	r8a7790_register_scif(7);
 	r8a7790_register_scif(8);
 	r8a7790_register_scif(9);
-	r8a7790_add_dt_devices();
+	r8a7790_register_cmt(0);
 	r8a7790_register_irqc(0);
 	r8a7790_register_thermal();
 }
-- 
1.8.3.2

[PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:28

Cc: devicetree at vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../devicetree/bindings/timer/renesas,cmt.txt      |  75 +++++++++++++++
 drivers/clocksource/sh_cmt.c                       | 104 +++++++++++++++++----
 2 files changed, 160 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/renesas,cmt.txt
diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
new file mode 100644
index 0000000..28d4ab5
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -0,0 +1,75 @@
+* Renesas R-Car Compare Match Timer (CMT)
+
+The CMT is a multi-channel 16/32/48-bit timer/counter with configurable clock
+inputs and programmable compare match.
+
+Channels share hadware resources but their counter and compare match value are
+independent. A particular CMT instance can implement only a subset of the
+channels supported by the CMT model. Channels indices start from 0 and are
+consecutive.
+
+Required Properties:
+
+  - compatible: must contain one of the following.
+    - "renesas,cmt-32" for the 32-bit CMT
+		(CMT0 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-32-fast" for the 32-bit CMT with fast clock support
+		(CMT[234] on sh7372, sh73a0 and r8a7740)
+    - "renasas,cmt-48" for the 48-bit CMT
+		(CMT1 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-48-gen2" for the second generation 48-bit CMT
+    		(CMT[01] on r8a73a4, r8a7790 and r8a7791)
+
+  - reg: base address and length of the registers block for the timer module.
+  - interrupt-parent, interrupts: interrupt-specifier for the timer, one per
+    channel.
+  - clocks: phandle and clock-specifier pair for the functional clock.
+  - clock-names: must be "fck".
+
+  - #address-cells: must be 1
+  - #size-cells: must be 0
+
+  - renesas,channels-mask: integer bitmask of the channels implemented by the
+    timer instance.
+
+
+Each channel is described by a sub-node named "channel@<idx>", where <idx> is
+the channel index.
+
+Channels Required Properties:
+
+  - reg: the channel index.
+
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source device.
+  - clock-event-rating: rating of the timer as a clock event device.
+
+
+Example: R8A7790 (R-Car H2) CMT0 node
+
+	CMT0 on R8A7790 implements hardware channels 5 and 6 only and names
+	them channels 0 and 1 in the documentation.
+
+	cmt0: timer at ffca0000 {
+		compatible = "renesas,cmt-48-gen2";
+		reg = <0 0xffca0000 0 0x1004>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 142 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp1_clks R8A7790_CLK_CMT0>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		renesas,channels-mask = <0x60>;
+
+		channel at 0 {
+			reg = <0>;
+			clock-event-rating = <80>;
+		};
+		channel at 0 {
+			reg = <0>;
+			clock-source-rating = <80>;
+		};
+	};
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index fe9694b..8e46c40 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -24,6 +24,7 @@
 #include <linux/ioport.h>
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
@@ -918,10 +919,72 @@ static int sh_cmt_map_memory(struct sh_cmt_device *cmt)
 	return 0;
 }
 
+static const struct platform_device_id sh_cmt_id_table[] = {
+	{ "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
+	{ "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
+	{ "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] },
+	{ "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] },
+	{ "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
+
+static const struct of_device_id sh_cmt_of_table[] = {
+	{ .compatible = "renesas,cmt-32", .data = &sh_cmt_info[SH_CMT_32BIT] },
+	{ .compatible = "renesas,cmt-32-fast", .data = &sh_cmt_info[SH_CMT_32BIT_FAST] },
+	{ .compatible = "renasas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] },
+	{ .compatible = "renesas,cmt-48-gen2", .data = &sh_cmt_info[SH_CMT_48BIT_GEN2] },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sh_cmt_of_table);
+
+static struct sh_timer_channel_config *
+sh_cmt_parse_dt(struct sh_cmt_device *cmt)
+{
+	struct sh_timer_channel_config *channels;
+	struct sh_timer_channel_config *channel;
+	struct device_node *np = cmt->pdev->dev.of_node;
+	struct device_node *child;
+	int ret;
+
+	cmt->num_channels = of_get_child_count(np);
+	if (cmt->num_channels == 0)
+		return ERR_PTR(-EINVAL);
+
+	ret = of_property_read_u32(np, "renesas,channels-mask",
+				   &cmt->hw_channels);
+	if (ret < 0)
+		return ERR_PTR(-EINVAL);
+
+	channels = devm_kzalloc(&cmt->pdev->dev, sizeof(*channels), GFP_KERNEL);
+	if (channels == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	channel = channels;
+
+	for_each_child_of_node(np, child) {
+		u32 val;
+
+		ret = of_property_read_u32(child, "reg", &channel->index);
+		if (ret < 0)
+			return ERR_PTR(-EINVAL);
+
+		ret = of_property_read_u32(child, "clock-source-rating", &val);
+		if (ret == 0)
+			channel->clocksource_rating = val;
+		ret = of_property_read_u32(child, "clock-event-rating", &val);
+		if (ret == 0)
+			channel->clockevent_rating = val;
+
+		channel++;
+	}
+
+	return channels;
+}
+
 static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 {
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
-	const struct platform_device_id *id = pdev->id_entry;
+	const struct sh_timer_channel_config *ch_cfg;
 	unsigned int mask;
 	unsigned int i;
 	int ret;
@@ -929,13 +992,28 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 	memset(cmt, 0, sizeof(*cmt));
 	cmt->pdev = pdev;
 
-	if (!cfg) {
+	if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
+		const struct of_device_id *id;
+
+		id = of_match_node(sh_cmt_of_table, pdev->dev.of_node);
+		cmt->info = id->data;
+
+		ch_cfg = sh_cmt_parse_dt(cmt);
+		if (IS_ERR(ch_cfg))
+			return PTR_ERR(ch_cfg);
+	} else if (pdev->dev.platform_data) {
+		struct sh_timer_config *cfg = pdev->dev.platform_data;
+		const struct platform_device_id *id = pdev->id_entry;
+
+		cmt->info = (const struct sh_cmt_info *)id->driver_data;
+		cmt->num_channels = cfg->num_channels;
+		cmt->hw_channels = ~cfg->channels_mask;
+		ch_cfg = cfg->channels;
+	} else {
 		dev_err(&cmt->pdev->dev, "missing platform data\n");
 		return -ENXIO;
 	}
 
-	cmt->info = (const struct sh_cmt_info *)id->driver_data;
-
 	/* Get hold of clock. */
 	cmt->clk = clk_get(&cmt->pdev->dev, NULL);
 	if (IS_ERR(cmt->clk)) {
@@ -953,9 +1031,6 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 		goto err_clk_unprepare;
 
 	/* Allocate and setup the channels. */
-	cmt->num_channels = cfg->num_channels;
-	cmt->hw_channels = ~cfg->channels_mask;
-
 	cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels),
 				GFP_KERNEL);
 	if (cmt->channels == NULL) {
@@ -966,7 +1041,7 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 	for (i = 0, mask = cmt->hw_channels; i < cmt->num_channels; ++i) {
 		unsigned int hwidx = ffs(mask) - 1;
 
-		ret = sh_cmt_setup_channel(&cmt->channels[i], &cfg->channels[i],
+		ret = sh_cmt_setup_channel(&cmt->channels[i], &ch_cfg[i],
 					   hwidx, cmt);
 		if (ret < 0)
 			goto err_unmap;
@@ -1032,21 +1107,12 @@ static int sh_cmt_remove(struct platform_device *pdev)
 	return -EBUSY; /* cannot unregister clockevent and clocksource */
 }
 
-static const struct platform_device_id sh_cmt_id_table[] = {
-	{ "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
-	{ "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
-	{ "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] },
-	{ "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] },
-	{ "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] },
-	{ }
-};
-MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
-
 static struct platform_driver sh_cmt_device_driver = {
 	.probe		= sh_cmt_probe,
 	.remove		= sh_cmt_remove,
 	.driver		= {
 		.name	= "sh_cmt",
+		.of_match_table = of_match_ptr(sh_cmt_of_table),
 	},
 	.id_table	= sh_cmt_id_table,
 };
-- 
1.8.3.2

[PATCH 27/27] ARM: shmobile: koelsch-reference: Enable CMT0 in device tree

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:30

Enable the CMT0 device and configure channel 0 as a clock event
provider.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/boot/dts/r8a7791-koelsch.dts            |  9 +++++++++
 arch/arm/mach-shmobile/board-koelsch-reference.c | 15 +--------------
 arch/arm/mach-shmobile/include/mach/r8a7791.h    |  1 -
 arch/arm/mach-shmobile/setup-r8a7791.c           |  7 +------
 4 files changed, 11 insertions(+), 21 deletions(-)
diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
index 42fd5eb..36e1c33 100644
--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -130,6 +130,15 @@
 	};
 };
 
+&cmt0 {
+	status = "ok";
+
+	channel at 0 {
+		reg = <0>;
+		clock-event-rating = <80>;
+	};
+};
+
 &sata0 {
 	status = "okay";
 };
diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
index e67a4be7..abcb8da 100644
--- a/arch/arm/mach-shmobile/board-koelsch-reference.c
+++ b/arch/arm/mach-shmobile/board-koelsch-reference.c
@@ -30,22 +30,9 @@
 
 static void __init koelsch_add_standard_devices(void)
 {
-#ifdef CONFIG_COMMON_CLK
-	/*
-	 * This is a really crude hack to provide clkdev support to the CMT
-	 * device until they get moved to DT.
-	 */
-	struct clk *clk;
-
-	clk = clk_get(NULL, "cmt0");
-	if (!IS_ERR(clk)) {
-		clk_register_clkdev(clk, NULL, "sh-cmt-48-gen2.0");
-		clk_put(clk);
-	}
-#else
+#ifndef CONFIG_COMMON_CLK
 	r8a7791_clock_init();
 #endif
-	r8a7791_add_dt_devices();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7791.h b/arch/arm/mach-shmobile/include/mach/r8a7791.h
index 200fa69..57a37f1 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7791.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7791.h
@@ -2,7 +2,6 @@
 #define __ASM_R8A7791_H__
 
 void r8a7791_add_standard_devices(void);
-void r8a7791_add_dt_devices(void);
 void r8a7791_clock_init(void);
 void r8a7791_pinmux_init(void);
 void r8a7791_init_early(void);
diff --git a/arch/arm/mach-shmobile/setup-r8a7791.c b/arch/arm/mach-shmobile/setup-r8a7791.c
index a17ebb8..c1e9c0f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7791.c
+++ b/arch/arm/mach-shmobile/setup-r8a7791.c
@@ -189,11 +189,6 @@ static const struct resource thermal_resources[] __initconst = {
 					thermal_resources,		\
 					ARRAY_SIZE(thermal_resources))
 
-void __init r8a7791_add_dt_devices(void)
-{
-	r8a7791_register_cmt(0);
-}
-
 void __init r8a7791_add_standard_devices(void)
 {
 	r8a7791_register_scif(0);
@@ -211,7 +206,7 @@ void __init r8a7791_add_standard_devices(void)
 	r8a7791_register_scif(12);
 	r8a7791_register_scif(13);
 	r8a7791_register_scif(14);
-	r8a7791_add_dt_devices();
+	r8a7791_register_cmt(0);
 	r8a7791_register_irqc(0);
 	r8a7791_register_thermal();
 }
-- 
1.8.3.2

[PATCH 02/27] clocksource: sh_cmt: Rename struct sh_cmt_priv to sh_cmt_device

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: 2014-02-14 01:00:33

Channel data is private as well, rename priv to device to make the
distrinction between the core device and the channels clearer.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 116 +++++++++++++++++++++----------------------
 1 file changed, 58 insertions(+), 58 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 12ccd11..68cca0a 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -35,10 +35,10 @@
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 
-struct sh_cmt_priv;
+struct sh_cmt_device;
 
 struct sh_cmt_channel {
-	struct sh_cmt_priv *cmt;
+	struct sh_cmt_device *cmt;
 
 	struct irqaction irqaction;
 
@@ -54,7 +54,7 @@ struct sh_cmt_channel {
 	bool cs_enabled;
 };
 
-struct sh_cmt_priv {
+struct sh_cmt_device {
 	struct platform_device *pdev;
 
 	void __iomem *mapbase;
@@ -695,136 +695,136 @@ static int sh_cmt_register(struct sh_cmt_channel *ch, char *name,
 	return 0;
 }
 
-static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
+static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
-	struct sh_cmt_channel *ch = &p->channel;
+	struct sh_cmt_channel *ch = &cmt->channel;
 	struct resource *res, *res2;
 	int irq, ret;
 	ret = -ENXIO;
 
-	memset(p, 0, sizeof(*p));
-	p->pdev = pdev;
+	memset(cmt, 0, sizeof(*cmt));
+	cmt->pdev = pdev;
 
 	if (!cfg) {
-		dev_err(&p->pdev->dev, "missing platform data\n");
+		dev_err(&cmt->pdev->dev, "missing platform data\n");
 		goto err0;
 	}
 
-	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 0);
 	if (!res) {
-		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
+		dev_err(&cmt->pdev->dev, "failed to get I/O memory\n");
 		goto err0;
 	}
 
 	/* optional resource for the shared timer start/stop register */
-	res2 = platform_get_resource(p->pdev, IORESOURCE_MEM, 1);
+	res2 = platform_get_resource(cmt->pdev, IORESOURCE_MEM, 1);
 
-	irq = platform_get_irq(p->pdev, 0);
+	irq = platform_get_irq(cmt->pdev, 0);
 	if (irq < 0) {
-		dev_err(&p->pdev->dev, "failed to get irq\n");
+		dev_err(&cmt->pdev->dev, "failed to get irq\n");
 		goto err0;
 	}
 
 	/* map memory, let mapbase point to our channel */
-	p->mapbase = ioremap_nocache(res->start, resource_size(res));
-	if (p->mapbase == NULL) {
-		dev_err(&p->pdev->dev, "failed to remap I/O memory\n");
+	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");
 		goto err0;
 	}
 
 	/* map second resource for CMSTR */
-	p->mapbase_str = ioremap_nocache(res2 ? res2->start :
-					 res->start - cfg->channel_offset,
-					 res2 ? resource_size(res2) : 2);
-	if (p->mapbase_str == NULL) {
-		dev_err(&p->pdev->dev, "failed to remap I/O second memory\n");
+	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");
 		goto err1;
 	}
 
 	/* request irq using setup_irq() (too early for request_irq()) */
-	ch->irqaction.name = dev_name(&p->pdev->dev);
+	ch->irqaction.name = dev_name(&cmt->pdev->dev);
 	ch->irqaction.handler = sh_cmt_interrupt;
 	ch->irqaction.dev_id = ch;
 	ch->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
 
 	/* get hold of clock */
-	p->clk = clk_get(&p->pdev->dev, "cmt_fck");
-	if (IS_ERR(p->clk)) {
-		dev_err(&p->pdev->dev, "cannot get clock\n");
-		ret = PTR_ERR(p->clk);
+	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);
 		goto err2;
 	}
 
-	ret = clk_prepare(p->clk);
+	ret = clk_prepare(cmt->clk);
 	if (ret < 0)
 		goto err3;
 
 	if (res2 && (resource_size(res2) == 4)) {
 		/* assume both CMSTR and CMCSR to be 32-bit */
-		p->read_control = sh_cmt_read32;
-		p->write_control = sh_cmt_write32;
+		cmt->read_control = sh_cmt_read32;
+		cmt->write_control = sh_cmt_write32;
 	} else {
-		p->read_control = sh_cmt_read16;
-		p->write_control = sh_cmt_write16;
+		cmt->read_control = sh_cmt_read16;
+		cmt->write_control = sh_cmt_write16;
 	}
 
 	if (resource_size(res) == 6) {
-		p->width = 16;
-		p->read_count = sh_cmt_read16;
-		p->write_count = sh_cmt_write16;
-		p->overflow_bit = 0x80;
-		p->clear_bits = ~0x80;
+		cmt->width = 16;
+		cmt->read_count = sh_cmt_read16;
+		cmt->write_count = sh_cmt_write16;
+		cmt->overflow_bit = 0x80;
+		cmt->clear_bits = ~0x80;
 	} else {
-		p->width = 32;
-		p->read_count = sh_cmt_read32;
-		p->write_count = sh_cmt_write32;
-		p->overflow_bit = 0x8000;
-		p->clear_bits = ~0xc000;
+		cmt->width = 32;
+		cmt->read_count = sh_cmt_read32;
+		cmt->write_count = sh_cmt_write32;
+		cmt->overflow_bit = 0x8000;
+		cmt->clear_bits = ~0xc000;
 	}
 
-	if (p->width == (sizeof(ch->max_match_value) * 8))
+	if (cmt->width == (sizeof(ch->max_match_value) * 8))
 		ch->max_match_value = ~0;
 	else
-		ch->max_match_value = (1 << p->width) - 1;
+		ch->max_match_value = (1 << cmt->width) - 1;
 
-	ch->cmt = p;
+	ch->cmt = cmt;
 	ch->match_value = ch->max_match_value;
 	raw_spin_lock_init(&ch->lock);
 
-	ret = sh_cmt_register(ch, (char *)dev_name(&p->pdev->dev),
+	ret = sh_cmt_register(ch, (char *)dev_name(&cmt->pdev->dev),
 			      cfg->clockevent_rating,
 			      cfg->clocksource_rating);
 	if (ret) {
-		dev_err(&p->pdev->dev, "registration failed\n");
+		dev_err(&cmt->pdev->dev, "registration failed\n");
 		goto err4;
 	}
 	ch->cs_enabled = false;
 
 	ret = setup_irq(irq, &ch->irqaction);
 	if (ret) {
-		dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
+		dev_err(&cmt->pdev->dev, "failed to request irq %d\n", irq);
 		goto err4;
 	}
 
-	platform_set_drvdata(pdev, p);
+	platform_set_drvdata(pdev, cmt);
 
 	return 0;
 err4:
-	clk_unprepare(p->clk);
+	clk_unprepare(cmt->clk);
 err3:
-	clk_put(p->clk);
+	clk_put(cmt->clk);
 err2:
-	iounmap(p->mapbase_str);
+	iounmap(cmt->mapbase_str);
 err1:
-	iounmap(p->mapbase);
+	iounmap(cmt->mapbase);
 err0:
 	return ret;
 }
 
 static int sh_cmt_probe(struct platform_device *pdev)
 {
-	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+	struct sh_cmt_device *cmt = platform_get_drvdata(pdev);
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	int ret;
 
@@ -833,20 +833,20 @@ static int sh_cmt_probe(struct platform_device *pdev)
 		pm_runtime_enable(&pdev->dev);
 	}
 
-	if (p) {
+	if (cmt) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		goto out;
 	}
 
-	p = kmalloc(sizeof(*p), GFP_KERNEL);
-	if (p == NULL) {
+	cmt = kmalloc(sizeof(*cmt), GFP_KERNEL);
+	if (cmt == NULL) {
 		dev_err(&pdev->dev, "failed to allocate driver data\n");
 		return -ENOMEM;
 	}
 
-	ret = sh_cmt_setup(p, pdev);
+	ret = sh_cmt_setup(cmt, pdev);
 	if (ret) {
-		kfree(p);
+		kfree(cmt);
 		pm_runtime_idle(&pdev->dev);
 		return ret;
 	}
-- 
1.8.3.2

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Geert Uytterhoeven <geert@linux-m68k.org>
Date: 2014-02-14 09:19:07

On Fri, Feb 14, 2014 at 2:00 AM, Laurent Pinchart
[off-list ref] wrote:
quoted hunk
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -0,0 +1,75 @@
+* Renesas R-Car Compare Match Timer (CMT)
+
+The CMT is a multi-channel 16/32/48-bit timer/counter with configurable clock
16-bit is mentioned here ...
+inputs and programmable compare match.
+
+Channels share hadware resources but their counter and compare match value are
hardware
+independent. A particular CMT instance can implement only a subset of the
+channels supported by the CMT model. Channels indices start from 0 and are
Channel indices
+consecutive.
+
+Required Properties:
+
+  - compatible: must contain one of the following.
... why not add "renesas,cmt-16" here (and one extra line in the actual driver),
while you're at it?
+    - "renesas,cmt-32" for the 32-bit CMT
+               (CMT0 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-32-fast" for the 32-bit CMT with fast clock support
+               (CMT[234] on sh7372, sh73a0 and r8a7740)
+    - "renasas,cmt-48" for the 48-bit CMT
+               (CMT1 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-48-gen2" for the second generation 48-bit CMT
+               (CMT[01] on r8a73a4, r8a7790 and r8a7791)
Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Mark Rutland <mark.rutland@arm.com>
Date: 2014-02-14 10:58:53

On Fri, Feb 14, 2014 at 01:00:01AM +0000, Laurent Pinchart wrote:
quoted hunk
Cc: devicetree at vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../devicetree/bindings/timer/renesas,cmt.txt      |  75 +++++++++++++++
 drivers/clocksource/sh_cmt.c                       | 104 +++++++++++++++++----
 2 files changed, 160 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/renesas,cmt.txt
diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
new file mode 100644
index 0000000..28d4ab5
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -0,0 +1,75 @@
+* Renesas R-Car Compare Match Timer (CMT)
+
+The CMT is a multi-channel 16/32/48-bit timer/counter with configurable clock
+inputs and programmable compare match.
+
+Channels share hadware resources but their counter and compare match value are
+independent. A particular CMT instance can implement only a subset of the
+channels supported by the CMT model. Channels indices start from 0 and are
+consecutive.
+
+Required Properties:
+
+  - compatible: must contain one of the following.
+    - "renesas,cmt-32" for the 32-bit CMT
+		(CMT0 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-32-fast" for the 32-bit CMT with fast clock support
+		(CMT[234] on sh7372, sh73a0 and r8a7740)
+    - "renasas,cmt-48" for the 48-bit CMT
+		(CMT1 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-48-gen2" for the second generation 48-bit CMT
+    		(CMT[01] on r8a73a4, r8a7790 and r8a7791)
+
+  - reg: base address and length of the registers block for the timer module.
+  - interrupt-parent, interrupts: interrupt-specifier for the timer, one per
+    channel.
It might make more sense to describe the interrupt on the channel
subnode. It makes it far clearer which channel has which interrupt.
+  - clocks: phandle and clock-specifier pair for the functional clock.
+  - clock-names: must be "fck".
It would be nice to define the list once:

- clocks: A list of phandle + clock-specifier pairs, one for each entry
  in clock-names.
- clock-names: Should contain "fck" for the functional clock.
+
+  - #address-cells: must be 1
+  - #size-cells: must be 0
+
+  - renesas,channels-mask: integer bitmask of the channels implemented by the
+    timer instance.
This is implied by the presence of a subnode. Either remove this or the
subnodes.
+
+
+Each channel is described by a sub-node named "channel@<idx>", where <idx> is
+the channel index.
+
+Channels Required Properties:
+
+  - reg: the channel index.
+
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source device.
+  - clock-event-rating: rating of the timer as a clock event device.
This feels like a leak of Linux internals. Why do you need this?
+
+
+Example: R8A7790 (R-Car H2) CMT0 node
+
+	CMT0 on R8A7790 implements hardware channels 5 and 6 only and names
+	them channels 0 and 1 in the documentation.
+
+	cmt0: timer at ffca0000 {
+		compatible = "renesas,cmt-48-gen2";
+		reg = <0 0xffca0000 0 0x1004>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 142 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp1_clks R8A7790_CLK_CMT0>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		renesas,channels-mask = <0x60>;
+
+		channel at 0 {
+			reg = <0>;
+			clock-event-rating = <80>;
+		};
+		channel at 0 {
+			reg = <0>;
+			clock-source-rating = <80>;
+		};
Aaargh. Use the _real_ channel IDs for the reg proeprties and get rid of
the mask. It's pointlessly confusing.

Thanks,
Mark

Re: [PATCH 26/27] ARM: shmobile: lager-reference: Enable CMT0 in device tree

From: Sergei Shtylyov <hidden>
Date: 2014-02-14 13:45:55

Hello.

On 14-02-2014 5:00, Laurent Pinchart wrote:
Enable the CMT0 device and configure channel 0 as a clock event
provider.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
quoted hunk
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h
index 0b95bab..62b31f3 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -29,7 +29,6 @@ enum {
  };

  void r8a7790_add_standard_devices(void);
-void r8a7790_add_dt_devices(void);
  void r8a7790_clock_init(void);
  void r8a7790_pinmux_init(void);
  void r8a7790_pm_init(void);
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
index 3e5813f..462c81f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -294,11 +294,6 @@ static struct resource cmt0_resources[] = {
  					  &cmt##idx##_platform_data,	\
  					  sizeof(struct sh_timer_config))

-void __init r8a7790_add_dt_devices(void)
-{
-	r8a7790_register_cmt(0);
-}
-
  void __init r8a7790_add_standard_devices(void)
  {
  	r8a7790_register_scif(0);
@@ -311,7 +306,7 @@ void __init r8a7790_add_standard_devices(void)
  	r8a7790_register_scif(7);
  	r8a7790_register_scif(8);
  	r8a7790_register_scif(9);
-	r8a7790_add_dt_devices();
+	r8a7790_register_cmt(0);
  	r8a7790_register_irqc(0);
  	r8a7790_register_thermal();
  }
    IMHO, these 2 files should be split into a separate patch.

WBR, Sergei

Re: [PATCH 26/27] ARM: shmobile: lager-reference: Enable CMT0 in device tree

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-14 13:47:41

Hi Sergei,

Thank you for the review.

On Friday 14 February 2014 17:45:56 Sergei Shtylyov wrote:
On 14-02-2014 5:00, Laurent Pinchart wrote:
quoted
Enable the CMT0 device and configure channel 0 as a clock event
provider.

Signed-off-by: Laurent Pinchart
[off-list ref]
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h
b/arch/arm/mach-shmobile/include/mach/r8a7790.h index 0b95bab..62b31f3
100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -29,7 +29,6 @@ enum {
 };
  
 void r8a7790_add_standard_devices(void);
-void r8a7790_add_dt_devices(void);
 void r8a7790_clock_init(void);
 void r8a7790_pinmux_init(void);
 void r8a7790_pm_init(void);
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c
b/arch/arm/mach-shmobile/setup-r8a7790.c index 3e5813f..462c81f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -294,11 +294,6 @@ static struct resource cmt0_resources[] = {
  					  &cmt##idx##_platform_data,	\
  					  sizeof(struct sh_timer_config))

-void __init r8a7790_add_dt_devices(void)
-{
-	r8a7790_register_cmt(0);
-}
-
 void __init r8a7790_add_standard_devices(void)
 {
  	r8a7790_register_scif(0);
@@ -311,7 +306,7 @@ void __init r8a7790_add_standard_devices(void)
  	r8a7790_register_scif(7);
  	r8a7790_register_scif(8);
  	r8a7790_register_scif(9);
-	r8a7790_add_dt_devices();
+	r8a7790_register_cmt(0);
  	r8a7790_register_irqc(0);
  	r8a7790_register_thermal();
 }
    IMHO, these 2 files should be split into a separate patch.
That could easily be done, but why ?

-- 
Regards,

Laurent Pinchart

Re: [PATCH 27/27] ARM: shmobile: koelsch-reference: Enable CMT0 in device tree

From: Sergei Shtylyov <hidden>
Date: 2014-02-14 13:47:43

Hello.

On 14-02-2014 5:00, Laurent Pinchart wrote:
Enable the CMT0 device and configure channel 0 as a clock event
provider.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
  arch/arm/boot/dts/r8a7791-koelsch.dts            |  9 +++++++++
  arch/arm/mach-shmobile/board-koelsch-reference.c | 15 +--------------
  arch/arm/mach-shmobile/include/mach/r8a7791.h    |  1 -
  arch/arm/mach-shmobile/setup-r8a7791.c           |  7 +------
    The latter 2 files are worth splitting into a separate patch as well...
  4 files changed, 11 insertions(+), 21 deletions(-)
WBR, Sergei

Re: [PATCH 26/27] ARM: shmobile: lager-reference: Enable CMT0 in device tree

From: Sergei Shtylyov <hidden>
Date: 2014-02-14 14:13:42

On 14-02-2014 17:48, Laurent Pinchart wrote:
quoted
quoted
Enable the CMT0 device and configure channel 0 as a clock event
provider.
quoted
quoted
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
quoted
quoted
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h
b/arch/arm/mach-shmobile/include/mach/r8a7790.h index 0b95bab..62b31f3 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -29,7 +29,6 @@ enum {
  };

  void r8a7790_add_standard_devices(void);
-void r8a7790_add_dt_devices(void);
  void r8a7790_clock_init(void);
  void r8a7790_pinmux_init(void);
  void r8a7790_pm_init(void);
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c
b/arch/arm/mach-shmobile/setup-r8a7790.c index 3e5813f..462c81f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -294,11 +294,6 @@ static struct resource cmt0_resources[] = {
   					  &cmt##idx##_platform_data,	\
   					  sizeof(struct sh_timer_config))

-void __init r8a7790_add_dt_devices(void)
-{
-	r8a7790_register_cmt(0);
-}
-
  void __init r8a7790_add_standard_devices(void)
  {
   	r8a7790_register_scif(0);
@@ -311,7 +306,7 @@ void __init r8a7790_add_standard_devices(void)
   	r8a7790_register_scif(7);
   	r8a7790_register_scif(8);
   	r8a7790_register_scif(9);
-	r8a7790_add_dt_devices();
+	r8a7790_register_cmt(0);
   	r8a7790_register_irqc(0);
   	r8a7790_register_thermal();
  }
quoted
     IMHO, these 2 files should be split into a separate patch.
That could easily be done, but why ?
    It does not seem necessary to combine these changes in one patch. 
Remember, Simon has separate branches for boards and SoCs. So finally it's up 
to him to decide on this...

WBR, Sergei

Re: [PATCH 26/27] ARM: shmobile: lager-reference: Enable CMT0 in device tree

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-14 14:21:20

Hi Sergei,

On Friday 14 February 2014 18:13:44 Sergei Shtylyov wrote:
On 14-02-2014 17:48, Laurent Pinchart wrote:
quoted
quoted
quoted
Enable the CMT0 device and configure channel 0 as a clock event
provider.

Signed-off-by: Laurent Pinchart
[off-list ref]
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h
b/arch/arm/mach-shmobile/include/mach/r8a7790.h index 0b95bab..62b31f3
100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -29,7 +29,6 @@ enum {
 };
  
 void r8a7790_add_standard_devices(void);
-void r8a7790_add_dt_devices(void);
 void r8a7790_clock_init(void);
 void r8a7790_pinmux_init(void);
 void r8a7790_pm_init(void);
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c
b/arch/arm/mach-shmobile/setup-r8a7790.c index 3e5813f..462c81f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -294,11 +294,6 @@ static struct resource cmt0_resources[] = {
   					  &cmt##idx##_platform_data,	\
   					  sizeof(struct sh_timer_config))

-void __init r8a7790_add_dt_devices(void)
-{
-	r8a7790_register_cmt(0);
-}
-
 void __init r8a7790_add_standard_devices(void)
 {
   	r8a7790_register_scif(0);
@@ -311,7 +306,7 @@ void __init r8a7790_add_standard_devices(void)
   	r8a7790_register_scif(7);
   	r8a7790_register_scif(8);
   	r8a7790_register_scif(9);
-	r8a7790_add_dt_devices();
+	r8a7790_register_cmt(0);
   	r8a7790_register_irqc(0);
   	r8a7790_register_thermal();
 }
  
IMHO, these 2 files should be split into a separate patch.
That could easily be done, but why ?
It does not seem necessary to combine these changes in one patch. Remember,
Simon has separate branches for boards and SoCs. So finally it's up to him
to decide on this...
Right, but in this case I need to remove the CMT platform device registration 
from r8a7790_add_dt_devices() at the same time as I enable it in DT, otherwise 
we'll have two instances of the same device.

-- 
Regards,

Laurent Pinchart

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-14 14:34:50

Hi Geert,

Thank you for the review.

On Friday 14 February 2014 10:18:58 Geert Uytterhoeven wrote:
On Fri, Feb 14, 2014 at 2:00 AM, Laurent Pinchart wrote:
quoted
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -0,0 +1,75 @@
+* Renesas R-Car Compare Match Timer (CMT)
+
+The CMT is a multi-channel 16/32/48-bit timer/counter with configurable
clock
16-bit is mentioned here ...
quoted
+inputs and programmable compare match.
+
+Channels share hadware resources but their counter and compare match
value are
hardware
quoted
+independent. A particular CMT instance can implement only a subset of the
+channels supported by the CMT model. Channels indices start from 0 and
are
Channel indices
quoted
+consecutive.
+
+Required Properties:
+
+  - compatible: must contain one of the following.
... why not add "renesas,cmt-16" here (and one extra line in the actual
driver), while you're at it?
Because the 16-bit variant is only used on SuperH SoCs, so there's not much 
point in adding DT bindings for it.
quoted
+    - "renesas,cmt-32" for the 32-bit CMT
+               (CMT0 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-32-fast" for the 32-bit CMT with fast clock support
+               (CMT[234] on sh7372, sh73a0 and r8a7740)
+    - "renasas,cmt-48" for the 48-bit CMT
+               (CMT1 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-48-gen2" for the second generation 48-bit CMT
+               (CMT[01] on r8a73a4, r8a7790 and r8a7791)
-- 
Regards,

Laurent Pinchart

Re: [PATCH 26/27] ARM: shmobile: lager-reference: Enable CMT0 in device tree

From: Sergei Shtylyov <hidden>
Date: 2014-02-14 14:36:10

Hello.

On 14-02-2014 18:22, Laurent Pinchart wrote:
quoted
quoted
quoted
quoted
Enable the CMT0 device and configure channel 0 as a clock event
provider.
quoted
quoted
quoted
quoted
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
quoted
quoted
quoted
quoted
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h
b/arch/arm/mach-shmobile/include/mach/r8a7790.h index 0b95bab..62b31f3
100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -29,7 +29,6 @@ enum {
  };

  void r8a7790_add_standard_devices(void);
-void r8a7790_add_dt_devices(void);
  void r8a7790_clock_init(void);
  void r8a7790_pinmux_init(void);
  void r8a7790_pm_init(void);
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c
b/arch/arm/mach-shmobile/setup-r8a7790.c index 3e5813f..462c81f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -294,11 +294,6 @@ static struct resource cmt0_resources[] = {
    					  &cmt##idx##_platform_data,	\
    					  sizeof(struct sh_timer_config))

-void __init r8a7790_add_dt_devices(void)
-{
-	r8a7790_register_cmt(0);
-}
-
  void __init r8a7790_add_standard_devices(void)
  {
    	r8a7790_register_scif(0);
@@ -311,7 +306,7 @@ void __init r8a7790_add_standard_devices(void)
    	r8a7790_register_scif(7);
    	r8a7790_register_scif(8);
    	r8a7790_register_scif(9);
-	r8a7790_add_dt_devices();
+	r8a7790_register_cmt(0);
    	r8a7790_register_irqc(0);
    	r8a7790_register_thermal();
  }
IMHO, these 2 files should be split into a separate patch.
That could easily be done, but why ?
It does not seem necessary to combine these changes in one patch. Remember,
Simon has separate branches for boards and SoCs. So finally it's up to him
to decide on this...
Right, but in this case I need to remove the CMT platform device registration
from r8a7790_add_dt_devices()
    You're not removing anything in these 2 files, you're just replacing 
"indirect" call to r8a7790_register_cmt(0) with direct.

WBR, Sergei

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-14 15:52:07

Hi Mark,

Thank you for the review.

On Friday 14 February 2014 10:58:22 Mark Rutland wrote:
On Fri, Feb 14, 2014 at 01:00:01AM +0000, Laurent Pinchart wrote:
quoted
Cc: devicetree at vger.kernel.org
Signed-off-by: Laurent Pinchart
[off-list ref]
---

 .../devicetree/bindings/timer/renesas,cmt.txt      |  75 +++++++++++++++
 drivers/clocksource/sh_cmt.c                       | 104 +++++++++++++---
 2 files changed, 160 insertions(+), 19 deletions(-)
 create mode 100644
 Documentation/devicetree/bindings/timer/renesas,cmt.txt
diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt
b/Documentation/devicetree/bindings/timer/renesas,cmt.txt new file mode
100644
index 0000000..28d4ab5
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -0,0 +1,75 @@
+* Renesas R-Car Compare Match Timer (CMT)
+
+The CMT is a multi-channel 16/32/48-bit timer/counter with configurable
clock
+inputs and programmable compare match.
+
+Channels share hadware resources but their counter and compare match
value are
+independent. A particular CMT instance can implement only a subset of the
+channels supported by the CMT model. Channels indices start from 0 and
are
+consecutive.
+
+Required Properties:
+
+  - compatible: must contain one of the following.
+    - "renesas,cmt-32" for the 32-bit CMT
+		(CMT0 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-32-fast" for the 32-bit CMT with fast clock support
+		(CMT[234] on sh7372, sh73a0 and r8a7740)
+    - "renasas,cmt-48" for the 48-bit CMT
+		(CMT1 on sh7372, sh73a0 and r8a7740)
+    - "renesas,cmt-48-gen2" for the second generation 48-bit CMT
+    		(CMT[01] on r8a73a4, r8a7790 and r8a7791)
+
+  - reg: base address and length of the registers block for the timer
module.
+  - interrupt-parent, interrupts: interrupt-specifier for the timer, one
per
+    channel.
It might make more sense to describe the interrupt on the channel
subnode. It makes it far clearer which channel has which interrupt.
That's a good point. I'm relying on platform_get_irq() which won't support 
that usage, but I can switch to of_irq_to_resource() instead.
quoted
+  - clocks: phandle and clock-specifier pair for the functional clock.
+  - clock-names: must be "fck".
It would be nice to define the list once:

- clocks: A list of phandle + clock-specifier pairs, one for each entry
  in clock-names.
- clock-names: Should contain "fck" for the functional clock.
OK.
quoted
+
+  - #address-cells: must be 1
+  - #size-cells: must be 0
+
+  - renesas,channels-mask: integer bitmask of the channels implemented by
the
+    timer instance.
This is implied by the presence of a subnode. Either remove this or the
subnodes.
quoted
+
+
+Each channel is described by a sub-node named "channel@<idx>", where
<idx> is +the channel index.
+
+Channels Required Properties:
+
+  - reg: the channel index.
+
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source device.
+  - clock-event-rating: rating of the timer as a clock event device.
This feels like a leak of Linux internals. Why do you need this?
You're right, it is. The clock source and clock event ratings are currently 
configured through platform data, I'll need to find a way to compute them in 
the driver instead.

There's still one piece of Linux-specific data I need though, as I need to 
specify for each channel whether to use it as a clock source device, a clock 
event device, both of them or none. That's configuration information that 
needs to be provided somehow.
quoted
+
+
+Example: R8A7790 (R-Car H2) CMT0 node
+
+	CMT0 on R8A7790 implements hardware channels 5 and 6 only and names
+	them channels 0 and 1 in the documentation.
+
+	cmt0: timer at ffca0000 {
+		compatible = "renesas,cmt-48-gen2";
+		reg = <0 0xffca0000 0 0x1004>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 142 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp1_clks R8A7790_CLK_CMT0>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		renesas,channels-mask = <0x60>;
+
+		channel at 0 {
+			reg = <0>;
+			clock-event-rating = <80>;
+		};
+		channel at 0 {
+			reg = <0>;
+			clock-source-rating = <80>;
+		};
Aaargh. Use the _real_ channel IDs for the reg proeprties and get rid of
the mask. It's pointlessly confusing.
There's two real channel IDs. One of them is the value used in the hardware 
implementation (5 and 6 in this case, used to compute the channel registers 
block address) and the other one is the value used throughout the datasheet, 0 
and 1 in this case.

The later is used by the driver to reference the correct interrupt, which 
won't be needed anymore when referencing interrupts in the channel subnodes 
directly. It's also used to print messages to the kernel log and match the 
channel numbers specified in the datasheets. I could use the hardware channel 
number instead, but that might become confusing.

-- 
Regards,

Laurent Pinchart

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Magnus Damm <magnus.damm@gmail.com>
Date: 2014-02-14 16:01:33

On Sat, Feb 15, 2014 at 12:53 AM, Laurent Pinchart
[off-list ref] wrote:
On Friday 14 February 2014 10:58:22 Mark Rutland wrote:
quoted
On Fri, Feb 14, 2014 at 01:00:01AM +0000, Laurent Pinchart wrote:
quoted
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source device.
+  - clock-event-rating: rating of the timer as a clock event device.
This feels like a leak of Linux internals. Why do you need this?
You're right, it is. The clock source and clock event ratings are currently
configured through platform data, I'll need to find a way to compute them in
the driver instead.
That would be very good!
There's still one piece of Linux-specific data I need though, as I need to
specify for each channel whether to use it as a clock source device, a clock
event device, both of them or none. That's configuration information that
needs to be provided somehow.
I think you can decide clock source or clock event assignment based on
number of channels available. If you have only a single channel then
both clock event and clock source need to be supported. Otherwise use
one channel for clock source and the rest for clock events.

This is probably out of scope for this DT conversion, but it would be
neat if you somehow could specify the CPU affinity for a channel to
tie a clock event to an individual CPU core. This would make a a
per-cpu timer unless I'm mistaken. But that's more of a software
policy than anything else.

Thanks,

/ magnus

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Josh Cartwright <hidden>
Date: 2014-02-14 16:02:15

On Fri, Feb 14, 2014 at 04:53:08PM +0100, Laurent Pinchart wrote:
On Friday 14 February 2014 10:58:22 Mark Rutland wrote:
quoted
On Fri, Feb 14, 2014 at 01:00:01AM +0000, Laurent Pinchart wrote:
quoted
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source device.
+  - clock-event-rating: rating of the timer as a clock event device.
This feels like a leak of Linux internals. Why do you need this?
You're right, it is. The clock source and clock event ratings are currently
configured through platform data, I'll need to find a way to compute them in
the driver instead.

There's still one piece of Linux-specific data I need though, as I need to
specify for each channel whether to use it as a clock source device, a clock
event device, both of them or none. That's configuration information that
needs to be provided somehow.
Are all the channels equally capable?  We had this problem for the
cadence_ttc timer used on Zynq, and decided to just statically allocate
the first timer to be the clocksource, and the second to be the
clockevent.

Also, should the rating really be user configurable?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-14 16:11:23

Hi Magnus,

On Saturday 15 February 2014 01:01:30 Magnus Damm wrote:
On Sat, Feb 15, 2014 at 12:53 AM, Laurent Pinchart wrote:
quoted
On Friday 14 February 2014 10:58:22 Mark Rutland wrote:
quoted
On Fri, Feb 14, 2014 at 01:00:01AM +0000, Laurent Pinchart wrote:
quoted
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source device.
+  - clock-event-rating: rating of the timer as a clock event device.
This feels like a leak of Linux internals. Why do you need this?
You're right, it is. The clock source and clock event ratings are
currently configured through platform data, I'll need to find a way to
compute them in the driver instead.
That would be very good!
Any pointer would be appreciated :-) How did you compute the various ratings 
used in platform data all over the place ?
quoted
There's still one piece of Linux-specific data I need though, as I need to
specify for each channel whether to use it as a clock source device, a
clock event device, both of them or none. That's configuration
information that needs to be provided somehow.
I think you can decide clock source or clock event assignment based on
number of channels available. If you have only a single channel then both
clock event and clock source need to be supported. Otherwise use one channel
for clock source and the rest for clock events.
That won't match the current situation. Look at CMT0 in r8a7790 for instance. 
There's two hardware channels available, and we only use the first one, for 
clock events only.
This is probably out of scope for this DT conversion, but it would be neat
if you somehow could specify the CPU affinity for a channel to tie a clock
event to an individual CPU core. This would make a a per-cpu timer unless
I'm mistaken. But that's more of a software policy than anything else.
Yes, that's a configuration that needs to be specified somewhere. I don't know 
where though.

-- 
Regards,

Laurent Pinchart

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-14 16:14:21

Hi Josh,

On Friday 14 February 2014 09:59:51 Josh Cartwright wrote:
On Fri, Feb 14, 2014 at 04:53:08PM +0100, Laurent Pinchart wrote:
quoted
On Friday 14 February 2014 10:58:22 Mark Rutland wrote:
quoted
On Fri, Feb 14, 2014 at 01:00:01AM +0000, Laurent Pinchart wrote:
quoted
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source
device.
+  - clock-event-rating: rating of the timer as a clock event device.
This feels like a leak of Linux internals. Why do you need this?
You're right, it is. The clock source and clock event ratings are
currently configured through platform data, I'll need to find a way to
compute them in the driver instead.

There's still one piece of Linux-specific data I need though, as I need to
specify for each channel whether to use it as a clock source device, a
clock event device, both of them or none. That's configuration
information that needs to be provided somehow.
Are all the channels equally capable?  We had this problem for the
cadence_ttc timer used on Zynq, and decided to just statically allocate
the first timer to be the clocksource, and the second to be the
clockevent.
No, they're not. The channels can be implemented with different counter 
widths, different available prescalers and source clocks and different power 
management features (not all of them are capable to run in all sleep states).
Also, should the rating really be user configurable?
Probably not. I suppose the rating should be computed by the driver based on 
the source clock frequency, prescaler and counter width. Any help there would 
be very appreciated, I'm pretty new to clock source and clock event devices.

-- 
Regards,

Laurent Pinchart

Re: [PATCH 26/27] ARM: shmobile: lager-reference: Enable CMT0 in device tree

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-14 16:25:42

Hi Sergei,

On Friday 14 February 2014 18:36:11 Sergei Shtylyov wrote:
Hello.

On 14-02-2014 18:22, Laurent Pinchart wrote:
quoted
quoted
quoted
quoted
quoted
Enable the CMT0 device and configure channel 0 as a clock event
provider.

Signed-off-by: Laurent Pinchart
[off-list ref]
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h
b/arch/arm/mach-shmobile/include/mach/r8a7790.h index 0b95bab..62b31f3
100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -29,7 +29,6 @@ enum {

  };
  
  void r8a7790_add_standard_devices(void);

-void r8a7790_add_dt_devices(void);

  void r8a7790_clock_init(void);
  void r8a7790_pinmux_init(void);
  void r8a7790_pm_init(void);
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c
b/arch/arm/mach-shmobile/setup-r8a7790.c index 3e5813f..462c81f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -294,11 +294,6 @@ static struct resource cmt0_resources[] = {
    					  &cmt##idx##_platform_data,	\
    					  sizeof(struct sh_timer_config))

-void __init r8a7790_add_dt_devices(void)
-{
-	r8a7790_register_cmt(0);
-}
-
 void __init r8a7790_add_standard_devices(void)
 {
    	r8a7790_register_scif(0);
@@ -311,7 +306,7 @@ void __init r8a7790_add_standard_devices(void)
	r8a7790_register_scif(7);
 	r8a7790_register_scif(8);
 	r8a7790_register_scif(9);
-	r8a7790_add_dt_devices();
+	r8a7790_register_cmt(0);
	r8a7790_register_irqc(0);
	r8a7790_register_thermal();
}
IMHO, these 2 files should be split into a separate patch.
That could easily be done, but why ?
It does not seem necessary to combine these changes in one patch.
Remember, Simon has separate branches for boards and SoCs. So finally
it's up to him to decide on this...
Right, but in this case I need to remove the CMT platform device
registration from r8a7790_add_dt_devices()
You're not removing anything in these 2 files, you're just replacing
"indirect" call to r8a7790_register_cmt(0) with direct.
OK, I see what you mean now. Given that the patch removes the 
r8a7790_add_dt_devices() call from arch/arm/mach-shmobile/board-lager-
reference.c, I could indeed split those two changes into a separate patch as 
there's no-one calling the function anymore. That would introduce a dependency 
between the branches, which might not be better. I'll let Simon comment on 
what he would prefer and will act accordingly.

-- 
Regards,

Laurent Pinchart

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Magnus Damm <magnus.damm@gmail.com>
Date: 2014-02-14 17:22:04

Hi Laurent,

On Sat, Feb 15, 2014 at 1:12 AM, Laurent Pinchart
[off-list ref] wrote:
Hi Magnus,

On Saturday 15 February 2014 01:01:30 Magnus Damm wrote:
quoted
On Sat, Feb 15, 2014 at 12:53 AM, Laurent Pinchart wrote:
quoted
On Friday 14 February 2014 10:58:22 Mark Rutland wrote:
quoted
On Fri, Feb 14, 2014 at 01:00:01AM +0000, Laurent Pinchart wrote:
quoted
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source device.
+  - clock-event-rating: rating of the timer as a clock event device.
This feels like a leak of Linux internals. Why do you need this?
You're right, it is. The clock source and clock event ratings are
currently configured through platform data, I'll need to find a way to
compute them in the driver instead.
That would be very good!
Any pointer would be appreciated :-) How did you compute the various ratings
used in platform data all over the place ?
Historically we used the rating to select between CMT and TMU. For
clock sources I suppose you also have the jiffy rating to consider.
And for the SMP parts we have ARM IP for TWD and arch timers that have
their ratings too. So you need to check all the timers on a particular
system and consider what you want to have operating by default. The
ARM IP timers should be preferred if available. For clock sources the
rule is probably the higher resolution the better.
quoted
quoted
There's still one piece of Linux-specific data I need though, as I need to
specify for each channel whether to use it as a clock source device, a
clock event device, both of them or none. That's configuration
information that needs to be provided somehow.
I think you can decide clock source or clock event assignment based on
number of channels available. If you have only a single channel then both
clock event and clock source need to be supported. Otherwise use one channel
for clock source and the rest for clock events.
That won't match the current situation. Look at CMT0 in r8a7790 for instance.
There's two hardware channels available, and we only use the first one, for
clock events only.
You are correct. The reason for that is that the CMT driver today is
optimized for combined clock event and clock source operation.

Historically the hardware it initially was written for (sh-mobile on
the SH arch) only had a single timer channel so combined operation was
required for tickless to work. But since you're asking how to allocate
channels then I propose checking numbers of channels available and go
from there. With that the r8a7790 support can only get better. =)
quoted
This is probably out of scope for this DT conversion, but it would be neat
if you somehow could specify the CPU affinity for a channel to tie a clock
event to an individual CPU core. This would make a a per-cpu timer unless
I'm mistaken. But that's more of a software policy than anything else.
Yes, that's a configuration that needs to be specified somewhere. I don't know
where though.
As long as you have per-channel interrupts described in DT you can
probably handle this in a generic way in the driver.

Thanks,

/ magnus

Re: [PATCH 26/27] ARM: shmobile: lager-reference: Enable CMT0 in device tree

From: Sergei Shtylyov <hidden>
Date: 2014-02-14 18:56:58

On 02/14/2014 07:26 PM, Laurent Pinchart wrote:
quoted
quoted
quoted
quoted
quoted
quoted
Enable the CMT0 device and configure channel 0 as a clock event
provider.
quoted
quoted
quoted
quoted
quoted
quoted
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
quoted
quoted
quoted
quoted
quoted
quoted
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h
b/arch/arm/mach-shmobile/include/mach/r8a7790.h index 0b95bab..62b31f3
100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -29,7 +29,6 @@ enum {

   };

   void r8a7790_add_standard_devices(void);

-void r8a7790_add_dt_devices(void);

   void r8a7790_clock_init(void);
   void r8a7790_pinmux_init(void);
   void r8a7790_pm_init(void);
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c
b/arch/arm/mach-shmobile/setup-r8a7790.c index 3e5813f..462c81f 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -294,11 +294,6 @@ static struct resource cmt0_resources[] = {
     					  &cmt##idx##_platform_data,	\
     					  sizeof(struct sh_timer_config))

-void __init r8a7790_add_dt_devices(void)
-{
-	r8a7790_register_cmt(0);
-}
-
  void __init r8a7790_add_standard_devices(void)
  {
     	r8a7790_register_scif(0);
@@ -311,7 +306,7 @@ void __init r8a7790_add_standard_devices(void)
	r8a7790_register_scif(7);
  	r8a7790_register_scif(8);
  	r8a7790_register_scif(9);
-	r8a7790_add_dt_devices();
+	r8a7790_register_cmt(0);
	r8a7790_register_irqc(0);
	r8a7790_register_thermal();
}
quoted
quoted
quoted
quoted
quoted
IMHO, these 2 files should be split into a separate patch.
quoted
quoted
quoted
quoted
That could easily be done, but why ?
quoted
quoted
quoted
It does not seem necessary to combine these changes in one patch.
Remember, Simon has separate branches for boards and SoCs. So finally
it's up to him to decide on this...
quoted
quoted
Right, but in this case I need to remove the CMT platform device
registration from r8a7790_add_dt_devices()
quoted
You're not removing anything in these 2 files, you're just replacing
"indirect" call to r8a7790_register_cmt(0) with direct.
OK, I see what you mean now. Given that the patch removes the
r8a7790_add_dt_devices() call from arch/arm/mach-shmobile/board-lager-
reference.c, I could indeed split those two changes into a separate patch as
there's no-one calling the function anymore. That would introduce a dependency
between the branches, which might not be better. I'll let Simon comment on
what he would prefer and will act accordingly.
    Yes, the branch inter-dependencies are bad too. I didn't think about it, 
sorry.

WBR, Sergei

Re: [PATCH 11/27] clocksource: sh_cmt: Add support for multiple channels per device

From: Thomas Gleixner <hidden>
Date: 2014-02-15 12:46:49

On Fri, 14 Feb 2014, Laurent Pinchart wrote:
quoted hunk
CMT hardware devices can support multiple channels, with global
registers and per-channel registers. The sh_cmt driver currently models
the hardware with one Linux device per channel. This model makes it
difficult to handle global registers in a clean way.

Add support for a new model that uses one Linux device per timer with
multiple channels per device. This requires changes to platform data,
add new channel configuration fields.

Support for the legacy model is kept and will be removed after all
platforms switch to the new model.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c | 299 +++++++++++++++++++++++++++++++++----------
 include/linux/sh_timer.h     |   9 ++
 2 files changed, 239 insertions(+), 69 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 5280231..8390f0f 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -53,7 +53,16 @@ struct sh_cmt_device;
  * channel registers block. All other versions have a shared start/stop register
  * located in the global space.
  *
- * Note that CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing 32-bit
+ * Channels are indexed from 0 to N-1 in the documentation. The channel index
+ * infers the start/stop bit position in the control register and the channel
+ * registers block address. Some CMT instances have a subset of channels
+ * available, in which case the index in the documentation doesn't match the
+ * "real" index as implemented in hardware. This is for instance the case with
+ * CMT0 on r8a7740, which is a 32-bit variant with a single channel numbered 0
+ * in the documentation but using start/stop bit 5 and having its registers
+ * block at 0x60.
+ *
+ * Similarly CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing 32-bit
  * channels only, is a 48-bit gen2 CMT with the 48-bit channels unavailable.
  */
 
@@ -85,11 +94,15 @@ struct sh_cmt_info {
 
 struct sh_cmt_channel {
 	struct sh_cmt_device *cmt;
-	unsigned int index;
 
-	void __iomem *base;
+	unsigned int index;	/* Index in the documentation */
+	unsigned int hwidx;	/* Real hardware index */
+
+	void __iomem *iostart;
+	void __iomem *ioctrl;
 	struct irqaction irqaction;
While you are at it, can you please get rid of that irqaction and use
request_irq() ?
  
Thanks,

	tglx

Re: [PATCH 11/27] clocksource: sh_cmt: Add support for multiple channels per device

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-16 18:16:57

Hi Thomas,

On Saturday 15 February 2014 13:46:54 Thomas Gleixner wrote:
On Fri, 14 Feb 2014, Laurent Pinchart wrote:
quoted
CMT hardware devices can support multiple channels, with global
registers and per-channel registers. The sh_cmt driver currently models
the hardware with one Linux device per channel. This model makes it
difficult to handle global registers in a clean way.

Add support for a new model that uses one Linux device per timer with
multiple channels per device. This requires changes to platform data,
add new channel configuration fields.

Support for the legacy model is kept and will be removed after all
platforms switch to the new model.

Signed-off-by: Laurent Pinchart
[off-list ref]
---

 drivers/clocksource/sh_cmt.c | 299 +++++++++++++++++++++++++++++---------
 include/linux/sh_timer.h     |   9 ++
 2 files changed, 239 insertions(+), 69 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 5280231..8390f0f 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -53,7 +53,16 @@ struct sh_cmt_device;

  * channel registers block. All other versions have a shared start/stop
  register * located in the global space.
  *

- * Note that CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing
32-bit + * Channels are indexed from 0 to N-1 in the documentation. The
channel index + * infers the start/stop bit position in the control
register and the channel + * registers block address. Some CMT instances
have a subset of channels + * available, in which case the index in the
documentation doesn't match the + * "real" index as implemented in
hardware. This is for instance the case with + * CMT0 on r8a7740, which
is a 32-bit variant with a single channel numbered 0 + * in the
documentation but using start/stop bit 5 and having its registers + *
block at 0x60.
+ *
+ * Similarly CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing
32-bit> 
  * channels only, is a 48-bit gen2 CMT with the 48-bit channels
  unavailable.
  */
@@ -85,11 +94,15 @@ struct sh_cmt_info {

 struct sh_cmt_channel {
 
 	struct sh_cmt_device *cmt;

-	unsigned int index;

-	void __iomem *base;
+	unsigned int index;	/* Index in the documentation */
+	unsigned int hwidx;	/* Real hardware index */
+
+	void __iomem *iostart;
+	void __iomem *ioctrl;

 	struct irqaction irqaction;
While you are at it, can you please get rid of that irqaction and use
request_irq() ?
The driver claims it can't use request_irq() because the function is not 
available for early platform devices. If the situation has changed I'd gladly 
get rid of irqaction.

-- 
Regards,

Laurent Pinchart

Re: [PATCH 11/27] clocksource: sh_cmt: Add support for multiple channels per device

From: Magnus Damm <magnus.damm@gmail.com>
Date: 2014-02-17 01:41:34

Hi Laurent,

On Mon, Feb 17, 2014 at 3:18 AM, Laurent Pinchart
[off-list ref] wrote:
Hi Thomas,

On Saturday 15 February 2014 13:46:54 Thomas Gleixner wrote:
quoted
On Fri, 14 Feb 2014, Laurent Pinchart wrote:
quoted
CMT hardware devices can support multiple channels, with global
registers and per-channel registers. The sh_cmt driver currently models
the hardware with one Linux device per channel. This model makes it
difficult to handle global registers in a clean way.

Add support for a new model that uses one Linux device per timer with
multiple channels per device. This requires changes to platform data,
add new channel configuration fields.

Support for the legacy model is kept and will be removed after all
platforms switch to the new model.

Signed-off-by: Laurent Pinchart
[off-list ref]
---

 drivers/clocksource/sh_cmt.c | 299 +++++++++++++++++++++++++++++---------
 include/linux/sh_timer.h     |   9 ++
 2 files changed, 239 insertions(+), 69 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 5280231..8390f0f 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -53,7 +53,16 @@ struct sh_cmt_device;

  * channel registers block. All other versions have a shared start/stop
  register * located in the global space.
  *

- * Note that CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing
32-bit + * Channels are indexed from 0 to N-1 in the documentation. The
channel index + * infers the start/stop bit position in the control
register and the channel + * registers block address. Some CMT instances
have a subset of channels + * available, in which case the index in the
documentation doesn't match the + * "real" index as implemented in
hardware. This is for instance the case with + * CMT0 on r8a7740, which
is a 32-bit variant with a single channel numbered 0 + * in the
documentation but using start/stop bit 5 and having its registers + *
block at 0x60.
+ *
+ * Similarly CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing
32-bit>
  * channels only, is a 48-bit gen2 CMT with the 48-bit channels
  unavailable.
  */
@@ -85,11 +94,15 @@ struct sh_cmt_info {

 struct sh_cmt_channel {

    struct sh_cmt_device *cmt;

-   unsigned int index;

-   void __iomem *base;
+   unsigned int index;     /* Index in the documentation */
+   unsigned int hwidx;     /* Real hardware index */
+
+   void __iomem *iostart;
+   void __iomem *ioctrl;

    struct irqaction irqaction;
While you are at it, can you please get rid of that irqaction and use
request_irq() ?
The driver claims it can't use request_irq() because the function is not
available for early platform devices. If the situation has changed I'd gladly
get rid of irqaction.
With the risk of stating the obvious, this depends on how early the
early platform device stuff is being run. The actual location may not
be the same on SH and ARM for instance.

On ARM we are doing all we can to initialize these devices as late as
ever possible in the MULTIPLAFORM (DT reference) case. Once we manage
to remove the legacy ARM case then there is one less user of early
platform timers.

One perhaps reasonable way forward could be to use request_irq() in
case of DT and leave the legacy platform data case to rely on
irqaction.

Cheers,

/ magnus

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-17 01:44:18

Hi Magnus,

On Saturday 15 February 2014 02:22:00 Magnus Damm wrote:
On Sat, Feb 15, 2014 at 1:12 AM, Laurent Pinchart wrote:
quoted
On Saturday 15 February 2014 01:01:30 Magnus Damm wrote:
quoted
On Sat, Feb 15, 2014 at 12:53 AM, Laurent Pinchart wrote:
quoted
On Friday 14 February 2014 10:58:22 Mark Rutland wrote:
quoted
On Fri, Feb 14, 2014 at 01:00:01AM +0000, Laurent Pinchart wrote:
quoted
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source
device.
+  - clock-event-rating: rating of the timer as a clock event
device.
This feels like a leak of Linux internals. Why do you need this?
You're right, it is. The clock source and clock event ratings are
currently configured through platform data, I'll need to find a way to
compute them in the driver instead.
That would be very good!
Any pointer would be appreciated :-) How did you compute the various
ratings used in platform data all over the place ?
Historically we used the rating to select between CMT and TMU. For
clock sources I suppose you also have the jiffy rating to consider.
And for the SMP parts we have ARM IP for TWD and arch timers that have
their ratings too. So you need to check all the timers on a particular
system and consider what you want to have operating by default. The
ARM IP timers should be preferred if available. For clock sources the
rule is probably the higher resolution the better.
quoted
quoted
quoted
There's still one piece of Linux-specific data I need though, as I need
to specify for each channel whether to use it as a clock source device,
a clock event device, both of them or none. That's configuration
information that needs to be provided somehow.
I think you can decide clock source or clock event assignment based on
number of channels available. If you have only a single channel then both
clock event and clock source need to be supported. Otherwise use one
channel for clock source and the rest for clock events.
That won't match the current situation. Look at CMT0 in r8a7790 for
instance. There's two hardware channels available, and we only use the
first one, for clock events only.
You are correct. The reason for that is that the CMT driver today is
optimized for combined clock event and clock source operation.

Historically the hardware it initially was written for (sh-mobile on
the SH arch) only had a single timer channel so combined operation was
required for tickless to work. But since you're asking how to allocate
channels then I propose checking numbers of channels available and go
from there. With that the r8a7790 support can only get better. =)
quoted
quoted
This is probably out of scope for this DT conversion, but it would be
neat if you somehow could specify the CPU affinity for a channel to tie a
clock event to an individual CPU core. This would make a a per-cpu timer
unless I'm mistaken. But that's more of a software policy than anything
else.
Yes, that's a configuration that needs to be specified somewhere. I don't
know where though.
As long as you have per-channel interrupts described in DT you can
probably handle this in a generic way in the driver.
But how do we decide whether to use a single timer channel or one channel per 
CPU ? Will the kernel use one clock event device per CPU automatically ? I 
have to confess I have no idea how this works.

-- 
Regards,

Laurent Pinchart

Re: [PATCH 11/27] clocksource: sh_cmt: Add support for multiple channels per device

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-17 01:47:38

Hi Magnus,

On Monday 17 February 2014 10:41:31 Magnus Damm wrote:
On Mon, Feb 17, 2014 at 3:18 AM, Laurent Pinchart wrote:
quoted
On Saturday 15 February 2014 13:46:54 Thomas Gleixner wrote:
quoted
On Fri, 14 Feb 2014, Laurent Pinchart wrote:
quoted
CMT hardware devices can support multiple channels, with global
registers and per-channel registers. The sh_cmt driver currently models
the hardware with one Linux device per channel. This model makes it
difficult to handle global registers in a clean way.

Add support for a new model that uses one Linux device per timer with
multiple channels per device. This requires changes to platform data,
add new channel configuration fields.

Support for the legacy model is kept and will be removed after all
platforms switch to the new model.

Signed-off-by: Laurent Pinchart
[off-list ref]
---

 drivers/clocksource/sh_cmt.c | 299 ++++++++++++++++++++++++++---------
 include/linux/sh_timer.h     |   9 ++
 2 files changed, 239 insertions(+), 69 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c
b/drivers/clocksource/sh_cmt.c
index 5280231..8390f0f 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
[snip]
quoted
quoted
quoted
@@ -85,11 +94,15 @@ struct sh_cmt_info {

 struct sh_cmt_channel {
    struct sh_cmt_device *cmt;
-   unsigned int index;
-   void __iomem *base;
+   unsigned int index;     /* Index in the documentation */
+   unsigned int hwidx;     /* Real hardware index */
+
+   void __iomem *iostart;
+   void __iomem *ioctrl;

    struct irqaction irqaction;
While you are at it, can you please get rid of that irqaction and use
request_irq() ?
The driver claims it can't use request_irq() because the function is not
available for early platform devices. If the situation has changed I'd
gladly get rid of irqaction.
With the risk of stating the obvious, this depends on how early the
early platform device stuff is being run. The actual location may not
be the same on SH and ARM for instance.

On ARM we are doing all we can to initialize these devices as late as
ever possible in the MULTIPLAFORM (DT reference) case. Once we manage
to remove the legacy ARM case then there is one less user of early
platform timers.

One perhaps reasonable way forward could be to use request_irq() in
case of DT and leave the legacy platform data case to rely on
irqaction.
The whole point of switching from setup_irq() to request_irq() is to simplify 
the code. Adding request_irq() as an option would go in the opposite 
direction.

-- 
Regards,

Laurent Pinchart

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Magnus Damm <magnus.damm@gmail.com>
Date: 2014-02-17 01:48:58

Hi Laurent,

On Mon, Feb 17, 2014 at 10:45 AM, Laurent Pinchart
[off-list ref] wrote:
Hi Magnus,

On Saturday 15 February 2014 02:22:00 Magnus Damm wrote:
quoted
On Sat, Feb 15, 2014 at 1:12 AM, Laurent Pinchart wrote:
quoted
On Saturday 15 February 2014 01:01:30 Magnus Damm wrote:
quoted
On Sat, Feb 15, 2014 at 12:53 AM, Laurent Pinchart wrote:
quoted
On Friday 14 February 2014 10:58:22 Mark Rutland wrote:
quoted
On Fri, Feb 14, 2014 at 01:00:01AM +0000, Laurent Pinchart wrote:
quoted
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source
device.
+  - clock-event-rating: rating of the timer as a clock event
device.
This feels like a leak of Linux internals. Why do you need this?
You're right, it is. The clock source and clock event ratings are
currently configured through platform data, I'll need to find a way to
compute them in the driver instead.
That would be very good!
Any pointer would be appreciated :-) How did you compute the various
ratings used in platform data all over the place ?
Historically we used the rating to select between CMT and TMU. For
clock sources I suppose you also have the jiffy rating to consider.
And for the SMP parts we have ARM IP for TWD and arch timers that have
their ratings too. So you need to check all the timers on a particular
system and consider what you want to have operating by default. The
ARM IP timers should be preferred if available. For clock sources the
rule is probably the higher resolution the better.
quoted
quoted
quoted
There's still one piece of Linux-specific data I need though, as I need
to specify for each channel whether to use it as a clock source device,
a clock event device, both of them or none. That's configuration
information that needs to be provided somehow.
I think you can decide clock source or clock event assignment based on
number of channels available. If you have only a single channel then both
clock event and clock source need to be supported. Otherwise use one
channel for clock source and the rest for clock events.
That won't match the current situation. Look at CMT0 in r8a7790 for
instance. There's two hardware channels available, and we only use the
first one, for clock events only.
You are correct. The reason for that is that the CMT driver today is
optimized for combined clock event and clock source operation.

Historically the hardware it initially was written for (sh-mobile on
the SH arch) only had a single timer channel so combined operation was
required for tickless to work. But since you're asking how to allocate
channels then I propose checking numbers of channels available and go
from there. With that the r8a7790 support can only get better. =)
quoted
quoted
This is probably out of scope for this DT conversion, but it would be
neat if you somehow could specify the CPU affinity for a channel to tie a
clock event to an individual CPU core. This would make a a per-cpu timer
unless I'm mistaken. But that's more of a software policy than anything
else.
Yes, that's a configuration that needs to be specified somewhere. I don't
know where though.
As long as you have per-channel interrupts described in DT you can
probably handle this in a generic way in the driver.
But how do we decide whether to use a single timer channel or one channel per
CPU ? Will the kernel use one clock event device per CPU automatically ? I
have to confess I have no idea how this works.
I guess that's the tricky bit about timer support, it is a mix of
hardware description and software configuration. So it sounds to me
that we need some kind of software configuration interface. But it can
probably be considered when/if we add such kind of support to the
driver. Probably out of scope for now.

Regardless it seems to me that the hardware description in DT doesn't
need to care about this.

Cheers,

/ magnus

Re: [PATCH 11/27] clocksource: sh_cmt: Add support for multiple channels per device

From: Magnus Damm <magnus.damm@gmail.com>
Date: 2014-02-17 02:07:11

Hi Laurent,

On Mon, Feb 17, 2014 at 10:48 AM, Laurent Pinchart
[off-list ref] wrote:
Hi Magnus,

On Monday 17 February 2014 10:41:31 Magnus Damm wrote:
quoted
On Mon, Feb 17, 2014 at 3:18 AM, Laurent Pinchart wrote:
quoted
On Saturday 15 February 2014 13:46:54 Thomas Gleixner wrote:
quoted
On Fri, 14 Feb 2014, Laurent Pinchart wrote:
quoted
CMT hardware devices can support multiple channels, with global
registers and per-channel registers. The sh_cmt driver currently models
the hardware with one Linux device per channel. This model makes it
difficult to handle global registers in a clean way.

Add support for a new model that uses one Linux device per timer with
multiple channels per device. This requires changes to platform data,
add new channel configuration fields.

Support for the legacy model is kept and will be removed after all
platforms switch to the new model.

Signed-off-by: Laurent Pinchart
[off-list ref]
---

 drivers/clocksource/sh_cmt.c | 299 ++++++++++++++++++++++++++---------
 include/linux/sh_timer.h     |   9 ++
 2 files changed, 239 insertions(+), 69 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c
b/drivers/clocksource/sh_cmt.c
index 5280231..8390f0f 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
[snip]
quoted
quoted
quoted
quoted
@@ -85,11 +94,15 @@ struct sh_cmt_info {

 struct sh_cmt_channel {
    struct sh_cmt_device *cmt;
-   unsigned int index;
-   void __iomem *base;
+   unsigned int index;     /* Index in the documentation */
+   unsigned int hwidx;     /* Real hardware index */
+
+   void __iomem *iostart;
+   void __iomem *ioctrl;

    struct irqaction irqaction;
While you are at it, can you please get rid of that irqaction and use
request_irq() ?
The driver claims it can't use request_irq() because the function is not
available for early platform devices. If the situation has changed I'd
gladly get rid of irqaction.
With the risk of stating the obvious, this depends on how early the
early platform device stuff is being run. The actual location may not
be the same on SH and ARM for instance.

On ARM we are doing all we can to initialize these devices as late as
ever possible in the MULTIPLAFORM (DT reference) case. Once we manage
to remove the legacy ARM case then there is one less user of early
platform timers.

One perhaps reasonable way forward could be to use request_irq() in
case of DT and leave the legacy platform data case to rely on
irqaction.
The whole point of switching from setup_irq() to request_irq() is to simplify
the code. Adding request_irq() as an option would go in the opposite
direction.
The point of switching to setup_irq() was not very clear to me. I
think it is fine to switch to using it over time, and I'm open to any
alternative ways forward. Usually moving in incremental steps means
more crap in the short term, but if someone could come up with a way
that involves little crap then I'm all for that! =)

Thanks,

/ magnus

Re: [PATCH 11/27] clocksource: sh_cmt: Add support for multiple channels per device

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-17 09:57:01

Hi Magnus,

On Monday 17 February 2014 11:07:06 Magnus Damm wrote:
On Mon, Feb 17, 2014 at 10:48 AM, Laurent Pinchart wrote:
quoted
On Monday 17 February 2014 10:41:31 Magnus Damm wrote:
quoted
On Mon, Feb 17, 2014 at 3:18 AM, Laurent Pinchart wrote:
quoted
On Saturday 15 February 2014 13:46:54 Thomas Gleixner wrote:
quoted
On Fri, 14 Feb 2014, Laurent Pinchart wrote:
quoted
CMT hardware devices can support multiple channels, with global
registers and per-channel registers. The sh_cmt driver currently
models the hardware with one Linux device per channel. This model
makes it difficult to handle global registers in a clean way.

Add support for a new model that uses one Linux device per timer
with multiple channels per device. This requires changes to platform
data, add new channel configuration fields.

Support for the legacy model is kept and will be removed after all
platforms switch to the new model.

Signed-off-by: Laurent Pinchart
[off-list ref]
---

 drivers/clocksource/sh_cmt.c | 299 ++++++++++++++++++++++++--------
 include/linux/sh_timer.h     |   9 ++
 2 files changed, 239 insertions(+), 69 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c
b/drivers/clocksource/sh_cmt.c
index 5280231..8390f0f 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
[snip]
quoted
quoted
quoted
quoted
@@ -85,11 +94,15 @@ struct sh_cmt_info {

 struct sh_cmt_channel {
    struct sh_cmt_device *cmt;

-   unsigned int index;
-   void __iomem *base;
+   unsigned int index;     /* Index in the documentation */
+   unsigned int hwidx;     /* Real hardware index */
+
+   void __iomem *iostart;
+   void __iomem *ioctrl;

    struct irqaction irqaction;
While you are at it, can you please get rid of that irqaction and use
request_irq() ?
The driver claims it can't use request_irq() because the function is
not available for early platform devices. If the situation has changed
I'd gladly get rid of irqaction.
With the risk of stating the obvious, this depends on how early the
early platform device stuff is being run. The actual location may not
be the same on SH and ARM for instance.

On ARM we are doing all we can to initialize these devices as late as
ever possible in the MULTIPLAFORM (DT reference) case. Once we manage
to remove the legacy ARM case then there is one less user of early
platform timers.

One perhaps reasonable way forward could be to use request_irq() in
case of DT and leave the legacy platform data case to rely on
irqaction.
The whole point of switching from setup_irq() to request_irq() is to
simplify the code. Adding request_irq() as an option would go in the
opposite direction.
The point of switching to setup_irq() was not very clear to me. I
think it is fine to switch to using it over time, and I'm open to any
alternative ways forward. Usually moving in incremental steps means
more crap in the short term, but if someone could come up with a way
that involves little crap then I'm all for that! =)
I've had a quick look at request_irq(). The function is defined as a static 
inline in include/linux/interrupt.h:

static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
            const char *name, void *dev)
{
        return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}

request_threaded_irq() is implemented in kernel/irq/manage.c. I've removed the 
code paths that would never be taken when called by the sh_cmt driver, due to

- handler not being NULL
- thread_fn being NULL
- CONFIG_DEBUG_SHIRQ_FIXME not being set
- IRQF_SHARED not being set

int request_threaded_irq(unsigned int irq, irq_handler_t handler,
                         irq_handler_t thread_fn, unsigned long irqflags,
                         const char *devname, void *dev_id)
{
        struct irqaction *action;
        struct irq_desc *desc;
        int retval;

        desc = irq_to_desc(irq);
        if (!desc)
                return -EINVAL;

        if (!irq_settings_can_request(desc) ||
            WARN_ON(irq_settings_is_per_cpu_devid(desc)))
                return -EINVAL;

        action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
        if (!action)
                return -ENOMEM;

        action->handler = handler;
        action->thread_fn = thread_fn;
        action->flags = irqflags;
        action->name = devname;
        action->dev_id = dev_id;

        chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, action);
        chip_bus_sync_unlock(desc);

        if (retval)
                kfree(action);

        return retval;
}

setup_irq() is implemented in the same file as

int setup_irq(unsigned int irq, struct irqaction *act)
{
        int retval;
        struct irq_desc *desc = irq_to_desc(irq);

        if (WARN_ON(irq_settings_is_per_cpu_devid(desc)))
                return -EINVAL;
        chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, act);
        chip_bus_sync_unlock(desc);

        return retval;
}

The only two differences between request_irq() and setup_irq() would thus be

- the extra !irq_settings_can_request(desc) check
- the extra kzalloc() call

The former should only be true for chained IRQ handlers, which isn't the case 
here. The latter is just a kmalloc + kmap_atomic + memset as far as I can 
tell.

It thus seems safe to replace setup_irq() with request_irq().

-- 
Regards,

Laurent Pinchart

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-17 21:42:35

Hi Magnus,

On Monday 17 February 2014 10:48:55 Magnus Damm wrote:
On Mon, Feb 17, 2014 at 10:45 AM, Laurent Pinchart wrote:
quoted
On Saturday 15 February 2014 02:22:00 Magnus Damm wrote:
quoted
On Sat, Feb 15, 2014 at 1:12 AM, Laurent Pinchart wrote:
quoted
On Saturday 15 February 2014 01:01:30 Magnus Damm wrote:
quoted
On Sat, Feb 15, 2014 at 12:53 AM, Laurent Pinchart wrote:
quoted
On Friday 14 February 2014 10:58:22 Mark Rutland wrote:
quoted
On Fri, Feb 14, 2014 at 01:00:01AM +0000, Laurent Pinchart wrote:
quoted
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source
device.
+  - clock-event-rating: rating of the timer as a clock event
device.
This feels like a leak of Linux internals. Why do you need this?
You're right, it is. The clock source and clock event ratings are
currently configured through platform data, I'll need to find a way
to compute them in the driver instead.
That would be very good!
Any pointer would be appreciated :-) How did you compute the various
ratings used in platform data all over the place ?
Historically we used the rating to select between CMT and TMU. For
clock sources I suppose you also have the jiffy rating to consider.
And for the SMP parts we have ARM IP for TWD and arch timers that have
their ratings too. So you need to check all the timers on a particular
system and consider what you want to have operating by default. The
ARM IP timers should be preferred if available. For clock sources the
rule is probably the higher resolution the better.
quoted
quoted
quoted
There's still one piece of Linux-specific data I need though, as I
need to specify for each channel whether to use it as a clock source
device, a clock event device, both of them or none. That's
configuration information that needs to be provided somehow.
I think you can decide clock source or clock event assignment based on
number of channels available. If you have only a single channel then
both clock event and clock source need to be supported. Otherwise use
one channel for clock source and the rest for clock events.
That won't match the current situation. Look at CMT0 in r8a7790 for
instance. There's two hardware channels available, and we only use the
first one, for clock events only.
You are correct. The reason for that is that the CMT driver today is
optimized for combined clock event and clock source operation.

Historically the hardware it initially was written for (sh-mobile on
the SH arch) only had a single timer channel so combined operation was
required for tickless to work. But since you're asking how to allocate
channels then I propose checking numbers of channels available and go
from there. With that the r8a7790 support can only get better. =)
quoted
quoted
This is probably out of scope for this DT conversion, but it would be
neat if you somehow could specify the CPU affinity for a channel to
tie a clock event to an individual CPU core. This would make a a per-
cpu timer unless I'm mistaken. But that's more of a software policy
than anything else.
Yes, that's a configuration that needs to be specified somewhere. I
don't know where though.
As long as you have per-channel interrupts described in DT you can
probably handle this in a generic way in the driver.
But how do we decide whether to use a single timer channel or one channel
per CPU ? Will the kernel use one clock event device per CPU
automatically ? I have to confess I have no idea how this works.
I guess that's the tricky bit about timer support, it is a mix of
hardware description and software configuration. So it sounds to me
that we need some kind of software configuration interface. But it can
probably be considered when/if we add such kind of support to the
driver. Probably out of scope for now.

Regardless it seems to me that the hardware description in DT doesn't
need to care about this.
I'll revisit that later. Per-CPU timers is not a high priority for now, so 
I'll just return -EAGAIN :-)

Nonetheless, specifying which timer channel to use as a clock source and which 
channel to use as a clock event device might need to be specified in DT (or 
somewhere else, but I'm not sure what other options we have here).

-- 
Regards,

Laurent Pinchart

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Magnus Damm <magnus.damm@gmail.com>
Date: 2014-02-18 00:51:34

Hi Laurent,

On Tue, Feb 18, 2014 at 6:43 AM, Laurent Pinchart
[off-list ref] wrote:
Hi Magnus,

On Monday 17 February 2014 10:48:55 Magnus Damm wrote:
quoted
On Mon, Feb 17, 2014 at 10:45 AM, Laurent Pinchart wrote:
quoted
On Saturday 15 February 2014 02:22:00 Magnus Damm wrote:
quoted
On Sat, Feb 15, 2014 at 1:12 AM, Laurent Pinchart wrote:
quoted
On Saturday 15 February 2014 01:01:30 Magnus Damm wrote:
quoted
On Sat, Feb 15, 2014 at 12:53 AM, Laurent Pinchart wrote:
quoted
On Friday 14 February 2014 10:58:22 Mark Rutland wrote:
quoted
On Fri, Feb 14, 2014 at 01:00:01AM +0000, Laurent Pinchart wrote:
quoted
+Channels Optional Properties:
+
+  - clock-source-rating: rating of the timer as a clock source
device.
+  - clock-event-rating: rating of the timer as a clock event
device.
This feels like a leak of Linux internals. Why do you need this?
You're right, it is. The clock source and clock event ratings are
currently configured through platform data, I'll need to find a way
to compute them in the driver instead.
That would be very good!
Any pointer would be appreciated :-) How did you compute the various
ratings used in platform data all over the place ?
Historically we used the rating to select between CMT and TMU. For
clock sources I suppose you also have the jiffy rating to consider.
And for the SMP parts we have ARM IP for TWD and arch timers that have
their ratings too. So you need to check all the timers on a particular
system and consider what you want to have operating by default. The
ARM IP timers should be preferred if available. For clock sources the
rule is probably the higher resolution the better.
quoted
quoted
quoted
There's still one piece of Linux-specific data I need though, as I
need to specify for each channel whether to use it as a clock source
device, a clock event device, both of them or none. That's
configuration information that needs to be provided somehow.
I think you can decide clock source or clock event assignment based on
number of channels available. If you have only a single channel then
both clock event and clock source need to be supported. Otherwise use
one channel for clock source and the rest for clock events.
That won't match the current situation. Look at CMT0 in r8a7790 for
instance. There's two hardware channels available, and we only use the
first one, for clock events only.
You are correct. The reason for that is that the CMT driver today is
optimized for combined clock event and clock source operation.

Historically the hardware it initially was written for (sh-mobile on
the SH arch) only had a single timer channel so combined operation was
required for tickless to work. But since you're asking how to allocate
channels then I propose checking numbers of channels available and go
from there. With that the r8a7790 support can only get better. =)
quoted
quoted
This is probably out of scope for this DT conversion, but it would be
neat if you somehow could specify the CPU affinity for a channel to
tie a clock event to an individual CPU core. This would make a a per-
cpu timer unless I'm mistaken. But that's more of a software policy
than anything else.
Yes, that's a configuration that needs to be specified somewhere. I
don't know where though.
As long as you have per-channel interrupts described in DT you can
probably handle this in a generic way in the driver.
But how do we decide whether to use a single timer channel or one channel
per CPU ? Will the kernel use one clock event device per CPU
automatically ? I have to confess I have no idea how this works.
I guess that's the tricky bit about timer support, it is a mix of
hardware description and software configuration. So it sounds to me
that we need some kind of software configuration interface. But it can
probably be considered when/if we add such kind of support to the
driver. Probably out of scope for now.

Regardless it seems to me that the hardware description in DT doesn't
need to care about this.
I'll revisit that later. Per-CPU timers is not a high priority for now, so
I'll just return -EAGAIN :-)
Thanks, that's fine.
Nonetheless, specifying which timer channel to use as a clock source and which
channel to use as a clock event device might need to be specified in DT (or
somewhere else, but I'm not sure what other options we have here).
I disagree about the need for specifying clock source or clock event
channel in DT.  Since per-cpu timers is out of scope for now then why
don't we simply just let the driver automatically allocate the during
run-time?

In case one CMT channel exists:
Use that for both clock source and clock event.

In case more than one CMT channel exists:
Use one separate channel for clock source and one separate channel for
clock event.

That would cover our existing use case, no?

Thanks,

/ magnus

Re: [PATCH 23/27] clocksource: sh_cmt: Add DT support

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: 2014-02-18 11:44:36

Hi Magnus,

On Tuesday 18 February 2014 09:51:30 Magnus Damm wrote:
On Tue, Feb 18, 2014 at 6:43 AM, Laurent Pinchart wrote:
quoted
On Monday 17 February 2014 10:48:55 Magnus Damm wrote:
quoted
On Mon, Feb 17, 2014 at 10:45 AM, Laurent Pinchart wrote:
quoted
On Saturday 15 February 2014 02:22:00 Magnus Damm wrote:
quoted
On Sat, Feb 15, 2014 at 1:12 AM, Laurent Pinchart wrote:
quoted
On Saturday 15 February 2014 01:01:30 Magnus Damm wrote:
quoted
On Sat, Feb 15, 2014 at 12:53 AM, Laurent Pinchart wrote:
[snip]
quoted
quoted
quoted
quoted
quoted
quoted
quoted
There's still one piece of Linux-specific data I need though, as
I need to specify for each channel whether to use it as a clock
source device, a clock event device, both of them or none. That's
configuration information that needs to be provided somehow.
I think you can decide clock source or clock event assignment based
on number of channels available. If you have only a single channel
then both clock event and clock source need to be supported.
Otherwise use one channel for clock source and the rest for clock
events.
That won't match the current situation. Look at CMT0 in r8a7790 for
instance. There's two hardware channels available, and we only use
the first one, for clock events only.
You are correct. The reason for that is that the CMT driver today is
optimized for combined clock event and clock source operation.

Historically the hardware it initially was written for (sh-mobile on
the SH arch) only had a single timer channel so combined operation was
required for tickless to work. But since you're asking how to allocate
channels then I propose checking numbers of channels available and go
from there. With that the r8a7790 support can only get better. =)
[snip]
quoted
Nonetheless, specifying which timer channel to use as a clock source and
which channel to use as a clock event device might need to be specified
in DT (or somewhere else, but I'm not sure what other options we have
here).
I disagree about the need for specifying clock source or clock event channel
in DT.  Since per-cpu timers is out of scope for now then why don't we
simply just let the driver automatically allocate the during run-time?

In case one CMT channel exists:
Use that for both clock source and clock event.

In case more than one CMT channel exists:
Use one separate channel for clock source and one separate channel for clock
event.

That would cover our existing use case, no?
One of the issues with that approach is that the decision on what to use a 
channel for will be taken locally from a timer point of view, without a global 
system-wide view. When more than one timer is available for a given platform 
(several CMT instances for instance, or CMT + TMU) the driver will decide on 
how to configure each instance without taking the other timers into account. 
Beside leading to creating more clock sources and clock event devices than 
today (is that a problem ?), couldn't it also lead to taking sub-optimal 
decisions ?

You also mentioned that only a subset of channels have the ability to run 
during sleep states. I suppose this needs to be taken into account as well. 
Could you please elaborate on our requirements in that area ?

-- 
Regards,

Laurent Pinchart
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help