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

Commit 9d626ecc authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Simon Horman
Browse files

sh: clkfwk: add sh_clk_fsidiv_register()



This patch adds sh_clk_fsidiv_register() to share FSI-DIV clock code

Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: default avatarPaul Mundt <lethal@linux-sh.org>
Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
parent 9d69f5b8
Loading
Loading
Loading
Loading
+86 −0
Original line number Original line Diff line number Diff line
@@ -361,3 +361,89 @@ int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
	return sh_clk_div_register_ops(clks, nr, table,
	return sh_clk_div_register_ops(clks, nr, table,
				       &sh_clk_div4_reparent_clk_ops);
				       &sh_clk_div4_reparent_clk_ops);
}
}

/* FSI-DIV */
static unsigned long fsidiv_recalc(struct clk *clk)
{
	u32 value;

	value = __raw_readl(clk->mapping->base);

	value >>= 16;
	if (value < 2)
		return clk->parent->rate;

	return clk->parent->rate / value;
}

static long fsidiv_round_rate(struct clk *clk, unsigned long rate)
{
	return clk_rate_div_range_round(clk, 1, 0xffff, rate);
}

static void fsidiv_disable(struct clk *clk)
{
	__raw_writel(0, clk->mapping->base);
}

static int fsidiv_enable(struct clk *clk)
{
	u32 value;

	value  = __raw_readl(clk->mapping->base) >> 16;
	if (value < 2)
		return 0;

	__raw_writel((value << 16) | 0x3, clk->mapping->base);

	return 0;
}

static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
{
	u32 val;
	int idx;

	idx = (clk->parent->rate / rate) & 0xffff;
	if (idx < 2)
		__raw_writel(0, clk->mapping->base);
	else
		__raw_writel(idx << 16, clk->mapping->base);

	return 0;
}

static struct sh_clk_ops fsidiv_clk_ops = {
	.recalc		= fsidiv_recalc,
	.round_rate	= fsidiv_round_rate,
	.set_rate	= fsidiv_set_rate,
	.enable		= fsidiv_enable,
	.disable	= fsidiv_disable,
};

int __init sh_clk_fsidiv_register(struct clk *clks, int nr)
{
	struct clk_mapping *map;
	int i;

	for (i = 0; i < nr; i++) {

		map = kzalloc(sizeof(struct clk_mapping), GFP_KERNEL);
		if (!map) {
			pr_err("%s: unable to alloc memory\n", __func__);
			return -ENOMEM;
		}

		/* clks[i].enable_reg came from SH_CLK_FSIDIV() */
		map->phys		= (phys_addr_t)clks[i].enable_reg;
		map->len		= 8;

		clks[i].enable_reg	= 0; /* remove .enable_reg */
		clks[i].ops		= &fsidiv_clk_ops;
		clks[i].mapping		= map;

		clk_register(&clks[i]);
	}

	return 0;
}
+9 −0
Original line number Original line Diff line number Diff line
@@ -199,4 +199,13 @@ int sh_clk_div6_reparent_register(struct clk *clks, int nr);
#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
#define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk }
#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }
#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk }


/* .enable_reg will be updated to .mapping on sh_clk_fsidiv_register() */
#define SH_CLK_FSIDIV(_reg, _parent)		\
{						\
	.enable_reg = (void __iomem *)_reg,	\
	.parent		= _parent,		\
}

int sh_clk_fsidiv_register(struct clk *clks, int nr);

#endif /* __SH_CLOCK_H */
#endif /* __SH_CLOCK_H */