Grant Likely wrote:
On 10/26/06, Grant Likely <[EMAIL PROTECTED]> wrote:
On 10/26/06, Nicolas DET <[EMAIL PROTECTED]> 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,
--- 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 <[EMAIL PROTECTED]>
+ *
+ * Based on (well, mostly copied from) the code from the 2.4 kernel by
+ * Dale Farnsworth <[EMAIL PROTECTED]> and Kent Borg.
+ * 
+ * Copyright (C) 2004 Sylvain Munaut <[EMAIL PROTECTED]>
+ * 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);
begin:vcard
fn:Nicolas DET ( bplan GmbH )
n:DET;Nicolas
org:bplan GmbH
adr:;;;;;;Germany
email;internet:[EMAIL PROTECTED]
title:Software Entwicklung
tel;work:+49 6171 9187 - 31
x-mozilla-html:FALSE
url:http://www.bplan-gmbh.de
version:2.1
end:vcard

_______________________________________________
Linuxppc-embedded mailing list
[email protected]
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

Reply via email to