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 #include #include +#include #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 + * + * Based on (well, mostly copied from) the code from the 2.4 kernel by + * Dale Farnsworth and Kent Borg. + * + * Copyright (C) 2004 Sylvain Munaut + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +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