1 /* $NetBSD: ifpga.c,v 1.22 2008/04/27 18:58:46 matt Exp $ */
4 * Copyright (c) 2001 ARM Ltd
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the company may not be used to endorse or promote
16 * products derived from this software without specific prior written
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Integrator FPGA core logic support.
35 * The integrator board supports the core logic in an FPGA which is loaded
36 * at POR with a custom design. This code supports the default logic as the
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: ifpga.c,v 1.22 2008/04/27 18:58:46 matt Exp $");
43 #include <sys/param.h>
44 #include <sys/types.h>
45 #include <sys/device.h>
46 #include <sys/systm.h>
47 #include <sys/extent.h>
48 #include <sys/malloc.h>
51 #include <dev/pci/pcivar.h>
52 #include <dev/pci/pciconf.h>
54 #include <arm/cpufunc.h>
59 #include <evbarm/ifpga/ifpgamem.h>
60 #include <evbarm/ifpga/ifpgavar.h>
61 #include <evbarm/ifpga/ifpgareg.h>
62 #include <evbarm/ifpga/ifpga_pcivar.h>
63 #include <evbarm/dev/v360reg.h>
65 #include <evbarm/integrator/int_bus_dma.h>
69 static int ifpga_match (device_t
, cfdata_t
, void *);
70 static void ifpga_attach (device_t
, device_t
, void *);
71 static int ifpga_print (void *, const char *);
73 /* Drive and attach structures */
74 CFATTACH_DECL_NEW(ifpga
, sizeof(struct ifpga_softc
),
75 ifpga_match
, ifpga_attach
, NULL
, NULL
);
79 /* Default UART clock speed (we should make this a boot option). */
80 int ifpga_uart_clk
= IFPGA_UART_CLK
;
84 extern struct arm32_pci_chipset ifpga_pci_chipset
;
85 extern struct arm32_bus_dma_tag ifpga_pci_bus_dma_tag
;
87 static struct bus_space ifpga_pci_io_tag
;
88 static struct bus_space ifpga_pci_mem_tag
;
91 static struct bus_space ifpga_bs_tag
;
93 struct ifpga_softc
*ifpga_sc
;
97 * Print the configuration information for children
101 ifpga_print(void *aux
, const char *pnp
)
103 struct ifpga_attach_args
*ifa
= aux
;
105 if (ifa
->ifa_addr
!= -1)
106 aprint_normal(" addr 0x%lx", (unsigned long)ifa
->ifa_addr
);
107 if (ifa
->ifa_irq
!= -1)
108 aprint_normal(" irq %d", ifa
->ifa_irq
);
114 ifpga_search(device_t parent
, cfdata_t cf
, const int *ldesc
, void *aux
)
116 struct ifpga_softc
*sc
= device_private(parent
);
117 struct ifpga_attach_args ifa
;
121 ifa
.ifa_iot
= sc
->sc_iot
;
122 ifa
.ifa_addr
= cf
->cf_iobase
;
123 ifa
.ifa_irq
= cf
->cf_irq
;
124 ifa
.ifa_sc_ioh
= sc
->sc_sc_ioh
;
127 if (config_match(parent
, cf
, &ifa
) > 0) {
128 config_attach(parent
, cf
, &ifa
, ifpga_print
);
129 tryagain
= (cf
->cf_fstate
== FSTATE_STAR
);
137 ifpga_match(device_t parent
, cfdata_t cf
, void *aux
)
140 struct mainbus_attach_args
*ma
= aux
;
142 /* Make sure that we're looking for the IFPGA. */
143 if (strcmp(ma
->ma_name
, ifpga_md
.md_name
))
147 /* We can only have one instance of the IFPGA. */
155 ifpga_attach(device_t parent
, device_t self
, void *aux
)
157 struct ifpga_softc
*sc
= device_private(self
);
159 #if defined(PCI_NETBSD_CONFIGURE) && NPCI > 0
160 struct extent
*ioext
, *memext
, *pmemext
;
161 struct ifpga_pci_softc
*pci_sc
;
162 struct pcibus_attach_args pci_pba
;
167 /* We want a memory-mapped bus space, since the I/O space is sparse. */
168 ifpga_create_mem_bs_tag(&ifpga_bs_tag
, (void *)IFPGA_IO_BASE
);
171 /* But the PCI config space is quite large, so we have a linear region
172 for that pre-allocated. */
174 ifpga_create_io_bs_tag(&ifpga_pci_io_tag
, (void *)IFPGA_PCI_IO_VBASE
);
175 ifpga_create_mem_bs_tag(&ifpga_pci_mem_tag
, (void *)0);
178 sc
->sc_iot
= &ifpga_bs_tag
;
183 /* Now map in the IFPGA motherboard registers. */
184 if (bus_space_map(sc
->sc_iot
, IFPGA_IO_SC_BASE
, IFPGA_IO_SC_SIZE
, 0,
186 panic("%s: Cannot map system controller registers",
189 id
= bus_space_read_4(sc
->sc_iot
, sc
->sc_sc_ioh
, IFPGA_SC_ID
);
191 printf(": Build %d, ", (id
& IFPGA_SC_ID_BUILD_MASK
) >>
192 IFPGA_SC_ID_BUILD_SHIFT
);
193 switch (id
& IFPGA_SC_ID_REV_MASK
)
195 case IFPGA_SC_ID_REV_A
:
198 case IFPGA_SC_ID_REV_B
:
203 printf("Manufacturer ");
204 switch (id
& IFPGA_SC_ID_MAN_MASK
)
206 case IFPGA_SC_ID_MAN_ARM
:
214 switch (id
& IFPGA_SC_ID_ARCH_MASK
)
216 case IFPGA_SC_ID_ARCH_ASBLE
:
217 printf(" ASB, Little-endian,");
219 case IFPGA_SC_ID_ARCH_AHBLE
:
220 printf(" AHB, Little-endian,");
223 panic(" Unsupported bus");
226 printf("\n%s: FPGA ", device_xname(self
));
228 switch (id
& IFPGA_SC_ID_FPGA_MASK
)
230 case IFPGA_SC_ID_FPGA_XC4062
:
233 case IFPGA_SC_ID_FPGA_XC4085
:
241 sysclk
= bus_space_read_1(sc
->sc_iot
, sc
->sc_sc_ioh
, IFPGA_SC_OSC
);
242 sysclk
&= IFPGA_SC_OSC_S_VDW
;
245 printf(", SYSCLK %d.%02dMHz", sysclk
>> 2, (sysclk
& 3) * 25);
247 /* Map the Interrupt controller */
248 if (bus_space_map(sc
->sc_iot
, IFPGA_IO_IRQ_BASE
, IFPGA_IO_IRQ_SIZE
,
249 BUS_SPACE_MAP_LINEAR
, &sc
->sc_irq_ioh
))
250 panic("%s: Cannot map irq controller registers",
253 /* We can write to the IRQ/FIQ controller now. */
254 ifpga_intr_postinit();
256 /* Map the core module */
257 if (bus_space_map(sc
->sc_iot
, IFPGA_IO_CM_BASE
, IFPGA_IO_CM_SIZE
, 0,
259 panic("%s: Cannot map core module registers",
264 if (bus_space_map(sc
->sc_iot
, IFPGA_IO_TMR_BASE
, IFPGA_IO_TMR_SIZE
, 0,
266 panic("%s: Cannot map timer registers", device_xname(self
));
271 pci_sc
= malloc(sizeof(struct ifpga_pci_softc
), M_DEVBUF
, M_WAITOK
);
272 pci_sc
->sc_iot
= &ifpga_pci_io_tag
;
273 pci_sc
->sc_memt
= &ifpga_pci_mem_tag
;
275 if (bus_space_map(pci_sc
->sc_iot
, 0, IFPGA_PCI_IO_VSIZE
, 0,
277 || bus_space_map(pci_sc
->sc_iot
,
278 IFPGA_PCI_CONF_VBASE
- IFPGA_PCI_IO_VBASE
, IFPGA_PCI_CONF_VSIZE
, 0,
279 &pci_sc
->sc_conf_ioh
)
280 || bus_space_map(pci_sc
->sc_memt
, IFPGA_V360_REG_BASE
,
281 IFPGA_V360_REG_SIZE
, 0, &pci_sc
->sc_reg_ioh
))
282 panic("%s: Cannot map pci memory", device_xname(self
));
285 pcireg_t id_reg
, class_reg
;
288 id_reg
= bus_space_read_4(pci_sc
->sc_memt
, pci_sc
->sc_reg_ioh
,
290 class_reg
= bus_space_read_4(pci_sc
->sc_memt
,
291 pci_sc
->sc_reg_ioh
, V360_PCI_CC_REV
);
293 pci_devinfo(id_reg
, class_reg
, 1, buf
, sizeof(buf
));
294 printf("%s: %s\n", device_xname(self
), buf
);
297 #if defined(PCI_NETBSD_CONFIGURE)
298 ioext
= extent_create("pciio", 0x00000000,
299 0x00000000 + IFPGA_PCI_IO_VSIZE
, M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
300 memext
= extent_create("pcimem", IFPGA_PCI_APP0_BASE
,
301 IFPGA_PCI_APP0_BASE
+ IFPGA_PCI_APP0_SIZE
,
302 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
303 pmemext
= extent_create("pcipmem", IFPGA_PCI_APP1_BASE
,
304 IFPGA_PCI_APP1_BASE
+ IFPGA_PCI_APP1_SIZE
,
305 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
306 ifpga_pci_chipset
.pc_conf_v
= (void *)pci_sc
;
307 pci_configure_bus(&ifpga_pci_chipset
, ioext
, memext
, pmemext
, 0,
309 extent_destroy(pmemext
);
310 extent_destroy(memext
);
311 extent_destroy(ioext
);
313 printf("pci_configure_bus done\n");
314 #endif /* PCI_NETBSD_CONFIGURE */
315 #endif /* NPCI > 0 */
317 /* Finally, search for children. */
318 config_search_ia(ifpga_search
, self
, "ifpga", NULL
);
321 integrator_pci_dma_init(&ifpga_pci_bus_dma_tag
);
323 pci_pba
.pba_pc
= &ifpga_pci_chipset
;
324 pci_pba
.pba_iot
= &ifpga_pci_io_tag
;
325 pci_pba
.pba_memt
= &ifpga_pci_mem_tag
;
326 pci_pba
.pba_dmat
= &ifpga_pci_bus_dma_tag
;
327 pci_pba
.pba_dmat64
= NULL
;
328 pci_pba
.pba_flags
= PCI_FLAGS_IO_ENABLED
| PCI_FLAGS_MEM_ENABLED
;
330 pci_pba
.pba_bridgetag
= NULL
;
332 config_found_ia(self
, "pcibus", &pci_pba
, pcibusprint
);
339 bus_space_write_1(ifpga_sc
->sc_iot
, ifpga_sc
->sc_sc_ioh
,
340 IFPGA_SC_CTRLS
, IFPGA_SC_CTRL_SOFTRESET
);