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/system.h>
  19#include <asm/ldc.h>
  20
  21static 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
  38void 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'. */
  52void 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'. */
  69void 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}
  83EXPORT_SYMBOL(prom_feval);
  84
  85#ifdef CONFIG_SMP
  86extern void smp_capture(void);
  87extern void smp_release(void);
  88#endif
  89
  90/* Drop into the prom, with the chance to continue with the 'go'
  91 * prom command.
  92 */
  93void 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 */
 120void 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
 128again:
 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
 136void 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 */
 157unsigned 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
 170int 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
 188static 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. */
 208static 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
 228long 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
 235long 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
 242int 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
 268void 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 */
 286int 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 */
 323int 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. */
 348void 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
 358int 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
 371int 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
 385void 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
 398void 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
 411void 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
 422void 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
 432void 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
 442void 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