/*
 * Copyright (c) 2021 Thomas Stranger
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/drivers/eeprom.h>
#include <zephyr/device.h>
#include <zephyr/drivers/i2c.h>

/* I2C Mux - nxp,pca9548 */
#define MUX_SLAVE_ADDR	    0x74U
#define EEPROM_CHANNEL_NO   0x01U

#define EEPROM_SAMPLE_OFFSET 0
#define EEPROM_SAMPLE_MAGIC  0xEE9703

struct perisistant_values {
	uint32_t magic;
	uint32_t boot_count;
};

/*
 * Get a device structure from a devicetree node with alias eeprom-0
 */
static const struct device *get_eeprom_device(void)
{
	const struct i2c_dt_spec i2c = I2C_DT_SPEC_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(vnd_i2c_mux));
	const struct device *const dev = DEVICE_DT_GET(DT_ALIAS(eeprom_0));
	int32_t ret;
	uint8_t datas[3];

	datas[0] = EEPROM_CHANNEL_NO;
	ret = i2c_write(i2c.bus, datas, 1, MUX_SLAVE_ADDR);
	if(ret != 0) {
		printk("Failed to select mux channel connected to pca9548\n");
		return NULL;
	}

	if (!device_is_ready(dev)) {
		printk("\nError: Device \"%s\" is not ready; "
		       "check the driver initialization logs for errors.\n",
		       dev->name);
		return NULL;
	}

	printk("Found EEPROM device \"%s\"\n", dev->name);
	return dev;
}

int main(void)
{
	const struct device *eeprom = get_eeprom_device();
	size_t eeprom_size;
	struct perisistant_values values;
	int rc;

	if (eeprom == NULL) {
		return 0;
	}

	eeprom_size = eeprom_get_size(eeprom);
	printk("Using eeprom with size of: %zu.\n", eeprom_size);

	rc = eeprom_read(eeprom, EEPROM_SAMPLE_OFFSET, &values, sizeof(values));
	if (rc < 0) {
		printk("Error: Couldn't read eeprom: err: %d.\n", rc);
		return 0;
	}

	if (values.magic != EEPROM_SAMPLE_MAGIC) {
		values.magic = EEPROM_SAMPLE_MAGIC;
		values.boot_count = 0;
	}

	values.boot_count++;
	printk("Device booted %d times.\n", values.boot_count);

	rc = eeprom_write(eeprom, EEPROM_SAMPLE_OFFSET, &values, sizeof(values));
	if (rc < 0) {
		printk("Error: Couldn't write eeprom: err:%d.\n", rc);
		return 0;
	}

	printk("Reset the MCU to see the increasing boot counter.\n\n");
	return 0;
}
