linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [GIT PULL] clockevents: new material for 3.16
@ 2014-05-23 10:22 Daniel Lezcano
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
       [not found] ` <20140526194512.032c6630@canb.auug.org.au>
  0 siblings, 2 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:22 UTC (permalink / raw)
  To: linux-arm-kernel


Hi Thomas, Ingo,

this time we have a big number of changes in the clockevents.

There is a branch shared between Simon and I with two merges. The first 
merge was to pull the cmt,mtu changes from Laurent into the 
clockevents/cmt-mtu2-tmu-cleanups branch. Then this one has been merged 
in the clockevents/3.16. A bit later, a new fix on top of these changes 
has been provided and applied to clockevents/cmt-mtu2-tmu-cleanups with 
a second merge to clockevents/3.16.

clockevents/cmt-mtu2-tmu-cleanups will stay there until the 3.16 is 
released.

This pull request contains the following changes:

  * Laurent Pinchart did a lot of modifications to prepare the DT 
support. These modifications include a lot of cleanup (structure 
renaming, preparation to support multiple channel, kzalloc usage, ...) 
and then finishes to drop the old code to the new one.

  * Jingoo Han removed the dev_err when an allocation fails because this 
error is already given by the mm subsystems.
	* http://patchwork.ozlabs.org/patch/324158/
         * [conflict resolved] kmalloc => kzalloc changes with cmt,tmu, 
mtu cleanups from Laurent Pinchard

  * Matthew Leach added the ARM global timer with vexpress, enabled the 
ARM global timer with the A5 and added the definition in the DT. He also 
fixed a invalid check when looking for an usable ARM global timer for A9

  * Maxime Ripard added the support for AllWinner A31 for sun4i and made 
the timer reset optional through the DT

  * Stephen Boyd used the msm timer for the udelay

  * Uwe Kleine-K?nig fixed the non-standard 'compatible' binding for efm32

  * Xiubo Li clarified the types for the clocksource_mmio_read* and 
added a new Flextimer Module (FTM) with its bindings

  * Yang Wei added the 'notrace' attribute to 'read_sched_clock' for the 
dw_apb_timer

The following changes since commit 2779ac167b1a1bf8153dca9f3a141c6148c6b89f:

   timer_stats/doc: Fix /proc/timer_stats documentation (2014-05-04 
20:46:32 +0200)

are available in the git repository at:

   git://git.linaro.org/people/daniel.lezcano/linux.git clockevents/3.16

for you to fetch changes up to 2529c3a330797000d699d70c9a65b8525c6652de:

   clocksource: Add Freescale FlexTimer Module (FTM) timer support 
(2014-05-23 10:12:04 +0200)

----------------------------------------------------------------
Daniel Lezcano (3):
       Merge branch 'clockevents/cmt-mtu2-tmu-cleanups' into 
clockevents/3.16
       Merge remote-tracking branch 'tip/timers/core/timers/core' into 
clockevents/3.16
       Merge branch 'clockevents/cmt-mtu2-tmu-cleanups' into 
clockevents/3.16

Jingoo Han (4):
       clocksource: em_sti: Remove unnecessary OOM messages
       clocksource: sh_cmt: Remove unnecessary OOM messages
       clocksource: sh_mtu2: Remove unnecessary OOM messages
       clocksource: sh_tmu: Remove unnecessary OOM messages

Laurent Pinchart (53):
       clocksource: sh_cmt: Use request_irq() instead of setup_irq()
       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: Constify name argument to sh_cmt_register()
       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: Set cpumask to cpu_possible_mask
       clocksource: sh_cmt: Hardcode CMT clock event rating to 125
       clocksource: sh_cmt: Hardcode CMT clock source rating to 125
       clocksource: sh_cmt: Add support for multiple channels per device
       clocksource: sh_cmt: Rename clock to "fck" in the non-legacy case
       clocksource: sh_cmt: Remove FSF mail address from GPL notice
       clocksource: sh_cmt: Sort headers alphabetically
       clocksource: sh_cmt: Request IRQ for clock event device only
       clocksource: sh_tmu: Use request_irq() instead of setup_irq()
       clocksource: sh_tmu: Split channel fields from sh_tmu_priv
       clocksource: sh_tmu: Rename struct sh_tmu_priv to sh_tmu_device
       clocksource: sh_tmu: Split channel setup to separate function
       clocksource: sh_tmu: Constify name argument to sh_tmu_register()
       clocksource: sh_tmu: Add memory base to sh_tmu_channel structure
       clocksource: sh_tmu: Add index to struct sh_tmu_channel
       clocksource: sh_tmu: Replace kmalloc + memset with kzalloc
       clocksource: sh_tmu: Allocate channels dynamically
       clocksource: sh_tmu: Replace hardcoded register values with macros
       clocksource: sh_tmu: Hardcode TMU clock event and source ratings 
to 200
       clocksource: sh_tmu: Add support for multiple channels per device
       clocksource: sh_tmu: Rename clock to "fck" in the non-legacy case
       clocksource: sh_tmu: Remove FSF mail address from GPL notice
       clocksource: sh_tmu: Sort headers alphabetically
       clocksource: sh_mtu2: Use request_irq() instead of setup_irq()
       clocksource: sh_mtu2: Turn sh_mtu2_priv fields into local variables
       clocksource: sh_mtu2: Split channel fields from sh_mtu2_priv
       clocksource: sh_mtu2: Rename struct sh_mtu2_priv to sh_mtu2_device
       clocksource: sh_mtu2: Split channel setup to separate function
       clocksource: sh_mtu2: Constify name argument to sh_mtu2_register()
       clocksource: sh_mtu2: Add memory base to sh_mtu2_channel structure
       clocksource: sh_mtu2: Add index to struct sh_mtu2_channel
       clocksource: sh_mtu2: Replace kmalloc + memset with kzalloc
       clocksource: sh_mtu2: Allocate channels dynamically
       clocksource: sh_mtu2: Replace hardcoded register values with macros
       clocksource: sh_mtu2: Set cpumask to cpu_possible_mask
       clocksource: sh_mtu2: Hardcode MTU2 clock event rating to 200
       clocksource: sh_mtu2: Add support for multiple channels per device
       clocksource: sh_mtu2: Rename clock to "fck" in the non-legacy case
       clocksource: sh_mtu2: Remove FSF mail address from GPL notice
       clocksource: sh_mtu2: Sort headers alphabetically
       clocksource: sh_tmu: Fix channel IRQ retrieval in legacy case

Matthew Leach (4):
       clocksource: arm_global_timer: Only check for unusable timer on A9
       documentaion: DT: allow a A5 compatible string in global timer
       dts: ca5: add the global timer for the A5
       KConfig: Vexpress: build the ARM_GLOBAL_TIMER with vexpress platform

Maxime Ripard (2):
       clocksource: sun5i: Add support for reset controller
       ARM: sun6i: a31: Add support for the High Speed Timers

Stephen Boyd (1):
       clocksource: qcom: Implement read_current_timer for udelay

Uwe Kleine-K?nig (1):
       clocksource: efm32: use $vendor,$device scheme for compatible string

Xiubo Li (5):
       clocksource: Fix type confusion for clocksource_mmio_readX_Y
       clocksource: Fix clocksource_mmio_readX_down
       clocksource: ftm: Add FlexTimer Module (FTM) Timer devicetree 
Documentation
       ARM: dts: vf610: Add Freescale FlexTimer Module timer node.
       clocksource: Add Freescale FlexTimer Module (FTM) timer support

Yang Wei (1):
       clocksource: dw_apb_timer_of: Do not trace read_sched_clock

  .../devicetree/bindings/arm/global_timer.txt       |    7 +-
  .../bindings/timer/allwinner,sun5i-a13-hstimer.txt |    4 +
  ...efm32,timer.txt => energymicro,efm32-timer.txt} |    4 +-
  .../devicetree/bindings/timer/fsl,ftm-timer.txt    |   31 +
  arch/arm/boot/dts/sun6i-a31.dtsi                   |   11 +
  arch/arm/boot/dts/vexpress-v2p-ca5s.dts            |   10 +-
  arch/arm/boot/dts/vf610.dtsi                       |   13 +
  arch/arm/mach-vexpress/Kconfig                     |    1 +
  drivers/clocksource/Kconfig                        |    5 +
  drivers/clocksource/Makefile                       |    1 +
  drivers/clocksource/arm_global_timer.c             |    5 +-
  drivers/clocksource/dw_apb_timer_of.c              |    2 +-
  drivers/clocksource/em_sti.c                       |    4 +-
  drivers/clocksource/fsl_ftm_timer.c                |  367 ++++++++
  drivers/clocksource/mmio.c                         |    8 +-
  drivers/clocksource/qcom-timer.c                   |   13 +
  drivers/clocksource/sh_cmt.c                       |  958 
+++++++++++++-------
  drivers/clocksource/sh_mtu2.c                      |  490 +++++++---
  drivers/clocksource/sh_tmu.c                       |  543 ++++++-----
  drivers/clocksource/time-efm32.c                   |    3 +-
  drivers/clocksource/timer-sun5i.c                  |    6 +
  include/linux/sh_timer.h                           |    1 +
  22 files changed, 1785 insertions(+), 702 deletions(-)
  rename Documentation/devicetree/bindings/timer/{efm32,timer.txt => 
energymicro,efm32-timer.txt} (87%)
  create mode 100644 
Documentation/devicetree/bindings/timer/fsl,ftm-timer.txt
  create mode 100644 drivers/clocksource/fsl_ftm_timer.c


-- 
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq()
  2014-05-23 10:22 [GIT PULL] clockevents: new material for 3.16 Daniel Lezcano
@ 2014-05-23 10:30 ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 02/71] clocksource: sh_cmt: Split channel fields from sh_cmt_priv Daniel Lezcano
                     ` (69 more replies)
       [not found] ` <20140526194512.032c6630@canb.auug.org.au>
  1 sibling, 70 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

The driver claims it needs to register an interrupt handler too early
for request_irq(). This might have been true in the past, but the only
meaningful difference between request_irq() and setup_irq() today is an
additional kzalloc() call in request_irq(). As the driver calls
kmalloc() itself we know that the slab allocator is available, we can
thus switch to request_irq().

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c |   10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 0b1836a..a3103b8 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -728,12 +728,6 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 		goto err1;
 	}
 
-	/* 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;
-
 	/* get hold of clock */
 	p->clk = clk_get(&p->pdev->dev, "cmt_fck");
 	if (IS_ERR(p->clk)) {
@@ -786,7 +780,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 	}
 	p->cs_enabled = false;
 
-	ret = setup_irq(irq, &p->irqaction);
+	ret = request_irq(irq, sh_cmt_interrupt,
+			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
+			  dev_name(&p->pdev->dev), p);
 	if (ret) {
 		dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
 		goto err4;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 02/71] clocksource: sh_cmt: Split channel fields from sh_cmt_priv
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 03/71] clocksource: sh_cmt: Rename struct sh_cmt_priv to sh_cmt_device Daniel Lezcano
                     ` (68 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 |  385 ++++++++++++++++++++++--------------------
 1 file changed, 199 insertions(+), 186 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index a3103b8..351b3ca 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -35,15 +35,10 @@
 #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 irqaction irqaction;
-	struct platform_device *pdev;
+struct sh_cmt_priv;
+
+struct sh_cmt_channel {
+	struct sh_cmt_priv *cmt;
 
 	unsigned long flags;
 	unsigned long match_value;
@@ -55,6 +50,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 +123,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 +186,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 +245,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 +289,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 +318,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 +342,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 +353,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 +369,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 +508,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 +563,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 +611,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 +632,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 +676,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 +696,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;
@@ -763,26 +775,27 @@ 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 = request_irq(irq, sh_cmt_interrupt,
 			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
-			  dev_name(&p->pdev->dev), p);
+			  dev_name(&p->pdev->dev), ch);
 	if (ret) {
 		dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
 		goto err4;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 03/71] clocksource: sh_cmt: Rename struct sh_cmt_priv to sh_cmt_device
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 02/71] clocksource: sh_cmt: Split channel fields from sh_cmt_priv Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 04/71] clocksource: sh_cmt: Split channel setup to separate function Daniel Lezcano
                     ` (67 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 351b3ca..604199a 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;
 
 	unsigned long flags;
 	unsigned long match_value;
@@ -52,7 +52,7 @@ struct sh_cmt_channel {
 	bool cs_enabled;
 };
 
-struct sh_cmt_priv {
+struct sh_cmt_device {
 	struct platform_device *pdev;
 
 	void __iomem *mapbase;
@@ -693,132 +693,132 @@ 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;
 	}
 
 	/* 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 = request_irq(irq, sh_cmt_interrupt,
 			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
-			  dev_name(&p->pdev->dev), ch);
+			  dev_name(&cmt->pdev->dev), ch);
 	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;
 
@@ -827,20 +827,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.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 04/71] clocksource: sh_cmt: Split channel setup to separate function
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 02/71] clocksource: sh_cmt: Split channel fields from sh_cmt_priv Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 03/71] clocksource: sh_cmt: Rename struct sh_cmt_priv to sh_cmt_device Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 05/71] clocksource: sh_cmt: Constify name argument to sh_cmt_register() Daniel Lezcano
                     ` (66 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 |   79 +++++++++++++++++++++++++-----------------
 1 file changed, 47 insertions(+), 32 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 604199a..26f73cf 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -693,12 +693,55 @@ 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;
+
+	irq = platform_get_irq(cmt->pdev, 0);
+	if (irq < 0) {
+		dev_err(&cmt->pdev->dev, "failed to get irq\n");
+		return irq;
+	}
+
+	if (cmt->width == (sizeof(ch->max_match_value) * 8))
+		ch->max_match_value = ~0;
+	else
+		ch->max_match_value = (1 << cmt->width) - 1;
+
+	ch->match_value = ch->max_match_value;
+	raw_spin_lock_init(&ch->lock);
+
+	ret = sh_cmt_register(ch, (char *)dev_name(&cmt->pdev->dev),
+			      cfg->clockevent_rating,
+			      cfg->clocksource_rating);
+	if (ret) {
+		dev_err(&cmt->pdev->dev, "registration failed\n");
+		return ret;
+	}
+	ch->cs_enabled = false;
+
+	ret = request_irq(irq, sh_cmt_interrupt,
+			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
+			  dev_name(&cmt->pdev->dev), ch);
+	if (ret) {
+		dev_err(&cmt->pdev->dev, "failed to request irq %d\n", irq);
+		return ret;
+	}
+
+	return 0;
+}
+
 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));
@@ -718,12 +761,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) {
@@ -775,31 +812,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 = request_irq(irq, sh_cmt_interrupt,
-			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
-			  dev_name(&cmt->pdev->dev), ch);
-	if (ret) {
-		dev_err(&cmt->pdev->dev, "failed to request irq %d\n", irq);
+	ret = sh_cmt_setup_channel(&cmt->channel, cmt);
+	if (ret < 0)
 		goto err4;
-	}
 
 	platform_set_drvdata(pdev, cmt);
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 05/71] clocksource: sh_cmt: Constify name argument to sh_cmt_register()
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (2 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 04/71] clocksource: sh_cmt: Split channel setup to separate function Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 06/71] clocksource: sh_cmt: Rename mapbase/mapbase_str to mapbase_ch/mapbase Daniel Lezcano
                     ` (65 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

The name argument is assigned to const structure fields only, constify
it.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 26f73cf..febd6bf 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -549,7 +549,7 @@ static void sh_cmt_clocksource_resume(struct clocksource *cs)
 }
 
 static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch,
-				       char *name, unsigned long rating)
+				       const char *name, unsigned long rating)
 {
 	struct clocksource *cs = &ch->cs;
 
@@ -660,7 +660,7 @@ static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
 }
 
 static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
-				       char *name, unsigned long rating)
+				       const char *name, unsigned long rating)
 {
 	struct clock_event_device *ced = &ch->ced;
 
@@ -680,7 +680,7 @@ static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
 	clockevents_register_device(ced);
 }
 
-static int sh_cmt_register(struct sh_cmt_channel *ch, char *name,
+static int sh_cmt_register(struct sh_cmt_channel *ch, const char *name,
 			   unsigned long clockevent_rating,
 			   unsigned long clocksource_rating)
 {
@@ -717,7 +717,7 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch,
 	ch->match_value = ch->max_match_value;
 	raw_spin_lock_init(&ch->lock);
 
-	ret = sh_cmt_register(ch, (char *)dev_name(&cmt->pdev->dev),
+	ret = sh_cmt_register(ch, dev_name(&cmt->pdev->dev),
 			      cfg->clockevent_rating,
 			      cfg->clocksource_rating);
 	if (ret) {
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 06/71] clocksource: sh_cmt: Rename mapbase/mapbase_str to mapbase_ch/mapbase
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (3 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 05/71] clocksource: sh_cmt: Constify name argument to sh_cmt_register() Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 07/71] clocksource: sh_cmt: Add memory base to sh_cmt_channel structure Daniel Lezcano
                     ` (64 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 febd6bf..eb93b88 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -55,8 +55,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;
@@ -125,41 +125,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,
@@ -761,18 +761,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;
 	}
@@ -824,9 +824,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.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 07/71] clocksource: sh_cmt: Add memory base to sh_cmt_channel structure
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (4 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 06/71] clocksource: sh_cmt: Rename mapbase/mapbase_str to mapbase_ch/mapbase Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 08/71] clocksource: sh_cmt: Add index to struct sh_cmt_channel Daniel Lezcano
                     ` (63 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 |   13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index eb93b88..4fcb05d 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -40,6 +40,8 @@ struct sh_cmt_device;
 struct sh_cmt_channel {
 	struct sh_cmt_device *cmt;
 
+	void __iomem *base;
+
 	unsigned long flags;
 	unsigned long match_value;
 	unsigned long next_match_value;
@@ -130,12 +132,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,
@@ -147,19 +149,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,
@@ -702,6 +704,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;
 
 	irq = platform_get_irq(cmt->pdev, 0);
 	if (irq < 0) {
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 08/71] clocksource: sh_cmt: Add index to struct sh_cmt_channel
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (5 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 07/71] clocksource: sh_cmt: Add memory base to sh_cmt_channel structure Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 09/71] clocksource: sh_cmt: Replace kmalloc + memset with kzalloc Daniel Lezcano
                     ` (62 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 |   37 ++++++++++++++++++++++++-------------
 1 file changed, 24 insertions(+), 13 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 4fcb05d..6b65621 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;
 
@@ -216,7 +217,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;
 	}
 
@@ -253,7 +255,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;
 	}
@@ -371,7 +374,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);
 }
@@ -379,7 +383,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);
@@ -565,7 +570,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);
@@ -614,12 +620,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:
@@ -678,7 +684,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);
 }
 
@@ -695,7 +702,7 @@ static int sh_cmt_register(struct sh_cmt_channel *ch, const 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;
@@ -705,10 +712,12 @@ 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;
 
 	irq = platform_get_irq(cmt->pdev, 0);
 	if (irq < 0) {
-		dev_err(&cmt->pdev->dev, "failed to get irq\n");
+		dev_err(&cmt->pdev->dev, "ch%u: failed to get irq\n",
+			ch->index);
 		return irq;
 	}
 
@@ -724,7 +733,8 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch,
 			      cfg->clockevent_rating,
 			      cfg->clocksource_rating);
 	if (ret) {
-		dev_err(&cmt->pdev->dev, "registration failed\n");
+		dev_err(&cmt->pdev->dev, "ch%u: registration failed\n",
+			ch->index);
 		return ret;
 	}
 	ch->cs_enabled = false;
@@ -733,7 +743,8 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch,
 			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
 			  dev_name(&cmt->pdev->dev), ch);
 	if (ret) {
-		dev_err(&cmt->pdev->dev, "failed to request irq %d\n", irq);
+		dev_err(&cmt->pdev->dev, "ch%u: failed to request irq %d\n",
+			ch->index, irq);
 		return ret;
 	}
 
@@ -815,7 +826,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.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 09/71] clocksource: sh_cmt: Replace kmalloc + memset with kzalloc
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (6 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 08/71] clocksource: sh_cmt: Add index to struct sh_cmt_channel Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 10/71] clocksource: sh_cmt: Allocate channels dynamically Daniel Lezcano
                     ` (61 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 6b65621..0779bf1 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -672,8 +672,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;
@@ -709,7 +707,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;
@@ -758,7 +755,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) {
@@ -861,7 +857,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.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 10/71] clocksource: sh_cmt: Allocate channels dynamically
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (7 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 09/71] clocksource: sh_cmt: Replace kmalloc + memset with kzalloc Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 11/71] clocksource: sh_cmt: Split static information from sh_cmt_device Daniel Lezcano
                     ` (60 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 0779bf1..f94db32 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -62,7 +62,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;
@@ -822,7 +823,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;
 
@@ -830,6 +839,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.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 11/71] clocksource: sh_cmt: Split static information from sh_cmt_device
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (8 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 10/71] clocksource: sh_cmt: Allocate channels dynamically Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 12/71] clocksource: sh_cmt: Replace hardcoded register values with macros Daniel Lezcano
                     ` (59 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 f94db32..879b8c2 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;
@@ -58,49 +104,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));
@@ -123,47 +136,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,
@@ -172,7 +238,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 {
@@ -180,7 +246,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)));
 
@@ -227,7 +293,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 {
@@ -405,7 +471,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
@@ -719,10 +786,10 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 		return irq;
 	}
 
-	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);
@@ -800,28 +867,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.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 12/71] clocksource: sh_cmt: Replace hardcoded register values with macros
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (9 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 11/71] clocksource: sh_cmt: Split static information from sh_cmt_device Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 13/71] clocksource: sh_cmt: Set cpumask to cpu_possible_mask Daniel Lezcano
                     ` (58 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 879b8c2..ce00baa 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -114,6 +114,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));
@@ -140,8 +168,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,
@@ -150,8 +178,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,
@@ -160,8 +188,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,
@@ -170,8 +198,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,
@@ -180,8 +208,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,
@@ -295,10 +323,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.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 13/71] clocksource: sh_cmt: Set cpumask to cpu_possible_mask
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (10 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 12/71] clocksource: sh_cmt: Replace hardcoded register values with macros Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 14/71] clocksource: sh_cmt: Hardcode CMT clock event rating to 125 Daniel Lezcano
                     ` (57 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

The CMT is a global timer not restricted to a single CPU. It has a lower
rating than the TMU or ARM architected timer, but is still useful on
systems where the other timers are stopped during CPU sleep.

When multiple timers are available the timers core selects which timer
to use based on timer ratings.

On SMP systems where timer broadcasting is required, one dummy timer is
instantiated per CPU with a rating of 100. On those systems the CMT
timer has a rating of 80, which makes the dummy timer selected by
default on all CPUs. The CMT is then available, and will be used as a
broadcast timer.

On UP systems no dummy timer is instantiated. The CMT timer has a rating
of 125 on those systems and is used directly as a clock event device for
CPU0 without broadcasting.

The CMT rating shouldn't depend on whether we boot a UP or SMP system.
We can't raise the CMT rating to 125 on SMP systems. This would select
CMT as the clock event device for CPU0 as its rating is higher than the
dummy timer rating, and would leave the system without a broadcast
timer. We could instead lower the rating to 80 on all systems, but that
wouldn't reflect reality as ratings between 1 and 99 are documented as
"unfit for real use".

We should raise the rating above 99 and still have the CMT selected as a
broadcast timer. This can be done by changing the cpumask from
cpumask_of(0) to cpu_possible_mask. In that case the timer selection
logic will prefer the previously probed and already selected dummy timer
for all CPUs based on the fact that already selected per-cpu timers are
preferred over new global timers, regardless of their respective
ratings. This also better reflects reality, as the CMT is not tied to
the boot CPU.

Ideally the timer selection logic should realize that the CMT needs to
be used as a broadcast timer on SMP systems as no other broadcast timer
is available, regardless of the cpumask and rating.

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 ce00baa..926abe2 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -776,7 +776,7 @@ static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
 	ced->features = CLOCK_EVT_FEAT_PERIODIC;
 	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
 	ced->rating = rating;
-	ced->cpumask = cpumask_of(0);
+	ced->cpumask = cpu_possible_mask;
 	ced->set_next_event = sh_cmt_clock_event_next;
 	ced->set_mode = sh_cmt_clock_event_mode;
 	ced->suspend = sh_cmt_clock_event_suspend;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 14/71] clocksource: sh_cmt: Hardcode CMT clock event rating to 125
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (11 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 13/71] clocksource: sh_cmt: Set cpumask to cpu_possible_mask Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 15/71] clocksource: sh_cmt: Hardcode CMT clock source " Daniel Lezcano
                     ` (56 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

All boards use or should use a clock event rating of 125 for the CMT,
hardcode it in the driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c |   13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 926abe2..75b1f83 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -768,14 +768,14 @@ static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
 }
 
 static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
