0001
0002
0003
0004
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
0023
0024
0025
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
0052 return;
0053 #else
0054 if(prom_searchsiblings(node, "leds")) {
0055
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
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
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;
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
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
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
0127 if (prom_getproperty(node, "reg", (char *)®s, sizeof(regs)) <= 0)
0128 return;
0129 prom_apply_obio_ranges(®s, 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
0138 if (auxio_power_register)
0139 printk(KERN_INFO "Power off control detected.\n");
0140 }