// SPDX-License-Identifier: GPL-2.0
/*
 * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
 * flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization
 * see flexcop.c for copyright information
 */
#include "flexcop.h"

#define FC_MAX_I2C_RETRIES 100000

static int flexcop_i2c_operation(struct flexcop_device *fc,
		flexcop_ibi_value *r100)
{
	int i;
	flexcop_ibi_value r;

	r100->tw_sm_c_100.working_start = 1;
	deb_i2c("r100 before: %08x\n",r100->raw);

	fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero);
	fc->write_ibi_reg(fc, tw_sm_c_100, *r100); /* initiating i2c operation */

	for (i = 0; i < FC_MAX_I2C_RETRIES; i++) {
		r = fc->read_ibi_reg(fc, tw_sm_c_100);

		if (!r.tw_sm_c_100.no_base_addr_ack_error) {
			if (r.tw_sm_c_100.st_done) {
				*r100 = r;
				deb_i2c("i2c success\n");
				return 0;
			}
		} else {
			deb_i2c("suffering from an i2c ack_error\n");
			return -EREMOTEIO;
		}
	}
	deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",
		i);
	return -EREMOTEIO;
}

static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
		flexcop_ibi_value r100, u8 *buf)
{
	flexcop_ibi_value r104;
	int len = r100.tw_sm_c_100.total_bytes,
		/* remember total_bytes is buflen-1 */
		ret;

	/* work-around to have CableStar2 and SkyStar2 rev 2.7 work
	 * correctly:
	 *
	 * the ITD1000 is behind an i2c-gate which closes automatically
	 * after an i2c-transaction the STV0297 needs 2 consecutive reads
	 * one with no_base_addr = 0 and one with 1
	 *
	 * those two work-arounds are conflictin: we check for the card
	 * type, it is set when probing the ITD1000 */
	if (i2c->fc->dev_type == FC_SKY_REV27)
		r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;

	ret = flexcop_i2c_operation(i2c->fc, &r100);
	if (ret != 0) {
		deb_i2c("Retrying operation\n");
		r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
		ret = flexcop_i2c_operation(i2c->fc, &r100);
	}
	if (ret != 0) {
		deb_i2c("read failed. %d\n", ret);
		return ret;
	}

	buf[0] = r100.tw_sm_c_100.data1_reg;

	if (len > 0) {
		r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104);
		deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw);

		/* there is at least one more byte, otherwise we wouldn't be here */
		buf[1] = r104.tw_sm_c_104.data2_reg;
		if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg;
		if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg;
	}
	return 0;
}

static int flexcop_i2c_write4(struct flexcop_device *fc,
		flexcop_ibi_value r100, u8 *buf)
{
	flexcop_ibi_value r104;
	int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */
	r104.raw = 0;

	/* there is at least one byte, otherwise we wouldn't be here */
	r100.tw_sm_c_100.data1_reg = buf[0];
	r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0;
	r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
	r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;

	deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw);

	/* write the additional i2c data before doing the actual i2c operation */
	fc->write_ibi_reg(fc, tw_sm_c_104, r104);
	return flexcop_i2c_operation(fc, &r100);
}

