s3c2800_pci.c revision 1.26 1 1.26 jmcneill /* $NetBSD: s3c2800_pci.c,v 1.26 2018/11/26 12:21:51 jmcneill Exp $ */
2 1.1 bsh
3 1.1 bsh /*
4 1.1 bsh * Copyright (c) 2002 Fujitsu Component Limited
5 1.1 bsh * Copyright (c) 2002 Genetec Corporation
6 1.1 bsh * All rights reserved.
7 1.1 bsh *
8 1.1 bsh * Redistribution and use in source and binary forms, with or without
9 1.1 bsh * modification, are permitted provided that the following conditions
10 1.1 bsh * are met:
11 1.1 bsh * 1. Redistributions of source code must retain the above copyright
12 1.1 bsh * notice, this list of conditions and the following disclaimer.
13 1.1 bsh * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 bsh * notice, this list of conditions and the following disclaimer in the
15 1.1 bsh * documentation and/or other materials provided with the distribution.
16 1.1 bsh * 3. Neither the name of The Fujitsu Component Limited nor the name of
17 1.1 bsh * Genetec corporation may not be used to endorse or promote products
18 1.1 bsh * derived from this software without specific prior written permission.
19 1.1 bsh *
20 1.1 bsh * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
21 1.1 bsh * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 1.1 bsh * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 1.1 bsh * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 1.1 bsh * DISCLAIMED. IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
25 1.1 bsh * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 1.1 bsh * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 1.1 bsh * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 1.1 bsh * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 1.1 bsh * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 1.1 bsh * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 1.1 bsh * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.1 bsh * SUCH DAMAGE.
33 1.1 bsh *
34 1.1 bsh * derived from evbarm/ifpga/ifpga_pci.c
35 1.1 bsh */
36 1.1 bsh
37 1.1 bsh /*
38 1.1 bsh * Copyright (c) 2001 ARM Ltd
39 1.1 bsh * All rights reserved.
40 1.1 bsh *
41 1.1 bsh * Redistribution and use in source and binary forms, with or without
42 1.1 bsh * modification, are permitted provided that the following conditions
43 1.1 bsh * are met:
44 1.1 bsh * 1. Redistributions of source code must retain the above copyright
45 1.1 bsh * notice, this list of conditions and the following disclaimer.
46 1.1 bsh * 2. Redistributions in binary form must reproduce the above copyright
47 1.1 bsh * notice, this list of conditions and the following disclaimer in the
48 1.1 bsh * documentation and/or other materials provided with the distribution.
49 1.1 bsh * 3. The name of the company may not be used to endorse or promote
50 1.1 bsh * products derived from this software without specific prior written
51 1.1 bsh * permission.
52 1.1 bsh *
53 1.1 bsh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
54 1.1 bsh * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
55 1.1 bsh * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
56 1.1 bsh * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
57 1.1 bsh * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
58 1.1 bsh * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
59 1.1 bsh * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 1.1 bsh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 1.1 bsh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 1.1 bsh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 1.1 bsh * SUCH DAMAGE.
64 1.1 bsh *
65 1.1 bsh * Copyright (c) 1997,1998 Mark Brinicombe.
66 1.1 bsh * Copyright (c) 1997,1998 Causality Limited
67 1.1 bsh * All rights reserved.
68 1.1 bsh *
69 1.1 bsh * Redistribution and use in source and binary forms, with or without
70 1.1 bsh * modification, are permitted provided that the following conditions
71 1.1 bsh * are met:
72 1.1 bsh * 1. Redistributions of source code must retain the above copyright
73 1.1 bsh * notice, this list of conditions and the following disclaimer.
74 1.1 bsh * 2. Redistributions in binary form must reproduce the above copyright
75 1.1 bsh * notice, this list of conditions and the following disclaimer in the
76 1.1 bsh * documentation and/or other materials provided with the distribution.
77 1.1 bsh * 3. All advertising materials mentioning features or use of this software
78 1.1 bsh * must display the following acknowledgement:
79 1.1 bsh * This product includes software developed by Mark Brinicombe
80 1.1 bsh * for the NetBSD Project.
81 1.1 bsh * 4. The name of the company nor the name of the author may be used to
82 1.1 bsh * endorse or promote products derived from this software without specific
83 1.1 bsh * prior written permission.
84 1.1 bsh *
85 1.1 bsh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
86 1.1 bsh * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
87 1.1 bsh * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
88 1.1 bsh * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
89 1.1 bsh * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
90 1.1 bsh * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
91 1.1 bsh * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
92 1.1 bsh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
93 1.1 bsh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
94 1.1 bsh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
95 1.1 bsh * SUCH DAMAGE.
96 1.1 bsh */
97 1.1 bsh
98 1.1 bsh /*
99 1.1 bsh * PCI configuration support for Samsung s3c2800.
100 1.1 bsh */
101 1.7 lukem
102 1.7 lukem #include <sys/cdefs.h>
103 1.26 jmcneill __KERNEL_RCSID(0, "$NetBSD: s3c2800_pci.c,v 1.26 2018/11/26 12:21:51 jmcneill Exp $");
104 1.20 matt
105 1.20 matt #include "opt_pci.h"
106 1.20 matt #include "pci.h"
107 1.1 bsh
108 1.1 bsh #include <sys/param.h>
109 1.1 bsh #include <sys/systm.h>
110 1.1 bsh #include <sys/kernel.h>
111 1.1 bsh #include <sys/device.h>
112 1.1 bsh #include <sys/extent.h>
113 1.1 bsh #include <sys/malloc.h>
114 1.1 bsh
115 1.1 bsh #include <uvm/uvm_extern.h>
116 1.1 bsh
117 1.16 dyoung #include <sys/bus.h>
118 1.1 bsh
119 1.1 bsh #include <dev/pci/pcireg.h>
120 1.20 matt #include <dev/pci/pcivar.h>
121 1.1 bsh #include <dev/pci/pciconf.h>
122 1.1 bsh
123 1.20 matt #include <arm/locore.h>
124 1.20 matt
125 1.20 matt #include <arm/s3c2xx0/s3c2800reg.h>
126 1.20 matt #include <arm/s3c2xx0/s3c2800var.h>
127 1.1 bsh
128 1.1 bsh /*
129 1.1 bsh * pci tag encoding.
130 1.1 bsh * also useful for configuration type 0 address
131 1.1 bsh */
132 1.1 bsh #define BUSNO_SHIFT 16
133 1.1 bsh #define BUSNO_MASK (0xff<<BUSNO_SHIFT)
134 1.1 bsh #define DEVNO_SHIFT 11
135 1.1 bsh #define DEVNO_MASK (0x1f<<DEVNO_SHIFT)
136 1.1 bsh #define tag_to_devno(tag) (((tag)&DEVNO_MASK)>>DEVNO_SHIFT)
137 1.1 bsh #define FUNNO_SHIFT 8
138 1.1 bsh #define FUNNO_MASK (0x07<<FUNNO_SHIFT)
139 1.1 bsh
140 1.1 bsh #define BUS0_DEV_MIN 1
141 1.1 bsh #define BUS0_DEV_MAX 21
142 1.1 bsh
143 1.19 chs void s3c2800_pci_attach_hook(device_t, device_t, struct pcibus_attach_args *);
144 1.1 bsh int s3c2800_pci_bus_maxdevs(void *, int);
145 1.1 bsh pcitag_t s3c2800_pci_make_tag(void *, int, int, int);
146 1.1 bsh void s3c2800_pci_decompose_tag(void *, pcitag_t, int *, int *, int *);
147 1.1 bsh pcireg_t s3c2800_pci_conf_read(void *, pcitag_t, int);
148 1.1 bsh void s3c2800_pci_conf_write(void *, pcitag_t, int, pcireg_t);
149 1.18 matt void s3c2800_pci_conf_interrupt(void *, int, int, int, int, int *);
150 1.14 dyoung int s3c2800_pci_intr_map(const struct pci_attach_args *,
151 1.14 dyoung pci_intr_handle_t *);
152 1.21 christos const char *s3c2800_pci_intr_string(void *, pci_intr_handle_t, char *, size_t);
153 1.1 bsh const struct evcnt *s3c2800_pci_intr_evcnt(void *, pci_intr_handle_t);
154 1.12 christos void *s3c2800_pci_intr_establish(void *, pci_intr_handle_t, int,
155 1.25 jmcneill int (*) (void *), void *, const char *);
156 1.1 bsh void s3c2800_pci_intr_disestablish(void *, void *);
157 1.1 bsh
158 1.1 bsh #define PCI_CONF_LOCK(s) (s) = disable_interrupts(I32_bit)
159 1.1 bsh #define PCI_CONF_UNLOCK(s) restore_interrupts((s))
160 1.1 bsh
161 1.1 bsh struct sspci_irq_handler {
162 1.1 bsh int (*func) (void *);
163 1.1 bsh void *arg;
164 1.1 bsh int level;
165 1.1 bsh SLIST_ENTRY(sspci_irq_handler) link;
166 1.1 bsh };
167 1.1 bsh
168 1.1 bsh struct sspci_softc {
169 1.19 chs device_t sc_dev;
170 1.1 bsh
171 1.1 bsh bus_space_tag_t sc_iot;
172 1.1 bsh bus_space_handle_t sc_reg_ioh;
173 1.1 bsh bus_space_handle_t sc_conf0_ioh; /* config type0 space */
174 1.1 bsh bus_space_handle_t sc_conf1_ioh; /* config type1 space */
175 1.1 bsh
176 1.1 bsh uint32_t sc_pciinten; /* copy of PCIINTEN register */
177 1.1 bsh
178 1.1 bsh /* list of interrupt handlers. SLIST is not good for removing
179 1.1 bsh * element from it, but intr_disestablish is rarely called */
180 1.1 bsh SLIST_HEAD(, sspci_irq_handler) sc_irq_handlers;
181 1.1 bsh
182 1.1 bsh void *sc_softinterrupt;
183 1.1 bsh };
184 1.1 bsh
185 1.19 chs static int sspci_match(device_t, cfdata_t, void *aux);
186 1.19 chs static void sspci_attach(device_t, device_t, void *);
187 1.1 bsh
188 1.1 bsh static int sspci_bs_map(void *, bus_addr_t, bus_size_t, int,
189 1.1 bsh bus_space_handle_t *);
190 1.1 bsh static int sspci_init_controller(struct sspci_softc *);
191 1.1 bsh static int sspci_intr(void *);
192 1.1 bsh static void sspci_softintr(void *);
193 1.1 bsh
194 1.1 bsh /* attach structures */
195 1.19 chs CFATTACH_DECL_NEW(sspci, sizeof(struct sspci_softc), sspci_match, sspci_attach,
196 1.1 bsh NULL, NULL);
197 1.1 bsh
198 1.1 bsh
199 1.1 bsh struct arm32_pci_chipset sspci_chipset = {
200 1.26 jmcneill .pc_attach_hook = s3c2800_pci_attach_hook,
201 1.26 jmcneill .pc_bus_maxdevs = s3c2800_pci_bus_maxdevs,
202 1.26 jmcneill .pc_make_tag = s3c2800_pci_make_tag,
203 1.26 jmcneill .pc_decompose_tag = s3c2800_pci_decompose_tag,
204 1.26 jmcneill .pc_conf_read = s3c2800_pci_conf_read,
205 1.26 jmcneill .pc_conf_write = s3c2800_pci_conf_write,
206 1.26 jmcneill .pc_intr_map = s3c2800_pci_intr_map,
207 1.26 jmcneill .pc_intr_string = s3c2800_pci_intr_string,
208 1.26 jmcneill .pc_intr_evcnt = s3c2800_pci_intr_evcnt,
209 1.26 jmcneill .pc_intr_establish = s3c2800_pci_intr_establish,
210 1.26 jmcneill .pc_intr_disestablish = s3c2800_pci_intr_disestablish,
211 1.26 jmcneill .pc_conf_interrupt = s3c2800_pci_conf_interrupt,
212 1.1 bsh };
213 1.1 bsh
214 1.1 bsh
215 1.1 bsh /*
216 1.1 bsh * bus space tag for PCI IO/Memory access space.
217 1.1 bsh * filled in by sspci_attach()
218 1.1 bsh */
219 1.1 bsh struct bus_space sspci_io_tag, sspci_mem_tag;
220 1.1 bsh
221 1.1 bsh static int
222 1.19 chs sspci_match(device_t parent, cfdata_t match, void *aux)
223 1.1 bsh {
224 1.1 bsh return 1;
225 1.1 bsh }
226 1.1 bsh
227 1.1 bsh static void
228 1.19 chs sspci_attach(device_t parent, device_t self, void *aux)
229 1.1 bsh {
230 1.19 chs struct sspci_softc *sc = device_private(self);
231 1.1 bsh struct s3c2xx0_attach_args *aa = aux;
232 1.1 bsh bus_space_tag_t iot;
233 1.1 bsh bus_dma_tag_t pci_dma_tag;
234 1.1 bsh const char *error_on; /* for panic message */
235 1.1 bsh #if defined(PCI_NETBSD_CONFIGURE)
236 1.1 bsh struct extent *ioext, *memext;
237 1.1 bsh struct pcibus_attach_args pci_pba;
238 1.1 bsh #endif
239 1.1 bsh
240 1.1 bsh #define FAIL(which) do { \
241 1.1 bsh error_on=(which); goto abort; }while(/*CONSTCOND*/0)
242 1.1 bsh
243 1.19 chs sc->sc_dev = self;
244 1.1 bsh iot = sc->sc_iot = aa->sa_iot;
245 1.1 bsh if (bus_space_map(iot, S3C2800_PCICTL_BASE,
246 1.1 bsh S3C2800_PCICTL_SIZE, 0, &sc->sc_reg_ioh))
247 1.1 bsh FAIL("control regs");
248 1.1 bsh
249 1.1 bsh if (bus_space_map(iot, S3C2800_PCI_CONF0_BASE,
250 1.1 bsh S3C2800_PCI_CONF0_SIZE, 0, &sc->sc_conf0_ioh))
251 1.1 bsh FAIL("config type 0 area");
252 1.1 bsh
253 1.1 bsh #if 0
254 1.1 bsh if (bus_space_map(iot, S3C2800_PCI_CONF1_BASE,
255 1.1 bsh S3C2800_PCI_CONF1_SIZE, 0, &sc->sc_conf1_ioh))
256 1.1 bsh FAIL("config type 1 area");
257 1.1 bsh #endif
258 1.1 bsh printf("\n");
259 1.1 bsh
260 1.1 bsh SLIST_INIT(&sc->sc_irq_handlers);
261 1.4 bsh if (!s3c2800_intr_establish(S3C2800_INT_PCI, IPL_AUDIO, IST_LEVEL,
262 1.1 bsh sspci_intr, sc))
263 1.1 bsh FAIL("intr_establish");
264 1.1 bsh
265 1.13 matt sc->sc_softinterrupt = softint_establish(SOFTINT_SERIAL,
266 1.1 bsh sspci_softintr, sc);
267 1.1 bsh if (sc->sc_softinterrupt == NULL)
268 1.13 matt FAIL("softint_establish");
269 1.1 bsh
270 1.1 bsh #if defined(PCI_NETBSD_CONFIGURE)
271 1.1 bsh if (sspci_init_controller(sc)) {
272 1.19 chs printf("%s: failed to initialize controller\n", device_xname(self));
273 1.1 bsh return;
274 1.1 bsh }
275 1.1 bsh #endif
276 1.1 bsh
277 1.1 bsh sc->sc_pciinten =
278 1.1 bsh PCIINT_INA | PCIINT_SER | PCIINT_TPE | PCIINT_MPE |
279 1.1 bsh PCIINT_MFE | PCIINT_PRA | PCIINT_PRD;
280 1.1 bsh
281 1.1 bsh bus_space_write_4(iot, sc->sc_reg_ioh, PCICTL_PCIINTEN,
282 1.1 bsh sc->sc_pciinten);
283 1.1 bsh
284 1.1 bsh {
285 1.1 bsh pcireg_t id_reg, class_reg;
286 1.1 bsh char buf[1000];
287 1.1 bsh
288 1.1 bsh id_reg = bus_space_read_4(iot, sc->sc_reg_ioh,
289 1.1 bsh PCI_ID_REG);
290 1.1 bsh class_reg = bus_space_read_4(iot,
291 1.1 bsh sc->sc_reg_ioh, PCI_CLASS_REG);
292 1.1 bsh
293 1.8 kleink pci_devinfo(id_reg, class_reg, 1, buf, sizeof(buf));
294 1.19 chs printf("%s: %s\n", device_xname(self), buf);
295 1.1 bsh }
296 1.1 bsh
297 1.1 bsh #if defined(PCI_NETBSD_CONFIGURE)
298 1.6 bsh ioext = extent_create("pciio", 0x100, S3C2800_PCI_IOSPACE_SIZE - 0x100,
299 1.17 para NULL, 0, EX_NOWAIT);
300 1.1 bsh
301 1.1 bsh memext = extent_create("pcimem", 0, S3C2800_PCI_MEMSPACE_SIZE,
302 1.17 para NULL, 0, EX_NOWAIT);
303 1.1 bsh
304 1.1 bsh sspci_chipset.pc_conf_v = (void *) sc;
305 1.1 bsh sspci_chipset.pc_intr_v = (void *) sc;
306 1.1 bsh
307 1.1 bsh pci_configure_bus(&sspci_chipset, ioext, memext, NULL, 0,
308 1.1 bsh arm_dcache_align);
309 1.1 bsh
310 1.1 bsh extent_destroy(memext);
311 1.1 bsh extent_destroy(ioext);
312 1.1 bsh #endif /* PCI_NETBSD_CONFIGURE */
313 1.1 bsh
314 1.1 bsh /* initialize bus space tag */
315 1.1 bsh sspci_io_tag = *iot;
316 1.1 bsh sspci_io_tag.bs_cookie = (void *) S3C2800_PCI_IOSPACE_BASE;
317 1.1 bsh sspci_io_tag.bs_map = sspci_bs_map;
318 1.1 bsh sspci_mem_tag = *iot;
319 1.1 bsh sspci_mem_tag.bs_cookie = (void *) S3C2800_PCI_MEMSPACE_BASE;
320 1.1 bsh sspci_mem_tag.bs_map = sspci_bs_map;
321 1.1 bsh
322 1.1 bsh
323 1.1 bsh /* Platform provides PCI DMA tag */
324 1.1 bsh pci_dma_tag = s3c2800_pci_dma_init();
325 1.1 bsh
326 1.1 bsh pci_pba.pba_pc = &sspci_chipset;
327 1.1 bsh pci_pba.pba_iot = &sspci_io_tag;
328 1.1 bsh pci_pba.pba_memt = &sspci_mem_tag;
329 1.1 bsh pci_pba.pba_dmat = pci_dma_tag;
330 1.5 fvdl pci_pba.pba_dmat64 = NULL;
331 1.15 dyoung pci_pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
332 1.1 bsh pci_pba.pba_bus = 0;
333 1.1 bsh pci_pba.pba_bridgetag = NULL;
334 1.1 bsh
335 1.9 drochner config_found_ia(self, "pcibus", &pci_pba, pcibusprint);
336 1.1 bsh
337 1.1 bsh return;
338 1.1 bsh
339 1.1 bsh #undef FAIL
340 1.1 bsh abort:
341 1.1 bsh panic("%s: map failed (%s)",
342 1.19 chs device_xname(self), error_on);
343 1.1 bsh }
344 1.1 bsh
345 1.1 bsh
346 1.1 bsh static int
347 1.1 bsh sspci_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flag,
348 1.1 bsh bus_space_handle_t * bshp)
349 1.1 bsh {
350 1.1 bsh bus_addr_t startpa, endpa;
351 1.1 bsh vaddr_t va;
352 1.1 bsh
353 1.1 bsh #ifdef PCI_DEBUG
354 1.1 bsh printf("sspci_bs_map: t=%p, addr=%lx, size=%lx, flag=%d\n",
355 1.1 bsh t, bpa, size, flag);
356 1.1 bsh #endif
357 1.1 bsh
358 1.1 bsh /* Round the allocation to page boundries */
359 1.1 bsh startpa = trunc_page(bpa);
360 1.1 bsh endpa = round_page(bpa + size);
361 1.1 bsh
362 1.1 bsh /* Get some VM. */
363 1.11 yamt va = uvm_km_alloc(kernel_map, endpa - startpa, 0,
364 1.11 yamt UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
365 1.1 bsh if (va == 0)
366 1.1 bsh return ENOMEM;
367 1.1 bsh
368 1.1 bsh /* Store the bus space handle */
369 1.1 bsh *bshp = va + (bpa & PGOFSET);
370 1.1 bsh
371 1.1 bsh /* Now map the pages */
372 1.1 bsh /* The cookie is the physical base address for PCI I/O or memory area */
373 1.1 bsh while (startpa < endpa) {
374 1.1 bsh /* XXX pmap_kenter_pa maps pages cacheable -- not what we
375 1.1 bsh * want. */
376 1.1 bsh pmap_enter(pmap_kernel(), va, (bus_addr_t) t + startpa,
377 1.1 bsh VM_PROT_READ | VM_PROT_WRITE, 0);
378 1.3 thorpej va += PAGE_SIZE;
379 1.3 thorpej startpa += PAGE_SIZE;
380 1.1 bsh }
381 1.1 bsh pmap_update(pmap_kernel());
382 1.1 bsh
383 1.1 bsh return 0;
384 1.1 bsh }
385 1.1 bsh
386 1.1 bsh
387 1.1 bsh
388 1.1 bsh void
389 1.18 matt s3c2800_pci_conf_interrupt(void *v, int bus, int dev, int ipin, int swiz, int *iline)
390 1.1 bsh {
391 1.1 bsh #ifdef PCI_DEBUG
392 1.18 matt printf("pci_conf_interrupt(v(%p), bus(%d), dev(%d), ipin(%d), swiz(%d), *iline(%p)\n", v, bus, dev, ipin, swiz, iline);
393 1.1 bsh #endif
394 1.1 bsh if (bus == 0) {
395 1.1 bsh *iline = dev;
396 1.1 bsh } else {
397 1.1 bsh panic("pci_conf_interrupt: bus=%d: not yet implemented", bus);
398 1.1 bsh }
399 1.1 bsh }
400 1.1 bsh
401 1.1 bsh void
402 1.19 chs s3c2800_pci_attach_hook(device_t parent, device_t self,
403 1.1 bsh struct pcibus_attach_args * pba)
404 1.1 bsh {
405 1.1 bsh
406 1.1 bsh /* Nothing to do. */
407 1.1 bsh #ifdef PCI_DEBUG
408 1.1 bsh printf("s3c2800_pci_attach_hook()\n");
409 1.1 bsh #endif
410 1.1 bsh }
411 1.1 bsh
412 1.1 bsh int
413 1.1 bsh s3c2800_pci_bus_maxdevs(void *v, int busno)
414 1.1 bsh {
415 1.1 bsh
416 1.1 bsh #ifdef PCI_DEBUG
417 1.1 bsh printf("s3c2800_pci_bus_maxdevs(v=%p, busno=%d)\n", v, busno);
418 1.1 bsh #endif
419 1.1 bsh return (32);
420 1.1 bsh }
421 1.1 bsh pcitag_t
422 1.1 bsh s3c2800_pci_make_tag(void *v, int bus, int device, int function)
423 1.1 bsh {
424 1.1 bsh
425 1.1 bsh return ((bus << BUSNO_SHIFT) | (device << DEVNO_SHIFT) |
426 1.1 bsh (function << FUNNO_SHIFT));
427 1.1 bsh }
428 1.1 bsh
429 1.1 bsh void
430 1.1 bsh s3c2800_pci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
431 1.1 bsh {
432 1.1 bsh if (bp != NULL)
433 1.1 bsh *bp = (tag >> BUSNO_SHIFT) & 0xff;
434 1.1 bsh if (dp != NULL)
435 1.1 bsh *dp = (tag >> DEVNO_SHIFT) & 0x1f;
436 1.1 bsh if (fp != NULL)
437 1.1 bsh *fp = (tag >> FUNNO_SHIFT) & 0x7;
438 1.1 bsh }
439 1.1 bsh
440 1.1 bsh static vaddr_t
441 1.1 bsh make_pci_conf_va(struct sspci_softc * sc, pcitag_t tag, int offset)
442 1.1 bsh {
443 1.22 msaitoh
444 1.22 msaitoh if ((unsigned int)offset >= PCI_CONF_SIZE)
445 1.22 msaitoh return (vaddr_t) -1;
446 1.22 msaitoh
447 1.1 bsh if ((tag & BUSNO_MASK) == 0) {
448 1.1 bsh /* configuration type 0 */
449 1.1 bsh int devno = tag_to_devno(tag);
450 1.1 bsh
451 1.1 bsh if (devno < BUS0_DEV_MIN || BUS0_DEV_MAX < devno)
452 1.1 bsh return 0;
453 1.1 bsh
454 1.1 bsh return (vaddr_t) bus_space_vaddr(sc->sc_iot, sc->sc_conf0_ioh) +
455 1.1 bsh (tag & (DEVNO_MASK | FUNNO_MASK)) + offset;
456 1.1 bsh } else {
457 1.1 bsh /* XXX */
458 1.1 bsh return (vaddr_t) - 1; /* cause fault */
459 1.1 bsh }
460 1.1 bsh }
461 1.1 bsh
462 1.1 bsh
463 1.1 bsh pcireg_t
464 1.1 bsh s3c2800_pci_conf_read(void *v, pcitag_t tag, int offset)
465 1.1 bsh {
466 1.1 bsh struct sspci_softc *sc = v;
467 1.1 bsh vaddr_t va = make_pci_conf_va(sc, tag, offset);
468 1.1 bsh int s;
469 1.1 bsh pcireg_t rv;
470 1.1 bsh
471 1.1 bsh #ifdef PCI_DEBUG
472 1.1 bsh printf("s3c2800_pci_conf_read: base=%lx tag=%lx offset=%x\n",
473 1.1 bsh sc->sc_conf0_ioh, tag, offset);
474 1.1 bsh #endif
475 1.1 bsh if (va == 0)
476 1.1 bsh return -1;
477 1.1 bsh
478 1.1 bsh PCI_CONF_LOCK(s);
479 1.1 bsh
480 1.1 bsh if (badaddr_read((void *) va, sizeof(rv), &rv)) {
481 1.1 bsh #if PCI_DEBUG
482 1.1 bsh printf("conf_read: %lx bad address\n", va);
483 1.1 bsh #endif
484 1.1 bsh rv = (pcireg_t) - 1;
485 1.1 bsh }
486 1.1 bsh PCI_CONF_UNLOCK(s);
487 1.1 bsh
488 1.1 bsh return rv;
489 1.1 bsh }
490 1.1 bsh
491 1.1 bsh void
492 1.1 bsh s3c2800_pci_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val)
493 1.1 bsh {
494 1.1 bsh struct sspci_softc *sc = v;
495 1.1 bsh vaddr_t va = make_pci_conf_va(sc, tag, offset);
496 1.1 bsh u_int s;
497 1.1 bsh
498 1.1 bsh #ifdef PCI_DEBUG
499 1.1 bsh printf("s3c2800_pci_conf_write: tag=%lx offset=%x -> va=%lx\n", tag, offset, va);
500 1.1 bsh #endif
501 1.1 bsh
502 1.1 bsh PCI_CONF_LOCK(s);
503 1.1 bsh
504 1.1 bsh *(pcireg_t *) va = val;
505 1.1 bsh
506 1.1 bsh PCI_CONF_UNLOCK(s);
507 1.1 bsh }
508 1.1 bsh
509 1.1 bsh void *
510 1.1 bsh s3c2800_pci_intr_establish(void *pcv, pci_intr_handle_t ih, int level,
511 1.25 jmcneill int (*func) (void *), void *arg, const char *xname)
512 1.1 bsh {
513 1.1 bsh struct sspci_softc *sc = pcv;
514 1.1 bsh struct sspci_irq_handler *handler;
515 1.1 bsh int s;
516 1.1 bsh
517 1.1 bsh #ifdef PCI_DEBUG
518 1.1 bsh printf("s3c2800_pci_intr_establish(pcv=%p, ih=0x%lx, level=%d, "
519 1.25 jmcneill "func=%p, arg=%p, xname=%s)\n", pcv, ih, level, func, arg, xname);
520 1.1 bsh #endif
521 1.1 bsh
522 1.1 bsh handler = malloc(sizeof *handler, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
523 1.1 bsh if (handler == NULL)
524 1.1 bsh panic("sspci_intr_establish: can't malloc handler info");
525 1.1 bsh
526 1.1 bsh handler->func = func;
527 1.1 bsh handler->arg = arg;
528 1.1 bsh handler->level = level;
529 1.1 bsh
530 1.1 bsh s = splhigh();
531 1.1 bsh SLIST_INSERT_HEAD(&sc->sc_irq_handlers, handler, link);
532 1.1 bsh splx(s);
533 1.1 bsh
534 1.1 bsh return (handler);
535 1.1 bsh }
536 1.1 bsh
537 1.1 bsh void
538 1.1 bsh s3c2800_pci_intr_disestablish(void *pcv, void *cookie)
539 1.1 bsh {
540 1.1 bsh struct sspci_softc *sc = pcv;
541 1.1 bsh struct sspci_irq_handler *ih = cookie;
542 1.1 bsh int s;
543 1.1 bsh
544 1.1 bsh #ifdef PCI_DEBUG
545 1.1 bsh printf("s3c2800_pci_intr_disestablish(pcv=%p, cookie=%p)\n",
546 1.1 bsh pcv, cookie);
547 1.1 bsh #endif
548 1.1 bsh
549 1.1 bsh s = splhigh();
550 1.1 bsh SLIST_REMOVE(&sc->sc_irq_handlers, ih, sspci_irq_handler, link);
551 1.1 bsh splx(s);
552 1.1 bsh }
553 1.1 bsh
554 1.1 bsh int
555 1.14 dyoung s3c2800_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
556 1.1 bsh {
557 1.1 bsh #ifdef PCI_DEBUG
558 1.1 bsh int pin = pa->pa_intrpin;
559 1.1 bsh void *pcv = pa->pa_pc;
560 1.1 bsh pcitag_t intrtag = pa->pa_intrtag;
561 1.1 bsh int bus, device, function;
562 1.1 bsh
563 1.1 bsh s3c2800_pci_decompose_tag(pcv, intrtag, &bus, &device, &function);
564 1.1 bsh printf("s3c2800_pci_intr_map: pcv=%p, tag=%08lx pin=%d dev=%d\n",
565 1.1 bsh pcv, intrtag, pin, device);
566 1.1 bsh #endif
567 1.1 bsh
568 1.1 bsh
569 1.1 bsh /* S3C2800 has only one interrupt line for PCI */
570 1.1 bsh *ihp = 0;
571 1.1 bsh return 0;
572 1.1 bsh }
573 1.1 bsh
574 1.1 bsh const char *
575 1.21 christos s3c2800_pci_intr_string(void *pcv, pci_intr_handle_t ih, char *buf, size_t len)
576 1.1 bsh {
577 1.1 bsh /* We have only one interrupt source from PCI */
578 1.21 christos strlcpy(buf, "pciint", len);
579 1.21 christos return buf;
580 1.1 bsh }
581 1.1 bsh
582 1.1 bsh const struct evcnt *
583 1.1 bsh s3c2800_pci_intr_evcnt(void *pcv, pci_intr_handle_t ih)
584 1.1 bsh {
585 1.1 bsh
586 1.1 bsh /* XXX for now, no evcnt parent reported */
587 1.1 bsh return NULL;
588 1.1 bsh }
589 1.1 bsh /*
590 1.1 bsh * Initialize PCI controller
591 1.1 bsh */
592 1.1 bsh int
593 1.1 bsh sspci_init_controller(struct sspci_softc * sc)
594 1.1 bsh {
595 1.1 bsh bus_space_tag_t iot = sc->sc_iot;
596 1.1 bsh bus_space_handle_t ioh = sc->sc_reg_ioh;
597 1.1 bsh
598 1.1 bsh /* disable PCI command */
599 1.1 bsh bus_space_write_4(iot, ioh, PCI_COMMAND_STATUS_REG,
600 1.1 bsh 0xffff0000);
601 1.1 bsh
602 1.1 bsh /* latency=0x10, cacheline=8 */
603 1.1 bsh bus_space_write_4(iot, ioh, PCI_BHLC_REG,
604 1.1 bsh PCI_BHLC_CODE(0, 0, 0, 0x10, 8));
605 1.1 bsh
606 1.1 bsh bus_space_write_4(iot, ioh, PCI_INTERRUPT_REG,
607 1.1 bsh PCI_INTERRUPT_CODE(0, 0, 0, 0));
608 1.1 bsh
609 1.1 bsh
610 1.1 bsh
611 1.1 bsh #if 1
612 1.1 bsh bus_space_write_4(iot, ioh, PCI_MAPREG_START,
613 1.1 bsh PCI_MAPREG_MEM_TYPE_32BIT | 0x80000000);
614 1.1 bsh /* Cover all DBANKs with BAR0 */
615 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBAM0, 0xf8000000);
616 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBATPA0, S3C2800_DBANK0_START);
617 1.1 bsh #else
618 1.1 bsh bus_space_write_4(iot, ioh, PCI_MAPREG_START,
619 1.1 bsh PCI_MAPREG_MEM_TYPE_32BIT | 0xf0000000);
620 1.1 bsh bus_space_write_4(iot, ioh, PCI_MAPREG_START + 4,
621 1.1 bsh PCI_MAPREG_MEM_TYPE_32BIT | 0x80000000);
622 1.1 bsh
623 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBAM0, 0xffff0000);
624 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBATPA0, 0xffff0000);
625 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBAM1, 0xf1000000);
626 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIBATPA1, S3C2800_DBANK0_START);
627 1.1 bsh #endif
628 1.1 bsh
629 1.1 bsh bus_space_write_4(iot, ioh, PCI_COMMAND_STATUS_REG,
630 1.1 bsh PCI_STATUS_PARITY_DETECT |
631 1.1 bsh PCI_STATUS_SPECIAL_ERROR |
632 1.1 bsh PCI_STATUS_MASTER_ABORT |
633 1.1 bsh PCI_STATUS_MASTER_TARGET_ABORT |
634 1.1 bsh PCI_STATUS_TARGET_TARGET_ABORT |
635 1.1 bsh PCI_STATUS_DEVSEL_MEDIUM |
636 1.1 bsh PCI_STATUS_PARITY_ERROR |
637 1.1 bsh PCI_STATUS_BACKTOBACK_SUPPORT |
638 1.1 bsh PCI_STATUS_CAPLIST_SUPPORT |
639 1.1 bsh PCI_COMMAND_MASTER_ENABLE |
640 1.1 bsh PCI_COMMAND_MEM_ENABLE |
641 1.1 bsh PCI_COMMAND_IO_ENABLE);
642 1.1 bsh
643 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCICON,
644 1.1 bsh PCICON_ARB | PCICON_HST);
645 1.1 bsh
646 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCISET, 0);
647 1.1 bsh /* clear all interrupts */
648 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIINTST, 0xffffffff);
649 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIINTEN, 0);
650 1.1 bsh
651 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCICON,
652 1.1 bsh PCICON_RDY | PCICON_CFD | PCICON_ATS |
653 1.1 bsh PCICON_ARB | PCICON_HST);
654 1.1 bsh
655 1.1 bsh
656 1.1 bsh #ifdef PCI_DEBUG
657 1.1 bsh {
658 1.1 bsh pcireg_t reg;
659 1.1 bsh int i;
660 1.1 bsh
661 1.1 bsh for (i = 0; i <= 0x40; i += sizeof(pcireg_t)) {
662 1.1 bsh reg = bus_space_read_4(iot, ioh, i);
663 1.1 bsh printf("%03x: %08x\n", i, reg);
664 1.1 bsh }
665 1.1 bsh for (i = 0x100; i <= 0x154; i += sizeof(pcireg_t)) {
666 1.1 bsh reg = bus_space_read_4(iot, ioh, i);
667 1.1 bsh printf("%03x: %08x\n", i, reg);
668 1.1 bsh }
669 1.1 bsh }
670 1.1 bsh #endif
671 1.1 bsh return 0;
672 1.1 bsh }
673 1.1 bsh
674 1.1 bsh
675 1.1 bsh static const char *pci_abnormal_error_name[] = {
676 1.1 bsh "PCI reset deasserted",
677 1.1 bsh "PCI reset asserted",
678 1.1 bsh "PCI master detected fatal error",
679 1.1 bsh "PCI master detected parity error",
680 1.1 bsh "PCI target detected parity error",
681 1.1 bsh "PCI SERR# asserted",
682 1.1 bsh };
683 1.1 bsh
684 1.1 bsh static int
685 1.1 bsh sspci_intr(void *arg)
686 1.1 bsh {
687 1.1 bsh struct sspci_softc *sc = arg;
688 1.1 bsh int s;
689 1.1 bsh bus_space_tag_t iot = sc->sc_iot;
690 1.1 bsh bus_space_handle_t ioh = sc->sc_reg_ioh;
691 1.1 bsh uint32_t interrupts, errors;
692 1.1 bsh
693 1.1 bsh interrupts = bus_space_read_4(iot, ioh, PCICTL_PCIINTST);
694 1.1 bsh
695 1.1 bsh if (interrupts & PCIINT_INA) {
696 1.1 bsh s = splhigh();
697 1.13 matt softint_schedule(sc->sc_softinterrupt);
698 1.1 bsh
699 1.1 bsh /* mask INTA itnerrupt until softinterrupt is handled */
700 1.1 bsh sc->sc_pciinten &= ~PCIINT_INA;
701 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIINTEN,
702 1.1 bsh sc->sc_pciinten);
703 1.1 bsh
704 1.1 bsh /* acknowledge INTA interrupt */
705 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIINTST, PCIINT_INA);
706 1.1 bsh
707 1.1 bsh splx(s);
708 1.1 bsh
709 1.1 bsh interrupts &= ~PCIINT_INA;
710 1.1 bsh
711 1.1 bsh }
712 1.1 bsh errors = interrupts & (PCIINT_SER | PCIINT_TPE | PCIINT_MPE |
713 1.1 bsh PCIINT_MFE | PCIINT_PRA | PCIINT_PRD);
714 1.1 bsh if (errors) {
715 1.1 bsh int i;
716 1.1 bsh
717 1.1 bsh for (i = 0; errors; ++i) {
718 1.1 bsh if ((errors & (1 << i)) == 0)
719 1.1 bsh continue;
720 1.1 bsh
721 1.19 chs printf("%s: %s\n", device_xname(sc->sc_dev),
722 1.1 bsh pci_abnormal_error_name[i > 4 ? 5 : i]);
723 1.1 bsh
724 1.1 bsh errors &= ~(1 << i);
725 1.1 bsh }
726 1.1 bsh /* acknowledge interrupts */
727 1.1 bsh bus_space_write_4(iot, ioh, PCICTL_PCIINTST, interrupts);
728 1.1 bsh }
729 1.1 bsh return 0;
730 1.1 bsh }
731 1.1 bsh
732 1.1 bsh static void
733 1.1 bsh sspci_softintr(void *arg)
734 1.1 bsh {
735 1.1 bsh struct sspci_softc *sc = arg;
736 1.1 bsh struct sspci_irq_handler *ih;
737 1.1 bsh int s;
738 1.1 bsh
739 1.1 bsh
740 1.1 bsh SLIST_FOREACH(ih, &(sc->sc_irq_handlers), link) {
741 1.1 bsh s = _splraise(ih->level);
742 1.1 bsh ih->func(ih->arg);
743 1.1 bsh splx(s);
744 1.1 bsh }
745 1.1 bsh
746 1.1 bsh /* unmask INTA interrupt */
747 1.1 bsh s = splhigh();
748 1.1 bsh sc->sc_pciinten |= PCIINT_INA;
749 1.1 bsh bus_space_write_4(sc->sc_iot, sc->sc_reg_ioh, PCICTL_PCIINTEN,
750 1.1 bsh sc->sc_pciinten);
751 1.1 bsh splx(s);
752 1.1 bsh }
753