* [Xenomai-core] [PATCH] Adeos support for IXP4xx
@ 2007-04-17 6:02 Richard Cochran
2007-04-17 17:48 ` [Xenomai-core] [Adeos-main] " Gilles Chanteperdrix
0 siblings, 1 reply; 8+ messages in thread
From: Richard Cochran @ 2007-04-17 6:02 UTC (permalink / raw)
To: adeos-main; +Cc: xenomai
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
*/
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Xenomai-core] [Adeos-main] [PATCH] Adeos support for IXP4xx
2007-04-17 6:02 [Xenomai-core] [PATCH] Adeos support for IXP4xx Richard Cochran
@ 2007-04-17 17:48 ` Gilles Chanteperdrix
2007-04-17 17:58 ` Gilles Chanteperdrix
2007-04-18 5:21 ` Richard Cochran
0 siblings, 2 replies; 8+ messages in thread
From: Gilles Chanteperdrix @ 2007-04-17 17:48 UTC (permalink / raw)
To: Richard Cochran; +Cc: adeos-main, xenomai
Richard Cochran wrote:
> 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.
Great.
> +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;
> +}
For reasons explained on the wiki, I would rather see
ixp4xx_timer_interrupt implemented as:
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)
*/
timer_tick();
last_jiffy_time += LATCH;
} 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)
*/
while ((long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) {
timer_tick();
last_jiffy_time += LATCH;
}
*IXP4XX_OSRT1 = LATCH | ONE_SHOT_ENABLE;
}
> +void __ipipe_mach_set_dec(unsigned long delay)
> +{
> + unsigned long flags;
> + if (delay > 8) {
Why 8 ? It looks suspiciously like you just copied the PXA code.
--
Gilles Chanteperdrix.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Xenomai-core] [Adeos-main] [PATCH] Adeos support for IXP4xx
2007-04-17 17:48 ` [Xenomai-core] [Adeos-main] " Gilles Chanteperdrix
@ 2007-04-17 17:58 ` Gilles Chanteperdrix
2007-04-18 5:58 ` Richard Cochran
2007-04-18 5:21 ` Richard Cochran
1 sibling, 1 reply; 8+ messages in thread
From: Gilles Chanteperdrix @ 2007-04-17 17:58 UTC (permalink / raw)
To: Richard Cochran, adeos-main, xenomai
Gilles Chanteperdrix wrote:
> *IXP4XX_OSRT1 = LATCH | ONE_SHOT_ENABLE;
In fact, should not this be:
*IXP4XX_OSRT1 =
(last_jiffy_time + LATCH - *IXP4XX_OSTS) | ONE_SHOT_ENABLE;
?
--
Gilles Chanteperdrix.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Xenomai-core] [Adeos-main] [PATCH] Adeos support for IXP4xx
2007-04-17 17:48 ` [Xenomai-core] [Adeos-main] " Gilles Chanteperdrix
2007-04-17 17:58 ` Gilles Chanteperdrix
@ 2007-04-18 5:21 ` Richard Cochran
2007-04-18 7:53 ` Gilles Chanteperdrix
1 sibling, 1 reply; 8+ messages in thread
From: Richard Cochran @ 2007-04-18 5:21 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: adeos-main, xenomai
> -----Original Message----- From: Gilles Chanteperdrix
>
> For reasons explained on the wiki, I would rather see
> ixp4xx_timer_interrupt implemented as:
>
> 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)
> */
> timer_tick();
> last_jiffy_time += LATCH;
Okay, I see. This comment, which I copied from other ARM code, is
misleading. In general, Linux cannot be sure that the "other domain"
will never lose interrupts. If there is only one other domain, and
that domain is Xenomai, then we trust it.
Even if Xenomai never loses a timer interrupt, is there some harm in
leaving the loop in?
IMHO, it makes the code more clear to leave the loop, since:
1. You see the connection to the unmodified Linux ISR.
2. The reason for _not_ looping is "invisible" knowledge.
> Why 8 ? It looks suspiciously like you just copied the PXA code.
Yes, indeed, it is copied. I put the question back to you: why 8 in
the PXA code?
If I know what 8 means, then I can put the right value for the
IXP4xx ;^)
(Probably this 8 really should be expressed as a macro-ized time
value)
Richard
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Xenomai-core] [Adeos-main] [PATCH] Adeos support for IXP4xx
2007-04-17 17:58 ` Gilles Chanteperdrix
@ 2007-04-18 5:58 ` Richard Cochran
2007-04-18 7:45 ` Gilles Chanteperdrix
0 siblings, 1 reply; 8+ messages in thread
From: Richard Cochran @ 2007-04-18 5:58 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: adeos-main, xenomai
> -----Original Message----- From: Gilles Chanteperdrix
>> *IXP4XX_OSRT1 = LATCH | ONE_SHOT_ENABLE;
>
> In fact, should not this be:
>
> *IXP4XX_OSRT1 =
> (last_jiffy_time + LATCH - *IXP4XX_OSTS) |
ONE_SHOT_ENABLE;
Nope, we are using GP Timer 1. It counts down from the dialed value and
then stops. It is _not_ a free running timer.
Richard
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Xenomai-core] [Adeos-main] [PATCH] Adeos support for IXP4xx
2007-04-18 5:58 ` Richard Cochran
@ 2007-04-18 7:45 ` Gilles Chanteperdrix
0 siblings, 0 replies; 8+ messages in thread
From: Gilles Chanteperdrix @ 2007-04-18 7:45 UTC (permalink / raw)
To: Richard Cochran; +Cc: adeos-main, xenomai
Richard Cochran wrote:
> > -----Original Message----- From: Gilles Chanteperdrix
> >> *IXP4XX_OSRT1 = LATCH | ONE_SHOT_ENABLE;
> >
> > In fact, should not this be:
> >
> > *IXP4XX_OSRT1 =
> > (last_jiffy_time + LATCH - *IXP4XX_OSTS) |
> ONE_SHOT_ENABLE;
>
> Nope, we are using GP Timer 1. It counts down from the dialed value and
> then stops. It is _not_ a free running timer.
I understand, but my point is that if we want the next timer interrupt
to occur at last_jiffy_time + LATCH, we should reprogram the decrementer
with last_jiffy_time + LATCH - *IXP4XX_OSTS to account for the time
which passed since last_jiffy_time.
--
Gilles Chanteperdrix.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Xenomai-core] [Adeos-main] [PATCH] Adeos support for IXP4xx
2007-04-18 5:21 ` Richard Cochran
@ 2007-04-18 7:53 ` Gilles Chanteperdrix
2007-04-18 9:19 ` Richard Cochran
0 siblings, 1 reply; 8+ messages in thread
From: Gilles Chanteperdrix @ 2007-04-18 7:53 UTC (permalink / raw)
To: Richard Cochran; +Cc: adeos-main, xenomai
Richard Cochran wrote:
> > -----Original Message----- From: Gilles Chanteperdrix
> >
> > For reasons explained on the wiki, I would rather see
> > ixp4xx_timer_interrupt implemented as:
> >
> > 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)
> > */
> > timer_tick();
> > last_jiffy_time += LATCH;
>
> Okay, I see. This comment, which I copied from other ARM code, is
> misleading. In general, Linux cannot be sure that the "other domain"
> will never lose interrupts. If there is only one other domain, and
> that domain is Xenomai, then we trust it.
>
> Even if Xenomai never loses a timer interrupt, is there some harm in
> leaving the loop in?
>
> IMHO, it makes the code more clear to leave the loop, since:
>
> 1. You see the connection to the unmodified Linux ISR.
>
> 2. The reason for _not_ looping is "invisible" knowledge.
The reason for not looping is that Adeos never looses interrupts. If we
leave the loop and Linux gets delayed, then the lost ticks will be
accounted for twice: one time because Xenomai will have posted the
missed timer interrupts, one time because of the loop. So, we remove the
loop.
>
> > Why 8 ? It looks suspiciously like you just copied the PXA code.
>
> Yes, indeed, it is copied. I put the question back to you: why 8 in
> the PXA code?
>
> If I know what 8 means, then I can put the right value for the
> IXP4xx ;^)
>
> (Probably this 8 really should be expressed as a macro-ized time
> value)
It's explained in the wiki. The PXA timer does not tick if programmed
with too short delays. To see if IXP4XX has the same problem, remove the
"if" and run latency with a tight period, so that the timer is
reprogrammed with short delays. If latency misteriously hangs, then you
have the same problem as PXA, and you should look for the minimum delay
by trial and errors.
--
Gilles Chanteperdrix.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Xenomai-core] [Adeos-main] [PATCH] Adeos support for IXP4xx
2007-04-18 7:53 ` Gilles Chanteperdrix
@ 2007-04-18 9:19 ` Richard Cochran
0 siblings, 0 replies; 8+ messages in thread
From: Richard Cochran @ 2007-04-18 9:19 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: adeos-main, xenomai
> -----Original Message----- From: Gilles Chanteperdrix
>
> The reason for not looping is that Adeos never looses interrupts. If
> we leave the loop and Linux gets delayed, then the lost ticks will
> be accounted for twice: one time because Xenomai will have posted
> the missed timer interrupts, one time because of the loop. So, we
> remove the loop.
Got it.
I'll post a new patch today with your corrections.
> It's explained in the wiki. The PXA timer does not tick if
> programmed with too short delays. To see if IXP4XX has the same
> problem, remove the "if" and run latency with a tight period, so
> that the timer is reprogrammed with short delays. If latency
> misteriously hangs, then you have the same problem as PXA, and you
> should look for the minimum delay by trial and errors.
AFAICT, the only hardware minimum would be 4 ticks (60 nanoseconds at
66.66 MHz), because you cannot set the two low order bits in the
reload register. However, since the ISR requires at least a few
microseconds, perhaps we should set some sanity value, like 5 usec.
Thanks,
Richard
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2007-04-18 9:19 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-17 6:02 [Xenomai-core] [PATCH] Adeos support for IXP4xx Richard Cochran
2007-04-17 17:48 ` [Xenomai-core] [Adeos-main] " Gilles Chanteperdrix
2007-04-17 17:58 ` Gilles Chanteperdrix
2007-04-18 5:58 ` Richard Cochran
2007-04-18 7:45 ` Gilles Chanteperdrix
2007-04-18 5:21 ` Richard Cochran
2007-04-18 7:53 ` Gilles Chanteperdrix
2007-04-18 9:19 ` Richard Cochran
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.