2 * Copyright 2012 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: GPL-2.0+
7 #include "vsc3316_3308.h"
9 #define REVISION_ID_REG 0x7E
10 #define INTERFACE_MODE_REG 0x79
11 #define CURRENT_PAGE_REGISTER 0x7F
12 #define CONNECTION_CONFIG_PAGE 0x00
13 #define INPUT_STATE_REG 0x13
14 #define GLOBAL_INPUT_ISE1 0x51
15 #define GLOBAL_INPUT_ISE2 0x52
16 #define GLOBAL_INPUT_GAIN 0x53
17 #define GLOBAL_INPUT_LOS 0x55
18 #define GLOBAL_OUTPUT_PE1 0x56
19 #define GLOBAL_OUTPUT_PE2 0x57
20 #define GLOBAL_OUTPUT_LEVEL 0x58
21 #define GLOBAL_OUTPUT_TERMINATION 0x5A
22 #define GLOBAL_CORE_CNTRL 0x5D
23 #define OUTPUT_MODE_PAGE 0x23
24 #define CORE_CONTROL_PAGE 0x25
25 #define CORE_CONFIG_REG 0x75
27 int vsc_if_enable(unsigned int vsc_addr)
31 debug("VSC:Configuring VSC at I2C address 0x%2x"
32 " for 2-wire interface\n", vsc_addr);
34 /* enable 2-wire Serial InterFace (I2C) */
36 return i2c_write(vsc_addr, INTERFACE_MODE_REG, 1, &data, 1);
39 int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2],
46 debug("VSC:Initializing VSC3316 at I2C address 0x%2x"
47 " for Tx\n", vsc_addr);
49 ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
51 printf("VSC:0x%x could not read REV_ID from device.\n",
57 printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
62 ret = vsc_if_enable(vsc_addr);
64 printf("VSC:0x%x could not configured for 2-wire I/F.\n",
69 /* config connections - page 0x00 */
70 i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
72 /* Making crosspoint connections, by connecting required
74 for (i = 0; i < num_con ; i++)
75 i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
77 /* input state - page 0x13 */
78 i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
79 /* Configuring the required input of the switch */
80 for (i = 0; i < num_con ; i++)
81 i2c_reg_write(vsc_addr, con_arr[i][0], 0x80);
83 /* Setting Global Input LOS threshold value */
84 i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
86 /* config output mode - page 0x23 */
87 i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
88 /* Turn ON the Output driver correspond to required output*/
89 for (i = 0; i < num_con ; i++)
90 i2c_reg_write(vsc_addr, con_arr[i][1], 0);
92 /* configure global core control register, Turn on Global core power */
93 i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
95 vsc_wp_config(vsc_addr);
100 #ifdef CONFIG_SYS_FSL_B4860QDS_XFI_ERR
101 int vsc3308_config_adjust(unsigned int vsc_addr, const int8_t con_arr[][2],
102 unsigned int num_con)
108 debug("VSC:Initializing VSC3308 at I2C address 0x%x for Tx\n",
111 ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
113 printf("VSC:0x%x could not read REV_ID from device.\n",
118 if (rev_id != 0xab) {
119 printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
124 ret = vsc_if_enable(vsc_addr);
126 printf("VSC:0x%x could not configured for 2-wire I/F.\n",
131 /* config connections - page 0x00 */
132 i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
134 /* Configure Global Input ISE */
135 i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0);
136 i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0);
138 /* Configure Tx/Rx Global Output PE1 */
139 i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE1, 0);
141 /* Configure Tx/Rx Global Output PE2 */
142 i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE2, 0);
144 /* Configure Tx/Rx Global Input GAIN */
145 i2c_reg_write(vsc_addr, GLOBAL_INPUT_GAIN, 0x3F);
147 /* Setting Global Input LOS threshold value */
148 i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0xE0);
150 /* Setting Global output termination */
151 i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_TERMINATION, 0);
153 /* Configure Tx/Rx Global Output level */
154 if (vsc_addr == VSC3308_TX_ADDRESS)
155 i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 4);
157 i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 2);
159 /* Making crosspoint connections, by connecting required
161 for (i = 0; i < num_con ; i++)
162 i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
164 /* input state - page 0x13 */
165 i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
166 /* Turning off all the required input of the switch */
167 for (i = 0; i < num_con; i++)
168 i2c_reg_write(vsc_addr, con_arr[i][0], 1);
170 /* only turn on specific Tx/Rx requested by the XFI erratum */
171 if (vsc_addr == VSC3308_TX_ADDRESS) {
172 i2c_reg_write(vsc_addr, 2, 0);
173 i2c_reg_write(vsc_addr, 3, 0);
175 i2c_reg_write(vsc_addr, 0, 0);
176 i2c_reg_write(vsc_addr, 1, 0);
179 /* config output mode - page 0x23 */
180 i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
181 /* Turn off the Output driver correspond to required output*/
182 for (i = 0; i < num_con ; i++)
183 i2c_reg_write(vsc_addr, con_arr[i][1], 1);
185 /* only turn on specific Tx/Rx requested by the XFI erratum */
186 if (vsc_addr == VSC3308_TX_ADDRESS) {
187 i2c_reg_write(vsc_addr, 0, 0);
188 i2c_reg_write(vsc_addr, 1, 0);
190 i2c_reg_write(vsc_addr, 3, 0);
191 i2c_reg_write(vsc_addr, 4, 0);
194 /* configure global core control register, Turn on Global core power */
195 i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
197 vsc_wp_config(vsc_addr);
203 int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2],
204 unsigned int num_con)
210 debug("VSC:Initializing VSC3308 at I2C address 0x%x"
211 " for Tx\n", vsc_addr);
213 ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
215 printf("VSC:0x%x could not read REV_ID from device.\n",
220 if (rev_id != 0xab) {
221 printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
226 ret = vsc_if_enable(vsc_addr);
228 printf("VSC:0x%x could not configured for 2-wire I/F.\n",
233 /* config connections - page 0x00 */
234 i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
236 /* Making crosspoint connections, by connecting required
238 for (i = 0; i < num_con ; i++)
239 i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
241 /*Configure Global Input ISE and gain */
242 i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0x12);
243 i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0x12);
245 /* input state - page 0x13 */
246 i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
247 /* Turning ON the required input of the switch */
248 for (i = 0; i < num_con ; i++)
249 i2c_reg_write(vsc_addr, con_arr[i][0], 0);
251 /* Setting Global Input LOS threshold value */
252 i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
254 /* config output mode - page 0x23 */
255 i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
256 /* Turn ON the Output driver correspond to required output*/
257 for (i = 0; i < num_con ; i++)
258 i2c_reg_write(vsc_addr, con_arr[i][1], 0);
260 /* configure global core control register, Turn on Global core power */
261 i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
263 vsc_wp_config(vsc_addr);
268 void vsc_wp_config(unsigned int vsc_addr)
270 debug("VSC:Configuring VSC at address:0x%x for WP\n", vsc_addr);
272 /* For new crosspoint configuration to occur, WP bit of
273 * CORE_CONFIG_REG should be set 1 and then reset to 0 */
274 i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x01);
275 i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x0);