| Maxime Bizon | e7300d0 | 2009-08-18 13:23:37 +0100 | [diff] [blame] | 1 | /* | 
 | 2 |  * This file is subject to the terms and conditions of the GNU General Public | 
 | 3 |  * License.  See the file "COPYING" in the main directory of this archive | 
 | 4 |  * for more details. | 
 | 5 |  * | 
 | 6 |  * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> | 
 | 7 |  */ | 
 | 8 |  | 
 | 9 | #include <linux/types.h> | 
 | 10 | #include <linux/pci.h> | 
 | 11 | #include <linux/kernel.h> | 
 | 12 | #include <linux/init.h> | 
 | 13 | #include <linux/delay.h> | 
 | 14 | #include <linux/io.h> | 
 | 15 |  | 
 | 16 | #include "pci-bcm63xx.h" | 
 | 17 |  | 
 | 18 | /* | 
 | 19 |  * swizzle 32bits data to return only the needed part | 
 | 20 |  */ | 
 | 21 | static int postprocess_read(u32 data, int where, unsigned int size) | 
 | 22 | { | 
 | 23 | 	u32 ret; | 
 | 24 |  | 
 | 25 | 	ret = 0; | 
 | 26 | 	switch (size) { | 
 | 27 | 	case 1: | 
 | 28 | 		ret = (data >> ((where & 3) << 3)) & 0xff; | 
 | 29 | 		break; | 
 | 30 | 	case 2: | 
 | 31 | 		ret = (data >> ((where & 3) << 3)) & 0xffff; | 
 | 32 | 		break; | 
 | 33 | 	case 4: | 
 | 34 | 		ret = data; | 
 | 35 | 		break; | 
 | 36 | 	} | 
 | 37 | 	return ret; | 
 | 38 | } | 
 | 39 |  | 
 | 40 | static int preprocess_write(u32 orig_data, u32 val, int where, | 
 | 41 | 			    unsigned int size) | 
 | 42 | { | 
 | 43 | 	u32 ret; | 
 | 44 |  | 
 | 45 | 	ret = 0; | 
 | 46 | 	switch (size) { | 
 | 47 | 	case 1: | 
 | 48 | 		ret = (orig_data & ~(0xff << ((where & 3) << 3))) | | 
 | 49 | 			(val << ((where & 3) << 3)); | 
 | 50 | 		break; | 
 | 51 | 	case 2: | 
 | 52 | 		ret = (orig_data & ~(0xffff << ((where & 3) << 3))) | | 
 | 53 | 			(val << ((where & 3) << 3)); | 
 | 54 | 		break; | 
 | 55 | 	case 4: | 
 | 56 | 		ret = val; | 
 | 57 | 		break; | 
 | 58 | 	} | 
 | 59 | 	return ret; | 
 | 60 | } | 
 | 61 |  | 
 | 62 | /* | 
 | 63 |  * setup hardware for a configuration cycle with given parameters | 
 | 64 |  */ | 
 | 65 | static int bcm63xx_setup_cfg_access(int type, unsigned int busn, | 
 | 66 | 				    unsigned int devfn, int where) | 
 | 67 | { | 
 | 68 | 	unsigned int slot, func, reg; | 
 | 69 | 	u32 val; | 
 | 70 |  | 
 | 71 | 	slot = PCI_SLOT(devfn); | 
 | 72 | 	func = PCI_FUNC(devfn); | 
 | 73 | 	reg = where >> 2; | 
 | 74 |  | 
 | 75 | 	/* sanity check */ | 
 | 76 | 	if (slot > (MPI_L2PCFG_DEVNUM_MASK >> MPI_L2PCFG_DEVNUM_SHIFT)) | 
 | 77 | 		return 1; | 
 | 78 |  | 
 | 79 | 	if (func > (MPI_L2PCFG_FUNC_MASK >> MPI_L2PCFG_FUNC_SHIFT)) | 
 | 80 | 		return 1; | 
 | 81 |  | 
 | 82 | 	if (reg > (MPI_L2PCFG_REG_MASK >> MPI_L2PCFG_REG_SHIFT)) | 
 | 83 | 		return 1; | 
 | 84 |  | 
 | 85 | 	/* ok, setup config access */ | 
 | 86 | 	val = (reg << MPI_L2PCFG_REG_SHIFT); | 
 | 87 | 	val |= (func << MPI_L2PCFG_FUNC_SHIFT); | 
 | 88 | 	val |= (slot << MPI_L2PCFG_DEVNUM_SHIFT); | 
 | 89 | 	val |= MPI_L2PCFG_CFG_USEREG_MASK; | 
 | 90 | 	val |= MPI_L2PCFG_CFG_SEL_MASK; | 
 | 91 | 	/* type 0 cycle for local bus, type 1 cycle for anything else */ | 
 | 92 | 	if (type != 0) { | 
 | 93 | 		/* FIXME: how to specify bus ??? */ | 
 | 94 | 		val |= (1 << MPI_L2PCFG_CFG_TYPE_SHIFT); | 
 | 95 | 	} | 
 | 96 | 	bcm_mpi_writel(val, MPI_L2PCFG_REG); | 
 | 97 |  | 
 | 98 | 	return 0; | 
 | 99 | } | 
 | 100 |  | 
 | 101 | static int bcm63xx_do_cfg_read(int type, unsigned int busn, | 
 | 102 | 				unsigned int devfn, int where, int size, | 
 | 103 | 				u32 *val) | 
 | 104 | { | 
 | 105 | 	u32 data; | 
 | 106 |  | 
 | 107 | 	/* two phase cycle, first we write address, then read data at | 
 | 108 | 	 * another location, caller already has a spinlock so no need | 
 | 109 | 	 * to add one here  */ | 
 | 110 | 	if (bcm63xx_setup_cfg_access(type, busn, devfn, where)) | 
 | 111 | 		return PCIBIOS_DEVICE_NOT_FOUND; | 
 | 112 | 	iob(); | 
 | 113 | 	data = le32_to_cpu(__raw_readl(pci_iospace_start)); | 
 | 114 | 	/* restore IO space normal behaviour */ | 
 | 115 | 	bcm_mpi_writel(0, MPI_L2PCFG_REG); | 
 | 116 |  | 
 | 117 | 	*val = postprocess_read(data, where, size); | 
 | 118 |  | 
 | 119 | 	return PCIBIOS_SUCCESSFUL; | 
 | 120 | } | 
 | 121 |  | 
 | 122 | static int bcm63xx_do_cfg_write(int type, unsigned int busn, | 
 | 123 | 				 unsigned int devfn, int where, int size, | 
 | 124 | 				 u32 val) | 
 | 125 | { | 
 | 126 | 	u32 data; | 
 | 127 |  | 
 | 128 | 	/* two phase cycle, first we write address, then write data to | 
 | 129 | 	 * another location, caller already has a spinlock so no need | 
 | 130 | 	 * to add one here  */ | 
 | 131 | 	if (bcm63xx_setup_cfg_access(type, busn, devfn, where)) | 
 | 132 | 		return PCIBIOS_DEVICE_NOT_FOUND; | 
 | 133 | 	iob(); | 
 | 134 |  | 
 | 135 | 	data = le32_to_cpu(__raw_readl(pci_iospace_start)); | 
 | 136 | 	data = preprocess_write(data, val, where, size); | 
 | 137 |  | 
 | 138 | 	__raw_writel(cpu_to_le32(data), pci_iospace_start); | 
 | 139 | 	wmb(); | 
 | 140 | 	/* no way to know the access is done, we have to wait */ | 
 | 141 | 	udelay(500); | 
 | 142 | 	/* restore IO space normal behaviour */ | 
 | 143 | 	bcm_mpi_writel(0, MPI_L2PCFG_REG); | 
 | 144 |  | 
 | 145 | 	return PCIBIOS_SUCCESSFUL; | 
 | 146 | } | 
 | 147 |  | 
 | 148 | static int bcm63xx_pci_read(struct pci_bus *bus, unsigned int devfn, | 
 | 149 | 			     int where, int size, u32 *val) | 
 | 150 | { | 
 | 151 | 	int type; | 
 | 152 |  | 
 | 153 | 	type = bus->parent ? 1 : 0; | 
 | 154 |  | 
 | 155 | 	if (type == 0 && PCI_SLOT(devfn) == CARDBUS_PCI_IDSEL) | 
 | 156 | 		return PCIBIOS_DEVICE_NOT_FOUND; | 
 | 157 |  | 
 | 158 | 	return bcm63xx_do_cfg_read(type, bus->number, devfn, | 
 | 159 | 				    where, size, val); | 
 | 160 | } | 
 | 161 |  | 
 | 162 | static int bcm63xx_pci_write(struct pci_bus *bus, unsigned int devfn, | 
 | 163 | 			      int where, int size, u32 val) | 
 | 164 | { | 
 | 165 | 	int type; | 
 | 166 |  | 
 | 167 | 	type = bus->parent ? 1 : 0; | 
 | 168 |  | 
 | 169 | 	if (type == 0 && PCI_SLOT(devfn) == CARDBUS_PCI_IDSEL) | 
 | 170 | 		return PCIBIOS_DEVICE_NOT_FOUND; | 
 | 171 |  | 
 | 172 | 	return bcm63xx_do_cfg_write(type, bus->number, devfn, | 
 | 173 | 				     where, size, val); | 
 | 174 | } | 
 | 175 |  | 
 | 176 | struct pci_ops bcm63xx_pci_ops = { | 
 | 177 | 	.read   = bcm63xx_pci_read, | 
 | 178 | 	.write  = bcm63xx_pci_write | 
 | 179 | }; | 
 | 180 |  | 
 | 181 | #ifdef CONFIG_CARDBUS | 
 | 182 | /* | 
 | 183 |  * emulate configuration read access on a cardbus bridge | 
 | 184 |  */ | 
 | 185 | #define FAKE_CB_BRIDGE_SLOT	0x1e | 
 | 186 |  | 
 | 187 | static int fake_cb_bridge_bus_number = -1; | 
 | 188 |  | 
 | 189 | static struct { | 
 | 190 | 	u16 pci_command; | 
 | 191 | 	u8 cb_latency; | 
 | 192 | 	u8 subordinate_busn; | 
 | 193 | 	u8 cardbus_busn; | 
 | 194 | 	u8 pci_busn; | 
 | 195 | 	int bus_assigned; | 
 | 196 | 	u16 bridge_control; | 
 | 197 |  | 
 | 198 | 	u32 mem_base0; | 
 | 199 | 	u32 mem_limit0; | 
 | 200 | 	u32 mem_base1; | 
 | 201 | 	u32 mem_limit1; | 
 | 202 |  | 
 | 203 | 	u32 io_base0; | 
 | 204 | 	u32 io_limit0; | 
 | 205 | 	u32 io_base1; | 
 | 206 | 	u32 io_limit1; | 
 | 207 | } fake_cb_bridge_regs; | 
 | 208 |  | 
 | 209 | static int fake_cb_bridge_read(int where, int size, u32 *val) | 
 | 210 | { | 
 | 211 | 	unsigned int reg; | 
 | 212 | 	u32 data; | 
 | 213 |  | 
 | 214 | 	data = 0; | 
 | 215 | 	reg = where >> 2; | 
 | 216 | 	switch (reg) { | 
 | 217 | 	case (PCI_VENDOR_ID >> 2): | 
 | 218 | 	case (PCI_CB_SUBSYSTEM_VENDOR_ID >> 2): | 
 | 219 | 		/* create dummy vendor/device id from our cpu id */ | 
 | 220 | 		data = (bcm63xx_get_cpu_id() << 16) | PCI_VENDOR_ID_BROADCOM; | 
 | 221 | 		break; | 
 | 222 |  | 
 | 223 | 	case (PCI_COMMAND >> 2): | 
 | 224 | 		data = (PCI_STATUS_DEVSEL_SLOW << 16); | 
 | 225 | 		data |= fake_cb_bridge_regs.pci_command; | 
 | 226 | 		break; | 
 | 227 |  | 
 | 228 | 	case (PCI_CLASS_REVISION >> 2): | 
 | 229 | 		data = (PCI_CLASS_BRIDGE_CARDBUS << 16); | 
 | 230 | 		break; | 
 | 231 |  | 
 | 232 | 	case (PCI_CACHE_LINE_SIZE >> 2): | 
 | 233 | 		data = (PCI_HEADER_TYPE_CARDBUS << 16); | 
 | 234 | 		break; | 
 | 235 |  | 
 | 236 | 	case (PCI_INTERRUPT_LINE >> 2): | 
 | 237 | 		/* bridge control */ | 
 | 238 | 		data = (fake_cb_bridge_regs.bridge_control << 16); | 
 | 239 | 		/* pin:intA line:0xff */ | 
 | 240 | 		data |= (0x1 << 8) | 0xff; | 
 | 241 | 		break; | 
 | 242 |  | 
 | 243 | 	case (PCI_CB_PRIMARY_BUS >> 2): | 
 | 244 | 		data = (fake_cb_bridge_regs.cb_latency << 24); | 
 | 245 | 		data |= (fake_cb_bridge_regs.subordinate_busn << 16); | 
 | 246 | 		data |= (fake_cb_bridge_regs.cardbus_busn << 8); | 
 | 247 | 		data |= fake_cb_bridge_regs.pci_busn; | 
 | 248 | 		break; | 
 | 249 |  | 
 | 250 | 	case (PCI_CB_MEMORY_BASE_0 >> 2): | 
 | 251 | 		data = fake_cb_bridge_regs.mem_base0; | 
 | 252 | 		break; | 
 | 253 |  | 
 | 254 | 	case (PCI_CB_MEMORY_LIMIT_0 >> 2): | 
 | 255 | 		data = fake_cb_bridge_regs.mem_limit0; | 
 | 256 | 		break; | 
 | 257 |  | 
 | 258 | 	case (PCI_CB_MEMORY_BASE_1 >> 2): | 
 | 259 | 		data = fake_cb_bridge_regs.mem_base1; | 
 | 260 | 		break; | 
 | 261 |  | 
 | 262 | 	case (PCI_CB_MEMORY_LIMIT_1 >> 2): | 
 | 263 | 		data = fake_cb_bridge_regs.mem_limit1; | 
 | 264 | 		break; | 
 | 265 |  | 
 | 266 | 	case (PCI_CB_IO_BASE_0 >> 2): | 
 | 267 | 		/* | 1 for 32bits io support */ | 
 | 268 | 		data = fake_cb_bridge_regs.io_base0 | 0x1; | 
 | 269 | 		break; | 
 | 270 |  | 
 | 271 | 	case (PCI_CB_IO_LIMIT_0 >> 2): | 
 | 272 | 		data = fake_cb_bridge_regs.io_limit0; | 
 | 273 | 		break; | 
 | 274 |  | 
 | 275 | 	case (PCI_CB_IO_BASE_1 >> 2): | 
 | 276 | 		/* | 1 for 32bits io support */ | 
 | 277 | 		data = fake_cb_bridge_regs.io_base1 | 0x1; | 
 | 278 | 		break; | 
 | 279 |  | 
 | 280 | 	case (PCI_CB_IO_LIMIT_1 >> 2): | 
 | 281 | 		data = fake_cb_bridge_regs.io_limit1; | 
 | 282 | 		break; | 
 | 283 | 	} | 
 | 284 |  | 
 | 285 | 	*val = postprocess_read(data, where, size); | 
 | 286 | 	return PCIBIOS_SUCCESSFUL; | 
 | 287 | } | 
 | 288 |  | 
 | 289 | /* | 
 | 290 |  * emulate configuration write access on a cardbus bridge | 
 | 291 |  */ | 
 | 292 | static int fake_cb_bridge_write(int where, int size, u32 val) | 
 | 293 | { | 
 | 294 | 	unsigned int reg; | 
 | 295 | 	u32 data, tmp; | 
 | 296 | 	int ret; | 
 | 297 |  | 
 | 298 | 	ret = fake_cb_bridge_read((where & ~0x3), 4, &data); | 
 | 299 | 	if (ret != PCIBIOS_SUCCESSFUL) | 
 | 300 | 		return ret; | 
 | 301 |  | 
 | 302 | 	data = preprocess_write(data, val, where, size); | 
 | 303 |  | 
 | 304 | 	reg = where >> 2; | 
 | 305 | 	switch (reg) { | 
 | 306 | 	case (PCI_COMMAND >> 2): | 
 | 307 | 		fake_cb_bridge_regs.pci_command = (data & 0xffff); | 
 | 308 | 		break; | 
 | 309 |  | 
 | 310 | 	case (PCI_CB_PRIMARY_BUS >> 2): | 
 | 311 | 		fake_cb_bridge_regs.cb_latency = (data >> 24) & 0xff; | 
 | 312 | 		fake_cb_bridge_regs.subordinate_busn = (data >> 16) & 0xff; | 
 | 313 | 		fake_cb_bridge_regs.cardbus_busn = (data >> 8) & 0xff; | 
 | 314 | 		fake_cb_bridge_regs.pci_busn = data & 0xff; | 
 | 315 | 		if (fake_cb_bridge_regs.cardbus_busn) | 
 | 316 | 			fake_cb_bridge_regs.bus_assigned = 1; | 
 | 317 | 		break; | 
 | 318 |  | 
 | 319 | 	case (PCI_INTERRUPT_LINE >> 2): | 
 | 320 | 		tmp = (data >> 16) & 0xffff; | 
 | 321 | 		/* disable memory prefetch support */ | 
 | 322 | 		tmp &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM0; | 
 | 323 | 		tmp &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1; | 
 | 324 | 		fake_cb_bridge_regs.bridge_control = tmp; | 
 | 325 | 		break; | 
 | 326 |  | 
 | 327 | 	case (PCI_CB_MEMORY_BASE_0 >> 2): | 
 | 328 | 		fake_cb_bridge_regs.mem_base0 = data; | 
 | 329 | 		break; | 
 | 330 |  | 
 | 331 | 	case (PCI_CB_MEMORY_LIMIT_0 >> 2): | 
 | 332 | 		fake_cb_bridge_regs.mem_limit0 = data; | 
 | 333 | 		break; | 
 | 334 |  | 
 | 335 | 	case (PCI_CB_MEMORY_BASE_1 >> 2): | 
 | 336 | 		fake_cb_bridge_regs.mem_base1 = data; | 
 | 337 | 		break; | 
 | 338 |  | 
 | 339 | 	case (PCI_CB_MEMORY_LIMIT_1 >> 2): | 
 | 340 | 		fake_cb_bridge_regs.mem_limit1 = data; | 
 | 341 | 		break; | 
 | 342 |  | 
 | 343 | 	case (PCI_CB_IO_BASE_0 >> 2): | 
 | 344 | 		fake_cb_bridge_regs.io_base0 = data; | 
 | 345 | 		break; | 
 | 346 |  | 
 | 347 | 	case (PCI_CB_IO_LIMIT_0 >> 2): | 
 | 348 | 		fake_cb_bridge_regs.io_limit0 = data; | 
 | 349 | 		break; | 
 | 350 |  | 
 | 351 | 	case (PCI_CB_IO_BASE_1 >> 2): | 
 | 352 | 		fake_cb_bridge_regs.io_base1 = data; | 
 | 353 | 		break; | 
 | 354 |  | 
 | 355 | 	case (PCI_CB_IO_LIMIT_1 >> 2): | 
 | 356 | 		fake_cb_bridge_regs.io_limit1 = data; | 
 | 357 | 		break; | 
 | 358 | 	} | 
 | 359 |  | 
 | 360 | 	return PCIBIOS_SUCCESSFUL; | 
 | 361 | } | 
 | 362 |  | 
 | 363 | static int bcm63xx_cb_read(struct pci_bus *bus, unsigned int devfn, | 
 | 364 | 			   int where, int size, u32 *val) | 
 | 365 | { | 
 | 366 | 	/* snoop access to slot 0x1e on root bus, we fake a cardbus | 
 | 367 | 	 * bridge at this location */ | 
 | 368 | 	if (!bus->parent && PCI_SLOT(devfn) == FAKE_CB_BRIDGE_SLOT) { | 
 | 369 | 		fake_cb_bridge_bus_number = bus->number; | 
 | 370 | 		return fake_cb_bridge_read(where, size, val); | 
 | 371 | 	} | 
 | 372 |  | 
 | 373 | 	/* a  configuration  cycle for  the  device  behind the  cardbus | 
 | 374 | 	 * bridge is  actually done as a  type 0 cycle  on the primary | 
 | 375 | 	 * bus. This means that only  one device can be on the cardbus | 
 | 376 | 	 * bus */ | 
 | 377 | 	if (fake_cb_bridge_regs.bus_assigned && | 
 | 378 | 	    bus->number == fake_cb_bridge_regs.cardbus_busn && | 
 | 379 | 	    PCI_SLOT(devfn) == 0) | 
 | 380 | 		return bcm63xx_do_cfg_read(0, 0, | 
 | 381 | 					   PCI_DEVFN(CARDBUS_PCI_IDSEL, 0), | 
 | 382 | 					   where, size, val); | 
 | 383 |  | 
 | 384 | 	return PCIBIOS_DEVICE_NOT_FOUND; | 
 | 385 | } | 
 | 386 |  | 
 | 387 | static int bcm63xx_cb_write(struct pci_bus *bus, unsigned int devfn, | 
 | 388 | 			    int where, int size, u32 val) | 
 | 389 | { | 
 | 390 | 	if (!bus->parent && PCI_SLOT(devfn) == FAKE_CB_BRIDGE_SLOT) { | 
 | 391 | 		fake_cb_bridge_bus_number = bus->number; | 
 | 392 | 		return fake_cb_bridge_write(where, size, val); | 
 | 393 | 	} | 
 | 394 |  | 
 | 395 | 	if (fake_cb_bridge_regs.bus_assigned && | 
 | 396 | 	    bus->number == fake_cb_bridge_regs.cardbus_busn && | 
 | 397 | 	    PCI_SLOT(devfn) == 0) | 
 | 398 | 		return bcm63xx_do_cfg_write(0, 0, | 
 | 399 | 					    PCI_DEVFN(CARDBUS_PCI_IDSEL, 0), | 
 | 400 | 					    where, size, val); | 
 | 401 |  | 
 | 402 | 	return PCIBIOS_DEVICE_NOT_FOUND; | 
 | 403 | } | 
 | 404 |  | 
 | 405 | struct pci_ops bcm63xx_cb_ops = { | 
 | 406 | 	.read   = bcm63xx_cb_read, | 
 | 407 | 	.write   = bcm63xx_cb_write, | 
 | 408 | }; | 
 | 409 |  | 
 | 410 | /* | 
 | 411 |  * only one IO window, so it  cannot be shared by PCI and cardbus, use | 
 | 412 |  * fixup to choose and detect unhandled configuration | 
 | 413 |  */ | 
 | 414 | static void bcm63xx_fixup(struct pci_dev *dev) | 
 | 415 | { | 
 | 416 | 	static int io_window = -1; | 
 | 417 | 	int i, found, new_io_window; | 
 | 418 | 	u32 val; | 
 | 419 |  | 
 | 420 | 	/* look for any io resource */ | 
 | 421 | 	found = 0; | 
 | 422 | 	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | 
 | 423 | 		if (pci_resource_flags(dev, i) & IORESOURCE_IO) { | 
 | 424 | 			found = 1; | 
 | 425 | 			break; | 
 | 426 | 		} | 
 | 427 | 	} | 
 | 428 |  | 
 | 429 | 	if (!found) | 
 | 430 | 		return; | 
 | 431 |  | 
 | 432 | 	/* skip our fake bus with only cardbus bridge on it */ | 
 | 433 | 	if (dev->bus->number == fake_cb_bridge_bus_number) | 
 | 434 | 		return; | 
 | 435 |  | 
 | 436 | 	/* find on which bus the device is */ | 
 | 437 | 	if (fake_cb_bridge_regs.bus_assigned && | 
 | 438 | 	    dev->bus->number == fake_cb_bridge_regs.cardbus_busn && | 
 | 439 | 	    PCI_SLOT(dev->devfn) == 0) | 
 | 440 | 		new_io_window = 1; | 
 | 441 | 	else | 
 | 442 | 		new_io_window = 0; | 
 | 443 |  | 
 | 444 | 	if (new_io_window == io_window) | 
 | 445 | 		return; | 
 | 446 |  | 
 | 447 | 	if (io_window != -1) { | 
 | 448 | 		printk(KERN_ERR "bcm63xx: both PCI and cardbus devices " | 
 | 449 | 		       "need IO, which hardware cannot do\n"); | 
 | 450 | 		return; | 
 | 451 | 	} | 
 | 452 |  | 
 | 453 | 	printk(KERN_INFO "bcm63xx: PCI IO window assigned to %s\n", | 
 | 454 | 	       (new_io_window == 0) ? "PCI" : "cardbus"); | 
 | 455 |  | 
 | 456 | 	val = bcm_mpi_readl(MPI_L2PIOREMAP_REG); | 
 | 457 | 	if (io_window) | 
 | 458 | 		val |= MPI_L2PREMAP_IS_CARDBUS_MASK; | 
 | 459 | 	else | 
 | 460 | 		val &= ~MPI_L2PREMAP_IS_CARDBUS_MASK; | 
 | 461 | 	bcm_mpi_writel(val, MPI_L2PIOREMAP_REG); | 
 | 462 |  | 
 | 463 | 	io_window = new_io_window; | 
 | 464 | } | 
 | 465 |  | 
 | 466 | DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup); | 
 | 467 | #endif |