From: Mark A. Greer <[email protected]> The davinci timer code currently hardcodes the timer register base addresses, the timer irq numbers, and the timers to use for clock events and clocksource. This won't work for some a new SoC so put those values into the davinci_soc_info infrastructure and set them up in the SoC-specific files.
Signed-off-by: Mark A. Greer <[email protected]> --- arch/arm/mach-davinci/devices.c | 15 ++++ arch/arm/mach-davinci/dm355.c | 15 ++++ arch/arm/mach-davinci/dm644x.c | 15 ++++ arch/arm/mach-davinci/dm646x.c | 15 ++++ arch/arm/mach-davinci/include/mach/common.h | 8 ++ arch/arm/mach-davinci/include/mach/time.h | 33 ++++++++++ arch/arm/mach-davinci/time.c | 93 ++++++++++++--------------- 7 files changed, 142 insertions(+), 52 deletions(-) create mode 100644 arch/arm/mach-davinci/include/mach/time.h diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index aff91e8..0ea0a84 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -29,6 +29,7 @@ #include <mach/cpu.h> #include <mach/mux.h> #include <mach/mmc.h> +#include <mach/time.h> #include <mach/dm646x.h> #include "clock.h" @@ -243,6 +244,20 @@ static void davinci_init_wdt(void) /*-------------------------------------------------------------------------*/ +u32 davinci_timer_bases[] = { + DAVINCI_TIMER0_BASE, + DAVINCI_TIMER1_BASE +}; + +u32 davinci_timer_irqs[NUM_TIMERS] = { + IRQ_TINT0_TINT12, + IRQ_TINT0_TINT34, + IRQ_TINT1_TINT12, + IRQ_TINT1_TINT34, +}; + +/*-------------------------------------------------------------------------*/ + #if defined(CONFIG_TI_DAVINCI_EMAC) || defined(CONFIG_TI_DAVINCI_EMAC_MODULE) void davinci_init_emac(struct emac_platform_data *pdata) diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 697893e..837570b 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -25,6 +25,7 @@ #include <mach/psc.h> #include <mach/mux.h> #include <mach/irqs.h> +#include <mach/time.h> #include <mach/common.h> #include "clock.h" @@ -616,6 +617,19 @@ static void __iomem *dm355_psc_bases[] = { IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE), }; +/* + * T0_BOT: Timer 0, bottom: clockevent source for hrtimers + * T0_TOP: Timer 0, top : clocksource for generic timekeeping + * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code) + * T1_TOP: Timer 1, top : <unused> + */ +struct davinci_timer_info dm355_timer_info = { + .timer_bases = davinci_timer_bases, + .timer_irqs = davinci_timer_irqs, + .clockevent_id = T0_BOT, + .clocksource_id = T0_TOP, +}; + static struct davinci_soc_info davinci_soc_info_dm355 = { .io_desc = dm355_io_desc, .io_desc_num = ARRAY_SIZE(dm355_io_desc), @@ -634,6 +648,7 @@ static struct davinci_soc_info davinci_soc_info_dm355 = { .intc_priorities = dm355_default_priorities, .intc_type = DAVINCI_INTC_TYPE_AINTC, .intc_num = DAVINCI_N_AINTC_IRQ, + .timer_info = &dm355_timer_info, }; struct davinci_soc_info *dm355_get_soc_info(void) diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index a82f095..5d63d46 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -22,6 +22,7 @@ #include <mach/irqs.h> #include <mach/psc.h> #include <mach/mux.h> +#include <mach/time.h> #include <mach/common.h> #include "clock.h" @@ -559,6 +560,19 @@ static void __iomem *dm644x_psc_bases[] = { IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE), }; +/* + * T0_BOT: Timer 0, bottom: clockevent source for hrtimers + * T0_TOP: Timer 0, top : clocksource for generic timekeeping + * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code) + * T1_TOP: Timer 1, top : <unused> + */ +struct davinci_timer_info dm644x_timer_info = { + .timer_bases = davinci_timer_bases, + .timer_irqs = davinci_timer_irqs, + .clockevent_id = T0_BOT, + .clocksource_id = T0_TOP, +}; + static struct davinci_soc_info davinci_soc_info_dm644x = { .io_desc = dm644x_io_desc, .io_desc_num = ARRAY_SIZE(dm644x_io_desc), @@ -577,6 +591,7 @@ static struct davinci_soc_info davinci_soc_info_dm644x = { .intc_priorities = dm644x_default_priorities, .intc_type = DAVINCI_INTC_TYPE_AINTC, .intc_num = DAVINCI_N_AINTC_IRQ, + .timer_info = &dm644x_timer_info, }; struct davinci_soc_info *dm644x_get_soc_info(void) diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 9c60971..96ae370 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -22,6 +22,7 @@ #include <mach/irqs.h> #include <mach/psc.h> #include <mach/mux.h> +#include <mach/time.h> #include <mach/common.h> #include "clock.h" @@ -538,6 +539,19 @@ static void __iomem *dm646x_psc_bases[] = { IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE), }; +/* + * T0_BOT: Timer 0, bottom: clockevent source for hrtimers + * T0_TOP: Timer 0, top : clocksource for generic timekeeping + * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code) + * T1_TOP: Timer 1, top : <unused> + */ +struct davinci_timer_info dm646x_timer_info = { + .timer_bases = davinci_timer_bases, + .timer_irqs = davinci_timer_irqs, + .clockevent_id = T0_BOT, + .clocksource_id = T0_TOP, +}; + static struct davinci_soc_info davinci_soc_info_dm646x = { .io_desc = dm646x_io_desc, .io_desc_num = ARRAY_SIZE(dm646x_io_desc), @@ -556,6 +570,7 @@ static struct davinci_soc_info davinci_soc_info_dm646x = { .intc_priorities = dm646x_default_priorities, .intc_type = DAVINCI_INTC_TYPE_AINTC, .intc_num = DAVINCI_N_AINTC_IRQ, + .timer_info = &dm646x_timer_info, }; struct davinci_soc_info *dm646x_get_soc_info(void) diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index b69a74f..664655b 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -25,6 +25,13 @@ extern void setup_usb(unsigned mA, unsigned potpgt_msec); /* parameters describe VBUS sourcing for host mode */ extern void setup_usb(unsigned mA, unsigned potpgt_msec); +struct davinci_timer_info { + u32 *timer_bases; + u32 *timer_irqs; + unsigned int clockevent_id; + unsigned int clocksource_id; +}; + /* SoC specific init support */ struct davinci_soc_info { struct map_desc *io_desc; @@ -46,6 +53,7 @@ struct davinci_soc_info { u8 *intc_priorities; int intc_type; unsigned long intc_num; + struct davinci_timer_info *timer_info; }; extern struct davinci_soc_info *davinci_soc_info; diff --git a/arch/arm/mach-davinci/include/mach/time.h b/arch/arm/mach-davinci/include/mach/time.h new file mode 100644 index 0000000..260d276 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/time.h @@ -0,0 +1,33 @@ +/* + * Local header file for DaVinci time code. + * + * Author: Kevin Hilman, MontaVista Software, Inc. <[email protected]> + * + * 2007 (c) MontaVista Software, Inc. 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. + */ +#ifndef __ARCH_ARM_MACH_DAVINCI_TIME_H +#define __ARCH_ARM_MACH_DAVINCI_TIME_H + +#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400) +#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800) + +enum { + T0_BOT, + T0_TOP, + T1_BOT, + T1_TOP, + NUM_TIMERS +}; + +#define IS_TIMER1(id) (id & 0x2) +#define IS_TIMER0(id) (!IS_TIMER1(id)) +#define IS_TIMER_TOP(id) ((id & 0x1)) +#define IS_TIMER_BOT(id) (!IS_TIMER_TOP(id)) + +extern u32 davinci_timer_bases[]; +extern u32 davinci_timer_irqs[]; + +#endif /* __ARCH_ARM_MACH_DAVINCI_TIME_H */ diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index a9992d6..ab456e5 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -28,42 +28,23 @@ #include <asm/errno.h> #include <mach/io.h> #include <mach/cpu.h> +#include <mach/time.h> #include "clock.h" static struct clock_event_device clockevent_davinci; static unsigned int davinci_clock_tick_rate; -#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400) -#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800) #define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00) -enum { - T0_BOT = 0, T0_TOP, T1_BOT, T1_TOP, NUM_TIMERS, -}; - -#define IS_TIMER1(id) (id & 0x2) -#define IS_TIMER0(id) (!IS_TIMER1(id)) -#define IS_TIMER_TOP(id) ((id & 0x1)) -#define IS_TIMER_BOT(id) (!IS_TIMER_TOP(id)) - -static int timer_irqs[NUM_TIMERS] = { - IRQ_TINT0_TINT12, - IRQ_TINT0_TINT34, - IRQ_TINT1_TINT12, - IRQ_TINT1_TINT34, -}; - /* * This driver configures the 2 64-bit count-up timers as 4 independent * 32-bit count-up timers used as follows: - * - * T0_BOT: Timer 0, bottom: clockevent source for hrtimers - * T0_TOP: Timer 0, top : clocksource for generic timekeeping - * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code) - * T1_TOP: Timer 1, top : <unused> */ -#define TID_CLOCKEVENT T0_BOT -#define TID_CLOCKSOURCE T0_TOP + +enum { + TID_CLOCKEVENT, + TID_CLOCKSOURCE, +}; /* Timer register offsets */ #define PID12 0x0 @@ -118,6 +99,13 @@ static struct timer_s timers[]; #define TIMER_OPTS_ONESHOT 0x01 #define TIMER_OPTS_PERIODIC 0x02 +static char *id_to_name[] = { + [T0_BOT] = "timer0_0", + [T0_TOP] = "timer0_1", + [T1_BOT] = "timer1_0", + [T1_TOP] = "timer1_1", +}; + static int timer32_config(struct timer_s *t) { u32 tcr = __raw_readl(t->base + TCR); @@ -182,7 +170,7 @@ static struct timer_s timers[] = { static void __init timer_init(void) { - u32 phys_bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE}; + u32 *phys_bases = davinci_soc_info->timer_info->timer_bases; int i; /* Global init of each 64-bit timer as a whole */ @@ -216,31 +204,27 @@ static void __init timer_init(void) struct timer_s *t = &timers[i]; u32 phys_base; - if (t->name) { - t->id = i; - phys_base = (IS_TIMER1(t->id) ? - DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE); - t->base = IO_ADDRESS(phys_base); - - if (IS_TIMER_BOT(t->id)) { - t->enamode_shift = 6; - t->tim_off = TIM12; - t->prd_off = PRD12; - } else { - t->enamode_shift = 22; - t->tim_off = TIM34; - t->prd_off = PRD34; - } - - /* Register interrupt */ - t->irqaction.name = t->name; - t->irqaction.dev_id = (void *)t; - if (t->irqaction.handler != NULL) { - setup_irq(timer_irqs[t->id], &t->irqaction); - } - - timer32_config(&timers[i]); + phys_base = (IS_TIMER1(t->id) ? phys_bases[1] : phys_bases[0]); + t->base = IO_ADDRESS(phys_base); + + if (IS_TIMER_BOT(t->id)) { + t->enamode_shift = 6; + t->tim_off = TIM12; + t->prd_off = PRD12; + } else { + t->enamode_shift = 22; + t->tim_off = TIM34; + t->prd_off = PRD34; } + + /* Register interrupt */ + t->irqaction.name = t->name; + t->irqaction.dev_id = (void *)t; + if (t->irqaction.handler != NULL) + setup_irq(davinci_soc_info->timer_info-> + timer_irqs[t->id], &t->irqaction); + + timer32_config(&timers[i]); } } @@ -255,7 +239,6 @@ static cycle_t read_cycles(void) } static struct clocksource clocksource_davinci = { - .name = "timer0_1", .rating = 300, .read = read_cycles, .mask = CLOCKSOURCE_MASK(32), @@ -300,7 +283,6 @@ static void davinci_set_mode(enum clock_event_mode mode, } static struct clock_event_device clockevent_davinci = { - .name = "timer0_0", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .shift = 32, .set_next_event = davinci_set_next_event, @@ -315,6 +297,11 @@ static void __init davinci_timer_init(void) static char err[] __initdata = KERN_ERR "%s: can't register clocksource!\n"; + timers[TID_CLOCKEVENT].id = + davinci_soc_info->timer_info->clockevent_id; + timers[TID_CLOCKSOURCE].id = + davinci_soc_info->timer_info->clocksource_id; + /* init timer hw */ timer_init(); @@ -326,6 +313,7 @@ static void __init davinci_timer_init(void) clk_put(timer_clk); /* setup clocksource */ + clocksource_davinci.name = id_to_name[timers[TID_CLOCKSOURCE].id]; clocksource_davinci.mult = clocksource_khz2mult(davinci_clock_tick_rate/1000, clocksource_davinci.shift); @@ -333,6 +321,7 @@ static void __init davinci_timer_init(void) printk(err, clocksource_davinci.name); /* setup clockevent */ + clockevent_davinci.name = id_to_name[timers[TID_CLOCKEVENT].id]; clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC, clockevent_davinci.shift); clockevent_davinci.max_delta_ns = -- 1.6.0.3 _______________________________________________ Davinci-linux-open-source mailing list [email protected] http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
