// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2021 Google LLC
 */

#include <cros_ec.h>
#include <dm.h>
#include <asm/test.h>
#include <dm/test.h>
#include <test/ut.h>

static int dm_test_cros_ec_hello(struct unit_test_state *uts)
{
	struct udevice *dev;
	uint val;

	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));

	ut_assertok(cros_ec_hello(dev, NULL));

	val = 0xdead1357;
	ut_assertok(cros_ec_hello(dev, &val));
	ut_asserteq(0xdead1357, val);

	sandbox_cros_ec_set_test_flags(dev, CROSECT_BREAK_HELLO);
	ut_asserteq(-ENOTSYNC, cros_ec_hello(dev, &val));
	ut_asserteq(0x12345678, val);

	return 0;
}
DM_TEST(dm_test_cros_ec_hello, UTF_SCAN_FDT);

static int dm_test_cros_ec_sku_id(struct unit_test_state *uts)
{
	struct udevice *dev;

	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
	ut_asserteq(1234, cros_ec_get_sku_id(dev));

	/* try the command */
	console_record_reset();
	ut_assertok(run_command("crosec sku", 0));
	ut_assert_nextline("1234");
	ut_assert_console_end();

	return 0;
}
DM_TEST(dm_test_cros_ec_sku_id, UTF_SCAN_FDT);

static int dm_test_cros_ec_features(struct unit_test_state *uts)
{
	struct udevice *dev;
	u64 feat;

	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
	ut_assertok(cros_ec_get_features(dev, &feat));
	ut_asserteq_64(1U << EC_FEATURE_FLASH | 1U << EC_FEATURE_I2C |
		1u << EC_FEATURE_VSTORE |
		1ULL << EC_FEATURE_UNIFIED_WAKE_MASKS | 1ULL << EC_FEATURE_ISH,
		feat);

	ut_asserteq(true, cros_ec_check_feature(dev, EC_FEATURE_I2C));
	ut_asserteq(false, cros_ec_check_feature(dev, EC_FEATURE_MOTION_SENSE));
	ut_asserteq(true, cros_ec_check_feature(dev, EC_FEATURE_ISH));

	/* try the command */
	console_record_reset();
	ut_assertok(run_command("crosec features", 0));
	ut_assert_nextline("flash");
	ut_assert_nextline("i2c");
	ut_assert_nextline("vstore");
	ut_assert_nextline("unified_wake_masks");
	ut_assert_nextline("ish");
	ut_assert_console_end();

	return 0;
}
DM_TEST(dm_test_cros_ec_features, UTF_SCAN_FDT);

static int dm_test_cros_ec_switches(struct unit_test_state *uts)
{
	struct udevice *dev;

	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
	ut_asserteq(0, cros_ec_get_switches(dev));

	/* try the command */
	console_record_reset();
	ut_assertok(run_command("crosec switches", 0));
	ut_assert_console_end();

	/* Open the lid and check the switch changes */
	sandbox_cros_ec_set_test_flags(dev, CROSECT_LID_OPEN);
	ut_asserteq(EC_SWITCH_LID_OPEN, cros_ec_get_switches(dev));

	/* try the command */
	console_record_reset();
	ut_assertok(run_command("crosec switches", 0));
	ut_assert_nextline("lid open");
	ut_assert_console_end();

	return 0;
}
DM_TEST(dm_test_cros_ec_switches, UTF_SCAN_FDT);

static int dm_test_cros_ec_events(struct unit_test_state *uts)
{
	struct udevice *dev;
	u32 events;

	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
	ut_assertok(cros_ec_get_host_events(dev, &events));
	ut_asserteq(0, events);

	/* try the command */
	console_record_reset();
	ut_assertok(run_command("crosec events", 0));
	ut_assert_nextline("00000000");
	ut_assert_console_end();

	/* Open the lid and check the event appears */
	sandbox_cros_ec_set_test_flags(dev, CROSECT_LID_OPEN);
	ut_assertok(cros_ec_get_host_events(dev, &events));
	ut_asserteq(EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN), events);

	/* try the command */
	console_record_reset();
	ut_assertok(run_command("crosec events", 0));
	ut_assert_nextline("00000002");
	ut_assert_nextline("lid_open");
	ut_assert_console_end();

	/* Clear the event */
	ut_assertok(cros_ec_clear_host_events(dev,
		EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN)));
	ut_assertok(cros_ec_get_host_events(dev, &events));
	ut_asserteq(0, events);

	return 0;
}
DM_TEST(dm_test_cros_ec_events, UTF_SCAN_FDT);

static int dm_test_cros_ec_vstore(struct unit_test_state *uts)
{
	const int size = EC_VSTORE_SLOT_SIZE;
	u8 test_data[size], data[size];
	struct udevice *dev;
	u32 locked;
	int i;

	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
	ut_asserteq(true, cros_ec_vstore_supported(dev));

	ut_asserteq(4, cros_ec_vstore_info(dev, &locked));
	ut_asserteq(0, locked);

	/* Write some data */
	for (i = 0; i < size; i++)
		test_data[i] = ' ' + i;
	ut_assertok(cros_ec_vstore_write(dev, 2, test_data, size));

	/* Check it is locked */
	ut_asserteq(4, cros_ec_vstore_info(dev, &locked));
	ut_asserteq(1 << 2, locked);

	/* Read it back and compare */
	ut_assertok(cros_ec_vstore_read(dev, 2, data));
	ut_asserteq_mem(test_data, data, size);

	/* Try another slot to make sure it is empty */
	ut_assertok(cros_ec_vstore_read(dev, 0, data));
	for (i = 0; i < size; i++)
		ut_asserteq(0, data[i]);

	return 0;
}
DM_TEST(dm_test_cros_ec_vstore, UTF_SCAN_FDT);
