Skip to content

Commit 05cf00a

Browse files
committed
Merge branch 'pci/controller/qcom'
- Add OF support for parsing DT 'eq-presets-<N>gts' property for lane equalization presets (Krishna Chaitanya Chundru) - Read Maximum Link Width from the Link Capabilities register if DT lacks 'num-lanes' property (Krishna Chaitanya Chundru) - Add Physical Layer 64 GT/s Capability ID and register offsets for 8, 32, and 64 GT/s lane equalization registers (Krishna Chaitanya Chundru) - Add generic dwc support for configuring lane equalization presets (Krishna Chaitanya Chundru) - Add DT and driver support for PCIe on IPQ5018 SoC (Nitheesh Sekar) * pci/controller/qcom: PCI: qcom: Add support for IPQ5018 dt-bindings: PCI: qcom: Add IPQ5018 SoC PCI: dwc: Add support for configuring lane equalization presets PCI: Add lane equalization register offsets PCI: dwc: Update pci->num_lanes to maximum supported link width PCI: of: Add of_pci_get_equalization_presets() API
2 parents c7b9c59 + 3e51274 commit 05cf00a

File tree

8 files changed

+228
-2
lines changed

8 files changed

+228
-2
lines changed

Documentation/devicetree/bindings/pci/qcom,pcie.yaml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ properties:
2121
- qcom,pcie-apq8064
2222
- qcom,pcie-apq8084
2323
- qcom,pcie-ipq4019
24+
- qcom,pcie-ipq5018
2425
- qcom,pcie-ipq6018
2526
- qcom,pcie-ipq8064
2627
- qcom,pcie-ipq8064-v2
@@ -168,6 +169,7 @@ allOf:
168169
compatible:
169170
contains:
170171
enum:
172+
- qcom,pcie-ipq5018
171173
- qcom,pcie-ipq6018
172174
- qcom,pcie-ipq8074-gen3
173175
- qcom,pcie-ipq9574
@@ -322,6 +324,53 @@ allOf:
322324
- const: ahb # AHB reset
323325
- const: phy_ahb # PHY AHB reset
324326

327+
- if:
328+
properties:
329+
compatible:
330+
contains:
331+
enum:
332+
- qcom,pcie-ipq5018
333+
then:
334+
properties:
335+
clocks:
336+
minItems: 6
337+
maxItems: 6
338+
clock-names:
339+
items:
340+
- const: iface # PCIe to SysNOC BIU clock
341+
- const: axi_m # AXI Master clock
342+
- const: axi_s # AXI Slave clock
343+
- const: ahb # AHB clock
344+
- const: aux # Auxiliary clock
345+
- const: axi_bridge # AXI bridge clock
346+
resets:
347+
minItems: 8
348+
maxItems: 8
349+
reset-names:
350+
items:
351+
- const: pipe # PIPE reset
352+
- const: sleep # Sleep reset
353+
- const: sticky # Core sticky reset
354+
- const: axi_m # AXI master reset
355+
- const: axi_s # AXI slave reset
356+
- const: ahb # AHB reset
357+
- const: axi_m_sticky # AXI master sticky reset
358+
- const: axi_s_sticky # AXI slave sticky reset
359+
interrupts:
360+
minItems: 9
361+
maxItems: 9
362+
interrupt-names:
363+
items:
364+
- const: msi0
365+
- const: msi1
366+
- const: msi2
367+
- const: msi3
368+
- const: msi4
369+
- const: msi5
370+
- const: msi6
371+
- const: msi7
372+
- const: global
373+
325374
- if:
326375
properties:
327376
compatible:
@@ -562,6 +611,7 @@ allOf:
562611
enum:
563612
- qcom,pcie-apq8064
564613
- qcom,pcie-ipq4019
614+
- qcom,pcie-ipq5018
565615
- qcom,pcie-ipq8064
566616
- qcom,pcie-ipq8064v2
567617
- qcom,pcie-ipq8074

drivers/pci/controller/dwc/pcie-designware-host.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,13 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
523523

524524
dw_pcie_iatu_detect(pci);
525525

