summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx3
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-03-31 01:53:32 +0400
committerIngo Molnar <mingo@elte.hu>2009-03-31 01:53:32 +0400
commit65fb0d23fcddd8697c871047b700c78817bdaa43 (patch)
tree119e6e5f276622c4c862f6c9b6d795264ba1603a /arch/arm/mach-mx3
parent8c083f081d0014057901c68a0a3e0f8ca7ac8d23 (diff)
parentdfbbe89e197a77f2c8046a51c74e33e35f878080 (diff)
downloadlinux-65fb0d23fcddd8697c871047b700c78817bdaa43.tar.xz
Merge branch 'linus' into cpumask-for-linus
Conflicts: arch/x86/kernel/cpu/common.c
Diffstat (limited to 'arch/arm/mach-mx3')
-rw-r--r--arch/arm/mach-mx3/Kconfig36
-rw-r--r--arch/arm/mach-mx3/Makefile8
-rw-r--r--arch/arm/mach-mx3/clock-imx35.c487
-rw-r--r--arch/arm/mach-mx3/clock.c959
-rw-r--r--arch/arm/mach-mx3/crm_regs.h153
-rw-r--r--arch/arm/mach-mx3/devices.c193
-rw-r--r--arch/arm/mach-mx3/devices.h8
-rw-r--r--arch/arm/mach-mx3/iomux.c88
-rw-r--r--arch/arm/mach-mx3/mm.c37
-rw-r--r--arch/arm/mach-mx3/mx31ads.c328
-rw-r--r--arch/arm/mach-mx3/mx31lite.c13
-rw-r--r--arch/arm/mach-mx3/mx31moboard-devboard.c48
-rw-r--r--arch/arm/mach-mx3/mx31moboard-marxbot.c37
-rw-r--r--arch/arm/mach-mx3/mx31moboard.c74
-rw-r--r--arch/arm/mach-mx3/mx31pdk.c44
-rw-r--r--arch/arm/mach-mx3/pcm037.c138
-rw-r--r--arch/arm/mach-mx3/qong.c312
17 files changed, 1894 insertions, 1069 deletions
diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index e79659e8176e..d6235583e979 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -1,21 +1,40 @@
-menu "MX3 Options"
- depends on ARCH_MX3
+if ARCH_MX3
+
+config ARCH_MX31
+ bool
+
+config ARCH_MX35
+ bool
+
+comment "MX3 platforms:"
config MACH_MX31ADS
bool "Support MX31ADS platforms"
+ select ARCH_MX31
default y
help
Include support for MX31ADS platform. This includes specific
configurations for the board and its peripherals.
+config MACH_MX31ADS_WM1133_EV1
+ bool "Support Wolfson Microelectronics 1133-EV1 module"
+ depends on MACH_MX31ADS
+ select MFD_WM8350_CONFIG_MODE_0
+ select MFD_WM8352_CONFIG_MODE_0
+ help
+ Include support for the Wolfson Microelectronics 1133-EV1 PMU
+ and audio module for the MX31ADS platform.
+
config MACH_PCM037
- bool "Support Phytec pcm037 platforms"
+ bool "Support Phytec pcm037 (i.MX31) platforms"
+ select ARCH_MX31
help
Include support for Phytec pcm037 platform. This includes
specific configurations for the board and its peripherals.
config MACH_MX31LITE
bool "Support MX31 LITEKIT (LogicPD)"
+ select ARCH_MX31
default n
help
Include support for MX31 LITEKIT platform. This includes specific
@@ -23,6 +42,7 @@ config MACH_MX31LITE
config MACH_MX31_3DS
bool "Support MX31PDK (3DS)"
+ select ARCH_MX31
default n
help
Include support for MX31PDK (3DS) platform. This includes specific
@@ -30,10 +50,18 @@ config MACH_MX31_3DS
config MACH_MX31MOBOARD
bool "Support mx31moboard platforms (EPFL Mobots group)"
+ select ARCH_MX31
default n
help
Include support for mx31moboard platform. This includes specific
configurations for the board and its peripherals.
-endmenu
+config MACH_QONG
+ bool "Support Dave/DENX QongEVB-LITE platform"
+ select ARCH_MX31
+ default n
+ help
+ Include support for Dave/DENX QongEVB-LITE platform. This includes
+ specific configurations for the board and its peripherals.
+endif
diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile
index 5a151540fe83..272c8a953b30 100644
--- a/arch/arm/mach-mx3/Makefile
+++ b/arch/arm/mach-mx3/Makefile
@@ -4,9 +4,13 @@
# Object file lists.
-obj-y := mm.o clock.o devices.o iomux.o
+obj-y := mm.o devices.o
+obj-$(CONFIG_ARCH_MX31) += clock.o iomux.o
+obj-$(CONFIG_ARCH_MX35) += clock-imx35.o
obj-$(CONFIG_MACH_MX31ADS) += mx31ads.o
obj-$(CONFIG_MACH_MX31LITE) += mx31lite.o
obj-$(CONFIG_MACH_PCM037) += pcm037.o
obj-$(CONFIG_MACH_MX31_3DS) += mx31pdk.o
-obj-$(CONFIG_MACH_MX31MOBOARD) += mx31moboard.o
+obj-$(CONFIG_MACH_MX31MOBOARD) += mx31moboard.o mx31moboard-devboard.o \
+ mx31moboard-marxbot.o
+obj-$(CONFIG_MACH_QONG) += qong.o
diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c
new file mode 100644
index 000000000000..53a112d4e04a
--- /dev/null
+++ b/arch/arm/mach-mx3/clock-imx35.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2009 by Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/clkdev.h>
+
+#include <mach/clock.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+
+#define CCM_BASE IO_ADDRESS(CCM_BASE_ADDR)
+
+#define CCM_CCMR 0x00
+#define CCM_PDR0 0x04
+#define CCM_PDR1 0x08
+#define CCM_PDR2 0x0C
+#define CCM_PDR3 0x10
+#define CCM_PDR4 0x14
+#define CCM_RCSR 0x18
+#define CCM_MPCTL 0x1C
+#define CCM_PPCTL 0x20
+#define CCM_ACMR 0x24
+#define CCM_COSR 0x28
+#define CCM_CGR0 0x2C
+#define CCM_CGR1 0x30
+#define CCM_CGR2 0x34
+#define CCM_CGR3 0x38
+
+#ifdef HAVE_SET_RATE_SUPPORT
+static void calc_dividers(u32 div, u32 *pre, u32 *post, u32 maxpost)
+{
+ u32 min_pre, temp_pre, old_err, err;
+
+ min_pre = (div - 1) / maxpost + 1;
+ old_err = 8;
+
+ for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
+ if (div > (temp_pre * maxpost))
+ break;
+
+ if (div < (temp_pre * temp_pre))
+ continue;
+
+ err = div % temp_pre;
+
+ if (err == 0) {
+ *pre = temp_pre;
+ break;
+ }
+
+ err = temp_pre - err;
+
+ if (err < old_err) {
+ old_err = err;
+ *pre = temp_pre;
+ }
+ }
+
+ *post = (div + *pre - 1) / *pre;
+}
+
+/* get the best values for a 3-bit divider combined with a 6-bit divider */
+static void calc_dividers_3_6(u32 div, u32 *pre, u32 *post)
+{
+ if (div >= 512) {
+ *pre = 8;
+ *post = 64;
+ } else if (div >= 64) {
+ calc_dividers(div, pre, post, 64);
+ } else if (div <= 8) {
+ *pre = div;
+ *post = 1;
+ } else {
+ *pre = 1;
+ *post = div;
+ }
+}
+
+/* get the best values for two cascaded 3-bit dividers */
+static void calc_dividers_3_3(u32 div, u32 *pre, u32 *post)
+{
+ if (div >= 64) {
+ *pre = *post = 8;
+ } else if (div > 8) {
+ calc_dividers(div, pre, post, 8);
+ } else {
+ *pre = 1;
+ *post = div;
+ }
+}
+#endif
+
+static unsigned long get_rate_mpll(void)
+{
+ ulong mpctl = __raw_readl(CCM_BASE + CCM_MPCTL);
+
+ return mxc_decode_pll(mpctl, 24000000);
+}
+
+static unsigned long get_rate_ppll(void)
+{
+ ulong ppctl = __raw_readl(CCM_BASE + CCM_PPCTL);
+
+ return mxc_decode_pll(ppctl, 24000000);
+}
+
+struct arm_ahb_div {
+ unsigned char arm, ahb, sel;
+};
+
+static struct arm_ahb_div clk_consumer[] = {
+ { .arm = 1, .ahb = 4, .sel = 0},
+ { .arm = 1, .ahb = 3, .sel = 1},
+ { .arm = 2, .ahb = 2, .sel = 0},
+ { .arm = 0, .ahb = 0, .sel = 0},
+ { .arm = 0, .ahb = 0, .sel = 0},
+ { .arm = 0, .ahb = 0, .sel = 0},
+ { .arm = 4, .ahb = 1, .sel = 0},
+ { .arm = 1, .ahb = 5, .sel = 0},
+ { .arm = 1, .ahb = 8, .sel = 0},
+ { .arm = 1, .ahb = 6, .sel = 1},
+ { .arm = 2, .ahb = 4, .sel = 0},
+ { .arm = 0, .ahb = 0, .sel = 0},
+ { .arm = 0, .ahb = 0, .sel = 0},
+ { .arm = 0, .ahb = 0, .sel = 0},
+ { .arm = 4, .ahb = 2, .sel = 0},
+ { .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},
+};
+
+static unsigned long get_rate_arm(void)
+{
+ unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0);
+ struct arm_ahb_div *aad;
+ unsigned long fref = get_rate_mpll();
+
+ if (pdr0 & 1) {
+ /* consumer path */
+ aad = &clk_consumer[(pdr0 >> 16) & 0xf];
+ if (aad->sel)
+ fref = fref * 2 / 3;
+ } else {
+ /* auto path */
+ aad = &clk_automotive[(pdr0 >> 9) & 0x7];
+ if (aad->sel)
+ fref = fref * 3 / 4;
+ }
+ return fref / aad->arm;
+}
+
+static unsigned long get_rate_ahb(struct clk *clk)
+{
+ unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0);
+ struct arm_ahb_div *aad;
+ unsigned long fref = get_rate_mpll();
+
+ if (pdr0 & 1)
+ /* consumer path */
+ aad = &clk_consumer[(pdr0 >> 16) & 0xf];
+ else
+ /* auto path */
+ aad = &clk_automotive[(pdr0 >> 9) & 0x7];
+
+ return fref / aad->ahb;
+}
+
+static unsigned long get_rate_ipg(struct clk *clk)
+{
+ return get_rate_ahb(NULL) >> 1;
+}
+
+static unsigned long get_3_3_div(unsigned long in)
+{
+ return (((in >> 3) & 0x7) + 1) * ((in & 0x7) + 1);
+}
+
+static unsigned long get_rate_uart(struct clk *clk)
+{
+ unsigned long pdr3 = __raw_readl(CCM_BASE + CCM_PDR3);
+ unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4);
+ unsigned long div = get_3_3_div(pdr4 >> 10);
+
+ if (pdr3 & (1 << 14))
+ return get_rate_arm() / div;
+ else
+ return get_rate_ppll() / div;
+}
+
+static unsigned long get_rate_sdhc(struct clk *clk)
+{
+ unsigned long pdr3 = __raw_readl(CCM_BASE + CCM_PDR3);
+ unsigned long div, rate;
+
+ if (pdr3 & (1 << 6))
+ rate = get_rate_arm();
+ else
+ rate = get_rate_ppll();
+
+ switch (clk->id) {
+ default:
+ case 0:
+ div = pdr3 & 0x3f;
+ break;
+ case 1:
+ div = (pdr3 >> 8) & 0x3f;
+ break;
+ case 2:
+ div = (pdr3 >> 16) & 0x3f;
+ break;
+ }
+
+ return rate / get_3_3_div(div);
+}
+
+static unsigned long get_rate_mshc(struct clk *clk)
+{
+ unsigned long pdr1 = __raw_readl(CCM_BASE + CCM_PDR1);
+ unsigned long div1, div2, rate;
+
+ if (pdr1 & (1 << 7))
+ rate = get_rate_arm();
+ else
+ rate = get_rate_ppll();
+
+ div1 = (pdr1 >> 29) & 0x7;
+ div2 = (pdr1 >> 22) & 0x3f;
+
+ return rate / ((div1 + 1) * (div2 + 1));
+}
+
+static unsigned long get_rate_ssi(struct clk *clk)
+{
+ unsigned long pdr2 = __raw_readl(CCM_BASE + CCM_PDR2);
+ unsigned long div1, div2, rate;
+
+ if (pdr2 & (1 << 6))
+ rate = get_rate_arm();
+ else
+ rate = get_rate_ppll();
+
+ switch (clk->id) {
+ default:
+ case 0:
+ div1 = pdr2 & 0x3f;
+ div2 = (pdr2 >> 24) & 0x7;
+ break;
+ case 1:
+ div1 = (pdr2 >> 8) & 0x3f;
+ div2 = (pdr2 >> 27) & 0x7;
+ break;
+ }
+
+ return rate / ((div1 + 1) * (div2 + 1));
+}
+
+static unsigned long get_rate_csi(struct clk *clk)
+{
+ unsigned long pdr2 = __raw_readl(CCM_BASE + CCM_PDR2);
+ unsigned long rate;
+
+ if (pdr2 & (1 << 7))
+ rate = get_rate_arm();
+ else
+ rate = get_rate_ppll();
+
+ return rate / get_3_3_div((pdr2 >> 16) & 0x3f);
+}
+
+static unsigned long get_rate_ipg_per(struct clk *clk)
+{
+ unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0);
+ unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4);
+ unsigned long div1, div2;
+
+ if (pdr0 & (1 << 26)) {
+ div1 = (pdr4 >> 19) & 0x7;
+ div2 = (pdr4 >> 16) & 0x7;
+ return get_rate_arm() / ((div1 + 1) * (div2 + 1));
+ } else {
+ div1 = (pdr0 >> 12) & 0x7;
+ return get_rate_ahb(NULL) / div1;
+ }
+}
+
+static int clk_cgr_enable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(clk->enable_reg);
+ reg |= 3 << clk->enable_shift;
+ __raw_writel(reg, clk->enable_reg);
+
+ return 0;
+}
+
+static void clk_cgr_disable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(3 << clk->enable_shift);
+ __raw_writel(reg, clk->enable_reg);
+}
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr) \
+ static struct clk name = { \
+ .id = i, \
+ .enable_reg = CCM_BASE + er, \
+ .enable_shift = es, \
+ .get_rate = gr, \
+ .set_rate = sr, \
+ .enable = clk_cgr_enable, \
+ .disable = clk_cgr_disable, \
+ }
+
+DEFINE_CLOCK(asrc_clk, 0, CCM_CGR0, 0, NULL, NULL);
+DEFINE_CLOCK(ata_clk, 0, CCM_CGR0, 2, get_rate_ipg, NULL);
+DEFINE_CLOCK(audmux_clk, 0, CCM_CGR0, 4, NULL, NULL);
+DEFINE_CLOCK(can1_clk, 0, CCM_CGR0, 6, get_rate_ipg, NULL);
+DEFINE_CLOCK(can2_clk, 1, CCM_CGR0, 8, get_rate_ipg, NULL);
+DEFINE_CLOCK(cspi1_clk, 0, CCM_CGR0, 10, get_rate_ipg, NULL);
+DEFINE_CLOCK(cspi2_clk, 1, CCM_CGR0, 12, get_rate_ipg, NULL);
+DEFINE_CLOCK(ect_clk, 0, CCM_CGR0, 14, get_rate_ipg, NULL);
+DEFINE_CLOCK(edio_clk, 0, CCM_CGR0, 16, NULL, NULL);
+DEFINE_CLOCK(emi_clk, 0, CCM_CGR0, 18, get_rate_ipg, NULL);
+DEFINE_CLOCK(epit1_clk, 0, CCM_CGR0, 20, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(epit2_clk, 1, CCM_CGR0, 22, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(esai_clk, 0, CCM_CGR0, 24, NULL, NULL);
+DEFINE_CLOCK(esdhc1_clk, 0, CCM_CGR0, 26, get_rate_sdhc, NULL);
+DEFINE_CLOCK(esdhc2_clk, 1, CCM_CGR0, 28, get_rate_sdhc, NULL);
+DEFINE_CLOCK(esdhc3_clk, 2, CCM_CGR0, 30, get_rate_sdhc, NULL);
+
+DEFINE_CLOCK(fec_clk, 0, CCM_CGR1, 0, get_rate_ipg, NULL);
+DEFINE_CLOCK(gpio1_clk, 0, CCM_CGR1, 2, NULL, NULL);
+DEFINE_CLOCK(gpio2_clk, 1, CCM_CGR1, 4, NULL, NULL);
+DEFINE_CLOCK(gpio3_clk, 2, CCM_CGR1, 6, NULL, NULL);
+DEFINE_CLOCK(gpt_clk, 0, CCM_CGR1, 8, get_rate_ipg, NULL);
+DEFINE_CLOCK(i2c1_clk, 0, CCM_CGR1, 10, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(i2c2_clk, 1, CCM_CGR1, 12, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(i2c3_clk, 2, CCM_CGR1, 14, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(iomuxc_clk, 0, CCM_CGR1, 16, NULL, NULL);
+DEFINE_CLOCK(ipu_clk, 0, CCM_CGR1, 18, NULL, NULL);
+DEFINE_CLOCK(kpp_clk, 0, CCM_CGR1, 20, get_rate_ipg, NULL);
+DEFINE_CLOCK(mlb_clk, 0, CCM_CGR1, 22, get_rate_ahb, NULL);
+DEFINE_CLOCK(mshc_clk, 0, CCM_CGR1, 24, get_rate_mshc, NULL);
+DEFINE_CLOCK(owire_clk, 0, CCM_CGR1, 26, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(pwm_clk, 0, CCM_CGR1, 28, get_rate_ipg_per, NULL);
+DEFINE_CLOCK(rngc_clk, 0, CCM_CGR1, 30, get_rate_ipg, NULL);
+
+DEFINE_CLOCK(rtc_clk, 0, CCM_CGR2, 0, get_rate_ipg, NULL);
+DEFINE_CLOCK(rtic_clk, 0, CCM_CGR2, 2, get_rate_ahb, NULL);
+DEFINE_CLOCK(scc_clk, 0, CCM_CGR2, 4, get_rate_ipg, NULL);
+DEFINE_CLOCK(sdma_clk, 0, CCM_CGR2, 6, NULL, NULL);
+DEFINE_CLOCK(spba_clk, 0, CCM_CGR2, 8, get_rate_ipg, NULL);
+DEFINE_CLOCK(spdif_clk, 0, CCM_CGR2, 10, NULL, NULL);
+DEFINE_CLOCK(ssi1_clk, 0, CCM_CGR2, 12, get_rate_ssi, NULL);
+DEFINE_CLOCK(ssi2_clk, 1, CCM_CGR2, 14, get_rate_ssi, NULL);
+DEFINE_CLOCK(uart1_clk, 0, CCM_CGR2, 16, get_rate_uart, NULL);
+DEFINE_CLOCK(uart2_clk, 1, CCM_CGR2, 18, get_rate_uart, NULL);
+DEFINE_CLOCK(uart3_clk, 2, CCM_CGR2, 20, get_rate_uart, NULL);
+DEFINE_CLOCK(usbotg_clk, 0, CCM_CGR2, 22, NULL, NULL);
+DEFINE_CLOCK(wdog_clk, 0, CCM_CGR2, 24, NULL, NULL);
+DEFINE_CLOCK(max_clk, 0, CCM_CGR2, 26, NULL, NULL);
+DEFINE_CLOCK(admux_clk, 0, CCM_CGR2, 30, NULL, NULL);
+
+DEFINE_CLOCK(csi_clk, 0, CCM_CGR3, 0, get_rate_csi, NULL);
+DEFINE_CLOCK(iim_clk, 0, CCM_CGR3, 2, NULL, NULL);
+DEFINE_CLOCK(gpu2d_clk, 0, CCM_CGR3, 4, NULL, NULL);
+
+#define _REGISTER_CLOCK(d, n, c) \
+ { \
+ .dev_id = d, \
+ .con_id = n, \
+ .clk = &c, \
+ },
+
+static struct clk_lookup lookups[] __initdata = {
+ _REGISTER_CLOCK(NULL, "asrc", asrc_clk)
+ _REGISTER_CLOCK(NULL, "ata", ata_clk)
+ _REGISTER_CLOCK(NULL, "audmux", audmux_clk)
+ _REGISTER_CLOCK(NULL, "can", can1_clk)
+ _REGISTER_CLOCK(NULL, "can", can2_clk)
+ _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
+ _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
+ _REGISTER_CLOCK(NULL, "ect", ect_clk)
+ _REGISTER_CLOCK(NULL, "edio", edio_clk)
+ _REGISTER_CLOCK(NULL, "emi", emi_clk)
+ _REGISTER_CLOCK(NULL, "epit", epit1_clk)
+ _REGISTER_CLOCK(NULL, "epit", epit2_clk)
+ _REGISTER_CLOCK(NULL, "esai", esai_clk)
+ _REGISTER_CLOCK(NULL, "sdhc", esdhc1_clk)
+ _REGISTER_CLOCK(NULL, "sdhc", esdhc2_clk)
+ _REGISTER_CLOCK(NULL, "sdhc", esdhc3_clk)
+ _REGISTER_CLOCK("fec.0", NULL, fec_clk)
+ _REGISTER_CLOCK(NULL, "gpio", gpio1_clk)
+ _REGISTER_CLOCK(NULL, "gpio", gpio2_clk)
+ _REGISTER_CLOCK(NULL, "gpio", gpio3_clk)
+ _REGISTER_CLOCK("gpt.0", NULL, gpt_clk)
+ _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+ _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+ _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
+ _REGISTER_CLOCK(NULL, "iomuxc", iomuxc_clk)
+ _REGISTER_CLOCK(NULL, "ipu", ipu_clk)
+ _REGISTER_CLOCK(NULL, "kpp", kpp_clk)
+ _REGISTER_CLOCK(NULL, "mlb", mlb_clk)
+ _REGISTER_CLOCK(NULL, "mshc", mshc_clk)
+ _REGISTER_CLOCK("mxc_w1", NULL, owire_clk)
+ _REGISTER_CLOCK(NULL, "pwm", pwm_clk)
+ _REGISTER_CLOCK(NULL, "rngc", rngc_clk)
+ _REGISTER_CLOCK(NULL, "rtc", rtc_clk)
+ _REGISTER_CLOCK(NULL, "rtic", rtic_clk)
+ _REGISTER_CLOCK(NULL, "scc", scc_clk)
+ _REGISTER_CLOCK(NULL, "sdma", sdma_clk)
+ _REGISTER_CLOCK(NULL, "spba", spba_clk)
+ _REGISTER_CLOCK(NULL, "spdif", spdif_clk)
+ _REGISTER_CLOCK(NULL, "ssi", ssi1_clk)
+ _REGISTER_CLOCK(NULL, "ssi", ssi2_clk)
+ _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+ _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+ _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+ _REGISTER_CLOCK(NULL, "usbotg", usbotg_clk)
+ _REGISTER_CLOCK("mxc_wdt.0", NULL, wdog_clk)
+ _REGISTER_CLOCK(NULL, "max", max_clk)
+ _REGISTER_CLOCK(NULL, "admux", admux_clk)
+ _REGISTER_CLOCK(NULL, "csi", csi_clk)
+ _REGISTER_CLOCK(NULL, "iim", iim_clk)
+ _REGISTER_CLOCK(NULL, "gpu2d", gpu2d_clk)
+};
+
+int __init mx35_clocks_init()
+{
+ int i;
+ unsigned int ll = 0;
+
+ mxc_set_cpu_type(MXC_CPU_MX35);
+
+#ifdef CONFIG_DEBUG_LL_CONSOLE
+ ll = (3 << 16);
+#endif
+
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
+
+ /* Turn off all clocks except the ones we need to survive, namely:
+ * EMI, GPIO1/2/3, GPT, IOMUX, MAX and eventually uart
+ */
+ __raw_writel((3 << 18), CCM_BASE + CCM_CGR0);
+ __raw_writel((3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 16),
+ CCM_BASE + CCM_CGR1);
+ __raw_writel((3 << 26) | ll, CCM_BASE + CCM_CGR2);
+ __raw_writel(0, CCM_BASE + CCM_CGR3);
+
+ mxc_timer_init(&gpt_clk);
+
+ return 0;
+}
+
diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c
index b1746aae1f89..ca46f4801c3d 100644
--- a/arch/arm/mach-mx3/clock.c
+++ b/arch/arm/mach-mx3/clock.c
@@ -23,9 +23,13 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
+
+#include <asm/clkdev.h>
+#include <asm/div64.h>
+
#include <mach/clock.h>
#include <mach/hardware.h>
-#include <asm/div64.h>
+#include <mach/common.h>
#include "crm_regs.h"
@@ -64,17 +68,17 @@ static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
}
static struct clk mcu_pll_clk;
-static struct clk mcu_main_clk;
-static struct clk usb_pll_clk;
static struct clk serial_pll_clk;
static struct clk ipg_clk;
static struct clk ckih_clk;
-static struct clk ahb_clk;
-static int _clk_enable(struct clk *clk)
+static int cgr_enable(struct clk *clk)
{
u32 reg;
+ if (!clk->enable_reg)
+ return 0;
+
reg = __raw_readl(clk->enable_reg);
reg |= 3 << clk->enable_shift;
__raw_writel(reg, clk->enable_reg);
@@ -82,133 +86,69 @@ static int _clk_enable(struct clk *clk)
return 0;
}
-static void _clk_disable(struct clk *clk)
+static void cgr_disable(struct clk *clk)
{
u32 reg;
+ if (!clk->enable_reg)
+ return;
+
reg = __raw_readl(clk->enable_reg);
reg &= ~(3 << clk->enable_shift);
+
+ /* special case for EMI clock */
+ if (clk->enable_reg == MXC_CCM_CGR2 && clk->enable_shift == 8)
+ reg |= (1 << clk->enable_shift);
+
__raw_writel(reg, clk->enable_reg);
}
-static void _clk_emi_disable(struct clk *clk)
+static unsigned long pll_ref_get_rate(void)
{
- u32 reg;
+ unsigned long ccmr;
+ unsigned int prcs;
- reg = __raw_readl(clk->enable_reg);
- reg &= ~(3 << clk->enable_shift);
- reg |= (1 << clk->enable_shift);
- __raw_writel(reg, clk->enable_reg);
+ ccmr = __raw_readl(MXC_CCM_CCMR);
+ prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
+ if (prcs == 0x1)
+ return CKIL_CLK_FREQ * 1024;
+ else
+ return clk_get_rate(&ckih_clk);
}
-static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
+static unsigned long usb_pll_get_rate(struct clk *clk)
{
- u32 reg;
- signed long pd = 1; /* Pre-divider */
- signed long mfi; /* Multiplication Factor (Integer part) */
- signed long mfn; /* Multiplication Factor (Integer part) */
- signed long mfd; /* Multiplication Factor (Denominator Part) */
- signed long tmp;
- u32 ref_freq = clk_get_rate(clk->parent);
+ unsigned long reg;
- while (((ref_freq / pd) * 10) > rate)
- pd++;
+ reg = __raw_readl(MXC_CCM_UPCTL);
- if ((ref_freq / pd) < PRE_DIV_MIN_FREQ)
- return -EINVAL;
+ return mxc_decode_pll(reg, pll_ref_get_rate());
+}
- /* the ref_freq/2 in the following is to round up */
- mfi = (((rate / 2) * pd) + (ref_freq / 2)) / ref_freq;
- if (mfi < 5 || mfi > 15)
- return -EINVAL;
+static unsigned long serial_pll_get_rate(struct clk *clk)
+{
+ unsigned long reg;
- /* pick a mfd value that will work
- * then solve for mfn */
- mfd = ref_freq / 50000;
-
- /*
- * pll_freq * pd * mfd
- * mfn = -------------------- - (mfi * mfd)
- * 2 * ref_freq
- */
- /* the tmp/2 is for rounding */
- tmp = ref_freq / 10000;
- mfn =
- ((((((rate / 2) + (tmp / 2)) / tmp) * pd) * mfd) / 10000) -
- (mfi * mfd);
-
- mfn = mfn & 0x3ff;
- pd--;
- mfd--;
-
- /* Change the Pll value */
- reg = (mfi << MXC_CCM_PCTL_MFI_OFFSET) |
- (mfn << MXC_CCM_PCTL_MFN_OFFSET) |
- (mfd << MXC_CCM_PCTL_MFD_OFFSET) | (pd << MXC_CCM_PCTL_PD_OFFSET);
-
- if (clk == &mcu_pll_clk)
- __raw_writel(reg, MXC_CCM_MPCTL);
- else if (clk == &usb_pll_clk)
- __raw_writel(reg, MXC_CCM_UPCTL);
- else if (clk == &serial_pll_clk)
- __raw_writel(reg, MXC_CCM_SRPCTL);
+ reg = __raw_readl(MXC_CCM_SRPCTL);
- return 0;
+ return mxc_decode_pll(reg, pll_ref_get_rate());
}
-static unsigned long _clk_pll_get_rate(struct clk *clk)
+static unsigned long mcu_pll_get_rate(struct clk *clk)
{
- long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
unsigned long reg, ccmr;
- s64 temp;
- unsigned int prcs;
ccmr = __raw_readl(MXC_CCM_CCMR);
- prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
- if (prcs == 0x1)
- ref_clk = CKIL_CLK_FREQ * 1024;
- else
- ref_clk = clk_get_rate(&ckih_clk);
-
- if (clk == &mcu_pll_clk) {
- if ((ccmr & MXC_CCM_CCMR_MPE) == 0)
- return ref_clk;
- if ((ccmr & MXC_CCM_CCMR_MDS) != 0)
- return ref_clk;
- reg = __raw_readl(MXC_CCM_MPCTL);
- } else if (clk == &usb_pll_clk)
- reg = __raw_readl(MXC_CCM_UPCTL);
- else if (clk == &serial_pll_clk)
- reg = __raw_readl(MXC_CCM_SRPCTL);
- else {
- BUG();
- return 0;
- }
-
- pdf = (reg & MXC_CCM_PCTL_PD_MASK) >> MXC_CCM_PCTL_PD_OFFSET;
- mfd = (reg & MXC_CCM_PCTL_MFD_MASK) >> MXC_CCM_PCTL_MFD_OFFSET;
- mfi = (reg & MXC_CCM_PCTL_MFI_MASK) >> MXC_CCM_PCTL_MFI_OFFSET;
- mfi = (mfi <= 5) ? 5 : mfi;
- mfn = mfn_abs = reg & MXC_CCM_PCTL_MFN_MASK;
- if (mfn >= 0x200) {
- mfn |= 0xFFFFFE00;
- mfn_abs = -mfn;
- }
-
- ref_clk *= 2;
- ref_clk /= pdf + 1;
+ if (!(ccmr & MXC_CCM_CCMR_MPE) || (ccmr & MXC_CCM_CCMR_MDS))
+ return clk_get_rate(&ckih_clk);
- temp = (u64) ref_clk * mfn_abs;
- do_div(temp, mfd + 1);
- if (mfn < 0)
- temp = -temp;
- temp = (ref_clk * mfi) + temp;
+ reg = __raw_readl(MXC_CCM_MPCTL);
- return temp;
+ return mxc_decode_pll(reg, pll_ref_get_rate());
}
-static int _clk_usb_pll_enable(struct clk *clk)
+static int usb_pll_enable(struct clk *clk)
{
u32 reg;
@@ -222,7 +162,7 @@ static int _clk_usb_pll_enable(struct clk *clk)
return 0;
}
-static void _clk_usb_pll_disable(struct clk *clk)
+static void usb_pll_disable(struct clk *clk)
{
u32 reg;
@@ -231,7 +171,7 @@ static void _clk_usb_pll_disable(struct clk *clk)
__raw_writel(reg, MXC_CCM_CCMR);
}
-static int _clk_serial_pll_enable(struct clk *clk)
+static int serial_pll_enable(struct clk *clk)
{
u32 reg;
@@ -245,7 +185,7 @@ static int _clk_serial_pll_enable(struct clk *clk)
return 0;
}
-static void _clk_serial_pll_disable(struct clk *clk)
+static void serial_pll_disable(struct clk *clk)
{
u32 reg;
@@ -258,7 +198,7 @@ static void _clk_serial_pll_disable(struct clk *clk)
#define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
#define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
-static unsigned long _clk_mcu_main_get_rate(struct clk *clk)
+static unsigned long mcu_main_get_rate(struct clk *clk)
{
u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0);
@@ -268,7 +208,7 @@ static unsigned long _clk_mcu_main_get_rate(struct clk *clk)
return clk_get_rate(&mcu_pll_clk);
}
-static unsigned long _clk_hclk_get_rate(struct clk *clk)
+static unsigned long ahb_get_rate(struct clk *clk)
{
unsigned long max_pdf;
@@ -277,7 +217,7 @@ static unsigned long _clk_hclk_get_rate(struct clk *clk)
return clk_get_rate(clk->parent) / (max_pdf + 1);
}
-static unsigned long _clk_ipg_get_rate(struct clk *clk)
+static unsigned long ipg_get_rate(struct clk *clk)
{
unsigned long ipg_pdf;
@@ -286,7 +226,7 @@ static unsigned long _clk_ipg_get_rate(struct clk *clk)
return clk_get_rate(clk->parent) / (ipg_pdf + 1);
}
-static unsigned long _clk_nfc_get_rate(struct clk *clk)
+static unsigned long nfc_get_rate(struct clk *clk)
{
unsigned long nfc_pdf;
@@ -295,7 +235,7 @@ static unsigned long _clk_nfc_get_rate(struct clk *clk)
return clk_get_rate(clk->parent) / (nfc_pdf + 1);
}
-static unsigned long _clk_hsp_get_rate(struct clk *clk)
+static unsigned long hsp_get_rate(struct clk *clk)
{
unsigned long hsp_pdf;
@@ -304,7 +244,7 @@ static unsigned long _clk_hsp_get_rate(struct clk *clk)
return clk_get_rate(clk->parent) / (hsp_pdf + 1);
}
-static unsigned long _clk_usb_get_rate(struct clk *clk)
+static unsigned long usb_get_rate(struct clk *clk)
{
unsigned long usb_pdf, usb_prepdf;
@@ -315,7 +255,7 @@ static unsigned long _clk_usb_get_rate(struct clk *clk)
return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1);
}
-static unsigned long _clk_csi_get_rate(struct clk *clk)
+static unsigned long csi_get_rate(struct clk *clk)
{
u32 reg, pre, post;
@@ -329,7 +269,7 @@ static unsigned long _clk_csi_get_rate(struct clk *clk)
return clk_get_rate(clk->parent) / (pre * post);
}
-static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long csi_round_rate(struct clk *clk, unsigned long rate)
{
u32 pre, post, parent = clk_get_rate(clk->parent);
u32 div = parent / rate;
@@ -342,7 +282,7 @@ static unsigned long _clk_csi_round_rate(struct clk *clk, unsigned long rate)
return parent / (pre * post);
}
-static int _clk_csi_set_rate(struct clk *clk, unsigned long rate)
+static int csi_set_rate(struct clk *clk, unsigned long rate)
{
u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
@@ -363,16 +303,7 @@ static int _clk_csi_set_rate(struct clk *clk, unsigned long rate)
return 0;
}
-static unsigned long _clk_per_get_rate(struct clk *clk)
-{
- unsigned long per_pdf;
-
- per_pdf = PDR0(MXC_CCM_PDR0_PER_PODF_MASK,
- MXC_CCM_PDR0_PER_PODF_OFFSET);
- return clk_get_rate(clk->parent) / (per_pdf + 1);
-}
-
-static unsigned long _clk_ssi1_get_rate(struct clk *clk)
+static unsigned long ssi1_get_rate(struct clk *clk)
{
unsigned long ssi1_pdf, ssi1_prepdf;
@@ -383,7 +314,7 @@ static unsigned long _clk_ssi1_get_rate(struct clk *clk)
return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1);
}
-static unsigned long _clk_ssi2_get_rate(struct clk *clk)
+static unsigned long ssi2_get_rate(struct clk *clk)
{
unsigned long ssi2_pdf, ssi2_prepdf;
@@ -394,7 +325,7 @@ static unsigned long _clk_ssi2_get_rate(struct clk *clk)
return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1);
}
-static unsigned long _clk_firi_get_rate(struct clk *clk)
+static unsigned long firi_get_rate(struct clk *clk)
{
unsigned long firi_pdf, firi_prepdf;
@@ -405,7 +336,7 @@ static unsigned long _clk_firi_get_rate(struct clk *clk)
return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1);
}
-static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long firi_round_rate(struct clk *clk, unsigned long rate)
{
u32 pre, post;
u32 parent = clk_get_rate(clk->parent);
@@ -420,7 +351,7 @@ static unsigned long _clk_firi_round_rate(struct clk *clk, unsigned long rate)
}
-static int _clk_firi_set_rate(struct clk *clk, unsigned long rate)
+static int firi_set_rate(struct clk *clk, unsigned long rate)
{
u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
@@ -441,12 +372,12 @@ static int _clk_firi_set_rate(struct clk *clk, unsigned long rate)
return 0;
}
-static unsigned long _clk_mbx_get_rate(struct clk *clk)
+static unsigned long mbx_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 2;
}
-static unsigned long _clk_mstick1_get_rate(struct clk *clk)
+static unsigned long mstick1_get_rate(struct clk *clk)
{
unsigned long msti_pdf;
@@ -455,7 +386,7 @@ static unsigned long _clk_mstick1_get_rate(struct clk *clk)
return clk_get_rate(clk->parent) / (msti_pdf + 1);
}
-static unsigned long _clk_mstick2_get_rate(struct clk *clk)
+static unsigned long mstick2_get_rate(struct clk *clk)
{
unsigned long msti_pdf;
@@ -472,661 +403,185 @@ static unsigned long clk_ckih_get_rate(struct clk *clk)
}
static struct clk ckih_clk = {
- .name = "ckih",
.get_rate = clk_ckih_get_rate,
};
-static unsigned long clk_ckil_get_rate(struct clk *clk)
-{
- return CKIL_CLK_FREQ;
-}
-
-static struct clk ckil_clk = {
- .name = "ckil",
- .get_rate = clk_ckil_get_rate,
-};
-
static struct clk mcu_pll_clk = {
- .name = "mcu_pll",
.parent = &ckih_clk,
- .set_rate = _clk_pll_set_rate,
- .get_rate = _clk_pll_get_rate,
+ .get_rate = mcu_pll_get_rate,
};
static struct clk mcu_main_clk = {
- .name = "mcu_main_clk",
.parent = &mcu_pll_clk,
- .get_rate = _clk_mcu_main_get_rate,
+ .get_rate = mcu_main_get_rate,
};
static struct clk serial_pll_clk = {
- .name = "serial_pll",
.parent = &ckih_clk,
- .set_rate = _clk_pll_set_rate,
- .get_rate = _clk_pll_get_rate,
- .enable = _clk_serial_pll_enable,
- .disable = _clk_serial_pll_disable,
+ .get_rate = serial_pll_get_rate,
+ .enable = serial_pll_enable,
+ .disable = serial_pll_disable,
};
static struct clk usb_pll_clk = {
- .name = "usb_pll",
.parent = &ckih_clk,
- .set_rate = _clk_pll_set_rate,
- .get_rate = _clk_pll_get_rate,
- .enable = _clk_usb_pll_enable,
- .disable = _clk_usb_pll_disable,
+ .get_rate = usb_pll_get_rate,
+ .enable = usb_pll_enable,
+ .disable = usb_pll_disable,
};
static struct clk ahb_clk = {
- .name = "ahb_clk",
.parent = &mcu_main_clk,
- .get_rate = _clk_hclk_get_rate,
-};
-
-static struct clk per_clk = {
- .name = "per_clk",
- .parent = &usb_pll_clk,
- .get_rate = _clk_per_get_rate,
-};
-
-static struct clk perclk_clk = {
- .name = "perclk_clk",
- .parent = &ipg_clk,
-};
-
-static struct clk cspi_clk[] = {
- {
- .name = "cspi_clk",
- .id = 0,
- .parent = &ipg_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR2,
- .enable_shift = MXC_CCM_CGR2_CSPI1_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "cspi_clk",
- .id = 1,
- .parent = &ipg_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR2,
- .enable_shift = MXC_CCM_CGR2_CSPI2_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "cspi_clk",
- .id = 2,
- .parent = &ipg_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_CSPI3_OFFSET,
- .disable = _clk_disable,},
-};
-
-static struct clk ipg_clk = {
- .name = "ipg_clk",
- .parent = &ahb_clk,
- .get_rate = _clk_ipg_get_rate,
-};
-
-static struct clk emi_clk = {
- .name = "emi_clk",
- .parent = &ahb_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR2,
- .enable_shift = MXC_CCM_CGR2_EMI_OFFSET,
- .disable = _clk_emi_disable,
-};
-
-static struct clk gpt_clk = {
- .name = "gpt_clk",
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_GPT_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk pwm_clk = {
- .name = "pwm_clk",
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR1_PWM_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk epit_clk[] = {
- {
- .name = "epit_clk",
- .id = 0,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_EPIT1_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "epit_clk",
- .id = 1,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_EPIT2_OFFSET,
- .disable = _clk_disable,},
-};
-
-static struct clk nfc_clk = {
- .name = "nfc_clk",
- .parent = &ahb_clk,
- .get_rate = _clk_nfc_get_rate,
-};
-
-static struct clk scc_clk = {
- .name = "scc_clk",
- .parent = &ipg_clk,
-};
-
-static struct clk ipu_clk = {
- .name = "ipu_clk",
- .parent = &mcu_main_clk,
- .get_rate = _clk_hsp_get_rate,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_IPU_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk kpp_clk = {
- .name = "kpp_clk",
- .parent = &ipg_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_KPP_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk wdog_clk = {
- .name = "wdog_clk",
- .parent = &ipg_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_WDOG_OFFSET,
- .disable = _clk_disable,
-};
-static struct clk rtc_clk = {
- .name = "rtc_clk",
- .parent = &ipg_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_RTC_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk usb_clk[] = {
- {
- .name = "usb_clk",
- .parent = &usb_pll_clk,
- .get_rate = _clk_usb_get_rate,},
- {
- .name = "usb_ahb_clk",
- .parent = &ahb_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_USBOTG_OFFSET,
- .disable = _clk_disable,},
-};
-
-static struct clk csi_clk = {
- .name = "csi_clk",
- .parent = &serial_pll_clk,
- .get_rate = _clk_csi_get_rate,
- .round_rate = _clk_csi_round_rate,
- .set_rate = _clk_csi_set_rate,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_CSI_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk uart_clk[] = {
- {
- .name = "uart_clk",
- .id = 0,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_UART1_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "uart_clk",
- .id = 1,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_UART2_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "uart_clk",
- .id = 2,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_UART3_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "uart_clk",
- .id = 3,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_UART4_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "uart_clk",
- .id = 4,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_UART5_OFFSET,
- .disable = _clk_disable,},
-};
-
-static struct clk i2c_clk[] = {
- {
- .name = "i2c_clk",
- .id = 0,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_I2C1_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "i2c_clk",
- .id = 1,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_I2C2_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "i2c_clk",
- .id = 2,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_I2C3_OFFSET,
- .disable = _clk_disable,},
-};
-
-static struct clk owire_clk = {
- .name = "owire_clk",
- .parent = &perclk_clk,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_OWIRE_OFFSET,
- .enable = _clk_enable,
- .disable = _clk_disable,
-};
-
-static struct clk sdhc_clk[] = {
- {
- .name = "sdhc_clk",
- .id = 0,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_SD_MMC1_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "sdhc_clk",
- .id = 1,
- .parent = &perclk_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_SD_MMC2_OFFSET,
- .disable = _clk_disable,},
-};
-
-static struct clk ssi_clk[] = {
- {
- .name = "ssi_clk",
- .parent = &serial_pll_clk,
- .get_rate = _clk_ssi1_get_rate,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_SSI1_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "ssi_clk",
- .id = 1,
- .parent = &serial_pll_clk,
- .get_rate = _clk_ssi2_get_rate,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR2,
- .enable_shift = MXC_CCM_CGR2_SSI2_OFFSET,
- .disable = _clk_disable,},
-};
-
-static struct clk firi_clk = {
- .name = "firi_clk",
- .parent = &usb_pll_clk,
- .round_rate = _clk_firi_round_rate,
- .set_rate = _clk_firi_set_rate,
- .get_rate = _clk_firi_get_rate,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR2,
- .enable_shift = MXC_CCM_CGR2_FIRI_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk ata_clk = {
- .name = "ata_clk",
- .parent = &ipg_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_ATA_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk mbx_clk = {
- .name = "mbx_clk",
- .parent = &ahb_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR2,
- .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
- .get_rate = _clk_mbx_get_rate,
-};
-
-static struct clk vpu_clk = {
- .name = "vpu_clk",
- .parent = &ahb_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR2,
- .enable_shift = MXC_CCM_CGR2_GACC_OFFSET,
- .get_rate = _clk_mbx_get_rate,
-};
-
-static struct clk rtic_clk = {
- .name = "rtic_clk",
- .parent = &ahb_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR2,
- .enable_shift = MXC_CCM_CGR2_RTIC_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk rng_clk = {
- .name = "rng_clk",
- .parent = &ipg_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_RNG_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk sdma_clk[] = {
- {
- .name = "sdma_ahb_clk",
- .parent = &ahb_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_SDMA_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "sdma_ipg_clk",
- .parent = &ipg_clk,}
-};
-
-static struct clk mpeg4_clk = {
- .name = "mpeg4_clk",
- .parent = &ahb_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk vl2cc_clk = {
- .name = "vl2cc_clk",
- .parent = &ahb_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_HANTRO_OFFSET,
- .disable = _clk_disable,
-};
-
-static struct clk mstick_clk[] = {
- {
- .name = "mstick_clk",
- .id = 0,
- .parent = &usb_pll_clk,
- .get_rate = _clk_mstick1_get_rate,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_MEMSTICK1_OFFSET,
- .disable = _clk_disable,},
- {
- .name = "mstick_clk",
- .id = 1,
- .parent = &usb_pll_clk,
- .get_rate = _clk_mstick2_get_rate,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR1,
- .enable_shift = MXC_CCM_CGR1_MEMSTICK2_OFFSET,
- .disable = _clk_disable,},
-};
-
-static struct clk iim_clk = {
- .name = "iim_clk",
- .parent = &ipg_clk,
- .enable = _clk_enable,
- .enable_reg = MXC_CCM_CGR0,
- .enable_shift = MXC_CCM_CGR0_IIM_OFFSET,
- .disable = _clk_disable,
-};
-
-static unsigned long _clk_cko1_round_rate(struct clk *clk, unsigned long rate)
-{
- u32 div, parent = clk_get_rate(clk->parent);
-
- div = parent / rate;
- if (parent % rate)
- div++;
-
- if (div > 8)
- div = 16;
- else if (div > 4)
- div = 8;
- else if (div > 2)
- div = 4;
-
- return parent / div;
-}
-
-static int _clk_cko1_set_rate(struct clk *clk, unsigned long rate)
-{
- u32 reg, div, parent = clk_get_rate(clk->parent);
-
- div = parent / rate;
-
- if (div == 16)
- div = 4;
- else if (div == 8)
- div = 3;
- else if (div == 4)
- div = 2;
- else if (div == 2)
- div = 1;
- else if (div == 1)
- div = 0;
- else
- return -EINVAL;
-
- reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOUTDIV_MASK;
- reg |= div << MXC_CCM_COSR_CLKOUTDIV_OFFSET;
- __raw_writel(reg, MXC_CCM_COSR);
-
- return 0;
-}
-
-static unsigned long _clk_cko1_get_rate(struct clk *clk)
-{
- u32 div;
-
- div = __raw_readl(MXC_CCM_COSR) & MXC_CCM_COSR_CLKOUTDIV_MASK >>
- MXC_CCM_COSR_CLKOUTDIV_OFFSET;
-
- return clk_get_rate(clk->parent) / (1 << div);
-}
-
-static int _clk_cko1_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOSEL_MASK;
-
- if (parent == &mcu_main_clk)
- reg |= 0 << MXC_CCM_COSR_CLKOSEL_OFFSET;
- else if (parent == &ipg_clk)
- reg |= 1 << MXC_CCM_COSR_CLKOSEL_OFFSET;
- else if (parent == &usb_pll_clk)
- reg |= 2 << MXC_CCM_COSR_CLKOSEL_OFFSET;
- else if (parent == mcu_main_clk.parent)
- reg |= 3 << MXC_CCM_COSR_CLKOSEL_OFFSET;
- else if (parent == &ahb_clk)
- reg |= 5 << MXC_CCM_COSR_CLKOSEL_OFFSET;
- else if (parent == &serial_pll_clk)
- reg |= 7 << MXC_CCM_COSR_CLKOSEL_OFFSET;
- else if (parent == &ckih_clk)
- reg |= 8 << MXC_CCM_COSR_CLKOSEL_OFFSET;
- else if (parent == &emi_clk)
- reg |= 9 << MXC_CCM_COSR_CLKOSEL_OFFSET;
- else if (parent == &ipu_clk)
- reg |= 0xA << MXC_CCM_COSR_CLKOSEL_OFFSET;
- else if (parent == &nfc_clk)
- reg |= 0xB << MXC_CCM_COSR_CLKOSEL_OFFSET;
- else if (parent == &uart_clk[0])
- reg |= 0xC << MXC_CCM_COSR_CLKOSEL_OFFSET;
- else
- return -EINVAL;
-
- __raw_writel(reg, MXC_CCM_COSR);
-
- return 0;
-}
-
-static int _clk_cko1_enable(struct clk *clk)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_COSR) | MXC_CCM_COSR_CLKOEN;
- __raw_writel(reg, MXC_CCM_COSR);
+ .get_rate = ahb_get_rate,
+};
+
+#define DEFINE_CLOCK(name, i, er, es, gr, s, p) \
+ static struct clk name = { \
+ .id = i, \
+ .enable_reg = er, \
+ .enable_shift = es, \
+ .get_rate = gr, \
+ .enable = cgr_enable, \
+ .disable = cgr_disable, \
+ .secondary = s, \
+ .parent = p, \
+ }
- return 0;
-}
+#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \
+ static struct clk name = { \
+ .id = i, \
+ .enable_reg = er, \
+ .enable_shift = es, \
+ .get_rate = getsetround##_get_rate, \
+ .set_rate = getsetround##_set_rate, \
+ .round_rate = getsetround##_round_rate, \
+ .enable = cgr_enable, \
+ .disable = cgr_disable, \
+ .secondary = s, \
+ .parent = p, \
+ }
-static void _clk_cko1_disable(struct clk *clk)
+DEFINE_CLOCK(perclk_clk, 0, NULL, 0, NULL, NULL, &ipg_clk);
+
+DEFINE_CLOCK(sdhc1_clk, 0, MXC_CCM_CGR0, 0, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(sdhc2_clk, 1, MXC_CCM_CGR0, 2, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CGR0, 4, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(epit1_clk, 0, MXC_CCM_CGR0, 6, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(epit2_clk, 1, MXC_CCM_CGR0, 8, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(iim_clk, 0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(ata_clk, 0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(sdma_clk1, 0, MXC_CCM_CGR0, 14, NULL, &sdma_clk1, &ahb_clk);
+DEFINE_CLOCK(cspi3_clk, 2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(rng_clk, 0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CGR0, 20, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CGR0, 22, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CGR0, 24, ssi1_get_rate, NULL, &serial_pll_clk);
+DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CGR0, 26, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CGR0, 28, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(i2c3_clk, 2, MXC_CCM_CGR0, 30, NULL, NULL, &perclk_clk);
+
+DEFINE_CLOCK(mpeg4_clk, 0, MXC_CCM_CGR1, 0, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(mstick1_clk, 0, MXC_CCM_CGR1, 2, mstick1_get_rate, NULL, &usb_pll_clk);
+DEFINE_CLOCK(mstick2_clk, 1, MXC_CCM_CGR1, 4, mstick2_get_rate, NULL, &usb_pll_clk);
+DEFINE_CLOCK1(csi_clk, 0, MXC_CCM_CGR1, 6, csi, NULL, &ahb_clk);
+DEFINE_CLOCK(rtc_clk, 0, MXC_CCM_CGR1, 8, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(wdog_clk, 0, MXC_CCM_CGR1, 10, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(pwm_clk, 0, MXC_CCM_CGR1, 12, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(usb_clk2, 0, MXC_CCM_CGR1, 18, usb_get_rate, NULL, &ahb_clk);
+DEFINE_CLOCK(kpp_clk, 0, MXC_CCM_CGR1, 20, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(ipu_clk, 0, MXC_CCM_CGR1, 22, hsp_get_rate, NULL, &mcu_main_clk);
+DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CGR1, 24, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CGR1, 26, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CGR1, 28, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(owire_clk, 0, MXC_CCM_CGR1, 30, NULL, NULL, &perclk_clk);
+
+DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CGR2, 0, ssi2_get_rate, NULL, &serial_pll_clk);
+DEFINE_CLOCK(cspi1_clk, 0, MXC_CCM_CGR2, 2, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(cspi2_clk, 1, MXC_CCM_CGR2, 4, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(mbx_clk, 0, MXC_CCM_CGR2, 6, mbx_get_rate, NULL, &ahb_clk);
+DEFINE_CLOCK(emi_clk, 0, MXC_CCM_CGR2, 8, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(rtic_clk, 0, MXC_CCM_CGR2, 10, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK1(firi_clk, 0, MXC_CCM_CGR2, 12, firi, NULL, &usb_pll_clk);
+
+DEFINE_CLOCK(sdma_clk2, 0, NULL, 0, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(usb_clk1, 0, NULL, 0, usb_get_rate, NULL, &usb_pll_clk);
+DEFINE_CLOCK(nfc_clk, 0, NULL, 0, nfc_get_rate, NULL, &ahb_clk);
+DEFINE_CLOCK(scc_clk, 0, NULL, 0, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(ipg_clk, 0, NULL, 0, ipg_get_rate, NULL, &ahb_clk);
+
+#define _REGISTER_CLOCK(d, n, c) \
+ { \
+ .dev_id = d, \
+ .con_id = n, \
+ .clk = &c, \
+ },
+
+static struct clk_lookup lookups[] __initdata = {
+ _REGISTER_CLOCK(NULL, "emi", emi_clk)
+ _REGISTER_CLOCK(NULL, "cspi", cspi1_clk)
+ _REGISTER_CLOCK(NULL, "cspi", cspi2_clk)
+ _REGISTER_CLOCK(NULL, "cspi", cspi3_clk)
+ _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
+ _REGISTER_CLOCK(NULL, "pwm", pwm_clk)
+ _REGISTER_CLOCK(NULL, "wdog", wdog_clk)
+ _REGISTER_CLOCK(NULL, "rtc", rtc_clk)
+ _REGISTER_CLOCK(NULL, "epit", epit1_clk)
+ _REGISTER_CLOCK(NULL, "epit", epit2_clk)
+ _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
+ _REGISTER_CLOCK("ipu-core", NULL, ipu_clk)
+ _REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk)
+ _REGISTER_CLOCK(NULL, "kpp", kpp_clk)
+ _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk1)
+ _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk2)
+ _REGISTER_CLOCK("mx3-camera.0", "csi", csi_clk)
+ _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+ _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+ _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+ _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk)
+ _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk)
+ _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+ _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+ _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
+ _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)
+ _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
+ _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
+ _REGISTER_CLOCK(NULL, "ssi", ssi1_clk)
+ _REGISTER_CLOCK(NULL, "ssi", ssi2_clk)
+ _REGISTER_CLOCK(NULL, "firi", firi_clk)
+ _REGISTER_CLOCK(NULL, "ata", ata_clk)
+ _REGISTER_CLOCK(NULL, "rtic", rtic_clk)
+ _REGISTER_CLOCK(NULL, "rng", rng_clk)
+ _REGISTER_CLOCK(NULL, "sdma_ahb", sdma_clk1)
+ _REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
+ _REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
+ _REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
+ _REGISTER_CLOCK(NULL, "scc", scc_clk)
+ _REGISTER_CLOCK(NULL, "iim", iim_clk)
+ _REGISTER_CLOCK(NULL, "mpeg4", mpeg4_clk)
+ _REGISTER_CLOCK(NULL, "mbx", mbx_clk)
+};
+
+int __init mx31_clocks_init(unsigned long fref)
{
u32 reg;
+ int i;
- reg = __raw_readl(MXC_CCM_COSR) & ~MXC_CCM_COSR_CLKOEN;
- __raw_writel(reg, MXC_CCM_COSR);
-}
-
-static struct clk cko1_clk = {
- .name = "cko1_clk",
- .get_rate = _clk_cko1_get_rate,
- .set_rate = _clk_cko1_set_rate,
- .round_rate = _clk_cko1_round_rate,
- .set_parent = _clk_cko1_set_parent,
- .enable = _clk_cko1_enable,
- .disable = _clk_cko1_disable,
-};
-
-static struct clk *mxc_clks[] = {
- &ckih_clk,
- &ckil_clk,
- &mcu_pll_clk,
- &usb_pll_clk,
- &serial_pll_clk,
- &mcu_main_clk,
- &ahb_clk,
- &per_clk,
- &perclk_clk,
- &cko1_clk,
- &emi_clk,
- &cspi_clk[0],
- &cspi_clk[1],
- &cspi_clk[2],
- &ipg_clk,
- &gpt_clk,
- &pwm_clk,
- &wdog_clk,
- &rtc_clk,
- &epit_clk[0],
- &epit_clk[1],
- &nfc_clk,
- &ipu_clk,
- &kpp_clk,
- &usb_clk[0],
- &usb_clk[1],
- &csi_clk,
- &uart_clk[0],
- &uart_clk[1],
- &uart_clk[2],
- &uart_clk[3],
- &uart_clk[4],
- &i2c_clk[0],
- &i2c_clk[1],
- &i2c_clk[2],
- &owire_clk,
- &sdhc_clk[0],
- &sdhc_clk[1],
- &ssi_clk[0],
- &ssi_clk[1],
- &firi_clk,
- &ata_clk,
- &rtic_clk,
- &rng_clk,
- &sdma_clk[0],
- &sdma_clk[1],
- &mstick_clk[0],
- &mstick_clk[1],
- &scc_clk,
- &iim_clk,
-};
-
-int __init mxc_clocks_init(unsigned long fref)
-{
- u32 reg;
- struct clk **clkp;
+ mxc_set_cpu_type(MXC_CPU_MX31);
ckih_rate = fref;
- for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++)
- clk_register(*clkp);
-
- if (cpu_is_mx31()) {
- clk_register(&mpeg4_clk);
- clk_register(&mbx_clk);
- } else {
- clk_register(&vpu_clk);
- clk_register(&vl2cc_clk);
- }
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
/* Turn off all possible clocks */
- __raw_writel(MXC_CCM_CGR0_GPT_MASK, MXC_CCM_CGR0);
+ __raw_writel((3 << 4), MXC_CCM_CGR0);
__raw_writel(0, MXC_CCM_CGR1);
-
- __raw_writel(MXC_CCM_CGR2_EMI_MASK |
- MXC_CCM_CGR2_IPMUX1_MASK |
- MXC_CCM_CGR2_IPMUX2_MASK |
- MXC_CCM_CGR2_MXCCLKENSEL_MASK | /* for MX32 */
- MXC_CCM_CGR2_CHIKCAMPEN_MASK | /* for MX32 */
- MXC_CCM_CGR2_OVRVPUBUSY_MASK | /* for MX32 */
+ __raw_writel((3 << 8) | (3 << 14) | (3 << 16)|
1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
MX32, but still required to be set */
MXC_CCM_CGR2);
- clk_disable(&cko1_clk);
- clk_disable(&usb_pll_clk);
+ usb_pll_disable(&usb_pll_clk);
pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
@@ -1143,6 +598,8 @@ int __init mxc_clocks_init(unsigned long fref)
__raw_writel(reg, MXC_CCM_PMCR1);
}
+ mxc_timer_init(&ipg_clk);
+
return 0;
}
diff --git a/arch/arm/mach-mx3/crm_regs.h b/arch/arm/mach-mx3/crm_regs.h
index 4a0e0ede23bb..adfa3627ad84 100644
--- a/arch/arm/mach-mx3/crm_regs.h
+++ b/arch/arm/mach-mx3/crm_regs.h
@@ -91,47 +91,6 @@
#define MXC_CCM_PDR0_MCU_PODF_OFFSET 0
#define MXC_CCM_PDR0_MCU_PODF_MASK 0x7
-#define MXC_CCM_PDR0_HSP_DIV_1 (0x0 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_2 (0x1 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_3 (0x2 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_4 (0x3 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_5 (0x4 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_6 (0x5 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_7 (0x6 << 11)
-#define MXC_CCM_PDR0_HSP_DIV_8 (0x7 << 11)
-
-#define MXC_CCM_PDR0_IPG_DIV_1 (0x0 << 6)
-#define MXC_CCM_PDR0_IPG_DIV_2 (0x1 << 6)
-#define MXC_CCM_PDR0_IPG_DIV_3 (0x2 << 6)
-#define MXC_CCM_PDR0_IPG_DIV_4 (0x3 << 6)
-
-#define MXC_CCM_PDR0_MAX_DIV_1 (0x0 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_2 (0x1 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_3 (0x2 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_4 (0x3 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_5 (0x4 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_6 (0x5 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_7 (0x6 << 3)
-#define MXC_CCM_PDR0_MAX_DIV_8 (0x7 << 3)
-
-#define MXC_CCM_PDR0_NFC_DIV_1 (0x0 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_2 (0x1 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_3 (0x2 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_4 (0x3 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_5 (0x4 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_6 (0x5 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_7 (0x6 << 8)
-#define MXC_CCM_PDR0_NFC_DIV_8 (0x7 << 8)
-
-#define MXC_CCM_PDR0_MCU_DIV_1 0x0
-#define MXC_CCM_PDR0_MCU_DIV_2 0x1
-#define MXC_CCM_PDR0_MCU_DIV_3 0x2
-#define MXC_CCM_PDR0_MCU_DIV_4 0x3
-#define MXC_CCM_PDR0_MCU_DIV_5 0x4
-#define MXC_CCM_PDR0_MCU_DIV_6 0x5
-#define MXC_CCM_PDR0_MCU_DIV_7 0x6
-#define MXC_CCM_PDR0_MCU_DIV_8 0x7
-
#define MXC_CCM_PDR1_USB_PRDF_OFFSET 30
#define MXC_CCM_PDR1_USB_PRDF_MASK (0x3 << 30)
#define MXC_CCM_PDR1_USB_PODF_OFFSET 27
@@ -152,118 +111,6 @@
/* Bit definitions for RCSR */
#define MXC_CCM_RCSR_NF16B 0x80000000
-/* Bit definitions for both MCU, USB and SR PLL control registers */
-#define MXC_CCM_PCTL_BRM 0x80000000
-#define MXC_CCM_PCTL_PD_OFFSET 26
-#define MXC_CCM_PCTL_PD_MASK (0xF << 26)
-#define MXC_CCM_PCTL_MFD_OFFSET 16
-#define MXC_CCM_PCTL_MFD_MASK (0x3FF << 16)
-#define MXC_CCM_PCTL_MFI_OFFSET 10
-#define MXC_CCM_PCTL_MFI_MASK (0xF << 10)
-#define MXC_CCM_PCTL_MFN_OFFSET 0
-#define MXC_CCM_PCTL_MFN_MASK 0x3FF
-
-#define MXC_CCM_CGR0_SD_MMC1_OFFSET 0
-#define MXC_CCM_CGR0_SD_MMC1_MASK (0x3 << 0)
-#define MXC_CCM_CGR0_SD_MMC2_OFFSET 2
-#define MXC_CCM_CGR0_SD_MMC2_MASK (0x3 << 2)
-#define MXC_CCM_CGR0_GPT_OFFSET 4
-#define MXC_CCM_CGR0_GPT_MASK (0x3 << 4)
-#define MXC_CCM_CGR0_EPIT1_OFFSET 6
-#define MXC_CCM_CGR0_EPIT1_MASK (0x3 << 6)
-#define MXC_CCM_CGR0_EPIT2_OFFSET 8
-#define MXC_CCM_CGR0_EPIT2_MASK (0x3 << 8)
-#define MXC_CCM_CGR0_IIM_OFFSET 10
-#define MXC_CCM_CGR0_IIM_MASK (0x3 << 10)
-#define MXC_CCM_CGR0_ATA_OFFSET 12
-#define MXC_CCM_CGR0_ATA_MASK (0x3 << 12)
-#define MXC_CCM_CGR0_SDMA_OFFSET 14
-#define MXC_CCM_CGR0_SDMA_MASK (0x3 << 14)
-#define MXC_CCM_CGR0_CSPI3_OFFSET 16
-#define MXC_CCM_CGR0_CSPI3_MASK (0x3 << 16)
-#define MXC_CCM_CGR0_RNG_OFFSET 18
-#define MXC_CCM_CGR0_RNG_MASK (0x3 << 18)
-#define MXC_CCM_CGR0_UART1_OFFSET 20
-#define MXC_CCM_CGR0_UART1_MASK (0x3 << 20)
-#define MXC_CCM_CGR0_UART2_OFFSET 22
-#define MXC_CCM_CGR0_UART2_MASK (0x3 << 22)
-#define MXC_CCM_CGR0_SSI1_OFFSET 24
-#define MXC_CCM_CGR0_SSI1_MASK (0x3 << 24)
-#define MXC_CCM_CGR0_I2C1_OFFSET 26
-#define MXC_CCM_CGR0_I2C1_MASK (0x3 << 26)
-#define MXC_CCM_CGR0_I2C2_OFFSET 28
-#define MXC_CCM_CGR0_I2C2_MASK (0x3 << 28)
-#define MXC_CCM_CGR0_I2C3_OFFSET 30
-#define MXC_CCM_CGR0_I2C3_MASK (0x3 << 30)
-
-#define MXC_CCM_CGR1_HANTRO_OFFSET 0
-#define MXC_CCM_CGR1_HANTRO_MASK (0x3 << 0)
-#define MXC_CCM_CGR1_MEMSTICK1_OFFSET 2
-#define MXC_CCM_CGR1_MEMSTICK1_MASK (0x3 << 2)
-#define MXC_CCM_CGR1_MEMSTICK2_OFFSET 4
-#define MXC_CCM_CGR1_MEMSTICK2_MASK (0x3 << 4)
-#define MXC_CCM_CGR1_CSI_OFFSET 6
-#define MXC_CCM_CGR1_CSI_MASK (0x3 << 6)
-#define MXC_CCM_CGR1_RTC_OFFSET 8
-#define MXC_CCM_CGR1_RTC_MASK (0x3 << 8)
-#define MXC_CCM_CGR1_WDOG_OFFSET 10
-#define MXC_CCM_CGR1_WDOG_MASK (0x3 << 10)
-#define MXC_CCM_CGR1_PWM_OFFSET 12
-#define MXC_CCM_CGR1_PWM_MASK (0x3 << 12)
-#define MXC_CCM_CGR1_SIM_OFFSET 14
-#define MXC_CCM_CGR1_SIM_MASK (0x3 << 14)
-#define MXC_CCM_CGR1_ECT_OFFSET 16
-#define MXC_CCM_CGR1_ECT_MASK (0x3 << 16)
-#define MXC_CCM_CGR1_USBOTG_OFFSET 18
-#define MXC_CCM_CGR1_USBOTG_MASK (0x3 << 18)
-#define MXC_CCM_CGR1_KPP_OFFSET 20
-#define MXC_CCM_CGR1_KPP_MASK (0x3 << 20)
-#define MXC_CCM_CGR1_IPU_OFFSET 22
-#define MXC_CCM_CGR1_IPU_MASK (0x3 << 22)
-#define MXC_CCM_CGR1_UART3_OFFSET 24
-#define MXC_CCM_CGR1_UART3_MASK (0x3 << 24)
-#define MXC_CCM_CGR1_UART4_OFFSET 26
-#define MXC_CCM_CGR1_UART4_MASK (0x3 << 26)
-#define MXC_CCM_CGR1_UART5_OFFSET 28
-#define MXC_CCM_CGR1_UART5_MASK (0x3 << 28)
-#define MXC_CCM_CGR1_OWIRE_OFFSET 30
-#define MXC_CCM_CGR1_OWIRE_MASK (0x3 << 30)
-
-#define MXC_CCM_CGR2_SSI2_OFFSET 0
-#define MXC_CCM_CGR2_SSI2_MASK (0x3 << 0)
-#define MXC_CCM_CGR2_CSPI1_OFFSET 2
-#define MXC_CCM_CGR2_CSPI1_MASK (0x3 << 2)
-#define MXC_CCM_CGR2_CSPI2_OFFSET 4
-#define MXC_CCM_CGR2_CSPI2_MASK (0x3 << 4)
-#define MXC_CCM_CGR2_GACC_OFFSET 6
-#define MXC_CCM_CGR2_GACC_MASK (0x3 << 6)
-#define MXC_CCM_CGR2_EMI_OFFSET 8
-#define MXC_CCM_CGR2_EMI_MASK (0x3 << 8)
-#define MXC_CCM_CGR2_RTIC_OFFSET 10
-#define MXC_CCM_CGR2_RTIC_MASK (0x3 << 10)
-#define MXC_CCM_CGR2_FIRI_OFFSET 12
-#define MXC_CCM_CGR2_FIRI_MASK (0x3 << 12)
-#define MXC_CCM_CGR2_IPMUX1_OFFSET 14
-#define MXC_CCM_CGR2_IPMUX1_MASK (0x3 << 14)
-#define MXC_CCM_CGR2_IPMUX2_OFFSET 16
-#define MXC_CCM_CGR2_IPMUX2_MASK (0x3 << 16)
-
-/* These new CGR2 bits are added in MX32 */
-#define MXC_CCM_CGR2_APMSYSCLKSEL_OFFSET 18
-#define MXC_CCM_CGR2_APMSYSCLKSEL_MASK (0x3 << 18)
-#define MXC_CCM_CGR2_APMSSICLKSEL_OFFSET 20
-#define MXC_CCM_CGR2_APMSSICLKSEL_MASK (0x3 << 20)
-#define MXC_CCM_CGR2_APMPERCLKSEL_OFFSET 22
-#define MXC_CCM_CGR2_APMPERCLKSEL_MASK (0x3 << 22)
-#define MXC_CCM_CGR2_MXCCLKENSEL_OFFSET 24
-#define MXC_CCM_CGR2_MXCCLKENSEL_MASK (0x1 << 24)
-#define MXC_CCM_CGR2_CHIKCAMPEN_OFFSET 25
-#define MXC_CCM_CGR2_CHIKCAMPEN_MASK (0x1 << 25)
-#define MXC_CCM_CGR2_OVRVPUBUSY_OFFSET 26
-#define MXC_CCM_CGR2_OVRVPUBUSY_MASK (0x1 << 26)
-#define MXC_CCM_CGR2_APMENA_OFFSET 30
-#define MXC_CCM_CGR2_AOMENA_MASK (0x1 << 30)
-
/*
* LTR0 register offsets
*/
diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c
index f8428800f286..380be0c9b213 100644
--- a/arch/arm/mach-mx3/devices.c
+++ b/arch/arm/mach-mx3/devices.c
@@ -25,6 +25,8 @@
#include <mach/irqs.h>
#include <mach/imx-uart.h>
+#include "devices.h"
+
static struct resource uart0[] = {
{
.start = UART1_BASE_ADDR,
@@ -82,6 +84,7 @@ struct platform_device mxc_uart_device2 = {
.num_resources = ARRAY_SIZE(uart2),
};
+#ifdef CONFIG_ARCH_MX31
static struct resource uart3[] = {
{
.start = UART4_BASE_ADDR,
@@ -119,6 +122,7 @@ struct platform_device mxc_uart_device4 = {
.resource = uart4,
.num_resources = ARRAY_SIZE(uart4),
};
+#endif /* CONFIG_ARCH_MX31 */
/* GPIO port description */
static struct mxc_gpio_port imx_gpio_ports[] = {
@@ -164,8 +168,8 @@ struct platform_device mxc_w1_master_device = {
static struct resource mxc_nand_resources[] = {
{
- .start = NFC_BASE_ADDR,
- .end = NFC_BASE_ADDR + 0xfff,
+ .start = 0, /* runtime dependent */
+ .end = 0,
.flags = IORESOURCE_MEM
}, {
.start = MXC_INT_NANDFC,
@@ -180,3 +184,188 @@ struct platform_device mxc_nand_device = {
.num_resources = ARRAY_SIZE(mxc_nand_resources),
.resource = mxc_nand_resources,
};
+
+static struct resource mxc_i2c0_resources[] = {
+ {
+ .start = I2C_BASE_ADDR,
+ .end = I2C_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_I2C,
+ .end = MXC_INT_I2C,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_i2c_device0 = {
+ .name = "imx-i2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxc_i2c0_resources),
+ .resource = mxc_i2c0_resources,
+};
+
+static struct resource mxc_i2c1_resources[] = {
+ {
+ .start = I2C2_BASE_ADDR,
+ .end = I2C2_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_I2C2,
+ .end = MXC_INT_I2C2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_i2c_device1 = {
+ .name = "imx-i2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(mxc_i2c1_resources),
+ .resource = mxc_i2c1_resources,
+};
+
+static struct resource mxc_i2c2_resources[] = {
+ {
+ .start = I2C3_BASE_ADDR,
+ .end = I2C3_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_I2C3,
+ .end = MXC_INT_I2C3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_i2c_device2 = {
+ .name = "imx-i2c",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(mxc_i2c2_resources),
+ .resource = mxc_i2c2_resources,
+};
+
+#ifdef CONFIG_ARCH_MX31
+static struct resource mxcsdhc0_resources[] = {
+ {
+ .start = MMC_SDHC1_BASE_ADDR,
+ .end = MMC_SDHC1_BASE_ADDR + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = MXC_INT_MMC_SDHC1,
+ .end = MXC_INT_MMC_SDHC1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource mxcsdhc1_resources[] = {
+ {
+ .start = MMC_SDHC2_BASE_ADDR,
+ .end = MMC_SDHC2_BASE_ADDR + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = MXC_INT_MMC_SDHC2,
+ .end = MXC_INT_MMC_SDHC2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxcsdhc_device0 = {
+ .name = "mxc-mmc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxcsdhc0_resources),
+ .resource = mxcsdhc0_resources,
+};
+
+struct platform_device mxcsdhc_device1 = {
+ .name = "mxc-mmc",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(mxcsdhc1_resources),
+ .resource = mxcsdhc1_resources,
+};
+#endif /* CONFIG_ARCH_MX31 */
+
+/* i.MX31 Image Processing Unit */
+
+/* The resource order is important! */
+static struct resource mx3_ipu_rsrc[] = {
+ {
+ .start = IPU_CTRL_BASE_ADDR,
+ .end = IPU_CTRL_BASE_ADDR + 0x5F,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IPU_CTRL_BASE_ADDR + 0x88,
+ .end = IPU_CTRL_BASE_ADDR + 0xB3,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = MXC_INT_IPU_SYN,
+ .end = MXC_INT_IPU_SYN,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .start = MXC_INT_IPU_ERR,
+ .end = MXC_INT_IPU_ERR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mx3_ipu = {
+ .name = "ipu-core",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(mx3_ipu_rsrc),
+ .resource = mx3_ipu_rsrc,
+};
+
+static struct resource fb_resources[] = {
+ {
+ .start = IPU_CTRL_BASE_ADDR + 0xB4,
+ .end = IPU_CTRL_BASE_ADDR + 0x1BF,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device mx3_fb = {
+ .name = "mx3_sdc_fb",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(fb_resources),
+ .resource = fb_resources,
+ .dev = {
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+#ifdef CONFIG_ARCH_MX35
+static struct resource mxc_fec_resources[] = {
+ {
+ .start = MXC_FEC_BASE_ADDR,
+ .end = MXC_FEC_BASE_ADDR + 0xfff,
+ .flags = IORESOURCE_MEM
+ }, {
+ .start = MXC_INT_FEC,
+ .end = MXC_INT_FEC,
+ .flags = IORESOURCE_IRQ
+ },
+};
+
+struct platform_device mxc_fec_device = {
+ .name = "fec",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxc_fec_resources),
+ .resource = mxc_fec_resources,
+};
+#endif
+
+static int mx3_devices_init(void)
+{
+ if (cpu_is_mx31()) {
+ mxc_nand_resources[0].start = MX31_NFC_BASE_ADDR;
+ mxc_nand_resources[0].end = MX31_NFC_BASE_ADDR + 0xfff;
+ }
+ if (cpu_is_mx35()) {
+ mxc_nand_resources[0].start = MX35_NFC_BASE_ADDR;
+ mxc_nand_resources[0].end = MX35_NFC_BASE_ADDR + 0xfff;
+ }
+
+ return 0;
+}
+
+subsys_initcall(mx3_devices_init);
diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h
index 9949ef4e0694..88c04b296fab 100644
--- a/arch/arm/mach-mx3/devices.h
+++ b/arch/arm/mach-mx3/devices.h
@@ -6,3 +6,11 @@ extern struct platform_device mxc_uart_device3;
extern struct platform_device mxc_uart_device4;
extern struct platform_device mxc_w1_master_device;
extern struct platform_device mxc_nand_device;
+extern struct platform_device mxc_i2c_device0;
+extern struct platform_device mxc_i2c_device1;
+extern struct platform_device mxc_i2c_device2;
+extern struct platform_device mx3_ipu;
+extern struct platform_device mx3_fb;
+extern struct platform_device mxc_fec_device;
+extern struct platform_device mxcsdhc_device0;
+extern struct platform_device mxcsdhc_device1;
diff --git a/arch/arm/mach-mx3/iomux.c b/arch/arm/mach-mx3/iomux.c
index 7a5088b519a8..40ffc5a664d9 100644
--- a/arch/arm/mach-mx3/iomux.c
+++ b/arch/arm/mach-mx3/iomux.c
@@ -1,6 +1,7 @@
/*
* Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Valentin Longchamp <valentin.longchamp@epfl.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -21,6 +22,7 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/gpio.h>
+#include <linux/kernel.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
#include <mach/iomux-mx3.h>
@@ -38,6 +40,8 @@
static DEFINE_SPINLOCK(gpio_mux_lock);
#define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3)
+
+unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
/*
* set the mode for a IOMUX pin.
*/
@@ -50,9 +54,6 @@ int mxc_iomux_mode(unsigned int pin_mode)
field = pin_mode & 0x3;
mode = (pin_mode & IOMUX_MODE_MASK) >> IOMUX_MODE_SHIFT;
- pr_debug("%s: reg offset = 0x%x field = %d mode = 0x%02x\n",
- __func__, (pin_mode & IOMUX_REG_MASK), field, mode);
-
spin_lock(&gpio_mux_lock);
l = __raw_readl(reg);
@@ -93,6 +94,86 @@ void mxc_iomux_set_pad(enum iomux_pins pin, u32 config)
EXPORT_SYMBOL(mxc_iomux_set_pad);
/*
+ * setups a single pin:
+ * - reserves the pin so that it is not claimed by another driver
+ * - setups the iomux according to the configuration
+ * - if the pin is configured as a GPIO, we claim it through kernel gpiolib
+ */
+int mxc_iomux_setup_pin(const unsigned int pin, const char *label)
+{
+ unsigned pad = pin & IOMUX_PADNUM_MASK;
+ unsigned gpio;
+
+ if (pad >= (PIN_MAX + 1)) {
+ printk(KERN_ERR "mxc_iomux: Attempt to request nonexistant pin %u for \"%s\"\n",
+ pad, label ? label : "?");
+ return -EINVAL;
+ }
+
+ if (test_and_set_bit(pad, mxc_pin_alloc_map)) {
+ printk(KERN_ERR "mxc_iomux: pin %u already used. Allocation for \"%s\" failed\n",
+ pad, label ? label : "?");
+ return -EINVAL;
+ }
+ mxc_iomux_mode(pin);
+
+ /* if we have a gpio, we can allocate it */
+ gpio = (pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT;
+ if (gpio < (GPIO_PORT_MAX + 1) * 32)
+ if (gpio_request(gpio, label))
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL(mxc_iomux_setup_pin);
+
+int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+ const char *label)
+{
+ unsigned int *p = pin_list;
+ int i;
+ int ret = -EINVAL;
+
+ for (i = 0; i < count; i++) {
+ if (mxc_iomux_setup_pin(*p, label))
+ goto setup_error;
+ p++;
+ }
+ return 0;
+
+setup_error:
+ mxc_iomux_release_multiple_pins(pin_list, i);
+ return ret;
+}
+EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins);
+
+void mxc_iomux_release_pin(const unsigned int pin)
+{
+ unsigned pad = pin & IOMUX_PADNUM_MASK;
+ unsigned gpio;
+
+ if (pad < (PIN_MAX + 1))
+ clear_bit(pad, mxc_pin_alloc_map);
+
+ gpio = (pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT;
+ if (gpio < (GPIO_PORT_MAX + 1) * 32)
+ gpio_free(gpio);
+}
+EXPORT_SYMBOL(mxc_iomux_release_pin);
+
+void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count)
+{
+ unsigned int *p = pin_list;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ mxc_iomux_release_pin(*p);
+ p++;
+ }
+}
+EXPORT_SYMBOL(mxc_iomux_release_multiple_pins);
+
+/*
* This function enables/disables the general purpose function for a particular
* signal.
*/
@@ -111,4 +192,3 @@ void mxc_iomux_set_gpr(enum iomux_gp_func gp, bool en)
spin_unlock(&gpio_mux_lock);
}
EXPORT_SYMBOL(mxc_iomux_set_gpr);
-
diff --git a/arch/arm/mach-mx3/mm.c b/arch/arm/mach-mx3/mm.c
index 0589b5cd33c7..9e1459cb4b74 100644
--- a/arch/arm/mach-mx3/mm.c
+++ b/arch/arm/mach-mx3/mm.c
@@ -22,10 +22,14 @@
#include <linux/mm.h>
#include <linux/init.h>
-#include <mach/hardware.h>
+#include <linux/err.h>
+
#include <asm/pgtable.h>
#include <asm/mach/map.h>
+#include <asm/hardware/cache-l2x0.h>
+
#include <mach/common.h>
+#include <mach/hardware.h>
/*!
* @file mm.c
@@ -50,6 +54,16 @@ static struct map_desc mxc_io_desc[] __initdata = {
.pfn = __phys_to_pfn(AVIC_BASE_ADDR),
.length = AVIC_SIZE,
.type = MT_DEVICE_NONSHARED
+ }, {
+ .virtual = AIPS1_BASE_ADDR_VIRT,
+ .pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
+ .length = AIPS1_SIZE,
+ .type = MT_DEVICE_NONSHARED
+ }, {
+ .virtual = AIPS2_BASE_ADDR_VIRT,
+ .pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
+ .length = AIPS2_SIZE,
+ .type = MT_DEVICE_NONSHARED
},
};
@@ -62,3 +76,24 @@ void __init mxc_map_io(void)
{
iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
}
+
+#ifdef CONFIG_CACHE_L2X0
+static int mxc_init_l2x0(void)
+{
+ void __iomem *l2x0_base;
+
+ l2x0_base = ioremap(L2CC_BASE_ADDR, 4096);
+ if (IS_ERR(l2x0_base)) {
+ printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
+ PTR_ERR(l2x0_base));
+ return 0;
+ }
+
+ l2x0_init(l2x0_base, 0x00030024, 0x00000000);
+
+ return 0;
+}
+
+arch_initcall(mxc_init_l2x0);
+#endif
+
diff --git a/arch/arm/mach-mx3/mx31ads.c b/arch/arm/mach-mx3/mx31ads.c
index f902a7c37c31..83e5e8e1276f 100644
--- a/arch/arm/mach-mx3/mx31ads.c
+++ b/arch/arm/mach-mx3/mx31ads.c
@@ -22,6 +22,8 @@
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/serial_8250.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
#include <linux/irq.h>
#include <mach/hardware.h>
@@ -35,6 +37,12 @@
#include <mach/imx-uart.h>
#include <mach/iomux-mx3.h>
+#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
+#include <linux/mfd/wm8350/audio.h>
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/pmic.h>
+#endif
+
#include "devices.h"
/*!
@@ -94,13 +102,16 @@ static struct imxuart_platform_data uart_pdata = {
.flags = IMXUART_HAVE_RTSCTS,
};
+static int uart_pins[] = {
+ MX31_PIN_CTS1__CTS1,
+ MX31_PIN_RTS1__RTS1,
+ MX31_PIN_TXD1__TXD1,
+ MX31_PIN_RXD1__RXD1
+};
+
static inline void mxc_init_imx_uart(void)
{
- mxc_iomux_mode(MX31_PIN_CTS1__CTS1);
- mxc_iomux_mode(MX31_PIN_RTS1__RTS1);
- mxc_iomux_mode(MX31_PIN_TXD1__TXD1);
- mxc_iomux_mode(MX31_PIN_RXD1__RXD1);
-
+ mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), "uart-0");
mxc_register_device(&mxc_uart_device0, &uart_pdata);
}
#else /* !SERIAL_IMX */
@@ -176,7 +187,7 @@ static void __init mx31ads_init_expio(void)
/*
* Configure INT line as GPIO input
*/
- mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO1_4, IOMUX_CONFIG_GPIO));
+ mxc_iomux_setup_pin(IOMUX_MODE(MX31_PIN_GPIO1_4, IOMUX_CONFIG_GPIO), "expio");
/* disable the interrupt and clear the status */
__raw_writew(0xFFFF, PBC_INTMASK_CLEAR_REG);
@@ -191,26 +202,301 @@ static void __init mx31ads_init_expio(void)
set_irq_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler);
}
+#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
+/* This section defines setup for the Wolfson Microelectronics
+ * 1133-EV1 PMU/audio board. When other PMU boards are supported the
+ * regulator definitions may be shared with them, but for now they can
+ * only be used with this board so would generate warnings about
+ * unused statics and some of the configuration is specific to this
+ * module.
+ */
+
+/* CPU */
+static struct regulator_consumer_supply sw1a_consumers[] = {
+ {
+ .supply = "cpu_vcc",
+ }
+};
+
+static struct regulator_init_data sw1a_data = {
+ .constraints = {
+ .name = "SW1A",
+ .min_uV = 1275000,
+ .max_uV = 1600000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_MODE,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL |
+ REGULATOR_MODE_FAST,
+ .state_mem = {
+ .uV = 1400000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ .initial_state = PM_SUSPEND_MEM,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1a_consumers),
+ .consumer_supplies = sw1a_consumers,
+};
+
+/* System IO - High */
+static struct regulator_init_data viohi_data = {
+ .constraints = {
+ .name = "VIOHO",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .state_mem = {
+ .uV = 2800000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ .initial_state = PM_SUSPEND_MEM,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+/* System IO - Low */
+static struct regulator_init_data violo_data = {
+ .constraints = {
+ .name = "VIOLO",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .state_mem = {
+ .uV = 1800000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ .initial_state = PM_SUSPEND_MEM,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+/* DDR RAM */
+static struct regulator_init_data sw2a_data = {
+ .constraints = {
+ .name = "SW2A",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .state_mem = {
+ .uV = 1800000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ .state_disk = {
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 0,
+ },
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ },
+};
+
+static struct regulator_init_data ldo1_data = {
+ .constraints = {
+ .name = "VCAM/VMMC1/VMMC2",
+ .min_uV = 2800000,
+ .max_uV = 2800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .apply_uV = 1,
+ },
+};
+
+static struct regulator_consumer_supply ldo2_consumers[] = {
+ {
+ .supply = "AVDD",
+ },
+ {
+ .supply = "HPVDD",
+ },
+};
+
+/* CODEC and SIM */
+static struct regulator_init_data ldo2_data = {
+ .constraints = {
+ .name = "VESIM/VSIM/AVDD",
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .apply_uV = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ldo2_consumers),
+ .consumer_supplies = ldo2_consumers,
+};
+
+/* General */
+static struct regulator_init_data vdig_data = {
+ .constraints = {
+ .name = "VDIG",
+ .min_uV = 1500000,
+ .max_uV = 1500000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .apply_uV = 1,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+/* Tranceivers */
+static struct regulator_init_data ldo4_data = {
+ .constraints = {
+ .name = "VRF1/CVDD_2.775",
+ .min_uV = 2500000,
+ .max_uV = 2500000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .apply_uV = 1,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct wm8350_led_platform_data wm8350_led_data = {
+ .name = "wm8350:white",
+ .default_trigger = "heartbeat",
+ .max_uA = 27899,
+};
+
+static struct wm8350_audio_platform_data imx32ads_wm8350_setup = {
+ .vmid_discharge_msecs = 1000,
+ .drain_msecs = 30,
+ .cap_discharge_msecs = 700,
+ .vmid_charge_msecs = 700,
+ .vmid_s_curve = WM8350_S_CURVE_SLOW,
+ .dis_out4 = WM8350_DISCHARGE_SLOW,
+ .dis_out3 = WM8350_DISCHARGE_SLOW,
+ .dis_out2 = WM8350_DISCHARGE_SLOW,
+ .dis_out1 = WM8350_DISCHARGE_SLOW,
+ .vroi_out4 = WM8350_TIE_OFF_500R,
+ .vroi_out3 = WM8350_TIE_OFF_500R,
+ .vroi_out2 = WM8350_TIE_OFF_500R,
+ .vroi_out1 = WM8350_TIE_OFF_500R,
+ .vroi_enable = 0,
+ .codec_current_on = WM8350_CODEC_ISEL_1_0,
+ .codec_current_standby = WM8350_CODEC_ISEL_0_5,
+ .codec_current_charge = WM8350_CODEC_ISEL_1_5,
+};
+
+static int mx31_wm8350_init(struct wm8350 *wm8350)
+{
+ int i;
+
+ wm8350_gpio_config(wm8350, 0, WM8350_GPIO_DIR_IN,
+ WM8350_GPIO0_PWR_ON_IN, WM8350_GPIO_ACTIVE_LOW,
+ WM8350_GPIO_PULL_UP, WM8350_GPIO_INVERT_OFF,
+ WM8350_GPIO_DEBOUNCE_ON);
+
+ wm8350_gpio_config(wm8350, 3, WM8350_GPIO_DIR_IN,
+ WM8350_GPIO3_PWR_OFF_IN, WM8350_GPIO_ACTIVE_HIGH,
+ WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
+ WM8350_GPIO_DEBOUNCE_ON);
+
+ wm8350_gpio_config(wm8350, 4, WM8350_GPIO_DIR_IN,
+ WM8350_GPIO4_MR_IN, WM8350_GPIO_ACTIVE_HIGH,
+ WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
+ WM8350_GPIO_DEBOUNCE_OFF);
+
+ wm8350_gpio_config(wm8350, 7, WM8350_GPIO_DIR_IN,
+ WM8350_GPIO7_HIBERNATE_IN, WM8350_GPIO_ACTIVE_HIGH,
+ WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
+ WM8350_GPIO_DEBOUNCE_OFF);
+
+ wm8350_gpio_config(wm8350, 6, WM8350_GPIO_DIR_OUT,
+ WM8350_GPIO6_SDOUT_OUT, WM8350_GPIO_ACTIVE_HIGH,
+ WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
+ WM8350_GPIO_DEBOUNCE_OFF);
+
+ wm8350_gpio_config(wm8350, 8, WM8350_GPIO_DIR_OUT,
+ WM8350_GPIO8_VCC_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW,
+ WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
+ WM8350_GPIO_DEBOUNCE_OFF);
+
+ wm8350_gpio_config(wm8350, 9, WM8350_GPIO_DIR_OUT,
+ WM8350_GPIO9_BATT_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW,
+ WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
+ WM8350_GPIO_DEBOUNCE_OFF);
+
+ /* Fix up for our own supplies. */
+ for (i = 0; i < ARRAY_SIZE(ldo2_consumers); i++)
+ ldo2_consumers[i].dev = wm8350->dev;
+
+ wm8350_register_regulator(wm8350, WM8350_DCDC_1, &sw1a_data);
+ wm8350_register_regulator(wm8350, WM8350_DCDC_3, &viohi_data);
+ wm8350_register_regulator(wm8350, WM8350_DCDC_4, &violo_data);
+ wm8350_register_regulator(wm8350, WM8350_DCDC_6, &sw2a_data);
+ wm8350_register_regulator(wm8350, WM8350_LDO_1, &ldo1_data);
+ wm8350_register_regulator(wm8350, WM8350_LDO_2, &ldo2_data);
+ wm8350_register_regulator(wm8350, WM8350_LDO_3, &vdig_data);
+ wm8350_register_regulator(wm8350, WM8350_LDO_4, &ldo4_data);
+
+ /* LEDs */
+ wm8350_dcdc_set_slot(wm8350, WM8350_DCDC_5, 1, 1,
+ WM8350_DC5_ERRACT_SHUTDOWN_CONV);
+ wm8350_isink_set_flash(wm8350, WM8350_ISINK_A,
+ WM8350_ISINK_FLASH_DISABLE,
+ WM8350_ISINK_FLASH_TRIG_BIT,
+ WM8350_ISINK_FLASH_DUR_32MS,
+ WM8350_ISINK_FLASH_ON_INSTANT,
+ WM8350_ISINK_FLASH_OFF_INSTANT,
+ WM8350_ISINK_FLASH_MODE_EN);
+ wm8350_dcdc25_set_mode(wm8350, WM8350_DCDC_5,
+ WM8350_ISINK_MODE_BOOST,
+ WM8350_ISINK_ILIM_NORMAL,
+ WM8350_DC5_RMP_20V,
+ WM8350_DC5_FBSRC_ISINKA);
+ wm8350_register_led(wm8350, 0, WM8350_DCDC_5, WM8350_ISINK_A,
+ &wm8350_led_data);
+
+ wm8350->codec.platform_data = &imx32ads_wm8350_setup;
+
+ return 0;
+}
+
+static struct wm8350_platform_data __initdata mx31_wm8350_pdata = {
+ .init = mx31_wm8350_init,
+};
+#endif
+
+#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
+static struct i2c_board_info __initdata mx31ads_i2c1_devices[] = {
+#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
+ {
+ I2C_BOARD_INFO("wm8350", 0x1a),
+ .platform_data = &mx31_wm8350_pdata,
+ .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+ },
+#endif
+};
+
+static void mxc_init_i2c(void)
+{
+ i2c_register_board_info(1, mx31ads_i2c1_devices,
+ ARRAY_SIZE(mx31ads_i2c1_devices));
+
+ mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_ALT1));
+ mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_ALT1));
+
+ mxc_register_device(&mxc_i2c_device1, NULL);
+}
+#else
+static void mxc_init_i2c(void)
+{
+}
+#endif
+
/*!
* This structure defines static mappings for the i.MX31ADS board.
*/
static struct map_desc mx31ads_io_desc[] __initdata = {
{
- .virtual = AIPS1_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
- .length = AIPS1_SIZE,
- .type = MT_DEVICE_NONSHARED
- }, {
.virtual = SPBA0_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
.length = SPBA0_SIZE,
.type = MT_DEVICE_NONSHARED
}, {
- .virtual = AIPS2_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
- .length = AIPS2_SIZE,
- .type = MT_DEVICE_NONSHARED
- }, {
.virtual = CS4_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(CS4_BASE_ADDR),
.length = CS4_SIZE / 2,
@@ -221,13 +507,13 @@ static struct map_desc mx31ads_io_desc[] __initdata = {
/*!
* Set up static virtual mappings.
*/
-void __init mx31ads_map_io(void)
+static void __init mx31ads_map_io(void)
{
mxc_map_io();
iotable_init(mx31ads_io_desc, ARRAY_SIZE(mx31ads_io_desc));
}
-void __init mx31ads_init_irq(void)
+static void __init mx31ads_init_irq(void)
{
mxc_init_irq();
mx31ads_init_expio();
@@ -240,15 +526,15 @@ static void __init mxc_board_init(void)
{
mxc_init_extuart();
mxc_init_imx_uart();
+ mxc_init_i2c();
}
static void __init mx31ads_timer_init(void)
{
- mxc_clocks_init(26000000);
- mxc_timer_init("ipg_clk.0");
+ mx31_clocks_init(26000000);
}
-struct sys_timer mx31ads_timer = {
+static struct sys_timer mx31ads_timer = {
.init = mx31ads_timer_init,
};
diff --git a/arch/arm/mach-mx3/mx31lite.c b/arch/arm/mach-mx3/mx31lite.c
index c43440070143..894d98cd9941 100644
--- a/arch/arm/mach-mx3/mx31lite.c
+++ b/arch/arm/mach-mx3/mx31lite.c
@@ -42,21 +42,11 @@
*/
static struct map_desc mx31lite_io_desc[] __initdata = {
{
- .virtual = AIPS1_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
- .length = AIPS1_SIZE,
- .type = MT_DEVICE_NONSHARED
- }, {
.virtual = SPBA0_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
.length = SPBA0_SIZE,
.type = MT_DEVICE_NONSHARED
}, {
- .virtual = AIPS2_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
- .length = AIPS2_SIZE,
- .type = MT_DEVICE_NONSHARED
- }, {
.virtual = CS4_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(CS4_BASE_ADDR),
.length = CS4_SIZE,
@@ -82,8 +72,7 @@ static void __init mxc_board_init(void)
static void __init mx31lite_timer_init(void)
{
- mxc_clocks_init(26000000);
- mxc_timer_init("ipg_clk.0");
+ mx31_clocks_init(26000000);
}
struct sys_timer mx31lite_timer = {
diff --git a/arch/arm/mach-mx3/mx31moboard-devboard.c b/arch/arm/mach-mx3/mx31moboard-devboard.c
new file mode 100644
index 000000000000..d080b4add79c
--- /dev/null
+++ b/arch/arm/mach-mx3/mx31moboard-devboard.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+
+#include "devices.h"
+
+static struct imxuart_platform_data uart_pdata = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int mxc_uart1_pins[] = {
+ MX31_PIN_CTS2__CTS2, MX31_PIN_RTS2__RTS2,
+ MX31_PIN_TXD2__TXD2, MX31_PIN_RXD2__RXD2,
+};
+
+/*
+ * system init for baseboard usage. Will be called by mx31moboard init.
+ */
+void __init mx31moboard_devboard_init(void)
+{
+ printk(KERN_INFO "Initializing mx31devboard peripherals\n");
+ mxc_iomux_setup_multiple_pins(mxc_uart1_pins, ARRAY_SIZE(mxc_uart1_pins), "uart1");
+ mxc_register_device(&mxc_uart_device1, &uart_pdata);
+}
diff --git a/arch/arm/mach-mx3/mx31moboard-marxbot.c b/arch/arm/mach-mx3/mx31moboard-marxbot.c
new file mode 100644
index 000000000000..9ef9566823fb
--- /dev/null
+++ b/arch/arm/mach-mx3/mx31moboard-marxbot.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+
+#include "devices.h"
+
+/*
+ * system init for baseboard usage. Will be called by mx31moboard init.
+ */
+void __init mx31moboard_marxbot_init(void)
+{
+ printk(KERN_INFO "Initializing mx31marxbot peripherals\n");
+}
diff --git a/arch/arm/mach-mx3/mx31moboard.c b/arch/arm/mach-mx3/mx31moboard.c
index c29098af7394..34c2a1b99d4f 100644
--- a/arch/arm/mach-mx3/mx31moboard.c
+++ b/arch/arm/mach-mx3/mx31moboard.c
@@ -32,6 +32,7 @@
#include <mach/common.h>
#include <mach/imx-uart.h>
#include <mach/iomux-mx3.h>
+#include <mach/board-mx31moboard.h>
#include "devices.h"
@@ -63,6 +64,18 @@ static struct platform_device *devices[] __initdata = {
&mx31moboard_flash,
};
+static int mxc_uart0_pins[] = {
+ MX31_PIN_CTS1__CTS1, MX31_PIN_RTS1__RTS1,
+ MX31_PIN_TXD1__TXD1, MX31_PIN_RXD1__RXD1,
+};
+static int mxc_uart4_pins[] = {
+ MX31_PIN_PC_RST__CTS5, MX31_PIN_PC_VS2__RTS5,
+ MX31_PIN_PC_BVD2__TXD5, MX31_PIN_PC_BVD1__RXD5,
+};
+
+static int mx31moboard_baseboard;
+core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
+
/*
* Board specific initialization.
*/
@@ -70,58 +83,29 @@ static void __init mxc_board_init(void)
{
platform_add_devices(devices, ARRAY_SIZE(devices));
- mxc_iomux_mode(MX31_PIN_CTS1__CTS1);
- mxc_iomux_mode(MX31_PIN_RTS1__RTS1);
- mxc_iomux_mode(MX31_PIN_TXD1__TXD1);
- mxc_iomux_mode(MX31_PIN_RXD1__RXD1);
-
+ mxc_iomux_setup_multiple_pins(mxc_uart0_pins, ARRAY_SIZE(mxc_uart0_pins), "uart0");
mxc_register_device(&mxc_uart_device0, &uart_pdata);
- mxc_iomux_mode(MX31_PIN_CTS2__CTS2);
- mxc_iomux_mode(MX31_PIN_RTS2__RTS2);
- mxc_iomux_mode(MX31_PIN_TXD2__TXD2);
- mxc_iomux_mode(MX31_PIN_RXD2__RXD2);
-
- mxc_register_device(&mxc_uart_device1, &uart_pdata);
-
- mxc_iomux_mode(MX31_PIN_PC_RST__CTS5);
- mxc_iomux_mode(MX31_PIN_PC_VS2__RTS5);
- mxc_iomux_mode(MX31_PIN_PC_BVD2__TXD5);
- mxc_iomux_mode(MX31_PIN_PC_BVD1__RXD5);
-
+ mxc_iomux_setup_multiple_pins(mxc_uart4_pins, ARRAY_SIZE(mxc_uart4_pins), "uart4");
mxc_register_device(&mxc_uart_device4, &uart_pdata);
-}
-/*
- * This structure defines static mappings for the mx31moboard.
- */
-static struct map_desc mx31moboard_io_desc[] __initdata = {
- {
- .virtual = AIPS1_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
- .length = AIPS1_SIZE,
- .type = MT_DEVICE_NONSHARED
- }, {
- .virtual = AIPS2_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
- .length = AIPS2_SIZE,
- .type = MT_DEVICE_NONSHARED
- },
-};
-
-/*
- * Set up static virtual mappings.
- */
-void __init mx31moboard_map_io(void)
-{
- mxc_map_io();
- iotable_init(mx31moboard_io_desc, ARRAY_SIZE(mx31moboard_io_desc));
+ switch (mx31moboard_baseboard) {
+ case MX31NOBOARD:
+ break;
+ case MX31DEVBOARD:
+ mx31moboard_devboard_init();
+ break;
+ case MX31MARXBOT:
+ mx31moboard_marxbot_init();
+ break;
+ default:
+ printk(KERN_ERR "Illegal mx31moboard_baseboard type %d\n", mx31moboard_baseboard);
+ }
}
static void __init mx31moboard_timer_init(void)
{
- mxc_clocks_init(26000000);
- mxc_timer_init("ipg_clk.0");
+ mx31_clocks_init(26000000);
}
struct sys_timer mx31moboard_timer = {
@@ -133,7 +117,7 @@ MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
.phys_io = AIPS1_BASE_ADDR,
.io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x100,
- .map_io = mx31moboard_map_io,
+ .map_io = mxc_map_io,
.init_irq = mxc_init_irq,
.init_machine = mxc_board_init,
.timer = &mx31moboard_timer,
diff --git a/arch/arm/mach-mx3/mx31pdk.c b/arch/arm/mach-mx3/mx31pdk.c
index d464d068a4a6..bc63f1785691 100644
--- a/arch/arm/mach-mx3/mx31pdk.c
+++ b/arch/arm/mach-mx3/mx31pdk.c
@@ -45,40 +45,17 @@ static struct imxuart_platform_data uart_pdata = {
.flags = IMXUART_HAVE_RTSCTS,
};
-static inline void mxc_init_imx_uart(void)
-{
- mxc_iomux_mode(MX31_PIN_CTS1__CTS1);
- mxc_iomux_mode(MX31_PIN_RTS1__RTS1);
- mxc_iomux_mode(MX31_PIN_TXD1__TXD1);
- mxc_iomux_mode(MX31_PIN_RXD1__RXD1);
-
- mxc_register_device(&mxc_uart_device0, &uart_pdata);
-}
-
-/*!
- * This structure defines static mappings for the i.MX31PDK board.
- */
-static struct map_desc mx31pdk_io_desc[] __initdata = {
- {
- .virtual = AIPS1_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
- .length = AIPS1_SIZE,
- .type = MT_DEVICE_NONSHARED
- }, {
- .virtual = AIPS2_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
- .length = AIPS2_SIZE,
- .type = MT_DEVICE_NONSHARED
- },
+static int uart_pins[] = {
+ MX31_PIN_CTS1__CTS1,
+ MX31_PIN_RTS1__RTS1,
+ MX31_PIN_TXD1__TXD1,
+ MX31_PIN_RXD1__RXD1
};
-/*!
- * Set up static virtual mappings.
- */
-static void __init mx31pdk_map_io(void)
+static inline void mxc_init_imx_uart(void)
{
- mxc_map_io();
- iotable_init(mx31pdk_io_desc, ARRAY_SIZE(mx31pdk_io_desc));
+ mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), "uart-0");
+ mxc_register_device(&mxc_uart_device0, &uart_pdata);
}
/*!
@@ -91,8 +68,7 @@ static void __init mxc_board_init(void)
static void __init mx31pdk_timer_init(void)
{
- mxc_clocks_init(26000000);
- mxc_timer_init("ipg_clk.0");
+ mx31_clocks_init(26000000);
}
static struct sys_timer mx31pdk_timer = {
@@ -108,7 +84,7 @@ MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
.phys_io = AIPS1_BASE_ADDR,
.io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x100,
- .map_io = mx31pdk_map_io,
+ .map_io = mxc_map_io,
.init_irq = mxc_init_irq,
.init_machine = mxc_board_init,
.timer = &mx31pdk_timer,
diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
index 8cea82587222..5fce022114de 100644
--- a/arch/arm/mach-mx3/pcm037.c
+++ b/arch/arm/mach-mx3/pcm037.c
@@ -26,6 +26,8 @@
#include <linux/gpio.h>
#include <linux/smc911x.h>
#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -37,6 +39,10 @@
#include <mach/iomux-mx3.h>
#include <mach/board-pcm037.h>
#include <mach/mxc_nand.h>
+#include <mach/mmc.h>
+#ifdef CONFIG_I2C_IMX
+#include <mach/i2c.h>
+#endif
#include "devices.h"
@@ -117,12 +123,90 @@ static struct mxc_nand_platform_data pcm037_nand_board_info = {
.hw_ecc = 1,
};
+#ifdef CONFIG_I2C_IMX
+static int i2c_1_pins[] = {
+ MX31_PIN_CSPI2_MOSI__SCL,
+ MX31_PIN_CSPI2_MISO__SDA,
+};
+
+static int pcm037_i2c_1_init(struct device *dev)
+{
+ return mxc_iomux_setup_multiple_pins(i2c_1_pins, ARRAY_SIZE(i2c_1_pins),
+ "i2c-1");
+}
+
+static void pcm037_i2c_1_exit(struct device *dev)
+{
+ mxc_iomux_release_multiple_pins(i2c_1_pins, ARRAY_SIZE(i2c_1_pins));
+}
+
+static struct imxi2c_platform_data pcm037_i2c_1_data = {
+ .bitrate = 100000,
+ .init = pcm037_i2c_1_init,
+ .exit = pcm037_i2c_1_exit,
+};
+
+static struct at24_platform_data board_eeprom = {
+ .byte_len = 4096,
+ .page_size = 32,
+ .flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info pcm037_i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
+ .platform_data = &board_eeprom,
+ }, {
+ I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+ .type = "pcf8563",
+ }
+};
+#endif
+
+static int sdhc1_pins[] = {
+ MX31_PIN_SD1_DATA3__SD1_DATA3,
+ MX31_PIN_SD1_DATA2__SD1_DATA2,
+ MX31_PIN_SD1_DATA1__SD1_DATA1,
+ MX31_PIN_SD1_DATA0__SD1_DATA0,
+ MX31_PIN_SD1_CLK__SD1_CLK,
+ MX31_PIN_SD1_CMD__SD1_CMD,
+};
+
+static int pcm970_sdhc1_init(struct device *dev, irq_handler_t h, void *data)
+{
+ return mxc_iomux_setup_multiple_pins(sdhc1_pins, ARRAY_SIZE(sdhc1_pins),
+ "sdhc-1");
+}
+
+static void pcm970_sdhc1_exit(struct device *dev, void *data)
+{
+ mxc_iomux_release_multiple_pins(sdhc1_pins, ARRAY_SIZE(sdhc1_pins));
+}
+
+/* No card and rw detection at the moment */
+static struct imxmmc_platform_data sdhc_pdata = {
+ .init = pcm970_sdhc1_init,
+ .exit = pcm970_sdhc1_exit,
+};
+
static struct platform_device *devices[] __initdata = {
&pcm037_flash,
&pcm037_eth,
&pcm037_sram_device,
};
+static int uart0_pins[] = {
+ MX31_PIN_CTS1__CTS1,
+ MX31_PIN_RTS1__RTS1,
+ MX31_PIN_TXD1__TXD1,
+ MX31_PIN_RXD1__RXD1
+};
+
+static int uart2_pins[] = {
+ MX31_PIN_CSPI3_MOSI__RXD3,
+ MX31_PIN_CSPI3_MISO__TXD3
+};
+
/*
* Board specific initialization.
*/
@@ -130,59 +214,33 @@ static void __init mxc_board_init(void)
{
platform_add_devices(devices, ARRAY_SIZE(devices));
- mxc_iomux_mode(MX31_PIN_CTS1__CTS1);
- mxc_iomux_mode(MX31_PIN_RTS1__RTS1);
- mxc_iomux_mode(MX31_PIN_TXD1__TXD1);
- mxc_iomux_mode(MX31_PIN_RXD1__RXD1);
-
+ mxc_iomux_setup_multiple_pins(uart0_pins, ARRAY_SIZE(uart0_pins), "uart-0");
mxc_register_device(&mxc_uart_device0, &uart_pdata);
- mxc_iomux_mode(MX31_PIN_CSPI3_MOSI__RXD3);
- mxc_iomux_mode(MX31_PIN_CSPI3_MISO__TXD3);
-
+ mxc_iomux_setup_multiple_pins(uart2_pins, ARRAY_SIZE(uart2_pins), "uart-2");
mxc_register_device(&mxc_uart_device2, &uart_pdata);
- mxc_iomux_mode(MX31_PIN_BATT_LINE__OWIRE);
+ mxc_iomux_setup_pin(MX31_PIN_BATT_LINE__OWIRE, "batt-0wire");
mxc_register_device(&mxc_w1_master_device, NULL);
/* SMSC9215 IRQ pin */
- mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO));
- if (!gpio_request(MX31_PIN_GPIO3_1, "pcm037-eth"))
+ if (!mxc_iomux_setup_pin(IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO),
+ "pcm037-eth"))
gpio_direction_input(MX31_PIN_GPIO3_1);
- mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
-}
+#ifdef CONFIG_I2C_IMX
+ i2c_register_board_info(1, pcm037_i2c_devices,
+ ARRAY_SIZE(pcm037_i2c_devices));
-/*
- * This structure defines static mappings for the pcm037 board.
- */
-static struct map_desc pcm037_io_desc[] __initdata = {
- {
- .virtual = AIPS1_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
- .length = AIPS1_SIZE,
- .type = MT_DEVICE_NONSHARED
- }, {
- .virtual = AIPS2_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
- .length = AIPS2_SIZE,
- .type = MT_DEVICE_NONSHARED
- },
-};
-
-/*
- * Set up static virtual mappings.
- */
-void __init pcm037_map_io(void)
-{
- mxc_map_io();
- iotable_init(pcm037_io_desc, ARRAY_SIZE(pcm037_io_desc));
+ mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
+#endif
+ mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
+ mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
}
static void __init pcm037_timer_init(void)
{
- mxc_clocks_init(26000000);
- mxc_timer_init("ipg_clk.0");
+ mx31_clocks_init(26000000);
}
struct sys_timer pcm037_timer = {
@@ -194,7 +252,7 @@ MACHINE_START(PCM037, "Phytec Phycore pcm037")
.phys_io = AIPS1_BASE_ADDR,
.io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
.boot_params = PHYS_OFFSET + 0x100,
- .map_io = pcm037_map_io,
+ .map_io = mxc_map_io,
.init_irq = mxc_init_irq,
.init_machine = mxc_board_init,
.timer = &pcm037_timer,
diff --git a/arch/arm/mach-mx3/qong.c b/arch/arm/mach-mx3/qong.c
new file mode 100644
index 000000000000..6c4283cec6f4
--- /dev/null
+++ b/arch/arm/mach-mx3/qong.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2009 Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/memory.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/nand.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <mach/common.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <mach/board-qong.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+#include "devices.h"
+
+/* FPGA defines */
+#define QONG_FPGA_VERSION(major, minor, rev) \
+ (((major & 0xF) << 12) | ((minor & 0xF) << 8) | (rev & 0xFF))
+
+#define QONG_FPGA_BASEADDR CS1_BASE_ADDR
+#define QONG_FPGA_PERIPH_SIZE (1 << 24)
+
+#define QONG_FPGA_CTRL_BASEADDR QONG_FPGA_BASEADDR
+#define QONG_FPGA_CTRL_SIZE 0x10
+/* FPGA control registers */
+#define QONG_FPGA_CTRL_VERSION 0x00
+
+#define QONG_DNET_ID 1
+#define QONG_DNET_BASEADDR \
+ (QONG_FPGA_BASEADDR + QONG_DNET_ID * QONG_FPGA_PERIPH_SIZE)
+#define QONG_DNET_SIZE 0x00001000
+
+#define QONG_FPGA_IRQ IOMUX_TO_IRQ(MX31_PIN_DTR_DCE1)
+
+/*
+ * This file contains the board-specific initialization routines.
+ */
+
+static struct imxuart_platform_data uart_pdata = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int uart_pins[] = {
+ MX31_PIN_CTS1__CTS1,
+ MX31_PIN_RTS1__RTS1,
+ MX31_PIN_TXD1__TXD1,
+ MX31_PIN_RXD1__RXD1
+};
+
+static inline void mxc_init_imx_uart(void)
+{
+ mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins),
+ "uart-0");
+ mxc_register_device(&mxc_uart_device0, &uart_pdata);
+}
+
+static struct resource dnet_resources[] = {
+ [0] = {
+ .name = "dnet-memory",
+ .start = QONG_DNET_BASEADDR,
+ .end = QONG_DNET_BASEADDR + QONG_DNET_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = QONG_FPGA_IRQ,
+ .end = QONG_FPGA_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device dnet_device = {
+ .name = "dnet",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(dnet_resources),
+ .resource = dnet_resources,
+};
+
+static int __init qong_init_dnet(void)
+{
+ int ret;
+
+ ret = platform_device_register(&dnet_device);
+ return ret;
+}
+
+/* MTD NOR flash */
+
+static struct physmap_flash_data qong_flash_data = {
+ .width = 2,
+};
+
+static struct resource qong_flash_resource = {
+ .start = CS0_BASE_ADDR,
+ .end = CS0_BASE_ADDR + QONG_NOR_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device qong_nor_mtd_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &qong_flash_data,
+ },
+ .resource = &qong_flash_resource,
+ .num_resources = 1,
+};
+
+static void qong_init_nor_mtd(void)
+{
+ (void)platform_device_register(&qong_nor_mtd_device);
+}
+
+/*
+ * Hardware specific access to control-lines
+ */
+static void qong_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+
+ if (cmd == NAND_CMD_NONE)
+ return;
+
+ if (ctrl & NAND_CLE)
+ writeb(cmd, nand_chip->IO_ADDR_W + (1 << 24));
+ else
+ writeb(cmd, nand_chip->IO_ADDR_W + (1 << 23));
+}
+
+/*
+ * Read the Device Ready pin.
+ */
+static int qong_nand_device_ready(struct mtd_info *mtd)
+{
+ return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_NFRB));
+}
+
+static void qong_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+ if (chip >= 0)
+ gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0);
+ else
+ gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 1);
+}
+
+static struct platform_nand_data qong_nand_data = {
+ .chip = {
+ .chip_delay = 20,
+ .options = 0,
+ },
+ .ctrl = {
+ .cmd_ctrl = qong_nand_cmd_ctrl,
+ .dev_ready = qong_nand_device_ready,
+ .select_chip = qong_nand_select_chip,
+ }
+};
+
+static struct resource qong_nand_resource = {
+ .start = CS3_BASE_ADDR,
+ .end = CS3_BASE_ADDR + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device qong_nand_device = {
+ .name = "gen_nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &qong_nand_data,
+ },
+ .num_resources = 1,
+ .resource = &qong_nand_resource,
+};
+
+static void __init qong_init_nand_mtd(void)
+{
+ /* init CS */
+ __raw_writel(0x00004f00, CSCR_U(3));
+ __raw_writel(0x20013b31, CSCR_L(3));
+ __raw_writel(0x00020800, CSCR_A(3));
+ mxc_iomux_set_gpr(MUX_SDCTL_CSD1_SEL, true);
+
+ /* enable pin */
+ mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFCE_B, IOMUX_CONFIG_GPIO));
+ if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), "nand_enable"))
+ gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0);
+
+ /* ready/busy pin */
+ mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFRB, IOMUX_CONFIG_GPIO));
+ if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFRB), "nand_rdy"))
+ gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFRB));
+
+ /* write protect pin */
+ mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFWP_B, IOMUX_CONFIG_GPIO));
+ if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFWP_B), "nand_wp"))
+ gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFWP_B));
+
+ platform_device_register(&qong_nand_device);
+}
+
+static void __init qong_init_fpga(void)
+{
+ void __iomem *regs;
+ u32 fpga_ver;
+
+ regs = ioremap(QONG_FPGA_CTRL_BASEADDR, QONG_FPGA_CTRL_SIZE);
+ if (!regs) {
+ printk(KERN_ERR "%s: failed to map registers, aborting.\n",
+ __func__);
+ return;
+ }
+
+ fpga_ver = readl(regs + QONG_FPGA_CTRL_VERSION);
+ iounmap(regs);
+ printk(KERN_INFO "Qong FPGA version %d.%d.%d\n",
+ (fpga_ver & 0xF000) >> 12,
+ (fpga_ver & 0x0F00) >> 8, fpga_ver & 0x00FF);
+ if (fpga_ver < QONG_FPGA_VERSION(0, 8, 7)) {
+ printk(KERN_ERR "qong: Unexpected FPGA version, FPGA-based "
+ "devices won't be registered!\n");
+ return;
+ }
+
+ /* register FPGA-based devices */
+ qong_init_nand_mtd();
+ qong_init_dnet();
+}
+
+/*
+ * This structure defines the MX31 memory map.
+ */
+static struct map_desc qong_io_desc[] __initdata = {
+ {
+ .virtual = AIPS1_BASE_ADDR_VIRT,
+ .pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
+ .length = AIPS1_SIZE,
+ .type = MT_DEVICE_NONSHARED
+ }, {
+ .virtual = AIPS2_BASE_ADDR_VIRT,
+ .pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
+ .length = AIPS2_SIZE,
+ .type = MT_DEVICE_NONSHARED
+ }
+};
+
+/*
+ * Set up static virtual mappings.
+ */
+static void __init qong_map_io(void)
+{
+ mxc_map_io();
+ iotable_init(qong_io_desc, ARRAY_SIZE(qong_io_desc));
+}
+
+/*
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+ mxc_init_imx_uart();
+ qong_init_nor_mtd();
+ qong_init_fpga();
+}
+
+static void __init qong_timer_init(void)
+{
+ mx31_clocks_init(26000000);
+}
+
+static struct sys_timer qong_timer = {
+ .init = qong_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros defined in arch.h in order to
+ * initialize __mach_desc_QONG data structure.
+ */
+
+MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
+ /* Maintainer: DENX Software Engineering GmbH */
+ .phys_io = AIPS1_BASE_ADDR,
+ .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+ .boot_params = PHYS_OFFSET + 0x100,
+ .map_io = qong_map_io,
+ .init_irq = mxc_init_irq,
+ .init_machine = mxc_board_init,
+ .timer = &qong_timer,
+MACHINE_END