1 /* $NetBSD: ixp425_pci.c,v 1.5 2006/04/10 03:36:03 simonb Exp $ */
5 * Ichiro FUKUHARA <ichiro@ichiro.org>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: ixp425_pci.c,v 1.5 2006/04/10 03:36:03 simonb Exp $");
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/device.h>
36 #include <sys/extent.h>
37 #include <sys/malloc.h>
39 #include <uvm/uvm_extern.h>
41 #include <machine/bus.h>
43 #include <arm/xscale/ixp425reg.h>
44 #include <arm/xscale/ixp425var.h>
46 #include <evbarm/ixdp425/ixdp425reg.h>
48 #include <dev/pci/pcireg.h>
49 #include <dev/pci/pcivar.h>
50 #include <dev/pci/pciconf.h>
55 void ixp425_pci_attach_hook(struct device
*, struct device
*,
56 struct pcibus_attach_args
*);
57 int ixp425_pci_bus_maxdevs(void *, int);
58 void ixp425_pci_decompose_tag(void *, pcitag_t
, int *, int *, int *);
59 void ixp425_pci_conf_setup(void *, struct ixp425_softc
*, pcitag_t
, int);
60 void ixp425_pci_conf_write(void *, pcitag_t
, int, pcireg_t
);
61 pcitag_t
ixp425_pci_make_tag(void *, int, int, int);
62 pcireg_t
ixp425_pci_conf_read(void *, pcitag_t
, int);
64 #define MAX_PCI_DEVICES 32
67 ixp425_pci_init(struct ixp425_softc
*sc
)
69 pci_chipset_tag_t pc
= &sc
->ia_pci_chipset
;
70 #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
71 struct extent
*ioext
, *memext
;
74 * Initialise the PCI chipset tag
77 pc
->pc_attach_hook
= ixp425_pci_attach_hook
;
78 pc
->pc_bus_maxdevs
= ixp425_pci_bus_maxdevs
;
79 pc
->pc_make_tag
= ixp425_pci_make_tag
;
80 pc
->pc_decompose_tag
= ixp425_pci_decompose_tag
;
81 pc
->pc_conf_read
= ixp425_pci_conf_read
;
82 pc
->pc_conf_write
= ixp425_pci_conf_write
;
85 * Initialize the bus space tags.
87 ixp425_io_bs_init(&sc
->sc_pci_iot
, sc
);
88 ixp425_mem_bs_init(&sc
->sc_pci_memt
, sc
);
90 #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
91 ioext
= extent_create("pciio", 0, IXP425_PCI_IO_SIZE
- 1,
92 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
93 /* PCI MEM space is mapped same address as real memory */
94 memext
= extent_create("pcimem", IXP425_PCI_MEM_HWBASE
,
95 IXP425_PCI_MEM_HWBASE
+
96 IXP425_PCI_MEM_SIZE
- 1,
97 M_DEVBUF
, NULL
, 0, EX_NOWAIT
);
98 printf("%s: configuring PCI bus\n", sc
->sc_dev
.dv_xname
);
99 pci_configure_bus(pc
, ioext
, memext
, NULL
, 0 /* XXX bus = 0 */,
102 extent_destroy(ioext
);
103 extent_destroy(memext
);
108 pci_conf_interrupt(pci_chipset_tag_t pc
, int a
, int b
, int c
, int d
, int *p
)
113 ixp425_pci_attach_hook(struct device
*parent
, struct device
*self
,
114 struct pcibus_attach_args
*pba
)
120 ixp425_pci_bus_maxdevs(void *v
, int busno
)
122 return(MAX_PCI_DEVICES
);
126 ixp425_pci_make_tag(void *v
, int bus
, int device
, int function
)
129 printf("ixp425_pci_make_tag(v=%p, bus=%d, device=%d, function=%d)\n",
130 v
, bus
, device
, function
);
132 return ((bus
<< 16) | (device
<< 11) | (function
<< 8));
136 ixp425_pci_decompose_tag(void *v
, pcitag_t tag
, int *busp
, int *devicep
,
140 printf("ixp425_pci_decompose_tag(v=%p, tag=0x%08lx, bp=%x, dp=%x, fp=%x)\n",
141 v
, tag
, (int)busp
, (int)devicep
, (int)functionp
);
144 *busp
= (tag
>> 16) & 0xff;
146 *devicep
= (tag
>> 11) & 0x1f;
147 if (functionp
!= NULL
)
148 *functionp
= (tag
>> 8) & 0x7;
152 ixp425_pci_conf_setup(void *v
, struct ixp425_softc
*sc
, pcitag_t tag
, int offset
)
154 int bus
, device
, function
;
156 ixp425_pci_decompose_tag(v
, tag
, &bus
, &device
, &function
);
159 if (device
== 0 && function
== 0) {
160 PCI_CSR_WRITE_4(sc
, PCI_NP_AD
, (offset
& ~3));
162 /* configuration type 0 */
163 PCI_CSR_WRITE_4(sc
, PCI_NP_AD
, (1U << (32 - device
)) |
164 (function
<< 8) | (offset
& ~3));
167 /* configuration type 1 */
168 PCI_CSR_WRITE_4(sc
, PCI_NP_AD
,
169 (bus
<< 16) | (device
<< 11) |
170 (function
<< 8) | (offset
& ~3) | 1);
174 /* read/write PCI Non-Pre-fetch Data */
177 ixp425_pci_conf_read(void *v
, pcitag_t tag
, int offset
)
179 struct ixp425_softc
*sc
= v
;
183 #define PCI_NP_HAVE_BUG
184 #ifdef PCI_NP_HAVE_BUG
189 ixp425_pci_conf_setup(v
, sc
, tag
, offset
);
192 printf("ixp425_pci_conf_read: tag=%lx,offset=%x\n",
196 #ifdef PCI_NP_HAVE_BUG
197 /* PCI NP Bug workaround */
198 for (i
= 0; i
< 8; i
++) {
199 PCI_CSR_WRITE_4(sc
, PCI_NP_CBE
, COMMAND_NP_CONF_READ
);
200 rv
= PCI_CSR_READ_4(sc
, PCI_NP_RDATA
);
201 rv
= PCI_CSR_READ_4(sc
, PCI_NP_RDATA
);
204 PCI_CSR_WRITE_4(sc
, PCI_NP_CBE
, COMMAND_NP_CONF_READ
);
205 rv
= PCI_CSR_READ_4(sc
, PCI_NP_RDATA
);
208 /* check&clear PCI abort */
209 data
= PCI_CSR_READ_4(sc
, PCI_ISR
);
210 if (data
& ISR_PFE
) {
211 PCI_CSR_WRITE_4(sc
, PCI_ISR
, ISR_PFE
);
221 ixp425_pci_conf_write(void *v
, pcitag_t tag
, int offset
, pcireg_t val
)
223 struct ixp425_softc
*sc
= v
;
229 ixp425_pci_conf_setup(v
, sc
, tag
, offset
);
231 printf("ixp425_pci_conf_write: tag=%lx offset=%x <- val=%x\n",
234 PCI_CSR_WRITE_4(sc
, PCI_NP_CBE
, COMMAND_NP_CONF_WRITE
);
235 PCI_CSR_WRITE_4(sc
, PCI_NP_WDATA
, val
);
237 /* check&clear PCI abort */
238 data
= PCI_CSR_READ_4(sc
, PCI_ISR
);
240 PCI_CSR_WRITE_4(sc
, PCI_ISR
, ISR_PFE
);
245 /* read/write pci configuration data */
248 ixp425_pci_conf_reg_read(struct ixp425_softc
*sc
, uint32_t reg
)
252 bus_space_write_4(sc
->sc_iot
, sc
->sc_pci_ioh
,
253 PCI_CRP_AD_CBE
, ((reg
& ~3) | COMMAND_CRP_READ
));
254 data
= bus_space_read_4(sc
->sc_iot
, sc
->sc_pci_ioh
,
261 ixp425_pci_conf_reg_write(struct ixp425_softc
*sc
, uint32_t reg
,
264 bus_space_write_4(sc
->sc_iot
, sc
->sc_pci_ioh
,
265 PCI_CRP_AD_CBE
, ((reg
& ~3) | COMMAND_CRP_WRITE
));
266 bus_space_write_4(sc
->sc_iot
, sc
->sc_pci_ioh
,
267 PCI_CRP_AD_WDATA
, data
);