From d5b9ee7b514ee2f3df649fe38d01494ad7a8b956 Mon Sep 17 00:00:00 2001 From: Tanmay Inamdar Date: Mon, 28 Nov 2011 21:01:41 +0000 Subject: [PATCH 01/10] powerpc/40x: Add APM8018X SOC support The AppliedMicro APM8018X embedded processor targets embedded applications that require low power and a small footprint. It features a PowerPC 405 processor core built in a 65nm low-power CMOS process with a five-stage pipeline executing up to one instruction per cycle. The family has 128-kbytes of on-chip memory, a 128-bit local bus and on-chip DDR2 SDRAM controller with 16-bit interface. Signed-off-by: Tanmay Inamdar Signed-off-by: Josh Boyer --- arch/powerpc/boot/dts/klondike.dts | 227 ++++++++++++++++++++ arch/powerpc/configs/40x/klondike_defconfig | 55 +++++ arch/powerpc/kernel/cputable.c | 13 ++ arch/powerpc/platforms/40x/Kconfig | 11 + arch/powerpc/platforms/40x/ppc40x_simple.c | 1 + 5 files changed, 307 insertions(+) create mode 100644 arch/powerpc/boot/dts/klondike.dts create mode 100644 arch/powerpc/configs/40x/klondike_defconfig diff --git a/arch/powerpc/boot/dts/klondike.dts b/arch/powerpc/boot/dts/klondike.dts new file mode 100644 index 0000000000000..8c94290336189 --- /dev/null +++ b/arch/powerpc/boot/dts/klondike.dts @@ -0,0 +1,227 @@ +/* + * Device Tree for Klondike (APM8018X) board. + * + * Copyright (c) 2010, Applied Micro Circuits Corporation + * Author: Tanmay Inamdar + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + model = "apm,klondike"; + compatible = "apm,klondike"; + dcr-parent = <&{/cpus/cpu@0}>; + + aliases { + ethernet0 = &EMAC0; + ethernet1 = &EMAC1; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + model = "PowerPC,apm8018x"; + reg = <0x00000000>; + clock-frequency = <300000000>; /* Filled in by U-Boot */ + timebase-frequency = <300000000>; /* Filled in by U-Boot */ + i-cache-line-size = <32>; + d-cache-line-size = <32>; + i-cache-size = <16384>; /* 16 kB */ + d-cache-size = <16384>; /* 16 kB */ + dcr-controller; + dcr-access-method = "native"; + }; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x20000000>; /* Filled in by U-Boot */ + }; + + UIC0: interrupt-controller { + compatible = "ibm,uic"; + interrupt-controller; + cell-index = <0>; + dcr-reg = <0x0c0 0x010>; + #address-cells = <0>; + #size-cells = <0>; + #interrupt-cells = <2>; + }; + + UIC1: interrupt-controller1 { + compatible = "ibm,uic"; + interrupt-controller; + cell-index = <1>; + dcr-reg = <0x0d0 0x010>; + #address-cells = <0>; + #size-cells = <0>; + #interrupt-cells = <2>; + interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */ + interrupt-parent = <&UIC0>; + }; + + UIC2: interrupt-controller2 { + compatible = "ibm,uic"; + interrupt-controller; + cell-index = <2>; + dcr-reg = <0x0e0 0x010>; + #address-cells = <0>; + #size-cells = <0>; + #interrupt-cells = <2>; + interrupts = <0x0a 0x4 0x0b 0x4>; /* cascade */ + interrupt-parent = <&UIC0>; + }; + + UIC3: interrupt-controller3 { + compatible = "ibm,uic"; + interrupt-controller; + cell-index = <3>; + dcr-reg = <0x0f0 0x010>; + #address-cells = <0>; + #size-cells = <0>; + #interrupt-cells = <2>; + interrupts = <0x10 0x4 0x11 0x4>; /* cascade */ + interrupt-parent = <&UIC0>; + }; + + plb { + compatible = "ibm,plb4"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + clock-frequency = <0>; /* Filled in by U-Boot */ + + SDRAM0: memory-controller { + compatible = "ibm,sdram-apm8018x"; + dcr-reg = <0x010 0x002>; + }; + + MAL0: mcmal { + compatible = "ibm,mcmal2"; + dcr-reg = <0x180 0x062>; + num-tx-chans = <2>; + num-rx-chans = <16>; + #address-cells = <0>; + #size-cells = <0>; + interrupt-parent = <&UIC1>; + interrupts = ; + }; + + POB0: opb { + compatible = "ibm,opb"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x20000000 0x20000000 0x30000000 + 0x50000000 0x50000000 0x10000000 + 0x60000000 0x60000000 0x10000000 + 0xFE000000 0xFE000000 0x00010000>; + dcr-reg = <0x100 0x020>; + clock-frequency = <300000000>; /* Filled in by U-Boot */ + + RGMII0: emac-rgmii@400a2000 { + compatible = "ibm,rgmii"; + reg = <0x400a2000 0x00000010>; + has-mdio; + }; + + TAH0: emac-tah@400a3000 { + compatible = "ibm,tah"; + reg = <0x400a3000 0x100>; + }; + + TAH1: emac-tah@400a4000 { + compatible = "ibm,tah"; + reg = <0x400a4000 0x100>; + }; + + EMAC0: ethernet@400a0000 { + compatible = "ibm,emac4", "ibm-emac4sync"; + interrupt-parent = <&EMAC0>; + interrupts = <0x0>; + #interrupt-cells = <1>; + #address-cells = <0>; + #size-cells = <0>; + interrupt-map = ; + reg = <0x400a0000 0x00000100>; + local-mac-address = [000000000000]; /* Filled in by U-Boot */ + mal-device = <&MAL0>; + mal-tx-channel = <0x0>; + mal-rx-channel = <0x0>; + cell-index = <0>; + max-frame-size = <9000>; + rx-fifo-size = <4096>; + tx-fifo-size = <2048>; + phy-mode = "rgmii"; + phy-address = <0x2>; + turbo = "no"; + phy-map = <0x00000000>; + rgmii-device = <&RGMII0>; + rgmii-channel = <0>; + tah-device = <&TAH0>; + tah-channel = <0>; + has-inverted-stacr-oc; + has-new-stacr-staopc; + }; + + EMAC1: ethernet@400a1000 { + compatible = "ibm,emac4", "ibm-emac4sync"; + status = "disabled"; + interrupt-parent = <&EMAC1>; + interrupts = <0x0>; + #interrupt-cells = <1>; + #address-cells = <0>; + #size-cells = <0>; + interrupt-map = ; + reg = <0x400a1000 0x00000100>; + local-mac-address = [000000000000]; /* Filled in by U-Boot */ + mal-device = <&MAL0>; + mal-tx-channel = <1>; + mal-rx-channel = <8>; + cell-index = <1>; + max-frame-size = <9000>; + rx-fifo-size = <4096>; + tx-fifo-size = <2048>; + phy-mode = "rgmii"; + phy-address = <0x3>; + turbo = "no"; + phy-map = <0x00000000>; + rgmii-device = <&RGMII0>; + rgmii-channel = <1>; + tah-device = <&TAH1>; + tah-channel = <0>; + has-inverted-stacr-oc; + has-new-stacr-staopc; + mdio-device = <&EMAC0>; + }; + }; + }; + + chosen { + linux,stdout-path = "/plb/opb/serial@50001000"; + }; +}; diff --git a/arch/powerpc/configs/40x/klondike_defconfig b/arch/powerpc/configs/40x/klondike_defconfig new file mode 100644 index 0000000000000..c0d228dc73dc5 --- /dev/null +++ b/arch/powerpc/configs/40x/klondike_defconfig @@ -0,0 +1,55 @@ +CONFIG_40x=y +CONFIG_EXPERIMENTAL=y +CONFIG_SYSVIPC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_WALNUT is not set +CONFIG_APM8018X=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_MATH_EMULATION=y +# CONFIG_MIGRATION is not set +# CONFIG_SUSPEND is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_PROC_DEVICETREE=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=35000 +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_SCSI_SAS_ATTRS=y +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT4_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_CRAMFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_AVERAGE=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_FTRACE is not set diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index edae5bb06f1f3..ce59693835c77 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1505,6 +1505,19 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_4xx, .platform = "ppc405", }, + { /* APM8018X */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x7ff11432, + .cpu_name = "APM8018X", + .cpu_features = CPU_FTRS_40X, + .cpu_user_features = PPC_FEATURE_32 | + PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, + .mmu_features = MMU_FTR_TYPE_40x, + .icache_bsize = 32, + .dcache_bsize = 32, + .machine_check = machine_check_4xx, + .platform = "ppc405", + }, { /* default match */ .pvr_mask = 0x00000000, .pvr_value = 0x00000000, diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig index 153022971daab..8883f2c01a1a4 100644 --- a/arch/powerpc/platforms/40x/Kconfig +++ b/arch/powerpc/platforms/40x/Kconfig @@ -186,3 +186,14 @@ config IBM405_ERR51 # bool # depends on !STB03xxx && PPC4xx_DMA # default y +# + +config APM8018X + bool "APM8018X" + depends on 40x + default n + select PPC40x_SIMPLE + help + This option enables support for the AppliedMicro APM8018X evaluation + board. + diff --git a/arch/powerpc/platforms/40x/ppc40x_simple.c b/arch/powerpc/platforms/40x/ppc40x_simple.c index e8dd5c5df7d90..2f8fde6521eab 100644 --- a/arch/powerpc/platforms/40x/ppc40x_simple.c +++ b/arch/powerpc/platforms/40x/ppc40x_simple.c @@ -55,6 +55,7 @@ static const char *board[] __initdata = { "amcc,haleakala", "amcc,kilauea", "amcc,makalu", + "apm,klondike", "est,hotfoot" }; From f1ab93755fecd43263f7885c45e477ee0d832e16 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 30 Nov 2011 10:07:51 -0500 Subject: [PATCH 02/10] MAINTAINERS: Update PowerPC 4xx git tree Update the PowerPC 4xx git tree to a new location Signed-off-by: Josh Boyer --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 3523ab000f1f9..3cdc8bc031331 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4020,7 +4020,7 @@ M: Josh Boyer M: Matt Porter W: http://www.penguinppc.org/ L: linuxppc-dev@lists.ozlabs.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git +T: git git://git.infradead.org/users/jwboyer/powerpc-4xx.git S: Maintained F: arch/powerpc/platforms/40x/ F: arch/powerpc/platforms/44x/ From 9fb552967977289f8c50b597f80583616d1fc994 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Wed, 30 Nov 2011 21:39:17 +0000 Subject: [PATCH 03/10] powerpc/44x: pci: Use PCI_BASE_ADDRESS_MEM_PREFETCH rather than magic value. Signed-off-by: Tony Breeds Signed-off-by: Josh Boyer --- arch/powerpc/sysdev/ppc4xx_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 862f11b3821e8..16f5eba6773db 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -1739,7 +1739,7 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, /* Calculate window size */ sa = (0xffffffffffffffffull << ilog2(size)); if (res->flags & IORESOURCE_PREFETCH) - sa |= 0x8; + sa |= PCI_BASE_ADDRESS_MEM_PREFETCH; if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx")) sa |= PCI_BASE_ADDRESS_MEM_TYPE_64; From 8115846e1a6c27714de442669694050f8ee35850 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Wed, 30 Nov 2011 21:39:18 +0000 Subject: [PATCH 04/10] powerpc/44x: pci: Add a want_sdr flag into ppc4xx_pciex_hwops Currituck doesn't need nor use SDR so aborting the pci setup if there is no sdr-base would be bad. Add a flag to ppc4xx_pciex_hwops for the backends to state if they need SDR and then only complain and abort if they do and it's not found in the device tree. Signed-off-by: Tony Breeds Signed-off-by: Josh Boyer --- arch/powerpc/sysdev/ppc4xx_pci.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 16f5eba6773db..95d5eaa0caa2e 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -647,6 +647,7 @@ static unsigned int ppc4xx_pciex_port_count; struct ppc4xx_pciex_hwops { + bool want_sdr; int (*core_init)(struct device_node *np); int (*port_init_hw)(struct ppc4xx_pciex_port *port); int (*setup_utl)(struct ppc4xx_pciex_port *port); @@ -916,6 +917,7 @@ static int ppc440speB_pciex_init_utl(struct ppc4xx_pciex_port *port) static struct ppc4xx_pciex_hwops ppc440speA_pcie_hwops __initdata = { + .want_sdr = true, .core_init = ppc440spe_pciex_core_init, .port_init_hw = ppc440speA_pciex_init_port_hw, .setup_utl = ppc440speA_pciex_init_utl, @@ -924,6 +926,7 @@ static struct ppc4xx_pciex_hwops ppc440speA_pcie_hwops __initdata = static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata = { + .want_sdr = true, .core_init = ppc440spe_pciex_core_init, .port_init_hw = ppc440speB_pciex_init_port_hw, .setup_utl = ppc440speB_pciex_init_utl, @@ -1034,6 +1037,7 @@ static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port) static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata = { + .want_sdr = true, .core_init = ppc460ex_pciex_core_init, .port_init_hw = ppc460ex_pciex_init_port_hw, .setup_utl = ppc460ex_pciex_init_utl, @@ -1181,6 +1185,7 @@ static void __init ppc460sx_pciex_check_link(struct ppc4xx_pciex_port *port) } static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = { + .want_sdr = true, .core_init = ppc460sx_pciex_core_init, .port_init_hw = ppc460sx_pciex_init_port_hw, .setup_utl = ppc460sx_pciex_init_utl, @@ -1276,6 +1281,7 @@ static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port) static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata = { + .want_sdr = true, .core_init = ppc405ex_pciex_core_init, .port_init_hw = ppc405ex_pciex_init_port_hw, .setup_utl = ppc405ex_pciex_init_utl, @@ -1972,13 +1978,15 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np) } port->node = of_node_get(np); - pval = of_get_property(np, "sdr-base", NULL); - if (pval == NULL) { - printk(KERN_ERR "PCIE: missing sdr-base for %s\n", - np->full_name); - return; + if (ppc4xx_pciex_hwops->want_sdr) { + pval = of_get_property(np, "sdr-base", NULL); + if (pval == NULL) { + printk(KERN_ERR "PCIE: missing sdr-base for %s\n", + np->full_name); + return; + } + port->sdr_base = *pval; } - port->sdr_base = *pval; /* Check if device_type property is set to "pci" or "pci-endpoint". * Resulting from this setup this PCIe port will be configured From 466c2bc762c4212f64c5cf778ff569efd79f0778 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Wed, 30 Nov 2011 21:39:19 +0000 Subject: [PATCH 05/10] powerpc/44x: pci: Setup the dma_window properties for each pci_controller Needed if you want to use swiotlb, harmless otherwise. Signed-off-by: Tony Breeds Signed-off-by: Josh Boyer --- arch/powerpc/sysdev/ppc4xx_pci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 95d5eaa0caa2e..472d2b840f10f 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -185,9 +185,15 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose, out: dma_offset_set = 1; pci_dram_offset = res->start; + hose->dma_window_base_cur = res->start; + hose->dma_window_size = resource_size(res); printk(KERN_INFO "4xx PCI DMA offset set to 0x%08lx\n", pci_dram_offset); + printk(KERN_INFO "4xx PCI DMA window base to 0x%016llx\n", + (unsigned long long)hose->dma_window_base_cur); + printk(KERN_INFO "DMA window size 0x%016llx\n", + (unsigned long long)hose->dma_window_size); return 0; } From ca899859f14e510854c5c8908d3ffdfcd34b16de Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Wed, 30 Nov 2011 21:39:20 +0000 Subject: [PATCH 06/10] powerpc/44x: Removing dead CONFIG_PPC47x CONFIG_PPC47x doesn't exist in Kconfig and no 476 processor calls this function ppc44x_pin_tlb() as it has it's own ppc47x_pin_tlb(). This code is probably an artifact of the original 476 code that shouldn't have made it upstream. Signed-off-by: Christoph Egger Signed-off-by: Tony Breeds Signed-off-by: Josh Boyer --- arch/powerpc/mm/44x_mmu.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c index f60e006d90c35..5d4e3fff6d6d6 100644 --- a/arch/powerpc/mm/44x_mmu.c +++ b/arch/powerpc/mm/44x_mmu.c @@ -78,11 +78,7 @@ static void __init ppc44x_pin_tlb(unsigned int virt, unsigned int phys) "tlbwe %1,%3,%5\n" "tlbwe %0,%3,%6\n" : -#ifdef CONFIG_PPC47x - : "r" (PPC47x_TLB2_S_RWX), -#else : "r" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G), -#endif "r" (phys), "r" (virt | PPC44x_TLB_VALID | PPC44x_TLB_256M), "r" (entry), From e32a03290c72773c304ffeebffed0a63c0a672ae Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Wed, 30 Nov 2011 21:39:21 +0000 Subject: [PATCH 07/10] powerpc/boot: Add extended precision shifts to the boot wrapper. The upcomming currituck patches will need to do 64-bit shifts which will fail with undefined symbol without this patch. I looked at linking against libgcc but we can't guarantee that libgcc was compiled with soft-float. Also Using ../lib/div64.S or ../kernel/misc_32.S, this will break the build as the .o's need to be built with different flags for the bootwrapper vs the kernel. So for now the easyest option is to just copy code from arch/powerpc/kernel/misc_32.S I don't think this code changes too often ;P Signed-off-by: Tony Breeds Signed-off-by: Josh Boyer --- arch/powerpc/boot/div64.S | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/arch/powerpc/boot/div64.S b/arch/powerpc/boot/div64.S index d271ab5426732..bbcb8a4cc1210 100644 --- a/arch/powerpc/boot/div64.S +++ b/arch/powerpc/boot/div64.S @@ -57,3 +57,55 @@ __div64_32: stw r8,4(r3) mr r3,r6 # return the remainder in r3 blr + +/* + * Extended precision shifts. + * + * Updated to be valid for shift counts from 0 to 63 inclusive. + * -- Gabriel + * + * R3/R4 has 64 bit value + * R5 has shift count + * result in R3/R4 + * + * ashrdi3: arithmetic right shift (sign propagation) + * lshrdi3: logical right shift + * ashldi3: left shift + */ + .globl __ashrdi3 +__ashrdi3: + subfic r6,r5,32 + srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count + addi r7,r5,32 # could be xori, or addi with -32 + slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count) + rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0 + sraw r7,r3,r7 # t2 = MSW >> (count-32) + or r4,r4,r6 # LSW |= t1 + slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2 + sraw r3,r3,r5 # MSW = MSW >> count + or r4,r4,r7 # LSW |= t2 + blr + + .globl __ashldi3 +__ashldi3: + subfic r6,r5,32 + slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count + addi r7,r5,32 # could be xori, or addi with -32 + srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count) + slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32) + or r3,r3,r6 # MSW |= t1 + slw r4,r4,r5 # LSW = LSW << count + or r3,r3,r7 # MSW |= t2 + blr + + .globl __lshrdi3 +__lshrdi3: + subfic r6,r5,32 + srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count + addi r7,r5,32 # could be xori, or addi with -32 + slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count) + srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32) + or r4,r4,r6 # LSW |= t1 + srw r3,r3,r5 # MSW = MSW >> count + or r4,r4,r7 # LSW |= t2 + blr From 075bcf5879225d0c2a119c23d8046b890e051e81 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Wed, 30 Nov 2011 21:39:22 +0000 Subject: [PATCH 08/10] powerpc/boot: Add mfdcrx Needed for currituck support. Signed-off-by: Tony Breeds Signed-off-by: Josh Boyer --- arch/powerpc/boot/dcr.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/powerpc/boot/dcr.h b/arch/powerpc/boot/dcr.h index 645a7c964e5fc..cc73f7a95e26c 100644 --- a/arch/powerpc/boot/dcr.h +++ b/arch/powerpc/boot/dcr.h @@ -9,6 +9,12 @@ }) #define mtdcr(rn, val) \ asm volatile("mtdcr %0,%1" : : "i"(rn), "r"(val)) +#define mfdcrx(rn) \ + ({ \ + unsigned long rval; \ + asm volatile("mfdcrx %0,%1" : "=r"(rval) : "r"(rn)); \ + rval; \ + }) /* 440GP/440GX SDRAM controller DCRs */ #define DCRN_SDRAM0_CFGADDR 0x010 From df777bd39a266637d1765d48043493489418e75b Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Wed, 30 Nov 2011 21:39:23 +0000 Subject: [PATCH 09/10] powerpc/476fpe: Add 476fpe SoC code Based on original work by David 'Shaggy' Kleikamp. Signed-off-by: Tony Breeds Signed-off-by: Josh Boyer --- arch/powerpc/include/asm/reg.h | 1 + arch/powerpc/kernel/cputable.c | 14 ++++++++ arch/powerpc/kernel/head_44x.S | 2 ++ arch/powerpc/platforms/44x/Kconfig | 4 +++ arch/powerpc/sysdev/ppc4xx_pci.c | 57 +++++++++++++++++++++++++++++- arch/powerpc/sysdev/ppc4xx_pci.h | 7 ++++ 6 files changed, 84 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 559da199edb59..7fdc2c0b7fa05 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -951,6 +951,7 @@ #define PVR_403GCX 0x00201400 #define PVR_405GP 0x40110000 #define PVR_476 0x11a52000 +#define PVR_476FPE 0x7ff50000 #define PVR_STB03XXX 0x40310000 #define PVR_NP405H 0x41410000 #define PVR_NP405L 0x41610000 diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index ce59693835c77..81db9e2a8a203 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1843,6 +1843,20 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_47x, .platform = "ppc470", }, + { /* 476fpe */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x7ff50000, + .cpu_name = "476fpe", + .cpu_features = CPU_FTRS_47X | CPU_FTR_476_DD2, + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_HAS_FPU, + .mmu_features = MMU_FTR_TYPE_47x | + MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL, + .icache_bsize = 32, + .dcache_bsize = 128, + .machine_check = machine_check_47x, + .platform = "ppc470", + }, { /* 476 iss */ .pvr_mask = 0xffff0000, .pvr_value = 0x00050000, diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index b725dab0f88a0..bb7a9c7a4c05c 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -732,6 +732,8 @@ _GLOBAL(init_cpu_state) /* We use the PVR to differenciate 44x cores from 476 */ mfspr r3,SPRN_PVR srwi r3,r3,16 + cmplwi cr0,r3,PVR_476FPE@h + beq head_start_47x cmplwi cr0,r3,PVR_476@h beq head_start_47x cmplwi cr0,r3,PVR_476_ISS@h diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 762322ce24a97..f0be6e0b164d8 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig @@ -308,6 +308,10 @@ config 460SX select IBM_EMAC_ZMII select IBM_EMAC_TAH +config 476FPE + bool + select PPC_FPU + config APM821xx bool select PPC_FPU diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 472d2b840f10f..4f05f75423462 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -1296,6 +1296,52 @@ static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata = #endif /* CONFIG_40x */ +#ifdef CONFIG_476FPE +static int __init ppc_476fpe_pciex_core_init(struct device_node *np) +{ + return 4; +} + +static void __init ppc_476fpe_pciex_check_link(struct ppc4xx_pciex_port *port) +{ + u32 timeout_ms = 20; + u32 val = 0, mask = (PECFG_TLDLP_LNKUP|PECFG_TLDLP_PRESENT); + void __iomem *mbase = ioremap(port->cfg_space.start + 0x10000000, + 0x1000); + + printk(KERN_INFO "PCIE%d: Checking link...\n", port->index); + + if (mbase == NULL) { + printk(KERN_WARNING "PCIE%d: failed to get cfg space\n", + port->index); + return; + } + + while (timeout_ms--) { + val = in_le32(mbase + PECFG_TLDLP); + + if ((val & mask) == mask) + break; + msleep(10); + } + + if (val & PECFG_TLDLP_PRESENT) { + printk(KERN_INFO "PCIE%d: link is up !\n", port->index); + port->link = 1; + } else + printk(KERN_WARNING "PCIE%d: Link up failed\n", port->index); + + iounmap(mbase); + return; +} + +static struct ppc4xx_pciex_hwops ppc_476fpe_pcie_hwops __initdata = +{ + .core_init = ppc_476fpe_pciex_core_init, + .check_link = ppc_476fpe_pciex_check_link, +}; +#endif /* CONFIG_476FPE */ + /* Check that the core has been initied and if not, do it */ static int __init ppc4xx_pciex_check_core_init(struct device_node *np) { @@ -1320,6 +1366,10 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np) #ifdef CONFIG_40x if (of_device_is_compatible(np, "ibm,plb-pciex-405ex")) ppc4xx_pciex_hwops = &ppc405ex_pcie_hwops; +#endif +#ifdef CONFIG_476FPE + if (of_device_is_compatible(np, "ibm,plb-pciex-476fpe")) + ppc4xx_pciex_hwops = &ppc_476fpe_pcie_hwops; #endif if (ppc4xx_pciex_hwops == NULL) { printk(KERN_WARNING "PCIE: unknown host type %s\n", @@ -1629,6 +1679,10 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port, dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT | DCRO_PEGPL_OMRxMSKL_VAL); + else if (of_device_is_compatible(port->node, "ibm,plb-pciex-476fpe")) + dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, + sa | DCRO_PEGPL_476FPE_OMR1MSKL_UOT + | DCRO_PEGPL_OMRxMSKL_VAL); else dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | DCRO_PEGPL_OMR1MSKL_UOT @@ -1753,7 +1807,8 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, if (res->flags & IORESOURCE_PREFETCH) sa |= PCI_BASE_ADDRESS_MEM_PREFETCH; - if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx")) + if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx") || + of_device_is_compatible(port->node, "ibm,plb-pciex-476fpe")) sa |= PCI_BASE_ADDRESS_MEM_TYPE_64; out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h index 32ce763a375a4..bb4821938ab13 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.h +++ b/arch/powerpc/sysdev/ppc4xx_pci.h @@ -476,6 +476,13 @@ #define DCRO_PEGPL_OMR1MSKL_UOT 0x00000002 #define DCRO_PEGPL_OMR3MSKL_IO 0x00000002 +/* 476FPE */ +#define PCCFG_LCPA 0x270 +#define PECFG_TLDLP 0x3F8 +#define PECFG_TLDLP_LNKUP 0x00000008 +#define PECFG_TLDLP_PRESENT 0x00000010 +#define DCRO_PEGPL_476FPE_OMR1MSKL_UOT 0x00000004 + /* SDR Bit Mappings */ #define PESDRx_RCSSET_HLDPLB 0x10000000 #define PESDRx_RCSSET_RSTGU 0x01000000 From 228d55053397e6d5325ca179c7ffe331de2846d3 Mon Sep 17 00:00:00 2001 From: Tony Breeds Date: Wed, 30 Nov 2011 21:39:24 +0000 Subject: [PATCH 10/10] powerpc/47x: Add support for the new IBM currituck platform Based on original work by David 'Shaggy' Kleikamp. Signed-off-by: Tony Breeds Signed-off-by: Josh Boyer --- arch/powerpc/boot/Makefile | 5 +- arch/powerpc/boot/dts/currituck.dts | 237 +++++++++++++++++++ arch/powerpc/boot/treeboot-currituck.c | 119 ++++++++++ arch/powerpc/boot/wrapper | 3 + arch/powerpc/configs/44x/currituck_defconfig | 110 +++++++++ arch/powerpc/platforms/44x/Kconfig | 10 + arch/powerpc/platforms/44x/Makefile | 1 + arch/powerpc/platforms/44x/currituck.c | 204 ++++++++++++++++ 8 files changed, 688 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/boot/dts/currituck.dts create mode 100644 arch/powerpc/boot/treeboot-currituck.c create mode 100644 arch/powerpc/configs/44x/currituck_defconfig create mode 100644 arch/powerpc/platforms/44x/currituck.c diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 72ee8c1fba483..ff0057fc48c4a 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -45,6 +45,7 @@ $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405 $(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405 $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405 $(obj)/treeboot-iss4xx.o: BOOTCFLAGS += -mcpu=405 +$(obj)/treeboot-currituck.o: BOOTCFLAGS += -mcpu=405 $(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405 @@ -79,7 +80,8 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \ virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \ cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c \ - gamecube-head.S gamecube.c wii-head.S wii.c treeboot-iss4xx.c + gamecube-head.S gamecube.c wii-head.S wii.c treeboot-iss4xx.c \ + treeboot-currituck.c src-boot := $(src-wlib) $(src-plat) empty.c src-boot := $(addprefix $(obj)/, $(src-boot)) @@ -212,6 +214,7 @@ image-$(CONFIG_WARP) += cuImage.warp image-$(CONFIG_YOSEMITE) += cuImage.yosemite image-$(CONFIG_ISS4xx) += treeImage.iss4xx \ treeImage.iss4xx-mpic +image-$(CONFIG_CURRITUCK) += treeImage.currituck # Board ports in arch/powerpc/platform/8xx/Kconfig image-$(CONFIG_MPC86XADS) += cuImage.mpc866ads diff --git a/arch/powerpc/boot/dts/currituck.dts b/arch/powerpc/boot/dts/currituck.dts new file mode 100644 index 0000000000000..b801dd06e5733 --- /dev/null +++ b/arch/powerpc/boot/dts/currituck.dts @@ -0,0 +1,237 @@ +/* + * Device Tree Source for IBM Embedded PPC 476 Platform + * + * Copyright © 2011 Tony Breeds IBM Corporation + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + */ + +/dts-v1/; + +/memreserve/ 0x01f00000 0x00100000; // spin table + +/ { + #address-cells = <2>; + #size-cells = <2>; + model = "ibm,currituck"; + compatible = "ibm,currituck"; + dcr-parent = <&{/cpus/cpu@0}>; + + aliases { + serial0 = &UART0; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + model = "PowerPC,476"; + reg = <0>; + clock-frequency = <1600000000>; // 1.6 GHz + timebase-frequency = <100000000>; // 100Mhz + i-cache-line-size = <32>; + d-cache-line-size = <32>; + i-cache-size = <32768>; + d-cache-size = <32768>; + dcr-controller; + dcr-access-method = "native"; + status = "ok"; + }; + cpu@1 { + device_type = "cpu"; + model = "PowerPC,476"; + reg = <1>; + clock-frequency = <1600000000>; // 1.6 GHz + timebase-frequency = <100000000>; // 100Mhz + i-cache-line-size = <32>; + d-cache-line-size = <32>; + i-cache-size = <32768>; + d-cache-size = <32768>; + dcr-controller; + dcr-access-method = "native"; + status = "disabled"; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x01f00000>; + }; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x0>; // filled in by zImage + }; + + MPIC: interrupt-controller { + compatible = "chrp,open-pic"; + interrupt-controller; + dcr-reg = <0xffc00000 0x00040000>; + #address-cells = <0>; + #size-cells = <0>; + #interrupt-cells = <2>; + + }; + + plb { + compatible = "ibm,plb6"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clock-frequency = <200000000>; // 200Mhz + + POB0: opb { + compatible = "ibm,opb-4xx", "ibm,opb"; + #address-cells = <1>; + #size-cells = <1>; + /* Wish there was a nicer way of specifying a full + * 32-bit range + */ + ranges = <0x00000000 0x00000200 0x00000000 0x80000000 + 0x80000000 0x00000200 0x80000000 0x80000000>; + clock-frequency = <100000000>; + + UART0: serial@10000000 { + device_type = "serial"; + compatible = "ns16750", "ns16550"; + reg = <0x10000000 0x00000008>; + virtual-reg = <0xe1000000>; + clock-frequency = <1851851>; // PCIe refclk/MCGC0_CTL[UART] + current-speed = <115200>; + interrupt-parent = <&MPIC>; + interrupts = <34 2>; + }; + + IIC0: i2c@00000000 { + compatible = "ibm,iic-currituck", "ibm,iic"; + reg = <0x0 0x00000014>; + interrupt-parent = <&MPIC>; + interrupts = <79 2>; + #address-cells = <1>; + #size-cells = <0>; + rtc@68 { + compatible = "stm,m41t80", "m41st85"; + reg = <0x68>; + }; + }; + }; + + PCIE0: pciex@10100000000 { // 4xGBIF1 + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + compatible = "ibm,plb-pciex-476fpe", "ibm,plb-pciex"; + primary; + port = <0x0>; /* port number */ + reg = <0x00000101 0x00000000 0x0 0x10000000 /* Config space access */ + 0x00000100 0x00000000 0x0 0x00001000>; /* UTL Registers space access */ + dcr-reg = <0x80 0x20>; + +// pci_space < pci_addr > < cpu_addr > < size > + ranges = <0x02000000 0x00000000 0x80000000 0x00000110 0x80000000 0x0 0x80000000 + 0x01000000 0x0 0x0 0x00000140 0x0 0x0 0x00010000>; + + /* Inbound starting at 0 to memsize filled in by zImage */ + dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>; + + /* This drives busses 0 to 0xf */ + bus-range = <0x0 0xf>; + + /* Legacy interrupts (note the weird polarity, the bridge seems + * to invert PCIe legacy interrupts). + * We are de-swizzling here because the numbers are actually for + * port of the root complex virtual P2P bridge. But I want + * to avoid putting a node for it in the tree, so the numbers + * below are basically de-swizzled numbers. + * The real slot is on idsel 0, so the swizzling is 1:1 + */ + interrupt-map-mask = <0x0 0x0 0x0 0x7>; + interrupt-map = < + 0x0 0x0 0x0 0x1 &MPIC 46 0x2 /* int A */ + 0x0 0x0 0x0 0x2 &MPIC 47 0x2 /* int B */ + 0x0 0x0 0x0 0x3 &MPIC 48 0x2 /* int C */ + 0x0 0x0 0x0 0x4 &MPIC 49 0x2 /* int D */>; + }; + + PCIE1: pciex@30100000000 { // 4xGBIF0 + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + compatible = "ibm,plb-pciex-476fpe", "ibm,plb-pciex"; + primary; + port = <0x1>; /* port number */ + reg = <0x00000301 0x00000000 0x0 0x10000000 /* Config space access */ + 0x00000300 0x00000000 0x0 0x00001000>; /* UTL Registers space access */ + dcr-reg = <0x60 0x20>; + + ranges = <0x02000000 0x00000000 0x80000000 0x00000310 0x80000000 0x0 0x80000000 + 0x01000000 0x0 0x0 0x00000340 0x0 0x0 0x00010000>; + + /* Inbound starting at 0 to memsize filled in by zImage */ + dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>; + + /* This drives busses 0 to 0xf */ + bus-range = <0x0 0xf>; + + /* Legacy interrupts (note the weird polarity, the bridge seems + * to invert PCIe legacy interrupts). + * We are de-swizzling here because the numbers are actually for + * port of the root complex virtual P2P bridge. But I want + * to avoid putting a node for it in the tree, so the numbers + * below are basically de-swizzled numbers. + * The real slot is on idsel 0, so the swizzling is 1:1 + */ + interrupt-map-mask = <0x0 0x0 0x0 0x7>; + interrupt-map = < + 0x0 0x0 0x0 0x1 &MPIC 38 0x2 /* int A */ + 0x0 0x0 0x0 0x2 &MPIC 39 0x2 /* int B */ + 0x0 0x0 0x0 0x3 &MPIC 40 0x2 /* int C */ + 0x0 0x0 0x0 0x4 &MPIC 41 0x2 /* int D */>; + }; + + PCIE2: pciex@38100000000 { // 2xGBIF0 + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + compatible = "ibm,plb-pciex-476fpe", "ibm,plb-pciex"; + primary; + port = <0x2>; /* port number */ + reg = <0x00000381 0x00000000 0x0 0x10000000 /* Config space access */ + 0x00000380 0x00000000 0x0 0x00001000>; /* UTL Registers space access */ + dcr-reg = <0xA0 0x20>; + + ranges = <0x02000000 0x00000000 0x80000000 0x00000390 0x80000000 0x0 0x80000000 + 0x01000000 0x0 0x0 0x000003C0 0x0 0x0 0x00010000>; + + /* Inbound starting at 0 to memsize filled in by zImage */ + dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>; + + /* This drives busses 0 to 0xf */ + bus-range = <0x0 0xf>; + + /* Legacy interrupts (note the weird polarity, the bridge seems + * to invert PCIe legacy interrupts). + * We are de-swizzling here because the numbers are actually for + * port of the root complex virtual P2P bridge. But I want + * to avoid putting a node for it in the tree, so the numbers + * below are basically de-swizzled numbers. + * The real slot is on idsel 0, so the swizzling is 1:1 + */ + interrupt-map-mask = <0x0 0x0 0x0 0x7>; + interrupt-map = < + 0x0 0x0 0x0 0x1 &MPIC 54 0x2 /* int A */ + 0x0 0x0 0x0 0x2 &MPIC 55 0x2 /* int B */ + 0x0 0x0 0x0 0x3 &MPIC 56 0x2 /* int C */ + 0x0 0x0 0x0 0x4 &MPIC 57 0x2 /* int D */>; + }; + + }; + + chosen { + linux,stdout-path = &UART0; + }; +}; diff --git a/arch/powerpc/boot/treeboot-currituck.c b/arch/powerpc/boot/treeboot-currituck.c new file mode 100644 index 0000000000000..925ae43b74671 --- /dev/null +++ b/arch/powerpc/boot/treeboot-currituck.c @@ -0,0 +1,119 @@ +/* + * Copyright © 2011 Tony Breeds IBM Corporation + * + * Based on earlier code: + * Copyright (C) Paul Mackerras 1997. + * + * Matt Porter + * Copyright 2002-2005 MontaVista Software Inc. + * + * Eugene Surovegin or + * Copyright (c) 2003, 2004 Zultys Technologies + * + * Copyright 2007 David Gibson, IBM Corporation. + * Copyright 2010 Ben. Herrenschmidt, IBM Corporation. + * Copyright © 2011 David Kleikamp IBM Corporation + * + * 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 +#include +#include "types.h" +#include "elf.h" +#include "string.h" +#include "stdio.h" +#include "page.h" +#include "ops.h" +#include "reg.h" +#include "io.h" +#include "dcr.h" +#include "4xx.h" +#include "44x.h" +#include "libfdt.h" + +BSS_STACK(4096); + +#define MAX_RANKS 0x4 +#define DDR3_MR0CF 0x80010011U + +static unsigned long long ibm_currituck_memsize; +static unsigned long long ibm_currituck_detect_memsize(void) +{ + u32 reg; + unsigned i; + unsigned long long memsize = 0; + + for(i = 0; i < MAX_RANKS; i++){ + reg = mfdcrx(DDR3_MR0CF + i); + + if (!(reg & 1)) + continue; + + reg &= 0x0000f000; + reg >>= 12; + memsize += (0x800000ULL << reg); + } + + return memsize; +} + +static void ibm_currituck_fixups(void) +{ + void *devp = finddevice("/"); + u32 dma_ranges[7]; + + dt_fixup_memory(0x0ULL, ibm_currituck_memsize); + + while ((devp = find_node_by_devtype(devp, "pci"))) { + if (getprop(devp, "dma-ranges", dma_ranges, sizeof(dma_ranges)) < 0) { + printf("%s: Failed to get dma-ranges\r\n", __func__); + continue; + } + + dma_ranges[5] = ibm_currituck_memsize >> 32; + dma_ranges[6] = ibm_currituck_memsize & 0xffffffffUL; + + setprop(devp, "dma-ranges", dma_ranges, sizeof(dma_ranges)); + } +} + +#define SPRN_PIR 0x11E /* Processor Indentification Register */ +void platform_init(void) +{ + unsigned long end_of_ram, avail_ram; + u32 pir_reg; + int node, size; + const u32 *timebase; + + ibm_currituck_memsize = ibm_currituck_detect_memsize(); + if (ibm_currituck_memsize >> 32) + end_of_ram = ~0UL; + else + end_of_ram = ibm_currituck_memsize; + avail_ram = end_of_ram - (unsigned long)_end; + + simple_alloc_init(_end, avail_ram, 128, 64); + platform_ops.fixups = ibm_currituck_fixups; + platform_ops.exit = ibm44x_dbcr_reset; + pir_reg = mfspr(SPRN_PIR); + + /* Make sure FDT blob is sane */ + if (fdt_check_header(_dtb_start) != 0) + fatal("Invalid device tree blob\n"); + + node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type", + "cpu", sizeof("cpu")); + if (!node) + fatal("Cannot find cpu node\n"); + timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size); + if (timebase && (size == 4)) + timebase_period_ns = 1000000000 / *timebase; + + fdt_set_boot_cpuid_phys(_dtb_start, pir_reg); + fdt_init(_dtb_start); + + serial_console_init(); +} diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index c74531af72c04..87f4950f38b15 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -244,6 +244,9 @@ gamecube|wii) link_address='0x600000' platformo="$object/$platform-head.o $object/$platform.o" ;; +treeboot-currituck) + link_address='0x1000000' + ;; treeboot-iss4xx-mpic) platformo="$object/treeboot-iss4xx.o" ;; diff --git a/arch/powerpc/configs/44x/currituck_defconfig b/arch/powerpc/configs/44x/currituck_defconfig new file mode 100644 index 0000000000000..4192322f8a7fa --- /dev/null +++ b/arch/powerpc/configs/44x/currituck_defconfig @@ -0,0 +1,110 @@ +CONFIG_44x=y +CONFIG_SMP=y +CONFIG_EXPERIMENTAL=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_SPARSE_IRQ=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_EXPERT=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PROFILING=y +CONFIG_OPROFILE=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PPC_47x=y +# CONFIG_EBONY is not set +CONFIG_CURRITUCK=y +CONFIG_HIGHMEM=y +CONFIG_HZ_100=y +CONFIG_MATH_EMULATION=y +CONFIG_IRQ_ALL_CPUS=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="" +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_IPV6 is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_CONNECTOR=y +CONFIG_MTD=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_PHYSMAP_OF=y +CONFIG_PROC_DEVICETREE=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=35000 +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +# CONFIG_SATA_PMP is not set +CONFIG_SATA_SIL24=y +# CONFIG_ATA_SFF is not set +CONFIG_NETDEVICES=y +CONFIG_E1000E=y +# CONFIG_NETDEV_10000 is not set +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_I2C_IBM_IIC=y +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_USB=y +CONFIG_USB_DEBUG=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_M41T80=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_CRAMFS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NLS_DEFAULT="n" +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEBUG_INFO=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_XMON=y +CONFIG_XMON_DEFAULT=y +CONFIG_PPC_EARLY_DEBUG=y +CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0x10000000 +CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x200 +CONFIG_CRYPTO=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_PCBC=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index f0be6e0b164d8..5d5aaf6c91aaf 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig @@ -186,6 +186,16 @@ config ISS4xx help This option enables support for the IBM ISS simulation environment +config CURRITUCK + bool "IBM Currituck (476fpe) Support" + depends on PPC_47x + default n + select SWIOTLB + select 476FPE + select PPC4xx_PCI_EXPRESS + help + This option enables support for the IBM Currituck (476fpe) evaluation board + config ICON bool "Icon" depends on 44x diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile index 553db6007217e..d03833abec092 100644 --- a/arch/powerpc/platforms/44x/Makefile +++ b/arch/powerpc/platforms/44x/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o obj-$(CONFIG_ISS4xx) += iss4xx.o obj-$(CONFIG_CANYONLANDS)+= canyonlands.o +obj-$(CONFIG_CURRITUCK) += currituck.o diff --git a/arch/powerpc/platforms/44x/currituck.c b/arch/powerpc/platforms/44x/currituck.c new file mode 100644 index 0000000000000..1fdf56916873e --- /dev/null +++ b/arch/powerpc/platforms/44x/currituck.c @@ -0,0 +1,204 @@ +/* + * Currituck board specific routines + * + * Copyright © 2011 Tony Breeds IBM Corporation + * + * Based on earlier code: + * Matt Porter + * Copyright 2002-2005 MontaVista Software Inc. + * + * Eugene Surovegin or + * Copyright (c) 2003-2005 Zultys Technologies + * + * Rewritten and ported to the merged powerpc tree: + * Copyright 2007 David Gibson , IBM Corporation. + * Copyright © 2011 David Kliekamp IBM Corporation + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static __initdata struct of_device_id ppc47x_of_bus[] = { + { .compatible = "ibm,plb4", }, + { .compatible = "ibm,plb6", }, + { .compatible = "ibm,opb", }, + { .compatible = "ibm,ebc", }, + {}, +}; + +/* The EEPROM is missing and the default values are bogus. This forces USB in + * to EHCI mode */ +static void __devinit quirk_ppc_currituck_usb_fixup(struct pci_dev *dev) +{ + if (of_machine_is_compatible("ibm,currituck")) { + pci_write_config_dword(dev, 0xe0, 0x0114231f); + pci_write_config_dword(dev, 0xe4, 0x00006c40); + } +} +DECLARE_PCI_FIXUP_HEADER(0x1033, 0x0035, quirk_ppc_currituck_usb_fixup); + +static int __init ppc47x_device_probe(void) +{ + of_platform_bus_probe(NULL, ppc47x_of_bus, NULL); + + return 0; +} +machine_device_initcall(ppc47x, ppc47x_device_probe); + +/* We can have either UICs or MPICs */ +static void __init ppc47x_init_irq(void) +{ + struct device_node *np; + + /* Find top level interrupt controller */ + for_each_node_with_property(np, "interrupt-controller") { + if (of_get_property(np, "interrupts", NULL) == NULL) + break; + } + if (np == NULL) + panic("Can't find top level interrupt controller"); + + /* Check type and do appropriate initialization */ + if (of_device_is_compatible(np, "chrp,open-pic")) { + /* The MPIC driver will get everything it needs from the + * device-tree, just pass 0 to all arguments + */ + struct mpic *mpic = + mpic_alloc(np, 0, MPIC_PRIMARY, 0, 0, " MPIC "); + BUG_ON(mpic == NULL); + mpic_init(mpic); + ppc_md.get_irq = mpic_get_irq; + } else + panic("Unrecognized top level interrupt controller"); +} + +#ifdef CONFIG_SMP +static void __cpuinit smp_ppc47x_setup_cpu(int cpu) +{ + mpic_setup_this_cpu(); +} + +static int __cpuinit smp_ppc47x_kick_cpu(int cpu) +{ + struct device_node *cpunode = of_get_cpu_node(cpu, NULL); + const u64 *spin_table_addr_prop; + u32 *spin_table; + extern void start_secondary_47x(void); + + BUG_ON(cpunode == NULL); + + /* Assume spin table. We could test for the enable-method in + * the device-tree but currently there's little point as it's + * our only supported method + */ + spin_table_addr_prop = + of_get_property(cpunode, "cpu-release-addr", NULL); + + if (spin_table_addr_prop == NULL) { + pr_err("CPU%d: Can't start, missing cpu-release-addr !\n", + cpu); + return 1; + } + + /* Assume it's mapped as part of the linear mapping. This is a bit + * fishy but will work fine for now + * + * XXX: Is there any reason to assume differently? + */ + spin_table = (u32 *)__va(*spin_table_addr_prop); + pr_debug("CPU%d: Spin table mapped at %p\n", cpu, spin_table); + + spin_table[3] = cpu; + smp_wmb(); + spin_table[1] = __pa(start_secondary_47x); + mb(); + + return 0; +} + +static struct smp_ops_t ppc47x_smp_ops = { + .probe = smp_mpic_probe, + .message_pass = smp_mpic_message_pass, + .setup_cpu = smp_ppc47x_setup_cpu, + .kick_cpu = smp_ppc47x_kick_cpu, + .give_timebase = smp_generic_give_timebase, + .take_timebase = smp_generic_take_timebase, +}; + +static void __init ppc47x_smp_init(void) +{ + if (mmu_has_feature(MMU_FTR_TYPE_47x)) + smp_ops = &ppc47x_smp_ops; +} + +#else /* CONFIG_SMP */ +static void __init ppc47x_smp_init(void) { } +#endif /* CONFIG_SMP */ + +static void __init ppc47x_setup_arch(void) +{ + + /* No need to check the DMA config as we /know/ our windows are all of + * RAM. Lets hope that doesn't change */ +#ifdef CONFIG_SWIOTLB + if (memblock_end_of_DRAM() > 0xffffffff) { + ppc_swiotlb_enable = 1; + set_pci_dma_ops(&swiotlb_dma_ops); + ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; + } +#endif + ppc47x_smp_init(); +} + +/* + * Called very early, MMU is off, device-tree isn't unflattened + */ +static int __init ppc47x_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (!of_flat_dt_is_compatible(root, "ibm,currituck")) + return 0; + + return 1; +} + +/* Use USB controller should have been hardware swizzled but it wasn't :( */ +static void ppc47x_pci_irq_fixup(struct pci_dev *dev) +{ + if (dev->vendor == 0x1033 && (dev->device == 0x0035 || + dev->device == 0x00e0)) { + dev->irq = irq_create_mapping(NULL, 47); + pr_info("%s: Mapping irq 47 %d\n", __func__, dev->irq); + } +} + +define_machine(ppc47x) { + .name = "PowerPC 47x", + .probe = ppc47x_probe, + .progress = udbg_progress, + .init_IRQ = ppc47x_init_irq, + .setup_arch = ppc47x_setup_arch, + .pci_irq_fixup = ppc47x_pci_irq_fixup, + .restart = ppc4xx_reset_system, + .calibrate_decr = generic_calibrate_decr, +};