526+
if (pci->num_lanes < 1)
527+
pci->num_lanes = dw_pcie_link_get_max_link_width(pci);
528+
529+
ret = of_pci_get_equalization_presets(dev, &pp->presets, pci->num_lanes);
530+
if (ret)
531+
goto err_free_msi;
532+
526533
/*
527534
* Allocate the resource for MSG TLP before programming the iATU
528535
* outbound window in dw_pcie_setup_rc(). Since the allocation depends
@@ -828,6 +835,77 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
828835
return 0;
829836
}
830837

838+
static void dw_pcie_program_presets(struct dw_pcie_rp *pp, enum pci_bus_speed speed)
839+
{
840+
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
841+
u8 lane_eq_offset, lane_reg_size, cap_id;
842+
u8 *presets;
843+
u32 cap;
844+
int i;
845+
846+
if (speed == PCIE_SPEED_8_0GT) {
847+
presets = (u8 *)pp->presets.eq_presets_8gts;
848+
lane_eq_offset = PCI_SECPCI_LE_CTRL;
849+
cap_id = PCI_EXT_CAP_ID_SECPCI;
850+
/* For data rate of 8 GT/S each lane equalization control is 16bits wide*/
851+
lane_reg_size = 0x2;
852+
} else if (speed == PCIE_SPEED_16_0GT) {
853+
presets = pp->presets.eq_presets_Ngts[EQ_PRESET_TYPE_16GTS - 1];
854+
lane_eq_offset = PCI_PL_16GT_LE_CTRL;
855+
cap_id = PCI_EXT_CAP_ID_PL_16GT;
856+
lane_reg_size = 0x1;
857+
} else if (speed == PCIE_SPEED_32_0GT) {
858+
presets = pp->presets.eq_presets_Ngts[EQ_PRESET_TYPE_32GTS - 1];
859+
lane_eq_offset = PCI_PL_32GT_LE_CTRL;
860+
cap_id = PCI_EXT_CAP_ID_PL_32GT;
861+
lane_reg_size = 0x1;
862+
} else if (speed == PCIE_SPEED_64_0GT) {
863+
presets = pp->presets.eq_presets_Ngts[EQ_PRESET_TYPE_64GTS - 1];
864+
lane_eq_offset = PCI_PL_64GT_LE_CTRL;
865+
cap_id = PCI_EXT_CAP_ID_PL_64GT;
866+
lane_reg_size = 0x1;
867+
} else {
868+
return;
869+
}
870+
871+
if (presets[0] == PCI_EQ_RESV)
872+
return;
873+
874+
cap = dw_pcie_find_ext_capability(pci, cap_id);
875+
if (!cap)
876+
return;
877+
878+
/*
879+
* Write preset values to the registers byte-by-byte for the given
880+
* number of lanes and register size.
881+
*/
882+
for (i = 0; i < pci->num_lanes * lane_reg_size; i++)
883+
dw_pcie_writeb_dbi(pci, cap + lane_eq_offset + i, presets[i]);
884+
}
885+
886+
static void dw_pcie_config_presets(struct dw_pcie_rp *pp)
887+
{
888+
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
889+
enum pci_bus_speed speed = pcie_link_speed[pci->max_link_speed];
890+
891+
/*
892+
* Lane equalization settings need to be applied for all data rates the
893+
* controller supports and for all supported lanes.
894+
*/
895+
896+
if (speed >= PCIE_SPEED_8_0GT)
897+
dw_pcie_program_presets(pp, PCIE_SPEED_8_0GT);
898+
899+
if (speed >= PCIE_SPEED_16_0GT)
900+
dw_pcie_program_presets(pp, PCIE_SPEED_16_0GT);
901+
902+
if (speed >= PCIE_SPEED_32_0GT)
903+
dw_pcie_program_presets(pp, PCIE_SPEED_32_0GT);
904+
905+
if (speed >= PCIE_SPEED_64_0GT)
906+
dw_pcie_program_presets(pp, PCIE_SPEED_64_0GT);
907+
}
908+
831909
int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
832910
{
833911
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -881,6 +959,7 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)
881959
PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
882960
dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
883961

