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