1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015, The Linux Foundation. All rights reserved. 4 */ 5 6 #include "dsi_phy.h" 7 #include "dsi.xml.h" 8 #include "dsi_phy_20nm.xml.h" 9 10 static void dsi_20nm_dphy_set_timing(struct msm_dsi_phy *phy, 11 struct msm_dsi_dphy_timing *timing) 12 { 13 void __iomem *base = phy->base; 14 15 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_0, 16 DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero)); 17 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_1, 18 DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail)); 19 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_2, 20 DSI_20nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare)); 21 if (timing->clk_zero & BIT(8)) 22 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_3, 23 DSI_20nm_PHY_TIMING_CTRL_3_CLK_ZERO_8); 24 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_4, 25 DSI_20nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit)); 26 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_5, 27 DSI_20nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero)); 28 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_6, 29 DSI_20nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare)); 30 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_7, 31 DSI_20nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail)); 32 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_8, 33 DSI_20nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst)); 34 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_9, 35 DSI_20nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) | 36 DSI_20nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure)); 37 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_10, 38 DSI_20nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get)); 39 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_11, 40 DSI_20nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0)); 41 } 42 43 static void dsi_20nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable) 44 { 45 void __iomem *base = phy->reg_base; 46 47 if (!enable) { 48 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0); 49 return; 50 } 51 52 if (phy->regulator_ldo_mode) { 53 dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 0x1d); 54 return; 55 } 56 57 /* non LDO mode */ 58 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_1, 0x03); 59 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_2, 0x03); 60 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_3, 0x00); 61 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_4, 0x20); 62 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0x01); 63 dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 0x00); 64 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_0, 0x03); 65 } 66 67 static int dsi_20nm_phy_enable(struct msm_dsi_phy *phy, 68 struct msm_dsi_phy_clk_request *clk_req) 69 { 70 struct msm_dsi_dphy_timing *timing = &phy->timing; 71 int i; 72 void __iomem *base = phy->base; 73 u32 cfg_4[4] = {0x20, 0x40, 0x20, 0x00}; 74 u32 val; 75 76 DBG(""); 77 78 if (msm_dsi_dphy_timing_calc(timing, clk_req)) { 79 DRM_DEV_ERROR(&phy->pdev->dev, 80 "%s: D-PHY timing calculation failed\n", __func__); 81 return -EINVAL; 82 } 83 84 dsi_20nm_phy_regulator_ctrl(phy, true); 85 86 dsi_phy_write(base + REG_DSI_20nm_PHY_STRENGTH_0, 0xff); 87 88 val = dsi_phy_read(base + REG_DSI_20nm_PHY_GLBL_TEST_CTRL); 89 if (phy->id == DSI_1 && phy->usecase == MSM_DSI_PHY_STANDALONE) 90 val |= DSI_20nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL; 91 else 92 val &= ~DSI_20nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL; 93 dsi_phy_write(base + REG_DSI_20nm_PHY_GLBL_TEST_CTRL, val); 94 95 for (i = 0; i < 4; i++) { 96 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_3(i), 97 (i >> 1) * 0x40); 98 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_TEST_STR_0(i), 0x01); 99 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_TEST_STR_1(i), 0x46); 100 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_0(i), 0x02); 101 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_1(i), 0xa0); 102 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_4(i), cfg_4[i]); 103 } 104 105 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_3, 0x80); 106 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_TEST_STR0, 0x01); 107 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_TEST_STR1, 0x46); 108 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_0, 0x00); 109 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_1, 0xa0); 110 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_2, 0x00); 111 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_4, 0x00); 112 113 dsi_20nm_dphy_set_timing(phy, timing); 114 115 dsi_phy_write(base + REG_DSI_20nm_PHY_CTRL_1, 0x00); 116 117 dsi_phy_write(base + REG_DSI_20nm_PHY_STRENGTH_1, 0x06); 118 119 /* make sure everything is written before enable */ 120 wmb(); 121 dsi_phy_write(base + REG_DSI_20nm_PHY_CTRL_0, 0x7f); 122 123 return 0; 124 } 125 126 static void dsi_20nm_phy_disable(struct msm_dsi_phy *phy) 127 { 128 dsi_phy_write(phy->base + REG_DSI_20nm_PHY_CTRL_0, 0); 129 dsi_20nm_phy_regulator_ctrl(phy, false); 130 } 131 132 static const struct regulator_bulk_data dsi_phy_20nm_regulators[] = { 133 { .supply = "vddio", .init_load_uA = 100000 }, /* 1.8 V */ 134 { .supply = "vcca", .init_load_uA = 10000 }, /* 1.0 V */ 135 }; 136 137 const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs = { 138 .has_phy_regulator = true, 139 .regulator_data = dsi_phy_20nm_regulators, 140 .num_regulators = ARRAY_SIZE(dsi_phy_20nm_regulators), 141 .ops = { 142 .enable = dsi_20nm_phy_enable, 143 .disable = dsi_20nm_phy_disable, 144 }, 145 .io_start = { 0xfd998500, 0xfd9a0500 }, 146 .num_dsi_phy = 2, 147 }; 148 149