File Index
Files and directories
Sign in
FILE

pcie-cadence-hpa.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pci/controller/cadence/pcie-cadence-hpa.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Cadence PCIe controller driver.
  4 *
  5 * Copyright (c) 2024, Cadence Design Systems
  6 * Author: Manikandan K Pillai <mpillai@cadence.com>
  7 */
  8#include <linux/kernel.h>
  9#include <linux/of.h>
 10
 11#include "pcie-cadence.h"
 12
 13bool cdns_pcie_hpa_link_up(struct cdns_pcie *pcie)
 14{
 15	u32 pl_reg_val;
 16
 17	pl_reg_val = cdns_pcie_hpa_readl(pcie, REG_BANK_IP_REG, CDNS_PCIE_HPA_PHY_DBG_STS_REG0);
 18	if (pl_reg_val & GENMASK(0, 0))
 19		return true;
 20	return false;
 21}
 22EXPORT_SYMBOL_GPL(cdns_pcie_hpa_link_up);
 23
 24void cdns_pcie_hpa_detect_quiet_min_delay_set(struct cdns_pcie *pcie)
 25{
 26	u32 delay = 0x3;
 27	u32 ltssm_control_cap;
 28
 29	/* Set the LTSSM Detect Quiet state min. delay to 2ms */
 30	ltssm_control_cap = cdns_pcie_hpa_readl(pcie, REG_BANK_IP_REG,
 31						CDNS_PCIE_HPA_PHY_LAYER_CFG0);
 32	ltssm_control_cap = ((ltssm_control_cap &
 33			    ~CDNS_PCIE_HPA_DETECT_QUIET_MIN_DELAY_MASK) |
 34			    CDNS_PCIE_HPA_DETECT_QUIET_MIN_DELAY(delay));
 35
 36	cdns_pcie_hpa_writel(pcie, REG_BANK_IP_REG,
 37			     CDNS_PCIE_HPA_PHY_LAYER_CFG0, ltssm_control_cap);
 38}
 39EXPORT_SYMBOL_GPL(cdns_pcie_hpa_detect_quiet_min_delay_set);
 40
 41void cdns_pcie_hpa_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn,
 42				       u32 r, bool is_io,
 43				       u64 cpu_addr, u64 pci_addr, size_t size)
 44{
 45	/*
 46	 * roundup_pow_of_two() returns an unsigned long, which is not suited
 47	 * for 64bit values
 48	 */
 49	u64 sz = 1ULL << fls64(size - 1);
 50	int nbits = ilog2(sz);
 51	u32 addr0, addr1, desc0, desc1, ctrl0;
 52
 53	if (nbits < 8)
 54		nbits = 8;
 55
 56	/* Set the PCI address */
 57	addr0 = CDNS_PCIE_HPA_AT_OB_REGION_PCI_ADDR0_NBITS(nbits) |
 58		(lower_32_bits(pci_addr) & GENMASK(31, 8));
 59	addr1 = upper_32_bits(pci_addr);
 60
 61	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
 62			     CDNS_PCIE_HPA_AT_OB_REGION_PCI_ADDR0(r), addr0);
 63	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
 64			     CDNS_PCIE_HPA_AT_OB_REGION_PCI_ADDR1(r), addr1);
 65
 66	/* Set the PCIe header descriptor */
 67	if (is_io)
 68		desc0 = CDNS_PCIE_HPA_AT_OB_REGION_DESC0_TYPE_IO;
 69	else
 70		desc0 = CDNS_PCIE_HPA_AT_OB_REGION_DESC0_TYPE_MEM;
 71	desc1 = 0;
 72	ctrl0 = 0;
 73
 74	/*
 75	 * Whether Bit [26] is set or not inside DESC0 register of the outbound
 76	 * PCIe descriptor, the PCI function number must be set into
 77	 * Bits [31:24] of DESC1 anyway.
 78	 *
 79	 * In Root Complex mode, the function number is always 0 but in Endpoint
 80	 * mode, the PCIe controller may support more than one function. This
 81	 * function number needs to be set properly into the outbound PCIe
 82	 * descriptor.
 83	 *
 84	 * Besides, setting Bit [26] is mandatory when in Root Complex mode:
 85	 * then the driver must provide the bus, resp. device, number in
 86	 * Bits [31:24] of DESC1, resp. Bits[23:16] of DESC0. Like the function
 87	 * number, the device number is always 0 in Root Complex mode.
 88	 *
 89	 * However when in Endpoint mode, we can clear Bit [26] of DESC0, hence
 90	 * the PCIe controller will use the captured values for the bus and
 91	 * device numbers.
 92	 */
 93	if (pcie->is_rc) {
 94		/* The device and function numbers are always 0 */
 95		desc1 = CDNS_PCIE_HPA_AT_OB_REGION_DESC1_BUS(busnr) |
 96			CDNS_PCIE_HPA_AT_OB_REGION_DESC1_DEVFN(0);
 97		ctrl0 = CDNS_PCIE_HPA_AT_OB_REGION_CTRL0_SUPPLY_BUS |
 98			CDNS_PCIE_HPA_AT_OB_REGION_CTRL0_SUPPLY_DEV_FN;
 99	} else {
100		/*
101		 * Use captured values for bus and device numbers but still
102		 * need to set the function number
103		 */
104		desc1 |= CDNS_PCIE_HPA_AT_OB_REGION_DESC1_DEVFN(fn);
105	}
106
107	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
108			     CDNS_PCIE_HPA_AT_OB_REGION_DESC0(r), desc0);
109	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
110			     CDNS_PCIE_HPA_AT_OB_REGION_DESC1(r), desc1);
111
112	addr0 = CDNS_PCIE_HPA_AT_OB_REGION_CPU_ADDR0_NBITS(nbits) |
113		(lower_32_bits(cpu_addr) & GENMASK(31, 8));
114	addr1 = upper_32_bits(cpu_addr);
115
116	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
117			     CDNS_PCIE_HPA_AT_OB_REGION_CPU_ADDR0(r), addr0);
118	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
119			     CDNS_PCIE_HPA_AT_OB_REGION_CPU_ADDR1(r), addr1);
120	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
121			     CDNS_PCIE_HPA_AT_OB_REGION_CTRL0(r), ctrl0);
122}
123EXPORT_SYMBOL_GPL(cdns_pcie_hpa_set_outbound_region);
124
125void cdns_pcie_hpa_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie,
126						      u8 busnr, u8 fn,
127						      u32 r, u64 cpu_addr)
128{
129	u32 addr0, addr1, desc0, desc1, ctrl0;
130
131	desc0 = CDNS_PCIE_HPA_AT_OB_REGION_DESC0_TYPE_NORMAL_MSG;
132	desc1 = 0;
133	ctrl0 = 0;
134
135	/* See cdns_pcie_set_outbound_region() comments above */
136	if (pcie->is_rc) {
137		desc1 = CDNS_PCIE_HPA_AT_OB_REGION_DESC1_BUS(busnr) |
138			CDNS_PCIE_HPA_AT_OB_REGION_DESC1_DEVFN(0);
139		ctrl0 = CDNS_PCIE_HPA_AT_OB_REGION_CTRL0_SUPPLY_BUS |
140			CDNS_PCIE_HPA_AT_OB_REGION_CTRL0_SUPPLY_DEV_FN;
141	} else {
142		desc1 |= CDNS_PCIE_HPA_AT_OB_REGION_DESC1_DEVFN(fn);
143	}
144
145	addr0 = CDNS_PCIE_HPA_AT_OB_REGION_CPU_ADDR0_NBITS(17) |
146		(lower_32_bits(cpu_addr) & GENMASK(31, 8));
147	addr1 = upper_32_bits(cpu_addr);
148
149	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
150			     CDNS_PCIE_HPA_AT_OB_REGION_PCI_ADDR0(r), 0);
151	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
152			     CDNS_PCIE_HPA_AT_OB_REGION_PCI_ADDR1(r), 0);
153	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
154			     CDNS_PCIE_HPA_AT_OB_REGION_DESC0(r), desc0);
155	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
156			     CDNS_PCIE_HPA_AT_OB_REGION_DESC1(r), desc1);
157	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
158			     CDNS_PCIE_HPA_AT_OB_REGION_CPU_ADDR0(r), addr0);
159	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
160			     CDNS_PCIE_HPA_AT_OB_REGION_CPU_ADDR1(r), addr1);
161	cdns_pcie_hpa_writel(pcie, REG_BANK_AXI_SLAVE,
162			     CDNS_PCIE_HPA_AT_OB_REGION_CTRL0(r), ctrl0);
163}
164EXPORT_SYMBOL_GPL(cdns_pcie_hpa_set_outbound_region_for_normal_msg);
165
166MODULE_LICENSE("GPL");
167MODULE_DESCRIPTION("Cadence PCIe controller driver");
~/ Read-only file preview.