linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] General CHRP/MPC5K2 platform support patch
@ 2006-10-25 19:05 Nicolas DET
  2006-10-25 21:59 ` Paul Mackerras
                   ` (3 more replies)
  0 siblings, 4 replies; 40+ messages in thread
From: Nicolas DET @ 2006-10-25 19:05 UTC (permalink / raw)
  To: linuxppc-dev, sl, akpm, Benjamin Herrenschmidt, Sylvain Munaut,
	grant.likely, linuxppc-embedded, sha

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

This patch add support for MPC52xx/CHRP/OFW platform.

It contains the minimal changes required: platform/chrp/ and the
interrupt controller code.

This one is slightly different than the one I submitted previously.
http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027133.html

* /proc/ppc64/rtas/ I left it for now. It's not really the concern of
this patch.

* mpc5k2_bestcomm.c (& helpers): I've been in contact with others people
using bestcomm and please to see the development was still active. I'm
already using latest code on my board but this is not include in this
patch. Indeed, it needs some changes for ARCH=powerpc. Moreover, we have
a different approach for the tasks. I'll be pleased to work with the
bestcomm folks.

* mpc5k2.c: As far as I understood, using of_platform_device will allow
'smart' of tree parsing. I did not implement it yet.

* mpc5k2_pic.c : The thingy ;-). I moved it into arch/powerpc/sysdev as
suggested. This code is 99% copy/paste from the ARCH=ppc. I added an
irq_host with the appropriate xlate and co. However, I have not done
more as this code has been written by others. I think we should work
together to move to new Linux style irq. I stay ready to test or code
upcoming revision/

* arch/powerpc/platform/*. Here, only small changes has been made. I
added _CHRP_E5K2 (in asm/processor.h), an entry in chrp_names() and the
correct detection in arch/powerpc/platform/setup.c / chrp_setup_arch().
in chrp_init_IRQ(), I set ppc_md.get_irq to mpc52xx_get_irq and call
mpc52xx_init_irq().

* fec driver: I did not wrote it and just made small modification to
make it works with our bestcomm API. However, we will soon you the same.
I think this is out of topic for his patch.

* serial stuff / IBP Freq. As this frequency is MPC52xx specific. I
think it would make sense to add a new func mpc52xx_getipbfreq(void).
The way it would be implemented may depend of the architecture. Our
firmware contains an 'ipb-freq' property in '/builtin/'.


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




[-- Attachment #2: chrpmpc52xx_2.6.19-rc3.patch --]
[-- Type: text/plain, Size: 15074 bytes --]

diff -uprN a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
--- a/arch/powerpc/platforms/chrp/setup.c	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/platforms/chrp/setup.c	2006-10-25 19:10:18.000000000 +0200
@@ -51,6 +51,7 @@
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 #include <asm/xmon.h>
+#include <asm/mpc52xx.h>
 
 #include "chrp.h"
 
@@ -101,7 +102,8 @@ static const char *chrp_names[] = {
 	"Motorola",
 	"IBM or Longtrail",
 	"Genesi Pegasos",
-	"Total Impact Briq"
+	"Total Impact Briq",
+	"bPlan Efika"
 };
 
 void chrp_show_cpuinfo(struct seq_file *m)
@@ -260,6 +262,8 @@ void __init chrp_setup_arch(void)
 		machine = get_property(root, "model", NULL);
 	if (machine && strncmp(machine, "Pegasos", 7) == 0) {
 		_chrp_type = _CHRP_Pegasos;
+	} else if (machine && strncmp(machine, "EFIKA5K2", 8) == 0) {
+		_chrp_type =_CHRP_E5K2;
 	} else if (machine && strncmp(machine, "IBM", 3) == 0) {
 		_chrp_type = _CHRP_IBM;
 	} else if (machine && strncmp(machine, "MOT", 3) == 0) {
@@ -494,6 +498,12 @@ void __init chrp_init_IRQ(void)
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
 	struct device_node *kbd;
 #endif
+	if (_chrp_type ==  _CHRP_E5K2) {
+		ppc_md.get_irq = mpc52xx_get_irq;
+		mpc52xx_init_irq();
+		return;
+	}
+
 	chrp_find_openpic();
 	chrp_find_8259();
 
@@ -530,6 +540,9 @@ chrp_init2(void)
 	chrp_nvram_init();
 #endif
 
+	if (_chrp_type == _CHRP_E5K2)
+		return;
+
 	request_region(0x20,0x20,"pic1");
 	request_region(0xa0,0x20,"pic2");
 	request_region(0x00,0x20,"dma1");
diff -uprN a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
--- a/include/asm-powerpc/processor.h	2006-10-25 19:07:48.000000000 +0200
+++ b/include/asm-powerpc/processor.h	2006-10-25 19:11:54.000000000 +0200
@@ -33,6 +33,7 @@
 #define _CHRP_IBM	0x05	/* IBM chrp, the longtrail and longtrail 2 */
 #define _CHRP_Pegasos	0x06	/* Genesi/bplan's Pegasos and Pegasos2 */
 #define _CHRP_briq	0x07	/* TotalImpact's briQ */
+#define _CHRP_E5K2	0x08	/* bPlan's Efika 5k2*/
 
 #if defined(__KERNEL__) && defined(CONFIG_PPC32)
 
diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
--- a/include/asm-ppc/mpc52xx.h	2006-10-25 19:07:48.000000000 +0200
+++ b/include/asm-ppc/mpc52xx.h	2006-10-25 19:11:55.000000000 +0200
@@ -119,7 +119,7 @@ enum ppc_sys_devices {
 #define MPC52xx_SDMA_IRQ_NUM	17
 #define MPC52xx_PERP_IRQ_NUM	23
 
-#define MPC52xx_CRIT_IRQ_BASE	1
+#define MPC52xx_CRIT_IRQ_BASE	0
 #define MPC52xx_MAIN_IRQ_BASE	(MPC52xx_CRIT_IRQ_BASE + MPC52xx_CRIT_IRQ_NUM)
 #define MPC52xx_SDMA_IRQ_BASE	(MPC52xx_MAIN_IRQ_BASE + MPC52xx_MAIN_IRQ_NUM)
 #define MPC52xx_PERP_IRQ_BASE	(MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)
@@ -415,7 +415,7 @@ struct mpc52xx_cdm {
 #ifndef __ASSEMBLY__
 
 extern void mpc52xx_init_irq(void);
-extern int mpc52xx_get_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
 
 extern unsigned long mpc52xx_find_end_of_memory(void);
 extern void mpc52xx_set_bat(void);
--- a/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-25 19:17:48.000000000 +0200
@@ -0,0 +1,375 @@
+/*
+ * arch/powerpc/platforms/mpc5k2_pic.c
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx 
+ * embedded CPU.
+ * Modified for CHRP Efika 5K2
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+//#define 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 <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 void
+mpc52xx_ic_disable(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        if (irq == MPC52xx_IRQ0) {
+                val = in_be32(&intr->ctrl);
+                val &= ~(1 << 11);
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_IRQ1) {
+                BUG();
+        } else if (irq <= MPC52xx_IRQ3) {
+                val = in_be32(&intr->ctrl);
+                val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+                val = in_be32(&intr->main_mask);
+                val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
+                out_be32(&intr->main_mask, val);
+        } else if (irq < MPC52xx_PERP_IRQ_BASE) {
+                val = in_be32(&sdma->IntMask);
+                val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
+                out_be32(&sdma->IntMask, val);
+        } else {
+                val = in_be32(&intr->per_mask);
+                val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
+                out_be32(&intr->per_mask, val);
+        }
+}
+
+static void
+mpc52xx_ic_enable(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        if (irq == MPC52xx_IRQ0) {
+                val = in_be32(&intr->ctrl);
+                val |= 1 << 11;
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_IRQ1) {
+                BUG();
+        } else if (irq <= MPC52xx_IRQ3) {
+                val = in_be32(&intr->ctrl);
+                val |= 1 << (10 - (irq - MPC52xx_IRQ1));
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+                val = in_be32(&intr->main_mask);
+                val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
+                out_be32(&intr->main_mask, val);
+        } else if (irq < MPC52xx_PERP_IRQ_BASE) {
+                val = in_be32(&sdma->IntMask);
+                val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+                out_be32(&sdma->IntMask, val);
+        } else {
+                val = in_be32(&intr->per_mask);
+                val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
+                out_be32(&intr->per_mask, val);
+        }
+}
+
+static void
+mpc52xx_ic_ack(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        /*
+         * Only some irqs are reset here, others in interrupting hardware.
+         */
+
+        switch (irq) {
+        case MPC52xx_IRQ0:
+                val = in_be32(&intr->ctrl);
+                val |= 0x08000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_CCS_IRQ:
+                val = in_be32(&intr->enc_status);
+                val |= 0x00000400;
+                out_be32(&intr->enc_status, val);
+                break;
+        case MPC52xx_IRQ1:
+                val = in_be32(&intr->ctrl);
+                val |= 0x04000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_IRQ2:
+                val = in_be32(&intr->ctrl);
+                val |= 0x02000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_IRQ3:
+                val = in_be32(&intr->ctrl);
+                val |= 0x01000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        default:
+                if (irq >= MPC52xx_SDMA_IRQ_BASE
+                                && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
+                        out_be32(&sdma->IntPend,
+                                 1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+                }
+
+                break;
+        }
+
+}
+
+static void
+mpc52xx_ic_disable_and_ack(unsigned int irq)
+{
+        mpc52xx_ic_disable(irq);
+        mpc52xx_ic_ack(irq);
+}
+
+static void
+mpc52xx_ic_end(unsigned int irq)
+{
+        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+                mpc52xx_ic_enable(irq);
+}
+
+static struct irq_chip mpc52xx_irqchip = {
+	.name	= " MPC52xx  ",
+	.enable		= mpc52xx_ic_enable,
+	.disable	= mpc52xx_ic_disable,
+	.ack		= mpc52xx_ic_disable_and_ack,
+	.end		= mpc52xx_ic_end,
+};
+
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+	pr_debug("%s: node=%p\n", __func__, node);
+
+	if ( device_is_compatible(node, "mpc52xx-pic") )
+		return 1;
+
+	return device_is_compatible(node, "mpc5200-pic");
+}
+
+
+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)
+{
+        static unsigned char map_senses[4] = {
+                IRQ_TYPE_LEVEL_HIGH,
+                IRQ_TYPE_EDGE_FALLING,
+                IRQ_TYPE_EDGE_RISING,
+		IRQ_TYPE_LEVEL_LOW,
+        };
+
+        int intrvect_l1;
+        int intrvect_l2;
+	int intrvect_type;
+        int intrvect_linux;
+
+        pr_debug("%s:\n", __func__);
+
+	if (intsize!=3)
+		return -1;
+
+        intrvect_l1 = (int) intspec[0];
+        intrvect_l2 = (int) intspec[1];
+	intrvect_type = (int) intspec[2];
+
+        pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2, intrvect_type );
+
+        switch(intrvect_l1) {
+        case 0: /* Critical */
+                intrvect_linux = MPC52xx_CRIT_IRQ_BASE;
+                break;
+
+        case 1: /* Main */
+                intrvect_linux = MPC52xx_MAIN_IRQ_BASE;
+                break;
+
+        case 2: /* Periph */
+                intrvect_linux = MPC52xx_PERP_IRQ_BASE;
+                break;
+
+        case 3: /* Bestcomm */
+                intrvect_linux = MPC52xx_SDMA_IRQ_BASE;
+                break;
+
+        default:
+                if ( printk_ratelimit() )
+			printk(KERN_ERR "Wrong L1 interrupt vector (%d)\n", intrvect_l1);
+
+                return -1;
+        }
+
+        intrvect_linux += intrvect_l2;
+
+        pr_debug("return %d\n", intrvect_linux);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = map_senses[intrvect_type];
+
+        return 0;
+
+}
+
+int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw)
+{
+	pr_debug("%s: v=%d, hw=%d\n", __func__, virq, (int) hw);
+
+	return 0;
+}
+
+void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
+{
+	pr_debug("%s: v=%d\n", __func__, virq);
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+        .match = mpc52xx_irqhost_match,
+        .xlate = mpc52xx_irqhost_xlate,
+	.map   = mpc52xx_irqhost_map,
+	.unmap = mpc52xx_irqhost_unmap,
+};
+
+void __init
+mpc52xx_init_irq(void)
+{
+	int i;
+        u32 intr_ctrl;
+	
+
+        /* Remap the necessary zones */
+        intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+        sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
+
+        if ((intr==NULL) || (sdma==NULL))
+                panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+        /* 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);
+        /* Initialize irq_desc[i].handler's with mpc52xx_ic. */
+        for (i = 0; i < NR_IRQS; i++) {
+                irq_desc[i].chip = &mpc52xx_irqchip;
+                irq_desc[i].status = IRQ_LEVEL;
+		
+        }
+
+#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
+        for (i=0 ; i<4 ; i++) {
+                int mode;
+                mode = IRQn_MODE(intr_ctrl,i);
+                if ((mode == 0x1) || (mode == 0x2))
+                        irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 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, 0, &mpc52xx_irqhost_ops, -1);
+	pr_debug("%s: mpc52xx_irqhost =%p\n", __func__, mpc52xx_irqhost );
+}
+
+unsigned int
+mpc52xx_get_irq(void)
+{
+        u32 status;
+	int virq;
+        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_CRIT_IRQ_BASE;
+        } else if (status & 0x00200000)
+        {		/* main */
+                irq = (status >> 16) & 0x1f;
+                if (irq == 4)			/* low priority peripheral */
+                        goto peripheral;
+                irq += MPC52xx_MAIN_IRQ_BASE;
+        } else if (status & 0x20000000)
+        {		/* peripheral */
+peripheral:
+                irq = (status >> 24) & 0x1f;
+                if (irq == 0) {			/* bestcomm */
+                        status = in_be32(&sdma->IntPend);
+                        irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1;
+                } else
+                        irq += MPC52xx_PERP_IRQ_BASE;
+
+        }
+
+	virq = irq_linear_revmap(mpc52xx_irqhost, irq);
+	pr_debug("%s: irq=%d -> %d\n", __func__, irq, virq);
+
+        return virq;
+}
+

--- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/Makefile	2006-10-25 20:33:32.000000000 +0200
@@ -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_CHRP)		+= mpc52xx_pic.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)		+= i8259.o

[-- 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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 19:05 [PATCH] General CHRP/MPC5K2 platform support patch Nicolas DET
@ 2006-10-25 21:59 ` Paul Mackerras
  2006-10-25 22:41   ` Grant Likely
  2006-10-25 22:53 ` Benjamin Herrenschmidt
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 40+ messages in thread
From: Paul Mackerras @ 2006-10-25 21:59 UTC (permalink / raw)
  To: Nicolas DET
  Cc: akpm, Sylvain Munaut, sl, linuxppc-dev, linuxppc-embedded, sha

Nicolas DET writes:

>  	if (machine && strncmp(machine, "Pegasos", 7) == 0) {
>  		_chrp_type = _CHRP_Pegasos;
> +	} else if (machine && strncmp(machine, "EFIKA5K2", 8) == 0) {
> +		_chrp_type =_CHRP_E5K2;

This whole _chrp_type thing, and having to do different things based
on the root-node model property, is really only a workaround for
older machines with inadequate device trees.  Decisions about things
like which interrupt controller driver(s) to instantiate should be
taken based on properties in the appropriate device-tree nodes, for
instance the model and compatible properties in the node(s) for the
interrupt controller(s).  In fact I'd like to get rid of _chrp_type
completely.

> diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
> --- a/include/asm-ppc/mpc52xx.h	2006-10-25 19:07:48.000000000 +0200
> +++ b/include/asm-ppc/mpc52xx.h	2006-10-25 19:11:55.000000000 +0200
> @@ -119,7 +119,7 @@ enum ppc_sys_devices {
>  #define MPC52xx_SDMA_IRQ_NUM	17
>  #define MPC52xx_PERP_IRQ_NUM	23
>  
> -#define MPC52xx_CRIT_IRQ_BASE	1
> +#define MPC52xx_CRIT_IRQ_BASE	0

What is this going to do to other 52xx users?

Paul.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 21:59 ` Paul Mackerras
@ 2006-10-25 22:41   ` Grant Likely
  2006-10-25 22:59     ` Benjamin Herrenschmidt
  2006-10-26 11:17     ` Nicolas DET
  0 siblings, 2 replies; 40+ messages in thread
From: Grant Likely @ 2006-10-25 22:41 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: akpm, linuxppc-embedded, sl, linuxppc-dev, sha

On 10/25/06, Paul Mackerras <paulus@samba.org> wrote:
> Nicolas DET writes:
>
> >       if (machine && strncmp(machine, "Pegasos", 7) == 0) {
> >               _chrp_type = _CHRP_Pegasos;
> > +     } else if (machine && strncmp(machine, "EFIKA5K2", 8) == 0) {
> > +             _chrp_type =_CHRP_E5K2;
>
> This whole _chrp_type thing, and having to do different things based
> on the root-node model property, is really only a workaround for
> older machines with inadequate device trees.  Decisions about things
> like which interrupt controller driver(s) to instantiate should be
> taken based on properties in the appropriate device-tree nodes, for
> instance the model and compatible properties in the node(s) for the
> interrupt controller(s).  In fact I'd like to get rid of _chrp_type
> completely.

What are the implications anyway for the bplan board being CHRP vs the
way the rest of the embedded ppcs are set up?  Will having this setup
as a CHRP system conflict w/ non-CHRP embedded boards?  (I'm assuming
that CHRP requires more capable firmware than u-boot passing in a fdt)

>
> > diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
> > --- a/include/asm-ppc/mpc52xx.h       2006-10-25 19:07:48.000000000 +0200
> > +++ b/include/asm-ppc/mpc52xx.h       2006-10-25 19:11:55.000000000 +0200
> > @@ -119,7 +119,7 @@ enum ppc_sys_devices {
> >  #define MPC52xx_SDMA_IRQ_NUM 17
> >  #define MPC52xx_PERP_IRQ_NUM 23
> >
> > -#define MPC52xx_CRIT_IRQ_BASE        1
> > +#define MPC52xx_CRIT_IRQ_BASE        0
>
> What is this going to do to other 52xx users?

Shouldn't be a big deal if all drivers use the macros; but as you
pointed out on IRC, the interrupt stuff needs to be reworked for the
interrupt mapping interface anyway

g.

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

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 19:05 [PATCH] General CHRP/MPC5K2 platform support patch Nicolas DET
  2006-10-25 21:59 ` Paul Mackerras
@ 2006-10-25 22:53 ` Benjamin Herrenschmidt
  2006-10-26 11:09   ` Nicolas DET
  2006-10-25 23:01 ` Grant Likely
  2006-10-26 17:17 ` John Rigby
  3 siblings, 1 reply; 40+ messages in thread
From: Benjamin Herrenschmidt @ 2006-10-25 22:53 UTC (permalink / raw)
  To: Nicolas DET
  Cc: akpm, Sylvain Munaut, sl, linuxppc-dev, linuxppc-embedded, sha

On Wed, 2006-10-25 at 21:05 +0200, Nicolas DET wrote:

In addition to various whitespace damage in the patch...

> +	if (_chrp_type ==  _CHRP_E5K2) {
> +		ppc_md.get_irq = mpc52xx_get_irq;
> +		mpc52xx_init_irq();
> +		return;
> +	}

As I wrote, the above should be unnecessary.

>  	chrp_find_openpic();
>  	chrp_find_8259();

Just add a

	chrp_find_mpc5200pic();

Which will set itself as the default controller and set ppc_md.get_irq
if none have done it before.
 
> @@ -530,6 +540,9 @@ chrp_init2(void)
>  	chrp_nvram_init();
>  #endif
>  
> +	if (_chrp_type == _CHRP_E5K2)
> +		return;

Why that ? Not that we really need those request_region() anyway, but
it's highly recommended that your firmware doesn't allocate anything in
that "legacy" portion of the IO space anyway, so requesting those
regions will do no harm.

>  	request_region(0x20,0x20,"pic1");
>  	request_region(0xa0,0x20,"pic2");
>  	request_region(0x00,0x20,"dma1");

> +static void
> +mpc52xx_ic_disable(unsigned int virq)
> +{
> +        u32 val;
> +	int irq;
> +
> +	irq = irq_map[virq].hwirq;

You should test if the result is valid just in case you were called with
a bogus irq number

> +	pr_debug("%s: irq=%d\n", __func__, irq);
> +
> +        if (irq == MPC52xx_IRQ0) {
> +                val = in_be32(&intr->ctrl);
> +                val &= ~(1 << 11);
> +                out_be32(&intr->ctrl, val);
> +        } else if (irq < MPC52xx_IRQ1) {
> +                BUG();
> +        } else if (irq <= MPC52xx_IRQ3) {
> +                val = in_be32(&intr->ctrl);
> +                val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
> +                out_be32(&intr->ctrl, val);
> +        } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
> +                val = in_be32(&intr->main_mask);
> +                val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
> +                out_be32(&intr->main_mask, val);
> +        } else if (irq < MPC52xx_PERP_IRQ_BASE) {
> +                val = in_be32(&sdma->IntMask);
> +                val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
> +                out_be32(&sdma->IntMask, val);
> +        } else {
> +                val = in_be32(&intr->per_mask);
> +                val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
> +                out_be32(&intr->per_mask, val);
> +        }
> +}

You may want to chose a different encoding for your HW irqs to make the
above less horrible. For example, have an irq category in some top bits
and the actual bit mask pre-mashed in the bottom bits.

And same comments for enable().

> +static void
> +mpc52xx_ic_disable_and_ack(unsigned int irq)
> +{
> +        mpc52xx_ic_disable(irq);
> +        mpc52xx_ic_ack(irq);
> +}

You don't need the above. It will be done for you by the core code once
you properly adapt to genirq.

> +static void
> +mpc52xx_ic_end(unsigned int irq)
> +{
> +        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
> +                mpc52xx_ic_enable(irq);
> +}

The above is not necessary anymore, you need to properly adapt to genirq
which you haven't done yet.

> +static struct irq_chip mpc52xx_irqchip = {
> +	.name	= " MPC52xx  ",
> +	.enable		= mpc52xx_ic_enable,
> +	.disable	= mpc52xx_ic_disable,
> +	.ack		= mpc52xx_ic_disable_and_ack,
> +	.end		= mpc52xx_ic_end,
> +};

As I said, you haven't properly adapted to genirq. That is

 enable -> unmask
 disable -> mask
 ack stays and doesn't do disable
 end is gone

You also need to call set_irq_chip_and_handler(), possibly in your host
map() function to set the right flow handler for your interrupts.

> +static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
> +{
> +	pr_debug("%s: node=%p\n", __func__, node);
> +
> +	if ( device_is_compatible(node, "mpc52xx-pic") )
> +		return 1;
> +
> +	return device_is_compatible(node, "mpc5200-pic");
> +}

You probably need only one of the above statements. It depends on how
the device-tree binding is defined for the MPC52xx which, for the
10000th time, should be done PUBLICALLY

> +int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw)
> +{
> +	pr_debug("%s: v=%d, hw=%d\n", __func__, virq, (int) hw);
> +
> +	return 0;
> +}

As I said earlier, the above needs to at least set a flow handler. Also,
if you intend to have different flow handlers for edge and level irqs,
then you'll also probably need to implement set_irq_type(). You may want
to look at the IPI driver for that (and beware of the lock problem with
set_irq_type() vs. set_irq_handler(), see the IPIC patch that went on
the list recently)

> +        /* 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);
> +        /* Initialize irq_desc[i].handler's with mpc52xx_ic. */
> +        for (i = 0; i < NR_IRQS; i++) {
> +                irq_desc[i].chip = &mpc52xx_irqchip;
> +                irq_desc[i].status = IRQ_LEVEL;
> +		
> +        }

The above should go. With the port to genirq, you get descriptors as
irqs get mapped, from your map callback, which is where you set the chip
and flow handler.

You should also never completley override status like that. Just or-in
the bits you need. Look at what other PICs in arch/powerpc do.

> +#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
> +        for (i=0 ; i<4 ; i++) {
> +                int mode;
> +                mode = IRQn_MODE(intr_ctrl,i);
> +                if ((mode == 0x1) || (mode == 0x2))
> +                        irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 0;
> +        }

What is the above about ?

> +	/*
> +	 * 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, 0, &mpc52xx_irqhost_ops, -1);
> +	pr_debug("%s: mpc52xx_irqhost =%p\n", __func__, mpc52xx_irqhost );
> +}

Ususally we do that first but heh, it doesn't really matter. However:

passing a count of 0 when creating a linear revmap is totally bogus (in
fact, I'm surprised your code works).

Also, as far as the invalid irq is concerned, you should probably define
it using a symbolic constant (properly typed) so you can use it
elsewhere in the code to test the result of the revmap functions among
others.

> +unsigned int
> +mpc52xx_get_irq(void)
> +{
> +        u32 status;
> +	int virq;
> +        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_CRIT_IRQ_BASE;
> +        } else if (status & 0x00200000)
> +        {		/* main */
> +                irq = (status >> 16) & 0x1f;
> +                if (irq == 4)			/* low priority peripheral */
> +                        goto peripheral;
> +                irq += MPC52xx_MAIN_IRQ_BASE;
> +        } else if (status & 0x20000000)
> +        {		/* peripheral */
> +peripheral:
> +                irq = (status >> 24) & 0x1f;
> +                if (irq == 0) {			/* bestcomm */
> +                        status = in_be32(&sdma->IntPend);
> +                        irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1;
> +                } else
> +                        irq += MPC52xx_PERP_IRQ_BASE;
> +
> +        }
> +
> +	virq = irq_linear_revmap(mpc52xx_irqhost, irq);
> +	pr_debug("%s: irq=%d -> %d\n", __func__, irq, virq);
> +
> +        return virq;
> +}

I'm surprised the revmap is working at all... considering the issues you
have above. You are lucky but things should be fixed anyway.

> --- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
> +++ b/arch/powerpc/sysdev/Makefile	2006-10-25 20:33:32.000000000 +0200
> @@ -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_CHRP)		+= mpc52xx_pic.o

That's not the proper way to do it. Instead, define an invisible
CONFIG_MPC52xx_PIC and have the chrp platform select it.

>  ifeq ($(CONFIG_PPC_MERGE),y)
>  obj-$(CONFIG_PPC_I8259)		+= i8259.o

Ben.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 22:41   ` Grant Likely
@ 2006-10-25 22:59     ` Benjamin Herrenschmidt
  2006-10-26 11:09       ` Nicolas DET
  2006-10-26 11:17     ` Nicolas DET
  1 sibling, 1 reply; 40+ messages in thread
From: Benjamin Herrenschmidt @ 2006-10-25 22:59 UTC (permalink / raw)
  To: Grant Likely
  Cc: akpm, linuxppc-embedded, sl, linuxppc-dev, Paul Mackerras, sha


> What are the implications anyway for the bplan board being CHRP vs the
> way the rest of the embedded ppcs are set up?  Will having this setup
> as a CHRP system conflict w/ non-CHRP embedded boards?  (I'm assuming
> that CHRP requires more capable firmware than u-boot passing in a fdt)

Not really :) The main thing they "buy" by going CHRP is that they use
RTAS for PCI config space access and thus don't have to write the host
bridge code. Since their firmware initializes everything properly, there
is little need for non-generic platform code and that sort of generic
platform code is what CHRP provides.

With the device-tree thingy done properly nowadays, there should be
little difference between platforms unless you end up dealing with
really special things.

There should be no conflict with non-CHRP boards using the MPC5200 chip
provided they do things right which is what I've been advocating so far.
That includes making sure everybody agrees on the format of the MPC5200
specific bits in the device-tree:

 - Format of the interrupt cells (they have come up upon my suggestion
to a 3-cell based format (could probably be compressed a bit but heh)
and that should be documented publically)

 - Binding (set of required properties and their definitions) for on
chip devices, and more specifically, for representing the bestcomm and
the links between devices and associated bestcomm tasks.

If the above is properly agreed upon, then the code for dealing with
MPC5200 specific devices will purely rely on those bits, and thus should
be useable from whatever platform it's included in, wether it's CHRP, or
something else.

Unfortunately, at this point, Nicolas seems to be unwilling to open up
his device-tree publically.

Ben.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 19:05 [PATCH] General CHRP/MPC5K2 platform support patch Nicolas DET
  2006-10-25 21:59 ` Paul Mackerras
  2006-10-25 22:53 ` Benjamin Herrenschmidt
