Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sparc/prom/misc_64.c
10817 views
1
/*
2
* misc.c: Miscellaneous prom functions that don't belong
3
* anywhere else.
4
*
5
* Copyright (C) 1995 David S. Miller ([email protected])
6
* Copyright (C) 1996,1997 Jakub Jelinek ([email protected])
7
*/
8
9
#include <linux/types.h>
10
#include <linux/kernel.h>
11
#include <linux/sched.h>
12
#include <linux/interrupt.h>
13
#include <linux/delay.h>
14
#include <linux/module.h>
15
16
#include <asm/openprom.h>
17
#include <asm/oplib.h>
18
#include <asm/system.h>
19
#include <asm/ldc.h>
20
21
static int prom_service_exists(const char *service_name)
22
{
23
unsigned long args[5];
24
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])
34
return 0;
35
return 1;
36
}
37
38
void prom_sun4v_guest_soft_state(void)
39
{
40
const char *svc = "SUNW,soft-state-supported";
41
unsigned long args[3];
42
43
if (!prom_service_exists(svc))
44
return;
45
args[0] = (unsigned long) svc;
46
args[1] = 0;
47
args[2] = 0;
48
p1275_cmd_direct(args);
49
}
50
51
/* Reset and reboot the machine with the command 'bcommand'. */
52
void prom_reboot(const char *bcommand)
53
{
54
unsigned long args[4];
55
56
#ifdef CONFIG_SUN_LDOMS
57
if (ldom_domaining_enabled)
58
ldom_reboot(bcommand);
59
#endif
60
args[0] = (unsigned long) "boot";
61
args[1] = 1;
62
args[2] = 0;
63
args[3] = (unsigned long) bcommand;
64
65
p1275_cmd_direct(args);
66
}
67
68
/* Forth evaluate the expression contained in 'fstring'. */
69
void prom_feval(const char *fstring)
70
{
71
unsigned long args[5];
72
73
if (!fstring || fstring[0] == 0)
74
return;
75
args[0] = (unsigned long) "interpret";
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);
82
}
83
EXPORT_SYMBOL(prom_feval);
84
85
#ifdef CONFIG_SMP
86
extern void smp_capture(void);
87
extern void smp_release(void);
88
#endif
89
90
/* Drop into the prom, with the chance to continue with the 'go'
91
* prom command.
92
*/
93
void prom_cmdline(void)
94
{
95
unsigned long args[3];
96
unsigned long flags;
97
98
local_irq_save(flags);
99
100
#ifdef CONFIG_SMP
101
smp_capture();
102
#endif
103
104
args[0] = (unsigned long) "enter";
105
args[1] = 0;
106
args[2] = 0;
107
108
p1275_cmd_direct(args);
109
110
#ifdef CONFIG_SMP
111
smp_release();
112
#endif
113
114
local_irq_restore(flags);
115
}
116
117
/* Drop into the prom, but completely terminate the program.
118
* No chance of continuing.
119
*/
120
void notrace prom_halt(void)
121
{
122
unsigned long args[3];
123
124
#ifdef CONFIG_SUN_LDOMS
125
if (ldom_domaining_enabled)
126
ldom_power_off();
127
#endif
128
again:
129
args[0] = (unsigned long) "exit";
130
args[1] = 0;
131
args[2] = 0;
132
p1275_cmd_direct(args);
133
goto again; /* PROM is out to get me -DaveM */
134
}
135
136
void prom_halt_power_off(void)
137
{
138
unsigned long args[3];
139
140
#ifdef CONFIG_SUN_LDOMS
141
if (ldom_domaining_enabled)
142
ldom_power_off();
143
#endif
144
args[0] = (unsigned long) "SUNW,power-off";
145
args[1] = 0;
146
args[2] = 0;
147
p1275_cmd_direct(args);
148
149
/* if nothing else helps, we just halt */
150
prom_halt();
151
}
152
153
/* Get the idprom and stuff it into buffer 'idbuf'. Returns the
154
* format type. 'num_bytes' is the number of bytes that your idbuf
155
* has space for. Returns 0xff on error.
156
*/
157
unsigned char prom_get_idprom(char *idbuf, int num_bytes)
158
{
159
int len;
160
161
len = prom_getproplen(prom_root_node, "idprom");
162
if ((len >num_bytes) || (len == -1))
163
return 0xff;
164
if (!prom_getproperty(prom_root_node, "idprom", idbuf, num_bytes))
165
return idbuf[0];
166
167
return 0xff;
168
}
169
170
int prom_get_mmu_ihandle(void)
171
{
172
phandle node;
173
int ret;
174
175
if (prom_mmu_ihandle_cache != 0)
176
return prom_mmu_ihandle_cache;
177
178
node = prom_finddevice(prom_chosen_path);
179
ret = prom_getint(node, prom_mmu_name);
180
if (ret == -1 || ret == 0)
181
prom_mmu_ihandle_cache = -1;
182
else
183
prom_mmu_ihandle_cache = ret;
184
185
return ret;
186
}
187
188
static int prom_get_memory_ihandle(void)
189
{
190
static int memory_ihandle_cache;
191
phandle node;
192
int ret;
193
194
if (memory_ihandle_cache != 0)
195
return memory_ihandle_cache;
196
197
node = prom_finddevice("/chosen");
198
ret = prom_getint(node, "memory");
199
if (ret == -1 || ret == 0)
200
memory_ihandle_cache = -1;
201
else
202
memory_ihandle_cache = ret;
203
204
return ret;
205
}
206
207
/* Load explicit I/D TLB entries. */
208
static long tlb_load(const char *type, unsigned long index,
209
unsigned long tte_data, unsigned long vaddr)
210
{
211
unsigned long args[9];
212
213
args[0] = (unsigned long) prom_callmethod_name;
214
args[1] = 5;
215
args[2] = 1;
216
args[3] = (unsigned long) type;
217
args[4] = (unsigned int) prom_get_mmu_ihandle();
218
args[5] = vaddr;
219
args[6] = tte_data;
220
args[7] = index;
221
args[8] = (unsigned long) -1;
222
223
p1275_cmd_direct(args);
224
225
return (long) args[8];
226
}
227
228
long prom_itlb_load(unsigned long index,
229
unsigned long tte_data,
230
unsigned long vaddr)
231
{
232
return tlb_load("SUNW,itlb-load", index, tte_data, vaddr);
233
}
234
235
long prom_dtlb_load(unsigned long index,
236
unsigned long tte_data,
237
unsigned long vaddr)
238
{
239
return tlb_load("SUNW,dtlb-load", index, tte_data, vaddr);
240
}
241
242
int prom_map(int mode, unsigned long size,
243
unsigned long vaddr, unsigned long paddr)
244
{
245
unsigned long args[11];
246
int ret;
247
248
args[0] = (unsigned long) prom_callmethod_name;
249
args[1] = 7;
250
args[2] = 1;
251
args[3] = (unsigned long) prom_map_name;
252
args[4] = (unsigned int) prom_get_mmu_ihandle();
253
args[5] = (unsigned int) mode;
254
args[6] = size;
255
args[7] = vaddr;
256
args[8] = 0;
257
args[9] = paddr;
258
args[10] = (unsigned long) -1;
259
260
p1275_cmd_direct(args);
261
262
ret = (int) args[10];
263
if (ret == 0)
264
ret = -1;
265
return ret;
266
}
267
268
void prom_unmap(unsigned long size, unsigned long vaddr)
269
{
270
unsigned long args[7];
271
272
args[0] = (unsigned long) prom_callmethod_name;
273
args[1] = 4;
274
args[2] = 0;
275
args[3] = (unsigned long) prom_unmap_name;
276
args[4] = (unsigned int) prom_get_mmu_ihandle();
277
args[5] = size;
278
args[6] = vaddr;
279
280
p1275_cmd_direct(args);
281
}
282
283
/* Set aside physical memory which is not touched or modified
284
* across soft resets.
285
*/
286
int prom_retain(const char *name, unsigned long size,
287
unsigned long align, unsigned long *paddr)
288
{
289
unsigned long args[11];
290
291
args[0] = (unsigned long) prom_callmethod_name;
292
args[1] = 5;
293
args[2] = 3;
294
args[3] = (unsigned long) "SUNW,retain";
295
args[4] = (unsigned int) prom_get_memory_ihandle();
296
args[5] = align;
297
args[6] = size;
298
args[7] = (unsigned long) name;
299
args[8] = (unsigned long) -1;
300
args[9] = (unsigned long) -1;
301
args[10] = (unsigned long) -1;
302
303
p1275_cmd_direct(args);
304
305
if (args[8])
306
return (int) args[8];
307
308
/* Next we get "phys_high" then "phys_low". On 64-bit
309
* the phys_high cell is don't care since the phys_low
310
* cell has the full value.
311
*/
312
*paddr = args[10];
313
314
return 0;
315
}
316
317
/* Get "Unumber" string for the SIMM at the given
318
* memory address. Usually this will be of the form
319
* "Uxxxx" where xxxx is a decimal number which is
320
* etched into the motherboard next to the SIMM slot
321
* in question.
322
*/
323
int prom_getunumber(int syndrome_code,
324
unsigned long phys_addr,
325
char *buf, int buflen)
326
{
327
unsigned long args[12];
328
329
args[0] = (unsigned long) prom_callmethod_name;
330
args[1] = 7;
331
args[2] = 2;
332
args[3] = (unsigned long) "SUNW,get-unumber";
333
args[4] = (unsigned int) prom_get_memory_ihandle();
334
args[5] = buflen;
335
args[6] = (unsigned long) buf;
336
args[7] = 0;
337
args[8] = phys_addr;
338
args[9] = (unsigned int) syndrome_code;
339
args[10] = (unsigned long) -1;
340
args[11] = (unsigned long) -1;
341
342
p1275_cmd_direct(args);
343
344
return (int) args[10];
345
}
346
347
/* Power management extensions. */
348
void prom_sleepself(void)
349
{
350
unsigned long args[3];
351
352
args[0] = (unsigned long) "SUNW,sleep-self";
353
args[1] = 0;
354
args[2] = 0;
355
p1275_cmd_direct(args);
356
}
357
358
int prom_sleepsystem(void)
359
{
360
unsigned long args[4];
361
362
args[0] = (unsigned long) "SUNW,sleep-system";
363
args[1] = 0;
364
args[2] = 1;
365
args[3] = (unsigned long) -1;
366
p1275_cmd_direct(args);
367
368
return (int) args[3];
369
}
370
371
int prom_wakeupsystem(void)
372
{
373
unsigned long args[4];
374
375
args[0] = (unsigned long) "SUNW,wakeup-system";
376
args[1] = 0;
377
args[2] = 1;
378
args[3] = (unsigned long) -1;
379
p1275_cmd_direct(args);
380
381
return (int) args[3];
382
}
383
384
#ifdef CONFIG_SMP
385
void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg)
386
{
387
unsigned long args[6];
388
389
args[0] = (unsigned long) "SUNW,start-cpu";
390
args[1] = 3;
391
args[2] = 0;
392
args[3] = (unsigned int) cpunode;
393
args[4] = pc;
394
args[5] = arg;
395
p1275_cmd_direct(args);
396
}
397
398
void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg)
399
{
400
unsigned long args[6];
401
402
args[0] = (unsigned long) "SUNW,start-cpu-by-cpuid";
403
args[1] = 3;
404
args[2] = 0;
405
args[3] = (unsigned int) cpuid;
406
args[4] = pc;
407
args[5] = arg;
408
p1275_cmd_direct(args);
409
}
410
411
void prom_stopcpu_cpuid(int cpuid)
412
{
413
unsigned long args[4];
414
415
args[0] = (unsigned long) "SUNW,stop-cpu-by-cpuid";
416
args[1] = 1;
417
args[2] = 0;
418
args[3] = (unsigned int) cpuid;
419
p1275_cmd_direct(args);
420
}
421
422
void prom_stopself(void)
423
{
424
unsigned long args[3];
425
426
args[0] = (unsigned long) "SUNW,stop-self";
427
args[1] = 0;
428
args[2] = 0;
429
p1275_cmd_direct(args);
430
}
431
432
void prom_idleself(void)
433
{
434
unsigned long args[3];
435
436
args[0] = (unsigned long) "SUNW,idle-self";
437
args[1] = 0;
438
args[2] = 0;
439
p1275_cmd_direct(args);
440
}
441
442
void prom_resumecpu(int cpunode)
443
{
444
unsigned long args[4];
445
446
args[0] = (unsigned long) "SUNW,resume-cpu";
447
args[1] = 1;
448
args[2] = 0;
449
args[3] = (unsigned int) cpunode;
450
p1275_cmd_direct(args);
451
}
452
#endif
453
454