diff mbox

[v4,2/6] clocksource: add Marvell Orion SoC timer

Message ID 1370856955-10514-1-git-send-email-sebastian.hesselbarth@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sebastian Hesselbarth June 10, 2013, 9:35 a.m. UTC
This patch add a DT enabled driver for timers found on Marvell Orion SoCs
(Kirkwood, Dove, Orion5x, and Discovery Innovation). It installs a free-
running clocksource on timer0 and a clockevent source on timer1.
Corresponding device tree documentation is also added.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
Changelog:
v3->v4:
- export thread-safe access to TIMER_CTRL register to use with watchdog
- remove IRQF_DISABLED and add .irq to clock event (Suggested by Daniel Lezcano)

Notes:
- This is only an update to clocksource driver, the remaining patches are
  not resent as they have not been changed.
- I will not rework orion watchdog driver for this patch set. It is written
  Kirkwood/Orion5x specific although it will also work on Dove and it is messing
  with shared registers. It has done it before, so I consider it broken anyway.
  I (or somebody else) will take care of proper watchdog later.
- An updated branch can be found on
  git://github.com/shesselba/linux-dove.git orion-irqchip-for-v3.11_v4

Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Gregory Clement <gregory.clement@free-electrons.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-doc@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
 .../bindings/timer/marvell,orion-timer.txt         |   17 +++
 drivers/clocksource/Kconfig                        |    5 +
 drivers/clocksource/Makefile                       |    1 +
 drivers/clocksource/time-orion.c                   |  150 ++++++++++++++++++++
 4 files changed, 173 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/marvell,orion-timer.txt
 create mode 100644 drivers/clocksource/time-orion.c

Comments

Daniel Lezcano June 10, 2013, 4:04 p.m. UTC | #1
On 06/10/2013 11:35 AM, Sebastian Hesselbarth wrote:
> This patch add a DT enabled driver for timers found on Marvell Orion SoCs
> (Kirkwood, Dove, Orion5x, and Discovery Innovation). It installs a free-
> running clocksource on timer0 and a clockevent source on timer1.
> Corresponding device tree documentation is also added.
> 
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>

It looks good for me.

Sebastian,

shall I take it through my tree (it will go to Thomas's tree) ?

Thanks
  -- Daniel

> ---
> Changelog:
> v3->v4:
> - export thread-safe access to TIMER_CTRL register to use with watchdog
> - remove IRQF_DISABLED and add .irq to clock event (Suggested by Daniel Lezcano)
> 
> Notes:
> - This is only an update to clocksource driver, the remaining patches are
>   not resent as they have not been changed.
> - I will not rework orion watchdog driver for this patch set. It is written
>   Kirkwood/Orion5x specific although it will also work on Dove and it is messing
>   with shared registers. It has done it before, so I consider it broken anyway.
>   I (or somebody else) will take care of proper watchdog later.
> - An updated branch can be found on
>   git://github.com/shesselba/linux-dove.git orion-irqchip-for-v3.11_v4
> 
> Cc: Grant Likely <grant.likely@linaro.org>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Rob Landley <rob@landley.net>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: John Stultz <john.stultz@linaro.org>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: Gregory Clement <gregory.clement@free-electrons.com>
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Cc: devicetree-discuss@lists.ozlabs.org
> Cc: linux-doc@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
> ---
>  .../bindings/timer/marvell,orion-timer.txt         |   17 +++
>  drivers/clocksource/Kconfig                        |    5 +
>  drivers/clocksource/Makefile                       |    1 +
>  drivers/clocksource/time-orion.c                   |  150 ++++++++++++++++++++
>  4 files changed, 173 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/timer/marvell,orion-timer.txt
>  create mode 100644 drivers/clocksource/time-orion.c
> 
> diff --git a/Documentation/devicetree/bindings/timer/marvell,orion-timer.txt b/Documentation/devicetree/bindings/timer/marvell,orion-timer.txt
> new file mode 100644
> index 0000000..62bb826
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/marvell,orion-timer.txt
> @@ -0,0 +1,17 @@
> +Marvell Orion SoC timer
> +
> +Required properties:
> +- compatible: shall be "marvell,orion-timer"
> +- reg: base address of the timer register starting with TIMERS CONTROL register
> +- interrupt-parent: phandle of the bridge interrupt controller
> +- interrupts: should contain the interrupts for Timer0 and Timer1
> +- clocks: phandle of timer reference clock (tclk)
> +
> +Example:
> +	timer: timer {
> +		compatible = "marvell,orion-timer";
> +		reg = <0x20300 0x20>;
> +		interrupt-parent = <&bridge_intc>;
> +		interrupts = <1>, <2>;
> +		clocks = <&core_clk 0>;
> +	};
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index f151c6c..2404869 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -25,6 +25,11 @@ config DW_APB_TIMER_OF
>  config ARMADA_370_XP_TIMER
>  	bool
>  
> +config ORION_TIMER
> +	select CLKSRC_OF
> +	select CLKSRC_MMIO
> +	bool
> +
>  config SUN4I_TIMER
>  	bool
>  
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 8d979c7..d1e8d68 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -15,6 +15,7 @@ obj-$(CONFIG_DW_APB_TIMER_OF)	+= dw_apb_timer_of.o
>  obj-$(CONFIG_CLKSRC_NOMADIK_MTU)	+= nomadik-mtu.o
>  obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o
>  obj-$(CONFIG_ARMADA_370_XP_TIMER)	+= time-armada-370-xp.o
> +obj-$(CONFIG_ORION_TIMER)	+= time-orion.o
>  obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
>  obj-$(CONFIG_ARCH_MARCO)	+= timer-marco.o
>  obj-$(CONFIG_ARCH_MXS)		+= mxs_timer.o
> diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c
> new file mode 100644
> index 0000000..ad7df17
> --- /dev/null
> +++ b/drivers/clocksource/time-orion.c
> @@ -0,0 +1,150 @@
> +/*
> + * Marvell Orion SoC timer handling.
> + *
> + * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + *
> + * Timer 0 is used as free-running clocksource, while timer 1 is
> + * used as clock_event_device.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/bitops.h>
> +#include <linux/clk.h>
> +#include <linux/clockchips.h>
> +#include <linux/interrupt.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/spinlock.h>
> +#include <asm/sched_clock.h>
> +
> +#define TIMER_CTRL		0x00
> +#define  TIMER0_EN		BIT(0)
> +#define  TIMER0_RELOAD_EN	BIT(1)
> +#define  TIMER1_EN		BIT(2)
> +#define  TIMER1_RELOAD_EN	BIT(3)
> +#define TIMER0_RELOAD		0x10
> +#define TIMER0_VAL		0x14
> +#define TIMER1_RELOAD		0x18
> +#define TIMER1_VAL		0x1c
> +
> +#define ORION_ONESHOT_MIN	1
> +#define ORION_ONESHOT_MAX	0xfffffffe
> +
> +static void __iomem *timer_base;
> +static DEFINE_SPINLOCK(timer_ctrl_lock);
> +
> +/*
> + * Thread-safe access to TIMER_CTRL register
> + * (shared with watchdog timer)
> + */
> +void orion_timer_ctrl_clrset(u32 clr, u32 set)
> +{
> +	spin_lock(&timer_ctrl_lock);
> +	writel((readl(timer_base + TIMER_CTRL) & ~clr) | set,
> +		timer_base + TIMER_CTRL);
> +	spin_unlock(&timer_ctrl_lock);
> +} 
> +EXPORT_SYMBOL(orion_timer_ctrl_clrset);
> +
> +/*
> + * Free-running clocksource handling.
> + */
> +static u32 notrace orion_read_sched_clock(void)
> +{
> +	return ~readl(timer_base + TIMER0_VAL);
> +}
> +
> +/*
> + * Clockevent handling.
> + */
> +static u32 ticks_per_jiffy;
> +
> +static int orion_clkevt_next_event(unsigned long delta,
> +				   struct clock_event_device *dev)
> +{
> +	/* setup and enable one-shot timer */
> +	writel(delta, timer_base + TIMER1_VAL);
> +	orion_timer_ctrl_clrset(TIMER1_RELOAD_EN, TIMER1_EN);
> +
> +	return 0;
> +}
> +
> +static void orion_clkevt_mode(enum clock_event_mode mode,
> +			      struct clock_event_device *dev)
> +{
> +	if (mode == CLOCK_EVT_MODE_PERIODIC) {
> +		/* setup and enable periodic timer at 1/HZ intervals */
> +		writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD);
> +		writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL);
> +		orion_timer_ctrl_clrset(0, TIMER1_RELOAD_EN | TIMER1_EN);
> +	} else {
> +		/* disable timer */
> +		orion_timer_ctrl_clrset(TIMER1_RELOAD_EN | TIMER1_EN, 0);
> +	}
> +}
> +
> +static struct clock_event_device orion_clkevt = {
> +	.name		= "orion_event",
> +	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
> +	.shift		= 32,
> +	.rating		= 300,
> +	.set_next_event	= orion_clkevt_next_event,
> +	.set_mode	= orion_clkevt_mode,
> +};
> +
> +static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id)
> +{
> +	orion_clkevt.event_handler(&orion_clkevt);
> +	return IRQ_HANDLED;
> +}
> +
> +static struct irqaction orion_clkevt_irq = {
> +	.name		= "orion_event",
> +	.flags		= IRQF_TIMER,
> +	.handler	= orion_clkevt_irq_handler,
> +};
> +
> +static void __init orion_timer_init(struct device_node *np)
> +{
> +	struct clk *clk;
> +	int irq;
> +
> +	/* timer registers are shared with watchdog timer */
> +	timer_base = of_iomap(np, 0);
> +	if (!timer_base)
> +		panic("%s: unable to map resource\n", np->name);
> +
> +	clk = of_clk_get(np, 0);
> +	if (IS_ERR(clk))
> +		panic("%s: unable to get clk\n", np->name);
> +	clk_prepare_enable(clk);
> +
> +	/* we are only interested in timer1 irq */
> +	irq = irq_of_parse_and_map(np, 1);
> +	if (irq <= 0)
> +		panic("%s: unable to parse timer1 irq\n", np->name);
> +
> +	/* setup timer0 as free-running clocksource */
> +	writel(~0, timer_base + TIMER0_VAL);
> +	writel(~0, timer_base + TIMER0_RELOAD);
> +	orion_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | TIMER0_EN);
> +	clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource",
> +			      clk_get_rate(clk), 300, 32,
> +			      clocksource_mmio_readl_down);
> +	setup_sched_clock(orion_read_sched_clock, 32, clk_get_rate(clk));
> +
> +	/* setup timer1 as clockevent timer */
> +	if (setup_irq(irq, &orion_clkevt_irq))
> +		panic("%s: unable to setup irq\n", np->name);
> +
> +	ticks_per_jiffy = (clk_get_rate(clk) + HZ/2) / HZ;
> +	orion_clkevt.cpumask = cpumask_of(0);
> +	orion_clkevt.irq = irq;
> +	clockevents_config_and_register(&orion_clkevt, clk_get_rate(clk),
> +					ORION_ONESHOT_MIN, ORION_ONESHOT_MAX);
> +}
> +CLOCKSOURCE_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init);
>
Sebastian Hesselbarth June 10, 2013, 4:31 p.m. UTC | #2
On 06/10/13 18:04, Daniel Lezcano wrote:
> On 06/10/2013 11:35 AM, Sebastian Hesselbarth wrote:
>> This patch add a DT enabled driver for timers found on Marvell Orion SoCs
>> (Kirkwood, Dove, Orion5x, and Discovery Innovation). It installs a free-
>> running clocksource on timer0 and a clockevent source on timer1.
>> Corresponding device tree documentation is also added.
>>
>> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>
> It looks good for me.
>
> Sebastian,
>
> shall I take it through my tree (it will go to Thomas's tree) ?

Daniel,

I checked MAINTAINERS and thought clocksource, i.e. patch 2/6, would go
through Thomas' or John's tree? If you want to take it, I am fine with
it but guess I am not the one to choose here ;)

Sebastian
Daniel Lezcano June 10, 2013, 4:44 p.m. UTC | #3
On 06/10/2013 06:31 PM, Sebastian Hesselbarth wrote:
> On 06/10/13 18:04, Daniel Lezcano wrote:
>> On 06/10/2013 11:35 AM, Sebastian Hesselbarth wrote:
>>> This patch add a DT enabled driver for timers found on Marvell Orion
>>> SoCs
>>> (Kirkwood, Dove, Orion5x, and Discovery Innovation). It installs a free-
>>> running clocksource on timer0 and a clockevent source on timer1.
>>> Corresponding device tree documentation is also added.
>>>
>>> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>>
>> It looks good for me.
>>
>> Sebastian,
>>
>> shall I take it through my tree (it will go to Thomas's tree) ?
> 
> Daniel,
> 
> I checked MAINTAINERS and thought clocksource, i.e. patch 2/6, would go
> through Thomas' or John's tree? If you want to take it, I am fine with
> it but guess I am not the one to choose here ;)

Actually, I am giving a hand to John and Thomas. I take the patches for
clockevents (and also for clocksource if both are mixed and John did not
pick it yet) and Thomas pulls from my tree [1].

If there is no dependency with any other patches of your patchset, which
seems to be the case, I will queue it for 3.11.

  -- Daniel

[1]
https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/commit/?h=timers/core&id=762cf9695d714d312ef7369bed1b9f9467c9e64e
Sebastian Hesselbarth June 10, 2013, 4:47 p.m. UTC | #4
On 06/10/13 18:44, Daniel Lezcano wrote:
> On 06/10/2013 06:31 PM, Sebastian Hesselbarth wrote:
>> On 06/10/13 18:04, Daniel Lezcano wrote:
>>> On 06/10/2013 11:35 AM, Sebastian Hesselbarth wrote:
>>>> This patch add a DT enabled driver for timers found on Marvell Orion
>>>> SoCs
>>>> (Kirkwood, Dove, Orion5x, and Discovery Innovation). It installs a free-
>>>> running clocksource on timer0 and a clockevent source on timer1.
>>>> Corresponding device tree documentation is also added.
>>>>
>>>> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>>>
>>> It looks good for me.
>>>
>>> Sebastian,
>>>
>>> shall I take it through my tree (it will go to Thomas's tree) ?
>>
>> Daniel,
>>
>> I checked MAINTAINERS and thought clocksource, i.e. patch 2/6, would go
>> through Thomas' or John's tree? If you want to take it, I am fine with
>> it but guess I am not the one to choose here ;)
>
> Actually, I am giving a hand to John and Thomas. I take the patches for
> clockevents (and also for clocksource if both are mixed and John did not
> pick it yet) and Thomas pulls from my tree [1].
>
> If there is no dependency with any other patches of your patchset, which
> seems to be the case, I will queue it for 3.11.

Ok, thanks!

Sebastian
Daniel Lezcano June 10, 2013, 5:06 p.m. UTC | #5
On 06/10/2013 06:47 PM, Sebastian Hesselbarth wrote:
> On 06/10/13 18:44, Daniel Lezcano wrote:
>> On 06/10/2013 06:31 PM, Sebastian Hesselbarth wrote:
>>> On 06/10/13 18:04, Daniel Lezcano wrote:
>>>> On 06/10/2013 11:35 AM, Sebastian Hesselbarth wrote:
>>>>> This patch add a DT enabled driver for timers found on Marvell Orion
>>>>> SoCs
>>>>> (Kirkwood, Dove, Orion5x, and Discovery Innovation). It installs a
>>>>> free-
>>>>> running clocksource on timer0 and a clockevent source on timer1.
>>>>> Corresponding device tree documentation is also added.
>>>>>
>>>>> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>>>>
>>>> It looks good for me.
>>>>
>>>> Sebastian,
>>>>
>>>> shall I take it through my tree (it will go to Thomas's tree) ?
>>>
>>> Daniel,
>>>
>>> I checked MAINTAINERS and thought clocksource, i.e. patch 2/6, would go
>>> through Thomas' or John's tree? If you want to take it, I am fine with
>>> it but guess I am not the one to choose here ;)
>>
>> Actually, I am giving a hand to John and Thomas. I take the patches for
>> clockevents (and also for clocksource if both are mixed and John did not
>> pick it yet) and Thomas pulls from my tree [1].
>>
>> If there is no dependency with any other patches of your patchset, which
>> seems to be the case, I will queue it for 3.11.
> 
> Ok, thanks!

