1 /* 2 * CBE Pervasive Monitor and Debug 3 * 4 * (C) Copyright IBM Corporation 2005 5 * 6 * Authors: Maximino Aguilar (maguilar@us.ibm.com) 7 * Michael N. Day (mnday@us.ibm.com) 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2, or (at your option) 12 * any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 */ 23 24 #undef DEBUG 25 26 #include <linux/interrupt.h> 27 #include <linux/irq.h> 28 #include <linux/percpu.h> 29 #include <linux/types.h> 30 #include <linux/kallsyms.h> 31 32 #include <asm/io.h> 33 #include <asm/machdep.h> 34 #include <asm/prom.h> 35 #include <asm/pgtable.h> 36 #include <asm/reg.h> 37 #include <asm/cell-regs.h> 38 39 #include "pervasive.h" 40 41 static int sysreset_hack; 42 43 static void cbe_power_save(void) 44 { 45 unsigned long ctrl, thread_switch_control; 46 47 /* 48 * We need to hard disable interrupts, the local_irq_enable() done by 49 * our caller upon return will hard re-enable. 50 */ 51 hard_irq_disable(); 52 53 ctrl = mfspr(SPRN_CTRLF); 54 55 /* Enable DEC and EE interrupt request */ 56 thread_switch_control = mfspr(SPRN_TSC_CELL); 57 thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST; 58 59 switch (ctrl & CTRL_CT) { 60 case CTRL_CT0: 61 thread_switch_control |= TSC_CELL_DEC_ENABLE_0; 62 break; 63 case CTRL_CT1: 64 thread_switch_control |= TSC_CELL_DEC_ENABLE_1; 65 break; 66 default: 67 printk(KERN_WARNING "%s: unknown configuration\n", 68 __FUNCTION__); 69 break; 70 } 71 mtspr(SPRN_TSC_CELL, thread_switch_control); 72 73 /* 74 * go into low thread priority, medium priority will be 75 * restored for us after wake-up. 76 */ 77 HMT_low(); 78 79 /* 80 * atomically disable thread execution and runlatch. 81 * External and Decrementer exceptions are still handled when the 82 * thread is disabled but now enter in cbe_system_reset_exception() 83 */ 84 ctrl &= ~(CTRL_RUNLATCH | CTRL_TE); 85 mtspr(SPRN_CTRLT, ctrl); 86 } 87 88 static int cbe_system_reset_exception(struct pt_regs *regs) 89 { 90 int cpu; 91 struct cbe_pmd_regs __iomem *pmd; 92 93 switch (regs->msr & SRR1_WAKEMASK) { 94 case SRR1_WAKEEE: 95 do_IRQ(regs); 96 break; 97 case SRR1_WAKEDEC: 98 timer_interrupt(regs); 99 break; 100 case SRR1_WAKEMT: 101 /* 102 * The BMC can inject user triggered system reset exceptions, 103 * but cannot set the system reset reason in srr1, 104 * so check an extra register here. 105 */ 106 if (sysreset_hack && (cpu = smp_processor_id()) == 0) { 107 pmd = cbe_get_cpu_pmd_regs(cpu); 108 if (in_be64(&pmd->ras_esc_0) & 0xffff) { 109 out_be64(&pmd->ras_esc_0, 0); 110 return 0; 111 } 112 } 113 break; 114 #ifdef CONFIG_CBE_RAS 115 case SRR1_WAKESYSERR: 116 cbe_system_error_exception(regs); 117 break; 118 case SRR1_WAKETHERM: 119 cbe_thermal_exception(regs); 120 break; 121 #endif /* CONFIG_CBE_RAS */ 122 default: 123 /* do system reset */ 124 return 0; 125 } 126 /* everything handled */ 127 return 1; 128 } 129 130 void __init cbe_pervasive_init(void) 131 { 132 int cpu; 133 134 if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) 135 return; 136 137 sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0"); 138 139 for_each_possible_cpu(cpu) { 140 struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu); 141 if (!regs) 142 continue; 143 144 /* Enable Pause(0) control bit */ 145 out_be64(®s->pmcr, in_be64(®s->pmcr) | 146 CBE_PMD_PAUSE_ZERO_CONTROL); 147 148 /* Enable JTAG system-reset hack */ 149 if (sysreset_hack) 150 out_be32(®s->fir_mode_reg, 151 in_be32(®s->fir_mode_reg) | 152 CBE_PMD_FIR_MODE_M8); 153 } 154 155 ppc_md.power_save = cbe_power_save; 156 ppc_md.system_reset_exception = cbe_system_reset_exception; 157 } 158