Skip to content

Commit

Permalink
PCI: qcom: Add support for SDM845 PCIe controller
Browse files Browse the repository at this point in the history
The SDM845 has one Gen2 and one Gen3 controller, add support for these.

Signed-off-by: Bjorn Andersson <[email protected]>
Signed-off-by: Lorenzo Pieralisi <[email protected]>
Reviewed-by: Vinod Koul <[email protected]>
Reviewed-by: Philipp Zabel <[email protected]>
Reviewed-by: Andrew Murray <[email protected]>
Acked-by: Stanimir Varbanov <[email protected]>
  • Loading branch information
andersson authored and Lorenzo Pieralisi committed Jan 10, 2020
1 parent 5d28bee commit ed8cc3b
Showing 1 changed file with 150 additions and 0 deletions.
150 changes: 150 additions & 0 deletions drivers/pci/controller/dwc/pcie-qcom.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#define PCIE20_PARF_LTSSM 0x1B0
#define PCIE20_PARF_SID_OFFSET 0x234
#define PCIE20_PARF_BDF_TRANSLATE_CFG 0x24C
#define PCIE20_PARF_DEVICE_TYPE 0x1000

#define PCIE20_ELBI_SYS_CTRL 0x04
#define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0)
Expand All @@ -80,6 +81,8 @@
#define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE 0x358
#define SLV_ADDR_SPACE_SZ 0x10000000

#define DEVICE_TYPE_RC 0x4

#define QCOM_PCIE_2_1_0_MAX_SUPPLY 3
struct qcom_pcie_resources_2_1_0 {
struct clk *iface_clk;
Expand Down Expand Up @@ -139,12 +142,20 @@ struct qcom_pcie_resources_2_3_3 {
struct reset_control *rst[7];
};

struct qcom_pcie_resources_2_7_0 {
struct clk_bulk_data clks[6];
struct regulator_bulk_data supplies[2];
struct reset_control *pci_reset;
struct clk *pipe_clk;
};

union qcom_pcie_resources {
struct qcom_pcie_resources_1_0_0 v1_0_0;
struct qcom_pcie_resources_2_1_0 v2_1_0;
struct qcom_pcie_resources_2_3_2 v2_3_2;
struct qcom_pcie_resources_2_3_3 v2_3_3;
struct qcom_pcie_resources_2_4_0 v2_4_0;
struct qcom_pcie_resources_2_7_0 v2_7_0;
};

struct qcom_pcie;
Expand Down Expand Up @@ -1068,6 +1079,134 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)
return ret;
}

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 dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
int ret;

res->pci_reset = devm_reset_control_get_exclusive(dev, "pci");
if (IS_ERR(res->pci_reset))
return PTR_ERR(res->pci_reset);

res->supplies[0].supply = "vdda";
res->supplies[1].supply = "vddpe-3v3";
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(res->supplies),
res->supplies);
if (ret)
return ret;

res->clks[0].id = "aux";
res->clks[1].id = "cfg";
res->clks[2].id = "bus_master";
res->clks[3].id = "bus_slave";
res->clks[4].id = "slave_q2a";
res->clks[5].id = "tbu";

ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks);
if (ret < 0)
return ret;

res->pipe_clk = devm_clk_get(dev, "pipe");
return PTR_ERR_OR_ZERO(res->pipe_clk);
}

static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
u32 val;
int ret;

ret = regulator_bulk_enable(ARRAY_SIZE(res->supplies), res->supplies);
if (ret < 0) {
dev_err(dev, "cannot enable regulators\n");
return ret;
}

ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks);
if (ret < 0)
goto err_disable_regulators;

ret = reset_control_assert(res->pci_reset);
if (ret < 0) {
dev_err(dev, "cannot deassert pci reset\n");
goto err_disable_clocks;
}

usleep_range(1000, 1500);

ret = reset_control_deassert(res->pci_reset);
if (ret < 0) {
dev_err(dev, "cannot deassert pci reset\n");
goto err_disable_clocks;
}

ret = clk_prepare_enable(res->pipe_clk);
if (ret) {
dev_err(dev, "cannot prepare/enable pipe clock\n");
goto err_disable_clocks;
}

/* configure PCIe to RC mode */
writel(DEVICE_TYPE_RC, pcie->parf + PCIE20_PARF_DEVICE_TYPE);

/* enable PCIe clocks and resets */
val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
val &= ~BIT(0);
writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);

/* change DBI base address */
writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);

/* MAC PHY_POWERDOWN MUX DISABLE */
val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL);
val &= ~BIT(29);
writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL);

val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
val |= BIT(4);
writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);

if (IS_ENABLED(CONFIG_PCI_MSI)) {
val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
val |= BIT(31);
writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
}

return 0;
err_disable_clocks:
clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks);
err_disable_regulators:
regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);

return ret;
}

static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;

clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks);
regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
}

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;

return clk_prepare_enable(res->pipe_clk);
}

static void qcom_pcie_post_deinit_2_7_0(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;

clk_disable_unprepare(res->pipe_clk);
}

static int qcom_pcie_link_up(struct dw_pcie *pci)
{
u16 val = readw(pci->dbi_base + PCIE20_CAP + PCI_EXP_LNKSTA);
Expand Down Expand Up @@ -1167,6 +1306,16 @@ static const struct qcom_pcie_ops ops_2_3_3 = {
.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
};

/* Qcom IP rev.: 2.7.0 Synopsys IP rev.: 4.30a */
static const struct qcom_pcie_ops ops_2_7_0 = {
.get_resources = qcom_pcie_get_resources_2_7_0,
.init = qcom_pcie_init_2_7_0,
.deinit = qcom_pcie_deinit_2_7_0,
.ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
.post_init = qcom_pcie_post_init_2_7_0,
.post_deinit = qcom_pcie_post_deinit_2_7_0,
};

static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = qcom_pcie_link_up,
};
Expand Down Expand Up @@ -1282,6 +1431,7 @@ static const struct of_device_id qcom_pcie_match[] = {
{ .compatible = "qcom,pcie-ipq8074", .data = &ops_2_3_3 },
{ .compatible = "qcom,pcie-ipq4019", .data = &ops_2_4_0 },
{ .compatible = "qcom,pcie-qcs404", .data = &ops_2_4_0 },
{ .compatible = "qcom,pcie-sdm845", .data = &ops_2_7_0 },
{ }
};

Expand Down

0 comments on commit ed8cc3b

Please sign in to comment.