Skip to content

Commit 57a4591

Browse files
PCI: of: Add of_pci_get_equalization_presets() API
PCIe equalization presets are predefined settings used to optimize signal integrity by compensating for signal loss and distortion in high-speed data transmission. As per PCIe spec 6.0.1 revision section 8.3.3.3 & 4.2.4 for data rates of 8.0 GT/s, 16.0 GT/s, 32.0 GT/s, and 64.0 GT/s, there is a way to configure lane equalization presets for each lane to enhance the PCIe link reliability. Each preset value represents a different combination of pre-shoot and de-emphasis values. For each data rate, different registers are defined: for 8.0 GT/s, registers are defined in section 7.7.3.4; for 16.0 GT/s, in section 7.7.5.9, etc. The 8.0 GT/s rate has an extra receiver preset hint, requiring 16 bits per lane, while the remaining data rates use 8 bits per lane. Based on the number of lanes and the supported data rate, of_pci_get_equalization_presets() reads the device tree property and stores in the presets structure. Signed-off-by: Krishna Chaitanya Chundru <[email protected]> Signed-off-by: Manivannan Sadhasivam <[email protected]> Reviewed-by: Manivannan Sadhasivam <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent 0af2f6b commit 57a4591

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

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 */
@@ -876,6 +878,21 @@ static inline u64 pci_rebar_size_to_bytes(int size)
876878

877879
struct device_node;
878880

881+
#define PCI_EQ_RESV 0xff
882+
883+
enum equalization_preset_type {
884+
EQ_PRESET_TYPE_8GTS,
885+
EQ_PRESET_TYPE_16GTS,
886+
EQ_PRESET_TYPE_32GTS,
887+
EQ_PRESET_TYPE_64GTS,
888+
EQ_PRESET_TYPE_MAX
889+
};
890+
891+
struct pci_eq_presets {
892+
u16 eq_presets_8gts[MAX_NR_LANES];
893+
u8 eq_presets_Ngts[EQ_PRESET_TYPE_MAX - 1][MAX_NR_LANES];
894+
};
895+
879896
#ifdef CONFIG_OF
880897
int of_get_pci_domain_nr(struct device_node *node);
881898
int of_pci_get_max_link_speed(struct device_node *node);
@@ -890,7 +907,9 @@ void pci_release_bus_of_node(struct pci_bus *bus);
890907

891908
int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge);
892909
bool of_pci_supply_present(struct device_node *np);
893-
910+
int of_pci_get_equalization_presets(struct device *dev,
911+
struct pci_eq_presets *presets,
912+
int num_lanes);
894913
#else
895914
static inline int
896915
of_get_pci_domain_nr(struct device_node *node)
@@ -935,6 +954,17 @@ static inline bool of_pci_supply_present(struct device_node *np)
935954
{
936955
return false;
937956
}
957+
958+
static inline int of_pci_get_equalization_presets(struct device *dev,
959+
struct pci_eq_presets *presets,
960+
int num_lanes)
961+
{
962+
presets->eq_presets_8gts[0] = PCI_EQ_RESV;
963+
for (int i = 0; i < EQ_PRESET_TYPE_MAX - 1; i++)
964+
presets->eq_presets_Ngts[i][0] = PCI_EQ_RESV;
965+
966+
return 0;
967+
}
938968
#endif /* CONFIG_OF */
939969

940970
struct of_changeset;

0 commit comments

Comments
 (0)