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