root/arch/sparc/prom/misc_64.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. prom_service_exists
  2. prom_sun4v_guest_soft_state
  3. prom_reboot
  4. prom_feval
  5. prom_cmdline
  6. prom_halt
  7. prom_halt_power_off
  8. prom_get_idprom
  9. prom_get_mmu_ihandle
  10. prom_get_memory_ihandle
  11. tlb_load
  12. prom_itlb_load
  13. prom_dtlb_load
  14. prom_map
  15. prom_unmap
  16. prom_retain
  17. prom_getunumber
  18. prom_sleepself
  19. prom_sleepsystem
  20. prom_wakeupsystem
  21. prom_startcpu
  22. prom_startcpu_cpuid
  23. prom_stopcpu_cpuid
  24. prom_stopself
  25. prom_idleself
  26. prom_resumecpu

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

/* [<][>][^][v][top][bottom][index][help] */