-				       const char *name, unsigned long rating)
+				       const char *name)
 {
 	struct clock_event_device *ced = &ch->ced;
 
 	ced->name = name;
 	ced->features = CLOCK_EVT_FEAT_PERIODIC;
 	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
-	ced->rating = rating;
+	ced->rating = 125;
 	ced->cpumask = cpu_possible_mask;
 	ced->set_next_event = sh_cmt_clock_event_next;
 	ced->set_mode = sh_cmt_clock_event_mode;
@@ -788,11 +788,10 @@ static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
 }
 
 static int sh_cmt_register(struct sh_cmt_channel *ch, const char *name,
-			   unsigned long clockevent_rating,
-			   unsigned long clocksource_rating)
+			   bool clockevent, unsigned long clocksource_rating)
 {
-	if (clockevent_rating)
-		sh_cmt_register_clockevent(ch, name, clockevent_rating);
+	if (clockevent)
+		sh_cmt_register_clockevent(ch, name);
 
 	if (clocksource_rating)
 		sh_cmt_register_clocksource(ch, name, clocksource_rating);
@@ -827,7 +826,7 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 	raw_spin_lock_init(&ch->lock);
 
 	ret = sh_cmt_register(ch, dev_name(&cmt->pdev->dev),
-			      cfg->clockevent_rating,
+			      cfg->clockevent_rating != 0,
 			      cfg->clocksource_rating);
 	if (ret) {
 		dev_err(&cmt->pdev->dev, "ch%u: registration failed\n",
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 15/71] clocksource: sh_cmt: Hardcode CMT clock source rating to 125
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (12 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 14/71] clocksource: sh_cmt: Hardcode CMT clock event rating to 125 Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 16/71] clocksource: sh_cmt: Add support for multiple channels per device Daniel Lezcano
                     ` (55 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

All boards use or should use a clock source rating of 125 for the CMT,
hardcode it in the driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 75b1f83..c753efc 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -656,12 +656,12 @@ static void sh_cmt_clocksource_resume(struct clocksource *cs)
 }
 
 static int sh_cmt_register_clocksource(struct sh_cmt_channel *ch,
-				       const char *name, unsigned long rating)
+				       const char *name)
 {
 	struct clocksource *cs = &ch->cs;
 
 	cs->name = name;
-	cs->rating = rating;
+	cs->rating = 125;
 	cs->read = sh_cmt_clocksource_read;
 	cs->enable = sh_cmt_clocksource_enable;
 	cs->disable = sh_cmt_clocksource_disable;
@@ -788,13 +788,13 @@ static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
 }
 
 static int sh_cmt_register(struct sh_cmt_channel *ch, const char *name,
-			   bool clockevent, unsigned long clocksource_rating)
+			   bool clockevent, bool clocksource)
 {
 	if (clockevent)
 		sh_cmt_register_clockevent(ch, name);
 
-	if (clocksource_rating)
-		sh_cmt_register_clocksource(ch, name, clocksource_rating);
+	if (clocksource)
+		sh_cmt_register_clocksource(ch, name);
 
 	return 0;
 }
@@ -827,7 +827,7 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 
 	ret = sh_cmt_register(ch, dev_name(&cmt->pdev->dev),
 			      cfg->clockevent_rating != 0,
-			      cfg->clocksource_rating);
+			      cfg->clocksource_rating != 0);
 	if (ret) {
 		dev_err(&cmt->pdev->dev, "ch%u: registration failed\n",
 			ch->index);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 16/71] clocksource: sh_cmt: Add support for multiple channels per device
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (13 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 15/71] clocksource: sh_cmt: Hardcode CMT clock source " Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 17/71] clocksource: sh_cmt: Rename clock to "fck" in the non-legacy case Daniel Lezcano
                     ` (54 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 |  304 ++++++++++++++++++++++++++++++++----------
 include/linux/sh_timer.h     |    1 +
 2 files changed, 237 insertions(+), 68 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index c753efc..1efe7d6 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,10 +94,14 @@ 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;
 
+	unsigned int timer_bit;
 	unsigned long flags;
 	unsigned long match_value;
 	unsigned long next_match_value;
@@ -105,6 +118,7 @@ struct sh_cmt_device {
 	struct platform_device *pdev;
 
 	const struct sh_cmt_info *info;
+	bool legacy;
 
 	void __iomem *mapbase_ch;
 	void __iomem *mapbase;
@@ -112,6 +126,9 @@ struct sh_cmt_device {
 
 	struct sh_cmt_channel *channels;
 	unsigned int num_channels;
+
+	bool has_clockevent;
+	bool has_clocksource;
 };
 
 #define SH_CMT16_CMCSR_CMF		(1 << 7)
@@ -223,41 +240,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,
@@ -286,7 +309,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 */
@@ -294,9 +316,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);
@@ -790,27 +812,72 @@ static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
 static int sh_cmt_register(struct sh_cmt_channel *ch, const char *name,
 			   bool clockevent, bool clocksource)
 {
-	if (clockevent)
+	if (clockevent) {
+		ch->cmt->has_clockevent = true;
 		sh_cmt_register_clockevent(ch, name);
+	}
 
-	if (clocksource)
+	if (clocksource) {
+		ch->cmt->has_clocksource = true;
 		sh_cmt_register_clocksource(ch, name);
+	}
 
 	return 0;
 }
 
 static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
-				struct sh_cmt_device *cmt)
+				unsigned int hwidx, bool clockevent,
+				bool clocksource, struct sh_cmt_device *cmt)
 {
-	struct sh_timer_config *cfg = cmt->pdev->dev.platform_data;
 	int irq;
 	int ret;
 
+	/* Skip unused channels. */
+	if (!clockevent && !clocksource)
+		return 0;
+
 	ch->cmt = cmt;
-	ch->base = cmt->mapbase_ch;
 	ch->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;
+		}
+	}
+
+	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, 0);
 	if (irq < 0) {
 		dev_err(&cmt->pdev->dev, "ch%u: failed to get irq\n",
 			ch->index);
@@ -825,9 +892,15 @@ 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 (cmt->legacy) {
+		ch->timer_bit = ch->hwidx;
+	} else {
+		ch->timer_bit = cmt->info->model == SH_CMT_48BIT_GEN2
+			      ? 0 : ch->hwidx;
+	}
+
 	ret = sh_cmt_register(ch, dev_name(&cmt->pdev->dev),
-			      cfg->clockevent_rating != 0,
-			      cfg->clocksource_rating != 0);
+			      clockevent, clocksource);
 	if (ret) {
 		dev_err(&cmt->pdev->dev, "ch%u: registration failed\n",
 			ch->index);
@@ -847,97 +920,180 @@ 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;
+	unsigned int hw_channels;
+	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;
+		hw_channels = 0;
+	} else {
+		cmt->num_channels = hweight8(cfg->channels_mask);
+		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, cfg->timer_bit,
+					   cfg->clockevent_rating != 0,
+					   cfg->clocksource_rating != 0, cmt);
+		if (ret < 0)
+			goto err_unmap;
+	} else {
+		unsigned int mask = hw_channels;
+		unsigned int i;
 
-	ret = sh_cmt_setup_channel(&cmt->channels[0], cfg->timer_bit, cmt);
-	if (ret < 0)
-		goto err4;
+		/*
+		 * Use the first channel as a clock event device and the second
+		 * channel as a clock source. If only one channel is available
+		 * use it for both.
+		 */
+		for (i = 0; i < cmt->num_channels; ++i) {
+			unsigned int hwidx = ffs(mask) - 1;
+			bool clocksource = i == 1 || cmt->num_channels == 1;
+			bool clockevent = i == 0;
+
+			ret = sh_cmt_setup_channel(&cmt->channels[i], i, hwidx,
+						   clockevent, clocksource,
+						   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)) {
@@ -966,7 +1122,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);
@@ -979,12 +1135,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..8e1e036 100644
--- a/include/linux/sh_timer.h
+++ b/include/linux/sh_timer.h
@@ -7,6 +7,7 @@ struct sh_timer_config {
 	int timer_bit;
 	unsigned long clockevent_rating;
 	unsigned long clocksource_rating;
+	unsigned int channels_mask;
 };
 
 #endif /* __SH_TIMER_H__ */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 17/71] clocksource: sh_cmt: Rename clock to "fck" in the non-legacy case
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (14 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 16/71] clocksource: sh_cmt: Add support for multiple channels per device Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 18/71] clocksource: sh_cmt: Remove FSF mail address from GPL notice Daniel Lezcano
                     ` (53 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 connection ID of "fck" in the non-legacy
platform data case. Clock lookup entries will be renamed to use the
device ID as well as the connection ID as platforms get moved to new
platform data. The legacy code will eventually be dropped, leaving us
with device ID based clock lookup, 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 1efe7d6..a5ea9ae 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -1007,7 +1007,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" : "fck");
 	if (IS_ERR(cmt->clk)) {
 		dev_err(&cmt->pdev->dev, "cannot get clock\n");
 		return PTR_ERR(cmt->clk);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 18/71] clocksource: sh_cmt: Remove FSF mail address from GPL notice
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (15 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 17/71] clocksource: sh_cmt: Rename clock to "fck" in the non-legacy case Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:30   ` [PATCH 19/71] clocksource: sh_cmt: Sort headers alphabetically Daniel Lezcano
                     ` (52 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 a5ea9ae..399e952 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.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 19/71] clocksource: sh_cmt: Sort headers alphabetically
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (16 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 18/71] clocksource: sh_cmt: Remove FSF mail address from GPL notice Daniel Lezcano
@ 2014-05-23 10:30   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 20/71] clocksource: sh_cmt: Request IRQ for clock event device only Daniel Lezcano
                     ` (51 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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 399e952..9f215e7 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.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 20/71] clocksource: sh_cmt: Request IRQ for clock event device only
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (17 preceding siblings ...)
  2014-05-23 10:30   ` [PATCH 19/71] clocksource: sh_cmt: Sort headers alphabetically Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 21/71] clocksource: sh_tmu: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (50 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Clock sources don't need an IRQ, request the IRQ only for channels used
as clock event devices.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_cmt.c |   51 ++++++++++++++++++++++--------------------
 1 file changed, 27 insertions(+), 24 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 9f215e7..bc8d025 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -785,10 +785,28 @@ static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
 	pm_genpd_syscore_poweron(&ch->cmt->pdev->dev);
 }
 
-static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
-				       const char *name)
+static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
+				      const char *name)
 {
 	struct clock_event_device *ced = &ch->ced;
+	int irq;
+	int ret;
+
+	irq = platform_get_irq(ch->cmt->pdev, ch->cmt->legacy ? 0 : ch->index);
+	if (irq < 0) {
+		dev_err(&ch->cmt->pdev->dev, "ch%u: failed to get irq\n",
+			ch->index);
+		return irq;
+	}
+
+	ret = request_irq(irq, sh_cmt_interrupt,
+			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
+			  dev_name(&ch->cmt->pdev->dev), ch);
+	if (ret) {
+		dev_err(&ch->cmt->pdev->dev, "ch%u: failed to request irq %d\n",
+			ch->index, irq);
+		return ret;
+	}
 
 	ced->name = name;
 	ced->features = CLOCK_EVT_FEAT_PERIODIC;
@@ -803,14 +821,20 @@ static void sh_cmt_register_clockevent(struct sh_cmt_channel *ch,
 	dev_info(&ch->cmt->pdev->dev, "ch%u: used for clock events\n",
 		 ch->index);
 	clockevents_register_device(ced);
+
+	return 0;
 }
 
 static int sh_cmt_register(struct sh_cmt_channel *ch, const char *name,
 			   bool clockevent, bool clocksource)
 {
+	int ret;
+
 	if (clockevent) {
 		ch->cmt->has_clockevent = true;
-		sh_cmt_register_clockevent(ch, name);
+		ret = sh_cmt_register_clockevent(ch, name);
+		if (ret < 0)
+			return ret;
 	}
 
 	if (clocksource) {
@@ -825,7 +849,6 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 				unsigned int hwidx, bool clockevent,
 				bool clocksource, struct sh_cmt_device *cmt)
 {
-	int irq;
 	int ret;
 
 	/* Skip unused channels. */
@@ -869,17 +892,6 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 		}
 	}
 
-	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, "ch%u: failed to get irq\n",
-			ch->index);
-		return irq;
-	}
-
 	if (cmt->info->width == (sizeof(ch->max_match_value) * 8))
 		ch->max_match_value = ~0;
 	else
@@ -904,15 +916,6 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
 	}
 	ch->cs_enabled = false;
 
-	ret = request_irq(irq, sh_cmt_interrupt,
-			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
-			  dev_name(&cmt->pdev->dev), ch);
-	if (ret) {
-		dev_err(&cmt->pdev->dev, "ch%u: failed to request irq %d\n",
-			ch->index, irq);
-		return ret;
-	}
-
 	return 0;
 }
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 21/71] clocksource: sh_tmu: Use request_irq() instead of setup_irq()
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (18 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 20/71] clocksource: sh_cmt: Request IRQ for clock event device only Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 22/71] clocksource: sh_tmu: Split channel fields from sh_tmu_priv Daniel Lezcano
                     ` (49 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

The driver claims it needs to register an interrupt handler too early
for request_irq(). This might have been true in the past, but the only
meaningful difference between request_irq() and setup_irq() today is an
additional kzalloc() call in request_irq(). As the driver calls
kmalloc() itself we know that the slab allocator is available, we can
thus switch to request_irq().

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_tmu.c |   22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index ecd7b60..8613cc9 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -38,7 +38,7 @@
 struct sh_tmu_priv {
 	void __iomem *mapbase;
 	struct clk *clk;
-	struct irqaction irqaction;
+	int irq;
 	struct platform_device *pdev;
 	unsigned long rate;
 	unsigned long periodic;
@@ -401,10 +401,11 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
 
 	clockevents_config_and_register(ced, 1, 0x300, 0xffffffff);
 
-	ret = setup_irq(p->irqaction.irq, &p->irqaction);
+	ret = request_irq(p->irq, sh_tmu_interrupt,
+			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
+			  dev_name(&p->pdev->dev), p);
 	if (ret) {
-		dev_err(&p->pdev->dev, "failed to request irq %d\n",
-			p->irqaction.irq);
+		dev_err(&p->pdev->dev, "failed to request irq %d\n", p->irq);
 		return;
 	}
 }
@@ -425,7 +426,7 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
-	int irq, ret;
+	int ret;
 	ret = -ENXIO;
 
 	memset(p, 0, sizeof(*p));
@@ -444,8 +445,8 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 		goto err0;
 	}
 
-	irq = platform_get_irq(p->pdev, 0);
-	if (irq < 0) {
+	p->irq = platform_get_irq(p->pdev, 0);
+	if (p->irq < 0) {
 		dev_err(&p->pdev->dev, "failed to get irq\n");
 		goto err0;
 	}
@@ -457,13 +458,6 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 		goto err0;
 	}
 
