linux/arch/sparc/kernel/auxio_32.c
<<
>>
Prefs
   1/* auxio.c: Probing for the Sparc AUXIO register at boot time.
   2 *
   3 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
   4 */
   5
   6#include <linux/stddef.h>
   7#include <linux/init.h>
   8#include <linux/spinlock.h>
   9#include <linux/of.h>
  10#include <linux/of_device.h>
  11#include <linux/export.h>
  12
  13#include <asm/oplib.h>
  14#include <asm/io.h>
  15#include <asm/auxio.h>
  16#include <asm/string.h>         /* memset(), Linux has no bzero() */
  17#include <asm/cpu_type.h>
  18
  19#include "kernel.h"
  20
  21/* Probe and map in the Auxiliary I/O register */
  22
  23/* auxio_register is not static because it is referenced 
  24 * in entry.S::floppy_tdone
  25 */
  26void __iomem *auxio_register = NULL;
  27static DEFINE_SPINLOCK(auxio_lock);
  28
  29void __init auxio_probe(void)
  30{
  31        phandle node, auxio_nd;
  32        struct linux_prom_registers auxregs[1];
  33        struct resource r;
  34
  35        switch (sparc_cpu_model) {
  36        case sparc_leon:
  37        case sun4d:
  38                return;
  39        default:
  40                break;
  41        }
  42        node = prom_getchild(prom_root_node);
  43        auxio_nd = prom_searchsiblings(node, "auxiliary-io");
  44        if(!auxio_nd) {
  45                node = prom_searchsiblings(node, "obio");
  46                node = prom_getchild(node);
  47                auxio_nd = prom_searchsiblings(node, "auxio");
  48                if(!auxio_nd) {
  49#ifdef CONFIG_PCI
  50                        /* There may be auxio on Ebus */
  51                        return;
  52#else
  53                        if(prom_searchsiblings(node, "leds")) {
  54                                /* VME chassis sun4m machine, no auxio exists. */
  55                                return;
  56                        }
  57                        prom_printf("Cannot find auxio node, cannot continue...\n");
  58                        prom_halt();
  59#endif
  60                }
  61        }
  62        if(prom_getproperty(auxio_nd, "reg", (char *) auxregs, sizeof(auxregs)) <= 0)
  63                return;
  64        prom_apply_obio_ranges(auxregs, 0x1);
  65        /* Map the register both read and write */
  66        r.flags = auxregs[0].which_io & 0xF;
  67        r.start = auxregs[0].phys_addr;
  68        r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1;
  69        auxio_register = of_ioremap(&r, 0, auxregs[0].reg_size, "auxio");
  70        /* Fix the address on sun4m. */
  71        if ((((unsigned long) auxregs[0].phys_addr) & 3) == 3)
  72                auxio_register += (3 - ((unsigned long)auxio_register & 3));
  73
  74        set_auxio(AUXIO_LED, 0);
  75}
  76
  77unsigned char get_auxio(void)
  78{
  79        if(auxio_register) 
  80                return sbus_readb(auxio_register);
  81        return 0;
  82}
  83EXPORT_SYMBOL(get_auxio);
  84
  85void set_auxio(unsigned char bits_on, unsigned char bits_off)
  86{
  87        unsigned char regval;
  88        unsigned long flags;
  89        spin_lock_irqsave(&auxio_lock, flags);
  90        switch (sparc_cpu_model) {
  91        case sun4m:
  92                if(!auxio_register)
  93                        break;     /* VME chassis sun4m, no auxio. */
  94                regval = sbus_readb(auxio_register);
  95                sbus_writeb(((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M,
  96                        auxio_register);
  97                break;
  98        case sun4d:
  99                break;
 100        default:
 101                panic("Can't set AUXIO register on this machine.");
 102        }
 103        spin_unlock_irqrestore(&auxio_lock, flags);
 104}
 105EXPORT_SYMBOL(set_auxio);
 106
 107/* sun4m power control register (AUXIO2) */
 108
 109volatile u8 __iomem *auxio_power_register = NULL;
 110
 111void __init auxio_power_probe(void)
 112{
 113        struct linux_prom_registers regs;
 114        phandle node;
 115        struct resource r;
 116
 117        /* Attempt to find the sun4m power control node. */
 118        node = prom_getchild(prom_root_node);
 119        node = prom_searchsiblings(node, "obio");
 120        node = prom_getchild(node);
 121        node = prom_searchsiblings(node, "power");
 122        if (node == 0 || (s32)node == -1)
 123                return;
 124
 125        /* Map the power control register. */
 126        if (prom_getproperty(node, "reg", (char *)&regs, sizeof(regs)) <= 0)
 127                return;
 128        prom_apply_obio_ranges(&regs, 1);
 129        memset(&r, 0, sizeof(r));
 130        r.flags = regs.which_io & 0xF;
 131        r.start = regs.phys_addr;
 132        r.end = regs.phys_addr + regs.reg_size - 1;
 133        auxio_power_register =
 134                (u8 __iomem *)of_ioremap(&r, 0, regs.reg_size, "auxpower");
 135
 136        /* Display a quick message on the console. */
 137        if (auxio_power_register)
 138                printk(KERN_INFO "Power off control detected.\n");
 139}
 140