@ 2006-10-25 23:01 ` Grant Likely
  2006-10-25 23:06   ` Benjamin Herrenschmidt
  2006-10-26 17:17 ` John Rigby
  3 siblings, 1 reply; 40+ messages in thread
From: Grant Likely @ 2006-10-25 23:01 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

Thanks Nicolas, I'll dig through the PIC code tonight.  I'm really not
sure about the implications of this being a CHRP board vs. the
Lite5200 using u-boot.  ie. Should the Lite5200 also be a CHRP
platform?  Does u-boot provide enough capability (this is where my
ignorance about CHRP shines through)

Cheers,
g.

On 10/25/06, Nicolas DET <nd@bplan-gmbh.de> wrote:
> * mpc5k2.c: As far as I understood, using of_platform_device will allow
> 'smart' of tree parsing. I did not implement it yet.
>
> * mpc5k2_pic.c : The thingy ;-). I moved it into arch/powerpc/sysdev as
> suggested. This code is 99% copy/paste from the ARCH=ppc. I added an
> irq_host with the appropriate xlate and co. However, I have not done
> more as this code has been written by others. I think we should work
> together to move to new Linux style irq. I stay ready to test or code
> upcoming revision/

Why change the naming scheme from mpc52xx to mpc5k3?  All other
freescale supports follow the mpcXXxxx scheme.

>
> * arch/powerpc/platform/*. Here, only small changes has been made. I
> added _CHRP_E5K2 (in asm/processor.h), an entry in chrp_names() and the
> correct detection in arch/powerpc/platform/setup.c / chrp_setup_arch().
> in chrp_init_IRQ(), I set ppc_md.get_irq to mpc52xx_get_irq and call
> mpc52xx_init_irq().
>
> * serial stuff / IBP Freq. As this frequency is MPC52xx specific. I
> think it would make sense to add a new func mpc52xx_getipbfreq(void).
> The way it would be implemented may depend of the architecture. Our
> firmware contains an 'ipb-freq' property in '/builtin/'.
>
> diff -uprN a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
> --- a/arch/powerpc/platforms/chrp/setup.c       2006-10-25 19:07:23.000000000 +0200
> +++ b/arch/powerpc/platforms/chrp/setup.c       2006-10-25 19:10:18.000000000 +0200
> @@ -101,7 +102,8 @@ static const char *chrp_names[] = {
>         "Motorola",
>         "IBM or Longtrail",
>         "Genesi Pegasos",
> -       "Total Impact Briq"
> +       "Total Impact Briq",
> +       "bPlan Efika"
>  };

I agree w/ Paul... the chrp_type stuff is stinky.  :)

> @@ -494,6 +498,12 @@ void __init chrp_init_IRQ(void)
>  #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
>         struct device_node *kbd;
>  #endif
> +       if (_chrp_type ==  _CHRP_E5K2) {
> +               ppc_md.get_irq = mpc52xx_get_irq;
> +               mpc52xx_init_irq();
> +               return;
> +       }
> +
>         chrp_find_openpic();
>         chrp_find_8259();

Also, this only covers one 52xx board and does not match the
convention in this function.  Shouldn't this instead call a new
function "chrp_find_mpc52xx_pic()?

>
> @@ -530,6 +540,9 @@ chrp_init2(void)
>         chrp_nvram_init();
>  #endif
>
> +       if (_chrp_type == _CHRP_E5K2)
> +               return;
> +
>         request_region(0x20,0x20,"pic1");
>         request_region(0xa0,0x20,"pic2");
>         request_region(0x00,0x20,"dma1");

There's got to be a better way to go about this.  If all the
request_regions are not required by all CHRP platforms, then they
should be enclosed by an if{} block.  Just bailing from the function
does not seem to be a good idea to me.  For example, at the end of
chrp_init2() there is a progress method called (if enabled).  Bailing
out prevents that progress message.  (not a big issue, but I'm looking
a convention consistency here)

> diff -uprN a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
> --- a/include/asm-powerpc/processor.h   2006-10-25 19:07:48.000000000 +0200
> +++ b/include/asm-powerpc/processor.h   2006-10-25 19:11:54.000000000 +0200
> @@ -33,6 +33,7 @@
>  #define _CHRP_IBM      0x05    /* IBM chrp, the longtrail and longtrail 2 */
>  #define _CHRP_Pegasos  0x06    /* Genesi/bplan's Pegasos and Pegasos2 */
>  #define _CHRP_briq     0x07    /* TotalImpact's briQ */
> +#define _CHRP_E5K2     0x08    /* bPlan's Efika 5k2*/

Ick.  :)

> diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
> --- a/include/asm-ppc/mpc52xx.h 2006-10-25 19:07:48.000000000 +0200
> +++ b/include/asm-ppc/mpc52xx.h 2006-10-25 19:11:55.000000000 +0200
> @@ -119,7 +119,7 @@ enum ppc_sys_devices {
>  #define MPC52xx_SDMA_IRQ_NUM   17
>  #define MPC52xx_PERP_IRQ_NUM   23
>
> -#define MPC52xx_CRIT_IRQ_BASE  1
> +#define MPC52xx_CRIT_IRQ_BASE  0
>  #define MPC52xx_MAIN_IRQ_BASE  (MPC52xx_CRIT_IRQ_BASE + MPC52xx_CRIT_IRQ_NUM)
>  #define MPC52xx_SDMA_IRQ_BASE  (MPC52xx_MAIN_IRQ_BASE + MPC52xx_MAIN_IRQ_NUM)
>  #define MPC52xx_PERP_IRQ_BASE  (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)

Just curious... why?

> --- a/arch/powerpc/sysdev/mpc52xx_pic.c 1970-01-01 01:00:00.000000000 +0100
> +++ b/arch/powerpc/sysdev/mpc52xx_pic.c 2006-10-25 19:17:48.000000000 +0200

I'll skip commenting on PIC stuff as I'm still working through how it
all works myself.  It still needs to be worked out if we go to a two
level interrupt # table in the device tree (interrupt_cells=3) and
where they will be mapped back into Linux IRQ numbers.

> --- a/arch/powerpc/sysdev/Makefile      2006-10-25 19:07:24.000000000 +0200
> +++ b/arch/powerpc/sysdev/Makefile      2006-10-25 20:33:32.000000000 +0200
> @@ -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_CHRP)         += mpc52xx_pic.o
>
>  ifeq ($(CONFIG_PPC_MERGE),y)
>  obj-$(CONFIG_PPC_I8259)                += i8259.o
>
>
>
>


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

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 23:01 ` Grant Likely
@ 2006-10-25 23:06   ` Benjamin Herrenschmidt
  2006-10-25 23:13     ` Sven Luther
  2006-10-26 12:09     ` Nicolas DET
  0 siblings, 2 replies; 40+ messages in thread
From: Benjamin Herrenschmidt @ 2006-10-25 23:06 UTC (permalink / raw)
  To: Grant Likely; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

On Wed, 2006-10-25 at 17:01 -0600, Grant Likely wrote:
> Thanks Nicolas, I'll dig through the PIC code tonight.  I'm really not
> sure about the implications of this being a CHRP board vs. the
> Lite5200 using u-boot.  ie. Should the Lite5200 also be a CHRP
> platform?  Does u-boot provide enough capability (this is where my
> ignorance about CHRP shines through)

Bah, if you have no RTAS, don't bother being CHRP.

> > * serial stuff / IBP Freq. As this frequency is MPC52xx specific. I
> > think it would make sense to add a new func mpc52xx_getipbfreq(void).
> > The way it would be implemented may depend of the architecture. Our
> > firmware contains an 'ipb-freq' property in '/builtin/'.

BTW. I forgot to comment on the above in my previous mail... As I said,
there should be no such thing. Instead, the IPB freq should be in the
device-tree.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 23:06   ` Benjamin Herrenschmidt
@ 2006-10-25 23:13     ` Sven Luther
  2006-10-26 12:09     ` Nicolas DET
  1 sibling, 0 replies; 40+ messages in thread
From: Sven Luther @ 2006-10-25 23:13 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: akpm, linuxppc-embedded, sl, linuxppc-dev, sven, sha

On Thu, Oct 26, 2006 at 09:06:16AM +1000, Benjamin Herrenschmidt wrote:
> > > * serial stuff / IBP Freq. As this frequency is MPC52xx specific. I
> > > think it would make sense to add a new func mpc52xx_getipbfreq(void).
> > > The way it would be implemented may depend of the architecture. Our
> > > firmware contains an 'ipb-freq' property in '/builtin/'.
> 
> BTW. I forgot to comment on the above in my previous mail... As I said,
> there should be no such thing. Instead, the IPB freq should be in the
> device-tree.

Euh, how is this different from having our "firmware contains an 'ipb-freq'
property in '/builtin/'". There is no an ipb-freq property in the device tree,
so you need a function to be able to get it from the the device tree, which i
believe what is proposed here.

Friendly,

Sven Luther

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 22:53 ` Benjamin Herrenschmidt
@ 2006-10-26 11:09   ` Nicolas DET
  2006-10-26 12:49     ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 40+ messages in thread
From: Nicolas DET @ 2006-10-26 11:09 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: akpm, Sylvain Munaut, sl, linuxppc-dev, linuxppc-embedded, sha

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

Benjamin Herrenschmidt wrote:
> On Wed, 2006-10-25 at 21:05 +0200, Nicolas DET wrote:
> 
> In addition to various whitespace damage in the patch...
> 
>> +	if (_chrp_type ==  _CHRP_E5K2) {
>> +		ppc_md.get_irq = mpc52xx_get_irq;
>> +		mpc52xx_init_irq();
>> +		return;
>> +	}
> 
> As I wrote, the above should be unnecessary.
> 
>>  	chrp_find_openpic();
>>  	chrp_find_8259();
> 
> Just add a
> 
> 	chrp_find_mpc5200pic();
> 
> Which will set itself as the default controller and set ppc_md.get_irq
> if none have done it before.
>  
>> @@ -530,6 +540,9 @@ chrp_init2(void)
>>  	chrp_nvram_init();
>>  #endif
>>  
>> +	if (_chrp_type == _CHRP_E5K2)
>> +		return;
> 

Done.


>> +static void
>> +mpc52xx_ic_disable(unsigned int virq)
>> +{
>> +        u32 val;
>> +	int irq;
>> +
>> +	irq = irq_map[virq].hwirq;
> 
> You should test if the result is valid just in case you were called with
> [...]
> I'm surprised the revmap is working at all... considering the issues you
> have above. You are lucky but things should be fixed anyway.
> 

As said in the mail. I'm waiting for the opinion of the original authors 
and the mainteners. What's why I did not made much change in this file.
In the current patch, I know do:
mpc52xx_irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, NR_IRQS, 
&mpc52xx_irqhost_ops, -1);

Which should be ok.

>> --- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
>> +++ b/arch/powerpc/sysdev/Makefile	2006-10-25 20:33:32.000000000 +0200
>> @@ -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_CHRP)		+= mpc52xx_pic.o
> 

Done.

Regards

[-- Attachment #2: chrpmpc52xx_2.6.19-rc3.patch --]
[-- Type: text/plain, Size: 15111 bytes --]

--- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/Makefile	2006-10-26 11:38:02.000000000 +0200
@@ -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/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-26 10:55:44.000000000 +0200
@@ -0,0 +1,371 @@
+/*
+ * arch/powerpc/sysdev/mpc52xx_pic.c
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx 
+ * embedded CPU.
+ * Modified for CHRP Efika 5K2
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+//#define 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 <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 void
+mpc52xx_ic_disable(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        if (irq == MPC52xx_IRQ0) {
+                val = in_be32(&intr->ctrl);
+                val &= ~(1 << 11);
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_IRQ1) {
+                BUG();
+        } else if (irq <= MPC52xx_IRQ3) {
+                val = in_be32(&intr->ctrl);
+                val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+                val = in_be32(&intr->main_mask);
+                val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
+                out_be32(&intr->main_mask, val);
+        } else if (irq < MPC52xx_PERP_IRQ_BASE) {
+                val = in_be32(&sdma->IntMask);
+                val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
+                out_be32(&sdma->IntMask, val);
+        } else {
+                val = in_be32(&intr->per_mask);
+                val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
+                out_be32(&intr->per_mask, val);
+        }
+}
+
+static void
+mpc52xx_ic_enable(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        if (irq == MPC52xx_IRQ0) {
+                val = in_be32(&intr->ctrl);
+                val |= 1 << 11;
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_IRQ1) {
+                BUG();
+        } else if (irq <= MPC52xx_IRQ3) {
+                val = in_be32(&intr->ctrl);
+                val |= 1 << (10 - (irq - MPC52xx_IRQ1));
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+                val = in_be32(&intr->main_mask);
+                val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
+                out_be32(&intr->main_mask, val);
+        } else if (irq < MPC52xx_PERP_IRQ_BASE) {
+                val = in_be32(&sdma->IntMask);
+                val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+                out_be32(&sdma->IntMask, val);
+        } else {
+                val = in_be32(&intr->per_mask);
+                val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
+                out_be32(&intr->per_mask, val);
+        }
+}
+
+static void
+mpc52xx_ic_ack(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        /*
+         * Only some irqs are reset here, others in interrupting hardware.
+         */
+
+        switch (irq) {
+        case MPC52xx_IRQ0:
+                val = in_be32(&intr->ctrl);
+                val |= 0x08000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_CCS_IRQ:
+                val = in_be32(&intr->enc_status);
+                val |= 0x00000400;
+                out_be32(&intr->enc_status, val);
+                break;
+        case MPC52xx_IRQ1:
+                val = in_be32(&intr->ctrl);
+                val |= 0x04000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_IRQ2:
+                val = in_be32(&intr->ctrl);
+                val |= 0x02000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_IRQ3:
+                val = in_be32(&intr->ctrl);
+                val |= 0x01000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        default:
+                if (irq >= MPC52xx_SDMA_IRQ_BASE
+                                && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
+                        out_be32(&sdma->IntPend,
+                                 1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+                }
+
+                break;
+        }
+
+}
+
+static void
+mpc52xx_ic_disable_and_ack(unsigned int irq)
+{
+        mpc52xx_ic_disable(irq);
+        mpc52xx_ic_ack(irq);
+}
+
+static void
+mpc52xx_ic_end(unsigned int irq)
+{
+        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+                mpc52xx_ic_enable(irq);
+}
+
+static struct irq_chip mpc52xx_irqchip = {
+	.name	= " MPC52xx  ",
+	.enable		= mpc52xx_ic_enable,
+	.disable	= mpc52xx_ic_disable,
+	.ack		= mpc52xx_ic_disable_and_ack,
+	.end		= mpc52xx_ic_end,
+};
+
+
+extern struct device_node *find_mpc52xx_pic(void);
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+	pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_pic(),  node);
+	return find_mpc52xx_pic() == 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)
+{
+        static unsigned char map_senses[4] = {
+                IRQ_TYPE_LEVEL_HIGH,
+                IRQ_TYPE_EDGE_FALLING,
+                IRQ_TYPE_EDGE_RISING,
+		IRQ_TYPE_LEVEL_LOW,
+        };
+
+        int intrvect_l1;
+        int intrvect_l2;
+	int intrvect_type;
+        int intrvect_linux;
+
+        pr_debug("%s:\n", __func__);
+
+	if (intsize!=3)
+		return -1;
+
+        intrvect_l1 = (int) intspec[0];
+        intrvect_l2 = (int) intspec[1];
+	intrvect_type = (int) intspec[2];
+
+        pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2, intrvect_type );
+
+        switch(intrvect_l1) {
+        case 0: /* Critical */
+                intrvect_linux = MPC52xx_CRIT_IRQ_BASE;
+                break;
+
+        case 1: /* Main */
+                intrvect_linux = MPC52xx_MAIN_IRQ_BASE;
+                break;
+
+        case 2: /* Periph */
+                intrvect_linux = MPC52xx_PERP_IRQ_BASE;
+                break;
+
+        case 3: /* Bestcomm */
+                intrvect_linux = MPC52xx_SDMA_IRQ_BASE;
+                break;
+
+        default:
+                if ( printk_ratelimit() )
+			printk(KERN_ERR "Wrong L1 interrupt vector (%d)\n", intrvect_l1);
+
+                return -1;
+        }
+
+        intrvect_linux += intrvect_l2;
+
+        pr_debug("return %d\n", intrvect_linux);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = map_senses[intrvect_type];
+
+        return 0;
+
+}
+
+int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw)
+{
+	pr_debug("%s: v=%d, hw=%d\n", __func__, virq, (int) hw);
+
+	return 0;
+}
+
+void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
+{
+	pr_debug("%s: v=%d\n", __func__, virq);
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+        .match = mpc52xx_irqhost_match,
+        .xlate = mpc52xx_irqhost_xlate,
+	.map   = mpc52xx_irqhost_map,
+	.unmap = mpc52xx_irqhost_unmap,
+};
+
+void __init
+mpc52xx_init_irq(void)
+{
+	int i;
+        u32 intr_ctrl;
+	
+
+        /* Remap the necessary zones */
+        intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+        sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
+
+        if ((intr==NULL) || (sdma==NULL))
+                panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+        /* 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);
+        /* Initialize irq_desc[i].handler's with mpc52xx_ic. */
+        for (i = 0; i < NR_IRQS; i++) {
+                irq_desc[i].chip = &mpc52xx_irqchip;
+                irq_desc[i].status = IRQ_LEVEL;
+		
+        }
+
+#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
+        for (i=0 ; i<4 ; i++) {
+                int mode;
+                mode = IRQn_MODE(intr_ctrl,i);
+                if ((mode == 0x1) || (mode == 0x2))
+                        irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 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, NR_IRQS, &mpc52xx_irqhost_ops, -1);
+	pr_debug("%s: mpc52xx_irqhost =%p\n", __func__, mpc52xx_irqhost );
+}
+
+unsigned int
+mpc52xx_get_irq(void)
+{
+        u32 status;
+	int virq;
+        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_CRIT_IRQ_BASE;
+        } else if (status & 0x00200000)
+        {		/* main */
+                irq = (status >> 16) & 0x1f;
+                if (irq == 4)			/* low priority peripheral */
+                        goto peripheral;
+                irq += MPC52xx_MAIN_IRQ_BASE;
+        } else if (status & 0x20000000)
+        {		/* peripheral */
+peripheral:
+                irq = (status >> 24) & 0x1f;
+                if (irq == 0) {			/* bestcomm */
+                        status = in_be32(&sdma->IntPend);
+                        irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1;
+                } else
+                        irq += MPC52xx_PERP_IRQ_BASE;
+
+        }
+
+	virq = irq_linear_revmap(mpc52xx_irqhost, irq);
+	pr_debug("%s: irq=%d -> %d\n", __func__, irq, virq);
+
+        return virq;
+}
+
--- a/arch/powerpc/Kconfig	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/Kconfig	2006-10-26 11:32:54.000000000 +0200
@@ -384,6 +384,12 @@ config PPC_CHRP
 	select PPC_RTAS
 	select PPC_MPC106
 	select PPC_UDBG_16550
+	select PPC_MPC52xx_PIC
+	default y
+
+config PPC_MPC52xx_PIC
+        bool
+	depends on PPC_CHRP
 	default y
 
 config PPC_PMAC
--- a/arch/powerpc/platforms/chrp/setup.c	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/platforms/chrp/setup.c	2006-10-26 10:59:39.000000000 +0200
@@ -51,6 +51,7 @@
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 #include <asm/xmon.h>
+#include <asm/mpc52xx.h>
 
 #include "chrp.h"
 
@@ -435,6 +436,51 @@ static struct irqaction xmon_irqaction =
 };
 #endif
 
+
+struct device_node *find_mpc52xx_pic(void)
+{
+	struct device_node *dev;
+	const char *piccompatible_list[] =
+	{
+		"mpc5200-interrupt-controller",
+		"mpc52xx-interrupt-controller",
+		"mpc52xx-pic",
+		"mpc5200-pic",
+		"5200-interrupt-controller",
+		"52xx-interrupt-controller",
+		"52xx-pic",
+		"5200-pic",
+		NULL
+	};
+
+	/* Look for an MPC52xx interrupt controller */
+	for_each_node_by_type(dev, "interrupt-controller")
+	{
+		const char **piccompatible_entry = piccompatible_list;
+
+		for(piccompatible_entry = piccompatible_list; *piccompatible_entry; piccompatible_entry++ )
+		{
+			if (device_is_compatible(dev, *piccompatible_entry ))
+				return dev;
+		}
+	}
+
+	return NULL;
+}
+
+static int  __init chrp_find_mpc52xx_pic(void)
+{
+	if (find_mpc52xx_pic())
+	{
+		printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
+		ppc_md.get_irq = mpc52xx_get_irq;
+		mpc52xx_init_irq();
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
 static void __init chrp_find_8259(void)
 {
 	struct device_node *np, *pic = NULL;
@@ -494,8 +540,12 @@ void __init chrp_init_IRQ(void)
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
 	struct device_node *kbd;
 #endif
-	chrp_find_openpic();
-	chrp_find_8259();
+
+	if ( chrp_find_mpc52xx_pic() < 0)
+	{
+		chrp_find_openpic();
+		chrp_find_8259();
+	}
 
 #ifdef CONFIG_SMP
 	/* Pegasos has no MPIC, those ops would make it crash. It might be an
diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
--- a/include/asm-ppc/mpc52xx.h	2006-10-25 19:07:48.000000000 +0200
+++ b/include/asm-ppc/mpc52xx.h	2006-10-25 19:11:55.000000000 +0200
@@ -119,7 +119,7 @@ enum ppc_sys_devices {
 #define MPC52xx_SDMA_IRQ_NUM	17
 #define MPC52xx_PERP_IRQ_NUM	23
 
-#define MPC52xx_CRIT_IRQ_BASE	1
+#define MPC52xx_CRIT_IRQ_BASE	0
 #define MPC52xx_MAIN_IRQ_BASE	(MPC52xx_CRIT_IRQ_BASE + MPC52xx_CRIT_IRQ_NUM)
 #define MPC52xx_SDMA_IRQ_BASE	(MPC52xx_MAIN_IRQ_BASE + MPC52xx_MAIN_IRQ_NUM)
 #define MPC52xx_PERP_IRQ_BASE	(MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)
@@ -415,7 +415,7 @@ struct mpc52xx_cdm {
 #ifndef __ASSEMBLY__
 
 extern void mpc52xx_init_irq(void);
-extern int mpc52xx_get_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
 
 extern unsigned long mpc52xx_find_end_of_memory(void);
 extern void mpc52xx_set_bat(void);

[-- 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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 22:59     ` Benjamin Herrenschmidt
@ 2006-10-26 11:09       ` Nicolas DET
  0 siblings, 0 replies; 40+ messages in thread
From: Nicolas DET @ 2006-10-26 11:09 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: akpm, sl, linuxppc-dev, Paul Mackerras, linuxppc-embedded, sha

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

Benjamin Herrenschmidt wrote:

>  - Format of the interrupt cells (they have come up upon my suggestion
> to a 3-cell based format (could probably be compressed a bit but heh)
> and that should be documented publically)
> 

It's some kind of 'documented' in mpc52xx_pic.c/xlate()

>  - Binding (set of required properties and their definitions) for on
> chip devices, and more specifically, for representing the bestcomm and
> the links between devices and associated bestcomm tasks.

Bestcomm is something a bit 'weird'. I think we are the only to use this 
approach (task code loaded by the OFW and not by the OS). As said 
earlier, I've been in contact with an bestcomm coders and I think we 
would work together on this subject.


[-- 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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 22:41   ` Grant Likely
  2006-10-25 22:59     ` Benjamin Herrenschmidt
@ 2006-10-26 11:17     ` Nicolas DET
  1 sibling, 0 replies; 40+ messages in thread
From: Nicolas DET @ 2006-10-26 11:17 UTC (permalink / raw)
  To: Grant Likely
  Cc: akpm, sl, linuxppc-dev, Paul Mackerras, linuxppc-embedded, sha

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

Paul Mackerras wrote:
 > Nicolas DET writes:
 >
 >>  	if (machine && strncmp(machine, "Pegasos", 7) == 0) {
 >>  		_chrp_type = _CHRP_Pegasos;
 >> +	} else if (machine && strncmp(machine, "EFIKA5K2", 8) == 0) {
 >> +		_chrp_type =_CHRP_E5K2;
 >
 > This whole _chrp_type thing, and having to do different things based
 > on the root-node model property, is really only a workaround for
 > older machines with inadequate device trees.  Decisions about things
 > like which interrupt controller driver(s) to instantiate should be
 > taken based on properties in the appropriate device-tree nodes, for
 > instance the model and compatible properties in the node(s) for the
 > interrupt controller(s).  In fact I'd like to get rid of _chrp_type
 > completely.
 >

I remove this part of the patch which is only cosmetic (good CHRP name).

 >> diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
 >> --- a/include/asm-ppc/mpc52xx.h	2006-10-25 19:07:48.000000000 +0200
 >> +++ b/include/asm-ppc/mpc52xx.h	2006-10-25 19:11:55.000000000 +0200
 >> @@ -119,7 +119,7 @@ enum ppc_sys_devices {
 >>  #define MPC52xx_SDMA_IRQ_NUM	17
 >>  #define MPC52xx_PERP_IRQ_NUM	23
 >>
 >> -#define MPC52xx_CRIT_IRQ_BASE	1
 >> +#define MPC52xx_CRIT_IRQ_BASE	0
 >
 > What is this going to do to other 52xx users?
 >

IRQ 0 may cause issue in earlier kernel as far as I understood. New one, 
using the new IRQ stuff, just works (at least works great here).

This is a revert change from:
http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=e21b9f2e9a580ce7375ec58953c1bb19aabe0db4
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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 23:06   ` Benjamin Herrenschmidt
  2006-10-25 23:13     ` Sven Luther
@ 2006-10-26 12:09     ` Nicolas DET
  2006-10-26 12:51       ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 40+ messages in thread
From: Nicolas DET @ 2006-10-26 12:09 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

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

Benjamin Herrenschmidt wrote:

>>> * serial stuff / IBP Freq. As this frequency is MPC52xx specific. I
>>> think it would make sense to add a new func mpc52xx_getipbfreq(void).
>>> The way it would be implemented may depend of the architecture. Our
>>> firmware contains an 'ipb-freq' property in '/builtin/'.
> 
> BTW. I forgot to comment on the above in my previous mail... As I said,
> there should be no such thing. Instead, the IPB freq should be in the
> device-tree.
> 
> 
> 

What do you mean exactly by 'the IPB freq should be in the device-tree'? 
It is as property.

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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 11:09   ` Nicolas DET
@ 2006-10-26 12:49     ` Benjamin Herrenschmidt
  2006-10-26 12:59       ` Nicolas DET
  0 siblings, 1 reply; 40+ messages in thread
From: Benjamin Herrenschmidt @ 2006-10-26 12:49 UTC (permalink / raw)
  To: Nicolas DET
  Cc: akpm, Sylvain Munaut, sl, linuxppc-dev, linuxppc-embedded, sha

> rent patch, I know do:
> mpc52xx_irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, NR_IRQS, 
> &mpc52xx_irqhost_ops, -1);
> 
> Which should be ok.

NR_IRQ, it's a bit violent :) It's also the max number of virtual IRQs
and thus has nothing to do with your HW numbers. Use the max number of
HW IRQs here.

Ben.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 12:09     ` Nicolas DET
@ 2006-10-26 12:51       ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 40+ messages in thread
From: Benjamin Herrenschmidt @ 2006-10-26 12:51 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

On Thu, 2006-10-26 at 14:09 +0200, Nicolas DET wrote:

> What do you mean exactly by 'the IPB freq should be in the device-tree'? 
> It is as property.

Yeah, just that drivers should pick it up from there

Ben.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 12:49     ` Benjamin Herrenschmidt
@ 2006-10-26 12:59       ` Nicolas DET
  2006-10-26 16:02         ` Grant Likely
  0 siblings, 1 reply; 40+ messages in thread
From: Nicolas DET @ 2006-10-26 12:59 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: akpm, Sylvain Munaut, sl, linuxppc-dev, linuxppc-embedded, sha

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

Benjamin Herrenschmidt wrote:
>> rent patch, I know do:
>> mpc52xx_irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, NR_IRQS, 
>> &mpc52xx_irqhost_ops, -1);
>>
>> Which should be ok.
> 
> NR_IRQ, it's a bit violent :) It's also the max number of virtual IRQs
> and thus has nothing to do with your HW numbers. Use the max number of
> HW IRQs here.
> 
> Ben.
> 
> 
> 


[-- Attachment #2: chrpmpc52xx_2.6.19-rc3.patch --]
[-- Type: text/plain, Size: 15122 bytes --]

--- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/Makefile	2006-10-26 11:38:02.000000000 +0200
@@ -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/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-26 10:55:44.000000000 +0200
@@ -0,0 +1,371 @@
+/*
+ * arch/powerpc/sysdev/mpc52xx_pic.c
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx 
+ * embedded CPU.
+ * Modified for CHRP Efika 5K2
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+//#define 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 <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 void
+mpc52xx_ic_disable(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        if (irq == MPC52xx_IRQ0) {
+                val = in_be32(&intr->ctrl);
+                val &= ~(1 << 11);
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_IRQ1) {
+                BUG();
+        } else if (irq <= MPC52xx_IRQ3) {
+                val = in_be32(&intr->ctrl);
+                val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+                val = in_be32(&intr->main_mask);
+                val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
+                out_be32(&intr->main_mask, val);
+        } else if (irq < MPC52xx_PERP_IRQ_BASE) {
+                val = in_be32(&sdma->IntMask);
+                val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
+                out_be32(&sdma->IntMask, val);
+        } else {
+                val = in_be32(&intr->per_mask);
+                val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
+                out_be32(&intr->per_mask, val);
+        }
+}
+
+static void
+mpc52xx_ic_enable(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        if (irq == MPC52xx_IRQ0) {
+                val = in_be32(&intr->ctrl);
+                val |= 1 << 11;
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_IRQ1) {
+                BUG();
+        } else if (irq <= MPC52xx_IRQ3) {
+                val = in_be32(&intr->ctrl);
+                val |= 1 << (10 - (irq - MPC52xx_IRQ1));
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+                val = in_be32(&intr->main_mask);
+                val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
+                out_be32(&intr->main_mask, val);
+        } else if (irq < MPC52xx_PERP_IRQ_BASE) {
+                val = in_be32(&sdma->IntMask);
+                val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+                out_be32(&sdma->IntMask, val);
+        } else {
+                val = in_be32(&intr->per_mask);
+                val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
+                out_be32(&intr->per_mask, val);
+        }
+}
+
+static void
+mpc52xx_ic_ack(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        /*
+         * Only some irqs are reset here, others in interrupting hardware.
+         */
+
+        switch (irq) {
+        case MPC52xx_IRQ0:
+                val = in_be32(&intr->ctrl);
+                val |= 0x08000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_CCS_IRQ:
+                val = in_be32(&intr->enc_status);
+                val |= 0x00000400;
+                out_be32(&intr->enc_status, val);
+                break;
+        case MPC52xx_IRQ1:
+                val = in_be32(&intr->ctrl);
+                val |= 0x04000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_IRQ2:
+                val = in_be32(&intr->ctrl);
+                val |= 0x02000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_IRQ3:
+                val = in_be32(&intr->ctrl);
+                val |= 0x01000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        default:
+                if (irq >= MPC52xx_SDMA_IRQ_BASE
+                                && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
+                        out_be32(&sdma->IntPend,
+                                 1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+                }
+
+                break;
+        }
+
+}
+
+static void
+mpc52xx_ic_disable_and_ack(unsigned int irq)
+{
+        mpc52xx_ic_disable(irq);
+        mpc52xx_ic_ack(irq);
+}
+
+static void
+mpc52xx_ic_end(unsigned int irq)
+{
+        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+                mpc52xx_ic_enable(irq);
+}
+
+static struct irq_chip mpc52xx_irqchip = {
+	.name	= " MPC52xx  ",
+	.enable		= mpc52xx_ic_enable,
+	.disable	= mpc52xx_ic_disable,
+	.ack		= mpc52xx_ic_disable_and_ack,
+	.end		= mpc52xx_ic_end,
+};
+
+
+extern struct device_node *find_mpc52xx_pic(void);
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+	pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_pic(),  node);
+	return find_mpc52xx_pic() == 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)
+{
+        static unsigned char map_senses[4] = {
+                IRQ_TYPE_LEVEL_HIGH,
+                IRQ_TYPE_EDGE_FALLING,
+                IRQ_TYPE_EDGE_RISING,
+		IRQ_TYPE_LEVEL_LOW,
+        };
+
+        int intrvect_l1;
+        int intrvect_l2;
+	int intrvect_type;
+        int intrvect_linux;
+
+        pr_debug("%s:\n", __func__);
+
+	if (intsize!=3)
+		return -1;
+
+        intrvect_l1 = (int) intspec[0];
+        intrvect_l2 = (int) intspec[1];
+	intrvect_type = (int) intspec[2];
+
+        pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2, intrvect_type );
+
+        switch(intrvect_l1) {
+        case 0: /* Critical */
+                intrvect_linux = MPC52xx_CRIT_IRQ_BASE;
+                break;
+
+        case 1: /* Main */
+                intrvect_linux = MPC52xx_MAIN_IRQ_BASE;
+                break;
+
+        case 2: /* Periph */
+                intrvect_linux = MPC52xx_PERP_IRQ_BASE;
+                break;
+
+        case 3: /* Bestcomm */
+                intrvect_linux = MPC52xx_SDMA_IRQ_BASE;
+                break;
+
+        default:
+                if ( printk_ratelimit() )
+			printk(KERN_ERR "Wrong L1 interrupt vector (%d)\n", intrvect_l1);
+
+                return -1;
+        }
+
+        intrvect_linux += intrvect_l2;
+
+        pr_debug("return %d\n", intrvect_linux);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = map_senses[intrvect_type];
+
+        return 0;
+
+}
+
+int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw)
+{
+	pr_debug("%s: v=%d, hw=%d\n", __func__, virq, (int) hw);
+
+	return 0;
+}
+
+void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
+{
+	pr_debug("%s: v=%d\n", __func__, virq);
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+        .match = mpc52xx_irqhost_match,
+        .xlate = mpc52xx_irqhost_xlate,
+	.map   = mpc52xx_irqhost_map,
+	.unmap = mpc52xx_irqhost_unmap,
+};
+
+void __init
+mpc52xx_init_irq(void)
+{
+	int i;
+        u32 intr_ctrl;
+	
+
+        /* Remap the necessary zones */
+        intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+        sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
+
+        if ((intr==NULL) || (sdma==NULL))
+                panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+        /* 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);
+        /* Initialize irq_desc[i].handler's with mpc52xx_ic. */
+        for (i = 0; i < NR_IRQS; i++) {
+                irq_desc[i].chip = &mpc52xx_irqchip;
+                irq_desc[i].status = IRQ_LEVEL;
+		
+        }
+
+#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
+        for (i=0 ; i<4 ; i++) {
+                int mode;
+                mode = IRQn_MODE(intr_ctrl,i);
+                if ((mode == 0x1) || (mode == 0x2))
+                        irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 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_BDLC_IRQ+1, &mpc52xx_irqhost_ops, -1);
+	pr_debug("%s: mpc52xx_irqhost =%p\n", __func__, mpc52xx_irqhost );
+}
+
+unsigned int
+mpc52xx_get_irq(void)
+{
+        u32 status;
+	int virq;
+        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_CRIT_IRQ_BASE;
+        } else if (status & 0x00200000)
+        {		/* main */
+                irq = (status >> 16) & 0x1f;
+                if (irq == 4)			/* low priority peripheral */
+                        goto peripheral;
+                irq += MPC52xx_MAIN_IRQ_BASE;
+        } else if (status & 0x20000000)
+        {		/* peripheral */
+peripheral:
+                irq = (status >> 24) & 0x1f;
+                if (irq == 0) {			/* bestcomm */
+                        status = in_be32(&sdma->IntPend);
+                        irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1;
+                } else
+                        irq += MPC52xx_PERP_IRQ_BASE;
+
+        }
+
+	virq = irq_linear_revmap(mpc52xx_irqhost, irq);
+	pr_debug("%s: irq=%d -> %d\n", __func__, irq, virq);
+
+        return virq;
+}
+
--- a/arch/powerpc/Kconfig	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/Kconfig	2006-10-26 11:32:54.000000000 +0200
@@ -384,6 +384,12 @@ config PPC_CHRP
 	select PPC_RTAS
 	select PPC_MPC106
 	select PPC_UDBG_16550
