1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Synopsys G210 Test Chip driver
4 *
5 * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
6 *
7 * Authors: Joao Pinto <jpinto@synopsys.com>
8 */
9
10#include "ufshcd.h"
11#include "unipro.h"
12
13#include "ufshcd-dwc.h"
14#include "ufshci-dwc.h"
15#include "tc-dwc-g210.h"
16
17/**
18 * tc_dwc_g210_setup_40bit_rmmi()
19 * This function configures Synopsys TC specific atributes (40-bit RMMI)
20 * @hba: Pointer to drivers structure
21 *
22 * Returns 0 on success or non-zero value on failure
23 */
24static int tc_dwc_g210_setup_40bit_rmmi(struct ufs_hba *hba)
25{
26	static const struct ufshcd_dme_attr_val setup_attrs[] = {
27		{ UIC_ARG_MIB(TX_GLOBALHIBERNATE), 0x00, DME_LOCAL },
28		{ UIC_ARG_MIB(REFCLKMODE), 0x01, DME_LOCAL },
29		{ UIC_ARG_MIB(CDIRECTCTRL6), 0x80, DME_LOCAL },
30		{ UIC_ARG_MIB(CBDIVFACTOR), 0x08, DME_LOCAL },
31		{ UIC_ARG_MIB(CBDCOCTRL5), 0x64, DME_LOCAL },
32		{ UIC_ARG_MIB(CBPRGTUNING), 0x09, DME_LOCAL },
33		{ UIC_ARG_MIB(RTOBSERVESELECT), 0x00, DME_LOCAL },
34		{ UIC_ARG_MIB_SEL(TX_REFCLKFREQ, SELIND_LN0_TX), 0x01,
35								DME_LOCAL },
36		{ UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, SELIND_LN0_TX), 0x19,
37								DME_LOCAL },
38		{ UIC_ARG_MIB_SEL(CFGEXTRATTR, SELIND_LN0_TX), 0x14,
39								DME_LOCAL },
40		{ UIC_ARG_MIB_SEL(DITHERCTRL2, SELIND_LN0_TX), 0xd6,
41								DME_LOCAL },
42		{ UIC_ARG_MIB_SEL(RX_REFCLKFREQ, SELIND_LN0_RX), 0x01,
43								DME_LOCAL },
44		{ UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, SELIND_LN0_RX), 0x19,
45								DME_LOCAL },
46		{ UIC_ARG_MIB_SEL(CFGWIDEINLN, SELIND_LN0_RX), 4,
47								DME_LOCAL },
48		{ UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN0_RX), 0x80,
49								DME_LOCAL },
50		{ UIC_ARG_MIB(DIRECTCTRL10), 0x04, DME_LOCAL },
51		{ UIC_ARG_MIB(DIRECTCTRL19), 0x02, DME_LOCAL },
52		{ UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN0_RX), 0x80,
53								DME_LOCAL },
54		{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, SELIND_LN0_RX), 0x03,
55								DME_LOCAL },
56		{ UIC_ARG_MIB_SEL(CFGRXOVR8, SELIND_LN0_RX), 0x16,
57								DME_LOCAL },
58		{ UIC_ARG_MIB_SEL(RXDIRECTCTRL2, SELIND_LN0_RX), 0x42,
59								DME_LOCAL },
60		{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, SELIND_LN0_RX), 0xa4,
61								DME_LOCAL },
62		{ UIC_ARG_MIB_SEL(RXCALCTRL, SELIND_LN0_RX), 0x01,
63								DME_LOCAL },
64		{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, SELIND_LN0_RX), 0x01,
65								DME_LOCAL },
66		{ UIC_ARG_MIB_SEL(CFGRXOVR4, SELIND_LN0_RX), 0x28,
67								DME_LOCAL },
68		{ UIC_ARG_MIB_SEL(RXSQCTRL, SELIND_LN0_RX), 0x1E,
69								DME_LOCAL },
70		{ UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN0_RX), 0x2f,
71								DME_LOCAL },
72		{ UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN0_RX), 0x2f,
73								DME_LOCAL },
74		{ UIC_ARG_MIB(CBPRGPLL2), 0x00, DME_LOCAL },
75	};
76
77	return ufshcd_dwc_dme_set_attrs(hba, setup_attrs,
78						ARRAY_SIZE(setup_attrs));
79}
80
81/**
82 * tc_dwc_g210_setup_20bit_rmmi_lane0()
83 * This function configures Synopsys TC 20-bit RMMI Lane 0
84 * @hba: Pointer to drivers structure
85 *
86 * Returns 0 on success or non-zero value on failure
87 */
88static int tc_dwc_g210_setup_20bit_rmmi_lane0(struct ufs_hba *hba)
89{
90	static const struct ufshcd_dme_attr_val setup_attrs[] = {
91		{ UIC_ARG_MIB_SEL(TX_REFCLKFREQ, SELIND_LN0_TX), 0x01,
92								DME_LOCAL },
93		{ UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, SELIND_LN0_TX), 0x19,
94								DME_LOCAL },
95		{ UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, SELIND_LN0_RX), 0x19,
96								DME_LOCAL },
97		{ UIC_ARG_MIB_SEL(CFGEXTRATTR, SELIND_LN0_TX), 0x12,
98								DME_LOCAL },
99		{ UIC_ARG_MIB_SEL(DITHERCTRL2, SELIND_LN0_TX), 0xd6,
100								DME_LOCAL },
101		{ UIC_ARG_MIB_SEL(RX_REFCLKFREQ, SELIND_LN0_RX), 0x01,
102								DME_LOCAL },
103		{ UIC_ARG_MIB_SEL(CFGWIDEINLN, SELIND_LN0_RX), 2,
104								DME_LOCAL },
105		{ UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN0_RX), 0x80,
106								DME_LOCAL },
107		{ UIC_ARG_MIB(DIRECTCTRL10), 0x04, DME_LOCAL },
108		{ UIC_ARG_MIB(DIRECTCTRL19), 0x02, DME_LOCAL },
109		{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, SELIND_LN0_RX), 0x03,
110								DME_LOCAL },
111		{ UIC_ARG_MIB_SEL(CFGRXOVR8, SELIND_LN0_RX), 0x16,
112								DME_LOCAL },
113		{ UIC_ARG_MIB_SEL(RXDIRECTCTRL2, SELIND_LN0_RX), 0x42,
114								DME_LOCAL },
115		{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, SELIND_LN0_RX), 0xa4,
116								DME_LOCAL },
117		{ UIC_ARG_MIB_SEL(RXCALCTRL, SELIND_LN0_RX), 0x01,
118								DME_LOCAL },
119		{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, SELIND_LN0_RX), 0x01,
120								DME_LOCAL },
121		{ UIC_ARG_MIB_SEL(CFGRXOVR4, SELIND_LN0_RX), 0x28,
122								DME_LOCAL },
123		{ UIC_ARG_MIB_SEL(RXSQCTRL, SELIND_LN0_RX), 0x1E,
124								DME_LOCAL },
125		{ UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN0_RX), 0x2f,
126								DME_LOCAL },
127		{ UIC_ARG_MIB(CBPRGPLL2), 0x00, DME_LOCAL },
128	};
129
130	return ufshcd_dwc_dme_set_attrs(hba, setup_attrs,
131						ARRAY_SIZE(setup_attrs));
132}
133
134/**
135 * tc_dwc_g210_setup_20bit_rmmi_lane1()
136 * This function configures Synopsys TC 20-bit RMMI Lane 1
137 * @hba: Pointer to drivers structure
138 *
139 * Returns 0 on success or non-zero value on failure
140 */
141static int tc_dwc_g210_setup_20bit_rmmi_lane1(struct ufs_hba *hba)
142{
143	int connected_rx_lanes = 0;
144	int connected_tx_lanes = 0;
145	int ret = 0;
146
147	static const struct ufshcd_dme_attr_val setup_tx_attrs[] = {
148		{ UIC_ARG_MIB_SEL(TX_REFCLKFREQ, SELIND_LN1_TX), 0x0d,
149								DME_LOCAL },
150		{ UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, SELIND_LN1_TX), 0x19,
151								DME_LOCAL },
152		{ UIC_ARG_MIB_SEL(CFGEXTRATTR, SELIND_LN1_TX), 0x12,
153								DME_LOCAL },
154		{ UIC_ARG_MIB_SEL(DITHERCTRL2, SELIND_LN0_TX), 0xd6,
155								DME_LOCAL },
156	};
157
158	static const struct ufshcd_dme_attr_val setup_rx_attrs[] = {
159		{ UIC_ARG_MIB_SEL(RX_REFCLKFREQ, SELIND_LN1_RX), 0x01,
160								DME_LOCAL },
161		{ UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, SELIND_LN1_RX), 0x19,
162								DME_LOCAL },
163		{ UIC_ARG_MIB_SEL(CFGWIDEINLN, SELIND_LN1_RX), 2,
164								DME_LOCAL },
165		{ UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN1_RX), 0x80,
166								DME_LOCAL },
167		{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, SELIND_LN1_RX), 0x03,
168								DME_LOCAL },
169		{ UIC_ARG_MIB_SEL(CFGRXOVR8, SELIND_LN1_RX), 0x16,
170								DME_LOCAL },
171		{ UIC_ARG_MIB_SEL(RXDIRECTCTRL2, SELIND_LN1_RX), 0x42,
172								DME_LOCAL },
173		{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, SELIND_LN1_RX), 0xa4,
174								DME_LOCAL },
175		{ UIC_ARG_MIB_SEL(RXCALCTRL, SELIND_LN1_RX), 0x01,
176								DME_LOCAL },
177		{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, SELIND_LN1_RX), 0x01,
178								DME_LOCAL },
179		{ UIC_ARG_MIB_SEL(CFGRXOVR4, SELIND_LN1_RX), 0x28,
180								DME_LOCAL },
181		{ UIC_ARG_MIB_SEL(RXSQCTRL, SELIND_LN1_RX), 0x1E,
182								DME_LOCAL },
183		{ UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN1_RX), 0x2f,
184								DME_LOCAL },
185	};
186
187	/* Get the available lane count */
188	ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILRXDATALANES),
189			&connected_rx_lanes);
190	ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILTXDATALANES),
191			&connected_tx_lanes);
192
193	if (connected_tx_lanes == 2) {
194
195		ret = ufshcd_dwc_dme_set_attrs(hba, setup_tx_attrs,
196						ARRAY_SIZE(setup_tx_attrs));
197
198		if (ret)
199			goto out;
200	}
201
202	if (connected_rx_lanes == 2) {
203		ret = ufshcd_dwc_dme_set_attrs(hba, setup_rx_attrs,
204						ARRAY_SIZE(setup_rx_attrs));
205	}
206
207out:
208	return ret;
209}
210
211/**
212 * tc_dwc_g210_setup_20bit_rmmi()
213 * This function configures Synopsys TC specific atributes (20-bit RMMI)
214 * @hba: Pointer to drivers structure
215 *
216 * Returns 0 on success or non-zero value on failure
217 */
218static int tc_dwc_g210_setup_20bit_rmmi(struct ufs_hba *hba)
219{
220	int ret = 0;
221
222	static const struct ufshcd_dme_attr_val setup_attrs[] = {
223		{ UIC_ARG_MIB(TX_GLOBALHIBERNATE), 0x00, DME_LOCAL },
224		{ UIC_ARG_MIB(REFCLKMODE), 0x01, DME_LOCAL },
225		{ UIC_ARG_MIB(CDIRECTCTRL6), 0xc0, DME_LOCAL },
226		{ UIC_ARG_MIB(CBDIVFACTOR), 0x44, DME_LOCAL },
227		{ UIC_ARG_MIB(CBDCOCTRL5), 0x64, DME_LOCAL },
228		{ UIC_ARG_MIB(CBPRGTUNING), 0x09, DME_LOCAL },
229		{ UIC_ARG_MIB(RTOBSERVESELECT), 0x00, DME_LOCAL },
230	};
231
232	ret = ufshcd_dwc_dme_set_attrs(hba, setup_attrs,
233						ARRAY_SIZE(setup_attrs));
234	if (ret)
235		goto out;
236
237	/* Lane 0 configuration*/
238	ret = tc_dwc_g210_setup_20bit_rmmi_lane0(hba);
239	if (ret)
240		goto out;
241
242	/* Lane 1 configuration*/
243	ret = tc_dwc_g210_setup_20bit_rmmi_lane1(hba);
244	if (ret)
245		goto out;
246
247out:
248	return ret;
249}
250
251/**
252 * tc_dwc_g210_config_40_bit()
253 * This function configures Local (host) Synopsys 40-bit TC specific attributes
254 *
255 * @hba: Pointer to drivers structure
256 *
257 * Returns 0 on success non-zero value on failure
258 */
259int tc_dwc_g210_config_40_bit(struct ufs_hba *hba)
260{
261	int ret = 0;
262
263	dev_info(hba->dev, "Configuring Test Chip 40-bit RMMI\n");
264	ret = tc_dwc_g210_setup_40bit_rmmi(hba);
265	if (ret) {
266		dev_err(hba->dev, "Configuration failed\n");
267		goto out;
268	}
269
270	/* To write Shadow register bank to effective configuration block */
271	ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYCFGUPDT), 0x01);
272	if (ret)
273		goto out;
274
275	/* To configure Debug OMC */
276	ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_DEBUGOMC), 0x01);
277
278out:
279	return ret;
280}
281EXPORT_SYMBOL(tc_dwc_g210_config_40_bit);
282
283/**
284 * tc_dwc_g210_config_20_bit()
285 * This function configures Local (host) Synopsys 20-bit TC specific attributes
286 *
287 * @hba: Pointer to drivers structure
288 *
289 * Returns 0 on success non-zero value on failure
290 */
291int tc_dwc_g210_config_20_bit(struct ufs_hba *hba)
292{
293	int ret = 0;
294
295	dev_info(hba->dev, "Configuring Test Chip 20-bit RMMI\n");
296	ret = tc_dwc_g210_setup_20bit_rmmi(hba);
297	if (ret) {
298		dev_err(hba->dev, "Configuration failed\n");
299		goto out;
300	}
301
302	/* To write Shadow register bank to effective configuration block */
303	ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYCFGUPDT), 0x01);
304	if (ret)
305		goto out;
306
307	/* To configure Debug OMC */
308	ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_DEBUGOMC), 0x01);
309
310out:
311	return ret;
312}
313EXPORT_SYMBOL(tc_dwc_g210_config_20_bit);
314
315MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
316MODULE_DESCRIPTION("Synopsys G210 Test Chip driver");
317MODULE_LICENSE("Dual BSD/GPL");
318