// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Microchip LAN966x SoC Clock driver.
 *
 * Copyright (C) 2021 Microchip Technology, Inc. and its subsidiaries
 *
 * Author: Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>
 */

#include <linux/bitfield.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#include <dt-bindings/clock/microchip,lan966x.h>

#define GCK_ENA         BIT(0)
#define GCK_SRC_SEL     GENMASK(9, 8)
#define GCK_PRESCALER   GENMASK(23, 16)

#define DIV_MAX		255

static const char * const lan966x_clk_names[] = {
	"qspi0", "qspi1", "qspi2", "sdmmc0",
	"pi", "mcan0", "mcan1", "flexcom0",
	"flexcom1", "flexcom2", "flexcom3",
	"flexcom4", "timer1", "usb_refclk",
};

static const char * const lan969x_clk_names[] = {
	"qspi0", "qspi2", "sdmmc0", "sdmmc1",
	"mcan0", "mcan1", "flexcom0",
	"flexcom1", "flexcom2", "flexcom3",
	"timer1", "usb_refclk",
};

struct lan966x_gck {
	struct clk_hw hw;
	void __iomem *reg;
};
#define to_lan966x_gck(hw) container_of(hw, struct lan966x_gck, hw)

static const struct clk_parent_data lan966x_gck_pdata[] = {
	{ .fw_name = "cpu", },
	{ .fw_name = "ddr", },
	{ .fw_name = "sys", },
};

static struct clk_init_data init = {
	.parent_data = lan966x_gck_pdata,
	.num_parents = ARRAY_SIZE(lan966x_gck_pdata),
};

struct clk_gate_soc_desc {
	const char *name;
	int bit_idx;
};

static const struct clk_gate_soc_desc lan966x_clk_gate_desc[] = {
	{ "uhphs", 11 },
	{ "udphs", 10 },
	{ "mcramc", 9 },
	{ "hmatrix", 8 },
	{ }
};

static const struct clk_gate_soc_desc lan969x_clk_gate_desc[] = {
	{ "usb_drd", 10 },
	{ "mcramc", 9 },
	{ "hmatrix", 8 },
	{ }
};

struct lan966x_match_data {
	char *name;
	const char * const *clk_name;
	const struct clk_gate_soc_desc *clk_gate_desc;
	u8 num_generic_clks;
	u8 num_total_clks;
};

static struct lan966x_match_data lan966x_desc = {
	.name = "lan966x",
	.clk_name = lan966x_clk_names,
	.clk_gate_desc = lan966x_clk_gate_desc,
	.num_total_clks = 18,
	.num_generic_clks = 14,
};

static struct lan966x_match_data lan969x_desc = {
	.name = "lan969x",
	.clk_name = lan969x_clk_names,
	.clk_gate_desc = lan969x_clk_gate_desc,
	.num_total_clks = 15,
	.num_generic_clks = 12,
};

static DEFINE_SPINLOCK(clk_gate_lock);
static void __iomem *base;

static int lan966x_gck_enable(struct clk_hw *hw)
{
	struct lan966x_gck *gck = to_lan966x_gck(hw);
	u32 val = readl(gck->reg);

	val |= GCK_ENA;
	writel(val, gck->reg);

	return 0;
}

static void lan966x_gck_disable(struct clk_hw *hw)
{
	struct lan966x_gck *gck = to_lan966x_gck(hw);
	u32 val = readl(gck->reg);

	val &= ~GCK_ENA;
	writel(val, gck->reg);
}

static int lan966x_gck_set_rate(struct clk_hw *hw,
				unsigned long rate,
				unsigned long parent_rate)
{
	struct lan966x_gck *gck = to_lan966x_gck(hw);
	u32 div, val = readl(gck->reg);

	if (rate == 0 || parent_rate == 0)
		return -EINVAL;

	/* Set Prescalar */
	div = parent_rate / rate;
	val &= ~GCK_PRESCALER;
	val |= FIELD_PREP(GCK_PRESCALER, (div - 1));
	writel(val, gck->reg);

	return 0;
}

static unsigned long lan966x_gck_recalc_rate(struct clk_hw *hw,
					     unsigned long parent_rate)
{
	struct lan966x_gck *gck = to_lan966x_gck(hw);
	u32 div, val = readl(gck->reg);

	div = FIELD_GET(GCK_PRESCALER, val);

	return parent_rate / (div + 1);
}

static int lan966x_gck_determine_rate(struct clk_hw *hw,
				      struct clk_rate_request *req)
{
	struct clk_hw *parent;
	int i;