+	select PPC_MPC52xx_PIC
+	default y
+
+config PPC_MPC52xx_PIC
+        bool
+	depends on PPC_CHRP
 	default y
 
 config PPC_PMAC
--- a/arch/powerpc/platforms/chrp/setup.c	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/platforms/chrp/setup.c	2006-10-26 10:59:39.000000000 +0200
@@ -51,6 +51,7 @@
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 #include <asm/xmon.h>
+#include <asm/mpc52xx.h>
 
 #include "chrp.h"
 
@@ -435,6 +436,51 @@ static struct irqaction xmon_irqaction =
 };
 #endif
 
+
+struct device_node *find_mpc52xx_pic(void)
+{
+	struct device_node *dev;
+	const char *piccompatible_list[] =
+	{
+		"mpc5200-interrupt-controller",
+		"mpc52xx-interrupt-controller",
+		"mpc52xx-pic",
+		"mpc5200-pic",
+		"5200-interrupt-controller",
+		"52xx-interrupt-controller",
+		"52xx-pic",
+		"5200-pic",
+		NULL
+	};
+
+	/* Look for an MPC52xx interrupt controller */
+	for_each_node_by_type(dev, "interrupt-controller")
+	{
+		const char **piccompatible_entry = piccompatible_list;
+
+		for(piccompatible_entry = piccompatible_list; *piccompatible_entry; piccompatible_entry++ )
+		{
+			if (device_is_compatible(dev, *piccompatible_entry ))
+				return dev;
+		}
+	}
+
+	return NULL;
+}
+
+static int  __init chrp_find_mpc52xx_pic(void)
+{
+	if (find_mpc52xx_pic())
+	{
+		printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
+		ppc_md.get_irq = mpc52xx_get_irq;
+		mpc52xx_init_irq();
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
 static void __init chrp_find_8259(void)
 {
 	struct device_node *np, *pic = NULL;
@@ -494,8 +540,12 @@ void __init chrp_init_IRQ(void)
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
 	struct device_node *kbd;
 #endif
-	chrp_find_openpic();
-	chrp_find_8259();
+
+	if ( chrp_find_mpc52xx_pic() < 0)
+	{
+		chrp_find_openpic();
+		chrp_find_8259();
+	}
 
 #ifdef CONFIG_SMP
 	/* Pegasos has no MPIC, those ops would make it crash. It might be an
diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
--- a/include/asm-ppc/mpc52xx.h	2006-10-25 19:07:48.000000000 +0200
+++ b/include/asm-ppc/mpc52xx.h	2006-10-25 19:11:55.000000000 +0200
@@ -119,7 +119,7 @@ enum ppc_sys_devices {
 #define MPC52xx_SDMA_IRQ_NUM	17
 #define MPC52xx_PERP_IRQ_NUM	23
 
-#define MPC52xx_CRIT_IRQ_BASE	1
+#define MPC52xx_CRIT_IRQ_BASE	0
 #define MPC52xx_MAIN_IRQ_BASE	(MPC52xx_CRIT_IRQ_BASE + MPC52xx_CRIT_IRQ_NUM)
 #define MPC52xx_SDMA_IRQ_BASE	(MPC52xx_MAIN_IRQ_BASE + MPC52xx_MAIN_IRQ_NUM)
 #define MPC52xx_PERP_IRQ_BASE	(MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)
@@ -415,7 +415,7 @@ struct mpc52xx_cdm {
 #ifndef __ASSEMBLY__
 
 extern void mpc52xx_init_irq(void);
-extern int mpc52xx_get_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
 
 extern unsigned long mpc52xx_find_end_of_memory(void);
 extern void mpc52xx_set_bat(void);

[-- 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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 12:59       ` Nicolas DET
@ 2006-10-26 16:02         ` Grant Likely
  2006-10-26 16:09           ` Grant Likely
                             ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: Grant Likely @ 2006-10-26 16:02 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

(minor) Whitespace is still inconsistent; mostly spaces used where
they should be tabs and a few lines longer than 80 chars.  Running the
source through scripts/Lindent will help.

On 10/26/06, Nicolas DET <nd@bplan-gmbh.de> wrote:
> --- a/arch/powerpc/sysdev/mpc52xx_pic.c 2006-10-25 19:07:24.000000000 +0200
> +++ b/arch/powerpc/sysdev/mpc52xx_pic.c 2006-10-26 10:55:44.000000000 +0200
> @@ -0,0 +1,371 @@
> +/*
> + * arch/powerpc/sysdev/mpc52xx_pic.c
> + *
> + * Programmable Interrupt Controller functions for the Freescale MPC52xx
> + * embedded CPU.
> + * Modified for CHRP Efika 5K2

Don't really need to add the "Modified for.." line; That's what git is
for.  Besides this code is modified for more than just the Efika now.
:)

> + *
> + * Maintainer : Sylvain Munaut <tnt@246tNt.com>
> + *
> + * Based on (well, mostly copied from) the code from the 2.4 kernel by
> + * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.

Ditto for this; but I know you didn't add it.  :)  Although this kind
of comment is more justified because it captures information not
maintained in git.  (Namely where the original file came from.)

> + *
> + * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
> + * Copyright (C) 2003 Montavista Software, Inc

You should add a bplan copyright line too.

> + *
> + * 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.
> + */
> +
> +//#define DEBUG

C++ style comment bad.  :)

> +
> +#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 <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;
> +

(snip)

> --- a/arch/powerpc/Kconfig      2006-10-25 19:07:23.000000000 +0200
> +++ b/arch/powerpc/Kconfig      2006-10-26 11:32:54.000000000 +0200
> @@ -384,6 +384,12 @@ config PPC_CHRP
>         select PPC_RTAS
>         select PPC_MPC106
>         select PPC_UDBG_16550
> +       select PPC_MPC52xx_PIC
> +       default y
> +
> +config PPC_MPC52xx_PIC
> +        bool
> +       depends on PPC_CHRP
>         default y

This isn't good for embedded 52xx boards.  Anything u-boot based
cannot be CHRP.  Please drop the "depends on" line

> --- a/arch/powerpc/platforms/chrp/setup.c       2006-10-25 19:07:23.000000000 +0200
> +++ b/arch/powerpc/platforms/chrp/setup.c       2006-10-26 10:59:39.000000000 +0200
> @@ -51,6 +51,7 @@
>  #include <asm/mpic.h>
>  #include <asm/rtas.h>
>  #include <asm/xmon.h>
> +#include <asm/mpc52xx.h>
>
>  #include "chrp.h"
>
> @@ -435,6 +436,51 @@ static struct irqaction xmon_irqaction =
>  };
>  #endif
>
> +
> +struct device_node *find_mpc52xx_pic(void)
> +{
> +       struct device_node *dev;
> +       const char *piccompatible_list[] =
> +       {
> +               "mpc5200-interrupt-controller",
> +               "mpc52xx-interrupt-controller",
> +               "mpc52xx-pic",
> +               "mpc5200-pic",
> +               "5200-interrupt-controller",
> +               "52xx-interrupt-controller",
> +               "52xx-pic",
> +               "5200-pic",
> +               NULL
> +       };

Considering Efika is the *only* CHRP 52xx board out there at the
moment, and only a handful of embedded folks trying to move it to
arch/powerpc, surely we can come to an agreement now on what this
thing is named.  :)

Seriously, just recommend a name to use and everyone will use it.
Providing a list of names means that every name in your list will be
used.

> +
> +       /* Look for an MPC52xx interrupt controller */
> +       for_each_node_by_type(dev, "interrupt-controller")
> +       {
> +               const char **piccompatible_entry = piccompatible_list;
> +
> +               for(piccompatible_entry = piccompatible_list; *piccompatible_entry; piccompatible_entry++ )
> +               {
> +                       if (device_is_compatible(dev, *piccompatible_entry ))
> +                               return dev;
> +               }
> +       }
> +
> +       return NULL;
> +}
> +
> +static int  __init chrp_find_mpc52xx_pic(void)
> +{
> +       if (find_mpc52xx_pic())
> +       {
> +               printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
> +               ppc_md.get_irq = mpc52xx_get_irq;
> +               mpc52xx_init_irq();
> +               return 0;
> +       }
> +
> +       return -ENODEV;
> +}
> +
>  static void __init chrp_find_8259(void)
>  {
>         struct device_node *np, *pic = NULL;
> @@ -494,8 +540,12 @@ void __init chrp_init_IRQ(void)
>  #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
>         struct device_node *kbd;
>  #endif
> -       chrp_find_openpic();
> -       chrp_find_8259();
> +
> +       if ( chrp_find_mpc52xx_pic() < 0)
> +       {
> +               chrp_find_openpic();
> +               chrp_find_8259();
> +       }

Why?  Why not just add the call to chrp_find_mpc52xx_pic() before or
after the other two chrp_find_ calls?  Will calling them cause things
to break?

Keep the code simple.

Cheers,
g.

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

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 16:02         ` Grant Likely
@ 2006-10-26 16:09           ` Grant Likely
  2006-10-26 17:06             ` Nicolas DET
  2006-10-26 16:45           ` Sven Luther
  2006-10-26 19:50           ` Nicolas DET
  2 siblings, 1 reply; 40+ messages in thread
From: Grant Likely @ 2006-10-26 16:09 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

On 10/26/06, Grant Likely <grant.likely@secretlab.ca> wrote:
> On 10/26/06, Nicolas DET <nd@bplan-gmbh.de> wrote:
> > -       chrp_find_openpic();
> > -       chrp_find_8259();
> > +
> > +       if ( chrp_find_mpc52xx_pic() < 0)
> > +       {
> > +               chrp_find_openpic();
> > +               chrp_find_8259();
> > +       }
>
> Why?  Why not just add the call to chrp_find_mpc52xx_pic() before or
> after the other two chrp_find_ calls?  Will calling them cause things
> to break?
>
> Keep the code simple.

... as possible; but no simpler.

:)

g.

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

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 16:02         ` Grant Likely
  2006-10-26 16:09           ` Grant Likely
@ 2006-10-26 16:45           ` Sven Luther
  2006-10-26 19:50           ` Nicolas DET
  2 siblings, 0 replies; 40+ messages in thread
From: Sven Luther @ 2006-10-26 16:45 UTC (permalink / raw)
  To: Grant Likely; +Cc: akpm, linuxppc-embedded, sl, linuxppc-dev, sven, sha

On Thu, Oct 26, 2006 at 10:02:00AM -0600, Grant Likely wrote:
> >+config PPC_MPC52xx_PIC
> >+        bool
> >+       depends on PPC_CHRP
> >        default y
> 
> This isn't good for embedded 52xx boards.  Anything u-boot based
> cannot be CHRP.  Please drop the "depends on" line

This was a direct suggestion from benh, ppc_chrp should not be dropped, but
ored with whatever you are using, or somethiung like it.

Friendly,

Sven Luther

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 16:09           ` Grant Likely
@ 2006-10-26 17:06             ` Nicolas DET
  2006-10-26 17:54               ` Sylvain Munaut
                                 ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: Nicolas DET @ 2006-10-26 17:06 UTC (permalink / raw)
  To: Grant Likely; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

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

Grant Likely wrote:
> On 10/26/06, Grant Likely <grant.likely@secretlab.ca> wrote:
>> On 10/26/06, Nicolas DET <nd@bplan-gmbh.de> wrote:
>> > -       chrp_find_openpic();
>> > -       chrp_find_8259();
>> > +
>> > +       if ( chrp_find_mpc52xx_pic() < 0)
>> > +       {
>> > +               chrp_find_openpic();
>> > +               chrp_find_8259();
>> > +       }
>>
>> Why?  Why not just add the call to chrp_find_mpc52xx_pic() before or
>> after the other two chrp_find_ calls?  Will calling them cause things
>> to break?
>>

As decided on the IRC channel. a patch which remove the check but fix 
chrp_find_8259().

Regards,

[-- Attachment #2: chrpmpc52xx_2.6.19-rc3.patch --]
[-- Type: text/plain, Size: 15259 bytes --]

--- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/Makefile	2006-10-26 11:38:02.000000000 +0200
@@ -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/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-26 18:55:04.000000000 +0200
@@ -0,0 +1,368 @@
+/*
+ * arch/powerpc/sysdev/mpc52xx_pic.c
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx 
+ * embedded CPU.
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+#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 <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 void
+mpc52xx_ic_disable(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        if (irq == MPC52xx_IRQ0) {
+                val = in_be32(&intr->ctrl);
+                val &= ~(1 << 11);
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_IRQ1) {
+                BUG();
+        } else if (irq <= MPC52xx_IRQ3) {
+                val = in_be32(&intr->ctrl);
+                val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+                val = in_be32(&intr->main_mask);
+                val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
+                out_be32(&intr->main_mask, val);
+        } else if (irq < MPC52xx_PERP_IRQ_BASE) {
+                val = in_be32(&sdma->IntMask);
+                val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
+                out_be32(&sdma->IntMask, val);
+        } else {
+                val = in_be32(&intr->per_mask);
+                val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
+                out_be32(&intr->per_mask, val);
+        }
+}
+
+static void
+mpc52xx_ic_enable(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        if (irq == MPC52xx_IRQ0) {
+                val = in_be32(&intr->ctrl);
+                val |= 1 << 11;
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_IRQ1) {
+                BUG();
+        } else if (irq <= MPC52xx_IRQ3) {
+                val = in_be32(&intr->ctrl);
+                val |= 1 << (10 - (irq - MPC52xx_IRQ1));
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+                val = in_be32(&intr->main_mask);
+                val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
+                out_be32(&intr->main_mask, val);
+        } else if (irq < MPC52xx_PERP_IRQ_BASE) {
+                val = in_be32(&sdma->IntMask);
+                val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+                out_be32(&sdma->IntMask, val);
+        } else {
+                val = in_be32(&intr->per_mask);
+                val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
+                out_be32(&intr->per_mask, val);
+        }
+}
+
+static void
+mpc52xx_ic_ack(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        /*
+         * Only some irqs are reset here, others in interrupting hardware.
+         */
+
+        switch (irq) {
+        case MPC52xx_IRQ0:
+                val = in_be32(&intr->ctrl);
+                val |= 0x08000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_CCS_IRQ:
+                val = in_be32(&intr->enc_status);
+                val |= 0x00000400;
+                out_be32(&intr->enc_status, val);
+                break;
+        case MPC52xx_IRQ1:
+                val = in_be32(&intr->ctrl);
+                val |= 0x04000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_IRQ2:
+                val = in_be32(&intr->ctrl);
+                val |= 0x02000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_IRQ3:
+                val = in_be32(&intr->ctrl);
+                val |= 0x01000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        default:
+                if (irq >= MPC52xx_SDMA_IRQ_BASE
+                                && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
+                        out_be32(&sdma->IntPend,
+                                 1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+                }
+
+                break;
+        }
+
+}
+
+static void
+mpc52xx_ic_disable_and_ack(unsigned int irq)
+{
+        mpc52xx_ic_disable(irq);
+        mpc52xx_ic_ack(irq);
+}
+
+static void
+mpc52xx_ic_end(unsigned int irq)
+{
+        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+                mpc52xx_ic_enable(irq);
+}
+
+static struct irq_chip mpc52xx_irqchip = {
+	.name	= " MPC52xx  ",
+	.enable		= mpc52xx_ic_enable,
+	.disable	= mpc52xx_ic_disable,
+	.ack		= mpc52xx_ic_disable_and_ack,
+	.end		= mpc52xx_ic_end,
+};
+
+
+extern struct device_node *find_mpc52xx_pic(void);
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+	pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_pic(),  node);
+	return find_mpc52xx_pic() == 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)
+{
+        static unsigned char map_senses[4] = {
+                IRQ_TYPE_LEVEL_HIGH,
+                IRQ_TYPE_EDGE_FALLING,
+                IRQ_TYPE_EDGE_RISING,
+		IRQ_TYPE_LEVEL_LOW,
+        };
+
+        int intrvect_l1;
+        int intrvect_l2;
+	int intrvect_type;
+        int intrvect_linux;
+
+        pr_debug("%s:\n", __func__);
+
+	if (intsize!=3)
+		return -1;
+
+        intrvect_l1 = (int) intspec[0];
+        intrvect_l2 = (int) intspec[1];
+	intrvect_type = (int) intspec[2];
+
+        pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2, intrvect_type );
+
+        switch(intrvect_l1) {
+        case 0: /* Critical */
+                intrvect_linux = MPC52xx_CRIT_IRQ_BASE;
+                break;
+
+        case 1: /* Main */
+                intrvect_linux = MPC52xx_MAIN_IRQ_BASE;
+                break;
+
+        case 2: /* Periph */
+                intrvect_linux = MPC52xx_PERP_IRQ_BASE;
+                break;
+
+        case 3: /* Bestcomm */
+                intrvect_linux = MPC52xx_SDMA_IRQ_BASE;
+                break;
+
+        default:
+                if ( printk_ratelimit() )
+			printk(KERN_ERR "Wrong L1 interrupt vector (%d)\n", intrvect_l1);
+
+                return -1;
+        }
+
+        intrvect_linux += intrvect_l2;
+
+        pr_debug("return %d\n", intrvect_linux);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = map_senses[intrvect_type];
+
+        return 0;
+
+}
+
+int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw)
+{
+	pr_debug("%s: v=%d, hw=%d\n", __func__, virq, (int) hw);
+
+	return 0;
+}
+
+void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
+{
+	pr_debug("%s: v=%d\n", __func__, virq);
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+        .match = mpc52xx_irqhost_match,
+        .xlate = mpc52xx_irqhost_xlate,
+	.map   = mpc52xx_irqhost_map,
+	.unmap = mpc52xx_irqhost_unmap,
+};
+
+void __init
+mpc52xx_init_irq(void)
+{
+	int i;
+        u32 intr_ctrl;
+	
+
+        /* Remap the necessary zones */
+        intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+        sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
+
+        if ((intr==NULL) || (sdma==NULL))
+                panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+        /* 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);
+        /* Initialize irq_desc[i].handler's with mpc52xx_ic. */
+        for (i = 0; i < NR_IRQS; i++) {
+                irq_desc[i].chip = &mpc52xx_irqchip;
+                irq_desc[i].status = IRQ_LEVEL;
+		
+        }
+
+#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
+        for (i=0 ; i<4 ; i++) {
+                int mode;
+                mode = IRQn_MODE(intr_ctrl,i);
+                if ((mode == 0x1) || (mode == 0x2))
+                        irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 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, NR_IRQS, &mpc52xx_irqhost_ops, -1);
+	pr_debug("%s: mpc52xx_irqhost =%p\n", __func__, mpc52xx_irqhost );
+}
+
+unsigned int
+mpc52xx_get_irq(void)
+{
+        u32 status;
+	int virq;
+        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_CRIT_IRQ_BASE;
+        } else if (status & 0x00200000)
+        {		/* main */
+                irq = (status >> 16) & 0x1f;
+                if (irq == 4)			/* low priority peripheral */
+                        goto peripheral;
+                irq += MPC52xx_MAIN_IRQ_BASE;
+        } else if (status & 0x20000000)
+        {		/* peripheral */
+peripheral:
+                irq = (status >> 24) & 0x1f;
+                if (irq == 0) {			/* bestcomm */
+                        status = in_be32(&sdma->IntPend);
+                        irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1;
+                } else
+                        irq += MPC52xx_PERP_IRQ_BASE;
+
+        }
+
+	virq = irq_linear_revmap(mpc52xx_irqhost, irq);
+	pr_debug("%s: irq=%d -> %d\n", __func__, irq, virq);
+
+        return virq;
+}
+
--- a/arch/powerpc/Kconfig	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/Kconfig	2006-10-26 18:55:58.000000000 +0200
@@ -384,6 +384,11 @@ config PPC_CHRP
 	select PPC_RTAS
 	select PPC_MPC106
 	select PPC_UDBG_16550
+	select PPC_MPC52xx_PIC
+	default y
+
+config PPC_MPC52xx_PIC
+        bool
 	default y
 
 config PPC_PMAC
--- a/arch/powerpc/platforms/chrp/setup.c	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/platforms/chrp/setup.c	2006-10-26 18:56:34.000000000 +0200
@@ -51,6 +51,7 @@
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 #include <asm/xmon.h>
+#include <asm/mpc52xx.h>
 
 #include "chrp.h"
 
@@ -435,6 +436,51 @@ static struct irqaction xmon_irqaction =
 };
 #endif
 
