Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* auxio.c: Probing for the Sparc AUXIO register at boot time.
0003  *
0004  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
0005  */
0006 
0007 #include <linux/stddef.h>
0008 #include <linux/init.h>
0009 #include <linux/spinlock.h>
0010 #include <linux/of.h>
0011 #include <linux/of_device.h>
0012 #include <linux/export.h>
0013 
0014 #include <asm/oplib.h>
0015 #include <asm/io.h>
0016 #include <asm/auxio.h>
0017 #include <asm/string.h>     /* memset(), Linux has no bzero() */
0018 #include <asm/cpu_type.h>
0019 
0020 #include "kernel.h"
0021 
0022 /* Probe and map in the Auxiliary I/O register */
0023 
0024 /* auxio_register is not static because it is referenced 
0025  * in entry.S::floppy_tdone
0026  */
0027 void __iomem *auxio_register = NULL;
0028 static DEFINE_SPINLOCK(auxio_lock);
0029 
0030 void __init auxio_probe(void)
0031 {
0032     phandle node, auxio_nd;
0033     struct linux_prom_registers auxregs[1];
0034     struct resource r;
0035 
0036     switch (sparc_cpu_model) {
0037     case sparc_leon:
0038     case sun4d:
0039         return;
0040     default:
0041         break;
0042     }
0043     node = prom_getchild(prom_root_node);
0044     auxio_nd = prom_searchsiblings(node, "auxiliary-io");
0045     if(!auxio_nd) {
0046         node = prom_searchsiblings(node, "obio");
0047         node = prom_getchild(node);
0048         auxio_nd = prom_searchsiblings(node, "auxio");
0049         if(!auxio_nd) {
0050 #ifdef CONFIG_PCI
0051             /* There may be auxio on Ebus */
0052             return;
0053 #else
0054             if(prom_searchsiblings(node, "leds")) {
0055                 /* VME chassis sun4m machine, no auxio exists. */
0056                 return;
0057             }
0058             prom_printf("Cannot find auxio node, cannot continue...\n");
0059             prom_halt();
0060 #endif
0061         }
0062     }
0063     if(prom_getproperty(auxio_nd, "reg", (char *) auxregs, sizeof(auxregs)) <= 0)
0064         return;
0065     prom_apply_obio_ranges(auxregs, 0x1);
0066     /* Map the register both read and write */
0067     r.flags = auxregs[0].which_io & 0xF;
0068     r.start = auxregs[0].phys_addr;
0069     r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1;
0070     auxio_register = of_ioremap(&r, 0, auxregs[0].reg_size, "auxio");
0071     /* Fix the address on sun4m. */
0072     if ((((unsigned long) auxregs[0].phys_addr) & 3) == 3)
0073         auxio_register += (3 - ((unsigned long)auxio_register & 3));
0074 
0075     set_auxio(AUXIO_LED, 0);
0076 }
0077 
0078 unsigned char get_auxio(void)
0079 {
0080     if(auxio_register) 
0081         return sbus_readb(auxio_register);
0082     return 0;
0083 }
0084 EXPORT_SYMBOL(get_auxio);
0085 
0086 void set_auxio(unsigned char bits_on, unsigned char bits_off)
0087 {
0088     unsigned char regval;
0089     unsigned long flags;
0090     spin_lock_irqsave(&auxio_lock, flags);
0091     switch (sparc_cpu_model) {
0092     case sun4m:
0093         if(!auxio_register)
0094             break;     /* VME chassis sun4m, no auxio. */
0095         regval = sbus_readb(auxio_register);
0096         sbus_writeb(((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M,
0097             auxio_register);
0098         break;
0099     case sun4d:
0100         break;
0101     default:
0102         panic("Can't set AUXIO register on this machine.");
0103     }
0104     spin_unlock_irqrestore(&auxio_lock, flags);
0105 }
0106 EXPORT_SYMBOL(set_auxio);
0107 
0108 /* sun4m power control register (AUXIO2) */
0109 
0110 volatile u8 __iomem *auxio_power_register = NULL;
0111 
0112 void __init auxio_power_probe(void)
0113 {
0114     struct linux_prom_registers regs;
0115     phandle node;
0116     struct resource r;
0117 
0118     /* Attempt to find the sun4m power control node. */
0119     node = prom_getchild(prom_root_node);
0120     node = prom_searchsiblings(node, "obio");
0121     node = prom_getchild(node);
0122     node = prom_searchsiblings(node, "power");
0123     if (node == 0 || (s32)node == -1)
0124         return;
0125 
0126     /* Map the power control register. */
0127     if (prom_getproperty(node, "reg", (char *)&regs, sizeof(regs)) <= 0)
0128         return;
0129     prom_apply_obio_ranges(&regs, 1);
0130     memset(&r, 0, sizeof(r));
0131     r.flags = regs.which_io & 0xF;
0132     r.start = regs.phys_addr;
0133     r.end = regs.phys_addr + regs.reg_size - 1;
0134     auxio_power_register =
0135         (u8 __iomem *)of_ioremap(&r, 0, regs.reg_size, "auxpower");
0136 
0137     /* Display a quick message on the console. */
0138     if (auxio_power_register)
0139         printk(KERN_INFO "Power off control detected.\n");
0140 }