aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/86xx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/86xx')
-rw-r--r--arch/powerpc/platforms/86xx/Kconfig75
-rw-r--r--arch/powerpc/platforms/86xx/Makefile7
-rw-r--r--arch/powerpc/platforms/86xx/gef_ppc9a.c246
-rw-r--r--arch/powerpc/platforms/86xx/gef_sbc310.c233
-rw-r--r--arch/powerpc/platforms/86xx/gef_sbc610.c223
-rw-r--r--arch/powerpc/platforms/86xx/mpc8610_hpcd.c359
-rw-r--r--arch/powerpc/platforms/86xx/mpc8641_hpcn.h21
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx.h13
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c387
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_smp.c23
-rw-r--r--arch/powerpc/platforms/86xx/pci.c205
-rw-r--r--arch/powerpc/platforms/86xx/pic.c71
-rw-r--r--arch/powerpc/platforms/86xx/sbc8641d.c124
13 files changed, 1390 insertions, 597 deletions
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index d1bcff50046..1afd1e4a2dd 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -1,21 +1,80 @@
-choice
- prompt "Machine Type"
- depends on PPC_86xx
- default MPC8641_HPCN
+config PPC_86xx
+menuconfig PPC_86xx
+ bool "86xx-based boards"
+ depends on 6xx
+ select FSL_SOC
+ select ALTIVEC
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+ help
+ The Freescale E600 SoCs have 74xx cores.
+
+if PPC_86xx
config MPC8641_HPCN
bool "Freescale MPC8641 HPCN"
select PPC_I8259
select DEFAULT_UIMAGE
+ select FSL_ULI1575 if PCI
+ select HAS_RAPIDIO
+ select SWIOTLB
help
This option enables support for the MPC8641 HPCN board.
-endchoice
+config SBC8641D
+ bool "Wind River SBC8641D"
+ select DEFAULT_UIMAGE
+ help
+ This option enables support for the WRS SBC8641D board.
+
+config MPC8610_HPCD
+ bool "Freescale MPC8610 HPCD"
+ select DEFAULT_UIMAGE
+ select FSL_ULI1575 if PCI
+ help
+ This option enables support for the MPC8610 HPCD board.
+
+config GEF_PPC9A
+ bool "GE PPC9A"
+ select DEFAULT_UIMAGE
+ select MMIO_NVRAM
+ select ARCH_REQUIRE_GPIOLIB
+ select GE_FPGA
+ help
+ This option enables support for the GE PPC9A.
+
+config GEF_SBC310
+ bool "GE SBC310"
+ select DEFAULT_UIMAGE
+ select MMIO_NVRAM
+ select ARCH_REQUIRE_GPIOLIB
+ select GE_FPGA
+ help
+ This option enables support for the GE SBC310.
+
+config GEF_SBC610
+ bool "GE SBC610"
+ select DEFAULT_UIMAGE
+ select MMIO_NVRAM
+ select ARCH_REQUIRE_GPIOLIB
+ select GE_FPGA
+ select HAS_RAPIDIO
+ help
+ This option enables support for the GE SBC610.
+
+endif
config MPC8641
bool
- select PPC_INDIRECT_PCI
- select PPC_INDIRECT_PCI_BE
+ select PPC_PCI_CHOICE
+ select FSL_PCI if PCI
+ select PPC_UDBG_16550
+ select MPIC
+ default y if MPC8641_HPCN || SBC8641D || GEF_SBC610 || GEF_SBC310 || GEF_PPC9A
+
+config MPC8610
+ bool
+ select PPC_PCI_CHOICE
+ select FSL_PCI if PCI
select PPC_UDBG_16550
select MPIC
- default y if MPC8641_HPCN
+ default y if MPC8610_HPCD
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
index 418fd8f4d26..ede815d6489 100644
--- a/arch/powerpc/platforms/86xx/Makefile
+++ b/arch/powerpc/platforms/86xx/Makefile
@@ -2,6 +2,11 @@
# Makefile for the PowerPC 86xx linux kernel.
#
+obj-y := pic.o
obj-$(CONFIG_SMP) += mpc86xx_smp.o
obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o
-obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_SBC8641D) += sbc8641d.o
+obj-$(CONFIG_MPC8610_HPCD) += mpc8610_hpcd.o
+obj-$(CONFIG_GEF_SBC610) += gef_sbc610.o
+obj-$(CONFIG_GEF_SBC310) += gef_sbc310.o
+obj-$(CONFIG_GEF_PPC9A) += gef_ppc9a.o
diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c
new file mode 100644
index 00000000000..c23f3443880
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c
@@ -0,0 +1,246 @@
+/*
+ * GE PPC9A board support
+ *
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ *
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Based on: mpc86xx_hpcn.c (MPC86xx HPCN board specific routines)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * NEC fixup adapted from arch/mips/pci/fixup-lm2e.c
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/of_platform.h>
+
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+
+#include <asm/mpic.h>
+#include <asm/nvram.h>
+
+#include <sysdev/fsl_pci.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/ge/ge_pic.h>
+
+#include "mpc86xx.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG (fmt...) do { printk(KERN_ERR "PPC9A: " fmt); } while (0)
+#else
+#define DBG (fmt...) do { } while (0)
+#endif
+
+void __iomem *ppc9a_regs;
+
+static void __init gef_ppc9a_init_irq(void)
+{
+ struct device_node *cascade_node = NULL;
+
+ mpc86xx_init_irq();
+
+ /*
+ * There is a simple interrupt handler in the main FPGA, this needs
+ * to be cascaded into the MPIC
+ */
+ cascade_node = of_find_compatible_node(NULL, NULL, "gef,fpga-pic-1.00");
+ if (!cascade_node) {
+ printk(KERN_WARNING "PPC9A: No FPGA PIC\n");
+ return;
+ }
+
+ gef_pic_init(cascade_node);
+ of_node_put(cascade_node);
+}
+
+static void __init gef_ppc9a_setup_arch(void)
+{
+ struct device_node *regs;
+
+ printk(KERN_INFO "GE Intelligent Platforms PPC9A 6U VME SBC\n");
+
+#ifdef CONFIG_SMP
+ mpc86xx_smp_init();
+#endif
+
+ fsl_pci_assign_primary();
+
+ /* Remap basic board registers */
+ regs = of_find_compatible_node(NULL, NULL, "gef,ppc9a-fpga-regs");
+ if (regs) {
+ ppc9a_regs = of_iomap(regs, 0);
+ if (ppc9a_regs == NULL)
+ printk(KERN_WARNING "Unable to map board registers\n");
+ of_node_put(regs);
+ }
+
+#if defined(CONFIG_MMIO_NVRAM)
+ mmio_nvram_init();
+#endif
+}
+
+/* Return the PCB revision */
+static unsigned int gef_ppc9a_get_pcb_rev(void)
+{
+ unsigned int reg;
+
+ reg = ioread32be(ppc9a_regs);
+ return (reg >> 16) & 0xff;
+}
+
+/* Return the board (software) revision */
+static unsigned int gef_ppc9a_get_board_rev(void)
+{
+ unsigned int reg;
+
+ reg = ioread32be(ppc9a_regs);
+ return (reg >> 8) & 0xff;
+}
+
+/* Return the FPGA revision */
+static unsigned int gef_ppc9a_get_fpga_rev(void)
+{
+ unsigned int reg;
+
+ reg = ioread32be(ppc9a_regs);
+ return reg & 0xf;
+}
+
+/* Return VME Geographical Address */
+static unsigned int gef_ppc9a_get_vme_geo_addr(void)
+{
+ unsigned int reg;
+
+ reg = ioread32be(ppc9a_regs + 0x4);
+ return reg & 0x1f;
+}
+
+/* Return VME System Controller Status */
+static unsigned int gef_ppc9a_get_vme_is_syscon(void)
+{
+ unsigned int reg;
+
+ reg = ioread32be(ppc9a_regs + 0x4);
+ return (reg >> 9) & 0x1;
+}
+
+static void gef_ppc9a_show_cpuinfo(struct seq_file *m)
+{
+ uint svid = mfspr(SPRN_SVR);
+
+ seq_printf(m, "Vendor\t\t: GE Intelligent Platforms\n");
+
+ seq_printf(m, "Revision\t: %u%c\n", gef_ppc9a_get_pcb_rev(),
+ ('A' + gef_ppc9a_get_board_rev()));
+ seq_printf(m, "FPGA Revision\t: %u\n", gef_ppc9a_get_fpga_rev());
+
+ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+ seq_printf(m, "VME geo. addr\t: %u\n", gef_ppc9a_get_vme_geo_addr());
+
+ seq_printf(m, "VME syscon\t: %s\n",
+ gef_ppc9a_get_vme_is_syscon() ? "yes" : "no");
+}
+
+static void gef_ppc9a_nec_fixup(struct pci_dev *pdev)
+{
+ unsigned int val;
+
+ /* Do not do the fixup on other platforms! */
+ if (!machine_is(gef_ppc9a))
+ return;
+
+ printk(KERN_INFO "Running NEC uPD720101 Fixup\n");
+
+ /* Ensure ports 1, 2, 3, 4 & 5 are enabled */
+ pci_read_config_dword(pdev, 0xe0, &val);
+ pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x5);
+
+ /* System clock is 48-MHz Oscillator and EHCI Enabled. */
+ pci_write_config_dword(pdev, 0xe4, 1 << 5);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+ gef_ppc9a_nec_fixup);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ *
+ * This function is called to determine whether the BSP is compatible with the
+ * supplied device-tree, which is assumed to be the correct one for the actual
+ * board. It is expected thati, in the future, a kernel may support multiple
+ * boards.
+ */
+static int __init gef_ppc9a_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (of_flat_dt_is_compatible(root, "gef,ppc9a"))
+ return 1;
+
+ return 0;
+}
+
+static long __init mpc86xx_time_init(void)
+{
+ unsigned int temp;
+
+ /* Set the time base to zero */
+ mtspr(SPRN_TBWL, 0);
+ mtspr(SPRN_TBWU, 0);
+
+ temp = mfspr(SPRN_HID0);
+ temp |= HID0_TBEN;
+ mtspr(SPRN_HID0, temp);
+ asm volatile("isync");
+
+ return 0;
+}
+
+static __initdata struct of_device_id of_bus_ids[] = {
+ { .compatible = "simple-bus", },
+ { .compatible = "gianfar", },
+ { .compatible = "fsl,mpc8641-pcie", },
+ {},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+ printk(KERN_DEBUG "Probe platform devices\n");
+ of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+ return 0;
+}
+machine_arch_initcall(gef_ppc9a, declare_of_platform_devices);
+
+define_machine(gef_ppc9a) {
+ .name = "GE PPC9A",
+ .probe = gef_ppc9a_probe,
+ .setup_arch = gef_ppc9a_setup_arch,
+ .init_IRQ = gef_ppc9a_init_irq,
+ .show_cpuinfo = gef_ppc9a_show_cpuinfo,
+ .get_irq = mpic_get_irq,
+ .restart = fsl_rstcr_restart,
+ .time_init = mpc86xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+};
diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c
new file mode 100644
index 00000000000..8a6ac20686e
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/gef_sbc310.c
@@ -0,0 +1,233 @@
+/*
+ * GE SBC310 board support
+ *
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ *
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Based on: mpc86xx_hpcn.c (MPC86xx HPCN board specific routines)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * NEC fixup adapted from arch/mips/pci/fixup-lm2e.c
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/of_platform.h>
+
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+
+#include <asm/mpic.h>
+#include <asm/nvram.h>
+
+#include <sysdev/fsl_pci.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/ge/ge_pic.h>
+
+#include "mpc86xx.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG (fmt...) do { printk(KERN_ERR "SBC310: " fmt); } while (0)
+#else
+#define DBG (fmt...) do { } while (0)
+#endif
+
+void __iomem *sbc310_regs;
+
+static void __init gef_sbc310_init_irq(void)
+{
+ struct device_node *cascade_node = NULL;
+
+ mpc86xx_init_irq();
+
+ /*
+ * There is a simple interrupt handler in the main FPGA, this needs
+ * to be cascaded into the MPIC
+ */
+ cascade_node = of_find_compatible_node(NULL, NULL, "gef,fpga-pic");
+ if (!cascade_node) {
+ printk(KERN_WARNING "SBC310: No FPGA PIC\n");
+ return;
+ }
+
+ gef_pic_init(cascade_node);
+ of_node_put(cascade_node);
+}
+
+static void __init gef_sbc310_setup_arch(void)
+{
+ struct device_node *regs;
+ printk(KERN_INFO "GE Intelligent Platforms SBC310 6U VPX SBC\n");
+
+#ifdef CONFIG_SMP
+ mpc86xx_smp_init();
+#endif
+
+ fsl_pci_assign_primary();
+
+ /* Remap basic board registers */
+ regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
+ if (regs) {
+ sbc310_regs = of_iomap(regs, 0);
+ if (sbc310_regs == NULL)
+ printk(KERN_WARNING "Unable to map board registers\n");
+ of_node_put(regs);
+ }
+
+#if defined(CONFIG_MMIO_NVRAM)
+ mmio_nvram_init();
+#endif
+}
+
+/* Return the PCB revision */
+static unsigned int gef_sbc310_get_board_id(void)
+{
+ unsigned int reg;
+
+ reg = ioread32(sbc310_regs);
+ return reg & 0xff;
+}
+
+/* Return the PCB revision */
+static unsigned int gef_sbc310_get_pcb_rev(void)
+{
+ unsigned int reg;
+
+ reg = ioread32(sbc310_regs);
+ return (reg >> 8) & 0xff;
+}
+
+/* Return the board (software) revision */
+static unsigned int gef_sbc310_get_board_rev(void)
+{
+ unsigned int reg;
+
+ reg = ioread32(sbc310_regs);
+ return (reg >> 16) & 0xff;
+}
+
+/* Return the FPGA revision */
+static unsigned int gef_sbc310_get_fpga_rev(void)
+{
+ unsigned int reg;
+
+ reg = ioread32(sbc310_regs);
+ return (reg >> 24) & 0xf;
+}
+
+static void gef_sbc310_show_cpuinfo(struct seq_file *m)
+{
+ uint svid = mfspr(SPRN_SVR);
+
+ seq_printf(m, "Vendor\t\t: GE Intelligent Platforms\n");
+
+ seq_printf(m, "Board ID\t: 0x%2.2x\n", gef_sbc310_get_board_id());
+ seq_printf(m, "Revision\t: %u%c\n", gef_sbc310_get_pcb_rev(),
+ ('A' + gef_sbc310_get_board_rev() - 1));
+ seq_printf(m, "FPGA Revision\t: %u\n", gef_sbc310_get_fpga_rev());
+
+ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+}
+
+static void gef_sbc310_nec_fixup(struct pci_dev *pdev)
+{
+ unsigned int val;
+
+ /* Do not do the fixup on other platforms! */
+ if (!machine_is(gef_sbc310))
+ return;
+
+ printk(KERN_INFO "Running NEC uPD720101 Fixup\n");
+
+ /* Ensure only ports 1 & 2 are enabled */
+ pci_read_config_dword(pdev, 0xe0, &val);
+ pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x2);
+
+ /* System clock is 48-MHz Oscillator and EHCI Enabled. */
+ pci_write_config_dword(pdev, 0xe4, 1 << 5);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+ gef_sbc310_nec_fixup);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ *
+ * This function is called to determine whether the BSP is compatible with the
+ * supplied device-tree, which is assumed to be the correct one for the actual
+ * board. It is expected thati, in the future, a kernel may support multiple
+ * boards.
+ */
+static int __init gef_sbc310_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (of_flat_dt_is_compatible(root, "gef,sbc310"))
+ return 1;
+
+ return 0;
+}
+
+static long __init mpc86xx_time_init(void)
+{
+ unsigned int temp;
+
+ /* Set the time base to zero */
+ mtspr(SPRN_TBWL, 0);
+ mtspr(SPRN_TBWU, 0);
+
+ temp = mfspr(SPRN_HID0);
+ temp |= HID0_TBEN;
+ mtspr(SPRN_HID0, temp);
+ asm volatile("isync");
+
+ return 0;
+}
+
+static __initdata struct of_device_id of_bus_ids[] = {
+ { .compatible = "simple-bus", },
+ { .compatible = "gianfar", },
+ { .compatible = "fsl,mpc8641-pcie", },
+ {},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+ printk(KERN_DEBUG "Probe platform devices\n");
+ of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+ return 0;
+}
+machine_arch_initcall(gef_sbc310, declare_of_platform_devices);
+
+define_machine(gef_sbc310) {
+ .name = "GE SBC310",
+ .probe = gef_sbc310_probe,
+ .setup_arch = gef_sbc310_setup_arch,
+ .init_IRQ = gef_sbc310_init_irq,
+ .show_cpuinfo = gef_sbc310_show_cpuinfo,
+ .get_irq = mpic_get_irq,
+ .restart = fsl_rstcr_restart,
+ .time_init = mpc86xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+};
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
new file mode 100644
index 00000000000..06c72636f29
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/gef_sbc610.c
@@ -0,0 +1,223 @@
+/*
+ * GE SBC610 board support
+ *
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ *
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Based on: mpc86xx_hpcn.c (MPC86xx HPCN board specific routines)
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * NEC fixup adapted from arch/mips/pci/fixup-lm2e.c
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/of_platform.h>
+
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+
+#include <asm/mpic.h>
+#include <asm/nvram.h>
+
+#include <sysdev/fsl_pci.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/ge/ge_pic.h>
+
+#include "mpc86xx.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG (fmt...) do { printk(KERN_ERR "SBC610: " fmt); } while (0)
+#else
+#define DBG (fmt...) do { } while (0)
+#endif
+
+void __iomem *sbc610_regs;
+
+static void __init gef_sbc610_init_irq(void)
+{
+ struct device_node *cascade_node = NULL;
+
+ mpc86xx_init_irq();
+
+ /*
+ * There is a simple interrupt handler in the main FPGA, this needs
+ * to be cascaded into the MPIC
+ */
+ cascade_node = of_find_compatible_node(NULL, NULL, "gef,fpga-pic");
+ if (!cascade_node) {
+ printk(KERN_WARNING "SBC610: No FPGA PIC\n");
+ return;
+ }
+
+ gef_pic_init(cascade_node);
+ of_node_put(cascade_node);
+}
+
+static void __init gef_sbc610_setup_arch(void)
+{
+ struct device_node *regs;
+
+ printk(KERN_INFO "GE Intelligent Platforms SBC610 6U VPX SBC\n");
+
+#ifdef CONFIG_SMP
+ mpc86xx_smp_init();
+#endif
+
+ fsl_pci_assign_primary();
+
+ /* Remap basic board registers */
+ regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
+ if (regs) {
+ sbc610_regs = of_iomap(regs, 0);
+ if (sbc610_regs == NULL)
+ printk(KERN_WARNING "Unable to map board registers\n");
+ of_node_put(regs);
+ }
+
+#if defined(CONFIG_MMIO_NVRAM)
+ mmio_nvram_init();
+#endif
+}
+
+/* Return the PCB revision */
+static unsigned int gef_sbc610_get_pcb_rev(void)
+{
+ unsigned int reg;
+
+ reg = ioread32(sbc610_regs);
+ return (reg >> 8) & 0xff;
+}
+
+/* Return the board (software) revision */
+static unsigned int gef_sbc610_get_board_rev(void)
+{
+ unsigned int reg;
+
+ reg = ioread32(sbc610_regs);
+ return (reg >> 16) & 0xff;
+}
+
+/* Return the FPGA revision */
+static unsigned int gef_sbc610_get_fpga_rev(void)
+{
+ unsigned int reg;
+
+ reg = ioread32(sbc610_regs);
+ return (reg >> 24) & 0xf;
+}
+
+static void gef_sbc610_show_cpuinfo(struct seq_file *m)
+{
+ uint svid = mfspr(SPRN_SVR);
+
+ seq_printf(m, "Vendor\t\t: GE Intelligent Platforms\n");
+
+ seq_printf(m, "Revision\t: %u%c\n", gef_sbc610_get_pcb_rev(),
+ ('A' + gef_sbc610_get_board_rev() - 1));
+ seq_printf(m, "FPGA Revision\t: %u\n", gef_sbc610_get_fpga_rev());
+
+ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+}
+
+static void gef_sbc610_nec_fixup(struct pci_dev *pdev)
+{
+ unsigned int val;
+
+ /* Do not do the fixup on other platforms! */
+ if (!machine_is(gef_sbc610))
+ return;
+
+ printk(KERN_INFO "Running NEC uPD720101 Fixup\n");
+
+ /* Ensure ports 1, 2, 3, 4 & 5 are enabled */
+ pci_read_config_dword(pdev, 0xe0, &val);
+ pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x5);
+
+ /* System clock is 48-MHz Oscillator and EHCI Enabled. */
+ pci_write_config_dword(pdev, 0xe4, 1 << 5);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+ gef_sbc610_nec_fixup);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ *
+ * This function is called to determine whether the BSP is compatible with the
+ * supplied device-tree, which is assumed to be the correct one for the actual
+ * board. It is expected thati, in the future, a kernel may support multiple
+ * boards.
+ */
+static int __init gef_sbc610_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (of_flat_dt_is_compatible(root, "gef,sbc610"))
+ return 1;
+
+ return 0;
+}
+
+static long __init mpc86xx_time_init(void)
+{
+ unsigned int temp;
+
+ /* Set the time base to zero */
+ mtspr(SPRN_TBWL, 0);
+ mtspr(SPRN_TBWU, 0);
+
+ temp = mfspr(SPRN_HID0);
+ temp |= HID0_TBEN;
+ mtspr(SPRN_HID0, temp);
+ asm volatile("isync");
+
+ return 0;
+}
+
+static __initdata struct of_device_id of_bus_ids[] = {
+ { .compatible = "simple-bus", },
+ { .compatible = "gianfar", },
+ { .compatible = "fsl,mpc8641-pcie", },
+ {},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+ printk(KERN_DEBUG "Probe platform devices\n");
+ of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+ return 0;
+}
+machine_arch_initcall(gef_sbc610, declare_of_platform_devices);
+
+define_machine(gef_sbc610) {
+ .name = "GE SBC610",
+ .probe = gef_sbc610_probe,
+ .setup_arch = gef_sbc610_setup_arch,
+ .init_IRQ = gef_sbc610_init_irq,
+ .show_cpuinfo = gef_sbc610_show_cpuinfo,
+ .get_irq = mpic_get_irq,
+ .restart = fsl_rstcr_restart,
+ .time_init = mpc86xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+};
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
new file mode 100644
index 00000000000..d479d68fbb2
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -0,0 +1,359 @@
+/*
+ * MPC8610 HPCD board specific routines
+ *
+ * Initial author: Xianghua Xiao <x.xiao@freescale.com>
+ * Recode: Jason Jin <jason.jin@freescale.com>
+ * York Sun <yorksun@freescale.com>
+ *
+ * Rewrite the interrupt routing. remove the 8259PIC support,
+ * All the integrated device in ULI use sideband interrupt.
+ *
+ * Copyright 2008 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/of.h>
+
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+
+#include <asm/mpic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_pci.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/simple_gpio.h>
+#include <asm/fsl_guts.h>
+
+#include "mpc86xx.h"
+
+static struct device_node *pixis_node;
+static unsigned char *pixis_bdcfg0, *pixis_arch;
+
+/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
+#define CLKDVDR_PXCKEN 0x80000000
+#define CLKDVDR_PXCKINV 0x10000000
+#define CLKDVDR_PXCKDLY 0x06000000
+#define CLKDVDR_PXCLK_MASK 0x001F0000
+
+#ifdef CONFIG_SUSPEND
+static irqreturn_t mpc8610_sw9_irq(int irq, void *data)
+{
+ pr_debug("%s: PIXIS' event (sw9/wakeup) IRQ handled\n", __func__);
+ return IRQ_HANDLED;
+}
+
+static void __init mpc8610_suspend_init(void)
+{
+ int irq;
+ int ret;
+
+ if (!pixis_node)
+ return;
+
+ irq = irq_of_parse_and_map(pixis_node, 0);
+ if (!irq) {
+ pr_err("%s: can't map pixis event IRQ.\n", __func__);
+ return;
+ }
+
+ ret = request_irq(irq, mpc8610_sw9_irq, 0, "sw9:wakeup", NULL);
+ if (ret) {
+ pr_err("%s: can't request pixis event IRQ: %d\n",
+ __func__, ret);
+ irq_dispose_mapping(irq);
+ }
+
+ enable_irq_wake(irq);
+}
+#else
+static inline void mpc8610_suspend_init(void) { }
+#endif /* CONFIG_SUSPEND */
+
+static struct of_device_id __initdata mpc8610_ids[] = {
+ { .compatible = "fsl,mpc8610-immr", },
+ { .compatible = "fsl,mpc8610-guts", },
+ { .compatible = "simple-bus", },
+ /* So that the DMA channel nodes can be probed individually: */
+ { .compatible = "fsl,eloplus-dma", },
+ /* PCI controllers */
+ { .compatible = "fsl,mpc8610-pci", },
+ { .compatible = "fsl,mpc8641-pcie", },
+ {}
+};
+
+static int __init mpc8610_declare_of_platform_devices(void)
+{
+ /* Firstly, register PIXIS GPIOs. */
+ simple_gpiochip_init("fsl,fpga-pixis-gpio-bank");
+
+ /* Enable wakeup on PIXIS' event IRQ. */
+ mpc8610_suspend_init();
+
+ /* Without this call, the SSI device driver won't get probed. */
+ of_platform_bus_probe(NULL, mpc8610_ids, NULL);
+
+ return 0;
+}
+machine_arch_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
+
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+
+/*
+ * DIU Area Descriptor
+ *
+ * The MPC8610 reference manual shows the bits of the AD register in
+ * little-endian order, which causes the BLUE_C field to be split into two
+ * parts. To simplify the definition of the MAKE_AD() macro, we define the
+ * fields in big-endian order and byte-swap the result.
+ *
+ * So even though the registers don't look like they're in the
+ * same bit positions as they are on the P1022, the same value is written to
+ * the AD register on the MPC8610 and on the P1022.
+ */
+#define AD_BYTE_F 0x10000000
+#define AD_ALPHA_C_MASK 0x0E000000
+#define AD_ALPHA_C_SHIFT 25
+#define AD_BLUE_C_MASK 0x01800000
+#define AD_BLUE_C_SHIFT 23
+#define AD_GREEN_C_MASK 0x00600000
+#define AD_GREEN_C_SHIFT 21
+#define AD_RED_C_MASK 0x00180000
+#define AD_RED_C_SHIFT 19
+#define AD_PALETTE 0x00040000
+#define AD_PIXEL_S_MASK 0x00030000
+#define AD_PIXEL_S_SHIFT 16
+#define AD_COMP_3_MASK 0x0000F000
+#define AD_COMP_3_SHIFT 12
+#define AD_COMP_2_MASK 0x00000F00
+#define AD_COMP_2_SHIFT 8
+#define AD_COMP_1_MASK 0x000000F0
+#define AD_COMP_1_SHIFT 4
+#define AD_COMP_0_MASK 0x0000000F
+#define AD_COMP_0_SHIFT 0
+
+#define MAKE_AD(alpha, red, blue, green, size, c0, c1, c2, c3) \
+ cpu_to_le32(AD_BYTE_F | (alpha << AD_ALPHA_C_SHIFT) | \
+ (blue << AD_BLUE_C_SHIFT) | (green << AD_GREEN_C_SHIFT) | \
+ (red << AD_RED_C_SHIFT) | (c3 << AD_COMP_3_SHIFT) | \
+ (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
+ (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
+
+u32 mpc8610hpcd_get_pixel_format(enum fsl_diu_monitor_port port,
+ unsigned int bits_per_pixel)
+{
+ static const u32 pixelformat[][3] = {
+ {
+ MAKE_AD(3, 0, 2, 1, 3, 8, 8, 8, 8),
+ MAKE_AD(4, 2, 0, 1, 2, 8, 8, 8, 0),
+ MAKE_AD(4, 0, 2, 1, 1, 5, 6, 5, 0)
+ },
+ {
+ MAKE_AD(3, 2, 0, 1, 3, 8, 8, 8, 8),
+ MAKE_AD(4, 0, 2, 1, 2, 8, 8, 8, 0),
+ MAKE_AD(4, 2, 0, 1, 1, 5, 6, 5, 0)
+ },
+ };
+ unsigned int arch_monitor;
+
+ /* The DVI port is mis-wired on revision 1 of this board. */
+ arch_monitor =
+ ((*pixis_arch == 0x01) && (port == FSL_DIU_PORT_DVI)) ? 0 : 1;
+
+ switch (bits_per_pixel) {
+ case 32:
+ return pixelformat[arch_monitor][0];
+ case 24:
+ return pixelformat[arch_monitor][1];
+ case 16:
+ return pixelformat[arch_monitor][2];
+ default:
+ pr_err("fsl-diu: unsupported pixel depth %u\n", bits_per_pixel);
+ return 0;
+ }
+}
+
+void mpc8610hpcd_set_gamma_table(enum fsl_diu_monitor_port port,
+ char *gamma_table_base)
+{
+ int i;
+ if (port == FSL_DIU_PORT_DLVDS) {
+ for (i = 0; i < 256*3; i++)
+ gamma_table_base[i] = (gamma_table_base[i] << 2) |
+ ((gamma_table_base[i] >> 6) & 0x03);
+ }
+}
+
+#define PX_BRDCFG0_DVISEL (1 << 3)
+#define PX_BRDCFG0_DLINK (1 << 4)
+#define PX_BRDCFG0_DIU_MASK (PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK)
+
+void mpc8610hpcd_set_monitor_port(enum fsl_diu_monitor_port port)
+{
+ switch (port) {
+ case FSL_DIU_PORT_DVI:
+ clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
+ PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK);
+ break;
+ case FSL_DIU_PORT_LVDS:
+ clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
+ PX_BRDCFG0_DLINK);
+ break;
+ case FSL_DIU_PORT_DLVDS:
+ clrbits8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK);
+ break;
+ }
+}
+
+/**
+ * mpc8610hpcd_set_pixel_clock: program the DIU's clock
+ *
+ * @pixclock: the wavelength, in picoseconds, of the clock
+ */
+void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
+{
+ struct device_node *guts_np = NULL;
+ struct ccsr_guts __iomem *guts;
+ unsigned long freq;
+ u64 temp;
+ u32 pxclk;
+
+ /* Map the global utilities registers. */
+ guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
+ if (!guts_np) {
+ pr_err("mpc8610hpcd: missing global utilities device node\n");
+ return;
+ }
+
+ guts = of_iomap(guts_np, 0);
+ of_node_put(guts_np);
+ if (!guts) {
+ pr_err("mpc8610hpcd: could not map global utilities device\n");
+ return;
+ }
+
+ /* Convert pixclock from a wavelength to a frequency */
+ temp = 1000000000000ULL;
+ do_div(temp, pixclock);
+ freq = temp;
+
+ /*
+ * 'pxclk' is the ratio of the platform clock to the pixel clock.
+ * On the MPC8610, the value programmed into CLKDVDR is the ratio
+ * minus one. The valid range of values is 2-31.
+ */
+ pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq) - 1;
+ pxclk = clamp_t(u32, pxclk, 2, 31);
+
+ /* Disable the pixel clock, and set it to non-inverted and no delay */
+ clrbits32(&guts->clkdvdr,
+ CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
+
+ /* Enable the clock and set the pxclk */
+ setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
+
+ iounmap(guts);
+}
+
+enum fsl_diu_monitor_port
+mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
+{
+ return port;
+}
+
+#endif
+
+static void __init mpc86xx_hpcd_setup_arch(void)
+{
+ struct resource r;
+ unsigned char *pixis;
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc86xx_hpcd_setup_arch()", 0);
+
+ fsl_pci_assign_primary();
+
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+ diu_ops.get_pixel_format = mpc8610hpcd_get_pixel_format;
+ diu_ops.set_gamma_table = mpc8610hpcd_set_gamma_table;
+ diu_ops.set_monitor_port = mpc8610hpcd_set_monitor_port;
+ diu_ops.set_pixel_clock = mpc8610hpcd_set_pixel_clock;
+ diu_ops.valid_monitor_port = mpc8610hpcd_valid_monitor_port;
+#endif
+
+ pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis");
+ if (pixis_node) {
+ of_address_to_resource(pixis_node, 0, &r);
+ of_node_put(pixis_node);
+ pixis = ioremap(r.start, 32);
+ if (!pixis) {
+ printk(KERN_ERR "Err: can't map FPGA cfg register!\n");
+ return;
+ }
+ pixis_bdcfg0 = pixis + 8;
+ pixis_arch = pixis + 1;
+ } else
+ printk(KERN_ERR "Err: "
+ "can't find device node 'fsl,fpga-pixis'\n");
+
+ printk("MPC86xx HPCD board from Freescale Semiconductor\n");
+}
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc86xx_hpcd_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (of_flat_dt_is_compatible(root, "fsl,MPC8610HPCD"))
+ return 1; /* Looks good */
+
+ return 0;
+}
+
+static long __init mpc86xx_time_init(void)
+{
+ unsigned int temp;
+
+ /* Set the time base to zero */
+ mtspr(SPRN_TBWL, 0);
+ mtspr(SPRN_TBWU, 0);
+
+ temp = mfspr(SPRN_HID0);
+ temp |= HID0_TBEN;
+ mtspr(SPRN_HID0, temp);
+ asm volatile("isync");
+
+ return 0;
+}
+
+define_machine(mpc86xx_hpcd) {
+ .name = "MPC86xx HPCD",
+ .probe = mpc86xx_hpcd_probe,
+ .setup_arch = mpc86xx_hpcd_setup_arch,
+ .init_IRQ = mpc86xx_init_irq,
+ .get_irq = mpic_get_irq,
+ .restart = fsl_rstcr_restart,
+ .time_init = mpc86xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+};
diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
deleted file mode 100644
index 41e554c4af9..00000000000
--- a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * MPC8641 HPCN board definitions
- *
- * Copyright 2006 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Author: Xianghua Xiao <x.xiao@freescale.com>
- */
-
-#ifndef __MPC8641_HPCN_H__
-#define __MPC8641_HPCN_H__
-
-#include <linux/init.h>
-
-#define MPC86XX_RSTCR_OFFSET (0xe00b0) /* Reset Control Register */
-
-#endif /* __MPC8641_HPCN_H__ */
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h
index 2834462590b..08efb57559d 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx.h
+++ b/arch/powerpc/platforms/86xx/mpc86xx.h
@@ -15,16 +15,7 @@
* mpc86xx_* files. Mostly for use by mpc86xx_setup().
*/
-extern int add_bridge(struct device_node *dev);
-
-extern int mpc86xx_exclude_device(u_char bus, u_char devfn);
-
-extern void setup_indirect_pcie(struct pci_controller *hose,
- u32 cfg_addr, u32 cfg_data);
-extern void setup_indirect_pcie_nomap(struct pci_controller *hose,
- void __iomem *cfg_addr,
- void __iomem *cfg_data);
-
-extern void __init mpc86xx_smp_init(void);
+extern void mpc86xx_smp_init(void);
+extern void mpc86xx_init_irq(void);
#endif /* __MPC86XX_H__ */
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 1051702c8d4..e8bf3fae560 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -18,23 +18,22 @@
#include <linux/kdev_t.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
+#include <linux/of_platform.h>
-#include <asm/system.h>
#include <asm/time.h>
#include <asm/machdep.h>
#include <asm/pci-bridge.h>
-#include <asm/mpc86xx.h>
#include <asm/prom.h>
#include <mm/mmu_decl.h>
#include <asm/udbg.h>
-#include <asm/i8259.h>
+#include <asm/swiotlb.h>
#include <asm/mpic.h>
+#include <sysdev/fsl_pci.h>
#include <sysdev/fsl_soc.h>
#include "mpc86xx.h"
-#include "mpc8641_hpcn.h"
#undef DEBUG
@@ -44,328 +43,28 @@
#define DBG(fmt...) do { } while(0)
#endif
-#ifndef CONFIG_PCI
-unsigned long isa_io_base = 0;
-unsigned long isa_mem_base = 0;
-unsigned long pci_dram_offset = 0;
-#endif
-
-
#ifdef CONFIG_PCI
-static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
-{
- unsigned int cascade_irq = i8259_irq();
- if (cascade_irq != NO_IRQ)
- generic_handle_irq(cascade_irq);
- desc->chip->eoi(irq);
-}
-#endif /* CONFIG_PCI */
+extern int uli_exclude_device(struct pci_controller *hose,
+ u_char bus, u_char devfn);
-void __init
-mpc86xx_hpcn_init_irq(void)
+static int mpc86xx_exclude_device(struct pci_controller *hose,
+ u_char bus, u_char devfn)
{
- struct mpic *mpic1;
- struct device_node *np;
- struct resource res;
-#ifdef CONFIG_PCI
- struct device_node *cascade_node = NULL;
- int cascade_irq;
-#endif
-
- /* Determine PIC address. */
- np = of_find_node_by_type(NULL, "open-pic");
- if (np == NULL)
- return;
- of_address_to_resource(np, 0, &res);
-
- /* Alloc mpic structure and per isu has 16 INT entries. */
- mpic1 = mpic_alloc(np, res.start,
- MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
- 16, NR_IRQS - 4,
- " MPIC ");
- BUG_ON(mpic1 == NULL);
-
- mpic_assign_isu(mpic1, 0, res.start + 0x10000);
-
- /* 48 Internal Interrupts */
- mpic_assign_isu(mpic1, 1, res.start + 0x10200);
- mpic_assign_isu(mpic1, 2, res.start + 0x10400);
- mpic_assign_isu(mpic1, 3, res.start + 0x10600);
-
- /* 16 External interrupts
- * Moving them from [0 - 15] to [64 - 79]
- */
- mpic_assign_isu(mpic1, 4, res.start + 0x10000);
-
- mpic_init(mpic1);
-
-#ifdef CONFIG_PCI
- /* Initialize i8259 controller */
- for_each_node_by_type(np, "interrupt-controller")
- if (of_device_is_compatible(np, "chrp,iic")) {
- cascade_node = np;
- break;
- }
- if (cascade_node == NULL) {
- printk(KERN_DEBUG "mpc86xxhpcn: no ISA interrupt controller\n");
- return;
- }
-
- cascade_irq = irq_of_parse_and_map(cascade_node, 0);
- if (cascade_irq == NO_IRQ) {
- printk(KERN_ERR "mpc86xxhpcn: failed to map cascade interrupt");
- return;
- }
- DBG("mpc86xxhpcn: cascade mapped to irq %d\n", cascade_irq);
-
- i8259_init(cascade_node, 0);
- of_node_put(cascade_node);
+ if (hose->dn == fsl_pci_primary)
+ return uli_exclude_device(hose, bus, devfn);
- set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade);
-#endif
-}
-
-#ifdef CONFIG_PCI
-
-enum pirq{PIRQA = 8, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH};
-const unsigned char uli1575_irq_route_table[16] = {
- 0, /* 0: Reserved */
- 0x8, /* 1: 0b1000 */
- 0, /* 2: Reserved */
- 0x2, /* 3: 0b0010 */
- 0x4, /* 4: 0b0100 */
- 0x5, /* 5: 0b0101 */
- 0x7, /* 6: 0b0111 */
- 0x6, /* 7: 0b0110 */
- 0, /* 8: Reserved */
- 0x1, /* 9: 0b0001 */
- 0x3, /* 10: 0b0011 */
- 0x9, /* 11: 0b1001 */
- 0xb, /* 12: 0b1011 */
- 0, /* 13: Reserved */
- 0xd, /* 14, 0b1101 */
- 0xf, /* 15, 0b1111 */
-};
-
-static int __devinit
-get_pci_irq_from_of(struct pci_controller *hose, int slot, int pin)
-{
- struct of_irq oirq;
- u32 laddr[3];
- struct device_node *hosenode = hose ? hose->arch_data : NULL;
-
- if (!hosenode) return -EINVAL;
-
- laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(slot, 0) << 8);
- laddr[1] = laddr[2] = 0;
- of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq);
- DBG("mpc86xx_hpcn: pci irq addr %x, slot %d, pin %d, irq %d\n",
- laddr[0], slot, pin, oirq.specifier[0]);
- return oirq.specifier[0];
-}
-
-static void __devinit quirk_uli1575(struct pci_dev *dev)
-{
- unsigned short temp;
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- unsigned char irq2pin[16], c;
- unsigned long pirq_map_word = 0;
- u32 irq;
- int i;
-
- /*
- * ULI1575 interrupts route setup
- */
- memset(irq2pin, 0, 16); /* Initialize default value 0 */
-
- /*
- * PIRQA -> PIRQD mapping read from OF-tree
- *
- * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
- * PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
- */
- for (i = 0; i < 4; i++){
- irq = get_pci_irq_from_of(hose, 17, i + 1);
- if (irq > 0 && irq < 16)
- irq2pin[irq] = PIRQA + i;
- else
- printk(KERN_WARNING "ULI1575 device"
- "(slot %d, pin %d) irq %d is invalid.\n",
- 17, i, irq);
- }
-
- /*
- * PIRQE -> PIRQF mapping set manually
- *
- * IRQ pin IRQ#
- * PIRQE ---- 9
- * PIRQF ---- 10
- * PIRQG ---- 11
- * PIRQH ---- 12
- */
- for (i = 0; i < 4; i++) irq2pin[i + 9] = PIRQE + i;
-
- /* Set IRQ-PIRQ Mapping to ULI1575 */
- for (i = 0; i < 16; i++)
- if (irq2pin[i])
- pirq_map_word |= (uli1575_irq_route_table[i] & 0xf)
- << ((irq2pin[i] - PIRQA) * 4);
-
- /* ULI1575 IRQ mapping conf register default value is 0xb9317542 */
- DBG("Setup ULI1575 IRQ mapping configuration register value = 0x%x\n",
- pirq_map_word);
- pci_write_config_dword(dev, 0x48, pirq_map_word);
-
-#define ULI1575_SET_DEV_IRQ(slot, pin, reg) \
- do { \
- int irq; \
- irq = get_pci_irq_from_of(hose, slot, pin); \
- if (irq > 0 && irq < 16) \
- pci_write_config_byte(dev, reg, irq2pin[irq]); \
- else \
- printk(KERN_WARNING "ULI1575 device" \
- "(slot %d, pin %d) irq %d is invalid.\n", \
- slot, pin, irq); \
- } while(0)
-
- /* USB 1.1 OHCI controller 1, slot 28, pin 1 */
- ULI1575_SET_DEV_IRQ(28, 1, 0x86);
-
- /* USB 1.1 OHCI controller 2, slot 28, pin 2 */
- ULI1575_SET_DEV_IRQ(28, 2, 0x87);
-
- /* USB 1.1 OHCI controller 3, slot 28, pin 3 */
- ULI1575_SET_DEV_IRQ(28, 3, 0x88);
-
- /* USB 2.0 controller, slot 28, pin 4 */
- irq = get_pci_irq_from_of(hose, 28, 4);
- if (irq >= 0 && irq <=15)
- pci_write_config_dword(dev, 0x74, uli1575_irq_route_table[irq]);
-
- /* Audio controller, slot 29, pin 1 */
- ULI1575_SET_DEV_IRQ(29, 1, 0x8a);
-
- /* Modem controller, slot 29, pin 2 */
- ULI1575_SET_DEV_IRQ(29, 2, 0x8b);
-
- /* HD audio controller, slot 29, pin 3 */
- ULI1575_SET_DEV_IRQ(29, 3, 0x8c);
-
- /* SMB interrupt: slot 30, pin 1 */
- ULI1575_SET_DEV_IRQ(30, 1, 0x8e);
-
- /* PMU ACPI SCI interrupt: slot 30, pin 2 */
- ULI1575_SET_DEV_IRQ(30, 2, 0x8f);
-
- /* Serial ATA interrupt: slot 31, pin 1 */
- ULI1575_SET_DEV_IRQ(31, 1, 0x8d);
-
- /* Primary PATA IDE IRQ: 14
- * Secondary PATA IDE IRQ: 15
- */
- pci_write_config_byte(dev, 0x44, 0x30 | uli1575_irq_route_table[14]);
- pci_write_config_byte(dev, 0x75, uli1575_irq_route_table[15]);
-
- /* Set IRQ14 and IRQ15 to legacy IRQs */
- pci_read_config_word(dev, 0x46, &temp);
- temp |= 0xc000;
- pci_write_config_word(dev, 0x46, temp);
-
- /* Set i8259 interrupt trigger
- * IRQ 3: Level
- * IRQ 4: Level
- * IRQ 5: Level
- * IRQ 6: Level
- * IRQ 7: Level
- * IRQ 9: Level
- * IRQ 10: Level
- * IRQ 11: Level
- * IRQ 12: Level
- * IRQ 14: Edge
- * IRQ 15: Edge
- */
- outb(0xfa, 0x4d0);
- outb(0x1e, 0x4d1);
-
-#undef ULI1575_SET_DEV_IRQ
-
- /* Disable the HD interface and enable the AC97 interface. */
- pci_read_config_byte(dev, 0xb8, &c);
- c &= 0x7f;
- pci_write_config_byte(dev, 0xb8, c);
+ return PCIBIOS_SUCCESSFUL;
}
-
-static void __devinit quirk_uli5288(struct pci_dev *dev)
-{
- unsigned char c;
-
- pci_read_config_byte(dev,0x83,&c);
- c |= 0x80;
- pci_write_config_byte(dev, 0x83, c);
-
- pci_write_config_byte(dev, 0x09, 0x01);
- pci_write_config_byte(dev, 0x0a, 0x06);
-
- pci_read_config_byte(dev,0x83,&c);
- c &= 0x7f;
- pci_write_config_byte(dev, 0x83, c);
-
- pci_read_config_byte(dev,0x84,&c);
- c |= 0x01;
- pci_write_config_byte(dev, 0x84, c);
-}
-
-static void __devinit quirk_uli5229(struct pci_dev *dev)
-{
- unsigned short temp;
- pci_write_config_word(dev, 0x04, 0x0405);
- pci_read_config_word(dev, 0x4a, &temp);
- temp |= 0x1000;
- pci_write_config_word(dev, 0x4a, temp);
-}
-
-static void __devinit early_uli5249(struct pci_dev *dev)
-{
- unsigned char temp;
- pci_write_config_word(dev, 0x04, 0x0007);
- pci_read_config_byte(dev, 0x7c, &temp);
- pci_write_config_byte(dev, 0x7c, 0x80);
- pci_write_config_byte(dev, 0x09, 0x01);
- pci_write_config_byte(dev, 0x7c, temp);
- dev->class |= 0x1;
-}
-
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249);
#endif /* CONFIG_PCI */
static void __init
mpc86xx_hpcn_setup_arch(void)
{
- struct device_node *np;
-
if (ppc_md.progress)
ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
- np = of_find_node_by_type(NULL, "cpu");
- if (np != 0) {
- const unsigned int *fp;
-
- fp = of_get_property(np, "clock-frequency", NULL);
- if (fp != 0)
- loops_per_jiffy = *fp / HZ;
- else
- loops_per_jiffy = 50000000 / HZ;
- of_node_put(np);
- }
-
#ifdef CONFIG_PCI
- for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
- add_bridge(np);
-
ppc_md.pci_exclude_device = mpc86xx_exclude_device;
#endif
@@ -374,27 +73,21 @@ mpc86xx_hpcn_setup_arch(void)
#ifdef CONFIG_SMP
mpc86xx_smp_init();
#endif
+
+ fsl_pci_assign_primary();
+
+ swiotlb_detect_4g();
}
-void
+static void
mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
{
- struct device_node *root;
- uint memsize = total_memory;
- const char *model = "";
uint svid = mfspr(SPRN_SVR);
seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
- root = of_find_node_by_path("/");
- if (root)
- model = of_get_property(root, "model", NULL);
- seq_printf(m, "Machine\t\t: %s\n", model);
- of_node_put(root);
-
seq_printf(m, "SVR\t\t: 0x%x\n", svid);
- seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
}
@@ -405,30 +98,19 @@ static int __init mpc86xx_hpcn_probe(void)
{
unsigned long root = of_get_flat_dt_root();
- if (of_flat_dt_is_compatible(root, "mpc86xx"))
+ if (of_flat_dt_is_compatible(root, "fsl,mpc8641hpcn"))
return 1; /* Looks good */
- return 0;
-}
-
-
-void
-mpc86xx_restart(char *cmd)
-{
- void __iomem *rstcr;
-
- rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100);
-
- local_irq_disable();
-
- /* Assert reset request to Reset Control Register */
- out_be32(rstcr, 0x2);
+ /* Be nice and don't give silent boot death. Delete this in 2.6.27 */
+ if (of_flat_dt_is_compatible(root, "mpc86xx")) {
+ pr_warning("WARNING: your dts/dtb is old. You must update before the next kernel release\n");
+ return 1;
+ }
- /* not reached */
+ return 0;
}
-
-long __init
+static long __init
mpc86xx_time_init(void)
{
unsigned int temp;
@@ -445,16 +127,35 @@ mpc86xx_time_init(void)
return 0;
}
+static __initdata struct of_device_id of_bus_ids[] = {
+ { .compatible = "simple-bus", },
+ { .compatible = "fsl,srio", },
+ { .compatible = "gianfar", },
+ { .compatible = "fsl,mpc8641-pcie", },
+ {},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+ of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+ return 0;
+}
+machine_arch_initcall(mpc86xx_hpcn, declare_of_platform_devices);
+machine_arch_initcall(mpc86xx_hpcn, swiotlb_setup_bus_notifier);
define_machine(mpc86xx_hpcn) {
.name = "MPC86xx HPCN",
.probe = mpc86xx_hpcn_probe,
.setup_arch = mpc86xx_hpcn_setup_arch,
- .init_IRQ = mpc86xx_hpcn_init_irq,
+ .init_IRQ = mpc86xx_init_irq,
.show_cpuinfo = mpc86xx_hpcn_show_cpuinfo,
.get_irq = mpic_get_irq,
- .restart = mpc86xx_restart,
+ .restart = fsl_rstcr_restart,
.time_init = mpc86xx_time_init,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
};
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
index ba55b0ff0f7..af09baee22c 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
@@ -15,11 +15,11 @@
#include <linux/init.h>
#include <linux/delay.h>
+#include <asm/code-patching.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/pci-bridge.h>
-#include <asm-powerpc/mpic.h>
-#include <asm/mpc86xx.h>
+#include <asm/mpic.h>
#include <asm/cacheflush.h>
#include <sysdev/fsl_soc.h>
@@ -27,8 +27,12 @@
#include "mpc86xx.h"
extern void __secondary_start_mpc86xx(void);
-extern unsigned long __secondary_hold_acknowledge;
+#define MCM_PORT_CONFIG_OFFSET 0x10
+
+/* Offset from CCSRBAR */
+#define MPC86xx_MCM_OFFSET (0x1000)
+#define MPC86xx_MCM_SIZE (0x1000)
static void __init
smp_86xx_release_core(int nr)
@@ -47,20 +51,21 @@ smp_86xx_release_core(int nr)
pcr = in_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2));
pcr |= 1 << (nr + 24);
out_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2), pcr);
+
+ iounmap(mcm_vaddr);
}
-static void __init
+static int __init
smp_86xx_kick_cpu(int nr)
{
unsigned int save_vector;
unsigned long target, flags;
int n = 0;
- volatile unsigned int *vector
- = (volatile unsigned int *)(KERNELBASE + 0x100);
+ unsigned int *vector = (unsigned int *)(KERNELBASE + 0x100);
if (nr < 0 || nr >= NR_CPUS)
- return;
+ return -ENOENT;
pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr);
@@ -71,7 +76,7 @@ smp_86xx_kick_cpu(int nr)
/* Setup fake reset vector to call __secondary_start_mpc86xx. */
target = (unsigned long) __secondary_start_mpc86xx;
- create_branch((unsigned long)vector, target, BRANCH_SET_LINK);
+ patch_branch(vector, target, BRANCH_SET_LINK);
/* Kick that CPU */
smp_86xx_release_core(nr);
@@ -87,6 +92,8 @@ smp_86xx_kick_cpu(int nr)
local_irq_restore(flags);
pr_debug("wait CPU #%d for %d msecs.\n", nr, n);
+
+ return 0;
}
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
deleted file mode 100644
index 8235c562661..00000000000
--- a/arch/powerpc/platforms/86xx/pci.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * MPC86XX pci setup code
- *
- * Recode: ZHANG WEI <wei.zhang@freescale.com>
- * Initial author: Xianghua Xiao <x.xiao@freescale.com>
- *
- * Copyright 2006 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/serial.h>
-
-#include <asm/system.h>
-#include <asm/atomic.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pcie.h>
-
-#include "mpc86xx.h"
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
-#else
-#define DBG(fmt, args...)
-#endif
-
-struct pcie_outbound_window_regs {
- uint pexotar; /* 0x.0 - PCI Express outbound translation address register */
- uint pexotear; /* 0x.4 - PCI Express outbound translation extended address register */
- uint pexowbar; /* 0x.8 - PCI Express outbound window base address register */
- char res1[4];
- uint pexowar; /* 0x.10 - PCI Express outbound window attributes register */
- char res2[12];
-};
-
-struct pcie_inbound_window_regs {
- uint pexitar; /* 0x.0 - PCI Express inbound translation address register */
- char res1[4];
- uint pexiwbar; /* 0x.8 - PCI Express inbound window base address register */
- uint pexiwbear; /* 0x.c - PCI Express inbound window base extended address register */
- uint pexiwar; /* 0x.10 - PCI Express inbound window attributes register */
- char res2[12];
-};
-
-static void __init setup_pcie_atmu(struct pci_controller *hose, struct resource *rsrc)
-{
- volatile struct ccsr_pex *pcie;
- volatile struct pcie_outbound_window_regs *pcieow;
- volatile struct pcie_inbound_window_regs *pcieiw;
- int i = 0;
-
- DBG("PCIE memory map start 0x%x, size 0x%x\n", rsrc->start,
- rsrc->end - rsrc->start + 1);
- pcie = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
-
- /* Disable all windows (except pexowar0 since its ignored) */
- pcie->pexowar1 = 0;
- pcie->pexowar2 = 0;
- pcie->pexowar3 = 0;
- pcie->pexowar4 = 0;
- pcie->pexiwar1 = 0;
- pcie->pexiwar2 = 0;
- pcie->pexiwar3 = 0;
-
- pcieow = (struct pcie_outbound_window_regs *)&pcie->pexotar1;
- pcieiw = (struct pcie_inbound_window_regs *)&pcie->pexitar1;
-
- /* Setup outbound MEM window */
- for(i = 0; i < 3; i++)
- if (hose->mem_resources[i].flags & IORESOURCE_MEM){
- DBG("PCIE MEM resource start 0x%08x, size 0x%08x.\n",
- hose->mem_resources[i].start,
- hose->mem_resources[i].end
- - hose->mem_resources[i].start + 1);
- pcieow->pexotar = (hose->mem_resources[i].start) >> 12
- & 0x000fffff;
- pcieow->pexotear = 0;
- pcieow->pexowbar = (hose->mem_resources[i].start) >> 12
- & 0x000fffff;
- /* Enable, Mem R/W */
- pcieow->pexowar = 0x80044000 |
- (__ilog2(hose->mem_resources[i].end
- - hose->mem_resources[i].start + 1)
- - 1);
- pcieow++;
- }
-
- /* Setup outbound IO window */
- if (hose->io_resource.flags & IORESOURCE_IO){
- DBG("PCIE IO resource start 0x%08x, size 0x%08x, phy base 0x%08x.\n",
- hose->io_resource.start,
- hose->io_resource.end - hose->io_resource.start + 1,
- hose->io_base_phys);
- pcieow->pexotar = (hose->io_resource.start) >> 12 & 0x000fffff;
- pcieow->pexotear = 0;
- pcieow->pexowbar = (hose->io_base_phys) >> 12 & 0x000fffff;
- /* Enable, IO R/W */
- pcieow->pexowar = 0x80088000 | (__ilog2(hose->io_resource.end
- - hose->io_resource.start + 1) - 1);
- }
-
- /* Setup 2G inbound Memory Window @ 0 */
- pcieiw->pexitar = 0x00000000;
- pcieiw->pexiwbar = 0x00000000;
- /* Enable, Prefetch, Local Mem, Snoop R/W, 2G */
- pcieiw->pexiwar = 0xa0f5501e;
-}
-
-static void __init
-mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
-{
- u16 cmd;
- unsigned int temps;
-
- DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n",
- pcie_offset, pcie_size);
-
- early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
- | PCI_COMMAND_IO;
- early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd);
-
- early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
-
- /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */
- early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps);
- temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
- early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps);
-}
-
-int mpc86xx_exclude_device(u_char bus, u_char devfn)
-{
- if (bus == 0 && PCI_SLOT(devfn) == 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-int __init add_bridge(struct device_node *dev)
-{
- int len;
- struct pci_controller *hose;
- struct resource rsrc;
- const int *bus_range;
- int has_address = 0;
- int primary = 0;
-
- DBG("Adding PCIE host bridge %s\n", dev->full_name);
-
- /* Fetch host bridge registers address */
- has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
-
- /* Get bus range if any */
- bus_range = of_get_property(dev, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int))
- printk(KERN_WARNING "Can't get bus-range for %s, assume"
- " bus 0\n", dev->full_name);
-
- hose = pcibios_alloc_controller();
- if (!hose)
- return -ENOMEM;
- hose->arch_data = dev;
- hose->set_cfg_type = 1;
-
- /* last_busno = 0xfe cause by MPC8641 PCIE bug */
- hose->first_busno = bus_range ? bus_range[0] : 0x0;
- hose->last_busno = bus_range ? bus_range[1] : 0xfe;
-
- setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4);
-
- /* Setup the PCIE host controller. */
- mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1);
-
- if ((rsrc.start & 0xfffff) == 0x8000)
- primary = 1;
-
- printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. "
- "Firmware bus number: %d->%d\n",
- (unsigned long) rsrc.start,
- hose->first_busno, hose->last_busno);
-
- DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
- hose, hose->cfg_addr, hose->cfg_data);
-
- /* Interpret the "ranges" property */
- /* This also maps the I/O region and sets isa_io/mem_base */
- pci_process_bridge_OF_ranges(hose, dev, primary);
-
- /* Setup PEX window registers */
- setup_pcie_atmu(hose, &rsrc);
-
- return 0;
-}
diff --git a/arch/powerpc/platforms/86xx/pic.c b/arch/powerpc/platforms/86xx/pic.c
new file mode 100644
index 00000000000..d5b98c0f958
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/pic.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/mpic.h>
+#include <asm/i8259.h>
+
+#ifdef CONFIG_PPC_I8259
+static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned int cascade_irq = i8259_irq();
+
+ if (cascade_irq != NO_IRQ)
+ generic_handle_irq(cascade_irq);
+
+ chip->irq_eoi(&desc->irq_data);
+}
+#endif /* CONFIG_PPC_I8259 */
+
+void __init mpc86xx_init_irq(void)
+{
+#ifdef CONFIG_PPC_I8259
+ struct device_node *np;
+ struct device_node *cascade_node = NULL;
+ int cascade_irq;
+#endif
+
+ struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
+ MPIC_SINGLE_DEST_CPU,
+ 0, 256, " MPIC ");
+ BUG_ON(mpic == NULL);
+
+ mpic_init(mpic);
+
+#ifdef CONFIG_PPC_I8259
+ /* Initialize i8259 controller */
+ for_each_node_by_type(np, "interrupt-controller")
+ if (of_device_is_compatible(np, "chrp,iic")) {
+ cascade_node = np;
+ break;
+ }
+
+ if (cascade_node == NULL) {
+ printk(KERN_DEBUG "Could not find i8259 PIC\n");
+ return;
+ }
+
+ cascade_irq = irq_of_parse_and_map(cascade_node, 0);
+ if (cascade_irq == NO_IRQ) {
+ printk(KERN_ERR "Failed to map cascade interrupt\n");
+ return;
+ }
+
+ i8259_init(cascade_node, 0);
+ of_node_put(cascade_node);
+
+ irq_set_chained_handler(cascade_irq, mpc86xx_8259_cascade);
+#endif
+}
diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
new file mode 100644
index 00000000000..b47a8fd0f3d
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/sbc8641d.c
@@ -0,0 +1,124 @@
+/*
+ * SBC8641D board specific routines
+ *
+ * Copyright 2008 Wind River Systems Inc.
+ *
+ * By Paul Gortmaker (see MAINTAINERS for contact information)
+ *
+ * Based largely on the 8641 HPCN support by Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/of_platform.h>
+
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_pci.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+
+static void __init
+sbc8641_setup_arch(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("sbc8641_setup_arch()", 0);
+
+ printk("SBC8641 board from Wind River\n");
+
+#ifdef CONFIG_SMP
+ mpc86xx_smp_init();
+#endif
+
+ fsl_pci_assign_primary();
+}
+
+
+static void
+sbc8641_show_cpuinfo(struct seq_file *m)
+{
+ uint svid = mfspr(SPRN_SVR);
+
+ seq_printf(m, "Vendor\t\t: Wind River Systems\n");
+
+ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+}
+
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init sbc8641_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (of_flat_dt_is_compatible(root, "wind,sbc8641"))
+ return 1; /* Looks good */
+
+ return 0;
+}
+
+static long __init
+mpc86xx_time_init(void)
+{
+ unsigned int temp;
+
+ /* Set the time base to zero */
+ mtspr(SPRN_TBWL, 0);
+ mtspr(SPRN_TBWU, 0);
+
+ temp = mfspr(SPRN_HID0);
+ temp |= HID0_TBEN;
+ mtspr(SPRN_HID0, temp);
+ asm volatile("isync");
+
+ return 0;
+}
+
+static __initdata struct of_device_id of_bus_ids[] = {
+ { .compatible = "simple-bus", },
+ { .compatible = "gianfar", },
+ { .compatible = "fsl,mpc8641-pcie", },
+ {},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+ of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+ return 0;
+}
+machine_arch_initcall(sbc8641, declare_of_platform_devices);
+
+define_machine(sbc8641) {
+ .name = "SBC8641D",
+ .probe = sbc8641_probe,
+ .setup_arch = sbc8641_setup_arch,
+ .init_IRQ = mpc86xx_init_irq,
+ .show_cpuinfo = sbc8641_show_cpuinfo,
+ .get_irq = mpic_get_irq,
+ .restart = fsl_rstcr_restart,
+ .time_init = mpc86xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+#ifdef CONFIG_PCI
+ .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
+#endif
+};