int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
			flexcop_access_op_t op, u8 chipaddr,
			u8 start_addr, u8 *buf, u16 size)
{
	int ret;
	int len = size;
	u8 *p;
	u8 addr = start_addr;

	u16 bytes_to_transfer;
	flexcop_ibi_value r100;

	deb_i2c("port %d %s(%02x): register %02x, size: %d\n",
		i2c->port,
		op == FC_READ ? "rd" : "wr",
		chipaddr, start_addr, size);
	r100.raw = 0;
	r100.tw_sm_c_100.chipaddr = chipaddr;
	r100.tw_sm_c_100.twoWS_rw = op;
	r100.tw_sm_c_100.twoWS_port_reg = i2c->port;

	/* in that case addr is the only value ->
	 * we write it twice as baseaddr and val0
	 * BBTI is doing it like that for ISL6421 at least */
	if (i2c->no_base_addr && len == 0 && op == FC_WRITE) {
		buf = &start_addr;
		len = 1;
	}

	p = buf;

	while (len != 0) {
		bytes_to_transfer = len > 4 ? 4 : len;

		r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1;
		r100.tw_sm_c_100.baseaddr = addr;

		if (op == FC_READ)
			ret = flexcop_i2c_read4(i2c, r100, p);
		else
			ret = flexcop_i2c_write4(i2c->fc, r100, p);

		if (ret < 0)
			return ret;

		p  += bytes_to_transfer;
		addr += bytes_to_transfer;
		len  -= bytes_to_transfer;
	}
	deb_i2c_dump("port %d %s(%02x): register %02x: %*ph\n",
		i2c->port,
		op == FC_READ ? "rd" : "wr",
		chipaddr, start_addr, size, buf);

	return 0;
}
/* exported for PCI i2c */
EXPORT_SYMBOL(flexcop_i2c_request);

/* master xfer callback for demodulator */
static int flexcop_master_xfer(struct i2c_adapter *i2c_adap,
		struct i2c_msg msgs[], int num)
{
	struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
	int i, ret = 0;

	/* Some drivers use 1 byte or 0 byte reads as probes, which this
	 * driver doesn't support.  These probes will always fail, so this
	 * hack makes them always succeed.  If one knew how, it would of
	 * course be better to actually do the read.  */
	if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
		return 1;

	if (mutex_lock_interruptible(&i2c->fc->i2c_mutex))
		return -ERESTARTSYS;

	for (i = 0; i < num; i++) {
		/* reading */
		if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) {
			ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr,
					msgs[i].buf[0], msgs[i+1].buf,
					msgs[i+1].len);
			i++; /* skip the following message */
		} else /* writing */
			ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,
					msgs[i].buf[0], &msgs[i].buf[1],
					msgs[i].len - 1);
		if (ret < 0) {
			deb_i2c("i2c master_xfer failed");
			break;
		}
	}

	mutex_unlock(&i2c->fc->i2c_mutex);

	if (ret == 0)
		ret = num;
	return ret;
}

static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
{
	return I2C_FUNC_I2C;
}

static struct i2c_algorithm flexcop_algo = {
	.master_xfer	= flexcop_master_xfer,
	.functionality	= flexcop_i2c_func,
};

int flexcop_i2c_init(struct flexcop_device *fc)
{
	int ret;
	mutex_init(&fc->i2c_mutex);

	fc->fc_i2c_adap[0].fc = fc;
	fc->fc_i2c_adap[1].fc = fc;
	fc->fc_i2c_adap[2].fc = fc;
	fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD;
	fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
	fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;

	strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod",
			sizeof(fc->fc_i2c_adap[0].i2c_adap.name));
	strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom",
			sizeof(fc->fc_i2c_adap[1].i2c_adap.name));
	strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner",
			sizeof(fc->fc_i2c_adap[2].i2c_adap.name));

	i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);
	i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
	i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);

	fc->fc_i2c_adap[0].i2c_adap.algo =
		fc->fc_i2c_adap[1].i2c_adap.algo =
		fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;
	fc->fc_i2c_adap[0].i2c_adap.algo_data =
		fc->fc_i2c_adap[1].i2c_adap.algo_data =
		fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL;
	fc->fc_i2c_adap[0].i2c_adap.dev.parent =
		fc->fc_i2c_adap[1].i2c_adap.dev.parent =
		fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev;

	ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap);
	if (ret < 0)
		return ret;

	ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap);
	if (ret < 0)
		goto adap_1_failed;

	ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap);
	if (ret < 0)
		goto adap_2_failed;

	fc->init_state |= FC_STATE_I2C_INIT;
	return 0;

adap_2_failed:
	i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
adap_1_failed:
	i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
	return ret;
}

void flexcop_i2c_exit(struct flexcop_device *fc)
{
	if (fc->init_state & FC_STATE_I2C_INIT) {
		i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap);
		i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
		i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
	}
	fc->init_state &= ~FC_STATE_I2C_INIT;
}
