/*
 * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <errno.h>
#include <stdbool.h>

#include <libfdt.h>

#include <platform_def.h>

#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <drivers/st/stm32mp_pmic.h>
#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32mp1_clk.h>
#include <drivers/st/stpmic1.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>

/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */
#define I2C_TIMING			0x10D07DB5

#define I2C_TIMEOUT			0xFFFFF

#define MASK_RESET_BUCK3		BIT(2)

#define STPMIC1_LDO12356_OUTPUT_MASK	(uint8_t)(GENMASK(6, 2))
#define STPMIC1_LDO12356_OUTPUT_SHIFT	2
#define STPMIC1_LDO3_MODE		(uint8_t)(BIT(7))
#define STPMIC1_LDO3_DDR_SEL		31U
#define STPMIC1_LDO3_1800000		(9U << STPMIC1_LDO12356_OUTPUT_SHIFT)

#define STPMIC1_BUCK_OUTPUT_SHIFT	2
#define STPMIC1_BUCK3_1V8		(39U << STPMIC1_BUCK_OUTPUT_SHIFT)

#define STPMIC1_DEFAULT_START_UP_DELAY_MS	1

static struct i2c_handle_s i2c_handle;
static uint32_t pmic_i2c_addr;

static int dt_get_pmic_node(void *fdt)
{
	return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
}

bool dt_check_pmic(void)
{
	int node;
	void *fdt;

	if (fdt_get_address(&fdt) == 0) {
		return false;
	}

	node = dt_get_pmic_node(fdt);
	if (node < 0) {
		VERBOSE("%s: No PMIC node found in DT\n", __func__);
		return false;
	}

	return fdt_get_status(node);
}

static int dt_pmic_i2c_config(struct dt_node_info *i2c_info)
{
	int pmic_node, i2c_node;
	void *fdt;
	const fdt32_t *cuint;

	if (fdt_get_address(&fdt) == 0) {
		return -ENOENT;
	}

	pmic_node = dt_get_pmic_node(fdt);
	if (pmic_node < 0) {
		return -FDT_ERR_NOTFOUND;
	}

	cuint = fdt_getprop(fdt, pmic_node, "reg", NULL);
	if (cuint == NULL) {
		return -FDT_ERR_NOTFOUND;
	}

	pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1;
	if (pmic_i2c_addr > UINT16_MAX) {
		return -EINVAL;
	}

	i2c_node = fdt_parent_offset(fdt, pmic_node);
	if (i2c_node < 0) {
		return -FDT_ERR_NOTFOUND;
	}

	dt_fill_device_info(i2c_info, i2c_node);
	if (i2c_info->base == 0U) {
		return -FDT_ERR_NOTFOUND;
	}

	return dt_set_pinctrl_config(i2c_node);
}

int dt_pmic_enable_boot_on_regulators(void)
{
	int pmic_node, regulators_node, regulator_node;
	void *fdt;

	if (fdt_get_address(&fdt) == 0) {
		return -ENOENT;
	}

	pmic_node = dt_get_pmic_node(fdt);
	if (pmic_node < 0) {
		return -FDT_ERR_NOTFOUND;
	}

	regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators");

	fdt_for_each_subnode(regulator_node, fdt, regulators_node) {
		const fdt32_t *cuint;
		const char *node_name;
		uint16_t voltage;

		if (fdt_getprop(fdt, regulator_node, "regulator-boot-on",
				NULL) == NULL) {
			continue;
		}

		cuint = fdt_getprop(fdt, regulator_node,
				    "regulator-min-microvolt", NULL);
		if (cuint == NULL) {
			continue;
		}

		/* DT uses microvolts, whereas driver awaits millivolts */
		voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
		node_name = fdt_get_name(fdt, regulator_node, NULL);

		if (stpmic1_is_regulator_enabled(node_name) == 0U) {
			int status;

			status = stpmic1_regulator_voltage_set(node_name,
							       voltage);
			if (status != 0) {
				return status;
			}

			status = stpmic1_regulator_enable(node_name);
			if (status != 0) {
				return status;
			}
		}
	}

	return 0;
}

