linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
@ 2006-11-01 20:27 Nicolas DET
  2006-11-01 22:05 ` Dale Farnsworth
  2006-11-01 22:12 ` Benjamin Herrenschmidt
  0 siblings, 2 replies; 27+ messages in thread
From: Nicolas DET @ 2006-11-01 20:27 UTC (permalink / raw)
  To: linuxppc-dev, benh, sl, linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 286 bytes --]

This patch add MPC52xx Interrupt controller for ARCH=powerpc.

It includes the main code in arch/powerpc/sysdev/ ad well as an header 
file in include/asm-powerpc.

PS: I did not success to properly inline the file using thrunderbird.

Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>





[-- Attachment #2: archpowerpc_mpc52x.patch --]
[-- Type: text/plain, Size: 24485 bytes --]

--- a/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-11-01 21:16:40.000000000 +0100
@@ -0,0 +1,566 @@
+/*
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx.
+ * 
+ * Copyright (C) 2006 bplan GmbH
+ * 
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/mpc52xx.h>
+
+/*
+ *
+*/
+
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_sdma __iomem *sdma;
+static struct irq_host *mpc52xx_irqhost = NULL;
+
+static unsigned char mpc52xx_map_senses[4] = {
+	IRQ_TYPE_LEVEL_HIGH,
+	IRQ_TYPE_EDGE_FALLING,
+	IRQ_TYPE_EDGE_RISING,
+	IRQ_TYPE_LEVEL_LOW,
+};
+
+/*
+ *
+*/
+
+static inline void io_be_setbit(u32 __iomem *addr, int bitno)
+{
+	out_be32(addr, in_be32(addr) | (1 << bitno) );
+}
+
+static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
+{
+	out_be32(addr, in_be32(addr) & ~(1 << bitno));
+}
+
+static inline struct device_node *find_mpc52xx_picnode(void)
+{
+	return of_find_compatible_node(NULL, "interrupt-controller",
+				       "mpc5200-pic");
+}
+
+static inline struct device_node *find_mpc52xx_sdmanode(void)
+{
+	return of_find_compatible_node(NULL, "dma-controller",
+				       "mpc5200-bestcomm");
+}
+
+/*
+ * Critial interrupt irq_chip
+*/
+static void mpc52xx_crit_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x, l2=%d\n", __func__, irq, l2irq);
+
+	BUG_ON(l2irq != 0);
+
+	io_be_clrbit(&intr->ctrl, 11);
+}
+
+static void mpc52xx_crit_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	BUG_ON(l2irq != 0);
+
+	io_be_setbit(&intr->ctrl, 11);
+}
+
+static void mpc52xx_crit_ack(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	BUG_ON(l2irq != 0);
+
+	io_be_setbit(&intr->ctrl, 27);
+}
+
+static struct irq_chip mpc52xx_crit_irqchip = {
+	.typename = "MPC52xx IRQ0",
+	.mask = mpc52xx_crit_mask,
+	.unmask = mpc52xx_crit_unmask,
+	.ack = mpc52xx_crit_ack,
+};
+
+/*
+ * IRQ[1-3] interrupt irq_chip
+*/
+
+static void mpc52xx_mainirq_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_mainirq_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_mainirq_ack(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->ctrl, 27-l2irq);
+}
+
+static struct irq_chip mpc52xx_mainirq_irqchip = {
+	.typename = " MPC52xx IRQ[1-3] ",
+	.mask = mpc52xx_mainirq_mask,
+	.unmask = mpc52xx_mainirq_unmask,
+	.ack = mpc52xx_mainirq_ack,
+};
+
+/*
+ * Main interrupt irq_chip
+*/
+
+static void mpc52xx_main_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->main_mask, 15 - l2irq);
+}
+
+static void mpc52xx_main_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->main_mask, 15 - l2irq);
+}
+
+static struct irq_chip mpc52xx_main_irqchip = {
+	.typename = "MPC52xx Main",
+	.mask = mpc52xx_main_mask,
+	.mask_ack = mpc52xx_main_mask,
+	.unmask = mpc52xx_main_unmask,
+};
+
+/*
+ * Peripherals interrupt irq_chip
+*/
+
+static void mpc52xx_periph_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->per_mask, 31 - l2irq);
+}
+
+static void mpc52xx_periph_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->per_mask, 31 - l2irq);
+}
+
+static struct irq_chip mpc52xx_periph_irqchip = {
+	.typename = "MPC52xx Peripherals",
+	.mask = mpc52xx_periph_mask,
+	.mask_ack = mpc52xx_periph_mask,
+	.unmask = mpc52xx_periph_unmask,
+};
+
+/*
+ * SDMA interrupt irq_chip
+*/
+
+static void mpc52xx_sdma_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_ack(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	out_be32(&sdma->IntPend, 1 << l2irq);
+}
+
+static struct irq_chip mpc52xx_sdma_irqchip = {
+	.typename = "MPC52xx SDMA",
+	.mask = mpc52xx_sdma_mask,
+	.unmask = mpc52xx_sdma_unmask,
+	.ack = mpc52xx_sdma_ack,
+};
+
+/*
+ * irq_host
+*/
+
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+	pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_picnode(), node);
+	return mpc52xx_irqhost->host_data == node;
+}
+
+static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
+				 u32 * intspec, unsigned int intsize,
+				 irq_hw_number_t * out_hwirq,
+				 unsigned int *out_flags)
+{
+	int intrvect_l1;
+	int intrvect_l2;
+	int intrvect_type;
+	int intrvect_linux;
+
+	if (intsize != 3)
+		return -1;
+
+	intrvect_l1 = (int)intspec[0];
+	intrvect_l2 = (int)intspec[1];
+	intrvect_type = (int)intspec[2];
+
+	intrvect_linux =
+	    (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
+	intrvect_linux |=
+	    (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
+
+	pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
+		 intrvect_l2);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = mpc52xx_map_senses[intrvect_type];
+
+	return 0;
+}
+
+/*
+ * this function retrieves the correct IRQ type out
+ * of the MPC regs
+ * Only externals IRQs needs this
+*/
+static int mpc52xx_irqx_gettype(int irq)
+{
+	int type;
+	u32 ctrl_reg;
+
+	ctrl_reg = in_be32(&intr->ctrl);
+	type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
+
+	return mpc52xx_map_senses[type];
+}
+
+static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+			       irq_hw_number_t irq)
+{
+	int l1irq;
+	int l2irq;
+	struct irq_chip *good_irqchip;
+	void *good_handle;
+	int type;
+
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	/*
+	 * Most of ours IRQs will be level low
+	 * Only external IRQs on some platform may be others
+	 */
+	type = IRQ_TYPE_LEVEL_LOW;
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
+
+		BUG_ON(l2irq != 0);
+
+		type = mpc52xx_irqx_gettype(l2irq);
+		good_irqchip = &mpc52xx_crit_irqchip;
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
+
+		if ((l2irq >= 0) && (l2irq <= 3)) {
+			type = mpc52xx_irqx_gettype(l2irq);
+			good_irqchip = &mpc52xx_mainirq_irqchip;
+		} else {
+			good_irqchip = &mpc52xx_main_irqchip;
+		}
+		break;
+
+	case MPC52xx_IRQ_L1_PERP:
+		pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
+		good_irqchip = &mpc52xx_periph_irqchip;
+		break;
+
+	case MPC52xx_IRQ_L1_SDMA:
+		pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
+		good_irqchip = &mpc52xx_sdma_irqchip;
+		break;
+
+	default:
+		pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq);
+		printk(KERN_ERR "Unknow IRQ!\n");
+		return -EINVAL;
+	}
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_FALLING:
+	case IRQ_TYPE_EDGE_RISING:
+		good_handle = handle_edge_irq;
+		break;
+	default:
+		good_handle = handle_level_irq;
+	}
+
+	set_irq_chip_and_handler(virq, good_irqchip, good_handle);
+
+	pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
+		 (int)irq, type);
+
+	return 0;
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+	.match = mpc52xx_irqhost_match,
+	.xlate = mpc52xx_irqhost_xlate,
+	.map = mpc52xx_irqhost_map,
+};
+
+/*
+ * init (public)
+*/
+
+void __init mpc52xx_init_irq(void)
+{
+	struct device_node *picnode;
+	int picnode_regsize;
+	u32 picnode_regoffset;
+
+	struct device_node *sdmanode;
+	int sdmanode_regsize;
+	u32 sdmanode_regoffset;
+
+	u64 size64;
+	int flags;
+
+	u32 intr_ctrl;
+
+	picnode = find_mpc52xx_picnode();
+	sdmanode = find_mpc52xx_sdmanode();
+
+	if ( (picnode == NULL) || (sdmanode == NULL) )
+		return;
+
+	/* Retrieve PIC ressources */
+	picnode_regoffset = (u32) of_get_address(picnode, 0, &size64, &flags);
+	if (picnode_regoffset == 0)
+		return ;
+
+	picnode_regoffset = of_translate_address(picnode, (u32 *) picnode_regoffset);
+	picnode_regsize = (int)size64;	
+
+	/* Retrieve SDMA ressources */
+	sdmanode_regoffset = (u32) of_get_address(sdmanode, 0, &size64, &flags);
+	if (sdmanode_regoffset == 0)
+		return ;
+
+	sdmanode_regoffset = of_translate_address(sdmanode, (u32 *) sdmanode_regoffset);
+	sdmanode_regsize = (int)size64;
+
+	/* Remap the necessary zones */
+	intr = ioremap(picnode_regoffset, picnode_regsize);
+	sdma = ioremap(sdmanode_regoffset, sdmanode_regsize);
+
+	if ((intr == NULL) || (sdma == NULL))
+		panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+	printk(KERN_INFO "Remapped MPC52xx PIC at 0x%8.8x\n", picnode_regoffset);
+	printk(KERN_INFO "Remapped MPC52xx SDMA at 0x%8.8x\n", sdmanode_regoffset);
+
+	of_node_put(picnode);
+	of_node_put(sdmanode);
+
+	/* Disable all interrupt sources. */
+	out_be32(&sdma->IntPend, 0xffffffff);	/* 1 means clear pending */
+	out_be32(&sdma->IntMask, 0xffffffff);	/* 1 means disabled */
+	out_be32(&intr->per_mask, 0x7ffffc00);	/* 1 means disabled */
+	out_be32(&intr->main_mask, 0x00010fff);	/* 1 means disabled */
+	intr_ctrl = in_be32(&intr->ctrl);
+	intr_ctrl &= 0x00ff0000;	/* Keeps IRQ[0-3] config */
+	intr_ctrl |= 0x0f000000 |	/* clear IRQ 0-3 */
+	    0x00001000 |	/* MEE master external enable */
+	    0x00000000 |	/* 0 means disable IRQ 0-3 */
+	    0x00000001;		/* CEb route critical normally */
+	out_be32(&intr->ctrl, intr_ctrl);
+
+	/* Zero a bunch of the priority settings.  */
+	out_be32(&intr->per_pri1, 0);
+	out_be32(&intr->per_pri2, 0);
+	out_be32(&intr->per_pri3, 0);
+	out_be32(&intr->main_pri1, 0);
+	out_be32(&intr->main_pri2, 0);
+
+	/*
+	 * As last step, add an irq host to translate the real
+	 * hw irq information provided by the ofw to linux virq
+	 */
+
+	mpc52xx_irqhost =
+	    irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTVIRQ,
+			   &mpc52xx_irqhost_ops, -1);
+
+	if (mpc52xx_irqhost)
+		mpc52xx_irqhost->host_data = picnode;
+}
+
+/*
+ * get_irq (public)
+*/
+unsigned int mpc52xx_get_irq(void)
+{
+	u32 status;
+	int irq = NO_IRQ_IGNORE;
+
+	status = in_be32(&intr->enc_status);
+	if (status & 0x00000400) {	/* critical */
+		irq = (status >> 8) & 0x3;
+		if (irq == 2)	/* high priority peripheral */
+			goto peripheral;
+		irq |=
+		    (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
+		    MPC52xx_IRQ_L1_MASK;
+	} else if (status & 0x00200000) {	/* main */
+		irq = (status >> 16) & 0x1f;
+		if (irq == 4)	/* low priority peripheral */
+			goto peripheral;
+		irq |=
+		    (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
+		    MPC52xx_IRQ_L1_MASK;
+	} else if (status & 0x20000000) {	/* peripheral */
+	      peripheral:
+		irq = (status >> 24) & 0x1f;
+		if (irq == 0) {	/* bestcomm */
+			status = in_be32(&sdma->IntPend);
+			irq = ffs(status) - 1;
+			irq |=
+			    (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
+			    MPC52xx_IRQ_L1_MASK;
+		} else
+			irq |=
+			    (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
+			    MPC52xx_IRQ_L1_MASK;
+
+	}
+
+	pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
+		 irq_linear_revmap(mpc52xx_irqhost, irq));
+
+	return irq_linear_revmap(mpc52xx_irqhost, irq);
+}
--- a/arch/powerpc/sysdev/Makefile	2006-11-01 09:18:43.000000000 +0100
+++ b/arch/powerpc/sysdev/Makefile	2006-10-31 19:56:41.000000000 +0100
@@ -13,6 +13,7 @@ obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_PPC_TODC)		+= todc.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
+obj-$(CONFIG_PPC_MPC52xx_PIC)	+= mpc52xx_pic.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
--- a/include/asm-powerpc/mpc52xx.h	1970-01-01 01:00:00.000000000 +0100
+++ b/include/asm-powerpc/mpc52xx.h	2006-11-01 21:18:38.000000000 +0100
@@ -0,0 +1,319 @@
+/*
+ * 
+ * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
+ * May need to be cleaned as the port goes on ...
+ *
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __ASM_POWERPC_MPC52xx_H__
+#define __ASM_POWERPC_MPC52xx_H__
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/prom.h>
+
+#endif				/* __ASSEMBLY__ */
+
+/* ======================================================================== */
+/* Main registers/struct addresses                                          */
+/* ======================================================================== */
+
+/* Registers zone offset/size  */
+#define MPC52xx_MMAP_CTL_OFFSET		0x0000
+#define MPC52xx_MMAP_CTL_SIZE		0x068
+#define MPC52xx_SDRAM_OFFSET		0x0100
+#define MPC52xx_SDRAM_SIZE		0x010
+#define MPC52xx_CDM_OFFSET		0x0200
+#define MPC52xx_CDM_SIZE		0x038
+#define MPC52xx_INTR_OFFSET		0x0500
+#define MPC52xx_INTR_SIZE		0x04c
+#define MPC52xx_GPTx_OFFSET(x)		(0x0600 + ((x)<<4))
+#define MPC52xx_GPT_SIZE		0x010
+#define MPC52xx_RTC_OFFSET		0x0800
+#define MPC52xx_RTC_SIZE		0x024
+#define MPC52xx_GPIO_OFFSET		0x0b00
+#define MPC52xx_GPIO_SIZE		0x040
+#define MPC52xx_GPIO_WKUP_OFFSET	0x0c00
+#define MPC52xx_GPIO_WKUP_SIZE		0x028
+#define MPC52xx_PCI_OFFSET		0x0d00
+#define MPC52xx_PCI_SIZE		0x100
+#define MPC52xx_SDMA_OFFSET		0x1200
+#define MPC52xx_SDMA_SIZE		0x100
+#define MPC52xx_XLB_OFFSET		0x1f00
+#define MPC52xx_XLB_SIZE		0x100
+#define MPC52xx_PSCx_OFFSET(x)		(((x)!=6)?(0x1e00+((x)<<9)):0x2c00)
+#define MPC52xx_PSC_SIZE		0x0a0
+
+/* SRAM used for SDMA */
+#define MPC52xx_SRAM_OFFSET		0x8000
+#define MPC52xx_SRAM_SIZE		0x4000
+
+/* ======================================================================== */
+/* IRQ mapping                                                              */
+/* ======================================================================== */
+
+#define MPC52xx_IRQ_L1_CRIT	(0)
+#define MPC52xx_IRQ_L1_MAIN	(1)
+#define MPC52xx_IRQ_L1_PERP	(2)
+#define MPC52xx_IRQ_L1_SDMA	(3)
+
+#define MPC52xx_IRQ_L1_OFFSET   (6)
+#define MPC52xx_IRQ_L1_MASK     (0x00c0)
+
+#define MPC52xx_IRQ_L2_OFFSET   (0)
+#define MPC52xx_IRQ_L2_MASK     (0x003f)
+
+#define MPC52xx_IRQ_HIGHTESTVIRQ (0xd0)
+
+/* ======================================================================== */
+/* Structures mapping of some unit register set                             */
+/* ======================================================================== */
+
+#ifndef __ASSEMBLY__
+
+/* Memory Mapping Control */
+struct mpc52xx_mmap_ctl {
+	u32 mbar;		/* MMAP_CTRL + 0x00 */
+
+	u32 cs0_start;		/* MMAP_CTRL + 0x04 */
+	u32 cs0_stop;		/* MMAP_CTRL + 0x08 */
+	u32 cs1_start;		/* MMAP_CTRL + 0x0c */
+	u32 cs1_stop;		/* MMAP_CTRL + 0x10 */
+	u32 cs2_start;		/* MMAP_CTRL + 0x14 */
+	u32 cs2_stop;		/* MMAP_CTRL + 0x18 */
+	u32 cs3_start;		/* MMAP_CTRL + 0x1c */
+	u32 cs3_stop;		/* MMAP_CTRL + 0x20 */
+	u32 cs4_start;		/* MMAP_CTRL + 0x24 */
+	u32 cs4_stop;		/* MMAP_CTRL + 0x28 */
+	u32 cs5_start;		/* MMAP_CTRL + 0x2c */
+	u32 cs5_stop;		/* MMAP_CTRL + 0x30 */
+
+	u32 sdram0;		/* MMAP_CTRL + 0x34 */
+	u32 sdram1;		/* MMAP_CTRL + 0X38 */
+
+	u32 reserved[4];	/* MMAP_CTRL + 0x3c .. 0x48 */
+
+	u32 boot_start;		/* MMAP_CTRL + 0x4c */
+	u32 boot_stop;		/* MMAP_CTRL + 0x50 */
+
+	u32 ipbi_ws_ctrl;	/* MMAP_CTRL + 0x54 */
+
+	u32 cs6_start;		/* MMAP_CTRL + 0x58 */
+	u32 cs6_stop;		/* MMAP_CTRL + 0x5c */
+	u32 cs7_start;		/* MMAP_CTRL + 0x60 */
+	u32 cs7_stop;		/* MMAP_CTRL + 0x64 */
+};
+
+/* SDRAM control */
+struct mpc52xx_sdram {
+	u32 mode;		/* SDRAM + 0x00 */
+	u32 ctrl;		/* SDRAM + 0x04 */
+	u32 config1;		/* SDRAM + 0x08 */
+	u32 config2;		/* SDRAM + 0x0c */
+};
+
+/* Interrupt controller */
+struct mpc52xx_intr {
+	u32 per_mask;		/* INTR + 0x00 */
+	u32 per_pri1;		/* INTR + 0x04 */
+	u32 per_pri2;		/* INTR + 0x08 */
+	u32 per_pri3;		/* INTR + 0x0c */
+	u32 ctrl;		/* INTR + 0x10 */
+	u32 main_mask;		/* INTR + 0x14 */
+	u32 main_pri1;		/* INTR + 0x18 */
+	u32 main_pri2;		/* INTR + 0x1c */
+	u32 reserved1;		/* INTR + 0x20 */
+	u32 enc_status;		/* INTR + 0x24 */
+	u32 crit_status;	/* INTR + 0x28 */
+	u32 main_status;	/* INTR + 0x2c */
+	u32 per_status;		/* INTR + 0x30 */
+	u32 reserved2;		/* INTR + 0x34 */
+	u32 per_error;		/* INTR + 0x38 */
+};
+
+/* SDMA */
+struct mpc52xx_sdma {
+	u32 taskBar;		/* SDMA + 0x00 */
+	u32 currentPointer;	/* SDMA + 0x04 */
+	u32 endPointer;		/* SDMA + 0x08 */
+	u32 variablePointer;	/* SDMA + 0x0c */
+
+	u8 IntVect1;		/* SDMA + 0x10 */
+	u8 IntVect2;		/* SDMA + 0x11 */
+	u16 PtdCntrl;		/* SDMA + 0x12 */
+
+	u32 IntPend;		/* SDMA + 0x14 */
+	u32 IntMask;		/* SDMA + 0x18 */
+
+	u16 tcr[16];		/* SDMA + 0x1c .. 0x3a */
+
+	u8 ipr[32];		/* SDMA + 0x3c .. 0x5b */
+
+	u32 cReqSelect;		/* SDMA + 0x5c */
+	u32 task_size0;		/* SDMA + 0x60 */
+	u32 task_size1;		/* SDMA + 0x64 */
+	u32 MDEDebug;		/* SDMA + 0x68 */
+	u32 ADSDebug;		/* SDMA + 0x6c */
+	u32 Value1;		/* SDMA + 0x70 */
+	u32 Value2;		/* SDMA + 0x74 */
+	u32 Control;		/* SDMA + 0x78 */
+	u32 Status;		/* SDMA + 0x7c */
+	u32 PTDDebug;		/* SDMA + 0x80 */
+};
+
+/* GPT */
+struct mpc52xx_gpt {
+	u32 mode;		/* GPTx + 0x00 */
+	u32 count;		/* GPTx + 0x04 */
+	u32 pwm;		/* GPTx + 0x08 */
+	u32 status;		/* GPTx + 0X0c */
+};
+
+/* GPIO */
+struct mpc52xx_gpio {
+	u32 port_config;	/* GPIO + 0x00 */
+	u32 simple_gpioe;	/* GPIO + 0x04 */
+	u32 simple_ode;		/* GPIO + 0x08 */
+	u32 simple_ddr;		/* GPIO + 0x0c */
+	u32 simple_dvo;		/* GPIO + 0x10 */
+	u32 simple_ival;	/* GPIO + 0x14 */
+	u8 outo_gpioe;		/* GPIO + 0x18 */
+	u8 reserved1[3];	/* GPIO + 0x19 */
+	u8 outo_dvo;		/* GPIO + 0x1c */
+	u8 reserved2[3];	/* GPIO + 0x1d */
+	u8 sint_gpioe;		/* GPIO + 0x20 */
+	u8 reserved3[3];	/* GPIO + 0x21 */
+	u8 sint_ode;		/* GPIO + 0x24 */
+	u8 reserved4[3];	/* GPIO + 0x25 */
+	u8 sint_ddr;		/* GPIO + 0x28 */
+	u8 reserved5[3];	/* GPIO + 0x29 */
+	u8 sint_dvo;		/* GPIO + 0x2c */
+	u8 reserved6[3];	/* GPIO + 0x2d */
+	u8 sint_inten;		/* GPIO + 0x30 */
+	u8 reserved7[3];	/* GPIO + 0x31 */
+	u16 sint_itype;		/* GPIO + 0x34 */
+	u16 reserved8;		/* GPIO + 0x36 */
+	u8 gpio_control;	/* GPIO + 0x38 */
+	u8 reserved9[3];	/* GPIO + 0x39 */
+	u8 sint_istat;		/* GPIO + 0x3c */
+	u8 sint_ival;		/* GPIO + 0x3d */
+	u8 bus_errs;		/* GPIO + 0x3e */
+	u8 reserved10;		/* GPIO + 0x3f */
+};
+
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD	4
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD	5
+#define MPC52xx_GPIO_PCI_DIS			(1<<15)
+
+/* GPIO with WakeUp*/
+struct mpc52xx_gpio_wkup {
+	u8 wkup_gpioe;		/* GPIO_WKUP + 0x00 */
+	u8 reserved1[3];	/* GPIO_WKUP + 0x03 */
+	u8 wkup_ode;		/* GPIO_WKUP + 0x04 */
+	u8 reserved2[3];	/* GPIO_WKUP + 0x05 */
+	u8 wkup_ddr;		/* GPIO_WKUP + 0x08 */
+	u8 reserved3[3];	/* GPIO_WKUP + 0x09 */
+	u8 wkup_dvo;		/* GPIO_WKUP + 0x0C */
+	u8 reserved4[3];	/* GPIO_WKUP + 0x0D */
+	u8 wkup_inten;		/* GPIO_WKUP + 0x10 */
+	u8 reserved5[3];	/* GPIO_WKUP + 0x11 */
+	u8 wkup_iinten;		/* GPIO_WKUP + 0x14 */
+	u8 reserved6[3];	/* GPIO_WKUP + 0x15 */
+	u16 wkup_itype;		/* GPIO_WKUP + 0x18 */
+	u8 reserved7[2];	/* GPIO_WKUP + 0x1A */
+	u8 wkup_maste;		/* GPIO_WKUP + 0x1C */
+	u8 reserved8[3];	/* GPIO_WKUP + 0x1D */
+	u8 wkup_ival;		/* GPIO_WKUP + 0x20 */
+	u8 reserved9[3];	/* GPIO_WKUP + 0x21 */
+	u8 wkup_istat;		/* GPIO_WKUP + 0x24 */
+	u8 reserved10[3];	/* GPIO_WKUP + 0x25 */
+};
+
+/* XLB Bus control */
+struct mpc52xx_xlb {
+	u8 reserved[0x40];
+	u32 config;		/* XLB + 0x40 */
+	u32 version;		/* XLB + 0x44 */
+	u32 status;		/* XLB + 0x48 */
+	u32 int_enable;		/* XLB + 0x4c */
+	u32 addr_capture;	/* XLB + 0x50 */
+	u32 bus_sig_capture;	/* XLB + 0x54 */
+	u32 addr_timeout;	/* XLB + 0x58 */
+	u32 data_timeout;	/* XLB + 0x5c */
+	u32 bus_act_timeout;	/* XLB + 0x60 */
+	u32 master_pri_enable;	/* XLB + 0x64 */
+	u32 master_priority;	/* XLB + 0x68 */
+	u32 base_address;	/* XLB + 0x6c */
+	u32 snoop_window;	/* XLB + 0x70 */
+};
+
+#define MPC52xx_XLB_CFG_PLDIS		(1 << 31)
+#define MPC52xx_XLB_CFG_SNOOP		(1 << 15)
+
+/* Clock Distribution control */
+struct mpc52xx_cdm {
+	u32 jtag_id;		/* CDM + 0x00  reg0 read only */
+	u32 rstcfg;		/* CDM + 0x04  reg1 read only */
+	u32 breadcrumb;		/* CDM + 0x08  reg2 */
+
+	u8 mem_clk_sel;		/* CDM + 0x0c  reg3 byte0 */
+	u8 xlb_clk_sel;		/* CDM + 0x0d  reg3 byte1 read only */
+	u8 ipb_clk_sel;		/* CDM + 0x0e  reg3 byte2 */
+	u8 pci_clk_sel;		/* CDM + 0x0f  reg3 byte3 */
+
+	u8 ext_48mhz_en;	/* CDM + 0x10  reg4 byte0 */
+	u8 fd_enable;		/* CDM + 0x11  reg4 byte1 */
+	u16 fd_counters;	/* CDM + 0x12  reg4 byte2,3 */
+
+	u32 clk_enables;	/* CDM + 0x14  reg5 */
+
+	u8 osc_disable;		/* CDM + 0x18  reg6 byte0 */
+	u8 reserved0[3];	/* CDM + 0x19  reg6 byte1,2,3 */
+
+	u8 ccs_sleep_enable;	/* CDM + 0x1c  reg7 byte0 */
+	u8 osc_sleep_enable;	/* CDM + 0x1d  reg7 byte1 */
+	u8 reserved1;		/* CDM + 0x1e  reg7 byte2 */
+	u8 ccs_qreq_test;	/* CDM + 0x1f  reg7 byte3 */
+
+	u8 soft_reset;		/* CDM + 0x20  u8 byte0 */
+	u8 no_ckstp;		/* CDM + 0x21  u8 byte0 */
+	u8 reserved2[2];	/* CDM + 0x22  u8 byte1,2,3 */
+
+	u8 pll_lock;		/* CDM + 0x24  reg9 byte0 */
+	u8 pll_looselock;	/* CDM + 0x25  reg9 byte1 */
+	u8 pll_sm_lockwin;	/* CDM + 0x26  reg9 byte2 */
+	u8 reserved3;		/* CDM + 0x27  reg9 byte3 */
+
+	u16 reserved4;		/* CDM + 0x28  reg10 byte0,1 */
+	u16 mclken_div_psc1;	/* CDM + 0x2a  reg10 byte2,3 */
+
+	u16 reserved5;		/* CDM + 0x2c  reg11 byte0,1 */
+	u16 mclken_div_psc2;	/* CDM + 0x2e  reg11 byte2,3 */
+
+	u16 reserved6;		/* CDM + 0x30  reg12 byte0,1 */
+	u16 mclken_div_psc3;	/* CDM + 0x32  reg12 byte2,3 */
+
+	u16 reserved7;		/* CDM + 0x34  reg13 byte0,1 */
+	u16 mclken_div_psc6;	/* CDM + 0x36  reg13 byte2,3 */
+};
+
+#endif				/* __ASSEMBLY__ */
+
+/* ========================================================================= */
+/* Prototypes for MPC52xx syslib                                             */
+/* ========================================================================= */
+
+#ifndef __ASSEMBLY__
+
+extern void mpc52xx_init_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
+
+#endif				/* __ASSEMBLY__ */
+
+#endif				/* _ASM_POWERPC_MPC52xx_H__ */

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-01 20:27 [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support Nicolas DET
@ 2006-11-01 22:05 ` Dale Farnsworth
  2006-11-01 22:07   ` Sven Luther
  2006-11-01 22:12 ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 27+ messages in thread
From: Dale Farnsworth @ 2006-11-01 22:05 UTC (permalink / raw)
  To: nd, linuxppc-embedded, linuxppc-dev

In article <454902F9.20206@bplan-gmbh.de> Nicolas wrote:
> --- a/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
> +++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-11-01 21:16:40.000000000 +0100
> @@ -0,0 +1,566 @@
> +/*
> + *
> + * Programmable Interrupt Controller functions for the Freescale MPC52xx.
> + * 
> + * Copyright (C) 2006 bplan GmbH
> + * 
> + * This file is licensed under the terms of the GNU General Public License

Once again, please restore the copyright lines you removed from this file.

Dale Farnsworth

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-01 22:05 ` Dale Farnsworth
@ 2006-11-01 22:07   ` Sven Luther
  2006-11-01 22:21     ` Dale Farnsworth
  0 siblings, 1 reply; 27+ messages in thread
From: Sven Luther @ 2006-11-01 22:07 UTC (permalink / raw)
  To: Dale Farnsworth; +Cc: linuxppc-dev, sven, linuxppc-embedded

On Wed, Nov 01, 2006 at 10:05:43PM -0000, Dale Farnsworth wrote:
> In article <454902F9.20206@bplan-gmbh.de> Nicolas wrote:
> > --- a/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
> > +++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-11-01 21:16:40.000000000 +0100
> > @@ -0,0 +1,566 @@
> > +/*
> > + *
> > + * Programmable Interrupt Controller functions for the Freescale MPC52xx.
> > + * 
> > + * Copyright (C) 2006 bplan GmbH
> > + * 
> > + * This file is licensed under the terms of the GNU General Public License
> 
> Once again, please restore the copyright lines you removed from this file.

Hehe, you are aware that, IIRW, someone suggested to cut them earlier in this
thread ? 

Friendly,

Sven Luther

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-01 20:27 [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support Nicolas DET
  2006-11-01 22:05 ` Dale Farnsworth
@ 2006-11-01 22:12 ` Benjamin Herrenschmidt
  2006-11-02 16:27   ` Nicolas DET
  1 sibling, 1 reply; 27+ messages in thread
From: Benjamin Herrenschmidt @ 2006-11-01 22:12 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-dev, Sylvain Munaut, sl, linuxppc-embedded

My only remaining comment is what I said earlier about the way you
divided the interrupt in levels.

In fact, I've finally dug into the doc and found out that the situation
is even less clear :)

The whole point of this division is to avoid special cases and properly
deal with the separation in different HW registers. We have basically 4
register sets controlling irqs:

 - intr->ctrl
 - intr->main_mask
 - intr->per_mask
 - sdma (different device)

Now, your current setup ends up defining a "level" and 5 irq_chips !!!

 - intr->ctrl bit 11 has it's own chip
 - intr->ctrl other bits or intr->main_mask (2 different chips)
 - intr->per_mask a chip 
 - sdma a chip

which seems to totally gross since the first one is basically "main" irq
0, and has no reason whatsoever to be kept separate from "main". Which
would give us something much more sensible with 4 levels and 4 chips:

 - intr->ctrl based interrupts (crit and main, crit being just main 0)
 - intr->main_mask
 - intr->per_mask
 - sdma

In that case, you have a nice 1 level == 1 irq_chip == one register set.

Now, in addition to that, we have another issue I haven't spotted
before, but it might be worth considering:

Do we actually want the sdma interrupts handled there ? Because if you
look closely, the SDMA is basically a cascaded interrupt controller. It
hangs of per interrupt 0 :)

Thus we could simply remove the code for it from that driver and
implement it as as separate controller with a separate interrupt domain.
I know you won't like that idea because it means having a different
interrupt tree but it's worth having the discussion.

Ben.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-01 22:07   ` Sven Luther
@ 2006-11-01 22:21     ` Dale Farnsworth
  0 siblings, 0 replies; 27+ messages in thread
From: Dale Farnsworth @ 2006-11-01 22:21 UTC (permalink / raw)
  To: Sven Luther; +Cc: linuxppc-embedded, linuxppc-dev

On Wed, Nov 01, 2006 at 11:07:08PM +0100, Sven Luther wrote:
> On Wed, Nov 01, 2006 at 10:05:43PM -0000, Dale Farnsworth wrote:
> > In article <454902F9.20206@bplan-gmbh.de> Nicolas wrote:
> > > --- a/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
> > > +++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-11-01 21:16:40.000000000 +0100
> > > @@ -0,0 +1,566 @@
> > > +/*
> > > + *
> > > + * Programmable Interrupt Controller functions for the Freescale MPC52xx.
> > > + * 
> > > + * Copyright (C) 2006 bplan GmbH
> > > + * 
> > > + * This file is licensed under the terms of the GNU General Public License
> > 
> > Once again, please restore the copyright lines you removed from this file.
> 
> Hehe, you are aware that, IIRW, someone suggested to cut them earlier in this
> thread ? 

I think people called for removing the "Maintained by" and the
changelog-like commentary, but not the copyrights.

-Dale

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-01 22:12 ` Benjamin Herrenschmidt
@ 2006-11-02 16:27   ` Nicolas DET
  2006-11-02 20:47     ` Nicolas DET
  0 siblings, 1 reply; 27+ messages in thread
From: Nicolas DET @ 2006-11-02 16:27 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev, Sylvain Munaut, sl, linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 974 bytes --]

Benjamin Herrenschmidt wrote:

> Now, in addition to that, we have another issue I haven't spotted
> before, but it might be worth considering:
> 
> Do we actually want the sdma interrupts handled there ? Because if you
> look closely, the SDMA is basically a cascaded interrupt controller. It
> hangs of per interrupt 0 :)

I know. I already spot this point (IRQ as far as I remenber and in 
private mails) and I got no answer so I assumed it was ok like I did. 
It's also really simplier and easier to add SDMA has another irq_chip.
Keep is simple ;-)

> Thus we could simply remove the code for it from that driver and
> implement it as as separate controller with a separate interrupt domain.
> I know you won't like that idea because it means having a different
> interrupt tree but it's worth having the discussion.
> 

The device tree won't change anyway...

I'll submit a new buch of patches pretty soon. Maybe the final version.

"On y est presque !" ;-)

Regards


[-- Attachment #2: nd.vcf --]
[-- Type: text/x-vcard, Size: 249 bytes --]

begin:vcard
fn:Nicolas DET ( bplan GmbH )
n:DET;Nicolas
org:bplan GmbH
adr:;;;;;;Germany
email;internet:nd@bplan-gmbh.de
title:Software Entwicklung
tel;work:+49 6171 9187 - 31
x-mozilla-html:FALSE
url:http://www.bplan-gmbh.de
version:2.1
end:vcard


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-02 16:27   ` Nicolas DET
@ 2006-11-02 20:47     ` Nicolas DET
  2006-11-04 23:35       ` Benjamin Herrenschmidt
  2006-11-06  6:55       ` Grant Likely
  0 siblings, 2 replies; 27+ messages in thread
From: Nicolas DET @ 2006-11-02 20:47 UTC (permalink / raw)
  To: Nicolas DET; +Cc: Sylvain Munaut, sl, linuxppc-embedded, linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 1143 bytes --]

Nicolas DET wrote:
> Benjamin Herrenschmidt wrote:
> 
>> Now, in addition to that, we have another issue I haven't spotted
>> before, but it might be worth considering:
>>
>> Do we actually want the sdma interrupts handled there ? Because if you
>> look closely, the SDMA is basically a cascaded interrupt controller. It
>> hangs of per interrupt 0 :)
> 
> I know. I already spot this point (IRQ as far as I remenber and in 
> private mails) and I got no answer so I assumed it was ok like I did. 
> It's also really simplier and easier to add SDMA has another irq_chip.
> Keep is simple ;-)
> 
>> Thus we could simply remove the code for it from that driver and
>> implement it as as separate controller with a separate interrupt domain.
>> I know you won't like that idea because it means having a different
>> interrupt tree but it's worth having the discussion.
>>
> 
> The device tree won't change anyway...
> 
> I'll submit a new buch of patches pretty soon. Maybe the final version.
> 
> "On y est presque !" ;-)
> 

I attached the new Interrupt Controller patch. I have been very busy 
today. I hope I did not overlook anything.

RFC


[-- Attachment #2: archpowerpc_mpc52x.patch --]
[-- Type: text/plain, Size: 23958 bytes --]

--- a/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-11-02 17:56:10.000000000 +0100
@@ -0,0 +1,515 @@
+/*
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx.
+ *
+ * Based on (well, mostly copied from) the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ * 
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/mpc52xx.h>
+
+/*
+ *
+*/
+
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_sdma __iomem *sdma;
+static struct irq_host *mpc52xx_irqhost = NULL;
+
+static unsigned char mpc52xx_map_senses[4] = {
+	IRQ_TYPE_LEVEL_HIGH,
+	IRQ_TYPE_EDGE_FALLING,
+	IRQ_TYPE_EDGE_RISING,
+	IRQ_TYPE_LEVEL_LOW,
+};
+
+/*
+ *
+*/
+
+static inline void io_be_setbit(u32 __iomem *addr, int bitno)
+{
+	out_be32(addr, in_be32(addr) | (1 << bitno) );
+}
+
+static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
+{
+	out_be32(addr, in_be32(addr) & ~(1 << bitno));
+}
+
+static inline struct device_node *find_mpc52xx_picnode(void)
+{
+	return of_find_compatible_node(NULL, "interrupt-controller",
+				       "mpc5200-pic");
+}
+
+static inline struct device_node *find_mpc52xx_sdmanode(void)
+{
+	return of_find_compatible_node(NULL, "dma-controller",
+				       "mpc5200-bestcomm");
+}
+
+/*
+ * IRQ[0-3] interrupt irq_chip
+*/
+
+static void mpc52xx_extirq_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_ack(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->ctrl, 27-l2irq);
+}
+
+static struct irq_chip mpc52xx_extirq_irqchip = {
+	.typename = " MPC52xx IRQ[0-3] ",
+	.mask = mpc52xx_extirq_mask,
+	.unmask = mpc52xx_extirq_unmask,
+	.ack = mpc52xx_extirq_ack,
+};
+
+/*
+ * Main interrupt irq_chip
+*/
+
+static void mpc52xx_main_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->main_mask, 15 - l2irq);
+}
+
+static void mpc52xx_main_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->main_mask, 15 - l2irq);
+}
+
+static struct irq_chip mpc52xx_main_irqchip = {
+	.typename = "MPC52xx Main",
+	.mask = mpc52xx_main_mask,
+	.mask_ack = mpc52xx_main_mask,
+	.unmask = mpc52xx_main_unmask,
+};
+
+/*
+ * Peripherals interrupt irq_chip
+*/
+
+static void mpc52xx_periph_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->per_mask, 31 - l2irq);
+}
+
+static void mpc52xx_periph_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->per_mask, 31 - l2irq);
+}
+
+static struct irq_chip mpc52xx_periph_irqchip = {
+	.typename = "MPC52xx Peripherals",
+	.mask = mpc52xx_periph_mask,
+	.mask_ack = mpc52xx_periph_mask,
+	.unmask = mpc52xx_periph_unmask,
+};
+
+/*
+ * SDMA interrupt irq_chip
+*/
+
+static void mpc52xx_sdma_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_ack(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	out_be32(&sdma->IntPend, 1 << l2irq);
+}
+
+static struct irq_chip mpc52xx_sdma_irqchip = {
+	.typename = "MPC52xx SDMA",
+	.mask = mpc52xx_sdma_mask,
+	.unmask = mpc52xx_sdma_unmask,
+	.ack = mpc52xx_sdma_ack,
+};
+
+/*
+ * irq_host
+*/
+
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+	pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_picnode(), node);
+	return mpc52xx_irqhost->host_data == node;
+}
+
+static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
+				 u32 * intspec, unsigned int intsize,
+				 irq_hw_number_t * out_hwirq,
+				 unsigned int *out_flags)
+{
+	int intrvect_l1;
+	int intrvect_l2;
+	int intrvect_type;
+	int intrvect_linux;
+
+	if (intsize != 3)
+		return -1;
+
+	intrvect_l1 = (int)intspec[0];
+	intrvect_l2 = (int)intspec[1];
+	intrvect_type = (int)intspec[2];
+
+	intrvect_linux =
+	    (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
+	intrvect_linux |=
+	    (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
+
+	pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
+		 intrvect_l2);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = mpc52xx_map_senses[intrvect_type];
+
+	return 0;
+}
+
+/*
+ * this function retrieves the correct IRQ type out
+ * of the MPC regs
+ * Only externals IRQs needs this
+*/
+static int mpc52xx_irqx_gettype(int irq)
+{
+	int type;
+	u32 ctrl_reg;
+
+	ctrl_reg = in_be32(&intr->ctrl);
+	type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
+
+	return mpc52xx_map_senses[type];
+}
+
+static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+			       irq_hw_number_t irq)
+{
+	int l1irq;
+	int l2irq;
+	struct irq_chip *good_irqchip;
+	void *good_handle;
+	int type;
+
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	/*
+	 * Most of ours IRQs will be level low
+	 * Only external IRQs on some platform may be others
+	 */
+	type = IRQ_TYPE_LEVEL_LOW;
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
+
+		BUG_ON(l2irq != 0);
+
+		type = mpc52xx_irqx_gettype(l2irq);
+		good_irqchip = &mpc52xx_extirq_irqchip;
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
+
+		if ((l2irq >= 1) && (l2irq <= 3)) {
+			type = mpc52xx_irqx_gettype(l2irq);
+			good_irqchip = &mpc52xx_extirq_irqchip;
+		} else {
+			good_irqchip = &mpc52xx_main_irqchip;
+		}
+		break;
+
+	case MPC52xx_IRQ_L1_PERP:
+		pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
+		good_irqchip = &mpc52xx_periph_irqchip;
+		break;
+
+	case MPC52xx_IRQ_L1_SDMA:
+		pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
+		good_irqchip = &mpc52xx_sdma_irqchip;
+		break;
+
+	default:
+		pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq);
+		printk(KERN_ERR "Unknow IRQ!\n");
+		return -EINVAL;
+	}
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_FALLING:
+	case IRQ_TYPE_EDGE_RISING:
+		good_handle = handle_edge_irq;
+		break;
+	default:
+		good_handle = handle_level_irq;
+	}
+
+	set_irq_chip_and_handler(virq, good_irqchip, good_handle);
+
+	pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
+		 (int)irq, type);
+
+	return 0;
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+	.match = mpc52xx_irqhost_match,
+	.xlate = mpc52xx_irqhost_xlate,
+	.map = mpc52xx_irqhost_map,
+};
+
+/*
+ * init (public)
+*/
+
+void __init mpc52xx_init_irq(void)
+{
+	struct device_node *picnode;
+	int picnode_regsize;
+	u32 picnode_regoffset;
+
+	struct device_node *sdmanode;
+	int sdmanode_regsize;
+	u32 sdmanode_regoffset;
+
+	u64 size64;
+	int flags;
+
+	u32 intr_ctrl;
+
+	picnode = find_mpc52xx_picnode();
+	sdmanode = find_mpc52xx_sdmanode();
+
+	if ( (picnode == NULL) || (sdmanode == NULL) )
+		return;
+
+	/* Retrieve PIC ressources */
+	picnode_regoffset = (u32) of_get_address(picnode, 0, &size64, &flags);
+	if (picnode_regoffset == 0)
+		return ;
+
+	picnode_regoffset = of_translate_address(picnode, (u32 *) picnode_regoffset);
+	picnode_regsize = (int)size64;	
+
+	/* Retrieve SDMA ressources */
+	sdmanode_regoffset = (u32) of_get_address(sdmanode, 0, &size64, &flags);
+	if (sdmanode_regoffset == 0)
+		return ;
+
+	sdmanode_regoffset = of_translate_address(sdmanode, (u32 *) sdmanode_regoffset);
+	sdmanode_regsize = (int)size64;
+
+	/* Remap the necessary zones */
+	intr = ioremap(picnode_regoffset, picnode_regsize);
+	sdma = ioremap(sdmanode_regoffset, sdmanode_regsize);
+
+	if ((intr == NULL) || (sdma == NULL))
+		panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+	printk(KERN_INFO "Remapped MPC52xx PIC at 0x%8.8x\n", picnode_regoffset);
+	printk(KERN_INFO "Remapped MPC52xx SDMA at 0x%8.8x\n", sdmanode_regoffset);
+
+	of_node_put(picnode);
+	of_node_put(sdmanode);
+
+	/* Disable all interrupt sources. */
+	out_be32(&sdma->IntPend, 0xffffffff);	/* 1 means clear pending */
+	out_be32(&sdma->IntMask, 0xffffffff);	/* 1 means disabled */
+	out_be32(&intr->per_mask, 0x7ffffc00);	/* 1 means disabled */
+	out_be32(&intr->main_mask, 0x00010fff);	/* 1 means disabled */
+	intr_ctrl = in_be32(&intr->ctrl);
+	intr_ctrl &= 0x00ff0000;	/* Keeps IRQ[0-3] config */
+	intr_ctrl |= 0x0f000000 |	/* clear IRQ 0-3 */
+	    0x00001000 |	/* MEE master external enable */
+	    0x00000000 |	/* 0 means disable IRQ 0-3 */
+	    0x00000001;		/* CEb route critical normally */
+	out_be32(&intr->ctrl, intr_ctrl);
+
+	/* Zero a bunch of the priority settings.  */
+	out_be32(&intr->per_pri1, 0);
+	out_be32(&intr->per_pri2, 0);
+	out_be32(&intr->per_pri3, 0);
+	out_be32(&intr->main_pri1, 0);
+	out_be32(&intr->main_pri2, 0);
+
+	/*
+	 * As last step, add an irq host to translate the real
+	 * hw irq information provided by the ofw to linux virq
+	 */
+
+	mpc52xx_irqhost =
+	    irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTVIRQ,
+			   &mpc52xx_irqhost_ops, -1);
+
+	if (mpc52xx_irqhost)
+		mpc52xx_irqhost->host_data = picnode;
+}
+
+/*
+ * get_irq (public)
+*/
+unsigned int mpc52xx_get_irq(void)
+{
+	u32 status;
+	int irq = NO_IRQ_IGNORE;
+
+	status = in_be32(&intr->enc_status);
+	if (status & 0x00000400) {	/* critical */
+		irq = (status >> 8) & 0x3;
+		if (irq == 2)	/* high priority peripheral */
+			goto peripheral;
+		irq |=
+		    (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
+		    MPC52xx_IRQ_L1_MASK;
+	} else if (status & 0x00200000) {	/* main */
+		irq = (status >> 16) & 0x1f;
+		if (irq == 4)	/* low priority peripheral */
+			goto peripheral;
+		irq |=
+		    (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
+		    MPC52xx_IRQ_L1_MASK;
+	} else if (status & 0x20000000) {	/* peripheral */
+	      peripheral:
+		irq = (status >> 24) & 0x1f;
+		if (irq == 0) {	/* bestcomm */
+			status = in_be32(&sdma->IntPend);
+			irq = ffs(status) - 1;
+			irq |=
+			    (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
+			    MPC52xx_IRQ_L1_MASK;
+		} else
+			irq |=
+			    (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
+			    MPC52xx_IRQ_L1_MASK;
+
+	}
+
+	pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
+		 irq_linear_revmap(mpc52xx_irqhost, irq));
+
+	return irq_linear_revmap(mpc52xx_irqhost, irq);
+}
--- a/arch/powerpc/sysdev/Makefile	2006-11-01 09:18:43.000000000 +0100
+++ b/arch/powerpc/sysdev/Makefile	2006-10-31 19:56:41.000000000 +0100
@@ -13,6 +13,7 @@ obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_PPC_TODC)		+= todc.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
+obj-$(CONFIG_PPC_MPC52xx_PIC)	+= mpc52xx_pic.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
--- a/include/asm-powerpc/mpc52xx.h	1970-01-01 01:00:00.000000000 +0100
+++ b/include/asm-powerpc/mpc52xx.h	2006-11-02 17:54:37.000000000 +0100
@@ -0,0 +1,319 @@
+/*
+ * 
+ * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
+ * May need to be cleaned as the port goes on ...
+ *
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __ASM_POWERPC_MPC52xx_H__
+#define __ASM_POWERPC_MPC52xx_H__
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/prom.h>
+
+#endif				/* __ASSEMBLY__ */
+
+/* ======================================================================== */
+/* Main registers/struct addresses                                          */
+/* ======================================================================== */
+
+/* Registers zone offset/size  */
+#define MPC52xx_MMAP_CTL_OFFSET		0x0000
+#define MPC52xx_MMAP_CTL_SIZE		0x068
+#define MPC52xx_SDRAM_OFFSET		0x0100
+#define MPC52xx_SDRAM_SIZE		0x010
+#define MPC52xx_CDM_OFFSET		0x0200
+#define MPC52xx_CDM_SIZE		0x038
+#define MPC52xx_INTR_OFFSET		0x0500
+#define MPC52xx_INTR_SIZE		0x04c
+#define MPC52xx_GPTx_OFFSET(x)		(0x0600 + ((x)<<4))
+#define MPC52xx_GPT_SIZE		0x010
+#define MPC52xx_RTC_OFFSET		0x0800
+#define MPC52xx_RTC_SIZE		0x024
+#define MPC52xx_GPIO_OFFSET		0x0b00
+#define MPC52xx_GPIO_SIZE		0x040
+#define MPC52xx_GPIO_WKUP_OFFSET	0x0c00
+#define MPC52xx_GPIO_WKUP_SIZE		0x028
+#define MPC52xx_PCI_OFFSET		0x0d00
+#define MPC52xx_PCI_SIZE		0x100
+#define MPC52xx_SDMA_OFFSET		0x1200
+#define MPC52xx_SDMA_SIZE		0x100
+#define MPC52xx_XLB_OFFSET		0x1f00
+#define MPC52xx_XLB_SIZE		0x100
+#define MPC52xx_PSCx_OFFSET(x)		(((x)!=6)?(0x1e00+((x)<<9)):0x2c00)
+#define MPC52xx_PSC_SIZE		0x0a0
+
+/* SRAM used for SDMA */
+#define MPC52xx_SRAM_OFFSET		0x8000
+#define MPC52xx_SRAM_SIZE		0x4000
+
+/* ======================================================================== */
+/* IRQ mapping                                                              */
+/* ======================================================================== */
+
+#define MPC52xx_IRQ_L1_CRIT	(0)
+#define MPC52xx_IRQ_L1_MAIN	(1)
+#define MPC52xx_IRQ_L1_PERP	(2)
+#define MPC52xx_IRQ_L1_SDMA	(3)
+
+#define MPC52xx_IRQ_L1_OFFSET   (6)
+#define MPC52xx_IRQ_L1_MASK     (0x00c0)
+
+#define MPC52xx_IRQ_L2_OFFSET   (0)
+#define MPC52xx_IRQ_L2_MASK     (0x003f)
+
+#define MPC52xx_IRQ_HIGHTESTVIRQ (0xd0)
+
+/* ======================================================================== */
+/* Structures mapping of some unit register set                             */
+/* ======================================================================== */
+
+#ifndef __ASSEMBLY__
+
+/* Memory Mapping Control */
+struct mpc52xx_mmap_ctl {
+	u32 mbar;		/* MMAP_CTRL + 0x00 */
+
+	u32 cs0_start;		/* MMAP_CTRL + 0x04 */
+	u32 cs0_stop;		/* MMAP_CTRL + 0x08 */
+	u32 cs1_start;		/* MMAP_CTRL + 0x0c */
+	u32 cs1_stop;		/* MMAP_CTRL + 0x10 */
+	u32 cs2_start;		/* MMAP_CTRL + 0x14 */
+	u32 cs2_stop;		/* MMAP_CTRL + 0x18 */
+	u32 cs3_start;		/* MMAP_CTRL + 0x1c */
+	u32 cs3_stop;		/* MMAP_CTRL + 0x20 */
+	u32 cs4_start;		/* MMAP_CTRL + 0x24 */
+	u32 cs4_stop;		/* MMAP_CTRL + 0x28 */
+	u32 cs5_start;		/* MMAP_CTRL + 0x2c */
+	u32 cs5_stop;		/* MMAP_CTRL + 0x30 */
+
+	u32 sdram0;		/* MMAP_CTRL + 0x34 */
+	u32 sdram1;		/* MMAP_CTRL + 0X38 */
+
+	u32 reserved[4];	/* MMAP_CTRL + 0x3c .. 0x48 */
+
+	u32 boot_start;		/* MMAP_CTRL + 0x4c */
+	u32 boot_stop;		/* MMAP_CTRL + 0x50 */
+
+	u32 ipbi_ws_ctrl;	/* MMAP_CTRL + 0x54 */
+
+	u32 cs6_start;		/* MMAP_CTRL + 0x58 */
+	u32 cs6_stop;		/* MMAP_CTRL + 0x5c */
+	u32 cs7_start;		/* MMAP_CTRL + 0x60 */
+	u32 cs7_stop;		/* MMAP_CTRL + 0x64 */
+};
+
+/* SDRAM control */
+struct mpc52xx_sdram {
+	u32 mode;		/* SDRAM + 0x00 */
+	u32 ctrl;		/* SDRAM + 0x04 */
+	u32 config1;		/* SDRAM + 0x08 */
+	u32 config2;		/* SDRAM + 0x0c */
+};
+
+/* Interrupt controller */
+struct mpc52xx_intr {
+	u32 per_mask;		/* INTR + 0x00 */
+	u32 per_pri1;		/* INTR + 0x04 */
+	u32 per_pri2;		/* INTR + 0x08 */
+	u32 per_pri3;		/* INTR + 0x0c */
+	u32 ctrl;		/* INTR + 0x10 */
+	u32 main_mask;		/* INTR + 0x14 */
+	u32 main_pri1;		/* INTR + 0x18 */
+	u32 main_pri2;		/* INTR + 0x1c */
+	u32 reserved1;		/* INTR + 0x20 */
+	u32 enc_status;		/* INTR + 0x24 */
+	u32 crit_status;	/* INTR + 0x28 */
+	u32 main_status;	/* INTR + 0x2c */
+	u32 per_status;		/* INTR + 0x30 */
+	u32 reserved2;		/* INTR + 0x34 */
+	u32 per_error;		/* INTR + 0x38 */
+};
+
+/* SDMA */
+struct mpc52xx_sdma {
+	u32 taskBar;		/* SDMA + 0x00 */
+	u32 currentPointer;	/* SDMA + 0x04 */
+	u32 endPointer;		/* SDMA + 0x08 */
+	u32 variablePointer;	/* SDMA + 0x0c */
+
+	u8 IntVect1;		/* SDMA + 0x10 */
+	u8 IntVect2;		/* SDMA + 0x11 */
+	u16 PtdCntrl;		/* SDMA + 0x12 */
+
+	u32 IntPend;		/* SDMA + 0x14 */
+	u32 IntMask;		/* SDMA + 0x18 */
+
+	u16 tcr[16];		/* SDMA + 0x1c .. 0x3a */
+
+	u8 ipr[32];		/* SDMA + 0x3c .. 0x5b */
+
+	u32 cReqSelect;		/* SDMA + 0x5c */
+	u32 task_size0;		/* SDMA + 0x60 */
+	u32 task_size1;		/* SDMA + 0x64 */
+	u32 MDEDebug;		/* SDMA + 0x68 */
+	u32 ADSDebug;		/* SDMA + 0x6c */
+	u32 Value1;		/* SDMA + 0x70 */
+	u32 Value2;		/* SDMA + 0x74 */
+	u32 Control;		/* SDMA + 0x78 */
+	u32 Status;		/* SDMA + 0x7c */
+	u32 PTDDebug;		/* SDMA + 0x80 */
+};
+
+/* GPT */
+struct mpc52xx_gpt {
+	u32 mode;		/* GPTx + 0x00 */
+	u32 count;		/* GPTx + 0x04 */
+	u32 pwm;		/* GPTx + 0x08 */
+	u32 status;		/* GPTx + 0X0c */
+};
+
+/* GPIO */
+struct mpc52xx_gpio {
+	u32 port_config;	/* GPIO + 0x00 */
+	u32 simple_gpioe;	/* GPIO + 0x04 */
+	u32 simple_ode;		/* GPIO + 0x08 */
+	u32 simple_ddr;		/* GPIO + 0x0c */
+	u32 simple_dvo;		/* GPIO + 0x10 */
+	u32 simple_ival;	/* GPIO + 0x14 */
+	u8 outo_gpioe;		/* GPIO + 0x18 */
+	u8 reserved1[3];	/* GPIO + 0x19 */
+	u8 outo_dvo;		/* GPIO + 0x1c */
+	u8 reserved2[3];	/* GPIO + 0x1d */
+	u8 sint_gpioe;		/* GPIO + 0x20 */
+	u8 reserved3[3];	/* GPIO + 0x21 */
+	u8 sint_ode;		/* GPIO + 0x24 */
+	u8 reserved4[3];	/* GPIO + 0x25 */
+	u8 sint_ddr;		/* GPIO + 0x28 */
+	u8 reserved5[3];	/* GPIO + 0x29 */
+	u8 sint_dvo;		/* GPIO + 0x2c */
+	u8 reserved6[3];	/* GPIO + 0x2d */
+	u8 sint_inten;		/* GPIO + 0x30 */
+	u8 reserved7[3];	/* GPIO + 0x31 */
+	u16 sint_itype;		/* GPIO + 0x34 */
+	u16 reserved8;		/* GPIO + 0x36 */
+	u8 gpio_control;	/* GPIO + 0x38 */
+	u8 reserved9[3];	/* GPIO + 0x39 */
+	u8 sint_istat;		/* GPIO + 0x3c */
+	u8 sint_ival;		/* GPIO + 0x3d */
+	u8 bus_errs;		/* GPIO + 0x3e */
+	u8 reserved10;		/* GPIO + 0x3f */
+};
+
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD	4
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD	5
+#define MPC52xx_GPIO_PCI_DIS			(1<<15)
+
+/* GPIO with WakeUp*/
+struct mpc52xx_gpio_wkup {
+	u8 wkup_gpioe;		/* GPIO_WKUP + 0x00 */
+	u8 reserved1[3];	/* GPIO_WKUP + 0x03 */
+	u8 wkup_ode;		/* GPIO_WKUP + 0x04 */
+	u8 reserved2[3];	/* GPIO_WKUP + 0x05 */
+	u8 wkup_ddr;		/* GPIO_WKUP + 0x08 */
+	u8 reserved3[3];	/* GPIO_WKUP + 0x09 */
+	u8 wkup_dvo;		/* GPIO_WKUP + 0x0C */
+	u8 reserved4[3];	/* GPIO_WKUP + 0x0D */
+	u8 wkup_inten;		/* GPIO_WKUP + 0x10 */
+	u8 reserved5[3];	/* GPIO_WKUP + 0x11 */
+	u8 wkup_iinten;		/* GPIO_WKUP + 0x14 */
+	u8 reserved6[3];	/* GPIO_WKUP + 0x15 */
+	u16 wkup_itype;		/* GPIO_WKUP + 0x18 */
+	u8 reserved7[2];	/* GPIO_WKUP + 0x1A */
+	u8 wkup_maste;		/* GPIO_WKUP + 0x1C */
+	u8 reserved8[3];	/* GPIO_WKUP + 0x1D */
+	u8 wkup_ival;		/* GPIO_WKUP + 0x20 */
+	u8 reserved9[3];	/* GPIO_WKUP + 0x21 */
+	u8 wkup_istat;		/* GPIO_WKUP + 0x24 */
+	u8 reserved10[3];	/* GPIO_WKUP + 0x25 */
+};
+
+/* XLB Bus control */
+struct mpc52xx_xlb {
+	u8 reserved[0x40];
+	u32 config;		/* XLB + 0x40 */
+	u32 version;		/* XLB + 0x44 */
+	u32 status;		/* XLB + 0x48 */
+	u32 int_enable;		/* XLB + 0x4c */
+	u32 addr_capture;	/* XLB + 0x50 */
+	u32 bus_sig_capture;	/* XLB + 0x54 */
+	u32 addr_timeout;	/* XLB + 0x58 */
+	u32 data_timeout;	/* XLB + 0x5c */
+	u32 bus_act_timeout;	/* XLB + 0x60 */
+	u32 master_pri_enable;	/* XLB + 0x64 */
+	u32 master_priority;	/* XLB + 0x68 */
+	u32 base_address;	/* XLB + 0x6c */
+	u32 snoop_window;	/* XLB + 0x70 */
+};
+
+#define MPC52xx_XLB_CFG_PLDIS		(1 << 31)
+#define MPC52xx_XLB_CFG_SNOOP		(1 << 15)
+
+/* Clock Distribution control */
+struct mpc52xx_cdm {
+	u32 jtag_id;		/* CDM + 0x00  reg0 read only */
+	u32 rstcfg;		/* CDM + 0x04  reg1 read only */
+	u32 breadcrumb;		/* CDM + 0x08  reg2 */
+
+	u8 mem_clk_sel;		/* CDM + 0x0c  reg3 byte0 */
+	u8 xlb_clk_sel;		/* CDM + 0x0d  reg3 byte1 read only */
+	u8 ipb_clk_sel;		/* CDM + 0x0e  reg3 byte2 */
+	u8 pci_clk_sel;		/* CDM + 0x0f  reg3 byte3 */
+
+	u8 ext_48mhz_en;	/* CDM + 0x10  reg4 byte0 */
+	u8 fd_enable;		/* CDM + 0x11  reg4 byte1 */
+	u16 fd_counters;	/* CDM + 0x12  reg4 byte2,3 */
+
+	u32 clk_enables;	/* CDM + 0x14  reg5 */
+
+	u8 osc_disable;		/* CDM + 0x18  reg6 byte0 */
+	u8 reserved0[3];	/* CDM + 0x19  reg6 byte1,2,3 */
+
+	u8 ccs_sleep_enable;	/* CDM + 0x1c  reg7 byte0 */
+	u8 osc_sleep_enable;	/* CDM + 0x1d  reg7 byte1 */
+	u8 reserved1;		/* CDM + 0x1e  reg7 byte2 */
+	u8 ccs_qreq_test;	/* CDM + 0x1f  reg7 byte3 */
+
+	u8 soft_reset;		/* CDM + 0x20  u8 byte0 */
+	u8 no_ckstp;		/* CDM + 0x21  u8 byte0 */
+	u8 reserved2[2];	/* CDM + 0x22  u8 byte1,2,3 */
+
+	u8 pll_lock;		/* CDM + 0x24  reg9 byte0 */
+	u8 pll_looselock;	/* CDM + 0x25  reg9 byte1 */
+	u8 pll_sm_lockwin;	/* CDM + 0x26  reg9 byte2 */
+	u8 reserved3;		/* CDM + 0x27  reg9 byte3 */
+
+	u16 reserved4;		/* CDM + 0x28  reg10 byte0,1 */
+	u16 mclken_div_psc1;	/* CDM + 0x2a  reg10 byte2,3 */
+
+	u16 reserved5;		/* CDM + 0x2c  reg11 byte0,1 */
+	u16 mclken_div_psc2;	/* CDM + 0x2e  reg11 byte2,3 */
+
+	u16 reserved6;		/* CDM + 0x30  reg12 byte0,1 */
+	u16 mclken_div_psc3;	/* CDM + 0x32  reg12 byte2,3 */
+
+	u16 reserved7;		/* CDM + 0x34  reg13 byte0,1 */
+	u16 mclken_div_psc6;	/* CDM + 0x36  reg13 byte2,3 */
+};
+
+#endif				/* __ASSEMBLY__ */
+
+/* ========================================================================= */
+/* Prototypes for MPC52xx syslib                                             */
+/* ========================================================================= */
+
+#ifndef __ASSEMBLY__
+
+extern void mpc52xx_init_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
+
+#endif				/* __ASSEMBLY__ */
+
+#endif				/* _ASM_POWERPC_MPC52xx_H__ */
--- a/include/asm-ppc/io.h	2006-11-01 09:19:02.000000000 +0100
+++ b/include/asm-ppc/io.h	2006-11-02 18:01:17.000000000 +0100
@@ -26,7 +26,7 @@
 
 #if defined(CONFIG_4xx)
 #include <asm/ibm4xx.h>
-#elif defined(CONFIG_PPC_MPC52xx)
+#elif defined(CONFIG_PPC_MPC52xx) && !defined(CONFIG_PPC_MERGE)
 #include <asm/mpc52xx.h>
 #elif defined(CONFIG_8xx)
 #include <asm/mpc8xx.h>

[-- Attachment #3: nd.vcf --]
[-- Type: text/x-vcard, Size: 249 bytes --]

begin:vcard
fn:Nicolas DET ( bplan GmbH )
n:DET;Nicolas
org:bplan GmbH
adr:;;;;;;Germany
email;internet:nd@bplan-gmbh.de
title:Software Entwicklung
tel;work:+49 6171 9187 - 31
x-mozilla-html:FALSE
url:http://www.bplan-gmbh.de
version:2.1
end:vcard


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-02 20:47     ` Nicolas DET
@ 2006-11-04 23:35       ` Benjamin Herrenschmidt
  2006-11-05  0:27         ` Sylvain Munaut
  2006-11-05 10:17         ` Nicolas DET
  2006-11-06  6:55       ` Grant Likely
  1 sibling, 2 replies; 27+ messages in thread
From: Benjamin Herrenschmidt @ 2006-11-04 23:35 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-dev, Sylvain Munaut, sl, linuxppc-embedded

On Thu, 2006-11-02 at 21:47 +0100, Nicolas DET wrote:

> + *
> + * Programmable Interrupt Controller functions for the Freescale MPC52xx.
> + *
> + * Based on (well, mostly copied from) the code from the 2.4 kernel by
> + * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
> + * 
> + * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
> + * Copyright (C) 2003 Montavista Software, Inc

You did significant changes, you should add your (c) before the "Based
on..." line.

> +	switch (l1irq) {
> +	case MPC52xx_IRQ_L1_CRIT:
> +		pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
> +
> +		BUG_ON(l2irq != 0);
> +
> +		type = mpc52xx_irqx_gettype(l2irq);
> +		good_irqchip = &mpc52xx_extirq_irqchip;
> +		break;
> +
> +	case MPC52xx_IRQ_L1_MAIN:
> +		pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
> +
> +		if ((l2irq >= 1) && (l2irq <= 3)) {
> +			type = mpc52xx_irqx_gettype(l2irq);
> +			good_irqchip = &mpc52xx_extirq_irqchip;
> +		} else {
> +			good_irqchip = &mpc52xx_main_irqchip;
> +		}
> +		break;

You have changed the mapping of L1/L2 but not the device-tree
representation to match them. Which means that you need the ugly hack
above. That is not goot. Fix your device-tree instead and do the same
split in the tree for L1/L2 than you do in the code.

In fact, I'm wondering if it might not be worth going back to 2 cells
and have cell 0 just contain the HW number now that we have sanitized
those... In any way, the above special casing should go.

> +	picnode = find_mpc52xx_picnode();
> +	sdmanode = find_mpc52xx_sdmanode();

Any reason why you have those inline 1-line functions and just not put
the actual of_find_* call in here ?

You probably also need some of_node_put() in the error case. You are
doing a whole bunch of "return" that bypass them.

The rest looks ok.

Please submit the io.h patch separately. Also, you may need to fix the
default case (which is the one we are using) in there to work with
CONFIG_PCI not set (by defining PCI_DRAM_BASE to 0 among others).

> --- a/include/asm-ppc/io.h	2006-11-01 09:19:02.000000000 +0100
> +++ b/include/asm-ppc/io.h	2006-11-02 18:01:17.000000000 +0100
> @@ -26,7 +26,7 @@
>  
>  #if defined(CONFIG_4xx)
>  #include <asm/ibm4xx.h>
> -#elif defined(CONFIG_PPC_MPC52xx)
> +#elif defined(CONFIG_PPC_MPC52xx) && !defined(CONFIG_PPC_MERGE)
>  #include <asm/mpc52xx.h>
>  #elif defined(CONFIG_8xx)
>  #include <asm/mpc8xx.h>

Ben.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-04 23:35       ` Benjamin Herrenschmidt
@ 2006-11-05  0:27         ` Sylvain Munaut
  2006-11-05  1:13           ` Benjamin Herrenschmidt
  2006-11-05 10:17         ` Nicolas DET
  1 sibling, 1 reply; 27+ messages in thread
From: Sylvain Munaut @ 2006-11-05  0:27 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linuxppc-embedded, sl


>> +	picnode = find_mpc52xx_picnode();
>> +	sdmanode = find_mpc52xx_sdmanode();
>>     
>
> Any reason why you have those inline 1-line functions and just not put
> the actual of_find_* call in here ?
>   
I think it might be worth creating a
arch/powerpc/sysdev/mpc52xx_common.c (we'll probably need it later on
anyway)
with a helper that would do
 - The find_node
 - get_address / translate /  get_size
 - ioremap

Something like :

intr = mpc52xx_find_and_map("mpc52xx-intr");
sdma = mpc52xx_find_and_map("mpc52xx-sdma");

would be more elegant. Especially since finding and mapping things like
intr/sdma/xlb/cdm ... will be done at several place. That would prevent
repeating all that code for nothing.




Also, in the Makefile, I would make the compilation conditionnal to
CONFIG_PPC_MPC52xx and not CONFIG_PPC_MPC52xx_PIC ...
If you're on a 52xx, you most likely want the interrupt controller ...

But the CONFIG_PPC_MPC52xx option should be in arch/powerpc/Kconfig
and not in the platform/embedded6xx/Kconfig


        Sylvain

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-05  0:27         ` Sylvain Munaut
@ 2006-11-05  1:13           ` Benjamin Herrenschmidt
  2006-11-06  6:28             ` Grant Likely
  0 siblings, 1 reply; 27+ messages in thread
From: Benjamin Herrenschmidt @ 2006-11-05  1:13 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: linuxppc-dev, linuxppc-embedded, sl

On Sun, 2006-11-05 at 01:27 +0100, Sylvain Munaut wrote:
> >> +	picnode = find_mpc52xx_picnode();
> >> +	sdmanode = find_mpc52xx_sdmanode();
> >>     
> >
> > Any reason why you have those inline 1-line functions and just not put
> > the actual of_find_* call in here ?
> >   
> I think it might be worth creating a
> arch/powerpc/sysdev/mpc52xx_common.c (we'll probably need it later on
> anyway)
> with a helper that would do

> - The find_node

I don't see why we need a helper for that at all in the first place :)

>  - get_address / translate /  get_size

That too

>  - ioremap
> 
> Something like :
> 
> intr = mpc52xx_find_and_map("mpc52xx-intr");
> sdma = mpc52xx_find_and_map("mpc52xx-sdma");

Hrm... I don't care that much but I also don't think we need that
helper. It's not saving much.

> would be more elegant. Especially since finding and mapping things like
> intr/sdma/xlb/cdm ... will be done at several place. That would prevent
> repeating all that code for nothing.

It's not much code to repeat ;) but if you want, I have no big problem
with that.

> Also, in the Makefile, I would make the compilation conditionnal to
> CONFIG_PPC_MPC52xx and not CONFIG_PPC_MPC52xx_PIC ...
> If you're on a 52xx, you most likely want the interrupt controller ...
> 
> But the CONFIG_PPC_MPC52xx option should be in arch/powerpc/Kconfig
> and not in the platform/embedded6xx/Kconfig

Ben.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-04 23:35       ` Benjamin Herrenschmidt
  2006-11-05  0:27         ` Sylvain Munaut
@ 2006-11-05 10:17         ` Nicolas DET
  2006-11-05 10:37           ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 27+ messages in thread
From: Nicolas DET @ 2006-11-05 10:17 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev, Sylvain Munaut, sl, linuxppc-embedded

On Sun, 05 Nov 2006 10:35:40 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> On Thu, 2006-11-02 at 21:47 +0100, Nicolas DET wrote:
> 
> > + *
> > + * Programmable Interrupt Controller functions for the Freescale MPC52xx.
> > + *
> > + * Based on (well, mostly copied from) the code from the 2.4 kernel by
> > + * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
> > + * 
> > + * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
> > + * Copyright (C) 2003 Montavista Software, Inc
> 
> You did significant changes, you should add your (c) before the "Based
> on..." line.

Ok. It now looks likes this:

+/*
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx.
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * Based on (well, mostly copied from) the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ * 
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */


> 
> > +	switch (l1irq) {
> > +	case MPC52xx_IRQ_L1_CRIT:
> > +		pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
> > +
> > +		BUG_ON(l2irq != 0);
> > +
> > +		type = mpc52xx_irqx_gettype(l2irq);
> > +		good_irqchip = &mpc52xx_extirq_irqchip;
> > +		break;
> > +
> > +	case MPC52xx_IRQ_L1_MAIN:
> > +		pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
> > +
> > +		if ((l2irq >= 1) && (l2irq <= 3)) {
> > +			type = mpc52xx_irqx_gettype(l2irq);
> > +			good_irqchip = &mpc52xx_extirq_irqchip;
> > +		} else {
> > +			good_irqchip = &mpc52xx_main_irqchip;
> > +		}
> > +		break;
> 
> You have changed the mapping of L1/L2 but not the device-tree
> representation to match them. Which means that you need the ugly hack
> above. That is not goot. Fix your device-tree instead and do the same
> split in the tree for L1/L2 than you do in the code.

There is no option here.

> > +	picnode = find_mpc52xx_picnode();
> > +	sdmanode = find_mpc52xx_sdmanode();
> 
> Any reason why you have those inline 1-line functions and just not put
> the actual of_find_* call in here ?
> 
> You probably also need some of_node_put() in the error case. You are
> doing a whole bunch of "return" that bypass them.

I have done it because other platform may add their how type/compatible/way to find the node. For example, I did not find any bestcomm node in the recent lite5200 device-tree.

http://ozlabs.org/pipermail/linuxppc-embedded/2006-November/024970.html

> The rest looks ok.
> 

;-)

> Please submit the io.h patch separately. Also, you may need to fix the
> default case (which is the one we are using) in there to work with
> CONFIG_PCI not set (by defining PCI_DRAM_BASE to 0 among others).
>

Sylvain was faster than me. :-)

Regards

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-05 10:17         ` Nicolas DET
@ 2006-11-05 10:37           ` Benjamin Herrenschmidt
  2006-11-05 11:30             ` Nicolas DET
  0 siblings, 1 reply; 27+ messages in thread
From: Benjamin Herrenschmidt @ 2006-11-05 10:37 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-dev, Sylvain Munaut, sl, linuxppc-embedded


> > You have changed the mapping of L1/L2 but not the device-tree
> > representation to match them. Which means that you need the ugly hack
> > above. That is not goot. Fix your device-tree instead and do the same
> > split in the tree for L1/L2 than you do in the code.
> 
> There is no option here.

I don't agree. Your firmware can always be upgraded. There is no way you
will impose a broken format on everybody else. Unfortunately, being the
first implementation, that's just what you are doing...

At worst, you'll have to do a fixup pass in prom_init.c

> I have done it because other platform may add their how type/compatible/way to find the node.
> For example, I did not find any bestcomm node in the recent lite5200 device-tree.
> 
> http://ozlabs.org/pipermail/linuxppc-embedded/2006-November/024970.html

They should get there ultimately.

Ben.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-05 10:37           ` Benjamin Herrenschmidt
@ 2006-11-05 11:30             ` Nicolas DET
  2006-11-05 13:02               ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 27+ messages in thread
From: Nicolas DET @ 2006-11-05 11:30 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev, Sylvain Munaut, sl, linuxppc-embedded

On Sun, 05 Nov 2006 21:37:11 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> 
> > > You have changed the mapping of L1/L2 but not the device-tree
> > > representation to match them. Which means that you need the ugly hack
> > > above. That is not goot. Fix your device-tree instead and do the same
> > > split in the tree for L1/L2 than you do in the code.
> > 
> > There is no option here.
> 
> I don't agree. Your firmware can always be upgraded. There is no way you
> will impose a broken format on everybody else. Unfortunately, being the
> first implementation, that's just what you are doing...
> 

As said, no option here. I think there is different way to see how works the PIC. However, from a register point of view. There is just critical, main, peripherals, SDMA.

Loot at "ICTL Perstat, MainStat, MainStat, CritStat Encoded Register--MBAR + 0x0524"

Page 160 of the MPC5200BUM.pdf.

> At worst, you'll have to do a fixup pass in prom_init.c
> 

If you really want to change the pic driver, tell me the way to adapt prom_init.c
However, I do think we do it the right way.

Regards,

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-05 11:30             ` Nicolas DET
@ 2006-11-05 13:02               ` Benjamin Herrenschmidt
  2006-11-05 13:16                 ` Nicolas DET
  2006-11-05 14:32                 ` Sylvain Munaut
  0 siblings, 2 replies; 27+ messages in thread
From: Benjamin Herrenschmidt @ 2006-11-05 13:02 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-dev, Sylvain Munaut, sl, linuxppc-embedded

On Sun, 2006-11-05 at 12:30 +0100, Nicolas DET wrote:
> On Sun, 05 Nov 2006 21:37:11 +1100
> Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> 
> > 
> > > > You have changed the mapping of L1/L2 but not the device-tree
> > > > representation to match them. Which means that you need the ugly hack
> > > > above. That is not goot. Fix your device-tree instead and do the same
> > > > split in the tree for L1/L2 than you do in the code.
> > > 
> > > There is no option here.
> > 
> > I don't agree. Your firmware can always be upgraded. There is no way you
> > will impose a broken format on everybody else. Unfortunately, being the
> > first implementation, that's just what you are doing...
> > 
> 
> As said, no option here. I think there is different way to see how works the PIC. However, from a register point of view. There is just critical, main, peripherals, SDMA.
> 
> Loot at "ICTL Perstat, MainStat, MainStat, CritStat Encoded Register--MBAR + 0x0524"

You should have your device-tree match your internal numbering. As you
noticed, the CRIT interrupt and the EXT interrupts are just the same.
And you properly folded them under the same level 1... now just make
the device-tree expose the same informations.

I don't care if you have firmwares in production or whatever... As a
matter of fact, you guys have been working on this board for long enough
you could have dealt with that issue long ago :-)

So right now, what you should do is figure out a proper encoding for the
firmware, and then either fix your device-tree, or do a hack in
prom_init.c that fixes it up.

Ben.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-05 13:02               ` Benjamin Herrenschmidt
@ 2006-11-05 13:16                 ` Nicolas DET
  2006-11-05 14:32                 ` Sylvain Munaut
  1 sibling, 0 replies; 27+ messages in thread
From: Nicolas DET @ 2006-11-05 13:16 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev, Sylvain Munaut, sl, linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 1232 bytes --]

Benjamin Herrenschmidt wrote:

>> As said, no option here. I think there is different way to see how works the PIC. However, from a register point of view. There is just critical, main, peripherals, SDMA.
>>
>> Loot at "ICTL Perstat, MainStat, MainStat, CritStat Encoded Register--MBAR + 0x0524"
> 
> You should have your device-tree match your internal numbering. As you
> noticed, the CRIT interrupt and the EXT interrupts are just the same.

As I see, they aren't.
Critical interrupts defines IRQ 0, as well as slice timer0, WakeUp from 
deep-sleep mode (CCS) interrupt, etc..

Where as main is IRQ[1-3] as well as others stuff.

I did implement/change the irqchip, on your request, because in this 
case (IRQ0 -> l2=1, IRQ[13] -> l2=1->3). and the ack/mask bit are the 
same, it makes sense to have the same func called.

> So right now, what you should do is figure out a proper encoding for the
> firmware, and then either fix your device-tree, or do a hack in
> prom_init.c that fixes it up.
> 

I think the OFW has proper encoding, moreover, this encoding was done up 
on your request and opinion.

If you still want to change the Linux interrupt encoding, I will then 
hack prom_init.c and submmit new patches...

Regards,

[-- Attachment #2: nd.vcf --]
[-- Type: text/x-vcard, Size: 249 bytes --]

begin:vcard
fn:Nicolas DET ( bplan GmbH )
n:DET;Nicolas
org:bplan GmbH
adr:;;;;;;Germany
email;internet:nd@bplan-gmbh.de
title:Software Entwicklung
tel;work:+49 6171 9187 - 31
x-mozilla-html:FALSE
url:http://www.bplan-gmbh.de
version:2.1
end:vcard


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-05 13:02               ` Benjamin Herrenschmidt
  2006-11-05 13:16                 ` Nicolas DET
@ 2006-11-05 14:32                 ` Sylvain Munaut
  1 sibling, 0 replies; 27+ messages in thread
From: Sylvain Munaut @ 2006-11-05 14:32 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linuxppc-embedded, sl


>> As said, no option here. I think there is different way to see how works the PIC. However, from a register point of view. There is just critical, main, peripherals, SDMA.
>>
>> Loot at "ICTL Perstat, MainStat, MainStat, CritStat Encoded Register--MBAR + 0x0524"
>>     
>
> You should have your device-tree match your internal numbering. As you
> noticed, the CRIT interrupt and the EXT interrupts are just the same.
> And you properly folded them under the same level 1... now just make
> the device-tree expose the same informations.
>
> I don't care if you have firmwares in production or whatever... As a
> matter of fact, you guys have been working on this board for long enough
> you could have dealt with that issue long ago :-)
>
> So right now, what you should do is figure out a proper encoding for the
> firmware, and then either fix your device-tree, or do a hack in
> prom_init.c that fixes it up.
>   
I think Nicolas's choice makes sense.
The HW provides 4 registers which each contain the "number" of the IRQ that
happenned. And IRQ0 is encoded separatly from IRQ[1-3].

So when IRQ0 happens,  you really have a flag saying that a critical
interrupt
happenned, and when you look at the encoded critical interrupt number,
you get
"00" which is IRQ0.

If IRQ2 happend, the flag say a main interrupt happenned and when looking in
the encoded main interrupt number, we get "000001" which is IRQ2 ...

So the Hardware maps the hw IRQ number like this, so it makes sense to
use that mapping. Sure we could just not use that mapping and put IRQ0 hwirq
number just before IRQ1 but then the hack is just moved in get_irq and
we have
a numbering scheme which is not really what's in hw.


        Sylvain

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-05  1:13           ` Benjamin Herrenschmidt
@ 2006-11-06  6:28             ` Grant Likely
  2006-11-06  8:39               ` Sylvain Munaut
  0 siblings, 1 reply; 27+ messages in thread
From: Grant Likely @ 2006-11-06  6:28 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, sl, linuxppc-embedded

On 11/4/06, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> On Sun, 2006-11-05 at 01:27 +0100, Sylvain Munaut wrote:
> > with a helper that would do
> > - The find_node
> >  - get_address / translate /  get_size
> >  - ioremap
> >
> > Something like :
> >
> > intr = mpc52xx_find_and_map("mpc52xx-intr");
> > sdma = mpc52xx_find_and_map("mpc52xx-sdma");
>
> Hrm... I don't care that much but I also don't think we need that
> helper. It's not saving much.

While on this topic... if a helper is added, what about it is 52xx
specific?  Wouldn't the same code apply to all platforms?

g.

-- 
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-02 20:47     ` Nicolas DET
  2006-11-04 23:35       ` Benjamin Herrenschmidt
@ 2006-11-06  6:55       ` Grant Likely
  1 sibling, 0 replies; 27+ messages in thread
From: Grant Likely @ 2006-11-06  6:55 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-dev, sl, linuxppc-embedded

I still haven't had the time to get this code working on my board, and
I haven't followed the discussion over the last week very carefully,
but here's my comments anyway.  :)

On 11/2/06, Nicolas DET <nd@bplan-gmbh.de> wrote:
> --- a/arch/powerpc/sysdev/mpc52xx_pic.c 1970-01-01 01:00:00.000000000 +0100
> +++ b/arch/powerpc/sysdev/mpc52xx_pic.c 2006-11-02 17:56:10.000000000 +0100
> +static inline void io_be_setbit(u32 __iomem *addr, int bitno)
> +{
> +       out_be32(addr, in_be32(addr) | (1 << bitno) );
> +}
> +
> +static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
> +{
> +       out_be32(addr, in_be32(addr) & ~(1 << bitno));
> +}
> +

Do these belong somewhere else?  In common code somewhere?  Does this
have the side effect of looking like an atomic operation to the casual
observer?  (That's a coding convention question directed at Ben)

> +static inline struct device_node *find_mpc52xx_picnode(void)
> +{
> +       return of_find_compatible_node(NULL, "interrupt-controller",
> +                                      "mpc5200-pic");
> +}
> +
> +static inline struct device_node *find_mpc52xx_sdmanode(void)
> +{
> +       return of_find_compatible_node(NULL, "dma-controller",
> +                                      "mpc5200-bestcomm");
> +}

I don't think this is a very good idea from a maintenance perspective.
 Effectively, they replace a single line of code with 5 lines (4 for
the static func, 1 where it is called).  If in the future they ever
need to be called in more than 1 or 2 places, then this could be
revisited.

> +
> +/*
> + * IRQ[0-3] interrupt irq_chip
> +*/
> +
> +static void mpc52xx_extirq_mask(unsigned int virq)
> +{
> +       int irq;
> +       int l2irq;
> +
> +       irq = irq_map[virq].hwirq;
> +       l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;

L2 offset will always be 0; why not just omit all references to it?
Keeps the code slightly more concise.

> +/*
> + * init (public)
> +*/
> +
> +void __init mpc52xx_init_irq(void)
> +{
> +       struct device_node *picnode;
> +       int picnode_regsize;
> +       u32 picnode_regoffset;
> +
> +       struct device_node *sdmanode;
> +       int sdmanode_regsize;
> +       u32 sdmanode_regoffset;
> +
> +       u64 size64;
> +       int flags;
> +
> +       u32 intr_ctrl;
> +
> +       picnode = find_mpc52xx_picnode();
> +       sdmanode = find_mpc52xx_sdmanode();
> +
> +       if ( (picnode == NULL) || (sdmanode == NULL) )
> +               return;

I don't think you should fail silently here.

> +
> +       /* Retrieve PIC ressources */
> +       picnode_regoffset = (u32) of_get_address(picnode, 0, &size64, &flags);
> +       if (picnode_regoffset == 0)
> +               return ;

ditto

> +
> +       picnode_regoffset = of_translate_address(picnode, (u32 *) picnode_regoffset);
> +       picnode_regsize = (int)size64;
> +
> +       /* Retrieve SDMA ressources */
> +       sdmanode_regoffset = (u32) of_get_address(sdmanode, 0, &size64, &flags);
> +       if (sdmanode_regoffset == 0)
> +               return ;

ditto

> +
> +       sdmanode_regoffset = of_translate_address(sdmanode, (u32 *) sdmanode_regoffset);
> +       sdmanode_regsize = (int)size64;
> +
> +       /* Remap the necessary zones */
> +       intr = ioremap(picnode_regoffset, picnode_regsize);
> +       sdma = ioremap(sdmanode_regoffset, sdmanode_regsize);
> +
> +       if ((intr == NULL) || (sdma == NULL))
> +               panic("Can't ioremap PIC/SDMA register or init_irq !");
> +
> +       printk(KERN_INFO "Remapped MPC52xx PIC at 0x%8.8x\n", picnode_regoffset);
> +       printk(KERN_INFO "Remapped MPC52xx SDMA at 0x%8.8x\n", sdmanode_regoffset);
> +
> +       of_node_put(picnode);
> +       of_node_put(sdmanode);

Silent failure cases above will bypass these calls to of_node_put().

> +
> +       /* Disable all interrupt sources. */
> +       out_be32(&sdma->IntPend, 0xffffffff);   /* 1 means clear pending */
> +       out_be32(&sdma->IntMask, 0xffffffff);   /* 1 means disabled */
> +       out_be32(&intr->per_mask, 0x7ffffc00);  /* 1 means disabled */
> +       out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
> +       intr_ctrl = in_be32(&intr->ctrl);
> +       intr_ctrl &= 0x00ff0000;        /* Keeps IRQ[0-3] config */
> +       intr_ctrl |= 0x0f000000 |       /* clear IRQ 0-3 */
> +           0x00001000 |        /* MEE master external enable */
> +           0x00000000 |        /* 0 means disable IRQ 0-3 */
> +           0x00000001;         /* CEb route critical normally */
> +       out_be32(&intr->ctrl, intr_ctrl);
> +
> +       /* Zero a bunch of the priority settings.  */
> +       out_be32(&intr->per_pri1, 0);
> +       out_be32(&intr->per_pri2, 0);
> +       out_be32(&intr->per_pri3, 0);
> +       out_be32(&intr->main_pri1, 0);
> +       out_be32(&intr->main_pri2, 0);
> +
> +       /*
> +        * As last step, add an irq host to translate the real
> +        * hw irq information provided by the ofw to linux virq
> +        */
> +
> +       mpc52xx_irqhost =
> +           irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTVIRQ,
> +                          &mpc52xx_irqhost_ops, -1);
> +
> +       if (mpc52xx_irqhost)
> +               mpc52xx_irqhost->host_data = picnode;
> +}
> +
> +/*
> + * get_irq (public)
> +*/
> +unsigned int mpc52xx_get_irq(void)
> +{
> +       u32 status;
> +       int irq = NO_IRQ_IGNORE;
> +
> +       status = in_be32(&intr->enc_status);
> +       if (status & 0x00000400) {      /* critical */
> +               irq = (status >> 8) & 0x3;
> +               if (irq == 2)   /* high priority peripheral */
> +                       goto peripheral;
> +               irq |=
> +                   (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
> +                   MPC52xx_IRQ_L1_MASK;
> +       } else if (status & 0x00200000) {       /* main */
> +               irq = (status >> 16) & 0x1f;
> +               if (irq == 4)   /* low priority peripheral */
> +                       goto peripheral;
> +               irq |=
> +                   (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
> +                   MPC52xx_IRQ_L1_MASK;
> +       } else if (status & 0x20000000) {       /* peripheral */
> +             peripheral:
> +               irq = (status >> 24) & 0x1f;
> +               if (irq == 0) { /* bestcomm */
> +                       status = in_be32(&sdma->IntPend);
> +                       irq = ffs(status) - 1;
> +                       irq |=
> +                           (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
> +                           MPC52xx_IRQ_L1_MASK;
> +               } else
> +                       irq |=
> +                           (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
> +                           MPC52xx_IRQ_L1_MASK;
> +
> +       }
> +
> +       pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
> +                irq_linear_revmap(mpc52xx_irqhost, irq));
> +
> +       return irq_linear_revmap(mpc52xx_irqhost, irq);
> +}
> --- a/include/asm-powerpc/mpc52xx.h     1970-01-01 01:00:00.000000000 +0100
> +++ b/include/asm-powerpc/mpc52xx.h     2006-11-02 17:54:37.000000000 +0100
> @@ -0,0 +1,319 @@
> +/*
> + *
> + * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
> + * May need to be cleaned as the port goes on ...
> + *
> + * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
> + * Copyright (C) 2003 MontaVista, Software, Inc.
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#ifndef __ASM_POWERPC_MPC52xx_H__
> +#define __ASM_POWERPC_MPC52xx_H__
> +
> +#ifndef __ASSEMBLY__
> +#include <asm/types.h>
> +#include <asm/prom.h>
> +
> +#endif                         /* __ASSEMBLY__ */
> +
> +/* ======================================================================== */
> +/* Main registers/struct addresses                                          */
> +/* ======================================================================== */
> +
> +/* Registers zone offset/size  */
> +#define MPC52xx_MMAP_CTL_OFFSET                0x0000
> +#define MPC52xx_MMAP_CTL_SIZE          0x068
> +#define MPC52xx_SDRAM_OFFSET           0x0100
> +#define MPC52xx_SDRAM_SIZE             0x010
> +#define MPC52xx_CDM_OFFSET             0x0200
> +#define MPC52xx_CDM_SIZE               0x038
> +#define MPC52xx_INTR_OFFSET            0x0500
> +#define MPC52xx_INTR_SIZE              0x04c
> +#define MPC52xx_GPTx_OFFSET(x)         (0x0600 + ((x)<<4))
> +#define MPC52xx_GPT_SIZE               0x010
> +#define MPC52xx_RTC_OFFSET             0x0800
> +#define MPC52xx_RTC_SIZE               0x024
> +#define MPC52xx_GPIO_OFFSET            0x0b00
> +#define MPC52xx_GPIO_SIZE              0x040
> +#define MPC52xx_GPIO_WKUP_OFFSET       0x0c00
> +#define MPC52xx_GPIO_WKUP_SIZE         0x028
> +#define MPC52xx_PCI_OFFSET             0x0d00
> +#define MPC52xx_PCI_SIZE               0x100
> +#define MPC52xx_SDMA_OFFSET            0x1200
> +#define MPC52xx_SDMA_SIZE              0x100
> +#define MPC52xx_XLB_OFFSET             0x1f00
> +#define MPC52xx_XLB_SIZE               0x100
> +#define MPC52xx_PSCx_OFFSET(x)         (((x)!=6)?(0x1e00+((x)<<9)):0x2c00)
> +#define MPC52xx_PSC_SIZE               0x0a0
> +
> +/* SRAM used for SDMA */
> +#define MPC52xx_SRAM_OFFSET            0x8000
> +#define MPC52xx_SRAM_SIZE              0x4000

Register addresses/lengths are being passed by the device tree.  I
think they should be taken out of here to remove the temptation for
driver writers to use them.

g.

-- 
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-06  6:28             ` Grant Likely
@ 2006-11-06  8:39               ` Sylvain Munaut
  0 siblings, 0 replies; 27+ messages in thread
From: Sylvain Munaut @ 2006-11-06  8:39 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-embedded, sl, linuxppc-dev

Grant Likely wrote:
> On 11/4/06, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
>> On Sun, 2006-11-05 at 01:27 +0100, Sylvain Munaut wrote:
>> > with a helper that would do
>> > - The find_node
>> >  - get_address / translate /  get_size
>> >  - ioremap
>> >
>> > Something like :
>> >
>> > intr = mpc52xx_find_and_map("mpc52xx-intr");
>> > sdma = mpc52xx_find_and_map("mpc52xx-sdma");
>>
>> Hrm... I don't care that much but I also don't think we need that
>> helper. It's not saving much.
>
> While on this topic... if a helper is added, what about it is 52xx
> specific?  Wouldn't the same code apply to all platforms?
>
> g.
>
The code would look like what I included at the end (untested). Not that
I used
of_find_by_name and not find_compatible. We can fix a naming convention
for those units ...

I think it does save quite a few lines and variable. It also simplifies the
error path ... granted it's not an exceptionnal reduction but still
worth it.
If it's not included now it's not that bad, I'll probably submitt a
patch later
when it's used in more places than mpc52xx_pic.c ...

About the use on other platform, maybe but do other platform need that a
lot ?
Here we have several unit that need to be mapped at different places ...


Sylvain


---

void __iomem *mpc52xx_find_and_map(const char *name)
{
        struct device_node *ofn;
        const u32 *regaddr_p;
        u64 regaddr64, size64;

        ofn = of_find_by_name(NULL, name);
        if (!ofn)
                return NULL;

        regaddr_p = of_get_address(ofn, 0, &size64, NULL);
        if (!regaddr_p) {
                of_node_put(ofn);
                return NULL;
        }

        regaddr64 = of_translate_address(ofn, regaddr_p);

        of_node_put(ofn);

        return ioremap((u32)regaddr64, (u32)size64);
}

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
@ 2006-11-06 10:26 Nicolas DET
  0 siblings, 0 replies; 27+ messages in thread
From: Nicolas DET @ 2006-11-06 10:26 UTC (permalink / raw)
  To: linuxppc-embedded; +Cc: linuxppc-dev

This patch add MPC52xx Interrupt controller for ARCH=3Dpowerpc.

It includes the main code in arch/powerpc/sysdev/ ad well as an header file=
 in include/asm-powerpc.

Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
---
--- a/arch/powerpc/sysdev/mpc52xx_pic.c=091970-01-01 01:00:00.000000000 +01=
00
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c=092006-11-06 11:10:29.000000000 +01=
00
@@ -0,0 +1,527 @@
+/*
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx.
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * Based on (well, mostly copied from) the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ *=20
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/mpc52xx.h>
+
+/*
+ *
+*/
+
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_sdma __iomem *sdma;
+static struct irq_host *mpc52xx_irqhost =3D NULL;
+
+static unsigned char mpc52xx_map_senses[4] =3D {
+=09IRQ_TYPE_LEVEL_HIGH,
+=09IRQ_TYPE_EDGE_RISING,
+=09IRQ_TYPE_EDGE_FALLING,
+=09IRQ_TYPE_LEVEL_LOW,
+};
+
+/*
+ *
+*/
+
+static inline void io_be_setbit(u32 __iomem *addr, int bitno)
+{
+=09out_be32(addr, in_be32(addr) | (1 << bitno) );
+}
+
+static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
+{
+=09out_be32(addr, in_be32(addr) & ~(1 << bitno));
+}
+
+/*
+ * IRQ[0-3] interrupt irq_chip
+*/
+
+static void mpc52xx_extirq_mask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_clrbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_unmask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_setbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_ack(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_setbit(&intr->ctrl, 27-l2irq);
+}
+
+static struct irq_chip mpc52xx_extirq_irqchip =3D {
+=09.typename =3D " MPC52xx IRQ[0-3] ",
+=09.mask =3D mpc52xx_extirq_mask,
+=09.unmask =3D mpc52xx_extirq_unmask,
+=09.ack =3D mpc52xx_extirq_ack,
+};
+
+/*
+ * Main interrupt irq_chip
+*/
+
+static void mpc52xx_main_mask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_setbit(&intr->main_mask, 15 - l2irq);
+}
+
+static void mpc52xx_main_unmask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_clrbit(&intr->main_mask, 15 - l2irq);
+}
+
+static struct irq_chip mpc52xx_main_irqchip =3D {
+=09.typename =3D "MPC52xx Main",
+=09.mask =3D mpc52xx_main_mask,
+=09.mask_ack =3D mpc52xx_main_mask,
+=09.unmask =3D mpc52xx_main_unmask,
+};
+
+/*
+ * Peripherals interrupt irq_chip
+*/
+
+static void mpc52xx_periph_mask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_setbit(&intr->per_mask, 31 - l2irq);
+}
+
+static void mpc52xx_periph_unmask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_clrbit(&intr->per_mask, 31 - l2irq);
+}
+
+static struct irq_chip mpc52xx_periph_irqchip =3D {
+=09.typename =3D "MPC52xx Peripherals",
+=09.mask =3D mpc52xx_periph_mask,
+=09.mask_ack =3D mpc52xx_periph_mask,
+=09.unmask =3D mpc52xx_periph_unmask,
+};
+
+/*
+ * SDMA interrupt irq_chip
+*/
+
+static void mpc52xx_sdma_mask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_setbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_unmask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_clrbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_ack(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09out_be32(&sdma->IntPend, 1 << l2irq);
+}
+
+static struct irq_chip mpc52xx_sdma_irqchip =3D {
+=09.typename =3D "MPC52xx SDMA",
+=09.mask =3D mpc52xx_sdma_mask,
+=09.unmask =3D mpc52xx_sdma_unmask,
+=09.ack =3D mpc52xx_sdma_ack,
+};
+
+/*
+ * irq_host
+*/
+
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *n=
ode)
+{
+=09pr_debug("%s: node=3D%pn", __func__, node);
+=09return mpc52xx_irqhost->host_data =3D=3D node;
+}
+
+static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *c=
t,
+=09=09=09=09 u32 * intspec, unsigned int intsize,
+=09=09=09=09 irq_hw_number_t * out_hwirq,
+=09=09=09=09 unsigned int *out_flags)
+{
+=09int intrvect_l1;
+=09int intrvect_l2;
+=09int intrvect_type;
+=09int intrvect_linux;
+
+=09if (intsize !=3D 3)
+=09=09return -1;
+
+=09intrvect_l1 =3D (int)intspec[0];
+=09intrvect_l2 =3D (int)intspec[1];
+=09intrvect_type =3D (int)intspec[2];
+
+=09intrvect_linux =3D
+=09    (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
+=09intrvect_linux |=3D
+=09    (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
+
+=09pr_debug("return %x, l1=3D%d, l2=3D%dn", intrvect_linux, intrvect_l1,
+=09=09 intrvect_l2);
+
+=09*out_hwirq =3D intrvect_linux;
+=09*out_flags =3D mpc52xx_map_senses[intrvect_type];
+
+=09return 0;
+}
+
+/*
+ * this function retrieves the correct IRQ type out
+ * of the MPC regs
+ * Only externals IRQs needs this
+*/
+static int mpc52xx_irqx_gettype(int irq)
+{
+=09int type;
+=09u32 ctrl_reg;
+
+=09ctrl_reg =3D in_be32(&intr->ctrl);
+=09type =3D (ctrl_reg >> (22 - irq * 2)) & 0x3;
+
+=09return mpc52xx_map_senses[type];
+}
+
+static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+=09=09=09       irq_hw_number_t irq)
+{
+=09int l1irq;
+=09int l2irq;
+=09struct irq_chip *good_irqchip;
+=09void *good_handle;
+=09int type;
+
+=09l1irq =3D (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09/*
+=09 * Most of ours IRQs will be level low
+=09 * Only external IRQs on some platform may be others
+=09 */
+=09type =3D IRQ_TYPE_LEVEL_LOW;
+
+=09switch (l1irq) {
+=09case MPC52xx_IRQ_L1_CRIT:
+=09=09pr_debug("%s: Critical. l2=3D%xn", __func__, l2irq);
+
+=09=09BUG_ON(l2irq !=3D 0);
+
+=09=09type =3D mpc52xx_irqx_gettype(l2irq);
+=09=09good_irqchip =3D &mpc52xx_extirq_irqchip;
+=09=09break;
+
+=09case MPC52xx_IRQ_L1_MAIN:
+=09=09pr_debug("%s: Main IRQ[1-3] l2=3D%xn", __func__, l2irq);
+
+=09=09if ((l2irq >=3D 1) && (l2irq <=3D 3)) {
+=09=09=09type =3D mpc52xx_irqx_gettype(l2irq);
+=09=09=09good_irqchip =3D &mpc52xx_extirq_irqchip;
+=09=09} else {
+=09=09=09good_irqchip =3D &mpc52xx_main_irqchip;
+=09=09}
+=09=09break;
+
+=09case MPC52xx_IRQ_L1_PERP:
+=09=09pr_debug("%s: Peripherals. l2=3D%xn", __func__, l2irq);
+=09=09good_irqchip =3D &mpc52xx_periph_irqchip;
+=09=09break;
+
+=09case MPC52xx_IRQ_L1_SDMA:
+=09=09pr_debug("%s: SDMA. l2=3D%xn", __func__, l2irq);
+=09=09good_irqchip =3D &mpc52xx_sdma_irqchip;
+=09=09break;
+
+=09default:
+=09=09pr_debug("%s: Error, unknown L1 IRQ (0x%x)n", __func__, l1irq);
+=09=09printk(KERN_ERR "Unknow IRQ!n");
+=09=09return -EINVAL;
+=09}
+
+=09switch (type) {
+=09case IRQ_TYPE_EDGE_FALLING:
+=09case IRQ_TYPE_EDGE_RISING:
+=09=09good_handle =3D handle_edge_irq;
+=09=09break;
+=09default:
+=09=09good_handle =3D handle_level_irq;
+=09}
+
+=09set_irq_chip_and_handler(virq, good_irqchip, good_handle);
+
+=09pr_debug("%s: virq=3D%x, hw=3D%x. type=3D%xn", __func__, virq,
+=09=09 (int)irq, type);
+
+=09return 0;
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops =3D {
+=09.match =3D mpc52xx_irqhost_match,
+=09.xlate =3D mpc52xx_irqhost_xlate,
+=09.map =3D mpc52xx_irqhost_map,
+};
+
+/*
+ * init (public)
+*/
+
+void __init mpc52xx_init_irq(void)
+{
+=09struct device_node *picnode =3D NULL;
+=09int picnode_regsize;
+=09u32 picnode_regoffset;
+
+=09struct device_node *sdmanode =3D NULL;
+=09int sdmanode_regsize;
+=09u32 sdmanode_regoffset;
+
+=09u64 size64;
+=09int flags;
+
+=09u32 intr_ctrl;
+
+=09picnode =3D of_find_compatible_node(NULL, "interrupt-controller", "mpc5=
200-pic");
+=09if (picnode =3D=3D NULL) {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to find the interrupt controlle=
r in the OpenFirmware device treen");
+=09=09goto end;
+=09}
+
+=09sdmanode =3D of_find_compatible_node(NULL, "dma-controller", "mpc5200-b=
estcomm");
+=09if (sdmanode =3D=3D NULL) {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to find the Bestcomm DMA contro=
ller device in the OpenFirmware device treen");
+=09=09goto end;
+=09}
+
+=09/* Retrieve PIC ressources */
+=09picnode_regoffset =3D (u32) of_get_address(picnode, 0, &size64, &flags)=
;
+=09if (picnode_regoffset =3D=3D 0) {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to get the interrupt controller=
 addressn");
+=09=09goto end;
+=09}
+
+=09picnode_regoffset =3D of_translate_address(picnode, (u32 *) picnode_reg=
offset);
+=09picnode_regsize =3D (int) size64;=09
+
+=09/* Retrieve SDMA ressources */
+=09sdmanode_regoffset =3D (u32) of_get_address(sdmanode, 0, &size64, &flag=
s);
+=09if (sdmanode_regoffset =3D=3D 0) {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to get the Bestcomm DMA control=
ler addressn");
+=09=09goto end;
+=09}
+
+=09sdmanode_regoffset =3D of_translate_address(sdmanode, (u32 *) sdmanode_=
regoffset);
+=09sdmanode_regsize =3D (int) size64;
+
+=09/* Remap the necessary zones */
+=09intr =3D ioremap(picnode_regoffset, picnode_regsize);
+=09if (intr =3D=3D NULL) {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to ioremap interrupt controller=
 registers!");
+=09=09goto end;
+=09}
+
+=09sdma =3D ioremap(sdmanode_regoffset, sdmanode_regsize);
+=09if (sdma =3D=3D NULL) {
+=09=09iounmap(intr);
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to ioremap Bestcomm DMA control=
ler registers!");
+=09=09goto end;
+=09}
+
+=09printk(KERN_INFO "MPC52xx PIC: MPC52xx PIC Remapped at 0x%8.8xn", picno=
de_regoffset);
+=09printk(KERN_INFO "MPC52xx PIC: MPC52xx SDMA Remapped at 0x%8.8xn", sdma=
node_regoffset);
+
+=09/* Disable all interrupt sources. */
+=09out_be32(&sdma->IntPend, 0xffffffff);=09/* 1 means clear pending */
+=09out_be32(&sdma->IntMask, 0xffffffff);=09/* 1 means disabled */
+=09out_be32(&intr->per_mask, 0x7ffffc00);=09/* 1 means disabled */
+=09out_be32(&intr->main_mask, 0x00010fff);=09/* 1 means disabled */
+=09intr_ctrl =3D in_be32(&intr->ctrl);
+=09intr_ctrl &=3D 0x00ff0000;=09/* Keeps IRQ[0-3] config */
+=09intr_ctrl |=3D 0x0f000000 |=09/* clear IRQ 0-3 */
+=09    0x00001000 |=09/* MEE master external enable */
+=09    0x00000000 |=09/* 0 means disable IRQ 0-3 */
+=09    0x00000001;=09=09/* CEb route critical normally */
+=09out_be32(&intr->ctrl, intr_ctrl);
+
+=09/* Zero a bunch of the priority settings.  */
+=09out_be32(&intr->per_pri1, 0);
+=09out_be32(&intr->per_pri2, 0);
+=09out_be32(&intr->per_pri3, 0);
+=09out_be32(&intr->main_pri1, 0);
+=09out_be32(&intr->main_pri2, 0);
+
+=09/*
+=09 * As last step, add an irq host to translate the real
+=09 * hw irq information provided by the ofw to linux virq
+=09 */
+
+=09mpc52xx_irqhost =3D
+=09    irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTHWIRQ,
+=09=09=09   &mpc52xx_irqhost_ops, -1);
+
+=09if (mpc52xx_irqhost) {
+=09=09mpc52xx_irqhost->host_data =3D picnode;
+=09=09printk(KERN_INFO "MPC52xx PIC is up and running!n");
+=09} else {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to allocate the IRQ hostn");
+=09}
+
+end:
+=09of_node_put(picnode);
+=09of_node_put(sdmanode);
+}
+
+/*
+ * get_irq (public)
+*/
+unsigned int mpc52xx_get_irq(void)
+{
+=09u32 status;
+=09int irq =3D NO_IRQ_IGNORE;
+
+=09status =3D in_be32(&intr->enc_status);
+=09if (status & 0x00000400) {=09/* critical */
+=09=09irq =3D (status >> 8) & 0x3;
+=09=09if (irq =3D=3D 2)=09/* high priority peripheral */
+=09=09=09goto peripheral;
+=09=09irq |=3D
+=09=09    (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
+=09=09    MPC52xx_IRQ_L1_MASK;
+=09} else if (status & 0x00200000) {=09/* main */
+=09=09irq =3D (status >> 16) & 0x1f;
+=09=09if (irq =3D=3D 4)=09/* low priority peripheral */
+=09=09=09goto peripheral;
+=09=09irq |=3D
+=09=09    (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
+=09=09    MPC52xx_IRQ_L1_MASK;
+=09} else if (status & 0x20000000) {=09/* peripheral */
+=09      peripheral:
+=09=09irq =3D (status >> 24) & 0x1f;
+=09=09if (irq =3D=3D 0) {=09/* bestcomm */
+=09=09=09status =3D in_be32(&sdma->IntPend);
+=09=09=09irq =3D ffs(status) - 1;
+=09=09=09irq |=3D
+=09=09=09    (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
+=09=09=09    MPC52xx_IRQ_L1_MASK;
+=09=09} else
+=09=09=09irq |=3D
+=09=09=09    (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
+=09=09=09    MPC52xx_IRQ_L1_MASK;
+
+=09}
+
+=09pr_debug("%s: irq=3D%x. virq=3D%dn", __func__, irq,
+=09=09 irq_linear_revmap(mpc52xx_irqhost, irq));
+
+=09return irq_linear_revmap(mpc52xx_irqhost, irq);
+}
--- a/arch/powerpc/sysdev/Makefile=092006-11-01 09:18:43.000000000 +0100
+++ b/arch/powerpc/sysdev/Makefile=092006-11-06 11:10:46.000000000 +0100
@@ -13,6 +13,7 @@ obj-$(CONFIG_FSL_SOC)=09=09+=3D fsl_soc.o
 obj-$(CONFIG_PPC_TODC)=09=09+=3D todc.o
 obj-$(CONFIG_TSI108_BRIDGE)=09+=3D tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)=09+=3D qe_lib/
+obj-$(CONFIG_PPC_MPC52xx)=09+=3D mpc52xx_pic.o
=20
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)=09=09+=3D i8259.o
--- a/include/asm-powerpc/mpc52xx.h=091970-01-01 01:00:00.000000000 +0100
+++ b/include/asm-powerpc/mpc52xx.h=092006-11-06 11:10:29.000000000 +0100
@@ -0,0 +1,283 @@
+/*
+ * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
+ * May need to be cleaned as the port goes on ...
+ *
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __ASM_POWERPC_MPC52xx_H__
+#define __ASM_POWERPC_MPC52xx_H__
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/prom.h>
+#endif /* __ASSEMBLY__ */
+
+/* HW IRQ mapping */
+#define MPC52xx_IRQ_L1_CRIT=09(0)
+#define MPC52xx_IRQ_L1_MAIN=09(1)
+#define MPC52xx_IRQ_L1_PERP=09(2)
+#define MPC52xx_IRQ_L1_SDMA=09(3)
+
+#define MPC52xx_IRQ_L1_OFFSET   (6)
+#define MPC52xx_IRQ_L1_MASK     (0xc0)
+
+#define MPC52xx_IRQ_L2_OFFSET   (0)
+#define MPC52xx_IRQ_L2_MASK     (0x3f)
+
+#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0)
+
+/* Interrupt controller Register set */
+struct mpc52xx_intr {
+=09u32 per_mask;=09=09/* INTR + 0x00 */
+=09u32 per_pri1;=09=09/* INTR + 0x04 */
+=09u32 per_pri2;=09=09/* INTR + 0x08 */
+=09u32 per_pri3;=09=09/* INTR + 0x0c */
+=09u32 ctrl;=09=09/* INTR + 0x10 */
+=09u32 main_mask;=09=09/* INTR + 0x14 */
+=09u32 main_pri1;=09=09/* INTR + 0x18 */
+=09u32 main_pri2;=09=09/* INTR + 0x1c */
+=09u32 reserved1;=09=09/* INTR + 0x20 */
+=09u32 enc_status;=09=09/* INTR + 0x24 */
+=09u32 crit_status;=09/* INTR + 0x28 */
+=09u32 main_status;=09/* INTR + 0x2c */
+=09u32 per_status;=09=09/* INTR + 0x30 */
+=09u32 reserved2;=09=09/* INTR + 0x34 */
+=09u32 per_error;=09=09/* INTR + 0x38 */
+};
+
+
+/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */
+/* Structures mapping of some unit register set                           =
  */
+/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */
+
+#ifndef __ASSEMBLY__
+
+/* Memory Mapping Control */
+struct mpc52xx_mmap_ctl {
+=09u32 mbar;=09=09/* MMAP_CTRL + 0x00 */
+
+=09u32 cs0_start;=09=09/* MMAP_CTRL + 0x04 */
+=09u32 cs0_stop;=09=09/* MMAP_CTRL + 0x08 */
+=09u32 cs1_start;=09=09/* MMAP_CTRL + 0x0c */
+=09u32 cs1_stop;=09=09/* MMAP_CTRL + 0x10 */
+=09u32 cs2_start;=09=09/* MMAP_CTRL + 0x14 */
+=09u32 cs2_stop;=09=09/* MMAP_CTRL + 0x18 */
+=09u32 cs3_start;=09=09/* MMAP_CTRL + 0x1c */
+=09u32 cs3_stop;=09=09/* MMAP_CTRL + 0x20 */
+=09u32 cs4_start;=09=09/* MMAP_CTRL + 0x24 */
+=09u32 cs4_stop;=09=09/* MMAP_CTRL + 0x28 */
+=09u32 cs5_start;=09=09/* MMAP_CTRL + 0x2c */
+=09u32 cs5_stop;=09=09/* MMAP_CTRL + 0x30 */
+
+=09u32 sdram0;=09=09/* MMAP_CTRL + 0x34 */
+=09u32 sdram1;=09=09/* MMAP_CTRL + 0X38 */
+
+=09u32 reserved[4];=09/* MMAP_CTRL + 0x3c .. 0x48 */
+
+=09u32 boot_start;=09=09/* MMAP_CTRL + 0x4c */
+=09u32 boot_stop;=09=09/* MMAP_CTRL + 0x50 */
+
+=09u32 ipbi_ws_ctrl;=09/* MMAP_CTRL + 0x54 */
+
+=09u32 cs6_start;=09=09/* MMAP_CTRL + 0x58 */
+=09u32 cs6_stop;=09=09/* MMAP_CTRL + 0x5c */
+=09u32 cs7_start;=09=09/* MMAP_CTRL + 0x60 */
+=09u32 cs7_stop;=09=09/* MMAP_CTRL + 0x64 */
+};
+
+/* SDRAM control */
+struct mpc52xx_sdram {
+=09u32 mode;=09=09/* SDRAM + 0x00 */
+=09u32 ctrl;=09=09/* SDRAM + 0x04 */
+=09u32 config1;=09=09/* SDRAM + 0x08 */
+=09u32 config2;=09=09/* SDRAM + 0x0c */
+};
+
+/* SDMA */
+struct mpc52xx_sdma {
+=09u32 taskBar;=09=09/* SDMA + 0x00 */
+=09u32 currentPointer;=09/* SDMA + 0x04 */
+=09u32 endPointer;=09=09/* SDMA + 0x08 */
+=09u32 variablePointer;=09/* SDMA + 0x0c */
+
+=09u8 IntVect1;=09=09/* SDMA + 0x10 */
+=09u8 IntVect2;=09=09/* SDMA + 0x11 */
+=09u16 PtdCntrl;=09=09/* SDMA + 0x12 */
+
+=09u32 IntPend;=09=09/* SDMA + 0x14 */
+=09u32 IntMask;=09=09/* SDMA + 0x18 */
+
+=09u16 tcr[16];=09=09/* SDMA + 0x1c .. 0x3a */
+
+=09u8 ipr[32];=09=09/* SDMA + 0x3c .. 0x5b */
+
+=09u32 cReqSelect;=09=09/* SDMA + 0x5c */
+=09u32 task_size0;=09=09/* SDMA + 0x60 */
+=09u32 task_size1;=09=09/* SDMA + 0x64 */
+=09u32 MDEDebug;=09=09/* SDMA + 0x68 */
+=09u32 ADSDebug;=09=09/* SDMA + 0x6c */
+=09u32 Value1;=09=09/* SDMA + 0x70 */
+=09u32 Value2;=09=09/* SDMA + 0x74 */
+=09u32 Control;=09=09/* SDMA + 0x78 */
+=09u32 Status;=09=09/* SDMA + 0x7c */
+=09u32 PTDDebug;=09=09/* SDMA + 0x80 */
+};
+
+/* GPT */
+struct mpc52xx_gpt {
+=09u32 mode;=09=09/* GPTx + 0x00 */
+=09u32 count;=09=09/* GPTx + 0x04 */
+=09u32 pwm;=09=09/* GPTx + 0x08 */
+=09u32 status;=09=09/* GPTx + 0X0c */
+};
+
+/* GPIO */
+struct mpc52xx_gpio {
+=09u32 port_config;=09/* GPIO + 0x00 */
+=09u32 simple_gpioe;=09/* GPIO + 0x04 */
+=09u32 simple_ode;=09=09/* GPIO + 0x08 */
+=09u32 simple_ddr;=09=09/* GPIO + 0x0c */
+=09u32 simple_dvo;=09=09/* GPIO + 0x10 */
+=09u32 simple_ival;=09/* GPIO + 0x14 */
+=09u8 outo_gpioe;=09=09/* GPIO + 0x18 */
+=09u8 reserved1[3];=09/* GPIO + 0x19 */
+=09u8 outo_dvo;=09=09/* GPIO + 0x1c */
+=09u8 reserved2[3];=09/* GPIO + 0x1d */
+=09u8 sint_gpioe;=09=09/* GPIO + 0x20 */
+=09u8 reserved3[3];=09/* GPIO + 0x21 */
+=09u8 sint_ode;=09=09/* GPIO + 0x24 */
+=09u8 reserved4[3];=09/* GPIO + 0x25 */
+=09u8 sint_ddr;=09=09/* GPIO + 0x28 */
+=09u8 reserved5[3];=09/* GPIO + 0x29 */
+=09u8 sint_dvo;=09=09/* GPIO + 0x2c */
+=09u8 reserved6[3];=09/* GPIO + 0x2d */
+=09u8 sint_inten;=09=09/* GPIO + 0x30 */
+=09u8 reserved7[3];=09/* GPIO + 0x31 */
+=09u16 sint_itype;=09=09/* GPIO + 0x34 */
+=09u16 reserved8;=09=09/* GPIO + 0x36 */
+=09u8 gpio_control;=09/* GPIO + 0x38 */
+=09u8 reserved9[3];=09/* GPIO + 0x39 */
+=09u8 sint_istat;=09=09/* GPIO + 0x3c */
+=09u8 sint_ival;=09=09/* GPIO + 0x3d */
+=09u8 bus_errs;=09=09/* GPIO + 0x3e */
+=09u8 reserved10;=09=09/* GPIO + 0x3f */
+};
+
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD=094
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD=095
+#define MPC52xx_GPIO_PCI_DIS=09=09=09(1<<15)
+
+/* GPIO with WakeUp*/
+struct mpc52xx_gpio_wkup {
+=09u8 wkup_gpioe;=09=09/* GPIO_WKUP + 0x00 */
+=09u8 reserved1[3];=09/* GPIO_WKUP + 0x03 */
+=09u8 wkup_ode;=09=09/* GPIO_WKUP + 0x04 */
+=09u8 reserved2[3];=09/* GPIO_WKUP + 0x05 */
+=09u8 wkup_ddr;=09=09/* GPIO_WKUP + 0x08 */
+=09u8 reserved3[3];=09/* GPIO_WKUP + 0x09 */
+=09u8 wkup_dvo;=09=09/* GPIO_WKUP + 0x0C */
+=09u8 reserved4[3];=09/* GPIO_WKUP + 0x0D */
+=09u8 wkup_inten;=09=09/* GPIO_WKUP + 0x10 */
+=09u8 reserved5[3];=09/* GPIO_WKUP + 0x11 */
+=09u8 wkup_iinten;=09=09/* GPIO_WKUP + 0x14 */
+=09u8 reserved6[3];=09/* GPIO_WKUP + 0x15 */
+=09u16 wkup_itype;=09=09/* GPIO_WKUP + 0x18 */
+=09u8 reserved7[2];=09/* GPIO_WKUP + 0x1A */
+=09u8 wkup_maste;=09=09/* GPIO_WKUP + 0x1C */
+=09u8 reserved8[3];=09/* GPIO_WKUP + 0x1D */
+=09u8 wkup_ival;=09=09/* GPIO_WKUP + 0x20 */
+=09u8 reserved9[3];=09/* GPIO_WKUP + 0x21 */
+=09u8 wkup_istat;=09=09/* GPIO_WKUP + 0x24 */
+=09u8 reserved10[3];=09/* GPIO_WKUP + 0x25 */
+};
+
+/* XLB Bus control */
+struct mpc52xx_xlb {
+=09u8 reserved[0x40];
+=09u32 config;=09=09/* XLB + 0x40 */
+=09u32 version;=09=09/* XLB + 0x44 */
+=09u32 status;=09=09/* XLB + 0x48 */
+=09u32 int_enable;=09=09/* XLB + 0x4c */
+=09u32 addr_capture;=09/* XLB + 0x50 */
+=09u32 bus_sig_capture;=09/* XLB + 0x54 */
+=09u32 addr_timeout;=09/* XLB + 0x58 */
+=09u32 data_timeout;=09/* XLB + 0x5c */
+=09u32 bus_act_timeout;=09/* XLB + 0x60 */
+=09u32 master_pri_enable;=09/* XLB + 0x64 */
+=09u32 master_priority;=09/* XLB + 0x68 */
+=09u32 base_address;=09/* XLB + 0x6c */
+=09u32 snoop_window;=09/* XLB + 0x70 */
+};
+
+#define MPC52xx_XLB_CFG_PLDIS=09=09(1 << 31)
+#define MPC52xx_XLB_CFG_SNOOP=09=09(1 << 15)
+
+/* Clock Distribution control */
+struct mpc52xx_cdm {
+=09u32 jtag_id;=09=09/* CDM + 0x00  reg0 read only */
+=09u32 rstcfg;=09=09/* CDM + 0x04  reg1 read only */
+=09u32 breadcrumb;=09=09/* CDM + 0x08  reg2 */
+
+=09u8 mem_clk_sel;=09=09/* CDM + 0x0c  reg3 byte0 */
+=09u8 xlb_clk_sel;=09=09/* CDM + 0x0d  reg3 byte1 read only */
+=09u8 ipb_clk_sel;=09=09/* CDM + 0x0e  reg3 byte2 */
+=09u8 pci_clk_sel;=09=09/* CDM + 0x0f  reg3 byte3 */
+
+=09u8 ext_48mhz_en;=09/* CDM + 0x10  reg4 byte0 */
+=09u8 fd_enable;=09=09/* CDM + 0x11  reg4 byte1 */
+=09u16 fd_counters;=09/* CDM + 0x12  reg4 byte2,3 */
+
+=09u32 clk_enables;=09/* CDM + 0x14  reg5 */
+
+=09u8 osc_disable;=09=09/* CDM + 0x18  reg6 byte0 */
+=09u8 reserved0[3];=09/* CDM + 0x19  reg6 byte1,2,3 */
+
+=09u8 ccs_sleep_enable;=09/* CDM + 0x1c  reg7 byte0 */
+=09u8 osc_sleep_enable;=09/* CDM + 0x1d  reg7 byte1 */
+=09u8 reserved1;=09=09/* CDM + 0x1e  reg7 byte2 */
+=09u8 ccs_qreq_test;=09/* CDM + 0x1f  reg7 byte3 */
+
+=09u8 soft_reset;=09=09/* CDM + 0x20  u8 byte0 */
+=09u8 no_ckstp;=09=09/* CDM + 0x21  u8 byte0 */
+=09u8 reserved2[2];=09/* CDM + 0x22  u8 byte1,2,3 */
+
+=09u8 pll_lock;=09=09/* CDM + 0x24  reg9 byte0 */
+=09u8 pll_looselock;=09/* CDM + 0x25  reg9 byte1 */
+=09u8 pll_sm_lockwin;=09/* CDM + 0x26  reg9 byte2 */
+=09u8 reserved3;=09=09/* CDM + 0x27  reg9 byte3 */
+
+=09u16 reserved4;=09=09/* CDM + 0x28  reg10 byte0,1 */
+=09u16 mclken_div_psc1;=09/* CDM + 0x2a  reg10 byte2,3 */
+
+=09u16 reserved5;=09=09/* CDM + 0x2c  reg11 byte0,1 */
+=09u16 mclken_div_psc2;=09/* CDM + 0x2e  reg11 byte2,3 */
+
+=09u16 reserved6;=09=09/* CDM + 0x30  reg12 byte0,1 */
+=09u16 mclken_div_psc3;=09/* CDM + 0x32  reg12 byte2,3 */
+
+=09u16 reserved7;=09=09/* CDM + 0x34  reg13 byte0,1 */
+=09u16 mclken_div_psc6;=09/* CDM + 0x36  reg13 byte2,3 */
+};
+
+#endif /* __ASSEMBLY__ */
+
+
+/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 */
+/* Prototypes for MPC52xx sysdev                                          =
   */
+/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 */
+
+#ifndef __ASSEMBLY__
+
+extern void mpc52xx_init_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_POWERPC_MPC52xx_H__ */
+

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
@ 2006-11-06 11:03 Nicolas DET
  2006-11-06 23:35 ` Sylvain Munaut
  0 siblings, 1 reply; 27+ messages in thread
From: Nicolas DET @ 2006-11-06 11:03 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: linuxppc-embedded

[-- Attachment #1: Type: text/html, Size: 26187 bytes --]

[-- Attachment #2: Type: text/plain, Size: 23707 bytes --]

This patch add MPC52xx Interrupt controller for ARCH=powerpc.

It includes the main code in arch/powerpc/sysdev/ ad well as an header file in
include/asm-powerpc.

Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
---
--- a/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-11-06 11:10:29.000000000 +0100
@@ -0,0 +1,527 @@
+/*
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx.
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * Based on (well, mostly copied from) the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ * 
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/mpc52xx.h>
+
+/*
+ *
+*/
+
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_sdma __iomem *sdma;
+static struct irq_host *mpc52xx_irqhost = NULL;
+
+static unsigned char mpc52xx_map_senses[4] = {
+	IRQ_TYPE_LEVEL_HIGH,
+	IRQ_TYPE_EDGE_RISING,
+	IRQ_TYPE_EDGE_FALLING,
+	IRQ_TYPE_LEVEL_LOW,
+};
+
+/*
+ *
+*/
+
+static inline void io_be_setbit(u32 __iomem *addr, int bitno)
+{
+	out_be32(addr, in_be32(addr) | (1 << bitno) );
+}
+
+static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
+{
+	out_be32(addr, in_be32(addr) & ~(1 << bitno));
+}
+
+/*
+ * IRQ[0-3] interrupt irq_chip
+*/
+
+static void mpc52xx_extirq_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_ack(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->ctrl, 27-l2irq);
+}
+
+static struct irq_chip mpc52xx_extirq_irqchip = {
+	.typename = " MPC52xx IRQ[0-3] ",
+	.mask = mpc52xx_extirq_mask,
+	.unmask = mpc52xx_extirq_unmask,
+	.ack = mpc52xx_extirq_ack,
+};
+
+/*
+ * Main interrupt irq_chip
+*/
+
+static void mpc52xx_main_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->main_mask, 15 - l2irq);
+}
+
+static void mpc52xx_main_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->main_mask, 15 - l2irq);
+}
+
+static struct irq_chip mpc52xx_main_irqchip = {
+	.typename = "MPC52xx Main",
+	.mask = mpc52xx_main_mask,
+	.mask_ack = mpc52xx_main_mask,
+	.unmask = mpc52xx_main_unmask,
+};
+
+/*
+ * Peripherals interrupt irq_chip
+*/
+
+static void mpc52xx_periph_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->per_mask, 31 - l2irq);
+}
+
+static void mpc52xx_periph_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->per_mask, 31 - l2irq);
+}
+
+static struct irq_chip mpc52xx_periph_irqchip = {
+	.typename = "MPC52xx Peripherals",
+	.mask = mpc52xx_periph_mask,
+	.mask_ack = mpc52xx_periph_mask,
+	.unmask = mpc52xx_periph_unmask,
+};
+
+/*
+ * SDMA interrupt irq_chip
+*/
+
+static void mpc52xx_sdma_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_ack(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	out_be32(&sdma->IntPend, 1 << l2irq);
+}
+
+static struct irq_chip mpc52xx_sdma_irqchip = {
+	.typename = "MPC52xx SDMA",
+	.mask = mpc52xx_sdma_mask,
+	.unmask = mpc52xx_sdma_unmask,
+	.ack = mpc52xx_sdma_ack,
+};
+
+/*
+ * irq_host
+*/
+
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+	pr_debug("%s: node=%p\n", __func__, node);
+	return mpc52xx_irqhost->host_data == node;
+}
+
+static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
+				 u32 * intspec, unsigned int intsize,
+				 irq_hw_number_t * out_hwirq,
+				 unsigned int *out_flags)
+{
+	int intrvect_l1;
+	int intrvect_l2;
+	int intrvect_type;
+	int intrvect_linux;
+
+	if (intsize != 3)
+		return -1;
+
+	intrvect_l1 = (int)intspec[0];
+	intrvect_l2 = (int)intspec[1];
+	intrvect_type = (int)intspec[2];
+
+	intrvect_linux =
+	    (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
+	intrvect_linux |=
+	    (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
+
+	pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
+		 intrvect_l2);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = mpc52xx_map_senses[intrvect_type];
+
+	return 0;
+}
+
+/*
+ * this function retrieves the correct IRQ type out
+ * of the MPC regs
+ * Only externals IRQs needs this
+*/
+static int mpc52xx_irqx_gettype(int irq)
+{
+	int type;
+	u32 ctrl_reg;
+
+	ctrl_reg = in_be32(&intr->ctrl);
+	type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
+
+	return mpc52xx_map_senses[type];
+}
+
+static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+			       irq_hw_number_t irq)
+{
+	int l1irq;
+	int l2irq;
+	struct irq_chip *good_irqchip;
+	void *good_handle;
+	int type;
+
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	/*
+	 * Most of ours IRQs will be level low
+	 * Only external IRQs on some platform may be others
+	 */
+	type = IRQ_TYPE_LEVEL_LOW;
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
+
+		BUG_ON(l2irq != 0);
+
+		type = mpc52xx_irqx_gettype(l2irq);
+		good_irqchip = &mpc52xx_extirq_irqchip;
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
+
+		if ((l2irq >= 1) && (l2irq <= 3)) {
+			type = mpc52xx_irqx_gettype(l2irq);
+			good_irqchip = &mpc52xx_extirq_irqchip;
+		} else {
+			good_irqchip = &mpc52xx_main_irqchip;
+		}
+		break;
+
+	case MPC52xx_IRQ_L1_PERP:
+		pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
+		good_irqchip = &mpc52xx_periph_irqchip;
+		break;
+
+	case MPC52xx_IRQ_L1_SDMA:
+		pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
+		good_irqchip = &mpc52xx_sdma_irqchip;
+		break;
+
+	default:
+		pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq);
+		printk(KERN_ERR "Unknow IRQ!\n");
+		return -EINVAL;
+	}
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_FALLING:
+	case IRQ_TYPE_EDGE_RISING:
+		good_handle = handle_edge_irq;
+		break;
+	default:
+		good_handle = handle_level_irq;
+	}
+
+	set_irq_chip_and_handler(virq, good_irqchip, good_handle);
+
+	pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
+		 (int)irq, type);
+
+	return 0;
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+	.match = mpc52xx_irqhost_match,
+	.xlate = mpc52xx_irqhost_xlate,
+	.map = mpc52xx_irqhost_map,
+};
+
+/*
+ * init (public)
+*/
+
+void __init mpc52xx_init_irq(void)
+{
+	struct device_node *picnode = NULL;
+	int picnode_regsize;
+	u32 picnode_regoffset;
+
+	struct device_node *sdmanode = NULL;
+	int sdmanode_regsize;
+	u32 sdmanode_regoffset;
+
+	u64 size64;
+	int flags;
+
+	u32 intr_ctrl;
+
+	picnode = of_find_compatible_node(NULL, "interrupt-controller", "mpc5200-pic");
+	if (picnode == NULL) {
+		printk(KERN_ERR "MPC52xx PIC: Unable to find the interrupt controller in the OpenFirmware device tree\n");
+		goto end;
+	}
+
+	sdmanode = of_find_compatible_node(NULL, "dma-controller", "mpc5200-bestcomm");
+	if (sdmanode == NULL) {
+		printk(KERN_ERR "MPC52xx PIC: Unable to find the Bestcomm DMA controller device in the OpenFirmware device tree\n");
+		goto end;
+	}
+
+	/* Retrieve PIC ressources */
+	picnode_regoffset = (u32) of_get_address(picnode, 0, &size64, &flags);
+	if (picnode_regoffset == 0) {
+		printk(KERN_ERR "MPC52xx PIC: Unable to get the interrupt controller address\n");
+		goto end;
+	}
+
+	picnode_regoffset = of_translate_address(picnode, (u32 *) picnode_regoffset);
+	picnode_regsize = (int) size64;	
+
+	/* Retrieve SDMA ressources */
+	sdmanode_regoffset = (u32) of_get_address(sdmanode, 0, &size64, &flags);
+	if (sdmanode_regoffset == 0) {
+		printk(KERN_ERR "MPC52xx PIC: Unable to get the Bestcomm DMA controller address\n");
+		goto end;
+	}
+
+	sdmanode_regoffset = of_translate_address(sdmanode, (u32 *) sdmanode_regoffset);
+	sdmanode_regsize = (int) size64;
+
+	/* Remap the necessary zones */
+	intr = ioremap(picnode_regoffset, picnode_regsize);
+	if (intr == NULL) {
+		printk(KERN_ERR "MPC52xx PIC: Unable to ioremap interrupt controller registers!");
+		goto end;
+	}
+
+	sdma = ioremap(sdmanode_regoffset, sdmanode_regsize);
+	if (sdma == NULL) {
+		iounmap(intr);
+		printk(KERN_ERR "MPC52xx PIC: Unable to ioremap Bestcomm DMA controller registers!");
+		goto end;
+	}
+
+	printk(KERN_INFO "MPC52xx PIC: MPC52xx PIC Remapped at 0x%8.8x\n", picnode_regoffset);
+	printk(KERN_INFO "MPC52xx PIC: MPC52xx SDMA Remapped at 0x%8.8x\n", sdmanode_regoffset);
+
+	/* Disable all interrupt sources. */
+	out_be32(&sdma->IntPend, 0xffffffff);	/* 1 means clear pending */
+	out_be32(&sdma->IntMask, 0xffffffff);	/* 1 means disabled */
+	out_be32(&intr->per_mask, 0x7ffffc00);	/* 1 means disabled */
+	out_be32(&intr->main_mask, 0x00010fff);	/* 1 means disabled */
+	intr_ctrl = in_be32(&intr->ctrl);
+	intr_ctrl &= 0x00ff0000;	/* Keeps IRQ[0-3] config */
+	intr_ctrl |= 0x0f000000 |	/* clear IRQ 0-3 */
+	    0x00001000 |	/* MEE master external enable */
+	    0x00000000 |	/* 0 means disable IRQ 0-3 */
+	    0x00000001;		/* CEb route critical normally */
+	out_be32(&intr->ctrl, intr_ctrl);
+
+	/* Zero a bunch of the priority settings.  */
+	out_be32(&intr->per_pri1, 0);
+	out_be32(&intr->per_pri2, 0);
+	out_be32(&intr->per_pri3, 0);
+	out_be32(&intr->main_pri1, 0);
+	out_be32(&intr->main_pri2, 0);
+
+	/*
+	 * As last step, add an irq host to translate the real
+	 * hw irq information provided by the ofw to linux virq
+	 */
+
+	mpc52xx_irqhost =
+	    irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTHWIRQ,
+			   &mpc52xx_irqhost_ops, -1);
+
+	if (mpc52xx_irqhost) {
+		mpc52xx_irqhost->host_data = picnode;
+		printk(KERN_INFO "MPC52xx PIC is up and running!\n");
+	} else {
+		printk(KERN_ERR "MPC52xx PIC: Unable to allocate the IRQ host\n");
+	}
+
+end:
+	of_node_put(picnode);
+	of_node_put(sdmanode);
+}
+
+/*
+ * get_irq (public)
+*/
+unsigned int mpc52xx_get_irq(void)
+{
+	u32 status;
+	int irq = NO_IRQ_IGNORE;
+
+	status = in_be32(&intr->enc_status);
+	if (status & 0x00000400) {	/* critical */
+		irq = (status >> 8) & 0x3;
+		if (irq == 2)	/* high priority peripheral */
+			goto peripheral;
+		irq |=
+		    (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
+		    MPC52xx_IRQ_L1_MASK;
+	} else if (status & 0x00200000) {	/* main */
+		irq = (status >> 16) & 0x1f;
+		if (irq == 4)	/* low priority peripheral */
+			goto peripheral;
+		irq |=
+		    (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
+		    MPC52xx_IRQ_L1_MASK;
+	} else if (status & 0x20000000) {	/* peripheral */
+	      peripheral:
+		irq = (status >> 24) & 0x1f;
+		if (irq == 0) {	/* bestcomm */
+			status = in_be32(&sdma->IntPend);
+			irq = ffs(status) - 1;
+			irq |=
+			    (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
+			    MPC52xx_IRQ_L1_MASK;
+		} else
+			irq |=
+			    (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
+			    MPC52xx_IRQ_L1_MASK;
+
+	}
+
+	pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
+		 irq_linear_revmap(mpc52xx_irqhost, irq));
+
+	return irq_linear_revmap(mpc52xx_irqhost, irq);
+}
--- a/arch/powerpc/sysdev/Makefile	2006-11-01 09:18:43.000000000 +0100
+++ b/arch/powerpc/sysdev/Makefile	2006-11-06 11:10:46.000000000 +0100
@@ -13,6 +13,7 @@ obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_PPC_TODC)		+= todc.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
+obj-$(CONFIG_PPC_MPC52xx)	+= mpc52xx_pic.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
--- a/include/asm-powerpc/mpc52xx.h	1970-01-01 01:00:00.000000000 +0100
+++ b/include/asm-powerpc/mpc52xx.h	2006-11-06 11:10:29.000000000 +0100
@@ -0,0 +1,283 @@
+/*
+ * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
+ * May need to be cleaned as the port goes on ...
+ *
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __ASM_POWERPC_MPC52xx_H__
+#define __ASM_POWERPC_MPC52xx_H__
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/prom.h>
+#endif /* __ASSEMBLY__ */
+
+/* HW IRQ mapping */
+#define MPC52xx_IRQ_L1_CRIT	(0)
+#define MPC52xx_IRQ_L1_MAIN	(1)
+#define MPC52xx_IRQ_L1_PERP	(2)
+#define MPC52xx_IRQ_L1_SDMA	(3)
+
+#define MPC52xx_IRQ_L1_OFFSET   (6)
+#define MPC52xx_IRQ_L1_MASK     (0xc0)
+
+#define MPC52xx_IRQ_L2_OFFSET   (0)
+#define MPC52xx_IRQ_L2_MASK     (0x3f)
+
+#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0)
+
+/* Interrupt controller Register set */
+struct mpc52xx_intr {
+	u32 per_mask;		/* INTR + 0x00 */
+	u32 per_pri1;		/* INTR + 0x04 */
+	u32 per_pri2;		/* INTR + 0x08 */
+	u32 per_pri3;		/* INTR + 0x0c */
+	u32 ctrl;		/* INTR + 0x10 */
+	u32 main_mask;		/* INTR + 0x14 */
+	u32 main_pri1;		/* INTR + 0x18 */
+	u32 main_pri2;		/* INTR + 0x1c */
+	u32 reserved1;		/* INTR + 0x20 */
+	u32 enc_status;		/* INTR + 0x24 */
+	u32 crit_status;	/* INTR + 0x28 */
+	u32 main_status;	/* INTR + 0x2c */
+	u32 per_status;		/* INTR + 0x30 */
+	u32 reserved2;		/* INTR + 0x34 */
+	u32 per_error;		/* INTR + 0x38 */
+};
+
+
+/* ======================================================================== */
+/* Structures mapping of some unit register set                             */
+/* ======================================================================== */
+
+#ifndef __ASSEMBLY__
+
+/* Memory Mapping Control */
+struct mpc52xx_mmap_ctl {
+	u32 mbar;		/* MMAP_CTRL + 0x00 */
+
+	u32 cs0_start;		/* MMAP_CTRL + 0x04 */
+	u32 cs0_stop;		/* MMAP_CTRL + 0x08 */
+	u32 cs1_start;		/* MMAP_CTRL + 0x0c */
+	u32 cs1_stop;		/* MMAP_CTRL + 0x10 */
+	u32 cs2_start;		/* MMAP_CTRL + 0x14 */
+	u32 cs2_stop;		/* MMAP_CTRL + 0x18 */
+	u32 cs3_start;		/* MMAP_CTRL + 0x1c */
+	u32 cs3_stop;		/* MMAP_CTRL + 0x20 */
+	u32 cs4_start;		/* MMAP_CTRL + 0x24 */
+	u32 cs4_stop;		/* MMAP_CTRL + 0x28 */
+	u32 cs5_start;		/* MMAP_CTRL + 0x2c */
+	u32 cs5_stop;		/* MMAP_CTRL + 0x30 */
+
+	u32 sdram0;		/* MMAP_CTRL + 0x34 */
+	u32 sdram1;		/* MMAP_CTRL + 0X38 */
+
+	u32 reserved[4];	/* MMAP_CTRL + 0x3c .. 0x48 */
+
+	u32 boot_start;		/* MMAP_CTRL + 0x4c */
+	u32 boot_stop;		/* MMAP_CTRL + 0x50 */
+
+	u32 ipbi_ws_ctrl;	/* MMAP_CTRL + 0x54 */
+
+	u32 cs6_start;		/* MMAP_CTRL + 0x58 */
+	u32 cs6_stop;		/* MMAP_CTRL + 0x5c */
+	u32 cs7_start;		/* MMAP_CTRL + 0x60 */
+	u32 cs7_stop;		/* MMAP_CTRL + 0x64 */
+};
+
+/* SDRAM control */
+struct mpc52xx_sdram {
+	u32 mode;		/* SDRAM + 0x00 */
+	u32 ctrl;		/* SDRAM + 0x04 */
+	u32 config1;		/* SDRAM + 0x08 */
+	u32 config2;		/* SDRAM + 0x0c */
+};
+
+/* SDMA */
+struct mpc52xx_sdma {
+	u32 taskBar;		/* SDMA + 0x00 */
+	u32 currentPointer;	/* SDMA + 0x04 */
+	u32 endPointer;		/* SDMA + 0x08 */
+	u32 variablePointer;	/* SDMA + 0x0c */
+
+	u8 IntVect1;		/* SDMA + 0x10 */
+	u8 IntVect2;		/* SDMA + 0x11 */
+	u16 PtdCntrl;		/* SDMA + 0x12 */
+
+	u32 IntPend;		/* SDMA + 0x14 */
+	u32 IntMask;		/* SDMA + 0x18 */
+
+	u16 tcr[16];		/* SDMA + 0x1c .. 0x3a */
+
+	u8 ipr[32];		/* SDMA + 0x3c .. 0x5b */
+
+	u32 cReqSelect;		/* SDMA + 0x5c */
+	u32 task_size0;		/* SDMA + 0x60 */
+	u32 task_size1;		/* SDMA + 0x64 */
+	u32 MDEDebug;		/* SDMA + 0x68 */
+	u32 ADSDebug;		/* SDMA + 0x6c */
+	u32 Value1;		/* SDMA + 0x70 */
+	u32 Value2;		/* SDMA + 0x74 */
+	u32 Control;		/* SDMA + 0x78 */
+	u32 Status;		/* SDMA + 0x7c */
+	u32 PTDDebug;		/* SDMA + 0x80 */
+};
+
+/* GPT */
+struct mpc52xx_gpt {
+	u32 mode;		/* GPTx + 0x00 */
+	u32 count;		/* GPTx + 0x04 */
+	u32 pwm;		/* GPTx + 0x08 */
+	u32 status;		/* GPTx + 0X0c */
+};
+
+/* GPIO */
+struct mpc52xx_gpio {
+	u32 port_config;	/* GPIO + 0x00 */
+	u32 simple_gpioe;	/* GPIO + 0x04 */
+	u32 simple_ode;		/* GPIO + 0x08 */
+	u32 simple_ddr;		/* GPIO + 0x0c */
+	u32 simple_dvo;		/* GPIO + 0x10 */
+	u32 simple_ival;	/* GPIO + 0x14 */
+	u8 outo_gpioe;		/* GPIO + 0x18 */
+	u8 reserved1[3];	/* GPIO + 0x19 */
+	u8 outo_dvo;		/* GPIO + 0x1c */
+	u8 reserved2[3];	/* GPIO + 0x1d */
+	u8 sint_gpioe;		/* GPIO + 0x20 */
+	u8 reserved3[3];	/* GPIO + 0x21 */
+	u8 sint_ode;		/* GPIO + 0x24 */
+	u8 reserved4[3];	/* GPIO + 0x25 */
+	u8 sint_ddr;		/* GPIO + 0x28 */
+	u8 reserved5[3];	/* GPIO + 0x29 */
+	u8 sint_dvo;		/* GPIO + 0x2c */
+	u8 reserved6[3];	/* GPIO + 0x2d */
+	u8 sint_inten;		/* GPIO + 0x30 */
+	u8 reserved7[3];	/* GPIO + 0x31 */
+	u16 sint_itype;		/* GPIO + 0x34 */
+	u16 reserved8;		/* GPIO + 0x36 */
+	u8 gpio_control;	/* GPIO + 0x38 */
+	u8 reserved9[3];	/* GPIO + 0x39 */
+	u8 sint_istat;		/* GPIO + 0x3c */
+	u8 sint_ival;		/* GPIO + 0x3d */
+	u8 bus_errs;		/* GPIO + 0x3e */
+	u8 reserved10;		/* GPIO + 0x3f */
+};
+
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD	4
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD	5
+#define MPC52xx_GPIO_PCI_DIS			(1<<15)
+
+/* GPIO with WakeUp*/
+struct mpc52xx_gpio_wkup {
+	u8 wkup_gpioe;		/* GPIO_WKUP + 0x00 */
+	u8 reserved1[3];	/* GPIO_WKUP + 0x03 */
+	u8 wkup_ode;		/* GPIO_WKUP + 0x04 */
+	u8 reserved2[3];	/* GPIO_WKUP + 0x05 */
+	u8 wkup_ddr;		/* GPIO_WKUP + 0x08 */
+	u8 reserved3[3];	/* GPIO_WKUP + 0x09 */
+	u8 wkup_dvo;		/* GPIO_WKUP + 0x0C */
+	u8 reserved4[3];	/* GPIO_WKUP + 0x0D */
+	u8 wkup_inten;		/* GPIO_WKUP + 0x10 */
+	u8 reserved5[3];	/* GPIO_WKUP + 0x11 */
+	u8 wkup_iinten;		/* GPIO_WKUP + 0x14 */
+	u8 reserved6[3];	/* GPIO_WKUP + 0x15 */
+	u16 wkup_itype;		/* GPIO_WKUP + 0x18 */
+	u8 reserved7[2];	/* GPIO_WKUP + 0x1A */
+	u8 wkup_maste;		/* GPIO_WKUP + 0x1C */
+	u8 reserved8[3];	/* GPIO_WKUP + 0x1D */
+	u8 wkup_ival;		/* GPIO_WKUP + 0x20 */
+	u8 reserved9[3];	/* GPIO_WKUP + 0x21 */
+	u8 wkup_istat;		/* GPIO_WKUP + 0x24 */
+	u8 reserved10[3];	/* GPIO_WKUP + 0x25 */
+};
+
+/* XLB Bus control */
+struct mpc52xx_xlb {
+	u8 reserved[0x40];
+	u32 config;		/* XLB + 0x40 */
+	u32 version;		/* XLB + 0x44 */
+	u32 status;		/* XLB + 0x48 */
+	u32 int_enable;		/* XLB + 0x4c */
+	u32 addr_capture;	/* XLB + 0x50 */
+	u32 bus_sig_capture;	/* XLB + 0x54 */
+	u32 addr_timeout;	/* XLB + 0x58 */
+	u32 data_timeout;	/* XLB + 0x5c */
+	u32 bus_act_timeout;	/* XLB + 0x60 */
+	u32 master_pri_enable;	/* XLB + 0x64 */
+	u32 master_priority;	/* XLB + 0x68 */
+	u32 base_address;	/* XLB + 0x6c */
+	u32 snoop_window;	/* XLB + 0x70 */
+};
+
+#define MPC52xx_XLB_CFG_PLDIS		(1 << 31)
+#define MPC52xx_XLB_CFG_SNOOP		(1 << 15)
+
+/* Clock Distribution control */
+struct mpc52xx_cdm {
+	u32 jtag_id;		/* CDM + 0x00  reg0 read only */
+	u32 rstcfg;		/* CDM + 0x04  reg1 read only */
+	u32 breadcrumb;		/* CDM + 0x08  reg2 */
+
+	u8 mem_clk_sel;		/* CDM + 0x0c  reg3 byte0 */
+	u8 xlb_clk_sel;		/* CDM + 0x0d  reg3 byte1 read only */
+	u8 ipb_clk_sel;		/* CDM + 0x0e  reg3 byte2 */
+	u8 pci_clk_sel;		/* CDM + 0x0f  reg3 byte3 */
+
+	u8 ext_48mhz_en;	/* CDM + 0x10  reg4 byte0 */
+	u8 fd_enable;		/* CDM + 0x11  reg4 byte1 */
+	u16 fd_counters;	/* CDM + 0x12  reg4 byte2,3 */
+
+	u32 clk_enables;	/* CDM + 0x14  reg5 */
+
+	u8 osc_disable;		/* CDM + 0x18  reg6 byte0 */
+	u8 reserved0[3];	/* CDM + 0x19  reg6 byte1,2,3 */
+
+	u8 ccs_sleep_enable;	/* CDM + 0x1c  reg7 byte0 */
+	u8 osc_sleep_enable;	/* CDM + 0x1d  reg7 byte1 */
+	u8 reserved1;		/* CDM + 0x1e  reg7 byte2 */
+	u8 ccs_qreq_test;	/* CDM + 0x1f  reg7 byte3 */
+
+	u8 soft_reset;		/* CDM + 0x20  u8 byte0 */
+	u8 no_ckstp;		/* CDM + 0x21  u8 byte0 */
+	u8 reserved2[2];	/* CDM + 0x22  u8 byte1,2,3 */
+
+	u8 pll_lock;		/* CDM + 0x24  reg9 byte0 */
+	u8 pll_looselock;	/* CDM + 0x25  reg9 byte1 */
+	u8 pll_sm_lockwin;	/* CDM + 0x26  reg9 byte2 */
+	u8 reserved3;		/* CDM + 0x27  reg9 byte3 */
+
+	u16 reserved4;		/* CDM + 0x28  reg10 byte0,1 */
+	u16 mclken_div_psc1;	/* CDM + 0x2a  reg10 byte2,3 */
+
+	u16 reserved5;		/* CDM + 0x2c  reg11 byte0,1 */
+	u16 mclken_div_psc2;	/* CDM + 0x2e  reg11 byte2,3 */
+
+	u16 reserved6;		/* CDM + 0x30  reg12 byte0,1 */
+	u16 mclken_div_psc3;	/* CDM + 0x32  reg12 byte2,3 */
+
+	u16 reserved7;		/* CDM + 0x34  reg13 byte0,1 */
+	u16 mclken_div_psc6;	/* CDM + 0x36  reg13 byte2,3 */
+};
+
+#endif /* __ASSEMBLY__ */
+
+
+/* ========================================================================= */
+/* Prototypes for MPC52xx sysdev                                             */
+/* ========================================================================= */
+
+#ifndef __ASSEMBLY__
+
+extern void mpc52xx_init_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_POWERPC_MPC52xx_H__ */
+


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-06 11:03 Nicolas DET
@ 2006-11-06 23:35 ` Sylvain Munaut
  2006-11-07  9:22   ` Nicolas DET
  0 siblings, 1 reply; 27+ messages in thread
From: Sylvain Munaut @ 2006-11-06 23:35 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-dev, linuxppc-embedded


> +
> +	/*
> +	 * Most of ours IRQs will be level low
> +	 * Only external IRQs on some platform may be others
> +	 */
> +	type = IRQ_TYPE_LEVEL_LOW;
>   
I've been wondering : Why LEVEL_LOW ?
Aren't they LEVEL_HIGH ?
(not that it changes much here ...)


> +
> +end:
> +	of_node_put(picnode);
> +	of_node_put(sdmanode);
>   
Is of_node_put specified as resilient to NULL argument ? (in the error
path, that could happen)

Also, I think "PANIC" would be appropriate in the error path. If we
can't init
the PIC properly we may as well give up ... It's not like we're going to
do much
without it ...


> +/* HW IRQ mapping */
> +#define MPC52xx_IRQ_L1_CRIT	(0)
> +#define MPC52xx_IRQ_L1_MAIN	(1)
> +#define MPC52xx_IRQ_L1_PERP	(2)
> +#define MPC52xx_IRQ_L1_SDMA	(3)
> +
> +#define MPC52xx_IRQ_L1_OFFSET   (6)
> +#define MPC52xx_IRQ_L1_MASK     (0xc0)
> +
> +#define MPC52xx_IRQ_L2_OFFSET   (0)
> +#define MPC52xx_IRQ_L2_MASK     (0x3f)
> +
> +#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0)
> +
> +/* Interrupt controller Register set */
> +struct mpc52xx_intr {
> +	u32 per_mask;		/* INTR + 0x00 */
> +	u32 per_pri1;		/* INTR + 0x04 */
> +	u32 per_pri2;		/* INTR + 0x08 */
> +	u32 per_pri3;		/* INTR + 0x0c */
> +	u32 ctrl;		/* INTR + 0x10 */
> +	u32 main_mask;		/* INTR + 0x14 */
> +	u32 main_pri1;		/* INTR + 0x18 */
> +	u32 main_pri2;		/* INTR + 0x1c */
> +	u32 reserved1;		/* INTR + 0x20 */
> +	u32 enc_status;		/* INTR + 0x24 */
> +	u32 crit_status;	/* INTR + 0x28 */
> +	u32 main_status;	/* INTR + 0x2c */
> +	u32 per_status;		/* INTR + 0x30 */
> +	u32 reserved2;		/* INTR + 0x34 */
> +	u32 per_error;		/* INTR + 0x38 */
> +};
>   
When I said on IRC you could remerge them, I meant a little more
smartly than just 'join' them. i.e., put the mpc52xx_intr with all the
other register set at the very least ...



    Sylvain

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-06 23:35 ` Sylvain Munaut
@ 2006-11-07  9:22   ` Nicolas DET
  0 siblings, 0 replies; 27+ messages in thread
From: Nicolas DET @ 2006-11-07  9:22 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: linuxppc-dev, linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 1494 bytes --]

Sylvain Munaut wrote:
>> +
>> +	/*
>> +	 * Most of ours IRQs will be level low
>> +	 * Only external IRQs on some platform may be others
>> +	 */
>> +	type = IRQ_TYPE_LEVEL_LOW;
>>   
> I've been wondering : Why LEVEL_LOW ?
> Aren't they LEVEL_HIGH ?
> (not that it changes much here ...)
> 

It makes only sense for the ext interrupts and not for the internal 
peripherals.
I made everything level low because it's quiet common (for example: 
PCI). Moreover, On our hardware (Efika) the IRQ[0-3] are dedicated to 
the PCI.

Anyway, as the current code looks inside the chipset register to 
retrieve the real settings, the 'type' vaiiable will be overwrite if 
require.

In my opinion, others platforms (without proper hw init by the firmware) 
may overwrite the external interrupt control reg in their platforms 
specific part.

>> +
>> +end:
>> +	of_node_put(picnode);
>> +	of_node_put(sdmanode);
>>   
> Is of_node_put specified as resilient to NULL argument ? (in the error
> path, that could happen)

of_node_put() is said to be NULL pointer safe.

> 
> Also, I think "PANIC" would be appropriate in the error path. If we
> can't init
> the PIC properly we may as well give up ... It's not like we're going to
> do much
> without it ...
> 

Well, panic or not your board won't do much ;-)
Moreover, the serial console should work a bit without interrupt.

On another hand, init_IRQ may return a value to indicate it succeed or 
not. but, this is beyound the scope of this patch.

Regards,

[-- Attachment #2: nd.vcf --]
[-- Type: text/x-vcard, Size: 249 bytes --]

begin:vcard
fn:Nicolas DET ( bplan GmbH )
n:DET;Nicolas
org:bplan GmbH
adr:;;;;;;Germany
email;internet:nd@bplan-gmbh.de
title:Software Entwicklung
tel;work:+49 6171 9187 - 31
x-mozilla-html:FALSE
url:http://www.bplan-gmbh.de
version:2.1
end:vcard


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
@ 2006-11-07 10:40 Nicolas DET
  2006-11-07 10:45 ` Sylvain Munaut
  0 siblings, 1 reply; 27+ messages in thread
From: Nicolas DET @ 2006-11-07 10:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: sven, linuxppc-embedded

This patch add MPC52xx Interrupt controller for ARCH=3Dpowerpc.

It includes the main code in arch/powerpc/sysdev/ ad well as an header file=
 in
include/asm-powerpc.

The header file has now distinct section for the struct and the IRQ mapping=
/enconding define

Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
---
--- a/arch/powerpc/sysdev/mpc52xx_pic.c=091970-01-01 01:00:00.000000000 +01=
00
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c=092006-11-07 10:57:28.000000000 +01=
00
@@ -0,0 +1,527 @@
+/*
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx.
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * Based on (well, mostly copied from) the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ *=20
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/mpc52xx.h>
+
+/*
+ *
+*/
+
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_sdma __iomem *sdma;
+static struct irq_host *mpc52xx_irqhost =3D NULL;
+
+static unsigned char mpc52xx_map_senses[4] =3D {
+=09IRQ_TYPE_LEVEL_HIGH,
+=09IRQ_TYPE_EDGE_RISING,
+=09IRQ_TYPE_EDGE_FALLING,
+=09IRQ_TYPE_LEVEL_LOW,
+};
+
+/*
+ *
+*/
+
+static inline void io_be_setbit(u32 __iomem *addr, int bitno)
+{
+=09out_be32(addr, in_be32(addr) | (1 << bitno) );
+}
+
+static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
+{
+=09out_be32(addr, in_be32(addr) & ~(1 << bitno));
+}
+
+/*
+ * IRQ[0-3] interrupt irq_chip
+*/
+
+static void mpc52xx_extirq_mask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_clrbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_unmask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_setbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_ack(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_setbit(&intr->ctrl, 27-l2irq);
+}
+
+static struct irq_chip mpc52xx_extirq_irqchip =3D {
+=09.typename =3D " MPC52xx IRQ[0-3] ",
+=09.mask =3D mpc52xx_extirq_mask,
+=09.unmask =3D mpc52xx_extirq_unmask,
+=09.ack =3D mpc52xx_extirq_ack,
+};
+
+/*
+ * Main interrupt irq_chip
+*/
+
+static void mpc52xx_main_mask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_setbit(&intr->main_mask, 15 - l2irq);
+}
+
+static void mpc52xx_main_unmask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_clrbit(&intr->main_mask, 15 - l2irq);
+}
+
+static struct irq_chip mpc52xx_main_irqchip =3D {
+=09.typename =3D "MPC52xx Main",
+=09.mask =3D mpc52xx_main_mask,
+=09.mask_ack =3D mpc52xx_main_mask,
+=09.unmask =3D mpc52xx_main_unmask,
+};
+
+/*
+ * Peripherals interrupt irq_chip
+*/
+
+static void mpc52xx_periph_mask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_setbit(&intr->per_mask, 31 - l2irq);
+}
+
+static void mpc52xx_periph_unmask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_clrbit(&intr->per_mask, 31 - l2irq);
+}
+
+static struct irq_chip mpc52xx_periph_irqchip =3D {
+=09.typename =3D "MPC52xx Peripherals",
+=09.mask =3D mpc52xx_periph_mask,
+=09.mask_ack =3D mpc52xx_periph_mask,
+=09.unmask =3D mpc52xx_periph_unmask,
+};
+
+/*
+ * SDMA interrupt irq_chip
+*/
+
+static void mpc52xx_sdma_mask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_setbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_unmask(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09io_be_clrbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_ack(unsigned int virq)
+{
+=09int irq;
+=09int l2irq;
+
+=09irq =3D irq_map[virq].hwirq;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09pr_debug("%s: irq=3D%x. l2=3D%dn", __func__, irq, l2irq);
+
+=09out_be32(&sdma->IntPend, 1 << l2irq);
+}
+
+static struct irq_chip mpc52xx_sdma_irqchip =3D {
+=09.typename =3D "MPC52xx SDMA",
+=09.mask =3D mpc52xx_sdma_mask,
+=09.unmask =3D mpc52xx_sdma_unmask,
+=09.ack =3D mpc52xx_sdma_ack,
+};
+
+/*
+ * irq_host
+*/
+
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *n=
ode)
+{
+=09pr_debug("%s: node=3D%pn", __func__, node);
+=09return mpc52xx_irqhost->host_data =3D=3D node;
+}
+
+static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *c=
t,
+=09=09=09=09 u32 * intspec, unsigned int intsize,
+=09=09=09=09 irq_hw_number_t * out_hwirq,
+=09=09=09=09 unsigned int *out_flags)
+{
+=09int intrvect_l1;
+=09int intrvect_l2;
+=09int intrvect_type;
+=09int intrvect_linux;
+
+=09if (intsize !=3D 3)
+=09=09return -1;
+
+=09intrvect_l1 =3D (int)intspec[0];
+=09intrvect_l2 =3D (int)intspec[1];
+=09intrvect_type =3D (int)intspec[2];
+
+=09intrvect_linux =3D
+=09    (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
+=09intrvect_linux |=3D
+=09    (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
+
+=09pr_debug("return %x, l1=3D%d, l2=3D%dn", intrvect_linux, intrvect_l1,
+=09=09 intrvect_l2);
+
+=09*out_hwirq =3D intrvect_linux;
+=09*out_flags =3D mpc52xx_map_senses[intrvect_type];
+
+=09return 0;
+}
+
+/*
+ * this function retrieves the correct IRQ type out
+ * of the MPC regs
+ * Only externals IRQs needs this
+*/
+static int mpc52xx_irqx_gettype(int irq)
+{
+=09int type;
+=09u32 ctrl_reg;
+
+=09ctrl_reg =3D in_be32(&intr->ctrl);
+=09type =3D (ctrl_reg >> (22 - irq * 2)) & 0x3;
+
+=09return mpc52xx_map_senses[type];
+}
+
+static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+=09=09=09       irq_hw_number_t irq)
+{
+=09int l1irq;
+=09int l2irq;
+=09struct irq_chip *good_irqchip;
+=09void *good_handle;
+=09int type;
+
+=09l1irq =3D (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+=09l2irq =3D (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+=09/*
+=09 * Most of ours IRQs will be level low
+=09 * Only external IRQs on some platform may be others
+=09 */
+=09type =3D IRQ_TYPE_LEVEL_LOW;
+
+=09switch (l1irq) {
+=09case MPC52xx_IRQ_L1_CRIT:
+=09=09pr_debug("%s: Critical. l2=3D%xn", __func__, l2irq);
+
+=09=09BUG_ON(l2irq !=3D 0);
+
+=09=09type =3D mpc52xx_irqx_gettype(l2irq);
+=09=09good_irqchip =3D &mpc52xx_extirq_irqchip;
+=09=09break;
+
+=09case MPC52xx_IRQ_L1_MAIN:
+=09=09pr_debug("%s: Main IRQ[1-3] l2=3D%xn", __func__, l2irq);
+
+=09=09if ((l2irq >=3D 1) && (l2irq <=3D 3)) {
+=09=09=09type =3D mpc52xx_irqx_gettype(l2irq);
+=09=09=09good_irqchip =3D &mpc52xx_extirq_irqchip;
+=09=09} else {
+=09=09=09good_irqchip =3D &mpc52xx_main_irqchip;
+=09=09}
+=09=09break;
+
+=09case MPC52xx_IRQ_L1_PERP:
+=09=09pr_debug("%s: Peripherals. l2=3D%xn", __func__, l2irq);
+=09=09good_irqchip =3D &mpc52xx_periph_irqchip;
+=09=09break;
+
+=09case MPC52xx_IRQ_L1_SDMA:
+=09=09pr_debug("%s: SDMA. l2=3D%xn", __func__, l2irq);
+=09=09good_irqchip =3D &mpc52xx_sdma_irqchip;
+=09=09break;
+
+=09default:
+=09=09pr_debug("%s: Error, unknown L1 IRQ (0x%x)n", __func__, l1irq);
+=09=09printk(KERN_ERR "Unknow IRQ!n");
+=09=09return -EINVAL;
+=09}
+
+=09switch (type) {
+=09case IRQ_TYPE_EDGE_FALLING:
+=09case IRQ_TYPE_EDGE_RISING:
+=09=09good_handle =3D handle_edge_irq;
+=09=09break;
+=09default:
+=09=09good_handle =3D handle_level_irq;
+=09}
+
+=09set_irq_chip_and_handler(virq, good_irqchip, good_handle);
+
+=09pr_debug("%s: virq=3D%x, hw=3D%x. type=3D%xn", __func__, virq,
+=09=09 (int)irq, type);
+
+=09return 0;
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops =3D {
+=09.match =3D mpc52xx_irqhost_match,
+=09.xlate =3D mpc52xx_irqhost_xlate,
+=09.map =3D mpc52xx_irqhost_map,
+};
+
+/*
+ * init (public)
+*/
+
+void __init mpc52xx_init_irq(void)
+{
+=09struct device_node *picnode =3D NULL;
+=09int picnode_regsize;
+=09u32 picnode_regoffset;
+
+=09struct device_node *sdmanode =3D NULL;
+=09int sdmanode_regsize;
+=09u32 sdmanode_regoffset;
+
+=09u64 size64;
+=09int flags;
+
+=09u32 intr_ctrl;
+
+=09picnode =3D of_find_compatible_node(NULL, "interrupt-controller", "mpc5=
200-pic");
+=09if (picnode =3D=3D NULL) {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to find the interrupt controlle=
r in the OpenFirmware device treen");
+=09=09goto end;
+=09}
+
+=09sdmanode =3D of_find_compatible_node(NULL, "dma-controller", "mpc5200-b=
estcomm");
+=09if (sdmanode =3D=3D NULL) {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to find the Bestcomm DMA contro=
ller device in the OpenFirmware device treen");
+=09=09goto end;
+=09}
+
+=09/* Retrieve PIC ressources */
+=09picnode_regoffset =3D (u32) of_get_address(picnode, 0, &size64, &flags)=
;
+=09if (picnode_regoffset =3D=3D 0) {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to get the interrupt controller=
 addressn");
+=09=09goto end;
+=09}
+
+=09picnode_regoffset =3D of_translate_address(picnode, (u32 *) picnode_reg=
offset);
+=09picnode_regsize =3D (int) size64;=09
+
+=09/* Retrieve SDMA ressources */
+=09sdmanode_regoffset =3D (u32) of_get_address(sdmanode, 0, &size64, &flag=
s);
+=09if (sdmanode_regoffset =3D=3D 0) {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to get the Bestcomm DMA control=
ler addressn");
+=09=09goto end;
+=09}
+
+=09sdmanode_regoffset =3D of_translate_address(sdmanode, (u32 *) sdmanode_=
regoffset);
+=09sdmanode_regsize =3D (int) size64;
+
+=09/* Remap the necessary zones */
+=09intr =3D ioremap(picnode_regoffset, picnode_regsize);
+=09if (intr =3D=3D NULL) {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to ioremap interrupt controller=
 registers!");
+=09=09goto end;
+=09}
+
+=09sdma =3D ioremap(sdmanode_regoffset, sdmanode_regsize);
+=09if (sdma =3D=3D NULL) {
+=09=09iounmap(intr);
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to ioremap Bestcomm DMA control=
ler registers!");
+=09=09goto end;
+=09}
+
+=09printk(KERN_INFO "MPC52xx PIC: MPC52xx PIC Remapped at 0x%8.8xn", picno=
de_regoffset);
+=09printk(KERN_INFO "MPC52xx PIC: MPC52xx SDMA Remapped at 0x%8.8xn", sdma=
node_regoffset);
+
+=09/* Disable all interrupt sources. */
+=09out_be32(&sdma->IntPend, 0xffffffff);=09/* 1 means clear pending */
+=09out_be32(&sdma->IntMask, 0xffffffff);=09/* 1 means disabled */
+=09out_be32(&intr->per_mask, 0x7ffffc00);=09/* 1 means disabled */
+=09out_be32(&intr->main_mask, 0x00010fff);=09/* 1 means disabled */
+=09intr_ctrl =3D in_be32(&intr->ctrl);
+=09intr_ctrl &=3D 0x00ff0000;=09/* Keeps IRQ[0-3] config */
+=09intr_ctrl |=3D 0x0f000000 |=09/* clear IRQ 0-3 */
+=09    0x00001000 |=09/* MEE master external enable */
+=09    0x00000000 |=09/* 0 means disable IRQ 0-3 */
+=09    0x00000001;=09=09/* CEb route critical normally */
+=09out_be32(&intr->ctrl, intr_ctrl);
+
+=09/* Zero a bunch of the priority settings.  */
+=09out_be32(&intr->per_pri1, 0);
+=09out_be32(&intr->per_pri2, 0);
+=09out_be32(&intr->per_pri3, 0);
+=09out_be32(&intr->main_pri1, 0);
+=09out_be32(&intr->main_pri2, 0);
+
+=09/*
+=09 * As last step, add an irq host to translate the real
+=09 * hw irq information provided by the ofw to linux virq
+=09 */
+
+=09mpc52xx_irqhost =3D
+=09    irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTHWIRQ,
+=09=09=09   &mpc52xx_irqhost_ops, -1);
+
+=09if (mpc52xx_irqhost) {
+=09=09mpc52xx_irqhost->host_data =3D picnode;
+=09=09printk(KERN_INFO "MPC52xx PIC is up and running!n");
+=09} else {
+=09=09printk(KERN_ERR "MPC52xx PIC: Unable to allocate the IRQ hostn");
+=09}
+
+end:
+=09of_node_put(picnode);
+=09of_node_put(sdmanode);
+}
+
+/*
+ * get_irq (public)
+*/
+unsigned int mpc52xx_get_irq(void)
+{
+=09u32 status;
+=09int irq =3D NO_IRQ_IGNORE;
+
+=09status =3D in_be32(&intr->enc_status);
+=09if (status & 0x00000400) {=09/* critical */
+=09=09irq =3D (status >> 8) & 0x3;
+=09=09if (irq =3D=3D 2)=09/* high priority peripheral */
+=09=09=09goto peripheral;
+=09=09irq |=3D
+=09=09    (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
+=09=09    MPC52xx_IRQ_L1_MASK;
+=09} else if (status & 0x00200000) {=09/* main */
+=09=09irq =3D (status >> 16) & 0x1f;
+=09=09if (irq =3D=3D 4)=09/* low priority peripheral */
+=09=09=09goto peripheral;
+=09=09irq |=3D
+=09=09    (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
+=09=09    MPC52xx_IRQ_L1_MASK;
+=09} else if (status & 0x20000000) {=09/* peripheral */
+=09      peripheral:
+=09=09irq =3D (status >> 24) & 0x1f;
+=09=09if (irq =3D=3D 0) {=09/* bestcomm */
+=09=09=09status =3D in_be32(&sdma->IntPend);
+=09=09=09irq =3D ffs(status) - 1;
+=09=09=09irq |=3D
+=09=09=09    (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
+=09=09=09    MPC52xx_IRQ_L1_MASK;
+=09=09} else
+=09=09=09irq |=3D
+=09=09=09    (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
+=09=09=09    MPC52xx_IRQ_L1_MASK;
+
+=09}
+
+=09pr_debug("%s: irq=3D%x. virq=3D%dn", __func__, irq,
+=09=09 irq_linear_revmap(mpc52xx_irqhost, irq));
+
+=09return irq_linear_revmap(mpc52xx_irqhost, irq);
+}
--- a/arch/powerpc/sysdev/Makefile=092006-11-01 09:18:43.000000000 +0100
+++ b/arch/powerpc/sysdev/Makefile=092006-11-07 11:21:25.000000000 +0100
@@ -13,6 +13,7 @@ obj-$(CONFIG_FSL_SOC)=09=09+=3D fsl_soc.o
 obj-$(CONFIG_PPC_TODC)=09=09+=3D todc.o
 obj-$(CONFIG_TSI108_BRIDGE)=09+=3D tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)=09+=3D qe_lib/
+obj-$(CONFIG_PPC_MPC52xx)=09+=3D mpc52xx_pic.o
=20
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)=09=09+=3D i8259.o
--- a/include/asm-powerpc/mpc52xx.h=091970-01-01 01:00:00.000000000 +0100
+++ b/include/asm-powerpc/mpc52xx.h=092006-11-07 10:57:28.000000000 +0100
@@ -0,0 +1,285 @@
+/*
+ * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
+ * May need to be cleaned as the port goes on ...
+ *
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __ASM_POWERPC_MPC52xx_H__
+#define __ASM_POWERPC_MPC52xx_H__
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/prom.h>
+#endif /* __ASSEMBLY__ */
+
+/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */
+/* HW IRQ mapping                                                         =
  */
+/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */
+
+#define MPC52xx_IRQ_L1_CRIT=09(0)
+#define MPC52xx_IRQ_L1_MAIN=09(1)
+#define MPC52xx_IRQ_L1_PERP=09(2)
+#define MPC52xx_IRQ_L1_SDMA=09(3)
+
+#define MPC52xx_IRQ_L1_OFFSET   (6)
+#define MPC52xx_IRQ_L1_MASK     (0xc0)
+
+#define MPC52xx_IRQ_L2_OFFSET   (0)
+#define MPC52xx_IRQ_L2_MASK     (0x3f)
+
+#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0)
+
+/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */
+/* Structures mapping of some unit register set                           =
  */
+/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */
+
+#ifndef __ASSEMBLY__
+
+/* Interrupt controller Register set */
+struct mpc52xx_intr {
+=09u32 per_mask;=09=09/* INTR + 0x00 */
+=09u32 per_pri1;=09=09/* INTR + 0x04 */
+=09u32 per_pri2;=09=09/* INTR + 0x08 */
+=09u32 per_pri3;=09=09/* INTR + 0x0c */
+=09u32 ctrl;=09=09/* INTR + 0x10 */
+=09u32 main_mask;=09=09/* INTR + 0x14 */
+=09u32 main_pri1;=09=09/* INTR + 0x18 */
+=09u32 main_pri2;=09=09/* INTR + 0x1c */
+=09u32 reserved1;=09=09/* INTR + 0x20 */
+=09u32 enc_status;=09=09/* INTR + 0x24 */
+=09u32 crit_status;=09/* INTR + 0x28 */
+=09u32 main_status;=09/* INTR + 0x2c */
+=09u32 per_status;=09=09/* INTR + 0x30 */
+=09u32 reserved2;=09=09/* INTR + 0x34 */
+=09u32 per_error;=09=09/* INTR + 0x38 */
+};
+
+/* Memory Mapping Control */
+struct mpc52xx_mmap_ctl {
+=09u32 mbar;=09=09/* MMAP_CTRL + 0x00 */
+
+=09u32 cs0_start;=09=09/* MMAP_CTRL + 0x04 */
+=09u32 cs0_stop;=09=09/* MMAP_CTRL + 0x08 */
+=09u32 cs1_start;=09=09/* MMAP_CTRL + 0x0c */
+=09u32 cs1_stop;=09=09/* MMAP_CTRL + 0x10 */
+=09u32 cs2_start;=09=09/* MMAP_CTRL + 0x14 */
+=09u32 cs2_stop;=09=09/* MMAP_CTRL + 0x18 */
+=09u32 cs3_start;=09=09/* MMAP_CTRL + 0x1c */
+=09u32 cs3_stop;=09=09/* MMAP_CTRL + 0x20 */
+=09u32 cs4_start;=09=09/* MMAP_CTRL + 0x24 */
+=09u32 cs4_stop;=09=09/* MMAP_CTRL + 0x28 */
+=09u32 cs5_start;=09=09/* MMAP_CTRL + 0x2c */
+=09u32 cs5_stop;=09=09/* MMAP_CTRL + 0x30 */
+
+=09u32 sdram0;=09=09/* MMAP_CTRL + 0x34 */
+=09u32 sdram1;=09=09/* MMAP_CTRL + 0X38 */
+
+=09u32 reserved[4];=09/* MMAP_CTRL + 0x3c .. 0x48 */
+
+=09u32 boot_start;=09=09/* MMAP_CTRL + 0x4c */
+=09u32 boot_stop;=09=09/* MMAP_CTRL + 0x50 */
+
+=09u32 ipbi_ws_ctrl;=09/* MMAP_CTRL + 0x54 */
+
+=09u32 cs6_start;=09=09/* MMAP_CTRL + 0x58 */
+=09u32 cs6_stop;=09=09/* MMAP_CTRL + 0x5c */
+=09u32 cs7_start;=09=09/* MMAP_CTRL + 0x60 */
+=09u32 cs7_stop;=09=09/* MMAP_CTRL + 0x64 */
+};
+
+/* SDRAM control */
+struct mpc52xx_sdram {
+=09u32 mode;=09=09/* SDRAM + 0x00 */
+=09u32 ctrl;=09=09/* SDRAM + 0x04 */
+=09u32 config1;=09=09/* SDRAM + 0x08 */
+=09u32 config2;=09=09/* SDRAM + 0x0c */
+};
+
+/* SDMA */
+struct mpc52xx_sdma {
+=09u32 taskBar;=09=09/* SDMA + 0x00 */
+=09u32 currentPointer;=09/* SDMA + 0x04 */
+=09u32 endPointer;=09=09/* SDMA + 0x08 */
+=09u32 variablePointer;=09/* SDMA + 0x0c */
+
+=09u8 IntVect1;=09=09/* SDMA + 0x10 */
+=09u8 IntVect2;=09=09/* SDMA + 0x11 */
+=09u16 PtdCntrl;=09=09/* SDMA + 0x12 */
+
+=09u32 IntPend;=09=09/* SDMA + 0x14 */
+=09u32 IntMask;=09=09/* SDMA + 0x18 */
+
+=09u16 tcr[16];=09=09/* SDMA + 0x1c .. 0x3a */
+
+=09u8 ipr[32];=09=09/* SDMA + 0x3c .. 0x5b */
+
+=09u32 cReqSelect;=09=09/* SDMA + 0x5c */
+=09u32 task_size0;=09=09/* SDMA + 0x60 */
+=09u32 task_size1;=09=09/* SDMA + 0x64 */
+=09u32 MDEDebug;=09=09/* SDMA + 0x68 */
+=09u32 ADSDebug;=09=09/* SDMA + 0x6c */
+=09u32 Value1;=09=09/* SDMA + 0x70 */
+=09u32 Value2;=09=09/* SDMA + 0x74 */
+=09u32 Control;=09=09/* SDMA + 0x78 */
+=09u32 Status;=09=09/* SDMA + 0x7c */
+=09u32 PTDDebug;=09=09/* SDMA + 0x80 */
+};
+
+/* GPT */
+struct mpc52xx_gpt {
+=09u32 mode;=09=09/* GPTx + 0x00 */
+=09u32 count;=09=09/* GPTx + 0x04 */
+=09u32 pwm;=09=09/* GPTx + 0x08 */
+=09u32 status;=09=09/* GPTx + 0X0c */
+};
+
+/* GPIO */
+struct mpc52xx_gpio {
+=09u32 port_config;=09/* GPIO + 0x00 */
+=09u32 simple_gpioe;=09/* GPIO + 0x04 */
+=09u32 simple_ode;=09=09/* GPIO + 0x08 */
+=09u32 simple_ddr;=09=09/* GPIO + 0x0c */
+=09u32 simple_dvo;=09=09/* GPIO + 0x10 */
+=09u32 simple_ival;=09/* GPIO + 0x14 */
+=09u8 outo_gpioe;=09=09/* GPIO + 0x18 */
+=09u8 reserved1[3];=09/* GPIO + 0x19 */
+=09u8 outo_dvo;=09=09/* GPIO + 0x1c */
+=09u8 reserved2[3];=09/* GPIO + 0x1d */
+=09u8 sint_gpioe;=09=09/* GPIO + 0x20 */
+=09u8 reserved3[3];=09/* GPIO + 0x21 */
+=09u8 sint_ode;=09=09/* GPIO + 0x24 */
+=09u8 reserved4[3];=09/* GPIO + 0x25 */
+=09u8 sint_ddr;=09=09/* GPIO + 0x28 */
+=09u8 reserved5[3];=09/* GPIO + 0x29 */
+=09u8 sint_dvo;=09=09/* GPIO + 0x2c */
+=09u8 reserved6[3];=09/* GPIO + 0x2d */
+=09u8 sint_inten;=09=09/* GPIO + 0x30 */
+=09u8 reserved7[3];=09/* GPIO + 0x31 */
+=09u16 sint_itype;=09=09/* GPIO + 0x34 */
+=09u16 reserved8;=09=09/* GPIO + 0x36 */
+=09u8 gpio_control;=09/* GPIO + 0x38 */
+=09u8 reserved9[3];=09/* GPIO + 0x39 */
+=09u8 sint_istat;=09=09/* GPIO + 0x3c */
+=09u8 sint_ival;=09=09/* GPIO + 0x3d */
+=09u8 bus_errs;=09=09/* GPIO + 0x3e */
+=09u8 reserved10;=09=09/* GPIO + 0x3f */
+};
+
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD=094
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD=095
+#define MPC52xx_GPIO_PCI_DIS=09=09=09(1<<15)
+
+/* GPIO with WakeUp*/
+struct mpc52xx_gpio_wkup {
+=09u8 wkup_gpioe;=09=09/* GPIO_WKUP + 0x00 */
+=09u8 reserved1[3];=09/* GPIO_WKUP + 0x03 */
+=09u8 wkup_ode;=09=09/* GPIO_WKUP + 0x04 */
+=09u8 reserved2[3];=09/* GPIO_WKUP + 0x05 */
+=09u8 wkup_ddr;=09=09/* GPIO_WKUP + 0x08 */
+=09u8 reserved3[3];=09/* GPIO_WKUP + 0x09 */
+=09u8 wkup_dvo;=09=09/* GPIO_WKUP + 0x0C */
+=09u8 reserved4[3];=09/* GPIO_WKUP + 0x0D */
+=09u8 wkup_inten;=09=09/* GPIO_WKUP + 0x10 */
+=09u8 reserved5[3];=09/* GPIO_WKUP + 0x11 */
+=09u8 wkup_iinten;=09=09/* GPIO_WKUP + 0x14 */
+=09u8 reserved6[3];=09/* GPIO_WKUP + 0x15 */
+=09u16 wkup_itype;=09=09/* GPIO_WKUP + 0x18 */
+=09u8 reserved7[2];=09/* GPIO_WKUP + 0x1A */
+=09u8 wkup_maste;=09=09/* GPIO_WKUP + 0x1C */
+=09u8 reserved8[3];=09/* GPIO_WKUP + 0x1D */
+=09u8 wkup_ival;=09=09/* GPIO_WKUP + 0x20 */
+=09u8 reserved9[3];=09/* GPIO_WKUP + 0x21 */
+=09u8 wkup_istat;=09=09/* GPIO_WKUP + 0x24 */
+=09u8 reserved10[3];=09/* GPIO_WKUP + 0x25 */
+};
+
+/* XLB Bus control */
+struct mpc52xx_xlb {
+=09u8 reserved[0x40];
+=09u32 config;=09=09/* XLB + 0x40 */
+=09u32 version;=09=09/* XLB + 0x44 */
+=09u32 status;=09=09/* XLB + 0x48 */
+=09u32 int_enable;=09=09/* XLB + 0x4c */
+=09u32 addr_capture;=09/* XLB + 0x50 */
+=09u32 bus_sig_capture;=09/* XLB + 0x54 */
+=09u32 addr_timeout;=09/* XLB + 0x58 */
+=09u32 data_timeout;=09/* XLB + 0x5c */
+=09u32 bus_act_timeout;=09/* XLB + 0x60 */
+=09u32 master_pri_enable;=09/* XLB + 0x64 */
+=09u32 master_priority;=09/* XLB + 0x68 */
+=09u32 base_address;=09/* XLB + 0x6c */
+=09u32 snoop_window;=09/* XLB + 0x70 */
+};
+
+#define MPC52xx_XLB_CFG_PLDIS=09=09(1 << 31)
+#define MPC52xx_XLB_CFG_SNOOP=09=09(1 << 15)
+
+/* Clock Distribution control */
+struct mpc52xx_cdm {
+=09u32 jtag_id;=09=09/* CDM + 0x00  reg0 read only */
+=09u32 rstcfg;=09=09/* CDM + 0x04  reg1 read only */
+=09u32 breadcrumb;=09=09/* CDM + 0x08  reg2 */
+
+=09u8 mem_clk_sel;=09=09/* CDM + 0x0c  reg3 byte0 */
+=09u8 xlb_clk_sel;=09=09/* CDM + 0x0d  reg3 byte1 read only */
+=09u8 ipb_clk_sel;=09=09/* CDM + 0x0e  reg3 byte2 */
+=09u8 pci_clk_sel;=09=09/* CDM + 0x0f  reg3 byte3 */
+
+=09u8 ext_48mhz_en;=09/* CDM + 0x10  reg4 byte0 */
+=09u8 fd_enable;=09=09/* CDM + 0x11  reg4 byte1 */
+=09u16 fd_counters;=09/* CDM + 0x12  reg4 byte2,3 */
+
+=09u32 clk_enables;=09/* CDM + 0x14  reg5 */
+
+=09u8 osc_disable;=09=09/* CDM + 0x18  reg6 byte0 */
+=09u8 reserved0[3];=09/* CDM + 0x19  reg6 byte1,2,3 */
+
+=09u8 ccs_sleep_enable;=09/* CDM + 0x1c  reg7 byte0 */
+=09u8 osc_sleep_enable;=09/* CDM + 0x1d  reg7 byte1 */
+=09u8 reserved1;=09=09/* CDM + 0x1e  reg7 byte2 */
+=09u8 ccs_qreq_test;=09/* CDM + 0x1f  reg7 byte3 */
+
+=09u8 soft_reset;=09=09/* CDM + 0x20  u8 byte0 */
+=09u8 no_ckstp;=09=09/* CDM + 0x21  u8 byte0 */
+=09u8 reserved2[2];=09/* CDM + 0x22  u8 byte1,2,3 */
+
+=09u8 pll_lock;=09=09/* CDM + 0x24  reg9 byte0 */
+=09u8 pll_looselock;=09/* CDM + 0x25  reg9 byte1 */
+=09u8 pll_sm_lockwin;=09/* CDM + 0x26  reg9 byte2 */
+=09u8 reserved3;=09=09/* CDM + 0x27  reg9 byte3 */
+
+=09u16 reserved4;=09=09/* CDM + 0x28  reg10 byte0,1 */
+=09u16 mclken_div_psc1;=09/* CDM + 0x2a  reg10 byte2,3 */
+
+=09u16 reserved5;=09=09/* CDM + 0x2c  reg11 byte0,1 */
+=09u16 mclken_div_psc2;=09/* CDM + 0x2e  reg11 byte2,3 */
+
+=09u16 reserved6;=09=09/* CDM + 0x30  reg12 byte0,1 */
+=09u16 mclken_div_psc3;=09/* CDM + 0x32  reg12 byte2,3 */
+
+=09u16 reserved7;=09=09/* CDM + 0x34  reg13 byte0,1 */
+=09u16 mclken_div_psc6;=09/* CDM + 0x36  reg13 byte2,3 */
+};
+
+#endif /* __ASSEMBLY__ */
+
+
+/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 */
+/* Prototypes for MPC52xx sysdev                                          =
   */
+/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 */
+
+#ifndef __ASSEMBLY__
+
+extern void mpc52xx_init_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_POWERPC_MPC52xx_H__ */
+

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-07 10:40 Nicolas DET
@ 2006-11-07 10:45 ` Sylvain Munaut
  2006-11-07 16:30   ` Grant Likely
  0 siblings, 1 reply; 27+ messages in thread
From: Sylvain Munaut @ 2006-11-07 10:45 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-dev, sven, linuxppc-embedded

Nicolas DET wrote:

> This patch add MPC52xx Interrupt controller for ARCH=powerpc.
>
> It includes the main code in arch/powerpc/sysdev/ ad well as an header file in
> include/asm-powerpc.
>
> The header file has now distinct section for the struct and the IRQ mapping/enconding define
>
> Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
Acked-by: Sylvain Munaut <tnt@246tNt.com>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-07 10:45 ` Sylvain Munaut
@ 2006-11-07 16:30   ` Grant Likely
  2006-11-07 20:52     ` Sylvain Munaut
  0 siblings, 1 reply; 27+ messages in thread
From: Grant Likely @ 2006-11-07 16:30 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: linuxppc-dev, sven, linuxppc-embedded

On 11/7/06, Sylvain Munaut <tnt@246tnt.com> wrote:
> Nicolas DET wrote:
>
> > This patch add MPC52xx Interrupt controller for ARCH=powerpc.
> >
> > It includes the main code in arch/powerpc/sysdev/ ad well as an header file in
> > include/asm-powerpc.
> >
> > The header file has now distinct section for the struct and the IRQ mapping/enconding define
> >
> > Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
> Acked-by: Sylvain Munaut <tnt@246tNt.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>

-- 
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support.
  2006-11-07 16:30   ` Grant Likely
@ 2006-11-07 20:52     ` Sylvain Munaut
  0 siblings, 0 replies; 27+ messages in thread
From: Sylvain Munaut @ 2006-11-07 20:52 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev, sven, linuxppc-embedded

Grant Likely wrote:
> On 11/7/06, Sylvain Munaut <tnt@246tnt.com> wrote:
>> Nicolas DET wrote:
>>
>> > This patch add MPC52xx Interrupt controller for ARCH=powerpc.
>> >
>> > It includes the main code in arch/powerpc/sysdev/ ad well as an
>> header file in
>> > include/asm-powerpc.
>> >
>> > The header file has now distinct section for the struct and the IRQ
>> mapping/enconding define
>> >
>> > Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
>> Acked-by: Sylvain Munaut <tnt@246tNt.com>
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
>
OOps ... sorry NAK ...

All your strings got screwed up ... all your \n got replaced by just n ...

And while your at it there is two extraneous whitespace, might be a good
time to get rid
of them. One in the comment header and one after a "size64".


    Sylvain

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2006-11-07 20:52 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-01 20:27 [PATCH/RFC] powerpc: Add MPC5200 Interrupt Controller support Nicolas DET
2006-11-01 22:05 ` Dale Farnsworth
2006-11-01 22:07   ` Sven Luther
2006-11-01 22:21     ` Dale Farnsworth
2006-11-01 22:12 ` Benjamin Herrenschmidt
2006-11-02 16:27   ` Nicolas DET
2006-11-02 20:47     ` Nicolas DET
2006-11-04 23:35       ` Benjamin Herrenschmidt
2006-11-05  0:27         ` Sylvain Munaut
2006-11-05  1:13           ` Benjamin Herrenschmidt
2006-11-06  6:28             ` Grant Likely
2006-11-06  8:39               ` Sylvain Munaut
2006-11-05 10:17         ` Nicolas DET
2006-11-05 10:37           ` Benjamin Herrenschmidt
2006-11-05 11:30             ` Nicolas DET
2006-11-05 13:02               ` Benjamin Herrenschmidt
2006-11-05 13:16                 ` Nicolas DET
2006-11-05 14:32                 ` Sylvain Munaut
2006-11-06  6:55       ` Grant Likely
  -- strict thread matches above, loose matches on Subject: below --
2006-11-06 10:26 Nicolas DET
2006-11-06 11:03 Nicolas DET
2006-11-06 23:35 ` Sylvain Munaut
2006-11-07  9:22   ` Nicolas DET
2006-11-07 10:40 Nicolas DET
2006-11-07 10:45 ` Sylvain Munaut
2006-11-07 16:30   ` Grant Likely
2006-11-07 20:52     ` Sylvain Munaut

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).