/*
 * Copyright (c) 2018 Synopsys, Inc. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/devicetree.h>
#include "sysconf.h"

/* default system clock */
#define SYSCLK_DEFAULT_IOSC_HZ			MHZ(16)

#define PLL_CLK_IN	(SYSCLK_DEFAULT_IOSC_HZ / 1000000)  /* PLL clock in */


#define sysconf_reg_ptr ((sysconf_reg_t *)(DT_REG_ADDR(DT_NODELABEL(sysconf))))


typedef struct pll_conf {
	uint32_t fout;
	uint32_t pll;
} pll_conf_t;

#define PLL_CONF_VAL(n, m, od) \
	(((n) << PLLCON_BIT_OFFSET_N) | \
	((m) << (PLLCON_BIT_OFFSET_M)) | \
	((od) << PLLCON_BIT_OFFSET_OD))


/* the following configuration is based on Fin = 16 Mhz */
static const pll_conf_t pll_configuration[] = {
	{100, PLL_CONF_VAL(1, 25, 2)},  /* 100 Mhz */
	{50,  PLL_CONF_VAL(1, 25, 3)},  /* 50 Mhz */
	{150, PLL_CONF_VAL(4, 75, 1)},  /* 150 Mhz */
	{75,  PLL_CONF_VAL(4, 75, 2)},  /* 75 Mhz */
	{25,  PLL_CONF_VAL(2, 25, 3)},  /* 25 Mhz */
	{72,  PLL_CONF_VAL(8, 144, 2)}, /* 72 Mhz */
	{144, PLL_CONF_VAL(8, 144, 1)}, /* 144 Mhz */
};


/**
 * PLL Fout = Fin * M/ (N *n NO)
 *
 * Fref = Fin / N; Fvco = Fref * M Fout = Fvco / NO
 *
 *  N = input divider value (1, 2, 3 … 15)
 *  M = feedback divider value (4, 5, 6 … 16383)
 *  NO = output divider value (1, 2, 4, or 8)
 *
 *  1 Mhz <= Fref <= 50 Mhz
 *  200 Mhz <= Fvco <= 400 Mhz
 *
 */
void arc_iot_pll_conf_reg(uint32_t val)
{

	sysconf_reg_ptr->CLKSEL = CLKSEL_EXT_16M;
	/* 0x52000000 is not described in spec. */
	sysconf_reg_ptr->PLLCON = val | (0x52000000);

	sysconf_reg_ptr->PLLCON = val | (1 << PLLCON_BIT_OFFSET_PLLRST);
	sysconf_reg_ptr->PLLCON = val & (~(1 << PLLCON_BIT_OFFSET_PLLRST));

	while (!(sysconf_reg_ptr->PLLSTAT & (1 << PLLSTAT_BIT_OFFSET_PLLSTB))) {
		;
	}

	sysconf_reg_ptr->CLKSEL = CLKSEL_PLL;
	/* from AHB_CLK_DIVIDER, not from DVFSS&PMC */
	sysconf_reg_ptr->AHBCLKDIV_SEL |= 1;
	/* AHB clk divisor = 1 */
	sysconf_reg_ptr->AHBCLKDIV = 0x1;
}

int32_t arc_iot_pll_fout_config(uint32_t freq)
{
	uint32_t i;

	if (freq == PLL_CLK_IN) {
		sysconf_reg_ptr->CLKSEL = CLKSEL_EXT_16M;
	}

	for (i = 0U; i < ARRAY_SIZE(pll_configuration); i++) {
		if (pll_configuration[i].fout == freq) {
			break;
		}
	}

	if (i >= ARRAY_SIZE(pll_configuration)) {
		return -1;
	}

	/* config eflash clk, must be < 100 Mhz */
	if (freq > 100) {
		arc_iot_eflash_clk_div(2);
	} else {
		arc_iot_eflash_clk_div(1);
	}

	arc_iot_pll_conf_reg(pll_configuration[i].pll);

	return 0;
}

void arc_iot_ahb_clk_divisor(uint8_t div)
{
	sysconf_reg_ptr->AHBCLKDIV = div;
}

void arc_iot_ahb_clk_enable(uint8_t dev)
{
	if (dev > AHBCLKEN_BIT_SDIO) {
		return;
	}

	sysconf_reg_ptr->AHBCLKEN |= (1 << dev);
}

void arc_iot_ahb_clk_disable(uint8_t dev)
{
	if (dev > AHBCLKEN_BIT_SDIO) {
		return;
	}

	sysconf_reg_ptr->AHBCLKEN &= (~(1 << dev));
}

void arc_iot_apb_clk_divisor(uint8_t div)
{
	sysconf_reg_ptr->APBCLKDIV = div;
}

void arc_iot_apb_clk_enable(uint8_t dev)
{
	if (dev > APBCLKEN_BIT_I3C) {
		return;
	}

	sysconf_reg_ptr->APBCLKEN |= (1 << dev);
}

void arc_iot_apb_clk_disable(uint8_t dev)
{
	if (dev > APBCLKEN_BIT_I3C) {
		return;
	}

	sysconf_reg_ptr->APBCLKEN &= (~(1 << dev));
}

void arc_iot_dio_clk_divisor(uint8_t div)
{
	sysconf_reg_ptr->SDIO_REFCLK_DIV;
}

void arc_iot_spi_master_clk_divisor(uint8_t id, uint8_t div)
{
	if (id == SPI_MASTER_0) {
		sysconf_reg_ptr->SPI_MST_CLKDIV =
		    (sysconf_reg_ptr->SPI_MST_CLKDIV & 0xffffff00) | div;
	} else if (id == SPI_MASTER_1) {
		sysconf_reg_ptr->SPI_MST_CLKDIV =
		    (sysconf_reg_ptr->SPI_MST_CLKDIV & 0xffff00ff) | (div << 8);
	} else if (id == SPI_MASTER_2) {
		sysconf_reg_ptr->SPI_MST_CLKDIV =
		    (sysconf_reg_ptr->SPI_MST_CLKDIV & 0xff00ffff) | (div << 16);
	}
}

void arc_iot_gpio8b_dbclk_div(uint8_t bank, uint8_t div)
{
	if (bank == GPIO8B_BANK0) {
		sysconf_reg_ptr->GPIO8B_DBCLK_DIV =
		    (sysconf_reg_ptr->GPIO8B_DBCLK_DIV & 0xffffff00) | div;
	} else if (bank == GPIO8B_BANK1) {
		sysconf_reg_ptr->GPIO8B_DBCLK_DIV =
		    (sysconf_reg_ptr->GPIO8B_DBCLK_DIV & 0xffff00ff) | (div << 8);
	} else if (bank == GPIO8B_BANK2) {
		sysconf_reg_ptr->GPIO8B_DBCLK_DIV =
		    (sysconf_reg_ptr->GPIO8B_DBCLK_DIV & 0xff00ffff) | (div << 16);
	} else if (bank == GPIO8B_BANK3) {
		sysconf_reg_ptr->GPIO8B_DBCLK_DIV =
		    (sysconf_reg_ptr->GPIO8B_DBCLK_DIV & 0x00ffffff) | (div << 24);
	}
}

void arc_iot_gpio4b_dbclk_div(uint8_t bank, uint8_t div)
{
	if (bank == GPIO4B_BANK0) {
		sysconf_reg_ptr->GPIO4B_DBCLK_DIV =
		    (sysconf_reg_ptr->GPIO4B_DBCLK_DIV & 0xffffff00) | div;
	} else if (bank == GPIO4B_BANK1) {
		sysconf_reg_ptr->GPIO4B_DBCLK_DIV =
		    (sysconf_reg_ptr->GPIO4B_DBCLK_DIV & 0xffff00ff) | (div << 8);
	} else if (bank == GPIO4B_BANK2) {
		sysconf_reg_ptr->GPIO4B_DBCLK_DIV =
		    (sysconf_reg_ptr->GPIO4B_DBCLK_DIV & 0xff00ffff) | (div << 16);
	}
}

