summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2009-03-19 17:46:48 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2009-03-19 18:23:57 +0100
commit8b75c20a41504824f911a1e75f60a586acc587fc (patch)
treef98f05aacbbb8d5442809e3bd34e75dcd244d89c /arch
parent7166742b04ff7e56e816c6d14df1906ad31f1334 (diff)
downloadbarebox-8b75c20a41504824f911a1e75f60a586acc587fc.tar.gz
barebox-8b75c20a41504824f911a1e75f60a586acc587fc.tar.xz
add clko support for i.mx35
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/Kconfig2
-rw-r--r--arch/arm/mach-imx/clko.c59
-rw-r--r--arch/arm/mach-imx/speed-imx27.c37
-rw-r--r--arch/arm/mach-imx/speed-imx35.c74
4 files changed, 128 insertions, 44 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 763a0051c9..447a2c1ff0 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -26,7 +26,7 @@ endmenu
menu "i.MX specific settings "
config IMX_CLKO
bool "clko command"
- depends on ARCH_IMX27
+ depends on ARCH_IMX27 || ARCH_IMX35
help
The i.MX SoCs have a Pin which can output different reference frequencies.
Say y here if you want to have the clko command which lets you select the
diff --git a/arch/arm/mach-imx/clko.c b/arch/arm/mach-imx/clko.c
index 4eaf3691ef..bee1ce20f2 100644
--- a/arch/arm/mach-imx/clko.c
+++ b/arch/arm/mach-imx/clko.c
@@ -2,10 +2,11 @@
#include <command.h>
#include <getopt.h>
#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
static int do_clko (cmd_tbl_t *cmdtp, int argc, char *argv[])
{
- int opt, div = 0, src = -2;
+ int opt, div = 0, src = -2, ret;
getopt_reset();
@@ -26,33 +27,26 @@ static int do_clko (cmd_tbl_t *cmdtp, int argc, char *argv[])
}
if (src == -1) {
- PCDR0 &= ~(1 << 25);
+ imx_clko_set_src(-1);
return 0;
}
- if (src != -2) {
- ulong ccsr;
- ccsr = CCSR & ~0x1f;
- ccsr |= src & 0x1f;
- CCSR = ccsr;
- }
+ if (src != -2)
+ imx_clko_set_src(src);
if (div != 0) {
- ulong pcdr;
- div--;
- pcdr = PCDR0 & ~(7 << 22);
- pcdr |= (div & 0x7) << 22;
- PCDR0 = pcdr;
+ ret = imx_clko_set_div(div);
+ if (ret != div)
+ printf("limited divider to %d\n", ret);
}
- PCDR0 |= (1 << 25);
return 0;
}
static __maybe_unused char cmd_clko_help[] =
"Usage: clko [OPTION]...\n"
"Route different signals to the i.MX clko pin\n"
-" -d <div> Divider (1..8)\n"
+" -d <div> Divider\n"
" -s <source> Clock select. See Ref. Manual for valid sources. Use -1\n"
" for disabling clock output\n";
@@ -63,3 +57,38 @@ U_BOOT_CMD_START(clko)
U_BOOT_CMD_HELP(cmd_clko_help)
U_BOOT_CMD_END
+
+static int do_mcpy_test (cmd_tbl_t *cmdtp, int argc, char *argv[])
+{
+ unsigned long src, dest, count, end;
+
+ if (argc < 4)
+ return 1;
+
+ dest = simple_strtoul(argv[1], NULL, 0);
+ src = simple_strtoul(argv[2], NULL, 0);
+ count = simple_strtoul(argv[3], NULL, 0);
+
+ printf("copying from 0x%08x to 0x%08x (size %d)\n", src, dest, count);
+
+ end = src + count;
+
+ __asm__ __volatile__(
+ "copy_loop:\n"
+ "ldmia %1!, {r3-r10}\n"
+ "stmia %0!, {r3-r10}\n"
+ "cmp %1, %2\n"
+ "ble copy_loop\n"
+ :
+ : "r" (dest), "r" (src), "r" (end)
+ : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10");
+
+ return 0;
+}
+
+U_BOOT_CMD_START(mcpy_test)
+ .maxargs = CONFIG_MAXARGS,
+ .cmd = do_mcpy_test,
+ .usage = "Adjust CLKO setting",
+U_BOOT_CMD_END
+
diff --git a/arch/arm/mach-imx/speed-imx27.c b/arch/arm/mach-imx/speed-imx27.c
index 5a2cdf1707..f5f5ff3048 100644
--- a/arch/arm/mach-imx/speed-imx27.c
+++ b/arch/arm/mach-imx/speed-imx27.c
@@ -172,3 +172,40 @@ int imx_dump_clocks(void)
late_initcall(imx_dump_clocks);
+/*
+ * Set the divider of the CLKO pin. Returns
+ * the new divider (which may be smaller
+ * than the desired one)
+ */
+int imx_clko_set_div(int div)
+{
+ ulong pcdr;
+ div--;
+ div &= 0x7;
+
+ pcdr = PCDR0 & ~(7 << 22);
+ pcdr |= div << 22;
+ PCDR0 = pcdr;
+
+ return div + 1;
+}
+
+/*
+ * Set the clock source for the CLKO pin
+ */
+void imx_clko_set_src(int src)
+{
+ unsigned long ccsr;
+
+ if (src < 0) {
+ PCDR0 &= ~(1 << 25);
+ return;
+ }
+
+ ccsr = CCSR & ~0x1f;
+ ccsr |= src & 0x1f;
+ CCSR = ccsr;
+
+ PCDR0 |= (1 << 25);
+}
+
diff --git a/arch/arm/mach-imx/speed-imx35.c b/arch/arm/mach-imx/speed-imx35.c
index f9a28e698c..a16c0fa70d 100644
--- a/arch/arm/mach-imx/speed-imx35.c
+++ b/arch/arm/mach-imx/speed-imx35.c
@@ -56,34 +56,17 @@ static struct arm_ahb_div clk_consumer[] = {
{ .arm = 0, .ahb = 0, .sel = 0},
};
-static struct arm_ahb_div clk_automotive[] = {
- { .arm = 1, .ahb = 3, .sel = 0},
- { .arm = 1, .ahb = 2, .sel = 1},
- { .arm = 2, .ahb = 1, .sel = 1},
- { .arm = 0, .ahb = 0, .sel = 0},
- { .arm = 1, .ahb = 6, .sel = 0},
- { .arm = 1, .ahb = 4, .sel = 1},
- { .arm = 2, .ahb = 2, .sel = 1},
- { .arm = 0, .ahb = 0, .sel = 0},
-};
-
unsigned long imx_get_armclk(void)
{
unsigned long pdr0 = readl(IMX_CCM_BASE + CCM_PDR0);
struct arm_ahb_div *aad;
unsigned long fref = imx_get_mpllclk();
- if (pdr0 & PDR0_AUTO_CON) {
- /* consumer path is selected */
- aad = &clk_consumer[(pdr0 >> 16) & 0xf];
- if (aad->sel)
- fref = fref * 2 / 3;
- } else {
- /* auto path is selected */
- aad = &clk_automotive[(pdr0 >> 9) & 0x7];
- if (aad->sel)
- fref = fref * 3 / 4;
- }
+ /* consumer path is selected */
+ aad = &clk_consumer[(pdr0 >> 16) & 0xf];
+ if (aad->sel)
+ fref = fref * 2 / 3;
+
return fref / aad->arm;
}
@@ -93,12 +76,7 @@ unsigned long imx_get_ahbclk(void)
struct arm_ahb_div *aad;
unsigned long fref = imx_get_mpllclk();
- if (pdr0 & PDR0_AUTO_CON)
- /* consumer path is selected */
- aad = &clk_consumer[(pdr0 >> 16) & 0xf];
- else
- /* auto path is selected */
- aad = &clk_automotive[(pdr0 >> 9) & 0x7];
+ aad = &clk_consumer[(pdr0 >> 16) & 0xf];
return fref / aad->ahb;
}
@@ -164,3 +142,43 @@ static int imx_dump_clocks(void)
}
late_initcall(imx_dump_clocks);
+
+/*
+ * Set the divider of the CLKO pin. Returns
+ * the new divider (which may be smaller
+ * than the desired one)
+ */
+int imx_clko_set_div(int div)
+{
+ unsigned long cosr = readl(IMX_CCM_BASE + CCM_COSR);
+
+ div -= 1;
+ div &= 0x3f;
+
+ cosr &= ~(0x3f << 10);
+ cosr |= div << 10;
+
+ return div + 1;
+}
+
+/*
+ * Set the clock source for the CLKO pin
+ */
+void imx_clko_set_src(int src)
+{
+ unsigned long cosr = readl(IMX_CCM_BASE + CCM_COSR);
+
+ if (src < 0) {
+ cosr &= ~(1 << 5);
+ writel(cosr, IMX_CCM_BASE + CCM_COSR);
+ return;
+ }
+
+ cosr |= 1 << 5;
+ cosr &= ~0x1f;
+ cosr &= ~(1 << 6);
+ cosr |= src & 0x1f;
+
+ writel(cosr, IMX_CCM_BASE + CCM_COSR);
+}
+