* [Xenomai-help] Patch to support ARM_MV
@ 2009-11-17 2:27 Sergey Didenko
2009-11-17 8:52 ` Gilles Chanteperdrix
0 siblings, 1 reply; 4+ messages in thread
From: Sergey Didenko @ 2009-11-17 2:27 UTC (permalink / raw)
To: xenomai, Gilles Chanteperdrix
[-- Attachment #1.1: Type: text/plain, Size: 174 bytes --]
Hello
This is a patch which includes the changes for xenomai-2.4.10 release,
required to support the ARM based targets controlled by plat-orion timer,
irq and gpio.
Sergey
[-- Attachment #1.2: Type: text/html, Size: 190 bytes --]
[-- Attachment #2: mv_orion_patch --]
[-- Type: application/octet-stream, Size: 9240 bytes --]
diff -Naur /home/d.sergey/original/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/gpio.c /home/d.sergey/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/gpio.c
--- /home/d.sergey/original/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/gpio.c 2009-06-17 13:25:07.000000000 +0900
+++ /home/d.sergey/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/gpio.c 2009-11-16 15:46:11.000000000 +0900
@@ -17,7 +17,7 @@
#include <linux/io.h>
#include <asm/gpio.h>
-static DEFINE_SPINLOCK(gpio_lock);
+static IPIPE_DEFINE_SPINLOCK(gpio_lock);
static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
static struct gpio_chip orion_chip;
static int orion_irq_gpio_start;
@@ -218,9 +218,18 @@
int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK;
u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
- u32 u = readl(reg);
+#ifdef CONFIG_IPIPE
+ u32 u;
+ unsigned long flags;
+
+ local_irq_save_hw(flags);
+#endif
+ u = readl(reg);
u &= ~(1 << (pin & 31));
writel(u, reg);
+#ifdef CONFIG_IPIPE
+ local_irq_restore_hw(flags);
+#endif
}
static void gpio_irq_unmask(u32 irq)
@@ -229,9 +238,18 @@
int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK;
u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
- u32 u = readl(reg);
+#ifdef CONFIG_IPIPE
+ u32 u;
+ unsigned long flags;
+
+ local_irq_save_hw(flags);
+#endif
+ u = readl(reg);
u |= 1 << (pin & 31);
writel(u, reg);
+#ifdef CONFIG_IPIPE
+ local_irq_restore_hw(flags);
+#endif
}
static int gpio_irq_set_type(u32 irq, u32 type)
@@ -253,7 +271,11 @@
* Set edge/level type.
*/
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+#ifdef CONFIG_IPIPE
+ desc->handle_irq = handle_level_irq;
+#else
desc->handle_irq = handle_edge_irq;
+#endif
} else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
desc->handle_irq = handle_level_irq;
} else {
@@ -328,6 +350,37 @@
}
}
+#ifdef CONFIG_IPIPE
+
+void __ipipe_mach_demux_irq(unsigned pinoff, struct pt_regs *regs)
+{
+ u32 cause;
+ int pin;
+
+ cause = readl(GPIO_DATA_IN(pinoff)) & readl(GPIO_LEVEL_MASK(pinoff));
+ cause |= readl(GPIO_EDGE_CAUSE(pinoff)) & readl(GPIO_EDGE_MASK(pinoff));
+
+ for (pin = pinoff; pin < pinoff + 8; pin++) {
+ int irq = pin + orion_irq_gpio_start;
+ struct irq_desc *desc = irq_desc + irq;
+
+ if (!(cause & (1 << (pin & 31))))
+ continue;
+
+ if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+ /* Swap polarity (race with GPIO line) */
+ u32 polarity;
+
+ polarity = readl(GPIO_IN_POL(pin));
+ polarity ^= 1 << (pin & 31);
+ writel(polarity, GPIO_IN_POL(pin));
+ }
+ desc_handle_irq(irq, regs); //ipipe_handle_irq(irq, regs);
+ }
+}
+
+#endif /* CONFIG_IPIPE */
+
int __init orion_gpio_init(int irq_gpio_start)
{
orion_chip.direction_input = orion_gpio_direction_input;
diff -Naur /home/d.sergey/original/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/include/plat/irq.h /home/d.sergey/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/include/plat/irq.h
--- /home/d.sergey/original/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/include/plat/irq.h 2009-06-17 13:25:07.000000000 +0900
+++ /home/d.sergey/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/include/plat/irq.h 2009-11-13 13:50:46.000000000 +0900
@@ -13,5 +13,12 @@
void orion_irq_init(unsigned int irq_start, void __iomem *maskaddr);
+#ifdef CONFIG_IPIPE
+#ifdef CONFIG_ARCH_MV88F6290
+#define __ipipe_mach_irq_mux_p(irq) \
+ ((unsigned)((irq) - IRQ_MV88F6290_GPIO7_0) <= \
+ IRQ_MV88F6290_GPIO31_24 - IRQ_MV88F6290_GPIO7_0)
+#endif
+#endif /* CONFIG_IPIPE */
#endif
diff -Naur /home/d.sergey/original/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/time.c /home/d.sergey/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/time.c
--- /home/d.sergey/original/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/time.c 2009-06-17 13:25:07.000000000 +0900
+++ /home/d.sergey/kernel/linux-2.6.29-v02.00.29/arch/arm/plat-orion/time.c 2009-11-16 15:43:18.000000000 +0900
@@ -18,25 +18,155 @@
#include <asm/mach/time.h>
#include <mach/hardware.h>
+#ifdef CONFIG_IPIPE
+
+#ifdef CONFIG_NO_IDLE_HZ
+#error "dynamic tick timer not yet supported with IPIPE"
+#endif /* CONFIG_NO_IDLE_HZ */
+
+#define TIMER_CTRL (TIMER_VIRT_BASE + 0x0000)
+#define TIMER0_EN 0x0001
+#define TIMER0_RELOAD_EN 0x0002
+#define TIMER1_EN 0x0004
+#define TIMER1_RELOAD_EN 0x0008
+#define TIMER0_RELOAD (TIMER_VIRT_BASE + 0x0010)
+#define TIMER0_VAL (TIMER_VIRT_BASE + 0x0014)
+#define TIMER1_RELOAD (TIMER_VIRT_BASE + 0x0018)
+#define TIMER1_VAL (TIMER_VIRT_BASE + 0x001c)
+
+int __ipipe_mach_timerint;
+EXPORT_SYMBOL(__ipipe_mach_timerint);
+
+int __ipipe_mach_timerstolen;
+EXPORT_SYMBOL(__ipipe_mach_timerstolen);
+
+unsigned int __ipipe_mach_ticks_per_jiffy;
+EXPORT_SYMBOL(__ipipe_mach_ticks_per_jiffy);
+
+static int orion_timer_initialized;
+
/*
* Number of timer ticks per jiffy.
*/
static u32 ticks_per_jiffy;
+union tsc_reg {
+#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;
+};
+
+static union tsc_reg *tsc;
+
+void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info)
+{
+ info->type = IPIPE_TSC_TYPE_FREERUNNING;
+ /*
+ * FIXME: Won't work as is: need countdown timer abstraction
+ * in Xenomai/ARM userland.
+ */
+ info->u.fr.counter = (unsigned *)TIMER0_VAL;
+ info->u.fr.mask = 0xffffffff;
+ info->u.fr.tsc = &tsc->full;
+}
+
+void __ipipe_mach_acktimer(void)
+{
+ writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+}
+
+static void ipipe_mach_update_tsc(void)
+{
+ unsigned long stamp, flags;
+ union tsc_reg *local_tsc;
+
+ if (unlikely(!orion_timer_initialized))
+ return;
+
+ local_irq_save_hw(flags);
+ local_tsc = &tsc[ipipe_processor_id()];
+ stamp = 0xffffffff - readl(TIMER0_VAL);
+ if (unlikely(stamp < local_tsc->low))
+ /* 32 bit counter wrapped, increment high word. */
+ local_tsc->high++;
+ local_tsc->low = stamp;
+ local_irq_restore_hw(flags);
+}
+
+notrace unsigned long long __ipipe_mach_get_tsc(void)
+{
+ union tsc_reg *local_tsc, result;
+ unsigned long stamp;
+
+ if (unlikely(!orion_timer_initialized))
+ return 0;
+
+ local_tsc = &tsc[ipipe_processor_id()];
+
+ __asm__ ("ldmia %1, %M0\n" :
+ "=r"(result.full) : "r"(local_tsc), "m"(*local_tsc));
+ barrier();
+ stamp = 0xffffffff - readl(TIMER0_VAL);
+ if (unlikely(stamp < result.low))
+ /* 32 bit counter wrapped, increment high word. */
+ result.high++;
+ result.low = stamp;
+
+ return result.full;
+}
+EXPORT_SYMBOL(__ipipe_mach_get_tsc);
+
/*
- * Timer block registers.
+ * Reprogram the timer
*/
-#define TIMER_CTRL (TIMER_VIRT_BASE + 0x0000)
-#define TIMER0_EN 0x0001
-#define TIMER0_RELOAD_EN 0x0002
-#define TIMER1_EN 0x0004
-#define TIMER1_RELOAD_EN 0x0008
-#define TIMER0_RELOAD (TIMER_VIRT_BASE + 0x0010)
-#define TIMER0_VAL (TIMER_VIRT_BASE + 0x0014)
-#define TIMER1_RELOAD (TIMER_VIRT_BASE + 0x0018)
-#define TIMER1_VAL (TIMER_VIRT_BASE + 0x001c)
+void __ipipe_mach_set_dec(unsigned long delay)
+{
+ u32 u;
+ if (delay <= 3) {
+ ipipe_trigger_irq(__ipipe_mach_timerint);
+ return;
+ }
+
+ /*
+ * Clear and enable clockevent timer interrupt.
+ */
+ writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+
+ u = readl(BRIDGE_MASK);
+ u |= BRIDGE_INT_TIMER1;
+ writel(u, BRIDGE_MASK);
+
+ /*
+ * Setup new clockevent timer value.
+ */
+ writel(delay, TIMER1_VAL);
+
+ /*
+ * Enable the timer.
+ */
+ u = readl(TIMER_CTRL);
+ u = (u & ~TIMER1_RELOAD_EN) | TIMER1_EN;
+ writel(u, TIMER_CTRL);
+}
+EXPORT_SYMBOL(__ipipe_mach_set_dec);
+
+unsigned long __ipipe_mach_get_dec(void)
+{
+ return readl(TIMER0_VAL);
+}
+
+#endif /* CONFIG_IPIPE */
/*
* Clocksource handling.
@@ -153,12 +283,23 @@
.set_mode = orion_clkevt_mode,
};
+#ifdef CONFIG_IPIPE
+int __ipipe_check_tickdev(const char *devname)
+{
+ return !strcmp(devname, orion_clkevt.name);
+}
+#endif
+
static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
{
/*
* ACK timer interrupt and call event handler.
*/
+#ifndef CONFIG_IPIPE
writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+#else /* CONFIG_IPIPE */
+ ipipe_mach_update_tsc();
+#endif
orion_clkevt.event_handler(&orion_clkevt);
return IRQ_HANDLED;
@@ -170,6 +311,17 @@
.handler = orion_timer_interrupt
};
+#ifdef CONFIG_IPIPE
+void __ipipe_mach_release_timer(void)
+{
+ struct clock_event_device *ckdev = &orion_clkevt;
+ ckdev->set_mode(ckdev->mode, ckdev);
+ if (ckdev->mode == CLOCK_EVT_MODE_ONESHOT)
+ ckdev->set_next_event(__ipipe_mach_ticks_per_jiffy, ckdev);
+}
+EXPORT_SYMBOL(__ipipe_mach_release_timer);
+#endif
+
void __init orion_time_init(unsigned int irq, unsigned int tclk)
{
u32 u;
@@ -191,6 +343,13 @@
clocksource_register(&orion_clksrc);
+#ifdef CONFIG_IPIPE
+ __ipipe_mach_timerint = irq;
+ __ipipe_mach_ticks_per_jiffy = ticks_per_jiffy;
+ tsc = (union tsc_reg *) __ipipe_tsc_area;
+ barrier();
+ orion_timer_initialized = 1;
+#endif /* CONFIG_IPIPE */
/*
* Setup clockevent timer (interrupt-driven.)
*/
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [Xenomai-help] Patch to support ARM_MV
2009-11-17 2:27 [Xenomai-help] Patch to support ARM_MV Sergey Didenko
@ 2009-11-17 8:52 ` Gilles Chanteperdrix
2009-11-19 5:31 ` Sergey Didenko
[not found] ` <1f3e02580911182130v4872251eic97a99cf81a449e2@domain.hid>
0 siblings, 2 replies; 4+ messages in thread
From: Gilles Chanteperdrix @ 2009-11-17 8:52 UTC (permalink / raw)
To: Sergey Didenko; +Cc: xenomai
Sergey Didenko wrote:
> Hello
>
> This is a patch which includes the changes for xenomai-2.4.10 release,
> required to support the ARM based targets controlled by plat-orion timer,
> irq and gpio.
Ok. In __ipipe_mach_demux_irq, you must call ipipe_handle_irq, not
desc_handle_irq. ipipe_mach_get_tscinfo also needs fixing (type should
be IPIPE_TSC_TYPE_FREERUNNING_COUNTDOWN, and counter should be set to
timer0's physical address, not virtual address, and if you do that, you
can remove the FIXME comment).
--
Gilles.
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [Xenomai-help] Patch to support ARM_MV
2009-11-17 8:52 ` Gilles Chanteperdrix
@ 2009-11-19 5:31 ` Sergey Didenko
[not found] ` <1f3e02580911182130v4872251eic97a99cf81a449e2@domain.hid>
1 sibling, 0 replies; 4+ messages in thread
From: Sergey Didenko @ 2009-11-19 5:31 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai
[-- Attachment #1: Type: text/plain, Size: 666 bytes --]
>
> In __ipipe_mach_demux_irq, you must call ipipe_handle_irq, not
> desc_handle_irq.
I hope you mean __ipipe_handle_irq
ipipe_mach_get_tscinfo also needs fixing (type should be
> IPIPE_TSC_TYPE_FREERUNNING_COUNTDOWN,
file ipipe.h (arch\arm\include\asm) has next defines
#define IPIPE_TSC_TYPE_NONE 0
#define IPIPE_TSC_TYPE_FREERUNNING 1
#define IPIPE_TSC_TYPE_DECREMENTER 2
Do you mean i have to use IPIPE_TSC_TYPE_DECREMENTER or I have to define
IPIPE_TSC_TYPE_FREERUNNING_COUNTDOWN as 3 and use it?
> and counter should be set to timer0's physical address, not virtual address
Ok, for my board it is same...naming problem, not an issue...
Sergey
[-- Attachment #2: Type: text/html, Size: 1277 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread[parent not found: <1f3e02580911182130v4872251eic97a99cf81a449e2@domain.hid>]
* Re: [Xenomai-help] Patch to support ARM_MV
[not found] ` <1f3e02580911182130v4872251eic97a99cf81a449e2@domain.hid>
@ 2009-11-22 17:06 ` Gilles Chanteperdrix
0 siblings, 0 replies; 4+ messages in thread
From: Gilles Chanteperdrix @ 2009-11-22 17:06 UTC (permalink / raw)
To: Sergey Didenko
Sergey Didenko wrote:
>> In __ipipe_mach_demux_irq, you must call ipipe_handle_irq, not
>> desc_handle_irq.
>
>
> I hope you mean __ipipe_handle_irq
Yes.
>
> ipipe_mach_get_tscinfo also needs fixing (type should be
>> IPIPE_TSC_TYPE_FREERUNNING_COUNTDOWN,
>
>
> file ipipe.h (arch\arm\include\asm) has next defines
>
> #define IPIPE_TSC_TYPE_NONE 0
> #define IPIPE_TSC_TYPE_FREERUNNING 1
> #define IPIPE_TSC_TYPE_DECREMENTER 2
>
> you mean i have to use IPIPE_TSC_TYPE_DECREMENTER or I have to define
> IPIPE_TSC_TYPE_FREERUNNING_COUNTDOWN as 3 and use it?
Yes, please do that.
>
>
>> and counter should be set to timer0's physical address, not virtual address
>
> Ok, for my board it is same...naming problem
That is a bit surprising, did you test the user-space tsc emulation?
--
Gilles.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-11-22 17:06 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-17 2:27 [Xenomai-help] Patch to support ARM_MV Sergey Didenko
2009-11-17 8:52 ` Gilles Chanteperdrix
2009-11-19 5:31 ` Sergey Didenko
[not found] ` <1f3e02580911182130v4872251eic97a99cf81a449e2@domain.hid>
2009-11-22 17:06 ` Gilles Chanteperdrix
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.