Message ID | 20250225-preset_v6-v7-2-a593f3ef3951@oss.qualcomm.com (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | PCI: dwc: Add support for configuring lane equalization presets | expand |
On Tue, Feb 25, 2025 at 05:15:05PM +0530, Krishna Chaitanya Chundru wrote: > 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, this function > reads the device tree property and stores in the presets structure. Can you mention the function name here somewhere so we don't have to dig it out of the patch? If you put it in the subject, the function name is descriptive enough that you hardly need anything more, e.g., PCI: of: Add of_pci_get_equalization_presets() API > + * of_pci_get_equalization_presets - Parses the "eq-presets-Ngts" property. > + * > + * @dev: Device containing the properties. > + * @presets: Pointer to store the parsed data. > + * @num_lanes: Maximum number of lanes supported. > + * > + * If the property is present read and store the data in the preset structure > + * else assign default value 0xff to indicate property is not present. > + * > + * Return: 0 if the property is not available or successfully parsed; errno otherwise. Wrap to fit in 80 columns like the rest of the file. > + */ > +int of_pci_get_equalization_presets(struct device *dev, > + struct pci_eq_presets *presets, > + int num_lanes) > +{
On Tue, Feb 25, 2025 at 05:15:05PM +0530, Krishna Chaitanya Chundru wrote: > 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, this function > reads the device tree property and stores in the presets structure. > > Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com> > --- > drivers/pci/of.c | 43 +++++++++++++++++++++++++++++++++++++++++++ > drivers/pci/pci.h | 27 ++++++++++++++++++++++++++- > 2 files changed, 69 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/of.c b/drivers/pci/of.c > index 7a806f5c0d20..9ebe7d0e4e0c 100644 > --- a/drivers/pci/of.c > +++ b/drivers/pci/of.c > @@ -851,3 +851,46 @@ u32 of_pci_get_slot_power_limit(struct device_node *node, > return slot_power_limit_mw; > } > EXPORT_SYMBOL_GPL(of_pci_get_slot_power_limit); > + > +/** > + * of_pci_get_equalization_presets - Parses the "eq-presets-Ngts" property. > + * > + * @dev: Device containing the properties. > + * @presets: Pointer to store the parsed data. > + * @num_lanes: Maximum number of lanes supported. > + * > + * If the property is present read and store the data in the preset structure > + * else assign default value 0xff to indicate property is not present. 'If the property is present, read and store the data in the @presets structure. Else, assign a default value of PCI_EQ_RESV.' > + * > + * Return: 0 if the property is not available or successfully parsed; errno otherwise. > + */ > +int of_pci_get_equalization_presets(struct device *dev, > + struct pci_eq_presets *presets, > + int num_lanes) > +{ > + char name[20]; > + int ret; > + > + presets->eq_presets_8gts[0] = PCI_EQ_RESV; > + ret = of_property_read_u16_array(dev->of_node, "eq-presets-8gts", > + presets->eq_presets_8gts, num_lanes); > + if (ret && ret != -EINVAL) { > + dev_err(dev, "Error reading eq-presets-8gts :%d\n", ret); > + return ret; > + } > + > + for (int i = 0; i < EQ_PRESET_TYPE_MAX; i++) { > + presets->eq_presets_Ngts[i][0] = PCI_EQ_RESV; > + snprintf(name, sizeof(name), "eq-presets-%dgts", 8 << (i + 1)); > + ret = of_property_read_u8_array(dev->of_node, name, > + presets->eq_presets_Ngts[i], > + num_lanes); > + if (ret && ret != -EINVAL) { > + dev_err(dev, "Error reading %s :%d\n", name, ret); > + return ret; > + } > + } > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(of_pci_get_equalization_presets); > diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h > index 01e51db8d285..c8d44b21ef03 100644 > --- a/drivers/pci/pci.h > +++ b/drivers/pci/pci.h > @@ -9,6 +9,8 @@ struct pcie_tlp_log; > /* Number of possible devfns: 0.0 to 1f.7 inclusive */ > #define MAX_NR_DEVFNS 256 > > +#define MAX_NR_LANES 16 > + > #define PCI_FIND_CAP_TTL 48 > > #define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */ > @@ -808,6 +810,20 @@ static inline u64 pci_rebar_size_to_bytes(int size) > > struct device_node; > > +#define PCI_EQ_RESV 0xff > + > +enum equalization_preset_type { For the sake of completeness, you should add EQ_PRESET_TYPE_8GTS also. You could skip it while reading the of_property_read_u8_array(). > + EQ_PRESET_TYPE_16GTS, > + EQ_PRESET_TYPE_32GTS, > + EQ_PRESET_TYPE_64GTS, > + EQ_PRESET_TYPE_MAX > +}; > + > +struct pci_eq_presets { > + u16 eq_presets_8gts[MAX_NR_LANES]; > + u8 eq_presets_Ngts[EQ_PRESET_TYPE_MAX][MAX_NR_LANES]; > +}; > + > #ifdef CONFIG_OF > int of_get_pci_domain_nr(struct device_node *node); > int of_pci_get_max_link_speed(struct device_node *node); > @@ -822,7 +838,9 @@ void pci_release_bus_of_node(struct pci_bus *bus); > > int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge); > bool of_pci_supply_present(struct device_node *np); > - > +int of_pci_get_equalization_presets(struct device *dev, > + struct pci_eq_presets *presets, > + int num_lanes); > #else > static inline int > of_get_pci_domain_nr(struct device_node *node) > @@ -867,6 +885,13 @@ static inline bool of_pci_supply_present(struct device_node *np) > { > return false; > } > + > +static inline int of_pci_get_equalization_presets(struct device *dev, > + struct pci_eq_presets *presets, > + int num_lanes) > +{ Don't you need to initialize presets to PCI_EQ_RESV? - Mani
On 3/6/2025 8:52 AM, Manivannan Sadhasivam wrote: > On Tue, Feb 25, 2025 at 05:15:05PM +0530, Krishna Chaitanya Chundru wrote: >> 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, this function >> reads the device tree property and stores in the presets structure. >> >> Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com> >> --- >> drivers/pci/of.c | 43 +++++++++++++++++++++++++++++++++++++++++++ >> drivers/pci/pci.h | 27 ++++++++++++++++++++++++++- >> 2 files changed, 69 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/pci/of.c b/drivers/pci/of.c >> index 7a806f5c0d20..9ebe7d0e4e0c 100644 >> --- a/drivers/pci/of.c >> +++ b/drivers/pci/of.c >> @@ -851,3 +851,46 @@ u32 of_pci_get_slot_power_limit(struct device_node *node, >> return slot_power_limit_mw; >> } >> EXPORT_SYMBOL_GPL(of_pci_get_slot_power_limit); >> + >> +/** >> + * of_pci_get_equalization_presets - Parses the "eq-presets-Ngts" property. >> + * >> + * @dev: Device containing the properties. >> + * @presets: Pointer to store the parsed data. >> + * @num_lanes: Maximum number of lanes supported. >> + * >> + * If the property is present read and store the data in the preset structure >> + * else assign default value 0xff to indicate property is not present. > > 'If the property is present, read and store the data in the @presets structure. > Else, assign a default value of PCI_EQ_RESV.' > >> + * >> + * Return: 0 if the property is not available or successfully parsed; errno otherwise. >> + */ >> +int of_pci_get_equalization_presets(struct device *dev, >> + struct pci_eq_presets *presets, >> + int num_lanes) >> +{ >> + char name[20]; >> + int ret; >> + >> + presets->eq_presets_8gts[0] = PCI_EQ_RESV; >> + ret = of_property_read_u16_array(dev->of_node, "eq-presets-8gts", >> + presets->eq_presets_8gts, num_lanes); >> + if (ret && ret != -EINVAL) { >> + dev_err(dev, "Error reading eq-presets-8gts :%d\n", ret); >> + return ret; >> + } >> + >> + for (int i = 0; i < EQ_PRESET_TYPE_MAX; i++) { >> + presets->eq_presets_Ngts[i][0] = PCI_EQ_RESV; >> + snprintf(name, sizeof(name), "eq-presets-%dgts", 8 << (i + 1)); >> + ret = of_property_read_u8_array(dev->of_node, name, >> + presets->eq_presets_Ngts[i], >> + num_lanes); >> + if (ret && ret != -EINVAL) { >> + dev_err(dev, "Error reading %s :%d\n", name, ret); >> + return ret; >> + } >> + } >> + >> + return 0; >> +} >> +EXPORT_SYMBOL_GPL(of_pci_get_equalization_presets); >> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h >> index 01e51db8d285..c8d44b21ef03 100644 >> --- a/drivers/pci/pci.h >> +++ b/drivers/pci/pci.h >> @@ -9,6 +9,8 @@ struct pcie_tlp_log; >> /* Number of possible devfns: 0.0 to 1f.7 inclusive */ >> #define MAX_NR_DEVFNS 256 >> >> +#define MAX_NR_LANES 16 >> + >> #define PCI_FIND_CAP_TTL 48 >> >> #define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */ >> @@ -808,6 +810,20 @@ static inline u64 pci_rebar_size_to_bytes(int size) >> >> struct device_node; >> >> +#define PCI_EQ_RESV 0xff >> + >> +enum equalization_preset_type { > > For the sake of completeness, you should add EQ_PRESET_TYPE_8GTS also. You could > skip it while reading the of_property_read_u8_array(). Can we add like this to make parsing logic easier otherwise while deference the presets array we need to subtract -1. currently we are using like this presets[EQ_PRESET_TYPE_16GTS] if we want to keep in same way we need to use like below. EQ_PRESET_TYPE_8GTS, EQ_PRESET_TYPE_16GTS = 0, > >> + EQ_PRESET_TYPE_16GTS, >> + EQ_PRESET_TYPE_32GTS, >> + EQ_PRESET_TYPE_64GTS, >> + EQ_PRESET_TYPE_MAX >> +}; >> + >> +struct pci_eq_presets { >> + u16 eq_presets_8gts[MAX_NR_LANES]; >> + u8 eq_presets_Ngts[EQ_PRESET_TYPE_MAX][MAX_NR_LANES]; >> +}; >> + >> #ifdef CONFIG_OF >> int of_get_pci_domain_nr(struct device_node *node); >> int of_pci_get_max_link_speed(struct device_node *node); >> @@ -822,7 +838,9 @@ void pci_release_bus_of_node(struct pci_bus *bus); >> >> int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge); >> bool of_pci_supply_present(struct device_node *np); >> - >> +int of_pci_get_equalization_presets(struct device *dev, >> + struct pci_eq_presets *presets, >> + int num_lanes); >> #else >> static inline int >> of_get_pci_domain_nr(struct device_node *node) >> @@ -867,6 +885,13 @@ static inline bool of_pci_supply_present(struct device_node *np) >> { >> return false; >> } >> + >> +static inline int of_pci_get_equalization_presets(struct device *dev, >> + struct pci_eq_presets *presets, >> + int num_lanes) >> +{ > > Don't you need to initialize presets to PCI_EQ_RESV? > I will update in the next patch. - Krishna Chaitanya. > - Mani >
diff --git a/drivers/pci/of.c b/drivers/pci/of.c index 7a806f5c0d20..9ebe7d0e4e0c 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -851,3 +851,46 @@ u32 of_pci_get_slot_power_limit(struct device_node *node, return slot_power_limit_mw; } EXPORT_SYMBOL_GPL(of_pci_get_slot_power_limit); + +/** + * of_pci_get_equalization_presets - Parses the "eq-presets-Ngts" property. + * + * @dev: Device containing the properties. + * @presets: Pointer to store the parsed data. + * @num_lanes: Maximum number of lanes supported. + * + * If the property is present read and store the data in the preset structure + * else assign default value 0xff to indicate property is not present. + * + * Return: 0 if the property is not available or successfully parsed; errno otherwise. + */ +int of_pci_get_equalization_presets(struct device *dev, + struct pci_eq_presets *presets, + int num_lanes) +{ + char name[20]; + int ret; + + presets->eq_presets_8gts[0] = PCI_EQ_RESV; + ret = of_property_read_u16_array(dev->of_node, "eq-presets-8gts", + presets->eq_presets_8gts, num_lanes); + if (ret && ret != -EINVAL) { + dev_err(dev, "Error reading eq-presets-8gts :%d\n", ret); + return ret; + } + + for (int i = 0; i < EQ_PRESET_TYPE_MAX; i++) { + presets->eq_presets_Ngts[i][0] = PCI_EQ_RESV; + snprintf(name, sizeof(name), "eq-presets-%dgts", 8 << (i + 1)); + ret = of_property_read_u8_array(dev->of_node, name, + presets->eq_presets_Ngts[i], + num_lanes); + if (ret && ret != -EINVAL) { + dev_err(dev, "Error reading %s :%d\n", name, ret); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(of_pci_get_equalization_presets); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 01e51db8d285..c8d44b21ef03 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -9,6 +9,8 @@ struct pcie_tlp_log; /* Number of possible devfns: 0.0 to 1f.7 inclusive */ #define MAX_NR_DEVFNS 256 +#define MAX_NR_LANES 16 + #define PCI_FIND_CAP_TTL 48 #define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */ @@ -808,6 +810,20 @@ static inline u64 pci_rebar_size_to_bytes(int size) struct device_node; +#define PCI_EQ_RESV 0xff + +enum equalization_preset_type { + EQ_PRESET_TYPE_16GTS, + EQ_PRESET_TYPE_32GTS, + EQ_PRESET_TYPE_64GTS, + EQ_PRESET_TYPE_MAX +}; + +struct pci_eq_presets { + u16 eq_presets_8gts[MAX_NR_LANES]; + u8 eq_presets_Ngts[EQ_PRESET_TYPE_MAX][MAX_NR_LANES]; +}; + #ifdef CONFIG_OF int of_get_pci_domain_nr(struct device_node *node); int of_pci_get_max_link_speed(struct device_node *node); @@ -822,7 +838,9 @@ void pci_release_bus_of_node(struct pci_bus *bus); int devm_of_pci_bridge_init(struct device *dev, struct pci_host_bridge *bridge); bool of_pci_supply_present(struct device_node *np); - +int of_pci_get_equalization_presets(struct device *dev, + struct pci_eq_presets *presets, + int num_lanes); #else static inline int of_get_pci_domain_nr(struct device_node *node) @@ -867,6 +885,13 @@ static inline bool of_pci_supply_present(struct device_node *np) { return false; } + +static inline int of_pci_get_equalization_presets(struct device *dev, + struct pci_eq_presets *presets, + int num_lanes) +{ + return 0; +} #endif /* CONFIG_OF */ struct of_changeset;
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, this function reads the device tree property and stores in the presets structure. Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com> --- drivers/pci/of.c | 43 +++++++++++++++++++++++++++++++++++++++++++ drivers/pci/pci.h | 27 ++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-)