// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
 *
 * Based on allwinner u-boot sources rsb code which is:
 * (C) Copyright 2007-2013
 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
 * lixiang <lixiang@allwinnertech.com>
 */

#include <axp_pmic.h>
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <i2c.h>
#include <time.h>
#include <asm/arch/cpu.h>
#include <asm/arch/gpio.h>
#include <asm/arch/prcm.h>
#include <asm/arch/rsb.h>

static int sun8i_rsb_await_trans(struct sunxi_rsb_reg *base)
{
	unsigned long tmo = timer_get_us() + 1000000;
	u32 stat;
	int ret;

	while (1) {
		stat = readl(&base->stat);
		if (stat & RSB_STAT_LBSY_INT) {
			ret = -EBUSY;
			break;
		}
		if (stat & RSB_STAT_TERR_INT) {
			ret = -EIO;
			break;
		}
		if (stat & RSB_STAT_TOVER_INT) {
			ret = 0;
			break;
		}
		if (timer_get_us() > tmo) {
			ret = -ETIME;
			break;
		}
	}
	writel(stat, &base->stat); /* Clear status bits */

	return ret;
}

static int sun8i_rsb_do_trans(struct sunxi_rsb_reg *base)
{
	setbits_le32(&base->ctrl, RSB_CTRL_START_TRANS);

	return sun8i_rsb_await_trans(base);
}

static int sun8i_rsb_read(struct sunxi_rsb_reg *base, u16 runtime_addr,
			  u8 reg_addr, u8 *data)
{
	int ret;

	writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr), &base->devaddr);
	writel(reg_addr, &base->addr);
	writel(RSB_CMD_BYTE_READ, &base->cmd);

	ret = sun8i_rsb_do_trans(base);
	if (ret)
		return ret;

	*data = readl(&base->data) & 0xff;

	return 0;
}

static int sun8i_rsb_write(struct sunxi_rsb_reg *base, u16 runtime_addr,
			   u8 reg_addr, u8 data)
{
	writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr), &base->devaddr);
	writel(reg_addr, &base->addr);
	writel(data, &base->data);
	writel(RSB_CMD_BYTE_WRITE, &base->cmd);

	return sun8i_rsb_do_trans(base);
}

static int sun8i_rsb_set_device_address(struct sunxi_rsb_reg *base,
					u16 device_addr, u16 runtime_addr)
{
	writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr) |
	       RSB_DEVADDR_DEVICE_ADDR(device_addr), &base->devaddr);
	writel(RSB_CMD_SET_RTSADDR, &base->cmd);

	return sun8i_rsb_do_trans(base);
}

static void sun8i_rsb_cfg_io(void)
{
#ifdef CONFIG_MACH_SUN8I
	sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL_R_RSB);
	sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL_R_RSB);
	sunxi_gpio_set_pull(SUNXI_GPL(0), 1);
	sunxi_gpio_set_pull(SUNXI_GPL(1), 1);
	sunxi_gpio_set_drv(SUNXI_GPL(0), 2);
	sunxi_gpio_set_drv(SUNXI_GPL(1), 2);
#elif defined CONFIG_MACH_SUN9I
	sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN_R_RSB);
	sunxi_gpio_set_cfgpin(SUNXI_GPN(1), SUN9I_GPN_R_RSB);
	sunxi_gpio_set_pull(SUNXI_GPN(0), 1);
	sunxi_gpio_set_pull(SUNXI_GPN(1), 1);
	sunxi_gpio_set_drv(SUNXI_GPN(0), 2);
	sunxi_gpio_set_drv(SUNXI_GPN(1), 2);
#else
#error unsupported MACH_SUNXI
#endif
}

static void sun8i_rsb_set_clk(struct sunxi_rsb_reg *base)
{
	u32 div = 0;
	u32 cd_odly = 0;

	/* Source is Hosc24M, set RSB clk to 3Mhz */
	div = 24000000 / 3000000 / 2 - 1;
	cd_odly = div >> 1;
	if (!cd_odly)
		cd_odly = 1;

	writel((cd_odly << 8) | div, &base->ccr);
}

static int sun8i_rsb_set_device_mode(struct sunxi_rsb_reg *base)
{
	unsigned long tmo = timer_get_us() + 1000000;

	writel(RSB_DMCR_DEVICE_MODE_START | RSB_DMCR_DEVICE_MODE_DATA,
	       &base->dmcr);

	while (readl(&base->dmcr) & RSB_DMCR_DEVICE_MODE_START) {
		if (timer_get_us() > tmo)
			return -ETIME;
	}

	return sun8i_rsb_await_trans(base);
}

static int sun8i_rsb_init(struct sunxi_rsb_reg *base)
{
	/* Enable RSB and PIO clk, and de-assert their resets */
	prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB);

	/* Setup external pins */
	sun8i_rsb_cfg_io();

	writel(RSB_CTRL_SOFT_RST, &base->ctrl);
	sun8i_rsb_set_clk(base);

	return sun8i_rsb_set_device_mode(base);
}

#if IS_ENABLED(CONFIG_AXP_PMIC_BUS)
int rsb_read(const u16 runtime_addr, const u8 reg_addr, u8 *data)
{
	struct sunxi_rsb_reg *base = (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;

	return sun8i_rsb_read(base, runtime_addr, reg_addr, data);
}

int rsb_write(const u16 runtime_addr, const u8 reg_addr, u8 data)
{
	struct sunxi_rsb_reg *base = (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;

	return sun8i_rsb_write(base, runtime_addr, reg_addr, data);
}

int rsb_set_device_address(u16 device_addr, u16 runtime_addr)
{
	struct sunxi_rsb_reg *base = (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;

	return sun8i_rsb_set_device_address(base, device_addr, runtime_addr);
}

int rsb_init(void)
{
	struct sunxi_rsb_reg *base = (struct sunxi_rsb_reg *)SUNXI_RSB_BASE;

	return sun8i_rsb_init(base);
}
#endif

#if CONFIG_IS_ENABLED(DM_I2C)
struct sun8i_rsb_priv {
	struct sunxi_rsb_reg *base;
};

/*
 * The mapping from hardware address to runtime address is fixed, and shared
 * among all RSB drivers. See the comment in drivers/bus/sunxi-rsb.c in Linux.
 */
static int sun8i_rsb_get_runtime_address(u16 device_addr)
{
	if (device_addr == AXP_PMIC_PRI_DEVICE_ADDR)
		return AXP_PMIC_PRI_RUNTIME_ADDR;
	if (device_addr == AXP_PMIC_SEC_DEVICE_ADDR)
		return AXP_PMIC_SEC_RUNTIME_ADDR;

	return -ENXIO;
}

static int sun8i_rsb_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
{
	int runtime_addr = sun8i_rsb_get_runtime_address(msg->addr);
	struct sun8i_rsb_priv *priv = dev_get_priv(bus);

	if (runtime_addr < 0)
		return runtime_addr;

	/* The hardware only supports SMBus-style transfers. */
	if (nmsgs == 2 && msg[1].flags == I2C_M_RD && msg[1].len == 1)
		return sun8i_rsb_read(priv->base, runtime_addr,
				      msg[0].buf[0], &msg[1].buf[0]);

	if (nmsgs == 1 && msg[0].len == 2)
		return sun8i_rsb_write(priv->base, runtime_addr,
				       msg[0].buf[0], msg[0].buf[1]);

	return -EINVAL;
}

static int sun8i_rsb_probe_chip(struct udevice *bus, uint chip_addr,
				uint chip_flags)
{
	int runtime_addr = sun8i_rsb_get_runtime_address(chip_addr);
	struct sun8i_rsb_priv *priv = dev_get_priv(bus);

	if (runtime_addr < 0)
		return runtime_addr;

	return sun8i_rsb_set_device_address(priv->base, chip_addr, runtime_addr);
}

static int sun8i_rsb_probe(struct udevice *bus)
{
	struct sun8i_rsb_priv *priv = dev_get_priv(bus);

	priv->base = dev_read_addr_ptr(bus);

	return sun8i_rsb_init(priv->base);
}

static int sun8i_rsb_child_pre_probe(struct udevice *child)
{
	struct dm_i2c_chip *chip = dev_get_parent_plat(child);

	/* Ensure each transfer is for a single register. */
	chip->flags |= DM_I2C_CHIP_RD_ADDRESS | DM_I2C_CHIP_WR_ADDRESS;

	return 0;
}

static const struct dm_i2c_ops sun8i_rsb_ops = {
	.xfer		= sun8i_rsb_xfer,
	.probe_chip	= sun8i_rsb_probe_chip,
};

static const struct udevice_id sun8i_rsb_ids[] = {
	{ .compatible = "allwinner,sun8i-a23-rsb" },
	{ /* sentinel */ }
};

U_BOOT_DRIVER(sun8i_rsb) = {
	.name			= "sun8i_rsb",
	.id			= UCLASS_I2C,
	.of_match		= sun8i_rsb_ids,
	.probe			= sun8i_rsb_probe,
	.child_pre_probe	= sun8i_rsb_child_pre_probe,
	.priv_auto		= sizeof(struct sun8i_rsb_priv),
	.ops			= &sun8i_rsb_ops,
};
#endif /* CONFIG_IS_ENABLED(DM_I2C) */
