/*
 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/tegra-soc.h>

#include "clk.h"

static DEFINE_SPINLOCK(periph_ref_lock);

/* Macros to assist peripheral gate clock */
#define read_enb(gate) \
	readl_relaxed(gate->clk_base + (gate->regs->enb_reg))
#define write_enb_set(val, gate) \
	writel_relaxed(val, gate->clk_base + (gate->regs->enb_set_reg))
#define write_enb_clr(val, gate) \
	writel_relaxed(val, gate->clk_base + (gate->regs->enb_clr_reg))

#define read_rst(gate) \
	readl_relaxed(gate->clk_base + (gate->regs->rst_reg))
#define write_rst_set(val, gate) \
	writel_relaxed(val, gate->clk_base + (gate->regs->rst_set_reg))
#define write_rst_clr(val, gate) \
	writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg))

#define periph_clk_to_bit(gate) (1 << (gate->clk_num % 32))

#define LVL2_CLK_GATE_OVRE 0x554

/* Peripheral gate clock ops */
static int clk_periph_is_enabled(struct clk_hw *hw)
{
	struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
	int state = 1;

	if (!(read_enb(gate) & periph_clk_to_bit(gate)))
		state = 0;

	if (!(gate->flags & TEGRA_PERIPH_NO_RESET))
		if (read_rst(gate) & periph_clk_to_bit(gate))
			state = 0;

	return state;
}

static int clk_periph_enable(struct clk_hw *hw)
{
	struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
	unsigned long flags = 0;

	spin_lock_irqsave(&periph_ref_lock, flags);

	gate->enable_refcnt[gate->clk_num]++;
	if (gate->enable_refcnt[gate->clk_num] > 1) {
		spin_unlock_irqrestore(&periph_ref_lock, flags);
		return 0;
	}

	write_enb_set(periph_clk_to_bit(gate), gate);
	udelay(2);

	if (!(gate->flags & TEGRA_PERIPH_NO_RESET) &&
	    !(gate->flags & TEGRA_PERIPH_MANUAL_RESET)) {
		if (read_rst(gate) & periph_clk_to_bit(gate)) {
			udelay(5); /* reset propogation delay */
			write_rst_clr(periph_clk_to_bit(gate), gate);
		}
	}

	if (gate->flags & TEGRA_PERIPH_WAR_1005168) {
		writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
		writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE);
		udelay(1);
		writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
	}

	spin_unlock_irqrestore(&periph_ref_lock, flags);

	return 0;
}

static void clk_periph_disable(struct clk_hw *hw)
{
	struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
	unsigned long flags = 0;

	spin_lock_irqsave(&periph_ref_lock, flags);

	gate->enable_refcnt[gate->clk_num]--;
	if (gate->enable_refcnt[gate->clk_num] > 0) {
		spin_unlock_irqrestore(&periph_ref_lock, flags);
		return;
	}

	/*
	 * If peripheral is in the APB bus then read the APB bus to
	 * flush the write operation in apb bus. This will avoid the
	 * peripheral access after disabling clock
	 */
	if (gate->flags & TEGRA_PERIPH_ON_APB)
		tegra_read_chipid();

	write_enb_clr(periph_clk_to_bit(gate), gate);

	spin_unlock_irqrestore(&periph_ref_lock, flags);
}

void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert)
{
	if (gate->flags & TEGRA_PERIPH_NO_RESET)
		return;

	if (assert) {
		/*
		 * If peripheral is in the APB bus then read the APB bus to
		 * flush the write operation in apb bus. This will avoid the
		 * peripheral access after disabling clock
		 */
		if (gate->flags & TEGRA_PERIPH_ON_APB)
			tegra_read_chipid();

		write_rst_set(periph_clk_to_bit(gate), gate);
	} else {
		write_rst_clr(periph_clk_to_bit(gate), gate);
	}
}

const struct clk_ops tegra_clk_periph_gate_ops = {
	.is_enabled = clk_periph_is_enabled,
	.enable = clk_periph_enable,
	.disable = clk_periph_disable,
};

struct clk *tegra_clk_register_periph_gate(const char *name,
		const char *parent_name, u8 gate_flags, void __iomem *clk_base,
		unsigned long flags, int clk_num,
		struct tegra_clk_periph_regs *pregs, int *enable_refcnt)
{
	struct tegra_clk_periph_gate *gate;
	struct clk *clk;
	struct clk_init_data init;

	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
	if (!gate) {
		pr_err("%s: could not allocate periph gate clk\n", __func__);
		return ERR_PTR(-ENOMEM);
	}

	init.name = name;
	init.flags = flags;
	init.parent_names = parent_name ? &parent_name : NULL;
	init.num_parents = parent_name ? 1 : 0;
	init.ops = &tegra_clk_periph_gate_ops;

	gate->magic = TEGRA_CLK_PERIPH_GATE_MAGIC;
	gate->clk_base = clk_base;
	gate->clk_num = clk_num;
	gate->flags = gate_flags;
	gate->enable_refcnt = enable_refcnt;
	gate->regs = pregs;

	/* Data in .init is copied by clk_register(), so stack variable OK */
	gate->hw.init = &init;

	clk = clk_register(NULL, &gate->hw);
	if (IS_ERR(clk))
		kfree(gate);

	return clk;
}
