diff options
Diffstat (limited to 'arch/sparc/prom/misc_64.c')
-rw-r--r-- | arch/sparc/prom/misc_64.c | 314 |
1 files changed, 220 insertions, 94 deletions
diff --git a/arch/sparc/prom/misc_64.c b/arch/sparc/prom/misc_64.c index 39fc6af21b7c..6cb1581d6aef 100644 --- a/arch/sparc/prom/misc_64.c +++ b/arch/sparc/prom/misc_64.c | |||
@@ -20,10 +20,17 @@ | |||
20 | 20 | ||
21 | int prom_service_exists(const char *service_name) | 21 | int prom_service_exists(const char *service_name) |
22 | { | 22 | { |
23 | int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) | | 23 | unsigned long args[5]; |
24 | P1275_INOUT(1, 1), service_name); | ||
25 | 24 | ||
26 | if (err) | 25 | args[0] = (unsigned long) "test"; |
26 | args[1] = 1; | ||
27 | args[2] = 1; | ||
28 | args[3] = (unsigned long) service_name; | ||
29 | args[4] = (unsigned long) -1; | ||
30 | |||
31 | p1275_cmd_direct(args); | ||
32 | |||
33 | if (args[4]) | ||
27 | return 0; | 34 | return 0; |
28 | return 1; | 35 | return 1; |
29 | } | 36 | } |
@@ -31,30 +38,47 @@ int prom_service_exists(const char *service_name) | |||
31 | void prom_sun4v_guest_soft_state(void) | 38 | void prom_sun4v_guest_soft_state(void) |
32 | { | 39 | { |
33 | const char *svc = "SUNW,soft-state-supported"; | 40 | const char *svc = "SUNW,soft-state-supported"; |
41 | unsigned long args[3]; | ||
34 | 42 | ||
35 | if (!prom_service_exists(svc)) | 43 | if (!prom_service_exists(svc)) |
36 | return; | 44 | return; |
37 | p1275_cmd(svc, P1275_INOUT(0, 0)); | 45 | args[0] = (unsigned long) svc; |
46 | args[1] = 0; | ||
47 | args[2] = 0; | ||
48 | p1275_cmd_direct(args); | ||
38 | } | 49 | } |
39 | 50 | ||
40 | /* Reset and reboot the machine with the command 'bcommand'. */ | 51 | /* Reset and reboot the machine with the command 'bcommand'. */ |
41 | void prom_reboot(const char *bcommand) | 52 | void prom_reboot(const char *bcommand) |
42 | { | 53 | { |
54 | unsigned long args[4]; | ||
55 | |||
43 | #ifdef CONFIG_SUN_LDOMS | 56 | #ifdef CONFIG_SUN_LDOMS |
44 | if (ldom_domaining_enabled) | 57 | if (ldom_domaining_enabled) |
45 | ldom_reboot(bcommand); | 58 | ldom_reboot(bcommand); |
46 | #endif | 59 | #endif |
47 | p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) | | 60 | args[0] = (unsigned long) "boot"; |
48 | P1275_INOUT(1, 0), bcommand); | 61 | args[1] = 1; |
62 | args[2] = 0; | ||
63 | args[3] = (unsigned long) bcommand; | ||
64 | |||
65 | p1275_cmd_direct(args); | ||
49 | } | 66 | } |
50 | 67 | ||
51 | /* Forth evaluate the expression contained in 'fstring'. */ | 68 | /* Forth evaluate the expression contained in 'fstring'. */ |
52 | void prom_feval(const char *fstring) | 69 | void prom_feval(const char *fstring) |
53 | { | 70 | { |
71 | unsigned long args[5]; | ||
72 | |||
54 | if (!fstring || fstring[0] == 0) | 73 | if (!fstring || fstring[0] == 0) |
55 | return; | 74 | return; |
56 | p1275_cmd("interpret", P1275_ARG(0, P1275_ARG_IN_STRING) | | 75 | args[0] = (unsigned long) "interpret"; |
57 | P1275_INOUT(1, 1), fstring); | 76 | args[1] = 1; |
77 | args[2] = 1; | ||
78 | args[3] = (unsigned long) fstring; | ||
79 | args[4] = (unsigned long) -1; | ||
80 | |||
81 | p1275_cmd_direct(args); | ||
58 | } | 82 | } |
59 | EXPORT_SYMBOL(prom_feval); | 83 | EXPORT_SYMBOL(prom_feval); |
60 | 84 | ||
@@ -68,6 +92,7 @@ extern void smp_release(void); | |||
68 | */ | 92 | */ |
69 | void prom_cmdline(void) | 93 | void prom_cmdline(void) |
70 | { | 94 | { |
95 | unsigned long args[3]; | ||
71 | unsigned long flags; | 96 | unsigned long flags; |
72 | 97 | ||
73 | local_irq_save(flags); | 98 | local_irq_save(flags); |
@@ -76,7 +101,11 @@ void prom_cmdline(void) | |||
76 | smp_capture(); | 101 | smp_capture(); |
77 | #endif | 102 | #endif |
78 | 103 | ||
79 | p1275_cmd("enter", P1275_INOUT(0, 0)); | 104 | args[0] = (unsigned long) "enter"; |
105 | args[1] = 0; | ||
106 | args[2] = 0; | ||
107 | |||
108 | p1275_cmd_direct(args); | ||
80 | 109 | ||
81 | #ifdef CONFIG_SMP | 110 | #ifdef CONFIG_SMP |
82 | smp_release(); | 111 | smp_release(); |
@@ -90,22 +119,32 @@ void prom_cmdline(void) | |||
90 | */ | 119 | */ |
91 | void notrace prom_halt(void) | 120 | void notrace prom_halt(void) |
92 | { | 121 | { |
122 | unsigned long args[3]; | ||
123 | |||
93 | #ifdef CONFIG_SUN_LDOMS | 124 | #ifdef CONFIG_SUN_LDOMS |
94 | if (ldom_domaining_enabled) | 125 | if (ldom_domaining_enabled) |
95 | ldom_power_off(); | 126 | ldom_power_off(); |
96 | #endif | 127 | #endif |
97 | again: | 128 | again: |
98 | p1275_cmd("exit", P1275_INOUT(0, 0)); | 129 | args[0] = (unsigned long) "exit"; |
130 | args[1] = 0; | ||
131 | args[2] = 0; | ||
132 | p1275_cmd_direct(args); | ||
99 | goto again; /* PROM is out to get me -DaveM */ | 133 | goto again; /* PROM is out to get me -DaveM */ |
100 | } | 134 | } |
101 | 135 | ||
102 | void prom_halt_power_off(void) | 136 | void prom_halt_power_off(void) |
103 | { | 137 | { |
138 | unsigned long args[3]; | ||
139 | |||
104 | #ifdef CONFIG_SUN_LDOMS | 140 | #ifdef CONFIG_SUN_LDOMS |
105 | if (ldom_domaining_enabled) | 141 | if (ldom_domaining_enabled) |
106 | ldom_power_off(); | 142 | ldom_power_off(); |
107 | #endif | 143 | #endif |
108 | p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0)); | 144 | args[0] = (unsigned long) "SUNW,power-off"; |
145 | args[1] = 0; | ||
146 | args[2] = 0; | ||
147 | p1275_cmd_direct(args); | ||
109 | 148 | ||
110 | /* if nothing else helps, we just halt */ | 149 | /* if nothing else helps, we just halt */ |
111 | prom_halt(); | 150 | prom_halt(); |
@@ -114,10 +153,15 @@ void prom_halt_power_off(void) | |||
114 | /* Set prom sync handler to call function 'funcp'. */ | 153 | /* Set prom sync handler to call function 'funcp'. */ |
115 | void prom_setcallback(callback_func_t funcp) | 154 | void prom_setcallback(callback_func_t funcp) |
116 | { | 155 | { |
156 | unsigned long args[5]; | ||
117 | if (!funcp) | 157 | if (!funcp) |
118 | return; | 158 | return; |
119 | p1275_cmd("set-callback", P1275_ARG(0, P1275_ARG_IN_FUNCTION) | | 159 | args[0] = (unsigned long) "set-callback"; |
120 | P1275_INOUT(1, 1), funcp); | 160 | args[1] = 1; |
161 | args[2] = 1; | ||
162 | args[3] = (unsigned long) funcp; | ||
163 | args[4] = (unsigned long) -1; | ||
164 | p1275_cmd_direct(args); | ||
121 | } | 165 | } |
122 | 166 | ||
123 | /* Get the idprom and stuff it into buffer 'idbuf'. Returns the | 167 | /* Get the idprom and stuff it into buffer 'idbuf'. Returns the |
@@ -173,57 +217,61 @@ static int prom_get_memory_ihandle(void) | |||
173 | } | 217 | } |
174 | 218 | ||
175 | /* Load explicit I/D TLB entries. */ | 219 | /* Load explicit I/D TLB entries. */ |
220 | static long tlb_load(const char *type, unsigned long index, | ||
221 | unsigned long tte_data, unsigned long vaddr) | ||
222 | { | ||
223 | unsigned long args[9]; | ||
224 | |||
225 | args[0] = (unsigned long) prom_callmethod_name; | ||
226 | args[1] = 5; | ||
227 | args[2] = 1; | ||
228 | args[3] = (unsigned long) type; | ||
229 | args[4] = (unsigned int) prom_get_mmu_ihandle(); | ||
230 | args[5] = vaddr; | ||
231 | args[6] = tte_data; | ||
232 | args[7] = index; | ||
233 | args[8] = (unsigned long) -1; | ||
234 | |||
235 | p1275_cmd_direct(args); | ||
236 | |||
237 | return (long) args[8]; | ||
238 | } | ||
239 | |||
176 | long prom_itlb_load(unsigned long index, | 240 | long prom_itlb_load(unsigned long index, |
177 | unsigned long tte_data, | 241 | unsigned long tte_data, |
178 | unsigned long vaddr) | 242 | unsigned long vaddr) |
179 | { | 243 | { |
180 | return p1275_cmd(prom_callmethod_name, | 244 | return tlb_load("SUNW,itlb-load", index, tte_data, vaddr); |
181 | (P1275_ARG(0, P1275_ARG_IN_STRING) | | ||
182 | P1275_ARG(2, P1275_ARG_IN_64B) | | ||
183 | P1275_ARG(3, P1275_ARG_IN_64B) | | ||
184 | P1275_INOUT(5, 1)), | ||
185 | "SUNW,itlb-load", | ||
186 | prom_get_mmu_ihandle(), | ||
187 | /* And then our actual args are pushed backwards. */ | ||
188 | vaddr, | ||
189 | tte_data, | ||
190 | index); | ||
191 | } | 245 | } |
192 | 246 | ||
193 | long prom_dtlb_load(unsigned long index, | 247 | long prom_dtlb_load(unsigned long index, |
194 | unsigned long tte_data, | 248 | unsigned long tte_data, |
195 | unsigned long vaddr) | 249 | unsigned long vaddr) |
196 | { | 250 | { |
197 | return p1275_cmd(prom_callmethod_name, | 251 | return tlb_load("SUNW,dtlb-load", index, tte_data, vaddr); |
198 | (P1275_ARG(0, P1275_ARG_IN_STRING) | | ||
199 | P1275_ARG(2, P1275_ARG_IN_64B) | | ||
200 | P1275_ARG(3, P1275_ARG_IN_64B) | | ||
201 | P1275_INOUT(5, 1)), | ||
202 | "SUNW,dtlb-load", | ||
203 | prom_get_mmu_ihandle(), | ||
204 | /* And then our actual args are pushed backwards. */ | ||
205 | vaddr, | ||
206 | tte_data, | ||
207 | index); | ||
208 | } | 252 | } |
209 | 253 | ||
210 | int prom_map(int mode, unsigned long size, | 254 | int prom_map(int mode, unsigned long size, |
211 | unsigned long vaddr, unsigned long paddr) | 255 | unsigned long vaddr, unsigned long paddr) |
212 | { | 256 | { |
213 | int ret = p1275_cmd(prom_callmethod_name, | 257 | unsigned long args[11]; |
214 | (P1275_ARG(0, P1275_ARG_IN_STRING) | | 258 | int ret; |
215 | P1275_ARG(3, P1275_ARG_IN_64B) | | 259 | |
216 | P1275_ARG(4, P1275_ARG_IN_64B) | | 260 | args[0] = (unsigned long) prom_callmethod_name; |
217 | P1275_ARG(6, P1275_ARG_IN_64B) | | 261 | args[1] = 7; |
218 | P1275_INOUT(7, 1)), | 262 | args[2] = 1; |
219 | prom_map_name, | 263 | args[3] = (unsigned long) prom_map_name; |
220 | prom_get_mmu_ihandle(), | 264 | args[4] = (unsigned int) prom_get_mmu_ihandle(); |
221 | mode, | 265 | args[5] = (unsigned int) mode; |
222 | size, | 266 | args[6] = size; |
223 | vaddr, | 267 | args[7] = vaddr; |
224 | 0, | 268 | args[8] = 0; |
225 | paddr); | 269 | args[9] = paddr; |
226 | 270 | args[10] = (unsigned long) -1; | |
271 | |||
272 | p1275_cmd_direct(args); | ||
273 | |||
274 | ret = (int) args[10]; | ||
227 | if (ret == 0) | 275 | if (ret == 0) |
228 | ret = -1; | 276 | ret = -1; |
229 | return ret; | 277 | return ret; |
@@ -231,40 +279,51 @@ int prom_map(int mode, unsigned long size, | |||
231 | 279 | ||
232 | void prom_unmap(unsigned long size, unsigned long vaddr) | 280 | void prom_unmap(unsigned long size, unsigned long vaddr) |
233 | { | 281 | { |
234 | p1275_cmd(prom_callmethod_name, | 282 | unsigned long args[7]; |
235 | (P1275_ARG(0, P1275_ARG_IN_STRING) | | 283 | |
236 | P1275_ARG(2, P1275_ARG_IN_64B) | | 284 | args[0] = (unsigned long) prom_callmethod_name; |
237 | P1275_ARG(3, P1275_ARG_IN_64B) | | 285 | args[1] = 4; |
238 | P1275_INOUT(4, 0)), | 286 | args[2] = 0; |
239 | prom_unmap_name, | 287 | args[3] = (unsigned long) prom_unmap_name; |
240 | prom_get_mmu_ihandle(), | 288 | args[4] = (unsigned int) prom_get_mmu_ihandle(); |
241 | size, | 289 | args[5] = size; |
242 | vaddr); | 290 | args[6] = vaddr; |
291 | |||
292 | p1275_cmd_direct(args); | ||
243 | } | 293 | } |
244 | 294 | ||
245 | /* Set aside physical memory which is not touched or modified | 295 | /* Set aside physical memory which is not touched or modified |
246 | * across soft resets. | 296 | * across soft resets. |
247 | */ | 297 | */ |
248 | unsigned long prom_retain(const char *name, | 298 | int prom_retain(const char *name, unsigned long size, |
249 | unsigned long pa_low, unsigned long pa_high, | 299 | unsigned long align, unsigned long *paddr) |
250 | long size, long align) | ||
251 | { | 300 | { |
252 | /* XXX I don't think we return multiple values correctly. | 301 | unsigned long args[11]; |
253 | * XXX OBP supposedly returns pa_low/pa_high here, how does | 302 | |
254 | * XXX it work? | 303 | args[0] = (unsigned long) prom_callmethod_name; |
304 | args[1] = 5; | ||
305 | args[2] = 3; | ||
306 | args[3] = (unsigned long) "SUNW,retain"; | ||
307 | args[4] = (unsigned int) prom_get_memory_ihandle(); | ||
308 | args[5] = align; | ||
309 | args[6] = size; | ||
310 | args[7] = (unsigned long) name; | ||
311 | args[8] = (unsigned long) -1; | ||
312 | args[9] = (unsigned long) -1; | ||
313 | args[10] = (unsigned long) -1; | ||
314 | |||
315 | p1275_cmd_direct(args); | ||
316 | |||
317 | if (args[8]) | ||
318 | return (int) args[8]; | ||
319 | |||
320 | /* Next we get "phys_high" then "phys_low". On 64-bit | ||
321 | * the phys_high cell is don't care since the phys_low | ||
322 | * cell has the full value. | ||
255 | */ | 323 | */ |
324 | *paddr = args[10]; | ||
256 | 325 | ||
257 | /* If align is zero, the pa_low/pa_high args are passed, | 326 | return 0; |
258 | * else they are not. | ||
259 | */ | ||
260 | if (align == 0) | ||
261 | return p1275_cmd("SUNW,retain", | ||
262 | (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 2)), | ||
263 | name, pa_low, pa_high, size, align); | ||
264 | else | ||
265 | return p1275_cmd("SUNW,retain", | ||
266 | (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(3, 2)), | ||
267 | name, size, align); | ||
268 | } | 327 | } |
269 | 328 | ||
270 | /* Get "Unumber" string for the SIMM at the given | 329 | /* Get "Unumber" string for the SIMM at the given |
@@ -277,62 +336,129 @@ int prom_getunumber(int syndrome_code, | |||
277 | unsigned long phys_addr, | 336 | unsigned long phys_addr, |
278 | char *buf, int buflen) | 337 | char *buf, int buflen) |
279 | { | 338 | { |
280 | return p1275_cmd(prom_callmethod_name, | 339 | unsigned long args[12]; |
281 | (P1275_ARG(0, P1275_ARG_IN_STRING) | | 340 | |
282 | P1275_ARG(3, P1275_ARG_OUT_BUF) | | 341 | args[0] = (unsigned long) prom_callmethod_name; |
283 | P1275_ARG(6, P1275_ARG_IN_64B) | | 342 | args[1] = 7; |
284 | P1275_INOUT(8, 2)), | 343 | args[2] = 2; |
285 | "SUNW,get-unumber", prom_get_memory_ihandle(), | 344 | args[3] = (unsigned long) "SUNW,get-unumber"; |
286 | buflen, buf, P1275_SIZE(buflen), | 345 | args[4] = (unsigned int) prom_get_memory_ihandle(); |
287 | 0, phys_addr, syndrome_code); | 346 | args[5] = buflen; |
347 | args[6] = (unsigned long) buf; | ||
348 | args[7] = 0; | ||
349 | args[8] = phys_addr; | ||
350 | args[9] = (unsigned int) syndrome_code; | ||
351 | args[10] = (unsigned long) -1; | ||
352 | args[11] = (unsigned long) -1; | ||
353 | |||
354 | p1275_cmd_direct(args); | ||
355 | |||
356 | return (int) args[10]; | ||
288 | } | 357 | } |
289 | 358 | ||
290 | /* Power management extensions. */ | 359 | /* Power management extensions. */ |
291 | void prom_sleepself(void) | 360 | void prom_sleepself(void) |
292 | { | 361 | { |
293 | p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0)); | 362 | unsigned long args[3]; |
363 | |||
364 | args[0] = (unsigned long) "SUNW,sleep-self"; | ||
365 | args[1] = 0; | ||
366 | args[2] = 0; | ||
367 | p1275_cmd_direct(args); | ||
294 | } | 368 | } |
295 | 369 | ||
296 | int prom_sleepsystem(void) | 370 | int prom_sleepsystem(void) |
297 | { | 371 | { |
298 | return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1)); | 372 | unsigned long args[4]; |
373 | |||
374 | args[0] = (unsigned long) "SUNW,sleep-system"; | ||
375 | args[1] = 0; | ||
376 | args[2] = 1; | ||
377 | args[3] = (unsigned long) -1; | ||
378 | p1275_cmd_direct(args); | ||
379 | |||
380 | return (int) args[3]; | ||
299 | } | 381 | } |
300 | 382 | ||
301 | int prom_wakeupsystem(void) | 383 | int prom_wakeupsystem(void) |
302 | { | 384 | { |
303 | return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1)); | 385 | unsigned long args[4]; |
386 | |||
387 | args[0] = (unsigned long) "SUNW,wakeup-system"; | ||
388 | args[1] = 0; | ||
389 | args[2] = 1; | ||
390 | args[3] = (unsigned long) -1; | ||
391 | p1275_cmd_direct(args); | ||
392 | |||
393 | return (int) args[3]; | ||
304 | } | 394 | } |
305 | 395 | ||
306 | #ifdef CONFIG_SMP | 396 | #ifdef CONFIG_SMP |
307 | void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg) | 397 | void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg) |
308 | { | 398 | { |
309 | p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, arg); | 399 | unsigned long args[6]; |
400 | |||
401 | args[0] = (unsigned long) "SUNW,start-cpu"; | ||
402 | args[1] = 3; | ||
403 | args[2] = 0; | ||
404 | args[3] = (unsigned int) cpunode; | ||
405 | args[4] = pc; | ||
406 | args[5] = arg; | ||
407 | p1275_cmd_direct(args); | ||
310 | } | 408 | } |
311 | 409 | ||
312 | void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg) | 410 | void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg) |
313 | { | 411 | { |
314 | p1275_cmd("SUNW,start-cpu-by-cpuid", P1275_INOUT(3, 0), | 412 | unsigned long args[6]; |
315 | cpuid, pc, arg); | 413 | |
414 | args[0] = (unsigned long) "SUNW,start-cpu-by-cpuid"; | ||
415 | args[1] = 3; | ||
416 | args[2] = 0; | ||
417 | args[3] = (unsigned int) cpuid; | ||
418 | args[4] = pc; | ||
419 | args[5] = arg; | ||
420 | p1275_cmd_direct(args); | ||
316 | } | 421 | } |
317 | 422 | ||
318 | void prom_stopcpu_cpuid(int cpuid) | 423 | void prom_stopcpu_cpuid(int cpuid) |
319 | { | 424 | { |
320 | p1275_cmd("SUNW,stop-cpu-by-cpuid", P1275_INOUT(1, 0), | 425 | unsigned long args[4]; |
321 | cpuid); | 426 | |
427 | args[0] = (unsigned long) "SUNW,stop-cpu-by-cpuid"; | ||
428 | args[1] = 1; | ||
429 | args[2] = 0; | ||
430 | args[3] = (unsigned int) cpuid; | ||
431 | p1275_cmd_direct(args); | ||
322 | } | 432 | } |
323 | 433 | ||
324 | void prom_stopself(void) | 434 | void prom_stopself(void) |
325 | { | 435 | { |
326 | p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0)); | 436 | unsigned long args[3]; |
437 | |||
438 | args[0] = (unsigned long) "SUNW,stop-self"; | ||
439 | args[1] = 0; | ||
440 | args[2] = 0; | ||
441 | p1275_cmd_direct(args); | ||
327 | } | 442 | } |
328 | 443 | ||
329 | void prom_idleself(void) | 444 | void prom_idleself(void) |
330 | { | 445 | { |
331 | p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0)); | 446 | unsigned long args[3]; |
447 | |||
448 | args[0] = (unsigned long) "SUNW,idle-self"; | ||
449 | args[1] = 0; | ||
450 | args[2] = 0; | ||
451 | p1275_cmd_direct(args); | ||
332 | } | 452 | } |
333 | 453 | ||
334 | void prom_resumecpu(int cpunode) | 454 | void prom_resumecpu(int cpunode) |
335 | { | 455 | { |
336 | p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode); | 456 | unsigned long args[4]; |
457 | |||
458 | args[0] = (unsigned long) "SUNW,resume-cpu"; | ||
459 | args[1] = 1; | ||
460 | args[2] = 0; | ||
461 | args[3] = (unsigned int) cpunode; | ||
462 | p1275_cmd_direct(args); | ||
337 | } | 463 | } |
338 | #endif | 464 | #endif |