1ff4a7481SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0 261a46766SPaul Mundt /* 361a46766SPaul Mundt * SDK7786 FPGA PCIe mux handling 461a46766SPaul Mundt * 561a46766SPaul Mundt * Copyright (C) 2010 Paul Mundt 661a46766SPaul Mundt */ 761a46766SPaul Mundt #define pr_fmt(fmt) "PCI: " fmt 861a46766SPaul Mundt 961a46766SPaul Mundt #include <linux/init.h> 1061a46766SPaul Mundt #include <linux/kernel.h> 1161a46766SPaul Mundt #include <linux/pci.h> 1261a46766SPaul Mundt #include <mach/fpga.h> 1361a46766SPaul Mundt 1461a46766SPaul Mundt /* 1561a46766SPaul Mundt * The SDK7786 FPGA supports mangling of most of the slots in some way or 1661a46766SPaul Mundt * another. Slots 3/4 are special in that only one can be supported at a 1761a46766SPaul Mundt * time, and both appear on port 3 to the PCI bus scan. Enabling slot 4 1861a46766SPaul Mundt * (the horizontal edge connector) will disable slot 3 entirely. 1961a46766SPaul Mundt * 2061a46766SPaul Mundt * Misconfigurations can be detected through the FPGA via the slot 2161a46766SPaul Mundt * resistors to determine card presence. Hotplug remains unsupported. 2261a46766SPaul Mundt */ 23ce8dd71aSMyron Stowe static unsigned int slot4en __initdata; 2461a46766SPaul Mundt pcibios_setup(char * str)25ce8dd71aSMyron Stowechar *__init pcibios_setup(char *str) 2661a46766SPaul Mundt { 2761a46766SPaul Mundt if (strcmp(str, "slot4en") == 0) { 2861a46766SPaul Mundt slot4en = 1; 2961a46766SPaul Mundt return NULL; 3061a46766SPaul Mundt } 3161a46766SPaul Mundt 3261a46766SPaul Mundt return str; 3361a46766SPaul Mundt } 3461a46766SPaul Mundt sdk7786_pci_init(void)3561a46766SPaul Mundtstatic int __init sdk7786_pci_init(void) 3661a46766SPaul Mundt { 3761a46766SPaul Mundt u16 data = fpga_read_reg(PCIECR); 3861a46766SPaul Mundt 3961a46766SPaul Mundt /* 4061a46766SPaul Mundt * Enable slot #4 if it's been specified on the command line. 4161a46766SPaul Mundt * 4261a46766SPaul Mundt * Optionally reroute if slot #4 has a card present while slot #3 4361a46766SPaul Mundt * does not, regardless of command line value. 4461a46766SPaul Mundt * 4561a46766SPaul Mundt * Card presence is logically inverted. 4661a46766SPaul Mundt */ 4761a46766SPaul Mundt slot4en ?: (!(data & PCIECR_PRST4) && (data & PCIECR_PRST3)); 4861a46766SPaul Mundt if (slot4en) { 4961a46766SPaul Mundt pr_info("Activating PCIe slot#4 (disabling slot#3)\n"); 5061a46766SPaul Mundt 5161a46766SPaul Mundt data &= ~PCIECR_PCIEMUX1; 5261a46766SPaul Mundt fpga_write_reg(data, PCIECR); 5361a46766SPaul Mundt 5461a46766SPaul Mundt /* Warn about forced rerouting if slot#3 is occupied */ 5561a46766SPaul Mundt if ((data & PCIECR_PRST3) == 0) { 56*6d80f20cSKefeng Wang pr_warn("Unreachable card detected in slot#3\n"); 5761a46766SPaul Mundt return -EBUSY; 5861a46766SPaul Mundt } 5961a46766SPaul Mundt } else 6061a46766SPaul Mundt pr_info("PCIe slot#4 disabled\n"); 6161a46766SPaul Mundt 6261a46766SPaul Mundt return 0; 6361a46766SPaul Mundt } 6461a46766SPaul Mundt postcore_initcall(sdk7786_pci_init); 65