962+
dw_pcie_config_presets(pp);
884963
/*
885964
* If the platform provides its own child bus config accesses, it means
886965
* the platform uses its own address translation component rather than

drivers/pci/controller/dwc/pcie-designware.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,14 @@ static void dw_pcie_link_set_max_speed(struct dw_pcie *pci)
781781

782782
}
783783

784+
int dw_pcie_link_get_max_link_width(struct dw_pcie *pci)
785+
{
786+
u8 cap = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
787+
u32 lnkcap = dw_pcie_readl_dbi(pci, cap + PCI_EXP_LNKCAP);
788+
789+
return FIELD_GET(PCI_EXP_LNKCAP_MLW, lnkcap);
790+
}
791+
784792
static void dw_pcie_link_set_max_link_width(struct dw_pcie *pci, u32 num_lanes)
785793
{
786794
u32 lnkcap, lwsc, plc;

drivers/pci/controller/dwc/pcie-designware.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include <linux/pci-epc.h>
2626
#include <linux/pci-epf.h>
2727

28+
#include "../../pci.h"
29+
2830
/* DWC PCIe IP-core versions (native support since v4.70a) */
2931
#define DW_PCIE_VER_365A 0x3336352a
3032
#define DW_PCIE_VER_460A 0x3436302a
@@ -412,6 +414,7 @@ struct dw_pcie_rp {
412414
int msg_atu_index;
413415
struct resource *msg_res;
414416
bool use_linkup_irq;
417+
struct pci_eq_presets presets;
415418
};
416419

417420
struct dw_pcie_ep_ops {
@@ -540,6 +543,7 @@ void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val);
540543
bool dw_pcie_link_up(struct dw_pcie *pci);
541544
void dw_pcie_upconfig_setup(struct dw_pcie *pci);
542545
int dw_pcie_wait_for_link(struct dw_pcie *pci);
546+
int dw_pcie_link_get_max_link_width(struct dw_pcie *pci);
543547
int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
544548
const struct dw_pcie_ob_atu_cfg *atu);
545549
int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type,

drivers/pci/controller/dwc/pcie-qcom.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,6 +1840,7 @@ static const struct of_device_id qcom_pcie_match[] = {
18401840
{ .compatible = "qcom,pcie-apq8064", .data = &cfg_2_1_0 },
18411841
{ .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 },
18421842
{ .compatible = "qcom,pcie-ipq4019", .data = &cfg_2_4_0 },
1843+
{ .compatible = "qcom,pcie-ipq5018", .data = &cfg_2_9_0 },
18431844
{ .compatible = "qcom,pcie-ipq6018", .data = &cfg_2_9_0 },
18441845
{ .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 },
18451846
{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 },

drivers/pci/of.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,3 +966,47 @@ u32 of_pci_get_slot_power_limit(struct device_node *node,
966966
return slot_power_limit_mw;
967967
}
968968
EXPORT_SYMBOL_GPL(of_pci_get_slot_power_limit);
969+
970+
/**
971+
* of_pci_get_equalization_presets - Parses the "eq-presets-Ngts" property.
972+
*
973+
* @dev: Device containing the properties.
974+
* @presets: Pointer to store the parsed data.
975+
* @num_lanes: Maximum number of lanes supported.
976+
*
977+
* If the property is present, read and store the data in the @presets structure.
978+
* Else, assign a default value of PCI_EQ_RESV.
979+
*
980+
* Return: 0 if the property is not available or successfully parsed else
981+
* errno otherwise.
982+
*/
983+
int of_pci_get_equalization_presets(struct device *dev,
984+
struct pci_eq_presets *presets,
985+
int num_lanes)
986+
{
987+
char name[20];
988+
int ret;
989+
990+
presets->eq_presets_8gts[0] = PCI_EQ_RESV;
991+
ret = of_property_read_u16_array(dev->of_node, "eq-presets-8gts",
992+
presets->eq_presets_8gts, num_lanes);
993+
if (ret && ret != -EINVAL) {
994+
dev_err(dev, "Error reading eq-presets-8gts: %d\n", ret);
995+
return ret;
996+
}
997+
998+
for (int i = 0; i < EQ_PRESET_TYPE_MAX - 1; i++) {
999+
presets->eq_presets_Ngts[i][0] = PCI_EQ_RESV;
1000+
snprintf(name, sizeof(name), "eq-presets-%dgts", 8 << (i + 1));
1001+
ret = of_property_read_u8_array(dev->of_node, name,
1002+
presets->eq_presets_Ngts[i],
1003+
num_lanes);
1004+
if (ret && ret != -EINVAL) {
1005+
dev_err(dev, "Error reading %s: %d\n", name, ret);
1006+
return ret;
1007+
}
1008+
}
1009+
1010+
return 0;
1011+
}
1012+
EXPORT_SYMBOL_GPL(of_pci_get_equalization_presets);

drivers/pci/pci.h

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ struct pcie_tlp_log;
99
/* Number of possible devfns: 0.0 to 1f.7 inclusive */
1010
#define MAX_NR_DEVFNS 256
1111

12+
#define MAX_NR_LANES 16
13+
1214
#define PCI_FIND_CAP_TTL 48
1315

1416
#define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */
@@ -891,6 +893,21 @@ static inline u64 pci_rebar_size_to_bytes(int size)
891893

892894
struct device_node;
893895

896+
#define PCI_EQ_RESV 0xff
897+
898+
enum equalization_preset_type {
899+
EQ_PRESET_TYPE_8GTS,
900+
EQ_PRESET_TYPE_16GTS,
901+
EQ_PRESET_TYPE_32GTS,
902+
EQ_PRESET_TYPE_64GTS,
903+
EQ_PRESET_TYPE_MAX
904+
};
905+
906+
struct pci_eq_presets {
907+
u16 eq_presets_8gts[MAX_NR_LANES];
908+
u8 eq_presets_Ngts[EQ_PRESET_TYPE_MAX - 1][MAX_NR_LANES];
909+
};
910+
894911
#ifdef CONFIG_OF
895912
int of_get_pci_domain_nr(struct device_node *node);
896913
int of_pci_get_max_link_speed(struct device_node *node);
@@ -905,7 +922,9 @@ void pci_release_bus_of_node(struct pci_bus *bus);
905922

906923
int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge);
907924
bool of_pci_supply_present(struct device_node *np);
908-
925+
int of_pci_get_equalization_presets(struct device *dev,
926+
struct pci_eq_presets *presets,
927+
int num_lanes);
909928
#else
910929
static inline int
911930
of_get_pci_domain_nr(struct device_node *node)
@@ -950,6 +969,17 @@ static inline bool of_pci_supply_present(struct device_node *np)
950969
{
951970
return false;
952971
}
972+
973+
static inline int of_pci_get_equalization_presets(struct device *dev,
974+
struct pci_eq_presets *presets,
975+
int num_lanes)
976+
{
977+
presets->eq_presets_8gts[0] = PCI_EQ_RESV;
978+
for (int i = 0; i < EQ_PRESET_TYPE_MAX - 1; i++)
979+
presets->eq_presets_Ngts[i][0] = PCI_EQ_RESV;
980+
981+
return 0;
982+
}
953983
#endif /* CONFIG_OF */
954984

