]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
PCI: qcom: Program T_POWER_ON
authorKrishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
Tue, 28 Apr 2026 08:37:17 +0000 (14:07 +0530)
committerManivannan Sadhasivam <mani@kernel.org>
Tue, 26 May 2026 14:44:47 +0000 (16:44 +0200)
Some platforms have incorrect T_POWER_ON value programmed in hardware.
Generally these will be corrected by bootloaders, but not all targets
support bootloaders to program correct values. That means the
LTR_L1.2_THRESHOLD value calculated by aspm.c can be wrong, which can
result in improper L1.2 exit behavior. If AER happens to be supported and
enabled, the error may be *reported* via AER.

Parse the 't-power-on-us' property from each Root Port node and program it
as part of host initialization using dw_pcie_program_t_power_on() before
link training.

This property in added to the dtschema here [1].

Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
[mani: reworded comment]
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Link[1]: https://lore.kernel.org/all/20260205093346.667898-1-krishna.chundru@oss.qualcomm.com/
Link: https://patch.msgid.link/20260428-t_power_on_fux-v5-3-f1ef926a91ff@oss.qualcomm.com
drivers/pci/controller/dwc/pcie-qcom.c

index 9173369cca8777ee696838b47506a9e3da26cb1b..65688e28f10d367d25ebcdd8f8dc7fa0e84cd586 100644 (file)
@@ -276,6 +276,7 @@ struct qcom_pcie_perst {
 struct qcom_pcie_port {
        struct list_head list;
        struct phy *phy;
+       u32 l1ss_t_power_on;
        struct list_head perst;
 };
 
@@ -1349,6 +1350,14 @@ static int qcom_pcie_phy_power_on(struct qcom_pcie *pcie)
        return 0;
 }
 
+static void qcom_pcie_configure_ports(struct qcom_pcie *pcie)
+{
+       struct qcom_pcie_port *port;
+
+       list_for_each_entry(port, &pcie->ports, list)
+               dw_pcie_program_t_power_on(pcie->pci, port->l1ss_t_power_on);
+}
+
 static int qcom_pcie_host_init(struct dw_pcie_rp *pp)
 {
        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
@@ -1387,6 +1396,8 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp)
        dw_pcie_remove_capability(pcie->pci, PCI_CAP_ID_MSIX);
        dw_pcie_remove_ext_capability(pcie->pci, PCI_EXT_CAP_ID_DPC);
 
+       qcom_pcie_configure_ports(pcie);
+
        qcom_pcie_perst_deassert(pcie);
 
        if (pcie->cfg->ops->config_sid) {
@@ -1868,6 +1879,9 @@ static int qcom_pcie_parse_port(struct qcom_pcie *pcie, struct device_node *node
        if (ret)
                return ret;
 
+       /* TODO: Move to DWC core after multi Root Port support is added */
+       of_property_read_u32(node, "t-power-on-us", &port->l1ss_t_power_on);
+
        port->phy = phy;
        INIT_LIST_HEAD(&port->list);
        list_add_tail(&port->list, &pcie->ports);