lkml.org 
[lkml]   [2010]   [May]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC PATCH] ARM: Add SSI Clock Adjustment for i.MX27 TO2
Date
This adds support for adjusting the SSI clocks using the generic clock
infrastructure.

Known bug:
The generated clock is approximately 1/4 of what is requested.
I'm not sure if this is due to a bug in reading MCLK, or
something else dividing the clock down. Hence the printk's in
get_rate_ssix, and the patch's "RFC" status.

This should open the door to using the SSI ports on the i.MX27 in I²S
Master mode amongst other things.

Signed-off-by: Stuart Longland <redhatter@gentoo.org>
---
arch/arm/mach-mx2/clock_imx27.c | 75 +++++++++++++++++++++++++++++++++++++--
1 files changed, 72 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c
index 0f0823c..48a4f62 100644
--- a/arch/arm/mach-mx2/clock_imx27.c
+++ b/arch/arm/mach-mx2/clock_imx27.c
@@ -244,12 +244,59 @@ static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)

parent_rate = clk_get_rate(clk->parent);

+ printk("%s: parent = %ld Hz; raw pdf = %ld\n",
+ __FUNCTION__, parent_rate, pdf );
+
if (mx27_revision() >= CHIP_REV_2_0)
pdf += 4; /* MX27 TO2+ */
else
pdf = (pdf < 2) ? 124UL : pdf; /* MX21 & MX27 TO1 */

- return 2UL * parent_rate / pdf;
+ printk("%s: parent = %ld Hz; pdf = %ld\n",
+ __FUNCTION__, parent_rate, pdf );
+
+ return (2UL * parent_rate) / pdf;
+}
+
+static unsigned long set_rate_ssix(struct clk *clk, unsigned long rate)
+{
+ unsigned long parent_rate;
+ unsigned long pdf;
+
+ parent_rate = clk_get_rate(clk->parent);
+ pdf = (2UL * parent_rate) / rate;
+
+ if (mx27_revision() >= CHIP_REV_2_0)
+ pdf -= 4; /* MX27 TO2+ */
+
+ /* TODO: Not sure how to handle other CPU types */
+#if 0
+ else
+ pdf = (pdf < 2) ? 124UL : pdf; /* MX21 & MX27 TO1 */
+#endif
+ printk("%s: %ld Hz => %ld; pdf = %ld\n",
+ __FUNCTION__, parent_rate, rate, pdf );
+
+ return pdf & 0x3f;
+}
+
+static unsigned long round_rate_ssix(struct clk *clk, unsigned long rate)
+{
+ unsigned long div;
+ unsigned long parent_rate = clk_get_rate(clk->parent);
+
+ div = (2UL * parent_rate) / rate;
+ printk("%s: 2* %ld Hz / %ld Hz = %ld\n",
+ __FUNCTION__, parent_rate, rate, div );
+
+ if ( ( div < 4 ) || ( div > 67 ) )
+ /* Corresponds to divider value < 2 or > 33.5 */
+ return -EINVAL;
+
+ printk("%s: 2* %ld Hz / %ld = %ld\n",
+ __FUNCTION__, parent_rate, div, (2UL*parent_rate) / div);
+
+ return (2UL * parent_rate) / div;
}

static unsigned long get_rate_ssi1(struct clk *clk)
@@ -257,11 +304,33 @@ static unsigned long get_rate_ssi1(struct clk *clk)
return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
}

+static int set_rate_ssi1(struct clk *clk, unsigned long rate)
+{
+ __raw_writel( set_rate_ssix(clk, rate) << 16, CCM_PCDR0 );
+ return 0;
+}
+
+static unsigned long round_rate_ssi1(struct clk *clk, unsigned long rate)
+{
+ return round_rate_ssix(clk, rate);
+}
+
static unsigned long get_rate_ssi2(struct clk *clk)
{
return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
}

+static int set_rate_ssi2(struct clk *clk, unsigned long rate)
+{
+ __raw_writel( set_rate_ssix(clk, rate) << 26, CCM_PCDR0 );
+ return 0;
+}
+
+static unsigned long round_rate_ssi2(struct clk *clk, unsigned long rate)
+{
+ return round_rate_ssix(clk, rate);
+}
+
static unsigned long get_rate_nfc(struct clk *clk)
{
unsigned long nfc_pdf;
@@ -564,8 +633,8 @@ DEFINE_CLOCK(cspi1_clk1, 0, PCCR0, 31, NULL, NULL, &ipg_clk);

DEFINE_CLOCK(mstick_clk, 0, PCCR1, 2, NULL, &mstick_clk1, &ipg_clk);
DEFINE_CLOCK(nfc_clk, 0, PCCR1, 3, get_rate_nfc, NULL, &cpu_clk);
-DEFINE_CLOCK(ssi2_clk, 1, PCCR1, 4, get_rate_ssi2, &ssi2_clk1, &mpll_main2_clk);
-DEFINE_CLOCK(ssi1_clk, 0, PCCR1, 5, get_rate_ssi1, &ssi1_clk1, &mpll_main2_clk);
+DEFINE_CLOCK1(ssi2_clk, 1, PCCR1, 4, ssi2, &ssi2_clk1, &mpll_main2_clk);
+DEFINE_CLOCK1(ssi1_clk, 0, PCCR1, 5, ssi1, &ssi1_clk1, &mpll_main2_clk);
DEFINE_CLOCK(vpu_clk, 0, PCCR1, 6, get_rate_vpu, &vpu_clk1, &mpll_main2_clk);
DEFINE_CLOCK1(per4_clk, 3, PCCR1, 7, per, NULL, &mpll_main2_clk);
DEFINE_CLOCK1(per3_clk, 2, PCCR1, 8, per, NULL, &mpll_main2_clk);
--
1.6.4.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2010-05-31 04:09    [W:0.033 / U:3.332 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site