void initialize_pmic_i2c(void)
{
	int ret;
	struct dt_node_info i2c_info;

	if (dt_pmic_i2c_config(&i2c_info) != 0) {
		ERROR("I2C configuration failed\n");
		panic();
	}

	if (stm32mp1_clk_enable((uint32_t)i2c_info.clock) < 0) {
		ERROR("I2C clock enable failed\n");
		panic();
	}

	/* Initialize PMIC I2C */
	i2c_handle.i2c_base_addr		= i2c_info.base;
	i2c_handle.i2c_init.timing		= I2C_TIMING;
	i2c_handle.i2c_init.own_address1	= pmic_i2c_addr;
	i2c_handle.i2c_init.addressing_mode	= I2C_ADDRESSINGMODE_7BIT;
	i2c_handle.i2c_init.dual_address_mode	= I2C_DUALADDRESS_DISABLE;
	i2c_handle.i2c_init.own_address2	= 0;
	i2c_handle.i2c_init.own_address2_masks	= I2C_OAR2_OA2NOMASK;
	i2c_handle.i2c_init.general_call_mode	= I2C_GENERALCALL_DISABLE;
	i2c_handle.i2c_init.no_stretch_mode	= I2C_NOSTRETCH_DISABLE;

	ret = stm32_i2c_init(&i2c_handle);
	if (ret != 0) {
		ERROR("Cannot initialize I2C %x (%d)\n",
		      i2c_handle.i2c_base_addr, ret);
		panic();
	}

	ret = stm32_i2c_config_analog_filter(&i2c_handle,
					     I2C_ANALOGFILTER_ENABLE);
	if (ret != 0) {
		ERROR("Cannot initialize I2C analog filter (%d)\n", ret);
		panic();
	}

	ret = stm32_i2c_is_device_ready(&i2c_handle, (uint16_t)pmic_i2c_addr, 1,
					I2C_TIMEOUT);
	if (ret != 0) {
		ERROR("I2C device not ready (%d)\n", ret);
		panic();
	}

	stpmic1_bind_i2c(&i2c_handle, (uint16_t)pmic_i2c_addr);
}

void initialize_pmic(void)
{
	int status;
	uint8_t read_val;

	initialize_pmic_i2c();

	status = stpmic1_register_read(VERSION_STATUS_REG, &read_val);
	if (status != 0) {
		panic();
	}

	INFO("PMIC version = 0x%x\n", read_val);

	/* Keep VDD on during the reset cycle */
	status = stpmic1_register_update(MASK_RESET_BUCK_REG,
					MASK_RESET_BUCK3,
					MASK_RESET_BUCK3);
	if (status != 0) {
		panic();
	}
}

int pmic_ddr_power_init(enum ddr_type ddr_type)
{
	bool buck3_at_1v8 = false;
	uint8_t read_val;
	int status;

	switch (ddr_type) {
	case STM32MP_DDR3:
		/* Set LDO3 to sync mode */
		status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
		if (status != 0) {
			return status;
		}

		read_val &= ~STPMIC1_LDO3_MODE;
		read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
		read_val |= STPMIC1_LDO3_DDR_SEL <<
			    STPMIC1_LDO12356_OUTPUT_SHIFT;

		status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
		if (status != 0) {
			return status;
		}

		status = stpmic1_regulator_voltage_set("buck2", 1350);
		if (status != 0) {
			return status;
		}

		status = stpmic1_regulator_enable("buck2");
		if (status != 0) {
			return status;
		}

		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);

		status = stpmic1_regulator_enable("vref_ddr");
		if (status != 0) {
			return status;
		}

		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);

		status = stpmic1_regulator_enable("ldo3");
		if (status != 0) {
			return status;
		}

		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
		break;

	case STM32MP_LPDDR2:
		/*
		 * Set LDO3 to 1.8V
		 * Set LDO3 to bypass mode if BUCK3 = 1.8V
		 * Set LDO3 to normal mode if BUCK3 != 1.8V
		 */
		status = stpmic1_register_read(BUCK3_CONTROL_REG, &read_val);
		if (status != 0) {
			return status;
		}

		if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) {
			buck3_at_1v8 = true;
		}

		status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
		if (status != 0) {
			return status;
		}

		read_val &= ~STPMIC1_LDO3_MODE;
		read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
		read_val |= STPMIC1_LDO3_1800000;
		if (buck3_at_1v8) {
			read_val |= STPMIC1_LDO3_MODE;
		}

		status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
		if (status != 0) {
			return status;
		}

		status = stpmic1_regulator_voltage_set("buck2", 1200);
		if (status != 0) {
			return status;
		}

		status = stpmic1_regulator_enable("ldo3");
		if (status != 0) {
			return status;
		}

		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);

		status = stpmic1_regulator_enable("buck2");
		if (status != 0) {
			return status;
		}

		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);

		status = stpmic1_regulator_enable("vref_ddr");
		if (status != 0) {
			return status;
		}

		mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
		break;

	default:
		break;
	};

	return 0;
}
