linux/drivers/pci/controller/pci-tegra.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * PCIe host controller driver for Tegra SoCs
 *
 * Copyright (c) 2010, CompuLab, Ltd.
 * Author: Mike Rapoport <[email protected]>
 *
 * Based on NVIDIA PCIe driver
 * Copyright (c) 2008-2009, NVIDIA Corporation.
 *
 * Bits taken from arch/arm/mach-dove/pcie.c
 *
 * Author: Thierry Reding <[email protected]>
 */

#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/pci.h>
#include <linux/phy/phy.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/regulator/consumer.h>

#include <soc/tegra/cpuidle.h>
#include <soc/tegra/pmc.h>

#include "../pci.h"

#define INT_PCI_MSI_NR

/* register definitions */

#define AFI_AXI_BAR0_SZ
#define AFI_AXI_BAR1_SZ
#define AFI_AXI_BAR2_SZ
#define AFI_AXI_BAR3_SZ
#define AFI_AXI_BAR4_SZ
#define AFI_AXI_BAR5_SZ

#define AFI_AXI_BAR0_START
#define AFI_AXI_BAR1_START
#define AFI_AXI_BAR2_START
#define AFI_AXI_BAR3_START
#define AFI_AXI_BAR4_START
#define AFI_AXI_BAR5_START

#define AFI_FPCI_BAR0
#define AFI_FPCI_BAR1
#define AFI_FPCI_BAR2
#define AFI_FPCI_BAR3
#define AFI_FPCI_BAR4
#define AFI_FPCI_BAR5

#define AFI_CACHE_BAR0_SZ
#define AFI_CACHE_BAR0_ST
#define AFI_CACHE_BAR1_SZ
#define AFI_CACHE_BAR1_ST

#define AFI_MSI_BAR_SZ
#define AFI_MSI_FPCI_BAR_ST
#define AFI_MSI_AXI_BAR_ST

#define AFI_MSI_VEC(x)
#define AFI_MSI_EN_VEC(x)

#define AFI_CONFIGURATION
#define AFI_CONFIGURATION_EN_FPCI
#define AFI_CONFIGURATION_CLKEN_OVERRIDE

#define AFI_FPCI_ERROR_MASKS

#define AFI_INTR_MASK
#define AFI_INTR_MASK_INT_MASK
#define AFI_INTR_MASK_MSI_MASK

#define AFI_INTR_CODE
#define AFI_INTR_CODE_MASK
#define AFI_INTR_INI_SLAVE_ERROR
#define AFI_INTR_INI_DECODE_ERROR
#define AFI_INTR_TARGET_ABORT
#define AFI_INTR_MASTER_ABORT
#define AFI_INTR_INVALID_WRITE
#define AFI_INTR_LEGACY
#define AFI_INTR_FPCI_DECODE_ERROR
#define AFI_INTR_AXI_DECODE_ERROR
#define AFI_INTR_FPCI_TIMEOUT
#define AFI_INTR_PE_PRSNT_SENSE
#define AFI_INTR_PE_CLKREQ_SENSE
#define AFI_INTR_CLKCLAMP_SENSE
#define AFI_INTR_RDY4PD_SENSE
#define AFI_INTR_P2P_ERROR

#define AFI_INTR_SIGNATURE
#define AFI_UPPER_FPCI_ADDRESS
#define AFI_SM_INTR_ENABLE
#define AFI_SM_INTR_INTA_ASSERT
#define AFI_SM_INTR_INTB_ASSERT
#define AFI_SM_INTR_INTC_ASSERT
#define AFI_SM_INTR_INTD_ASSERT
#define AFI_SM_INTR_INTA_DEASSERT
#define AFI_SM_INTR_INTB_DEASSERT
#define AFI_SM_INTR_INTC_DEASSERT
#define AFI_SM_INTR_INTD_DEASSERT

