1 /* $NetBSD: i80321.c,v 1.8 2002/09/27 15:35:51 provos Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* 39 * Autoconfiguration support for the Intel i80321 I/O Processor. 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/device.h> 45 46 #define _ARM32_BUS_DMA_PRIVATE 47 #include <machine/bus.h> 48 49 #include <arm/xscale/i80321reg.h> 50 #include <arm/xscale/i80321var.h> 51 52 /* 53 * Statically-allocated bus_space stucture used to access the 54 * i80321's own registers. 55 */ 56 struct bus_space i80321_bs_tag; 57 58 /* 59 * There can be only one i80321, so we keep a global pointer to 60 * the softc, so board-specific code can use features of the 61 * i80321 without having to have a handle on the softc itself. 62 */ 63 struct i80321_softc *i80321_softc; 64 65 static int i80321_iopxs_print(void *, const char *); 66 static int i80321_pcibus_print(void *, const char *); 67 68 /* Built-in devices. */ 69 static const struct iopxs_device { 70 const char *id_name; 71 bus_addr_t id_offset; 72 bus_size_t id_size; 73 } iopxs_devices[] = { 74 { "iopaau", VERDE_AAU_BASE, VERDE_AAU_SIZE }, 75 { "iopdma", VERDE_DMA_BASE, VERDE_DMA_SIZE }, 76 { "iopssp", VERDE_SSP_BASE, VERDE_SSP_SIZE }, 77 { "iopwdog", 0, 0 }, 78 { NULL, 0, 0 } 79 }; 80 81 static void i80321_pci_dma_init(struct i80321_softc *); 82 static void i80321_local_dma_init(struct i80321_softc *); 83 84 /* 85 * i80321_attach: 86 * 87 * Board-independent attach routine for the i80321. 88 */ 89 void 90 i80321_attach(struct i80321_softc *sc) 91 { 92 struct pcibus_attach_args pba; 93 const struct iopxs_device *id; 94 struct iopxs_attach_args ia; 95 pcireg_t preg; 96 97 i80321_softc = sc; 98 99 /* 100 * Slice off some useful subregion handles. 101 */ 102 103 if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE, 104 VERDE_ATU_SIZE, &sc->sc_atu_sh)) 105 panic("%s: unable to subregion ATU registers", 106 sc->sc_dev.dv_xname); 107 108 /* We expect the Memory Controller to be already sliced off. */ 109 110 /* 111 * Program the Inbound windows. 112 */ 113 if (sc->sc_is_host) { 114 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 115 PCI_MAPREG_START, sc->sc_iwin[0].iwin_base_lo); 116 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 117 PCI_MAPREG_START + 0x04, sc->sc_iwin[0].iwin_base_hi); 118 } 119 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR0, 120 (0xffffffff - (sc->sc_iwin[0].iwin_size - 1)) & 0xffffffc0); 121 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR0, 122 sc->sc_iwin[0].iwin_xlate); 123 124 if (sc->sc_is_host) { 125 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 126 PCI_MAPREG_START + 0x08, sc->sc_iwin[1].iwin_base_lo); 127 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 128 PCI_MAPREG_START + 0x0c, sc->sc_iwin[1].iwin_base_hi); 129 } 130 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR1, 131 (0xffffffff - (sc->sc_iwin[1].iwin_size - 1)) & 0xffffffc0); 132 /* no xlate for window 1 */ 133 134 if (sc->sc_is_host) { 135 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 136 PCI_MAPREG_START + 0x10, sc->sc_iwin[2].iwin_base_lo); 137 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 138 PCI_MAPREG_START + 0x14, sc->sc_iwin[2].iwin_base_hi); 139 } 140 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR2, 141 (0xffffffff - (sc->sc_iwin[2].iwin_size - 1)) & 0xffffffc0); 142 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR2, 143 sc->sc_iwin[2].iwin_xlate); 144 145 if (sc->sc_is_host) { 146 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 147 ATU_IABAR3, sc->sc_iwin[3].iwin_base_lo); 148 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 149 ATU_IAUBAR3, sc->sc_iwin[3].iwin_base_hi); 150 } 151 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IALR3, 152 (0xffffffff - (sc->sc_iwin[3].iwin_size - 1)) & 0xffffffc0); 153 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_IATVR3, 154 sc->sc_iwin[3].iwin_xlate); 155 156 /* 157 * Mask (disable) the ATU interrupt sources. 158 * XXX May want to revisit this if we encounter 159 * XXX an application that wants it. 160 */ 161 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 162 ATU_ATUIMR, 163 ATUIMR_IMW1BU|ATUIMR_ISCEM|ATUIMR_RSCEM|ATUIMR_PST| 164 ATUIMR_DPE|ATUIMR_P_SERR_ASRT|ATUIMR_PMA|ATUIMR_PTAM| 165 ATUIMR_PTAT|ATUIMR_PMPE); 166 167 /* 168 * Program the outbound windows. 169 */ 170 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 171 ATU_OIOWTVR, sc->sc_ioout_xlate); 172 173 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 174 ATU_OMWTVR0, sc->sc_owin[0].owin_xlate_lo); 175 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 176 ATU_OUMWTVR0, sc->sc_owin[0].owin_xlate_hi); 177 178 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 179 ATU_OMWTVR1, sc->sc_owin[1].owin_xlate_lo); 180 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 181 ATU_OUMWTVR1, sc->sc_owin[1].owin_xlate_hi); 182 183 /* 184 * Set up the ATU configuration register. All we do 185 * right now is enable Outbound Windows. 186 */ 187 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUCR, 188 ATUCR_OUT_EN); 189 190 /* 191 * Enable bus mastering, memory access, SERR, and parity 192 * checking on the ATU. 193 */ 194 if (sc->sc_is_host) { 195 preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, 196 PCI_COMMAND_STATUS_REG); 197 preg |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE | 198 PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE; 199 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 200 PCI_COMMAND_STATUS_REG, preg); 201 } 202 203 /* Initialize the bus space tags. */ 204 i80321_io_bs_init(&sc->sc_pci_iot, sc); 205 i80321_mem_bs_init(&sc->sc_pci_memt, sc); 206 207 /* Initialize the PCI chipset tag. */ 208 i80321_pci_init(&sc->sc_pci_chipset, sc); 209 210 /* Initialize the DMA tags. */ 211 i80321_pci_dma_init(sc); 212 i80321_local_dma_init(sc); 213 214 /* 215 * Attach all the IOP built-ins. 216 */ 217 for (id = iopxs_devices; id->id_name != NULL; id++) { 218 ia.ia_name = id->id_name; 219 ia.ia_st = sc->sc_st; 220 ia.ia_sh = sc->sc_sh; 221 ia.ia_dmat = &sc->sc_local_dmat; 222 ia.ia_offset = id->id_offset; 223 ia.ia_size = id->id_size; 224 225 (void) config_found(&sc->sc_dev, &ia, i80321_iopxs_print); 226 } 227 228 /* 229 * Attach the PCI bus. 230 */ 231 preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR); 232 preg = PCIXSR_BUSNO(preg); 233 if (preg == 0xff) 234 preg = 0; 235 pba.pba_busname = "pci"; 236 pba.pba_iot = &sc->sc_pci_iot; 237 pba.pba_memt = &sc->sc_pci_memt; 238 pba.pba_dmat = &sc->sc_pci_dmat; 239 pba.pba_pc = &sc->sc_pci_chipset; 240 pba.pba_bus = preg; 241 pba.pba_bridgetag = NULL; 242 pba.pba_intrswiz = 0; /* XXX what if busno != 0? */ 243 pba.pba_intrtag = 0; 244 pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED | 245 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; 246 (void) config_found(&sc->sc_dev, &pba, i80321_pcibus_print); 247 } 248 249 /* 250 * i80321_iopxs_print: 251 * 252 * Autoconfiguration cfprint routine when attaching 253 * to the "iopxs" device. 254 */ 255 static int 256 i80321_iopxs_print(void *aux, const char *pnp) 257 { 258 259 return (QUIET); 260 } 261 262 /* 263 * i80321_pcibus_print: 264 * 265 * Autoconfiguration cfprint routine when attaching 266 * to the "pcibus" attribute. 267 */ 268 static int 269 i80321_pcibus_print(void *aux, const char *pnp) 270 { 271 struct pcibus_attach_args *pba = aux; 272 273 if (pnp) 274 printf("%s at %s", pba->pba_busname, pnp); 275 276 printf(" bus %d", pba->pba_bus); 277 278 return (UNCONF); 279 } 280 281 /* 282 * i80321_pci_dma_init: 283 * 284 * Initialize the PCI DMA tag. 285 */ 286 static void 287 i80321_pci_dma_init(struct i80321_softc *sc) 288 { 289 bus_dma_tag_t dmat = &sc->sc_pci_dmat; 290 struct arm32_dma_range *dr = &sc->sc_pci_dma_range; 291 292 dr->dr_sysbase = sc->sc_iwin[2].iwin_xlate; 293 dr->dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo); 294 dr->dr_len = sc->sc_iwin[2].iwin_size; 295 296 dmat->_ranges = dr; 297 dmat->_nranges = 1; 298 299 dmat->_dmamap_create = _bus_dmamap_create; 300 dmat->_dmamap_destroy = _bus_dmamap_destroy; 301 dmat->_dmamap_load = _bus_dmamap_load; 302 dmat->_dmamap_load_mbuf = _bus_dmamap_load_mbuf; 303 dmat->_dmamap_load_uio = _bus_dmamap_load_uio; 304 dmat->_dmamap_load_raw = _bus_dmamap_load_raw; 305 dmat->_dmamap_unload = _bus_dmamap_unload; 306 dmat->_dmamap_sync_pre = _bus_dmamap_sync; 307 dmat->_dmamap_sync_post = NULL; 308 309 dmat->_dmamem_alloc = _bus_dmamem_alloc; 310 dmat->_dmamem_free = _bus_dmamem_free; 311 dmat->_dmamem_map = _bus_dmamem_map; 312 dmat->_dmamem_unmap = _bus_dmamem_unmap; 313 dmat->_dmamem_mmap = _bus_dmamem_mmap; 314 } 315 316 /* 317 * i80321_local_dma_init: 318 * 319 * Initialize the local DMA tag. 320 */ 321 static void 322 i80321_local_dma_init(struct i80321_softc *sc) 323 { 324 bus_dma_tag_t dmat = &sc->sc_local_dmat; 325 326 dmat->_ranges = NULL; 327 dmat->_nranges = 0; 328 329 dmat->_dmamap_create = _bus_dmamap_create; 330 dmat->_dmamap_destroy = _bus_dmamap_destroy; 331 dmat->_dmamap_load = _bus_dmamap_load; 332 dmat->_dmamap_load_mbuf = _bus_dmamap_load_mbuf; 333 dmat->_dmamap_load_uio = _bus_dmamap_load_uio; 334 dmat->_dmamap_load_raw = _bus_dmamap_load_raw; 335 dmat->_dmamap_unload = _bus_dmamap_unload; 336 dmat->_dmamap_sync_pre = _bus_dmamap_sync; 337 dmat->_dmamap_sync_post = NULL; 338 339 dmat->_dmamem_alloc = _bus_dmamem_alloc; 340 dmat->_dmamem_free = _bus_dmamem_free; 341 dmat->_dmamem_map = _bus_dmamem_map; 342 dmat->_dmamem_unmap = _bus_dmamem_unmap; 343 dmat->_dmamem_mmap = _bus_dmamem_mmap; 344 } 345