-	/* setup data for setup_irq() (too early for request_irq()) */
-	p->irqaction.name = dev_name(&p->pdev->dev);
-	p->irqaction.handler = sh_tmu_interrupt;
-	p->irqaction.dev_id = p;
-	p->irqaction.irq = irq;
-	p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
-
 	/* get hold of clock */
 	p->clk = clk_get(&p->pdev->dev, "tmu_fck");
 	if (IS_ERR(p->clk)) {
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 22/71] clocksource: sh_tmu: Split channel fields from sh_tmu_priv
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (19 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 21/71] clocksource: sh_tmu: Use request_irq() instead of setup_irq() Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 23/71] clocksource: sh_tmu: Rename struct sh_tmu_priv to sh_tmu_device Daniel Lezcano
                     ` (48 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Create a new sh_tmu_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_tmu.c |  235 ++++++++++++++++++++++--------------------
 1 file changed, 125 insertions(+), 110 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 8613cc9..26457e1 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -35,11 +35,13 @@
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 
-struct sh_tmu_priv {
-	void __iomem *mapbase;
-	struct clk *clk;
+struct sh_tmu_priv;
+
+struct sh_tmu_channel {
+	struct sh_tmu_priv *tmu;
+
 	int irq;
-	struct platform_device *pdev;
+
 	unsigned long rate;
 	unsigned long periodic;
 	struct clock_event_device ced;
@@ -48,6 +50,15 @@ struct sh_tmu_priv {
 	unsigned int enable_count;
 };
 
+struct sh_tmu_priv {
+	struct platform_device *pdev;
+
+	void __iomem *mapbase;
+	struct clk *clk;
+
+	struct sh_tmu_channel channel;
+};
+
 static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
 
 #define TSTR -1 /* shared register */
@@ -55,10 +66,10 @@ static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
 #define TCNT 1 /* channel register */
 #define TCR 2 /* channel register */
 
-static inline unsigned long sh_tmu_read(struct sh_tmu_priv *p, int reg_nr)
+static inline unsigned long sh_tmu_read(struct sh_tmu_channel *ch, int reg_nr)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-	void __iomem *base = p->mapbase;
+	struct sh_timer_config *cfg = ch->tmu->pdev->dev.platform_data;
+	void __iomem *base = ch->tmu->mapbase;
 	unsigned long offs;
 
 	if (reg_nr == TSTR)
@@ -72,11 +83,11 @@ static inline unsigned long sh_tmu_read(struct sh_tmu_priv *p, int reg_nr)
 		return ioread32(base + offs);
 }
 
-static inline void sh_tmu_write(struct sh_tmu_priv *p, int reg_nr,
+static inline void sh_tmu_write(struct sh_tmu_channel *ch, int reg_nr,
 				unsigned long value)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-	void __iomem *base = p->mapbase;
+	struct sh_timer_config *cfg = ch->tmu->pdev->dev.platform_data;
+	void __iomem *base = ch->tmu->mapbase;
 	unsigned long offs;
 
 	if (reg_nr == TSTR) {
@@ -92,152 +103,152 @@ static inline void sh_tmu_write(struct sh_tmu_priv *p, int reg_nr,
 		iowrite32(value, base + offs);
 }
 
-static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
+static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+	struct sh_timer_config *cfg = ch->tmu->pdev->dev.platform_data;
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
 	raw_spin_lock_irqsave(&sh_tmu_lock, flags);
-	value = sh_tmu_read(p, TSTR);
+	value = sh_tmu_read(ch, TSTR);
 
 	if (start)
 		value |= 1 << cfg->timer_bit;
 	else
 		value &= ~(1 << cfg->timer_bit);
 
-	sh_tmu_write(p, TSTR, value);
+	sh_tmu_write(ch, TSTR, value);
 	raw_spin_unlock_irqrestore(&sh_tmu_lock, flags);
 }
 
-static int __sh_tmu_enable(struct sh_tmu_priv *p)
+static int __sh_tmu_enable(struct sh_tmu_channel *ch)
 {
 	int ret;
 
 	/* enable clock */
-	ret = clk_enable(p->clk);
+	ret = clk_enable(ch->tmu->clk);
 	if (ret) {
-		dev_err(&p->pdev->dev, "cannot enable clock\n");
+		dev_err(&ch->tmu->pdev->dev, "cannot enable clock\n");
 		return ret;
 	}
 
 	/* make sure channel is disabled */
-	sh_tmu_start_stop_ch(p, 0);
+	sh_tmu_start_stop_ch(ch, 0);
 
 	/* maximum timeout */
-	sh_tmu_write(p, TCOR, 0xffffffff);
-	sh_tmu_write(p, TCNT, 0xffffffff);
+	sh_tmu_write(ch, TCOR, 0xffffffff);
+	sh_tmu_write(ch, TCNT, 0xffffffff);
 
 	/* configure channel to parent clock / 4, irq off */
-	p->rate = clk_get_rate(p->clk) / 4;
-	sh_tmu_write(p, TCR, 0x0000);
+	ch->rate = clk_get_rate(ch->tmu->clk) / 4;
+	sh_tmu_write(ch, TCR, 0x0000);
 
 	/* enable channel */
-	sh_tmu_start_stop_ch(p, 1);
+	sh_tmu_start_stop_ch(ch, 1);
 
 	return 0;
 }
 
-static int sh_tmu_enable(struct sh_tmu_priv *p)
+static int sh_tmu_enable(struct sh_tmu_channel *ch)
 {
-	if (p->enable_count++ > 0)
+	if (ch->enable_count++ > 0)
 		return 0;
 
-	pm_runtime_get_sync(&p->pdev->dev);
-	dev_pm_syscore_device(&p->pdev->dev, true);
+	pm_runtime_get_sync(&ch->tmu->pdev->dev);
+	dev_pm_syscore_device(&ch->tmu->pdev->dev, true);
 
-	return __sh_tmu_enable(p);
+	return __sh_tmu_enable(ch);
 }
 
-static void __sh_tmu_disable(struct sh_tmu_priv *p)
+static void __sh_tmu_disable(struct sh_tmu_channel *ch)
 {
 	/* disable channel */
-	sh_tmu_start_stop_ch(p, 0);
+	sh_tmu_start_stop_ch(ch, 0);
 
 	/* disable interrupts in TMU block */
-	sh_tmu_write(p, TCR, 0x0000);
+	sh_tmu_write(ch, TCR, 0x0000);
 
 	/* stop clock */
-	clk_disable(p->clk);
+	clk_disable(ch->tmu->clk);
 }
 
-static void sh_tmu_disable(struct sh_tmu_priv *p)
+static void sh_tmu_disable(struct sh_tmu_channel *ch)
 {
-	if (WARN_ON(p->enable_count == 0))
+	if (WARN_ON(ch->enable_count == 0))
 		return;
 
-	if (--p->enable_count > 0)
+	if (--ch->enable_count > 0)
 		return;
 
-	__sh_tmu_disable(p);
+	__sh_tmu_disable(ch);
 
-	dev_pm_syscore_device(&p->pdev->dev, false);
-	pm_runtime_put(&p->pdev->dev);
+	dev_pm_syscore_device(&ch->tmu->pdev->dev, false);
+	pm_runtime_put(&ch->tmu->pdev->dev);
 }
 
-static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta,
+static void sh_tmu_set_next(struct sh_tmu_channel *ch, unsigned long delta,
 			    int periodic)
 {
 	/* stop timer */
-	sh_tmu_start_stop_ch(p, 0);
+	sh_tmu_start_stop_ch(ch, 0);
 
 	/* acknowledge interrupt */
-	sh_tmu_read(p, TCR);
+	sh_tmu_read(ch, TCR);
 
 	/* enable interrupt */
-	sh_tmu_write(p, TCR, 0x0020);
+	sh_tmu_write(ch, TCR, 0x0020);
 
 	/* reload delta value in case of periodic timer */
 	if (periodic)
-		sh_tmu_write(p, TCOR, delta);
+		sh_tmu_write(ch, TCOR, delta);
 	else
-		sh_tmu_write(p, TCOR, 0xffffffff);
+		sh_tmu_write(ch, TCOR, 0xffffffff);
 
-	sh_tmu_write(p, TCNT, delta);
+	sh_tmu_write(ch, TCNT, delta);
 
 	/* start timer */
-	sh_tmu_start_stop_ch(p, 1);
+	sh_tmu_start_stop_ch(ch, 1);
 }
 
 static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id)
 {
-	struct sh_tmu_priv *p = dev_id;
+	struct sh_tmu_channel *ch = dev_id;
 
 	/* disable or acknowledge interrupt */
-	if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT)
-		sh_tmu_write(p, TCR, 0x0000);
+	if (ch->ced.mode == CLOCK_EVT_MODE_ONESHOT)
+		sh_tmu_write(ch, TCR, 0x0000);
 	else
-		sh_tmu_write(p, TCR, 0x0020);
+		sh_tmu_write(ch, TCR, 0x0020);
 
 	/* notify clockevent layer */
-	p->ced.event_handler(&p->ced);
+	ch->ced.event_handler(&ch->ced);
 	return IRQ_HANDLED;
 }
 
-static struct sh_tmu_priv *cs_to_sh_tmu(struct clocksource *cs)
+static struct sh_tmu_channel *cs_to_sh_tmu(struct clocksource *cs)
 {
-	return container_of(cs, struct sh_tmu_priv, cs);
+	return container_of(cs, struct sh_tmu_channel, cs);
 }
 
 static cycle_t sh_tmu_clocksource_read(struct clocksource *cs)
 {
-	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+	struct sh_tmu_channel *ch = cs_to_sh_tmu(cs);
 
-	return sh_tmu_read(p, TCNT) ^ 0xffffffff;
+	return sh_tmu_read(ch, TCNT) ^ 0xffffffff;
 }
 
 static int sh_tmu_clocksource_enable(struct clocksource *cs)
 {
-	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+	struct sh_tmu_channel *ch = cs_to_sh_tmu(cs);
 	int ret;
 
-	if (WARN_ON(p->cs_enabled))
+	if (WARN_ON(ch->cs_enabled))
 		return 0;
 
-	ret = sh_tmu_enable(p);
+	ret = sh_tmu_enable(ch);
 	if (!ret) {
-		__clocksource_updatefreq_hz(cs, p->rate);
-		p->cs_enabled = true;
+		__clocksource_updatefreq_hz(cs, ch->rate);
+		ch->cs_enabled = true;
 	}
 
 	return ret;
@@ -245,45 +256,45 @@ static int sh_tmu_clocksource_enable(struct clocksource *cs)
 
 static void sh_tmu_clocksource_disable(struct clocksource *cs)
 {
-	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+	struct sh_tmu_channel *ch = cs_to_sh_tmu(cs);
 
-	if (WARN_ON(!p->cs_enabled))
+	if (WARN_ON(!ch->cs_enabled))
 		return;
 
-	sh_tmu_disable(p);
-	p->cs_enabled = false;
+	sh_tmu_disable(ch);
+	ch->cs_enabled = false;
 }
 
 static void sh_tmu_clocksource_suspend(struct clocksource *cs)
 {
-	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+	struct sh_tmu_channel *ch = cs_to_sh_tmu(cs);
 
-	if (!p->cs_enabled)
+	if (!ch->cs_enabled)
 		return;
 
-	if (--p->enable_count == 0) {
-		__sh_tmu_disable(p);
-		pm_genpd_syscore_poweroff(&p->pdev->dev);
+	if (--ch->enable_count == 0) {
+		__sh_tmu_disable(ch);
+		pm_genpd_syscore_poweroff(&ch->tmu->pdev->dev);
 	}
 }
 
 static void sh_tmu_clocksource_resume(struct clocksource *cs)
 {
-	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+	struct sh_tmu_channel *ch = cs_to_sh_tmu(cs);
 
-	if (!p->cs_enabled)
+	if (!ch->cs_enabled)
 		return;
 
-	if (p->enable_count++ == 0) {
-		pm_genpd_syscore_poweron(&p->pdev->dev);
-		__sh_tmu_enable(p);
+	if (ch->enable_count++ == 0) {
+		pm_genpd_syscore_poweron(&ch->tmu->pdev->dev);
+		__sh_tmu_enable(ch);
 	}
 }
 
-static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
+static int sh_tmu_register_clocksource(struct sh_tmu_channel *ch,
 				       char *name, unsigned long rating)
 {
-	struct clocksource *cs = &p->cs;
+	struct clocksource *cs = &ch->cs;
 
 	cs->name = name;
 	cs->rating = rating;
@@ -295,43 +306,43 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
 	cs->mask = CLOCKSOURCE_MASK(32);
 	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
 
-	dev_info(&p->pdev->dev, "used as clock source\n");
+	dev_info(&ch->tmu->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_tmu_priv *ced_to_sh_tmu(struct clock_event_device *ced)
+static struct sh_tmu_channel *ced_to_sh_tmu(struct clock_event_device *ced)
 {
-	return container_of(ced, struct sh_tmu_priv, ced);
+	return container_of(ced, struct sh_tmu_channel, ced);
 }
 
-static void sh_tmu_clock_event_start(struct sh_tmu_priv *p, int periodic)
+static void sh_tmu_clock_event_start(struct sh_tmu_channel *ch, int periodic)
 {
-	struct clock_event_device *ced = &p->ced;
+	struct clock_event_device *ced = &ch->ced;
 
-	sh_tmu_enable(p);
+	sh_tmu_enable(ch);
 
-	clockevents_config(ced, p->rate);
+	clockevents_config(ced, ch->rate);
 
 	if (periodic) {
-		p->periodic = (p->rate + HZ/2) / HZ;
-		sh_tmu_set_next(p, p->periodic, 1);
+		ch->periodic = (ch->rate + HZ/2) / HZ;
+		sh_tmu_set_next(ch, ch->periodic, 1);
 	}
 }
 
 static void sh_tmu_clock_event_mode(enum clock_event_mode mode,
 				    struct clock_event_device *ced)
 {
-	struct sh_tmu_priv *p = ced_to_sh_tmu(ced);
+	struct sh_tmu_channel *ch = ced_to_sh_tmu(ced);
 	int disabled = 0;
 
 	/* deal with old setting first */
 	switch (ced->mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 	case CLOCK_EVT_MODE_ONESHOT:
-		sh_tmu_disable(p);
+		sh_tmu_disable(ch);
 		disabled = 1;
 		break;
 	default:
@@ -340,16 +351,18 @@ static void sh_tmu_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_tmu_clock_event_start(p, 1);
+		dev_info(&ch->tmu->pdev->dev,
+			 "used for periodic clock events\n");
+		sh_tmu_clock_event_start(ch, 1);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
-		dev_info(&p->pdev->dev, "used for oneshot clock events\n");
-		sh_tmu_clock_event_start(p, 0);
+		dev_info(&ch->tmu->pdev->dev,
+			 "used for oneshot clock events\n");
+		sh_tmu_clock_event_start(ch, 0);
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
 		if (!disabled)
-			sh_tmu_disable(p);
+			sh_tmu_disable(ch);
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	default:
@@ -360,29 +373,29 @@ static void sh_tmu_clock_event_mode(enum clock_event_mode mode,
 static int sh_tmu_clock_event_next(unsigned long delta,
 				   struct clock_event_device *ced)
 {
-	struct sh_tmu_priv *p = ced_to_sh_tmu(ced);
+	struct sh_tmu_channel *ch = ced_to_sh_tmu(ced);
 
 	BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
 
 	/* program new delta value */
-	sh_tmu_set_next(p, delta, 0);
+	sh_tmu_set_next(ch, delta, 0);
 	return 0;
 }
 
 static void sh_tmu_clock_event_suspend(struct clock_event_device *ced)
 {
-	pm_genpd_syscore_poweroff(&ced_to_sh_tmu(ced)->pdev->dev);
+	pm_genpd_syscore_poweroff(&ced_to_sh_tmu(ced)->tmu->pdev->dev);
 }
 
 static void sh_tmu_clock_event_resume(struct clock_event_device *ced)
 {
-	pm_genpd_syscore_poweron(&ced_to_sh_tmu(ced)->pdev->dev);
+	pm_genpd_syscore_poweron(&ced_to_sh_tmu(ced)->tmu->pdev->dev);
 }
 
-static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
+static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
 				       char *name, unsigned long rating)
 {
-	struct clock_event_device *ced = &p->ced;
+	struct clock_event_device *ced = &ch->ced;
 	int ret;
 
 	memset(ced, 0, sizeof(*ced));
@@ -397,27 +410,28 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
 	ced->suspend = sh_tmu_clock_event_suspend;
 	ced->resume = sh_tmu_clock_event_resume;
 
-	dev_info(&p->pdev->dev, "used for clock events\n");
+	dev_info(&ch->tmu->pdev->dev, "used for clock events\n");
 
 	clockevents_config_and_register(ced, 1, 0x300, 0xffffffff);
 
-	ret = request_irq(p->irq, sh_tmu_interrupt,
+	ret = request_irq(ch->irq, sh_tmu_interrupt,
 			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
-			  dev_name(&p->pdev->dev), p);
+			  dev_name(&ch->tmu->pdev->dev), ch);
 	if (ret) {
-		dev_err(&p->pdev->dev, "failed to request irq %d\n", p->irq);
+		dev_err(&ch->tmu->pdev->dev, "failed to request irq %d\n",
+			ch->irq);
 		return;
 	}
 }
 
-static int sh_tmu_register(struct sh_tmu_priv *p, char *name,
+static int sh_tmu_register(struct sh_tmu_channel *ch, char *name,
 		    unsigned long clockevent_rating,
 		    unsigned long clocksource_rating)
 {
 	if (clockevent_rating)
-		sh_tmu_register_clockevent(p, name, clockevent_rating);
+		sh_tmu_register_clockevent(ch, name, clockevent_rating);
 	else if (clocksource_rating)
-		sh_tmu_register_clocksource(p, name, clocksource_rating);
+		sh_tmu_register_clocksource(ch, name, clocksource_rating);
 
 	return 0;
 }
@@ -445,8 +459,8 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 		goto err0;
 	}
 
-	p->irq = platform_get_irq(p->pdev, 0);
-	if (p->irq < 0) {
+	p->channel.irq = platform_get_irq(p->pdev, 0);
+	if (p->channel.irq < 0) {
 		dev_err(&p->pdev->dev, "failed to get irq\n");
 		goto err0;
 	}
@@ -470,10 +484,11 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 	if (ret < 0)
 		goto err2;
 
-	p->cs_enabled = false;
-	p->enable_count = 0;
+	p->channel.cs_enabled = false;
+	p->channel.enable_count = 0;
+	p->channel.tmu = p;
 
-	ret = sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
+	ret = sh_tmu_register(&p->channel, (char *)dev_name(&p->pdev->dev),
 			      cfg->clockevent_rating,
 			      cfg->clocksource_rating);
 	if (ret < 0)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 23/71] clocksource: sh_tmu: Rename struct sh_tmu_priv to sh_tmu_device
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (20 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 22/71] clocksource: sh_tmu: Split channel fields from sh_tmu_priv Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 24/71] clocksource: sh_tmu: Split channel setup to separate function Daniel Lezcano
                     ` (47 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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_tmu.c |   68 +++++++++++++++++++++---------------------
 1 file changed, 34 insertions(+), 34 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 26457e1..7013790 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -35,10 +35,10 @@
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 
-struct sh_tmu_priv;
+struct sh_tmu_device;
 
 struct sh_tmu_channel {
-	struct sh_tmu_priv *tmu;
+	struct sh_tmu_device *tmu;
 
 	int irq;
 
@@ -50,7 +50,7 @@ struct sh_tmu_channel {
 	unsigned int enable_count;
 };
 
-struct sh_tmu_priv {
+struct sh_tmu_device {
 	struct platform_device *pdev;
 
 	void __iomem *mapbase;
@@ -436,59 +436,59 @@ static int sh_tmu_register(struct sh_tmu_channel *ch, char *name,
 	return 0;
 }
 
-static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
+static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
 	int ret;
 	ret = -ENXIO;
 
-	memset(p, 0, sizeof(*p));
-	p->pdev = pdev;
+	memset(tmu, 0, sizeof(*tmu));
+	tmu->pdev = pdev;
 
 	if (!cfg) {
-		dev_err(&p->pdev->dev, "missing platform data\n");
+		dev_err(&tmu->pdev->dev, "missing platform data\n");
 		goto err0;
 	}
 
-	platform_set_drvdata(pdev, p);
+	platform_set_drvdata(pdev, tmu);
 
-	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource(tmu->pdev, IORESOURCE_MEM, 0);
 	if (!res) {
-		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
+		dev_err(&tmu->pdev->dev, "failed to get I/O memory\n");
 		goto err0;
 	}
 
-	p->channel.irq = platform_get_irq(p->pdev, 0);
-	if (p->channel.irq < 0) {
-		dev_err(&p->pdev->dev, "failed to get irq\n");
+	tmu->channel.irq = platform_get_irq(tmu->pdev, 0);
+	if (tmu->channel.irq < 0) {
+		dev_err(&tmu->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");
+	tmu->mapbase = ioremap_nocache(res->start, resource_size(res));
+	if (tmu->mapbase == NULL) {
+		dev_err(&tmu->pdev->dev, "failed to remap I/O memory\n");
 		goto err0;
 	}
 
 	/* get hold of clock */
-	p->clk = clk_get(&p->pdev->dev, "tmu_fck");
-	if (IS_ERR(p->clk)) {
-		dev_err(&p->pdev->dev, "cannot get clock\n");
-		ret = PTR_ERR(p->clk);
+	tmu->clk = clk_get(&tmu->pdev->dev, "tmu_fck");
+	if (IS_ERR(tmu->clk)) {
+		dev_err(&tmu->pdev->dev, "cannot get clock\n");
+		ret = PTR_ERR(tmu->clk);
 		goto err1;
 	}
 
-	ret = clk_prepare(p->clk);
+	ret = clk_prepare(tmu->clk);
 	if (ret < 0)
 		goto err2;
 
-	p->channel.cs_enabled = false;
-	p->channel.enable_count = 0;
-	p->channel.tmu = p;
+	tmu->channel.cs_enabled = false;
+	tmu->channel.enable_count = 0;
+	tmu->channel.tmu = tmu;
 
-	ret = sh_tmu_register(&p->channel, (char *)dev_name(&p->pdev->dev),
+	ret = sh_tmu_register(&tmu->channel, (char *)dev_name(&tmu->pdev->dev),
 			      cfg->clockevent_rating,
 			      cfg->clocksource_rating);
 	if (ret < 0)
@@ -497,18 +497,18 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 	return 0;
 
  err3:
-	clk_unprepare(p->clk);
+	clk_unprepare(tmu->clk);
  err2:
-	clk_put(p->clk);
+	clk_put(tmu->clk);
  err1:
-	iounmap(p->mapbase);
+	iounmap(tmu->mapbase);
  err0:
 	return ret;
 }
 
 static int sh_tmu_probe(struct platform_device *pdev)
 {
-	struct sh_tmu_priv *p = platform_get_drvdata(pdev);
+	struct sh_tmu_device *tmu = platform_get_drvdata(pdev);
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	int ret;
 
@@ -517,20 +517,20 @@ static int sh_tmu_probe(struct platform_device *pdev)
 		pm_runtime_enable(&pdev->dev);
 	}
 
-	if (p) {
+	if (tmu) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		goto out;
 	}
 
-	p = kmalloc(sizeof(*p), GFP_KERNEL);
-	if (p == NULL) {
+	tmu = kmalloc(sizeof(*tmu), GFP_KERNEL);
+	if (tmu == NULL) {
 		dev_err(&pdev->dev, "failed to allocate driver data\n");
 		return -ENOMEM;
 	}
 
-	ret = sh_tmu_setup(p, pdev);
+	ret = sh_tmu_setup(tmu, pdev);
 	if (ret) {
-		kfree(p);
+		kfree(tmu);
 		pm_runtime_idle(&pdev->dev);
 		return ret;
 	}
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 24/71] clocksource: sh_tmu: Split channel setup to separate function
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (21 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 23/71] clocksource: sh_tmu: Rename struct sh_tmu_priv to sh_tmu_device Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 25/71] clocksource: sh_tmu: Constify name argument to sh_tmu_register() Daniel Lezcano
                     ` (46 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Move the channel setup code from sh_tmu_setup to a new
sh_tmu_setup_channel function and call it from sh_tmu_setup.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_tmu.c |   36 +++++++++++++++++++++++-------------
 1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 7013790..4779c97 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -436,6 +436,28 @@ static int sh_tmu_register(struct sh_tmu_channel *ch, char *name,
 	return 0;
 }
 
+static int sh_tmu_channel_setup(struct sh_tmu_channel *ch,
+				struct sh_tmu_device *tmu)
+{
+	struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
+
+	memset(ch, 0, sizeof(*ch));
+	ch->tmu = tmu;
+
+	ch->irq = platform_get_irq(tmu->pdev, 0);
+	if (ch->irq < 0) {
+		dev_err(&tmu->pdev->dev, "failed to get irq\n");
+		return ch->irq;
+	}
+
+	ch->cs_enabled = false;
+	ch->enable_count = 0;
+
+	return sh_tmu_register(ch, (char *)dev_name(&tmu->pdev->dev),
+			       cfg->clockevent_rating,
+			       cfg->clocksource_rating);
+}
+
 static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
@@ -459,12 +481,6 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
 		goto err0;
 	}
 
-	tmu->channel.irq = platform_get_irq(tmu->pdev, 0);
-	if (tmu->channel.irq < 0) {
-		dev_err(&tmu->pdev->dev, "failed to get irq\n");
-		goto err0;
-	}
-
 	/* map memory, let mapbase point to our channel */
 	tmu->mapbase = ioremap_nocache(res->start, resource_size(res));
 	if (tmu->mapbase == NULL) {
@@ -484,13 +500,7 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
 	if (ret < 0)
 		goto err2;
 
-	tmu->channel.cs_enabled = false;
-	tmu->channel.enable_count = 0;
-	tmu->channel.tmu = tmu;
-
-	ret = sh_tmu_register(&tmu->channel, (char *)dev_name(&tmu->pdev->dev),
-			      cfg->clockevent_rating,
-			      cfg->clocksource_rating);
+	ret = sh_tmu_channel_setup(&tmu->channel, tmu);
 	if (ret < 0)
 		goto err3;
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 25/71] clocksource: sh_tmu: Constify name argument to sh_tmu_register()
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (22 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 24/71] clocksource: sh_tmu: Split channel setup to separate function Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 26/71] clocksource: sh_tmu: Add memory base to sh_tmu_channel structure Daniel Lezcano
                     ` (45 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

The name argument is assigned to const structure fields only, constify
it.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_tmu.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 4779c97..2c64e3f 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -292,7 +292,7 @@ static void sh_tmu_clocksource_resume(struct clocksource *cs)
 }
 
 static int sh_tmu_register_clocksource(struct sh_tmu_channel *ch,
-				       char *name, unsigned long rating)
+				       const char *name, unsigned long rating)
 {
 	struct clocksource *cs = &ch->cs;
 
@@ -393,7 +393,7 @@ static void sh_tmu_clock_event_resume(struct clock_event_device *ced)
 }
 
 static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
-				       char *name, unsigned long rating)
+				       const char *name, unsigned long rating)
 {
 	struct clock_event_device *ced = &ch->ced;
 	int ret;
@@ -424,7 +424,7 @@ static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
 	}
 }
 
-static int sh_tmu_register(struct sh_tmu_channel *ch, char *name,
+static int sh_tmu_register(struct sh_tmu_channel *ch, const char *name,
 		    unsigned long clockevent_rating,
 		    unsigned long clocksource_rating)
 {
@@ -453,7 +453,7 @@ static int sh_tmu_channel_setup(struct sh_tmu_channel *ch,
 	ch->cs_enabled = false;
 	ch->enable_count = 0;
 
-	return sh_tmu_register(ch, (char *)dev_name(&tmu->pdev->dev),
+	return sh_tmu_register(ch, dev_name(&tmu->pdev->dev),
 			       cfg->clockevent_rating,
 			       cfg->clocksource_rating);
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 26/71] clocksource: sh_tmu: Add memory base to sh_tmu_channel structure
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (23 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 25/71] clocksource: sh_tmu: Constify name argument to sh_tmu_register() Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 27/71] clocksource: sh_tmu: Add index to struct sh_tmu_channel Daniel Lezcano
                     ` (44 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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_tmu.c |   30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 2c64e3f..a464ed8 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -40,6 +40,7 @@ struct sh_tmu_device;
 struct sh_tmu_channel {
 	struct sh_tmu_device *tmu;
 
+	void __iomem *base;
 	int irq;
 
 	unsigned long rate;
@@ -68,39 +69,35 @@ static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
 
 static inline unsigned long sh_tmu_read(struct sh_tmu_channel *ch, int reg_nr)
 {
-	struct sh_timer_config *cfg = ch->tmu->pdev->dev.platform_data;
-	void __iomem *base = ch->tmu->mapbase;
 	unsigned long offs;
 
 	if (reg_nr == TSTR)
-		return ioread8(base - cfg->channel_offset);
+		return ioread8(ch->tmu->mapbase);
 
 	offs = reg_nr << 2;
 
 	if (reg_nr == TCR)
-		return ioread16(base + offs);
+		return ioread16(ch->base + offs);
 	else
-		return ioread32(base + offs);
+		return ioread32(ch->base + offs);
 }
 
 static inline void sh_tmu_write(struct sh_tmu_channel *ch, int reg_nr,
 				unsigned long value)
 {
-	struct sh_timer_config *cfg = ch->tmu->pdev->dev.platform_data;
-	void __iomem *base = ch->tmu->mapbase;
 	unsigned long offs;
 
 	if (reg_nr == TSTR) {
-		iowrite8(value, base - cfg->channel_offset);
+		iowrite8(value, ch->tmu->mapbase);
 		return;
 	}
 
 	offs = reg_nr << 2;
 
 	if (reg_nr == TCR)
-		iowrite16(value, base + offs);
+		iowrite16(value, ch->base + offs);
 	else
-		iowrite32(value, base + offs);
+		iowrite32(value, ch->base + offs);
 }
 
 static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start)
@@ -481,13 +478,18 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
 		goto err0;
 	}
 
-	/* map memory, let mapbase point to our channel */
-	tmu->mapbase = ioremap_nocache(res->start, resource_size(res));
-	if (tmu->mapbase == NULL) {
+	/*
+	 * Map memory, let channel.base point to our channel and mapbase to the
+	 * start/stop shared register.
+	 */
+	tmu->channel.base = ioremap_nocache(res->start, resource_size(res));
+	if (tmu->channel.base == NULL) {
 		dev_err(&tmu->pdev->dev, "failed to remap I/O memory\n");
 		goto err0;
 	}
 
+	tmu->mapbase = tmu->channel.base - cfg->channel_offset;
+
 	/* get hold of clock */
 	tmu->clk = clk_get(&tmu->pdev->dev, "tmu_fck");
 	if (IS_ERR(tmu->clk)) {
@@ -511,7 +513,7 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
  err2:
 	clk_put(tmu->clk);
  err1:
-	iounmap(tmu->mapbase);
+	iounmap(tmu->channel.base);
  err0:
 	return ret;
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 27/71] clocksource: sh_tmu: Add index to struct sh_tmu_channel
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (24 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 26/71] clocksource: sh_tmu: Add memory base to sh_tmu_channel structure Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 28/71] clocksource: sh_tmu: Replace kmalloc + memset with kzalloc Daniel Lezcano
                     ` (43 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Use the index as the timer start/stop bit and when printing messages to
identify the channel.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_tmu.c |   35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index a464ed8..e304304 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -39,6 +39,7 @@ struct sh_tmu_device;
 
 struct sh_tmu_channel {
 	struct sh_tmu_device *tmu;
+	unsigned int index;
 
 	void __iomem *base;
 	int irq;
@@ -102,7 +103,6 @@ static inline void sh_tmu_write(struct sh_tmu_channel *ch, int reg_nr,
 
 static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start)
 {
-	struct sh_timer_config *cfg = ch->tmu->pdev->dev.platform_data;
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
@@ -110,9 +110,9 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_channel *ch, int start)
 	value = sh_tmu_read(ch, TSTR);
 
 	if (start)
-		value |= 1 << cfg->timer_bit;
+		value |= 1 << ch->index;
 	else
-		value &= ~(1 << cfg->timer_bit);
+		value &= ~(1 << ch->index);
 
 	sh_tmu_write(ch, TSTR, value);
 	raw_spin_unlock_irqrestore(&sh_tmu_lock, flags);
@@ -125,7 +125,8 @@ static int __sh_tmu_enable(struct sh_tmu_channel *ch)
 	/* enable clock */
 	ret = clk_enable(ch->tmu->clk);
 	if (ret) {
-		dev_err(&ch->tmu->pdev->dev, "cannot enable clock\n");
+		dev_err(&ch->tmu->pdev->dev, "ch%u: cannot enable clock\n",
+			ch->index);
 		return ret;
 	}
 
@@ -303,7 +304,8 @@ static int sh_tmu_register_clocksource(struct sh_tmu_channel *ch,
 	cs->mask = CLOCKSOURCE_MASK(32);
 	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
 
-	dev_info(&ch->tmu->pdev->dev, "used as clock source\n");
+	dev_info(&ch->tmu->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);
@@ -349,12 +351,12 @@ static void sh_tmu_clock_event_mode(enum clock_event_mode mode,
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		dev_info(&ch->tmu->pdev->dev,
-			 "used for periodic clock events\n");
+			 "ch%u: used for periodic clock events\n", ch->index);
 		sh_tmu_clock_event_start(ch, 1);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		dev_info(&ch->tmu->pdev->dev,
-			 "used for oneshot clock events\n");
+			 "ch%u: used for oneshot clock events\n", ch->index);
 		sh_tmu_clock_event_start(ch, 0);
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
@@ -407,7 +409,8 @@ static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
 	ced->suspend = sh_tmu_clock_event_suspend;
 	ced->resume = sh_tmu_clock_event_resume;
 
-	dev_info(&ch->tmu->pdev->dev, "used for clock events\n");
+	dev_info(&ch->tmu->pdev->dev, "ch%u: used for clock events\n",
+		 ch->index);
 
 	clockevents_config_and_register(ced, 1, 0x300, 0xffffffff);
 
@@ -415,8 +418,8 @@ static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
 			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
 			  dev_name(&ch->tmu->pdev->dev), ch);
 	if (ret) {
-		dev_err(&ch->tmu->pdev->dev, "failed to request irq %d\n",
-			ch->irq);
+		dev_err(&ch->tmu->pdev->dev, "ch%u: failed to request irq %d\n",
+			ch->index, ch->irq);
 		return;
 	}
 }
@@ -441,9 +444,19 @@ static int sh_tmu_channel_setup(struct sh_tmu_channel *ch,
 	memset(ch, 0, sizeof(*ch));
 	ch->tmu = tmu;
 
+	/*
+	 * The SH3 variant (SH770x, SH7705, SH7710 and SH7720) maps channel
+	 * registers blocks at base + 2 + 12 * index, while all other variants
+	 * map them at base + 4 + 12 * index. We can compute the index by just
+	 * dividing by 12, the 2 bytes or 4 bytes offset being hidden by the
+	 * integer division.
+	 */
+	ch->index = cfg->channel_offset / 12;
+
 	ch->irq = platform_get_irq(tmu->pdev, 0);
 	if (ch->irq < 0) {
-		dev_err(&tmu->pdev->dev, "failed to get irq\n");
+		dev_err(&tmu->pdev->dev, "ch%u: failed to get irq\n",
+			ch->index);
 		return ch->irq;
 	}
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 28/71] clocksource: sh_tmu: Replace kmalloc + memset with kzalloc
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (25 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 27/71] clocksource: sh_tmu: Add index to struct sh_tmu_channel Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 29/71] clocksource: sh_tmu: Allocate channels dynamically Daniel Lezcano
                     ` (42 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

One kzalloc a day keeps the bugs away.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_tmu.c |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index e304304..26a9f7d 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -397,8 +397,6 @@ static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
 	struct clock_event_device *ced = &ch->ced;
 	int ret;
 
-	memset(ced, 0, sizeof(*ced));
-
 	ced->name = name;
 	ced->features = CLOCK_EVT_FEAT_PERIODIC;
 	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
@@ -441,7 +439,6 @@ static int sh_tmu_channel_setup(struct sh_tmu_channel *ch,
 {
 	struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
 
-	memset(ch, 0, sizeof(*ch));
 	ch->tmu = tmu;
 
 	/*
@@ -475,7 +472,6 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
 	int ret;
 	ret = -ENXIO;
 
-	memset(tmu, 0, sizeof(*tmu));
 	tmu->pdev = pdev;
 
 	if (!cfg) {
@@ -547,7 +543,7 @@ static int sh_tmu_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	tmu = kmalloc(sizeof(*tmu), GFP_KERNEL);
+	tmu = kzalloc(sizeof(*tmu), GFP_KERNEL);
 	if (tmu == NULL) {
 		dev_err(&pdev->dev, "failed to allocate driver data\n");
 		return -ENOMEM;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 29/71] clocksource: sh_tmu: Allocate channels dynamically
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (26 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 28/71] clocksource: sh_tmu: Replace kmalloc + memset with kzalloc Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 30/71] clocksource: sh_tmu: Replace hardcoded register values with macros Daniel Lezcano
                     ` (41 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

This prepares the driver for multi-channel support.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_tmu.c |   27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 26a9f7d..55b7a37 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -58,7 +58,8 @@ struct sh_tmu_device {
 	void __iomem *mapbase;
 	struct clk *clk;
 
-	struct sh_tmu_channel channel;
+	struct sh_tmu_channel *channels;
+	unsigned int num_channels;
 };
 
 static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
@@ -469,6 +470,7 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
+	void __iomem *base;
 	int ret;
 	ret = -ENXIO;
 
@@ -488,16 +490,16 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
 	}
 
 	/*
-	 * Map memory, let channel.base point to our channel and mapbase to the
+	 * Map memory, let base point to our channel and mapbase to the
 	 * start/stop shared register.
 	 */
-	tmu->channel.base = ioremap_nocache(res->start, resource_size(res));
-	if (tmu->channel.base == NULL) {
+	base = ioremap_nocache(res->start, resource_size(res));
+	if (base == NULL) {
 		dev_err(&tmu->pdev->dev, "failed to remap I/O memory\n");
 		goto err0;
 	}
 
-	tmu->mapbase = tmu->channel.base - cfg->channel_offset;
+	tmu->mapbase = base - cfg->channel_offset;
 
 	/* get hold of clock */
 	tmu->clk = clk_get(&tmu->pdev->dev, "tmu_fck");
@@ -511,18 +513,29 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
 	if (ret < 0)
 		goto err2;
 
-	ret = sh_tmu_channel_setup(&tmu->channel, tmu);
+	tmu->channels = kzalloc(sizeof(*tmu->channels), GFP_KERNEL);
+	if (tmu->channels == NULL) {
+		ret = -ENOMEM;
+		goto err3;
+	}
+
+	tmu->num_channels = 1;
+
+	tmu->channels[0].base = base;
+
+	ret = sh_tmu_channel_setup(&tmu->channels[0], tmu);
 	if (ret < 0)
 		goto err3;
 
 	return 0;
 
  err3:
+	kfree(tmu->channels);
 	clk_unprepare(tmu->clk);
  err2:
 	clk_put(tmu->clk);
  err1:
-	iounmap(tmu->channel.base);
+	iounmap(base);
  err0:
 	return ret;
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 30/71] clocksource: sh_tmu: Replace hardcoded register values with macros
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (27 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 29/71] clocksource: sh_tmu: Allocate channels dynamically Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 31/71] clocksource: sh_tmu: Hardcode TMU clock event and source ratings to 200 Daniel Lezcano
                     ` (40 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Define symbolic macros for all used registers bits.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_tmu.c |   19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 55b7a37..63ed92d 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -69,6 +69,15 @@ static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
 #define TCNT 1 /* channel register */
 #define TCR 2 /* channel register */
 
+#define TCR_UNF			(1 << 8)
+#define TCR_UNIE		(1 << 5)
+#define TCR_TPSC_CLK4		(0 << 0)
+#define TCR_TPSC_CLK16		(1 << 0)
+#define TCR_TPSC_CLK64		(2 << 0)
+#define TCR_TPSC_CLK256		(3 << 0)
+#define TCR_TPSC_CLK1024	(4 << 0)
+#define TCR_TPSC_MASK		(7 << 0)
+
 static inline unsigned long sh_tmu_read(struct sh_tmu_channel *ch, int reg_nr)
 {
 	unsigned long offs;
@@ -140,7 +149,7 @@ static int __sh_tmu_enable(struct sh_tmu_channel *ch)
 
 	/* configure channel to parent clock / 4, irq off */
 	ch->rate = clk_get_rate(ch->tmu->clk) / 4;
-	sh_tmu_write(ch, TCR, 0x0000);
+	sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);
 
 	/* enable channel */
 	sh_tmu_start_stop_ch(ch, 1);
@@ -165,7 +174,7 @@ static void __sh_tmu_disable(struct sh_tmu_channel *ch)
 	sh_tmu_start_stop_ch(ch, 0);
 
 	/* disable interrupts in TMU block */
-	sh_tmu_write(ch, TCR, 0x0000);
+	sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);
 
 	/* stop clock */
 	clk_disable(ch->tmu->clk);
@@ -195,7 +204,7 @@ static void sh_tmu_set_next(struct sh_tmu_channel *ch, unsigned long delta,
 	sh_tmu_read(ch, TCR);
 
 	/* enable interrupt */
-	sh_tmu_write(ch, TCR, 0x0020);
+	sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4);
 
 	/* reload delta value in case of periodic timer */
 	if (periodic)
@@ -215,9 +224,9 @@ static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id)
 
 	/* disable or acknowledge interrupt */
 	if (ch->ced.mode == CLOCK_EVT_MODE_ONESHOT)
-		sh_tmu_write(ch, TCR, 0x0000);
+		sh_tmu_write(ch, TCR, TCR_TPSC_CLK4);
 	else
-		sh_tmu_write(ch, TCR, 0x0020);
+		sh_tmu_write(ch, TCR, TCR_UNIE | TCR_TPSC_CLK4);
 
 	/* notify clockevent layer */
 	ch->ced.event_handler(&ch->ced);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 31/71] clocksource: sh_tmu: Hardcode TMU clock event and source ratings to 200
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (28 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 30/71] clocksource: sh_tmu: Replace hardcoded register values with macros Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 32/71] clocksource: sh_tmu: Add support for multiple channels per device Daniel Lezcano
                     ` (39 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

All boards use clock event and clock source ratings of 200 for the TMU,
hardcode it in the driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_tmu.c |   23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 63ed92d..fec9bed 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -300,12 +300,12 @@ static void sh_tmu_clocksource_resume(struct clocksource *cs)
 }
 
 static int sh_tmu_register_clocksource(struct sh_tmu_channel *ch,
-				       const char *name, unsigned long rating)
+				       const char *name)
 {
 	struct clocksource *cs = &ch->cs;
 
 	cs->name = name;
-	cs->rating = rating;
+	cs->rating = 200;
 	cs->read = sh_tmu_clocksource_read;
 	cs->enable = sh_tmu_clocksource_enable;
 	cs->disable = sh_tmu_clocksource_disable;
@@ -402,7 +402,7 @@ static void sh_tmu_clock_event_resume(struct clock_event_device *ced)
 }
 
 static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
-				       const char *name, unsigned long rating)
+				       const char *name)
 {
 	struct clock_event_device *ced = &ch->ced;
 	int ret;
@@ -410,7 +410,7 @@ static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
 	ced->name = name;
 	ced->features = CLOCK_EVT_FEAT_PERIODIC;
 	ced->features |= CLOCK_EVT_FEAT_ONESHOT;
-	ced->rating = rating;
+	ced->rating = 200;
 	ced->cpumask = cpumask_of(0);
 	ced->set_next_event = sh_tmu_clock_event_next;
 	ced->set_mode = sh_tmu_clock_event_mode;
@@ -433,13 +433,12 @@ static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
 }
 
 static int sh_tmu_register(struct sh_tmu_channel *ch, const char *name,
-		    unsigned long clockevent_rating,
-		    unsigned long clocksource_rating)
+			   bool clockevent, bool clocksource)
 {
-	if (clockevent_rating)
-		sh_tmu_register_clockevent(ch, name, clockevent_rating);
-	else if (clocksource_rating)
-		sh_tmu_register_clocksource(ch, name, clocksource_rating);
+	if (clockevent)
+		sh_tmu_register_clockevent(ch, name);
+	else if (clocksource)
+		sh_tmu_register_clocksource(ch, name);
 
 	return 0;
 }
