/*
 * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <errno.h>

#include <libfdt.h>

#include <common/debug.h>
#include <drivers/allwinner/axp.h>

int axp_check_id(void)
{
	int ret;

	ret = axp_read(0x03);
	if (ret < 0)
		return ret;

	ret &= 0xcf;
	if (ret != axp_chip_id) {
		ERROR("PMIC: Found unknown PMIC %02x\n", ret);
		return ret;
	}

	return 0;
}

int axp_clrsetbits(uint8_t reg, uint8_t clr_mask, uint8_t set_mask)
{
	uint8_t val;
	int ret;

	ret = axp_read(reg);
	if (ret < 0)
		return ret;

	val = (ret & ~clr_mask) | set_mask;

	return axp_write(reg, val);
}

void axp_power_off(void)
{
	/* Set "power disable control" bit */
	axp_setbits(0x32, BIT(7));
}

#if SUNXI_SETUP_REGULATORS == 1
/*
 * Retrieve the voltage from a given regulator DTB node.
 * Both the regulator-{min,max}-microvolt properties must be present and
 * have the same value. Return that value in millivolts.
 */
static int fdt_get_regulator_millivolt(const void *fdt, int node)
{
	const fdt32_t *prop;
	uint32_t min_volt;

	prop = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
	if (prop == NULL)
		return -EINVAL;
	min_volt = fdt32_to_cpu(*prop);

	prop = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
	if (prop == NULL)
		return -EINVAL;

	if (fdt32_to_cpu(*prop) != min_volt)
		return -EINVAL;

	return min_volt / 1000;
}

static int setup_regulator(const void *fdt, int node,
			   const struct axp_regulator *reg)
{
	uint8_t val;
	int mvolt;

	mvolt = fdt_get_regulator_millivolt(fdt, node);
	if (mvolt < reg->min_volt || mvolt > reg->max_volt)
		return -EINVAL;

	val = (mvolt / reg->step) - (reg->min_volt / reg->step);
	if (val > reg->split)
		val = ((val - reg->split) / 2) + reg->split;

	axp_write(reg->volt_reg, val);
	axp_setbits(reg->switch_reg, BIT(reg->switch_bit));

	INFO("PMIC: %s voltage: %d.%03dV\n", reg->dt_name,
	     mvolt / 1000, mvolt % 1000);

	return 0;
}

static bool is_node_disabled(const void *fdt, int node)
{
	const char *cell;
	cell = fdt_getprop(fdt, node, "status", NULL);
	if (cell == NULL) {
		return false;
	}
	return strcmp(cell, "okay") != 0;
}

static bool should_enable_regulator(const void *fdt, int node)
{
	if (is_node_disabled(fdt, node)) {
		return false;
	}
	if (fdt_getprop(fdt, node, "phandle", NULL) != NULL) {
		return true;
	}
	if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) {
		return true;
	}
	return false;
}

static bool board_uses_usb0_host_mode(const void *fdt)
{
	int node, length;
	const char *prop;

	node = fdt_node_offset_by_compatible(fdt, -1,
					     "allwinner,sun8i-a33-musb");
	if (node < 0) {
		return false;
	}

	prop = fdt_getprop(fdt, node, "dr_mode", &length);
	if (!prop) {
		return false;
	}

	return !strncmp(prop, "host", length);
}

void axp_setup_regulators(const void *fdt)
{
	int node;
	bool sw = false;

	if (fdt == NULL)
		return;

	/* locate the PMIC DT node, bail out if not found */
	node = fdt_node_offset_by_compatible(fdt, -1, axp_compatible);
	if (node < 0) {
		WARN("PMIC: No PMIC DT node, skipping setup\n");
		return;
	}

	/* This applies to AXP803 only. */
	if (fdt_getprop(fdt, node, "x-powers,drive-vbus-en", NULL) &&
	    board_uses_usb0_host_mode(fdt)) {
		axp_clrbits(0x8f, BIT(4));
		axp_setbits(0x30, BIT(2));
		INFO("PMIC: Enabling DRIVEVBUS\n");
	}

	/* descend into the "regulators" subnode */
	node = fdt_subnode_offset(fdt, node, "regulators");
	if (node < 0) {
		WARN("PMIC: No regulators DT node, skipping setup\n");
		return;
	}

	/* iterate over all regulators to find used ones */
	fdt_for_each_subnode(node, fdt, node) {
		const struct axp_regulator *reg;
		const char *name;
		int length;

		/* We only care if it's always on or referenced. */
		if (!should_enable_regulator(fdt, node))
			continue;

		name = fdt_get_name(fdt, node, &length);

		/* Enable the switch last to avoid overheating. */
		if (!strncmp(name, "dc1sw", length) ||
		    !strncmp(name, "sw", length)) {
			sw = true;
			continue;
		}

		for (reg = axp_regulators; reg->dt_name; reg++) {
			if (!strncmp(name, reg->dt_name, length)) {
				setup_regulator(fdt, node, reg);
				break;
			}
		}
	}

	/*
	 * On the AXP803, if DLDO2 is enabled after DC1SW, the PMIC overheats
	 * and shuts down. So always enable DC1SW as the very last regulator.
	 */
	if (sw) {
		INFO("PMIC: Enabling DC SW\n");
		if (axp_chip_id == AXP803_CHIP_ID)
			axp_setbits(0x12, BIT(7));
		if (axp_chip_id == AXP805_CHIP_ID)
			axp_setbits(0x11, BIT(7));
	}
}
#endif	/* SUNXI_SETUP_REGULATORS */
