]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/nlm/xlp_pci.c
Upgrade to OpenSSH 7.6p1. This will be followed shortly by 7.7p1.
[FreeBSD/FreeBSD.git] / sys / mips / nlm / xlp_pci.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2003-2012 Broadcom Corporation
5  * All Rights Reserved
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
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
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/types.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/malloc.h>
40 #include <sys/bus.h>
41 #include <sys/endian.h>
42 #include <sys/rman.h>
43 #include <sys/pciio.h>
44
45 #include <machine/bus.h>
46 #include <machine/md_var.h>
47 #include <machine/intr_machdep.h>
48 #include <machine/cpuregs.h>
49
50 #include <vm/vm.h>
51 #include <vm/vm_param.h>
52 #include <vm/pmap.h>
53
54 #include <dev/pci/pcivar.h>
55 #include <dev/pci/pcireg.h>
56 #include <dev/pci/pci_private.h>
57
58 #include <dev/uart/uart.h>
59 #include <dev/uart/uart_bus.h>
60 #include <dev/uart/uart_cpu.h>
61
62 #include <dev/ofw/openfirm.h>
63 #include <dev/ofw/ofw_bus.h>
64 #include <dev/ofw/ofw_bus_subr.h>
65
66 #include <mips/nlm/hal/haldefs.h>
67 #include <mips/nlm/interrupt.h>
68 #include <mips/nlm/hal/iomap.h>
69 #include <mips/nlm/hal/mips-extns.h>
70 #include <mips/nlm/hal/pic.h>
71 #include <mips/nlm/hal/bridge.h>
72 #include <mips/nlm/hal/gbu.h>
73 #include <mips/nlm/hal/pcibus.h>
74 #include <mips/nlm/hal/uart.h>
75 #include <mips/nlm/xlp.h>
76
77 #include "pcib_if.h"
78 #include <dev/pci/pcib_private.h>
79 #include "pci_if.h"
80
81 static int
82 xlp_pci_attach(device_t dev)
83 {
84         struct pci_devinfo *dinfo;
85         device_t pcib;
86         int maxslots, s, f, pcifunchigh, irq;
87         int busno, node, devoffset;
88         uint16_t devid;
89         uint8_t hdrtype;
90
91         /*
92          * The on-chip devices are on a bus that is almost, but not
93          * quite, completely like PCI. Add those things by hand.
94          */
95         pcib = device_get_parent(dev);
96         busno = pcib_get_bus(dev);
97         maxslots = PCIB_MAXSLOTS(pcib);
98         for (s = 0; s <= maxslots; s++) {
99                 pcifunchigh = 0;
100                 f = 0;
101                 hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1);
102                 if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
103                         continue;
104                 if (hdrtype & PCIM_MFDEV)
105                         pcifunchigh = PCI_FUNCMAX;
106                 node = s / 8;
107                 for (f = 0; f <= pcifunchigh; f++) {
108                         devoffset = XLP_HDR_OFFSET(node, 0, s % 8, f);
109                         if (!nlm_dev_exists(devoffset))
110                                 continue;
111
112                         /* Find if there is a desc for the SoC device */
113                         devid = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_DEVICE, 2);
114
115                         /* Skip devices that don't have a proper PCI header */
116                         switch (devid) {
117                         case PCI_DEVICE_ID_NLM_ICI:
118                         case PCI_DEVICE_ID_NLM_PIC:
119                         case PCI_DEVICE_ID_NLM_FMN:
120                         case PCI_DEVICE_ID_NLM_UART:
121                         case PCI_DEVICE_ID_NLM_I2C:
122                         case PCI_DEVICE_ID_NLM_NOR:
123                         case PCI_DEVICE_ID_NLM_MMC:
124                                 continue;
125                         case PCI_DEVICE_ID_NLM_EHCI:
126                                 irq = PIC_USB_IRQ(f);
127                                 PCIB_WRITE_CONFIG(pcib, busno, s, f,
128                                     XLP_PCI_DEVSCRATCH_REG0 << 2,
129                                     (1 << 8) | irq, 4);
130                         }
131                         dinfo = pci_read_device(pcib, dev, pcib_get_domain(dev),
132                             busno, s, f);
133                         pci_add_child(dev, dinfo);
134                 }
135         }
136         return (bus_generic_attach(dev));
137 }
138
139 static int
140 xlp_pci_probe(device_t dev)
141 {
142         device_t pcib;
143
144         pcib = device_get_parent(dev);
145         /*
146          * Only the top level bus has SoC devices, leave the rest to
147          * Generic PCI code
148          */
149         if (strcmp(device_get_nameunit(pcib), "pcib0") != 0)
150                 return (ENXIO);
151         device_set_desc(dev, "XLP SoCbus");
152         return (BUS_PROBE_DEFAULT);
153 }
154
155 static devclass_t pci_devclass;
156 static device_method_t xlp_pci_methods[] = {
157         /* Device interface */
158         DEVMETHOD(device_probe,         xlp_pci_probe),
159         DEVMETHOD(device_attach,        xlp_pci_attach),
160         DEVMETHOD(bus_rescan,           bus_null_rescan),
161         DEVMETHOD_END
162 };
163
164 DEFINE_CLASS_1(pci, xlp_pci_driver, xlp_pci_methods, sizeof(struct pci_softc),
165     pci_driver);
166 DRIVER_MODULE(xlp_pci, pcib, xlp_pci_driver, pci_devclass, 0, 0);
167
168 static int
169 xlp_pcib_probe(device_t dev)
170 {
171
172         if (ofw_bus_is_compatible(dev, "netlogic,xlp-pci")) {
173                 device_set_desc(dev, "XLP PCI bus");
174                 return (BUS_PROBE_DEFAULT);
175         }
176         return (ENXIO);
177 }
178
179 static int
180 xlp_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
181 {
182
183         switch (which) {
184         case PCIB_IVAR_DOMAIN:
185                 *result = 0;
186                 return (0);
187         case PCIB_IVAR_BUS:
188                 *result = 0;
189                 return (0);
190         }
191         return (ENOENT);
192 }
193
194 static int
195 xlp_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
196 {
197         switch (which) {
198         case PCIB_IVAR_DOMAIN:
199                 return (EINVAL);
200         case PCIB_IVAR_BUS:
201                 return (EINVAL);
202         }
203         return (ENOENT);
204 }
205
206 static int
207 xlp_pcib_maxslots(device_t dev)
208 {
209
210         return (PCI_SLOTMAX);
211 }
212
213 static u_int32_t
214 xlp_pcib_read_config(device_t dev, u_int b, u_int s, u_int f,
215     u_int reg, int width)
216 {
217         uint32_t data = 0;
218         uint64_t cfgaddr;
219         int     regindex = reg/sizeof(uint32_t);
220
221         cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f));
222         if ((width == 2) && (reg & 1))
223                 return 0xFFFFFFFF;
224         else if ((width == 4) && (reg & 3))
225                 return 0xFFFFFFFF;
226
227         /*
228          * The intline and int pin of SoC devices are DOA, except
229          * for bridges (slot %8 == 1).
230          * use the values we stashed in a writable PCI scratch reg.
231          */
232         if (b == 0 && regindex == 0xf && s % 8 > 1)
233                 regindex = XLP_PCI_DEVSCRATCH_REG0;
234
235         data = nlm_read_pci_reg(cfgaddr, regindex);
236         if (width == 1)
237                 return ((data >> ((reg & 3) << 3)) & 0xff);
238         else if (width == 2)
239                 return ((data >> ((reg & 3) << 3)) & 0xffff);
240         else
241                 return (data);
242 }
243
244 static void
245 xlp_pcib_write_config(device_t dev, u_int b, u_int s, u_int f,
246     u_int reg, u_int32_t val, int width)
247 {
248         uint64_t cfgaddr;
249         uint32_t data = 0;
250         int     regindex = reg / sizeof(uint32_t);
251
252         cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f));
253         if ((width == 2) && (reg & 1))
254                 return;
255         else if ((width == 4) && (reg & 3))
256                 return;
257
258         if (width == 1) {
259                 data = nlm_read_pci_reg(cfgaddr, regindex);
260                 data = (data & ~(0xff << ((reg & 3) << 3))) |
261                     (val << ((reg & 3) << 3));
262         } else if (width == 2) {
263                 data = nlm_read_pci_reg(cfgaddr, regindex);
264                 data = (data & ~(0xffff << ((reg & 3) << 3))) |
265                     (val << ((reg & 3) << 3));
266         } else {
267                 data = val;
268         }
269
270         /*
271          * use shadow reg for intpin/intline which are dead
272          */
273         if (b == 0 && regindex == 0xf && s % 8 > 1)
274                 regindex = XLP_PCI_DEVSCRATCH_REG0;
275         nlm_write_pci_reg(cfgaddr, regindex, data);
276 }
277
278 /*
279  * Enable byte swap in hardware when compiled big-endian.
280  * Programs a link's PCIe SWAP regions from the link's IO and MEM address
281  * ranges.
282  */
283 static void
284 xlp_pcib_hardware_swap_enable(int node, int link)
285 {
286 #if BYTE_ORDER == BIG_ENDIAN
287         uint64_t bbase, linkpcibase;
288         uint32_t bar;
289         int pcieoffset;
290
291         pcieoffset = XLP_IO_PCIE_OFFSET(node, link);
292         if (!nlm_dev_exists(pcieoffset))
293                 return;
294
295         bbase = nlm_get_bridge_regbase(node);
296         linkpcibase = nlm_pcicfg_base(pcieoffset);
297         bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEMEM_BASE0 + link);
298         nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_MEM_BASE, bar);
299
300         bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEMEM_LIMIT0 + link);
301         nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_MEM_LIM, bar | 0xFFF);
302
303         bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_BASE0 + link);
304         nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_BASE, bar);
305
306         bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_LIMIT0 + link);
307         nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_LIM, bar | 0xFFF);
308 #endif
309 }
310
311 static int
312 xlp_pcib_attach(device_t dev)
313 {
314         int node, link;
315
316         /* enable hardware swap on all nodes/links */
317         for (node = 0; node < XLP_MAX_NODES; node++)
318                 for (link = 0; link < 4; link++)
319                         xlp_pcib_hardware_swap_enable(node, link);
320
321         device_add_child(dev, "pci", -1);
322         bus_generic_attach(dev);
323         return (0);
324 }
325
326 /*
327  * XLS PCIe can have upto 4 links, and each link has its on IRQ
328  * Find the link on which the device is on
329  */
330 static int
331 xlp_pcie_link(device_t pcib, device_t dev)
332 {
333         device_t parent, tmp;
334
335         /* find the lane on which the slot is connected to */
336         tmp = dev;
337         while (1) {
338                 parent = device_get_parent(tmp);
339                 if (parent == NULL || parent == pcib) {
340                         device_printf(dev, "Cannot find parent bus\n");
341                         return (-1);
342                 }
343                 if (strcmp(device_get_nameunit(parent), "pci0") == 0)
344                         break;
345                 tmp = parent;
346         }
347         return (pci_get_function(tmp));
348 }
349
350 static int
351 xlp_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
352 {
353         int i, link;
354
355         /*
356          * Each link has 32 MSIs that can be allocated, but for now
357          * we only support one device per link.
358          * msi_alloc() equivalent is needed when we start supporting
359          * bridges on the PCIe link.
360          */
361         link = xlp_pcie_link(pcib, dev);
362         if (link == -1)
363                 return (ENXIO);
364
365         /*
366          * encode the irq so that we know it is a MSI interrupt when we
367          * setup interrupts
368          */
369         for (i = 0; i < count; i++)
370                 irqs[i] = 64 + link * 32 + i;
371
372         return (0);
373 }
374
375 static int
376 xlp_release_msi(device_t pcib, device_t dev, int count, int *irqs)
377 {
378         return (0);
379 }
380
381 static int
382 xlp_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
383     uint32_t *data)
384 {
385         int link;
386
387         if (irq < 64) {
388                 device_printf(dev, "%s: map_msi for irq %d  - ignored",
389                     device_get_nameunit(pcib), irq);
390                 return (ENXIO);
391         }
392         link = (irq - 64) / 32;
393         *addr = MIPS_MSI_ADDR(0);
394         *data = MIPS_MSI_DATA(PIC_PCIE_IRQ(link));
395         return (0);
396 }
397
398 static void
399 bridge_pcie_ack(int irq, void *arg)
400 {
401         uint32_t node,reg;
402         uint64_t base;
403
404         node = nlm_nodeid();
405         reg = PCIE_MSI_STATUS;
406
407         switch (irq) {
408                 case PIC_PCIE_0_IRQ:
409                         base = nlm_pcicfg_base(XLP_IO_PCIE0_OFFSET(node));
410                         break;
411                 case PIC_PCIE_1_IRQ:
412                         base = nlm_pcicfg_base(XLP_IO_PCIE1_OFFSET(node));
413                         break;
414                 case PIC_PCIE_2_IRQ:
415                         base = nlm_pcicfg_base(XLP_IO_PCIE2_OFFSET(node));
416                         break;
417                 case PIC_PCIE_3_IRQ:
418                         base = nlm_pcicfg_base(XLP_IO_PCIE3_OFFSET(node));
419                         break;
420                 default:
421                         return;
422         }
423
424         nlm_write_pci_reg(base, reg, 0xFFFFFFFF);
425         return;
426 }
427
428 static int
429 mips_platform_pcib_setup_intr(device_t dev, device_t child,
430     struct resource *irq, int flags, driver_filter_t *filt,
431     driver_intr_t *intr, void *arg, void **cookiep)
432 {
433         int error = 0;
434         int xlpirq;
435
436         error = rman_activate_resource(irq);
437         if (error)
438                 return error;
439         if (rman_get_start(irq) != rman_get_end(irq)) {
440                 device_printf(dev, "Interrupt allocation %ju != %ju\n",
441                     rman_get_start(irq), rman_get_end(irq));
442                 return (EINVAL);
443         }
444         xlpirq = rman_get_start(irq);
445         if (xlpirq == 0)
446                 return (0);
447
448         if (strcmp(device_get_name(dev), "pcib") != 0)
449                 return (0);
450
451         /*
452          * temporary hack for MSI, we support just one device per
453          * link, and assign the link interrupt to the device interrupt
454          */
455         if (xlpirq >= 64) {
456                 int node, val, link;
457                 uint64_t base;
458
459                 xlpirq -= 64;
460                 if (xlpirq % 32 != 0)
461                         return (0);
462
463                 node = nlm_nodeid();
464                 link = xlpirq / 32;
465                 base = nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node,link));
466
467                 /* MSI Interrupt Vector enable at bridge's configuration */
468                 nlm_write_pci_reg(base, PCIE_MSI_EN, PCIE_MSI_VECTOR_INT_EN);
469
470                 val = nlm_read_pci_reg(base, PCIE_INT_EN0);
471                 /* MSI Interrupt enable at bridge's configuration */
472                 nlm_write_pci_reg(base, PCIE_INT_EN0,
473                     (val | PCIE_MSI_INT_EN));
474
475                 /* legacy interrupt disable at bridge */
476                 val = nlm_read_pci_reg(base, PCIE_BRIDGE_CMD);
477                 nlm_write_pci_reg(base, PCIE_BRIDGE_CMD,
478                     (val | PCIM_CMD_INTxDIS));
479
480                 /* MSI address update at bridge */
481                 nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_ADDRL,
482                     MSI_MIPS_ADDR_BASE);
483                 nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_ADDRH, 0);
484
485                 val = nlm_read_pci_reg(base, PCIE_BRIDGE_MSI_CAP);
486                 /* MSI capability enable at bridge */
487                 nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_CAP,
488                     (val | (PCIM_MSICTRL_MSI_ENABLE << 16) |
489                         (PCIM_MSICTRL_MMC_32 << 16)));
490                 xlpirq = PIC_PCIE_IRQ(link);
491         }
492
493         /* if it is for real PCIe, we need to ack at bridge too */
494         if (xlpirq >= PIC_PCIE_IRQ(0) && xlpirq <= PIC_PCIE_IRQ(3))
495                 xlp_set_bus_ack(xlpirq, bridge_pcie_ack, NULL);
496         cpu_establish_hardintr(device_get_name(child), filt, intr, arg,
497             xlpirq, flags, cookiep);
498
499         return (0);
500 }
501
502 static int
503 mips_platform_pcib_teardown_intr(device_t dev, device_t child,
504     struct resource *irq, void *cookie)
505 {
506         if (strcmp(device_get_name(child), "pci") == 0) {
507                 /* if needed reprogram the pic to clear pcix related entry */
508                 device_printf(dev, "teardown intr\n");
509         }
510         return (bus_generic_teardown_intr(dev, child, irq, cookie));
511 }
512
513 static int
514 mips_pcib_route_interrupt(device_t bus, device_t dev, int pin)
515 {
516         int f, d;
517
518         /*
519          * Validate requested pin number.
520          */
521         if ((pin < 1) || (pin > 4))
522                 return (255);
523
524         if (pci_get_bus(dev) == 0 &&
525             pci_get_vendor(dev) == PCI_VENDOR_NETLOGIC) {
526                 f = pci_get_function(dev);
527                 d = pci_get_slot(dev) % 8;
528
529                 /*
530                  * For PCIe links, return link IRT, for other SoC devices
531                  * get the IRT from its PCIe header
532                  */
533                 if (d == 1)
534                         return (PIC_PCIE_IRQ(f));
535                 else
536                         return (255);   /* use intline, don't reroute */
537         } else {
538                 /* Regular PCI devices */
539                 return (PIC_PCIE_IRQ(xlp_pcie_link(bus, dev)));
540         }
541 }
542
543 static device_method_t xlp_pcib_methods[] = {
544         /* Device interface */
545         DEVMETHOD(device_probe, xlp_pcib_probe),
546         DEVMETHOD(device_attach, xlp_pcib_attach),
547
548         /* Bus interface */
549         DEVMETHOD(bus_read_ivar, xlp_pcib_read_ivar),
550         DEVMETHOD(bus_write_ivar, xlp_pcib_write_ivar),
551         DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
552         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
553         DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
554         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
555         DEVMETHOD(bus_setup_intr, mips_platform_pcib_setup_intr),
556         DEVMETHOD(bus_teardown_intr, mips_platform_pcib_teardown_intr),
557
558         /* pcib interface */
559         DEVMETHOD(pcib_maxslots, xlp_pcib_maxslots),
560         DEVMETHOD(pcib_read_config, xlp_pcib_read_config),
561         DEVMETHOD(pcib_write_config, xlp_pcib_write_config),
562         DEVMETHOD(pcib_route_interrupt, mips_pcib_route_interrupt),
563         DEVMETHOD(pcib_request_feature, pcib_request_feature_allow),
564
565         DEVMETHOD(pcib_alloc_msi, xlp_alloc_msi),
566         DEVMETHOD(pcib_release_msi, xlp_release_msi),
567         DEVMETHOD(pcib_map_msi, xlp_map_msi),
568
569         DEVMETHOD_END
570 };
571
572 static driver_t xlp_pcib_driver = {
573         "pcib",
574         xlp_pcib_methods,
575         1, /* no softc */
576 };
577
578 static devclass_t pcib_devclass;
579 DRIVER_MODULE(xlp_pcib, simplebus, xlp_pcib_driver, pcib_devclass, 0, 0);