1 /* $NetBSD: footbridge.c,v 1.7 2002/05/16 01:01:33 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1997,1998 Mark Brinicombe. 5 * Copyright (c) 1997,1998 Causality Limited 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Mark Brinicombe 19 * for the NetBSD Project. 20 * 4. The name of the company nor the name of the author may be used to 21 * endorse or promote products derived from this software without specific 22 * prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/conf.h> 41 #include <sys/malloc.h> 42 #include <sys/device.h> 43 44 #include <dev/pci/pcivar.h> 45 #define _ARM32_BUS_DMA_PRIVATE 46 #include <machine/bus.h> 47 #include <machine/intr.h> 48 49 #include <arm/cpuconf.h> 50 #include <arm/cpufunc.h> 51 52 #include <arm/footbridge/footbridgevar.h> 53 #include <arm/footbridge/dc21285reg.h> 54 #include <arm/footbridge/dc21285mem.h> 55 #include <arm/footbridge/footbridge.h> 56 57 /* 58 * DC21285 'Footbridge' device 59 * 60 * This probes and attaches the footbridge device 61 * It then configures any children 62 */ 63 64 /* Declare prototypes */ 65 66 static int footbridge_match __P((struct device *parent, struct cfdata *cf, 67 void *aux)); 68 static void footbridge_attach __P((struct device *parent, struct device *self, 69 void *aux)); 70 static int footbridge_print __P((void *aux, const char *pnp)); 71 static int footbridge_intr __P((void *arg)); 72 73 /* Driver and attach structures */ 74 struct cfattach footbridge_ca = { 75 sizeof(struct footbridge_softc), footbridge_match, footbridge_attach 76 }; 77 78 /* Various bus space tags */ 79 extern struct bus_space footbridge_bs_tag; 80 extern void footbridge_create_io_bs_tag(bus_space_tag_t t, void *cookie); 81 extern void footbridge_create_mem_bs_tag(bus_space_tag_t t, void *cookie); 82 struct bus_space footbridge_csr_tag; 83 struct bus_space footbridge_pci_io_bs_tag; 84 struct bus_space footbridge_pci_mem_bs_tag; 85 extern struct arm32_pci_chipset footbridge_pci_chipset; 86 extern struct arm32_bus_dma_tag footbridge_pci_bus_dma_tag; 87 88 /* Used in footbridge_clock.c */ 89 struct footbridge_softc *clock_sc; 90 91 /* Set to non-zero to enable verbose reporting of footbridge system ints */ 92 int footbridge_intr_report = 0; 93 94 int footbridge_found; 95 96 void 97 footbridge_pci_bs_tag_init(void) 98 { 99 /* Set up the PCI bus tags */ 100 footbridge_create_io_bs_tag(&footbridge_pci_io_bs_tag, 101 (void *)DC21285_PCI_IO_VBASE); 102 footbridge_create_mem_bs_tag(&footbridge_pci_mem_bs_tag, 103 (void *)DC21285_PCI_MEM_BASE); 104 } 105 106 /* 107 * int footbridgeprint(void *aux, const char *name) 108 * 109 * print configuration info for children 110 */ 111 112 static int 113 footbridge_print(aux, pnp) 114 void *aux; 115 const char *pnp; 116 { 117 union footbridge_attach_args *fba = aux; 118 119 if (pnp) 120 printf("%s at %s", fba->fba_name, pnp); 121 if (strcmp(fba->fba_name, "pci") == 0) 122 printf(" bus %d", fba->fba_pba.pba_bus); 123 return(UNCONF); 124 } 125 126 /* 127 * int footbridge_match(struct device *parent, struct cfdata *cf, void *aux) 128 * 129 * Just return ok for this if it is device 0 130 */ 131 132 static int 133 footbridge_match(parent, cf, aux) 134 struct device *parent; 135 struct cfdata *cf; 136 void *aux; 137 { 138 if (footbridge_found) 139 return(0); 140 return(1); 141 } 142 143 144 /* 145 * void footbridge_attach(struct device *parent, struct device *dev, void *aux) 146 * 147 */ 148 149 static void 150 footbridge_attach(parent, self, aux) 151 struct device *parent; 152 struct device *self; 153 void *aux; 154 { 155 struct footbridge_softc *sc = (struct footbridge_softc *)self; 156 union footbridge_attach_args fba; 157 int vendor, device, rev; 158 159 /* There can only be 1 footbridge. */ 160 footbridge_found = 1; 161 162 clock_sc = sc; 163 164 sc->sc_iot = &footbridge_bs_tag; 165 166 /* Map the Footbridge */ 167 if (bus_space_map(sc->sc_iot, DC21285_ARMCSR_VBASE, 168 DC21285_ARMCSR_VSIZE, 0, &sc->sc_ioh)) 169 panic("%s: Cannot map registers\n", self->dv_xname); 170 171 /* Read the ID to make sure it is what we think it is */ 172 vendor = bus_space_read_2(sc->sc_iot, sc->sc_ioh, VENDOR_ID); 173 device = bus_space_read_2(sc->sc_iot, sc->sc_ioh, DEVICE_ID); 174 rev = bus_space_read_1(sc->sc_iot, sc->sc_ioh, REVISION); 175 if (vendor != DC21285_VENDOR_ID && device != DC21285_DEVICE_ID) 176 panic("%s: Unrecognised ID\n", self->dv_xname); 177 178 printf(": DC21285 rev %d\n", rev); 179 180 /* Disable all interrupts from the footbridge */ 181 bus_space_write_4(sc->sc_iot, sc->sc_ioh, IRQ_ENABLE_CLEAR, 0xffffffff); 182 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FIQ_ENABLE_CLEAR, 0xffffffff); 183 184 /* bus_space_write_4(sc->sc_iot, sc->sc_ioh, 0x18, 0x40000000);*/ 185 186 /* Install a generic handler to catch a load of system interrupts */ 187 sc->sc_serr_ih = intr_claim(IRQ_SERR, IPL_NONE, 188 "serr", footbridge_intr, sc); 189 sc->sc_sdram_par_ih = intr_claim(IRQ_SDRAM_PARITY, IPL_NONE, 190 "sdram parity", footbridge_intr, sc); 191 sc->sc_data_par_ih = intr_claim(IRQ_DATA_PARITY, IPL_NONE, 192 "data parity", footbridge_intr, sc); 193 sc->sc_master_abt_ih = intr_claim(IRQ_MASTER_ABORT, IPL_NONE, 194 "mast abt", footbridge_intr, sc); 195 sc->sc_target_abt_ih = intr_claim(IRQ_TARGET_ABORT, IPL_NONE, 196 "targ abt", footbridge_intr, sc); 197 sc->sc_parity_ih = intr_claim(IRQ_PARITY, IPL_NONE, 198 "parity", footbridge_intr, sc); 199 200 /* Set up the PCI bus tags */ 201 footbridge_create_io_bs_tag(&footbridge_pci_io_bs_tag, 202 (void *)DC21285_PCI_IO_VBASE); 203 footbridge_create_mem_bs_tag(&footbridge_pci_mem_bs_tag, 204 (void *)DC21285_PCI_MEM_BASE); 205 206 /* calibrate the delay loop */ 207 calibrate_delay(); 208 /* Attach the PCI bus */ 209 fba.fba_pba.pba_busname = "pci"; 210 fba.fba_pba.pba_pc = &footbridge_pci_chipset; 211 fba.fba_pba.pba_iot = &footbridge_pci_io_bs_tag; 212 fba.fba_pba.pba_memt = &footbridge_pci_mem_bs_tag; 213 fba.fba_pba.pba_dmat = &footbridge_pci_bus_dma_tag; 214 fba.fba_pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED; 215 fba.fba_pba.pba_bus = 0; 216 fba.fba_pba.pba_bridgetag = NULL; 217 config_found(self, &fba.fba_pba, footbridge_print); 218 219 /* Attach a time-of-day clock device */ 220 fba.fba_tca.ta_name = "todclock"; 221 fba.fba_tca.ta_rtc_arg = NULL; 222 fba.fba_tca.ta_rtc_write = NULL; 223 fba.fba_tca.ta_rtc_read = NULL; 224 fba.fba_tca.ta_flags = TODCLOCK_FLAG_FAKE; 225 config_found(self, &fba.fba_tca, footbridge_print); 226 227 /* Attach uart device */ 228 fba.fba_fca.fca_name = "fcom"; 229 fba.fba_fca.fca_iot = sc->sc_iot; 230 fba.fba_fca.fca_ioh = sc->sc_ioh; 231 fba.fba_fca.fca_rx_irq = IRQ_SERIAL_RX; 232 fba.fba_fca.fca_tx_irq = IRQ_SERIAL_TX; 233 config_found(self, &fba.fba_fca, footbridge_print); 234 235 /* Setup fast SA110 cache clean area */ 236 #ifdef CPU_SA110 237 if (cputype == CPU_ID_SA110) 238 footbridge_sa110_cc_setup(); 239 #endif /* CPU_SA110 */ 240 241 } 242 243 /* Generic footbridge interrupt handler */ 244 245 int 246 footbridge_intr(arg) 247 void *arg; 248 { 249 struct footbridge_softc *sc = arg; 250 u_int ctrl, intr; 251 252 /* 253 * Read the footbridge control register and check for 254 * SERR and parity errors 255 */ 256 ctrl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SA_CONTROL); 257 intr = ctrl & (RECEIVED_SERR | SA_SDRAM_PARITY_ERROR | 258 PCI_SDRAM_PARITY_ERROR | DMA_SDRAM_PARITY_ERROR); 259 if (intr) { 260 /* Report the interrupt if reporting is enabled */ 261 if (footbridge_intr_report) 262 printf("footbridge_intr: ctrl=%08x\n", intr); 263 /* Clear the interrupt state */ 264 bus_space_write_4(sc->sc_iot, sc->sc_ioh, SA_CONTROL, 265 ctrl | intr); 266 } 267 /* 268 * Read the PCI status register and check for errors 269 */ 270 ctrl = bus_space_read_4(sc->sc_iot, sc->sc_ioh, PCI_COMMAND_STATUS_REG); 271 intr = ctrl & (PCI_STATUS_PARITY_ERROR | PCI_STATUS_MASTER_TARGET_ABORT 272 | PCI_STATUS_MASTER_ABORT | PCI_STATUS_SPECIAL_ERROR 273 | PCI_STATUS_PARITY_DETECT); 274 if (intr) { 275 /* Report the interrupt if reporting is enabled */ 276 if (footbridge_intr_report) 277 printf("footbridge_intr: pcistat=%08x\n", intr); 278 /* Clear the interrupt state */ 279 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 280 PCI_COMMAND_STATUS_REG, ctrl | intr); 281 } 282 return(0); 283 } 284 285 /* End of footbridge.c */ 286