+
+struct device_node *find_mpc52xx_pic(void)
+{
+	struct device_node *dev;
+	const char *piccompatible_list[] =
+	{
+		"mpc5200-interrupt-controller",
+		"mpc52xx-interrupt-controller",
+		"mpc52xx-pic",
+		"mpc5200-pic",
+		"5200-interrupt-controller",
+		"52xx-interrupt-controller",
+		"52xx-pic",
+		"5200-pic",
+		NULL
+	};
+
+	/* Look for an MPC52xx interrupt controller */
+	for_each_node_by_type(dev, "interrupt-controller")
+	{
+		const char **piccompatible_entry = piccompatible_list;
+
+		for(piccompatible_entry = piccompatible_list; *piccompatible_entry; piccompatible_entry++ )
+		{
+			if (device_is_compatible(dev, *piccompatible_entry ))
+				return dev;
+		}
+	}
+
+	return NULL;
+}
+
+static int  __init chrp_find_mpc52xx_pic(void)
+{
+	if (find_mpc52xx_pic())
+	{
+		printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
+		ppc_md.get_irq = mpc52xx_get_irq;
+		mpc52xx_init_irq();
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
 static void __init chrp_find_8259(void)
 {
 	struct device_node *np, *pic = NULL;
@@ -473,8 +519,11 @@ static void __init chrp_find_8259(void)
 		break;
 	}
 	if (np == NULL)
-		printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
-		       " address, polling\n");
+	{
+		printk(KERN_WARNING "Cannot find PCI/i8259 interrupt acknowledge"
+		       " Fix your tree!\n");
+		return;
+	}
 
 	i8259_init(pic, chrp_int_ack);
 	if (ppc_md.get_irq == NULL)
@@ -494,6 +543,8 @@ void __init chrp_init_IRQ(void)
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
 	struct device_node *kbd;
 #endif
+
+	chrp_find_mpc52xx_pic();
 	chrp_find_openpic();
 	chrp_find_8259();
 
diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
--- a/include/asm-ppc/mpc52xx.h	2006-10-25 19:07:48.000000000 +0200
+++ b/include/asm-ppc/mpc52xx.h	2006-10-25 19:11:55.000000000 +0200
@@ -119,7 +119,7 @@ enum ppc_sys_devices {
 #define MPC52xx_SDMA_IRQ_NUM	17
 #define MPC52xx_PERP_IRQ_NUM	23
 
-#define MPC52xx_CRIT_IRQ_BASE	1
+#define MPC52xx_CRIT_IRQ_BASE	0
 #define MPC52xx_MAIN_IRQ_BASE	(MPC52xx_CRIT_IRQ_BASE + MPC52xx_CRIT_IRQ_NUM)
 #define MPC52xx_SDMA_IRQ_BASE	(MPC52xx_MAIN_IRQ_BASE + MPC52xx_MAIN_IRQ_NUM)
 #define MPC52xx_PERP_IRQ_BASE	(MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)
@@ -415,7 +415,7 @@ struct mpc52xx_cdm {
 #ifndef __ASSEMBLY__
 
 extern void mpc52xx_init_irq(void);
-extern int mpc52xx_get_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
 
 extern unsigned long mpc52xx_find_end_of_memory(void);
 extern void mpc52xx_set_bat(void);

[-- 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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-25 19:05 [PATCH] General CHRP/MPC5K2 platform support patch Nicolas DET
                   ` (2 preceding siblings ...)
  2006-10-25 23:01 ` Grant Likely
@ 2006-10-26 17:17 ` John Rigby
  2006-10-26 17:23   ` Nicolas DET
                     ` (2 more replies)
  3 siblings, 3 replies; 40+ messages in thread
From: John Rigby @ 2006-10-26 17:17 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

>
> * mpc5k2_bestcomm.c (& helpers): I've been in contact with others people
> using bestcomm and please to see the development was still active. I'm
> already using latest code on my board but this is not include in this
> patch. Indeed, it needs some changes for ARCH=powerpc. Moreover, we have
> a different approach for the tasks. I'll be pleased to work with the
> bestcomm folks.
>

So you preload the bestcomm task code in your boot loader?  Do those
of us using other bootloaders still have the option of loading the
task code later in linux?

What api are you using?  Sylvain's proposed one based on Dale's with
some additions from me?  Or have you come up with your own?

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 17:17 ` John Rigby
@ 2006-10-26 17:23   ` Nicolas DET
  2006-10-26 17:33   ` Sylvain Munaut
  2006-10-27  2:57   ` Benjamin Herrenschmidt
  2 siblings, 0 replies; 40+ messages in thread
From: Nicolas DET @ 2006-10-26 17:23 UTC (permalink / raw)
  To: John Rigby; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

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

John Rigby wrote:
>>
>> * mpc5k2_bestcomm.c (& helpers): I've been in contact with others people
>> using bestcomm and please to see the development was still active. I'm
>> already using latest code on my board but this is not include in this
>> patch. Indeed, it needs some changes for ARCH=powerpc. Moreover, we have
>> a different approach for the tasks. I'll be pleased to work with the
>> bestcomm folks.
>>
> 
> So you preload the bestcomm task code in your boot loader?  

Yes.

>Do those
> of us using other bootloaders still have the option of loading the
> task code later in linux?

Well, just reading the phy address from 0xf008000 to 0xf00c0000 (if I 
remenber correctly) should be enough to get the tasks code.

> What api are you using?  Sylvain's proposed one based on Dale's with
> some additions from me?  Or have you come up with your own?
> 

We implemented our own yet. However, we could moved to any.

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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 17:17 ` John Rigby
  2006-10-26 17:23   ` Nicolas DET
@ 2006-10-26 17:33   ` Sylvain Munaut
  2006-10-27  3:03     ` Benjamin Herrenschmidt
  2006-10-27  2:57   ` Benjamin Herrenschmidt
  2 siblings, 1 reply; 40+ messages in thread
From: Sylvain Munaut @ 2006-10-26 17:33 UTC (permalink / raw)
  To: John Rigby; +Cc: akpm, linuxppc-embedded, sl, linuxppc-dev, sha

John Rigby wrote:
>>
>> * mpc5k2_bestcomm.c (& helpers): I've been in contact with others people
>> using bestcomm and please to see the development was still active. I'm
>> already using latest code on my board but this is not include in this
>> patch. Indeed, it needs some changes for ARCH=powerpc. Moreover, we have
>> a different approach for the tasks. I'll be pleased to work with the
>> bestcomm folks.
>>
>
> So you preload the bestcomm task code in your boot loader?  Do those
> of us using other bootloaders still have the option of loading the
> task code later in linux?
>
> What api are you using?  Sylvain's proposed one based on Dale's with
> some additions from me?  Or have you come up with your own?
>
Hi John,

I've sent him the latest API you describe.

As for task preloading, I'm not too sure what Nicolas' plan is. I'm
waiting to see
what he's proposing.

Since the bestcomm init is in a module, a different module could be
implemented,
(like bestcomm-chrp5k2.ko) that instead of clearing SRAM and doing
everything
from scrtch, would rely on the bootloader more. This would allow
"custom" tasks
to be marked as "don't touch". So if the bootloader want to load
something that
will not be altered by the linux driver (for whatever reason ...)

However, for the tasks like FEC and ATA and everything supported in the
kernel
natively, I would still recommend reload the task code (anyway the
driver is gonna
reset the task and everything ...) Trying to reuse the microcode loaded
by the
bootloader is not a great idea IMHO. (Imagine, the fec driver is changed
to use
the latest microcode, but the bootloader is not ... both have to be in
perfect sync ...)

We would still have to compare the internal FDT and the preloaded one
though since
they have to match ...



       Sylvain

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 17:06             ` Nicolas DET
@ 2006-10-26 17:54               ` Sylvain Munaut
  2006-10-27  3:08                 ` Benjamin Herrenschmidt
  2006-10-26 19:14               ` Grant Likely
  2006-10-27  2:49               ` Benjamin Herrenschmidt
  2 siblings, 1 reply; 40+ messages in thread
From: Sylvain Munaut @ 2006-10-26 17:54 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

Hi Nicolas,


I don't have much to add to what's already been posted, so here's a
couple of details,
mainly compatibility concerns with the legacy arch/ppc tree.

>  
> diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
> --- a/include/asm-ppc/mpc52xx.h	2006-10-25 19:07:48.000000000 +0200
> +++ b/include/asm-ppc/mpc52xx.h	2006-10-25 19:11:55.000000000 +0200
> @@ -119,7 +119,7 @@ enum ppc_sys_devices {
>  #define MPC52xx_SDMA_IRQ_NUM	17
>  #define MPC52xx_PERP_IRQ_NUM	23
>  
> -#define MPC52xx_CRIT_IRQ_BASE	1
> +#define MPC52xx_CRIT_IRQ_BASE	0
As explained in IRC, I'm not sure about this.
I was previously talked into applying this to avoid using interrupt
number 0. In the LITE5200 IRQ0 is used for PCI. It's interrupt number
is equal to MPC52xx_CRIT_IRQ_BASE and if it's 0 some drivers just don't
work.
That's when using the arch/ppc code. Apparently this is no longer an
issue in arch/powerpc (someone to confirm and explain me why ? I would guess
the irq_linear_revmap thingie ), but can a "standard" lite5200 be booted
in a arch/powerpc kernel ?

So if no critical, I would postpone that change until it's confirmed
a lite5200 can boot ...


> -extern int mpc52xx_get_irq(void);
> +extern unsigned int mpc52xx_get_irq(void);
Mmmh, the one in arch/ppc is not unsigned but I guess the warning is fine.


Finally, some triviality : The patch adds some space on empty lines. Also,
the indentation is sometimes done with space and sometimes with space ...




    Sylvain

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 17:06             ` Nicolas DET
  2006-10-26 17:54               ` Sylvain Munaut
@ 2006-10-26 19:14               ` Grant Likely
  2006-10-26 19:21                 ` Nicolas DET
  2006-10-27  2:49               ` Benjamin Herrenschmidt
  2 siblings, 1 reply; 40+ messages in thread
From: Grant Likely @ 2006-10-26 19:14 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

I've already made these comments on IRC; but I'll repeat them here for
posterity.  :)

General:
- Run this code through Lindent; fixes up spacing and line endings

On 10/26/06, Nicolas DET <nd@bplan-gmbh.de> wrote:
> --- a/arch/powerpc/platforms/chrp/setup.c       2006-10-25 19:07:23.000000000 +0200
> +++ b/arch/powerpc/platforms/chrp/setup.c       2006-10-26 18:56:34.000000000 +0200
> @@ -51,6 +51,7 @@
>  #include <asm/mpic.h>
>  #include <asm/rtas.h>
>  #include <asm/xmon.h>
> +#include <asm/mpc52xx.h>
>
>  #include "chrp.h"
>
> @@ -435,6 +436,51 @@ static struct irqaction xmon_irqaction =
>  };
>  #endif
>
> +
> +struct device_node *find_mpc52xx_pic(void)
> +{
> +       struct device_node *dev;
> +       const char *piccompatible_list[] =
> +       {
> +               "mpc5200-interrupt-controller",
> +               "mpc52xx-interrupt-controller",
> +               "mpc52xx-pic",
> +               "mpc5200-pic",
> +               "5200-interrupt-controller",
> +               "52xx-interrupt-controller",
> +               "52xx-pic",
> +               "5200-pic",
> +               NULL
> +       };

As you mentioned on IRC that benh suggested "mpc52xx-pic"; Just call
it mpc52xx-pic and be done with it.  Don't need to loop over this
table.  If incompatible variants appear in the future; this can
change.

> +
> +       /* Look for an MPC52xx interrupt controller */
> +       for_each_node_by_type(dev, "interrupt-controller")
> +       {
> +               const char **piccompatible_entry = piccompatible_list;
> +
> +               for(piccompatible_entry = piccompatible_list; *piccompatible_entry; piccompatible_entry++ )
> +               {
> +                       if (device_is_compatible(dev, *piccompatible_entry ))
> +                               return dev;
> +               }
> +       }
> +
> +       return NULL;
> +}
> +
> +static int  __init chrp_find_mpc52xx_pic(void)
> +{
> +       if (find_mpc52xx_pic())
> +       {
> +               printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
> +               ppc_md.get_irq = mpc52xx_get_irq;
> +               mpc52xx_init_irq();
> +               return 0;
> +       }
> +
> +       return -ENODEV;
> +}
> +
>  static void __init chrp_find_8259(void)
>  {
>         struct device_node *np, *pic = NULL;
> @@ -473,8 +519,11 @@ static void __init chrp_find_8259(void)
>                 break;
>         }
>         if (np == NULL)
> -               printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
> -                      " address, polling\n");
> +       {
> +               printk(KERN_WARNING "Cannot find PCI/i8259 interrupt acknowledge"
> +                      " Fix your tree!\n");
> +               return;
> +       }
>
>         i8259_init(pic, chrp_int_ack);
>         if (ppc_md.get_irq == NULL)

Missing the fixup to prevent i8258 from clobbering the 52xx-pic.  You
do need to have that change in this patch; or have this patch
dependent on another patch that fixes it.  Otherwise, as you know,
this patch is worthless!  :)

And on the other side of this coin; I don't think that the message
change in chrp_find_8259 has anything to do with adding mpc52xx.  :)
(Unfortunately, I have tendencies towards perfectionism)

And on the flip side, I would (*
> @@ -494,6 +543,8 @@ void __init chrp_init_IRQ(void)
>  #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
>         struct device_node *kbd;
>  #endif
> +
> +       chrp_find_mpc52xx_pic();
>         chrp_find_openpic();
>         chrp_find_8259();
>
> diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
> --- a/include/asm-ppc/mpc52xx.h 2006-10-25 19:07:48.000000000 +0200
> +++ b/include/asm-ppc/mpc52xx.h 2006-10-25 19:11:55.000000000 +0200
> @@ -119,7 +119,7 @@ enum ppc_sys_devices {
>  #define MPC52xx_SDMA_IRQ_NUM   17
>  #define MPC52xx_PERP_IRQ_NUM   23
>
> -#define MPC52xx_CRIT_IRQ_BASE  1
> +#define MPC52xx_CRIT_IRQ_BASE  0

Is this *strictly* necessary for adding mpc52xx-pic support to
arch/powerpc?  If not, then move it to a separate patch.

>  #define MPC52xx_MAIN_IRQ_BASE  (MPC52xx_CRIT_IRQ_BASE + MPC52xx_CRIT_IRQ_NUM)
>  #define MPC52xx_SDMA_IRQ_BASE  (MPC52xx_MAIN_IRQ_BASE + MPC52xx_MAIN_IRQ_NUM)
>  #define MPC52xx_PERP_IRQ_BASE  (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)
> @@ -415,7 +415,7 @@ struct mpc52xx_cdm {
>  #ifndef __ASSEMBLY__
>
>  extern void mpc52xx_init_irq(void);
> -extern int mpc52xx_get_irq(void);
> +extern unsigned int mpc52xx_get_irq(void);

Yeah, you really shouldn't do this without fixing the arch/ppc side too.

g.

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

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 19:14               ` Grant Likely
@ 2006-10-26 19:21                 ` Nicolas DET
  2006-10-26 19:32                   ` Nicolas DET
  0 siblings, 1 reply; 40+ messages in thread
From: Nicolas DET @ 2006-10-26 19:21 UTC (permalink / raw)
  To: Grant Likely; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

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

Grant Likely wrote:

>>
>> diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
>> --- a/include/asm-ppc/mpc52xx.h 2006-10-25 19:07:48.000000000 +0200
>> +++ b/include/asm-ppc/mpc52xx.h 2006-10-25 19:11:55.000000000 +0200
>> @@ -119,7 +119,7 @@ enum ppc_sys_devices {
>>  #define MPC52xx_SDMA_IRQ_NUM   17
>>  #define MPC52xx_PERP_IRQ_NUM   23
>>
>> -#define MPC52xx_CRIT_IRQ_BASE  1
>> +#define MPC52xx_CRIT_IRQ_BASE  0
> 
> Is this *strictly* necessary for adding mpc52xx-pic support to
> arch/powerpc?  If not, then move it to a separate patch.


Removed as it does not hurt ARCH=powerpc.

Bye

[-- Attachment #2: chrpmpc52xx_2.6.19-rc3.patch --]
[-- Type: text/plain, Size: 14370 bytes --]

--- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/Makefile	2006-10-26 11:38:02.000000000 +0200
@@ -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/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-26 18:55:04.000000000 +0200
@@ -0,0 +1,368 @@
+/*
+ * arch/powerpc/sysdev/mpc52xx_pic.c
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx 
+ * embedded CPU.
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+#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 <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 void
+mpc52xx_ic_disable(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        if (irq == MPC52xx_IRQ0) {
+                val = in_be32(&intr->ctrl);
+                val &= ~(1 << 11);
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_IRQ1) {
+                BUG();
+        } else if (irq <= MPC52xx_IRQ3) {
+                val = in_be32(&intr->ctrl);
+                val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+                val = in_be32(&intr->main_mask);
+                val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
+                out_be32(&intr->main_mask, val);
+        } else if (irq < MPC52xx_PERP_IRQ_BASE) {
+                val = in_be32(&sdma->IntMask);
+                val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
+                out_be32(&sdma->IntMask, val);
+        } else {
+                val = in_be32(&intr->per_mask);
+                val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
+                out_be32(&intr->per_mask, val);
+        }
+}
+
+static void
+mpc52xx_ic_enable(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        if (irq == MPC52xx_IRQ0) {
+                val = in_be32(&intr->ctrl);
+                val |= 1 << 11;
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_IRQ1) {
+                BUG();
+        } else if (irq <= MPC52xx_IRQ3) {
+                val = in_be32(&intr->ctrl);
+                val |= 1 << (10 - (irq - MPC52xx_IRQ1));
+                out_be32(&intr->ctrl, val);
+        } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+                val = in_be32(&intr->main_mask);
+                val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
+                out_be32(&intr->main_mask, val);
+        } else if (irq < MPC52xx_PERP_IRQ_BASE) {
+                val = in_be32(&sdma->IntMask);
+                val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+                out_be32(&sdma->IntMask, val);
+        } else {
+                val = in_be32(&intr->per_mask);
+                val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
+                out_be32(&intr->per_mask, val);
+        }
+}
+
+static void
+mpc52xx_ic_ack(unsigned int virq)
+{
+        u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+        /*
+         * Only some irqs are reset here, others in interrupting hardware.
+         */
+
+        switch (irq) {
+        case MPC52xx_IRQ0:
+                val = in_be32(&intr->ctrl);
+                val |= 0x08000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_CCS_IRQ:
+                val = in_be32(&intr->enc_status);
+                val |= 0x00000400;
+                out_be32(&intr->enc_status, val);
+                break;
+        case MPC52xx_IRQ1:
+                val = in_be32(&intr->ctrl);
+                val |= 0x04000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_IRQ2:
+                val = in_be32(&intr->ctrl);
+                val |= 0x02000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        case MPC52xx_IRQ3:
+                val = in_be32(&intr->ctrl);
+                val |= 0x01000000;
+                out_be32(&intr->ctrl, val);
+                break;
+        default:
+                if (irq >= MPC52xx_SDMA_IRQ_BASE
+                                && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
+                        out_be32(&sdma->IntPend,
+                                 1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+                }
+
+                break;
+        }
+
+}
+
+static void
+mpc52xx_ic_disable_and_ack(unsigned int irq)
+{
+        mpc52xx_ic_disable(irq);
+        mpc52xx_ic_ack(irq);
+}
+
+static void
+mpc52xx_ic_end(unsigned int irq)
+{
+        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+                mpc52xx_ic_enable(irq);
+}
+
+static struct irq_chip mpc52xx_irqchip = {
+	.name	= " MPC52xx  ",
+	.enable		= mpc52xx_ic_enable,
+	.disable	= mpc52xx_ic_disable,
+	.ack		= mpc52xx_ic_disable_and_ack,
+	.end		= mpc52xx_ic_end,
+};
+
+
+extern struct device_node *find_mpc52xx_pic(void);
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+	pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_pic(),  node);
+	return find_mpc52xx_pic() == 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)
+{
+        static unsigned char map_senses[4] = {
+                IRQ_TYPE_LEVEL_HIGH,
+                IRQ_TYPE_EDGE_FALLING,
+                IRQ_TYPE_EDGE_RISING,
+		IRQ_TYPE_LEVEL_LOW,
+        };
+
+        int intrvect_l1;
+        int intrvect_l2;
+	int intrvect_type;
+        int intrvect_linux;
+
+        pr_debug("%s:\n", __func__);
+
+	if (intsize!=3)
+		return -1;
+
+        intrvect_l1 = (int) intspec[0];
+        intrvect_l2 = (int) intspec[1];
+	intrvect_type = (int) intspec[2];
+
+        pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2, intrvect_type );
+
+        switch(intrvect_l1) {
+        case 0: /* Critical */
+                intrvect_linux = MPC52xx_CRIT_IRQ_BASE;
+                break;
+
+        case 1: /* Main */
+                intrvect_linux = MPC52xx_MAIN_IRQ_BASE;
+                break;
+
+        case 2: /* Periph */
+                intrvect_linux = MPC52xx_PERP_IRQ_BASE;
+                break;
+
+        case 3: /* Bestcomm */
+                intrvect_linux = MPC52xx_SDMA_IRQ_BASE;
+                break;
+
+        default:
+                if ( printk_ratelimit() )
+			printk(KERN_ERR "Wrong L1 interrupt vector (%d)\n", intrvect_l1);
+
+                return -1;
+        }
+
+        intrvect_linux += intrvect_l2;
+
+        pr_debug("return %d\n", intrvect_linux);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = map_senses[intrvect_type];
+
+        return 0;
+
+}
+
+int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw)
+{
+	pr_debug("%s: v=%d, hw=%d\n", __func__, virq, (int) hw);
+
+	return 0;
+}
+
+void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
+{
+	pr_debug("%s: v=%d\n", __func__, virq);
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+        .match = mpc52xx_irqhost_match,
+        .xlate = mpc52xx_irqhost_xlate,
+	.map   = mpc52xx_irqhost_map,
+	.unmap = mpc52xx_irqhost_unmap,
+};
+
+void __init
+mpc52xx_init_irq(void)
+{
+	int i;
+        u32 intr_ctrl;
+	
+
+        /* Remap the necessary zones */
+        intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+        sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
+
+        if ((intr==NULL) || (sdma==NULL))
+                panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+        /* 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);
+        /* Initialize irq_desc[i].handler's with mpc52xx_ic. */
+        for (i = 0; i < NR_IRQS; i++) {
+                irq_desc[i].chip = &mpc52xx_irqchip;
+                irq_desc[i].status = IRQ_LEVEL;
+		
+        }
+
+#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
+        for (i=0 ; i<4 ; i++) {
+                int mode;
+                mode = IRQn_MODE(intr_ctrl,i);
+                if ((mode == 0x1) || (mode == 0x2))
+                        irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 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, NR_IRQS, &mpc52xx_irqhost_ops, -1);
+	pr_debug("%s: mpc52xx_irqhost =%p\n", __func__, mpc52xx_irqhost );
+}
+
+unsigned int
+mpc52xx_get_irq(void)
+{
+        u32 status;
+	int virq;
+        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_CRIT_IRQ_BASE;
+        } else if (status & 0x00200000)
+        {		/* main */
+                irq = (status >> 16) & 0x1f;
+                if (irq == 4)			/* low priority peripheral */
+                        goto peripheral;
+                irq += MPC52xx_MAIN_IRQ_BASE;
+        } else if (status & 0x20000000)
+        {		/* peripheral */
+peripheral:
+                irq = (status >> 24) & 0x1f;
+                if (irq == 0) {			/* bestcomm */
+                        status = in_be32(&sdma->IntPend);
+                        irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1;
+                } else
+                        irq += MPC52xx_PERP_IRQ_BASE;
+
+        }
+
+	virq = irq_linear_revmap(mpc52xx_irqhost, irq);
+	pr_debug("%s: irq=%d -> %d\n", __func__, irq, virq);
+
+        return virq;
+}
+
--- a/arch/powerpc/Kconfig	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/Kconfig	2006-10-26 18:55:58.000000000 +0200
@@ -384,6 +384,11 @@ config PPC_CHRP
 	select PPC_RTAS
 	select PPC_MPC106
 	select PPC_UDBG_16550
+	select PPC_MPC52xx_PIC
+	default y
+
+config PPC_MPC52xx_PIC
+        bool
 	default y
 
 config PPC_PMAC
--- a/arch/powerpc/platforms/chrp/setup.c	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/platforms/chrp/setup.c	2006-10-26 18:56:34.000000000 +0200
@@ -51,6 +51,7 @@
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 #include <asm/xmon.h>
+#include <asm/mpc52xx.h>
 
 #include "chrp.h"
 
@@ -435,6 +436,51 @@ static struct irqaction xmon_irqaction =
 };
 #endif
 
+
+struct device_node *find_mpc52xx_pic(void)
+{
+	struct device_node *dev;
+	const char *piccompatible_list[] =
+	{
+		"mpc5200-interrupt-controller",
+		"mpc52xx-interrupt-controller",
+		"mpc52xx-pic",
+		"mpc5200-pic",
+		"5200-interrupt-controller",
+		"52xx-interrupt-controller",
+		"52xx-pic",
+		"5200-pic",
+		NULL
+	};
+
+	/* Look for an MPC52xx interrupt controller */
+	for_each_node_by_type(dev, "interrupt-controller")
+	{
+		const char **piccompatible_entry = piccompatible_list;
+
+		for(piccompatible_entry = piccompatible_list; *piccompatible_entry; piccompatible_entry++ )
+		{
+			if (device_is_compatible(dev, *piccompatible_entry ))
+				return dev;
+		}
+	}
+
+	return NULL;
+}
+
+static int  __init chrp_find_mpc52xx_pic(void)
+{
+	if (find_mpc52xx_pic())
+	{
+		printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
+		ppc_md.get_irq = mpc52xx_get_irq;
+		mpc52xx_init_irq();
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
 static void __init chrp_find_8259(void)
 {
 	struct device_node *np, *pic = NULL;
@@ -473,8 +519,11 @@ static void __init chrp_find_8259(void)
 		break;
 	}
 	if (np == NULL)
-		printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
-		       " address, polling\n");
+	{
+		printk(KERN_WARNING "Cannot find PCI/i8259 interrupt acknowledge"
+		       " Fix your tree!\n");
+		return;
+	}
 
 	i8259_init(pic, chrp_int_ack);
 	if (ppc_md.get_irq == NULL)
@@ -494,6 +543,8 @@ void __init chrp_init_IRQ(void)
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
 	struct device_node *kbd;
 #endif
+
+	chrp_find_mpc52xx_pic();
 	chrp_find_openpic();
 	chrp_find_8259();
 

[-- 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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 19:21                 ` Nicolas DET
@ 2006-10-26 19:32                   ` Nicolas DET
  0 siblings, 0 replies; 40+ messages in thread
From: Nicolas DET @ 2006-10-26 19:32 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

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

Nicolas DET wrote:
> Grant Likely wrote:
> 
>>>
>>> diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
>>> --- a/include/asm-ppc/mpc52xx.h 2006-10-25 19:07:48.000000000 +0200
>>> +++ b/include/asm-ppc/mpc52xx.h 2006-10-25 19:11:55.000000000 +0200
>>> @@ -119,7 +119,7 @@ enum ppc_sys_devices {
>>>  #define MPC52xx_SDMA_IRQ_NUM   17
>>>  #define MPC52xx_PERP_IRQ_NUM   23
>>>
>>> -#define MPC52xx_CRIT_IRQ_BASE  1
>>> +#define MPC52xx_CRIT_IRQ_BASE  0
>>
>> Is this *strictly* necessary for adding mpc52xx-pic support to
>> arch/powerpc?  If not, then move it to a separate patch.
> 
> 
> Removed as it does not hurt ARCH=powerpc.

Lindent...

[-- Attachment #2: chrpmpc52xx_2.6.19-rc3.patch --]
[-- Type: text/plain, Size: 12346 bytes --]

--- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/Makefile	2006-10-26 11:38:02.000000000 +0200
@@ -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/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-26 21:32:05.000000000 +0200
@@ -0,0 +1,363 @@
+/*
+ * arch/powerpc/sysdev/mpc52xx_pic.c
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx 
+ * embedded CPU.
+ * Modified for CHRP Efika 5K2
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+#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 <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 void mpc52xx_ic_disable(unsigned int virq)
+{
+	u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+	if (irq == MPC52xx_IRQ0) {
+		val = in_be32(&intr->ctrl);
+		val &= ~(1 << 11);
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC52xx_IRQ1) {
+		BUG();
+	} else if (irq <= MPC52xx_IRQ3) {
+		val = in_be32(&intr->ctrl);
+		val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+		val = in_be32(&intr->main_mask);
+		val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
+		out_be32(&intr->main_mask, val);
+	} else if (irq < MPC52xx_PERP_IRQ_BASE) {
+		val = in_be32(&sdma->IntMask);
+		val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
+		out_be32(&sdma->IntMask, val);
+	} else {
+		val = in_be32(&intr->per_mask);
+		val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
+		out_be32(&intr->per_mask, val);
+	}
+}
+
+static void mpc52xx_ic_enable(unsigned int virq)
+{
+	u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+	if (irq == MPC52xx_IRQ0) {
+		val = in_be32(&intr->ctrl);
+		val |= 1 << 11;
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC52xx_IRQ1) {
+		BUG();
+	} else if (irq <= MPC52xx_IRQ3) {
+		val = in_be32(&intr->ctrl);
+		val |= 1 << (10 - (irq - MPC52xx_IRQ1));
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+		val = in_be32(&intr->main_mask);
+		val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
+		out_be32(&intr->main_mask, val);
+	} else if (irq < MPC52xx_PERP_IRQ_BASE) {
+		val = in_be32(&sdma->IntMask);
+		val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+		out_be32(&sdma->IntMask, val);
+	} else {
+		val = in_be32(&intr->per_mask);
+		val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
+		out_be32(&intr->per_mask, val);
+	}
+}
+
+static void mpc52xx_ic_ack(unsigned int virq)
+{
+	u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+	/*
+	 * Only some irqs are reset here, others in interrupting hardware.
+	 */
+
+	switch (irq) {
+	case MPC52xx_IRQ0:
+		val = in_be32(&intr->ctrl);
+		val |= 0x08000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC52xx_CCS_IRQ:
+		val = in_be32(&intr->enc_status);
+		val |= 0x00000400;
+		out_be32(&intr->enc_status, val);
+		break;
+	case MPC52xx_IRQ1:
+		val = in_be32(&intr->ctrl);
+		val |= 0x04000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC52xx_IRQ2:
+		val = in_be32(&intr->ctrl);
+		val |= 0x02000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC52xx_IRQ3:
+		val = in_be32(&intr->ctrl);
+		val |= 0x01000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	default:
+		if (irq >= MPC52xx_SDMA_IRQ_BASE
+		    && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
+			out_be32(&sdma->IntPend,
+				 1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+		}
+
+		break;
+	}
+
+}
+
+static void mpc52xx_ic_disable_and_ack(unsigned int irq)
+{
+	mpc52xx_ic_disable(irq);
+	mpc52xx_ic_ack(irq);
+}
+
+static void mpc52xx_ic_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		mpc52xx_ic_enable(irq);
+}
+
+static struct irq_chip mpc52xx_irqchip = {
+	.name = " MPC52xx  ",
+	.enable = mpc52xx_ic_enable,
+	.disable = mpc52xx_ic_disable,
+	.ack = mpc52xx_ic_disable_and_ack,
+	.end = mpc52xx_ic_end,
+};
+
+extern struct device_node *find_mpc52xx_pic(void);
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+	pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_pic(), node);
+	return find_mpc52xx_pic() == 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)
+{
+	static unsigned char map_senses[4] = {
+		IRQ_TYPE_LEVEL_HIGH,
+		IRQ_TYPE_EDGE_FALLING,
+		IRQ_TYPE_EDGE_RISING,
+		IRQ_TYPE_LEVEL_LOW,
+	};
+
+	int intrvect_l1;
+	int intrvect_l2;
+	int intrvect_type;
+	int intrvect_linux;
+
+	pr_debug("%s:\n", __func__);
+
+	if (intsize != 3)
+		return -1;
+
+	intrvect_l1 = (int)intspec[0];
+	intrvect_l2 = (int)intspec[1];
+	intrvect_type = (int)intspec[2];
+
+	pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2,
+		 intrvect_type);
+
+	switch (intrvect_l1) {
+	case 0:		/* Critical */
+		intrvect_linux = MPC52xx_CRIT_IRQ_BASE;
+		break;
+
+	case 1:		/* Main */
+		intrvect_linux = MPC52xx_MAIN_IRQ_BASE;
+		break;
+
+	case 2:		/* Periph */
+		intrvect_linux = MPC52xx_PERP_IRQ_BASE;
+		break;
+
+	case 3:		/* Bestcomm */
+		intrvect_linux = MPC52xx_SDMA_IRQ_BASE;
+		break;
+
+	default:
+		if (printk_ratelimit())
+			printk(KERN_ERR "Wrong L1 interrupt vector (%d)\n",
+			       intrvect_l1);
+
+		return -1;
+	}
+
+	intrvect_linux += intrvect_l2;
+
+	pr_debug("return %d\n", intrvect_linux);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = map_senses[intrvect_type];
+
+	return 0;
+
+}
+
+int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+			irq_hw_number_t hw)
+{
+	pr_debug("%s: v=%d, hw=%d\n", __func__, virq, (int)hw);
+
+	return 0;
+}
+
+void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
+{
+	pr_debug("%s: v=%d\n", __func__, virq);
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+	.match = mpc52xx_irqhost_match,
+	.xlate = mpc52xx_irqhost_xlate,
+	.map = mpc52xx_irqhost_map,
+	.unmap = mpc52xx_irqhost_unmap,
+};
+
+void __init mpc52xx_init_irq(void)
+{
+	int i;
+	u32 intr_ctrl;
+
+	/* Remap the necessary zones */
+	intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+	sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
+
+	if ((intr == NULL) || (sdma == NULL))
+		panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+	/* 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);
+	/* Initialize irq_desc[i].handler's with mpc52xx_ic. */
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].chip = &mpc52xx_irqchip;
+		irq_desc[i].status = IRQ_LEVEL;
+
+	}
+
+#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
+	for (i = 0; i < 4; i++) {
+		int mode;
+		mode = IRQn_MODE(intr_ctrl, i);
+		if ((mode == 0x1) || (mode == 0x2))
+			irq_desc[i ? MPC52xx_IRQ1 + i -
+				 1 : MPC52xx_IRQ0].status = 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, NR_IRQS, &mpc52xx_irqhost_ops,
+			   -1);
+	pr_debug("%s: mpc52xx_irqhost =%p\n", __func__, mpc52xx_irqhost);
+}
+
+unsigned int mpc52xx_get_irq(void)
+{
+	u32 status;
+	int virq;
+	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_CRIT_IRQ_BASE;
+	} else if (status & 0x00200000) {	/* main */
+		irq = (status >> 16) & 0x1f;
+		if (irq == 4)	/* low priority peripheral */
+			goto peripheral;
+		irq += MPC52xx_MAIN_IRQ_BASE;
+	} else if (status & 0x20000000) {	/* peripheral */
+	      peripheral:
+		irq = (status >> 24) & 0x1f;
+		if (irq == 0) {	/* bestcomm */
+			status = in_be32(&sdma->IntPend);
+			irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE - 1;
+		} else
+			irq += MPC52xx_PERP_IRQ_BASE;
+
+	}
+
+	virq = irq_linear_revmap(mpc52xx_irqhost, irq);
+	pr_debug("%s: irq=%d -> %d\n", __func__, irq, virq);
+
+	return virq;
+}
--- a/arch/powerpc/Kconfig	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/Kconfig	2006-10-26 18:55:58.000000000 +0200
@@ -384,6 +384,11 @@ config PPC_CHRP
 	select PPC_RTAS
 	select PPC_MPC106
 	select PPC_UDBG_16550
+	select PPC_MPC52xx_PIC
+	default y
+
+config PPC_MPC52xx_PIC
+        bool
 	default y
 
 config PPC_PMAC
--- a/arch/powerpc/platforms/chrp/setup.c	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/platforms/chrp/setup.c	2006-10-26 18:56:34.000000000 +0200
@@ -51,6 +51,7 @@
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 #include <asm/xmon.h>
+#include <asm/mpc52xx.h>
 
 #include "chrp.h"
 
@@ -435,6 +436,51 @@ static struct irqaction xmon_irqaction =
 };
 #endif
 
+
+struct device_node *find_mpc52xx_pic(void)
+{
+	struct device_node *dev;
+	const char *piccompatible_list[] =
+	{
+		"mpc5200-interrupt-controller",
+		"mpc52xx-interrupt-controller",
+		"mpc52xx-pic",
+		"mpc5200-pic",
+		"5200-interrupt-controller",
+		"52xx-interrupt-controller",
+		"52xx-pic",
+		"5200-pic",
+		NULL
+	};
+
+	/* Look for an MPC52xx interrupt controller */
+	for_each_node_by_type(dev, "interrupt-controller")
+	{
+		const char **piccompatible_entry = piccompatible_list;
+
+		for(piccompatible_entry = piccompatible_list; *piccompatible_entry; piccompatible_entry++ )
+		{
+			if (device_is_compatible(dev, *piccompatible_entry ))
+				return dev;
+		}
+	}
+
+	return NULL;
+}
+
+static int  __init chrp_find_mpc52xx_pic(void)
+{
+	if (find_mpc52xx_pic())
+	{
+		printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
+		ppc_md.get_irq = mpc52xx_get_irq;
+		mpc52xx_init_irq();
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
 static void __init chrp_find_8259(void)
 {
 	struct device_node *np, *pic = NULL;
@@ -473,8 +519,11 @@ static void __init chrp_find_8259(void)
 		break;
 	}
 	if (np == NULL)
-		printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
-		       " address, polling\n");
+	{
+		printk(KERN_WARNING "Cannot find PCI/i8259 interrupt acknowledge"
+		       " Fix your tree!\n");
+		return;
+	}
 
 	i8259_init(pic, chrp_int_ack);
 	if (ppc_md.get_irq == NULL)
@@ -494,6 +543,8 @@ void __init chrp_init_IRQ(void)
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
 	struct device_node *kbd;
 #endif
+
+	chrp_find_mpc52xx_pic();
 	chrp_find_openpic();
 	chrp_find_8259();
 

[-- 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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 16:02         ` Grant Likely
  2006-10-26 16:09           ` Grant Likely
  2006-10-26 16:45           ` Sven Luther
@ 2006-10-26 19:50           ` Nicolas DET
  2006-10-26 20:00             ` Grant Likely
  2 siblings, 1 reply; 40+ messages in thread
From: Nicolas DET @ 2006-10-26 19:50 UTC (permalink / raw)
  To: Grant Likely; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

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

Grant Likely wrote:

>> +
>> +struct device_node *find_mpc52xx_pic(void)
>> +{
>> +       struct device_node *dev;
>> +       const char *piccompatible_list[] =
>> +       {
>> +               "mpc5200-interrupt-controller",
>> +               "mpc52xx-interrupt-controller",
>> +               "mpc52xx-pic",
>> +               "mpc5200-pic",
>> +               "5200-interrupt-controller",
>> +               "52xx-interrupt-controller",
>> +               "52xx-pic",
>> +               "5200-pic",
>> +               NULL
>> +       };
> 
> Considering Efika is the *only* CHRP 52xx board out there at the
> moment, and only a handful of embedded folks trying to move it to
> arch/powerpc, surely we can come to an agreement now on what this
> thing is named.  :)
>
> 

Done



[-- Attachment #2: chrpmpc52xx_2.6.19-rc3.patch --]
[-- Type: text/plain, Size: 12164 bytes --]

--- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/Makefile	2006-10-26 11:38:02.000000000 +0200
@@ -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/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-26 21:32:05.000000000 +0200
@@ -0,0 +1,363 @@
+/*
+ * arch/powerpc/sysdev/mpc52xx_pic.c
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx 
+ * embedded CPU.
+ * Modified for CHRP Efika 5K2
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ */
+
+#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 <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 void mpc52xx_ic_disable(unsigned int virq)
+{
+	u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+	if (irq == MPC52xx_IRQ0) {
+		val = in_be32(&intr->ctrl);
+		val &= ~(1 << 11);
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC52xx_IRQ1) {
+		BUG();
+	} else if (irq <= MPC52xx_IRQ3) {
+		val = in_be32(&intr->ctrl);
+		val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+		val = in_be32(&intr->main_mask);
+		val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
+		out_be32(&intr->main_mask, val);
+	} else if (irq < MPC52xx_PERP_IRQ_BASE) {
+		val = in_be32(&sdma->IntMask);
+		val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
+		out_be32(&sdma->IntMask, val);
+	} else {
+		val = in_be32(&intr->per_mask);
+		val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
+		out_be32(&intr->per_mask, val);
+	}
+}
+
+static void mpc52xx_ic_enable(unsigned int virq)
+{
+	u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+	if (irq == MPC52xx_IRQ0) {
+		val = in_be32(&intr->ctrl);
+		val |= 1 << 11;
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC52xx_IRQ1) {
+		BUG();
+	} else if (irq <= MPC52xx_IRQ3) {
+		val = in_be32(&intr->ctrl);
+		val |= 1 << (10 - (irq - MPC52xx_IRQ1));
+		out_be32(&intr->ctrl, val);
+	} else if (irq < MPC52xx_SDMA_IRQ_BASE) {
+		val = in_be32(&intr->main_mask);
+		val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
+		out_be32(&intr->main_mask, val);
+	} else if (irq < MPC52xx_PERP_IRQ_BASE) {
+		val = in_be32(&sdma->IntMask);
+		val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+		out_be32(&sdma->IntMask, val);
+	} else {
+		val = in_be32(&intr->per_mask);
+		val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
+		out_be32(&intr->per_mask, val);
+	}
+}
+
+static void mpc52xx_ic_ack(unsigned int virq)
+{
+	u32 val;
+	int irq;
+
+	irq = irq_map[virq].hwirq;
+
+	pr_debug("%s: irq=%d\n", __func__, irq);
+
+	/*
+	 * Only some irqs are reset here, others in interrupting hardware.
+	 */
+
+	switch (irq) {
+	case MPC52xx_IRQ0:
+		val = in_be32(&intr->ctrl);
+		val |= 0x08000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC52xx_CCS_IRQ:
+		val = in_be32(&intr->enc_status);
+		val |= 0x00000400;
+		out_be32(&intr->enc_status, val);
+		break;
+	case MPC52xx_IRQ1:
+		val = in_be32(&intr->ctrl);
+		val |= 0x04000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC52xx_IRQ2:
+		val = in_be32(&intr->ctrl);
+		val |= 0x02000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	case MPC52xx_IRQ3:
+		val = in_be32(&intr->ctrl);
+		val |= 0x01000000;
+		out_be32(&intr->ctrl, val);
+		break;
+	default:
+		if (irq >= MPC52xx_SDMA_IRQ_BASE
+		    && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
+			out_be32(&sdma->IntPend,
+				 1 << (irq - MPC52xx_SDMA_IRQ_BASE));
+		}
+
+		break;
+	}
+
+}
+
+static void mpc52xx_ic_disable_and_ack(unsigned int irq)
+{
+	mpc52xx_ic_disable(irq);
+	mpc52xx_ic_ack(irq);
+}
+
+static void mpc52xx_ic_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		mpc52xx_ic_enable(irq);
+}
+
+static struct irq_chip mpc52xx_irqchip = {
+	.name = " MPC52xx  ",
+	.enable = mpc52xx_ic_enable,
+	.disable = mpc52xx_ic_disable,
+	.ack = mpc52xx_ic_disable_and_ack,
+	.end = mpc52xx_ic_end,
+};
+
+extern struct device_node *find_mpc52xx_pic(void);
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+	pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_pic(), node);
+	return find_mpc52xx_pic() == 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)
+{
+	static unsigned char map_senses[4] = {
+		IRQ_TYPE_LEVEL_HIGH,
+		IRQ_TYPE_EDGE_FALLING,
+		IRQ_TYPE_EDGE_RISING,
+		IRQ_TYPE_LEVEL_LOW,
+	};
+
+	int intrvect_l1;
+	int intrvect_l2;
+	int intrvect_type;
+	int intrvect_linux;
+
+	pr_debug("%s:\n", __func__);
+
+	if (intsize != 3)
+		return -1;
+
+	intrvect_l1 = (int)intspec[0];
+	intrvect_l2 = (int)intspec[1];
+	intrvect_type = (int)intspec[2];
+
+	pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2,
+		 intrvect_type);
+
+	switch (intrvect_l1) {
+	case 0:		/* Critical */
+		intrvect_linux = MPC52xx_CRIT_IRQ_BASE;
+		break;
+
+	case 1:		/* Main */
+		intrvect_linux = MPC52xx_MAIN_IRQ_BASE;
+		break;
+
+	case 2:		/* Periph */
+		intrvect_linux = MPC52xx_PERP_IRQ_BASE;
+		break;
+
+	case 3:		/* Bestcomm */
+		intrvect_linux = MPC52xx_SDMA_IRQ_BASE;
+		break;
+
+	default:
+		if (printk_ratelimit())
+			printk(KERN_ERR "Wrong L1 interrupt vector (%d)\n",
+			       intrvect_l1);
+
+		return -1;
+	}
+
+	intrvect_linux += intrvect_l2;
+
+	pr_debug("return %d\n", intrvect_linux);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = map_senses[intrvect_type];
+
+	return 0;
+
+}
+
+int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+			irq_hw_number_t hw)
+{
+	pr_debug("%s: v=%d, hw=%d\n", __func__, virq, (int)hw);
+
+	return 0;
+}
+
+void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
+{
+	pr_debug("%s: v=%d\n", __func__, virq);
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+	.match = mpc52xx_irqhost_match,
+	.xlate = mpc52xx_irqhost_xlate,
+	.map = mpc52xx_irqhost_map,
+	.unmap = mpc52xx_irqhost_unmap,
+};
+
+void __init mpc52xx_init_irq(void)
+{
+	int i;
+	u32 intr_ctrl;
+
+	/* Remap the necessary zones */
+	intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+	sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
+
+	if ((intr == NULL) || (sdma == NULL))
+		panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+	/* 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);
+	/* Initialize irq_desc[i].handler's with mpc52xx_ic. */
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].chip = &mpc52xx_irqchip;
+		irq_desc[i].status = IRQ_LEVEL;
+
+	}
+
+#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
+	for (i = 0; i < 4; i++) {
+		int mode;
+		mode = IRQn_MODE(intr_ctrl, i);
+		if ((mode == 0x1) || (mode == 0x2))
+			irq_desc[i ? MPC52xx_IRQ1 + i -
+				 1 : MPC52xx_IRQ0].status = 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, NR_IRQS, &mpc52xx_irqhost_ops,
+			   -1);
+	pr_debug("%s: mpc52xx_irqhost =%p\n", __func__, mpc52xx_irqhost);
+}
+
+unsigned int mpc52xx_get_irq(void)
+{
+	u32 status;
+	int virq;
+	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_CRIT_IRQ_BASE;
+	} else if (status & 0x00200000) {	/* main */
+		irq = (status >> 16) & 0x1f;
+		if (irq == 4)	/* low priority peripheral */
+			goto peripheral;
+		irq += MPC52xx_MAIN_IRQ_BASE;
+	} else if (status & 0x20000000) {	/* peripheral */
+	      peripheral:
+		irq = (status >> 24) & 0x1f;
+		if (irq == 0) {	/* bestcomm */
+			status = in_be32(&sdma->IntPend);
+			irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE - 1;
+		} else
+			irq += MPC52xx_PERP_IRQ_BASE;
+
+	}
+
+	virq = irq_linear_revmap(mpc52xx_irqhost, irq);
+	pr_debug("%s: irq=%d -> %d\n", __func__, irq, virq);
+
+	return virq;
+}
--- a/arch/powerpc/Kconfig	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/Kconfig	2006-10-26 18:55:58.000000000 +0200
@@ -384,6 +384,11 @@ config PPC_CHRP
 	select PPC_RTAS
 	select PPC_MPC106
 	select PPC_UDBG_16550
