lkml.org 
[lkml]   [2009]   [Jul]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    SubjectRE: [PATCH 1/1] [ARM] ep93xx clockevent support
    Date
    From
    On Wednesday, July 22, 2009 3:13 AM, Ahmed Ammar wrote:
    > From: Ahmed Ammar <aammar@edge-techno.com>
    >
    > Based on previous work by Thomas Gleixner.
    >
    > Signed-off-by: Ahmed Ammar <aammar@edge-techno.com>

    Hmm.. With kernel 2.6.30.2 this does not build. See below.

    > ---
    > arch/arm/Kconfig | 2 +
    > arch/arm/mach-ep93xx/core.c | 130 ++++++++++++++++++-----
    > arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 6 +
    > 3 files changed, 112 insertions(+), 26 deletions(-)
    >
    > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
    > index 74713a5..f33fd06 100644
    > --- a/arch/arm/Kconfig
    > +++ b/arch/arm/Kconfig
    > @@ -273,6 +273,8 @@ config ARCH_EP93XX
    > select HAVE_CLK
    > select COMMON_CLKDEV
    > select ARCH_REQUIRE_GPIOLIB
    > + select GENERIC_TIME
    > + select GENERIC_CLOCKEVENTS
    > help
    > This enables support for the Cirrus EP93xx series of CPUs.
    >
    > diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
    > index 7983a3b..cbd9187 100644
    > --- a/arch/arm/mach-ep93xx/core.c
    > +++ b/arch/arm/mach-ep93xx/core.c
    > @@ -33,6 +33,9 @@
    > #include <linux/termios.h>
    > #include <linux/amba/bus.h>
    > #include <linux/amba/serial.h>
    > +#include <linux/clocksource.h>
    > +#include <linux/clockchips.h>
    > +
    > #include <linux/io.h>
    > #include <linux/i2c.h>
    > #include <linux/i2c-gpio.h>
    > @@ -100,55 +103,130 @@ void __init ep93xx_map_io(void)
    > * to use this timer for something else. We also use timer 4 for keeping
    > * track of lost jiffies.
    > */
    > -static unsigned int last_jiffy_time;
    > -
    > -#define TIMER4_TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ)
    >
    > static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
    > {
    > - __raw_writel(1, EP93XX_TIMER1_CLEAR);
    > - while ((signed long)
    > - (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time)
    > - >= TIMER4_TICKS_PER_JIFFY) {
    > - last_jiffy_time += TIMER4_TICKS_PER_JIFFY;
    > - timer_tick();
    > - }
    > -
    > + struct clock_event_device *evt = dev_id;
    > + __raw_writel(EP93XX_TC_CLEAR, EP93XX_TIMER1_CLEAR);
    > + evt->event_handler(evt);

    Here I get "error: dereferencing pointer to incomplete type"

    > return IRQ_HANDLED;
    > }
    >
    > +
    > +static int ep93xx_set_next_event(unsigned long evt,
    > + struct clock_event_device *unused)
    > +{
    > + u32 tmode = __raw_readl(EP93XX_TIMER1_CONTROL);
    > +
    > + /* stop timer */
    > + __raw_writel(tmode & ~EP93XX_TC123_ENABLE, EP93XX_TIMER1_CONTROL);
    > + /* program timer */
    > + __raw_writel(evt, EP93XX_TIMER1_LOAD);
    > + /* start timer */
    > + __raw_writel(tmode | EP93XX_TC123_ENABLE, EP93XX_TIMER1_CONTROL);
    > +
    > + return 0;
    > +}
    > +
    > +static void ep93xx_set_mode(enum clock_event_mode mode,
    > + struct clock_event_device *evt)
    > +{
    > + u32 tmode = EP93XX_TC123_SEL_508KHZ;
    > + /* Disable timer */
    > + __raw_writel(tmode, EP93XX_TIMER1_CONTROL);
    > +
    > + switch(mode) {
    > + case CLOCK_EVT_MODE_PERIODIC:
    > + /* Set timer period */
    > + __raw_writel((508469 / HZ) - 1, EP93XX_TIMER1_LOAD);
    > + tmode |= EP93XX_TC123_PERIODIC;
    > +
    > + case CLOCK_EVT_MODE_ONESHOT:
    > + tmode |= EP93XX_TC123_ENABLE;
    > + __raw_writel(tmode, EP93XX_TIMER1_CONTROL);
    > + break;
    > +
    > + case CLOCK_EVT_MODE_SHUTDOWN:
    > + case CLOCK_EVT_MODE_UNUSED:
    > + case CLOCK_EVT_MODE_RESUME:
    > + return;
    > + }
    > +}
    > +
    > +static struct clock_event_device clockevent_ep93xx = {
    > + .name = "ep93xx-timer1",
    > + .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
    > + .shift = 32,
    > + .set_mode = ep93xx_set_mode,
    > + .set_next_event = ep93xx_set_next_event,
    > +};
    > +
    > static struct irqaction ep93xx_timer_irq = {
    > .name = "ep93xx timer",
    > .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
    > .handler = ep93xx_timer_interrupt,
    > + .dev_id = &clockevent_ep93xx,
    > };
    >
    > -static void __init ep93xx_timer_init(void)
    > +static void __init ep93xx_clockevent_init(void)
    > {
    > - /* Enable periodic HZ timer. */
    > - __raw_writel(0x48, EP93XX_TIMER1_CONTROL);
    > - __raw_writel((508469 / HZ) - 1, EP93XX_TIMER1_LOAD);
    > - __raw_writel(0xc8, EP93XX_TIMER1_CONTROL);
    > + setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq);
    > + clockevent_ep93xx.mult = div_sc(508469, NSEC_PER_SEC,
    > + clockevent_ep93xx.shift);
    > + clockevent_ep93xx.max_delta_ns =
    > + clockevent_delta2ns(0xfffffffe, &clockevent_ep93xx);
    > + clockevent_ep93xx.min_delta_ns =
    > + clockevent_delta2ns(0xf, &clockevent_ep93xx);
    > + clockevent_ep93xx.cpumask = cpumask_of(0);
    > + clockevents_register_device(&clockevent_ep93xx);
    > +}
    >
    > - /* Enable lost jiffy timer. */
    > - __raw_writel(0x100, EP93XX_TIMER4_VALUE_HIGH);
    > +/*
    > + * timer4 is a 40 Bit timer, separated in a 32bit and a 8 bit
    > + * register, EP93XX_TIMER4_VALUE_LOW stores 32 bit word. The
    > + * controlregister is in EP93XX_TIMER4_VALUE_HIGH
    > + */
    >
    > - setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq);
    > +cycle_t ep93xx_get_cycles(void)
    > +{
    > + return __raw_readl(EP93XX_TIMER4_VALUE_LOW);
    > }
    >
    > -static unsigned long ep93xx_gettimeoffset(void)
    > +static struct clocksource clocksource_ep93xx = {
    > + .name = "ep93xx_timer4",
    > + .rating = 200,
    > + .read = ep93xx_get_cycles,

    Here I get "warning: initialization from incompatible pointer type"

    > + .mask = 0xFFFFFFFF,
    > + .shift = 20,
    > + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
    > +};
    > +
    > +/*
    > + * Returns current time from boot in nsecs. It's OK for this to wrap
    > + * around for now, as it's just a relative time stamp.
    > + */
    > +unsigned long long sched_clock(void)
    > {
    > - int offset;
    > + return cyc2ns(&clocksource_ep93xx, ep93xx_get_cycles());
    > +}
    >
    > - offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time;
    > +static void __init ep93xx_clocksource_init(void)
    > +{
    > + /* Reset time-stamp counter */
    > + __raw_writel(0x100, EP93XX_TIMER4_VALUE_HIGH);
    > + clocksource_ep93xx.mult =
    > + clocksource_hz2mult(983040, clocksource_ep93xx.shift);
    > + clocksource_register(&clocksource_ep93xx);
    > +}
    >
    > - /* Calculate (1000000 / 983040) * offset. */
    > - return offset + (53 * offset / 3072);
    > +static void __init ep93xx_timer_init(void)
    > +{
    > + ep93xx_clocksource_init();
    > + ep93xx_clockevent_init();
    > }
    >
    > struct sys_timer ep93xx_timer = {
    > - .init = ep93xx_timer_init,
    > - .offset = ep93xx_gettimeoffset,
    > + .init = ep93xx_timer_init,
    > };
    >
    >
    > diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
    > index 36c23fb..473cdec 100644
    > --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
    > +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
    > @@ -101,6 +101,12 @@
    > #define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88)
    > #define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c)
    >
    > +#define EP93XX_TC_CLEAR 0x00000001
    > +#define EP93XX_TC123_ENABLE 0x00000080
    > +#define EP93XX_TC123_PERIODIC 0x00000040
    > +#define EP93XX_TC123_SEL_508KHZ 0x00000008
    > +#define EP93XX_TC4_ENABLE 0x00000100
    > +
    > #define EP93XX_I2S_BASE (EP93XX_APB_VIRT_BASE + 0x00020000)
    >
    > #define EP93XX_SECURITY_BASE (EP93XX_APB_VIRT_BASE + 0x00030000)


    \
     
     \ /
      Last update: 2009-07-31 00:29    [W:0.036 / U:0.036 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site