162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * SDK7786 FPGA PCIe mux handling 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2010 Paul Mundt 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#define pr_fmt(fmt) "PCI: " fmt 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/init.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/pci.h> 1262306a36Sopenharmony_ci#include <mach/fpga.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* 1562306a36Sopenharmony_ci * The SDK7786 FPGA supports mangling of most of the slots in some way or 1662306a36Sopenharmony_ci * another. Slots 3/4 are special in that only one can be supported at a 1762306a36Sopenharmony_ci * time, and both appear on port 3 to the PCI bus scan. Enabling slot 4 1862306a36Sopenharmony_ci * (the horizontal edge connector) will disable slot 3 entirely. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * Misconfigurations can be detected through the FPGA via the slot 2162306a36Sopenharmony_ci * resistors to determine card presence. Hotplug remains unsupported. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_cistatic unsigned int slot4en __initdata; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cichar *__init pcibios_setup(char *str) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci if (strcmp(str, "slot4en") == 0) { 2862306a36Sopenharmony_ci slot4en = 1; 2962306a36Sopenharmony_ci return NULL; 3062306a36Sopenharmony_ci } 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci return str; 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic int __init sdk7786_pci_init(void) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci u16 data = fpga_read_reg(PCIECR); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci /* 4062306a36Sopenharmony_ci * Enable slot #4 if it's been specified on the command line. 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * Optionally reroute if slot #4 has a card present while slot #3 4362306a36Sopenharmony_ci * does not, regardless of command line value. 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * Card presence is logically inverted. 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci slot4en ?: (!(data & PCIECR_PRST4) && (data & PCIECR_PRST3)); 4862306a36Sopenharmony_ci if (slot4en) { 4962306a36Sopenharmony_ci pr_info("Activating PCIe slot#4 (disabling slot#3)\n"); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci data &= ~PCIECR_PCIEMUX1; 5262306a36Sopenharmony_ci fpga_write_reg(data, PCIECR); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci /* Warn about forced rerouting if slot#3 is occupied */ 5562306a36Sopenharmony_ci if ((data & PCIECR_PRST3) == 0) { 5662306a36Sopenharmony_ci pr_warn("Unreachable card detected in slot#3\n"); 5762306a36Sopenharmony_ci return -EBUSY; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci } else 6062306a36Sopenharmony_ci pr_info("PCIe slot#4 disabled\n"); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci return 0; 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_cipostcore_initcall(sdk7786_pci_init); 65