Skip to contentSkip to conversation

clocksource: sh_cmt: CMT driver update

PATCH In review Magnus Damm 4 participants 12 messages Dec 14, 2012 – Feb 13, 2013

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover clocksource: sh_cmt: CMT driver update

clocksource: sh_cmt: CMT driver update

[PATCH 01/08] clocksource: sh_cmt: Take care of clk_put() when setup_irq() fails [PATCH 02/08] clocksource: sh_cmt: Initialize 'max_match_value' and 'lock' in sh_cmt_setup() [PATCH 03/08] clocksource: sh_cmt: Consolidate platform_set_drvdata() call [PATCH 04/08] clocksource: sh_cmt: Introduce per-register functions
[PATCH 05/08] clocksource: sh_cmt: CMSTR and CMCSR register access update [PATCH 06/08] clocksource: sh_cmt: CMCNT and CMCOR register access update [PATCH 07/08] clocksource: sh_cmt: Add control register callbacks
[PATCH 08/08] clocksource: sh_cmt: Add CMT register layout comment

This patch series contains a couple of driver updates from Kuribayashi-san together with some register access changes from me. The register access changes work towards adding support for 32-bit only CMT hardware, but the final bits are not yet included in this series due to lack of hardware.

Patches 1-3:

Patches 4-8:

---

 drivers/clocksource/sh_cmt.c |  257 ++++++++++++++++++++++++------------------
 1 file changed, 152 insertions(+), 105 deletions(-)
#1 lore raw

PATCH 1/8 clocksource: sh_cmt: Take care of clk_put() when setup_irq() fails

From: Magnus Damm <[email protected]>

Make sure clk_put() is called in case of failure in sh_cmt_setup().

---

 drivers/clocksource/sh_cmt.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/clocksource/sh_cmt.c +4 -2
@@ -708,17 +708,19 @@ static int sh_cmt_setup(struct sh_cmt_pr
 			      cfg->clocksource_rating);
 	if (ret) {
 		dev_err(&p->pdev->dev, "registration failed\n");
-		goto err1;
+		goto err2;
 	}
 	p->cs_enabled = false;
 
 	ret = setup_irq(irq, &p->irqaction);
 	if (ret) {
 		dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
-		goto err1;
+		goto err2;
 	}
 
 	return 0;
+err2:
+	clk_put(p->clk);
 
 err1:
 	iounmap(p->mapbase);
#2 lore raw

PATCH 2/8 clocksource: sh_cmt: Initialize 'max_match_value' and 'lock' in sh_cmt_setup()

In reply to Magnus Damm

From: Magnus Damm <[email protected]>

Move the setup of spinlock and max_match_value to sh_cmt_setup(). There's no need to defer those steps until sh_cmt_register().

---

 drivers/clocksource/sh_cmt.c |   16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
drivers/clocksource/sh_cmt.c +8 -8
@@ -625,14 +625,6 @@ static int sh_cmt_register(struct sh_cmt
 			   unsigned long clockevent_rating,
 			   unsigned long clocksource_rating)
 {
-	if (p->width == (sizeof(p->max_match_value) * 8))
-		p->max_match_value = ~0;
-	else
-		p->max_match_value = (1 << p->width) - 1;
-
-	p->match_value = p->max_match_value;
-	raw_spin_lock_init(&p->lock);
-
 	if (clockevent_rating)
 		sh_cmt_register_clockevent(p, name, clockevent_rating);
 
@@ -703,6 +695,14 @@ static int sh_cmt_setup(struct sh_cmt_pr
 		p->clear_bits = ~0xc000;
 	}
 
+	if (p->width == (sizeof(p->max_match_value) * 8))
+		p->max_match_value = ~0;
+	else
+		p->max_match_value = (1 << p->width) - 1;
+
+	p->match_value = p->max_match_value;
+	raw_spin_lock_init(&p->lock);
+
 	ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev),
 			      cfg->clockevent_rating,
 			      cfg->clocksource_rating);
#3 lore raw

PATCH 3/8 clocksource: sh_cmt: Consolidate platform_set_drvdata() call

