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