diff options
Diffstat (limited to 'drivers/pci/controller/dwc/pcie-qcom.c')
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-qcom.c | 96 | 
1 files changed, 85 insertions, 11 deletions
| diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 8a7a300163e5..1c3d1116bb60 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -166,6 +166,9 @@ struct qcom_pcie_resources_2_7_0 {  	struct regulator_bulk_data supplies[2];  	struct reset_control *pci_reset;  	struct clk *pipe_clk; +	struct clk *pipe_clk_src; +	struct clk *phy_pipe_clk; +	struct clk *ref_clk_src;  };  union qcom_pcie_resources { @@ -189,6 +192,11 @@ struct qcom_pcie_ops {  	int (*config_sid)(struct qcom_pcie *pcie);  }; +struct qcom_pcie_cfg { +	const struct qcom_pcie_ops *ops; +	unsigned int pipe_clk_need_muxing:1; +}; +  struct qcom_pcie {  	struct dw_pcie *pci;  	void __iomem *parf;			/* DT parf */ @@ -197,6 +205,7 @@ struct qcom_pcie {  	struct phy *phy;  	struct gpio_desc *reset;  	const struct qcom_pcie_ops *ops; +	unsigned int pipe_clk_need_muxing:1;  };  #define to_qcom_pcie(x)		dev_get_drvdata((x)->dev) @@ -1167,6 +1176,20 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)  	if (ret < 0)  		return ret; +	if (pcie->pipe_clk_need_muxing) { +		res->pipe_clk_src = devm_clk_get(dev, "pipe_mux"); +		if (IS_ERR(res->pipe_clk_src)) +			return PTR_ERR(res->pipe_clk_src); + +		res->phy_pipe_clk = devm_clk_get(dev, "phy_pipe"); +		if (IS_ERR(res->phy_pipe_clk)) +			return PTR_ERR(res->phy_pipe_clk); + +		res->ref_clk_src = devm_clk_get(dev, "ref"); +		if (IS_ERR(res->ref_clk_src)) +			return PTR_ERR(res->ref_clk_src); +	} +  	res->pipe_clk = devm_clk_get(dev, "pipe");  	return PTR_ERR_OR_ZERO(res->pipe_clk);  } @@ -1185,6 +1208,10 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)  		return ret;  	} +	/* Set TCXO as clock source for pcie_pipe_clk_src */ +	if (pcie->pipe_clk_need_muxing) +		clk_set_parent(res->pipe_clk_src, res->ref_clk_src); +  	ret = clk_bulk_prepare_enable(res->num_clks, res->clks);  	if (ret < 0)  		goto err_disable_regulators; @@ -1256,6 +1283,10 @@ 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; +	/* Set pipe clock as clock source for pcie_pipe_clk_src */ +	if (pcie->pipe_clk_need_muxing) +		clk_set_parent(res->pipe_clk_src, res->phy_pipe_clk); +  	return clk_prepare_enable(res->pipe_clk);  } @@ -1456,6 +1487,39 @@ static const struct qcom_pcie_ops ops_1_9_0 = {  	.config_sid = qcom_pcie_config_sid_sm8250,  }; +static const struct qcom_pcie_cfg apq8084_cfg = { +	.ops = &ops_1_0_0, +}; + +static const struct qcom_pcie_cfg ipq8064_cfg = { +	.ops = &ops_2_1_0, +}; + +static const struct qcom_pcie_cfg msm8996_cfg = { +	.ops = &ops_2_3_2, +}; + +static const struct qcom_pcie_cfg ipq8074_cfg = { +	.ops = &ops_2_3_3, +}; + +static const struct qcom_pcie_cfg ipq4019_cfg = { +	.ops = &ops_2_4_0, +}; + +static const struct qcom_pcie_cfg sdm845_cfg = { +	.ops = &ops_2_7_0, +}; + +static const struct qcom_pcie_cfg sm8250_cfg = { +	.ops = &ops_1_9_0, +}; + +static const struct qcom_pcie_cfg sc7280_cfg = { +	.ops = &ops_1_9_0, +	.pipe_clk_need_muxing = true, +}; +  static const struct dw_pcie_ops dw_pcie_ops = {  	.link_up = qcom_pcie_link_up,  	.start_link = qcom_pcie_start_link, @@ -1467,6 +1531,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)  	struct pcie_port *pp;  	struct dw_pcie *pci;  	struct qcom_pcie *pcie; +	const struct qcom_pcie_cfg *pcie_cfg;  	int ret;  	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); @@ -1488,7 +1553,14 @@ static int qcom_pcie_probe(struct platform_device *pdev)  	pcie->pci = pci; -	pcie->ops = of_device_get_match_data(dev); +	pcie_cfg = of_device_get_match_data(dev); +	if (!pcie_cfg || !pcie_cfg->ops) { +		dev_err(dev, "Invalid platform data\n"); +		return -EINVAL; +	} + +	pcie->ops = pcie_cfg->ops; +	pcie->pipe_clk_need_muxing = pcie_cfg->pipe_clk_need_muxing;  	pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_HIGH);  	if (IS_ERR(pcie->reset)) { @@ -1545,16 +1617,18 @@ err_pm_runtime_put:  }  static const struct of_device_id qcom_pcie_match[] = { -	{ .compatible = "qcom,pcie-apq8084", .data = &ops_1_0_0 }, -	{ .compatible = "qcom,pcie-ipq8064", .data = &ops_2_1_0 }, -	{ .compatible = "qcom,pcie-ipq8064-v2", .data = &ops_2_1_0 }, -	{ .compatible = "qcom,pcie-apq8064", .data = &ops_2_1_0 }, -	{ .compatible = "qcom,pcie-msm8996", .data = &ops_2_3_2 }, -	{ .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 }, -	{ .compatible = "qcom,pcie-sm8250", .data = &ops_1_9_0 }, +	{ .compatible = "qcom,pcie-apq8084", .data = &apq8084_cfg }, +	{ .compatible = "qcom,pcie-ipq8064", .data = &ipq8064_cfg }, +	{ .compatible = "qcom,pcie-ipq8064-v2", .data = &ipq8064_cfg }, +	{ .compatible = "qcom,pcie-apq8064", .data = &ipq8064_cfg }, +	{ .compatible = "qcom,pcie-msm8996", .data = &msm8996_cfg }, +	{ .compatible = "qcom,pcie-ipq8074", .data = &ipq8074_cfg }, +	{ .compatible = "qcom,pcie-ipq4019", .data = &ipq4019_cfg }, +	{ .compatible = "qcom,pcie-qcs404", .data = &ipq4019_cfg }, +	{ .compatible = "qcom,pcie-sdm845", .data = &sdm845_cfg }, +	{ .compatible = "qcom,pcie-sm8250", .data = &sm8250_cfg }, +	{ .compatible = "qcom,pcie-sc8180x", .data = &sm8250_cfg }, +	{ .compatible = "qcom,pcie-sc7280", .data = &sc7280_cfg },  	{ }  }; |