// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
 */

#include <common.h>
#include <dm.h>
#include <errno.h>
#include <regmap.h>
#include <syscon.h>
#include <power/pmic.h>
#include <power/regulator.h>

#define STM32MP_PWR_CR3 0xc
#define STM32MP_PWR_CR3_USB33DEN BIT(24)
#define STM32MP_PWR_CR3_USB33RDY BIT(26)
#define STM32MP_PWR_CR3_REG18DEN BIT(28)
#define STM32MP_PWR_CR3_REG18RDY BIT(29)
#define STM32MP_PWR_CR3_REG11DEN BIT(30)
#define STM32MP_PWR_CR3_REG11RDY BIT(31)

struct stm32mp_pwr_reg_info {
	u32 enable;
	u32 ready;
	char *name;
};

struct stm32mp_pwr_priv {
	struct regmap *regmap;
};

static int stm32mp_pwr_write(struct udevice *dev, uint reg,
			     const uint8_t *buff, int len)
{
	struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
	u32 val = *(u32 *)buff;

	if (len != 4)
		return -EINVAL;

	return regmap_write(priv->regmap, STM32MP_PWR_CR3, val);
}

static int stm32mp_pwr_read(struct udevice *dev, uint reg, uint8_t *buff,
			    int len)
{
	struct stm32mp_pwr_priv *priv = dev_get_priv(dev);

	if (len != 4)
		return -EINVAL;

	return regmap_read(priv->regmap, STM32MP_PWR_CR3, (u32 *)buff);
}

static int stm32mp_pwr_ofdata_to_platdata(struct udevice *dev)
{
	struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
	struct regmap *regmap;

	regmap = syscon_get_regmap_by_driver_data(STM32MP_SYSCON_PWR);
	if (IS_ERR(regmap)) {
		pr_err("%s: unable to find regmap (%ld)\n", __func__,
		       PTR_ERR(regmap));
		return PTR_ERR(regmap);
	}
	priv->regmap = regmap;

	return 0;
}

static const struct pmic_child_info pwr_children_info[] = {
	{ .prefix = "reg", .driver = "stm32mp_pwr_regulator"},
	{ .prefix = "usb", .driver = "stm32mp_pwr_regulator"},
	{ },
};

static int stm32mp_pwr_bind(struct udevice *dev)
{
	int children;

	children = pmic_bind_children(dev, dev->node, pwr_children_info);
	if (!children)
		dev_dbg(dev, "no child found\n");

	return 0;
}

static struct dm_pmic_ops stm32mp_pwr_ops = {
	.read = stm32mp_pwr_read,
	.write = stm32mp_pwr_write,
};

static const struct udevice_id stm32mp_pwr_ids[] = {
	{ .compatible = "st,stm32mp1,pwr-reg" },
	{ }
};

U_BOOT_DRIVER(stm32mp_pwr_pmic) = {
	.name = "stm32mp_pwr_pmic",
	.id = UCLASS_PMIC,
	.of_match = stm32mp_pwr_ids,
	.bind = stm32mp_pwr_bind,
	.ops = &stm32mp_pwr_ops,
	.ofdata_to_platdata = stm32mp_pwr_ofdata_to_platdata,
	.priv_auto_alloc_size = sizeof(struct stm32mp_pwr_priv),
};

static const struct stm32mp_pwr_reg_info stm32mp_pwr_reg11 = {
	.enable = STM32MP_PWR_CR3_REG11DEN,
	.ready = STM32MP_PWR_CR3_REG11RDY,
	.name = "reg11"
};

static const struct stm32mp_pwr_reg_info stm32mp_pwr_reg18 = {
	.enable = STM32MP_PWR_CR3_REG18DEN,
	.ready = STM32MP_PWR_CR3_REG18RDY,
	.name = "reg18"
};

static const struct stm32mp_pwr_reg_info stm32mp_pwr_usb33 = {
	.enable = STM32MP_PWR_CR3_USB33DEN,
	.ready = STM32MP_PWR_CR3_USB33RDY,
	.name = "usb33"
};

static const struct stm32mp_pwr_reg_info *stm32mp_pwr_reg_infos[] = {
	&stm32mp_pwr_reg11,
	&stm32mp_pwr_reg18,
	&stm32mp_pwr_usb33,
	NULL
};

