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