1 /* $NetBSD: admpci.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $ */
4 * Copyright (c) 2007 David Young. All rights reserved.
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30 * Copyright (c) 2006 Itronix Inc.
31 * All rights reserved.
33 * Written by Garrett D'Amore for Itronix Inc.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. The name of Itronix Inc. may not be used to endorse
44 * or promote products derived from this software without specific
45 * prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
49 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
50 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
51 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
54 * ON ANY THEORY OF LIABILITY, WHETHER IN
55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 * POSSIBILITY OF SUCH DAMAGE.
63 #include <sys/cdefs.h>
64 __KERNEL_RCSID(0, "$NetBSD: admpci.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $");
66 #include <sys/types.h>
67 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <sys/errno.h>
71 #include <sys/device.h>
72 #include <sys/malloc.h>
73 #include <sys/extent.h>
75 #include <uvm/uvm_extern.h>
77 #include <machine/bus.h>
78 #include <machine/cpu.h>
79 #include <machine/pte.h>
81 #include <dev/pci/pcivar.h>
82 #include <dev/pci/pcireg.h>
83 #include <dev/pci/pciconf.h>
85 #ifdef PCI_NETBSD_CONFIGURE
86 #include <mips/cache.h>
89 #include <mips/adm5120/include/adm5120_mainbusvar.h>
90 #include <mips/adm5120/include/adm5120reg.h>
91 #include <mips/adm5120/include/adm5120var.h>
95 #define ADMPCI_DPRINTF(__fmt, ...) \
98 printf((__fmt), __VA_ARGS__); \
99 } while (/*CONSTCOND*/0)
100 #else /* !ADMPCI_DEBUG */
101 #define ADMPCI_DPRINTF(__fmt, ...) do { } while (/*CONSTCOND*/0)
102 #endif /* ADMPCI_DEBUG */
104 #define ADMPCI_TAG_BUS_MASK __BITS(23, 16)
105 /* Bit 11 is reserved. It selects the AHB-PCI bridge. Let device 0
106 * be the bridge. For all other device numbers, let bit[11] == 0.
108 #define ADMPCI_TAG_DEVICE_MASK __BITS(15, 11)
109 #define ADMPCI_TAG_DEVICE_SUBMASK __BITS(15, 12)
110 #define ADMPCI_TAG_DEVICE_BRIDGE __BIT(11)
111 #define ADMPCI_TAG_FUNCTION_MASK __BITS(10, 8)
112 #define ADMPCI_TAG_REGISTER_MASK __BITS(7, 0)
114 #define ADMPCI_MAX_DEVICE
116 struct admpci_softc
{
117 struct device sc_dev
;
118 struct mips_pci_chipset sc_pc
;
120 bus_space_tag_t sc_memt
;
121 bus_space_tag_t sc_iot
;
123 bus_space_tag_t sc_conft
;
124 bus_space_handle_t sc_addrh
;
125 bus_space_handle_t sc_datah
;
128 int admpcimatch(struct device
*, struct cfdata
*, void *);
129 void admpciattach(struct device
*, struct device
*, void *);
132 static void admpci_attach_hook(struct device
*, struct device
*,
133 struct pcibus_attach_args
*);
134 static int admpci_bus_maxdevs(void *, int);
135 static pcitag_t
admpci_make_tag(void *, int, int, int);
136 static void admpci_decompose_tag(void *, pcitag_t
, int *, int *, int *);
137 static pcireg_t
admpci_conf_read(void *, pcitag_t
, int);
138 static void admpci_conf_write(void *, pcitag_t
, int, pcireg_t
);
139 static const char *admpci_intr_string(void *, pci_intr_handle_t
);
140 static void admpci_conf_interrupt(void *, int, int, int, int, int *);
141 static void *admpci_intr_establish(void *, pci_intr_handle_t
, int,
142 int (*)(void *), void *);
143 static void admpci_intr_disestablish(void *, void *);
144 static int admpci_intr_map(struct pci_attach_args
*, pci_intr_handle_t
*);
146 #ifdef PCI_NETBSD_CONFIGURE
147 static struct extent
*io_ex
= NULL
;
148 static struct extent
*mem_ex
= NULL
;
149 #endif /* PCI_NETBSD_CONFIGURE */
151 #endif /* NPCI > 0 */
153 CFATTACH_DECL(admpci
, sizeof(struct admpci_softc
),
154 admpcimatch
, admpciattach
, NULL
, NULL
);
156 int admpci_found
= 0;
159 * Physical PCI addresses are 36-bits long, so we need to have
160 * adequate storage space for them.
163 #if !defined(_MIPS_PADDR_T_64BIT) && !defined(_LP64)
164 #error "admpci requires 64 bit paddr_t!"
169 admpcimatch(struct device
*parent
, struct cfdata
*match
, void *aux
)
171 struct mainbus_attach_args
*ma
= (struct mainbus_attach_args
*)aux
;
173 return !admpci_found
&& strcmp(ma
->ma_name
, "admpci") == 0;
177 admpciattach(struct device
*parent
, struct device
*self
, void *aux
)
179 struct adm5120_config
*admc
= &adm5120_configuration
;
180 struct admpci_softc
*sc
= (struct admpci_softc
*)self
;
181 struct mainbus_attach_args
*ma
= (struct mainbus_attach_args
*)aux
;
185 struct pcibus_attach_args pba
;
190 sc
->sc_conft
= ma
->ma_obiot
;
191 if (bus_space_map(sc
->sc_conft
, ADM5120_BASE_PCI_CONFDATA
, 4, 0,
192 &sc
->sc_datah
) != 0) {
194 "\n%s: unable to map PCI Configuration Data register\n",
195 device_xname(&sc
->sc_dev
));
198 if (bus_space_map(sc
->sc_conft
, ADM5120_BASE_PCI_CONFADDR
, 4, 0,
199 &sc
->sc_addrh
) != 0) {
201 "\n%s: unable to map PCI Configuration Address register\n",
202 device_xname(&sc
->sc_dev
));
206 printf(": ADM5120 Host-PCI Bridge, data %lx addr %lx, sc %p\n",
207 sc
->sc_datah
, sc
->sc_addrh
, (void *)sc
);
210 sc
->sc_memt
= &admc
->pcimem_space
;
211 sc
->sc_iot
= &admc
->pciio_space
;
213 sc
->sc_pc
.pc_conf_v
= sc
;
214 sc
->sc_pc
.pc_attach_hook
= admpci_attach_hook
;
215 sc
->sc_pc
.pc_bus_maxdevs
= admpci_bus_maxdevs
;
216 sc
->sc_pc
.pc_make_tag
= admpci_make_tag
;
217 sc
->sc_pc
.pc_decompose_tag
= admpci_decompose_tag
;
218 sc
->sc_pc
.pc_conf_read
= admpci_conf_read
;
219 sc
->sc_pc
.pc_conf_write
= admpci_conf_write
;
221 sc
->sc_pc
.pc_intr_v
= sc
;
222 sc
->sc_pc
.pc_intr_map
= admpci_intr_map
;
223 sc
->sc_pc
.pc_intr_string
= admpci_intr_string
;
224 sc
->sc_pc
.pc_intr_establish
= admpci_intr_establish
;
225 sc
->sc_pc
.pc_intr_disestablish
= admpci_intr_disestablish
;
226 sc
->sc_pc
.pc_conf_interrupt
= admpci_conf_interrupt
;
228 tag
= pci_make_tag(&sc
->sc_pc
, 0, 0, 0);
229 ADMPCI_DPRINTF("%s: BAR 0x10 0x%08x\n", __func__
,
230 pci_conf_read(&sc
->sc_pc
, tag
, PCI_MAPREG_START
));
232 #ifdef PCI_NETBSD_CONFIGURE
233 mem_ex
= extent_create("pcimem",
234 ADM5120_BOTTOM
, ADM5120_TOP
,
235 M_DEVBUF
, NULL
, 0, EX_WAITOK
);
236 (void)extent_alloc_subregion(mem_ex
,
237 ADM5120_BASE_SRAM1
, ADM5120_BASE_PCI_MEM
- 1,
238 ADM5120_BASE_PCI_MEM
- ADM5120_BASE_SRAM1
,
239 ADM5120_BASE_PCI_MEM
- ADM5120_BASE_SRAM1
,
240 0, EX_WAITOK
, &result
);
241 (void)extent_alloc_subregion(mem_ex
,
242 ADM5120_BASE_PCI_IO
, ADM5120_TOP
,
243 ADM5120_TOP
- ADM5120_BASE_PCI_IO
+ 1,
244 ADM5120_TOP
- ADM5120_BASE_PCI_IO
+ 1,
245 0, EX_WAITOK
, &result
);
247 io_ex
= extent_create("pciio",
248 ADM5120_BASE_PCI_IO
, ADM5120_BASE_PCI_CONFADDR
- 1,
249 M_DEVBUF
, NULL
, 0, EX_WAITOK
);
251 pci_configure_bus(&sc
->sc_pc
,
252 io_ex
, mem_ex
, NULL
, 0, mips_dcache_align
);
253 extent_destroy(mem_ex
);
254 extent_destroy(io_ex
);
257 pba
.pba_iot
= sc
->sc_iot
;
258 pba
.pba_memt
= sc
->sc_memt
;
259 /* XXX: review dma tag logic */
260 pba
.pba_dmat
= ma
->ma_dmat
;
261 pba
.pba_dmat64
= NULL
;
262 pba
.pba_pc
= &sc
->sc_pc
;
263 pba
.pba_flags
= PCI_FLAGS_IO_ENABLED
| PCI_FLAGS_MEM_ENABLED
;
265 pba
.pba_bridgetag
= NULL
;
267 config_found_ia(self
, "pcibus", &pba
, pcibusprint
);
268 #endif /* NPCI > 0 */
274 admpci_attach_hook(struct device
*parent
, struct device
*self
,
275 struct pcibus_attach_args
*pba
)
279 /* There are at most four devices on bus 0. The ADM5120 has
280 * request/grant lines for 3 PCI devices: 1, 2, and 3. The host
281 * bridge is device 0.
284 admpci_bus_maxdevs(void *v
, int bus
)
289 return 1 + __SHIFTOUT_MASK(ADMPCI_TAG_DEVICE_MASK
);
293 admpci_make_tag(void *v
, int bus
, int device
, int function
)
295 if (bus
> __SHIFTOUT_MASK(ADMPCI_TAG_BUS_MASK
) ||
296 device
> __SHIFTOUT_MASK(ADMPCI_TAG_DEVICE_MASK
) ||
297 function
> __SHIFTOUT_MASK(ADMPCI_TAG_FUNCTION_MASK
))
298 panic("%s: bad request", __func__
);
300 return __SHIFTIN(bus
, ADMPCI_TAG_BUS_MASK
) |
301 __SHIFTIN(device
, ADMPCI_TAG_DEVICE_MASK
) |
302 __SHIFTIN(function
, ADMPCI_TAG_FUNCTION_MASK
);
306 admpci_decompose_tag(void *v
, pcitag_t tag
, int *b
, int *d
, int *f
)
308 int bus
, device
, function
;
310 bus
= __SHIFTOUT(tag
, ADMPCI_TAG_BUS_MASK
);
311 device
= __SHIFTOUT(tag
, ADMPCI_TAG_DEVICE_MASK
);
312 function
= __SHIFTOUT(tag
, ADMPCI_TAG_FUNCTION_MASK
);
323 admpci_tag_to_addr(void *v
, pcitag_t tag
, int reg
, bus_addr_t
*addrp
)
325 int bus
, device
, function
;
327 KASSERT(addrp
!= NULL
);
328 /* panics if tag is not well-formed */
329 admpci_decompose_tag(v
, tag
, &bus
, &device
, &function
);
330 if (reg
> __SHIFTOUT_MASK(ADMPCI_TAG_REGISTER_MASK
))
331 panic("%s: bad register", __func__
);
333 *addrp
= 0x80000000 | tag
| __SHIFTIN(reg
, ADMPCI_TAG_REGISTER_MASK
);
339 admpci_conf_read(void *v
, pcitag_t tag
, int reg
)
342 struct admpci_softc
*sc
= (struct admpci_softc
*)v
;
346 ADMPCI_DPRINTF("%s: sc %p tag %lx reg %d\n", __func__
, (void *)sc
, tag
,
349 if (admpci_tag_to_addr(v
, tag
, reg
, &addr
) == -1)
352 ADMPCI_DPRINTF("%s: sc_addrh %lx sc_datah %lx addr %lx\n", __func__
,
353 sc
->sc_addrh
, sc
->sc_datah
, addr
);
356 bus_space_write_4(sc
->sc_conft
, sc
->sc_addrh
, 0, addr
);
357 data
= bus_space_read_4(sc
->sc_conft
, sc
->sc_datah
, 0);
360 ADMPCI_DPRINTF("%s: read 0x%" PRIx32
"\n", __func__
, data
);
365 admpci_conf_write(void *v
, pcitag_t tag
, int reg
, pcireg_t data
)
368 struct admpci_softc
*sc
= (struct admpci_softc
*)v
;
371 ADMPCI_DPRINTF("%s: sc %p tag %lx reg %d\n", __func__
, (void *)sc
, tag
,
374 if (admpci_tag_to_addr(v
, tag
, reg
, &addr
) == -1)
377 ADMPCI_DPRINTF("%s: sc_addrh %lx sc_datah %lx addr %lx\n", __func__
,
378 sc
->sc_addrh
, sc
->sc_datah
, addr
);
381 bus_space_write_4(sc
->sc_conft
, sc
->sc_addrh
, 0, addr
);
382 bus_space_write_4(sc
->sc_conft
, sc
->sc_datah
, 0, data
);
387 admpci_intr_string(void *v
, pci_intr_handle_t ih
)
389 static char name
[16];
391 (void)snprintf(name
, sizeof(name
), "irq %u", (unsigned)ih
);
396 admpci_intr_establish(void *v
, pci_intr_handle_t ih
, int ipl
,
397 int (*handler
)(void *), void *arg
)
399 return adm5120_intr_establish(ih
, ipl
, handler
, arg
);
403 admpci_intr_disestablish(void *v
, void *cookie
)
405 adm5120_intr_disestablish(cookie
);
409 admpci_conf_interrupt(void *v
, int bus
, int dev
, int ipin
, int swiz
, int *iline
)
412 * We let the machdep_pci_intr_map take care of IRQ routing.
413 * On some platforms the BIOS may have handled this properly,
414 * on others it might not have. For now we avoid clobbering
415 * the settings establishsed by the BIOS, so that they will be
416 * there if the platform logic is confident that it can rely
422 * Map the bus 0 device numbers 1, 2, and 3 to IRQ 6, 7, and 8,
425 * XXX How to handle bridges?
428 admpci_intr_map(struct pci_attach_args
*pa
, pci_intr_handle_t
*ihp
)
430 int bus
, device
, function
;
432 admpci_decompose_tag(pa
->pa_pc
->pc_conf_v
, pa
->pa_tag
,
433 &bus
, &device
, &function
);
435 if (bus
!= 0 || device
> 3)
438 *ihp
= (device
- 1) + 6;