1 /* $NetBSD: i80312.c,v 1.14 2003/06/15 23:08:57 fvdl Exp $ */ 2 3 /* 4 * Copyright (c) 2001, 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 i80312 Companion I/O chip. 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/i80312reg.h> 50 #include <arm/xscale/i80312var.h> 51 52 #include <dev/pci/ppbreg.h> 53 54 /* 55 * Statically-allocated bus_space stucture used to access the 56 * i80312's own registers. 57 */ 58 struct bus_space i80312_bs_tag; 59 60 /* 61 * There can be only one i80312, so we keep a global pointer to 62 * the softc, so board-specific code can use features of the 63 * i80312 without having to have a handle on the softc itself. 64 */ 65 struct i80312_softc *i80312_softc; 66 67 static void i80312_pci_dma_init(struct i80312_softc *); 68 69 static int i80312_pcibus_print(void *, const char *); 70 71 /* 72 * i80312_attach: 73 * 74 * Board-independent attach routine for the i80312. 75 */ 76 void 77 i80312_attach(struct i80312_softc *sc) 78 { 79 struct pcibus_attach_args pba; 80 uint32_t atucr; 81 pcireg_t preg; 82 83 i80312_softc = sc; 84 85 /* 86 * Slice off some useful subregion handles. 87 */ 88 89 if (bus_space_subregion(sc->sc_st, sc->sc_sh, I80312_PPB_BASE, 90 I80312_PPB_SIZE, &sc->sc_ppb_sh)) 91 panic("%s: unable to subregion PPB registers", 92 sc->sc_dev.dv_xname); 93 94 if (bus_space_subregion(sc->sc_st, sc->sc_sh, I80312_ATU_BASE, 95 I80312_ATU_SIZE, &sc->sc_atu_sh)) 96 panic("%s: unable to subregion ATU registers", 97 sc->sc_dev.dv_xname); 98 99 if (bus_space_subregion(sc->sc_st, sc->sc_sh, I80312_INTC_BASE, 100 I80312_INTC_SIZE, &sc->sc_intc_sh)) 101 panic("%s: unable to subregion INTC registers", 102 sc->sc_dev.dv_xname); 103 104 /* We expect the Memory Controller to be already sliced off. */ 105 106 /* 107 * Disable the private space decode. 108 */ 109 sc->sc_sder = bus_space_read_1(sc->sc_st, sc->sc_ppb_sh, 110 I80312_PPB_SDER); 111 sc->sc_sder &= ~PPB_SDER_PMSE; 112 bus_space_write_1(sc->sc_st, sc->sc_ppb_sh, 113 I80312_PPB_SDER, sc->sc_sder); 114 115 /* 116 * Program the Secondary ID Select register. 117 */ 118 bus_space_write_2(sc->sc_st, sc->sc_ppb_sh, 119 I80312_PPB_SISR, sc->sc_sisr); 120 121 /* 122 * Program the private secondary bus spaces. 123 */ 124 if (sc->sc_privmem_size && sc->sc_privio_size) { 125 bus_space_write_1(sc->sc_st, sc->sc_ppb_sh, I80312_PPB_SIOBR, 126 (sc->sc_privio_base >> 12) << 4); 127 bus_space_write_1(sc->sc_st, sc->sc_ppb_sh, I80312_PPB_SIOLR, 128 ((sc->sc_privio_base + sc->sc_privio_size - 1) 129 >> 12) << 4); 130 131 bus_space_write_2(sc->sc_st, sc->sc_ppb_sh, I80312_PPB_SMBR, 132 (sc->sc_privmem_base >> 20) << 4); 133 bus_space_write_2(sc->sc_st, sc->sc_ppb_sh, I80312_PPB_SMLR, 134 ((sc->sc_privmem_base + sc->sc_privmem_size - 1) 135 >> 20) << 4); 136 137 sc->sc_sder |= PPB_SDER_PMSE; 138 bus_space_write_1(sc->sc_st, sc->sc_ppb_sh, I80312_PPB_SDER, 139 sc->sc_sder); 140 } else if (sc->sc_privmem_size || sc->sc_privio_size) { 141 printf("%s: WARNING: privmem_size 0x%08x privio_size 0x%08x\n", 142 sc->sc_dev.dv_xname, sc->sc_privmem_size, 143 sc->sc_privio_size); 144 printf("%s: private bus spaces not enabled\n", 145 sc->sc_dev.dv_xname); 146 } 147 148 /* 149 * Program the Primary Inbound window. 150 */ 151 if (sc->sc_is_host) 152 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 153 PCI_MAPREG_START, sc->sc_pin_base); 154 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 155 I80312_ATU_PIAL, ATU_LIMIT(sc->sc_pin_size)); 156 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 157 I80312_ATU_PIATV, sc->sc_pin_xlate); 158 159 /* 160 * Program the Secondary Inbound window. 161 */ 162 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 163 I80312_ATU_SIAM, sc->sc_sin_base); 164 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 165 I80312_ATU_SIAL, ATU_LIMIT(sc->sc_sin_size)); 166 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 167 I80312_ATU_SIATV, sc->sc_sin_xlate); 168 169 /* 170 * Mask (disable) the ATU interrupt sources. 171 * XXX May want to revisit this if we encounter 172 * XXX an application that wants it. 173 */ 174 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 175 I80312_ATU_PAIM, 176 ATU_AIM_MPEIM | ATU_AIM_TATIM | ATU_AIM_TAMIM | 177 ATU_AIM_MAIM | ATU_AIM_SAIM | ATU_AIM_DPEIM | 178 ATU_AIM_PSTIM); 179 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 180 I80312_ATU_SAIM, 181 ATU_AIM_MPEIM | ATU_AIM_TATIM | ATU_AIM_TAMIM | 182 ATU_AIM_MAIM | ATU_AIM_SAIM | ATU_AIM_DPEIM); 183 184 /* 185 * Clear: 186 * 187 * Primary Outbound ATU Enable 188 * Secondary Outbound ATU Enable 189 * Secondary Direct Addressing Select 190 * Direct Addressing Enable 191 */ 192 atucr = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, I80312_ATU_ACR); 193 atucr &= ~(ATU_ACR_POAE|ATU_ACR_SOAE|ATU_ACR_SDAS|ATU_ACR_DAE); 194 195 /* 196 * Program the Primary Outbound windows. 197 */ 198 if (sc->sc_pmemout_size) 199 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 200 I80312_ATU_POMWV, sc->sc_pmemout_base); 201 if (sc->sc_pioout_size) 202 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 203 I80312_ATU_POIOWV, sc->sc_pioout_base); 204 if (sc->sc_pmemout_size || sc->sc_pioout_size) 205 atucr |= ATU_ACR_POAE; 206 207 /* 208 * Program the Secondary Outbound windows. 209 */ 210 if (sc->sc_smemout_size) 211 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 212 I80312_ATU_SOMWV, sc->sc_smemout_base); 213 if (sc->sc_sioout_size) 214 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 215 I80312_ATU_SOIOWV, sc->sc_sioout_base); 216 if (sc->sc_smemout_size || sc->sc_sioout_size) 217 atucr |= ATU_ACR_SOAE; 218 219 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, I80312_ATU_ACR, atucr); 220 221 /* 222 * Enable bus mastering, memory access, SERR, and parity 223 * checking on the ATU. 224 */ 225 if (sc->sc_is_host) { 226 preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, 227 PCI_COMMAND_STATUS_REG); 228 preg |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE | 229 PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE; 230 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 231 PCI_COMMAND_STATUS_REG, preg); 232 } 233 preg = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, 234 I80312_ATU_SACS); 235 preg |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE | 236 PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE; 237 bus_space_write_4(sc->sc_st, sc->sc_atu_sh, 238 I80312_ATU_SACS, preg); 239 240 /* 241 * Configure the bridge. If we're a host, set the primary 242 * bus to bus #0 and the secondary bus to bus #1. We also 243 * set the PPB's subordinate bus # to 1. It will be fixed 244 * up later when we fully configure the bus. 245 * 246 * If we're a slave, just use the bus #'s that the host 247 * provides. 248 */ 249 if (sc->sc_is_host) { 250 bus_space_write_4(sc->sc_st, sc->sc_ppb_sh, 251 PPB_REG_BUSINFO, 252 (0 << PCI_BRIDGE_BUS_PRIMARY_SHIFT) | 253 (1 << PCI_BRIDGE_BUS_SECONDARY_SHIFT) | 254 (1 << PCI_BRIDGE_BUS_SUBORDINATE_SHIFT)); 255 } 256 257 /* Initialize the bus space tags. */ 258 i80312_io_bs_init(&sc->sc_pci_iot, sc); 259 i80312_mem_bs_init(&sc->sc_pci_memt, sc); 260 261 /* Initialize the PCI chipset tag. */ 262 i80312_pci_init(&sc->sc_pci_chipset, sc); 263 264 /* Initialize the DMA tags. */ 265 i80312_pci_dma_init(sc); 266 267 /* 268 * Attach the PCI bus. 269 * 270 * Note: We only probe the Secondary PCI bus, since that 271 * is the only bus on which we can have a private device 272 * space. 273 */ 274 preg = bus_space_read_4(sc->sc_st, sc->sc_ppb_sh, PPB_REG_BUSINFO); 275 pba.pba_busname = "pci"; 276 pba.pba_iot = &sc->sc_pci_iot; 277 pba.pba_memt = &sc->sc_pci_memt; 278 pba.pba_dmat = &sc->sc_pci_dmat; 279 pba.pba_dmat64 = NULL; 280 pba.pba_pc = &sc->sc_pci_chipset; 281 pba.pba_bus = PPB_BUSINFO_SECONDARY(preg); 282 pba.pba_bridgetag = NULL; 283 pba.pba_intrswiz = 3; 284 pba.pba_intrtag = 0; 285 /* XXX MRL/MRM/MWI seem to have problems, at the moment. */ 286 pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED /* | 287 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY */; 288 (void) config_found(&sc->sc_dev, &pba, i80312_pcibus_print); 289 } 290 291 /* 292 * i80312_pcibus_print: 293 * 294 * Autoconfiguration cfprint routine when attaching 295 * to the "pcibus" attribute. 296 */ 297 static int 298 i80312_pcibus_print(void *aux, const char *pnp) 299 { 300 struct pcibus_attach_args *pba = aux; 301 302 if (pnp) 303 aprint_normal("%s at %s", pba->pba_busname, pnp); 304 305 aprint_normal(" bus %d", pba->pba_bus); 306 307 return (UNCONF); 308 } 309 310 /* 311 * i80312_pci_dma_init: 312 * 313 * Initialize the PCI DMA tag. 314 */ 315 static void 316 i80312_pci_dma_init(struct i80312_softc *sc) 317 { 318 bus_dma_tag_t dmat = &sc->sc_pci_dmat; 319 struct arm32_dma_range *dr = &sc->sc_pci_dma_range; 320 321 dr->dr_sysbase = sc->sc_sin_xlate; 322 dr->dr_busbase = sc->sc_sin_base; 323 dr->dr_len = sc->sc_sin_size; 324 325 dmat->_ranges = dr; 326 dmat->_nranges = 1; 327 328 dmat->_dmamap_create = _bus_dmamap_create; 329 dmat->_dmamap_destroy = _bus_dmamap_destroy; 330 dmat->_dmamap_load = _bus_dmamap_load; 331 dmat->_dmamap_load_mbuf = _bus_dmamap_load_mbuf; 332 dmat->_dmamap_load_uio = _bus_dmamap_load_uio; 333 dmat->_dmamap_load_raw = _bus_dmamap_load_raw; 334 dmat->_dmamap_unload = _bus_dmamap_unload; 335 dmat->_dmamap_sync_pre = _bus_dmamap_sync; 336 dmat->_dmamap_sync_post = NULL; 337 338 dmat->_dmamem_alloc = _bus_dmamem_alloc; 339 dmat->_dmamem_free = _bus_dmamem_free; 340 dmat->_dmamem_map = _bus_dmamem_map; 341 dmat->_dmamem_unmap = _bus_dmamem_unmap; 342 dmat->_dmamem_mmap = _bus_dmamem_mmap; 343 } 344