All of lore.kernel.org
 help / color / mirror / Atom feed
* [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

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.