/*
 * Copyright 2013-2015 Emilio López
 *
 * Emilio López <emilio@elopez.com.ar>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/clk.h>
#include <linux/clk-provider.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,
};

/**
 * sunxi_usb_clk_setup() - Setup function for usb gate clocks
 */

#define SUNXI_USB_MAX_SIZE 32

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

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);