955985
struct of_changeset;

include/uapi/linux/pci_regs.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,8 @@
750750
#define PCI_EXT_CAP_ID_NPEM 0x29 /* Native PCIe Enclosure Management */
751751
#define PCI_EXT_CAP_ID_PL_32GT 0x2A /* Physical Layer 32.0 GT/s */
752752
#define PCI_EXT_CAP_ID_DOE 0x2E /* Data Object Exchange */
753-
#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DOE
753+
#define PCI_EXT_CAP_ID_PL_64GT 0x31 /* Physical Layer 64.0 GT/s */
754+
#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PL_64GT
754755

755756
#define PCI_EXT_CAP_DSN_SIZEOF 12
756757
#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40
@@ -1144,12 +1145,21 @@
11441145
#define PCI_DLF_CAP 0x04 /* Capabilities Register */
11451146
#define PCI_DLF_EXCHANGE_ENABLE 0x80000000 /* Data Link Feature Exchange Enable */
11461147

1148+
/* Secondary PCIe Capability 8.0 GT/s */
1149+
#define PCI_SECPCI_LE_CTRL 0x0c /* Lane Equalization Control Register */
1150+
11471151
/* Physical Layer 16.0 GT/s */
11481152
#define PCI_PL_16GT_LE_CTRL 0x20 /* Lane Equalization Control Register */
11491153
#define PCI_PL_16GT_LE_CTRL_DSP_TX_PRESET_MASK 0x0000000F
11501154
#define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK 0x000000F0
11511155
#define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_SHIFT 4
11521156

1157+
/* Physical Layer 32.0 GT/s */
1158+
#define PCI_PL_32GT_LE_CTRL 0x20 /* Lane Equalization Control Register */
1159+
1160+
/* Physical Layer 64.0 GT/s */
1161+
#define PCI_PL_64GT_LE_CTRL 0x20 /* Lane Equalization Control Register */
1162+
11531163
/* Native PCIe Enclosure Management */
11541164
#define PCI_NPEM_CAP 0x04 /* NPEM capability register */
11551165
#define PCI_NPEM_CAP_CAPABLE 0x00000001 /* NPEM Capable */

0 commit comments

Comments
 (0)