1 /* $Id: misc.c,v 1.19 2000/06/30 10:18:38 davem Exp $
2 * misc.c: Miscellaneous prom functions that don't belong
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
9 #include <linux/config.h>
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/interrupt.h>
14 #include <linux/delay.h>
15 #include <asm/openprom.h>
16 #include <asm/oplib.h>
18 /* Reset and reboot the machine with the command 'bcommand'. */
20 prom_reboot(char *bcommand
)
22 p1275_cmd ("boot", P1275_ARG(0,P1275_ARG_IN_STRING
)|
23 P1275_INOUT(1,0), bcommand
);
26 /* Forth evaluate the expression contained in 'fstring'. */
28 prom_feval(char *fstring
)
30 if(!fstring
|| fstring
[0] == 0)
32 p1275_cmd ("interpret", P1275_ARG(0,P1275_ARG_IN_STRING
)|
33 P1275_INOUT(1,1), fstring
);
36 /* We want to do this more nicely some day. */
37 #ifdef CONFIG_SUN_CONSOLE
38 extern void (*prom_palette
)(int);
39 extern int serial_console
;
43 extern void smp_capture(void);
44 extern void smp_release(void);
47 /* Drop into the prom, with the chance to continue with the 'go'
55 __save_and_cli(flags
);
57 #ifdef CONFIG_SUN_CONSOLE
58 if(!serial_console
&& prom_palette
)
62 /* We always arrive here via a serial interrupt.
63 * So in order for everything to work reliably, even
64 * on SMP, we need to drop the IRQ locks we hold.
67 irq_exit(smp_processor_id(), 0);
70 local_irq_count(smp_processor_id())--;
73 p1275_cmd ("enter", P1275_INOUT(0,0));
77 irq_enter(smp_processor_id(), 0);
78 spin_unlock_wait(&__br_write_locks
[BR_GLOBALIRQ_LOCK
].lock
);
80 local_irq_count(smp_processor_id())++;
83 #ifdef CONFIG_SUN_CONSOLE
84 if(!serial_console
&& prom_palette
)
88 __restore_flags(flags
);
92 extern void smp_promstop_others(void);
95 /* Drop into the prom, but completely terminate the program.
96 * No chance of continuing.
102 smp_promstop_others();
106 p1275_cmd ("exit", P1275_INOUT(0,0));
107 goto again
; /* PROM is out to get me -DaveM */
110 /* Set prom sync handler to call function 'funcp'. */
112 prom_setcallback(callback_func_t funcp
)
115 p1275_cmd ("set-callback", P1275_ARG(0,P1275_ARG_IN_FUNCTION
)|
116 P1275_INOUT(1,1), funcp
);
119 /* Get the idprom and stuff it into buffer 'idbuf'. Returns the
120 * format type. 'num_bytes' is the number of bytes that your idbuf
121 * has space for. Returns 0xff on error.
124 prom_get_idprom(char *idbuf
, int num_bytes
)
128 len
= prom_getproplen(prom_root_node
, "idprom");
129 if((len
>num_bytes
) || (len
==-1)) return 0xff;
130 if(!prom_getproperty(prom_root_node
, "idprom", idbuf
, num_bytes
))
136 /* Get the major prom version number. */
143 /* Get the prom plugin-revision. */
150 /* Get the prom firmware print revision. */
157 /* Install Linux trap table so PROM uses that instead of it's own. */
158 void prom_set_trap_table(unsigned long tba
)
160 p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba
);
163 int mmu_ihandle_cache
= 0;
165 int prom_get_mmu_ihandle(void)
169 if (mmu_ihandle_cache
!= 0)
170 return mmu_ihandle_cache
;
172 node
= prom_finddevice("/chosen");
173 ret
= prom_getint(node
, "mmu");
174 if(ret
== -1 || ret
== 0)
175 mmu_ihandle_cache
= -1;
177 mmu_ihandle_cache
= ret
;
182 static int prom_get_memory_ihandle(void)
184 static int memory_ihandle_cache
= 0;
187 if (memory_ihandle_cache
!= 0)
188 return memory_ihandle_cache
;
190 node
= prom_finddevice("/chosen");
191 ret
= prom_getint(node
, "memory");
192 if (ret
== -1 || ret
== 0)
193 memory_ihandle_cache
= -1;
195 memory_ihandle_cache
= ret
;
200 /* Load explicit I/D TLB entries. */
201 long prom_itlb_load(unsigned long index
,
202 unsigned long tte_data
,
205 return p1275_cmd("call-method",
206 (P1275_ARG(0, P1275_ARG_IN_STRING
) |
207 P1275_ARG(2, P1275_ARG_IN_64B
) |
208 P1275_ARG(3, P1275_ARG_IN_64B
) |
211 prom_get_mmu_ihandle(),
212 /* And then our actual args are pushed backwards. */
218 long prom_dtlb_load(unsigned long index
,
219 unsigned long tte_data
,
222 return p1275_cmd("call-method",
223 (P1275_ARG(0, P1275_ARG_IN_STRING
) |
224 P1275_ARG(2, P1275_ARG_IN_64B
) |
225 P1275_ARG(3, P1275_ARG_IN_64B
) |
228 prom_get_mmu_ihandle(),
229 /* And then our actual args are pushed backwards. */
235 int prom_map(int mode
, unsigned long size
,
236 unsigned long vaddr
, unsigned long paddr
)
238 int ret
= p1275_cmd("call-method",
239 (P1275_ARG(0, P1275_ARG_IN_STRING
) |
240 P1275_ARG(3, P1275_ARG_IN_64B
) |
241 P1275_ARG(4, P1275_ARG_IN_64B
) |
242 P1275_ARG(6, P1275_ARG_IN_64B
) |
245 prom_get_mmu_ihandle(),
257 void prom_unmap(unsigned long size
, unsigned long vaddr
)
259 p1275_cmd("call-method",
260 (P1275_ARG(0, P1275_ARG_IN_STRING
) |
261 P1275_ARG(2, P1275_ARG_IN_64B
) |
262 P1275_ARG(3, P1275_ARG_IN_64B
) |
265 prom_get_mmu_ihandle(),
270 /* Set aside physical memory which is not touched or modified
271 * across soft resets.
273 unsigned long prom_retain(char *name
,
274 unsigned long pa_low
, unsigned long pa_high
,
275 long size
, long align
)
277 /* XXX I don't think we return multiple values correctly.
278 * XXX OBP supposedly returns pa_low/pa_high here, how does
282 /* If align is zero, the pa_low/pa_high args are passed,
286 return p1275_cmd("SUNW,retain",
287 (P1275_ARG(0, P1275_ARG_IN_BUF
) | P1275_INOUT(5, 2)),
288 name
, pa_low
, pa_high
, size
, align
);
290 return p1275_cmd("SUNW,retain",
291 (P1275_ARG(0, P1275_ARG_IN_BUF
) | P1275_INOUT(3, 2)),
295 /* Get "Unumber" string for the SIMM at the given
296 * memory address. Usually this will be of the form
297 * "Uxxxx" where xxxx is a decimal number which is
298 * etched into the motherboard next to the SIMM slot
301 int prom_getunumber(int syndrome_code
,
302 unsigned long phys_addr
,
303 char *buf
, int buflen
)
305 return p1275_cmd("call-method",
306 (P1275_ARG(0, P1275_ARG_IN_STRING
) |
307 P1275_ARG(3, P1275_ARG_OUT_BUF
) |
308 P1275_ARG(6, P1275_ARG_IN_64B
) |
310 "SUNW,get-unumber", prom_get_memory_ihandle(),
311 buflen
, buf
, P1275_SIZE(buflen
),
312 0, phys_addr
, syndrome_code
);
315 /* Power management extensions. */
316 void prom_sleepself(void)
318 p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0));
321 int prom_sleepsystem(void)
323 return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1));
326 int prom_wakeupsystem(void)
328 return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1));
332 void prom_startcpu(int cpunode
, unsigned long pc
, unsigned long o0
)
334 p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode
, pc
, o0
);
337 void prom_stopself(void)
339 p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0));
342 void prom_idleself(void)
344 p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0));
347 void prom_resumecpu(int cpunode
)
349 p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode
);