diff options
| author | Tony Truong <truong@codeaurora.org> | 2016-09-12 18:38:00 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-09-19 10:34:16 -0700 |
| commit | 8963c2ab154a921ef334c2f0844c82cf247155e1 (patch) | |
| tree | 93f4cfdfce737e0b5ab8fe4c9f0da232773b0614 /drivers/pci | |
| parent | 4e2a8a0fa1c78712904312e13ef33d02be78d421 (diff) | |
msm: pcie: add support for reset controller framework
The current api which performs the clock reset is moved
to use the reset framework, so support the changes in PCIe
driver for the same. The reset framework requires to get
reset handle and perform assert/deassert of the resets.
Change-Id: I1ca8bb386673f0db020554659f69c71b540e3dcc
Signed-off-by: Amit Nischal <anischal@codeaurora.org>
Signed-off-by: Tony Truong <truong@codeaurora.org>
Diffstat (limited to 'drivers/pci')
| -rw-r--r-- | drivers/pci/host/pci-msm.c | 162 |
1 files changed, 142 insertions, 20 deletions
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index 3f186137e730..abacd7347c44 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -31,6 +31,7 @@ #include <linux/types.h> #include <linux/of_gpio.h> #include <linux/clk/msm-clk.h> +#include <linux/reset.h> #include <linux/msm-bus.h> #include <linux/msm-bus-board.h> #include <linux/debugfs.h> @@ -298,7 +299,7 @@ #define MAX_PROP_SIZE 32 #define MAX_RC_NAME_LEN 15 #define MSM_PCIE_MAX_VREG 4 -#define MSM_PCIE_MAX_CLK 13 +#define MSM_PCIE_MAX_CLK 9 #define MSM_PCIE_MAX_PIPE_CLK 1 #define MAX_RC_NUM 3 #define MAX_DEVICE_NUM 20 @@ -312,6 +313,9 @@ #define PCIE_CLEAR 0xDEADBEEF #define PCIE_LINK_DOWN 0xFFFFFFFF +#define MSM_PCIE_MAX_RESET 4 +#define MSM_PCIE_MAX_PIPE_RESET 1 + #define MSM_PCIE_MSI_PHY 0xa0000000 #define PCIE20_MSI_CTRL_ADDR (0x820) #define PCIE20_MSI_CTRL_UPPER_ADDR (0x824) @@ -496,6 +500,13 @@ struct msm_pcie_vreg_info_t { bool required; }; +/* reset info structure */ +struct msm_pcie_reset_info_t { + struct reset_control *hdl; + char *name; + bool required; +}; + /* clock info structure */ struct msm_pcie_clk_info_t { struct clk *hdl; @@ -552,6 +563,8 @@ struct msm_pcie_dev_t { struct msm_pcie_res_info_t res[MSM_PCIE_MAX_RES]; struct msm_pcie_irq_info_t irq[MSM_PCIE_MAX_IRQ]; struct msm_pcie_irq_info_t msi[MSM_PCIE_MAX_MSI]; + struct msm_pcie_reset_info_t reset[MSM_PCIE_MAX_RESET]; + struct msm_pcie_reset_info_t pipe_reset[MSM_PCIE_MAX_PIPE_RESET]; void __iomem *parf; void __iomem *phy; @@ -707,6 +720,43 @@ static struct msm_pcie_gpio_info_t msm_pcie_gpio_info[MSM_PCIE_MAX_GPIO] = { {"qcom,ep-gpio", 0, 1, 1, 0, 0} }; +/* resets */ +static struct msm_pcie_reset_info_t +msm_pcie_reset_info[MAX_RC_NUM][MSM_PCIE_MAX_RESET] = { + { + {NULL, "pcie_phy_reset", false}, + {NULL, "pcie_phy_com_reset", false}, + {NULL, "pcie_phy_nocsr_com_phy_reset", false}, + {NULL, "pcie_0_phy_reset", false} + }, + { + {NULL, "pcie_phy_reset", false}, + {NULL, "pcie_phy_com_reset", false}, + {NULL, "pcie_phy_nocsr_com_phy_reset", false}, + {NULL, "pcie_1_phy_reset", false} + }, + { + {NULL, "pcie_phy_reset", false}, + {NULL, "pcie_phy_com_reset", false}, + {NULL, "pcie_phy_nocsr_com_phy_reset", false}, + {NULL, "pcie_2_phy_reset", false} + } +}; + +/* pipe reset */ +static struct msm_pcie_reset_info_t +msm_pcie_pipe_reset_info[MAX_RC_NUM][MSM_PCIE_MAX_PIPE_RESET] = { + { + {NULL, "pcie_0_phy_pipe_reset", false} + }, + { + {NULL, "pcie_1_phy_pipe_reset", false} + }, + { + {NULL, "pcie_2_phy_pipe_reset", false} + } +}; + /* clocks */ static struct msm_pcie_clk_info_t msm_pcie_clk_info[MAX_RC_NUM][MSM_PCIE_MAX_CLK] = { @@ -719,11 +769,7 @@ static struct msm_pcie_clk_info_t {NULL, "pcie_0_ldo", 0, false, true}, {NULL, "pcie_0_smmu_clk", 0, false, false}, {NULL, "pcie_phy_cfg_ahb_clk", 0, false, false}, - {NULL, "pcie_phy_aux_clk", 0, false, false}, - {NULL, "pcie_phy_reset", 0, false, false}, - {NULL, "pcie_phy_com_reset", 0, false, false}, - {NULL, "pcie_phy_nocsr_com_phy_reset", 0, false, false}, - {NULL, "pcie_0_phy_reset", 0, false, true} + {NULL, "pcie_phy_aux_clk", 0, false, false} }, { {NULL, "pcie_1_ref_clk_src", 0, false, false}, @@ -734,11 +780,7 @@ static struct msm_pcie_clk_info_t {NULL, "pcie_1_ldo", 0, false, true}, {NULL, "pcie_1_smmu_clk", 0, false, false}, {NULL, "pcie_phy_cfg_ahb_clk", 0, false, false}, - {NULL, "pcie_phy_aux_clk", 0, false, false}, - {NULL, "pcie_phy_reset", 0, false, false}, - {NULL, "pcie_phy_com_reset", 0, false, false}, - {NULL, "pcie_phy_nocsr_com_phy_reset", 0, false, false}, - {NULL, "pcie_1_phy_reset", 0, false, true} + {NULL, "pcie_phy_aux_clk", 0, false, false} }, { {NULL, "pcie_2_ref_clk_src", 0, false, false}, @@ -749,11 +791,7 @@ static struct msm_pcie_clk_info_t {NULL, "pcie_2_ldo", 0, false, true}, {NULL, "pcie_2_smmu_clk", 0, false, false}, {NULL, "pcie_phy_cfg_ahb_clk", 0, false, false}, - {NULL, "pcie_phy_aux_clk", 0, false, false}, - {NULL, "pcie_phy_reset", 0, false, false}, - {NULL, "pcie_phy_com_reset", 0, false, false}, - {NULL, "pcie_phy_nocsr_com_phy_reset", 0, false, false}, - {NULL, "pcie_2_phy_reset", 0, false, true} + {NULL, "pcie_phy_aux_clk", 0, false, false} } }; @@ -3431,6 +3469,7 @@ static int msm_pcie_clk_init(struct msm_pcie_dev_t *dev) { int i, rc = 0; struct msm_pcie_clk_info_t *info; + struct msm_pcie_reset_info_t *reset_info; PCIE_DBG(dev, "RC%d: entry\n", dev->rc_idx); @@ -3474,9 +3513,6 @@ static int msm_pcie_clk_init(struct msm_pcie_dev_t *dev) if (!info->hdl) continue; - if (i >= MSM_PCIE_MAX_CLK - (dev->common_phy ? 4 : 1)) - clk_reset(info->hdl, CLK_RESET_DEASSERT); - if (info->config_mem) msm_pcie_config_clock_mem(dev, info); @@ -3519,6 +3555,21 @@ static int msm_pcie_clk_init(struct msm_pcie_dev_t *dev) regulator_disable(dev->gdsc); } + for (i = 0; i < MSM_PCIE_MAX_RESET; i++) { + reset_info = &dev->reset[i]; + if (reset_info->hdl) { + rc = reset_control_deassert(reset_info->hdl); + if (rc) + PCIE_ERR(dev, + "PCIe: RC%d failed to deassert reset for %s.\n", + dev->rc_idx, reset_info->name); + else + PCIE_DBG2(dev, + "PCIe: RC%d successfully deasserted reset for %s.\n", + dev->rc_idx, reset_info->name); + } + } + PCIE_DBG(dev, "RC%d: exit\n", dev->rc_idx); return rc; @@ -3562,6 +3613,7 @@ static int msm_pcie_pipe_clk_init(struct msm_pcie_dev_t *dev) { int i, rc = 0; struct msm_pcie_clk_info_t *info; + struct msm_pcie_reset_info_t *pipe_reset_info; PCIE_DBG(dev, "RC%d: entry\n", dev->rc_idx); @@ -3571,7 +3623,6 @@ static int msm_pcie_pipe_clk_init(struct msm_pcie_dev_t *dev) if (!info->hdl) continue; - clk_reset(info->hdl, CLK_RESET_DEASSERT); if (info->config_mem) msm_pcie_config_clock_mem(dev, info); @@ -3608,6 +3659,22 @@ static int msm_pcie_pipe_clk_init(struct msm_pcie_dev_t *dev) clk_disable_unprepare(dev->pipeclk[i].hdl); } + for (i = 0; i < MSM_PCIE_MAX_PIPE_RESET; i++) { + pipe_reset_info = &dev->pipe_reset[i]; + if (pipe_reset_info->hdl) { + rc = reset_control_deassert( + pipe_reset_info->hdl); + if (rc) + PCIE_ERR(dev, + "PCIe: RC%d failed to deassert pipe reset for %s.\n", + dev->rc_idx, pipe_reset_info->name); + else + PCIE_DBG2(dev, + "PCIe: RC%d successfully deasserted pipe reset for %s.\n", + dev->rc_idx, pipe_reset_info->name); + } + } + PCIE_DBG(dev, "RC%d: exit\n", dev->rc_idx); return rc; @@ -3945,6 +4012,8 @@ static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev, struct msm_pcie_res_info_t *res_info; struct msm_pcie_irq_info_t *irq_info; struct msm_pcie_irq_info_t *msi_info; + struct msm_pcie_reset_info_t *reset_info; + struct msm_pcie_reset_info_t *pipe_reset_info; char prop_name[MAX_PROP_SIZE]; const __be32 *prop; u32 *clkfreq = NULL; @@ -4161,6 +4230,54 @@ static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev, } } + for (i = 0; i < MSM_PCIE_MAX_RESET; i++) { + reset_info = &dev->reset[i]; + + reset_info->hdl = devm_reset_control_get(&pdev->dev, + reset_info->name); + + if (IS_ERR(reset_info->hdl)) { + if (reset_info->required) { + PCIE_DBG(dev, + "Reset %s isn't available:%ld\n", + reset_info->name, + PTR_ERR(reset_info->hdl)); + + ret = PTR_ERR(reset_info->hdl); + reset_info->hdl = NULL; + goto out; + } else { + PCIE_DBG(dev, "Ignoring Reset %s\n", + reset_info->name); + reset_info->hdl = NULL; + } + } + } + + for (i = 0; i < MSM_PCIE_MAX_PIPE_RESET; i++) { + pipe_reset_info = &dev->pipe_reset[i]; + + pipe_reset_info->hdl = devm_reset_control_get(&pdev->dev, + pipe_reset_info->name); + + if (IS_ERR(pipe_reset_info->hdl)) { + if (pipe_reset_info->required) { + PCIE_DBG(dev, + "Pipe Reset %s isn't available:%ld\n", + pipe_reset_info->name, + PTR_ERR(pipe_reset_info->hdl)); + + ret = PTR_ERR(pipe_reset_info->hdl); + pipe_reset_info->hdl = NULL; + goto out; + } else { + PCIE_DBG(dev, "Ignoring Pipe Reset %s\n", + pipe_reset_info->name); + pipe_reset_info->hdl = NULL; + } + } + } + dev->bus_scale_table = msm_bus_cl_get_pdata(pdev); if (!dev->bus_scale_table) { PCIE_DBG(dev, "PCIe: No bus scale table for RC%d (%s)\n", @@ -6052,6 +6169,11 @@ static int msm_pcie_probe(struct platform_device *pdev) sizeof(msm_pcie_irq_info)); memcpy(msm_pcie_dev[rc_idx].msi, msm_pcie_msi_info, sizeof(msm_pcie_msi_info)); + memcpy(msm_pcie_dev[rc_idx].reset, msm_pcie_reset_info[rc_idx], + sizeof(msm_pcie_reset_info[rc_idx])); + memcpy(msm_pcie_dev[rc_idx].pipe_reset, + msm_pcie_pipe_reset_info[rc_idx], + sizeof(msm_pcie_pipe_reset_info[rc_idx])); msm_pcie_dev[rc_idx].shadow_en = true; for (i = 0; i < PCIE_CONF_SPACE_DW; i++) msm_pcie_dev[rc_idx].rc_shadow[i] = PCIE_CLEAR; |
