1 1.31 skrll /* $NetBSD: ifpga.c,v 1.31 2022/09/27 06:12:19 skrll Exp $ */ 2 1.1 rearnsha 3 1.1 rearnsha /* 4 1.1 rearnsha * Copyright (c) 2001 ARM Ltd 5 1.1 rearnsha * All rights reserved. 6 1.1 rearnsha * 7 1.1 rearnsha * Redistribution and use in source and binary forms, with or without 8 1.1 rearnsha * modification, are permitted provided that the following conditions 9 1.1 rearnsha * are met: 10 1.1 rearnsha * 1. Redistributions of source code must retain the above copyright 11 1.1 rearnsha * notice, this list of conditions and the following disclaimer. 12 1.1 rearnsha * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 rearnsha * notice, this list of conditions and the following disclaimer in the 14 1.1 rearnsha * documentation and/or other materials provided with the distribution. 15 1.1 rearnsha * 3. The name of the company may not be used to endorse or promote 16 1.1 rearnsha * products derived from this software without specific prior written 17 1.1 rearnsha * permission. 18 1.1 rearnsha * 19 1.1 rearnsha * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 1.1 rearnsha * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 1.1 rearnsha * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 1.1 rearnsha * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 1.1 rearnsha * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 1.1 rearnsha * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 1.1 rearnsha * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 rearnsha * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 rearnsha * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 rearnsha * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 rearnsha * SUCH DAMAGE. 30 1.1 rearnsha */ 31 1.1 rearnsha 32 1.1 rearnsha /* 33 1.1 rearnsha * Integrator FPGA core logic support. 34 1.1 rearnsha * 35 1.1 rearnsha * The integrator board supports the core logic in an FPGA which is loaded 36 1.1 rearnsha * at POR with a custom design. This code supports the default logic as the 37 1.1 rearnsha * board is shipped. 38 1.1 rearnsha */ 39 1.16 lukem 40 1.16 lukem #include <sys/cdefs.h> 41 1.31 skrll __KERNEL_RCSID(0, "$NetBSD: ifpga.c,v 1.31 2022/09/27 06:12:19 skrll Exp $"); 42 1.1 rearnsha 43 1.22 matt #include <sys/param.h> 44 1.1 rearnsha #include <sys/types.h> 45 1.1 rearnsha #include <sys/device.h> 46 1.1 rearnsha #include <sys/systm.h> 47 1.31 skrll #include <sys/kmem.h> 48 1.1 rearnsha #include <sys/null.h> 49 1.1 rearnsha 50 1.1 rearnsha #include <dev/pci/pcivar.h> 51 1.1 rearnsha #include <dev/pci/pciconf.h> 52 1.1 rearnsha 53 1.5 thorpej #include <arm/cpufunc.h> 54 1.1 rearnsha 55 1.1 rearnsha #include "opt_pci.h" 56 1.1 rearnsha #include "pci.h" 57 1.1 rearnsha 58 1.1 rearnsha #include <evbarm/ifpga/ifpgamem.h> 59 1.1 rearnsha #include <evbarm/ifpga/ifpgavar.h> 60 1.1 rearnsha #include <evbarm/ifpga/ifpgareg.h> 61 1.1 rearnsha #include <evbarm/ifpga/ifpga_pcivar.h> 62 1.1 rearnsha #include <evbarm/dev/v360reg.h> 63 1.1 rearnsha 64 1.10 thorpej #include <evbarm/integrator/int_bus_dma.h> 65 1.17 rearnsha #include "locators.h" 66 1.10 thorpej 67 1.1 rearnsha /* Prototypes */ 68 1.23 dyoung static int ifpga_match (device_t, cfdata_t, void *); 69 1.23 dyoung static void ifpga_attach (device_t, device_t, void *); 70 1.1 rearnsha static int ifpga_print (void *, const char *); 71 1.1 rearnsha 72 1.1 rearnsha /* Drive and attach structures */ 73 1.23 dyoung CFATTACH_DECL_NEW(ifpga, sizeof(struct ifpga_softc), 74 1.13 thorpej ifpga_match, ifpga_attach, NULL, NULL); 75 1.1 rearnsha 76 1.1 rearnsha int ifpga_found; 77 1.1 rearnsha 78 1.1 rearnsha /* Default UART clock speed (we should make this a boot option). */ 79 1.1 rearnsha int ifpga_uart_clk = IFPGA_UART_CLK; 80 1.1 rearnsha 81 1.1 rearnsha #if NPCI > 0 82 1.1 rearnsha /* PCI handles */ 83 1.1 rearnsha extern struct arm32_pci_chipset ifpga_pci_chipset; 84 1.1 rearnsha extern struct arm32_bus_dma_tag ifpga_pci_bus_dma_tag; 85 1.1 rearnsha 86 1.1 rearnsha static struct bus_space ifpga_pci_io_tag; 87 1.1 rearnsha static struct bus_space ifpga_pci_mem_tag; 88 1.1 rearnsha #endif /* NPCI > 0 */ 89 1.1 rearnsha 90 1.26 skrll extern struct bus_space ifpga_common_bs_tag; 91 1.1 rearnsha 92 1.17 rearnsha struct ifpga_softc *ifpga_sc; 93 1.23 dyoung device_t ifpga_dev; 94 1.23 dyoung 95 1.1 rearnsha /* 96 1.1 rearnsha * Print the configuration information for children 97 1.1 rearnsha */ 98 1.1 rearnsha 99 1.1 rearnsha static int 100 1.1 rearnsha ifpga_print(void *aux, const char *pnp) 101 1.1 rearnsha { 102 1.1 rearnsha struct ifpga_attach_args *ifa = aux; 103 1.1 rearnsha 104 1.1 rearnsha if (ifa->ifa_addr != -1) 105 1.14 thorpej aprint_normal(" addr 0x%lx", (unsigned long)ifa->ifa_addr); 106 1.1 rearnsha if (ifa->ifa_irq != -1) 107 1.14 thorpej aprint_normal(" irq %d", ifa->ifa_irq); 108 1.1 rearnsha 109 1.1 rearnsha return UNCONF; 110 1.1 rearnsha } 111 1.1 rearnsha 112 1.1 rearnsha static int 113 1.23 dyoung ifpga_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 114 1.1 rearnsha { 115 1.23 dyoung struct ifpga_softc *sc = device_private(parent); 116 1.1 rearnsha struct ifpga_attach_args ifa; 117 1.1 rearnsha int tryagain; 118 1.1 rearnsha 119 1.1 rearnsha do { 120 1.1 rearnsha ifa.ifa_iot = sc->sc_iot; 121 1.1 rearnsha ifa.ifa_addr = cf->cf_iobase; 122 1.1 rearnsha ifa.ifa_irq = cf->cf_irq; 123 1.1 rearnsha ifa.ifa_sc_ioh = sc->sc_sc_ioh; 124 1.1 rearnsha 125 1.1 rearnsha tryagain = 0; 126 1.29 thorpej if (config_probe(parent, cf, &ifa)) { 127 1.30 thorpej config_attach(parent, cf, &ifa, ifpga_print, CFARGS_NONE); 128 1.1 rearnsha tryagain = (cf->cf_fstate == FSTATE_STAR); 129 1.1 rearnsha } 130 1.1 rearnsha } while (tryagain); 131 1.1 rearnsha 132 1.1 rearnsha return 0; 133 1.1 rearnsha } 134 1.1 rearnsha 135 1.1 rearnsha static int 136 1.23 dyoung ifpga_match(device_t parent, cfdata_t cf, void *aux) 137 1.1 rearnsha { 138 1.1 rearnsha #if 0 139 1.1 rearnsha struct mainbus_attach_args *ma = aux; 140 1.1 rearnsha 141 1.1 rearnsha /* Make sure that we're looking for the IFPGA. */ 142 1.1 rearnsha if (strcmp(ma->ma_name, ifpga_md.md_name)) 143 1.1 rearnsha return 0; 144 1.1 rearnsha #endif 145 1.1 rearnsha 146 1.1 rearnsha /* We can only have one instance of the IFPGA. */ 147 1.1 rearnsha if (ifpga_found) 148 1.1 rearnsha return 0; 149 1.1 rearnsha 150 1.1 rearnsha return 1; 151 1.1 rearnsha } 152 1.1 rearnsha 153 1.1 rearnsha static void 154 1.23 dyoung ifpga_attach(device_t parent, device_t self, void *aux) 155 1.1 rearnsha { 156 1.23 dyoung struct ifpga_softc *sc = device_private(self); 157 1.1 rearnsha u_int id, sysclk; 158 1.26 skrll extern struct bus_space ifpga_common_bs_tag; 159 1.1 rearnsha #if defined(PCI_NETBSD_CONFIGURE) && NPCI > 0 160 1.28 thorpej struct pciconf_resources *pcires; 161 1.1 rearnsha struct ifpga_pci_softc *pci_sc; 162 1.1 rearnsha struct pcibus_attach_args pci_pba; 163 1.1 rearnsha #endif 164 1.1 rearnsha 165 1.26 skrll ifpga_intr_init(); 166 1.26 skrll 167 1.1 rearnsha ifpga_found = 1; 168 1.1 rearnsha 169 1.1 rearnsha #if NPCI > 0 170 1.1 rearnsha /* But the PCI config space is quite large, so we have a linear region 171 1.1 rearnsha for that pre-allocated. */ 172 1.1 rearnsha 173 1.1 rearnsha ifpga_create_io_bs_tag(&ifpga_pci_io_tag, (void *)IFPGA_PCI_IO_VBASE); 174 1.1 rearnsha ifpga_create_mem_bs_tag(&ifpga_pci_mem_tag, (void *)0); 175 1.1 rearnsha #endif 176 1.1 rearnsha 177 1.26 skrll sc->sc_iot = &ifpga_common_bs_tag; 178 1.1 rearnsha 179 1.23 dyoung ifpga_dev = self; 180 1.1 rearnsha ifpga_sc = sc; 181 1.1 rearnsha 182 1.1 rearnsha /* Now map in the IFPGA motherboard registers. */ 183 1.1 rearnsha if (bus_space_map(sc->sc_iot, IFPGA_IO_SC_BASE, IFPGA_IO_SC_SIZE, 0, 184 1.1 rearnsha &sc->sc_sc_ioh)) 185 1.1 rearnsha panic("%s: Cannot map system controller registers", 186 1.23 dyoung device_xname(self)); 187 1.1 rearnsha 188 1.1 rearnsha id = bus_space_read_4(sc->sc_iot, sc->sc_sc_ioh, IFPGA_SC_ID); 189 1.1 rearnsha 190 1.1 rearnsha printf(": Build %d, ", (id & IFPGA_SC_ID_BUILD_MASK) >> 191 1.1 rearnsha IFPGA_SC_ID_BUILD_SHIFT); 192 1.1 rearnsha switch (id & IFPGA_SC_ID_REV_MASK) 193 1.1 rearnsha { 194 1.1 rearnsha case IFPGA_SC_ID_REV_A: 195 1.1 rearnsha printf("Rev A, "); 196 1.1 rearnsha break; 197 1.1 rearnsha case IFPGA_SC_ID_REV_B: 198 1.1 rearnsha printf("Rev B, "); 199 1.1 rearnsha break; 200 1.1 rearnsha } 201 1.1 rearnsha 202 1.1 rearnsha printf("Manufacturer "); 203 1.1 rearnsha switch (id & IFPGA_SC_ID_MAN_MASK) 204 1.1 rearnsha { 205 1.1 rearnsha case IFPGA_SC_ID_MAN_ARM: 206 1.1 rearnsha printf("ARM Ltd,"); 207 1.1 rearnsha break; 208 1.1 rearnsha default: 209 1.1 rearnsha printf("Unknown,"); 210 1.1 rearnsha break; 211 1.1 rearnsha } 212 1.1 rearnsha 213 1.1 rearnsha switch (id & IFPGA_SC_ID_ARCH_MASK) 214 1.1 rearnsha { 215 1.1 rearnsha case IFPGA_SC_ID_ARCH_ASBLE: 216 1.1 rearnsha printf(" ASB, Little-endian,"); 217 1.1 rearnsha break; 218 1.1 rearnsha case IFPGA_SC_ID_ARCH_AHBLE: 219 1.1 rearnsha printf(" AHB, Little-endian,"); 220 1.1 rearnsha break; 221 1.1 rearnsha default: 222 1.1 rearnsha panic(" Unsupported bus"); 223 1.1 rearnsha } 224 1.1 rearnsha 225 1.23 dyoung printf("\n%s: FPGA ", device_xname(self)); 226 1.1 rearnsha 227 1.1 rearnsha switch (id & IFPGA_SC_ID_FPGA_MASK) 228 1.1 rearnsha { 229 1.1 rearnsha case IFPGA_SC_ID_FPGA_XC4062: 230 1.1 rearnsha printf("XC4062"); 231 1.1 rearnsha break; 232 1.1 rearnsha case IFPGA_SC_ID_FPGA_XC4085: 233 1.1 rearnsha printf("XC4085"); 234 1.1 rearnsha break; 235 1.1 rearnsha default: 236 1.1 rearnsha printf("unknown"); 237 1.1 rearnsha break; 238 1.1 rearnsha } 239 1.1 rearnsha 240 1.1 rearnsha sysclk = bus_space_read_1(sc->sc_iot, sc->sc_sc_ioh, IFPGA_SC_OSC); 241 1.1 rearnsha sysclk &= IFPGA_SC_OSC_S_VDW; 242 1.1 rearnsha sysclk += 8; 243 1.1 rearnsha 244 1.1 rearnsha printf(", SYSCLK %d.%02dMHz", sysclk >> 2, (sysclk & 3) * 25); 245 1.1 rearnsha 246 1.1 rearnsha /* Map the Interrupt controller */ 247 1.1 rearnsha if (bus_space_map(sc->sc_iot, IFPGA_IO_IRQ_BASE, IFPGA_IO_IRQ_SIZE, 248 1.1 rearnsha BUS_SPACE_MAP_LINEAR, &sc->sc_irq_ioh)) 249 1.1 rearnsha panic("%s: Cannot map irq controller registers", 250 1.23 dyoung device_xname(self)); 251 1.1 rearnsha 252 1.1 rearnsha /* We can write to the IRQ/FIQ controller now. */ 253 1.17 rearnsha ifpga_intr_postinit(); 254 1.1 rearnsha 255 1.1 rearnsha /* Map the core module */ 256 1.1 rearnsha if (bus_space_map(sc->sc_iot, IFPGA_IO_CM_BASE, IFPGA_IO_CM_SIZE, 0, 257 1.23 dyoung &sc->sc_cm_ioh)) { 258 1.23 dyoung panic("%s: Cannot map core module registers", 259 1.23 dyoung device_xname(self)); 260 1.23 dyoung } 261 1.1 rearnsha 262 1.1 rearnsha /* Map the timers */ 263 1.1 rearnsha if (bus_space_map(sc->sc_iot, IFPGA_IO_TMR_BASE, IFPGA_IO_TMR_SIZE, 0, 264 1.1 rearnsha &sc->sc_tmr_ioh)) 265 1.23 dyoung panic("%s: Cannot map timer registers", device_xname(self)); 266 1.1 rearnsha 267 1.1 rearnsha printf("\n"); 268 1.1 rearnsha 269 1.1 rearnsha #if NPCI > 0 270 1.31 skrll pci_sc = kmem_alloc(sizeof(*pci_sc), KM_SLEEP); 271 1.1 rearnsha pci_sc->sc_iot = &ifpga_pci_io_tag; 272 1.1 rearnsha pci_sc->sc_memt = &ifpga_pci_mem_tag; 273 1.1 rearnsha 274 1.1 rearnsha if (bus_space_map(pci_sc->sc_iot, 0, IFPGA_PCI_IO_VSIZE, 0, 275 1.1 rearnsha &pci_sc->sc_io_ioh) 276 1.1 rearnsha || bus_space_map(pci_sc->sc_iot, 277 1.1 rearnsha IFPGA_PCI_CONF_VBASE - IFPGA_PCI_IO_VBASE, IFPGA_PCI_CONF_VSIZE, 0, 278 1.1 rearnsha &pci_sc->sc_conf_ioh) 279 1.1 rearnsha || bus_space_map(pci_sc->sc_memt, IFPGA_V360_REG_BASE, 280 1.1 rearnsha IFPGA_V360_REG_SIZE, 0, &pci_sc->sc_reg_ioh)) 281 1.23 dyoung panic("%s: Cannot map pci memory", device_xname(self)); 282 1.1 rearnsha 283 1.1 rearnsha { 284 1.1 rearnsha pcireg_t id_reg, class_reg; 285 1.1 rearnsha char buf[1000]; 286 1.1 rearnsha 287 1.1 rearnsha id_reg = bus_space_read_4(pci_sc->sc_memt, pci_sc->sc_reg_ioh, 288 1.1 rearnsha V360_PCI_VENDOR); 289 1.1 rearnsha class_reg = bus_space_read_4(pci_sc->sc_memt, 290 1.1 rearnsha pci_sc->sc_reg_ioh, V360_PCI_CC_REV); 291 1.1 rearnsha 292 1.18 kleink pci_devinfo(id_reg, class_reg, 1, buf, sizeof(buf)); 293 1.23 dyoung printf("%s: %s\n", device_xname(self), buf); 294 1.1 rearnsha } 295 1.1 rearnsha 296 1.1 rearnsha #if defined(PCI_NETBSD_CONFIGURE) 297 1.28 thorpej pcires = pciconf_resource_init(); 298 1.28 thorpej 299 1.28 thorpej pciconf_resource_add(pcires, PCICONF_RESOURCE_IO, 300 1.28 thorpej 0x00000000, IFPGA_PCI_IO_VSIZE); 301 1.28 thorpej pciconf_resource_add(pcires, PCICONF_RESOURCE_MEM, 302 1.28 thorpej IFPGA_PCI_APP0_BASE, IFPGA_PCI_APP0_SIZE); 303 1.28 thorpej pciconf_resource_add(pcires, PCICONF_RESOURCE_PREFETCHABLE_MEM, 304 1.28 thorpej IFPGA_PCI_APP1_BASE, IFPGA_PCI_APP1_SIZE); 305 1.28 thorpej 306 1.1 rearnsha ifpga_pci_chipset.pc_conf_v = (void *)pci_sc; 307 1.28 thorpej pci_configure_bus(&ifpga_pci_chipset, pcires, 0, 308 1.4 thorpej arm_dcache_align); 309 1.28 thorpej pciconf_resource_fini(pcires); 310 1.1 rearnsha 311 1.1 rearnsha printf("pci_configure_bus done\n"); 312 1.1 rearnsha #endif /* PCI_NETBSD_CONFIGURE */ 313 1.1 rearnsha #endif /* NPCI > 0 */ 314 1.1 rearnsha 315 1.1 rearnsha /* Finally, search for children. */ 316 1.29 thorpej config_search(self, NULL, 317 1.30 thorpej CFARGS(.search = ifpga_search, 318 1.30 thorpej .iattr = "ifpga")); 319 1.1 rearnsha 320 1.1 rearnsha #if NPCI > 0 321 1.10 thorpej integrator_pci_dma_init(&ifpga_pci_bus_dma_tag); 322 1.10 thorpej 323 1.1 rearnsha pci_pba.pba_pc = &ifpga_pci_chipset; 324 1.1 rearnsha pci_pba.pba_iot = &ifpga_pci_io_tag; 325 1.1 rearnsha pci_pba.pba_memt = &ifpga_pci_mem_tag; 326 1.1 rearnsha pci_pba.pba_dmat = &ifpga_pci_bus_dma_tag; 327 1.15 fvdl pci_pba.pba_dmat64 = NULL; 328 1.24 dyoung pci_pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY; 329 1.1 rearnsha pci_pba.pba_bus = 0; 330 1.9 briggs pci_pba.pba_bridgetag = NULL; 331 1.1 rearnsha 332 1.29 thorpej config_found(self, &pci_pba, pcibusprint, 333 1.30 thorpej CFARGS(.iattr = "pcibus")); 334 1.1 rearnsha #endif 335 1.1 rearnsha } 336 1.1 rearnsha 337 1.1 rearnsha void 338 1.1 rearnsha ifpga_reset(void) 339 1.1 rearnsha { 340 1.1 rearnsha bus_space_write_1(ifpga_sc->sc_iot, ifpga_sc->sc_sc_ioh, 341 1.1 rearnsha IFPGA_SC_CTRLS, IFPGA_SC_CTRL_SOFTRESET); 342 1.1 rearnsha } 343