Commit 234b6ced authored by Russell King's avatar Russell King

clocksource: convert ARM 32-bit up counting clocksources

Convert ixp4xx, lpc32xx, mxc, netx, pxa, sa1100, tcc8k, tegra and u300
to use the generic mmio clocksource recently introduced.

Cc: Imre Kaloz <kaloz@openwrt.org>
Cc: Krzysztof Halasa <khc@pm.waw.pl>
Acked-by: default avatarEric Miao <eric.y.miao@gmail.com>
Acked-by: default avatar"Hans J. Koch" <hjk@hansjkoch.de>
Acked-by: default avatarColin Cross <ccross@android.com>
Cc: Erik Gilling <konkers@android.com>
Cc: Olof Johansson <olof@lixom.net>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Acked-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 442c8176
...@@ -366,6 +366,7 @@ config ARCH_MXC ...@@ -366,6 +366,7 @@ config ARCH_MXC
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select CLKDEV_LOOKUP select CLKDEV_LOOKUP
select CLKSRC_MMIO
select HAVE_SCHED_CLOCK select HAVE_SCHED_CLOCK
help help
Support for Freescale MXC/iMX-based family of processors Support for Freescale MXC/iMX-based family of processors
...@@ -390,6 +391,7 @@ config ARCH_STMP3XXX ...@@ -390,6 +391,7 @@ config ARCH_STMP3XXX
config ARCH_NETX config ARCH_NETX
bool "Hilscher NetX based" bool "Hilscher NetX based"
select CLKSRC_MMIO
select CPU_ARM926T select CPU_ARM926T
select ARM_VIC select ARM_VIC
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
...@@ -457,6 +459,7 @@ config ARCH_IXP2000 ...@@ -457,6 +459,7 @@ config ARCH_IXP2000
config ARCH_IXP4XX config ARCH_IXP4XX
bool "IXP4xx-based" bool "IXP4xx-based"
depends on MMU depends on MMU
select CLKSRC_MMIO
select CPU_XSCALE select CPU_XSCALE
select GENERIC_GPIO select GENERIC_GPIO
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
...@@ -497,6 +500,7 @@ config ARCH_LOKI ...@@ -497,6 +500,7 @@ config ARCH_LOKI
config ARCH_LPC32XX config ARCH_LPC32XX
bool "NXP LPC32XX" bool "NXP LPC32XX"
select CLKSRC_MMIO
select CPU_ARM926T select CPU_ARM926T
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select HAVE_IDE select HAVE_IDE
...@@ -592,6 +596,7 @@ config ARCH_NUC93X ...@@ -592,6 +596,7 @@ config ARCH_NUC93X
config ARCH_TEGRA config ARCH_TEGRA
bool "NVIDIA Tegra" bool "NVIDIA Tegra"
select CLKDEV_LOOKUP select CLKDEV_LOOKUP
select CLKSRC_MMIO
select GENERIC_TIME select GENERIC_TIME
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select GENERIC_GPIO select GENERIC_GPIO
...@@ -617,6 +622,7 @@ config ARCH_PXA ...@@ -617,6 +622,7 @@ config ARCH_PXA
select ARCH_MTD_XIP select ARCH_MTD_XIP
select ARCH_HAS_CPUFREQ select ARCH_HAS_CPUFREQ
select CLKDEV_LOOKUP select CLKDEV_LOOKUP
select CLKSRC_MMIO
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select HAVE_SCHED_CLOCK select HAVE_SCHED_CLOCK
...@@ -667,6 +673,7 @@ config ARCH_RPC ...@@ -667,6 +673,7 @@ config ARCH_RPC
config ARCH_SA1100 config ARCH_SA1100
bool "SA1100-based" bool "SA1100-based"
select CLKSRC_MMIO
select CPU_SA1100 select CPU_SA1100
select ISA select ISA
select ARCH_SPARSEMEM_ENABLE select ARCH_SPARSEMEM_ENABLE
...@@ -803,6 +810,7 @@ config ARCH_SHARK ...@@ -803,6 +810,7 @@ config ARCH_SHARK
config ARCH_TCC_926 config ARCH_TCC_926
bool "Telechips TCC ARM926-based systems" bool "Telechips TCC ARM926-based systems"
select CLKSRC_MMIO
select CPU_ARM926T select CPU_ARM926T
select HAVE_CLK select HAVE_CLK
select CLKDEV_LOOKUP select CLKDEV_LOOKUP
...@@ -813,6 +821,7 @@ config ARCH_TCC_926 ...@@ -813,6 +821,7 @@ config ARCH_TCC_926
config ARCH_U300 config ARCH_U300
bool "ST-Ericsson U300 Series" bool "ST-Ericsson U300 Series"
depends on MMU depends on MMU
select CLKSRC_MMIO
select CPU_ARM926T select CPU_ARM926T
select HAVE_SCHED_CLOCK select HAVE_SCHED_CLOCK
select HAVE_TCM select HAVE_TCM
......
...@@ -419,26 +419,14 @@ static void notrace ixp4xx_update_sched_clock(void) ...@@ -419,26 +419,14 @@ static void notrace ixp4xx_update_sched_clock(void)
/* /*
* clocksource * clocksource
*/ */
static cycle_t ixp4xx_get_cycles(struct clocksource *cs)
{
return *IXP4XX_OSTS;
}
static struct clocksource clocksource_ixp4xx = {
.name = "OSTS",
.rating = 200,
.read = ixp4xx_get_cycles,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ; unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;
EXPORT_SYMBOL(ixp4xx_timer_freq); EXPORT_SYMBOL(ixp4xx_timer_freq);
static void __init ixp4xx_clocksource_init(void) static void __init ixp4xx_clocksource_init(void)
{ {
init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq); init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq);
clocksource_register_hz(&clocksource_ixp4xx, ixp4xx_timer_freq); clocksource_mmio_init(&IXP4XX_OSTS, "OSTS", ixp4xx_timer_freq, 200, 32,
clocksource_mmio_readl_up);
} }
/* /*
......
...@@ -31,19 +31,6 @@ ...@@ -31,19 +31,6 @@
#include <mach/platform.h> #include <mach/platform.h>
#include "common.h" #include "common.h"
static cycle_t lpc32xx_clksrc_read(struct clocksource *cs)
{
return (cycle_t)__raw_readl(LCP32XX_TIMER_TC(LPC32XX_TIMER1_BASE));
}
static struct clocksource lpc32xx_clksrc = {
.name = "lpc32xx_clksrc",
.rating = 300,
.read = lpc32xx_clksrc_read,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static int lpc32xx_clkevt_next_event(unsigned long delta, static int lpc32xx_clkevt_next_event(unsigned long delta,
struct clock_event_device *dev) struct clock_event_device *dev)
{ {
...@@ -170,7 +157,9 @@ static void __init lpc32xx_timer_init(void) ...@@ -170,7 +157,9 @@ static void __init lpc32xx_timer_init(void)
__raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE)); __raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE));
__raw_writel(LCP32XX_TIMER_CNTR_TCR_EN, __raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE)); LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
clocksource_register_hz(&lpc32xx_clksrc, clkrate);
clocksource_mmio_init(LCP32XX_TIMER_TC(LPC32XX_TIMER1_BASE),
"lpc32xx_clksrc", clkrate, 300, 32, clocksource_mmio_readl_up);
} }
struct sys_timer lpc32xx_timer = { struct sys_timer lpc32xx_timer = {
......
...@@ -104,19 +104,6 @@ static struct irqaction netx_timer_irq = { ...@@ -104,19 +104,6 @@ static struct irqaction netx_timer_irq = {
.handler = netx_timer_interrupt, .handler = netx_timer_interrupt,
}; };
cycle_t netx_get_cycles(struct clocksource *cs)
{
return readl(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE));
}
static struct clocksource clocksource_netx = {
.name = "netx_timer",
.rating = 200,
.read = netx_get_cycles,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
/* /*
* Set up timer interrupt * Set up timer interrupt
*/ */
...@@ -150,7 +137,8 @@ static void __init netx_timer_init(void) ...@@ -150,7 +137,8 @@ static void __init netx_timer_init(void)
writel(NETX_GPIO_COUNTER_CTRL_RUN, writel(NETX_GPIO_COUNTER_CTRL_RUN,
NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE)); NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE));
clocksource_register_hz(&clocksource_netx, CLOCK_TICK_RATE); clocksource_mmio_init(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE),
"netx_timer", CLOCK_TICK_RATE, 200, 32, clocksource_mmio_readl_up);
netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
netx_clockevent.shift); netx_clockevent.shift);
......
...@@ -105,19 +105,6 @@ static struct clock_event_device ckevt_pxa_osmr0 = { ...@@ -105,19 +105,6 @@ static struct clock_event_device ckevt_pxa_osmr0 = {
.set_mode = pxa_osmr0_set_mode, .set_mode = pxa_osmr0_set_mode,
}; };
static cycle_t pxa_read_oscr(struct clocksource *cs)
{
return OSCR;
}
static struct clocksource cksrc_pxa_oscr0 = {
.name = "oscr0",
.rating = 200,
.read = pxa_read_oscr,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static struct irqaction pxa_ost0_irq = { static struct irqaction pxa_ost0_irq = {
.name = "ost0", .name = "ost0",
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
...@@ -134,7 +121,6 @@ static void __init pxa_timer_init(void) ...@@ -134,7 +121,6 @@ static void __init pxa_timer_init(void)
init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate); init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate);
clocksource_calc_mult_shift(&cksrc_pxa_oscr0, clock_tick_rate, 4);
clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4); clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4);
ckevt_pxa_osmr0.max_delta_ns = ckevt_pxa_osmr0.max_delta_ns =
clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0);
...@@ -144,7 +130,8 @@ static void __init pxa_timer_init(void) ...@@ -144,7 +130,8 @@ static void __init pxa_timer_init(void)
setup_irq(IRQ_OST0, &pxa_ost0_irq); setup_irq(IRQ_OST0, &pxa_ost0_irq);
clocksource_register_hz(&cksrc_pxa_oscr0, clock_tick_rate); clocksource_mmio_init(&OSCR, "oscr0", clock_tick_rate, 200, 32,
clocksource_mmio_readl_up);
clockevents_register_device(&ckevt_pxa_osmr0); clockevents_register_device(&ckevt_pxa_osmr0);
} }
......
...@@ -97,19 +97,6 @@ static struct clock_event_device ckevt_sa1100_osmr0 = { ...@@ -97,19 +97,6 @@ static struct clock_event_device ckevt_sa1100_osmr0 = {
.set_mode = sa1100_osmr0_set_mode, .set_mode = sa1100_osmr0_set_mode,
}; };
static cycle_t sa1100_read_oscr(struct clocksource *s)
{
return OSCR;
}
static struct clocksource cksrc_sa1100_oscr = {
.name = "oscr",
.rating = 200,
.read = sa1100_read_oscr,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static struct irqaction sa1100_timer_irq = { static struct irqaction sa1100_timer_irq = {
.name = "ost0", .name = "ost0",
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
...@@ -134,7 +121,8 @@ static void __init sa1100_timer_init(void) ...@@ -134,7 +121,8 @@ static void __init sa1100_timer_init(void)
setup_irq(IRQ_OST0, &sa1100_timer_irq); setup_irq(IRQ_OST0, &sa1100_timer_irq);
clocksource_register_hz(&cksrc_sa1100_oscr, CLOCK_TICK_RATE); clocksource_mmio_init(&OSCR, "oscr", CLOCK_TICK_RATE, 200, 32,
clocksource_mmio_readl_up);
clockevents_register_device(&ckevt_sa1100_osmr0); clockevents_register_device(&ckevt_sa1100_osmr0);
} }
......
...@@ -25,19 +25,6 @@ ...@@ -25,19 +25,6 @@
static void __iomem *timer_base; static void __iomem *timer_base;
static cycle_t tcc_get_cycles(struct clocksource *cs)
{
return __raw_readl(timer_base + TC32MCNT_OFFS);
}
static struct clocksource clocksource_tcc = {
.name = "tcc_tc32",
.rating = 200,
.read = tcc_get_cycles,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static int tcc_set_next_event(unsigned long evt, static int tcc_set_next_event(unsigned long evt,
struct clock_event_device *unused) struct clock_event_device *unused)
{ {
...@@ -102,7 +89,8 @@ static int __init tcc_clockevent_init(struct clk *clock) ...@@ -102,7 +89,8 @@ static int __init tcc_clockevent_init(struct clk *clock)
{ {
unsigned int c = clk_get_rate(clock); unsigned int c = clk_get_rate(clock);
clocksource_register_hz(&clocksource_tcc, c); clocksource_mmio_init(timer_base + TC32MCNT_OFFS, "tcc_tc32", c,
200, 32, clocksource_mmio_readl_up);
clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC, clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC,
clockevent_tcc.shift); clockevent_tcc.shift);
......
...@@ -98,11 +98,6 @@ static void tegra_timer_set_mode(enum clock_event_mode mode, ...@@ -98,11 +98,6 @@ static void tegra_timer_set_mode(enum clock_event_mode mode,
} }
} }
static cycle_t tegra_clocksource_read(struct clocksource *cs)
{
return timer_readl(TIMERUS_CNTR_1US);
}
static struct clock_event_device tegra_clockevent = { static struct clock_event_device tegra_clockevent = {
.name = "timer0", .name = "timer0",
.rating = 300, .rating = 300,
...@@ -111,14 +106,6 @@ static struct clock_event_device tegra_clockevent = { ...@@ -111,14 +106,6 @@ static struct clock_event_device tegra_clockevent = {
.set_mode = tegra_timer_set_mode, .set_mode = tegra_timer_set_mode,
}; };
static struct clocksource tegra_clocksource = {
.name = "timer_us",
.rating = 300,
.read = tegra_clocksource_read,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static DEFINE_CLOCK_DATA(cd); static DEFINE_CLOCK_DATA(cd);
/* /*
...@@ -234,7 +221,8 @@ static void __init tegra_init_timer(void) ...@@ -234,7 +221,8 @@ static void __init tegra_init_timer(void)
init_fixed_sched_clock(&cd, tegra_update_sched_clock, 32, init_fixed_sched_clock(&cd, tegra_update_sched_clock, 32,
1000000, SC_MULT, SC_SHIFT); 1000000, SC_MULT, SC_SHIFT);
if (clocksource_register_hz(&tegra_clocksource, 1000000)) { if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US,
"timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) {
printk(KERN_ERR "Failed to register clocksource\n"); printk(KERN_ERR "Failed to register clocksource\n");
BUG(); BUG();
} }
......
...@@ -333,20 +333,6 @@ static struct irqaction u300_timer_irq = { ...@@ -333,20 +333,6 @@ static struct irqaction u300_timer_irq = {
.handler = u300_timer_interrupt, .handler = u300_timer_interrupt,
}; };
/* Use general purpose timer 2 as clock source */
static cycle_t u300_get_cycles(struct clocksource *cs)
{
return (cycles_t) readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC);
}
static struct clocksource clocksource_u300_1mhz = {
.name = "GPT2",
.rating = 300, /* Reasonably fast and accurate clock source */
.read = u300_get_cycles,
.mask = CLOCKSOURCE_MASK(32), /* 32 bits */
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
/* /*
* Override the global weak sched_clock symbol with this * Override the global weak sched_clock symbol with this
* local implementation which uses the clocksource to get some * local implementation which uses the clocksource to get some
...@@ -422,7 +408,9 @@ static void __init u300_timer_init(void) ...@@ -422,7 +408,9 @@ static void __init u300_timer_init(void)
writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE, writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE,
U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2); U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2);
if (clocksource_register_hz(&clocksource_u300_1mhz, rate)) /* Use general purpose timer 2 as clock source */
if (clocksource_mmio_init(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC,
"GPT2", rate, 300, 32, clocksource_mmio_readl_up))
printk(KERN_ERR "timer: failed to initialize clock " printk(KERN_ERR "timer: failed to initialize clock "
"source %s\n", clocksource_u300_1mhz.name); "source %s\n", clocksource_u300_1mhz.name);
......
...@@ -106,56 +106,32 @@ static void gpt_irq_acknowledge(void) ...@@ -106,56 +106,32 @@ static void gpt_irq_acknowledge(void)
__raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT); __raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT);
} }
static cycle_t dummy_get_cycles(struct clocksource *cs) static void __iomem *sched_clock_reg;
{
return 0;
}
static cycle_t mx1_2_get_cycles(struct clocksource *cs)
{
return __raw_readl(timer_base + MX1_2_TCN);
}
static cycle_t v2_get_cycles(struct clocksource *cs)
{
return __raw_readl(timer_base + V2_TCN);
}
static struct clocksource clocksource_mxc = {
.name = "mxc_timer1",
.rating = 200,
.read = dummy_get_cycles,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static DEFINE_CLOCK_DATA(cd); static DEFINE_CLOCK_DATA(cd);
unsigned long long notrace sched_clock(void) unsigned long long notrace sched_clock(void)
{ {
cycle_t cyc = clocksource_mxc.read(&clocksource_mxc); cycle_t cyc = sched_clock_reg ? __raw_readl(sched_clock_reg) : 0;
return cyc_to_sched_clock(&cd, cyc, (u32)~0); return cyc_to_sched_clock(&cd, cyc, (u32)~0);
} }
static void notrace mxc_update_sched_clock(void) static void notrace mxc_update_sched_clock(void)
{ {
cycle_t cyc = clocksource_mxc.read(&clocksource_mxc); cycle_t cyc = sched_clock_reg ? __raw_readl(sched_clock_reg) : 0;
update_sched_clock(&cd, cyc, (u32)~0); update_sched_clock(&cd, cyc, (u32)~0);
} }
static int __init mxc_clocksource_init(struct clk *timer_clk) static int __init mxc_clocksource_init(struct clk *timer_clk)
{ {
unsigned int c = clk_get_rate(timer_clk); unsigned int c = clk_get_rate(timer_clk);
void __iomem *reg = timer_base + (timer_is_v2() ? V2_TCN : MX1_2_TCN);
if (timer_is_v2()) sched_clock_reg = reg;
clocksource_mxc.read = v2_get_cycles;
else
clocksource_mxc.read = mx1_2_get_cycles;
init_sched_clock(&cd, mxc_update_sched_clock, 32, c); init_sched_clock(&cd, mxc_update_sched_clock, 32, c);
clocksource_register_hz(&clocksource_mxc, c); return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32,
clocksource_mmio_readl_up);
return 0;
} }
/* clock event */ /* clock event */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment