[PATCH] sh: support SIU sourcing from external clock on sh7722

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


This is a preparation patch for upcoming SIU audio interface support 
patches. It implements switching between the PLL and the master clock, 
supplied from a codec over SIUMCK[AB] pins, as a clock source for SIU[AB] 
and setting of the divisor.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@xxxxxx>
---

In fact, the .set_rate() method can be easily extended to become suitable 
for all "div4" clocks, would this be preferred?

diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index ea38b55..a6cc9eb 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -172,6 +172,63 @@ static struct clk mstp_clks[] = {
 	SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0),
 };
 
+static int siu_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk_div_mult_table *table = clk->priv;
+	u32 value;
+	int ret;
+
+	if (!strcmp("pll_clk", parent->name))
+		value = __raw_readl(clk->enable_reg) & ~(1 << 7);
+	else if ((!strcmp("siumcka_clk", parent->name) &&
+		  !strcmp("siua_clk", clk->name)) ||
+		 (!strcmp("siumckb_clk", parent->name) &&
+		  !strcmp("siub_clk", clk->name)))
+		value = __raw_readl(clk->enable_reg) | (1 << 7);
+	else
+		return -EINVAL;
+
+	ret = clk_reparent(clk, parent);
+	if (ret < 0)
+		return ret;
+
+	__raw_writel(value, clk->enable_reg);
+
+	/* Rebiuld the frequency table */
+	clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+			     table, &clk->arch_flags);
+
+	return 0;
+}
+
+static int siu_clk_set_rate(struct clk *clk, unsigned long rate, int algo_id)
+{
+	unsigned long value;
+	int idx = clk_rate_table_find(clk, clk->freq_table, rate);
+	if (idx < 0)
+		return idx;
+
+	value = __raw_readl(clk->enable_reg);
+	value &= ~0xf;
+	value |= idx;
+	__raw_writel(value, clk->enable_reg);
+
+	return 0;
+}
+
+static int siu_clk_enable(struct clk *clk)
+{
+	__raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
+	return 0;
+}
+
+static void siu_clk_disable(struct clk *clk)
+{
+	__raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
+}
+
+static struct clk_ops siu_ops;
+
 int __init arch_clk_init(void)
 {
 	int k, ret = 0;
@@ -187,6 +244,15 @@ int __init arch_clk_init(void)
 
 	if (!ret)
 		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+	if (!ret) {
+		siu_ops = *div4_clks[DIV4_SIUA].ops;
+		siu_ops.enable = siu_clk_enable;
+		siu_ops.disable = siu_clk_disable;
+		siu_ops.set_rate = siu_clk_set_rate;
+		siu_ops.set_parent = siu_clk_set_parent;
+		div4_clks[DIV4_SIUA].ops = &siu_ops;
+		div4_clks[DIV4_SIUB].ops = &siu_ops;
+	}
 
 	if (!ret)
 		ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Linux OMAP]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Free Online Dating]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Devices]

Add to Google Powered by Linux