Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * CBE Pervasive Monitor and Debug
0004  *
0005  * (C) Copyright IBM Corporation 2005
0006  *
0007  * Authors: Maximino Aguilar (maguilar@us.ibm.com)
0008  *          Michael N. Day (mnday@us.ibm.com)
0009  */
0010 
0011 #undef DEBUG
0012 
0013 #include <linux/interrupt.h>
0014 #include <linux/irq.h>
0015 #include <linux/percpu.h>
0016 #include <linux/types.h>
0017 #include <linux/kallsyms.h>
0018 #include <linux/pgtable.h>
0019 
0020 #include <asm/io.h>
0021 #include <asm/machdep.h>
0022 #include <asm/reg.h>
0023 #include <asm/cell-regs.h>
0024 #include <asm/cpu_has_feature.h>
0025 
0026 #include "pervasive.h"
0027 #include "ras.h"
0028 
0029 static void cbe_power_save(void)
0030 {
0031     unsigned long ctrl, thread_switch_control;
0032 
0033     /* Ensure our interrupt state is properly tracked */
0034     if (!prep_irq_for_idle())
0035         return;
0036 
0037     ctrl = mfspr(SPRN_CTRLF);
0038 
0039     /* Enable DEC and EE interrupt request */
0040     thread_switch_control  = mfspr(SPRN_TSC_CELL);
0041     thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST;
0042 
0043     switch (ctrl & CTRL_CT) {
0044     case CTRL_CT0:
0045         thread_switch_control |= TSC_CELL_DEC_ENABLE_0;
0046         break;
0047     case CTRL_CT1:
0048         thread_switch_control |= TSC_CELL_DEC_ENABLE_1;
0049         break;
0050     default:
0051         printk(KERN_WARNING "%s: unknown configuration\n",
0052             __func__);
0053         break;
0054     }
0055     mtspr(SPRN_TSC_CELL, thread_switch_control);
0056 
0057     /*
0058      * go into low thread priority, medium priority will be
0059      * restored for us after wake-up.
0060      */
0061     HMT_low();
0062 
0063     /*
0064      * atomically disable thread execution and runlatch.
0065      * External and Decrementer exceptions are still handled when the
0066      * thread is disabled but now enter in cbe_system_reset_exception()
0067      */
0068     ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
0069     mtspr(SPRN_CTRLT, ctrl);
0070 
0071     /* Re-enable interrupts in MSR */
0072     __hard_irq_enable();
0073 }
0074 
0075 static int cbe_system_reset_exception(struct pt_regs *regs)
0076 {
0077     switch (regs->msr & SRR1_WAKEMASK) {
0078     case SRR1_WAKEDEC:
0079         set_dec(1);
0080         break;
0081     case SRR1_WAKEEE:
0082         /*
0083          * Handle these when interrupts get re-enabled and we take
0084          * them as regular exceptions. We are in an NMI context
0085          * and can't handle these here.
0086          */
0087         break;
0088     case SRR1_WAKEMT:
0089         return cbe_sysreset_hack();
0090 #ifdef CONFIG_CBE_RAS
0091     case SRR1_WAKESYSERR:
0092         cbe_system_error_exception(regs);
0093         break;
0094     case SRR1_WAKETHERM:
0095         cbe_thermal_exception(regs);
0096         break;
0097 #endif /* CONFIG_CBE_RAS */
0098     default:
0099         /* do system reset */
0100         return 0;
0101     }
0102     /* everything handled */
0103     return 1;
0104 }
0105 
0106 void __init cbe_pervasive_init(void)
0107 {
0108     int cpu;
0109 
0110     if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
0111         return;
0112 
0113     for_each_possible_cpu(cpu) {
0114         struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu);
0115         if (!regs)
0116             continue;
0117 
0118          /* Enable Pause(0) control bit */
0119         out_be64(&regs->pmcr, in_be64(&regs->pmcr) |
0120                         CBE_PMD_PAUSE_ZERO_CONTROL);
0121     }
0122 
0123     ppc_md.power_save = cbe_power_save;
0124     ppc_md.system_reset_exception = cbe_system_reset_exception;
0125 }