All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/7] ARM: shmobile: Define DT bindings for timer devices
@ 2013-03-17 15:43 ` Bastian Hecht
  0 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

The SH mobile series currently features 3 timer devices in the kernel:
Compare Match Timer (CMT), Timer Unit (TMU) and MTU2. These devices
share register layout characteristics amongst each that enable us to
define common DT bindings for them.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 .../devicetree/bindings/timer/renesas,timer.txt    |   45 ++++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/renesas,timer.txt

diff --git a/Documentation/devicetree/bindings/timer/renesas,timer.txt b/Documentation/devicetree/bindings/timer/renesas,timer.txt
new file mode 100644
index 0000000..2c001bf
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/renesas,timer.txt
@@ -0,0 +1,45 @@
+* Renesas SH Mobile Timer
+
+Bindings for several timer devices from Renesas including CMT, TMU and MTU2.
+
+Required properties:
+- compatible : Should be "renesas,{device}-timer",
+  whereas device is "cmt", "tmu" or "mtu2".
+- reg : Address and length of the register set for the device
+- interrupts : Timer interrupt
+- renesas,device-id : The ID of the timer device
+- renesas,channel-id : The channel ID of the timer device
+- renesas,source-quality : The viability to use this device as a free
+  running clock. From 0 (do not use) to 10 (best possible clock).
+- renesas,event-quality : The viability to use this device as an event
+  generator. From 0 (do not use) to 10 (best possible clock).
+
+The properties renesas,{source,event}-quality reflect the situation that the
+usability of the timer devices depend on the location within their SoCs. E.g.
+the power domain affinty affects power management, some mux-ed lines might be
+preferred to be assigned to other functions and other constraints.
+
+Example for CMT1 channel 0 on the R8A7740 SoC:
+
+	timer@e6138010 {
+		compatible = "renesas,cmt-timer";
+		interrupt-parent = <&intca>;
+		reg = <0xe6138010 0xc>;
+		interrupts = <0x0b00>;
+		renesas,device-id = <1>;
+		renesas,channel-id = <0>;
+		renesas,source-quality = <3>;
+		renesas,event-quality = <3>;
+	};
+
+Example for TMU0 channel 1 on the SH7372 SoC:
+	timer@fff60014 {
+		compatible = "renesas,tmu-timer";
+		interrupt-parent = <&intcs>;
+		reg = <0xfff60014 0xc>;
+		interrupts = <0xea0>;
+		renesas,device-id = <0>;
+		renesas,channel-id = <1>;
+		renesas,source-quality = <4>;
+		renesas,event-quality = <0>;
+	};
-- 
1.7.9.5


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

* [PATCH v3 1/7] ARM: shmobile: Define DT bindings for timer devices
@ 2013-03-17 15:43 ` Bastian Hecht
  0 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

The SH mobile series currently features 3 timer devices in the kernel:
Compare Match Timer (CMT), Timer Unit (TMU) and MTU2. These devices
share register layout characteristics amongst each that enable us to
define common DT bindings for them.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 .../devicetree/bindings/timer/renesas,timer.txt    |   45 ++++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/renesas,timer.txt

diff --git a/Documentation/devicetree/bindings/timer/renesas,timer.txt b/Documentation/devicetree/bindings/timer/renesas,timer.txt
new file mode 100644
index 0000000..2c001bf
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/renesas,timer.txt
@@ -0,0 +1,45 @@
+* Renesas SH Mobile Timer
+
+Bindings for several timer devices from Renesas including CMT, TMU and MTU2.
+
+Required properties:
+- compatible : Should be "renesas,{device}-timer",
+  whereas device is "cmt", "tmu" or "mtu2".
+- reg : Address and length of the register set for the device
+- interrupts : Timer interrupt
+- renesas,device-id : The ID of the timer device
+- renesas,channel-id : The channel ID of the timer device
+- renesas,source-quality : The viability to use this device as a free
+  running clock. From 0 (do not use) to 10 (best possible clock).
+- renesas,event-quality : The viability to use this device as an event
+  generator. From 0 (do not use) to 10 (best possible clock).
+
+The properties renesas,{source,event}-quality reflect the situation that the
+usability of the timer devices depend on the location within their SoCs. E.g.
+the power domain affinty affects power management, some mux-ed lines might be
+preferred to be assigned to other functions and other constraints.
+
+Example for CMT1 channel 0 on the R8A7740 SoC:
+
+	timer at e6138010 {
+		compatible = "renesas,cmt-timer";
+		interrupt-parent = <&intca>;
+		reg = <0xe6138010 0xc>;
+		interrupts = <0x0b00>;
+		renesas,device-id = <1>;
+		renesas,channel-id = <0>;
+		renesas,source-quality = <3>;
+		renesas,event-quality = <3>;
+	};
+
+Example for TMU0 channel 1 on the SH7372 SoC:
+	timer at fff60014 {
+		compatible = "renesas,tmu-timer";
+		interrupt-parent = <&intcs>;
+		reg = <0xfff60014 0xc>;
+		interrupts = <0xea0>;
+		renesas,device-id = <0>;
+		renesas,channel-id = <1>;
+		renesas,source-quality = <4>;
+		renesas,event-quality = <0>;
+	};
-- 
1.7.9.5

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

* [PATCH v3 2/7] clocksource: sh_cmt: Add OF support
  2013-03-17 15:43 ` Bastian Hecht
@ 2013-03-17 15:43   ` Bastian Hecht
  -1 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

We add the capabilty to probe SH CMT timer devices using Device Tree
setup.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 drivers/clocksource/sh_cmt.c |  109 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 96 insertions(+), 13 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 08d0c41..79bc526 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -34,10 +34,13 @@
 #include <linux/module.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
 
 struct sh_cmt_priv {
 	void __iomem *mapbase;
 	struct clk *clk;
+	long channel_offset;
+	int timer_bit;
 	unsigned long width; /* 16 or 32 bit version of hardware block */
 	unsigned long overflow_bit;
 	unsigned long clear_bits;
@@ -109,9 +112,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
 
 static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-
-	return p->read_control(p->mapbase - cfg->channel_offset, 0);
+	return p->read_control(p->mapbase - p->channel_offset, 0);
 }
 
 static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
@@ -127,9 +128,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
 static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
 				      unsigned long value)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-
-	p->write_control(p->mapbase - cfg->channel_offset, 0, value);
+	p->write_control(p->mapbase - p->channel_offset, 0, value);
 }
 
 static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
@@ -176,7 +175,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
 
 static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
@@ -184,9 +182,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
 	value = sh_cmt_read_cmstr(p);
 
 	if (start)
-		value |= 1 << cfg->timer_bit;
+		value |= 1 << p->timer_bit;
 	else
-		value &= ~(1 << cfg->timer_bit);
+		value &= ~(1 << p->timer_bit);
 
 	sh_cmt_write_cmstr(p, value);
 	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
@@ -673,9 +671,85 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
 	return 0;
 }
 
-static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
+static const struct of_device_id of_sh_cmt_match[] = {
+	{ .compatible = "renesas,cmt-timer" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_sh_cmt_match);
+
+static const int sh_cmt_offset_multiplier[] = { 0x60, 0x10, 0x40, 0x40, 0x40 };
+#define CMT_MAX_CHANNELS	6
+
+static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev)
+{
+	struct sh_timer_config *cfg;
+	struct device_node *np = dev->of_node;
+	u32 timer_id, channel_id, rating;
+
+	if (!IS_ENABLED(CONFIG_OF) || !np)
+		return NULL;
+
+	cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
+	if (!cfg) {
+		dev_err(dev, "failed to allocate DT config data\n");
+		return NULL;
+	}
+
+	if (of_property_read_u32(np, "renesas,device-id", &timer_id)) {
+		dev_err(dev, "device id missing\n");
+		return NULL;
+	}
+	if (timer_id >= ARRAY_SIZE(sh_cmt_offset_multiplier)) {
+		dev_err(dev, "invalid device id\n");
+		return NULL;
+	}
+
+	if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
+		dev_err(dev, "channel id missing\n");
+		return NULL;
+	}
+	if (channel_id >= CMT_MAX_CHANNELS) {
+		dev_err(dev, "invalid channel id\n");
+		return NULL;
+	}
+
+	cfg->channel_offset = sh_cmt_offset_multiplier[timer_id] *
+							(channel_id + 1);
+	cfg->timer_bit = channel_id;
+
+	/*
+	 * We convert the {source,event}-quality DT properties to linux specific
+	 * clock{source,event}_ratings.
+	 */
+	if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
+		if (rating > 10) {
+			dev_err(dev, "invalid source-quality\n");
+			return NULL;
+		}
+		if (rating)
+			cfg->clocksource_rating = rating * 50 - 1;
+	}
+
+	if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
+		if (rating > 10) {
+			dev_err(dev, "invalid event-quality\n");
+			return NULL;
+		}
+		if (rating)
+			cfg->clockevent_rating = rating * 50 - 1;
+	}
+
+	if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
+		dev_err(dev, "source- and event-quality 0, timer is unused\n");
+		return NULL;
+	}
+
+	return cfg;
+}
+
+static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev,
+						struct sh_timer_config *cfg)
 {
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
 	int irq, ret;
 	ret = -ENXIO;
@@ -762,6 +836,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 		goto err2;
 	}
 
+	p->channel_offset = cfg->channel_offset;
+	p->timer_bit = cfg->timer_bit;
+
 	platform_set_drvdata(pdev, p);
 
 	return 0;
