Commit aef4b9aa authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  powerpc: Don't export cvt_fd & _df when CONFIG_PPC_FPU is not set
  powerpc/44x: icon: select SM502 and frame buffer console support
  powerpc/85xx: Add P1021MDS board support
  powerpc/85xx: Change MPC8572DS camp dtses for MSI sharing
  powerpc/fsl_msi: add removal path and probe failing path
  powerpc/fsl_msi: enable msi sharing through AMP OSes
  powerpc/fsl_msi: enable msi allocation in all banks
  powerpc/fsl_msi: fix the conflict of virt_msir's chip_data
  powerpc/fsl_msi: Add multiple MSI bank support
  powerpc/kexec: Add support for FSL-BookE
  powerpc/fsl-booke: Move the entry setup code into a seperate file
  powerpc/fsl-booke: fix the case where we are not in the first page
  powerpc/85xx: Enable support for ports 3 and 4 on 8548 CDS
  powerpc/fsl-booke: Add hibernation support for FSL BookE processors
  powerpc/e500mc: Implement machine check handler.
  powerpc/44x: Add basic ICON PPC440SPe board support
  powerpc/44x: Fix UART clocks on 440SPe
  powerpc/44x: Add reset-type to katmai.dts
  powerpc/44x: Adding PCI-E support for PowerPC 460SX based SOC.
