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 41static void cbe_power_save(void) 42{ 43 unsigned long ctrl, thread_switch_control; 44 45 /* 46 * We need to hard disable interrupts, the local_irq_enable() done by 47 * our caller upon return will hard re-enable. 48 */ 49 hard_irq_disable(); 50 51 ctrl = mfspr(SPRN_CTRLF); 52 53 /* Enable DEC and EE interrupt request */ 54 thread_switch_control = mfspr(SPRN_TSC_CELL); 55 thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST; 56 57 switch (ctrl & CTRL_CT) { 58 case CTRL_CT0: 59 thread_switch_control |= TSC_CELL_DEC_ENABLE_0; 60 break; 61 case CTRL_CT1: 62 thread_switch_control |= TSC_CELL_DEC_ENABLE_1; 63 break; 64 default: 65 printk(KERN_WARNING "%s: unknown configuration\n", 66 __func__); 67 break; 68 } 69 mtspr(SPRN_TSC_CELL, thread_switch_control); 70 71 /* 72 * go into low thread priority, medium priority will be 73 * restored for us after wake-up. 74 */ 75 HMT_low(); 76 77 /* 78 * atomically disable thread execution and runlatch. 79 * External and Decrementer exceptions are still handled when the 80 * thread is disabled but now enter in cbe_system_reset_exception() 81 */ 82 ctrl &= ~(CTRL_RUNLATCH | CTRL_TE); 83 mtspr(SPRN_CTRLT, ctrl); 84} 85 86static int cbe_system_reset_exception(struct pt_regs *regs) 87{ 88 switch (regs->msr & SRR1_WAKEMASK) { 89 case SRR1_WAKEEE: 90 do_IRQ(regs); 91 break; 92 case SRR1_WAKEDEC: 93 timer_interrupt(regs); 94 break; 95 case SRR1_WAKEMT: 96 return cbe_sysreset_hack(); 97#ifdef CONFIG_CBE_RAS 98 case SRR1_WAKESYSERR: 99 cbe_system_error_exception(regs); 100 break; 101 case SRR1_WAKETHERM: 102 cbe_thermal_exception(regs); 103 break; 104#endif /* CONFIG_CBE_RAS */ 105 default: 106 /* do system reset */ 107 return 0; 108 } 109 /* everything handled */ 110 return 1; 111} 112 113void __init cbe_pervasive_init(void) 114{ 115 int cpu; 116 117 if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) 118 return; 119 120 for_each_possible_cpu(cpu) { 121 struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu); 122 if (!regs) 123 continue; 124 125 /* Enable Pause(0) control bit */ 126 out_be64(®s->pmcr, in_be64(®s->pmcr) | 127 CBE_PMD_PAUSE_ZERO_CONTROL); 128 } 129 130 ppc_md.power_save = cbe_power_save; 131 ppc_md.system_reset_exception = cbe_system_reset_exception; 132} 133