Merge branch 'remotes/lorenzo/pci/qcom'

- Save pointer to device match data instead of copying it (Dmitry
  Baryshkov)

- Add ddrss_sf_tbu flag to device match data instead of checking OF
  compatible string (Dmitry Baryshkov)

- Add SM8450 SoC PCIe DT bindings (Dmitry Baryshkov)

- Add SM8450 PCIe support (Dmitry Baryshkov)

* remotes/lorenzo/pci/qcom:
  PCI: qcom: Add SM8450 PCIe support
  PCI: qcom: Add ddrss_sf_tbu flag
  PCI: qcom: Remove redundancy between qcom_pcie and qcom_pcie_cfg
  dt-bindings: pci: qcom: Document PCIe bindings for SM8450
This commit is contained in:
Bjorn Helgaas
2022-03-22 17:16:26 -05:00
2 changed files with 83 additions and 32 deletions

View File

@@ -15,6 +15,8 @@
- "qcom,pcie-sc8180x" for sc8180x - "qcom,pcie-sc8180x" for sc8180x
- "qcom,pcie-sdm845" for sdm845 - "qcom,pcie-sdm845" for sdm845
- "qcom,pcie-sm8250" for sm8250 - "qcom,pcie-sm8250" for sm8250
- "qcom,pcie-sm8450-pcie0" for PCIe0 on sm8450
- "qcom,pcie-sm8450-pcie1" for PCIe1 on sm8450
- "qcom,pcie-ipq6018" for ipq6018 - "qcom,pcie-ipq6018" for ipq6018
- reg: - reg:
@@ -169,6 +171,24 @@
- "ddrss_sf_tbu" PCIe SF TBU clock - "ddrss_sf_tbu" PCIe SF TBU clock
- "pipe" PIPE clock - "pipe" PIPE clock
- clock-names:
Usage: required for sm8450-pcie0 and sm8450-pcie1
Value type: <stringlist>
Definition: Should contain the following entries
- "aux" Auxiliary clock
- "cfg" Configuration clock
- "bus_master" Master AXI clock
- "bus_slave" Slave AXI clock
- "slave_q2a" Slave Q2A clock
- "tbu" PCIe TBU clock
- "ddrss_sf_tbu" PCIe SF TBU clock
- "pipe" PIPE clock
- "pipe_mux" PIPE MUX
- "phy_pipe" PIPE output clock
- "ref" REFERENCE clock
- "aggre0" Aggre NoC PCIe0 AXI clock, only for sm8450-pcie0
- "aggre1" Aggre NoC PCIe1 AXI clock
- resets: - resets:
Usage: required Usage: required
Value type: <prop-encoded-array> Value type: <prop-encoded-array>
@@ -246,7 +266,7 @@
- "ahb" AHB reset - "ahb" AHB reset
- reset-names: - reset-names:
Usage: required for sc8180x, sdm845 and sm8250 Usage: required for sc8180x, sdm845, sm8250 and sm8450
Value type: <stringlist> Value type: <stringlist>
Definition: Should contain the following entries Definition: Should contain the following entries
- "pci" PCIe core reset - "pci" PCIe core reset

View File

