/*
 * Copyright (c) 2020 Peter Bigot Consulting, LLC
 *
 * SPDX-License-Identifier: Apache-2.0
 */


#include <sys/types.h>
#include <kernel.h>
#include "jesd216.h"
#include "spi_nor.h"

static bool extract_instr(uint16_t packed,
			  struct jesd216_instr *res)
{
	bool rv = (res != NULL);

	if (rv) {
		res->instr = packed >> 8;
		res->mode_clocks = (packed >> 5) & 0x07;
		res->wait_states = packed & 0x1F;
	}
	return rv;
}

int jesd216_bfp_read_support(const struct jesd216_param_header *php,
			     const struct jesd216_bfp *bfp,
			     enum jesd216_mode_type mode,
			     struct jesd216_instr *res)
{
	int rv = -ENOTSUP;

	switch (mode) {
	case JESD216_MODE_044:
		if ((php->len_dw >= 15)
		    && (sys_le32_to_cpu(bfp->dw10[5]) & BIT(9))) {
			rv = 0;
		}
		break;
	case JESD216_MODE_088:
		if ((php->len_dw >= 19)
		    && (sys_le32_to_cpu(bfp->dw10[9]) & BIT(9))) {
			rv = 0;
		}
		break;
	case JESD216_MODE_111:
		rv = 0;
		break;
	case JESD216_MODE_112:
		if (sys_le32_to_cpu(bfp->dw1) & BIT(16)) {
			uint32_t dw4 = sys_le32_to_cpu(bfp->dw4);

			rv = extract_instr(dw4 >> 0, res);
		}
		break;
	case JESD216_MODE_114:
		if (sys_le32_to_cpu(bfp->dw1) & BIT(22)) {
			uint32_t dw3 = sys_le32_to_cpu(bfp->dw3);

			rv = extract_instr(dw3 >> 16, res);
		}
		break;
	case JESD216_MODE_118:
		if (php->len_dw >= 17) {
			uint32_t dw17 = sys_le32_to_cpu(bfp->dw10[7]);

			if ((dw17 >> 24) != 0) {
				rv = extract_instr(dw17 >> 16, res);
			}
		}
		break;
	case JESD216_MODE_122:
		if (sys_le32_to_cpu(bfp->dw1) & BIT(20)) {
			uint32_t dw4 = sys_le32_to_cpu(bfp->dw4);

			rv = extract_instr(dw4 >> 16, res);
		}
		break;
	case JESD216_MODE_144:
		if (sys_le32_to_cpu(bfp->dw1) & BIT(21)) {
			uint32_t dw3 = sys_le32_to_cpu(bfp->dw3);

			rv = extract_instr(dw3 >> 0, res);
		}
		break;
	case JESD216_MODE_188:
		if (php->len_dw >= 17) {
			uint32_t dw17 = sys_le32_to_cpu(bfp->dw10[7]);

			if ((uint8_t)(dw17 >> 8) != 0) {
				rv = extract_instr(dw17 >> 0, res);
			}
		}
		break;
	case JESD216_MODE_222:
		if (sys_le32_to_cpu(bfp->dw5) & BIT(0)) {
			uint32_t dw6 = sys_le32_to_cpu(bfp->dw6);

			rv = extract_instr(dw6 >> 16, res);
		}
		break;
	case JESD216_MODE_444:
		if (sys_le32_to_cpu(bfp->dw5) & BIT(4)) {
			uint32_t dw7 = sys_le32_to_cpu(bfp->dw7);

			rv = extract_instr(dw7 >> 16, res);
		}
		break;
	/* Not clear how to detect these; they are identified only by
	 * enable/disable sequences.
	 */
	case JESD216_MODE_44D4D:
	case JESD216_MODE_888:
	case JESD216_MODE_8D8D8D:
		break;
	default:
		rv = -EINVAL;
	}

	return rv;
}

int jesd216_bfp_erase(const struct jesd216_bfp *bfp,
		       uint8_t idx,
		       struct jesd216_erase_type *etp)
{
	__ASSERT_NO_MSG((idx > 0) && (idx <= JESD216_NUM_ERASE_TYPES));

	/* Types 1 and 2 are in dw8, types 3 and 4 in dw9 */
	const uint32_t *dwp = &bfp->dw8 + (idx - 1U) / 2U;
	uint32_t dw = sys_le32_to_cpu(*dwp);

	/* Type 2(4) is in the upper half of the value. */
	if ((idx & 0x01) == 0x00) {
		dw >>= 16;
	}

	/* Extract the exponent and command */
	uint8_t exp = (uint8_t)dw;
	uint8_t cmd = (uint8_t)(dw >> 8);

	if (exp == 0) {
		return -EINVAL;
	}
	etp->cmd = cmd;
	etp->exp = exp;
	return 0;
}