#define AFI_AFI_INTR_ENABLE
#define AFI_INTR_EN_INI_SLVERR
#define AFI_INTR_EN_INI_DECERR
#define AFI_INTR_EN_TGT_SLVERR
#define AFI_INTR_EN_TGT_DECERR
#define AFI_INTR_EN_TGT_WRERR
#define AFI_INTR_EN_DFPCI_DECERR
#define AFI_INTR_EN_AXI_DECERR
#define AFI_INTR_EN_FPCI_TIMEOUT
#define AFI_INTR_EN_PRSNT_SENSE

#define AFI_PCIE_PME

#define AFI_PCIE_CONFIG
#define AFI_PCIE_CONFIG_PCIE_DISABLE(x)
#define AFI_PCIE_CONFIG_PCIE_DISABLE_ALL
#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK
#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE
#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420
#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1
#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_401
#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL
#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222
#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1
#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211
#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411
#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_111
#define AFI_PCIE_CONFIG_PCIE_CLKREQ_GPIO(x)
#define AFI_PCIE_CONFIG_PCIE_CLKREQ_GPIO_ALL

#define AFI_FUSE
#define AFI_FUSE_PCIE_T0_GEN2_DIS

#define AFI_PEX0_CTRL
#define AFI_PEX1_CTRL
#define AFI_PEX_CTRL_RST
#define AFI_PEX_CTRL_CLKREQ_EN
#define AFI_PEX_CTRL_REFCLK_EN
#define AFI_PEX_CTRL_OVERRIDE_EN

#define AFI_PLLE_CONTROL
#define AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL
#define AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN

#define AFI_PEXBIAS_CTRL_0

#define RP_ECTL_2_R1
#define RP_ECTL_2_R1_RX_CTLE_1C_MASK

#define RP_ECTL_4_R1
#define RP_ECTL_4_R1_RX_CDR_CTRL_1C_MASK
#define RP_ECTL_4_R1_RX_CDR_CTRL_1C_SHIFT

#define RP_ECTL_5_R1
#define RP_ECTL_5_R1_RX_EQ_CTRL_L_1C_MASK

#define RP_ECTL_6_R1
#define RP_ECTL_6_R1_RX_EQ_CTRL_H_1C_MASK

#define RP_ECTL_2_R2
#define RP_ECTL_2_R2_RX_CTLE_1C_MASK

#define RP_ECTL_4_R2
#define RP_ECTL_4_R2_RX_CDR_CTRL_1C_MASK
#define RP_ECTL_4_R2_RX_CDR_CTRL_1C_SHIFT

#define RP_ECTL_5_R2
#define RP_ECTL_5_R2_RX_EQ_CTRL_L_1C_MASK

#define RP_ECTL_6_R2
#define RP_ECTL_6_R2_RX_EQ_CTRL_H_1C_MASK

#define RP_VEND_XP
#define RP_VEND_XP_DL_UP
#define RP_VEND_XP_OPPORTUNISTIC_ACK
#define RP_VEND_XP_OPPORTUNISTIC_UPDATEFC
#define RP_VEND_XP_UPDATE_FC_THRESHOLD_MASK

#define RP_VEND_CTL0
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH_MASK
#define RP_VEND_CTL0_DSK_RST_PULSE_WIDTH

#define RP_VEND_CTL1
#define RP_VEND_CTL1_ERPT

#define RP_VEND_XP_BIST
#define RP_VEND_XP_BIST_GOTO_L1_L2_AFTER_DLLP_DONE

#define RP_VEND_CTL2
#define RP_VEND_CTL2_PCA_ENABLE

#define RP_PRIV_MISC
#define RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT
#define RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT
#define RP_PRIV_MISC_CTLR_CLK_CLAMP_THRESHOLD_MASK
#define RP_PRIV_MISC_CTLR_CLK_CLAMP_THRESHOLD
#define RP_PRIV_MISC_CTLR_CLK_CLAMP_ENABLE
#define RP_PRIV_MISC_TMS_CLK_CLAMP_THRESHOLD_MASK
#define RP_PRIV_MISC_TMS_CLK_CLAMP_THRESHOLD
#define RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE

#define RP_LINK_CONTROL_STATUS
#define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE
#define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK

#define RP_LINK_CONTROL_STATUS_2

#define PADS_CTL_SEL

