diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2014-02-03 09:55:13 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2014-02-03 09:55:13 +0100 |
commit | c224cd316197132321869d859048f89da49c0162 (patch) | |
tree | 275649e84cb143b3a389bf05c8416904b9da0dba /arch/arm/mach-imx | |
parent | 3cbd92bf6e96d4274e3a4f6aeceaf51d5406a0a6 (diff) | |
parent | cc66cf109b1d2ca40c180a87fd76c2099dff2d92 (diff) | |
download | barebox-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/Kconfig | 68 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-imx25.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-imx27.c | 44 | ||||
-rw-r--r-- | arch/arm/mach-imx/clocksource.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/external-nand-boot.c | 290 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx6.c | 41 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/imx-gpio.h | 48 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/imx-nand.h | 10 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/imx25-regs.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/imx6.h | 49 |
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 *)®s); 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 */ |