1 /* $NetBSD: auxiotwo.c,v 1.9 2008/04/28 20:23:36 martin Exp $ */ 2 3 /* 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Julian Coleman. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Based on software developed by the Computer Systems Engineering group 34 * at Lawrence Berkeley Laboratory. 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: auxiotwo.c,v 1.9 2008/04/28 20:23:36 martin Exp $"); 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/device.h> 43 #include <sys/kernel.h> 44 45 #include <machine/autoconf.h> 46 47 #include <sparc/include/tctrl.h> 48 #include <sparc/sparc/auxiotwo.h> 49 #include <sparc/sparc/vaddrs.h> 50 51 static int serial_refcount; 52 static int serial_power; 53 54 static int auxiotwomatch(struct device *, struct cfdata *, void *); 55 static void auxiotwoattach(struct device *, struct device *, void *); 56 57 CFATTACH_DECL(auxiotwo_obio, sizeof(struct device), 58 auxiotwomatch, auxiotwoattach, NULL, NULL); 59 60 /* 61 * The OPENPROM calls this "auxio2". 62 */ 63 static int 64 auxiotwomatch(struct device *parent, struct cfdata *cf, void *aux) 65 { 66 union obio_attach_args *uoba = aux; 67 68 if (uoba->uoba_isobio4 != 0) 69 return (0); 70 71 return (strcmp("auxio2", uoba->uoba_sbus.sa_name) == 0); 72 } 73 74 static void 75 auxiotwoattach(struct device *parent, struct device *self, void *aux) 76 { 77 union obio_attach_args *uoba = aux; 78 struct sbus_attach_args *sa = &uoba->uoba_sbus; 79 bus_space_handle_t bh; 80 81 if (sbus_bus_map(sa->sa_bustag, 82 sa->sa_slot, sa->sa_offset, 83 sizeof(long), 84 BUS_SPACE_MAP_LINEAR, &bh) != 0) { 85 printf("auxiotwoattach: can't map register\n"); 86 return; 87 } 88 89 auxiotwo_reg = (volatile u_char *)bh; 90 auxiotwo_regval = *auxiotwo_reg; 91 serial_refcount = 0; 92 serial_power = PORT_PWR_STANDBY; 93 printf("\n"); 94 } 95 96 unsigned int 97 auxiotwobisc(int bis, int bic) 98 { 99 register int s; 100 101 if (auxiotwo_reg == 0) 102 /* 103 * Most machines do not have an `aux2' register; devices that 104 * depend on it should not get configured if it's absent. 105 */ 106 panic("no aux2 register"); 107 108 s = splhigh(); 109 auxiotwo_regval = (auxiotwo_regval | bis) & ~bic; 110 *auxiotwo_reg = auxiotwo_regval; 111 splx(s); 112 return (auxiotwo_regval); 113 } 114 115 /* 116 * Serial port state - called from zs_enable()/zs_disable() 117 */ 118 void 119 auxiotwoserialendis(int state) 120 { 121 switch (state) { 122 123 case ZS_ENABLE: 124 /* Power on the serial ports? */ 125 serial_refcount++; 126 if (serial_refcount == 1 && serial_power == PORT_PWR_STANDBY) 127 auxiotwobisc(AUXIOTWO_SON, 0); 128 break; 129 case ZS_DISABLE: 130 /* Power off the serial ports? */ 131 serial_refcount--; 132 if (!serial_refcount && serial_power == PORT_PWR_STANDBY) 133 auxiotwobisc(AUXIOTWO_SOF, 1); 134 break; 135 } 136 } 137 138 /* 139 * Set power management - called by tctrl 140 */ 141 void 142 auxiotwoserialsetapm(int state) 143 { 144 switch (state) { 145 146 case PORT_PWR_ON: 147 /* Change to: power always on */ 148 if (serial_power == PORT_PWR_OFF || 149 (serial_power == PORT_PWR_STANDBY && !serial_refcount)) 150 auxiotwobisc(AUXIOTWO_SON, 0); 151 serial_power = PORT_PWR_ON; 152 break; 153 154 case PORT_PWR_STANDBY: 155 /* Change to: power on if open */ 156 if (serial_power == PORT_PWR_ON && !serial_refcount) 157 auxiotwobisc(AUXIOTWO_SOF, 1); 158 if (serial_power == PORT_PWR_OFF && serial_refcount) 159 auxiotwobisc(AUXIOTWO_SON, 0); 160 serial_power = PORT_PWR_STANDBY; 161 break; 162 163 case PORT_PWR_OFF: 164 /* Change to: power always off */ 165 if (serial_power == PORT_PWR_ON || 166 (serial_power == PORT_PWR_STANDBY && serial_refcount)) 167 auxiotwobisc(AUXIOTWO_SOF, 1); 168 serial_power = PORT_PWR_OFF; 169 break; 170 } 171 } 172 173 /* 174 * Get power management - called by tctrl 175 */ 176 int 177 auxiotwoserialgetapm (void) 178 { 179 180 return (serial_power); 181 } 182