Hi,
this is the new version of patch support for AT91SAM9261.
To use it:
- take a vanilla linux
- apply the I-pipe patch
- apply the AT91 patch, then solve the three rejects by hand
- finaly apply this patch
Comment from Gilles are integrated.
As I have no better idea we keep all the ifdef around
AT91_VA_BASE_TCB0 ( in include/asm-arm/arch-at91rm9200/hardware.h)
and around __ipipe_mach_irq_mux_p ( in
include/asm-arm/arch-at91rm9200/irqs.h )
Latency under load are running on AT91SAM9261-EK board, we will send
the histogramm later this afternoon.
--
Gregory CLEMENT
Adeneo
2, chemin du Ruisseau - BP21
69136 Ecully Cedex
France
Tel : +33-4 72 18 08 40
diff -aurdpbB -X nodiff linux-2.6.19.at91/arch/arm/mach-at91rm9200/at91sam9261.c linux-2.6.19.patched/arch/arm/mach-at91rm9200/at91sam9261.c
--- linux-2.6.19.at91/arch/arm/mach-at91rm9200/at91sam9261.c 2007-04-10 08:04:00.000000000 +0200
+++ linux-2.6.19.patched/arch/arm/mach-at91rm9200/at91sam9261.c 2007-04-18 13:51:16.000000000 +0200
@@ -27,6 +27,13 @@ static struct map_desc at91sam9261_io_de
.length = SZ_16K,
.type = MT_DEVICE,
}, {
+#ifdef CONFIG_IPIPE
+ .virtual = AT91_VA_BASE_TCB0,
+ .pfn = __phys_to_pfn(AT91SAM9261_BASE_TCB0),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+#endif /* CONFIG_IPIPE */
.virtual = AT91_IO_VIRT_BASE - AT91SAM9261_SRAM_SIZE,
.pfn = __phys_to_pfn(AT91SAM9261_SRAM_BASE),
.length = AT91SAM9261_SRAM_SIZE,
@@ -242,6 +249,7 @@ void __init at91sam9261_initialize(unsig
* The default interrupt priority levels (0 = lowest, 7 = highest).
*/
static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
+#ifndef CONFIG_IPIPE
7, /* Advanced Interrupt Controller */
7, /* System Peripherals */
0, /* Parallel IO Controller A */
@@ -274,6 +282,42 @@ static unsigned int at91sam9261_default_
0, /* Advanced Interrupt Controller */
0, /* Advanced Interrupt Controller */
0, /* Advanced Interrupt Controller */
+#else /* CONFIG_IPIPE */
+/* Give the highest priority to TC, since they are used as timer interrupt by
+ I-pipe. */
+ 7, /* Advanced Interrupt Controller */
+ 7, /* System Peripherals */
+ 0, /* Parallel IO Controller A */
+ 0, /* Parallel IO Controller B */
+ 0, /* Parallel IO Controller C */
+ 0,
+ 6, /* USART 0 */
+ 6, /* USART 1 */
+ 6, /* USART 2 */
+ 0, /* Multimedia Card Interface */
+ 4, /* USB Device Port */
+ 0, /* Two-Wire Interface */
+ 6, /* Serial Peripheral Interface 0 */
+ 6, /* Serial Peripheral Interface 1 */
+ 5, /* Serial Synchronous Controller 0 */
+ 5, /* Serial Synchronous Controller 1 */
+ 5, /* Serial Synchronous Controller 2 */
+ 7, /* Timer Counter 0 */
+ 7, /* Timer Counter 1 */
+ 7, /* Timer Counter 2 */
+ 3, /* USB Host port */
+ 3, /* LCD Controller */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* Advanced Interrupt Controller */
+ 0, /* Advanced Interrupt Controller */
+ 0, /* Advanced Interrupt Controller */
+#endif /*CONFIG_IPIPE */
};
void __init at91sam9261_init_interrupts(unsigned int priority[NR_AIC_IRQS])
diff -aurdpbB -X nodiff linux-2.6.19.at91/arch/arm/mach-at91rm9200/at91sam926x_time.c linux-2.6.19.patched/arch/arm/mach-at91rm9200/at91sam926x_time.c
--- linux-2.6.19.at91/arch/arm/mach-at91rm9200/at91sam926x_time.c 2007-04-10 08:04:00.000000000 +0200
+++ linux-2.6.19.patched/arch/arm/mach-at91rm9200/at91sam926x_time.c 2007-04-18 13:51:16.000000000 +0200
@@ -22,10 +22,69 @@
#include <asm/arch/at91_pit.h>
+static unsigned long last_crtr;
+
+#ifdef CONFIG_IPIPE
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/module.h>
+#include <asm/arch/at91sam9261.h>
+#include <asm/arch/at91_tc.h>
+#include "clock.h"
+
+#ifdef CONFIG_NO_IDLE_HZ
+#error "dynamic tick timer not yet supported with IPIPE"
+#endif /* CONFIG_NO_IDLE_HZ */
+
+#define TCNXCNS(timer,v) ((v) << ((timer)<<1))
+#define AT91_TC_REG_MASK (0xffff)
+
+#if (CONFIG_IPIPE_AT91_TC==0)
+# define KERNEL_TIMER_IRQ_NUM AT91SAM9261_ID_TC0
+#elif (CONFIG_IPIPE_AT91_TC==1)
+# define KERNEL_TIMER_IRQ_NUM AT91SAM9261_ID_TC1
+#elif (CONFIG_IPIPE_AT91_TC==2)
+# define KERNEL_TIMER_IRQ_NUM AT91SAM9261_ID_TC2
+#else
+#error IPIPE_AT91_TC must be 0, 1 or 2.
+#endif
+
+static inline unsigned int at91_tc_read(unsigned int reg_offset)
+{
+ unsigned long addr =
+ (AT91_VA_BASE_TCB0 + 0x40 * CONFIG_IPIPE_AT91_TC);
+
+ return readl((void __iomem *)(addr + reg_offset));
+}
+
+static inline void at91_tc_write(unsigned int reg_offset, unsigned long value)
+{
+ unsigned long addr =
+ (AT91_VA_BASE_TCB0 + 0x40 * CONFIG_IPIPE_AT91_TC);
+
+ writel(value, (void __iomem *)(addr + reg_offset));
+}
+
+#define read_CV() at91_tc_read(AT91_TC_CV)
+#define read_RC() at91_tc_read(AT91_TC_RC)
+#define write_RC(value) at91_tc_write(AT91_TC_RC, value)
+
+int __ipipe_mach_timerint = KERNEL_TIMER_IRQ_NUM;
+EXPORT_SYMBOL(__ipipe_mach_timerint);
+
+int __ipipe_mach_timerstolen = 0;
+EXPORT_SYMBOL(__ipipe_mach_timerstolen);
+
+unsigned int __ipipe_mach_ticks_per_jiffy = LATCH;
+EXPORT_SYMBOL(__ipipe_mach_ticks_per_jiffy);
+
+static int at91_timer_initialized;
+#endif /* CONFIG_IPIPE */
#define PIT_CPIV(x) ((x) & AT91_PIT_CPIV)
#define PIT_PICNT(x) (((x) & AT91_PIT_PICNT) >> 20)
+#ifndef CONFIG_IPIPE
/*
* Returns number of microseconds since last timer interrupt. Note that interrupts
* will have been disabled by do_gettimeofday()
@@ -112,3 +171,209 @@ struct sys_timer at91sam926x_timer = {
.resume = at91sam926x_timer_reset,
};
+#else /* CONFIG_IPIPE */
+
+/*
+ * Returns number of microseconds since last timer interrupt. Note that interrupts
+ * will have been disabled by do_gettimeofday()
+ * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
+* 'tick' is usecs per jiffy (linux/timex.h).
+ */
+static unsigned long at91sam926x_gettimeoffset(void)
+{
+ unsigned long elapsed;
+
+ elapsed = (read_CV() - last_crtr) & AT91_TC_REG_MASK;
+
+ return (unsigned long) (elapsed * (tick_nsec / 1000)) / LATCH;
+}
+
+void __ipipe_mach_acktimer(void)
+{
+ at91_tc_read(AT91_TC_SR);
+}
+
+/*
+ * IRQ handler for the timer.
+ */
+static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
+{
+ /*
+ * - 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)
+ * - if some other domain has taken over the timer, then do nothing
+ * (ipipe has acked it, and the other domain has reprogramed it)
+ */
+
+ write_seqlock(&xtime_lock);
+
+ if (__ipipe_mach_timerstolen) {
+ timer_tick();
+ last_crtr = (last_crtr + LATCH) & AT91_TC_REG_MASK;
+ } else {
+ while (((read_CV() - last_crtr) & AT91_TC_REG_MASK) >= LATCH) {
+ timer_tick();
+ last_crtr = (last_crtr + LATCH) & AT91_TC_REG_MASK;
+ }
+ write_RC((last_crtr + LATCH) & AT91_TC_REG_MASK);
+ }
+
+ write_sequnlock(&xtime_lock);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t at91sam926x_bad_freq(int irq, void *dev_id)
+{
+ static int ticks = 0;
+
+ if (++ticks != HZ * 120) {
+ if (!console_drivers || try_acquire_console_sem())
+ return at91sam926x_timer_interrupt(irq, dev_id);
+
+ release_console_sem();
+ }
+
+ panic("AT91 clock rate incorrectly set.\n"
+ "Please recompile with IPIPE_AT91_MCK set to %lu Hz.",
+ clk_get_rate(clk_get(NULL, "mck")));
+}
+
+notrace unsigned long long __ipipe_mach_get_tsc(void)
+{
+ if (likely(at91_timer_initialized)) {
+ static union {
+#ifdef __BIG_ENDIAN
+ struct {
+ unsigned long high;
+ unsigned short mid;
+ unsigned short low;
+ };
+#else /* __LITTLE_ENDIAN */
+ struct {
+ unsigned short low;
+ unsigned short mid;
+ unsigned long high;
+ };
+#endif /* __LITTLE_ENDIAN */
+ unsigned long long full;
+ } tsc[NR_CPUS], *local_tsc;
+ unsigned long long result;
+ unsigned short stamp;
+ unsigned long flags;
+
+ local_irq_save_hw(flags);
+ local_tsc = &tsc[ipipe_processor_id()];
+ stamp = read_CV();
+ if (unlikely(stamp < local_tsc->low)) {
+ if (unlikely(!++local_tsc->mid))
+ /* 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
+ */
+
+void __ipipe_mach_set_dec(unsigned long delay)
+{
+ unsigned long flags;
+
+ if (delay > 2) {
+ local_irq_save_hw(flags);
+ write_RC((read_CV() + delay) & AT91_TC_REG_MASK);
+ local_irq_restore_hw(flags);
+ } else
+ ipipe_trigger_irq(KERNEL_TIMER_IRQ_NUM);
+}
+EXPORT_SYMBOL(__ipipe_mach_set_dec);
+
+void __ipipe_mach_release_timer(void)
+{
+ __ipipe_mach_set_dec(__ipipe_mach_ticks_per_jiffy);
+}
+EXPORT_SYMBOL(__ipipe_mach_release_timer);
+
+unsigned long __ipipe_mach_get_dec(void)
+{
+ return (read_RC() - read_CV()) & AT91_TC_REG_MASK;
+}
+
+static struct irqaction at91sam926x_timer_irq = {
+ .name = "at91_tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .handler = &at91sam926x_timer_interrupt
+};
+
+static char clk_name [] = "tc%";
+
+static struct clk tc = {
+ .name = (const char *) clk_name,
+ .users = 0,
+ .type = CLK_TYPE_PERIPHERAL,
+ .pmc_mask = 1 << (KERNEL_TIMER_IRQ_NUM),
+};
+
+void __init at91sam926x_timer_init(void)
+{
+ unsigned long v;
+
+ if (clk_get_rate(clk_get(NULL, "mck")) != CONFIG_IPIPE_AT91_MCK)
+ at91sam926x_timer_irq.handler = &at91sam926x_bad_freq;
+
+ snprintf(clk_name, sizeof(clk_name), "tc%d", CONFIG_IPIPE_AT91_TC);
+ clk_register(&tc);
+ clk_enable(&tc);
+
+ /* No Sync. */
+ at91_tc_write(AT91_TC_BCR, 0);
+
+ /* program NO signal on XCN */
+ v = readl((void __iomem *) (AT91_VA_BASE_TCB0 + AT91_TC_BMR));
+ v &= ~TCNXCNS(CONFIG_IPIPE_AT91_TC, 3);
+ v |= TCNXCNS(CONFIG_IPIPE_AT91_TC, 1); /* AT91_TC_TCNXCNS_NONE */
+ writel(v, (void __iomem *) (AT91_VA_BASE_TCB0 + AT91_TC_BMR));
+
+ /* Disable the channel */
+ at91_tc_write(AT91_TC_CCR, AT91_TC_CLKDIS);
+
+ /* Select TIMER_CLOCK3 (MCLK/32) as input frequency for TC. */
+ at91_tc_write(AT91_TC_CMR, AT91_TC_TIMER_CLOCK3);
+
+ /* Disable all interrupts. */
+ at91_tc_write(AT91_TC_IDR, ~0ul);
+
+ /* Load the TC register C. */
+ last_crtr = 0;
+ write_RC(LATCH);
+
+ /* Enable CPCS interrupt. */
+ at91_tc_write(AT91_TC_IER, AT91_TC_CPCS);
+
+ /* Set up the interrupt. */
+ setup_irq(KERNEL_TIMER_IRQ_NUM, &at91sam926x_timer_irq);
+
+ /* Enable the channel. */
+ at91_tc_write(AT91_TC_CCR, AT91_TC_CLKEN | AT91_TC_SWTRG);
+
+ at91_timer_initialized = 1;
+}
+
+struct sys_timer at91sam926x_timer = {
+ .init = at91sam926x_timer_init,
+ .offset = at91sam926x_gettimeoffset,
+ .suspend = NULL,
+ .resume = NULL,
+};
+#endif /* CONFIG_IPIPE */
diff -aurdpbB -X nodiff linux-2.6.19.at91/arch/arm/mach-at91rm9200/Kconfig linux-2.6.19.patched/arch/arm/mach-at91rm9200/Kconfig
--- linux-2.6.19.at91/arch/arm/mach-at91rm9200/Kconfig 2007-04-20 14:39:20.000000000 +0200
+++ linux-2.6.19.patched/arch/arm/mach-at91rm9200/Kconfig 2007-04-18 13:53:42.000000000 +0200
@@ -84,24 +84,6 @@ config MACH_KAFA
help
Select this if you are using Sperry-Sun's KAFA board.
-config IPIPE_AT91_TC
- depends on IPIPE
- int "AT91 TC used as time base"
- default 0
- help
- When Adeos interrupt pipeline is enabled, TC0 is used by default
- as time base, but you can use TC1 or TC2 by setting this variable to 1
- or 2. This should only be needed to avoid conflicts with other drivers.
-
-config IPIPE_AT91_MCK
- depends on IPIPE
- int "AT91 Master clock Frequency"
- default 46080000
- help
- When Adeos interrupt pipeline is enabled, AT91 timer is based on
- the AT91 master clock, whose frequency need hence to be known at
- compilation time.
-
endif
# ----------------------------------------------------------
@@ -136,6 +118,38 @@ endif
# ----------------------------------------------------------
+if ARCH_AT91
+
+comment "Ipipe dependent"
+
+config IPIPE_AT91_TC
+ depends on IPIPE
+ int "AT91 TC used as time base"
+ default 0
+ help
+ When Adeos interrupt pipeline is enabled, TC0 is used by default
+ as time base, but you can use TC1 or TC2 by setting this variable to 1
+ or 2. This should only be needed to avoid conflicts with other drivers.
+ At the moment, Adeos/I-Pipe has only been implemented for AT91RM9200 and
+ AT91SAM9261 processors.
+
+config IPIPE_AT91_MCK
+ depends on IPIPE
+ int "AT91 Master clock Frequency"
+ default 59904000 if MACH_AT91RM9200EK
+ default 99328000 if MACH_AT91SAM9261EK
+ default 53000000
+ help
+ When Adeos interrupt pipeline is enabled, AT91 timer is based on
+ the AT91 master clock, whose frequency need hence to be known at
+ compilation time.
+ At the moment, Adeos/I-Pipe has only been implemented for AT91RM9200 and
+ AT91SAM9261 processors.
+
+endif
+
+# ----------------------------------------------------------
+
comment "AT91 Board Options"
config MTD_AT91_DATAFLASH_CARD
Seulement dans linux-2.6.19.patched/include/asm-arm: arch
diff -aurdpbB -X nodiff linux-2.6.19.at91/include/asm-arm/arch-at91rm9200/hardware.h linux-2.6.19.patched/include/asm-arm/arch-at91rm9200/hardware.h
--- linux-2.6.19.at91/include/asm-arm/arch-at91rm9200/hardware.h 2007-04-20 14:44:01.000000000 +0200
+++ linux-2.6.19.patched/include/asm-arm/arch-at91rm9200/hardware.h 2007-04-18 13:54:48.000000000 +0200
@@ -43,8 +43,17 @@
*/
#define AT91_VA_BASE_SYS AT91_IO_P2V(AT91_BASE_SYS)
#define AT91_VA_BASE_EMAC AT91_IO_P2V(AT91RM9200_BASE_EMAC)
+
#ifdef CONFIG_IPIPE
-#define AT91_VA_BASE_TCB0 AT91_IO_P2V(AT91RM9200_BASE_TCB0)
+#if defined(CONFIG_ARCH_AT91RM9200)
+ #define AT91_VA_BASE_TCB0 AT91_IO_P2V(AT91RM9200_BASE_TCB0)
+#elif defined(CONFIG_ARCH_AT91SAM9260)
+ #define AT91_VA_BASE_TCB0 AT91_IO_P2V(AT91SAM9260_BASE_TCB0)
+#elif defined(CONFIG_ARCH_AT91SAM9261)
+ #define AT91_VA_BASE_TCB0 AT91_IO_P2V(AT91SAM9261_BASE_TCB0)
+#else
+#error "Unsupported AT91 processor"
+#endif
#endif /* CONFIG_IPIPE */
/* Internal SRAM is mapped below the IO devices */
diff -aurdpbB -X nodiff linux-2.6.19.at91/include/asm-arm/arch-at91rm9200/irqs.h linux-2.6.19.patched/include/asm-arm/arch-at91rm9200/irqs.h
--- linux-2.6.19.at91/include/asm-arm/arch-at91rm9200/irqs.h 2007-04-20 14:39:20.000000000 +0200
+++ linux-2.6.19.patched/include/asm-arm/arch-at91rm9200/irqs.h 2007-04-18 13:51:16.000000000 +0200
@@ -44,8 +44,19 @@
#if defined(CONFIG_IPIPE) && !defined(__ASSEMBLY__)
extern unsigned __ipipe_at91_gpio_banks;
-#define __ipipe_mach_irq_mux_p(irq) \
+#if defined(CONFIG_ARCH_AT91RM9200)
+ #define __ipipe_mach_irq_mux_p(irq) \
((unsigned) (irq - AT91RM9200_ID_PIOA) < __ipipe_at91_gpio_banks)
+#elif defined(CONFIG_ARCH_AT91SAM9260)
+ #define __ipipe_mach_irq_mux_p(irq) \
+ ((unsigned) (irq - AT91SAM9260_ID_PIOA) < __ipipe_at91_gpio_banks)
+#elif defined(CONFIG_ARCH_AT91SAM9261)
+ #define __ipipe_mach_irq_mux_p(irq) \
+ ((unsigned) (irq - AT91SAM9261_ID_PIOA) < __ipipe_at91_gpio_banks)
+#else
+#error "Unsupported AT91 processor"
+#endif
+
#endif /* CONFIG_IPIPE && !__ASSEMBLY__ */
diff -aurdpbB -X nodiff linux-2.6.19.at91/include/asm-arm/arch-at91rm9200/timex.h linux-2.6.19.patched/include/asm-arm/arch-at91rm9200/timex.h
--- linux-2.6.19.at91/include/asm-arm/arch-at91rm9200/timex.h 2007-04-20 14:39:20.000000000 +0200
+++ linux-2.6.19.patched/include/asm-arm/arch-at91rm9200/timex.h 2007-04-18 14:55:16.000000000 +0200
@@ -23,19 +23,23 @@
#include <asm/hardware.h>
+#ifndef CONFIG_IPIPE
+
#if defined(CONFIG_ARCH_AT91RM9200)
-#ifndef CONFIG_IPIPE
#define CLOCK_TICK_RATE (AT91_SLOW_CLOCK)
-#else /* !CONFIG_IPIPE */
-#define CLOCK_TICK_RATE (CONFIG_IPIPE_AT91_MCK / 32)
-#endif /* !CONFIG_IPIPE */
#elif defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9261)
#define AT91SAM9_MASTER_CLOCK 99300000
#define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16)
-#endif
+#endif /* arch specific */
+
+#else /* !CONFIG_IPIPE */
+
+#define CLOCK_TICK_RATE (CONFIG_IPIPE_AT91_MCK / 32)
+
+#endif /* !CONFIG_IPIPE */
#endif
_______________________________________________
Adeos-main mailing list
[email protected]
https://mail.gna.org/listinfo/adeos-main