@@ -471,8 +470,8 @@ static int sh_tmu_channel_setup(struct sh_tmu_channel *ch,
 	ch->enable_count = 0;
 
 	return sh_tmu_register(ch, dev_name(&tmu->pdev->dev),
-			       cfg->clockevent_rating,
-			       cfg->clocksource_rating);
+			       cfg->clockevent_rating != 0,
+			       cfg->clocksource_rating != 0);
 }
 
 static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 32/71] clocksource: sh_tmu: Add support for multiple channels per device
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (29 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 31/71] clocksource: sh_tmu: Hardcode TMU clock event and source ratings to 200 Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 33/71] clocksource: sh_tmu: Rename clock to "fck" in the non-legacy case Daniel Lezcano
                     ` (38 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

TMU hardware devices can support multiple channels, with global
registers and per-channel registers. The sh_tmu 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_tmu.c |  213 ++++++++++++++++++++++++++++++------------
 1 file changed, 152 insertions(+), 61 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index fec9bed..0306d31 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -35,6 +35,12 @@
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 
+enum sh_tmu_model {
+	SH_TMU_LEGACY,
+	SH_TMU,
+	SH_TMU_SH3,
+};
+
 struct sh_tmu_device;
 
 struct sh_tmu_channel {
@@ -58,8 +64,13 @@ struct sh_tmu_device {
 	void __iomem *mapbase;
 	struct clk *clk;
 
+	enum sh_tmu_model model;
+
 	struct sh_tmu_channel *channels;
 	unsigned int num_channels;
+
+	bool has_clockevent;
+	bool has_clocksource;
 };
 
 static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
@@ -82,8 +93,16 @@ static inline unsigned long sh_tmu_read(struct sh_tmu_channel *ch, int reg_nr)
 {
 	unsigned long offs;
 
-	if (reg_nr == TSTR)
-		return ioread8(ch->tmu->mapbase);
+	if (reg_nr == TSTR) {
+		switch (ch->tmu->model) {
+		case SH_TMU_LEGACY:
+			return ioread8(ch->tmu->mapbase);
+		case SH_TMU_SH3:
+			return ioread8(ch->tmu->mapbase + 2);
+		case SH_TMU:
+			return ioread8(ch->tmu->mapbase + 4);
+		}
+	}
 
 	offs = reg_nr << 2;
 
@@ -99,8 +118,14 @@ static inline void sh_tmu_write(struct sh_tmu_channel *ch, int reg_nr,
 	unsigned long offs;
 
 	if (reg_nr == TSTR) {
-		iowrite8(value, ch->tmu->mapbase);
-		return;
+		switch (ch->tmu->model) {
+		case SH_TMU_LEGACY:
+			return iowrite8(value, ch->tmu->mapbase);
+		case SH_TMU_SH3:
+			return iowrite8(value, ch->tmu->mapbase + 2);
+		case SH_TMU:
+			return iowrite8(value, ch->tmu->mapbase + 4);
+		}
 	}
 
 	offs = reg_nr << 2;
@@ -435,31 +460,49 @@ static void sh_tmu_register_clockevent(struct sh_tmu_channel *ch,
 static int sh_tmu_register(struct sh_tmu_channel *ch, const char *name,
 			   bool clockevent, bool clocksource)
 {
-	if (clockevent)
+	if (clockevent) {
+		ch->tmu->has_clockevent = true;
 		sh_tmu_register_clockevent(ch, name);
-	else if (clocksource)
+	} else if (clocksource) {
+		ch->tmu->has_clocksource = true;
 		sh_tmu_register_clocksource(ch, name);
+	}
 
 	return 0;
 }
 
-static int sh_tmu_channel_setup(struct sh_tmu_channel *ch,
+static int sh_tmu_channel_setup(struct sh_tmu_channel *ch, unsigned int index,
+				bool clockevent, bool clocksource,
 				struct sh_tmu_device *tmu)
 {
-	struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
+	/* Skip unused channels. */
+	if (!clockevent && !clocksource)
+		return 0;
 
 	ch->tmu = tmu;
 
-	/*
-	 * The SH3 variant (SH770x, SH7705, SH7710 and SH7720) maps channel
-	 * registers blocks at base + 2 + 12 * index, while all other variants
-	 * map them at base + 4 + 12 * index. We can compute the index by just
-	 * dividing by 12, the 2 bytes or 4 bytes offset being hidden by the
-	 * integer division.
-	 */
-	ch->index = cfg->channel_offset / 12;
+	if (tmu->model == SH_TMU_LEGACY) {
+		struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
+
+		/*
+		 * The SH3 variant (SH770x, SH7705, SH7710 and SH7720) maps
+		 * channel registers blocks at base + 2 + 12 * index, while all
+		 * other variants map them at base + 4 + 12 * index. We can
+		 * compute the index by just dividing by 12, the 2 bytes or 4
+		 * bytes offset being hidden by the integer division.
+		 */
+		ch->index = cfg->channel_offset / 12;
+		ch->base = tmu->mapbase + cfg->channel_offset;
+	} else {
+		ch->index = index;
+
+		if (tmu->model == SH_TMU_SH3)
+			ch->base = tmu->mapbase + 4 + ch->index * 12;
+		else
+			ch->base = tmu->mapbase + 8 + ch->index * 12;
+	}
 
-	ch->irq = platform_get_irq(tmu->pdev, 0);
+	ch->irq = platform_get_irq(tmu->pdev, ch->index);
 	if (ch->irq < 0) {
 		dev_err(&tmu->pdev->dev, "ch%u: failed to get irq\n",
 			ch->index);
@@ -470,88 +513,127 @@ static int sh_tmu_channel_setup(struct sh_tmu_channel *ch,
 	ch->enable_count = 0;
 
 	return sh_tmu_register(ch, dev_name(&tmu->pdev->dev),
-			       cfg->clockevent_rating != 0,
-			       cfg->clocksource_rating != 0);
+			       clockevent, clocksource);
 }
 
-static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
+static int sh_tmu_map_memory(struct sh_tmu_device *tmu)
 {
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
-	void __iomem *base;
-	int ret;
-	ret = -ENXIO;
-
-	tmu->pdev = pdev;
-
-	if (!cfg) {
-		dev_err(&tmu->pdev->dev, "missing platform data\n");
-		goto err0;
-	}
-
-	platform_set_drvdata(pdev, tmu);
 
 	res = platform_get_resource(tmu->pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(&tmu->pdev->dev, "failed to get I/O memory\n");
-		goto err0;
+		return -ENXIO;
 	}
 
+	tmu->mapbase = ioremap_nocache(res->start, resource_size(res));
+	if (tmu->mapbase == NULL)
+		return -ENXIO;
+
 	/*
-	 * Map memory, let base point to our channel and mapbase to the
-	 * start/stop shared register.
+	 * In legacy platform device configuration (with one device per channel)
+	 * the resource points to the channel base address.
 	 */
-	base = ioremap_nocache(res->start, resource_size(res));
-	if (base == NULL) {
-		dev_err(&tmu->pdev->dev, "failed to remap I/O memory\n");
-		goto err0;
+	if (tmu->model == SH_TMU_LEGACY) {
+		struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
+		tmu->mapbase -= cfg->channel_offset;
 	}
 
-	tmu->mapbase = base - cfg->channel_offset;
+	return 0;
+}
 
-	/* get hold of clock */
+static void sh_tmu_unmap_memory(struct sh_tmu_device *tmu)
+{
+	if (tmu->model == SH_TMU_LEGACY) {
+		struct sh_timer_config *cfg = tmu->pdev->dev.platform_data;
+		tmu->mapbase += cfg->channel_offset;
+	}
+
+	iounmap(tmu->mapbase);
+}
+
+static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
+{
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	const struct platform_device_id *id = pdev->id_entry;
+	unsigned int i;
+	int ret;
+
+	if (!cfg) {
+		dev_err(&tmu->pdev->dev, "missing platform data\n");
+		return -ENXIO;
+	}
+
+	tmu->pdev = pdev;
+	tmu->model = id->driver_data;
+
+	/* Get hold of clock. */
 	tmu->clk = clk_get(&tmu->pdev->dev, "tmu_fck");
 	if (IS_ERR(tmu->clk)) {
 		dev_err(&tmu->pdev->dev, "cannot get clock\n");
-		ret = PTR_ERR(tmu->clk);
-		goto err1;
+		return PTR_ERR(tmu->clk);
 	}
 
 	ret = clk_prepare(tmu->clk);
 	if (ret < 0)
-		goto err2;
+		goto err_clk_put;
+
+	/* Map the memory resource. */
+	ret = sh_tmu_map_memory(tmu);
+	if (ret < 0) {
+		dev_err(&tmu->pdev->dev, "failed to remap I/O memory\n");
+		goto err_clk_unprepare;
+	}
 
-	tmu->channels = kzalloc(sizeof(*tmu->channels), GFP_KERNEL);
+	/* Allocate and setup the channels. */
+	if (tmu->model == SH_TMU_LEGACY)
+		tmu->num_channels = 1;
+	else
+		tmu->num_channels = hweight8(cfg->channels_mask);
+
+	tmu->channels = kzalloc(sizeof(*tmu->channels) * tmu->num_channels,
+				GFP_KERNEL);
 	if (tmu->channels == NULL) {
 		ret = -ENOMEM;
-		goto err3;
+		goto err_unmap;
 	}
 
-	tmu->num_channels = 1;
-
-	tmu->channels[0].base = base;
+	if (tmu->model == SH_TMU_LEGACY) {
+		ret = sh_tmu_channel_setup(&tmu->channels[0], 0,
+					   cfg->clockevent_rating != 0,
+					   cfg->clocksource_rating != 0, tmu);
+		if (ret < 0)
+			goto err_unmap;
+	} else {
+		/*
+		 * Use the first channel as a clock event device and the second
+		 * channel as a clock source.
+		 */
+		for (i = 0; i < tmu->num_channels; ++i) {
+			ret = sh_tmu_channel_setup(&tmu->channels[i], i,
+						   i == 0, i == 1, tmu);
+			if (ret < 0)
+				goto err_unmap;
+		}
+	}
 
-	ret = sh_tmu_channel_setup(&tmu->channels[0], tmu);
-	if (ret < 0)
-		goto err3;
+	platform_set_drvdata(pdev, tmu);
 
 	return 0;
 
- err3:
+err_unmap:
 	kfree(tmu->channels);
+	sh_tmu_unmap_memory(tmu);
+err_clk_unprepare:
 	clk_unprepare(tmu->clk);
- err2:
+err_clk_put:
 	clk_put(tmu->clk);
- err1:
-	iounmap(base);
- err0:
 	return ret;
 }
 
 static int sh_tmu_probe(struct platform_device *pdev)
 {
 	struct sh_tmu_device *tmu = platform_get_drvdata(pdev);
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	int ret;
 
 	if (!is_early_platform_device(pdev)) {
@@ -580,7 +662,7 @@ static int sh_tmu_probe(struct platform_device *pdev)
 		return 0;
 
  out:
-	if (cfg->clockevent_rating || cfg->clocksource_rating)
+	if (tmu->has_clockevent || tmu->has_clocksource)
 		pm_runtime_irq_safe(&pdev->dev);
 	else
 		pm_runtime_idle(&pdev->dev);
@@ -593,12 +675,21 @@ static int sh_tmu_remove(struct platform_device *pdev)
 	return -EBUSY; /* cannot unregister clockevent and clocksource */
 }
 
+static const struct platform_device_id sh_tmu_id_table[] = {
+	{ "sh_tmu", SH_TMU_LEGACY },
+	{ "sh-tmu", SH_TMU },
+	{ "sh-tmu-sh3", SH_TMU_SH3 },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, sh_tmu_id_table);
+
 static struct platform_driver sh_tmu_device_driver = {
 	.probe		= sh_tmu_probe,
 	.remove		= sh_tmu_remove,
 	.driver		= {
 		.name	= "sh_tmu",
-	}
+	},
+	.id_table	= sh_tmu_id_table,
 };
 
 static int __init sh_tmu_init(void)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 33/71] clocksource: sh_tmu: Rename clock to "fck" in the non-legacy case
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (30 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 32/71] clocksource: sh_tmu: Add support for multiple channels per device Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 34/71] clocksource: sh_tmu: Remove FSF mail address from GPL notice Daniel Lezcano
                     ` (37 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

The sh_tmu driver gets the TMU functional clock using a connection ID of
"tmu_fck". While all SH SoCs create clock lookup entries with a NULL
device ID and a "tmu_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 connection ID of "fck" in the non-legacy
platform data case. Clock lookup entries will be renamed to use the
device ID as well as the connection ID as platforms get moved to new
platform data. The legacy code will eventually be dropped, leaving us
with device ID based clock lookup, compatible with DT boot.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_tmu.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 0306d31..cf07797 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -568,7 +568,8 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
 	tmu->model = id->driver_data;
 
 	/* Get hold of clock. */
-	tmu->clk = clk_get(&tmu->pdev->dev, "tmu_fck");
+	tmu->clk = clk_get(&tmu->pdev->dev,
+			   tmu->model == SH_TMU_LEGACY ? "tmu_fck" : "fck");
 	if (IS_ERR(tmu->clk)) {
 		dev_err(&tmu->pdev->dev, "cannot get clock\n");
 		return PTR_ERR(tmu->clk);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 34/71] clocksource: sh_tmu: Remove FSF mail address from GPL notice
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (31 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 33/71] clocksource: sh_tmu: Rename clock to "fck" in the non-legacy case Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 35/71] clocksource: sh_tmu: Sort headers alphabetically Daniel Lezcano
                     ` (36 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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_tmu.c |    4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index cf07797..981f8d3 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.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.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 35/71] clocksource: sh_tmu: Sort headers alphabetically
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (32 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 34/71] clocksource: sh_tmu: Remove FSF mail address from GPL notice Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 36/71] clocksource: sh_mtu2: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (35 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

This helps locating duplicates and inserting new headers.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/clocksource/sh_tmu.c |   20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 981f8d3..4ba2c0f 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.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/delay.h>
 #include <linux/io.h>
-#include <linux/clk.h>
+#include <linux/ioport.h>
 #include <linux/irq.h>
-#include <linux/err.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>
 
 enum sh_tmu_model {
 	SH_TMU_LEGACY,
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 36/71] clocksource: sh_mtu2: Use request_irq() instead of setup_irq()
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (33 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 35/71] clocksource: sh_tmu: Sort headers alphabetically Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 37/71] clocksource: sh_mtu2: Turn sh_mtu2_priv fields into local variables Daniel Lezcano
                     ` (34 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

The driver claims it needs to register an interrupt handler too early
for request_irq(). This might have been true in the past, but the only
meaningful difference between request_irq() and setup_irq() today is an
additional kzalloc() call in request_irq(). As the driver calls
kmalloc() itself we know that the slab allocator is available, we can
thus switch to request_irq().

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |   22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index e30d76e..77992e0 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -37,7 +37,7 @@
 struct sh_mtu2_priv {
 	void __iomem *mapbase;
 	struct clk *clk;
-	struct irqaction irqaction;
+	int irq;
 	struct platform_device *pdev;
 	unsigned long rate;
 	unsigned long periodic;
@@ -244,10 +244,11 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p,
 	dev_info(&p->pdev->dev, "used for clock events\n");
 	clockevents_register_device(ced);
 
-	ret = setup_irq(p->irqaction.irq, &p->irqaction);
+	ret = request_irq(p->irq, sh_mtu2_interrupt,
+			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
+			  dev_name(&p->pdev->dev), p);
 	if (ret) {
-		dev_err(&p->pdev->dev, "failed to request irq %d\n",
-			p->irqaction.irq);
+		dev_err(&p->pdev->dev, "failed to request irq %d\n", p->irq);
 		return;
 	}
 }
@@ -265,7 +266,7 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
-	int irq, ret;
+	int ret;
 	ret = -ENXIO;
 
 	memset(p, 0, sizeof(*p));
@@ -284,8 +285,8 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
 		goto err0;
 	}
 
-	irq = platform_get_irq(p->pdev, 0);
-	if (irq < 0) {
+	p->irq = platform_get_irq(p->pdev, 0);
+	if (p->irq < 0) {
 		dev_err(&p->pdev->dev, "failed to get irq\n");
 		goto err0;
 	}
@@ -297,13 +298,6 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
 		goto err0;
 	}
 
-	/* setup data for setup_irq() (too early for request_irq()) */
-	p->irqaction.name = dev_name(&p->pdev->dev);
-	p->irqaction.handler = sh_mtu2_interrupt;
-	p->irqaction.dev_id = p;
-	p->irqaction.irq = irq;
-	p->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING;
-
 	/* get hold of clock */
 	p->clk = clk_get(&p->pdev->dev, "mtu2_fck");
 	if (IS_ERR(p->clk)) {
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 37/71] clocksource: sh_mtu2: Turn sh_mtu2_priv fields into local variables
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (34 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 36/71] clocksource: sh_mtu2: Use request_irq() instead of setup_irq() Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 38/71] clocksource: sh_mtu2: Split channel fields from sh_mtu2_priv Daniel Lezcano
                     ` (33 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

The rate and periodic fields are used in a single function only, as
local variables. Remove them from the structure.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 77992e0..6668455 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -39,8 +39,6 @@ struct sh_mtu2_priv {
 	struct clk *clk;
 	int irq;
 	struct platform_device *pdev;
-	unsigned long rate;
-	unsigned long periodic;
 	struct clock_event_device ced;
 };
 
@@ -122,6 +120,8 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start)
 
 static int sh_mtu2_enable(struct sh_mtu2_priv *p)
 {
+	unsigned long periodic;
+	unsigned long rate;
 	int ret;
 
 	pm_runtime_get_sync(&p->pdev->dev);
@@ -137,13 +137,13 @@ static int sh_mtu2_enable(struct sh_mtu2_priv *p)
 	/* make sure channel is disabled */
 	sh_mtu2_start_stop_ch(p, 0);
 
-	p->rate = clk_get_rate(p->clk) / 64;
-	p->periodic = (p->rate + HZ/2) / HZ;
+	rate = clk_get_rate(p->clk) / 64;
+	periodic = (rate + HZ/2) / HZ;
 
 	/* "Periodic Counter Operation" */
 	sh_mtu2_write(p, TCR, 0x23); /* TGRA clear, divide clock by 64 */
 	sh_mtu2_write(p, TIOR, 0);
-	sh_mtu2_write(p, TGR, p->periodic);
+	sh_mtu2_write(p, TGR, periodic);
 	sh_mtu2_write(p, TCNT, 0);
 	sh_mtu2_write(p, TMDR, 0);
 	sh_mtu2_write(p, TIER, 0x01);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 38/71] clocksource: sh_mtu2: Split channel fields from sh_mtu2_priv
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (35 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 37/71] clocksource: sh_mtu2: Turn sh_mtu2_priv fields into local variables Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 39/71] clocksource: sh_mtu2: Rename struct sh_mtu2_priv to sh_mtu2_device Daniel Lezcano
                     ` (32 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |  125 +++++++++++++++++++++++------------------
 1 file changed, 69 insertions(+), 56 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 6668455..e509f41 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -34,12 +34,21 @@
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 
+struct sh_mtu2_priv;
+
+struct sh_mtu2_channel {
+	struct sh_mtu2_priv *mtu;
+	int irq;
+	struct clock_event_device ced;
+};
+
 struct sh_mtu2_priv {
+	struct platform_device *pdev;
+
 	void __iomem *mapbase;
 	struct clk *clk;
-	int irq;
-	struct platform_device *pdev;
-	struct clock_event_device ced;
+
+	struct sh_mtu2_channel channel;
 };
 
 static DEFINE_RAW_SPINLOCK(sh_mtu2_lock);
@@ -63,10 +72,10 @@ static unsigned long mtu2_reg_offs[] = {
 	[TGR] = 8,
 };
 
-static inline unsigned long sh_mtu2_read(struct sh_mtu2_priv *p, int reg_nr)
+static inline unsigned long sh_mtu2_read(struct sh_mtu2_channel *ch, int reg_nr)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-	void __iomem *base = p->mapbase;
+	struct sh_timer_config *cfg = ch->mtu->pdev->dev.platform_data;
+	void __iomem *base = ch->mtu->mapbase;
 	unsigned long offs;
 
 	if (reg_nr == TSTR)
@@ -80,11 +89,11 @@ static inline unsigned long sh_mtu2_read(struct sh_mtu2_priv *p, int reg_nr)
 		return ioread8(base + offs);
 }
 
