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 writel(DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero), 16 base + REG_DSI_20nm_PHY_TIMING_CTRL_0); 17 writel(DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail), 18 base + REG_DSI_20nm_PHY_TIMING_CTRL_1); 19 writel(DSI_20nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare), 20 base + REG_DSI_20nm_PHY_TIMING_CTRL_2); 21 if (timing->clk_zero & BIT(8)) 22 writel(DSI_20nm_PHY_TIMING_CTRL_3_CLK_ZERO_8, 23 base + REG_DSI_20nm_PHY_TIMING_CTRL_3); 24 writel(DSI_20nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit), 25 base + REG_DSI_20nm_PHY_TIMING_CTRL_4); 26 writel(DSI_20nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero), 27 base + REG_DSI_20nm_PHY_TIMING_CTRL_5); 28 writel(DSI_20nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare), 29 base + REG_DSI_20nm_PHY_TIMING_CTRL_6); 30 writel(DSI_20nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail), 31 base + REG_DSI_20nm_PHY_TIMING_CTRL_7); 32 writel(DSI_20nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst), 33 base + REG_DSI_20nm_PHY_TIMING_CTRL_8); 34 writel(DSI_20nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) | 35 DSI_20nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure), 36 base + REG_DSI_20nm_PHY_TIMING_CTRL_9); 37 writel(DSI_20nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get), 38 base + REG_DSI_20nm_PHY_TIMING_CTRL_10); 39 writel(DSI_20nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0), 40 base + REG_DSI_20nm_PHY_TIMING_CTRL_11); 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 writel(0, base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG); 49 return; 50 } 51 52 if (phy->regulator_ldo_mode) { 53 writel(0x1d, phy->base + REG_DSI_20nm_PHY_LDO_CNTRL); 54 return; 55 } 56 57 /* non LDO mode */ 58 writel(0x03, base + REG_DSI_20nm_PHY_REGULATOR_CTRL_1); 59 writel(0x03, base + REG_DSI_20nm_PHY_REGULATOR_CTRL_2); 60 writel(0x00, base + REG_DSI_20nm_PHY_REGULATOR_CTRL_3); 61 writel(0x20, base + REG_DSI_20nm_PHY_REGULATOR_CTRL_4); 62 writel(0x01, base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG); 63 writel(0x00, phy->base + REG_DSI_20nm_PHY_LDO_CNTRL); 64 writel(0x03, base + REG_DSI_20nm_PHY_REGULATOR_CTRL_0); 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 writel(0xff, base + REG_DSI_20nm_PHY_STRENGTH_0); 87 88 val = readl(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 writel(val, base + REG_DSI_20nm_PHY_GLBL_TEST_CTRL); 94 95 for (i = 0; i < 4; i++) { 96 writel((i >> 1) * 0x40, base + REG_DSI_20nm_PHY_LN_CFG_3(i)); 97 writel(0x01, base + REG_DSI_20nm_PHY_LN_TEST_STR_0(i)); 98 writel(0x46, base + REG_DSI_20nm_PHY_LN_TEST_STR_1(i)); 99 writel(0x02, base + REG_DSI_20nm_PHY_LN_CFG_0(i)); 100 writel(0xa0, base + REG_DSI_20nm_PHY_LN_CFG_1(i)); 101 writel(cfg_4[i], base + REG_DSI_20nm_PHY_LN_CFG_4(i)); 102 } 103 104 writel(0x80, base + REG_DSI_20nm_PHY_LNCK_CFG_3); 105 writel(0x01, base + REG_DSI_20nm_PHY_LNCK_TEST_STR0); 106 writel(0x46, base + REG_DSI_20nm_PHY_LNCK_TEST_STR1); 107 writel(0x00, base + REG_DSI_20nm_PHY_LNCK_CFG_0); 108 writel(0xa0, base + REG_DSI_20nm_PHY_LNCK_CFG_1); 109 writel(0x00, base + REG_DSI_20nm_PHY_LNCK_CFG_2); 110 writel(0x00, base + REG_DSI_20nm_PHY_LNCK_CFG_4); 111 112 dsi_20nm_dphy_set_timing(phy, timing); 113 114 writel(0x00, base + REG_DSI_20nm_PHY_CTRL_1); 115 116 writel(0x06, base + REG_DSI_20nm_PHY_STRENGTH_1); 117 118 /* make sure everything is written before enable */ 119 wmb(); 120 writel(0x7f, base + REG_DSI_20nm_PHY_CTRL_0); 121 122 return 0; 123 } 124 125 static void dsi_20nm_phy_disable(struct msm_dsi_phy *phy) 126 { 127 writel(0, phy->base + REG_DSI_20nm_PHY_CTRL_0); 128 dsi_20nm_phy_regulator_ctrl(phy, false); 129 } 130 131 static const struct regulator_bulk_data dsi_phy_20nm_regulators[] = { 132 { .supply = "vddio", .init_load_uA = 100000 }, /* 1.8 V */ 133 { .supply = "vcca", .init_load_uA = 10000 }, /* 1.0 V */ 134 }; 135 136 const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs = { 137 .has_phy_regulator = true, 138 .regulator_data = dsi_phy_20nm_regulators, 139 .num_regulators = ARRAY_SIZE(dsi_phy_20nm_regulators), 140 .ops = { 141 .enable = dsi_20nm_phy_enable, 142 .disable = dsi_20nm_phy_disable, 143 }, 144 .io_start = { 0xfd998500, 0xfd9a0500 }, 145 .num_dsi_phy = 2, 146 }; 147 148