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