1 /* $NetBSD: plumiobus.c,v 1.14 2012/10/27 17:17:53 chs Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 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 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: plumiobus.c,v 1.14 2012/10/27 17:17:53 chs Exp $"); 34 35 #define PLUMIOBUSDEBUG 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 #include <sys/malloc.h> 41 42 #include <machine/bus.h> 43 #include <machine/intr.h> 44 45 #include <hpcmips/tx/tx39var.h> 46 #include <hpcmips/dev/plumvar.h> 47 #include <hpcmips/dev/plumicuvar.h> 48 #include <hpcmips/dev/plumpowervar.h> 49 #include <hpcmips/dev/plumiobusreg.h> 50 #include <hpcmips/dev/plumiobusvar.h> 51 52 #include "locators.h" 53 54 #ifdef PLUMIOBUSDEBUG 55 int plumiobus_debug = 0; 56 #define DPRINTF(arg) if (plumiobus_debug) printf arg; 57 #define DPRINTFN(n, arg) if (plumiobus_debug > (n)) printf arg; 58 #else 59 #define DPRINTF(arg) 60 #define DPRINTFN(n, arg) 61 #endif 62 63 int plumiobus_match(device_t, cfdata_t, void *); 64 void plumiobus_attach(device_t, device_t, void *); 65 int plumiobus_print(void *, const char *); 66 int plumiobus_search(device_t, cfdata_t , const int *, void *); 67 68 struct plumisa_resource { 69 int pr_irq; 70 bus_space_tag_t pr_iot; 71 int pr_enabled; 72 }; 73 74 struct plumiobus_softc { 75 plum_chipset_tag_t sc_pc; 76 bus_space_tag_t sc_regt; 77 bus_space_handle_t sc_regh; 78 bus_space_tag_t sc_iot; 79 bus_space_handle_t sc_ioh; 80 struct plumisa_resource sc_isa[PLUM_IOBUS_IO5CSMAX]; 81 }; 82 83 CFATTACH_DECL_NEW(plumiobus, sizeof(struct plumiobus_softc), 84 plumiobus_match, plumiobus_attach, NULL, NULL); 85 86 bus_space_tag_t __plumiobus_subregion(bus_space_tag_t, bus_addr_t, 87 bus_size_t); 88 #ifdef PLUMIOBUSDEBUG 89 void plumiobus_dump(struct plumiobus_softc *); 90 #endif 91 92 int 93 plumiobus_match(device_t parent, cfdata_t cf, void *aux) 94 { 95 96 return (1); 97 } 98 99 void 100 plumiobus_attach(device_t parent, device_t self, void *aux) 101 { 102 struct plum_attach_args *pa = aux; 103 struct plumiobus_softc *sc = device_private(self); 104 struct plumisa_resource *pr; 105 106 sc->sc_pc = pa->pa_pc; 107 sc->sc_regt = pa->pa_regt; 108 sc->sc_iot = pa->pa_iot; 109 110 if (bus_space_map(sc->sc_regt, PLUM_IOBUS_REGBASE, 111 PLUM_IOBUS_REGSIZE, 0, &sc->sc_regh)) { 112 printf(": register map failed.\n"); 113 return; 114 } 115 printf("\n"); 116 plum_power_establish(sc->sc_pc, PLUM_PWR_IO5); 117 118 /* Address space <-> IRQ mapping */ 119 pr = &sc->sc_isa[IO5CS0]; 120 pr->pr_irq = PLUM_INT_EXT5IO0; 121 pr->pr_iot = __plumiobus_subregion( 122 sc->sc_iot, 123 PLUM_IOBUS_IOBASE + PLUM_IOBUS_IO5CS0BASE, 124 PLUM_IOBUS_IO5SIZE); 125 126 pr = &sc->sc_isa[IO5CS1]; 127 pr->pr_irq = PLUM_INT_EXT5IO1; 128 pr->pr_iot = __plumiobus_subregion( 129 sc->sc_iot, 130 PLUM_IOBUS_IOBASE + PLUM_IOBUS_IO5CS1BASE, 131 PLUM_IOBUS_IO5SIZE); 132 133 pr = &sc->sc_isa[IO5CS2]; 134 pr->pr_irq = PLUM_INT_EXT5IO2; 135 pr->pr_iot = __plumiobus_subregion( 136 sc->sc_iot, 137 PLUM_IOBUS_IOBASE + PLUM_IOBUS_IO5CS2BASE, 138 PLUM_IOBUS_IO5SIZE); 139 140 pr = &sc->sc_isa[IO5CS3]; 141 pr->pr_irq = PLUM_INT_EXT5IO3; 142 pr->pr_iot = __plumiobus_subregion( 143 sc->sc_iot, 144 PLUM_IOBUS_IOBASE + PLUM_IOBUS_IO5CS3BASE, 145 PLUM_IOBUS_IO5SIZE); 146 147 pr = &sc->sc_isa[IO5CS4]; 148 pr->pr_irq = PLUM_INT_EXT3IO0; /* XXX */ 149 pr->pr_iot = __plumiobus_subregion( 150 sc->sc_iot, 151 PLUM_IOBUS_IOBASE + PLUM_IOBUS_IO5CS4BASE, 152 PLUM_IOBUS_IO5SIZE); 153 154 155 pr = &sc->sc_isa[IO5NCS]; 156 pr->pr_irq = PLUM_INT_EXT3IO1; 157 pr->pr_iot = __plumiobus_subregion( 158 sc->sc_iot, 159 PLUM_IOBUS_IOBASE + PLUM_IOBUS_IO5CS5BASE, 160 PLUM_IOBUS_IO5SIZE); 161 162 #ifdef PLUMIOBUSDEBUG 163 plumiobus_dump(sc); 164 #endif 165 166 config_search_ia(plumiobus_search, self, "plumiobusif", plumiobus_print); 167 } 168 169 /* XXX something kludge */ 170 bus_space_tag_t 171 __plumiobus_subregion(bus_space_tag_t t, bus_addr_t ofs, bus_size_t size) 172 { 173 struct hpcmips_bus_space *hbs; 174 175 if (!(hbs = malloc(sizeof(struct hpcmips_bus_space), 176 M_DEVBUF, M_NOWAIT))) { 177 panic ("__plumiobus_subregion: no memory."); 178 } 179 *hbs = *t; 180 hbs->t_base += ofs; 181 hbs->t_size = size; 182 183 return (hbs); 184 } 185 186 int 187 plumiobus_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 188 { 189 struct plumiobus_softc *sc = device_private(parent); 190 struct plumiobus_attach_args pba; 191 int slot; 192 193 /* Disallow wildcarded IO5CS slot */ 194 if (cf->cf_loc[PLUMIOBUSIFCF_SLOT] == PLUMIOBUSIFCF_SLOT_DEFAULT) { 195 printf("plumiobus_search: wildcarded slot, skipping\n"); 196 return (0); 197 } 198 slot = pba.pba_slot = cf->cf_loc[PLUMIOBUSIFCF_SLOT]; 199 200 pba.pba_pc = sc->sc_pc; 201 pba.pba_iot = sc->sc_isa[slot].pr_iot; 202 pba.pba_irq = sc->sc_isa[slot].pr_irq; 203 pba.pba_busname = "plumisab"; 204 205 if (!(sc->sc_isa[slot].pr_enabled) && /* not attached slot */ 206 config_match(parent, cf, &pba)) { 207 config_attach(parent, cf, &pba, plumiobus_print); 208 sc->sc_isa[slot].pr_enabled = 1; 209 } 210 211 return (0); 212 } 213 214 int 215 plumiobus_print(void *aux, const char *pnp) 216 { 217 218 return (pnp ? QUIET : UNCONF); 219 } 220 221 #ifdef PLUMIOBUSDEBUG 222 void 223 plumiobus_dump(struct plumiobus_softc *sc) 224 { 225 bus_space_tag_t regt = sc->sc_regt; 226 bus_space_handle_t regh = sc->sc_regh; 227 plumreg_t reg; 228 int i, wait; 229 230 reg = plum_conf_read(regt, regh, PLUM_IOBUS_IOXBSZ_REG); 231 printf("8bit port:"); 232 for (i = 0; i < 6; i++) { 233 if (reg & (1 << i)) { 234 printf(" IO5CS%d", i); 235 } 236 } 237 printf("\n"); 238 239 reg = PLUM_IOBUS_IOXCCNT_MASK & 240 plum_conf_read(regt, regh, PLUM_IOBUS_IOXCCNT_REG); 241 printf(" # of wait to become from the access begining: %d clock\n", 242 reg + 1); 243 reg = plum_conf_read(regt, regh, PLUM_IOBUS_IOXACNT_REG); 244 printf(" # of wait in access clock: "); 245 for (i = 0; i < 5; i++) { 246 wait = (reg >> (i * PLUM_IOBUS_IOXACNT_SHIFT)) 247 & PLUM_IOBUS_IOXACNT_MASK; 248 printf("[CS%d:%d] ", i, wait + 1); 249 } 250 printf("\n"); 251 252 reg = PLUM_IOBUS_IOXSCNT_MASK & 253 plum_conf_read(regt, regh, PLUM_IOBUS_IOXSCNT_REG); 254 printf(" # of wait during access by I/O bus : %d clock\n", reg + 1); 255 256 reg = plum_conf_read(regt, regh, PLUM_IOBUS_IDEMODE_REG); 257 if (reg & PLUM_IOBUS_IDEMODE) { 258 printf("IO5CS3,4 IDE mode\n"); 259 } 260 } 261 #endif /* PLUMIOBUSDEBUG */ 262