public inbox for linux-sh@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH][RFC] sh: helper code for 4-bit divisors
@ 2009-05-28  4:59 Magnus Damm
  2009-05-28  5:25 ` Paul Mundt
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Magnus Damm @ 2009-05-28  4:59 UTC (permalink / raw)
  To: linux-sh

[-- Attachment #1: Type: text/plain, Size: 1087 bytes --]

Hey Paul,

Attached are two versions of helper code for 4-bit divisors. The
sh7785 clock code is modified as an example.

linux-2.6.31-pre-sh-clk-cpg-div4-sh7785-a-20090528.patch
 include/asm/clock.h            |   42 +++++++
 kernel/cpu/clock-cpg.c         |   66 +++++++++++
 kernel/cpu/sh4a/clock-sh7785.c |  241 +++++++++++++----------------------------
 3 files changed, 188 insertions(+), 161 deletions(-)

linux-2.6.31-pre-sh-clk-cpg-div4-sh7785-b-20090528.patch
 include/asm/clock.h            |   40 +++++++
 kernel/cpu/clock-cpg.c         |   69 +++++++++++++
 kernel/cpu/sh4a/clock-sh7785.c |  206 ++++++++---------------------------------
 3 files changed, 154 insertions(+), 161 deletions(-)

I prefer version b (the last) since it allows us to write more compact
per-processor code. Also, I think using offsetof is a quick and cheap
way to get private data without using much memory. I may be the only
person that likes wrapping stuff like this though. Any thoughts?

If we can agree on something then i'd like to convert the SuperH
Mobile processors using this.

/ magnus

[-- Attachment #2: linux-2.6.31-pre-sh-clk-cpg-div4-sh7785-a-20090528.patch --]
[-- Type: application/octet-stream, Size: 11251 bytes --]

--- 0001/arch/sh/include/asm/clock.h
+++ work/arch/sh/include/asm/clock.h	2009-05-28 13:02:03.000000000 +0900
@@ -3,6 +3,7 @@
 
 #include <linux/list.h>
 #include <linux/seq_file.h>
+#include <linux/cpufreq.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 
@@ -117,4 +118,45 @@ long clk_rate_table_round(struct clk *cl
 			  struct cpufreq_frequency_table *freq_table,
 			  unsigned long rate);
 
+
+/* helper data structures and function for 4-bit width clock divisors */
+struct sh_clk_cpg_div4_table {
+	unsigned int div[1 << 4];
+	unsigned int mult[1 << 4];
+	struct clk_div_mult_table t;
+};
+
+struct sh_clk_cpg_div4_data {
+	unsigned int shift;
+	void __iomem *reg;
+
+	/* allowable divisor bitmap */
+	unsigned long div_bitmap;
+
+	/* Supportable frequencies + termination entry */
+	struct cpufreq_frequency_table freq_table[(1 << 4)+1];
+
+	/* Configuration table */
+	struct sh_clk_cpg_div4_table *config_table;
+};
+
+#define SH_CLK_CPG_DIV4_DATA(_reg, _shift, _div_bitmap)	\
+{							\
+	.reg            = (void __iomem *)_reg,		\
+	.shift          = _shift,			\
+	.div_bitmap     = _div_bitmap,			\
+							\
+	.freq_table[0]  = {				\
+		.index = 0,				\
+		.frequency = CPUFREQ_TABLE_END,		\
+	},						\
+}
+
+int sh_clk_cpg_div4_register(struct clk *clk,
+			      int nr,
+			      struct sh_clk_cpg_div4_data *data,
+			      struct sh_clk_cpg_div4_table *table);
+
+
+
 #endif /* __ASM_SH_CLOCK_H */
--- 0001/arch/sh/kernel/cpu/clock-cpg.c
+++ work/arch/sh/kernel/cpu/clock-cpg.c	2009-05-28 13:00:35.000000000 +0900
@@ -1,7 +1,73 @@
 #include <linux/clk.h>
 #include <linux/compiler.h>
+#include <linux/io.h>
 #include <asm/clock.h>
 
+static unsigned long sh_clk_cpg_div4_recalc(struct clk *clk)
+{
+	struct sh_clk_cpg_div4_data *data = clk->priv;
+	unsigned int idx = (__raw_readl(data->reg) >> data->shift) & 0x000f;
+
+	clk_rate_table_build(clk, data->freq_table,
+			     ARRAY_SIZE(data->config_table->div),
+			     &data->config_table->t, &data->div_bitmap);
+
+	return data->freq_table[idx].frequency;
+}
+
+static long sh_clk_cpg_div4_round_rate(struct clk *clk, unsigned long rate)
+{
+	struct sh_clk_cpg_div4_data *data = clk->priv;
+
+	return clk_rate_table_round(clk, data->freq_table, rate);
+}
+
+static struct clk_ops sh_clk_cpg_div4_clk_ops = {
+	.recalc		= sh_clk_cpg_div4_recalc,
+	.round_rate	= sh_clk_cpg_div4_round_rate,
+};
+
+int __init sh_clk_cpg_div4_register(struct clk *clk,
+				    int nr,
+				    struct sh_clk_cpg_div4_data *data,
+				    struct sh_clk_cpg_div4_table *table)
+{
+	struct clk *clkp;
+	struct sh_clk_cpg_div4_data *datap;
+	int ret = 0;
+	int k;
+
+	for (k = 0; k < ARRAY_SIZE(table->div); k++) {
+		if (!table->div[k])
+			table->div[k] = 1;
+		if (!table->mult[k])
+			table->mult[k] = 1;
+	}
+
+	table->t.divisors = table->div;
+	table->t.nr_divisors = ARRAY_SIZE(table->div);
+	table->t.multipliers = table->mult;
+	table->t.nr_multipliers = ARRAY_SIZE(table->mult);
+
+	for (k = 0; !ret && (k < nr); k++) {
+		clkp = clk + k;
+		datap = data + k;
+
+		datap->config_table = table;
+
+		BUG_ON(!clkp->parent || !clkp->name);
+
+		clkp->id = -1;
+		clkp->ops = &sh_clk_cpg_div4_clk_ops;
+		clkp->priv = datap;
+		clkp->flags = CLK_ENABLE_ON_INIT;
+
+		ret = clk_register(clkp);
+	}
+
+	return ret;
+}
+
 #ifdef CONFIG_SH_CLK_CPG_LEGACY
 static struct clk master_clk = {
 	.name		= "master_clk",
--- 0001/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
+++ work/arch/sh/kernel/cpu/sh4a/clock-sh7785.c	2009-05-28 13:00:06.000000000 +0900
@@ -17,65 +17,14 @@
 #include <asm/clock.h>
 #include <asm/freq.h>
 
-static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
-			       24, 32, 36, 48 };
-
-static struct clk_div_mult_table cpg_div = {
-	.divisors = div2,
-	.nr_divisors = ARRAY_SIZE(div2),
-};
-
-struct clk_priv {
-	unsigned int			shift;
-
-	/* allowable divisor bitmap */
-	unsigned long			div_bitmap;
-
-	/* Supportable frequencies + termination entry */
-	struct cpufreq_frequency_table	freq_table[ARRAY_SIZE(div2)+1];
-};
-
-#define FRQMR_CLK_DATA(_name, _shift, _div_bitmap)	\
-static struct clk_priv _name##_data = {			\
-	.shift		= _shift,			\
-	.div_bitmap	= _div_bitmap,			\
-							\
-	.freq_table[0]	= {				\
-		.index = 0,				\
-		.frequency = CPUFREQ_TABLE_END,		\
-	},						\
-}
-
-FRQMR_CLK_DATA(pfc,  0, 0x0f80);
-FRQMR_CLK_DATA(s3fc, 4, 0x0ff0);
-FRQMR_CLK_DATA(s2fc, 8, 0x0030);
-FRQMR_CLK_DATA(mfc, 12, 0x000c);
-FRQMR_CLK_DATA(bfc, 16, 0x0fe0);
-FRQMR_CLK_DATA(sfc, 20, 0x000c);
-FRQMR_CLK_DATA(ufc, 24, 0x000c);
-FRQMR_CLK_DATA(ifc, 28, 0x000e);
-
-static unsigned long frqmr_recalc(struct clk *clk)
-{
-	struct clk_priv *data = clk->priv;
-	unsigned int idx = (__raw_readl(FRQMR1) >> data->shift) & 0x000f;
-
-	clk_rate_table_build(clk, data->freq_table, ARRAY_SIZE(div2),
-			     &cpg_div, &data->div_bitmap);
-	
-	return data->freq_table[idx].frequency;
-}
-
-static long frqmr_round_rate(struct clk *clk, unsigned long rate)
-{
-	struct clk_priv *data = clk->priv;
-
-	return clk_rate_table_round(clk, data->freq_table, rate);
-}
-
-static struct clk_ops frqmr_clk_ops = {
-	.recalc			= frqmr_recalc,
-	.round_rate		= frqmr_round_rate,
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+	.name		= "extal",
+	.id		= -1,
+	.rate		= 33333333,
 };
 
 static unsigned long pll_recalc(struct clk *clk)
@@ -92,16 +41,6 @@ static struct clk_ops pll_clk_ops = {
 	.recalc		= pll_recalc,
 };
 
-/*
- * Default rate for the root input clock, reset this with clk_set_rate()
- * from the platform code.
- */
-static struct clk extal_clk = {
-	.name		= "extal",
-	.id		= -1,
-	.rate		= 33333333,
-};
-
 static struct clk pll_clk = {
 	.name		= "pll_clk",
 	.id		= -1,
@@ -110,87 +49,62 @@ static struct clk pll_clk = {
 	.flags		= CLK_ENABLE_ON_INIT,
 };
 
-static struct clk cpu_clk = {
-	.name		= "cpu_clk",		/* Ick */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &ifc_data,
-};
-
-static struct clk shyway_clk = {
-	.name		= "shyway_clk",		/* SHck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &sfc_data,
-};
-
-static struct clk peripheral_clk = {
-	.name		= "peripheral_clk",	/* Pck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &pfc_data,
-};
-
-static struct clk ddr_clk = {
-	.name		= "ddr_clk",		/* DDRck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &mfc_data,
-};
-
-static struct clk bus_clk = {
-	.name		= "bus_clk",		/* Bck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &bfc_data,
+static struct clk *clks[] = {
+	&extal_clk,
+	&pll_clk,
 };
 
-static struct clk ga_clk = {
-	.name		= "ga_clk",		/* GAck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.priv		= &s2fc_data,
+struct sh_clk_cpg_div4_table div4_table = {
+	.div = { 1, 2, 4, 6, 8, 12, 16, 18, 24, 32, 36, 48, },
 };
 
-static struct clk du_clk = {
-	.name		= "du_clk",		/* DUck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.priv		= &s3fc_data,
-};
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_GA,
+	DIV4_DU, DIV4_P, DIV4_NR };
 
-static struct clk umem_clk = {
-	.name		= "umem_clk",		/* uck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &ufc_data,
-};
-
-static struct clk *clks[] = {
-	&extal_clk,
-	&pll_clk,
-	&cpu_clk,
-	&shyway_clk,
-	&peripheral_clk,
-	&ddr_clk,
-	&bus_clk,
-	&ga_clk,
-	&du_clk,
-	&umem_clk,
+struct sh_clk_cpg_div4_data div4_data[DIV4_NR] = {
+	[DIV4_P] = SH_CLK_CPG_DIV4_DATA(FRQMR1, 0, 0x0f80),
+	[DIV4_DU] = SH_CLK_CPG_DIV4_DATA(FRQMR1, 4, 0x0ff0),
+	[DIV4_GA] = SH_CLK_CPG_DIV4_DATA(FRQMR1, 8, 0x0030),
+	[DIV4_DDR] = SH_CLK_CPG_DIV4_DATA(FRQMR1, 12, 0x000c),
+	[DIV4_B] = SH_CLK_CPG_DIV4_DATA(FRQMR1, 16, 0x0fe0),
+	[DIV4_SH] = SH_CLK_CPG_DIV4_DATA(FRQMR1, 20, 0x000c),
+	[DIV4_U] = SH_CLK_CPG_DIV4_DATA(FRQMR1, 24, 0x000c),
+	[DIV4_I] = SH_CLK_CPG_DIV4_DATA(FRQMR1, 28, 0x000e),
+};
+
+struct clk div4_clks[DIV4_NR] = {
+	[DIV4_I] = {
+		.name		= "cpu_clk",		/* Ick */
+		.parent		= &pll_clk,
+	},
+	[DIV4_SH] = {
+		.name		= "shyway_clk",		/* SHck */
+		.parent		= &pll_clk,
+	},
+	[DIV4_P] = {
+		.name		= "peripheral_clk",	/* Pck */
+		.parent		= &pll_clk,
+	},
+	[DIV4_DDR] = {
+		.name		= "ddr_clk",		/* DDRck */
+		.parent		= &pll_clk,
+	},
+	[DIV4_B] = {
+		.name		= "bus_clk",		/* Bck */
+		.parent		= &pll_clk,
+	},
+	[DIV4_GA] = {
+		.name		= "ga_clk",		/* GAck */
+		.parent		= &pll_clk,
+	},
+	[DIV4_DU] = {
+		.name		= "du_clk",		/* DUck */
+		.parent		= &pll_clk,
+	},
+	[DIV4_U] = {
+		.name		= "umem_clk",		/* uck */
+		.parent		= &pll_clk,
+	},
 };
 
 static int mstpcr_clk_enable(struct clk *clk)
@@ -229,22 +143,22 @@ static struct clk_ops mstpcr_clk_ops = {
 
 static struct clk mstpcr_clks[] = {
 	/* MSTPCR0 */
-	CLK("scif_fck", 5, &peripheral_clk, MSTPCR0, 29, 0),
-	CLK("scif_fck", 4, &peripheral_clk, MSTPCR0, 28, 0),
-	CLK("scif_fck", 3, &peripheral_clk, MSTPCR0, 27, 0),
-	CLK("scif_fck", 2, &peripheral_clk, MSTPCR0, 26, 0),
-	CLK("scif_fck", 1, &peripheral_clk, MSTPCR0, 25, 0),
-	CLK("scif_fck", 0, &peripheral_clk, MSTPCR0, 24, 0),
-	CLK("ssi_fck", 1, &peripheral_clk, MSTPCR0, 21, 0),
-	CLK("ssi_fck", 0, &peripheral_clk, MSTPCR0, 20, 0),
-	CLK("hac_fck", 1, &peripheral_clk, MSTPCR0, 17, 0),
-	CLK("hac_fck", 0, &peripheral_clk, MSTPCR0, 16, 0),
-	CLK("mmcif_fck", -1, &peripheral_clk, MSTPCR0, 13, 0),
-	CLK("flctl_fck", -1, &peripheral_clk, MSTPCR0, 12, 0),
-	CLK("tmu345_fck", -1, &peripheral_clk, MSTPCR0, 9, 0),
-	CLK("tmu012_fck", -1, &peripheral_clk, MSTPCR0, 8, 0),
-	CLK("siof_fck", -1, &peripheral_clk, MSTPCR0, 3, 0),
-	CLK("hspi_fck", -1, &peripheral_clk, MSTPCR0, 2, 0),
+	CLK("scif_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0),
+	CLK("scif_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0),
+	CLK("scif_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0),
+	CLK("scif_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0),
+	CLK("scif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0),
+	CLK("scif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0),
+	CLK("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0),
+	CLK("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0),
+	CLK("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0),
+	CLK("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0),
+	CLK("mmcif_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 13, 0),
+	CLK("flctl_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 12, 0),
+	CLK("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0),
+	CLK("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0),
+	CLK("siof_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 3, 0),
+	CLK("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0),
 
 	/* MSTPCR1 */
 	CLK("hudi_fck", -1, NULL, MSTPCR1, 19, 0),
@@ -260,6 +174,11 @@ int __init arch_clk_init(void)
 
 	for (i = 0; i < ARRAY_SIZE(clks); i++)
 		ret |= clk_register(clks[i]);
+
+	if (!ret)
+		ret = sh_clk_cpg_div4_register(div4_clks, DIV4_NR,
+					       div4_data, &div4_table);
+
 	for (i = 0; i < ARRAY_SIZE(mstpcr_clks); i++)
 		ret |= clk_register(&mstpcr_clks[i]);
 

[-- Attachment #3: linux-2.6.31-pre-sh-clk-cpg-div4-sh7785-b-20090528.patch --]
[-- Type: application/octet-stream, Size: 10598 bytes --]

--- 0001/arch/sh/include/asm/clock.h
+++ work/arch/sh/include/asm/clock.h	2009-05-28 13:31:34.000000000 +0900
@@ -3,6 +3,7 @@
 
 #include <linux/list.h>
 #include <linux/seq_file.h>
+#include <linux/cpufreq.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 
@@ -117,4 +118,43 @@ long clk_rate_table_round(struct clk *cl
 			  struct cpufreq_frequency_table *freq_table,
 			  unsigned long rate);
 
+
+/* helper data structures and function for 4-bit width clock divisors */
+struct sh_clk_cpg_div4_table {
+	unsigned int div[1 << 4];
+	unsigned int mult[1 << 4];
+	struct clk_div_mult_table t;
+};
+
+struct sh_clk_cpg_div4 {
+	struct clk clk;
+
+	/* allowable divisor bitmap */
+	unsigned long div_bitmap;
+
+	/* Supportable frequencies + termination entry */
+	struct cpufreq_frequency_table freq_table[(1 << 4)+1];
+};
+
+#define SH_CLK_CPG_DIV4(_name, _reg, _shift, _div_bitmap)	\
+{								\
+	.clk = {						\
+		.name = _name,					\
+		.enable_reg = (void __iomem *)_reg,		\
+		.enable_bit = _shift,				\
+	},							\
+	.div_bitmap     = _div_bitmap,				\
+	.freq_table[0]  = {					\
+		.index = 0,					\
+		.frequency = CPUFREQ_TABLE_END,			\
+	},							\
+}
+
+int sh_clk_cpg_div4_register(struct sh_clk_cpg_div4 *div4,
+			     int nr,
+			     struct clk *parent,
+			     struct sh_clk_cpg_div4_table *table);
+
+
+
 #endif /* __ASM_SH_CLOCK_H */
--- 0001/arch/sh/kernel/cpu/clock-cpg.c
+++ work/arch/sh/kernel/cpu/clock-cpg.c	2009-05-28 13:41:28.000000000 +0900
@@ -1,7 +1,76 @@
 #include <linux/clk.h>
 #include <linux/compiler.h>
+#include <linux/io.h>
 #include <asm/clock.h>
 
+
+static struct sh_clk_cpg_div4 *clk2div4(struct clk *clk)
+{
+	return (void *)clk - offsetof(struct sh_clk_cpg_div4, clk);
+}
+
+static unsigned long sh_clk_cpg_div4_recalc(struct clk *clk)
+{
+	struct sh_clk_cpg_div4 *div4 = clk2div4(clk);
+	struct sh_clk_cpg_div4_table *table = clk->priv;
+	unsigned int idx;
+
+	clk_rate_table_build(clk, div4->freq_table, ARRAY_SIZE(table->div),
+			     &table->t, &div4->div_bitmap);
+
+	idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
+
+	return div4->freq_table[idx].frequency;
+}
+
+static long sh_clk_cpg_div4_round_rate(struct clk *clk, unsigned long rate)
+{
+	return clk_rate_table_round(clk, clk2div4(clk)->freq_table, rate);
+}
+
+static struct clk_ops sh_clk_cpg_div4_clk_ops = {
+	.recalc		= sh_clk_cpg_div4_recalc,
+	.round_rate	= sh_clk_cpg_div4_round_rate,
+};
+
+int __init sh_clk_cpg_div4_register(struct sh_clk_cpg_div4 *div4,
+				    int nr,
+				    struct clk *parent,
+				    struct sh_clk_cpg_div4_table *table)
+{
+	struct clk *clkp;
+	struct sh_clk_cpg_div4 *div4p;
+	int ret = 0;
+	int k;
+
+	for (k = 0; k < ARRAY_SIZE(table->div); k++) {
+		if (!table->div[k])
+			table->div[k] = 1;
+		if (!table->mult[k])
+			table->mult[k] = 1;
+	}
+
+	table->t.divisors = table->div;
+	table->t.nr_divisors = ARRAY_SIZE(table->div);
+	table->t.multipliers = table->mult;
+	table->t.nr_multipliers = ARRAY_SIZE(table->mult);
+
+	for (k = 0; !ret && (k < nr); k++) {
+		div4p = div4 + k;
+		clkp = &div4p->clk;
+
+		clkp->id = -1;
+		clkp->ops = &sh_clk_cpg_div4_clk_ops;
+		clkp->parent = parent;
+		clkp->priv = table;
+		clkp->flags = CLK_ENABLE_ON_INIT;
+
+		ret = clk_register(clkp);
+	}
+
+	return ret;
+}
+
 #ifdef CONFIG_SH_CLK_CPG_LEGACY
 static struct clk master_clk = {
 	.name		= "master_clk",
--- 0001/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
+++ work/arch/sh/kernel/cpu/sh4a/clock-sh7785.c	2009-05-28 13:32:37.000000000 +0900
@@ -17,65 +17,14 @@
 #include <asm/clock.h>
 #include <asm/freq.h>
 
-static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
-			       24, 32, 36, 48 };
-
-static struct clk_div_mult_table cpg_div = {
-	.divisors = div2,
-	.nr_divisors = ARRAY_SIZE(div2),
-};
-
-struct clk_priv {
-	unsigned int			shift;
-
-	/* allowable divisor bitmap */
-	unsigned long			div_bitmap;
-
-	/* Supportable frequencies + termination entry */
-	struct cpufreq_frequency_table	freq_table[ARRAY_SIZE(div2)+1];
-};
-
-#define FRQMR_CLK_DATA(_name, _shift, _div_bitmap)	\
-static struct clk_priv _name##_data = {			\
-	.shift		= _shift,			\
-	.div_bitmap	= _div_bitmap,			\
-							\
-	.freq_table[0]	= {				\
-		.index = 0,				\
-		.frequency = CPUFREQ_TABLE_END,		\
-	},						\
-}
-
-FRQMR_CLK_DATA(pfc,  0, 0x0f80);
-FRQMR_CLK_DATA(s3fc, 4, 0x0ff0);
-FRQMR_CLK_DATA(s2fc, 8, 0x0030);
-FRQMR_CLK_DATA(mfc, 12, 0x000c);
-FRQMR_CLK_DATA(bfc, 16, 0x0fe0);
-FRQMR_CLK_DATA(sfc, 20, 0x000c);
-FRQMR_CLK_DATA(ufc, 24, 0x000c);
-FRQMR_CLK_DATA(ifc, 28, 0x000e);
-
-static unsigned long frqmr_recalc(struct clk *clk)
-{
-	struct clk_priv *data = clk->priv;
-	unsigned int idx = (__raw_readl(FRQMR1) >> data->shift) & 0x000f;
-
-	clk_rate_table_build(clk, data->freq_table, ARRAY_SIZE(div2),
-			     &cpg_div, &data->div_bitmap);
-	
-	return data->freq_table[idx].frequency;
-}
-
-static long frqmr_round_rate(struct clk *clk, unsigned long rate)
-{
-	struct clk_priv *data = clk->priv;
-
-	return clk_rate_table_round(clk, data->freq_table, rate);
-}
-
-static struct clk_ops frqmr_clk_ops = {
-	.recalc			= frqmr_recalc,
-	.round_rate		= frqmr_round_rate,
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+	.name		= "extal",
+	.id		= -1,
+	.rate		= 33333333,
 };
 
 static unsigned long pll_recalc(struct clk *clk)
@@ -92,16 +41,6 @@ static struct clk_ops pll_clk_ops = {
 	.recalc		= pll_recalc,
 };
 
-/*
- * Default rate for the root input clock, reset this with clk_set_rate()
- * from the platform code.
- */
-static struct clk extal_clk = {
-	.name		= "extal",
-	.id		= -1,
-	.rate		= 33333333,
-};
-
 static struct clk pll_clk = {
 	.name		= "pll_clk",
 	.id		= -1,
@@ -110,87 +49,27 @@ static struct clk pll_clk = {
 	.flags		= CLK_ENABLE_ON_INIT,
 };
 
-static struct clk cpu_clk = {
-	.name		= "cpu_clk",		/* Ick */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &ifc_data,
-};
-
-static struct clk shyway_clk = {
-	.name		= "shyway_clk",		/* SHck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &sfc_data,
-};
-
-static struct clk peripheral_clk = {
-	.name		= "peripheral_clk",	/* Pck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &pfc_data,
-};
-
-static struct clk ddr_clk = {
-	.name		= "ddr_clk",		/* DDRck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &mfc_data,
-};
-
-static struct clk bus_clk = {
-	.name		= "bus_clk",		/* Bck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &bfc_data,
+static struct clk *clks[] = {
+	&extal_clk,
+	&pll_clk,
 };
 
-static struct clk ga_clk = {
-	.name		= "ga_clk",		/* GAck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.priv		= &s2fc_data,
+struct sh_clk_cpg_div4_table div4_table = {
+	.div = { 1, 2, 4, 6, 8, 12, 16, 18, 24, 32, 36, 48, },
 };
 
-static struct clk du_clk = {
-	.name		= "du_clk",		/* DUck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.priv		= &s3fc_data,
-};
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_GA,
+	DIV4_DU, DIV4_P, DIV4_NR };
 
-static struct clk umem_clk = {
-	.name		= "umem_clk",		/* uck */
-	.id		= -1,
-	.ops		= &frqmr_clk_ops,
-	.parent		= &pll_clk,
-	.flags		= CLK_ENABLE_ON_INIT,
-	.priv		= &ufc_data,
-};
-
-static struct clk *clks[] = {
-	&extal_clk,
-	&pll_clk,
-	&cpu_clk,
-	&shyway_clk,
-	&peripheral_clk,
-	&ddr_clk,
-	&bus_clk,
-	&ga_clk,
-	&du_clk,
-	&umem_clk,
+struct sh_clk_cpg_div4 div4[DIV4_NR] = {
+	[DIV4_P] = SH_CLK_CPG_DIV4("peripheral_clk", FRQMR1, 0, 0x0f80),
+	[DIV4_DU] = SH_CLK_CPG_DIV4("du_clk", FRQMR1, 4, 0x0ff0),
+	[DIV4_GA] = SH_CLK_CPG_DIV4("ga_clk", FRQMR1, 8, 0x0030),
+	[DIV4_DDR] = SH_CLK_CPG_DIV4("ddr_clk", FRQMR1, 12, 0x000c),
+	[DIV4_B] = SH_CLK_CPG_DIV4("bus_clk", FRQMR1, 16, 0x0fe0),
+	[DIV4_SH] = SH_CLK_CPG_DIV4("shyway_clk", FRQMR1, 20, 0x000c),
+	[DIV4_U] = SH_CLK_CPG_DIV4("umem_clk", FRQMR1, 24, 0x000c),
+	[DIV4_I] = SH_CLK_CPG_DIV4("cpu_clk", FRQMR1, 28, 0x000e),
 };
 
 static int mstpcr_clk_enable(struct clk *clk)
@@ -229,22 +108,22 @@ static struct clk_ops mstpcr_clk_ops = {
 
 static struct clk mstpcr_clks[] = {
 	/* MSTPCR0 */
-	CLK("scif_fck", 5, &peripheral_clk, MSTPCR0, 29, 0),
-	CLK("scif_fck", 4, &peripheral_clk, MSTPCR0, 28, 0),
-	CLK("scif_fck", 3, &peripheral_clk, MSTPCR0, 27, 0),
-	CLK("scif_fck", 2, &peripheral_clk, MSTPCR0, 26, 0),
-	CLK("scif_fck", 1, &peripheral_clk, MSTPCR0, 25, 0),
-	CLK("scif_fck", 0, &peripheral_clk, MSTPCR0, 24, 0),
-	CLK("ssi_fck", 1, &peripheral_clk, MSTPCR0, 21, 0),
-	CLK("ssi_fck", 0, &peripheral_clk, MSTPCR0, 20, 0),
-	CLK("hac_fck", 1, &peripheral_clk, MSTPCR0, 17, 0),
-	CLK("hac_fck", 0, &peripheral_clk, MSTPCR0, 16, 0),
-	CLK("mmcif_fck", -1, &peripheral_clk, MSTPCR0, 13, 0),
-	CLK("flctl_fck", -1, &peripheral_clk, MSTPCR0, 12, 0),
-	CLK("tmu345_fck", -1, &peripheral_clk, MSTPCR0, 9, 0),
-	CLK("tmu012_fck", -1, &peripheral_clk, MSTPCR0, 8, 0),
-	CLK("siof_fck", -1, &peripheral_clk, MSTPCR0, 3, 0),
-	CLK("hspi_fck", -1, &peripheral_clk, MSTPCR0, 2, 0),
+	CLK("scif_fck", 5, &div4[DIV4_P].clk, MSTPCR0, 29, 0),
+	CLK("scif_fck", 4, &div4[DIV4_P].clk, MSTPCR0, 28, 0),
+	CLK("scif_fck", 3, &div4[DIV4_P].clk, MSTPCR0, 27, 0),
+	CLK("scif_fck", 2, &div4[DIV4_P].clk, MSTPCR0, 26, 0),
+	CLK("scif_fck", 1, &div4[DIV4_P].clk, MSTPCR0, 25, 0),
+	CLK("scif_fck", 0, &div4[DIV4_P].clk, MSTPCR0, 24, 0),
+	CLK("ssi_fck", 1, &div4[DIV4_P].clk, MSTPCR0, 21, 0),
+	CLK("ssi_fck", 0, &div4[DIV4_P].clk, MSTPCR0, 20, 0),
+	CLK("hac_fck", 1, &div4[DIV4_P].clk, MSTPCR0, 17, 0),
+	CLK("hac_fck", 0, &div4[DIV4_P].clk, MSTPCR0, 16, 0),
+	CLK("mmcif_fck", -1, &div4[DIV4_P].clk, MSTPCR0, 13, 0),
+	CLK("flctl_fck", -1, &div4[DIV4_P].clk, MSTPCR0, 12, 0),
+	CLK("tmu345_fck", -1, &div4[DIV4_P].clk, MSTPCR0, 9, 0),
+	CLK("tmu012_fck", -1, &div4[DIV4_P].clk, MSTPCR0, 8, 0),
+	CLK("siof_fck", -1, &div4[DIV4_P].clk, MSTPCR0, 3, 0),
+	CLK("hspi_fck", -1, &div4[DIV4_P].clk, MSTPCR0, 2, 0),
 
 	/* MSTPCR1 */
 	CLK("hudi_fck", -1, NULL, MSTPCR1, 19, 0),
@@ -260,6 +139,11 @@ int __init arch_clk_init(void)
 
 	for (i = 0; i < ARRAY_SIZE(clks); i++)
 		ret |= clk_register(clks[i]);
+
+	if (!ret)
+		ret = sh_clk_cpg_div4_register(div4, DIV4_NR,
+					       &pll_clk, &div4_table);
+
 	for (i = 0; i < ARRAY_SIZE(mstpcr_clks); i++)
 		ret |= clk_register(&mstpcr_clks[i]);
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-05-28  6:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-28  4:59 [PATCH][RFC] sh: helper code for 4-bit divisors Magnus Damm
2009-05-28  5:25 ` Paul Mundt
2009-05-28  5:54 ` Magnus Damm
2009-05-28  6:54 ` Paul Mundt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox