1 /*
2  * Copyright (c) 2016, 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 #define PHY_14NM_CKLN_IDX	4
18 
19 static void dsi_14nm_dphy_set_timing(struct msm_dsi_phy *phy,
20 				     struct msm_dsi_dphy_timing *timing,
21 				     int lane_idx)
22 {
23 	void __iomem *base = phy->lane_base;
24 	bool clk_ln = (lane_idx == PHY_14NM_CKLN_IDX);
25 	u32 zero = clk_ln ? timing->clk_zero : timing->hs_zero;
26 	u32 prepare = clk_ln ? timing->clk_prepare : timing->hs_prepare;
27 	u32 trail = clk_ln ? timing->clk_trail : timing->hs_trail;
28 	u32 rqst = clk_ln ? timing->hs_rqst_ckln : timing->hs_rqst;
29 	u32 prep_dly = clk_ln ? timing->hs_prep_dly_ckln : timing->hs_prep_dly;
30 	u32 halfbyte_en = clk_ln ? timing->hs_halfbyte_en_ckln :
31 				   timing->hs_halfbyte_en;
32 
33 	dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_4(lane_idx),
34 		      DSI_14nm_PHY_LN_TIMING_CTRL_4_HS_EXIT(timing->hs_exit));
35 	dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_5(lane_idx),
36 		      DSI_14nm_PHY_LN_TIMING_CTRL_5_HS_ZERO(zero));
37 	dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_6(lane_idx),
38 		      DSI_14nm_PHY_LN_TIMING_CTRL_6_HS_PREPARE(prepare));
39 	dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_7(lane_idx),
40 		      DSI_14nm_PHY_LN_TIMING_CTRL_7_HS_TRAIL(trail));
41 	dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_8(lane_idx),
42 		      DSI_14nm_PHY_LN_TIMING_CTRL_8_HS_RQST(rqst));
43 	dsi_phy_write(base + REG_DSI_14nm_PHY_LN_CFG0(lane_idx),
44 		      DSI_14nm_PHY_LN_CFG0_PREPARE_DLY(prep_dly));
45 	dsi_phy_write(base + REG_DSI_14nm_PHY_LN_CFG1(lane_idx),
46 		      halfbyte_en ? DSI_14nm_PHY_LN_CFG1_HALFBYTECLK_EN : 0);
47 	dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_9(lane_idx),
48 		      DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_GO(timing->ta_go) |
49 		      DSI_14nm_PHY_LN_TIMING_CTRL_9_TA_SURE(timing->ta_sure));
50 	dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_10(lane_idx),
51 		      DSI_14nm_PHY_LN_TIMING_CTRL_10_TA_GET(timing->ta_get));
52 	dsi_phy_write(base + REG_DSI_14nm_PHY_LN_TIMING_CTRL_11(lane_idx),
53 		      DSI_14nm_PHY_LN_TIMING_CTRL_11_TRIG3_CMD(0xa0));
54 }
55 
56 static int dsi_14nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
57 			       struct msm_dsi_phy_clk_request *clk_req)
58 {
59 	struct msm_dsi_dphy_timing *timing = &phy->timing;
60 	u32 data;
61 	int i;
62 	int ret;
63 	void __iomem *base = phy->base;
64 	void __iomem *lane_base = phy->lane_base;
65 
66 	if (msm_dsi_dphy_timing_calc_v2(timing, clk_req)) {
67 		dev_err(&phy->pdev->dev,
68 			"%s: D-PHY timing calculation failed\n", __func__);
69 		return -EINVAL;
70 	}
71 
72 	data = 0x1c;
73 	if (phy->usecase != MSM_DSI_PHY_STANDALONE)
74 		data |= DSI_14nm_PHY_CMN_LDO_CNTRL_VREG_CTRL(32);
75 	dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_LDO_CNTRL, data);
76 
77 	dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL, 0x1);
78 
79 	/* 4 data lanes + 1 clk lane configuration */
80 	for (i = 0; i < 5; i++) {
81 		dsi_phy_write(lane_base + REG_DSI_14nm_PHY_LN_VREG_CNTRL(i),
82 			      0x1d);
83 
84 		dsi_phy_write(lane_base +
85 			      REG_DSI_14nm_PHY_LN_STRENGTH_CTRL_0(i), 0xff);
86 		dsi_phy_write(lane_base +
87 			      REG_DSI_14nm_PHY_LN_STRENGTH_CTRL_1(i),
88 			      (i == PHY_14NM_CKLN_IDX) ? 0x00 : 0x06);
89 
90 		dsi_phy_write(lane_base + REG_DSI_14nm_PHY_LN_CFG3(i),
91 			      (i == PHY_14NM_CKLN_IDX) ? 0x8f : 0x0f);
92 		dsi_phy_write(lane_base + REG_DSI_14nm_PHY_LN_CFG2(i), 0x10);
93 		dsi_phy_write(lane_base + REG_DSI_14nm_PHY_LN_TEST_DATAPATH(i),
94 			      0);
95 		dsi_phy_write(lane_base + REG_DSI_14nm_PHY_LN_TEST_STR(i),
96 			      0x88);
97 
98 		dsi_14nm_dphy_set_timing(phy, timing, i);
99 	}
100 
101 	/* Make sure PLL is not start */
102 	dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_PLL_CNTRL, 0x00);
103 
104 	wmb(); /* make sure everything is written before reset and enable */
105 
106 	/* reset digital block */
107 	dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0x80);
108 	wmb(); /* ensure reset is asserted */
109 	udelay(100);
110 	dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_CTRL_1, 0x00);
111 
112 	msm_dsi_phy_set_src_pll(phy, src_pll_id,
113 				REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL,
114 				DSI_14nm_PHY_CMN_GLBL_TEST_CTRL_BITCLK_HS_SEL);
115 
116 	ret = msm_dsi_pll_set_usecase(phy->pll, phy->usecase);
117 	if (ret) {
118 		dev_err(&phy->pdev->dev, "%s: set pll usecase failed, %d\n",
119 			__func__, ret);
120 		return ret;
121 	}
122 
123 	/* Remove power down from PLL and all lanes */
124 	dsi_phy_write(base + REG_DSI_14nm_PHY_CMN_CTRL_0, 0xff);
125 
126 	return 0;
127 }
128 
129 static void dsi_14nm_phy_disable(struct msm_dsi_phy *phy)
130 {
131 	dsi_phy_write(phy->base + REG_DSI_14nm_PHY_CMN_GLBL_TEST_CTRL, 0);
132 	dsi_phy_write(phy->base + REG_DSI_14nm_PHY_CMN_CTRL_0, 0);
133 
134 	/* ensure that the phy is completely disabled */
135 	wmb();
136 }
137 
138 static int dsi_14nm_phy_init(struct msm_dsi_phy *phy)
139 {
140 	struct platform_device *pdev = phy->pdev;
141 
142 	phy->lane_base = msm_ioremap(pdev, "dsi_phy_lane",
143 				"DSI_PHY_LANE");
144 	if (IS_ERR(phy->lane_base)) {
145 		dev_err(&pdev->dev, "%s: failed to map phy lane base\n",
146 			__func__);
147 		return -ENOMEM;
148 	}
149 
150 	return 0;
151 }
152 
153 const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs = {
154 	.type = MSM_DSI_PHY_14NM,
155 	.src_pll_truthtable = { {false, false}, {true, false} },
156 	.reg_cfg = {
157 		.num = 1,
158 		.regs = {
159 			{"vcca", 17000, 32},
160 		},
161 	},
162 	.ops = {
163 		.enable = dsi_14nm_phy_enable,
164 		.disable = dsi_14nm_phy_disable,
165 		.init = dsi_14nm_phy_init,
166 	},
167 	.io_start = { 0x994400, 0x996400 },
168 	.num_dsi_phy = 2,
169 };
170