diff options
author | Quinn Jensen <quinn.jensen@freescale.com> | 2007-10-24 21:25:45 -0600 |
---|---|---|
committer | Quinn Jensen <quinn.jensen@freescale.com> | 2007-10-24 21:25:45 -0600 |
commit | 911eb62722a75d3e133c54aaa02d0700f5f924db (patch) | |
tree | 62e3b2e6de7ac2680bbb5e2bbd230d261309428b /arch | |
parent | 8434b44ae8dfeaba99136bd8b4c3d500f622bac6 (diff) |
CR ENGR00048068 mxc add clocksource and clockevent support (update)
Patch for CR ENGR00048068: Add mxc clocksource and clockevent support
(update). This patch adds clocksource and clockevent support to the
GPT. This enables GENERIC_TIME and GENERIC_CLOCKEVENT support. Dynamic
tick support is also enabled.
http://www.bitshrine.org/gpp/linux-2.6.22-mx-CR-ENGR00048068-mxc-add-clocksource-and-cl.patch
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-mx27/time.c | 100 | ||||
-rw-r--r-- | arch/arm/plat-mxc/time.c | 173 |
2 files changed, 120 insertions, 153 deletions
diff --git a/arch/arm/mach-mx27/time.c b/arch/arm/mach-mx27/time.c index 97c56e18ec64..30d8dbcb192c 100644 --- a/arch/arm/mach-mx27/time.c +++ b/arch/arm/mach-mx27/time.c @@ -17,15 +17,16 @@ */ /*! - * @defgroup Timers OS Tick Timer + * @defgroup Timers_MX27 OS Tick Timer + * @ingroup MSL_MX27 */ /*! - * @file plat-mxc/time.c + * @file mach-mx27/time.c * @brief This file contains OS tick timer implementation. * * This file contains OS tick timer implementation. * - * @ingroup Timers + * @ingroup Timers_MX27 */ #include <linux/module.h> @@ -35,40 +36,46 @@ #include <linux/io.h> #include <linux/clocksource.h> #include <linux/clockchips.h> +#include <asm/hardware.h> #include <asm/mach/time.h> -/* - ***************************************** - * GPT Register definitions * - ***************************************** +/*! + * GPT register address definitions */ -#define GPT_BASE_ADDR(x) (GPT ##x## _BASE_ADDR) -#define MXC_GPT_GPTCR (IO_ADDRESS(GPT_BASE_ADDR(1) + 0x00)) -#define MXC_GPT_GPTPR (IO_ADDRESS(GPT_BASE_ADDR(1) + 0x04)) -#define MXC_GPT_GPTOCR1 (IO_ADDRESS(GPT_BASE_ADDR(1) + 0x08)) -#define MXC_GPT_GPTICR1 (IO_ADDRESS(GPT_BASE_ADDR(1) + 0x0C)) -#define MXC_GPT_GPTCNT (IO_ADDRESS(GPT_BASE_ADDR(1) + 0x10)) -#define MXC_GPT_GPTSR (IO_ADDRESS(GPT_BASE_ADDR(1) + 0x14)) - -#define GPTCR_CLKSRC_HIGHFREQ (1 << 1) -#define GPTCR_CLKSRC_CLK32K (4 << 1) +#define GPT_BASE_ADDR (IO_ADDRESS(GPT1_BASE_ADDR)) +#define MXC_GPT_GPTCR (GPT_BASE_ADDR + 0x00) +#define MXC_GPT_GPTPR (GPT_BASE_ADDR + 0x04) +#define MXC_GPT_GPTOCR1 (GPT_BASE_ADDR + 0x08) +#define MXC_GPT_GPTICR1 (GPT_BASE_ADDR + 0x0C) +#define MXC_GPT_GPTCNT (GPT_BASE_ADDR + 0x10) +#define MXC_GPT_GPTSR (GPT_BASE_ADDR + 0x14) +/*! + * GPT Control register bit definitions + */ #define GPTCR_COMPEN (1 << 4) -#define GPTCR_SWR (1<<15) -#define GPTCR_FRR (1<<8) -#define GPTCR_ENABLE (1<<0) +#define GPTCR_SWR (1 << 15) +#define GPTCR_FRR (1 << 8) + +#define GPTCR_CLKSRC_SHIFT 1 +#define GPTCR_CLKSRC_MASK (7 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_NOCLOCK (0 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_HIGHFREQ (1 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_CLKIN (3 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_CLK32K (4 << GPTCR_CLKSRC_SHIFT) -#define GPTSR_OF1 (1<<0) +#define GPTCR_ENABLE (1 << 0) +#define GPTSR_OF1 (1 << 0) extern unsigned long clk_early_get_timer_rate(void); static int mxc_gpt_set_next_event(unsigned long cycles, - struct clock_event_device *evt) + struct clock_event_device *evt) { unsigned long now, expires; u32 reg; - + now = __raw_readl(MXC_GPT_GPTCNT); expires = now + cycles; __raw_writel(expires, MXC_GPT_GPTOCR1); @@ -78,12 +85,12 @@ static int mxc_gpt_set_next_event(unsigned long cycles, reg = __raw_readl(MXC_GPT_GPTCR); reg |= GPTCR_COMPEN; __raw_writel(reg, MXC_GPT_GPTCR); - + return 0; } static void mxc_gpt_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) + struct clock_event_device *evt) { u32 reg; switch (mode) { @@ -103,12 +110,12 @@ static void mxc_gpt_set_mode(enum clock_event_mode mode, } static struct clock_event_device gpt_clockevent = { - .name = "mxc_gpt", - .features = CLOCK_EVT_FEAT_ONESHOT, - .rating = 300, - .shift = 32, - .set_next_event = mxc_gpt_set_next_event, - .set_mode = mxc_gpt_set_mode, + .name = "mxc_gpt", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, + .shift = 32, + .set_next_event = mxc_gpt_set_next_event, + .set_mode = mxc_gpt_set_mode, }; /*! @@ -160,13 +167,12 @@ static cycle_t mxc_gpt_read(void) } static struct clocksource gpt_clocksrc = { - .name = "mxc_gpt", - .rating = 300, - .read = mxc_gpt_read, - .mask = CLOCKSOURCE_MASK(32), - .shift = 24, - .flags = CLOCK_SOURCE_IS_CONTINUOUS | - CLOCK_SOURCE_VALID_FOR_HRES, + .name = "mxc_gpt", + .rating = 300, + .read = mxc_gpt_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 24, + .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_VALID_FOR_HRES, }; /*! @@ -188,18 +194,17 @@ void __init mxc_init_time(void) rate = clk_early_get_timer_rate(); if (rate == 0) panic("MXC GPT: Can't get timer clock rate\n"); - + #ifdef CLOCK_TICK_RATE div = rate / CLOCK_TICK_RATE; WARN_ON((div * CLOCK_TICK_RATE) != rate); - rate /= div; -#else /* Hopefully CLOCK_TICK_RATE will go away soon */ +#else /* Hopefully CLOCK_TICK_RATE will go away soon */ div = 1; - while (rate > 20000000) { + while ((rate / div) > 20000000) { div++; - rate /= div; } #endif + rate /= div; __raw_writel(div - 1, MXC_GPT_GPTPR); reg = GPTCR_FRR | GPTCR_CLKSRC_HIGHFREQ | GPTCR_ENABLE; @@ -212,10 +217,8 @@ void __init mxc_init_time(void) } gpt_clockevent.mult = div_sc(rate, NSEC_PER_SEC, gpt_clockevent.shift); - gpt_clockevent.max_delta_ns = - clockevent_delta2ns(-1, &gpt_clockevent); - gpt_clockevent.min_delta_ns = - clockevent_delta2ns(1, &gpt_clockevent); + gpt_clockevent.max_delta_ns = clockevent_delta2ns(-1, &gpt_clockevent); + gpt_clockevent.min_delta_ns = clockevent_delta2ns(1, &gpt_clockevent); gpt_clockevent.cpumask = cpumask_of_cpu(0); clockevents_register_device(&gpt_clockevent); @@ -227,11 +230,10 @@ void __init mxc_init_time(void) pr_info("MXC GPT timer initialized, rate = %lu\n", rate); return; -err: + err: panic("Unable to initialize timer\n"); } struct sys_timer mxc_timer = { .init = mxc_init_time, }; - diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index 5ba34425604e..4dd10c3f4c7e 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c @@ -35,88 +35,54 @@ #include <linux/io.h> #include <linux/clocksource.h> #include <linux/clockchips.h> +#include <asm/hardware.h> #include <asm/mach/time.h> -#define MXC_GPT_GPTCR (IO_ADDRESS(GPT1_BASE_ADDR + 0x00)) -#define MXC_GPT_GPTPR (IO_ADDRESS(GPT1_BASE_ADDR + 0x04)) -#define MXC_GPT_GPTSR (IO_ADDRESS(GPT1_BASE_ADDR + 0x08)) -#define MXC_GPT_GPTIR (IO_ADDRESS(GPT1_BASE_ADDR + 0x0C)) -#define MXC_GPT_GPTOCR1 (IO_ADDRESS(GPT1_BASE_ADDR + 0x10)) -#define MXC_GPT_GPTOCR2 (IO_ADDRESS(GPT1_BASE_ADDR + 0x14)) -#define MXC_GPT_GPTOCR3 (IO_ADDRESS(GPT1_BASE_ADDR + 0x18)) -#define MXC_GPT_GPTICR1 (IO_ADDRESS(GPT1_BASE_ADDR + 0x1C)) -#define MXC_GPT_GPTICR2 (IO_ADDRESS(GPT1_BASE_ADDR + 0x20)) -#define MXC_GPT_GPTCNT (IO_ADDRESS(GPT1_BASE_ADDR + 0x24)) +/*! + * GPT register address definitions + */ +#define GPT_BASE_ADDR (IO_ADDRESS(GPT1_BASE_ADDR)) +#define MXC_GPT_GPTCR (GPT_BASE_ADDR + 0x00) +#define MXC_GPT_GPTPR (GPT_BASE_ADDR + 0x04) +#define MXC_GPT_GPTSR (GPT_BASE_ADDR + 0x08) +#define MXC_GPT_GPTIR (GPT_BASE_ADDR + 0x0C) +#define MXC_GPT_GPTOCR1 (GPT_BASE_ADDR + 0x10) +#define MXC_GPT_GPTOCR2 (GPT_BASE_ADDR + 0x14) +#define MXC_GPT_GPTOCR3 (GPT_BASE_ADDR + 0x18) +#define MXC_GPT_GPTICR1 (GPT_BASE_ADDR + 0x1C) +#define MXC_GPT_GPTICR2 (GPT_BASE_ADDR + 0x20) +#define MXC_GPT_GPTCNT (GPT_BASE_ADDR + 0x24) /*! * GPT Control register bit definitions */ -#define GPTCR_FO3 (1<<31) -#define GPTCR_FO2 (1<<30) -#define GPTCR_FO1 (1<<29) - -#define GPTCR_OM3_SHIFT 26 -#define GPTCR_OM3_MASK (7<<GPTCR_OM3_SHIFT) -#define GPTCR_OM3_DISCONNECTED (0<<GPTCR_OM3_SHIFT) -#define GPTCR_OM3_TOGGLE (1<<GPTCR_OM3_SHIFT) -#define GPTCR_OM3_CLEAR (2<<GPTCR_OM3_SHIFT) -#define GPTCR_OM3_SET (3<<GPTCR_OM3_SHIFT) -#define GPTCR_OM3_GENERATE_LOW (7<<GPTCR_OM3_SHIFT) - -#define GPTCR_OM2_SHIFT 23 -#define GPTCR_OM2_MASK (7<<GPTCR_OM2_SHIFT) -#define GPTCR_OM2_DISCONNECTED (0<<GPTCR_OM2_SHIFT) -#define GPTCR_OM2_TOGGLE (1<<GPTCR_OM2_SHIFT) -#define GPTCR_OM2_CLEAR (2<<GPTCR_OM2_SHIFT) -#define GPTCR_OM2_SET (3<<GPTCR_OM2_SHIFT) -#define GPTCR_OM2_GENERATE_LOW (7<<GPTCR_OM2_SHIFT) - -#define GPTCR_OM1_SHIFT 20 -#define GPTCR_OM1_MASK (7<<GPTCR_OM1_SHIFT) -#define GPTCR_OM1_DISCONNECTED (0<<GPTCR_OM1_SHIFT) -#define GPTCR_OM1_TOGGLE (1<<GPTCR_OM1_SHIFT) -#define GPTCR_OM1_CLEAR (2<<GPTCR_OM1_SHIFT) -#define GPTCR_OM1_SET (3<<GPTCR_OM1_SHIFT) -#define GPTCR_OM1_GENERATE_LOW (7<<GPTCR_OM1_SHIFT) - -#define GPTCR_IM2_SHIFT 18 -#define GPTCR_IM2_MASK (3<<GPTCR_IM2_SHIFT) -#define GPTCR_IM2_CAPTURE_DISABLE (0<<GPTCR_IM2_SHIFT) -#define GPTCR_IM2_CAPTURE_RISING (1<<GPTCR_IM2_SHIFT) -#define GPTCR_IM2_CAPTURE_FALLING (2<<GPTCR_IM2_SHIFT) -#define GPTCR_IM2_CAPTURE_BOTH (3<<GPTCR_IM2_SHIFT) - -#define GPTCR_IM1_SHIFT 16 -#define GPTCR_IM1_MASK (3<<GPTCR_IM1_SHIFT) -#define GPTCR_IM1_CAPTURE_DISABLE (0<<GPTCR_IM1_SHIFT) -#define GPTCR_IM1_CAPTURE_RISING (1<<GPTCR_IM1_SHIFT) -#define GPTCR_IM1_CAPTURE_FALLING (2<<GPTCR_IM1_SHIFT) -#define GPTCR_IM1_CAPTURE_BOTH (3<<GPTCR_IM1_SHIFT) - -#define GPTCR_SWR (1<<15) -#define GPTCR_FRR (1<<9) +#define GPTCR_FO3 (1 << 31) +#define GPTCR_FO2 (1 << 30) +#define GPTCR_FO1 (1 << 29) + +#define GPTCR_SWR (1 << 15) +#define GPTCR_FRR (1 << 9) #define GPTCR_CLKSRC_SHIFT 6 -#define GPTCR_CLKSRC_MASK (7<<GPTCR_CLKSRC_SHIFT) -#define GPTCR_CLKSRC_NOCLOCK (0<<GPTCR_CLKSRC_SHIFT) -#define GPTCR_CLKSRC_HIGHFREQ (2<<GPTCR_CLKSRC_SHIFT) -#define GPTCR_CLKSRC_CLKIN (3<<GPTCR_CLKSRC_SHIFT) -#define GPTCR_CLKSRC_CLK32K (7<<GPTCR_CLKSRC_SHIFT) - -#define GPTCR_STOPEN (1<<5) -#define GPTCR_DOZEN (1<<4) -#define GPTCR_WAITEN (1<<3) -#define GPTCR_DBGEN (1<<2) - -#define GPTCR_ENMOD (1<<1) -#define GPTCR_ENABLE (1<<0) - -#define GPTSR_OF1 (1<<0) -#define GPTSR_OF2 (1<<1) -#define GPTSR_OF3 (1<<2) -#define GPTSR_IF1 (1<<3) -#define GPTSR_IF2 (1<<4) -#define GPTSR_ROV (1<<5) +#define GPTCR_CLKSRC_MASK (7 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_NOCLOCK (0 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_HIGHFREQ (2 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_CLKIN (3 << GPTCR_CLKSRC_SHIFT) +#define GPTCR_CLKSRC_CLK32K (4 << GPTCR_CLKSRC_SHIFT) + +#define GPTCR_STOPEN (1 << 5) +#define GPTCR_DOZEN (1 << 4) +#define GPTCR_WAITEN (1 << 3) +#define GPTCR_DBGEN (1 << 2) +#define GPTCR_ENMOD (1 << 1) +#define GPTCR_ENABLE (1 << 0) + +#define GPTSR_OF1 (1 << 0) +#define GPTSR_OF2 (1 << 1) +#define GPTSR_OF3 (1 << 2) +#define GPTSR_IF1 (1 << 3) +#define GPTSR_IF2 (1 << 4) +#define GPTSR_ROV (1 << 5) #define GPTIR_OF1IE GPTSR_OF1 #define GPTIR_OF2IE GPTSR_OF2 @@ -128,11 +94,11 @@ extern unsigned long clk_early_get_timer_rate(void); static int mxc_gpt_set_next_event(unsigned long cycles, - struct clock_event_device *evt) + struct clock_event_device *evt) { unsigned long now, expires; u32 reg; - + now = __raw_readl(MXC_GPT_GPTCNT); expires = now + cycles; __raw_writel(expires, MXC_GPT_GPTOCR1); @@ -142,13 +108,15 @@ static int mxc_gpt_set_next_event(unsigned long cycles, reg = __raw_readl(MXC_GPT_GPTIR); reg |= GPTIR_OF1IE; __raw_writel(reg, MXC_GPT_GPTIR); - + return 0; } static void mxc_gpt_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) + struct clock_event_device *evt) { + u32 reg; + switch (mode) { case CLOCK_EVT_MODE_PERIODIC: panic("MXC GPT: CLOCK_EVT_MODE_PERIODIC not supported\n"); @@ -158,18 +126,20 @@ static void mxc_gpt_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: /* Disable interrupts */ - __raw_writel(0, MXC_GPT_GPTIR); + reg = __raw_readl(MXC_GPT_GPTIR); + reg &= ~GPTIR_OF1IE; + __raw_writel(reg, MXC_GPT_GPTIR); break; } } static struct clock_event_device gpt_clockevent = { - .name = "mxc_gpt", - .features = CLOCK_EVT_FEAT_ONESHOT, - .rating = 300, - .shift = 32, - .set_next_event = mxc_gpt_set_next_event, - .set_mode = mxc_gpt_set_mode, + .name = "mxc_gpt", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, + .shift = 32, + .set_next_event = mxc_gpt_set_next_event, + .set_mode = mxc_gpt_set_mode, }; /*! @@ -189,7 +159,7 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id) unsigned int gptsr; u32 reg; - gptsr = __raw_readl(MXC_GPT_GPTSR) & __raw_readl(MXC_GPT_GPTIR); + gptsr = __raw_readl(MXC_GPT_GPTSR); if (gptsr & GPTSR_OF1) { /* Disable interrupt */ reg = __raw_readl(MXC_GPT_GPTIR); @@ -221,13 +191,12 @@ static cycle_t mxc_gpt_read(void) } static struct clocksource gpt_clocksrc = { - .name = "mxc_gpt", - .rating = 300, - .read = mxc_gpt_read, - .mask = CLOCKSOURCE_MASK(32), - .shift = 24, - .flags = CLOCK_SOURCE_IS_CONTINUOUS | - CLOCK_SOURCE_VALID_FOR_HRES, + .name = "mxc_gpt", + .rating = 300, + .read = mxc_gpt_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 24, + .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_VALID_FOR_HRES, }; /*! @@ -249,18 +218,17 @@ void __init mxc_init_time(void) rate = clk_early_get_timer_rate(); if (rate == 0) panic("MXC GPT: Can't get timer clock rate\n"); - + #ifdef CLOCK_TICK_RATE div = rate / CLOCK_TICK_RATE; WARN_ON((div * CLOCK_TICK_RATE) != rate); - rate /= div; -#else /* Hopefully CLOCK_TICK_RATE will go away soon */ +#else /* Hopefully CLOCK_TICK_RATE will go away soon */ div = 1; - while (rate > 20000000) { + while ((rate / div) > 20000000) { div++; - rate /= div; } #endif + rate /= div; __raw_writel(div - 1, MXC_GPT_GPTPR); reg = GPTCR_FRR | GPTCR_CLKSRC_HIGHFREQ | GPTCR_STOPEN | @@ -274,10 +242,8 @@ void __init mxc_init_time(void) } gpt_clockevent.mult = div_sc(rate, NSEC_PER_SEC, gpt_clockevent.shift); - gpt_clockevent.max_delta_ns = - clockevent_delta2ns(-1, &gpt_clockevent); - gpt_clockevent.min_delta_ns = - clockevent_delta2ns(1, &gpt_clockevent); + gpt_clockevent.max_delta_ns = clockevent_delta2ns(-1, &gpt_clockevent); + gpt_clockevent.min_delta_ns = clockevent_delta2ns(1, &gpt_clockevent); gpt_clockevent.cpumask = cpumask_of_cpu(0); clockevents_register_device(&gpt_clockevent); @@ -289,11 +255,10 @@ void __init mxc_init_time(void) pr_info("MXC GPT timer initialized, rate = %lu\n", rate); return; -err: + err: panic("Unable to initialize timer\n"); } struct sys_timer mxc_timer = { .init = mxc_init_time, }; - |