--- 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 + * + * 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. + */ + +#undef DEBUG + +#include +#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_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 #include #include +#include #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 + * + * Originally written by Dale Farnsworth + * for the 2.4 kernel. + * + * Copyright (C) 2004-2005 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. + */ + +#ifndef __ASM_POWERPC_MPC52xx_H__ +#define __ASM_POWERPC_MPC52xx_H__ + +#ifndef __ASSEMBLY__ +#include +#include + +#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__ */