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