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

#include <zephyr.h>
#include <sys/printk.h>
#include <drivers/peci.h>
#include <soc.h>

#define TASK_STACK_SIZE         1024
#define PRIORITY                7

/* PECI Host address */
#define PECI_HOST_ADDR          0x30u
/* PECI Host bitrate 1Mbps */
#define PECI_HOST_BITRATE       1000u

#define PECI_CONFIGINDEX_TJMAX  16u
#define PECI_CONFIGHOSTID       0u
#define PECI_CONFIGPARAM        0u

#define PECI_SAFE_TEMP          72

static const struct device *peci_dev;
static bool peci_initialized;
static uint8_t tjmax;
static uint8_t rx_fcs;
static void monitor_temperature_func(void *dummy1, void *dummy2, void *dummy3);

static struct k_thread temp_id;
K_THREAD_STACK_DEFINE(temp_stack, TASK_STACK_SIZE);

int peci_ping(void)
{
	int ret;
	struct peci_msg packet;

	printk("%s\n", __func__);

	packet.addr = PECI_HOST_ADDR;
	packet.cmd_code = PECI_CMD_PING;
	packet.tx_buffer.buf = NULL;
	packet.tx_buffer.len = PECI_PING_WR_LEN;
	packet.rx_buffer.buf = NULL;
	packet.rx_buffer.len = PECI_PING_RD_LEN;

	ret = peci_transfer(peci_dev, &packet);
	if (ret) {
		printk("ping failed %d\n", ret);
		return ret;
	}

	return 0;
}

int peci_get_tjmax(uint8_t *tjmax)
{
	int ret;
	int retries = 3;
	uint8_t peci_resp;
	struct peci_msg packet;

	uint8_t peci_resp_buf[PECI_RD_PKG_LEN_DWORD+1];
	uint8_t peci_req_buf[] = { PECI_CONFIGHOSTID,
				PECI_CONFIGINDEX_TJMAX,
				PECI_CONFIGPARAM & 0x00FF,
				(PECI_CONFIGPARAM & 0xFF00) >> 8,
	};

	packet.tx_buffer.buf = peci_req_buf;
	packet.tx_buffer.len = PECI_RD_PKG_WR_LEN;
	packet.rx_buffer.buf = peci_resp_buf;
	packet.rx_buffer.len = PECI_RD_PKG_LEN_DWORD;

	do {
		rx_fcs = 0;
		packet.addr = PECI_HOST_ADDR;
		packet.cmd_code = PECI_CMD_RD_PKG_CFG0;

		ret = peci_transfer(peci_dev, &packet);

		for (int i = 0; i < PECI_RD_PKG_LEN_DWORD; i++) {
			printk("%02x\n", packet.rx_buffer.buf[i]);
		}

		peci_resp = packet.rx_buffer.buf[0];
		rx_fcs = packet.rx_buffer.buf[PECI_RD_PKG_LEN_DWORD];
		k_sleep(K_MSEC(1));
		printk("\npeci_resp %x\n", peci_resp);
		retries--;
	} while ((peci_resp != PECI_RW_PKG_CFG_RSP_PASS) && (retries > 0));

	*tjmax = packet.rx_buffer.buf[3];

	return 0;
}

int peci_get_temp(int *temperature)
{
	int16_t raw_cpu_temp;
	int ret;
	struct peci_msg packet = {0};

	uint8_t peci_resp_buf[PECI_GET_TEMP_RD_LEN+1];

	rx_fcs = 0;
	packet.tx_buffer.buf = NULL;
	packet.tx_buffer.len = PECI_GET_TEMP_WR_LEN;
	packet.rx_buffer.buf = peci_resp_buf;
	packet.rx_buffer.len = PECI_GET_TEMP_RD_LEN;

	packet.addr = PECI_HOST_ADDR;
	packet.cmd_code = PECI_CMD_GET_TEMP0;

	ret = peci_transfer(peci_dev, &packet);
	if (ret) {
		printk("Get temp failed %d\n", ret);
		return ret;
	}

	rx_fcs = packet.rx_buffer.buf[PECI_GET_TEMP_RD_LEN];
	printk("R FCS %x\n", rx_fcs);
	printk("Temp bytes: %02x", packet.rx_buffer.buf[0]);
	printk("%02x\n", packet.rx_buffer.buf[1]);

	raw_cpu_temp = (int16_t)(packet.rx_buffer.buf[0] |
			(int16_t)((packet.rx_buffer.buf[1] << 8) & 0xFF00));

	if (raw_cpu_temp == 0x8000) {
		printk("Invalid temp %x\n", raw_cpu_temp);
		*temperature = PECI_SAFE_TEMP;
		return -1;
	}

	raw_cpu_temp = (raw_cpu_temp >> 6) | 0x7E00;
	*temperature = raw_cpu_temp + tjmax;

	return 0;
}

void read_temp(void)
{
	int ret;
	int temp;

	ret = peci_get_temp(&temp);

	if (!ret) {
		printk("Temperature %d C\n", temp);
	}
}

void get_max_temp(void)
{
	int ret;

	ret = peci_get_tjmax(&tjmax);
	if (ret) {
		printk("Fail to obtain maximum temperature: %d\n", ret);
	} else {
		printk("Maximum temperature: %u\n", tjmax);
	}
}

static void monitor_temperature_func(void *dummy1, void *dummy2, void *dummy3)
{
	while (true) {
		k_sleep(K_MSEC(1000));
		if (peci_initialized) {
			read_temp();
		}
	}
}

void main(void)
{
#if DT_NODE_HAS_STATUS(DT_ALIAS(peci_0), okay)
	int ret;
#endif

	printk("PECI sample test\n");

	k_thread_create(&temp_id, temp_stack, TASK_STACK_SIZE,
		monitor_temperature_func, NULL, NULL, NULL, PRIORITY,
		K_INHERIT_PERMS, K_FOREVER);

#if DT_NODE_HAS_STATUS(DT_ALIAS(peci_0), okay)
	peci_dev = device_get_binding(DT_LABEL(DT_ALIAS(peci_0)));
	if (!peci_dev) {
		printk("Err: PECI device not found\n");
		return;
	}

	ret = peci_config(peci_dev, 1000u);
	if (ret) {
		printk("Err: Fail to configure bitrate\n");
		return;
	}

	peci_enable(peci_dev);

	tjmax = 100;

	get_max_temp();
	printk("Start thread...\n");
	k_thread_start(&temp_id);

	peci_initialized = true;
#endif
}
