1 /* $NetBSD: gemini_obio.c,v 1.8 2010/01/05 13:14:56 mbalmer Exp $ */ 2 3 /* adapted from: 4 * NetBSD: omap2_obio.c,v 1.5 2008/10/21 18:50:25 matt Exp 5 */ 6 7 /* 8 * Autoconfiguration support for the Gemini "On Board" I/O. 9 * 10 * Based on arm/omap/omap2_obio.c which in turn was derived 11 * Based on arm/omap/omap_emifs.c which in turn was derived 12 * Based on arm/xscale/pxa2x0.c which in turn was derived 13 * from arm/sa11x0/sa11x0.c 14 * 15 * Copyright (c) 2002, 2005 Genetec Corporation. All rights reserved. 16 * Written by Hiroyuki Bessho for Genetec Corporation. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions 20 * are met: 21 * 1. Redistributions of source code must retain the above copyright 22 * notice, this list of conditions and the following disclaimer. 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution. 26 * 3. All advertising materials mentioning features or use of this software 27 * must display the following acknowledgement: 28 * This product includes software developed for the NetBSD Project by 29 * Genetec Corporation. 30 * 4. The name of Genetec Corporation may not be used to endorse or 31 * promote products derived from this software without specific prior 32 * written permission. 33 * 34 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND 35 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 36 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 37 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION 38 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 39 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 40 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 41 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 42 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 43 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 44 * POSSIBILITY OF SUCH DAMAGE. 45 * 46 * Copyright (c) 1997,1998, 2001, The NetBSD Foundation, Inc. 47 * All rights reserved. 48 * 49 * This code is derived from software contributed to The NetBSD Foundation 50 * by IWAMOTO Toshihiro, Ichiro FUKUHARA and Paul Kranenburg. 51 * 52 * Redistribution and use in source and binary forms, with or without 53 * modification, are permitted provided that the following conditions 54 * are met: 55 * 1. Redistributions of source code must retain the above copyright 56 * notice, this list of conditions and the following disclaimer. 57 * 2. Redistributions in binary form must reproduce the above copyright 58 * notice, this list of conditions and the following disclaimer in the 59 * documentation and/or other materials provided with the distribution. 60 * 61 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 62 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 63 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 64 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 65 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 66 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 67 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 68 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 69 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 70 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 71 * POSSIBILITY OF SUCH DAMAGE. 72 * 73 * Copyright (c) 1999 74 * Shin Takemura and PocketBSD Project. All rights reserved. 75 * 76 * Redistribution and use in source and binary forms, with or without 77 * modification, are permitted provided that the following conditions 78 * are met: 79 * 1. Redistributions of source code must retain the above copyright 80 * notice, this list of conditions and the following disclaimer. 81 * 2. Redistributions in binary form must reproduce the above copyright 82 * notice, this list of conditions and the following disclaimer in the 83 * documentation and/or other materials provided with the distribution. 84 * 3. All advertising materials mentioning features or use of this software 85 * must display the following acknowledgement: 86 * This product includes software developed by the PocketBSD project 87 * and its contributors. 88 * 4. Neither the name of the project nor the names of its contributors 89 * may be used to endorse or promote products derived from this software 90 * without specific prior written permission. 91 * 92 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 93 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 95 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 96 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 97 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 98 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 100 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 101 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 102 * SUCH DAMAGE. 103 */ 104 105 #include "opt_gemini.h" 106 #include <sys/cdefs.h> 107 __KERNEL_RCSID(0, "$NetBSD: gemini_obio.c,v 1.8 2010/01/05 13:14:56 mbalmer Exp $"); 108 109 #include "locators.h" 110 #include "obio.h" 111 #include "geminiicu.h" 112 #include "pci.h" 113 114 #include <sys/param.h> 115 #include <sys/systm.h> 116 #include <sys/device.h> 117 #include <sys/kernel.h> 118 #include <sys/reboot.h> 119 120 #include <machine/cpu.h> 121 #include <machine/bus.h> 122 123 #include <arm/cpufunc.h> 124 #include <arm/mainbus/mainbus.h> 125 #include <arm/gemini/gemini_var.h> 126 #include <arm/gemini/gemini_reg.h> 127 128 #include <arm/gemini/gemini_obiovar.h> 129 130 typedef struct { 131 boolean_t cs_valid; 132 ulong cs_addr; 133 ulong cs_size; 134 } obio_csconfig_t; 135 136 /* prototypes */ 137 static int obio_match(device_t, cfdata_t, void *); 138 static void obio_attach(device_t, device_t, void *); 139 static int obio_search(device_t, cfdata_t, const int *, void *); 140 static int obio_find(device_t, cfdata_t, const int *, void *); 141 static int obio_print(void *, const char *); 142 static void obio_attach_critical(struct obio_softc *); 143 144 /* attach structures */ 145 CFATTACH_DECL_NEW(obio, sizeof(struct obio_softc), 146 obio_match, obio_attach, NULL, NULL); 147 148 149 static int 150 obio_match(device_t parent, cfdata_t match, void *aux) 151 { 152 return 1; 153 } 154 155 static void 156 obio_attach(device_t parent, device_t self, void *aux) 157 { 158 struct obio_softc *sc = device_private(self); 159 struct mainbus_attach_args *mb = (struct mainbus_attach_args *)aux; 160 #if NPCI > 0 161 struct pcibus_attach_args pba; 162 #endif 163 164 sc->sc_dev = self; 165 166 sc->sc_iot = &gemini_bs_tag; 167 168 aprint_normal(": On-Board IO\n"); 169 170 #if (GEMINI_BUSBASE != 0) 171 sc->sc_dmarange.dr_sysbase = 0; 172 sc->sc_dmarange.dr_busbase = (GEMINI_BUSBASE * 1024 * 1024); 173 sc->sc_dmarange.dr_len = MEMSIZE * 1024 * 1024; 174 gemini_bus_dma_tag._ranges = &sc->sc_dmarange; 175 gemini_bus_dma_tag._nranges = 1; 176 #endif 177 178 sc->sc_ioh = 0; 179 sc->sc_dmat = &gemini_bus_dma_tag; 180 sc->sc_base = mb->mb_iobase; 181 sc->sc_size = mb->mb_iosize; 182 183 /* 184 * Attach critical devices first. 185 */ 186 obio_attach_critical(sc); 187 188 #if NPCI > 0 189 /* 190 * map PCI controller registers 191 */ 192 if (bus_space_map(sc->sc_iot, GEMINI_PCICFG_BASE, 193 GEMINI_PCI_CFG_DATA+4, 0, &sc->sc_pcicfg_ioh)) { 194 aprint_error("cannot map PCI controller at %#x\n", 195 GEMINI_PCICFG_BASE); 196 return; 197 } 198 /* 199 * initialize the PCI chipset tag 200 */ 201 gemini_pci_init(&sc->sc_pci_chipset, sc); 202 #endif /* NPCI */ 203 204 /* 205 * attach the rest of our devices 206 */ 207 config_search_ia(obio_search, self, "obio", NULL); 208 209 #if NPCI > 0 210 /* 211 * attach the PCI bus 212 */ 213 pba.pba_memt = sc->sc_iot; 214 pba.pba_iot = sc->sc_iot; 215 pba.pba_dmat = sc->sc_dmat; 216 pba.pba_dmat64 = NULL; 217 pba.pba_pc = &sc->sc_pci_chipset; 218 pba.pba_bus = 0; 219 pba.pba_bridgetag = NULL; 220 pba.pba_intrswiz = 0; 221 pba.pba_intrtag = 0; 222 pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED | 223 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; 224 225 (void) config_found_ia(sc->sc_dev, "pcibus", &pba, pcibusprint); 226 #endif /* NPCI */ 227 228 } 229 230 static int 231 obio_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 232 { 233 struct obio_softc * const sc = device_private(parent); 234 struct obio_attach_args oa; 235 236 /* Set up the attach args. */ 237 if (cf->cf_loc[OBIOCF_NOBYTEACC] == 1) { 238 #if 0 239 if (cf->cf_loc[OBIOCF_MULT] == 1) 240 oa.obio_iot = &nobyteacc_bs_tag; 241 else 242 #endif 243 panic("nobyteacc specified for device with " 244 "non-byte multiplier\n"); 245 } else { 246 switch (cf->cf_loc[OBIOCF_MULT]) { 247 case 1: 248 oa.obio_iot = &gemini_bs_tag; 249 break; 250 #if 0 251 case 2: 252 oa.obio_iot = &gemini_a2x_bs_tag; 253 break; 254 #endif 255 case 4: 256 oa.obio_iot = &gemini_a4x_bs_tag; 257 break; 258 default: 259 panic("Unsupported obio bus multiplier."); 260 break; 261 } 262 } 263 264 oa.obio_dmat = sc->sc_dmat; 265 oa.obio_addr = cf->cf_loc[OBIOCF_ADDR]; 266 oa.obio_size = cf->cf_loc[OBIOCF_SIZE]; 267 oa.obio_intr = cf->cf_loc[OBIOCF_INTR]; 268 oa.obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE]; 269 270 if (config_match(parent, cf, &oa)) { 271 config_attach(parent, cf, &oa, obio_print); 272 return 0; /* love it */ 273 } 274 275 return UNCONF; /* NG */ 276 } 277 278 static int 279 obio_find(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 280 { 281 struct obio_attach_args * const oa = aux; 282 283 if (oa->obio_addr != OBIOCF_ADDR_DEFAULT 284 && oa->obio_addr != cf->cf_loc[OBIOCF_ADDR]) 285 return 0; 286 if (oa->obio_size != OBIOCF_SIZE_DEFAULT 287 && oa->obio_size != cf->cf_loc[OBIOCF_SIZE]) 288 return 0; 289 if (oa->obio_intr != OBIOCF_INTR_DEFAULT 290 && oa->obio_intr != cf->cf_loc[OBIOCF_INTR]) 291 return 0; 292 if (oa->obio_intrbase != OBIOCF_INTRBASE_DEFAULT 293 && oa->obio_intrbase != cf->cf_loc[OBIOCF_INTRBASE]) 294 return 0; 295 296 /* Set up the attach args. */ 297 if (cf->cf_loc[OBIOCF_NOBYTEACC] == 1) { 298 #if 0 299 if (cf->cf_loc[OBIOCF_MULT] == 1) 300 oa->obio_iot = &nobyteacc_bs_tag; 301 else 302 #endif 303 panic("nobyteacc specified for device with " 304 "non-byte multiplier\n"); 305 } else { 306 switch (cf->cf_loc[OBIOCF_MULT]) { 307 case 1: 308 oa->obio_iot = &gemini_bs_tag; 309 break; 310 #if 0 311 case 2: 312 oa->obio_iot = &gemini_a2x_bs_tag; 313 break; 314 #endif 315 case 4: 316 oa->obio_iot = &gemini_a4x_bs_tag; 317 break; 318 default: 319 panic("Unsupported obio bus multiplier."); 320 break; 321 } 322 } 323 oa->obio_addr = cf->cf_loc[OBIOCF_ADDR]; 324 oa->obio_size = cf->cf_loc[OBIOCF_SIZE]; 325 oa->obio_intr = cf->cf_loc[OBIOCF_INTR]; 326 oa->obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE]; 327 328 return config_match(parent, cf, oa); 329 } 330 331 #if NGEMINIICU == 0 332 #error no geminiicu present in config file 333 #endif 334 335 static const struct { 336 const char *name; 337 bus_addr_t addr; 338 bool required; 339 } critical_devs[] = { 340 #if defined(GEMINI_MASTER) || defined(GEMINI_SINGLE) 341 { .name = "geminiicu0", .addr = 0x48000000, .required = true }, 342 { .name = "geminiwdt0", .addr = 0x41000000, .required = true }, 343 { .name = "geminitmr0", .addr = 0x43000000, .required = true }, 344 { .name = "geminitmr2", .addr = 0x43000000, .required = true }, 345 { .name = "com0", .addr = 0x42000000, .required = true }, 346 #elif defined(GEMINI_SLAVE) 347 { .name = "geminiicu1", .addr = 0x49000000, .required = true }, 348 { .name = "geminitmr1", .addr = 0x43000000, .required = true }, 349 { .name = "geminitmr2", .addr = 0x43000000, .required = true }, 350 { .name = "geminilpchc0", .addr = 0x47000000, .required = true }, 351 #endif 352 }; 353 354 static void 355 obio_attach_critical(struct obio_softc *sc) 356 { 357 struct obio_attach_args oa; 358 cfdata_t cf; 359 size_t i; 360 361 for (i = 0; i < __arraycount(critical_devs); i++) { 362 oa.obio_iot = sc->sc_iot; 363 oa.obio_dmat = sc->sc_dmat; 364 365 oa.obio_addr = critical_devs[i].addr; 366 oa.obio_size = OBIOCF_SIZE_DEFAULT; 367 oa.obio_intr = OBIOCF_INTR_DEFAULT; 368 oa.obio_intrbase = OBIOCF_INTRBASE_DEFAULT; 369 370 #if 0 371 if (oa.obio_addr != OBIOCF_ADDR_DEFAULT 372 && (oa.obio_addr < sc->sc_base 373 || oa.obio_addr >= sc->sc_base + sc->sc_size)) 374 continue; 375 #endif 376 377 cf = config_search_ia(obio_find, sc->sc_dev, "obio", &oa); 378 if (cf == NULL && critical_devs[i].required) 379 panic("obio_attach_critical: failed to find %s!", 380 critical_devs[i].name); 381 382 oa.obio_addr = cf->cf_loc[OBIOCF_ADDR]; 383 oa.obio_size = cf->cf_loc[OBIOCF_SIZE]; 384 oa.obio_intr = cf->cf_loc[OBIOCF_INTR]; 385 oa.obio_intrbase = cf->cf_loc[OBIOCF_INTRBASE]; 386 config_attach(sc->sc_dev, cf, &oa, obio_print); 387 } 388 } 389 390 static int 391 obio_print(void *aux, const char *name) 392 { 393 struct obio_attach_args *oa = (struct obio_attach_args*)aux; 394 395 if (oa->obio_addr != OBIOCF_ADDR_DEFAULT) { 396 aprint_normal(" addr 0x%08lx", oa->obio_addr); 397 if (oa->obio_size != OBIOCF_SIZE_DEFAULT) 398 aprint_normal("-0x%08lx", 399 oa->obio_addr + oa->obio_size-1); 400 } 401 if (oa->obio_intr != OBIOCF_INTR_DEFAULT) 402 aprint_normal(" intr %d", oa->obio_intr); 403 if (oa->obio_intrbase != OBIOCF_INTRBASE_DEFAULT) 404 aprint_normal(" intrbase %d", oa->obio_intrbase); 405 406 return UNCONF; 407 } 408