-static inline void sh_mtu2_write(struct sh_mtu2_priv *p, int reg_nr,
+static inline void sh_mtu2_write(struct sh_mtu2_channel *ch, int reg_nr,
 				unsigned long value)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-	void __iomem *base = p->mapbase;
+	struct sh_timer_config *cfg = ch->mtu->pdev->dev.platform_data;
+	void __iomem *base = ch->mtu->mapbase;
 	unsigned long offs;
 
 	if (reg_nr == TSTR) {
@@ -100,100 +109,100 @@ static inline void sh_mtu2_write(struct sh_mtu2_priv *p, int reg_nr,
 		iowrite8(value, base + offs);
 }
 
-static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start)
+static void sh_mtu2_start_stop_ch(struct sh_mtu2_channel *ch, int start)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+	struct sh_timer_config *cfg = ch->mtu->pdev->dev.platform_data;
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
 	raw_spin_lock_irqsave(&sh_mtu2_lock, flags);
-	value = sh_mtu2_read(p, TSTR);
+	value = sh_mtu2_read(ch, TSTR);
 
 	if (start)
 		value |= 1 << cfg->timer_bit;
 	else
 		value &= ~(1 << cfg->timer_bit);
 
-	sh_mtu2_write(p, TSTR, value);
+	sh_mtu2_write(ch, TSTR, value);
 	raw_spin_unlock_irqrestore(&sh_mtu2_lock, flags);
 }
 
-static int sh_mtu2_enable(struct sh_mtu2_priv *p)
+static int sh_mtu2_enable(struct sh_mtu2_channel *ch)
 {
 	unsigned long periodic;
 	unsigned long rate;
 	int ret;
 
-	pm_runtime_get_sync(&p->pdev->dev);
-	dev_pm_syscore_device(&p->pdev->dev, true);
+	pm_runtime_get_sync(&ch->mtu->pdev->dev);
+	dev_pm_syscore_device(&ch->mtu->pdev->dev, true);
 
 	/* enable clock */
-	ret = clk_enable(p->clk);
+	ret = clk_enable(ch->mtu->clk);
 	if (ret) {
-		dev_err(&p->pdev->dev, "cannot enable clock\n");
+		dev_err(&ch->mtu->pdev->dev, "cannot enable clock\n");
 		return ret;
 	}
 
 	/* make sure channel is disabled */
-	sh_mtu2_start_stop_ch(p, 0);
+	sh_mtu2_start_stop_ch(ch, 0);
 
-	rate = clk_get_rate(p->clk) / 64;
+	rate = clk_get_rate(ch->mtu->clk) / 64;
 	periodic = (rate + HZ/2) / HZ;
 
 	/* "Periodic Counter Operation" */
-	sh_mtu2_write(p, TCR, 0x23); /* TGRA clear, divide clock by 64 */
-	sh_mtu2_write(p, TIOR, 0);
-	sh_mtu2_write(p, TGR, periodic);
-	sh_mtu2_write(p, TCNT, 0);
-	sh_mtu2_write(p, TMDR, 0);
-	sh_mtu2_write(p, TIER, 0x01);
+	sh_mtu2_write(ch, TCR, 0x23); /* TGRA clear, divide clock by 64 */
+	sh_mtu2_write(ch, TIOR, 0);
+	sh_mtu2_write(ch, TGR, periodic);
+	sh_mtu2_write(ch, TCNT, 0);
+	sh_mtu2_write(ch, TMDR, 0);
+	sh_mtu2_write(ch, TIER, 0x01);
 
 	/* enable channel */
-	sh_mtu2_start_stop_ch(p, 1);
+	sh_mtu2_start_stop_ch(ch, 1);
 
 	return 0;
 }
 
-static void sh_mtu2_disable(struct sh_mtu2_priv *p)
+static void sh_mtu2_disable(struct sh_mtu2_channel *ch)
 {
 	/* disable channel */
-	sh_mtu2_start_stop_ch(p, 0);
+	sh_mtu2_start_stop_ch(ch, 0);
 
 	/* stop clock */
-	clk_disable(p->clk);
+	clk_disable(ch->mtu->clk);
 
-	dev_pm_syscore_device(&p->pdev->dev, false);
-	pm_runtime_put(&p->pdev->dev);
+	dev_pm_syscore_device(&ch->mtu->pdev->dev, false);
+	pm_runtime_put(&ch->mtu->pdev->dev);
 }
 
 static irqreturn_t sh_mtu2_interrupt(int irq, void *dev_id)
 {
-	struct sh_mtu2_priv *p = dev_id;
+	struct sh_mtu2_channel *ch = dev_id;
 
 	/* acknowledge interrupt */
-	sh_mtu2_read(p, TSR);
-	sh_mtu2_write(p, TSR, 0xfe);
+	sh_mtu2_read(ch, TSR);
+	sh_mtu2_write(ch, TSR, 0xfe);
 
 	/* notify clockevent layer */
-	p->ced.event_handler(&p->ced);
+	ch->ced.event_handler(&ch->ced);
 	return IRQ_HANDLED;
 }
 
-static struct sh_mtu2_priv *ced_to_sh_mtu2(struct clock_event_device *ced)
+static struct sh_mtu2_channel *ced_to_sh_mtu2(struct clock_event_device *ced)
 {
-	return container_of(ced, struct sh_mtu2_priv, ced);
+	return container_of(ced, struct sh_mtu2_channel, ced);
 }
 
 static void sh_mtu2_clock_event_mode(enum clock_event_mode mode,
 				    struct clock_event_device *ced)
 {
-	struct sh_mtu2_priv *p = ced_to_sh_mtu2(ced);
+	struct sh_mtu2_channel *ch = ced_to_sh_mtu2(ced);
 	int disabled = 0;
 
 	/* deal with old setting first */
 	switch (ced->mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		sh_mtu2_disable(p);
+		sh_mtu2_disable(ch);
 		disabled = 1;
 		break;
 	default:
@@ -202,12 +211,13 @@ static void sh_mtu2_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_mtu2_enable(p);
+		dev_info(&ch->mtu->pdev->dev,
+			 "used for periodic clock events\n");
+		sh_mtu2_enable(ch);
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
 		if (!disabled)
-			sh_mtu2_disable(p);
+			sh_mtu2_disable(ch);
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	default:
@@ -217,18 +227,18 @@ static void sh_mtu2_clock_event_mode(enum clock_event_mode mode,
 
 static void sh_mtu2_clock_event_suspend(struct clock_event_device *ced)
 {
-	pm_genpd_syscore_poweroff(&ced_to_sh_mtu2(ced)->pdev->dev);
+	pm_genpd_syscore_poweroff(&ced_to_sh_mtu2(ced)->mtu->pdev->dev);
 }
 
 static void sh_mtu2_clock_event_resume(struct clock_event_device *ced)
 {
-	pm_genpd_syscore_poweron(&ced_to_sh_mtu2(ced)->pdev->dev);
+	pm_genpd_syscore_poweron(&ced_to_sh_mtu2(ced)->mtu->pdev->dev);
 }
 
-static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p,
+static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
 				       char *name, unsigned long rating)
 {
-	struct clock_event_device *ced = &p->ced;
+	struct clock_event_device *ced = &ch->ced;
 	int ret;
 
 	memset(ced, 0, sizeof(*ced));
@@ -241,23 +251,24 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p,
 	ced->suspend = sh_mtu2_clock_event_suspend;
 	ced->resume = sh_mtu2_clock_event_resume;
 
-	dev_info(&p->pdev->dev, "used for clock events\n");
+	dev_info(&ch->mtu->pdev->dev, "used for clock events\n");
 	clockevents_register_device(ced);
 
-	ret = request_irq(p->irq, sh_mtu2_interrupt,
+	ret = request_irq(ch->irq, sh_mtu2_interrupt,
 			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
-			  dev_name(&p->pdev->dev), p);
+			  dev_name(&ch->mtu->pdev->dev), ch);
 	if (ret) {
-		dev_err(&p->pdev->dev, "failed to request irq %d\n", p->irq);
+		dev_err(&ch->mtu->pdev->dev, "failed to request irq %d\n",
+			ch->irq);
 		return;
 	}
 }
 
-static int sh_mtu2_register(struct sh_mtu2_priv *p, char *name,
+static int sh_mtu2_register(struct sh_mtu2_channel *ch, char *name,
 			    unsigned long clockevent_rating)
 {
 	if (clockevent_rating)
-		sh_mtu2_register_clockevent(p, name, clockevent_rating);
+		sh_mtu2_register_clockevent(ch, name, clockevent_rating);
 
 	return 0;
 }
@@ -285,8 +296,8 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
 		goto err0;
 	}
 
-	p->irq = platform_get_irq(p->pdev, 0);
-	if (p->irq < 0) {
+	p->channel.irq = platform_get_irq(p->pdev, 0);
+	if (p->channel.irq < 0) {
 		dev_err(&p->pdev->dev, "failed to get irq\n");
 		goto err0;
 	}
@@ -310,7 +321,9 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
 	if (ret < 0)
 		goto err2;
 
-	ret = sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev),
+	p->channel.mtu = p;
+
+	ret = sh_mtu2_register(&p->channel, (char *)dev_name(&p->pdev->dev),
 			       cfg->clockevent_rating);
 	if (ret < 0)
 		goto err3;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 39/71] clocksource: sh_mtu2: Rename struct sh_mtu2_priv to sh_mtu2_device
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (36 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 38/71] clocksource: sh_mtu2: Split channel fields from sh_mtu2_priv Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 40/71] clocksource: sh_mtu2: Split channel setup to separate function Daniel Lezcano
                     ` (31 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |   65 +++++++++++++++++++++--------------------
 1 file changed, 33 insertions(+), 32 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index e509f41..256621c 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -34,15 +34,15 @@
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 
-struct sh_mtu2_priv;
+struct sh_mtu2_device;
 
 struct sh_mtu2_channel {
-	struct sh_mtu2_priv *mtu;
+	struct sh_mtu2_device *mtu;
 	int irq;
 	struct clock_event_device ced;
 };
 
-struct sh_mtu2_priv {
+struct sh_mtu2_device {
 	struct platform_device *pdev;
 
 	void __iomem *mapbase;
@@ -273,75 +273,76 @@ static int sh_mtu2_register(struct sh_mtu2_channel *ch, char *name,
 	return 0;
 }
 
-static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
+static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
+			 struct platform_device *pdev)
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
 	int ret;
 	ret = -ENXIO;
 
-	memset(p, 0, sizeof(*p));
-	p->pdev = pdev;
+	memset(mtu, 0, sizeof(*mtu));
+	mtu->pdev = pdev;
 
 	if (!cfg) {
-		dev_err(&p->pdev->dev, "missing platform data\n");
+		dev_err(&mtu->pdev->dev, "missing platform data\n");
 		goto err0;
 	}
 
-	platform_set_drvdata(pdev, p);
+	platform_set_drvdata(pdev, mtu);
 
-	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource(mtu->pdev, IORESOURCE_MEM, 0);
 	if (!res) {
-		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
+		dev_err(&mtu->pdev->dev, "failed to get I/O memory\n");
 		goto err0;
 	}
 
-	p->channel.irq = platform_get_irq(p->pdev, 0);
-	if (p->channel.irq < 0) {
-		dev_err(&p->pdev->dev, "failed to get irq\n");
+	mtu->channel.irq = platform_get_irq(mtu->pdev, 0);
+	if (mtu->channel.irq < 0) {
+		dev_err(&mtu->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");
+	mtu->mapbase = ioremap_nocache(res->start, resource_size(res));
+	if (mtu->mapbase == NULL) {
+		dev_err(&mtu->pdev->dev, "failed to remap I/O memory\n");
 		goto err0;
 	}
 
 	/* get hold of clock */
-	p->clk = clk_get(&p->pdev->dev, "mtu2_fck");
-	if (IS_ERR(p->clk)) {
-		dev_err(&p->pdev->dev, "cannot get clock\n");
-		ret = PTR_ERR(p->clk);
+	mtu->clk = clk_get(&mtu->pdev->dev, "mtu2_fck");
+	if (IS_ERR(mtu->clk)) {
+		dev_err(&mtu->pdev->dev, "cannot get clock\n");
+		ret = PTR_ERR(mtu->clk);
 		goto err1;
 	}
 
-	ret = clk_prepare(p->clk);
+	ret = clk_prepare(mtu->clk);
 	if (ret < 0)
 		goto err2;
 
-	p->channel.mtu = p;
+	mtu->channel.mtu = mtu;
 
-	ret = sh_mtu2_register(&p->channel, (char *)dev_name(&p->pdev->dev),
+	ret = sh_mtu2_register(&mtu->channel, (char *)dev_name(&mtu->pdev->dev),
 			       cfg->clockevent_rating);
 	if (ret < 0)
 		goto err3;
 
 	return 0;
  err3:
-	clk_unprepare(p->clk);
+	clk_unprepare(mtu->clk);
  err2:
-	clk_put(p->clk);
+	clk_put(mtu->clk);
  err1:
-	iounmap(p->mapbase);
+	iounmap(mtu->mapbase);
  err0:
 	return ret;
 }
 
 static int sh_mtu2_probe(struct platform_device *pdev)
 {
-	struct sh_mtu2_priv *p = platform_get_drvdata(pdev);
+	struct sh_mtu2_device *mtu = platform_get_drvdata(pdev);
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	int ret;
 
@@ -350,20 +351,20 @@ static int sh_mtu2_probe(struct platform_device *pdev)
 		pm_runtime_enable(&pdev->dev);
 	}
 
-	if (p) {
+	if (mtu) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		goto out;
 	}
 
-	p = kmalloc(sizeof(*p), GFP_KERNEL);
-	if (p == NULL) {
+	mtu = kmalloc(sizeof(*mtu), GFP_KERNEL);
+	if (mtu == NULL) {
 		dev_err(&pdev->dev, "failed to allocate driver data\n");
 		return -ENOMEM;
 	}
 
-	ret = sh_mtu2_setup(p, pdev);
+	ret = sh_mtu2_setup(mtu, pdev);
 	if (ret) {
-		kfree(p);
+		kfree(mtu);
 		pm_runtime_idle(&pdev->dev);
 		return ret;
 	}
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 40/71] clocksource: sh_mtu2: Split channel setup to separate function
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (37 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 39/71] clocksource: sh_mtu2: Rename struct sh_mtu2_priv to sh_mtu2_device Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 41/71] clocksource: sh_mtu2: Constify name argument to sh_mtu2_register() Daniel Lezcano
                     ` (30 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Move the channel setup code from sh_mtu2_setup to a new
sh_mtu2_setup_channel function and call it from sh_mtu2_setup.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |   29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 256621c..8fd7059 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -273,6 +273,24 @@ static int sh_mtu2_register(struct sh_mtu2_channel *ch, char *name,
 	return 0;
 }
 
+static int sh_mtu2_setup_channel(struct sh_mtu2_channel *ch,
+				 struct sh_mtu2_device *mtu)
+{
+	struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
+
+	memset(ch, 0, sizeof(*ch));
+	ch->mtu = mtu;
+
+	ch->irq = platform_get_irq(mtu->pdev, 0);
+	if (ch->irq < 0) {
+		dev_err(&mtu->pdev->dev, "failed to get irq\n");
+		return ch->irq;
+	}
+
+	return sh_mtu2_register(ch, (char *)dev_name(&mtu->pdev->dev),
+				cfg->clockevent_rating);
+}
+
 static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
 			 struct platform_device *pdev)
 {
@@ -297,12 +315,6 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
 		goto err0;
 	}
 
