[POWERPC] cell: Support pinhole-reset on IBM cell blades

The Cell Broadband Engine has a method of injecting a
system-reset-exception from an external source into the
operating system, which should trigger the regular behaviour
of entering xmon or kdump.

Unfortunately, the exception handler cannot distinguish it from
other interrupt causes by the SRR1 register, which gets used
for this on Power 6 and others.

IBM Blade servers that want to support triggering the
system reset exception using a pinhole button in the front
panel therefore use an extra register to determine the
reset cause.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>

--
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by

Arnd Bergmann and committed by
Paul Mackerras
3addf55c fa7f374b

+32 -2
+6 -2
arch/powerpc/platforms/cell/cbe_regs.h
··· 113 u64 checkstop_fir; /* 0x0c00 */ 114 u64 recoverable_fir; /* 0x0c08 */ 115 u64 spec_att_mchk_fir; /* 0x0c10 */ 116 - u64 fir_mode_reg; /* 0x0c18 */ 117 u64 fir_enable_mask; /* 0x0c20 */ 118 119 - u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */ 120 }; 121 122 extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
··· 113 u64 checkstop_fir; /* 0x0c00 */ 114 u64 recoverable_fir; /* 0x0c08 */ 115 u64 spec_att_mchk_fir; /* 0x0c10 */ 116 + u32 fir_mode_reg; /* 0x0c18 */ 117 + u8 pad_0x0c1c_0x0c20 [4]; /* 0x0c1c */ 118 + #define CBE_PMD_FIR_MODE_M8 0x00800 119 u64 fir_enable_mask; /* 0x0c20 */ 120 121 + u8 pad_0x0c28_0x0ca8 [0x0ca8 - 0x0c28]; /* 0x0c28 */ 122 + u64 ras_esc_0; /* 0x0ca8 */ 123 + u8 pad_0x0cb0_0x1000 [0x1000 - 0x0cb0]; /* 0x0cb0 */ 124 }; 125 126 extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
+26
arch/powerpc/platforms/cell/pervasive.c
··· 38 #include "pervasive.h" 39 #include "cbe_regs.h" 40 41 static void cbe_power_save(void) 42 { 43 unsigned long ctrl, thread_switch_control; ··· 87 88 static int cbe_system_reset_exception(struct pt_regs *regs) 89 { 90 switch (regs->msr & SRR1_WAKEMASK) { 91 case SRR1_WAKEEE: 92 do_IRQ(regs); ··· 98 timer_interrupt(regs); 99 break; 100 case SRR1_WAKEMT: 101 break; 102 #ifdef CONFIG_CBE_RAS 103 case SRR1_WAKESYSERR: ··· 130 void __init cbe_pervasive_init(void) 131 { 132 int cpu; 133 if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) 134 return; 135 136 for_each_possible_cpu(cpu) { 137 struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu); ··· 144 /* Enable Pause(0) control bit */ 145 out_be64(&regs->pmcr, in_be64(&regs->pmcr) | 146 CBE_PMD_PAUSE_ZERO_CONTROL); 147 } 148 149 ppc_md.power_save = cbe_power_save;
··· 38 #include "pervasive.h" 39 #include "cbe_regs.h" 40 41 + static int sysreset_hack; 42 + 43 static void cbe_power_save(void) 44 { 45 unsigned long ctrl, thread_switch_control; ··· 85 86 static int cbe_system_reset_exception(struct pt_regs *regs) 87 { 88 + int cpu; 89 + struct cbe_pmd_regs __iomem *pmd; 90 + 91 switch (regs->msr & SRR1_WAKEMASK) { 92 case SRR1_WAKEEE: 93 do_IRQ(regs); ··· 93 timer_interrupt(regs); 94 break; 95 case SRR1_WAKEMT: 96 + /* 97 + * The BMC can inject user triggered system reset exceptions, 98 + * but cannot set the system reset reason in srr1, 99 + * so check an extra register here. 100 + */ 101 + if (sysreset_hack && (cpu = smp_processor_id()) == 0) { 102 + pmd = cbe_get_cpu_pmd_regs(cpu); 103 + if (in_be64(&pmd->ras_esc_0) & 0xffff) { 104 + out_be64(&pmd->ras_esc_0, 0); 105 + return 0; 106 + } 107 + } 108 break; 109 #ifdef CONFIG_CBE_RAS 110 case SRR1_WAKESYSERR: ··· 113 void __init cbe_pervasive_init(void) 114 { 115 int cpu; 116 + 117 if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) 118 return; 119 + 120 + sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0"); 121 122 for_each_possible_cpu(cpu) { 123 struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu); ··· 124 /* Enable Pause(0) control bit */ 125 out_be64(&regs->pmcr, in_be64(&regs->pmcr) | 126 CBE_PMD_PAUSE_ZERO_CONTROL); 127 + 128 + /* Enable JTAG system-reset hack */ 129 + if (sysreset_hack) 130 + out_be32(&regs->fir_mode_reg, 131 + in_be32(&regs->fir_mode_reg) | 132 + CBE_PMD_FIR_MODE_M8); 133 } 134 135 ppc_md.power_save = cbe_power_save;