// SPDX-License-Identifier: GPL-2.0
/*
 * Amlogic Meson VPU Power Domain Controller driver
 *
 * Copyright (c) 2018 BayLibre, SAS.
 * Author: Neil Armstrong <narmstrong@baylibre.com>
 */

#include <common.h>
#include <dm.h>
#include <malloc.h>
#include <power-domain-uclass.h>
#include <regmap.h>
#include <syscon.h>
#include <reset.h>
#include <clk.h>
#include <linux/err.h>

enum {
	VPU_PWRC_COMPATIBLE_GX		= 0,
	VPU_PWRC_COMPATIBLE_G12A	= 1,
};

/* AO Offsets */

#define AO_RTI_GEN_PWR_SLEEP0		(0x3a << 2)

#define GEN_PWR_VPU_HDMI		BIT(8)
#define GEN_PWR_VPU_HDMI_ISO		BIT(9)

/* HHI Offsets */

#define HHI_MEM_PD_REG0			(0x40 << 2)
#define HHI_VPU_MEM_PD_REG0		(0x41 << 2)
#define HHI_VPU_MEM_PD_REG1		(0x42 << 2)
#define HHI_VPU_MEM_PD_REG2		(0x4d << 2)

struct meson_gx_pwrc_vpu_priv {
	struct regmap *regmap_ao;
	struct regmap *regmap_hhi;
	struct reset_ctl_bulk resets;
	struct clk_bulk clks;
};

static int meson_pwrc_vpu_request(struct power_domain *power_domain)
{
	return 0;
}

static int meson_pwrc_vpu_free(struct power_domain *power_domain)
{
	return 0;
}

static int meson_gx_pwrc_vpu_on(struct power_domain *power_domain)
{
	struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev);
	int i, ret;

	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
			   GEN_PWR_VPU_HDMI, 0);
	udelay(20);

	/* Power Up Memories */
	for (i = 0; i < 32; i += 2) {
		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG0,
				   0x3 << i, 0);
		udelay(5);
	}

	for (i = 0; i < 32; i += 2) {
		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG1,
				   0x3 << i, 0);
		udelay(5);
	}

	for (i = 8; i < 16; i++) {
		regmap_update_bits(priv->regmap_hhi, HHI_MEM_PD_REG0,
				   BIT(i), 0);
		udelay(5);
	}
	udelay(20);

	ret = reset_assert_bulk(&priv->resets);
	if (ret)
		return ret;

	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
			   GEN_PWR_VPU_HDMI_ISO, 0);

	ret = reset_deassert_bulk(&priv->resets);
	if (ret)
		return ret;

	ret = clk_enable_bulk(&priv->clks);
	if (ret)
		return ret;

	return 0;
}

static int meson_g12a_pwrc_vpu_on(struct power_domain *power_domain)
{
	struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev);
	int i, ret;

	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
			   GEN_PWR_VPU_HDMI, 0);
	udelay(20);

	/* Power Up Memories */
	for (i = 0; i < 32; i += 2) {
		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG0,
				   0x3 << i, 0);
		udelay(5);
	}

	for (i = 0; i < 32; i += 2) {
		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG1,
				   0x3 << i, 0);
		udelay(5);
	}

	for (i = 0; i < 32; i += 2) {
		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG2,
				   0x3 << i, 0);
		udelay(5);
	}

	for (i = 8; i < 16; i++) {
		regmap_update_bits(priv->regmap_hhi, HHI_MEM_PD_REG0,
				   BIT(i), 0);
		udelay(5);
	}
	udelay(20);

	ret = reset_assert_bulk(&priv->resets);
	if (ret)
		return ret;

	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
			   GEN_PWR_VPU_HDMI_ISO, 0);

	ret = reset_deassert_bulk(&priv->resets);
	if (ret)
		return ret;

	ret = clk_enable_bulk(&priv->clks);
	if (ret)
		return ret;

	return 0;
}

static int meson_pwrc_vpu_on(struct power_domain *power_domain)
{
	unsigned int compat = dev_get_driver_data(power_domain->dev);

	switch (compat) {
	case VPU_PWRC_COMPATIBLE_GX:
		return meson_gx_pwrc_vpu_on(power_domain);
	case VPU_PWRC_COMPATIBLE_G12A:
		return meson_g12a_pwrc_vpu_on(power_domain);
	}

	return -EINVAL;
}

