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