Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 098dee99 authored by Magnus Damm's avatar Magnus Damm Committed by Paul Mundt
Browse files

sh: add enable()/disable()/set_rate() to div6 code



This patch updates the div6 clock helper code to add support
for enable(), disable() and set_rate() callbacks.

Needed by the camera clock enabling board code on Migo-R.

Signed-off-by: default avatarMagnus Damm <damm@igel.co.jp>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent c01641b4
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -119,6 +119,10 @@ long clk_rate_table_round(struct clk *clk,
			  struct cpufreq_frequency_table *freq_table,
			  unsigned long rate);

int clk_rate_table_find(struct clk *clk,
			struct cpufreq_frequency_table *freq_table,
			unsigned long rate);

#define SH_CLK_MSTP32(_name, _id, _parent, _enable_reg,	\
	    _enable_bit, _flags)			\
{							\
+44 −0
Original line number Diff line number Diff line
@@ -68,9 +68,53 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
	return clk->freq_table[idx].frequency;
}

static int sh_clk_div6_set_rate(struct clk *clk,
				unsigned long rate, int algo_id)
{
	unsigned long value;
	int idx;

	idx = clk_rate_table_find(clk, clk->freq_table, rate);
	if (idx < 0)
		return idx;

	value = __raw_readl(clk->enable_reg);
	value &= ~0x3f;
	value |= idx;
	__raw_writel(value, clk->enable_reg);
	return 0;
}

static int sh_clk_div6_enable(struct clk *clk)
{
	unsigned long value;
	int ret;

	ret = sh_clk_div6_set_rate(clk, clk->rate, 0);
	if (ret == 0) {
		value = __raw_readl(clk->enable_reg);
		value &= ~0x100; /* clear stop bit to enable clock */
		__raw_writel(value, clk->enable_reg);
	}
	return ret;
}

static void sh_clk_div6_disable(struct clk *clk)
{
	unsigned long value;

	value = __raw_readl(clk->enable_reg);
	value |= 0x100; /* stop clock */
	value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
	__raw_writel(value, clk->enable_reg);
}

static struct clk_ops sh_clk_div6_clk_ops = {
	.recalc		= sh_clk_div6_recalc,
	.round_rate	= sh_clk_div_round_rate,
	.set_rate	= sh_clk_div6_set_rate,
	.enable		= sh_clk_div6_enable,
	.disable	= sh_clk_div6_disable,
};

int __init sh_clk_div6_register(struct clk *clks, int nr)
+19 −0
Original line number Diff line number Diff line
@@ -111,6 +111,25 @@ long clk_rate_table_round(struct clk *clk,
	return rate_best_fit;
}

int clk_rate_table_find(struct clk *clk,
			struct cpufreq_frequency_table *freq_table,
			unsigned long rate)
{
	int i;

	for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
		unsigned long freq = freq_table[i].frequency;

		if (freq == CPUFREQ_ENTRY_INVALID)
			continue;

		if (freq == rate)
			return i;
	}

	return -ENOENT;
}

/* Used for clocks that always have same value as the parent clock */
unsigned long followparent_recalc(struct clk *clk)
{