// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright 2013-2015 Emilio López
 *
 * Emilio López <emilio@elopez.com.ar>
 */

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


/*
 * sunxi_usb_reset... - reset bits in usb clk registers handling
 */

struct usb_reset_data {
	void __iomem			*reg;
	spinlock_t			*lock;
	struct clk			*clk;
	struct reset_controller_dev	rcdev;
};

static int sunxi_usb_reset_assert(struct reset_controller_dev *rcdev,
			      unsigned long id)
{
	struct usb_reset_data *data = container_of(rcdev,
						   struct usb_reset_data,
						   rcdev);
	unsigned long flags;
	u32 reg;

	clk_prepare_enable(data->clk);
	spin_lock_irqsave(data->lock, flags);

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

	spin_unlock_irqrestore(data->lock, flags);
	clk_disable_unprepare(data->clk);

	return 0;
}

static int sunxi_usb_reset_deassert(struct reset_controller_dev *rcdev,
				unsigned long id)
{
	struct usb_reset_data *data = container_of(rcdev,
						     struct usb_reset_data,
						     rcdev);
	unsigned long flags;
	u32 reg;

	clk_prepare_enable(data->clk);
	spin_lock_irqsave(data->lock, flags);

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

	spin_unlock_irqrestore(data->lock, flags);
	clk_disable_unprepare(data->clk);

	return 0;
}

static const struct reset_control_ops sunxi_usb_reset_ops = {
	.assert		= sunxi_usb_reset_assert,
	.deassert	= sunxi_usb_reset_deassert,
};


#define SUNXI_USB_MAX_SIZE 32

struct usb_clk_data {
	u32 clk_mask;
	u32 reset_mask;
	bool reset_needs_clk;
};

/**
 * sunxi_usb_clk_setup() - Setup function for usb gate clocks
 * @node: &struct device_node for the clock
 * @data: &struct usb_clk_data for the clock
 * @lock: spinlock for the clock
 */
static void __init sunxi_usb_clk_setup(struct device_node *node,
				       const struct usb_clk_data *data,
				       spinlock_t *lock)
{
	struct clk_onecell_data *clk_data;
	struct usb_reset_data *reset_data;
	const char *clk_parent;
	const char *clk_name;
	void __iomem *reg;
	int qty;
	int i = 0;
	int j = 0;

	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
	if (IS_ERR(reg))
		return;

	clk_parent = of_clk_get_parent_name(node, 0);
	if (!clk_parent)
		return;

	/* Worst-case size approximation and memory allocation */
	qty = find_last_bit((unsigned long *)&data->clk_mask,
			    SUNXI_USB_MAX_SIZE);

	clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
	if (!clk_data)
		return;

	clk_data->clks = kcalloc(qty + 1, sizeof(struct clk *), GFP_KERNEL);
	if (!clk_data->clks) {
		kfree(clk_data);
		return;
	}

	for_each_set_bit(i, (unsigned long *)&data->clk_mask,
			 SUNXI_USB_MAX_SIZE) {
		of_property_read_string_index(node, "clock-output-names",
					      j, &clk_name);
		clk_data->clks[i] = clk_register_gate(NULL, clk_name,
						      clk_parent, 0,
						      reg, i, 0, lock);
		WARN_ON(IS_ERR(clk_data->clks[i]));

		j++;
	}

	/* Adjust to the real max */
	clk_data->clk_num = i;

	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);

	/* Register a reset controller for usb with reset bits */
	if (data->reset_mask == 0)
		return;

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

	if (data->reset_needs_clk) {
		reset_data->clk = of_clk_get(node, 0);
		if (IS_ERR(reset_data->clk)) {
			pr_err("Could not get clock for reset controls\n");
			kfree(reset_data);
			return;
		}
	}

	reset_data->reg = reg;
	reset_data->lock = lock;
	reset_data->rcdev.nr_resets = __fls(data->reset_mask) + 1;
	reset_data->rcdev.ops = &sunxi_usb_reset_ops;
	reset_data->rcdev.of_node = node;
	reset_controller_register(&reset_data->rcdev);
}

static const struct usb_clk_data sun4i_a10_usb_clk_data __initconst = {
	.clk_mask = BIT(8) | BIT(7) | BIT(6),
	.reset_mask = BIT(2) | BIT(1) | BIT(0),
};

static DEFINE_SPINLOCK(sun4i_a10_usb_lock);

static void __init sun4i_a10_usb_setup(struct device_node *node)
{
	sunxi_usb_clk_setup(node, &sun4i_a10_usb_clk_data, &sun4i_a10_usb_lock);
}
CLK_OF_DECLARE(sun4i_a10_usb, "allwinner,sun4i-a10-usb-clk", sun4i_a10_usb_setup);

static const struct usb_clk_data sun5i_a13_usb_clk_data __initconst = {
	.clk_mask = BIT(8) | BIT(6),
	.reset_mask = BIT(1) | BIT(0),
};

static void __init sun5i_a13_usb_setup(struct device_node *node)
{
	sunxi_usb_clk_setup(node, &sun5i_a13_usb_clk_data, &sun4i_a10_usb_lock);
}
CLK_OF_DECLARE(sun5i_a13_usb, "allwinner,sun5i-a13-usb-clk", sun5i_a13_usb_setup);

static const struct usb_clk_data sun6i_a31_usb_clk_data __initconst = {
	.clk_mask = BIT(18) | BIT(17) | BIT(16) | BIT(10) | BIT(9) | BIT(8),
	.reset_mask = BIT(2) | BIT(1) | BIT(0),
};

static void __init sun6i_a31_usb_setup(struct device_node *node)
{
	sunxi_usb_clk_setup(node, &sun6i_a31_usb_clk_data, &sun4i_a10_usb_lock);
}
CLK_OF_DECLARE(sun6i_a31_usb, "allwinner,sun6i-a31-usb-clk", sun6i_a31_usb_setup);

static const struct usb_clk_data sun8i_a23_usb_clk_data __initconst = {
	.clk_mask = BIT(16) | BIT(11) | BIT(10) | BIT(9) | BIT(8),
	.reset_mask = BIT(2) | BIT(1) | BIT(0),
};

static void __init sun8i_a23_usb_setup(struct device_node *node)
{
	sunxi_usb_clk_setup(node, &sun8i_a23_usb_clk_data, &sun4i_a10_usb_lock);
}
CLK_OF_DECLARE(sun8i_a23_usb, "allwinner,sun8i-a23-usb-clk", sun8i_a23_usb_setup);

static const struct usb_clk_data sun8i_h3_usb_clk_data __initconst = {
	.clk_mask =  BIT(19) | BIT(18) | BIT(17) | BIT(16) |
		     BIT(11) | BIT(10) | BIT(9) | BIT(8),
	.reset_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
};

static void __init sun8i_h3_usb_setup(struct device_node *node)
{
	sunxi_usb_clk_setup(node, &sun8i_h3_usb_clk_data, &sun4i_a10_usb_lock);
}
CLK_OF_DECLARE(sun8i_h3_usb, "allwinner,sun8i-h3-usb-clk", sun8i_h3_usb_setup);

static const struct usb_clk_data sun9i_a80_usb_mod_data __initconst = {
	.clk_mask = BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1),
	.reset_mask = BIT(19) | BIT(18) | BIT(17),
	.reset_needs_clk = 1,
};

static DEFINE_SPINLOCK(a80_usb_mod_lock);

static void __init sun9i_a80_usb_mod_setup(struct device_node *node)
{
	sunxi_usb_clk_setup(node, &sun9i_a80_usb_mod_data, &a80_usb_mod_lock);
}
CLK_OF_DECLARE(sun9i_a80_usb_mod, "allwinner,sun9i-a80-usb-mod-clk", sun9i_a80_usb_mod_setup);

static const struct usb_clk_data sun9i_a80_usb_phy_data __initconst = {
	.clk_mask = BIT(10) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1),
	.reset_mask = BIT(21) | BIT(20) | BIT(19) | BIT(18) | BIT(17),
	.reset_needs_clk = 1,
};

static DEFINE_SPINLOCK(a80_usb_phy_lock);

static void __init sun9i_a80_usb_phy_setup(struct device_node *node)
{
	sunxi_usb_clk_setup(node, &sun9i_a80_usb_phy_data, &a80_usb_phy_lock);
}
CLK_OF_DECLARE(sun9i_a80_usb_phy, "allwinner,sun9i-a80-usb-phy-clk", sun9i_a80_usb_phy_setup);
