1 /* $NetBSD: plumiobus.c,v 1.19 2022/01/24 09:14:37 andvar 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.19 2022/01/24 09:14:37 andvar Exp $"); 34 35 #define PLUMIOBUSDEBUG 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 #include <sys/kmem.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(self, NULL, 167 CFARGS(.search = plumiobus_search)); 168 } 169 170 /* XXX something kludge */ 171 bus_space_tag_t 172 __plumiobus_subregion(bus_space_tag_t t, bus_addr_t ofs, bus_size_t size) 173 { 174 struct hpcmips_bus_space *hbs; 175 176 hbs = kmem_alloc(sizeof(*hbs), KM_SLEEP); 177 *hbs = *t; 178 hbs->t_base += ofs; 179 hbs->t_size = size; 180 181 return (hbs); 182 } 183 184 int 185 plumiobus_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 186 { 187 struct plumiobus_softc *sc = device_private(parent); 188 struct plumiobus_attach_args pba; 189 int slot; 190 191 /* Disallow wildcarded IO5CS slot */ 192 if (cf->cf_loc[PLUMIOBUSIFCF_SLOT] == PLUMIOBUSIFCF_SLOT_DEFAULT) { 193 printf("plumiobus_search: wildcarded slot, skipping\n"); 194 return (0); 195 } 196 slot = pba.pba_slot = cf->cf_loc[PLUMIOBUSIFCF_SLOT]; 197 198 pba.pba_pc = sc->sc_pc; 199 pba.pba_iot = sc->sc_isa[slot].pr_iot; 200 pba.pba_irq = sc->sc_isa[slot].pr_irq; 201 pba.pba_busname = "plumisab"; 202 203 if (!(sc->sc_isa[slot].pr_enabled) && /* not attached slot */ 204 config_probe(parent, cf, &pba)) { 205 config_attach(parent, cf, &pba, plumiobus_print, CFARGS_NONE); 206 sc->sc_isa[slot].pr_enabled = 1; 207 } 208 209 return (0); 210 } 211 212 int 213 plumiobus_print(void *aux, const char *pnp) 214 { 215 216 return (pnp ? QUIET : UNCONF); 217 } 218 219 #ifdef PLUMIOBUSDEBUG 220 void 221 plumiobus_dump(struct plumiobus_softc *sc) 222 { 223 bus_space_tag_t regt = sc->sc_regt; 224 bus_space_handle_t regh = sc->sc_regh; 225 plumreg_t reg; 226 int i, wait; 227 228 reg = plum_conf_read(regt, regh, PLUM_IOBUS_IOXBSZ_REG); 229 printf("8bit port:"); 230 for (i = 0; i < 6; i++) { 231 if (reg & (1 << i)) { 232 printf(" IO5CS%d", i); 233 } 234 } 235 printf("\n"); 236 237 reg = PLUM_IOBUS_IOXCCNT_MASK & 238 plum_conf_read(regt, regh, PLUM_IOBUS_IOXCCNT_REG); 239 printf(" # of wait to become from the access beginning: %d clock\n", 240 reg + 1); 241 reg = plum_conf_read(regt, regh, PLUM_IOBUS_IOXACNT_REG); 242 printf(" # of wait in access clock: "); 243 for (i = 0; i < 5; i++) { 244 wait = (reg >> (i * PLUM_IOBUS_IOXACNT_SHIFT)) 245 & PLUM_IOBUS_IOXACNT_MASK; 246 printf("[CS%d:%d] ", i, wait + 1); 247 } 248 printf("\n"); 249 250 reg = PLUM_IOBUS_IOXSCNT_MASK & 251 plum_conf_read(regt, regh, PLUM_IOBUS_IOXSCNT_REG); 252 printf(" # of wait during access by I/O bus : %d clock\n", reg + 1); 253 254 reg = plum_conf_read(regt, regh, PLUM_IOBUS_IDEMODE_REG); 255 if (reg & PLUM_IOBUS_IDEMODE) { 256 printf("IO5CS3,4 IDE mode\n"); 257 } 258 } 259 #endif /* PLUMIOBUSDEBUG */ 260