diff options
| author | Linus Torvalds <[email protected]> | 2021-11-06 14:36:12 -0700 | 
|---|---|---|
| committer | Linus Torvalds <[email protected]> | 2021-11-06 14:36:12 -0700 | 
| commit | 0c5c62ddf88c34bc83b66e4ac9beb2bb0e1887d4 (patch) | |
| tree | f1043e124056c7f2a061f2d2e5240aa687534633 /drivers/pci/controller/pci-aardvark.c | |
| parent | 512b7931ad0561ffe14265f9ff554a3c081b476b (diff) | |
| parent | dda4b381f05d447a0ae31e2e44aeb35d313a311f (diff) | |
Merge tag 'pci-v5.16-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull pci updates from Bjorn Helgaas:
 "Enumeration:
   - Conserve IRQs by setting up portdrv IRQs only when there are users
     (Jan Kiszka)
   - Rework and simplify _OSC negotiation for control of PCIe features
     (Joerg Roedel)
   - Remove struct pci_dev.driver pointer since it's redundant with the
     struct device.driver pointer (Uwe Kleine-König)
  Resource management:
   - Coalesce contiguous host bridge apertures from _CRS to accommodate
     BARs that cover more than one aperture (Kai-Heng Feng)
  Sysfs:
   - Check CAP_SYS_ADMIN before parsing user input (Krzysztof
     Wilczyński)
   - Return -EINVAL consistently from "store" functions (Krzysztof
     Wilczyński)
   - Use sysfs_emit() in endpoint "show" functions to avoid buffer
     overruns (Kunihiko Hayashi)
  PCIe native device hotplug:
   - Ignore Link Down/Up caused by resets during error recovery so
     endpoint drivers can remain bound to the device (Lukas Wunner)
  Virtualization:
   - Avoid bus resets on Atheros QCA6174, where they hang the device
     (Ingmar Klein)
   - Work around Pericom PI7C9X2G switch packet drop erratum by using
     store and forward mode instead of cut-through (Nathan Rossi)
   - Avoid trying to enable AtomicOps on VFs; the PF setting applies to
     all VFs (Selvin Xavier)
  MSI:
   - Document that /sys/bus/pci/devices/.../irq contains the legacy INTx
     interrupt or the IRQ of the first MSI (not MSI-X) vector (Barry
     Song)
  VPD:
   - Add pci_read_vpd_any() and pci_write_vpd_any() to access anywhere
     in the possible VPD space; use these to simplify the cxgb3 driver
     (Heiner Kallweit)
  Peer-to-peer DMA:
   - Add (not subtract) the bus offset when calculating DMA address
     (Wang Lu)
  ASPM:
   - Re-enable LTR at Downstream Ports so they don't report Unsupported
     Requests when reset or hot-added devices send LTR messages
     (Mingchuang Qiao)
  Apple PCIe controller driver:
   - Add driver for Apple M1 PCIe controller (Alyssa Rosenzweig, Marc
     Zyngier)
  Cadence PCIe controller driver:
   - Return success when probe succeeds instead of falling into error
     path (Li Chen)
  HiSilicon Kirin PCIe controller driver:
   - Reorganize PHY logic and add support for external PHY drivers
     (Mauro Carvalho Chehab)
   - Support PERST# GPIOs for HiKey970 external PEX 8606 bridge (Mauro
     Carvalho Chehab)
   - Add Kirin 970 support (Mauro Carvalho Chehab)
   - Make driver removable (Mauro Carvalho Chehab)
  Intel VMD host bridge driver:
   - If IOMMU supports interrupt remapping, leave VMD MSI-X remapping
     enabled (Adrian Huang)
   - Number each controller so we can tell them apart in
     /proc/interrupts (Chunguang Xu)
   - Avoid building on UML because VMD depends on x86 bare metal APIs
     (Johannes Berg)
  Marvell Aardvark PCIe controller driver:
   - Define macros for PCI_EXP_DEVCTL_PAYLOAD_* (Pali Rohár)
   - Set Max Payload Size to 512 bytes per Marvell spec (Pali Rohár)
   - Downgrade PIO Response Status messages to debug level (Marek Behún)
   - Preserve CRS SV (Config Request Retry Software Visibility) bit in
     emulated Root Control register (Pali Rohár)
   - Fix issue in configuring reference clock (Pali Rohár)
   - Don't clear status bits for masked interrupts (Pali Rohár)
   - Don't mask unused interrupts (Pali Rohár)
   - Avoid code repetition in advk_pcie_rd_conf() (Marek Behún)
   - Retry config accesses on CRS response (Pali Rohár)
   - Simplify emulated Root Capabilities initialization (Pali Rohár)
   - Fix several link training issues (Pali Rohár)
   - Fix link-up checking via LTSSM (Pali Rohár)
   - Fix reporting of Data Link Layer Link Active (Pali Rohár)
   - Fix emulation of W1C bits (Marek Behún)
   - Fix MSI domain .alloc() method to return zero on success (Marek
     Behún)
   - Read entire 16-bit MSI vector in MSI handler, not just low 8 bits
     (Marek Behún)
   - Clear Root Port I/O Space, Memory Space, and Bus Master Enable bits
     at startup; PCI core will set those as necessary (Pali Rohár)
   - When operating as a Root Port, set class code to "PCI Bridge"
     instead of the default "Mass Storage Controller" (Pali Rohár)
   - Add emulation for PCI_BRIDGE_CTL_BUS_RESET since aardvark doesn't
     implement this per spec (Pali Rohár)
   - Add emulation of option ROM BAR since aardvark doesn't implement
     this per spec (Pali Rohár)
  MediaTek MT7621 PCIe controller driver:
   - Add MediaTek MT7621 PCIe host controller driver and DT binding
     (Sergio Paracuellos)
  Qualcomm PCIe controller driver:
   - Add SC8180x compatible string (Bjorn Andersson)
   - Add endpoint controller driver and DT binding (Manivannan
     Sadhasivam)
   - Restructure to use of_device_get_match_data() (Prasad Malisetty)
   - Add SC7280-specific pcie_1_pipe_clk_src handling (Prasad Malisetty)
  Renesas R-Car PCIe controller driver:
   - Remove unnecessary includes (Geert Uytterhoeven)
  Rockchip DesignWare PCIe controller driver:
   - Add DT binding (Simon Xue)
  Socionext UniPhier Pro5 controller driver:
   - Serialize INTx masking/unmasking (Kunihiko Hayashi)
  Synopsys DesignWare PCIe controller driver:
   - Run dwc .host_init() method before registering MSI interrupt
     handler so we can deal with pending interrupts left by bootloader
     (Bjorn Andersson)
   - Clean up Kconfig dependencies (Andy Shevchenko)
   - Export symbols to allow more modular drivers (Luca Ceresoli)
  TI DRA7xx PCIe controller driver:
   - Allow host and endpoint drivers to be modules (Luca Ceresoli)
   - Enable external clock if present (Luca Ceresoli)
  TI J721E PCIe driver:
   - Disable PHY when probe fails after initializing it (Christophe
     JAILLET)
  MicroSemi Switchtec management driver:
   - Return error to application when command execution fails because an
     out-of-band reset has cleared the device BARs, Memory Space Enable,
     etc (Kelvin Cao)
   - Fix MRPC error status handling issue (Kelvin Cao)
   - Mask out other bits when reading of management VEP instance ID
     (Kelvin Cao)
   - Return EOPNOTSUPP instead of ENOTSUPP from sysfs show functions
     (Kelvin Cao)
   - Add check of event support (Logan Gunthorpe)
  Miscellaneous:
   - Remove unused pci_pool wrappers, which have been replaced by
     dma_pool (Cai Huoqing)
   - Use 'unsigned int' instead of bare 'unsigned' (Krzysztof
     Wilczyński)
   - Use kstrtobool() directly, sans strtobool() wrapper (Krzysztof
     Wilczyński)
   - Fix some sscanf(), sprintf() format mismatches (Krzysztof
     Wilczyński)
   - Update PCI subsystem information in MAINTAINERS (Krzysztof
     Wilczyński)
   - Correct some misspellings (Krzysztof Wilczyński)"
