/*
 * Copyright 2012 Freescale Semiconductor, Inc.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include "vsc3316_3308.h"

#define REVISION_ID_REG		0x7E
#define INTERFACE_MODE_REG		0x79
#define CURRENT_PAGE_REGISTER		0x7F
#define CONNECTION_CONFIG_PAGE		0x00
#define INPUT_STATE_REG		0x13
#define GLOBAL_INPUT_ISE1		0x51
#define GLOBAL_INPUT_ISE2		0x52
#define GLOBAL_INPUT_GAIN		0x53
#define GLOBAL_INPUT_LOS		0x55
#define GLOBAL_OUTPUT_PE1		0x56
#define GLOBAL_OUTPUT_PE2		0x57
#define GLOBAL_OUTPUT_LEVEL		0x58
#define GLOBAL_OUTPUT_TERMINATION	0x5A
#define GLOBAL_CORE_CNTRL		0x5D
#define OUTPUT_MODE_PAGE		0x23
#define CORE_CONTROL_PAGE		0x25
#define CORE_CONFIG_REG		0x75

int vsc_if_enable(unsigned int vsc_addr)
{
	u8 data;

	debug("VSC:Configuring VSC at I2C address 0x%2x"
			" for 2-wire interface\n", vsc_addr);

	/* enable 2-wire Serial InterFace (I2C) */
	data = 0x02;
	return i2c_write(vsc_addr, INTERFACE_MODE_REG, 1, &data, 1);
}

int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2],
		unsigned int num_con)
{
	unsigned int i;
	u8 rev_id = 0;
	int ret;

	debug("VSC:Initializing VSC3316 at I2C address 0x%2x"
		" for Tx\n", vsc_addr);

	ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
	if (ret < 0) {
		printf("VSC:0x%x could not read REV_ID from device.\n",
			vsc_addr);
		return ret;
	}

	if (rev_id != 0xab) {
		printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
			vsc_addr);
		return -ENODEV;
	}

	ret = vsc_if_enable(vsc_addr);
	if (ret) {
		printf("VSC:0x%x could not configured for 2-wire I/F.\n",
			vsc_addr);
		return ret;
	}

	/* config connections - page 0x00 */
	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);

	/* Making crosspoint connections, by connecting required
	 * input to output */
	for (i = 0; i < num_con ; i++)
		i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);

	/* input state - page 0x13 */
	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
	/* Configuring the required input of the switch */
	for (i = 0; i < num_con ; i++)
		i2c_reg_write(vsc_addr, con_arr[i][0], 0x80);

	/* Setting Global Input LOS threshold value */
	i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);

	/* config output mode - page 0x23 */
	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
	/* Turn ON the Output driver correspond to required output*/
	for (i = 0; i < num_con ; i++)
		i2c_reg_write(vsc_addr,  con_arr[i][1], 0);

	/* configure global core control register, Turn on Global core power */
	i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);

	vsc_wp_config(vsc_addr);

	return 0;
}