I have a lot of ^M in the patch ... dos2unix removed them but I am
wondering how they get there ?
Jason Cooper June 10, 2013, 5:09 p.m. UTC | #6
On Mon, Jun 10, 2013 at 07:06:38PM +0200, Daniel Lezcano wrote:
> On 06/10/2013 06:47 PM, Sebastian Hesselbarth wrote:
> > On 06/10/13 18:44, Daniel Lezcano wrote:
> >> On 06/10/2013 06:31 PM, Sebastian Hesselbarth wrote:
> >>> On 06/10/13 18:04, Daniel Lezcano wrote:
> >>>> On 06/10/2013 11:35 AM, Sebastian Hesselbarth wrote:
> >>>>> This patch add a DT enabled driver for timers found on Marvell Orion
> >>>>> SoCs
> >>>>> (Kirkwood, Dove, Orion5x, and Discovery Innovation). It installs a
> >>>>> free-
> >>>>> running clocksource on timer0 and a clockevent source on timer1.
> >>>>> Corresponding device tree documentation is also added.
> >>>>>
> >>>>> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> >>>>
> >>>> It looks good for me.
> >>>>
> >>>> Sebastian,
> >>>>
> >>>> shall I take it through my tree (it will go to Thomas's tree) ?
> >>>
> >>> Daniel,
> >>>
> >>> I checked MAINTAINERS and thought clocksource, i.e. patch 2/6, would go
> >>> through Thomas' or John's tree? If you want to take it, I am fine with
> >>> it but guess I am not the one to choose here ;)
> >>
> >> Actually, I am giving a hand to John and Thomas. I take the patches for
> >> clockevents (and also for clocksource if both are mixed and John did not
> >> pick it yet) and Thomas pulls from my tree [1].
> >>
> >> If there is no dependency with any other patches of your patchset, which
> >> seems to be the case, I will queue it for 3.11.
> > 
> > Ok, thanks!
> 
> I have a lot of ^M in the patch ... dos2unix removed them but I am
> wondering how they get there ?

He sent it with git-send-mail, how are you extracting it from
Thunderbird?

thx,

Jason.
Daniel Lezcano June 10, 2013, 5:21 p.m. UTC | #7
On 06/10/2013 07:09 PM, Jason Cooper wrote:
> On Mon, Jun 10, 2013 at 07:06:38PM +0200, Daniel Lezcano wrote:
>> On 06/10/2013 06:47 PM, Sebastian Hesselbarth wrote:
>>> On 06/10/13 18:44, Daniel Lezcano wrote:
>>>> On 06/10/2013 06:31 PM, Sebastian Hesselbarth wrote:
>>>>> On 06/10/13 18:04, Daniel Lezcano wrote:
>>>>>> On 06/10/2013 11:35 AM, Sebastian Hesselbarth wrote:
>>>>>>> This patch add a DT enabled driver for timers found on Marvell Orion
>>>>>>> SoCs
>>>>>>> (Kirkwood, Dove, Orion5x, and Discovery Innovation). It installs a
>>>>>>> free-
>>>>>>> running clocksource on timer0 and a clockevent source on timer1.
>>>>>>> Corresponding device tree documentation is also added.
>>>>>>>
>>>>>>> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
>>>>>>
>>>>>> It looks good for me.
>>>>>>
>>>>>> Sebastian,
>>>>>>
>>>>>> shall I take it through my tree (it will go to Thomas's tree) ?
>>>>>
>>>>> Daniel,
>>>>>
>>>>> I checked MAINTAINERS and thought clocksource, i.e. patch 2/6, would go
>>>>> through Thomas' or John's tree? If you want to take it, I am fine with
>>>>> it but guess I am not the one to choose here ;)
>>>>
>>>> Actually, I am giving a hand to John and Thomas. I take the patches for
>>>> clockevents (and also for clocksource if both are mixed and John did not
>>>> pick it yet) and Thomas pulls from my tree [1].
>>>>
>>>> If there is no dependency with any other patches of your patchset, which
>>>> seems to be the case, I will queue it for 3.11.
>>>
>>> Ok, thanks!
>>
>> I have a lot of ^M in the patch ... dos2unix removed them but I am
>> wondering how they get there ?
> 
> He sent it with git-send-mail, how are you extracting it from
> Thunderbird?

I use a script to extract the patch from my mailbox. I am using it for
years now I did not face these spurious characters before.

Anyway, it seems not related to the patch itself, I will handle that.

Thanks
  -- Daniel