@@ -777,7 +854,7 @@ err0:
 static int sh_cmt_probe(struct platform_device *pdev)
 {
 	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	struct sh_timer_config *cfg;
 	int ret;
 
 	if (!is_early_platform_device(pdev)) {
@@ -785,6 +862,11 @@ static int sh_cmt_probe(struct platform_device *pdev)
 		pm_runtime_enable(&pdev->dev);
 	}
 
+	if (pdev->dev.of_node)
+		cfg = sh_cmt_parse_dt(&pdev->dev);
+	else
+		cfg = pdev->dev.platform_data;
+
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		goto out;
@@ -796,7 +878,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	ret = sh_cmt_setup(p, pdev);
+	ret = sh_cmt_setup(p, pdev, cfg);
 	if (ret) {
 		kfree(p);
 		pm_runtime_idle(&pdev->dev);
@@ -824,6 +906,7 @@ static struct platform_driver sh_cmt_device_driver = {
 	.remove		= sh_cmt_remove,
 	.driver		= {
 		.name	= "sh_cmt",
+		.of_match_table = of_match_ptr(of_sh_cmt_match),
 	}
 };
 
-- 
1.7.9.5


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

* [PATCH v3 2/7] clocksource: sh_cmt: Add OF support
@ 2013-03-17 15:43   ` Bastian Hecht
  0 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

We add the capabilty to probe SH CMT timer devices using Device Tree
setup.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 drivers/clocksource/sh_cmt.c |  109 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 96 insertions(+), 13 deletions(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 08d0c41..79bc526 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -34,10 +34,13 @@
 #include <linux/module.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
 
 struct sh_cmt_priv {
 	void __iomem *mapbase;
 	struct clk *clk;
+	long channel_offset;
+	int timer_bit;
 	unsigned long width; /* 16 or 32 bit version of hardware block */
 	unsigned long overflow_bit;
 	unsigned long clear_bits;
@@ -109,9 +112,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
 
 static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-
-	return p->read_control(p->mapbase - cfg->channel_offset, 0);
+	return p->read_control(p->mapbase - p->channel_offset, 0);
 }
 
 static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
@@ -127,9 +128,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
 static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
 				      unsigned long value)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-
-	p->write_control(p->mapbase - cfg->channel_offset, 0, value);
+	p->write_control(p->mapbase - p->channel_offset, 0, value);
 }
 
 static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
@@ -176,7 +175,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
 
 static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
@@ -184,9 +182,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
 	value = sh_cmt_read_cmstr(p);
 
 	if (start)
-		value |= 1 << cfg->timer_bit;
+		value |= 1 << p->timer_bit;
 	else
-		value &= ~(1 << cfg->timer_bit);
+		value &= ~(1 << p->timer_bit);
 
 	sh_cmt_write_cmstr(p, value);
 	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
@@ -673,9 +671,85 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
 	return 0;
 }
 
-static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
+static const struct of_device_id of_sh_cmt_match[] = {
+	{ .compatible = "renesas,cmt-timer" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_sh_cmt_match);
+
+static const int sh_cmt_offset_multiplier[] = { 0x60, 0x10, 0x40, 0x40, 0x40 };
+#define CMT_MAX_CHANNELS	6
+
+static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev)
+{
+	struct sh_timer_config *cfg;
+	struct device_node *np = dev->of_node;
+	u32 timer_id, channel_id, rating;
+
+	if (!IS_ENABLED(CONFIG_OF) || !np)
+		return NULL;
+
+	cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
+	if (!cfg) {
+		dev_err(dev, "failed to allocate DT config data\n");
+		return NULL;
+	}
+
+	if (of_property_read_u32(np, "renesas,device-id", &timer_id)) {
+		dev_err(dev, "device id missing\n");
+		return NULL;
+	}
+	if (timer_id >= ARRAY_SIZE(sh_cmt_offset_multiplier)) {
+		dev_err(dev, "invalid device id\n");
+		return NULL;
+	}
+
+	if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
+		dev_err(dev, "channel id missing\n");
+		return NULL;
+	}
+	if (channel_id >= CMT_MAX_CHANNELS) {
+		dev_err(dev, "invalid channel id\n");
+		return NULL;
+	}
+
+	cfg->channel_offset = sh_cmt_offset_multiplier[timer_id] *
+							(channel_id + 1);
+	cfg->timer_bit = channel_id;
+
+	/*
+	 * We convert the {source,event}-quality DT properties to linux specific
+	 * clock{source,event}_ratings.
+	 */
+	if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
+		if (rating > 10) {
+			dev_err(dev, "invalid source-quality\n");
+			return NULL;
+		}
+		if (rating)
+			cfg->clocksource_rating = rating * 50 - 1;
+	}
+
+	if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
+		if (rating > 10) {
+			dev_err(dev, "invalid event-quality\n");
+			return NULL;
+		}
+		if (rating)
+			cfg->clockevent_rating = rating * 50 - 1;
+	}
+
+	if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
+		dev_err(dev, "source- and event-quality 0, timer is unused\n");
+		return NULL;
+	}
+
+	return cfg;
+}
+
+static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev,
+						struct sh_timer_config *cfg)
 {
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
 	int irq, ret;
 	ret = -ENXIO;
@@ -762,6 +836,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 		goto err2;
 	}
 
+	p->channel_offset = cfg->channel_offset;
+	p->timer_bit = cfg->timer_bit;
+
 	platform_set_drvdata(pdev, p);
 
 	return 0;
@@ -777,7 +854,7 @@ err0:
 static int sh_cmt_probe(struct platform_device *pdev)
 {
 	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	struct sh_timer_config *cfg;
 	int ret;
 
 	if (!is_early_platform_device(pdev)) {
@@ -785,6 +862,11 @@ static int sh_cmt_probe(struct platform_device *pdev)
 		pm_runtime_enable(&pdev->dev);
 	}
 
+	if (pdev->dev.of_node)
+		cfg = sh_cmt_parse_dt(&pdev->dev);
+	else
+		cfg = pdev->dev.platform_data;
+
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		goto out;
@@ -796,7 +878,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	ret = sh_cmt_setup(p, pdev);
+	ret = sh_cmt_setup(p, pdev, cfg);
 	if (ret) {
 		kfree(p);
 		pm_runtime_idle(&pdev->dev);
@@ -824,6 +906,7 @@ static struct platform_driver sh_cmt_device_driver = {
 	.remove		= sh_cmt_remove,
 	.driver		= {
 		.name	= "sh_cmt",
+		.of_match_table = of_match_ptr(of_sh_cmt_match),
 	}
 };
 
-- 
1.7.9.5

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

* [PATCH v3 3/7] clocksource: sh_tmu: Add OF support
  2013-03-17 15:43 ` Bastian Hecht
@ 2013-03-17 15:43   ` Bastian Hecht
  -1 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

We add the capabilty to probe SH CMT timer devices using Device Tree
setup.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: trivial fix: assign config values to driver data.

 drivers/clocksource/sh_tmu.c |   96 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 85 insertions(+), 11 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index b4502edc..98a3c3c 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -34,10 +34,13 @@
 #include <linux/module.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
 
 struct sh_tmu_priv {
 	void __iomem *mapbase;
 	struct clk *clk;
+	long channel_offset;
+	int timer_bit;
 	struct irqaction irqaction;
 	struct platform_device *pdev;
 	unsigned long rate;
@@ -57,12 +60,11 @@ static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
 
 static inline unsigned long sh_tmu_read(struct sh_tmu_priv *p, int reg_nr)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	void __iomem *base = p->mapbase;
 	unsigned long offs;
 
 	if (reg_nr = TSTR)
-		return ioread8(base - cfg->channel_offset);
+		return ioread8(base - p->channel_offset);
 
 	offs = reg_nr << 2;
 
@@ -75,12 +77,11 @@ static inline unsigned long sh_tmu_read(struct sh_tmu_priv *p, int reg_nr)
 static inline void sh_tmu_write(struct sh_tmu_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 = TSTR) {
-		iowrite8(value, base - cfg->channel_offset);
+		iowrite8(value, base - p->channel_offset);
 		return;
 	}
 
@@ -94,7 +95,6 @@ static inline void sh_tmu_write(struct sh_tmu_priv *p, int reg_nr,
 
 static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
@@ -102,9 +102,9 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
 	value = sh_tmu_read(p, TSTR);
 
 	if (start)
-		value |= 1 << cfg->timer_bit;
+		value |= 1 << p->timer_bit;
 	else
-		value &= ~(1 << cfg->timer_bit);
+		value &= ~(1 << p->timer_bit);
 
 	sh_tmu_write(p, TSTR, value);
 	raw_spin_unlock_irqrestore(&sh_tmu_lock, flags);
@@ -421,9 +421,75 @@ static int sh_tmu_register(struct sh_tmu_priv *p, char *name,
 	return 0;
 }
 
-static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
+static const struct of_device_id of_sh_tmu_match[] = {
+	{ .compatible = "renesas,tmu-timer" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_sh_tmu_match);
+
+#define TMU_OFFSET_MULTIPLIER	0xc
+#define TMU_MAX_CHANNELS	3
+
+static struct sh_timer_config *sh_tmu_parse_dt(struct device *dev)
+{
+	struct sh_timer_config *cfg;
+	struct device_node *np = dev->of_node;
+	u32 channel_id, rating;
+
+	if (!IS_ENABLED(CONFIG_OF) || !np)
+		return NULL;
+
+	cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
+	if (!cfg) {
+		dev_err(dev, "failed to allocate DT config data\n");
+		return NULL;
+	}
+
+	if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
+		dev_err(dev, "channel id missing\n");
+		return NULL;
+	}
+	if (channel_id >= TMU_MAX_CHANNELS) {
+		dev_err(dev, "invalid channel id\n");
+		return NULL;
+	}
+
+	cfg->channel_offset = channel_id * TMU_OFFSET_MULTIPLIER + 4;
+	cfg->timer_bit = channel_id;
+
+	/*
+	 * We convert the {source,event}-quality DT properties to linux specific
+	 * clock{source,event}_ratings.
+	 */
+	if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
+		if (rating > 10) {
+			dev_err(dev, "invalid source-quality\n");
+			return NULL;
+		}
+		if (rating)
+			cfg->clocksource_rating = rating * 50 - 1;
+	}
+
+	if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
+		if (rating > 10) {
+			dev_err(dev, "invalid event-quality\n");
+			return NULL;
+		}
+		if (rating)
+			cfg->clockevent_rating = rating * 50 - 1;
+	}
+
+	if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
+		dev_err(dev, "source- and event-quality 0, timer is unused\n");
+		return NULL;
+	}
+
+	return cfg;
+}
+
+static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev,
+						struct sh_timer_config *cfg)
 {
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
 	int irq, ret;
 	ret = -ENXIO;
@@ -474,6 +540,8 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 	}
 	p->cs_enabled = false;
 	p->enable_count = 0;
+	p->channel_offset = cfg->channel_offset;
+	p->timer_bit = cfg->timer_bit;
 
 	return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
 			       cfg->clockevent_rating,
@@ -487,7 +555,7 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 static int sh_tmu_probe(struct platform_device *pdev)
 {
 	struct sh_tmu_priv *p = platform_get_drvdata(pdev);
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	struct sh_timer_config *cfg;
 	int ret;
 
 	if (!is_early_platform_device(pdev)) {
@@ -495,6 +563,11 @@ static int sh_tmu_probe(struct platform_device *pdev)
 		pm_runtime_enable(&pdev->dev);
 	}
 
+	if (pdev->dev.of_node)
+		cfg = sh_tmu_parse_dt(&pdev->dev);
+	else
+		cfg = pdev->dev.platform_data;
+
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		goto out;
@@ -506,7 +579,7 @@ static int sh_tmu_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	ret = sh_tmu_setup(p, pdev);
+	ret = sh_tmu_setup(p, pdev, cfg);
 	if (ret) {
 		kfree(p);
 		platform_set_drvdata(pdev, NULL);
@@ -535,6 +608,7 @@ static struct platform_driver sh_tmu_device_driver = {
 	.remove		= sh_tmu_remove,
 	.driver		= {
 		.name	= "sh_tmu",
+		.of_match_table = of_sh_tmu_match,
 	}
 };
 
-- 
1.7.9.5


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

* [PATCH v3 3/7] clocksource: sh_tmu: Add OF support
@ 2013-03-17 15:43   ` Bastian Hecht
  0 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

We add the capabilty to probe SH CMT timer devices using Device Tree
setup.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: trivial fix: assign config values to driver data.

 drivers/clocksource/sh_tmu.c |   96 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 85 insertions(+), 11 deletions(-)

diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index b4502edc..98a3c3c 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -34,10 +34,13 @@
 #include <linux/module.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
 
 struct sh_tmu_priv {
 	void __iomem *mapbase;
 	struct clk *clk;
+	long channel_offset;
+	int timer_bit;
 	struct irqaction irqaction;
 	struct platform_device *pdev;
 	unsigned long rate;
@@ -57,12 +60,11 @@ static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
 
 static inline unsigned long sh_tmu_read(struct sh_tmu_priv *p, int reg_nr)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	void __iomem *base = p->mapbase;
 	unsigned long offs;
 
 	if (reg_nr == TSTR)
-		return ioread8(base - cfg->channel_offset);
+		return ioread8(base - p->channel_offset);
 
 	offs = reg_nr << 2;
 
@@ -75,12 +77,11 @@ static inline unsigned long sh_tmu_read(struct sh_tmu_priv *p, int reg_nr)
 static inline void sh_tmu_write(struct sh_tmu_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 == TSTR) {
-		iowrite8(value, base - cfg->channel_offset);
+		iowrite8(value, base - p->channel_offset);
 		return;
 	}
 
@@ -94,7 +95,6 @@ static inline void sh_tmu_write(struct sh_tmu_priv *p, int reg_nr,
 
 static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
 {
-	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
 	unsigned long flags, value;
 
 	/* start stop register shared by multiple timer channels */
@@ -102,9 +102,9 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
 	value = sh_tmu_read(p, TSTR);
 
 	if (start)
-		value |= 1 << cfg->timer_bit;
+		value |= 1 << p->timer_bit;
 	else
-		value &= ~(1 << cfg->timer_bit);
+		value &= ~(1 << p->timer_bit);
 
 	sh_tmu_write(p, TSTR, value);
 	raw_spin_unlock_irqrestore(&sh_tmu_lock, flags);
@@ -421,9 +421,75 @@ static int sh_tmu_register(struct sh_tmu_priv *p, char *name,
 	return 0;
 }
 
-static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
+static const struct of_device_id of_sh_tmu_match[] = {
+	{ .compatible = "renesas,tmu-timer" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_sh_tmu_match);
+
+#define TMU_OFFSET_MULTIPLIER	0xc
+#define TMU_MAX_CHANNELS	3
+
+static struct sh_timer_config *sh_tmu_parse_dt(struct device *dev)
+{
+	struct sh_timer_config *cfg;
+	struct device_node *np = dev->of_node;
+	u32 channel_id, rating;
+
+	if (!IS_ENABLED(CONFIG_OF) || !np)
+		return NULL;
+
+	cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
+	if (!cfg) {
+		dev_err(dev, "failed to allocate DT config data\n");
+		return NULL;
+	}
+
+	if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
+		dev_err(dev, "channel id missing\n");
+		return NULL;
+	}
+	if (channel_id >= TMU_MAX_CHANNELS) {
+		dev_err(dev, "invalid channel id\n");
+		return NULL;
+	}
+
+	cfg->channel_offset = channel_id * TMU_OFFSET_MULTIPLIER + 4;
+	cfg->timer_bit = channel_id;
+
+	/*
+	 * We convert the {source,event}-quality DT properties to linux specific
+	 * clock{source,event}_ratings.
+	 */
+	if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
+		if (rating > 10) {
+			dev_err(dev, "invalid source-quality\n");
+			return NULL;
+		}
+		if (rating)
+			cfg->clocksource_rating = rating * 50 - 1;
+	}
+
+	if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
+		if (rating > 10) {
+			dev_err(dev, "invalid event-quality\n");
+			return NULL;
+		}
+		if (rating)
+			cfg->clockevent_rating = rating * 50 - 1;
+	}
+
+	if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
+		dev_err(dev, "source- and event-quality 0, timer is unused\n");
+		return NULL;
+	}
+
+	return cfg;
+}
+
+static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev,
+						struct sh_timer_config *cfg)
 {
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	struct resource *res;
 	int irq, ret;
 	ret = -ENXIO;
@@ -474,6 +540,8 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 	}
 	p->cs_enabled = false;
 	p->enable_count = 0;
+	p->channel_offset = cfg->channel_offset;
+	p->timer_bit = cfg->timer_bit;
 
 	return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
 			       cfg->clockevent_rating,
@@ -487,7 +555,7 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 static int sh_tmu_probe(struct platform_device *pdev)
 {
 	struct sh_tmu_priv *p = platform_get_drvdata(pdev);
-	struct sh_timer_config *cfg = pdev->dev.platform_data;
+	struct sh_timer_config *cfg;
 	int ret;
 
 	if (!is_early_platform_device(pdev)) {
@@ -495,6 +563,11 @@ static int sh_tmu_probe(struct platform_device *pdev)
 		pm_runtime_enable(&pdev->dev);
 	}
 
+	if (pdev->dev.of_node)
+		cfg = sh_tmu_parse_dt(&pdev->dev);
+	else
+		cfg = pdev->dev.platform_data;
+
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
 		goto out;
@@ -506,7 +579,7 @@ static int sh_tmu_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	ret = sh_tmu_setup(p, pdev);
+	ret = sh_tmu_setup(p, pdev, cfg);
 	if (ret) {
 		kfree(p);
 		platform_set_drvdata(pdev, NULL);
@@ -535,6 +608,7 @@ static struct platform_driver sh_tmu_device_driver = {
 	.remove		= sh_tmu_remove,
 	.driver		= {
 		.name	= "sh_tmu",
+		.of_match_table = of_sh_tmu_match,
 	}
 };
 
-- 
1.7.9.5

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

* [PATCH v3 4/7] ARM: shmobile: sh73a0: Add timer DT names to clock list
  2013-03-17 15:43 ` Bastian Hecht
@ 2013-03-17 15:43   ` Bastian Hecht
  -1 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

This adds temporarily the alternative device names to the clock list
that are used when booting via Device Tree setup.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 arch/arm/mach-shmobile/clock-sh73a0.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index 71843dd..2704467 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -558,7 +558,9 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU0 */
 	CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2-RX0 */
 	CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), /* TMU00 */
+	CLKDEV_DEV_ID("fff60008.timer", &mstp_clks[MSTP125]), /* TMU00 */
 	CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */
+	CLKDEV_DEV_ID("fff60014.timer", &mstp_clks[MSTP125]), /* TMU01 */
 	CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */
 	CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */
 	CLKDEV_DEV_ID("e6820000.i2c", &mstp_clks[MSTP116]), /* I2C0 */
@@ -575,6 +577,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
 	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
 	CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
+	CLKDEV_DEV_ID("e6138010.timer", &mstp_clks[MSTP329]), /* CMT10 */
 	CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */
 	CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
 	CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */
-- 
1.7.9.5


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

* [PATCH v3 4/7] ARM: shmobile: sh73a0: Add timer DT names to clock list
@ 2013-03-17 15:43   ` Bastian Hecht
  0 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

This adds temporarily the alternative device names to the clock list
that are used when booting via Device Tree setup.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 arch/arm/mach-shmobile/clock-sh73a0.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index 71843dd..2704467 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -558,7 +558,9 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU0 */
 	CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2-RX0 */
 	CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), /* TMU00 */
+	CLKDEV_DEV_ID("fff60008.timer", &mstp_clks[MSTP125]), /* TMU00 */
 	CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */
+	CLKDEV_DEV_ID("fff60014.timer", &mstp_clks[MSTP125]), /* TMU01 */
 	CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */
 	CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */
 	CLKDEV_DEV_ID("e6820000.i2c", &mstp_clks[MSTP116]), /* I2C0 */
@@ -575,6 +577,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
 	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */
 	CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
+	CLKDEV_DEV_ID("e6138010.timer", &mstp_clks[MSTP329]), /* CMT10 */
 	CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */
 	CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
 	CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */
-- 
1.7.9.5

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

* [PATCH v3 5/7] ARM: mach-shmobile: sh73a0: Setup the timer CMT10 using DT
  2013-03-17 15:43 ` Bastian Hecht
@ 2013-03-17 15:43   ` Bastian Hecht
  -1 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

We can now use the Device Tree for bringing up our timer device CMT10 on
the SoC sh73a0.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 arch/arm/boot/dts/sh73a0.dtsi         |   11 +++++++++++
 arch/arm/mach-shmobile/setup-sh73a0.c |   32 --------------------------------
 2 files changed, 11 insertions(+), 32 deletions(-)

diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index 8a59465..6549d6c 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -97,4 +97,15 @@
 			      0 189 0x4
 			      0 190 0x4>;
 	};
+
+	timer@e6138010 {
+		compatible = "renesas,cmt-timer";
+		interrupt-parent = <&gic>;
+		reg = <0xe6138010 0xc>;
+		interrupts = <0 65 0x4>;
+		renesas,device-id = <1>;
+		renesas,channel-id = <0>;
+		renesas,source-quality = <3>;
+		renesas,event-quality = <3>;
+	};
 };
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index 95a75af..64bc2c5 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -247,37 +247,6 @@ static struct platform_device scif8_device = {
 	},
 };
 
-static struct sh_timer_config cmt10_platform_data = {
-	.name = "CMT10",
-	.channel_offset = 0x10,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 125,
-};
-
-static struct resource cmt10_resources[] = {
-	[0] = {
-		.name	= "CMT10",
-		.start	= 0xe6138010,
-		.end	= 0xe613801b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= gic_spi(65),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt10_device = {
-	.name		= "sh_cmt",
-	.id		= 10,
-	.dev = {
-		.platform_data	= &cmt10_platform_data,
-	},
-	.resource	= cmt10_resources,
-	.num_resources	= ARRAY_SIZE(cmt10_resources),
-};
-
 /* TMU */
 static struct sh_timer_config tmu00_platform_data = {
 	.name = "TMU00",
@@ -913,7 +882,6 @@ static struct platform_device *sh73a0_devices_dt[] __initdata = {
 	&scif6_device,
 	&scif7_device,
 	&scif8_device,
-	&cmt10_device,
 };
 
 static struct platform_device *sh73a0_early_devices[] __initdata = {
-- 
1.7.9.5


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

* [PATCH v3 5/7] ARM: mach-shmobile: sh73a0: Setup the timer CMT10 using DT
@ 2013-03-17 15:43   ` Bastian Hecht
  0 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

We can now use the Device Tree for bringing up our timer device CMT10 on
the SoC sh73a0.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 arch/arm/boot/dts/sh73a0.dtsi         |   11 +++++++++++
 arch/arm/mach-shmobile/setup-sh73a0.c |   32 --------------------------------
 2 files changed, 11 insertions(+), 32 deletions(-)

diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index 8a59465..6549d6c 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -97,4 +97,15 @@
 			      0 189 0x4
 			      0 190 0x4>;
 	};
+
+	timer at e6138010 {
+		compatible = "renesas,cmt-timer";
+		interrupt-parent = <&gic>;
+		reg = <0xe6138010 0xc>;
+		interrupts = <0 65 0x4>;
+		renesas,device-id = <1>;
+		renesas,channel-id = <0>;
+		renesas,source-quality = <3>;
+		renesas,event-quality = <3>;
+	};
 };
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index 95a75af..64bc2c5 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -247,37 +247,6 @@ static struct platform_device scif8_device = {
 	},
 };
 
