blob: 5b9a7e9f144b356c27154d1af4c3204c3c941c9f [file] [log] [blame]
Thomas Gleixnerde6cc652019-05-27 08:55:02 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Arnd Bergmannc902be72006-01-04 19:55:53 +00002/*
3 * CBE Pervasive Monitor and Debug
4 *
5 * (C) Copyright IBM Corporation 2005
6 *
7 * Authors: Maximino Aguilar (maguilar@us.ibm.com)
8 * Michael N. Day (mnday@us.ibm.com)
Arnd Bergmannc902be72006-01-04 19:55:53 +00009 */
10
11#undef DEBUG
12
Arnd Bergmannc902be72006-01-04 19:55:53 +000013#include <linux/interrupt.h>
14#include <linux/irq.h>
15#include <linux/percpu.h>
16#include <linux/types.h>
17#include <linux/kallsyms.h>
Mike Rapoport65fddcf2020-06-08 21:32:42 -070018#include <linux/pgtable.h>
Arnd Bergmannc902be72006-01-04 19:55:53 +000019
20#include <asm/io.h>
21#include <asm/machdep.h>
22#include <asm/prom.h>
Arnd Bergmannc902be72006-01-04 19:55:53 +000023#include <asm/reg.h>
Benjamin Herrenschmidteef686a02007-10-04 15:40:42 +100024#include <asm/cell-regs.h>
Kevin Haob92a2262016-07-23 14:42:40 +053025#include <asm/cpu_has_feature.h>
Arnd Bergmannc902be72006-01-04 19:55:53 +000026
27#include "pervasive.h"
Nicholas Piggindcdb4f12021-01-30 23:08:32 +100028#include "ras.h"
Arnd Bergmannc902be72006-01-04 19:55:53 +000029
arnd@arndb.de302eca12006-10-24 18:31:26 +020030static void cbe_power_save(void)
Arnd Bergmannc902be72006-01-04 19:55:53 +000031{
arnd@arndb.de302eca12006-10-24 18:31:26 +020032 unsigned long ctrl, thread_switch_control;
Benjamin Herrenschmidt5850dd82006-11-23 00:46:38 +010033
Benjamin Herrenschmidtbe2cf202012-07-10 18:36:40 +100034 /* Ensure our interrupt state is properly tracked */
35 if (!prep_irq_for_idle())
36 return;
Benjamin Herrenschmidt5850dd82006-11-23 00:46:38 +010037
arnd@arndb.de302eca12006-10-24 18:31:26 +020038 ctrl = mfspr(SPRN_CTRLF);
Arnd Bergmannc902be72006-01-04 19:55:53 +000039
40 /* Enable DEC and EE interrupt request */
41 thread_switch_control = mfspr(SPRN_TSC_CELL);
42 thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST;
43
arnd@arndb.de302eca12006-10-24 18:31:26 +020044 switch (ctrl & CTRL_CT) {
Arnd Bergmannc902be72006-01-04 19:55:53 +000045 case CTRL_CT0:
46 thread_switch_control |= TSC_CELL_DEC_ENABLE_0;
Arnd Bergmannc902be72006-01-04 19:55:53 +000047 break;
48 case CTRL_CT1:
49 thread_switch_control |= TSC_CELL_DEC_ENABLE_1;
Arnd Bergmannc902be72006-01-04 19:55:53 +000050 break;
51 default:
52 printk(KERN_WARNING "%s: unknown configuration\n",
Harvey Harrisone48b1b42008-03-29 08:21:07 +110053 __func__);
Arnd Bergmannc902be72006-01-04 19:55:53 +000054 break;
55 }
Arnd Bergmannc902be72006-01-04 19:55:53 +000056 mtspr(SPRN_TSC_CELL, thread_switch_control);
57
arnd@arndb.de302eca12006-10-24 18:31:26 +020058 /*
59 * go into low thread priority, medium priority will be
60 * restored for us after wake-up.
Benjamin Herrenschmidtacf7d762006-06-19 20:33:16 +020061 */
arnd@arndb.de302eca12006-10-24 18:31:26 +020062 HMT_low();
Arnd Bergmannc902be72006-01-04 19:55:53 +000063
arnd@arndb.de302eca12006-10-24 18:31:26 +020064 /*
65 * atomically disable thread execution and runlatch.
66 * External and Decrementer exceptions are still handled when the
67 * thread is disabled but now enter in cbe_system_reset_exception()
68 */
69 ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
70 mtspr(SPRN_CTRLT, ctrl);
Benjamin Herrenschmidtbe2cf202012-07-10 18:36:40 +100071
72 /* Re-enable interrupts in MSR */
73 __hard_irq_enable();
Arnd Bergmannc902be72006-01-04 19:55:53 +000074}
75
Arnd Bergmann8fce10a2006-01-11 23:07:11 +000076static int cbe_system_reset_exception(struct pt_regs *regs)
Arnd Bergmannc902be72006-01-04 19:55:53 +000077{
78 switch (regs->msr & SRR1_WAKEMASK) {
Arnd Bergmannc902be72006-01-04 19:55:53 +000079 case SRR1_WAKEDEC:
Nicholas Piggin6e839852017-03-20 16:31:49 +100080 set_dec(1);
81 case SRR1_WAKEEE:
82 /*
83 * Handle these when interrupts get re-enabled and we take
84 * them as regular exceptions. We are in an NMI context
85 * and can't handle these here.
86 */
Arnd Bergmannc902be72006-01-04 19:55:53 +000087 break;
88 case SRR1_WAKEMT:
Christian Krafft70694a82008-07-16 05:51:44 +100089 return cbe_sysreset_hack();
Benjamin Herrenschmidtacf7d762006-06-19 20:33:16 +020090#ifdef CONFIG_CBE_RAS
91 case SRR1_WAKESYSERR:
92 cbe_system_error_exception(regs);
93 break;
94 case SRR1_WAKETHERM:
95 cbe_thermal_exception(regs);
96 break;
97#endif /* CONFIG_CBE_RAS */
Arnd Bergmannc902be72006-01-04 19:55:53 +000098 default:
99 /* do system reset */
100 return 0;
101 }
102 /* everything handled */
103 return 1;
104}
105
Benjamin Herrenschmidtacf7d762006-06-19 20:33:16 +0200106void __init cbe_pervasive_init(void)
Arnd Bergmannc902be72006-01-04 19:55:53 +0000107{
arnd@arndb.de302eca12006-10-24 18:31:26 +0200108 int cpu;
Arnd Bergmann3addf552007-08-23 03:01:26 +1000109
Arnd Bergmannc902be72006-01-04 19:55:53 +0000110 if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
111 return;
112
arnd@arndb.de302eca12006-10-24 18:31:26 +0200113 for_each_possible_cpu(cpu) {
114 struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu);
115 if (!regs)
116 continue;
117
118 /* Enable Pause(0) control bit */
119 out_be64(&regs->pmcr, in_be64(&regs->pmcr) |
120 CBE_PMD_PAUSE_ZERO_CONTROL);
121 }
122
123 ppc_md.power_save = cbe_power_save;
Arnd Bergmannc902be72006-01-04 19:55:53 +0000124 ppc_md.system_reset_exception = cbe_system_reset_exception;
125}