[U-Boot] [PATCH-V3 0/8] Add support for i.MX25 SOC and KARO TX25 board

This series has been updated to merge cleanly on top of Scotts nand tree which had earlier mxc nand conflicts
The whole series is included for completeness even though most patches have not changed.
Changes since v2:
0001-mxc_serial-replace-platform-specific-clock.patch unchanged 0002-arm926ejs-add-nand_spl-boot-support.patch unchanged 0003-Add-MX25-support-to-nand_spl-fsl-nfc-driver.patch unchanged 0004-Nand-mxc_nand-add-v1.1-controller-support.patch updated to apply cleanly to current nand tree 0005-fec_mxc-cleanup-and-factor-out-imx27-dependencies.patch unchanged 0006-Add-support-for-Freescale-MX25-SOC.patch unchanged 0007-fec_mxc-add-imx25-support.patch small changes associated with the nand changes 0008-Add-support-for-KARO-TX25-board.patch small changes associated with the nand changes (this was 0009 in previous series, the previous 0008 has already been merged)
John Rigby (8): mxc_serial replace platform specific clock arm926ejs: add nand_spl boot support Add MX25 support to nand_spl fsl nfc driver Nand mxc_nand add v1.1 controller support fec_mxc: cleanup and factor out MX27 dependencies Add support for Freescale MX25 SOC fec_mxc: add MX25 support Add support for KARO TX25 board
MAINTAINERS | 4 + Makefile | 4 + board/karo/tx25/Makefile | 51 +++ board/karo/tx25/config.mk | 5 + board/karo/tx25/lowlevel_init.S | 131 +++++++ board/karo/tx25/tx25.c | 176 +++++++++ cpu/arm926ejs/mx25/Makefile | 46 +++ cpu/arm926ejs/mx25/generic.c | 263 +++++++++++++ cpu/arm926ejs/mx25/reset.c | 56 +++ cpu/arm926ejs/mx25/timer.c | 187 +++++++++ cpu/arm926ejs/mx27/generic.c | 5 + cpu/arm926ejs/start.S | 42 ++- drivers/mtd/nand/mxc_nand.c | 617 ++++++++++++++++++++++++++---- drivers/net/fec_mxc.c | 57 ++- drivers/net/fec_mxc.h | 32 ++- drivers/serial/serial_mxc.c | 16 +- include/asm-arm/arch-mx25/clock.h | 36 ++ include/asm-arm/arch-mx25/imx-regs.h | 316 +++++++++++++++ include/asm-arm/arch-mx25/imx25-pinmux.h | 421 ++++++++++++++++++++ include/asm-arm/arch-mx27/clock.h | 3 + include/asm-arm/arch-mx31/mx31.h | 1 + include/configs/mx31pdk.h | 4 + include/configs/tx25.h | 179 +++++++++ include/fsl_nfc.h | 78 ++++- nand_spl/board/karo/tx25/Makefile | 78 ++++ nand_spl/board/karo/tx25/config.mk | 1 + nand_spl/board/karo/tx25/u-boot.lds | 58 +++ nand_spl/nand_boot_fsl_nfc.c | 72 +++- 28 files changed, 2812 insertions(+), 127 deletions(-) create mode 100644 board/karo/tx25/Makefile create mode 100644 board/karo/tx25/config.mk create mode 100644 board/karo/tx25/lowlevel_init.S create mode 100644 board/karo/tx25/tx25.c create mode 100644 cpu/arm926ejs/mx25/Makefile create mode 100644 cpu/arm926ejs/mx25/generic.c create mode 100644 cpu/arm926ejs/mx25/reset.c create mode 100644 cpu/arm926ejs/mx25/timer.c create mode 100644 include/asm-arm/arch-mx25/clock.h create mode 100644 include/asm-arm/arch-mx25/imx-regs.h create mode 100644 include/asm-arm/arch-mx25/imx25-pinmux.h create mode 100644 include/configs/tx25.h create mode 100644 nand_spl/board/karo/tx25/Makefile create mode 100644 nand_spl/board/karo/tx25/config.mk create mode 100644 nand_spl/board/karo/tx25/u-boot.lds