@@ -161,7 +161,7 @@ struct qcom_pcie_resources_2_3_3 {
/* 6 clocks typically, 7 for sm8250 */ /* 6 clocks typically, 7 for sm8250 */
struct qcom_pcie_resources_2_7_0 { struct qcom_pcie_resources_2_7_0 {
struct clk_bulk_data clks[7]; struct clk_bulk_data clks[9];
int num_clks; int num_clks;
struct regulator_bulk_data supplies[2]; struct regulator_bulk_data supplies[2];
struct reset_control *pci_reset; struct reset_control *pci_reset;
@@ -195,6 +195,10 @@ struct qcom_pcie_ops {
struct qcom_pcie_cfg { struct qcom_pcie_cfg {
const struct qcom_pcie_ops *ops; const struct qcom_pcie_ops *ops;
unsigned int pipe_clk_need_muxing:1; unsigned int pipe_clk_need_muxing:1;
unsigned int has_tbu_clk:1;
unsigned int has_ddrss_sf_tbu_clk:1;
unsigned int has_aggre0_clk:1;
unsigned int has_aggre1_clk:1;
}; };
struct qcom_pcie { struct qcom_pcie {
@@ -204,8 +208,7 @@ struct qcom_pcie {
union qcom_pcie_resources res; union qcom_pcie_resources res;
struct phy *phy; struct phy *phy;
struct gpio_desc *reset; struct gpio_desc *reset;
const struct qcom_pcie_ops *ops; const struct qcom_pcie_cfg *cfg;
unsigned int pipe_clk_need_muxing:1;
}; };
#define to_qcom_pcie(x) dev_get_drvdata((x)->dev) #define to_qcom_pcie(x) dev_get_drvdata((x)->dev)
@@ -229,8 +232,8 @@ static int qcom_pcie_start_link(struct dw_pcie *pci)
struct qcom_pcie *pcie = to_qcom_pcie(pci); struct qcom_pcie *pcie = to_qcom_pcie(pci);
/* Enable Link Training state machine */ /* Enable Link Training state machine */
if (pcie->ops->ltssm_enable) if (pcie->cfg->ops->ltssm_enable)
pcie->ops->ltssm_enable(pcie); pcie->cfg->ops->ltssm_enable(pcie);
return 0; return 0;
} }
@@ -1146,6 +1149,7 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)
struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
struct dw_pcie *pci = pcie->pci; struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev; struct device *dev = pci->dev;
unsigned int idx;
int ret; int ret;
res->pci_reset = devm_reset_control_get_exclusive(dev, "pci"); res->pci_reset = devm_reset_control_get_exclusive(dev, "pci");
@@ -1159,24 +1163,28 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)
if (ret) if (ret)
return ret; return ret;
res->clks[0].id = "aux"; idx = 0;
res->clks[1].id = "cfg"; res->clks[idx++].id = "aux";
res->clks[2].id = "bus_master"; res->clks[idx++].id = "cfg";
res->clks[3].id = "bus_slave"; res->clks[idx++].id = "bus_master";
res->clks[4].id = "slave_q2a"; res->clks[idx++].id = "bus_slave";
res->clks[5].id = "tbu"; res->clks[idx++].id = "slave_q2a";
if (of_device_is_compatible(dev->of_node, "qcom,pcie-sm8250")) { if (pcie->cfg->has_tbu_clk)
res->clks[6].id = "ddrss_sf_tbu"; res->clks[idx++].id = "tbu";
res->num_clks = 7; if (pcie->cfg->has_ddrss_sf_tbu_clk)
} else { res->clks[idx++].id = "ddrss_sf_tbu";
res->num_clks = 6; if (pcie->cfg->has_aggre0_clk)
} res->clks[idx++].id = "aggre0";
if (pcie->cfg->has_aggre1_clk)
res->clks[idx++].id = "aggre1";
res->num_clks = idx;
ret = devm_clk_bulk_get(dev, res->num_clks, res->clks); ret = devm_clk_bulk_get(dev, res->num_clks, res->clks);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (pcie->pipe_clk_need_muxing) { if (pcie->cfg->pipe_clk_need_muxing) {
res->pipe_clk_src = devm_clk_get(dev, "pipe_mux"); res->pipe_clk_src = devm_clk_get(dev, "pipe_mux");
if (IS_ERR(res->pipe_clk_src)) if (IS_ERR(res->pipe_clk_src))
return PTR_ERR(res->pipe_clk_src); return PTR_ERR(res->pipe_clk_src);
@@ -1209,7 +1217,7 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
} }
/* Set TCXO as clock source for pcie_pipe_clk_src */ /* Set TCXO as clock source for pcie_pipe_clk_src */
if (pcie->pipe_clk_need_muxing) if (pcie->cfg->pipe_clk_need_muxing)
clk_set_parent(res->pipe_clk_src, res->ref_clk_src); clk_set_parent(res->pipe_clk_src, res->ref_clk_src);
ret = clk_bulk_prepare_enable(res->num_clks, res->clks); ret = clk_bulk_prepare_enable(res->num_clks, res->clks);
@@ -1236,6 +1244,9 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
goto err_disable_clocks; goto err_disable_clocks;
} }
/* Wait for reset to complete, required on SM8450 */
usleep_range(1000, 1500);
/* configure PCIe to RC mode */ /* configure PCIe to RC mode */
writel(DEVICE_TYPE_RC, pcie->parf + PCIE20_PARF_DEVICE_TYPE); writel(DEVICE_TYPE_RC, pcie->parf + PCIE20_PARF_DEVICE_TYPE);
@@ -1284,7 +1295,7 @@ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
/* Set pipe clock as clock source for pcie_pipe_clk_src */ /* Set pipe clock as clock source for pcie_pipe_clk_src */
if (pcie->pipe_clk_need_muxing) if (pcie->cfg->pipe_clk_need_muxing)
clk_set_parent(res->pipe_clk_src, res->phy_pipe_clk); clk_set_parent(res->pipe_clk_src, res->phy_pipe_clk);
return clk_prepare_enable(res->pipe_clk); return clk_prepare_enable(res->pipe_clk);
@@ -1384,7 +1395,7 @@ static int qcom_pcie_host_init(struct pcie_port *pp)
qcom_ep_reset_assert(pcie); qcom_ep_reset_assert(pcie);
ret = pcie->ops->init(pcie); ret = pcie->cfg->ops->init(pcie);
if (ret) if (ret)
return ret; return ret;
@@ -1392,16 +1403,16 @@ static int qcom_pcie_host_init(struct pcie_port *pp)
if (ret) if (ret)
goto err_deinit; goto err_deinit;
if (pcie->ops->post_init) { if (pcie->cfg->ops->post_init) {
ret = pcie->ops->post_init(pcie); ret = pcie->cfg->ops->post_init(pcie);
if (ret) if (ret)
goto err_disable_phy; goto err_disable_phy;
} }
qcom_ep_reset_deassert(pcie); qcom_ep_reset_deassert(pcie);
if (pcie->ops->config_sid) { if (pcie->cfg->ops->config_sid) {
ret = pcie->ops->config_sid(pcie); ret = pcie->cfg->ops->config_sid(pcie);
if (ret) if (ret)
goto err; goto err;
} }
@@ -1410,12 +1421,12 @@ static int qcom_pcie_host_init(struct pcie_port *pp)
err: err:
qcom_ep_reset_assert(pcie); qcom_ep_reset_assert(pcie);
if (pcie->ops->post_deinit) if (pcie->cfg->ops->post_deinit)
pcie->ops->post_deinit(pcie); pcie->cfg->ops->post_deinit(pcie);
err_disable_phy: err_disable_phy:
phy_power_off(pcie->phy); phy_power_off(pcie->phy);
err_deinit: err_deinit:
pcie->ops->deinit(pcie); pcie->cfg->ops->deinit(pcie);
return ret; return ret;
} }
@@ -1509,14 +1520,33 @@ static const struct qcom_pcie_cfg ipq4019_cfg = {
static const struct qcom_pcie_cfg sdm845_cfg = { static const struct qcom_pcie_cfg sdm845_cfg = {
.ops = &ops_2_7_0, .ops = &ops_2_7_0,
.has_tbu_clk = true,
}; };
static const struct qcom_pcie_cfg sm8250_cfg = { static const struct qcom_pcie_cfg sm8250_cfg = {
.ops = &ops_1_9_0, .ops = &ops_1_9_0,
.has_tbu_clk = true,
.has_ddrss_sf_tbu_clk = true,
};
static const struct qcom_pcie_cfg sm8450_pcie0_cfg = {
.ops = &ops_1_9_0,
.has_ddrss_sf_tbu_clk = true,
.pipe_clk_need_muxing = true,
.has_aggre0_clk = true,
.has_aggre1_clk = true,
};
static const struct qcom_pcie_cfg sm8450_pcie1_cfg = {
.ops = &ops_1_9_0,
.has_ddrss_sf_tbu_clk = true,
.pipe_clk_need_muxing = true,
.has_aggre1_clk = true,
}; };
static const struct qcom_pcie_cfg sc7280_cfg = { static const struct qcom_pcie_cfg sc7280_cfg = {
.ops = &ops_1_9_0, .ops = &ops_1_9_0,
.has_tbu_clk = true,
.pipe_clk_need_muxing = true, .pipe_clk_need_muxing = true,
}; };
@@ -1559,8 +1589,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
pcie->pci = pci; pcie->pci = pci;
pcie->ops = pcie_cfg->ops; pcie->cfg = pcie_cfg;
pcie->pipe_clk_need_muxing = pcie_cfg->pipe_clk_need_muxing;
pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_HIGH); pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_HIGH);
if (IS_ERR(pcie->reset)) { if (IS_ERR(pcie->reset)) {
@@ -1586,7 +1615,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
goto err_pm_runtime_put; goto err_pm_runtime_put;
} }
ret = pcie->ops->get_resources(pcie); ret = pcie->cfg->ops->get_resources(pcie);
if (ret) if (ret)
goto err_pm_runtime_put; goto err_pm_runtime_put;
@@ -1628,6 +1657,8 @@ static const struct of_device_id qcom_pcie_match[] = {
{ .compatible = "qcom,pcie-sdm845", .data = &sdm845_cfg }, { .compatible = "qcom,pcie-sdm845", .data = &sdm845_cfg },
{ .compatible = "qcom,pcie-sm8250", .data = &sm8250_cfg }, { .compatible = "qcom,pcie-sm8250", .data = &sm8250_cfg },
{ .compatible = "qcom,pcie-sc8180x", .data = &sm8250_cfg }, { .compatible = "qcom,pcie-sc8180x", .data = &sm8250_cfg },
{ .compatible = "qcom,pcie-sm8450-pcie0", .data = &sm8450_pcie0_cfg },
{ .compatible = "qcom,pcie-sm8450-pcie1", .data = &sm8450_pcie1_cfg },
{ .compatible = "qcom,pcie-sc7280", .data = &sc7280_cfg }, { .compatible = "qcom,pcie-sc7280", .data = &sc7280_cfg },
{ } { }
}; };