]>
Commit | Line | Data |
---|---|---|
aa42cb71 SL |
1 | /* |
2 | * Copyright 2012 Freescale Semiconductor, Inc. | |
3 | * | |
1a459660 | 4 | * SPDX-License-Identifier: GPL-2.0+ |
aa42cb71 SL |
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, const 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 | } |