/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <errno.h>
#include <zephyr.h>
#include <sys/printk.h>
#include <device.h>
#include <drivers/spi.h>

/**
 * @file Sample app using the Fujitsu MB85RS64V FRAM through SPI.
 */

#define MB85RS64V_MANUFACTURER_ID_CMD 0x9f
#define MB85RS64V_WRITE_ENABLE_CMD 0x06
#define MB85RS64V_READ_CMD 0x03
#define MB85RS64V_WRITE_CMD 0x02
#define MAX_USER_DATA_LENGTH 1024

static uint8_t data[MAX_USER_DATA_LENGTH], cmp_data[MAX_USER_DATA_LENGTH];

static int mb85rs64v_access(const struct device *spi,
			    struct spi_config *spi_cfg,
			    uint8_t cmd, uint16_t addr, void *data, size_t len)
{
	uint8_t access[3];
	struct spi_buf bufs[] = {
		{
			.buf = access,
		},
		{
			.buf = data,
			.len = len
		}
	};
	struct spi_buf_set tx = {
		.buffers = bufs
	};

	access[0] = cmd;

	if (cmd == MB85RS64V_WRITE_CMD || cmd == MB85RS64V_READ_CMD) {
		access[1] = (addr >> 8) & 0xFF;
		access[2] = addr & 0xFF;

		bufs[0].len = 3;
		tx.count = 2;

		if (cmd == MB85RS64V_READ_CMD) {
			struct spi_buf_set rx = {
				.buffers = bufs,
				.count = 2
			};

			return spi_transceive(spi, spi_cfg, &tx, &rx);
		}
	} else {
		tx.count = 1;
	}

	return spi_write(spi, spi_cfg, &tx);
}


static int mb85rs64v_read_id(const struct device *spi,
			     struct spi_config *spi_cfg)
{
	uint8_t id[4];
	int err;

	err = mb85rs64v_access(spi, spi_cfg,
			       MB85RS64V_MANUFACTURER_ID_CMD, 0, &id, 4);
	if (err) {
		printk("Error during ID read\n");
		return -EIO;
	}

	if (id[0] != 0x04) {
		return -EIO;
	}

	if (id[1] != 0x7f) {
		return -EIO;
	}

	if (id[2] != 0x03) {
		return -EIO;
	}

	if (id[3] != 0x02) {
		return -EIO;
	}

	return 0;
}

static int write_bytes(const struct device *spi, struct spi_config *spi_cfg,
		       uint16_t addr, uint8_t *data, uint32_t num_bytes)
{
	int err;

	/* disable write protect */
	err = mb85rs64v_access(spi, spi_cfg,
			       MB85RS64V_WRITE_ENABLE_CMD, 0, NULL, 0);
	if (err) {
		printk("unable to disable write protect\n");
		return -EIO;
	}

	/* write cmd */
	err = mb85rs64v_access(spi, spi_cfg,
			       MB85RS64V_WRITE_CMD, addr, data, num_bytes);
	if (err) {
		printk("Error during SPI write\n");
		return -EIO;
	}

	return 0;
}

static int read_bytes(const struct device *spi, struct spi_config *spi_cfg,
		      uint16_t addr, uint8_t *data, uint32_t num_bytes)
{
	int err;

	/* read cmd */
	err = mb85rs64v_access(spi, spi_cfg,
			       MB85RS64V_READ_CMD, addr, data, num_bytes);
	if (err) {
		printk("Error during SPI read\n");
		return -EIO;
	}

	return 0;
}

void main(void)
{
	const struct device *spi;
	struct spi_config spi_cfg = {0};
	int err;

	printk("fujitsu FRAM example application\n");

	spi = DEVICE_DT_GET(DT_ALIAS(spi_1));
	if (!device_is_ready(spi)) {
		printk("SPI device %s is not ready\n", spi->name);
		return;
	}

	spi_cfg.operation = SPI_WORD_SET(8);
	spi_cfg.frequency = 256000U;


	err = mb85rs64v_read_id(spi, &spi_cfg);
	if (err) {
		printk("Could not verify FRAM ID\n");
		return;
	}

	/* Do one-byte read/write */
	data[0] = 0xAE;
	err = write_bytes(spi, &spi_cfg, 0x00, data, 1);
	if (err) {
		printk("Error writing to FRAM! errro code (%d)\n", err);
		return;
	} else {
		printk("Wrote 0xAE to address 0x00.\n");
	}

	data[0] = 0x86;
	err = write_bytes(spi, &spi_cfg, 0x01, data, 1);
	if (err) {
		printk("Error writing to FRAM! error code (%d)\n", err);
		return;
	} else {
		printk("Wrote 0x86 to address 0x01.\n");
	}

	data[0] = 0x00;
	err = read_bytes(spi, &spi_cfg, 0x00, data, 1);
	if (err) {
		printk("Error reading from FRAM! error code (%d)\n", err);
		return;
	} else {
		printk("Read 0x%X from address 0x00.\n", data[0]);
	}

	data[0] = 0x00;
	err = read_bytes(spi, &spi_cfg, 0x01, data, 1);
	if (err) {
		printk("Error reading from FRAM! error code (%d)\n", err);
		return;
	} else {
		printk("Read 0x%X from address 0x01.\n", data[0]);
	}

	/* Do multi-byte read/write */
	/* get some random data, and clear out data[] */
	for (uint32_t i = 0; i < sizeof(cmp_data); i++) {
		cmp_data[i] = k_cycle_get_32() & 0xFF;
		data[i] = 0x00;
	}

	/* write them to the FRAM */
	err = write_bytes(spi, &spi_cfg, 0x00, cmp_data, sizeof(cmp_data));
	if (err) {
		printk("Error writing to FRAM! error code (%d)\n", err);
		return;
	} else {
		printk("Wrote %d bytes to address 0x00.\n",
		       (uint32_t) sizeof(cmp_data));
	}

	err = read_bytes(spi, &spi_cfg, 0x00, data, sizeof(data));
	if (err) {
		printk("Error reading from FRAM! error code (%d)\n", err);
		return;
	} else {
		printk("Read %d bytes from address 0x00.\n",
		       (uint32_t) sizeof(data));
	}

	err = 0;
	for (uint32_t i = 0; i < sizeof(cmp_data); i++) {
		if (cmp_data[i] != data[i]) {
			printk("Data comparison failed @ %d.\n", i);
			err = -EIO;
		}
	}
	if (err == 0) {
		printk("Data comparison successful.\n");
	}
}
