Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / scsi / ufs / tc-dwc-g210.c
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  */
24 static 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  */
88 static 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  */
141 static 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
207 out:
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  */
218 static 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
247 out:
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  */
259 int 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
278 out:
279         return ret;
280 }
281 EXPORT_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  */
291 int 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
310 out:
311         return ret;
312 }
313 EXPORT_SYMBOL(tc_dwc_g210_config_20_bit);
314
315 MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
316 MODULE_DESCRIPTION("Synopsys G210 Test Chip driver");
317 MODULE_LICENSE("Dual BSD/GPL");