#define PADS_CTL
#define PADS_CTL_IDDQ_1L
#define PADS_CTL_TX_DATA_EN_1L
#define PADS_CTL_RX_DATA_EN_1L

#define PADS_PLL_CTL_TEGRA20
#define PADS_PLL_CTL_TEGRA30
#define PADS_PLL_CTL_RST_B4SM
#define PADS_PLL_CTL_LOCKDET
#define PADS_PLL_CTL_REFCLK_MASK
#define PADS_PLL_CTL_REFCLK_INTERNAL_CML
#define PADS_PLL_CTL_REFCLK_INTERNAL_CMOS
#define PADS_PLL_CTL_REFCLK_EXTERNAL
#define PADS_PLL_CTL_TXCLKREF_MASK
#define PADS_PLL_CTL_TXCLKREF_DIV10
#define PADS_PLL_CTL_TXCLKREF_DIV5
#define PADS_PLL_CTL_TXCLKREF_BUF_EN

#define PADS_REFCLK_CFG0
#define PADS_REFCLK_CFG1
#define PADS_REFCLK_BIAS

/*
 * Fields in PADS_REFCLK_CFG*. Those registers form an array of 16-bit
 * entries, one entry per PCIe port. These field definitions and desired
 * values aren't in the TRM, but do come from NVIDIA.
 */
#define PADS_REFCLK_CFG_TERM_SHIFT
#define PADS_REFCLK_CFG_E_TERM_SHIFT
#define PADS_REFCLK_CFG_PREDI_SHIFT
#define PADS_REFCLK_CFG_DRVI_SHIFT

#define PME_ACK_TIMEOUT
#define LINK_RETRAIN_TIMEOUT

struct tegra_msi {};

/* used to differentiate between Tegra SoC generations */
struct tegra_pcie_port_soc {};

struct tegra_pcie_soc {};

struct tegra_pcie {};

static inline struct tegra_pcie *msi_to_pcie(struct tegra_msi *msi)
{}

struct tegra_pcie_port {};

static inline void afi_writel(struct tegra_pcie *pcie, u32 value,
			      unsigned long offset)
{}

static inline u32 afi_readl(struct tegra_pcie *pcie, unsigned long offset)
{}

static inline void pads_writel(struct tegra_pcie *pcie, u32 value,
			       unsigned long offset)
{}

static inline u32 pads_readl(struct tegra_pcie *pcie, unsigned long offset)
{}

/*
 * The configuration space mapping on Tegra is somewhat similar to the ECAM
 * defined by PCIe. However it deviates a bit in how the 4 bits for extended
 * register accesses are mapped:
 *
 *    [27:24] extended register number
 *    [23:16] bus number
 *    [15:11] device number
 *    [10: 8] function number
 *    [ 7: 0] register number
 *
 * Mapping the whole extended configuration space would require 256 MiB of
 * virtual address space, only a small part of which will actually be used.
 *
 * To work around this, a 4 KiB region is used to generate the required
 * configuration transaction with relevant B:D:F and register offset values.
 * This is achieved by dynamically programming base address and size of
 * AFI_AXI_BAR used for end point config space mapping to make sure that the
 * address (access to which generates correct config transaction) falls in
 * this 4 KiB region.
 */
static unsigned int tegra_pcie_conf_offset(u8 bus, unsigned int devfn,
					   unsigned int where)
{}

static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus,
					unsigned int devfn,
					int where)
{}

static int tegra_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
				  int where, int size, u32 *value)
{}

static int tegra_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
				   int where, int size, u32 value)
{}

static struct pci_ops tegra_pcie_ops =;

static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port)
{}

static void tegra_pcie_port_reset(struct tegra_pcie_port *port)
{}

static void tegra_pcie_enable_rp_features(struct tegra_pcie_port *port)
{}

static void tegra_pcie_program_ectl_settings(struct tegra_pcie_port *port)
{}

static void tegra_pcie_apply_sw_fixup(struct tegra_pcie_port *port)
{}

static void tegra_pcie_port_enable(struct tegra_pcie_port *port)
{}

static void tegra_pcie_port_disable(struct tegra_pcie_port *port)
{}

