linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] clocksource: Add support for Aspeed timer
@ 2016-07-21 13:43 Joel Stanley
  2016-07-21 13:43 ` [PATCH v2 1/3] drivers/clocksource/moxart: Refactor enable/disable Joel Stanley
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Joel Stanley @ 2016-07-21 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Daniel,

This adds support for the Aspeed ast2400 and ast2500 families of BMC SoCs to
the moxart driver.

I've dropped the first patch and respun the others so they apply. I've also
boot tested on our hardware, so they are good to go.

It would be great to seem them make it for the upcoming merge window so I can
focus my time on cleaning up the the other drivers we have on their way.

Cheers,

Joel

Joel Stanley (3):
  drivers/clocksource/moxart: Refactor enable/disable
  drivers/clocksource/moxart: Use struct to hold state
  drivers/clocksource/moxart: Add Aspeed support

 .../bindings/timer/moxa,moxart-timer.txt           |   4 +-
 drivers/clocksource/moxart_timer.c                 | 195 ++++++++++++++-------
 2 files changed, 134 insertions(+), 65 deletions(-)

-- 
2.8.1

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

* [PATCH v2 1/3] drivers/clocksource/moxart: Refactor enable/disable
  2016-07-21 13:43 [PATCH v2 0/3] clocksource: Add support for Aspeed timer Joel Stanley
@ 2016-07-21 13:43 ` Joel Stanley
  2016-07-21 13:43 ` [PATCH v2 2/3] drivers/clocksource/moxart: Use struct to hold state Joel Stanley
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Joel Stanley @ 2016-07-21 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

This patch abstracts the enable and disable register writes into their
own functions in preparation for future changes to use SoC specific
values for the writes.

Signed-off-by: Joel Stanley <joel@jms.id.au>
---
 drivers/clocksource/moxart_timer.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c
index 841454417acd..a3aaa5658a49 100644
--- a/drivers/clocksource/moxart_timer.c
+++ b/drivers/clocksource/moxart_timer.c
@@ -58,15 +58,25 @@
 static void __iomem *base;
 static unsigned int clock_count_per_tick;
 
-static int moxart_shutdown(struct clock_event_device *evt)
+static inline void moxart_disable(struct clock_event_device *evt)
 {
 	writel(TIMER1_DISABLE, base + TIMER_CR);
+}
+
+static inline void moxart_enable(struct clock_event_device *evt)
+{
+	writel(TIMER1_ENABLE, base + TIMER_CR);
+}
+
+static int moxart_shutdown(struct clock_event_device *evt)
+{
+	moxart_disable(evt);
 	return 0;
 }
 
 static int moxart_set_oneshot(struct clock_event_device *evt)
 {
-	writel(TIMER1_DISABLE, base + TIMER_CR);
+	moxart_disable(evt);
 	writel(~0, base + TIMER1_BASE + REG_LOAD);
 	return 0;
 }
@@ -74,21 +84,21 @@ static int moxart_set_oneshot(struct clock_event_device *evt)
 static int moxart_set_periodic(struct clock_event_device *evt)
 {
 	writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD);
-	writel(TIMER1_ENABLE, base + TIMER_CR);
+	moxart_enable(evt);
 	return 0;
 }
 
 static int moxart_clkevt_next_event(unsigned long cycles,
-				    struct clock_event_device *unused)
+				    struct clock_event_device *evt)
 {
 	u32 u;
 
-	writel(TIMER1_DISABLE, base + TIMER_CR);
+	moxart_disable(evt);
 
 	u = readl(base + TIMER1_BASE + REG_COUNT) - cycles;
 	writel(u, base + TIMER1_BASE + REG_MATCH1);
 
-	writel(TIMER1_ENABLE, base + TIMER_CR);
+	moxart_enable(evt);
 
 	return 0;
 }
-- 
2.8.1

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

* [PATCH v2 2/3] drivers/clocksource/moxart: Use struct to hold state
  2016-07-21 13:43 [PATCH v2 0/3] clocksource: Add support for Aspeed timer Joel Stanley
  2016-07-21 13:43 ` [PATCH v2 1/3] drivers/clocksource/moxart: Refactor enable/disable Joel Stanley
