ixp425_pci.c revision 1.3.4.2 1 1.3.4.2 skrll /* $NetBSD: ixp425_pci.c,v 1.3.4.2 2004/08/03 10:32:58 skrll Exp $ */
2 1.3.4.2 skrll
3 1.3.4.2 skrll /*
4 1.3.4.2 skrll * Copyright (c) 2003
5 1.3.4.2 skrll * Ichiro FUKUHARA <ichiro (at) ichiro.org>.
6 1.3.4.2 skrll * All rights reserved.
7 1.3.4.2 skrll *
8 1.3.4.2 skrll * Redistribution and use in source and binary forms, with or without
9 1.3.4.2 skrll * modification, are permitted provided that the following conditions
10 1.3.4.2 skrll * are met:
11 1.3.4.2 skrll * 1. Redistributions of source code must retain the above copyright
12 1.3.4.2 skrll * notice, this list of conditions and the following disclaimer.
13 1.3.4.2 skrll * 2. Redistributions in binary form must reproduce the above copyright
14 1.3.4.2 skrll * notice, this list of conditions and the following disclaimer in the
15 1.3.4.2 skrll * documentation and/or other materials provided with the distribution.
16 1.3.4.2 skrll * 3. All advertising materials mentioning features or use of this software
17 1.3.4.2 skrll * must display the following acknowledgement:
18 1.3.4.2 skrll * This product includes software developed by Ichiro FUKUHARA.
19 1.3.4.2 skrll * 4. The name of the company nor the name of the author may be used to
20 1.3.4.2 skrll * endorse or promote products derived from this software without specific
21 1.3.4.2 skrll * prior written permission.
22 1.3.4.2 skrll *
23 1.3.4.2 skrll * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
24 1.3.4.2 skrll * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 1.3.4.2 skrll * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 1.3.4.2 skrll * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
27 1.3.4.2 skrll * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.3.4.2 skrll * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.3.4.2 skrll * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.3.4.2 skrll * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.3.4.2 skrll * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.3.4.2 skrll * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.3.4.2 skrll * SUCH DAMAGE.
34 1.3.4.2 skrll */
35 1.3.4.2 skrll
36 1.3.4.2 skrll #include <sys/cdefs.h>
37 1.3.4.2 skrll __KERNEL_RCSID(0, "$NetBSD: ixp425_pci.c,v 1.3.4.2 2004/08/03 10:32:58 skrll Exp $");
38 1.3.4.2 skrll
39 1.3.4.2 skrll #include <sys/param.h>
40 1.3.4.2 skrll #include <sys/systm.h>
41 1.3.4.2 skrll #include <sys/device.h>
42 1.3.4.2 skrll #include <sys/extent.h>
43 1.3.4.2 skrll #include <sys/malloc.h>
44 1.3.4.2 skrll
45 1.3.4.2 skrll #include <uvm/uvm_extern.h>
46 1.3.4.2 skrll
47 1.3.4.2 skrll #include <machine/bus.h>
48 1.3.4.2 skrll
49 1.3.4.2 skrll #include <arm/xscale/ixp425reg.h>
50 1.3.4.2 skrll #include <arm/xscale/ixp425var.h>
51 1.3.4.2 skrll
52 1.3.4.2 skrll #include <evbarm/ixdp425/ixdp425reg.h>
53 1.3.4.2 skrll
54 1.3.4.2 skrll #include <dev/pci/pcireg.h>
55 1.3.4.2 skrll #include <dev/pci/pcivar.h>
56 1.3.4.2 skrll #include <dev/pci/pciconf.h>
57 1.3.4.2 skrll
58 1.3.4.2 skrll #include "opt_pci.h"
59 1.3.4.2 skrll #include "pci.h"
60 1.3.4.2 skrll
61 1.3.4.2 skrll void ixp425_pci_attach_hook(struct device *, struct device *,
62 1.3.4.2 skrll struct pcibus_attach_args *);
63 1.3.4.2 skrll int ixp425_pci_bus_maxdevs(void *, int);
64 1.3.4.2 skrll void ixp425_pci_decompose_tag(void *, pcitag_t, int *, int *, int *);
65 1.3.4.2 skrll void ixp425_pci_conf_setup(void *, struct ixp425_softc *, pcitag_t, int);
66 1.3.4.2 skrll void ixp425_pci_conf_write(void *, pcitag_t, int, pcireg_t);
67 1.3.4.2 skrll pcitag_t ixp425_pci_make_tag(void *, int, int, int);
68 1.3.4.2 skrll pcireg_t ixp425_pci_conf_read(void *, pcitag_t, int);
69 1.3.4.2 skrll
70 1.3.4.2 skrll #define MAX_PCI_DEVICES 32
71 1.3.4.2 skrll
72 1.3.4.2 skrll void
73 1.3.4.2 skrll ixp425_pci_init(struct ixp425_softc *sc)
74 1.3.4.2 skrll {
75 1.3.4.2 skrll pci_chipset_tag_t pc = &sc->ia_pci_chipset;
76 1.3.4.2 skrll #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
77 1.3.4.2 skrll struct extent *ioext, *memext;
78 1.3.4.2 skrll #endif
79 1.3.4.2 skrll /*
80 1.3.4.2 skrll * Initialise the PCI chipset tag
81 1.3.4.2 skrll */
82 1.3.4.2 skrll pc->pc_conf_v = sc;
83 1.3.4.2 skrll pc->pc_attach_hook = ixp425_pci_attach_hook;
84 1.3.4.2 skrll pc->pc_bus_maxdevs = ixp425_pci_bus_maxdevs;
85 1.3.4.2 skrll pc->pc_make_tag = ixp425_pci_make_tag;
86 1.3.4.2 skrll pc->pc_decompose_tag = ixp425_pci_decompose_tag;
87 1.3.4.2 skrll pc->pc_conf_read = ixp425_pci_conf_read;
88 1.3.4.2 skrll pc->pc_conf_write = ixp425_pci_conf_write;
89 1.3.4.2 skrll
90 1.3.4.2 skrll /*
91 1.3.4.2 skrll * Initialize the bus space tags.
92 1.3.4.2 skrll */
93 1.3.4.2 skrll ixp425_io_bs_init(&sc->sc_pci_iot, sc);
94 1.3.4.2 skrll ixp425_mem_bs_init(&sc->sc_pci_memt, sc);
95 1.3.4.2 skrll
96 1.3.4.2 skrll #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
97 1.3.4.2 skrll ioext = extent_create("pciio", 0, IXP425_PCI_IO_SIZE - 1,
98 1.3.4.2 skrll M_DEVBUF, NULL, 0, EX_NOWAIT);
99 1.3.4.2 skrll /* PCI MEM space is mapped same address as real memory */
100 1.3.4.2 skrll memext = extent_create("pcimem", IXP425_PCI_MEM_HWBASE,
101 1.3.4.2 skrll IXP425_PCI_MEM_HWBASE +
102 1.3.4.2 skrll IXP425_PCI_MEM_SIZE - 1,
103 1.3.4.2 skrll M_DEVBUF, NULL, 0, EX_NOWAIT);
104 1.3.4.2 skrll printf("%s: configuring PCI bus\n", sc->sc_dev.dv_xname);
105 1.3.4.2 skrll pci_configure_bus(pc, ioext, memext, NULL, 0 /* XXX bus = 0 */,
106 1.3.4.2 skrll arm_dcache_align);
107 1.3.4.2 skrll
108 1.3.4.2 skrll extent_destroy(ioext);
109 1.3.4.2 skrll extent_destroy(memext);
110 1.3.4.2 skrll #endif
111 1.3.4.2 skrll }
112 1.3.4.2 skrll
113 1.3.4.2 skrll void
114 1.3.4.2 skrll pci_conf_interrupt(pci_chipset_tag_t pc, int a, int b, int c, int d, int *p)
115 1.3.4.2 skrll {
116 1.3.4.2 skrll }
117 1.3.4.2 skrll
118 1.3.4.2 skrll void
119 1.3.4.2 skrll ixp425_pci_attach_hook(struct device *parent, struct device *self,
120 1.3.4.2 skrll struct pcibus_attach_args *pba)
121 1.3.4.2 skrll {
122 1.3.4.2 skrll /* Nothing to do. */
123 1.3.4.2 skrll }
124 1.3.4.2 skrll
125 1.3.4.2 skrll int
126 1.3.4.2 skrll ixp425_pci_bus_maxdevs(void *v, int busno)
127 1.3.4.2 skrll {
128 1.3.4.2 skrll return(MAX_PCI_DEVICES);
129 1.3.4.2 skrll }
130 1.3.4.2 skrll
131 1.3.4.2 skrll pcitag_t
132 1.3.4.2 skrll ixp425_pci_make_tag(void *v, int bus, int device, int function)
133 1.3.4.2 skrll {
134 1.3.4.2 skrll #ifdef PCI_DEBUG
135 1.3.4.2 skrll printf("ixp425_pci_make_tag(v=%p, bus=%d, device=%d, function=%d)\n",
136 1.3.4.2 skrll v, bus, device, function);
137 1.3.4.2 skrll #endif
138 1.3.4.2 skrll return ((bus << 16) | (device << 11) | (function << 8));
139 1.3.4.2 skrll }
140 1.3.4.2 skrll
141 1.3.4.2 skrll void
142 1.3.4.2 skrll ixp425_pci_decompose_tag(void *v, pcitag_t tag, int *busp, int *devicep,
143 1.3.4.2 skrll int *functionp)
144 1.3.4.2 skrll {
145 1.3.4.2 skrll #ifdef PCI_DEBUG
146 1.3.4.2 skrll printf("ixp425_pci_decompose_tag(v=%p, tag=0x%08lx, bp=%x, dp=%x, fp=%x)\n",
147 1.3.4.2 skrll v, tag, (int)busp, (int)devicep, (int)functionp);
148 1.3.4.2 skrll #endif
149 1.3.4.2 skrll if (busp != NULL)
150 1.3.4.2 skrll *busp = (tag >> 16) & 0xff;
151 1.3.4.2 skrll if (devicep != NULL)
152 1.3.4.2 skrll *devicep = (tag >> 11) & 0x1f;
153 1.3.4.2 skrll if (functionp != NULL)
154 1.3.4.2 skrll *functionp = (tag >> 8) & 0x7;
155 1.3.4.2 skrll }
156 1.3.4.2 skrll
157 1.3.4.2 skrll void
158 1.3.4.2 skrll ixp425_pci_conf_setup(void *v, struct ixp425_softc *sc, pcitag_t tag, int offset)
159 1.3.4.2 skrll {
160 1.3.4.2 skrll int bus, device, function;
161 1.3.4.2 skrll
162 1.3.4.2 skrll ixp425_pci_decompose_tag(v, tag, &bus, &device, &function);
163 1.3.4.2 skrll
164 1.3.4.2 skrll if (bus == 0) {
165 1.3.4.2 skrll if (device == 0 && function == 0) {
166 1.3.4.2 skrll PCI_CSR_WRITE_4(sc, PCI_NP_AD, (offset & ~3));
167 1.3.4.2 skrll } else {
168 1.3.4.2 skrll /* configuration type 0 */
169 1.3.4.2 skrll PCI_CSR_WRITE_4(sc, PCI_NP_AD, (1U << (32 - device)) |
170 1.3.4.2 skrll (function << 8) | (offset & ~3));
171 1.3.4.2 skrll }
172 1.3.4.2 skrll } else {
173 1.3.4.2 skrll /* configuration type 1 */
174 1.3.4.2 skrll PCI_CSR_WRITE_4(sc, PCI_NP_AD,
175 1.3.4.2 skrll (bus << 16) | (device << 11) |
176 1.3.4.2 skrll (function << 8) | (offset & ~3) | 1);
177 1.3.4.2 skrll }
178 1.3.4.2 skrll }
179 1.3.4.2 skrll
180 1.3.4.2 skrll /* read/write PCI Non-Pre-fetch Data */
181 1.3.4.2 skrll
182 1.3.4.2 skrll pcireg_t
183 1.3.4.2 skrll ixp425_pci_conf_read(void *v, pcitag_t tag, int offset)
184 1.3.4.2 skrll {
185 1.3.4.2 skrll struct ixp425_softc *sc = v;
186 1.3.4.2 skrll u_int32_t data;
187 1.3.4.2 skrll pcireg_t rv;
188 1.3.4.2 skrll int s;
189 1.3.4.2 skrll #define PCI_NP_HAVE_BUG
190 1.3.4.2 skrll #ifdef PCI_NP_HAVE_BUG
191 1.3.4.2 skrll int i;
192 1.3.4.2 skrll #endif
193 1.3.4.2 skrll
194 1.3.4.2 skrll PCI_CONF_LOCK(s);
195 1.3.4.2 skrll ixp425_pci_conf_setup(v, sc, tag, offset);
196 1.3.4.2 skrll
197 1.3.4.2 skrll #ifdef PCI_DEBUG
198 1.3.4.2 skrll printf("ixp425_pci_conf_read: tag=%lx,offset=%x\n",
199 1.3.4.2 skrll tag, offset);
200 1.3.4.2 skrll #endif
201 1.3.4.2 skrll
202 1.3.4.2 skrll #ifdef PCI_NP_HAVE_BUG
203 1.3.4.2 skrll /* PCI NP Bug workaround */
204 1.3.4.2 skrll for (i = 0; i < 8; i++) {
205 1.3.4.2 skrll PCI_CSR_WRITE_4(sc, PCI_NP_CBE, COMMAND_NP_CONF_READ);
206 1.3.4.2 skrll rv = PCI_CSR_READ_4(sc, PCI_NP_RDATA);
207 1.3.4.2 skrll rv = PCI_CSR_READ_4(sc, PCI_NP_RDATA);
208 1.3.4.2 skrll }
209 1.3.4.2 skrll #else
210 1.3.4.2 skrll PCI_CSR_WRITE_4(sc, PCI_NP_CBE, COMMAND_NP_CONF_READ);
211 1.3.4.2 skrll rv = PCI_CSR_READ_4(sc, PCI_NP_RDATA);
212 1.3.4.2 skrll #endif
213 1.3.4.2 skrll
214 1.3.4.2 skrll /* check&clear PCI abort */
215 1.3.4.2 skrll data = PCI_CSR_READ_4(sc, PCI_ISR);
216 1.3.4.2 skrll if (data & ISR_PFE) {
217 1.3.4.2 skrll PCI_CSR_WRITE_4(sc, PCI_ISR, ISR_PFE);
218 1.3.4.2 skrll PCI_CONF_UNLOCK(s);
219 1.3.4.2 skrll return -1;
220 1.3.4.2 skrll } else {
221 1.3.4.2 skrll PCI_CONF_UNLOCK(s);
222 1.3.4.2 skrll return rv;
223 1.3.4.2 skrll }
224 1.3.4.2 skrll }
225 1.3.4.2 skrll
226 1.3.4.2 skrll void
227 1.3.4.2 skrll ixp425_pci_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val)
228 1.3.4.2 skrll {
229 1.3.4.2 skrll struct ixp425_softc *sc = v;
230 1.3.4.2 skrll u_int32_t data;
231 1.3.4.2 skrll int s;
232 1.3.4.2 skrll
233 1.3.4.2 skrll PCI_CONF_LOCK(s);
234 1.3.4.2 skrll
235 1.3.4.2 skrll ixp425_pci_conf_setup(v, sc, tag, offset);
236 1.3.4.2 skrll #ifdef PCI_DEBUG
237 1.3.4.2 skrll printf("ixp425_pci_conf_write: tag=%lx offset=%x <- val=%x\n",
238 1.3.4.2 skrll tag, offset, val);
239 1.3.4.2 skrll #endif
240 1.3.4.2 skrll PCI_CSR_WRITE_4(sc, PCI_NP_CBE, COMMAND_NP_CONF_WRITE);
241 1.3.4.2 skrll PCI_CSR_WRITE_4(sc, PCI_NP_WDATA, val);
242 1.3.4.2 skrll
243 1.3.4.2 skrll /* check&clear PCI abort */
244 1.3.4.2 skrll data = PCI_CSR_READ_4(sc, PCI_ISR);
245 1.3.4.2 skrll if (data & ISR_PFE)
246 1.3.4.2 skrll PCI_CSR_WRITE_4(sc, PCI_ISR, ISR_PFE);
247 1.3.4.2 skrll
248 1.3.4.2 skrll PCI_CONF_UNLOCK(s);
249 1.3.4.2 skrll }
250 1.3.4.2 skrll
251 1.3.4.2 skrll /* read/write pci configuration data */
252 1.3.4.2 skrll
253 1.3.4.2 skrll uint32_t
254 1.3.4.2 skrll ixp425_pci_conf_reg_read(struct ixp425_softc *sc, uint32_t reg)
255 1.3.4.2 skrll {
256 1.3.4.2 skrll uint32_t data;
257 1.3.4.2 skrll
258 1.3.4.2 skrll bus_space_write_4(sc->sc_iot, sc->sc_pci_ioh,
259 1.3.4.2 skrll PCI_CRP_AD_CBE, ((reg & ~3) | COMMAND_CRP_READ));
260 1.3.4.2 skrll data = bus_space_read_4(sc->sc_iot, sc->sc_pci_ioh,
261 1.3.4.2 skrll PCI_CRP_AD_RDATA);
262 1.3.4.2 skrll
263 1.3.4.2 skrll return data;
264 1.3.4.2 skrll }
265 1.3.4.2 skrll
266 1.3.4.2 skrll void
267 1.3.4.2 skrll ixp425_pci_conf_reg_write(struct ixp425_softc *sc, uint32_t reg,
268 1.3.4.2 skrll uint32_t data)
269 1.3.4.2 skrll {
270 1.3.4.2 skrll bus_space_write_4(sc->sc_iot, sc->sc_pci_ioh,
271 1.3.4.2 skrll PCI_CRP_AD_CBE, ((reg & ~3) | COMMAND_CRP_WRITE));
272 1.3.4.2 skrll bus_space_write_4(sc->sc_iot, sc->sc_pci_ioh,
273 1.3.4.2 skrll PCI_CRP_AD_WDATA, data);
274 1.3.4.2 skrll }
275