From 15ed672eb9e0e672d21ccfaabc89a00d6f940580 Mon Sep 17 00:00:00 2001 From: Tony Truong Date: Mon, 23 May 2016 15:05:58 -0700 Subject: [PATCH] msm: pcie: add support to get PCIe port PHY sequence from DT PCIe PHY varies between each chipset. Thus, the port PHY init sequence on each of these chipsets are also different. Therefore, add the support to read PCIe port PHY init sequence from devicetree. Change-Id: I92969b7b59a64018b80470566567887248ced2bd Signed-off-by: Tony Truong --- Documentation/devicetree/bindings/pci/msm_pcie.txt | 10 +++++ drivers/pci/host/pci-msm.c | 48 ++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/Documentation/devicetree/bindings/pci/msm_pcie.txt b/Documentation/devicetree/bindings/pci/msm_pcie.txt index c8e634617edb..4b5a6b4af789 100644 --- a/Documentation/devicetree/bindings/pci/msm_pcie.txt +++ b/Documentation/devicetree/bindings/pci/msm_pcie.txt @@ -75,6 +75,9 @@ Optional Properties: - qcom,pcie-phy-ver: version of PCIe PHY. - qcom,phy-sequence: The initialization sequence to bring up the PCIe PHY. Should be specified in groups (offset, value, delay). + - qcom,port-phy-sequence: The initialization sequence to bring up the + PCIe port PHY. + Should be specified in groups (offset, value, delay). - qcom,use-19p2mhz-aux-clk: The frequency of PCIe AUX clock is 19.2MHz. - qcom,ep-wakeirq: The endpoint will issue wake signal when it is up, and the root complex has the capability to enumerate the endpoint for this case. @@ -197,6 +200,13 @@ Example: 0x15c 0x06 0x00 0x090 0x01 0x00 0x808 0x03 0x00>; + qcom,port-phy-sequence = <0x804 0x01 0x00 + 0x034 0x14 0x00 + 0x138 0x30 0x00 + 0x048 0x0f 0x00 + 0x15c 0x06 0x00 + 0x090 0x01 0x00 + 0x808 0x03 0x00>; perst-gpio = <&msmgpio 70 0>; wake-gpio = <&msmgpio 69 0>; clkreq-gpio = <&msmgpio 68 0>; diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index c9c092dc4c5c..a5d627a89c31 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -637,7 +637,9 @@ struct msm_pcie_dev_t { u32 num_ep; bool pending_ep_reg; u32 phy_len; + u32 port_phy_len; struct msm_pcie_phy_info_t *phy_sequence; + struct msm_pcie_phy_info_t *port_phy_sequence; u32 ep_shadow[MAX_DEVICE_NUM][PCIE_CONF_SPACE_DW]; u32 rc_shadow[PCIE_CONF_SPACE_DW]; bool shadow_en; @@ -1522,6 +1524,8 @@ static void pcie_phy_init(struct msm_pcie_dev_t *dev) static void pcie_pcs_port_phy_init(struct msm_pcie_dev_t *dev) { + int i; + struct msm_pcie_phy_info_t *phy_seq; u8 common_phy; if (dev->phy_ver >= 0x20) @@ -1534,6 +1538,21 @@ static void pcie_pcs_port_phy_init(struct msm_pcie_dev_t *dev) else common_phy = 0; + if (dev->port_phy_sequence) { + i = dev->port_phy_len; + phy_seq = dev->port_phy_sequence; + while (i--) { + msm_pcie_write_reg(dev->phy, + phy_seq->offset, + phy_seq->val); + if (phy_seq->delay) + usleep_range(phy_seq->delay, + phy_seq->delay + 1); + phy_seq++; + } + return; + } + msm_pcie_write_reg(dev->phy, QSERDES_TX_N_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN(dev->rc_idx, common_phy), 0x45); @@ -1833,6 +1852,8 @@ static void msm_pcie_show_status(struct msm_pcie_dev_t *dev) dev->pending_ep_reg ? "true" : "false"); PCIE_DBG_FS(dev, "phy_len is %d", dev->phy_len); + PCIE_DBG_FS(dev, "port_phy_len is %d", + dev->port_phy_len); PCIE_DBG_FS(dev, "disable_pc is %d", dev->disable_pc); PCIE_DBG_FS(dev, "l0s_supported is %s supported\n", @@ -4028,6 +4049,31 @@ static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev, dev->rc_idx); } + of_get_property(pdev->dev.of_node, "qcom,port-phy-sequence", &size); + if (size) { + dev->port_phy_sequence = (struct msm_pcie_phy_info_t *) + devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + + if (dev->port_phy_sequence) { + dev->port_phy_len = + size / sizeof(*dev->port_phy_sequence); + + of_property_read_u32_array(pdev->dev.of_node, + "qcom,port-phy-sequence", + (unsigned int *)dev->port_phy_sequence, + size / sizeof(dev->port_phy_sequence->offset)); + } else { + PCIE_ERR(dev, + "RC%d: Could not allocate memory for port phy init sequence.\n", + dev->rc_idx); + ret = -ENOMEM; + goto out; + } + } else { + PCIE_DBG(dev, "RC%d: port phy sequence is not present in DT\n", + dev->rc_idx); + } + for (i = 0; i < MSM_PCIE_MAX_CLK; i++) { clk_info = &dev->clk[i]; @@ -5934,7 +5980,9 @@ static int msm_pcie_probe(struct platform_device *pdev) msm_pcie_dev[rc_idx].num_ep = 0; msm_pcie_dev[rc_idx].pending_ep_reg = false; msm_pcie_dev[rc_idx].phy_len = 0; + msm_pcie_dev[rc_idx].port_phy_len = 0; msm_pcie_dev[rc_idx].phy_sequence = NULL; + msm_pcie_dev[rc_idx].port_phy_sequence = NULL; msm_pcie_dev[rc_idx].event_reg = NULL; msm_pcie_dev[rc_idx].linkdown_counter = 0; msm_pcie_dev[rc_idx].link_turned_on_counter = 0; -- 2.11.0