/* SPDX-License-Identifier: GPL-2.0-only */

#include <device/i2c_simple.h>
#include <limits.h>
#include <tests/test.h>

/* Simulate two i2c devices, both on bus 0, each with three uint8_t regs
   implemented. */
typedef struct {
	uint8_t reg;
	uint8_t data;
} i2c_ex_regs_t;

typedef struct {
	unsigned int bus;
	uint8_t slave;
	i2c_ex_regs_t regs[3];
} i2c_ex_devs_t;

i2c_ex_devs_t i2c_ex_devs[] = {
	{.bus = 0, .slave = 0xA, .regs = {
		{.reg = 0x0, .data = 0xB},
		{.reg = 0x1, .data = 0x6},
		{.reg = 0x2, .data = 0xF},
	} },
	{.bus = 0, .slave = 0x3, .regs = {
		{.reg = 0x0, .data = 0xDE},
		{.reg = 0x1, .data = 0xAD},
		{.reg = 0x2, .data = 0xBE},
	} },
};

int __wrap_platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments,
	int count)
{
	int i;
	int reg;
	struct i2c_msg *tmp = segments;
	i2c_ex_devs_t *i2c_dev = NULL;

	check_expected(count);

	for (i = 0; i < count; i++, segments++) {
		check_expected_ptr(segments->buf);
		check_expected(segments->flags);
	}

	reg = tmp->buf[0];

	/* Find object for requested device */
	for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
		if (i2c_ex_devs[i].slave == tmp->slave) {
			i2c_dev = &i2c_ex_devs[i];
			break;
		}

	if (i2c_dev == NULL)
		return -1;

	/* Write commands */
	if (tmp->len > 1) {
		i2c_dev->regs[reg].data = tmp->buf[1];
	};

	/* Read commands */
	for (i = 0; i < count; i++, tmp++)
		if (tmp->flags & I2C_M_RD) {
			*(tmp->buf) = i2c_dev->regs[reg].data;
		};

	return 0;
}

static void mock_expect_params_platform_i2c_transfer(void)
{
	unsigned long int expected_flags[] = {0, I2C_M_RD, I2C_M_TEN,
		I2C_M_RECV_LEN, I2C_M_NOSTART};

	/* Flags should always be only within supported range */
	expect_in_set_count(__wrap_platform_i2c_transfer, segments->flags,
		expected_flags, -1);

	expect_not_value_count(__wrap_platform_i2c_transfer, segments->buf,
		NULL, -1);

	expect_in_range_count(__wrap_platform_i2c_transfer, count, 1, INT_MAX,
		-1);
}

#define MASK	0x3
#define SHIFT	0x1

static void i2c_read_field_test(void **state)
{
	int i, j;
	uint8_t buf;

	mock_expect_params_platform_i2c_transfer();

	/* Read particular bits in all registers in all devices, then compare
	   with expected value. */
	for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
		for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
			i2c_read_field(i2c_ex_devs[i].bus,
				i2c_ex_devs[i].slave,
				i2c_ex_devs[i].regs[j].reg,
				&buf, MASK, SHIFT);
			assert_int_equal((i2c_ex_devs[i].regs[j].data &
				(MASK << SHIFT)) >> SHIFT, buf);
		};

	/* Read whole registers */
	for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
		for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
			i2c_read_field(i2c_ex_devs[i].bus,
				i2c_ex_devs[i].slave,
				i2c_ex_devs[i].regs[j].reg,
				&buf, 0xFF, 0);
			assert_int_equal(i2c_ex_devs[i].regs[j].data, buf);
		};
}

static void i2c_write_field_test(void **state)
{
	int i, j;
	uint8_t buf, tmp;

	mock_expect_params_platform_i2c_transfer();

	/* Clear particular bits in all registers in all devices, then compare
	   with expected value. */
	for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
		for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
			buf = 0x0;
			tmp = i2c_ex_devs[i].regs[j].data;
			i2c_write_field(i2c_ex_devs[i].bus,
				i2c_ex_devs[i].slave,
				i2c_ex_devs[i].regs[j].reg,
				buf, MASK, SHIFT);
			assert_int_equal(i2c_ex_devs[i].regs[j].data,
				(tmp & ~(MASK << SHIFT)) | (buf << SHIFT));
		};

	/* Set all bits in all registers, this time verify using
	   i2c_read_field() accessor. */
	for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
		for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
			i2c_write_field(i2c_ex_devs[i].bus,
				i2c_ex_devs[i].slave,
				i2c_ex_devs[i].regs[j].reg,
				0xFF, 0xFF, 0);
			i2c_read_field(i2c_ex_devs[i].bus,
				i2c_ex_devs[i].slave,
				i2c_ex_devs[i].regs[j].reg,
				&buf, 0xFF, 0);
			assert_int_equal(buf, 0xFF);
		};
}

int main(void)
{
	const struct CMUnitTest tests[] = {
		cmocka_unit_test(i2c_read_field_test),
		cmocka_unit_test(i2c_write_field_test)
	};

	return cmocka_run_group_tests(tests, NULL, NULL);
}