parents 709d015b a7fed9f7
...@@ -351,7 +351,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE ...@@ -351,7 +351,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
config KEXEC config KEXEC
bool "kexec system call (EXPERIMENTAL)" bool "kexec system call (EXPERIMENTAL)"
depends on PPC_BOOK3S && EXPERIMENTAL depends on (PPC_BOOK3S || (FSL_BOOKE && !SMP)) && EXPERIMENTAL
help help
kexec is a system call that implements the ability to shutdown your kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot current kernel, and to start another kernel. It is like a reboot
......
...@@ -519,7 +519,7 @@ void ibm440ep_fixup_clocks(unsigned int sys_clk, ...@@ -519,7 +519,7 @@ void ibm440ep_fixup_clocks(unsigned int sys_clk,
{ {
unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 0); unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 0);
/* serial clocks beed fixup based on int/ext */ /* serial clocks need fixup based on int/ext */
eplike_fixup_uart_clk(0, "/plb/opb/serial@ef600300", ser_clk, plb_clk); eplike_fixup_uart_clk(0, "/plb/opb/serial@ef600300", ser_clk, plb_clk);
eplike_fixup_uart_clk(1, "/plb/opb/serial@ef600400", ser_clk, plb_clk); eplike_fixup_uart_clk(1, "/plb/opb/serial@ef600400", ser_clk, plb_clk);
eplike_fixup_uart_clk(2, "/plb/opb/serial@ef600500", ser_clk, plb_clk); eplike_fixup_uart_clk(2, "/plb/opb/serial@ef600500", ser_clk, plb_clk);
...@@ -532,7 +532,7 @@ void ibm440gx_fixup_clocks(unsigned int sys_clk, ...@@ -532,7 +532,7 @@ void ibm440gx_fixup_clocks(unsigned int sys_clk,
{ {
unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1); unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
/* serial clocks beed fixup based on int/ext */ /* serial clocks need fixup based on int/ext */
eplike_fixup_uart_clk(0, "/plb/opb/serial@40000200", ser_clk, plb_clk); eplike_fixup_uart_clk(0, "/plb/opb/serial@40000200", ser_clk, plb_clk);
eplike_fixup_uart_clk(1, "/plb/opb/serial@40000300", ser_clk, plb_clk); eplike_fixup_uart_clk(1, "/plb/opb/serial@40000300", ser_clk, plb_clk);
} }
...@@ -543,10 +543,10 @@ void ibm440spe_fixup_clocks(unsigned int sys_clk, ...@@ -543,10 +543,10 @@ void ibm440spe_fixup_clocks(unsigned int sys_clk,
{ {
unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1); unsigned int plb_clk = __ibm440eplike_fixup_clocks(sys_clk, tmr_clk, 1);
/* serial clocks beed fixup based on int/ext */ /* serial clocks need fixup based on int/ext */
eplike_fixup_uart_clk(0, "/plb/opb/serial@10000200", ser_clk, plb_clk); eplike_fixup_uart_clk(0, "/plb/opb/serial@f0000200", ser_clk, plb_clk);
eplike_fixup_uart_clk(1, "/plb/opb/serial@10000300", ser_clk, plb_clk); eplike_fixup_uart_clk(1, "/plb/opb/serial@f0000300", ser_clk, plb_clk);
eplike_fixup_uart_clk(2, "/plb/opb/serial@10000600", ser_clk, plb_clk); eplike_fixup_uart_clk(2, "/plb/opb/serial@f0000600", ser_clk, plb_clk);
} }
void ibm405gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk) void ibm405gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk)
......
This diff is collapsed.
...@@ -44,6 +44,7 @@ cpu@0 { ...@@ -44,6 +44,7 @@ cpu@0 {
d-cache-size = <32768>; d-cache-size = <32768>;
dcr-controller; dcr-controller;
dcr-access-method = "native"; dcr-access-method = "native";
reset-type = <2>; /* Use chip-reset */
}; };
}; };
......
...@@ -20,10 +20,8 @@ / { ...@@ -20,10 +20,8 @@ / {
aliases { aliases {
ethernet0 = &enet0; ethernet0 = &enet0;
ethernet1 = &enet1; ethernet1 = &enet1;
/*
ethernet2 = &enet2; ethernet2 = &enet2;
ethernet3 = &enet3; ethernet3 = &enet3;
*/
serial0 = &serial0; serial0 = &serial0;
serial1 = &serial1; serial1 = &serial1;
pci0 = &pci0; pci0 = &pci0;
...@@ -254,7 +252,6 @@ tbi1: tbi-phy@11 { ...@@ -254,7 +252,6 @@ tbi1: tbi-phy@11 {
}; };
}; };
/* eTSEC 3/4 are currently broken
enet2: ethernet@26000 { enet2: ethernet@26000 {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
...@@ -310,7 +307,6 @@ tbi3: tbi-phy@11 { ...@@ -310,7 +307,6 @@ tbi3: tbi-phy@11 {
}; };
}; };
}; };
*/
serial0: serial@4500 { serial0: serial@4500 {
cell-index = <0>; cell-index = <0>;
......
...@@ -215,6 +215,18 @@ serial0: serial@4500 { ...@@ -215,6 +215,18 @@ serial0: serial@4500 {
clock-frequency = <0>; clock-frequency = <0>;
}; };
msi@41600 {
compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
reg = <0x41600 0x80>;
msi-available-ranges = <0 0x80>;
interrupts = <
0xe0 0
0xe1 0
0xe2 0
0xe3 0>;
interrupt-parent = <&mpic>;
};
global-utilities@e0000 { //global utilities block global-utilities@e0000 { //global utilities block
compatible = "fsl,mpc8572-guts"; compatible = "fsl,mpc8572-guts";
reg = <0xe0000 0x1000>; reg = <0xe0000 0x1000>;
...@@ -243,8 +255,7 @@ mpic: pic@40000 { ...@@ -243,8 +255,7 @@ mpic: pic@40000 {
protected-sources = < protected-sources = <
31 32 33 37 38 39 /* enet2 enet3 */ 31 32 33 37 38 39 /* enet2 enet3 */
76 77 78 79 26 42 /* dma2 pci2 serial*/ 76 77 78 79 26 42 /* dma2 pci2 serial*/
0xe0 0xe1 0xe2 0xe3 /* msi */ 0xe4 0xe5 0xe6 0xe7 /* msi */
0xe4 0xe5 0xe6 0xe7
>; >;
}; };
}; };
......
...@@ -154,12 +154,8 @@ enet3: ethernet@27000 { ...@@ -154,12 +154,8 @@ enet3: ethernet@27000 {
msi@41600 { msi@41600 {
compatible = "fsl,mpc8572-msi", "fsl,mpic-msi"; compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
reg = <0x41600 0x80>; reg = <0x41600 0x80>;
msi-available-ranges = <0 0x100>; msi-available-ranges = <0x80 0x80>;
interrupts = < interrupts = <
0xe0 0
0xe1 0
0xe2 0
0xe3 0
0xe4 0 0xe4 0
0xe5 0 0xe5 0
0xe6 0 0xe6 0
...@@ -190,6 +186,7 @@ mpic: pic@40000 { ...@@ -190,6 +186,7 @@ mpic: pic@40000 {
0x1 0x2 0x3 0x4 /* pci slot */ 0x1 0x2 0x3 0x4 /* pci slot */
0x9 0xa 0xb 0xc /* usb */ 0x9 0xa 0xb 0xc /* usb */
0x6 0x7 0xe 0x5 /* Audio elgacy SATA */ 0x6 0x7 0xe 0x5 /* Audio elgacy SATA */
0xe0 0xe1 0xe2 0xe3 /* msi */
>; >;
}; };
}; };
......
This diff is collapsed.
...@@ -234,10 +234,132 @@ EMAC0: ethernet@ef600a00 { ...@@ -234,10 +234,132 @@ EMAC0: ethernet@ef600a00 {
has-inverted-stacr-oc; has-inverted-stacr-oc;
has-new-stacr-staopc; has-new-stacr-staopc;
}; };
};
PCIE0: pciex@d00000000 {
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
compatible = "ibm,plb-pciex-460sx", "ibm,plb-pciex";
primary;
port = <0x0>; /* port number */
reg = <0x0000000d 0x00000000 0x20000000 /* Config space access */
0x0000000c 0x10000000 0x00001000>; /* Registers */
dcr-reg = <0x100 0x020>;
sdr-base = <0x300>;
/* Outbound ranges, one memory and one IO,
* later cannot be changed
*/
ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000
0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>;
/* Inbound 2GB range starting at 0 */
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
/* This drives busses 10 to 0x1f */
bus-range = <0x10 0x1f>;
/* Legacy interrupts (note the weird polarity, the bridge seems
* to invert PCIe legacy interrupts).
* We are de-swizzling here because the numbers are actually for
* port of the root complex virtual P2P bridge. But I want
* to avoid putting a node for it in the tree, so the numbers
* below are basically de-swizzled numbers.
* The real slot is on idsel 0, so the swizzling is 1:1
*/
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
interrupt-map = <
0x0 0x0 0x0 0x1 &UIC3 0x0 0x4 /* swizzled int A */
0x0 0x0 0x0 0x2 &UIC3 0x1 0x4 /* swizzled int B */
0x0 0x0 0x0 0x3 &UIC3 0x2 0x4 /* swizzled int C */
0x0 0x0 0x0 0x4 &UIC3 0x3 0x4 /* swizzled int D */>;
};
PCIE1: pciex@d20000000 {
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
compatible = "ibm,plb-pciex-460sx", "ibm,plb-pciex";
primary;
port = <0x1>; /* port number */
reg = <0x0000000d 0x20000000 0x20000000 /* Config space access */
0x0000000c 0x10001000 0x00001000>; /* Registers */
dcr-reg = <0x120 0x020>;
sdr-base = <0x340>;
/* Outbound ranges, one memory and one IO,
* later cannot be changed
*/
ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000
0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>;
/* Inbound 2GB range starting at 0 */
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
/* This drives busses 10 to 0x1f */
bus-range = <0x20 0x2f>;
/* Legacy interrupts (note the weird polarity, the bridge seems
* to invert PCIe legacy interrupts).
* We are de-swizzling here because the numbers are actually for
* port of the root complex virtual P2P bridge. But I want
* to avoid putting a node for it in the tree, so the numbers
* below are basically de-swizzled numbers.
* The real slot is on idsel 0, so the swizzling is 1:1
*/
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
interrupt-map = <
0x0 0x0 0x0 0x1 &UIC3 0x4 0x4 /* swizzled int A */
0x0 0x0 0x0 0x2 &UIC3 0x5 0x4 /* swizzled int B */
0x0 0x0 0x0 0x3 &UIC3 0x6 0x4 /* swizzled int C */
0x0 0x0 0x0 0x4 &UIC3 0x7 0x4 /* swizzled int D */>;
}; };
PCIE2: pciex@d40000000 {
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
compatible = "ibm,plb-pciex-460sx", "ibm,plb-pciex";
primary;
port = <0x2>; /* port number */
reg = <0x0000000d 0x40000000 0x20000000 /* Config space access */
0x0000000c 0x10002000 0x00001000>; /* Registers */
dcr-reg = <0x140 0x020>;
sdr-base = <0x370>;
/* Outbound ranges, one memory and one IO,
* later cannot be changed
*/
ranges = <0x02000000 0x00000000 0x80000000 0x0000000f 0x00000000 0x00000000 0x80000000
0x01000000 0x00000000 0x00000000 0x0000000f 0x80020000 0x00000000 0x00010000>;
/* Inbound 2GB range starting at 0 */
dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x80000000>;
/* This drives busses 10 to 0x1f */
bus-range = <0x30 0x3f>;
/* Legacy interrupts (note the weird polarity, the bridge seems
* to invert PCIe legacy interrupts).
* We are de-swizzling here because the numbers are actually for
* port of the root complex virtual P2P bridge. But I want
* to avoid putting a node for it in the tree, so the numbers
* below are basically de-swizzled numbers.
* The real slot is on idsel 0, so the swizzling is 1:1
*/
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
interrupt-map = <
0x0 0x0 0x0 0x1 &UIC3 0x8 0x4 /* swizzled int A */
0x0 0x0 0x0 0x2 &UIC3 0x9 0x4 /* swizzled int B */
0x0 0x0 0x0 0x3 &UIC3 0xa 0x4 /* swizzled int C */
0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>;
}; };
};
chosen { chosen {
linux,stdout-path = "/plb/opb/serial@ef600200"; linux,stdout-path = "/plb/opb/serial@ef600200";
}; };
......
This diff is collapsed.
...@@ -70,6 +70,7 @@ struct pt_regs; ...@@ -70,6 +70,7 @@ struct pt_regs;
extern int machine_check_generic(struct pt_regs *regs); extern int machine_check_generic(struct pt_regs *regs);
extern int machine_check_4xx(struct pt_regs *regs); extern int machine_check_4xx(struct pt_regs *regs);
extern int machine_check_440A(struct pt_regs *regs); extern int machine_check_440A(struct pt_regs *regs);
extern int machine_check_e500mc(struct pt_regs *regs);
extern int machine_check_e500(struct pt_regs *regs); extern int machine_check_e500(struct pt_regs *regs);
extern int machine_check_e200(struct pt_regs *regs); extern int machine_check_e200(struct pt_regs *regs);
extern int machine_check_47x(struct pt_regs *regs); extern int machine_check_47x(struct pt_regs *regs);
......
...@@ -2,6 +2,18 @@ ...@@ -2,6 +2,18 @@
#define _ASM_POWERPC_KEXEC_H #define _ASM_POWERPC_KEXEC_H
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifdef CONFIG_FSL_BOOKE
/*
* On FSL-BookE we setup a 1:1 mapping which covers the first 2GiB of memory
* and therefore we can only deal with memory within this range
*/
#define KEXEC_SOURCE_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
#define KEXEC_DESTINATION_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
#define KEXEC_CONTROL_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
#else
/* /*
* Maximum page that is mapped directly into kernel memory. * Maximum page that is mapped directly into kernel memory.
* XXX: Since we copy virt we can use any page we allocate * XXX: Since we copy virt we can use any page we allocate
...@@ -21,6 +33,7 @@ ...@@ -21,6 +33,7 @@
/* TASK_SIZE, probably left over from use_mm ?? */ /* TASK_SIZE, probably left over from use_mm ?? */
#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE #define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
#endif #endif
#endif
#define KEXEC_CONTROL_PAGE_SIZE 4096 #define KEXEC_CONTROL_PAGE_SIZE 4096
......
...@@ -4,6 +4,12 @@ ...@@ -4,6 +4,12 @@
* are not true Book E PowerPCs, they borrowed a number of features * are not true Book E PowerPCs, they borrowed a number of features
* before Book E was finalized, and are included here as well. Unfortunatly, * before Book E was finalized, and are included here as well. Unfortunatly,
* they sometimes used different locations than true Book E CPUs did. * they sometimes used different locations than true Book E CPUs did.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* Copyright 2009-2010 Freescale Semiconductor, Inc.
*/ */
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifndef __ASM_POWERPC_REG_BOOKE_H__ #ifndef __ASM_POWERPC_REG_BOOKE_H__
...@@ -88,6 +94,7 @@ ...@@ -88,6 +94,7 @@
#define SPRN_IVOR35 0x213 /* Interrupt Vector Offset Register 35 */ #define SPRN_IVOR35 0x213 /* Interrupt Vector Offset Register 35 */
#define SPRN_IVOR36 0x214 /* Interrupt Vector Offset Register 36 */ #define SPRN_IVOR36 0x214 /* Interrupt Vector Offset Register 36 */
#define SPRN_IVOR37 0x215 /* Interrupt Vector Offset Register 37 */ #define SPRN_IVOR37 0x215 /* Interrupt Vector Offset Register 37 */
#define SPRN_MCARU 0x239 /* Machine Check Address Register Upper */
#define SPRN_MCSRR0 0x23A /* Machine Check Save and Restore Register 0 */ #define SPRN_MCSRR0 0x23A /* Machine Check Save and Restore Register 0 */
#define SPRN_MCSRR1 0x23B /* Machine Check Save and Restore Register 1 */ #define SPRN_MCSRR1 0x23B /* Machine Check Save and Restore Register 1 */
#define SPRN_MCSR 0x23C /* Machine Check Status Register */ #define SPRN_MCSR 0x23C /* Machine Check Status Register */
...@@ -196,8 +203,11 @@ ...@@ -196,8 +203,11 @@
#define PPC47x_MCSR_IPR 0x00400000 /* Imprecise Machine Check Exception */ #define PPC47x_MCSR_IPR 0x00400000 /* Imprecise Machine Check Exception */
#ifdef CONFIG_E500 #ifdef CONFIG_E500
/* All e500 */
#define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */ #define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */
#define MCSR_ICPERR 0x40000000UL /* I-Cache Parity Error */ #define MCSR_ICPERR 0x40000000UL /* I-Cache Parity Error */
/* e500v1/v2 */
#define MCSR_DCP_PERR 0x20000000UL /* D-Cache Push Parity Error */ #define MCSR_DCP_PERR 0x20000000UL /* D-Cache Push Parity Error */
#define MCSR_DCPERR 0x10000000UL /* D-Cache Parity Error */ #define MCSR_DCPERR 0x10000000UL /* D-Cache Parity Error */
#define MCSR_BUS_IAERR 0x00000080UL /* Instruction Address Error */ #define MCSR_BUS_IAERR 0x00000080UL /* Instruction Address Error */
...@@ -209,12 +219,20 @@ ...@@ -209,12 +219,20 @@
#define MCSR_BUS_IPERR 0x00000002UL /* Instruction parity Error */ #define MCSR_BUS_IPERR 0x00000002UL /* Instruction parity Error */
#define MCSR_BUS_RPERR 0x00000001UL /* Read parity Error */ #define MCSR_BUS_RPERR 0x00000001UL /* Read parity Error */
/* e500 parts may set unused bits in MCSR; mask these off */ /* e500mc */
#define MCSR_MASK (MCSR_MCP | MCSR_ICPERR | MCSR_DCP_PERR | \ #define MCSR_DCPERR_MC 0x20000000UL /* D-Cache Parity Error */
MCSR_DCPERR | MCSR_BUS_IAERR | MCSR_BUS_RAERR | \ #define MCSR_L2MMU_MHIT 0x04000000UL /* Hit on multiple TLB entries */
MCSR_BUS_WAERR | MCSR_BUS_IBERR | MCSR_BUS_RBERR | \ #define MCSR_NMI 0x00100000UL /* Non-Maskable Interrupt */
MCSR_BUS_WBERR | MCSR_BUS_IPERR | MCSR_BUS_RPERR) #define MCSR_MAV 0x00080000UL /* MCAR address valid */
#define MCSR_MEA 0x00040000UL /* MCAR is effective address */
#define MCSR_IF 0x00010000UL /* Instruction Fetch */
#define MCSR_LD 0x00008000UL /* Load */
#define MCSR_ST 0x00004000UL /* Store */
#define MCSR_LDG 0x00002000UL /* Guarded Load */
#define MCSR_TLBSYNC 0x00000002UL /* Multiple tlbsyncs detected */
#define MCSR_BSL2_ERR 0x00000001UL /* Backside L2 cache error */
#endif #endif
#ifdef CONFIG_E200 #ifdef CONFIG_E200
#define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */ #define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */
#define MCSR_CP_PERR 0x20000000UL /* Cache Push Parity Error */ #define MCSR_CP_PERR 0x20000000UL /* Cache Push Parity Error */
...@@ -225,11 +243,6 @@ ...@@ -225,11 +243,6 @@
#define MCSR_BUS_DRERR 0x00000008UL /* Read Bus Error on data load */ #define MCSR_BUS_DRERR 0x00000008UL /* Read Bus Error on data load */
#define MCSR_BUS_WRERR 0x00000004UL /* Write Bus Error on buffered #define MCSR_BUS_WRERR 0x00000004UL /* Write Bus Error on buffered
store or cache line push */ store or cache line push */
/* e200 parts may set unused bits in MCSR; mask these off */
#define MCSR_MASK (MCSR_MCP | MCSR_CP_PERR | MCSR_CPERR | \
MCSR_EXCP_ERR | MCSR_BUS_IRERR | MCSR_BUS_DRERR | \
MCSR_BUS_WRERR)
#endif #endif
/* Bit definitions for the DBSR. */ /* Bit definitions for the DBSR. */
......
...@@ -57,8 +57,12 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o ...@@ -57,8 +57,12 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_E500) += idle_e500.o obj-$(CONFIG_E500) += idle_e500.o
obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
obj-$(CONFIG_TAU) += tau_6xx.o obj-$(CONFIG_TAU) += tau_6xx.o
obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \ obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o
swsusp_$(CONFIG_WORD_SIZE).o ifeq ($(CONFIG_FSL_BOOKE),y)
obj-$(CONFIG_HIBERNATION) += swsusp_booke.o
else
obj-$(CONFIG_HIBERNATION) += swsusp_$(CONFIG_WORD_SIZE).o
endif
obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o
obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o
obj-$(CONFIG_44x) += cpu_setup_44x.o obj-$(CONFIG_44x) += cpu_setup_44x.o
......
...@@ -1840,7 +1840,7 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -1840,7 +1840,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.oprofile_cpu_type = "ppc/e500mc", .oprofile_cpu_type = "ppc/e500mc",
.oprofile_type = PPC_OPROFILE_FSL_EMB, .oprofile_type = PPC_OPROFILE_FSL_EMB,
.cpu_setup = __setup_cpu_e500mc, .cpu_setup = __setup_cpu_e500mc,
.machine_check = machine_check_e500, .machine_check = machine_check_e500mc,
.platform = "ppce500mc", .platform = "ppce500mc",
}, },
{ /* default match */ { /* default match */
......
...@@ -163,6 +163,7 @@ static void crash_kexec_prepare_cpus(int cpu) ...@@ -163,6 +163,7 @@ static void crash_kexec_prepare_cpus(int cpu)
} }
/* wait for all the CPUs to hit real mode but timeout if they don't come in */ /* wait for all the CPUs to hit real mode but timeout if they don't come in */
#ifdef CONFIG_PPC_STD_MMU_64
static void crash_kexec_wait_realmode(int cpu) static void crash_kexec_wait_realmode(int cpu)
{ {
unsigned int msecs; unsigned int msecs;
...@@ -187,6 +188,7 @@ static void crash_kexec_wait_realmode(int cpu) ...@@ -187,6 +188,7 @@ static void crash_kexec_wait_realmode(int cpu)
} }
mb(); mb();
} }
#endif
/* /*
* This function will be called by secondary cpus or by kexec cpu * This function will be called by secondary cpus or by kexec cpu
...@@ -445,7 +447,9 @@ void default_machine_crash_shutdown(struct pt_regs *regs) ...@@ -445,7 +447,9 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
crash_kexec_prepare_cpus(crashing_cpu); crash_kexec_prepare_cpus(crashing_cpu);
cpu_set(crashing_cpu, cpus_in_crash); cpu_set(crashing_cpu, cpus_in_crash);
crash_kexec_stop_spus(); crash_kexec_stop_spus();
#ifdef CONFIG_PPC_STD_MMU_64
crash_kexec_wait_realmode(crashing_cpu); crash_kexec_wait_realmode(crashing_cpu);
#endif
if (ppc_md.kexec_cpu_down) if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 0); ppc_md.kexec_cpu_down(1, 0);
} }
/* 1. Find the index of the entry we're executing in */
bl invstr /* Find our address */
invstr: mflr r6 /* Make it accessible */
mfmsr r7
rlwinm r4,r7,27,31,31 /* extract MSR[IS] */
mfspr r7, SPRN_PID0
slwi r7,r7,16
or r7,r7,r4
mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */
mfspr r7,SPRN_MAS1
andis. r7,r7,MAS1_VALID@h
bne match_TLB
mfspr r7,SPRN_MMUCFG
rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
cmpwi r7,3
bne match_TLB /* skip if NPIDS != 3 */
mfspr r7,SPRN_PID1
slwi r7,r7,16
or r7,r7,r4
mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* search MSR[IS], SPID=PID1 */
mfspr r7,SPRN_MAS1
andis. r7,r7,MAS1_VALID@h
bne match_TLB
mfspr r7, SPRN_PID2
slwi r7,r7,16
or r7,r7,r4
mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* Fall through, we had to match */
match_TLB:
mfspr r7,SPRN_MAS0
rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */
mfspr r7,SPRN_MAS1 /* Insure IPROT set */
oris r7,r7,MAS1_IPROT@h
mtspr SPRN_MAS1,r7
tlbwe
/* 2. Invalidate all entries except the entry we're executing in */
mfspr r9,SPRN_TLB1CFG
andi. r9,r9,0xfff
li r6,0 /* Set Entry counter to 0 */
1: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */
mtspr SPRN_MAS0,r7
tlbre
mfspr r7,SPRN_MAS1
rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */
cmpw r3,r6
beq skpinv /* Dont update the current execution TLB */
mtspr SPRN_MAS1,r7
tlbwe
isync
skpinv: addi r6,r6,1 /* Increment */
cmpw r6,r9 /* Are we done? */
bne 1b /* If not, repeat */
/* Invalidate TLB0 */
li r6,0x04
tlbivax 0,r6
TLBSYNC
/* Invalidate TLB1 */
li r6,0x0c
tlbivax 0,r6
TLBSYNC
/* 3. Setup a temp mapping and jump to it */
andi. r5, r3, 0x1 /* Find an entry not used and is non-zero */
addi r5, r5, 0x1
lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
mtspr SPRN_MAS0,r7
tlbre
/* grab and fixup the RPN */
mfspr r6,SPRN_MAS1 /* extract MAS1[SIZE] */
rlwinm r6,r6,25,27,31
li r8,-1
addi r6,r6,10
slw r6,r8,r6 /* convert to mask */
bl 1f /* Find our address */
1: mflr r7
mfspr r8,SPRN_MAS3
#ifdef CONFIG_PHYS_64BIT
mfspr r23,SPRN_MAS7
#endif
and r8,r6,r8
subfic r9,r6,-4096
and r9,r9,r7
or r25,r8,r9
ori r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
/* Just modify the entry ID and EPN for the temp mapping */
lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
mtspr SPRN_MAS0,r7
xori r6,r4,1 /* Setup TMP mapping in the other Address space */
slwi r6,r6,12
oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h
ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
mtspr SPRN_MAS1,r6
mfspr r6,SPRN_MAS2
li r7,0 /* temp EPN = 0 */
rlwimi r7,r6,0,20,31
mtspr SPRN_MAS2,r7
mtspr SPRN_MAS3,r8
tlbwe
xori r6,r4,1
slwi r6,r6,5 /* setup new context with other address space */
bl 1f /* Find our address */
1: mflr r9
rlwimi r7,r9,0,20,31
addi r7,r7,(2f - 1b)
mtspr SPRN_SRR0,r7
mtspr SPRN_SRR1,r6
rfi
2:
/* 4. Clear out PIDs & Search info */
li r6,0
mtspr SPRN_MAS6,r6
mtspr SPRN_PID0,r6
mfspr r7,SPRN_MMUCFG
rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
cmpwi r7,3
bne 2f /* skip if NPIDS != 3 */
mtspr SPRN_PID1,r6
mtspr SPRN_PID2,r6
/* 5. Invalidate mapping we started in */
2:
lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
mtspr SPRN_MAS0,r7
tlbre
mfspr r6,SPRN_MAS1
rlwinm r6,r6,0,2,0 /* clear IPROT */
mtspr SPRN_MAS1,r6
tlbwe
/* Invalidate TLB1 */
li r9,0x0c
tlbivax 0,r9
TLBSYNC
/* The mapping only needs to be cache-coherent on SMP */
#ifdef CONFIG_SMP
#define M_IF_SMP MAS2_M
#else
#define M_IF_SMP 0
#endif
#if defined(ENTRY_MAPPING_BOOT_SETUP)
/* 6. Setup KERNELBASE mapping in TLB1[0] */
lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
mtspr SPRN_MAS0,r6
lis r6,(MAS1_VALID|MAS1_IPROT)@h
ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
mtspr SPRN_MAS1,r6
lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
mtspr SPRN_MAS2,r6
mtspr SPRN_MAS3,r8
tlbwe
/* 7. Jump to KERNELBASE mapping */
lis r6,(KERNELBASE & ~0xfff)@h
ori r6,r6,(KERNELBASE & ~0xfff)@l
#elif defined(ENTRY_MAPPING_KEXEC_SETUP)
/*
* 6. Setup a 1:1 mapping in TLB1. Esel 0 is unsued, 1 or 2 contains the tmp
* mapping so we start at 3. We setup 8 mappings, each 256MiB in size. This
* will cover the first 2GiB of memory.
*/
lis r10, (MAS1_VALID|MAS1_IPROT)@h
ori r10,r10, (MAS1_TSIZE(BOOK3E_PAGESZ_256M))@l
li r11, 0
li r0, 8
mtctr r0
next_tlb_setup:
addi r0, r11, 3
rlwinm r0, r0, 16, 4, 15 // Compute esel
rlwinm r9, r11, 28, 0, 3 // Compute [ER]PN
oris r0, r0, (MAS0_TLBSEL(1))@h
mtspr SPRN_MAS0,r0
mtspr SPRN_MAS1,r10
mtspr SPRN_MAS2,r9
ori r9, r9, (MAS3_SX|MAS3_SW|MAS3_SR)
mtspr SPRN_MAS3,r9
tlbwe
addi r11, r11, 1
bdnz+ next_tlb_setup
/* 7. Jump to our 1:1 mapping */
li r6, 0
#else
#error You need to specify the mapping or not use this at all.
#endif
lis r7,MSR_KERNEL@h
ori r7,r7,MSR_KERNEL@l
bl 1f /* Find our address */
1: mflr r9
rlwimi r6,r9,0,20,31
addi r6,r6,(2f - 1b)
add r6, r6, r25
mtspr SPRN_SRR0,r6
mtspr SPRN_SRR1,r7
rfi /* start execution out of TLB1[0] entry */
/* 8. Clear out the temp mapping */
2: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
mtspr SPRN_MAS0,r7
tlbre
mfspr r8,SPRN_MAS1
rlwinm r8,r8,0,2,0 /* clear IPROT */
mtspr SPRN_MAS1,r8
tlbwe
/* Invalidate TLB1 */
li r9,0x0c
tlbivax 0,r9
TLBSYNC
...@@ -94,204 +94,10 @@ _ENTRY(_start); ...@@ -94,204 +94,10 @@ _ENTRY(_start);
*/ */
_ENTRY(__early_start) _ENTRY(__early_start)
/* 1. Find the index of the entry we're executing in */
bl invstr /* Find our address */
invstr: mflr r6 /* Make it accessible */
mfmsr r7
rlwinm r4,r7,27,31,31 /* extract MSR[IS] */
mfspr r7, SPRN_PID0
slwi r7,r7,16
or r7,r7,r4
mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */
mfspr r7,SPRN_MAS1
andis. r7,r7,MAS1_VALID@h
bne match_TLB
mfspr r7,SPRN_MMUCFG
rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
cmpwi r7,3
bne match_TLB /* skip if NPIDS != 3 */
mfspr r7,SPRN_PID1
slwi r7,r7,16
or r7,r7,r4
mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* search MSR[IS], SPID=PID1 */
mfspr r7,SPRN_MAS1
andis. r7,r7,MAS1_VALID@h
bne match_TLB
mfspr r7, SPRN_PID2
slwi r7,r7,16
or r7,r7,r4
mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* Fall through, we had to match */
match_TLB:
mfspr r7,SPRN_MAS0
rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */
mfspr r7,SPRN_MAS1 /* Insure IPROT set */
oris r7,r7,MAS1_IPROT@h
mtspr SPRN_MAS1,r7
tlbwe
/* 2. Invalidate all entries except the entry we're executing in */
mfspr r9,SPRN_TLB1CFG
andi. r9,r9,0xfff
li r6,0 /* Set Entry counter to 0 */
1: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */
mtspr SPRN_MAS0,r7
tlbre
mfspr r7,SPRN_MAS1
rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */
cmpw r3,r6
beq skpinv /* Dont update the current execution TLB */
mtspr SPRN_MAS1,r7
tlbwe
isync
skpinv: addi r6,r6,1 /* Increment */
cmpw r6,r9 /* Are we done? */
bne 1b /* If not, repeat */
/* Invalidate TLB0 */
li r6,0x04
tlbivax 0,r6
TLBSYNC
/* Invalidate TLB1 */
li r6,0x0c
tlbivax 0,r6
TLBSYNC
/* 3. Setup a temp mapping and jump to it */
andi. r5, r3, 0x1 /* Find an entry not used and is non-zero */
addi r5, r5, 0x1
lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
mtspr SPRN_MAS0,r7
tlbre
/* grab and fixup the RPN */
mfspr r6,SPRN_MAS1 /* extract MAS1[SIZE] */
rlwinm r6,r6,25,27,31
li r8,-1
addi r6,r6,10
slw r6,r8,r6 /* convert to mask */
bl 1f /* Find our address */
1: mflr r7
mfspr r8,SPRN_MAS3
#ifdef CONFIG_PHYS_64BIT
mfspr r23,SPRN_MAS7
#endif
and r8,r6,r8
subfic r9,r6,-4096
and r9,r9,r7
or r25,r8,r9
ori r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
/* Just modify the entry ID and EPN for the temp mapping */
lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
mtspr SPRN_MAS0,r7
xori r6,r4,1 /* Setup TMP mapping in the other Address space */
slwi r6,r6,12
oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h
ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
mtspr SPRN_MAS1,r6
mfspr r6,SPRN_MAS2
li r7,0 /* temp EPN = 0 */
rlwimi r7,r6,0,20,31
mtspr SPRN_MAS2,r7
mtspr SPRN_MAS3,r8
tlbwe
xori r6,r4,1
slwi r6,r6,5 /* setup new context with other address space */
bl 1f /* Find our address */
1: mflr r9
rlwimi r7,r9,0,20,31
addi r7,r7,(2f - 1b)
mtspr SPRN_SRR0,r7
mtspr SPRN_SRR1,r6
rfi
2:
/* 4. Clear out PIDs & Search info */
li r6,0
mtspr SPRN_MAS6,r6
mtspr SPRN_PID0,r6
mfspr r7,SPRN_MMUCFG
rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */
cmpwi r7,3
bne 2f /* skip if NPIDS != 3 */
mtspr SPRN_PID1,r6 #define ENTRY_MAPPING_BOOT_SETUP
mtspr SPRN_PID2,r6 #include "fsl_booke_entry_mapping.S"
#undef ENTRY_MAPPING_BOOT_SETUP
/* 5. Invalidate mapping we started in */
2:
lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */
mtspr SPRN_MAS0,r7
tlbre
mfspr r6,SPRN_MAS1
rlwinm r6,r6,0,2,0 /* clear IPROT */
mtspr SPRN_MAS1,r6
tlbwe
/* Invalidate TLB1 */
li r9,0x0c
tlbivax 0,r9
TLBSYNC
/* The mapping only needs to be cache-coherent on SMP */
#ifdef CONFIG_SMP
#define M_IF_SMP MAS2_M
#else
#define M_IF_SMP 0
#endif
/* 6. Setup KERNELBASE mapping in TLB1[0] */
lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
mtspr SPRN_MAS0,r6
lis r6,(MAS1_VALID|MAS1_IPROT)@h
ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
mtspr SPRN_MAS1,r6
lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h
ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l
mtspr SPRN_MAS2,r6
mtspr SPRN_MAS3,r8
tlbwe
/* 7. Jump to KERNELBASE mapping */
lis r6,(KERNELBASE & ~0xfff)@h
ori r6,r6,(KERNELBASE & ~0xfff)@l
lis r7,MSR_KERNEL@h
ori r7,r7,MSR_KERNEL@l
bl 1f /* Find our address */
1: mflr r9
rlwimi r6,r9,0,20,31
addi r6,r6,(2f - 1b)
mtspr SPRN_SRR0,r6
mtspr SPRN_SRR1,r7
rfi /* start execution out of TLB1[0] entry */
/* 8. Clear out the temp mapping */
2: lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */
rlwimi r7,r5,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r5) */
mtspr SPRN_MAS0,r7
tlbre
mfspr r8,SPRN_MAS1
rlwinm r8,r8,0,2,0 /* clear IPROT */
mtspr SPRN_MAS1,r8
tlbwe
/* Invalidate TLB1 */
li r9,0x0c
tlbivax 0,r9
TLBSYNC
/* Establish the interrupt vector offsets */ /* Establish the interrupt vector offsets */
SET_IVOR(0, CriticalInput); SET_IVOR(0, CriticalInput);
......
...@@ -711,6 +711,22 @@ relocate_new_kernel: ...@@ -711,6 +711,22 @@ relocate_new_kernel:
/* r4 = reboot_code_buffer */ /* r4 = reboot_code_buffer */
/* r5 = start_address */ /* r5 = start_address */
#ifdef CONFIG_FSL_BOOKE
mr r29, r3
mr r30, r4
mr r31, r5
#define ENTRY_MAPPING_KEXEC_SETUP
#include "fsl_booke_entry_mapping.S"
#undef ENTRY_MAPPING_KEXEC_SETUP
mr r3, r29
mr r4, r30
mr r5, r31
li r0, 0
#else
li r0, 0 li r0, 0
/* /*
...@@ -727,6 +743,7 @@ relocate_new_kernel: ...@@ -727,6 +743,7 @@ relocate_new_kernel:
rfi rfi
1: 1:
#endif
/* from this point address translation is turned off */ /* from this point address translation is turned off */
/* and interrupts are disabled */ /* and interrupts are disabled */
......
...@@ -101,7 +101,7 @@ EXPORT_SYMBOL(pci_dram_offset); ...@@ -101,7 +101,7 @@ EXPORT_SYMBOL(pci_dram_offset);
EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(kernel_thread);
#ifndef CONFIG_BOOKE #ifdef CONFIG_PPC_FPU
EXPORT_SYMBOL_GPL(cvt_df); EXPORT_SYMBOL_GPL(cvt_df);
EXPORT_SYMBOL_GPL(cvt_fd); EXPORT_SYMBOL_GPL(cvt_fd);
#endif #endif
......
/*
* Based on swsusp_32.S, modified for FSL BookE by
* Anton Vorontsov <avorontsov@ru.mvista.com>
* Copyright (c) 2009-2010 MontaVista Software, LLC.
*/
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/mmu.h>
/*
* Structure for storing CPU registers on the save area.
*/
#define SL_SP 0
#define SL_PC 4
#define SL_MSR 8
#define SL_TCR 0xc
#define SL_SPRG0 0x10
#define SL_SPRG1 0x14
#define SL_SPRG2 0x18
#define SL_SPRG3 0x1c
#define SL_SPRG4 0x20
#define SL_SPRG5 0x24
#define SL_SPRG6 0x28
#define SL_SPRG7 0x2c
#define SL_TBU 0x30
#define SL_TBL 0x34
#define SL_R2 0x38
#define SL_CR 0x3c
#define SL_LR 0x40
#define SL_R12 0x44 /* r12 to r31 */
#define SL_SIZE (SL_R12 + 80)
.section .data
.align 5
_GLOBAL(swsusp_save_area)
.space SL_SIZE
.section .text
.align 5
_GLOBAL(swsusp_arch_suspend)
lis r11,swsusp_save_area@h
ori r11,r11,swsusp_save_area@l
mflr r0
stw r0,SL_LR(r11)
mfcr r0
stw r0,SL_CR(r11)
stw r1,SL_SP(r11)
stw r2,SL_R2(r11)
stmw r12,SL_R12(r11)
/* Save MSR & TCR */
mfmsr r4
stw r4,SL_MSR(r11)
mfspr r4,SPRN_TCR
stw r4,SL_TCR(r11)
/* Get a stable timebase and save it */
1: mfspr r4,SPRN_TBRU
stw r4,SL_TBU(r11)
mfspr r5,SPRN_TBRL
stw r5,SL_TBL(r11)
mfspr r3,SPRN_TBRU
cmpw r3,r4
bne 1b
/* Save SPRGs */
mfsprg r4,0
stw r4,SL_SPRG0(r11)
mfsprg r4,1
stw r4,SL_SPRG1(r11)
mfsprg r4,2
stw r4,SL_SPRG2(r11)
mfsprg r4,3
stw r4,SL_SPRG3(r11)
mfsprg r4,4
stw r4,SL_SPRG4(r11)
mfsprg r4,5
stw r4,SL_SPRG5(r11)
mfsprg r4,6
stw r4,SL_SPRG6(r11)
mfsprg r4,7
stw r4,SL_SPRG7(r11)
/* Call the low level suspend stuff (we should probably have made
* a stackframe...
*/
bl swsusp_save
/* Restore LR from the save area */
lis r11,swsusp_save_area@h
ori r11,r11,swsusp_save_area@l
lwz r0,SL_LR(r11)
mtlr r0
blr
_GLOBAL(swsusp_arch_resume)
sync
/* Load ptr the list of pages to copy in r3 */
lis r11,(restore_pblist)@h
ori r11,r11,restore_pblist@l
lwz r3,0(r11)
/* Copy the pages. This is a very basic implementation, to
* be replaced by something more cache efficient */
1:
li r0,256
mtctr r0
lwz r5,pbe_address(r3) /* source */
lwz r6,pbe_orig_address(r3) /* destination */
2:
lwz r8,0(r5)
lwz r9,4(r5)
lwz r10,8(r5)
lwz r11,12(r5)
addi r5,r5,16
stw r8,0(r6)
stw r9,4(r6)
stw r10,8(r6)
stw r11,12(r6)
addi r6,r6,16
bdnz 2b
lwz r3,pbe_next(r3)
cmpwi 0,r3,0
bne 1b
bl flush_dcache_L1
bl flush_instruction_cache
lis r11,swsusp_save_area@h
ori r11,r11,swsusp_save_area@l
lwz r4,SL_SPRG0(r11)
mtsprg 0,r4
lwz r4,SL_SPRG1(r11)
mtsprg 1,r4
lwz r4,SL_SPRG2(r11)
mtsprg 2,r4
lwz r4,SL_SPRG3(r11)
mtsprg 3,r4
lwz r4,SL_SPRG4(r11)
mtsprg 4,r4
lwz r4,SL_SPRG5(r11)
mtsprg 5,r4
lwz r4,SL_SPRG6(r11)
mtsprg 6,r4
lwz r4,SL_SPRG7(r11)
mtsprg 7,r4
/* restore the MSR */
lwz r3,SL_MSR(r11)
mtmsr r3
/* Restore TB */
li r3,0
mtspr SPRN_TBWL,r3
lwz r3,SL_TBU(r11)
lwz r4,SL_TBL(r11)
mtspr SPRN_TBWU,r3
mtspr SPRN_TBWL,r4
/* Restore TCR and clear any pending bits in TSR. */
lwz r4,SL_TCR(r11)
mtspr SPRN_TCR,r4
lis r4, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h
mtspr SPRN_TSR,r4
/* Kick decrementer */
li r0,1
mtdec r0
/* Restore the callee-saved registers and return */
lwz r0,SL_CR(r11)
mtcr r0
lwz r2,SL_R2(r11)
lmw r12,SL_R12(r11)
lwz r1,SL_SP(r11)
lwz r0,SL_LR(r11)
mtlr r0
li r3,0
blr
/* /*
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
* Copyright 2007-2010 Freescale Semiconductor, Inc.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -305,7 +306,7 @@ static inline int check_io_access(struct pt_regs *regs) ...@@ -305,7 +306,7 @@ static inline int check_io_access(struct pt_regs *regs)
#ifndef CONFIG_FSL_BOOKE #ifndef CONFIG_FSL_BOOKE
#define get_mc_reason(regs) ((regs)->dsisr) #define get_mc_reason(regs) ((regs)->dsisr)
#else #else
#define get_mc_reason(regs) (mfspr(SPRN_MCSR) & MCSR_MASK) #define get_mc_reason(regs) (mfspr(SPRN_MCSR))
#endif #endif
#define REASON_FP ESR_FP #define REASON_FP ESR_FP
#define REASON_ILLEGAL (ESR_PIL | ESR_PUO) #define REASON_ILLEGAL (ESR_PIL | ESR_PUO)
...@@ -421,6 +422,91 @@ int machine_check_47x(struct pt_regs *regs) ...@@ -421,6 +422,91 @@ int machine_check_47x(struct pt_regs *regs)
return 0; return 0;
} }
#elif defined(CONFIG_E500) #elif defined(CONFIG_E500)
int machine_check_e500mc(struct pt_regs *regs)
{
unsigned long mcsr = mfspr(SPRN_MCSR);
unsigned long reason = mcsr;
int recoverable = 1;
printk("Machine check in kernel mode.\n");
printk("Caused by (from MCSR=%lx): ", reason);
if (reason & MCSR_MCP)
printk("Machine Check Signal\n");
if (reason & MCSR_ICPERR) {
printk("Instruction Cache Parity Error\n");
/*
* This is recoverable by invalidating the i-cache.
*/
mtspr(SPRN_L1CSR1, mfspr(SPRN_L1CSR1) | L1CSR1_ICFI);
while (mfspr(SPRN_L1CSR1) & L1CSR1_ICFI)
;
/*
* This will generally be accompanied by an instruction
* fetch error report -- only treat MCSR_IF as fatal
* if it wasn't due to an L1 parity error.
*/
reason &= ~MCSR_IF;
}
if (reason & MCSR_DCPERR_MC) {
printk("Data Cache Parity Error\n");
recoverable = 0;
}
if (reason & MCSR_L2MMU_MHIT) {
printk("Hit on multiple TLB entries\n");
recoverable = 0;
}
if (reason & MCSR_NMI)
printk("Non-maskable interrupt\n");
if (reason & MCSR_IF) {
printk("Instruction Fetch Error Report\n");
recoverable = 0;
}
if (reason & MCSR_LD) {
printk("Load Error Report\n");
recoverable = 0;
}
if (reason & MCSR_ST) {
printk("Store Error Report\n");
recoverable = 0;
}
if (reason & MCSR_LDG) {
printk("Guarded Load Error Report\n");
recoverable = 0;
}
if (reason & MCSR_TLBSYNC)
printk("Simultaneous tlbsync operations\n");
if (reason & MCSR_BSL2_ERR) {
printk("Level 2 Cache Error\n");
recoverable = 0;
}
if (reason & MCSR_MAV) {
u64 addr;
addr = mfspr(SPRN_MCAR);
addr |= (u64)mfspr(SPRN_MCARU) << 32;
printk("Machine Check %s Address: %#llx\n",
reason & MCSR_MEA ? "Effective" : "Physical", addr);
}
mtspr(SPRN_MCSR, mcsr);
return mfspr(SPRN_MCSR) == 0 && recoverable;
}
int machine_check_e500(struct pt_regs *regs) int machine_check_e500(struct pt_regs *regs)
{ {
unsigned long reason = get_mc_reason(regs); unsigned long reason = get_mc_reason(regs);
......
...@@ -171,6 +171,17 @@ config ISS4xx ...@@ -171,6 +171,17 @@ config ISS4xx
help help
This option enables support for the IBM ISS simulation environment This option enables support for the IBM ISS simulation environment
config ICON
bool "Icon"
depends on 44x
default n
select PPC44x_SIMPLE
select 440SPe
select PCI
select PPC4xx_PCI_EXPRESS
help
This option enables support for the AMCC PPC440SPe evaluation board.
#config LUAN #config LUAN
# bool "Luan" # bool "Luan"
# depends on 44x # depends on 44x
......
...@@ -61,7 +61,8 @@ static char *board[] __initdata = { ...@@ -61,7 +61,8 @@ static char *board[] __initdata = {
"amcc,redwood", "amcc,redwood",
"amcc,sequoia", "amcc,sequoia",
"amcc,taishan", "amcc,taishan",
"amcc,yosemite" "amcc,yosemite",
"mosaixtech,icon"
}; };
static int __init ppc44x_probe(void) static int __init ppc44x_probe(void)
......
/* /*
* Copyright (C) Freescale Semicondutor, Inc. 2006-2007. All rights reserved. * Copyright (C) Freescale Semicondutor, Inc. 2006-2010. All rights reserved.
* *
* Author: Andy Fleming <afleming@freescale.com> * Author: Andy Fleming <afleming@freescale.com>
* *
...@@ -154,6 +154,10 @@ static int mpc8568_mds_phy_fixups(struct phy_device *phydev) ...@@ -154,6 +154,10 @@ static int mpc8568_mds_phy_fixups(struct phy_device *phydev)
* Setup the architecture * Setup the architecture
* *
*/ */
#ifdef CONFIG_SMP
extern void __init mpc85xx_smp_init(void);
#endif
static void __init mpc85xx_mds_setup_arch(void) static void __init mpc85xx_mds_setup_arch(void)
{ {
struct device_node *np; struct device_node *np;
...@@ -194,6 +198,10 @@ static void __init mpc85xx_mds_setup_arch(void) ...@@ -194,6 +198,10 @@ static void __init mpc85xx_mds_setup_arch(void)
} }
#endif #endif
#ifdef CONFIG_SMP
mpc85xx_smp_init();
#endif
#ifdef CONFIG_QUICC_ENGINE #ifdef CONFIG_QUICC_ENGINE
np = of_find_compatible_node(NULL, NULL, "fsl,qe"); np = of_find_compatible_node(NULL, NULL, "fsl,qe");
if (!np) { if (!np) {
...@@ -271,9 +279,49 @@ static void __init mpc85xx_mds_setup_arch(void) ...@@ -271,9 +279,49 @@ static void __init mpc85xx_mds_setup_arch(void)
BCSR_UCC_RGMII, BCSR_UCC_RTBI); BCSR_UCC_RGMII, BCSR_UCC_RTBI);
} }
} else if (machine_is(p1021_mds)) {
#define BCSR11_ENET_MICRST (0x1 << 5)
/* Reset Micrel PHY */
clrbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
setbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
} }
iounmap(bcsr_regs); iounmap(bcsr_regs);
} }
if (machine_is(p1021_mds)) {
#define MPC85xx_PMUXCR_OFFSET 0x60
#define MPC85xx_PMUXCR_QE0 0x00008000
#define MPC85xx_PMUXCR_QE3 0x00001000
#define MPC85xx_PMUXCR_QE9 0x00000040
#define MPC85xx_PMUXCR_QE12 0x00000008
static __be32 __iomem *pmuxcr;
np = of_find_node_by_name(NULL, "global-utilities");
if (np) {
pmuxcr = of_iomap(np, 0) + MPC85xx_PMUXCR_OFFSET;
if (!pmuxcr)
printk(KERN_EMERG "Error: Alternate function"
" signal multiplex control register not"
" mapped!\n");
else
/* P1021 has pins muxed for QE and other functions. To
* enable QE UEC mode, we need to set bit QE0 for UCC1
* in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
* and QE12 for QE MII management singals in PMUXCR
* register.
*/
setbits32(pmuxcr, MPC85xx_PMUXCR_QE0 |
MPC85xx_PMUXCR_QE3 |
MPC85xx_PMUXCR_QE9 |
MPC85xx_PMUXCR_QE12);
of_node_put(np);
}
}
#endif /* CONFIG_QUICC_ENGINE */ #endif /* CONFIG_QUICC_ENGINE */
#ifdef CONFIG_SWIOTLB #ifdef CONFIG_SWIOTLB
...@@ -330,6 +378,16 @@ static struct of_device_id mpc85xx_ids[] = { ...@@ -330,6 +378,16 @@ static struct of_device_id mpc85xx_ids[] = {
{}, {},
}; };
static struct of_device_id p1021_ids[] = {
{ .type = "soc", },
{ .compatible = "soc", },
{ .compatible = "simple-bus", },
{ .type = "qe", },
{ .compatible = "fsl,qe", },
{ .compatible = "gianfar", },
{},
};
static int __init mpc85xx_publish_devices(void) static int __init mpc85xx_publish_devices(void)
{ {
if (machine_is(mpc8568_mds)) if (machine_is(mpc8568_mds))
...@@ -342,11 +400,22 @@ static int __init mpc85xx_publish_devices(void) ...@@ -342,11 +400,22 @@ static int __init mpc85xx_publish_devices(void)
return 0; return 0;
} }
static int __init p1021_publish_devices(void)
{
/* Publish the QE devices */
of_platform_bus_probe(NULL, p1021_ids, NULL);
return 0;
}
machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices); machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices); machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices);
machine_device_initcall(p1021_mds, p1021_publish_devices);
machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier); machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier);
machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier); machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier);
machine_arch_initcall(p1021_mds, swiotlb_setup_bus_notifier);
static void __init mpc85xx_mds_pic_init(void) static void __init mpc85xx_mds_pic_init(void)
{ {
...@@ -366,7 +435,7 @@ static void __init mpc85xx_mds_pic_init(void) ...@@ -366,7 +435,7 @@ static void __init mpc85xx_mds_pic_init(void)
mpic = mpic_alloc(np, r.start, mpic = mpic_alloc(np, r.start,
MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN |
MPIC_BROKEN_FRR_NIRQS, MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
0, 256, " OpenPIC "); 0, 256, " OpenPIC ");
BUG_ON(mpic == NULL); BUG_ON(mpic == NULL);
of_node_put(np); of_node_put(np);
...@@ -380,6 +449,10 @@ static void __init mpc85xx_mds_pic_init(void) ...@@ -380,6 +449,10 @@ static void __init mpc85xx_mds_pic_init(void)
if (!np) if (!np)
return; return;
} }
if (machine_is(p1021_mds))
qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
qe_ic_cascade_high_mpic);
else
qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL); qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL);
of_node_put(np); of_node_put(np);
#endif /* CONFIG_QUICC_ENGINE */ #endif /* CONFIG_QUICC_ENGINE */
...@@ -426,3 +499,26 @@ define_machine(mpc8569_mds) { ...@@ -426,3 +499,26 @@ define_machine(mpc8569_mds) {
.pcibios_fixup_bus = fsl_pcibios_fixup_bus, .pcibios_fixup_bus = fsl_pcibios_fixup_bus,
#endif #endif
}; };
static int __init p1021_mds_probe(void)
{
unsigned long root = of_get_flat_dt_root();
return of_flat_dt_is_compatible(root, "fsl,P1021MDS");
}
define_machine(p1021_mds) {
.name = "P1021 MDS",
.probe = p1021_mds_probe,
.setup_arch = mpc85xx_mds_setup_arch,
.init_IRQ = mpc85xx_mds_pic_init,
.get_irq = mpic_get_irq,
.restart = fsl_rstcr_restart,
.calibrate_decr = generic_calibrate_decr,
.progress = udbg_progress,
#ifdef CONFIG_PCI
.pcibios_fixup_bus = fsl_pcibios_fixup_bus,
#endif
};
/* /*
* Copyright (C) 2007-2008 Freescale Semiconductor, Inc. All rights reserved. * Copyright (C) 2007-2010 Freescale Semiconductor, Inc.
* *
* Author: Tony Li <tony.li@freescale.com> * Author: Tony Li <tony.li@freescale.com>
* Jason Jin <Jason.jin@freescale.com> * Jason Jin <Jason.jin@freescale.com>
...@@ -22,14 +22,20 @@ ...@@ -22,14 +22,20 @@
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/hw_irq.h> #include <asm/hw_irq.h>
#include <asm/ppc-pci.h> #include <asm/ppc-pci.h>
#include <asm/mpic.h>
#include "fsl_msi.h" #include "fsl_msi.h"
LIST_HEAD(msi_head);
struct fsl_msi_feature { struct fsl_msi_feature {
u32 fsl_pic_ip; u32 fsl_pic_ip;
u32 msiir_offset; u32 msiir_offset;
}; };
static struct fsl_msi *fsl_msi; struct fsl_msi_cascade_data {
struct fsl_msi *msi_data;
int index;
};
static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg) static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg)
{ {
...@@ -54,10 +60,12 @@ static struct irq_chip fsl_msi_chip = { ...@@ -54,10 +60,12 @@ static struct irq_chip fsl_msi_chip = {
static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, static int fsl_msi_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hw) irq_hw_number_t hw)
{ {
struct fsl_msi *msi_data = h->host_data;
struct irq_chip *chip = &fsl_msi_chip; struct irq_chip *chip = &fsl_msi_chip;
irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING; irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
set_irq_chip_data(virq, msi_data);
set_irq_chip_and_handler(virq, chip, handle_edge_irq); set_irq_chip_and_handler(virq, chip, handle_edge_irq);
return 0; return 0;
...@@ -96,11 +104,12 @@ static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) ...@@ -96,11 +104,12 @@ static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
static void fsl_teardown_msi_irqs(struct pci_dev *pdev) static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
{ {
struct msi_desc *entry; struct msi_desc *entry;
struct fsl_msi *msi_data = fsl_msi; struct fsl_msi *msi_data;
list_for_each_entry(entry, &pdev->msi_list, list) { list_for_each_entry(entry, &pdev->msi_list, list) {
if (entry->irq == NO_IRQ) if (entry->irq == NO_IRQ)
continue; continue;
msi_data = get_irq_data(entry->irq);
set_irq_msi(entry->irq, NULL); set_irq_msi(entry->irq, NULL);
msi_bitmap_free_hwirqs(&msi_data->bitmap, msi_bitmap_free_hwirqs(&msi_data->bitmap,
virq_to_hw(entry->irq), 1); virq_to_hw(entry->irq), 1);
...@@ -111,9 +120,10 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev) ...@@ -111,9 +120,10 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
} }
static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
struct msi_msg *msg) struct msi_msg *msg,
struct fsl_msi *fsl_msi_data)
{ {
struct fsl_msi *msi_data = fsl_msi; struct fsl_msi *msi_data = fsl_msi_data;
struct pci_controller *hose = pci_bus_to_host(pdev->bus); struct pci_controller *hose = pci_bus_to_host(pdev->bus);
u32 base = 0; u32 base = 0;
...@@ -130,14 +140,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, ...@@ -130,14 +140,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
{ {
int rc, hwirq; int rc, hwirq = -ENOMEM;
unsigned int virq; unsigned int virq;
struct msi_desc *entry; struct msi_desc *entry;
struct msi_msg msg; struct msi_msg msg;
struct fsl_msi *msi_data = fsl_msi; struct fsl_msi *msi_data;
list_for_each_entry(entry, &pdev->msi_list, list) { list_for_each_entry(entry, &pdev->msi_list, list) {
list_for_each_entry(msi_data, &msi_head, list) {
hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
if (hwirq >= 0)
break;
}
if (hwirq < 0) { if (hwirq < 0) {
rc = hwirq; rc = hwirq;
pr_debug("%s: fail allocating msi interrupt\n", pr_debug("%s: fail allocating msi interrupt\n",
...@@ -154,25 +169,31 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) ...@@ -154,25 +169,31 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
rc = -ENOSPC; rc = -ENOSPC;
goto out_free; goto out_free;
} }
set_irq_data(virq, msi_data);
set_irq_msi(virq, entry); set_irq_msi(virq, entry);
fsl_compose_msi_msg(pdev, hwirq, &msg); fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data);
write_msi_msg(virq, &msg); write_msi_msg(virq, &msg);
} }
return 0; return 0;
out_free: out_free:
/* free by the caller of this function */
return rc; return rc;
} }
static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
{ {
unsigned int cascade_irq; unsigned int cascade_irq;
struct fsl_msi *msi_data = fsl_msi; struct fsl_msi *msi_data;
int msir_index = -1; int msir_index = -1;
u32 msir_value = 0; u32 msir_value = 0;
u32 intr_index; u32 intr_index;
u32 have_shift = 0; u32 have_shift = 0;
struct fsl_msi_cascade_data *cascade_data;
cascade_data = (struct fsl_msi_cascade_data *)get_irq_data(irq);
msi_data = cascade_data->msi_data;
raw_spin_lock(&desc->lock); raw_spin_lock(&desc->lock);
if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) { if ((msi_data->feature & FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) {
...@@ -187,13 +208,13 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) ...@@ -187,13 +208,13 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
if (unlikely(desc->status & IRQ_INPROGRESS)) if (unlikely(desc->status & IRQ_INPROGRESS))
goto unlock; goto unlock;
msir_index = (int)desc->handler_data; msir_index = cascade_data->index;
if (msir_index >= NR_MSI_REG) if (msir_index >= NR_MSI_REG)
cascade_irq = NO_IRQ; cascade_irq = NO_IRQ;
desc->status |= IRQ_INPROGRESS; desc->status |= IRQ_INPROGRESS;
switch (fsl_msi->feature & FSL_PIC_IP_MASK) { switch (msi_data->feature & FSL_PIC_IP_MASK) {
case FSL_PIC_IP_MPIC: case FSL_PIC_IP_MPIC:
msir_value = fsl_msi_read(msi_data->msi_regs, msir_value = fsl_msi_read(msi_data->msi_regs,
msir_index * 0x10); msir_index * 0x10);
...@@ -229,6 +250,30 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc) ...@@ -229,6 +250,30 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
raw_spin_unlock(&desc->lock); raw_spin_unlock(&desc->lock);
} }
static int fsl_of_msi_remove(struct of_device *ofdev)
{
struct fsl_msi *msi = ofdev->dev.platform_data;
int virq, i;
struct fsl_msi_cascade_data *cascade_data;
if (msi->list.prev != NULL)
list_del(&msi->list);
for (i = 0; i < NR_MSI_REG; i++) {
virq = msi->msi_virqs[i];
if (virq != NO_IRQ) {
cascade_data = get_irq_data(virq);
kfree(cascade_data);
irq_dispose_mapping(virq);
}
}
if (msi->bitmap.bitmap)
msi_bitmap_free(&msi->bitmap);
iounmap(msi->msi_regs);
kfree(msi);
return 0;
}
static int __devinit fsl_of_msi_probe(struct of_device *dev, static int __devinit fsl_of_msi_probe(struct of_device *dev,
const struct of_device_id *match) const struct of_device_id *match)
{ {
...@@ -239,15 +284,18 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev, ...@@ -239,15 +284,18 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
int virt_msir; int virt_msir;
const u32 *p; const u32 *p;
struct fsl_msi_feature *features = match->data; struct fsl_msi_feature *features = match->data;
struct fsl_msi_cascade_data *cascade_data = NULL;
int len;
u32 offset;
printk(KERN_DEBUG "Setting up Freescale MSI support\n"); printk(KERN_DEBUG "Setting up Freescale MSI support\n");
msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL); msi = kzalloc(sizeof(struct fsl_msi), GFP_KERNEL);
if (!msi) { if (!msi) {
dev_err(&dev->dev, "No memory for MSI structure\n"); dev_err(&dev->dev, "No memory for MSI structure\n");
err = -ENOMEM; return -ENOMEM;
goto error_out;
} }
dev->dev.platform_data = msi;
msi->irqhost = irq_alloc_host(dev->dev.of_node, IRQ_HOST_MAP_LINEAR, msi->irqhost = irq_alloc_host(dev->dev.of_node, IRQ_HOST_MAP_LINEAR,
NR_MSI_IRQS, &fsl_msi_host_ops, 0); NR_MSI_IRQS, &fsl_msi_host_ops, 0);
...@@ -298,27 +346,47 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev, ...@@ -298,27 +346,47 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
err = -EINVAL; err = -EINVAL;
goto error_out; goto error_out;
} }
offset = 0;
p = of_get_property(dev->node, "msi-available-ranges", &len);
if (p)
offset = *p / IRQS_PER_MSI_REG;
count /= sizeof(u32); count /= sizeof(u32);
for (i = 0; i < count / 2; i++) { for (i = 0; i < min(count / 2, NR_MSI_REG); i++) {
if (i > NR_MSI_REG)
break;
virt_msir = irq_of_parse_and_map(dev->dev.of_node, i); virt_msir = irq_of_parse_and_map(dev->dev.of_node, i);
if (virt_msir != NO_IRQ) { if (virt_msir != NO_IRQ) {
set_irq_data(virt_msir, (void *)i); cascade_data = kzalloc(
sizeof(struct fsl_msi_cascade_data),
GFP_KERNEL);
if (!cascade_data) {
dev_err(&dev->dev,
"No memory for MSI cascade data\n");
err = -ENOMEM;
goto error_out;
}
msi->msi_virqs[i] = virt_msir;
cascade_data->index = i + offset;
cascade_data->msi_data = msi;
set_irq_data(virt_msir, (void *)cascade_data);
set_irq_chained_handler(virt_msir, fsl_msi_cascade); set_irq_chained_handler(virt_msir, fsl_msi_cascade);
} }
} }
fsl_msi = msi; list_add_tail(&msi->list, &msi_head);
WARN_ON(ppc_md.setup_msi_irqs); /* The multiple setting ppc_md.setup_msi_irqs will not harm things */
if (!ppc_md.setup_msi_irqs) {
ppc_md.setup_msi_irqs = fsl_setup_msi_irqs; ppc_md.setup_msi_irqs = fsl_setup_msi_irqs;
ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs; ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs;
ppc_md.msi_check_device = fsl_msi_check_device; ppc_md.msi_check_device = fsl_msi_check_device;
} else if (ppc_md.setup_msi_irqs != fsl_setup_msi_irqs) {
dev_err(&dev->dev, "Different MSI driver already installed!\n");
err = -ENODEV;
goto error_out;
}
return 0; return 0;
error_out: error_out:
kfree(msi); fsl_of_msi_remove(dev);
return err; return err;
} }
...@@ -351,6 +419,7 @@ static struct of_platform_driver fsl_of_msi_driver = { ...@@ -351,6 +419,7 @@ static struct of_platform_driver fsl_of_msi_driver = {
.of_match_table = fsl_of_msi_ids, .of_match_table = fsl_of_msi_ids,
}, },
.probe = fsl_of_msi_probe, .probe = fsl_of_msi_probe,
.remove = fsl_of_msi_remove,
}; };
static __init int fsl_of_msi_init(void) static __init int fsl_of_msi_init(void)
......
...@@ -32,8 +32,11 @@ struct fsl_msi { ...@@ -32,8 +32,11 @@ struct fsl_msi {
u32 msi_addr_hi; u32 msi_addr_hi;
void __iomem *msi_regs; void __iomem *msi_regs;
u32 feature; u32 feature;
int msi_virqs[NR_MSI_REG];
struct msi_bitmap bitmap; struct msi_bitmap bitmap;
struct list_head list; /* support multiple MSI banks */
}; };
#endif /* _POWERPC_SYSDEV_FSL_MSI_H */ #endif /* _POWERPC_SYSDEV_FSL_MSI_H */
......
...@@ -974,6 +974,123 @@ static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata = ...@@ -974,6 +974,123 @@ static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =
.setup_utl = ppc460ex_pciex_init_utl, .setup_utl = ppc460ex_pciex_init_utl,
}; };
static int __init ppc460sx_pciex_core_init(struct device_node *np)
{
/* HSS drive amplitude */
mtdcri(SDR0, PESDR0_460SX_HSSL0DAMP, 0xB9843211);
mtdcri(SDR0, PESDR0_460SX_HSSL1DAMP, 0xB9843211);
mtdcri(SDR0, PESDR0_460SX_HSSL2DAMP, 0xB9843211);
mtdcri(SDR0, PESDR0_460SX_HSSL3DAMP, 0xB9843211);
mtdcri(SDR0, PESDR0_460SX_HSSL4DAMP, 0xB9843211);
mtdcri(SDR0, PESDR0_460SX_HSSL5DAMP, 0xB9843211);
mtdcri(SDR0, PESDR0_460SX_HSSL6DAMP, 0xB9843211);
mtdcri(SDR0, PESDR0_460SX_HSSL7DAMP, 0xB9843211);
mtdcri(SDR0, PESDR1_460SX_HSSL0DAMP, 0xB9843211);
mtdcri(SDR0, PESDR1_460SX_HSSL1DAMP, 0xB9843211);
mtdcri(SDR0, PESDR1_460SX_HSSL2DAMP, 0xB9843211);
mtdcri(SDR0, PESDR1_460SX_HSSL3DAMP, 0xB9843211);
mtdcri(SDR0, PESDR2_460SX_HSSL0DAMP, 0xB9843211);
mtdcri(SDR0, PESDR2_460SX_HSSL1DAMP, 0xB9843211);
mtdcri(SDR0, PESDR2_460SX_HSSL2DAMP, 0xB9843211);
mtdcri(SDR0, PESDR2_460SX_HSSL3DAMP, 0xB9843211);
/* HSS TX pre-emphasis */
mtdcri(SDR0, PESDR0_460SX_HSSL0COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR0_460SX_HSSL1COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR0_460SX_HSSL2COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR0_460SX_HSSL3COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR0_460SX_HSSL4COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR0_460SX_HSSL5COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR0_460SX_HSSL6COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR0_460SX_HSSL7COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR1_460SX_HSSL0COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR1_460SX_HSSL1COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR1_460SX_HSSL2COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR1_460SX_HSSL3COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR2_460SX_HSSL0COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR2_460SX_HSSL1COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR2_460SX_HSSL2COEFA, 0xDCB98987);
mtdcri(SDR0, PESDR2_460SX_HSSL3COEFA, 0xDCB98987);
/* HSS TX calibration control */
mtdcri(SDR0, PESDR0_460SX_HSSL1CALDRV, 0x22222222);
mtdcri(SDR0, PESDR1_460SX_HSSL1CALDRV, 0x22220000);
mtdcri(SDR0, PESDR2_460SX_HSSL1CALDRV, 0x22220000);
/* HSS TX slew control */
mtdcri(SDR0, PESDR0_460SX_HSSSLEW, 0xFFFFFFFF);
mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000);
mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000);
udelay(100);
/* De-assert PLLRESET */
dcri_clrset(SDR0, PESDR0_PLLLCT2, 0x00000100, 0);
/* Reset DL, UTL, GPL before configuration */
mtdcri(SDR0, PESDR0_460SX_RCSSET,
PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
mtdcri(SDR0, PESDR1_460SX_RCSSET,
PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
mtdcri(SDR0, PESDR2_460SX_RCSSET,
PESDRx_RCSSET_RSTDL | PESDRx_RCSSET_RSTGU);
udelay(100);
/*
* If bifurcation is not enabled, u-boot would have disabled the
* third PCIe port
*/
if (((mfdcri(SDR0, PESDR1_460SX_HSSCTLSET) & 0x00000001) ==
0x00000001)) {
printk(KERN_INFO "PCI: PCIE bifurcation setup successfully.\n");
printk(KERN_INFO "PCI: Total 3 PCIE ports are present\n");
return 3;
}
printk(KERN_INFO "PCI: Total 2 PCIE ports are present\n");
return 2;
}
static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
{
if (port->endpoint)
dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
0x01000000, 0);
else
dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
0, 0x01000000);
/*Gen-1*/
mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000);
dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL),
PESDRx_RCSSET_RSTPYN);
port->has_ibpre = 1;
return 0;
}
static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)
{
/* Max 128 Bytes */
out_be32 (port->utl_base + PEUTL_PBBSZ, 0x00000000);
return 0;
}
static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
.core_init = ppc460sx_pciex_core_init,
.port_init_hw = ppc460sx_pciex_init_port_hw,
.setup_utl = ppc460sx_pciex_init_utl,
};
#endif /* CONFIG_44x */ #endif /* CONFIG_44x */
#ifdef CONFIG_40x #ifdef CONFIG_40x
...@@ -1089,6 +1206,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np) ...@@ -1089,6 +1206,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
} }
if (of_device_is_compatible(np, "ibm,plb-pciex-460ex")) if (of_device_is_compatible(np, "ibm,plb-pciex-460ex"))
ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops; ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops;
if (of_device_is_compatible(np, "ibm,plb-pciex-460sx"))
ppc4xx_pciex_hwops = &ppc460sx_pcie_hwops;
#endif /* CONFIG_44x */ #endif /* CONFIG_44x */
#ifdef CONFIG_40x #ifdef CONFIG_40x
if (of_device_is_compatible(np, "ibm,plb-pciex-405ex")) if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
......
...@@ -323,6 +323,64 @@ ...@@ -323,6 +323,64 @@
#define PESDR0_460EX_IHS1 0x036C #define PESDR0_460EX_IHS1 0x036C
#define PESDR0_460EX_IHS2 0x036D #define PESDR0_460EX_IHS2 0x036D
/*
* 460SX addtional DCRs
*/
#define PESDRn_460SX_RCEI 0x02
#define PESDR0_460SX_HSSL0DAMP 0x320
#define PESDR0_460SX_HSSL1DAMP 0x321
#define PESDR0_460SX_HSSL2DAMP 0x322
#define PESDR0_460SX_HSSL3DAMP 0x323
#define PESDR0_460SX_HSSL4DAMP 0x324
#define PESDR0_460SX_HSSL5DAMP 0x325
#define PESDR0_460SX_HSSL6DAMP 0x326
#define PESDR0_460SX_HSSL7DAMP 0x327
#define PESDR1_460SX_HSSL0DAMP 0x354
#define PESDR1_460SX_HSSL1DAMP 0x355
#define PESDR1_460SX_HSSL2DAMP 0x356
#define PESDR1_460SX_HSSL3DAMP 0x357
#define PESDR2_460SX_HSSL0DAMP 0x384
#define PESDR2_460SX_HSSL1DAMP 0x385
#define PESDR2_460SX_HSSL2DAMP 0x386
#define PESDR2_460SX_HSSL3DAMP 0x387
#define PESDR0_460SX_HSSL0COEFA 0x328
#define PESDR0_460SX_HSSL1COEFA 0x329
#define PESDR0_460SX_HSSL2COEFA 0x32A
#define PESDR0_460SX_HSSL3COEFA 0x32B
#define PESDR0_460SX_HSSL4COEFA 0x32C
#define PESDR0_460SX_HSSL5COEFA 0x32D
#define PESDR0_460SX_HSSL6COEFA 0x32E
#define PESDR0_460SX_HSSL7COEFA 0x32F
#define PESDR1_460SX_HSSL0COEFA 0x358
#define PESDR1_460SX_HSSL1COEFA 0x359
#define PESDR1_460SX_HSSL2COEFA 0x35A
#define PESDR1_460SX_HSSL3COEFA 0x35B
#define PESDR2_460SX_HSSL0COEFA 0x388
#define PESDR2_460SX_HSSL1COEFA 0x389
#define PESDR2_460SX_HSSL2COEFA 0x38A
#define PESDR2_460SX_HSSL3COEFA 0x38B
#define PESDR0_460SX_HSSL1CALDRV 0x339
#define PESDR1_460SX_HSSL1CALDRV 0x361
#define PESDR2_460SX_HSSL1CALDRV 0x391
#define PESDR0_460SX_HSSSLEW 0x338
#define PESDR1_460SX_HSSSLEW 0x360
#define PESDR2_460SX_HSSSLEW 0x390
#define PESDR0_460SX_HSSCTLSET 0x31E
#define PESDR1_460SX_HSSCTLSET 0x352
#define PESDR2_460SX_HSSCTLSET 0x382
#define PESDR0_460SX_RCSSET 0x304
#define PESDR1_460SX_RCSSET 0x344
#define PESDR2_460SX_RCSSET 0x374
/* /*
* Of the above, some are common offsets from the base * Of the above, some are common offsets from the base
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment