// SPDX-License-Identifier: GPL-2.0+
/*
 * Generic clock support for AT91 architectures.
 *
 * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
 *
 * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
 *
 * Based on drivers/clk/at91/clk-generated.c from Linux.
 */
#include <clk-uclass.h>
#include <dm.h>
#include <linux/io.h>
#include <linux/clk-provider.h>
#include <linux/clk/at91_pmc.h>

#include "pmc.h"

#define UBOOT_DM_CLK_AT91_GCK		"at91-gck-clk"

#define GENERATED_MAX_DIV	255

struct clk_gck {
	void __iomem *base;
	const u32 *clk_mux_table;
	const u32 *mux_table;
	const struct clk_pcr_layout *layout;
	struct clk_range range;
	struct clk clk;
	u32 num_parents;
	u32 id;
};

#define to_clk_gck(_c) container_of(_c, struct clk_gck, clk)

static int clk_gck_enable(struct clk *clk)
{
	struct clk_gck *gck = to_clk_gck(clk);

	pmc_write(gck->base, gck->layout->offset,
		  (gck->id & gck->layout->pid_mask));
	pmc_update_bits(gck->base, gck->layout->offset,
			gck->layout->cmd | AT91_PMC_PCR_GCKEN,
			gck->layout->cmd | AT91_PMC_PCR_GCKEN);

	return 0;
}

static int clk_gck_disable(struct clk *clk)
{
	struct clk_gck *gck = to_clk_gck(clk);

	pmc_write(gck->base, gck->layout->offset,
		  (gck->id & gck->layout->pid_mask));
	pmc_update_bits(gck->base, gck->layout->offset,
			gck->layout->cmd | AT91_PMC_PCR_GCKEN,
			gck->layout->cmd);

	return 0;
}

static int clk_gck_set_parent(struct clk *clk, struct clk *parent)
{
	struct clk_gck *gck = to_clk_gck(clk);
	int index;

	index = at91_clk_mux_val_to_index(gck->clk_mux_table, gck->num_parents,
					  parent->id);
	if (index < 0)
		return index;

	index = at91_clk_mux_index_to_val(gck->mux_table, gck->num_parents,
					  index);
	if (index < 0)
		return index;

	pmc_write(gck->base, gck->layout->offset,
		  (gck->id & gck->layout->pid_mask));
	pmc_update_bits(gck->base, gck->layout->offset,
			gck->layout->gckcss_mask | gck->layout->cmd,
			(index << (ffs(gck->layout->gckcss_mask) - 1)) |
			gck->layout->cmd);

	return 0;
}

static ulong clk_gck_set_rate(struct clk *clk, ulong rate)
{
	struct clk_gck *gck = to_clk_gck(clk);
	ulong parent_rate = clk_get_parent_rate(clk);
	u32 div;

	if (!rate || !parent_rate)
		return 0;

	if (gck->range.max && rate > gck->range.max)
		return 0;

	div = DIV_ROUND_CLOSEST(parent_rate, rate);
	if (div > GENERATED_MAX_DIV + 1 || !div)
		return 0;

	pmc_write(gck->base, gck->layout->offset,
		  (gck->id & gck->layout->pid_mask));
	pmc_update_bits(gck->base, gck->layout->offset,
			AT91_PMC_PCR_GCKDIV_MASK | gck->layout->cmd,
			((div - 1) << (ffs(AT91_PMC_PCR_GCKDIV_MASK) - 1)) |
			gck->layout->cmd);

	return parent_rate / div;
}

static ulong clk_gck_get_rate(struct clk *clk)
{
	struct clk_gck *gck = to_clk_gck(clk);
	ulong parent_rate = clk_get_parent_rate(clk);
	u32 val, div;

	if (!parent_rate)
		return 0;

	pmc_write(gck->base, gck->layout->offset,
		  (gck->id & gck->layout->pid_mask));
	pmc_read(gck->base, gck->layout->offset, &val);

	div = (val & AT91_PMC_PCR_GCKDIV_MASK) >>
		(ffs(AT91_PMC_PCR_GCKDIV_MASK) - 1);

	return parent_rate / (div + 1);
}

static const struct clk_ops gck_ops = {
	.enable = clk_gck_enable,
	.disable = clk_gck_disable,
	.set_parent = clk_gck_set_parent,
	.set_rate = clk_gck_set_rate,
	.get_rate = clk_gck_get_rate,
};

struct clk *
at91_clk_register_generic(void __iomem *base,
			  const struct clk_pcr_layout *layout,
			  const char *name, const char * const *parent_names,
			  const u32 *clk_mux_table, const u32 *mux_table,
			  u8 num_parents, u8 id,
			  const struct clk_range *range)
{
	struct clk_gck *gck;
	struct clk *clk;
	int ret, index;
	u32 val;

	if (!base || !layout || !name || !parent_names || !num_parents ||
	    !clk_mux_table || !mux_table || !range)
		return ERR_PTR(-EINVAL);

	gck = kzalloc(sizeof(*gck), GFP_KERNEL);
	if (!gck)
		return ERR_PTR(-ENOMEM);

	gck->id = id;
	gck->base = base;
	gck->range = *range;
	gck->layout = layout;
	gck->clk_mux_table = clk_mux_table;
	gck->mux_table = mux_table;
	gck->num_parents = num_parents;

	clk = &gck->clk;
	clk->flags = CLK_GET_RATE_NOCACHE;

	pmc_write(gck->base, gck->layout->offset,
		  (gck->id & gck->layout->pid_mask));
	pmc_read(gck->base, gck->layout->offset, &val);

	val = (val & gck->layout->gckcss_mask) >>
		(ffs(gck->layout->gckcss_mask) - 1);

	index = at91_clk_mux_val_to_index(gck->mux_table, gck->num_parents,
					  val);
	if (index < 0) {
		kfree(gck);
		return ERR_PTR(index);
	}

	ret = clk_register(clk, UBOOT_DM_CLK_AT91_GCK, name,
			   parent_names[index]);
	if (ret) {
		kfree(gck);
		clk = ERR_PTR(ret);
	}

	return clk;
}

U_BOOT_DRIVER(at91_gck_clk) = {
	.name = UBOOT_DM_CLK_AT91_GCK,
	.id = UCLASS_CLK,
	.ops = &gck_ops,
	.flags = DM_FLAG_PRE_RELOC,
};