int jesd216_bfp_erase_type_times(const struct jesd216_param_header *php,
				 const struct jesd216_bfp *bfp,
				 uint8_t idx,
				 uint32_t *typ_ms)
{
	__ASSERT_NO_MSG((idx > 0) && (idx <= JESD216_NUM_ERASE_TYPES));

	/* DW10 introduced in JESD216A */
	if (php->len_dw < 10) {
		return -ENOTSUP;
	}

	uint32_t dw10 = sys_le32_to_cpu(bfp->dw10[0]);

	/* Each 7-bit erase time entry has a 5-bit count in the lower
	 * bits, and a 2-bit unit in the upper bits.  The actual count
	 * is the field content plus one.
	 *
	 * The entries start with ET1 at bit 4.  The low four bits
	 * encode a value that is offset and scaled to produce a
	 * multiplier to convert from typical time to maximum time.
	 */
	unsigned int count = 1 + ((dw10 >> (4 + (idx - 1) * 7)) & 0x1F);
	unsigned int units = ((dw10 >> (4 + 5 + (idx - 1) * 7)) & 0x03);
	unsigned int max_factor = 2 * (1 + (dw10 & 0x0F));

	switch (units) {
	case 0x00:		/* 1 ms */
		*typ_ms = count;
		break;
	case 0x01:		/* 16 ms */
		*typ_ms = count * 16;
		break;
	case 0x02:		/* 128 ms */
		*typ_ms = count * 128;
		break;
	case 0x03:		/* 1 s */
		*typ_ms = count * MSEC_PER_SEC;
		break;
	}

	return max_factor;
}

int jesd216_bfp_decode_dw11(const struct jesd216_param_header *php,
			    const struct jesd216_bfp *bfp,
			    struct jesd216_bfp_dw11 *res)
{
	/* DW11 introduced in JESD216A */
	if (php->len_dw < 11) {
		return -ENOTSUP;
	}

	uint32_t dw11 = sys_le32_to_cpu(bfp->dw10[1]);
	uint32_t value = 1 + ((dw11 >> 24) & 0x1F);

	switch ((dw11 >> 29) & 0x03) {
	case 0x00: /* 16 ms */
		value *= 16;
		break;
	case 0x01:
		value *= 256;
		break;
	case 0x02:
		value *= 4 * MSEC_PER_SEC;
		break;
	case 0x03:
		value *= 64 * MSEC_PER_SEC;
		break;
	}
	res->chip_erase_ms = value;

	value = 1 + ((dw11 >> 19) & 0x0F);
	if (dw11 & BIT(23)) {
		value *= 8;
	}
	res->byte_prog_addl_us = value;

	value = 1 + ((dw11 >> 14) & 0x0F);
	if (dw11 & BIT(18)) {
		value *= 8;
	}
	res->byte_prog_first_us = value;

	value = 1 + ((dw11 >> 8) & 0x01F);
	if (dw11 & BIT(13)) {
		value *= 64;
	} else {
		value *= 8;
	}
	res->page_prog_us = value;

	res->page_size = BIT((dw11 >> 4) & 0x0F);
	res->typ_max_factor = 2 * (1 + (dw11 & 0x0F));

	return 0;
}

int jesd216_bfp_decode_dw14(const struct jesd216_param_header *php,
			    const struct jesd216_bfp *bfp,
			    struct jesd216_bfp_dw14 *res)
{
	/* DW14 introduced in JESD216A */
	if (php->len_dw < 14) {
		return -ENOTSUP;
	}

	uint32_t dw14 = sys_le32_to_cpu(bfp->dw10[4]);

	if (dw14 & BIT(31)) {
		return -ENOTSUP;
	}

	res->enter_dpd_instr = (dw14 >> 23) & 0xFF;
	res->exit_dpd_instr = (dw14 >> 15) & 0xFF;

	uint32_t value = 1 + ((dw14 >> 8) & 0x1F);

	switch ((dw14 >> 13) & 0x03) {
	case 0x00: /* 128 ns */
		value *= 128;
		break;
	case 0x01: /* 1 us */
		value *= NSEC_PER_USEC;
		break;
	case 0x02: /* 8 us */
		value *= 8 * NSEC_PER_USEC;
		break;
	case 0x03: /* 64 us */
		value *= 64 * NSEC_PER_USEC;
		break;
	}

	res->exit_delay_ns = value;

	res->poll_options = (dw14 >> 2) & 0x3F;

	return 0;
}

int jesd216_bfp_decode_dw15(const struct jesd216_param_header *php,
			    const struct jesd216_bfp *bfp,
			    struct jesd216_bfp_dw15 *res)
{
	/* DW15 introduced in JESD216A */
	if (php->len_dw < 15) {
		return -ENOTSUP;
	}

	uint32_t dw15 = sys_le32_to_cpu(bfp->dw10[5]);

	res->hold_reset_disable = (dw15 & BIT(23)) != 0U;
	res->qer = (dw15 >> 20) & 0x07;
	res->entry_044 = (dw15 >> 16) & 0x0F;
	res->exit_044 = (dw15 >> 10) & 0x3F;
	res->support_044 = (dw15 & BIT(9)) != 0U;
	res->enable_444 = (dw15 >> 4) & 0x1F;
	res->disable_444 = (dw15 >> 0) & 0x0F;

	return 0;
}

int jesd216_bfp_decode_dw16(const struct jesd216_param_header *php,
			    const struct jesd216_bfp *bfp,
			    struct jesd216_bfp_dw16 *res)
{
	/* DW16 introduced in JESD216A */
	if (php->len_dw < 16) {
		return -ENOTSUP;
	}

	uint32_t dw16 = sys_le32_to_cpu(bfp->dw10[6]);

	res->enter_4ba = (dw16 >> 24) & 0xFF;
	res->exit_4ba = (dw16 >> 14) & 0x3FF;
	res->srrs_support = (dw16 >> 8) & 0x3F;
	res->sr1_interface = (dw16 >> 0) & 0x7F;

	return 0;
}
