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/Kconfig60
-rw-r--r--arch/powerpc/platforms/86xx/Makefile5
-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.c352
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx.h3
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c124
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_smp.c23
-rw-r--r--arch/powerpc/platforms/86xx/pic.c71
-rw-r--r--arch/powerpc/platforms/86xx/sbc8641d.c124
11 files changed, 1233 insertions, 231 deletions
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 21d113536b8..1afd1e4a2dd 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -1,33 +1,79 @@
-choice
- prompt "86xx Board 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
+ select FSL_ULI1575 if PCI
+ select HAS_RAPIDIO
+ select SWIOTLB
help
This option enables support for the MPC8641 HPCN board.
+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.
-endchoice
+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_PCI_CHOICE
select FSL_PCI if PCI
select PPC_UDBG_16550
select MPIC
- default y if MPC8641_HPCN
+ 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
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
index c96706327ea..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_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
index 0b07485641f..d479d68fbb2 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -3,11 +3,12 @@
*
* 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 2007 Freescale Semiconductor Inc.
+ * 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
@@ -18,16 +19,15 @@
#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/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>
@@ -37,153 +37,280 @@
#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_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
-
-void __init
-mpc86xx_hpcd_init_irq(void)
-{
- struct mpic *mpic1;
- struct device_node *np;
- struct resource res;
-
- /* Determine PIC address. */
- np = of_find_node_by_type(NULL, "open-pic");
- if (np == NULL)
- return;
- of_address_to_resource(np, 0, &res);
+machine_arch_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
- /* Alloc mpic structure and per isu has 16 INT entries. */
- mpic1 = mpic_alloc(np, res.start,
- MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
- 0, 256, " MPIC ");
- BUG_ON(mpic1 == NULL);
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
- mpic_init(mpic1);
+/*
+ * 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;
+ }
}
-#ifdef CONFIG_PCI
-static void __devinit quirk_uli1575(struct pci_dev *dev)
+void mpc8610hpcd_set_gamma_table(enum fsl_diu_monitor_port port,
+ char *gamma_table_base)
{
- u32 temp32;
+ 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);
+ }
+}
- /* Disable INTx */
- pci_read_config_dword(dev, 0x48, &temp32);
- pci_write_config_dword(dev, 0x48, (temp32 | 1<<26));
+#define PX_BRDCFG0_DVISEL (1 << 3)
+#define PX_BRDCFG0_DLINK (1 << 4)
+#define PX_BRDCFG0_DIU_MASK (PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK)
- /* Enable sideband interrupt */
- pci_read_config_dword(dev, 0x90, &temp32);
- pci_write_config_dword(dev, 0x90, (temp32 | 1<<22));
+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;
+ }
}
-static void __devinit quirk_uli5288(struct pci_dev *dev)
+/**
+ * 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)
{
- unsigned char c;
- unsigned short temp;
+ 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;
+ }
- /* Interrupt Disable, Needed when SATA disabled */
- pci_read_config_word(dev, PCI_COMMAND, &temp);
- temp |= 1<<10;
- pci_write_config_word(dev, PCI_COMMAND, temp);
+ guts = of_iomap(guts_np, 0);
+ of_node_put(guts_np);
+ if (!guts) {
+ pr_err("mpc8610hpcd: could not map global utilities device\n");
+ return;
+ }
- pci_read_config_byte(dev, 0x83, &c);
- c |= 0x80;
- pci_write_config_byte(dev, 0x83, c);
+ /* Convert pixclock from a wavelength to a frequency */
+ temp = 1000000000000ULL;
+ do_div(temp, pixclock);
+ freq = temp;
- pci_write_config_byte(dev, PCI_CLASS_PROG, 0x01);
- pci_write_config_byte(dev, PCI_CLASS_DEVICE, 0x06);
+ /*
+ * '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);
- pci_read_config_byte(dev, 0x83, &c);
- c &= 0x7f;
- pci_write_config_byte(dev, 0x83, c);
-}
+ /* Disable the pixel clock, and set it to non-inverted and no delay */
+ clrbits32(&guts->clkdvdr,
+ CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
-/*
- * Since 8259PIC was disabled on the board, the IDE device can not
- * use the legacy IRQ, we need to let the IDE device work under
- * native mode and use the interrupt line like other PCI devices.
- * IRQ14 is a sideband interrupt from IDE device to CPU and we use this
- * as the interrupt for IDE device.
- */
-static void __devinit quirk_uli5229(struct pci_dev *dev)
-{
- unsigned char c;
+ /* Enable the clock and set the pxclk */
+ setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
- pci_read_config_byte(dev, 0x4b, &c);
- c |= 0x10;
- pci_write_config_byte(dev, 0x4b, c);
+ iounmap(guts);
}
-/*
- * SATA interrupt pin bug fix
- * There's a chip bug for 5288, The interrupt pin should be 2,
- * not the read only value 1, So it use INTB#, not INTA# which
- * actually used by the IDE device 5229.
- * As of this bug, during the PCI initialization, 5288 read the
- * irq of IDE device from the device tree, this function fix this
- * bug by re-assigning a correct irq to 5288.
- *
- */
-static void __devinit final_uli5288(struct pci_dev *dev)
+enum fsl_diu_monitor_port
+mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- struct device_node *hosenode = hose ? hose->dn : NULL;
- struct of_irq oirq;
- int virq, pin = 2;
- u32 laddr[3];
-
- if (!hosenode)
- return;
-
- laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8);
- laddr[1] = laddr[2] = 0;
- of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq);
- virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
- oirq.size);
- dev->irq = virq;
+ return port;
}
-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_FINAL(PCI_VENDOR_ID_AL, 0x5288, final_uli5288);
-#endif /* CONFIG_PCI */
+#endif
-static void __init
-mpc86xx_hpcd_setup_arch(void)
+static void __init mpc86xx_hpcd_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
+ struct resource r;
+ unsigned char *pixis;
+
if (ppc_md.progress)
ppc_md.progress("mpc86xx_hpcd_setup_arch()", 0);
-#ifdef CONFIG_PCI
- for_each_node_by_type(np, "pci") {
- if (of_device_is_compatible(np, "fsl,mpc8610-pci")
- || of_device_is_compatible(np, "fsl,mpc8641-pcie")) {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0xa000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 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");
}
@@ -200,8 +327,7 @@ static int __init mpc86xx_hpcd_probe(void)
return 0;
}
-long __init
-mpc86xx_time_init(void)
+static long __init mpc86xx_time_init(void)
{
unsigned int temp;
@@ -221,11 +347,13 @@ define_machine(mpc86xx_hpcd) {
.name = "MPC86xx HPCD",
.probe = mpc86xx_hpcd_probe,
.setup_arch = mpc86xx_hpcd_setup_arch,
- .init_IRQ = mpc86xx_hpcd_init_irq,
+ .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/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h
index 525ffa1904f..08efb57559d 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx.h
+++ b/arch/powerpc/platforms/86xx/mpc86xx.h
@@ -15,6 +15,7 @@
* mpc86xx_* files. Mostly for use by mpc86xx_setup().
*/
-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 cfbe8c52e26..e8bf3fae560 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -20,15 +20,13 @@
#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>
@@ -46,83 +44,14 @@
#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 */
-
-void __init
-mpc86xx_hpcn_init_irq(void)
-{
- 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,
- 0, 256, " MPIC ");
- BUG_ON(mpic1 == NULL);
-
- 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);
-
- set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade);
-#endif
-}
-
-#ifdef CONFIG_PCI
-extern int uses_fsl_uli_m1575;
extern int uli_exclude_device(struct pci_controller *hose,
u_char bus, u_char devfn);
static int mpc86xx_exclude_device(struct pci_controller *hose,
u_char bus, u_char devfn)
{
- struct device_node* node;
- struct resource rsrc;
-
- node = hose->dn;
- of_address_to_resource(node, 0, &rsrc);
-
- if ((rsrc.start & 0xfffff) == 0x8000) {
+ if (hose->dn == fsl_pci_primary)
return uli_exclude_device(hose, bus, devfn);
- }
return PCIBIOS_SUCCESSFUL;
}
@@ -132,26 +61,11 @@ static int mpc86xx_exclude_device(struct pci_controller *hose,
static void __init
mpc86xx_hpcn_setup_arch(void)
{
-#ifdef CONFIG_PCI
- struct device_node *np;
-#endif
-
if (ppc_md.progress)
ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
#ifdef CONFIG_PCI
- for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
- struct resource rsrc;
- of_address_to_resource(np, 0, &rsrc);
- if ((rsrc.start & 0xfffff) == 0x8000)
- fsl_add_bridge(np, 1);
- else
- fsl_add_bridge(np, 0);
- }
-
- uses_fsl_uli_m1575 = 1;
ppc_md.pci_exclude_device = mpc86xx_exclude_device;
-
#endif
printk("MPC86xx HPCN board from Freescale Semiconductor\n");
@@ -159,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));
}
@@ -190,13 +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 */
+ /* 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;
+ }
+
return 0;
}
-long __init
+static long __init
mpc86xx_time_init(void)
{
unsigned int temp;
@@ -215,6 +129,9 @@ mpc86xx_time_init(void)
static __initdata struct of_device_id of_bus_ids[] = {
{ .compatible = "simple-bus", },
+ { .compatible = "fsl,srio", },
+ { .compatible = "gianfar", },
+ { .compatible = "fsl,mpc8641-pcie", },
{},
};
@@ -224,13 +141,14 @@ static int __init declare_of_platform_devices(void)
return 0;
}
-machine_device_initcall(mpc86xx_hpcn, declare_of_platform_devices);
+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 = fsl_rstcr_restart,
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/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
+};