From bfe45e0be88d8a2e408226d473bff60da4a97d1f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 8 May 2011 15:33:30 +0100 Subject: clocksource: convert ARM 32-bit down counting clocksources Convert SP804, MXC, Nomadik and Orion 32-bit down-counting clocksources to generic mmio clocksource infrastructure. Acked-by: Catalin Marinas Cc: Sascha Hauer Cc: Alessandro Rubini Acked-by: Linus Walleij Cc: Lennert Buytenhek Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/common/timer-sp.c | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) (limited to 'arch/arm/common/timer-sp.c') diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index 6ef3342153b9..445b05ee8511 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -32,35 +32,17 @@ #define TIMER_FREQ_KHZ (1000) #define TIMER_RELOAD (TIMER_FREQ_KHZ * 1000 / HZ) -static void __iomem *clksrc_base; - -static cycle_t sp804_read(struct clocksource *cs) -{ - return ~readl(clksrc_base + TIMER_VALUE); -} - -static struct clocksource clocksource_sp804 = { - .name = "timer3", - .rating = 200, - .read = sp804_read, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - void __init sp804_clocksource_init(void __iomem *base) { - struct clocksource *cs = &clocksource_sp804; - - clksrc_base = base; - /* setup timer 0 as free-running clocksource */ - writel(0, clksrc_base + TIMER_CTRL); - writel(0xffffffff, clksrc_base + TIMER_LOAD); - writel(0xffffffff, clksrc_base + TIMER_VALUE); + writel(0, base + TIMER_CTRL); + writel(0xffffffff, base + TIMER_LOAD); + writel(0xffffffff, base + TIMER_VALUE); writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, - clksrc_base + TIMER_CTRL); + base + TIMER_CTRL); - clocksource_register_khz(cs, TIMER_FREQ_KHZ); + clocksource_mmio_init(base + TIMER_VALUE, "timer3", + TIMER_FREQ_KHZ * 1000, 200, 32, clocksource_mmio_readl_down); } -- cgit v1.2.3 From fb593cf38fc426331275d761fefe13096070f56a Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 May 2011 12:08:23 +0100 Subject: clocksource: ARM sp804: allow clocksource name to be specified This allows platforms to specify the clocksource name upon registration, which is necessary should they wish to register more than one sp804 clocksource. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/common/timer-sp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/common/timer-sp.c') diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index 445b05ee8511..f6b9011744aa 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -32,7 +32,7 @@ #define TIMER_FREQ_KHZ (1000) #define TIMER_RELOAD (TIMER_FREQ_KHZ * 1000 / HZ) -void __init sp804_clocksource_init(void __iomem *base) +void __init sp804_clocksource_init(void __iomem *base, const char *name) { /* setup timer 0 as free-running clocksource */ writel(0, base + TIMER_CTRL); @@ -41,7 +41,7 @@ void __init sp804_clocksource_init(void __iomem *base) writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, base + TIMER_CTRL); - clocksource_mmio_init(base + TIMER_VALUE, "timer3", + clocksource_mmio_init(base + TIMER_VALUE, name, TIMER_FREQ_KHZ * 1000, 200, 32, clocksource_mmio_readl_down); } -- cgit v1.2.3 From 7ff550de99141cbd3be0129d563cc4554fdde9f6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 May 2011 13:31:48 +0100 Subject: clocksource: ARM sp804: obtain sp804 timer rate via clks This allows platforms to specify the rate of the SP804 clocksource via the clk subsystem. While ARM boards clock these at 1MHz, BCMRing also has SP804 timers but are clocked at different rates. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/common/timer-sp.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'arch/arm/common/timer-sp.c') diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index f6b9011744aa..166f892a24d5 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -18,8 +18,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include +#include #include #include #include @@ -32,8 +34,43 @@ #define TIMER_FREQ_KHZ (1000) #define TIMER_RELOAD (TIMER_FREQ_KHZ * 1000 / HZ) +static long __init sp804_get_clock_rate(const char *name) +{ + struct clk *clk; + long rate; + int err; + + clk = clk_get_sys("sp804", name); + if (IS_ERR(clk)) { + pr_err("sp804: %s clock not found: %d\n", name, + (int)PTR_ERR(clk)); + return PTR_ERR(clk); + } + + err = clk_enable(clk); + if (err) { + pr_err("sp804: %s clock failed to enable: %d\n", name, err); + clk_put(clk); + return err; + } + + rate = clk_get_rate(clk); + if (rate < 0) { + pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate); + clk_disable(clk); + clk_put(clk); + } + + return rate; +} + void __init sp804_clocksource_init(void __iomem *base, const char *name) { + long rate = sp804_get_clock_rate(name); + + if (rate < 0) + return; + /* setup timer 0 as free-running clocksource */ writel(0, base + TIMER_CTRL); writel(0xffffffff, base + TIMER_LOAD); @@ -42,7 +79,7 @@ void __init sp804_clocksource_init(void __iomem *base, const char *name) base + TIMER_CTRL); clocksource_mmio_init(base + TIMER_VALUE, name, - TIMER_FREQ_KHZ * 1000, 200, 32, clocksource_mmio_readl_down); + rate, 200, 32, clocksource_mmio_readl_down); } -- cgit v1.2.3 From 57cc4f7de2b896ca79185e337eaf7ff9906c4656 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 May 2011 15:31:13 +0100 Subject: clockevents: ARM sp804: allow clockevent name to be specified This allows platforms to specify the clcokevent name upon registration. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/common/timer-sp.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch/arm/common/timer-sp.c') diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index 166f892a24d5..5b7e8c9046be 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -139,7 +139,6 @@ static int sp804_set_next_event(unsigned long next, } static struct clock_event_device sp804_clockevent = { - .name = "timer0", .shift = 32, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = sp804_set_mode, @@ -155,17 +154,19 @@ static struct irqaction sp804_timer_irq = { .dev_id = &sp804_clockevent, }; -void __init sp804_clockevents_init(void __iomem *base, unsigned int timer_irq) +void __init sp804_clockevents_init(void __iomem *base, unsigned int irq, + const char *name) { struct clock_event_device *evt = &sp804_clockevent; clkevt_base = base; - evt->irq = timer_irq; + evt->name = name; + evt->irq = irq; evt->mult = div_sc(TIMER_FREQ_KHZ, NSEC_PER_MSEC, evt->shift); evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt); evt->min_delta_ns = clockevent_delta2ns(0xf, evt); - setup_irq(timer_irq, &sp804_timer_irq); + setup_irq(irq, &sp804_timer_irq); clockevents_register_device(evt); } -- cgit v1.2.3 From 23828a7a976eb8dbe3b5f4e83584c3fe814b295b Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 May 2011 15:45:16 +0100 Subject: clockevents: ARM sp804: obtain sp804 timer rate via clks This allows platforms to specify the rate of the SP804 clockevent via the clk subsystem. While ARM boards clock these at 1MHz, BCMRing also has SP804 timers but are clocked at different rates. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/common/timer-sp.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch/arm/common/timer-sp.c') diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index 5b7e8c9046be..41df47875122 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -28,12 +28,6 @@ #include -/* - * These timers are currently always setup to be clocked at 1MHz. - */ -#define TIMER_FREQ_KHZ (1000) -#define TIMER_RELOAD (TIMER_FREQ_KHZ * 1000 / HZ) - static long __init sp804_get_clock_rate(const char *name) { struct clk *clk; @@ -84,6 +78,7 @@ void __init sp804_clocksource_init(void __iomem *base, const char *name) static void __iomem *clkevt_base; +static unsigned long clkevt_reload; /* * IRQ handler for the timer @@ -109,7 +104,7 @@ static void sp804_set_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - writel(TIMER_RELOAD, clkevt_base + TIMER_LOAD); + writel(clkevt_reload, clkevt_base + TIMER_LOAD); ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; break; @@ -158,12 +153,17 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name) { struct clock_event_device *evt = &sp804_clockevent; + long rate = sp804_get_clock_rate(name); + + if (rate < 0) + return; clkevt_base = base; + clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ); evt->name = name; evt->irq = irq; - evt->mult = div_sc(TIMER_FREQ_KHZ, NSEC_PER_MSEC, evt->shift); + evt->mult = div_sc(rate, NSEC_PER_SEC, evt->shift); evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt); evt->min_delta_ns = clockevent_delta2ns(0xf, evt); -- cgit v1.2.3