1 /* 2 * Copyright (c) 2015, The Linux Foundation. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 and 6 * only version 2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14 #include "dsi_phy.h" 15 #include "dsi.xml.h" 16 17 static void dsi_20nm_dphy_set_timing(struct msm_dsi_phy *phy, 18 struct msm_dsi_dphy_timing *timing) 19 { 20 void __iomem *base = phy->base; 21 22 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_0, 23 DSI_20nm_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero)); 24 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_1, 25 DSI_20nm_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail)); 26 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_2, 27 DSI_20nm_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare)); 28 if (timing->clk_zero & BIT(8)) 29 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_3, 30 DSI_20nm_PHY_TIMING_CTRL_3_CLK_ZERO_8); 31 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_4, 32 DSI_20nm_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit)); 33 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_5, 34 DSI_20nm_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero)); 35 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_6, 36 DSI_20nm_PHY_TIMING_CTRL_6_HS_PREPARE(timing->hs_prepare)); 37 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_7, 38 DSI_20nm_PHY_TIMING_CTRL_7_HS_TRAIL(timing->hs_trail)); 39 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_8, 40 DSI_20nm_PHY_TIMING_CTRL_8_HS_RQST(timing->hs_rqst)); 41 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_9, 42 DSI_20nm_PHY_TIMING_CTRL_9_TA_GO(timing->ta_go) | 43 DSI_20nm_PHY_TIMING_CTRL_9_TA_SURE(timing->ta_sure)); 44 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_10, 45 DSI_20nm_PHY_TIMING_CTRL_10_TA_GET(timing->ta_get)); 46 dsi_phy_write(base + REG_DSI_20nm_PHY_TIMING_CTRL_11, 47 DSI_20nm_PHY_TIMING_CTRL_11_TRIG3_CMD(0)); 48 } 49 50 static void dsi_20nm_phy_regulator_ctrl(struct msm_dsi_phy *phy, bool enable) 51 { 52 void __iomem *base = phy->reg_base; 53 54 if (!enable) { 55 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0); 56 return; 57 } 58 59 if (phy->regulator_ldo_mode) { 60 dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 0x1d); 61 return; 62 } 63 64 /* non LDO mode */ 65 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_1, 0x03); 66 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_2, 0x03); 67 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_3, 0x00); 68 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_4, 0x20); 69 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CAL_PWR_CFG, 0x01); 70 dsi_phy_write(phy->base + REG_DSI_20nm_PHY_LDO_CNTRL, 0x00); 71 dsi_phy_write(base + REG_DSI_20nm_PHY_REGULATOR_CTRL_0, 0x03); 72 } 73 74 static int dsi_20nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, 75 struct msm_dsi_phy_clk_request *clk_req) 76 { 77 struct msm_dsi_dphy_timing *timing = &phy->timing; 78 int i; 79 void __iomem *base = phy->base; 80 u32 cfg_4[4] = {0x20, 0x40, 0x20, 0x00}; 81 82 DBG(""); 83 84 if (msm_dsi_dphy_timing_calc(timing, clk_req)) { 85 dev_err(&phy->pdev->dev, 86 "%s: D-PHY timing calculation failed\n", __func__); 87 return -EINVAL; 88 } 89 90 dsi_20nm_phy_regulator_ctrl(phy, true); 91 92 dsi_phy_write(base + REG_DSI_20nm_PHY_STRENGTH_0, 0xff); 93 94 msm_dsi_phy_set_src_pll(phy, src_pll_id, 95 REG_DSI_20nm_PHY_GLBL_TEST_CTRL, 96 DSI_20nm_PHY_GLBL_TEST_CTRL_BITCLK_HS_SEL); 97 98 for (i = 0; i < 4; i++) { 99 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_3(i), 100 (i >> 1) * 0x40); 101 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_TEST_STR_0(i), 0x01); 102 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_TEST_STR_1(i), 0x46); 103 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_0(i), 0x02); 104 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_1(i), 0xa0); 105 dsi_phy_write(base + REG_DSI_20nm_PHY_LN_CFG_4(i), cfg_4[i]); 106 } 107 108 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_3, 0x80); 109 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_TEST_STR0, 0x01); 110 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_TEST_STR1, 0x46); 111 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_0, 0x00); 112 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_1, 0xa0); 113 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_2, 0x00); 114 dsi_phy_write(base + REG_DSI_20nm_PHY_LNCK_CFG_4, 0x00); 115 116 dsi_20nm_dphy_set_timing(phy, timing); 117 118 dsi_phy_write(base + REG_DSI_20nm_PHY_CTRL_1, 0x00); 119 120 dsi_phy_write(base + REG_DSI_20nm_PHY_STRENGTH_1, 0x06); 121 122 /* make sure everything is written before enable */ 123 wmb(); 124 dsi_phy_write(base + REG_DSI_20nm_PHY_CTRL_0, 0x7f); 125 126 return 0; 127 } 128 129 static void dsi_20nm_phy_disable(struct msm_dsi_phy *phy) 130 { 131 dsi_phy_write(phy->base + REG_DSI_20nm_PHY_CTRL_0, 0); 132 dsi_20nm_phy_regulator_ctrl(phy, false); 133 } 134 135 const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs = { 136 .type = MSM_DSI_PHY_20NM, 137 .src_pll_truthtable = { {false, true}, {false, true} }, 138 .reg_cfg = { 139 .num = 2, 140 .regs = { 141 {"vddio", 100000, 100}, /* 1.8 V */ 142 {"vcca", 10000, 100}, /* 1.0 V */ 143 }, 144 }, 145 .ops = { 146 .enable = dsi_20nm_phy_enable, 147 .disable = dsi_20nm_phy_disable, 148 .init = msm_dsi_phy_init_common, 149 }, 150 .io_start = { 0xfd998300, 0xfd9a0300 }, 151 .num_dsi_phy = 2, 152 }; 153 154