remove ifdef'd clock selection code from serial_mxc.c and replace with call to imx_get_uartclk
Add definitions for imx_get_uartclk to imx31 and imx27 include files.
This makes it easier to add new imx platforms.
Signed-off-by: John Rigby jcrigby@gmail.com --- drivers/serial/serial_mxc.c | 6 +----- include/asm-arm/arch-mx27/clock.h | 2 ++ include/asm-arm/arch-mx31/mx31.h | 1 + 3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c index acc5b7d..7dcedf6 100644 --- a/drivers/serial/serial_mxc.c +++ b/drivers/serial/serial_mxc.c @@ -166,11 +166,7 @@ DECLARE_GLOBAL_DATA_PTR;
void serial_setbrg (void) { -#ifdef CONFIG_MX31 - u32 clk = mx31_get_ipg_clk(); -#else - u32 clk = imx_get_perclk1(); -#endif + u32 clk = imx_get_uartclk();
if (!gd->baudrate) gd->baudrate = CONFIG_BAUDRATE; diff --git a/include/asm-arm/arch-mx27/clock.h b/include/asm-arm/arch-mx27/clock.h index 5fc75c5..472e8f2 100644 --- a/include/asm-arm/arch-mx27/clock.h +++ b/include/asm-arm/arch-mx27/clock.h @@ -36,4 +36,6 @@ ulong imx_get_perclk2(void); ulong imx_get_perclk3(void); ulong imx_get_ahbclk(void);
+#define imx_get_uartclk imx_get_perclk1 + #endif /* __ASM_ARCH_CLOCK_H */ diff --git a/include/asm-arm/arch-mx31/mx31.h b/include/asm-arm/arch-mx31/mx31.h index 53b9f27..3cc4b35 100644 --- a/include/asm-arm/arch-mx31/mx31.h +++ b/include/asm-arm/arch-mx31/mx31.h @@ -25,6 +25,7 @@ #define __ASM_ARCH_MX31_H
extern u32 mx31_get_ipg_clk(void); +#define imx_get_uartclk mx31_get_ipg_clk extern void mx31_gpio_mux(unsigned long mode);
enum mx31_gpio_direction {

Add CONFIG_PRELOADER/CONFIG_NAND_SPL support for nand booting to arm926ejs/start.S
This is derived from CONFIG_PRELOADER support in arm1136/start.S
Signed-off-by: John Rigby jcrigby@gmail.com CC: Scott Wood scottwood@freescale.com --- cpu/arm926ejs/start.S | 42 +++++++++++++++++++++++++++++++++++++++++- 1 files changed, 41 insertions(+), 1 deletions(-)
diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S index 4421b6a..3b81151 100644 --- a/cpu/arm926ejs/start.S +++ b/cpu/arm926ejs/start.S @@ -53,6 +53,27 @@ .globl _start _start: b reset +#ifdef CONFIG_PRELOADER +/* No exception handlers in preloader */ + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + +_hang: + .word do_hang +/* pad to 64 byte boundary */ + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 +#else ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort @@ -76,6 +97,7 @@ _irq: _fiq: .word fiq
+#endif /* CONFIG_PRELOADER */ .balignl 16,0xdeadbeef
@@ -150,7 +172,6 @@ relocate: /* relocate U-Boot to RAM */ ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ cmp r0, r1 /* don't reloc during debug */ beq stack_setup - ldr r2, _armboot_start ldr r3, _bss_start sub r2, r3, r2 /* r2 <- size of armboot */ @@ -166,11 +187,14 @@ copy_loop: /* Set up the stack */ stack_setup: ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ + sub sp, r0, #128 /* leave 32 words for abort-stack */ +#ifndef CONFIG_PRELOADER sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ #ifdef CONFIG_USE_IRQ sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif +#endif /* CONFIG_PRELOADER */ sub sp, r0, #12 /* leave 3 words for abort-stack */ bic sp, r0, #7 /* 8-byte align stack for ABI compliance */
@@ -179,6 +203,7 @@ clear_bss: ldr r1, _bss_end /* stop here */ mov r2, #0x00000000 /* clear */
+#ifndef CONFIG_PRELOADER clbss_l:str r2, [r0] /* clear loop... */ add r0, r0, #4 cmp r0, r1 @@ -186,11 +211,16 @@ clbss_l:str r2, [r0] /* clear loop... */
bl coloured_LED_init bl red_LED_on +#endif /* CONFIG_PRELOADER */
ldr pc, _start_armboot
_start_armboot: +#ifdef CONFIG_NAND_SPL + .word nand_boot +#else .word start_armboot +#endif /* CONFIG_NAND_SPL */
/* @@ -231,6 +261,7 @@ cpu_init_crit: mov pc, lr /* back to my caller */ #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
+#ifndef CONFIG_PRELOADER /* ************************************************************************* * @@ -332,10 +363,18 @@ cpu_init_crit: .macro get_fiq_stack @ setup FIQ stack ldr sp, FIQ_STACK_START .endm +#endif /* CONFIG_PRELOADER */
/* * exception handlers */ +#ifdef CONFIG_PRELOADER + .align 5 +do_hang: + ldr sp, _TEXT_BASE /* switch to abort stack */ +1: + bl 1b /* hang and never return */ +#else /* !CONFIG_PRELOADER */ .align 5 undefined_instruction: get_bad_stack @@ -398,3 +437,4 @@ fiq: bl do_fiq
#endif +#endif /* CONFIG_PRELOADER */

MX25 has a different version of the fsl_nfc flash controller known as version 1.1.
Add support to the nand_spl fsl_nfc driver keyed off CONFIG_NAND_NFC_V1_1.
Also add a define CONFIG_NAND_NFC_V1 to the only existing user configs/mx31pdk.h.
Versioning differs from mainline mxc kernel driver no consensus yet on if the naming here and in Redboot or the kernel is "correct".
Signed-off-by: John Rigby jcrigby@gmail.com Signed-off-by: Wolfgang Denk wd@denx.de CC: Scott Wood scottwood@freescale.com --- include/configs/mx31pdk.h | 4 ++ include/fsl_nfc.h | 78 +++++++++++++++++++++++++++++++++++------ nand_spl/nand_boot_fsl_nfc.c | 72 ++++++++++++++++++++++++++++++-------- 3 files changed, 127 insertions(+), 27 deletions(-)
diff --git a/include/configs/mx31pdk.h b/include/configs/mx31pdk.h index bee2f45..53e7503 100644 --- a/include/configs/mx31pdk.h +++ b/include/configs/mx31pdk.h @@ -50,6 +50,10 @@ #define CONFIG_SKIP_RELOCATE_UBOOT #endif
+#ifdef CONFIG_NAND_SPL +#define CONFIG_NAND_MXC_V1 +#endif + /* * Size of malloc() pool */ diff --git a/include/fsl_nfc.h b/include/fsl_nfc.h index da5be37..6af158f 100644 --- a/include/fsl_nfc.h +++ b/include/fsl_nfc.h @@ -1,5 +1,4 @@ /* - * * (c) 2009 Magnus Lilja lilja.magnus@gmail.com * * See file CREDITS for list of people who contributed to this @@ -25,21 +24,49 @@ #define __FSL_NFC_H
/* + * TODO: Use same register defs for nand_spl mxc nand driver + * and mtd mxc nand driver. + * * Register map and bit definitions for the Freescale NAND Flash - * Controller present in i.MX31 and other devices. + * Controller present in various i.MX devices. + * + * MX31 and MX27 have version 1 which has + * 4 512 byte main buffers and + * 4 16 byte spare buffers + * to support up to 2K byte pagesize nand. + * Reading or writing a 2K page requires 4 FDI/FDO cycles. + * + * MX25 has version 1.1 which has + * 8 512 byte main buffers and + * 8 64 byte spare buffers + * to support up to 4K byte pagesize nand. + * Reading or writing a 2K or 4K page requires only 1 FDI/FDO cycle. + * Also some of registers are moved and/or changed meaning as seen below. */ +#if defined(CONFIG_NAND_MXC_V1) +#define NAND_MXC_NR_BUFS 4 +#define NAND_MXC_SPARE_BUF_SIZE 16 +#define NAND_MXC_REG_OFFSET 0xe00 +#define NAND_MXC_2K_MULTI_CYCLE 1 +#elif defined(CONFIG_NAND_MXC_V1_1) +#define NAND_MXC_NR_BUFS 8 +#define NAND_MXC_SPARE_BUF_SIZE 64 +#define NAND_MXC_REG_OFFSET 0x1e00 +#else +#error "define CONFIG_NAND_MXC_VXXX to use the mxc spl_nand driver" +#endif
struct fsl_nfc_regs { - u32 main_area0[128]; /* @0x000 */ - u32 main_area1[128]; - u32 main_area2[128]; - u32 main_area3[128]; - u32 spare_area0[4]; - u32 spare_area1[4]; - u32 spare_area2[4]; - u32 spare_area3[4]; - u32 reserved1[64 - 16 + 64 * 5]; - u16 bufsiz; /* @ 0xe00 */ + u32 main_area[NAND_MXC_NR_BUFS][512/4]; + u32 spare_area[NAND_MXC_NR_BUFS][NAND_MXC_SPARE_BUF_SIZE/4]; + /* + * reserved size is offset of nfc registers + * minus total main and spare sizes + */ + u8 reserved1[NAND_MXC_REG_OFFSET + - NAND_MXC_NR_BUFS * (512 + NAND_MXC_SPARE_BUF_SIZE)]; +#if defined(CONFIG_NAND_MXC_V1) + u16 bufsiz; u16 reserved2; u16 buffer_address; u16 flash_add; @@ -54,6 +81,30 @@ struct fsl_nfc_regs { u16 nand_flash_wr_pr_st; u16 nand_flash_config1; u16 nand_flash_config2; +#elif defined(CONFIG_NAND_MXC_V1_1) + u16 reserved2[2]; + u16 buffer_address; + u16 flash_add; + u16 flash_cmd; + u16 configuration; + u16 ecc_status_result; + u16 ecc_status_result2; + u16 spare_area_size; + u16 nf_wr_prot; + u16 reserved3[2]; + u16 nand_flash_wr_pr_st; + u16 nand_flash_config1; + u16 nand_flash_config2; + u16 reserved4; + u16 unlock_start_blk_add0; + u16 unlock_end_blk_add0; + u16 unlock_start_blk_add1; + u16 unlock_end_blk_add1; + u16 unlock_start_blk_add2; + u16 unlock_end_blk_add2; + u16 unlock_start_blk_add3; + u16 unlock_end_blk_add3; +#endif };
/* @@ -98,6 +149,9 @@ struct fsl_nfc_regs { */ #define NFC_INT 0x8000
+#ifdef CONFIG_NAND_MXC_V1_1 +#define NFC_4_8N_ECC (1 << 0) +#endif #define NFC_SP_EN (1 << 2) #define NFC_ECC_EN (1 << 3) #define NFC_INT_MSK (1 << 4) diff --git a/nand_spl/nand_boot_fsl_nfc.c b/nand_spl/nand_boot_fsl_nfc.c index a9df2a8..ea4e59b 100644 --- a/nand_spl/nand_boot_fsl_nfc.c +++ b/nand_spl/nand_boot_fsl_nfc.c @@ -26,11 +26,15 @@
#include <common.h> #include <nand.h> +#ifdef CONFIG_MX31 #include <asm-arm/arch/mx31-regs.h> +#else +#include <asm-arm/arch/imx-regs.h> +#endif #include <asm/io.h> #include <fsl_nfc.h>
-static struct fsl_nfc_regs *nfc; +struct fsl_nfc_regs *nfc;
static void nfc_wait_ready(void) { @@ -45,13 +49,35 @@ static void nfc_wait_ready(void) writew(tmp, &nfc->nand_flash_config2); }
-static void nfc_nand_init(void) +void nfc_nand_init(void) { +#if defined(CONFIG_NAND_MXC_V1_1) + int ecc_per_page = CONFIG_SYS_NAND_PAGE_SIZE / 512; + int config1; + + writew(CONFIG_SYS_NAND_SPARE_SIZE / 2, &nfc->spare_area_size); + + /* unlocking RAM Buff */ + writew(0x2, &nfc->configuration); + + /* hardware ECC checking and correct */ + config1 = readw(&nfc->nand_flash_config1) | NFC_ECC_EN | 0x800; + /* + * if spare size is larger that 16 bytes per 512 byte hunk + * then use 8 symbol correction instead of 4 + */ + if ((CONFIG_SYS_NAND_SPARE_SIZE / ecc_per_page) > 16) + config1 &= ~NFC_4_8N_ECC; + else + config1 |= NFC_4_8N_ECC; + writew(config1, &nfc->nand_flash_config1); +#elif defined(CONFIG_NAND_MXC_V1) /* unlocking RAM Buff */ writew(0x2, &nfc->configuration);
/* hardware ECC checking and correct */ writew(NFC_ECC_EN, &nfc->nand_flash_config1); +#endif }
static void nfc_nand_command(unsigned short command) @@ -65,12 +91,12 @@ static void nfc_nand_page_address(unsigned int page_address) { unsigned int page_count;
- writew(0x00, &nfc->flash_cmd); + writew(0x00, &nfc->flash_add); writew(NFC_ADDR, &nfc->nand_flash_config2); nfc_wait_ready();
- /* code only for 2kb flash */ - if (CONFIG_SYS_NAND_PAGE_SIZE == 0x800) { + /* code only for large page flash */ + if (CONFIG_SYS_NAND_PAGE_SIZE > 512) { writew(0x00, &nfc->flash_add); writew(NFC_ADDR, &nfc->nand_flash_config2); nfc_wait_ready(); @@ -88,22 +114,38 @@ static void nfc_nand_page_address(unsigned int page_address) page_count = page_count >> 8; } while (page_count); } + + writew(0x00, &nfc->flash_add); + writew(NFC_ADDR, &nfc->nand_flash_config2); + nfc_wait_ready(); }
static void nfc_nand_data_output(void) { + int config1 = readw(&nfc->nand_flash_config1); +#ifdef NAND_MXC_2K_MULTI_CYCLE int i; +#endif
+ config1 |= NFC_ECC_EN | NFC_INT_MSK; + writew(config1, &nfc->nand_flash_config1); + writew(0, &nfc->buffer_address); + writew(NFC_OUTPUT, &nfc->nand_flash_config2); + nfc_wait_ready(); +#ifdef NAND_MXC_2K_MULTI_CYCLE /* - * The NAND controller requires four output commands for - * large page devices. + * This NAND controller requires multiple input commands + * for pages larger than 512 bytes. */ - for (i = 0; i < (CONFIG_SYS_NAND_PAGE_SIZE / 512); i++) { - writew(NFC_ECC_EN, &nfc->nand_flash_config1); - writew(i, &nfc->buffer_address); /* read in i:th buffer */ + for (i = 1; i < (CONFIG_SYS_NAND_PAGE_SIZE / 512); i++) { + config1 = readw(&nfc->nand_flash_config1); + config1 |= NFC_ECC_EN | NFC_INT_MSK; + writew(config1, &nfc->nand_flash_config1); + writew(i, &nfc->buffer_address); writew(NFC_OUTPUT, &nfc->nand_flash_config2); nfc_wait_ready(); } +#endif }
static int nfc_nand_check_ecc(void) @@ -121,7 +163,7 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf) nfc_nand_command(NAND_CMD_READ0); nfc_nand_page_address(page_address);
- if (CONFIG_SYS_NAND_PAGE_SIZE == 0x800) + if (CONFIG_SYS_NAND_PAGE_SIZE > 512) nfc_nand_command(NAND_CMD_READSTART);
nfc_nand_data_output(); /* fill the main buffer 0 */ @@ -129,7 +171,7 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf) if (nfc_nand_check_ecc()) return -1;
- src = &nfc->main_area0[0]; + src = &nfc->main_area[0][0]; dst = (u32 *)buf;
/* main copy loop from NAND-buffer to SDRAM memory */ @@ -154,12 +196,12 @@ static int is_badblock(int pagenumber) nfc_nand_command(NAND_CMD_READ0); nfc_nand_page_address(page);
- if (CONFIG_SYS_NAND_PAGE_SIZE == 0x800) + if (CONFIG_SYS_NAND_PAGE_SIZE > 512) nfc_nand_command(NAND_CMD_READSTART);
nfc_nand_data_output(); /* fill the main buffer 0 */
- src = &nfc->spare_area0[0]; + src = &nfc->spare_area[0][0];
/* * IMPORTANT NOTE: The nand flash controller uses a non- @@ -209,7 +251,7 @@ static int nand_load(unsigned int from, unsigned int size, unsigned char *buf) if (!(page % CONFIG_SYS_NAND_PAGE_COUNT)) { /* * Yes, new block. See if this block is good. If not, - * loop until we find i good block. + * loop until we find a good block. */ while (is_badblock(page)) { page = page + CONFIG_SYS_NAND_PAGE_COUNT;

Add support for version 1.1 of the nfc nand flash controller which is on the i.mx25 soc.
Signed-off-by: John Rigby jcrigby@gmail.com CC: Scott Wood scottwood@freescale.com --- drivers/mtd/nand/mxc_nand.c | 617 ++++++++++++++++++++++++++++++++++++++----- 1 files changed, 545 insertions(+), 72 deletions(-)
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index b2b612e..35f2a03 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -22,27 +22,63 @@ #include <nand.h> #include <linux/err.h> #include <asm/io.h> -#ifdef CONFIG_MX27 #include <asm/arch/imx-regs.h> -#endif
#define DRIVER_NAME "mxc_nand"
+/* + * TODO: Use same register defs here as nand_spl mxc nand driver. + */ +/* + * Register map and bit definitions for the Freescale NAND Flash Controller + * present in various i.MX devices. + * + * MX31 and MX27 have version 1 which has + * 4 512 byte main buffers and + * 4 16 byte spare buffers + * to support up to 2K byte pagesize nand. + * Reading or writing a 2K page requires 4 FDI/FDO cycles. + * + * MX25 has version 1.1 which has + * 8 512 byte main buffers and + * 8 64 byte spare buffers + * to support up to 4K byte pagesize nand. + * Reading or writing a 2K or 4K page requires only 1 FDI/FDO cycle. + * Also some of registers are moved and/or changed meaning as seen below. + */ +#if defined(CONFIG_MX31) || defined(CONFIG_MX27) +#define MXC_NFC_V1 +#elif defined(CONFIG_MX25) +#define MXC_NFC_V1_1 +#else +#warning "MXC NFC version not defined" +#endif + +#if defined(MXC_NFC_V1) +#define NAND_MXC_NR_BUFS 4 +#define NAND_MXC_SPARE_BUF_SIZE 16 +#define NAND_MXC_REG_OFFSET 0xe00 +#define is_mxc_nfc_11() 0 +#elif defined(MXC_NFC_V1_1) +#define NAND_MXC_NR_BUFS 8 +#define NAND_MXC_SPARE_BUF_SIZE 64 +#define NAND_MXC_REG_OFFSET 0x1e00 +#define is_mxc_nfc_11() 1 +#else +#error "define CONFIG_NAND_MXC_VXXX to use mtd mxc nand driver" +#endif struct nfc_regs { -/* NFC RAM BUFFER Main area 0 */ - uint8_t main_area0[0x200]; - uint8_t main_area1[0x200]; - uint8_t main_area2[0x200]; - uint8_t main_area3[0x200]; -/* SPARE BUFFER Spare area 0 */ - uint8_t spare_area0[0x10]; - uint8_t spare_area1[0x10]; - uint8_t spare_area2[0x10]; - uint8_t spare_area3[0x10]; - uint8_t pad[0x5c0]; -/* NFC registers */ + uint8_t main_area[NAND_MXC_NR_BUFS][0x200]; + uint8_t spare_area[NAND_MXC_NR_BUFS][NAND_MXC_SPARE_BUF_SIZE]; + /* + * reserved size is offset of nfc registers + * minus total main and spare sizes + */ + uint8_t reserved1[NAND_MXC_REG_OFFSET + - NAND_MXC_NR_BUFS * (512 + NAND_MXC_SPARE_BUF_SIZE)]; +#if defined(MXC_NFC_V1) uint16_t nfc_buf_size; - uint16_t reserved; + uint16_t reserved2; uint16_t nfc_buf_addr; uint16_t nfc_flash_addr; uint16_t nfc_flash_cmd; @@ -56,6 +92,30 @@ struct nfc_regs { uint16_t nfc_nf_wrprst; uint16_t nfc_config1; uint16_t nfc_config2; +#elif defined(MXC_NFC_V1_1) + uint16_t reserved2[2]; + uint16_t nfc_buf_addr; + uint16_t nfc_flash_addr; + uint16_t nfc_flash_cmd; + uint16_t nfc_config; + uint16_t nfc_ecc_status_result; + uint16_t nfc_ecc_status_result2; + uint16_t nfc_spare_area_size; + uint16_t nfc_wrprot; + uint16_t reserved3[2]; + uint16_t nfc_nf_wrprst; + uint16_t nfc_config1; + uint16_t nfc_config2; + uint16_t reserved4; + uint16_t nfc_unlockstart_blkaddr; + uint16_t nfc_unlockend_blkaddr; + uint16_t nfc_unlockstart_blkaddr1; + uint16_t nfc_unlockend_blkaddr1; + uint16_t nfc_unlockstart_blkaddr2; + uint16_t nfc_unlockend_blkaddr2; + uint16_t nfc_unlockstart_blkaddr3; + uint16_t nfc_unlockend_blkaddr3; +#endif };
/* @@ -100,6 +160,11 @@ struct nfc_regs { */ #define NFC_INT 0x8000
+#ifdef MXC_NFC_V1_1 +#define NFC_4_8N_ECC (1 << 0) +#else +#define NFC_4_8N_ECC 0 +#endif #define NFC_SP_EN (1 << 2) #define NFC_ECC_EN (1 << 3) #define NFC_BIG (1 << 5) @@ -119,6 +184,7 @@ struct mxc_nand_host { int pagesize_2k; int clk_act; uint16_t col_addr; + unsigned int page_addr; };
static struct mxc_nand_host mxc_host; @@ -135,26 +201,45 @@ static struct mxc_nand_host *host = &mxc_host; #define SPARE_SINGLEBIT_ERROR 0x1
/* OOB placement block for use with hardware ecc generation */ -#ifdef CONFIG_MXC_NAND_HWECC +#if defined(MXC_NFC_V1) +#ifndef CONFIG_SYS_NAND_LARGEPAGE static struct nand_ecclayout nand_hw_eccoob = { .eccbytes = 5, .eccpos = {6, 7, 8, 9, 10}, - .oobfree = {{0, 5}, {11, 5}, } + .oobfree = { {0, 5}, {11, 5}, } }; #else -static struct nand_ecclayout nand_soft_eccoob = { - .eccbytes = 6, - .eccpos = {6, 7, 8, 9, 10, 11}, - .oobfree = {{0, 5}, {12, 4}, } +static struct nand_ecclayout nand_hw_eccoob2k = { + .eccbytes = 20, + .eccpos = { + 6, 7, 8, 9, 10, + 22, 23, 24, 25, 26, + 38, 39, 40, 41, 42, + 54, 55, 56, 57, 58, + }, + .oobfree = { {2, 4}, {11, 11}, {27, 11}, {43, 11}, {59, 5} }, }; #endif - -static struct nand_ecclayout nand_hw_eccoob_largepage = { - .eccbytes = 20, - .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26, - 38, 39, 40, 41, 42, 54, 55, 56, 57, 58}, - .oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, } +#elif defined(MXC_NFC_V1_1) +#ifndef CONFIG_SYS_NAND_LARGEPAGE +static struct nand_ecclayout nand_hw_eccoob = { + .eccbytes = 9, + .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, + .oobfree = { {2, 5} } +}; +#else +static struct nand_ecclayout nand_hw_eccoob2k = { + .eccbytes = 36, + .eccpos = { + 7, 8, 9, 10, 11, 12, 13, 14, 15, + 23, 24, 25, 26, 27, 28, 29, 30, 31, + 39, 40, 41, 42, 43, 44, 45, 46, 47, + 55, 56, 57, 58, 59, 60, 61, 62, 63, + }, + .oobfree = { {2, 5}, {16, 7}, {32, 7}, {48, 7} }, }; +#endif +#endif
#ifdef CONFIG_MX27 static int is_16bit_nand(void) @@ -178,6 +263,17 @@ static int is_16bit_nand(void) else return 0; } +#elif defined(CONFIG_MX25) +static int is_16bit_nand(void) +{ + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + + if (readl(&ccm->rcsr) & CCM_RCSR_NF_16BIT_SEL) + return 1; + else + return 0; +} #else #warning "8/16 bit NAND autodetection not supported" static int is_16bit_nand(void) @@ -258,7 +354,24 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr) static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id, int spare_only) { - MTDDEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only); + if (spare_only) + MTDDEBUG(MTD_DEBUG_LEVEL1, "send_prog_page (%d)\n", spare_only); + + if (is_mxc_nfc_11()) { + int i; + /* + * The controller copies the 64 bytes of spare data from + * the first 16 bytes of each of the 4 64 byte spare buffers. + * Copy the contiguous data starting in spare_area[0] to + * the four spare area buffers. + */ + for (i = 1; i < 4; i++) { + void __iomem *src = &host->regs->spare_area[0][i * 16]; + void __iomem *dst = &host->regs->spare_area[i][0]; + + mxc_nand_memcpy32(dst, src, 16); + } + }
writew(buf_id, &host->regs->nfc_buf_addr);
@@ -303,6 +416,22 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
/* Wait for operation to complete */ wait_op_done(host, TROP_US_DELAY, spare_only); + + if (is_mxc_nfc_11()) { + int i; + + /* + * The controller copies the 64 bytes of spare data to + * the first 16 bytes of each of the 4 spare buffers. + * Make the data contiguous starting in spare_area[0]. + */ + for (i = 1; i < 4; i++) { + void __iomem *src = &host->regs->spare_area[i][0]; + void __iomem *dst = &host->regs->spare_area[0][i * 16]; + + mxc_nand_memcpy32(dst, src, 16); + } + } }
/* Request the NANDFC to perform a read of the NAND device ID. */ @@ -330,7 +459,7 @@ static void send_read_id(struct mxc_nand_host *host) */ static uint16_t get_dev_status(struct mxc_nand_host *host) { - void __iomem *main_buf = host->regs->main_area1; + void __iomem *main_buf = host->regs->main_area[1]; uint32_t store; uint16_t ret, tmp; /* Issue status request to NAND device */ @@ -379,6 +508,330 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) */ }
+#ifdef MXC_NFC_V1_1 +static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on) +{ + struct nand_chip *nand_chip = mtd->priv; + struct mxc_nand_host *host = nand_chip->priv; + uint16_t tmp = readw(&host->regs->nfc_config1); + + if (on) + tmp |= NFC_ECC_EN; + else + tmp &= ~NFC_ECC_EN; + writew(tmp, &host->regs->nfc_config1); +} + +static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, + struct nand_chip *chip, + int page, int sndcmd) +{ + struct mxc_nand_host *host = chip->priv; + uint8_t *buf = chip->oob_poi; + int length = mtd->oobsize; + int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; + uint8_t *bufpoi = buf; + int i, toread; + + MTDDEBUG(MTD_DEBUG_LEVEL0, + "%s: Reading OOB area of page %u to oob %p\n", + __FUNCTION__, host->page_addr, buf); + + chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, page); + for (i = 0; i < chip->ecc.steps; i++) { + toread = min_t(int, length, chip->ecc.prepad); + if (toread) { + chip->read_buf(mtd, bufpoi, toread); + bufpoi += toread; + length -= toread; + } + bufpoi += chip->ecc.bytes; + host->col_addr += chip->ecc.bytes; + length -= chip->ecc.bytes; + + toread = min_t(int, length, chip->ecc.postpad); + if (toread) { + chip->read_buf(mtd, bufpoi, toread); + bufpoi += toread; + length -= toread; + } + } + if (length > 0) + chip->read_buf(mtd, bufpoi, length); + + _mxc_nand_enable_hwecc(mtd, 0); + chip->cmdfunc(mtd, NAND_CMD_READOOB, + mtd->writesize + chip->ecc.prepad, page); + bufpoi = buf + chip->ecc.prepad; + length = mtd->oobsize - chip->ecc.prepad; + for (i = 0; i < chip->ecc.steps; i++) { + toread = min_t(int, length, chip->ecc.bytes); + chip->read_buf(mtd, bufpoi, toread); + bufpoi += eccpitch; + length -= eccpitch; + host->col_addr += chip->ecc.postpad + chip->ecc.prepad; + } + _mxc_nand_enable_hwecc(mtd, 1); + return 1; +} + +static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd, + struct nand_chip *chip, + uint8_t *buf, + int page) +{ + struct mxc_nand_host *host = chip->priv; + int eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad; + uint8_t *oob = chip->oob_poi; + int steps, size; + int n; + + _mxc_nand_enable_hwecc(mtd, 0); + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, host->page_addr); + + for (n = 0, steps = chip->ecc.steps; steps > 0; n++, steps--) { + host->col_addr = n * eccsize; + chip->read_buf(mtd, buf, eccsize); + buf += eccsize; + + host->col_addr = mtd->writesize + n * eccpitch; + if (chip->ecc.prepad) { + chip->read_buf(mtd, oob, chip->ecc.prepad); + oob += chip->ecc.prepad; + } + + chip->read_buf(mtd, oob, eccbytes); + oob += eccbytes; + + if (chip->ecc.postpad) { + chip->read_buf(mtd, oob, chip->ecc.postpad); + oob += chip->ecc.postpad; + } + } + + size = mtd->oobsize - (oob - chip->oob_poi); + if (size) + chip->read_buf(mtd, oob, size); + _mxc_nand_enable_hwecc(mtd, 0); + + return 0; +} + +static int mxc_nand_read_page_syndrome(struct mtd_info *mtd, + struct nand_chip *chip, + uint8_t *buf, + int page) +{ + struct mxc_nand_host *host = chip->priv; + int n, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad; + int eccsteps = chip->ecc.steps; + uint8_t *p = buf; + uint8_t *oob = chip->oob_poi; + + MTDDEBUG(MTD_DEBUG_LEVEL1, "Reading page %u to buf %p oob %p\n", + host->page_addr, buf, oob); + + /* first read out the data area and the available portion of OOB */ + for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) { + int stat; + + host->col_addr = n * eccsize; + + chip->read_buf(mtd, p, eccsize); + + host->col_addr = mtd->writesize + n * eccpitch; + + if (chip->ecc.prepad) { + chip->read_buf(mtd, oob, chip->ecc.prepad); + oob += chip->ecc.prepad; + } + + stat = chip->ecc.correct(mtd, p, oob, NULL); + + if (stat < 0) + mtd->ecc_stats.failed++; + else + mtd->ecc_stats.corrected += stat; + oob += eccbytes; + + if (chip->ecc.postpad) { + chip->read_buf(mtd, oob, chip->ecc.postpad); + oob += chip->ecc.postpad; + } + } + + /* Calculate remaining oob bytes */ + n = mtd->oobsize - (oob - chip->oob_poi); + if (n) + chip->read_buf(mtd, oob, n); + + /* Then switch ECC off and read the OOB area to get the ECC code */ + _mxc_nand_enable_hwecc(mtd, 0); + chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, host->page_addr); + eccsteps = chip->ecc.steps; + oob = chip->oob_poi + chip->ecc.prepad; + for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) { + host->col_addr = mtd->writesize + + n * eccpitch + + chip->ecc.prepad; + chip->read_buf(mtd, oob, eccbytes); + oob += eccbytes + chip->ecc.postpad; + } + _mxc_nand_enable_hwecc(mtd, 1); + return 0; +} + +static int mxc_nand_write_oob_syndrome(struct mtd_info *mtd, + struct nand_chip *chip, int page) +{ + struct mxc_nand_host *host = chip->priv; + int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; + int length = mtd->oobsize; + int i, len, status, steps = chip->ecc.steps; + const uint8_t *bufpoi = chip->oob_poi; + + chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page); + for (i = 0; i < steps; i++) { + len = min_t(int, length, eccpitch); + + chip->write_buf(mtd, bufpoi, len); + bufpoi += len; + length -= len; + host->col_addr += chip->ecc.prepad + chip->ecc.postpad; + } + if (length > 0) + chip->write_buf(mtd, bufpoi, length); + + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + status = chip->waitfunc(mtd, chip); + return status & NAND_STATUS_FAIL ? -EIO : 0; +} + +static void mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd, + struct nand_chip *chip, + const uint8_t *buf) +{ + struct mxc_nand_host *host = chip->priv; + int eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad; + uint8_t *oob = chip->oob_poi; + int steps, size; + int n; + + for (n = 0, steps = chip->ecc.steps; steps > 0; n++, steps--) { + host->col_addr = n * eccsize; + chip->write_buf(mtd, buf, eccsize); + buf += eccsize; + + host->col_addr = mtd->writesize + n * eccpitch; + + if (chip->ecc.prepad) { + chip->write_buf(mtd, oob, chip->ecc.prepad); + oob += chip->ecc.prepad; + } + + host->col_addr += eccbytes; + oob += eccbytes; + + if (chip->ecc.postpad) { + chip->write_buf(mtd, oob, chip->ecc.postpad); + oob += chip->ecc.postpad; + } + } + + size = mtd->oobsize - (oob - chip->oob_poi); + if (size) + chip->write_buf(mtd, oob, size); +} + +static void mxc_nand_write_page_syndrome(struct mtd_info *mtd, + struct nand_chip *chip, + const uint8_t *buf) +{ + struct mxc_nand_host *host = chip->priv; + int i, n, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad; + int eccsteps = chip->ecc.steps; + const uint8_t *p = buf; + uint8_t *oob = chip->oob_poi; + + chip->ecc.hwctl(mtd, NAND_ECC_WRITE); + + for (i = n = 0; + eccsteps; + n++, eccsteps--, i += eccbytes, p += eccsize) { + host->col_addr = n * eccsize; + + chip->write_buf(mtd, p, eccsize); + + host->col_addr = mtd->writesize + n * eccpitch; + + if (chip->ecc.prepad) { + chip->write_buf(mtd, oob, chip->ecc.prepad); + oob += chip->ecc.prepad; + } + + chip->write_buf(mtd, oob, eccbytes); + oob += eccbytes; + + if (chip->ecc.postpad) { + chip->write_buf(mtd, oob, chip->ecc.postpad); + oob += chip->ecc.postpad; + } + } + + /* Calculate remaining oob bytes */ + i = mtd->oobsize - (oob - chip->oob_poi); + if (i) + chip->write_buf(mtd, oob, i); +} + +static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, + u_char *read_ecc, u_char *calc_ecc) +{ + struct nand_chip *nand_chip = mtd->priv; + struct mxc_nand_host *host = nand_chip->priv; + uint16_t ecc_status = readw(&host->regs->nfc_ecc_status_result); + int subpages = mtd->writesize / nand_chip->subpagesize; + int pg2blk_shift = nand_chip->phys_erase_shift - + nand_chip->page_shift; + + do { + if ((ecc_status & 0xf) > 4) { + static int last_bad = -1; + + if (last_bad != host->page_addr >> pg2blk_shift) { + last_bad = host->page_addr >> pg2blk_shift; + printk(KERN_DEBUG + "MXC_NAND: HWECC uncorrectable ECC error" + " in block %u page %u subpage %d\n", + last_bad, host->page_addr, + mtd->writesize / nand_chip->subpagesize + - subpages); + } + return -1; + } + ecc_status >>= 4; + subpages--; + } while (subpages > 0); + + return 0; +} +#else +#define mxc_nand_read_page_syndrome NULL +#define mxc_nand_read_page_raw_syndrome NULL +#define mxc_nand_read_oob_syndrome NULL +#define mxc_nand_write_page_syndrome NULL +#define mxc_nand_write_page_raw_syndrome NULL +#define mxc_nand_write_oob_syndrome NULL +#define mxc_nfc_11_nand_correct_data NULL + static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc) { @@ -400,6 +853,9 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
return 0; } +#endif + +
static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) @@ -415,9 +871,9 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) uint8_t ret = 0; uint16_t col; uint16_t __iomem *main_buf = - (uint16_t __iomem *)host->regs->main_area0; + (uint16_t __iomem *)host->regs->main_area[0]; uint16_t __iomem *spare_buf = - (uint16_t __iomem *)host->regs->spare_area0; + (uint16_t __iomem *)host->regs->spare_area[0]; union { uint16_t word; uint8_t bytes[2]; @@ -464,9 +920,10 @@ static uint16_t mxc_nand_read_word(struct mtd_info *mtd) col += mtd->writesize;
if (col < mtd->writesize) { - p = (uint16_t __iomem *)(host->regs->main_area0 + (col >> 1)); + p = (uint16_t __iomem *)(host->regs->main_area[0] + + (col >> 1)); } else { - p = (uint16_t __iomem *)(host->regs->spare_area0 + + p = (uint16_t __iomem *)(host->regs->spare_area[0] + ((col - mtd->writesize) >> 1)); }
@@ -525,9 +982,9 @@ static void mxc_nand_write_buf(struct mtd_info *mtd, void __iomem *p;
if (col < mtd->writesize) { - p = host->regs->main_area0 + (col & ~3); + p = host->regs->main_area[0] + (col & ~3); } else { - p = host->regs->spare_area0 - + p = host->regs->spare_area[0] - mtd->writesize + (col & ~3); }
@@ -595,9 +1052,9 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) void __iomem *p;
if (col < mtd->writesize) { - p = host->regs->main_area0 + (col & ~3); + p = host->regs->main_area[0] + (col & ~3); } else { - p = host->regs->spare_area0 - + p = host->regs->spare_area[0] - mtd->writesize + (col & ~3); }
@@ -683,7 +1140,7 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) * Used by the upper layer to write command to NAND Flash for * different operations to be carried out on NAND Flash */ -static void mxc_nand_command(struct mtd_info *mtd, unsigned command, +void mxc_nand_command(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct nand_chip *nand_chip = mtd->priv; @@ -705,6 +1162,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, break;
case NAND_CMD_READ0: + host->page_addr = page_addr; host->col_addr = column; host->spare_only = false; break; @@ -750,7 +1208,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, case NAND_CMD_PAGEPROG: send_prog_page(host, 0, host->spare_only);
- if (host->pagesize_2k) { + if (host->pagesize_2k && !is_mxc_nfc_11()) { /* data in 4 areas datas */ send_prog_page(host, 1, host->spare_only); send_prog_page(host, 2, host->spare_only); @@ -780,30 +1238,12 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
/* Write out page address, if necessary */ if (page_addr != -1) { - /* paddr_0 - p_addr_7 */ - send_addr(host, (page_addr & 0xff)); - - if (host->pagesize_2k) { - send_addr(host, (page_addr >> 8) & 0xFF); - if (mtd->size >= 0x10000000) { - /* paddr_8 - paddr_15 */ - send_addr(host, (page_addr >> 8) & 0xff); - send_addr(host, (page_addr >> 16) & 0xff); - } else { - /* paddr_8 - paddr_15 */ - send_addr(host, (page_addr >> 8) & 0xff); - } - } else { - /* One more address cycle for higher density devices */ - if (mtd->size >= 0x4000000) { - /* paddr_8 - paddr_15 */ - send_addr(host, (page_addr >> 8) & 0xff); - send_addr(host, (page_addr >> 16) & 0xff); - } else { - /* paddr_8 - paddr_15 */ - send_addr(host, (page_addr >> 8) & 0xff); - } - } + u32 page_mask = nand_chip->pagemask; + do { + send_addr(host, page_addr & 0xFF); + page_addr >>= 8; + page_mask >>= 8; + } while (page_mask); }
/* Command post-processing step */ @@ -819,9 +1259,11 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, send_cmd(host, NAND_CMD_READSTART); /* read for each AREA */ send_read_page(host, 0, host->spare_only); - send_read_page(host, 1, host->spare_only); - send_read_page(host, 2, host->spare_only); - send_read_page(host, 3, host->spare_only); + if (!is_mxc_nfc_11()) { + send_read_page(host, 1, host->spare_only); + send_read_page(host, 2, host->spare_only); + send_read_page(host, 3, host->spare_only); + } } else { send_read_page(host, 0, host->spare_only); } @@ -843,6 +1285,24 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, } }
+#ifdef MXC_NFC_V1_1 +static void mxc_setup_config1(void) +{ + uint16_t tmp; + + tmp = readw(&host->regs->nfc_config1); + tmp |= NFC_ONE_CYCLE; + tmp |= NFC_4_8N_ECC; + writew(tmp, &host->regs->nfc_config1); + if (host->pagesize_2k) + writew(64/2, &host->regs->nfc_spare_area_size); + else + writew(16/2, &host->regs->nfc_spare_area_size); +} +#else +#define mxc_setup_config1() +#endif + int board_nand_init(struct nand_chip *this) { struct mtd_info *mtd; @@ -874,10 +1334,23 @@ int board_nand_init(struct nand_chip *this) this->ecc.calculate = mxc_nand_calculate_ecc; this->ecc.hwctl = mxc_nand_enable_hwecc; this->ecc.correct = mxc_nand_correct_data; - this->ecc.mode = NAND_ECC_HW; + if (is_mxc_nfc_11()) { + this->ecc.mode = NAND_ECC_HW_SYNDROME; + this->ecc.read_page = mxc_nand_read_page_syndrome; + this->ecc.read_page_raw = mxc_nand_read_page_raw_syndrome; + this->ecc.read_oob = mxc_nand_read_oob_syndrome; + this->ecc.write_page = mxc_nand_write_page_syndrome; + this->ecc.write_page_raw = mxc_nand_write_page_raw_syndrome; + this->ecc.write_oob = mxc_nand_write_oob_syndrome; + this->ecc.bytes = 9; + this->ecc.prepad = 7; + } else { + this->ecc.mode = NAND_ECC_HW; + } + + host->pagesize_2k = 0; + this->ecc.size = 512; - this->ecc.bytes = 3; - this->ecc.layout = &nand_hw_eccoob; tmp = readw(&host->regs->nfc_config1); tmp |= NFC_ECC_EN; writew(tmp, &host->regs->nfc_config1); @@ -888,7 +1361,6 @@ int board_nand_init(struct nand_chip *this) tmp &= ~NFC_ECC_EN; writew(tmp, &host->regs->nfc_config1); #endif - /* Reset NAND */ this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
@@ -911,10 +1383,11 @@ int board_nand_init(struct nand_chip *this)
#ifdef CONFIG_SYS_NAND_LARGEPAGE host->pagesize_2k = 1; - this->ecc.layout = &nand_hw_eccoob_largepage; + this->ecc.layout = &nand_hw_eccoob2k; #else host->pagesize_2k = 0; + this->ecc.layout = &nand_hw_eccoob; #endif - + mxc_setup_config1(); return err; }

general cleanup move clock init to cpu_eth_init in cpu/arm926ejs/mx27/generic.c make MX27 specific phy init conditional on CONFIG_MX27 replace call to imx_get_ahbclk with one to imx_get_fecclk and define imx_get_fecclk in include/asm-arm/arch-mx27/clock.h
Signed-off-by: John Rigby jcrigby@gmail.com CC: Ben Warren biggerbadderben@gmail.com CC: Fred Fan fanyefeng@gmail.com CC: Tom Tom.Rix@windriver.com --- cpu/arm926ejs/mx27/generic.c | 5 +++++ drivers/net/fec_mxc.c | 28 +++++++++++++--------------- include/asm-arm/arch-mx27/clock.h | 1 + 3 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/cpu/arm926ejs/mx27/generic.c b/cpu/arm926ejs/mx27/generic.c index da05c55..30cf544 100644 --- a/cpu/arm926ejs/mx27/generic.c +++ b/cpu/arm926ejs/mx27/generic.c @@ -166,6 +166,11 @@ int print_cpuinfo (void) int cpu_eth_init(bd_t *bis) { #if defined(CONFIG_FEC_MXC) + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + /* enable FEC clock */ + writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); + writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0); return fecmxc_initialize(bis); #else return 0; diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 19116f2..b5619eb 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -151,7 +151,9 @@ static int miiphy_restart_aneg(struct eth_device *dev) * Wake up from sleep if necessary * Reset PHY, then delay 300ns */ +#ifdef CONFIG_MX27 miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_MIPGSR, 0x00FF); +#endif miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_BMCR, PHY_BMCR_RESET); udelay(1000); @@ -343,7 +345,8 @@ static int fec_open(struct eth_device *edev) /* * Enable FEC-Lite controller */ - writel(FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); + writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN, + &fec->eth->ecntrl);
miiphy_wait_aneg(edev); miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); @@ -415,10 +418,10 @@ static int fec_init(struct eth_device *dev, bd_t* bd) * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock * and do not drop the Preamble. */ - writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1, + writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1, &fec->eth->mii_speed); debug("fec_init: mii_speed %#lx\n", - (((imx_get_ahbclk() / 1000000) + 2) / 5) << 1); + (((imx_get_fecclk() / 1000000) + 2) / 5) << 1); } /* * Set Opcode/Pause Duration Register @@ -475,7 +478,7 @@ static void fec_halt(struct eth_device *dev) /* * issue graceful stop command to the FEC transmitter if necessary */ - writel(FEC_ECNTRL_RESET | readl(&fec->eth->x_cntrl), + writel(FEC_TCNTRL_GTS | readl(&fec->eth->x_cntrl), &fec->eth->x_cntrl);
debug("eth_halt: wait for stop regs\n"); @@ -483,7 +486,7 @@ static void fec_halt(struct eth_device *dev) * wait for graceful stop to register */ while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA))) - ; /* FIXME ensure time */ + udelay(1);
/* * Disable SmartDMA tasks @@ -495,7 +498,7 @@ static void fec_halt(struct eth_device *dev) * Disable the Ethernet Controller * Note: this will also reset the BD index counter! */ - writel(0, &fec->eth->ecntrl); + writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); fec->rbd_index = 0; fec->tbd_index = 0; debug("eth_halt: done\n"); @@ -554,7 +557,7 @@ static int fec_send(struct eth_device *dev, volatile void* packet, int length) * wait until frame is sent . */ while (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY) { - /* FIXME: Timeout */ + udelay(1); } debug("fec_send: status 0x%x index %d\n", readw(&fec->tbd_base[fec->tbd_index].status), @@ -651,7 +654,6 @@ static int fec_recv(struct eth_device *dev)
static int fec_probe(bd_t *bd) { - struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; struct eth_device *edev; struct fec_priv *fec = &gfec; unsigned char ethaddr_str[20]; @@ -659,10 +661,6 @@ static int fec_probe(bd_t *bd) char *tmp = getenv("ethaddr"); char *end;
- /* enable FEC clock */ - writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); - writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0); - /* create and fill edev struct */ edev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!edev) { @@ -681,7 +679,7 @@ static int fec_probe(bd_t *bd) fec->xcv_type = MII100;
/* Reset chip. */ - writel(FEC_ECNTRL_RESET, &fec->eth->ecntrl); + writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl); while (readl(&fec->eth->ecntrl) & 1) udelay(10);
@@ -706,10 +704,10 @@ static int fec_probe(bd_t *bd) * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock * and do not drop the Preamble. */ - writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1, + writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1, &fec->eth->mii_speed); debug("fec_init: mii_speed %#lx\n", - (((imx_get_ahbclk() / 1000000) + 2) / 5) << 1); + (((imx_get_fecclk() / 1000000) + 2) / 5) << 1);
sprintf(edev->name, "FEC_MXC");
diff --git a/include/asm-arm/arch-mx27/clock.h b/include/asm-arm/arch-mx27/clock.h index 472e8f2..7e9c7aa 100644 --- a/include/asm-arm/arch-mx27/clock.h +++ b/include/asm-arm/arch-mx27/clock.h @@ -37,5 +37,6 @@ ulong imx_get_perclk3(void); ulong imx_get_ahbclk(void);
#define imx_get_uartclk imx_get_perclk1 +#define imx_get_fecclk imx_get_ahbclk
#endif /* __ASM_ARCH_CLOCK_H */

