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