mirror of
https://gitee.com/openharmony/kernel_linux
synced 2025-02-22 12:44:50 +00:00
Merge branch 'pci/host-qcom' into next
* pci/host-qcom: PCI: qcom: Limit TLP size to 2K to work around hardware issue PCI: qcom: Fix spelling mistake: "asser" -> "assert" PCI: qcom: Reorder to put v0 functions together, v1 functions together, etc PCI: qcom: Add support for IPQ4019 PCIe controller
This commit is contained in:
commit
bec36cfa7b
@ -8,6 +8,7 @@
|
||||
- "qcom,pcie-apq8064" for apq8064
|
||||
- "qcom,pcie-apq8084" for apq8084
|
||||
- "qcom,pcie-msm8996" for msm8996 or apq8096
|
||||
- "qcom,pcie-ipq4019" for ipq4019
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
@ -87,7 +88,7 @@
|
||||
- "core" Clocks the pcie hw block
|
||||
- "phy" Clocks the pcie PHY block
|
||||
- clock-names:
|
||||
Usage: required for apq8084
|
||||
Usage: required for apq8084/ipq4019
|
||||
Value type: <stringlist>
|
||||
Definition: Should contain the following entries
|
||||
- "aux" Auxiliary (AUX) clock
|
||||
@ -126,6 +127,23 @@
|
||||
Definition: Should contain the following entries
|
||||
- "core" Core reset
|
||||
|
||||
- reset-names:
|
||||
Usage: required for ipq/apq8064
|
||||
Value type: <stringlist>
|
||||
Definition: Should contain the following entries
|
||||
- "axi_m" AXI master reset
|
||||
- "axi_s" AXI slave reset
|
||||
- "pipe" PIPE reset
|
||||
- "axi_m_vmid" VMID reset
|
||||
- "axi_s_xpu" XPU reset
|
||||
- "parf" PARF reset
|
||||
- "phy" PHY reset
|
||||
- "axi_m_sticky" AXI sticky reset
|
||||
- "pipe_sticky" PIPE sticky reset
|
||||
- "pwr" PWR reset
|
||||
- "ahb" AHB reset
|
||||
- "phy_ahb" PHY AHB reset
|
||||
|
||||
- power-domains:
|
||||
Usage: required for apq8084 and msm8996/apq8096
|
||||
Value type: <prop-encoded-array>
|
||||
|
@ -51,6 +51,12 @@
|
||||
#define PCIE20_ELBI_SYS_CTRL 0x04
|
||||
#define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0)
|
||||
|
||||
#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0 0x818
|
||||
#define CFG_REMOTE_RD_REQ_BRIDGE_SIZE_2K 0x4
|
||||
#define CFG_REMOTE_RD_REQ_BRIDGE_SIZE_4K 0x5
|
||||
#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1 0x81c
|
||||
#define CFG_BRIDGE_SB_INIT BIT(0)
|
||||
|
||||
#define PCIE20_CAP 0x70
|
||||
|
||||
#define PERST_DELAY_US 1000
|
||||
@ -86,10 +92,29 @@ struct qcom_pcie_resources_v2 {
|
||||
struct clk *pipe_clk;
|
||||
};
|
||||
|
||||
struct qcom_pcie_resources_v3 {
|
||||
struct clk *aux_clk;
|
||||
struct clk *master_clk;
|
||||
struct clk *slave_clk;
|
||||
struct reset_control *axi_m_reset;
|
||||
struct reset_control *axi_s_reset;
|
||||
struct reset_control *pipe_reset;
|
||||
struct reset_control *axi_m_vmid_reset;
|
||||
struct reset_control *axi_s_xpu_reset;
|
||||
struct reset_control *parf_reset;
|
||||
struct reset_control *phy_reset;
|
||||
struct reset_control *axi_m_sticky_reset;
|
||||
struct reset_control *pipe_sticky_reset;
|
||||
struct reset_control *pwr_reset;
|
||||
struct reset_control *ahb_reset;
|
||||
struct reset_control *phy_ahb_reset;
|
||||
};
|
||||
|
||||
union qcom_pcie_resources {
|
||||
struct qcom_pcie_resources_v0 v0;
|
||||
struct qcom_pcie_resources_v1 v1;
|
||||
struct qcom_pcie_resources_v2 v2;
|
||||
struct qcom_pcie_resources_v3 v3;
|
||||
};
|
||||
|
||||
struct qcom_pcie;
|
||||
@ -133,26 +158,6 @@ static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg)
|
||||
return dw_handle_msi_irq(pp);
|
||||
}
|
||||
|
||||
static void qcom_pcie_v0_v1_ltssm_enable(struct qcom_pcie *pcie)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* enable link training */
|
||||
val = readl(pcie->elbi + PCIE20_ELBI_SYS_CTRL);
|
||||
val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE;
|
||||
writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL);
|
||||
}
|
||||
|
||||
static void qcom_pcie_v2_ltssm_enable(struct qcom_pcie *pcie)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* enable link training */
|
||||
val = readl(pcie->parf + PCIE20_PARF_LTSSM);
|
||||
val |= BIT(8);
|
||||
writel(val, pcie->parf + PCIE20_PARF_LTSSM);
|
||||
}
|
||||
|
||||
static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct dw_pcie *pci = pcie->pci;
|
||||
@ -167,6 +172,16 @@ static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
|
||||
return dw_pcie_wait_for_link(pci);
|
||||
}
|
||||
|
||||
static void qcom_pcie_v0_v1_ltssm_enable(struct qcom_pcie *pcie)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* enable link training */
|
||||
val = readl(pcie->elbi + PCIE20_ELBI_SYS_CTRL);
|
||||
val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE;
|
||||
writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL);
|
||||
}
|
||||
|
||||
static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
|
||||
@ -217,36 +232,6 @@ static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
|
||||
return PTR_ERR_OR_ZERO(res->phy_reset);
|
||||
}
|
||||
|
||||
static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
|
||||
struct dw_pcie *pci = pcie->pci;
|
||||
struct device *dev = pci->dev;
|
||||
|
||||
res->vdda = devm_regulator_get(dev, "vdda");
|
||||
if (IS_ERR(res->vdda))
|
||||
return PTR_ERR(res->vdda);
|
||||
|
||||
res->iface = devm_clk_get(dev, "iface");
|
||||
if (IS_ERR(res->iface))
|
||||
return PTR_ERR(res->iface);
|
||||
|
||||
res->aux = devm_clk_get(dev, "aux");
|
||||
if (IS_ERR(res->aux))
|
||||
return PTR_ERR(res->aux);
|
||||
|
||||
res->master_bus = devm_clk_get(dev, "master_bus");
|
||||
if (IS_ERR(res->master_bus))
|
||||
return PTR_ERR(res->master_bus);
|
||||
|
||||
res->slave_bus = devm_clk_get(dev, "slave_bus");
|
||||
if (IS_ERR(res->slave_bus))
|
||||
return PTR_ERR(res->slave_bus);
|
||||
|
||||
res->core = devm_reset_control_get(dev, "core");
|
||||
return PTR_ERR_OR_ZERO(res->core);
|
||||
}
|
||||
|
||||
static void qcom_pcie_deinit_v0(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
|
||||
@ -357,6 +342,13 @@ static int qcom_pcie_init_v0(struct qcom_pcie *pcie)
|
||||
/* wait for clock acquisition */
|
||||
usleep_range(1000, 1500);
|
||||
|
||||
|
||||
/* Set the Max TLP size to 2K, instead of using default of 4K */
|
||||
writel(CFG_REMOTE_RD_REQ_BRIDGE_SIZE_2K,
|
||||
pci->dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL0);
|
||||
writel(CFG_BRIDGE_SB_INIT,
|
||||
pci->dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1);
|
||||
|
||||
return 0;
|
||||
|
||||
err_deassert_ahb:
|
||||
@ -375,6 +367,36 @@ err_refclk:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
|
||||
struct dw_pcie *pci = pcie->pci;
|
||||
struct device *dev = pci->dev;
|
||||
|
||||
res->vdda = devm_regulator_get(dev, "vdda");
|
||||
if (IS_ERR(res->vdda))
|
||||
return PTR_ERR(res->vdda);
|
||||
|
||||
res->iface = devm_clk_get(dev, "iface");
|
||||
if (IS_ERR(res->iface))
|
||||
return PTR_ERR(res->iface);
|
||||
|
||||
res->aux = devm_clk_get(dev, "aux");
|
||||
if (IS_ERR(res->aux))
|
||||
return PTR_ERR(res->aux);
|
||||
|
||||
res->master_bus = devm_clk_get(dev, "master_bus");
|
||||
if (IS_ERR(res->master_bus))
|
||||
return PTR_ERR(res->master_bus);
|
||||
|
||||
res->slave_bus = devm_clk_get(dev, "slave_bus");
|
||||
if (IS_ERR(res->slave_bus))
|
||||
return PTR_ERR(res->slave_bus);
|
||||
|
||||
res->core = devm_reset_control_get(dev, "core");
|
||||
return PTR_ERR_OR_ZERO(res->core);
|
||||
}
|
||||
|
||||
static void qcom_pcie_deinit_v1(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
|
||||
@ -455,6 +477,16 @@ err_res:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qcom_pcie_v2_ltssm_enable(struct qcom_pcie *pcie)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* enable link training */
|
||||
val = readl(pcie->parf + PCIE20_PARF_LTSSM);
|
||||
val |= BIT(8);
|
||||
writel(val, pcie->parf + PCIE20_PARF_LTSSM);
|
||||
}
|
||||
|
||||
static int qcom_pcie_get_resources_v2(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
|
||||
@ -481,6 +513,17 @@ static int qcom_pcie_get_resources_v2(struct qcom_pcie *pcie)
|
||||
return PTR_ERR_OR_ZERO(res->pipe_clk);
|
||||
}
|
||||
|
||||
static void qcom_pcie_deinit_v2(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
|
||||
|
||||
clk_disable_unprepare(res->pipe_clk);
|
||||
clk_disable_unprepare(res->slave_clk);
|
||||
clk_disable_unprepare(res->master_clk);
|
||||
clk_disable_unprepare(res->cfg_clk);
|
||||
clk_disable_unprepare(res->aux_clk);
|
||||
}
|
||||
|
||||
static int qcom_pcie_init_v2(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
|
||||
@ -562,6 +605,285 @@ static int qcom_pcie_post_init_v2(struct qcom_pcie *pcie)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_pcie_get_resources_v3(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v3 *res = &pcie->res.v3;
|
||||
struct dw_pcie *pci = pcie->pci;
|
||||
struct device *dev = pci->dev;
|
||||
|
||||
res->aux_clk = devm_clk_get(dev, "aux");
|
||||
if (IS_ERR(res->aux_clk))
|
||||
return PTR_ERR(res->aux_clk);
|
||||
|
||||
res->master_clk = devm_clk_get(dev, "master_bus");
|
||||
if (IS_ERR(res->master_clk))
|
||||
return PTR_ERR(res->master_clk);
|
||||
|
||||
res->slave_clk = devm_clk_get(dev, "slave_bus");
|
||||
if (IS_ERR(res->slave_clk))
|
||||
return PTR_ERR(res->slave_clk);
|
||||
|
||||
res->axi_m_reset = devm_reset_control_get(dev, "axi_m");
|
||||
if (IS_ERR(res->axi_m_reset))
|
||||
return PTR_ERR(res->axi_m_reset);
|
||||
|
||||
res->axi_s_reset = devm_reset_control_get(dev, "axi_s");
|
||||
if (IS_ERR(res->axi_s_reset))
|
||||
return PTR_ERR(res->axi_s_reset);
|
||||
|
||||
res->pipe_reset = devm_reset_control_get(dev, "pipe");
|
||||
if (IS_ERR(res->pipe_reset))
|
||||
return PTR_ERR(res->pipe_reset);
|
||||
|
||||
res->axi_m_vmid_reset = devm_reset_control_get(dev, "axi_m_vmid");
|
||||
if (IS_ERR(res->axi_m_vmid_reset))
|
||||
return PTR_ERR(res->axi_m_vmid_reset);
|
||||
|
||||
res->axi_s_xpu_reset = devm_reset_control_get(dev, "axi_s_xpu");
|
||||
if (IS_ERR(res->axi_s_xpu_reset))
|
||||
return PTR_ERR(res->axi_s_xpu_reset);
|
||||
|
||||
res->parf_reset = devm_reset_control_get(dev, "parf");
|
||||
if (IS_ERR(res->parf_reset))
|
||||
return PTR_ERR(res->parf_reset);
|
||||
|
||||
res->phy_reset = devm_reset_control_get(dev, "phy");
|
||||
if (IS_ERR(res->phy_reset))
|
||||
return PTR_ERR(res->phy_reset);
|
||||
|
||||
res->axi_m_sticky_reset = devm_reset_control_get(dev, "axi_m_sticky");
|
||||
if (IS_ERR(res->axi_m_sticky_reset))
|
||||
return PTR_ERR(res->axi_m_sticky_reset);
|
||||
|
||||
res->pipe_sticky_reset = devm_reset_control_get(dev, "pipe_sticky");
|
||||
if (IS_ERR(res->pipe_sticky_reset))
|
||||
return PTR_ERR(res->pipe_sticky_reset);
|
||||
|
||||
res->pwr_reset = devm_reset_control_get(dev, "pwr");
|
||||
if (IS_ERR(res->pwr_reset))
|
||||
return PTR_ERR(res->pwr_reset);
|
||||
|
||||
res->ahb_reset = devm_reset_control_get(dev, "ahb");
|
||||
if (IS_ERR(res->ahb_reset))
|
||||
return PTR_ERR(res->ahb_reset);
|
||||
|
||||
res->phy_ahb_reset = devm_reset_control_get(dev, "phy_ahb");
|
||||
if (IS_ERR(res->phy_ahb_reset))
|
||||
return PTR_ERR(res->phy_ahb_reset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qcom_pcie_deinit_v3(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v3 *res = &pcie->res.v3;
|
||||
|
||||
reset_control_assert(res->axi_m_reset);
|
||||
reset_control_assert(res->axi_s_reset);
|
||||
reset_control_assert(res->pipe_reset);
|
||||
reset_control_assert(res->pipe_sticky_reset);
|
||||
reset_control_assert(res->phy_reset);
|
||||
reset_control_assert(res->phy_ahb_reset);
|
||||
reset_control_assert(res->axi_m_sticky_reset);
|
||||
reset_control_assert(res->pwr_reset);
|
||||
reset_control_assert(res->ahb_reset);
|
||||
clk_disable_unprepare(res->aux_clk);
|
||||
clk_disable_unprepare(res->master_clk);
|
||||
clk_disable_unprepare(res->slave_clk);
|
||||
}
|
||||
|
||||
static int qcom_pcie_init_v3(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v3 *res = &pcie->res.v3;
|
||||
struct dw_pcie *pci = pcie->pci;
|
||||
struct device *dev = pci->dev;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = reset_control_assert(res->axi_m_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot assert axi master reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_assert(res->axi_s_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot assert axi slave reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(10000, 12000);
|
||||
|
||||
ret = reset_control_assert(res->pipe_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot assert pipe reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_assert(res->pipe_sticky_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot assert pipe sticky reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_assert(res->phy_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot assert phy reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_assert(res->phy_ahb_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot assert phy ahb reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(10000, 12000);
|
||||
|
||||
ret = reset_control_assert(res->axi_m_sticky_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot assert axi master sticky reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_assert(res->pwr_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot assert power reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_assert(res->ahb_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot assert ahb reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(10000, 12000);
|
||||
|
||||
ret = reset_control_deassert(res->phy_ahb_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert phy ahb reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(res->phy_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert phy reset\n");
|
||||
goto err_rst_phy;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(res->pipe_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert pipe reset\n");
|
||||
goto err_rst_pipe;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(res->pipe_sticky_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert pipe sticky reset\n");
|
||||
goto err_rst_pipe_sticky;
|
||||
}
|
||||
|
||||
usleep_range(10000, 12000);
|
||||
|
||||
ret = reset_control_deassert(res->axi_m_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert axi master reset\n");
|
||||
goto err_rst_axi_m;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(res->axi_m_sticky_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert axi master sticky reset\n");
|
||||
goto err_rst_axi_m_sticky;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(res->axi_s_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert axi slave reset\n");
|
||||
goto err_rst_axi_s;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(res->pwr_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert power reset\n");
|
||||
goto err_rst_pwr;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(res->ahb_reset);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot deassert ahb reset\n");
|
||||
goto err_rst_ahb;
|
||||
}
|
||||
|
||||
usleep_range(10000, 12000);
|
||||
|
||||
ret = clk_prepare_enable(res->aux_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot prepare/enable iface clock\n");
|
||||
goto err_clk_aux;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(res->master_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot prepare/enable core clock\n");
|
||||
goto err_clk_axi_m;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(res->slave_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot prepare/enable phy clock\n");
|
||||
goto err_clk_axi_s;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
|
||||
val |= BIT(31);
|
||||
writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk_axi_s:
|
||||
clk_disable_unprepare(res->master_clk);
|
||||
err_clk_axi_m:
|
||||
clk_disable_unprepare(res->aux_clk);
|
||||
err_clk_aux:
|
||||
reset_control_assert(res->ahb_reset);
|
||||
err_rst_ahb:
|
||||
reset_control_assert(res->pwr_reset);
|
||||
err_rst_pwr:
|
||||
reset_control_assert(res->axi_s_reset);
|
||||
err_rst_axi_s:
|
||||
reset_control_assert(res->axi_m_sticky_reset);
|
||||
err_rst_axi_m_sticky:
|
||||
reset_control_assert(res->axi_m_reset);
|
||||
err_rst_axi_m:
|
||||
reset_control_assert(res->pipe_sticky_reset);
|
||||
err_rst_pipe_sticky:
|
||||
reset_control_assert(res->pipe_reset);
|
||||
err_rst_pipe:
|
||||
reset_control_assert(res->phy_reset);
|
||||
err_rst_phy:
|
||||
reset_control_assert(res->phy_ahb_reset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_pcie_link_up(struct dw_pcie *pci)
|
||||
{
|
||||
u16 val = readw(pci->dbi_base + PCIE20_CAP + PCI_EXP_LNKSTA);
|
||||
@ -569,17 +891,6 @@ static int qcom_pcie_link_up(struct dw_pcie *pci)
|
||||
return !!(val & PCI_EXP_LNKSTA_DLLLA);
|
||||
}
|
||||
|
||||
static void qcom_pcie_deinit_v2(struct qcom_pcie *pcie)
|
||||
{
|
||||
struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
|
||||
|
||||
clk_disable_unprepare(res->pipe_clk);
|
||||
clk_disable_unprepare(res->slave_clk);
|
||||
clk_disable_unprepare(res->master_clk);
|
||||
clk_disable_unprepare(res->cfg_clk);
|
||||
clk_disable_unprepare(res->aux_clk);
|
||||
}
|
||||
|
||||
static void qcom_pcie_host_init(struct pcie_port *pp)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||||
@ -665,6 +976,13 @@ static const struct dw_pcie_ops dw_pcie_ops = {
|
||||
.link_up = qcom_pcie_link_up,
|
||||
};
|
||||
|
||||
static const struct qcom_pcie_ops ops_v3 = {
|
||||
.get_resources = qcom_pcie_get_resources_v3,
|
||||
.init = qcom_pcie_init_v3,
|
||||
.deinit = qcom_pcie_deinit_v3,
|
||||
.ltssm_enable = qcom_pcie_v2_ltssm_enable,
|
||||
};
|
||||
|
||||
static int qcom_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -755,6 +1073,7 @@ static const struct of_device_id qcom_pcie_match[] = {
|
||||
{ .compatible = "qcom,pcie-apq8064", .data = &ops_v0 },
|
||||
{ .compatible = "qcom,pcie-apq8084", .data = &ops_v1 },
|
||||
{ .compatible = "qcom,pcie-msm8996", .data = &ops_v2 },
|
||||
{ .compatible = "qcom,pcie-ipq4019", .data = &ops_v3 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user