From 25084d72bf7fdf13acf80b3f864bca84254fce93 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 26 Apr 2007 08:26:13 +0100 Subject: [PATCH] --- yaml --- r: 53999 b: refs/heads/master c: ff4bfb2163e8914332267be3758eb28239460316 h: refs/heads/master i: 53997: a84daf355c23f8e32ad80517e157a41efe8791b8 53995: 777531e44dfce9e33b4acf3eefc9a7c220b4d61f 53991: 969a7ec97bd4329ed80602f800b6044f5b20379f 53983: e764f208b59331927c55d1c43c352421c6360f6d v: v3 --- [refs] | 2 +- trunk/arch/arm/Kconfig | 12 - trunk/arch/arm/kernel/process.c | 3 - trunk/arch/arm/kernel/time.c | 4 +- trunk/arch/arm/mach-ixp4xx/common.c | 93 ++------ trunk/arch/arm/mach-omap1/time.c | 206 ++++++----------- trunk/arch/arm/mach-versatile/core.c | 129 ++++------- trunk/arch/arm/plat-omap/Kconfig | 1 - trunk/arch/arm/plat-omap/common.c | 50 ---- trunk/arch/arm/plat-omap/timer32k.c | 139 +++++++---- trunk/drivers/serial/imx.c | 268 +++++++++++++++++----- trunk/include/asm-arm/arch-imx/imx-regs.h | 118 ---------- 12 files changed, 443 insertions(+), 582 deletions(-) diff --git a/[refs] b/[refs] index f80439aa6fed..6bc655ebf0aa 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 075192ae807579448afcc0833bd349ccce057825 +refs/heads/master: ff4bfb2163e8914332267be3758eb28239460316 diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index 3116bafc7533..e7baca29f3fb 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -29,10 +29,6 @@ config GENERIC_TIME bool default n -config GENERIC_CLOCKEVENTS - bool - default n - config MMU bool default y @@ -166,8 +162,6 @@ config ARCH_VERSATILE select ARM_AMBA select ARM_VIC select ICST307 - select GENERIC_TIME - select GENERIC_CLOCKEVENTS help This enables support for ARM Ltd Versatile board. @@ -268,7 +262,6 @@ config ARCH_IXP4XX bool "IXP4xx-based" depends on MMU select GENERIC_TIME - select GENERIC_CLOCKEVENTS help Support for Intel's IXP4XX (XScale) family of processors. @@ -370,7 +363,6 @@ config ARCH_LH7A40X config ARCH_OMAP bool "TI OMAP" select GENERIC_GPIO - select GENERIC_TIME help Support for TI's OMAP platform (OMAP1 and OMAP2). @@ -521,8 +513,6 @@ endmenu menu "Kernel Features" -source "kernel/time/Kconfig" - config SMP bool "Symmetric Multi-Processing (EXPERIMENTAL)" depends on EXPERIMENTAL && REALVIEW_MPCORE @@ -582,7 +572,6 @@ config PREEMPT config NO_IDLE_HZ bool "Dynamic tick timer" - depends on !GENERIC_CLOCKEVENTS help Select this option if you want to disable continuous timer ticks and have them programmed to occur as required. This option saves @@ -680,7 +669,6 @@ config LEDS_TIMER bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \ MACH_OMAP_H2 || MACH_OMAP_PERSEUS2 depends on LEDS - depends on !GENERIC_CLOCKEVENTS default y if ARCH_EBSA110 help If you say Y here, one of the system LEDs (the green one on the diff --git a/trunk/arch/arm/kernel/process.c b/trunk/arch/arm/kernel/process.c index 5d6e6523598b..8afd83d0cbdd 100644 --- a/trunk/arch/arm/kernel/process.c +++ b/trunk/arch/arm/kernel/process.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -160,11 +159,9 @@ void cpu_idle(void) if (!idle) idle = default_idle; leds_event(led_idle_start); - tick_nohz_stop_sched_tick(); while (!need_resched()) idle(); leds_event(led_idle_end); - tick_nohz_restart_sched_tick(); preempt_enable_no_resched(); schedule(); preempt_disable(); diff --git a/trunk/arch/arm/kernel/time.c b/trunk/arch/arm/kernel/time.c index d0540e4eaf5b..f61decb89ba2 100644 --- a/trunk/arch/arm/kernel/time.c +++ b/trunk/arch/arm/kernel/time.c @@ -327,7 +327,6 @@ void restore_time_delta(struct timespec *delta, struct timespec *rtc) } EXPORT_SYMBOL(restore_time_delta); -#ifndef CONFIG_GENERIC_CLOCKEVENTS /* * Kernel system timer support. */ @@ -341,9 +340,8 @@ void timer_tick(void) update_process_times(user_mode(get_irq_regs())); #endif } -#endif -#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS) +#ifdef CONFIG_PM static int timer_suspend(struct sys_device *dev, pm_message_t state) { struct sys_timer *timer = container_of(dev, struct sys_timer, dev); diff --git a/trunk/arch/arm/mach-ixp4xx/common.c b/trunk/arch/arm/mach-ixp4xx/common.c index 09edea9779e6..45068c3d8dcc 100644 --- a/trunk/arch/arm/mach-ixp4xx/common.c +++ b/trunk/arch/arm/mach-ixp4xx/common.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -42,8 +41,6 @@ #include static int __init ixp4xx_clocksource_init(void); -static int __init ixp4xx_clockevent_init(void); -static struct clock_event_device clockevent_ixp4xx; /************************************************************************* * IXP4xx chipset I/O mapping @@ -242,40 +239,52 @@ void __init ixp4xx_init_irq(void) * counter as a source of real clock ticks to account for missed jiffies. *************************************************************************/ +static unsigned volatile last_jiffy_time; + +#define CLOCK_TICKS_PER_USEC ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC) + static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) { - struct clock_event_device *evt = &clockevent_ixp4xx; + write_seqlock(&xtime_lock); /* Clear Pending Interrupt by writing '1' to it */ *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; - evt->event_handler(evt); + /* + * Catch up with the real idea of time + */ + while ((signed long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) { + timer_tick(); + last_jiffy_time += LATCH; + } + + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } static struct irqaction ixp4xx_timer_irq = { - .name = "timer1", + .name = "IXP4xx Timer Tick", .flags = IRQF_DISABLED | IRQF_TIMER, .handler = ixp4xx_timer_interrupt, }; static void __init ixp4xx_timer_init(void) { - /* Reset/disable counter */ - *IXP4XX_OSRT1 = 0; - /* Clear Pending Interrupt by writing '1' to it */ *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; + /* Setup the Timer counter value */ + *IXP4XX_OSRT1 = (LATCH & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE; + /* Reset time-stamp counter */ *IXP4XX_OSTS = 0; + last_jiffy_time = 0; /* Connect the interrupt handler and enable the interrupt */ setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); ixp4xx_clocksource_init(); - ixp4xx_clockevent_init(); } struct sys_timer ixp4xx_timer = { @@ -375,9 +384,6 @@ void __init ixp4xx_sys_init(void) ixp4xx_exp_bus_size >> 20); } -/* - * clocksource - */ cycle_t ixp4xx_get_cycles(void) { return *IXP4XX_OSTS; @@ -402,64 +408,3 @@ static int __init ixp4xx_clocksource_init(void) return 0; } - -/* - * clockevents - */ -static int ixp4xx_set_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; - - *IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts; - - return 0; -} - -static void ixp4xx_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - unsigned long opts, osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK; - - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - osrt = LATCH & ~IXP4XX_OST_RELOAD_MASK; - opts = IXP4XX_OST_ENABLE; - break; - case CLOCK_EVT_MODE_ONESHOT: - /* period set by 'set next_event' */ - osrt = 0; - opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT; - break; - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - default: - osrt = opts = 0; - break; - } - - *IXP4XX_OSRT1 = osrt | opts; -} - -static struct clock_event_device clockevent_ixp4xx = { - .name = "ixp4xx timer1", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .shift = 24, - .set_mode = ixp4xx_set_mode, - .set_next_event = ixp4xx_set_next_event, -}; - -static int __init ixp4xx_clockevent_init(void) -{ - clockevent_ixp4xx.mult = div_sc(FREQ, NSEC_PER_SEC, - clockevent_ixp4xx.shift); - clockevent_ixp4xx.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx); - clockevent_ixp4xx.min_delta_ns = - clockevent_delta2ns(0xf, &clockevent_ixp4xx); - clockevent_ixp4xx.cpumask = cpumask_of_cpu(0); - - clockevents_register_device(&clockevent_ixp4xx); - return 0; -} diff --git a/trunk/arch/arm/mach-omap1/time.c b/trunk/arch/arm/mach-omap1/time.c index 85e048b259f5..1b7e4a506c26 100644 --- a/trunk/arch/arm/mach-omap1/time.c +++ b/trunk/arch/arm/mach-omap1/time.c @@ -39,10 +39,6 @@ #include #include #include -#include -#include -#include -#include #include #include @@ -52,7 +48,13 @@ #include #include +struct sys_timer omap_timer; +/* + * --------------------------------------------------------------------------- + * MPU timer + * --------------------------------------------------------------------------- + */ #define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE #define OMAP_MPU_TIMER_OFFSET 0x100 @@ -86,6 +88,21 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc) return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; } +/* + * MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs + * will break. On P2, the timer count rate is 6.5 MHz after programming PTV + * with 0. This divides the 13MHz input by 2, and is undocumented. + */ +#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE) +/* REVISIT: This ifdef construct should be replaced by a query to clock + * framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz. + */ +#define MPU_TICKS_PER_SEC (13000000 / 2) +#else +#define MPU_TICKS_PER_SEC (12000000 / 2) +#endif + +#define MPU_TIMER_TICK_PERIOD ((MPU_TICKS_PER_SEC / HZ) - 1) typedef struct { u32 cntl; /* CNTL_TIMER, R/W */ @@ -103,164 +120,98 @@ static inline unsigned long omap_mpu_timer_read(int nr) return timer->read_tim; } -static inline void omap_mpu_set_autoreset(int nr) +static inline void omap_mpu_timer_start(int nr, unsigned long load_val) { volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); - timer->cntl = timer->cntl | MPU_TIMER_AR; -} - -static inline void omap_mpu_remove_autoreset(int nr) -{ - volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); - - timer->cntl = timer->cntl & ~MPU_TIMER_AR; -} - -static inline void omap_mpu_timer_start(int nr, unsigned long load_val, - int autoreset) -{ - volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); - unsigned int timerflags = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_ST); - - if (autoreset) timerflags |= MPU_TIMER_AR; - timer->cntl = MPU_TIMER_CLOCK_ENABLE; udelay(1); timer->load_tim = load_val; udelay(1); - timer->cntl = timerflags; -} - -/* - * --------------------------------------------------------------------------- - * MPU timer 1 ... count down to zero, interrupt, reload - * --------------------------------------------------------------------------- - */ -static int omap_mpu_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - omap_mpu_timer_start(0, cycles, 0); - return 0; -} - -static void omap_mpu_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - omap_mpu_set_autoreset(0); - break; - case CLOCK_EVT_MODE_ONESHOT: - omap_mpu_remove_autoreset(0); - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - break; - } + timer->cntl = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_AR | MPU_TIMER_ST); } -static struct clock_event_device clockevent_mpu_timer1 = { - .name = "mpu_timer1", - .features = CLOCK_EVT_FEAT_PERIODIC, CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, - .set_next_event = omap_mpu_set_next_event, - .set_mode = omap_mpu_set_mode, -}; - -static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id) +unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks) { - struct clock_event_device *evt = &clockevent_mpu_timer1; - - evt->event_handler(evt); + unsigned long long nsec; - return IRQ_HANDLED; + nsec = cycles_2_ns((unsigned long long)nr_ticks); + return (unsigned long)nsec / 1000; } -static struct irqaction omap_mpu_timer1_irq = { - .name = "mpu_timer1", - .flags = IRQF_DISABLED | IRQF_TIMER, - .handler = omap_mpu_timer1_interrupt, -}; +/* + * Last processed system timer interrupt + */ +static unsigned long omap_mpu_timer_last = 0; -static __init void omap_init_mpu_timer(unsigned long rate) +/* + * Returns elapsed usecs since last system timer interrupt + */ +static unsigned long omap_mpu_timer_gettimeoffset(void) { - set_cyc2ns_scale(rate / 1000); + unsigned long now = 0 - omap_mpu_timer_read(0); + unsigned long elapsed = now - omap_mpu_timer_last; - setup_irq(INT_TIMER1, &omap_mpu_timer1_irq); - omap_mpu_timer_start(0, (rate / HZ) - 1, 1); - - clockevent_mpu_timer1.mult = div_sc(rate, NSEC_PER_SEC, - clockevent_mpu_timer1.shift); - clockevent_mpu_timer1.max_delta_ns = - clockevent_delta2ns(-1, &clockevent_mpu_timer1); - clockevent_mpu_timer1.min_delta_ns = - clockevent_delta2ns(1, &clockevent_mpu_timer1); - - clockevent_mpu_timer1.cpumask = cpumask_of_cpu(0); - clockevents_register_device(&clockevent_mpu_timer1); + return omap_mpu_timer_ticks_to_usecs(elapsed); } - /* - * --------------------------------------------------------------------------- - * MPU timer 2 ... free running 32-bit clock source and scheduler clock - * --------------------------------------------------------------------------- + * Elapsed time between interrupts is calculated using timer0. + * Latency during the interrupt is calculated using timer1. + * Both timer0 and timer1 are counting at 6MHz (P2 6.5MHz). */ +static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id) +{ + unsigned long now, latency; -static unsigned long omap_mpu_timer2_overflows; + write_seqlock(&xtime_lock); + now = 0 - omap_mpu_timer_read(0); + latency = MPU_TICKS_PER_SEC / HZ - omap_mpu_timer_read(1); + omap_mpu_timer_last = now - latency; + timer_tick(); + write_sequnlock(&xtime_lock); -static irqreturn_t omap_mpu_timer2_interrupt(int irq, void *dev_id) -{ - omap_mpu_timer2_overflows++; return IRQ_HANDLED; } -static struct irqaction omap_mpu_timer2_irq = { - .name = "mpu_timer2", - .flags = IRQF_DISABLED, - .handler = omap_mpu_timer2_interrupt, +static struct irqaction omap_mpu_timer_irq = { + .name = "mpu timer", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = omap_mpu_timer_interrupt, }; -static cycle_t mpu_read(void) +static unsigned long omap_mpu_timer1_overflows; +static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id) { - return ~omap_mpu_timer_read(1); + omap_mpu_timer1_overflows++; + return IRQ_HANDLED; } -static struct clocksource clocksource_mpu = { - .name = "mpu_timer2", - .rating = 300, - .read = mpu_read, - .mask = CLOCKSOURCE_MASK(32), - .shift = 24, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, +static struct irqaction omap_mpu_timer1_irq = { + .name = "mpu timer1 overflow", + .flags = IRQF_DISABLED, + .handler = omap_mpu_timer1_interrupt, }; -static void __init omap_init_clocksource(unsigned long rate) +static __init void omap_init_mpu_timer(void) { - static char err[] __initdata = KERN_ERR - "%s: can't register clocksource!\n"; - - clocksource_mpu.mult - = clocksource_khz2mult(rate/1000, clocksource_mpu.shift); - - setup_irq(INT_TIMER2, &omap_mpu_timer2_irq); - omap_mpu_timer_start(1, ~0, 1); - - if (clocksource_register(&clocksource_mpu)) - printk(err, clocksource_mpu.name); + set_cyc2ns_scale(MPU_TICKS_PER_SEC / 1000); + omap_timer.offset = omap_mpu_timer_gettimeoffset; + setup_irq(INT_TIMER1, &omap_mpu_timer1_irq); + setup_irq(INT_TIMER2, &omap_mpu_timer_irq); + omap_mpu_timer_start(0, 0xffffffff); + omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD); } - /* * Scheduler clock - returns current time in nanosec units. */ unsigned long long sched_clock(void) { - unsigned long ticks = 0 - omap_mpu_timer_read(1); + unsigned long ticks = 0 - omap_mpu_timer_read(0); unsigned long long ticks64; - ticks64 = omap_mpu_timer2_overflows; + ticks64 = omap_mpu_timer1_overflows; ticks64 <<= 32; ticks64 |= ticks; @@ -274,21 +225,10 @@ unsigned long long sched_clock(void) */ static void __init omap_timer_init(void) { - struct clk *ck_ref = clk_get(NULL, "ck_ref"); - unsigned long rate; - - BUG_ON(IS_ERR(ck_ref)); - - rate = clk_get_rate(ck_ref); - clk_put(ck_ref); - - /* PTV = 0 */ - rate /= 2; - - omap_init_mpu_timer(rate); - omap_init_clocksource(rate); + omap_init_mpu_timer(); } struct sys_timer omap_timer = { .init = omap_timer_init, + .offset = NULL, /* Initialized later */ }; diff --git a/trunk/arch/arm/mach-versatile/core.c b/trunk/arch/arm/mach-versatile/core.c index 1275aa7d2eb1..bf71507c76fd 100644 --- a/trunk/arch/arm/mach-versatile/core.c +++ b/trunk/arch/arm/mach-versatile/core.c @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include @@ -830,61 +828,59 @@ void __init versatile_init(void) #define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) #endif -static void timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk) +/* + * Returns number of ms since last clock interrupt. Note that interrupts + * will have been disabled by do_gettimeoffset() + */ +static unsigned long versatile_gettimeoffset(void) { - unsigned long ctrl; - - switch(mode) { - case CLOCK_EVT_MODE_PERIODIC: - writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD); - - ctrl = TIMER_CTRL_PERIODIC; - ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE; - break; - case CLOCK_EVT_MODE_ONESHOT: - /* period set, and timer enabled in 'next_event' hook */ - ctrl = TIMER_CTRL_ONESHOT; - ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE; - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - default: - ctrl = 0; - } + unsigned long ticks1, ticks2, status; - writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL); -} + /* + * Get the current number of ticks. Note that there is a race + * condition between us reading the timer and checking for + * an interrupt. We get around this by ensuring that the + * counter has not reloaded between our two reads. + */ + ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; + do { + ticks1 = ticks2; + status = __raw_readl(VA_IC_BASE + VIC_RAW_STATUS); + ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; + } while (ticks2 > ticks1); -static int timer_set_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL); + /* + * Number of ticks since last interrupt. + */ + ticks1 = TIMER_RELOAD - ticks2; - writel(evt, TIMER0_VA_BASE + TIMER_LOAD); - writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL); + /* + * Interrupt pending? If so, we've reloaded once already. + * + * FIXME: Need to check this is effectively timer 0 that expires + */ + if (status & IRQMASK_TIMERINT0_1) + ticks1 += TIMER_RELOAD; - return 0; + /* + * Convert the ticks to usecs + */ + return TICKS2USECS(ticks1); } -static struct clock_event_device timer0_clockevent = { - .name = "timer0", - .shift = 32, - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = timer_set_mode, - .set_next_event = timer_set_next_event, -}; - /* * IRQ handler for the timer */ static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id) { - struct clock_event_device *evt = &timer0_clockevent; + write_seqlock(&xtime_lock); + // ...clear the interrupt writel(1, TIMER0_VA_BASE + TIMER_INTCLR); - evt->event_handler(evt); + timer_tick(); + + write_sequnlock(&xtime_lock); return IRQ_HANDLED; } @@ -895,36 +891,6 @@ static struct irqaction versatile_timer_irq = { .handler = versatile_timer_interrupt, }; -static cycle_t versatile_get_cycles(void) -{ - return ~readl(TIMER3_VA_BASE + TIMER_VALUE); -} - -static struct clocksource clocksource_versatile = { - .name = "timer3", - .rating = 200, - .read = versatile_get_cycles, - .mask = CLOCKSOURCE_MASK(32), - .shift = 20, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static int __init versatile_clocksource_init(void) -{ - /* setup timer3 as free-running clocksource */ - writel(0, TIMER3_VA_BASE + TIMER_CTRL); - writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD); - writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE); - writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, - TIMER3_VA_BASE + TIMER_CTRL); - - clocksource_versatile.mult = - clocksource_khz2mult(1000, clocksource_versatile.shift); - clocksource_register(&clocksource_versatile); - - return 0; -} - /* * Set up timer interrupt, and return the current time in seconds. */ @@ -952,25 +918,18 @@ static void __init versatile_timer_init(void) writel(0, TIMER2_VA_BASE + TIMER_CTRL); writel(0, TIMER3_VA_BASE + TIMER_CTRL); + writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD); + writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE); + writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC | + TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL); + /* * Make irqs happen for the system timer */ setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq); - - versatile_clocksource_init(); - - timer0_clockevent.mult = - div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift); - timer0_clockevent.max_delta_ns = - clockevent_delta2ns(0xffffffff, &timer0_clockevent); - timer0_clockevent.min_delta_ns = - clockevent_delta2ns(0xf, &timer0_clockevent); - - timer0_clockevent.cpumask = cpumask_of_cpu(0); - clockevents_register_device(&timer0_clockevent); } struct sys_timer versatile_timer = { .init = versatile_timer_init, + .offset = versatile_gettimeoffset, }; - diff --git a/trunk/arch/arm/plat-omap/Kconfig b/trunk/arch/arm/plat-omap/Kconfig index 9e8d21eca4ec..f2dc363de66b 100644 --- a/trunk/arch/arm/plat-omap/Kconfig +++ b/trunk/arch/arm/plat-omap/Kconfig @@ -11,7 +11,6 @@ choice config ARCH_OMAP1 bool "TI OMAP1" - select GENERIC_CLOCKEVENTS config ARCH_OMAP2 bool "TI OMAP2" diff --git a/trunk/arch/arm/plat-omap/common.c b/trunk/arch/arm/plat-omap/common.c index fecd3d625995..57b7b93674a4 100644 --- a/trunk/arch/arm/plat-omap/common.c +++ b/trunk/arch/arm/plat-omap/common.c @@ -156,53 +156,3 @@ static int __init omap_add_serial_console(void) return add_preferred_console("ttyS", line, opt); } console_initcall(omap_add_serial_console); - - -/* - * 32KHz clocksource ... always available, on pretty most chips except - * OMAP 730 and 1510. Other timers could be used as clocksources, with - * higher resolution in free-running counter modes (e.g. 12 MHz xtal), - * but systems won't necessarily want to spend resources that way. - */ - -#if defined(CONFIG_ARCH_OMAP16XX) -#define TIMER_32K_SYNCHRONIZED 0xfffbc410 -#elif defined(CONFIG_ARCH_OMAP24XX) -#define TIMER_32K_SYNCHRONIZED 0x48004010 -#endif - -#ifdef TIMER_32K_SYNCHRONIZED - -#include - -static cycle_t omap_32k_read(void) -{ - return omap_readl(TIMER_32K_SYNCHRONIZED); -} - -static struct clocksource clocksource_32k = { - .name = "32k_counter", - .rating = 250, - .read = omap_32k_read, - .mask = CLOCKSOURCE_MASK(32), - .shift = 10, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static int __init omap_init_clocksource_32k(void) -{ - static char err[] __initdata = KERN_ERR - "%s: can't register clocksource!\n"; - - if (cpu_is_omap16xx() || cpu_is_omap24xx()) { - clocksource_32k.mult = clocksource_hz2mult(32768, - clocksource_32k.shift); - - if (clocksource_register(&clocksource_32k)) - printk(err, clocksource_32k.name); - } - return 0; -} -arch_initcall(omap_init_clocksource_32k); - -#endif /* TIMER_32K_SYNCHRONIZED */ diff --git a/trunk/arch/arm/plat-omap/timer32k.c b/trunk/arch/arm/plat-omap/timer32k.c index 114f87151d60..265310601161 100644 --- a/trunk/arch/arm/plat-omap/timer32k.c +++ b/trunk/arch/arm/plat-omap/timer32k.c @@ -42,8 +42,6 @@ #include #include #include -#include -#include #include #include @@ -82,13 +80,13 @@ struct sys_timer omap_timer; #define OMAP1_32K_TIMER_TVR 0x00 #define OMAP1_32K_TIMER_TCR 0x04 -#define OMAP_32K_TICKS_PER_SEC (32768) +#define OMAP_32K_TICKS_PER_HZ (32768 / HZ) /* * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1 * so with HZ = 128, TVR = 255. */ -#define OMAP_32K_TIMER_TICK_PERIOD ((OMAP_32K_TICKS_PER_SEC / HZ) - 1) +#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1) #define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \ (((nr_jiffies) * (clock_rate)) / HZ) @@ -144,28 +142,6 @@ static inline void omap_32k_timer_ack_irq(void) #endif -static void omap_32k_timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ - switch (mode) { - case CLOCK_EVT_MODE_ONESHOT: - case CLOCK_EVT_MODE_PERIODIC: - omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - omap_32k_timer_stop(); - break; - } -} - -static struct clock_event_device clockevent_32k_timer = { - .name = "32k-timer", - .features = CLOCK_EVT_FEAT_PERIODIC, - .shift = 32, - .set_mode = omap_32k_timer_set_mode, -}; - /* * The 32KHz synchronized timer is an additional timer on 16xx. * It is always running. @@ -194,6 +170,15 @@ omap_32k_ticks_to_nsecs(unsigned long ticks_32k) static unsigned long omap_32k_last_tick = 0; +/* + * Returns elapsed usecs since last 32k timer interrupt + */ +static unsigned long omap_32k_timer_gettimeoffset(void) +{ + unsigned long now = omap_32k_sync_timer_read(); + return omap_32k_ticks_to_usecs(now - omap_32k_last_tick); +} + /* * 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. @@ -203,16 +188,95 @@ unsigned long long sched_clock(void) return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read()); } -static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id) +/* + * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this + * function is also called from other interrupts to remove latency + * issues with dynamic tick. In the dynamic tick case, we need to lock + * with irqsave. + */ +static inline irqreturn_t _omap_32k_timer_interrupt(int irq, void *dev_id) { - struct clock_event_device *evt = &clockevent_32k_timer; + unsigned long now; + omap_32k_timer_ack_irq(); + now = omap_32k_sync_timer_read(); + + while ((signed long)(now - omap_32k_last_tick) + >= OMAP_32K_TICKS_PER_HZ) { + omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ; + timer_tick(); + } + + /* Restart timer so we don't drift off due to modulo or dynamic tick. + * By default we program the next timer to be continuous to avoid + * latencies during high system load. During dynamic tick operation the + * continuous timer can be overridden from pm_idle to be longer. + */ + omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now); + + return IRQ_HANDLED; +} + +static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id) +{ + return _omap_32k_timer_interrupt(irq, dev_id); +} + +static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id) +{ + unsigned long flags; - evt->event_handler(evt); + write_seqlock_irqsave(&xtime_lock, flags); + _omap_32k_timer_interrupt(irq, dev_id); + write_sequnlock_irqrestore(&xtime_lock, flags); return IRQ_HANDLED; } +#ifdef CONFIG_NO_IDLE_HZ +/* + * Programs the next timer interrupt needed. Called when dynamic tick is + * enabled, and to reprogram the ticks to skip from pm_idle. Note that + * we can keep the timer continuous, and don't need to set it to run in + * one-shot mode. This is because the timer will get reprogrammed again + * after next interrupt. + */ +void omap_32k_timer_reprogram(unsigned long next_tick) +{ + unsigned long ticks = JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1; + unsigned long now = omap_32k_sync_timer_read(); + unsigned long idled = now - omap_32k_last_tick; + + if (idled + 1 < ticks) + ticks -= idled; + else + ticks = 1; + omap_32k_timer_start(ticks); +} + +static struct irqaction omap_32k_timer_irq; +extern struct timer_update_handler timer_update; + +static int omap_32k_timer_enable_dyn_tick(void) +{ + /* No need to reprogram timer, just use the next interrupt */ + return 0; +} + +static int omap_32k_timer_disable_dyn_tick(void) +{ + omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); + return 0; +} + +static struct dyn_tick_timer omap_dyn_tick_timer = { + .enable = omap_32k_timer_enable_dyn_tick, + .disable = omap_32k_timer_disable_dyn_tick, + .reprogram = omap_32k_timer_reprogram, + .handler = omap_32k_timer_handler, +}; +#endif /* CONFIG_NO_IDLE_HZ */ + static struct irqaction omap_32k_timer_irq = { .name = "32KHz timer", .flags = IRQF_DISABLED | IRQF_TIMER, @@ -221,8 +285,13 @@ static struct irqaction omap_32k_timer_irq = { static __init void omap_init_32k_timer(void) { +#ifdef CONFIG_NO_IDLE_HZ + omap_timer.dyn_tick = &omap_dyn_tick_timer; +#endif + if (cpu_class_is_omap1()) setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); + omap_timer.offset = omap_32k_timer_gettimeoffset; omap_32k_last_tick = omap_32k_sync_timer_read(); #ifdef CONFIG_ARCH_OMAP2 @@ -239,16 +308,7 @@ static __init void omap_init_32k_timer(void) } #endif - clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC, - NSEC_PER_SEC, - clockevent_32k_timer.shift); - clockevent_32k_timer.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer); - clockevent_32k_timer.min_delta_ns = - clockevent_delta2ns(1, &clockevent_32k_timer); - - clockevent_32k_timer.cpumask = cpumask_of_cpu(0); - clockevents_register_device(&clockevent_32k_timer); + omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); } /* @@ -266,4 +326,5 @@ static void __init omap_timer_init(void) struct sys_timer omap_timer = { .init = omap_timer_init, + .offset = NULL, /* Initialized later */ }; diff --git a/trunk/drivers/serial/imx.c b/trunk/drivers/serial/imx.c index 04cc88cc528c..e42faa4e4282 100644 --- a/trunk/drivers/serial/imx.c +++ b/trunk/drivers/serial/imx.c @@ -46,6 +46,122 @@ #include #include +/* Register definitions */ +#define URXD0 0x0 /* Receiver Register */ +#define URTX0 0x40 /* Transmitter Register */ +#define UCR1 0x80 /* Control Register 1 */ +#define UCR2 0x84 /* Control Register 2 */ +#define UCR3 0x88 /* Control Register 3 */ +#define UCR4 0x8c /* Control Register 4 */ +#define UFCR 0x90 /* FIFO Control Register */ +#define USR1 0x94 /* Status Register 1 */ +#define USR2 0x98 /* Status Register 2 */ +#define UESC 0x9c /* Escape Character Register */ +#define UTIM 0xa0 /* Escape Timer Register */ +#define UBIR 0xa4 /* BRM Incremental Register */ +#define UBMR 0xa8 /* BRM Modulator Register */ +#define UBRC 0xac /* Baud Rate Count Register */ +#define BIPR1 0xb0 /* Incremental Preset Register 1 */ +#define BIPR2 0xb4 /* Incremental Preset Register 2 */ +#define BIPR3 0xb8 /* Incremental Preset Register 3 */ +#define BIPR4 0xbc /* Incremental Preset Register 4 */ +#define BMPR1 0xc0 /* BRM Modulator Register 1 */ +#define BMPR2 0xc4 /* BRM Modulator Register 2 */ +#define BMPR3 0xc8 /* BRM Modulator Register 3 */ +#define BMPR4 0xcc /* BRM Modulator Register 4 */ +#define UTS 0xd0 /* UART Test Register */ + +/* UART Control Register Bit Fields.*/ +#define URXD_CHARRDY (1<<15) +#define URXD_ERR (1<<14) +#define URXD_OVRRUN (1<<13) +#define URXD_FRMERR (1<<12) +#define URXD_BRK (1<<11) +#define URXD_PRERR (1<<10) +#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ +#define UCR1_ADBR (1<<14) /* Auto detect baud rate */ +#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ +#define UCR1_IDEN (1<<12) /* Idle condition interrupt */ +#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ +#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ +#define UCR1_IREN (1<<7) /* Infrared interface enable */ +#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ +#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ +#define UCR1_SNDBRK (1<<4) /* Send break */ +#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ +#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ +#define UCR1_DOZE (1<<1) /* Doze */ +#define UCR1_UARTEN (1<<0) /* UART enabled */ +#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ +#define UCR2_IRTS (1<<14) /* Ignore RTS pin */ +#define UCR2_CTSC (1<<13) /* CTS pin control */ +#define UCR2_CTS (1<<12) /* Clear to send */ +#define UCR2_ESCEN (1<<11) /* Escape enable */ +#define UCR2_PREN (1<<8) /* Parity enable */ +#define UCR2_PROE (1<<7) /* Parity odd/even */ +#define UCR2_STPB (1<<6) /* Stop */ +#define UCR2_WS (1<<5) /* Word size */ +#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ +#define UCR2_TXEN (1<<2) /* Transmitter enabled */ +#define UCR2_RXEN (1<<1) /* Receiver enabled */ +#define UCR2_SRST (1<<0) /* SW reset */ +#define UCR3_DTREN (1<<13) /* DTR interrupt enable */ +#define UCR3_PARERREN (1<<12) /* Parity enable */ +#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */ +#define UCR3_DSR (1<<10) /* Data set ready */ +#define UCR3_DCD (1<<9) /* Data carrier detect */ +#define UCR3_RI (1<<8) /* Ring indicator */ +#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */ +#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ +#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ +#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ +#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */ +#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */ +#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ +#define UCR3_BPEN (1<<0) /* Preset registers enable */ +#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ +#define UCR4_INVR (1<<9) /* Inverted infrared reception */ +#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ +#define UCR4_WKEN (1<<7) /* Wake interrupt enable */ +#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */ +#define UCR4_IRSC (1<<5) /* IR special case */ +#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */ +#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */ +#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ +#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ +#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ +#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ +#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ +#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */ +#define USR1_RTSD (1<<12) /* RTS delta */ +#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */ +#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */ +#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */ +#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */ +#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */ +#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */ +#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */ +#define USR2_ADET (1<<15) /* Auto baud rate detect complete */ +#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */ +#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */ +#define USR2_IDLE (1<<12) /* Idle condition */ +#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */ +#define USR2_WAKE (1<<7) /* Wake */ +#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */ +#define USR2_TXDC (1<<3) /* Transmitter complete */ +#define USR2_BRCD (1<<2) /* Break condition */ +#define USR2_ORE (1<<1) /* Overrun error */ +#define USR2_RDR (1<<0) /* Recv data ready */ +#define UTS_FRCPERR (1<<13) /* Force parity error */ +#define UTS_LOOP (1<<12) /* Loop tx and rx */ +#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ +#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ +#define UTS_TXFULL (1<<4) /* TxFIFO full */ +#define UTS_RXFULL (1<<3) /* RxFIFO full */ +#define UTS_SOFTRST (1<<0) /* Software reset */ + /* We've been assigned a range on the "Low-density serial ports" major */ #define SERIAL_IMX_MAJOR 204 #define MINOR_START 41 @@ -128,7 +244,10 @@ static void imx_timeout(unsigned long data) static void imx_stop_tx(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; - UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN; + unsigned long temp; + + temp = readl(sport->port.membase + UCR1); + writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1); } /* @@ -137,7 +256,10 @@ static void imx_stop_tx(struct uart_port *port) static void imx_stop_rx(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; - UCR2((u32)sport->port.membase) &= ~UCR2_RXEN; + unsigned long temp; + + temp = readl(sport->port.membase + UCR2); + writel(temp &~ UCR2_RXEN, sport->port.membase + UCR2); } /* @@ -154,10 +276,10 @@ static inline void imx_transmit_buffer(struct imx_port *sport) { struct circ_buf *xmit = &sport->port.info->xmit; - while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)) { + while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) { /* send xmit->buf[xmit->tail] * out the port here */ - URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail]; + writel(xmit->buf[xmit->tail], sport->port.membase + URTX0); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); sport->port.icount.tx++; @@ -175,21 +297,24 @@ static inline void imx_transmit_buffer(struct imx_port *sport) static void imx_start_tx(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; + unsigned long temp; - UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN; + temp = readl(sport->port.membase + UCR1); + writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); - imx_transmit_buffer(sport); + if (readl(sport->port.membase + UTS) & UTS_TXEMPTY) + imx_transmit_buffer(sport); } static irqreturn_t imx_rtsint(int irq, void *dev_id) { struct imx_port *sport = (struct imx_port *)dev_id; - unsigned int val = USR1((u32)sport->port.membase)&USR1_RTSS; + unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS; unsigned long flags; spin_lock_irqsave(&sport->port.lock, flags); - USR1((u32)sport->port.membase) = USR1_RTSD; + writel(USR1_RTSD, sport->port.membase + USR1); uart_handle_cts_change(&sport->port, !!val); wake_up_interruptible(&sport->port.info->delta_msr_wait); @@ -207,7 +332,7 @@ static irqreturn_t imx_txint(int irq, void *dev_id) if (sport->port.x_char) { /* Send next char */ - URTX0((u32)sport->port.membase) = sport->port.x_char; + writel(sport->port.x_char, sport->port.membase + URTX0); goto out; } @@ -231,17 +356,18 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) struct imx_port *sport = dev_id; unsigned int rx,flg,ignored = 0; struct tty_struct *tty = sport->port.info->tty; - unsigned long flags; + unsigned long flags, temp; - rx = URXD0((u32)sport->port.membase); + rx = readl(sport->port.membase + URXD0); spin_lock_irqsave(&sport->port.lock,flags); do { flg = TTY_NORMAL; sport->port.icount.rx++; - if( USR2((u32)sport->port.membase) & USR2_BRCD ) { - USR2((u32)sport->port.membase) |= USR2_BRCD; + temp = readl(sport->port.membase + USR2); + if( temp & USR2_BRCD ) { + writel(temp | USR2_BRCD, sport->port.membase + USR2); if(uart_handle_break(&sport->port)) goto ignore_char; } @@ -257,7 +383,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) tty_insert_flip_char(tty, rx, flg); ignore_char: - rx = URXD0((u32)sport->port.membase); + rx = readl(sport->port.membase + URXD0); } while(rx & URXD_CHARRDY); out: @@ -301,7 +427,7 @@ static unsigned int imx_tx_empty(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; - return USR2((u32)sport->port.membase) & USR2_TXDC ? TIOCSER_TEMT : 0; + return (readl(sport->port.membase + USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0; } /* @@ -312,10 +438,10 @@ static unsigned int imx_get_mctrl(struct uart_port *port) struct imx_port *sport = (struct imx_port *)port; unsigned int tmp = TIOCM_DSR | TIOCM_CAR; - if (USR1((u32)sport->port.membase) & USR1_RTSS) + if (readl(sport->port.membase + USR1) & USR1_RTSS) tmp |= TIOCM_CTS; - if (UCR2((u32)sport->port.membase) & UCR2_CTS) + if (readl(sport->port.membase + UCR2) & UCR2_CTS) tmp |= TIOCM_RTS; return tmp; @@ -324,11 +450,14 @@ static unsigned int imx_get_mctrl(struct uart_port *port) static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) { struct imx_port *sport = (struct imx_port *)port; + unsigned long temp; + + temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS; if (mctrl & TIOCM_RTS) - UCR2((u32)sport->port.membase) |= UCR2_CTS; - else - UCR2((u32)sport->port.membase) &= ~UCR2_CTS; + temp |= UCR2_CTS; + + writel(temp, sport->port.membase + UCR2); } /* @@ -337,14 +466,16 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) static void imx_break_ctl(struct uart_port *port, int break_state) { struct imx_port *sport = (struct imx_port *)port; - unsigned long flags; + unsigned long flags, temp; spin_lock_irqsave(&sport->port.lock, flags); + temp = readl(sport->port.membase + UCR1) & ~UCR1_SNDBRK; + if ( break_state != 0 ) - UCR1((u32)sport->port.membase) |= UCR1_SNDBRK; - else - UCR1((u32)sport->port.membase) &= ~UCR1_SNDBRK; + temp |= UCR1_SNDBRK; + + writel(temp, sport->port.membase + UCR1); spin_unlock_irqrestore(&sport->port.lock, flags); } @@ -360,7 +491,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) /* set receiver / transmitter trigger level. * RFDIV is set such way to satisfy requested uartclk value */ - val = TXTL<<10 | RXTL; + val = TXTL << 10 | RXTL; ufcr_rfdiv = (imx_get_perclk1() + sport->port.uartclk / 2) / sport->port.uartclk; if(!ufcr_rfdiv) @@ -373,7 +504,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) val |= UFCR_RFDIV & (ufcr_rfdiv << 7); - UFCR((u32)sport->port.membase) = val; + writel(val, sport->port.membase + UFCR); return 0; } @@ -382,14 +513,15 @@ static int imx_startup(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; int retval; - unsigned long flags; + unsigned long flags, temp; imx_setup_ufcr(sport, 0); /* disable the DREN bit (Data Ready interrupt enable) before * requesting IRQs */ - UCR4((u32)sport->port.membase) &= ~UCR4_DREN; + temp = readl(sport->port.membase + UCR4); + writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); /* * Allocate the IRQ @@ -411,12 +543,16 @@ static int imx_startup(struct uart_port *port) /* * Finally, clear and enable interrupts */ + writel(USR1_RTSD, sport->port.membase + USR1); + + temp = readl(sport->port.membase + UCR1); + temp |= (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); + writel(temp, sport->port.membase + UCR1); - USR1((u32)sport->port.membase) = USR1_RTSD; - UCR1((u32)sport->port.membase) |= - (UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); + temp = readl(sport->port.membase + UCR2); + temp |= (UCR2_RXEN | UCR2_TXEN); + writel(temp, sport->port.membase + UCR2); - UCR2((u32)sport->port.membase) |= (UCR2_RXEN | UCR2_TXEN); /* * Enable modem status interrupts */ @@ -437,6 +573,7 @@ static int imx_startup(struct uart_port *port) static void imx_shutdown(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; + unsigned long temp; /* * Stop our timer. @@ -454,8 +591,9 @@ static void imx_shutdown(struct uart_port *port) * Disable all interrupts, port and break condition. */ - UCR1((u32)sport->port.membase) &= - ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); + temp = readl(sport->port.membase + UCR1); + temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); + writel(temp, sport->port.membase + UCR1); } static void @@ -548,18 +686,18 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, /* * disable interrupts and drain transmitter */ - old_ucr1 = UCR1((u32)sport->port.membase); - UCR1((u32)sport->port.membase) &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); + old_ucr1 = readl(sport->port.membase + UCR1); + writel(old_ucr1 & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN), + sport->port.membase + UCR1); - while ( !(USR2((u32)sport->port.membase) & USR2_TXDC)) + while ( !(readl(sport->port.membase + USR2) & USR2_TXDC)) barrier(); /* then, disable everything */ - old_txrxen = UCR2((u32)sport->port.membase) & ( UCR2_TXEN | UCR2_RXEN ); - UCR2((u32)sport->port.membase) &= ~( UCR2_TXEN | UCR2_RXEN); - - /* set the parity, stop bits and data size */ - UCR2((u32)sport->port.membase) = ucr2; + old_txrxen = readl(sport->port.membase + UCR2); + writel(old_txrxen & ~( UCR2_TXEN | UCR2_RXEN), + sport->port.membase + UCR2); + old_txrxen &= (UCR2_TXEN | UCR2_RXEN); /* set the baud rate. We assume uartclk = 16 MHz * @@ -567,11 +705,13 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, * --------- = -------- * uartclk UBMR - 1 */ - UBIR((u32)sport->port.membase) = (baud / 100) - 1; - UBMR((u32)sport->port.membase) = 10000 - 1; + writel((baud / 100) - 1, sport->port.membase + UBIR); + writel(10000 - 1, sport->port.membase + UBMR); + + writel(old_ucr1, sport->port.membase + UCR1); - UCR1((u32)sport->port.membase) = old_ucr1; - UCR2((u32)sport->port.membase) |= old_txrxen; + /* set the parity, stop bits and data size */ + writel(ucr2 | old_txrxen, sport->port.membase + UCR2); if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) imx_enable_ms(&sport->port); @@ -730,9 +870,11 @@ static void __init imx_init_ports(void) static void imx_console_putchar(struct uart_port *port, int ch) { struct imx_port *sport = (struct imx_port *)port; - while ((UTS((u32)sport->port.membase) & UTS_TXFULL)) + + while (readl(sport->port.membase + UTS) & UTS_TXFULL) barrier(); - URTX0((u32)sport->port.membase) = ch; + + writel(ch, sport->port.membase + URTX0); } /* @@ -747,13 +889,14 @@ imx_console_write(struct console *co, const char *s, unsigned int count) /* * First, save UCR1/2 and then disable interrupts */ - old_ucr1 = UCR1((u32)sport->port.membase); - old_ucr2 = UCR2((u32)sport->port.membase); + old_ucr1 = readl(sport->port.membase + UCR1); + old_ucr2 = readl(sport->port.membase + UCR2); - UCR1((u32)sport->port.membase) = - (old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN) - & ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN); - UCR2((u32)sport->port.membase) = old_ucr2 | UCR2_TXEN; + writel((old_ucr1 | UCR1_UARTCLKEN | UCR1_UARTEN) & + ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN), + sport->port.membase + UCR1); + + writel(old_ucr2 | UCR2_TXEN, sport->port.membase + UCR2); uart_console_write(&sport->port, s, count, imx_console_putchar); @@ -761,10 +904,10 @@ imx_console_write(struct console *co, const char *s, unsigned int count) * Finally, wait for transmitter to become empty * and restore UCR1/2 */ - while (!(USR2((u32)sport->port.membase) & USR2_TXDC)); + while (!(readl(sport->port.membase + USR2) & USR2_TXDC)); - UCR1((u32)sport->port.membase) = old_ucr1; - UCR2((u32)sport->port.membase) = old_ucr2; + writel(old_ucr1, sport->port.membase + UCR1); + writel(old_ucr2, sport->port.membase + UCR2); } /* @@ -776,13 +919,13 @@ imx_console_get_options(struct imx_port *sport, int *baud, int *parity, int *bits) { - if ( UCR1((u32)sport->port.membase) | UCR1_UARTEN ) { + if ( readl(sport->port.membase + UCR1) | UCR1_UARTEN ) { /* ok, the port was enabled */ unsigned int ucr2, ubir,ubmr, uartclk; unsigned int baud_raw; unsigned int ucfr_rfdiv; - ucr2 = UCR2((u32)sport->port.membase); + ucr2 = readl(sport->port.membase + UCR2); *parity = 'n'; if (ucr2 & UCR2_PREN) { @@ -797,11 +940,10 @@ imx_console_get_options(struct imx_port *sport, int *baud, else *bits = 7; - ubir = UBIR((u32)sport->port.membase) & 0xffff; - ubmr = UBMR((u32)sport->port.membase) & 0xffff; - + ubir = readl(sport->port.membase + UBIR) & 0xffff; + ubmr = readl(sport->port.membase + UBMR) & 0xffff; - ucfr_rfdiv = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) >> 7; + ucfr_rfdiv = (readl(sport->port.membase + UFCR) & UFCR_RFDIV) >> 7; if (ucfr_rfdiv == 6) ucfr_rfdiv = 7; else diff --git a/trunk/include/asm-arm/arch-imx/imx-regs.h b/trunk/include/asm-arm/arch-imx/imx-regs.h index e56a4e247d62..de6494a4dc6b 100644 --- a/trunk/include/asm-arm/arch-imx/imx-regs.h +++ b/trunk/include/asm-arm/arch-imx/imx-regs.h @@ -477,122 +477,4 @@ #define LCDISR_EOF (1<<1) #define LCDISR_BOF (1<<0) -/* - * UART Module. Takes the UART base address as argument - */ -#define URXD0(x) __REG( 0x0 + (x)) /* Receiver Register */ -#define URTX0(x) __REG( 0x40 + (x)) /* Transmitter Register */ -#define UCR1(x) __REG( 0x80 + (x)) /* Control Register 1 */ -#define UCR2(x) __REG( 0x84 + (x)) /* Control Register 2 */ -#define UCR3(x) __REG( 0x88 + (x)) /* Control Register 3 */ -#define UCR4(x) __REG( 0x8c + (x)) /* Control Register 4 */ -#define UFCR(x) __REG( 0x90 + (x)) /* FIFO Control Register */ -#define USR1(x) __REG( 0x94 + (x)) /* Status Register 1 */ -#define USR2(x) __REG( 0x98 + (x)) /* Status Register 2 */ -#define UESC(x) __REG( 0x9c + (x)) /* Escape Character Register */ -#define UTIM(x) __REG( 0xa0 + (x)) /* Escape Timer Register */ -#define UBIR(x) __REG( 0xa4 + (x)) /* BRM Incremental Register */ -#define UBMR(x) __REG( 0xa8 + (x)) /* BRM Modulator Register */ -#define UBRC(x) __REG( 0xac + (x)) /* Baud Rate Count Register */ -#define BIPR1(x) __REG( 0xb0 + (x)) /* Incremental Preset Register 1 */ -#define BIPR2(x) __REG( 0xb4 + (x)) /* Incremental Preset Register 2 */ -#define BIPR3(x) __REG( 0xb8 + (x)) /* Incremental Preset Register 3 */ -#define BIPR4(x) __REG( 0xbc + (x)) /* Incremental Preset Register 4 */ -#define BMPR1(x) __REG( 0xc0 + (x)) /* BRM Modulator Register 1 */ -#define BMPR2(x) __REG( 0xc4 + (x)) /* BRM Modulator Register 2 */ -#define BMPR3(x) __REG( 0xc8 + (x)) /* BRM Modulator Register 3 */ -#define BMPR4(x) __REG( 0xcc + (x)) /* BRM Modulator Register 4 */ -#define UTS(x) __REG( 0xd0 + (x)) /* UART Test Register */ - -/* UART Control Register Bit Fields.*/ -#define URXD_CHARRDY (1<<15) -#define URXD_ERR (1<<14) -#define URXD_OVRRUN (1<<13) -#define URXD_FRMERR (1<<12) -#define URXD_BRK (1<<11) -#define URXD_PRERR (1<<10) -#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ -#define UCR1_ADBR (1<<14) /* Auto detect baud rate */ -#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ -#define UCR1_IDEN (1<<12) /* Idle condition interrupt */ -#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ -#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ -#define UCR1_IREN (1<<7) /* Infrared interface enable */ -#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ -#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ -#define UCR1_SNDBRK (1<<4) /* Send break */ -#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ -#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ -#define UCR1_DOZE (1<<1) /* Doze */ -#define UCR1_UARTEN (1<<0) /* UART enabled */ -#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ -#define UCR2_IRTS (1<<14) /* Ignore RTS pin */ -#define UCR2_CTSC (1<<13) /* CTS pin control */ -#define UCR2_CTS (1<<12) /* Clear to send */ -#define UCR2_ESCEN (1<<11) /* Escape enable */ -#define UCR2_PREN (1<<8) /* Parity enable */ -#define UCR2_PROE (1<<7) /* Parity odd/even */ -#define UCR2_STPB (1<<6) /* Stop */ -#define UCR2_WS (1<<5) /* Word size */ -#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ -#define UCR2_TXEN (1<<2) /* Transmitter enabled */ -#define UCR2_RXEN (1<<1) /* Receiver enabled */ -#define UCR2_SRST (1<<0) /* SW reset */ -#define UCR3_DTREN (1<<13) /* DTR interrupt enable */ -#define UCR3_PARERREN (1<<12) /* Parity enable */ -#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */ -#define UCR3_DSR (1<<10) /* Data set ready */ -#define UCR3_DCD (1<<9) /* Data carrier detect */ -#define UCR3_RI (1<<8) /* Ring indicator */ -#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */ -#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ -#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ -#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ -#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */ -#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */ -#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ -#define UCR3_BPEN (1<<0) /* Preset registers enable */ -#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ -#define UCR4_INVR (1<<9) /* Inverted infrared reception */ -#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ -#define UCR4_WKEN (1<<7) /* Wake interrupt enable */ -#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */ -#define UCR4_IRSC (1<<5) /* IR special case */ -#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */ -#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */ -#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ -#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ -#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ -#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ -#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ -#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ -#define USR1_RTSS (1<<14) /* RTS pin status */ -#define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */ -#define USR1_RTSD (1<<12) /* RTS delta */ -#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */ -#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */ -#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */ -#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */ -#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */ -#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */ -#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */ -#define USR2_ADET (1<<15) /* Auto baud rate detect complete */ -#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */ -#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */ -#define USR2_IDLE (1<<12) /* Idle condition */ -#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */ -#define USR2_WAKE (1<<7) /* Wake */ -#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */ -#define USR2_TXDC (1<<3) /* Transmitter complete */ -#define USR2_BRCD (1<<2) /* Break condition */ -#define USR2_ORE (1<<1) /* Overrun error */ -#define USR2_RDR (1<<0) /* Recv data ready */ -#define UTS_FRCPERR (1<<13) /* Force parity error */ -#define UTS_LOOP (1<<12) /* Loop tx and rx */ -#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ -#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ -#define UTS_TXFULL (1<<4) /* TxFIFO full */ -#define UTS_RXFULL (1<<3) /* RxFIFO full */ -#define UTS_SOFTRST (1<<0) /* Software reset */ - #endif // _IMX_REGS_H