+	select PPC_MPC52xx_PIC
+	default y
+
+config PPC_MPC52xx_PIC
+        bool
 	default y
 
 config PPC_PMAC
--- a/arch/powerpc/platforms/chrp/setup.c	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/platforms/chrp/setup.c	2006-10-26 21:47:29.000000000 +0200
@@ -51,6 +51,7 @@
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 #include <asm/xmon.h>
+#include <asm/mpc52xx.h>
 
 #include "chrp.h"
 
@@ -435,6 +436,44 @@ static struct irqaction xmon_irqaction =
 };
 #endif
 
+
+struct device_node *find_mpc52xx_pic(void)
+{
+	struct device_node *dev;
+	const char *piccompatible_list[] =
+	{
+		"mpc5200-pic",
+		NULL
+	};
+
+	/* Look for an MPC52xx interrupt controller */
+	for_each_node_by_type(dev, "interrupt-controller")
+	{
+		const char **piccompatible_entry = piccompatible_list;
+
+		for(piccompatible_entry = piccompatible_list; *piccompatible_entry; piccompatible_entry++ )
+		{
+			if (device_is_compatible(dev, *piccompatible_entry ))
+				return dev;
+		}
+	}
+
+	return NULL;
+}
+
+static int  __init chrp_find_mpc52xx_pic(void)
+{
+	if (find_mpc52xx_pic())
+	{
+		printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
+		ppc_md.get_irq = mpc52xx_get_irq;
+		mpc52xx_init_irq();
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
 static void __init chrp_find_8259(void)
 {
 	struct device_node *np, *pic = NULL;
@@ -473,8 +512,11 @@ static void __init chrp_find_8259(void)
 		break;
 	}
 	if (np == NULL)
-		printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
-		       " address, polling\n");
+	{
+		printk(KERN_WARNING "Cannot find PCI/i8259 interrupt acknowledge"
+		       " Fix your tree!\n");
+		return;
+	}
 
 	i8259_init(pic, chrp_int_ack);
 	if (ppc_md.get_irq == NULL)
@@ -494,6 +536,8 @@ void __init chrp_init_IRQ(void)
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
 	struct device_node *kbd;
 #endif
+
+	chrp_find_mpc52xx_pic();
 	chrp_find_openpic();
 	chrp_find_8259();
 

[-- 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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 19:50           ` Nicolas DET
@ 2006-10-26 20:00             ` Grant Likely
  2006-10-26 20:51               ` Sylvain Munaut
  2006-10-27  3:28               ` Benjamin Herrenschmidt
  0 siblings, 2 replies; 40+ messages in thread
From: Grant Likely @ 2006-10-26 20:00 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

My comments are satisfied

Acked-by: Grant Likely <grant.likely@secretlab.ca>

On 10/26/06, Nicolas DET <nd@bplan-gmbh.de> wrote:
> Grant Likely wrote:
>
> >> +
> >> +struct device_node *find_mpc52xx_pic(void)
> >> +{
> >> +       struct device_node *dev;
> >> +       const char *piccompatible_list[] =
> >> +       {
> >> +               "mpc5200-interrupt-controller",
> >> +               "mpc52xx-interrupt-controller",
> >> +               "mpc52xx-pic",
> >> +               "mpc5200-pic",
> >> +               "5200-interrupt-controller",
> >> +               "52xx-interrupt-controller",
> >> +               "52xx-pic",
> >> +               "5200-pic",
> >> +               NULL
> >> +       };
> >
> > Considering Efika is the *only* CHRP 52xx board out there at the
> > moment, and only a handful of embedded folks trying to move it to
> > arch/powerpc, surely we can come to an agreement now on what this
> > thing is named.  :)
> >
> >
>
> Done
>
>
>
>
> --- a/arch/powerpc/sysdev/Makefile      2006-10-25 19:07:24.000000000 +0200
> +++ b/arch/powerpc/sysdev/Makefile      2006-10-26 11:38:02.000000000 +0200
> @@ -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/arch/powerpc/sysdev/mpc52xx_pic.c 1970-01-01 01:00:00.000000000 +0100
> +++ b/arch/powerpc/sysdev/mpc52xx_pic.c 2006-10-26 21:32:05.000000000 +0200
> @@ -0,0 +1,363 @@
> +/*
> + * arch/powerpc/sysdev/mpc52xx_pic.c
> + *
> + * Programmable Interrupt Controller functions for the Freescale MPC52xx
> + * embedded CPU.
> + * Modified for CHRP Efika 5K2
> + *
> + * Maintainer : Sylvain Munaut <tnt@246tNt.com>
> + *
> + * 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.
> + */
> +
> +#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 <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 void mpc52xx_ic_disable(unsigned int virq)
> +{
> +       u32 val;
> +       int irq;
> +
> +       irq = irq_map[virq].hwirq;
> +
> +       pr_debug("%s: irq=%d\n", __func__, irq);
> +
> +       if (irq == MPC52xx_IRQ0) {
> +               val = in_be32(&intr->ctrl);
> +               val &= ~(1 << 11);
> +               out_be32(&intr->ctrl, val);
> +       } else if (irq < MPC52xx_IRQ1) {
> +               BUG();
> +       } else if (irq <= MPC52xx_IRQ3) {
> +               val = in_be32(&intr->ctrl);
> +               val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
> +               out_be32(&intr->ctrl, val);
> +       } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
> +               val = in_be32(&intr->main_mask);
> +               val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
> +               out_be32(&intr->main_mask, val);
> +       } else if (irq < MPC52xx_PERP_IRQ_BASE) {
> +               val = in_be32(&sdma->IntMask);
> +               val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
> +               out_be32(&sdma->IntMask, val);
> +       } else {
> +               val = in_be32(&intr->per_mask);
> +               val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
> +               out_be32(&intr->per_mask, val);
> +       }
> +}
> +
> +static void mpc52xx_ic_enable(unsigned int virq)
> +{
> +       u32 val;
> +       int irq;
> +
> +       irq = irq_map[virq].hwirq;
> +
> +       pr_debug("%s: irq=%d\n", __func__, irq);
> +
> +       if (irq == MPC52xx_IRQ0) {
> +               val = in_be32(&intr->ctrl);
> +               val |= 1 << 11;
> +               out_be32(&intr->ctrl, val);
> +       } else if (irq < MPC52xx_IRQ1) {
> +               BUG();
> +       } else if (irq <= MPC52xx_IRQ3) {
> +               val = in_be32(&intr->ctrl);
> +               val |= 1 << (10 - (irq - MPC52xx_IRQ1));
> +               out_be32(&intr->ctrl, val);
> +       } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
> +               val = in_be32(&intr->main_mask);
> +               val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
> +               out_be32(&intr->main_mask, val);
> +       } else if (irq < MPC52xx_PERP_IRQ_BASE) {
> +               val = in_be32(&sdma->IntMask);
> +               val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
> +               out_be32(&sdma->IntMask, val);
> +       } else {
> +               val = in_be32(&intr->per_mask);
> +               val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
> +               out_be32(&intr->per_mask, val);
> +       }
> +}
> +
> +static void mpc52xx_ic_ack(unsigned int virq)
> +{
> +       u32 val;
> +       int irq;
> +
> +       irq = irq_map[virq].hwirq;
> +
> +       pr_debug("%s: irq=%d\n", __func__, irq);
> +
> +       /*
> +        * Only some irqs are reset here, others in interrupting hardware.
> +        */
> +
> +       switch (irq) {
> +       case MPC52xx_IRQ0:
> +               val = in_be32(&intr->ctrl);
> +               val |= 0x08000000;
> +               out_be32(&intr->ctrl, val);
> +               break;
> +       case MPC52xx_CCS_IRQ:
> +               val = in_be32(&intr->enc_status);
> +               val |= 0x00000400;
> +               out_be32(&intr->enc_status, val);
> +               break;
> +       case MPC52xx_IRQ1:
> +               val = in_be32(&intr->ctrl);
> +               val |= 0x04000000;
> +               out_be32(&intr->ctrl, val);
> +               break;
> +       case MPC52xx_IRQ2:
> +               val = in_be32(&intr->ctrl);
> +               val |= 0x02000000;
> +               out_be32(&intr->ctrl, val);
> +               break;
> +       case MPC52xx_IRQ3:
> +               val = in_be32(&intr->ctrl);
> +               val |= 0x01000000;
> +               out_be32(&intr->ctrl, val);
> +               break;
> +       default:
> +               if (irq >= MPC52xx_SDMA_IRQ_BASE
> +                   && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
> +                       out_be32(&sdma->IntPend,
> +                                1 << (irq - MPC52xx_SDMA_IRQ_BASE));
> +               }
> +
> +               break;
> +       }
> +
> +}
> +
> +static void mpc52xx_ic_disable_and_ack(unsigned int irq)
> +{
> +       mpc52xx_ic_disable(irq);
> +       mpc52xx_ic_ack(irq);
> +}
> +
> +static void mpc52xx_ic_end(unsigned int irq)
> +{
> +       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
> +               mpc52xx_ic_enable(irq);
> +}
> +
> +static struct irq_chip mpc52xx_irqchip = {
> +       .name = " MPC52xx  ",
> +       .enable = mpc52xx_ic_enable,
> +       .disable = mpc52xx_ic_disable,
> +       .ack = mpc52xx_ic_disable_and_ack,
> +       .end = mpc52xx_ic_end,
> +};
> +
> +extern struct device_node *find_mpc52xx_pic(void);
> +static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
> +{
> +       pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_pic(), node);
> +       return find_mpc52xx_pic() == 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)
> +{
> +       static unsigned char map_senses[4] = {
> +               IRQ_TYPE_LEVEL_HIGH,
> +               IRQ_TYPE_EDGE_FALLING,
> +               IRQ_TYPE_EDGE_RISING,
> +               IRQ_TYPE_LEVEL_LOW,
> +       };
> +
> +       int intrvect_l1;
> +       int intrvect_l2;
> +       int intrvect_type;
> +       int intrvect_linux;
> +
> +       pr_debug("%s:\n", __func__);
> +
> +       if (intsize != 3)
> +               return -1;
> +
> +       intrvect_l1 = (int)intspec[0];
> +       intrvect_l2 = (int)intspec[1];
> +       intrvect_type = (int)intspec[2];
> +
> +       pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2,
> +                intrvect_type);
> +
> +       switch (intrvect_l1) {
> +       case 0:         /* Critical */
> +               intrvect_linux = MPC52xx_CRIT_IRQ_BASE;
> +               break;
> +
> +       case 1:         /* Main */
> +               intrvect_linux = MPC52xx_MAIN_IRQ_BASE;
> +               break;
> +
> +       case 2:         /* Periph */
> +               intrvect_linux = MPC52xx_PERP_IRQ_BASE;
> +               break;
> +
> +       case 3:         /* Bestcomm */
> +               intrvect_linux = MPC52xx_SDMA_IRQ_BASE;
> +               break;
> +
> +       default:
> +               if (printk_ratelimit())
> +                       printk(KERN_ERR "Wrong L1 interrupt vector (%d)\n",
> +                              intrvect_l1);
> +
> +               return -1;
> +       }
> +
> +       intrvect_linux += intrvect_l2;
> +
> +       pr_debug("return %d\n", intrvect_linux);
> +
> +       *out_hwirq = intrvect_linux;
> +       *out_flags = map_senses[intrvect_type];
> +
> +       return 0;
> +
> +}
> +
> +int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
> +                       irq_hw_number_t hw)
> +{
> +       pr_debug("%s: v=%d, hw=%d\n", __func__, virq, (int)hw);
> +
> +       return 0;
> +}
> +
> +void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
> +{
> +       pr_debug("%s: v=%d\n", __func__, virq);
> +}
> +
> +static struct irq_host_ops mpc52xx_irqhost_ops = {
> +       .match = mpc52xx_irqhost_match,
> +       .xlate = mpc52xx_irqhost_xlate,
> +       .map = mpc52xx_irqhost_map,
> +       .unmap = mpc52xx_irqhost_unmap,
> +};
> +
> +void __init mpc52xx_init_irq(void)
> +{
> +       int i;
> +       u32 intr_ctrl;
> +
> +       /* Remap the necessary zones */
> +       intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
> +       sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
> +
> +       if ((intr == NULL) || (sdma == NULL))
> +               panic("Can't ioremap PIC/SDMA register or init_irq !");
> +
> +       /* 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);
> +       /* Initialize irq_desc[i].handler's with mpc52xx_ic. */
> +       for (i = 0; i < NR_IRQS; i++) {
> +               irq_desc[i].chip = &mpc52xx_irqchip;
> +               irq_desc[i].status = IRQ_LEVEL;
> +
> +       }
> +
> +#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
> +       for (i = 0; i < 4; i++) {
> +               int mode;
> +               mode = IRQn_MODE(intr_ctrl, i);
> +               if ((mode == 0x1) || (mode == 0x2))
> +                       irq_desc[i ? MPC52xx_IRQ1 + i -
> +                                1 : MPC52xx_IRQ0].status = 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, NR_IRQS, &mpc52xx_irqhost_ops,
> +                          -1);
> +       pr_debug("%s: mpc52xx_irqhost =%p\n", __func__, mpc52xx_irqhost);
> +}
> +
> +unsigned int mpc52xx_get_irq(void)
> +{
> +       u32 status;
> +       int virq;
> +       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_CRIT_IRQ_BASE;
> +       } else if (status & 0x00200000) {       /* main */
> +               irq = (status >> 16) & 0x1f;
> +               if (irq == 4)   /* low priority peripheral */
> +                       goto peripheral;
> +               irq += MPC52xx_MAIN_IRQ_BASE;
> +       } else if (status & 0x20000000) {       /* peripheral */
> +             peripheral:
> +               irq = (status >> 24) & 0x1f;
> +               if (irq == 0) { /* bestcomm */
> +                       status = in_be32(&sdma->IntPend);
> +                       irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE - 1;
> +               } else
> +                       irq += MPC52xx_PERP_IRQ_BASE;
> +
> +       }
> +
> +       virq = irq_linear_revmap(mpc52xx_irqhost, irq);
> +       pr_debug("%s: irq=%d -> %d\n", __func__, irq, virq);
> +
> +       return virq;
> +}
> --- a/arch/powerpc/Kconfig      2006-10-25 19:07:23.000000000 +0200
> +++ b/arch/powerpc/Kconfig      2006-10-26 18:55:58.000000000 +0200
> @@ -384,6 +384,11 @@ config PPC_CHRP
>         select PPC_RTAS
>         select PPC_MPC106
>         select PPC_UDBG_16550
> +       select PPC_MPC52xx_PIC
> +       default y
> +
> +config PPC_MPC52xx_PIC
> +        bool
>         default y
>
>  config PPC_PMAC
> --- a/arch/powerpc/platforms/chrp/setup.c       2006-10-25 19:07:23.000000000 +0200
> +++ b/arch/powerpc/platforms/chrp/setup.c       2006-10-26 21:47:29.000000000 +0200
> @@ -51,6 +51,7 @@
>  #include <asm/mpic.h>
>  #include <asm/rtas.h>
>  #include <asm/xmon.h>
> +#include <asm/mpc52xx.h>
>
>  #include "chrp.h"
>
> @@ -435,6 +436,44 @@ static struct irqaction xmon_irqaction =
>  };
>  #endif
>
> +
> +struct device_node *find_mpc52xx_pic(void)
> +{
> +       struct device_node *dev;
> +       const char *piccompatible_list[] =
> +       {
> +               "mpc5200-pic",
> +               NULL
> +       };
> +
> +       /* Look for an MPC52xx interrupt controller */
> +       for_each_node_by_type(dev, "interrupt-controller")
> +       {
> +               const char **piccompatible_entry = piccompatible_list;
> +
> +               for(piccompatible_entry = piccompatible_list; *piccompatible_entry; piccompatible_entry++ )
> +               {
> +                       if (device_is_compatible(dev, *piccompatible_entry ))
> +                               return dev;
> +               }
> +       }
> +
> +       return NULL;
> +}
> +
> +static int  __init chrp_find_mpc52xx_pic(void)
> +{
> +       if (find_mpc52xx_pic())
> +       {
> +               printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
> +               ppc_md.get_irq = mpc52xx_get_irq;
> +               mpc52xx_init_irq();
> +               return 0;
> +       }
> +
> +       return -ENODEV;
> +}
> +
>  static void __init chrp_find_8259(void)
>  {
>         struct device_node *np, *pic = NULL;
> @@ -473,8 +512,11 @@ static void __init chrp_find_8259(void)
>                 break;
>         }
>         if (np == NULL)
> -               printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
> -                      " address, polling\n");
> +       {
> +               printk(KERN_WARNING "Cannot find PCI/i8259 interrupt acknowledge"
> +                      " Fix your tree!\n");
> +               return;
> +       }
>
>         i8259_init(pic, chrp_int_ack);
>         if (ppc_md.get_irq == NULL)
> @@ -494,6 +536,8 @@ void __init chrp_init_IRQ(void)
>  #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
>         struct device_node *kbd;
>  #endif
> +
> +       chrp_find_mpc52xx_pic();
>         chrp_find_openpic();
>         chrp_find_8259();
>
>
>
>
>


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

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 20:00             ` Grant Likely
@ 2006-10-26 20:51               ` Sylvain Munaut
  2006-10-27  3:28               ` Benjamin Herrenschmidt
  1 sibling, 0 replies; 40+ messages in thread
From: Sylvain Munaut @ 2006-10-26 20:51 UTC (permalink / raw)
  To: Grant Likely; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

FWIW, Looks good to me too.

Acked-by: Sylvain Munaut <tnt@246tNt.com>


It will need some changes when we'll get rid of the need to stay compatible
with arch/ppc. This will hopefully be soon and getting this in should help
get things moving imho.


       Sylvain



Grant Likely wrote:
> My comments are satisfied
>
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
>
> On 10/26/06, Nicolas DET <nd@bplan-gmbh.de> wrote:
>> Grant Likely wrote:
>>
>> >> +
>> >> +struct device_node *find_mpc52xx_pic(void)
>> >> +{
>> >> +       struct device_node *dev;
>> >> +       const char *piccompatible_list[] =
>> >> +       {
>> >> +               "mpc5200-interrupt-controller",
>> >> +               "mpc52xx-interrupt-controller",
>> >> +               "mpc52xx-pic",
>> >> +               "mpc5200-pic",
>> >> +               "5200-interrupt-controller",
>> >> +               "52xx-interrupt-controller",
>> >> +               "52xx-pic",
>> >> +               "5200-pic",
>> >> +               NULL
>> >> +       };
>> >
>> > Considering Efika is the *only* CHRP 52xx board out there at the
>> > moment, and only a handful of embedded folks trying to move it to
>> > arch/powerpc, surely we can come to an agreement now on what this
>> > thing is named.  :)
>> >
>> >
>>
>> Done
>>
>>
>>
>>
>> --- a/arch/powerpc/sysdev/Makefile      2006-10-25 19:07:24.000000000
>> +0200
>> +++ b/arch/powerpc/sysdev/Makefile      2006-10-26 11:38:02.000000000
>> +0200
>> @@ -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/arch/powerpc/sysdev/mpc52xx_pic.c 1970-01-01 01:00:00.000000000
>> +0100
>> +++ b/arch/powerpc/sysdev/mpc52xx_pic.c 2006-10-26 21:32:05.000000000
>> +0200
>> @@ -0,0 +1,363 @@
>> +/*
>> + * arch/powerpc/sysdev/mpc52xx_pic.c
>> + *
>> + * Programmable Interrupt Controller functions for the Freescale
>> MPC52xx
>> + * embedded CPU.
>> + * Modified for CHRP Efika 5K2
>> + *
>> + * Maintainer : Sylvain Munaut <tnt@246tNt.com>
>> + *
>> + * 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.
>> + */
>> +
>> +#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 <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 void mpc52xx_ic_disable(unsigned int virq)
>> +{
>> +       u32 val;
>> +       int irq;
>> +
>> +       irq = irq_map[virq].hwirq;
>> +
>> +       pr_debug("%s: irq=%d\n", __func__, irq);
>> +
>> +       if (irq == MPC52xx_IRQ0) {
>> +               val = in_be32(&intr->ctrl);
>> +               val &= ~(1 << 11);
>> +               out_be32(&intr->ctrl, val);
>> +       } else if (irq < MPC52xx_IRQ1) {
>> +               BUG();
>> +       } else if (irq <= MPC52xx_IRQ3) {
>> +               val = in_be32(&intr->ctrl);
>> +               val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
>> +               out_be32(&intr->ctrl, val);
>> +       } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
>> +               val = in_be32(&intr->main_mask);
>> +               val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
>> +               out_be32(&intr->main_mask, val);
>> +       } else if (irq < MPC52xx_PERP_IRQ_BASE) {
>> +               val = in_be32(&sdma->IntMask);
>> +               val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
>> +               out_be32(&sdma->IntMask, val);
>> +       } else {
>> +               val = in_be32(&intr->per_mask);
>> +               val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
>> +               out_be32(&intr->per_mask, val);
>> +       }
>> +}
>> +
>> +static void mpc52xx_ic_enable(unsigned int virq)
>> +{
>> +       u32 val;
>> +       int irq;
>> +
>> +       irq = irq_map[virq].hwirq;
>> +
>> +       pr_debug("%s: irq=%d\n", __func__, irq);
>> +
>> +       if (irq == MPC52xx_IRQ0) {
>> +               val = in_be32(&intr->ctrl);
>> +               val |= 1 << 11;
>> +               out_be32(&intr->ctrl, val);
>> +       } else if (irq < MPC52xx_IRQ1) {
>> +               BUG();
>> +       } else if (irq <= MPC52xx_IRQ3) {
>> +               val = in_be32(&intr->ctrl);
>> +               val |= 1 << (10 - (irq - MPC52xx_IRQ1));
>> +               out_be32(&intr->ctrl, val);
>> +       } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
>> +               val = in_be32(&intr->main_mask);
>> +               val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
>> +               out_be32(&intr->main_mask, val);
>> +       } else if (irq < MPC52xx_PERP_IRQ_BASE) {
>> +               val = in_be32(&sdma->IntMask);
>> +               val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
>> +               out_be32(&sdma->IntMask, val);
>> +       } else {
>> +               val = in_be32(&intr->per_mask);
>> +               val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
>> +               out_be32(&intr->per_mask, val);
>> +       }
>> +}
>> +
>> +static void mpc52xx_ic_ack(unsigned int virq)
>> +{
>> +       u32 val;
>> +       int irq;
>> +
>> +       irq = irq_map[virq].hwirq;
>> +
>> +       pr_debug("%s: irq=%d\n", __func__, irq);
>> +
>> +       /*
>> +        * Only some irqs are reset here, others in interrupting
>> hardware.
>> +        */
>> +
>> +       switch (irq) {
>> +       case MPC52xx_IRQ0:
>> +               val = in_be32(&intr->ctrl);
>> +               val |= 0x08000000;
>> +               out_be32(&intr->ctrl, val);
>> +               break;
>> +       case MPC52xx_CCS_IRQ:
>> +               val = in_be32(&intr->enc_status);
>> +               val |= 0x00000400;
>> +               out_be32(&intr->enc_status, val);
>> +               break;
>> +       case MPC52xx_IRQ1:
>> +               val = in_be32(&intr->ctrl);
>> +               val |= 0x04000000;
>> +               out_be32(&intr->ctrl, val);
>> +               break;
>> +       case MPC52xx_IRQ2:
>> +               val = in_be32(&intr->ctrl);
>> +               val |= 0x02000000;
>> +               out_be32(&intr->ctrl, val);
>> +               break;
>> +       case MPC52xx_IRQ3:
>> +               val = in_be32(&intr->ctrl);
>> +               val |= 0x01000000;
>> +               out_be32(&intr->ctrl, val);
>> +               break;
>> +       default:
>> +               if (irq >= MPC52xx_SDMA_IRQ_BASE
>> +                   && irq < (MPC52xx_SDMA_IRQ_BASE +
>> MPC52xx_SDMA_IRQ_NUM)) {
>> +                       out_be32(&sdma->IntPend,
>> +                                1 << (irq - MPC52xx_SDMA_IRQ_BASE));
>> +               }
>> +
>> +               break;
>> +       }
>> +
>> +}
>> +
>> +static void mpc52xx_ic_disable_and_ack(unsigned int irq)
>> +{
>> +       mpc52xx_ic_disable(irq);
>> +       mpc52xx_ic_ack(irq);
>> +}
>> +
>> +static void mpc52xx_ic_end(unsigned int irq)
>> +{
>> +       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
>> +               mpc52xx_ic_enable(irq);
>> +}
>> +
>> +static struct irq_chip mpc52xx_irqchip = {
>> +       .name = " MPC52xx  ",
>> +       .enable = mpc52xx_ic_enable,
>> +       .disable = mpc52xx_ic_disable,
>> +       .ack = mpc52xx_ic_disable_and_ack,
>> +       .end = mpc52xx_ic_end,
>> +};
>> +
>> +extern struct device_node *find_mpc52xx_pic(void);
>> +static int mpc52xx_irqhost_match(struct irq_host *h, struct
>> device_node *node)
>> +{
>> +       pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_pic(), node);
>> +       return find_mpc52xx_pic() == 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)
>> +{
>> +       static unsigned char map_senses[4] = {
>> +               IRQ_TYPE_LEVEL_HIGH,
>> +               IRQ_TYPE_EDGE_FALLING,
>> +               IRQ_TYPE_EDGE_RISING,
>> +               IRQ_TYPE_LEVEL_LOW,
>> +       };
>> +
>> +       int intrvect_l1;
>> +       int intrvect_l2;
>> +       int intrvect_type;
>> +       int intrvect_linux;
>> +
>> +       pr_debug("%s:\n", __func__);
>> +
>> +       if (intsize != 3)
>> +               return -1;
>> +
>> +       intrvect_l1 = (int)intspec[0];
>> +       intrvect_l2 = (int)intspec[1];
>> +       intrvect_type = (int)intspec[2];
>> +
>> +       pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2,
>> +                intrvect_type);
>> +
>> +       switch (intrvect_l1) {
>> +       case 0:         /* Critical */
>> +               intrvect_linux = MPC52xx_CRIT_IRQ_BASE;
>> +               break;
>> +
>> +       case 1:         /* Main */
>> +               intrvect_linux = MPC52xx_MAIN_IRQ_BASE;
>> +               break;
>> +
>> +       case 2:         /* Periph */
>> +               intrvect_linux = MPC52xx_PERP_IRQ_BASE;
>> +               break;
>> +
>> +       case 3:         /* Bestcomm */
>> +               intrvect_linux = MPC52xx_SDMA_IRQ_BASE;
>> +               break;
>> +
>> +       default:
>> +               if (printk_ratelimit())
>> +                       printk(KERN_ERR "Wrong L1 interrupt vector
>> (%d)\n",
>> +                              intrvect_l1);
>> +
>> +               return -1;
>> +       }
>> +
>> +       intrvect_linux += intrvect_l2;
>> +
>> +       pr_debug("return %d\n", intrvect_linux);
>> +
>> +       *out_hwirq = intrvect_linux;
>> +       *out_flags = map_senses[intrvect_type];
>> +
>> +       return 0;
>> +
>> +}
>> +
>> +int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
>> +                       irq_hw_number_t hw)
>> +{
>> +       pr_debug("%s: v=%d, hw=%d\n", __func__, virq, (int)hw);
>> +
>> +       return 0;
>> +}
>> +
>> +void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
>> +{
>> +       pr_debug("%s: v=%d\n", __func__, virq);
>> +}
>> +
>> +static struct irq_host_ops mpc52xx_irqhost_ops = {
>> +       .match = mpc52xx_irqhost_match,
>> +       .xlate = mpc52xx_irqhost_xlate,
>> +       .map = mpc52xx_irqhost_map,
>> +       .unmap = mpc52xx_irqhost_unmap,
>> +};
>> +
>> +void __init mpc52xx_init_irq(void)
>> +{
>> +       int i;
>> +       u32 intr_ctrl;
>> +
>> +       /* Remap the necessary zones */
>> +       intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET),
>> MPC52xx_INTR_SIZE);
>> +       sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET),
>> MPC52xx_SDMA_SIZE);
>> +
>> +       if ((intr == NULL) || (sdma == NULL))
>> +               panic("Can't ioremap PIC/SDMA register or init_irq !");
>> +
>> +       /* 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);
>> +       /* Initialize irq_desc[i].handler's with mpc52xx_ic. */
>> +       for (i = 0; i < NR_IRQS; i++) {
>> +               irq_desc[i].chip = &mpc52xx_irqchip;
>> +               irq_desc[i].status = IRQ_LEVEL;
>> +
>> +       }
>> +
>> +#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
>> +       for (i = 0; i < 4; i++) {
>> +               int mode;
>> +               mode = IRQn_MODE(intr_ctrl, i);
>> +               if ((mode == 0x1) || (mode == 0x2))
>> +                       irq_desc[i ? MPC52xx_IRQ1 + i -
>> +                                1 : MPC52xx_IRQ0].status = 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, NR_IRQS,
>> &mpc52xx_irqhost_ops,
>> +                          -1);
>> +       pr_debug("%s: mpc52xx_irqhost =%p\n", __func__,
>> mpc52xx_irqhost);
>> +}
>> +
>> +unsigned int mpc52xx_get_irq(void)
>> +{
>> +       u32 status;
>> +       int virq;
>> +       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_CRIT_IRQ_BASE;
>> +       } else if (status & 0x00200000) {       /* main */
>> +               irq = (status >> 16) & 0x1f;
>> +               if (irq == 4)   /* low priority peripheral */
>> +                       goto peripheral;
>> +               irq += MPC52xx_MAIN_IRQ_BASE;
>> +       } else if (status & 0x20000000) {       /* peripheral */
>> +             peripheral:
>> +               irq = (status >> 24) & 0x1f;
>> +               if (irq == 0) { /* bestcomm */
>> +                       status = in_be32(&sdma->IntPend);
>> +                       irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE - 1;
>> +               } else
>> +                       irq += MPC52xx_PERP_IRQ_BASE;
>> +
>> +       }
>> +
>> +       virq = irq_linear_revmap(mpc52xx_irqhost, irq);
>> +       pr_debug("%s: irq=%d -> %d\n", __func__, irq, virq);
>> +
>> +       return virq;
>> +}
>> --- a/arch/powerpc/Kconfig      2006-10-25 19:07:23.000000000 +0200
>> +++ b/arch/powerpc/Kconfig      2006-10-26 18:55:58.000000000 +0200
>> @@ -384,6 +384,11 @@ config PPC_CHRP
>>         select PPC_RTAS
>>         select PPC_MPC106
>>         select PPC_UDBG_16550
>> +       select PPC_MPC52xx_PIC
>> +       default y
>> +
>> +config PPC_MPC52xx_PIC
>> +        bool
>>         default y
>>
>>  config PPC_PMAC
>> --- a/arch/powerpc/platforms/chrp/setup.c       2006-10-25
>> 19:07:23.000000000 +0200
>> +++ b/arch/powerpc/platforms/chrp/setup.c       2006-10-26
>> 21:47:29.000000000 +0200
>> @@ -51,6 +51,7 @@
>>  #include <asm/mpic.h>
>>  #include <asm/rtas.h>
>>  #include <asm/xmon.h>
>> +#include <asm/mpc52xx.h>
>>
>>  #include "chrp.h"
>>
>> @@ -435,6 +436,44 @@ static struct irqaction xmon_irqaction =
>>  };
>>  #endif
>>
>> +
>> +struct device_node *find_mpc52xx_pic(void)
>> +{
>> +       struct device_node *dev;
>> +       const char *piccompatible_list[] =
>> +       {
>> +               "mpc5200-pic",
>> +               NULL
>> +       };
>> +
>> +       /* Look for an MPC52xx interrupt controller */
>> +       for_each_node_by_type(dev, "interrupt-controller")
>> +       {
>> +               const char **piccompatible_entry = piccompatible_list;
>> +
>> +               for(piccompatible_entry = piccompatible_list;
>> *piccompatible_entry; piccompatible_entry++ )
>> +               {
>> +                       if (device_is_compatible(dev,
>> *piccompatible_entry ))
>> +                               return dev;
>> +               }
>> +       }
>> +
>> +       return NULL;
>> +}
>> +
>> +static int  __init chrp_find_mpc52xx_pic(void)
>> +{
>> +       if (find_mpc52xx_pic())
>> +       {
>> +               printk(KERN_INFO "Found MPC52xx Interrupt
>> Controller\n");
>> +               ppc_md.get_irq = mpc52xx_get_irq;
>> +               mpc52xx_init_irq();
>> +               return 0;
>> +       }
>> +
>> +       return -ENODEV;
>> +}
>> +
>>  static void __init chrp_find_8259(void)
>>  {
>>         struct device_node *np, *pic = NULL;
>> @@ -473,8 +512,11 @@ static void __init chrp_find_8259(void)
>>                 break;
>>         }
>>         if (np == NULL)
>> -               printk(KERN_WARNING "Cannot find PCI interrupt
>> acknowledge"
>> -                      " address, polling\n");
>> +       {
>> +               printk(KERN_WARNING "Cannot find PCI/i8259 interrupt
>> acknowledge"
>> +                      " Fix your tree!\n");
>> +               return;
>> +       }
>>
>>         i8259_init(pic, chrp_int_ack);
>>         if (ppc_md.get_irq == NULL)
>> @@ -494,6 +536,8 @@ void __init chrp_init_IRQ(void)
>>  #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
>>         struct device_node *kbd;
>>  #endif
>> +
>> +       chrp_find_mpc52xx_pic();
>>         chrp_find_openpic();
>>         chrp_find_8259();
>>
>>
>>
>>
>>
>
>

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 17:06             ` Nicolas DET
  2006-10-26 17:54               ` Sylvain Munaut
  2006-10-26 19:14               ` Grant Likely
