summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTony Truong <truong@codeaurora.org>2016-04-12 11:58:22 -0700
committerJeevan Shriram <jshriram@codeaurora.org>2016-05-16 20:10:17 -0700
commit3993dd4312f4385caec9a6c2b408da6c5b2412ad (patch)
tree355cf4172d8fa411a77a64039416c96d8789960c /drivers
parenta5b1da948d135ba6023274640d5a1c7dfb525e03 (diff)
msm: pcie: add support to get PCIe PHY init sequence from DT
PCIe PHY varies between each chipset. Thus, the PHY init sequence on each of these chipsets are also different. Therefore, add the support to read PCIe PHY init sequence from devicetree. Change-Id: I21c2ce2b7d3bf1541a5d3580db4bc40497701095 Signed-off-by: Tony Truong <truong@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/host/pci-msm.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 8dd18606e27f..21cc701aa5e3 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -502,6 +502,13 @@ struct msm_pcie_irq_info_t {
uint32_t num;
};
+/* phy info structure */
+struct msm_pcie_phy_info_t {
+ u32 offset;
+ u32 val;
+ u32 delay;
+};
+
/* PCIe device info structure */
struct msm_pcie_device_info {
u32 bdf;
@@ -613,6 +620,8 @@ struct msm_pcie_dev_t {
u32 num_active_ep;
u32 num_ep;
bool pending_ep_reg;
+ u32 phy_len;
+ struct msm_pcie_phy_info_t *phy_sequence;
u32 ep_shadow[MAX_DEVICE_NUM][PCIE_CONF_SPACE_DW];
u32 rc_shadow[PCIE_CONF_SPACE_DW];
bool shadow_en;
@@ -1409,10 +1418,28 @@ static bool pcie_phy_is_ready(struct msm_pcie_dev_t *dev)
#else
static void pcie_phy_init(struct msm_pcie_dev_t *dev)
{
+ int i;
+ struct msm_pcie_phy_info_t *phy_seq;
+
PCIE_DBG(dev,
"RC%d: Initializing 14nm QMP phy - 19.2MHz with Common Mode Clock (SSC ON)\n",
dev->rc_idx);
+ if (dev->phy_sequence) {
+ i = dev->phy_len;
+ phy_seq = dev->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;
+ }
+
if (dev->common_phy)
msm_pcie_write_reg(dev->phy, PCIE_COM_POWER_DOWN_CONTROL, 0x01);
@@ -1770,6 +1797,8 @@ static void msm_pcie_show_status(struct msm_pcie_dev_t *dev)
dev->num_active_ep);
PCIE_DBG_FS(dev, "pending_ep_reg: %s\n",
dev->pending_ep_reg ? "true" : "false");
+ PCIE_DBG_FS(dev, "phy_len is %d",
+ dev->phy_len);
PCIE_DBG_FS(dev, "disable_pc is %d",
dev->disable_pc);
PCIE_DBG_FS(dev, "l0s_supported is %s supported\n",
@@ -3815,7 +3844,7 @@ void msm_pcie_config_msi_controller(struct msm_pcie_dev_t *dev)
static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev,
struct platform_device *pdev)
{
- int i, len, cnt, ret = 0;
+ int i, len, cnt, ret = 0, size = 0;
struct msm_pcie_vreg_info_t *vreg_info;
struct msm_pcie_gpio_info_t *gpio_info;
struct msm_pcie_clk_info_t *clk_info;
@@ -3938,6 +3967,31 @@ static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev,
ret = 0;
}
+ of_get_property(pdev->dev.of_node, "qcom,phy-sequence", &size);
+ if (size) {
+ dev->phy_sequence = (struct msm_pcie_phy_info_t *)
+ devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+
+ if (dev->phy_sequence) {
+ dev->phy_len =
+ size / sizeof(*dev->phy_sequence);
+
+ of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,phy-sequence",
+ (unsigned int *)dev->phy_sequence,
+ size / sizeof(dev->phy_sequence->offset));
+ } else {
+ PCIE_ERR(dev,
+ "RC%d: Could not allocate memory for phy init sequence.\n",
+ dev->rc_idx);
+ ret = -ENOMEM;
+ goto out;
+ }
+ } else {
+ PCIE_DBG(dev, "RC%d: 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];
@@ -5829,6 +5883,8 @@ static int msm_pcie_probe(struct platform_device *pdev)
msm_pcie_dev[rc_idx].num_active_ep = 0;
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].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;