1*aa42cb71SShaveta Leekha /*
2*aa42cb71SShaveta Leekha  * Copyright 2012 Freescale Semiconductor, Inc.
3*aa42cb71SShaveta Leekha  *
4*aa42cb71SShaveta Leekha  * See file CREDITS for list of people who contributed to this
5*aa42cb71SShaveta Leekha  * project.
6*aa42cb71SShaveta Leekha  *
7*aa42cb71SShaveta Leekha  * This program is free software; you can redistribute it and/or
8*aa42cb71SShaveta Leekha  * modify it under the terms of the GNU General Public License as
9*aa42cb71SShaveta Leekha  * published by the Free Software Foundation; either version 2 of
10*aa42cb71SShaveta Leekha  * the License, or (at your option) any later version.
11*aa42cb71SShaveta Leekha  *
12*aa42cb71SShaveta Leekha  * This program is distributed in the hope that it will be useful,
13*aa42cb71SShaveta Leekha  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*aa42cb71SShaveta Leekha  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*aa42cb71SShaveta Leekha  * GNU General Public License for more details.
16*aa42cb71SShaveta Leekha  *
17*aa42cb71SShaveta Leekha  * You should have received a copy of the GNU General Public License
18*aa42cb71SShaveta Leekha  * along with this program; if not, write to the Free Software
19*aa42cb71SShaveta Leekha  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20*aa42cb71SShaveta Leekha  * MA 02111-1307 USA
21*aa42cb71SShaveta Leekha  */
22*aa42cb71SShaveta Leekha 
23*aa42cb71SShaveta Leekha #include "vsc3316_3308.h"
24*aa42cb71SShaveta Leekha 
25*aa42cb71SShaveta Leekha #define REVISION_ID_REG		0x7E
26*aa42cb71SShaveta Leekha #define INTERFACE_MODE_REG		0x79
27*aa42cb71SShaveta Leekha #define CURRENT_PAGE_REGISTER		0x7F
28*aa42cb71SShaveta Leekha #define CONNECTION_CONFIG_PAGE		0x00
29*aa42cb71SShaveta Leekha #define INPUT_STATE_REG		0x13
30*aa42cb71SShaveta Leekha #define GLOBAL_INPUT_ISE1		0x51
31*aa42cb71SShaveta Leekha #define GLOBAL_INPUT_ISE2		0x52
32*aa42cb71SShaveta Leekha #define GLOBAL_INPUT_LOS		0x55
33*aa42cb71SShaveta Leekha #define GLOBAL_CORE_CNTRL		0x5D
34*aa42cb71SShaveta Leekha #define OUTPUT_MODE_PAGE		0x23
35*aa42cb71SShaveta Leekha #define CORE_CONTROL_PAGE		0x25
36*aa42cb71SShaveta Leekha #define CORE_CONFIG_REG		0x75
37*aa42cb71SShaveta Leekha 
38*aa42cb71SShaveta Leekha int vsc_if_enable(unsigned int vsc_addr)
39*aa42cb71SShaveta Leekha {
40*aa42cb71SShaveta Leekha 	u8 data;
41*aa42cb71SShaveta Leekha 
42*aa42cb71SShaveta Leekha 	debug("VSC:Configuring VSC at I2C address 0x%2x"
43*aa42cb71SShaveta Leekha 			" for 2-wire interface\n", vsc_addr);
44*aa42cb71SShaveta Leekha 
45*aa42cb71SShaveta Leekha 	/* enable 2-wire Serial InterFace (I2C) */
46*aa42cb71SShaveta Leekha 	data = 0x02;
47*aa42cb71SShaveta Leekha 	return i2c_write(vsc_addr, INTERFACE_MODE_REG, 1, &data, 1);
48*aa42cb71SShaveta Leekha }
49*aa42cb71SShaveta Leekha 
50*aa42cb71SShaveta Leekha int vsc3316_config(unsigned int vsc_addr, const int8_t con_arr[][2],
51*aa42cb71SShaveta Leekha 		unsigned int num_con)
52*aa42cb71SShaveta Leekha {
53*aa42cb71SShaveta Leekha 	unsigned int i;
54*aa42cb71SShaveta Leekha 	u8 rev_id = 0;
55*aa42cb71SShaveta Leekha 	int ret;
56*aa42cb71SShaveta Leekha 
57*aa42cb71SShaveta Leekha 	debug("VSC:Initializing VSC3316 at I2C address 0x%2x"
58*aa42cb71SShaveta Leekha 		" for Tx\n", vsc_addr);
59*aa42cb71SShaveta Leekha 
60*aa42cb71SShaveta Leekha 	ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
61*aa42cb71SShaveta Leekha 	if (ret < 0) {
62*aa42cb71SShaveta Leekha 		printf("VSC:0x%x could not read REV_ID from device.\n",
63*aa42cb71SShaveta Leekha 			vsc_addr);
64*aa42cb71SShaveta Leekha 		return ret;
65*aa42cb71SShaveta Leekha 	}
66*aa42cb71SShaveta Leekha 
67*aa42cb71SShaveta Leekha 	if (rev_id != 0xab) {
68*aa42cb71SShaveta Leekha 		printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
69*aa42cb71SShaveta Leekha 			vsc_addr);
70*aa42cb71SShaveta Leekha 		return -ENODEV;
71*aa42cb71SShaveta Leekha 	}
72*aa42cb71SShaveta Leekha 
73*aa42cb71SShaveta Leekha 	ret = vsc_if_enable(vsc_addr);
74*aa42cb71SShaveta Leekha 	if (ret) {
75*aa42cb71SShaveta Leekha 		printf("VSC:0x%x could not configured for 2-wire I/F.\n",
76*aa42cb71SShaveta Leekha 			vsc_addr);
77*aa42cb71SShaveta Leekha 		return ret;
78*aa42cb71SShaveta Leekha 	}
79*aa42cb71SShaveta Leekha 
80*aa42cb71SShaveta Leekha 	/* config connections - page 0x00 */
81*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
82*aa42cb71SShaveta Leekha 
83*aa42cb71SShaveta Leekha 	/* Making crosspoint connections, by connecting required
84*aa42cb71SShaveta Leekha 	 * input to output */
85*aa42cb71SShaveta Leekha 	for (i = 0; i < num_con ; i++)
86*aa42cb71SShaveta Leekha 		i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
87*aa42cb71SShaveta Leekha 
88*aa42cb71SShaveta Leekha 	/* input state - page 0x13 */
89*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
90*aa42cb71SShaveta Leekha 	/* Configuring the required input of the switch */
91*aa42cb71SShaveta Leekha 	for (i = 0; i < num_con ; i++)
92*aa42cb71SShaveta Leekha 		i2c_reg_write(vsc_addr, con_arr[i][0], 0x80);
93*aa42cb71SShaveta Leekha 
94*aa42cb71SShaveta Leekha 	/* Setting Global Input LOS threshold value */
95*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
96*aa42cb71SShaveta Leekha 
97*aa42cb71SShaveta Leekha 	/* config output mode - page 0x23 */
98*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
99*aa42cb71SShaveta Leekha 	/* Turn ON the Output driver correspond to required output*/
100*aa42cb71SShaveta Leekha 	for (i = 0; i < num_con ; i++)
101*aa42cb71SShaveta Leekha 		i2c_reg_write(vsc_addr,  con_arr[i][1], 0);
102*aa42cb71SShaveta Leekha 
103*aa42cb71SShaveta Leekha 	/* configure global core control register, Turn on Global core power */
104*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
105*aa42cb71SShaveta Leekha 
106*aa42cb71SShaveta Leekha 	vsc_wp_config(vsc_addr);
107*aa42cb71SShaveta Leekha 
108*aa42cb71SShaveta Leekha 	return 0;
109*aa42cb71SShaveta Leekha }
110*aa42cb71SShaveta Leekha 
111*aa42cb71SShaveta Leekha int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2],
112*aa42cb71SShaveta Leekha 		unsigned int num_con)
113*aa42cb71SShaveta Leekha {
114*aa42cb71SShaveta Leekha 	unsigned int i;
115*aa42cb71SShaveta Leekha 	u8 rev_id = 0;
116*aa42cb71SShaveta Leekha 	int ret;
117*aa42cb71SShaveta Leekha 
118*aa42cb71SShaveta Leekha 	debug("VSC:Initializing VSC3308 at I2C address 0x%x"
119*aa42cb71SShaveta Leekha 		" for Tx\n", vsc_addr);
120*aa42cb71SShaveta Leekha 
121*aa42cb71SShaveta Leekha 	ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
122*aa42cb71SShaveta Leekha 	if (ret < 0) {
123*aa42cb71SShaveta Leekha 		printf("VSC:0x%x could not read REV_ID from device.\n",
124*aa42cb71SShaveta Leekha 			vsc_addr);
125*aa42cb71SShaveta Leekha 		return ret;
126*aa42cb71SShaveta Leekha 	}
127*aa42cb71SShaveta Leekha 
128*aa42cb71SShaveta Leekha 	if (rev_id != 0xab) {
129*aa42cb71SShaveta Leekha 		printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
130*aa42cb71SShaveta Leekha 			vsc_addr);
131*aa42cb71SShaveta Leekha 		return -ENODEV;
132*aa42cb71SShaveta Leekha 	}
133*aa42cb71SShaveta Leekha 
134*aa42cb71SShaveta Leekha 	ret = vsc_if_enable(vsc_addr);
135*aa42cb71SShaveta Leekha 	if (ret) {
136*aa42cb71SShaveta Leekha 		printf("VSC:0x%x could not configured for 2-wire I/F.\n",
137*aa42cb71SShaveta Leekha 			vsc_addr);
138*aa42cb71SShaveta Leekha 		return ret;
139*aa42cb71SShaveta Leekha 	}
140*aa42cb71SShaveta Leekha 
141*aa42cb71SShaveta Leekha 	/* config connections - page 0x00 */
142*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
143*aa42cb71SShaveta Leekha 
144*aa42cb71SShaveta Leekha 	/* Making crosspoint connections, by connecting required
145*aa42cb71SShaveta Leekha 	 * input to output */
146*aa42cb71SShaveta Leekha 	for (i = 0; i < num_con ; i++)
147*aa42cb71SShaveta Leekha 		i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
148*aa42cb71SShaveta Leekha 
149*aa42cb71SShaveta Leekha 	/*Configure Global Input ISE and gain */
150*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0x12);
151*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0x12);
152*aa42cb71SShaveta Leekha 
153*aa42cb71SShaveta Leekha 	/* input state - page 0x13 */
154*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
155*aa42cb71SShaveta Leekha 	/* Turning ON the required input of the switch */
156*aa42cb71SShaveta Leekha 	for (i = 0; i < num_con ; i++)
157*aa42cb71SShaveta Leekha 		i2c_reg_write(vsc_addr, con_arr[i][0], 0);
158*aa42cb71SShaveta Leekha 
159*aa42cb71SShaveta Leekha 	/* Setting Global Input LOS threshold value */
160*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
161*aa42cb71SShaveta Leekha 
162*aa42cb71SShaveta Leekha 	/* config output mode - page 0x23 */
163*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
164*aa42cb71SShaveta Leekha 	/* Turn ON the Output driver correspond to required output*/
165*aa42cb71SShaveta Leekha 	for (i = 0; i < num_con ; i++)
166*aa42cb71SShaveta Leekha 		i2c_reg_write(vsc_addr,  con_arr[i][1], 0);
167*aa42cb71SShaveta Leekha 
168*aa42cb71SShaveta Leekha 	/* configure global core control register, Turn on Global core power */
169*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
170*aa42cb71SShaveta Leekha 
171*aa42cb71SShaveta Leekha 	vsc_wp_config(vsc_addr);
172*aa42cb71SShaveta Leekha 
173*aa42cb71SShaveta Leekha 	return 0;
174*aa42cb71SShaveta Leekha }
175*aa42cb71SShaveta Leekha 
176*aa42cb71SShaveta Leekha void vsc_wp_config(unsigned int vsc_addr)
177*aa42cb71SShaveta Leekha {
178*aa42cb71SShaveta Leekha 	debug("VSC:Configuring VSC at address:0x%x for WP\n", vsc_addr);
179*aa42cb71SShaveta Leekha 
180*aa42cb71SShaveta Leekha 	/* For new crosspoint configuration to occur, WP bit of
181*aa42cb71SShaveta Leekha 	 * CORE_CONFIG_REG should be set 1 and then reset to 0 */
182*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x01);
183*aa42cb71SShaveta Leekha 	i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x0);
184*aa42cb71SShaveta Leekha }
185