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 16*b24f6d40SShaohui Xie #define GLOBAL_INPUT_GAIN 0x53 17aa42cb71SShaveta Leekha #define GLOBAL_INPUT_LOS 0x55 18*b24f6d40SShaohui Xie #define GLOBAL_OUTPUT_PE1 0x56 19*b24f6d40SShaohui Xie #define GLOBAL_OUTPUT_PE2 0x57 20*b24f6d40SShaohui Xie #define GLOBAL_OUTPUT_LEVEL 0x58 21*b24f6d40SShaohui Xie #define GLOBAL_OUTPUT_TERMINATION 0x5A 22aa42cb71SShaveta Leekha #define GLOBAL_CORE_CNTRL 0x5D 23aa42cb71SShaveta Leekha #define OUTPUT_MODE_PAGE 0x23 24aa42cb71SShaveta Leekha #define CORE_CONTROL_PAGE 0x25 25aa42cb71SShaveta Leekha #define CORE_CONFIG_REG 0x75 26aa42cb71SShaveta Leekha 27aa42cb71SShaveta Leekha int vsc_if_enable(unsigned int vsc_addr) 28aa42cb71SShaveta Leekha { 29aa42cb71SShaveta Leekha u8 data; 30aa42cb71SShaveta Leekha 31aa42cb71SShaveta Leekha debug("VSC:Configuring VSC at I2C address 0x%2x" 32aa42cb71SShaveta Leekha " for 2-wire interface\n", vsc_addr); 33aa42cb71SShaveta Leekha 34aa42cb71SShaveta Leekha /* enable 2-wire Serial InterFace (I2C) */ 35aa42cb71SShaveta Leekha data = 0x02; 36aa42cb71SShaveta Leekha return i2c_write(vsc_addr, INTERFACE_MODE_REG, 1, &data, 1); 37aa42cb71SShaveta Leekha } 38aa42cb71SShaveta Leekha 397d0d355fSShaohui Xie int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2], 40aa42cb71SShaveta Leekha unsigned int num_con) 41aa42cb71SShaveta Leekha { 42aa42cb71SShaveta Leekha unsigned int i; 43aa42cb71SShaveta Leekha u8 rev_id = 0; 44aa42cb71SShaveta Leekha int ret; 45aa42cb71SShaveta Leekha 46aa42cb71SShaveta Leekha debug("VSC:Initializing VSC3316 at I2C address 0x%2x" 47aa42cb71SShaveta Leekha " for Tx\n", vsc_addr); 48aa42cb71SShaveta Leekha 49aa42cb71SShaveta Leekha ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1); 50aa42cb71SShaveta Leekha if (ret < 0) { 51aa42cb71SShaveta Leekha printf("VSC:0x%x could not read REV_ID from device.\n", 52aa42cb71SShaveta Leekha vsc_addr); 53aa42cb71SShaveta Leekha return ret; 54aa42cb71SShaveta Leekha } 55aa42cb71SShaveta Leekha 56aa42cb71SShaveta Leekha if (rev_id != 0xab) { 57aa42cb71SShaveta Leekha printf("VSC: device at address 0x%x is not VSC3316/3308.\n", 58aa42cb71SShaveta Leekha vsc_addr); 59aa42cb71SShaveta Leekha return -ENODEV; 60aa42cb71SShaveta Leekha } 61aa42cb71SShaveta Leekha 62aa42cb71SShaveta Leekha ret = vsc_if_enable(vsc_addr); 63aa42cb71SShaveta Leekha if (ret) { 64aa42cb71SShaveta Leekha printf("VSC:0x%x could not configured for 2-wire I/F.\n", 65aa42cb71SShaveta Leekha vsc_addr); 66aa42cb71SShaveta Leekha return ret; 67aa42cb71SShaveta Leekha } 68aa42cb71SShaveta Leekha 69aa42cb71SShaveta Leekha /* config connections - page 0x00 */ 70aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE); 71aa42cb71SShaveta Leekha 72aa42cb71SShaveta Leekha /* Making crosspoint connections, by connecting required 73aa42cb71SShaveta Leekha * input to output */ 74aa42cb71SShaveta Leekha for (i = 0; i < num_con ; i++) 75aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]); 76aa42cb71SShaveta Leekha 77aa42cb71SShaveta Leekha /* input state - page 0x13 */ 78aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG); 79aa42cb71SShaveta Leekha /* Configuring the required input of the switch */ 80aa42cb71SShaveta Leekha for (i = 0; i < num_con ; i++) 81aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, con_arr[i][0], 0x80); 82aa42cb71SShaveta Leekha 83aa42cb71SShaveta Leekha /* Setting Global Input LOS threshold value */ 84aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60); 85aa42cb71SShaveta Leekha 86aa42cb71SShaveta Leekha /* config output mode - page 0x23 */ 87aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE); 88aa42cb71SShaveta Leekha /* Turn ON the Output driver correspond to required output*/ 89aa42cb71SShaveta Leekha for (i = 0; i < num_con ; i++) 90aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, con_arr[i][1], 0); 91aa42cb71SShaveta Leekha 92aa42cb71SShaveta Leekha /* configure global core control register, Turn on Global core power */ 93aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0); 94aa42cb71SShaveta Leekha 95aa42cb71SShaveta Leekha vsc_wp_config(vsc_addr); 96aa42cb71SShaveta Leekha 97aa42cb71SShaveta Leekha return 0; 98aa42cb71SShaveta Leekha } 99aa42cb71SShaveta Leekha 100*b24f6d40SShaohui Xie #ifdef CONFIG_SYS_FSL_B4860QDS_XFI_ERR 101*b24f6d40SShaohui Xie int vsc3308_config_adjust(unsigned int vsc_addr, const int8_t con_arr[][2], 102*b24f6d40SShaohui Xie unsigned int num_con) 103*b24f6d40SShaohui Xie { 104*b24f6d40SShaohui Xie unsigned int i; 105*b24f6d40SShaohui Xie u8 rev_id = 0; 106*b24f6d40SShaohui Xie int ret; 107*b24f6d40SShaohui Xie 108*b24f6d40SShaohui Xie debug("VSC:Initializing VSC3308 at I2C address 0x%x for Tx\n", 109*b24f6d40SShaohui Xie vsc_addr); 110*b24f6d40SShaohui Xie 111*b24f6d40SShaohui Xie ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1); 112*b24f6d40SShaohui Xie if (ret < 0) { 113*b24f6d40SShaohui Xie printf("VSC:0x%x could not read REV_ID from device.\n", 114*b24f6d40SShaohui Xie vsc_addr); 115*b24f6d40SShaohui Xie return ret; 116*b24f6d40SShaohui Xie } 117*b24f6d40SShaohui Xie 118*b24f6d40SShaohui Xie if (rev_id != 0xab) { 119*b24f6d40SShaohui Xie printf("VSC: device at address 0x%x is not VSC3316/3308.\n", 120*b24f6d40SShaohui Xie vsc_addr); 121*b24f6d40SShaohui Xie return -ENODEV; 122*b24f6d40SShaohui Xie } 123*b24f6d40SShaohui Xie 124*b24f6d40SShaohui Xie ret = vsc_if_enable(vsc_addr); 125*b24f6d40SShaohui Xie if (ret) { 126*b24f6d40SShaohui Xie printf("VSC:0x%x could not configured for 2-wire I/F.\n", 127*b24f6d40SShaohui Xie vsc_addr); 128*b24f6d40SShaohui Xie return ret; 129*b24f6d40SShaohui Xie } 130*b24f6d40SShaohui Xie 131*b24f6d40SShaohui Xie /* config connections - page 0x00 */ 132*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE); 133*b24f6d40SShaohui Xie 134*b24f6d40SShaohui Xie /* Configure Global Input ISE */ 135*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0); 136*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0); 137*b24f6d40SShaohui Xie 138*b24f6d40SShaohui Xie /* Configure Tx/Rx Global Output PE1 */ 139*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE1, 0); 140*b24f6d40SShaohui Xie 141*b24f6d40SShaohui Xie /* Configure Tx/Rx Global Output PE2 */ 142*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE2, 0); 143*b24f6d40SShaohui Xie 144*b24f6d40SShaohui Xie /* Configure Tx/Rx Global Input GAIN */ 145*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, GLOBAL_INPUT_GAIN, 0x3F); 146*b24f6d40SShaohui Xie 147*b24f6d40SShaohui Xie /* Setting Global Input LOS threshold value */ 148*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0xE0); 149*b24f6d40SShaohui Xie 150*b24f6d40SShaohui Xie /* Setting Global output termination */ 151*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_TERMINATION, 0); 152*b24f6d40SShaohui Xie 153*b24f6d40SShaohui Xie /* Configure Tx/Rx Global Output level */ 154*b24f6d40SShaohui Xie if (vsc_addr == VSC3308_TX_ADDRESS) 155*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 4); 156*b24f6d40SShaohui Xie else 157*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 2); 158*b24f6d40SShaohui Xie 159*b24f6d40SShaohui Xie /* Making crosspoint connections, by connecting required 160*b24f6d40SShaohui Xie * input to output */ 161*b24f6d40SShaohui Xie for (i = 0; i < num_con ; i++) 162*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]); 163*b24f6d40SShaohui Xie 164*b24f6d40SShaohui Xie /* input state - page 0x13 */ 165*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG); 166*b24f6d40SShaohui Xie /* Turning off all the required input of the switch */ 167*b24f6d40SShaohui Xie for (i = 0; i < num_con; i++) 168*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, con_arr[i][0], 1); 169*b24f6d40SShaohui Xie 170*b24f6d40SShaohui Xie /* only turn on specific Tx/Rx requested by the XFI erratum */ 171*b24f6d40SShaohui Xie if (vsc_addr == VSC3308_TX_ADDRESS) { 172*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, 2, 0); 173*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, 3, 0); 174*b24f6d40SShaohui Xie } else { 175*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, 0, 0); 176*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, 1, 0); 177*b24f6d40SShaohui Xie } 178*b24f6d40SShaohui Xie 179*b24f6d40SShaohui Xie /* config output mode - page 0x23 */ 180*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE); 181*b24f6d40SShaohui Xie /* Turn off the Output driver correspond to required output*/ 182*b24f6d40SShaohui Xie for (i = 0; i < num_con ; i++) 183*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, con_arr[i][1], 1); 184*b24f6d40SShaohui Xie 185*b24f6d40SShaohui Xie /* only turn on specific Tx/Rx requested by the XFI erratum */ 186*b24f6d40SShaohui Xie if (vsc_addr == VSC3308_TX_ADDRESS) { 187*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, 0, 0); 188*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, 1, 0); 189*b24f6d40SShaohui Xie } else { 190*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, 3, 0); 191*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, 4, 0); 192*b24f6d40SShaohui Xie } 193*b24f6d40SShaohui Xie 194*b24f6d40SShaohui Xie /* configure global core control register, Turn on Global core power */ 195*b24f6d40SShaohui Xie i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0); 196*b24f6d40SShaohui Xie 197*b24f6d40SShaohui Xie vsc_wp_config(vsc_addr); 198*b24f6d40SShaohui Xie 199*b24f6d40SShaohui Xie return 0; 200*b24f6d40SShaohui Xie } 201*b24f6d40SShaohui Xie #endif 202*b24f6d40SShaohui Xie 203aa42cb71SShaveta Leekha int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2], 204aa42cb71SShaveta Leekha unsigned int num_con) 205aa42cb71SShaveta Leekha { 206aa42cb71SShaveta Leekha unsigned int i; 207aa42cb71SShaveta Leekha u8 rev_id = 0; 208aa42cb71SShaveta Leekha int ret; 209aa42cb71SShaveta Leekha 210aa42cb71SShaveta Leekha debug("VSC:Initializing VSC3308 at I2C address 0x%x" 211aa42cb71SShaveta Leekha " for Tx\n", vsc_addr); 212aa42cb71SShaveta Leekha 213aa42cb71SShaveta Leekha ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1); 214aa42cb71SShaveta Leekha if (ret < 0) { 215aa42cb71SShaveta Leekha printf("VSC:0x%x could not read REV_ID from device.\n", 216aa42cb71SShaveta Leekha vsc_addr); 217aa42cb71SShaveta Leekha return ret; 218aa42cb71SShaveta Leekha } 219aa42cb71SShaveta Leekha 220aa42cb71SShaveta Leekha if (rev_id != 0xab) { 221aa42cb71SShaveta Leekha printf("VSC: device at address 0x%x is not VSC3316/3308.\n", 222aa42cb71SShaveta Leekha vsc_addr); 223aa42cb71SShaveta Leekha return -ENODEV; 224aa42cb71SShaveta Leekha } 225aa42cb71SShaveta Leekha 226aa42cb71SShaveta Leekha ret = vsc_if_enable(vsc_addr); 227aa42cb71SShaveta Leekha if (ret) { 228aa42cb71SShaveta Leekha printf("VSC:0x%x could not configured for 2-wire I/F.\n", 229aa42cb71SShaveta Leekha vsc_addr); 230aa42cb71SShaveta Leekha return ret; 231aa42cb71SShaveta Leekha } 232aa42cb71SShaveta Leekha 233aa42cb71SShaveta Leekha /* config connections - page 0x00 */ 234aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE); 235aa42cb71SShaveta Leekha 236aa42cb71SShaveta Leekha /* Making crosspoint connections, by connecting required 237aa42cb71SShaveta Leekha * input to output */ 238aa42cb71SShaveta Leekha for (i = 0; i < num_con ; i++) 239aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]); 240aa42cb71SShaveta Leekha 241aa42cb71SShaveta Leekha /*Configure Global Input ISE and gain */ 242aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0x12); 243aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0x12); 244aa42cb71SShaveta Leekha 245aa42cb71SShaveta Leekha /* input state - page 0x13 */ 246aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG); 247aa42cb71SShaveta Leekha /* Turning ON the required input of the switch */ 248aa42cb71SShaveta Leekha for (i = 0; i < num_con ; i++) 249aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, con_arr[i][0], 0); 250aa42cb71SShaveta Leekha 251aa42cb71SShaveta Leekha /* Setting Global Input LOS threshold value */ 252aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60); 253aa42cb71SShaveta Leekha 254aa42cb71SShaveta Leekha /* config output mode - page 0x23 */ 255aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE); 256aa42cb71SShaveta Leekha /* Turn ON the Output driver correspond to required output*/ 257aa42cb71SShaveta Leekha for (i = 0; i < num_con ; i++) 258aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, con_arr[i][1], 0); 259aa42cb71SShaveta Leekha 260aa42cb71SShaveta Leekha /* configure global core control register, Turn on Global core power */ 261aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0); 262aa42cb71SShaveta Leekha 263aa42cb71SShaveta Leekha vsc_wp_config(vsc_addr); 264aa42cb71SShaveta Leekha 265aa42cb71SShaveta Leekha return 0; 266aa42cb71SShaveta Leekha } 267aa42cb71SShaveta Leekha 268aa42cb71SShaveta Leekha void vsc_wp_config(unsigned int vsc_addr) 269aa42cb71SShaveta Leekha { 270aa42cb71SShaveta Leekha debug("VSC:Configuring VSC at address:0x%x for WP\n", vsc_addr); 271aa42cb71SShaveta Leekha 272aa42cb71SShaveta Leekha /* For new crosspoint configuration to occur, WP bit of 273aa42cb71SShaveta Leekha * CORE_CONFIG_REG should be set 1 and then reset to 0 */ 274aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x01); 275aa42cb71SShaveta Leekha i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x0); 276aa42cb71SShaveta Leekha } 277