ARM926EJS core with MX31 peripherals.
Signed-off-by: John Rigby jcrigby@gmail.com Earlier Version Signed-off-by: Wolfgang Denk wd@denx.de CC: Fred Fan fanyefeng@gmail.com CC: Tom Tom.Rix@windriver.com --- cpu/arm926ejs/mx25/Makefile | 46 ++++ cpu/arm926ejs/mx25/generic.c | 263 +++++++++++++++++++ cpu/arm926ejs/mx25/reset.c | 56 ++++ cpu/arm926ejs/mx25/timer.c | 187 +++++++++++++ drivers/serial/serial_mxc.c | 10 +- include/asm-arm/arch-mx25/clock.h | 35 +++ include/asm-arm/arch-mx25/imx-regs.h | 316 ++++++++++++++++++++++ include/asm-arm/arch-mx25/imx25-pinmux.h | 421 ++++++++++++++++++++++++++++++ 8 files changed, 1329 insertions(+), 5 deletions(-) create mode 100644 cpu/arm926ejs/mx25/Makefile create mode 100644 cpu/arm926ejs/mx25/generic.c create mode 100644 cpu/arm926ejs/mx25/reset.c create mode 100644 cpu/arm926ejs/mx25/timer.c create mode 100644 include/asm-arm/arch-mx25/clock.h create mode 100644 include/asm-arm/arch-mx25/imx-regs.h create mode 100644 include/asm-arm/arch-mx25/imx25-pinmux.h
diff --git a/cpu/arm926ejs/mx25/Makefile b/cpu/arm926ejs/mx25/Makefile new file mode 100644 index 0000000..55c1e89 --- /dev/null +++ b/cpu/arm926ejs/mx25/Makefile @@ -0,0 +1,46 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +COBJS = generic.o timer.o +MX27OBJS = reset.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +SRCS += $(addprefix $(SRCTREE)/cpu/arm926ejs/mx27/,$(MX27OBJS:.o=.c)) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS) $(MX27OBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm926ejs/mx25/generic.c b/cpu/arm926ejs/mx25/generic.c new file mode 100644 index 0000000..694841d --- /dev/null +++ b/cpu/arm926ejs/mx25/generic.c @@ -0,0 +1,263 @@ +/* + * (C) Copyright 2009 DENX Software Engineering + * Author: John Rigby jrigby@gmail.com + * + * Based on mx27/generic.c: + * Copyright (c) 2008 Eric Jarrige eric.jarrige@armadeus.org + * Copyright (c) 2009 Ilya Yanok 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 <common.h> +#include <div64.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/imx25-pinmux.h> +#ifdef CONFIG_MXC_MMC +#include <asm/arch/mxcmmc.h> +#endif + +/* + * get the system pll clock in Hz + * + * mfi + mfn / (mfd +1) + * f = 2 * f_ref * -------------------- + * pd + 1 + */ +static unsigned int imx_decode_pll (unsigned int pll, unsigned int f_ref) +{ + unsigned int mfi = (pll >> CCM_PLL_MFI_SHIFT) + & CCM_PLL_MFI_MASK; + unsigned int mfn = (pll >> CCM_PLL_MFN_SHIFT) + & CCM_PLL_MFN_MASK; + unsigned int mfd = (pll >> CCM_PLL_MFD_SHIFT) + & CCM_PLL_MFD_MASK; + unsigned int pd = (pll >> CCM_PLL_PD_SHIFT) + & CCM_PLL_PD_MASK; + + mfi = mfi <= 5 ? 5 : mfi; + + return lldiv (2 * (u64) f_ref * (mfi * (mfd + 1) + mfn), + (mfd + 1) * (pd + 1)); +} + +static ulong imx_get_mpllclk (void) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong fref = 24000000; + + return imx_decode_pll (readl (&ccm->mpctl), fref); +} + +ulong imx_get_armclk (void) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong cctl = readl (&ccm->cctl); + ulong fref = imx_get_mpllclk (); + ulong div; + + if (cctl & CCM_CCTL_ARM_SRC) + fref = lldiv ((fref * 3), 4); + + div = ((cctl >> CCM_CCTL_ARM_DIV_SHIFT) + & CCM_CCTL_ARM_DIV_MASK) + 1; + + return lldiv (fref, div); +} + +ulong imx_get_ahbclk (void) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong cctl = readl (&ccm->cctl); + ulong fref = imx_get_armclk (); + ulong div; + + div = ((cctl >> CCM_CCTL_AHB_DIV_SHIFT) + & CCM_CCTL_AHB_DIV_MASK) + 1; + + return lldiv (fref, div); +} + +ulong imx_get_perclk (int clk) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong fref = imx_get_ahbclk (); + ulong div; + + div = readl (&ccm->pcdr[CCM_PERCLK_REG (clk)]); + div = ((div >> CCM_PERCLK_SHIFT (clk)) & CCM_PERCLK_MASK) + 1; + + return lldiv (fref, div); +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo (void) +{ + char buf[32]; + + printf ("CPU: Freescale i.MX25 at %s MHz\n\n", + strmhz (buf, imx_get_mpllclk ())); + return 0; +} +#endif + +int cpu_eth_init (bd_t * bis) +{ +#if defined(CONFIG_FEC_MXC) + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong val; + + val = readl (&ccm->cgr0); + val |= (1 << 23); + writel (val, &ccm->cgr0); + return fecmxc_initialize (bis); +#else + return 0; +#endif +} + +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init (bd_t * bis) +{ +#ifdef CONFIG_MXC_MMC + return mxc_mmc_init (bis); +#else + return 0; +#endif +} + +#ifdef CONFIG_MXC_UART +void mx25_uart_init_pins (void) +{ + struct iomuxc_mux_ctl *muxctl; + struct iomuxc_pad_ctl *padctl; + u32 inpadctl; + u32 outpadctl; + u32 muxmode0; + + muxctl = (struct iomuxc_mux_ctl *)IMX_IOPADMUX_BASE; + padctl = (struct iomuxc_pad_ctl *)IMX_IOPADCTL_BASE; + muxmode0 = MX25_PIN_MUX_MODE (0); + /* + * set up input pins with hysteresis and 100K pull-ups + */ + inpadctl = MX25_PIN_PAD_CTL_HYS + | MX25_PIN_PAD_CTL_PKE + | MX25_PIN_PAD_CTL_PUE | MX25_PIN_PAD_CTL_100K_PU; + + /* + * set up output pins with 100K pull-downs + * FIXME: need to revisit this + * PUE is ignored if PKE is not set + * so the right value here is likely + * 0x0 for no pull up/down + * or + * 0xc0 for 100k pull down + */ + outpadctl = MX25_PIN_PAD_CTL_PUE | MX25_PIN_PAD_CTL_100K_PD; + + /* UART1 */ + /* rxd */ + writel (muxmode0, &muxctl->pad_uart1_rxd); + writel (inpadctl, &padctl->pad_uart1_rxd); + + /* txd */ + writel (muxmode0, &muxctl->pad_uart1_txd); + writel (outpadctl, &padctl->pad_uart1_txd); + + /* rts */ + writel (muxmode0, &muxctl->pad_uart1_rts); + writel (outpadctl, &padctl->pad_uart1_rts); + + /* cts */ + writel (muxmode0, &muxctl->pad_uart1_cts); + writel (inpadctl, &padctl->pad_uart1_cts); +} +#endif /* CONFIG_MXC_UART */ + +#ifdef CONFIG_FEC_MXC +void mx25_fec_init_pins (void) +{ + struct iomuxc_mux_ctl *muxctl; + struct iomuxc_pad_ctl *padctl; + u32 inpadctl_100kpd; + u32 inpadctl_22kpu; + u32 outpadctl; + u32 muxmode0; + + muxctl = (struct iomuxc_mux_ctl *)IMX_IOPADMUX_BASE; + padctl = (struct iomuxc_pad_ctl *)IMX_IOPADCTL_BASE; + muxmode0 = MX25_PIN_MUX_MODE (0); + inpadctl_100kpd = MX25_PIN_PAD_CTL_HYS + | MX25_PIN_PAD_CTL_PKE + | MX25_PIN_PAD_CTL_PUE | MX25_PIN_PAD_CTL_100K_PD; + inpadctl_22kpu = MX25_PIN_PAD_CTL_HYS + | MX25_PIN_PAD_CTL_PKE + | MX25_PIN_PAD_CTL_PUE | MX25_PIN_PAD_CTL_22K_PU; + /* + * set up output pins with 100K pull-downs + * FIXME: need to revisit this + * PUE is ignored if PKE is not set + * so the right value here is likely + * 0x0 for no pull + * or + * 0xc0 for 100k pull down + */ + outpadctl = MX25_PIN_PAD_CTL_PUE | MX25_PIN_PAD_CTL_100K_PD; + + /* FEC_TX_CLK */ + writel (muxmode0, &muxctl->pad_fec_tx_clk); + writel (inpadctl_100kpd, &padctl->pad_fec_tx_clk); + + /* FEC_RX_DV */ + writel (muxmode0, &muxctl->pad_fec_rx_dv); + writel (inpadctl_100kpd, &padctl->pad_fec_rx_dv); + + /* FEC_RDATA0 */ + writel (muxmode0, &muxctl->pad_fec_rdata0); + writel (inpadctl_100kpd, &padctl->pad_fec_rdata0); + + /* FEC_TDATA0 */ + writel (muxmode0, &muxctl->pad_fec_tdata0); + writel (outpadctl, &padctl->pad_fec_tdata0); + + /* FEC_TX_EN */ + writel (muxmode0, &muxctl->pad_fec_tx_en); + writel (outpadctl, &padctl->pad_fec_tx_en); + + /* FEC_MDC */ + writel (muxmode0, &muxctl->pad_fec_mdc); + writel (outpadctl, &padctl->pad_fec_mdc); + + /* FEC_MDIO */ + writel (muxmode0, &muxctl->pad_fec_mdio); + writel (inpadctl_22kpu, &padctl->pad_fec_mdio); + + /* FEC_RDATA1 */ + writel (muxmode0, &muxctl->pad_fec_rdata1); + writel (inpadctl_100kpd, &padctl->pad_fec_rdata1); + + /* FEC_TDATA1 */ + writel (muxmode0, &muxctl->pad_fec_tdata1); + writel (outpadctl, &padctl->pad_fec_tdata1); + +} +#endif /* CONFIG_FEC_MXC */ diff --git a/cpu/arm926ejs/mx25/reset.c b/cpu/arm926ejs/mx25/reset.c new file mode 100644 index 0000000..1e33150 --- /dev/null +++ b/cpu/arm926ejs/mx25/reset.c @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger mgroeger@sysgo.de + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke azu@sysgo.de + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, gj@denx.de + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* + * Reset the cpu by setting up the watchdog timer and let it time out + */ +void reset_cpu (ulong ignored) +{ + struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE; + /* Disable watchdog and set Time-Out field to 0 */ + writel (0x00000000, ®s->wcr); + + /* Write Service Sequence */ + writel (0x00005555, ®s->wsr); + writel (0x0000AAAA, ®s->wsr); + + /* Enable watchdog */ + writel (WCR_WDE, ®s->wcr); + + while (1) ; +} diff --git a/cpu/arm926ejs/mx25/timer.c b/cpu/arm926ejs/mx25/timer.c new file mode 100644 index 0000000..11d41a8 --- /dev/null +++ b/cpu/arm926ejs/mx25/timer.c @@ -0,0 +1,187 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger mgroeger@sysgo.de + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke azu@sysgo.de + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, gj@denx.de + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com + * + * (C) Copyright 2009 DENX Software Engineering + * Author: John Rigby jrigby@gmail.com + * Add support for MX25 + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 <common.h> +#include <div64.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +static ulong timestamp; +static ulong lastinc; + +/* + * "time" is measured in 1 / CONFIG_SYS_HZ seconds, + * "tick" is internal timer period + */ +#ifdef CONFIG_MX25_TIMER_HIGH_PRECISION +/* ~0.4% error - measured with stop-watch on 100s boot-delay */ +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, CONFIG_MX25_CLK32); + return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ + time *= CONFIG_MX25_CLK32; + do_div(time, CONFIG_SYS_HZ); + return time; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ + us = us * CONFIG_MX25_CLK32 + 999999; + do_div(us, 1000000); + return us; +} +#else +/* ~2% error */ +#define TICK_PER_TIME ((CONFIG_MX25_CLK32 + CONFIG_SYS_HZ / 2) / \ + CONFIG_SYS_HZ) +#define US_PER_TICK (1000000 / CONFIG_MX25_CLK32) + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + do_div(tick, TICK_PER_TIME); + return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ + return time * TICK_PER_TIME; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ + us += US_PER_TICK - 1; + do_div(us, US_PER_TICK); + return us; +} +#endif + +/* nothing really to do with interrupts, just starts up a counter. */ +/* The 32KHz 32-bit timer overruns in 134217 seconds */ +int timer_init(void) +{ + int i; + struct gpt_regs *gpt = (struct gpt_regs *)IMX_GPT1_BASE; + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + + /* setup GP Timer 1 */ + writel(GPT_CTRL_SWR, &gpt->ctrl); + + writel(readl(&ccm->cgr1) | CCM_CGR1_GPT1, &ccm->cgr1); + + for (i = 0; i < 100; i++) + writel(0, &gpt->ctrl); /* We have no udelay by now */ + writel(0, &gpt->pre); /* prescaler = 1 */ + /* Freerun Mode, 32KHz input */ + writel(readl(&gpt->ctrl) | GPT_CTRL_CLKSOURCE_32 | GPT_CTRL_FRR, + &gpt->ctrl); + writel(readl(&gpt->ctrl) | GPT_CTRL_TEN, &gpt->ctrl); + + return 0; +} + +void reset_timer_masked(void) +{ + struct gpt_regs *gpt = (struct gpt_regs *)IMX_GPT1_BASE; + /* reset time */ + /* capture current incrementer value time */ + lastinc = readl(&gpt->counter); + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +void reset_timer(void) +{ + reset_timer_masked(); +} + +unsigned long long get_ticks (void) +{ + struct gpt_regs *gpt = (struct gpt_regs *)IMX_GPT1_BASE; + ulong now = readl(&gpt->counter); /* current tick value */ + + if (now >= lastinc) { + /* + * normal mode (non roll) + * move stamp forward with absolut diff ticks + */ + timestamp += (now - lastinc); + } else { + /* we have rollover of incrementer */ + timestamp += (0xFFFFFFFF - lastinc) + now; + } + lastinc = now; + return timestamp; +} + +ulong get_timer_masked (void) +{ + /* + * get_ticks() returns a long long (64 bit), it wraps in + * 2^64 / CONFIG_MX25_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ + * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in + * 5 * 10^6 days - long enough. + */ + return tick_to_time(get_ticks()); +} + +ulong get_timer (ulong base) +{ + return get_timer_masked () - base; +} + +void set_timer (ulong t) +{ + timestamp = time_to_tick(t); +} + +/* delay x useconds AND preserve advance timstamp value */ +void __udelay (unsigned long usec) +{ + unsigned long long tmp; + ulong tmo; + + tmo = us_to_tick(usec); + tmp = get_ticks() + tmo; /* get current timestamp */ + + while (get_ticks() < tmp) /* loop till event */ + /*NOP*/; +} diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c index 7dcedf6..70c1c1e 100644 --- a/drivers/serial/serial_mxc.c +++ b/drivers/serial/serial_mxc.c @@ -27,15 +27,15 @@
#define __REG(x) (*((volatile u32 *)(x)))
-#ifdef CONFIG_SYS_MX31_UART1 +#if defined(CONFIG_SYS_MX31_UART1) || defined(CONFIG_SYS_MX25_UART1) #define UART_PHYS 0x43f90000 -#elif defined(CONFIG_SYS_MX31_UART2) +#elif defined(CONFIG_SYS_MX31_UART2) || defined(CONFIG_SYS_MX25_UART2) #define UART_PHYS 0x43f94000 -#elif defined(CONFIG_SYS_MX31_UART3) +#elif defined(CONFIG_SYS_MX31_UART3) || defined(CONFIG_SYS_MX25_UART3) #define UART_PHYS 0x5000c000 -#elif defined(CONFIG_SYS_MX31_UART4) +#elif defined(CONFIG_SYS_MX31_UART4) || defined(CONFIG_SYS_MX25_UART4) #define UART_PHYS 0x43fb0000 -#elif defined(CONFIG_SYS_MX31_UART5) +#elif defined(CONFIG_SYS_MX31_UART5) || defined(CONFIG_SYS_MX25_UART5) #define UART_PHYS 0x43fb4000 #elif defined(CONFIG_SYS_MX27_UART1) #define UART_PHYS 0x1000a000 diff --git a/include/asm-arm/arch-mx25/clock.h b/include/asm-arm/arch-mx25/clock.h new file mode 100644 index 0000000..b0752e7 --- /dev/null +++ b/include/asm-arm/arch-mx25/clock.h @@ -0,0 +1,35 @@ +/* + * + * (c) 2009 Ilya Yanok, Emcraft Systems yanok@emcraft.com + * + * Modified for mx25 by John Rigby jrigby@gmail.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +#ifndef __ASM_ARCH_CLOCK_H +#define __ASM_ARCH_CLOCK_H + +ulong imx_get_perclk(int clk); +ulong imx_get_ahbclk(void); + +#define imx_get_uartclk() imx_get_perclk(15) + + +#endif /* __ASM_ARCH_CLOCK_H */ diff --git a/include/asm-arm/arch-mx25/imx-regs.h b/include/asm-arm/arch-mx25/imx-regs.h new file mode 100644 index 0000000..f709bd8 --- /dev/null +++ b/include/asm-arm/arch-mx25/imx-regs.h @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2009, DENX Software Engineering + * Author: John Rigby <jcrigby@gmail.com + * + * Based on arch-mx31/mx31-regs.h + * Copyright (C) 2009 Ilya Yanok, + * Emcraft Systems yanok@emcraft.com + * and arch-mx27/imx-regs.h + * Copyright (C) 2007 Pengutronix, + * Sascha Hauer s.hauer@pengutronix.de + * Copyright (C) 2009 Ilya Yanok, + * Emcraft Systems yanok@emcraft.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +#ifndef _IMX_REGS_H +#define _IMX_REGS_H + +#ifndef __ASSEMBLY__ +#ifdef CONFIG_FEC_MXC +extern void mx25_fec_init_pins(void); +#endif + +/* Clock Control Module (CCM) registers */ +struct ccm_regs { + u32 mpctl; /* Core PLL Control */ + u32 upctl; /* USB PLL Control */ + u32 cctl; /* Clock Control */ + u32 cgr0; /* Clock Gating Control 0 */ + u32 cgr1; /* Clock Gating Control 1 */ + u32 cgr2; /* Clock Gating Control 2 */ + u32 pcdr[4]; /* PER Clock Dividers */ + u32 rcsr; /* CCM Status */ + u32 crdr; /* CCM Reset and Debug */ + u32 dcvr0; /* DPTC Comparator Value 0 */ + u32 dcvr1; /* DPTC Comparator Value 1 */ + u32 dcvr2; /* DPTC Comparator Value 2 */ + u32 dcvr3; /* DPTC Comparator Value 3 */ + u32 ltr0; /* Load Tracking 0 */ + u32 ltr1; /* Load Tracking 1 */ + u32 ltr2; /* Load Tracking 2 */ + u32 ltr3; /* Load Tracking 3 */ + u32 ltbr0; /* Load Tracking Buffer 0 */ + u32 ltbr1; /* Load Tracking Buffer 1 */ + u32 pcmr0; /* Power Management Control 0 */ + u32 pcmr1; /* Power Management Control 1 */ + u32 pcmr2; /* Power Management Control 2 */ + u32 mcr; /* Miscellaneous Control */ + u32 lpimr0; /* Low Power Interrupt Mask 0 */ + u32 lpimr1; /* Low Power Interrupt Mask 1 */ +}; + +/* Enhanced SDRAM Controller (ESDRAMC) registers */ +struct esdramc_regs { + u32 ctl0; /* control 0 */ + u32 cfg0; /* configuration 0 */ + u32 ctl1; /* control 1 */ + u32 cfg1; /* configuration 1 */ + u32 misc; /* miscellaneous */ + u32 pad[3]; + u32 cdly1; /* Delay Line 1 configuration debug */ + u32 cdly2; /* delay line 2 configuration debug */ + u32 cdly3; /* delay line 3 configuration debug */ + u32 cdly4; /* delay line 4 configuration debug */ + u32 cdly5; /* delay line 5 configuration debug */ + u32 cdlyl; /* delay line cycle length debug */ +}; + +/* GPIO registers */ +struct gpio_regs { + u32 dr; /* data */ + u32 dir; /* direction */ + u32 psr; /* pad satus */ + u32 icr1; /* interrupt config 1 */ + u32 icr2; /* interrupt config 2 */ + u32 imr; /* interrupt mask */ + u32 isr; /* interrupt status */ + u32 edge_sel; /* edge select */ +}; + +/* General Purpose Timer (GPT) registers */ +struct gpt_regs { + u32 ctrl; /* control */ + u32 pre; /* prescaler */ + u32 stat; /* status */ + u32 intr; /* interrupt */ + u32 cmp[3]; /* output compare 1-3 */ + u32 capt[2]; /* input capture 1-2 */ + u32 counter; /* counter */ +}; + +/* Watchdog Timer (WDOG) registers */ +struct wdog_regs { + u32 wcr; /* Control */ + u32 wsr; /* Service */ + u32 wrsr; /* Reset Status */ + u32 wicr; /* Interrupt Control */ + u32 wmcr; /* Misc Control */ +}; + +/* IIM control registers */ +struct iim_regs { + u32 iim_stat; + u32 iim_statm; + u32 iim_err; + u32 iim_emask; + u32 iim_fctl; + u32 iim_ua; + u32 iim_la; + u32 iim_sdat; + u32 iim_prev; + u32 iim_srev; + u32 iim_prog_p; + u32 res1[0x1f5]; + u32 iim_bank_area0[0x20]; + u32 res2[0xe0]; + u32 iim_bank_area1[0x20]; + u32 res3[0xe0]; + u32 iim_bank_area2[0x20]; +}; +#endif + +/* AIPS 1 */ +#define IMX_AIPS1_BASE (0x43F00000) +#define IMX_MAX_BASE (0x43F04000) +#define IMX_CLKCTL_BASE (0x43F08000) +#define IMX_ETB_SLOT4_BASE (0x43F0C000) +#define IMX_ETB_SLOT5_BASE (0x43F10000) +#define IMX_ECT_CTIO_BASE (0x43F18000) +#define IMX_I2C_BASE (0x43F80000) +#define IMX_I2C3_BASE (0x43F84000) +#define IMX_CAN1_BASE (0x43F88000) +#define IMX_CAN2_BASE (0x43F8C000) +#define IMX_UART1_BASE (0x43F90000) +#define IMX_UART2_BASE (0x43F94000) +#define IMX_I2C2_BASE (0x43F98000) +#define IMX_OWIRE_BASE (0x43F9C000) +#define IMX_CSPI1_BASE (0x43FA4000) +#define IMX_KPP_BASE (0x43FA8000) +#define IMX_IOPADMUX_BASE (0x43FAC000) +#define IMX_IOPADCTL_BASE (0x43FAC22C) +#define IMX_IOPADGRPCTL_BASE (0x43FAC418) +#define IMX_IOPADINPUTSEL_BASE (0x43FAC460) +#define IMX_AUDMUX_BASE (0x43FB0000) +#define IMX_ECT_IP1_BASE (0x43FB8000) +#define IMX_ECT_IP2_BASE (0x43FBC000) + +/* SPBA */ +#define IMX_SPBA_BASE (0x50000000) +#define IMX_CSPI3_BASE (0x50004000) +#define IMX_UART4_BASE (0x50008000) +#define IMX_UART3_BASE (0x5000C000) +#define IMX_CSPI2_BASE (0x50010000) +#define IMX_SSI2_BASE (0x50014000) +#define IMX_ESAI_BASE (0x50018000) +#define IMX_ATA_DMA_BASE (0x50020000) +#define IMX_SIM1_BASE (0x50024000) +#define IMX_SIM2_BASE (0x50028000) +#define IMX_UART5_BASE (0x5002C000) +#define IMX_TSC_BASE (0x50030000) +#define IMX_SSI1_BASE (0x50034000) +#define IMX_FEC_BASE (0x50038000) +#define IMX_SPBA_CTRL_BASE (0x5003C000) + +/* AIPS 2 */ +#define IMX_AIPS2_BASE (0x53F00000) +#define IMX_CCM_BASE (0x53F80000) +#define IMX_GPT4_BASE (0x53F84000) +#define IMX_GPT3_BASE (0x53F88000) +#define IMX_GPT2_BASE (0x53F8C000) +#define IMX_GPT1_BASE (0x53F90000) +#define IMX_EPIT1_BASE (0x53F94000) +#define IMX_EPIT2_BASE (0x53F98000) +#define IMX_GPIO4_BASE (0x53F9C000) +#define IMX_PWM2_BASE (0x53FA0000) +#define IMX_GPIO3_BASE (0x53FA4000) +#define IMX_PWM3_BASE (0x53FA8000) +#define IMX_SCC_BASE (0x53FAC000) +#define IMX_SCM_BASE (0x53FAE000) +#define IMX_SMN_BASE (0x53FAF000) +#define IMX_RNGD_BASE (0x53FB0000) +#define IMX_MMC_SDHC1_BASE (0x53FB4000) +#define IMX_MMC_SDHC2_BASE (0x53FB8000) +#define IMX_LCDC_BASE (0x53FBC000) +#define IMX_SLCDC_BASE (0x53FC0000) +#define IMX_PWM4_BASE (0x53FC8000) +#define IMX_GPIO1_BASE (0x53FCC000) +#define IMX_GPIO2_BASE (0x53FD0000) +#define IMX_SDMA_BASE (0x53FD4000) +#define IMX_WDT_BASE (0x53FDC000) +#define IMX_PWM1_BASE (0x53FE0000) +#define IMX_RTIC_BASE (0x53FEC000) +#define IMX_IIM_BASE (0x53FF0000) +#define IMX_USB_BASE (0x53FF4000) +#define IMX_CSI_BASE (0x53FF8000) +#define IMX_DRYICE_BASE (0x53FFC000) + +#define IMX_ARM926_ROMPATCH (0x60000000) +#define IMX_ARM926_ASIC (0x68000000) + +/* 128K Internal Static RAM */ +#define IMX_RAM_BASE (0x78000000) + +/* SDRAM BANKS */ +#define IMX_SDRAM_BANK0_BASE (0x80000000) +#define IMX_SDRAM_BANK1_BASE (0x90000000) + +#define IMX_WEIM_CS0 (0xA0000000) +#define IMX_WEIM_CS1 (0xA8000000) +#define IMX_WEIM_CS2 (0xB0000000) +#define IMX_WEIM_CS3 (0xB2000000) +#define IMX_WEIM_CS4 (0xB4000000) +#define IMX_ESDRAMC_BASE (0xB8001000) +#define IMX_WEIM_CTRL_BASE (0xB8002000) +#define IMX_M3IF_CTRL_BASE (0xB8003000) +#define IMX_EMI_CTRL_BASE (0xB8004000) + +/* NAND Flash Controller */ +#define IMX_NFC_BASE (0xBB000000) +#define NFC_BASE_ADDR IMX_NFC_BASE + +/* CCM bitfields */ +#define CCM_PLL_MFI_SHIFT 10 +#define CCM_PLL_MFI_MASK 0xf +#define CCM_PLL_MFN_SHIFT 0 +#define CCM_PLL_MFN_MASK 0x3ff +#define CCM_PLL_MFD_SHIFT 16 +#define CCM_PLL_MFD_MASK 0x3ff +#define CCM_PLL_PD_SHIFT 26 +#define CCM_PLL_PD_MASK 0xf +#define CCM_CCTL_ARM_DIV_SHIFT 30 +#define CCM_CCTL_ARM_DIV_MASK 3 +#define CCM_CCTL_AHB_DIV_SHIFT 28 +#define CCM_CCTL_AHB_DIV_MASK 3 +#define CCM_CCTL_ARM_SRC (1 << 14) +#define CCM_CGR1_GPT1 (1 << 19) +#define CCM_PERCLK_REG(clk) (clk / 4) +#define CCM_PERCLK_SHIFT(clk) (8 * (clk % 4)) +#define CCM_PERCLK_MASK 0x3f +#define CCM_RCSR_NF_16BIT_SEL (1 << 14) +#define CCM_RCSR_NF_PS(v) ((v >> 26) & 3) + +/* ESDRAM Controller register bitfields */ +#define ESDCTL_PRCT(x) (((x) & 0x3f) << 0) +#define ESDCTL_BL (1 << 7) +#define ESDCTL_FP (1 << 8) +#define ESDCTL_PWDT(x) (((x) & 3) << 10) +#define ESDCTL_SREFR(x) (((x) & 7) << 13) +#define ESDCTL_DSIZ_16_UPPER (0 << 16) +#define ESDCTL_DSIZ_16_LOWER (1 << 16) +#define ESDCTL_DSIZ_32 (2 << 16) +#define ESDCTL_COL8 (0 << 20) +#define ESDCTL_COL9 (1 << 20) +#define ESDCTL_COL10 (2 << 20) +#define ESDCTL_ROW11 (0 << 24) +#define ESDCTL_ROW12 (1 << 24) +#define ESDCTL_ROW13 (2 << 24) +#define ESDCTL_ROW14 (3 << 24) +#define ESDCTL_ROW15 (4 << 24) +#define ESDCTL_SP (1 << 27) +#define ESDCTL_SMODE_NORMAL (0 << 28) +#define ESDCTL_SMODE_PRECHARGE (1 << 28) +#define ESDCTL_SMODE_AUTO_REF (2 << 28) +#define ESDCTL_SMODE_LOAD_MODE (3 << 28) +#define ESDCTL_SMODE_MAN_REF (4 << 28) +#define ESDCTL_SDE (1 << 31) + +#define ESDCFG_TRC(x) (((x) & 0xf) << 0) +#define ESDCFG_TRCD(x) (((x) & 0x7) << 4) +#define ESDCFG_TCAS(x) (((x) & 0x3) << 8) +#define ESDCFG_TRRD(x) (((x) & 0x3) << 10) +#define ESDCFG_TRAS(x) (((x) & 0x7) << 12) +#define ESDCFG_TWR (1 << 15) +#define ESDCFG_TMRD(x) (((x) & 0x3) << 16) +#define ESDCFG_TRP(x) (((x) & 0x3) << 18) +#define ESDCFG_TWTR (1 << 20) +#define ESDCFG_TXP(x) (((x) & 0x3) << 21) + +#define ESDMISC_RST (1 << 1) +#define ESDMISC_MDDREN (1 << 2) +#define ESDMISC_MDDR_DL_RST (1 << 3) +#define ESDMISC_MDDR_MDIS (1 << 4) +#define ESDMISC_LHD (1 << 5) +#define ESDMISC_MA10_SHARE (1 << 6) +#define ESDMISC_SDRAM_RDY (1 << 31) + +/* GPT bits */ +#define GPT_CTRL_SWR (1 << 15) /* Software reset */ +#define GPT_CTRL_FRR (1 << 9) /* Freerun / restart */ +#define GPT_CTRL_CLKSOURCE_32 (4 << 6) /* Clock source */ +#define GPT_CTRL_TEN 1 /* Timer enable */ + +/* WDOG enable */ +#define WCR_WDE 0x04 + +/* FUSE bank offsets */ +#define IIM0_MAC 0x1a + +#endif /* _IMX_REGS_H */ diff --git a/include/asm-arm/arch-mx25/imx25-pinmux.h b/include/asm-arm/arch-mx25/imx25-pinmux.h new file mode 100644 index 0000000..a4c658b --- /dev/null +++ b/include/asm-arm/arch-mx25/imx25-pinmux.h @@ -0,0 +1,421 @@ +/* + * iopin settings are controlled by four different sets of registers + * iopad mux control + * individual iopad setup (voltage select, pull/keep, drive strength ...) + * group iopad setup (same as above but for groups of signals) + * input select when multiple inputs are possible + */ + +/* + * software pad mux control + */ +/* SW Input On (Loopback) */ +#define MX25_PIN_MUX_SION (1 << 4) +/* MUX Mode (0-7) */ +#define MX25_PIN_MUX_MODE(mode) ((mode & 0x7) << 0) +struct iomuxc_mux_ctl { + u32 gpr1; + u32 observe_int_mux; + u32 pad_a10; + u32 pad_a13; + u32 pad_a14; + u32 pad_a15; + u32 pad_a16; + u32 pad_a17; + u32 pad_a18; + u32 pad_a19; + u32 pad_a20; + u32 pad_a21; + u32 pad_a22; + u32 pad_a23; + u32 pad_a24; + u32 pad_a25; + u32 pad_eb0; + u32 pad_eb1; + u32 pad_oe; + u32 pad_cs0; + u32 pad_cs1; + u32 pad_cs4; + u32 pad_cs5; + u32 pad_nf_ce0; + u32 pad_ecb; + u32 pad_lba; + u32 pad_bclk; + u32 pad_rw; + u32 pad_nfwe_b; + u32 pad_nfre_b; + u32 pad_nfale; + u32 pad_nfcle; + u32 pad_nfwp_b; + u32 pad_nfrb; + u32 pad_d15; + u32 pad_d14; + u32 pad_d13; + u32 pad_d12; + u32 pad_d11; + u32 pad_d10; + u32 pad_d9; + u32 pad_d8; + u32 pad_d7; + u32 pad_d6; + u32 pad_d5; + u32 pad_d4; + u32 pad_d3; + u32 pad_d2; + u32 pad_d1; + u32 pad_d0; + u32 pad_ld0; + u32 pad_ld1; + u32 pad_ld2; + u32 pad_ld3; + u32 pad_ld4; + u32 pad_ld5; + u32 pad_ld6; + u32 pad_ld7; + u32 pad_ld8; + u32 pad_ld9; + u32 pad_ld10; + u32 pad_ld11; + u32 pad_ld12; + u32 pad_ld13; + u32 pad_ld14; + u32 pad_ld15; + u32 pad_hsync; + u32 pad_vsync; + u32 pad_lsclk; + u32 pad_oe_acd; + u32 pad_contrast; + u32 pad_pwm; + u32 pad_csi_d2; + u32 pad_csi_d3; + u32 pad_csi_d4; + u32 pad_csi_d5; + u32 pad_csi_d6; + u32 pad_csi_d7; + u32 pad_csi_d8; + u32 pad_csi_d9; + u32 pad_csi_mclk; + u32 pad_csi_vsync; + u32 pad_csi_hsync; + u32 pad_csi_pixclk; + u32 pad_i2c1_clk; + u32 pad_i2c1_dat; + u32 pad_cspi1_mosi; + u32 pad_cspi1_miso; + u32 pad_cspi1_ss0; + u32 pad_cspi1_ss1; + u32 pad_cspi1_sclk; + u32 pad_cspi1_rdy; + u32 pad_uart1_rxd; + u32 pad_uart1_txd; + u32 pad_uart1_rts; + u32 pad_uart1_cts; + u32 pad_uart2_rxd; + u32 pad_uart2_txd; + u32 pad_uart2_rts; + u32 pad_uart2_cts; + u32 pad_sd1_cmd; + u32 pad_sd1_clk; + u32 pad_sd1_data0; + u32 pad_sd1_data1; + u32 pad_sd1_data2; + u32 pad_sd1_data3; + u32 pad_kpp_row0; + u32 pad_kpp_row1; + u32 pad_kpp_row2; + u32 pad_kpp_row3; + u32 pad_kpp_col0; + u32 pad_kpp_col1; + u32 pad_kpp_col2; + u32 pad_kpp_col3; + u32 pad_fec_mdc; + u32 pad_fec_mdio; + u32 pad_fec_tdata0; + u32 pad_fec_tdata1; + u32 pad_fec_tx_en; + u32 pad_fec_rdata0; + u32 pad_fec_rdata1; + u32 pad_fec_rx_dv; + u32 pad_fec_tx_clk; + u32 pad_rtck; + u32 pad_de_b; + u32 pad_gpio_a; + u32 pad_gpio_b; + u32 pad_gpio_c; + u32 pad_gpio_d; + u32 pad_gpio_e; + u32 pad_gpio_f; + u32 pad_ext_armclk; + u32 pad_upll_bypclk; + u32 pad_vstby_req; + u32 pad_vstby_ack; + u32 pad_power_fail; + u32 pad_clko; + u32 pad_boot_mode0; + u32 pad_boot_mode1; +}; + +/* + * software pad control + */ +/* Select 3.3 or 1.8 volts */ +#define MX25_PIN_PAD_CTL_DVS_33 (0 << 13) +#define MX25_PIN_PAD_CTL_DVS_18 (1 << 13) +/* Enable hysteresis */ +#define MX25_PIN_PAD_CTL_HYS (1 << 8) +/* Enable pull/keeper */ +#define MX25_PIN_PAD_CTL_PKE (1 << 7) +/* 0 - keeper / 1 - pull */ +#define MX25_PIN_PAD_CTL_PUE (1 << 6) +/* pull up/down strength */ +#define MX25_PIN_PAD_CTL_100K_PD (0 << 4) +#define MX25_PIN_PAD_CTL_47K_PU (1 << 4) +#define MX25_PIN_PAD_CTL_100K_PU (2 << 4) +#define MX25_PIN_PAD_CTL_22K_PU (3 << 4) +/* open drain control */ +#define MX25_PIN_PAD_CTL_OD (1 << 3) +/* drive strength */ +#define MX25_PIN_PAD_CTL_DS_NOM (0 << 1) +#define MX25_PIN_PAD_CTL_DS_HIGH (1 << 1) +#define MX25_PIN_PAD_CTL_DS_MAX (2 << 1) +#define MX25_PIN_PAD_CTL_DS_MAX11 (3 << 1) +/* slew rate */ +#define MX25_PIN_PAD_CTL_SRE_SLOW (0 << 0) +#define MX25_PIN_PAD_CTL_SRE_FAST (1 << 0) +struct iomuxc_pad_ctl { + u32 pad_a13; + u32 pad_a14; + u32 pad_a15; + u32 pad_a17; + u32 pad_a18; + u32 pad_a19; + u32 pad_a20; + u32 pad_a21; + u32 pad_a23; + u32 pad_a24; + u32 pad_a25; + u32 pad_eb0; + u32 pad_eb1; + u32 pad_oe; + u32 pad_cs4; + u32 pad_cs5; + u32 pad_nf_ce0; + u32 pad_ecb; + u32 pad_lba; + u32 pad_rw; + u32 pad_nfrb; + u32 pad_d15; + u32 pad_d14; + u32 pad_d13; + u32 pad_d12; + u32 pad_d11; + u32 pad_d10; + u32 pad_d9; + u32 pad_d8; + u32 pad_d7; + u32 pad_d6; + u32 pad_d5; + u32 pad_d4; + u32 pad_d3; + u32 pad_d2; + u32 pad_d1; + u32 pad_d0; + u32 pad_ld0; + u32 pad_ld1; + u32 pad_ld2; + u32 pad_ld3; + u32 pad_ld4; + u32 pad_ld5; + u32 pad_ld6; + u32 pad_ld7; + u32 pad_ld8; + u32 pad_ld9; + u32 pad_ld10; + u32 pad_ld11; + u32 pad_ld12; + u32 pad_ld13; + u32 pad_ld14; + u32 pad_ld15; + u32 pad_hsync; + u32 pad_vsync; + u32 pad_lsclk; + u32 pad_oe_acd; + u32 pad_contrast; + u32 pad_pwm; + u32 pad_csi_d2; + u32 pad_csi_d3; + u32 pad_csi_d4; + u32 pad_csi_d5; + u32 pad_csi_d6; + u32 pad_csi_d7; + u32 pad_csi_d8; + u32 pad_csi_d9; + u32 pad_csi_mclk; + u32 pad_csi_vsync; + u32 pad_csi_hsync; + u32 pad_csi_pixclk; + u32 pad_i2c1_clk; + u32 pad_i2c1_dat; + u32 pad_cspi1_mosi; + u32 pad_cspi1_miso; + u32 pad_cspi1_ss0; + u32 pad_cspi1_ss1; + u32 pad_cspi1_sclk; + u32 pad_cspi1_rdy; + u32 pad_uart1_rxd; + u32 pad_uart1_txd; + u32 pad_uart1_rts; + u32 pad_uart1_cts; + u32 pad_uart2_rxd; + u32 pad_uart2_txd; + u32 pad_uart2_rts; + u32 pad_uart2_cts; + u32 pad_sd1_cmd; + u32 pad_sd1_clk; + u32 pad_sd1_data0; + u32 pad_sd1_data1; + u32 pad_sd1_data2; + u32 pad_sd1_data3; + u32 pad_kpp_row0; + u32 pad_kpp_row1; + u32 pad_kpp_row2; + u32 pad_kpp_row3; + u32 pad_kpp_col0; + u32 pad_kpp_col1; + u32 pad_kpp_col2; + u32 pad_kpp_col3; + u32 pad_fec_mdc; + u32 pad_fec_mdio; + u32 pad_fec_tdata0; + u32 pad_fec_tdata1; + u32 pad_fec_tx_en; + u32 pad_fec_rdata0; + u32 pad_fec_rdata1; + u32 pad_fec_rx_dv; + u32 pad_fec_tx_clk; + u32 pad_rtck; + u32 pad_tdo; + u32 pad_de_b; + u32 pad_gpio_a; + u32 pad_gpio_b; + u32 pad_gpio_c; + u32 pad_gpio_d; + u32 pad_gpio_e; + u32 pad_gpio_f; + u32 pad_vstby_req; + u32 pad_vstby_ack; + u32 pad_power_fail; + u32 pad_clko; +}; + + +/* + * Pad group drive strength and voltage select + * Same fields as iomuxc_pad_ctl plus ddr type + */ +/* Select DDR type */ +#define MX25_PIN_PAD_CTL_DDR_18 (0 << 11) +#define MX25_PIN_PAD_CTL_DDR_33 (1 << 11) +#define MX25_PIN_PAD_CTL_DDR_MAX (2 << 11) +struct iomuxc_pad_grp_ctl { + u32 grp_dvs_misc; + u32 grp_dse_fec; + u32 grp_dvs_jtag; + u32 grp_dse_nfc; + u32 grp_dse_csi; + u32 grp_dse_weim; + u32 grp_dse_ddr; + u32 grp_dvs_crm; + u32 grp_dse_kpp; + u32 grp_dse_sdhc1; + u32 grp_dse_lcd; + u32 grp_dse_uart; + u32 grp_dvs_nfc; + u32 grp_dvs_csi; + u32 grp_dse_cspi1; + u32 grp_ddrtype; + u32 grp_dvs_sdhc1; + u32 grp_dvs_lcd; +}; + +/* + * Pad input select control + * Select which pad to connect to an input port + * where multiple pads can function as given input + */ +#define MX25_PAD_INPUT_SELECT_DAISY(in) ((in & 0x7) << 0) +struct iomuxc_pad_input_select { + u32 audmux_p4_input_da_amx; + u32 audmux_p4_input_db_amx; + u32 audmux_p4_input_rxclk_amx; + u32 audmux_p4_input_rxfs_amx; + u32 audmux_p4_input_txclk_amx; + u32 audmux_p4_input_txfs_amx; + u32 audmux_p7_input_da_amx; + u32 audmux_p7_input_txfs_amx; + u32 can1_ipp_ind_canrx; + u32 can2_ipp_ind_canrx; + u32 csi_ipp_csi_d_0; + u32 csi_ipp_csi_d_1; + u32 cspi1_ipp_ind_ss3_b; + u32 cspi2_ipp_cspi_clk_in; + u32 cspi2_ipp_ind_dataready_b; + u32 cspi2_ipp_ind_miso; + u32 cspi2_ipp_ind_mosi; + u32 cspi2_ipp_ind_ss0_b; + u32 cspi2_ipp_ind_ss1_b; + u32 cspi3_ipp_cspi_clk_in; + u32 cspi3_ipp_ind_dataready_b; + u32 cspi3_ipp_ind_miso; + u32 cspi3_ipp_ind_mosi; + u32 cspi3_ipp_ind_ss0_b; + u32 cspi3_ipp_ind_ss1_b; + u32 cspi3_ipp_ind_ss2_b; + u32 cspi3_ipp_ind_ss3_b; + u32 esdhc1_ipp_dat4_in; + u32 esdhc1_ipp_dat5_in; + u32 esdhc1_ipp_dat6_in; + u32 esdhc1_ipp_dat7_in; + u32 esdhc2_ipp_card_clk_in; + u32 esdhc2_ipp_cmd_in; + u32 esdhc2_ipp_dat0_in; + u32 esdhc2_ipp_dat1_in; + u32 esdhc2_ipp_dat2_in; + u32 esdhc2_ipp_dat3_in; + u32 esdhc2_ipp_dat4_in; + u32 esdhc2_ipp_dat5_in; + u32 esdhc2_ipp_dat6_in; + u32 esdhc2_ipp_dat7_in; + u32 fec_fec_col; + u32 fec_fec_crs; + u32 fec_fec_rdata_2; + u32 fec_fec_rdata_3; + u32 fec_fec_rx_clk; + u32 fec_fec_rx_er; + u32 i2c2_ipp_scl_in; + u32 i2c2_ipp_sda_in; + u32 i2c3_ipp_scl_in; + u32 i2c3_ipp_sda_in; + u32 kpp_ipp_ind_col_4; + u32 kpp_ipp_ind_col_5; + u32 kpp_ipp_ind_col_6; + u32 kpp_ipp_ind_col_7; + u32 kpp_ipp_ind_row_4; + u32 kpp_ipp_ind_row_5; + u32 kpp_ipp_ind_row_6; + u32 kpp_ipp_ind_row_7; + u32 sim1_pin_sim_rcvd1_in; + u32 sim1_pin_sim_simpd1; + u32 sim1_sim_rcvd1_io; + u32 sim2_pin_sim_rcvd1_in; + u32 sim2_pin_sim_simpd1; + u32 sim2_sim_rcvd1_io; + u32 uart3_ipp_uart_rts_b; + u32 uart3_ipp_uart_rxd_mux; + u32 uart4_ipp_uart_rts_b; + u32 uart4_ipp_uart_rxd_mux; + u32 uart5_ipp_uart_rts_b; + u32 uart5_ipp_uart_rxd_mux; + u32 usb_top_ipp_ind_otg_usb_oc; + u32 usb_top_ipp_ind_uh2_usb_oc; +};

