1*41173abcSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20dad5d26SRalf Baechle /*
30dad5d26SRalf Baechle * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc.
40dad5d26SRalf Baechle * All rights reserved.
50dad5d26SRalf Baechle * Authors: Carsten Langgaard <carstenl@mips.com>
60dad5d26SRalf Baechle * Maciej W. Rozycki <macro@mips.com>
70dad5d26SRalf Baechle *
80dad5d26SRalf Baechle * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
90dad5d26SRalf Baechle *
100dad5d26SRalf Baechle * MIPS boards specific PCI support.
110dad5d26SRalf Baechle */
120dad5d26SRalf Baechle #include <linux/types.h>
130dad5d26SRalf Baechle #include <linux/pci.h>
140dad5d26SRalf Baechle #include <linux/kernel.h>
150dad5d26SRalf Baechle #include <linux/init.h>
160dad5d26SRalf Baechle
170dad5d26SRalf Baechle #include <asm/gt64120.h>
18e83f7e02SPaul Burton #include <asm/mips-cps.h>
190dad5d26SRalf Baechle #include <asm/mips-boards/generic.h>
200dad5d26SRalf Baechle #include <asm/mips-boards/bonito64.h>
210dad5d26SRalf Baechle #include <asm/mips-boards/msc01_pci.h>
220dad5d26SRalf Baechle
230dad5d26SRalf Baechle static struct resource bonito64_mem_resource = {
240dad5d26SRalf Baechle .name = "Bonito PCI MEM",
250dad5d26SRalf Baechle .flags = IORESOURCE_MEM,
260dad5d26SRalf Baechle };
270dad5d26SRalf Baechle
280dad5d26SRalf Baechle static struct resource bonito64_io_resource = {
290dad5d26SRalf Baechle .name = "Bonito PCI I/O",
300dad5d26SRalf Baechle .start = 0x00000000UL,
310dad5d26SRalf Baechle .end = 0x000fffffUL,
320dad5d26SRalf Baechle .flags = IORESOURCE_IO,
330dad5d26SRalf Baechle };
340dad5d26SRalf Baechle
350dad5d26SRalf Baechle static struct resource gt64120_mem_resource = {
360dad5d26SRalf Baechle .name = "GT-64120 PCI MEM",
370dad5d26SRalf Baechle .flags = IORESOURCE_MEM,
380dad5d26SRalf Baechle };
390dad5d26SRalf Baechle
400dad5d26SRalf Baechle static struct resource gt64120_io_resource = {
410dad5d26SRalf Baechle .name = "GT-64120 PCI I/O",
420dad5d26SRalf Baechle .flags = IORESOURCE_IO,
430dad5d26SRalf Baechle };
440dad5d26SRalf Baechle
450dad5d26SRalf Baechle static struct resource msc_mem_resource = {
460dad5d26SRalf Baechle .name = "MSC PCI MEM",
470dad5d26SRalf Baechle .flags = IORESOURCE_MEM,
480dad5d26SRalf Baechle };
490dad5d26SRalf Baechle
500dad5d26SRalf Baechle static struct resource msc_io_resource = {
510dad5d26SRalf Baechle .name = "MSC PCI I/O",
520dad5d26SRalf Baechle .flags = IORESOURCE_IO,
530dad5d26SRalf Baechle };
540dad5d26SRalf Baechle
550dad5d26SRalf Baechle extern struct pci_ops bonito64_pci_ops;
560dad5d26SRalf Baechle extern struct pci_ops gt64xxx_pci0_ops;
570dad5d26SRalf Baechle extern struct pci_ops msc_pci_ops;
580dad5d26SRalf Baechle
590dad5d26SRalf Baechle static struct pci_controller bonito64_controller = {
600dad5d26SRalf Baechle .pci_ops = &bonito64_pci_ops,
610dad5d26SRalf Baechle .io_resource = &bonito64_io_resource,
620dad5d26SRalf Baechle .mem_resource = &bonito64_mem_resource,
630dad5d26SRalf Baechle .io_offset = 0x00000000UL,
640dad5d26SRalf Baechle };
650dad5d26SRalf Baechle
660dad5d26SRalf Baechle static struct pci_controller gt64120_controller = {
670dad5d26SRalf Baechle .pci_ops = >64xxx_pci0_ops,
680dad5d26SRalf Baechle .io_resource = >64120_io_resource,
690dad5d26SRalf Baechle .mem_resource = >64120_mem_resource,
700dad5d26SRalf Baechle };
710dad5d26SRalf Baechle
720dad5d26SRalf Baechle static struct pci_controller msc_controller = {
730dad5d26SRalf Baechle .pci_ops = &msc_pci_ops,
740dad5d26SRalf Baechle .io_resource = &msc_io_resource,
750dad5d26SRalf Baechle .mem_resource = &msc_mem_resource,
760dad5d26SRalf Baechle };
770dad5d26SRalf Baechle
mips_pcibios_init(void)780dad5d26SRalf Baechle void __init mips_pcibios_init(void)
790dad5d26SRalf Baechle {
800dad5d26SRalf Baechle struct pci_controller *controller;
810dad5d26SRalf Baechle resource_size_t start, end, map, start1, end1, map1, map2, map3, mask;
820dad5d26SRalf Baechle
830dad5d26SRalf Baechle switch (mips_revision_sconid) {
840dad5d26SRalf Baechle case MIPS_REVISION_SCON_GT64120:
850dad5d26SRalf Baechle /*
860dad5d26SRalf Baechle * Due to a bug in the Galileo system controller, we need
870dad5d26SRalf Baechle * to setup the PCI BAR for the Galileo internal registers.
880dad5d26SRalf Baechle * This should be done in the bios/bootprom and will be
890dad5d26SRalf Baechle * fixed in a later revision of YAMON (the MIPS boards
900dad5d26SRalf Baechle * boot prom).
910dad5d26SRalf Baechle */
920dad5d26SRalf Baechle GT_WRITE(GT_PCI0_CFGADDR_OFS,
930dad5d26SRalf Baechle (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
940dad5d26SRalf Baechle (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
950dad5d26SRalf Baechle (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
960dad5d26SRalf Baechle ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
970dad5d26SRalf Baechle GT_PCI0_CFGADDR_CONFIGEN_BIT);
980dad5d26SRalf Baechle
990dad5d26SRalf Baechle /* Perform the write */
1000dad5d26SRalf Baechle GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
1010dad5d26SRalf Baechle
1020dad5d26SRalf Baechle /* Set up resource ranges from the controller's registers. */
1030dad5d26SRalf Baechle start = GT_READ(GT_PCI0M0LD_OFS);
1040dad5d26SRalf Baechle end = GT_READ(GT_PCI0M0HD_OFS);
1050dad5d26SRalf Baechle map = GT_READ(GT_PCI0M0REMAP_OFS);
1060dad5d26SRalf Baechle end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
1070dad5d26SRalf Baechle start1 = GT_READ(GT_PCI0M1LD_OFS);
1080dad5d26SRalf Baechle end1 = GT_READ(GT_PCI0M1HD_OFS);
1090dad5d26SRalf Baechle map1 = GT_READ(GT_PCI0M1REMAP_OFS);
1100dad5d26SRalf Baechle end1 = (end1 & GT_PCI_HD_MSK) | (start1 & ~GT_PCI_HD_MSK);
1110dad5d26SRalf Baechle /* Cannot support multiple windows, use the wider. */
1120dad5d26SRalf Baechle if (end1 - start1 > end - start) {
1130dad5d26SRalf Baechle start = start1;
1140dad5d26SRalf Baechle end = end1;
1150dad5d26SRalf Baechle map = map1;
1160dad5d26SRalf Baechle }
1170dad5d26SRalf Baechle mask = ~(start ^ end);
1180dad5d26SRalf Baechle /* We don't support remapping with a discontiguous mask. */
1190dad5d26SRalf Baechle BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
1200dad5d26SRalf Baechle mask != ~((mask & -mask) - 1));
1210dad5d26SRalf Baechle gt64120_mem_resource.start = start;
1220dad5d26SRalf Baechle gt64120_mem_resource.end = end;
1230dad5d26SRalf Baechle gt64120_controller.mem_offset = (start & mask) - (map & mask);
1240dad5d26SRalf Baechle /* Addresses are 36-bit, so do shifts in the destinations. */
1250dad5d26SRalf Baechle gt64120_mem_resource.start <<= GT_PCI_DCRM_SHF;
1260dad5d26SRalf Baechle gt64120_mem_resource.end <<= GT_PCI_DCRM_SHF;
1270dad5d26SRalf Baechle gt64120_mem_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
1280dad5d26SRalf Baechle gt64120_controller.mem_offset <<= GT_PCI_DCRM_SHF;
1290dad5d26SRalf Baechle
1300dad5d26SRalf Baechle start = GT_READ(GT_PCI0IOLD_OFS);
1310dad5d26SRalf Baechle end = GT_READ(GT_PCI0IOHD_OFS);
1320dad5d26SRalf Baechle map = GT_READ(GT_PCI0IOREMAP_OFS);
1330dad5d26SRalf Baechle end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK);
1340dad5d26SRalf Baechle mask = ~(start ^ end);
1350dad5d26SRalf Baechle /* We don't support remapping with a discontiguous mask. */
1360dad5d26SRalf Baechle BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) &&
1370dad5d26SRalf Baechle mask != ~((mask & -mask) - 1));
1380dad5d26SRalf Baechle gt64120_io_resource.start = map & mask;
1390dad5d26SRalf Baechle gt64120_io_resource.end = (map & mask) | ~mask;
1400dad5d26SRalf Baechle gt64120_controller.io_offset = 0;
1410dad5d26SRalf Baechle /* Addresses are 36-bit, so do shifts in the destinations. */
1420dad5d26SRalf Baechle gt64120_io_resource.start <<= GT_PCI_DCRM_SHF;
1430dad5d26SRalf Baechle gt64120_io_resource.end <<= GT_PCI_DCRM_SHF;
1440dad5d26SRalf Baechle gt64120_io_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1;
1450dad5d26SRalf Baechle
1460dad5d26SRalf Baechle controller = >64120_controller;
1470dad5d26SRalf Baechle break;
1480dad5d26SRalf Baechle
1490dad5d26SRalf Baechle case MIPS_REVISION_SCON_BONITO:
1500dad5d26SRalf Baechle /* Set up resource ranges from the controller's registers. */
1510dad5d26SRalf Baechle map = BONITO_PCIMAP;
1520dad5d26SRalf Baechle map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >>
1530dad5d26SRalf Baechle BONITO_PCIMAP_PCIMAP_LO0_SHIFT;
1540dad5d26SRalf Baechle map2 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO1) >>
1550dad5d26SRalf Baechle BONITO_PCIMAP_PCIMAP_LO1_SHIFT;
1560dad5d26SRalf Baechle map3 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO2) >>
1570dad5d26SRalf Baechle BONITO_PCIMAP_PCIMAP_LO2_SHIFT;
1580dad5d26SRalf Baechle /* Combine as many adjacent windows as possible. */
1590dad5d26SRalf Baechle map = map1;
1600dad5d26SRalf Baechle start = BONITO_PCILO0_BASE;
1610dad5d26SRalf Baechle end = 1;
1620dad5d26SRalf Baechle if (map3 == map2 + 1) {
1630dad5d26SRalf Baechle map = map2;
1640dad5d26SRalf Baechle start = BONITO_PCILO1_BASE;
1650dad5d26SRalf Baechle end++;
1660dad5d26SRalf Baechle }
1670dad5d26SRalf Baechle if (map2 == map1 + 1) {
1680dad5d26SRalf Baechle map = map1;
1690dad5d26SRalf Baechle start = BONITO_PCILO0_BASE;
1700dad5d26SRalf Baechle end++;
1710dad5d26SRalf Baechle }
1720dad5d26SRalf Baechle bonito64_mem_resource.start = start;
1730dad5d26SRalf Baechle bonito64_mem_resource.end = start +
1740dad5d26SRalf Baechle BONITO_PCIMAP_WINBASE(end) - 1;
1750dad5d26SRalf Baechle bonito64_controller.mem_offset = start -
1760dad5d26SRalf Baechle BONITO_PCIMAP_WINBASE(map);
1770dad5d26SRalf Baechle
1780dad5d26SRalf Baechle controller = &bonito64_controller;
1790dad5d26SRalf Baechle break;
1800dad5d26SRalf Baechle
1810dad5d26SRalf Baechle case MIPS_REVISION_SCON_SOCIT:
1820dad5d26SRalf Baechle case MIPS_REVISION_SCON_ROCIT:
1830dad5d26SRalf Baechle case MIPS_REVISION_SCON_SOCITSC:
1840dad5d26SRalf Baechle case MIPS_REVISION_SCON_SOCITSCP:
1850dad5d26SRalf Baechle /* Set up resource ranges from the controller's registers. */
1860dad5d26SRalf Baechle MSC_READ(MSC01_PCI_SC2PMBASL, start);
1870dad5d26SRalf Baechle MSC_READ(MSC01_PCI_SC2PMMSKL, mask);
1880dad5d26SRalf Baechle MSC_READ(MSC01_PCI_SC2PMMAPL, map);
1890dad5d26SRalf Baechle msc_mem_resource.start = start & mask;
1900dad5d26SRalf Baechle msc_mem_resource.end = (start & mask) | ~mask;
1910dad5d26SRalf Baechle msc_controller.mem_offset = (start & mask) - (map & mask);
1923c9b4166SPaul Burton if (mips_cps_numiocu(0)) {
193237036deSPaul Burton write_gcr_reg0_base(start);
194237036deSPaul Burton write_gcr_reg0_mask(mask |
195237036deSPaul Burton CM_GCR_REGn_MASK_CMTGT_IOCU0);
196237036deSPaul Burton }
1970dad5d26SRalf Baechle MSC_READ(MSC01_PCI_SC2PIOBASL, start);
1980dad5d26SRalf Baechle MSC_READ(MSC01_PCI_SC2PIOMSKL, mask);
1990dad5d26SRalf Baechle MSC_READ(MSC01_PCI_SC2PIOMAPL, map);
2000dad5d26SRalf Baechle msc_io_resource.start = map & mask;
2010dad5d26SRalf Baechle msc_io_resource.end = (map & mask) | ~mask;
2020dad5d26SRalf Baechle msc_controller.io_offset = 0;
2030dad5d26SRalf Baechle ioport_resource.end = ~mask;
2043c9b4166SPaul Burton if (mips_cps_numiocu(0)) {
205237036deSPaul Burton write_gcr_reg1_base(start);
206237036deSPaul Burton write_gcr_reg1_mask(mask |
207237036deSPaul Burton CM_GCR_REGn_MASK_CMTGT_IOCU0);
208237036deSPaul Burton }
2090dad5d26SRalf Baechle /* If ranges overlap I/O takes precedence. */
2100dad5d26SRalf Baechle start = start & mask;
2110dad5d26SRalf Baechle end = start | ~mask;
2120dad5d26SRalf Baechle if ((start >= msc_mem_resource.start &&
2130dad5d26SRalf Baechle start <= msc_mem_resource.end) ||
2140dad5d26SRalf Baechle (end >= msc_mem_resource.start &&
2150dad5d26SRalf Baechle end <= msc_mem_resource.end)) {
2160dad5d26SRalf Baechle /* Use the larger space. */
2170dad5d26SRalf Baechle start = max(start, msc_mem_resource.start);
2180dad5d26SRalf Baechle end = min(end, msc_mem_resource.end);
2190dad5d26SRalf Baechle if (start - msc_mem_resource.start >=
2200dad5d26SRalf Baechle msc_mem_resource.end - end)
2210dad5d26SRalf Baechle msc_mem_resource.end = start - 1;
2220dad5d26SRalf Baechle else
2230dad5d26SRalf Baechle msc_mem_resource.start = end + 1;
2240dad5d26SRalf Baechle }
2250dad5d26SRalf Baechle
2260dad5d26SRalf Baechle controller = &msc_controller;
2270dad5d26SRalf Baechle break;
2280dad5d26SRalf Baechle default:
2290dad5d26SRalf Baechle return;
2300dad5d26SRalf Baechle }
2310dad5d26SRalf Baechle
23227547abfSDeng-Cheng Zhu /* PIIX4 ACPI starts at 0x1000 */
23327547abfSDeng-Cheng Zhu if (controller->io_resource->start < 0x00001000UL)
23427547abfSDeng-Cheng Zhu controller->io_resource->start = 0x00001000UL;
2350dad5d26SRalf Baechle
2360dad5d26SRalf Baechle iomem_resource.end &= 0xfffffffffULL; /* 64 GB */
2370dad5d26SRalf Baechle ioport_resource.end = controller->io_resource->end;
2380dad5d26SRalf Baechle
2390dad5d26SRalf Baechle controller->io_map_base = mips_io_port_base;
2400dad5d26SRalf Baechle
2410dad5d26SRalf Baechle register_pci_controller(controller);
2420dad5d26SRalf Baechle }
243