@ 2006-10-27  2:49               ` Benjamin Herrenschmidt
  2 siblings, 0 replies; 40+ messages in thread
From: Benjamin Herrenschmidt @ 2006-10-27  2:49 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha



Any reason why this is not static nor __init ? :
> +struct device_node *find_mpc52xx_pic(void)
> +{
> +	struct device_node *dev;
> +	const char *piccompatible_list[] =
> +	{
> +		"mpc5200-interrupt-controller",
> +		"mpc52xx-interrupt-controller",
> +		"mpc52xx-pic",
> +		"mpc5200-pic",
> +		"5200-interrupt-controller",
> +		"52xx-interrupt-controller",
> +		"52xx-pic",
> +		"5200-pic",
> +		NULL
> +	};
> +
> +	/* Look for an MPC52xx interrupt controller */
> +	for_each_node_by_type(dev, "interrupt-controller")
> +	{
> +		const char **piccompatible_entry = piccompatible_list;
> +
> +		for(piccompatible_entry = piccompatible_list; *piccompatible_entry; piccompatible_entry++ )
> +		{
> +			if (device_is_compatible(dev, *piccompatible_entry ))
> +				return dev;
> +		}
> +	}
> +
> +	return NULL;
> +}
> +
> +static int  __init chrp_find_mpc52xx_pic(void)
> +{
> +	if (find_mpc52xx_pic())
> +	{
> +		printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
> +		ppc_md.get_irq = mpc52xx_get_irq;
> +		mpc52xx_init_irq();
> +		return 0;
> +	}
> +
> +	return -ENODEV;
> +}

I'm not sure I see any point in splitting in two functions like that
 
>  static void __init chrp_find_8259(void)
>  {
>  	struct device_node *np, *pic = NULL;
> @@ -473,8 +519,11 @@ static void __init chrp_find_8259(void)
>  		break;
>  	}
>  	if (np == NULL)
> -		printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
> -		       " address, polling\n");
> +	{
> +		printk(KERN_WARNING "Cannot find PCI/i8259 interrupt acknowledge"
> +		       " Fix your tree!\n");
> +		return;
> +	}

Unrelated changes/fix, should probably be in a separate patch.

Cheers,
Ben.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 17:17 ` John Rigby
  2006-10-26 17:23   ` Nicolas DET
  2006-10-26 17:33   ` Sylvain Munaut
@ 2006-10-27  2:57   ` Benjamin Herrenschmidt
  2 siblings, 0 replies; 40+ messages in thread
From: Benjamin Herrenschmidt @ 2006-10-27  2:57 UTC (permalink / raw)
  To: John Rigby; +Cc: akpm, linuxppc-embedded, sl, linuxppc-dev, sha

On Thu, 2006-10-26 at 11:17 -0600, John Rigby wrote:
> >
> > * mpc5k2_bestcomm.c (& helpers): I've been in contact with others people
> > using bestcomm and please to see the development was still active. I'm
> > already using latest code on my board but this is not include in this
> > patch. Indeed, it needs some changes for ARCH=powerpc. Moreover, we have
> > a different approach for the tasks. I'll be pleased to work with the
> > bestcomm folks.
> >
> 
> So you preload the bestcomm task code in your boot loader?  Do those
> of us using other bootloaders still have the option of loading the
> task code later in linux?
> 
> What api are you using?  Sylvain's proposed one based on Dale's with
> some additions from me?  Or have you come up with your own?

I think we need to look into 3 options for the bestcomm task code:

 - Preloaded by the firmware
 - In the device-tree but not preloaded
 - In the kernel

Though we might want to completely dismiss the 3rd option and decide
that it has to be in the device-tree, wether it's provided by the
zImage wrapper, or by the firmware.

Do you see any other case ?

So we need to define the content of the various device nodes for those
3 cases. The 3rd case is easy: probably nothing to put there, purely an
in-kernel thing, unless the bestcomm task IDs related to a given cell
are always the same.

The two first ones are similar, with the exception that the "blob" is in
one case preloaded (thus we provide a property telling where it is in
the sram) and in the other case, the blob is in the DT itself, thus we
have a bit of "bootstrap" code that loads it. In both cases, tasks IDs
are known and thus the device-tree might contain the necessary binding
informations.

Now, in any case, the "drivers" need a way to link to their respective
"tasks". That is, the function drivers (FEC, ...) need to use functions
provided by the "bestcomm" driver to setup and use tasks. In order to do
that the function drivers need to provide enough information of course
to allow the bestcomm to properly find out the tasks.

That's why my idea is that we associate to "known" bestcomm tasks a name
(a string), for example, "fec-tx" and "fec-rx" and the function drivers
pass their device-node to the bestcomm drivers. The Bestcomm "driver"
can then look into the device-tree node for a property "bestcomm-task-%
s" where %s is the task "name", containing the task informations (ID,
position in a table, whatever, I don't remember the details, it's up to
you guys to define something).

That property can then be in the device own node, in the bestcomm node,
or absent in the case where the whole bestcom ucode is embedded in the
kernel itself, in which case the driver has an internal table to resolve
that, but I wonder if we shouldn't make madantory to at least have it in
the device-tree and thus ignore that case 3...

Ben.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 17:33   ` Sylvain Munaut
@ 2006-10-27  3:03     ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 40+ messages in thread
From: Benjamin Herrenschmidt @ 2006-10-27  3:03 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: akpm, linuxppc-embedded, sl, linuxppc-dev, sha

> Since the bestcomm init is in a module, a different module could be
> implemented,
> (like bestcomm-chrp5k2.ko) that instead of clearing SRAM and doing
> everything
> from scrtch, would rely on the bootloader more. This would allow
> "custom" tasks
> to be marked as "don't touch". So if the bootloader want to load
> something that
> will not be altered by the linux driver (for whatever reason ...)

I don't think we should have two different modules.

We are talking here about arch/powerpc where the presence of a
device-tree is mandatory. Thus, we should rely on that and define
something based on that.

