summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2014-02-03 09:55:13 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2014-02-03 09:55:13 +0100
commitc224cd316197132321869d859048f89da49c0162 (patch)
tree275649e84cb143b3a389bf05c8416904b9da0dba /arch/arm/mach-imx
parent3cbd92bf6e96d4274e3a4f6aeceaf51d5406a0a6 (diff)
parentcc66cf109b1d2ca40c180a87fd76c2099dff2d92 (diff)
downloadbarebox-c224cd316197132321869d859048f89da49c0162.tar.gz
barebox-c224cd316197132321869d859048f89da49c0162.tar.xz
Merge branch 'for-next/imx'
Conflicts: arch/arm/boards/dmo-mx6-realq7/lowlevel.c
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/Kconfig68
-rw-r--r--arch/arm/mach-imx/clk-imx25.c3
-rw-r--r--arch/arm/mach-imx/clk-imx27.c44
-rw-r--r--arch/arm/mach-imx/clocksource.c2
-rw-r--r--arch/arm/mach-imx/external-nand-boot.c290
-rw-r--r--arch/arm/mach-imx/imx6.c41
-rw-r--r--arch/arm/mach-imx/include/mach/imx-gpio.h48
-rw-r--r--arch/arm/mach-imx/include/mach/imx-nand.h10
-rw-r--r--arch/arm/mach-imx/include/mach/imx25-regs.h3
-rw-r--r--arch/arm/mach-imx/include/mach/imx6.h49
10 files changed, 344 insertions, 214 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 3a1089f0ed..5933f81e95 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -38,8 +38,9 @@ config ARCH_TEXT_BASE
default 0x4fc00000 if MACH_PHYTEC_PFLA02
default 0x4fc00000 if MACH_DFI_FS700_M60
-choice
- prompt "Select boot mode"
+config ARCH_IMX_INTERNAL_BOOT
+ bool "support internal boot mode"
+ depends on ARCH_IMX25 || ARCH_IMX35 || ARCH_IMX51 || ARCH_IMX53 || ARCH_IMX6
depends on !HAVE_PBL_MULTI_IMAGES
help
i.MX processors support two different boot modes. With the internal
@@ -58,16 +59,6 @@ choice
The external boot mode is supported on older i.MX processors (i.MX1,
i.MX21, i.MX25, i.MX27, i.MX31, i.MX35).
-config ARCH_IMX_INTERNAL_BOOT
- bool "support internal boot mode"
- depends on ARCH_IMX25 || ARCH_IMX35 || ARCH_IMX51 || ARCH_IMX53 || ARCH_IMX6
-
-config ARCH_IMX_EXTERNAL_BOOT
- bool "support external boot mode"
- depends on ARCH_IMX1 || ARCH_IMX21 || ARCH_IMX25 || ARCH_IMX27 || ARCH_IMX31 || ARCH_IMX35
-
-endchoice
-
config ARCH_IMX_IMXIMAGE
bool
default y
@@ -105,16 +96,10 @@ config ARCH_IMX_INTERNAL_BOOT_SERIAL
endchoice
-config NAND_IMX_BOOT
- bool
- depends on ARCH_IMX_EXTERNAL_BOOT_NAND
- default y
-
config ARCH_IMX_EXTERNAL_BOOT_NAND
bool
- depends on !ARCH_IMX1
- prompt "Support Starting barebox from NAND"
- depends on ARCH_IMX_EXTERNAL_BOOT
+ depends on ARCH_IMX25 || ARCH_IMX27 || ARCH_IMX31 || ARCH_IMX35
+ prompt "Support Starting barebox from NAND in external bootmode"
config BAREBOX_UPDATE_IMX_EXTERNAL_NAND
bool
@@ -182,6 +167,13 @@ config IMX_MULTI_BOARDS
if IMX_MULTI_BOARDS
+config MACH_TX25
+ bool "Ka-Ro TX25"
+ select ARCH_IMX25
+ select ARCH_IMX_EXTERNAL_BOOT_NAND
+ help
+ Say Y here if you are using the Ka-Ro tx25 board
+
config MACH_EFIKA_MX_SMARTBOOK
bool "Efika MX smartbook"
select ARCH_IMX51
@@ -196,6 +188,10 @@ config MACH_FREESCALE_MX53_LOCO
bool "Freescale i.MX53 LOCO"
select ARCH_IMX53
+config MACH_TQMA53
+ bool "TQ i.MX53 TQMa53"
+ select ARCH_IMX53
+
config MACH_FREESCALE_MX53_VMX53
bool "Voipac i.MX53"
select ARCH_IMX53
@@ -229,8 +225,12 @@ config MACH_SABRELITE
select HAVE_DEFAULT_ENVIRONMENT_NEW
select HAVE_PBL_MULTI_IMAGES
-config MACH_SOLIDRUN_CARRIER1
- bool "SolidRun CuBox-i Carrier-1"
+config MACH_NITROGEN6X
+ bool "BoundaryDevices Nitrogen6x"
+ select ARCH_IMX6
+
+config MACH_SOLIDRUN_HUMMINGBOARD
+ bool "SolidRun Hummingboard"
select ARCH_IMX6
endif
@@ -282,13 +282,6 @@ config MACH_FREESCALE_MX25_3STACK
Say Y here if you are using the Freescale MX25 3stack board equipped
with a Freescale i.MX25 Processor
-config MACH_TX25
- bool "Ka-Ro TX25"
- select ARCH_IMX25
- select HAVE_DEFAULT_ENVIRONMENT_NEW
- help
- Say Y here if you are using the Ka-Ro tx25 board
-
# ----------------------------------------------------------
comment "i.MX27 Boards"
@@ -310,6 +303,8 @@ config MACH_IMX27ADS
config MACH_PCA100
bool "phyCard-i.MX27"
select ARCH_IMX27
+ select HAVE_DEFAULT_ENVIRONMENT_NEW
+ select ARCH_IMX_EXTERNAL_BOOT_NAND
help
Say Y here if you are using Phytec's phyCard-i.MX27 (pca100) equipped
with a Freescale i.MX27 Processor
@@ -439,11 +434,6 @@ config MACH_FREESCALE_MX53_SMD
bool "Freescale i.MX53 SMD"
select ARCH_IMX53
-config MACH_TQMA53
- bool "TQ i.MX53 TQMa53"
- select ARCH_IMX53
- select HAVE_DEFAULT_ENVIRONMENT_NEW
-
config MACH_TX53
bool "Ka-Ro TX53"
select ARCH_IMX53
@@ -539,16 +529,6 @@ endchoice
endif
-if MACH_TQMA53
-
-config MACH_TQMA53_1GB_RAM
- bool "Use 1GiB of SDRAM"
- depends on MACH_TQMA53
- help
- use 1GiB of SDRAM (512MiB otherwise)
-
-endif
-
if MACH_TX53
choice
diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c
index 9817990667..4d8631cb01 100644
--- a/arch/arm/mach-imx/clk-imx25.c
+++ b/arch/arm/mach-imx/clk-imx25.c
@@ -140,6 +140,9 @@ static int imx25_ccm_probe(struct device_d *dev)
clkdev_add_physbase(clks[per15], MX25_UART4_BASE_ADDR, NULL);
clkdev_add_physbase(clks[per15], MX25_UART5_BASE_ADDR, NULL);
clkdev_add_physbase(clks[per5], MX25_GPT1_BASE_ADDR, NULL);
+ clkdev_add_physbase(clks[per5], MX25_GPT2_BASE_ADDR, NULL);
+ clkdev_add_physbase(clks[per5], MX25_GPT3_BASE_ADDR, NULL);
+ clkdev_add_physbase(clks[per5], MX25_GPT4_BASE_ADDR, NULL);
clkdev_add_physbase(clks[ipg], MX25_FEC_BASE_ADDR, NULL);
clkdev_add_physbase(clks[ipg], MX25_I2C1_BASE_ADDR, NULL);
clkdev_add_physbase(clks[ipg], MX25_I2C2_BASE_ADDR, NULL);
diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
index 6fd3cd6fc8..c7922612e2 100644
--- a/arch/arm/mach-imx/clk-imx27.c
+++ b/arch/arm/mach-imx/clk-imx27.c
@@ -92,8 +92,23 @@
enum mx27_clks {
dummy, ckih, ckil, mpll, spll, mpll_main2, ahb, ipg, nfc_div, per1_div,
- per2_div, per3_div, per4_div, usb_div, cpu_sel, clko_sel, cpu_div, clko_div,
- clko_en, lcdc_per_gate, lcdc_ahb_gate, lcdc_ipg_gate, clk_max
+ per2_div, per3_div, per4_div, vpu_sel, vpu_div, usb_div, cpu_sel,
+ clko_sel, cpu_div, clko_div, ssi1_sel, ssi2_sel, ssi1_div, ssi2_div,
+ clko_en, ssi2_ipg_gate, ssi1_ipg_gate, slcdc_ipg_gate, sdhc3_ipg_gate,
+ sdhc2_ipg_gate, sdhc1_ipg_gate, scc_ipg_gate, sahara_ipg_gate,
+ rtc_ipg_gate, pwm_ipg_gate, owire_ipg_gate, lcdc_ipg_gate,
+ kpp_ipg_gate, iim_ipg_gate, i2c2_ipg_gate, i2c1_ipg_gate,
+ gpt6_ipg_gate, gpt5_ipg_gate, gpt4_ipg_gate, gpt3_ipg_gate,
+ gpt2_ipg_gate, gpt1_ipg_gate, gpio_ipg_gate, fec_ipg_gate,
+ emma_ipg_gate, dma_ipg_gate, cspi3_ipg_gate, cspi2_ipg_gate,
+ cspi1_ipg_gate, nfc_baud_gate, ssi2_baud_gate, ssi1_baud_gate,
+ vpu_baud_gate, per4_gate, per3_gate, per2_gate, per1_gate,
+ usb_ahb_gate, slcdc_ahb_gate, sahara_ahb_gate, lcdc_ahb_gate,
+ vpu_ahb_gate, fec_ahb_gate, emma_ahb_gate, emi_ahb_gate, dma_ahb_gate,
+ csi_ahb_gate, brom_ahb_gate, ata_ahb_gate, wdog_ipg_gate, usb_ipg_gate,
+ uart6_ipg_gate, uart5_ipg_gate, uart4_ipg_gate, uart3_ipg_gate,
+ uart2_ipg_gate, uart1_ipg_gate, ckih_div1p5, fpm, mpll_osc_sel,
+ mpll_sel, spll_gate, clk_max
};
static struct clk *clks[clk_max];
@@ -103,6 +118,16 @@ static const char *cpu_sel_clks[] = {
"mpll",
};
+static const char *mpll_sel_clks[] = {
+ "fpm",
+ "mpll_osc_sel",
+};
+
+static const char *mpll_osc_sel_clks[] = {
+ "ckih",
+ "ckih_div1p5",
+};
+
static const char *clko_sel_clks[] = {
"ckil",
NULL,
@@ -152,7 +177,16 @@ static int imx27_ccm_probe(struct device_d *dev)
clks[dummy] = clk_fixed("dummy", 0);
clks[ckih] = clk_fixed("ckih", 26000000);
clks[ckil] = clk_fixed("ckil", 32768);
- clks[mpll] = imx_clk_pllv1("mpll", "ckih", base + CCM_MPCTL0);
+ clks[fpm] = imx_clk_fixed_factor("fpm", "ckil", 1024, 1);
+ clks[ckih_div1p5] = imx_clk_fixed_factor("ckih_div1p5", "ckih", 2, 3);
+
+ clks[mpll_osc_sel] = imx_clk_mux("mpll_osc_sel", base + CCM_CSCR, 4, 1,
+ mpll_osc_sel_clks,
+ ARRAY_SIZE(mpll_osc_sel_clks));
+ clks[mpll_sel] = imx_clk_mux("mpll_sel", base + CCM_CSCR, 16, 1, mpll_sel_clks,
+ ARRAY_SIZE(mpll_sel_clks));
+
+ clks[mpll] = imx_clk_pllv1("mpll", "mpll_sel", base + CCM_MPCTL0);
clks[spll] = imx_clk_pllv1("spll", "ckih", base + CCM_SPCTL0);
clks[mpll_main2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
@@ -179,7 +213,7 @@ static int imx27_ccm_probe(struct device_d *dev)
else
clks[cpu_div] = imx_clk_divider("cpu_div", "cpu_sel", base + CCM_CSCR, 13, 3);
clks[clko_div] = imx_clk_divider("clko_div", "clko_sel", base + CCM_PCDR0, 22, 3);
- clks[lcdc_per_gate] = imx_clk_gate("lcdc_per_gate", "per3_div", base + CCM_PCCR1, 8);
+ clks[per3_gate] = imx_clk_gate("per3_gate", "per3_div", base + CCM_PCCR1, 8);
clks[lcdc_ahb_gate] = imx_clk_gate("lcdc_ahb_gate", "ahb", base + CCM_PCCR1, 15);
clks[lcdc_ipg_gate] = imx_clk_gate("lcdc_ipg_gate", "ipg", base + CCM_PCCR0, 14);
@@ -203,7 +237,7 @@ static int imx27_ccm_probe(struct device_d *dev)
clkdev_add_physbase(clks[per2_div], MX27_SDHC1_BASE_ADDR, NULL);
clkdev_add_physbase(clks[per2_div], MX27_SDHC2_BASE_ADDR, NULL);
clkdev_add_physbase(clks[per2_div], MX27_SDHC3_BASE_ADDR, NULL);
- clkdev_add_physbase(clks[lcdc_per_gate], MX27_LCDC_BASE_ADDR, NULL);
+ clkdev_add_physbase(clks[per3_gate], MX27_LCDC_BASE_ADDR, NULL);
clkdev_add_physbase(clks[lcdc_ahb_gate], MX27_LCDC_BASE_ADDR, "ahb");
clkdev_add_physbase(clks[lcdc_ipg_gate], MX27_LCDC_BASE_ADDR, "ipg");
clkdev_add_physbase(clks[ipg], MX27_FEC_BASE_ADDR, NULL);
diff --git a/arch/arm/mach-imx/clocksource.c b/arch/arm/mach-imx/clocksource.c
index dc29d200c0..9f5ca568fd 100644
--- a/arch/arm/mach-imx/clocksource.c
+++ b/arch/arm/mach-imx/clocksource.c
@@ -97,7 +97,7 @@ static int imx_gpt_probe(struct device_d *dev)
/* one timer is enough */
if (timer_base)
- return -EBUSY;
+ return 0;
ret = dev_get_drvdata(dev, (unsigned long *)&regs);
if (ret)
diff --git a/arch/arm/mach-imx/external-nand-boot.c b/arch/arm/mach-imx/external-nand-boot.c
index 1af46b78ea..fe933aa3a9 100644
--- a/arch/arm/mach-imx/external-nand-boot.c
+++ b/arch/arm/mach-imx/external-nand-boot.c
@@ -28,6 +28,10 @@
#include <mach/imx31-regs.h>
#include <mach/imx35-regs.h>
+#define BARE_INIT_FUNCTION(name) \
+ __section(.text_bare_init_##name) \
+ name
+
static void __bare_init noinline imx_nandboot_wait_op_done(void *regs)
{
u32 r;
@@ -91,12 +95,12 @@ static void __bare_init imx_nandboot_nfc_addr(void *regs, u32 offs, int pagesize
}
}
-static void __bare_init imx_nandboot_send_page(void *regs,
+static void __bare_init imx_nandboot_send_page(void *regs, int v1,
unsigned int ops, int pagesize_2k)
{
int bufs, i;
- if (nfc_is_v1() && pagesize_2k)
+ if (v1 && pagesize_2k)
bufs = 4;
else
bufs = 1;
@@ -122,15 +126,15 @@ static void __bare_init __memcpy32(void *trg, const void *src, int size)
*t++ = *s++;
}
-static noinline void __bare_init imx_nandboot_get_page(void *regs,
+static noinline void __bare_init imx_nandboot_get_page(void *regs, int v1,
u32 offs, int pagesize_2k)
{
imx_nandboot_send_cmd(regs, NAND_CMD_READ0);
imx_nandboot_nfc_addr(regs, offs, pagesize_2k);
- imx_nandboot_send_page(regs, NFC_OUTPUT, pagesize_2k);
+ imx_nandboot_send_page(regs, v1, NFC_OUTPUT, pagesize_2k);
}
-void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
+void __bare_init imx_nand_load_image(void *dest, int v1, int size, void __iomem *base,
int pagesize_2k)
{
u32 tmp, page, block, blocksize, pagesize, badblocks;
@@ -145,12 +149,12 @@ void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
blocksize = 16 * 1024;
}
- if (nfc_is_v21()) {
- regs = base + 0x1e00;
- spare0 = base + 0x1000;
- } else if (nfc_is_v1()) {
+ if (v1) {
regs = base + 0xe00;
spare0 = base + 0x800;
+ } else {
+ regs = base + 0x1e00;
+ spare0 = base + 0x1000;
}
imx_nandboot_send_cmd(regs, NAND_CMD_RESET);
@@ -164,13 +168,13 @@ void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
tmp = readw(regs + NFC_V1_V2_CONFIG1);
tmp |= NFC_V1_V2_CONFIG1_ECC_EN;
- if (nfc_is_v21())
+ if (!v1)
/* currently no support for 218 byte OOB with stronger ECC */
tmp |= NFC_V2_CONFIG1_ECC_MODE_4;
tmp &= ~(NFC_V1_V2_CONFIG1_SP_EN | NFC_V1_V2_CONFIG1_INT_MSK);
writew(tmp, regs + NFC_V1_V2_CONFIG1);
- if (nfc_is_v21()) {
+ if (!v1) {
if (pagesize_2k)
writew(NFC_V2_SPAS_SPARESIZE(64), regs + NFC_V2_SPAS);
else
@@ -192,7 +196,7 @@ void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
while (1) {
page = 0;
- imx_nandboot_get_page(regs, block * blocksize +
+ imx_nandboot_get_page(regs, v1, block * blocksize +
page * pagesize, pagesize_2k);
if (bbt) {
@@ -219,7 +223,7 @@ void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
block * blocksize +
page * pagesize);
if (page)
- imx_nandboot_get_page(regs, block * blocksize +
+ imx_nandboot_get_page(regs, v1, block * blocksize +
page * pagesize, pagesize_2k);
page++;
@@ -235,164 +239,152 @@ void __bare_init imx_nand_load_image(void *dest, int size, void __iomem *base,
}
}
-/*
- * This function assumes the currently running binary has been
- * copied from its current position to an offset. It returns
- * to the calling function - offset.
- * NOTE: The calling function may not return itself since it still
- * works on the old content of the lr register. Only call this
- * from a __noreturn function.
- */
-static __bare_init __naked void jump_sdram(unsigned long offset)
+void BARE_INIT_FUNCTION(imx21_nand_load_image)(void *dest, int size,
+ void __iomem *base, int pagesize_2k)
{
- flush_icache();
-
- __asm__ __volatile__ (
- "sub lr, lr, %0;"
- "mov pc, lr;" : : "r"(offset)
- );
+ imx_nand_load_image(dest, 1, size, base, pagesize_2k);
}
-/*
- * Load and start barebox from NAND. This function also checks if we are really
- * running inside the NFC address space. If not, barebox is started from the
- * currently running address without loading anything from NAND.
- */
-int __bare_init imx_barebox_boot_nand_external(unsigned long nfc_base)
+void BARE_INIT_FUNCTION(imx25_nand_load_image)(void *dest, int size,
+ void __iomem *base, int pagesize_2k)
{
- u32 r;
- u32 *src, *trg;
- int i;
-
- /* skip NAND boot if not running from NFC space */
- r = get_pc();
- if (r < nfc_base || r > nfc_base + 0x800)
- return 0;
-
- src = (unsigned int *)nfc_base;
- trg = (unsigned int *)ld_var(_text);
-
- /* Move ourselves out of NFC SRAM */
- for (i = 0; i < 0x800 / sizeof(int); i++)
- *trg++ = *src++;
-
- return 1;
+ imx_nand_load_image(dest, 0, size, base, pagesize_2k);
}
-#define BARE_INIT_FUNCTION(name) \
- void __noreturn __section(.text_bare_init_##name) \
- name
-
-/*
- * SoC specific entries for booting in external NAND mode. To be called from
- * the board specific entry code. This is safe to call even if not booting from
- * NAND. In this case the booting is continued without loading an image from
- * NAND. This function needs a stack to be set up.
- */
-#ifdef BROKEN
-BARE_INIT_FUNCTION(imx21_barebox_boot_nand_external)(void)
+void BARE_INIT_FUNCTION(imx27_nand_load_image)(void *dest, int size,
+ void __iomem *base, int pagesize_2k)
{
- unsigned long nfc_base = MX21_NFC_BASE_ADDR;
- int pagesize_2k;
-
- if (imx_barebox_boot_nand_external(nfc_base)) {
- jump_sdram(nfc_base - ld_var(_text));
-
- if (readl(MX21_SYSCTRL_BASE_ADDR + 0x14) & (1 << 5))
- pagesize_2k = 1;
- else
- pagesize_2k = 0;
-
- imx_nand_load_image((void *)ld_var(_text),
- ld_var(barebox_image_size),
- (void *)nfc_base, pagesize_2k);
- }
-
- /* This function doesn't exist yet */
- imx21_barebox_entry(0);
+ imx_nand_load_image(dest, 1, size, base, pagesize_2k);
}
-#endif
-BARE_INIT_FUNCTION(imx25_barebox_boot_nand_external)(void)
+void BARE_INIT_FUNCTION(imx31_nand_load_image)(void *dest, int size,
+ void __iomem *base, int pagesize_2k)
{
- unsigned long nfc_base = MX25_NFC_BASE_ADDR;
- int pagesize_2k;
-
- if (imx_barebox_boot_nand_external(nfc_base)) {
- jump_sdram(nfc_base - ld_var(_text));
-
- if (readl(MX25_CCM_BASE_ADDR + MX25_CCM_RCSR) & (1 << 8))
- pagesize_2k = 1;
- else
- pagesize_2k = 0;
-
- imx_nand_load_image((void *)ld_var(_text),
- ld_var(_barebox_image_size),
- (void *)nfc_base, pagesize_2k);
- }
-
- imx25_barebox_entry(0);
+ imx_nand_load_image(dest, 1, size, base, pagesize_2k);
}
-BARE_INIT_FUNCTION(imx27_barebox_boot_nand_external)(void)
+void BARE_INIT_FUNCTION(imx35_nand_load_image)(void *dest, int size,
+ void __iomem *base, int pagesize_2k)
{
- unsigned long nfc_base = MX27_NFC_BASE_ADDR;
- int pagesize_2k;
-
- if (imx_barebox_boot_nand_external(nfc_base)) {
- jump_sdram(nfc_base - ld_var(_text));
-
- if (readl(MX27_SYSCTRL_BASE_ADDR + 0x14) & (1 << 5))
- pagesize_2k = 1;
- else
- pagesize_2k = 0;
-
- imx_nand_load_image((void *)ld_var(_text),
- ld_var(_barebox_image_size),
- (void *)nfc_base, pagesize_2k);
- }
-
- imx27_barebox_entry(0);
+ imx_nand_load_image(dest, 0, size, base, pagesize_2k);
}
-BARE_INIT_FUNCTION(imx31_barebox_boot_nand_external)(void)
+static inline int imx21_pagesize_2k(void)
{
- unsigned long nfc_base = MX31_NFC_BASE_ADDR;
- int pagesize_2k;
-
- if (imx_barebox_boot_nand_external(nfc_base)) {
- jump_sdram(nfc_base - ld_var(_text));
-
- if (readl(MX31_CCM_BASE_ADDR + MX31_CCM_RCSR) & MX31_RCSR_NFMS)
- pagesize_2k = 1;
- else
- pagesize_2k = 0;
-
- imx_nand_load_image((void *)ld_var(_text),
- ld_var(_barebox_image_size),
- (void *)nfc_base, pagesize_2k);
- }
+ if (readl(MX21_SYSCTRL_BASE_ADDR + 0x14) & (1 << 5))
+ return 1;
+ else
+ return 0;
+}
- imx31_barebox_entry(0);
+static inline int imx25_pagesize_2k(void)
+{
+ if (readl(MX25_CCM_BASE_ADDR + MX25_CCM_RCSR) & (1 << 8))
+ return 1;
+ else
+ return 0;
}
-BARE_INIT_FUNCTION(imx35_barebox_boot_nand_external)(void)
+static inline int imx27_pagesize_2k(void)
{
- unsigned long nfc_base = MX35_NFC_BASE_ADDR;
- int pagesize_2k;
+ if (readl(MX27_SYSCTRL_BASE_ADDR + 0x14) & (1 << 5))
+ return 1;
+ else
+ return 0;
+}
- if (imx_barebox_boot_nand_external(nfc_base)) {
- jump_sdram(nfc_base - ld_var(_text));
+static inline int imx31_pagesize_2k(void)
+{
+ if (readl(MX31_CCM_BASE_ADDR + MX31_CCM_RCSR) & MX31_RCSR_NFMS)
+ return 1;
+ else
+ return 0;
+}
- if (readl(MX35_CCM_BASE_ADDR + MX35_CCM_RCSR) & (1 << 8))
- pagesize_2k = 1;
- else
- pagesize_2k = 0;
+static inline int imx35_pagesize_2k(void)
+{
+ if (readl(MX35_CCM_BASE_ADDR + MX35_CCM_RCSR) & (1 << 8))
+ return 1;
+ else
+ return 0;
+}
- imx_nand_load_image((void *)ld_var(_text),
- ld_var(_barebox_image_size),
- (void *)nfc_base, pagesize_2k);
- }
+/*
+ * SoC specific entries for booting in external NAND mode. To be called from
+ * the board specific entry code. This is safe to call even if not booting from
+ * NAND. In this case the booting is continued without loading an image from
+ * NAND. This function needs a stack to be set up.
+ */
- imx35_barebox_entry(0);
+#define DEFINE_EXTERNAL_NAND_ENTRY(soc) \
+ \
+void __noreturn BARE_INIT_FUNCTION(imx##soc##_boot_nand_external_cont) \
+ (uint32_t boarddata) \
+{ \
+ unsigned long nfc_base = MX##soc##_NFC_BASE_ADDR; \
+ void *sdram = (void *)MX##soc##_CSD0_BASE_ADDR; \
+ uint32_t image_size; \
+ \
+ image_size = *(uint32_t *)(sdram + 0x2c); \
+ \
+ imx##soc##_nand_load_image(sdram, \
+ image_size, \
+ (void *)nfc_base, \
+ imx##soc##_pagesize_2k()); \
+ \
+ imx##soc##_barebox_entry(boarddata); \
+} \
+ \
+void __noreturn BARE_INIT_FUNCTION(imx##soc##_barebox_boot_nand_external) \
+ (uint32_t boarddata) \
+{ \
+ unsigned long nfc_base = MX##soc##_NFC_BASE_ADDR; \
+ unsigned long sdram = MX##soc##_CSD0_BASE_ADDR; \
+ unsigned long __fn; \
+ u32 r; \
+ u32 *src, *trg; \
+ int i; \
+ void __noreturn (*fn)(uint32_t); \
+ \
+ /* skip NAND boot if not running from NFC space */ \
+ r = get_pc(); \
+ if (r < nfc_base || r > nfc_base + 0x800) \
+ imx##soc##_barebox_entry(boarddata); \
+ \
+ src = (unsigned int *)nfc_base; \
+ trg = (unsigned int *)sdram; \
+ \
+ /* \
+ * Copy initial binary portion from NFC SRAM to beginning of \
+ * SDRAM \
+ */ \
+ for (i = 0; i < 0x800 / sizeof(int); i++) \
+ *trg++ = *src++; \
+ \
+ /* The next function we jump to */ \
+ __fn = (unsigned long)imx##soc##_boot_nand_external_cont; \
+ /* mask out TEXT_BASE */ \
+ __fn &= 0x7ff; \
+ /* \
+ * and add sdram base instead where we copied the initial \
+ * binary above \
+ */ \
+ __fn += sdram; \
+ \
+ fn = (void *)__fn; \
+ \
+ if (boarddata > nfc_base && boarddata < nfc_base + SZ_512K) { \
+ boarddata &= SZ_512K - 1; \
+ boarddata += sdram; \
+ } \
+ \
+ fn(boarddata); \
}
+
+#ifdef BROKEN
+DEFINE_EXTERNAL_NAND_ENTRY(21)
+#endif
+DEFINE_EXTERNAL_NAND_ENTRY(25)
+DEFINE_EXTERNAL_NAND_ENTRY(27)
+DEFINE_EXTERNAL_NAND_ENTRY(31)
+DEFINE_EXTERNAL_NAND_ENTRY(35)
diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index ed1edd7adc..304b1c0f2e 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -18,6 +18,7 @@
#include <mach/imx6.h>
#include <mach/generic.h>
#include <mach/revision.h>
+#include <mach/imx6-anadig.h>
#include <mach/imx6-regs.h>
#include <mach/generic.h>
@@ -27,6 +28,7 @@ void imx6_init_lowlevel(void)
{
void __iomem *aips1 = (void *)MX6_AIPS1_ON_BASE_ADDR;
void __iomem *aips2 = (void *)MX6_AIPS2_ON_BASE_ADDR;
+ int is_imx6q = __imx6_cpu_type() == IMX6_CPUTYPE_IMX6Q;
/*
* Set all MPROTx to be non-bufferable, trusted for R/W,
@@ -56,6 +58,35 @@ void imx6_init_lowlevel(void)
writel(0xffffffff, 0x020c4078);
writel(0xffffffff, 0x020c407c);
writel(0xffffffff, 0x020c4080);
+
+ /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
+ * to make sure PFD is working right, otherwise, PFDs may
+ * not output clock after reset, MX6DL and MX6SL have added 396M pfd
+ * workaround in ROM code, as bus clock need it
+ */
+ writel(BM_ANADIG_PFD_480_PFD3_CLKGATE |
+ BM_ANADIG_PFD_480_PFD2_CLKGATE |
+ BM_ANADIG_PFD_480_PFD1_CLKGATE |
+ BM_ANADIG_PFD_480_PFD0_CLKGATE,
+ MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_SET);
+ writel(BM_ANADIG_PFD_528_PFD3_CLKGATE |
+ (is_imx6q ? BM_ANADIG_PFD_528_PFD2_CLKGATE : 0) |
+ BM_ANADIG_PFD_528_PFD1_CLKGATE |
+ BM_ANADIG_PFD_528_PFD0_CLKGATE,
+ MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_SET);
+
+ writel(BM_ANADIG_PFD_480_PFD3_CLKGATE |
+ BM_ANADIG_PFD_480_PFD2_CLKGATE |
+ BM_ANADIG_PFD_480_PFD1_CLKGATE |
+ BM_ANADIG_PFD_480_PFD0_CLKGATE,
+ MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_CLR);
+ writel(BM_ANADIG_PFD_528_PFD3_CLKGATE |
+ (is_imx6q ? BM_ANADIG_PFD_528_PFD2_CLKGATE : 0) |
+ BM_ANADIG_PFD_528_PFD2_CLKGATE |
+ BM_ANADIG_PFD_528_PFD1_CLKGATE |
+ BM_ANADIG_PFD_528_PFD0_CLKGATE,
+ MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_CLR);
+
}
int imx6_init(void)
@@ -86,10 +117,16 @@ int imx6_init(void)
switch (imx6_cpu_type()) {
case IMX6_CPUTYPE_IMX6Q:
- cputypestr = "i.MX6 Dual/Quad";
+ cputypestr = "i.MX6 Quad";
+ break;
+ case IMX6_CPUTYPE_IMX6D:
+ cputypestr = "i.MX6 Dual";
break;
case IMX6_CPUTYPE_IMX6DL:
- cputypestr = "i.MX6 Solo/DualLite";
+ cputypestr = "i.MX6 DualLite";
+ break;
+ case IMX6_CPUTYPE_IMX6S:
+ cputypestr = "i.MX6 Solo";
break;
default:
cputypestr = "unknown i.MX6";
diff --git a/arch/arm/mach-imx/include/mach/imx-gpio.h b/arch/arm/mach-imx/include/mach/imx-gpio.h
new file mode 100644
index 0000000000..5e673beef9
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/imx-gpio.h
@@ -0,0 +1,48 @@
+#ifndef __MACH_IMX_GPIO_H
+#define __MACH_IMX_GPIO_H
+
+#include <io.h>
+
+/*
+ * i.MX lowlevel gpio functions. Only for use with lowlevel code. Use
+ * regular gpio functions outside of lowlevel code!
+ */
+
+static inline void imx_gpio_direction_output(void __iomem *gdir, void __iomem *dr,
+ int gpio, int value)
+{
+ uint32_t val;
+
+ val = readl(gdir);
+ val |= 1 << gpio;
+ writel(val, gdir);
+
+ val = readl(dr);
+ if (value)
+ val |= 1 << gpio;
+ else
+ val &= ~(1 << gpio);
+
+ writel(val, dr);
+}
+
+static inline void imx1_gpio_direction_output(void *base, int gpio, int value)
+{
+ imx_gpio_direction_output(base + 0x0, base + 0x1c, gpio, value);
+}
+
+#define imx21_gpio_direction_output(base, gpio, value) imx1_gpio_direction_output(base, gpio,value)
+#define imx27_gpio_direction_output(base, gpio, value) imx1_gpio_direction_output(base, gpio,value)
+
+static inline void imx31_gpio_direction_output(void *base, int gpio, int value)
+{
+ imx_gpio_direction_output(base + 0x4, base + 0x0, gpio, value);
+}
+
+#define imx25_gpio_direction_output(base, gpio, value) imx31_gpio_direction_output(base, gpio,value)
+#define imx35_gpio_direction_output(base, gpio, value) imx31_gpio_direction_output(base, gpio,value)
+#define imx51_gpio_direction_output(base, gpio, value) imx31_gpio_direction_output(base, gpio,value)
+#define imx53_gpio_direction_output(base, gpio, value) imx31_gpio_direction_output(base, gpio,value)
+#define imx6_gpio_direction_output(base, gpio, value) imx31_gpio_direction_output(base, gpio,value)
+
+#endif /* __MACH_IMX_GPIO_H */
diff --git a/arch/arm/mach-imx/include/mach/imx-nand.h b/arch/arm/mach-imx/include/mach/imx-nand.h
index 9e6416e4d4..972a0da5d7 100644
--- a/arch/arm/mach-imx/include/mach/imx-nand.h
+++ b/arch/arm/mach-imx/include/mach/imx-nand.h
@@ -3,11 +3,11 @@
#include <linux/mtd/mtd.h>
-void imx21_barebox_boot_nand_external(void);
-void imx25_barebox_boot_nand_external(void);
-void imx27_barebox_boot_nand_external(void);
-void imx31_barebox_boot_nand_external(void);
-void imx35_barebox_boot_nand_external(void);
+void imx21_barebox_boot_nand_external(uint32_t boarddata);
+void imx25_barebox_boot_nand_external(uint32_t boarddata);
+void imx27_barebox_boot_nand_external(uint32_t boarddata);
+void imx31_barebox_boot_nand_external(uint32_t boarddata);
+void imx35_barebox_boot_nand_external(uint32_t boarddata);
void imx_nand_set_layout(int writesize, int datawidth);
struct imx_nand_platform_data {
diff --git a/arch/arm/mach-imx/include/mach/imx25-regs.h b/arch/arm/mach-imx/include/mach/imx25-regs.h
index 9ab0fb3eee..71812764c9 100644
--- a/arch/arm/mach-imx/include/mach/imx25-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx25-regs.h
@@ -35,6 +35,9 @@
#define MX25_IOMUXC_BASE_ADDR (MX25_AIPS1_BASE_ADDR + 0xac000)
#define MX25_CCM_BASE_ADDR (MX25_AIPS2_BASE_ADDR + 0x80000)
+#define MX25_GPT4_BASE_ADDR (MX25_AIPS2_BASE_ADDR + 0x84000)
+#define MX25_GPT3_BASE_ADDR (MX25_AIPS2_BASE_ADDR + 0x88000)
+#define MX25_GPT2_BASE_ADDR (MX25_AIPS2_BASE_ADDR + 0x8c000)
#define MX25_GPT1_BASE_ADDR (MX25_AIPS2_BASE_ADDR + 0x90000)
#define MX25_GPIO4_BASE_ADDR (MX25_AIPS2_BASE_ADDR + 0x9c000)
#define MX25_PWM2_BASE_ADDR (MX25_AIPS2_BASE_ADDR + 0xa0000)
diff --git a/arch/arm/mach-imx/include/mach/imx6.h b/arch/arm/mach-imx/include/mach/imx6.h
index 4b2b1c7a69..1898d8150b 100644
--- a/arch/arm/mach-imx/include/mach/imx6.h
+++ b/arch/arm/mach-imx/include/mach/imx6.h
@@ -9,24 +9,47 @@ void imx6_init_lowlevel(void);
#define IMX6_ANATOP_SI_REV 0x260
-#define IMX6_CPUTYPE_IMX6Q 0x63
-#define IMX6_CPUTYPE_IMX6DL 0x61
+#define IMX6_CPUTYPE_IMX6S 0x161
+#define IMX6_CPUTYPE_IMX6DL 0x261
+#define IMX6_CPUTYPE_IMX6D 0x263
+#define IMX6_CPUTYPE_IMX6Q 0x463
-static inline int imx6_cpu_type(void)
+#define SCU_CONFIG 0x04
+
+static inline int scu_get_core_count(void)
+{
+ unsigned long base;
+ unsigned int ncores;
+
+ asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+ ncores = readl(base + SCU_CONFIG);
+ return (ncores & 0x03) + 1;
+}
+
+static inline int __imx6_cpu_type(void)
{
uint32_t val;
+ val = readl(MX6_ANATOP_BASE_ADDR + IMX6_ANATOP_SI_REV);
+ val = (val >> 16) & 0xff;
+
+ val |= scu_get_core_count() << 8;
+
+ return val;
+}
+
+static inline int imx6_cpu_type(void)
+{
if (!cpu_is_mx6())
return 0;
- val = readl(MX6_ANATOP_BASE_ADDR + IMX6_ANATOP_SI_REV);
-
- return (val >> 16) & 0xff;
+ return __imx6_cpu_type();
}
-static inline int cpu_is_mx6q(void)
+static inline int cpu_is_mx6s(void)
{
- return imx6_cpu_type() == IMX6_CPUTYPE_IMX6Q;
+ return imx6_cpu_type() == IMX6_CPUTYPE_IMX6S;
}
static inline int cpu_is_mx6dl(void)
@@ -34,4 +57,14 @@ static inline int cpu_is_mx6dl(void)
return imx6_cpu_type() == IMX6_CPUTYPE_IMX6DL;
}
+static inline int cpu_is_mx6d(void)
+{
+ return imx6_cpu_type() == IMX6_CPUTYPE_IMX6D;
+}
+
+static inline int cpu_is_mx6q(void)
+{
+ return imx6_cpu_type() == IMX6_CPUTYPE_IMX6Q;
+}
+
#endif /* __MACH_IMX6_H */