@ 2016-07-21 13:43 ` Joel Stanley
  2016-07-21 13:43 ` [PATCH v2 3/3] drivers/clocksource/moxart: Add Aspeed support Joel Stanley
  2016-09-08 13:57 ` [PATCH v2 0/3] clocksource: Add support for Aspeed timer Daniel Lezcano
  3 siblings, 0 replies; 5+ messages in thread
From: Joel Stanley @ 2016-07-21 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

Add a struct moxart_timer to hold the driver state, including the
irqaction and struct clock_event_device.

Most importantly this holds values for enabling and disabling the timer,
so future support can be added for devices that use different bits for
enable/disable.

In preparation for future hardware support we add a MOXART prefix to the
existing values.

Signed-off-by: Joel Stanley <joel@jms.id.au>
---
 drivers/clocksource/moxart_timer.c | 147 ++++++++++++++++++++++---------------
 1 file changed, 86 insertions(+), 61 deletions(-)

diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c
index a3aaa5658a49..cb0b34786a8e 100644
--- a/drivers/clocksource/moxart_timer.c
+++ b/drivers/clocksource/moxart_timer.c
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/clocksource.h>
 #include <linux/bitops.h>
+#include <linux/slab.h>
 
 #define TIMER1_BASE		0x00
 #define TIMER2_BASE		0x10
@@ -36,36 +37,51 @@
 #define TIMER_INTR_MASK		0x38
 
 /*
- * TIMER_CR flags:
+ * Moxart TIMER_CR flags:
  *
- * TIMEREG_CR_*_CLOCK	0: PCLK, 1: EXT1CLK
- * TIMEREG_CR_*_INT	overflow interrupt enable bit
+ * MOXART_CR_*_CLOCK	0: PCLK, 1: EXT1CLK
+ * MOXART_CR_*_INT	overflow interrupt enable bit
  */
-#define TIMEREG_CR_1_ENABLE	BIT(0)
-#define TIMEREG_CR_1_CLOCK	BIT(1)
-#define TIMEREG_CR_1_INT	BIT(2)
-#define TIMEREG_CR_2_ENABLE	BIT(3)
-#define TIMEREG_CR_2_CLOCK	BIT(4)
-#define TIMEREG_CR_2_INT	BIT(5)
-#define TIMEREG_CR_3_ENABLE	BIT(6)
-#define TIMEREG_CR_3_CLOCK	BIT(7)
-#define TIMEREG_CR_3_INT	BIT(8)
-#define TIMEREG_CR_COUNT_UP	BIT(9)
-
-#define TIMER1_ENABLE		(TIMEREG_CR_2_ENABLE | TIMEREG_CR_1_ENABLE)
-#define TIMER1_DISABLE		(TIMEREG_CR_2_ENABLE)
-
-static void __iomem *base;
-static unsigned int clock_count_per_tick;
+#define MOXART_CR_1_ENABLE	BIT(0)
+#define MOXART_CR_1_CLOCK	BIT(1)
+#define MOXART_CR_1_INT	BIT(2)
+#define MOXART_CR_2_ENABLE	BIT(3)
+#define MOXART_CR_2_CLOCK	BIT(4)
+#define MOXART_CR_2_INT	BIT(5)
+#define MOXART_CR_3_ENABLE	BIT(6)
+#define MOXART_CR_3_CLOCK	BIT(7)
+#define MOXART_CR_3_INT	BIT(8)
+#define MOXART_CR_COUNT_UP	BIT(9)
+
+#define MOXART_TIMER1_ENABLE	(MOXART_CR_2_ENABLE | MOXART_CR_1_ENABLE)
+#define MOXART_TIMER1_DISABLE	(MOXART_CR_2_ENABLE)
+
+struct moxart_timer {
+	void __iomem *base;
+	unsigned int t1_disable_val;
+	unsigned int t1_enable_val;
+	unsigned int count_per_tick;
+	struct clock_event_device clkevt;
+	struct irqaction act;
+};
+
+static inline struct moxart_timer *to_moxart(struct clock_event_device *evt)
+{
+	return container_of(evt, struct moxart_timer, clkevt);
+}
 
 static inline void moxart_disable(struct clock_event_device *evt)
 {
-	writel(TIMER1_DISABLE, base + TIMER_CR);
+	struct moxart_timer *timer = to_moxart(evt);
+
+	writel(timer->t1_disable_val, timer->base + TIMER_CR);
 }
 
 static inline void moxart_enable(struct clock_event_device *evt)
 {
-	writel(TIMER1_ENABLE, base + TIMER_CR);
+	struct moxart_timer *timer = to_moxart(evt);
+
+	writel(timer->t1_enable_val, timer->base + TIMER_CR);
 }
 
 static int moxart_shutdown(struct clock_event_device *evt)
@@ -77,13 +93,17 @@ static int moxart_shutdown(struct clock_event_device *evt)
 static int moxart_set_oneshot(struct clock_event_device *evt)
 {
 	moxart_disable(evt);
-	writel(~0, base + TIMER1_BASE + REG_LOAD);
+	writel(~0, to_moxart(evt)->base + TIMER1_BASE + REG_LOAD);
 	return 0;
 }
 
 static int moxart_set_periodic(struct clock_event_device *evt)
 {
-	writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD);
+	struct moxart_timer *timer = to_moxart(evt);
+
+	moxart_disable(evt);
+	writel(timer->count_per_tick, timer->base + TIMER1_BASE + REG_LOAD);
+	writel(0, timer->base + TIMER1_BASE + REG_MATCH1);
 	moxart_enable(evt);
 	return 0;
 }
@@ -91,30 +111,19 @@ static int moxart_set_periodic(struct clock_event_device *evt)
 static int moxart_clkevt_next_event(unsigned long cycles,
 				    struct clock_event_device *evt)
 {
+	struct moxart_timer *timer = to_moxart(evt);
 	u32 u;
 
 	moxart_disable(evt);
 
-	u = readl(base + TIMER1_BASE + REG_COUNT) - cycles;
-	writel(u, base + TIMER1_BASE + REG_MATCH1);
+	u = readl(timer->base + TIMER1_BASE + REG_COUNT) - cycles;
+	writel(u, timer->base + TIMER1_BASE + REG_MATCH1);
 
 	moxart_enable(evt);
 
 	return 0;
 }
 
-static struct clock_event_device moxart_clockevent = {
-	.name			= "moxart_timer",
-	.rating			= 200,
-	.features		= CLOCK_EVT_FEAT_PERIODIC |
-				  CLOCK_EVT_FEAT_ONESHOT,
-	.set_state_shutdown	= moxart_shutdown,
-	.set_state_periodic	= moxart_set_periodic,
-	.set_state_oneshot	= moxart_set_oneshot,
-	.tick_resume		= moxart_set_oneshot,
-	.set_next_event		= moxart_clkevt_next_event,
-};
-
 static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = dev_id;
@@ -122,21 +131,19 @@ static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static struct irqaction moxart_timer_irq = {
-	.name		= "moxart-timer",
-	.flags		= IRQF_TIMER,
-	.handler	= moxart_timer_interrupt,
-	.dev_id		= &moxart_clockevent,
-};
-
 static int __init moxart_timer_init(struct device_node *node)
 {
 	int ret, irq;
 	unsigned long pclk;
 	struct clk *clk;
+	struct moxart_timer *timer;
 
-	base = of_iomap(node, 0);
-	if (!base) {
+	timer = kzalloc(sizeof(*timer), GFP_KERNEL);
+	if (!timer)
+		return -ENOMEM;
+
+	timer->base = of_iomap(node, 0);
+	if (!timer->base) {
 		pr_err("%s: of_iomap failed\n", node->full_name);
 		return -ENXIO;
 	}
@@ -147,12 +154,6 @@ static int __init moxart_timer_init(struct device_node *node)
 		return -EINVAL;
 	}
 
-	ret = setup_irq(irq, &moxart_timer_irq);
-	if (ret) {
-		pr_err("%s: setup_irq failed\n", node->full_name);
-		return ret;
-	}
-
 	clk = of_clk_get(node, 0);
 	if (IS_ERR(clk))  {
 		pr_err("%s: of_clk_get failed\n", node->full_name);
@@ -161,7 +162,31 @@ static int __init moxart_timer_init(struct device_node *node)
 
 	pclk = clk_get_rate(clk);
 
-	ret = clocksource_mmio_init(base + TIMER2_BASE + REG_COUNT,
+	if (of_device_is_compatible(node, "moxa,moxart-timer")) {
+		timer->t1_enable_val = MOXART_TIMER1_ENABLE;
+		timer->t1_disable_val = MOXART_TIMER1_DISABLE;
+	} else
+		panic("%s: unknown platform\n", node->full_name);
+
+	timer->count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ);
+
+	timer->clkevt.name = node->name;
+	timer->clkevt.rating = 200;
+	timer->clkevt.features = CLOCK_EVT_FEAT_PERIODIC |
+					CLOCK_EVT_FEAT_ONESHOT;
+	timer->clkevt.set_state_shutdown = moxart_shutdown;
+	timer->clkevt.set_state_periodic = moxart_set_periodic;
+	timer->clkevt.set_state_oneshot = moxart_set_oneshot;
+	timer->clkevt.tick_resume = moxart_set_oneshot;
+	timer->clkevt.set_next_event = moxart_clkevt_next_event;
+	timer->clkevt.cpumask = cpumask_of(0);
+	timer->clkevt.irq = irq;
+	timer->act.name = node->name;
+	timer->act.flags = IRQF_TIMER;
+	timer->act.handler = moxart_timer_interrupt;
+	timer->act.dev_id = &timer->clkevt;
+
+	ret = clocksource_mmio_init(timer->base + TIMER2_BASE + REG_COUNT,
 				    "moxart_timer", pclk, 200, 32,
 				    clocksource_mmio_readl_down);
 	if (ret) {
@@ -169,13 +194,14 @@ static int __init moxart_timer_init(struct device_node *node)
 		return ret;
 	}
 
-	clock_count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ);
-
-	writel(~0, base + TIMER2_BASE + REG_LOAD);
-	writel(TIMEREG_CR_2_ENABLE, base + TIMER_CR);
+	ret = setup_irq(irq, &timer->act);
+	if (ret) {
+		pr_err("%s: setup_irq failed\n", node->full_name);
+		return ret;
+	}
 
-	moxart_clockevent.cpumask = cpumask_of(0);
-	moxart_clockevent.irq = irq;
+	writel(~0, timer->base + TIMER2_BASE + REG_LOAD);
+	writel(timer->t1_disable_val, timer->base + TIMER_CR);
 
 	/*
 	 * documentation is not publicly available:
@@ -183,8 +209,7 @@ static int __init moxart_timer_init(struct device_node *node)
 	 * max_delta 0xfffffffe should be ok because count
 	 * register size is u32
 	 */
-	clockevents_config_and_register(&moxart_clockevent, pclk,
-					0x4, 0xfffffffe);
+	clockevents_config_and_register(&timer->clkevt, pclk, 0x4, 0xfffffffe);
 
 	return 0;
 }
-- 
2.8.1

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

* [PATCH v2 3/3] drivers/clocksource/moxart: Add Aspeed support
  2016-07-21 13:43 [PATCH v2 0/3] clocksource: Add support for Aspeed timer Joel Stanley
  2016-07-21 13:43 ` [PATCH v2 1/3] drivers/clocksource/moxart: Refactor enable/disable Joel Stanley
  2016-07-21 13:43 ` [PATCH v2 2/3] drivers/clocksource/moxart: Use struct to hold state Joel Stanley
@ 2016-07-21 13:43 ` Joel Stanley
  2016-09-08 13:57 ` [PATCH v2 0/3] clocksource: Add support for Aspeed timer Daniel Lezcano
  3 siblings, 0 replies; 5+ messages in thread
From: Joel Stanley @ 2016-07-21 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

The Aspeed SoC has timer IP with a very similar register layout to the
moxart timer. This patch adds support for the fourth and fifth gen
aspeed SoCs, and has been tested on the ast2400 and ast2500.

Signed-off-by: Joel Stanley <joel@jms.id.au>
Acked-by: Rob Herring <robh@kernel.org>
---
 .../bindings/timer/moxa,moxart-timer.txt           |  4 ++-
 drivers/clocksource/moxart_timer.c                 | 32 ++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt
index da2d510cae47..e207c11630af 100644
--- a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt
+++ b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt
@@ -2,7 +2,9 @@ MOXA ART timer
 
 Required properties:
 
-- compatible : Must be "moxa,moxart-timer"
+- compatible : Must be one of:
+ 	- "moxa,moxart-timer"
+ 	- "aspeed,ast2400-timer"
 - reg : Should contain registers location and length
 - interrupts : Should contain the timer interrupt number
 - clocks : Should contain phandle for the clock that drives the counter
diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c
index cb0b34786a8e..ad2bead9ce45 100644
--- a/drivers/clocksource/moxart_timer.c
+++ b/drivers/clocksource/moxart_timer.c
@@ -56,6 +56,23 @@
 #define MOXART_TIMER1_ENABLE	(MOXART_CR_2_ENABLE | MOXART_CR_1_ENABLE)
 #define MOXART_TIMER1_DISABLE	(MOXART_CR_2_ENABLE)
 
+/*
+ * The ASpeed variant of the IP block has a different layout
+ * for the control register
+ */
+#define ASPEED_CR_1_ENABLE	BIT(0)
+#define ASPEED_CR_1_CLOCK	BIT(1)
+#define ASPEED_CR_1_INT		BIT(2)
+#define ASPEED_CR_2_ENABLE	BIT(4)
+#define ASPEED_CR_2_CLOCK	BIT(5)
+#define ASPEED_CR_2_INT		BIT(6)
+#define ASPEED_CR_3_ENABLE	BIT(8)
+#define ASPEED_CR_3_CLOCK	BIT(9)
+#define ASPEED_CR_3_INT		BIT(10)
+
+#define ASPEED_TIMER1_ENABLE   (ASPEED_CR_2_ENABLE | ASPEED_CR_1_ENABLE)
+#define ASPEED_TIMER1_DISABLE  (ASPEED_CR_2_ENABLE)
+
 struct moxart_timer {
 	void __iomem *base;
 	unsigned int t1_disable_val;
@@ -165,6 +182,9 @@ static int __init moxart_timer_init(struct device_node *node)
 	if (of_device_is_compatible(node, "moxa,moxart-timer")) {
 		timer->t1_enable_val = MOXART_TIMER1_ENABLE;
 		timer->t1_disable_val = MOXART_TIMER1_DISABLE;
+	} else if (of_device_is_compatible(node, "aspeed,ast2400-timer")) {
+		timer->t1_enable_val = ASPEED_TIMER1_ENABLE;
+		timer->t1_disable_val = ASPEED_TIMER1_DISABLE;
 	} else
 		panic("%s: unknown platform\n", node->full_name);
 
@@ -200,6 +220,17 @@ static int __init moxart_timer_init(struct device_node *node)
 		return ret;
 	}
 
+	/* Clear match registers */
+	writel(0, timer->base + TIMER1_BASE + REG_MATCH1);
+	writel(0, timer->base + TIMER1_BASE + REG_MATCH2);
+	writel(0, timer->base + TIMER2_BASE + REG_MATCH1);
+	writel(0, timer->base + TIMER2_BASE + REG_MATCH2);
+
+	/*
+	 * Start timer 2 rolling as our main wall clock source, keep timer 1
+	 * disabled
+	 */
+	writel(0, timer->base + TIMER_CR);
 	writel(~0, timer->base + TIMER2_BASE + REG_LOAD);
 	writel(timer->t1_disable_val, timer->base + TIMER_CR);
 
@@ -214,3 +245,4 @@ static int __init moxart_timer_init(struct device_node *node)
 	return 0;
 }
 CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", moxart_timer_init);
+CLOCKSOURCE_OF_DECLARE(aspeed, "aspeed,ast2400-timer", moxart_timer_init);
-- 
2.8.1

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

* [PATCH v2 0/3] clocksource: Add support for Aspeed timer
  2016-07-21 13:43 [PATCH v2 0/3] clocksource: Add support for Aspeed timer Joel Stanley
                   ` (2 preceding siblings ...)
  2016-07-21 13:43 ` [PATCH v2 3/3] drivers/clocksource/moxart: Add Aspeed support Joel Stanley
@ 2016-09-08 13:57 ` Daniel Lezcano
  3 siblings, 0 replies; 5+ messages in thread