-	mtu->channel.irq = platform_get_irq(mtu->pdev, 0);
-	if (mtu->channel.irq < 0) {
-		dev_err(&mtu->pdev->dev, "failed to get irq\n");
-		goto err0;
-	}
-
 	/* map memory, let mapbase point to our channel */
 	mtu->mapbase = ioremap_nocache(res->start, resource_size(res));
 	if (mtu->mapbase == NULL) {
@@ -322,10 +334,7 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
 	if (ret < 0)
 		goto err2;
 
-	mtu->channel.mtu = mtu;
-
-	ret = sh_mtu2_register(&mtu->channel, (char *)dev_name(&mtu->pdev->dev),
-			       cfg->clockevent_rating);
+	ret = sh_mtu2_setup_channel(&mtu->channel, mtu);
 	if (ret < 0)
 		goto err3;
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 41/71] clocksource: sh_mtu2: Constify name argument to sh_mtu2_register()
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (38 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 40/71] clocksource: sh_mtu2: Split channel setup to separate function Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 42/71] clocksource: sh_mtu2: Add memory base to sh_mtu2_channel structure Daniel Lezcano
                     ` (29 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

The name argument is assigned to const structure fields only, constify
it.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 8fd7059..2fe3ab4c 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -236,7 +236,7 @@ static void sh_mtu2_clock_event_resume(struct clock_event_device *ced)
 }
 
 static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
-				       char *name, unsigned long rating)
+					const char *name, unsigned long rating)
 {
 	struct clock_event_device *ced = &ch->ced;
 	int ret;
@@ -264,7 +264,7 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
 	}
 }
 
-static int sh_mtu2_register(struct sh_mtu2_channel *ch, char *name,
+static int sh_mtu2_register(struct sh_mtu2_channel *ch, const char *name,
 			    unsigned long clockevent_rating)
 {
 	if (clockevent_rating)
@@ -287,7 +287,7 @@ static int sh_mtu2_setup_channel(struct sh_mtu2_channel *ch,
 		return ch->irq;
 	}
 
-	return sh_mtu2_register(ch, (char *)dev_name(&mtu->pdev->dev),
+	return sh_mtu2_register(ch, dev_name(&mtu->pdev->dev),
 				cfg->clockevent_rating);
 }
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 42/71] clocksource: sh_mtu2: Add memory base to sh_mtu2_channel structure
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (39 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 41/71] clocksource: sh_mtu2: Constify name argument to sh_mtu2_register() Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 43/71] clocksource: sh_mtu2: Add index to struct sh_mtu2_channel Daniel Lezcano
                     ` (28 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |   32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 2fe3ab4c..97714ce 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -38,7 +38,10 @@ struct sh_mtu2_device;
 
 struct sh_mtu2_channel {
 	struct sh_mtu2_device *mtu;
+
+	void __iomem *base;
 	int irq;
+
 	struct clock_event_device ced;
 };
 
@@ -74,39 +77,35 @@ static unsigned long mtu2_reg_offs[] = {
 
 static inline unsigned long sh_mtu2_read(struct sh_mtu2_channel *ch, int reg_nr)
 {
-	struct sh_timer_config *cfg = ch->mtu->pdev->dev.platform_data;
-	void __iomem *base = ch->mtu->mapbase;
 	unsigned long offs;
 
 	if (reg_nr == TSTR)
-		return ioread8(base + cfg->channel_offset);
+		return ioread8(ch->mtu->mapbase);
 
 	offs = mtu2_reg_offs[reg_nr];
 
 	if ((reg_nr == TCNT) || (reg_nr == TGR))
-		return ioread16(base + offs);
+		return ioread16(ch->base + offs);
 	else
-		return ioread8(base + offs);
+		return ioread8(ch->base + offs);
 }
 
 static inline void sh_mtu2_write(struct sh_mtu2_channel *ch, int reg_nr,
 				unsigned long value)
 {
-	struct sh_timer_config *cfg = ch->mtu->pdev->dev.platform_data;
-	void __iomem *base = ch->mtu->mapbase;
 	unsigned long offs;
 
 	if (reg_nr == TSTR) {
-		iowrite8(value, base + cfg->channel_offset);
+		iowrite8(value, ch->mtu->mapbase);
 		return;
 	}
 
 	offs = mtu2_reg_offs[reg_nr];
 
 	if ((reg_nr == TCNT) || (reg_nr == TGR))
-		iowrite16(value, base + offs);
+		iowrite16(value, ch->base + offs);
 	else
-		iowrite8(value, base + offs);
+		iowrite8(value, ch->base + offs);
 }
 
 static void sh_mtu2_start_stop_ch(struct sh_mtu2_channel *ch, int start)
@@ -315,13 +314,18 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
 		goto err0;
 	}
 
-	/* map memory, let mapbase point to our channel */
-	mtu->mapbase = ioremap_nocache(res->start, resource_size(res));
-	if (mtu->mapbase == NULL) {
+	/*
+	 * Map memory, let channel.base point to our channel and mapbase to the
+	 * start/stop shared register.
+	 */
+	mtu->channel.base = ioremap_nocache(res->start, resource_size(res));
+	if (mtu->channel.base == NULL) {
 		dev_err(&mtu->pdev->dev, "failed to remap I/O memory\n");
 		goto err0;
 	}
 
+	mtu->mapbase = mtu->channel.base + cfg->channel_offset;
+
 	/* get hold of clock */
 	mtu->clk = clk_get(&mtu->pdev->dev, "mtu2_fck");
 	if (IS_ERR(mtu->clk)) {
@@ -344,7 +348,7 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
  err2:
 	clk_put(mtu->clk);
  err1:
-	iounmap(mtu->mapbase);
+	iounmap(mtu->channel.base);
  err0:
 	return ret;
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 43/71] clocksource: sh_mtu2: Add index to struct sh_mtu2_channel
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (40 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 42/71] clocksource: sh_mtu2: Add memory base to sh_mtu2_channel structure Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 44/71] clocksource: sh_mtu2: Replace kmalloc + memset with kzalloc Daniel Lezcano
                     ` (27 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Use the index as the timer start/stop bit and when printing messages to
identify the channel.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |   22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 97714ce..61827c6 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -38,6 +38,7 @@ struct sh_mtu2_device;
 
 struct sh_mtu2_channel {
 	struct sh_mtu2_device *mtu;
+	unsigned int index;
 
 	void __iomem *base;
 	int irq;
@@ -110,7 +111,6 @@ static inline void sh_mtu2_write(struct sh_mtu2_channel *ch, int reg_nr,
 
 static void sh_mtu2_start_stop_ch(struct sh_mtu2_channel *ch, int start)
 {
-	struct sh_timer_config *cfg = ch->mtu->pdev->dev.platform_data;
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
@@ -118,9 +118,9 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_channel *ch, int start)
 	value = sh_mtu2_read(ch, TSTR);
 
 	if (start)
-		value |= 1 << cfg->timer_bit;
+		value |= 1 << ch->index;
 	else
-		value &= ~(1 << cfg->timer_bit);
+		value &= ~(1 << ch->index);
 
 	sh_mtu2_write(ch, TSTR, value);
 	raw_spin_unlock_irqrestore(&sh_mtu2_lock, flags);
@@ -138,7 +138,8 @@ static int sh_mtu2_enable(struct sh_mtu2_channel *ch)
 	/* enable clock */
 	ret = clk_enable(ch->mtu->clk);
 	if (ret) {
-		dev_err(&ch->mtu->pdev->dev, "cannot enable clock\n");
+		dev_err(&ch->mtu->pdev->dev, "ch%u: cannot enable clock\n",
+			ch->index);
 		return ret;
 	}
 
@@ -211,7 +212,7 @@ static void sh_mtu2_clock_event_mode(enum clock_event_mode mode,
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		dev_info(&ch->mtu->pdev->dev,
-			 "used for periodic clock events\n");
+			 "ch%u: used for periodic clock events\n", ch->index);
 		sh_mtu2_enable(ch);
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
@@ -250,15 +251,16 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
 	ced->suspend = sh_mtu2_clock_event_suspend;
 	ced->resume = sh_mtu2_clock_event_resume;
 
-	dev_info(&ch->mtu->pdev->dev, "used for clock events\n");
+	dev_info(&ch->mtu->pdev->dev, "ch%u: used for clock events\n",
+		 ch->index);
 	clockevents_register_device(ced);
 
 	ret = request_irq(ch->irq, sh_mtu2_interrupt,
 			  IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING,
 			  dev_name(&ch->mtu->pdev->dev), ch);
 	if (ret) {
-		dev_err(&ch->mtu->pdev->dev, "failed to request irq %d\n",
-			ch->irq);
+		dev_err(&ch->mtu->pdev->dev, "ch%u: failed to request irq %d\n",
+			ch->index, ch->irq);
 		return;
 	}
 }
@@ -279,10 +281,12 @@ static int sh_mtu2_setup_channel(struct sh_mtu2_channel *ch,
 
 	memset(ch, 0, sizeof(*ch));
 	ch->mtu = mtu;
+	ch->index = cfg->timer_bit;
 
 	ch->irq = platform_get_irq(mtu->pdev, 0);
 	if (ch->irq < 0) {
-		dev_err(&mtu->pdev->dev, "failed to get irq\n");
+		dev_err(&mtu->pdev->dev, "ch%u: failed to get irq\n",
+			ch->index);
 		return ch->irq;
 	}
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 44/71] clocksource: sh_mtu2: Replace kmalloc + memset with kzalloc
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (41 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 43/71] clocksource: sh_mtu2: Add index to struct sh_mtu2_channel Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 45/71] clocksource: sh_mtu2: Allocate channels dynamically Daniel Lezcano
                     ` (26 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

One kzalloc a day keeps the bugs away.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |    6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 61827c6..94a5342 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -241,8 +241,6 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
 	struct clock_event_device *ced = &ch->ced;
 	int ret;
 
-	memset(ced, 0, sizeof(*ced));
-
 	ced->name = name;
 	ced->features = CLOCK_EVT_FEAT_PERIODIC;
 	ced->rating = rating;
@@ -279,7 +277,6 @@ static int sh_mtu2_setup_channel(struct sh_mtu2_channel *ch,
 {
 	struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
 
-	memset(ch, 0, sizeof(*ch));
 	ch->mtu = mtu;
 	ch->index = cfg->timer_bit;
 
@@ -302,7 +299,6 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
 	int ret;
 	ret = -ENXIO;
 
-	memset(mtu, 0, sizeof(*mtu));
 	mtu->pdev = pdev;
 
 	if (!cfg) {
@@ -373,7 +369,7 @@ static int sh_mtu2_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	mtu = kmalloc(sizeof(*mtu), GFP_KERNEL);
+	mtu = kzalloc(sizeof(*mtu), GFP_KERNEL);
 	if (mtu == NULL) {
 		dev_err(&pdev->dev, "failed to allocate driver data\n");
 		return -ENOMEM;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 45/71] clocksource: sh_mtu2: Allocate channels dynamically
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (42 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 44/71] clocksource: sh_mtu2: Replace kmalloc + memset with kzalloc Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 46/71] clocksource: sh_mtu2: Replace hardcoded register values with macros Daniel Lezcano
                     ` (25 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

This prepares the driver for multi-channel support.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |   27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 94a5342..45e1e85 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -52,7 +52,8 @@ struct sh_mtu2_device {
 	void __iomem *mapbase;
 	struct clk *clk;
 
-	struct sh_mtu2_channel channel;
+	struct sh_mtu2_channel *channels;
+	unsigned int num_channels;
 };
 
 static DEFINE_RAW_SPINLOCK(sh_mtu2_lock);
@@ -296,6 +297,7 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
 {
 	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
+	void __iomem *base;
 	int ret;
 	ret = -ENXIO;
 
@@ -315,16 +317,16 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
 	}
 
 	/*
-	 * Map memory, let channel.base point to our channel and mapbase to the
+	 * Map memory, let base point to our channel and mapbase to the
 	 * start/stop shared register.
 	 */
-	mtu->channel.base = ioremap_nocache(res->start, resource_size(res));
-	if (mtu->channel.base == NULL) {
+	base = ioremap_nocache(res->start, resource_size(res));
+	if (base == NULL) {
 		dev_err(&mtu->pdev->dev, "failed to remap I/O memory\n");
 		goto err0;
 	}
 
-	mtu->mapbase = mtu->channel.base + cfg->channel_offset;
+	mtu->mapbase = base + cfg->channel_offset;
 
 	/* get hold of clock */
 	mtu->clk = clk_get(&mtu->pdev->dev, "mtu2_fck");
@@ -338,17 +340,28 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
 	if (ret < 0)
 		goto err2;
 
-	ret = sh_mtu2_setup_channel(&mtu->channel, mtu);
+	mtu->channels = kzalloc(sizeof(*mtu->channels), GFP_KERNEL);
+	if (mtu->channels == NULL) {
+		ret = -ENOMEM;
+		goto err3;
+	}
+
+	mtu->num_channels = 1;
+
+	mtu->channels[0].base = base;
+
+	ret = sh_mtu2_setup_channel(&mtu->channels[0], mtu);
 	if (ret < 0)
 		goto err3;
 
 	return 0;
  err3:
+	kfree(mtu->channels);
 	clk_unprepare(mtu->clk);
  err2:
 	clk_put(mtu->clk);
  err1:
-	iounmap(mtu->channel.base);
+	iounmap(base);
  err0:
 	return ret;
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 46/71] clocksource: sh_mtu2: Replace hardcoded register values with macros
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (43 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 45/71] clocksource: sh_mtu2: Allocate channels dynamically Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 47/71] clocksource: sh_mtu2: Set cpumask to cpu_possible_mask Daniel Lezcano
                     ` (24 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Define symbolic macros for all used registers bits.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |   98 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 92 insertions(+), 6 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 45e1e85..2cf0048 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -67,6 +67,88 @@ static DEFINE_RAW_SPINLOCK(sh_mtu2_lock);
 #define TCNT 5 /* channel register */
 #define TGR  6 /* channel register */
 
+#define TCR_CCLR_NONE		(0 << 5)
+#define TCR_CCLR_TGRA		(1 << 5)
+#define TCR_CCLR_TGRB		(2 << 5)
+#define TCR_CCLR_SYNC		(3 << 5)
+#define TCR_CCLR_TGRC		(5 << 5)
+#define TCR_CCLR_TGRD		(6 << 5)
+#define TCR_CCLR_MASK		(7 << 5)
+#define TCR_CKEG_RISING		(0 << 3)
+#define TCR_CKEG_FALLING	(1 << 3)
+#define TCR_CKEG_BOTH		(2 << 3)
+#define TCR_CKEG_MASK		(3 << 3)
+/* Values 4 to 7 are channel-dependent */
+#define TCR_TPSC_P1		(0 << 0)
+#define TCR_TPSC_P4		(1 << 0)
+#define TCR_TPSC_P16		(2 << 0)
+#define TCR_TPSC_P64		(3 << 0)
+#define TCR_TPSC_CH0_TCLKA	(4 << 0)
+#define TCR_TPSC_CH0_TCLKB	(5 << 0)
+#define TCR_TPSC_CH0_TCLKC	(6 << 0)
+#define TCR_TPSC_CH0_TCLKD	(7 << 0)
+#define TCR_TPSC_CH1_TCLKA	(4 << 0)
+#define TCR_TPSC_CH1_TCLKB	(5 << 0)
+#define TCR_TPSC_CH1_P256	(6 << 0)
+#define TCR_TPSC_CH1_TCNT2	(7 << 0)
+#define TCR_TPSC_CH2_TCLKA	(4 << 0)
+#define TCR_TPSC_CH2_TCLKB	(5 << 0)
+#define TCR_TPSC_CH2_TCLKC	(6 << 0)
+#define TCR_TPSC_CH2_P1024	(7 << 0)
+#define TCR_TPSC_CH34_P256	(4 << 0)
+#define TCR_TPSC_CH34_P1024	(5 << 0)
+#define TCR_TPSC_CH34_TCLKA	(6 << 0)
+#define TCR_TPSC_CH34_TCLKB	(7 << 0)
+#define TCR_TPSC_MASK		(7 << 0)
+
+#define TMDR_BFE		(1 << 6)
+#define TMDR_BFB		(1 << 5)
+#define TMDR_BFA		(1 << 4)
+#define TMDR_MD_NORMAL		(0 << 0)
+#define TMDR_MD_PWM_1		(2 << 0)
+#define TMDR_MD_PWM_2		(3 << 0)
+#define TMDR_MD_PHASE_1		(4 << 0)
+#define TMDR_MD_PHASE_2		(5 << 0)
+#define TMDR_MD_PHASE_3		(6 << 0)
+#define TMDR_MD_PHASE_4		(7 << 0)
+#define TMDR_MD_PWM_SYNC	(8 << 0)
+#define TMDR_MD_PWM_COMP_CREST	(13 << 0)
+#define TMDR_MD_PWM_COMP_TROUGH	(14 << 0)
+#define TMDR_MD_PWM_COMP_BOTH	(15 << 0)
+#define TMDR_MD_MASK		(15 << 0)
+
+#define TIOC_IOCH(n)		((n) << 4)
+#define TIOC_IOCL(n)		((n) << 0)
+#define TIOR_OC_RETAIN		(0 << 0)
+#define TIOR_OC_0_CLEAR		(1 << 0)
+#define TIOR_OC_0_SET		(2 << 0)
+#define TIOR_OC_0_TOGGLE	(3 << 0)
+#define TIOR_OC_1_CLEAR		(5 << 0)
+#define TIOR_OC_1_SET		(6 << 0)
+#define TIOR_OC_1_TOGGLE	(7 << 0)
+#define TIOR_IC_RISING		(8 << 0)
+#define TIOR_IC_FALLING		(9 << 0)
+#define TIOR_IC_BOTH		(10 << 0)
+#define TIOR_IC_TCNT		(12 << 0)
+#define TIOR_MASK		(15 << 0)
+
+#define TIER_TTGE		(1 << 7)
+#define TIER_TTGE2		(1 << 6)
+#define TIER_TCIEU		(1 << 5)
+#define TIER_TCIEV		(1 << 4)
+#define TIER_TGIED		(1 << 3)
+#define TIER_TGIEC		(1 << 2)
+#define TIER_TGIEB		(1 << 1)
+#define TIER_TGIEA		(1 << 0)
+
+#define TSR_TCFD		(1 << 7)
+#define TSR_TCFU		(1 << 5)
+#define TSR_TCFV		(1 << 4)
+#define TSR_TGFD		(1 << 3)
+#define TSR_TGFC		(1 << 2)
+#define TSR_TGFB		(1 << 1)
+#define TSR_TGFA		(1 << 0)
+
 static unsigned long mtu2_reg_offs[] = {
 	[TCR] = 0,
 	[TMDR] = 1,
@@ -150,13 +232,17 @@ static int sh_mtu2_enable(struct sh_mtu2_channel *ch)
 	rate = clk_get_rate(ch->mtu->clk) / 64;
 	periodic = (rate + HZ/2) / HZ;
 
-	/* "Periodic Counter Operation" */
-	sh_mtu2_write(ch, TCR, 0x23); /* TGRA clear, divide clock by 64 */
-	sh_mtu2_write(ch, TIOR, 0);
+	/*
+	 * "Periodic Counter Operation"
+	 * Clear on TGRA compare match, divide clock by 64.
+	 */
+	sh_mtu2_write(ch, TCR, TCR_CCLR_TGRA | TCR_TPSC_P64);
+	sh_mtu2_write(ch, TIOR, TIOC_IOCH(TIOR_OC_0_CLEAR) |
+		      TIOC_IOCL(TIOR_OC_0_CLEAR));
 	sh_mtu2_write(ch, TGR, periodic);
 	sh_mtu2_write(ch, TCNT, 0);
-	sh_mtu2_write(ch, TMDR, 0);
-	sh_mtu2_write(ch, TIER, 0x01);
+	sh_mtu2_write(ch, TMDR, TMDR_MD_NORMAL);
+	sh_mtu2_write(ch, TIER, TIER_TGIEA);
 
 	/* enable channel */
 	sh_mtu2_start_stop_ch(ch, 1);
@@ -182,7 +268,7 @@ static irqreturn_t sh_mtu2_interrupt(int irq, void *dev_id)
 
 	/* acknowledge interrupt */
 	sh_mtu2_read(ch, TSR);
-	sh_mtu2_write(ch, TSR, 0xfe);
+	sh_mtu2_write(ch, TSR, ~TSR_TGFA);
 
 	/* notify clockevent layer */
 	ch->ced.event_handler(&ch->ced);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 47/71] clocksource: sh_mtu2: Set cpumask to cpu_possible_mask
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (44 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 46/71] clocksource: sh_mtu2: Replace hardcoded register values with macros Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 48/71] clocksource: sh_mtu2: Hardcode MTU2 clock event rating to 200 Daniel Lezcano
                     ` (23 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

The MTU2 is not tied to CPU0, make it usable on any CPU.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 2cf0048..702ce60 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -331,7 +331,7 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
 	ced->name = name;
 	ced->features = CLOCK_EVT_FEAT_PERIODIC;
 	ced->rating = rating;
-	ced->cpumask = cpumask_of(0);
+	ced->cpumask = cpu_possible_mask;
 	ced->set_mode = sh_mtu2_clock_event_mode;
 	ced->suspend = sh_mtu2_clock_event_suspend;
 	ced->resume = sh_mtu2_clock_event_resume;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 48/71] clocksource: sh_mtu2: Hardcode MTU2 clock event rating to 200
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (45 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 47/71] clocksource: sh_mtu2: Set cpumask to cpu_possible_mask Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 49/71] clocksource: sh_mtu2: Add support for multiple channels per device Daniel Lezcano
                     ` (22 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

All boards use clock event ratings of 200 for the MTU2, hardcode it in
the driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 702ce60..14cc7b6 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -323,14 +323,14 @@ static void sh_mtu2_clock_event_resume(struct clock_event_device *ced)
 }
 
 static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
-					const char *name, unsigned long rating)
+					const char *name)
 {
 	struct clock_event_device *ced = &ch->ced;
 	int ret;
 
 	ced->name = name;
 	ced->features = CLOCK_EVT_FEAT_PERIODIC;
-	ced->rating = rating;
+	ced->rating = 200;
 	ced->cpumask = cpu_possible_mask;
 	ced->set_mode = sh_mtu2_clock_event_mode;
 	ced->suspend = sh_mtu2_clock_event_suspend;
@@ -351,10 +351,10 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
 }
 
 static int sh_mtu2_register(struct sh_mtu2_channel *ch, const char *name,
-			    unsigned long clockevent_rating)
+			    bool clockevent)
 {
-	if (clockevent_rating)
-		sh_mtu2_register_clockevent(ch, name, clockevent_rating);
+	if (clockevent)
+		sh_mtu2_register_clockevent(ch, name);
 
 	return 0;
 }
@@ -375,7 +375,7 @@ static int sh_mtu2_setup_channel(struct sh_mtu2_channel *ch,
 	}
 
 	return sh_mtu2_register(ch, dev_name(&mtu->pdev->dev),
-				cfg->clockevent_rating);
+				cfg->clockevent_rating != 0);
 }
 
 static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 49/71] clocksource: sh_mtu2: Add support for multiple channels per device
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (46 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 48/71] clocksource: sh_mtu2: Hardcode MTU2 clock event rating to 200 Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 50/71] clocksource: sh_mtu2: Rename clock to "fck" in the non-legacy case Daniel Lezcano
                     ` (21 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

MTU2 hardware devices can support multiple channels, with global
registers and per-channel registers. The sh_mtu2 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>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |  184 +++++++++++++++++++++++++++++------------
 1 file changed, 130 insertions(+), 54 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 14cc7b6..7cc6d942 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -54,6 +54,9 @@ struct sh_mtu2_device {
 
 	struct sh_mtu2_channel *channels;
 	unsigned int num_channels;
+
+	bool legacy;
+	bool has_clockevent;
 };
 
 static DEFINE_RAW_SPINLOCK(sh_mtu2_lock);
@@ -163,8 +166,12 @@ static inline unsigned long sh_mtu2_read(struct sh_mtu2_channel *ch, int reg_nr)
 {
 	unsigned long offs;
 
-	if (reg_nr == TSTR)
-		return ioread8(ch->mtu->mapbase);
+	if (reg_nr == TSTR) {
+		if (ch->mtu->legacy)
+			return ioread8(ch->mtu->mapbase);
+		else
+			return ioread8(ch->mtu->mapbase + 0x280);
+	}
 
 	offs = mtu2_reg_offs[reg_nr];
 
@@ -180,8 +187,10 @@ static inline void sh_mtu2_write(struct sh_mtu2_channel *ch, int reg_nr,
 	unsigned long offs;
 
 	if (reg_nr == TSTR) {
-		iowrite8(value, ch->mtu->mapbase);
-		return;
+		if (ch->mtu->legacy)
+			return iowrite8(value, ch->mtu->mapbase);
+		else
+			return iowrite8(value, ch->mtu->mapbase + 0x280);
 	}
 
 	offs = mtu2_reg_offs[reg_nr];
@@ -353,109 +362,168 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_channel *ch,
 static int sh_mtu2_register(struct sh_mtu2_channel *ch, const char *name,
 			    bool clockevent)
 {
-	if (clockevent)
+	if (clockevent) {
+		ch->mtu->has_clockevent = true;
 		sh_mtu2_register_clockevent(ch, name);
+	}
 
 	return 0;
 }
 
-static int sh_mtu2_setup_channel(struct sh_mtu2_channel *ch,
+static int sh_mtu2_setup_channel(struct sh_mtu2_channel *ch, unsigned int index,
 				 struct sh_mtu2_device *mtu)
 {
-	struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
+	static const unsigned int channel_offsets[] = {
+		0x300, 0x380, 0x000,
+	};
+	bool clockevent;
 
 	ch->mtu = mtu;
-	ch->index = cfg->timer_bit;
 
-	ch->irq = platform_get_irq(mtu->pdev, 0);
+	if (mtu->legacy) {
+		struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
+
+		clockevent = cfg->clockevent_rating != 0;
+
+		ch->irq = platform_get_irq(mtu->pdev, 0);
+		ch->base = mtu->mapbase - cfg->channel_offset;
+		ch->index = cfg->timer_bit;
+	} else {
+		char name[6];
+
+		clockevent = true;
+
+		sprintf(name, "tgi%ua", index);
+		ch->irq = platform_get_irq_byname(mtu->pdev, name);
+		ch->base = mtu->mapbase + channel_offsets[index];
+		ch->index = index;
+	}
+
 	if (ch->irq < 0) {
+		/* Skip channels with no declared interrupt. */
+		if (!mtu->legacy)
+			return 0;
+
 		dev_err(&mtu->pdev->dev, "ch%u: failed to get irq\n",
 			ch->index);
 		return ch->irq;
 	}
 
-	return sh_mtu2_register(ch, dev_name(&mtu->pdev->dev),
-				cfg->clockevent_rating != 0);
+	return sh_mtu2_register(ch, dev_name(&mtu->pdev->dev), clockevent);
 }
 
-static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
-			 struct platform_device *pdev)
+static int sh_mtu2_map_memory(struct sh_mtu2_device *mtu)
 {
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
-	void __iomem *base;
-	int ret;
-	ret = -ENXIO;
-
-	mtu->pdev = pdev;
-
-	if (!cfg) {
-		dev_err(&mtu->pdev->dev, "missing platform data\n");
-		goto err0;
-	}
-
-	platform_set_drvdata(pdev, mtu);
 
 	res = platform_get_resource(mtu->pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(&mtu->pdev->dev, "failed to get I/O memory\n");
-		goto err0;
+		return -ENXIO;
 	}
 
+	mtu->mapbase = ioremap_nocache(res->start, resource_size(res));
+	if (mtu->mapbase == NULL)
+		return -ENXIO;
+
 	/*
-	 * Map memory, let base point to our channel and mapbase to the
-	 * start/stop shared register.
+	 * In legacy platform device configuration (with one device per channel)
+	 * the resource points to the channel base address.
 	 */
-	base = ioremap_nocache(res->start, resource_size(res));
-	if (base == NULL) {
-		dev_err(&mtu->pdev->dev, "failed to remap I/O memory\n");
-		goto err0;
+	if (mtu->legacy) {
+		struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
+		mtu->mapbase += cfg->channel_offset;
+	}
+
+	return 0;
+}
+
+static void sh_mtu2_unmap_memory(struct sh_mtu2_device *mtu)
+{
+	if (mtu->legacy) {
+		struct sh_timer_config *cfg = mtu->pdev->dev.platform_data;
+		mtu->mapbase -= cfg->channel_offset;
 	}
 
-	mtu->mapbase = base + cfg->channel_offset;
+	iounmap(mtu->mapbase);
+}
+
+static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
+			 struct platform_device *pdev)
+{
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	const struct platform_device_id *id = pdev->id_entry;
+	unsigned int i;
+	int ret;
+
+	mtu->pdev = pdev;
+	mtu->legacy = id->driver_data;
+
+	if (mtu->legacy && !cfg) {
+		dev_err(&mtu->pdev->dev, "missing platform data\n");
+		return -ENXIO;
+	}
 
-	/* get hold of clock */
+	/* Get hold of clock. */
 	mtu->clk = clk_get(&mtu->pdev->dev, "mtu2_fck");
 	if (IS_ERR(mtu->clk)) {
 		dev_err(&mtu->pdev->dev, "cannot get clock\n");
-		ret = PTR_ERR(mtu->clk);
-		goto err1;
+		return PTR_ERR(mtu->clk);
 	}
 
 	ret = clk_prepare(mtu->clk);
 	if (ret < 0)
-		goto err2;
+		goto err_clk_put;
 
-	mtu->channels = kzalloc(sizeof(*mtu->channels), GFP_KERNEL);
+	/* Map the memory resource. */
+	ret = sh_mtu2_map_memory(mtu);
+	if (ret < 0) {
+		dev_err(&mtu->pdev->dev, "failed to remap I/O memory\n");
+		goto err_clk_unprepare;
+	}
+
+	/* Allocate and setup the channels. */
+	if (mtu->legacy)
+		mtu->num_channels = 1;
+	else
+		mtu->num_channels = 3;
+
+	mtu->channels = kzalloc(sizeof(*mtu->channels) * mtu->num_channels,
+				GFP_KERNEL);
 	if (mtu->channels == NULL) {
 		ret = -ENOMEM;
-		goto err3;
+		goto err_unmap;
 	}
 
-	mtu->num_channels = 1;
-
-	mtu->channels[0].base = base;
+	if (mtu->legacy) {
+		ret = sh_mtu2_setup_channel(&mtu->channels[0], 0, mtu);
+		if (ret < 0)
+			goto err_unmap;
+	} else {
+		for (i = 0; i < mtu->num_channels; ++i) {
+			ret = sh_mtu2_setup_channel(&mtu->channels[i], i, mtu);
+			if (ret < 0)
+				goto err_unmap;
+		}
+	}
 
-	ret = sh_mtu2_setup_channel(&mtu->channels[0], mtu);
-	if (ret < 0)
-		goto err3;
+	platform_set_drvdata(pdev, mtu);
 
 	return 0;
- err3:
+
+err_unmap:
 	kfree(mtu->channels);
+	sh_mtu2_unmap_memory(mtu);
+err_clk_unprepare:
 	clk_unprepare(mtu->clk);
- err2:
+err_clk_put:
 	clk_put(mtu->clk);
- err1:
-	iounmap(base);
- err0:
 	return ret;
 }
 
 static int sh_mtu2_probe(struct platform_device *pdev)
 {
 	struct sh_mtu2_device *mtu = platform_get_drvdata(pdev);
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	int ret;
 
 	if (!is_early_platform_device(pdev)) {
@@ -484,7 +552,7 @@ static int sh_mtu2_probe(struct platform_device *pdev)
 		return 0;
 
  out:
-	if (cfg->clockevent_rating)
+	if (mtu->has_clockevent)
 		pm_runtime_irq_safe(&pdev->dev);
 	else
 		pm_runtime_idle(&pdev->dev);
@@ -497,12 +565,20 @@ static int sh_mtu2_remove(struct platform_device *pdev)
 	return -EBUSY; /* cannot unregister clockevent */
 }
 
+static const struct platform_device_id sh_mtu2_id_table[] = {
+	{ "sh_mtu2", 1 },
+	{ "sh-mtu2", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, sh_mtu2_id_table);
+
 static struct platform_driver sh_mtu2_device_driver = {
 	.probe		= sh_mtu2_probe,
 	.remove		= sh_mtu2_remove,
 	.driver		= {
 		.name	= "sh_mtu2",
-	}
+	},
+	.id_table	= sh_mtu2_id_table,
 };
 
 static int __init sh_mtu2_init(void)
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 50/71] clocksource: sh_mtu2: Rename clock to "fck" in the non-legacy case
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (47 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 49/71] clocksource: sh_mtu2: Add support for multiple channels per device Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 51/71] clocksource: sh_mtu2: Remove FSF mail address from GPL notice Daniel Lezcano
                     ` (20 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

The sh_mtu2 driver gets the MTU2 functional clock using a connection ID
of "mtu2_fck". While all SH SoCs create clock lookup entries with a NULL
device ID and a "mtu2_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 connection ID of "fck" in the non-legacy
platform data case. Clock lookup entries will be renamed to use the
device ID as well as the connection ID as platforms get moved to new
platform data. The legacy code will eventually be dropped, leaving us
with device ID based clock lookup, compatible with DT boot.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 7cc6d942..3a37857 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -465,7 +465,7 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
 	}
 
 	/* Get hold of clock. */