static void tegra_pcie_port_free(struct tegra_pcie_port *port)
{}

/* Tegra PCIE root complex wrongly reports device class */
static void tegra_pcie_fixup_class(struct pci_dev *dev)
{}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf0, tegra_pcie_fixup_class);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0e1c, tegra_pcie_fixup_class);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0e1d, tegra_pcie_fixup_class);

/* Tegra20 and Tegra30 PCIE requires relaxed ordering */
static void tegra_pcie_relax_enable(struct pci_dev *dev)
{}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0bf0, tegra_pcie_relax_enable);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_relax_enable);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0e1c, tegra_pcie_relax_enable);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0e1d, tegra_pcie_relax_enable);

static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
{}

static irqreturn_t tegra_pcie_isr(int irq, void *arg)
{}

/*
 * FPCI map is as follows:
 * - 0xfdfc000000: I/O space
 * - 0xfdfe000000: type 0 configuration space
 * - 0xfdff000000: type 1 configuration space
 * - 0xfe00000000: type 0 extended configuration space
 * - 0xfe10000000: type 1 extended configuration space
 */
static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
{}

static int tegra_pcie_pll_wait(struct tegra_pcie *pcie, unsigned long timeout)
{}

static int tegra_pcie_phy_enable(struct tegra_pcie *pcie)
{}

static int tegra_pcie_phy_disable(struct tegra_pcie *pcie)
{}

static int tegra_pcie_port_phy_power_on(struct tegra_pcie_port *port)
{}

static int tegra_pcie_port_phy_power_off(struct tegra_pcie_port *port)
{}

static int tegra_pcie_phy_power_on(struct tegra_pcie *pcie)
{}

static int tegra_pcie_phy_power_off(struct tegra_pcie *pcie)
{}

static void tegra_pcie_enable_controller(struct tegra_pcie *pcie)
{}

static void tegra_pcie_power_off(struct tegra_pcie *pcie)
{}

static int tegra_pcie_power_on(struct tegra_pcie *pcie)
{}

static void tegra_pcie_apply_pad_settings(struct tegra_pcie *pcie)
{}

static int tegra_pcie_clocks_get(struct tegra_pcie *pcie)
{}

static int tegra_pcie_resets_get(struct tegra_pcie *pcie)
{}

static int tegra_pcie_phys_get_legacy(struct tegra_pcie *pcie)
{}

static struct phy *devm_of_phy_optional_get_index(struct device *dev,
						  struct device_node *np,
						  const char *consumer,
						  unsigned int index)
{}

static int tegra_pcie_port_get_phys(struct tegra_pcie_port *port)
{}

static int tegra_pcie_phys_get(struct tegra_pcie *pcie)
{}

static void tegra_pcie_phys_put(struct tegra_pcie *pcie)
{}

static int tegra_pcie_get_resources(struct tegra_pcie *pcie)
{}

static int tegra_pcie_put_resources(struct tegra_pcie *pcie)
{}

static void tegra_pcie_pme_turnoff(struct tegra_pcie_port *port)
{}

static void tegra_pcie_msi_irq(struct irq_desc *desc)
{}

static void tegra_msi_top_irq_ack(struct irq_data *d)
{}

static void tegra_msi_top_irq_mask(struct irq_data *d)
{}

static void tegra_msi_top_irq_unmask(struct irq_data *d)
{}

static struct irq_chip tegra_msi_top_chip =;

static void tegra_msi_irq_ack(struct irq_data *d)
{}

static void tegra_msi_irq_mask(struct irq_data *d)
{}

static void tegra_msi_irq_unmask(struct irq_data *d)
{}

static int tegra_msi_set_affinity(struct irq_data *d, const struct cpumask *mask, bool force)
{}

static void tegra_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
{}

static struct irq_chip tegra_msi_bottom_chip =;

static int tegra_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
				  unsigned int nr_irqs, void *args)
{}

static void tegra_msi_domain_free(struct irq_domain *domain, unsigned int virq,
				  unsigned int nr_irqs)
{}

static const struct irq_domain_ops tegra_msi_domain_ops =;

static struct msi_domain_info tegra_msi_info =;