In any case, I strongly think a single module with a single API should
be able to deal with all the cases we need to define for loading the
tasks. As I defined in a separate email, that includes wether the tasks
are preloaded, provided as a blob in the device-tree (possibly via the
zImage wrapper, and thus still in the kernel tree), or hard coded in the
kernel driver (I don't like that solution though).

It's mostly a matter on how the thing initializes anyway. Once it's up
and running, the code path should be identical.

> However, for the tasks like FEC and ATA and everything supported in the
> kernel
> natively, I would still recommend reload the task code (anyway the
> driver is gonna
> reset the task and everything ...) Trying to reuse the microcode loaded
> by the
> bootloader is not a great idea IMHO. (Imagine, the fec driver is changed
> to use
> the latest microcode, but the bootloader is not ... both have to be in
> perfect sync ...)

Is there some versionning available with the microcode ? I'm afraid
there might not be (since that whole bestcomm business seems to be
immune to good ideas from whoever design the whole chip), but that would
be useful. I agree that having the task code coming from the firmware
might not be the best idea if there is no versionning, but it nicely
solves some of the problems related to distributing "binary blobs" ...
I'm sure debian would have issues with bestcomm code shipped with the
kernel....

If no versionning is available we might want to create one ourselves,
via a wiki possibly and one person (you ?) responsible for distributing
the "releases" and assigning them versions...

At which point, the device-tree can contain version information along
with the task code or pointers to the code in sram.

> We would still have to compare the internal FDT and the preloaded one
> though since
> they have to match ...

Ben.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 17:54               ` Sylvain Munaut
@ 2006-10-27  3:08                 ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 40+ messages in thread
From: Benjamin Herrenschmidt @ 2006-10-27  3:08 UTC (permalink / raw)
  To: Sylvain Munaut; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

On Thu, 2006-10-26 at 19:54 +0200, Sylvain Munaut wrote:
> Hi Nicolas,
> 
> 
> I don't have much to add to what's already been posted, so here's a
> couple of details,
> mainly compatibility concerns with the legacy arch/ppc tree.

I'd rather not clobber the code to be compatible with arch/ppc... once
52xx is ported over, I'm happy to completely drop support for arch/ppc
52xx. If we want to keep dual support for a while and we are changing
APIs too much, we can just fork the drivers for a kernel version of two
until we are confident enough to drop the arch/ppc version.
  
> > diff -uprN a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
> > --- a/include/asm-ppc/mpc52xx.h	2006-10-25 19:07:48.000000000 +0200
> > +++ b/include/asm-ppc/mpc52xx.h	2006-10-25 19:11:55.000000000 +0200
> > @@ -119,7 +119,7 @@ enum ppc_sys_devices {
> >  #define MPC52xx_SDMA_IRQ_NUM	17
> >  #define MPC52xx_PERP_IRQ_NUM	23
> >  
> > -#define MPC52xx_CRIT_IRQ_BASE	1
> > +#define MPC52xx_CRIT_IRQ_BASE	0

> As explained in IRC, I'm not sure about this.
> I was previously talked into applying this to avoid using interrupt
> number 0. In the LITE5200 IRQ0 is used for PCI. It's interrupt number
> is equal to MPC52xx_CRIT_IRQ_BASE and if it's 0 some drivers just don't
> work.

arch/powerpc has completely virtualized interrupt numbering. The
"hardware" numbers supported by a given interrupt controller are
generally not visible to a driver and can have any value including 0.
The system will assign virtual numbers when interrupts are "mapped" and
those will never be 0.

> That's when using the arch/ppc code. Apparently this is no longer an
> issue in arch/powerpc (someone to confirm and explain me why ? I would guess
> the irq_linear_revmap thingie ), but can a "standard" lite5200 be booted
> in a arch/powerpc kernel ?

Once the code has been ported over :-)

> So if no critical, I would postpone that change until it's confirmed
> a lite5200 can boot ...

It's not been ported yet I presume. Anyway, as I said, we shouldn't
bother too much about what is in arch/ppc. If we think we are changing
things in a conflicting way, then we should fork the drivers and
includes (you can have the same include in both asm-ppc and asm-powerpc,
the one matching you building ARCH will be used and they can have
different definitions).

> > -extern int mpc52xx_get_irq(void);
> > +extern unsigned int mpc52xx_get_irq(void);

> Mmmh, the one in arch/ppc is not unsigned but I guess the warning is fine.

We should instead create a new mpc52xx.h in include/asm-powerpc and
leave arch/ppc alone

> Finally, some triviality : The patch adds some space on empty lines. Also,
> the indentation is sometimes done with space and sometimes with space ...

Yeah, I've noticed that the patch is fairly whitespace damaged. It's
also incorrect in many ways concerning the hooking to genirq, I'm
surprised it works at all in fact.

It might be useful if somebody got me one of those boards (either efika
or lite5200b) so I can do some proper rework of that stuff.

Ben.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-26 20:00             ` Grant Likely
  2006-10-26 20:51               ` Sylvain Munaut
@ 2006-10-27  3:28               ` Benjamin Herrenschmidt
  2006-10-27 14:52                 ` Nicolas DET
  1 sibling, 1 reply; 40+ messages in thread
From: Benjamin Herrenschmidt @ 2006-10-27  3:28 UTC (permalink / raw)
  To: Grant Likely; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

On Thu, 2006-10-26 at 14:00 -0600, Grant Likely wrote:
> My comments are satisfied
> 
> Acked-by: Grant Likely <grant.likely@secretlab.ca>

Nack.

The irq code doesn't properly use the genirq infrastructure. It's not
setting flow handlers, not implementing set_irq_type, not using the new
mask/unmask instead of the toplevel enable/disable...

Ben.

> On 10/26/06, Nicolas DET <nd@bplan-gmbh.de> wrote:
> > Grant Likely wrote:
> >
> > >> +
> > >> +struct device_node *find_mpc52xx_pic(void)
> > >> +{
> > >> +       struct device_node *dev;
> > >> +       const char *piccompatible_list[] =
> > >> +       {
> > >> +               "mpc5200-interrupt-controller",
> > >> +               "mpc52xx-interrupt-controller",
> > >> +               "mpc52xx-pic",
> > >> +               "mpc5200-pic",
> > >> +               "5200-interrupt-controller",
> > >> +               "52xx-interrupt-controller",
> > >> +               "52xx-pic",
> > >> +               "5200-pic",
> > >> +               NULL
> > >> +       };
> > >
> > > Considering Efika is the *only* CHRP 52xx board out there at the
> > > moment, and only a handful of embedded folks trying to move it to
> > > arch/powerpc, surely we can come to an agreement now on what this
> > > thing is named.  :)
> > >
> > >
> >
> > Done
> >
> >
> >
> >
> > --- a/arch/powerpc/sysdev/Makefile      2006-10-25 19:07:24.000000000 +0200
> > +++ b/arch/powerpc/sysdev/Makefile      2006-10-26 11:38:02.000000000 +0200
> > @@ -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/arch/powerpc/sysdev/mpc52xx_pic.c 1970-01-01 01:00:00.000000000 +0100
> > +++ b/arch/powerpc/sysdev/mpc52xx_pic.c 2006-10-26 21:32:05.000000000 +0200
> > @@ -0,0 +1,363 @@
> > +/*
> > + * arch/powerpc/sysdev/mpc52xx_pic.c
> > + *
> > + * Programmable Interrupt Controller functions for the Freescale MPC52xx
> > + * embedded CPU.
> > + * Modified for CHRP Efika 5K2
> > + *
> > + * Maintainer : Sylvain Munaut <tnt@246tNt.com>
> > + *
> > + * 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.
> > + */
> > +
> > +#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 <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 void mpc52xx_ic_disable(unsigned int virq)
> > +{
> > +       u32 val;
> > +       int irq;
> > +
> > +       irq = irq_map[virq].hwirq;
> > +
> > +       pr_debug("%s: irq=%d\n", __func__, irq);
> > +
> > +       if (irq == MPC52xx_IRQ0) {
> > +               val = in_be32(&intr->ctrl);
> > +               val &= ~(1 << 11);
> > +               out_be32(&intr->ctrl, val);
> > +       } else if (irq < MPC52xx_IRQ1) {
> > +               BUG();
> > +       } else if (irq <= MPC52xx_IRQ3) {
> > +               val = in_be32(&intr->ctrl);
> > +               val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
> > +               out_be32(&intr->ctrl, val);
> > +       } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
> > +               val = in_be32(&intr->main_mask);
> > +               val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
> > +               out_be32(&intr->main_mask, val);
> > +       } else if (irq < MPC52xx_PERP_IRQ_BASE) {
> > +               val = in_be32(&sdma->IntMask);
> > +               val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
> > +               out_be32(&sdma->IntMask, val);
> > +       } else {
> > +               val = in_be32(&intr->per_mask);
> > +               val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
> > +               out_be32(&intr->per_mask, val);
> > +       }
> > +}
> > +
> > +static void mpc52xx_ic_enable(unsigned int virq)
> > +{
> > +       u32 val;
> > +       int irq;
> > +
> > +       irq = irq_map[virq].hwirq;
> > +
> > +       pr_debug("%s: irq=%d\n", __func__, irq);
> > +
> > +       if (irq == MPC52xx_IRQ0) {
> > +               val = in_be32(&intr->ctrl);
> > +               val |= 1 << 11;
> > +               out_be32(&intr->ctrl, val);
> > +       } else if (irq < MPC52xx_IRQ1) {
> > +               BUG();
> > +       } else if (irq <= MPC52xx_IRQ3) {
> > +               val = in_be32(&intr->ctrl);
> > +               val |= 1 << (10 - (irq - MPC52xx_IRQ1));
> > +               out_be32(&intr->ctrl, val);
> > +       } else if (irq < MPC52xx_SDMA_IRQ_BASE) {
> > +               val = in_be32(&intr->main_mask);
> > +               val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
> > +               out_be32(&intr->main_mask, val);
> > +       } else if (irq < MPC52xx_PERP_IRQ_BASE) {
> > +               val = in_be32(&sdma->IntMask);
> > +               val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
> > +               out_be32(&sdma->IntMask, val);
> > +       } else {
> > +               val = in_be32(&intr->per_mask);
> > +               val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
> > +               out_be32(&intr->per_mask, val);
> > +       }
> > +}
> > +
> > +static void mpc52xx_ic_ack(unsigned int virq)
> > +{
> > +       u32 val;
> > +       int irq;
> > +
> > +       irq = irq_map[virq].hwirq;
> > +
> > +       pr_debug("%s: irq=%d\n", __func__, irq);
> > +
> > +       /*
> > +        * Only some irqs are reset here, others in interrupting hardware.
> > +        */
> > +
> > +       switch (irq) {
> > +       case MPC52xx_IRQ0:
> > +               val = in_be32(&intr->ctrl);
> > +               val |= 0x08000000;
> > +               out_be32(&intr->ctrl, val);
> > +               break;
> > +       case MPC52xx_CCS_IRQ:
> > +               val = in_be32(&intr->enc_status);
> > +               val |= 0x00000400;
> > +               out_be32(&intr->enc_status, val);
> > +               break;
> > +       case MPC52xx_IRQ1:
> > +               val = in_be32(&intr->ctrl);
> > +               val |= 0x04000000;
> > +               out_be32(&intr->ctrl, val);
> > +               break;
> > +       case MPC52xx_IRQ2:
> > +               val = in_be32(&intr->ctrl);
> > +               val |= 0x02000000;
> > +               out_be32(&intr->ctrl, val);
> > +               break;
> > +       case MPC52xx_IRQ3:
> > +               val = in_be32(&intr->ctrl);
> > +               val |= 0x01000000;
> > +               out_be32(&intr->ctrl, val);
> > +               break;
> > +       default:
> > +               if (irq >= MPC52xx_SDMA_IRQ_BASE
> > +                   && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
> > +                       out_be32(&sdma->IntPend,
> > +                                1 << (irq - MPC52xx_SDMA_IRQ_BASE));
> > +               }
> > +
> > +               break;
> > +       }
> > +
> > +}
> > +
> > +static void mpc52xx_ic_disable_and_ack(unsigned int irq)
> > +{
> > +       mpc52xx_ic_disable(irq);
> > +       mpc52xx_ic_ack(irq);
> > +}
> > +
> > +static void mpc52xx_ic_end(unsigned int irq)
> > +{
> > +       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
> > +               mpc52xx_ic_enable(irq);
> > +}
> > +
> > +static struct irq_chip mpc52xx_irqchip = {
> > +       .name = " MPC52xx  ",
> > +       .enable = mpc52xx_ic_enable,
> > +       .disable = mpc52xx_ic_disable,
> > +       .ack = mpc52xx_ic_disable_and_ack,
> > +       .end = mpc52xx_ic_end,
> > +};
> > +
> > +extern struct device_node *find_mpc52xx_pic(void);
> > +static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
> > +{
> > +       pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_pic(), node);
> > +       return find_mpc52xx_pic() == 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)
> > +{
> > +       static unsigned char map_senses[4] = {
> > +               IRQ_TYPE_LEVEL_HIGH,
> > +               IRQ_TYPE_EDGE_FALLING,
> > +               IRQ_TYPE_EDGE_RISING,
> > +               IRQ_TYPE_LEVEL_LOW,
> > +       };
> > +
> > +       int intrvect_l1;
> > +       int intrvect_l2;
> > +       int intrvect_type;
> > +       int intrvect_linux;
> > +
> > +       pr_debug("%s:\n", __func__);
> > +
> > +       if (intsize != 3)
> > +               return -1;
> > +
> > +       intrvect_l1 = (int)intspec[0];
> > +       intrvect_l2 = (int)intspec[1];
> > +       intrvect_type = (int)intspec[2];
> > +
> > +       pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2,
> > +                intrvect_type);
> > +
> > +       switch (intrvect_l1) {
> > +       case 0:         /* Critical */
> > +               intrvect_linux = MPC52xx_CRIT_IRQ_BASE;
> > +               break;
> > +
> > +       case 1:         /* Main */
> > +               intrvect_linux = MPC52xx_MAIN_IRQ_BASE;
> > +               break;
> > +
> > +       case 2:         /* Periph */
> > +               intrvect_linux = MPC52xx_PERP_IRQ_BASE;
> > +               break;
> > +
> > +       case 3:         /* Bestcomm */
> > +               intrvect_linux = MPC52xx_SDMA_IRQ_BASE;
> > +               break;
> > +
> > +       default:
> > +               if (printk_ratelimit())
> > +                       printk(KERN_ERR "Wrong L1 interrupt vector (%d)\n",
> > +                              intrvect_l1);
> > +
> > +               return -1;
> > +       }
> > +
> > +       intrvect_linux += intrvect_l2;
> > +
> > +       pr_debug("return %d\n", intrvect_linux);
> > +
> > +       *out_hwirq = intrvect_linux;
> > +       *out_flags = map_senses[intrvect_type];
> > +
> > +       return 0;
> > +
> > +}
> > +
> > +int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
> > +                       irq_hw_number_t hw)
> > +{
> > +       pr_debug("%s: v=%d, hw=%d\n", __func__, virq, (int)hw);
> > +
> > +       return 0;
> > +}
> > +
> > +void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
> > +{
> > +       pr_debug("%s: v=%d\n", __func__, virq);
> > +}
> > +
> > +static struct irq_host_ops mpc52xx_irqhost_ops = {
> > +       .match = mpc52xx_irqhost_match,
> > +       .xlate = mpc52xx_irqhost_xlate,
> > +       .map = mpc52xx_irqhost_map,
> > +       .unmap = mpc52xx_irqhost_unmap,
> > +};
> > +
> > +void __init mpc52xx_init_irq(void)
> > +{
> > +       int i;
> > +       u32 intr_ctrl;
> > +
> > +       /* Remap the necessary zones */
> > +       intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
> > +       sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
> > +
> > +       if ((intr == NULL) || (sdma == NULL))
> > +               panic("Can't ioremap PIC/SDMA register or init_irq !");
> > +
> > +       /* 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);
> > +       /* Initialize irq_desc[i].handler's with mpc52xx_ic. */
> > +       for (i = 0; i < NR_IRQS; i++) {
> > +               irq_desc[i].chip = &mpc52xx_irqchip;
> > +               irq_desc[i].status = IRQ_LEVEL;
> > +
> > +       }
> > +
> > +#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
> > +       for (i = 0; i < 4; i++) {
> > +               int mode;
> > +               mode = IRQn_MODE(intr_ctrl, i);
> > +               if ((mode == 0x1) || (mode == 0x2))
> > +                       irq_desc[i ? MPC52xx_IRQ1 + i -
> > +                                1 : MPC52xx_IRQ0].status = 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, NR_IRQS, &mpc52xx_irqhost_ops,
> > +                          -1);
> > +       pr_debug("%s: mpc52xx_irqhost =%p\n", __func__, mpc52xx_irqhost);
> > +}
> > +
> > +unsigned int mpc52xx_get_irq(void)
> > +{
> > +       u32 status;
> > +       int virq;
> > +       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_CRIT_IRQ_BASE;
> > +       } else if (status & 0x00200000) {       /* main */
> > +               irq = (status >> 16) & 0x1f;
> > +               if (irq == 4)   /* low priority peripheral */
> > +                       goto peripheral;
> > +               irq += MPC52xx_MAIN_IRQ_BASE;
> > +       } else if (status & 0x20000000) {       /* peripheral */
> > +             peripheral:
> > +               irq = (status >> 24) & 0x1f;
> > +               if (irq == 0) { /* bestcomm */
> > +                       status = in_be32(&sdma->IntPend);
> > +                       irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE - 1;
> > +               } else
> > +                       irq += MPC52xx_PERP_IRQ_BASE;
> > +
> > +       }
> > +
> > +       virq = irq_linear_revmap(mpc52xx_irqhost, irq);
> > +       pr_debug("%s: irq=%d -> %d\n", __func__, irq, virq);
> > +
> > +       return virq;
> > +}
> > --- a/arch/powerpc/Kconfig      2006-10-25 19:07:23.000000000 +0200
> > +++ b/arch/powerpc/Kconfig      2006-10-26 18:55:58.000000000 +0200
> > @@ -384,6 +384,11 @@ config PPC_CHRP
> >         select PPC_RTAS
> >         select PPC_MPC106
> >         select PPC_UDBG_16550
> > +       select PPC_MPC52xx_PIC
> > +       default y
> > +
> > +config PPC_MPC52xx_PIC
> > +        bool
> >         default y
> >
> >  config PPC_PMAC
> > --- a/arch/powerpc/platforms/chrp/setup.c       2006-10-25 19:07:23.000000000 +0200
> > +++ b/arch/powerpc/platforms/chrp/setup.c       2006-10-26 21:47:29.000000000 +0200
> > @@ -51,6 +51,7 @@
> >  #include <asm/mpic.h>
> >  #include <asm/rtas.h>
> >  #include <asm/xmon.h>
> > +#include <asm/mpc52xx.h>
> >
> >  #include "chrp.h"
> >
> > @@ -435,6 +436,44 @@ static struct irqaction xmon_irqaction =
> >  };
> >  #endif
> >
> > +
> > +struct device_node *find_mpc52xx_pic(void)
> > +{
> > +       struct device_node *dev;
> > +       const char *piccompatible_list[] =
> > +       {
> > +               "mpc5200-pic",
> > +               NULL
> > +       };
> > +
> > +       /* Look for an MPC52xx interrupt controller */
> > +       for_each_node_by_type(dev, "interrupt-controller")
> > +       {
> > +               const char **piccompatible_entry = piccompatible_list;
> > +
> > +               for(piccompatible_entry = piccompatible_list; *piccompatible_entry; piccompatible_entry++ )
> > +               {
> > +                       if (device_is_compatible(dev, *piccompatible_entry ))
> > +                               return dev;
> > +               }
> > +       }
> > +
> > +       return NULL;
> > +}
> > +
> > +static int  __init chrp_find_mpc52xx_pic(void)
> > +{
> > +       if (find_mpc52xx_pic())
> > +       {
> > +               printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
> > +               ppc_md.get_irq = mpc52xx_get_irq;
> > +               mpc52xx_init_irq();
> > +               return 0;
> > +       }
> > +
> > +       return -ENODEV;
> > +}
> > +
> >  static void __init chrp_find_8259(void)
> >  {
> >         struct device_node *np, *pic = NULL;
> > @@ -473,8 +512,11 @@ static void __init chrp_find_8259(void)
> >                 break;
> >         }
> >         if (np == NULL)
> > -               printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
> > -                      " address, polling\n");
> > +       {
> > +               printk(KERN_WARNING "Cannot find PCI/i8259 interrupt acknowledge"
> > +                      " Fix your tree!\n");
> > +               return;
> > +       }
> >
> >         i8259_init(pic, chrp_int_ack);
> >         if (ppc_md.get_irq == NULL)
> > @@ -494,6 +536,8 @@ void __init chrp_init_IRQ(void)
> >  #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
> >         struct device_node *kbd;
> >  #endif
> > +
> > +       chrp_find_mpc52xx_pic();
> >         chrp_find_openpic();
> >         chrp_find_8259();
> >
> >
> >
> >
> >
> 
> 

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-27  3:28               ` Benjamin Herrenschmidt
@ 2006-10-27 14:52                 ` Nicolas DET
  2006-10-27 15:04                   ` Nicolas DET
  2006-10-27 22:05                   ` Sylvain Munaut
  0 siblings, 2 replies; 40+ messages in thread
From: Nicolas DET @ 2006-10-27 14:52 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

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

Benjamin Herrenschmidt wrote:
> On Thu, 2006-10-26 at 14:00 -0600, Grant Likely wrote:
>> My comments are satisfied
>>
>> Acked-by: Grant Likely <grant.likely@secretlab.ca>
> 
> Nack.
> 
> The irq code doesn't properly use the genirq infrastructure. It's not
> setting flow handlers, not implementing set_irq_type, not using the new
> mask/unmask instead of the toplevel enable/disable...
> 
>

Done.

We agree on IRC last night to postpone this implementation later on. 
However, here it is.

This patch compiles fine when applied to the kernel 2.6.19-rc3. I also 
tested gcc 3.3.5 and 4.1.2.

I made some tests and did not found any issue. However, more 
testing/stressing/torturing and also with on others platforms is 
required to fully validate the driver.

Regards

[-- Attachment #2: chrpmpc52xx_2.6.19-rc3.patch --]
[-- Type: text/plain, Size: 24917 bytes --]

--- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/Makefile	2006-10-27 15:31:41.000000000 +0200
@@ -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/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-27 15:58:29.000000000 +0200
@@ -0,0 +1,414 @@
+/*
+ * arch/powerpc/sysdev/mpc52xx_pic.c
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx 
+ * embedded CPU.
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 void mpc52xx_ic_mask(unsigned int virq)
+{
+	u32 val;
+	int irq;
+	int l1irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l1=%d, l2=%d\n", __func__, irq, l1irq, l2irq);
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		if (l2irq != 0)
+			BUG();
+
+		val = in_be32(&intr->ctrl);
+		val &= ~(1 << 11);
+		out_be32(&intr->ctrl, val);
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		if ( (l2irq >= 1) && (l2irq <= 3) ) {
+			val = in_be32(&intr->ctrl);
+			val &= ~(1 << (11 - l2irq));
+			out_be32(&intr->ctrl, val);
+		} else {
+			val = in_be32(&intr->main_mask);
+			val |= 1 << (16 - l2irq);
+			out_be32(&intr->main_mask, val);
+		}
+		break;
+
+	case MPC52xx_IRQ_L1_PERP:
+		val = in_be32(&intr->per_mask);
+		val |= 1 << (31 - l2irq);
+		out_be32(&intr->per_mask, val);
+		break;
+
+	case MPC52xx_IRQ_L1_SDMA:
+		val = in_be32(&sdma->IntMask);
+		val |= 1 << l2irq;
+		out_be32(&sdma->IntMask, val);
+		break;
+
+	default:
+		printk(KERN_ERR "MPC52xx PIC: Wrong interrupt\n");
+	}
+}
+
+static void mpc52xx_ic_unmask(unsigned int virq)
+{
+	u32 val;
+	int irq;
+	int l1irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l1=%d, l2=%d\n", __func__, irq, l1irq, l2irq);
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		if (l2irq != 0)
+			BUG();
+
+		val = in_be32(&intr->ctrl);
+		val |= 1 << 11;
+		out_be32(&intr->ctrl, val);
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		if ( (l2irq >= 1) && (l2irq <= 3) ) {
+			val = in_be32(&intr->ctrl);
+			val |= 1 << (11 - l2irq);
+			out_be32(&intr->ctrl, val);
+		} else {
+			val = in_be32(&intr->main_mask);
+			val &= ~(1 << (16 - l2irq));
+			out_be32(&intr->main_mask, val);
+		}
+		break;
+
+	case MPC52xx_IRQ_L1_PERP:
+		val = in_be32(&intr->per_mask);
+		val &= ~(1 << (31 - l2irq));
+		out_be32(&intr->per_mask, val);
+		break;
+
+	case MPC52xx_IRQ_L1_SDMA:
+		val = in_be32(&sdma->IntMask);
+		val &= ~(1 << l2irq);
+		out_be32(&sdma->IntMask, val);
+		break;
+
+	default:
+		printk(KERN_ERR "MPC52xx PIC: Wrong interrupt\n");
+	}
+}
+
+static void mpc52xx_ic_ack(unsigned int virq)
+{
+	u32 val;
+	int irq;
+	int l1irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l1=%d, l2=%d\n", __func__, irq, l1irq, l2irq);
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		if (l2irq != 0)
+			BUG();
+
+		val = in_be32(&intr->ctrl);
+		val |= 0x08000000;
+		out_be32(&intr->ctrl, val);
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		if ( (l2irq >= 1) && (l2irq <= 3) ) {
+			val = in_be32(&intr->ctrl);
+			val |= 0x08000000 >> l2irq;
+			out_be32(&intr->ctrl, val);
+		}
+		break;
+
+	case MPC52xx_IRQ_L1_PERP:
+		val = in_be32(&intr->per_mask);
+		val &= ~(1 << (31 - l2irq));
+		out_be32(&intr->per_mask, val);
+		break;
+
+	case MPC52xx_IRQ_L1_SDMA:
+		out_be32(&sdma->IntPend, 1 << l2irq);
+		break;
+
+	default:
+		printk(KERN_ERR "MPC52xx PIC: Wrong interrupt\n");
+	}
+}
+
+static void mpc52xx_ic_mask_and_ack(unsigned int irq)
+{
+	mpc52xx_ic_mask(irq);
+	mpc52xx_ic_ack(irq);
+}
+
+static struct irq_chip mpc52xx_irqchip = {
+	.typename = " MPC52xx  ",
+	.mask = mpc52xx_ic_mask,
+	.unmask = mpc52xx_ic_unmask,
+	.mask_ack = mpc52xx_ic_mask_and_ack,
+};
+
+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 find_mpc52xx_picnode() == 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)
+{
+	static unsigned char map_senses[4] = {
+		IRQ_TYPE_LEVEL_HIGH,
+		IRQ_TYPE_EDGE_FALLING,
+		IRQ_TYPE_EDGE_RISING,
+		IRQ_TYPE_LEVEL_LOW,
+	};
+
+	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];
+
+	pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2,
+		 intrvect_type);
+
+	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\n", intrvect_linux);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = map_senses[intrvect_type];
+
+	return 0;
+
+}
+
+static int mpc52xx_islevel(int num)
+{
+	u32 ictl_req;
+	int ictl_type;
+
+	ictl_req = in_be32(&intr->ctrl);
+	ictl_type = (ictl_req >> 16) & 0x3;
+
+	switch (ictl_type) {
+	case 0:
+	case 3:
+		return 1;
+	}
+
+	return 0;
+}
+
+static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+			       irq_hw_number_t irq)
+{
+	int l1irq;
+	int l2irq;
+	unsigned int status;
+
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	status = get_irq_desc(virq)->status;
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		if (l2irq != 0)
+			BUG();
+		if (mpc52xx_islevel(0))
+			status |= IRQ_LEVEL;
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		if (mpc52xx_islevel(l2irq))
+			status |= IRQ_LEVEL;
+		break;
+
+	default:
+		status |= IRQ_LEVEL;
+	}
+
+	get_irq_desc(virq)->status = status;
+	set_irq_chip_and_handler(virq, &mpc52xx_irqchip,
+				 (status & IRQ_LEVEL) ? handle_level_irq :
+				 handle_edge_irq);
+
+	pr_debug("%s: virq=%x, hw=%x. desc status=%x\n", __func__, virq,
+		 (int)irq, status);
+
+	return 0;
+}
+
+void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
+{
+	pr_debug("%s: v=%x\n", __func__, virq);
+
+	mpc52xx_ic_mask(virq);
+	set_irq_chip_and_handler(virq, NULL, NULL);
+	synchronize_irq(virq);
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+	.match = mpc52xx_irqhost_match,
+	.xlate = mpc52xx_irqhost_xlate,
+	.map = mpc52xx_irqhost_map,
+	.unmap = mpc52xx_irqhost_unmap,
+};
+
+void __init mpc52xx_init_irq(void)
+{
+	int i;
+	u32 intr_ctrl;
+
+	/* Remap the necessary zones */
+	intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+	sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
+
+	if ((intr == NULL) || (sdma == NULL))
+		panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+	/* 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);
+	/* Initialize irq_desc[i].handler's with mpc52xx_ic. */
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].chip = &mpc52xx_irqchip;
+		irq_desc[i].status = IRQ_LEVEL;
+
+	}
+
+	/*
+	 * 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, NR_IRQS, &mpc52xx_irqhost_ops,
+			   -1);
+}
+
+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/Kconfig	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/Kconfig	2006-10-27 15:50:21.000000000 +0200
@@ -384,6 +384,11 @@ config PPC_CHRP
 	select PPC_RTAS
 	select PPC_MPC106
 	select PPC_UDBG_16550
+	select PPC_MPC52xx_PIC
+	default y
+
+config PPC_MPC52xx_PIC
+        bool
 	default y
 
 config PPC_PMAC
--- a/arch/powerpc/platforms/chrp/setup.c	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/platforms/chrp/setup.c	2006-10-27 16:08:03.000000000 +0200
@@ -51,6 +51,7 @@
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 #include <asm/xmon.h>
+#include <asm/mpc52xx.h>
 
 #include "chrp.h"
 
@@ -435,6 +436,18 @@ static struct irqaction xmon_irqaction =
 };
 #endif
 
+static int __init chrp_find_mpc52xx_pic(void)
+{
+	if (find_mpc52xx_picnode()) {
+		printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
+		ppc_md.get_irq = mpc52xx_get_irq;
+		mpc52xx_init_irq();
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
 static void __init chrp_find_8259(void)
 {
 	struct device_node *np, *pic = NULL;
@@ -496,6 +509,7 @@ void __init chrp_init_IRQ(void)
 #endif
 	chrp_find_openpic();
 	chrp_find_8259();
+	chrp_find_mpc52xx_pic();
 
 #ifdef CONFIG_SMP
 	/* Pegasos has no MPIC, those ops would make it crash. It might be an
diff -uprN a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
--- a/include/asm-powerpc/mpc52xx.h	1970-01-01 01:00:00.000000000 +0100
+++ b/include/asm-powerpc/mpc52xx.h	2006-10-27 15:51:55.000000000 +0200
@@ -0,0 +1,414 @@
+/*
+ * include/asm-ppc/mpc52xx.h
+ * 
+ * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
+ * May need to be cleaned as the port goes on ...
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> 
+ * for the 2.4 kernel.
+ *
+ * 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__ */
+
+
+#ifdef CONFIG_PCI
+#define _IO_BASE	isa_io_base
+#define _ISA_MEM_BASE	isa_mem_base
+#define PCI_DRAM_OFFSET	pci_dram_offset
+#else
+#define _IO_BASE	0
+#define _ISA_MEM_BASE	0
+#define PCI_DRAM_OFFSET	0
+#endif
+
+
+/* ======================================================================== */
+/* PPC Sys devices definition                                               */
+/* ======================================================================== */
+
+enum ppc_sys_devices {
+	MPC52xx_MSCAN1,
+	MPC52xx_MSCAN2,
+	MPC52xx_SPI,
+	MPC52xx_USB,
+	MPC52xx_BDLC,
+	MPC52xx_PSC1,
+	MPC52xx_PSC2,
+	MPC52xx_PSC3,
+	MPC52xx_PSC4,
+	MPC52xx_PSC5,
+	MPC52xx_PSC6,
+	MPC52xx_FEC,
+	MPC52xx_ATA,
+	MPC52xx_I2C1,
+	MPC52xx_I2C2,
+	NUM_PPC_SYS_DEVS,
+};
+
+
+/* ======================================================================== */
+/* Main registers/struct addresses                                          */
+/* ======================================================================== */
+
+/* MBAR position */
+#define MPC52xx_MBAR		0xf0000000	/* Phys address */
+#define MPC52xx_MBAR_VIRT	0xf0000000	/* Virt address */
+#define MPC52xx_MBAR_SIZE	0x00010000
+
+#define MPC52xx_PA(x)		((phys_addr_t)(MPC52xx_MBAR + (x)))
+#define MPC52xx_VA(x)		((void __iomem *)(MPC52xx_MBAR_VIRT + (x)))
+
+/* 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    (0xc0)
+
+#define MPC52xx_IRQ_L2_OFFSET  (0)
+#define MPC52xx_IRQ_L2_MASK    (0x3f)
+
+
+/* ======================================================================== */
+/* 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 */
+};
+
+/* RTC */
+struct mpc52xx_rtc {
+	u32	time_set;	/* RTC + 0x00 */
+	u32	date_set;	/* RTC + 0x04 */
+	u32	stopwatch;	/* RTC + 0x08 */
+	u32	int_enable;	/* RTC + 0x0c */
+	u32	time;		/* RTC + 0x10 */
+	u32	date;		/* RTC + 0x14 */
+	u32	stopwatch_intr;	/* RTC + 0x18 */
+	u32	bus_error;	/* RTC + 0x1c */
+	u32	dividers;	/* RTC + 0x20 */
+};
+
+/* 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);
+
+extern unsigned long mpc52xx_find_end_of_memory(void);
+extern void mpc52xx_set_bat(void);
+extern void mpc52xx_map_io(void);
+extern void mpc52xx_restart(char *cmd);
+extern void mpc52xx_halt(void);
+extern void mpc52xx_power_off(void);
+extern void mpc52xx_progress(char *s, unsigned short hex);
+extern void mpc52xx_calibrate_decr(void);
+
+extern void mpc52xx_find_bridges(void);
+
+extern void mpc52xx_setup_cpu(void);
+
+static inline struct device_node *
+find_mpc52xx_picnode(void)
+{
+	return of_find_compatible_node(NULL, "interrupt-controller", "mpc5200-pic");
+}
+
+	/* Matching of PSC function */
+struct mpc52xx_psc_func {
+	int id;
+	char *func;
+};
+
+extern int mpc52xx_match_psc_function(int psc_idx, const char *func);
+extern struct  mpc52xx_psc_func mpc52xx_psc_functions[];
+	/* This array is to be defined in platform file */
+
+#endif /* __ASSEMBLY__ */
+
+
+#endif /* _ASM_POWERPC_MPC52xx_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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-27 14:52                 ` Nicolas DET
@ 2006-10-27 15:04                   ` Nicolas DET
  2006-10-27 17:08                     ` Jon Loeliger
  2006-10-27 22:34                     ` Benjamin Herrenschmidt
  2006-10-27 22:05                   ` Sylvain Munaut
  1 sibling, 2 replies; 40+ messages in thread
From: Nicolas DET @ 2006-10-27 15:04 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

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

Nicolas DET wrote:
> Benjamin Herrenschmidt wrote:
>> On Thu, 2006-10-26 at 14:00 -0600, Grant Likely wrote:
>>> My comments are satisfied
>>>
>>> Acked-by: Grant Likely <grant.likely@secretlab.ca>
>>
>> Nack.
>>
>> The irq code doesn't properly use the genirq infrastructure. It's not
>> setting flow handlers, not implementing set_irq_type, not using the new
>> mask/unmask instead of the toplevel enable/disable...
>>
>>
> 
> Done.
> 
> We agree on IRC last night to postpone this implementation later on. 
> However, here it is.
> 
> This patch compiles fine when applied to the kernel 2.6.19-rc3. I also 
> tested gcc 3.3.5 and 4.1.2.
> 
> I made some tests and did not found any issue. However, more 
> testing/stressing/torturing and also with on others platforms is 
> required to fully validate the driver.
> 
>
>  	/* Pegasos has no MPIC, those ops would make it crash. It might be an
> diff -uprN a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
> --- a/include/asm-powerpc/mpc52xx.h	1970-01-01 01:00:00.000000000 +0100
> +++ b/include/asm-powerpc/mpc52xx.h	2006-10-27 15:51:55.000000000 +0200
> @@ -0,0 +1,414 @@
> +/*
> + * include/asm-ppc/mpc52xx.h
> + * 


Fixed to powerpc


> +#endif /* __ASSEMBLY__ */
> +
> +
> +#ifdef CONFIG_PCI
> +#define _IO_BASE	isa_io_base
> +#define _ISA_MEM_BASE	isa_mem_base
> +#define PCI_DRAM_OFFSET	pci_dram_offset
> +#else
> +#define _IO_BASE	0
> +#define _ISA_MEM_BASE	0
> +#define PCI_DRAM_OFFSET	0
> +#endif
> +
> +
> +/* ======================================================================== */
> +/* PPC Sys devices definition                                               */
> +/* ======================================================================== */
> +
> +enum ppc_sys_devices {
> +	MPC52xx_MSCAN1,
> +	MPC52xx_MSCAN2,
> +	MPC52xx_SPI,
> +	MPC52xx_USB,
> +	MPC52xx_BDLC,
> +	MPC52xx_PSC1,
> +	MPC52xx_PSC2,
> +	MPC52xx_PSC3,
> +	MPC52xx_PSC4,
> +	MPC52xx_PSC5,
> +	MPC52xx_PSC6,
> +	MPC52xx_FEC,
> +	MPC52xx_ATA,
> +	MPC52xx_I2C1,
> +	MPC52xx_I2C2,
> +	NUM_PPC_SYS_DEVS,
> +};
> +
> +

Removed


[-- Attachment #2: chrpmpc52xx_2.6.19-rc3.patch --]
[-- Type: text/plain, Size: 24385 bytes --]

--- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/Makefile	2006-10-27 15:31:41.000000000 +0200
@@ -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/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-27 15:58:29.000000000 +0200
@@ -0,0 +1,414 @@
+/*
+ * arch/powerpc/sysdev/mpc52xx_pic.c
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx 
+ * embedded CPU.
+ * 
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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 void mpc52xx_ic_mask(unsigned int virq)
+{
+	u32 val;
+	int irq;
+	int l1irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l1=%d, l2=%d\n", __func__, irq, l1irq, l2irq);
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		if (l2irq != 0)
+			BUG();
+
+		val = in_be32(&intr->ctrl);
+		val &= ~(1 << 11);
+		out_be32(&intr->ctrl, val);
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		if ( (l2irq >= 1) && (l2irq <= 3) ) {
+			val = in_be32(&intr->ctrl);
+			val &= ~(1 << (11 - l2irq));
+			out_be32(&intr->ctrl, val);
+		} else {
+			val = in_be32(&intr->main_mask);
+			val |= 1 << (16 - l2irq);
+			out_be32(&intr->main_mask, val);
+		}
+		break;
+
+	case MPC52xx_IRQ_L1_PERP:
+		val = in_be32(&intr->per_mask);
+		val |= 1 << (31 - l2irq);
+		out_be32(&intr->per_mask, val);
+		break;
+
+	case MPC52xx_IRQ_L1_SDMA:
+		val = in_be32(&sdma->IntMask);
+		val |= 1 << l2irq;
+		out_be32(&sdma->IntMask, val);
+		break;
+
+	default:
+		printk(KERN_ERR "MPC52xx PIC: Wrong interrupt\n");
+	}
+}
+
+static void mpc52xx_ic_unmask(unsigned int virq)
+{
+	u32 val;
+	int irq;
+	int l1irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l1=%d, l2=%d\n", __func__, irq, l1irq, l2irq);
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		if (l2irq != 0)
+			BUG();
+
+		val = in_be32(&intr->ctrl);
+		val |= 1 << 11;
+		out_be32(&intr->ctrl, val);
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		if ( (l2irq >= 1) && (l2irq <= 3) ) {
+			val = in_be32(&intr->ctrl);
+			val |= 1 << (11 - l2irq);
+			out_be32(&intr->ctrl, val);
+		} else {
+			val = in_be32(&intr->main_mask);
+			val &= ~(1 << (16 - l2irq));
+			out_be32(&intr->main_mask, val);
+		}
+		break;
+
+	case MPC52xx_IRQ_L1_PERP:
+		val = in_be32(&intr->per_mask);
+		val &= ~(1 << (31 - l2irq));
+		out_be32(&intr->per_mask, val);
+		break;
+
+	case MPC52xx_IRQ_L1_SDMA:
+		val = in_be32(&sdma->IntMask);
+		val &= ~(1 << l2irq);
+		out_be32(&sdma->IntMask, val);
+		break;
+
+	default:
+		printk(KERN_ERR "MPC52xx PIC: Wrong interrupt\n");
+	}
+}
+
+static void mpc52xx_ic_ack(unsigned int virq)
+{
+	u32 val;
+	int irq;
+	int l1irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l1=%d, l2=%d\n", __func__, irq, l1irq, l2irq);
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		if (l2irq != 0)
+			BUG();
+
+		val = in_be32(&intr->ctrl);
+		val |= 0x08000000;
+		out_be32(&intr->ctrl, val);
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		if ( (l2irq >= 1) && (l2irq <= 3) ) {
+			val = in_be32(&intr->ctrl);
+			val |= 0x08000000 >> l2irq;
+			out_be32(&intr->ctrl, val);
+		}
+		break;
+
+	case MPC52xx_IRQ_L1_PERP:
+		val = in_be32(&intr->per_mask);
+		val &= ~(1 << (31 - l2irq));
+		out_be32(&intr->per_mask, val);
+		break;
+
+	case MPC52xx_IRQ_L1_SDMA:
+		out_be32(&sdma->IntPend, 1 << l2irq);
+		break;
+
+	default:
+		printk(KERN_ERR "MPC52xx PIC: Wrong interrupt\n");
+	}
+}
+
+static void mpc52xx_ic_mask_and_ack(unsigned int irq)
+{
+	mpc52xx_ic_mask(irq);
+	mpc52xx_ic_ack(irq);
+}
+
+static struct irq_chip mpc52xx_irqchip = {
+	.typename = " MPC52xx  ",
+	.mask = mpc52xx_ic_mask,
+	.unmask = mpc52xx_ic_unmask,
+	.mask_ack = mpc52xx_ic_mask_and_ack,
+};
+
+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 find_mpc52xx_picnode() == 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)
+{
+	static unsigned char map_senses[4] = {
+		IRQ_TYPE_LEVEL_HIGH,
+		IRQ_TYPE_EDGE_FALLING,
+		IRQ_TYPE_EDGE_RISING,
+		IRQ_TYPE_LEVEL_LOW,
+	};
+
+	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];
+
+	pr_debug("l1=%d, l2=%d, type=%d\n", intrvect_l1, intrvect_l2,
+		 intrvect_type);
+
+	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\n", intrvect_linux);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = map_senses[intrvect_type];
+
+	return 0;
+
+}
+
+static int mpc52xx_islevel(int num)
+{
+	u32 ictl_req;
+	int ictl_type;
+
+	ictl_req = in_be32(&intr->ctrl);
+	ictl_type = (ictl_req >> 16) & 0x3;
+
+	switch (ictl_type) {
+	case 0:
+	case 3:
+		return 1;
+	}
+
+	return 0;
+}
+
+static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+			       irq_hw_number_t irq)
+{
+	int l1irq;
+	int l2irq;
+	unsigned int status;
+
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	status = get_irq_desc(virq)->status;
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		if (l2irq != 0)
+			BUG();
+		if (mpc52xx_islevel(0))
+			status |= IRQ_LEVEL;
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		if (mpc52xx_islevel(l2irq))
+			status |= IRQ_LEVEL;
+		break;
+
+	default:
+		status |= IRQ_LEVEL;
+	}
+
+	get_irq_desc(virq)->status = status;
+	set_irq_chip_and_handler(virq, &mpc52xx_irqchip,
+				 (status & IRQ_LEVEL) ? handle_level_irq :
+				 handle_edge_irq);
+
+	pr_debug("%s: virq=%x, hw=%x. desc status=%x\n", __func__, virq,
+		 (int)irq, status);
+
+	return 0;
+}
+
+void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
+{
+	pr_debug("%s: v=%x\n", __func__, virq);
+
+	mpc52xx_ic_mask(virq);
+	set_irq_chip_and_handler(virq, NULL, NULL);
+	synchronize_irq(virq);
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+	.match = mpc52xx_irqhost_match,
+	.xlate = mpc52xx_irqhost_xlate,
+	.map = mpc52xx_irqhost_map,
+	.unmap = mpc52xx_irqhost_unmap,
+};
+
+void __init mpc52xx_init_irq(void)
+{
+	int i;
+	u32 intr_ctrl;
+
+	/* Remap the necessary zones */
+	intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+	sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
+
+	if ((intr == NULL) || (sdma == NULL))
+		panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+	/* 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);
+	/* Initialize irq_desc[i].handler's with mpc52xx_ic. */
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].chip = &mpc52xx_irqchip;
+		irq_desc[i].status = IRQ_LEVEL;
+
+	}
+
+	/*
+	 * 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, NR_IRQS, &mpc52xx_irqhost_ops,
+			   -1);
+}
+
+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/Kconfig	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/Kconfig	2006-10-27 15:50:21.000000000 +0200
@@ -384,6 +384,11 @@ config PPC_CHRP
 	select PPC_RTAS
 	select PPC_MPC106
 	select PPC_UDBG_16550
+	select PPC_MPC52xx_PIC
+	default y
+
+config PPC_MPC52xx_PIC
+        bool
 	default y
 
 config PPC_PMAC
--- a/arch/powerpc/platforms/chrp/setup.c	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/platforms/chrp/setup.c	2006-10-27 16:08:03.000000000 +0200
@@ -51,6 +51,7 @@
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 #include <asm/xmon.h>
+#include <asm/mpc52xx.h>
 
 #include "chrp.h"
 
@@ -435,6 +436,18 @@ static struct irqaction xmon_irqaction =
 };
 #endif
 
+static int __init chrp_find_mpc52xx_pic(void)
+{
+	if (find_mpc52xx_picnode()) {
+		printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
+		ppc_md.get_irq = mpc52xx_get_irq;
+		mpc52xx_init_irq();
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
 static void __init chrp_find_8259(void)
 {
 	struct device_node *np, *pic = NULL;
@@ -496,6 +509,7 @@ void __init chrp_init_IRQ(void)
 #endif
 	chrp_find_openpic();
 	chrp_find_8259();
+	chrp_find_mpc52xx_pic();
 
 #ifdef CONFIG_SMP
 	/* Pegasos has no MPIC, those ops would make it crash. It might be an
diff -uprN a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
--- a/include/asm-powerpc/mpc52xx.h	1970-01-01 01:00:00.000000000 +0100
+++ b/include/asm-powerpc/mpc52xx.h	2006-10-27 15:51:55.000000000 +0200
@@ -0,0 +1,414 @@
+/*
+ * include/asm-powerpc/mpc52xx.h
+ * 
+ * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
+ * May need to be cleaned as the port goes on ...
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> 
+ * for the 2.4 kernel.
+ *
+ * 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__ */
+
+
+#ifdef CONFIG_PCI
+#define _IO_BASE	isa_io_base
+#define _ISA_MEM_BASE	isa_mem_base
+#define PCI_DRAM_OFFSET	pci_dram_offset
+#else
+#define _IO_BASE	0
+#define _ISA_MEM_BASE	0
+#define PCI_DRAM_OFFSET	0
+#endif
+
+/* ======================================================================== */
+/* Main registers/struct addresses                                          */
+/* ======================================================================== */
+
+/* MBAR position */
+#define MPC52xx_MBAR		0xf0000000	/* Phys address */
+#define MPC52xx_MBAR_VIRT	0xf0000000	/* Virt address */
+#define MPC52xx_MBAR_SIZE	0x00010000
+
+#define MPC52xx_PA(x)		((phys_addr_t)(MPC52xx_MBAR + (x)))
+#define MPC52xx_VA(x)		((void __iomem *)(MPC52xx_MBAR_VIRT + (x)))
+
+/* 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    (0xc0)
+
+#define MPC52xx_IRQ_L2_OFFSET  (0)
+#define MPC52xx_IRQ_L2_MASK    (0x3f)
+
+
+/* ======================================================================== */
+/* 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 */
+};
+
+/* RTC */
+struct mpc52xx_rtc {
+	u32	time_set;	/* RTC + 0x00 */
+	u32	date_set;	/* RTC + 0x04 */
+	u32	stopwatch;	/* RTC + 0x08 */
+	u32	int_enable;	/* RTC + 0x0c */
+	u32	time;		/* RTC + 0x10 */
+	u32	date;		/* RTC + 0x14 */
+	u32	stopwatch_intr;	/* RTC + 0x18 */
+	u32	bus_error;	/* RTC + 0x1c */
+	u32	dividers;	/* RTC + 0x20 */
+};
+
+/* 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);
+
+extern unsigned long mpc52xx_find_end_of_memory(void);
+extern void mpc52xx_set_bat(void);
+extern void mpc52xx_map_io(void);
+extern void mpc52xx_restart(char *cmd);
+extern void mpc52xx_halt(void);
+extern void mpc52xx_power_off(void);
+extern void mpc52xx_progress(char *s, unsigned short hex);
+extern void mpc52xx_calibrate_decr(void);
+
+extern void mpc52xx_find_bridges(void);
+
+extern void mpc52xx_setup_cpu(void);
+
+static inline struct device_node *
+find_mpc52xx_picnode(void)
+{
+	return of_find_compatible_node(NULL, "interrupt-controller", "mpc5200-pic");
+}
+
+	/* Matching of PSC function */
+struct mpc52xx_psc_func {
+	int id;
+	char *func;
+};
+
+extern int mpc52xx_match_psc_function(int psc_idx, const char *func);
+extern struct  mpc52xx_psc_func mpc52xx_psc_functions[];
+	/* This array is to be defined in platform file */
+
+#endif /* __ASSEMBLY__ */
+
+
+#endif /* _ASM_POWERPC_MPC52xx_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] 40+ messages in thread

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-27 15:04                   ` Nicolas DET
@ 2006-10-27 17:08                     ` Jon Loeliger
  2006-10-28  0:27                       ` Stephen Rothwell
  2006-10-27 22:34                     ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 40+ messages in thread
From: Jon Loeliger @ 2006-10-27 17:08 UTC (permalink / raw)
  To: Nicolas DET
  Cc: akpm, linuxppc-dev@ozlabs.org, sl, sha,
	linuxppc-embedded@ozlabs.org

On Fri, 2006-10-27 at 10:04, Nicolas DET wrote:

> > diff -uprN a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
> > --- a/include/asm-powerpc/mpc52xx.h	1970-01-01 01:00:00.000000000 +0100
> > +++ b/include/asm-powerpc/mpc52xx.h	2006-10-27 15:51:55.000000000 +0200
> > @@ -0,0 +1,414 @@
> > +/*
> > + * include/asm-ppc/mpc52xx.h
> > + * 
> 
> 
> Fixed to powerpc

I thought we were removing the names of files from
within the file itself, right?

Thanks,
jdl

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-27 14:52                 ` Nicolas DET
  2006-10-27 15:04                   ` Nicolas DET
@ 2006-10-27 22:05                   ` Sylvain Munaut
  1 sibling, 0 replies; 40+ messages in thread