	for (i = 0; i < clk_hw_get_num_parents(hw); ++i) {
		parent = clk_hw_get_parent_by_index(hw, i);
		if (!parent)
			continue;

		/* Allowed prescaler divider range is 0-255 */
		if (clk_hw_get_rate(parent) / req->rate <= DIV_MAX) {
			req->best_parent_hw = parent;
			req->best_parent_rate = clk_hw_get_rate(parent);

			return 0;
		}
	}

	return -EINVAL;
}

static u8 lan966x_gck_get_parent(struct clk_hw *hw)
{
	struct lan966x_gck *gck = to_lan966x_gck(hw);
	u32 val = readl(gck->reg);

	return FIELD_GET(GCK_SRC_SEL, val);
}

static int lan966x_gck_set_parent(struct clk_hw *hw, u8 index)
{
	struct lan966x_gck *gck = to_lan966x_gck(hw);
	u32 val = readl(gck->reg);

	val &= ~GCK_SRC_SEL;
	val |= FIELD_PREP(GCK_SRC_SEL, index);
	writel(val, gck->reg);

	return 0;
}

static const struct clk_ops lan966x_gck_ops = {
	.enable         = lan966x_gck_enable,
	.disable        = lan966x_gck_disable,
	.set_rate       = lan966x_gck_set_rate,
	.recalc_rate    = lan966x_gck_recalc_rate,
	.determine_rate = lan966x_gck_determine_rate,
	.set_parent     = lan966x_gck_set_parent,
	.get_parent     = lan966x_gck_get_parent,
};

static struct clk_hw *lan966x_gck_clk_register(struct device *dev, int i)
{
	struct lan966x_gck *priv;
	int ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return ERR_PTR(-ENOMEM);

	priv->reg = base + (i * 4);
	priv->hw.init = &init;
	ret = devm_clk_hw_register(dev, &priv->hw);
	if (ret)
		return ERR_PTR(ret);

	return &priv->hw;
};

static int lan966x_gate_clk_register(struct device *dev,
				     const struct lan966x_match_data *data,
				     struct clk_hw_onecell_data *hw_data,
				     void __iomem *gate_base)
{
	for (int i = data->num_generic_clks; i < data->num_total_clks; ++i) {
		int idx = i - data->num_generic_clks;
		const struct clk_gate_soc_desc *desc;

		desc = &data->clk_gate_desc[idx];

		hw_data->hws[i] =
			devm_clk_hw_register_gate(dev, desc->name,
						  data->name, 0, gate_base,
						  desc->bit_idx,
						  0, &clk_gate_lock);

		if (IS_ERR(hw_data->hws[i]))
			return dev_err_probe(dev, PTR_ERR(hw_data->hws[i]),
					     "failed to register %s clock\n",
					     desc->name);
	}

	return 0;
}

static int lan966x_clk_probe(struct platform_device *pdev)
{
	const struct lan966x_match_data *data;
	struct clk_hw_onecell_data *hw_data;
	struct device *dev = &pdev->dev;
	void __iomem *gate_base;
	struct resource *res;
	int i, ret;

	data = device_get_match_data(dev);
	if (!data)
		return -EINVAL;

	hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, data->num_total_clks),
			       GFP_KERNEL);
	if (!hw_data)
		return -ENOMEM;

	base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(base))
		return PTR_ERR(base);

	init.ops = &lan966x_gck_ops;

	hw_data->num = data->num_generic_clks;

	for (i = 0; i < data->num_generic_clks; i++) {
		init.name = data->clk_name[i];
		hw_data->hws[i] = lan966x_gck_clk_register(dev, i);
		if (IS_ERR(hw_data->hws[i])) {
			dev_err(dev, "failed to register %s clock\n",
				init.name);
			return PTR_ERR(hw_data->hws[i]);
		}
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (res) {
		gate_base = devm_ioremap_resource(&pdev->dev, res);
		if (IS_ERR(gate_base))
			return PTR_ERR(gate_base);

		hw_data->num = data->num_total_clks;

		ret = lan966x_gate_clk_register(dev, data, hw_data, gate_base);
		if (ret)
			return ret;
	}

	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data);
}

static const struct of_device_id lan966x_clk_dt_ids[] = {
	{ .compatible = "microchip,lan966x-gck", .data = &lan966x_desc },
	{ .compatible = "microchip,lan9691-gck", .data = &lan969x_desc },
	{ }
};
MODULE_DEVICE_TABLE(of, lan966x_clk_dt_ids);

static struct platform_driver lan966x_clk_driver = {
	.probe  = lan966x_clk_probe,
	.driver = {
		.name = "lan966x-clk",
		.of_match_table = lan966x_clk_dt_ids,
	},
};
module_platform_driver(lan966x_clk_driver);

MODULE_AUTHOR("Kavyasree Kotagiri <kavyasree.kotagiri@microchip.com>");
MODULE_DESCRIPTION("LAN966X clock driver");
MODULE_LICENSE("GPL v2");
