]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/freescale/common/vsc3316_3308.c
Merge branch 'master' of git://git.denx.de/u-boot-usb
[karo-tx-uboot.git] / board / freescale / common / vsc3316_3308.c
1 /*
2  * Copyright 2012 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include "vsc3316_3308.h"
8
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
26
27 int vsc_if_enable(unsigned int vsc_addr)
28 {
29         u8 data;
30
31         debug("VSC:Configuring VSC at I2C address 0x%2x"
32                         " for 2-wire interface\n", vsc_addr);
33
34         /* enable 2-wire Serial InterFace (I2C) */
35         data = 0x02;
36         return i2c_write(vsc_addr, INTERFACE_MODE_REG, 1, &data, 1);
37 }
38
39 int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2],
40                 unsigned int num_con)
41 {
42         unsigned int i;
43         u8 rev_id = 0;
44         int ret;
45
46         debug("VSC:Initializing VSC3316 at I2C address 0x%2x"
47                 " for Tx\n", vsc_addr);
48
49         ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
50         if (ret < 0) {
51                 printf("VSC:0x%x could not read REV_ID from device.\n",
52                         vsc_addr);
53                 return ret;
54         }
55
56         if (rev_id != 0xab) {
57                 printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
58                         vsc_addr);
59                 return -ENODEV;
60         }
61
62         ret = vsc_if_enable(vsc_addr);
63         if (ret) {
64                 printf("VSC:0x%x could not configured for 2-wire I/F.\n",
65                         vsc_addr);
66                 return ret;
67         }
68
69         /* config connections - page 0x00 */
70         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
71
72         /* Making crosspoint connections, by connecting required
73          * input to output */
74         for (i = 0; i < num_con ; i++)
75                 i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
76
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);
82
83         /* Setting Global Input LOS threshold value */
84         i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
85
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);
91
92         /* configure global core control register, Turn on Global core power */
93         i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
94
95         vsc_wp_config(vsc_addr);
96
97         return 0;
98 }
99
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)
103 {
104         unsigned int i;
105         u8 rev_id = 0;
106         int ret;
107
108         debug("VSC:Initializing VSC3308 at I2C address 0x%x for Tx\n",
109               vsc_addr);
110
111         ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
112         if (ret < 0) {
113                 printf("VSC:0x%x could not read REV_ID from device.\n",
114                        vsc_addr);
115                 return ret;
116         }
117
118         if (rev_id != 0xab) {
119                 printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
120                        vsc_addr);
121                 return -ENODEV;
122         }
123
124         ret = vsc_if_enable(vsc_addr);
125         if (ret) {
126                 printf("VSC:0x%x could not configured for 2-wire I/F.\n",
127                        vsc_addr);
128                 return ret;
129         }
130
131         /* config connections - page 0x00 */
132         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
133
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);
137
138         /* Configure Tx/Rx Global Output PE1 */
139         i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE1, 0);
140
141         /* Configure Tx/Rx Global Output PE2 */
142         i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE2, 0);
143
144         /* Configure Tx/Rx Global Input GAIN */
145         i2c_reg_write(vsc_addr, GLOBAL_INPUT_GAIN, 0x3F);
146
147         /* Setting Global Input LOS threshold value */
148         i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0xE0);
149
150         /* Setting Global output termination */
151         i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_TERMINATION, 0);
152
153         /* Configure Tx/Rx Global Output level */
154         if (vsc_addr == VSC3308_TX_ADDRESS)
155                 i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 4);
156         else
157                 i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 2);
158
159         /* Making crosspoint connections, by connecting required
160          * input to output */
161         for (i = 0; i < num_con ; i++)
162                 i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
163
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);
169
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);
174         } else {
175                 i2c_reg_write(vsc_addr, 0, 0);
176                 i2c_reg_write(vsc_addr, 1, 0);
177         }
178
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);
184
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);
189         } else {
190                 i2c_reg_write(vsc_addr, 3, 0);
191                 i2c_reg_write(vsc_addr, 4, 0);
192         }
193
194         /* configure global core control register, Turn on Global core power */
195         i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
196
197         vsc_wp_config(vsc_addr);
198
199         return 0;
200 }
201 #endif
202
203 int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2],
204                 unsigned int num_con)
205 {
206         unsigned int i;
207         u8 rev_id = 0;
208         int ret;
209
210         debug("VSC:Initializing VSC3308 at I2C address 0x%x"
211                 " for Tx\n", vsc_addr);
212
213         ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
214         if (ret < 0) {
215                 printf("VSC:0x%x could not read REV_ID from device.\n",
216                         vsc_addr);
217                 return ret;
218         }
219
220         if (rev_id != 0xab) {
221                 printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
222                         vsc_addr);
223                 return -ENODEV;
224         }
225
226         ret = vsc_if_enable(vsc_addr);
227         if (ret) {
228                 printf("VSC:0x%x could not configured for 2-wire I/F.\n",
229                         vsc_addr);
230                 return ret;
231         }
232
233         /* config connections - page 0x00 */
234         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
235
236         /* Making crosspoint connections, by connecting required
237          * input to output */
238         for (i = 0; i < num_con ; i++)
239                 i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
240
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);
244
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);
250
251         /* Setting Global Input LOS threshold value */
252         i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
253
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);
259
260         /* configure global core control register, Turn on Global core power */
261         i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
262
263         vsc_wp_config(vsc_addr);
264
265         return 0;
266 }
267
268 void vsc_wp_config(unsigned int vsc_addr)
269 {
270         debug("VSC:Configuring VSC at address:0x%x for WP\n", vsc_addr);
271
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);
276 }