From: Sylvain Munaut @ 2006-10-27 22:05 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, sl, linuxppc-dev, linuxppc-embedded, sha

Hi Nicolas,

Here is a few comments. I'm not very familiar with the new irq stuff so
others
might have more insights.


Sylvain

> --- a/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
> +++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-27 15:58:29.000000000 +0200
> @@ -0,0 +1,414 @@
> +/*
> + * arch/powerpc/sysdev/mpc52xx_pic.c
>   
Looks like jdl is right, we apparently don't do that any more ... So
let's not ;)
> + * Based on (well, mostly copied from) the code from the 2.4 kernel by
> + * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
>   
That can be removed ... We can't blame Dale anymore if it doesn't work ;)

> +
> +static void mpc52xx_ic_mask_and_ack(unsigned int irq)
> +{
> +	mpc52xx_ic_mask(irq);
> +	mpc52xx_ic_ack(irq);
> +}
>   
>From kernel/irq/chip.c that's done automatically if mask_and_ack is NULL.

> +
> +static struct irq_chip mpc52xx_irqchip = {
> +	.typename = " MPC52xx  ",
> +	.mask = mpc52xx_ic_mask,
> +	.unmask = mpc52xx_ic_unmask,
> +	.mask_ack = mpc52xx_ic_mask_and_ack,
> +};
Is it useful to implement set_type for IRQ[0-3] ? (Just asking ...)

> +	for (i = 0; i < NR_IRQS; i++) {
> +		irq_desc[i].chip = &mpc52xx_irqchip;
> +		irq_desc[i].status = IRQ_LEVEL;
> +
> +	}
>   
All LEVEL ?

> +
> +	/*
> +	 * 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, NR_IRQS, &mpc52xx_irqhost_ops,
> +			   -1);
> +}
>   
NR_IRQS ? Might be time to do something better.



> diff -uprN a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
> --- a/include/asm-powerpc/mpc52xx.h	1970-01-01 01:00:00.000000000 +0100
> +++ b/include/asm-powerpc/mpc52xx.h	2006-10-27 15:51:55.000000000 +0200
> @@ -0,0 +1,414 @@
> +/*
> + * include/asm-ppc/mpc52xx.h
> + * 
> + * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
> + * May need to be cleaned as the port goes on ...
> + *
> + *
> + * Maintainer : Sylvain Munaut <tnt@246tNt.com>
> + *
> + * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> 
> + * for the 2.4 kernel.
>   
Again, remove all that (just leave the first line of the description)

> +
> +/* ======================================================================== */
> +/* 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)
>   
As benh suggested on IRC, a L1 offset of 8 might be better for
readability of the
hw irq numbers.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-27 15:04                   ` Nicolas DET
  2006-10-27 17:08                     ` Jon Loeliger
@ 2006-10-27 22:34                     ` Benjamin Herrenschmidt
  1 sibling, 0 replies; 40+ messages in thread
From: Benjamin Herrenschmidt @ 2006-10-27 22:34 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, linuxppc-dev, sl, sha, linuxppc-embedded

On Fri, 2006-10-27 at 17:04 +0200, Nicolas DET wrote:

> +static void mpc52xx_ic_mask(unsigned int virq)
> +{
> +	u32 val;
> +	int irq;
> +	int l1irq;
> +	int l2irq;
> +
> +	irq = irq_map[virq].hwirq;
> +	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
> +	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
> +
> +	pr_debug("%s: irq=%x. l1=%d, l2=%d\n", __func__, irq, l1irq, l2irq);
> +
> +	switch (l1irq) {
> +	case MPC52xx_IRQ_L1_CRIT:
> +		if (l2irq != 0)
> +			BUG();
> +
> +		val = in_be32(&intr->ctrl);
> +		val &= ~(1 << 11);
> +		out_be32(&intr->ctrl, val);
> +		break;
> +
> +	case MPC52xx_IRQ_L1_MAIN:
> +		if ( (l2irq >= 1) && (l2irq <= 3) ) {
> +			val = in_be32(&intr->ctrl);
> +			val &= ~(1 << (11 - l2irq));
> +			out_be32(&intr->ctrl, val);
> +		} else {
> +			val = in_be32(&intr->main_mask);
> +			val |= 1 << (16 - l2irq);
> +			out_be32(&intr->main_mask, val);
> +		}
> +		break;

Any reason why you do the above instead o defining two diferent levels
instead. Also, L1_CRIT would fit in the L1_MAIN case too...

I don't see the point of having also XXX-l2, just put a bit number in L2
and be done with it.

The idea is to streamling the code, such that you can index an array
with l1irq to get the register, and build a mask. No test, no switch
case, etc...

Actually... the most performant way of doing all this is to have a
different irq_chip (with a different set of ask,mask,unmask) for each
"L1" so that they get right to the point. But I would settle for an
array indexed by L1.

> +static void mpc52xx_ic_mask_and_ack(unsigned int irq)
> +{
> +	mpc52xx_ic_mask(irq);
> +	mpc52xx_ic_ack(irq);
> +}

The above is unnuecessary. The core will call mask and ack.

> +static struct irq_chip mpc52xx_irqchip = {
> +	.typename = " MPC52xx  ",
> +	.mask = mpc52xx_ic_mask,
> +	.unmask = mpc52xx_ic_unmask,
> +	.mask_ack = mpc52xx_ic_mask_and_ack,
> +};

In the above, you need to provide ack.

> +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 find_mpc52xx_picnode() == node;
> +}

Don't redo the whole find all the time. Put the node in your
irq_host->host_data at init time and compare it there. That way, also,
find_mpc53xx_picnode() thingy can just stay static to chrp/setup.c. The
way you did it would be a problem if we had more than one platform using
52xx built in the same kernel.

> +static int mpc52xx_islevel(int num)
> +{
> +	u32 ictl_req;
> +	int ictl_type;
> +
> +	ictl_req = in_be32(&intr->ctrl);
> +	ictl_type = (ictl_req >> 16) & 0x3;
> +
> +	switch (ictl_type) {
> +	case 0:
> +	case 3:
> +		return 1;
> +	}
> +
> +	return 0;
> +}

You only have level/edge settings, not polarity ? Also, you aren't
giving the user or device-tree the option to set the type manually....

Ideally, you should use the bits in IRQ_TYPE_SENSE_MASK to fully
define the irq type/polarity and provide a set_irq_type() callback.

Also, beware that you cannot call set_irq_chip_and_handler() from within
set_irq_type() due to a spinlock recursion issue. There is a patch
floating on the list for IPIC fixing an issue of that sort, you may want
to have a look.

In general, look at what others are doing, notably mpic and ipic.

You can also keep IRQ_LEVEL in "sync" with the other polarity bits, it's
really only useful to display the polarity in /proc/interrupts.

Note that your map code would always OR the bit, never clear it. It
should have probably cleared it before the switch/case.

> +void mpc52xx_irqhost_unmap(struct irq_host *h, unsigned int virq)
> +{
> +	pr_debug("%s: v=%x\n", __func__, virq);
> +
> +	mpc52xx_ic_mask(virq);
> +	set_irq_chip_and_handler(virq, NULL, NULL);
> +	synchronize_irq(virq);
> +}

The common code will do all of the above. Your unmap can be empty. (Or
just don't do an unmap).

> +static struct irq_host_ops mpc52xx_irqhost_ops = {
> +	.match = mpc52xx_irqhost_match,
> +	.xlate = mpc52xx_irqhost_xlate,
> +	.map = mpc52xx_irqhost_map,
> +	.unmap = mpc52xx_irqhost_unmap,
> +};
> +
> +void __init mpc52xx_init_irq(void)
> +{
> +	int i;
> +	u32 intr_ctrl;
> +
> +	/* Remap the necessary zones */
> +	intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
> +	sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
> +
> +	if ((intr == NULL) || (sdma == NULL))
> +		panic("Can't ioremap PIC/SDMA register or init_irq !");
> +
> +	/* 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);
> +	/* Initialize irq_desc[i].handler's with mpc52xx_ic. */
> +	for (i = 0; i < NR_IRQS; i++) {
> +		irq_desc[i].chip = &mpc52xx_irqchip;
> +		irq_desc[i].status = IRQ_LEVEL;
> +
> +	}

The above is completely bogus and should be just removed. You should not
touch the irq_desc array. You should only ever modify irq_desc's that
have been assigned to you by your host->map callback.

> +	/*
> +	 * 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, NR_IRQS, &mpc52xx_irqhost_ops,
> +			   -1);
> +}

As I said before, NR_IRQ is a poor choice for the size of the revmap.
You should have a constant somewhere defining what is your max HW irq
number. and use that +1, or a hw irq count.
> --- a/arch/powerpc/platforms/chrp/setup.c	2006-10-25 19:07:23.000000000 +0200
> +++ b/arch/powerpc/platforms/chrp/setup.c	2006-10-27 16:08:03.000000000 +0200
> @@ -51,6 +51,7 @@
>  #include <asm/mpic.h>
>  #include <asm/rtas.h>
>  #include <asm/xmon.h>
> +#include <asm/mpc52xx.h>
>  
>  #include "chrp.h"
>  
> @@ -435,6 +436,18 @@ static struct irqaction xmon_irqaction =
>  };
>  #endif
>  
> +static int __init chrp_find_mpc52xx_pic(void)
> +{
> +	if (find_mpc52xx_picnode()) {
> +		printk(KERN_INFO "Found MPC52xx Interrupt Controller\n");
> +		ppc_md.get_irq = mpc52xx_get_irq;
> +		mpc52xx_init_irq();
> +		return 0;
> +	}
> +
> +	return -ENODEV;
> +}

Just get rif of find_mpic53xx_picnode. Do it locally and pass the device
node to mpc52xx_init_irq().

>  static void __init chrp_find_8259(void)
>  {
>  	struct device_node *np, *pic = NULL;
> @@ -496,6 +509,7 @@ void __init chrp_init_IRQ(void)
>  #endif
>  	chrp_find_openpic();
>  	chrp_find_8259();
> +	chrp_find_mpc52xx_pic();
>  
>  #ifdef CONFIG_SMP
>  	/* Pegasos has no MPIC, those ops would make it crash. It might be an
> diff -uprN a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
> --- a/include/asm-powerpc/mpc52xx.h	1970-01-01 01:00:00.000000000 +0100
> +++ b/include/asm-powerpc/mpc52xx.h	2006-10-27 15:51:55.000000000 +0200
> @@ -0,0 +1,414 @@
> +/*
> + * include/asm-powerpc/mpc52xx.h
> + * 
> + * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
> + * May need to be cleaned as the port goes on ...
> + *
> + *
> + * Maintainer : Sylvain Munaut <tnt@246tNt.com>
> + *
> + * Originally written by Dale Farnsworth <dfarnsworth@mvista.com> 
> + * for the 2.4 kernel.
> + *
> + * 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__ */
> +
> +
> +#ifdef CONFIG_PCI
> +#define _IO_BASE	isa_io_base
> +#define _ISA_MEM_BASE	isa_mem_base
> +#define PCI_DRAM_OFFSET	pci_dram_offset
> +#else
> +#define _IO_BASE	0
> +#define _ISA_MEM_BASE	0
> +#define PCI_DRAM_OFFSET	0
> +#endif

Remove all of the above, it's bogus. You don't want to touch those
things when CONFIG_MULTIPLATFORM. (That is, they are variables set
programmatically, you can't just go #define them and common code already
takes care of defining them anyway).

Ben.

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

* Re: [PATCH] General CHRP/MPC5K2 platform support patch
  2006-10-27 17:08                     ` Jon Loeliger
@ 2006-10-28  0:27                       ` Stephen Rothwell
  0 siblings, 0 replies; 40+ messages in thread
From: Stephen Rothwell @ 2006-10-28  0:27 UTC (permalink / raw)
  To: Jon Loeliger
  Cc: akpm, sl, linuxppc-dev@ozlabs.org, linuxppc-embedded@ozlabs.org,
	sha

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

On Fri, 27 Oct 2006 12:08:46 -0500 Jon Loeliger <jdl@freescale.com> wrote:
>
> On Fri, 2006-10-27 at 10:04, Nicolas DET wrote:
>
> > > diff -uprN a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
> > > --- a/include/asm-powerpc/mpc52xx.h	1970-01-01 01:00:00.000000000 +0100
> > > +++ b/include/asm-powerpc/mpc52xx.h	2006-10-27 15:51:55.000000000 +0200
> > > @@ -0,0 +1,414 @@
> > > +/*
> > > + * include/asm-ppc/mpc52xx.h
> > > + *
> >
> > Fixed to powerpc
>
> I thought we were removing the names of files from
> within the file itself, right?

Correct. They add nothing and become stale.

--
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

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

end of thread, other threads:[~2006-10-28  0:27 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-25 19:05 [PATCH] General CHRP/MPC5K2 platform support patch Nicolas DET
2006-10-25 21:59 ` Paul Mackerras
2006-10-25 22:41   ` Grant Likely
2006-10-25 22:59     ` Benjamin Herrenschmidt
2006-10-26 11:09       ` Nicolas DET
2006-10-26 11:17     ` Nicolas DET
2006-10-25 22:53 ` Benjamin Herrenschmidt
2006-10-26 11:09   ` Nicolas DET
2006-10-26 12:49     ` Benjamin Herrenschmidt
2006-10-26 12:59       ` Nicolas DET
2006-10-26 16:02         ` Grant Likely
2006-10-26 16:09           ` Grant Likely
2006-10-26 17:06             ` Nicolas DET
2006-10-26 17:54               ` Sylvain Munaut
2006-10-27  3:08                 ` Benjamin Herrenschmidt
2006-10-26 19:14               ` Grant Likely
2006-10-26 19:21                 ` Nicolas DET
2006-10-26 19:32                   ` Nicolas DET
2006-10-27  2:49               ` Benjamin Herrenschmidt
2006-10-26 16:45           ` Sven Luther
2006-10-26 19:50           ` Nicolas DET
2006-10-26 20:00             ` Grant Likely
2006-10-26 20:51               ` Sylvain Munaut
2006-10-27  3:28               ` Benjamin Herrenschmidt
2006-10-27 14:52                 ` Nicolas DET
2006-10-27 15:04                   ` Nicolas DET
2006-10-27 17:08                     ` Jon Loeliger
2006-10-28  0:27                       ` Stephen Rothwell
2006-10-27 22:34                     ` Benjamin Herrenschmidt
2006-10-27 22:05                   ` Sylvain Munaut
2006-10-25 23:01 ` Grant Likely
2006-10-25 23:06   ` Benjamin Herrenschmidt
2006-10-25 23:13     ` Sven Luther
2006-10-26 12:09     ` Nicolas DET
2006-10-26 12:51       ` Benjamin Herrenschmidt
2006-10-26 17:17 ` John Rigby
2006-10-26 17:23   ` Nicolas DET
2006-10-26 17:33   ` Sylvain Munaut
2006-10-27  3:03     ` Benjamin Herrenschmidt
2006-10-27  2:57   ` Benjamin Herrenschmidt

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).