1 /* $OpenBSD: lasi.c,v 1.23 2018/05/14 13:54:39 kettenis Exp $ */ 2 3 /* 4 * Copyright (c) 1998-2003 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #undef LASIDEBUG 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/device.h> 34 #include <sys/reboot.h> 35 36 #include <machine/bus.h> 37 #include <machine/iomod.h> 38 #include <machine/reg.h> 39 #include <machine/autoconf.h> 40 41 #include <hppa/dev/cpudevs.h> 42 43 #include <hppa/gsc/gscbusvar.h> 44 45 #define LASI_IOMASK 0xfff00000 46 47 struct lasi_hwr { 48 u_int32_t lasi_power; 49 #define LASI_BLINK 0x01 50 #define LASI_OFF 0x02 51 u_int32_t lasi_error; 52 u_int32_t lasi_version; 53 u_int32_t lasi_reset; 54 u_int32_t lasi_arbmask; 55 }; 56 57 struct lasi_softc { 58 struct device sc_dev; 59 60 struct lasi_hwr volatile *sc_hw; 61 struct gsc_attach_args ga; /* for deferred attach */ 62 }; 63 64 int lasimatch(struct device *, void *, void *); 65 void lasiattach(struct device *, struct device *, void *); 66 67 const struct cfattach lasi_ca = { 68 sizeof(struct lasi_softc), lasimatch, lasiattach 69 }; 70 71 struct cfdriver lasi_cd = { 72 NULL, "lasi", DV_DULL 73 }; 74 75 void lasi_cold_hook(int on); 76 void lasi_gsc_attach(struct device *self); 77 78 int 79 lasimatch(parent, cfdata, aux) 80 struct device *parent; 81 void *cfdata; 82 void *aux; 83 { 84 struct confargs *ca = aux; 85 /* struct cfdata *cf = cfdata; */ 86 87 if (ca->ca_type.iodc_type != HPPA_TYPE_BHA || 88 ca->ca_type.iodc_sv_model != HPPA_BHA_LASI) 89 return 0; 90 91 return 1; 92 } 93 94 void 95 lasiattach(parent, self, aux) 96 struct device *parent; 97 struct device *self; 98 void *aux; 99 { 100 struct lasi_softc *sc = (struct lasi_softc *)self; 101 struct confargs *ca = aux; 102 struct gscbus_ic *ic; 103 bus_space_handle_t ioh, ioh2; 104 int s; 105 106 if (bus_space_map(ca->ca_iot, ca->ca_hpa, 107 IOMOD_HPASIZE, 0, &ioh)) { 108 printf(": can't map TRS space\n"); 109 return; 110 } 111 112 if (bus_space_map(ca->ca_iot, ca->ca_hpa + 0xc000, 113 IOMOD_HPASIZE, 0, &ioh2)) { 114 bus_space_unmap(ca->ca_iot, ioh, IOMOD_HPASIZE); 115 printf(": can't map IO space\n"); 116 return; 117 } 118 119 sc->sc_hw = (struct lasi_hwr *)(ca->ca_hpa + 0xc000); 120 ic = (struct gscbus_ic *)ca->ca_hpa; 121 122 /* XXX should we reset the chip here? */ 123 124 printf(": rev %d.%d\n", (sc->sc_hw->lasi_version & 0xf0) >> 4, 125 sc->sc_hw->lasi_version & 0xf); 126 127 /* interrupts guts */ 128 s = splhigh(); 129 ic->iar = 0; /* will be set up by gsc when attaching */ 130 ic->icr = 0; 131 ic->imr = ~0U; 132 (void)ic->irr; 133 ic->imr = 0; 134 splx(s); 135 136 #ifdef USELEDS 137 /* figure out the leds address */ 138 switch (cpu_hvers) { 139 case HPPA_BOARD_HP712_60: 140 case HPPA_BOARD_HP712_80: 141 case HPPA_BOARD_HP712_100: 142 case HPPA_BOARD_HP743I_64: 143 case HPPA_BOARD_HP743I_100: 144 case HPPA_BOARD_HP712_120: 145 break; /* only has one led. works different */ 146 147 case HPPA_BOARD_HP715_64: 148 case HPPA_BOARD_HP715_80: 149 case HPPA_BOARD_HP715_100: 150 case HPPA_BOARD_HP715_100XC: 151 case HPPA_BOARD_HP725_100: 152 case HPPA_BOARD_HP725_120: 153 if (bus_space_map(ca->ca_iot, ca->ca_hpa - 0x20000, 154 4, 0, (bus_space_handle_t *)&machine_ledaddr)) 155 machine_ledaddr = NULL; 156 machine_ledword = 1; 157 break; 158 159 case HPPA_BOARD_HP800_A180C: 160 case HPPA_BOARD_HP778_B132L: 161 case HPPA_BOARD_HP778_B132LP: 162 case HPPA_BOARD_HP778_B160L: 163 case HPPA_BOARD_HP778_B180L: 164 case HPPA_BOARD_HP780_C100: 165 case HPPA_BOARD_HP780_C110: 166 case HPPA_BOARD_HP779_C132L: 167 case HPPA_BOARD_HP779_C160L: 168 case HPPA_BOARD_HP779_C180L: 169 case HPPA_BOARD_HP779_C160L1: 170 if (bus_space_map(ca->ca_iot, 0xf0190000, 171 4, 0, (bus_space_handle_t *)&machine_ledaddr)) 172 machine_ledaddr = NULL; 173 machine_ledword = 1; 174 break; 175 176 default: 177 machine_ledaddr = (u_int8_t *)sc->sc_hw; 178 machine_ledword = 1; 179 break; 180 } 181 #endif 182 183 sc->ga.ga_ca = *ca; /* clone from us */ 184 if (!strcmp(parent->dv_xname, "mainbus0")) { 185 sc->ga.ga_dp.dp_bc[0] = sc->ga.ga_dp.dp_bc[1]; 186 sc->ga.ga_dp.dp_bc[1] = sc->ga.ga_dp.dp_bc[2]; 187 sc->ga.ga_dp.dp_bc[2] = sc->ga.ga_dp.dp_bc[3]; 188 sc->ga.ga_dp.dp_bc[3] = sc->ga.ga_dp.dp_bc[4]; 189 sc->ga.ga_dp.dp_bc[4] = sc->ga.ga_dp.dp_bc[5]; 190 sc->ga.ga_dp.dp_bc[5] = sc->ga.ga_dp.dp_mod; 191 sc->ga.ga_dp.dp_mod = 0; 192 } 193 sc->ga.ga_name = "gsc"; 194 sc->ga.ga_hpamask = LASI_IOMASK; 195 sc->ga.ga_parent = gsc_lasi; 196 sc->ga.ga_ic = ic; 197 if (sc->sc_dev.dv_unit) 198 config_defer(self, lasi_gsc_attach); 199 else { 200 extern void (*cold_hook)(int); 201 202 lasi_gsc_attach(self); 203 /* could be already set by power(4) */ 204 if (!cold_hook) 205 cold_hook = lasi_cold_hook; 206 } 207 } 208 209 void 210 lasi_gsc_attach(self) 211 struct device *self; 212 { 213 struct lasi_softc *sc = (struct lasi_softc *)self; 214 215 config_found(self, &sc->ga, gscprint); 216 } 217 218 void 219 lasi_cold_hook(on) 220 int on; 221 { 222 struct lasi_softc *sc = lasi_cd.cd_devs[0]; 223 224 if (!sc) 225 return; 226 227 switch (on) { 228 case HPPA_COLD_COLD: 229 sc->sc_hw->lasi_power = LASI_BLINK; 230 break; 231 case HPPA_COLD_HOT: 232 sc->sc_hw->lasi_power = 0; 233 break; 234 case HPPA_COLD_OFF: 235 sc->sc_hw->lasi_power = LASI_OFF; 236 break; 237 } 238 } 239