1c902be71SArnd Bergmann /* 2c902be71SArnd Bergmann * CBE Pervasive Monitor and Debug 3c902be71SArnd Bergmann * 4c902be71SArnd Bergmann * (C) Copyright IBM Corporation 2005 5c902be71SArnd Bergmann * 6c902be71SArnd Bergmann * Authors: Maximino Aguilar (maguilar@us.ibm.com) 7c902be71SArnd Bergmann * Michael N. Day (mnday@us.ibm.com) 8c902be71SArnd Bergmann * 9c902be71SArnd Bergmann * This program is free software; you can redistribute it and/or modify 10c902be71SArnd Bergmann * it under the terms of the GNU General Public License as published by 11c902be71SArnd Bergmann * the Free Software Foundation; either version 2, or (at your option) 12c902be71SArnd Bergmann * any later version. 13c902be71SArnd Bergmann * 14c902be71SArnd Bergmann * This program is distributed in the hope that it will be useful, 15c902be71SArnd Bergmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 16c902be71SArnd Bergmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17c902be71SArnd Bergmann * GNU General Public License for more details. 18c902be71SArnd Bergmann * 19c902be71SArnd Bergmann * You should have received a copy of the GNU General Public License 20c902be71SArnd Bergmann * along with this program; if not, write to the Free Software 21c902be71SArnd Bergmann * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22c902be71SArnd Bergmann */ 23c902be71SArnd Bergmann 24c902be71SArnd Bergmann #undef DEBUG 25c902be71SArnd Bergmann 26c902be71SArnd Bergmann #include <linux/interrupt.h> 27c902be71SArnd Bergmann #include <linux/irq.h> 28c902be71SArnd Bergmann #include <linux/percpu.h> 29c902be71SArnd Bergmann #include <linux/types.h> 30c902be71SArnd Bergmann #include <linux/kallsyms.h> 31c902be71SArnd Bergmann 32c902be71SArnd Bergmann #include <asm/io.h> 33c902be71SArnd Bergmann #include <asm/machdep.h> 34c902be71SArnd Bergmann #include <asm/prom.h> 35c902be71SArnd Bergmann #include <asm/pgtable.h> 36c902be71SArnd Bergmann #include <asm/reg.h> 37eef686a0SBenjamin Herrenschmidt #include <asm/cell-regs.h> 38c902be71SArnd Bergmann 39c902be71SArnd Bergmann #include "pervasive.h" 40c902be71SArnd Bergmann 413addf55cSArnd Bergmann static int sysreset_hack; 423addf55cSArnd Bergmann 43302eca18Sarnd@arndb.de static void cbe_power_save(void) 44c902be71SArnd Bergmann { 45302eca18Sarnd@arndb.de unsigned long ctrl, thread_switch_control; 465850dd8fSBenjamin Herrenschmidt 475850dd8fSBenjamin Herrenschmidt /* 48e1fa2e13SBenjamin Herrenschmidt * We need to hard disable interrupts, the local_irq_enable() done by 49e1fa2e13SBenjamin Herrenschmidt * our caller upon return will hard re-enable. 505850dd8fSBenjamin Herrenschmidt */ 515850dd8fSBenjamin Herrenschmidt hard_irq_disable(); 525850dd8fSBenjamin Herrenschmidt 53302eca18Sarnd@arndb.de ctrl = mfspr(SPRN_CTRLF); 54c902be71SArnd Bergmann 55c902be71SArnd Bergmann /* Enable DEC and EE interrupt request */ 56c902be71SArnd Bergmann thread_switch_control = mfspr(SPRN_TSC_CELL); 57c902be71SArnd Bergmann thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST; 58c902be71SArnd Bergmann 59302eca18Sarnd@arndb.de switch (ctrl & CTRL_CT) { 60c902be71SArnd Bergmann case CTRL_CT0: 61c902be71SArnd Bergmann thread_switch_control |= TSC_CELL_DEC_ENABLE_0; 62c902be71SArnd Bergmann break; 63c902be71SArnd Bergmann case CTRL_CT1: 64c902be71SArnd Bergmann thread_switch_control |= TSC_CELL_DEC_ENABLE_1; 65c902be71SArnd Bergmann break; 66c902be71SArnd Bergmann default: 67c902be71SArnd Bergmann printk(KERN_WARNING "%s: unknown configuration\n", 68c902be71SArnd Bergmann __FUNCTION__); 69c902be71SArnd Bergmann break; 70c902be71SArnd Bergmann } 71c902be71SArnd Bergmann mtspr(SPRN_TSC_CELL, thread_switch_control); 72c902be71SArnd Bergmann 73302eca18Sarnd@arndb.de /* 74302eca18Sarnd@arndb.de * go into low thread priority, medium priority will be 75302eca18Sarnd@arndb.de * restored for us after wake-up. 76acf7d768SBenjamin Herrenschmidt */ 77c902be71SArnd Bergmann HMT_low(); 78c902be71SArnd Bergmann 79c902be71SArnd Bergmann /* 80302eca18Sarnd@arndb.de * atomically disable thread execution and runlatch. 81302eca18Sarnd@arndb.de * External and Decrementer exceptions are still handled when the 82302eca18Sarnd@arndb.de * thread is disabled but now enter in cbe_system_reset_exception() 83c902be71SArnd Bergmann */ 84c902be71SArnd Bergmann ctrl &= ~(CTRL_RUNLATCH | CTRL_TE); 85c902be71SArnd Bergmann mtspr(SPRN_CTRLT, ctrl); 86c902be71SArnd Bergmann } 87c902be71SArnd Bergmann 888fce10a3SArnd Bergmann static int cbe_system_reset_exception(struct pt_regs *regs) 89c902be71SArnd Bergmann { 903addf55cSArnd Bergmann int cpu; 913addf55cSArnd Bergmann struct cbe_pmd_regs __iomem *pmd; 923addf55cSArnd Bergmann 93c902be71SArnd Bergmann switch (regs->msr & SRR1_WAKEMASK) { 94c902be71SArnd Bergmann case SRR1_WAKEEE: 95c902be71SArnd Bergmann do_IRQ(regs); 96c902be71SArnd Bergmann break; 97c902be71SArnd Bergmann case SRR1_WAKEDEC: 98c902be71SArnd Bergmann timer_interrupt(regs); 99c902be71SArnd Bergmann break; 100c902be71SArnd Bergmann case SRR1_WAKEMT: 1013addf55cSArnd Bergmann /* 1023addf55cSArnd Bergmann * The BMC can inject user triggered system reset exceptions, 1033addf55cSArnd Bergmann * but cannot set the system reset reason in srr1, 1043addf55cSArnd Bergmann * so check an extra register here. 1053addf55cSArnd Bergmann */ 1063addf55cSArnd Bergmann if (sysreset_hack && (cpu = smp_processor_id()) == 0) { 1073addf55cSArnd Bergmann pmd = cbe_get_cpu_pmd_regs(cpu); 1083addf55cSArnd Bergmann if (in_be64(&pmd->ras_esc_0) & 0xffff) { 1093addf55cSArnd Bergmann out_be64(&pmd->ras_esc_0, 0); 1103addf55cSArnd Bergmann return 0; 1113addf55cSArnd Bergmann } 1123addf55cSArnd Bergmann } 113c902be71SArnd Bergmann break; 114acf7d768SBenjamin Herrenschmidt #ifdef CONFIG_CBE_RAS 115acf7d768SBenjamin Herrenschmidt case SRR1_WAKESYSERR: 116acf7d768SBenjamin Herrenschmidt cbe_system_error_exception(regs); 117acf7d768SBenjamin Herrenschmidt break; 118acf7d768SBenjamin Herrenschmidt case SRR1_WAKETHERM: 119acf7d768SBenjamin Herrenschmidt cbe_thermal_exception(regs); 120acf7d768SBenjamin Herrenschmidt break; 121acf7d768SBenjamin Herrenschmidt #endif /* CONFIG_CBE_RAS */ 122c902be71SArnd Bergmann default: 123c902be71SArnd Bergmann /* do system reset */ 124c902be71SArnd Bergmann return 0; 125c902be71SArnd Bergmann } 126c902be71SArnd Bergmann /* everything handled */ 127c902be71SArnd Bergmann return 1; 128c902be71SArnd Bergmann } 129c902be71SArnd Bergmann 130acf7d768SBenjamin Herrenschmidt void __init cbe_pervasive_init(void) 131c902be71SArnd Bergmann { 132302eca18Sarnd@arndb.de int cpu; 1333addf55cSArnd Bergmann 134c902be71SArnd Bergmann if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) 135c902be71SArnd Bergmann return; 136c902be71SArnd Bergmann 1373addf55cSArnd Bergmann sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0"); 1383addf55cSArnd Bergmann 139302eca18Sarnd@arndb.de for_each_possible_cpu(cpu) { 140302eca18Sarnd@arndb.de struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu); 141302eca18Sarnd@arndb.de if (!regs) 142302eca18Sarnd@arndb.de continue; 143302eca18Sarnd@arndb.de 144302eca18Sarnd@arndb.de /* Enable Pause(0) control bit */ 145302eca18Sarnd@arndb.de out_be64(®s->pmcr, in_be64(®s->pmcr) | 146302eca18Sarnd@arndb.de CBE_PMD_PAUSE_ZERO_CONTROL); 1473addf55cSArnd Bergmann 1483addf55cSArnd Bergmann /* Enable JTAG system-reset hack */ 1493addf55cSArnd Bergmann if (sysreset_hack) 1503addf55cSArnd Bergmann out_be32(®s->fir_mode_reg, 1513addf55cSArnd Bergmann in_be32(®s->fir_mode_reg) | 1523addf55cSArnd Bergmann CBE_PMD_FIR_MODE_M8); 153302eca18Sarnd@arndb.de } 154302eca18Sarnd@arndb.de 155302eca18Sarnd@arndb.de ppc_md.power_save = cbe_power_save; 156c902be71SArnd Bergmann ppc_md.system_reset_exception = cbe_system_reset_exception; 157c902be71SArnd Bergmann } 158