-static struct sh_timer_config cmt10_platform_data = {
-	.name = "CMT10",
-	.channel_offset = 0x10,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 125,
-};
-
-static struct resource cmt10_resources[] = {
-	[0] = {
-		.name	= "CMT10",
-		.start	= 0xe6138010,
-		.end	= 0xe613801b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= gic_spi(65),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt10_device = {
-	.name		= "sh_cmt",
-	.id		= 10,
-	.dev = {
-		.platform_data	= &cmt10_platform_data,
-	},
-	.resource	= cmt10_resources,
-	.num_resources	= ARRAY_SIZE(cmt10_resources),
-};
-
 /* TMU */
 static struct sh_timer_config tmu00_platform_data = {
 	.name = "TMU00",
@@ -913,7 +882,6 @@ static struct platform_device *sh73a0_devices_dt[] __initdata = {
 	&scif6_device,
 	&scif7_device,
 	&scif8_device,
-	&cmt10_device,
 };
 
 static struct platform_device *sh73a0_early_devices[] __initdata = {
-- 
1.7.9.5

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

* [PATCH v3 6/7] ARM: shmobile: r8a7740: Add DT name to clock list for CMT10
  2013-03-17 15:43 ` Bastian Hecht
@ 2013-03-17 15:43   ` Bastian Hecht
  -1 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

This adds temporarily the alternative device name to the clock list
that is used when booting via Device Tree setup.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 arch/arm/mach-shmobile/clock-r8a7740.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index 1feb9a2..b0b5d3c 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -616,6 +616,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("e6cc0000.sci",		&mstp_clks[MSTP230]),
 
 	CLKDEV_DEV_ID("sh_cmt.10",		&mstp_clks[MSTP329]),
+	CLKDEV_DEV_ID("e6138010.timer",		&mstp_clks[MSTP329]),
 	CLKDEV_DEV_ID("sh_fsi2",		&mstp_clks[MSTP328]),
 	CLKDEV_DEV_ID("i2c-sh_mobile.1",	&mstp_clks[MSTP323]),
 	CLKDEV_DEV_ID("renesas_usbhs",		&mstp_clks[MSTP320]),
-- 
1.7.9.5


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

* [PATCH v3 6/7] ARM: shmobile: r8a7740: Add DT name to clock list for CMT10
@ 2013-03-17 15:43   ` Bastian Hecht
  0 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

This adds temporarily the alternative device name to the clock list
that is used when booting via Device Tree setup.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 arch/arm/mach-shmobile/clock-r8a7740.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index 1feb9a2..b0b5d3c 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -616,6 +616,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("e6cc0000.sci",		&mstp_clks[MSTP230]),
 
 	CLKDEV_DEV_ID("sh_cmt.10",		&mstp_clks[MSTP329]),
+	CLKDEV_DEV_ID("e6138010.timer",		&mstp_clks[MSTP329]),
 	CLKDEV_DEV_ID("sh_fsi2",		&mstp_clks[MSTP328]),
 	CLKDEV_DEV_ID("i2c-sh_mobile.1",	&mstp_clks[MSTP323]),
 	CLKDEV_DEV_ID("renesas_usbhs",		&mstp_clks[MSTP320]),
-- 
1.7.9.5

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

* [PATCH v3 7/7] ARM: mach-shmobile: r8a7740: Setup the timer CMT10 using DT
  2013-03-17 15:43 ` Bastian Hecht
@ 2013-03-17 15:43   ` Bastian Hecht
  -1 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

We can now use the Device Tree for bringing up our timer device CMT10 on
the SoC r8a7740.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 arch/arm/boot/dts/r8a7740.dtsi         |   11 +++++++++++
 arch/arm/mach-shmobile/setup-r8a7740.c |   33 --------------------------------
 2 files changed, 11 insertions(+), 33 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi
index 798fa35..72f4c80 100644
--- a/arch/arm/boot/dts/r8a7740.dtsi
+++ b/arch/arm/boot/dts/r8a7740.dtsi
@@ -18,4 +18,15 @@
 			compatible = "arm,cortex-a9";
 		};
 	};
+
+	timer@e6138010 {
+		compatible = "renesas,cmt-timer";
+		interrupt-parent = <&intca>;
+		reg = <0xe6138010 0xc>;
+		interrupts = <0x0b00>;
+		renesas,device-id = <1>;
+		renesas,channel-id = <0>;
+		renesas,source-quality = <3>;
+		renesas,event-quality = <3>;
+	};
 };
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 30ac79c..9db61a6 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -255,38 +255,6 @@ static struct platform_device scifb_device = {
 	},
 };
 
-/* CMT */
-static struct sh_timer_config cmt10_platform_data = {
-	.name = "CMT10",
-	.channel_offset = 0x10,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 125,
-};
-
-static struct resource cmt10_resources[] = {
-	[0] = {
-		.name	= "CMT10",
-		.start	= 0xe6138010,
-		.end	= 0xe613801b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0x0b00),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt10_device = {
-	.name		= "sh_cmt",
-	.id		= 10,
-	.dev = {
-		.platform_data	= &cmt10_platform_data,
-	},
-	.resource	= cmt10_resources,
-	.num_resources	= ARRAY_SIZE(cmt10_resources),
-};
-
 /* TMU */
 static struct sh_timer_config tmu00_platform_data = {
 	.name = "TMU00",
@@ -388,7 +356,6 @@ static struct platform_device *r8a7740_early_devices[] __initdata = {
 	&scif6_device,
 	&scif7_device,
 	&scifb_device,
-	&cmt10_device,
 	&tmu00_device,
 	&tmu01_device,
 	&tmu02_device,
-- 
1.7.9.5


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

* [PATCH v3 7/7] ARM: mach-shmobile: r8a7740: Setup the timer CMT10 using DT
@ 2013-03-17 15:43   ` Bastian Hecht
  0 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-17 15:43 UTC (permalink / raw)
  To: linux-arm-kernel

We can now use the Device Tree for bringing up our timer device CMT10 on
the SoC r8a7740.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v3: same (only patch 0003 changed)

 arch/arm/boot/dts/r8a7740.dtsi         |   11 +++++++++++
 arch/arm/mach-shmobile/setup-r8a7740.c |   33 --------------------------------
 2 files changed, 11 insertions(+), 33 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi
index 798fa35..72f4c80 100644
--- a/arch/arm/boot/dts/r8a7740.dtsi
+++ b/arch/arm/boot/dts/r8a7740.dtsi
@@ -18,4 +18,15 @@
 			compatible = "arm,cortex-a9";
 		};
 	};
+
+	timer at e6138010 {
+		compatible = "renesas,cmt-timer";
+		interrupt-parent = <&intca>;
+		reg = <0xe6138010 0xc>;
+		interrupts = <0x0b00>;
+		renesas,device-id = <1>;
+		renesas,channel-id = <0>;
+		renesas,source-quality = <3>;
+		renesas,event-quality = <3>;
+	};
 };
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 30ac79c..9db61a6 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -255,38 +255,6 @@ static struct platform_device scifb_device = {
 	},
 };
 
-/* CMT */
-static struct sh_timer_config cmt10_platform_data = {
-	.name = "CMT10",
-	.channel_offset = 0x10,
-	.timer_bit = 0,
-	.clockevent_rating = 125,
-	.clocksource_rating = 125,
-};
-
-static struct resource cmt10_resources[] = {
-	[0] = {
-		.name	= "CMT10",
-		.start	= 0xe6138010,
-		.end	= 0xe613801b,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= evt2irq(0x0b00),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device cmt10_device = {
-	.name		= "sh_cmt",
-	.id		= 10,
-	.dev = {
-		.platform_data	= &cmt10_platform_data,
-	},
-	.resource	= cmt10_resources,
-	.num_resources	= ARRAY_SIZE(cmt10_resources),
-};
-
 /* TMU */
 static struct sh_timer_config tmu00_platform_data = {
 	.name = "TMU00",
@@ -388,7 +356,6 @@ static struct platform_device *r8a7740_early_devices[] __initdata = {
 	&scif6_device,
 	&scif7_device,
 	&scifb_device,
-	&cmt10_device,
 	&tmu00_device,
 	&tmu01_device,
 	&tmu02_device,
-- 
1.7.9.5

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

* Re: [PATCH v3 1/7] ARM: shmobile: Define DT bindings for timer devices
  2013-03-17 15:43 ` Bastian Hecht
@ 2013-03-19  3:28   ` Simon Horman
  -1 siblings, 0 replies; 26+ messages in thread
From: Simon Horman @ 2013-03-19  3:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Mar 17, 2013 at 04:43:45PM +0100, Bastian Hecht wrote:
> The SH mobile series currently features 3 timer devices in the kernel:
> Compare Match Timer (CMT), Timer Unit (TMU) and MTU2. These devices
> share register layout characteristics amongst each that enable us to
> define common DT bindings for them.

Bastian, could you comment on the status of these changes.
I see no outstanding objections to them.

Magnus, ditto.

Paul, how do you want to handle merging these?
There are several shmobile changes so it could
be logical for me request arm-soc to take them.

> Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
> ---
> v3: same (only patch 0003 changed)
> 
>  .../devicetree/bindings/timer/renesas,timer.txt    |   45 ++++++++++++++++++++
>  1 file changed, 45 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/timer/renesas,timer.txt
> 
> diff --git a/Documentation/devicetree/bindings/timer/renesas,timer.txt b/Documentation/devicetree/bindings/timer/renesas,timer.txt
> new file mode 100644
> index 0000000..2c001bf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/renesas,timer.txt
> @@ -0,0 +1,45 @@
> +* Renesas SH Mobile Timer
> +
> +Bindings for several timer devices from Renesas including CMT, TMU and MTU2.
> +
> +Required properties:
> +- compatible : Should be "renesas,{device}-timer",
> +  whereas device is "cmt", "tmu" or "mtu2".
> +- reg : Address and length of the register set for the device
> +- interrupts : Timer interrupt
> +- renesas,device-id : The ID of the timer device
> +- renesas,channel-id : The channel ID of the timer device
> +- renesas,source-quality : The viability to use this device as a free
> +  running clock. From 0 (do not use) to 10 (best possible clock).
> +- renesas,event-quality : The viability to use this device as an event
> +  generator. From 0 (do not use) to 10 (best possible clock).
> +
> +The properties renesas,{source,event}-quality reflect the situation that the
> +usability of the timer devices depend on the location within their SoCs. E.g.
> +the power domain affinty affects power management, some mux-ed lines might be
> +preferred to be assigned to other functions and other constraints.
> +
> +Example for CMT1 channel 0 on the R8A7740 SoC:
> +
> +	timer@e6138010 {
> +		compatible = "renesas,cmt-timer";
> +		interrupt-parent = <&intca>;
> +		reg = <0xe6138010 0xc>;
> +		interrupts = <0x0b00>;
> +		renesas,device-id = <1>;
> +		renesas,channel-id = <0>;
> +		renesas,source-quality = <3>;
> +		renesas,event-quality = <3>;
> +	};
> +
> +Example for TMU0 channel 1 on the SH7372 SoC:
> +	timer@fff60014 {
> +		compatible = "renesas,tmu-timer";
> +		interrupt-parent = <&intcs>;
> +		reg = <0xfff60014 0xc>;
> +		interrupts = <0xea0>;
> +		renesas,device-id = <0>;
> +		renesas,channel-id = <1>;
> +		renesas,source-quality = <4>;
> +		renesas,event-quality = <0>;
> +	};
> -- 
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* [PATCH v3 1/7] ARM: shmobile: Define DT bindings for timer devices
@ 2013-03-19  3:28   ` Simon Horman
  0 siblings, 0 replies; 26+ messages in thread
From: Simon Horman @ 2013-03-19  3:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Mar 17, 2013 at 04:43:45PM +0100, Bastian Hecht wrote:
> The SH mobile series currently features 3 timer devices in the kernel:
> Compare Match Timer (CMT), Timer Unit (TMU) and MTU2. These devices
> share register layout characteristics amongst each that enable us to
> define common DT bindings for them.

Bastian, could you comment on the status of these changes.
I see no outstanding objections to them.

Magnus, ditto.

Paul, how do you want to handle merging these?
There are several shmobile changes so it could
be logical for me request arm-soc to take them.

> Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
> ---
> v3: same (only patch 0003 changed)
> 
>  .../devicetree/bindings/timer/renesas,timer.txt    |   45 ++++++++++++++++++++
>  1 file changed, 45 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/timer/renesas,timer.txt
> 
> diff --git a/Documentation/devicetree/bindings/timer/renesas,timer.txt b/Documentation/devicetree/bindings/timer/renesas,timer.txt
> new file mode 100644
> index 0000000..2c001bf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/renesas,timer.txt
> @@ -0,0 +1,45 @@
> +* Renesas SH Mobile Timer
> +
> +Bindings for several timer devices from Renesas including CMT, TMU and MTU2.
> +
> +Required properties:
> +- compatible : Should be "renesas,{device}-timer",
> +  whereas device is "cmt", "tmu" or "mtu2".
> +- reg : Address and length of the register set for the device
> +- interrupts : Timer interrupt
> +- renesas,device-id : The ID of the timer device
> +- renesas,channel-id : The channel ID of the timer device
> +- renesas,source-quality : The viability to use this device as a free
> +  running clock. From 0 (do not use) to 10 (best possible clock).
> +- renesas,event-quality : The viability to use this device as an event
> +  generator. From 0 (do not use) to 10 (best possible clock).
> +
> +The properties renesas,{source,event}-quality reflect the situation that the
> +usability of the timer devices depend on the location within their SoCs. E.g.
> +the power domain affinty affects power management, some mux-ed lines might be
> +preferred to be assigned to other functions and other constraints.
> +
> +Example for CMT1 channel 0 on the R8A7740 SoC:
> +
> +	timer at e6138010 {
> +		compatible = "renesas,cmt-timer";
> +		interrupt-parent = <&intca>;
> +		reg = <0xe6138010 0xc>;
> +		interrupts = <0x0b00>;
> +		renesas,device-id = <1>;
> +		renesas,channel-id = <0>;
> +		renesas,source-quality = <3>;
> +		renesas,event-quality = <3>;
> +	};
> +
> +Example for TMU0 channel 1 on the SH7372 SoC:
> +	timer at fff60014 {
> +		compatible = "renesas,tmu-timer";
> +		interrupt-parent = <&intcs>;
> +		reg = <0xfff60014 0xc>;
> +		interrupts = <0xea0>;
> +		renesas,device-id = <0>;
> +		renesas,channel-id = <1>;
> +		renesas,source-quality = <4>;
> +		renesas,event-quality = <0>;
> +	};
> -- 
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH v3 1/7] ARM: shmobile: Define DT bindings for timer devices
  2013-03-19  3:28   ` Simon Horman
@ 2013-03-19 10:19     ` Bastian Hecht
  -1 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-19 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Simon!

2013/3/19 Simon Horman <horms@verge.net.au>:
> On Sun, Mar 17, 2013 at 04:43:45PM +0100, Bastian Hecht wrote:
>> The SH mobile series currently features 3 timer devices in the kernel:
>> Compare Match Timer (CMT), Timer Unit (TMU) and MTU2. These devices
>> share register layout characteristics amongst each that enable us to
>> define common DT bindings for them.
>
> Bastian, could you comment on the status of these changes.
> I see no outstanding objections to them.

Yes I think they are fine as they are now and ready to be merged.

Thanks,

 Bastian


> Magnus, ditto.
>
> Paul, how do you want to handle merging these?
> There are several shmobile changes so it could
> be logical for me request arm-soc to take them.
>
>> Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
>> ---
>> v3: same (only patch 0003 changed)
>>
>>  .../devicetree/bindings/timer/renesas,timer.txt    |   45 ++++++++++++++++++++
>>  1 file changed, 45 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/timer/renesas,timer.txt
>>
>> diff --git a/Documentation/devicetree/bindings/timer/renesas,timer.txt b/Documentation/devicetree/bindings/timer/renesas,timer.txt
>> new file mode 100644
>> index 0000000..2c001bf
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/timer/renesas,timer.txt
>> @@ -0,0 +1,45 @@
>> +* Renesas SH Mobile Timer
>> +
>> +Bindings for several timer devices from Renesas including CMT, TMU and MTU2.
>> +
>> +Required properties:
>> +- compatible : Should be "renesas,{device}-timer",
>> +  whereas device is "cmt", "tmu" or "mtu2".
>> +- reg : Address and length of the register set for the device
>> +- interrupts : Timer interrupt
>> +- renesas,device-id : The ID of the timer device
>> +- renesas,channel-id : The channel ID of the timer device
>> +- renesas,source-quality : The viability to use this device as a free
>> +  running clock. From 0 (do not use) to 10 (best possible clock).
>> +- renesas,event-quality : The viability to use this device as an event
>> +  generator. From 0 (do not use) to 10 (best possible clock).
>> +
>> +The properties renesas,{source,event}-quality reflect the situation that the
>> +usability of the timer devices depend on the location within their SoCs. E.g.
>> +the power domain affinty affects power management, some mux-ed lines might be
>> +preferred to be assigned to other functions and other constraints.
>> +
>> +Example for CMT1 channel 0 on the R8A7740 SoC:
>> +
>> +     timer@e6138010 {
>> +             compatible = "renesas,cmt-timer";
>> +             interrupt-parent = <&intca>;
>> +             reg = <0xe6138010 0xc>;
>> +             interrupts = <0x0b00>;
>> +             renesas,device-id = <1>;
>> +             renesas,channel-id = <0>;
>> +             renesas,source-quality = <3>;
>> +             renesas,event-quality = <3>;
>> +     };
>> +
>> +Example for TMU0 channel 1 on the SH7372 SoC:
>> +     timer@fff60014 {
>> +             compatible = "renesas,tmu-timer";
>> +             interrupt-parent = <&intcs>;
>> +             reg = <0xfff60014 0xc>;
>> +             interrupts = <0xea0>;
>> +             renesas,device-id = <0>;
>> +             renesas,channel-id = <1>;
>> +             renesas,source-quality = <4>;
>> +             renesas,event-quality = <0>;
>> +     };
>> --
>> 1.7.9.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 1/7] ARM: shmobile: Define DT bindings for timer devices
@ 2013-03-19 10:19     ` Bastian Hecht
  0 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-03-19 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Simon!

2013/3/19 Simon Horman <horms@verge.net.au>:
> On Sun, Mar 17, 2013 at 04:43:45PM +0100, Bastian Hecht wrote:
>> The SH mobile series currently features 3 timer devices in the kernel:
>> Compare Match Timer (CMT), Timer Unit (TMU) and MTU2. These devices
>> share register layout characteristics amongst each that enable us to
>> define common DT bindings for them.
>
> Bastian, could you comment on the status of these changes.
> I see no outstanding objections to them.

Yes I think they are fine as they are now and ready to be merged.

Thanks,

 Bastian


> Magnus, ditto.
>
> Paul, how do you want to handle merging these?
> There are several shmobile changes so it could
> be logical for me request arm-soc to take them.
>
>> Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
>> ---
>> v3: same (only patch 0003 changed)
>>
>>  .../devicetree/bindings/timer/renesas,timer.txt    |   45 ++++++++++++++++++++
>>  1 file changed, 45 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/timer/renesas,timer.txt
>>
>> diff --git a/Documentation/devicetree/bindings/timer/renesas,timer.txt b/Documentation/devicetree/bindings/timer/renesas,timer.txt
>> new file mode 100644
>> index 0000000..2c001bf
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/timer/renesas,timer.txt
>> @@ -0,0 +1,45 @@
>> +* Renesas SH Mobile Timer
>> +
>> +Bindings for several timer devices from Renesas including CMT, TMU and MTU2.
>> +
>> +Required properties:
>> +- compatible : Should be "renesas,{device}-timer",
>> +  whereas device is "cmt", "tmu" or "mtu2".
>> +- reg : Address and length of the register set for the device
>> +- interrupts : Timer interrupt
>> +- renesas,device-id : The ID of the timer device
>> +- renesas,channel-id : The channel ID of the timer device
>> +- renesas,source-quality : The viability to use this device as a free
>> +  running clock. From 0 (do not use) to 10 (best possible clock).
>> +- renesas,event-quality : The viability to use this device as an event
>> +  generator. From 0 (do not use) to 10 (best possible clock).
>> +
>> +The properties renesas,{source,event}-quality reflect the situation that the
>> +usability of the timer devices depend on the location within their SoCs. E.g.
>> +the power domain affinty affects power management, some mux-ed lines might be
>> +preferred to be assigned to other functions and other constraints.
>> +
>> +Example for CMT1 channel 0 on the R8A7740 SoC:
>> +
>> +     timer at e6138010 {
>> +             compatible = "renesas,cmt-timer";
>> +             interrupt-parent = <&intca>;
>> +             reg = <0xe6138010 0xc>;
>> +             interrupts = <0x0b00>;
>> +             renesas,device-id = <1>;
>> +             renesas,channel-id = <0>;
>> +             renesas,source-quality = <3>;
>> +             renesas,event-quality = <3>;
>> +     };
>> +
>> +Example for TMU0 channel 1 on the SH7372 SoC:
>> +     timer at fff60014 {
>> +             compatible = "renesas,tmu-timer";
>> +             interrupt-parent = <&intcs>;
>> +             reg = <0xfff60014 0xc>;
>> +             interrupts = <0xea0>;
>> +             renesas,device-id = <0>;
>> +             renesas,channel-id = <1>;
>> +             renesas,source-quality = <4>;
>> +             renesas,event-quality = <0>;
>> +     };
>> --
>> 1.7.9.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v3 2/7] clocksource: sh_cmt: Add OF support
  2013-03-17 15:43   ` Bastian Hecht
@ 2013-03-21 13:07     ` Simon Horman
  -1 siblings, 0 replies; 26+ messages in thread
From: Simon Horman @ 2013-03-21 13:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Mar 17, 2013 at 04:43:46PM +0100, Bastian Hecht wrote:
> We add the capabilty to probe SH CMT timer devices using Device Tree
> setup.
> 
> Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
> ---
> v3: same (only patch 0003 changed)
> 
>  drivers/clocksource/sh_cmt.c |  109 +++++++++++++++++++++++++++++++++++++-----


This change appears to break booting of kzm9g-reference
with MMC enabled. I assume because it somehow causes CMT to
(once again) be initialised after SDHI and/or MMC.

Tested using next with the defconfig + CONFIG_MACH_KZM9G_REFERENCE=y +
initrd root fs.

>  1 file changed, 96 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
> index 08d0c41..79bc526 100644
> --- a/drivers/clocksource/sh_cmt.c
> +++ b/drivers/clocksource/sh_cmt.c
> @@ -34,10 +34,13 @@
>  #include <linux/module.h>
>  #include <linux/pm_domain.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/of.h>
>  
>  struct sh_cmt_priv {
>  	void __iomem *mapbase;
>  	struct clk *clk;
> +	long channel_offset;
> +	int timer_bit;
>  	unsigned long width; /* 16 or 32 bit version of hardware block */
>  	unsigned long overflow_bit;
>  	unsigned long clear_bits;
> @@ -109,9 +112,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
>  
>  static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
>  {
> -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
> -
> -	return p->read_control(p->mapbase - cfg->channel_offset, 0);
> +	return p->read_control(p->mapbase - p->channel_offset, 0);
>  }
>  
>  static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
> @@ -127,9 +128,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
>  static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
>  				      unsigned long value)
>  {
> -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
> -
> -	p->write_control(p->mapbase - cfg->channel_offset, 0, value);
> +	p->write_control(p->mapbase - p->channel_offset, 0, value);
>  }
>  
>  static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
> @@ -176,7 +175,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
>  
>  static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>  {
> -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>  	unsigned long flags, value;
>  
>  	/* start stop register shared by multiple timer channels */
> @@ -184,9 +182,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>  	value = sh_cmt_read_cmstr(p);
>  
>  	if (start)
> -		value |= 1 << cfg->timer_bit;
> +		value |= 1 << p->timer_bit;
>  	else
> -		value &= ~(1 << cfg->timer_bit);
> +		value &= ~(1 << p->timer_bit);
>  
>  	sh_cmt_write_cmstr(p, value);
>  	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
> @@ -673,9 +671,85 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
>  	return 0;
>  }
>  
> -static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
> +static const struct of_device_id of_sh_cmt_match[] = {
> +	{ .compatible = "renesas,cmt-timer" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, of_sh_cmt_match);
> +
> +static const int sh_cmt_offset_multiplier[] = { 0x60, 0x10, 0x40, 0x40, 0x40 };
> +#define CMT_MAX_CHANNELS	6
> +
> +static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev)
> +{
> +	struct sh_timer_config *cfg;
> +	struct device_node *np = dev->of_node;
> +	u32 timer_id, channel_id, rating;
> +
> +	if (!IS_ENABLED(CONFIG_OF) || !np)
> +		return NULL;
> +
> +	cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
> +	if (!cfg) {
> +		dev_err(dev, "failed to allocate DT config data\n");
> +		return NULL;
> +	}
> +
> +	if (of_property_read_u32(np, "renesas,device-id", &timer_id)) {
> +		dev_err(dev, "device id missing\n");
> +		return NULL;
> +	}
> +	if (timer_id >= ARRAY_SIZE(sh_cmt_offset_multiplier)) {
> +		dev_err(dev, "invalid device id\n");
> +		return NULL;
> +	}
> +
> +	if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
> +		dev_err(dev, "channel id missing\n");
> +		return NULL;
> +	}
> +	if (channel_id >= CMT_MAX_CHANNELS) {
> +		dev_err(dev, "invalid channel id\n");
> +		return NULL;
> +	}
> +
> +	cfg->channel_offset = sh_cmt_offset_multiplier[timer_id] *
> +							(channel_id + 1);
> +	cfg->timer_bit = channel_id;
> +
> +	/*
> +	 * We convert the {source,event}-quality DT properties to linux specific
> +	 * clock{source,event}_ratings.
> +	 */
> +	if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
> +		if (rating > 10) {
> +			dev_err(dev, "invalid source-quality\n");
> +			return NULL;
> +		}
> +		if (rating)
> +			cfg->clocksource_rating = rating * 50 - 1;
> +	}
> +
> +	if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
> +		if (rating > 10) {
> +			dev_err(dev, "invalid event-quality\n");
> +			return NULL;
> +		}
> +		if (rating)
> +			cfg->clockevent_rating = rating * 50 - 1;
> +	}
> +
> +	if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
> +		dev_err(dev, "source- and event-quality 0, timer is unused\n");
> +		return NULL;
> +	}
> +
> +	return cfg;
> +}
> +
> +static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev,
> +						struct sh_timer_config *cfg)
>  {
> -	struct sh_timer_config *cfg = pdev->dev.platform_data;
>  	struct resource *res;
>  	int irq, ret;
>  	ret = -ENXIO;
> @@ -762,6 +836,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
>  		goto err2;
>  	}
>  
> +	p->channel_offset = cfg->channel_offset;
> +	p->timer_bit = cfg->timer_bit;
> +
>  	platform_set_drvdata(pdev, p);
>  
>  	return 0;
> @@ -777,7 +854,7 @@ err0:
>  static int sh_cmt_probe(struct platform_device *pdev)
>  {
>  	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
> -	struct sh_timer_config *cfg = pdev->dev.platform_data;
> +	struct sh_timer_config *cfg;
>  	int ret;
>  
>  	if (!is_early_platform_device(pdev)) {
> @@ -785,6 +862,11 @@ static int sh_cmt_probe(struct platform_device *pdev)
>  		pm_runtime_enable(&pdev->dev);
>  	}
>  
> +	if (pdev->dev.of_node)
> +		cfg = sh_cmt_parse_dt(&pdev->dev);
> +	else
> +		cfg = pdev->dev.platform_data;
> +
>  	if (p) {
>  		dev_info(&pdev->dev, "kept as earlytimer\n");
>  		goto out;
> @@ -796,7 +878,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  	}
>  
> -	ret = sh_cmt_setup(p, pdev);
> +	ret = sh_cmt_setup(p, pdev, cfg);
>  	if (ret) {
>  		kfree(p);
>  		pm_runtime_idle(&pdev->dev);
> @@ -824,6 +906,7 @@ static struct platform_driver sh_cmt_device_driver = {
>  	.remove		= sh_cmt_remove,
>  	.driver		= {
>  		.name	= "sh_cmt",
> +		.of_match_table = of_match_ptr(of_sh_cmt_match),
>  	}
>  };
>  
> -- 
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* [PATCH v3 2/7] clocksource: sh_cmt: Add OF support
@ 2013-03-21 13:07     ` Simon Horman
  0 siblings, 0 replies; 26+ messages in thread
From: Simon Horman @ 2013-03-21 13:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Mar 17, 2013 at 04:43:46PM +0100, Bastian Hecht wrote:
> We add the capabilty to probe SH CMT timer devices using Device Tree
> setup.
> 
> Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
> ---
> v3: same (only patch 0003 changed)
> 
>  drivers/clocksource/sh_cmt.c |  109 +++++++++++++++++++++++++++++++++++++-----


This change appears to break booting of kzm9g-reference
with MMC enabled. I assume because it somehow causes CMT to
(once again) be initialised after SDHI and/or MMC.

Tested using next with the defconfig + CONFIG_MACH_KZM9G_REFERENCE=y +
initrd root fs.

>  1 file changed, 96 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
> index 08d0c41..79bc526 100644
> --- a/drivers/clocksource/sh_cmt.c
> +++ b/drivers/clocksource/sh_cmt.c
> @@ -34,10 +34,13 @@
>  #include <linux/module.h>
>  #include <linux/pm_domain.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/of.h>
>  
>  struct sh_cmt_priv {
>  	void __iomem *mapbase;
>  	struct clk *clk;
> +	long channel_offset;
> +	int timer_bit;
>  	unsigned long width; /* 16 or 32 bit version of hardware block */
>  	unsigned long overflow_bit;
>  	unsigned long clear_bits;
> @@ -109,9 +112,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
>  
>  static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
>  {
> -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
> -
> -	return p->read_control(p->mapbase - cfg->channel_offset, 0);
> +	return p->read_control(p->mapbase - p->channel_offset, 0);
>  }
>  
>  static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
> @@ -127,9 +128,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
>  static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
>  				      unsigned long value)
>  {
> -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
> -
> -	p->write_control(p->mapbase - cfg->channel_offset, 0, value);
> +	p->write_control(p->mapbase - p->channel_offset, 0, value);
>  }
>  
>  static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
> @@ -176,7 +175,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
>  
>  static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>  {
> -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>  	unsigned long flags, value;
>  
>  	/* start stop register shared by multiple timer channels */
> @@ -184,9 +182,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>  	value = sh_cmt_read_cmstr(p);
>  
>  	if (start)
> -		value |= 1 << cfg->timer_bit;
> +		value |= 1 << p->timer_bit;
>  	else
> -		value &= ~(1 << cfg->timer_bit);
> +		value &= ~(1 << p->timer_bit);
>  
>  	sh_cmt_write_cmstr(p, value);
>  	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
> @@ -673,9 +671,85 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
>  	return 0;
>  }
>  
> -static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
> +static const struct of_device_id of_sh_cmt_match[] = {
> +	{ .compatible = "renesas,cmt-timer" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, of_sh_cmt_match);
> +
> +static const int sh_cmt_offset_multiplier[] = { 0x60, 0x10, 0x40, 0x40, 0x40 };
> +#define CMT_MAX_CHANNELS	6
> +
> +static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev)
> +{
> +	struct sh_timer_config *cfg;
> +	struct device_node *np = dev->of_node;
> +	u32 timer_id, channel_id, rating;
> +
> +	if (!IS_ENABLED(CONFIG_OF) || !np)
> +		return NULL;
> +
> +	cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
> +	if (!cfg) {
> +		dev_err(dev, "failed to allocate DT config data\n");
> +		return NULL;
> +	}
> +
> +	if (of_property_read_u32(np, "renesas,device-id", &timer_id)) {
> +		dev_err(dev, "device id missing\n");
> +		return NULL;
> +	}
> +	if (timer_id >= ARRAY_SIZE(sh_cmt_offset_multiplier)) {
> +		dev_err(dev, "invalid device id\n");
> +		return NULL;
> +	}
> +
> +	if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
> +		dev_err(dev, "channel id missing\n");
> +		return NULL;
> +	}
> +	if (channel_id >= CMT_MAX_CHANNELS) {
> +		dev_err(dev, "invalid channel id\n");
> +		return NULL;
> +	}
> +
> +	cfg->channel_offset = sh_cmt_offset_multiplier[timer_id] *
> +							(channel_id + 1);
> +	cfg->timer_bit = channel_id;
> +
> +	/*
> +	 * We convert the {source,event}-quality DT properties to linux specific
> +	 * clock{source,event}_ratings.
> +	 */
> +	if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
> +		if (rating > 10) {
> +			dev_err(dev, "invalid source-quality\n");
> +			return NULL;
> +		}
> +		if (rating)
> +			cfg->clocksource_rating = rating * 50 - 1;
> +	}
> +
> +	if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
> +		if (rating > 10) {
> +			dev_err(dev, "invalid event-quality\n");
> +			return NULL;
> +		}
> +		if (rating)
> +			cfg->clockevent_rating = rating * 50 - 1;
> +	}
> +
> +	if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
> +		dev_err(dev, "source- and event-quality 0, timer is unused\n");
> +		return NULL;
> +	}
> +
> +	return cfg;
> +}
> +
> +static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev,
> +						struct sh_timer_config *cfg)
>  {
> -	struct sh_timer_config *cfg = pdev->dev.platform_data;
>  	struct resource *res;
>  	int irq, ret;
>  	ret = -ENXIO;
> @@ -762,6 +836,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
>  		goto err2;
>  	}
>  
> +	p->channel_offset = cfg->channel_offset;
> +	p->timer_bit = cfg->timer_bit;
> +
>  	platform_set_drvdata(pdev, p);
>  
>  	return 0;
> @@ -777,7 +854,7 @@ err0:
>  static int sh_cmt_probe(struct platform_device *pdev)
>  {
>  	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
> -	struct sh_timer_config *cfg = pdev->dev.platform_data;
> +	struct sh_timer_config *cfg;
>  	int ret;
>  
>  	if (!is_early_platform_device(pdev)) {
> @@ -785,6 +862,11 @@ static int sh_cmt_probe(struct platform_device *pdev)
>  		pm_runtime_enable(&pdev->dev);
>  	}
>  
> +	if (pdev->dev.of_node)
> +		cfg = sh_cmt_parse_dt(&pdev->dev);
> +	else
> +		cfg = pdev->dev.platform_data;
> +
>  	if (p) {
>  		dev_info(&pdev->dev, "kept as earlytimer\n");
>  		goto out;
> @@ -796,7 +878,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  	}
>  
> -	ret = sh_cmt_setup(p, pdev);
> +	ret = sh_cmt_setup(p, pdev, cfg);
>  	if (ret) {
>  		kfree(p);
>  		pm_runtime_idle(&pdev->dev);
> @@ -824,6 +906,7 @@ static struct platform_driver sh_cmt_device_driver = {
>  	.remove		= sh_cmt_remove,
>  	.driver		= {
>  		.name	= "sh_cmt",
> +		.of_match_table = of_match_ptr(of_sh_cmt_match),
>  	}
>  };
>  
> -- 
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH v3 2/7] clocksource: sh_cmt: Add OF support
  2013-03-21 13:07     ` Simon Horman
@ 2013-04-09 13:38       ` Simon Horman
  -1 siblings, 0 replies; 26+ messages in thread
From: Simon Horman @ 2013-04-09 13:38 UTC (permalink / raw)
  To: linux-arm-kernel

On 木,  3月 21, 2013 at 10:07:15午後 +0900, Simon Horman wrote:
> On Sun, Mar 17, 2013 at 04:43:46PM +0100, Bastian Hecht wrote:
> > We add the capabilty to probe SH CMT timer devices using Device Tree
> > setup.
> > 
> > Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
> > ---
> > v3: same (only patch 0003 changed)
> > 
> >  drivers/clocksource/sh_cmt.c |  109 +++++++++++++++++++++++++++++++++++++-----
> 
> 
> This change appears to break booting of kzm9g-reference
> with MMC enabled. I assume because it somehow causes CMT to
> (once again) be initialised after SDHI and/or MMC.
> 
> Tested using next with the defconfig + CONFIG_MACH_KZM9G_REFERENCE=y +
> initrd root fs.

Ping.

> >  1 file changed, 96 insertions(+), 13 deletions(-)
> > 
> > diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
> > index 08d0c41..79bc526 100644
> > --- a/drivers/clocksource/sh_cmt.c
> > +++ b/drivers/clocksource/sh_cmt.c
> > @@ -34,10 +34,13 @@
> >  #include <linux/module.h>
> >  #include <linux/pm_domain.h>
> >  #include <linux/pm_runtime.h>
> > +#include <linux/of.h>
> >  
> >  struct sh_cmt_priv {
> >  	void __iomem *mapbase;
> >  	struct clk *clk;
> > +	long channel_offset;
> > +	int timer_bit;
> >  	unsigned long width; /* 16 or 32 bit version of hardware block */
> >  	unsigned long overflow_bit;
> >  	unsigned long clear_bits;
> > @@ -109,9 +112,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
> >  
> >  static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
> >  {
> > -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
> > -
> > -	return p->read_control(p->mapbase - cfg->channel_offset, 0);
> > +	return p->read_control(p->mapbase - p->channel_offset, 0);
> >  }
> >  
> >  static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
> > @@ -127,9 +128,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
> >  static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
> >  				      unsigned long value)
> >  {
> > -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
> > -
> > -	p->write_control(p->mapbase - cfg->channel_offset, 0, value);
> > +	p->write_control(p->mapbase - p->channel_offset, 0, value);
> >  }
> >  
> >  static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
> > @@ -176,7 +175,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
> >  
> >  static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
> >  {
> > -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
> >  	unsigned long flags, value;
> >  
> >  	/* start stop register shared by multiple timer channels */
> > @@ -184,9 +182,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
> >  	value = sh_cmt_read_cmstr(p);
> >  
> >  	if (start)
> > -		value |= 1 << cfg->timer_bit;
> > +		value |= 1 << p->timer_bit;
> >  	else
> > -		value &= ~(1 << cfg->timer_bit);
> > +		value &= ~(1 << p->timer_bit);
> >  
> >  	sh_cmt_write_cmstr(p, value);
> >  	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
> > @@ -673,9 +671,85 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
> >  	return 0;
> >  }
> >  
> > -static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
> > +static const struct of_device_id of_sh_cmt_match[] = {
> > +	{ .compatible = "renesas,cmt-timer" },
> > +	{},
> > +};
> > +MODULE_DEVICE_TABLE(of, of_sh_cmt_match);
> > +
> > +static const int sh_cmt_offset_multiplier[] = { 0x60, 0x10, 0x40, 0x40, 0x40 };
> > +#define CMT_MAX_CHANNELS	6
> > +
> > +static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev)
> > +{
> > +	struct sh_timer_config *cfg;
> > +	struct device_node *np = dev->of_node;
> > +	u32 timer_id, channel_id, rating;
> > +
> > +	if (!IS_ENABLED(CONFIG_OF) || !np)
> > +		return NULL;
> > +
> > +	cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
> > +	if (!cfg) {
> > +		dev_err(dev, "failed to allocate DT config data\n");
> > +		return NULL;
> > +	}
> > +
> > +	if (of_property_read_u32(np, "renesas,device-id", &timer_id)) {
> > +		dev_err(dev, "device id missing\n");
> > +		return NULL;
> > +	}
> > +	if (timer_id >= ARRAY_SIZE(sh_cmt_offset_multiplier)) {
> > +		dev_err(dev, "invalid device id\n");
> > +		return NULL;
> > +	}
> > +
> > +	if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
> > +		dev_err(dev, "channel id missing\n");
> > +		return NULL;
> > +	}
> > +	if (channel_id >= CMT_MAX_CHANNELS) {
> > +		dev_err(dev, "invalid channel id\n");
> > +		return NULL;
> > +	}
> > +
> > +	cfg->channel_offset = sh_cmt_offset_multiplier[timer_id] *
> > +							(channel_id + 1);
> > +	cfg->timer_bit = channel_id;
> > +
> > +	/*
> > +	 * We convert the {source,event}-quality DT properties to linux specific
> > +	 * clock{source,event}_ratings.
> > +	 */
> > +	if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
> > +		if (rating > 10) {
> > +			dev_err(dev, "invalid source-quality\n");
> > +			return NULL;
> > +		}
> > +		if (rating)
> > +			cfg->clocksource_rating = rating * 50 - 1;
> > +	}
> > +
> > +	if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
> > +		if (rating > 10) {
> > +			dev_err(dev, "invalid event-quality\n");
> > +			return NULL;
> > +		}
> > +		if (rating)
> > +			cfg->clockevent_rating = rating * 50 - 1;
> > +	}
> > +
> > +	if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
> > +		dev_err(dev, "source- and event-quality 0, timer is unused\n");
> > +		return NULL;
> > +	}
> > +
> > +	return cfg;
> > +}
> > +
> > +static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev,
> > +						struct sh_timer_config *cfg)
> >  {
> > -	struct sh_timer_config *cfg = pdev->dev.platform_data;
> >  	struct resource *res;
> >  	int irq, ret;
> >  	ret = -ENXIO;
> > @@ -762,6 +836,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
> >  		goto err2;
> >  	}
> >  
> > +	p->channel_offset = cfg->channel_offset;
> > +	p->timer_bit = cfg->timer_bit;
> > +
> >  	platform_set_drvdata(pdev, p);
> >  
> >  	return 0;
> > @@ -777,7 +854,7 @@ err0:
> >  static int sh_cmt_probe(struct platform_device *pdev)
> >  {
> >  	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
> > -	struct sh_timer_config *cfg = pdev->dev.platform_data;
> > +	struct sh_timer_config *cfg;
> >  	int ret;
> >  
> >  	if (!is_early_platform_device(pdev)) {
> > @@ -785,6 +862,11 @@ static int sh_cmt_probe(struct platform_device *pdev)
> >  		pm_runtime_enable(&pdev->dev);
> >  	}
> >  
> > +	if (pdev->dev.of_node)
> > +		cfg = sh_cmt_parse_dt(&pdev->dev);
> > +	else
> > +		cfg = pdev->dev.platform_data;
> > +
> >  	if (p) {
> >  		dev_info(&pdev->dev, "kept as earlytimer\n");
> >  		goto out;
> > @@ -796,7 +878,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
> >  		return -ENOMEM;
> >  	}
> >  
> > -	ret = sh_cmt_setup(p, pdev);
> > +	ret = sh_cmt_setup(p, pdev, cfg);
> >  	if (ret) {
> >  		kfree(p);
> >  		pm_runtime_idle(&pdev->dev);
> > @@ -824,6 +906,7 @@ static struct platform_driver sh_cmt_device_driver = {
> >  	.remove		= sh_cmt_remove,
> >  	.driver		= {
> >  		.name	= "sh_cmt",
> > +		.of_match_table = of_match_ptr(of_sh_cmt_match),
> >  	}
> >  };
> >  
> > -- 
> > 1.7.9.5
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* [PATCH v3 2/7] clocksource: sh_cmt: Add OF support
@ 2013-04-09 13:38       ` Simon Horman
  0 siblings, 0 replies; 26+ messages in thread
From: Simon Horman @ 2013-04-09 13:38 UTC (permalink / raw)
  To: linux-arm-kernel

On ?,  3? 21, 2013 at 10:07:15?? +0900, Simon Horman wrote:
> On Sun, Mar 17, 2013 at 04:43:46PM +0100, Bastian Hecht wrote:
> > We add the capabilty to probe SH CMT timer devices using Device Tree
> > setup.
> > 
> > Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
> > ---
> > v3: same (only patch 0003 changed)
> > 
> >  drivers/clocksource/sh_cmt.c |  109 +++++++++++++++++++++++++++++++++++++-----
> 
> 
> This change appears to break booting of kzm9g-reference
> with MMC enabled. I assume because it somehow causes CMT to
> (once again) be initialised after SDHI and/or MMC.
> 
> Tested using next with the defconfig + CONFIG_MACH_KZM9G_REFERENCE=y +
> initrd root fs.

Ping.

> >  1 file changed, 96 insertions(+), 13 deletions(-)
> > 
> > diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
> > index 08d0c41..79bc526 100644
> > --- a/drivers/clocksource/sh_cmt.c
> > +++ b/drivers/clocksource/sh_cmt.c
> > @@ -34,10 +34,13 @@
> >  #include <linux/module.h>
> >  #include <linux/pm_domain.h>
> >  #include <linux/pm_runtime.h>
> > +#include <linux/of.h>
> >  
> >  struct sh_cmt_priv {
> >  	void __iomem *mapbase;
> >  	struct clk *clk;
> > +	long channel_offset;
> > +	int timer_bit;
> >  	unsigned long width; /* 16 or 32 bit version of hardware block */
> >  	unsigned long overflow_bit;
> >  	unsigned long clear_bits;
> > @@ -109,9 +112,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
> >  
> >  static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
> >  {
> > -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
> > -
> > -	return p->read_control(p->mapbase - cfg->channel_offset, 0);
> > +	return p->read_control(p->mapbase - p->channel_offset, 0);
> >  }
> >  
> >  static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
> > @@ -127,9 +128,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
> >  static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
> >  				      unsigned long value)
> >  {
> > -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
> > -
> > -	p->write_control(p->mapbase - cfg->channel_offset, 0, value);
> > +	p->write_control(p->mapbase - p->channel_offset, 0, value);
> >  }
> >  
> >  static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
> > @@ -176,7 +175,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
> >  
> >  static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
> >  {
> > -	struct sh_timer_config *cfg = p->pdev->dev.platform_data;
> >  	unsigned long flags, value;
> >  
> >  	/* start stop register shared by multiple timer channels */
> > @@ -184,9 +182,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
> >  	value = sh_cmt_read_cmstr(p);
> >  
> >  	if (start)
> > -		value |= 1 << cfg->timer_bit;
> > +		value |= 1 << p->timer_bit;
> >  	else
> > -		value &= ~(1 << cfg->timer_bit);
> > +		value &= ~(1 << p->timer_bit);
> >  
> >  	sh_cmt_write_cmstr(p, value);
> >  	raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
> > @@ -673,9 +671,85 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
> >  	return 0;
> >  }
> >  
> > -static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
> > +static const struct of_device_id of_sh_cmt_match[] = {
> > +	{ .compatible = "renesas,cmt-timer" },
> > +	{},
> > +};
> > +MODULE_DEVICE_TABLE(of, of_sh_cmt_match);
> > +
> > +static const int sh_cmt_offset_multiplier[] = { 0x60, 0x10, 0x40, 0x40, 0x40 };
> > +#define CMT_MAX_CHANNELS	6
> > +
> > +static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev)
> > +{
> > +	struct sh_timer_config *cfg;
> > +	struct device_node *np = dev->of_node;
> > +	u32 timer_id, channel_id, rating;
> > +
> > +	if (!IS_ENABLED(CONFIG_OF) || !np)
> > +		return NULL;
> > +
> > +	cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
> > +	if (!cfg) {
> > +		dev_err(dev, "failed to allocate DT config data\n");
> > +		return NULL;
> > +	}
> > +
> > +	if (of_property_read_u32(np, "renesas,device-id", &timer_id)) {
> > +		dev_err(dev, "device id missing\n");
> > +		return NULL;
> > +	}
> > +	if (timer_id >= ARRAY_SIZE(sh_cmt_offset_multiplier)) {
> > +		dev_err(dev, "invalid device id\n");
> > +		return NULL;
> > +	}
> > +
> > +	if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
> > +		dev_err(dev, "channel id missing\n");
> > +		return NULL;
> > +	}
> > +	if (channel_id >= CMT_MAX_CHANNELS) {
> > +		dev_err(dev, "invalid channel id\n");
> > +		return NULL;
> > +	}
> > +
> > +	cfg->channel_offset = sh_cmt_offset_multiplier[timer_id] *
> > +							(channel_id + 1);
> > +	cfg->timer_bit = channel_id;
> > +
> > +	/*
> > +	 * We convert the {source,event}-quality DT properties to linux specific
> > +	 * clock{source,event}_ratings.
> > +	 */
> > +	if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
> > +		if (rating > 10) {
> > +			dev_err(dev, "invalid source-quality\n");
> > +			return NULL;
> > +		}
> > +		if (rating)
> > +			cfg->clocksource_rating = rating * 50 - 1;
> > +	}
> > +
> > +	if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
> > +		if (rating > 10) {
> > +			dev_err(dev, "invalid event-quality\n");
> > +			return NULL;
> > +		}
> > +		if (rating)
> > +			cfg->clockevent_rating = rating * 50 - 1;
> > +	}
> > +
> > +	if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
> > +		dev_err(dev, "source- and event-quality 0, timer is unused\n");
> > +		return NULL;
> > +	}
> > +
> > +	return cfg;
> > +}
> > +
> > +static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev,
> > +						struct sh_timer_config *cfg)
> >  {
> > -	struct sh_timer_config *cfg = pdev->dev.platform_data;
> >  	struct resource *res;
> >  	int irq, ret;
> >  	ret = -ENXIO;
> > @@ -762,6 +836,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
> >  		goto err2;
> >  	}
> >  
> > +	p->channel_offset = cfg->channel_offset;
> > +	p->timer_bit = cfg->timer_bit;
> > +
> >  	platform_set_drvdata(pdev, p);
> >  
> >  	return 0;
> > @@ -777,7 +854,7 @@ err0:
> >  static int sh_cmt_probe(struct platform_device *pdev)
> >  {
> >  	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
> > -	struct sh_timer_config *cfg = pdev->dev.platform_data;
> > +	struct sh_timer_config *cfg;
> >  	int ret;
> >  
> >  	if (!is_early_platform_device(pdev)) {
> > @@ -785,6 +862,11 @@ static int sh_cmt_probe(struct platform_device *pdev)
> >  		pm_runtime_enable(&pdev->dev);
> >  	}
> >  
> > +	if (pdev->dev.of_node)
> > +		cfg = sh_cmt_parse_dt(&pdev->dev);
> > +	else
> > +		cfg = pdev->dev.platform_data;
> > +
> >  	if (p) {
> >  		dev_info(&pdev->dev, "kept as earlytimer\n");
> >  		goto out;
> > @@ -796,7 +878,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
> >  		return -ENOMEM;
> >  	}
> >  
> > -	ret = sh_cmt_setup(p, pdev);
> > +	ret = sh_cmt_setup(p, pdev, cfg);
> >  	if (ret) {
> >  		kfree(p);
> >  		pm_runtime_idle(&pdev->dev);
> > @@ -824,6 +906,7 @@ static struct platform_driver sh_cmt_device_driver = {
> >  	.remove		= sh_cmt_remove,
> >  	.driver		= {
> >  		.name	= "sh_cmt",
> > +		.of_match_table = of_match_ptr(of_sh_cmt_match),
> >  	}
> >  };
> >  
> > -- 
> > 1.7.9.5
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> > the body of a message to majordomo at vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH v3 2/7] clocksource: sh_cmt: Add OF support
  2013-04-09 13:38       ` Simon Horman
@ 2013-04-09 15:06         ` Bastian Hecht
  -1 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-04-09 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Simon,

2013/4/9 Simon Horman <horms@verge.net.au>:
> On 木,  3月 21, 2013 at 10:07:15午後 +0900, Simon Horman wrote:
>> On Sun, Mar 17, 2013 at 04:43:46PM +0100, Bastian Hecht wrote:
>> > We add the capabilty to probe SH CMT timer devices using Device Tree
>> > setup.
>> >
>> > Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
>> > ---
>> > v3: same (only patch 0003 changed)
>> >
>> >  drivers/clocksource/sh_cmt.c |  109 +++++++++++++++++++++++++++++++++++++-----
>>
>>
>> This change appears to break booting of kzm9g-reference
>> with MMC enabled. I assume because it somehow causes CMT to
>> (once again) be initialised after SDHI and/or MMC.
>>
>> Tested using next with the defconfig + CONFIG_MACH_KZM9G_REFERENCE=y +
>> initrd root fs.
>

Thanks for finding this flaw. I've got it on my agenda.

Bastian

>> >  1 file changed, 96 insertions(+), 13 deletions(-)
>> >
>> > diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
>> > index 08d0c41..79bc526 100644
>> > --- a/drivers/clocksource/sh_cmt.c
>> > +++ b/drivers/clocksource/sh_cmt.c
>> > @@ -34,10 +34,13 @@
>> >  #include <linux/module.h>
>> >  #include <linux/pm_domain.h>
>> >  #include <linux/pm_runtime.h>
>> > +#include <linux/of.h>
>> >
>> >  struct sh_cmt_priv {
>> >     void __iomem *mapbase;
>> >     struct clk *clk;
>> > +   long channel_offset;
>> > +   int timer_bit;
>> >     unsigned long width; /* 16 or 32 bit version of hardware block */
>> >     unsigned long overflow_bit;
>> >     unsigned long clear_bits;
>> > @@ -109,9 +112,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
>> >
>> >  static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
>> >  {
>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>> > -
>> > -   return p->read_control(p->mapbase - cfg->channel_offset, 0);
>> > +   return p->read_control(p->mapbase - p->channel_offset, 0);
>> >  }
>> >
>> >  static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
>> > @@ -127,9 +128,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
>> >  static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
>> >                                   unsigned long value)
>> >  {
>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>> > -
>> > -   p->write_control(p->mapbase - cfg->channel_offset, 0, value);
>> > +   p->write_control(p->mapbase - p->channel_offset, 0, value);
>> >  }
>> >
>> >  static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
>> > @@ -176,7 +175,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
>> >
>> >  static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>> >  {
>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>> >     unsigned long flags, value;
>> >
>> >     /* start stop register shared by multiple timer channels */
>> > @@ -184,9 +182,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>> >     value = sh_cmt_read_cmstr(p);
>> >
>> >     if (start)
>> > -           value |= 1 << cfg->timer_bit;
>> > +           value |= 1 << p->timer_bit;
>> >     else
>> > -           value &= ~(1 << cfg->timer_bit);
>> > +           value &= ~(1 << p->timer_bit);
>> >
>> >     sh_cmt_write_cmstr(p, value);
>> >     raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
>> > @@ -673,9 +671,85 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
>> >     return 0;
>> >  }
>> >
>> > -static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
>> > +static const struct of_device_id of_sh_cmt_match[] = {
>> > +   { .compatible = "renesas,cmt-timer" },
>> > +   {},
>> > +};
>> > +MODULE_DEVICE_TABLE(of, of_sh_cmt_match);
>> > +
>> > +static const int sh_cmt_offset_multiplier[] = { 0x60, 0x10, 0x40, 0x40, 0x40 };
>> > +#define CMT_MAX_CHANNELS   6
>> > +
>> > +static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev)
>> > +{
>> > +   struct sh_timer_config *cfg;
>> > +   struct device_node *np = dev->of_node;
>> > +   u32 timer_id, channel_id, rating;
>> > +
>> > +   if (!IS_ENABLED(CONFIG_OF) || !np)
>> > +           return NULL;
>> > +
>> > +   cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
>> > +   if (!cfg) {
>> > +           dev_err(dev, "failed to allocate DT config data\n");
>> > +           return NULL;
>> > +   }
>> > +
>> > +   if (of_property_read_u32(np, "renesas,device-id", &timer_id)) {
>> > +           dev_err(dev, "device id missing\n");
>> > +           return NULL;
>> > +   }
>> > +   if (timer_id >= ARRAY_SIZE(sh_cmt_offset_multiplier)) {
>> > +           dev_err(dev, "invalid device id\n");
>> > +           return NULL;
>> > +   }
>> > +
>> > +   if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
>> > +           dev_err(dev, "channel id missing\n");
>> > +           return NULL;
>> > +   }
>> > +   if (channel_id >= CMT_MAX_CHANNELS) {
>> > +           dev_err(dev, "invalid channel id\n");
>> > +           return NULL;
>> > +   }
>> > +
>> > +   cfg->channel_offset = sh_cmt_offset_multiplier[timer_id] *
>> > +                                                   (channel_id + 1);
>> > +   cfg->timer_bit = channel_id;
>> > +
>> > +   /*
>> > +    * We convert the {source,event}-quality DT properties to linux specific
>> > +    * clock{source,event}_ratings.
>> > +    */
>> > +   if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
>> > +           if (rating > 10) {
>> > +                   dev_err(dev, "invalid source-quality\n");
>> > +                   return NULL;
>> > +           }
>> > +           if (rating)
>> > +                   cfg->clocksource_rating = rating * 50 - 1;
>> > +   }
>> > +
>> > +   if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
>> > +           if (rating > 10) {
>> > +                   dev_err(dev, "invalid event-quality\n");
>> > +                   return NULL;
>> > +           }
>> > +           if (rating)
>> > +                   cfg->clockevent_rating = rating * 50 - 1;
>> > +   }
>> > +
>> > +   if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
>> > +           dev_err(dev, "source- and event-quality 0, timer is unused\n");
>> > +           return NULL;
>> > +   }
>> > +
>> > +   return cfg;
>> > +}
>> > +
>> > +static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev,
>> > +                                           struct sh_timer_config *cfg)
>> >  {
>> > -   struct sh_timer_config *cfg = pdev->dev.platform_data;
>> >     struct resource *res;
>> >     int irq, ret;
>> >     ret = -ENXIO;
>> > @@ -762,6 +836,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
>> >             goto err2;
>> >     }
>> >
>> > +   p->channel_offset = cfg->channel_offset;
>> > +   p->timer_bit = cfg->timer_bit;
>> > +
>> >     platform_set_drvdata(pdev, p);
>> >
>> >     return 0;
>> > @@ -777,7 +854,7 @@ err0:
>> >  static int sh_cmt_probe(struct platform_device *pdev)
>> >  {
>> >     struct sh_cmt_priv *p = platform_get_drvdata(pdev);
>> > -   struct sh_timer_config *cfg = pdev->dev.platform_data;
>> > +   struct sh_timer_config *cfg;
>> >     int ret;
>> >
>> >     if (!is_early_platform_device(pdev)) {
>> > @@ -785,6 +862,11 @@ static int sh_cmt_probe(struct platform_device *pdev)
>> >             pm_runtime_enable(&pdev->dev);
>> >     }
>> >
>> > +   if (pdev->dev.of_node)
>> > +           cfg = sh_cmt_parse_dt(&pdev->dev);
>> > +   else
>> > +           cfg = pdev->dev.platform_data;
>> > +
>> >     if (p) {
>> >             dev_info(&pdev->dev, "kept as earlytimer\n");
>> >             goto out;
>> > @@ -796,7 +878,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
>> >             return -ENOMEM;
>> >     }
>> >
>> > -   ret = sh_cmt_setup(p, pdev);
>> > +   ret = sh_cmt_setup(p, pdev, cfg);
>> >     if (ret) {
>> >             kfree(p);
>> >             pm_runtime_idle(&pdev->dev);
>> > @@ -824,6 +906,7 @@ static struct platform_driver sh_cmt_device_driver = {
>> >     .remove         = sh_cmt_remove,
>> >     .driver         = {
>> >             .name   = "sh_cmt",
>> > +           .of_match_table = of_match_ptr(of_sh_cmt_match),
>> >     }
>> >  };
>> >
>> > --
>> > 1.7.9.5
>> >
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>> > the body of a message to majordomo@vger.kernel.org
>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> >
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>

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

* [PATCH v3 2/7] clocksource: sh_cmt: Add OF support
@ 2013-04-09 15:06         ` Bastian Hecht
  0 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-04-09 15:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Simon,

2013/4/9 Simon Horman <horms@verge.net.au>:
> On ?,  3? 21, 2013 at 10:07:15?? +0900, Simon Horman wrote:
>> On Sun, Mar 17, 2013 at 04:43:46PM +0100, Bastian Hecht wrote:
>> > We add the capabilty to probe SH CMT timer devices using Device Tree
>> > setup.
>> >
>> > Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
>> > ---
>> > v3: same (only patch 0003 changed)
>> >
>> >  drivers/clocksource/sh_cmt.c |  109 +++++++++++++++++++++++++++++++++++++-----
>>
>>
>> This change appears to break booting of kzm9g-reference
>> with MMC enabled. I assume because it somehow causes CMT to
>> (once again) be initialised after SDHI and/or MMC.
>>
>> Tested using next with the defconfig + CONFIG_MACH_KZM9G_REFERENCE=y +
>> initrd root fs.
>

Thanks for finding this flaw. I've got it on my agenda.

Bastian

>> >  1 file changed, 96 insertions(+), 13 deletions(-)
>> >
>> > diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
>> > index 08d0c41..79bc526 100644
>> > --- a/drivers/clocksource/sh_cmt.c
>> > +++ b/drivers/clocksource/sh_cmt.c
>> > @@ -34,10 +34,13 @@
>> >  #include <linux/module.h>
>> >  #include <linux/pm_domain.h>
>> >  #include <linux/pm_runtime.h>
>> > +#include <linux/of.h>
>> >
>> >  struct sh_cmt_priv {
>> >     void __iomem *mapbase;
>> >     struct clk *clk;
>> > +   long channel_offset;
>> > +   int timer_bit;
>> >     unsigned long width; /* 16 or 32 bit version of hardware block */
>> >     unsigned long overflow_bit;
>> >     unsigned long clear_bits;
>> > @@ -109,9 +112,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
>> >
>> >  static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
>> >  {
>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>> > -
>> > -   return p->read_control(p->mapbase - cfg->channel_offset, 0);
>> > +   return p->read_control(p->mapbase - p->channel_offset, 0);
>> >  }
>> >
>> >  static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
>> > @@ -127,9 +128,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
>> >  static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
>> >                                   unsigned long value)
>> >  {
>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>> > -
>> > -   p->write_control(p->mapbase - cfg->channel_offset, 0, value);
>> > +   p->write_control(p->mapbase - p->channel_offset, 0, value);
>> >  }
>> >
>> >  static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
>> > @@ -176,7 +175,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
>> >
>> >  static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>> >  {
>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>> >     unsigned long flags, value;
>> >
>> >     /* start stop register shared by multiple timer channels */
>> > @@ -184,9 +182,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>> >     value = sh_cmt_read_cmstr(p);
>> >
>> >     if (start)
>> > -           value |= 1 << cfg->timer_bit;
>> > +           value |= 1 << p->timer_bit;
>> >     else
>> > -           value &= ~(1 << cfg->timer_bit);
>> > +           value &= ~(1 << p->timer_bit);
>> >
>> >     sh_cmt_write_cmstr(p, value);
>> >     raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
>> > @@ -673,9 +671,85 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
>> >     return 0;
>> >  }
>> >
>> > -static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
>> > +static const struct of_device_id of_sh_cmt_match[] = {
>> > +   { .compatible = "renesas,cmt-timer" },
>> > +   {},
>> > +};
>> > +MODULE_DEVICE_TABLE(of, of_sh_cmt_match);
>> > +
>> > +static const int sh_cmt_offset_multiplier[] = { 0x60, 0x10, 0x40, 0x40, 0x40 };
>> > +#define CMT_MAX_CHANNELS   6
>> > +
>> > +static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev)
>> > +{
>> > +   struct sh_timer_config *cfg;
>> > +   struct device_node *np = dev->of_node;
>> > +   u32 timer_id, channel_id, rating;
>> > +
>> > +   if (!IS_ENABLED(CONFIG_OF) || !np)
>> > +           return NULL;
>> > +
>> > +   cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
>> > +   if (!cfg) {
>> > +           dev_err(dev, "failed to allocate DT config data\n");
>> > +           return NULL;
>> > +   }
>> > +
>> > +   if (of_property_read_u32(np, "renesas,device-id", &timer_id)) {
>> > +           dev_err(dev, "device id missing\n");
>> > +           return NULL;
>> > +   }
>> > +   if (timer_id >= ARRAY_SIZE(sh_cmt_offset_multiplier)) {
>> > +           dev_err(dev, "invalid device id\n");
>> > +           return NULL;
>> > +   }
>> > +
>> > +   if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
>> > +           dev_err(dev, "channel id missing\n");
>> > +           return NULL;
>> > +   }
>> > +   if (channel_id >= CMT_MAX_CHANNELS) {
>> > +           dev_err(dev, "invalid channel id\n");
>> > +           return NULL;
>> > +   }
>> > +
>> > +   cfg->channel_offset = sh_cmt_offset_multiplier[timer_id] *
>> > +                                                   (channel_id + 1);
>> > +   cfg->timer_bit = channel_id;
>> > +
>> > +   /*
>> > +    * We convert the {source,event}-quality DT properties to linux specific
>> > +    * clock{source,event}_ratings.
>> > +    */
>> > +   if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
>> > +           if (rating > 10) {
>> > +                   dev_err(dev, "invalid source-quality\n");
>> > +                   return NULL;
>> > +           }
>> > +           if (rating)
>> > +                   cfg->clocksource_rating = rating * 50 - 1;
>> > +   }
>> > +
>> > +   if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
>> > +           if (rating > 10) {
>> > +                   dev_err(dev, "invalid event-quality\n");
>> > +                   return NULL;
>> > +           }
>> > +           if (rating)
>> > +                   cfg->clockevent_rating = rating * 50 - 1;
>> > +   }
>> > +
>> > +   if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
>> > +           dev_err(dev, "source- and event-quality 0, timer is unused\n");
>> > +           return NULL;
>> > +   }
>> > +
>> > +   return cfg;
>> > +}
>> > +
>> > +static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev,
>> > +                                           struct sh_timer_config *cfg)
>> >  {
>> > -   struct sh_timer_config *cfg = pdev->dev.platform_data;
>> >     struct resource *res;
>> >     int irq, ret;
>> >     ret = -ENXIO;
>> > @@ -762,6 +836,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
>> >             goto err2;
>> >     }
>> >
>> > +   p->channel_offset = cfg->channel_offset;
>> > +   p->timer_bit = cfg->timer_bit;
>> > +
>> >     platform_set_drvdata(pdev, p);
>> >
>> >     return 0;
>> > @@ -777,7 +854,7 @@ err0:
>> >  static int sh_cmt_probe(struct platform_device *pdev)
>> >  {
>> >     struct sh_cmt_priv *p = platform_get_drvdata(pdev);
>> > -   struct sh_timer_config *cfg = pdev->dev.platform_data;
>> > +   struct sh_timer_config *cfg;
>> >     int ret;
>> >
>> >     if (!is_early_platform_device(pdev)) {
>> > @@ -785,6 +862,11 @@ static int sh_cmt_probe(struct platform_device *pdev)
>> >             pm_runtime_enable(&pdev->dev);
>> >     }
>> >
>> > +   if (pdev->dev.of_node)
>> > +           cfg = sh_cmt_parse_dt(&pdev->dev);
>> > +   else
>> > +           cfg = pdev->dev.platform_data;
>> > +
>> >     if (p) {
>> >             dev_info(&pdev->dev, "kept as earlytimer\n");
>> >             goto out;
>> > @@ -796,7 +878,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
>> >             return -ENOMEM;
>> >     }
>> >
>> > -   ret = sh_cmt_setup(p, pdev);
>> > +   ret = sh_cmt_setup(p, pdev, cfg);
>> >     if (ret) {
>> >             kfree(p);
>> >             pm_runtime_idle(&pdev->dev);
>> > @@ -824,6 +906,7 @@ static struct platform_driver sh_cmt_device_driver = {
>> >     .remove         = sh_cmt_remove,
>> >     .driver         = {
>> >             .name   = "sh_cmt",
>> > +           .of_match_table = of_match_ptr(of_sh_cmt_match),
>> >     }
>> >  };
>> >
>> > --
>> > 1.7.9.5
>> >
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>> > the body of a message to majordomo at vger.kernel.org
>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> >
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>

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

* Re: [PATCH v3 2/7] clocksource: sh_cmt: Add OF support
  2013-04-09 15:06         ` Bastian Hecht
@ 2013-04-11  8:01           ` Bastian Hecht
  -1 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-04-11  8:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Simon,

2013/4/9 Bastian Hecht <hechtb@gmail.com>:
> Hi Simon,
>
> 2013/4/9 Simon Horman <horms@verge.net.au>:
>> On 木,  3月 21, 2013 at 10:07:15午後 +0900, Simon Horman wrote:
>>> On Sun, Mar 17, 2013 at 04:43:46PM +0100, Bastian Hecht wrote:
>>> > We add the capabilty to probe SH CMT timer devices using Device Tree
>>> > setup.
>>> >
>>> > Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
>>> > ---
>>> > v3: same (only patch 0003 changed)
>>> >
>>> >  drivers/clocksource/sh_cmt.c |  109 +++++++++++++++++++++++++++++++++++++-----
>>>
>>>
>>> This change appears to break booting of kzm9g-reference
>>> with MMC enabled. I assume because it somehow causes CMT to
>>> (once again) be initialised after SDHI and/or MMC.
>>>
>>> Tested using next with the defconfig + CONFIG_MACH_KZM9G_REFERENCE=y +
>>> initrd root fs.
>>
>
> Thanks for finding this flaw. I've got it on my agenda.
>
> Bastian
>
>>> >  1 file changed, 96 insertions(+), 13 deletions(-)
>>> >
>>> > diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
>>> > index 08d0c41..79bc526 100644
>>> > --- a/drivers/clocksource/sh_cmt.c
>>> > +++ b/drivers/clocksource/sh_cmt.c
>>> > @@ -34,10 +34,13 @@
>>> >  #include <linux/module.h>
>>> >  #include <linux/pm_domain.h>
>>> >  #include <linux/pm_runtime.h>
>>> > +#include <linux/of.h>
>>> >
>>> >  struct sh_cmt_priv {
>>> >     void __iomem *mapbase;
>>> >     struct clk *clk;
>>> > +   long channel_offset;
>>> > +   int timer_bit;
>>> >     unsigned long width; /* 16 or 32 bit version of hardware block */
>>> >     unsigned long overflow_bit;
>>> >     unsigned long clear_bits;
>>> > @@ -109,9 +112,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
>>> >
>>> >  static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
>>> >  {
>>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>>> > -
>>> > -   return p->read_control(p->mapbase - cfg->channel_offset, 0);
>>> > +   return p->read_control(p->mapbase - p->channel_offset, 0);
>>> >  }
>>> >
>>> >  static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
>>> > @@ -127,9 +128,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
>>> >  static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
>>> >                                   unsigned long value)
>>> >  {
>>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>>> > -
>>> > -   p->write_control(p->mapbase - cfg->channel_offset, 0, value);
>>> > +   p->write_control(p->mapbase - p->channel_offset, 0, value);
>>> >  }
>>> >
>>> >  static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
>>> > @@ -176,7 +175,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
>>> >
>>> >  static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>>> >  {
>>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>>> >     unsigned long flags, value;
>>> >
>>> >     /* start stop register shared by multiple timer channels */
>>> > @@ -184,9 +182,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>>> >     value = sh_cmt_read_cmstr(p);
>>> >
>>> >     if (start)
>>> > -           value |= 1 << cfg->timer_bit;
>>> > +           value |= 1 << p->timer_bit;
>>> >     else
>>> > -           value &= ~(1 << cfg->timer_bit);
>>> > +           value &= ~(1 << p->timer_bit);
>>> >
>>> >     sh_cmt_write_cmstr(p, value);
>>> >     raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
>>> > @@ -673,9 +671,85 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
>>> >     return 0;
>>> >  }
>>> >
>>> > -static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
>>> > +static const struct of_device_id of_sh_cmt_match[] = {
>>> > +   { .compatible = "renesas,cmt-timer" },
>>> > +   {},
>>> > +};
>>> > +MODULE_DEVICE_TABLE(of, of_sh_cmt_match);
>>> > +
>>> > +static const int sh_cmt_offset_multiplier[] = { 0x60, 0x10, 0x40, 0x40, 0x40 };
>>> > +#define CMT_MAX_CHANNELS   6
>>> > +
>>> > +static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev)
>>> > +{
>>> > +   struct sh_timer_config *cfg;
>>> > +   struct device_node *np = dev->of_node;
>>> > +   u32 timer_id, channel_id, rating;
>>> > +
>>> > +   if (!IS_ENABLED(CONFIG_OF) || !np)
>>> > +           return NULL;
>>> > +
>>> > +   cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
>>> > +   if (!cfg) {
>>> > +           dev_err(dev, "failed to allocate DT config data\n");
>>> > +           return NULL;
>>> > +   }
>>> > +
>>> > +   if (of_property_read_u32(np, "renesas,device-id", &timer_id)) {
>>> > +           dev_err(dev, "device id missing\n");
>>> > +           return NULL;
>>> > +   }
>>> > +   if (timer_id >= ARRAY_SIZE(sh_cmt_offset_multiplier)) {
>>> > +           dev_err(dev, "invalid device id\n");
>>> > +           return NULL;
>>> > +   }
>>> > +
>>> > +   if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
>>> > +           dev_err(dev, "channel id missing\n");
>>> > +           return NULL;
>>> > +   }
>>> > +   if (channel_id >= CMT_MAX_CHANNELS) {
>>> > +           dev_err(dev, "invalid channel id\n");
>>> > +           return NULL;
>>> > +   }
>>> > +
>>> > +   cfg->channel_offset = sh_cmt_offset_multiplier[timer_id] *
>>> > +                                                   (channel_id + 1);
>>> > +   cfg->timer_bit = channel_id;
>>> > +
>>> > +   /*
>>> > +    * We convert the {source,event}-quality DT properties to linux specific
>>> > +    * clock{source,event}_ratings.
>>> > +    */
>>> > +   if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
>>> > +           if (rating > 10) {
>>> > +                   dev_err(dev, "invalid source-quality\n");
>>> > +                   return NULL;
>>> > +           }
>>> > +           if (rating)
>>> > +                   cfg->clocksource_rating = rating * 50 - 1;
>>> > +   }
>>> > +
>>> > +   if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
>>> > +           if (rating > 10) {
>>> > +                   dev_err(dev, "invalid event-quality\n");
>>> > +                   return NULL;
>>> > +           }
>>> > +           if (rating)
>>> > +                   cfg->clockevent_rating = rating * 50 - 1;
>>> > +   }
>>> > +
>>> > +   if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
>>> > +           dev_err(dev, "source- and event-quality 0, timer is unused\n");
>>> > +           return NULL;
>>> > +   }
>>> > +
>>> > +   return cfg;
>>> > +}
>>> > +
>>> > +static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev,
>>> > +                                           struct sh_timer_config *cfg)
>>> >  {
>>> > -   struct sh_timer_config *cfg = pdev->dev.platform_data;
>>> >     struct resource *res;
>>> >     int irq, ret;
>>> >     ret = -ENXIO;
>>> > @@ -762,6 +836,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
>>> >             goto err2;
>>> >     }
>>> >
>>> > +   p->channel_offset = cfg->channel_offset;
>>> > +   p->timer_bit = cfg->timer_bit;
>>> > +

This happens too late. After interrupt registration. I have to check
the TMU patch as well and I'll send out a v4 later.

Thanks again for detecting this flaw.

Bastian


>>> >     platform_set_drvdata(pdev, p);
>>> >
>>> >     return 0;
>>> > @@ -777,7 +854,7 @@ err0:
>>> >  static int sh_cmt_probe(struct platform_device *pdev)
>>> >  {
>>> >     struct sh_cmt_priv *p = platform_get_drvdata(pdev);
>>> > -   struct sh_timer_config *cfg = pdev->dev.platform_data;
>>> > +   struct sh_timer_config *cfg;
>>> >     int ret;
>>> >
>>> >     if (!is_early_platform_device(pdev)) {
>>> > @@ -785,6 +862,11 @@ static int sh_cmt_probe(struct platform_device *pdev)
>>> >             pm_runtime_enable(&pdev->dev);
>>> >     }
>>> >
>>> > +   if (pdev->dev.of_node)
>>> > +           cfg = sh_cmt_parse_dt(&pdev->dev);
>>> > +   else
>>> > +           cfg = pdev->dev.platform_data;
>>> > +
>>> >     if (p) {
>>> >             dev_info(&pdev->dev, "kept as earlytimer\n");
>>> >             goto out;
>>> > @@ -796,7 +878,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
>>> >             return -ENOMEM;
>>> >     }
>>> >
>>> > -   ret = sh_cmt_setup(p, pdev);
>>> > +   ret = sh_cmt_setup(p, pdev, cfg);
>>> >     if (ret) {
>>> >             kfree(p);
>>> >             pm_runtime_idle(&pdev->dev);
>>> > @@ -824,6 +906,7 @@ static struct platform_driver sh_cmt_device_driver = {
>>> >     .remove         = sh_cmt_remove,
>>> >     .driver         = {
>>> >             .name   = "sh_cmt",
>>> > +           .of_match_table = of_match_ptr(of_sh_cmt_match),
>>> >     }
>>> >  };
>>> >
>>> > --
>>> > 1.7.9.5
>>> >
>>> > --
>>> > To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>>> > the body of a message to majordomo@vger.kernel.org
>>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>> >
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>

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

* [PATCH v3 2/7] clocksource: sh_cmt: Add OF support
@ 2013-04-11  8:01           ` Bastian Hecht
  0 siblings, 0 replies; 26+ messages in thread
From: Bastian Hecht @ 2013-04-11  8:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Simon,

2013/4/9 Bastian Hecht <hechtb@gmail.com>:
> Hi Simon,
>
> 2013/4/9 Simon Horman <horms@verge.net.au>:
>> On ?,  3? 21, 2013 at 10:07:15?? +0900, Simon Horman wrote:
>>> On Sun, Mar 17, 2013 at 04:43:46PM +0100, Bastian Hecht wrote:
>>> > We add the capabilty to probe SH CMT timer devices using Device Tree
>>> > setup.
>>> >
>>> > Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
>>> > ---
>>> > v3: same (only patch 0003 changed)
>>> >
>>> >  drivers/clocksource/sh_cmt.c |  109 +++++++++++++++++++++++++++++++++++++-----
>>>
>>>
>>> This change appears to break booting of kzm9g-reference
>>> with MMC enabled. I assume because it somehow causes CMT to
>>> (once again) be initialised after SDHI and/or MMC.
>>>
>>> Tested using next with the defconfig + CONFIG_MACH_KZM9G_REFERENCE=y +
>>> initrd root fs.
>>
>
> Thanks for finding this flaw. I've got it on my agenda.
>
> Bastian
>
>>> >  1 file changed, 96 insertions(+), 13 deletions(-)
>>> >
>>> > diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
>>> > index 08d0c41..79bc526 100644
>>> > --- a/drivers/clocksource/sh_cmt.c
>>> > +++ b/drivers/clocksource/sh_cmt.c
>>> > @@ -34,10 +34,13 @@
>>> >  #include <linux/module.h>
>>> >  #include <linux/pm_domain.h>
>>> >  #include <linux/pm_runtime.h>
>>> > +#include <linux/of.h>
>>> >
>>> >  struct sh_cmt_priv {
>>> >     void __iomem *mapbase;
>>> >     struct clk *clk;
>>> > +   long channel_offset;
>>> > +   int timer_bit;
>>> >     unsigned long width; /* 16 or 32 bit version of hardware block */
>>> >     unsigned long overflow_bit;
>>> >     unsigned long clear_bits;
>>> > @@ -109,9 +112,7 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
>>> >
>>> >  static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
>>> >  {
>>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>>> > -
>>> > -   return p->read_control(p->mapbase - cfg->channel_offset, 0);
>>> > +   return p->read_control(p->mapbase - p->channel_offset, 0);
>>> >  }
>>> >
>>> >  static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
>>> > @@ -127,9 +128,7 @@ static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
>>> >  static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
>>> >                                   unsigned long value)
>>> >  {
>>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>>> > -
>>> > -   p->write_control(p->mapbase - cfg->channel_offset, 0, value);
>>> > +   p->write_control(p->mapbase - p->channel_offset, 0, value);
>>> >  }
>>> >
>>> >  static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
>>> > @@ -176,7 +175,6 @@ static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
>>> >
>>> >  static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>>> >  {
>>> > -   struct sh_timer_config *cfg = p->pdev->dev.platform_data;
>>> >     unsigned long flags, value;
>>> >
>>> >     /* start stop register shared by multiple timer channels */
>>> > @@ -184,9 +182,9 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
>>> >     value = sh_cmt_read_cmstr(p);
>>> >
>>> >     if (start)
>>> > -           value |= 1 << cfg->timer_bit;
>>> > +           value |= 1 << p->timer_bit;
>>> >     else
>>> > -           value &= ~(1 << cfg->timer_bit);
>>> > +           value &= ~(1 << p->timer_bit);
>>> >
>>> >     sh_cmt_write_cmstr(p, value);
>>> >     raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
>>> > @@ -673,9 +671,85 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
>>> >     return 0;
>>> >  }
>>> >
>>> > -static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
>>> > +static const struct of_device_id of_sh_cmt_match[] = {
>>> > +   { .compatible = "renesas,cmt-timer" },
>>> > +   {},
>>> > +};
>>> > +MODULE_DEVICE_TABLE(of, of_sh_cmt_match);
>>> > +
>>> > +static const int sh_cmt_offset_multiplier[] = { 0x60, 0x10, 0x40, 0x40, 0x40 };
>>> > +#define CMT_MAX_CHANNELS   6
>>> > +
>>> > +static struct sh_timer_config *sh_cmt_parse_dt(struct device *dev)
>>> > +{
>>> > +   struct sh_timer_config *cfg;
>>> > +   struct device_node *np = dev->of_node;
>>> > +   u32 timer_id, channel_id, rating;
>>> > +
>>> > +   if (!IS_ENABLED(CONFIG_OF) || !np)
>>> > +           return NULL;
>>> > +
>>> > +   cfg = devm_kzalloc(dev, sizeof(struct sh_timer_config), GFP_KERNEL);
>>> > +   if (!cfg) {
>>> > +           dev_err(dev, "failed to allocate DT config data\n");
>>> > +           return NULL;
>>> > +   }
>>> > +
>>> > +   if (of_property_read_u32(np, "renesas,device-id", &timer_id)) {
>>> > +           dev_err(dev, "device id missing\n");
>>> > +           return NULL;
>>> > +   }
>>> > +   if (timer_id >= ARRAY_SIZE(sh_cmt_offset_multiplier)) {
>>> > +           dev_err(dev, "invalid device id\n");
>>> > +           return NULL;
>>> > +   }
>>> > +
>>> > +   if (of_property_read_u32(np, "renesas,channel-id", &channel_id)) {
>>> > +           dev_err(dev, "channel id missing\n");
>>> > +           return NULL;
>>> > +   }
>>> > +   if (channel_id >= CMT_MAX_CHANNELS) {
>>> > +           dev_err(dev, "invalid channel id\n");
>>> > +           return NULL;
>>> > +   }
>>> > +
>>> > +   cfg->channel_offset = sh_cmt_offset_multiplier[timer_id] *
>>> > +                                                   (channel_id + 1);
>>> > +   cfg->timer_bit = channel_id;
>>> > +
>>> > +   /*
>>> > +    * We convert the {source,event}-quality DT properties to linux specific
>>> > +    * clock{source,event}_ratings.
>>> > +    */
>>> > +   if (!of_property_read_u32(np, "renesas,source-quality", &rating)) {
>>> > +           if (rating > 10) {
>>> > +                   dev_err(dev, "invalid source-quality\n");
>>> > +                   return NULL;
>>> > +           }
>>> > +           if (rating)
>>> > +                   cfg->clocksource_rating = rating * 50 - 1;
>>> > +   }
>>> > +
>>> > +   if (!of_property_read_u32(np, "renesas,event-quality", &rating)) {
>>> > +           if (rating > 10) {
>>> > +                   dev_err(dev, "invalid event-quality\n");
>>> > +                   return NULL;
>>> > +           }
>>> > +           if (rating)
>>> > +                   cfg->clockevent_rating = rating * 50 - 1;
>>> > +   }
>>> > +
>>> > +   if (!cfg->clocksource_rating && !cfg->clockevent_rating) {
>>> > +           dev_err(dev, "source- and event-quality 0, timer is unused\n");
>>> > +           return NULL;
>>> > +   }
>>> > +
>>> > +   return cfg;
>>> > +}
>>> > +
>>> > +static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev,
>>> > +                                           struct sh_timer_config *cfg)
>>> >  {
>>> > -   struct sh_timer_config *cfg = pdev->dev.platform_data;
>>> >     struct resource *res;
>>> >     int irq, ret;
>>> >     ret = -ENXIO;
>>> > @@ -762,6 +836,9 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
>>> >             goto err2;
>>> >     }
>>> >
>>> > +   p->channel_offset = cfg->channel_offset;
>>> > +   p->timer_bit = cfg->timer_bit;
>>> > +

This happens too late. After interrupt registration. I have to check
the TMU patch as well and I'll send out a v4 later.

Thanks again for detecting this flaw.

Bastian


>>> >     platform_set_drvdata(pdev, p);
>>> >
>>> >     return 0;
>>> > @@ -777,7 +854,7 @@ err0:
>>> >  static int sh_cmt_probe(struct platform_device *pdev)
>>> >  {
>>> >     struct sh_cmt_priv *p = platform_get_drvdata(pdev);
>>> > -   struct sh_timer_config *cfg = pdev->dev.platform_data;
>>> > +   struct sh_timer_config *cfg;
>>> >     int ret;
>>> >
>>> >     if (!is_early_platform_device(pdev)) {
>>> > @@ -785,6 +862,11 @@ static int sh_cmt_probe(struct platform_device *pdev)
>>> >             pm_runtime_enable(&pdev->dev);
>>> >     }
>>> >
>>> > +   if (pdev->dev.of_node)
>>> > +           cfg = sh_cmt_parse_dt(&pdev->dev);
>>> > +   else
>>> > +           cfg = pdev->dev.platform_data;
>>> > +
>>> >     if (p) {
>>> >             dev_info(&pdev->dev, "kept as earlytimer\n");
>>> >             goto out;
>>> > @@ -796,7 +878,7 @@ static int sh_cmt_probe(struct platform_device *pdev)
>>> >             return -ENOMEM;
>>> >     }
>>> >
>>> > -   ret = sh_cmt_setup(p, pdev);
>>> > +   ret = sh_cmt_setup(p, pdev, cfg);
>>> >     if (ret) {
>>> >             kfree(p);
>>> >             pm_runtime_idle(&pdev->dev);
>>> > @@ -824,6 +906,7 @@ static struct platform_driver sh_cmt_device_driver = {
>>> >     .remove         = sh_cmt_remove,
>>> >     .driver         = {
>>> >             .name   = "sh_cmt",
>>> > +           .of_match_table = of_match_ptr(of_sh_cmt_match),
>>> >     }
>>> >  };
>>> >
>>> > --
>>> > 1.7.9.5
>>> >
>>> > --
>>> > To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>>> > the body of a message to majordomo at vger.kernel.org
>>> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>> >
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>>> the body of a message to majordomo at vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>

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

end of thread, other threads:[~2013-04-11  8:01 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-17 15:43 [PATCH v3 1/7] ARM: shmobile: Define DT bindings for timer devices Bastian Hecht
2013-03-17 15:43 ` Bastian Hecht
2013-03-17 15:43 ` [PATCH v3 2/7] clocksource: sh_cmt: Add OF support Bastian Hecht
2013-03-17 15:43   ` Bastian Hecht
2013-03-21 13:07   ` Simon Horman
2013-03-21 13:07     ` Simon Horman
2013-04-09 13:38     ` Simon Horman
2013-04-09 13:38       ` Simon Horman
2013-04-09 15:06       ` Bastian Hecht
2013-04-09 15:06         ` Bastian Hecht
2013-04-11  8:01         ` Bastian Hecht
2013-04-11  8:01           ` Bastian Hecht
2013-03-17 15:43 ` [PATCH v3 3/7] clocksource: sh_tmu: " Bastian Hecht
2013-03-17 15:43   ` Bastian Hecht
2013-03-17 15:43 ` [PATCH v3 4/7] ARM: shmobile: sh73a0: Add timer DT names to clock list Bastian Hecht
2013-03-17 15:43   ` Bastian Hecht
2013-03-17 15:43 ` [PATCH v3 5/7] ARM: mach-shmobile: sh73a0: Setup the timer CMT10 using DT Bastian Hecht
2013-03-17 15:43   ` Bastian Hecht
2013-03-17 15:43 ` [PATCH v3 6/7] ARM: shmobile: r8a7740: Add DT name to clock list for CMT10 Bastian Hecht
2013-03-17 15:43   ` Bastian Hecht
2013-03-17 15:43 ` [PATCH v3 7/7] ARM: mach-shmobile: r8a7740: Setup the timer CMT10 using DT Bastian Hecht
2013-03-17 15:43   ` Bastian Hecht
2013-03-19  3:28 ` [PATCH v3 1/7] ARM: shmobile: Define DT bindings for timer devices Simon Horman
2013-03-19  3:28   ` Simon Horman
2013-03-19 10:19   ` Bastian Hecht
2013-03-19 10:19     ` Bastian Hecht

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.