Use RMII for MX25 Add code to init gasket that enables RMII
Signed-off-by: John Rigby jcrigby@gmail.com CC: Ben Warren biggerbadderben@gmail.com --- drivers/net/fec_mxc.c | 31 ++++++++++++++++++++++++++++++- drivers/net/fec_mxc.h | 32 ++++++++++++++++++++++++++++++-- include/asm-arm/arch-mx25/clock.h | 1 + 3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index b5619eb..f109485 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -347,6 +347,34 @@ static int fec_open(struct eth_device *edev) */ writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); +#ifdef CONFIG_MX25 + udelay(100); + /* + * setup the MII gasket for RMII mode + */ + + /* disable the gasket */ + writew(0, &fec->eth->miigsk_enr); + + /* wait for the gasket to be disabled */ + while (readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) + udelay(2); + + /* configure gasket for RMII, 50 MHz, no loopback, and no echo */ + writew(MIIGSK_CFGR_IF_MODE_RMII, &fec->eth->miigsk_cfgr); + + /* re-enable the gasket */ + writew(MIIGSK_ENR_EN, &fec->eth->miigsk_enr); + + /* wait until MII gasket is ready */ + int max_loops = 10; + while ((readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) == 0) { + if (--max_loops <= 0) { + printf("WAIT for MII Gasket ready timed out\n"); + break; + } + } +#endif
miiphy_wait_aneg(edev); miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); @@ -498,7 +526,8 @@ static void fec_halt(struct eth_device *dev) * Disable the Ethernet Controller * Note: this will also reset the BD index counter! */ - writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); + writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN, + &fec->eth->ecntrl); fec->rbd_index = 0; fec->tbd_index = 0; debug("eth_halt: done\n"); diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index 6cb1bfc..5d0d69d 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -145,9 +145,17 @@ struct ethernet_regs { uint32_t r_fdxfc; /* MBAR_ETH + 0x2DC */ uint32_t ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
- uint32_t res14[6]; /* MBAR_ETH + 0x2E4-2FC */ - + uint32_t res14[7]; /* MBAR_ETH + 0x2E4-2FC */ + +#ifdef CONFIG_MX25 + uint16_t miigsk_cfgr; /* MBAR_ETH + 0x300 */ + uint16_t res15[3]; /* MBAR_ETH + 0x302-306 */ + uint16_t miigsk_enr; /* MBAR_ETH + 0x308 */ + uint16_t res16[3]; /* MBAR_ETH + 0x30a-30e */ + uint32_t res17[60]; /* MBAR_ETH + 0x300-3FF */ +#else uint32_t res15[64]; /* MBAR_ETH + 0x300-3FF */ +#endif };
#define FEC_IEVENT_HBERR 0x80000000 @@ -196,6 +204,26 @@ struct ethernet_regs { #define FEC_ECNTRL_RESET 0x00000001 /* reset the FEC */ #define FEC_ECNTRL_ETHER_EN 0x00000002 /* enable the FEC */
+#ifdef CONFIG_MX25 +/* defines for MIIGSK */ +/* RMII frequency control: 0=50MHz, 1=5MHz */ +#define MIIGSK_CFGR_FRCONT (1 << 6) +/* loopback mode */ +#define MIIGSK_CFGR_LBMODE (1 << 4) +/* echo mode */ +#define MIIGSK_CFGR_EMODE (1 << 3) +/* MII gasket mode field */ +#define MIIGSK_CFGR_IF_MODE_MASK (3 << 0) +/* MMI/7-Wire mode */ +#define MIIGSK_CFGR_IF_MODE_MII (0 << 0) +/* RMII mode */ +#define MIIGSK_CFGR_IF_MODE_RMII (1 << 0) +/* reflects MIIGSK Enable bit (RO) */ +#define MIIGSK_ENR_READY (1 << 2) +/* enable MIGSK (set by default) */ +#define MIIGSK_ENR_EN (1 << 1) +#endif + /** * @brief Descriptor buffer alignment * diff --git a/include/asm-arm/arch-mx25/clock.h b/include/asm-arm/arch-mx25/clock.h index b0752e7..c59f588 100644 --- a/include/asm-arm/arch-mx25/clock.h +++ b/include/asm-arm/arch-mx25/clock.h @@ -30,6 +30,7 @@ ulong imx_get_perclk(int clk); ulong imx_get_ahbclk(void);
#define imx_get_uartclk() imx_get_perclk(15) +#define imx_get_fecclk() (imx_get_ahbclk()/2)
#endif /* __ASM_ARCH_CLOCK_H */

This is an i.MX25 base board with only NAND so it uses nand_spl to boot.
Signed-off-by: John Rigby jcrigby@gmail.com
Tune configuration, add support for (redundant) environment in NAND. Signed-off-by: Wolfgang Denk wd@denx.de
Acked-by: Wolfgang Denk wd@denx.de CC: Fred Fan fanyefeng@gmail.com CC: Tom Tom.Rix@windriver.com --- MAINTAINERS | 4 + Makefile | 4 + board/karo/tx25/Makefile | 51 ++++++++++ board/karo/tx25/config.mk | 5 + board/karo/tx25/lowlevel_init.S | 131 +++++++++++++++++++++++++ board/karo/tx25/tx25.c | 176 ++++++++++++++++++++++++++++++++++ include/configs/tx25.h | 179 +++++++++++++++++++++++++++++++++++ nand_spl/board/karo/tx25/Makefile | 78 +++++++++++++++ nand_spl/board/karo/tx25/config.mk | 1 + nand_spl/board/karo/tx25/u-boot.lds | 58 +++++++++++ 10 files changed, 687 insertions(+), 0 deletions(-) create mode 100644 board/karo/tx25/Makefile create mode 100644 board/karo/tx25/config.mk create mode 100644 board/karo/tx25/lowlevel_init.S create mode 100644 board/karo/tx25/tx25.c create mode 100644 include/configs/tx25.h create mode 100644 nand_spl/board/karo/tx25/Makefile create mode 100644 nand_spl/board/karo/tx25/config.mk create mode 100644 nand_spl/board/karo/tx25/u-boot.lds
diff --git a/MAINTAINERS b/MAINTAINERS index e8ba4bc..7dc6dfe 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -688,6 +688,10 @@ Tom Rix Tom.Rix@windriver.com
omap3_zoom2 ARM CORTEX-A8 (OMAP3xx SoC)
+John Rigby jcrigby@gmail.com + + tx25 i.MX25 + Stefan Roese sr@denx.de
ixdpg425 xscale diff --git a/Makefile b/Makefile index ed1a180..cab9168 100644 --- a/Makefile +++ b/Makefile @@ -3085,6 +3085,10 @@ trab_old_config: unconfig } @$(MKCONFIG) -a $(call xtract_trab,$@) arm arm920t trab NULL s3c24x0
+tx25_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm926ejs tx25 karo mx25 + @echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk + VCMA9_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm920t vcma9 mpl s3c24x0
diff --git a/board/karo/tx25/Makefile b/board/karo/tx25/Makefile new file mode 100644 index 0000000..b0e610f --- /dev/null +++ b/board/karo/tx25/Makefile @@ -0,0 +1,51 @@ +# +# (C) Copyright 2009 DENX Software Engineering +# Author: John Rigby jcrigby@gmail.com +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := tx25.o +SOBJS := lowlevel_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### + diff --git a/board/karo/tx25/config.mk b/board/karo/tx25/config.mk new file mode 100644 index 0000000..732a14a --- /dev/null +++ b/board/karo/tx25/config.mk @@ -0,0 +1,5 @@ +ifdef CONFIG_NAND_SPL +TEXT_BASE = 0x81ec0000 +else +TEXT_BASE = 0x81f00000 +endif diff --git a/board/karo/tx25/lowlevel_init.S b/board/karo/tx25/lowlevel_init.S new file mode 100644 index 0000000..823df10 --- /dev/null +++ b/board/karo/tx25/lowlevel_init.S @@ -0,0 +1,131 @@ +/* + * (C) Copyright 2009 DENX Software Engineering + * Author: John Rigby jrigby@gmail.com + * + * Based on U-Boot and RedBoot sources for several different i.mx + * platforms. + * + * 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 <asm/macro.h> + +.macro init_aips + write32 0x43f00000, 0x77777777 + write32 0x43f00004, 0x77777777 + write32 0x43f00000, 0x77777777 + write32 0x53f00004, 0x77777777 +.endm + +.macro init_max + write32 0x43f04000, 0x43210 + write32 0x43f04100, 0x43210 + write32 0x43f04200, 0x43210 + write32 0x43f04300, 0x43210 + write32 0x43f04400, 0x43210 + + write32 0x43f04010, 0x10 + write32 0x43f04110, 0x10 + write32 0x43f04210, 0x10 + write32 0x43f04310, 0x10 + write32 0x43f04410, 0x10 + + write32 0x43f04800, 0x0 + write32 0x43f04900, 0x0 + write32 0x43f04a00, 0x0 + write32 0x43f04b00, 0x0 + write32 0x43f04c00, 0x0 +.endm + +.macro init_m3if + write32 0xb8003000, 0x1 +.endm + +.macro init_clocks + /* + * clocks + * + * first enable CLKO debug output + * 0x40000000 enables the debug CLKO signal + * 0x05000000 sets CLKO divider to 6 + * 0x00600000 makes CLKO parent clk the USB clk + */ + write32 0x53f80064, 0x45600000 + write32 0x53f80008, 0x20034000 + + /* + * enable all implemented clocks in all three + * clock control registers + */ + write32 0x53f8000c, 0x1fffffff + write32 0x53f80010, 0xffffffff + write32 0x53f80014, 0xfdfff +.endm + +.macro init_ddrtype + /* + * ddr_type is 3.3v SDRAM + */ + write32 0x43fac454, 0x800 +.endm + +/* + * sdram controller init + */ +.macro init_sdram_bank bankaddr, ctl, cfg + ldr r0, =0xb8001000 + ldr r2, =\bankaddr + /* + * reset SDRAM controller + * then wait for initialization to complete + */ + ldr r1, =(1 << 1) + str r1, [r0, #0x10] +1: ldr r3, [r0, #0x10] + tst r3, #(1 << 31) + beq 1b + + ldr r1, =0x95728 + str r1, [r0, #\cfg] /* config */ + + ldr r1, =0x92116480 /* control | precharge */ + str r1, [r0, #\ctl] /* write command to controller */ + str r1, [r2, #0x400] /* command encoded in address */ + + ldr r1, =0xa2116480 /* auto refresh */ + str r1, [r0, #\ctl] + ldrb r3, [r2] /* read dram twice to auto refresh */ + ldrb r3, [r2] + + ldr r1, =0xb2116480 /* control | load mode */ + str r1, [r0, #\ctl] /* write command to controller */ + strb r1, [r2, #0x33] /* command encoded in address */ + + ldr r1, =0x82116480 /* control | normal (0)*/ + str r1, [r0, #\ctl] /* write command to controller */ +.endm + +.globl lowlevel_init +lowlevel_init: + init_aips + init_max + init_m3if + init_clocks + + init_sdram_bank 0x80000000, 0x0, 0x4 + + init_sdram_bank 0x90000000, 0x8, 0xc + mov pc, lr diff --git a/board/karo/tx25/tx25.c b/board/karo/tx25/tx25.c new file mode 100644 index 0000000..4d6a96d --- /dev/null +++ b/board/karo/tx25/tx25.c @@ -0,0 +1,176 @@ +/* + * (C) Copyright 2009 DENX Software Engineering + * Author: John Rigby jrigby@gmail.com + * + * Based on imx27lite.c: + * Copyright (C) 2008,2009 Eric Jarrige jorasse@users.sourceforge.net + * Copyright (C) 2009 Ilya Yanok yanok@emcraft.com + * And: + * RedBoot tx25_misc.c Copyright (C) 2009 Red Hat + * + * 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 <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/imx25-pinmux.h> + +static void mdelay(int n) +{ + while (n-- > 0) + udelay(1000); +} + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_FEC_MXC +void tx25_fec_init(void) +{ + struct iomuxc_mux_ctl *muxctl; + struct iomuxc_pad_ctl *padctl; + u32 val; + u32 gpio_mux_mode = MX25_PIN_MUX_MODE(5); + struct gpio_regs *gpio4 = (struct gpio_regs *)IMX_GPIO4_BASE; + struct gpio_regs *gpio3 = (struct gpio_regs *)IMX_GPIO3_BASE; + u32 saved_rdata0_mode, saved_rdata1_mode, saved_rx_dv_mode; + + debug("tx25_fec_init\n"); + /* + * fec pin init is generic + */ + mx25_fec_init_pins(); + + /* + * Set up the FEC_RESET_B and FEC_ENABLE GPIO pins. + * + * FEC_RESET_B: gpio4[7] is ALT 5 mode of pin D13 + * FEC_ENABLE_B: gpio4[9] is ALT 5 mode of pin D11 + */ + muxctl = (struct iomuxc_mux_ctl *)IMX_IOPADMUX_BASE; + padctl = (struct iomuxc_pad_ctl *)IMX_IOPADCTL_BASE; + + writel(gpio_mux_mode, &muxctl->pad_d13); + writel(gpio_mux_mode, &muxctl->pad_d11); + + writel(0x0, &padctl->pad_d13); + writel(0x0, &padctl->pad_d11); + + /* drop PHY power and assert reset (low) */ + val = readl(&gpio4->dr) & ~((1 << 7) | (1 << 9)); + writel(val, &gpio4->dr); + val = readl(&gpio4->dir) | (1 << 7) | (1 << 9); + writel(val, &gpio4->dir); + + mdelay(5); + + debug("resetting phy\n"); + + /* turn on PHY power leaving reset asserted */ + val = readl(&gpio4->dr) | 1 << 9; + writel(val, &gpio4->dr); + + mdelay(10); + + /* + * Setup some strapping pins that are latched by the PHY + * as reset goes high. + * + * Set PHY mode to 111 + * mode0 comes from FEC_RDATA0 which is GPIO 3_10 in mux mode 5 + * mode1 comes from FEC_RDATA1 which is GPIO 3_11 in mux mode 5 + * mode2 is tied high so nothing to do + * + * Turn on RMII mode + * RMII mode is selected by FEC_RX_DV which is GPIO 3_12 in mux mode + */ + /* + * save three current mux modes and set each to gpio mode + */ + saved_rdata0_mode = readl(&muxctl->pad_fec_rdata0); + saved_rdata1_mode = readl(&muxctl->pad_fec_rdata1); + saved_rx_dv_mode = readl(&muxctl->pad_fec_rx_dv); + + writel(gpio_mux_mode, &muxctl->pad_fec_rdata0); + writel(gpio_mux_mode, &muxctl->pad_fec_rdata1); + writel(gpio_mux_mode, &muxctl->pad_fec_rx_dv); + + /* + * set each to 1 and make each an output + */ + val = readl(&gpio3->dr) | (1 << 10) | (1 << 11) | (1 << 12); + writel(val, &gpio3->dr); + val = readl(&gpio3->dir) | (1 << 10) | (1 << 11) | (1 << 12); + writel(val, &gpio3->dir); + + mdelay(22); /* this value came from RedBoot */ + + /* + * deassert PHY reset + */ + val = readl(&gpio4->dr) | 1 << 7; + writel(val, &gpio4->dr); + writel(val, &gpio4->dr); + + mdelay(5); + + /* + * set FEC pins back + */ + writel(saved_rdata0_mode, &muxctl->pad_fec_rdata0); + writel(saved_rdata1_mode, &muxctl->pad_fec_rdata1); + writel(saved_rx_dv_mode, &muxctl->pad_fec_rx_dv); +} +#else +#define tx25_fec_init() +#endif + +int board_init() +{ +#ifdef CONFIG_MXC_UART + extern void mx25_uart_init_pins(void); + + mx25_uart_init_pins(); +#endif + return 0; +} + +int board_late_init(void) +{ + tx25_fec_init(); + return 0; +} + +int dram_init (void) +{ + + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = get_ram_size((volatile void *)PHYS_SDRAM_1, + PHYS_SDRAM_1_SIZE); +#if CONFIG_NR_DRAM_BANKS > 1 + gd->bd->bi_dram[1].start = PHYS_SDRAM_2; + gd->bd->bi_dram[1].size = get_ram_size((volatile void *)PHYS_SDRAM_2, + PHYS_SDRAM_2_SIZE); +#endif + + return 0; +} + +int checkboard(void) +{ + printf("KARO TX25\n"); + return 0; +} diff --git a/include/configs/tx25.h b/include/configs/tx25.h new file mode 100644 index 0000000..c8188ca --- /dev/null +++ b/include/configs/tx25.h @@ -0,0 +1,179 @@ +/* + * (C) Copyright 2009 DENX Software Engineering + * Author: John Rigby jrigby@gmail.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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + + +/* + * KARO TX25 board - SoC Configuration + */ +#define CONFIG_ARM926EJS /* arm926ejs CPU core */ +#define CONFIG_MX25 +#define CONFIG_TX25 +#define CONFIG_MX25_CLK32 32000 /* OSC32K frequency */ +#define CONFIG_SYS_HZ 1000 + +#define CONFIG_SYS_MONITOR_LEN (256 << 10) /* 256 kB for U-Boot */ + +/* NAND BOOT is the only boot method */ +#define CONFIG_NAND_U_BOOT + +#ifdef CONFIG_NAND_SPL +/* Start copying real U-boot from the second page */ +#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x800 +#define CONFIG_SYS_NAND_U_BOOT_SIZE 0x30000 +/* Load U-Boot to this address */ +#define CONFIG_SYS_NAND_U_BOOT_DST 0x81f00000 +#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_NAND_U_BOOT_DST + +#define CONFIG_SYS_NAND_PAGE_SIZE 2048 +#define CONFIG_SYS_NAND_SPARE_SIZE 64 +#define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024) +#define CONFIG_SYS_NAND_PAGE_COUNT 64 +#define CONFIG_SYS_NAND_SIZE (128 * 1024 * 1024) +#define CONFIG_SYS_NAND_BAD_BLOCK_POS 0 +#else +#define CONFIG_SKIP_LOWLEVEL_INIT +#define CONFIG_SKIP_RELOCATE_UBOOT +#endif + +#define CONFIG_DISPLAY_CPUINFO + +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_INITRD_TAG 1 + +/* + * Memory Info + */ +/* malloc() len */ +#define CONFIG_SYS_MALLOC_LEN (1 << 20) /* 1 MiB */ +/* reserved for initial data */ +#define CONFIG_SYS_GBL_DATA_SIZE 128 +/* + * Board has 2 32MB banks of DRAM but there is a bug when using + * both so only the first is configured + */ +#define CONFIG_NR_DRAM_BANKS 1 + +#define PHYS_SDRAM_1 0x80000000 +#define PHYS_SDRAM_1_SIZE 0x02000000 +#if (CONFIG_NR_DRAM_BANKS == 2) +#define PHYS_SDRAM_2 0x90000000 +#define PHYS_SDRAM_2_SIZE 0x02000000 +#endif +/* 8MB DRAM test */ +#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1 +#define CONFIG_SYS_MEMTEST_END (PHYS_SDRAM_1+0x0800000) +#define CONFIG_STACKSIZE (256 * 1024) /* regular stack */ + +/* + * Serial Info + */ +#define CONFIG_MXC_UART 1 +#define CONFIG_SYS_MX25_UART1 1 +#define CONFIG_CONS_INDEX 1 /* use UART0 for console */ +#define CONFIG_BAUDRATE 115200 /* Default baud rate */ +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +/* + * Flash & Environment + */ +/* No NOR flash present */ +#define CONFIG_SYS_NO_FLASH 1 +#define CONFIG_ENV_IS_IN_NAND +#define CONFIG_ENV_OFFSET CONFIG_SYS_MONITOR_LEN +#define CONFIG_ENV_SIZE (128 * 1024) /* 128 kB NAND block size */ +#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE) + +/* NAND */ +#define CONFIG_NAND_MXC +#define CONFIG_NAND_MXC_V1_1 +#define CONFIG_MXC_NAND_REGS_BASE (0xBB000000) +#define CONFIG_SYS_MAX_NAND_DEVICE 1 +#define CONFIG_SYS_NAND_BASE (0xBB000000) +#define CONFIG_JFFS2_NAND +#define CONFIG_MXC_NAND_HWECC +#define CONFIG_SYS_NAND_LARGEPAGE + +#define CONFIG_SYS_64BIT_VSPRINTF + +/* U-Boot general configuration */ +#define CONFIG_SYS_PROMPT "=> " /* Monitor Command Prompt */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */ +/* Print buffer sz */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_MAXARGS 32 /* max number of command args */ +/* Boot Argument Buffer Size */ +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE +#define CONFIG_CMDLINE_EDITING +#define CONFIG_SYS_LONGHELP + +/* U-Boot commands */ +#include <config_cmd_default.h> +#define CONFIG_CMD_NAND + +/* + * Ethernet + */ +#define CONFIG_FEC_MXC +#define CONFIG_FEC_MXC_PHYADDR 0x1f +#define CONFIG_MII +#define CONFIG_CMD_NET +#define CONFIG_NET_MULTI +#define BOARD_LATE_INIT +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_BOOTDELAY 5 + +#define CONFIG_LOADADDR 0x81000000 /* loadaddr env var */ +#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR + +#define xstr(s) str(s) +#define str(s) #s + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "netdev=eth0\0" \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=${serverip}:${rootpath}\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs ${bootargs} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \ + ":${hostname}:${netdev}:off panic=1\0" \ + "addtty=setenv bootargs ${bootargs}" \ + " console=ttymxc0,${baudrate}\0" \ + "addmtd=setenv bootargs ${bootargs} ${mtdparts}\0" \ + "addmisc=setenv bootargs ${bootargs}\0" \ + "u-boot=tx25/u-boot.bin\0" \ + "kernel_addr_r=" xstr(CONFIG_LOADADDR) "\0" \ + "hostname=tx25\0" \ + "bootfile=tx25/uImage\0" \ + "rootpath=/opt/eldk/arm\0" \ + "net_nfs=tftp ${kernel_addr_r} ${bootfile};" \ + "run nfsargs addip addtty addmtd addmisc;" \ + "bootm\0" \ + "bootcmd=run net_nfs\0" \ + "load=tftp ${loadaddr} ${u-boot}\0" \ + "update=nand erase 0 40000;nand write ${loadaddr} 0 40000\0" \ + "upd=run load update\0" \ + +#endif /* __CONFIG_H */ diff --git a/nand_spl/board/karo/tx25/Makefile b/nand_spl/board/karo/tx25/Makefile new file mode 100644 index 0000000..ae71f66 --- /dev/null +++ b/nand_spl/board/karo/tx25/Makefile @@ -0,0 +1,78 @@ +# +# (C) Copyright 2009 DENX Software Engineering +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 Foundatio; 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 +# +CONFIG_NAND_SPL = y + +include $(TOPDIR)/config.mk +include $(TOPDIR)/nand_spl/board/$(BOARDDIR)/config.mk + +LDSCRIPT= $(TOPDIR)/nand_spl/board/$(BOARDDIR)/u-boot.lds +LDFLAGS = -Bstatic -T $(nandobj)u-boot.lds -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS) +AFLAGS += -DCONFIG_PRELOADER -DCONFIG_NAND_SPL +CFLAGS += -DCONFIG_PRELOADER -DCONFIG_NAND_SPL + +SOBJS = start.o lowlevel_init.o +COBJS = nand_boot_fsl_nfc.o + +SRCS := $(SRCTREE)/nand_spl/nand_boot_fsl_nfc.c +SRCS += $(SRCTREE)/cpu/arm926ejs/start.S +SRCS += $(SRCTREE)/board/karo/tx25/lowlevel_init.S +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +__OBJS := $(SOBJS) $(COBJS) +LNDIR := $(OBJTREE)/nand_spl/board/$(BOARDDIR) + +nandobj := $(OBJTREE)/nand_spl/ + +ALL = $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin + +all: $(obj).depend $(ALL) + +$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl + $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $< $@ + +$(nandobj)u-boot-spl.bin: $(nandobj)u-boot-spl + $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ + +$(nandobj)u-boot-spl: $(OBJS) $(nandobj)u-boot.lds + cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) \ + -Map $(nandobj)u-boot-spl.map \ + -o $@ + +$(nandobj)u-boot.lds: $(LDSCRIPT) + $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@ + +######################################################################### + +$(obj)%.o: $(SRCTREE)/cpu/arm926ejs/%.S + $(CC) $(AFLAGS) -c -o $@ $< + +$(obj)%.o: $(SRCTREE)/board/karo/tx25/%.S + $(CC) $(AFLAGS) -c -o $@ $< + +$(obj)%.o: $(SRCTREE)/nand_spl/%.c + $(CC) $(CFLAGS) -c -o $@ $< + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/nand_spl/board/karo/tx25/config.mk b/nand_spl/board/karo/tx25/config.mk new file mode 100644 index 0000000..68afbf1 --- /dev/null +++ b/nand_spl/board/karo/tx25/config.mk @@ -0,0 +1 @@ +PAD_TO := 2048 diff --git a/nand_spl/board/karo/tx25/u-boot.lds b/nand_spl/board/karo/tx25/u-boot.lds new file mode 100644 index 0000000..423bed3 --- /dev/null +++ b/nand_spl/board/karo/tx25/u-boot.lds @@ -0,0 +1,58 @@ +/* + * (C) Copyright 2009 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + start.o (.text) + lowlevel_init.o (.text) + nand_boot_fsl_nfc.o (.text) + *(.text) + . = 2K; + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; +}

