// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2015 Maxime Ripard
 *
 * Maxime Ripard <maxime.ripard@free-electrons.com>
 */

#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include <linux/spinlock.h>

struct sun4i_a10_display_clk_data {
	bool	has_div;
	u8	num_rst;
	u8	parents;

	u8	offset_en;
	u8	offset_div;
	u8	offset_mux;
	u8	offset_rst;

	u8	width_div;
	u8	width_mux;

	u32	flags;
};

struct reset_data {
	void __iomem			*reg;
	spinlock_t			*lock;
	struct reset_controller_dev	rcdev;
	u8				offset;
};

static DEFINE_SPINLOCK(sun4i_a10_display_lock);

static inline struct reset_data *rcdev_to_reset_data(struct reset_controller_dev *rcdev)
{
	return container_of(rcdev, struct reset_data, rcdev);
};

static int sun4i_a10_display_assert(struct reset_controller_dev *rcdev,
				    unsigned long id)
{
	struct reset_data *data = rcdev_to_reset_data(rcdev);
	unsigned long flags;
	u32 reg;

	spin_lock_irqsave(data->lock, flags);

	reg = readl(data->reg);
	writel(reg & ~BIT(data->offset + id), data->reg);

	spin_unlock_irqrestore(data->lock, flags);

	return 0;
}

static int sun4i_a10_display_deassert(struct reset_controller_dev *rcdev,
				      unsigned long id)
{
	struct reset_data *data = rcdev_to_reset_data(rcdev);
	unsigned long flags;
	u32 reg;

	spin_lock_irqsave(data->lock, flags);

	reg = readl(data->reg);
	writel(reg | BIT(data->offset + id), data->reg);

	spin_unlock_irqrestore(data->lock, flags);

	return 0;
}

static int sun4i_a10_display_status(struct reset_controller_dev *rcdev,
				    unsigned long id)
{
	struct reset_data *data = rcdev_to_reset_data(rcdev);

	return !(readl(data->reg) & BIT(data->offset + id));
}

static const struct reset_control_ops sun4i_a10_display_reset_ops = {
	.assert		= sun4i_a10_display_assert,
	.deassert	= sun4i_a10_display_deassert,
	.status		= sun4i_a10_display_status,
};

static int sun4i_a10_display_reset_xlate(struct reset_controller_dev *rcdev,
					 const struct of_phandle_args *spec)
{
	/* We only have a single reset signal */
	return 0;
}

static void __init sun4i_a10_display_init(struct device_node *node,
					  const struct sun4i_a10_display_clk_data *data)
{
	const char *parents[4];
	const char *clk_name = node->name;
	struct reset_data *reset_data;
	struct clk_divider *div = NULL;
	struct clk_gate *gate;
	struct resource res;
	struct clk_mux *mux;
	void __iomem *reg;
	struct clk *clk;
	int ret;

	of_property_read_string(node, "clock-output-names", &clk_name);

	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
	if (IS_ERR(reg)) {
		pr_err("%s: Could not map the clock registers\n", clk_name);
		return;
	}

	ret = of_clk_parent_fill(node, parents, data->parents);
	if (ret != data->parents) {
		pr_err("%s: Could not retrieve the parents\n", clk_name);
		goto unmap;
	}

	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
	if (!mux)
		goto unmap;

	mux->reg = reg;
	mux->shift = data->offset_mux;
	mux->mask = (1 << data->width_mux) - 1;
	mux->lock = &sun4i_a10_display_lock;

	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
	if (!gate)
		goto free_mux;

	gate->reg = reg;
	gate->bit_idx = data->offset_en;
	gate->lock = &sun4i_a10_display_lock;

	if (data->has_div) {
		div = kzalloc(sizeof(*div), GFP_KERNEL);
		if (!div)
			goto free_gate;

		div->reg = reg;
		div->shift = data->offset_div;
		div->width = data->width_div;
		div->lock = &sun4i_a10_display_lock;
	}

	clk = clk_register_composite(NULL, clk_name,
				     parents, data->parents,
				     &mux->hw, &clk_mux_ops,
				     data->has_div ? &div->hw : NULL,
				     data->has_div ? &clk_divider_ops : NULL,
				     &gate->hw, &clk_gate_ops,
				     data->flags);
	if (IS_ERR(clk)) {
		pr_err("%s: Couldn't register the clock\n", clk_name);
		goto free_div;
	}

	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
	if (ret) {
		pr_err("%s: Couldn't register DT provider\n", clk_name);
		goto free_clk;
	}

	if (!data->num_rst)
		return;

	reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
	if (!reset_data)
		goto free_of_clk;

	reset_data->reg = reg;
	reset_data->offset = data->offset_rst;
	reset_data->lock = &sun4i_a10_display_lock;
	reset_data->rcdev.nr_resets = data->num_rst;
	reset_data->rcdev.ops = &sun4i_a10_display_reset_ops;
	reset_data->rcdev.of_node = node;

	if (data->num_rst == 1) {
		reset_data->rcdev.of_reset_n_cells = 0;
		reset_data->rcdev.of_xlate = &sun4i_a10_display_reset_xlate;
	} else {
		reset_data->rcdev.of_reset_n_cells = 1;
	}

	if (reset_controller_register(&reset_data->rcdev)) {
		pr_err("%s: Couldn't register the reset controller\n",
		       clk_name);
		goto free_reset;
	}

	return;

free_reset:
	kfree(reset_data);
free_of_clk:
	of_clk_del_provider(node);
free_clk:
	clk_unregister_composite(clk);
free_div:
	kfree(div);
free_gate:
	kfree(gate);
free_mux:
	kfree(mux);
unmap:
	iounmap(reg);
	of_address_to_resource(node, 0, &res);
	release_mem_region(res.start, resource_size(&res));
}

static const struct sun4i_a10_display_clk_data sun4i_a10_tcon_ch0_data __initconst = {
	.num_rst	= 2,
	.parents	= 4,
	.offset_en	= 31,
	.offset_rst	= 29,
	.offset_mux	= 24,
	.width_mux	= 2,
	.flags		= CLK_SET_RATE_PARENT,
};

static void __init sun4i_a10_tcon_ch0_setup(struct device_node *node)
{
	sun4i_a10_display_init(node, &sun4i_a10_tcon_ch0_data);
}
CLK_OF_DECLARE(sun4i_a10_tcon_ch0, "allwinner,sun4i-a10-tcon-ch0-clk",
	       sun4i_a10_tcon_ch0_setup);

static const struct sun4i_a10_display_clk_data sun4i_a10_display_data __initconst = {
	.has_div	= true,
	.num_rst	= 1,
	.parents	= 3,
	.offset_en	= 31,
	.offset_rst	= 30,
	.offset_mux	= 24,
	.offset_div	= 0,
	.width_mux	= 2,
	.width_div	= 4,
};

static void __init sun4i_a10_display_setup(struct device_node *node)
{
	sun4i_a10_display_init(node, &sun4i_a10_display_data);
}
CLK_OF_DECLARE(sun4i_a10_display, "allwinner,sun4i-a10-display-clk",
	       sun4i_a10_display_setup);