static int tegra_allocate_domains(struct tegra_msi *msi)
{}

static void tegra_free_domains(struct tegra_msi *msi)
{}

static int tegra_pcie_msi_setup(struct tegra_pcie *pcie)
{}

static void tegra_pcie_enable_msi(struct tegra_pcie *pcie)
{}

static void tegra_pcie_msi_teardown(struct tegra_pcie *pcie)
{}

static int tegra_pcie_disable_msi(struct tegra_pcie *pcie)
{}

static void tegra_pcie_disable_interrupts(struct tegra_pcie *pcie)
{}

static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
				      u32 *xbar)
{}

/*
 * Check whether a given set of supplies is available in a device tree node.
 * This is used to check whether the new or the legacy device tree bindings
 * should be used.
 */
static bool of_regulator_bulk_available(struct device_node *np,
					struct regulator_bulk_data *supplies,
					unsigned int num_supplies)
{}

/*
 * Old versions of the device tree binding for this device used a set of power
 * supplies that didn't match the hardware inputs. This happened to work for a
 * number of cases but is not future proof. However to preserve backwards-
 * compatibility with old device trees, this function will try to use the old
 * set of supplies.
 */
static int tegra_pcie_get_legacy_regulators(struct tegra_pcie *pcie)
{}

/*
 * Obtains the list of regulators required for a particular generation of the
 * IP block.
 *
 * This would've been nice to do simply by providing static tables for use
 * with the regulator_bulk_*() API, but unfortunately Tegra30 is a bit quirky
 * in that it has two pairs or AVDD_PEX and VDD_PEX supplies (PEXA and PEXB)
 * and either seems to be optional depending on which ports are being used.
 */
static int tegra_pcie_get_regulators(struct tegra_pcie *pcie, u32 lane_mask)
{}

static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
{}

/*
 * FIXME: If there are no PCIe cards attached, then calling this function
 * can result in the increase of the bootup time as there are big timeout
 * loops.
 */
#define TEGRA_PCIE_LINKUP_TIMEOUT
static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port)
{}

static void tegra_pcie_change_link_speed(struct tegra_pcie *pcie)
{}

static void tegra_pcie_enable_ports(struct tegra_pcie *pcie)
{}

static void tegra_pcie_disable_ports(struct tegra_pcie *pcie)
{}

static const struct tegra_pcie_port_soc tegra20_pcie_ports[] =;

static const struct tegra_pcie_soc tegra20_pcie =;

static const struct tegra_pcie_port_soc tegra30_pcie_ports[] =;

static const struct tegra_pcie_soc tegra30_pcie =;

static const struct tegra_pcie_soc tegra124_pcie =;

static const struct tegra_pcie_soc tegra210_pcie =;

static const struct tegra_pcie_port_soc tegra186_pcie_ports[] =;

static const struct tegra_pcie_soc tegra186_pcie =;

static const struct of_device_id tegra_pcie_of_match[] =;
MODULE_DEVICE_TABLE(of, tegra_pcie_of_match);

static void *tegra_pcie_ports_seq_start(struct seq_file *s, loff_t *pos)
{}

static void *tegra_pcie_ports_seq_next(struct seq_file *s, void *v, loff_t *pos)
{}

static void tegra_pcie_ports_seq_stop(struct seq_file *s, void *v)
{}

static int tegra_pcie_ports_seq_show(struct seq_file *s, void *v)
{}

static const struct seq_operations tegra_pcie_ports_sops =;

DEFINE_SEQ_ATTRIBUTE();

static void tegra_pcie_debugfs_exit(struct tegra_pcie *pcie)
{}

static void tegra_pcie_debugfs_init(struct tegra_pcie *pcie)
{}

static int tegra_pcie_probe(struct platform_device *pdev)
{}

static void tegra_pcie_remove(struct platform_device *pdev)
{}

static int tegra_pcie_pm_suspend(struct device *dev)
{}

static int tegra_pcie_pm_resume(struct device *dev)
{}

static const struct dev_pm_ops tegra_pcie_pm_ops =;

static struct platform_driver tegra_pcie_driver =;
module_platform_driver();