Hi John,
Why don't you use mxc_fec?
Actually, we use mxc_fec in mx25 u-boot.
Thanks~~
Yours Terry
-----Original Message----- From: u-boot-bounces@lists.denx.de [mailto:u-boot-bounces@lists.denx.de] On Behalf Of John Rigby Sent: 2010年1月26日 14:13 To: u-boot@lists.denx.de Cc: John Rigby; Ben Warren Subject: [U-Boot] [PATCH V3 7/8] fec_mxc: add MX25 support
Use RMII for MX25 Add code to init gasket that enables RMII
Signed-off-by: John Rigby jcrigby@gmail.com CC: Ben Warren biggerbadderben@gmail.com --- drivers/net/fec_mxc.c | 31 ++++++++++++++++++++++++++++++- drivers/net/fec_mxc.h | 32 ++++++++++++++++++++++++++++++-- include/asm-arm/arch-mx25/clock.h | 1 + 3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index b5619eb..f109485 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -347,6 +347,34 @@ static int fec_open(struct eth_device *edev) */ writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); +#ifdef CONFIG_MX25 + udelay(100); + /* + * setup the MII gasket for RMII mode + */ + + /* disable the gasket */ + writew(0, &fec->eth->miigsk_enr); + + /* wait for the gasket to be disabled */ + while (readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) + udelay(2); + + /* configure gasket for RMII, 50 MHz, no loopback, and no echo */ + writew(MIIGSK_CFGR_IF_MODE_RMII, &fec->eth->miigsk_cfgr); + + /* re-enable the gasket */ + writew(MIIGSK_ENR_EN, &fec->eth->miigsk_enr); + + /* wait until MII gasket is ready */ + int max_loops = 10; + while ((readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) == 0) { + if (--max_loops <= 0) { + printf("WAIT for MII Gasket ready timed out\n"); + break; + } + } +#endif
miiphy_wait_aneg(edev); miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); @@ -498,7 +526,8 @@ static void fec_halt(struct eth_device *dev) * Disable the Ethernet Controller * Note: this will also reset the BD index counter! */ - writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); + writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN, + &fec->eth->ecntrl); fec->rbd_index = 0; fec->tbd_index = 0; debug("eth_halt: done\n"); diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index 6cb1bfc..5d0d69d 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -145,9 +145,17 @@ struct ethernet_regs { uint32_t r_fdxfc; /* MBAR_ETH + 0x2DC */ uint32_t ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
- uint32_t res14[6]; /* MBAR_ETH + 0x2E4-2FC */ - + uint32_t res14[7]; /* MBAR_ETH + 0x2E4-2FC */ + +#ifdef CONFIG_MX25 + uint16_t miigsk_cfgr; /* MBAR_ETH + 0x300 */ + uint16_t res15[3]; /* MBAR_ETH + 0x302-306 */ + uint16_t miigsk_enr; /* MBAR_ETH + 0x308 */ + uint16_t res16[3]; /* MBAR_ETH + 0x30a-30e */ + uint32_t res17[60]; /* MBAR_ETH + 0x300-3FF */ +#else uint32_t res15[64]; /* MBAR_ETH + 0x300-3FF */ +#endif };
#define FEC_IEVENT_HBERR 0x80000000 @@ -196,6 +204,26 @@ struct ethernet_regs { #define FEC_ECNTRL_RESET 0x00000001 /* reset the FEC */ #define FEC_ECNTRL_ETHER_EN 0x00000002 /* enable the FEC */
+#ifdef CONFIG_MX25 +/* defines for MIIGSK */ +/* RMII frequency control: 0=50MHz, 1=5MHz */ +#define MIIGSK_CFGR_FRCONT (1 << 6) +/* loopback mode */ +#define MIIGSK_CFGR_LBMODE (1 << 4) +/* echo mode */ +#define MIIGSK_CFGR_EMODE (1 << 3) +/* MII gasket mode field */ +#define MIIGSK_CFGR_IF_MODE_MASK (3 << 0) +/* MMI/7-Wire mode */ +#define MIIGSK_CFGR_IF_MODE_MII (0 << 0) +/* RMII mode */ +#define MIIGSK_CFGR_IF_MODE_RMII (1 << 0) +/* reflects MIIGSK Enable bit (RO) */ +#define MIIGSK_ENR_READY (1 << 2) +/* enable MIGSK (set by default) */ +#define MIIGSK_ENR_EN (1 << 1) +#endif + /** * @brief Descriptor buffer alignment * diff --git a/include/asm-arm/arch-mx25/clock.h b/include/asm-arm/arch-mx25/clock.h index b0752e7..c59f588 100644 --- a/include/asm-arm/arch-mx25/clock.h +++ b/include/asm-arm/arch-mx25/clock.h @@ -30,6 +30,7 @@ ulong imx_get_perclk(int clk); ulong imx_get_ahbclk(void);
#define imx_get_uartclk() imx_get_perclk(15) +#define imx_get_fecclk() (imx_get_ahbclk()/2)
#endif /* __ASM_ARCH_CLOCK_H */ -- 1.6.4.2.236.gf324c
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Terry,
I don't see a mxc_fec driver in the u-boot repository, so I don't know what you are referring too. There is a fec_mxc driver which this patch modifies to add mx25:
$ git ls-files | grep fec cpu/mpc8220/fec.c cpu/mpc8220/fec.h cpu/mpc8220/fec_dma_tasks.S cpu/mpc8xx/fec.c cpu/mpc8xx/fec.h drivers/net/fec_mxc.c drivers/net/fec_mxc.h drivers/net/fsl_mcdmafec.c drivers/net/mcffec.c drivers/net/mpc512x_fec.c drivers/net/mpc512x_fec.h drivers/net/mpc5xxx_fec.c drivers/net/mpc5xxx_fec.h include/asm-m68k/fec.h include/asm-m68k/fsl_mcdmafec.h
Perhaps you are looking at a private Freescale repo?
John
2010/1/27 Lv Terry-R65388 r65388@freescale.com:
Hi John,
Why don't you use mxc_fec? Actually, we use mxc_fec in mx25 u-boot. Thanks~~
Yours Terry
-----Original Message----- From: u-boot-bounces@lists.denx.de [mailto:u-boot-bounces@lists.denx.de] On Behalf Of John Rigby Sent: 2010年1月26日 14:13 To: u-boot@lists.denx.de Cc: John Rigby; Ben Warren Subject: [U-Boot] [PATCH V3 7/8] fec_mxc: add MX25 support
Use RMII for MX25 Add code to init gasket that enables RMII
Signed-off-by: John Rigby jcrigby@gmail.com CC: Ben Warren biggerbadderben@gmail.com
drivers/net/fec_mxc.c | 31 ++++++++++++++++++++++++++++++- drivers/net/fec_mxc.h | 32 ++++++++++++++++++++++++++++++-- include/asm-arm/arch-mx25/clock.h | 1 + 3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index b5619eb..f109485 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -347,6 +347,34 @@ static int fec_open(struct eth_device *edev) */ writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); +#ifdef CONFIG_MX25
udelay(100);
/*
* setup the MII gasket for RMII mode
*/
/* disable the gasket */
writew(0, &fec->eth->miigsk_enr);
/* wait for the gasket to be disabled */
while (readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY)
udelay(2);
/* configure gasket for RMII, 50 MHz, no loopback, and no echo */
writew(MIIGSK_CFGR_IF_MODE_RMII, &fec->eth->miigsk_cfgr);
/* re-enable the gasket */
writew(MIIGSK_ENR_EN, &fec->eth->miigsk_enr);
/* wait until MII gasket is ready */
int max_loops = 10;
while ((readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) == 0) {
if (--max_loops <= 0) {
printf("WAIT for MII Gasket ready timed out\n");
break;
}
}
+#endif
miiphy_wait_aneg(edev); miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); @@ -498,7 +526,8 @@ static void fec_halt(struct eth_device *dev) * Disable the Ethernet Controller * Note: this will also reset the BD index counter! */
writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl);
writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN,
&fec->eth->ecntrl); fec->rbd_index = 0; fec->tbd_index = 0; debug("eth_halt: done\n");
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index 6cb1bfc..5d0d69d 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -145,9 +145,17 @@ struct ethernet_regs { uint32_t r_fdxfc; /* MBAR_ETH + 0x2DC */ uint32_t ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
uint32_t res14[6]; /* MBAR_ETH + 0x2E4-2FC */
uint32_t res14[7]; /* MBAR_ETH + 0x2E4-2FC */
+#ifdef CONFIG_MX25
uint16_t miigsk_cfgr; /* MBAR_ETH + 0x300 */
uint16_t res15[3]; /* MBAR_ETH + 0x302-306 */
uint16_t miigsk_enr; /* MBAR_ETH + 0x308 */
uint16_t res16[3]; /* MBAR_ETH + 0x30a-30e */
uint32_t res17[60]; /* MBAR_ETH + 0x300-3FF */
+#else uint32_t res15[64]; /* MBAR_ETH + 0x300-3FF */ +#endif };
#define FEC_IEVENT_HBERR 0x80000000 @@ -196,6 +204,26 @@ struct ethernet_regs { #define FEC_ECNTRL_RESET 0x00000001 /* reset the FEC */ #define FEC_ECNTRL_ETHER_EN 0x00000002 /* enable the FEC */
+#ifdef CONFIG_MX25 +/* defines for MIIGSK */ +/* RMII frequency control: 0=50MHz, 1=5MHz */ +#define MIIGSK_CFGR_FRCONT (1 << 6) +/* loopback mode */ +#define MIIGSK_CFGR_LBMODE (1 << 4) +/* echo mode */ +#define MIIGSK_CFGR_EMODE (1 << 3) +/* MII gasket mode field */ +#define MIIGSK_CFGR_IF_MODE_MASK (3 << 0) +/* MMI/7-Wire mode */ +#define MIIGSK_CFGR_IF_MODE_MII (0 << 0) +/* RMII mode */ +#define MIIGSK_CFGR_IF_MODE_RMII (1 << 0) +/* reflects MIIGSK Enable bit (RO) */ +#define MIIGSK_ENR_READY (1 << 2) +/* enable MIGSK (set by default) */ +#define MIIGSK_ENR_EN (1 << 1) +#endif
/**
- @brief Descriptor buffer alignment
diff --git a/include/asm-arm/arch-mx25/clock.h b/include/asm-arm/arch-mx25/clock.h index b0752e7..c59f588 100644 --- a/include/asm-arm/arch-mx25/clock.h +++ b/include/asm-arm/arch-mx25/clock.h @@ -30,6 +30,7 @@ ulong imx_get_perclk(int clk); ulong imx_get_ahbclk(void);
#define imx_get_uartclk() imx_get_perclk(15) +#define imx_get_fecclk() (imx_get_ahbclk()/2)
#endif /* __ASM_ARCH_CLOCK_H */
1.6.4.2.236.gf324c
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Tom,
As with the other one, I can't apply this by itself. Please apply to your tree.
John Rigby wrote:
Use RMII for MX25 Add code to init gasket that enables RMII
Signed-off-by: John Rigby jcrigby@gmail.com
Acked-by: Ben Warren biggerbadderben@gmail.com
drivers/net/fec_mxc.c | 31 ++++++++++++++++++++++++++++++- drivers/net/fec_mxc.h | 32 ++++++++++++++++++++++++++++++-- include/asm-arm/arch-mx25/clock.h | 1 + 3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index b5619eb..f109485 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -347,6 +347,34 @@ static int fec_open(struct eth_device *edev) */ writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); +#ifdef CONFIG_MX25
- udelay(100);
- /*
* setup the MII gasket for RMII mode
*/
- /* disable the gasket */
- writew(0, &fec->eth->miigsk_enr);
- /* wait for the gasket to be disabled */
- while (readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY)
udelay(2);
- /* configure gasket for RMII, 50 MHz, no loopback, and no echo */
- writew(MIIGSK_CFGR_IF_MODE_RMII, &fec->eth->miigsk_cfgr);
- /* re-enable the gasket */
- writew(MIIGSK_ENR_EN, &fec->eth->miigsk_enr);
- /* wait until MII gasket is ready */
- int max_loops = 10;
- while ((readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) == 0) {
if (--max_loops <= 0) {
printf("WAIT for MII Gasket ready timed out\n");
break;
}
- }
+#endif
miiphy_wait_aneg(edev); miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); @@ -498,7 +526,8 @@ static void fec_halt(struct eth_device *dev) * Disable the Ethernet Controller * Note: this will also reset the BD index counter! */
- writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl);
- writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN,
fec->rbd_index = 0; fec->tbd_index = 0; debug("eth_halt: done\n");&fec->eth->ecntrl);
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index 6cb1bfc..5d0d69d 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -145,9 +145,17 @@ struct ethernet_regs { uint32_t r_fdxfc; /* MBAR_ETH + 0x2DC */ uint32_t ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
- uint32_t res14[6]; /* MBAR_ETH + 0x2E4-2FC */
- uint32_t res14[7]; /* MBAR_ETH + 0x2E4-2FC */
+#ifdef CONFIG_MX25
- uint16_t miigsk_cfgr; /* MBAR_ETH + 0x300 */
- uint16_t res15[3]; /* MBAR_ETH + 0x302-306 */
- uint16_t miigsk_enr; /* MBAR_ETH + 0x308 */
- uint16_t res16[3]; /* MBAR_ETH + 0x30a-30e */
- uint32_t res17[60]; /* MBAR_ETH + 0x300-3FF */
+#else uint32_t res15[64]; /* MBAR_ETH + 0x300-3FF */ +#endif };
#define FEC_IEVENT_HBERR 0x80000000 @@ -196,6 +204,26 @@ struct ethernet_regs { #define FEC_ECNTRL_RESET 0x00000001 /* reset the FEC */ #define FEC_ECNTRL_ETHER_EN 0x00000002 /* enable the FEC */
+#ifdef CONFIG_MX25 +/* defines for MIIGSK */ +/* RMII frequency control: 0=50MHz, 1=5MHz */ +#define MIIGSK_CFGR_FRCONT (1 << 6) +/* loopback mode */ +#define MIIGSK_CFGR_LBMODE (1 << 4) +/* echo mode */ +#define MIIGSK_CFGR_EMODE (1 << 3) +/* MII gasket mode field */ +#define MIIGSK_CFGR_IF_MODE_MASK (3 << 0) +/* MMI/7-Wire mode */ +#define MIIGSK_CFGR_IF_MODE_MII (0 << 0) +/* RMII mode */ +#define MIIGSK_CFGR_IF_MODE_RMII (1 << 0) +/* reflects MIIGSK Enable bit (RO) */ +#define MIIGSK_ENR_READY (1 << 2) +/* enable MIGSK (set by default) */ +#define MIIGSK_ENR_EN (1 << 1) +#endif
/**
- @brief Descriptor buffer alignment
diff --git a/include/asm-arm/arch-mx25/clock.h b/include/asm-arm/arch-mx25/clock.h index b0752e7..c59f588 100644 --- a/include/asm-arm/arch-mx25/clock.h +++ b/include/asm-arm/arch-mx25/clock.h @@ -30,6 +30,7 @@ ulong imx_get_perclk(int clk); ulong imx_get_ahbclk(void);
#define imx_get_uartclk() imx_get_perclk(15) +#define imx_get_fecclk() (imx_get_ahbclk()/2)
#endif /* __ASM_ARCH_CLOCK_H */
regards, Ben

Hi John,
I think it is better that you can add a new config, e.g. CONFIG_MIIGSK for MII gasket. Then if other i.MX platforms uses MIIGSK, we can use the config for it.
Thanks~~
Yours Terry
-----Original Message----- From: u-boot-bounces@lists.denx.de [mailto:u-boot-bounces@lists.denx.de] On Behalf Of John Rigby Sent: 2010年1月26日 14:13 To: u-boot@lists.denx.de Cc: John Rigby; Ben Warren Subject: [U-Boot] [PATCH V3 7/8] fec_mxc: add MX25 support
Use RMII for MX25 Add code to init gasket that enables RMII
Signed-off-by: John Rigby jcrigby@gmail.com CC: Ben Warren biggerbadderben@gmail.com --- drivers/net/fec_mxc.c | 31 ++++++++++++++++++++++++++++++- drivers/net/fec_mxc.h | 32 ++++++++++++++++++++++++++++++-- include/asm-arm/arch-mx25/clock.h | 1 + 3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index b5619eb..f109485 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -347,6 +347,34 @@ static int fec_open(struct eth_device *edev) */ writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); +#ifdef CONFIG_MX25 + udelay(100); + /* + * setup the MII gasket for RMII mode + */ + + /* disable the gasket */ + writew(0, &fec->eth->miigsk_enr); + + /* wait for the gasket to be disabled */ + while (readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) + udelay(2); + + /* configure gasket for RMII, 50 MHz, no loopback, and no echo */ + writew(MIIGSK_CFGR_IF_MODE_RMII, &fec->eth->miigsk_cfgr); + + /* re-enable the gasket */ + writew(MIIGSK_ENR_EN, &fec->eth->miigsk_enr); + + /* wait until MII gasket is ready */ + int max_loops = 10; + while ((readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) == 0) { + if (--max_loops <= 0) { + printf("WAIT for MII Gasket ready timed out\n"); + break; + } + } +#endif
miiphy_wait_aneg(edev); miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); @@ -498,7 +526,8 @@ static void fec_halt(struct eth_device *dev) * Disable the Ethernet Controller * Note: this will also reset the BD index counter! */ - writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); + writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN, + &fec->eth->ecntrl); fec->rbd_index = 0; fec->tbd_index = 0; debug("eth_halt: done\n"); diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index 6cb1bfc..5d0d69d 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -145,9 +145,17 @@ struct ethernet_regs { uint32_t r_fdxfc; /* MBAR_ETH + 0x2DC */ uint32_t ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
- uint32_t res14[6]; /* MBAR_ETH + 0x2E4-2FC */ - + uint32_t res14[7]; /* MBAR_ETH + 0x2E4-2FC */ + +#ifdef CONFIG_MX25 + uint16_t miigsk_cfgr; /* MBAR_ETH + 0x300 */ + uint16_t res15[3]; /* MBAR_ETH + 0x302-306 */ + uint16_t miigsk_enr; /* MBAR_ETH + 0x308 */ + uint16_t res16[3]; /* MBAR_ETH + 0x30a-30e */ + uint32_t res17[60]; /* MBAR_ETH + 0x300-3FF */ +#else uint32_t res15[64]; /* MBAR_ETH + 0x300-3FF */ +#endif };
#define FEC_IEVENT_HBERR 0x80000000 @@ -196,6 +204,26 @@ struct ethernet_regs { #define FEC_ECNTRL_RESET 0x00000001 /* reset the FEC */ #define FEC_ECNTRL_ETHER_EN 0x00000002 /* enable the FEC */
+#ifdef CONFIG_MX25 +/* defines for MIIGSK */ +/* RMII frequency control: 0=50MHz, 1=5MHz */ +#define MIIGSK_CFGR_FRCONT (1 << 6) +/* loopback mode */ +#define MIIGSK_CFGR_LBMODE (1 << 4) +/* echo mode */ +#define MIIGSK_CFGR_EMODE (1 << 3) +/* MII gasket mode field */ +#define MIIGSK_CFGR_IF_MODE_MASK (3 << 0) +/* MMI/7-Wire mode */ +#define MIIGSK_CFGR_IF_MODE_MII (0 << 0) +/* RMII mode */ +#define MIIGSK_CFGR_IF_MODE_RMII (1 << 0) +/* reflects MIIGSK Enable bit (RO) */ +#define MIIGSK_ENR_READY (1 << 2) +/* enable MIGSK (set by default) */ +#define MIIGSK_ENR_EN (1 << 1) +#endif + /** * @brief Descriptor buffer alignment * diff --git a/include/asm-arm/arch-mx25/clock.h b/include/asm-arm/arch-mx25/clock.h index b0752e7..c59f588 100644 --- a/include/asm-arm/arch-mx25/clock.h +++ b/include/asm-arm/arch-mx25/clock.h @@ -30,6 +30,7 @@ ulong imx_get_perclk(int clk); ulong imx_get_ahbclk(void);
#define imx_get_uartclk() imx_get_perclk(15) +#define imx_get_fecclk() (imx_get_ahbclk()/2)
#endif /* __ASM_ARCH_CLOCK_H */ -- 1.6.4.2.236.gf324c
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

I think that is a good idea but I would like to get the current change in as is and add this change later when needed.
2010/3/2 Lv Terry-R65388 r65388@freescale.com
Hi John,
I think it is better that you can add a new config, e.g.
CONFIG_MIIGSK for MII gasket. Then if other i.MX platforms uses MIIGSK, we can use the config for it.
Thanks~~
Yours Terry
-----Original Message----- From: u-boot-bounces@lists.denx.de [mailto:u-boot-bounces@lists.denx.de] On Behalf Of John Rigby Sent: 2010年1月26日 14:13 To: u-boot@lists.denx.de Cc: John Rigby; Ben Warren Subject: [U-Boot] [PATCH V3 7/8] fec_mxc: add MX25 support
Use RMII for MX25 Add code to init gasket that enables RMII
Signed-off-by: John Rigby jcrigby@gmail.com CC: Ben Warren biggerbadderben@gmail.com
drivers/net/fec_mxc.c | 31 ++++++++++++++++++++++++++++++- drivers/net/fec_mxc.h | 32 ++++++++++++++++++++++++++++++-- include/asm-arm/arch-mx25/clock.h | 1 + 3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index b5619eb..f109485 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -347,6 +347,34 @@ static int fec_open(struct eth_device *edev) */ writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); +#ifdef CONFIG_MX25
udelay(100);
/*
* setup the MII gasket for RMII mode
*/
/* disable the gasket */
writew(0, &fec->eth->miigsk_enr);
/* wait for the gasket to be disabled */
while (readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY)
udelay(2);
/* configure gasket for RMII, 50 MHz, no loopback, and no echo */
writew(MIIGSK_CFGR_IF_MODE_RMII, &fec->eth->miigsk_cfgr);
/* re-enable the gasket */
writew(MIIGSK_ENR_EN, &fec->eth->miigsk_enr);
/* wait until MII gasket is ready */
int max_loops = 10;
while ((readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) == 0) {
if (--max_loops <= 0) {
printf("WAIT for MII Gasket ready timed out\n");
break;
}
}
+#endif
miiphy_wait_aneg(edev); miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); @@ -498,7 +526,8
@@ static void fec_halt(struct eth_device *dev) * Disable the Ethernet Controller * Note: this will also reset the BD index counter! */
writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN,
&fec->eth->ecntrl);
writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN,
&fec->eth->ecntrl); fec->rbd_index = 0; fec->tbd_index = 0; debug("eth_halt: done\n");
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index 6cb1bfc..5d0d69d 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -145,9 +145,17 @@ struct ethernet_regs { uint32_t r_fdxfc; /* MBAR_ETH + 0x2DC */ uint32_t ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
uint32_t res14[6]; /* MBAR_ETH + 0x2E4-2FC */
uint32_t res14[7]; /* MBAR_ETH + 0x2E4-2FC */
+#ifdef CONFIG_MX25
uint16_t miigsk_cfgr; /* MBAR_ETH + 0x300 */
uint16_t res15[3]; /* MBAR_ETH + 0x302-306 */
uint16_t miigsk_enr; /* MBAR_ETH + 0x308 */
uint16_t res16[3]; /* MBAR_ETH + 0x30a-30e */
uint32_t res17[60]; /* MBAR_ETH + 0x300-3FF */
+#else uint32_t res15[64]; /* MBAR_ETH + 0x300-3FF */ +#endif };
#define FEC_IEVENT_HBERR 0x80000000 @@ -196,6 +204,26 @@ struct ethernet_regs { #define FEC_ECNTRL_RESET 0x00000001 /* reset the FEC */ #define FEC_ECNTRL_ETHER_EN 0x00000002 /* enable the FEC */
+#ifdef CONFIG_MX25 +/* defines for MIIGSK */ +/* RMII frequency control: 0=50MHz, 1=5MHz */ +#define MIIGSK_CFGR_FRCONT (1 << 6) +/* loopback mode */ +#define MIIGSK_CFGR_LBMODE (1 << 4) +/* echo mode */ +#define MIIGSK_CFGR_EMODE (1 << 3) +/* MII gasket mode field */ +#define MIIGSK_CFGR_IF_MODE_MASK (3 << 0) +/* MMI/7-Wire mode */ +#define MIIGSK_CFGR_IF_MODE_MII (0 << 0) +/* RMII mode */ +#define MIIGSK_CFGR_IF_MODE_RMII (1 << 0) +/* reflects MIIGSK Enable bit (RO) */ +#define MIIGSK_ENR_READY (1 << 2) +/* enable MIGSK (set by default) */ +#define MIIGSK_ENR_EN (1 << 1) +#endif
/**
- @brief Descriptor buffer alignment
diff --git a/include/asm-arm/arch-mx25/clock.h b/include/asm-arm/arch-mx25/clock.h index b0752e7..c59f588 100644 --- a/include/asm-arm/arch-mx25/clock.h +++ b/include/asm-arm/arch-mx25/clock.h @@ -30,6 +30,7 @@ ulong imx_get_perclk(int clk); ulong imx_get_ahbclk(void);
#define imx_get_uartclk() imx_get_perclk(15) +#define imx_get_fecclk() (imx_get_ahbclk()/2)
#endif /* __ASM_ARCH_CLOCK_H */
1.6.4.2.236.gf324c
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Tom,
I can't apply this independently of the other patches in this set. Please do so.
John Rigby wrote:
general cleanup move clock init to cpu_eth_init in cpu/arm926ejs/mx27/generic.c make MX27 specific phy init conditional on CONFIG_MX27 replace call to imx_get_ahbclk with one to imx_get_fecclk and define imx_get_fecclk in include/asm-arm/arch-mx27/clock.h
Signed-off-by: John Rigby jcrigby@gmail.com CC: Fred Fan fanyefeng@gmail.com CC: Tom Tom.Rix@windriver.com
Acked-by: Ben Warren biggerbadderben@gmail.com
cpu/arm926ejs/mx27/generic.c | 5 +++++ drivers/net/fec_mxc.c | 28 +++++++++++++--------------- include/asm-arm/arch-mx27/clock.h | 1 + 3 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/cpu/arm926ejs/mx27/generic.c b/cpu/arm926ejs/mx27/generic.c index da05c55..30cf544 100644 --- a/cpu/arm926ejs/mx27/generic.c +++ b/cpu/arm926ejs/mx27/generic.c @@ -166,6 +166,11 @@ int print_cpuinfo (void) int cpu_eth_init(bd_t *bis) { #if defined(CONFIG_FEC_MXC)
- struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
- /* enable FEC clock */
- writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1);
- writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0); return fecmxc_initialize(bis);
#else return 0; diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 19116f2..b5619eb 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -151,7 +151,9 @@ static int miiphy_restart_aneg(struct eth_device *dev) * Wake up from sleep if necessary * Reset PHY, then delay 300ns */ +#ifdef CONFIG_MX27 miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_MIPGSR, 0x00FF); +#endif miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, PHY_BMCR, PHY_BMCR_RESET); udelay(1000); @@ -343,7 +345,8 @@ static int fec_open(struct eth_device *edev) /* * Enable FEC-Lite controller */
- writel(FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl);
writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN,
&fec->eth->ecntrl);
miiphy_wait_aneg(edev); miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR);
@@ -415,10 +418,10 @@ static int fec_init(struct eth_device *dev, bd_t* bd) * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock * and do not drop the Preamble. */
writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1,
debug("fec_init: mii_speed %#lx\n",writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1, &fec->eth->mii_speed);
(((imx_get_ahbclk() / 1000000) + 2) / 5) << 1);
} /*(((imx_get_fecclk() / 1000000) + 2) / 5) << 1);
- Set Opcode/Pause Duration Register
@@ -475,7 +478,7 @@ static void fec_halt(struct eth_device *dev) /* * issue graceful stop command to the FEC transmitter if necessary */
- writel(FEC_ECNTRL_RESET | readl(&fec->eth->x_cntrl),
writel(FEC_TCNTRL_GTS | readl(&fec->eth->x_cntrl), &fec->eth->x_cntrl);
debug("eth_halt: wait for stop regs\n");
@@ -483,7 +486,7 @@ static void fec_halt(struct eth_device *dev) * wait for graceful stop to register */ while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA)))
; /* FIXME ensure time */
udelay(1);
/*
- Disable SmartDMA tasks
@@ -495,7 +498,7 @@ static void fec_halt(struct eth_device *dev) * Disable the Ethernet Controller * Note: this will also reset the BD index counter! */
- writel(0, &fec->eth->ecntrl);
- writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN, &fec->eth->ecntrl); fec->rbd_index = 0; fec->tbd_index = 0; debug("eth_halt: done\n");
@@ -554,7 +557,7 @@ static int fec_send(struct eth_device *dev, volatile void* packet, int length) * wait until frame is sent . */ while (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY) {
/* FIXME: Timeout */
} debug("fec_send: status 0x%x index %d\n", readw(&fec->tbd_base[fec->tbd_index].status),udelay(1);
@@ -651,7 +654,6 @@ static int fec_recv(struct eth_device *dev)
static int fec_probe(bd_t *bd) {
- struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; struct eth_device *edev; struct fec_priv *fec = &gfec; unsigned char ethaddr_str[20];
@@ -659,10 +661,6 @@ static int fec_probe(bd_t *bd) char *tmp = getenv("ethaddr"); char *end;
- /* enable FEC clock */
- writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1);
- writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0);
- /* create and fill edev struct */ edev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!edev) {
@@ -681,7 +679,7 @@ static int fec_probe(bd_t *bd) fec->xcv_type = MII100;
/* Reset chip. */
- writel(FEC_ECNTRL_RESET, &fec->eth->ecntrl);
- writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl); while (readl(&fec->eth->ecntrl) & 1) udelay(10);
@@ -706,10 +704,10 @@ static int fec_probe(bd_t *bd) * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock * and do not drop the Preamble. */
- writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1,
- writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1, &fec->eth->mii_speed); debug("fec_init: mii_speed %#lx\n",
(((imx_get_ahbclk() / 1000000) + 2) / 5) << 1);
(((imx_get_fecclk() / 1000000) + 2) / 5) << 1);
sprintf(edev->name, "FEC_MXC");
diff --git a/include/asm-arm/arch-mx27/clock.h b/include/asm-arm/arch-mx27/clock.h index 472e8f2..7e9c7aa 100644 --- a/include/asm-arm/arch-mx27/clock.h +++ b/include/asm-arm/arch-mx27/clock.h @@ -37,5 +37,6 @@ ulong imx_get_perclk3(void); ulong imx_get_ahbclk(void);
#define imx_get_uartclk imx_get_perclk1 +#define imx_get_fecclk imx_get_ahbclk
#endif /* __ASM_ARCH_CLOCK_H */
regards, Ben

