0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/types.h>
0011 #include <linux/kernel.h>
0012 #include <linux/sched.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/delay.h>
0015 #include <linux/module.h>
0016
0017 #include <asm/openprom.h>
0018 #include <asm/oplib.h>
0019 #include <asm/ldc.h>
0020
0021 static int prom_service_exists(const char *service_name)
0022 {
0023 unsigned long args[5];
0024
0025 args[0] = (unsigned long) "test";
0026 args[1] = 1;
0027 args[2] = 1;
0028 args[3] = (unsigned long) service_name;
0029 args[4] = (unsigned long) -1;
0030
0031 p1275_cmd_direct(args);
0032
0033 if (args[4])
0034 return 0;
0035 return 1;
0036 }
0037
0038 void prom_sun4v_guest_soft_state(void)
0039 {
0040 const char *svc = "SUNW,soft-state-supported";
0041 unsigned long args[3];
0042
0043 if (!prom_service_exists(svc))
0044 return;
0045 args[0] = (unsigned long) svc;
0046 args[1] = 0;
0047 args[2] = 0;
0048 p1275_cmd_direct(args);
0049 }
0050
0051
0052 void prom_reboot(const char *bcommand)
0053 {
0054 unsigned long args[4];
0055
0056 #ifdef CONFIG_SUN_LDOMS
0057 if (ldom_domaining_enabled)
0058 ldom_reboot(bcommand);
0059 #endif
0060 args[0] = (unsigned long) "boot";
0061 args[1] = 1;
0062 args[2] = 0;
0063 args[3] = (unsigned long) bcommand;
0064
0065 p1275_cmd_direct(args);
0066 }
0067
0068
0069 void prom_feval(const char *fstring)
0070 {
0071 unsigned long args[5];
0072
0073 if (!fstring || fstring[0] == 0)
0074 return;
0075 args[0] = (unsigned long) "interpret";
0076 args[1] = 1;
0077 args[2] = 1;
0078 args[3] = (unsigned long) fstring;
0079 args[4] = (unsigned long) -1;
0080
0081 p1275_cmd_direct(args);
0082 }
0083 EXPORT_SYMBOL(prom_feval);
0084
0085
0086
0087
0088 void prom_cmdline(void)
0089 {
0090 unsigned long args[3];
0091 unsigned long flags;
0092
0093 local_irq_save(flags);
0094
0095 #ifdef CONFIG_SMP
0096 smp_capture();
0097 #endif
0098
0099 args[0] = (unsigned long) "enter";
0100 args[1] = 0;
0101 args[2] = 0;
0102
0103 p1275_cmd_direct(args);
0104
0105 #ifdef CONFIG_SMP
0106 smp_release();
0107 #endif
0108
0109 local_irq_restore(flags);
0110 }
0111
0112
0113
0114
0115 void notrace prom_halt(void)
0116 {
0117 unsigned long args[3];
0118
0119 #ifdef CONFIG_SUN_LDOMS
0120 if (ldom_domaining_enabled)
0121 ldom_power_off();
0122 #endif
0123 again:
0124 args[0] = (unsigned long) "exit";
0125 args[1] = 0;
0126 args[2] = 0;
0127 p1275_cmd_direct(args);
0128 goto again;
0129 }
0130
0131 void prom_halt_power_off(void)
0132 {
0133 unsigned long args[3];
0134
0135 #ifdef CONFIG_SUN_LDOMS
0136 if (ldom_domaining_enabled)
0137 ldom_power_off();
0138 #endif
0139 args[0] = (unsigned long) "SUNW,power-off";
0140 args[1] = 0;
0141 args[2] = 0;
0142 p1275_cmd_direct(args);
0143
0144
0145 prom_halt();
0146 }
0147
0148
0149
0150
0151
0152 unsigned char prom_get_idprom(char *idbuf, int num_bytes)
0153 {
0154 int len;
0155
0156 len = prom_getproplen(prom_root_node, "idprom");
0157 if ((len >num_bytes) || (len == -1))
0158 return 0xff;
0159 if (!prom_getproperty(prom_root_node, "idprom", idbuf, num_bytes))
0160 return idbuf[0];
0161
0162 return 0xff;
0163 }
0164
0165 int prom_get_mmu_ihandle(void)
0166 {
0167 phandle node;
0168 int ret;
0169
0170 if (prom_mmu_ihandle_cache != 0)
0171 return prom_mmu_ihandle_cache;
0172
0173 node = prom_finddevice(prom_chosen_path);
0174 ret = prom_getint(node, prom_mmu_name);
0175 if (ret == -1 || ret == 0)
0176 prom_mmu_ihandle_cache = -1;
0177 else
0178 prom_mmu_ihandle_cache = ret;
0179
0180 return ret;
0181 }
0182
0183 static int prom_get_memory_ihandle(void)
0184 {
0185 static int memory_ihandle_cache;
0186 phandle node;
0187 int ret;
0188
0189 if (memory_ihandle_cache != 0)
0190 return memory_ihandle_cache;
0191
0192 node = prom_finddevice("/chosen");
0193 ret = prom_getint(node, "memory");
0194 if (ret == -1 || ret == 0)
0195 memory_ihandle_cache = -1;
0196 else
0197 memory_ihandle_cache = ret;
0198
0199 return ret;
0200 }
0201
0202
0203 static long tlb_load(const char *type, unsigned long index,
0204 unsigned long tte_data, unsigned long vaddr)
0205 {
0206 unsigned long args[9];
0207
0208 args[0] = (unsigned long) prom_callmethod_name;
0209 args[1] = 5;
0210 args[2] = 1;
0211 args[3] = (unsigned long) type;
0212 args[4] = (unsigned int) prom_get_mmu_ihandle();
0213 args[5] = vaddr;
0214 args[6] = tte_data;
0215 args[7] = index;
0216 args[8] = (unsigned long) -1;
0217
0218 p1275_cmd_direct(args);
0219
0220 return (long) args[8];
0221 }
0222
0223 long prom_itlb_load(unsigned long index,
0224 unsigned long tte_data,
0225 unsigned long vaddr)
0226 {
0227 return tlb_load("SUNW,itlb-load", index, tte_data, vaddr);
0228 }
0229
0230 long prom_dtlb_load(unsigned long index,
0231 unsigned long tte_data,
0232 unsigned long vaddr)
0233 {
0234 return tlb_load("SUNW,dtlb-load", index, tte_data, vaddr);
0235 }
0236
0237 int prom_map(int mode, unsigned long size,
0238 unsigned long vaddr, unsigned long paddr)
0239 {
0240 unsigned long args[11];
0241 int ret;
0242
0243 args[0] = (unsigned long) prom_callmethod_name;
0244 args[1] = 7;
0245 args[2] = 1;
0246 args[3] = (unsigned long) prom_map_name;
0247 args[4] = (unsigned int) prom_get_mmu_ihandle();
0248 args[5] = (unsigned int) mode;
0249 args[6] = size;
0250 args[7] = vaddr;
0251 args[8] = 0;
0252 args[9] = paddr;
0253 args[10] = (unsigned long) -1;
0254
0255 p1275_cmd_direct(args);
0256
0257 ret = (int) args[10];
0258 if (ret == 0)
0259 ret = -1;
0260 return ret;
0261 }
0262
0263 void prom_unmap(unsigned long size, unsigned long vaddr)
0264 {
0265 unsigned long args[7];
0266
0267 args[0] = (unsigned long) prom_callmethod_name;
0268 args[1] = 4;
0269 args[2] = 0;
0270 args[3] = (unsigned long) prom_unmap_name;
0271 args[4] = (unsigned int) prom_get_mmu_ihandle();
0272 args[5] = size;
0273 args[6] = vaddr;
0274
0275 p1275_cmd_direct(args);
0276 }
0277
0278
0279
0280
0281 int prom_retain(const char *name, unsigned long size,
0282 unsigned long align, unsigned long *paddr)
0283 {
0284 unsigned long args[11];
0285
0286 args[0] = (unsigned long) prom_callmethod_name;
0287 args[1] = 5;
0288 args[2] = 3;
0289 args[3] = (unsigned long) "SUNW,retain";
0290 args[4] = (unsigned int) prom_get_memory_ihandle();
0291 args[5] = align;
0292 args[6] = size;
0293 args[7] = (unsigned long) name;
0294 args[8] = (unsigned long) -1;
0295 args[9] = (unsigned long) -1;
0296 args[10] = (unsigned long) -1;
0297
0298 p1275_cmd_direct(args);
0299
0300 if (args[8])
0301 return (int) args[8];
0302
0303
0304
0305
0306
0307 *paddr = args[10];
0308
0309 return 0;
0310 }
0311
0312
0313
0314
0315
0316
0317
0318 int prom_getunumber(int syndrome_code,
0319 unsigned long phys_addr,
0320 char *buf, int buflen)
0321 {
0322 unsigned long args[12];
0323
0324 args[0] = (unsigned long) prom_callmethod_name;
0325 args[1] = 7;
0326 args[2] = 2;
0327 args[3] = (unsigned long) "SUNW,get-unumber";
0328 args[4] = (unsigned int) prom_get_memory_ihandle();
0329 args[5] = buflen;
0330 args[6] = (unsigned long) buf;
0331 args[7] = 0;
0332 args[8] = phys_addr;
0333 args[9] = (unsigned int) syndrome_code;
0334 args[10] = (unsigned long) -1;
0335 args[11] = (unsigned long) -1;
0336
0337 p1275_cmd_direct(args);
0338
0339 return (int) args[10];
0340 }
0341
0342
0343 void prom_sleepself(void)
0344 {
0345 unsigned long args[3];
0346
0347 args[0] = (unsigned long) "SUNW,sleep-self";
0348 args[1] = 0;
0349 args[2] = 0;
0350 p1275_cmd_direct(args);
0351 }
0352
0353 int prom_sleepsystem(void)
0354 {
0355 unsigned long args[4];
0356
0357 args[0] = (unsigned long) "SUNW,sleep-system";
0358 args[1] = 0;
0359 args[2] = 1;
0360 args[3] = (unsigned long) -1;
0361 p1275_cmd_direct(args);
0362
0363 return (int) args[3];
0364 }
0365
0366 int prom_wakeupsystem(void)
0367 {
0368 unsigned long args[4];
0369
0370 args[0] = (unsigned long) "SUNW,wakeup-system";
0371 args[1] = 0;
0372 args[2] = 1;
0373 args[3] = (unsigned long) -1;
0374 p1275_cmd_direct(args);
0375
0376 return (int) args[3];
0377 }
0378
0379 #ifdef CONFIG_SMP
0380 void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg)
0381 {
0382 unsigned long args[6];
0383
0384 args[0] = (unsigned long) "SUNW,start-cpu";
0385 args[1] = 3;
0386 args[2] = 0;
0387 args[3] = (unsigned int) cpunode;
0388 args[4] = pc;
0389 args[5] = arg;
0390 p1275_cmd_direct(args);
0391 }
0392
0393 void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg)
0394 {
0395 unsigned long args[6];
0396
0397 args[0] = (unsigned long) "SUNW,start-cpu-by-cpuid";
0398 args[1] = 3;
0399 args[2] = 0;
0400 args[3] = (unsigned int) cpuid;
0401 args[4] = pc;
0402 args[5] = arg;
0403 p1275_cmd_direct(args);
0404 }
0405
0406 void prom_stopcpu_cpuid(int cpuid)
0407 {
0408 unsigned long args[4];
0409
0410 args[0] = (unsigned long) "SUNW,stop-cpu-by-cpuid";
0411 args[1] = 1;
0412 args[2] = 0;
0413 args[3] = (unsigned int) cpuid;
0414 p1275_cmd_direct(args);
0415 }
0416
0417 void prom_stopself(void)
0418 {
0419 unsigned long args[3];
0420
0421 args[0] = (unsigned long) "SUNW,stop-self";
0422 args[1] = 0;
0423 args[2] = 0;
0424 p1275_cmd_direct(args);
0425 }
0426
0427 void prom_idleself(void)
0428 {
0429 unsigned long args[3];
0430
0431 args[0] = (unsigned long) "SUNW,idle-self";
0432 args[1] = 0;
0433 args[2] = 0;
0434 p1275_cmd_direct(args);
0435 }
0436
0437 void prom_resumecpu(int cpunode)
0438 {
0439 unsigned long args[4];
0440
0441 args[0] = (unsigned long) "SUNW,resume-cpu";
0442 args[1] = 1;
0443 args[2] = 0;
0444 args[3] = (unsigned int) cpunode;
0445 p1275_cmd_direct(args);
0446 }
0447 #endif