1 /* 2 * SDK7786 FPGA PCIe mux handling 3 * 4 * Copyright (C) 2010 Paul Mundt 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 */ 10 #define pr_fmt(fmt) "PCI: " fmt 11 12 #include <linux/init.h> 13 #include <linux/kernel.h> 14 #include <linux/pci.h> 15 #include <mach/fpga.h> 16 17 /* 18 * The SDK7786 FPGA supports mangling of most of the slots in some way or 19 * another. Slots 3/4 are special in that only one can be supported at a 20 * time, and both appear on port 3 to the PCI bus scan. Enabling slot 4 21 * (the horizontal edge connector) will disable slot 3 entirely. 22 * 23 * Misconfigurations can be detected through the FPGA via the slot 24 * resistors to determine card presence. Hotplug remains unsupported. 25 */ 26 static unsigned int slot4en __initdata; 27 28 char *__init pcibios_setup(char *str) 29 { 30 if (strcmp(str, "slot4en") == 0) { 31 slot4en = 1; 32 return NULL; 33 } 34 35 return str; 36 } 37 38 static int __init sdk7786_pci_init(void) 39 { 40 u16 data = fpga_read_reg(PCIECR); 41 42 /* 43 * Enable slot #4 if it's been specified on the command line. 44 * 45 * Optionally reroute if slot #4 has a card present while slot #3 46 * does not, regardless of command line value. 47 * 48 * Card presence is logically inverted. 49 */ 50 slot4en ?: (!(data & PCIECR_PRST4) && (data & PCIECR_PRST3)); 51 if (slot4en) { 52 pr_info("Activating PCIe slot#4 (disabling slot#3)\n"); 53 54 data &= ~PCIECR_PCIEMUX1; 55 fpga_write_reg(data, PCIECR); 56 57 /* Warn about forced rerouting if slot#3 is occupied */ 58 if ((data & PCIECR_PRST3) == 0) { 59 pr_warning("Unreachable card detected in slot#3\n"); 60 return -EBUSY; 61 } 62 } else 63 pr_info("PCIe slot#4 disabled\n"); 64 65 return 0; 66 } 67 postcore_initcall(sdk7786_pci_init); 68