1 /* $OpenBSD: lasi.c,v 1.22 2004/09/15 20:11:28 mickey 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_trs { 58 u_int32_t lasi_irr; /* int requset register */ 59 u_int32_t lasi_imr; /* int mask register */ 60 u_int32_t lasi_ipr; /* int pending register */ 61 u_int32_t lasi_icr; /* int command? register */ 62 u_int32_t lasi_iar; /* int acquire? register */ 63 }; 64 65 struct lasi_softc { 66 struct device sc_dev; 67 struct gscbus_ic sc_ic; 68 69 struct lasi_hwr volatile *sc_hw; 70 struct lasi_trs volatile *sc_trs; 71 struct gsc_attach_args ga; /* for deferred attach */ 72 }; 73 74 int lasimatch(struct device *, void *, void *); 75 void lasiattach(struct device *, struct device *, void *); 76 77 struct cfattach lasi_ca = { 78 sizeof(struct lasi_softc), lasimatch, lasiattach 79 }; 80 81 struct cfdriver lasi_cd = { 82 NULL, "lasi", DV_DULL 83 }; 84 85 void lasi_cold_hook(int on); 86 void lasi_gsc_attach(struct device *self); 87 88 int 89 lasimatch(parent, cfdata, aux) 90 struct device *parent; 91 void *cfdata; 92 void *aux; 93 { 94 register struct confargs *ca = aux; 95 /* register struct cfdata *cf = cfdata; */ 96 97 if (ca->ca_type.iodc_type != HPPA_TYPE_BHA || 98 ca->ca_type.iodc_sv_model != HPPA_BHA_LASI) 99 return 0; 100 101 return 1; 102 } 103 104 void 105 lasiattach(parent, self, aux) 106 struct device *parent; 107 struct device *self; 108 void *aux; 109 { 110 struct lasi_softc *sc = (struct lasi_softc *)self; 111 struct confargs *ca = aux; 112 bus_space_handle_t ioh, ioh2; 113 int s, in; 114 115 if (bus_space_map(ca->ca_iot, ca->ca_hpa, 116 IOMOD_HPASIZE, 0, &ioh)) { 117 printf(": can't map TRS space\n"); 118 return; 119 } 120 121 if (bus_space_map(ca->ca_iot, ca->ca_hpa + 0xc000, 122 IOMOD_HPASIZE, 0, &ioh2)) { 123 bus_space_unmap(ca->ca_iot, ioh, IOMOD_HPASIZE); 124 printf(": can't map IO space\n"); 125 return; 126 } 127 128 sc->sc_trs = (struct lasi_trs *)ca->ca_hpa; 129 sc->sc_hw = (struct lasi_hwr *)(ca->ca_hpa + 0xc000); 130 131 /* XXX should we reset the chip here? */ 132 133 printf(": rev %d.%d\n", (sc->sc_hw->lasi_version & 0xf0) >> 4, 134 sc->sc_hw->lasi_version & 0xf); 135 136 /* interrupts guts */ 137 s = splhigh(); 138 sc->sc_trs->lasi_iar = cpu_gethpa(0) | (31 - ca->ca_irq); 139 sc->sc_trs->lasi_icr = 0; 140 sc->sc_trs->lasi_imr = ~0U; 141 in = sc->sc_trs->lasi_irr; 142 sc->sc_trs->lasi_imr = 0; 143 splx(s); 144 145 sc->sc_ic.gsc_type = gsc_lasi; 146 sc->sc_ic.gsc_dv = sc; 147 sc->sc_ic.gsc_base = sc->sc_trs; 148 149 #ifdef USELEDS 150 /* figure out the leds address */ 151 switch (cpu_hvers) { 152 case HPPA_BOARD_HP712_60: 153 case HPPA_BOARD_HP712_80: 154 case HPPA_BOARD_HP712_100: 155 case HPPA_BOARD_HP743I_64: 156 case HPPA_BOARD_HP743I_100: 157 case HPPA_BOARD_HP712_120: 158 break; /* only has one led. works different */ 159 160 case HPPA_BOARD_HP715_64: 161 case HPPA_BOARD_HP715_80: 162 case HPPA_BOARD_HP715_100: 163 case HPPA_BOARD_HP715_100XC: 164 case HPPA_BOARD_HP725_100: 165 case HPPA_BOARD_HP725_120: 166 if (bus_space_map(ca->ca_iot, ca->ca_hpa - 0x20000, 167 4, 0, (bus_space_handle_t *)&machine_ledaddr)) 168 machine_ledaddr = NULL; 169 machine_ledword = 1; 170 break; 171 172 case HPPA_BOARD_HP800_A180C: 173 case HPPA_BOARD_HP778_B132L: 174 case HPPA_BOARD_HP778_B132LP: 175 case HPPA_BOARD_HP778_B160L: 176 case HPPA_BOARD_HP778_B180L: 177 case HPPA_BOARD_HP780_C100: 178 case HPPA_BOARD_HP780_C110: 179 case HPPA_BOARD_HP779_C132L: 180 case HPPA_BOARD_HP779_C160L: 181 case HPPA_BOARD_HP779_C180L: 182 case HPPA_BOARD_HP779_C160L1: 183 if (bus_space_map(ca->ca_iot, 0xf0190000, 184 4, 0, (bus_space_handle_t *)&machine_ledaddr)) 185 machine_ledaddr = NULL; 186 machine_ledword = 1; 187 break; 188 189 default: 190 machine_ledaddr = (u_int8_t *)sc->sc_hw; 191 machine_ledword = 1; 192 break; 193 } 194 #endif 195 196 sc->ga.ga_ca = *ca; /* clone from us */ 197 if (!strcmp(parent->dv_xname, "mainbus0")) { 198 sc->ga.ga_dp.dp_bc[0] = sc->ga.ga_dp.dp_bc[1]; 199 sc->ga.ga_dp.dp_bc[1] = sc->ga.ga_dp.dp_bc[2]; 200 sc->ga.ga_dp.dp_bc[2] = sc->ga.ga_dp.dp_bc[3]; 201 sc->ga.ga_dp.dp_bc[3] = sc->ga.ga_dp.dp_bc[4]; 202 sc->ga.ga_dp.dp_bc[4] = sc->ga.ga_dp.dp_bc[5]; 203 sc->ga.ga_dp.dp_bc[5] = sc->ga.ga_dp.dp_mod; 204 sc->ga.ga_dp.dp_mod = 0; 205 } 206 if (sc->sc_dev.dv_unit) 207 config_defer(self, lasi_gsc_attach); 208 else { 209 extern void (*cold_hook)(int); 210 211 lasi_gsc_attach(self); 212 /* could be already set by power(4) */ 213 if (!cold_hook) 214 cold_hook = lasi_cold_hook; 215 } 216 } 217 218 void 219 lasi_gsc_attach(self) 220 struct device *self; 221 { 222 struct lasi_softc *sc = (struct lasi_softc *)self; 223 224 sc->ga.ga_name = "gsc"; 225 sc->ga.ga_hpamask = LASI_IOMASK; 226 sc->ga.ga_ic = &sc->sc_ic; 227 config_found(self, &sc->ga, gscprint); 228 } 229 230 void 231 lasi_cold_hook(on) 232 int on; 233 { 234 register struct lasi_softc *sc = lasi_cd.cd_devs[0]; 235 236 if (!sc) 237 return; 238 239 switch (on) { 240 case HPPA_COLD_COLD: 241 sc->sc_hw->lasi_power = LASI_BLINK; 242 break; 243 case HPPA_COLD_HOT: 244 sc->sc_hw->lasi_power = 0; 245 break; 246 case HPPA_COLD_OFF: 247 sc->sc_hw->lasi_power = LASI_OFF; 248 break; 249 } 250 } 251