OMAP1 realtime patch 2.6.21-rc3-rt0-omap1
Subsystems (5)
Update of our realtime patch to most recent rt patch patch-2.6.21-rc3-rt0.
As ususal, use recent OMAP git as starting point, then apply patch-2.6.21-rc3-rt0 [1] ignoring conflicts, and on top of this patch in attachment.
Note: The raw_spinlock in plat-omap/gpio.c is directly from patch-2.6.21-rc3-rt0. Not tested yet if this and the other OMAP related raw_spinlock conversions in patch-2.6.21-rc3-rt0 are really necessary.
Cheers,
Dirk
[1] http://people.redhat.com/mingo/realtime-preempt/
arch/arm/mach-omap1/time.c +67 -8
@@ -42,6 +42,7 @@#include <linux/clk.h> #include <linux/err.h> #include <linux/clocksource.h> +#include <linux/clockchips.h> #include <asm/system.h> #include <asm/hardware.h>
@@ -102,15 +103,33 @@ static inline unsigned long omap_mpu_timreturn timer->read_tim; } -static inline void omap_mpu_timer_start (int nr,unsigned long load_val) +static inline void omap_mpu_set_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_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 = (MPU_TIMER_CLOCK_ENABLE |MPU_TIMER_AR |MPU_TIMER_ST ); + timer->cntl = timerflags; }/*
@@ -118,12 +137,42 @@ static inline void omap_mpu_timer_start(* 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 ; + } +} + +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) { -write_seqlock (&xtime_lock); -/* NOTE: no lost-tick detection/handling! */ -timer_tick (); -write_sequnlock (&xtime_lock); +struct clock_event_device *evt = &clockevent_mpu_timer1; + + evt->event_handler (evt);return IRQ_HANDLED ; }
@@ -139,7 +188,17 @@ static __init void omap_init_mpu_timer(uset_cyc2ns_scale (rate /1000 );setup_irq (INT_TIMER1 , &omap_mpu_timer1_irq); -omap_mpu_timer_start (0 , (rate /HZ ) -1 ); +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); }/*
@@ -185,7 +244,7 @@ static void __init omap_init_clocksource = clocksource_khz2mult(rate/1000, clocksource_mpu.shift);setup_irq (INT_TIMER2 , &omap_mpu_timer2_irq); -omap_mpu_timer_start (1 , ~0 ); +omap_mpu_timer_start (1 , ~0 ,1 );if (clocksource_register (&clocksource_mpu))printk (err, clocksource_mpu.name);
arch/arm/plat-omap/timer32k.c +5 -98
127 lines not on this page · raw message
kernel/irq/manage.c +14 -0
@@ -628,6 +628,7 @@ static void thread_simple_irq(irq_desc_tunsigned int irq = desc - irq_desc;irqreturn_t action_ret; + restart:if (action && !desc->depth) {spin_unlock (&desc->lock); action_ret =handle_IRQ_event (irq, action);
@@ -636,6 +637,19 @@ static void thread_simple_irq(irq_desc_tif (!noirqdebug)note_interrupt (irq, desc, action_ret); } + +/* +* Some boards will disable an interrupt when it +* sets IRQ_PENDING . So we have to remove the flag +* and re-enable to handle it. +*/ +if (desc->status &IRQ_PENDING ) { + desc->status &= ~IRQ_PENDING ; +if (desc->chip) + desc->chip->enable (irq); + goto restart; + } + desc->status &= ~IRQ_INPROGRESS ; }
sound/arm/omap/omap-alsa.c +0 -3
@@ -168,7 +168,6 @@ static void audio_stop_dma(struct audio_unsigned long flags;ADEBUG (); -spin_lock_irqsave (&s->dma_lock, flags); s->active =0 ; s->period =0 ; s->periods =0 ;
@@ -177,8 +176,6 @@ static void audio_stop_dma(struct audio_omap_stop_alsa_sound_dma (s);omap_clear_alsa_sound_dma (s); - -spin_unlock_irqrestore (&s->dma_lock, flags); }/*
arch/arm/plat-omap/gpio.c +1 -1
@@ -136,7 +136,7 @@ struct gpio_bank {u32 saved_fallingdetect;u32 saved_risingdetect;#endif -spinlock_t lock; +raw_spinlock_t lock; };#define METHOD_MPUIO 0