On Mon, Jan 25, 2010 at 11:12:54PM -0700, John Rigby wrote:
Add support for version 1.1 of the nfc nand flash controller which is on the i.mx25 soc.
Signed-off-by: John Rigby jcrigby@gmail.com CC: Scott Wood scottwood@freescale.com
drivers/mtd/nand/mxc_nand.c | 617 ++++++++++++++++++++++++++++++++++++++----- 1 files changed, 545 insertions(+), 72 deletions(-)
Configuring for mx31pdk board... mxc_nand.c:25:31: error: asm/arch/imx-regs.h: No such file or directory
-Scott

On Mon, Jan 25, 2010 at 11:12:53PM -0700, John Rigby wrote:
MX25 has a different version of the fsl_nfc flash controller known as version 1.1.
Add support to the nand_spl fsl_nfc driver keyed off CONFIG_NAND_NFC_V1_1.
Also add a define CONFIG_NAND_NFC_V1 to the only existing user configs/mx31pdk.h.
Versioning differs from mainline mxc kernel driver no consensus yet on if the naming here and in Redboot or the kernel is "correct".
Signed-off-by: John Rigby jcrigby@gmail.com Signed-off-by: Wolfgang Denk wd@denx.de CC: Scott Wood scottwood@freescale.com
$ CROSS_COMPILE=arm-linux- ./MAKEALL mx31pdk_nand Configuring for mx31pdk board... In file included from /home/scott/git/u-boot/nand/nand_spl/nand_boot_fsl_nfc.c:35: /home/scott/git/u-boot/nand/include/fsl_nfc.h:56:2: error: #error "define CONFIG_NAND_MXC_VXXX to use the mxc spl_nand driver"
-Scott

I'll send updates for both of these tonight.
On Tue, Jan 26, 2010 at 1:05 PM, Scott Wood scottwood@freescale.com wrote:
On Mon, Jan 25, 2010 at 11:12:53PM -0700, John Rigby wrote:
MX25 has a different version of the fsl_nfc flash controller known as version 1.1.
Add support to the nand_spl fsl_nfc driver keyed off CONFIG_NAND_NFC_V1_1.
Also add a define CONFIG_NAND_NFC_V1 to the only existing user configs/mx31pdk.h.
Versioning differs from mainline mxc kernel driver no consensus yet on if the naming here and in Redboot or the kernel is "correct".
Signed-off-by: John Rigby jcrigby@gmail.com Signed-off-by: Wolfgang Denk wd@denx.de CC: Scott Wood scottwood@freescale.com
$ CROSS_COMPILE=arm-linux- ./MAKEALL mx31pdk_nand Configuring for mx31pdk board... In file included from /home/scott/git/u-boot/nand/nand_spl/nand_boot_fsl_nfc.c:35: /home/scott/git/u-boot/nand/include/fsl_nfc.h:56:2: error: #error "define CONFIG_NAND_MXC_VXXX to use the mxc spl_nand driver"
-Scott
participants (4)
-
Ben Warren
-
John Rigby
-
Lv Terry-R65388
-
Scott Wood