Andrew Lunn June 10, 2013, 5:25 p.m. UTC | #8
On Mon, Jun 10, 2013 at 11:35:55AM +0200, Sebastian Hesselbarth wrote:
> This patch add a DT enabled driver for timers found on Marvell Orion SoCs
> (Kirkwood, Dove, Orion5x, and Discovery Innovation). It installs a free-
> running clocksource on timer0 and a clockevent source on timer1.
> Corresponding device tree documentation is also added.
> 
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> ---
> Changelog:
> v3->v4:
> - export thread-safe access to TIMER_CTRL register to use with watchdog
> - remove IRQF_DISABLED and add .irq to clock event (Suggested by Daniel Lezcano)
> 
> Notes:
> - This is only an update to clocksource driver, the remaining patches are
>   not resent as they have not been changed.
> - I will not rework orion watchdog driver for this patch set. It is written
>   Kirkwood/Orion5x specific although it will also work on Dove and it is messing
>   with shared registers. It has done it before, so I consider it broken anyway.
>   I (or somebody else) will take care of proper watchdog later.
> - An updated branch can be found on
>   git://github.com/shesselba/linux-dove.git orion-irqchip-for-v3.11_v4

Hi Sebastian

You can add a

Tested-by: Andrew Lunn <andrew@lunn.ch>

I tested on my kirkwood QNAP.

           CPU0
  2:       6062  bridge-interrupt-ctrl  orion_event
  9:          0  f1010140.gpio  Reset
 15:          0  f1010140.gpio  USB Copy
 24:        106  main-interrupt-ctrl  ehci_hcd:usb1
 25:       2463  main-interrupt-ctrl  sata_mv
 26:          0  main-interrupt-ctrl  f1030000.crypto
 27:          2  main-interrupt-ctrl  f1060800.xor
 28:          2  main-interrupt-ctrl  f1060800.xor
 29:         71  main-interrupt-ctrl  mv64xxx_i2c
 30:          2  main-interrupt-ctrl  f1060900.xor
 31:          2  main-interrupt-ctrl  f1060900.xor
 32:         41  main-interrupt-ctrl  eth0
 33:       1317  main-interrupt-ctrl  serial
 75:        745  main-interrupt-ctrl  f1072004.mdio-bus
Err:          0                                              

      Andrew
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/timer/marvell,orion-timer.txt b/Documentation/devicetree/bindings/timer/marvell,orion-timer.txt
new file mode 100644
index 0000000..62bb826
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/marvell,orion-timer.txt
@@ -0,0 +1,17 @@ 
+Marvell Orion SoC timer
+
+Required properties:
+- compatible: shall be "marvell,orion-timer"
+- reg: base address of the timer register starting with TIMERS CONTROL register
+- interrupt-parent: phandle of the bridge interrupt controller
+- interrupts: should contain the interrupts for Timer0 and Timer1
+- clocks: phandle of timer reference clock (tclk)
+
+Example:
+	timer: timer {
+		compatible = "marvell,orion-timer";
+		reg = <0x20300 0x20>;
+		interrupt-parent = <&bridge_intc>;
+		interrupts = <1>, <2>;
+		clocks = <&core_clk 0>;
+	};
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index f151c6c..2404869 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -25,6 +25,11 @@  config DW_APB_TIMER_OF
 config ARMADA_370_XP_TIMER
 	bool
 
+config ORION_TIMER
+	select CLKSRC_OF
+	select CLKSRC_MMIO
+	bool
+
 config SUN4I_TIMER
 	bool
 
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 8d979c7..d1e8d68 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -15,6 +15,7 @@  obj-$(CONFIG_DW_APB_TIMER_OF)	+= dw_apb_timer_of.o
 obj-$(CONFIG_CLKSRC_NOMADIK_MTU)	+= nomadik-mtu.o
 obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o
 obj-$(CONFIG_ARMADA_370_XP_TIMER)	+= time-armada-370-xp.o
+obj-$(CONFIG_ORION_TIMER)	+= time-orion.o
 obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
 obj-$(CONFIG_ARCH_MARCO)	+= timer-marco.o
 obj-$(CONFIG_ARCH_MXS)		+= mxs_timer.o
diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c
new file mode 100644
index 0000000..ad7df17
--- /dev/null
+++ b/drivers/clocksource/time-orion.c
@@ -0,0 +1,150 @@ 
+/*
+ * Marvell Orion SoC timer handling.
+ *
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Timer 0 is used as free-running clocksource, while timer 1 is
+ * used as clock_event_device.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/spinlock.h>
+#include <asm/sched_clock.h>
+
+#define TIMER_CTRL		0x00
+#define  TIMER0_EN		BIT(0)
+#define  TIMER0_RELOAD_EN	BIT(1)
+#define  TIMER1_EN		BIT(2)
+#define  TIMER1_RELOAD_EN	BIT(3)
+#define TIMER0_RELOAD		0x10
+#define TIMER0_VAL		0x14
+#define TIMER1_RELOAD		0x18
+#define TIMER1_VAL		0x1c
+
+#define ORION_ONESHOT_MIN	1
+#define ORION_ONESHOT_MAX	0xfffffffe
+
+static void __iomem *timer_base;
+static DEFINE_SPINLOCK(timer_ctrl_lock);
+
+/*
+ * Thread-safe access to TIMER_CTRL register
+ * (shared with watchdog timer)
+ */
+void orion_timer_ctrl_clrset(u32 clr, u32 set)
+{
+	spin_lock(&timer_ctrl_lock);
+	writel((readl(timer_base + TIMER_CTRL) & ~clr) | set,
+		timer_base + TIMER_CTRL);
+	spin_unlock(&timer_ctrl_lock);
+} 
+EXPORT_SYMBOL(orion_timer_ctrl_clrset);
+
+/*
+ * Free-running clocksource handling.
+ */
+static u32 notrace orion_read_sched_clock(void)
+{
+	return ~readl(timer_base + TIMER0_VAL);
+}
+
+/*
+ * Clockevent handling.
+ */
+static u32 ticks_per_jiffy;
+
+static int orion_clkevt_next_event(unsigned long delta,
+				   struct clock_event_device *dev)
+{
+	/* setup and enable one-shot timer */
+	writel(delta, timer_base + TIMER1_VAL);
+	orion_timer_ctrl_clrset(TIMER1_RELOAD_EN, TIMER1_EN);
+
+	return 0;
+}
+
+static void orion_clkevt_mode(enum clock_event_mode mode,
+			      struct clock_event_device *dev)
+{
+	if (mode == CLOCK_EVT_MODE_PERIODIC) {
+		/* setup and enable periodic timer at 1/HZ intervals */
+		writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD);
+		writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL);
+		orion_timer_ctrl_clrset(0, TIMER1_RELOAD_EN | TIMER1_EN);
+	} else {
+		/* disable timer */
+		orion_timer_ctrl_clrset(TIMER1_RELOAD_EN | TIMER1_EN, 0);
+	}
+}
+
+static struct clock_event_device orion_clkevt = {
+	.name		= "orion_event",
+	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
+	.shift		= 32,
+	.rating		= 300,
+	.set_next_event	= orion_clkevt_next_event,
+	.set_mode	= orion_clkevt_mode,
+};
+
+static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id)
+{
+	orion_clkevt.event_handler(&orion_clkevt);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction orion_clkevt_irq = {
+	.name		= "orion_event",
+	.flags		= IRQF_TIMER,
+	.handler	= orion_clkevt_irq_handler,
+};
+
+static void __init orion_timer_init(struct device_node *np)
+{
+	struct clk *clk;
+	int irq;
+
+	/* timer registers are shared with watchdog timer */
+	timer_base = of_iomap(np, 0);
+	if (!timer_base)
+		panic("%s: unable to map resource\n", np->name);
+
+	clk = of_clk_get(np, 0);
+	if (IS_ERR(clk))
+		panic("%s: unable to get clk\n", np->name);
+	clk_prepare_enable(clk);
+
+	/* we are only interested in timer1 irq */
+	irq = irq_of_parse_and_map(np, 1);
+	if (irq <= 0)
+		panic("%s: unable to parse timer1 irq\n", np->name);
+
+	/* setup timer0 as free-running clocksource */
+	writel(~0, timer_base + TIMER0_VAL);
+	writel(~0, timer_base + TIMER0_RELOAD);
+	orion_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | TIMER0_EN);
+	clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource",
+			      clk_get_rate(clk), 300, 32,
+			      clocksource_mmio_readl_down);
+	setup_sched_clock(orion_read_sched_clock, 32, clk_get_rate(clk));
+
+	/* setup timer1 as clockevent timer */
+	if (setup_irq(irq, &orion_clkevt_irq))
+		panic("%s: unable to setup irq\n", np->name);
+
+	ticks_per_jiffy = (clk_get_rate(clk) + HZ/2) / HZ;
+	orion_clkevt.cpumask = cpumask_of(0);
+	orion_clkevt.irq = irq;
+	clockevents_config_and_register(&orion_clkevt, clk_get_rate(clk),
+					ORION_ONESHOT_MIN, ORION_ONESHOT_MAX);
+}
+CLOCKSOURCE_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init);