#ifdef CONFIG_SYS_FSL_B4860QDS_XFI_ERR
int vsc3308_config_adjust(unsigned int vsc_addr, const int8_t con_arr[][2],
		unsigned int num_con)
{
	unsigned int i;
	u8 rev_id = 0;
	int ret;

	debug("VSC:Initializing VSC3308 at I2C address 0x%x for Tx\n",
	      vsc_addr);

	ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
	if (ret < 0) {
		printf("VSC:0x%x could not read REV_ID from device.\n",
		       vsc_addr);
		return ret;
	}

	if (rev_id != 0xab) {
		printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
		       vsc_addr);
		return -ENODEV;
	}

	ret = vsc_if_enable(vsc_addr);
	if (ret) {
		printf("VSC:0x%x could not configured for 2-wire I/F.\n",
		       vsc_addr);
		return ret;
	}

	/* config connections - page 0x00 */
	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);

	/* Configure Global Input ISE */
	i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0);
	i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0);

	/* Configure Tx/Rx Global Output PE1 */
	i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE1, 0);

	/* Configure Tx/Rx Global Output PE2 */
	i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE2, 0);

	/* Configure Tx/Rx Global Input GAIN */
	i2c_reg_write(vsc_addr, GLOBAL_INPUT_GAIN, 0x3F);

	/* Setting Global Input LOS threshold value */
	i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0xE0);

	/* Setting Global output termination */
	i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_TERMINATION, 0);

	/* Configure Tx/Rx Global Output level */
	if (vsc_addr == VSC3308_TX_ADDRESS)
		i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 4);
	else
		i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 2);

	/* Making crosspoint connections, by connecting required
	 * input to output */
	for (i = 0; i < num_con ; i++)
		i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);

	/* input state - page 0x13 */
	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
	/* Turning off all the required input of the switch */
	for (i = 0; i < num_con; i++)
		i2c_reg_write(vsc_addr, con_arr[i][0], 1);

	/* only turn on specific Tx/Rx requested by the XFI erratum */
	if (vsc_addr == VSC3308_TX_ADDRESS) {
		i2c_reg_write(vsc_addr, 2, 0);
		i2c_reg_write(vsc_addr, 3, 0);
	} else {
		i2c_reg_write(vsc_addr, 0, 0);
		i2c_reg_write(vsc_addr, 1, 0);
	}

	/* config output mode - page 0x23 */
	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
	/* Turn off the Output driver correspond to required output*/
	for (i = 0; i < num_con ; i++)
		i2c_reg_write(vsc_addr,  con_arr[i][1], 1);

	/* only turn on specific Tx/Rx requested by the XFI erratum */
	if (vsc_addr == VSC3308_TX_ADDRESS) {
		i2c_reg_write(vsc_addr, 0, 0);
		i2c_reg_write(vsc_addr, 1, 0);
	} else {
		i2c_reg_write(vsc_addr, 3, 0);
		i2c_reg_write(vsc_addr, 4, 0);
	}

	/* configure global core control register, Turn on Global core power */
	i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);

	vsc_wp_config(vsc_addr);

	return 0;
}
#endif

int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2],
		unsigned int num_con)
{
	unsigned int i;
	u8 rev_id = 0;
	int ret;

	debug("VSC:Initializing VSC3308 at I2C address 0x%x"
		" for Tx\n", vsc_addr);

	ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
	if (ret < 0) {
		printf("VSC:0x%x could not read REV_ID from device.\n",
			vsc_addr);
		return ret;
	}

	if (rev_id != 0xab) {
		printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
			vsc_addr);
		return -ENODEV;
	}

	ret = vsc_if_enable(vsc_addr);
	if (ret) {
		printf("VSC:0x%x could not configured for 2-wire I/F.\n",
			vsc_addr);
		return ret;
	}

	/* config connections - page 0x00 */
	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);

	/* Making crosspoint connections, by connecting required
	 * input to output */
	for (i = 0; i < num_con ; i++)
		i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);

	/*Configure Global Input ISE and gain */
	i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0x12);
	i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0x12);

	/* input state - page 0x13 */
	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
	/* Turning ON the required input of the switch */
	for (i = 0; i < num_con ; i++)
		i2c_reg_write(vsc_addr, con_arr[i][0], 0);

	/* Setting Global Input LOS threshold value */
	i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);

	/* config output mode - page 0x23 */
	i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
	/* Turn ON the Output driver correspond to required output*/
	for (i = 0; i < num_con ; i++)
		i2c_reg_write(vsc_addr,  con_arr[i][1], 0);

	/* configure global core control register, Turn on Global core power */
	i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);

	vsc_wp_config(vsc_addr);

	return 0;
}

void vsc_wp_config(unsigned int vsc_addr)
{
	debug("VSC:Configuring VSC at address:0x%x for WP\n", vsc_addr);

	/* For new crosspoint configuration to occur, WP bit of
	 * CORE_CONFIG_REG should be set 1 and then reset to 0 */
	i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x01);
	i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x0);
}
