1de6cc651SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2c902be71SArnd Bergmann /* 3c902be71SArnd Bergmann * CBE Pervasive Monitor and Debug 4c902be71SArnd Bergmann * 5c902be71SArnd Bergmann * (C) Copyright IBM Corporation 2005 6c902be71SArnd Bergmann * 7c902be71SArnd Bergmann * Authors: Maximino Aguilar (maguilar@us.ibm.com) 8c902be71SArnd Bergmann * Michael N. Day (mnday@us.ibm.com) 9c902be71SArnd Bergmann */ 10c902be71SArnd Bergmann 11c902be71SArnd Bergmann #undef DEBUG 12c902be71SArnd Bergmann 13c902be71SArnd Bergmann #include <linux/interrupt.h> 14c902be71SArnd Bergmann #include <linux/irq.h> 15c902be71SArnd Bergmann #include <linux/percpu.h> 16c902be71SArnd Bergmann #include <linux/types.h> 17c902be71SArnd Bergmann #include <linux/kallsyms.h> 1865fddcfcSMike Rapoport #include <linux/pgtable.h> 19c902be71SArnd Bergmann 20c902be71SArnd Bergmann #include <asm/io.h> 21c902be71SArnd Bergmann #include <asm/machdep.h> 22c902be71SArnd Bergmann #include <asm/prom.h> 23c902be71SArnd Bergmann #include <asm/reg.h> 24eef686a0SBenjamin Herrenschmidt #include <asm/cell-regs.h> 25b92a226eSKevin Hao #include <asm/cpu_has_feature.h> 26c902be71SArnd Bergmann 27c902be71SArnd Bergmann #include "pervasive.h" 28dcdb4f12SNicholas Piggin #include "ras.h" 29c902be71SArnd Bergmann 30302eca18Sarnd@arndb.de static void cbe_power_save(void) 31c902be71SArnd Bergmann { 32302eca18Sarnd@arndb.de unsigned long ctrl, thread_switch_control; 335850dd8fSBenjamin Herrenschmidt 34be2cf20aSBenjamin Herrenschmidt /* Ensure our interrupt state is properly tracked */ 35be2cf20aSBenjamin Herrenschmidt if (!prep_irq_for_idle()) 36be2cf20aSBenjamin Herrenschmidt return; 375850dd8fSBenjamin Herrenschmidt 38302eca18Sarnd@arndb.de ctrl = mfspr(SPRN_CTRLF); 39c902be71SArnd Bergmann 40c902be71SArnd Bergmann /* Enable DEC and EE interrupt request */ 41c902be71SArnd Bergmann thread_switch_control = mfspr(SPRN_TSC_CELL); 42c902be71SArnd Bergmann thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST; 43c902be71SArnd Bergmann 44302eca18Sarnd@arndb.de switch (ctrl & CTRL_CT) { 45c902be71SArnd Bergmann case CTRL_CT0: 46c902be71SArnd Bergmann thread_switch_control |= TSC_CELL_DEC_ENABLE_0; 47c902be71SArnd Bergmann break; 48c902be71SArnd Bergmann case CTRL_CT1: 49c902be71SArnd Bergmann thread_switch_control |= TSC_CELL_DEC_ENABLE_1; 50c902be71SArnd Bergmann break; 51c902be71SArnd Bergmann default: 52c902be71SArnd Bergmann printk(KERN_WARNING "%s: unknown configuration\n", 53e48b1b45SHarvey Harrison __func__); 54c902be71SArnd Bergmann break; 55c902be71SArnd Bergmann } 56c902be71SArnd Bergmann mtspr(SPRN_TSC_CELL, thread_switch_control); 57c902be71SArnd Bergmann 58302eca18Sarnd@arndb.de /* 59302eca18Sarnd@arndb.de * go into low thread priority, medium priority will be 60302eca18Sarnd@arndb.de * restored for us after wake-up. 61acf7d768SBenjamin Herrenschmidt */ 62c902be71SArnd Bergmann HMT_low(); 63c902be71SArnd Bergmann 64c902be71SArnd Bergmann /* 65302eca18Sarnd@arndb.de * atomically disable thread execution and runlatch. 66302eca18Sarnd@arndb.de * External and Decrementer exceptions are still handled when the 67302eca18Sarnd@arndb.de * thread is disabled but now enter in cbe_system_reset_exception() 68c902be71SArnd Bergmann */ 69c902be71SArnd Bergmann ctrl &= ~(CTRL_RUNLATCH | CTRL_TE); 70c902be71SArnd Bergmann mtspr(SPRN_CTRLT, ctrl); 71be2cf20aSBenjamin Herrenschmidt 72be2cf20aSBenjamin Herrenschmidt /* Re-enable interrupts in MSR */ 73be2cf20aSBenjamin Herrenschmidt __hard_irq_enable(); 74c902be71SArnd Bergmann } 75c902be71SArnd Bergmann 768fce10a3SArnd Bergmann static int cbe_system_reset_exception(struct pt_regs *regs) 77c902be71SArnd Bergmann { 78c902be71SArnd Bergmann switch (regs->msr & SRR1_WAKEMASK) { 79c902be71SArnd Bergmann case SRR1_WAKEDEC: 806e83985bSNicholas Piggin set_dec(1); 81*e89257e2SAnders Roxell break; 826e83985bSNicholas Piggin case SRR1_WAKEEE: 836e83985bSNicholas Piggin /* 846e83985bSNicholas Piggin * Handle these when interrupts get re-enabled and we take 856e83985bSNicholas Piggin * them as regular exceptions. We are in an NMI context 866e83985bSNicholas Piggin * and can't handle these here. 876e83985bSNicholas Piggin */ 88c902be71SArnd Bergmann break; 89c902be71SArnd Bergmann case SRR1_WAKEMT: 9070694a8bSChristian Krafft return cbe_sysreset_hack(); 91acf7d768SBenjamin Herrenschmidt #ifdef CONFIG_CBE_RAS 92acf7d768SBenjamin Herrenschmidt case SRR1_WAKESYSERR: 93acf7d768SBenjamin Herrenschmidt cbe_system_error_exception(regs); 94acf7d768SBenjamin Herrenschmidt break; 95acf7d768SBenjamin Herrenschmidt case SRR1_WAKETHERM: 96acf7d768SBenjamin Herrenschmidt cbe_thermal_exception(regs); 97acf7d768SBenjamin Herrenschmidt break; 98acf7d768SBenjamin Herrenschmidt #endif /* CONFIG_CBE_RAS */ 99c902be71SArnd Bergmann default: 100c902be71SArnd Bergmann /* do system reset */ 101c902be71SArnd Bergmann return 0; 102c902be71SArnd Bergmann } 103c902be71SArnd Bergmann /* everything handled */ 104c902be71SArnd Bergmann return 1; 105c902be71SArnd Bergmann } 106c902be71SArnd Bergmann 107acf7d768SBenjamin Herrenschmidt void __init cbe_pervasive_init(void) 108c902be71SArnd Bergmann { 109302eca18Sarnd@arndb.de int cpu; 1103addf55cSArnd Bergmann 111c902be71SArnd Bergmann if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) 112c902be71SArnd Bergmann return; 113c902be71SArnd Bergmann 114302eca18Sarnd@arndb.de for_each_possible_cpu(cpu) { 115302eca18Sarnd@arndb.de struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu); 116302eca18Sarnd@arndb.de if (!regs) 117302eca18Sarnd@arndb.de continue; 118302eca18Sarnd@arndb.de 119302eca18Sarnd@arndb.de /* Enable Pause(0) control bit */ 120302eca18Sarnd@arndb.de out_be64(®s->pmcr, in_be64(®s->pmcr) | 121302eca18Sarnd@arndb.de CBE_PMD_PAUSE_ZERO_CONTROL); 122302eca18Sarnd@arndb.de } 123302eca18Sarnd@arndb.de 124302eca18Sarnd@arndb.de ppc_md.power_save = cbe_power_save; 125c902be71SArnd Bergmann ppc_md.system_reset_exception = cbe_system_reset_exception; 126c902be71SArnd Bergmann } 127