// SPDX-License-Identifier: GPL-2.0+
/*
 * OMAP clock controller support
 *
 * Copyright (C) 2020 Dario Binacchi <dariobin@libero.it>
 */

#include <dm.h>
#include <dm/device_compat.h>
#include <clk-uclass.h>
#include <asm/arch-am33xx/clock.h>

struct clk_ti_ctrl_offs {
	fdt_addr_t start;
	fdt_size_t end;
};

struct clk_ti_ctrl_priv {
	int offs_num;
	struct clk_ti_ctrl_offs *offs;
};

static int clk_ti_ctrl_check_offs(struct clk *clk, fdt_addr_t offs)
{
	struct clk_ti_ctrl_priv *priv = dev_get_priv(clk->dev);
	int i;

	for (i = 0; i < priv->offs_num; i++) {
		if (offs >= priv->offs[i].start && offs <= priv->offs[i].end)
			return 0;
	}

	return -EFAULT;
}

static int clk_ti_ctrl_disable(struct clk *clk)
{
	struct clk_ti_ctrl_priv *priv = dev_get_priv(clk->dev);
	u32 *clk_modules[2] = { };
	fdt_addr_t offs;
	int err;

	offs = priv->offs[0].start + clk->id;
	err = clk_ti_ctrl_check_offs(clk, offs);
	if (err) {
		dev_err(clk->dev, "invalid offset: 0x%llx\n", (fdt64_t)offs);
		return err;
	}

	clk_modules[0] = (u32 *)(offs);
	dev_dbg(clk->dev, "disable module @ %p\n", clk_modules[0]);
	do_disable_clocks(NULL, clk_modules, 1);
	return 0;
}

static int clk_ti_ctrl_enable(struct clk *clk)
{
	struct clk_ti_ctrl_priv *priv = dev_get_priv(clk->dev);
	u32 *clk_modules[2] = { };
	fdt_addr_t offs;
	int err;

	offs = priv->offs[0].start + clk->id;
	err = clk_ti_ctrl_check_offs(clk, offs);
	if (err) {
		dev_err(clk->dev, "invalid offset: 0x%llx\n", (fdt64_t)offs);
		return err;
	}

	clk_modules[0] = (u32 *)(offs);
	dev_dbg(clk->dev, "enable module @ %p\n", clk_modules[0]);
	do_enable_clocks(NULL, clk_modules, 1);
	return 0;
}

static ulong clk_ti_ctrl_get_rate(struct clk *clk)
{
	return 0;
}

static int clk_ti_ctrl_of_xlate(struct clk *clk,
				struct ofnode_phandle_args *args)
{
	if (args->args_count != 2) {
		dev_err(clk->dev, "invalid args_count: %d\n", args->args_count);
		return -EINVAL;
	}

	if (args->args_count)
		clk->id = args->args[0];
	else
		clk->id = 0;

	dev_dbg(clk->dev, "name=%s, id=%ld\n", clk->dev->name, clk->id);
	return 0;
}

static int clk_ti_ctrl_of_to_plat(struct udevice *dev)
{
	struct clk_ti_ctrl_priv *priv = dev_get_priv(dev);
	fdt_size_t fdt_size;
	int i, size;

	size = dev_read_size(dev, "reg");
	if (size < 0) {
		dev_err(dev, "failed to get 'reg' size\n");
		return size;
	}

	priv->offs_num = size / 2 / sizeof(u32);
	dev_dbg(dev, "size=%d, regs_num=%d\n", size, priv->offs_num);

	priv->offs = kmalloc_array(priv->offs_num, sizeof(*priv->offs),
				   GFP_KERNEL);
	if (!priv->offs)
		return -ENOMEM;

	for (i = 0; i < priv->offs_num; i++) {
		priv->offs[i].start =
			dev_read_addr_size_index(dev, i, &fdt_size);
		if (priv->offs[i].start == FDT_ADDR_T_NONE) {
			dev_err(dev, "failed to get offset %d\n", i);
			return -EINVAL;
		}

		priv->offs[i].end = priv->offs[i].start + fdt_size;
		dev_dbg(dev, "start=0x%016llx, end=0x%016llx\n",
			(fdt64_t)priv->offs[i].start,
			(fdt64_t)priv->offs[i].end);
	}

	return 0;
}

static struct clk_ops clk_ti_ctrl_ops = {
	.of_xlate = clk_ti_ctrl_of_xlate,
	.enable = clk_ti_ctrl_enable,
	.disable = clk_ti_ctrl_disable,
	.get_rate = clk_ti_ctrl_get_rate,
};

static const struct udevice_id clk_ti_ctrl_ids[] = {
	{.compatible = "ti,clkctrl"},
	{},
};

U_BOOT_DRIVER(clk_ti_ctrl) = {
	.name = "ti_ctrl_clk",
	.id = UCLASS_CLK,
	.of_match = clk_ti_ctrl_ids,
	.of_to_plat = clk_ti_ctrl_of_to_plat,
	.ops = &clk_ti_ctrl_ops,
	.priv_auto = sizeof(struct clk_ti_ctrl_priv),
};
