1 /* $NetBSD: becc.c,v 1.6 2003/06/15 23:08:57 fvdl Exp $ */ 2 3 /* 4 * Copyright (c) 2002, 2003 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 ADI Engineering Big Endian 40 * Companion Chip. 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/device.h> 46 47 #define _ARM32_BUS_DMA_PRIVATE 48 #include <machine/bus.h> 49 50 #include <arm/xscale/i80200reg.h> 51 #include <arm/xscale/beccreg.h> 52 #include <arm/xscale/beccvar.h> 53 54 /* 55 * Virtual address at which the BECC is mapped. This is filled in 56 * by machine-dependent code. 57 */ 58 vaddr_t becc_vaddr; 59 60 /* 61 * BECC revision number. This is initialized by early bootstrap code. 62 */ 63 int becc_rev; 64 const char *becc_revisions[] = { 65 "<= 7", 66 "8", 67 ">= 9", 68 }; 69 70 /* 71 * There can be only one BECC, so we keep a global pointer to 72 * the softc, so board-specific code can use features of the 73 * BECC without having to have a handle on the softc itself. 74 */ 75 struct becc_softc *becc_softc; 76 77 static int becc_pcibus_print(void *, const char *); 78 79 static int becc_search(struct device *, struct cfdata *, void *); 80 static int becc_print(void *, const char *); 81 82 static void becc_pci_dma_init(struct becc_softc *); 83 static void becc_local_dma_init(struct becc_softc *); 84 85 /* 86 * becc_attach: 87 * 88 * Board-independent attach routine for the BECC. 89 */ 90 void 91 becc_attach(struct becc_softc *sc) 92 { 93 struct pcibus_attach_args pba; 94 uint32_t reg; 95 96 becc_softc = sc; 97 98 /* 99 * Set the AF bit in the BCUMOD since the BECC will honor it. 100 * This allows the BECC to return the requested 4-byte word 101 * first when filling a cache line. 102 */ 103 __asm __volatile("mrc p13, 0, %0, c1, c1, 0" : "=r" (reg)); 104 __asm __volatile("mcr p13, 0, %0, c1, c1, 0" : : "r" (reg | BCUMOD_AF)); 105 106 /* 107 * Program the address windows of the PCI core. Note 108 * that PCI master and target cycles must be disabled 109 * while we configure the windows. 110 */ 111 reg = becc_pcicore_read(sc, PCI_COMMAND_STATUS_REG); 112 reg &= ~(PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE); 113 becc_pcicore_write(sc, PCI_COMMAND_STATUS_REG, reg); 114 115 /* 116 * Program the two inbound PCI memory windows. 117 */ 118 becc_pcicore_write(sc, PCI_MAPREG_START + 0, 119 sc->sc_iwin[0].iwin_base | PCI_MAPREG_MEM_TYPE_32BIT | 120 PCI_MAPREG_MEM_PREFETCHABLE_MASK); 121 reg = becc_pcicore_read(sc, PCI_MAPREG_START + 0); 122 BECC_CSR_WRITE(BECC_PSTR0, sc->sc_iwin[0].iwin_xlate & PSTRx_ADDRMASK); 123 124 becc_pcicore_write(sc, PCI_MAPREG_START + 4, 125 sc->sc_iwin[1].iwin_base | PCI_MAPREG_MEM_TYPE_32BIT | 126 PCI_MAPREG_MEM_PREFETCHABLE_MASK); 127 reg = becc_pcicore_read(sc, PCI_MAPREG_START + 4); 128 BECC_CSR_WRITE(BECC_PSTR1, sc->sc_iwin[1].iwin_xlate & PSTRx_ADDRMASK); 129 130 /* 131 * ...and the third on v8 and later. 132 */ 133 if (becc_rev >= BECC_REV_V8) { 134 becc_pcicore_write(sc, PCI_MAPREG_START + 8, 135 sc->sc_iwin[2].iwin_base | PCI_MAPREG_MEM_TYPE_32BIT | 136 PCI_MAPREG_MEM_PREFETCHABLE_MASK); 137 reg = becc_pcicore_read(sc, PCI_MAPREG_START + 8); 138 BECC_CSR_WRITE(BECC_PSTR2, 139 sc->sc_iwin[2].iwin_xlate & PSTR2_ADDRMASK); 140 } 141 142 /* 143 * Program the two outbound PCI memory windows. 144 * NOTE: WE DO NOT BYTE-SWAP OUTBOUND WINDOWS IN BIG-ENDIAN 145 * MODE. I know this seems counter-intuitive, but that's 146 * how it is. 147 * 148 * There's a third window on v9 and later, but we don't 149 * use it for anything; program it anyway, just to be 150 * safe. 151 */ 152 BECC_CSR_WRITE(BECC_POMR1, sc->sc_owin_xlate[0] /* | POMRx_F32 */); 153 BECC_CSR_WRITE(BECC_POMR2, sc->sc_owin_xlate[1] /* | POMRx_F32 */); 154 155 if (becc_rev >= BECC_REV_V9) 156 BECC_CSR_WRITE(BECC_POMR3, 157 sc->sc_owin_xlate[2] /* | POMRx_F32 */); 158 159 /* 160 * Program the PCI I/O window. See note above about byte-swapping. 161 * 162 * XXX What about STREAM transfers? 163 */ 164 BECC_CSR_WRITE(BECC_POIR, sc->sc_ioout_xlate); 165 166 /* 167 * Configure PCI configuration cycle access. 168 */ 169 BECC_CSR_WRITE(BECC_POCR, 0); 170 171 /* 172 * ...and now reenable PCI access. 173 */ 174 reg = becc_pcicore_read(sc, PCI_COMMAND_STATUS_REG); 175 reg |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE | 176 PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE; 177 becc_pcicore_write(sc, PCI_COMMAND_STATUS_REG, reg); 178 179 /* Initialize the bus space tags. */ 180 becc_io_bs_init(&sc->sc_pci_iot, sc); 181 becc_mem_bs_init(&sc->sc_pci_memt, sc); 182 183 /* Initialize the PCI chipset tag. */ 184 becc_pci_init(&sc->sc_pci_chipset, sc); 185 186 /* Initialize the DMA tags. */ 187 becc_pci_dma_init(sc); 188 becc_local_dma_init(sc); 189 190 /* 191 * Attach any on-chip peripherals. We used indirect config, since 192 * the BECC is a soft-core with a variety of peripherals, depending 193 * on configuration. 194 */ 195 config_search(becc_search, &sc->sc_dev, NULL); 196 197 /* 198 * Attach the PCI bus. 199 */ 200 pba.pba_busname = "pci"; 201 pba.pba_iot = &sc->sc_pci_iot; 202 pba.pba_memt = &sc->sc_pci_memt; 203 pba.pba_dmat = &sc->sc_pci_dmat; 204 pba.pba_dmat64 = NULL; 205 pba.pba_pc = &sc->sc_pci_chipset; 206 pba.pba_bus = 0; 207 pba.pba_bridgetag = NULL; 208 pba.pba_intrswiz = 0; 209 pba.pba_intrtag = 0; 210 pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED | 211 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; 212 (void) config_found(&sc->sc_dev, &pba, becc_pcibus_print); 213 } 214 215 /* 216 * becc_pcibus_print: 217 * 218 * Autoconfiguration cfprint routine when attaching 219 * to the "pcibus" attribute. 220 */ 221 static int 222 becc_pcibus_print(void *aux, const char *pnp) 223 { 224 struct pcibus_attach_args *pba = aux; 225 226 if (pnp) 227 aprint_normal("%s at %s", pba->pba_busname, pnp); 228 229 aprint_normal(" bus %d", pba->pba_bus); 230 231 return (UNCONF); 232 } 233 234 /* 235 * becc_search: 236 * 237 * Indirect autoconfiguration glue for BECC. 238 */ 239 static int 240 becc_search(struct device *parent, struct cfdata *cf, void *aux) 241 { 242 struct becc_softc *sc = (void *) parent; 243 struct becc_attach_args ba; 244 245 ba.ba_dmat = &sc->sc_local_dmat; 246 247 if (config_match(parent, cf, &ba) > 0) 248 config_attach(parent, cf, &ba, becc_print); 249 250 return (0); 251 } 252 253 /* 254 * becc_print: 255 * 256 * Autoconfiguration cfprint routine when attaching 257 * to the BECC. 258 */ 259 static int 260 becc_print(void *aux, const char *pnp) 261 { 262 263 return (UNCONF); 264 } 265 266 /* 267 * becc_pci_dma_init: 268 * 269 * Initialize the PCI DMA tag. 270 */ 271 static void 272 becc_pci_dma_init(struct becc_softc *sc) 273 { 274 bus_dma_tag_t dmat = &sc->sc_pci_dmat; 275 struct arm32_dma_range *dr = sc->sc_pci_dma_range; 276 int i = 0; 277 278 /* 279 * If we have the 128MB window, put it first, since it 280 * will always cover the entire memory range. 281 */ 282 if (becc_rev >= BECC_REV_V8) { 283 dr[i].dr_sysbase = sc->sc_iwin[2].iwin_xlate; 284 dr[i].dr_busbase = sc->sc_iwin[2].iwin_base; 285 dr[i].dr_len = (128U * 1024 * 1024); 286 i++; 287 } 288 289 dr[i].dr_sysbase = sc->sc_iwin[0].iwin_xlate; 290 dr[i].dr_busbase = sc->sc_iwin[0].iwin_base; 291 dr[i].dr_len = (32U * 1024 * 1024); 292 i++; 293 294 dr[i].dr_sysbase = sc->sc_iwin[1].iwin_xlate; 295 dr[i].dr_busbase = sc->sc_iwin[1].iwin_base; 296 dr[i].dr_len = (32U * 1024 * 1024); 297 i++; 298 299 dmat->_ranges = dr; 300 dmat->_nranges = i; 301 302 dmat->_dmamap_create = _bus_dmamap_create; 303 dmat->_dmamap_destroy = _bus_dmamap_destroy; 304 dmat->_dmamap_load = _bus_dmamap_load; 305 dmat->_dmamap_load_mbuf = _bus_dmamap_load_mbuf; 306 dmat->_dmamap_load_uio = _bus_dmamap_load_uio; 307 dmat->_dmamap_load_raw = _bus_dmamap_load_raw; 308 dmat->_dmamap_unload = _bus_dmamap_unload; 309 dmat->_dmamap_sync_pre = _bus_dmamap_sync; 310 dmat->_dmamap_sync_post = NULL; 311 312 dmat->_dmamem_alloc = _bus_dmamem_alloc; 313 dmat->_dmamem_free = _bus_dmamem_free; 314 dmat->_dmamem_map = _bus_dmamem_map; 315 dmat->_dmamem_unmap = _bus_dmamem_unmap; 316 dmat->_dmamem_mmap = _bus_dmamem_mmap; 317 } 318 319 /* 320 * becc_local_dma_init: 321 * 322 * Initialize the local DMA tag. 323 */ 324 static void 325 becc_local_dma_init(struct becc_softc *sc) 326 { 327 bus_dma_tag_t dmat = &sc->sc_local_dmat; 328 329 dmat->_ranges = NULL; 330 dmat->_nranges = 0; 331 332 dmat->_dmamap_create = _bus_dmamap_create; 333 dmat->_dmamap_destroy = _bus_dmamap_destroy; 334 dmat->_dmamap_load = _bus_dmamap_load; 335 dmat->_dmamap_load_mbuf = _bus_dmamap_load_mbuf; 336 dmat->_dmamap_load_uio = _bus_dmamap_load_uio; 337 dmat->_dmamap_load_raw = _bus_dmamap_load_raw; 338 dmat->_dmamap_unload = _bus_dmamap_unload; 339 dmat->_dmamap_sync_pre = _bus_dmamap_sync; 340 dmat->_dmamap_sync_post = NULL; 341 342 dmat->_dmamem_alloc = _bus_dmamem_alloc; 343 dmat->_dmamem_free = _bus_dmamem_free; 344 dmat->_dmamem_map = _bus_dmamem_map; 345 dmat->_dmamem_unmap = _bus_dmamem_unmap; 346 dmat->_dmamem_mmap = _bus_dmamem_mmap; 347 } 348 349 uint32_t 350 becc_pcicore_read(struct becc_softc *sc, bus_addr_t reg) 351 { 352 vaddr_t va = sc->sc_pci_cfg_base | (1U << BECC_IDSEL_BIT) | reg; 353 354 return (*(__volatile uint32_t *) va); 355 } 356 357 void 358 becc_pcicore_write(struct becc_softc *sc, bus_addr_t reg, uint32_t val) 359 { 360 vaddr_t va = sc->sc_pci_cfg_base | (1U << BECC_IDSEL_BIT) | reg; 361 362 *(__volatile uint32_t *) va = val; 363 } 364