In reply to Magnus Damm

From: Magnus Damm <[email protected]>

Cleanup the use of platform_set_drvdata() to reduce code size

---

 drivers/clocksource/sh_cmt.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/clocksource/sh_cmt.c +2 -3
@@ -649,8 +649,6 @@ static int sh_cmt_setup(struct sh_cmt_pr
 		goto err0;
 	}
 
-	platform_set_drvdata(pdev, p);
-
 	res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(&p->pdev->dev, "failed to get I/O memory\n");
@@ -718,6 +716,8 @@ static int sh_cmt_setup(struct sh_cmt_pr
 		goto err2;
 	}
 
+	platform_set_drvdata(pdev, p);
+
 	return 0;
 err2:
 	clk_put(p->clk);
@@ -753,7 +753,6 @@ static int __devinit sh_cmt_probe(struct
 	ret = sh_cmt_setup(p, pdev);
 	if (ret) {
 		kfree(p);
-		platform_set_drvdata(pdev, NULL);
 		pm_runtime_idle(&pdev->dev);
 		return ret;
 	}
#4 lore raw

PATCH 4/8 clocksource: sh_cmt: Introduce per-register functions

In reply to Magnus Damm

From: Magnus Damm <[email protected]>

Introduce sh_cmt_read_cmstr/cmcsr/cmcnt() and sh_cmt_write_cmstr/cmcsr/cmcnt/cmcor() to in the future allow us to split counter registers from control registers and reduce code complexity by removing sh_cmt_read() and sh_cmt_write().

---

 drivers/clocksource/sh_cmt.c |   71 ++++++++++++++++++++++++++++++++----------
 1 file changed, 55 insertions(+), 16 deletions(-)
drivers/clocksource/sh_cmt.c +55 -16
@@ -86,6 +86,21 @@ static inline unsigned long sh_cmt_read(
 	return ioread16(base + offs);
 }
 
+static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
+{
+	return sh_cmt_read(p, CMSTR);
+}
+
+static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
+{
+	return sh_cmt_read(p, CMCSR);
+}
+
+static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
+{
+	return sh_cmt_read(p, CMCNT);
+}
+
 static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
 				unsigned long value)
 {
@@ -112,21 +127,45 @@ static inline void sh_cmt_write(struct s
 	iowrite16(value, base + offs);
 }
 
+static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
+				      unsigned long value)
+{
+	sh_cmt_write(p, CMSTR, value);
+}
+
+static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
+				      unsigned long value)
+{
+	sh_cmt_write(p, CMCSR, value);
+}
+
+static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p,
+				      unsigned long value)
+{
+	sh_cmt_write(p, CMCNT, value);
+}
+
+static inline void sh_cmt_write_cmcor(struct sh_cmt_priv *p,
+				      unsigned long value)
+{
+	sh_cmt_write(p, CMCOR, value);
+}
+
 static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
 					int *has_wrapped)
 {
 	unsigned long v1, v2, v3;
 	int o1, o2;
 
-	o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+	o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit;
 
 	/* Make sure the timer value is stable. Stolen from acpi_pm.c */
 	do {
 		o2 = o1;
-		v1 = sh_cmt_read(p, CMCNT);
-		v2 = sh_cmt_read(p, CMCNT);
-		v3 = sh_cmt_read(p, CMCNT);
-		o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+		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;
 	} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
 			  || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
 
@@ -142,14 +181,14 @@ static void sh_cmt_start_stop_ch(struct
 
 	/* start stop register shared by multiple timer channels */
 	raw_spin_lock_irqsave(&sh_cmt_lock, flags);
-	value = sh_cmt_read(p, CMSTR);
+	value = sh_cmt_read_cmstr(p);
 
 	if (start)
 		value |= 1 << cfg->timer_bit;
 	else
 		value &= ~(1 << cfg->timer_bit);
 
-	sh_cmt_write(p, CMSTR, value);
+	sh_cmt_write_cmstr(p, value);
 	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
 }
 
@@ -173,14 +212,14 @@ static int sh_cmt_enable(struct sh_cmt_p
 	/* configure channel, periodic mode and maximum timeout */
 	if (p->width == 16) {
 		*rate = clk_get_rate(p->clk) / 512;
-		sh_cmt_write(p, CMCSR, 0x43);
+		sh_cmt_write_cmcsr(p, 0x43);
 	} else {
 		*rate = clk_get_rate(p->clk) / 8;
-		sh_cmt_write(p, CMCSR, 0x01a4);
+		sh_cmt_write_cmcsr(p, 0x01a4);
 	}
 
-	sh_cmt_write(p, CMCOR, 0xffffffff);
-	sh_cmt_write(p, CMCNT, 0);
+	sh_cmt_write_cmcor(p, 0xffffffff);
+	sh_cmt_write_cmcnt(p, 0);
 
 	/*
 	 * According to the sh73a0 user's manual, as CMCNT can be operated
@@ -194,12 +233,12 @@ static int sh_cmt_enable(struct sh_cmt_p
 	 * take RCLKx2 at maximum.
 	 */
 	for (k = 0; k < 100; k++) {
-		if (!sh_cmt_read(p, CMCNT))
+		if (!sh_cmt_read_cmcnt(p))
 			break;
 		udelay(1);
 	}
 
-	if (sh_cmt_read(p, CMCNT)) {
+	if (sh_cmt_read_cmcnt(p)) {
 		dev_err(&p->pdev->dev, "cannot clear CMCNT\n");
 		ret = -ETIMEDOUT;
 		goto err1;
@@ -222,7 +261,7 @@ static void sh_cmt_disable(struct sh_cmt
 	sh_cmt_start_stop_ch(p, 0);
 
 	/* disable interrupts in CMT block */
-	sh_cmt_write(p, CMCSR, 0);
+	sh_cmt_write_cmcsr(p, 0);
 
 	/* stop clock */
 	clk_disable(p->clk);
@@ -270,7 +309,7 @@ static void sh_cmt_clock_event_program_v
 		if (new_match > p->max_match_value)
 			new_match = p->max_match_value;
 
-		sh_cmt_write(p, CMCOR, new_match);
+		sh_cmt_write_cmcor(p, new_match);
 
 		now = sh_cmt_get_counter(p, &has_wrapped);
 		if (has_wrapped && (new_match > p->match_value)) {
@@ -346,7 +385,7 @@ static irqreturn_t sh_cmt_interrupt(int
 	struct sh_cmt_priv *p = dev_id;
 
 	/* clear flags */
-	sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits);
+	sh_cmt_write_cmcsr(p, sh_cmt_read_cmcsr(p) & p->clear_bits);
 
 	/* update clock source counter to begin with if enabled
 	 * the wrap flag should be cleared by the timer specific
#5 lore raw

PATCH 5/8 clocksource: sh_cmt: CMSTR and CMCSR register access update

In reply to Magnus Damm

From: Magnus Damm <[email protected]>

Update hardware register access code for CMSTR and CMCSR from using sh_cmt_read() and sh_cmt_write() to make use of 16-bit register access functions such as sh_cmt_read16() and sh_cmt_write16(). Also update sh_cmt_read() and sh_cmt_write() now when the special cases are gone.

This patch moves us one step closer to the goal of separating counter register access functions from control control register functions.

---

 drivers/clocksource/sh_cmt.c |   66 +++++++++++++++++++-----------------------
 1 file changed, 30 insertions(+), 36 deletions(-)
drivers/clocksource/sh_cmt.c +30 -36
@@ -56,44 +56,46 @@ struct sh_cmt_priv {
 	bool cs_enabled;
 };
 
-static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
+static inline unsigned long sh_cmt_read16(void __iomem *base,
+					  unsigned long offs)
+{
+	return ioread16(base + (offs << 1));
+}
+
+static inline void sh_cmt_write16(void __iomem *base, unsigned long offs,
+				  unsigned long value)
+{
+	iowrite16(value, base + (offs << 1));
+}
 
-#define CMSTR -1 /* shared register */
 #define CMCSR 0 /* channel register */
 #define CMCNT 1 /* channel register */
 #define CMCOR 2 /* channel register */
 
 static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	void __iomem *base = p->mapbase;
-	unsigned long offs;
+	unsigned long offs = reg_nr;
 
-	if (reg_nr == CMSTR) {
-		offs = 0;
-		base -= cfg->channel_offset;
-	} else
-		offs = reg_nr;
-
-	if (p->width == 16)
+	if (p->width == 16) {
 		offs <<= 1;
-	else {
+		return ioread16(base + offs);
+	} else {
 		offs <<= 2;
-		if ((reg_nr == CMCNT) || (reg_nr == CMCOR))
-			return ioread32(base + offs);
+		return ioread32(base + offs);
 	}
-
-	return ioread16(base + offs);
 }
 
 static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
 {
-	return sh_cmt_read(p, CMSTR);
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+
+	return sh_cmt_read16(p->mapbase - cfg->channel_offset, 0);
 }
 
 static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
 {
-	return sh_cmt_read(p, CMCSR);
+	return sh_cmt_read16(p->mapbase, CMCSR);
 }
 
 static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
@@ -104,39 +106,30 @@ static inline unsigned long sh_cmt_read_
 static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
 				unsigned long value)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	void __iomem *base = p->mapbase;
-	unsigned long offs;
-
-	if (reg_nr == CMSTR) {
-		offs = 0;
-		base -= cfg->channel_offset;
-	} else
-		offs = reg_nr;
+	unsigned long offs = reg_nr;
 
-	if (p->width == 16)
+	if (p->width == 16) {
 		offs <<= 1;
-	else {
+		iowrite16(value, base + offs);
+	} else {
 		offs <<= 2;
-		if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) {
-			iowrite32(value, base + offs);
-			return;
-		}
+		iowrite32(value, base + offs);
 	}
-
-	iowrite16(value, base + offs);
 }
 
 static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
 				      unsigned long value)
 {
-	sh_cmt_write(p, CMSTR, value);
+	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
+
+	sh_cmt_write16(p->mapbase - cfg->channel_offset, 0, value);
 }
 
 static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
 				      unsigned long value)
 {
-	sh_cmt_write(p, CMCSR, value);
+	sh_cmt_write16(p->mapbase, CMCSR, value);
 }
 
 static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p,
@@ -173,6 +166,7 @@ static unsigned long sh_cmt_get_counter(
 	return v2;
 }
 
+static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
 
 static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
 {
#6 lore raw

PATCH 6/8 clocksource: sh_cmt: CMCNT and CMCOR register access update

In reply to Magnus Damm

From: Magnus Damm <[email protected]>

Break out the CMCNT and CMCOR register access code into separate 16-bit and 32-bit functions that are hooked into callbacks at init time. This reduces the amount of software calculations happening at runtime.

---

 drivers/clocksource/sh_cmt.c |   62 +++++++++++++++++-------------------------
 1 file changed, 26 insertions(+), 36 deletions(-)
drivers/clocksource/sh_cmt.c +26 -36
@@ -54,38 +54,39 @@ struct sh_cmt_priv {
 	struct clocksource cs;
 	unsigned long total_cycles;
 	bool cs_enabled;
+
+	/* 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);
 };
 
-static inline unsigned long sh_cmt_read16(void __iomem *base,
-					  unsigned long offs)
+static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
 {
 	return ioread16(base + (offs << 1));
 }
 
-static inline void sh_cmt_write16(void __iomem *base, unsigned long offs,
-				  unsigned long value)
+static unsigned long sh_cmt_read32(void __iomem *base, unsigned long offs)
+{
+	return ioread32(base + (offs << 2));
+}
+
+static void sh_cmt_write16(void __iomem *base, unsigned long offs,
+			   unsigned long value)
 {
 	iowrite16(value, base + (offs << 1));
 }
 
+static void sh_cmt_write32(void __iomem *base, unsigned long offs,
+			   unsigned long value)
+{
+	iowrite32(value, base + (offs << 2));
+}
+
 #define CMCSR 0 /* channel register */
 #define CMCNT 1 /* channel register */
 #define CMCOR 2 /* channel register */
 
-static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
-{
-	void __iomem *base = p->mapbase;
-	unsigned long offs = reg_nr;
-
-	if (p->width == 16) {
-		offs <<= 1;
-		return ioread16(base + offs);
-	} else {
-		offs <<= 2;
-		return ioread32(base + offs);
-	}
-}
-
 static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
 {
 	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
@@ -100,22 +101,7 @@ static inline unsigned long sh_cmt_read_
 
 static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
 {
-	return sh_cmt_read(p, CMCNT);
-}
-
-static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
-				unsigned long value)
-{
-	void __iomem *base = p->mapbase;
-	unsigned long offs = reg_nr;
-
-	if (p->width == 16) {
-		offs <<= 1;
-		iowrite16(value, base + offs);
-	} else {
-		offs <<= 2;
-		iowrite32(value, base + offs);
-	}
+	return p->read_count(p->mapbase, CMCNT);
 }
 
 static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
@@ -135,13 +121,13 @@ static inline void sh_cmt_write_cmcsr(st
 static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p,
 				      unsigned long value)
 {
-	sh_cmt_write(p, CMCNT, value);
+	p->write_count(p->mapbase, CMCNT, value);
 }
 
 static inline void sh_cmt_write_cmcor(struct sh_cmt_priv *p,
 				      unsigned long value)
 {
-	sh_cmt_write(p, CMCOR, value);
+	p->write_count(p->mapbase, CMCOR, value);
 }
 
 static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
@@ -718,10 +704,14 @@ static int sh_cmt_setup(struct sh_cmt_pr
 
 	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;
 	} else {
 		p->width = 32;
+		p->read_count = sh_cmt_read32;
+		p->write_count = sh_cmt_write32;
 		p->overflow_bit = 0x8000;
 		p->clear_bits = ~0xc000;
 	}
#7 lore raw

PATCH 7/8 clocksource: sh_cmt: Add control register callbacks

In reply to Magnus Damm

From: Magnus Damm <[email protected]>

This patch adds control register callbacks for the CMT driver. At this point only 16-bit access is supported but in the future this will be updated to allow 32-bit access as well.

---

 drivers/clocksource/sh_cmt.c |   16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/clocksource/sh_cmt.c +12 -4
@@ -55,6 +55,11 @@ struct sh_cmt_priv {
 	unsigned long total_cycles;
 	bool cs_enabled;
 
+	/* 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,
@@ -94,12 +99,12 @@ static inline unsigned long sh_cmt_read_
 {
 	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 
-	return sh_cmt_read16(p->mapbase - cfg->channel_offset, 0);
+	return p->read_control(p->mapbase - cfg->channel_offset, 0);
 }
 
 static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
 {
-	return sh_cmt_read16(p->mapbase, CMCSR);
+	return p->read_control(p->mapbase, CMCSR);
 }
 
 static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
@@ -112,13 +117,13 @@ static inline void sh_cmt_write_cmstr(st
 {
 	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 
-	sh_cmt_write16(p->mapbase - cfg->channel_offset, 0, value);
+	p->write_control(p->mapbase - cfg->channel_offset, 0, value);
 }
 
 static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
 				      unsigned long value)
 {
-	sh_cmt_write16(p->mapbase, CMCSR, value);
+	p->write_control(p->mapbase, CMCSR, value);
 }
 
 static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p,
@@ -714,6 +719,9 @@ static int sh_cmt_setup(struct sh_cmt_pr
 		goto err1;
 	}
 
+	p->read_control = sh_cmt_read16;
+	p->write_control = sh_cmt_write16;
+
 	if (resource_size(res) == 6) {
 		p->width = 16;
 		p->read_count = sh_cmt_read16;
#8 lore raw

PATCH 8/8 clocksource: sh_cmt: Add CMT register layout comment

In reply to Magnus Damm

From: Magnus Damm <[email protected]>

Add a comment about different register layouts
supported by the CMT driver.

---

 drivers/clocksource/sh_cmt.c |   15 +++++++++++++++
 1 file changed, 15 insertions(+)
drivers/clocksource/sh_cmt.c +15 -0
@@ -66,6 +66,21 @@ struct sh_cmt_priv {
 			    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
+ */
+
 static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
 {
 	return ioread16(base + (offs << 1));
Acked-by on the v1 series
#9 lore raw
In reply to Magnus Damm
Quoted 16 lines · Magnus Damm

clocksource: sh_cmt: CMT driver update

[PATCH 01/08] clocksource: sh_cmt: Take care of clk_put() when setup_irq() fails [PATCH 02/08] clocksource: sh_cmt: Initialize 'max_match_value' and 'lock' in sh_cmt_setup() [PATCH 03/08] clocksource: sh_cmt: Consolidate platform_set_drvdata() call [PATCH 04/08] clocksource: sh_cmt: Introduce per-register functions
[PATCH 05/08] clocksource: sh_cmt: CMSTR and CMCSR register access update [PATCH 06/08] clocksource: sh_cmt: CMCNT and CMCOR register access update [PATCH 07/08] clocksource: sh_cmt: Add control register callbacks
[PATCH 08/08] clocksource: sh_cmt: Add CMT register layout comment

This patch series contains a couple of driver updates from Kuribayashi-san together with some register access changes from me. The register access changes work towards adding support for 32-bit only CMT hardware, but the final bits are not yet included in this series due to lack of hardware.

Quoted 6 lines

Patches 1-3:

Patches 4-8:

Due to unfamiliarity with the hardware, I can't really review these changes, so I'd prefer they be merged through the arch tree, where it can get proper review/testing.

thanks
-john

Tested-by on the v1 series
#10 lore raw
In reply to Magnus Damm

Hi Magnus

Quoted 10 lines · Magnus Damm

clocksource: sh_cmt: CMT driver update

[PATCH 01/08] clocksource: sh_cmt: Take care of clk_put() when setup_irq() fails [PATCH 02/08] clocksource: sh_cmt: Initialize 'max_match_value' and 'lock' in sh_cmt_setup() [PATCH 03/08] clocksource: sh_cmt: Consolidate platform_set_drvdata() call [PATCH 04/08] clocksource: sh_cmt: Introduce per-register functions
[PATCH 05/08] clocksource: sh_cmt: CMSTR and CMCSR register access update [PATCH 06/08] clocksource: sh_cmt: CMCNT and CMCOR register access update [PATCH 07/08] clocksource: sh_cmt: Add control register callbacks
[PATCH 08/08] clocksource: sh_cmt: Add CMT register layout comment

On a kzm9g board with -reference DT configuration and on armadillo800eva:

Thanks
Guennadi

Quoted 13 lines

This patch series contains a couple of driver updates from Kuribayashi-san together with some register access changes from me. The register access changes work towards adding support for 32-bit only CMT hardware, but the final bits are not yet included in this series due to lack of hardware.

Patches 1-3:

Patches 4-8:

---

Quoted 9 lines
 drivers/clocksource/sh_cmt.c |  257 ++++++++++++++++++++++++------------------
 1 file changed, 152 insertions(+), 105 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

#11 lore raw
Quoted 15 lines · Guennadi Liakhovetski

Hi Magnus

Quoted 10 lines · Magnus Damm

clocksource: sh_cmt: CMT driver update

[PATCH 01/08] clocksource: sh_cmt: Take care of clk_put() when setup_irq() fails [PATCH 02/08] clocksource: sh_cmt: Initialize 'max_match_value' and 'lock' in sh_cmt_setup() [PATCH 03/08] clocksource: sh_cmt: Consolidate platform_set_drvdata() call [PATCH 04/08] clocksource: sh_cmt: Introduce per-register functions
[PATCH 05/08] clocksource: sh_cmt: CMSTR and CMCSR register access update [PATCH 06/08] clocksource: sh_cmt: CMCNT and CMCOR register access update [PATCH 07/08] clocksource: sh_cmt: Add control register callbacks
[PATCH 08/08] clocksource: sh_cmt: Add CMT register layout comment

Quoted 3 lines

On a kzm9g board with -reference DT configuration and on armadillo800eva:

Thanks, I have applied these to the clocksource branch.