1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc. 4 * All rights reserved. 5 * Authors: Carsten Langgaard <carstenl@mips.com> 6 * Maciej W. Rozycki <macro@mips.com> 7 * 8 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) 9 * 10 * MIPS boards specific PCI support. 11 */ 12 #include <linux/types.h> 13 #include <linux/pci.h> 14 #include <linux/kernel.h> 15 #include <linux/init.h> 16 17 #include <asm/gt64120.h> 18 #include <asm/mips-cps.h> 19 #include <asm/mips-boards/generic.h> 20 #include <asm/mips-boards/bonito64.h> 21 #include <asm/mips-boards/msc01_pci.h> 22 23 static struct resource bonito64_mem_resource = { 24 .name = "Bonito PCI MEM", 25 .flags = IORESOURCE_MEM, 26 }; 27 28 static struct resource bonito64_io_resource = { 29 .name = "Bonito PCI I/O", 30 .start = 0x00000000UL, 31 .end = 0x000fffffUL, 32 .flags = IORESOURCE_IO, 33 }; 34 35 static struct resource gt64120_mem_resource = { 36 .name = "GT-64120 PCI MEM", 37 .flags = IORESOURCE_MEM, 38 }; 39 40 static struct resource gt64120_io_resource = { 41 .name = "GT-64120 PCI I/O", 42 .flags = IORESOURCE_IO, 43 }; 44 45 static struct resource msc_mem_resource = { 46 .name = "MSC PCI MEM", 47 .flags = IORESOURCE_MEM, 48 }; 49 50 static struct resource msc_io_resource = { 51 .name = "MSC PCI I/O", 52 .flags = IORESOURCE_IO, 53 }; 54 55 extern struct pci_ops bonito64_pci_ops; 56 extern struct pci_ops gt64xxx_pci0_ops; 57 extern struct pci_ops msc_pci_ops; 58 59 static struct pci_controller bonito64_controller = { 60 .pci_ops = &bonito64_pci_ops, 61 .io_resource = &bonito64_io_resource, 62 .mem_resource = &bonito64_mem_resource, 63 .io_offset = 0x00000000UL, 64 }; 65 66 static struct pci_controller gt64120_controller = { 67 .pci_ops = >64xxx_pci0_ops, 68 .io_resource = >64120_io_resource, 69 .mem_resource = >64120_mem_resource, 70 }; 71 72 static struct pci_controller msc_controller = { 73 .pci_ops = &msc_pci_ops, 74 .io_resource = &msc_io_resource, 75 .mem_resource = &msc_mem_resource, 76 }; 77 78 void __init mips_pcibios_init(void) 79 { 80 struct pci_controller *controller; 81 resource_size_t start, end, map, start1, end1, map1, map2, map3, mask; 82 83 switch (mips_revision_sconid) { 84 case MIPS_REVISION_SCON_GT64120: 85 /* 86 * Due to a bug in the Galileo system controller, we need 87 * to setup the PCI BAR for the Galileo internal registers. 88 * This should be done in the bios/bootprom and will be 89 * fixed in a later revision of YAMON (the MIPS boards 90 * boot prom). 91 */ 92 GT_WRITE(GT_PCI0_CFGADDR_OFS, 93 (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */ 94 (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */ 95 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/ 96 ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/ 97 GT_PCI0_CFGADDR_CONFIGEN_BIT); 98 99 /* Perform the write */ 100 GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE)); 101 102 /* Set up resource ranges from the controller's registers. */ 103 start = GT_READ(GT_PCI0M0LD_OFS); 104 end = GT_READ(GT_PCI0M0HD_OFS); 105 map = GT_READ(GT_PCI0M0REMAP_OFS); 106 end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK); 107 start1 = GT_READ(GT_PCI0M1LD_OFS); 108 end1 = GT_READ(GT_PCI0M1HD_OFS); 109 map1 = GT_READ(GT_PCI0M1REMAP_OFS); 110 end1 = (end1 & GT_PCI_HD_MSK) | (start1 & ~GT_PCI_HD_MSK); 111 /* Cannot support multiple windows, use the wider. */ 112 if (end1 - start1 > end - start) { 113 start = start1; 114 end = end1; 115 map = map1; 116 } 117 mask = ~(start ^ end); 118 /* We don't support remapping with a discontiguous mask. */ 119 BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) && 120 mask != ~((mask & -mask) - 1)); 121 gt64120_mem_resource.start = start; 122 gt64120_mem_resource.end = end; 123 gt64120_controller.mem_offset = (start & mask) - (map & mask); 124 /* Addresses are 36-bit, so do shifts in the destinations. */ 125 gt64120_mem_resource.start <<= GT_PCI_DCRM_SHF; 126 gt64120_mem_resource.end <<= GT_PCI_DCRM_SHF; 127 gt64120_mem_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1; 128 gt64120_controller.mem_offset <<= GT_PCI_DCRM_SHF; 129 130 start = GT_READ(GT_PCI0IOLD_OFS); 131 end = GT_READ(GT_PCI0IOHD_OFS); 132 map = GT_READ(GT_PCI0IOREMAP_OFS); 133 end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK); 134 mask = ~(start ^ end); 135 /* We don't support remapping with a discontiguous mask. */ 136 BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) && 137 mask != ~((mask & -mask) - 1)); 138 gt64120_io_resource.start = map & mask; 139 gt64120_io_resource.end = (map & mask) | ~mask; 140 gt64120_controller.io_offset = 0; 141 /* Addresses are 36-bit, so do shifts in the destinations. */ 142 gt64120_io_resource.start <<= GT_PCI_DCRM_SHF; 143 gt64120_io_resource.end <<= GT_PCI_DCRM_SHF; 144 gt64120_io_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1; 145 146 controller = >64120_controller; 147 break; 148 149 case MIPS_REVISION_SCON_BONITO: 150 /* Set up resource ranges from the controller's registers. */ 151 map = BONITO_PCIMAP; 152 map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >> 153 BONITO_PCIMAP_PCIMAP_LO0_SHIFT; 154 map2 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO1) >> 155 BONITO_PCIMAP_PCIMAP_LO1_SHIFT; 156 map3 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO2) >> 157 BONITO_PCIMAP_PCIMAP_LO2_SHIFT; 158 /* Combine as many adjacent windows as possible. */ 159 map = map1; 160 start = BONITO_PCILO0_BASE; 161 end = 1; 162 if (map3 == map2 + 1) { 163 map = map2; 164 start = BONITO_PCILO1_BASE; 165 end++; 166 } 167 if (map2 == map1 + 1) { 168 map = map1; 169 start = BONITO_PCILO0_BASE; 170 end++; 171 } 172 bonito64_mem_resource.start = start; 173 bonito64_mem_resource.end = start + 174 BONITO_PCIMAP_WINBASE(end) - 1; 175 bonito64_controller.mem_offset = start - 176 BONITO_PCIMAP_WINBASE(map); 177 178 controller = &bonito64_controller; 179 break; 180 181 case MIPS_REVISION_SCON_SOCIT: 182 case MIPS_REVISION_SCON_ROCIT: 183 case MIPS_REVISION_SCON_SOCITSC: 184 case MIPS_REVISION_SCON_SOCITSCP: 185 /* Set up resource ranges from the controller's registers. */ 186 MSC_READ(MSC01_PCI_SC2PMBASL, start); 187 MSC_READ(MSC01_PCI_SC2PMMSKL, mask); 188 MSC_READ(MSC01_PCI_SC2PMMAPL, map); 189 msc_mem_resource.start = start & mask; 190 msc_mem_resource.end = (start & mask) | ~mask; 191 msc_controller.mem_offset = (start & mask) - (map & mask); 192 if (mips_cps_numiocu(0)) { 193 write_gcr_reg0_base(start); 194 write_gcr_reg0_mask(mask | 195 CM_GCR_REGn_MASK_CMTGT_IOCU0); 196 } 197 MSC_READ(MSC01_PCI_SC2PIOBASL, start); 198 MSC_READ(MSC01_PCI_SC2PIOMSKL, mask); 199 MSC_READ(MSC01_PCI_SC2PIOMAPL, map); 200 msc_io_resource.start = map & mask; 201 msc_io_resource.end = (map & mask) | ~mask; 202 msc_controller.io_offset = 0; 203 ioport_resource.end = ~mask; 204 if (mips_cps_numiocu(0)) { 205 write_gcr_reg1_base(start); 206 write_gcr_reg1_mask(mask | 207 CM_GCR_REGn_MASK_CMTGT_IOCU0); 208 } 209 /* If ranges overlap I/O takes precedence. */ 210 start = start & mask; 211 end = start | ~mask; 212 if ((start >= msc_mem_resource.start && 213 start <= msc_mem_resource.end) || 214 (end >= msc_mem_resource.start && 215 end <= msc_mem_resource.end)) { 216 /* Use the larger space. */ 217 start = max(start, msc_mem_resource.start); 218 end = min(end, msc_mem_resource.end); 219 if (start - msc_mem_resource.start >= 220 msc_mem_resource.end - end) 221 msc_mem_resource.end = start - 1; 222 else 223 msc_mem_resource.start = end + 1; 224 } 225 226 controller = &msc_controller; 227 break; 228 default: 229 return; 230 } 231 232 /* PIIX4 ACPI starts at 0x1000 */ 233 if (controller->io_resource->start < 0x00001000UL) 234 controller->io_resource->start = 0x00001000UL; 235 236 iomem_resource.end &= 0xfffffffffULL; /* 64 GB */ 237 ioport_resource.end = controller->io_resource->end; 238 239 controller->io_map_base = mips_io_port_base; 240 241 register_pci_controller(controller); 242 } 243
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.