static int stm32mp_pwr_regulator_probe(struct udevice *dev)
{
	const struct stm32mp_pwr_reg_info **p = stm32mp_pwr_reg_infos;
	struct dm_regulator_uclass_platdata *uc_pdata;

	uc_pdata = dev_get_uclass_platdata(dev);

	while (*p) {
		int rc;

		rc = dev_read_stringlist_search(dev, "regulator-name",
						(*p)->name);
		if (rc >= 0) {
			dev_dbg(dev, "found regulator %s\n", (*p)->name);
			break;
		} else if (rc != -ENODATA) {
			return rc;
		}
		p++;
	}
	if (!*p) {
		int i = 0;
		const char *s;

		dev_dbg(dev, "regulator ");
		while (dev_read_string_index(dev, "regulator-name",
					     i++, &s) >= 0)
			dev_dbg(dev, "%s'%s' ", (i > 1) ? ", " : "", s);
		dev_dbg(dev, "%s not supported\n", (i > 2) ? "are" : "is");
		return -EINVAL;
	}

	uc_pdata->type = REGULATOR_TYPE_FIXED;
	dev->priv = (void *)*p;

	return 0;
}

static int stm32mp_pwr_regulator_set_value(struct udevice *dev, int uV)
{
	struct dm_regulator_uclass_platdata *uc_pdata;

	uc_pdata = dev_get_uclass_platdata(dev);
	if (!uc_pdata)
		return -ENXIO;

	if (uc_pdata->min_uV != uV) {
		dev_dbg(dev, "Invalid uV=%d for: %s\n", uV, uc_pdata->name);
		return -EINVAL;
	}

	return 0;
}

static int stm32mp_pwr_regulator_get_value(struct udevice *dev)
{
	struct dm_regulator_uclass_platdata *uc_pdata;

	uc_pdata = dev_get_uclass_platdata(dev);
	if (!uc_pdata)
		return -ENXIO;

	if (uc_pdata->min_uV != uc_pdata->max_uV) {
		dev_dbg(dev, "Invalid constraints for: %s\n", uc_pdata->name);
		return -EINVAL;
	}

	return uc_pdata->min_uV;
}

static int stm32mp_pwr_regulator_get_enable(struct udevice *dev)
{
	const struct stm32mp_pwr_reg_info *p = dev_get_priv(dev);
	int rc;
	u32 reg;

	rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
	if (rc)
		return rc;

	dev_dbg(dev, "%s id %s\n", p->name, (reg & p->enable) ? "on" : "off");

	return (reg & p->enable) != 0;
}

static int stm32mp_pwr_regulator_set_enable(struct udevice *dev, bool enable)
{
	const struct stm32mp_pwr_reg_info *p = dev_get_priv(dev);
	int rc;
	u32 reg;
	u32 time_start;

	dev_dbg(dev, "Turning %s %s\n", enable ? "on" : "off", p->name);

	rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
	if (rc)
		return rc;

	/* if regulator is already in the wanted state, nothing to do */
	if (!!(reg & p->enable) == enable)
		return 0;

	reg &= ~p->enable;
	if (enable)
		reg |= p->enable;

	rc = pmic_write(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
	if (rc)
		return rc;

	if (!enable)
		return 0;

	/* waiting ready for enable */
	time_start = get_timer(0);
	while (1) {
		rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
		if (rc)
			return rc;
		if (reg & p->ready)
			break;
		if (get_timer(time_start) > CONFIG_SYS_HZ) {
			dev_dbg(dev, "%s: timeout\n", p->name);
			return -ETIMEDOUT;
		}
	}
	return 0;
}

static const struct dm_regulator_ops stm32mp_pwr_regulator_ops = {
	.set_value  = stm32mp_pwr_regulator_set_value,
	.get_value  = stm32mp_pwr_regulator_get_value,
	.get_enable = stm32mp_pwr_regulator_get_enable,
	.set_enable = stm32mp_pwr_regulator_set_enable,
};

U_BOOT_DRIVER(stm32mp_pwr_regulator) = {
	.name = "stm32mp_pwr_regulator",
	.id = UCLASS_REGULATOR,
	.ops = &stm32mp_pwr_regulator_ops,
	.probe = stm32mp_pwr_regulator_probe,
};
