This patch adds Adeos support for the Intel IXP425 processor. It may also work on the IXP465, but I only tested it on the 425. The patch is against a vanilla 2.6.19 kernel.
Enjoy, Richard ******************************************************************** Richard Cochran (Mr), Software Development OMICRON electronics GmbH, Oberes Ried 1, A-6833 Klaus / Austria http://www.omicron.at/ ******************************************************************** --- diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index fbe288a..794e348 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -39,6 +39,30 @@ #include <asm/mach/irq.h> #include <asm/mach/time.h> +#ifdef CONFIG_IPIPE +#include <linux/ipipe.h> + +/* We have no cascaded interrupts. */ +void __ipipe_mach_demux_irq(unsigned irq, struct pt_regs *regs) {} + +#ifdef CONFIG_NO_IDLE_HZ +#error "dynamic tick timer not yet supported with IPIPE" +#endif + +int __ipipe_mach_timerint = IRQ_IXP4XX_TIMER1; +int __ipipe_mach_timerstolen = 0; +unsigned int __ipipe_mach_ticks_per_jiffy = LATCH; + +EXPORT_SYMBOL(__ipipe_mach_timerint); +EXPORT_SYMBOL(__ipipe_mach_timerstolen); +EXPORT_SYMBOL(__ipipe_mach_ticks_per_jiffy); + +static int ixp4xx_timer_initialized; + +#define ONE_SHOT_ENABLE (IXP4XX_OST_ENABLE|IXP4XX_OST_ONE_SHOT) + +#endif /* CONFIG_IPIPE */ + /*********************************************************************** ** * IXP4xx chipset I/O mapping ************************************************************************ */ @@ -240,6 +264,37 @@ static unsigned volatile last_jiffy_time; #define CLOCK_TICKS_PER_USEC ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC) +#ifdef CONFIG_IPIPE + +static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) +{ + write_seqlock(&xtime_lock); + if (__ipipe_mach_timerstolen) { + /* If some other domain has taken over the timer, then + * do nothing (ipipe has acked it, and the other + * domain has reprogramed it) + */ + } else { + /* If Linux is running under ipipe, but it still has + * the control over the timer (no Xenomai for + * example), then reprogram the timer (ipipe has + * already acked it) + */ + *IXP4XX_OSRT1 = LATCH | ONE_SHOT_ENABLE; + } + /* + * 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; +} + +#else /* !CONFIG_IPIPE */ + static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) { write_seqlock(&xtime_lock); @@ -260,6 +315,8 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +#endif /* !CONFIG_IPIPE */ + static struct irqaction ixp4xx_timer_irq = { .name = "IXP4xx Timer Tick", .flags = IRQF_DISABLED | IRQF_TIMER, @@ -272,7 +329,12 @@ static void __init ixp4xx_timer_init(void) *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; /* Setup the Timer counter value */ +#ifdef CONFIG_IPIPE + ixp4xx_timer_initialized = 1; + *IXP4XX_OSRT1 = LATCH | ONE_SHOT_ENABLE; +#else *IXP4XX_OSRT1 = (LATCH & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE; +#endif /* Reset time-stamp counter */ *IXP4XX_OSTS = 0; @@ -365,3 +427,92 @@ static int __init ixp4xx_clocksource_init(void) } device_initcall(ixp4xx_clocksource_init); + +#ifdef CONFIG_IPIPE + +void __ipipe_mach_acktimer(void) +{ + /* Clear Pending Interrupt by writing '1' to it */ + *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; +} + +EXPORT_SYMBOL(__ipipe_mach_acktimer); + +unsigned long long __ipipe_mach_get_tsc(void) +{ + if (likely(ixp4xx_timer_initialized)) { + static union { +#ifdef __BIG_ENDIAN + struct { + unsigned long high; + unsigned long low; + }; +#else /* __LITTLE_ENDIAN */ + struct { + unsigned long low; + unsigned long high; + }; +#endif /* __LITTLE_ENDIAN */ + unsigned long long full; + } tsc[NR_CPUS], *local_tsc; + unsigned long stamp, flags; + unsigned long long result; + + local_irq_save_hw(flags); + local_tsc = &tsc[ipipe_processor_id()]; + stamp = *IXP4XX_OSTS; + if (unlikely(stamp < local_tsc->low)) + /* 32 bit counter wrapped, increment high word. */ + local_tsc->high++; + local_tsc->low = stamp; + result = local_tsc->full; + local_irq_restore_hw(flags); + + return result; + } + + return 0; +} + +EXPORT_SYMBOL(__ipipe_mach_get_tsc); + +/* + * Reprogram the timer + * + * The timer is aperiodic (most of the time) when running Xenomai, so + * __ipipe_mach_set_dec is called for each timer tick and programs the + * timer hardware for the next tick. + * + */ +void __ipipe_mach_set_dec(unsigned long delay) +{ + unsigned long flags; + if (delay > 8) { + local_irq_save_hw(flags); + *IXP4XX_OSRT1 = delay | ONE_SHOT_ENABLE; + local_irq_restore_hw(flags); + } else { + ipipe_trigger_irq(IRQ_IXP4XX_TIMER1); + } +} + +EXPORT_SYMBOL(__ipipe_mach_set_dec); + +/* + * This returns the number of clock ticks remaining. + */ +unsigned long __ipipe_mach_get_dec(void) +{ + return(*IXP4XX_OST1); /* remaining */ +} + +EXPORT_SYMBOL(__ipipe_mach_get_dec); + +void __ipipe_mach_release_timer(void) +{ + __ipipe_mach_set_dec(__ipipe_mach_ticks_per_jiffy); +} + +EXPORT_SYMBOL(__ipipe_mach_release_timer); + +#endif /* CONFIG_IPIPE */ diff --git a/include/asm-arm/arch-ixp4xx/irqs.h b/include/asm-arm/arch-ixp4xx/irqs.h index f24b763..04609bd 100644 --- a/include/asm-arm/arch-ixp4xx/irqs.h +++ b/include/asm-arm/arch-ixp4xx/irqs.h @@ -70,6 +70,10 @@ #define XSCALE_PMU_IRQ (IRQ_IXP4XX_XSCALE_PMU) +#ifdef CONFIG_IPIPE +#define __ipipe_mach_irq_mux_p(irq) 0 /* We have no cascaded interrupts. */ +#endif + /* * IXDP425 board IRQs */ _______________________________________________ Adeos-main mailing list [email protected] https://mail.gna.org/listinfo/adeos-main
