Merge branch 'next' of git://git.denx.de/u-boot-mpc83xx
[platform/kernel/u-boot.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_LOS                0x55
17 #define GLOBAL_CORE_CNTRL               0x5D
18 #define OUTPUT_MODE_PAGE                0x23
19 #define CORE_CONTROL_PAGE               0x25
20 #define CORE_CONFIG_REG         0x75
21
22 int vsc_if_enable(unsigned int vsc_addr)
23 {
24         u8 data;
25
26         debug("VSC:Configuring VSC at I2C address 0x%2x"
27                         " for 2-wire interface\n", vsc_addr);
28
29         /* enable 2-wire Serial InterFace (I2C) */
30         data = 0x02;
31         return i2c_write(vsc_addr, INTERFACE_MODE_REG, 1, &data, 1);
32 }
33
34 int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2],
35                 unsigned int num_con)
36 {
37         unsigned int i;
38         u8 rev_id = 0;
39         int ret;
40
41         debug("VSC:Initializing VSC3316 at I2C address 0x%2x"
42                 " for Tx\n", vsc_addr);
43
44         ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
45         if (ret < 0) {
46                 printf("VSC:0x%x could not read REV_ID from device.\n",
47                         vsc_addr);
48                 return ret;
49         }
50
51         if (rev_id != 0xab) {
52                 printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
53                         vsc_addr);
54                 return -ENODEV;
55         }
56
57         ret = vsc_if_enable(vsc_addr);
58         if (ret) {
59                 printf("VSC:0x%x could not configured for 2-wire I/F.\n",
60                         vsc_addr);
61                 return ret;
62         }
63
64         /* config connections - page 0x00 */
65         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
66
67         /* Making crosspoint connections, by connecting required
68          * input to output */
69         for (i = 0; i < num_con ; i++)
70                 i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
71
72         /* input state - page 0x13 */
73         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
74         /* Configuring the required input of the switch */
75         for (i = 0; i < num_con ; i++)
76                 i2c_reg_write(vsc_addr, con_arr[i][0], 0x80);
77
78         /* Setting Global Input LOS threshold value */
79         i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
80
81         /* config output mode - page 0x23 */
82         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
83         /* Turn ON the Output driver correspond to required output*/
84         for (i = 0; i < num_con ; i++)
85                 i2c_reg_write(vsc_addr,  con_arr[i][1], 0);
86
87         /* configure global core control register, Turn on Global core power */
88         i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
89
90         vsc_wp_config(vsc_addr);
91
92         return 0;
93 }
94
95 int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2],
96                 unsigned int num_con)
97 {
98         unsigned int i;
99         u8 rev_id = 0;
100         int ret;
101
102         debug("VSC:Initializing VSC3308 at I2C address 0x%x"
103                 " for Tx\n", vsc_addr);
104
105         ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
106         if (ret < 0) {
107                 printf("VSC:0x%x could not read REV_ID from device.\n",
108                         vsc_addr);
109                 return ret;
110         }
111
112         if (rev_id != 0xab) {
113                 printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
114                         vsc_addr);
115                 return -ENODEV;
116         }
117
118         ret = vsc_if_enable(vsc_addr);
119         if (ret) {
120                 printf("VSC:0x%x could not configured for 2-wire I/F.\n",
121                         vsc_addr);
122                 return ret;
123         }
124
125         /* config connections - page 0x00 */
126         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
127
128         /* Making crosspoint connections, by connecting required
129          * input to output */
130         for (i = 0; i < num_con ; i++)
131                 i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
132
133         /*Configure Global Input ISE and gain */
134         i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0x12);
135         i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0x12);
136
137         /* input state - page 0x13 */
138         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
139         /* Turning ON the required input of the switch */
140         for (i = 0; i < num_con ; i++)
141                 i2c_reg_write(vsc_addr, con_arr[i][0], 0);
142
143         /* Setting Global Input LOS threshold value */
144         i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
145
146         /* config output mode - page 0x23 */
147         i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
148         /* Turn ON the Output driver correspond to required output*/
149         for (i = 0; i < num_con ; i++)
150                 i2c_reg_write(vsc_addr,  con_arr[i][1], 0);
151
152         /* configure global core control register, Turn on Global core power */
153         i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
154
155         vsc_wp_config(vsc_addr);
156
157         return 0;
158 }
159
160 void vsc_wp_config(unsigned int vsc_addr)
161 {
162         debug("VSC:Configuring VSC at address:0x%x for WP\n", vsc_addr);
163
164         /* For new crosspoint configuration to occur, WP bit of
165          * CORE_CONFIG_REG should be set 1 and then reset to 0 */
166         i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x01);
167         i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x0);
168 }