From: Daniel Lezcano @ 2016-09-08 13:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 21/07/2016 15:43, Joel Stanley wrote:
> Hello Daniel,
> 
> This adds support for the Aspeed ast2400 and ast2500 families of BMC SoCs to
> the moxart driver.
> 
> I've dropped the first patch and respun the others so they apply. I've also
> boot tested on our hardware, so they are good to go.
> 
> It would be great to seem them make it for the upcoming merge window so I can
> focus my time on cleaning up the the other drivers we have on their way.

Hi Joel,

I applied your series for 4.9.

Thanks !

  -- Daniel


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

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

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

end of thread, other threads:[~2016-09-08 13:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-21 13:43 [PATCH v2 0/3] clocksource: Add support for Aspeed timer Joel Stanley
2016-07-21 13:43 ` [PATCH v2 1/3] drivers/clocksource/moxart: Refactor enable/disable Joel Stanley
2016-07-21 13:43 ` [PATCH v2 2/3] drivers/clocksource/moxart: Use struct to hold state Joel Stanley
2016-07-21 13:43 ` [PATCH v2 3/3] drivers/clocksource/moxart: Add Aspeed support Joel Stanley
2016-09-08 13:57 ` [PATCH v2 0/3] clocksource: Add support for Aspeed timer Daniel Lezcano

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