void arc_iot_i2s_tx_clk_div(uint8_t div)
{
	sysconf_reg_ptr->I2S_TX_SCLKDIV = div;
}

void arc_iot_i2s_rx_clk_div(uint8_t div)
{
	sysconf_reg_ptr->I2S_RX_SCLKDIV = div;
}

void arc_iot_i2s_rx_clk_sel(uint8_t sel)
{
	sysconf_reg_ptr->I2S_RX_SCLKSEL = sel;
}

void arc_iot_syscon_reset(void)
{
	sysconf_reg_ptr->RSTCON = 0x55AA6699;
}

uint32_t arc_iot_is_poweron_rst(void)
{
	if (sysconf_reg_ptr->RSTSTAT & SYS_RST_SOFTWARE_ON) {
		return 0;
	} else {
		return 1;
	}
}

void arc_iot_dvfs_clk_divisor(uint8_t level, uint8_t div)
{
	if (level == DVFS_PERF_LEVEL0) {
		sysconf_reg_ptr->DVFS_CLKDIV =
		    (sysconf_reg_ptr->DVFS_CLKDIV & 0xffffff00) | div;
	} else if (level == DVFS_PERF_LEVEL1) {
		sysconf_reg_ptr->DVFS_CLKDIV =
		    (sysconf_reg_ptr->DVFS_CLKDIV & 0xffff00ff) | (div << 8);
	} else if (level == DVFS_PERF_LEVEL2) {
		sysconf_reg_ptr->DVFS_CLKDIV =
		    (sysconf_reg_ptr->DVFS_CLKDIV & 0xff00ffff) | (div << 16);
	} else if (level == DVFS_PERF_LEVEL3) {
		sysconf_reg_ptr->DVFS_CLKDIV =
		    (sysconf_reg_ptr->DVFS_CLKDIV & 0x00ffffff) | (div << 24);
	}
}

void arc_iot_dvfs_vdd_config(uint8_t level, uint8_t val)
{
	val &= 0xf;

	if (level == DVFS_PERF_LEVEL0) {
		sysconf_reg_ptr->DVFS_VDDSET =
		    (sysconf_reg_ptr->DVFS_VDDSET & 0xfffffff0) | val;
	} else if (level == DVFS_PERF_LEVEL1) {
		sysconf_reg_ptr->DVFS_VDDSET =
		    (sysconf_reg_ptr->DVFS_VDDSET & 0xffffff0f) | (val << 4);
	} else if (level == DVFS_PERF_LEVEL2) {
		sysconf_reg_ptr->DVFS_VDDSET =
		    (sysconf_reg_ptr->DVFS_VDDSET & 0xfffff0ff) | (val << 8);
	} else if (level == DVFS_PERF_LEVEL3) {
		sysconf_reg_ptr->DVFS_CLKDIV =
		    (sysconf_reg_ptr->DVFS_CLKDIV & 0xffff0fff) | (val << 12);
	}
}

void arc_iot_dvfs_vwtime_config(uint8_t time)
{
	sysconf_reg_ptr->DVFS_VWTIME = time;
}

void arc_iot_pmc_pwwtime_config(uint8_t time)
{
	sysconf_reg_ptr->PMC_PUWTIME = time;
}

void arc_iot_uart3_clk_divisor(uint8_t div)
{
	sysconf_reg_ptr->UART3SCLK_DIV = div;
}

void arc_iot_reset_powerdown_vector(uint32_t addr)
{
	sysconf_reg_ptr->RESET_PD_VECTOR = addr;
}

void arc_iot_pwm_timer_pause(uint32_t id, uint32_t pause)
{
	uint32_t val = sysconf_reg_ptr->TIMER_PAUSE;

	if (id > PWM_TIMER5) {
		return;
	}

	if (pause) {
		val |= (1 << id);
	} else {
		val &= (~(1 << id));
	}

	sysconf_reg_ptr->TIMER_PAUSE = val;
}

void arc_iot_eflash_clk_div(uint8_t div)
{
	sysconf_reg_ptr->AHBCLKDIV |= (div << 8);
}
