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 } 169