-	mtu->clk = clk_get(&mtu->pdev->dev, "mtu2_fck");
+	mtu->clk = clk_get(&mtu->pdev->dev, mtu->legacy ? "mtu2_fck" : "fck");
 	if (IS_ERR(mtu->clk)) {
 		dev_err(&mtu->pdev->dev, "cannot get clock\n");
 		return PTR_ERR(mtu->clk);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 51/71] clocksource: sh_mtu2: Remove FSF mail address from GPL notice
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (48 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 50/71] clocksource: sh_mtu2: Rename clock to "fck" in the non-legacy case Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 52/71] clocksource: sh_mtu2: Sort headers alphabetically Daniel Lezcano
                     ` (19 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

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>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |    4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 3a37857..510bd32 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.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.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 52/71] clocksource: sh_mtu2: Sort headers alphabetically
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (49 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 51/71] clocksource: sh_mtu2: Remove FSF mail address from GPL notice Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 53/71] clocksource: arm_global_timer: Only check for unusable timer on A9 Daniel Lezcano
                     ` (18 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

This helps locating duplicates and inserting new headers.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Wolfram Sang <wsa@sang-engineering.com>
---
 drivers/clocksource/sh_mtu2.c |   18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 510bd32..f2c1c36 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -13,22 +13,22 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk.h>
+#include <linux/clockchips.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/delay.h>
 #include <linux/io.h>
-#include <linux/clk.h>
+#include <linux/ioport.h>
 #include <linux/irq.h>
-#include <linux/err.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_mtu2_device;
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 53/71] clocksource: arm_global_timer: Only check for unusable timer on A9
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (50 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 52/71] clocksource: sh_mtu2: Sort headers alphabetically Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 54/71] documentaion: DT: allow a A5 compatible string in global timer Daniel Lezcano
                     ` (17 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Matthew Leach <matthew.leach@arm.com>

The check for a usable global timer in the probe code does not enquire
which CPU we are currently running on. This can cause the driver to
incorrectly assume we have an unusable global timer if we are running
on a CPU other than A9.

Before checking the CPU revision, ensure we are running on an A9 CPU.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Matthew Leach <matthew.leach@arm.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/arm_global_timer.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
index 0fc31d0..60e5a170 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -246,11 +246,12 @@ static void __init global_timer_of_register(struct device_node *np)
 	int err = 0;
 
 	/*
-	 * In r2p0 the comparators for each processor with the global timer
+	 * In A9 r2p0 the comparators for each processor with the global timer
 	 * fire when the timer value is greater than or equal to. In previous
 	 * revisions the comparators fired when the timer value was equal to.
 	 */
-	if ((read_cpuid_id() & 0xf0000f) < 0x200000) {
+	if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9
+	    && (read_cpuid_id() & 0xf0000f) < 0x200000) {
 		pr_warn("global-timer: non support for this cpu version.\n");
 		return;
 	}
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 54/71] documentaion: DT: allow a A5 compatible string in global timer
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (51 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 53/71] clocksource: arm_global_timer: Only check for unusable timer on A9 Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 55/71] dts: ca5: add the global timer for the A5 Daniel Lezcano
                     ` (16 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Matthew Leach <matthew.leach@arm.com>

The global timer is present on the Cortex A5. Add a compatibility
string to the DT binding to allow a Cortex A5 global timer.

Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Matthew Leach <matthew.leach@arm.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 .../devicetree/bindings/arm/global_timer.txt       |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/global_timer.txt b/Documentation/devicetree/bindings/arm/global_timer.txt
index 1e54898..bdae3a8 100644
--- a/Documentation/devicetree/bindings/arm/global_timer.txt
+++ b/Documentation/devicetree/bindings/arm/global_timer.txt
@@ -4,8 +4,11 @@
 
 ** Timer node required properties:
 
-- compatible : Should be "arm,cortex-a9-global-timer"
-		Driver supports versions r2p0 and above.
+- compatible : should contain
+	     * "arm,cortex-a5-global-timer" for Cortex-A5 global timers.
+	     * "arm,cortex-a9-global-timer" for Cortex-A9 global
+	         timers or any compatible implementation. Note: driver
+	         supports versions r2p0 and above.
 
 - interrupts : One interrupt to each core
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 55/71] dts: ca5: add the global timer for the A5
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (52 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 54/71] documentaion: DT: allow a A5 compatible string in global timer Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 56/71] KConfig: Vexpress: build the ARM_GLOBAL_TIMER with vexpress platform Daniel Lezcano
                     ` (15 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Matthew Leach <matthew.leach@arm.com>

The Cortex A5 contains a global timer: add the appropriate device tree
node.

Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Matthew Leach <matthew.leach@arm.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 arch/arm/boot/dts/vexpress-v2p-ca5s.dts |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
index c544a55..d2709b7 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
@@ -88,6 +88,14 @@
 		interrupts = <1 13 0x304>;
 	};
 
+	timer at 2c000200 {
+		compatible = "arm,cortex-a5-global-timer",
+		             "arm,cortex-a9-global-timer";
+		reg = <0x2c000200 0x20>;
+		interrupts = <1 11 0x304>;
+		clocks = <&oscclk0>;
+	};
+
 	watchdog at 2c000620 {
 		compatible = "arm,cortex-a5-twd-wdt";
 		reg = <0x2c000620 0x20>;
@@ -120,7 +128,7 @@
 		compatible = "arm,vexpress,config-bus";
 		arm,vexpress,config-bridge = <&v2m_sysreg>;
 
-		osc at 0 {
+		oscclk0: osc at 0 {
 			/* CPU and internal AXI reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 0>;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 56/71] KConfig: Vexpress: build the ARM_GLOBAL_TIMER with vexpress platform
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (53 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 55/71] dts: ca5: add the global timer for the A5 Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 57/71] clocksource: efm32: use $vendor, $device scheme for compatible string Daniel Lezcano
                     ` (14 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Matthew Leach <matthew.leach@arm.com>

The Cortex A5 now contains bindings for the global timer
driver. Ensure that the driver is built with a vexpress platform.

Signed-off-by: Matthew Leach <matthew.leach@arm.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 arch/arm/mach-vexpress/Kconfig |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 657d52d..e9811a0 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -4,6 +4,7 @@ config ARCH_VEXPRESS
 	select ARCH_SUPPORTS_BIG_ENDIAN
 	select ARM_AMBA
 	select ARM_GIC
+	select ARM_GLOBAL_TIMER
 	select ARM_TIMER_SP804
 	select COMMON_CLK_VERSATILE
 	select HAVE_ARM_SCU if SMP
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 57/71] clocksource: efm32: use $vendor, $device scheme for compatible string
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (54 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 56/71] KConfig: Vexpress: build the ARM_GLOBAL_TIMER with vexpress platform Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 58/71] clocksource: sun5i: Add support for reset controller Daniel Lezcano
                     ` (13 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>

Wolfram Sang pointed out that "efm32,$device" is non-standard. So use the
common scheme and prefix device with "efm32-". The old compatible string
is left in place until arch/arm/boot/dts/efm32* is fixed.

Acked-by: Wolfram Sang <wsa@the-dreams.de>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 .../devicetree/bindings/timer/efm32,timer.txt      |   23 --------------------
 .../bindings/timer/energymicro,efm32-timer.txt     |   23 ++++++++++++++++++++
 drivers/clocksource/time-efm32.c                   |    3 ++-
 3 files changed, 25 insertions(+), 24 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/timer/efm32,timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/energymicro,efm32-timer.txt

diff --git a/Documentation/devicetree/bindings/timer/efm32,timer.txt b/Documentation/devicetree/bindings/timer/efm32,timer.txt
deleted file mode 100644
index 97a568f..0000000
--- a/Documentation/devicetree/bindings/timer/efm32,timer.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-* EFM32 timer hardware
-
-The efm32 Giant Gecko SoCs come with four 16 bit timers. Two counters can be
-connected to form a 32 bit counter. Each timer has three Compare/Capture
-channels and can be used as PWM or Quadrature Decoder. Available clock sources
-are the cpu's HFPERCLK (with a 10-bit prescaler) or an external pin.
-
-Required properties:
-- compatible : Should be efm32,timer
-- reg : Address and length of the register set
-- clocks : Should contain a reference to the HFPERCLK
-
-Optional properties:
-- interrupts : Reference to the timer interrupt
-
-Example:
-
-timer at 40010c00 {
-	compatible = "efm32,timer";
-	reg = <0x40010c00 0x400>;
-	interrupts = <14>;
-	clocks = <&cmu clk_HFPERCLKTIMER3>;
-};
diff --git a/Documentation/devicetree/bindings/timer/energymicro,efm32-timer.txt b/Documentation/devicetree/bindings/timer/energymicro,efm32-timer.txt
new file mode 100644
index 0000000..e502c11
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/energymicro,efm32-timer.txt
@@ -0,0 +1,23 @@
+* EFM32 timer hardware
+
+The efm32 Giant Gecko SoCs come with four 16 bit timers. Two counters can be
+connected to form a 32 bit counter. Each timer has three Compare/Capture
+channels and can be used as PWM or Quadrature Decoder. Available clock sources
+are the cpu's HFPERCLK (with a 10-bit prescaler) or an external pin.
+
+Required properties:
+- compatible : Should be "energymicro,efm32-timer"
+- reg : Address and length of the register set
+- clocks : Should contain a reference to the HFPERCLK
+
+Optional properties:
+- interrupts : Reference to the timer interrupt
+
+Example:
+
+timer at 40010c00 {
+	compatible = "energymicro,efm32-timer";
+	reg = <0x40010c00 0x400>;
+	interrupts = <14>;
+	clocks = <&cmu clk_HFPERCLKTIMER3>;
+};
diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c
index 1a6205b..bba62f9 100644
--- a/drivers/clocksource/time-efm32.c
+++ b/drivers/clocksource/time-efm32.c
@@ -272,4 +272,5 @@ static void __init efm32_timer_init(struct device_node *np)
 		}
 	}
 }
-CLOCKSOURCE_OF_DECLARE(efm32, "efm32,timer", efm32_timer_init);
+CLOCKSOURCE_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init);
+CLOCKSOURCE_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 58/71] clocksource: sun5i: Add support for reset controller
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (55 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 57/71] clocksource: efm32: use $vendor, $device scheme for compatible string Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 59/71] ARM: sun6i: a31: Add support for the High Speed Timers Daniel Lezcano
                     ` (12 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Maxime Ripard <maxime.ripard@free-electrons.com>

The Allwinner A31 that uses this timer has the timer IP asserted in reset.
Add an optional reset property to the DT, and deassert the timer from reset if
it's there.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 .../bindings/timer/allwinner,sun5i-a13-hstimer.txt |    4 ++++
 drivers/clocksource/timer-sun5i.c                  |    6 ++++++
 2 files changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
index 7c26154..27cfc7d 100644
--- a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
+++ b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
@@ -9,6 +9,9 @@ Required properties:
 		one)
 - clocks: phandle to the source clock (usually the AHB clock)
 
+Optionnal properties:
+- resets: phandle to a reset controller asserting the timer
+
 Example:
 
 timer at 01c60000 {
@@ -19,4 +22,5 @@ timer at 01c60000 {
 		     <0 53 1>,
 		     <0 54 1>;
 	clocks = <&ahb1_gates 19>;
+	resets = <&ahb1rst 19>;
 };
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c
index deebcd6..0226844 100644
--- a/drivers/clocksource/timer-sun5i.c
+++ b/drivers/clocksource/timer-sun5i.c
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqreturn.h>
+#include <linux/reset.h>
 #include <linux/sched_clock.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -143,6 +144,7 @@ static u64 sun5i_timer_sched_read(void)
 
 static void __init sun5i_timer_init(struct device_node *node)
 {
+	struct reset_control *rstc;
 	unsigned long rate;
 	struct clk *clk;
 	int ret, irq;
@@ -162,6 +164,10 @@ static void __init sun5i_timer_init(struct device_node *node)
 	clk_prepare_enable(clk);
 	rate = clk_get_rate(clk);
 
+	rstc = of_reset_control_get(node, NULL);
+	if (!IS_ERR(rstc))
+		reset_control_deassert(rstc);
+
 	writel(~0, timer_base + TIMER_INTVAL_LO_REG(1));
 	writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
 	       timer_base + TIMER_CTL_REG(1));
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 59/71] ARM: sun6i: a31: Add support for the High Speed Timers
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (56 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 58/71] clocksource: sun5i: Add support for reset controller Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 60/71] clocksource: qcom: Implement read_current_timer for udelay Daniel Lezcano
                     ` (11 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Maxime Ripard <maxime.ripard@free-electrons.com>

The Allwinner A31 has support for four high speed timers. Apart for the
number of timers (4 vs 2), it's basically the same logic than the high
speed timers found in the sun5i chips.

Now that we have a driver to support it, we can enable them in the
device tree.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 arch/arm/boot/dts/sun6i-a31.dtsi |   11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index d45efa7..8cee8a1 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -428,6 +428,17 @@
 			status = "disabled";
 		};
 
+		timer at 01c60000 {
+			compatible = "allwinner,sun6i-a31-hstimer", "allwinner,sun7i-a20-hstimer";
+			reg = <0x01c60000 0x1000>;
+			interrupts = <0 51 4>,
+				     <0 52 4>,
+				     <0 53 4>,
+				     <0 54 4>;
+			clocks = <&ahb1_gates 19>;
+			resets = <&ahb1_rst 19>;
+		};
+
 		spi0: spi at 01c68000 {
 			compatible = "allwinner,sun6i-a31-spi";
 			reg = <0x01c68000 0x1000>;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 60/71] clocksource: qcom: Implement read_current_timer for udelay
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (57 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 59/71] ARM: sun6i: a31: Add support for the High Speed Timers Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 61/71] clocksource: sh_tmu: Fix channel IRQ retrieval in legacy case Daniel Lezcano
                     ` (10 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Stephen Boyd <sboyd@codeaurora.org>

Setup the same timer used as the clocksource to be used as the
read_current_timer implementation. This allows us to support a
stable udelay implementation on MSMs where it's possible for the
CPUs to scale speeds independently of one another.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/qcom-timer.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c
index e807acf..8d115db 100644
--- a/drivers/clocksource/qcom-timer.c
+++ b/drivers/clocksource/qcom-timer.c
@@ -26,6 +26,8 @@
 #include <linux/of_irq.h>
 #include <linux/sched_clock.h>
 
+#include <asm/delay.h>
+
 #define TIMER_MATCH_VAL			0x0000
 #define TIMER_COUNT_VAL			0x0004
 #define TIMER_ENABLE			0x0008
@@ -179,6 +181,15 @@ static u64 notrace msm_sched_clock_read(void)
 	return msm_clocksource.read(&msm_clocksource);
 }
 
+static unsigned long msm_read_current_timer(void)
+{
+	return msm_clocksource.read(&msm_clocksource);
+}
+
+static struct delay_timer msm_delay_timer = {
+	.read_current_timer = msm_read_current_timer,
+};
+
 static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
 				  bool percpu)
 {
@@ -217,6 +228,8 @@ err:
 	if (res)
 		pr_err("clocksource_register failed\n");
 	sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz);