static int meson_gx_pwrc_vpu_off(struct power_domain *power_domain)
{
	struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev);
	int i;

	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
			   GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO);
	udelay(20);

	/* Power Down Memories */
	for (i = 0; i < 32; i += 2) {
		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG0,
				   0x3 << i, 0x3 << i);
		udelay(5);
	}
	for (i = 0; i < 32; i += 2) {
		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG1,
				   0x3 << i, 0x3 << i);
		udelay(5);
	}
	for (i = 8; i < 16; i++) {
		regmap_update_bits(priv->regmap_hhi, HHI_MEM_PD_REG0,
				   BIT(i), BIT(i));
		udelay(5);
	}
	udelay(20);

	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
			   GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI);
	mdelay(20);

	clk_disable_bulk(&priv->clks);

	return 0;
}

static int meson_g12a_pwrc_vpu_off(struct power_domain *power_domain)
{
	struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev);
	int i;

	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
			   GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO);
	udelay(20);

	/* Power Down Memories */
	for (i = 0; i < 32; i += 2) {
		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG0,
				   0x3 << i, 0x3 << i);
		udelay(5);
	}
	for (i = 0; i < 32; i += 2) {
		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG1,
				   0x3 << i, 0x3 << i);
		udelay(5);
	}
	for (i = 0; i < 32; i += 2) {
		regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG2,
				   0x3 << i, 0x3 << i);
		udelay(5);
	}
	for (i = 8; i < 16; i++) {
		regmap_update_bits(priv->regmap_hhi, HHI_MEM_PD_REG0,
				   BIT(i), BIT(i));
		udelay(5);
	}
	udelay(20);

	regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
			   GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI);
	mdelay(20);

	clk_disable_bulk(&priv->clks);

	return 0;
}

static int meson_pwrc_vpu_off(struct power_domain *power_domain)
{
	unsigned int compat = dev_get_driver_data(power_domain->dev);

	switch (compat) {
	case VPU_PWRC_COMPATIBLE_GX:
		return meson_gx_pwrc_vpu_off(power_domain);
	case VPU_PWRC_COMPATIBLE_G12A:
		return meson_g12a_pwrc_vpu_off(power_domain);
	}

	return -EINVAL;
}

static int meson_pwrc_vpu_of_xlate(struct power_domain *power_domain,
				   struct ofnode_phandle_args *args)
{
	/* #power-domain-cells is 0 */

	if (args->args_count != 0) {
		debug("Invalid args_count: %d\n", args->args_count);
		return -EINVAL;
	}

	return 0;
}

struct power_domain_ops meson_gx_pwrc_vpu_ops = {
	.rfree = meson_pwrc_vpu_free,
	.off = meson_pwrc_vpu_off,
	.on = meson_pwrc_vpu_on,
	.request = meson_pwrc_vpu_request,
	.of_xlate = meson_pwrc_vpu_of_xlate,
};

static const struct udevice_id meson_gx_pwrc_vpu_ids[] = {
	{
		.compatible = "amlogic,meson-gx-pwrc-vpu",
		.data = VPU_PWRC_COMPATIBLE_GX,
	},
	{
		.compatible = "amlogic,meson-g12a-pwrc-vpu",
		.data = VPU_PWRC_COMPATIBLE_G12A,
	},
	{ }
};

static int meson_gx_pwrc_vpu_probe(struct udevice *dev)
{
	struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(dev);
	u32 hhi_phandle;
	ofnode hhi_node;
	int ret;

	priv->regmap_ao = syscon_node_to_regmap(dev_get_parent(dev)->node);
	if (IS_ERR(priv->regmap_ao))
		return PTR_ERR(priv->regmap_ao);

	ret = ofnode_read_u32(dev->node, "amlogic,hhi-sysctrl",
			      &hhi_phandle);
	if (ret)
		return ret;

	hhi_node = ofnode_get_by_phandle(hhi_phandle);
	if (!ofnode_valid(hhi_node))
		return -EINVAL;

	priv->regmap_hhi = syscon_node_to_regmap(hhi_node);
	if (IS_ERR(priv->regmap_hhi))
		return PTR_ERR(priv->regmap_hhi);

	ret = reset_get_bulk(dev, &priv->resets);
	if (ret)
		return ret;

	ret = clk_get_bulk(dev, &priv->clks);
	if (ret)
		return ret;

	return 0;
}

U_BOOT_DRIVER(meson_gx_pwrc_vpu) = {
	.name = "meson_gx_pwrc_vpu",
	.id = UCLASS_POWER_DOMAIN,
	.of_match = meson_gx_pwrc_vpu_ids,
	.probe = meson_gx_pwrc_vpu_probe,
	.ops = &meson_gx_pwrc_vpu_ops,
	.priv_auto_alloc_size = sizeof(struct meson_gx_pwrc_vpu_priv),
};
