aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/82xx/Kconfig21
-rw-r--r--arch/powerpc/platforms/82xx/Makefile5
-rw-r--r--arch/powerpc/platforms/82xx/m82xx_pci.h19
-rw-r--r--arch/powerpc/platforms/82xx/mpc82xx.c111
-rw-r--r--arch/powerpc/platforms/82xx/mpc82xx_ads.c661
-rw-r--r--arch/powerpc/platforms/82xx/pq2ads.h67
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig13
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c215
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.h19
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_itx.c4
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_sys.h2
-rw-r--r--arch/powerpc/platforms/83xx/mpc8360e_pb.c219
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig21
-rw-r--r--arch/powerpc/platforms/85xx/Makefile1
-rw-r--r--arch/powerpc/platforms/85xx/mpc8540_ads.h2
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx.h2
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.c120
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ads.h61
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.h2
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c235
-rw-r--r--arch/powerpc/platforms/cell/interrupt.h97
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c9
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c23
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c4
-rw-r--r--arch/powerpc/platforms/iseries/mf.c2
-rw-r--r--arch/powerpc/platforms/iseries/pci.c8
-rw-r--r--arch/powerpc/platforms/iseries/setup.c16
-rw-r--r--arch/powerpc/platforms/maple/pci.c60
-rw-r--r--arch/powerpc/platforms/powermac/udbg_scc.c14
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c7
-rw-r--r--arch/powerpc/platforms/pseries/setup.c34
32 files changed, 1872 insertions, 204 deletions
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
new file mode 100644
index 0000000000000..47d841ecf2e28
--- /dev/null
+++ b/arch/powerpc/platforms/82xx/Kconfig
@@ -0,0 +1,21 @@
+menu "Platform support"
+ depends on PPC_82xx
+
+choice
+ prompt "Machine Type"
+ default MPC82xx_ADS
+
+config MPC82xx_ADS
+ bool "Freescale MPC82xx ADS"
+ select DEFAULT_UIMAGE
+ select PQ2ADS
+ select 8272
+ select 8260
+ select CPM2
+ select FSL_SOC
+ help
+ This option enables support for the MPC8272 ADS board
+
+endchoice
+
+endmenu
diff --git a/arch/powerpc/platforms/82xx/Makefile b/arch/powerpc/platforms/82xx/Makefile
new file mode 100644
index 0000000000000..d9fd4c84d2e05
--- /dev/null
+++ b/arch/powerpc/platforms/82xx/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the PowerPC 82xx linux kernel.
+#
+obj-$(CONFIG_PPC_82xx) += mpc82xx.o
+obj-$(CONFIG_MPC82xx_ADS) += mpc82xx_ads.o
diff --git a/arch/powerpc/platforms/82xx/m82xx_pci.h b/arch/powerpc/platforms/82xx/m82xx_pci.h
new file mode 100644
index 0000000000000..9cd8893b5a32e
--- /dev/null
+++ b/arch/powerpc/platforms/82xx/m82xx_pci.h
@@ -0,0 +1,19 @@
+#ifndef _PPC_KERNEL_M82XX_PCI_H
+#define _PPC_KERNEL_M82XX_PCI_H
+
+/*
+ * 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 <asm/m8260_pci.h>
+
+#define SIU_INT_IRQ1 ((uint)0x13 + CPM_IRQ_OFFSET)
+
+#ifndef _IO_BASE
+#define _IO_BASE isa_io_base
+#endif
+
+#endif /* _PPC_KERNEL_M8260_PCI_H */
diff --git a/arch/powerpc/platforms/82xx/mpc82xx.c b/arch/powerpc/platforms/82xx/mpc82xx.c
new file mode 100644
index 0000000000000..89d702de48639
--- /dev/null
+++ b/arch/powerpc/platforms/82xx/mpc82xx.c
@@ -0,0 +1,111 @@
+/*
+ * MPC82xx setup and early boot code plus other random bits.
+ *
+ * Author: Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * Copyright (c) 2006 MontaVista Software, 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/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+#include <linux/fs_uart_pd.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc8260.h>
+#include <asm/irq.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/cpm2.h>
+#include <asm/udbg.h>
+#include <asm/i8259.h>
+#include <linux/fs_enet_pd.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/cpm2_pic.h>
+
+#include "pq2ads_pd.h"
+
+static int __init get_freq(char *name, unsigned long *val)
+{
+ struct device_node *cpu;
+ unsigned int *fp;
+ int found = 0;
+
+ /* The cpu node should have timebase and clock frequency properties */
+ cpu = of_find_node_by_type(NULL, "cpu");
+
+ if (cpu) {
+ fp = (unsigned int *)get_property(cpu, name, NULL);
+ if (fp) {
+ found = 1;
+ *val = *fp++;
+ }
+
+ of_node_put(cpu);
+ }
+
+ return found;
+}
+
+void __init m82xx_calibrate_decr(void)
+{
+ ppc_tb_freq = 125000000;
+ if (!get_freq("bus-frequency", &ppc_tb_freq)) {
+ printk(KERN_ERR "WARNING: Estimating decrementer frequency "
+ "(not found)\n");
+ }
+ ppc_tb_freq /= 4;
+ ppc_proc_freq = 1000000000;
+ if (!get_freq("clock-frequency", &ppc_proc_freq))
+ printk(KERN_ERR "WARNING: Estimating processor frequency"
+ "(not found)\n");
+}
+
+void mpc82xx_ads_show_cpuinfo(struct seq_file *m)
+{
+ uint pvid, svid, phid1;
+ uint memsize = total_memory;
+
+ pvid = mfspr(SPRN_PVR);
+ svid = mfspr(SPRN_SVR);
+
+ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+ seq_printf(m, "Machine\t\t: %s\n", CPUINFO_MACHINE);
+ seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+ /* Display cpu Pll setting */
+ phid1 = mfspr(SPRN_HID1);
+ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+ /* Display the amount of memory */
+ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+}
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
new file mode 100644
index 0000000000000..4276f087f26ef
--- /dev/null
+++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c
@@ -0,0 +1,661 @@
+/*
+ * MPC82xx_ads setup and early boot code plus other random bits.
+ *
+ * Author: Vitaly Bordug <vbordug@ru.mvista.com>
+ * m82xx_restart fix by Wade Farnsworth <wfarnsworth@mvista.com>
+ *
+ * Copyright (c) 2006 MontaVista Software, 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/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+#include <linux/fs_uart_pd.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc8260.h>
+#include <asm/irq.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/cpm2.h>
+#include <asm/udbg.h>
+#include <asm/i8259.h>
+#include <linux/fs_enet_pd.h>
+
+#include <sysdev/fsl_soc.h>
+#include <../sysdev/cpm2_pic.h>
+
+#include "pq2ads_pd.h"
+
+#ifdef CONFIG_PCI
+static uint pci_clk_frq;
+static struct {
+ unsigned long *pci_int_stat_reg;
+ unsigned long *pci_int_mask_reg;
+} pci_regs;
+
+static unsigned long pci_int_base;
+static struct irq_host *pci_pic_host;
+static struct device_node *pci_pic_node;
+#endif
+
+static void __init mpc82xx_ads_pic_init(void)
+{
+ struct device_node *np = of_find_compatible_node(NULL, "cpm-pic", "CPM2");
+ struct resource r;
+ cpm2_map_t *cpm_reg;
+
+ if (np == NULL) {
+ printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
+ return;
+ }
+ if (of_address_to_resource(np, 0, &r)) {
+ printk(KERN_ERR "PIC init: invalid resource\n");
+ of_node_put(np);
+ return;
+ }
+ cpm2_pic_init(np);
+ of_node_put(np);
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ cpm_reg = (cpm2_map_t *) ioremap(get_immrbase(), sizeof(cpm2_map_t));
+ cpm_reg->im_intctl.ic_siprr = 0x05309770;
+ iounmap(cpm_reg);
+#ifdef CONFIG_PCI
+ /* Initialize stuff for the 82xx CPLD IC and install demux */
+ m82xx_pci_init_irq();
+#endif
+}
+
+static void init_fcc1_ioports(struct fs_platform_info *fpi)
+{
+ struct io_port *io;
+ u32 tempval;
+ cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
+ struct device_node *np;
+ struct resource r;
+ u32 *bcsr;
+
+ np = of_find_node_by_type(NULL, "memory");
+ if (!np) {
+ printk(KERN_INFO "No memory node in device tree\n");
+ return;
+ }
+ if (of_address_to_resource(np, 1, &r)) {
+ printk(KERN_INFO "No memory reg property [1] in devicetree\n");
+ return;
+ }
+ of_node_put(np);
+ bcsr = ioremap(r.start + 4, sizeof(u32));
+ io = &immap->im_ioport;
+
+ /* Enable the PHY */
+ clrbits32(bcsr, BCSR1_FETHIEN);
+ setbits32(bcsr, BCSR1_FETH_RST);
+
+ /* FCC1 pins are on port A/C. */
+ /* Configure port A and C pins for FCC1 Ethernet. */
+
+ tempval = in_be32(&io->iop_pdira);
+ tempval &= ~PA1_DIRA0;
+ tempval |= PA1_DIRA1;
+ out_be32(&io->iop_pdira, tempval);
+
+ tempval = in_be32(&io->iop_psora);
+ tempval &= ~PA1_PSORA0;
+ tempval |= PA1_PSORA1;
+ out_be32(&io->iop_psora, tempval);
+
+ setbits32(&io->iop_ppara, PA1_DIRA0 | PA1_DIRA1);
+
+ /* Alter clocks */
+ tempval = PC_CLK(fpi->clk_tx - 8) | PC_CLK(fpi->clk_rx - 8);
+
+ clrbits32(&io->iop_psorc, tempval);
+ clrbits32(&io->iop_pdirc, tempval);
+ setbits32(&io->iop_pparc, tempval);
+
+ cpm2_clk_setup(CPM_CLK_FCC1, fpi->clk_rx, CPM_CLK_RX);
+ cpm2_clk_setup(CPM_CLK_FCC1, fpi->clk_tx, CPM_CLK_TX);
+
+ iounmap(bcsr);
+ iounmap(immap);
+}
+
+static void init_fcc2_ioports(struct fs_platform_info *fpi)
+{
+ cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
+ struct device_node *np;
+ struct resource r;
+ u32 *bcsr;
+
+ struct io_port *io;
+ u32 tempval;
+
+ np = of_find_node_by_type(NULL, "memory");
+ if (!np) {
+ printk(KERN_INFO "No memory node in device tree\n");
+ return;
+ }
+ if (of_address_to_resource(np, 1, &r)) {
+ printk(KERN_INFO "No memory reg property [1] in devicetree\n");
+ return;
+ }
+ of_node_put(np);
+ io = &immap->im_ioport;
+ bcsr = ioremap(r.start + 12, sizeof(u32));
+
+ /* Enable the PHY */
+ clrbits32(bcsr, BCSR3_FETHIEN2);
+ setbits32(bcsr, BCSR3_FETH2_RST);
+
+ /* FCC2 are port B/C. */
+ /* Configure port A and C pins for FCC2 Ethernet. */
+
+ tempval = in_be32(&io->iop_pdirb);
+ tempval &= ~PB2_DIRB0;
+ tempval |= PB2_DIRB1;
+ out_be32(&io->iop_pdirb, tempval);
+
+ tempval = in_be32(&io->iop_psorb);
+ tempval &= ~PB2_PSORB0;
+ tempval |= PB2_PSORB1;
+ out_be32(&io->iop_psorb, tempval);
+
+ setbits32(&io->iop_pparb, PB2_DIRB0 | PB2_DIRB1);
+
+ tempval = PC_CLK(fpi->clk_tx - 8) | PC_CLK(fpi->clk_rx - 8);
+
+ /* Alter clocks */
+ clrbits32(&io->iop_psorc, tempval);
+ clrbits32(&io->iop_pdirc, tempval);
+ setbits32(&io->iop_pparc, tempval);
+
+ cpm2_clk_setup(CPM_CLK_FCC2, fpi->clk_rx, CPM_CLK_RX);
+ cpm2_clk_setup(CPM_CLK_FCC2, fpi->clk_tx, CPM_CLK_TX);
+
+ iounmap(bcsr);
+ iounmap(immap);
+}
+
+void init_fcc_ioports(struct fs_platform_info *fpi)
+{
+ int fcc_no = fs_get_fcc_index(fpi->fs_no);
+
+ switch (fcc_no) {
+ case 0:
+ init_fcc1_ioports(fpi);
+ break;
+ case 1:
+ init_fcc2_ioports(fpi);
+ break;
+ default:
+ printk(KERN_ERR "init_fcc_ioports: invalid FCC number\n");
+ return;
+ }
+}
+
+static void init_scc1_uart_ioports(struct fs_uart_platform_info *data)
+{
+ cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
+
+ /* SCC1 is only on port D */
+ setbits32(&immap->im_ioport.iop_ppard, 0x00000003);
+ clrbits32(&immap->im_ioport.iop_psord, 0x00000001);
+ setbits32(&immap->im_ioport.iop_psord, 0x00000002);
+ clrbits32(&immap->im_ioport.iop_pdird, 0x00000001);
+ setbits32(&immap->im_ioport.iop_pdird, 0x00000002);
+
+ clrbits32(&immap->im_cpmux.cmx_scr, (0x00000007 << (4 - data->clk_tx)));
+ clrbits32(&immap->im_cpmux.cmx_scr, (0x00000038 << (4 - data->clk_rx)));
+ setbits32(&immap->im_cpmux.cmx_scr,
+ ((data->clk_tx - 1) << (4 - data->clk_tx)));
+ setbits32(&immap->im_cpmux.cmx_scr,
+ ((data->clk_rx - 1) << (4 - data->clk_rx)));
+
+ iounmap(immap);
+}
+
+static void init_scc4_uart_ioports(struct fs_uart_platform_info *data)
+{
+ cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
+
+ setbits32(&immap->im_ioport.iop_ppard, 0x00000600);
+ clrbits32(&immap->im_ioport.iop_psord, 0x00000600);
+ clrbits32(&immap->im_ioport.iop_pdird, 0x00000200);
+ setbits32(&immap->im_ioport.iop_pdird, 0x00000400);
+
+ clrbits32(&immap->im_cpmux.cmx_scr, (0x00000007 << (4 - data->clk_tx)));
+ clrbits32(&immap->im_cpmux.cmx_scr, (0x00000038 << (4 - data->clk_rx)));
+ setbits32(&immap->im_cpmux.cmx_scr,
+ ((data->clk_tx - 1) << (4 - data->clk_tx)));
+ setbits32(&immap->im_cpmux.cmx_scr,
+ ((data->clk_rx - 1) << (4 - data->clk_rx)));
+
+ iounmap(immap);
+}
+
+void init_scc_ioports(struct fs_uart_platform_info *data)
+{
+ int scc_no = fs_get_scc_index(data->fs_no);
+
+ switch (scc_no) {
+ case 0:
+ init_scc1_uart_ioports(data);
+ data->brg = data->clk_rx;
+ break;
+ case 3:
+ init_scc4_uart_ioports(data);
+ data->brg = data->clk_rx;
+ break;
+ default:
+ printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
+ return;
+ }
+}
+
+void __init m82xx_board_setup(void)
+{
+ cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
+ struct device_node *np;
+ struct resource r;
+ u32 *bcsr;
+
+ np = of_find_node_by_type(NULL, "memory");
+ if (!np) {
+ printk(KERN_INFO "No memory node in device tree\n");
+ return;
+ }
+ if (of_address_to_resource(np, 1, &r)) {
+ printk(KERN_INFO "No memory reg property [1] in devicetree\n");
+ return;
+ }
+ of_node_put(np);
+ bcsr = ioremap(r.start + 4, sizeof(u32));
+ /* Enable the 2nd UART port */
+ clrbits32(bcsr, BCSR1_RS232_EN2);
+
+#ifdef CONFIG_SERIAL_CPM_SCC1
+ clrbits32((u32 *) & immap->im_scc[0].scc_sccm,
+ UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32 *) & immap->im_scc[0].scc_gsmrl,
+ SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC2
+ clrbits32((u32 *) & immap->im_scc[1].scc_sccm,
+ UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32 *) & immap->im_scc[1].scc_gsmrl,
+ SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC3
+ clrbits32((u32 *) & immap->im_scc[2].scc_sccm,
+ UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32 *) & immap->im_scc[2].scc_gsmrl,
+ SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC4
+ clrbits32((u32 *) & immap->im_scc[3].scc_sccm,
+ UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32 *) & immap->im_scc[3].scc_gsmrl,
+ SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+ iounmap(bcsr);
+ iounmap(immap);
+}
+
+#ifdef CONFIG_PCI
+static void m82xx_pci_mask_irq(unsigned int irq)
+{
+ int bit = irq - pci_int_base;
+
+ *pci_regs.pci_int_mask_reg |= (1 << (31 - bit));
+ return;
+}
+
+static void m82xx_pci_unmask_irq(unsigned int irq)
+{
+ int bit = irq - pci_int_base;
+
+ *pci_regs.pci_int_mask_reg &= ~(1 << (31 - bit));
+ return;
+}
+
+static void m82xx_pci_mask_and_ack(unsigned int irq)
+{
+ int bit = irq - pci_int_base;
+
+ *pci_regs.pci_int_mask_reg |= (1 << (31 - bit));
+ return;
+}
+
+static void m82xx_pci_end_irq(unsigned int irq)
+{
+ int bit = irq - pci_int_base;
+
+ *pci_regs.pci_int_mask_reg &= ~(1 << (31 - bit));
+ return;
+}
+
+struct hw_interrupt_type m82xx_pci_ic = {
+ .typename = "MPC82xx ADS PCI",
+ .name = "MPC82xx ADS PCI",
+ .enable = m82xx_pci_unmask_irq,
+ .disable = m82xx_pci_mask_irq,
+ .ack = m82xx_pci_mask_and_ack,
+ .end = m82xx_pci_end_irq,
+ .mask = m82xx_pci_mask_irq,
+ .mask_ack = m82xx_pci_mask_and_ack,
+ .unmask = m82xx_pci_unmask_irq,
+ .eoi = m82xx_pci_end_irq,
+};
+
+static void
+m82xx_pci_irq_demux(unsigned int irq, struct irq_desc *desc,
+ struct pt_regs *regs)
+{
+ unsigned long stat, mask, pend;
+ int bit;
+
+ for (;;) {
+ stat = *pci_regs.pci_int_stat_reg;
+ mask = *pci_regs.pci_int_mask_reg;
+ pend = stat & ~mask & 0xf0000000;
+ if (!pend)
+ break;
+ for (bit = 0; pend != 0; ++bit, pend <<= 1) {
+ if (pend & 0x80000000)
+ __do_IRQ(pci_int_base + bit, regs);
+ }
+ }
+}
+
+static int pci_pic_host_match(struct irq_host *h, struct device_node *node)
+{
+ return node == pci_pic_node;
+}
+
+static int pci_pic_host_map(struct irq_host *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ get_irq_desc(virq)->status |= IRQ_LEVEL;
+ set_irq_chip(virq, &m82xx_pci_ic);
+ return 0;
+}
+
+static void pci_host_unmap(struct irq_host *h, unsigned int virq)
+{
+ /* remove chip and handler */
+ set_irq_chip(virq, NULL);
+}
+
+static struct irq_host_ops pci_pic_host_ops = {
+ .match = pci_pic_host_match,
+ .map = pci_pic_host_map,
+ .unmap = pci_host_unmap,
+};
+
+void m82xx_pci_init_irq(void)
+{
+ int irq;
+ cpm2_map_t *immap;
+ struct device_node *np;
+ struct resource r;
+ const u32 *regs;
+ unsigned int size;
+ const u32 *irq_map;
+ int i;
+ unsigned int irq_max, irq_min;
+
+ if ((np = of_find_node_by_type(NULL, "soc")) == NULL) {
+ printk(KERN_INFO "No SOC node in device tree\n");
+ return;
+ }
+ memset(&r, 0, sizeof(r));
+ if (of_address_to_resource(np, 0, &r)) {
+ printk(KERN_INFO "No SOC reg property in device tree\n");
+ return;
+ }
+ immap = ioremap(r.start, sizeof(*immap));
+ of_node_put(np);
+
+ /* install the demultiplexer for the PCI cascade interrupt */
+ np = of_find_node_by_type(NULL, "pci");
+ if (!np) {
+ printk(KERN_INFO "No pci node on device tree\n");
+ iounmap(immap);
+ return;
+ }
+ irq_map = get_property(np, "interrupt-map", &size);
+ if ((!irq_map) || (size <= 7)) {
+ printk(KERN_INFO "No interrupt-map property of pci node\n");
+ iounmap(immap);
+ return;
+ }
+ size /= sizeof(irq_map[0]);
+ for (i = 0, irq_max = 0, irq_min = 512; i < size; i += 7, irq_map += 7) {
+ if (irq_map[5] < irq_min)
+ irq_min = irq_map[5];
+ if (irq_map[5] > irq_max)
+ irq_max = irq_map[5];
+ }
+ pci_int_base = irq_min;
+ irq = irq_of_parse_and_map(np, 0);
+ set_irq_chained_handler(irq, m82xx_pci_irq_demux);
+ of_node_put(np);
+ np = of_find_node_by_type(NULL, "pci-pic");
+ if (!np) {
+ printk(KERN_INFO "No pci pic node on device tree\n");
+ iounmap(immap);
+ return;
+ }
+ pci_pic_node = of_node_get(np);
+ /* PCI interrupt controller registers: status and mask */
+ regs = get_property(np, "reg", &size);
+ if ((!regs) || (size <= 2)) {
+ printk(KERN_INFO "No reg property in pci pic node\n");
+ iounmap(immap);
+ return;
+ }
+ pci_regs.pci_int_stat_reg =
+ ioremap(regs[0], sizeof(*pci_regs.pci_int_stat_reg));
+ pci_regs.pci_int_mask_reg =
+ ioremap(regs[1], sizeof(*pci_regs.pci_int_mask_reg));
+ of_node_put(np);
+ /* configure chip select for PCI interrupt controller */
+ immap->im_memctl.memc_br3 = regs[0] | 0x00001801;
+ immap->im_memctl.memc_or3 = 0xffff8010;
+ /* make PCI IRQ level sensitive */
+ immap->im_intctl.ic_siexr &= ~(1 << (14 - (irq - SIU_INT_IRQ1)));
+
+ /* mask all PCI interrupts */
+ *pci_regs.pci_int_mask_reg |= 0xfff00000;
+ iounmap(immap);
+ pci_pic_host =
+ irq_alloc_host(IRQ_HOST_MAP_LINEAR, irq_max - irq_min + 1,
+ &pci_pic_host_ops, irq_max + 1);
+ return;
+}
+
+static int m82xx_pci_exclude_device(u_char bus, u_char devfn)
+{
+ if (bus == 0 && PCI_SLOT(devfn) == 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static void
+__init mpc82xx_pcibios_fixup(void)
+{
+ struct pci_dev *dev = NULL;
+
+ for_each_pci_dev(dev) {
+ pci_read_irq_line(dev);
+ }
+}
+
+void __init add_bridge(struct device_node *np)
+{
+ int len;
+ struct pci_controller *hose;
+ struct resource r;
+ const int *bus_range;
+ const void *ptr;
+
+ memset(&r, 0, sizeof(r));
+ if (of_address_to_resource(np, 0, &r)) {
+ printk(KERN_INFO "No PCI reg property in device tree\n");
+ return;
+ }
+ if (!(ptr = get_property(np, "clock-frequency", NULL))) {
+ printk(KERN_INFO "No clock-frequency property in PCI node");
+ return;
+ }
+ pci_clk_frq = *(uint *) ptr;
+ of_node_put(np);
+ bus_range = get_property(np, "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", np->full_name);
+ }
+
+ pci_assign_all_buses = 1;
+
+ hose = pcibios_alloc_controller();
+
+ if (!hose)
+ return;
+
+ hose->arch_data = np;
+ hose->set_cfg_type = 1;
+
+ hose->first_busno = bus_range ? bus_range[0] : 0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
+ hose->bus_offset = 0;
+
+ hose->set_cfg_type = 1;
+
+ setup_indirect_pci(hose,
+ r.start + offsetof(pci_cpm2_t, pci_cfg_addr),
+ r.start + offsetof(pci_cpm2_t, pci_cfg_data));
+
+ pci_process_bridge_OF_ranges(hose, np, 1);
+}
+#endif
+
+/*
+ * Setup the architecture
+ */
+static void __init mpc82xx_ads_setup_arch(void)
+{
+#ifdef CONFIG_PCI
+ struct device_node *np;
+#endif
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc82xx_ads_setup_arch()", 0);
+ cpm2_reset();
+
+ /* Map I/O region to a 256MB BAT */
+
+ m82xx_board_setup();
+
+#ifdef CONFIG_PCI
+ ppc_md.pci_exclude_device = m82xx_pci_exclude_device;
+ for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+ add_bridge(np);
+
+ of_node_put(np);
+ ppc_md.pci_map_irq = NULL;
+ ppc_md.pcibios_fixup = mpc82xx_pcibios_fixup;
+ ppc_md.pcibios_fixup_bus = NULL;
+#endif
+
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc82xx_ads_setup_arch(), finish", 0);
+}
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc82xx_ads_probe(void)
+{
+ /* We always match for now, eventually we should look at
+ * the flat dev tree to ensure this is the board we are
+ * supposed to run on
+ */
+ return 1;
+}
+
+#define RMR_CSRE 0x00000001
+static void m82xx_restart(char *cmd)
+{
+ __volatile__ unsigned char dummy;
+
+ local_irq_disable();
+ ((cpm2_map_t *) cpm2_immr)->im_clkrst.car_rmr |= RMR_CSRE;
+
+ /* Clear the ME,EE,IR & DR bits in MSR to cause checkstop */
+ mtmsr(mfmsr() & ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR));
+ dummy = ((cpm2_map_t *) cpm2_immr)->im_clkrst.res[0];
+ printk("Restart failed\n");
+ while (1) ;
+}
+
+static void m82xx_halt(void)
+{
+ local_irq_disable();
+ while (1) ;
+}
+
+define_machine(mpc82xx_ads)
+{
+ .name = "MPC82xx ADS",
+ .probe = mpc82xx_ads_probe,
+ .setup_arch = mpc82xx_ads_setup_arch,
+ .init_IRQ = mpc82xx_ads_pic_init,
+ .show_cpuinfo = mpc82xx_ads_show_cpuinfo,
+ .get_irq = cpm2_get_irq,
+ .calibrate_decr = m82xx_calibrate_decr,
+ .restart = m82xx_restart,.halt = m82xx_halt,
+};
diff --git a/arch/powerpc/platforms/82xx/pq2ads.h b/arch/powerpc/platforms/82xx/pq2ads.h
new file mode 100644
index 0000000000000..a7348213508f0
--- /dev/null
+++ b/arch/powerpc/platforms/82xx/pq2ads.h
@@ -0,0 +1,67 @@
+/*
+ * PQ2/mpc8260 board-specific stuff
+ *
+ * A collection of structures, addresses, and values associated with
+ * the Freescale MPC8260ADS/MPC8266ADS-PCI boards.
+ * Copied from the RPX-Classic and SBS8260 stuff.
+ *
+ * Author: Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * Originally written by Dan Malek for Motorola MPC8260 family
+ *
+ * Copyright (c) 2001 Dan Malek <dan@embeddedalley.com>
+ * Copyright (c) 2006 MontaVista Software, 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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __MACH_ADS8260_DEFS
+#define __MACH_ADS8260_DEFS
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR "Freescale Semiconductor"
+#define CPUINFO_MACHINE "PQ2 ADS PowerPC"
+
+/* Backword-compatibility stuff for the drivers */
+#define CPM_MAP_ADDR ((uint)0xf0000000)
+#define CPM_IRQ_OFFSET 0
+
+/* The ADS8260 has 16, 32-bit wide control/status registers, accessed
+ * only on word boundaries.
+ * Not all are used (yet), or are interesting to us (yet).
+ */
+
+/* Things of interest in the CSR.
+ */
+#define BCSR0_LED0 ((uint)0x02000000) /* 0 == on */
+#define BCSR0_LED1 ((uint)0x01000000) /* 0 == on */
+#define BCSR1_FETHIEN ((uint)0x08000000) /* 0 == enable*/
+#define BCSR1_FETH_RST ((uint)0x04000000) /* 0 == reset */
+#define BCSR1_RS232_EN1 ((uint)0x02000000) /* 0 ==enable */
+#define BCSR1_RS232_EN2 ((uint)0x01000000) /* 0 ==enable */
+#define BCSR3_FETHIEN2 ((uint)0x10000000) /* 0 == enable*/
+#define BCSR3_FETH2_RS ((uint)0x80000000) /* 0 == reset */
+
+/* cpm serial driver works with constants below */
+
+#define SIU_INT_SMC1 ((uint)0x04+CPM_IRQ_OFFSET)
+#define SIU_INT_SMC2i ((uint)0x05+CPM_IRQ_OFFSET)
+#define SIU_INT_SCC1 ((uint)0x28+CPM_IRQ_OFFSET)
+#define SIU_INT_SCC2 ((uint)0x29+CPM_IRQ_OFFSET)
+#define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET)
+#define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET)
+
+void m82xx_pci_init_irq(void);
+void mpc82xx_ads_show_cpuinfo(struct seq_file*);
+void m82xx_calibrate_decr(void);
+
+#endif /* __MACH_ADS8260_DEFS */
+#endif /* __KERNEL__ */
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 5fe7b7faf45f1..0975e94ac7c46 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -5,6 +5,13 @@ choice
prompt "Machine Type"
default MPC834x_SYS
+config MPC832x_MDS
+ bool "Freescale MPC832x MDS"
+ select DEFAULT_UIMAGE
+ select QUICC_ENGINE
+ help
+ This option enables support for the MPC832x MDS evaluation board.
+
config MPC834x_SYS
bool "Freescale MPC834x SYS"
select DEFAULT_UIMAGE
@@ -27,6 +34,12 @@ config MPC834x_ITX
endchoice
+config PPC_MPC832x
+ bool
+ select PPC_UDBG_16550
+ select PPC_INDIRECT_PCI
+ default y if MPC832x_MDS
+
config MPC834x
bool
select PPC_UDBG_16550
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
new file mode 100644
index 0000000000000..54dea9d42dc96
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Description:
+ * MPC832xE MDS board specific routines.
+ *
+ * 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/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <sysdev/fsl_soc.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+
+#include "mpc83xx.h"
+#include "mpc832x_mds.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+static u8 *bcsr_regs = NULL;
+
+u8 *get_bcsr(void)
+{
+ return bcsr_regs;
+}
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init mpc832x_sys_setup_arch(void)
+{
+ struct device_node *np;
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc832x_sys_setup_arch()", 0);
+
+ np = of_find_node_by_type(NULL, "cpu");
+ if (np != 0) {
+ unsigned int *fp =
+ (int *)get_property(np, "clock-frequency", NULL);
+ if (fp != 0)
+ loops_per_jiffy = *fp / HZ;
+ else
+ loops_per_jiffy = 50000000 / HZ;
+ of_node_put(np);
+ }
+
+ /* Map BCSR area */
+ np = of_find_node_by_name(NULL, "bcsr");
+ if (np != 0) {
+ struct resource res;
+
+ of_address_to_resource(np, 0, &res);
+ bcsr_regs = ioremap(res.start, res.end - res.start +1);
+ 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_swizzle = common_swizzle;
+ ppc_md.pci_exclude_device = mpc83xx_exclude_device;
+#endif
+
+#ifdef CONFIG_QUICC_ENGINE
+ qe_reset();
+
+ if ((np = of_find_node_by_name(np, "par_io")) != NULL) {
+ par_io_init(np);
+ of_node_put(np);
+
+ for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
+ par_io_of_config(np);
+ }
+
+ if ((np = of_find_compatible_node(NULL, "network", "ucc_geth"))
+ != NULL){
+ /* Reset the Ethernet PHY */
+ bcsr_regs[9] &= ~0x20;
+ udelay(1000);
+ bcsr_regs[9] |= 0x20;
+ iounmap(bcsr_regs);
+ of_node_put(np);
+ }
+
+#endif /* CONFIG_QUICC_ENGINE */
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+}
+
+void __init mpc832x_sys_init_IRQ(void)
+{
+
+ struct device_node *np;
+
+ np = of_find_node_by_type(NULL, "ipic");
+ if (!np)
+ return;
+
+ ipic_init(np, 0);
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ ipic_set_default_priority();
+ of_node_put(np);
+
+#ifdef CONFIG_QUICC_ENGINE
+ np = of_find_node_by_type(NULL, "qeic");
+ if (!np)
+ return;
+
+ qe_ic_init(np, 0);
+ of_node_put(np);
+#endif /* CONFIG_QUICC_ENGINE */
+}
+
+#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
+extern ulong ds1374_get_rtc_time(void);
+extern int ds1374_set_rtc_time(ulong);
+
+static int __init mpc832x_rtc_hookup(void)
+{
+ struct timespec tv;
+
+ ppc_md.get_rtc_time = ds1374_get_rtc_time;
+ ppc_md.set_rtc_time = ds1374_set_rtc_time;
+
+ tv.tv_nsec = 0;
+ tv.tv_sec = (ppc_md.get_rtc_time) ();
+ do_settimeofday(&tv);
+
+ return 0;
+}
+
+late_initcall(mpc832x_rtc_hookup);
+#endif
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc832x_sys_probe(void)
+{
+ char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
+ "model", NULL);
+
+ if (model == NULL)
+ return 0;
+ if (strcmp(model, "MPC8323EMDS"))
+ return 0;
+
+ DBG("%s found\n", model);
+
+ return 1;
+}
+
+define_machine(mpc832x_mds) {
+ .name = "MPC832x MDS",
+ .probe = mpc832x_sys_probe,
+ .setup_arch = mpc832x_sys_setup_arch,
+ .init_IRQ = mpc832x_sys_init_IRQ,
+ .get_irq = ipic_get_irq,
+ .restart = mpc83xx_restart,
+ .time_init = mpc83xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.h b/arch/powerpc/platforms/83xx/mpc832x_mds.h
new file mode 100644
index 0000000000000..a49588904f8a4
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Description:
+ * MPC832x MDS board specific header.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_MPC832x_MDS_H__
+#define __MACH_MPC832x_MDS_H__
+
+extern u8 *get_bcsr(void);
+
+#endif /* __MACH_MPC832x_MDS_H__ */
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 969fbb6d8c467..8c676d763bb0a 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -109,6 +109,10 @@ static int __init mpc834x_itx_probe(void)
return 1;
}
+#ifdef CONFIG_RTC_CLASS
+late_initcall(rtc_class_hookup);
+#endif
+
define_machine(mpc834x_itx) {
.name = "MPC834x ITX",
.probe = mpc834x_itx_probe,
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.h b/arch/powerpc/platforms/83xx/mpc834x_sys.h
index fedecb73f7ffc..7d5bbef084e71 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_sys.h
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.h
@@ -1,5 +1,5 @@
/*
- * arch/powerppc/platforms/83xx/mpc834x_sys.h
+ * arch/powerpc/platforms/83xx/mpc834x_sys.h
*
* MPC834X SYS common board definitions
*
diff --git a/arch/powerpc/platforms/83xx/mpc8360e_pb.c b/arch/powerpc/platforms/83xx/mpc8360e_pb.c
new file mode 100644
index 0000000000000..c0191900fc251
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc8360e_pb.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Li Yang <LeoLi@freescale.com>
+ * Yin Olivia <Hong-hua.Yin@freescale.com>
+ *
+ * Description:
+ * MPC8360E MDS PB board specific routines.
+ *
+ * Changelog:
+ * Jun 21, 2006 Initial version
+ *
+ * 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/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <sysdev/fsl_soc.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+
+#include "mpc83xx.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+static u8 *bcsr_regs = NULL;
+
+u8 *get_bcsr(void)
+{
+ return bcsr_regs;
+}
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init mpc8360_sys_setup_arch(void)
+{
+ struct device_node *np;
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc8360_sys_setup_arch()", 0);
+
+ np = of_find_node_by_type(NULL, "cpu");
+ if (np != 0) {
+ const unsigned int *fp =
+ get_property(np, "clock-frequency", NULL);
+ if (fp != 0)
+ loops_per_jiffy = *fp / HZ;
+ else
+ loops_per_jiffy = 50000000 / HZ;
+ of_node_put(np);
+ }
+
+ /* Map BCSR area */
+ np = of_find_node_by_name(NULL, "bcsr");
+ if (np != 0) {
+ struct resource res;
+
+ of_address_to_resource(np, 0, &res);
+ bcsr_regs = ioremap(res.start, res.end - res.start +1);
+ 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_swizzle = common_swizzle;
+ ppc_md.pci_exclude_device = mpc83xx_exclude_device;
+#endif
+
+#ifdef CONFIG_QUICC_ENGINE
+ qe_reset();
+
+ if ((np = of_find_node_by_name(np, "par_io")) != NULL) {
+ par_io_init(np);
+ of_node_put(np);
+
+ for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
+ par_io_of_config(np);
+ }
+
+ if ((np = of_find_compatible_node(NULL, "network", "ucc_geth"))
+ != NULL){
+ /* Reset the Ethernet PHY */
+ bcsr_regs[9] &= ~0x20;
+ udelay(1000);
+ bcsr_regs[9] |= 0x20;
+ iounmap(bcsr_regs);
+ of_node_put(np);
+ }
+
+#endif /* CONFIG_QUICC_ENGINE */
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+}
+
+void __init mpc8360_sys_init_IRQ(void)
+{
+
+ struct device_node *np;
+
+ np = of_find_node_by_type(NULL, "ipic");
+ if (!np)
+ return;
+
+ ipic_init(np, 0);
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ ipic_set_default_priority();
+ of_node_put(np);
+
+#ifdef CONFIG_QUICC_ENGINE
+ np = of_find_node_by_type(NULL, "qeic");
+ if (!np)
+ return;
+
+ qe_ic_init(np, 0);
+ of_node_put(np);
+#endif /* CONFIG_QUICC_ENGINE */
+}
+
+#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
+extern ulong ds1374_get_rtc_time(void);
+extern int ds1374_set_rtc_time(ulong);
+
+static int __init mpc8360_rtc_hookup(void)
+{
+ struct timespec tv;
+
+ ppc_md.get_rtc_time = ds1374_get_rtc_time;
+ ppc_md.set_rtc_time = ds1374_set_rtc_time;
+
+ tv.tv_nsec = 0;
+ tv.tv_sec = (ppc_md.get_rtc_time) ();
+ do_settimeofday(&tv);
+
+ return 0;
+}
+
+late_initcall(mpc8360_rtc_hookup);
+#endif
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc8360_sys_probe(void)
+{
+ char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
+ "model", NULL);
+ if (model == NULL)
+ return 0;
+ if (strcmp(model, "MPC8360EPB"))
+ return 0;
+
+ DBG("MPC8360EMDS-PB found\n");
+
+ return 1;
+}
+
+define_machine(mpc8360_sys) {
+ .name = "MPC8360E PB",
+ .probe = mpc8360_sys_probe,
+ .setup_arch = mpc8360_sys_setup_arch,
+ .init_IRQ = mpc8360_sys_init_IRQ,
+ .get_irq = ipic_get_irq,
+ .restart = mpc83xx_restart,
+ .time_init = mpc83xx_time_init,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index c3268d9877e47..0584f3c7e8844 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -11,6 +11,12 @@ config MPC8540_ADS
help
This option enables support for the MPC 8540 ADS board
+config MPC8560_ADS
+ bool "Freescale MPC8560 ADS"
+ select DEFAULT_UIMAGE
+ help
+ This option enables support for the MPC 8560 ADS board
+
config MPC85xx_CDS
bool "Freescale MPC85xx CDS"
select DEFAULT_UIMAGE
@@ -25,6 +31,11 @@ config MPC8540
select PPC_INDIRECT_PCI
default y if MPC8540_ADS || MPC85xx_CDS
+config MPC8560
+ bool
+ select PPC_INDIRECT_PCI
+ default y if MPC8560_ADS
+
config PPC_INDIRECT_PCI_BE
bool
depends on PPC_85xx
@@ -34,4 +45,14 @@ config MPIC
bool
default y
+config CPM2
+ bool
+ depends on MPC8560
+ default y
+ help
+ The CPM2 (Communications Processor Module) is a coprocessor on
+ embedded CPUs made by Motorola. Selecting this option means that
+ you wish to build a kernel for a machine with a CPM2 coprocessor
+ on it.
+
endmenu
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 7615aa59c78ba..282f5d0d01520 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -3,4 +3,5 @@
#
obj-$(CONFIG_PPC_85xx) += misc.o pci.o
obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
+obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
diff --git a/arch/powerpc/platforms/85xx/mpc8540_ads.h b/arch/powerpc/platforms/85xx/mpc8540_ads.h
index c0d56d2bb5a56..da82f4c0fdac6 100644
--- a/arch/powerpc/platforms/85xx/mpc8540_ads.h
+++ b/arch/powerpc/platforms/85xx/mpc8540_ads.h
@@ -1,5 +1,5 @@
/*
- * arch/ppc/platforms/85xx/mpc8540_ads.h
+ * arch/powerpc/platforms/85xx/mpc8540_ads.h
*
* MPC8540ADS board definitions
*
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h
index b44db6268f3d0..83415db33378e 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx.h
+++ b/arch/powerpc/platforms/85xx/mpc85xx.h
@@ -1,5 +1,5 @@
/*
- * arch/ppc/platforms/85xx/mpc85xx.h
+ * arch/powerpc/platforms/85xx/mpc85xx.h
*
* MPC85xx soc definitions/function decls
*
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index cae6b73357d5b..28070e7ae5074 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -32,6 +32,13 @@
#include <sysdev/fsl_soc.h>
#include "mpc85xx.h"
+#ifdef CONFIG_CPM2
+#include <linux/fs_enet_pd.h>
+#include <asm/cpm2.h>
+#include <sysdev/cpm2_pic.h>
+#include <asm/fs_pd.h>
+#endif
+
#ifndef CONFIG_PCI
unsigned long isa_io_base = 0;
unsigned long isa_mem_base = 0;
@@ -57,12 +64,29 @@ mpc85xx_pcibios_fixup(void)
}
#endif /* CONFIG_PCI */
+#ifdef CONFIG_CPM2
+
+static void cpm2_cascade(unsigned int irq, struct irq_desc *desc,
+ struct pt_regs *regs)
+{
+ int cascade_irq;
+
+ while ((cascade_irq = cpm2_get_irq(regs)) >= 0) {
+ generic_handle_irq(cascade_irq, regs);
+ }
+ desc->chip->eoi(irq);
+}
+
+#endif /* CONFIG_CPM2 */
void __init mpc85xx_ads_pic_init(void)
{
struct mpic *mpic;
struct resource r;
struct device_node *np = NULL;
+#ifdef CONFIG_CPM2
+ int irq;
+#endif
np = of_find_node_by_type(np, "open-pic");
@@ -104,11 +128,103 @@ void __init mpc85xx_ads_pic_init(void)
mpic_assign_isu(mpic, 14, r.start + 0x10100);
mpic_init(mpic);
+
+#ifdef CONFIG_CPM2
+ /* Setup CPM2 PIC */
+ np = of_find_node_by_type(NULL, "cpm-pic");
+ if (np == NULL) {
+ printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
+ return;
+ }
+ irq = irq_of_parse_and_map(np, 0);
+
+ cpm2_pic_init(np);
+ set_irq_chained_handler(irq, cpm2_cascade);
+#endif
}
/*
* Setup the architecture
*/
+#ifdef CONFIG_CPM2
+void init_fcc_ioports(struct fs_platform_info *fpi)
+{
+ struct io_port *io = cpm2_map(im_ioport);
+ int fcc_no = fs_get_fcc_index(fpi->fs_no);
+ int target;
+ u32 tempval;
+
+ switch(fcc_no) {
+ case 1:
+ tempval = in_be32(&io->iop_pdirb);
+ tempval &= ~PB2_DIRB0;
+ tempval |= PB2_DIRB1;
+ out_be32(&io->iop_pdirb, tempval);
+
+ tempval = in_be32(&io->iop_psorb);
+ tempval &= ~PB2_PSORB0;
+ tempval |= PB2_PSORB1;
+ out_be32(&io->iop_psorb, tempval);
+
+ tempval = in_be32(&io->iop_pparb);
+ tempval |= (PB2_DIRB0 | PB2_DIRB1);
+ out_be32(&io->iop_pparb, tempval);
+
+ target = CPM_CLK_FCC2;
+ break;
+ case 2:
+ tempval = in_be32(&io->iop_pdirb);
+ tempval &= ~PB3_DIRB0;
+ tempval |= PB3_DIRB1;
+ out_be32(&io->iop_pdirb, tempval);
+
+ tempval = in_be32(&io->iop_psorb);
+ tempval &= ~PB3_PSORB0;
+ tempval |= PB3_PSORB1;
+ out_be32(&io->iop_psorb, tempval);
+
+ tempval = in_be32(&io->iop_pparb);
+ tempval |= (PB3_DIRB0 | PB3_DIRB1);
+ out_be32(&io->iop_pparb, tempval);
+
+ tempval = in_be32(&io->iop_pdirc);
+ tempval |= PC3_DIRC1;
+ out_be32(&io->iop_pdirc, tempval);
+
+ tempval = in_be32(&io->iop_pparc);
+ tempval |= PC3_DIRC1;
+ out_be32(&io->iop_pparc, tempval);
+
+ target = CPM_CLK_FCC3;
+ break;
+ default:
+ printk(KERN_ERR "init_fcc_ioports: invalid FCC number\n");
+ return;
+ }
+
+ /* Port C has clocks...... */
+ tempval = in_be32(&io->iop_psorc);
+ tempval &= ~(PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8));
+ out_be32(&io->iop_psorc, tempval);
+
+ tempval = in_be32(&io->iop_pdirc);
+ tempval &= ~(PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8));
+ out_be32(&io->iop_pdirc, tempval);
+ tempval = in_be32(&io->iop_pparc);
+ tempval |= (PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8));
+ out_be32(&io->iop_pparc, tempval);
+
+ cpm2_unmap(io);
+
+ /* Configure Serial Interface clock routing.
+ * First, clear FCC bits to zero,
+ * then set the ones we want.
+ */
+ cpm2_clk_setup(target, fpi->clk_rx, CPM_CLK_RX);
+ cpm2_clk_setup(target, fpi->clk_tx, CPM_CLK_TX);
+}
+#endif
+
static void __init mpc85xx_ads_setup_arch(void)
{
struct device_node *cpu;
@@ -131,6 +247,10 @@ static void __init mpc85xx_ads_setup_arch(void)
of_node_put(cpu);
}
+#ifdef CONFIG_CPM2
+ cpm2_reset();
+#endif
+
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.h b/arch/powerpc/platforms/85xx/mpc85xx_ads.h
new file mode 100644
index 0000000000000..effcbf78f8517
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.h
@@ -0,0 +1,61 @@
+/*
+ * MPC85xx ADS board definitions
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_MPC85XXADS_H
+#define __MACH_MPC85XXADS_H
+
+#include <linux/config.h>
+#include <linux/initrd.h>
+#include <sysdev/fsl_soc.h>
+
+#define BCSR_ADDR ((uint)0xf8000000)
+#define BCSR_SIZE ((uint)(32 * 1024))
+
+#ifdef CONFIG_CPM2
+
+#define MPC85xx_CPM_OFFSET (0x80000)
+
+#define CPM_MAP_ADDR (get_immrbase() + MPC85xx_CPM_OFFSET)
+#define CPM_IRQ_OFFSET 60
+
+#define SIU_INT_SMC1 ((uint)0x04+CPM_IRQ_OFFSET)
+#define SIU_INT_SMC2 ((uint)0x05+CPM_IRQ_OFFSET)
+#define SIU_INT_SCC1 ((uint)0x28+CPM_IRQ_OFFSET)
+#define SIU_INT_SCC2 ((uint)0x29+CPM_IRQ_OFFSET)
+#define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET)
+#define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET)
+
+/* FCC1 Clock Source Configuration. These can be
+ * redefined in the board specific file.
+ * Can only choose from CLK9-12 */
+#define F1_RXCLK 12
+#define F1_TXCLK 11
+
+/* FCC2 Clock Source Configuration. These can be
+ * redefined in the board specific file.
+ * Can only choose from CLK13-16 */
+#define F2_RXCLK 13
+#define F2_TXCLK 14
+
+/* FCC3 Clock Source Configuration. These can be
+ * redefined in the board specific file.
+ * Can only choose from CLK13-16 */
+#define F3_RXCLK 15
+#define F3_TXCLK 16
+
+#endif /* CONFIG_CPM2 */
+#endif /* __MACH_MPC85XXADS_H */
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.h b/arch/powerpc/platforms/85xx/mpc85xx_cds.h
index 671f54ff185ac..b251c9feb3dc2 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.h
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.h
@@ -1,5 +1,5 @@
/*
- * arch/ppc/platforms/85xx/mpc85xx_cds_common.h
+ * arch/powerpc/platforms/85xx/mpc85xx_cds.h
*
* MPC85xx CDS board definitions
*
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 6b57a47c5d37f..6cc59e0b45822 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -21,6 +21,12 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * TODO:
+ * - Fix various assumptions related to HW CPU numbers vs. linux CPU numbers
+ * vs node numbers in the setup code
+ * - Implement proper handling of maxcpus=1/2 (that is, routing of irqs from
+ * a non-active node to the active node)
*/
#include <linux/interrupt.h>
@@ -44,24 +50,25 @@ struct iic {
u8 target_id;
u8 eoi_stack[16];
int eoi_ptr;
- struct irq_host *host;
+ struct device_node *node;
};
static DEFINE_PER_CPU(struct iic, iic);
#define IIC_NODE_COUNT 2
-static struct irq_host *iic_hosts[IIC_NODE_COUNT];
+static struct irq_host *iic_host;
/* Convert between "pending" bits and hw irq number */
static irq_hw_number_t iic_pending_to_hwnum(struct cbe_iic_pending_bits bits)
{
unsigned char unit = bits.source & 0xf;
+ unsigned char node = bits.source >> 4;
+ unsigned char class = bits.class & 3;
+ /* Decode IPIs */
if (bits.flags & CBE_IIC_IRQ_IPI)
- return IIC_IRQ_IPI0 | (bits.prio >> 4);
- else if (bits.class <= 3)
- return (bits.class << 4) | unit;
+ return IIC_IRQ_TYPE_IPI | (bits.prio >> 4);
else
- return IIC_IRQ_INVALID;
+ return (node << IIC_IRQ_NODE_SHIFT) | (class << 4) | unit;
}
static void iic_mask(unsigned int irq)
@@ -86,21 +93,70 @@ static struct irq_chip iic_chip = {
.eoi = iic_eoi,
};
+
+static void iic_ioexc_eoi(unsigned int irq)
+{
+}
+
+static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc,
+ struct pt_regs *regs)
+{
+ struct cbe_iic_regs *node_iic = desc->handler_data;
+ unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC;
+ unsigned long bits, ack;
+ int cascade;
+
+ for (;;) {
+ bits = in_be64(&node_iic->iic_is);
+ if (bits == 0)
+ break;
+ /* pre-ack edge interrupts */
+ ack = bits & IIC_ISR_EDGE_MASK;
+ if (ack)
+ out_be64(&node_iic->iic_is, ack);
+ /* handle them */
+ for (cascade = 63; cascade >= 0; cascade--)
+ if (bits & (0x8000000000000000UL >> cascade)) {
+ unsigned int cirq =
+ irq_linear_revmap(iic_host,
+ base | cascade);
+ if (cirq != NO_IRQ)
+ generic_handle_irq(cirq, regs);
+ }
+ /* post-ack level interrupts */
+ ack = bits & ~IIC_ISR_EDGE_MASK;
+ if (ack)
+ out_be64(&node_iic->iic_is, ack);
+ }
+ desc->chip->eoi(irq);
+}
+
+
+static struct irq_chip iic_ioexc_chip = {
+ .typename = " CELL-IOEX",
+ .mask = iic_mask,
+ .unmask = iic_unmask,
+ .eoi = iic_ioexc_eoi,
+};
+
/* Get an IRQ number from the pending state register of the IIC */
static unsigned int iic_get_irq(struct pt_regs *regs)
{
struct cbe_iic_pending_bits pending;
struct iic *iic;
+ unsigned int virq;
iic = &__get_cpu_var(iic);
*(unsigned long *) &pending =
in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
+ if (!(pending.flags & CBE_IIC_IRQ_VALID))
+ return NO_IRQ;
+ virq = irq_linear_revmap(iic_host, iic_pending_to_hwnum(pending));
+ if (virq == NO_IRQ)
+ return NO_IRQ;
iic->eoi_stack[++iic->eoi_ptr] = pending.prio;
BUG_ON(iic->eoi_ptr > 15);
- if (pending.flags & CBE_IIC_IRQ_VALID)
- return irq_linear_revmap(iic->host,
- iic_pending_to_hwnum(pending));
- return NO_IRQ;
+ return virq;
}
#ifdef CONFIG_SMP
@@ -108,12 +164,7 @@ static unsigned int iic_get_irq(struct pt_regs *regs)
/* Use the highest interrupt priorities for IPI */
static inline int iic_ipi_to_irq(int ipi)
{
- return IIC_IRQ_IPI0 + IIC_NUM_IPIS - 1 - ipi;
-}
-
-static inline int iic_irq_to_ipi(int irq)
-{
- return IIC_NUM_IPIS - 1 - (irq - IIC_IRQ_IPI0);
+ return IIC_IRQ_TYPE_IPI + 0xf - ipi;
}
void iic_setup_cpu(void)
@@ -123,7 +174,7 @@ void iic_setup_cpu(void)
void iic_cause_IPI(int cpu, int mesg)
{
- out_be64(&per_cpu(iic, cpu).regs->generate, (IIC_NUM_IPIS - 1 - mesg) << 4);
+ out_be64(&per_cpu(iic, cpu).regs->generate, (0xf - mesg) << 4);
}
u8 iic_get_target_id(int cpu)
@@ -134,9 +185,7 @@ EXPORT_SYMBOL_GPL(iic_get_target_id);
struct irq_host *iic_get_irq_host(int node)
{
- if (node < 0 || node >= IIC_NODE_COUNT)
- return NULL;
- return iic_hosts[node];
+ return iic_host;
}
EXPORT_SYMBOL_GPL(iic_get_irq_host);
@@ -149,34 +198,20 @@ static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-
static void iic_request_ipi(int ipi, const char *name)
{
- int node, virq;
+ int virq;
- for (node = 0; node < IIC_NODE_COUNT; node++) {
- char *rname;
- if (iic_hosts[node] == NULL)
- continue;
- virq = irq_create_mapping(iic_hosts[node],
- iic_ipi_to_irq(ipi));
- if (virq == NO_IRQ) {
- printk(KERN_ERR
- "iic: failed to map IPI %s on node %d\n",
- name, node);
- continue;
- }
- rname = kzalloc(strlen(name) + 16, GFP_KERNEL);
- if (rname)
- sprintf(rname, "%s node %d", name, node);
- else
- rname = (char *)name;
- if (request_irq(virq, iic_ipi_action, IRQF_DISABLED,
- rname, (void *)(long)ipi))
- printk(KERN_ERR
- "iic: failed to request IPI %s on node %d\n",
- name, node);
+ virq = irq_create_mapping(iic_host, iic_ipi_to_irq(ipi));
+ if (virq == NO_IRQ) {
+ printk(KERN_ERR
+ "iic: failed to map IPI %s\n", name);
+ return;
}
+ if (request_irq(virq, iic_ipi_action, IRQF_DISABLED, name,
+ (void *)(long)ipi))
+ printk(KERN_ERR
+ "iic: failed to request IPI %s\n", name);
}
void iic_request_IPIs(void)
@@ -193,16 +228,24 @@ void iic_request_IPIs(void)
static int iic_host_match(struct irq_host *h, struct device_node *node)
{
- return h->host_data != NULL && node == h->host_data;
+ return device_is_compatible(node,
+ "IBM,CBEA-Internal-Interrupt-Controller");
}
static int iic_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw)
{
- if (hw < IIC_IRQ_IPI0)
- set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq);
- else
+ switch (hw & IIC_IRQ_TYPE_MASK) {
+ case IIC_IRQ_TYPE_IPI:
set_irq_chip_and_handler(virq, &iic_chip, handle_percpu_irq);
+ break;
+ case IIC_IRQ_TYPE_IOEXC:
+ set_irq_chip_and_handler(virq, &iic_ioexc_chip,
+ handle_fasteoi_irq);
+ break;
+ default:
+ set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq);
+ }
return 0;
}
@@ -211,11 +254,39 @@ static int iic_host_xlate(struct irq_host *h, struct device_node *ct,
irq_hw_number_t *out_hwirq, unsigned int *out_flags)
{
- /* Currently, we don't translate anything. That needs to be fixed as
- * we get better defined device-trees. iic interrupts have to be
- * explicitely mapped by whoever needs them
- */
- return -ENODEV;
+ unsigned int node, ext, unit, class;
+ const u32 *val;
+
+ if (!device_is_compatible(ct,
+ "IBM,CBEA-Internal-Interrupt-Controller"))
+ return -ENODEV;
+ if (intsize != 1)
+ return -ENODEV;
+ val = get_property(ct, "#interrupt-cells", NULL);
+ if (val == NULL || *val != 1)
+ return -ENODEV;
+
+ node = intspec[0] >> 24;
+ ext = (intspec[0] >> 16) & 0xff;
+ class = (intspec[0] >> 8) & 0xff;
+ unit = intspec[0] & 0xff;
+
+ /* Check if node is in supported range */
+ if (node > 1)
+ return -EINVAL;
+
+ /* Build up interrupt number, special case for IO exceptions */
+ *out_hwirq = (node << IIC_IRQ_NODE_SHIFT);
+ if (unit == IIC_UNIT_IIC && class == 1)
+ *out_hwirq |= IIC_IRQ_TYPE_IOEXC | ext;
+ else
+ *out_hwirq |= IIC_IRQ_TYPE_NORMAL |
+ (class << IIC_IRQ_CLASS_SHIFT) | unit;
+
+ /* Dummy flags, ignored by iic code */
+ *out_flags = IRQ_TYPE_EDGE_RISING;
+
+ return 0;
}
static struct irq_host_ops iic_host_ops = {
@@ -225,7 +296,7 @@ static struct irq_host_ops iic_host_ops = {
};
static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr,
- struct irq_host *host)
+ struct device_node *node)
{
/* XXX FIXME: should locate the linux CPU number from the HW cpu
* number properly. We are lucky for now
@@ -237,19 +308,19 @@ static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr,
iic->target_id = ((hw_cpu & 2) << 3) | ((hw_cpu & 1) ? 0xf : 0xe);
iic->eoi_stack[0] = 0xff;
- iic->host = host;
+ iic->node = of_node_get(node);
out_be64(&iic->regs->prio, 0);
- printk(KERN_INFO "IIC for CPU %d at %lx mapped to %p, target id 0x%x\n",
- hw_cpu, addr, iic->regs, iic->target_id);
+ printk(KERN_INFO "IIC for CPU %d target id 0x%x : %s\n",
+ hw_cpu, iic->target_id, node->full_name);
}
static int __init setup_iic(void)
{
struct device_node *dn;
struct resource r0, r1;
- struct irq_host *host;
- int found = 0;
+ unsigned int node, cascade, found = 0;
+ struct cbe_iic_regs *node_iic;
const u32 *np;
for (dn = NULL;
@@ -269,19 +340,33 @@ static int __init setup_iic(void)
of_node_put(dn);
return -ENODEV;
}
- host = NULL;
- if (found < IIC_NODE_COUNT) {
- host = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
- IIC_SOURCE_COUNT,
- &iic_host_ops,
- IIC_IRQ_INVALID);
- iic_hosts[found] = host;
- BUG_ON(iic_hosts[found] == NULL);
- iic_hosts[found]->host_data = of_node_get(dn);
- found++;
- }
- init_one_iic(np[0], r0.start, host);
- init_one_iic(np[1], r1.start, host);
+ found++;
+ init_one_iic(np[0], r0.start, dn);
+ init_one_iic(np[1], r1.start, dn);
+
+ /* Setup cascade for IO exceptions. XXX cleanup tricks to get
+ * node vs CPU etc...
+ * Note that we configure the IIC_IRR here with a hard coded
+ * priority of 1. We might want to improve that later.
+ */
+ node = np[0] >> 1;
+ node_iic = cbe_get_cpu_iic_regs(np[0]);
+ cascade = node << IIC_IRQ_NODE_SHIFT;
+ cascade |= 1 << IIC_IRQ_CLASS_SHIFT;
+ cascade |= IIC_UNIT_IIC;
+ cascade = irq_create_mapping(iic_host, cascade);
+ if (cascade == NO_IRQ)
+ continue;
+ set_irq_data(cascade, node_iic);
+ set_irq_chained_handler(cascade , iic_ioexc_cascade);
+ out_be64(&node_iic->iic_ir,
+ (1 << 12) /* priority */ |
+ (node << 4) /* dest node */ |
+ IIC_UNIT_THREAD_0 /* route them to thread 0 */);
+ /* Flush pending (make sure it triggers if there is
+ * anything pending
+ */
+ out_be64(&node_iic->iic_is, 0xfffffffffffffffful);
}
if (found)
@@ -292,6 +377,12 @@ static int __init setup_iic(void)
void __init iic_init_IRQ(void)
{
+ /* Setup an irq host data structure */
+ iic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, IIC_SOURCE_COUNT,
+ &iic_host_ops, IIC_IRQ_INVALID);
+ BUG_ON(iic_host == NULL);
+ irq_set_default_host(iic_host);
+
/* Discover and initialize iics */
if (setup_iic() < 0)
panic("IIC: Failed to initialize !\n");
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h
index 5560a92ec3abf..9ba1d3c17b4b4 100644
--- a/arch/powerpc/platforms/cell/interrupt.h
+++ b/arch/powerpc/platforms/cell/interrupt.h
@@ -2,48 +2,76 @@
#define ASM_CELL_PIC_H
#ifdef __KERNEL__
/*
- * Mapping of IIC pending bits into per-node
- * interrupt numbers.
+ * Mapping of IIC pending bits into per-node interrupt numbers.
*
- * IRQ FF CC SS PP FF CC SS PP Description
+ * Interrupt numbers are in the range 0...0x1ff where the top bit
+ * (0x100) represent the source node. Only 2 nodes are supported with
+ * the current code though it's trivial to extend that if necessary using
+ * higher level bits
*
- * 00-3f 80 02 +0 00 - 80 02 +0 3f South Bridge
- * 00-3f 80 02 +b 00 - 80 02 +b 3f South Bridge
- * 41-4a 80 00 +1 ** - 80 00 +a ** SPU Class 0
- * 51-5a 80 01 +1 ** - 80 01 +a ** SPU Class 1
- * 61-6a 80 02 +1 ** - 80 02 +a ** SPU Class 2
- * 70-7f C0 ** ** 00 - C0 ** ** 0f IPI
+ * The bottom 8 bits are split into 2 type bits and 6 data bits that
+ * depend on the type:
*
- * F flags
- * C class
- * S source
- * P Priority
- * + node number
- * * don't care
+ * 00 (0x00 | data) : normal interrupt. data is (class << 4) | source
+ * 01 (0x40 | data) : IO exception. data is the exception number as
+ * defined by bit numbers in IIC_SR
+ * 10 (0x80 | data) : IPI. data is the IPI number (obtained from the priority)
+ * and node is always 0 (IPIs are per-cpu, their source is
+ * not relevant)
+ * 11 (0xc0 | data) : reserved
*
- * A node consists of a Cell Broadband Engine and an optional
- * south bridge device providing a maximum of 64 IRQs.
- * The south bridge may be connected to either IOIF0
- * or IOIF1.
- * Each SPE is represented as three IRQ lines, one per
- * interrupt class.
- * 16 IRQ numbers are reserved for inter processor
- * interruptions, although these are only used in the
- * range of the first node.
+ * In addition, interrupt number 0x80000000 is defined as always invalid
+ * (that is the node field is expected to never extend to move than 23 bits)
*
- * This scheme needs 128 IRQ numbers per BIF node ID,
- * which means that with the total of 512 lines
- * available, we can have a maximum of four nodes.
*/
enum {
- IIC_IRQ_INVALID = 0xff,
- IIC_IRQ_MAX = 0x3f,
- IIC_IRQ_EXT_IOIF0 = 0x20,
- IIC_IRQ_EXT_IOIF1 = 0x2b,
- IIC_IRQ_IPI0 = 0x40,
- IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */
- IIC_SOURCE_COUNT = 0x50,
+ IIC_IRQ_INVALID = 0x80000000u,
+ IIC_IRQ_NODE_MASK = 0x100,
+ IIC_IRQ_NODE_SHIFT = 8,
+ IIC_IRQ_MAX = 0x1ff,
+ IIC_IRQ_TYPE_MASK = 0xc0,
+ IIC_IRQ_TYPE_NORMAL = 0x00,
+ IIC_IRQ_TYPE_IOEXC = 0x40,
+ IIC_IRQ_TYPE_IPI = 0x80,
+ IIC_IRQ_CLASS_SHIFT = 4,
+ IIC_IRQ_CLASS_0 = 0x00,
+ IIC_IRQ_CLASS_1 = 0x10,
+ IIC_IRQ_CLASS_2 = 0x20,
+ IIC_SOURCE_COUNT = 0x200,
+
+ /* Here are defined the various source/dest units. Avoid using those
+ * definitions if you can, they are mostly here for reference
+ */
+ IIC_UNIT_SPU_0 = 0x4,
+ IIC_UNIT_SPU_1 = 0x7,
+ IIC_UNIT_SPU_2 = 0x3,
+ IIC_UNIT_SPU_3 = 0x8,
+ IIC_UNIT_SPU_4 = 0x2,
+ IIC_UNIT_SPU_5 = 0x9,
+ IIC_UNIT_SPU_6 = 0x1,
+ IIC_UNIT_SPU_7 = 0xa,
+ IIC_UNIT_IOC_0 = 0x0,
+ IIC_UNIT_IOC_1 = 0xb,
+ IIC_UNIT_THREAD_0 = 0xe, /* target only */
+ IIC_UNIT_THREAD_1 = 0xf, /* target only */
+ IIC_UNIT_IIC = 0xe, /* source only (IO exceptions) */
+
+ /* Base numbers for the external interrupts */
+ IIC_IRQ_EXT_IOIF0 =
+ IIC_IRQ_TYPE_NORMAL | IIC_IRQ_CLASS_2 | IIC_UNIT_IOC_0,
+ IIC_IRQ_EXT_IOIF1 =
+ IIC_IRQ_TYPE_NORMAL | IIC_IRQ_CLASS_2 | IIC_UNIT_IOC_1,
+
+ /* Base numbers for the IIC_ISR interrupts */
+ IIC_IRQ_IOEX_TMI = IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 63,
+ IIC_IRQ_IOEX_PMI = IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 62,
+ IIC_IRQ_IOEX_ATI = IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 61,
+ IIC_IRQ_IOEX_MATBFI = IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 60,
+ IIC_IRQ_IOEX_ELDI = IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 59,
+
+ /* Which bits in IIC_ISR are edge sensitive */
+ IIC_ISR_EDGE_MASK = 0x4ul,
};
extern void iic_init_IRQ(void);
@@ -52,7 +80,6 @@ extern void iic_request_IPIs(void);
extern void iic_setup_cpu(void);
extern u8 iic_get_target_id(int cpu);
-extern struct irq_host *iic_get_irq_host(int node);
extern void spider_init_IRQ(void);
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 742a03282b440..608b1ebc56b28 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -243,7 +243,6 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
const u32 *imap, *tmp;
int imaplen, intsize, unit;
struct device_node *iic;
- struct irq_host *iic_host;
#if 0 /* Enable that when we have a way to retreive the node as well */
/* First, we check wether we have a real "interrupts" in the device
@@ -289,11 +288,11 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
* the iic host from the iic OF node, but that way I'm still compatible
* with really really old old firmwares for which we don't have a node
*/
- iic_host = iic_get_irq_host(pic->node_id);
- if (iic_host == NULL)
- return NO_IRQ;
/* Manufacture an IIC interrupt number of class 2 */
- virq = irq_create_mapping(iic_host, 0x20 | unit);
+ virq = irq_create_mapping(NULL,
+ (pic->node_id << IIC_IRQ_NODE_SHIFT) |
+ (2 << IIC_IRQ_CLASS_SHIFT) |
+ unit);
if (virq == NO_IRQ)
printk(KERN_ERR "spider_pic: failed to map cascade !");
return virq;
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 3bd36d46ab4ae..f78680346e5fe 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -538,7 +538,7 @@ static void __iomem * __init map_spe_prop(struct spu *spu,
const void *p;
int proplen;
- void* ret = NULL;
+ void __iomem *ret = NULL;
int err = 0;
p = get_property(n, name, &proplen);
@@ -562,30 +562,29 @@ static void spu_unmap(struct spu *spu)
iounmap(spu->priv2);
iounmap(spu->priv1);
iounmap(spu->problem);
- iounmap((u8 __iomem *)spu->local_store);
+ iounmap((__force u8 __iomem *)spu->local_store);
}
/* This function shall be abstracted for HV platforms */
static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
{
- struct irq_host *host;
unsigned int isrc;
const u32 *tmp;
- host = iic_get_irq_host(spu->node);
- if (host == NULL)
- return -ENODEV;
-
- /* Get the interrupt source from the device-tree */
+ /* Get the interrupt source unit from the device-tree */
tmp = get_property(np, "isrc", NULL);
if (!tmp)
return -ENODEV;
- spu->isrc = isrc = tmp[0];
+ isrc = tmp[0];
+
+ /* Add the node number */
+ isrc |= spu->node << IIC_IRQ_NODE_SHIFT;
+ spu->isrc = isrc;
/* Now map interrupts of all 3 classes */
- spu->irqs[0] = irq_create_mapping(host, 0x00 | isrc);
- spu->irqs[1] = irq_create_mapping(host, 0x10 | isrc);
- spu->irqs[2] = irq_create_mapping(host, 0x20 | isrc);
+ spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc);
+ spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc);
+ spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc);
/* Right now, we only fail if class 2 failed */
return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 58e794f9da1b6..51fd197ab5dd1 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1342,7 +1342,7 @@ static u64 spufs_id_get(void *data)
return num;
}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, 0, "0x%llx\n")
+DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n")
struct tree_descr spufs_dir_contents[] = {
{ "mem", &spufs_mem_fops, 0666, },
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index c8670f519734a..efc452e71ab0f 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -234,7 +234,7 @@ static void spu_hw_runcntl_stop(struct spu_context *ctx)
static int spu_hw_set_mfc_query(struct spu_context * ctx, u32 mask, u32 mode)
{
- struct spu_problem *prob = ctx->spu->problem;
+ struct spu_problem __iomem *prob = ctx->spu->problem;
int ret;
spin_lock_irq(&ctx->spu->register_lock);
@@ -263,7 +263,7 @@ static int spu_hw_send_mfc_command(struct spu_context *ctx,
struct mfc_dma_command *cmd)
{
u32 status;
- struct spu_problem *prob = ctx->spu->problem;
+ struct spu_problem __iomem *prob = ctx->spu->problem;
spin_lock_irq(&ctx->spu->register_lock);
out_be32(&prob->mfc_lsa_W, cmd->lsa);
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index 1a2c2a50f9221..1983b640bac11 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -357,7 +357,7 @@ static int dma_and_signal_ce_msg(char *ce_msg,
*/
static int shutdown(void)
{
- int rc = kill_proc(1, SIGINT, 1);
+ int rc = kill_cad_pid(SIGINT, 1);
if (rc) {
printk(KERN_ALERT "mf.c: SIGINT to init failed (%d), "
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 3eb12065df23e..4aa165e010d91 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -262,14 +262,6 @@ void __init iSeries_pci_final_fixup(void)
mf_display_src(0xC9000200);
}
-void pcibios_fixup_bus(struct pci_bus *PciBus)
-{
-}
-
-void pcibios_fixup_resources(struct pci_dev *pdev)
-{
-}
-
/*
* Look down the chain to find the matching Device Device
*/
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 7f1953066ff8f..a0ff7ba7d666a 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -649,15 +649,21 @@ static void iseries_dedicated_idle(void)
void __init iSeries_init_IRQ(void) { }
#endif
+/*
+ * iSeries has no legacy IO, anything calling this function has to
+ * fail or bad things will happen
+ */
+static int iseries_check_legacy_ioport(unsigned int baseport)
+{
+ return -ENODEV;
+}
+
static int __init iseries_probe(void)
{
unsigned long root = of_get_flat_dt_root();
if (!of_flat_dt_is_compatible(root, "IBM,iSeries"))
return 0;
- powerpc_firmware_features |= FW_FEATURE_ISERIES;
- powerpc_firmware_features |= FW_FEATURE_LPAR;
-
hpte_init_iSeries();
return 1;
@@ -680,6 +686,7 @@ define_machine(iseries) {
.calibrate_decr = generic_calibrate_decr,
.progress = iSeries_progress,
.probe = iseries_probe,
+ .check_legacy_ioport = iseries_check_legacy_ioport,
/* XXX Implement enable_pmcs for iSeries */
};
@@ -687,6 +694,9 @@ void * __init iSeries_early_setup(void)
{
unsigned long phys_mem_size;
+ powerpc_firmware_features |= FW_FEATURE_ISERIES;
+ powerpc_firmware_features |= FW_FEATURE_LPAR;
+
iSeries_fixup_klimit();
/*
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index c3aa46b8e2b9d..1b827618e05f9 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -96,14 +96,14 @@ static unsigned long u3_agp_cfa1(u8 bus, u8 devfn, u8 off)
1UL;
}
-static unsigned long u3_agp_cfg_access(struct pci_controller* hose,
+static volatile void __iomem *u3_agp_cfg_access(struct pci_controller* hose,
u8 bus, u8 dev_fn, u8 offset)
{
unsigned int caddr;
if (bus == hose->first_busno) {
if (dev_fn < (11 << 3))
- return 0;
+ return NULL;
caddr = u3_agp_cfa0(dev_fn, offset);
} else
caddr = u3_agp_cfa1(bus, dev_fn, offset);
@@ -114,14 +114,14 @@ static unsigned long u3_agp_cfg_access(struct pci_controller* hose,
} while (in_le32(hose->cfg_addr) != caddr);
offset &= 0x07;
- return ((unsigned long)hose->cfg_data) + offset;
+ return hose->cfg_data + offset;
}
static int u3_agp_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val)
{
struct pci_controller *hose;
- unsigned long addr;
+ volatile void __iomem *addr;
hose = pci_bus_to_host(bus);
if (hose == NULL)
@@ -136,13 +136,13 @@ static int u3_agp_read_config(struct pci_bus *bus, unsigned int devfn,
*/
switch (len) {
case 1:
- *val = in_8((u8 *)addr);
+ *val = in_8(addr);
break;
case 2:
- *val = in_le16((u16 *)addr);
+ *val = in_le16(addr);
break;
default:
- *val = in_le32((u32 *)addr);
+ *val = in_le32(addr);
break;
}
return PCIBIOS_SUCCESSFUL;
@@ -152,7 +152,7 @@ static int u3_agp_write_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 val)
{
struct pci_controller *hose;
- unsigned long addr;
+ volatile void __iomem *addr;
hose = pci_bus_to_host(bus);
if (hose == NULL)
@@ -167,16 +167,16 @@ static int u3_agp_write_config(struct pci_bus *bus, unsigned int devfn,
*/
switch (len) {
case 1:
- out_8((u8 *)addr, val);
- (void) in_8((u8 *)addr);
+ out_8(addr, val);
+ (void) in_8(addr);
break;
case 2:
- out_le16((u16 *)addr, val);
- (void) in_le16((u16 *)addr);
+ out_le16(addr, val);
+ (void) in_le16(addr);
break;
default:
- out_le32((u32 *)addr, val);
- (void) in_le32((u32 *)addr);
+ out_le32(addr, val);
+ (void) in_le32(addr);
break;
}
return PCIBIOS_SUCCESSFUL;
@@ -198,22 +198,22 @@ static unsigned long u3_ht_cfa1(u8 bus, u8 devfn, u8 off)
return u3_ht_cfa0(devfn, off) + (bus << 16) + 0x01000000UL;
}
-static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
+static volatile void __iomem *u3_ht_cfg_access(struct pci_controller* hose,
u8 bus, u8 devfn, u8 offset)
{
if (bus == hose->first_busno) {
if (PCI_SLOT(devfn) == 0)
- return 0;
- return ((unsigned long)hose->cfg_data) + u3_ht_cfa0(devfn, offset);
+ return NULL;
+ return hose->cfg_data + u3_ht_cfa0(devfn, offset);
} else
- return ((unsigned long)hose->cfg_data) + u3_ht_cfa1(bus, devfn, offset);
+ return hose->cfg_data + u3_ht_cfa1(bus, devfn, offset);
}
static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val)
{
struct pci_controller *hose;
- unsigned long addr;
+ volatile void __iomem *addr;
hose = pci_bus_to_host(bus);
if (hose == NULL)
@@ -232,13 +232,13 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
*/
switch (len) {
case 1:
- *val = in_8((u8 *)addr);
+ *val = in_8(addr);
break;
case 2:
- *val = in_le16((u16 *)addr);
+ *val = in_le16(addr);
break;
default:
- *val = in_le32((u32 *)addr);
+ *val = in_le32(addr);
break;
}
return PCIBIOS_SUCCESSFUL;
@@ -248,7 +248,7 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 val)
{
struct pci_controller *hose;
- unsigned long addr;
+ volatile void __iomem *addr;
hose = pci_bus_to_host(bus);
if (hose == NULL)
@@ -266,16 +266,16 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
*/
switch (len) {
case 1:
- out_8((u8 *)addr, val);
- (void) in_8((u8 *)addr);
+ out_8(addr, val);
+ (void) in_8(addr);
break;
case 2:
- out_le16((u16 *)addr, val);
- (void) in_le16((u16 *)addr);
+ out_le16(addr, val);
+ (void) in_le16(addr);
break;
default:
- out_le32((u32 *)addr, val);
- (void) in_le32((u32 *)addr);
+ out_le32(addr, val);
+ (void) in_le32(addr);
break;
}
return PCIBIOS_SUCCESSFUL;
@@ -315,7 +315,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
* the reg address cell, we shall fix that by killing struct
* reg_property and using some accessor functions instead
*/
- hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000);
+ hose->cfg_data = ioremap(0xf2000000, 0x02000000);
hose->first_busno = 0;
hose->last_busno = 0xef;
diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c
index ce1a235855f75..379db05b00824 100644
--- a/arch/powerpc/platforms/powermac/udbg_scc.c
+++ b/arch/powerpc/platforms/powermac/udbg_scc.c
@@ -111,8 +111,6 @@ void udbg_scc_init(int force_scc)
pmac_call_feature(PMAC_FTR_SCC_ENABLE, ch,
PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
-
- /* Setup for 57600 8N1 */
if (ch == ch_a)
addr += 0x20;
sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
@@ -125,9 +123,21 @@ void udbg_scc_init(int force_scc)
x = in_8(sccc);
out_8(sccc, 0x09); /* reset A or B side */
out_8(sccc, 0xc0);
+
+ /* If SCC was the OF output port, read the BRG value, else
+ * Setup for 57600 8N1
+ */
+ if (ch_def != NULL) {
+ out_8(sccc, 13);
+ scc_inittab[1] = in_8(sccc);
+ out_8(sccc, 12);
+ scc_inittab[3] = in_8(sccc);
+ }
+
for (i = 0; i < sizeof(scc_inittab); ++i)
out_8(sccc, scc_inittab[i]);
+
udbg_putc = udbg_scc_putc;
udbg_getc = udbg_scc_getc;
udbg_getc_poll = udbg_scc_getc_poll;
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 84bc8f7e17ef7..3c2d63ebf787f 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -225,6 +225,7 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
void eeh_mark_slot (struct device_node *dn, int mode_flag)
{
+ struct pci_dev *dev;
dn = find_device_pe (dn);
/* Back up one, since config addrs might be shared */
@@ -232,6 +233,12 @@ void eeh_mark_slot (struct device_node *dn, int mode_flag)
dn = dn->parent;
PCI_DN(dn)->eeh_mode |= mode_flag;
+
+ /* Mark the pci device too */
+ dev = PCI_DN(dn)->pcidev;
+ if (dev)
+ dev->error_state = pci_channel_io_frozen;
+
__eeh_mark_slot (dn->child, mode_flag);
}
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 8ed362140452e..f82b13e531a3d 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -180,7 +180,7 @@ static void __init pseries_mpic_init_IRQ(void)
cascade_irq = irq_of_parse_and_map(cascade, 0);
if (cascade == NO_IRQ) {
- printk(KERN_ERR "xics: failed to map cascade interrupt");
+ printk(KERN_ERR "mpic: failed to map cascade interrupt");
return;
}
@@ -342,7 +342,7 @@ static int __init pSeries_init_panel(void)
{
/* Manually leave the kernel version on the panel. */
ppc_md.progress("Linux ppc64\n", 0);
- ppc_md.progress(system_utsname.release, 0);
+ ppc_md.progress(init_utsname()->version, 0);
return 0;
}
@@ -415,12 +415,6 @@ static int pSeries_check_legacy_ioport(unsigned int baseport)
return -ENODEV;
of_node_put(np);
break;
- case PARALLEL_BASE:
- np = of_find_node_by_type(NULL, "parallel");
- if (np == NULL)
- return -ENODEV;
- of_node_put(np);
- break;
}
return 0;
}
@@ -483,7 +477,6 @@ static void pseries_dedicated_idle_sleep(void)
{
unsigned int cpu = smp_processor_id();
unsigned long start_snooze;
- unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
/*
* Indicate to the HV that we are idle. Now would be
@@ -496,9 +489,9 @@ static void pseries_dedicated_idle_sleep(void)
* has been checked recently. If we should poll for a little
* while, do so.
*/
- if (*smt_snooze_delay) {
+ if (__get_cpu_var(smt_snooze_delay)) {
start_snooze = get_tb() +
- *smt_snooze_delay * tb_ticks_per_usec;
+ __get_cpu_var(smt_snooze_delay) * tb_ticks_per_usec;
local_irq_enable();
set_thread_flag(TIF_POLLING_NRFLAG);
@@ -518,24 +511,7 @@ static void pseries_dedicated_idle_sleep(void)
goto out;
}
- /*
- * If not SMT, cede processor. If CPU is running SMT
- * cede if the other thread is not idle, so that it can
- * go single-threaded. If the other thread is idle,
- * we ask the hypervisor if it has pending work it
- * wants to do and cede if it does. Otherwise we keep
- * polling in order to reduce interrupt latency.
- *
- * Doing the cede when the other thread is active will
- * result in this thread going dormant, meaning the other
- * thread gets to run in single-threaded (ST) mode, which
- * is slightly faster than SMT mode with this thread at
- * very low priority. The cede enables interrupts, which
- * doesn't matter here.
- */
- if (!cpu_has_feature(CPU_FTR_SMT) || !lppaca[cpu ^ 1].idle
- || poll_pending() == H_PENDING)
- cede_processor();
+ cede_processor();
out:
HMT_medium();