+	msm_delay_timer.freq = dgt_hz;
+	register_current_timer_delay(&msm_delay_timer);
 }
 
 #ifdef CONFIG_ARCH_QCOM
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 61/71] clocksource: sh_tmu: Fix channel IRQ retrieval in legacy case
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (58 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 60/71] clocksource: qcom: Implement read_current_timer for udelay Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 62/71] clocksource: Fix type confusion for clocksource_mmio_readX_Y Daniel Lezcano
                     ` (9 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

In the legacy platform data case each TMU platform device handles a
single channel with a single IRQ for the platform device. Retrieve the
IRQ using the logical channel number instead of the hardware channel
number.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/sh_tmu.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 4ba2c0f..ec34095 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -498,7 +498,7 @@ static int sh_tmu_channel_setup(struct sh_tmu_channel *ch, unsigned int index,
 			ch->base = tmu->mapbase + 8 + ch->index * 12;
 	}
 
-	ch->irq = platform_get_irq(tmu->pdev, ch->index);
+	ch->irq = platform_get_irq(tmu->pdev, index);
 	if (ch->irq < 0) {
 		dev_err(&tmu->pdev->dev, "ch%u: failed to get irq\n",
 			ch->index);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 62/71] clocksource: Fix type confusion for clocksource_mmio_readX_Y
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (59 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 61/71] clocksource: sh_tmu: Fix channel IRQ retrieval in legacy case Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 63/71] clocksource: Fix clocksource_mmio_readX_down Daniel Lezcano
                     ` (8 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Xiubo Li <Li.Xiubo@freescale.com>

The types' definations are:
   o  cycle_t       -> u64
   o  readl_relaxed -> u32
   o  readw_relaxed -> u16

So let clocksource_mmio_readX_Ys return a cast to cycle_t, though
this maybe look reduntant sometimes, it make sense and they will be
more readable and less confusion...

This patch clarifies the functions type and fix it.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/mmio.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/clocksource/mmio.c b/drivers/clocksource/mmio.c
index c0e2512..19a6b3f 100644
--- a/drivers/clocksource/mmio.c
+++ b/drivers/clocksource/mmio.c
@@ -22,22 +22,22 @@ static inline struct clocksource_mmio *to_mmio_clksrc(struct clocksource *c)
 
 cycle_t clocksource_mmio_readl_up(struct clocksource *c)
 {
-	return readl_relaxed(to_mmio_clksrc(c)->reg);
+	return (cycle_t)readl_relaxed(to_mmio_clksrc(c)->reg);
 }
 
 cycle_t clocksource_mmio_readl_down(struct clocksource *c)
 {
-	return ~readl_relaxed(to_mmio_clksrc(c)->reg);
+	return ~(cycle_t)readl_relaxed(to_mmio_clksrc(c)->reg);
 }
 
 cycle_t clocksource_mmio_readw_up(struct clocksource *c)
 {
-	return readw_relaxed(to_mmio_clksrc(c)->reg);
+	return (cycle_t)readw_relaxed(to_mmio_clksrc(c)->reg);
 }
 
 cycle_t clocksource_mmio_readw_down(struct clocksource *c)
 {
-	return ~(unsigned)readw_relaxed(to_mmio_clksrc(c)->reg);
+	return ~(cycle_t)readw_relaxed(to_mmio_clksrc(c)->reg);
 }
 
 /**
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 63/71] clocksource: Fix clocksource_mmio_readX_down
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (60 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 62/71] clocksource: Fix type confusion for clocksource_mmio_readX_Y Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 64/71] clocksource: dw_apb_timer_of: Do not trace read_sched_clock Daniel Lezcano
                     ` (7 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Xiubo Li <Li.Xiubo@freescale.com>

For some clocksource devices, for example, the registers are 32-bit, while
the lower 16-bit is used for timer counting(And reading the upper 16-bit
will return 0).

For example, when the counter value is 0x00001111, and then the
~readl_relaxed(to_mmio_clksrc(c)->reg) will return the value of 0xFFFFEEEE,
but it should be 0x0000EEEE.

So just using the c->mask to mask the unused bits.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/mmio.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clocksource/mmio.c b/drivers/clocksource/mmio.c
index 19a6b3f..1593ade 100644
--- a/drivers/clocksource/mmio.c
+++ b/drivers/clocksource/mmio.c
@@ -27,7 +27,7 @@ cycle_t clocksource_mmio_readl_up(struct clocksource *c)
 
 cycle_t clocksource_mmio_readl_down(struct clocksource *c)
 {
-	return ~(cycle_t)readl_relaxed(to_mmio_clksrc(c)->reg);
+	return ~(cycle_t)readl_relaxed(to_mmio_clksrc(c)->reg) & c->mask;
 }
 
 cycle_t clocksource_mmio_readw_up(struct clocksource *c)
@@ -37,7 +37,7 @@ cycle_t clocksource_mmio_readw_up(struct clocksource *c)
 
 cycle_t clocksource_mmio_readw_down(struct clocksource *c)
 {
-	return ~(cycle_t)readw_relaxed(to_mmio_clksrc(c)->reg);
+	return ~(cycle_t)readw_relaxed(to_mmio_clksrc(c)->reg) & c->mask;
 }
 
 /**
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 64/71] clocksource: dw_apb_timer_of: Do not trace read_sched_clock
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (61 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 63/71] clocksource: Fix clocksource_mmio_readX_down Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 65/71] clocksource: em_sti: Remove unnecessary OOM messages Daniel Lezcano
                     ` (6 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Yang Wei <Wei.Yang@windriver.com>

We do not need to trace read_sched_clock function,
so add notrace attribute for this function.

Signed-off-by: Yang Wei <Wei.Yang@windriver.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/dw_apb_timer_of.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index 2a2ea27..d305fb0 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
+++ b/drivers/clocksource/dw_apb_timer_of.c
@@ -106,7 +106,7 @@ static void __init add_clocksource(struct device_node *source_timer)
 	sched_rate = rate;
 }
 
-static u64 read_sched_clock(void)
+static u64 notrace read_sched_clock(void)
 {
 	return ~__raw_readl(sched_io_base);
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 65/71] clocksource: em_sti: Remove unnecessary OOM messages
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (62 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 64/71] clocksource: dw_apb_timer_of: Do not trace read_sched_clock Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 66/71] clocksource: sh_cmt: " Daniel Lezcano
                     ` (5 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jingoo Han <jg1.han@samsung.com>

The site-specific OOM messages are unnecessary, because they
duplicate the MM subsystem generic OOM message.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/em_sti.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c
index 9d17083..d0a7bd6 100644
--- a/drivers/clocksource/em_sti.c
+++ b/drivers/clocksource/em_sti.c
@@ -318,10 +318,8 @@ static int em_sti_probe(struct platform_device *pdev)
 	int irq;
 
 	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
-	if (p == NULL) {
-		dev_err(&pdev->dev, "failed to allocate driver data\n");
+	if (p == NULL)
 		return -ENOMEM;
-	}
 
 	p->pdev = pdev;
 	platform_set_drvdata(pdev, p);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 66/71] clocksource: sh_cmt: Remove unnecessary OOM messages
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (63 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 65/71] clocksource: em_sti: Remove unnecessary OOM messages Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 67/71] clocksource: sh_mtu2: " Daniel Lezcano
                     ` (4 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jingoo Han <jg1.han@samsung.com>

The site-specific OOM messages are unnecessary, because they
duplicate the MM subsystem generic OOM message.

[dlezcano] : refreshed against latest modifications: kmalloc -> kzalloc

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/sh_cmt.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index bc8d025..dfa7803 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -1106,10 +1106,8 @@ static int sh_cmt_probe(struct platform_device *pdev)
 	}
 
 	cmt = kzalloc(sizeof(*cmt), GFP_KERNEL);
-	if (cmt == NULL) {
-		dev_err(&pdev->dev, "failed to allocate driver data\n");
+	if (cmt == NULL)
 		return -ENOMEM;
-	}
 
 	ret = sh_cmt_setup(cmt, pdev);
 	if (ret) {
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 67/71] clocksource: sh_mtu2: Remove unnecessary OOM messages
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (64 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 66/71] clocksource: sh_cmt: " Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 68/71] clocksource: sh_tmu: " Daniel Lezcano
                     ` (3 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jingoo Han <jg1.han@samsung.com>

The site-specific OOM messages are unnecessary, because they
duplicate the MM subsystem generic OOM message.

[dlezcano] : refreshed against latest modifications: kmalloc -> kzalloc

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/sh_mtu2.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index f2c1c36..188d4e0 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -533,10 +533,8 @@ static int sh_mtu2_probe(struct platform_device *pdev)
 	}
 
 	mtu = kzalloc(sizeof(*mtu), GFP_KERNEL);
-	if (mtu == NULL) {
-		dev_err(&pdev->dev, "failed to allocate driver data\n");
+	if (mtu == NULL)
 		return -ENOMEM;
-	}
 
 	ret = sh_mtu2_setup(mtu, pdev);
 	if (ret) {
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 68/71] clocksource: sh_tmu: Remove unnecessary OOM messages
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (65 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 67/71] clocksource: sh_mtu2: " Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 69/71] clocksource: ftm: Add FlexTimer Module (FTM) Timer devicetree Documentation Daniel Lezcano
                     ` (2 subsequent siblings)
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jingoo Han <jg1.han@samsung.com>

The site-specific OOM messages are unnecessary, because they
duplicate the MM subsystem generic OOM message.

[dlezcano] : refreshed against latest modifications: kmalloc -> kzalloc

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/sh_tmu.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 4ba2c0f..a38022f 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -644,10 +644,8 @@ static int sh_tmu_probe(struct platform_device *pdev)
 	}
 
 	tmu = kzalloc(sizeof(*tmu), GFP_KERNEL);
-	if (tmu == NULL) {
-		dev_err(&pdev->dev, "failed to allocate driver data\n");
+	if (tmu == NULL)
 		return -ENOMEM;
-	}
 
 	ret = sh_tmu_setup(tmu, pdev);
 	if (ret) {
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 69/71] clocksource: ftm: Add FlexTimer Module (FTM) Timer devicetree Documentation
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (66 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 68/71] clocksource: sh_tmu: " Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 70/71] ARM: dts: vf610: Add Freescale FlexTimer Module timer node Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 71/71] clocksource: Add Freescale FlexTimer Module (FTM) timer support Daniel Lezcano
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Xiubo Li <Li.Xiubo@freescale.com>

The FTM binding could be used on Vybrid and LS1+, add a binding
document for it.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Jingchang Lu <b35083@freescale.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 .../devicetree/bindings/timer/fsl,ftm-timer.txt    |   31 ++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/fsl,ftm-timer.txt

diff --git a/Documentation/devicetree/bindings/timer/fsl,ftm-timer.txt b/Documentation/devicetree/bindings/timer/fsl,ftm-timer.txt
new file mode 100644
index 0000000..aa8c402
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/fsl,ftm-timer.txt
@@ -0,0 +1,31 @@
+Freescale FlexTimer Module (FTM) Timer
+
+Required properties:
+
+- compatible : should be "fsl,ftm-timer"
+- reg : Specifies base physical address and size of the register sets for the
+  clock event device and clock source device.
+- interrupts : Should be the clock event device interrupt.
+- clocks : The clocks provided by the SoC to drive the timer, must contain an
+  entry for each entry in clock-names.
+- clock-names : Must include the following entries:
+  o "ftm-evt"
+  o "ftm-src"
+  o "ftm-evt-counter-en"
+  o "ftm-src-counter-en"
+- big-endian: One boolean property, the big endian mode will be in use if it is
+  present, or the little endian mode will be in use for all the device registers.
+
+Example:
+ftm: ftm at 400b8000 {
+	compatible = "fsl,ftm-timer";
+	reg = <0x400b8000 0x1000 0x400b9000 0x1000>;
+	interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
+	clock-names = "ftm-evt", "ftm-src",
+		"ftm-evt-counter-en", "ftm-src-counter-en";
+	clocks = <&clks VF610_CLK_FTM2>,
+		<&clks VF610_CLK_FTM3>,
+		<&clks VF610_CLK_FTM2_EXT_FIX_EN>,
+		<&clks VF610_CLK_FTM3_EXT_FIX_EN>;
+	big-endian;
+};
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 70/71] ARM: dts: vf610: Add Freescale FlexTimer Module timer node.
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (67 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 69/71] clocksource: ftm: Add FlexTimer Module (FTM) Timer devicetree Documentation Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  2014-05-23 10:31   ` [PATCH 71/71] clocksource: Add Freescale FlexTimer Module (FTM) timer support Daniel Lezcano
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Xiubo Li <Li.Xiubo@freescale.com>

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Jingchang Lu <b35083@freescale.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 arch/arm/boot/dts/vf610.dtsi |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index b8ce0aa7..3c91b84 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -347,6 +347,19 @@
 				status = "disabled";
 			};
 
+			ftm: ftm at 400b8000 {
+				compatible = "fsl,ftm-timer";
+				reg = <0x400b8000 0x1000 0x400b9000 0x1000>;
+				interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
+				clock-names = "ftm-evt", "ftm-src",
+					"ftm-evt-counter-en", "ftm-src-counter-en";
+				clocks = <&clks VF610_CLK_FTM2>,
+					<&clks VF610_CLK_FTM3>,
+					<&clks VF610_CLK_FTM2_EXT_FIX_EN>,
+					<&clks VF610_CLK_FTM3_EXT_FIX_EN>;
+				status = "disabled";
+			};
+
 			fec0: ethernet at 400d0000 {
 				compatible = "fsl,mvf600-fec";
 				reg = <0x400d0000 0x1000>;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 71/71] clocksource: Add Freescale FlexTimer Module (FTM) timer support
  2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
                     ` (68 preceding siblings ...)
  2014-05-23 10:31   ` [PATCH 70/71] ARM: dts: vf610: Add Freescale FlexTimer Module timer node Daniel Lezcano
@ 2014-05-23 10:31   ` Daniel Lezcano
  69 siblings, 0 replies; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-23 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Xiubo Li <Li.Xiubo@freescale.com>

The Freescale FlexTimer Module time reference is a 16-bit counter
that can be used as an unsigned or signed increase counter.

CNTIN defines the starting value of the count and MOD defines the
final value of the count. The value of CNTIN is loaded into the FTM
counter, and the counter increments until the value of MOD is reached,
at which point the counter is reloaded with the value of CNTIN. That's
also when an overflow interrupt will be generated.

Here using the 'evt' prefix or postfix as clock event device and
the 'src' as clock source device.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Jingchang Lu <b35083@freescale.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/clocksource/Kconfig         |    5 +
 drivers/clocksource/Makefile        |    1 +
 drivers/clocksource/fsl_ftm_timer.c |  367 +++++++++++++++++++++++++++++++++++
 3 files changed, 373 insertions(+)
 create mode 100644 drivers/clocksource/fsl_ftm_timer.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 96918e1..0437767 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -136,6 +136,11 @@ config CLKSRC_SAMSUNG_PWM
 	  for all devicetree enabled platforms. This driver will be
 	  needed only on systems that do not have the Exynos MCT available.
 
+config FSL_FTM_TIMER
+	bool
+	help
+	  Support for Freescale FlexTimer Module (FTM) timer.
+
 config VF_PIT_TIMER
 	bool
 	help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 98cb6c5..0770916 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_CADENCE_TTC_TIMER)	+= cadence_ttc_timer.o
 obj-$(CONFIG_CLKSRC_EFM32)	+= time-efm32.o
 obj-$(CONFIG_CLKSRC_EXYNOS_MCT)	+= exynos_mct.o
 obj-$(CONFIG_CLKSRC_SAMSUNG_PWM)	+= samsung_pwm_timer.o
+obj-$(CONFIG_FSL_FTM_TIMER)	+= fsl_ftm_timer.o
 obj-$(CONFIG_VF_PIT_TIMER)	+= vf_pit_timer.o
 obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
 
diff --git a/drivers/clocksource/fsl_ftm_timer.c b/drivers/clocksource/fsl_ftm_timer.c
new file mode 100644
index 0000000..454227d
--- /dev/null
+++ b/drivers/clocksource/fsl_ftm_timer.c
@@ -0,0 +1,367 @@
+/*
+ * Freescale FlexTimer Module (FTM) timer driver.
+ *
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+#include <linux/slab.h>
+
+#define FTM_SC		0x00
+#define FTM_SC_CLK_SHIFT	3
+#define FTM_SC_CLK_MASK	(0x3 << FTM_SC_CLK_SHIFT)
+#define FTM_SC_CLK(c)	((c) << FTM_SC_CLK_SHIFT)
+#define FTM_SC_PS_MASK	0x7
+#define FTM_SC_TOIE	BIT(6)
+#define FTM_SC_TOF	BIT(7)
+
+#define FTM_CNT		0x04
+#define FTM_MOD		0x08
+#define FTM_CNTIN	0x4C
+
+#define FTM_PS_MAX	7
+
+struct ftm_clock_device {
+	void __iomem *clksrc_base;
+	void __iomem *clkevt_base;
+	unsigned long periodic_cyc;
+	unsigned long ps;
+	bool big_endian;
+};
+
+static struct ftm_clock_device *priv;
+
+static inline u32 ftm_readl(void __iomem *addr)
+{
+	if (priv->big_endian)
+		return ioread32be(addr);
+	else
+		return ioread32(addr);
+}
+
+static inline void ftm_writel(u32 val, void __iomem *addr)
+{
+	if (priv->big_endian)
+		iowrite32be(val, addr);
+	else
+		iowrite32(val, addr);
+}
+
+static inline void ftm_counter_enable(void __iomem *base)
+{
+	u32 val;
+
+	/* select and enable counter clock source */
+	val = ftm_readl(base + FTM_SC);
+	val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK);
+	val |= priv->ps | FTM_SC_CLK(1);
+	ftm_writel(val, base + FTM_SC);
+}
+
+static inline void ftm_counter_disable(void __iomem *base)
+{
+	u32 val;
+
+	/* disable counter clock source */
+	val = ftm_readl(base + FTM_SC);
+	val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK);
+	ftm_writel(val, base + FTM_SC);
+}
+
+static inline void ftm_irq_acknowledge(void __iomem *base)
+{
+	u32 val;
+
+	val = ftm_readl(base + FTM_SC);
+	val &= ~FTM_SC_TOF;
+	ftm_writel(val, base + FTM_SC);
+}
+
+static inline void ftm_irq_enable(void __iomem *base)
+{
+	u32 val;
+
+	val = ftm_readl(base + FTM_SC);
+	val |= FTM_SC_TOIE;
+	ftm_writel(val, base + FTM_SC);
+}
+
+static inline void ftm_irq_disable(void __iomem *base)
+{
+	u32 val;
+
+	val = ftm_readl(base + FTM_SC);
+	val &= ~FTM_SC_TOIE;
+	ftm_writel(val, base + FTM_SC);
+}
+
+static inline void ftm_reset_counter(void __iomem *base)
+{
+	/*
+	 * The CNT register contains the FTM counter value.
+	 * Reset clears the CNT register. Writing any value to COUNT
+	 * updates the counter with its initial value, CNTIN.
+	 */
+	ftm_writel(0x00, base + FTM_CNT);
+}
+
+static u64 ftm_read_sched_clock(void)
+{
+	return ftm_readl(priv->clksrc_base + FTM_CNT);
+}
+
+static int ftm_set_next_event(unsigned long delta,
+				struct clock_event_device *unused)
+{
+	/*
+	 * The CNNIN and MOD are all double buffer registers, writing
+	 * to the MOD register latches the value into a buffer. The MOD
+	 * register is updated with the value of its write buffer with
+	 * the following scenario:
+	 * a, the counter source clock is diabled.
+	 */
+	ftm_counter_disable(priv->clkevt_base);
+
+	/* Force the value of CNTIN to be loaded into the FTM counter */
+	ftm_reset_counter(priv->clkevt_base);
+
+	/*
+	 * The counter increments until the value of MOD is reached,
+	 * at which point the counter is reloaded with the value of CNTIN.
+	 * The TOF (the overflow flag) bit is set when the FTM counter
+	 * changes from MOD to CNTIN. So we should using the delta - 1.
+	 */
+	ftm_writel(delta - 1, priv->clkevt_base + FTM_MOD);
+
+	ftm_counter_enable(priv->clkevt_base);
+
+	ftm_irq_enable(priv->clkevt_base);
+
+	return 0;
+}
+
+static void ftm_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		ftm_set_next_event(priv->periodic_cyc, evt);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		ftm_counter_disable(priv->clkevt_base);
+		break;
+	default:
+		return;
+	}
+}
+
+static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	ftm_irq_acknowledge(priv->clkevt_base);
+
+	if (likely(evt->mode == CLOCK_EVT_MODE_ONESHOT)) {
+		ftm_irq_disable(priv->clkevt_base);
+		ftm_counter_disable(priv->clkevt_base);
+	}
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct clock_event_device ftm_clockevent = {
+	.name		= "Freescale ftm timer",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode	= ftm_set_mode,
+	.set_next_event	= ftm_set_next_event,
+	.rating		= 300,
+};
+
+static struct irqaction ftm_timer_irq = {
+	.name		= "Freescale ftm timer",
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= ftm_evt_interrupt,
+	.dev_id		= &ftm_clockevent,
+};
+
+static int __init ftm_clockevent_init(unsigned long freq, int irq)
+{
+	int err;
+
+	ftm_writel(0x00, priv->clkevt_base + FTM_CNTIN);
+	ftm_writel(~0UL, priv->clkevt_base + FTM_MOD);
+
+	ftm_reset_counter(priv->clkevt_base);
+
+	err = setup_irq(irq, &ftm_timer_irq);
+	if (err) {
+		pr_err("ftm: setup irq failed: %d\n", err);
+		return err;
+	}
+
+	ftm_clockevent.cpumask = cpumask_of(0);
+	ftm_clockevent.irq = irq;
+
+	clockevents_config_and_register(&ftm_clockevent,
+					freq / (1 << priv->ps),
+					1, 0xffff);
+
+	ftm_counter_enable(priv->clkevt_base);
+
+	return 0;
+}
+
+static int __init ftm_clocksource_init(unsigned long freq)
+{
+	int err;
+
+	ftm_writel(0x00, priv->clksrc_base + FTM_CNTIN);
+	ftm_writel(~0UL, priv->clksrc_base + FTM_MOD);
+
+	ftm_reset_counter(priv->clksrc_base);
+
+	sched_clock_register(ftm_read_sched_clock, 16, freq / (1 << priv->ps));
+	err = clocksource_mmio_init(priv->clksrc_base + FTM_CNT, "fsl-ftm",
+				    freq / (1 << priv->ps), 300, 16,
+				    clocksource_mmio_readl_up);
+	if (err) {
+		pr_err("ftm: init clock source mmio failed: %d\n", err);
+		return err;
+	}
+
+	ftm_counter_enable(priv->clksrc_base);
+
+	return 0;
+}
+
+static int __init __ftm_clk_init(struct device_node *np, char *cnt_name,
+				 char *ftm_name)
+{
+	struct clk *clk;
+	int err;
+
+	clk = of_clk_get_by_name(np, cnt_name);
+	if (IS_ERR(clk)) {
+		pr_err("ftm: Cannot get \"%s\": %ld\n", cnt_name, PTR_ERR(clk));
+		return PTR_ERR(clk);
+	}
+	err = clk_prepare_enable(clk);
+	if (err) {
+		pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n",
+			cnt_name, err);
+		return err;
+	}
+
+	clk = of_clk_get_by_name(np, ftm_name);
+	if (IS_ERR(clk)) {
+		pr_err("ftm: Cannot get \"%s\": %ld\n", ftm_name, PTR_ERR(clk));
+		return PTR_ERR(clk);
+	}
+	err = clk_prepare_enable(clk);
+	if (err)
+		pr_err("ftm: clock failed to prepare+enable \"%s\": %d\n",
+			ftm_name, err);
+
+	return clk_get_rate(clk);
+}
+
+static unsigned long __init ftm_clk_init(struct device_node *np)
+{
+	unsigned long freq;
+
+	freq = __ftm_clk_init(np, "ftm-evt-counter-en", "ftm-evt");
+	if (freq <= 0)
+		return 0;
+
+	freq = __ftm_clk_init(np, "ftm-src-counter-en", "ftm-src");
+	if (freq <= 0)
+		return 0;
+
+	return freq;
+}
+
+static int __init ftm_calc_closest_round_cyc(unsigned long freq)
+{
+	priv->ps = 0;
+
+	/* The counter register is only using the lower 16 bits, and
+	 * if the 'freq' value is to big here, then the periodic_cyc
+	 * may exceed 0xFFFF.
+	 */
+	do {
+		priv->periodic_cyc = DIV_ROUND_CLOSEST(freq,
+						HZ * (1 << priv->ps++));
+	} while (priv->periodic_cyc > 0xFFFF);
+
+	if (priv->ps > FTM_PS_MAX) {
+		pr_err("ftm: the prescaler is %lu > %d\n",
+				priv->ps, FTM_PS_MAX);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void __init ftm_timer_init(struct device_node *np)
+{
+	unsigned long freq;
+	int irq;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return;
+
+	priv->clkevt_base = of_iomap(np, 0);
+	if (!priv->clkevt_base) {
+		pr_err("ftm: unable to map event timer registers\n");
+		goto err;
+	}
+
+	priv->clksrc_base = of_iomap(np, 1);
+	if (!priv->clksrc_base) {
+		pr_err("ftm: unable to map source timer registers\n");
+		goto err;
+	}
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (irq <= 0) {
+		pr_err("ftm: unable to get IRQ from DT, %d\n", irq);
+		goto err;
+	}
+
+	priv->big_endian = of_property_read_bool(np, "big-endian");
+
+	freq = ftm_clk_init(np);
+	if (!freq)
+		goto err;
+
+	if (ftm_calc_closest_round_cyc(freq))
+		goto err;
+
+	if (ftm_clocksource_init(freq))
+		goto err;
+
+	if (ftm_clockevent_init(freq, irq))
+		goto err;
+
+	return;
+
+err:
+	kfree(priv);
+}
+CLOCKSOURCE_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [GIT PULL] clockevents: new material for 3.16
       [not found] ` <20140526194512.032c6630@canb.auug.org.au>
@ 2014-05-26  9:52   ` Daniel Lezcano
  2014-05-26 13:40     ` Maxime Ripard
  0 siblings, 1 reply; 75+ messages in thread
From: Daniel Lezcano @ 2014-05-26  9:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/26/2014 11:45 AM, Stephen Rothwell wrote:
> Hi all,
>
> On Fri, 23 May 2014 12:22:04 +0200 Daniel Lezcano <daniel.lezcano@linaro.org> wrote:
>>
>>         clocksource: sun5i: Add support for reset controller
>
> This commit caused a build failure on arm in linux-next today ...

Thanks Stephen.

Maxime ?


-- 
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [GIT PULL] clockevents: new material for 3.16
  2014-05-26  9:52   ` [GIT PULL] clockevents: new material for 3.16 Daniel Lezcano
@ 2014-05-26 13:40     ` Maxime Ripard
  2014-05-26 15:07       ` Philipp Zabel
  0 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2014-05-26 13:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, May 26, 2014 at 11:52:25AM +0200, Daniel Lezcano wrote:
> On 05/26/2014 11:45 AM, Stephen Rothwell wrote:
> >Hi all,
> >
> >On Fri, 23 May 2014 12:22:04 +0200 Daniel Lezcano <daniel.lezcano@linaro.org> wrote:
> >>
> >>        clocksource: sun5i: Add support for reset controller
> >
> >This commit caused a build failure on arm in linux-next today ...

It's weird... of_reset_control_get has been merged in 3.15 by this
commit fc0a5921561c71be2c334a335c1680f7930434d7 ("reset: Add
of_reset_control_get"), and then the commit
b424080a9e086e683ad5fdc624a7cf3c024e0c0f ("reset: Add optional resets
and stubs") removed it, still in 3.15 (probably a mismerge).

Finally, Hans de Goede introduced it back in the following patch:
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-April/246738.html

That should have shown up in one of 3.15-rc's according to:
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-April/252317.html

Philipp, what's going on?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140526/3d498f0f/attachment.sig>

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [GIT PULL] clockevents: new material for 3.16
  2014-05-26 13:40     ` Maxime Ripard
@ 2014-05-26 15:07       ` Philipp Zabel
  0 siblings, 0 replies; 75+ messages in thread
From: Philipp Zabel @ 2014-05-26 15:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Maxime,

Am Montag, den 26.05.2014, 15:40 +0200 schrieb Maxime Ripard:
> On Mon, May 26, 2014 at 11:52:25AM +0200, Daniel Lezcano wrote:
> > On 05/26/2014 11:45 AM, Stephen Rothwell wrote:
> > >Hi all,
> > >
> > >On Fri, 23 May 2014 12:22:04 +0200 Daniel Lezcano <daniel.lezcano@linaro.org> wrote:
> > >>
> > >>        clocksource: sun5i: Add support for reset controller
> > >
> > >This commit caused a build failure on arm in linux-next today ...
> 
> It's weird... of_reset_control_get has been merged in 3.15 by this
> commit fc0a5921561c71be2c334a335c1680f7930434d7 ("reset: Add
> of_reset_control_get"), and then the commit
> b424080a9e086e683ad5fdc624a7cf3c024e0c0f ("reset: Add optional resets
> and stubs") removed it, still in 3.15 (probably a mismerge).
> 
> Finally, Hans de Goede introduced it back in the following patch:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-April/246738.html
> 
> That should have shown up in one of 3.15-rc's according to:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-April/252317.html
> 
> Philipp, what's going on?

I have sent a pull request now.

regards
Philipp

^ permalink raw reply	[flat|nested] 75+ messages in thread

end of thread, other threads:[~2014-05-26 15:07 UTC | newest]

Thread overview: 75+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-23 10:22 [GIT PULL] clockevents: new material for 3.16 Daniel Lezcano
2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
2014-05-23 10:30   ` [PATCH 02/71] clocksource: sh_cmt: Split channel fields from sh_cmt_priv Daniel Lezcano
2014-05-23 10:30   ` [PATCH 03/71] clocksource: sh_cmt: Rename struct sh_cmt_priv to sh_cmt_device Daniel Lezcano
2014-05-23 10:30   ` [PATCH 04/71] clocksource: sh_cmt: Split channel setup to separate function Daniel Lezcano
2014-05-23 10:30   ` [PATCH 05/71] clocksource: sh_cmt: Constify name argument to sh_cmt_register() Daniel Lezcano
2014-05-23 10:30   ` [PATCH 06/71] clocksource: sh_cmt: Rename mapbase/mapbase_str to mapbase_ch/mapbase Daniel Lezcano
2014-05-23 10:30   ` [PATCH 07/71] clocksource: sh_cmt: Add memory base to sh_cmt_channel structure Daniel Lezcano
2014-05-23 10:30   ` [PATCH 08/71] clocksource: sh_cmt: Add index to struct sh_cmt_channel Daniel Lezcano
2014-05-23 10:30   ` [PATCH 09/71] clocksource: sh_cmt: Replace kmalloc + memset with kzalloc Daniel Lezcano
2014-05-23 10:30   ` [PATCH 10/71] clocksource: sh_cmt: Allocate channels dynamically Daniel Lezcano
2014-05-23 10:30   ` [PATCH 11/71] clocksource: sh_cmt: Split static information from sh_cmt_device Daniel Lezcano
2014-05-23 10:30   ` [PATCH 12/71] clocksource: sh_cmt: Replace hardcoded register values with macros Daniel Lezcano
2014-05-23 10:30   ` [PATCH 13/71] clocksource: sh_cmt: Set cpumask to cpu_possible_mask Daniel Lezcano
2014-05-23 10:30   ` [PATCH 14/71] clocksource: sh_cmt: Hardcode CMT clock event rating to 125 Daniel Lezcano
2014-05-23 10:30   ` [PATCH 15/71] clocksource: sh_cmt: Hardcode CMT clock source " Daniel Lezcano
2014-05-23 10:30   ` [PATCH 16/71] clocksource: sh_cmt: Add support for multiple channels per device Daniel Lezcano
2014-05-23 10:30   ` [PATCH 17/71] clocksource: sh_cmt: Rename clock to "fck" in the non-legacy case Daniel Lezcano
2014-05-23 10:30   ` [PATCH 18/71] clocksource: sh_cmt: Remove FSF mail address from GPL notice Daniel Lezcano
2014-05-23 10:30   ` [PATCH 19/71] clocksource: sh_cmt: Sort headers alphabetically Daniel Lezcano
2014-05-23 10:31   ` [PATCH 20/71] clocksource: sh_cmt: Request IRQ for clock event device only Daniel Lezcano
2014-05-23 10:31   ` [PATCH 21/71] clocksource: sh_tmu: Use request_irq() instead of setup_irq() Daniel Lezcano
2014-05-23 10:31   ` [PATCH 22/71] clocksource: sh_tmu: Split channel fields from sh_tmu_priv Daniel Lezcano
2014-05-23 10:31   ` [PATCH 23/71] clocksource: sh_tmu: Rename struct sh_tmu_priv to sh_tmu_device Daniel Lezcano
2014-05-23 10:31   ` [PATCH 24/71] clocksource: sh_tmu: Split channel setup to separate function Daniel Lezcano
2014-05-23 10:31   ` [PATCH 25/71] clocksource: sh_tmu: Constify name argument to sh_tmu_register() Daniel Lezcano
2014-05-23 10:31   ` [PATCH 26/71] clocksource: sh_tmu: Add memory base to sh_tmu_channel structure Daniel Lezcano
2014-05-23 10:31   ` [PATCH 27/71] clocksource: sh_tmu: Add index to struct sh_tmu_channel Daniel Lezcano
2014-05-23 10:31   ` [PATCH 28/71] clocksource: sh_tmu: Replace kmalloc + memset with kzalloc Daniel Lezcano
2014-05-23 10:31   ` [PATCH 29/71] clocksource: sh_tmu: Allocate channels dynamically Daniel Lezcano
2014-05-23 10:31   ` [PATCH 30/71] clocksource: sh_tmu: Replace hardcoded register values with macros Daniel Lezcano
2014-05-23 10:31   ` [PATCH 31/71] clocksource: sh_tmu: Hardcode TMU clock event and source ratings to 200 Daniel Lezcano
2014-05-23 10:31   ` [PATCH 32/71] clocksource: sh_tmu: Add support for multiple channels per device Daniel Lezcano
2014-05-23 10:31   ` [PATCH 33/71] clocksource: sh_tmu: Rename clock to "fck" in the non-legacy case Daniel Lezcano
2014-05-23 10:31   ` [PATCH 34/71] clocksource: sh_tmu: Remove FSF mail address from GPL notice Daniel Lezcano
2014-05-23 10:31   ` [PATCH 35/71] clocksource: sh_tmu: Sort headers alphabetically Daniel Lezcano
2014-05-23 10:31   ` [PATCH 36/71] clocksource: sh_mtu2: Use request_irq() instead of setup_irq() Daniel Lezcano
2014-05-23 10:31   ` [PATCH 37/71] clocksource: sh_mtu2: Turn sh_mtu2_priv fields into local variables Daniel Lezcano
2014-05-23 10:31   ` [PATCH 38/71] clocksource: sh_mtu2: Split channel fields from sh_mtu2_priv Daniel Lezcano
2014-05-23 10:31   ` [PATCH 39/71] clocksource: sh_mtu2: Rename struct sh_mtu2_priv to sh_mtu2_device Daniel Lezcano
2014-05-23 10:31   ` [PATCH 40/71] clocksource: sh_mtu2: Split channel setup to separate function Daniel Lezcano
2014-05-23 10:31   ` [PATCH 41/71] clocksource: sh_mtu2: Constify name argument to sh_mtu2_register() Daniel Lezcano
2014-05-23 10:31   ` [PATCH 42/71] clocksource: sh_mtu2: Add memory base to sh_mtu2_channel structure Daniel Lezcano
2014-05-23 10:31   ` [PATCH 43/71] clocksource: sh_mtu2: Add index to struct sh_mtu2_channel Daniel Lezcano
2014-05-23 10:31   ` [PATCH 44/71] clocksource: sh_mtu2: Replace kmalloc + memset with kzalloc Daniel Lezcano
2014-05-23 10:31   ` [PATCH 45/71] clocksource: sh_mtu2: Allocate channels dynamically Daniel Lezcano
2014-05-23 10:31   ` [PATCH 46/71] clocksource: sh_mtu2: Replace hardcoded register values with macros Daniel Lezcano
2014-05-23 10:31   ` [PATCH 47/71] clocksource: sh_mtu2: Set cpumask to cpu_possible_mask Daniel Lezcano
2014-05-23 10:31   ` [PATCH 48/71] clocksource: sh_mtu2: Hardcode MTU2 clock event rating to 200 Daniel Lezcano
2014-05-23 10:31   ` [PATCH 49/71] clocksource: sh_mtu2: Add support for multiple channels per device Daniel Lezcano
2014-05-23 10:31   ` [PATCH 50/71] clocksource: sh_mtu2: Rename clock to "fck" in the non-legacy case Daniel Lezcano
2014-05-23 10:31   ` [PATCH 51/71] clocksource: sh_mtu2: Remove FSF mail address from GPL notice Daniel Lezcano
2014-05-23 10:31   ` [PATCH 52/71] clocksource: sh_mtu2: Sort headers alphabetically Daniel Lezcano
2014-05-23 10:31   ` [PATCH 53/71] clocksource: arm_global_timer: Only check for unusable timer on A9 Daniel Lezcano
2014-05-23 10:31   ` [PATCH 54/71] documentaion: DT: allow a A5 compatible string in global timer Daniel Lezcano
2014-05-23 10:31   ` [PATCH 55/71] dts: ca5: add the global timer for the A5 Daniel Lezcano
2014-05-23 10:31   ` [PATCH 56/71] KConfig: Vexpress: build the ARM_GLOBAL_TIMER with vexpress platform Daniel Lezcano
2014-05-23 10:31   ` [PATCH 57/71] clocksource: efm32: use $vendor, $device scheme for compatible string Daniel Lezcano
2014-05-23 10:31   ` [PATCH 58/71] clocksource: sun5i: Add support for reset controller Daniel Lezcano
2014-05-23 10:31   ` [PATCH 59/71] ARM: sun6i: a31: Add support for the High Speed Timers Daniel Lezcano
2014-05-23 10:31   ` [PATCH 60/71] clocksource: qcom: Implement read_current_timer for udelay Daniel Lezcano
2014-05-23 10:31   ` [PATCH 61/71] clocksource: sh_tmu: Fix channel IRQ retrieval in legacy case Daniel Lezcano
2014-05-23 10:31   ` [PATCH 62/71] clocksource: Fix type confusion for clocksource_mmio_readX_Y Daniel Lezcano
2014-05-23 10:31   ` [PATCH 63/71] clocksource: Fix clocksource_mmio_readX_down Daniel Lezcano
2014-05-23 10:31   ` [PATCH 64/71] clocksource: dw_apb_timer_of: Do not trace read_sched_clock Daniel Lezcano
2014-05-23 10:31   ` [PATCH 65/71] clocksource: em_sti: Remove unnecessary OOM messages Daniel Lezcano
2014-05-23 10:31   ` [PATCH 66/71] clocksource: sh_cmt: " Daniel Lezcano
2014-05-23 10:31   ` [PATCH 67/71] clocksource: sh_mtu2: " Daniel Lezcano
2014-05-23 10:31   ` [PATCH 68/71] clocksource: sh_tmu: " Daniel Lezcano
2014-05-23 10:31   ` [PATCH 69/71] clocksource: ftm: Add FlexTimer Module (FTM) Timer devicetree Documentation Daniel Lezcano
2014-05-23 10:31   ` [PATCH 70/71] ARM: dts: vf610: Add Freescale FlexTimer Module timer node Daniel Lezcano
2014-05-23 10:31   ` [PATCH 71/71] clocksource: Add Freescale FlexTimer Module (FTM) timer support Daniel Lezcano
     [not found] ` <20140526194512.032c6630@canb.auug.org.au>
2014-05-26  9:52   ` [GIT PULL] clockevents: new material for 3.16 Daniel Lezcano
2014-05-26 13:40     ` Maxime Ripard
2014-05-26 15:07       ` Philipp Zabel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).