1 /* $NetBSD: aupci.c,v 1.7 2007/02/21 22:59:47 thorpej Exp $ */
4 * Copyright (c) 2006 Itronix Inc.
7 * Written by Garrett D'Amore for Itronix Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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. The name of Itronix Inc. may not be used to endorse
18 * or promote products derived from this software without specific
19 * prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: aupci.c,v 1.7 2007/02/21 22:59:47 thorpej Exp $");
40 #include <sys/types.h>
41 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/errno.h>
45 #include <sys/device.h>
46 #include <sys/malloc.h>
47 #include <sys/extent.h>
49 #include <uvm/uvm_extern.h>
51 #include <machine/bus.h>
52 #include <machine/cpu.h>
53 #include <machine/pte.h>
55 #include <dev/pci/pcivar.h>
56 #include <dev/pci/pcireg.h>
57 #include <dev/pci/pciconf.h>
59 #ifdef PCI_NETBSD_CONFIGURE
60 #include <mips/cache.h>
63 #include <mips/alchemy/include/au_himem_space.h>
64 #include <mips/alchemy/include/aubusvar.h>
65 #include <mips/alchemy/include/aureg.h>
66 #include <mips/alchemy/include/auvar.h>
68 #include <mips/alchemy/dev/aupcireg.h>
69 #include <mips/alchemy/dev/aupcivar.h>
73 struct mips_pci_chipset sc_pc
;
74 struct mips_bus_space sc_mem_space
;
75 struct mips_bus_space sc_io_space
;
76 struct mips_bus_space sc_cfg_space
;
78 bus_space_tag_t sc_memt
;
79 bus_space_tag_t sc_iot
;
80 bus_space_tag_t sc_cfgt
;
82 bus_space_tag_t sc_bust
;
84 bus_space_handle_t sc_bush
;
92 int aupcimatch(struct device
*, struct cfdata
*, void *);
93 void aupciattach(struct device
*, struct device
*, void *);
96 static void aupci_attach_hook(struct device
*, struct device
*,
97 struct pcibus_attach_args
*);
98 static int aupci_bus_maxdevs(void *, int);
99 static pcitag_t
aupci_make_tag(void *, int, int, int);
100 static void aupci_decompose_tag(void *, pcitag_t
, int *, int *, int *);
101 static pcireg_t
aupci_conf_read(void *, pcitag_t
, int);
102 static void aupci_conf_write(void *, pcitag_t
, int, pcireg_t
);
103 static const char *aupci_intr_string(void *, pci_intr_handle_t
);
104 static void aupci_conf_interrupt(void *, int, int, int, int, int *);
105 static void *aupci_intr_establish(void *, pci_intr_handle_t
, int,
106 int (*)(void *), void *);
107 static void aupci_intr_disestablish(void *, void *);
109 #ifdef PCI_NETBSD_CONFIGURE
110 static struct extent
*io_ex
= NULL
;
111 static struct extent
*mem_ex
= NULL
;
112 #endif /* PCI_NETBSD_CONFIGURE */
114 #define PCI_CFG_READ 0
115 #define PCI_CFG_WRITE 1
117 #endif /* NPCI > 0 */
119 CFATTACH_DECL(aupci
, sizeof(struct aupci_softc
),
120 aupcimatch
, aupciattach
, NULL
, NULL
);
125 * Physical PCI addresses are 36-bits long, so we need to have
126 * adequate storage space for them.
129 #if !defined(_MIPS_PADDR_T_64BIT) && !defined(_LP64)
130 #error "aupci requires 64 bit paddr_t!"
135 aupcimatch(struct device
*parent
, struct cfdata
*match
, void *aux
)
137 struct aubus_attach_args
*aa
= (struct aubus_attach_args
*)aux
;
139 if (strcmp(aa
->aa_name
, "aupci") != 0)
149 aupciattach(struct device
*parent
, struct device
*self
, void *aux
)
151 struct aupci_softc
*sc
= (struct aupci_softc
*)self
;
152 struct aubus_attach_args
*aa
= (struct aubus_attach_args
*)aux
;
157 struct pcibus_attach_args pba
;
162 sc
->sc_bust
= aa
->aa_st
;
163 if (bus_space_map(sc
->sc_bust
, aa
->aa_addrs
[0], 512, 0,
164 &sc
->sc_bush
) != 0) {
165 printf("\n%s: unable to map PCI registers\n",
166 sc
->sc_dev
.dv_xname
);
172 * These physical addresses are locked in on the CPUs we have
173 * seen. Perhaps these should be passed in via locators, thru
174 * the configuration file.
176 sc
->sc_cfgbase
= PCI_CONFIG_BASE
;
177 sc
->sc_membase
= PCI_MEM_BASE
;
178 sc
->sc_iobase
= PCI_IO_BASE
;
182 * Configure byte swapping, as YAMON doesn't do it. YAMON does take
183 * care of most of the rest of the details (clocking, etc.), however.
185 #if _BYTE_ORDER == _BIG_ENDIAN
187 * N.B.: This still doesn't do the DMA thing properly. I have
188 * not yet figured out how to get DMA access to work properly
189 * without having bytes swapped while the processor is in
190 * big-endian mode. I'm not even sure that the Alchemy part
191 * can do it without swapping the bytes (which would be a
192 * bummer, since then only parts which had hardware detection
193 * and swapping support would work without special hacks in
196 cfg
= AUPCI_CONFIG_CH
| AUPCI_CONFIG_R1H
|
197 AUPCI_CONFIG_R2H
| AUPCI_CONFIG_AEN
|
198 AUPCI_CONFIG_SM
| AUPCI_CONFIG_ST
| AUPCI_CONFIG_SIC_DATA
;
200 cfg
= AUPCI_CONFIG_CH
| AUPCI_CONFIG_R1H
|
201 AUPCI_CONFIG_R2H
| AUPCI_CONFIG_AEN
;
203 bus_space_write_4(sc
->sc_bust
, sc
->sc_bush
, AUPCI_CONFIG
, cfg
);
205 cfg
= bus_space_read_4(sc
->sc_bust
, sc
->sc_bush
, AUPCI_COMMAND_STATUS
);
207 printf(": Alchemy Host-PCI Bridge");
208 if (cfg
& PCI_STATUS_66MHZ_SUPPORT
)
217 * PCI configuration space. Address in this bus are
218 * orthogonal to other spaces. We need to make the entire
219 * 32-bit address space available.
221 sc
->sc_cfgt
= &sc
->sc_cfg_space
;
222 au_himem_space_init(sc
->sc_cfgt
, "pcicfg", sc
->sc_cfgbase
,
223 0x00000000, 0xffffffff, AU_HIMEM_SPACE_IO
);
226 * Virtual PCI memory. Configured so that we don't overlap
227 * with PCI memory space.
229 mask
= bus_space_read_4(sc
->sc_bust
, sc
->sc_bush
, AUPCI_MWMASK
);
230 mask
>>= AUPCI_MWMASK_SHIFT
;
231 mask
<<= AUPCI_MWMASK_SHIFT
;
233 mbar
= bus_space_read_4(sc
->sc_bust
, sc
->sc_bush
, AUPCI_MBAR
);
234 mstart
= (mbar
& mask
) + (~mask
+ 1);
236 sc
->sc_memt
= &sc
->sc_mem_space
;
237 au_himem_space_init(sc
->sc_memt
, "pcimem", sc
->sc_membase
,
238 mstart
, 0xffffffff, AU_HIMEM_SPACE_LITTLE_ENDIAN
);
241 * IO space. Address in this bus are orthogonal to other spaces.
242 * 16 MB should be plenty. We don't start from zero to avoid
243 * potential device bugs.
245 sc
->sc_iot
= &sc
->sc_io_space
;
246 au_himem_space_init(sc
->sc_iot
, "pciio",
247 sc
->sc_iobase
, AUPCI_IO_START
, AUPCI_IO_END
,
248 AU_HIMEM_SPACE_LITTLE_ENDIAN
| AU_HIMEM_SPACE_IO
);
250 sc
->sc_pc
.pc_conf_v
= sc
;
251 sc
->sc_pc
.pc_attach_hook
= aupci_attach_hook
;
252 sc
->sc_pc
.pc_bus_maxdevs
= aupci_bus_maxdevs
;
253 sc
->sc_pc
.pc_make_tag
= aupci_make_tag
;
254 sc
->sc_pc
.pc_decompose_tag
= aupci_decompose_tag
;
255 sc
->sc_pc
.pc_conf_read
= aupci_conf_read
;
256 sc
->sc_pc
.pc_conf_write
= aupci_conf_write
;
258 sc
->sc_pc
.pc_intr_v
= sc
;
259 sc
->sc_pc
.pc_intr_map
= aupci_intr_map
;
260 sc
->sc_pc
.pc_intr_string
= aupci_intr_string
;
261 sc
->sc_pc
.pc_intr_establish
= aupci_intr_establish
;
262 sc
->sc_pc
.pc_intr_disestablish
= aupci_intr_disestablish
;
263 sc
->sc_pc
.pc_conf_interrupt
= aupci_conf_interrupt
;
265 #ifdef PCI_NETBSD_CONFIGURE
266 mem_ex
= extent_create("pcimem", mstart
, 0xffffffff,
267 M_DEVBUF
, NULL
, 0, EX_WAITOK
);
269 io_ex
= extent_create("pciio", AUPCI_IO_START
, AUPCI_IO_END
,
270 M_DEVBUF
, NULL
, 0, EX_WAITOK
);
272 pci_configure_bus(&sc
->sc_pc
,
273 io_ex
, mem_ex
, NULL
, 0, mips_dcache_align
);
274 extent_destroy(mem_ex
);
275 extent_destroy(io_ex
);
278 pba
.pba_iot
= sc
->sc_iot
;
279 pba
.pba_memt
= sc
->sc_memt
;
280 /* XXX: review dma tag logic */
281 pba
.pba_dmat
= aa
->aa_dt
;
282 pba
.pba_dmat64
= NULL
;
283 pba
.pba_pc
= &sc
->sc_pc
;
284 pba
.pba_flags
= PCI_FLAGS_IO_ENABLED
| PCI_FLAGS_MEM_ENABLED
;
286 pba
.pba_bridgetag
= NULL
;
288 config_found_ia(self
, "pcibus", &pba
, pcibusprint
);
289 #endif /* NPCI > 0 */
295 aupci_attach_hook(struct device
*parent
, struct device
*self
,
296 struct pcibus_attach_args
*pba
)
301 aupci_bus_maxdevs(void *v
, int busno
)
308 aupci_make_tag(void *v
, int bus
, int device
, int function
)
312 if (bus
>= 256 || device
>= 32 || function
>= 8)
313 panic("aupci_make_tag: bad request");
315 tag
= (bus
<< 16) | (device
<< 11) | (function
<< 8);
321 aupci_decompose_tag(void *v
, pcitag_t tag
, int *b
, int *d
, int *f
)
325 *b
= (tag
>> 16) & 0xff;
327 *d
= (tag
>> 11) & 0x1f;
329 *f
= (tag
>> 8) & 0x07;
333 aupci_conf_access(void *v
, int dir
, pcitag_t tag
, int reg
, pcireg_t
*datap
)
335 struct aupci_softc
*sc
= (struct aupci_softc
*)v
;
340 bus_space_handle_t h
;
342 aupci_decompose_tag(v
, tag
, &b
, &d
, &f
);
344 /* configuration type 1 */
345 addr
= 0x80000000 | tag
;
347 /* device num too big for bus 0 */
350 addr
= (0x800 << d
) | (f
<< 8);
353 /* probing illegal target is OK, return an error indication */
357 if (bus_space_map(sc
->sc_cfgt
, addr
, 256, 0, &h
) != 0)
362 if (dir
== PCI_CFG_WRITE
)
363 bus_space_write_4(sc
->sc_cfgt
, h
, reg
, *datap
);
365 *datap
= bus_space_read_4(sc
->sc_cfgt
, h
, reg
);
369 /* check for and clear master abort condition */
370 status
= bus_space_read_4(sc
->sc_bust
, sc
->sc_bush
, AUPCI_CONFIG
);
371 bus_space_write_4(sc
->sc_bust
, sc
->sc_bush
, AUPCI_CONFIG
,
372 status
& ~(AUPCI_CONFIG_EF
));
376 bus_space_unmap(sc
->sc_cfgt
, h
, 256);
378 /* if we got a PCI master abort, fail it */
379 if (status
& AUPCI_CONFIG_EF
)
386 aupci_conf_read(void *v
, pcitag_t tag
, int reg
)
390 if (aupci_conf_access(v
, PCI_CFG_READ
, tag
, reg
, &data
) == false)
397 aupci_conf_write(void *v
, pcitag_t tag
, int reg
, pcireg_t data
)
400 aupci_conf_access(v
, PCI_CFG_WRITE
, tag
, reg
, &data
);
404 aupci_intr_string(void *v
, pci_intr_handle_t ih
)
406 static char name
[16];
408 sprintf(name
, "irq %u", (unsigned)ih
);
413 aupci_intr_establish(void *v
, pci_intr_handle_t ih
, int ipl
,
414 int (*handler
)(void *), void *arg
)
417 return (au_intr_establish(ih
, 0, ipl
, IST_LEVEL_LOW
, handler
, arg
));
421 aupci_intr_disestablish(void *v
, void *cookie
)
424 au_intr_disestablish(cookie
);
428 aupci_conf_interrupt(void *v
, int bus
, int dev
, int ipin
, int swiz
, int *iline
)
431 * We let the machdep_pci_intr_map take care of IRQ routing.
432 * On some platforms the BIOS may have handled this properly,
433 * on others it might not have. For now we avoid clobbering
434 * the settings establishsed by the BIOS, so that they will be
435 * there if the platform logic is confident that it can rely