diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 00:55:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 00:55:47 -0400 |
commit | e86908614f2c7fec401827e5cefd7a6ea9407f85 (patch) | |
tree | fcb5d9e52422b37bdaf0e647126ebdfc1680f162 /arch/powerpc/platforms/pasemi | |
parent | 547307420931344a868275bd7ea7a30f117a15a9 (diff) | |
parent | 9b4b8feb962f4b3e74768b7205f1f8f6cce87238 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (408 commits)
[POWERPC] Add memchr() to the bootwrapper
[POWERPC] Implement logging of unhandled signals
[POWERPC] Add legacy serial support for OPB with flattened device tree
[POWERPC] Use 1TB segments
[POWERPC] XilinxFB: Allow fixed framebuffer base address
[POWERPC] XilinxFB: Add support for custom screen resolution
[POWERPC] XilinxFB: Use pdata to pass around framebuffer parameters
[POWERPC] PCI: Add 64-bit physical address support to setup_indirect_pci
[POWERPC] 4xx: Kilauea defconfig file
[POWERPC] 4xx: Kilauea DTS
[POWERPC] 4xx: Add AMCC Kilauea eval board support to platforms/40x
[POWERPC] 4xx: Add AMCC 405EX support to cputable.c
[POWERPC] Adjust TASK_SIZE on ppc32 systems to 3GB that are capable
[POWERPC] Use PAGE_OFFSET to tell if an address is user/kernel in SW TLB handlers
[POWERPC] 85xx: Enable FP emulation in MPC8560 ADS defconfig
[POWERPC] 85xx: Killed <asm/mpc85xx.h>
[POWERPC] 85xx: Add cpm nodes for 8541/8555 CDS
[POWERPC] 85xx: Convert mpc8560ads to the new CPM binding.
[POWERPC] mpc8272ads: Remove muram from the CPM reg property.
[POWERPC] Make clockevents work on PPC601 processors
...
Fixed up conflict in Documentation/powerpc/booting-without-of.txt manually.
Diffstat (limited to 'arch/powerpc/platforms/pasemi')
-rw-r--r-- | arch/powerpc/platforms/pasemi/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/gpio_mdio.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/idle.c | 8 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/iommu.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/pasemi.h | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/pci.c | 74 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/setup.c | 134 |
7 files changed, 203 insertions, 26 deletions
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig index e95261ef6f98..735e1536cbfc 100644 --- a/arch/powerpc/platforms/pasemi/Kconfig +++ b/arch/powerpc/platforms/pasemi/Kconfig | |||
@@ -5,6 +5,7 @@ config PPC_PASEMI | |||
5 | select MPIC | 5 | select MPIC |
6 | select PPC_UDBG_16550 | 6 | select PPC_UDBG_16550 |
7 | select PPC_NATIVE | 7 | select PPC_NATIVE |
8 | select MPIC_BROKEN_REGREAD | ||
8 | help | 9 | help |
9 | This option enables support for PA Semi's PWRficient line | 10 | This option enables support for PA Semi's PWRficient line |
10 | of SoC processors, including PA6T-1682M | 11 | of SoC processors, including PA6T-1682M |
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index c91a33593bb8..dae9f658122e 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[] = | |||
320 | 320 | ||
321 | static struct of_platform_driver gpio_mdio_driver = | 321 | static struct of_platform_driver gpio_mdio_driver = |
322 | { | 322 | { |
323 | .name = "gpio-mdio-bitbang", | ||
324 | .match_table = gpio_mdio_match, | 323 | .match_table = gpio_mdio_match, |
325 | .probe = gpio_mdio_probe, | 324 | .probe = gpio_mdio_probe, |
326 | .remove = gpio_mdio_remove, | 325 | .remove = gpio_mdio_remove, |
326 | .driver = { | ||
327 | .name = "gpio-mdio-bitbang", | ||
328 | }, | ||
327 | }; | 329 | }; |
328 | 330 | ||
329 | int gpio_mdio_init(void) | 331 | int gpio_mdio_init(void) |
diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c index 3c962d5757be..d8e1fcc78513 100644 --- a/arch/powerpc/platforms/pasemi/idle.c +++ b/arch/powerpc/platforms/pasemi/idle.c | |||
@@ -72,8 +72,11 @@ static int pasemi_system_reset_exception(struct pt_regs *regs) | |||
72 | return 1; | 72 | return 1; |
73 | } | 73 | } |
74 | 74 | ||
75 | void __init pasemi_idle_init(void) | 75 | static int __init pasemi_idle_init(void) |
76 | { | 76 | { |
77 | if (!machine_is(pasemi)) | ||
78 | return -ENODEV; | ||
79 | |||
77 | #ifndef CONFIG_PPC_PASEMI_CPUFREQ | 80 | #ifndef CONFIG_PPC_PASEMI_CPUFREQ |
78 | printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n"); | 81 | printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n"); |
79 | current_mode = 0; | 82 | current_mode = 0; |
@@ -82,7 +85,10 @@ void __init pasemi_idle_init(void) | |||
82 | ppc_md.system_reset_exception = pasemi_system_reset_exception; | 85 | ppc_md.system_reset_exception = pasemi_system_reset_exception; |
83 | ppc_md.power_save = modes[current_mode].entry; | 86 | ppc_md.power_save = modes[current_mode].entry; |
84 | printk(KERN_INFO "Using PA6T idle loop (%s)\n", modes[current_mode].name); | 87 | printk(KERN_INFO "Using PA6T idle loop (%s)\n", modes[current_mode].name); |
88 | |||
89 | return 0; | ||
85 | } | 90 | } |
91 | late_initcall(pasemi_idle_init); | ||
86 | 92 | ||
87 | static int __init idle_param(char *p) | 93 | static int __init idle_param(char *p) |
88 | { | 94 | { |
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index a1111b5c6cb4..9916a0f3e431 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c | |||
@@ -192,7 +192,7 @@ static void pci_dma_dev_setup_pasemi(struct pci_dev *dev) | |||
192 | static void pci_dma_bus_setup_null(struct pci_bus *b) { } | 192 | static void pci_dma_bus_setup_null(struct pci_bus *b) { } |
193 | static void pci_dma_dev_setup_null(struct pci_dev *d) { } | 193 | static void pci_dma_dev_setup_null(struct pci_dev *d) { } |
194 | 194 | ||
195 | int iob_init(struct device_node *dn) | 195 | int __init iob_init(struct device_node *dn) |
196 | { | 196 | { |
197 | unsigned long tmp; | 197 | unsigned long tmp; |
198 | u32 regword; | 198 | u32 regword; |
@@ -238,7 +238,7 @@ int iob_init(struct device_node *dn) | |||
238 | 238 | ||
239 | 239 | ||
240 | /* These are called very early. */ | 240 | /* These are called very early. */ |
241 | void iommu_init_early_pasemi(void) | 241 | void __init iommu_init_early_pasemi(void) |
242 | { | 242 | { |
243 | int iommu_off; | 243 | int iommu_off; |
244 | 244 | ||
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h index be8495497611..516acabb4e96 100644 --- a/arch/powerpc/platforms/pasemi/pasemi.h +++ b/arch/powerpc/platforms/pasemi/pasemi.h | |||
@@ -6,9 +6,9 @@ extern void pas_pci_init(void); | |||
6 | extern void __devinit pas_pci_irq_fixup(struct pci_dev *dev); | 6 | extern void __devinit pas_pci_irq_fixup(struct pci_dev *dev); |
7 | extern void __devinit pas_pci_dma_dev_setup(struct pci_dev *dev); | 7 | extern void __devinit pas_pci_dma_dev_setup(struct pci_dev *dev); |
8 | 8 | ||
9 | extern void __init alloc_iobmap_l2(void); | 9 | extern void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset); |
10 | 10 | ||
11 | extern void __init pasemi_idle_init(void); | 11 | extern void __init alloc_iobmap_l2(void); |
12 | 12 | ||
13 | /* Power savings modes, implemented in asm */ | 13 | /* Power savings modes, implemented in asm */ |
14 | extern void idle_spin(void); | 14 | extern void idle_spin(void); |
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index ab1f5f62bcd8..b6a0ec45c695 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c | |||
@@ -51,6 +51,61 @@ static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose, | |||
51 | return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset); | 51 | return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset); |
52 | } | 52 | } |
53 | 53 | ||
54 | static inline int is_root_port(int busno, int devfn) | ||
55 | { | ||
56 | return ((busno == 0) && (PCI_FUNC(devfn) < 4) && | ||
57 | ((PCI_SLOT(devfn) == 16) || (PCI_SLOT(devfn) == 17))); | ||
58 | } | ||
59 | |||
60 | static inline int is_5945_reg(int reg) | ||
61 | { | ||
62 | return (((reg >= 0x18) && (reg < 0x34)) || | ||
63 | ((reg >= 0x158) && (reg < 0x178))); | ||
64 | } | ||
65 | |||
66 | static int workaround_5945(struct pci_bus *bus, unsigned int devfn, | ||
67 | int offset, int len, u32 *val) | ||
68 | { | ||
69 | struct pci_controller *hose; | ||
70 | void volatile __iomem *addr, *dummy; | ||
71 | int byte; | ||
72 | u32 tmp; | ||
73 | |||
74 | if (!is_root_port(bus->number, devfn) || !is_5945_reg(offset)) | ||
75 | return 0; | ||
76 | |||
77 | hose = pci_bus_to_host(bus); | ||
78 | |||
79 | addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset & ~0x3); | ||
80 | byte = offset & 0x3; | ||
81 | |||
82 | /* Workaround bug 5945: write 0 to a dummy register before reading, | ||
83 | * and write back what we read. We must read/write the full 32-bit | ||
84 | * contents so we need to shift and mask by hand. | ||
85 | */ | ||
86 | dummy = pa_pxp_cfg_addr(hose, bus->number, devfn, 0x10); | ||
87 | out_le32(dummy, 0); | ||
88 | tmp = in_le32(addr); | ||
89 | out_le32(addr, tmp); | ||
90 | |||
91 | switch (len) { | ||
92 | case 1: | ||
93 | *val = (tmp >> (8*byte)) & 0xff; | ||
94 | break; | ||
95 | case 2: | ||
96 | if (byte == 0) | ||
97 | *val = tmp & 0xffff; | ||
98 | else | ||
99 | *val = (tmp >> 16) & 0xffff; | ||
100 | break; | ||
101 | default: | ||
102 | *val = tmp; | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | return 1; | ||
107 | } | ||
108 | |||
54 | static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, | 109 | static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, |
55 | int offset, int len, u32 *val) | 110 | int offset, int len, u32 *val) |
56 | { | 111 | { |
@@ -64,6 +119,9 @@ static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, | |||
64 | if (!pa_pxp_offset_valid(bus->number, devfn, offset)) | 119 | if (!pa_pxp_offset_valid(bus->number, devfn, offset)) |
65 | return PCIBIOS_BAD_REGISTER_NUMBER; | 120 | return PCIBIOS_BAD_REGISTER_NUMBER; |
66 | 121 | ||
122 | if (workaround_5945(bus, devfn, offset, len, val)) | ||
123 | return PCIBIOS_SUCCESSFUL; | ||
124 | |||
67 | addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); | 125 | addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); |
68 | 126 | ||
69 | /* | 127 | /* |
@@ -107,23 +165,20 @@ static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn, | |||
107 | switch (len) { | 165 | switch (len) { |
108 | case 1: | 166 | case 1: |
109 | out_8(addr, val); | 167 | out_8(addr, val); |
110 | (void) in_8(addr); | ||
111 | break; | 168 | break; |
112 | case 2: | 169 | case 2: |
113 | out_le16(addr, val); | 170 | out_le16(addr, val); |
114 | (void) in_le16(addr); | ||
115 | break; | 171 | break; |
116 | default: | 172 | default: |
117 | out_le32(addr, val); | 173 | out_le32(addr, val); |
118 | (void) in_le32(addr); | ||
119 | break; | 174 | break; |
120 | } | 175 | } |
121 | return PCIBIOS_SUCCESSFUL; | 176 | return PCIBIOS_SUCCESSFUL; |
122 | } | 177 | } |
123 | 178 | ||
124 | static struct pci_ops pa_pxp_ops = { | 179 | static struct pci_ops pa_pxp_ops = { |
125 | pa_pxp_read_config, | 180 | .read = pa_pxp_read_config, |
126 | pa_pxp_write_config, | 181 | .write = pa_pxp_write_config, |
127 | }; | 182 | }; |
128 | 183 | ||
129 | static void __init setup_pa_pxp(struct pci_controller *hose) | 184 | static void __init setup_pa_pxp(struct pci_controller *hose) |
@@ -178,3 +233,12 @@ void __init pas_pci_init(void) | |||
178 | /* Use the common resource allocation mechanism */ | 233 | /* Use the common resource allocation mechanism */ |
179 | pci_probe_only = 1; | 234 | pci_probe_only = 1; |
180 | } | 235 | } |
236 | |||
237 | void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset) | ||
238 | { | ||
239 | struct pci_controller *hose; | ||
240 | |||
241 | hose = pci_bus_to_host(dev->bus); | ||
242 | |||
243 | return (void __iomem *)pa_pxp_cfg_addr(hose, dev->bus->number, dev->devfn, offset); | ||
244 | } | ||
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index ffe6528048b5..5ddf40a66ae8 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c | |||
@@ -39,8 +39,21 @@ | |||
39 | 39 | ||
40 | #include "pasemi.h" | 40 | #include "pasemi.h" |
41 | 41 | ||
42 | /* SDC reset register, must be pre-mapped at reset time */ | ||
42 | static void __iomem *reset_reg; | 43 | static void __iomem *reset_reg; |
43 | 44 | ||
45 | /* Various error status registers, must be pre-mapped at MCE time */ | ||
46 | |||
47 | #define MAX_MCE_REGS 32 | ||
48 | struct mce_regs { | ||
49 | char *name; | ||
50 | void __iomem *addr; | ||
51 | }; | ||
52 | |||
53 | static struct mce_regs mce_regs[MAX_MCE_REGS]; | ||
54 | static int num_mce_regs; | ||
55 | |||
56 | |||
44 | static void pas_restart(char *cmd) | 57 | static void pas_restart(char *cmd) |
45 | { | 58 | { |
46 | printk("Restarting...\n"); | 59 | printk("Restarting...\n"); |
@@ -50,26 +63,30 @@ static void pas_restart(char *cmd) | |||
50 | 63 | ||
51 | #ifdef CONFIG_SMP | 64 | #ifdef CONFIG_SMP |
52 | static DEFINE_SPINLOCK(timebase_lock); | 65 | static DEFINE_SPINLOCK(timebase_lock); |
66 | static unsigned long timebase; | ||
53 | 67 | ||
54 | static void __devinit pas_give_timebase(void) | 68 | static void __devinit pas_give_timebase(void) |
55 | { | 69 | { |
56 | unsigned long tb; | ||
57 | |||
58 | spin_lock(&timebase_lock); | 70 | spin_lock(&timebase_lock); |
59 | mtspr(SPRN_TBCTL, TBCTL_FREEZE); | 71 | mtspr(SPRN_TBCTL, TBCTL_FREEZE); |
60 | tb = mftb(); | 72 | isync(); |
61 | mtspr(SPRN_TBCTL, TBCTL_UPDATE_LOWER | (tb & 0xffffffff)); | 73 | timebase = get_tb(); |
62 | mtspr(SPRN_TBCTL, TBCTL_UPDATE_UPPER | (tb >> 32)); | ||
63 | mtspr(SPRN_TBCTL, TBCTL_RESTART); | ||
64 | spin_unlock(&timebase_lock); | 74 | spin_unlock(&timebase_lock); |
65 | pr_debug("pas_give_timebase: cpu %d gave tb %lx\n", | 75 | |
66 | smp_processor_id(), tb); | 76 | while (timebase) |
77 | barrier(); | ||
78 | mtspr(SPRN_TBCTL, TBCTL_RESTART); | ||
67 | } | 79 | } |
68 | 80 | ||
69 | static void __devinit pas_take_timebase(void) | 81 | static void __devinit pas_take_timebase(void) |
70 | { | 82 | { |
71 | pr_debug("pas_take_timebase: cpu %d has tb %lx\n", | 83 | while (!timebase) |
72 | smp_processor_id(), mftb()); | 84 | smp_rmb(); |
85 | |||
86 | spin_lock(&timebase_lock); | ||
87 | set_tb(timebase >> 32, timebase & 0xffffffff); | ||
88 | timebase = 0; | ||
89 | spin_unlock(&timebase_lock); | ||
73 | } | 90 | } |
74 | 91 | ||
75 | struct smp_ops_t pas_smp_ops = { | 92 | struct smp_ops_t pas_smp_ops = { |
@@ -98,9 +115,60 @@ void __init pas_setup_arch(void) | |||
98 | /* Remap SDC register for doing reset */ | 115 | /* Remap SDC register for doing reset */ |
99 | /* XXXOJN This should maybe come out of the device tree */ | 116 | /* XXXOJN This should maybe come out of the device tree */ |
100 | reset_reg = ioremap(0xfc101100, 4); | 117 | reset_reg = ioremap(0xfc101100, 4); |
118 | } | ||
119 | |||
120 | static int __init pas_setup_mce_regs(void) | ||
121 | { | ||
122 | struct pci_dev *dev; | ||
123 | int reg; | ||
124 | |||
125 | if (!machine_is(pasemi)) | ||
126 | return -ENODEV; | ||
127 | |||
128 | /* Remap various SoC status registers for use by the MCE handler */ | ||
129 | |||
130 | reg = 0; | ||
131 | |||
132 | dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa00a, NULL); | ||
133 | while (dev && reg < MAX_MCE_REGS) { | ||
134 | mce_regs[reg].name = kasprintf(GFP_KERNEL, | ||
135 | "mc%d_mcdebug_errsta", reg); | ||
136 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x730); | ||
137 | dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa00a, dev); | ||
138 | reg++; | ||
139 | } | ||
140 | |||
141 | dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL); | ||
142 | if (dev && reg+4 < MAX_MCE_REGS) { | ||
143 | mce_regs[reg].name = "iobdbg_IntStatus1"; | ||
144 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x438); | ||
145 | reg++; | ||
146 | mce_regs[reg].name = "iobdbg_IOCTbusIntDbgReg"; | ||
147 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x454); | ||
148 | reg++; | ||
149 | mce_regs[reg].name = "iobiom_IntStatus"; | ||
150 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0xc10); | ||
151 | reg++; | ||
152 | mce_regs[reg].name = "iobiom_IntDbgReg"; | ||
153 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0xc1c); | ||
154 | reg++; | ||
155 | } | ||
156 | |||
157 | dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa009, NULL); | ||
158 | if (dev && reg+2 < MAX_MCE_REGS) { | ||
159 | mce_regs[reg].name = "l2csts_IntStatus"; | ||
160 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x200); | ||
161 | reg++; | ||
162 | mce_regs[reg].name = "l2csts_Cnt"; | ||
163 | mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x214); | ||
164 | reg++; | ||
165 | } | ||
101 | 166 | ||
102 | pasemi_idle_init(); | 167 | num_mce_regs = reg; |
168 | |||
169 | return 0; | ||
103 | } | 170 | } |
171 | device_initcall(pas_setup_mce_regs); | ||
104 | 172 | ||
105 | static __init void pas_init_IRQ(void) | 173 | static __init void pas_init_IRQ(void) |
106 | { | 174 | { |
@@ -162,25 +230,34 @@ static int pas_machine_check_handler(struct pt_regs *regs) | |||
162 | { | 230 | { |
163 | int cpu = smp_processor_id(); | 231 | int cpu = smp_processor_id(); |
164 | unsigned long srr0, srr1, dsisr; | 232 | unsigned long srr0, srr1, dsisr; |
233 | int dump_slb = 0; | ||
234 | int i; | ||
165 | 235 | ||
166 | srr0 = regs->nip; | 236 | srr0 = regs->nip; |
167 | srr1 = regs->msr; | 237 | srr1 = regs->msr; |
168 | dsisr = mfspr(SPRN_DSISR); | 238 | dsisr = mfspr(SPRN_DSISR); |
169 | printk(KERN_ERR "Machine Check on CPU %d\n", cpu); | 239 | printk(KERN_ERR "Machine Check on CPU %d\n", cpu); |
170 | printk(KERN_ERR "SRR0 0x%016lx SRR1 0x%016lx\n", srr0, srr1); | 240 | printk(KERN_ERR "SRR0 0x%016lx SRR1 0x%016lx\n", srr0, srr1); |
171 | printk(KERN_ERR "DSISR 0x%016lx DAR 0x%016lx\n", dsisr, regs->dar); | 241 | printk(KERN_ERR "DSISR 0x%016lx DAR 0x%016lx\n", dsisr, regs->dar); |
242 | printk(KERN_ERR "BER 0x%016lx MER 0x%016lx\n", mfspr(SPRN_PA6T_BER), | ||
243 | mfspr(SPRN_PA6T_MER)); | ||
244 | printk(KERN_ERR "IER 0x%016lx DER 0x%016lx\n", mfspr(SPRN_PA6T_IER), | ||
245 | mfspr(SPRN_PA6T_DER)); | ||
172 | printk(KERN_ERR "Cause:\n"); | 246 | printk(KERN_ERR "Cause:\n"); |
173 | 247 | ||
174 | if (srr1 & 0x200000) | 248 | if (srr1 & 0x200000) |
175 | printk(KERN_ERR "Signalled by SDC\n"); | 249 | printk(KERN_ERR "Signalled by SDC\n"); |
250 | |||
176 | if (srr1 & 0x100000) { | 251 | if (srr1 & 0x100000) { |
177 | printk(KERN_ERR "Load/Store detected error:\n"); | 252 | printk(KERN_ERR "Load/Store detected error:\n"); |
178 | if (dsisr & 0x8000) | 253 | if (dsisr & 0x8000) |
179 | printk(KERN_ERR "D-cache ECC double-bit error or bus error\n"); | 254 | printk(KERN_ERR "D-cache ECC double-bit error or bus error\n"); |
180 | if (dsisr & 0x4000) | 255 | if (dsisr & 0x4000) |
181 | printk(KERN_ERR "LSU snoop response error\n"); | 256 | printk(KERN_ERR "LSU snoop response error\n"); |
182 | if (dsisr & 0x2000) | 257 | if (dsisr & 0x2000) { |
183 | printk(KERN_ERR "MMU SLB multi-hit or invalid B field\n"); | 258 | printk(KERN_ERR "MMU SLB multi-hit or invalid B field\n"); |
259 | dump_slb = 1; | ||
260 | } | ||
184 | if (dsisr & 0x1000) | 261 | if (dsisr & 0x1000) |
185 | printk(KERN_ERR "Recoverable Duptags\n"); | 262 | printk(KERN_ERR "Recoverable Duptags\n"); |
186 | if (dsisr & 0x800) | 263 | if (dsisr & 0x800) |
@@ -188,13 +265,40 @@ static int pas_machine_check_handler(struct pt_regs *regs) | |||
188 | if (dsisr & 0x400) | 265 | if (dsisr & 0x400) |
189 | printk(KERN_ERR "TLB parity error count overflow\n"); | 266 | printk(KERN_ERR "TLB parity error count overflow\n"); |
190 | } | 267 | } |
268 | |||
191 | if (srr1 & 0x80000) | 269 | if (srr1 & 0x80000) |
192 | printk(KERN_ERR "Bus Error\n"); | 270 | printk(KERN_ERR "Bus Error\n"); |
193 | if (srr1 & 0x40000) | 271 | |
272 | if (srr1 & 0x40000) { | ||
194 | printk(KERN_ERR "I-side SLB multiple hit\n"); | 273 | printk(KERN_ERR "I-side SLB multiple hit\n"); |
274 | dump_slb = 1; | ||
275 | } | ||
276 | |||
195 | if (srr1 & 0x20000) | 277 | if (srr1 & 0x20000) |
196 | printk(KERN_ERR "I-cache parity error hit\n"); | 278 | printk(KERN_ERR "I-cache parity error hit\n"); |
197 | 279 | ||
280 | if (num_mce_regs == 0) | ||
281 | printk(KERN_ERR "No MCE registers mapped yet, can't dump\n"); | ||
282 | else | ||
283 | printk(KERN_ERR "SoC debug registers:\n"); | ||
284 | |||
285 | for (i = 0; i < num_mce_regs; i++) | ||
286 | printk(KERN_ERR "%s: 0x%08x\n", mce_regs[i].name, | ||
287 | in_le32(mce_regs[i].addr)); | ||
288 | |||
289 | if (dump_slb) { | ||
290 | unsigned long e, v; | ||
291 | int i; | ||
292 | |||
293 | printk(KERN_ERR "slb contents:\n"); | ||
294 | for (i = 0; i < SLB_NUM_ENTRIES; i++) { | ||
295 | asm volatile("slbmfee %0,%1" : "=r" (e) : "r" (i)); | ||
296 | asm volatile("slbmfev %0,%1" : "=r" (v) : "r" (i)); | ||
297 | printk(KERN_ERR "%02d %016lx %016lx\n", i, e, v); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | |||
198 | /* SRR1[62] is from MSR[62] if recoverable, so pass that back */ | 302 | /* SRR1[62] is from MSR[62] if recoverable, so pass that back */ |
199 | return !!(srr1 & 0x2); | 303 | return !!(srr1 & 0x2); |
200 | } | 304 | } |