/*
 * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of The Linux Foundation nor
 *     the names of its contributors may be used to endorse or promote
 *     products derived from this software without specific prior written
 *     permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include <arch/defines.h>
#include <assert.h>
#include <reg.h>
#include <err.h>
#include <clock.h>
#include <clock_pll.h>
#include <clock_lib2.h>
#include <platform/timer.h>

/*=============== CXO clock ops =============*/
int cxo_clk_enable(struct clk *clk)
{
	/* Nothing to do. */
	return 0;
}

void cxo_clk_disable(struct clk *clk)
{
	/* Nothing to do. */
	return;
}


/*=============== Branch clock ops =============*/

/* Branch clock enable */
int clock_lib2_branch_clk_enable(struct clk *clk)
{
	int rc = 0;
	uint32_t cbcr_val;
	int retry = 100;
	struct branch_clk *bclk = to_branch_clk(clk);

	cbcr_val  = readl(bclk->cbcr_reg);
	cbcr_val |= CBCR_BRANCH_ENABLE_BIT;
	writel(cbcr_val, bclk->cbcr_reg);

	/* Some clocks do not need to check the enable status, return
	 * if the halt_check is not set
	 */
	if (!bclk->halt_check)
		return rc;

	/* wait until status shows it is enabled */
	while(readl(bclk->cbcr_reg) & CBCR_BRANCH_OFF_BIT)
	{
		/* Add 100 ms of time out, bail out if the clock is not enable
		 * within 100 ms */
		if (!retry)
		{
			rc = 1;
			break;
		}
		retry--;
		mdelay(1);
	}

	return rc;
}

/* Branch clock disable */
void clock_lib2_branch_clk_disable(struct clk *clk)
{
	uint32_t cbcr_val;
	struct branch_clk *bclk = to_branch_clk(clk);

	cbcr_val  = readl(bclk->cbcr_reg);
	cbcr_val &= ~CBCR_BRANCH_ENABLE_BIT;
	writel(cbcr_val, bclk->cbcr_reg);

	if (!bclk->no_halt_check_on_disable)
		/* wait until status shows it is disabled */
		while(!(readl(bclk->cbcr_reg) & CBCR_BRANCH_OFF_BIT));
}

/* Branch clock set rate */
int clock_lib2_branch_set_rate(struct clk *c, unsigned rate)
{
	struct branch_clk *branch = to_branch_clk(c);

	if (!branch->has_sibling)
		return clk_set_rate(branch->parent, rate);

	return -1;
}


/*=============== Root clock ops =============*/

/* Root enable */
int clock_lib2_rcg_enable(struct clk *c)
{
	/* Hardware feedback from branch enable results in root being enabled.
	 * Nothing to do here.
	 */

	return 0;
}

/* Root set rate:
 * Find the entry in the frequecy table corresponding to the requested rate.
 * Enable the source clock required for the new frequency.
 * Call the set_rate function defined for this particular root clock.
 */
int clock_lib2_rcg_set_rate(struct clk *c, unsigned rate)
{
	struct rcg_clk *rclk = to_rcg_clk(c);
	struct clk_freq_tbl *nf; /* new freq */
	int rc = 0;

	/* ck if new freq is in table */
	for (nf = rclk->freq_tbl; nf->freq_hz != FREQ_END
			&& nf->freq_hz != rate; nf++)
		;

	/* Frequency not found in the table */
	if (nf->freq_hz == FREQ_END)
		return ERR_INVALID_ARGS;

	/* Check if frequency is actually changed. */
	if (nf == rclk->current_freq)
		return rc;

	/* First enable the source clock for this freq. */
	clk_enable(nf->src_clk);

	/* Perform clock-specific frequency switch operations. */
	ASSERT(rclk->set_rate);
	rclk->set_rate(rclk, nf);

	/* update current freq */
	rclk->current_freq = nf;

	return rc;
}

/* root update config: informs h/w to start using the new config values */
static void clock_lib2_rcg_update_config(struct rcg_clk *rclk)
{
	uint32_t cmd;

	cmd  = readl(rclk->cmd_reg);
	cmd |= CMD_UPDATE_BIT;
	writel(cmd, rclk->cmd_reg);

	/* Wait for frequency to be updated. */
	while(readl(rclk->cmd_reg) & CMD_UPDATE_MASK);
}

/* root set rate for clocks with half integer and MND divider */
void clock_lib2_rcg_set_rate_mnd(struct rcg_clk *rclk, struct clk_freq_tbl *freq)
{
	uint32_t cfg;

	/* Program MND values */
	writel(freq->m_val, rclk->m_reg);
	writel(freq->n_val, rclk->n_reg);
	writel(freq->d_val, rclk->d_reg);

	/* setup src select and divider */
	cfg  = readl(rclk->cfg_reg);
	cfg &= ~(CFG_SRC_SEL_MASK | CFG_SRC_DIV_MASK | CFG_MODE_MASK);
	cfg |= freq->div_src_val;
	if(freq->n_val !=0)
	{
		cfg |= (CFG_MODE_DUAL_EDGE << CFG_MODE_OFFSET);
	}
	writel(cfg, rclk->cfg_reg);

	/* Inform h/w to start using the new config. */
	clock_lib2_rcg_update_config(rclk);
}

/* root set rate for clocks with half integer divider */
void clock_lib2_rcg_set_rate_hid(struct rcg_clk *rclk, struct clk_freq_tbl *freq)
{
	uint32_t cfg;

	/* setup src select and divider */
	cfg  = readl(rclk->cfg_reg);
	cfg &= ~(CFG_SRC_SEL_MASK | CFG_SRC_DIV_MASK);
	cfg |= freq->div_src_val;
	writel(cfg, rclk->cfg_reg);

	clock_lib2_rcg_update_config(rclk);
}

/*=============== Vote clock ops =============*/

/* Vote clock enable */
int clock_lib2_vote_clk_enable(struct clk *c)
{
	uint32_t vote_regval;
	uint32_t val;
	struct vote_clk *vclk = to_local_vote_clk(c);

	vote_regval = readl(vclk->vote_reg);
	vote_regval |= vclk->en_mask;
	writel_relaxed(vote_regval, vclk->vote_reg);
	do {
		val = readl(vclk->cbcr_reg);
		val &= BRANCH_CHECK_MASK;
	}
	/*  wait until status shows it is enabled */
	while((val != BRANCH_ON_VAL) && (val != BRANCH_NOC_FSM_ON_VAL));

	return 0;
}

/* Vote clock disable */
void clock_lib2_vote_clk_disable(struct clk *c)
{
	uint32_t vote_regval;
	struct vote_clk *vclk = to_local_vote_clk(c);

	vote_regval = readl(vclk->vote_reg);
	vote_regval &= ~vclk->en_mask;
    writel_relaxed(vote_regval, vclk->vote_reg);
}

/* Reset clock */
static int __clock_lib2_branch_clk_reset(uint32_t bcr_reg, enum clk_reset_action action)
{
	uint32_t reg;
	int ret = 0;

	reg = readl(bcr_reg);

	switch (action) {
	case CLK_RESET_ASSERT:
		reg |= BIT(0);
		break;
	case CLK_RESET_DEASSERT:
		reg &= ~BIT(0);
		break;
	default:
		ret = 1;
	}

	writel(reg, bcr_reg);

	/* Wait for writes to go through */
	dmb();

	return ret;
}

int clock_lib2_reset_clk_reset(struct clk *c, enum clk_reset_action action)
{
	struct reset_clk *rst = to_reset_clk(c);

	if (!rst)
		return 0;

	return __clock_lib2_branch_clk_reset(rst->bcr_reg, action);
}

int clock_lib2_branch_clk_reset(struct clk *c, enum clk_reset_action action)
{
	struct branch_clk *bclk = to_branch_clk(c);

	if (!bclk)
		return 0;

	return __clock_lib2_branch_clk_reset((uint32_t)bclk->bcr_reg, action);
}
