cpu: imx8: show RevC instead of Rev? at boot log
[oweals/u-boot.git] / board / freescale / common / vsc3316_3308.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2012 Freescale Semiconductor, Inc.
4  */
5
6 #include "vsc3316_3308.h"
7
8 #define REVISION_ID_REG         0x7E
9 #define INTERFACE_MODE_REG              0x79
10 #define CURRENT_PAGE_REGISTER           0x7F
11 #define CONNECTION_CONFIG_PAGE          0x00
12 #define INPUT_STATE_REG         0x13
13 #define GLOBAL_INPUT_ISE1               0x51
14 #define GLOBAL_INPUT_ISE2               0x52
15 #define GLOBAL_INPUT_GAIN               0x53
16 #define GLOBAL_INPUT_LOS                0x55
17 #define GLOBAL_OUTPUT_PE1               0x56
18 #define GLOBAL_OUTPUT_PE2               0x57
19 #define GLOBAL_OUTPUT_LEVEL             0x58
20 #define GLOBAL_OUTPUT_TERMINATION       0x5A
21 #define GLOBAL_CORE_CNTRL               0x5D
22 #define OUTPUT_MODE_PAGE                0x23
23 #define CORE_CONTROL_PAGE               0x25
24 #define CORE_CONFIG_REG         0x75
25
26 int vsc_if_enable(unsigned int vsc_addr)
27 {
28         u8 data;
29
30         debug("VSC:Configuring VSC at I2C address 0x%2x"
31                         " for 2-wire interface\n", vsc_addr);
32
33         /* enable 2-wire Serial InterFace (I2C) */
34         data = 0x02;
35         return i2c_write(vsc_addr, INTERFACE_MODE_REG, 1, &data, 1);
36 }
37
38 int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2],
39                 unsigned int num_con)
40 {
41         unsigned int i;
42         u8 rev_id = 0;
43         int ret;
44
45         debug("VSC:Initializing VSC3316 at I2C address 0x%2x"
46                 " for Tx\n", vsc_addr);
47
48         ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
49         if (ret < 0) {
50                 printf("VSC:0x%x could not read REV_ID from device.\n",
51                         vsc_addr);
52                 return ret;
53         }
54
55         if (rev_id != 0xab) {
56                 printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
57                         vsc_addr);
58                 return -ENODEV;
59         }
60
61         ret = vsc_if_enable(vsc_addr);
62         if (ret) {
63                 printf("VSC:0x%x could not configured for 2-wire I/F.\n",
64                         vsc_addr);
65                 return ret;
66         }
67
68         /* config connections - page 0x00 */
69         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
70
71         /* Making crosspoint connections, by connecting required
72          * input to output */
73         for (i = 0; i < num_con ; i++)
74                 i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
75
76         /* input state - page 0x13 */
77         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
78         /* Configuring the required input of the switch */
79         for (i = 0; i < num_con ; i++)
80                 i2c_reg_write(vsc_addr, con_arr[i][0], 0x80);
81
82         /* Setting Global Input LOS threshold value */
83         i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
84
85         /* config output mode - page 0x23 */
86         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
87         /* Turn ON the Output driver correspond to required output*/
88         for (i = 0; i < num_con ; i++)
89                 i2c_reg_write(vsc_addr,  con_arr[i][1], 0);
90
91         /* configure global core control register, Turn on Global core power */
92         i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
93
94         vsc_wp_config(vsc_addr);
95
96         return 0;
97 }
98
99 #ifdef CONFIG_SYS_FSL_B4860QDS_XFI_ERR
100 int vsc3308_config_adjust(unsigned int vsc_addr, const int8_t con_arr[][2],
101                 unsigned int num_con)
102 {
103         unsigned int i;
104         u8 rev_id = 0;
105         int ret;
106
107         debug("VSC:Initializing VSC3308 at I2C address 0x%x for Tx\n",
108               vsc_addr);
109
110         ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
111         if (ret < 0) {
112                 printf("VSC:0x%x could not read REV_ID from device.\n",
113                        vsc_addr);
114                 return ret;
115         }
116
117         if (rev_id != 0xab) {
118                 printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
119                        vsc_addr);
120                 return -ENODEV;
121         }
122
123         ret = vsc_if_enable(vsc_addr);
124         if (ret) {
125                 printf("VSC:0x%x could not configured for 2-wire I/F.\n",
126                        vsc_addr);
127                 return ret;
128         }
129
130         /* config connections - page 0x00 */
131         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
132
133         /* Configure Global Input ISE */
134         i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0);
135         i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0);
136
137         /* Configure Tx/Rx Global Output PE1 */
138         i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE1, 0);
139
140         /* Configure Tx/Rx Global Output PE2 */
141         i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE2, 0);
142
143         /* Configure Tx/Rx Global Input GAIN */
144         i2c_reg_write(vsc_addr, GLOBAL_INPUT_GAIN, 0x3F);
145
146         /* Setting Global Input LOS threshold value */
147         i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0xE0);
148
149         /* Setting Global output termination */
150         i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_TERMINATION, 0);
151
152         /* Configure Tx/Rx Global Output level */
153         if (vsc_addr == VSC3308_TX_ADDRESS)
154                 i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 4);
155         else
156                 i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 2);
157
158         /* Making crosspoint connections, by connecting required
159          * input to output */
160         for (i = 0; i < num_con ; i++)
161                 i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
162
163         /* input state - page 0x13 */
164         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
165         /* Turning off all the required input of the switch */
166         for (i = 0; i < num_con; i++)
167                 i2c_reg_write(vsc_addr, con_arr[i][0], 1);
168
169         /* only turn on specific Tx/Rx requested by the XFI erratum */
170         if (vsc_addr == VSC3308_TX_ADDRESS) {
171                 i2c_reg_write(vsc_addr, 2, 0);
172                 i2c_reg_write(vsc_addr, 3, 0);
173         } else {
174                 i2c_reg_write(vsc_addr, 0, 0);
175                 i2c_reg_write(vsc_addr, 1, 0);
176         }
177
178         /* config output mode - page 0x23 */
179         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
180         /* Turn off the Output driver correspond to required output*/
181         for (i = 0; i < num_con ; i++)
182                 i2c_reg_write(vsc_addr,  con_arr[i][1], 1);
183
184         /* only turn on specific Tx/Rx requested by the XFI erratum */
185         if (vsc_addr == VSC3308_TX_ADDRESS) {
186                 i2c_reg_write(vsc_addr, 0, 0);
187                 i2c_reg_write(vsc_addr, 1, 0);
188         } else {
189                 i2c_reg_write(vsc_addr, 3, 0);
190                 i2c_reg_write(vsc_addr, 4, 0);
191         }
192
193         /* configure global core control register, Turn on Global core power */
194         i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
195
196         vsc_wp_config(vsc_addr);
197
198         return 0;
199 }
200 #endif
201
202 int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2],
203                 unsigned int num_con)
204 {
205         unsigned int i;
206         u8 rev_id = 0;
207         int ret;
208
209         debug("VSC:Initializing VSC3308 at I2C address 0x%x"
210                 " for Tx\n", vsc_addr);
211
212         ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
213         if (ret < 0) {
214                 printf("VSC:0x%x could not read REV_ID from device.\n",
215                         vsc_addr);
216                 return ret;
217         }
218
219         if (rev_id != 0xab) {
220                 printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
221                         vsc_addr);
222                 return -ENODEV;
223         }
224
225         ret = vsc_if_enable(vsc_addr);
226         if (ret) {
227                 printf("VSC:0x%x could not configured for 2-wire I/F.\n",
228                         vsc_addr);
229                 return ret;
230         }
231
232         /* config connections - page 0x00 */
233         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
234
235         /* Making crosspoint connections, by connecting required
236          * input to output */
237         for (i = 0; i < num_con ; i++)
238                 i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
239
240         /*Configure Global Input ISE and gain */
241         i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0x12);
242         i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0x12);
243
244         /* input state - page 0x13 */
245         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
246         /* Turning ON the required input of the switch */
247         for (i = 0; i < num_con ; i++)
248                 i2c_reg_write(vsc_addr, con_arr[i][0], 0);
249
250         /* Setting Global Input LOS threshold value */
251         i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
252
253         /* config output mode - page 0x23 */
254         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
255         /* Turn ON the Output driver correspond to required output*/
256         for (i = 0; i < num_con ; i++)
257                 i2c_reg_write(vsc_addr,  con_arr[i][1], 0);
258
259         /* configure global core control register, Turn on Global core power */
260         i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
261
262         vsc_wp_config(vsc_addr);
263
264         return 0;
265 }
266
267 void vsc_wp_config(unsigned int vsc_addr)
268 {
269         debug("VSC:Configuring VSC at address:0x%x for WP\n", vsc_addr);
270
271         /* For new crosspoint configuration to occur, WP bit of
272          * CORE_CONFIG_REG should be set 1 and then reset to 0 */
273         i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x01);
274         i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x0);
275 }