diff --git a/drivers/pci/controller/pci-msm.c b/drivers/pci/controller/pci-msm.c index bc7e19f0cc79..f7d8fa725a9b 100644 --- a/drivers/pci/controller/pci-msm.c +++ b/drivers/pci/controller/pci-msm.c @@ -341,6 +341,8 @@ pr_err("%s: " fmt, __func__, arg); \ } while (0) +#define CHECK_NTN3_VERSION_MASK (0x000000FF) +#define NTN3_CHIP_VERSION_1 (0x00000000) enum msm_pcie_res { MSM_PCIE_RES_PARF, @@ -703,6 +705,7 @@ struct pcie_i2c_reg_update { u32 val; }; + /* i2c control interface for a i2c client device */ struct pcie_i2c_ctrl { struct i2c_client *client; @@ -715,7 +718,10 @@ struct pcie_i2c_ctrl { u32 dump_reg_count; struct pcie_i2c_reg_update *reg_update; u32 reg_update_count; - + u32 version_reg; + bool force_i2c_setting; + struct pcie_i2c_reg_update *switch_reg_update; + u32 switch_reg_update_count; /* client specific callbacks */ int (*client_i2c_read)(struct i2c_client *client, u32 reg_addr, u32 *val); @@ -4519,22 +4525,46 @@ static void ntn3_dump_regs(struct pcie_i2c_ctrl *i2c_ctrl) static void ntn3_de_emphasis_wa(struct pcie_i2c_ctrl *i2c_ctrl) { - int i, val; + int i, val, ret, rd_val; struct msm_pcie_dev_t *pcie_dev = container_of(i2c_ctrl, struct msm_pcie_dev_t, i2c_ctrl); + ret = i2c_ctrl->client_i2c_read(i2c_ctrl->client, + i2c_ctrl->version_reg, &rd_val); + if (ret) { + PCIE_DBG(pcie_dev, "PCIe: RC%d: gpio version reg read failed : %d\n", + pcie_dev->rc_idx, ret); + } + i2c_ctrl->force_i2c_setting = of_property_read_bool(i2c_ctrl->client->dev.of_node, + "force-i2c-setting"); + rd_val &= CHECK_NTN3_VERSION_MASK; + PCIE_DBG(pcie_dev, "PCIe: RC%d: NTN3 Version reg:0x%x and force-i2c-setting is %s enabled", + pcie_dev->rc_idx, rd_val, i2c_ctrl->force_i2c_setting ? "" : "not"); + if (rd_val == NTN3_CHIP_VERSION_1 || i2c_ctrl->force_i2c_setting) { + PCIE_DBG(pcie_dev, "PCIe: RC%d: NTN3 reg update\n", pcie_dev->rc_idx); - PCIE_DBG(pcie_dev, "PCIe: RC%d: NTN3 reg update\n", pcie_dev->rc_idx); - - for (i = 0; i < i2c_ctrl->reg_update_count; i++) { - i2c_ctrl->client_i2c_write(i2c_ctrl->client, i2c_ctrl->reg_update[i].offset, - i2c_ctrl->reg_update[i].val); - /*Read to make sure writes are completed*/ - i2c_ctrl->client_i2c_read(i2c_ctrl->client, i2c_ctrl->reg_update[i].offset, - &val); - PCIE_DBG(pcie_dev, "PCIe: RC%d: NTN3 reg off:0x%x wr_val:0x%x rd_val:0x%x\n", - pcie_dev->rc_idx, i2c_ctrl->reg_update[i].offset, - i2c_ctrl->reg_update[i].val, val); + for (i = 0; i < i2c_ctrl->reg_update_count; i++) { + i2c_ctrl->client_i2c_write(i2c_ctrl->client, i2c_ctrl->reg_update[i].offset, + i2c_ctrl->reg_update[i].val); + /*Read to make sure writes are completed*/ + i2c_ctrl->client_i2c_read(i2c_ctrl->client, i2c_ctrl->reg_update[i].offset, + &val); + PCIE_DBG(pcie_dev, + "PCIe: RC%d: NTN3 reg off:0x%x wr_val:0x%x rd_val:0x%x\n", + pcie_dev->rc_idx, i2c_ctrl->reg_update[i].offset, + i2c_ctrl->reg_update[i].val, val); + } + } + for (i = 0; i < i2c_ctrl->switch_reg_update_count; i++) { + i2c_ctrl->client_i2c_write(i2c_ctrl->client, i2c_ctrl->switch_reg_update[i].offset, + i2c_ctrl->switch_reg_update[i].val); + /*Read to make sure writes are completed*/ + i2c_ctrl->client_i2c_read(i2c_ctrl->client, i2c_ctrl->switch_reg_update[i].offset, + &val); + PCIE_DBG(pcie_dev, + "PCIe: RC%d: NTN3 reg off:0x%x wr_val:0x%x rd_val:0x%x\n", + pcie_dev->rc_idx, i2c_ctrl->switch_reg_update[i].offset, + i2c_ctrl->switch_reg_update[i].val, val); } } @@ -5965,7 +5995,10 @@ static int msm_pcie_i2c_ctrl_init(struct msm_pcie_dev_t *pcie_dev) of_property_read_u32(i2c_client_node, "ep-reset-gpio-mask", &i2c_ctrl->ep_reset_gpio_mask); - + of_property_read_u32(i2c_client_node, "version-reg", + &i2c_ctrl->version_reg); + i2c_ctrl->force_i2c_setting = of_property_read_bool(i2c_client_node, + "force-i2c-setting"); of_get_property(i2c_client_node, "dump-regs", &size); if (size) { @@ -5998,8 +6031,23 @@ static int msm_pcie_i2c_ctrl_init(struct msm_pcie_dev_t *pcie_dev) if (ret) i2c_ctrl->reg_update_count = 0; } + of_get_property(i2c_client_node, "switch_reg_update", &size); - return 0; + if (size) { + i2c_ctrl->switch_reg_update = devm_kzalloc(dev, size, GFP_KERNEL); + if (!i2c_ctrl->switch_reg_update) + return -ENOMEM; + + i2c_ctrl->switch_reg_update_count = size / sizeof(*i2c_ctrl->switch_reg_update); + + ret = of_property_read_u32_array(i2c_client_node, + "switch_reg_update", + (unsigned int *)i2c_ctrl->switch_reg_update, + size/sizeof(i2c_ctrl->switch_reg_update->offset)); + if (ret) + i2c_ctrl->switch_reg_update_count = 0; + } + return 0; } static int msm_pcie_probe(struct platform_device *pdev)