aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/boot/Makefile4
-rw-r--r--arch/powerpc/boot/dts/kilauea.dts252
-rw-r--r--arch/powerpc/boot/uartlite.c4
-rw-r--r--arch/powerpc/configs/kilauea_defconfig768
-rw-r--r--arch/powerpc/kernel/cputable.c56
-rw-r--r--arch/powerpc/kernel/of_platform.c17
-rw-r--r--arch/powerpc/kernel/prom.c3
-rw-r--r--arch/powerpc/kernel/setup_32.c3
-rw-r--r--arch/powerpc/kernel/setup_64.c3
-rw-r--r--arch/powerpc/kernel/systbl.S2
-rw-r--r--arch/powerpc/kernel/time.c16
-rw-r--r--arch/powerpc/kernel/vdso.c2
-rw-r--r--arch/powerpc/kernel/vio.c95
-rw-r--r--arch/powerpc/oprofile/cell/pr_util.h3
-rw-r--r--arch/powerpc/oprofile/op_model_cell.c2
-rw-r--r--arch/powerpc/platforms/40x/Kconfig7
-rw-r--r--arch/powerpc/platforms/40x/Makefile5
-rw-r--r--arch/powerpc/platforms/40x/kilauea.c58
-rw-r--r--arch/powerpc/platforms/40x/virtex.c5
-rw-r--r--arch/powerpc/platforms/40x/walnut.c5
-rw-r--r--arch/powerpc/platforms/44x/bamboo.c5
-rw-r--r--arch/powerpc/platforms/44x/ebony.c5
-rw-r--r--arch/powerpc/platforms/44x/sequoia.c5
-rw-r--r--arch/powerpc/platforms/52xx/efika.c9
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.c2
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c2
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c2
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.c3
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.h271
-rw-r--r--arch/powerpc/platforms/cell/cbe_thermal.c2
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c2
-rw-r--r--arch/powerpc/platforms/cell/iommu.c2
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c2
-rw-r--r--arch/powerpc/platforms/cell/pmu.c2
-rw-r--r--arch/powerpc/platforms/cell/ras.c2
-rw-r--r--arch/powerpc/platforms/cell/setup.c17
-rw-r--r--arch/powerpc/platforms/celleb/setup.c5
-rw-r--r--arch/powerpc/platforms/chrp/setup.c10
-rw-r--r--arch/powerpc/platforms/iseries/Makefile2
-rw-r--r--arch/powerpc/platforms/iseries/dt.c17
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c52
-rw-r--r--arch/powerpc/platforms/iseries/mf.c23
-rw-r--r--arch/powerpc/platforms/iseries/vio.c553
-rw-r--r--arch/powerpc/platforms/iseries/viopath.c8
-rw-r--r--arch/powerpc/platforms/pasemi/gpio_mdio.c4
-rw-r--r--arch/powerpc/platforms/powermac/setup.c77
-rw-r--r--arch/powerpc/platforms/ps3/os-area.c646
-rw-r--r--arch/powerpc/platforms/ps3/platform.h6
-rw-r--r--arch/powerpc/platforms/ps3/setup.c3
-rw-r--r--arch/powerpc/platforms/ps3/time.c14
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c14
-rw-r--r--arch/powerpc/platforms/pseries/setup.c5
-rw-r--r--arch/powerpc/sysdev/Makefile2
-rw-r--r--arch/powerpc/sysdev/axonram.c8
-rw-r--r--arch/powerpc/sysdev/pmi.c6
55 files changed, 2472 insertions, 626 deletions
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index f3f7ce3d79a..18e32719d0e 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -25,6 +25,10 @@ BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-isystem $(shell $(CROSS32CC) -print-file-name=include)
BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
+ifdef CONFIG_DEBUG_INFO
+BOOTCFLAGS += -g
+endif
+
ifeq ($(call cc-option-yn, -fstack-protector),y)
BOOTCFLAGS += -fno-stack-protector
endif
diff --git a/arch/powerpc/boot/dts/kilauea.dts b/arch/powerpc/boot/dts/kilauea.dts
new file mode 100644
index 00000000000..c824e8f0645
--- /dev/null
+++ b/arch/powerpc/boot/dts/kilauea.dts
@@ -0,0 +1,252 @@
+/*
+ * Device Tree Source for AMCC Kilauea (405EX)
+ *
+ * Copyright 2007 DENX Software Engineering, Stefan Roese <sr@denx.de>
+ *
+ * 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.
+ */
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "amcc,kilauea";
+ compatible = "amcc,kilauea";
+ dcr-parent = <&/cpus/PowerPC,405EX@0>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,405EX@0 {
+ device_type = "cpu";
+ reg = <0>;
+ clock-frequency = <0>; /* Filled in by U-Boot */
+ timebase-frequency = <0>; /* Filled in by U-Boot */
+ i-cache-line-size = <20>;
+ d-cache-line-size = <20>;
+ i-cache-size = <4000>; /* 16 kB */
+ d-cache-size = <4000>; /* 16 kB */
+ dcr-controller;
+ dcr-access-method = "native";
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0 0>; /* Filled in by U-Boot */
+ };
+
+ UIC0: interrupt-controller {
+ compatible = "ibm,uic-405ex", "ibm,uic";
+ interrupt-controller;
+ cell-index = <0>;
+ dcr-reg = <0c0 009>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ #interrupt-cells = <2>;
+ };
+
+ UIC1: interrupt-controller1 {
+ compatible = "ibm,uic-405ex","ibm,uic";
+ interrupt-controller;
+ cell-index = <1>;
+ dcr-reg = <0d0 009>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ #interrupt-cells = <2>;
+ interrupts = <1e 4 1f 4>; /* cascade */
+ interrupt-parent = <&UIC0>;
+ };
+
+ UIC2: interrupt-controller2 {
+ compatible = "ibm,uic-405ex","ibm,uic";
+ interrupt-controller;
+ cell-index = <2>;
+ dcr-reg = <0e0 009>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ #interrupt-cells = <2>;
+ interrupts = <1c 4 1d 4>; /* cascade */
+ interrupt-parent = <&UIC0>;
+ };
+
+ plb {
+ compatible = "ibm,plb-405ex", "ibm,plb4";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ clock-frequency = <0>; /* Filled in by U-Boot */
+
+ SDRAM0: memory-controller {
+ compatible = "ibm,sdram-405ex";
+ dcr-reg = <010 2>;
+ };
+
+ MAL0: mcmal {
+ compatible = "ibm,mcmal-405ex", "ibm,mcmal2";
+ dcr-reg = <180 62>;
+ num-tx-chans = <2>;
+ num-rx-chans = <2>;
+ interrupt-parent = <&MAL0>;
+ interrupts = <0 1 2 3 4>;
+ #interrupt-cells = <1>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ interrupt-map = </*TXEOB*/ 0 &UIC0 a 4
+ /*RXEOB*/ 1 &UIC0 b 4
+ /*SERR*/ 2 &UIC1 0 4
+ /*TXDE*/ 3 &UIC1 1 4
+ /*RXDE*/ 4 &UIC1 2 4>;
+ interrupt-map-mask = <ffffffff>;
+ };
+
+ POB0: opb {
+ compatible = "ibm,opb-405ex", "ibm,opb";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <80000000 80000000 10000000
+ ef600000 ef600000 a00000
+ f0000000 f0000000 10000000>;
+ dcr-reg = <0a0 5>;
+ clock-frequency = <0>; /* Filled in by U-Boot */
+
+ EBC0: ebc {
+ compatible = "ibm,ebc-405ex", "ibm,ebc";
+ dcr-reg = <012 2>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ clock-frequency = <0>; /* Filled in by U-Boot */
+ /* ranges property is supplied by U-Boot */
+ interrupts = <5 1>;
+ interrupt-parent = <&UIC1>;
+
+ nor_flash@0,0 {
+ compatible = "amd,s29gl512n", "cfi-flash";
+ bank-width = <2>;
+ reg = <0 000000 4000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partition@0 {
+ label = "kernel";
+ reg = <0 200000>;
+ };
+ partition@200000 {
+ label = "root";
+ reg = <200000 200000>;
+ };
+ partition@400000 {
+ label = "user";
+ reg = <400000 3b60000>;
+ };
+ partition@3f60000 {
+ label = "env";
+ reg = <3f60000 40000>;
+ };
+ partition@3fa0000 {
+ label = "u-boot";
+ reg = <3fa0000 60000>;
+ };
+ };
+ };
+
+ UART0: serial@ef600200 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <ef600200 8>;
+ virtual-reg = <ef600200>;
+ clock-frequency = <0>; /* Filled in by U-Boot */
+ current-speed = <0>;
+ interrupt-parent = <&UIC0>;
+ interrupts = <1a 4>;
+ };
+
+ UART1: serial@ef600300 {
+ device_type = "serial";
+ compatible = "ns16550";
+ reg = <ef600300 8>;
+ virtual-reg = <ef600300>;
+ clock-frequency = <0>; /* Filled in by U-Boot */
+ current-speed = <0>;
+ interrupt-parent = <&UIC0>;
+ interrupts = <1 4>;
+ };
+
+ IIC0: i2c@ef600400 {
+ device_type = "i2c";
+ compatible = "ibm,iic-405ex", "ibm,iic";
+ reg = <ef600400 14>;
+ interrupt-parent = <&UIC0>;
+ interrupts = <2 4>;
+ };
+
+ IIC1: i2c@ef600500 {
+ device_type = "i2c";
+ compatible = "ibm,iic-405ex", "ibm,iic";
+ reg = <ef600500 14>;
+ interrupt-parent = <&UIC0>;
+ interrupts = <7 4>;
+ };
+
+
+ RGMII0: emac-rgmii@ef600b00 {
+ device_type = "rgmii-interface";
+ compatible = "ibm,rgmii-405ex", "ibm,rgmii";
+ reg = <ef600b00 104>;
+ };
+
+ EMAC0: ethernet@ef600900 {
+ linux,network-index = <0>;
+ device_type = "network";
+ compatible = "ibm,emac-405ex", "ibm,emac4";
+ interrupt-parent = <&EMAC0>;
+ interrupts = <0 1>;
+ #interrupt-cells = <1>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ interrupt-map = </*Status*/ 0 &UIC0 18 4
+ /*Wake*/ 1 &UIC1 1d 4>;
+ reg = <ef600900 70>;
+ local-mac-address = [000000000000]; /* Filled in by U-Boot */
+ mal-device = <&MAL0>;
+ mal-tx-channel = <0>;
+ mal-rx-channel = <0>;
+ cell-index = <0>;
+ max-frame-size = <5dc>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+ phy-map = <00000000>;
+ rgmii-device = <&RGMII0>;
+ rgmii-channel = <0>;
+ };
+
+ EMAC1: ethernet@ef600a00 {
+ linux,network-index = <1>;
+ device_type = "network";
+ compatible = "ibm,emac-405ex", "ibm,emac4";
+ interrupt-parent = <&EMAC1>;
+ interrupts = <0 1>;
+ #interrupt-cells = <1>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ interrupt-map = </*Status*/ 0 &UIC0 19 4
+ /*Wake*/ 1 &UIC1 1f 4>;
+ reg = <ef600a00 70>;
+ local-mac-address = [000000000000]; /* Filled in by U-Boot */
+ mal-device = <&MAL0>;
+ mal-tx-channel = <1>;
+ mal-rx-channel = <1>;
+ cell-index = <1>;
+ max-frame-size = <5dc>;
+ rx-fifo-size = <1000>;
+ tx-fifo-size = <800>;
+ phy-mode = "rgmii";
+ phy-map = <00000000>;
+ rgmii-device = <&RGMII0>;
+ rgmii-channel = <1>;
+ };
+ };
+ };
+};
diff --git a/arch/powerpc/boot/uartlite.c b/arch/powerpc/boot/uartlite.c
index 38a470b329e..46bed69b416 100644
--- a/arch/powerpc/boot/uartlite.c
+++ b/arch/powerpc/boot/uartlite.c
@@ -45,8 +45,8 @@ static void uartlite_putc(unsigned char c)
static unsigned char uartlite_getc(void)
{
- u32 reg = ULITE_STATUS_RXVALID;
- while (reg & ULITE_STATUS_RXVALID) /* spin on RXVALID bit */
+ u32 reg = 0;
+ while (!(reg & ULITE_STATUS_RXVALID)) /* spin waiting for RXVALID bit */
reg = in_be32(reg_base + ULITE_STATUS);
return in_be32(reg_base + ULITE_RX);
}
diff --git a/arch/powerpc/configs/kilauea_defconfig b/arch/powerpc/configs/kilauea_defconfig
new file mode 100644
index 00000000000..31790d32926
--- /dev/null
+++ b/arch/powerpc/configs/kilauea_defconfig
@@ -0,0 +1,768 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23-rc9
+# Thu Oct 11 19:05:15 2007
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+# CONFIG_6xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_4xx=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_PPC_DCR_NATIVE=y
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_DCR=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Platform support
+#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_KILAUEA=y
+# CONFIG_WALNUT is not set
+# CONFIG_XILINX_VIRTEX_GENERIC_BOARD is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
+# CONFIG_FSL_ULI1575 is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_MATH_EMULATION is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_HIBERNATION_UP_POSSIBLE=y
+CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE="kilauea.dts"
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# 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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP_OF=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=35000
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_XILINX_SYSACE is not set
+# CONFIG_MISC_DEVICES is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUGGER is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_PPC_CLOCK is not set
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index b03a442b788..d3fb7d0c6c1 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -71,7 +71,7 @@ extern void __restore_cpu_ppc970(void);
#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
PPC_FEATURE_BOOKE)
-static struct cpu_spec cpu_specs[] = {
+static struct cpu_spec __initdata cpu_specs[] = {
#ifdef CONFIG_PPC64
{ /* Power3 */
.pvr_mask = 0xffff0000,
@@ -327,14 +327,6 @@ static struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER_POWER5_PLUS,
.icache_bsize = 128,
.dcache_bsize = 128,
- .num_pmcs = 6,
- .pmc_type = PPC_PMC_IBM,
- .oprofile_cpu_type = "ppc64/power6",
- .oprofile_type = PPC_OPROFILE_POWER4,
- .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
- .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
- .oprofile_mmcra_clear = POWER6_MMCRA_THRM |
- POWER6_MMCRA_OTHER,
.platform = "power5+",
},
{ /* Power6 */
@@ -364,14 +356,6 @@ static struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER_POWER6,
.icache_bsize = 128,
.dcache_bsize = 128,
- .num_pmcs = 6,
- .pmc_type = PPC_PMC_IBM,
- .oprofile_cpu_type = "ppc64/power6",
- .oprofile_type = PPC_OPROFILE_POWER4,
- .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
- .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
- .oprofile_mmcra_clear = POWER6_MMCRA_THRM |
- POWER6_MMCRA_OTHER,
.platform = "power6",
},
{ /* Cell Broadband Engine */
@@ -1103,6 +1087,17 @@ static struct cpu_spec cpu_specs[] = {
.dcache_bsize = 32,
.platform = "ppc405",
},
+ { /* 405EX */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x12910000,
+ .cpu_name = "405EX",
+ .cpu_features = CPU_FTRS_40X,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .platform = "ppc405",
+ },
#endif /* CONFIG_40x */
#ifdef CONFIG_44x
@@ -1316,18 +1311,37 @@ static struct cpu_spec cpu_specs[] = {
#endif /* CONFIG_PPC32 */
};
-struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr)
+static struct cpu_spec the_cpu_spec;
+
+struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
{
struct cpu_spec *s = cpu_specs;
- struct cpu_spec **cur = &cur_cpu_spec;
+ struct cpu_spec *t = &the_cpu_spec;
int i;
s = PTRRELOC(s);
- cur = PTRRELOC(cur);
+ t = PTRRELOC(t);
for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
if ((pvr & s->pvr_mask) == s->pvr_value) {
- *cur = cpu_specs + i;
+ /*
+ * If we are overriding a previous value derived
+ * from the real PVR with a new value obtained
+ * using a logical PVR value, don't modify the
+ * performance monitor fields.
+ */
+ if (t->num_pmcs && !s->num_pmcs) {
+ t->cpu_name = s->cpu_name;
+ t->cpu_features = s->cpu_features;
+ t->cpu_user_features = s->cpu_user_features;
+ t->icache_bsize = s->icache_bsize;
+ t->dcache_bsize = s->dcache_bsize;
+ t->cpu_setup = s->cpu_setup;
+ t->cpu_restore = s->cpu_restore;
+ t->platform = s->platform;
+ } else
+ *t = *s;
+ *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
#if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE)
/* ppc64 and booke expect identify_cpu to also call
* setup_cpu for that processor. I will consolidate
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index f70e787d556..eca8ccc3fa1 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -19,11 +19,11 @@
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <linux/pci.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
#include <asm/errno.h>
#include <asm/dcr.h>
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
#include <asm/topology.h>
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
@@ -70,7 +70,10 @@ postcore_initcall(of_bus_driver_init);
int of_register_platform_driver(struct of_platform_driver *drv)
{
/* initialize common driver fields */
- drv->driver.name = drv->name;
+ if (!drv->driver.name)
+ drv->driver.name = drv->name;
+ if (!drv->driver.owner)
+ drv->driver.owner = drv->owner;
drv->driver.bus = &of_platform_bus_type;
/* register with core */
@@ -385,9 +388,11 @@ static struct of_device_id of_pci_phb_ids[] = {
};
static struct of_platform_driver of_pci_phb_driver = {
- .name = "of-pci",
- .match_table = of_pci_phb_ids,
- .probe = of_pci_phb_probe,
+ .match_table = of_pci_phb_ids,
+ .probe = of_pci_phb_probe,
+ .driver = {
+ .name = "of-pci",
+ },
};
static __init int of_pci_phb_init(void)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 172dcc3849a..9f329a8928e 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -531,10 +531,7 @@ static struct ibm_pa_feature {
{CPU_FTR_CTRL, 0, 0, 3, 0},
{CPU_FTR_NOEXECUTE, 0, 0, 6, 0},
{CPU_FTR_NODSISRALIGN, 0, 1, 1, 1},
-#if 0
- /* put this back once we know how to test if firmware does 64k IO */
{CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0},
-#endif
{CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},
};
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 7474502dace..cd870a823d1 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -290,7 +290,8 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &dummy_con;
#endif
- ppc_md.setup_arch();
+ if (ppc_md.setup_arch)
+ ppc_md.setup_arch();
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
paging_init();
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 3089eaed325..008ab6823b0 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -530,7 +530,8 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &dummy_con;
#endif
- ppc_md.setup_arch();
+ if (ppc_md.setup_arch)
+ ppc_md.setup_arch();
paging_init();
ppc64_boot_msg(0x15, "Setup Done");
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 579de70e0b4..93219c34af3 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -39,6 +39,8 @@
#ifdef CONFIG_PPC64
#define sys_sigpending sys_ni_syscall
#define sys_old_getrlimit sys_ni_syscall
+
+ .p2align 3
#endif
_GLOBAL(sys_call_table)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index d20947cf173..9368da371f3 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -108,7 +108,7 @@ static void decrementer_set_mode(enum clock_event_mode mode,
static struct clock_event_device decrementer_clockevent = {
.name = "decrementer",
.rating = 200,
- .shift = 32,
+ .shift = 16,
.mult = 0, /* To be filled in */
.irq = 0,
.set_next_event = decrementer_set_next_event,
@@ -118,6 +118,7 @@ static struct clock_event_device decrementer_clockevent = {
static DEFINE_PER_CPU(struct clock_event_device, decrementers);
void init_decrementer_clockevent(void);
+static DEFINE_PER_CPU(u64, decrementer_next_tb);
#ifdef CONFIG_PPC_ISERIES
static unsigned long __initdata iSeries_recal_titan;
@@ -541,6 +542,7 @@ void timer_interrupt(struct pt_regs * regs)
struct pt_regs *old_regs;
int cpu = smp_processor_id();
struct clock_event_device *evt = &per_cpu(decrementers, cpu);
+ u64 now;
/* Ensure a positive value is written to the decrementer, or else
* some CPUs will continuue to take decrementer exceptions */
@@ -551,6 +553,14 @@ void timer_interrupt(struct pt_regs * regs)
do_IRQ(regs);
#endif
+ now = get_tb_or_rtc();
+ if (now < per_cpu(decrementer_next_tb, cpu)) {
+ /* not time for this event yet */
+ now = per_cpu(decrementer_next_tb, cpu) - now;
+ if (now <= DECREMENTER_MAX)
+ set_dec((unsigned int)now - 1);
+ return;
+ }
old_regs = set_irq_regs(regs);
irq_enter();
@@ -797,6 +807,10 @@ void __init clocksource_init(void)
static int decrementer_set_next_event(unsigned long evt,
struct clock_event_device *dev)
{
+ __get_cpu_var(decrementer_next_tb) = get_tb_or_rtc() + evt;
+ /* The decrementer interrupts on the 0 -> -1 transition */
+ if (evt)
+ --evt;
set_dec(evt);
return 0;
}
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 213fa31ac53..2322ba5cce4 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -766,7 +766,9 @@ static int __init vdso_init(void)
return 0;
}
+#ifdef CONFIG_PPC_MERGE
arch_initcall(vdso_init);
+#endif
int in_gate_area_no_task(unsigned long addr)
{
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 1d7b272b373..cb22a3557c4 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -48,66 +48,33 @@ static struct vio_dev vio_bus_device = { /* fake "parent" device */
.dev.bus = &vio_bus_type,
};
-#ifdef CONFIG_PPC_ISERIES
-struct device *iSeries_vio_dev = &vio_bus_device.dev;
-EXPORT_SYMBOL(iSeries_vio_dev);
+static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
+{
+ const unsigned char *dma_window;
+ struct iommu_table *tbl;
+ unsigned long offset, size;
-static struct iommu_table veth_iommu_table;
-static struct iommu_table vio_iommu_table;
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ return vio_build_iommu_table_iseries(dev);
-static void __init iommu_vio_init(void)
-{
- iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
- veth_iommu_table.it_size /= 2;
- vio_iommu_table = veth_iommu_table;
- vio_iommu_table.it_offset += veth_iommu_table.it_size;
-
- if (!iommu_init_table(&veth_iommu_table, -1))
- printk("Virtual Bus VETH TCE table failed.\n");
- if (!iommu_init_table(&vio_iommu_table, -1))
- printk("Virtual Bus VIO TCE table failed.\n");
- vio_bus_device.dev.archdata.dma_ops = &dma_iommu_ops;
- vio_bus_device.dev.archdata.dma_data = &vio_iommu_table;
-}
-#else
-static void __init iommu_vio_init(void)
-{
-}
-#endif
+ dma_window = of_get_property(dev->dev.archdata.of_node,
+ "ibm,my-dma-window", NULL);
+ if (!dma_window)
+ return NULL;
-static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
-{
-#ifdef CONFIG_PPC_ISERIES
- if (firmware_has_feature(FW_FEATURE_ISERIES)) {
- if (strcmp(dev->type, "network") == 0)
- return &veth_iommu_table;
- return &vio_iommu_table;
- } else
-#endif
- {
- const unsigned char *dma_window;
- struct iommu_table *tbl;
- unsigned long offset, size;
-
- dma_window = of_get_property(dev->dev.archdata.of_node,
- "ibm,my-dma-window", NULL);
- if (!dma_window)
- return NULL;
-
- tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
-
- of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
- &tbl->it_index, &offset, &size);
-
- /* TCE table size - measured in tce entries */
- tbl->it_size = size >> IOMMU_PAGE_SHIFT;
- /* offset for VIO should always be 0 */
- tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
- tbl->it_busno = 0;
- tbl->it_type = TCE_VB;
-
- return iommu_init_table(tbl, -1);
- }
+ tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
+
+ of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
+ &tbl->it_index, &offset, &size);
+
+ /* TCE table size - measured in tce entries */
+ tbl->it_size = size >> IOMMU_PAGE_SHIFT;
+ /* offset for VIO should always be 0 */
+ tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
+ tbl->it_busno = 0;
+ tbl->it_type = TCE_VB;
+
+ return iommu_init_table(tbl, -1);
}
/**
@@ -168,16 +135,6 @@ static int vio_bus_remove(struct device *dev)
return 1;
}
-/* convert from struct device to struct vio_dev and pass to driver. */
-static void vio_bus_shutdown(struct device *dev)
-{
- struct vio_dev *viodev = to_vio_dev(dev);
- struct vio_driver *viodrv = to_vio_driver(dev->driver);
-
- if (dev->driver && viodrv->shutdown)
- viodrv->shutdown(viodev);
-}
-
/**
* vio_register_driver: - Register a new vio driver
* @drv: The vio_driver structure to be registered.
@@ -290,9 +247,6 @@ static int __init vio_bus_init(void)
int err;
struct device_node *node_vroot;
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- iommu_vio_init();
-
err = bus_register(&vio_bus_type);
if (err) {
printk(KERN_ERR "failed to register VIO bus\n");
@@ -397,7 +351,6 @@ static struct bus_type vio_bus_type = {
.match = vio_bus_match,
.probe = vio_bus_probe,
.remove = vio_bus_remove,
- .shutdown = vio_bus_shutdown,
};
/**
diff --git a/arch/powerpc/oprofile/cell/pr_util.h b/arch/powerpc/oprofile/cell/pr_util.h
index e5704f00c8b..22e4e8d4eb2 100644
--- a/arch/powerpc/oprofile/cell/pr_util.h
+++ b/arch/powerpc/oprofile/cell/pr_util.h
@@ -17,10 +17,9 @@
#include <linux/cpumask.h>
#include <linux/oprofile.h>
#include <asm/cell-pmu.h>
+#include <asm/cell-regs.h>
#include <asm/spu.h>
-#include "../../platforms/cell/cbe_regs.h"
-
/* Defines used for sync_start */
#define SKIP_GENERIC_SYNC 0
#define SYNC_START_ERROR -1
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c
index d928b54f3a0..bb6bff51ce4 100644
--- a/arch/powerpc/oprofile/op_model_cell.c
+++ b/arch/powerpc/oprofile/op_model_cell.c
@@ -35,9 +35,9 @@
#include <asm/reg.h>
#include <asm/rtas.h>
#include <asm/system.h>
+#include <asm/cell-regs.h>
#include "../platforms/cell/interrupt.h"
-#include "../platforms/cell/cbe_regs.h"
#include "cell/pr_util.h"
static void cell_global_stop_spu(void);
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
index a0a50b16b8a..47b3b0a3864 100644
--- a/arch/powerpc/platforms/40x/Kconfig
+++ b/arch/powerpc/platforms/40x/Kconfig
@@ -29,6 +29,13 @@
# help
# This option enables support for the extra features of the EP405PC board.
+config KILAUEA
+ bool "Kilauea"
+ depends on 40x
+ default n
+ help
+ This option enables support for the AMCC PPC405EX evaluation board.
+
#config REDWOOD_5
# bool "Redwood-5"
# depends on 40x
diff --git a/arch/powerpc/platforms/40x/Makefile b/arch/powerpc/platforms/40x/Makefile
index 0a3cfe99a7e..51dadeee6fc 100644
--- a/arch/powerpc/platforms/40x/Makefile
+++ b/arch/powerpc/platforms/40x/Makefile
@@ -1,2 +1,3 @@
-obj-$(CONFIG_WALNUT) += walnut.o
-obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD) += virtex.o
+obj-$(CONFIG_KILAUEA) += kilauea.o
+obj-$(CONFIG_WALNUT) += walnut.o
+obj-$(CONFIG_XILINX_VIRTEX_GENERIC_BOARD) += virtex.o
diff --git a/arch/powerpc/platforms/40x/kilauea.c b/arch/powerpc/platforms/40x/kilauea.c
new file mode 100644
index 00000000000..1bffdbdd21b
--- /dev/null
+++ b/arch/powerpc/platforms/40x/kilauea.c
@@ -0,0 +1,58 @@
+/*
+ * Kilauea board specific routines
+ *
+ * Copyright 2007 DENX Software Engineering, Stefan Roese <sr@denx.de>
+ *
+ * Based on the Walnut code by
+ * Josh Boyer <jwboyer@linux.vnet.ibm.com>
+ * Copyright 2007 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 <linux/init.h>
+#include <linux/of_platform.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/time.h>
+#include <asm/uic.h>
+
+static struct of_device_id kilauea_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+ { .compatible = "ibm,opb", },
+ { .compatible = "ibm,ebc", },
+ {},
+};
+
+static int __init kilauea_device_probe(void)
+{
+ if (!machine_is(kilauea))
+ return 0;
+
+ of_platform_bus_probe(NULL, kilauea_of_bus, NULL);
+
+ return 0;
+}
+device_initcall(kilauea_device_probe);
+
+static int __init kilauea_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (!of_flat_dt_is_compatible(root, "amcc,kilauea"))
+ return 0;
+
+ return 1;
+}
+
+define_machine(kilauea) {
+ .name = "Kilauea",
+ .probe = kilauea_probe,
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
+ .calibrate_decr = generic_calibrate_decr,
+};
diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c
index b52aa94abd7..14bbc328170 100644
--- a/arch/powerpc/platforms/40x/virtex.c
+++ b/arch/powerpc/platforms/40x/virtex.c
@@ -36,14 +36,9 @@ static int __init virtex_probe(void)
return 1;
}
-static void __init virtex_setup_arch(void)
-{
-}
-
define_machine(virtex) {
.name = "Xilinx Virtex",
.probe = virtex_probe,
- .setup_arch = virtex_setup_arch,
.init_IRQ = xilinx_intc_init_tree,
.get_irq = xilinx_intc_get_irq,
.calibrate_decr = generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c
index c17fdf23b49..eb0c136b1c4 100644
--- a/arch/powerpc/platforms/40x/walnut.c
+++ b/arch/powerpc/platforms/40x/walnut.c
@@ -53,14 +53,9 @@ static int __init walnut_probe(void)
return 1;
}
-static void __init walnut_setup_arch(void)
-{
-}
-
define_machine(walnut) {
.name = "Walnut",
.probe = walnut_probe,
- .setup_arch = walnut_setup_arch,
.progress = udbg_progress,
.init_IRQ = uic_init_tree,
.get_irq = uic_get_irq,
diff --git a/arch/powerpc/platforms/44x/bamboo.c b/arch/powerpc/platforms/44x/bamboo.c
index 9bc45dea078..470e1a3fd75 100644
--- a/arch/powerpc/platforms/44x/bamboo.c
+++ b/arch/powerpc/platforms/44x/bamboo.c
@@ -50,14 +50,9 @@ static int __init bamboo_probe(void)
return 1;
}
-static void __init bamboo_setup_arch(void)
-{
-}
-
define_machine(bamboo) {
.name = "Bamboo",
.probe = bamboo_probe,
- .setup_arch = bamboo_setup_arch,
.progress = udbg_progress,
.init_IRQ = uic_init_tree,
.get_irq = uic_get_irq,
diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c
index 5a7fec8d10d..40e18fcb666 100644
--- a/arch/powerpc/platforms/44x/ebony.c
+++ b/arch/powerpc/platforms/44x/ebony.c
@@ -57,14 +57,9 @@ static int __init ebony_probe(void)
return 1;
}
-static void __init ebony_setup_arch(void)
-{
-}
-
define_machine(ebony) {
.name = "Ebony",
.probe = ebony_probe,
- .setup_arch = ebony_setup_arch,
.progress = udbg_progress,
.init_IRQ = uic_init_tree,
.get_irq = uic_get_irq,
diff --git a/arch/powerpc/platforms/44x/sequoia.c b/arch/powerpc/platforms/44x/sequoia.c
index 7d0d9d567d2..30700b31d43 100644
--- a/arch/powerpc/platforms/44x/sequoia.c
+++ b/arch/powerpc/platforms/44x/sequoia.c
@@ -50,14 +50,9 @@ static int __init sequoia_probe(void)
return 1;
}
-static void __init sequoia_setup_arch(void)
-{
-}
-
define_machine(sequoia) {
.name = "Sequoia",
.probe = sequoia_probe,
- .setup_arch = sequoia_setup_arch,
.progress = udbg_progress,
.init_IRQ = uic_init_tree,
.get_irq = uic_get_irq,
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index 6fc17faf74b..a0da70c8b50 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -180,15 +180,6 @@ static void __init efika_setup_arch(void)
{
rtas_initialize();
-#ifdef CONFIG_BLK_DEV_INITRD
- initrd_below_start_ok = 1;
-
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
- ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
-
efika_pcisetup();
#ifdef CONFIG_PM
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
index 0b6e8ee85ab..901236fa0f0 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -24,7 +24,7 @@
#include <asm/machdep.h>
#include <asm/of_platform.h>
#include <asm/prom.h>
-#include "cbe_regs.h"
+#include <asm/cell-regs.h>
#include "cbe_cpufreq.h"
static DEFINE_MUTEX(cbe_switch_mutex);
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
index 163263b3e1c..70fa7aef5ed 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
@@ -28,8 +28,8 @@
#include <linux/time.h>
#include <asm/machdep.h>
#include <asm/hw_irq.h>
+#include <asm/cell-regs.h>
-#include "cbe_regs.h"
#include "cbe_cpufreq.h"
/* to write to MIC register */
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
index fc6f38982ff..6a2c1b0a9a9 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
@@ -27,12 +27,12 @@
#include <asm/processor.h>
#include <asm/prom.h>
#include <asm/pmi.h>
+#include <asm/cell-regs.h>
#ifdef DEBUG
#include <asm/time.h>
#endif
-#include "cbe_regs.h"
#include "cbe_cpufreq.h"
static u8 pmi_slow_mode_limit[MAX_CBE];
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c
index c8f7f000742..16a9b07e7b0 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.c
+++ b/arch/powerpc/platforms/cell/cbe_regs.c
@@ -16,8 +16,7 @@
#include <asm/ptrace.h>
#include <asm/of_device.h>
#include <asm/of_platform.h>
-
-#include "cbe_regs.h"
+#include <asm/cell-regs.h>
/*
* Current implementation uses "cpu" nodes. We build our own mapping
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h
deleted file mode 100644
index b24025f2ac7..00000000000
--- a/arch/powerpc/platforms/cell/cbe_regs.h
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * cbe_regs.h
- *
- * This file is intended to hold the various register definitions for CBE
- * on-chip system devices (memory controller, IO controller, etc...)
- *
- * (C) Copyright IBM Corporation 2001,2006
- *
- * Authors: Maximino Aguilar (maguilar@us.ibm.com)
- * David J. Erb (djerb@us.ibm.com)
- *
- * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
- */
-
-#ifndef CBE_REGS_H
-#define CBE_REGS_H
-
-#include <asm/cell-pmu.h>
-
-/*
- *
- * Some HID register definitions
- *
- */
-
-/* CBE specific HID0 bits */
-#define HID0_CBE_THERM_WAKEUP 0x0000020000000000ul
-#define HID0_CBE_SYSERR_WAKEUP 0x0000008000000000ul
-#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul
-#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul
-
-#define MAX_CBE 2
-
-/*
- *
- * Pervasive unit register definitions
- *
- */
-
-union spe_reg {
- u64 val;
- u8 spe[8];
-};
-
-union ppe_spe_reg {
- u64 val;
- struct {
- u32 ppe;
- u32 spe;
- };
-};
-
-
-struct cbe_pmd_regs {
- /* Debug Bus Control */
- u64 pad_0x0000; /* 0x0000 */
-
- u64 group_control; /* 0x0008 */
-
- u8 pad_0x0010_0x00a8 [0x00a8 - 0x0010]; /* 0x0010 */
-
- u64 debug_bus_control; /* 0x00a8 */
-
- u8 pad_0x00b0_0x0100 [0x0100 - 0x00b0]; /* 0x00b0 */
-
- u64 trace_aux_data; /* 0x0100 */
- u64 trace_buffer_0_63; /* 0x0108 */
- u64 trace_buffer_64_127; /* 0x0110 */
- u64 trace_address; /* 0x0118 */
- u64 ext_tr_timer; /* 0x0120 */
-
- u8 pad_0x0128_0x0400 [0x0400 - 0x0128]; /* 0x0128 */
-
- /* Performance Monitor */
- u64 pm_status; /* 0x0400 */
- u64 pm_control; /* 0x0408 */
- u64 pm_interval; /* 0x0410 */
- u64 pm_ctr[4]; /* 0x0418 */
- u64 pm_start_stop; /* 0x0438 */
- u64 pm07_control[8]; /* 0x0440 */
-
- u8 pad_0x0480_0x0800 [0x0800 - 0x0480]; /* 0x0480 */
-
- /* Thermal Sensor Registers */
- union spe_reg ts_ctsr1; /* 0x0800 */
- u64 ts_ctsr2; /* 0x0808 */
- union spe_reg ts_mtsr1; /* 0x0810 */
- u64 ts_mtsr2; /* 0x0818 */
- union spe_reg ts_itr1; /* 0x0820 */
- u64 ts_itr2; /* 0x0828 */
- u64 ts_gitr; /* 0x0830 */
- u64 ts_isr; /* 0x0838 */
- u64 ts_imr; /* 0x0840 */
- union spe_reg tm_cr1; /* 0x0848 */
- u64 tm_cr2; /* 0x0850 */
- u64 tm_simr; /* 0x0858 */
- union ppe_spe_reg tm_tpr; /* 0x0860 */
- union spe_reg tm_str1; /* 0x0868 */
- u64 tm_str2; /* 0x0870 */
- union ppe_spe_reg tm_tsr; /* 0x0878 */
-
- /* Power Management */
- u64 pmcr; /* 0x0880 */
-#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000
- u64 pmsr; /* 0x0888 */
-
- /* Time Base Register */
- u64 tbr; /* 0x0890 */
-
- u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */
-
- /* Fault Isolation Registers */
- u64 checkstop_fir; /* 0x0c00 */
- u64 recoverable_fir; /* 0x0c08 */
- u64 spec_att_mchk_fir; /* 0x0c10 */
- u32 fir_mode_reg; /* 0x0c18 */
- u8 pad_0x0c1c_0x0c20 [4]; /* 0x0c1c */
-#define CBE_PMD_FIR_MODE_M8 0x00800
- u64 fir_enable_mask; /* 0x0c20 */
-
- u8 pad_0x0c28_0x0ca8 [0x0ca8 - 0x0c28]; /* 0x0c28 */
- u64 ras_esc_0; /* 0x0ca8 */
- u8 pad_0x0cb0_0x1000 [0x1000 - 0x0cb0]; /* 0x0cb0 */
-};
-
-extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
-extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu);
-
-/*
- * PMU shadow registers
- *
- * Many of the registers in the performance monitoring unit are write-only,
- * so we need to save a copy of what we write to those registers.
- *
- * The actual data counters are read/write. However, writing to the counters
- * only takes effect if the PMU is enabled. Otherwise the value is stored in
- * a hardware latch until the next time the PMU is enabled. So we save a copy
- * of the counter values if we need to read them back while the PMU is
- * disabled. The counter_value_in_latch field is a bitmap indicating which
- * counters currently have a value waiting to be written.
- */
-
-struct cbe_pmd_shadow_regs {
- u32 group_control;
- u32 debug_bus_control;
- u32 trace_address;
- u32 ext_tr_timer;
- u32 pm_status;
- u32 pm_control;
- u32 pm_interval;
- u32 pm_start_stop;
- u32 pm07_control[NR_CTRS];
-
- u32 pm_ctr[NR_PHYS_CTRS];
- u32 counter_value_in_latch;
-};
-
-extern struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np);
-extern struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu);
-
-/*
- *
- * IIC unit register definitions
- *
- */
-
-struct cbe_iic_pending_bits {
- u32 data;
- u8 flags;
- u8 class;
- u8 source;
- u8 prio;
-};
-
-#define CBE_IIC_IRQ_VALID 0x80
-#define CBE_IIC_IRQ_IPI 0x40
-
-struct cbe_iic_thread_regs {
- struct cbe_iic_pending_bits pending;
- struct cbe_iic_pending_bits pending_destr;
- u64 generate;
- u64 prio;
-};
-
-struct cbe_iic_regs {
- u8 pad_0x0000_0x0400[0x0400 - 0x0000]; /* 0x0000 */
-
- /* IIC interrupt registers */
- struct cbe_iic_thread_regs thread[2]; /* 0x0400 */
-
- u64 iic_ir; /* 0x0440 */
-#define CBE_IIC_IR_PRIO(x) (((x) & 0xf) << 12)
-#define CBE_IIC_IR_DEST_NODE(x) (((x) & 0xf) << 4)
-#define CBE_IIC_IR_DEST_UNIT(x) ((x) & 0xf)
-#define CBE_IIC_IR_IOC_0 0x0
-#define CBE_IIC_IR_IOC_1S 0xb
-#define CBE_IIC_IR_PT_0 0xe
-#define CBE_IIC_IR_PT_1 0xf
-
- u64 iic_is; /* 0x0448 */
-#define CBE_IIC_IS_PMI 0x2
-
- u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */
-
- /* IOC FIR */
- u64 ioc_fir_reset; /* 0x0500 */
- u64 ioc_fir_set; /* 0x0508 */
- u64 ioc_checkstop_enable; /* 0x0510 */
- u64 ioc_fir_error_mask; /* 0x0518 */
- u64 ioc_syserr_enable; /* 0x0520 */
- u64 ioc_fir; /* 0x0528 */
-
- u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */
-};
-
-extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np);
-extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu);
-
-
-struct cbe_mic_tm_regs {
- u8 pad_0x0000_0x0040[0x0040 - 0x0000]; /* 0x0000 */
-
- u64 mic_ctl_cnfg2; /* 0x0040 */
-#define CBE_MIC_ENABLE_AUX_TRC 0x8000000000000000LL
-#define CBE_MIC_DISABLE_PWR_SAV_2 0x0200000000000000LL
-#define CBE_MIC_DISABLE_AUX_TRC_WRAP 0x0100000000000000LL
-#define CBE_MIC_ENABLE_AUX_TRC_INT 0x0080000000000000LL
-
- u64 pad_0x0048; /* 0x0048 */
-
- u64 mic_aux_trc_base; /* 0x0050 */
- u64 mic_aux_trc_max_addr; /* 0x0058 */
- u64 mic_aux_trc_cur_addr; /* 0x0060 */
- u64 mic_aux_trc_grf_addr; /* 0x0068 */
- u64 mic_aux_trc_grf_data; /* 0x0070 */
-
- u64 pad_0x0078; /* 0x0078 */
-
- u64 mic_ctl_cnfg_0; /* 0x0080 */
-#define CBE_MIC_DISABLE_PWR_SAV_0 0x8000000000000000LL
-
- u64 pad_0x0088; /* 0x0088 */
-
- u64 slow_fast_timer_0; /* 0x0090 */
- u64 slow_next_timer_0; /* 0x0098 */
-
- u8 pad_0x00a0_0x01c0[0x01c0 - 0x0a0]; /* 0x00a0 */
-
- u64 mic_ctl_cnfg_1; /* 0x01c0 */
-#define CBE_MIC_DISABLE_PWR_SAV_1 0x8000000000000000LL
- u64 pad_0x01c8; /* 0x01c8 */
-
- u64 slow_fast_timer_1; /* 0x01d0 */
- u64 slow_next_timer_1; /* 0x01d8 */
-
- u8 pad_0x01e0_0x1000[0x1000 - 0x01e0]; /* 0x01e0 */
-};
-
-extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np);
-extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu);
-
-/* some utility functions to deal with SMT */
-extern u32 cbe_get_hw_thread_id(int cpu);
-extern u32 cbe_cpu_to_node(int cpu);
-extern u32 cbe_node_to_cpu(int node);
-
-/* Init this module early */
-extern void cbe_regs_init(void);
-
-
-#endif /* CBE_REGS_H */
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c
index fb5eda48467..4852bf312d8 100644
--- a/arch/powerpc/platforms/cell/cbe_thermal.c
+++ b/arch/powerpc/platforms/cell/cbe_thermal.c
@@ -52,8 +52,8 @@
#include <asm/spu.h>
#include <asm/io.h>
#include <asm/prom.h>
+#include <asm/cell-regs.h>
-#include "cbe_regs.h"
#include "spu_priv1_mmio.h"
#define TEMP_MIN 65
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index c29e634177f..151fd8b82d6 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -41,9 +41,9 @@
#include <asm/prom.h>
#include <asm/ptrace.h>
#include <asm/machdep.h>
+#include <asm/cell-regs.h>
#include "interrupt.h"
-#include "cbe_regs.h"
struct iic {
struct cbe_iic_thread_regs __iomem *regs;
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 760caa76841..faabc3fdc13 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -34,8 +34,8 @@
#include <asm/udbg.h>
#include <asm/of_platform.h>
#include <asm/lmb.h>
+#include <asm/cell-regs.h>
-#include "cbe_regs.h"
#include "interrupt.h"
/* Define CELL_IOMMU_REAL_UNMAP to actually unmap non-used pages
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 4ede22d363f..0304589c0a8 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -34,9 +34,9 @@
#include <asm/prom.h>
#include <asm/pgtable.h>
#include <asm/reg.h>
+#include <asm/cell-regs.h>
#include "pervasive.h"
-#include "cbe_regs.h"
static int sysreset_hack;
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c
index 66ca4b5a1db..1ed30367888 100644
--- a/arch/powerpc/platforms/cell/pmu.c
+++ b/arch/powerpc/platforms/cell/pmu.c
@@ -30,8 +30,8 @@
#include <asm/pmc.h>
#include <asm/reg.h>
#include <asm/spu.h>
+#include <asm/cell-regs.h>
-#include "cbe_regs.h"
#include "interrupt.h"
/*
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 3961a085b43..b2494ebcdbe 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -10,9 +10,9 @@
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/rtas.h>
+#include <asm/cell-regs.h>
#include "ras.h"
-#include "cbe_regs.h"
static void dump_fir(int cpu)
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index db6654272e1..98e7ef8e6fc 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -52,9 +52,9 @@
#include <asm/udbg.h>
#include <asm/mpic.h>
#include <asm/of_platform.h>
+#include <asm/cell-regs.h>
#include "interrupt.h"
-#include "cbe_regs.h"
#include "pervasive.h"
#include "ras.h"
@@ -83,12 +83,22 @@ static void cell_progress(char *s, unsigned short hex)
static int __init cell_publish_devices(void)
{
+ int node;
+
if (!machine_is(cell))
return 0;
/* Publish OF platform devices for southbridge IOs */
of_platform_bus_probe(NULL, NULL, NULL);
+ /* There is no device for the MIC memory controller, thus we create
+ * a platform device for it to attach the EDAC driver to.
+ */
+ for_each_online_node(node) {
+ if (cbe_get_cpu_mic_tm_regs(cbe_node_to_cpu(node)) == NULL)
+ continue;
+ platform_device_register_simple("cbe-mic", node, NULL, 0);
+ }
return 0;
}
device_initcall(cell_publish_devices);
@@ -161,11 +171,6 @@ static void __init cell_setup_arch(void)
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000;
- if (ROOT_DEV == 0) {
- printk("No ramdisk, default root is /dev/hda2\n");
- ROOT_DEV = Root_HDA2;
- }
-
/* Find and initialize PCI host bridges */
init_pci_config_tokens();
find_and_init_phbs();
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
index 0f1dddb81cd..1769d755eff 100644
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -101,11 +101,6 @@ static void __init celleb_setup_arch(void)
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000;
- if (ROOT_DEV == 0) {
- printk("No ramdisk, default root is /dev/hda2\n");
- ROOT_DEV = Root_HDA2;
- }
-
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 96498ad7b94..59306261f5b 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -290,16 +290,6 @@ void __init chrp_setup_arch(void)
ppc_md.set_rtc_time = rtas_set_rtc_time;
}
-#ifdef CONFIG_BLK_DEV_INITRD
- /* this is fine for chrp */
- initrd_below_start_ok = 1;
-
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
- ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
-
/* On pegasos, enable the L2 cache if not already done by OF */
pegasos_set_l2cr();
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index 60db509638f..a65f1b44abf 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -7,7 +7,7 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
hvcall.o proc.o htab.o iommu.o misc.o irq.o
obj-$(CONFIG_PCI) += pci.o vpdinfo.o
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_VIOPATH) += viopath.o
+obj-$(CONFIG_VIOPATH) += viopath.o vio.o
obj-$(CONFIG_MODULES) += ksyms.o
quiet_cmd_dt_strings = DT_STR $@
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 9e8a334a518..4543c4bc3a5 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -72,8 +72,6 @@ static char __initdata device_type_cpu[] = "cpu";
static char __initdata device_type_memory[] = "memory";
static char __initdata device_type_serial[] = "serial";
static char __initdata device_type_network[] = "network";
-static char __initdata device_type_block[] = "block";
-static char __initdata device_type_byte[] = "byte";
static char __initdata device_type_pci[] = "pci";
static char __initdata device_type_vdevice[] = "vdevice";
static char __initdata device_type_vscsi[] = "vscsi";
@@ -375,21 +373,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
dt_end_node(dt);
}
- reg += HVMAXARCHITECTEDVIRTUALLANS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
- dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
- "IBM,iSeries-viodasd", 1);
- reg += HVMAXARCHITECTEDVIRTUALDISKS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
- dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
- "IBM,iSeries-viocd", 1);
- reg += HVMAXARCHITECTEDVIRTUALCDROMS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
- dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
- "IBM,iSeries-viotape", 1);
dt_end_node(dt);
}
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 3b6a9666c2c..49e9c664ea8 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -28,14 +28,17 @@
#include <linux/dma-mapping.h>
#include <linux/list.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <asm/iommu.h>
+#include <asm/vio.h>
#include <asm/tce.h>
#include <asm/machdep.h>
#include <asm/abs_addr.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/hv_call_event.h>
#include <asm/iseries/iommu.h>
static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
@@ -189,6 +192,55 @@ void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn)
}
#endif
+static struct iommu_table veth_iommu_table;
+static struct iommu_table vio_iommu_table;
+
+void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
+{
+ return iommu_alloc_coherent(&vio_iommu_table, size, dma_handle,
+ DMA_32BIT_MASK, flag, -1);
+}
+EXPORT_SYMBOL_GPL(iseries_hv_alloc);
+
+void iseries_hv_free(size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+ iommu_free_coherent(&vio_iommu_table, size, vaddr, dma_handle);
+}
+EXPORT_SYMBOL_GPL(iseries_hv_free);
+
+dma_addr_t iseries_hv_map(void *vaddr, size_t size,
+ enum dma_data_direction direction)
+{
+ return iommu_map_single(&vio_iommu_table, vaddr, size,
+ DMA_32BIT_MASK, direction);
+}
+
+void iseries_hv_unmap(dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ iommu_unmap_single(&vio_iommu_table, dma_handle, size, direction);
+}
+
+void __init iommu_vio_init(void)
+{
+ iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
+ veth_iommu_table.it_size /= 2;
+ vio_iommu_table = veth_iommu_table;
+ vio_iommu_table.it_offset += veth_iommu_table.it_size;
+
+ if (!iommu_init_table(&veth_iommu_table, -1))
+ printk("Virtual Bus VETH TCE table failed.\n");
+ if (!iommu_init_table(&vio_iommu_table, -1))
+ printk("Virtual Bus VIO TCE table failed.\n");
+}
+
+struct iommu_table *vio_build_iommu_table_iseries(struct vio_dev *dev)
+{
+ if (strcmp(dev->type, "network") == 0)
+ return &veth_iommu_table;
+ return &vio_iommu_table;
+}
+
void iommu_init_early_iSeries(void)
{
ppc_md.tce_build = tce_build_iSeries;
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index b1187d95e3b..c0f2433bc16 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -39,9 +39,9 @@
#include <asm/paca.h>
#include <asm/abs_addr.h>
#include <asm/firmware.h>
-#include <asm/iseries/vio.h>
#include <asm/iseries/mf.h>
#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/it_lp_queue.h>
#include "setup.h"
@@ -870,8 +870,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
if ((off + count) > 256)
count = 256 - off;
- dma_addr = dma_map_single(iSeries_vio_dev, page, off + count,
- DMA_FROM_DEVICE);
+ dma_addr = iseries_hv_map(page, off + count, DMA_FROM_DEVICE);
if (dma_mapping_error(dma_addr))
return -ENOMEM;
memset(page, 0, off + count);
@@ -883,8 +882,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
vsp_cmd.sub_data.kern.length = off + count;
mb();
rc = signal_vsp_instruction(&vsp_cmd);
- dma_unmap_single(iSeries_vio_dev, dma_addr, off + count,
- DMA_FROM_DEVICE);
+ iseries_hv_unmap(dma_addr, off + count, DMA_FROM_DEVICE);
if (rc)
return rc;
if (vsp_cmd.result_code != 0)
@@ -919,8 +917,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
int len = *size;
dma_addr_t dma_addr;
- dma_addr = dma_map_single(iSeries_vio_dev, buffer, len,
- DMA_FROM_DEVICE);
+ dma_addr = iseries_hv_map(buffer, len, DMA_FROM_DEVICE);
memset(buffer, 0, len);
memset(&vsp_cmd, 0, sizeof(vsp_cmd));
vsp_cmd.cmd = 32;
@@ -938,7 +935,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
rc = -ENOMEM;
}
- dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE);
+ iseries_hv_unmap(dma_addr, len, DMA_FROM_DEVICE);
return rc;
}
@@ -1149,8 +1146,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
goto out;
dma_addr = 0;
- page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
- GFP_ATOMIC);
+ page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC);
ret = -ENOMEM;
if (page == NULL)
goto out;
@@ -1170,7 +1166,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
ret = count;
out_free:
- dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
+ iseries_hv_free(count, page, dma_addr);
out:
return ret;
}
@@ -1190,8 +1186,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file,
goto out;
dma_addr = 0;
- page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
- GFP_ATOMIC);
+ page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC);
rc = -ENOMEM;
if (page == NULL) {
printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n");
@@ -1219,7 +1214,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file,
*ppos += count;
rc = count;
out_free:
- dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
+ iseries_hv_free(count, page, dma_addr);
out:
return rc;
}
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
new file mode 100644
index 00000000000..910b00b4703
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -0,0 +1,553 @@
+/*
+ * Legacy iSeries specific vio initialisation
+ * that needs to be built in (not a module).
+ *
+ * © Copyright 2007 IBM Corporation
+ * Author: Stephen Rothwell
+ * Some parts collected from various other files
+ *
+ * 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
+ */
+#include <linux/of.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/completion.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+
+#include <asm/firmware.h>
+#include <asm/vio.h>
+#include <asm/iseries/vio.h>
+#include <asm/iseries/iommu.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_event.h>
+
+#define FIRST_VTY 0
+#define NUM_VTYS 1
+#define FIRST_VSCSI (FIRST_VTY + NUM_VTYS)
+#define NUM_VSCSIS 1
+#define FIRST_VLAN (FIRST_VSCSI + NUM_VSCSIS)
+#define NUM_VLANS HVMAXARCHITECTEDVIRTUALLANS
+#define FIRST_VIODASD (FIRST_VLAN + NUM_VLANS)
+#define NUM_VIODASDS HVMAXARCHITECTEDVIRTUALDISKS
+#define FIRST_VIOCD (FIRST_VIODASD + NUM_VIODASDS)
+#define NUM_VIOCDS HVMAXARCHITECTEDVIRTUALCDROMS
+#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS)
+#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES
+
+struct vio_waitevent {
+ struct completion com;
+ int rc;
+ u16 sub_result;
+};
+
+struct vio_resource {
+ char rsrcname[10];
+ char type[4];
+ char model[3];
+};
+
+static struct property *new_property(const char *name, int length,
+ const void *value)
+{
+ struct property *np = kzalloc(sizeof(*np) + strlen(name) + 1 + length,
+ GFP_KERNEL);
+
+ if (!np)
+ return NULL;
+ np->name = (char *)(np + 1);
+ np->value = np->name + strlen(name) + 1;
+ strcpy(np->name, name);
+ memcpy(np->value, value, length);
+ np->length = length;
+ return np;
+}
+
+static void __init free_property(struct property *np)
+{
+ kfree(np);
+}
+
+static struct device_node *new_node(const char *path,
+ struct device_node *parent)
+{
+ struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL);
+
+ if (!np)
+ return NULL;
+ np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
+ if (!np->full_name) {
+ kfree(np);
+ return NULL;
+ }
+ strcpy(np->full_name, path);
+ of_node_set_flag(np, OF_DYNAMIC);
+ kref_init(&np->kref);
+ np->parent = of_node_get(parent);
+ return np;
+}
+
+static void free_node(struct device_node *np)
+{
+ struct property *next;
+ struct property *prop;
+
+ next = np->properties;
+ while (next) {
+ prop = next;
+ next = prop->next;
+ free_property(prop);
+ }
+ of_node_put(np->parent);
+ kfree(np->full_name);
+ kfree(np);
+}
+
+static int add_string_property(struct device_node *np, const char *name,
+ const char *value)
+{
+ struct property *nprop = new_property(name, strlen(value) + 1, value);
+
+ if (!nprop)
+ return 0;
+ prom_add_property(np, nprop);
+ return 1;
+}
+
+static int add_raw_property(struct device_node *np, const char *name,
+ int length, const void *value)
+{
+ struct property *nprop = new_property(name, length, value);
+
+ if (!nprop)
+ return 0;
+ prom_add_property(np, nprop);
+ return 1;
+}
+
+static struct device_node *do_device_node(struct device_node *parent,
+ const char *name, u32 reg, u32 unit, const char *type,
+ const char *compat, struct vio_resource *res)
+{
+ struct device_node *np;
+ char path[32];
+
+ snprintf(path, sizeof(path), "/vdevice/%s@%08x", name, reg);
+ np = new_node(path, parent);
+ if (!np)
+ return NULL;
+ if (!add_string_property(np, "name", name) ||
+ !add_string_property(np, "device_type", type) ||
+ !add_string_property(np, "compatible", compat) ||
+ !add_raw_property(np, "reg", sizeof(reg), &reg) ||
+ !add_raw_property(np, "linux,unit_address",
+ sizeof(unit), &unit)) {
+ goto node_free;
+ }
+ if (res) {
+ if (!add_raw_property(np, "linux,vio_rsrcname",
+ sizeof(res->rsrcname), res->rsrcname) ||
+ !add_raw_property(np, "linux,vio_type",
+ sizeof(res->type), res->type) ||
+ !add_raw_property(np, "linux,vio_model",
+ sizeof(res->model), res->model))
+ goto node_free;
+ }
+ np->name = of_get_property(np, "name", NULL);
+ np->type = of_get_property(np, "device_type", NULL);
+ of_attach_node(np);
+#ifdef CONFIG_PROC_DEVICETREE
+ if (parent->pde) {
+ struct proc_dir_entry *ent;
+
+ ent = proc_mkdir(strrchr(np->full_name, '/') + 1, parent->pde);
+ if (ent)
+ proc_device_tree_add_node(np, ent);
+ }
+#endif
+ return np;
+
+ node_free:
+ free_node(np);
+ return NULL;
+}
+
+/*
+ * This is here so that we can dynamically add viodasd
+ * devices without exposing all the above infrastructure.
+ */
+struct vio_dev *vio_create_viodasd(u32 unit)
+{
+ struct device_node *vio_root;
+ struct device_node *np;
+ struct vio_dev *vdev = NULL;
+
+ vio_root = of_find_node_by_path("/vdevice");
+ if (!vio_root)
+ return NULL;
+ np = do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
+ "block", "IBM,iSeries-viodasd", NULL);
+ of_node_put(vio_root);
+ if (np) {
+ vdev = vio_register_device_node(np);
+ if (!vdev)
+ free_node(np);
+ }
+ return vdev;
+}
+EXPORT_SYMBOL_GPL(vio_create_viodasd);
+
+static void __init handle_block_event(struct HvLpEvent *event)
+{
+ struct vioblocklpevent *bevent = (struct vioblocklpevent *)event;
+ struct vio_waitevent *pwe;
+
+ if (event == NULL)
+ /* Notification that a partition went away! */
+ return;
+ /* First, we should NEVER get an int here...only acks */
+ if (hvlpevent_is_int(event)) {
+ printk(KERN_WARNING "handle_viod_request: "
+ "Yikes! got an int in viodasd event handler!\n");
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ return;
+ }
+
+ switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+ case vioblockopen:
+ /*
+ * Handle a response to an open request. We get all the
+ * disk information in the response, so update it. The
+ * correlation token contains a pointer to a waitevent
+ * structure that has a completion in it. update the
+ * return code in the waitevent structure and post the
+ * completion to wake up the guy who sent the request
+ */
+ pwe = (struct vio_waitevent *)event->xCorrelationToken;
+ pwe->rc = event->xRc;
+ pwe->sub_result = bevent->sub_result;
+ complete(&pwe->com);
+ break;
+ case vioblockclose:
+ break;
+ default:
+ printk(KERN_WARNING "handle_viod_request: unexpected subtype!");
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ }
+}
+
+static void __init probe_disk(struct device_node *vio_root, u32 unit)
+{
+ HvLpEvent_Rc hvrc;
+ struct vio_waitevent we;
+ u16 flags = 0;
+
+retry:
+ init_completion(&we.com);
+
+ /* Send the open event to OS/400 */
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_blockio | vioblockopen,
+ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ (u64)(unsigned long)&we, VIOVERSION << 16,
+ ((u64)unit << 48) | ((u64)flags<< 32),
+ 0, 0, 0);
+ if (hvrc != 0) {
+ printk(KERN_WARNING "probe_disk: bad rc on HV open %d\n",
+ (int)hvrc);
+ return;
+ }
+
+ wait_for_completion(&we.com);
+
+ if (we.rc != 0) {
+ if (flags != 0)
+ return;
+ /* try again with read only flag set */
+ flags = vioblockflags_ro;
+ goto retry;
+ }
+
+ /* Send the close event to OS/400. We DON'T expect a response */
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_blockio | vioblockclose,
+ HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ 0, VIOVERSION << 16,
+ ((u64)unit << 48) | ((u64)flags << 32),
+ 0, 0, 0);
+ if (hvrc != 0) {
+ printk(KERN_WARNING "probe_disk: "
+ "bad rc sending event to OS/400 %d\n", (int)hvrc);
+ return;
+ }
+
+ do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
+ "block", "IBM,iSeries-viodasd", NULL);
+}
+
+static void __init get_viodasd_info(struct device_node *vio_root)
+{
+ int rc;
+ u32 unit;
+
+ rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio, 2);
+ if (rc) {
+ printk(KERN_WARNING "get_viodasd_info: "
+ "error opening path to host partition %d\n",
+ viopath_hostLp);
+ return;
+ }
+
+ /* Initialize our request handler */
+ vio_setHandler(viomajorsubtype_blockio, handle_block_event);
+
+ for (unit = 0; unit < HVMAXARCHITECTEDVIRTUALDISKS; unit++)
+ probe_disk(vio_root, unit);
+
+ vio_clearHandler(viomajorsubtype_blockio);
+ viopath_close(viopath_hostLp, viomajorsubtype_blockio, 2);
+}
+
+static void __init handle_cd_event(struct HvLpEvent *event)
+{
+ struct viocdlpevent *bevent;
+ struct vio_waitevent *pwe;
+
+ if (!event)
+ /* Notification that a partition went away! */
+ return;
+
+ /* First, we should NEVER get an int here...only acks */
+ if (hvlpevent_is_int(event)) {
+ printk(KERN_WARNING "handle_cd_event: got an unexpected int\n");
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ return;
+ }
+
+ bevent = (struct viocdlpevent *)event;
+
+ switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+ case viocdgetinfo:
+ pwe = (struct vio_waitevent *)event->xCorrelationToken;
+ pwe->rc = event->xRc;
+ pwe->sub_result = bevent->sub_result;
+ complete(&pwe->com);
+ break;
+
+ default:
+ printk(KERN_WARNING "handle_cd_event: "
+ "message with unexpected subtype %0x04X!\n",
+ event->xSubtype & VIOMINOR_SUBTYPE_MASK);
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ }
+}
+
+static void __init get_viocd_info(struct device_node *vio_root)
+{
+ HvLpEvent_Rc hvrc;
+ u32 unit;
+ struct vio_waitevent we;
+ struct vio_resource *unitinfo;
+ dma_addr_t unitinfo_dmaaddr;
+ int ret;
+
+ ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio, 2);
+ if (ret) {
+ printk(KERN_WARNING
+ "get_viocd_info: error opening path to host partition %d\n",
+ viopath_hostLp);
+ return;
+ }
+
+ /* Initialize our request handler */
+ vio_setHandler(viomajorsubtype_cdio, handle_cd_event);
+
+ unitinfo = iseries_hv_alloc(
+ sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
+ &unitinfo_dmaaddr, GFP_ATOMIC);
+ if (!unitinfo) {
+ printk(KERN_WARNING
+ "get_viocd_info: error allocating unitinfo\n");
+ goto clear_handler;
+ }
+
+ memset(unitinfo, 0, sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS);
+
+ init_completion(&we.com);
+
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_cdio | viocdgetinfo,
+ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
+ sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, 0);
+ if (hvrc != HvLpEvent_Rc_Good) {
+ printk(KERN_WARNING
+ "get_viocd_info: cdrom error sending event. rc %d\n",
+ (int)hvrc);
+ goto hv_free;
+ }
+
+ wait_for_completion(&we.com);
+
+ if (we.rc) {
+ printk(KERN_WARNING "get_viocd_info: bad rc %d:0x%04X\n",
+ we.rc, we.sub_result);
+ goto hv_free;
+ }
+
+ for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) &&
+ unitinfo[unit].rsrcname[0]; unit++) {
+ if (!do_device_node(vio_root, "viocd", FIRST_VIOCD + unit, unit,
+ "block", "IBM,iSeries-viocd", &unitinfo[unit]))
+ break;
+ }
+
+ hv_free:
+ iseries_hv_free(sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
+ unitinfo, unitinfo_dmaaddr);
+ clear_handler:
+ vio_clearHandler(viomajorsubtype_cdio);
+ viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
+}
+
+/* Handle interrupt events for tape */
+static void __init handle_tape_event(struct HvLpEvent *event)
+{
+ struct vio_waitevent *we;
+ struct viotapelpevent *tevent = (struct viotapelpevent *)event;
+
+ if (event == NULL)
+ /* Notification that a partition went away! */
+ return;
+
+ we = (struct vio_waitevent *)event->xCorrelationToken;
+ switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+ case viotapegetinfo:
+ we->rc = tevent->sub_type_result;
+ complete(&we->com);
+ break;
+ default:
+ printk(KERN_WARNING "handle_tape_event: weird ack\n");
+ }
+}
+
+static void __init get_viotape_info(struct device_node *vio_root)
+{
+ HvLpEvent_Rc hvrc;
+ u32 unit;
+ struct vio_resource *unitinfo;
+ dma_addr_t unitinfo_dmaaddr;
+ size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES;
+ struct vio_waitevent we;
+ int ret;
+
+ ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2);
+ if (ret) {
+ printk(KERN_WARNING "get_viotape_info: "
+ "error on viopath_open to hostlp %d\n", ret);
+ return;
+ }
+
+ vio_setHandler(viomajorsubtype_tape, handle_tape_event);
+
+ unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC);
+ if (!unitinfo)
+ goto clear_handler;
+
+ memset(unitinfo, 0, len);
+
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_tape | viotapegetinfo,
+ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ (u64)(unsigned long)&we, VIOVERSION << 16,
+ unitinfo_dmaaddr, len, 0, 0);
+ if (hvrc != HvLpEvent_Rc_Good) {
+ printk(KERN_WARNING "get_viotape_info: hv error on op %d\n",
+ (int)hvrc);
+ goto hv_free;
+ }
+
+ wait_for_completion(&we.com);
+
+ for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
+ unitinfo[unit].rsrcname[0]; unit++) {
+ if (!do_device_node(vio_root, "viotape", FIRST_VIOTAPE + unit,
+ unit, "byte", "IBM,iSeries-viotape",
+ &unitinfo[unit]))
+ break;
+ }
+
+ hv_free:
+ iseries_hv_free(len, unitinfo, unitinfo_dmaaddr);
+ clear_handler:
+ vio_clearHandler(viomajorsubtype_tape);
+ viopath_close(viopath_hostLp, viomajorsubtype_tape, 2);
+}
+
+static int __init iseries_vio_init(void)
+{
+ struct device_node *vio_root;
+
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return -ENODEV;
+
+ iommu_vio_init();
+
+ vio_root = of_find_node_by_path("/vdevice");
+ if (!vio_root)
+ return -ENODEV;
+
+ if (viopath_hostLp == HvLpIndexInvalid) {
+ vio_set_hostlp();
+ /* If we don't have a host, bail out */
+ if (viopath_hostLp == HvLpIndexInvalid)
+ goto put_node;
+ }
+
+ get_viodasd_info(vio_root);
+ get_viocd_info(vio_root);
+ get_viotape_info(vio_root);
+
+ return 0;
+
+ put_node:
+ of_node_put(vio_root);
+ return -ENODEV;
+}
+arch_initcall(iseries_vio_init);
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index 6a0060a5f2e..df23331eb25 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -124,8 +124,7 @@ static int proc_viopath_show(struct seq_file *m, void *v)
if (!buf)
return 0;
- handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE,
- DMA_FROM_DEVICE);
+ handle = iseries_hv_map(buf, HW_PAGE_SIZE, DMA_FROM_DEVICE);
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
HvLpEvent_Type_VirtualIo,
@@ -146,8 +145,7 @@ static int proc_viopath_show(struct seq_file *m, void *v)
buf[HW_PAGE_SIZE-1] = '\0';
seq_printf(m, "%s", buf);
- dma_unmap_single(iSeries_vio_dev, handle, HW_PAGE_SIZE,
- DMA_FROM_DEVICE);
+ iseries_hv_unmap(handle, HW_PAGE_SIZE, DMA_FROM_DEVICE);
kfree(buf);
seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap);
@@ -596,7 +594,7 @@ int viopath_close(HvLpIndex remoteLp, int subtype, int numReq)
numOpen += viopathStatus[remoteLp].users[i];
if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) {
- printk(VIOPATH_KERN_INFO "closing connection to partition %d",
+ printk(VIOPATH_KERN_INFO "closing connection to partition %d\n",
remoteLp);
HvCallEvent_closeLpEventPath(remoteLp,
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
index c91a33593bb..dae9f658122 100644
--- a/arch/powerpc/platforms/pasemi/gpio_mdio.c
+++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
@@ -320,10 +320,12 @@ static struct of_device_id gpio_mdio_match[] =
static struct of_platform_driver gpio_mdio_driver =
{
- .name = "gpio-mdio-bitbang",
.match_table = gpio_mdio_match,
.probe = gpio_mdio_probe,
.remove = gpio_mdio_remove,
+ .driver = {
+ .name = "gpio-mdio-bitbang",
+ },
};
int gpio_mdio_init(void)
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 7ccb9236e8b..02c53309662 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -387,69 +387,13 @@ static void __init pmac_setup_arch(void)
#endif /* CONFIG_ADB */
}
-char *bootpath;
-char *bootdevice;
-void *boot_host;
-int boot_target;
-int boot_part;
-static dev_t boot_dev;
-
#ifdef CONFIG_SCSI
void note_scsi_host(struct device_node *node, void *host)
{
- int l;
- char *p;
-
- l = strlen(node->full_name);
- if (bootpath != NULL && bootdevice != NULL
- && strncmp(node->full_name, bootdevice, l) == 0
- && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
- boot_host = host;
- /*
- * There's a bug in OF 1.0.5. (Why am I not surprised.)
- * If you pass a path like scsi/sd@1:0 to canon, it returns
- * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
- * That is, the scsi target number doesn't get preserved.
- * So we pick the target number out of bootpath and use that.
- */
- p = strstr(bootpath, "/sd@");
- if (p != NULL) {
- p += 4;
- boot_target = simple_strtoul(p, NULL, 10);
- p = strchr(p, ':');
- if (p != NULL)
- boot_part = simple_strtoul(p + 1, NULL, 10);
- }
- }
}
EXPORT_SYMBOL(note_scsi_host);
#endif
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-static dev_t __init find_ide_boot(void)
-{
- char *p;
- int n;
- dev_t __init pmac_find_ide_boot(char *bootdevice, int n);
-
- if (bootdevice == NULL)
- return 0;
- p = strrchr(bootdevice, '/');
- if (p == NULL)
- return 0;
- n = p - bootdevice;
-
- return pmac_find_ide_boot(bootdevice, n);
-}
-#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
-
-static void __init find_boot_device(void)
-{
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
- boot_dev = find_ide_boot();
-#endif
-}
-
static int initializing = 1;
static int pmac_late_init(void)
@@ -466,10 +410,14 @@ static int pmac_late_init(void)
late_initcall(pmac_late_init);
-/* can't be __init - can be called whenever a disk is first accessed */
-void note_bootable_part(dev_t dev, int part, int goodness)
+/*
+ * This is __init_refok because we check for "initializing" before
+ * touching any of the __init sensitive things and "initializing"
+ * will be false after __init time. This can't be __init because it
+ * can be called whenever a disk is first accessed.
+ */
+void __init_refok note_bootable_part(dev_t dev, int part, int goodness)
{
- static int found_boot = 0;
char *p;
if (!initializing)
@@ -481,15 +429,8 @@ void note_bootable_part(dev_t dev, int part, int goodness)
if (p != NULL && (p == boot_command_line || p[-1] == ' '))
return;
- if (!found_boot) {
- find_boot_device();
- found_boot = 1;
- }
- if (!boot_dev || dev == boot_dev) {
- ROOT_DEV = dev + part;
- boot_dev = 0;
- current_root_goodness = goodness;
- }
+ ROOT_DEV = dev + part;
+ current_root_goodness = goodness;
}
#ifdef CONFIG_ADB_CUDA
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index b70e474014f..766685ab26f 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -1,5 +1,5 @@
/*
- * PS3 'Other OS' area data.
+ * PS3 flash memory os area.
*
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* Copyright 2006 Sony Corp.
@@ -20,6 +20,9 @@
#include <linux/kernel.h>
#include <linux/io.h>
+#include <linux/workqueue.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
#include <asm/lmb.h>
@@ -29,7 +32,7 @@ enum {
OS_AREA_SEGMENT_SIZE = 0X200,
};
-enum {
+enum os_area_ldr_format {
HEADER_LDR_FORMAT_RAW = 0,
HEADER_LDR_FORMAT_GZIP = 1,
};
@@ -38,7 +41,7 @@ enum {
* struct os_area_header - os area header segment.
* @magic_num: Always 'cell_ext_os_area'.
* @hdr_version: Header format version number.
- * @os_area_offset: Starting segment number of os image area.
+ * @db_area_offset: Starting segment number of other os database area.
* @ldr_area_offset: Starting segment number of bootloader image area.
* @ldr_format: HEADER_LDR_FORMAT flag.
* @ldr_size: Size of bootloader image in bytes.
@@ -50,9 +53,9 @@ enum {
*/
struct os_area_header {
- s8 magic_num[16];
+ u8 magic_num[16];
u32 hdr_version;
- u32 os_area_offset;
+ u32 db_area_offset;
u32 ldr_area_offset;
u32 _reserved_1;
u32 ldr_format;
@@ -60,12 +63,12 @@ struct os_area_header {
u32 _reserved_2[6];
};
-enum {
+enum os_area_boot_flag {
PARAM_BOOT_FLAG_GAME_OS = 0,
PARAM_BOOT_FLAG_OTHER_OS = 1,
};
-enum {
+enum os_area_ctrl_button {
PARAM_CTRL_BUTTON_O_IS_YES = 0,
PARAM_CTRL_BUTTON_X_IS_YES = 1,
};
@@ -84,6 +87,9 @@ enum {
* @dns_primary: User preference of static primary dns server.
* @dns_secondary: User preference of static secondary dns server.
*
+ * The ps3 rtc maintains a read-only value that approximates seconds since
+ * 2000-01-01 00:00:00 UTC.
+ *
* User preference of zero for static_ip_addr means use dhcp.
*/
@@ -108,45 +114,172 @@ struct os_area_params {
u8 _reserved_5[8];
};
+enum {
+ OS_AREA_DB_MAGIC_NUM = 0x2d64622dU,
+};
+
/**
- * struct saved_params - Static working copies of data from the 'Other OS' area.
+ * struct os_area_db - Shared flash memory database.
+ * @magic_num: Always '-db-' = 0x2d64622d.
+ * @version: os_area_db format version number.
+ * @index_64: byte offset of the database id index for 64 bit variables.
+ * @count_64: number of usable 64 bit index entries
+ * @index_32: byte offset of the database id index for 32 bit variables.
+ * @count_32: number of usable 32 bit index entries
+ * @index_16: byte offset of the database id index for 16 bit variables.
+ * @count_16: number of usable 16 bit index entries
*
- * For the convinience of the guest, the HV makes a copy of the 'Other OS' area
- * in flash to a high address in the boot memory region and then puts that RAM
- * address and the byte count into the repository for retreval by the guest.
- * We copy the data we want into a static variable and allow the memory setup
- * by the HV to be claimed by the lmb manager.
+ * Flash rom storage for exclusive use by guests running in the other os lpar.
+ * The current system configuration allocates 1K (two segments) for other os
+ * use.
+ */
+
+struct os_area_db {
+ u32 magic_num;
+ u16 version;
+ u16 _reserved_1;
+ u16 index_64;
+ u16 count_64;
+ u16 index_32;
+ u16 count_32;
+ u16 index_16;
+ u16 count_16;
+ u32 _reserved_2;
+ u8 _db_data[1000];
+};
+
+/**
+ * enum os_area_db_owner - Data owners.
+ */
+
+enum os_area_db_owner {
+ OS_AREA_DB_OWNER_ANY = -1,
+ OS_AREA_DB_OWNER_NONE = 0,
+ OS_AREA_DB_OWNER_PROTOTYPE = 1,
+ OS_AREA_DB_OWNER_LINUX = 2,
+ OS_AREA_DB_OWNER_PETITBOOT = 3,
+ OS_AREA_DB_OWNER_MAX = 32,
+};
+
+enum os_area_db_key {
+ OS_AREA_DB_KEY_ANY = -1,
+ OS_AREA_DB_KEY_NONE = 0,
+ OS_AREA_DB_KEY_RTC_DIFF = 1,
+ OS_AREA_DB_KEY_VIDEO_MODE = 2,
+ OS_AREA_DB_KEY_MAX = 8,
+};
+
+struct os_area_db_id {
+ int owner;
+ int key;
+};
+
+static const struct os_area_db_id os_area_db_id_empty = {
+ .owner = OS_AREA_DB_OWNER_NONE,
+ .key = OS_AREA_DB_KEY_NONE
+};
+
+static const struct os_area_db_id os_area_db_id_any = {
+ .owner = OS_AREA_DB_OWNER_ANY,
+ .key = OS_AREA_DB_KEY_ANY
+};
+
+static const struct os_area_db_id os_area_db_id_rtc_diff = {
+ .owner = OS_AREA_DB_OWNER_LINUX,
+ .key = OS_AREA_DB_KEY_RTC_DIFF
+};
+
+static const struct os_area_db_id os_area_db_id_video_mode = {
+ .owner = OS_AREA_DB_OWNER_LINUX,
+ .key = OS_AREA_DB_KEY_VIDEO_MODE
+};
+
+#define SECONDS_FROM_1970_TO_2000 946684800LL
+
+/**
+ * struct saved_params - Static working copies of data from the PS3 'os area'.
+ *
+ * The order of preference we use for the rtc_diff source:
+ * 1) The database value.
+ * 2) The game os value.
+ * 3) The number of seconds from 1970 to 2000.
*/
struct saved_params {
- /* param 0 */
+ unsigned int valid;
s64 rtc_diff;
unsigned int av_multi_out;
- unsigned int ctrl_button;
- /* param 1 */
- u8 static_ip_addr[4];
- u8 network_mask[4];
- u8 default_gateway[4];
- /* param 2 */
- u8 dns_primary[4];
- u8 dns_secondary[4];
} static saved_params;
+static struct property property_rtc_diff = {
+ .name = "linux,rtc_diff",
+ .length = sizeof(saved_params.rtc_diff),
+ .value = &saved_params.rtc_diff,
+};
+
+static struct property property_av_multi_out = {
+ .name = "linux,av_multi_out",
+ .length = sizeof(saved_params.av_multi_out),
+ .value = &saved_params.av_multi_out,
+};
+
+/**
+ * os_area_set_property - Add or overwrite a saved_params value to the device tree.
+ *
+ * Overwrites an existing property.
+ */
+
+static void os_area_set_property(struct device_node *node,
+ struct property *prop)
+{
+ int result;
+ struct property *tmp = of_find_property(node, prop->name, NULL);
+
+ if (tmp) {
+ pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name);
+ prom_remove_property(node, tmp);
+ }
+
+ result = prom_add_property(node, prop);
+
+ if (result)
+ pr_debug("%s:%d prom_set_property failed\n", __func__,
+ __LINE__);
+}
+
+/**
+ * os_area_get_property - Get a saved_params value from the device tree.
+ *
+ */
+
+static void __init os_area_get_property(struct device_node *node,
+ struct property *prop)
+{
+ const struct property *tmp = of_find_property(node, prop->name, NULL);
+
+ if (tmp) {
+ BUG_ON(prop->length != tmp->length);
+ memcpy(prop->value, tmp->value, prop->length);
+ } else
+ pr_debug("%s:%d not found %s\n", __func__, __LINE__,
+ prop->name);
+}
+
#define dump_header(_a) _dump_header(_a, __func__, __LINE__)
static void _dump_header(const struct os_area_header *h, const char *func,
int line)
{
- pr_debug("%s:%d: h.magic_num: '%s'\n", func, line,
+ pr_debug("%s:%d: h.magic_num: '%s'\n", func, line,
h->magic_num);
- pr_debug("%s:%d: h.hdr_version: %u\n", func, line,
+ pr_debug("%s:%d: h.hdr_version: %u\n", func, line,
h->hdr_version);
- pr_debug("%s:%d: h.os_area_offset: %u\n", func, line,
- h->os_area_offset);
+ pr_debug("%s:%d: h.db_area_offset: %u\n", func, line,
+ h->db_area_offset);
pr_debug("%s:%d: h.ldr_area_offset: %u\n", func, line,
h->ldr_area_offset);
- pr_debug("%s:%d: h.ldr_format: %u\n", func, line,
+ pr_debug("%s:%d: h.ldr_format: %u\n", func, line,
h->ldr_format);
- pr_debug("%s:%d: h.ldr_size: %xh\n", func, line,
+ pr_debug("%s:%d: h.ldr_size: %xh\n", func, line,
h->ldr_size);
}
@@ -176,7 +309,7 @@ static void _dump_params(const struct os_area_params *p, const char *func,
p->dns_secondary[2], p->dns_secondary[3]);
}
-static int __init verify_header(const struct os_area_header *header)
+static int verify_header(const struct os_area_header *header)
{
if (memcmp(header->magic_num, "cell_ext_os_area", 16)) {
pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
@@ -188,7 +321,7 @@ static int __init verify_header(const struct os_area_header *header)
return -1;
}
- if (header->os_area_offset > header->ldr_area_offset) {
+ if (header->db_area_offset > header->ldr_area_offset) {
pr_debug("%s:%d offsets failed\n", __func__, __LINE__);
return -1;
}
@@ -196,58 +329,477 @@ static int __init verify_header(const struct os_area_header *header)
return 0;
}
-int __init ps3_os_area_init(void)
+static int db_verify(const struct os_area_db *db)
+{
+ if (db->magic_num != OS_AREA_DB_MAGIC_NUM) {
+ pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
+ return -1;
+ }
+
+ if (db->version != 1) {
+ pr_debug("%s:%d version failed\n", __func__, __LINE__);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct db_index {
+ uint8_t owner:5;
+ uint8_t key:3;
+};
+
+struct db_iterator {
+ const struct os_area_db *db;
+ struct os_area_db_id match_id;
+ struct db_index *idx;
+ struct db_index *last_idx;
+ union {
+ uint64_t *value_64;
+ uint32_t *value_32;
+ uint16_t *value_16;
+ };
+};
+
+static unsigned int db_align_up(unsigned int val, unsigned int size)
+{
+ return (val + (size - 1)) & (~(size - 1));
+}
+
+/**
+ * db_for_each_64 - Iterator for 64 bit entries.
+ *
+ * A NULL value for id can be used to match all entries.
+ * OS_AREA_DB_OWNER_ANY and OS_AREA_DB_KEY_ANY can be used to match all.
+ */
+
+static int db_for_each_64(const struct os_area_db *db,
+ const struct os_area_db_id *match_id, struct db_iterator *i)
+{
+next:
+ if (!i->db) {
+ i->db = db;
+ i->match_id = match_id ? *match_id : os_area_db_id_any;
+ i->idx = (void *)db + db->index_64;
+ i->last_idx = i->idx + db->count_64;
+ i->value_64 = (void *)db + db->index_64
+ + db_align_up(db->count_64, 8);
+ } else {
+ i->idx++;
+ i->value_64++;
+ }
+
+ if (i->idx >= i->last_idx) {
+ pr_debug("%s:%d: reached end\n", __func__, __LINE__);
+ return 0;
+ }
+
+ if (i->match_id.owner != OS_AREA_DB_OWNER_ANY
+ && i->match_id.owner != (int)i->idx->owner)
+ goto next;
+ if (i->match_id.key != OS_AREA_DB_KEY_ANY
+ && i->match_id.key != (int)i->idx->key)
+ goto next;
+
+ return 1;
+}
+
+static int db_delete_64(struct os_area_db *db, const struct os_area_db_id *id)
+{
+ struct db_iterator i;
+
+ for (i.db = NULL; db_for_each_64(db, id, &i); ) {
+
+ pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,
+ i.idx->owner, i.idx->key,
+ (unsigned long long)*i.value_64);
+
+ i.idx->owner = 0;
+ i.idx->key = 0;
+ *i.value_64 = 0;
+ }
+ return 0;
+}
+
+static int db_set_64(struct os_area_db *db, const struct os_area_db_id *id,
+ uint64_t value)
+{
+ struct db_iterator i;
+
+ pr_debug("%s:%d: (%d:%d) <= %llxh\n", __func__, __LINE__,
+ id->owner, id->key, (unsigned long long)value);
+
+ if (!id->owner || id->owner == OS_AREA_DB_OWNER_ANY
+ || id->key == OS_AREA_DB_KEY_ANY) {
+ pr_debug("%s:%d: bad id: (%d:%d)\n", __func__,
+ __LINE__, id->owner, id->key);
+ return -1;
+ }
+
+ db_delete_64(db, id);
+
+ i.db = NULL;
+ if (db_for_each_64(db, &os_area_db_id_empty, &i)) {
+
+ pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,
+ i.idx->owner, i.idx->key,
+ (unsigned long long)*i.value_64);
+
+ i.idx->owner = id->owner;
+ i.idx->key = id->key;
+ *i.value_64 = value;
+
+ pr_debug("%s:%d: set (%d:%d) <= %llxh\n", __func__, __LINE__,
+ i.idx->owner, i.idx->key,
+ (unsigned long long)*i.value_64);
+ return 0;
+ }
+ pr_debug("%s:%d: database full.\n",
+ __func__, __LINE__);
+ return -1;
+}
+
+static int db_get_64(const struct os_area_db *db,
+ const struct os_area_db_id *id, uint64_t *value)
+{
+ struct db_iterator i;
+
+ i.db = NULL;
+ if (db_for_each_64(db, id, &i)) {
+ *value = *i.value_64;
+ pr_debug("%s:%d: found %lld\n", __func__, __LINE__,
+ (long long int)*i.value_64);
+ return 0;
+ }
+ pr_debug("%s:%d: not found\n", __func__, __LINE__);
+ return -1;
+}
+
+static int db_get_rtc_diff(const struct os_area_db *db, int64_t *rtc_diff)
+{
+ return db_get_64(db, &os_area_db_id_rtc_diff, (uint64_t*)rtc_diff);
+}
+
+#define dump_db(a) _dump_db(a, __func__, __LINE__)
+static void _dump_db(const struct os_area_db *db, const char *func,
+ int line)
+{
+ pr_debug("%s:%d: db.magic_num: '%s'\n", func, line,
+ (const char*)&db->magic_num);
+ pr_debug("%s:%d: db.version: %u\n", func, line,
+ db->version);
+ pr_debug("%s:%d: db.index_64: %u\n", func, line,
+ db->index_64);
+ pr_debug("%s:%d: db.count_64: %u\n", func, line,
+ db->count_64);
+ pr_debug("%s:%d: db.index_32: %u\n", func, line,
+ db->index_32);
+ pr_debug("%s:%d: db.count_32: %u\n", func, line,
+ db->count_32);
+ pr_debug("%s:%d: db.index_16: %u\n", func, line,
+ db->index_16);
+ pr_debug("%s:%d: db.count_16: %u\n", func, line,
+ db->count_16);
+}
+
+static void os_area_db_init(struct os_area_db *db)
+{
+ enum {
+ HEADER_SIZE = offsetof(struct os_area_db, _db_data),
+ INDEX_64_COUNT = 64,
+ VALUES_64_COUNT = 57,
+ INDEX_32_COUNT = 64,
+ VALUES_32_COUNT = 57,
+ INDEX_16_COUNT = 64,
+ VALUES_16_COUNT = 57,
+ };
+
+ memset(db, 0, sizeof(struct os_area_db));
+
+ db->magic_num = OS_AREA_DB_MAGIC_NUM;
+ db->version = 1;
+ db->index_64 = HEADER_SIZE;
+ db->count_64 = VALUES_64_COUNT;
+ db->index_32 = HEADER_SIZE
+ + INDEX_64_COUNT * sizeof(struct db_index)
+ + VALUES_64_COUNT * sizeof(u64);
+ db->count_32 = VALUES_32_COUNT;
+ db->index_16 = HEADER_SIZE
+ + INDEX_64_COUNT * sizeof(struct db_index)
+ + VALUES_64_COUNT * sizeof(u64)
+ + INDEX_32_COUNT * sizeof(struct db_index)
+ + VALUES_32_COUNT * sizeof(u32);
+ db->count_16 = VALUES_16_COUNT;
+
+ /* Rules to check db layout. */
+
+ BUILD_BUG_ON(sizeof(struct db_index) != 1);
+ BUILD_BUG_ON(sizeof(struct os_area_db) != 2 * OS_AREA_SEGMENT_SIZE);
+ BUILD_BUG_ON(INDEX_64_COUNT & 0x7);
+ BUILD_BUG_ON(VALUES_64_COUNT > INDEX_64_COUNT);
+ BUILD_BUG_ON(INDEX_32_COUNT & 0x7);
+ BUILD_BUG_ON(VALUES_32_COUNT > INDEX_32_COUNT);
+ BUILD_BUG_ON(INDEX_16_COUNT & 0x7);
+ BUILD_BUG_ON(VALUES_16_COUNT > INDEX_16_COUNT);
+ BUILD_BUG_ON(HEADER_SIZE
+ + INDEX_64_COUNT * sizeof(struct db_index)
+ + VALUES_64_COUNT * sizeof(u64)
+ + INDEX_32_COUNT * sizeof(struct db_index)
+ + VALUES_32_COUNT * sizeof(u32)
+ + INDEX_16_COUNT * sizeof(struct db_index)
+ + VALUES_16_COUNT * sizeof(u16)
+ > sizeof(struct os_area_db));
+}
+
+/**
+ * update_flash_db - Helper for os_area_queue_work_handler.
+ *
+ */
+
+static void update_flash_db(void)
+{
+ int result;
+ int file;
+ off_t offset;
+ ssize_t count;
+ static const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;
+ const struct os_area_header *header;
+ struct os_area_db* db;
+
+ /* Read in header and db from flash. */
+
+ file = sys_open("/dev/ps3flash", O_RDWR, 0);
+
+ if (file < 0) {
+ pr_debug("%s:%d sys_open failed\n", __func__, __LINE__);
+ goto fail_open;
+ }
+
+ header = kmalloc(buf_len, GFP_KERNEL);
+
+ if (!header) {
+ pr_debug("%s:%d kmalloc failed\n", __func__, __LINE__);
+ goto fail_malloc;
+ }
+
+ offset = sys_lseek(file, 0, SEEK_SET);
+
+ if (offset != 0) {
+ pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
+ goto fail_header_seek;
+ }
+
+ count = sys_read(file, (char __user *)header, buf_len);
+
+ result = count < OS_AREA_SEGMENT_SIZE || verify_header(header)
+ || count < header->db_area_offset * OS_AREA_SEGMENT_SIZE;
+
+ if (result) {
+ pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
+ dump_header(header);
+ goto fail_header;
+ }
+
+ /* Now got a good db offset and some maybe good db data. */
+
+ db = (void*)header + header->db_area_offset * OS_AREA_SEGMENT_SIZE;
+
+ result = db_verify(db);
+
+ if (result) {
+ printk(KERN_NOTICE "%s:%d: Verify of flash database failed, "
+ "formatting.\n", __func__, __LINE__);
+ dump_db(db);
+ os_area_db_init(db);
+ }
+
+ /* Now got good db data. */
+
+ db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff);
+
+ offset = sys_lseek(file, header->db_area_offset * OS_AREA_SEGMENT_SIZE,
+ SEEK_SET);
+
+ if (offset != header->db_area_offset * OS_AREA_SEGMENT_SIZE) {
+ pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
+ goto fail_db_seek;
+ }
+
+ count = sys_write(file, (const char __user *)db,
+ sizeof(struct os_area_db));
+
+ if (count < sizeof(struct os_area_db)) {
+ pr_debug("%s:%d sys_write failed\n", __func__, __LINE__);
+ }
+
+fail_db_seek:
+fail_header:
+fail_header_seek:
+ kfree(header);
+fail_malloc:
+ sys_close(file);
+fail_open:
+ return;
+}
+
+/**
+ * os_area_queue_work_handler - Asynchronous write handler.
+ *
+ * An asynchronous write for flash memory and the device tree. Do not
+ * call directly, use os_area_queue_work().
+ */
+
+static void os_area_queue_work_handler(struct work_struct *work)
+{
+ struct device_node *node;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ node = of_find_node_by_path("/");
+
+ if (node) {
+ os_area_set_property(node, &property_rtc_diff);
+ of_node_put(node);
+ } else
+ pr_debug("%s:%d of_find_node_by_path failed\n",
+ __func__, __LINE__);
+
+#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
+ update_flash_db();
+#else
+ printk(KERN_WARNING "%s:%d: No flash rom driver configured.\n",
+ __func__, __LINE__);
+#endif
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+}
+
+static void os_area_queue_work(void)
+{
+ static DECLARE_WORK(q, os_area_queue_work_handler);
+
+ wmb();
+ schedule_work(&q);
+}
+
+/**
+ * ps3_os_area_save_params - Copy data from os area mirror to @saved_params.
+ *
+ * For the convenience of the guest the HV makes a copy of the os area in
+ * flash to a high address in the boot memory region and then puts that RAM
+ * address and the byte count into the repository for retrieval by the guest.
+ * We copy the data we want into a static variable and allow the memory setup
+ * by the HV to be claimed by the lmb manager.
+ *
+ * The os area mirror will not be available to a second stage kernel, and
+ * the header verify will fail. In this case, the saved_params values will
+ * be set from flash memory or the passed in device tree in ps3_os_area_init().
+ */
+
+void __init ps3_os_area_save_params(void)
{
int result;
u64 lpar_addr;
unsigned int size;
struct os_area_header *header;
struct os_area_params *params;
+ struct os_area_db *db;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
result = ps3_repository_read_boot_dat_info(&lpar_addr, &size);
if (result) {
pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n",
__func__, __LINE__);
- return result;
+ return;
}
header = (struct os_area_header *)__va(lpar_addr);
- params = (struct os_area_params *)__va(lpar_addr + OS_AREA_SEGMENT_SIZE);
+ params = (struct os_area_params *)__va(lpar_addr
+ + OS_AREA_SEGMENT_SIZE);
result = verify_header(header);
if (result) {
+ /* Second stage kernels exit here. */
pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
dump_header(header);
- return -EIO;
+ return;
}
+ db = (struct os_area_db *)__va(lpar_addr
+ + header->db_area_offset * OS_AREA_SEGMENT_SIZE);
+
dump_header(header);
dump_params(params);
+ dump_db(db);
- saved_params.rtc_diff = params->rtc_diff;
+ result = db_verify(db) || db_get_rtc_diff(db, &saved_params.rtc_diff);
+ if (result)
+ saved_params.rtc_diff = params->rtc_diff ? params->rtc_diff
+ : SECONDS_FROM_1970_TO_2000;
saved_params.av_multi_out = params->av_multi_out;
- saved_params.ctrl_button = params->ctrl_button;
- memcpy(saved_params.static_ip_addr, params->static_ip_addr, 4);
- memcpy(saved_params.network_mask, params->network_mask, 4);
- memcpy(saved_params.default_gateway, params->default_gateway, 4);
- memcpy(saved_params.dns_secondary, params->dns_secondary, 4);
+ saved_params.valid = 1;
+
+ memset(header, 0, sizeof(*header));
- return result;
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
}
/**
- * ps3_os_area_rtc_diff - Returns the ps3 rtc diff value.
+ * ps3_os_area_init - Setup os area device tree properties as needed.
+ */
+
+void __init ps3_os_area_init(void)
+{
+ struct device_node *node;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ node = of_find_node_by_path("/");
+
+ if (!saved_params.valid && node) {
+ /* Second stage kernels should have a dt entry. */
+ os_area_get_property(node, &property_rtc_diff);
+ os_area_get_property(node, &property_av_multi_out);
+ }
+
+ if(!saved_params.rtc_diff)
+ saved_params.rtc_diff = SECONDS_FROM_1970_TO_2000;
+
+ if (node) {
+ os_area_set_property(node, &property_rtc_diff);
+ os_area_set_property(node, &property_av_multi_out);
+ of_node_put(node);
+ } else
+ pr_debug("%s:%d of_find_node_by_path failed\n",
+ __func__, __LINE__);
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+}
+
+/**
+ * ps3_os_area_get_rtc_diff - Returns the rtc diff value.
+ */
+
+u64 ps3_os_area_get_rtc_diff(void)
+{
+ return saved_params.rtc_diff;
+}
+
+/**
+ * ps3_os_area_set_rtc_diff - Set the rtc diff value.
*
- * The ps3 rtc maintains a value that approximates seconds since
- * 2000-01-01 00:00:00 UTC. Returns the exact number of seconds from 1970 to
- * 2000 when saved_params.rtc_diff has not been properly set up.
+ * An asynchronous write is needed to support writing updates from
+ * the timer interrupt context.
*/
-u64 ps3_os_area_rtc_diff(void)
+void ps3_os_area_set_rtc_diff(u64 rtc_diff)
{
- return saved_params.rtc_diff ? saved_params.rtc_diff : 946684800UL;
+ if (saved_params.rtc_diff != rtc_diff) {
+ saved_params.rtc_diff = rtc_diff;
+ os_area_queue_work();
+ }
}
/**
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
index 27c7d099816..01f0c9506e1 100644
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -62,8 +62,10 @@ int ps3_set_rtc_time(struct rtc_time *time);
/* os area */
-int __init ps3_os_area_init(void);
-u64 ps3_os_area_rtc_diff(void);
+void __init ps3_os_area_save_params(void);
+void __init ps3_os_area_init(void);
+u64 ps3_os_area_get_rtc_diff(void);
+void ps3_os_area_set_rtc_diff(u64 rtc_diff);
/* spu */
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 609945dbe39..5c2cbb08eb5 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -206,6 +206,7 @@ static void __init ps3_setup_arch(void)
prealloc_ps3flash_bounce_buffer();
ppc_md.power_save = ps3_power_save;
+ ps3_os_area_init();
DBG(" <- %s:%d\n", __func__, __LINE__);
}
@@ -228,7 +229,7 @@ static int __init ps3_probe(void)
powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;
- ps3_os_area_init();
+ ps3_os_area_save_params();
ps3_mm_init();
ps3_mm_vas_create(&htab_size);
ps3_hpte_init(htab_size);
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index 802a9ccacb5..d0daf7d6d3b 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -50,12 +50,6 @@ static void __maybe_unused _dump_time(int time, const char *func,
_dump_tm(&tm, func, line);
}
-/**
- * rtc_shift - Difference in seconds between 1970 and the ps3 rtc value.
- */
-
-static s64 rtc_shift;
-
void __init ps3_calibrate_decr(void)
{
int result;
@@ -66,8 +60,6 @@ void __init ps3_calibrate_decr(void)
ppc_tb_freq = tmp;
ppc_proc_freq = ppc_tb_freq * 40;
-
- rtc_shift = ps3_os_area_rtc_diff();
}
static u64 read_rtc(void)
@@ -87,18 +79,18 @@ int ps3_set_rtc_time(struct rtc_time *tm)
u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
- rtc_shift = now - read_rtc();
+ ps3_os_area_set_rtc_diff(now - read_rtc());
return 0;
}
void ps3_get_rtc_time(struct rtc_time *tm)
{
- to_tm(read_rtc() + rtc_shift, tm);
+ to_tm(read_rtc() + ps3_os_area_get_rtc_diff(), tm);
tm->tm_year -= 1900;
tm->tm_mon -= 1;
}
unsigned long __init ps3_get_boot_time(void)
{
- return read_rtc() + rtc_shift;
+ return read_rtc() + ps3_os_area_get_rtc_diff();
}
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 9711eb0d549..fc48b96c81b 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -252,6 +252,20 @@ static struct notifier_block pseries_smp_nb = {
static int __init pseries_cpu_hotplug_init(void)
{
+ struct device_node *np;
+ const char *typep;
+
+ for_each_node_by_name(np, "interrupt-controller") {
+ typep = of_get_property(np, "compatible", NULL);
+ if (strstr(typep, "open-pic")) {
+ of_node_put(np);
+
+ printk(KERN_INFO "CPU Hotplug not supported on "
+ "systems using MPIC\n");
+ return 0;
+ }
+ }
+
rtas_stop_self_args.token = rtas_token("stop-self");
qcss_tok = rtas_token("query-cpu-stopped-state");
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index f0b7146a110..fdb9b1c8f97 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -257,11 +257,6 @@ static void __init pSeries_setup_arch(void)
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000;
- if (ROOT_DEV == 0) {
- printk("No ramdisk, default root is /dev/sda2\n");
- ROOT_DEV = Root_SDA2;
- }
-
fwnmi_init();
/* Find and initialize PCI host bridges */
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 52e93bca10c..1a6f5641ebc 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -6,7 +6,6 @@ mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o
obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
obj-$(CONFIG_PPC_MPC106) += grackle.o
-obj-$(CONFIG_PPC_DCR) += dcr.o
obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o
obj-$(CONFIG_PPC_PMI) += pmi.o
obj-$(CONFIG_U3_DART) += dart_iommu.o
@@ -33,6 +32,7 @@ endif
ifeq ($(ARCH),powerpc)
obj-$(CONFIG_CPM) += cpm_common.o
obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
+obj-$(CONFIG_PPC_DCR) += dcr.o
obj-$(CONFIG_8xx) += mpc8xx_pic.o commproc.o
obj-$(CONFIG_UCODE_PATCH) += micropatch.o
endif
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index ab037a3a40d..4d3ba63bba7 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -324,11 +324,13 @@ static struct of_device_id axon_ram_device_id[] = {
};
static struct of_platform_driver axon_ram_driver = {
- .owner = THIS_MODULE,
- .name = AXON_RAM_MODULE_NAME,
.match_table = axon_ram_device_id,
.probe = axon_ram_probe,
- .remove = axon_ram_remove
+ .remove = axon_ram_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = AXON_RAM_MODULE_NAME,
+ },
};
/**
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
index 2f91b55b775..20edd1e94ef 100644
--- a/arch/powerpc/sysdev/pmi.c
+++ b/arch/powerpc/sysdev/pmi.c
@@ -205,10 +205,12 @@ static int pmi_of_remove(struct of_device *dev)
}
static struct of_platform_driver pmi_of_platform_driver = {
- .name = "pmi",
.match_table = pmi_match,
.probe = pmi_of_probe,
- .remove = pmi_of_remove
+ .remove = pmi_of_remove,
+ .driver = {
+ .name = "pmi",
+ },
};
static int __init pmi_module_init(void)