xref: /openbsd/sys/dev/fdt/bcm2711_pcie.c (revision 2ee472d0)
1 /*	$OpenBSD: bcm2711_pcie.c,v 1.13 2024/03/27 15:15:00 patrick Exp $	*/
2 /*
3  * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/extent.h>
22 #include <sys/malloc.h>
23 
24 #include <machine/intr.h>
25 #include <machine/bus.h>
26 #include <machine/fdt.h>
27 #include <machine/simplebusvar.h>
28 
29 #include <dev/pci/pcidevs.h>
30 #include <dev/pci/pcireg.h>
31 #include <dev/pci/pcivar.h>
32 #include <dev/pci/ppbreg.h>
33 
34 #include <dev/ofw/openfirm.h>
35 #include <dev/ofw/fdt.h>
36 
37 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO		0x400c
38 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI		0x4010
39 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT	0x4070
40 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI		0x4080
41 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI		0x4084
42 #define PCIE_EXT_CFG_DATA				0x8000
43 #define PCIE_EXT_CFG_INDEX				0x9000
44 #define PCIE_RGR1_SW_INIT_1				0x9210
45 #define  PCIE_RGR1_SW_INIT_1_PERST_MASK			(1 << 0)
46 #define  PCIE_RGR1_SW_INIT_1_INIT_MASK			(1 << 1)
47 
48 #define HREAD4(sc, reg)							\
49 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
50 #define HWRITE4(sc, reg, val)						\
51 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
52 
53 struct bcmpcie_range {
54 	uint32_t		flags;
55 	uint64_t		pci_base;
56 	uint64_t		phys_base;
57 	uint64_t		size;
58 };
59 
60 struct bcmpcie_softc {
61 	struct simplebus_softc	sc_sbus;
62 	bus_space_tag_t		sc_iot;
63 	bus_space_handle_t	sc_ioh;
64 	bus_dma_tag_t		sc_dmat;
65 
66 	int			sc_node;
67 	int			sc_acells;
68 	int			sc_scells;
69 	int			sc_pacells;
70 	int			sc_pscells;
71 	struct bcmpcie_range	*sc_ranges;
72 	int			sc_nranges;
73 	struct bcmpcie_range	*sc_dmaranges;
74 	int			sc_ndmaranges;
75 
76 	struct bus_space	sc_bus_iot;
77 	struct bus_space	sc_bus_memt;
78 
79 	struct machine_bus_dma_tag sc_dma;
80 
81 	struct machine_pci_chipset sc_pc;
82 	int			sc_bus;
83 };
84 
85 int bcmpcie_match(struct device *, void *, void *);
86 void bcmpcie_attach(struct device *, struct device *, void *);
87 
88 const struct cfattach bcmpcie_ca = {
89 	sizeof (struct bcmpcie_softc), bcmpcie_match, bcmpcie_attach
90 };
91 
92 struct cfdriver bcmpcie_cd = {
93 	NULL, "bcmpcie", DV_DULL
94 };
95 
96 int
bcmpcie_match(struct device * parent,void * match,void * aux)97 bcmpcie_match(struct device *parent, void *match, void *aux)
98 {
99 	struct fdt_attach_args *faa = aux;
100 
101 	return OF_is_compatible(faa->fa_node, "brcm,bcm2711-pcie") ||
102 	    OF_is_compatible(faa->fa_node, "brcm,bcm2712-pcie");
103 }
104 
105 int	bcmpcie_submatch(struct device *, void *, void *);
106 void	bcmpcie_attach_hook(struct device *, struct device *,
107 	    struct pcibus_attach_args *);
108 int	bcmpcie_bus_maxdevs(void *, int);
109 pcitag_t bcmpcie_make_tag(void *, int, int, int);
110 void	bcmpcie_decompose_tag(void *, pcitag_t, int *, int *, int *);
111 int	bcmpcie_conf_size(void *, pcitag_t);
112 pcireg_t bcmpcie_conf_read(void *, pcitag_t, int);
113 void	bcmpcie_conf_write(void *, pcitag_t, int, pcireg_t);
114 int	bcmpcie_probe_device_hook(void *, struct pci_attach_args *);
115 
116 int	bcmpcie_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
117 const char *bcmpcie_intr_string(void *, pci_intr_handle_t);
118 void	*bcmpcie_intr_establish(void *, pci_intr_handle_t, int,
119 	    struct cpu_info *, int (*)(void *), void *, char *);
120 void	bcmpcie_intr_disestablish(void *, void *);
121 
122 int	bcmpcie_bs_iomap(bus_space_tag_t, bus_addr_t, bus_size_t, int,
123 	    bus_space_handle_t *);
124 int	bcmpcie_bs_memmap(bus_space_tag_t, bus_addr_t, bus_size_t, int,
125 	    bus_space_handle_t *);
126 int	bcmpcie_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *,
127 	    bus_size_t, struct proc *, int, paddr_t *, int *, int);
128 int	bcmpcie_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
129 	    bus_dma_segment_t *, int, bus_size_t, int);
130 
131 void
bcmpcie_attach(struct device * parent,struct device * self,void * aux)132 bcmpcie_attach(struct device *parent, struct device *self, void *aux)
133 {
134 	struct bcmpcie_softc *sc = (struct bcmpcie_softc *)self;
135 	struct fdt_attach_args *faa = aux;
136 	struct pcibus_attach_args pba;
137 	uint32_t *ranges;
138 	int i, j, nranges, rangeslen;
139 	uint32_t reg;
140 
141 	if (faa->fa_nreg < 1) {
142 		printf(": no registers\n");
143 		return;
144 	}
145 
146 	sc->sc_iot = faa->fa_iot;
147 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
148 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
149 		printf(": can't map registers\n");
150 		return;
151 	}
152 
153 	reg = HREAD4(sc, PCIE_RGR1_SW_INIT_1);
154 	if (reg & PCIE_RGR1_SW_INIT_1_INIT_MASK) {
155 		printf(": disabled\n");
156 		return;
157 	}
158 
159 	sc->sc_node = faa->fa_node;
160 	sc->sc_dmat = faa->fa_dmat;
161 
162 	sc->sc_acells = OF_getpropint(sc->sc_node, "#address-cells",
163 	    faa->fa_acells);
164 	sc->sc_scells = OF_getpropint(sc->sc_node, "#size-cells",
165 	    faa->fa_scells);
166 	sc->sc_pacells = faa->fa_acells;
167 	sc->sc_pscells = faa->fa_scells;
168 
169 	/* Memory and IO space translations. */
170 	rangeslen = OF_getproplen(sc->sc_node, "ranges");
171 	if (rangeslen <= 0 || (rangeslen % sizeof(uint32_t)) ||
172 	     (rangeslen / sizeof(uint32_t)) % (sc->sc_acells +
173 	     sc->sc_pacells + sc->sc_scells)) {
174 		printf(": invalid ranges property\n");
175 		return;
176 	}
177 
178 	ranges = malloc(rangeslen, M_TEMP, M_WAITOK);
179 	OF_getpropintarray(sc->sc_node, "ranges", ranges,
180 	    rangeslen);
181 
182 	nranges = (rangeslen / sizeof(uint32_t)) /
183 	    (sc->sc_acells + sc->sc_pacells + sc->sc_scells);
184 	sc->sc_ranges = mallocarray(nranges,
185 	    sizeof(struct bcmpcie_range), M_DEVBUF, M_WAITOK);
186 	sc->sc_nranges = nranges;
187 
188 	for (i = 0, j = 0; i < sc->sc_nranges; i++) {
189 		sc->sc_ranges[i].flags = ranges[j++];
190 		sc->sc_ranges[i].pci_base = ranges[j++];
191 		if (sc->sc_acells - 1 == 2) {
192 			sc->sc_ranges[i].pci_base <<= 32;
193 			sc->sc_ranges[i].pci_base |= ranges[j++];
194 		}
195 		sc->sc_ranges[i].phys_base = ranges[j++];
196 		if (sc->sc_pacells == 2) {
197 			sc->sc_ranges[i].phys_base <<= 32;
198 			sc->sc_ranges[i].phys_base |= ranges[j++];
199 		}
200 		sc->sc_ranges[i].size = ranges[j++];
201 		if (sc->sc_scells == 2) {
202 			sc->sc_ranges[i].size <<= 32;
203 			sc->sc_ranges[i].size |= ranges[j++];
204 		}
205 	}
206 
207 	free(ranges, M_TEMP, rangeslen);
208 
209 	/* DMA translations */
210 	rangeslen = OF_getproplen(sc->sc_node, "dma-ranges");
211 	if (rangeslen > 0) {
212 		if ((rangeslen % sizeof(uint32_t)) ||
213 		     (rangeslen / sizeof(uint32_t)) % (sc->sc_acells +
214 		     sc->sc_pacells + sc->sc_scells)) {
215 			printf(": invalid dma-ranges property\n");
216 			free(sc->sc_ranges, M_DEVBUF,
217 			    sc->sc_nranges * sizeof(struct bcmpcie_range));
218 			return;
219 		}
220 
221 		ranges = malloc(rangeslen, M_TEMP, M_WAITOK);
222 		OF_getpropintarray(sc->sc_node, "dma-ranges", ranges,
223 		    rangeslen);
224 
225 		nranges = (rangeslen / sizeof(uint32_t)) /
226 		    (sc->sc_acells + sc->sc_pacells + sc->sc_scells);
227 		sc->sc_dmaranges = mallocarray(nranges,
228 		    sizeof(struct bcmpcie_range), M_DEVBUF, M_WAITOK);
229 		sc->sc_ndmaranges = nranges;
230 
231 		for (i = 0, j = 0; i < sc->sc_ndmaranges; i++) {
232 			sc->sc_dmaranges[i].flags = ranges[j++];
233 			sc->sc_dmaranges[i].pci_base = ranges[j++];
234 			if (sc->sc_acells - 1 == 2) {
235 				sc->sc_dmaranges[i].pci_base <<= 32;
236 				sc->sc_dmaranges[i].pci_base |= ranges[j++];
237 			}
238 			sc->sc_dmaranges[i].phys_base = ranges[j++];
239 			if (sc->sc_pacells == 2) {
240 				sc->sc_dmaranges[i].phys_base <<= 32;
241 				sc->sc_dmaranges[i].phys_base |= ranges[j++];
242 			}
243 			sc->sc_dmaranges[i].size = ranges[j++];
244 			if (sc->sc_scells == 2) {
245 				sc->sc_dmaranges[i].size <<= 32;
246 				sc->sc_dmaranges[i].size |= ranges[j++];
247 			}
248 		}
249 
250 		free(ranges, M_TEMP, rangeslen);
251 	}
252 
253 	/*
254 	 * Reprogram the outbound window to match the configuration in
255 	 * the device tree.  This is necessary since the EDK2-based
256 	 * UEFI firmware reprograms the window.
257 	 */
258 	for (i = 0; i < sc->sc_nranges; i++) {
259 		if ((sc->sc_ranges[i].flags & 0x03000000) == 0x02000000) {
260 			uint64_t cpu_base = sc->sc_ranges[i].phys_base;
261 			uint64_t cpu_limit = sc->sc_ranges[i].phys_base +
262 			    sc->sc_ranges[i].size - 1;
263 
264 			HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO,
265 			    sc->sc_ranges[i].pci_base);
266 			HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI,
267 			    sc->sc_ranges[i].pci_base >> 32);
268 			HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT,
269 			    (cpu_base & PPB_MEM_MASK) >> PPB_MEM_SHIFT |
270 			    (cpu_limit & PPB_MEM_MASK));
271 			HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI,
272 			    cpu_base >> 32);
273 			HWRITE4(sc, PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI,
274 			    cpu_limit >> 32);
275 		}
276 	}
277 
278 	memcpy(&sc->sc_bus_iot, sc->sc_iot, sizeof(sc->sc_bus_iot));
279 	sc->sc_bus_iot.bus_private = sc;
280 	sc->sc_bus_iot._space_map = bcmpcie_bs_iomap;
281 	memcpy(&sc->sc_bus_memt, sc->sc_iot, sizeof(sc->sc_bus_memt));
282 	sc->sc_bus_memt.bus_private = sc;
283 	sc->sc_bus_memt._space_map = bcmpcie_bs_memmap;
284 
285 	memcpy(&sc->sc_dma, sc->sc_dmat, sizeof(sc->sc_dma));
286 	sc->sc_dma._dmamap_load_buffer = bcmpcie_dmamap_load_buffer;
287 	sc->sc_dma._dmamap_load_raw = bcmpcie_dmamap_load_raw;
288 	sc->sc_dma._cookie = sc;
289 
290 	sc->sc_pc.pc_conf_v = sc;
291 	sc->sc_pc.pc_attach_hook = bcmpcie_attach_hook;
292 	sc->sc_pc.pc_bus_maxdevs = bcmpcie_bus_maxdevs;
293 	sc->sc_pc.pc_make_tag = bcmpcie_make_tag;
294 	sc->sc_pc.pc_decompose_tag = bcmpcie_decompose_tag;
295 	sc->sc_pc.pc_conf_size = bcmpcie_conf_size;
296 	sc->sc_pc.pc_conf_read = bcmpcie_conf_read;
297 	sc->sc_pc.pc_conf_write = bcmpcie_conf_write;
298 	sc->sc_pc.pc_probe_device_hook = bcmpcie_probe_device_hook;
299 
300 	sc->sc_pc.pc_intr_v = sc;
301 	sc->sc_pc.pc_intr_map = bcmpcie_intr_map;
302 	sc->sc_pc.pc_intr_map_msi = _pci_intr_map_msi;
303 	sc->sc_pc.pc_intr_map_msivec = _pci_intr_map_msivec;
304 	sc->sc_pc.pc_intr_map_msix = _pci_intr_map_msix;
305 	sc->sc_pc.pc_intr_string = bcmpcie_intr_string;
306 	sc->sc_pc.pc_intr_establish = bcmpcie_intr_establish;
307 	sc->sc_pc.pc_intr_disestablish = bcmpcie_intr_disestablish;
308 
309 	memset(&pba, 0, sizeof(pba));
310 	pba.pba_busname = "pci";
311 	pba.pba_iot = &sc->sc_bus_iot;
312 	pba.pba_memt = &sc->sc_bus_memt;
313 	pba.pba_dmat = &sc->sc_dma;
314 	pba.pba_pc = &sc->sc_pc;
315 	pba.pba_domain = pci_ndomains++;
316 	pba.pba_bus = 0;
317 
318 	/* Attach device tree nodes enumerating PCIe bus */
319 	simplebus_attach(parent, &sc->sc_sbus.sc_dev, faa);
320 
321 	config_found_sm(self, &pba, NULL, bcmpcie_submatch);
322 }
323 
324 int
bcmpcie_submatch(struct device * self,void * match,void * aux)325 bcmpcie_submatch(struct device *self, void *match, void *aux)
326 {
327 	struct cfdata *cf = match;
328 	struct pcibus_attach_args *pba = aux;
329 
330 	if (strcmp(pba->pba_busname, cf->cf_driver->cd_name) != 0)
331 		return 0;
332 
333 	return (*cf->cf_attach->ca_match)(self, match, aux);
334 }
335 
336 void
bcmpcie_attach_hook(struct device * parent,struct device * self,struct pcibus_attach_args * pba)337 bcmpcie_attach_hook(struct device *parent, struct device *self,
338     struct pcibus_attach_args *pba)
339 {
340 }
341 
342 int
bcmpcie_bus_maxdevs(void * v,int bus)343 bcmpcie_bus_maxdevs(void *v, int bus)
344 {
345 	struct bcmpcie_softc *sc = v;
346 
347 	if (bus == sc->sc_bus || bus == sc->sc_bus + 1)
348 		return 1;
349 	return 32;
350 }
351 
352 pcitag_t
bcmpcie_make_tag(void * v,int bus,int device,int function)353 bcmpcie_make_tag(void *v, int bus, int device, int function)
354 {
355 	/* Return ECAM address. */
356 	return ((bus << 20) | (device << 15) | (function << 12));
357 }
358 
359 void
bcmpcie_decompose_tag(void * v,pcitag_t tag,int * bp,int * dp,int * fp)360 bcmpcie_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
361 {
362 	if (bp != NULL)
363 		*bp = (tag >> 20) & 0xff;
364 	if (dp != NULL)
365 		*dp = (tag >> 15) & 0x1f;
366 	if (fp != NULL)
367 		*fp = (tag >> 12) & 0x7;
368 }
369 
370 int
bcmpcie_conf_size(void * v,pcitag_t tag)371 bcmpcie_conf_size(void *v, pcitag_t tag)
372 {
373 	return PCIE_CONFIG_SPACE_SIZE;
374 }
375 
376 pcireg_t
bcmpcie_conf_read(void * v,pcitag_t tag,int reg)377 bcmpcie_conf_read(void *v, pcitag_t tag, int reg)
378 {
379 	struct bcmpcie_softc *sc = v;
380 	int bus, dev, fn;
381 
382 	bcmpcie_decompose_tag(sc, tag, &bus, &dev, &fn);
383 	if (bus == 0) {
384 		KASSERT(dev == 0);
385 		return HREAD4(sc, tag | reg);
386 	}
387 
388 	HWRITE4(sc, PCIE_EXT_CFG_INDEX, tag);
389 	return HREAD4(sc, PCIE_EXT_CFG_DATA + reg);
390 }
391 
392 void
bcmpcie_conf_write(void * v,pcitag_t tag,int reg,pcireg_t data)393 bcmpcie_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
394 {
395 	struct bcmpcie_softc *sc = v;
396 	int bus, dev, fn;
397 
398 	bcmpcie_decompose_tag(sc, tag, &bus, &dev, &fn);
399 	if (bus == 0) {
400 		KASSERT(dev == 0);
401 		HWRITE4(sc, tag | reg, data);
402 		return;
403 	}
404 
405 	HWRITE4(sc, PCIE_EXT_CFG_INDEX, tag);
406 	HWRITE4(sc, PCIE_EXT_CFG_DATA + reg, data);
407 }
408 
409 int
bcmpcie_probe_device_hook(void * v,struct pci_attach_args * pa)410 bcmpcie_probe_device_hook(void *v, struct pci_attach_args *pa)
411 {
412 	return 0;
413 }
414 
415 int
bcmpcie_intr_map(struct pci_attach_args * pa,pci_intr_handle_t * ihp)416 bcmpcie_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
417 {
418 	int pin = pa->pa_rawintrpin;
419 
420 	if (pin == 0 || pin > PCI_INTERRUPT_PIN_MAX)
421 		return -1;
422 
423 	if (pa->pa_tag == 0)
424 		return -1;
425 
426 	ihp->ih_pc = pa->pa_pc;
427 	ihp->ih_tag = pa->pa_intrtag;
428 	ihp->ih_intrpin = pa->pa_intrpin;
429 	ihp->ih_type = PCI_INTX;
430 
431 	return 0;
432 }
433 
434 const char *
bcmpcie_intr_string(void * v,pci_intr_handle_t ih)435 bcmpcie_intr_string(void *v, pci_intr_handle_t ih)
436 {
437 	switch (ih.ih_type) {
438 	case PCI_MSI:
439 		return "msi";
440 	case PCI_MSIX:
441 		return "msix";
442 	}
443 
444 	return "intx";
445 }
446 
447 void *
bcmpcie_intr_establish(void * v,pci_intr_handle_t ih,int level,struct cpu_info * ci,int (* func)(void *),void * arg,char * name)448 bcmpcie_intr_establish(void *v, pci_intr_handle_t ih, int level,
449     struct cpu_info *ci, int (*func)(void *), void *arg, char *name)
450 {
451 	struct bcmpcie_softc *sc = v;
452 	int bus, dev, fn;
453 	uint32_t reg[4];
454 
455 	KASSERT(ih.ih_type == PCI_INTX);
456 	bcmpcie_decompose_tag(sc, ih.ih_tag, &bus, &dev, &fn);
457 
458 	reg[0] = bus << 16 | dev << 11 | fn << 8;
459 	reg[1] = reg[2] = 0;
460 	reg[3] = ih.ih_intrpin;
461 
462 	return fdt_intr_establish_imap_cpu(sc->sc_node, reg, sizeof(reg),
463 	    level, ci, func, arg, name);
464 }
465 
466 void
bcmpcie_intr_disestablish(void * v,void * cookie)467 bcmpcie_intr_disestablish(void *v, void *cookie)
468 {
469 }
470 
471 int
bcmpcie_bs_iomap(bus_space_tag_t t,bus_addr_t addr,bus_size_t size,int flags,bus_space_handle_t * bshp)472 bcmpcie_bs_iomap(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
473     int flags, bus_space_handle_t *bshp)
474 {
475 	struct bcmpcie_softc *sc = t->bus_private;
476 	int i;
477 
478 	for (i = 0; i < sc->sc_nranges; i++) {
479 		uint64_t pci_start = sc->sc_ranges[i].pci_base;
480 		uint64_t pci_end = pci_start + sc->sc_ranges[i].size;
481 		uint64_t phys_start = sc->sc_ranges[i].phys_base;
482 
483 		if ((sc->sc_ranges[i].flags & 0x03000000) == 0x01000000 &&
484 		    addr >= pci_start && addr + size <= pci_end) {
485 			return bus_space_map(sc->sc_iot,
486 			    addr - pci_start + phys_start, size, flags, bshp);
487 		}
488 	}
489 
490 	return ENXIO;
491 }
492 
493 int
bcmpcie_bs_memmap(bus_space_tag_t t,bus_addr_t addr,bus_size_t size,int flags,bus_space_handle_t * bshp)494 bcmpcie_bs_memmap(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
495     int flags, bus_space_handle_t *bshp)
496 {
497 	struct bcmpcie_softc *sc = t->bus_private;
498 	int i;
499 
500 	for (i = 0; i < sc->sc_nranges; i++) {
501 		uint64_t pci_start = sc->sc_ranges[i].pci_base;
502 		uint64_t pci_end = pci_start + sc->sc_ranges[i].size;
503 		uint64_t phys_start = sc->sc_ranges[i].phys_base;
504 
505 		if ((sc->sc_ranges[i].flags & 0x03000000) == 0x02000000 &&
506 		    addr >= pci_start && addr + size <= pci_end) {
507 			return bus_space_map(sc->sc_iot,
508 			    addr - pci_start + phys_start, size, flags, bshp);
509 		}
510 	}
511 
512 	return ENXIO;
513 }
514 
515 int
bcmpcie_dmamap_load_buffer(bus_dma_tag_t t,bus_dmamap_t map,void * buf,bus_size_t buflen,struct proc * p,int flags,paddr_t * lastaddrp,int * segp,int first)516 bcmpcie_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
517     bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp,
518     int *segp, int first)
519 {
520 	struct bcmpcie_softc *sc = t->_cookie;
521 	int seg, firstseg = *segp;
522 	int error;
523 
524 	error = sc->sc_dmat->_dmamap_load_buffer(sc->sc_dmat, map, buf, buflen,
525 	    p, flags, lastaddrp, segp, first);
526 	if (error)
527 		return error;
528 
529 	if (sc->sc_dmaranges == NULL)
530 		return 0;
531 
532 	/* For each segment. */
533 	for (seg = firstseg; seg <= *segp; seg++) {
534 		uint64_t addr = map->dm_segs[seg].ds_addr;
535 		uint64_t size = map->dm_segs[seg].ds_len;
536 		int i;
537 
538 		/* For each range. */
539 		for (i = 0; i < sc->sc_ndmaranges; i++) {
540 			uint64_t pci_start = sc->sc_dmaranges[i].pci_base;
541 			uint64_t phys_start = sc->sc_dmaranges[i].phys_base;
542 			uint64_t phys_end = phys_start +
543 			    sc->sc_dmaranges[i].size;
544 
545 			if (addr >= phys_start && addr + size <= phys_end) {
546 				map->dm_segs[seg].ds_addr -= phys_start;
547 				map->dm_segs[seg].ds_addr += pci_start;
548 				break;
549 			}
550 		}
551 
552 		if (i == sc->sc_ndmaranges)
553 			return EINVAL;
554 	}
555 
556 	return 0;
557 }
558 
559 int
bcmpcie_dmamap_load_raw(bus_dma_tag_t t,bus_dmamap_t map,bus_dma_segment_t * segs,int nsegs,bus_size_t size,int flags)560 bcmpcie_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map,
561     bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags)
562 {
563 	struct bcmpcie_softc *sc = t->_cookie;
564 	int seg, error;
565 
566 	error = sc->sc_dmat->_dmamap_load_raw(sc->sc_dmat, map,
567 	     segs, nsegs, size, flags);
568 	if (error)
569 		return error;
570 
571 	if (sc->sc_dmaranges == NULL)
572 		return 0;
573 
574 	/* For each segment. */
575 	for (seg = 0; seg < map->dm_nsegs; seg++) {
576 		uint64_t addr = map->dm_segs[seg].ds_addr;
577 		uint64_t size = map->dm_segs[seg].ds_len;
578 		int i;
579 
580 		/* For each range. */
581 		for (i = 0; i < sc->sc_ndmaranges; i++) {
582 			uint64_t pci_start = sc->sc_dmaranges[i].pci_base;
583 			uint64_t phys_start = sc->sc_dmaranges[i].phys_base;
584 			uint64_t phys_end = phys_start +
585 			    sc->sc_dmaranges[i].size;
586 
587 			if (addr >= phys_start && addr + size <= phys_end) {
588 				map->dm_segs[seg].ds_addr -= phys_start;
589 				map->dm_segs[seg].ds_addr += pci_start;
590 				break;
591 			}
592 		}
593 
594 		if (i == sc->sc_ndmaranges)
595 			return EINVAL;
596 	}
597 
598 	return 0;
599 }
600