* tag 'pci-v5.16-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (137 commits)
  PCI: Add ACS quirk for Pericom PI7C9X2G switches
  PCI: apple: Configure RID to SID mapper on device addition
  iommu/dart: Exclude MSI doorbell from PCIe device IOVA range
  PCI: apple: Implement MSI support
  PCI: apple: Add INTx and per-port interrupt support
  PCI: kirin: Allow removing the driver
  PCI: kirin: De-init the dwc driver
  PCI: kirin: Disable clkreq during poweroff sequence
  PCI: kirin: Move the power-off code to a common routine
  PCI: kirin: Add power_off support for Kirin 960 PHY
  PCI: kirin: Allow building it as a module
  PCI: kirin: Add MODULE_* macros
  PCI: kirin: Add Kirin 970 compatible
  PCI: kirin: Support PERST# GPIOs for HiKey970 external PEX 8606 bridge
  PCI: apple: Set up reference clocks when probing
  PCI: apple: Add initial hardware bring-up
  PCI: of: Allow matching of an interrupt-map local to a PCI device
  of/irq: Allow matching of an interrupt-map local to an interrupt controller
  irqdomain: Make of_phandle_args_to_fwspec() generally available
  PCI: Do not enable AtomicOps on VFs
  ...
Diffstat (limited to 'drivers/pci/controller/pci-aardvark.c')
| -rw-r--r-- | drivers/pci/controller/pci-aardvark.c | 491 | 
1 files changed, 312 insertions, 179 deletions
| diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c index 596ebcfcc82d..c5300d49807a 100644 --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c @@ -31,10 +31,8 @@  /* PCIe core registers */  #define PCIE_CORE_DEV_ID_REG					0x0  #define PCIE_CORE_CMD_STATUS_REG				0x4 -#define     PCIE_CORE_CMD_IO_ACCESS_EN				BIT(0) -#define     PCIE_CORE_CMD_MEM_ACCESS_EN				BIT(1) -#define     PCIE_CORE_CMD_MEM_IO_REQ_EN				BIT(2)  #define PCIE_CORE_DEV_REV_REG					0x8 +#define PCIE_CORE_EXP_ROM_BAR_REG				0x30  #define PCIE_CORE_PCIEXP_CAP					0xc0  #define PCIE_CORE_ERR_CAPCTL_REG				0x118  #define     PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX			BIT(5) @@ -99,6 +97,7 @@  #define     PCIE_CORE_CTRL2_MSI_ENABLE		BIT(10)  #define PCIE_CORE_REF_CLK_REG			(CONTROL_BASE_ADDR + 0x14)  #define     PCIE_CORE_REF_CLK_TX_ENABLE		BIT(1) +#define     PCIE_CORE_REF_CLK_RX_ENABLE		BIT(2)  #define PCIE_MSG_LOG_REG			(CONTROL_BASE_ADDR + 0x30)  #define PCIE_ISR0_REG				(CONTROL_BASE_ADDR + 0x40)  #define PCIE_MSG_PM_PME_MASK			BIT(7) @@ -106,18 +105,19 @@  #define     PCIE_ISR0_MSI_INT_PENDING		BIT(24)  #define     PCIE_ISR0_INTX_ASSERT(val)		BIT(16 + (val))  #define     PCIE_ISR0_INTX_DEASSERT(val)	BIT(20 + (val)) -#define	    PCIE_ISR0_ALL_MASK			GENMASK(26, 0) +#define     PCIE_ISR0_ALL_MASK			GENMASK(31, 0)  #define PCIE_ISR1_REG				(CONTROL_BASE_ADDR + 0x48)  #define PCIE_ISR1_MASK_REG			(CONTROL_BASE_ADDR + 0x4C)  #define     PCIE_ISR1_POWER_STATE_CHANGE	BIT(4)  #define     PCIE_ISR1_FLUSH			BIT(5)  #define     PCIE_ISR1_INTX_ASSERT(val)		BIT(8 + (val)) -#define     PCIE_ISR1_ALL_MASK			GENMASK(11, 4) +#define     PCIE_ISR1_ALL_MASK			GENMASK(31, 0)  #define PCIE_MSI_ADDR_LOW_REG			(CONTROL_BASE_ADDR + 0x50)  #define PCIE_MSI_ADDR_HIGH_REG			(CONTROL_BASE_ADDR + 0x54)  #define PCIE_MSI_STATUS_REG			(CONTROL_BASE_ADDR + 0x58)  #define PCIE_MSI_MASK_REG			(CONTROL_BASE_ADDR + 0x5C)  #define PCIE_MSI_PAYLOAD_REG			(CONTROL_BASE_ADDR + 0x9C) +#define     PCIE_MSI_DATA_MASK			GENMASK(15, 0)  /* PCIe window configuration */  #define OB_WIN_BASE_ADDR			0x4c00 @@ -164,8 +164,50 @@  #define CFG_REG					(LMI_BASE_ADDR + 0x0)  #define     LTSSM_SHIFT				24  #define     LTSSM_MASK				0x3f -#define     LTSSM_L0				0x10  #define     RC_BAR_CONFIG			0x300 + +/* LTSSM values in CFG_REG */ +enum { +	LTSSM_DETECT_QUIET			= 0x0, +	LTSSM_DETECT_ACTIVE			= 0x1, +	LTSSM_POLLING_ACTIVE			= 0x2, +	LTSSM_POLLING_COMPLIANCE		= 0x3, +	LTSSM_POLLING_CONFIGURATION		= 0x4, +	LTSSM_CONFIG_LINKWIDTH_START		= 0x5, +	LTSSM_CONFIG_LINKWIDTH_ACCEPT		= 0x6, +	LTSSM_CONFIG_LANENUM_ACCEPT		= 0x7, +	LTSSM_CONFIG_LANENUM_WAIT		= 0x8, +	LTSSM_CONFIG_COMPLETE			= 0x9, +	LTSSM_CONFIG_IDLE			= 0xa, +	LTSSM_RECOVERY_RCVR_LOCK		= 0xb, +	LTSSM_RECOVERY_SPEED			= 0xc, +	LTSSM_RECOVERY_RCVR_CFG			= 0xd, +	LTSSM_RECOVERY_IDLE			= 0xe, +	LTSSM_L0				= 0x10, +	LTSSM_RX_L0S_ENTRY			= 0x11, +	LTSSM_RX_L0S_IDLE			= 0x12, +	LTSSM_RX_L0S_FTS			= 0x13, +	LTSSM_TX_L0S_ENTRY			= 0x14, +	LTSSM_TX_L0S_IDLE			= 0x15, +	LTSSM_TX_L0S_FTS			= 0x16, +	LTSSM_L1_ENTRY				= 0x17, +	LTSSM_L1_IDLE				= 0x18, +	LTSSM_L2_IDLE				= 0x19, +	LTSSM_L2_TRANSMIT_WAKE			= 0x1a, +	LTSSM_DISABLED				= 0x20, +	LTSSM_LOOPBACK_ENTRY_MASTER		= 0x21, +	LTSSM_LOOPBACK_ACTIVE_MASTER		= 0x22, +	LTSSM_LOOPBACK_EXIT_MASTER		= 0x23, +	LTSSM_LOOPBACK_ENTRY_SLAVE		= 0x24, +	LTSSM_LOOPBACK_ACTIVE_SLAVE		= 0x25, +	LTSSM_LOOPBACK_EXIT_SLAVE		= 0x26, +	LTSSM_HOT_RESET				= 0x27, +	LTSSM_RECOVERY_EQUALIZATION_PHASE0	= 0x28, +	LTSSM_RECOVERY_EQUALIZATION_PHASE1	= 0x29, +	LTSSM_RECOVERY_EQUALIZATION_PHASE2	= 0x2a, +	LTSSM_RECOVERY_EQUALIZATION_PHASE3	= 0x2b, +}; +  #define VENDOR_ID_REG				(LMI_BASE_ADDR + 0x44)  /* PCIe core controller registers */ @@ -198,7 +240,7 @@  #define     PCIE_IRQ_MSI_INT2_DET		BIT(21)  #define     PCIE_IRQ_RC_DBELL_DET		BIT(22)  #define     PCIE_IRQ_EP_STATUS			BIT(23) -#define     PCIE_IRQ_ALL_MASK			0xfff0fb +#define     PCIE_IRQ_ALL_MASK			GENMASK(31, 0)  #define     PCIE_IRQ_ENABLE_INTS_MASK		PCIE_IRQ_CORE_INT  /* Transaction types */ @@ -257,18 +299,49 @@ static inline u32 advk_readl(struct advk_pcie *pcie, u64 reg)  	return readl(pcie->base + reg);  } -static inline u16 advk_read16(struct advk_pcie *pcie, u64 reg) +static u8 advk_pcie_ltssm_state(struct advk_pcie *pcie)  { -	return advk_readl(pcie, (reg & ~0x3)) >> ((reg & 0x3) * 8); +	u32 val; +	u8 ltssm_state; + +	val = advk_readl(pcie, CFG_REG); +	ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK; +	return ltssm_state;  } -static int advk_pcie_link_up(struct advk_pcie *pcie) +static inline bool advk_pcie_link_up(struct advk_pcie *pcie)  { -	u32 val, ltssm_state; +	/* check if LTSSM is in normal operation - some L* state */ +	u8 ltssm_state = advk_pcie_ltssm_state(pcie); +	return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED; +} -	val = advk_readl(pcie, CFG_REG); -	ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK; -	return ltssm_state >= LTSSM_L0; +static inline bool advk_pcie_link_active(struct advk_pcie *pcie) +{ +	/* +	 * According to PCIe Base specification 3.0, Table 4-14: Link +	 * Status Mapped to the LTSSM, and 4.2.6.3.6 Configuration.Idle +	 * is Link Up mapped to LTSSM Configuration.Idle, Recovery, L0, +	 * L0s, L1 and L2 states. And according to 3.2.1. Data Link +	 * Control and Management State Machine Rules is DL Up status +	 * reported in DL Active state. +	 */ +	u8 ltssm_state = advk_pcie_ltssm_state(pcie); +	return ltssm_state >= LTSSM_CONFIG_IDLE && ltssm_state < LTSSM_DISABLED; +} + +static inline bool advk_pcie_link_training(struct advk_pcie *pcie) +{ +	/* +	 * According to PCIe Base specification 3.0, Table 4-14: Link +	 * Status Mapped to the LTSSM is Link Training mapped to LTSSM +	 * Configuration and Recovery states. +	 */ +	u8 ltssm_state = advk_pcie_ltssm_state(pcie); +	return ((ltssm_state >= LTSSM_CONFIG_LINKWIDTH_START && +		 ltssm_state < LTSSM_L0) || +		(ltssm_state >= LTSSM_RECOVERY_EQUALIZATION_PHASE0 && +		 ltssm_state <= LTSSM_RECOVERY_EQUALIZATION_PHASE3));  }  static int advk_pcie_wait_for_link(struct advk_pcie *pcie) @@ -291,7 +364,7 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)  	size_t retries;  	for (retries = 0; retries < RETRAIN_WAIT_MAX_RETRIES; ++retries) { -		if (!advk_pcie_link_up(pcie)) +		if (advk_pcie_link_training(pcie))  			break;  		udelay(RETRAIN_WAIT_USLEEP_US);  	} @@ -299,23 +372,9 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)  static void advk_pcie_issue_perst(struct advk_pcie *pcie)  { -	u32 reg; -  	if (!pcie->reset_gpio)  		return; -	/* -	 * As required by PCI Express spec (PCI Express Base Specification, REV. -	 * 4.0 PCI Express, February 19 2014, 6.6.1 Conventional Reset) a delay -	 * for at least 100ms after de-asserting PERST# signal is needed before -	 * link training is enabled. So ensure that link training is disabled -	 * prior de-asserting PERST# signal to fulfill that PCI Express spec -	 * requirement. -	 */ -	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); -	reg &= ~LINK_TRAINING_EN; -	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); -  	/* 10ms delay is needed for some cards */  	dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n");  	gpiod_set_value_cansleep(pcie->reset_gpio, 1); @@ -323,54 +382,47 @@ static void advk_pcie_issue_perst(struct advk_pcie *pcie)  	gpiod_set_value_cansleep(pcie->reset_gpio, 0);  } -static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen) +static void advk_pcie_train_link(struct advk_pcie *pcie)  { -	int ret, neg_gen; +	struct device *dev = &pcie->pdev->dev;  	u32 reg; +	int ret; -	/* Setup link speed */ +	/* +	 * Setup PCIe rev / gen compliance based on device tree property +	 * 'max-link-speed' which also forces maximal link speed. +	 */  	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);  	reg &= ~PCIE_GEN_SEL_MSK; -	if (gen == 3) +	if (pcie->link_gen == 3)  		reg |= SPEED_GEN_3; -	else if (gen == 2) +	else if (pcie->link_gen == 2)  		reg |= SPEED_GEN_2;  	else  		reg |= SPEED_GEN_1;  	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);  	/* -	 * Enable link training. This is not needed in every call to this -	 * function, just once suffices, but it does not break anything either. +	 * Set maximal link speed value also into PCIe Link Control 2 register. +	 * Armada 3700 Functional Specification says that default value is based +	 * on SPEED_GEN but tests showed that default value is always 8.0 GT/s.  	 */ +	reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2); +	reg &= ~PCI_EXP_LNKCTL2_TLS; +	if (pcie->link_gen == 3) +		reg |= PCI_EXP_LNKCTL2_TLS_8_0GT; +	else if (pcie->link_gen == 2) +		reg |= PCI_EXP_LNKCTL2_TLS_5_0GT; +	else +		reg |= PCI_EXP_LNKCTL2_TLS_2_5GT; +	advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2); + +	/* Enable link training after selecting PCIe generation */  	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);  	reg |= LINK_TRAINING_EN;  	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);  	/* -	 * Start link training immediately after enabling it. -	 * This solves problems for some buggy cards. -	 */ -	reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL); -	reg |= PCI_EXP_LNKCTL_RL; -	advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL); - -	ret = advk_pcie_wait_for_link(pcie); -	if (ret) -		return ret; - -	reg = advk_read16(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKSTA); -	neg_gen = reg & PCI_EXP_LNKSTA_CLS; - -	return neg_gen; -} - -static void advk_pcie_train_link(struct advk_pcie *pcie) -{ -	struct device *dev = &pcie->pdev->dev; -	int neg_gen = -1, gen; - -	/*  	 * Reset PCIe card via PERST# signal. Some cards are not detected  	 * during link training when they are in some non-initial state.  	 */ @@ -380,41 +432,18 @@ static void advk_pcie_train_link(struct advk_pcie *pcie)  	 * PERST# signal could have been asserted by pinctrl subsystem before  	 * probe() callback has been called or issued explicitly by reset gpio  	 * function advk_pcie_issue_perst(), making the endpoint going into -	 * fundamental reset. As required by PCI Express spec a delay for at -	 * least 100ms after such a reset before link training is needed. +	 * fundamental reset. As required by PCI Express spec (PCI Express +	 * Base Specification, REV. 4.0 PCI Express, February 19 2014, 6.6.1 +	 * Conventional Reset) a delay for at least 100ms after such a reset +	 * before sending a Configuration Request to the device is needed. +	 * So wait until PCIe link is up. Function advk_pcie_wait_for_link() +	 * waits for link at least 900ms.  	 */ -	msleep(PCI_PM_D3COLD_WAIT); - -	/* -	 * Try link training at link gen specified by device tree property -	 * 'max-link-speed'. If this fails, iteratively train at lower gen. -	 */ -	for (gen = pcie->link_gen; gen > 0; --gen) { -		neg_gen = advk_pcie_train_at_gen(pcie, gen); -		if (neg_gen > 0) -			break; -	} - -	if (neg_gen < 0) -		goto err; - -	/* -	 * After successful training if negotiated gen is lower than requested, -	 * train again on negotiated gen. This solves some stability issues for -	 * some buggy gen1 cards. -	 */ -	if (neg_gen < gen) { -		gen = neg_gen; -		neg_gen = advk_pcie_train_at_gen(pcie, gen); -	} - -	if (neg_gen == gen) { -		dev_info(dev, "link up at gen %i\n", gen); -		return; -	} - -err: -	dev_err(dev, "link never came up\n"); +	ret = advk_pcie_wait_for_link(pcie); +	if (ret < 0) +		dev_err(dev, "link never came up\n"); +	else +		dev_info(dev, "link up\n");  }  /* @@ -451,9 +480,15 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)  	u32 reg;  	int i; -	/* Enable TX */ +	/* +	 * Configure PCIe Reference clock. Direction is from the PCIe +	 * controller to the endpoint card, so enable transmitting of +	 * Reference clock differential signal off-chip and disable +	 * receiving off-chip differential signal. +	 */  	reg = advk_readl(pcie, PCIE_CORE_REF_CLK_REG);  	reg |= PCIE_CORE_REF_CLK_TX_ENABLE; +	reg &= ~PCIE_CORE_REF_CLK_RX_ENABLE;  	advk_writel(pcie, reg, PCIE_CORE_REF_CLK_REG);  	/* Set to Direct mode */ @@ -477,6 +512,31 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)  	reg = (PCI_VENDOR_ID_MARVELL << 16) | PCI_VENDOR_ID_MARVELL;  	advk_writel(pcie, reg, VENDOR_ID_REG); +	/* +	 * Change Class Code of PCI Bridge device to PCI Bridge (0x600400), +	 * because the default value is Mass storage controller (0x010400). +	 * +	 * Note that this Aardvark PCI Bridge does not have compliant Type 1 +	 * Configuration Space and it even cannot be accessed via Aardvark's +	 * PCI config space access method. Something like config space is +	 * available in internal Aardvark registers starting at offset 0x0 +	 * and is reported as Type 0. In range 0x10 - 0x34 it has totally +	 * different registers. +	 * +	 * Therefore driver uses emulation of PCI Bridge which emulates +	 * access to configuration space via internal Aardvark registers or +	 * emulated configuration buffer. +	 */ +	reg = advk_readl(pcie, PCIE_CORE_DEV_REV_REG); +	reg &= ~0xffffff00; +	reg |= (PCI_CLASS_BRIDGE_PCI << 8) << 8; +	advk_writel(pcie, reg, PCIE_CORE_DEV_REV_REG); + +	/* Disable Root Bridge I/O space, memory space and bus mastering */ +	reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); +	reg &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); +	advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG); +  	/* Set Advanced Error Capabilities and Control PF0 register */  	reg = PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX |  		PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN | @@ -488,8 +548,9 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)  	reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL);  	reg &= ~PCI_EXP_DEVCTL_RELAX_EN;  	reg &= ~PCI_EXP_DEVCTL_NOSNOOP_EN; +	reg &= ~PCI_EXP_DEVCTL_PAYLOAD;  	reg &= ~PCI_EXP_DEVCTL_READRQ; -	reg |= PCI_EXP_DEVCTL_PAYLOAD; /* Set max payload size */ +	reg |= PCI_EXP_DEVCTL_PAYLOAD_512B;  	reg |= PCI_EXP_DEVCTL_READRQ_512B;  	advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL); @@ -574,19 +635,6 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)  		advk_pcie_disable_ob_win(pcie, i);  	advk_pcie_train_link(pcie); - -	/* -	 * FIXME: The following register update is suspicious. This register is -	 * applicable only when the PCI controller is configured for Endpoint -	 * mode, not as a Root Complex. But apparently when this code is -	 * removed, some cards stop working. This should be investigated and -	 * a comment explaining this should be put here. -	 */ -	reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); -	reg |= PCIE_CORE_CMD_MEM_ACCESS_EN | -		PCIE_CORE_CMD_IO_ACCESS_EN | -		PCIE_CORE_CMD_MEM_IO_REQ_EN; -	advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG);  }  static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u32 *val) @@ -595,6 +643,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3  	u32 reg;  	unsigned int status;  	char *strcomp_status, *str_posted; +	int ret;  	reg = advk_readl(pcie, PIO_STAT);  	status = (reg & PIO_COMPLETION_STATUS_MASK) >> @@ -619,6 +668,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3  	case PIO_COMPLETION_STATUS_OK:  		if (reg & PIO_ERR_STATUS) {  			strcomp_status = "COMP_ERR"; +			ret = -EFAULT;  			break;  		}  		/* Get the read result */ @@ -626,9 +676,11 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3  			*val = advk_readl(pcie, PIO_RD_DATA);  		/* No error */  		strcomp_status = NULL; +		ret = 0;  		break;  	case PIO_COMPLETION_STATUS_UR:  		strcomp_status = "UR"; +		ret = -EOPNOTSUPP;  		break;  	case PIO_COMPLETION_STATUS_CRS:  		if (allow_crs && val) { @@ -646,6 +698,7 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3  			 */  			*val = CFG_RD_CRS_VAL;  			strcomp_status = NULL; +			ret = 0;  			break;  		}  		/* PCIe r4.0, sec 2.3.2, says: @@ -661,31 +714,34 @@ static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u3  		 * Request and taking appropriate action, e.g., complete the  		 * Request to the host as a failed transaction.  		 * -		 * To simplify implementation do not re-issue the Configuration -		 * Request and complete the Request as a failed transaction. +		 * So return -EAGAIN and caller (pci-aardvark.c driver) will +		 * re-issue request again up to the PIO_RETRY_CNT retries.  		 */  		strcomp_status = "CRS"; +		ret = -EAGAIN;  		break;  	case PIO_COMPLETION_STATUS_CA:  		strcomp_status = "CA"; +		ret = -ECANCELED;  		break;  	default:  		strcomp_status = "Unknown"; +		ret = -EINVAL;  		break;  	}  	if (!strcomp_status) -		return 0; +		return ret;  	if (reg & PIO_NON_POSTED_REQ)  		str_posted = "Non-posted";  	else  		str_posted = "Posted"; -	dev_err(dev, "%s PIO Response Status: %s, %#x @ %#x\n", +	dev_dbg(dev, "%s PIO Response Status: %s, %#x @ %#x\n",  		str_posted, strcomp_status, reg, advk_readl(pcie, PIO_ADDR_LS)); -	return -EFAULT; +	return ret;  }  static int advk_pcie_wait_pio(struct advk_pcie *pcie) @@ -693,13 +749,13 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie)  	struct device *dev = &pcie->pdev->dev;  	int i; -	for (i = 0; i < PIO_RETRY_CNT; i++) { +	for (i = 1; i <= PIO_RETRY_CNT; i++) {  		u32 start, isr;  		start = advk_readl(pcie, PIO_START);  		isr = advk_readl(pcie, PIO_ISR);  		if (!start && isr) -			return 0; +			return i;  		udelay(PIO_RETRY_DELAY);  	} @@ -707,6 +763,72 @@ static int advk_pcie_wait_pio(struct advk_pcie *pcie)  	return -ETIMEDOUT;  } +static pci_bridge_emul_read_status_t +advk_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge, +				    int reg, u32 *value) +{ +	struct advk_pcie *pcie = bridge->data; + +	switch (reg) { +	case PCI_COMMAND: +		*value = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); +		return PCI_BRIDGE_EMUL_HANDLED; + +	case PCI_ROM_ADDRESS1: +		*value = advk_readl(pcie, PCIE_CORE_EXP_ROM_BAR_REG); +		return PCI_BRIDGE_EMUL_HANDLED; + +	case PCI_INTERRUPT_LINE: { +		/* +		 * From the whole 32bit register we support reading from HW only +		 * one bit: PCI_BRIDGE_CTL_BUS_RESET. +		 * Other bits are retrieved only from emulated config buffer. +		 */ +		__le32 *cfgspace = (__le32 *)&bridge->conf; +		u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]); +		if (advk_readl(pcie, PCIE_CORE_CTRL1_REG) & HOT_RESET_GEN) +			val |= PCI_BRIDGE_CTL_BUS_RESET << 16; +		else +			val &= ~(PCI_BRIDGE_CTL_BUS_RESET << 16); +		*value = val; +		return PCI_BRIDGE_EMUL_HANDLED; +	} + +	default: +		return PCI_BRIDGE_EMUL_NOT_HANDLED; +	} +} + +static void +advk_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, +				     int reg, u32 old, u32 new, u32 mask) +{ +	struct advk_pcie *pcie = bridge->data; + +	switch (reg) { +	case PCI_COMMAND: +		advk_writel(pcie, new, PCIE_CORE_CMD_STATUS_REG); +		break; + +	case PCI_ROM_ADDRESS1: +		advk_writel(pcie, new, PCIE_CORE_EXP_ROM_BAR_REG); +		break; + +	case PCI_INTERRUPT_LINE: +		if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) { +			u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG); +			if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16)) +				val |= HOT_RESET_GEN; +			else +				val &= ~HOT_RESET_GEN; +			advk_writel(pcie, val, PCIE_CORE_CTRL1_REG); +		} +		break; + +	default: +		break; +	} +}  static pci_bridge_emul_read_status_t  advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge, @@ -723,6 +845,7 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,  	case PCI_EXP_RTCTL: {  		u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);  		*value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE; +		*value |= le16_to_cpu(bridge->pcie_conf.rootctl) & PCI_EXP_RTCTL_CRSSVE;  		*value |= PCI_EXP_RTCAP_CRSVIS << 16;  		return PCI_BRIDGE_EMUL_HANDLED;  	} @@ -734,12 +857,26 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,  		return PCI_BRIDGE_EMUL_HANDLED;  	} +	case PCI_EXP_LNKCAP: { +		u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg); +		/* +		 * PCI_EXP_LNKCAP_DLLLARC bit is hardwired in aardvark HW to 0. +		 * But support for PCI_EXP_LNKSTA_DLLLA is emulated via ltssm +		 * state so explicitly enable PCI_EXP_LNKCAP_DLLLARC flag. +		 */ +		val |= PCI_EXP_LNKCAP_DLLLARC; +		*value = val; +		return PCI_BRIDGE_EMUL_HANDLED; +	} +  	case PCI_EXP_LNKCTL: {  		/* u32 contains both PCI_EXP_LNKCTL and PCI_EXP_LNKSTA */  		u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg) &  			~(PCI_EXP_LNKSTA_LT << 16); -		if (!advk_pcie_link_up(pcie)) +		if (advk_pcie_link_training(pcie))  			val |= (PCI_EXP_LNKSTA_LT << 16); +		if (advk_pcie_link_active(pcie)) +			val |= (PCI_EXP_LNKSTA_DLLLA << 16);  		*value = val;  		return PCI_BRIDGE_EMUL_HANDLED;  	} @@ -747,7 +884,6 @@ advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,  	case PCI_CAP_LIST_ID:  	case PCI_EXP_DEVCAP:  	case PCI_EXP_DEVCTL: -	case PCI_EXP_LNKCAP:  		*value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);  		return PCI_BRIDGE_EMUL_HANDLED;  	default: @@ -794,6 +930,8 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,  }  static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = { +	.read_base = advk_pci_bridge_emul_base_conf_read, +	.write_base = advk_pci_bridge_emul_base_conf_write,  	.read_pcie = advk_pci_bridge_emul_pcie_conf_read,  	.write_pcie = advk_pci_bridge_emul_pcie_conf_write,  }; @@ -805,7 +943,6 @@ static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {  static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)  {  	struct pci_bridge_emul *bridge = &pcie->bridge; -	int ret;  	bridge->conf.vendor =  		cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff); @@ -825,19 +962,14 @@ static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)  	/* Support interrupt A for MSI feature */  	bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE; +	/* Indicates supports for Completion Retry Status */ +	bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS); +  	bridge->has_pcie = true;  	bridge->data = pcie;  	bridge->ops = &advk_pci_bridge_emul_ops; -	/* PCIe config space can be initialized after pci_bridge_emul_init() */ -	ret = pci_bridge_emul_init(bridge, 0); -	if (ret < 0) -		return ret; - -	/* Indicates supports for Completion Retry Status */ -	bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS); - -	return 0; +	return pci_bridge_emul_init(bridge, 0);  }  static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus, @@ -889,6 +1021,7 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,  			     int where, int size, u32 *val)  {  	struct advk_pcie *pcie = bus->sysdata; +	int retry_count;  	bool allow_crs;  	u32 reg;  	int ret; @@ -911,18 +1044,8 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,  		    (le16_to_cpu(pcie->bridge.pcie_conf.rootctl) &  		     PCI_EXP_RTCTL_CRSSVE); -	if (advk_pcie_pio_is_running(pcie)) { -		/* -		 * If it is possible return Completion Retry Status so caller -		 * tries to issue the request again instead of failing. -		 */ -		if (allow_crs) { -			*val = CFG_RD_CRS_VAL; -			return PCIBIOS_SUCCESSFUL; -		} -		*val = 0xffffffff; -		return PCIBIOS_SET_FAILED; -	} +	if (advk_pcie_pio_is_running(pcie)) +		goto try_crs;  	/* Program the control register */  	reg = advk_readl(pcie, PIO_CTRL); @@ -941,30 +1064,24 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,  	/* Program the data strobe */  	advk_writel(pcie, 0xf, PIO_WR_DATA_STRB); -	/* Clear PIO DONE ISR and start the transfer */ -	advk_writel(pcie, 1, PIO_ISR); -	advk_writel(pcie, 1, PIO_START); +	retry_count = 0; +	do { +		/* Clear PIO DONE ISR and start the transfer */ +		advk_writel(pcie, 1, PIO_ISR); +		advk_writel(pcie, 1, PIO_START); -	ret = advk_pcie_wait_pio(pcie); -	if (ret < 0) { -		/* -		 * If it is possible return Completion Retry Status so caller -		 * tries to issue the request again instead of failing. -		 */ -		if (allow_crs) { -			*val = CFG_RD_CRS_VAL; -			return PCIBIOS_SUCCESSFUL; -		} -		*val = 0xffffffff; -		return PCIBIOS_SET_FAILED; -	} +		ret = advk_pcie_wait_pio(pcie); +		if (ret < 0) +			goto try_crs; -	/* Check PIO status and get the read result */ -	ret = advk_pcie_check_pio_status(pcie, allow_crs, val); -	if (ret < 0) { -		*val = 0xffffffff; -		return PCIBIOS_SET_FAILED; -	} +		retry_count += ret; + +		/* Check PIO status and get the read result */ +		ret = advk_pcie_check_pio_status(pcie, allow_crs, val); +	} while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT); + +	if (ret < 0) +		goto fail;  	if (size == 1)  		*val = (*val >> (8 * (where & 3))) & 0xff; @@ -972,6 +1089,20 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,  		*val = (*val >> (8 * (where & 3))) & 0xffff;  	return PCIBIOS_SUCCESSFUL; + +try_crs: +	/* +	 * If it is possible, return Completion Retry Status so that caller +	 * tries to issue the request again instead of failing. +	 */ +	if (allow_crs) { +		*val = CFG_RD_CRS_VAL; +		return PCIBIOS_SUCCESSFUL; +	} + +fail: +	*val = 0xffffffff; +	return PCIBIOS_SET_FAILED;  }  static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn, @@ -980,6 +1111,7 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,  	struct advk_pcie *pcie = bus->sysdata;  	u32 reg;  	u32 data_strobe = 0x0; +	int retry_count;  	int offset;  	int ret; @@ -1021,19 +1153,22 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,  	/* Program the data strobe */  	advk_writel(pcie, data_strobe, PIO_WR_DATA_STRB); -	/* Clear PIO DONE ISR and start the transfer */ -	advk_writel(pcie, 1, PIO_ISR); -	advk_writel(pcie, 1, PIO_START); +	retry_count = 0; +	do { +		/* Clear PIO DONE ISR and start the transfer */ +		advk_writel(pcie, 1, PIO_ISR); +		advk_writel(pcie, 1, PIO_START); -	ret = advk_pcie_wait_pio(pcie); -	if (ret < 0) -		return PCIBIOS_SET_FAILED; +		ret = advk_pcie_wait_pio(pcie); +		if (ret < 0) +			return PCIBIOS_SET_FAILED; -	ret = advk_pcie_check_pio_status(pcie, false, NULL); -	if (ret < 0) -		return PCIBIOS_SET_FAILED; +		retry_count += ret; -	return PCIBIOS_SUCCESSFUL; +		ret = advk_pcie_check_pio_status(pcie, false, NULL); +	} while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT); + +	return ret < 0 ? PCIBIOS_SET_FAILED : PCIBIOS_SUCCESSFUL;  }  static struct pci_ops advk_pcie_ops = { @@ -1082,7 +1217,7 @@ static int advk_msi_irq_domain_alloc(struct irq_domain *domain,  				    domain->host_data, handle_simple_irq,  				    NULL, NULL); -	return hwirq; +	return 0;  }  static void advk_msi_irq_domain_free(struct irq_domain *domain, @@ -1263,8 +1398,12 @@ static void advk_pcie_handle_msi(struct advk_pcie *pcie)  		if (!(BIT(msi_idx) & msi_status))  			continue; +		/* +		 * msi_idx contains bits [4:0] of the msi_data and msi_data +		 * contains 16bit MSI interrupt number +		 */  		advk_writel(pcie, BIT(msi_idx), PCIE_MSI_STATUS_REG); -		msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & 0xFF; +		msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & PCIE_MSI_DATA_MASK;  		generic_handle_irq(msi_data);  	} @@ -1286,12 +1425,6 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)  	isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);  	isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK); -	if (!isr0_status && !isr1_status) { -		advk_writel(pcie, isr0_val, PCIE_ISR0_REG); -		advk_writel(pcie, isr1_val, PCIE_ISR1_REG); -		return; -	} -  	/* Process MSI interrupts */  	if (isr0_status & PCIE_ISR0_MSI_INT_PENDING)  		advk_pcie_handle_msi(pcie); |