diff options
-rw-r--r-- | arch/powerpc/configs/cell_defconfig | 57 | ||||
-rw-r--r-- | arch/powerpc/oprofile/op_model_cell.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/cbe_cpufreq.c | 81 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/cbe_regs.c | 165 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/cbe_regs.h | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/cbe_thermal.c | 177 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/ras.c | 160 | ||||
-rw-r--r-- | arch/powerpc/sysdev/pmi.c | 29 | ||||
-rw-r--r-- | include/asm-powerpc/cell-pmu.h | 5 | ||||
-rw-r--r-- | include/asm-powerpc/prom.h | 11 |
10 files changed, 581 insertions, 110 deletions
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index cf7e316ad4f6..6061e5f7696e 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.21-rc3 | 3 | # Linux kernel version: 2.6.21-rc6 |
4 | # Fri Mar 9 23:34:53 2007 | 4 | # Mon Apr 23 20:46:48 2007 |
5 | # | 5 | # |
6 | CONFIG_PPC64=y | 6 | CONFIG_PPC64=y |
7 | CONFIG_64BIT=y | 7 | CONFIG_64BIT=y |
@@ -139,11 +139,31 @@ CONFIG_PPC_MULTIPLATFORM=y | |||
139 | # CONFIG_PPC_PMAC is not set | 139 | # CONFIG_PPC_PMAC is not set |
140 | # CONFIG_PPC_MAPLE is not set | 140 | # CONFIG_PPC_MAPLE is not set |
141 | # CONFIG_PPC_PASEMI is not set | 141 | # CONFIG_PPC_PASEMI is not set |
142 | CONFIG_PPC_CELLEB=y | ||
143 | CONFIG_PPC_PS3=y | ||
144 | |||
145 | # | ||
146 | # PS3 Platform Options | ||
147 | # | ||
148 | # CONFIG_PS3_ADVANCED is not set | ||
149 | CONFIG_PS3_HTAB_SIZE=20 | ||
150 | # CONFIG_PS3_DYNAMIC_DMA is not set | ||
151 | CONFIG_PS3_USE_LPAR_ADDR=y | ||
152 | CONFIG_PS3_VUART=y | ||
153 | CONFIG_PS3_PS3AV=y | ||
154 | CONFIG_PS3_SYS_MANAGER=y | ||
142 | CONFIG_PPC_CELL=y | 155 | CONFIG_PPC_CELL=y |
143 | CONFIG_PPC_CELL_NATIVE=y | 156 | CONFIG_PPC_CELL_NATIVE=y |
144 | CONFIG_PPC_IBM_CELL_BLADE=y | 157 | CONFIG_PPC_IBM_CELL_BLADE=y |
145 | CONFIG_PPC_PS3=y | 158 | |
146 | CONFIG_PPC_CELLEB=y | 159 | # |
160 | # Cell Broadband Engine options | ||
161 | # | ||
162 | CONFIG_SPU_FS=m | ||
163 | CONFIG_SPU_BASE=y | ||
164 | CONFIG_CBE_RAS=y | ||
165 | CONFIG_CBE_THERM=m | ||
166 | CONFIG_CBE_CPUFREQ=m | ||
147 | CONFIG_PPC_NATIVE=y | 167 | CONFIG_PPC_NATIVE=y |
148 | CONFIG_UDBG_RTAS_CONSOLE=y | 168 | CONFIG_UDBG_RTAS_CONSOLE=y |
149 | CONFIG_PPC_UDBG_BEAT=y | 169 | CONFIG_PPC_UDBG_BEAT=y |
@@ -175,26 +195,6 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y | |||
175 | CONFIG_MPIC=y | 195 | CONFIG_MPIC=y |
176 | 196 | ||
177 | # | 197 | # |
178 | # Cell Broadband Engine options | ||
179 | # | ||
180 | CONFIG_SPU_FS=m | ||
181 | CONFIG_SPU_BASE=y | ||
182 | CONFIG_CBE_RAS=y | ||
183 | CONFIG_CBE_THERM=m | ||
184 | CONFIG_CBE_CPUFREQ=m | ||
185 | |||
186 | # | ||
187 | # PS3 Platform Options | ||
188 | # | ||
189 | # CONFIG_PS3_ADVANCED is not set | ||
190 | CONFIG_PS3_HTAB_SIZE=20 | ||
191 | # CONFIG_PS3_DYNAMIC_DMA is not set | ||
192 | CONFIG_PS3_USE_LPAR_ADDR=y | ||
193 | CONFIG_PS3_VUART=y | ||
194 | CONFIG_PS3_PS3AV=y | ||
195 | CONFIG_PS3_SYS_MANAGER=y | ||
196 | |||
197 | # | ||
198 | # Kernel options | 198 | # Kernel options |
199 | # | 199 | # |
200 | # CONFIG_HZ_100 is not set | 200 | # CONFIG_HZ_100 is not set |
@@ -534,7 +534,6 @@ CONFIG_BLK_DEV_GENERIC=y | |||
534 | # CONFIG_BLK_DEV_OPTI621 is not set | 534 | # CONFIG_BLK_DEV_OPTI621 is not set |
535 | CONFIG_BLK_DEV_IDEDMA_PCI=y | 535 | CONFIG_BLK_DEV_IDEDMA_PCI=y |
536 | # CONFIG_BLK_DEV_IDEDMA_FORCED is not set | 536 | # CONFIG_BLK_DEV_IDEDMA_FORCED is not set |
537 | CONFIG_IDEDMA_PCI_AUTO=y | ||
538 | # CONFIG_IDEDMA_ONLYDISK is not set | 537 | # CONFIG_IDEDMA_ONLYDISK is not set |
539 | CONFIG_BLK_DEV_AEC62XX=y | 538 | CONFIG_BLK_DEV_AEC62XX=y |
540 | # CONFIG_BLK_DEV_ALI15X3 is not set | 539 | # CONFIG_BLK_DEV_ALI15X3 is not set |
@@ -561,11 +560,10 @@ CONFIG_BLK_DEV_SIIMAGE=y | |||
561 | # CONFIG_BLK_DEV_TRM290 is not set | 560 | # CONFIG_BLK_DEV_TRM290 is not set |
562 | # CONFIG_BLK_DEV_VIA82CXXX is not set | 561 | # CONFIG_BLK_DEV_VIA82CXXX is not set |
563 | # CONFIG_BLK_DEV_TC86C001 is not set | 562 | # CONFIG_BLK_DEV_TC86C001 is not set |
564 | CONFIG_BLK_DEV_IDE_CELLEB=y | 563 | CONFIG_BLK_DEV_CELLEB=y |
565 | # CONFIG_IDE_ARM is not set | 564 | # CONFIG_IDE_ARM is not set |
566 | CONFIG_BLK_DEV_IDEDMA=y | 565 | CONFIG_BLK_DEV_IDEDMA=y |
567 | # CONFIG_IDEDMA_IVB is not set | 566 | # CONFIG_IDEDMA_IVB is not set |
568 | CONFIG_IDEDMA_AUTO=y | ||
569 | # CONFIG_BLK_DEV_HD is not set | 567 | # CONFIG_BLK_DEV_HD is not set |
570 | 568 | ||
571 | # | 569 | # |
@@ -937,7 +935,7 @@ CONFIG_UNIX98_PTYS=y | |||
937 | # CONFIG_LEGACY_PTYS is not set | 935 | # CONFIG_LEGACY_PTYS is not set |
938 | CONFIG_HVC_DRIVER=y | 936 | CONFIG_HVC_DRIVER=y |
939 | CONFIG_HVC_RTAS=y | 937 | CONFIG_HVC_RTAS=y |
940 | # CONFIG_HVC_BEAT is not set | 938 | CONFIG_HVC_BEAT=y |
941 | 939 | ||
942 | # | 940 | # |
943 | # IPMI | 941 | # IPMI |
@@ -1482,6 +1480,8 @@ CONFIG_NLS_ISO8859_15=m | |||
1482 | # Distributed Lock Manager | 1480 | # Distributed Lock Manager |
1483 | # | 1481 | # |
1484 | # CONFIG_DLM is not set | 1482 | # CONFIG_DLM is not set |
1483 | # CONFIG_UCC_SLOW is not set | ||
1484 | # CONFIG_UCC_FAST is not set | ||
1485 | 1485 | ||
1486 | # | 1486 | # |
1487 | # Library routines | 1487 | # Library routines |
@@ -1540,6 +1540,7 @@ CONFIG_DEBUG_BUGVERBOSE=y | |||
1540 | # CONFIG_FAULT_INJECTION is not set | 1540 | # CONFIG_FAULT_INJECTION is not set |
1541 | # CONFIG_DEBUG_STACKOVERFLOW is not set | 1541 | # CONFIG_DEBUG_STACKOVERFLOW is not set |
1542 | # CONFIG_DEBUG_STACK_USAGE is not set | 1542 | # CONFIG_DEBUG_STACK_USAGE is not set |
1543 | # CONFIG_DEBUG_PAGEALLOC is not set | ||
1543 | CONFIG_DEBUGGER=y | 1544 | CONFIG_DEBUGGER=y |
1544 | CONFIG_XMON=y | 1545 | CONFIG_XMON=y |
1545 | CONFIG_XMON_DEFAULT=y | 1546 | CONFIG_XMON_DEFAULT=y |
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c index e08e1d7b3dc5..fb999e3e9f21 100644 --- a/arch/powerpc/oprofile/op_model_cell.c +++ b/arch/powerpc/oprofile/op_model_cell.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <asm/system.h> | 37 | #include <asm/system.h> |
38 | 38 | ||
39 | #include "../platforms/cell/interrupt.h" | 39 | #include "../platforms/cell/interrupt.h" |
40 | #include "../platforms/cell/cbe_regs.h" | ||
40 | 41 | ||
41 | #define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */ | 42 | #define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */ |
42 | #define PPU_CYCLES_GRP_NUM 1 /* special group number for identifying | 43 | #define PPU_CYCLES_GRP_NUM 1 /* special group number for identifying |
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c index 9c5d63b7e76c..4495973bff59 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <asm/processor.h> | 28 | #include <asm/processor.h> |
29 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
30 | #include <asm/time.h> | 30 | #include <asm/time.h> |
31 | #include <asm/pmi.h> | ||
32 | #include <asm/of_platform.h> | ||
31 | 33 | ||
32 | #include "cbe_regs.h" | 34 | #include "cbe_regs.h" |
33 | 35 | ||
@@ -68,6 +70,38 @@ static u64 MIC_Slow_Next_Timer_table[] = { | |||
68 | * hardware specific functions | 70 | * hardware specific functions |
69 | */ | 71 | */ |
70 | 72 | ||
73 | static struct of_device *pmi_dev; | ||
74 | |||
75 | static int set_pmode_pmi(int cpu, unsigned int pmode) | ||
76 | { | ||
77 | int ret; | ||
78 | pmi_message_t pmi_msg; | ||
79 | #ifdef DEBUG | ||
80 | u64 time; | ||
81 | #endif | ||
82 | |||
83 | pmi_msg.type = PMI_TYPE_FREQ_CHANGE; | ||
84 | pmi_msg.data1 = cbe_cpu_to_node(cpu); | ||
85 | pmi_msg.data2 = pmode; | ||
86 | |||
87 | #ifdef DEBUG | ||
88 | time = (u64) get_cycles(); | ||
89 | #endif | ||
90 | |||
91 | pmi_send_message(pmi_dev, pmi_msg); | ||
92 | ret = pmi_msg.data2; | ||
93 | |||
94 | pr_debug("PMI returned slow mode %d\n", ret); | ||
95 | |||
96 | #ifdef DEBUG | ||
97 | time = (u64) get_cycles() - time; /* actual cycles (not cpu cycles!) */ | ||
98 | time = 1000000000 * time / CLOCK_TICK_RATE; /* time in ns (10^-9) */ | ||
99 | pr_debug("had to wait %lu ns for a transition\n", time); | ||
100 | #endif | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | |||
71 | static int get_pmode(int cpu) | 105 | static int get_pmode(int cpu) |
72 | { | 106 | { |
73 | int ret; | 107 | int ret; |
@@ -79,7 +113,7 @@ static int get_pmode(int cpu) | |||
79 | return ret; | 113 | return ret; |
80 | } | 114 | } |
81 | 115 | ||
82 | static int set_pmode(int cpu, unsigned int pmode) | 116 | static int set_pmode_reg(int cpu, unsigned int pmode) |
83 | { | 117 | { |
84 | struct cbe_pmd_regs __iomem *pmd_regs; | 118 | struct cbe_pmd_regs __iomem *pmd_regs; |
85 | struct cbe_mic_tm_regs __iomem *mic_tm_regs; | 119 | struct cbe_mic_tm_regs __iomem *mic_tm_regs; |
@@ -120,6 +154,39 @@ static int set_pmode(int cpu, unsigned int pmode) | |||
120 | return 0; | 154 | return 0; |
121 | } | 155 | } |
122 | 156 | ||
157 | static int set_pmode(int cpu, unsigned int slow_mode) { | ||
158 | if(pmi_dev) | ||
159 | return set_pmode_pmi(cpu, slow_mode); | ||
160 | else | ||
161 | return set_pmode_reg(cpu, slow_mode); | ||
162 | } | ||
163 | |||
164 | static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg) | ||
165 | { | ||
166 | struct cpufreq_policy policy; | ||
167 | u8 cpu; | ||
168 | u8 cbe_pmode_new; | ||
169 | |||
170 | BUG_ON (pmi_msg.type != PMI_TYPE_FREQ_CHANGE); | ||
171 | |||
172 | cpu = cbe_node_to_cpu(pmi_msg.data1); | ||
173 | cbe_pmode_new = pmi_msg.data2; | ||
174 | |||
175 | cpufreq_get_policy(&policy, cpu); | ||
176 | |||
177 | policy.max = min(policy.max, cbe_freqs[cbe_pmode_new].frequency); | ||
178 | policy.min = min(policy.min, policy.max); | ||
179 | |||
180 | pr_debug("cbe_handle_pmi: new policy.min=%d policy.max=%d\n", policy.min, policy.max); | ||
181 | cpufreq_set_policy(&policy); | ||
182 | } | ||
183 | |||
184 | static struct pmi_handler cbe_pmi_handler = { | ||
185 | .type = PMI_TYPE_FREQ_CHANGE, | ||
186 | .handle_pmi_message = cbe_cpufreq_handle_pmi, | ||
187 | }; | ||
188 | |||
189 | |||
123 | /* | 190 | /* |
124 | * cpufreq functions | 191 | * cpufreq functions |
125 | */ | 192 | */ |
@@ -234,11 +301,23 @@ static struct cpufreq_driver cbe_cpufreq_driver = { | |||
234 | 301 | ||
235 | static int __init cbe_cpufreq_init(void) | 302 | static int __init cbe_cpufreq_init(void) |
236 | { | 303 | { |
304 | struct device_node *np; | ||
305 | |||
306 | np = of_find_node_by_type(NULL, "ibm,pmi"); | ||
307 | |||
308 | pmi_dev = of_find_device_by_node(np); | ||
309 | |||
310 | if (pmi_dev) | ||
311 | pmi_register_handler(pmi_dev, &cbe_pmi_handler); | ||
312 | |||
237 | return cpufreq_register_driver(&cbe_cpufreq_driver); | 313 | return cpufreq_register_driver(&cbe_cpufreq_driver); |
238 | } | 314 | } |
239 | 315 | ||
240 | static void __exit cbe_cpufreq_exit(void) | 316 | static void __exit cbe_cpufreq_exit(void) |
241 | { | 317 | { |
318 | if(pmi_dev) | ||
319 | pmi_unregister_handler(pmi_dev, &cbe_pmi_handler); | ||
320 | |||
242 | cpufreq_unregister_driver(&cbe_cpufreq_driver); | 321 | cpufreq_unregister_driver(&cbe_cpufreq_driver); |
243 | } | 322 | } |
244 | 323 | ||
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index 7c94af4ac439..12c9674b4b1f 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <asm/pgtable.h> | 14 | #include <asm/pgtable.h> |
15 | #include <asm/prom.h> | 15 | #include <asm/prom.h> |
16 | #include <asm/ptrace.h> | 16 | #include <asm/ptrace.h> |
17 | #include <asm/of_device.h> | ||
18 | #include <asm/of_platform.h> | ||
17 | 19 | ||
18 | #include "cbe_regs.h" | 20 | #include "cbe_regs.h" |
19 | 21 | ||
@@ -27,6 +29,7 @@ | |||
27 | static struct cbe_regs_map | 29 | static struct cbe_regs_map |
28 | { | 30 | { |
29 | struct device_node *cpu_node; | 31 | struct device_node *cpu_node; |
32 | struct device_node *be_node; | ||
30 | struct cbe_pmd_regs __iomem *pmd_regs; | 33 | struct cbe_pmd_regs __iomem *pmd_regs; |
31 | struct cbe_iic_regs __iomem *iic_regs; | 34 | struct cbe_iic_regs __iomem *iic_regs; |
32 | struct cbe_mic_tm_regs __iomem *mic_tm_regs; | 35 | struct cbe_mic_tm_regs __iomem *mic_tm_regs; |
@@ -37,30 +40,43 @@ static int cbe_regs_map_count; | |||
37 | static struct cbe_thread_map | 40 | static struct cbe_thread_map |
38 | { | 41 | { |
39 | struct device_node *cpu_node; | 42 | struct device_node *cpu_node; |
43 | struct device_node *be_node; | ||
40 | struct cbe_regs_map *regs; | 44 | struct cbe_regs_map *regs; |
45 | unsigned int thread_id; | ||
46 | unsigned int cbe_id; | ||
41 | } cbe_thread_map[NR_CPUS]; | 47 | } cbe_thread_map[NR_CPUS]; |
42 | 48 | ||
49 | static cpumask_t cbe_local_mask[MAX_CBE] = { [0 ... MAX_CBE-1] = CPU_MASK_NONE }; | ||
50 | static cpumask_t cbe_first_online_cpu = CPU_MASK_NONE; | ||
51 | |||
43 | static struct cbe_regs_map *cbe_find_map(struct device_node *np) | 52 | static struct cbe_regs_map *cbe_find_map(struct device_node *np) |
44 | { | 53 | { |
45 | int i; | 54 | int i; |
46 | struct device_node *tmp_np; | 55 | struct device_node *tmp_np; |
47 | 56 | ||
48 | if (strcasecmp(np->type, "spe") == 0) { | 57 | if (strcasecmp(np->type, "spe")) { |
49 | if (np->data == NULL) { | 58 | for (i = 0; i < cbe_regs_map_count; i++) |
50 | /* walk up path until cpu node was found */ | 59 | if (cbe_regs_maps[i].cpu_node == np || |
51 | tmp_np = np->parent; | 60 | cbe_regs_maps[i].be_node == np) |
52 | while (tmp_np != NULL && strcasecmp(tmp_np->type, "cpu") != 0) | 61 | return &cbe_regs_maps[i]; |
53 | tmp_np = tmp_np->parent; | 62 | return NULL; |
63 | } | ||
54 | 64 | ||
55 | np->data = cbe_find_map(tmp_np); | 65 | if (np->data) |
56 | } | ||
57 | return np->data; | 66 | return np->data; |
58 | } | ||
59 | 67 | ||
60 | for (i = 0; i < cbe_regs_map_count; i++) | 68 | /* walk up path until cpu or be node was found */ |
61 | if (cbe_regs_maps[i].cpu_node == np) | 69 | tmp_np = np; |
62 | return &cbe_regs_maps[i]; | 70 | do { |
63 | return NULL; | 71 | tmp_np = tmp_np->parent; |
72 | /* on a correct devicetree we wont get up to root */ | ||
73 | BUG_ON(!tmp_np); | ||
74 | } while (strcasecmp(tmp_np->type, "cpu") && | ||
75 | strcasecmp(tmp_np->type, "be")); | ||
76 | |||
77 | np->data = cbe_find_map(tmp_np); | ||
78 | |||
79 | return np->data; | ||
64 | } | 80 | } |
65 | 81 | ||
66 | struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) | 82 | struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) |
@@ -130,49 +146,69 @@ struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu) | |||
130 | } | 146 | } |
131 | EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs); | 147 | EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs); |
132 | 148 | ||
133 | /* FIXME | ||
134 | * This is little more than a stub at the moment. It should be | ||
135 | * fleshed out so that it works for both SMT and non-SMT, no | ||
136 | * matter if the passed cpu is odd or even. | ||
137 | * For SMT enabled, returns 0 for even-numbered cpu; otherwise 1. | ||
138 | * For SMT disabled, returns 0 for all cpus. | ||
139 | */ | ||
140 | u32 cbe_get_hw_thread_id(int cpu) | 149 | u32 cbe_get_hw_thread_id(int cpu) |
141 | { | 150 | { |
142 | return (cpu & 1); | 151 | return cbe_thread_map[cpu].thread_id; |
143 | } | 152 | } |
144 | EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id); | 153 | EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id); |
145 | 154 | ||
146 | void __init cbe_regs_init(void) | 155 | u32 cbe_cpu_to_node(int cpu) |
147 | { | 156 | { |
148 | int i; | 157 | return cbe_thread_map[cpu].cbe_id; |
149 | struct device_node *cpu; | 158 | } |
159 | EXPORT_SYMBOL_GPL(cbe_cpu_to_node); | ||
150 | 160 | ||
151 | /* Build local fast map of CPUs */ | 161 | u32 cbe_node_to_cpu(int node) |
152 | for_each_possible_cpu(i) | 162 | { |
153 | cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL); | 163 | return find_first_bit( (unsigned long *) &cbe_local_mask[node], sizeof(cpumask_t)); |
164 | } | ||
165 | EXPORT_SYMBOL_GPL(cbe_node_to_cpu); | ||
154 | 166 | ||
155 | /* Find maps for each device tree CPU */ | 167 | static struct device_node *cbe_get_be_node(int cpu_id) |
156 | for_each_node_by_type(cpu, "cpu") { | 168 | { |
157 | struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++]; | 169 | struct device_node *np; |
170 | |||
171 | for_each_node_by_type (np, "be") { | ||
172 | int len,i; | ||
173 | const phandle *cpu_handle; | ||
174 | |||
175 | cpu_handle = of_get_property(np, "cpus", &len); | ||
176 | |||
177 | for (i=0; i<len; i++) | ||
178 | if (of_find_node_by_phandle(cpu_handle[i]) == of_get_cpu_node(cpu_id, NULL)) | ||
179 | return np; | ||
180 | } | ||
181 | |||
182 | return NULL; | ||
183 | } | ||
184 | |||
185 | void __init cbe_fill_regs_map(struct cbe_regs_map *map) | ||
186 | { | ||
187 | if(map->be_node) { | ||
188 | struct device_node *be, *np; | ||
189 | |||
190 | be = map->be_node; | ||
158 | 191 | ||
192 | for_each_node_by_type(np, "pervasive") | ||
193 | if (of_get_parent(np) == be) | ||
194 | map->pmd_regs = of_iomap(np, 0); | ||
195 | |||
196 | for_each_node_by_type(np, "CBEA-Internal-Interrupt-Controller") | ||
197 | if (of_get_parent(np) == be) | ||
198 | map->iic_regs = of_iomap(np, 2); | ||
199 | |||
200 | for_each_node_by_type(np, "mic-tm") | ||
201 | if (of_get_parent(np) == be) | ||
202 | map->mic_tm_regs = of_iomap(np, 0); | ||
203 | } else { | ||
204 | struct device_node *cpu; | ||
159 | /* That hack must die die die ! */ | 205 | /* That hack must die die die ! */ |
160 | const struct address_prop { | 206 | const struct address_prop { |
161 | unsigned long address; | 207 | unsigned long address; |
162 | unsigned int len; | 208 | unsigned int len; |
163 | } __attribute__((packed)) *prop; | 209 | } __attribute__((packed)) *prop; |
164 | 210 | ||
165 | 211 | cpu = map->cpu_node; | |
166 | if (cbe_regs_map_count > MAX_CBE) { | ||
167 | printk(KERN_ERR "cbe_regs: More BE chips than supported" | ||
168 | "!\n"); | ||
169 | cbe_regs_map_count--; | ||
170 | return; | ||
171 | } | ||
172 | map->cpu_node = cpu; | ||
173 | for_each_possible_cpu(i) | ||
174 | if (cbe_thread_map[i].cpu_node == cpu) | ||
175 | cbe_thread_map[i].regs = map; | ||
176 | 212 | ||
177 | prop = of_get_property(cpu, "pervasive", NULL); | 213 | prop = of_get_property(cpu, "pervasive", NULL); |
178 | if (prop != NULL) | 214 | if (prop != NULL) |
@@ -188,3 +224,50 @@ void __init cbe_regs_init(void) | |||
188 | } | 224 | } |
189 | } | 225 | } |
190 | 226 | ||
227 | |||
228 | void __init cbe_regs_init(void) | ||
229 | { | ||
230 | int i; | ||
231 | unsigned int thread_id; | ||
232 | struct device_node *cpu; | ||
233 | |||
234 | /* Build local fast map of CPUs */ | ||
235 | for_each_possible_cpu(i) { | ||
236 | cbe_thread_map[i].cpu_node = of_get_cpu_node(i, &thread_id); | ||
237 | cbe_thread_map[i].be_node = cbe_get_be_node(i); | ||
238 | cbe_thread_map[i].thread_id = thread_id; | ||
239 | } | ||
240 | |||
241 | /* Find maps for each device tree CPU */ | ||
242 | for_each_node_by_type(cpu, "cpu") { | ||
243 | struct cbe_regs_map *map; | ||
244 | unsigned int cbe_id; | ||
245 | |||
246 | cbe_id = cbe_regs_map_count++; | ||
247 | map = &cbe_regs_maps[cbe_id]; | ||
248 | |||
249 | if (cbe_regs_map_count > MAX_CBE) { | ||
250 | printk(KERN_ERR "cbe_regs: More BE chips than supported" | ||
251 | "!\n"); | ||
252 | cbe_regs_map_count--; | ||
253 | return; | ||
254 | } | ||
255 | map->cpu_node = cpu; | ||
256 | |||
257 | for_each_possible_cpu(i) { | ||
258 | struct cbe_thread_map *thread = &cbe_thread_map[i]; | ||
259 | |||
260 | if (thread->cpu_node == cpu) { | ||
261 | thread->regs = map; | ||
262 | thread->cbe_id = cbe_id; | ||
263 | map->be_node = thread->be_node; | ||
264 | cpu_set(i, cbe_local_mask[cbe_id]); | ||
265 | if(thread->thread_id == 0) | ||
266 | cpu_set(i, cbe_first_online_cpu); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | cbe_fill_regs_map(map); | ||
271 | } | ||
272 | } | ||
273 | |||
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h index 440a7ecc66ea..17d597144877 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ b/arch/powerpc/platforms/cell/cbe_regs.h | |||
@@ -255,6 +255,11 @@ struct cbe_mic_tm_regs { | |||
255 | extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); | 255 | extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); |
256 | extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); | 256 | extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); |
257 | 257 | ||
258 | /* some utility functions to deal with SMT */ | ||
259 | extern u32 cbe_get_hw_thread_id(int cpu); | ||
260 | extern u32 cbe_cpu_to_node(int cpu); | ||
261 | extern u32 cbe_node_to_cpu(int node); | ||
262 | |||
258 | /* Init this module early */ | 263 | /* Init this module early */ |
259 | extern void cbe_regs_init(void); | 264 | extern void cbe_regs_init(void); |
260 | 265 | ||
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c index e8bcd2a767ce..f370f0fa6f4c 100644 --- a/arch/powerpc/platforms/cell/cbe_thermal.c +++ b/arch/powerpc/platforms/cell/cbe_thermal.c | |||
@@ -1,6 +1,31 @@ | |||
1 | /* | 1 | /* |
2 | * thermal support for the cell processor | 2 | * thermal support for the cell processor |
3 | * | 3 | * |
4 | * This module adds some sysfs attributes to cpu and spu nodes. | ||
5 | * Base for measurements are the digital thermal sensors (DTS) | ||
6 | * located on the chip. | ||
7 | * The accuracy is 2 degrees, starting from 65 up to 125 degrees celsius | ||
8 | * The attributes can be found under | ||
9 | * /sys/devices/system/cpu/cpuX/thermal | ||
10 | * /sys/devices/system/spu/spuX/thermal | ||
11 | * | ||
12 | * The following attributes are added for each node: | ||
13 | * temperature: | ||
14 | * contains the current temperature measured by the DTS | ||
15 | * throttle_begin: | ||
16 | * throttling begins when temperature is greater or equal to | ||
17 | * throttle_begin. Setting this value to 125 prevents throttling. | ||
18 | * throttle_end: | ||
19 | * throttling is being ceased, if the temperature is lower than | ||
20 | * throttle_end. Due to a delay between applying throttling and | ||
21 | * a reduced temperature this value should be less than throttle_begin. | ||
22 | * A value equal to throttle_begin provides only a very little hysteresis. | ||
23 | * throttle_full_stop: | ||
24 | * If the temperatrue is greater or equal to throttle_full_stop, | ||
25 | * full throttling is applied to the cpu or spu. This value should be | ||
26 | * greater than throttle_begin and throttle_end. Setting this value to | ||
27 | * 65 prevents the unit from running code at all. | ||
28 | * | ||
4 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 | 29 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 |
5 | * | 30 | * |
6 | * Author: Christian Krafft <krafft@de.ibm.com> | 31 | * Author: Christian Krafft <krafft@de.ibm.com> |
@@ -31,6 +56,26 @@ | |||
31 | #include "cbe_regs.h" | 56 | #include "cbe_regs.h" |
32 | #include "spu_priv1_mmio.h" | 57 | #include "spu_priv1_mmio.h" |
33 | 58 | ||
59 | #define TEMP_MIN 65 | ||
60 | #define TEMP_MAX 125 | ||
61 | |||
62 | #define SYSDEV_PREFIX_ATTR(_prefix,_name,_mode) \ | ||
63 | struct sysdev_attribute attr_ ## _prefix ## _ ## _name = { \ | ||
64 | .attr = { .name = __stringify(_name), .mode = _mode }, \ | ||
65 | .show = _prefix ## _show_ ## _name, \ | ||
66 | .store = _prefix ## _store_ ## _name, \ | ||
67 | }; | ||
68 | |||
69 | static inline u8 reg_to_temp(u8 reg_value) | ||
70 | { | ||
71 | return ((reg_value & 0x3f) << 1) + TEMP_MIN; | ||
72 | } | ||
73 | |||
74 | static inline u8 temp_to_reg(u8 temp) | ||
75 | { | ||
76 | return ((temp - TEMP_MIN) >> 1) & 0x3f; | ||
77 | } | ||
78 | |||
34 | static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) | 79 | static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) |
35 | { | 80 | { |
36 | struct spu *spu; | 81 | struct spu *spu; |
@@ -58,20 +103,81 @@ static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iom | |||
58 | 103 | ||
59 | static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf) | 104 | static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf) |
60 | { | 105 | { |
61 | int value; | 106 | u8 value; |
62 | struct cbe_pmd_regs __iomem *pmd_regs; | 107 | struct cbe_pmd_regs __iomem *pmd_regs; |
63 | 108 | ||
64 | pmd_regs = get_pmd_regs(sysdev); | 109 | pmd_regs = get_pmd_regs(sysdev); |
65 | 110 | ||
66 | value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1); | 111 | value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1); |
67 | /* clear all other bits */ | 112 | |
113 | return sprintf(buf, "%d\n", reg_to_temp(value)); | ||
114 | } | ||
115 | |||
116 | static ssize_t show_throttle(struct cbe_pmd_regs __iomem *pmd_regs, char *buf, int pos) | ||
117 | { | ||
118 | u64 value; | ||
119 | |||
120 | value = in_be64(&pmd_regs->tm_tpr.val); | ||
121 | /* access the corresponding byte */ | ||
122 | value >>= pos; | ||
68 | value &= 0x3F; | 123 | value &= 0x3F; |
69 | /* temp is stored in steps of 2 degrees */ | ||
70 | value *= 2; | ||
71 | /* base temp is 65 degrees */ | ||
72 | value += 65; | ||
73 | 124 | ||
74 | return sprintf(buf, "%d\n", (int) value); | 125 | return sprintf(buf, "%d\n", reg_to_temp(value)); |
126 | } | ||
127 | |||
128 | static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char *buf, size_t size, int pos) | ||
129 | { | ||
130 | u64 reg_value; | ||
131 | int temp; | ||
132 | u64 new_value; | ||
133 | int ret; | ||
134 | |||
135 | ret = sscanf(buf, "%u", &temp); | ||
136 | |||
137 | if (ret != 1 || temp < TEMP_MIN || temp > TEMP_MAX) | ||
138 | return -EINVAL; | ||
139 | |||
140 | new_value = temp_to_reg(temp); | ||
141 | |||
142 | reg_value = in_be64(&pmd_regs->tm_tpr.val); | ||
143 | |||
144 | /* zero out bits for new value */ | ||
145 | reg_value &= ~(0xffull << pos); | ||
146 | /* set bits to new value */ | ||
147 | reg_value |= new_value << pos; | ||
148 | |||
149 | out_be64(&pmd_regs->tm_tpr.val, reg_value); | ||
150 | return size; | ||
151 | } | ||
152 | |||
153 | static ssize_t spu_show_throttle_end(struct sys_device *sysdev, char *buf) | ||
154 | { | ||
155 | return show_throttle(get_pmd_regs(sysdev), buf, 0); | ||
156 | } | ||
157 | |||
158 | static ssize_t spu_show_throttle_begin(struct sys_device *sysdev, char *buf) | ||
159 | { | ||
160 | return show_throttle(get_pmd_regs(sysdev), buf, 8); | ||
161 | } | ||
162 | |||
163 | static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev, char *buf) | ||
164 | { | ||
165 | return show_throttle(get_pmd_regs(sysdev), buf, 16); | ||
166 | } | ||
167 | |||
168 | static ssize_t spu_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size) | ||
169 | { | ||
170 | return store_throttle(get_pmd_regs(sysdev), buf, size, 0); | ||
171 | } | ||
172 | |||
173 | static ssize_t spu_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size) | ||
174 | { | ||
175 | return store_throttle(get_pmd_regs(sysdev), buf, size, 8); | ||
176 | } | ||
177 | |||
178 | static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size) | ||
179 | { | ||
180 | return store_throttle(get_pmd_regs(sysdev), buf, size, 16); | ||
75 | } | 181 | } |
76 | 182 | ||
77 | static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) | 183 | static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) |
@@ -82,16 +188,9 @@ static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) | |||
82 | pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); | 188 | pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); |
83 | value = in_be64(&pmd_regs->ts_ctsr2); | 189 | value = in_be64(&pmd_regs->ts_ctsr2); |
84 | 190 | ||
85 | /* access the corresponding byte */ | 191 | value = (value >> pos) & 0x3f; |
86 | value >>= pos; | ||
87 | /* clear all other bits */ | ||
88 | value &= 0x3F; | ||
89 | /* temp is stored in steps of 2 degrees */ | ||
90 | value *= 2; | ||
91 | /* base temp is 65 degrees */ | ||
92 | value += 65; | ||
93 | 192 | ||
94 | return sprintf(buf, "%d\n", (int) value); | 193 | return sprintf(buf, "%d\n", reg_to_temp(value)); |
95 | } | 194 | } |
96 | 195 | ||
97 | 196 | ||
@@ -108,13 +207,52 @@ static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf) | |||
108 | return ppe_show_temp(sysdev, buf, 0); | 207 | return ppe_show_temp(sysdev, buf, 0); |
109 | } | 208 | } |
110 | 209 | ||
210 | static ssize_t ppe_show_throttle_end(struct sys_device *sysdev, char *buf) | ||
211 | { | ||
212 | return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 32); | ||
213 | } | ||
214 | |||
215 | static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev, char *buf) | ||
216 | { | ||
217 | return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 40); | ||
218 | } | ||
219 | |||
220 | static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev, char *buf) | ||
221 | { | ||
222 | return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 48); | ||
223 | } | ||
224 | |||
225 | static ssize_t ppe_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size) | ||
226 | { | ||
227 | return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 32); | ||
228 | } | ||
229 | |||
230 | static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size) | ||
231 | { | ||
232 | return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 40); | ||
233 | } | ||
234 | |||
235 | static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size) | ||
236 | { | ||
237 | return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 48); | ||
238 | } | ||
239 | |||
240 | |||
111 | static struct sysdev_attribute attr_spu_temperature = { | 241 | static struct sysdev_attribute attr_spu_temperature = { |
112 | .attr = {.name = "temperature", .mode = 0400 }, | 242 | .attr = {.name = "temperature", .mode = 0400 }, |
113 | .show = spu_show_temp, | 243 | .show = spu_show_temp, |
114 | }; | 244 | }; |
115 | 245 | ||
246 | static SYSDEV_PREFIX_ATTR(spu, throttle_end, 0600); | ||
247 | static SYSDEV_PREFIX_ATTR(spu, throttle_begin, 0600); | ||
248 | static SYSDEV_PREFIX_ATTR(spu, throttle_full_stop, 0600); | ||
249 | |||
250 | |||
116 | static struct attribute *spu_attributes[] = { | 251 | static struct attribute *spu_attributes[] = { |
117 | &attr_spu_temperature.attr, | 252 | &attr_spu_temperature.attr, |
253 | &attr_spu_throttle_end.attr, | ||
254 | &attr_spu_throttle_begin.attr, | ||
255 | &attr_spu_throttle_full_stop.attr, | ||
118 | NULL, | 256 | NULL, |
119 | }; | 257 | }; |
120 | 258 | ||
@@ -133,9 +271,16 @@ static struct sysdev_attribute attr_ppe_temperature1 = { | |||
133 | .show = ppe_show_temp1, | 271 | .show = ppe_show_temp1, |
134 | }; | 272 | }; |
135 | 273 | ||
274 | static SYSDEV_PREFIX_ATTR(ppe, throttle_end, 0600); | ||
275 | static SYSDEV_PREFIX_ATTR(ppe, throttle_begin, 0600); | ||
276 | static SYSDEV_PREFIX_ATTR(ppe, throttle_full_stop, 0600); | ||
277 | |||
136 | static struct attribute *ppe_attributes[] = { | 278 | static struct attribute *ppe_attributes[] = { |
137 | &attr_ppe_temperature0.attr, | 279 | &attr_ppe_temperature0.attr, |
138 | &attr_ppe_temperature1.attr, | 280 | &attr_ppe_temperature1.attr, |
281 | &attr_ppe_throttle_end.attr, | ||
282 | &attr_ppe_throttle_begin.attr, | ||
283 | &attr_ppe_throttle_full_stop.attr, | ||
139 | NULL, | 284 | NULL, |
140 | }; | 285 | }; |
141 | 286 | ||
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 0984c7071695..b5ebc916388b 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c | |||
@@ -3,11 +3,13 @@ | |||
3 | #include <linux/types.h> | 3 | #include <linux/types.h> |
4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
5 | #include <linux/smp.h> | 5 | #include <linux/smp.h> |
6 | #include <linux/reboot.h> | ||
6 | 7 | ||
7 | #include <asm/reg.h> | 8 | #include <asm/reg.h> |
8 | #include <asm/io.h> | 9 | #include <asm/io.h> |
9 | #include <asm/prom.h> | 10 | #include <asm/prom.h> |
10 | #include <asm/machdep.h> | 11 | #include <asm/machdep.h> |
12 | #include <asm/rtas.h> | ||
11 | 13 | ||
12 | #include "ras.h" | 14 | #include "ras.h" |
13 | #include "cbe_regs.h" | 15 | #include "cbe_regs.h" |
@@ -82,6 +84,164 @@ static int cbe_machine_check_handler(struct pt_regs *regs) | |||
82 | return 0; | 84 | return 0; |
83 | } | 85 | } |
84 | 86 | ||
87 | struct ptcal_area { | ||
88 | struct list_head list; | ||
89 | int nid; | ||
90 | int order; | ||
91 | struct page *pages; | ||
92 | }; | ||
93 | |||
94 | static LIST_HEAD(ptcal_list); | ||
95 | |||
96 | static int ptcal_start_tok, ptcal_stop_tok; | ||
97 | |||
98 | static int __init cbe_ptcal_enable_on_node(int nid, int order) | ||
99 | { | ||
100 | struct ptcal_area *area; | ||
101 | int ret = -ENOMEM; | ||
102 | unsigned long addr; | ||
103 | |||
104 | #ifdef CONFIG_CRASH_DUMP | ||
105 | rtas_call(ptcal_stop_tok, 1, 1, NULL, nid); | ||
106 | #endif | ||
107 | |||
108 | area = kmalloc(sizeof(*area), GFP_KERNEL); | ||
109 | if (!area) | ||
110 | goto out_err; | ||
111 | |||
112 | area->nid = nid; | ||
113 | area->order = order; | ||
114 | area->pages = alloc_pages_node(area->nid, GFP_KERNEL, area->order); | ||
115 | |||
116 | if (!area->pages) | ||
117 | goto out_free_area; | ||
118 | |||
119 | addr = __pa(page_address(area->pages)); | ||
120 | |||
121 | ret = -EIO; | ||
122 | if (rtas_call(ptcal_start_tok, 3, 1, NULL, area->nid, | ||
123 | (unsigned int)(addr >> 32), | ||
124 | (unsigned int)(addr & 0xffffffff))) { | ||
125 | printk(KERN_ERR "%s: error enabling PTCAL on node %d!\n", | ||
126 | __FUNCTION__, nid); | ||
127 | goto out_free_pages; | ||
128 | } | ||
129 | |||
130 | list_add(&area->list, &ptcal_list); | ||
131 | |||
132 | return 0; | ||
133 | |||
134 | out_free_pages: | ||
135 | __free_pages(area->pages, area->order); | ||
136 | out_free_area: | ||
137 | kfree(area); | ||
138 | out_err: | ||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | static int __init cbe_ptcal_enable(void) | ||
143 | { | ||
144 | const u32 *size; | ||
145 | struct device_node *np; | ||
146 | int order, found_mic = 0; | ||
147 | |||
148 | np = of_find_node_by_path("/rtas"); | ||
149 | if (!np) | ||
150 | return -ENODEV; | ||
151 | |||
152 | size = get_property(np, "ibm,cbe-ptcal-size", NULL); | ||
153 | if (!size) | ||
154 | return -ENODEV; | ||
155 | |||
156 | pr_debug("%s: enabling PTCAL, size = 0x%x\n", __FUNCTION__, *size); | ||
157 | order = get_order(*size); | ||
158 | of_node_put(np); | ||
159 | |||
160 | /* support for malta device trees, with be@/mic@ nodes */ | ||
161 | for_each_node_by_type(np, "mic-tm") { | ||
162 | cbe_ptcal_enable_on_node(of_node_to_nid(np), order); | ||
163 | found_mic = 1; | ||
164 | } | ||
165 | |||
166 | if (found_mic) | ||
167 | return 0; | ||
168 | |||
169 | /* support for older device tree - use cpu nodes */ | ||
170 | for_each_node_by_type(np, "cpu") { | ||
171 | const u32 *nid = get_property(np, "node-id", NULL); | ||
172 | if (!nid) { | ||
173 | printk(KERN_ERR "%s: node %s is missing node-id?\n", | ||
174 | __FUNCTION__, np->full_name); | ||
175 | continue; | ||
176 | } | ||
177 | cbe_ptcal_enable_on_node(*nid, order); | ||
178 | found_mic = 1; | ||
179 | } | ||
180 | |||
181 | return found_mic ? 0 : -ENODEV; | ||
182 | } | ||
183 | |||
184 | static int cbe_ptcal_disable(void) | ||
185 | { | ||
186 | struct ptcal_area *area, *tmp; | ||
187 | int ret = 0; | ||
188 | |||
189 | pr_debug("%s: disabling PTCAL\n", __FUNCTION__); | ||
190 | |||
191 | list_for_each_entry_safe(area, tmp, &ptcal_list, list) { | ||
192 | /* disable ptcal on this node */ | ||
193 | if (rtas_call(ptcal_stop_tok, 1, 1, NULL, area->nid)) { | ||
194 | printk(KERN_ERR "%s: error disabling PTCAL " | ||
195 | "on node %d!\n", __FUNCTION__, | ||
196 | area->nid); | ||
197 | ret = -EIO; | ||
198 | continue; | ||
199 | } | ||
200 | |||
201 | /* ensure we can access the PTCAL area */ | ||
202 | memset(page_address(area->pages), 0, | ||
203 | 1 << (area->order + PAGE_SHIFT)); | ||
204 | |||
205 | /* clean up */ | ||
206 | list_del(&area->list); | ||
207 | __free_pages(area->pages, area->order); | ||
208 | kfree(area); | ||
209 | } | ||
210 | |||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | static int cbe_ptcal_notify_reboot(struct notifier_block *nb, | ||
215 | unsigned long code, void *data) | ||
216 | { | ||
217 | return cbe_ptcal_disable(); | ||
218 | } | ||
219 | |||
220 | static struct notifier_block cbe_ptcal_reboot_notifier = { | ||
221 | .notifier_call = cbe_ptcal_notify_reboot | ||
222 | }; | ||
223 | |||
224 | int __init cbe_ptcal_init(void) | ||
225 | { | ||
226 | int ret; | ||
227 | ptcal_start_tok = rtas_token("ibm,cbe-start-ptcal"); | ||
228 | ptcal_stop_tok = rtas_token("ibm,cbe-stop-ptcal"); | ||
229 | |||
230 | if (ptcal_start_tok == RTAS_UNKNOWN_SERVICE | ||
231 | || ptcal_stop_tok == RTAS_UNKNOWN_SERVICE) | ||
232 | return -ENODEV; | ||
233 | |||
234 | ret = register_reboot_notifier(&cbe_ptcal_reboot_notifier); | ||
235 | if (ret) { | ||
236 | printk(KERN_ERR "Can't disable PTCAL, so not enabling\n"); | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | return cbe_ptcal_enable(); | ||
241 | } | ||
242 | |||
243 | arch_initcall(cbe_ptcal_init); | ||
244 | |||
85 | void __init cbe_ras_init(void) | 245 | void __init cbe_ras_init(void) |
86 | { | 246 | { |
87 | unsigned long hid0; | 247 | unsigned long hid0; |
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c index a5282011d39e..85a7c99c1003 100644 --- a/arch/powerpc/sysdev/pmi.c +++ b/arch/powerpc/sysdev/pmi.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <asm/of_platform.h> | 33 | #include <asm/of_platform.h> |
34 | #include <asm/io.h> | 34 | #include <asm/io.h> |
35 | #include <asm/pmi.h> | 35 | #include <asm/pmi.h> |
36 | 36 | #include <asm/prom.h> | |
37 | 37 | ||
38 | struct pmi_data { | 38 | struct pmi_data { |
39 | struct list_head handler; | 39 | struct list_head handler; |
@@ -49,21 +49,6 @@ struct pmi_data { | |||
49 | }; | 49 | }; |
50 | 50 | ||
51 | 51 | ||
52 | |||
53 | static void __iomem *of_iomap(struct device_node *np) | ||
54 | { | ||
55 | struct resource res; | ||
56 | |||
57 | if (of_address_to_resource(np, 0, &res)) | ||
58 | return NULL; | ||
59 | |||
60 | pr_debug("Resource start: 0x%lx\n", res.start); | ||
61 | pr_debug("Resource end: 0x%lx\n", res.end); | ||
62 | |||
63 | return ioremap(res.start, 1 + res.end - res.start); | ||
64 | } | ||
65 | |||
66 | |||
67 | static int pmi_irq_handler(int irq, void *dev_id) | 52 | static int pmi_irq_handler(int irq, void *dev_id) |
68 | { | 53 | { |
69 | struct pmi_data *data; | 54 | struct pmi_data *data; |
@@ -118,6 +103,7 @@ out: | |||
118 | 103 | ||
119 | static struct of_device_id pmi_match[] = { | 104 | static struct of_device_id pmi_match[] = { |
120 | { .type = "ibm,pmi", .name = "ibm,pmi" }, | 105 | { .type = "ibm,pmi", .name = "ibm,pmi" }, |
106 | { .type = "ibm,pmi" }, | ||
121 | {}, | 107 | {}, |
122 | }; | 108 | }; |
123 | 109 | ||
@@ -153,7 +139,7 @@ static int pmi_of_probe(struct of_device *dev, | |||
153 | goto out; | 139 | goto out; |
154 | } | 140 | } |
155 | 141 | ||
156 | data->pmi_reg = of_iomap(np); | 142 | data->pmi_reg = of_iomap(np, 0); |
157 | if (!data->pmi_reg) { | 143 | if (!data->pmi_reg) { |
158 | printk(KERN_ERR "pmi: invalid register address.\n"); | 144 | printk(KERN_ERR "pmi: invalid register address.\n"); |
159 | rc = -EFAULT; | 145 | rc = -EFAULT; |
@@ -279,6 +265,9 @@ void pmi_register_handler(struct of_device *device, | |||
279 | struct pmi_data *data; | 265 | struct pmi_data *data; |
280 | data = device->dev.driver_data; | 266 | data = device->dev.driver_data; |
281 | 267 | ||
268 | if (!data) | ||
269 | return; | ||
270 | |||
282 | spin_lock(&data->handler_spinlock); | 271 | spin_lock(&data->handler_spinlock); |
283 | list_add_tail(&handler->node, &data->handler); | 272 | list_add_tail(&handler->node, &data->handler); |
284 | spin_unlock(&data->handler_spinlock); | 273 | spin_unlock(&data->handler_spinlock); |
@@ -289,10 +278,12 @@ void pmi_unregister_handler(struct of_device *device, | |||
289 | struct pmi_handler *handler) | 278 | struct pmi_handler *handler) |
290 | { | 279 | { |
291 | struct pmi_data *data; | 280 | struct pmi_data *data; |
281 | data = device->dev.driver_data; | ||
292 | 282 | ||
293 | pr_debug("pmi: unregistering handler %p\n", handler); | 283 | if (!data) |
284 | return; | ||
294 | 285 | ||
295 | data = device->dev.driver_data; | 286 | pr_debug("pmi: unregistering handler %p\n", handler); |
296 | 287 | ||
297 | spin_lock(&data->handler_spinlock); | 288 | spin_lock(&data->handler_spinlock); |
298 | list_del(&handler->node); | 289 | list_del(&handler->node); |
diff --git a/include/asm-powerpc/cell-pmu.h b/include/asm-powerpc/cell-pmu.h index 35b95773746c..8066eede3a0c 100644 --- a/include/asm-powerpc/cell-pmu.h +++ b/include/asm-powerpc/cell-pmu.h | |||
@@ -97,11 +97,6 @@ extern void cbe_disable_pm_interrupts(u32 cpu); | |||
97 | extern u32 cbe_get_and_clear_pm_interrupts(u32 cpu); | 97 | extern u32 cbe_get_and_clear_pm_interrupts(u32 cpu); |
98 | extern void cbe_sync_irq(int node); | 98 | extern void cbe_sync_irq(int node); |
99 | 99 | ||
100 | /* Utility functions, macros */ | ||
101 | extern u32 cbe_get_hw_thread_id(int cpu); | ||
102 | |||
103 | #define cbe_cpu_to_node(cpu) ((cpu) >> 1) | ||
104 | |||
105 | #define CBE_COUNT_SUPERVISOR_MODE 0 | 100 | #define CBE_COUNT_SUPERVISOR_MODE 0 |
106 | #define CBE_COUNT_HYPERVISOR_MODE 1 | 101 | #define CBE_COUNT_HYPERVISOR_MODE 1 |
107 | #define CBE_COUNT_PROBLEM_MODE 2 | 102 | #define CBE_COUNT_PROBLEM_MODE 2 |
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index e73a2b482a15..f31af713e6a4 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <asm/irq.h> | 21 | #include <asm/irq.h> |
22 | #include <asm/atomic.h> | 22 | #include <asm/atomic.h> |
23 | #include <asm/io.h> | ||
23 | 24 | ||
24 | /* Definitions used by the flattened device tree */ | 25 | /* Definitions used by the flattened device tree */ |
25 | #define OF_DT_HEADER 0xd00dfeed /* marker */ | 26 | #define OF_DT_HEADER 0xd00dfeed /* marker */ |
@@ -355,6 +356,16 @@ static inline int of_irq_to_resource(struct device_node *dev, int index, struct | |||
355 | return irq; | 356 | return irq; |
356 | } | 357 | } |
357 | 358 | ||
359 | static inline void __iomem *of_iomap(struct device_node *np, int index) | ||
360 | { | ||
361 | struct resource res; | ||
362 | |||
363 | if (of_address_to_resource(np, index, &res)) | ||
364 | return NULL; | ||
365 | |||
366 | return ioremap(res.start, 1 + res.end - res.start); | ||
367 | } | ||
368 | |||
358 | 369 | ||
359 | #endif /* __KERNEL__ */ | 370 | #endif /* __KERNEL__ */ |
360 | #endif /* _POWERPC_PROM_H */ | 371 | #endif /* _POWERPC_PROM_H */ |