1 /* $NetBSD: i80321_pci.c,v 1.7.38.1 2007/05/22 17:26:41 matt Exp $ */
4 * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
7 * Written by Jason R. Thorpe for Wasabi Systems, 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. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * PCI configuration support for i80321 I/O Processor chip.
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: i80321_pci.c,v 1.7.38.1 2007/05/22 17:26:41 matt Exp $");
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/device.h>
48 #include <sys/extent.h>
49 #include <sys/malloc.h>
51 #include <uvm/uvm_extern.h>
53 #include <machine/bus.h>
55 #include <arm/xscale/i80321reg.h>
56 #include <arm/xscale/i80321var.h>
58 #include <dev/pci/ppbreg.h>
59 #include <dev/pci/pciconf.h>
62 #include "opt_i80321.h"
65 void i80321_pci_attach_hook(struct device
*, struct device
*,
66 struct pcibus_attach_args
*);
67 int i80321_pci_bus_maxdevs(void *, int);
68 pcitag_t
i80321_pci_make_tag(void *, int, int, int);
69 void i80321_pci_decompose_tag(void *, pcitag_t
, int *, int *,
71 pcireg_t
i80321_pci_conf_read(void *, pcitag_t
, int);
72 void i80321_pci_conf_write(void *, pcitag_t
, int, pcireg_t
);
74 #define PCI_CONF_LOCK(s) (s) = disable_interrupts(I32_bit)
75 #define PCI_CONF_UNLOCK(s) restore_interrupts((s))
78 i80321_pci_init(pci_chipset_tag_t pc
, void *cookie
)
80 #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
81 struct i80321_softc
*sc
= cookie
;
82 struct extent
*ioext
, *memext
;
86 pc
->pc_conf_v
= cookie
;
87 pc
->pc_attach_hook
= i80321_pci_attach_hook
;
88 pc
->pc_bus_maxdevs
= i80321_pci_bus_maxdevs
;
89 pc
->pc_make_tag
= i80321_pci_make_tag
;
90 pc
->pc_decompose_tag
= i80321_pci_decompose_tag
;
91 pc
->pc_conf_read
= i80321_pci_conf_read
;
92 pc
->pc_conf_write
= i80321_pci_conf_write
;
94 #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
96 * Configure the PCI bus.
98 * XXX We need to revisit this. We only configure the Secondary
99 * bus (and its children). The bus configure code needs changes
100 * to support how the busses are arranged on this chip. We also
101 * need to only configure devices in the private device space on
105 busno
= bus_space_read_4(sc
->sc_st
, sc
->sc_atu_sh
, ATU_PCIXSR
);
106 busno
= PCIXSR_BUSNO(busno
);
110 ioext
= extent_create("pciio",
111 sc
->sc_ioout_xlate
+ sc
->sc_ioout_xlate_offset
,
112 sc
->sc_ioout_xlate
+ VERDE_OUT_XLATE_IO_WIN_SIZE
- 1,
113 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
115 #ifdef I80321_USE_DIRECT_WIN
116 memext
= extent_create("pcimem", VERDE_OUT_DIRECT_WIN_BASE
+ VERDE_OUT_DIRECT_WIN_SKIP
,
117 VERDE_OUT_DIRECT_WIN_BASE
+ VERDE_OUT_DIRECT_WIN_SIZE
- 1,
118 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
120 memext
= extent_create("pcimem", sc
->sc_owin
[0].owin_xlate_lo
,
121 sc
->sc_owin
[0].owin_xlate_lo
+ VERDE_OUT_XLATE_MEM_WIN_SIZE
- 1,
122 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
125 aprint_normal("%s: configuring PCI bus\n", sc
->sc_dev
.dv_xname
);
126 pci_configure_bus(pc
, ioext
, memext
, NULL
, busno
, arm_dcache_align
);
128 extent_destroy(ioext
);
129 extent_destroy(memext
);
134 pci_conf_interrupt(pci_chipset_tag_t pc
, int a
, int b
, int c
, int d
, int *p
)
139 i80321_pci_attach_hook(struct device
*parent
, struct device
*self
,
140 struct pcibus_attach_args
*pba
)
147 i80321_pci_bus_maxdevs(void *v
, int busno
)
154 i80321_pci_make_tag(void *v
, int b
, int d
, int f
)
157 return ((b
<< 16) | (d
<< 11) | (f
<< 8));
161 i80321_pci_decompose_tag(void *v
, pcitag_t tag
, int *bp
, int *dp
, int *fp
)
165 *bp
= (tag
>> 16) & 0xff;
167 *dp
= (tag
>> 11) & 0x1f;
169 *fp
= (tag
>> 8) & 0x7;
172 struct pciconf_state
{
173 uint32_t ps_addr_val
;
175 int ps_b
, ps_d
, ps_f
;
179 i80321_pci_conf_setup(struct i80321_softc
*sc
, pcitag_t tag
, int offset
,
180 struct pciconf_state
*ps
)
184 i80321_pci_decompose_tag(sc
, tag
, &ps
->ps_b
, &ps
->ps_d
, &ps
->ps_f
);
186 busno
= bus_space_read_4(sc
->sc_st
, sc
->sc_atu_sh
, ATU_PCIXSR
);
187 busno
= PCIXSR_BUSNO(busno
);
192 * If the bus # is the same as our own, then use Type 0 cycles,
195 * XXX We should filter out all non-private devices here!
196 * XXX How does private space interact with PCI-PCI bridges?
198 if (ps
->ps_b
== busno
) {
199 if (ps
->ps_d
> (31 - 16))
202 * NOTE: PCI-X requires that that devices updated their
203 * PCIXSR on every config write with the device number
204 * specified in AD[15:11]. If we don't set this field,
205 * each device could end of thinking it is at device 0,
206 * which can cause a number of problems. Doing this
207 * unconditionally should be OK when only PCI devices
210 ps
->ps_addr_val
= (1U << (ps
->ps_d
+ 16)) |
211 (ps
->ps_d
<< 11) | (ps
->ps_f
<< 8) | offset
;
213 /* The tag is already in the correct format. */
214 ps
->ps_addr_val
= tag
| offset
| 1;
221 i80321_pci_conf_read(void *v
, pcitag_t tag
, int offset
)
223 struct i80321_softc
*sc
= v
;
224 struct pciconf_state ps
;
230 if (i80321_pci_conf_setup(sc
, tag
, offset
, &ps
))
231 return ((pcireg_t
) -1);
235 bus_space_write_4(sc
->sc_st
, sc
->sc_atu_sh
, ATU_OCCAR
,
238 va
= (vaddr_t
) bus_space_vaddr(sc
->sc_st
, sc
->sc_atu_sh
);
239 if (badaddr_read((void *) (va
+ ATU_OCCDR
), sizeof(rv
), &rv
)) {
240 isr
= bus_space_read_4(sc
->sc_st
, sc
->sc_atu_sh
, ATU_ATUISR
);
241 bus_space_write_4(sc
->sc_st
, sc
->sc_atu_sh
, ATU_ATUISR
,
242 isr
& (ATUISR_P_SERR_DET
|ATUISR_PMA
|ATUISR_PTAM
|
243 ATUISR_PTAT
|ATUISR_PMPE
));
245 printf("conf_read: %d/%d/%d bad address\n",
246 ps
.ps_b
, ps
.ps_d
, ps
.ps_f
);
257 i80321_pci_conf_write(void *v
, pcitag_t tag
, int offset
, pcireg_t val
)
259 struct i80321_softc
*sc
= v
;
260 struct pciconf_state ps
;
263 if (i80321_pci_conf_setup(sc
, tag
, offset
, &ps
))
268 bus_space_write_4(sc
->sc_st
, sc
->sc_atu_sh
, ATU_OCCAR
,
270 bus_space_write_4(sc
->sc_st
, sc
->sc_atu_sh
, ATU_OCCDR
, val
);