--- uboot-imx-2009.01.orig/debian/docs +++ uboot-imx-2009.01/debian/docs @@ -0,0 +1,3 @@ +README +README.nios_CONFIG_SYS_NIOS_CPU +CHANGELOG-before-U-Boot-1.1.5 --- uboot-imx-2009.01.orig/debian/changelog +++ uboot-imx-2009.01/debian/changelog @@ -0,0 +1,5 @@ +uboot-imx (2009.01-0ubuntu1) karmic; urgency=low + + * Initial release (LP: #398785) + + -- Michael Casadevall Thu, 09 Jul 2009 10:31:28 -0400 --- uboot-imx-2009.01.orig/debian/compat +++ uboot-imx-2009.01/debian/compat @@ -0,0 +1 @@ +7 --- uboot-imx-2009.01.orig/debian/copyright +++ uboot-imx-2009.01/debian/copyright @@ -0,0 +1,73 @@ +This package was debianized by: + + Michael Casadevall on Thu, 09 Jul 2009 10:31:28 -0400 + +It was provided by Freescale Semiconditors. The base u-boot source was +downloaded from: http://www.denx.de/wiki/U-Boot + +Major Copyright Holders: + Copyright (C) 2000-2009 Wolfgang Denk, DENX Software Engineering, wd@denx.de. + Copyright (C) 2007-2009 Freescale Semiconditors, Inc + +For a complete list, see the CREDITS file for everyone who has ever contributed +to uboot-imx + +License: + + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + This package 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 package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +The YAFFS2 filesystem included as part of u-boot is licensed under the +LGPL 2.1 + + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version + 2.1 as published by the Free Software Foundation. + + This package 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 LesserGeneral Public License + along with this package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Parts of this package are licensed under the BSD 3-clause license: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +On Debian and Ubuntu systems, the complete test of the BSD 3-clause license +can be found in '/usr/share/common-licenes/BSD'. + +On Debian and Ubuntu systems, the complete text of the GNU General +Public License version 2 can be found in `/usr/share/common-licenses/GPL-2'. + +On Debian and Ubuntu systems, the complete text of the GNU Lesser General +Public License version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'. + +The Debian packaging is: + + Copyright (C) 2009 Michael Casadevall + +and is licensed under the GPL version 2, see `/usr/share/common-licenses/GPL-2'. --- uboot-imx-2009.01.orig/debian/rules +++ uboot-imx-2009.01/debian/rules @@ -0,0 +1,31 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +include /usr/share/cdbs/1/rules/debhelper.mk +include /usr/share/cdbs/1/rules/simple-patchsys.mk + +# Disbale default LDFLAGS/CFLAGS for uboot +LDFLAGS= +CFLAGS= + +build/uboot-imx51-to2:: + $(MAKE) O=build/build-imx51 imx51_config + $(MAKE) O=build/build-imx51 + + touch $@ + +install/uboot-imx51-to2:: + install -D build/build-imx51/u-boot.bin debian/uboot-imx51-to2/usr/lib/uboot/uboot-imx51_to2.bin + install -D debian/uboot-imx51-to2.lintian-overrides debian/uboot-imx51-to2/usr/share/lintian/overrides/uboot-imx51-to2 + +clean:: + rm -rf build + +get-orig-source: + cd $(CURDIR)/.. && \ + wget ftp://ftp.denx.de/pub/u-boot/u-boot-2009.01.tar.bz2 && \ + echo "Recompressing the bz2 as a gzip ..." && \ + bunzip2 u-boot-2009.01.tar.bz2 && \ + gzip -9 u-boot-2009.01.tar && \ + mv u-boot-2009.01.tar.gz uboot-imx_2009.01.orig.tar.gz + --- uboot-imx-2009.01.orig/debian/control +++ uboot-imx-2009.01/debian/control @@ -0,0 +1,16 @@ +Source: uboot-imx +Section: admin +Priority: extra +Maintainer: Michael Casadevall +Build-Depends: cdbs, debhelper (>= 7) +Standards-Version: 3.8.2 +Homepage: http://freescale.com + +Package: uboot-imx51-to2 +Architecture: armel +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Das U-Boot bootloader configured for iMX51 Babbage TO2 + This package contains the Das U-Boot bootloader for the Babbage TO2, + which is responsible for loading and executing the Linux kernel on those + boards. This package contains the u-boot binary blob, and is not usually + needed on a normal system --- uboot-imx-2009.01.orig/debian/uboot-imx51-to2.lintian-overrides +++ uboot-imx-2009.01/debian/uboot-imx51-to2.lintian-overrides @@ -0,0 +1,2 @@ +# u-boot binaries are binary blobs +uboot-imx51-to2 binary: executable-not-elf-or-script --- uboot-imx-2009.01.orig/debian/patches/0005-ENGR00102776-Support-boot-from-NAND-on-i.mx35-3stack.patch +++ uboot-imx-2009.01/debian/patches/0005-ENGR00102776-Support-boot-from-NAND-on-i.mx35-3stack.patch @@ -0,0 +1,485 @@ +From 38107a4d85c8e53bde8bb873ec67e8b4a969899d Mon Sep 17 00:00:00 2001 +From: Fred Fan +Date: Mon, 23 Feb 2009 13:54:46 +0800 +Subject: [PATCH] ENGR00102776 Support boot from NAND on i.mx35 3stack TO1 + +1. Support boot from NAND +Changes link script to separate initial code to multiple sections. +2. One binary support boot from NOR and NAND +Changes common file start.S to support multiple sections. + +Signed-off-by: Fred Fan +--- + board/freescale/mx35_3stack/lowlevel_init.S | 12 ++- + board/freescale/mx35_3stack/u-boot.lds | 7 +- + cpu/arm1136/mx35/Makefile | 1 + + cpu/arm1136/mx35/mxc_nand_load.S | 261 +++++++++++++++++++++++++++ + cpu/arm1136/start.S | 34 ++-- + include/asm-arm/arch-mx35/mx35.h | 39 ++++ + 6 files changed, 334 insertions(+), 20 deletions(-) + +diff --git a/board/freescale/mx35_3stack/lowlevel_init.S b/board/freescale/mx35_3stack/lowlevel_init.S +index 84614fc..40792f1 100644 +--- a/board/freescale/mx35_3stack/lowlevel_init.S ++++ b/board/freescale/mx35_3stack/lowlevel_init.S +@@ -241,6 +241,8 @@ + str r3, [r0, #0x30] + .endm /* setup_sdram */ + ++.section ".text.init", "x" ++ + .globl lowlevel_init + lowlevel_init: + /* Platform CHIP level init*/ +@@ -306,7 +308,15 @@ init_clock_start: + /*init_sdram*/ + setup_sdram + skip_sdram_setup: +- mov pc, lr ++ mov r0, #NFC_BASE_ADDR ++ add r1, r0, #NFC_BUF_SIZE ++ cmp pc, r0 ++ movlo pc, lr ++ cmp pc, r1 ++ movhi pc, lr ++ /* return from mxc_nand_load */ ++ /* r12 saved upper lr*/ ++ b mxc_nand_load + + /* + * r0: ESDCTL control base, r1: sdram slot base +diff --git a/board/freescale/mx35_3stack/u-boot.lds b/board/freescale/mx35_3stack/u-boot.lds +index 8a565e7..1b343be 100644 +--- a/board/freescale/mx35_3stack/u-boot.lds ++++ b/board/freescale/mx35_3stack/u-boot.lds +@@ -38,8 +38,11 @@ SECTIONS + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ +- +- cpu/arm1136/start.o (.text) ++ *(.text.head) /*arm startup code*/ ++ *(.text.init) /*platform lowlevel initial code*/ ++ *(.text.load) /*load bootloader*/ ++ *(.text.setup) /*platform post lowlevel initial code*/ ++ *(.text.vect) /*platform post lowlevel initial code*/ + board/freescale/mx35_3stack/libmx35_3stack.a (.text) + lib_arm/libarm.a (.text) + net/libnet.a (.text) +diff --git a/cpu/arm1136/mx35/Makefile b/cpu/arm1136/mx35/Makefile +index e83cbf7..afcf771 100644 +--- a/cpu/arm1136/mx35/Makefile ++++ b/cpu/arm1136/mx35/Makefile +@@ -28,6 +28,7 @@ include $(TOPDIR)/config.mk + LIB = $(obj)lib$(SOC).a + + COBJS = interrupts.o serial.o generic.o iomux.o ++SOBJS = mxc_nand_load.o + + SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) + OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +diff --git a/cpu/arm1136/mx35/mxc_nand_load.S b/cpu/arm1136/mx35/mxc_nand_load.S +new file mode 100644 +index 0000000..2ff223d +--- /dev/null ++++ b/cpu/arm1136/mx35/mxc_nand_load.S +@@ -0,0 +1,261 @@ ++/* ++ * (C) Copyright 2008 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++ ++.macro nfc_cmd_input ++ strh r3, [r12, #NAND_FLASH_CMD_REG_OFF] ++ mov r3, #NAND_FLASH_CONFIG2_FCMD_EN; ++ strh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF] ++ bl do_wait_op_done ++.endm // nfc_cmd_input ++ ++.macro do_addr_input ++ and r3, r3, #0xFF ++ strh r3, [r12, #NAND_FLASH_ADD_REG_OFF] ++ mov r3, #NAND_FLASH_CONFIG2_FADD_EN ++ strh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF] ++ bl do_wait_op_done ++.endm // do_addr_input ++ ++.section ".text.load", "x" ++.globl mxc_nand_load ++mxc_nand_load: ++ ldr r2, U_BOOT_NAND_START ++1: ldmia r0!, {r3-r10} ++ stmia r2!, {r3-r10} ++ cmp r0, r1 ++ blo 1b ++ ++ ldr r1, CONST_0X0FFF ++ ldr r2, U_BOOT_NAND_START ++ and lr, lr, r1 ++ add lr, lr, r2 ++ and r12, r12, r1 ++ add r12, r12, r2 ++ add r2, r2, #0x8 ++ and r0, pc, r1 ++ add pc, r0, r2 ++ nop ++ nop ++ nop ++ nop ++ nop ++ adr r0, SAVE_REGS ++ str r12, [r0] ++ str lr, [r0, #4] ++Copy_Main: ++ mov r0, #NFC_BASE_ADDR ++ add r12, r0, #0x1E00 ++ ldrh r3, [r12, #NAND_FLASH_CONFIG1_REG_OFF] ++ orr r3, r3, #1 ++ ++ /* Setting NFC */ ++ ldr r7, =CCM_BASE_ADDR ++ ldr r1, [r7, #CLKCTL_RCSR] ++ /*BUS WIDTH setting*/ ++ tst r1, #0x20000000 ++ orrne r1, r1, #0x4000 ++ biceq r1, r1, #0x4000 ++ ++ /*4K PAGE*/ ++ tst r1, #0x10000000 ++ orrne r1, r1, #0x200 ++ bne 1f ++ /*2K PAGE*/ ++ bic r1, r1, #0x200 ++ tst r1, #0x08000000 ++ orrne r1, r1, #0x100 /*2KB page size*/ ++ biceq r1, r1, #0x100 /*512B page size*/ ++ movne r2, #32 /*64 bytes*/ ++ moveq r2, #8 /*16 bytes*/ ++ b NAND_setup ++1: ++ tst r1, #0x08000000 ++ bicne r3, r3, #1 /*Enable 8bit ECC mode*/ ++ movne r2, #109 /*218 bytes*/ ++ moveq r2, #64 /*128 bytes*/ ++NAND_setup: ++ str r1, [r7, #CLKCTL_RCSR] ++ strh r2, [r12, #ECC_RSLT_SPARE_AREA_REG_OFF] ++ strh r3, [r12, #NAND_FLASH_CONFIG1_REG_OFF] ++ ++ //unlock internal buffer ++ mov r3, #0x2 ++ strh r3, [r12, #NFC_CONFIGURATION_REG_OFF] ++ //unlock nand device ++ mov r3, #0 ++ strh r3, [r12, #UNLOCK_START_BLK_ADD_REG_OFF] ++ sub r3, r3, #1 ++ strh r3, [r12, #UNLOCK_END_BLK_ADD_REG_OFF] ++ mov r3, #4 ++ strh r3, [r12, #NF_WR_PROT_REG_OFF] ++ ++ /* r0: NFC base address. RAM buffer base address. [constantly] ++ * r1: starting flash address to be copied. [constantly] ++ * r2: page size. [Doesn't change] ++ * r3: used as argument. ++ * r11: starting SDRAM address for copying. [Updated constantly]. ++ * r12: NFC register base address. [constantly]. ++ * r13: end of SDRAM address for copying. [Doesn't change]. ++ */ ++ ++ mov r1, #0x1000 ++ ldr r3, [r7, #CLKCTL_RCSR] ++ tst r3, #0x200 ++ movne r2, #0x1000 ++ bne 1f ++ tst r3, #0x100 ++ mov r1, #0x800 /*Strange Why is not 4K offset*/ ++ movne r2, #0x800 ++ moveq r2, #0x200 ++1: /*Update the indicator of copy area */ ++ ldr r11, U_BOOT_NAND_START ++ add r13, r11, #0x00088000; /*512K + 32K*/ ++ add r11, r11, r1 ++ ++Nfc_Read_Page: ++ mov r3, #0x0 ++ nfc_cmd_input ++ ++ cmp r2, #0x800 ++ bhi nfc_addr_ops_4kb ++ beq nfc_addr_ops_2kb ++ ++ mov r3, r1 ++ do_addr_input //1st addr cycle ++ mov r3, r1, lsr #9 ++ do_addr_input //2nd addr cycle ++ mov r3, r1, lsr #17 ++ do_addr_input //3rd addr cycle ++ mov r3, r1, lsr #25 ++ do_addr_input //4th addr cycle ++ b end_of_nfc_addr_ops ++ ++nfc_addr_ops_2kb: ++ mov r3, #0 ++ do_addr_input //1st addr cycle ++ mov r3, #0 ++ do_addr_input //2nd addr cycle ++ mov r3, r1, lsr #11 ++ do_addr_input //3rd addr cycle ++ mov r3, r1, lsr #19 ++ do_addr_input //4th addr cycle ++ mov r3, r1, lsr #27 ++ do_addr_input //5th addr cycle ++ ++ mov r3, #0x30 ++ nfc_cmd_input ++ b end_of_nfc_addr_ops ++ ++nfc_addr_ops_4kb: ++ mov r3, #0 ++ do_addr_input //1st addr cycle ++ mov r3, #0 ++ do_addr_input //2nd addr cycle ++ mov r3, r1, lsr #12 ++ do_addr_input //3rd addr cycle ++ mov r3, r1, lsr #20 ++ do_addr_input //4th addr cycle ++ mov r3, r1, lsr #27 ++ do_addr_input //5th addr cycle ++ ++ mov r3, #0x30 ++ nfc_cmd_input ++ ++end_of_nfc_addr_ops: ++ mov r8, #0 ++ bl nfc_data_output ++ bl do_wait_op_done ++ // Check if x16/2kb page ++ cmp r2, #0x800 ++ bhi nfc_addr_data_output_done_4k ++ beq nfc_addr_data_output_done_2k ++ beq nfc_addr_data_output_done_512 ++ ++ // check for bad block ++ // mov r3, r1, lsl #(32-17) // get rid of block number ++ // cmp r3, #(0x800 << (32-17)) // check if not page 0 or 1 ++ b nfc_addr_data_output_done ++ ++nfc_addr_data_output_done_4k: ++//TODO ++ b nfc_addr_data_output_done ++ ++nfc_addr_data_output_done_2k: ++ // end of 4th ++ // check for bad block ++ //TODO mov r3, r1, lsl #(32-17) // get rid of block number ++ // cmp r3, #(0x800 << (32-17)) // check if not page 0 or 1 ++ b nfc_addr_data_output_done ++ ++nfc_addr_data_output_done_512: ++ // check for bad block ++ // TODO mov r3, r1, lsl #(32-5-9) // get rid of block number ++ // TODO cmp r3, #(512 << (32-5-9)) // check if not page 0 or 1 ++ ++nfc_addr_data_output_done: ++Copy_Good_Blk: ++ //copying page ++ add r2, r2, #NFC_BASE_ADDR ++1: ldmia r0!, {r3-r10} ++ stmia r11!, {r3-r10} ++ cmp r0, r2 ++ blo 1b ++ sub r2, r2, #NFC_BASE_ADDR ++ ++ cmp r11, r13 ++ bge NAND_Copy_Main_done ++ // Check if x16/2kb page ++ add r1, r1, r2 ++ mov r0, #NFC_BASE_ADDR ++ b Nfc_Read_Page ++ ++NAND_Copy_Main_done: ++ adr r0, SAVE_REGS ++ ldr r12, [r0] ++ ldr lr, [r0, #4] ++ mov pc, lr ++ ++do_wait_op_done: ++1: ++ ldrh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF] ++ ands r3, r3, #NAND_FLASH_CONFIG2_INT_DONE ++ beq 1b ++ bx lr // do ++ ++nfc_data_output: ++ ldrh r3, [r12, #NAND_FLASH_CONFIG1_REG_OFF] ++ orr r3, r3, #(NAND_FLASH_CONFIG1_INT_MSK | NAND_FLASH_CONFIG1_ECC_EN) ++ strh r3, [r12, #NAND_FLASH_CONFIG1_REG_OFF] ++ ++ strh r8, [r12, #RAM_BUFFER_ADDRESS_REG_OFF] ++ ++ mov r3, #FDO_PAGE_SPARE_VAL ++ strh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF] ++ bx lr ++ ++U_BOOT_NAND_START: .word TEXT_BASE ++CONST_0X0FFF: .word 0x0FFF ++SAVE_REGS: .word 0x0 ++ .word 0x0 +diff --git a/cpu/arm1136/start.S b/cpu/arm1136/start.S +index 9d2ea1e..acfb21d 100644 +--- a/cpu/arm1136/start.S ++++ b/cpu/arm1136/start.S +@@ -30,8 +30,14 @@ + + #include + #include ++ ++.section ".text.head", "ax" + .globl _start +-_start: b reset ++_start: ++.section ".text.vect", "ax" ++.global _start_vect ++_start_vect: ++ b reset + #ifdef CONFIG_ONENAND_IPL + ldr pc, _hang + ldr pc, _hang +@@ -89,10 +95,7 @@ _end_vect: + * the actual reset code + */ + +-#ifdef CONFIG_NAND_BOOT +-.section ".text.head", "x" +-#endif +- ++.section ".text.head", "ax" + .globl reset + reset: + /* +@@ -106,7 +109,7 @@ reset: + #ifdef CONFIG_OMAP2420H4 + /* Copy vectors to mask ROM indirect addr */ + adr r0, _start /* r0 <- current position of code */ +- add r0, r0, #4 /* skip reset vector */ ++ add r0, r0, #4 /* skip reset vector */ + mov r2, #64 /* r2 <- size to copy */ + add r2, r0, r2 /* r2 <- source end address */ + mov r1, #SRAM_OFFSET0 /* build vect addr */ +@@ -165,21 +168,15 @@ cpu_init_crit: + mov pc, lr /* back to my caller */ + + +-#ifdef CONFIG_NAND_BOOT +-.section ".text.setup" +-#endif ++.section ".text.setup", "ax" + +-.globl _TEST_BASE ++.globl _TEXT_BASE + _TEXT_BASE: + .word TEXT_BASE + + .globl _armboot_start + _armboot_start: +-#ifndef CONFIG_NAND_BOOT + .word _start +-#else +- .word reset +-#endif + + /* + * These are defined in the board-specific linker script. +@@ -208,13 +205,16 @@ setup_env: + + #ifndef CONFIG_SKIP_RELOCATE_UBOOT + relocate: /* relocate U-Boot to RAM */ +- adr r0, _start /* r0 <- current position of code */ +- ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ ++ adr r0, _armboot_start ++ ldr r1, =_armboot_start + cmp r0, r1 /* don't reloc during debug */ + #ifndef CONFIG_ONENAND_IPL + beq stack_setup + #endif /* CONFIG_ONENAND_IPL */ +- ++ ldr r2, _TEXT_BASE ++ sub r0, r1, r0 ++ sub r0, r2, r0 ++ ldr r1, _TEXT_BASE + ldr r2, _armboot_start + ldr r3, _bss_start + sub r2, r3, r2 /* r2 <- size of armboot */ +diff --git a/include/asm-arm/arch-mx35/mx35.h b/include/asm-arm/arch-mx35/mx35.h +index ba30597..b430c83 100644 +--- a/include/asm-arm/arch-mx35/mx35.h ++++ b/include/asm-arm/arch-mx35/mx35.h +@@ -179,6 +179,45 @@ + #define GPIO_PORT_NUM 3 + #define GPIO_NUM_PIN 32 + ++#define NFC_BUF_SIZE 0x1000 ++#define NFC_BUFSIZE_REG_OFF (0 + 0x00) ++#define RAM_BUFFER_ADDRESS_REG_OFF (0 + 0x04) ++#define NAND_FLASH_ADD_REG_OFF (0 + 0x06) ++#define NAND_FLASH_CMD_REG_OFF (0 + 0x08) ++#define NFC_CONFIGURATION_REG_OFF (0 + 0x0A) ++#define ECC_STATUS_RESULT_REG_OFF (0 + 0x0C) ++#define ECC_RSLT_MAIN_AREA_REG_OFF (0 + 0x0E) ++#define ECC_RSLT_SPARE_AREA_REG_OFF (0 + 0x10) ++#define NF_WR_PROT_REG_OFF (0 + 0x12) ++#define NAND_FLASH_WR_PR_ST_REG_OFF (0 + 0x18) ++#define NAND_FLASH_CONFIG1_REG_OFF (0 + 0x1A) ++#define NAND_FLASH_CONFIG2_REG_OFF (0 + 0x1C) ++#define UNLOCK_START_BLK_ADD_REG_OFF (0 + 0x20) ++#define UNLOCK_END_BLK_ADD_REG_OFF (0 + 0x22) ++#define RAM_BUFFER_ADDRESS_RBA_3 0x3 ++#define NFC_BUFSIZE_1KB 0x0 ++#define NFC_BUFSIZE_2KB 0x1 ++#define NFC_CONFIGURATION_UNLOCKED 0x2 ++#define ECC_STATUS_RESULT_NO_ERR 0x0 ++#define ECC_STATUS_RESULT_1BIT_ERR 0x1 ++#define ECC_STATUS_RESULT_2BIT_ERR 0x2 ++#define NF_WR_PROT_UNLOCK 0x4 ++#define NAND_FLASH_CONFIG1_FORCE_CE (1 << 7) ++#define NAND_FLASH_CONFIG1_RST (1 << 6) ++#define NAND_FLASH_CONFIG1_BIG (1 << 5) ++#define NAND_FLASH_CONFIG1_INT_MSK (1 << 4) ++#define NAND_FLASH_CONFIG1_ECC_EN (1 << 3) ++#define NAND_FLASH_CONFIG1_SP_EN (1 << 2) ++#define NAND_FLASH_CONFIG2_INT_DONE (1 << 15) ++#define NAND_FLASH_CONFIG2_FDO_PAGE (0 << 3) ++#define NAND_FLASH_CONFIG2_FDO_ID (2 << 3) ++#define NAND_FLASH_CONFIG2_FDO_STATUS (4 << 3) ++#define NAND_FLASH_CONFIG2_FDI_EN (1 << 2) ++#define NAND_FLASH_CONFIG2_FADD_EN (1 << 1) ++#define NAND_FLASH_CONFIG2_FCMD_EN (1 << 0) ++#define FDO_PAGE_SPARE_VAL 0x8 ++#define NAND_BUF_NUM 8 ++ + #ifndef __ASSEMBLER__ + + enum mxc_clock { +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0008-ENGR00104583-MX35-can-not-boot-up-kernel.patch +++ uboot-imx-2009.01/debian/patches/0008-ENGR00104583-MX35-can-not-boot-up-kernel.patch @@ -0,0 +1,162 @@ +From 9ffbcea76fd9ed024c2e06e08f43e7a9a6d608b4 Mon Sep 17 00:00:00 2001 +From: Fred Fan +Date: Mon, 23 Feb 2009 14:08:23 +0800 +Subject: [PATCH] ENGR00104583 MX35 can not boot up kernel + +uboot can not boot kernel. +There are no more messages excepts uncompression message. +The root cause is wrong romfile version offset. + +Signed-off-by: Fred Fan +--- + board/freescale/mx35_3stack/lowlevel_init.S | 15 +++++++++++---- + board/freescale/mx35_3stack/mx35_3stack.c | 10 ++++++---- + drivers/net/smc911x.c | 8 ++------ + include/asm-arm/arch-mx35/mx35.h | 12 +++++++++++- + 4 files changed, 30 insertions(+), 15 deletions(-) + +diff --git a/board/freescale/mx35_3stack/lowlevel_init.S b/board/freescale/mx35_3stack/lowlevel_init.S +index 0b47ef1..c255e98 100644 +--- a/board/freescale/mx35_3stack/lowlevel_init.S ++++ b/board/freescale/mx35_3stack/lowlevel_init.S +@@ -33,8 +33,8 @@ + ldr \tmp, =IIM_BASE_ADDR + ldr \ret, [\tmp, #IIM_SREV] + cmp \ret, #0x00 +- moveq \tmp, #ROMPATCH_BASE_ADDR +- ldreq \ret, [\tmp, #ROMPATCH_REV] ++ moveq \tmp, #ROMPATCH_REV ++ ldreq \ret, [\tmp] + moveq \ret, \ret, lsl #4 + addne \ret, \ret, #0x10 + .endm +@@ -62,6 +62,13 @@ + orr r1, r1, r2 + str r1, [r0, #L2_CACHE_AUX_CTL_REG] + ++ /* Workaournd for TO1 DDR issue:WT*/ ++ check_soc_version r1, r2 ++ cmp r1, #CHIP_REV_2_0 ++ ldrlo r1, [r0, #L2_CACHE_DBG_CTL_REG] ++ orrlo r1, r1, #2 ++ strlo r1, [r0, #L2_CACHE_DBG_CTL_REG] ++ + /* Invalidate L2 */ + mov r1, #0x000000FF + str r1, [r0, #L2_CACHE_INV_WAY_REG] +@@ -196,7 +203,7 @@ + str r2, [r0, #CLKCTL_CCMR] + + check_soc_version r1, r2 +- cmp r1, #0x20 ++ cmp r1, #CHIP_REV_2_0 + ldrhs r3, =CCM_MPLL_399_HZ + bhs 1f + ldr r2, [r0, #CLKCTL_PDR0] +@@ -247,7 +254,7 @@ + mov lr, fp + + check_soc_version r3, r4 +- cmp r1, #0x20 ++ cmp r1, #CHIP_REV_2_0 + bhs 1f + cmp r5, #0 + movne r3, #L2CC_BASE_ADDR +diff --git a/board/freescale/mx35_3stack/mx35_3stack.c b/board/freescale/mx35_3stack/mx35_3stack.c +index 7854f86..267e9f1 100644 +--- a/board/freescale/mx35_3stack/mx35_3stack.c ++++ b/board/freescale/mx35_3stack/mx35_3stack.c +@@ -43,19 +43,20 @@ static inline void setup_soc_rev(void) + int reg; + reg = __REG(IIM_BASE_ADDR + IIM_SREV); + if (!reg) { +- reg = __REG(ROMPATCH_BASE_ADDR + ROMPATCH_REV); ++ reg = __REG(ROMPATCH_REV); + reg <<= 4; + } else +- reg += 0x10; ++ reg += CHIP_REV_1_0; + system_rev = 0x35000 + (reg & 0xFF); + } + + static inline void set_board_rev(int rev) + { +- system_rev |= (rev & 0xF) << 8; ++ int reg; ++ system_rev = (system_rev & ~(0xF << 8)) | (rev & 0xF) << 8; + } + +-static inline int is_soc_rev(int rev) ++int is_soc_rev(int rev) + { + return (system_rev & 0xFF) - rev; + } +@@ -171,6 +172,7 @@ static inline int board_detect(void) + set_board_rev(1); + return 1; + } ++ set_board_rev(0); + return 0; + } + +diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c +index e0794f2..b5b2f92 100644 +--- a/drivers/net/smc911x.c ++++ b/drivers/net/smc911x.c +@@ -29,12 +29,6 @@ + #include + #include + +-#if defined (CONFIG_DRIVER_SMC911X_32_BIT) && \ +- defined (CONFIG_DRIVER_SMC911X_16_BIT) +-#error "SMC911X: Only one of CONFIG_DRIVER_SMC911X_32_BIT and \ +- CONFIG_DRIVER_SMC911X_16_BIT shall be set" +-#endif +- + #if defined (CONFIG_DRIVER_SMC911X_32_BIT) + static inline u32 reg_read(u32 addr) + { +@@ -742,3 +736,5 @@ int smc911x_initialize(bd_t *bis) + return 0; + } + #endif ++ ++#endif +diff --git a/include/asm-arm/arch-mx35/mx35.h b/include/asm-arm/arch-mx35/mx35.h +index 2ed85d3..c96092c 100644 +--- a/include/asm-arm/arch-mx35/mx35.h ++++ b/include/asm-arm/arch-mx35/mx35.h +@@ -221,6 +221,12 @@ + #define FDO_PAGE_SPARE_VAL 0x8 + #define NAND_BUF_NUM 8 + ++#define CHIP_REV_1_0 0x10 ++#define CHIP_REV_2_0 0x20 ++ ++#define BOARD_REV_1_0 0x0 ++#define BOARD_REV_2_0 0x1 ++ + #ifndef __ASSEMBLER__ + + enum mxc_clock { +@@ -239,12 +245,16 @@ MXC_UART_CLK, + #define NFMS_NF_DWIDTH 14 + #define NFMS_NF_PG_SZ 8 + ++ + extern unsigned int mxc_get_clock(enum mxc_clock clk); ++extern unsigned int get_board_rev(void); ++extern int is_soc_rev(int rev); + + #define fixup_before_linux \ + { \ + volatile unsigned long *l2cc_ctl = (unsigned long *)0x30000100;\ +- *l2cc_ctl = 1;\ ++ if (is_soc_rev(CHIP_REV_2_0) < 0) \ ++ *l2cc_ctl = 1;\ + } + #endif /* __ASSEMBLER__*/ + #endif /* __ASM_ARCH_MX35_H */ +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0015-ENGR00107840-Add-U-Boot-for-MX25-PDK-board.patch +++ uboot-imx-2009.01/debian/patches/0015-ENGR00107840-Add-U-Boot-for-MX25-PDK-board.patch @@ -0,0 +1,753 @@ +From 5954b3325016380aa3963d25be2e4e12cef5df98 Mon Sep 17 00:00:00 2001 +From: Alan Carvalho de Assis +Date: Thu, 5 Mar 2009 09:26:00 -0300 +Subject: [PATCH] ENGR00107840 Add U-Boot for MX25 PDK board + +These patches add functional support to iMX25PDK. +Currently only the internal FEC is supported. + +Signed-off-by: Alan Carvalho de Assis +--- + Makefile | 3 + + board/freescale/mx25_3stack/Makefile | 53 +++++++ + board/freescale/mx25_3stack/config.mk | 1 + + board/freescale/mx25_3stack/dcdheader.S | 99 +++++++++++++ + board/freescale/mx25_3stack/lowlevel_init.S | 72 ++++++++++ + board/freescale/mx25_3stack/mx25_3stack.c | 187 +++++++++++++++++++++++++ + board/freescale/mx25_3stack/u-boot.lds | 62 ++++++++ + include/configs/mx25_3stack.h | 200 +++++++++++++++++++++++++++ + 8 files changed, 677 insertions(+), 0 deletions(-) + +diff --git a/Makefile b/Makefile +index 1b5172d..46dd8fb 100644 +--- a/Makefile ++++ b/Makefile +@@ -2677,6 +2677,9 @@ at91sam9rlek_config : unconfig + fi; + @$(MKCONFIG) -a at91sam9rlek arm arm926ejs at91sam9rlek atmel at91 + ++mx25_3stack_config : unconfig ++ @$(MKCONFIG) $(@:_config=) arm arm926ejs mx25_3stack freescale mx25 ++ + ######################################################################## + ## ARM Integrator boards - see doc/README-integrator for more info. + integratorap_config \ +diff --git a/board/freescale/mx25_3stack/Makefile b/board/freescale/mx25_3stack/Makefile +new file mode 100644 +index 0000000..ac308fe +--- /dev/null ++++ b/board/freescale/mx25_3stack/Makefile +@@ -0,0 +1,53 @@ ++# ++# (c) Copyright 2009 Freescale Semiconductor ++# ++# (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$(BOARD).a ++ ++COBJS := mx25_3stack.o ++SOBJS := lowlevel_init.o dcdheader.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 .depend ++ ++######################################################################### ++ ++# defines $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +diff --git a/board/freescale/mx25_3stack/config.mk b/board/freescale/mx25_3stack/config.mk +new file mode 100644 +index 0000000..4c401e7 +--- /dev/null ++++ b/board/freescale/mx25_3stack/config.mk +@@ -0,0 +1 @@ ++TEXT_BASE = 0x83F00000 +diff --git a/board/freescale/mx25_3stack/dcdheader.S b/board/freescale/mx25_3stack/dcdheader.S +new file mode 100644 +index 0000000..2bd61ed +--- /dev/null ++++ b/board/freescale/mx25_3stack/dcdheader.S +@@ -0,0 +1,99 @@ ++/* ++ * Copyright (c) 2009 Freescale Semiconductor ++ * ++ * 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 ++#include ++ ++.extern reset ++ ++#define DCDGEN(i,type, addr, data) \ ++dcd_##i: ;\ ++ .long type ;\ ++ .long addr ;\ ++ .long data ++ ++.globl _initheader ++_initheader: ++ b reset ++ .org 0x400 ++app_code_jump_v: .long reset ++app_code_barker: .long 0xB1 ++app_code_csf: .long 0 ++hwcfg_ptr_ptr: .long hwcfg_ptr ++super_root_key: .long 0 ++hwcfg_ptr: .long dcd_data ++app_dest_ptr: .long TEXT_BASE ++dcd_data: .long 0xB17219E9 ++ ++#ifdef MXC_MEMORY_MDDR ++dcd_len: .long 12*15 ++#else ++dcd_len: .long 12*24 ++#endif ++ ++/* WEIM config-CS5 init -- CPLD */ ++DCDGEN( 1, 4, 0xB8002050, 0x0000D843) /* CS5_CSCRU */ ++DCDGEN( 2, 4, 0xB8002054, 0x22252521) /* CS5_CSCRL */ ++DCDGEN( 3, 4, 0xB8002058, 0x22220A00) /* CS5_CSCRA */ ++#ifdef MXC_MEMORY_MDDR ++/* MDDR init */ ++DCDGEN( 4, 4, 0xB8001010, 0x00000004) /* enable mDDR */ ++DCDGEN( 5, 4, 0xB8001000, 0x92100000) /* precharge command */ ++DCDGEN( 6, 1, 0x80000400, 0x12344321) /* precharge all dummy write */ ++DCDGEN( 7, 4, 0xB8001000, 0xA2100000) /* auto-refresh command */ ++DCDGEN( 8, 4, 0x80000000, 0x12344321) /* dummy write for refresh */ ++DCDGEN( 9, 4, 0x80000000, 0x12344321) /* dummy write for refresh */ ++DCDGEN(10, 4, 0xB8001000, 0xB2100000) /* Load Mode Reg command - cas=3 bl=8 */ ++DCDGEN(11, 1, 0x80000033, 0xda) /* dummy write -- address has the mode bits */ ++DCDGEN(12, 1, 0x81000000, 0xff) /* dummy write -- address has the mode bits */ ++DCDGEN(13, 4, 0xB8001000, 0x82216880) ++DCDGEN(14, 4, 0xB8001004, 0x00295729) ++#else ++/* DDR2 init */ ++DCDGEN( 4, 4, 0xB8001004, 0x0076E83A) /* initial value for ESDCFG0 */ ++DCDGEN( 5, 4, 0xB8001010, 0x00000204) /* ESD_MISC */ ++DCDGEN( 6, 4, 0xB8001000, 0x92210000) /* CS0 precharge command */ ++DCDGEN( 7, 4, 0x80000f00, 0x12344321) /* precharge all dummy write */ ++DCDGEN( 8, 4, 0xB8001000, 0xB2210000) /* Load Mode Register command */ ++DCDGEN( 9, 1, 0x82000000, 0xda) /* dummy write Load EMR2 */ ++DCDGEN(10, 1, 0x83000000, 0xda) /* dummy write Load EMR3 */ ++DCDGEN(11, 1, 0x81000400, 0xda) /* dummy write Load EMR1; enable DLL */ ++DCDGEN(12, 1, 0x80000333, 0xda) /* dummy write Load MR; reset DLL */ ++ ++DCDGEN(13, 4, 0xB8001000, 0x92210000) /* CS0 precharge command */ ++DCDGEN(14, 1, 0x80000400, 0x12345678) /* precharge all dummy write */ ++ ++DCDGEN(15, 4, 0xB8001000, 0xA2210000) /* select manual refresh mode */ ++DCDGEN(16, 4, 0x80000000, 0x87654321) /* manual refresh */ ++DCDGEN(17, 4, 0x80000000, 0x87654321) /* manual refresh twice */ ++ ++DCDGEN(18, 4, 0xB8001000, 0xB2210000) /* Load Mode Register command */ ++DCDGEN(19, 1, 0x80000233, 0xda) /* Load MR; CL=3, BL=8, end DLL reset */ ++DCDGEN(20, 1, 0x81000780, 0xda) /* Load EMR1; OCD default */ ++DCDGEN(21, 1, 0x81000400, 0xda) /* Load EMR1; OCD exit */ ++DCDGEN(22, 4, 0xB8001000, 0x82216080) /* normal mode */ ++DCDGEN(23, 4, 0x43FAC454, 0x00001000) /* IOMUXC_SW_PAD_CTL_GRP_DDRTYPE(1-5) */ ++#endif ++ ++DCDGEN(99, 4, 0x53F80008, 0x20034000) /* CLKCTL ARM=400 AHB=133 */ ++card_cfg: .long UBOOT_IMAGE_SIZE +diff --git a/board/freescale/mx25_3stack/lowlevel_init.S b/board/freescale/mx25_3stack/lowlevel_init.S +new file mode 100644 +index 0000000..61bb589 +--- /dev/null ++++ b/board/freescale/mx25_3stack/lowlevel_init.S +@@ -0,0 +1,72 @@ ++/* ++ * Copyright (c) 2009 Freescale Semiconductor ++ * ++ * 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 ++ ++.macro REG reg, val ++ ldr r2, =\reg ++ ldr r3, =\val ++ str r3, [r2] ++.endm ++ ++.macro REG8 reg, val ++ ldr r2, =\reg ++ ldr r3, =\val ++ strb r3, [r2] ++.endm ++ ++.globl lowlevel_init ++lowlevel_init: ++ ++ REG 0x53F80008, 0x20034000 // ARM clk = 399, AHB clk = 133 ++ ++ /* Init Debug Board CS5 */ ++ REG 0xB8002050, 0x0000D843 ++ REG 0xB8002054, 0x22252521 ++ REG 0xB8002058, 0x22220A00 ++ ++ /* M3IF setup */ ++ ldr r0, =0x00000001 ++ str r0, [r1] /* M3IF control reg */ ++ ++ /* default CLKO to 1/32 of the ARM core */ ++ ldr r0, =CCM_MCR ++ ldr r1, =CCM_MCR ++ bic r1, r1, #0x00F00000 ++ bic r1, r1, #0x7F000000 ++ mov r2, #0x5F000000 ++ add r2, r2, #0x00200000 ++ orr r1, r1, r2 ++ str r1, [r0] ++ ++ /* enable all the clocks */ ++ ldr r2, =0x1FFFFFFF ++ ldr r0, =CCM_CGR0 ++ str r2, [r0] ++ ldr r2, =0xFFFFFFFF ++ ldr r0, =CCM_CGR1 ++ str r2, [r0] ++ ldr r2, =0x000FDFFF ++ ldr r0, =CCM_CGR2 ++ str r2, [r0] ++ mov pc, lr ++ +diff --git a/board/freescale/mx25_3stack/mx25_3stack.c b/board/freescale/mx25_3stack/mx25_3stack.c +new file mode 100644 +index 0000000..22559b6 +--- /dev/null ++++ b/board/freescale/mx25_3stack/mx25_3stack.c +@@ -0,0 +1,187 @@ ++/* ++ * (c) Copyright 2009 Freescale Semiconductor ++ * ++ * (c) 2007 Pengutronix, Sascha Hauer ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++static u32 system_rev; ++ ++u32 get_board_rev(void) ++{ ++ return system_rev; ++} ++ ++static inline void setup_soc_rev(void) ++{ ++ int reg; ++ reg = __REG(IIM_BASE + IIM_SREV); ++ if (!reg) { ++ reg = __REG(ROMPATCH_REV); ++ reg <<= 4; ++ } else ++ reg += CHIP_REV_1_0; ++ system_rev = 0x25000 + (reg & 0xFF); ++} ++ ++int dram_init(void) ++{ ++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1; ++ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; ++ ++ return 0; ++} ++ ++int board_init(void) ++{ ++ int pad; ++ u8 reg[4]; ++ ++ setup_soc_rev(); ++ ++ /* setup pins for UART1 */ ++ /* UART 1 IOMUX Configs */ ++ mxc_request_iomux(MX25_PIN_UART1_RXD, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_UART1_TXD, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_UART1_RTS, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_UART1_CTS, MUX_CONFIG_FUNC); ++ mxc_iomux_set_pad(MX25_PIN_UART1_RXD, ++ PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | ++ PAD_CTL_PUE_PUD | PAD_CTL_100K_PU); ++ mxc_iomux_set_pad(MX25_PIN_UART1_TXD, ++ PAD_CTL_PUE_PUD | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX25_PIN_UART1_RTS, ++ PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | ++ PAD_CTL_PUE_PUD | PAD_CTL_100K_PU); ++ mxc_iomux_set_pad(MX25_PIN_UART1_CTS, ++ PAD_CTL_PUE_PUD | PAD_CTL_100K_PD); ++ ++ /* setup pins for FEC */ ++ mxc_request_iomux(MX25_PIN_FEC_TX_CLK, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_FEC_RX_DV, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_FEC_RDATA0, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_FEC_TDATA0, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_FEC_TX_EN, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_FEC_MDC, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_FEC_MDIO, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_FEC_RDATA1, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_FEC_TDATA1, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX25_PIN_POWER_FAIL, MUX_CONFIG_FUNC); /* PHY INT */ ++ ++#define FEC_PAD_CTL1 (PAD_CTL_HYS_SCHMITZ | PAD_CTL_PUE_PUD | \ ++ PAD_CTL_PKE_ENABLE) ++#define FEC_PAD_CTL2 (PAD_CTL_PUE_PUD) ++ ++ mxc_iomux_set_pad(MX25_PIN_FEC_TX_CLK, FEC_PAD_CTL1); ++ mxc_iomux_set_pad(MX25_PIN_FEC_RX_DV, FEC_PAD_CTL1); ++ mxc_iomux_set_pad(MX25_PIN_FEC_RDATA0, FEC_PAD_CTL1); ++ mxc_iomux_set_pad(MX25_PIN_FEC_TDATA0, FEC_PAD_CTL2); ++ mxc_iomux_set_pad(MX25_PIN_FEC_TX_EN, FEC_PAD_CTL2); ++ mxc_iomux_set_pad(MX25_PIN_FEC_MDC, FEC_PAD_CTL2); ++ mxc_iomux_set_pad(MX25_PIN_FEC_MDIO, FEC_PAD_CTL1 | PAD_CTL_22K_PU); ++ mxc_iomux_set_pad(MX25_PIN_FEC_RDATA1, FEC_PAD_CTL1); ++ mxc_iomux_set_pad(MX25_PIN_FEC_TDATA1, FEC_PAD_CTL2); ++ mxc_iomux_set_pad(MX25_PIN_POWER_FAIL, FEC_PAD_CTL1); ++ ++ /* ++ * Set up the FEC_RESET_B and FEC_ENABLE GPIO pins. ++ * Assert FEC_RESET_B, then power up the PHY by asserting ++ * FEC_ENABLE, at the same time lifting FEC_RESET_B. ++ * ++ * FEC_RESET_B: gpio2[3] is ALT 5 mode of pin D12 ++ * FEC_ENABLE_B: gpio4[8] is ALT 5 mode of pin A17 ++ */ ++ mxc_request_iomux(MX25_PIN_A17, MUX_CONFIG_ALT5); /* FEC_EN */ ++ mxc_request_iomux(MX25_PIN_D12, MUX_CONFIG_ALT5); /* FEC_RESET_B */ ++ ++ mxc_iomux_set_pad(MX25_PIN_A17, PAD_CTL_ODE_OpenDrain); ++ mxc_iomux_set_pad(MX25_PIN_D12, 0); ++ ++ mxc_set_gpio_direction(MX25_PIN_A17, 0); /* FEC_EN */ ++ mxc_set_gpio_direction(MX25_PIN_D12, 0); /* FEC_RESET_B */ ++ ++ /* drop PHY power */ ++ mxc_set_gpio_dataout(MX25_PIN_A17, 0); /* FEC_EN */ ++ ++ /* assert reset */ ++ mxc_set_gpio_dataout(MX25_PIN_D12, 0); /* FEC_RESET_B */ ++ udelay(2); /* spec says 1us min */ ++ ++ /* turn on PHY power and lift reset */ ++ mxc_set_gpio_dataout(MX25_PIN_A17, 1); /* FEC_EN */ ++ mxc_set_gpio_dataout(MX25_PIN_D12, 1); /* FEC_RESET_B */ ++ ++#define I2C_PAD_CTL (PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | \ ++ PAD_CTL_PUE_PUD | PAD_CTL_100K_PU | PAD_CTL_ODE_OpenDrain) ++ ++ mxc_request_iomux(MX25_PIN_I2C1_CLK, MUX_CONFIG_SION); ++ mxc_request_iomux(MX25_PIN_I2C1_DAT, MUX_CONFIG_SION); ++ mxc_iomux_set_pad(MX25_PIN_I2C1_CLK, 0x1E8); ++ mxc_iomux_set_pad(MX25_PIN_I2C1_DAT, 0x1E8); ++ ++ gd->bd->bi_arch_number = MACH_TYPE_MX25_3DS; /* board id for linux */ ++ gd->bd->bi_boot_params = 0x80000100; /* address of boot parameters */ ++ ++ return 0; ++ ++#undef FEC_PAD_CTL1 ++#undef FEC_PAD_CTL2 ++#undef I2C_PAD_CTL ++} ++ ++#ifdef BOARD_LATE_INIT ++int board_late_init(void) ++{ ++ u8 reg[4]; ++ ++ /* Turn PMIC On*/ ++ reg[0] = 0x09; ++ i2c_write(0x54, 0x02, 1, reg, 1); ++} ++#endif ++ ++ ++int checkboard(void) ++{ ++ printf("Board: i.MX25 MAX PDK (3DS)\n"); ++ return 0; ++} ++ ++int board_eth_init(bd_t *bis) ++{ ++ int rc = -ENODEV; ++#if defined(CONFIG_DRIVER_SMC911X) ++ rc = smc911x_initialize(bis); ++#endif ++ return rc; ++} ++ +diff --git a/board/freescale/mx25_3stack/u-boot.lds b/board/freescale/mx25_3stack/u-boot.lds +new file mode 100644 +index 0000000..8d61156 +--- /dev/null ++++ b/board/freescale/mx25_3stack/u-boot.lds +@@ -0,0 +1,62 @@ ++/* ++ * (c) Copyright 2009 Freescale Semiconductor ++ * ++ * January 2004 - Changed to support H4 device ++ * Copyright (c) 2004 Texas Instruments ++ * ++ * (C) Copyright 2002 ++ * Gary Jennejohn, 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 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 : ++ { ++ board/freescale/mx25_3stack/dcdheader.o (.text) ++ cpu/arm926ejs/start.o (.text) ++ *(.text) ++ } ++ ++ . = 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 = .; ++} +diff --git a/include/configs/mx25_3stack.h b/include/configs/mx25_3stack.h +new file mode 100644 +index 0000000..01a4c03 +--- /dev/null ++++ b/include/configs/mx25_3stack.h +@@ -0,0 +1,200 @@ ++/* ++ * (C) Copyright 2009 Freescale Semiconductor ++ * ++ * (C) Copyright 2004 ++ * Texas Instruments. ++ * Richard Woodruff ++ * Kshitij Gupta ++ * ++ * Configuration settings for the Freescale i.MX31 PDK board. ++ * ++ * 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 __CONFIG_H ++#define __CONFIG_H ++ ++#include ++#include ++ ++/* High Level Configuration Options */ ++#define CONFIG_ARM926EJS 1 /* This is an arm1136 CPU core */ ++#define CONFIG_MX25 1 /* in a mx31 */ ++#define CONFIG_MX25_HCLK_FREQ 24000000 ++#define CONFIG_MX25_CLK32 32768 ++ ++/* IF iMX25 3DS V-1.0 define it */ ++/* #define CONFIG_MX25_3DS_V10 */ ++ ++#ifdef CONFIG_MX25_3DS_V10 ++#define MXC_MEMORY_MDDR ++#endif ++ ++#define CONFIG_DISPLAY_CPUINFO ++#define CONFIG_DISPLAY_BOARDINFO ++ ++#define BOARD_LATE_INIT ++ ++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ ++#define CONFIG_SETUP_MEMORY_TAGS 1 ++#define CONFIG_INITRD_TAG 1 ++ ++/* No support for NAND boot for i.MX31 PDK yet, so we rely on some other ++ * program to initialize the SDRAM. ++ */ ++#define CONFIG_SKIP_RELOCATE_UBOOT ++ ++/* ++ * Size of malloc() pool ++ */ ++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 512 * 1024) ++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* bytes reserved initial data */ ++ ++/* ++ * Hardware drivers ++ */ ++#define CONFIG_HARD_I2C 1 ++#define CONFIG_I2C_MXC 1 ++#define CONFIG_SYS_I2C_PORT I2C1_BASE ++#define CONFIG_SYS_I2C_SPEED 40000 ++#define CONFIG_SYS_I2C_SLAVE 0xfe ++ ++#define CONFIG_MX25_UART 1 ++#define CONFIG_MX25_UART1 1 ++ ++/* allow to overwrite serial and ethaddr */ ++#define CONFIG_ENV_OVERWRITE ++#define CONFIG_CONS_INDEX 1 ++#define CONFIG_BAUDRATE 115200 ++#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200} ++ ++/*********************************************************** ++ * Command definition ++ ***********************************************************/ ++ ++#include ++ ++#define CONFIG_CMD_I2C ++#define CONFIG_CMD_MII ++#define CONFIG_CMD_PING ++/* #define CONFIG_CMD_SPI */ ++/* #define CONFIG_CMD_DATE */ ++#define CONFIG_CMD_NAND ++ ++/* Disabled due to compilation errors in cmd_bootm.c (IMLS seems to require ++ * that CONFIG_NO_FLASH is undefined). ++ */ ++#undef CONFIG_CMD_IMLS ++ ++#define CONFIG_BOOTDELAY 3 ++ ++#define CONFIG_LOADADDR 0x80800000 /* loadaddr env var */ ++ ++#define CONFIG_EXTRA_ENV_SETTINGS \ ++ "netdev=eth0\0" \ ++ "ethprime=fec\0" \ ++ "bootargs_base=setenv bootargs console=ttymxc0,115200\0" \ ++ "bootargs_nfs=setenv bootargs $(bootargs) root=/dev/nfs " \ ++ "ip=dhcp nfsroot=$(serverip):$(nfsrootfs),v3,tcp\0" \ ++ "bootcmd=run bootcmd_net\0" \ ++ "bootcmd_net=run bootargs_base bootargs_mtd bootargs_nfs; " \ ++ "tftpboot 0x81000000 uImage; bootm\0" ++ ++/*Support LAN9217*/ ++/*#define CONFIG_DRIVER_SMC911X 1 ++#define CONFIG_DRIVER_SMC911X_16_BIT 1 ++#define CONFIG_DRIVER_SMC911X_BASE CS5_BASE*/ ++ ++/*#define CONFIG_HAS_ETH1*/ ++#define CONFIG_NET_MULTI 1 ++#define CONFIG_MXC_FEC ++#define CONFIG_MII ++#define CONFIG_DISCOVER_PHY ++ ++#define CONFIG_FEC0_IOBASE FEC_BASE ++#define CONFIG_FEC0_PINMUX -1 ++#define CONFIG_FEC0_PHY_ADDR 0x1F ++#define CONFIG_FEC0_MIIBASE -1 ++ ++/* ++ * Miscellaneous configurable options ++ */ ++#define CONFIG_SYS_LONGHELP /* undef to save memory */ ++#define CONFIG_SYS_PROMPT "uboot> " ++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ ++/* Print Buffer Size */ ++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) ++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ ++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buf Size */ ++ ++#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1 /* memtest works on */ ++#define CONFIG_SYS_MEMTEST_END 0x10000 ++ ++#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR /* default load address */ ++ ++#define CONFIG_SYS_HZ CONFIG_MX25_CLK32 ++ ++#define UBOOT_IMAGE_SIZE 0x40000 ++ ++#define CONFIG_CMDLINE_EDITING 1 ++ ++/*----------------------------------------------------------------------- ++ * Stack sizes ++ * ++ * The stack sizes are set up in start.S using the settings below ++ */ ++#define CONFIG_STACKSIZE (128 * 1024) /* regular stack */ ++ ++/*----------------------------------------------------------------------- ++ * Physical Memory Map ++ */ ++#define CONFIG_NR_DRAM_BANKS 1 ++#define PHYS_SDRAM_1 CSD0_BASE ++ ++/* iMX25 V-1.0 has 128MB but V-1.1 has only 64MB */ ++#ifdef CONFIG_MX25_3DS_V10 ++#define PHYS_SDRAM_1_SIZE (128 * 1024 * 1024) ++#else ++#define PHYS_SDRAM_1_SIZE (64 * 1024 * 1024) ++#endif ++/*----------------------------------------------------------------------- ++ * FLASH and environment organization ++ */ ++ ++#define CONFIG_ENV_IS_IN_NAND 1 ++#define CONFIG_ENV_OFFSET 0x80000 /* 2nd block */ ++#define CONFIG_ENV_SECT_SIZE (256 * 1024) ++#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE ++ ++/*----------------------------------------------------------------------- ++ * NAND FLASH driver setup ++ */ ++#define CONFIG_SYS_NO_FLASH ++#define NAND_MAX_CHIPS 1 ++#define CONFIG_SYS_MAX_NAND_DEVICE 1 ++#define CONFIG_SYS_NAND_BASE 0x40000000 ++ ++/* ++ * JFFS2 partitions TODO: ++ */ ++#undef CONFIG_JFFS2_CMDLINE ++#define CONFIG_JFFS2_DEV "nand0" ++ ++#endif /* __CONFIG_H */ ++ +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0002-ENGR00094618-Update-.gitignore-configure-file.patch +++ uboot-imx-2009.01/debian/patches/0002-ENGR00094618-Update-.gitignore-configure-file.patch @@ -0,0 +1,27 @@ +From 576faf1cc5ceae8938d09ee227a2b29d1556af72 Mon Sep 17 00:00:00 2001 +From: Fred Fan +Date: Mon, 23 Feb 2009 13:32:44 +0800 +Subject: [PATCH] ENGR00094618 Update .gitignore configure file + +Update .gitignore configure file to ignore vim swap and ctags file + +Signed-off-by: Xinyu Chen +--- + .gitignore | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/.gitignore b/.gitignore +index e13fc96..35cb6c4 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -13,6 +13,7 @@ + *~ + *.swp + *.patch ++*.swp + + # + # Top-level generic files +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0009-ENGR00107886-Porting-MX31-MX35-3stack-to-u-boot-V20.patch +++ uboot-imx-2009.01/debian/patches/0009-ENGR00107886-Porting-MX31-MX35-3stack-to-u-boot-V20.patch @@ -0,0 +1,882 @@ +From 4cd144513e763f15d341c7d579d749d14254c44f Mon Sep 17 00:00:00 2001 +From: Fred Fan +Date: Mon, 23 Feb 2009 14:50:43 +0800 +Subject: [PATCH] ENGR00107886 Porting MX31, MX35 3stack to u-boot V2009.01 + +Modify and Verfiy MX31 & MX35 3stack according to the changes in V2009.01 + +Signed-off-by: Fred Fan +--- + board/freescale/mx31_3stack/mx31_3stack.c | 2 +- + board/freescale/mx31_3stack/u-boot.lds | 2 +- + board/freescale/mx35_3stack/mx35_3stack.c | 10 +++ + cpu/arm1136/mx35/generic.c | 14 ++++ + drivers/i2c/mxc_i2c.c | 2 +- + drivers/mtd/nand/mx31_nand.c | 103 ++++++++++++++--------------- + drivers/mtd/nand/mxc_nand.c | 76 ++++++++++----------- + drivers/mtd/nand/nand_ids.c | 2 +- + drivers/net/smc911x.c | 2 - + include/asm-arm/arch-mx35/mxc_nand.h | 6 +- + include/configs/mx31_3stack.h | 50 +++++++------- + include/configs/mx35_3stack.h | 4 +- + net/eth.c | 3 - + 13 files changed, 144 insertions(+), 132 deletions(-) + +diff --git a/board/freescale/mx31_3stack/mx31_3stack.c b/board/freescale/mx31_3stack/mx31_3stack.c +index 33adfd3..c8dd7ce 100644 +--- a/board/freescale/mx31_3stack/mx31_3stack.c ++++ b/board/freescale/mx31_3stack/mx31_3stack.c +@@ -48,7 +48,7 @@ int board_init(void) + mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX); + mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX); + mx31_gpio_mux(MUX_RTS1__UART1_RTS_B); +- mx31_gpio_mux(MUX_RTS1__UART1_CTS_B); ++ mx31_gpio_mux(MUX_CTS1__UART1_CTS_B); + + /* SPI2 */ + mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS2); +diff --git a/board/freescale/mx31_3stack/u-boot.lds b/board/freescale/mx31_3stack/u-boot.lds +index 8b717ff..b26def7 100644 +--- a/board/freescale/mx31_3stack/u-boot.lds ++++ b/board/freescale/mx31_3stack/u-boot.lds +@@ -46,7 +46,7 @@ SECTIONS + drivers/mtd/libmtd.a (.text) + + . = DEFINED(env_offset) ? env_offset : .; +- common/environment.o(.text) ++ common/env_embedded.o(.text) + + *(.text) + } +diff --git a/board/freescale/mx35_3stack/mx35_3stack.c b/board/freescale/mx35_3stack/mx35_3stack.c +index 267e9f1..41163f4 100644 +--- a/board/freescale/mx35_3stack/mx35_3stack.c ++++ b/board/freescale/mx35_3stack/mx35_3stack.c +@@ -24,6 +24,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -269,3 +270,12 @@ int checkboard(void) + printf("]\n"); + return 0; + } ++ ++int board_eth_init(bd_t *bis) ++{ ++ int rc = -ENODEV; ++#if defined(CONFIG_DRIVER_SMC911X) ++ rc = smc911x_initialize(bis); ++#endif ++ return rc; ++} +diff --git a/cpu/arm1136/mx35/generic.c b/cpu/arm1136/mx35/generic.c +index d6ad6d7..b70c3ea 100644 +--- a/cpu/arm1136/mx35/generic.c ++++ b/cpu/arm1136/mx35/generic.c +@@ -24,6 +24,7 @@ + */ + + #include ++#include + #include + #include "crm_regs.h" + +@@ -203,3 +204,16 @@ int print_cpuinfo(void) + return 0; + } + #endif ++ ++/* ++ * Initializes on-chip ethernet controllers. ++ * to override, implement board_eth_init() ++ */ ++int cpu_eth_init(bd_t *bis) ++{ ++ int rc = -ENODEV; ++#if defined(CONFIG_MXC_FEC) ++ rc = mxc_fec_initialize(bis); ++#endif ++ return rc; ++} +diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c +index 860f0be..2b4fcb2 100644 +--- a/drivers/i2c/mxc_i2c.c ++++ b/drivers/i2c/mxc_i2c.c +@@ -58,7 +58,7 @@ + #ifdef CONFIG_SYS_I2C_PORT + # define I2C_BASE CONFIG_SYS_I2C_PORT + #else +-# error "define CFG_I2C_PORT(I2C base address) to use the I2C driver" ++# error "define CONFIG_SYS_I2C_PORT(I2C base address) to use the I2C driver" + #endif + + #define I2C_MAX_TIMEOUT 100000 +diff --git a/drivers/mtd/nand/mx31_nand.c b/drivers/mtd/nand/mx31_nand.c +index 325e0f0..867f347 100644 +--- a/drivers/mtd/nand/mx31_nand.c ++++ b/drivers/mtd/nand/mx31_nand.c +@@ -43,8 +43,7 @@ static int ecc_disabled; + /* + * OOB placement block for use with hardware ecc generation + */ +-static struct nand_oobinfo nand_hw_eccoob_8 = { +- .useecc = MTD_NANDECC_AUTOPL_USR, ++static struct nand_ecclayout nand_hw_eccoob_8 = { + .eccbytes = 5, + .eccpos = {6, 7, 8, 9, 10}, + .oobfree = { +@@ -53,8 +52,7 @@ static struct nand_oobinfo nand_hw_eccoob_8 = { + } + }; + +-static struct nand_oobinfo nand_hw_eccoob_2k = { +- .useecc = MTD_NANDECC_AUTOPL_USR, ++static struct nand_ecclayout nand_hw_eccoob_2k = { + .eccbytes = 20, + .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26, + 38, 39, 40, 41, 42, 54, 55, 56, 57, 58}, +@@ -142,7 +140,7 @@ static void wait_op_done(int max_retries) + udelay(1); + } + if (max_retries <= 0) +- DEBUG(MTD_DEBUG_LEVEL0, "wait: INT not set\n"); ++ MTDDEBUG(MTD_DEBUG_LEVEL0, "wait: INT not set\n"); + } + + /** +@@ -153,7 +151,7 @@ static void wait_op_done(int max_retries) + */ + static void send_cmd(u16 cmd) + { +- DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(0x%x)\n", cmd); ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(0x%x)\n", cmd); + + NFC_FLASH_CMD = (u16) cmd; + NFC_CONFIG2 = NFC_CMD; +@@ -172,7 +170,7 @@ static void send_cmd(u16 cmd) + */ + static void send_addr(u16 addr) + { +- DEBUG(MTD_DEBUG_LEVEL3, "send_addr(0x%x %d)\n", addr); ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(0x%x %d)\n", addr); + + NFC_FLASH_ADDR = addr; + NFC_CONFIG2 = NFC_ADDR; +@@ -190,7 +188,7 @@ static void send_addr(u16 addr) + */ + static void send_prog_page(u8 buf_id) + { +- DEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", nandinfo.oob); ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", nandinfo.oob); + + /* NANDFC buffer 0 is used for page read/write */ + +@@ -227,7 +225,7 @@ static void mxc_nd_correct_error(u8 buf_id, u16 eccpos, int oob) + col = COLPOS(eccpos); /* Get half-word position */ + pos = BITPOS(eccpos); /* Get bit position */ + +- DEBUG(MTD_DEBUG_LEVEL3, ++ MTDDEBUG(MTD_DEBUG_LEVEL3, + "mxc_nd_correct_error (col=%d pos=%d)\n", col, pos); + + /* Set the pointer for main / spare area */ +@@ -253,7 +251,7 @@ static void mxc_nd_correct_ecc(u8 buf_id, int spare) + + /* Read the ECC result */ + ecc_status = NFC_ECC_STATUS_RESULT; +- DEBUG(MTD_DEBUG_LEVEL3, ++ MTDDEBUG(MTD_DEBUG_LEVEL3, + "mxc_nd_correct_ecc (Ecc status=%x)\n", ecc_status); + + if (((ecc_status & 0xC) == MAIN_SINGLEBIT_ERROR) +@@ -298,7 +296,7 @@ static void mxc_nd_correct_ecc(u8 buf_id, int spare) + */ + static void send_read_page(u8 buf_id) + { +- DEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", nandinfo.oob); ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", nandinfo.oob); + + /* NANDFC buffer 0 is used for page read/write */ + NFC_BUF_ADDR = buf_id; +@@ -397,7 +395,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, unsigned char *dat, + u16 ecc_status = NFC_ECC_STATUS_RESULT; + + if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { +- DEBUG(MTD_DEBUG_LEVEL0, ++ MTDDEBUG(MTD_DEBUG_LEVEL0, + "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); + return -1; + } +@@ -467,17 +465,17 @@ static u16 mxc_nand_read_word(struct mtd_info *mtd) + u16 rd_word, ret_val; + volatile u16 *p; + +- DEBUG(MTD_DEBUG_LEVEL3, "mxc_nand_read_word(col = %d)\n", nandinfo.col); ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "mxc_nand_read_word(col = %d)\n", nandinfo.col); + + col = nandinfo.col; + /* Adjust saved column address */ +- if (col < mtd->oobblock && nandinfo.oob) +- col += mtd->oobblock; ++ if (col < mtd->writesize && nandinfo.oob) ++ col += mtd->writesize; + +- if (col < mtd->oobblock) ++ if (col < mtd->writesize) + p = (MAIN_AREA0) + (col >> 1); + else +- p = (SPARE_AREA0) + ((col - mtd->oobblock) >> 1); ++ p = (SPARE_AREA0) + ((col - mtd->writesize) >> 1); + + if (col & 1) { + rd_word = *p; +@@ -510,33 +508,33 @@ static void mxc_nand_write_buf(struct mtd_info *mtd, + int col; + int i = 0; + +- DEBUG(MTD_DEBUG_LEVEL3, ++ MTDDEBUG(MTD_DEBUG_LEVEL3, + "mxc_nand_write_buf(col = %d, len = %d)\n", nandinfo.col, len); + + col = nandinfo.col; + + /* Adjust saved column address */ +- if (col < mtd->oobblock && nandinfo.oob) +- col += mtd->oobblock; ++ if (col < mtd->writesize && nandinfo.oob) ++ col += mtd->writesize; + +- n = mtd->oobblock + mtd->oobsize - col; +- if (len > mtd->oobblock + mtd->oobsize - col) +- DEBUG(MTD_DEBUG_LEVEL1, "Error: too much data.\n"); ++ n = mtd->writesize + mtd->oobsize - col; ++ if (len > mtd->writesize + mtd->oobsize - col) ++ MTDDEBUG(MTD_DEBUG_LEVEL1, "Error: too much data.\n"); + + n = min(len, n); + +- DEBUG(MTD_DEBUG_LEVEL3, ++ MTDDEBUG(MTD_DEBUG_LEVEL3, + "%s:%d: col = %d, n = %d\n", __FUNCTION__, __LINE__, col, n); + + while (n) { + volatile u32 *p; +- if (col < mtd->oobblock) ++ if (col < mtd->writesize) + p = (volatile u32 *)((ulong) (MAIN_AREA0) + (col & ~3)); + else + p = (volatile u32 *)((ulong) (SPARE_AREA0) - +- mtd->oobblock + (col & ~3)); ++ mtd->writesize + (col & ~3)); + +- DEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", + __FUNCTION__, __LINE__, p); + + if (((col | (int)&buf[i]) & 3) || n < 16) { +@@ -578,14 +576,14 @@ static void mxc_nand_write_buf(struct mtd_info *mtd, + + *p = data; + } else { +- int m = mtd->oobblock - col; ++ int m = mtd->writesize - col; + +- if (col >= mtd->oobblock) ++ if (col >= mtd->writesize) + m += mtd->oobsize; + + m = min(n, m) & ~3; + +- DEBUG(MTD_DEBUG_LEVEL3, ++ MTDDEBUG(MTD_DEBUG_LEVEL3, + "%s:%d: n = %d, m = %d, i = %d, col = %d\n", + __FUNCTION__, __LINE__, n, m, i, col); + +@@ -615,7 +613,7 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, unsigned char *buf, int len) + int col; + int i = 0; + +- DEBUG(MTD_DEBUG_LEVEL3, ++ MTDDEBUG(MTD_DEBUG_LEVEL3, + "mxc_nand_read_buf(col = %d, len = %d)\n", nandinfo.col, len); + + col = nandinfo.col; +@@ -623,20 +621,20 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, unsigned char *buf, int len) + * Adjust saved column address + * for nand_read_oob will pass col within oobsize + */ +- if (col < mtd->oobblock && nandinfo.oob) +- col += mtd->oobblock; ++ if (col < mtd->writesize && nandinfo.oob) ++ col += mtd->writesize; + +- n = mtd->oobblock + mtd->oobsize - col; ++ n = mtd->writesize + mtd->oobsize - col; + n = min(len, n); + + while (n) { + volatile u32 *p; + +- if (col < mtd->oobblock) ++ if (col < mtd->writesize) + p = (volatile u32 *)((ulong) (MAIN_AREA0) + (col & ~3)); + else + p = (volatile u32 *)((ulong) (SPARE_AREA0) - +- mtd->oobblock + (col & ~3)); ++ mtd->writesize + (col & ~3)); + + if (((col | (int)&buf[i]) & 3) || n < 16) { + u32 data; +@@ -669,9 +667,9 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, unsigned char *buf, int len) + } + } + } else { +- int m = mtd->oobblock - col; ++ int m = mtd->writesize - col; + +- if (col >= mtd->oobblock) ++ if (col >= mtd->writesize) + m += mtd->oobsize; + + m = min(n, m) & ~3; +@@ -724,7 +722,7 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) + static void mxc_nand_command(struct mtd_info *mtd, unsigned command, + int column, int page_addr) + { +- DEBUG(MTD_DEBUG_LEVEL3, ++ MTDDEBUG(MTD_DEBUG_LEVEL3, + "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", + command, column, page_addr); + +@@ -752,7 +750,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, + break; + + case NAND_CMD_SEQIN: +- if (column >= mtd->oobblock) { ++ if (column >= mtd->writesize) { + /* write oob routine caller */ + if (nandinfo.largepage) { + /* +@@ -766,7 +764,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, + mxc_nand_command(mtd, NAND_CMD_READ0, 0, + page_addr); + } +- nandinfo.col = column - mtd->oobblock; ++ nandinfo.col = column - mtd->writesize; + nandinfo.oob = 1; + /* Set program pointer to spare region */ + if (!nandinfo.largepage) +@@ -878,6 +876,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, + + case NAND_CMD_READID: + send_read_id(); ++ nandinfo.col = column; + break; + + case NAND_CMD_PAGEPROG: +@@ -898,8 +897,8 @@ static int mxc_nand_scan_bbt(struct mtd_info *mtd) + + /* Config before scanning */ + /* Do not rely on NFMS_BIT, set/clear NFMS bit based +- * on mtd->oobblock */ +- if (mtd->oobblock == 2048) ++ * on mtd->writesize */ ++ if (mtd->writesize == 2048) + NFMS |= 1 << NFMS_BIT; + else if ((NFMS >> NFMS_BIT) & 0x1) + NFMS &= ~(1 << NFMS_BIT); +@@ -915,7 +914,7 @@ static int mxc_nand_scan_bbt(struct mtd_info *mtd) + if (nandinfo.largepage) + this->badblock_pattern = &smallpage_memorybased; + else +- this->badblock_pattern = (mtd->oobblock > 512) ? ++ this->badblock_pattern = (mtd->writesize > 512) ? + &largepage_memorybased : &smallpage_memorybased; + } + /* Build bad block table */ +@@ -934,12 +933,12 @@ int board_nand_init(struct nand_chip *nand) + nand->read_buf = mxc_nand_read_buf; + nand->verify_buf = mxc_nand_verify_buf; + nand->scan_bbt = mxc_nand_scan_bbt; +- nand->calculate_ecc = mxc_nand_calculate_ecc; +- nand->correct_data = mxc_nand_correct_data; +- nand->enable_hwecc = mxc_nand_enable_hwecc; +- nand->eccmode = NAND_ECC_HW3_512; +- nand->eccbytes = 512; +- nand->eccsize = 3; ++ nand->ecc.calculate = mxc_nand_calculate_ecc; ++ nand->ecc.correct = mxc_nand_correct_data; ++ nand->ecc.hwctl = mxc_nand_enable_hwecc; ++ nand->ecc.mode = NAND_ECC_HW; ++ nand->ecc.bytes = 3; ++ nand->ecc.size = 512; + + /* Reset NAND */ + NFC_CONFIG1 |= NFC_INT_MSK | NFC_RST | NFC_ECC_EN; +@@ -959,10 +958,10 @@ int board_nand_init(struct nand_chip *nand) + + if ((NFMS >> NFMS_BIT) & 1) { + nandinfo.largepage = 1; +- nand->autooob = &nand_hw_eccoob_2k; ++ nand->ecc.layout = &nand_hw_eccoob_2k; + } else { + nandinfo.largepage = 0; +- nand->autooob = &nand_hw_eccoob_8; ++ nand->ecc.layout = &nand_hw_eccoob_8; + } + + return 0; +diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c +index d458d0a..7e224b7 100644 +--- a/drivers/mtd/nand/mxc_nand.c ++++ b/drivers/mtd/nand/mxc_nand.c +@@ -16,7 +16,6 @@ + #include + #include + #include +-#include + #include + + struct nand_info { +@@ -39,22 +38,19 @@ struct nand_info { + /* + * OOB placement block for use with hardware ecc generation + */ +-static struct nand_oobinfo nand_hw_eccoob_512 = { +- .useecc = MTD_NANDECC_AUTOPL_USR, ++static struct nand_ecclayout nand_hw_eccoob_512 = { + .eccbytes = 9, + .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, + .oobfree = {{0, 4} } + }; + +-static struct nand_oobinfo nand_hw_eccoob_2k = { +- .useecc = MTD_NANDECC_AUTOPL_USR, ++static struct nand_ecclayout nand_hw_eccoob_2k = { + .eccbytes = 9, + .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, + .oobfree = {{2, 4} } + }; + +-static struct nand_oobinfo nand_hw_eccoob_4k = { +- .useecc = MTD_NANDECC_AUTOPL_USR, ++static struct nand_ecclayout nand_hw_eccoob_4k = { + .eccbytes = 9, + .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, + .oobfree = {{2, 4} } +@@ -97,7 +93,7 @@ copy_spare(struct mtd_info *mtd, void *pbuf, void *pspare, int len, int bfrom) + { + u16 i, j; + u16 m = mtd->oobsize; +- u16 n = mtd->oobblock >> 9; ++ u16 n = mtd->writesize >> 9; + u8 *d = (u8 *) pbuf; + u8 *s = (u8 *) pspare; + u16 t = SPARE_LEN; +@@ -144,7 +140,7 @@ static void wait_op_done(int max_retries) + udelay(1); + } + if (max_retries <= 0) +- DEBUG(MTD_DEBUG_LEVEL0, "wait: INT not set\n"); ++ MTDDEBUG(MTD_DEBUG_LEVEL0, "wait: INT not set\n"); + } + + static void send_cmd_atomic(struct mtd_info *mtd, u16 cmd) +@@ -211,7 +207,7 @@ static void send_cmd_interleave(struct mtd_info *mtd, u16 cmd) + u32 page_addr = addr_low >> 16 | addr_high << 16; + u8 *dbuf = mtd->info.data_buf; + u8 *obuf = mtd->info.oob_buf; +- u32 dlen = mtd->oobblock / j; ++ u32 dlen = mtd->writesize / j; + u32 olen = mtd->oobsize / j; + + /* adjust the addr value +@@ -303,7 +299,7 @@ static void send_cmd(struct mtd_info *mtd, u16 cmd) + else + send_cmd_atomic(mtd, cmd); + +- DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(0x%x, %d)\n", cmd); ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(0x%x, %d)\n", cmd); + } + + /*! +@@ -316,7 +312,7 @@ static void send_cmd(struct mtd_info *mtd, u16 cmd) + */ + static void send_addr(u16 addr) + { +- DEBUG(MTD_DEBUG_LEVEL3, "send_addr(0x%x %d)\n", addr); ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(0x%x %d)\n", addr); + + /* fill address */ + raw_write((addr << NFC_FLASH_ADDR_SHIFT), REG_NFC_FLASH_ADDR); +@@ -355,7 +351,7 @@ static void send_prog_page(struct mtd_info *mtd, u8 buf_id) + /* Wait for operation to complete */ + wait_op_done(TROP_US_DELAY); + +- DEBUG(MTD_DEBUG_LEVEL3, "%s\n", __func__); ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "%s\n", __func__); + } + } + +@@ -384,7 +380,7 @@ static void send_read_page(struct mtd_info *mtd, u8 buf_id) + /* Wait for operation to complete */ + wait_op_done(TROP_US_DELAY); + +- DEBUG(MTD_DEBUG_LEVEL3, "%s(%d)\n", __func__, buf_id); ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "%s(%d)\n", __func__, buf_id); + + } + +@@ -511,7 +507,7 @@ static int mxc_nand_ecc_status(struct mtd_info *mtd) + ecc_bit_mask = (IS_4BIT_ECC ? 0x7 : 0xf); + err_limit = (IS_4BIT_ECC ? 0x4 : 0x8); + +- no_subpages = mtd->oobblock >> 9; ++ no_subpages = mtd->writesize >> 9; + + no_subpages /= info->num_of_intlv; + +@@ -527,7 +523,7 @@ static int mxc_nand_ecc_status(struct mtd_info *mtd) + ecc_stat >>= 4; + } while (--no_subpages); + +- DEBUG(MTD_DEBUG_LEVEL3, "%d Symbol Correctable RS-ECC Error\n", ret); ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "%d Symbol Correctable RS-ECC Error\n", ret); + + return ret; + } +@@ -574,9 +570,9 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len) + u8 *data_buf = info->data_buf; + u8 *oob_buf = info->oob_buf; + +- if (mtd->oobblock) { ++ if (mtd->writesize) { + +- int j = mtd->oobblock - col; ++ int j = mtd->writesize - col; + int n = mtd->oobsize + j; + + n = min(n, len); +@@ -589,7 +585,7 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len) + memcpy(buf, &data_buf[col], n); + } + } else { +- col -= mtd->oobblock; ++ col -= mtd->writesize; + memcpy(buf, &oob_buf[col], len); + } + +@@ -598,7 +594,7 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len) + + } else { + /* At flash identify phase, +- * mtd->oobblock has not been ++ * mtd->writesize has not been + * set correctly, it should + * be zero.And len will less 2 + */ +@@ -683,7 +679,7 @@ static void mxc_nand_write_buf(struct mtd_info *mtd, + u16 col = info->col_addr; + u8 *data_buf = info->data_buf; + u8 *oob_buf = info->oob_buf; +- int j = mtd->oobblock - col; ++ int j = mtd->writesize - col; + int n = mtd->oobsize + j; + + n = min(n, len); +@@ -696,7 +692,7 @@ static void mxc_nand_write_buf(struct mtd_info *mtd, + memcpy(&data_buf[col], buf, n); + } + } else { +- col -= mtd->oobblock; ++ col -= mtd->writesize; + memcpy(&oob_buf[col], buf, len); + } + +@@ -773,7 +769,7 @@ static void mxc_do_addr_cycle_auto(struct mtd_info *mtd, int column, + raw_write(page_addr, NFC_FLASH_ADDR0); + } + +- DEBUG(MTD_DEBUG_LEVEL3, ++ MTDDEBUG(MTD_DEBUG_LEVEL3, + "AutoMode:the ADDR REGS value is (0x%x, 0x%x)\n", + raw_read(NFC_FLASH_ADDR0), raw_read(NFC_FLASH_ADDR8)); + #endif +@@ -836,7 +832,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, + struct nand_chip *this = mtd->priv; + struct nand_info *info = this->priv; + +- DEBUG(MTD_DEBUG_LEVEL3, ++ MTDDEBUG(MTD_DEBUG_LEVEL3, + "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", + command, column, page_addr); + /* +@@ -888,7 +884,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, + + case NAND_CMD_PAGEPROG: + if (!info->auto_mode) { +- nfc_memcpy(MAIN_AREA0, info->data_buf, mtd->oobblock); ++ nfc_memcpy(MAIN_AREA0, info->data_buf, mtd->writesize); + copy_spare(mtd, info->oob_buf, SPARE_AREA0, + mtd->oobsize, 0); + } +@@ -923,7 +919,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, + + if (!info->auto_mode) { + mxc_nand_ecc_status(mtd); +- nfc_memcpy(info->data_buf, MAIN_AREA0, mtd->oobblock); ++ nfc_memcpy(info->data_buf, MAIN_AREA0, mtd->writesize); + copy_spare(mtd, info->oob_buf, SPARE_AREA0, + mtd->oobsize, 1); + } +@@ -989,14 +985,14 @@ static int mxc_nand_scan_bbt(struct mtd_info *mtd) + + if (IS_2K_PAGE_NAND) { + NFC_SET_NFMS(1 << NFMS_NF_PG_SZ); +- this->autooob = &nand_hw_eccoob_2k; ++ this->ecc.layout = &nand_hw_eccoob_2k; + info->large_page = 1; + } else if (IS_4K_PAGE_NAND) { + NFC_SET_NFMS(1 << NFMS_NF_PG_SZ); +- this->autooob = &nand_hw_eccoob_4k; ++ this->ecc.layout = &nand_hw_eccoob_4k; + info->large_page = 1; + } else { +- this->autooob = &nand_hw_eccoob_512; ++ this->ecc.layout = &nand_hw_eccoob_512; + info->large_page = 0; + } + +@@ -1012,17 +1008,17 @@ static int mxc_nand_scan_bbt(struct mtd_info *mtd) + */ + mtd->size = this->chipsize; + mtd->erasesize *= info->num_of_intlv; +- mtd->oobblock *= info->num_of_intlv; ++ mtd->writesize *= info->num_of_intlv; + mtd->oobsize *= info->num_of_intlv; +- this->page_shift = ffs(mtd->oobblock) - 1; ++ this->page_shift = ffs(mtd->writesize) - 1; + this->bbt_erase_shift = + this->phys_erase_shift = ffs(mtd->erasesize) - 1; + this->chip_shift = ffs(this->chipsize) - 1; +- /*this->oob_poi = this->buffers->databuf + mtd->oobblock;*/ ++ /*this->oob_poi = this->buffers->databuf + mtd->writesize;*/ + } + + /* propagate ecc.layout to mtd_info */ +- memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); ++ mtd->ecclayout = this->ecc.layout; + + /* jffs2 not write oob */ + /*mtd->flags &= ~MTD_OOB_WRITEABLE;*/ +@@ -1035,7 +1031,7 @@ static int mxc_nand_scan_bbt(struct mtd_info *mtd) + this->options |= NAND_USE_FLASH_BBT; + + if (!this->badblock_pattern) { +- this->badblock_pattern = (mtd->oobblock > 512) ? ++ this->badblock_pattern = (mtd->writesize > 512) ? + &largepage_memorybased : &smallpage_memorybased; + } + +@@ -1136,12 +1132,12 @@ int board_nand_init(struct nand_chip *nand) + this->read_buf = mxc_nand_read_buf; + this->verify_buf = mxc_nand_verify_buf; + this->scan_bbt = mxc_nand_scan_bbt; +- this->calculate_ecc = mxc_nand_calculate_ecc; +- this->correct_data = mxc_nand_correct_data; +- this->enable_hwecc = mxc_nand_enable_hwecc; +- this->eccmode = NAND_ECC_HW3_512; +- this->eccbytes = 9; +- this->eccsize = 512; ++ this->ecc.calculate = mxc_nand_calculate_ecc; ++ this->ecc.correct = mxc_nand_correct_data; ++ this->ecc.hwctl = mxc_nand_enable_hwecc; ++ this->ecc.mode = NAND_ECC_HW; ++ this->ecc.bytes = 9; ++ this->ecc.size = 512; + + return 0; + +diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c +index f48cccb..3fd4220 100644 +--- a/drivers/mtd/nand/nand_ids.c ++++ b/drivers/mtd/nand/nand_ids.c +@@ -23,7 +23,7 @@ + * 512 512 Byte page size + */ + struct nand_flash_dev nand_flash_ids[] = { +-#if 0 ++#ifdef CONFIG_MTD_NAND_MUSEUM_IDS + {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, + {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0}, + {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0}, +diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c +index b5b2f92..790f35f 100644 +--- a/drivers/net/smc911x.c ++++ b/drivers/net/smc911x.c +@@ -736,5 +736,3 @@ int smc911x_initialize(bd_t *bis) + return 0; + } + #endif +- +-#endif +diff --git a/include/asm-arm/arch-mx35/mxc_nand.h b/include/asm-arm/arch-mx35/mxc_nand.h +index f4d2ae7..bc04c09 100644 +--- a/include/asm-arm/arch-mx35/mxc_nand.h ++++ b/include/asm-arm/arch-mx35/mxc_nand.h +@@ -25,11 +25,11 @@ + + #include + +-#define IS_2K_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) \ ++#define IS_2K_PAGE_NAND ((mtd->writesize / info->num_of_intlv) \ + == NAND_PAGESIZE_2KB) +-#define IS_4K_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) \ ++#define IS_4K_PAGE_NAND ((mtd->writesize / info->num_of_intlv) \ + == NAND_PAGESIZE_4KB) +-#define IS_LARGE_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) > 512) ++#define IS_LARGE_PAGE_NAND ((mtd->writesize / info->num_of_intlv) > 512) + + #define NAND_PAGESIZE_2KB 2048 + #define NAND_PAGESIZE_4KB 4096 +diff --git a/include/configs/mx31_3stack.h b/include/configs/mx31_3stack.h +index 887ffe3..e90df0a 100644 +--- a/include/configs/mx31_3stack.h ++++ b/include/configs/mx31_3stack.h +@@ -44,27 +44,27 @@ + /* + * Size of malloc() pool + */ +-#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128 * 1024) +-#define CFG_GBL_DATA_SIZE 128 ++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 512 * 1024) ++#define CONFIG_SYS_GBL_DATA_SIZE 128 + + /* + * Hardware drivers + */ + + #define CONFIG_MX31_UART 1 +-#define CFG_MX31_UART1 1 ++#define CONFIG_SYS_MX31_UART1 1 + +-#define CONFIG_HARD_SPI 1 + #define CONFIG_MXC_SPI 1 +-#define CONFIG_MXC_SPI_IFACE 1 + + #define CONFIG_RTC_MC13783 1 ++#define CONFIG_MC13783_SPI_BUS 1 ++#define CONFIG_MC13783_SPI_CS 0 + + /* allow to overwrite serial and ethaddr */ + #define CONFIG_ENV_OVERWRITE + #define CONFIG_CONS_INDEX 1 + #define CONFIG_BAUDRATE 115200 +-#define CFG_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200} ++#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200} + + /*********************************************************** + * Command definition +@@ -99,32 +99,31 @@ + "tftpboot ${loadaddr} ${tftp_server}:${kernel}; bootm\0" + + /* configure for smc91xx debug board ethernet */ +-#define CONFIG_NET_MULTI 1 + #define CONFIG_DRIVER_SMC911X 1 ++#define CONFIG_DRIVER_SMC911X_16_BIT 1 + #define CONFIG_DRIVER_SMC911X_BASE CS5_BASE +-#define CONFIG_DRIVER_SMC911X_32_BIT 1 + + #define CONFIG_ARP_TIMEOUT 200UL + + /* + * Miscellaneous configurable options + */ +-#define CFG_LONGHELP /* undef to save memory */ +-#define CFG_PROMPT "=> " +-#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ ++#define CONFIG_SYS_LONGHELP /* undef to save memory */ ++#define CONFIG_SYS_PROMPT "=> " ++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ + /* Print Buffer Size */ +-#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) +-#define CFG_MAXARGS 16 /* max number of command args */ +-#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ ++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) ++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ ++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ + +-#define CFG_MEMTEST_START 0 /* memtest works on */ +-#define CFG_MEMTEST_END 0x10000 ++#define CONFIG_SYS_MEMTEST_START 0 /* memtest works on */ ++#define CONFIG_SYS_MEMTEST_END 0x10000 + +-#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */ ++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */ + +-#define CFG_LOAD_ADDR CONFIG_LOADADDR ++#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR + +-#define CFG_HZ CONFIG_MX31_CLK32 ++#define CONFIG_SYS_HZ CONFIG_MX31_CLK32 + + #define CONFIG_CMDLINE_EDITING 1 + +@@ -146,15 +145,14 @@ + * TODO: NAND Flash configure + */ + +-#define CFG_NO_FLASH ++#define CONFIG_SYS_NO_FLASH + #define NAND_MAX_CHIPS 1 +-#define CFG_MAX_NAND_DEVICE 1 +-#define CFG_NAND_BASE 0x40000000 +- +-#define CFG_ENV_IS_IN_NAND 1 +-#define CFG_ENV_OFFSET 0x40000 /* 2nd block */ +-#define CFG_ENV_SIZE (128*1024) ++#define CONFIG_SYS_MAX_NAND_DEVICE 1 ++#define CONFIG_SYS_NAND_BASE 0x40000000 + ++#define CONFIG_ENV_IS_IN_NAND 1 ++#define CONFIG_ENV_OFFSET 0x40000 /* 2nd block */ ++#define CONFIG_ENV_SIZE (128*1024) + /* + * JFFS2 partitions TODO: + */ +diff --git a/include/configs/mx35_3stack.h b/include/configs/mx35_3stack.h +index a141ad0..58b098e 100644 +--- a/include/configs/mx35_3stack.h ++++ b/include/configs/mx35_3stack.h +@@ -217,8 +217,8 @@ + * NAND FLASH driver setup + */ + #define NAND_MAX_CHIPS 1 +-#define CFG_MAX_NAND_DEVICE 1 +-#define CFG_NAND_BASE 0x40000000 ++#define CONFIG_SYS_MAX_NAND_DEVICE 1 ++#define CONFIG_SYS_NAND_BASE 0x40000000 + /* + * JFFS2 partitions + */ +diff --git a/net/eth.c b/net/eth.c +index 32af7da..8a2bd5a 100644 +--- a/net/eth.c ++++ b/net/eth.c +@@ -495,9 +495,6 @@ int eth_initialize(bd_t *bis) + #if defined(CONFIG_DRIVER_TI_EMAC) + davinci_eth_miiphy_initialize(bis); + #endif +-#if defined(CONFIG_DRIVER_SMC911X) +- smc911x_initialize(bis); +-#endif + return 0; + } + #endif +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0003-ENGR00094619-Support-i.MX31-3stack-board.patch +++ uboot-imx-2009.01/debian/patches/0003-ENGR00094619-Support-i.MX31-3stack-board.patch @@ -0,0 +1,2186 @@ +From e5b3a2fa60a067f7853b7f2bfb81e8c4e1ba68c5 Mon Sep 17 00:00:00 2001 +From: Fred Fan +Date: Mon, 23 Feb 2009 13:34:09 +0800 +Subject: [PATCH] ENGR00094619 Support i.MX31 3stack board + +Support boot from NAND Flash +Add driver for i.MX31 NFC +Upgate U-Boot to support NAND boot + +Signed-off-by: Xinyu Chen +--- + Makefile | 3 + + board/freescale/mx31_3stack/Makefile | 47 ++ + board/freescale/mx31_3stack/config.mk | 1 + + board/freescale/mx31_3stack/lowlevel_init.S | 248 +++++++ + board/freescale/mx31_3stack/mx31_3stack.c | 75 ++ + board/freescale/mx31_3stack/u-boot.lds | 72 ++ + cpu/arm1136/mx31/Makefile | 4 + + cpu/arm1136/mx31/interrupts.c | 17 +- + cpu/arm1136/mx31/nand_load.S | 160 +++++ + cpu/arm1136/start.S | 151 +++-- + drivers/mtd/nand/Makefile | 1 + + drivers/mtd/nand/mx31_nand.c | 969 +++++++++++++++++++++++++++ + include/asm-arm/arch-mx31/mx31-regs.h | 101 +++ + include/configs/mx31_3stack.h | 165 +++++ + 14 files changed, 1938 insertions(+), 76 deletions(-) + +diff --git a/Makefile b/Makefile +index 16744f5..f02e9c3 100644 +--- a/Makefile ++++ b/Makefile +@@ -2964,6 +2964,9 @@ imx31_phycore_config : unconfig + mx31ads_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm1136 mx31ads freescale mx31 + ++mx31_3stack_config : unconfig ++ @$(MKCONFIG) $(@:_config=) arm arm1136 mx31_3stack freescale mx31 ++ + mx35_3stack_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm1136 mx35_3stack freescale mx35 + +diff --git a/board/freescale/mx31_3stack/Makefile b/board/freescale/mx31_3stack/Makefile +new file mode 100644 +index 0000000..836c19c +--- /dev/null ++++ b/board/freescale/mx31_3stack/Makefile +@@ -0,0 +1,47 @@ ++# ++# Copyright (C) 2008, Guennadi Liakhovetski ++# ++# 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 := mx31_3stack.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 .depend ++ ++######################################################################### ++ ++# defines $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +diff --git a/board/freescale/mx31_3stack/config.mk b/board/freescale/mx31_3stack/config.mk +new file mode 100644 +index 0000000..d34dc02 +--- /dev/null ++++ b/board/freescale/mx31_3stack/config.mk +@@ -0,0 +1 @@ ++TEXT_BASE = 0x87f00000 +diff --git a/board/freescale/mx31_3stack/lowlevel_init.S b/board/freescale/mx31_3stack/lowlevel_init.S +new file mode 100644 +index 0000000..bd0de81 +--- /dev/null ++++ b/board/freescale/mx31_3stack/lowlevel_init.S +@@ -0,0 +1,248 @@ ++/* ++ * Copyright (C) 2008, Guennadi Liakhovetski ++ * Copyright (C) 2008, Freescale Semiconductor ++ * Modifications for MX31 3Stack board ++ * ++ * 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 ++ ++.macro REG reg, val ++ ldr r2, =\reg ++ ldr r3, =\val ++ str r3, [r2] ++.endm ++ ++.macro REG8 reg, val ++ ldr r2, =\reg ++ ldr r3, =\val ++ strb r3, [r2] ++.endm ++ ++.macro DELAY loops ++ ldr r2, =\loops ++1: ++ subs r2, r2, #1 ++ nop ++ bcs 1b ++.endm ++ ++.macro init_aips ++ /* ++ * Set all MPROTx to be non-bufferable, trusted for R/W, ++ * not forced to user-mode. ++ */ ++ ldr r0, =0x43F00000 ++ ldr r1, =0x77777777 ++ str r1, [r0, #0x00] ++ str r1, [r0, #0x04] ++ ldr r0, =0x53F00000 ++ str r1, [r0, #0x00] ++ str r1, [r0, #0x04] ++ ++ /* ++ * Clear the on and off peripheral modules Supervisor Protect bit ++ * for SDMA to access them. Did not change the AIPS control registers ++ * (offset 0x20) access type ++ */ ++ ldr r0, =0x43F00000 ++ ldr r1, =0x0 ++ str r1, [r0, #0x40] ++ str r1, [r0, #0x44] ++ str r1, [r0, #0x48] ++ str r1, [r0, #0x4C] ++ ldr r1, [r0, #0x50] ++ and r1, r1, #0x00FFFFFF ++ str r1, [r0, #0x50] ++ ++ ldr r0, =0x53F00000 ++ ldr r1, =0x0 ++ str r1, [r0, #0x40] ++ str r1, [r0, #0x44] ++ str r1, [r0, #0x48] ++ str r1, [r0, #0x4C] ++ ldr r1, [r0, #0x50] ++ and r1, r1, #0x00FFFFFF ++ str r1, [r0, #0x50] ++.endm /* init_aips */ ++ ++.macro init_max ++ ldr r0, =0x43F04000 ++ /* MPR - priority is M4 > M2 > M3 > M5 > M0 > M1 */ ++ ldr r1, =0x00302154 ++ str r1, [r0, #0x000] /* for S0 */ ++ str r1, [r0, #0x100] /* for S1 */ ++ str r1, [r0, #0x200] /* for S2 */ ++ str r1, [r0, #0x300] /* for S3 */ ++ str r1, [r0, #0x400] /* for S4 */ ++ /* SGPCR - always park on last master */ ++ ldr r1, =0x10 ++ str r1, [r0, #0x010] /* for S0 */ ++ str r1, [r0, #0x110] /* for S1 */ ++ str r1, [r0, #0x210] /* for S2 */ ++ str r1, [r0, #0x310] /* for S3 */ ++ str r1, [r0, #0x410] /* for S4 */ ++ /* MGPCR - restore default values */ ++ ldr r1, =0x0 ++ str r1, [r0, #0x800] /* for M0 */ ++ str r1, [r0, #0x900] /* for M1 */ ++ str r1, [r0, #0xA00] /* for M2 */ ++ str r1, [r0, #0xB00] /* for M3 */ ++ str r1, [r0, #0xC00] /* for M4 */ ++ str r1, [r0, #0xD00] /* for M5 */ ++.endm /* init_max */ ++ ++.macro init_m3if ++ /* Configure M3IF registers */ ++ ldr r1, =0xB8003000 ++ /* ++ * M3IF Control Register (M3IFCTL) ++ * MRRP[0] = L2CC0 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[1] = L2CC1 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[2] = MBX not on priority list (0 << 0) = 0x00000000 ++ * MRRP[3] = MAX1 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[4] = SDMA not on priority list (0 << 0) = 0x00000000 ++ * MRRP[5] = MPEG4 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[6] = IPU1 on priority list (1 << 6) = 0x00000040 ++ * MRRP[7] = IPU2 not on priority list (0 << 0) = 0x00000000 ++ * ------------ ++ * 0x00000040 ++ */ ++ ldr r0, =0x00000040 ++ str r0, [r1] /* M3IF control reg */ ++.endm /* init_m3if */ ++ ++.macro init_drive_strength ++ /* ++ * Disable maximum drive strength SDRAM/DDR lines by clearing DSE1 bits ++ * in SW_PAD_CTL registers ++ */ ++ ++ /* SDCLK */ ++ ldr r1, =0x43FAC200 ++ ldr r0, [r1, #0x6C] ++ bic r0, r0, #(1 << 12) ++ str r0, [r1, #0x6C] ++ ++ /* CAS */ ++ ldr r0, [r1, #0x70] ++ bic r0, r0, #(1 << 22) ++ str r0, [r1, #0x70] ++ ++ /* RAS */ ++ ldr r0, [r1, #0x74] ++ bic r0, r0, #(1 << 2) ++ str r0, [r1, #0x74] ++ ++ /* CS2 (CSD0) */ ++ ldr r0, [r1, #0x7C] ++ bic r0, r0, #(1 << 22) ++ str r0, [r1, #0x7C] ++ ++ /* DQM3 */ ++ ldr r0, [r1, #0x84] ++ bic r0, r0, #(1 << 22) ++ str r0, [r1, #0x84] ++ ++ /* DQM2, DQM1, DQM0, SD31-SD0, A25-A0, MA10 (0x288..0x2DC) */ ++ ldr r2, =22 /* (0x2E0 - 0x288) / 4 = 22 */ ++pad_loop: ++ ldr r0, [r1, #0x88] ++ bic r0, r0, #(1 << 22) ++ bic r0, r0, #(1 << 12) ++ bic r0, r0, #(1 << 2) ++ str r0, [r1, #0x88] ++ add r1, r1, #4 ++ subs r2, r2, #0x1 ++ bne pad_loop ++.endm /* init_drive_strength */ ++ ++.section ".text.init", "x" ++ ++.globl lowlevel_init ++lowlevel_init: ++ ++ ldr r0, =0x40000015 /* start from AIPS 2GB region */ ++ mcr p15, 0, r0, c15, c2, 4 ++ ++ init_aips ++ ++ init_max ++ ++ init_m3if ++ ++ init_drive_strength ++ ++ /* Image Processing Unit: */ ++ /* Too early to switch display on? */ ++ REG IPU_CONF, IPU_CONF_DI_EN ++ /* Clock Control Module: */ ++ REG CCM_CCMR, 0x074B0BF5 /* Use CKIH, MCU PLL off */ ++ ++ DELAY 0x40000 ++ ++ REG CCM_CCMR, 0x074B0BF5 | CCMR_MPE /* MCU PLL on */ ++ /* Switch to MCU PLL */ ++ REG CCM_CCMR, (0x074B0BF5 | CCMR_MPE) & ~CCMR_MDS ++ ++ /* 532-133-66.5 */ ++ ldr r0, =CCM_BASE ++ ldr r1, =0xFF871D58 ++ /* PDR0 */ ++ str r1, [r0, #0x4] ++ ldr r1, MPCTL_PARAM_532 ++ /* MPCTL */ ++ str r1, [r0, #0x10] ++ ++ /* Set UPLL=240MHz, USB=60MHz */ ++ ldr r1, =0x49FCFE7F ++ /* PDR1 */ ++ str r1, [r0, #0x8] ++ ldr r1, UPCTL_PARAM_240 ++ /* UPCTL */ ++ str r1, [r0, #0x14] ++ /* default CLKO to 1/8 of the ARM core */ ++ mov r1, #0x000002C0 ++ add r1, r1, #0x00000006 ++ /* COSR */ ++ str r1, [r0, #0x1c] ++ ++ /* initial CSD0 MDDR */ ++ REG 0xB8001004, 0x0075E73A ++ REG 0xB8001010, 0x00000002 /* reset */ ++ REG 0xB8001010, 0x00000004 ++ DELAY 0x10000 ++ ++ REG 0xB8001000, 0x92100000 ++ REG 0x80000F00, 0x0 ++ REG 0xB8001000, 0xA2100000 ++ REG 0x80000000, 0x0 ++ REG 0xB8001000, 0xB2100000 ++ REG8 0x80000033, 0x0 ++ REG8 0x81000000, 0xff ++ REG 0xB8001000, 0x82226080 ++ REG 0x80000000, 0x0 ++ REG 0xB8001010, 0x0000000c ++ ++ mov r13, ip ++ /* copy blocks of total uboot to DDR */ ++ b mxc_nand_load ++ ++MPCTL_PARAM_532: ++ .word (((1-1) << 26) + ((52-1) << 16) + (10 << 10) + (12 << 0)) ++UPCTL_PARAM_240: ++ .word (((2-1) << 26) + ((13-1) << 16) + (9 << 10) + (3 << 0)) +diff --git a/board/freescale/mx31_3stack/mx31_3stack.c b/board/freescale/mx31_3stack/mx31_3stack.c +new file mode 100644 +index 0000000..33adfd3 +--- /dev/null ++++ b/board/freescale/mx31_3stack/mx31_3stack.c +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (C) 2008, Guennadi Liakhovetski ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ * Modifications for MX31 3Stack board ++ * ++ * 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 ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++int dram_init(void) ++{ ++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1; ++ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; ++ ++ return 0; ++} ++ ++int board_init(void) ++{ ++ /* CS5: Debug board for ethernet */ ++ __REG(CSCR_U(5)) = 0x0000D843; ++ __REG(CSCR_L(5)) = 0x22252521; ++ __REG(CSCR_A(5)) = 0x22220A00; ++ ++ /* setup pins for UART1 */ ++ mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX); ++ mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX); ++ mx31_gpio_mux(MUX_RTS1__UART1_RTS_B); ++ mx31_gpio_mux(MUX_RTS1__UART1_CTS_B); ++ ++ /* SPI2 */ ++ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS2); ++ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SCLK); ++ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SPI_RDY); ++ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_MOSI); ++ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_MISO); ++ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS0); ++ mx31_gpio_mux((MUX_CTL_FUNC << 8) | MUX_CTL_CSPI2_SS1); ++ ++ /* start SPI2 clock */ ++ __REG(CCM_CGR2) = __REG(CCM_CGR2) | (3 << 4); ++ ++ gd->bd->bi_arch_number = MACH_TYPE_MX31_3DS; /* board id for linux */ ++ gd->bd->bi_boot_params = 0x80000100; /* adress of boot parameters */ ++ ++ return 0; ++} ++ ++int checkboard(void) ++{ ++ printf("Board: MX31 3Stack\n"); ++ return 0; ++} +diff --git a/board/freescale/mx31_3stack/u-boot.lds b/board/freescale/mx31_3stack/u-boot.lds +new file mode 100644 +index 0000000..8b717ff +--- /dev/null ++++ b/board/freescale/mx31_3stack/u-boot.lds +@@ -0,0 +1,72 @@ ++/* ++ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. ++ * ++ * (C) Copyright 2002 ++ * Gary Jennejohn, 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 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(reset) ++SECTIONS ++{ ++ . = 0x00000000; ++ ++ . = ALIGN(4); ++ .text : ++ { ++ /* WARNING - the following is hand-optimized to fit within */ ++ /* the sector layout of our flash chips! XXX FIXME XXX */ ++ ++ * (.text.head) /* arm reset handler */ ++ * (.text.init) /* lowlevel initial */ ++ * (.text.load) /* nand copy and load */ ++ * (.text.setup) ++ board/freescale/mx31_3stack/libmx31_3stack.a (.text) ++ lib_arm/libarm.a (.text) ++ net/libnet.a (.text) ++ drivers/mtd/libmtd.a (.text) ++ ++ . = DEFINED(env_offset) ? env_offset : .; ++ common/environment.o(.text) ++ ++ *(.text) ++ } ++ ++ . = 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 = .; ++} +diff --git a/cpu/arm1136/mx31/Makefile b/cpu/arm1136/mx31/Makefile +index b648ffd..56313e0 100644 +--- a/cpu/arm1136/mx31/Makefile ++++ b/cpu/arm1136/mx31/Makefile +@@ -27,6 +27,10 @@ LIB = $(obj)lib$(SOC).a + + COBJS = interrupts.o serial.o generic.o + ++ifdef CONFIG_NAND_BOOT ++SOBJS = nand_load.o ++endif ++ + SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) + OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +diff --git a/cpu/arm1136/mx31/interrupts.c b/cpu/arm1136/mx31/interrupts.c +index ab7202f..7ad7001 100644 +--- a/cpu/arm1136/mx31/interrupts.c ++++ b/cpu/arm1136/mx31/interrupts.c +@@ -34,10 +34,11 @@ + #define GPTCNT __REG(TIMER_BASE + 0x24) /* Counter register */ + + /* General purpose timers bitfields */ +-#define GPTCR_SWR (1 << 15) /* Software reset */ +-#define GPTCR_FRR (1 << 9) /* Freerun / restart */ +-#define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source */ +-#define GPTCR_TEN 1 /* Timer enable */ ++#define GPTCR_SWR (1<<15) /* Software reset */ ++#define GPTCR_FRR (1<<9) /* Freerun / restart */ ++#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ ++#define GPTCR_TEN (1) /* Timer enable */ ++#define GPTCR_ENMODE (1<<1) /* gpt enable mode */ + + static ulong timestamp; + static ulong lastinc; +@@ -93,15 +94,13 @@ static inline unsigned long long us_to_tick(unsigned long long us) + /* The 32768Hz 32-bit timer overruns in 131072 seconds */ + int interrupt_init (void) + { +- int i; +- + /* setup GP Timer 1 */ + GPTCR = GPTCR_SWR; +- for (i = 0; i < 100; i++) +- GPTCR = 0; /* We have no udelay by now */ ++ while (GPTCR & GPTCR_SWR) ++ ; + GPTPR = 0; /* 32Khz */ + /* Freerun Mode, PERCLK1 input */ +- GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; ++ GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN | GPTCR_ENMODE; + + return 0; + } +diff --git a/cpu/arm1136/mx31/nand_load.S b/cpu/arm1136/mx31/nand_load.S +new file mode 100644 +index 0000000..c0d099a +--- /dev/null ++++ b/cpu/arm1136/mx31/nand_load.S +@@ -0,0 +1,160 @@ ++/* ++ * Copyright (C) 2008 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++ ++.section ".text.load", "x" ++ ++.macro wait_op_done ++1: ldrh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF] ++ ands r3, r3, #NAND_FLASH_CONFIG2_INT_DONE ++ beq 1b ++.endm ++ ++data_output: ++ strh r8, [r12, #RAM_BUFFER_ADDRESS_REG_OFF] ++ mov r3, #FDO_PAGE_SPARE_VAL ++ strh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF] ++ wait_op_done ++ bx lr ++ ++send_addr: ++ strh r3, [r12, #NAND_FLASH_ADD_REG_OFF] ++ mov r3, #NAND_FLASH_CONFIG2_FADD_EN ++ strh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF] ++ wait_op_done ++ bx lr ++ ++send_cmd: ++ strh r3, [r12, #NAND_FLASH_CMD_REG_OFF] ++ mov r3, #NAND_FLASH_CONFIG2_FCMD_EN ++ strh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF] ++ wait_op_done ++ bx lr ++ ++ ++nand_read_page: ++ ++ mov r7, lr ++ ++ mov r3, #0x0 ++ /* send command */ ++ bl send_cmd ++ /* 5 cycles address input */ ++ mov r3, #0x0 ++ bl send_addr ++ mov r3, #0x0 ++ bl send_addr ++ mov r3, r0 ++ bl send_addr ++ mov r3, #0x0 ++ bl send_addr ++ mov r3, #0x0 ++ bl send_addr ++ /* confirm read */ ++ mov r3, #0x30 ++ bl send_cmd ++ /* data output */ ++ mov r8, #0x0 ++ mov r4, #0x4 ++1: ++ bl data_output ++ add r8, r8, #0x01 ++ cmp r8, r4 ++ bne 1b ++ ldrh r3, [r12, #ECC_STATUS_RESULT_REG_OFF] ++ tst r3, #0x0a ++ bne . ++ mov pc, r7 ++ ++.global mxc_nand_load ++mxc_nand_load: ++ ++ /* Copy image from flash to SDRAM first */ ++ mov r0, #NFC_BASE_ADDR ++ add r12, r0, #0xE00 /* register */ ++ add r2, r0, #0x800 /* 2K */ ++ ldr r1, __TEXT_BASE ++ ++1: ldmia r0!, {r3-r10} ++ stmia r1!, {r3-r10} ++ cmp r0, r2 ++ blo 1b ++ /* Jump to SDRAM */ ++ ldr r1, =0x0FFF ++ and r0, pc, r1 /* offset of pc */ ++ ldr r1, __TEXT_BASE ++ add r1, r1, #0x10 ++ add pc, r0, r1 ++ nop ++ nop ++ nop ++ nop ++ ++nand_copy_block: ++ ++ /* wait for boot complete */ ++4: ++ ldrh r3, [r12, #NAND_FLASH_CONFIG2_REG_OFF] ++ tst r3, #0x8000 ++ beq 4b ++ ++ /* unlock buffer and blocks */ ++ mov r3, #0x02 ++ strh r3, [r12, #NFC_CONFIGURATION_REG_OFF] ++ mov r3, #0x0 ++ strh r3, [r12, #UNLOCK_START_BLK_ADD_REG_OFF] ++ mov r3, #0x800 ++ strh r3, [r12, #UNLOCK_END_BLK_ADD_REG_OFF] ++ mov r3, #0x04 ++ strh r3, [r12, #NF_WR_PROT_REG_OFF] ++ mov r3, #0x10 ++ strh r3, [r12, #NAND_FLASH_CONFIG1_REG_OFF] ++ ++ /* read 1 block, 256K */ ++ mov r0, #0x01 /* page offset */ ++ ldr r11, __TEXT_BASE ++ add r11, r11, #0x800 ++ ++ mov r1, #NFC_BASE_ADDR ++ add r2, r1, #0x800 ++2: ++ bl nand_read_page /* r0, r1, r2, r11 has been used */ ++ /* copy data from internal buffer */ ++3: ldmia r1!, {r3-r10} ++ stmia r11!, {r3-r10} ++ cmp r1, r2 ++ blo 3b ++ ++ add r0, r0, #0x01 ++ cmp r0, #0x80 ++ mov r1, #NFC_BASE_ADDR ++ bne 2b ++ ++ /* set pc to _set_env */ ++ ldr r11, __TEXT_BASE ++ ldr r1, =0x7FF ++ /* correct the lr */ ++ and r13, r13, r1 ++ add r13, r13, r11 ++ mov pc, r13 ++ ++__TEXT_BASE: ++ .word TEXT_BASE +diff --git a/cpu/arm1136/start.S b/cpu/arm1136/start.S +index e622338..9d2ea1e 100644 +--- a/cpu/arm1136/start.S ++++ b/cpu/arm1136/start.S +@@ -85,40 +85,15 @@ _end_vect: + ************************************************************************* + */ + +-_TEXT_BASE: +- .word TEXT_BASE +- +-.globl _armboot_start +-_armboot_start: +- .word _start +- + /* +- * These are defined in the board-specific linker script. ++ * the actual reset code + */ +-.globl _bss_start +-_bss_start: +- .word __bss_start +- +-.globl _bss_end +-_bss_end: +- .word _end +- +-#ifdef CONFIG_USE_IRQ +-/* IRQ stack memory (calculated at run-time) */ +-.globl IRQ_STACK_START +-IRQ_STACK_START: +- .word 0x0badc0de + +-/* IRQ stack memory (calculated at run-time) */ +-.globl FIQ_STACK_START +-FIQ_STACK_START: +- .word 0x0badc0de ++#ifdef CONFIG_NAND_BOOT ++.section ".text.head", "x" + #endif + +-/* +- * the actual reset code +- */ +- ++.globl reset + reset: + /* + * set the cpu to SVC32 mode +@@ -150,6 +125,86 @@ next: + #ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit + #endif ++ b setup_env ++ ++/* ++ ************************************************************************* ++ * ++ * CPU_init_critical registers ++ * ++ * setup important registers ++ * setup memory timing ++ * ++ ************************************************************************* ++ */ ++cpu_init_crit: ++ /* ++ * flush v4 I/D caches ++ */ ++ mov r0, #0 ++ mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ ++ mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ ++ ++ /* ++ * disable MMU stuff and caches ++ */ ++ mrc p15, 0, r0, c1, c0, 0 ++ bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) ++ bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) ++ orr r0, r0, #0x00000002 @ set bit 2 (A) Align ++ orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache ++ mcr p15, 0, r0, c1, c0, 0 ++ ++ /* ++ * Jump to board specific initialization... The Mask ROM will have already initialized ++ * basic memory. Go here to bump up clock rate and handle wake up conditions. ++ */ ++ mov ip, lr /* persevere link reg across call */ ++ bl lowlevel_init /* go setup pll,mux,memory */ ++ mov lr, ip /* restore link */ ++ mov pc, lr /* back to my caller */ ++ ++ ++#ifdef CONFIG_NAND_BOOT ++.section ".text.setup" ++#endif ++ ++.globl _TEST_BASE ++_TEXT_BASE: ++ .word TEXT_BASE ++ ++.globl _armboot_start ++_armboot_start: ++#ifndef CONFIG_NAND_BOOT ++ .word _start ++#else ++ .word reset ++#endif ++ ++/* ++ * These are defined in the board-specific linker script. ++ */ ++.globl _bss_start ++_bss_start: ++ .word __bss_start ++ ++.globl _bss_end ++_bss_end: ++ .word _end ++ ++#ifdef CONFIG_USE_IRQ ++/* IRQ stack memory (calculated at run-time) */ ++.globl IRQ_STACK_START ++IRQ_STACK_START: ++ .word 0x0badc0de ++ ++/* IRQ stack memory (calculated at run-time) */ ++.globl FIQ_STACK_START ++FIQ_STACK_START: ++ .word 0x0badc0de ++#endif ++ ++setup_env: + + #ifndef CONFIG_SKIP_RELOCATE_UBOOT + relocate: /* relocate U-Boot to RAM */ +@@ -206,44 +261,6 @@ _start_armboot: .word start_oneboot + _start_armboot: .word start_armboot + #endif + +- +-/* +- ************************************************************************* +- * +- * CPU_init_critical registers +- * +- * setup important registers +- * setup memory timing +- * +- ************************************************************************* +- */ +-cpu_init_crit: +- /* +- * flush v4 I/D caches +- */ +- mov r0, #0 +- mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ +- mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ +- +- /* +- * disable MMU stuff and caches +- */ +- mrc p15, 0, r0, c1, c0, 0 +- bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) +- bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) +- orr r0, r0, #0x00000002 @ set bit 2 (A) Align +- orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache +- mcr p15, 0, r0, c1, c0, 0 +- +- /* +- * Jump to board specific initialization... The Mask ROM will have already initialized +- * basic memory. Go here to bump up clock rate and handle wake up conditions. +- */ +- mov ip, lr /* persevere link reg across call */ +- bl lowlevel_init /* go setup pll,mux,memory */ +- mov lr, ip /* restore link */ +- mov pc, lr /* back to my caller */ +- + #ifndef CONFIG_ONENAND_IPL + /* + ************************************************************************* +diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile +index b0abe6e..8537523 100644 +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -38,6 +38,7 @@ endif + COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o + COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o + COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o ++COBJS-$(CONFIG_MX31_NAND) += mx31_nand.o + endif + + COBJS := $(COBJS-y) +diff --git a/drivers/mtd/nand/mx31_nand.c b/drivers/mtd/nand/mx31_nand.c +new file mode 100644 +index 0000000..325e0f0 +--- /dev/null ++++ b/drivers/mtd/nand/mx31_nand.c +@@ -0,0 +1,969 @@ ++/* ++ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++ ++/* ++ * Define delays in microsec for NAND device operations ++ */ ++#define TROP_US_DELAY 2000 ++ ++/* ++ * Macros to get byte and bit positions of ECC ++ */ ++#define COLPOS(x) ((x) >> 4) ++#define BITPOS(x) ((x) & 0xf) ++ ++/* Define single bit Error positions in Main & Spare area */ ++#define MAIN_SINGLEBIT_ERROR 0x4 ++#define SPARE_SINGLEBIT_ERROR 0x1 ++ ++struct nand_info { ++ int oob; ++ int read_status; ++ int largepage; ++ u16 col; ++}; ++ ++static struct nand_info nandinfo; ++static int ecc_disabled; ++ ++/* ++ * OOB placement block for use with hardware ecc generation ++ */ ++static struct nand_oobinfo nand_hw_eccoob_8 = { ++ .useecc = MTD_NANDECC_AUTOPL_USR, ++ .eccbytes = 5, ++ .eccpos = {6, 7, 8, 9, 10}, ++ .oobfree = { ++ {0, 5}, ++ {11, 5} ++ } ++}; ++ ++static struct nand_oobinfo nand_hw_eccoob_2k = { ++ .useecc = MTD_NANDECC_AUTOPL_USR, ++ .eccbytes = 20, ++ .eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26, ++ 38, 39, 40, 41, 42, 54, 55, 56, 57, 58}, ++ .oobfree = { ++ {0, 5}, ++ {11, 10}, ++ {27, 10}, ++ {43, 10}, ++ {59, 5} ++ } ++}; ++ ++/* Define some generic bad / good block scan pattern which are used ++ * while scanning a device for factory marked good / bad blocks. */ ++static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; ++ ++static struct nand_bbt_descr smallpage_memorybased = { ++ .options = NAND_BBT_SCAN2NDPAGE, ++ .offs = 5, ++ .len = 1, ++ .pattern = scan_ff_pattern ++}; ++ ++static struct nand_bbt_descr largepage_memorybased = { ++ .options = 0, ++ .offs = 0, ++ .len = 2, ++ .pattern = scan_ff_pattern ++}; ++ ++/* Generic flash bbt decriptors */ ++static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' }; ++static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' }; ++ ++static struct nand_bbt_descr bbt_main_descr = { ++ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE ++ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, ++ .offs = 0, ++ .len = 4, ++ .veroffs = 4, ++ .maxblocks = 4, ++ .pattern = bbt_pattern ++}; ++ ++static struct nand_bbt_descr bbt_mirror_descr = { ++ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE ++ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, ++ .offs = 0, ++ .len = 4, ++ .veroffs = 4, ++ .maxblocks = 4, ++ .pattern = mirror_pattern ++}; ++ ++/** ++ * memcpy variant that copies 32 bit words. This is needed since the ++ * NFC only allows 32 bit accesses. Added for U-boot. ++ */ ++static void *memcpy_32(void *dest, const void *src, size_t n) ++{ ++ u32 *dst_32 = (u32 *) dest; ++ const u32 *src_32 = (u32 *) src; ++ ++ while (n > 0) { ++ *dst_32++ = *src_32++; ++ n -= 4; ++ } ++ ++ return dest; ++} ++ ++/** ++ * This function polls the NANDFC to wait for the basic operation to ++ * complete by checking the INT bit of config2 register. ++ * ++ * @param max_retries number of retry attempts (separated by 1 us) ++ */ ++static void wait_op_done(int max_retries) ++{ ++ while (max_retries-- > 0) { ++ if (NFC_CONFIG2 & NFC_INT) { ++ NFC_CONFIG2 &= ~NFC_INT; ++ break; ++ } ++ udelay(1); ++ } ++ if (max_retries <= 0) ++ DEBUG(MTD_DEBUG_LEVEL0, "wait: INT not set\n"); ++} ++ ++/** ++ * This function issues the specified command to the NAND device and ++ * waits for completion. ++ * ++ * @param cmd command for NAND Flash ++ */ ++static void send_cmd(u16 cmd) ++{ ++ DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(0x%x)\n", cmd); ++ ++ NFC_FLASH_CMD = (u16) cmd; ++ NFC_CONFIG2 = NFC_CMD; ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++} ++ ++/** ++ * This function sends an address (or partial address) to the ++ * NAND device. The address is used to select the source/destination for ++ * a NAND command. ++ * ++ * @param addr address to be written to NFC. ++ * @param islast 1 if this is the last address cycle for command ++ */ ++static void send_addr(u16 addr) ++{ ++ DEBUG(MTD_DEBUG_LEVEL3, "send_addr(0x%x %d)\n", addr); ++ ++ NFC_FLASH_ADDR = addr; ++ NFC_CONFIG2 = NFC_ADDR; ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++} ++ ++/** ++ * This function requests the NANDFC to initate the transfer ++ * of data currently in the NANDFC RAM buffer to the NAND device. ++ * ++ * @param buf_id Specify Internal RAM Buffer number (0-3) ++ * @param oob set to 1 if only the spare area is transferred ++ */ ++static void send_prog_page(u8 buf_id) ++{ ++ DEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", nandinfo.oob); ++ ++ /* NANDFC buffer 0 is used for page read/write */ ++ ++ NFC_BUF_ADDR = buf_id; ++ ++ /* Configure spare or page+spare access */ ++ if (!nandinfo.largepage) { ++ if (nandinfo.oob) ++ NFC_CONFIG1 |= NFC_SP_EN; ++ else ++ NFC_CONFIG1 &= ~NFC_SP_EN; ++ } ++ NFC_CONFIG2 = NFC_INPUT; ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++} ++ ++/** ++ * This function will correct the single bit ECC error ++ * ++ * @param buf_id Specify Internal RAM Buffer number (0-3) ++ * @param eccpos Ecc byte and bit position ++ * @param oob set to 1 if only spare area needs correction ++ */ ++static void mxc_nd_correct_error(u8 buf_id, u16 eccpos, int oob) ++{ ++ u16 col; ++ u8 pos; ++ u16 *buf; ++ ++ /* Get col & bit position of error ++ these macros works for both 8 & 16 bits */ ++ col = COLPOS(eccpos); /* Get half-word position */ ++ pos = BITPOS(eccpos); /* Get bit position */ ++ ++ DEBUG(MTD_DEBUG_LEVEL3, ++ "mxc_nd_correct_error (col=%d pos=%d)\n", col, pos); ++ ++ /* Set the pointer for main / spare area */ ++ if (!oob) ++ buf = (u16 *)(MAIN_AREA0 + col + (256 * buf_id)); ++ else ++ buf = (u16 *)(SPARE_AREA0 + col + (8 * buf_id)); ++ ++ /* Fix the data */ ++ *buf ^= 1 << pos; ++} ++ ++/** ++ * This function will maintains state of single bit Error ++ * in Main & spare area ++ * ++ * @param buf_id Specify Internal RAM Buffer number (0-3) ++ * @param spare set to 1 if only spare area needs correction ++ */ ++static void mxc_nd_correct_ecc(u8 buf_id, int spare) ++{ ++ u16 value, ecc_status; ++ ++ /* Read the ECC result */ ++ ecc_status = NFC_ECC_STATUS_RESULT; ++ DEBUG(MTD_DEBUG_LEVEL3, ++ "mxc_nd_correct_ecc (Ecc status=%x)\n", ecc_status); ++ ++ if (((ecc_status & 0xC) == MAIN_SINGLEBIT_ERROR) ++ || ((ecc_status & 0x3) == SPARE_SINGLEBIT_ERROR)) { ++ if (ecc_disabled) { ++ if ((ecc_status & 0xC) == MAIN_SINGLEBIT_ERROR) { ++ value = NFC_RSLTMAIN_AREA; ++ /* Correct single bit error in Mainarea ++ NFC will not correct the error in ++ current page */ ++ mxc_nd_correct_error(buf_id, value, 0); ++ } ++ if ((ecc_status & 0x3) == SPARE_SINGLEBIT_ERROR) { ++ value = NFC_RSLTSPARE_AREA; ++ /* Correct single bit error in Mainarea ++ NFC will not correct the error in ++ current page */ ++ mxc_nd_correct_error(buf_id, value, 1); ++ } ++ ++ } else { ++ /* Disable ECC */ ++ NFC_CONFIG1 &= ~NFC_ECC_EN; ++ ecc_disabled = 1; ++ } ++ } else if (ecc_status == 0) { ++ if (ecc_disabled) { ++ /* Enable ECC */ ++ NFC_CONFIG1 |= NFC_ECC_EN; ++ ecc_disabled = 0; ++ } ++ } /* else 2-bit Error. Do nothing */ ++} ++ ++/** ++ * This function requests the NANDFC to initated the transfer ++ * of data from the NAND device into in the NANDFC ram buffer. ++ * ++ * @param buf_id Specify Internal RAM Buffer number (0-3) ++ * @param oob set 1 if only the spare area is ++ * transferred ++ */ ++static void send_read_page(u8 buf_id) ++{ ++ DEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", nandinfo.oob); ++ ++ /* NANDFC buffer 0 is used for page read/write */ ++ NFC_BUF_ADDR = buf_id; ++ ++ /* Configure spare or page+spare access */ ++ if (!nandinfo.largepage) { ++ if (nandinfo.oob) ++ NFC_CONFIG1 |= NFC_SP_EN; ++ else ++ NFC_CONFIG1 &= ~NFC_SP_EN; ++ } ++ ++ NFC_CONFIG2 = NFC_OUTPUT; ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++ ++ /* If there are single bit errors in ++ two consecutive page reads then ++ the error is not corrected by the ++ NFC for the second page. ++ Correct single bit error in driver */ ++ ++ mxc_nd_correct_ecc(buf_id, nandinfo.oob); ++} ++ ++/** ++ * This function requests the NANDFC to perform a read of the ++ * NAND device ID. ++ */ ++static void send_read_id(void) ++{ ++ /* NANDFC buffer 0 is used for device ID output */ ++ NFC_BUF_ADDR = 0x0; ++ ++ /* Read ID into main buffer */ ++ NFC_CONFIG1 &= ~NFC_SP_EN; ++ NFC_CONFIG2 = NFC_ID; ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++} ++ ++/** ++ * This function requests the NANDFC to perform a read of the ++ * NAND device status and returns the current status. ++ * ++ * @return device status ++ */ ++static u16 get_dev_status(void) ++{ ++ volatile u16 *mainbuf = MAIN_AREA1; ++ u32 store; ++ u16 ret; ++ /* Issue status request to NAND device */ ++ ++ /* store the main area1 first word, later do recovery */ ++ store = *((u32 *) mainbuf); ++ /* ++ * NANDFC buffer 1 is used for device status to prevent ++ * corruption of read/write buffer on status requests. ++ */ ++ NFC_BUF_ADDR = 1; ++ ++ /* Read status into main buffer */ ++ NFC_CONFIG1 &= ~NFC_SP_EN; ++ NFC_CONFIG2 = NFC_STATUS; ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++ ++ /* Status is placed in first word of main buffer */ ++ /* get status, then recovery area 1 data */ ++ ret = mainbuf[0]; ++ *((u32 *) mainbuf) = store; ++ ++ return ret; ++} ++ ++static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) ++{ ++ /* ++ * If HW ECC is enabled, we turn it on during init. There is ++ * no need to enable again here. ++ */ ++} ++ ++static int mxc_nand_correct_data(struct mtd_info *mtd, unsigned char *dat, ++ unsigned char *read_ecc, unsigned char *calc_ecc) ++{ ++ /* ++ * 1-Bit errors are automatically corrected in HW. No need for ++ * additional correction. 2-Bit errors cannot be corrected by ++ * HW ECC, so we need to return failure ++ */ ++ u16 ecc_status = NFC_ECC_STATUS_RESULT; ++ ++ if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { ++ DEBUG(MTD_DEBUG_LEVEL0, ++ "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *dat, ++ unsigned char *ecc_code) ++{ ++ /* ++ * Just return success. HW ECC does not read/write the NFC spare ++ * buffer. Only the FLASH spare area contains the calcuated ECC. ++ */ ++ return 0; ++} ++ ++/** ++ * This function reads byte from the NAND Flash ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * ++ * @return data read from the NAND Flash ++ */ ++static unsigned char mxc_nand_read_byte(struct mtd_info *mtd) ++{ ++ unsigned char ret_val = 0; ++ u16 col, rd_word; ++ volatile u16 *mainbuf = MAIN_AREA0; ++ volatile u16 *sparebuf = SPARE_AREA0; ++ ++ /* Check for status request */ ++ if (nandinfo.read_status) ++ return get_dev_status() & 0xFF; ++ ++ /* Get column for 16-bit access */ ++ col = nandinfo.col >> 1; ++ ++ /* If we are accessing the spare region */ ++ if (nandinfo.oob) ++ rd_word = sparebuf[col]; ++ else ++ rd_word = mainbuf[col]; ++ ++ /* Pick upper/lower byte of word from RAM buffer */ ++ if (nandinfo.col & 0x1) ++ ret_val = (rd_word >> 8) & 0xFF; ++ else ++ ret_val = rd_word & 0xFF; ++ ++ /* Update saved column address */ ++ nandinfo.col++; ++ ++ return ret_val; ++} ++ ++/** ++ * This function reads word from the NAND Flash ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * ++ * @return data read from the NAND Flash ++ */ ++static u16 mxc_nand_read_word(struct mtd_info *mtd) ++{ ++ u16 col; ++ u16 rd_word, ret_val; ++ volatile u16 *p; ++ ++ DEBUG(MTD_DEBUG_LEVEL3, "mxc_nand_read_word(col = %d)\n", nandinfo.col); ++ ++ col = nandinfo.col; ++ /* Adjust saved column address */ ++ if (col < mtd->oobblock && nandinfo.oob) ++ col += mtd->oobblock; ++ ++ if (col < mtd->oobblock) ++ p = (MAIN_AREA0) + (col >> 1); ++ else ++ p = (SPARE_AREA0) + ((col - mtd->oobblock) >> 1); ++ ++ if (col & 1) { ++ rd_word = *p; ++ ret_val = (rd_word >> 8) & 0xff; ++ rd_word = *(p + 1); ++ ret_val |= (rd_word << 8) & 0xff00; ++ ++ } else ++ ret_val = *p; ++ ++ /* Update saved column address */ ++ nandinfo.col = col + 2; ++ ++ return ret_val; ++} ++ ++/** ++ * This function writes data of length \b len to buffer \b buf. The data ++ * to be written on NAND Flash is first copied to RAMbuffer. After the ++ * Data Input Operation by the NFC, the data is written to NAND Flash. ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * @param buf data to be written to NAND Flash ++ * @param len number of bytes to be written ++ */ ++static void mxc_nand_write_buf(struct mtd_info *mtd, ++ const unsigned char *buf, int len) ++{ ++ int n; ++ int col; ++ int i = 0; ++ ++ DEBUG(MTD_DEBUG_LEVEL3, ++ "mxc_nand_write_buf(col = %d, len = %d)\n", nandinfo.col, len); ++ ++ col = nandinfo.col; ++ ++ /* Adjust saved column address */ ++ if (col < mtd->oobblock && nandinfo.oob) ++ col += mtd->oobblock; ++ ++ n = mtd->oobblock + mtd->oobsize - col; ++ if (len > mtd->oobblock + mtd->oobsize - col) ++ DEBUG(MTD_DEBUG_LEVEL1, "Error: too much data.\n"); ++ ++ n = min(len, n); ++ ++ DEBUG(MTD_DEBUG_LEVEL3, ++ "%s:%d: col = %d, n = %d\n", __FUNCTION__, __LINE__, col, n); ++ ++ while (n) { ++ volatile u32 *p; ++ if (col < mtd->oobblock) ++ p = (volatile u32 *)((ulong) (MAIN_AREA0) + (col & ~3)); ++ else ++ p = (volatile u32 *)((ulong) (SPARE_AREA0) - ++ mtd->oobblock + (col & ~3)); ++ ++ DEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", ++ __FUNCTION__, __LINE__, p); ++ ++ if (((col | (int)&buf[i]) & 3) || n < 16) { ++ u32 data = 0; ++ ++ if (col & 3 || n < 4) ++ data = *p; ++ ++ switch (col & 3) { ++ case 0: ++ if (n) { ++ data = (data & 0xffffff00) | ++ (buf[i++] << 0); ++ n--; ++ col++; ++ } ++ case 1: ++ if (n) { ++ data = (data & 0xffff00ff) | ++ (buf[i++] << 8); ++ n--; ++ col++; ++ } ++ case 2: ++ if (n) { ++ data = (data & 0xff00ffff) | ++ (buf[i++] << 16); ++ n--; ++ col++; ++ } ++ case 3: ++ if (n) { ++ data = (data & 0x00ffffff) | ++ (buf[i++] << 24); ++ n--; ++ col++; ++ } ++ } ++ ++ *p = data; ++ } else { ++ int m = mtd->oobblock - col; ++ ++ if (col >= mtd->oobblock) ++ m += mtd->oobsize; ++ ++ m = min(n, m) & ~3; ++ ++ DEBUG(MTD_DEBUG_LEVEL3, ++ "%s:%d: n = %d, m = %d, i = %d, col = %d\n", ++ __FUNCTION__, __LINE__, n, m, i, col); ++ ++ memcpy_32((void *)(p), &buf[i], m); ++ col += m; ++ i += m; ++ n -= m; ++ } ++ } ++ /* Update saved column address */ ++ nandinfo.col = col; ++} ++ ++/** ++ * This function id is used to read the data buffer from the NAND Flash. To ++ * read the data from NAND Flash first the data output cycle is initiated by ++ * the NFC, which copies the data to RAMbuffer. This data of length \b len is ++ * then copied to buffer \b buf. ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * @param buf data to be read from NAND Flash ++ * @param len number of bytes to be read ++ */ ++static void mxc_nand_read_buf(struct mtd_info *mtd, unsigned char *buf, int len) ++{ ++ int n; ++ int col; ++ int i = 0; ++ ++ DEBUG(MTD_DEBUG_LEVEL3, ++ "mxc_nand_read_buf(col = %d, len = %d)\n", nandinfo.col, len); ++ ++ col = nandinfo.col; ++ /** ++ * Adjust saved column address ++ * for nand_read_oob will pass col within oobsize ++ */ ++ if (col < mtd->oobblock && nandinfo.oob) ++ col += mtd->oobblock; ++ ++ n = mtd->oobblock + mtd->oobsize - col; ++ n = min(len, n); ++ ++ while (n) { ++ volatile u32 *p; ++ ++ if (col < mtd->oobblock) ++ p = (volatile u32 *)((ulong) (MAIN_AREA0) + (col & ~3)); ++ else ++ p = (volatile u32 *)((ulong) (SPARE_AREA0) - ++ mtd->oobblock + (col & ~3)); ++ ++ if (((col | (int)&buf[i]) & 3) || n < 16) { ++ u32 data; ++ ++ data = *p; ++ switch (col & 3) { ++ case 0: ++ if (n) { ++ buf[i++] = (u8) (data); ++ n--; ++ col++; ++ } ++ case 1: ++ if (n) { ++ buf[i++] = (u8) (data >> 8); ++ n--; ++ col++; ++ } ++ case 2: ++ if (n) { ++ buf[i++] = (u8) (data >> 16); ++ n--; ++ col++; ++ } ++ case 3: ++ if (n) { ++ buf[i++] = (u8) (data >> 24); ++ n--; ++ col++; ++ } ++ } ++ } else { ++ int m = mtd->oobblock - col; ++ ++ if (col >= mtd->oobblock) ++ m += mtd->oobsize; ++ ++ m = min(n, m) & ~3; ++ memcpy_32(&buf[i], (void *)(p), m); ++ col += m; ++ i += m; ++ n -= m; ++ } ++ } ++ /* Update saved column address */ ++ nandinfo.col = col; ++} ++ ++/** ++ * This function is used by the upper layer to verify the data in NAND Flash ++ * with the data in the \b buf. ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * @param buf data to be verified ++ * @param len length of the data to be verified ++ * ++ * @return -EFAULT if error else 0 ++ */ ++static int ++mxc_nand_verify_buf(struct mtd_info *mtd, const unsigned char *buf, int len) ++{ ++ return -1; /* Was -EFAULT */ ++} ++ ++/** ++ * This function is used by upper layer for select and deselect of the NAND ++ * chip. ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * @param chip val indicating select or deselect ++ */ ++static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) ++{ ++} ++ ++/** ++ * This function is used by the upper layer to write command to NAND Flash ++ * for different operations to be carried out on NAND Flash ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * @param command command for NAND Flash ++ * @param column column offset for the page read ++ * @param page_addr page to be read from NAND Flash ++ */ ++static void mxc_nand_command(struct mtd_info *mtd, unsigned command, ++ int column, int page_addr) ++{ ++ DEBUG(MTD_DEBUG_LEVEL3, ++ "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", ++ command, column, page_addr); ++ ++ /* Reset command state information */ ++ nandinfo.read_status = 0; ++ nandinfo.oob = 0; ++ ++ /* Command pre-processing step */ ++ switch (command) { ++ ++ case NAND_CMD_STATUS: ++ nandinfo.col = 0; ++ nandinfo.read_status = 1; ++ break; ++ ++ case NAND_CMD_READ0: ++ nandinfo.col = column; ++ break; ++ ++ case NAND_CMD_READOOB: ++ nandinfo.col = column; ++ nandinfo.oob = 1; ++ if (nandinfo.largepage) ++ command = NAND_CMD_READ0; ++ break; ++ ++ case NAND_CMD_SEQIN: ++ if (column >= mtd->oobblock) { ++ /* write oob routine caller */ ++ if (nandinfo.largepage) { ++ /* ++ * FIXME: before send SEQIN command for ++ * write OOB, we must read one page out. ++ * For 2K nand has no READ1 command to set ++ * current HW pointer to spare area, we must ++ * write the whole page including OOB together. ++ */ ++ /* call itself to read a page */ ++ mxc_nand_command(mtd, NAND_CMD_READ0, 0, ++ page_addr); ++ } ++ nandinfo.col = column - mtd->oobblock; ++ nandinfo.oob = 1; ++ /* Set program pointer to spare region */ ++ if (!nandinfo.largepage) ++ send_cmd(NAND_CMD_READOOB); ++ } else { ++ nandinfo.oob = 0; ++ nandinfo.col = column; ++ /* Set program pointer to page start */ ++ if (!nandinfo.largepage) ++ send_cmd(NAND_CMD_READ0); ++ } ++ break; ++ ++ case NAND_CMD_PAGEPROG: ++ if (ecc_disabled) { ++ /* Enable Ecc for page writes */ ++ NFC_CONFIG1 |= NFC_ECC_EN; ++ } ++ send_prog_page(0); ++ ++ if (nandinfo.largepage) { ++ /* data in 4 areas datas */ ++ send_prog_page(1); ++ send_prog_page(2); ++ send_prog_page(3); ++ } ++ ++ break; ++ ++ case NAND_CMD_ERASE1: ++ break; ++ } ++ ++ /* ++ * Write out the command to the device. ++ */ ++ send_cmd(command); ++ ++ /* ++ * Write out column address, if necessary ++ */ ++ if (column != -1) { ++ /* ++ * MXC NANDFC can only perform full page+spare or ++ * spare-only read/write. When the upper layers ++ * layers perform a read/write buf operation, ++ * we will used the saved column adress to index into ++ * the full page. ++ */ ++ send_addr(0); ++ if (nandinfo.largepage) ++ /* another col addr cycle for 2k page */ ++ send_addr(0); ++ } ++ ++ /* ++ * Write out page address, if necessary ++ */ ++ if (page_addr != -1) { ++ /* paddr_0 - p_addr_7 */ ++ send_addr((page_addr & 0xff)); ++ ++ if (nandinfo.largepage) { ++ /* One more address cycle for higher ++ * density devices */ ++ ++ if (mtd->size >= 0x10000000) { ++ /* paddr_8 - paddr_15 */ ++ send_addr((page_addr >> 8) & 0xff); ++ send_addr((page_addr >> 16) & 0xff); ++ } else ++ /* paddr_8 - paddr_15 */ ++ send_addr((page_addr >> 8) & 0xff); ++ } else { ++ /* One more address cycle for higher ++ * density devices */ ++ ++ if (mtd->size >= 0x4000000) { ++ /* paddr_8 - paddr_15 */ ++ send_addr((page_addr >> 8) & 0xff); ++ send_addr((page_addr >> 16) & 0xff); ++ } else ++ /* paddr_8 - paddr_15 */ ++ send_addr((page_addr >> 8) & 0xff); ++ } ++ } ++ ++ /* ++ * Command post-processing step ++ */ ++ switch (command) { ++ ++ case NAND_CMD_RESET: ++ break; ++ ++ case NAND_CMD_READOOB: ++ case NAND_CMD_READ0: ++ if (nandinfo.largepage) { ++ /* send read confirm command */ ++ send_cmd(NAND_CMD_READSTART); ++ /* read for each AREA */ ++ send_read_page(0); ++ send_read_page(1); ++ send_read_page(2); ++ send_read_page(3); ++ } else ++ send_read_page(0); ++ break; ++ ++ case NAND_CMD_READID: ++ send_read_id(); ++ break; ++ ++ case NAND_CMD_PAGEPROG: ++ if (ecc_disabled) { ++ /* Disable Ecc after page writes */ ++ NFC_CONFIG1 &= ~NFC_ECC_EN; ++ } ++ break; ++ ++ case NAND_CMD_ERASE2: ++ break; ++ } ++} ++ ++static int mxc_nand_scan_bbt(struct mtd_info *mtd) ++{ ++ struct nand_chip *this = mtd->priv; ++ ++ /* Config before scanning */ ++ /* Do not rely on NFMS_BIT, set/clear NFMS bit based ++ * on mtd->oobblock */ ++ if (mtd->oobblock == 2048) ++ NFMS |= 1 << NFMS_BIT; ++ else if ((NFMS >> NFMS_BIT) & 0x1) ++ NFMS &= ~(1 << NFMS_BIT); ++ ++ /* use flash based bbt */ ++ this->bbt_td = &bbt_main_descr; ++ this->bbt_md = &bbt_mirror_descr; ++ ++ /* update flash based bbt */ ++ this->options |= NAND_USE_FLASH_BBT; ++ ++ if (!this->badblock_pattern) { ++ if (nandinfo.largepage) ++ this->badblock_pattern = &smallpage_memorybased; ++ else ++ this->badblock_pattern = (mtd->oobblock > 512) ? ++ &largepage_memorybased : &smallpage_memorybased; ++ } ++ /* Build bad block table */ ++ return nand_scan_bbt(mtd, this->badblock_pattern); ++} ++ ++int board_nand_init(struct nand_chip *nand) ++{ ++ nand->chip_delay = 0; ++ ++ nand->cmdfunc = mxc_nand_command; ++ nand->select_chip = mxc_nand_select_chip; ++ nand->read_byte = mxc_nand_read_byte; ++ nand->read_word = mxc_nand_read_word; ++ nand->write_buf = mxc_nand_write_buf; ++ nand->read_buf = mxc_nand_read_buf; ++ nand->verify_buf = mxc_nand_verify_buf; ++ nand->scan_bbt = mxc_nand_scan_bbt; ++ nand->calculate_ecc = mxc_nand_calculate_ecc; ++ nand->correct_data = mxc_nand_correct_data; ++ nand->enable_hwecc = mxc_nand_enable_hwecc; ++ nand->eccmode = NAND_ECC_HW3_512; ++ nand->eccbytes = 512; ++ nand->eccsize = 3; ++ ++ /* Reset NAND */ ++ NFC_CONFIG1 |= NFC_INT_MSK | NFC_RST | NFC_ECC_EN; ++ ++ /* Unlock the internal RAM buffer */ ++ NFC_CONFIG = 0x2; ++ ++ /* Block to be unlocked */ ++ NFC_UNLOCKSTART_BLKADDR = 0x0; ++ NFC_UNLOCKEND_BLKADDR = 0x4000; ++ ++ /* Unlock Block Command for given address range */ ++ NFC_WRPROT = 0x4; ++ ++ /* Only 8 bit bus support for now */ ++ nand->options |= 0; ++ ++ if ((NFMS >> NFMS_BIT) & 1) { ++ nandinfo.largepage = 1; ++ nand->autooob = &nand_hw_eccoob_2k; ++ } else { ++ nandinfo.largepage = 0; ++ nand->autooob = &nand_hw_eccoob_8; ++ } ++ ++ return 0; ++} +diff --git a/include/asm-arm/arch-mx31/mx31-regs.h b/include/asm-arm/arch-mx31/mx31-regs.h +index b04a718..83ac646 100644 +--- a/include/asm-arm/arch-mx31/mx31-regs.h ++++ b/include/asm-arm/arch-mx31/mx31-regs.h +@@ -168,4 +168,105 @@ + #define CS5_BASE 0xB6000000 + #define PCMCIA_MEM_BASE 0xC0000000 + ++/* ++ * NAND controller ++ */ ++#define NFC_BASE_ADDR 0xB8000000 ++ ++/* ++ * Addresses for NFC registers ++ */ ++#define NFC_BUF_SIZE (*((volatile u16 *)(NFC_BASE_ADDR + 0xE00))) ++#define NFC_BUF_ADDR (*((volatile u16 *)(NFC_BASE_ADDR + 0xE04))) ++#define NFC_FLASH_ADDR (*((volatile u16 *)(NFC_BASE_ADDR + 0xE06))) ++#define NFC_FLASH_CMD (*((volatile u16 *)(NFC_BASE_ADDR + 0xE08))) ++#define NFC_CONFIG (*((volatile u16 *)(NFC_BASE_ADDR + 0xE0A))) ++#define NFC_ECC_STATUS_RESULT (*((volatile u16 *)(NFC_BASE_ADDR + 0xE0C))) ++#define NFC_RSLTMAIN_AREA (*((volatile u16 *)(NFC_BASE_ADDR + 0xE0E))) ++#define NFC_RSLTSPARE_AREA (*((volatile u16 *)(NFC_BASE_ADDR + 0xE10))) ++#define NFC_WRPROT (*((volatile u16 *)(NFC_BASE_ADDR + 0xE12))) ++#define NFC_UNLOCKSTART_BLKADDR (*((volatile u16 *)(NFC_BASE_ADDR + 0xE14))) ++#define NFC_UNLOCKEND_BLKADDR (*((volatile u16 *)(NFC_BASE_ADDR + 0xE16))) ++#define NFC_NF_WRPRST (*((volatile u16 *)(NFC_BASE_ADDR + 0xE18))) ++#define NFC_CONFIG1 (*((volatile u16 *)(NFC_BASE_ADDR + 0xE1A))) ++#define NFC_CONFIG2 (*((volatile u16 *)(NFC_BASE_ADDR + 0xE1C))) ++ ++#define NFC_BUFSIZE_REG_OFF (0 + 0x00) ++#define RAM_BUFFER_ADDRESS_REG_OFF (0 + 0x04) ++#define NAND_FLASH_ADD_REG_OFF (0 + 0x06) ++#define NAND_FLASH_CMD_REG_OFF (0 + 0x08) ++#define NFC_CONFIGURATION_REG_OFF (0 + 0x0A) ++#define ECC_STATUS_RESULT_REG_OFF (0 + 0x0C) ++#define ECC_RSLT_MAIN_AREA_REG_OFF (0 + 0x0E) ++#define ECC_RSLT_SPARE_AREA_REG_OFF (0 + 0x10) ++#define NF_WR_PROT_REG_OFF (0 + 0x12) ++#define UNLOCK_START_BLK_ADD_REG_OFF (0 + 0x14) ++#define UNLOCK_END_BLK_ADD_REG_OFF (0 + 0x16) ++#define NAND_FLASH_WR_PR_ST_REG_OFF (0 + 0x18) ++#define NAND_FLASH_CONFIG1_REG_OFF (0 + 0x1A) ++#define NAND_FLASH_CONFIG2_REG_OFF (0 + 0x1C) ++#define RAM_BUFFER_ADDRESS_RBA_3 0x3 ++#define NFC_BUFSIZE_1KB 0x0 ++#define NFC_BUFSIZE_2KB 0x1 ++#define NFC_CONFIGURATION_UNLOCKED 0x2 ++#define ECC_STATUS_RESULT_NO_ERR 0x0 ++#define ECC_STATUS_RESULT_1BIT_ERR 0x1 ++#define ECC_STATUS_RESULT_2BIT_ERR 0x2 ++#define NF_WR_PROT_UNLOCK 0x4 ++#define NAND_FLASH_CONFIG1_FORCE_CE (1 << 7) ++#define NAND_FLASH_CONFIG1_RST (1 << 6) ++#define NAND_FLASH_CONFIG1_BIG (1 << 5) ++#define NAND_FLASH_CONFIG1_INT_MSK (1 << 4) ++#define NAND_FLASH_CONFIG1_ECC_EN (1 << 3) ++#define NAND_FLASH_CONFIG1_SP_EN (1 << 2) ++#define NAND_FLASH_CONFIG2_INT_DONE (1 << 15) ++#define NAND_FLASH_CONFIG2_FDO_PAGE (0 << 3) ++#define NAND_FLASH_CONFIG2_FDO_ID (2 << 3) ++#define NAND_FLASH_CONFIG2_FDO_STATUS (4 << 3) ++#define NAND_FLASH_CONFIG2_FDI_EN (1 << 2) ++#define NAND_FLASH_CONFIG2_FADD_EN (1 << 1) ++#define NAND_FLASH_CONFIG2_FCMD_EN (1 << 0) ++#define FDO_PAGE_SPARE_VAL 0x8 ++#define NAND_FLASH_BOOT 0x10000000 ++#define MXCFIS_NAND 0x10000000 ++ ++/* ++ * Addresses for NFC RAM BUFFER Main area 0 ++ */ ++#define MAIN_AREA0 (volatile u16 *)(NFC_BASE_ADDR + 0x000) ++#define MAIN_AREA1 (volatile u16 *)(NFC_BASE_ADDR + 0x200) ++#define MAIN_AREA2 (volatile u16 *)(NFC_BASE_ADDR + 0x400) ++#define MAIN_AREA3 (volatile u16 *)(NFC_BASE_ADDR + 0x600) ++ ++/* ++ * Addresses for NFC SPARE BUFFER Spare area 0 ++ */ ++#define SPARE_AREA0 (volatile u16 *)(NFC_BASE_ADDR + 0x800) ++#define SPARE_AREA1 (volatile u16 *)(NFC_BASE_ADDR + 0x810) ++#define SPARE_AREA2 (volatile u16 *)(NFC_BASE_ADDR + 0x820) ++#define SPARE_AREA3 (volatile u16 *)(NFC_BASE_ADDR + 0x830) ++ ++#define NFC_CMD 0x1 ++#define NFC_ADDR 0x2 ++#define NFC_INPUT 0x4 ++#define NFC_OUTPUT 0x8 ++#define NFC_ID 0x10 ++#define NFC_STATUS 0x20 ++#define NFC_INT 0x8000 ++ ++#define NFC_SP_EN (1 << 2) ++#define NFC_ECC_EN (1 << 3) ++#define NFC_INT_MSK (1 << 4) ++#define NFC_BIG (1 << 5) ++#define NFC_RST (1 << 6) ++#define NFC_CE (1 << 7) ++#define NFC_ONE_CYCLE (1 << 8) ++ ++/* ++ * NFMS bit in RCSR register for pagesize of nandflash ++ */ ++#define NFMS (*((volatile u32 *)CCM_RCSR)) ++#define NFMS_BIT 30 ++ + #endif /* __ASM_ARCH_MX31_REGS_H */ ++ +diff --git a/include/configs/mx31_3stack.h b/include/configs/mx31_3stack.h +new file mode 100644 +index 0000000..7aaef4f +--- /dev/null ++++ b/include/configs/mx31_3stack.h +@@ -0,0 +1,165 @@ ++/* ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ * ++ * Configuration settings for the MX31 3Stack Freescale board. ++ * ++ * 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 ++ ++#include ++ ++ /* High Level Configuration Options */ ++#define CONFIG_ARM1136 1 /* This is an arm1136 CPU core */ ++#define CONFIG_MX31 1 /* in a mx31 */ ++#define CONFIG_MX31_HCLK_FREQ 26000000 ++#define CONFIG_MX31_CLK32 32768 ++ ++#define CONFIG_MX31_NAND ++ ++#define CONFIG_DISPLAY_CPUINFO ++#define CONFIG_DISPLAY_BOARDINFO ++ ++#define CONFIG_NAND_BOOT ++#define CONFIG_SKIP_RELOCATE_UBOOT ++ ++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ ++#define CONFIG_SETUP_MEMORY_TAGS 1 ++#define CONFIG_INITRD_TAG 1 ++ ++/* ++ * Size of malloc() pool ++ */ ++#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128 * 1024) ++#define CFG_GBL_DATA_SIZE 128 ++ ++/* ++ * Hardware drivers ++ */ ++ ++#define CONFIG_MX31_UART 1 ++#define CFG_MX31_UART1 1 ++ ++#define CONFIG_HARD_SPI 1 ++#define CONFIG_MXC_SPI 1 ++#define CONFIG_MXC_SPI_IFACE 1 ++ ++#define CONFIG_RTC_MC13783 1 ++ ++/* allow to overwrite serial and ethaddr */ ++#define CONFIG_ENV_OVERWRITE ++#define CONFIG_CONS_INDEX 1 ++#define CONFIG_BAUDRATE 115200 ++#define CFG_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200} ++ ++/*********************************************************** ++ * Command definition ++ ***********************************************************/ ++ ++#include ++ ++#define CONFIG_CMD_PING ++#define CONFIG_CMD_DHCP ++#define CONFIG_CMD_SPI ++#define CONFIG_CMD_DATE ++#define CONFIG_CMD_NAND ++#undef CONFIG_CMD_IMLS ++ ++#define CONFIG_BOOTDELAY 3 ++ ++#define CONFIG_LOADADDR 0x80800000 /* loadaddr env var */ ++ ++#define CONFIG_EXTRA_ENV_SETTINGS \ ++ "netdev=eth0\0" \ ++ "uboot=u-boot.bin\0" \ ++ "kernel=uImage\0" \ ++ "loadaddr=0x80010000\0" \ ++ "tftp_server=10.192.225.58\0" \ ++ "serverip=10.192.225.211\0" \ ++ "nfsroot=/tools/rootfs/rootfs-2.6.24\0" \ ++ "bootargs_base=setenv bootargs console=ttymxc0,115200\0" \ ++ "bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs " \ ++ "ip=dhcp nfsroot=${serverip}:${nfsroot} rw\0" \ ++ "bootcmd=run bootcmd_net\0" \ ++ "bootcmd_net=run bootargs_base bootargs_nfs; " \ ++ "tftpboot ${loadaddr} ${tftp_server}:${kernel}; bootm\0" ++ ++/* configure for smc91xx debug board ethernet */ ++#define CONFIG_NET_MULTI 1 ++#define CONFIG_DRIVER_SMC911X 1 ++#define CONFIG_DRIVER_SMC911X_BASE CS5_BASE ++#define CONFIG_DRIVER_SMC911X_32_BIT 1 ++ ++#define CONFIG_ARP_TIMEOUT 200UL ++ ++/* ++ * Miscellaneous configurable options ++ */ ++#define CFG_LONGHELP /* undef to save memory */ ++#define CFG_PROMPT "=> " ++#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ ++/* Print Buffer Size */ ++#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) ++#define CFG_MAXARGS 16 /* max number of command args */ ++#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ ++ ++#define CFG_MEMTEST_START 0 /* memtest works on */ ++#define CFG_MEMTEST_END 0x10000 ++ ++#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */ ++ ++#define CFG_LOAD_ADDR CONFIG_LOADADDR ++ ++#define CFG_HZ CONFIG_MX31_CLK32 ++ ++#define CONFIG_CMDLINE_EDITING 1 ++ ++/*----------------------------------------------------------------------- ++ * Stack sizes ++ * ++ * The stack sizes are set up in start.S using the settings below ++ */ ++#define CONFIG_STACKSIZE (128 * 1024) /* regular stack */ ++ ++/*----------------------------------------------------------------------- ++ * Physical Memory Map ++ */ ++#define CONFIG_NR_DRAM_BANKS 1 ++#define PHYS_SDRAM_1 CSD0_BASE ++#define PHYS_SDRAM_1_SIZE (128 * 1024 * 1024) ++ ++/* ++ * TODO: NAND Flash configure ++ */ ++ ++#define CFG_NO_FLASH ++#define NAND_MAX_CHIPS 1 ++#define CFG_MAX_NAND_DEVICE 1 ++#define CFG_NAND_BASE 0x40000000 ++ ++#define CFG_ENV_IS_IN_NAND 1 ++#define CFG_ENV_OFFSET 0x40000 /* 2nd block */ ++#define CFG_ENV_SIZE (128*1024) ++ ++/* ++ * JFFS2 partitions TODO: ++ */ ++#undef CONFIG_JFFS2_CMDLINE ++#define CONFIG_JFFS2_DEV "nand0" ++ ++#endif /* __CONFIG_H */ +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0007-ENGR00103914-Support-i.MX35-TO2-and-3stack-board-ver.patch +++ uboot-imx-2009.01/debian/patches/0007-ENGR00103914-Support-i.MX35-TO2-and-3stack-board-ver.patch @@ -0,0 +1,291 @@ +From ad3a535c6a32f1f36e8ef3d129b16ec6773beb3c Mon Sep 17 00:00:00 2001 +From: Fred Fan +Date: Mon, 23 Feb 2009 13:59:58 +0800 +Subject: [PATCH] ENGR00103914 Support i.MX35 TO2 and 3stack board version 2 + +1. Check Soc version +2. Check Board version based on TO2 pmic chip version. +3. Based on soc version, skips To1 workaround code +4. based on board version, enables FEC power and select pin mux. + +Signed-off-by: Fred Fan +--- + board/freescale/mx35_3stack/lowlevel_init.S | 36 +++++++-- + board/freescale/mx35_3stack/mx35_3stack.c | 108 +++++++++++++++++++++++---- + include/asm-arm/arch-mx35/mx35.h | 3 + + include/configs/mx35_3stack.h | 1 + + 4 files changed, 125 insertions(+), 23 deletions(-) + +diff --git a/board/freescale/mx35_3stack/lowlevel_init.S b/board/freescale/mx35_3stack/lowlevel_init.S +index 40792f1..0b47ef1 100644 +--- a/board/freescale/mx35_3stack/lowlevel_init.S ++++ b/board/freescale/mx35_3stack/lowlevel_init.S +@@ -24,6 +24,22 @@ + #include "board-mx35_3stack.h" + + /* ++ * return soc version ++ * 0x10: TO1 ++ * 0x20: TO2 ++ * 0x30: TO3 ++ */ ++.macro check_soc_version ret, tmp ++ ldr \tmp, =IIM_BASE_ADDR ++ ldr \ret, [\tmp, #IIM_SREV] ++ cmp \ret, #0x00 ++ moveq \tmp, #ROMPATCH_BASE_ADDR ++ ldreq \ret, [\tmp, #ROMPATCH_REV] ++ moveq \ret, \ret, lsl #4 ++ addne \ret, \ret, #0x10 ++.endm ++ ++/* + * L2CC Cache setup/invalidation/disable + */ + .macro init_l2cc +@@ -46,11 +62,6 @@ + orr r1, r1, r2 + str r1, [r0, #L2_CACHE_AUX_CTL_REG] + +-/* Workaournd for DDR issue:WT*/ +- ldr r1, [r0, #L2_CACHE_DBG_CTL_REG] +- orr r1, r1, #2 +- str r1, [r0, #L2_CACHE_DBG_CTL_REG] +- + /* Invalidate L2 */ + mov r1, #0x000000FF + str r1, [r0, #L2_CACHE_INV_WAY_REG] +@@ -184,11 +195,15 @@ + ldr r2, =CCM_CCMR_CONFIG + str r2, [r0, #CLKCTL_CCMR] + ++ check_soc_version r1, r2 ++ cmp r1, #0x20 ++ ldrhs r3, =CCM_MPLL_399_HZ ++ bhs 1f + ldr r2, [r0, #CLKCTL_PDR0] + tst r2, #CLKMODE_CONSUMER + ldrne r3, =CCM_MPLL_532_HZ /* consumer path*/ + ldreq r3, =CCM_MPLL_399_HZ /* auto path*/ +- ++1: + str r3, [r0, #CLKCTL_MPCTL] + + ldr r1, =CCM_PPLL_300_HZ +@@ -231,12 +246,15 @@ + + mov lr, fp + ++ check_soc_version r3, r4 ++ cmp r1, #0x20 ++ bhs 1f + cmp r5, #0 + movne r3, #L2CC_BASE_ADDR + ldrne r4, [r3, #L2_CACHE_AUX_CTL_REG] + orrne r4, r4, #0x1000 + strne r4, [r3, #L2_CACHE_AUX_CTL_REG] +- ++1: + ldr r3, =ESDCTL_DELAY_LINE5 + str r3, [r0, #0x30] + .endm /* setup_sdram */ +@@ -280,8 +298,6 @@ lowlevel_init: + #endif + mcr 15, 0, r0, c7, c10, 4 /* Drain the write buffer */ + +- init_l2cc +- + /* initializes very early AIPS, what for? + * Then it also initializes Multi-Layer AHB Crossbar Switch, + * M3IF */ +@@ -289,6 +305,8 @@ lowlevel_init: + ldr r0, =0x40000015 /* start from AIPS 2GB region */ + mcr p15, 0, r0, c15, c2, 4 + ++ init_l2cc ++ + init_aips + + init_max +diff --git a/board/freescale/mx35_3stack/mx35_3stack.c b/board/freescale/mx35_3stack/mx35_3stack.c +index f6d5641..7854f86 100644 +--- a/board/freescale/mx35_3stack/mx35_3stack.c ++++ b/board/freescale/mx35_3stack/mx35_3stack.c +@@ -31,6 +31,35 @@ + + DECLARE_GLOBAL_DATA_PTR; + ++static u32 system_rev; ++ ++u32 get_board_rev(void) ++{ ++ return system_rev; ++} ++ ++static inline void setup_soc_rev(void) ++{ ++ int reg; ++ reg = __REG(IIM_BASE_ADDR + IIM_SREV); ++ if (!reg) { ++ reg = __REG(ROMPATCH_BASE_ADDR + ROMPATCH_REV); ++ reg <<= 4; ++ } else ++ reg += 0x10; ++ system_rev = 0x35000 + (reg & 0xFF); ++} ++ ++static inline void set_board_rev(int rev) ++{ ++ system_rev |= (rev & 0xF) << 8; ++} ++ ++static inline int is_soc_rev(int rev) ++{ ++ return (system_rev & 0xFF) - rev; ++} ++ + int dram_init(void) + { + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; +@@ -43,6 +72,8 @@ int board_init(void) + { + int pad; + ++ setup_soc_rev(); ++ + /* enable clocks */ + __REG(CCM_BASE_ADDR + CLKCTL_CGR0) |= 0x003F0000; + __REG(CCM_BASE_ADDR + CLKCTL_CGR1) |= 0x00030FFF; +@@ -124,40 +155,89 @@ int board_init(void) + } + + #ifdef BOARD_LATE_INIT ++static inline int board_detect(void) ++{ ++ u8 buf[4]; ++ int id; ++ ++ if (i2c_read(0x08, 0x7, 1, buf, 3) < 0) { ++ printf("board_late_init: read PMIC@0x08:0x7 fail\n"); ++ return 0; ++ } ++ id = (buf[0] << 16) + (buf[1] << 8) + buf[2]; ++ printf("PMIC@0x08:0x7 is %x\n", id); ++ id = (id >> 6) & 0x7; ++ if (id == 0x7) { ++ set_board_rev(1); ++ return 1; ++ } ++ return 0; ++} ++ + int board_late_init(void) + { +- u8 reg; ++ u8 reg[3]; + int i; +- if (i2c_read(0x69, 0x20, 1, ®, 1) < 0) { +- printf("board_late_init: read PMIC@0x20 fail\n"); ++ ++ if (board_detect()) { ++ mxc_request_iomux(MX35_PIN_WATCHDOG_RST, MUX_CONFIG_SION | ++ MUX_CONFIG_ALT1); ++ printf("i.MX35 CPU board version 2.0\n"); ++ if (i2c_read(0x08, 0x1E, 1, reg, 3)) { ++ printf("board_late_init: read PMIC@0x08:0x1E fail\n"); ++ return 0; ++ } ++ reg[2] |= 0x3; ++ if (i2c_write(0x08, 0x1E, 1, reg, 3)) { ++ printf("board_late_init: write PMIC@0x08:0x1E fail\n"); ++ return 0; ++ } ++ if (i2c_read(0x08, 0x20, 1, reg, 3)) { ++ printf("board_late_init: read PMIC@0x08:0x20 fail\n"); ++ return 0; ++ } ++ reg[2] |= 0x1; ++ if (i2c_write(0x08, 0x20, 1, reg, 3)) { ++ printf("board_late_init: write PMIC@0x08:0x20 fail\n"); ++ return 0; ++ } ++ mxc_request_iomux(MX35_PIN_COMPARE, MUX_CONFIG_GPIO); ++ mxc_iomux_set_input(MUX_IN_GPIO1_IN_5, INPUT_CTL_PATH0); ++ __REG(GPIO1_BASE_ADDR + 0x04) |= 1 << 5; ++ __REG(GPIO1_BASE_ADDR) |= 1 << 5; ++ } else ++ printf("i.MX35 CPU board version 1.0\n"); ++ ++ if (i2c_read(0x69, 0x20, 1, reg, 1) < 0) { ++ printf("board_late_init: read PMIC@0x69:0x20 fail\n"); + return 0; + } + +- reg |= 0x4; +- if (i2c_write(0x69, 0x20, 1, ®, 1) < 0) { +- printf("board_late_init: write back PMIC@0x20 fail\n"); ++ reg[0] |= 0x4; ++ if (i2c_write(0x69, 0x20, 1, reg, 1) < 0) { ++ printf("board_late_init: write back PMIC@0x69:0x20 fail\n"); + return 0; + } + + for (i = 0; i < 1000; i++) + udelay(200); + +- if (i2c_read(0x69, 0x1A, 1, ®, 1) < 0) { +- printf("board_late_init: read PMIC@0x1A fail\n"); ++ if (i2c_read(0x69, 0x1A, 1, reg, 1) < 0) { ++ printf("board_late_init: read PMIC@0x69:0x1A fail\n"); + return 0; + } + +- reg &= 0x7F; +- if (i2c_write(0x69, 0x1A, 1, ®, 1) < 0) { +- printf("board_late_init: write back PMIC@0x1A fail\n"); ++ reg[0] &= 0x7F; ++ if (i2c_write(0x69, 0x1A, 1, reg, 1) < 0) { ++ printf("board_late_init: write back PMIC@0x69:0x1A fail\n"); + return 0; + } + for (i = 0; i < 1000; i++) + udelay(200); + +- reg |= 0x80; +- if (i2c_write(0x69, 0x1A, 1, ®, 1) < 0) { +- printf("board_late_init: 2st write back PMIC@0x1A fail\n"); ++ reg[0] |= 0x80; ++ if (i2c_write(0x69, 0x1A, 1, reg, 1) < 0) { ++ printf("board_late_init: 2st write back PMIC@0x69:0x1A fail\n"); + return 0; + } + +diff --git a/include/asm-arm/arch-mx35/mx35.h b/include/asm-arm/arch-mx35/mx35.h +index b430c83..2ed85d3 100644 +--- a/include/asm-arm/arch-mx35/mx35.h ++++ b/include/asm-arm/arch-mx35/mx35.h +@@ -164,6 +164,9 @@ + #define CSCR_L(x) (WEIM_CTRL_CS#x + 4) + #define CSCR_A(x) (WEIM_CTRL_CS#x + 8) + ++#define IIM_SREV 0x24 ++#define ROMPATCH_REV 0x40 ++ + #define IPU_CONF IPU_CTRL_BASE_ADDR + + #define IPU_CONF_PXL_ENDIAN (1<<8) +diff --git a/include/configs/mx35_3stack.h b/include/configs/mx35_3stack.h +index 39be55c..a141ad0 100644 +--- a/include/configs/mx35_3stack.h ++++ b/include/configs/mx35_3stack.h +@@ -48,6 +48,7 @@ + #endif + + #define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ ++#define CONFIG_REVISION_TAG 1 + #define CONFIG_SETUP_MEMORY_TAGS 1 + #define CONFIG_INITRD_TAG 1 + +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/1000_fix_gcc_4.4_compability.patch +++ uboot-imx-2009.01/debian/patches/1000_fix_gcc_4.4_compability.patch @@ -0,0 +1,52 @@ +diff -Nur -x '*.orig' -x '*~' u-boot-imx-2009.01/common/main.c u-boot-imx-2009.01.new/common/main.c +--- u-boot-imx-2009.01/common/main.c 2009-01-21 17:08:12.000000000 -0500 ++++ u-boot-imx-2009.01.new/common/main.c 2009-07-09 12:15:22.000000000 -0400 +@@ -47,8 +47,8 @@ + /* + * Board-specific Platform code can reimplement show_boot_progress () if needed + */ +-void inline __show_boot_progress (int val) {} +-void inline show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress"))); ++void __show_boot_progress (int val) {} ++void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress"))); + + #if defined(CONFIG_BOOT_RETRY_TIME) && defined(CONFIG_RESET_TO_RETRY) + extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); /* for do_reset() prototype */ +diff -Nur -x '*.orig' -x '*~' u-boot-imx-2009.01/lib_arm/board.c u-boot-imx-2009.01.new/lib_arm/board.c +--- u-boot-imx-2009.01/lib_arm/board.c 2009-07-09 12:13:31.000000000 -0400 ++++ u-boot-imx-2009.01.new/lib_arm/board.c 2009-07-09 12:14:04.000000000 -0400 +@@ -122,20 +122,20 @@ + ************************************************************************ + * May be supplied by boards if desired + */ +-void inline __coloured_LED_init (void) {} +-void inline coloured_LED_init (void) __attribute__((weak, alias("__coloured_LED_init"))); +-void inline __red_LED_on (void) {} +-void inline red_LED_on (void) __attribute__((weak, alias("__red_LED_on"))); +-void inline __red_LED_off(void) {} +-void inline red_LED_off(void) __attribute__((weak, alias("__red_LED_off"))); +-void inline __green_LED_on(void) {} +-void inline green_LED_on(void) __attribute__((weak, alias("__green_LED_on"))); +-void inline __green_LED_off(void) {} +-void inline green_LED_off(void)__attribute__((weak, alias("__green_LED_off"))); +-void inline __yellow_LED_on(void) {} +-void inline yellow_LED_on(void)__attribute__((weak, alias("__yellow_LED_on"))); +-void inline __yellow_LED_off(void) {} +-void inline yellow_LED_off(void)__attribute__((weak, alias("__yellow_LED_off"))); ++void __coloured_LED_init (void) {} ++void coloured_LED_init (void) __attribute__((weak, alias("__coloured_LED_init"))); ++void __red_LED_on (void) {} ++void red_LED_on (void) __attribute__((weak, alias("__red_LED_on"))); ++void __red_LED_off(void) {} ++void red_LED_off(void) __attribute__((weak, alias("__red_LED_off"))); ++void __green_LED_on(void) {} ++void green_LED_on(void) __attribute__((weak, alias("__green_LED_on"))); ++void __green_LED_off(void) {} ++void green_LED_off(void)__attribute__((weak, alias("__green_LED_off"))); ++void __yellow_LED_on(void) {} ++void yellow_LED_on(void)__attribute__((weak, alias("__yellow_LED_on"))); ++void __yellow_LED_off(void) {} ++void yellow_LED_off(void)__attribute__((weak, alias("__yellow_LED_off"))); + + /************************************************************************ + * Init Utilities * --- uboot-imx-2009.01.orig/debian/patches/0001-ENGR00081147-Support-i.MX35-3stack-board.patch +++ uboot-imx-2009.01/debian/patches/0001-ENGR00081147-Support-i.MX35-3stack-board.patch @@ -0,0 +1,4567 @@ +From 6dff4beda2df6c461e03920f0f15b7548f3d231c Mon Sep 17 00:00:00 2001 +From: Fred Fan +Date: Fri, 20 Feb 2009 10:38:48 +0800 +Subject: [PATCH] ENGR00081147 Support i.MX35 3stack board + +Support boot from NOR flash +Support Multiple ethernet:LAN9217 and FEC +Support upgrade u-boot + +Signed-off-by: Fred Fan +--- + Makefile | 3 + + board/freescale/mx35_3stack/Makefile | 49 ++ + board/freescale/mx35_3stack/board-mx35_3stack.h | 107 ++++ + board/freescale/mx35_3stack/config.mk | 1 + + board/freescale/mx35_3stack/lowlevel_init.S | 406 +++++++++++++ + board/freescale/mx35_3stack/mx35_3stack.c | 189 ++++++ + board/freescale/mx35_3stack/u-boot.lds | 72 +++ + cpu/arm1136/cpu.c | 6 + + cpu/arm1136/mx35/Makefile | 47 ++ + cpu/arm1136/mx35/crm_regs.h | 258 ++++++++ + cpu/arm1136/mx35/generic.c | 205 +++++++ + cpu/arm1136/mx35/interrupts.c | 110 ++++ + cpu/arm1136/mx35/iomux.c | 149 +++++ + cpu/arm1136/mx35/serial.c | 220 +++++++ + drivers/i2c/mxc_i2c.c | 202 +++++-- + drivers/net/Makefile | 1 + + drivers/net/mxc_fec.c | 733 +++++++++++++++++++++++ + drivers/net/smc911x.c | 47 ++- + include/asm-arm/arch-mx35/iomux.h | 290 +++++++++ + include/asm-arm/arch-mx35/mx35.h | 200 ++++++ + include/asm-arm/arch-mx35/mx35_pins.h | 342 +++++++++++ + include/asm-arm/fec.h | 315 ++++++++++ + include/configs/mx35_3stack.h | 218 +++++++ + net/eth.c | 5 + + 24 files changed, 4119 insertions(+), 56 deletions(-) + +diff --git a/Makefile b/Makefile +index d533564..16744f5 100644 +--- a/Makefile ++++ b/Makefile +@@ -2964,6 +2964,9 @@ imx31_phycore_config : unconfig + mx31ads_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm1136 mx31ads freescale mx31 + ++mx35_3stack_config : unconfig ++ @$(MKCONFIG) $(@:_config=) arm arm1136 mx35_3stack freescale mx35 ++ + omap2420h4_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm1136 omap2420h4 NULL omap24xx + +diff --git a/board/freescale/mx35_3stack/Makefile b/board/freescale/mx35_3stack/Makefile +new file mode 100644 +index 0000000..4c38a8b +--- /dev/null ++++ b/board/freescale/mx35_3stack/Makefile +@@ -0,0 +1,49 @@ ++# ++# Copyright (C) 2007, Guennadi Liakhovetski ++# ++# (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++# ++# 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 := mx35_3stack.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 .depend ++ ++######################################################################### ++ ++# defines $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +diff --git a/board/freescale/mx35_3stack/board-mx35_3stack.h b/board/freescale/mx35_3stack/board-mx35_3stack.h +new file mode 100644 +index 0000000..f9c3074 +--- /dev/null ++++ b/board/freescale/mx35_3stack/board-mx35_3stack.h +@@ -0,0 +1,107 @@ ++/* ++ * ++ * (c) 2007 Pengutronix, Sascha Hauer ++ * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 __BOARD_MX35_3STACK_H ++#define __BOARD_MX35_3STACK_H ++ ++#define UNALIGNED_ACCESS_ENABLE ++#define LOW_INT_LATENCY_ENABLE ++#define BRANCH_PREDICTION_ENABLE ++ ++#define L2CC_AUX_CTL_CONFIG 0x00030024 ++ ++#define AIPS_MPR_CONFIG 0x77777777 ++#define AIPS_OPACR_CONFIG 0x00000000 ++ ++/* MPR - priority is M4 > M2 > M3 > M5 > M0 > M1 */ ++#define MAX_MPR_CONFIG 0x00302154 ++/* SGPCR - always park on last master */ ++#define MAX_SGPCR_CONFIG 0x00000010 ++/* MGPCR - restore default values */ ++#define MAX_MGPCR_CONFIG 0x00000000 ++ ++/* ++ * M3IF Control Register (M3IFCTL) ++ * MRRP[0] = L2CC0 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[1] = L2CC1 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[2] = MBX not on priority list (0 << 0) = 0x00000000 ++ * MRRP[3] = MAX1 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[4] = SDMA not on priority list (0 << 0) = 0x00000000 ++ * MRRP[5] = MPEG4 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[6] = IPU1 on priority list (1 << 6) = 0x00000040 ++ * MRRP[7] = IPU2 not on priority list (0 << 0) = 0x00000000 ++ * ------------ ++ * 0x00000040 ++ */ ++#define M3IF_CONFIG 0x00000040 ++ ++#define DBG_BASE_ADDR WEIM_CTRL_CS5 ++#define DBG_CSCR_U_CONFIG 0x0000D843 ++#define DBG_CSCR_L_CONFIG 0x22252521 ++#define DBG_CSCR_A_CONFIG 0x22220A00 ++ ++#define CCM_CCMR_CONFIG 0x003F4208 ++#define CCM_PDR0_CONFIG 0x00821000 ++ ++#define PLL_BRM_OFFSET 31 ++#define PLL_PD_OFFSET 26 ++#define PLL_MFD_OFFSET 16 ++#define PLL_MFI_OFFSET 10 ++ ++#define _PLL_BRM(x) ((x) << PLL_BRM_OFFSET) ++#define _PLL_PD(x) (((x) - 1) << PLL_PD_OFFSET) ++#define _PLL_MFD(x) (((x) - 1) << PLL_MFD_OFFSET) ++#define _PLL_MFI(x) ((x) << PLL_MFI_OFFSET) ++#define _PLL_MFN(x) (x) ++#define _PLL_SETTING(brm, pd, mfd, mfi, mfn) \ ++ (_PLL_BRM(brm) | _PLL_PD(pd) | _PLL_MFD(mfd) | _PLL_MFI(mfi) |\ ++ _PLL_MFN(mfn)) ++ ++#define CCM_MPLL_532_HZ _PLL_SETTING(1, 1, 12, 11, 1) ++#define CCM_MPLL_399_HZ _PLL_SETTING(0, 1, 16, 8, 5) ++#define CCM_PPLL_300_HZ _PLL_SETTING(0, 1, 4, 6, 1) ++ ++/*MEMORY SETING*/ ++#define ESDCTL_0x92220000 0x92220000 ++#define ESDCTL_0xA2220000 0xA2220000 ++#define ESDCTL_0xB2220000 0xB2220000 ++#define ESDCTL_0x82228080 0x82228080 ++ ++#define ESDCTL_PRECHARGE 0x00000400 ++ ++#define ESDCTL_MDDR_CONFIG 0x007FFC3F ++#define ESDCTL_MDDR_MR 0x00000033 ++#define ESDCTL_MDDR_EMR 0x02000000 ++ ++#define ESDCTL_DDR2_CONFIG 0x007FFC3F ++#define ESDCTL_DDR2_EMR2 0x04000000 ++#define ESDCTL_DDR2_EMR3 0x06000000 ++#define ESDCTL_DDR2_EN_DLL 0x02000400 ++#define ESDCTL_DDR2_RESET_DLL 0x00000333 ++#define ESDCTL_DDR2_MR 0x00000233 ++#define ESDCTL_DDR2_OCD_DEFAULT 0x02000780 ++ ++#define ESDCTL_DELAY_LINE5 0x00F49F00 ++#endif /* __BOARD_MX35_3STACK_H */ +diff --git a/board/freescale/mx35_3stack/config.mk b/board/freescale/mx35_3stack/config.mk +new file mode 100644 +index 0000000..d34dc02 +--- /dev/null ++++ b/board/freescale/mx35_3stack/config.mk +@@ -0,0 +1 @@ ++TEXT_BASE = 0x87f00000 +diff --git a/board/freescale/mx35_3stack/lowlevel_init.S b/board/freescale/mx35_3stack/lowlevel_init.S +new file mode 100644 +index 0000000..84614fc +--- /dev/null ++++ b/board/freescale/mx35_3stack/lowlevel_init.S +@@ -0,0 +1,406 @@ ++/* ++ * Copyright (C) 2007, Guennadi Liakhovetski ++ * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include "board-mx35_3stack.h" ++ ++/* ++ * L2CC Cache setup/invalidation/disable ++ */ ++.macro init_l2cc ++ /* Disable L2 cache first */ ++ mov r0, #L2CC_BASE_ADDR ++ ldr r1, [r0, #L2_CACHE_CTL_REG] ++ bic r1, r1, #0x1 ++ str r1, [r0, #L2_CACHE_CTL_REG] ++ ++ /* ++ * Configure L2 Cache: ++ * - 128k size(16k way) ++ * - 8-way associativity ++ * - 0 ws TAG/VALID/DIRTY ++ * - 4 ws DATA R/W ++ */ ++ ldr r1, [r0, #L2_CACHE_AUX_CTL_REG] ++ and r1, r1, #0xFE000000 ++ ldr r2, =L2CC_AUX_CTL_CONFIG ++ orr r1, r1, r2 ++ str r1, [r0, #L2_CACHE_AUX_CTL_REG] ++ ++/* Workaournd for DDR issue:WT*/ ++ ldr r1, [r0, #L2_CACHE_DBG_CTL_REG] ++ orr r1, r1, #2 ++ str r1, [r0, #L2_CACHE_DBG_CTL_REG] ++ ++ /* Invalidate L2 */ ++ mov r1, #0x000000FF ++ str r1, [r0, #L2_CACHE_INV_WAY_REG] ++1: ++ /* Poll Invalidate By Way register */ ++ ldr r2, [r0, #L2_CACHE_INV_WAY_REG] ++ cmp r2, #0 ++ bne 1b ++.endm /* init_l2cc */ ++ ++/* AIPS setup - Only setup MPROTx registers. ++ * The PACR default values are good.*/ ++.macro init_aips ++ /* ++ * Set all MPROTx to be non-bufferable, trusted for R/W, ++ * not forced to user-mode. ++ */ ++ ldr r0, =AIPS1_BASE_ADDR ++ ldr r1, =AIPS_MPR_CONFIG ++ str r1, [r0, #0x00] ++ str r1, [r0, #0x04] ++ ldr r0, =AIPS2_BASE_ADDR ++ str r1, [r0, #0x00] ++ str r1, [r0, #0x04] ++ ++ /* ++ * Clear the on and off peripheral modules Supervisor Protect bit ++ * for SDMA to access them. Did not change the AIPS control registers ++ * (offset 0x20) access type ++ */ ++ ldr r0, =AIPS1_BASE_ADDR ++ ldr r1, =AIPS_OPACR_CONFIG ++ str r1, [r0, #0x40] ++ str r1, [r0, #0x44] ++ str r1, [r0, #0x48] ++ str r1, [r0, #0x4C] ++ str r1, [r0, #0x50] ++ ldr r0, =AIPS2_BASE_ADDR ++ str r1, [r0, #0x40] ++ str r1, [r0, #0x44] ++ str r1, [r0, #0x48] ++ str r1, [r0, #0x4C] ++ str r1, [r0, #0x50] ++.endm /* init_aips */ ++ ++/* MAX (Multi-Layer AHB Crossbar Switch) setup */ ++.macro init_max ++ ldr r0, =MAX_BASE_ADDR ++ /* MPR - priority is M4 > M2 > M3 > M5 > M0 > M1 */ ++ ldr r1, =MAX_MPR_CONFIG ++ str r1, [r0, #0x000] /* for S0 */ ++ str r1, [r0, #0x100] /* for S1 */ ++ str r1, [r0, #0x200] /* for S2 */ ++ str r1, [r0, #0x300] /* for S3 */ ++ str r1, [r0, #0x400] /* for S4 */ ++ /* SGPCR - always park on last master */ ++ ldr r1, =MAX_SGPCR_CONFIG ++ str r1, [r0, #0x010] /* for S0 */ ++ str r1, [r0, #0x110] /* for S1 */ ++ str r1, [r0, #0x210] /* for S2 */ ++ str r1, [r0, #0x310] /* for S3 */ ++ str r1, [r0, #0x410] /* for S4 */ ++ /* MGPCR - restore default values */ ++ ldr r1, =MAX_MGPCR_CONFIG ++ str r1, [r0, #0x800] /* for M0 */ ++ str r1, [r0, #0x900] /* for M1 */ ++ str r1, [r0, #0xA00] /* for M2 */ ++ str r1, [r0, #0xB00] /* for M3 */ ++ str r1, [r0, #0xC00] /* for M4 */ ++ str r1, [r0, #0xD00] /* for M5 */ ++.endm /* init_max */ ++ ++/* M3IF setup */ ++.macro init_m3if ++ /* Configure M3IF registers */ ++ ldr r1, =M3IF_BASE_ADDR ++ /* ++ * M3IF Control Register (M3IFCTL) ++ * MRRP[0] = L2CC0 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[1] = L2CC1 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[2] = MBX not on priority list (0 << 0) = 0x00000000 ++ * MRRP[3] = MAX1 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[4] = SDMA not on priority list (0 << 0) = 0x00000000 ++ * MRRP[5] = MPEG4 not on priority list (0 << 0) = 0x00000000 ++ * MRRP[6] = IPU1 on priority list (1 << 6) = 0x00000040 ++ * MRRP[7] = IPU2 not on priority list (0 << 0) = 0x00000000 ++ * ------------ ++ * 0x00000040 ++ */ ++ ldr r0, =M3IF_CONFIG ++ str r0, [r1] /* M3IF control reg */ ++.endm /* init_m3if */ ++ ++/* To support 133MHz DDR */ ++.macro init_drive_strength ++/* ++ mov r0, #0x2 ++ ldr r1, =IOMUXC_BASE_ADDR ++ add r1, r1, #0x368 ++ add r2, r1, #0x4C8 - 0x368 ++1: str r0, [r1], #4 ++ cmp r1, r2 ++ ble 1b ++*/ ++.endm /* init_drive_strength */ ++ ++/* CPLD on CS5 setup */ ++.macro init_debug_board ++ ldr r0, =DBG_BASE_ADDR ++ ldr r1, =DBG_CSCR_U_CONFIG ++ str r1, [r0, #0x00] ++ ldr r1, =DBG_CSCR_L_CONFIG ++ str r1, [r0, #0x04] ++ ldr r1, =DBG_CSCR_A_CONFIG ++ str r1, [r0, #0x08] ++.endm /* init_debug_board */ ++ ++/* clock setup */ ++.macro init_clock ++ ldr r0, =CCM_BASE_ADDR ++ ++ /* default CLKO to 1/32 of the ARM core*/ ++ ldr r1, [r0, #CLKCTL_COSR] ++ bic r1, r1, #0x00000FF00 ++ bic r1, r1, #0x0000000FF ++ mov r2, #0x00006C00 ++ add r2, r2, #0x67 ++ orr r1, r1, r2 ++ str r1, [r0, #CLKCTL_COSR] ++ ++ ldr r2, =CCM_CCMR_CONFIG ++ str r2, [r0, #CLKCTL_CCMR] ++ ++ ldr r2, [r0, #CLKCTL_PDR0] ++ tst r2, #CLKMODE_CONSUMER ++ ldrne r3, =CCM_MPLL_532_HZ /* consumer path*/ ++ ldreq r3, =CCM_MPLL_399_HZ /* auto path*/ ++ ++ str r3, [r0, #CLKCTL_MPCTL] ++ ++ ldr r1, =CCM_PPLL_300_HZ ++ str r1, [r0, #CLKCTL_PPCTL] ++ ++ ldr r1, [r0, #CLKCTL_PDR0] ++ orr r1, r1, #0x800000 ++ str r1, [r0, #CLKCTL_PDR0] ++ ++ ldr r1, =CCM_PDR0_CONFIG ++ str r1, [r0, #CLKCTL_PDR0] ++ ++ ldr r1, [r0, #CLKCTL_CGR0] ++ orr r1, r1, #0x00300000 ++ str r1, [r0, #CLKCTL_CGR0] ++ ++ ldr r1, [r0, #CLKCTL_CGR1] ++ orr r1, r1, #0x00000C00 ++ orr r1, r1, #0x00000003 ++ str r1, [r0, #CLKCTL_CGR1] ++.endm /* init_clock */ ++ ++.macro setup_sdram ++ ldr r0, =ESDCTL_BASE_ADDR ++ mov r3, #0x2000 ++ str r3, [r0, #0x0] ++ str r3, [r0, #0x8] ++ ++ /*ip(r12) has used to save lr register in upper calling*/ ++ mov fp, lr ++ ++ mov r5, #0x00 ++ mov r2, #0x00 ++ mov r1, #CSD0_BASE_ADDR ++ bl setup_sdram_bank ++ cmp r3, #0x0 ++ orreq r5, r5, #1 ++ eorne r2, r2, #0x1 ++ blne setup_sdram_bank ++ ++ mov lr, fp ++ ++ cmp r5, #0 ++ movne r3, #L2CC_BASE_ADDR ++ ldrne r4, [r3, #L2_CACHE_AUX_CTL_REG] ++ orrne r4, r4, #0x1000 ++ strne r4, [r3, #L2_CACHE_AUX_CTL_REG] ++ ++ ldr r3, =ESDCTL_DELAY_LINE5 ++ str r3, [r0, #0x30] ++.endm /* setup_sdram */ ++ ++.globl lowlevel_init ++lowlevel_init: ++ /* Platform CHIP level init*/ ++#ifdef TURN_OFF_IMPRECISE_ABORT ++ mrs r0, cpsr ++ bic r0, r0, #0x100 ++ msr cpsr, r0 ++#endif ++ ++ mrc 15, 0, r1, c1, c0, 0 ++ ++#ifndef BRANCH_PREDICTION_ENABLE ++ mrc 15, 0, r0, c1, c0, 1 ++ bic r0, r0, #7 ++ mcr 15, 0, r0, c1, c0, 1 ++#else ++ mrc 15, 0, r0, c1, c0, 1 ++ orr r0, r0, #7 ++ mcr 15, 0, r0, c1, c0, 1 ++ orr r1, r1, #(1<<11) ++#endif ++ ++#ifdef UNALIGNED_ACCESS_ENABLE ++ orr r1, r1, #(1<<22) ++#endif ++ ++#ifdef LOW_INT_LATENCY_ENABLE ++ orr r1, r1, #(1<<21) ++#endif ++ mcr 15, 0, r1, c1, c0, 0 ++ ++ mov r0, #0 ++#ifdef BRANCH_PREDICTION_ENABLE ++ mcr 15, 0, r0, c15, c2, 4 ++#endif ++ mcr 15, 0, r0, c7, c10, 4 /* Drain the write buffer */ ++ ++ init_l2cc ++ ++ /* initializes very early AIPS, what for? ++ * Then it also initializes Multi-Layer AHB Crossbar Switch, ++ * M3IF */ ++ /* Also setup the Peripheral Port Remap register inside the core */ ++ ldr r0, =0x40000015 /* start from AIPS 2GB region */ ++ mcr p15, 0, r0, c15, c2, 4 ++ ++ init_aips ++ ++ init_max ++ ++ init_m3if ++ ++ init_drive_strength ++ ++ cmp pc, #PHYS_SDRAM_1 ++ blo init_clock_start ++ cmp pc, #(PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE) ++ blo skip_sdram_setup ++ ++init_clock_start: ++ init_clock ++ init_debug_board ++ /*init_sdram*/ ++ setup_sdram ++skip_sdram_setup: ++ mov pc, lr ++ ++/* ++ * r0: ESDCTL control base, r1: sdram slot base ++ * r2: DDR type(0:DDR2, 1:MDDR) r3, r4:working base ++ */ ++setup_sdram_bank: ++ mov r3, #0xE /*0xA + 0x4*/ ++ tst r2, #0x1 ++ orreq r3, r3, #0x300 /*DDR2*/ ++ str r3, [r0, #0x10] ++ bic r3, r3, #0x00A ++ str r3, [r0, #0x10] ++ beq 2f ++ ++ mov r3, #0x20000 ++1: subs r3, r3, #1 ++ bne 1b ++ ++2: tst r2, #0x1 ++ ldreq r3, =ESDCTL_DDR2_CONFIG ++ ldrne r3, =ESDCTL_MDDR_CONFIG ++ cmp r1, #CSD1_BASE_ADDR ++ strlo r3, [r0, #0x4] ++ strhs r3, [r0, #0xC] ++ ++ ldr r3, =ESDCTL_0x92220000 ++ strlo r3, [r0, #0x0] ++ strhs r3, [r0, #0x8] ++ mov r3, #0xDA ++ ldr r4, =ESDCTL_PRECHARGE ++ strb r3, [r1, r4] ++ ++ tst r2, #0x1 ++ bne skip_set_mode ++ ++ cmp r1, #CSD1_BASE_ADDR ++ ldr r3, =ESDCTL_0xB2220000 ++ strlo r3, [r0, #0x0] ++ strhs r3, [r0, #0x8] ++ mov r3, #0xDA ++ ldr r4, =ESDCTL_DDR2_EMR2 ++ strb r3, [r1, r4] ++ ldr r4, =ESDCTL_DDR2_EMR3 ++ strb r3, [r1, r4] ++ ldr r4, =ESDCTL_DDR2_EN_DLL ++ strb r3, [r1, r4] ++ ldr r4, =ESDCTL_DDR2_RESET_DLL ++ strb r3, [r1, r4] ++ ++ ldr r3, =ESDCTL_0x92220000 ++ strlo r3, [r0, #0x0] ++ strhs r3, [r0, #0x8] ++ mov r3, #0xDA ++ ldr r4, =ESDCTL_PRECHARGE ++ strb r3, [r1, r4] ++ ++skip_set_mode: ++ cmp r1, #CSD1_BASE_ADDR ++ ldr r3, =ESDCTL_0xA2220000 ++ strlo r3, [r0, #0x0] ++ strhs r3, [r0, #0x8] ++ mov r3, #0xDA ++ strb r3, [r1] ++ strb r3, [r1] ++ ++ ldr r3, =ESDCTL_0xB2220000 ++ strlo r3, [r0, #0x0] ++ strhs r3, [r0, #0x8] ++ tst r2, #0x1 ++ ldreq r4, =ESDCTL_DDR2_MR ++ ldrne r4, =ESDCTL_MDDR_MR ++ mov r3, #0xDA ++ strb r3, [r1, r4] ++ ldreq r4, =ESDCTL_DDR2_OCD_DEFAULT ++ streqb r3, [r1, r4] ++ ldreq r4, =ESDCTL_DDR2_EN_DLL ++ ldrne r4, =ESDCTL_MDDR_EMR ++ strb r3, [r1, r4] ++ ++ cmp r1, #CSD1_BASE_ADDR ++ ldr r3, =ESDCTL_0x82228080 ++ strlo r3, [r0, #0x0] ++ strhs r3, [r0, #0x8] ++ ++ tst r2, #0x1 ++ moveq r4, #0x20000 ++ movne r4, #0x200 ++1: subs r4, r4, #1 ++ bne 1b ++ ++ str r3, [r1, #0x100] ++ ldr r4, [r1, #0x100] ++ cmp r3, r4 ++ movne r3, #1 ++ moveq r3, #0 ++ ++ mov pc, lr +diff --git a/board/freescale/mx35_3stack/mx35_3stack.c b/board/freescale/mx35_3stack/mx35_3stack.c +new file mode 100644 +index 0000000..f6d5641 +--- /dev/null ++++ b/board/freescale/mx35_3stack/mx35_3stack.c +@@ -0,0 +1,189 @@ ++/* ++ * Copyright (C) 2007, Guennadi Liakhovetski ++ * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++int dram_init(void) ++{ ++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1; ++ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; ++ ++ return 0; ++} ++ ++int board_init(void) ++{ ++ int pad; ++ ++ /* enable clocks */ ++ __REG(CCM_BASE_ADDR + CLKCTL_CGR0) |= 0x003F0000; ++ __REG(CCM_BASE_ADDR + CLKCTL_CGR1) |= 0x00030FFF; ++ ++ /* setup pins for I2C1 */ ++ mxc_request_iomux(MX35_PIN_I2C1_CLK, MUX_CONFIG_SION); ++ mxc_request_iomux(MX35_PIN_I2C1_DAT, MUX_CONFIG_SION); ++ ++ pad = (PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE \ ++ | PAD_CTL_PUE_PUD | PAD_CTL_ODE_OpenDrain); ++ ++ mxc_iomux_set_pad(MX35_PIN_I2C1_CLK, pad); ++ mxc_iomux_set_pad(MX35_PIN_I2C1_DAT, pad); ++ ++ /* setup pins for FEC */ ++ mxc_request_iomux(MX35_PIN_FEC_TX_CLK, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_RX_CLK, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_RX_DV, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_COL, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_RDATA0, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_TDATA0, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_TX_EN, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_MDC, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_MDIO, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_TX_ERR, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_RX_ERR, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_CRS, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_RDATA1, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_TDATA1, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_RDATA2, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_TDATA2, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_RDATA3, MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_FEC_TDATA3, MUX_CONFIG_FUNC); ++ ++ pad = (PAD_CTL_DRV_3_3V | PAD_CTL_PUE_PUD | PAD_CTL_ODE_CMOS | \ ++ PAD_CTL_DRV_NORMAL | PAD_CTL_SRE_SLOW); ++ ++ mxc_iomux_set_pad(MX35_PIN_FEC_TX_CLK, pad | PAD_CTL_HYS_SCHMITZ | \ ++ PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_RX_CLK, pad | PAD_CTL_HYS_SCHMITZ | \ ++ PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_RX_DV, pad | PAD_CTL_HYS_SCHMITZ | \ ++ PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_COL, pad | PAD_CTL_HYS_SCHMITZ | \ ++ PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_RDATA0, pad | PAD_CTL_HYS_SCHMITZ | \ ++ PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_TDATA0, pad | PAD_CTL_HYS_CMOS | \ ++ PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_TX_EN, pad | PAD_CTL_HYS_CMOS | \ ++ PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_MDC, pad | PAD_CTL_HYS_CMOS | \ ++ PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_MDIO, pad | PAD_CTL_HYS_SCHMITZ | \ ++ PAD_CTL_PKE_ENABLE | PAD_CTL_22K_PU); ++ mxc_iomux_set_pad(MX35_PIN_FEC_TX_ERR, pad | PAD_CTL_HYS_CMOS | \ ++ PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_RX_ERR, pad | PAD_CTL_HYS_SCHMITZ | \ ++ PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_CRS, pad | PAD_CTL_HYS_SCHMITZ | \ ++ PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_RDATA1, pad | PAD_CTL_HYS_SCHMITZ | \ ++ PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_TDATA1, pad | PAD_CTL_HYS_CMOS | \ ++ PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_RDATA2, pad | PAD_CTL_HYS_SCHMITZ | \ ++ PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_TDATA2, pad | PAD_CTL_HYS_CMOS | \ ++ PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_RDATA3, pad | PAD_CTL_HYS_SCHMITZ | \ ++ PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PD); ++ mxc_iomux_set_pad(MX35_PIN_FEC_TDATA3, pad | PAD_CTL_HYS_CMOS | \ ++ PAD_CTL_PKE_NONE | PAD_CTL_100K_PD); ++ ++ gd->bd->bi_arch_number = MACH_TYPE_MX35_3DS; /* board id for linux */ ++ gd->bd->bi_boot_params = 0x80000100; /* address of boot parameters */ ++ ++ return 0; ++} ++ ++#ifdef BOARD_LATE_INIT ++int board_late_init(void) ++{ ++ u8 reg; ++ int i; ++ if (i2c_read(0x69, 0x20, 1, ®, 1) < 0) { ++ printf("board_late_init: read PMIC@0x20 fail\n"); ++ return 0; ++ } ++ ++ reg |= 0x4; ++ if (i2c_write(0x69, 0x20, 1, ®, 1) < 0) { ++ printf("board_late_init: write back PMIC@0x20 fail\n"); ++ return 0; ++ } ++ ++ for (i = 0; i < 1000; i++) ++ udelay(200); ++ ++ if (i2c_read(0x69, 0x1A, 1, ®, 1) < 0) { ++ printf("board_late_init: read PMIC@0x1A fail\n"); ++ return 0; ++ } ++ ++ reg &= 0x7F; ++ if (i2c_write(0x69, 0x1A, 1, ®, 1) < 0) { ++ printf("board_late_init: write back PMIC@0x1A fail\n"); ++ return 0; ++ } ++ for (i = 0; i < 1000; i++) ++ udelay(200); ++ ++ reg |= 0x80; ++ if (i2c_write(0x69, 0x1A, 1, ®, 1) < 0) { ++ printf("board_late_init: 2st write back PMIC@0x1A fail\n"); ++ return 0; ++ } ++ ++ return 0; ++} ++#endif ++ ++int checkboard(void) ++{ ++ printf("Board: MX35 3STACK ["); ++ switch (__REG(CCM_BASE_ADDR + CLKCTL_RCSR) & 0x0F) { ++ case 0x0000: ++ printf("POR"); ++ break; ++ case 0x0002: ++ printf("JTAG"); ++ break; ++ case 0x0004: ++ printf("RST"); ++ break; ++ case 0x0008: ++ printf("WDT"); ++ break; ++ default: ++ printf("unknown"); ++ } ++ printf("]\n"); ++ return 0; ++} +diff --git a/board/freescale/mx35_3stack/u-boot.lds b/board/freescale/mx35_3stack/u-boot.lds +new file mode 100644 +index 0000000..8a565e7 +--- /dev/null ++++ b/board/freescale/mx35_3stack/u-boot.lds +@@ -0,0 +1,72 @@ ++/* ++ * January 2004 - Changed to support H4 device ++ * Copyright (c) 2004 Texas Instruments ++ * ++ * (C) Copyright 2002 ++ * Gary Jennejohn, DENX Software Engineering, ++ * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 : ++ { ++ /* WARNING - the following is hand-optimized to fit within */ ++ /* the sector layout of our flash chips! XXX FIXME XXX */ ++ ++ cpu/arm1136/start.o (.text) ++ board/freescale/mx35_3stack/libmx35_3stack.a (.text) ++ lib_arm/libarm.a (.text) ++ net/libnet.a (.text) ++ drivers/mtd/libmtd.a (.text) ++ ++ . = DEFINED(env_offset) ? env_offset : .; ++ common/env_embedded.o(.text) ++ ++ *(.text) ++ } ++ ++ . = 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 = .; ++} +diff --git a/cpu/arm1136/cpu.c b/cpu/arm1136/cpu.c +index 0486163..c59c1c3 100644 +--- a/cpu/arm1136/cpu.c ++++ b/cpu/arm1136/cpu.c +@@ -8,6 +8,8 @@ + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * + * See file CREDITS for list of people who contributed to this + * project. + * +@@ -127,6 +129,10 @@ int cleanup_before_linux (void) + i = 0; + asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); /* invalidate both caches and flush btb */ + asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); /* mem barrier to sync things */ ++/*Workaround to enable L2CC during kernel decompressing*/ ++#ifdef fixup_before_linux ++ fixup_before_linux; ++#endif + return(0); + } + +diff --git a/cpu/arm1136/mx35/Makefile b/cpu/arm1136/mx35/Makefile +new file mode 100644 +index 0000000..e83cbf7 +--- /dev/null ++++ b/cpu/arm1136/mx35/Makefile +@@ -0,0 +1,47 @@ ++# ++# (C) Copyright 2000-2006 ++# Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++# ++# (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++# ++# 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 = interrupts.o serial.o generic.o iomux.o ++ ++SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) ++OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) ++ ++all: $(obj).depend $(LIB) ++ ++$(LIB): $(OBJS) ++ $(AR) $(ARFLAGS) $@ $(OBJS) ++ ++######################################################################### ++ ++# defines $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +diff --git a/cpu/arm1136/mx35/crm_regs.h b/cpu/arm1136/mx35/crm_regs.h +new file mode 100644 +index 0000000..082fdc6 +--- /dev/null ++++ b/cpu/arm1136/mx35/crm_regs.h +@@ -0,0 +1,258 @@ ++/* ++ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++#ifndef __CPU_ARM1136_MX35_CRM_REGS_H__ ++#define __CPU_ARM1136_MX35_CRM_REGS_H__ ++ ++/* Register bit definitions */ ++#define MXC_CCM_CCMR_WFI (1 << 30) ++#define MXC_CCM_CCMR_STBY_EXIT_SRC (1 << 29) ++#define MXC_CCM_CCMR_VSTBY (1 << 28) ++#define MXC_CCM_CCMR_WBEN (1 << 27) ++#define MXC_CCM_CCMR_VOL_RDY_CNT_OFFSET 20 ++#define MXC_CCM_CCMR_VOL_RDY_CNT_MASK (0xF << 20) ++#define MXC_CCM_CCMR_ROMW_OFFSET 18 ++#define MXC_CCM_CCMR_ROMW_MASK (0x3 << 18) ++#define MXC_CCM_CCMR_RAMW_OFFSET 21 ++#define MXC_CCM_CCMR_RAMW_MASK (0x3 << 21) ++#define MXC_CCM_CCMR_LPM_OFFSET 14 ++#define MXC_CCM_CCMR_LPM_MASK (0x3 << 14) ++#define MXC_CCM_CCMR_UPE (1 << 9) ++#define MXC_CCM_CCMR_MPE (1 << 3) ++ ++#define MXC_CCM_PDR0_PER_SEL (1 << 26) ++#define MXC_CCM_PDR0_IPU_HND_BYP (1 << 23) ++#define MXC_CCM_PDR0_HSP_PODF_OFFSET 20 ++#define MXC_CCM_PDR0_HSP_PODF_MASK (0x3 << 20) ++#define MXC_CCM_PDR0_CON_MUX_DIV_OFFSET 16 ++#define MXC_CCM_PDR0_CON_MUX_DIV_MASK (0xF << 16) ++#define MXC_CCM_PDR0_CKIL_SEL (1 << 15) ++#define MXC_CCM_PDR0_PER_PODF_OFFSET 12 ++#define MXC_CCM_PDR0_PER_PODF_MASK (0xF << 12) ++#define MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET 9 ++#define MXC_CCM_PDR0_AUTO_MUX_DIV_MASK (0x7 << 9) ++#define MXC_CCM_PDR0_AUTO_CON 0x1 ++ ++#define MXC_CCM_PDR1_MSHC_PRDF_OFFSET 28 ++#define MXC_CCM_PDR1_MSHC_PRDF_MASK (0x7 << 28) ++#define MXC_CCM_PDR1_MSHC_PODF_OFFSET 22 ++#define MXC_CCM_PDR1_MSHC_PODF_MASK (0x3F << 22) ++#define MXC_CCM_PDR1_MSHC_M_U (1 << 7) ++ ++#define MXC_CCM_PDR2_SSI2_PRDF_OFFSET 27 ++#define MXC_CCM_PDR2_SSI2_PRDF_MASK (0x7 << 27) ++#define MXC_CCM_PDR2_SSI1_PRDF_OFFSET 24 ++#define MXC_CCM_PDR2_SSI1_PRDF_MASK (0x7 << 24) ++#define MXC_CCM_PDR2_CSI_PRDF_OFFSET 19 ++#define MXC_CCM_PDR2_CSI_PRDF_MASK (0x7 << 19) ++#define MXC_CCM_PDR2_CSI_PODF_OFFSET 16 ++#define MXC_CCM_PDR2_CSI_PODF_MASK (0x7 << 16) ++#define MXC_CCM_PDR2_SSI2_PODF_OFFSET 8 ++#define MXC_CCM_PDR2_SSI2_PODF_MASK (0x3F << 8) ++#define MXC_CCM_PDR2_CSI_M_U (1 << 7) ++#define MXC_CCM_PDR2_SSI_M_U (1 << 6) ++#define MXC_CCM_PDR2_SSI1_PODF_OFFSET 0 ++#define MXC_CCM_PDR2_SSI1_PODF_MASK (0x3F) ++ ++#define MXC_CCM_PDR3_SPDIF_PRDF_OFFSET 29 ++#define MXC_CCM_PDR3_SPDIF_PRDF_MASK (0x7 << 29) ++#define MXC_CCM_PDR3_SPDIF_PODF_OFFSET 23 ++#define MXC_CCM_PDR3_SPDIF_PODF_MASK (0x3F << 23) ++#define MXC_CCM_PDR3_SPDIF_M_U (1 << 22) ++#define MXC_CCM_PDR3_ESDHC3_PRDF_OFFSET 19 ++#define MXC_CCM_PDR3_ESDHC3_PRDF_MASK (0x7 << 19) ++#define MXC_CCM_PDR3_ESDHC3_PODF_OFFSET 16 ++#define MXC_CCM_PDR3_ESDHC3_PODF_MASK (0x7 << 16) ++#define MXC_CCM_PDR3_UART_M_U (1 << 15) ++#define MXC_CCM_PDR3_ESDHC2_PRDF_OFFSET 11 ++#define MXC_CCM_PDR3_ESDHC2_PRDF_MASK (0x7 << 11) ++#define MXC_CCM_PDR3_ESDHC2_PODF_OFFSET 8 ++#define MXC_CCM_PDR3_ESDHC2_PODF_MASK (0x7 << 8) ++#define MXC_CCM_PDR3_ESDHC_M_U (1 << 6) ++#define MXC_CCM_PDR3_ESDHC1_PRDF_OFFSET 3 ++#define MXC_CCM_PDR3_ESDHC1_PRDF_MASK (0x7 << 3) ++#define MXC_CCM_PDR3_ESDHC1_PODF_OFFSET 0 ++#define MXC_CCM_PDR3_ESDHC1_PODF_MASK (0x7) ++ ++#define MXC_CCM_PDR4_NFC_PODF_OFFSET 28 ++#define MXC_CCM_PDR4_NFC_PODF_MASK (0xF << 28) ++#define MXC_CCM_PDR4_USB_PRDF_OFFSET 25 ++#define MXC_CCM_PDR4_USB_PRDF_MASK (0x7 << 25) ++#define MXC_CCM_PDR4_USB_PODF_OFFSET 22 ++#define MXC_CCM_PDR4_USB_PODF_MASK (0x7 << 22) ++#define MXC_CCM_PDR4_PER0_PRDF_OFFSET 19 ++#define MXC_CCM_PDR4_PER0_PRDF_MASK (0x7 << 19) ++#define MXC_CCM_PDR4_PER0_PODF_OFFSET 16 ++#define MXC_CCM_PDR4_PER0_PODF_MASK (0x7 << 16) ++#define MXC_CCM_PDR4_UART_PRDF_OFFSET 13 ++#define MXC_CCM_PDR4_UART_PRDF_MASK (0x7 << 13) ++#define MXC_CCM_PDR4_UART_PODF_OFFSET 10 ++#define MXC_CCM_PDR4_UART_PODF_MASK (0x7 << 10) ++#define MXC_CCM_PDR4_USB_M_U (1 << 9) ++ ++/* Bit definitions for RCSR */ ++#define MXC_CCM_RCSR_BUS_WIDTH (1 << 29) ++#define MXC_CCM_RCSR_BUS_16BIT (1 << 29) ++#define MXC_CCM_RCSR_PAGE_SIZE (3 << 27) ++#define MXC_CCM_RCSR_PAGE_512 (0 << 27) ++#define MXC_CCM_RCSR_PAGE_2K (1 << 27) ++#define MXC_CCM_RCSR_PAGE_4K1 (2 << 27) ++#define MXC_CCM_RCSR_PAGE_4K2 (3 << 27) ++#define MXC_CCM_RCSR_SOFT_RESET (1 << 15) ++#define MXC_CCM_RCSR_NF16B (1 << 14) ++#define MXC_CCM_RCSR_NFC_4K (1 << 9) ++#define MXC_CCM_RCSR_NFC_FMS (1 << 8) ++ ++/* Bit definitions for both MCU, PERIPHERAL PLL control registers */ ++#define MXC_CCM_PCTL_BRM 0x80000000 ++#define MXC_CCM_PCTL_PD_OFFSET 26 ++#define MXC_CCM_PCTL_PD_MASK (0xF << 26) ++#define MXC_CCM_PCTL_MFD_OFFSET 16 ++#define MXC_CCM_PCTL_MFD_MASK (0x3FF << 16) ++#define MXC_CCM_PCTL_MFI_OFFSET 10 ++#define MXC_CCM_PCTL_MFI_MASK (0xF << 10) ++#define MXC_CCM_PCTL_MFN_OFFSET 0 ++#define MXC_CCM_PCTL_MFN_MASK 0x3FF ++ ++/* Bit definitions for Audio clock mux register*/ ++#define MXC_CCM_ACMR_ESAI_CLK_SEL_OFFSET 12 ++#define MXC_CCM_ACMR_ESAI_CLK_SEL_MASK (0xF << 12) ++#define MXC_CCM_ACMR_SPDIF_CLK_SEL_OFFSET 8 ++#define MXC_CCM_ACMR_SPDIF_CLK_SEL_MASK (0xF << 8) ++#define MXC_CCM_ACMR_SSI1_CLK_SEL_OFFSET 4 ++#define MXC_CCM_ACMR_SSI1_CLK_SEL_MASK (0xF << 4) ++#define MXC_CCM_ACMR_SSI2_CLK_SEL_OFFSET 0 ++#define MXC_CCM_ACMR_SSI2_CLK_SEL_MASK (0xF << 0) ++ ++/* Bit definitions for Clock gating Register*/ ++#define MXC_CCM_CGR0_ASRC_OFFSET 0 ++#define MXC_CCM_CGR0_ASRC_MASK (0x3 << 0) ++#define MXC_CCM_CGR0_ATA_OFFSET 2 ++#define MXC_CCM_CGR0_ATA_MASK (0x3 << 2) ++#define MXC_CCM_CGR0_CAN1_OFFSET 6 ++#define MXC_CCM_CGR0_CAN1_MASK (0x3 << 6) ++#define MXC_CCM_CGR0_CAN2_OFFSET 8 ++#define MXC_CCM_CGR0_CAN2_MASK (0x3 << 8) ++#define MXC_CCM_CGR0_CSPI1_OFFSET 10 ++#define MXC_CCM_CGR0_CSPI1_MASK (0x3 << 10) ++#define MXC_CCM_CGR0_CSPI2_OFFSET 12 ++#define MXC_CCM_CGR0_CSPI2_MASK (0x3 << 12) ++#define MXC_CCM_CGR0_ECT_OFFSET 14 ++#define MXC_CCM_CGR0_ECT_MASK (0x3 << 14) ++#define MXC_CCM_CGR0_EMI_OFFSET 18 ++#define MXC_CCM_CGR0_EMI_MASK (0x3 << 18) ++#define MXC_CCM_CGR0_EPIT1_OFFSET 20 ++#define MXC_CCM_CGR0_EPIT1_MASK (0x3 << 20) ++#define MXC_CCM_CGR0_EPIT2_OFFSET 22 ++#define MXC_CCM_CGR0_EPIT2_MASK (0x3 << 22) ++#define MXC_CCM_CGR0_ESAI_OFFSET 24 ++#define MXC_CCM_CGR0_ESAI_MASK (0x3 << 24) ++#define MXC_CCM_CGR0_ESDHC1_OFFSET 26 ++#define MXC_CCM_CGR0_ESDHC1_MASK (0x3 << 26) ++#define MXC_CCM_CGR0_ESDHC2_OFFSET 28 ++#define MXC_CCM_CGR0_ESDHC2_MASK (0x3 << 28) ++#define MXC_CCM_CGR0_ESDHC3_OFFSET 30 ++#define MXC_CCM_CGR0_ESDHC3_MASK (0x3 << 30) ++ ++#define MXC_CCM_CGR1_FEC_OFFSET 0 ++#define MXC_CCM_CGR1_FEC_MASK (0x3 << 0) ++#define MXC_CCM_CGR1_GPIO1_OFFSET 2 ++#define MXC_CCM_CGR1_GPIO1_MASK (0x3 << 2) ++#define MXC_CCM_CGR1_GPIO2_OFFSET 4 ++#define MXC_CCM_CGR1_GPIO2_MASK (0x3 << 4) ++#define MXC_CCM_CGR1_GPIO3_OFFSET 6 ++#define MXC_CCM_CGR1_GPIO3_MASK (0x3 << 6) ++#define MXC_CCM_CGR1_GPT_OFFSET 8 ++#define MXC_CCM_CGR1_GPT_MASK (0x3 << 8) ++#define MXC_CCM_CGR1_I2C1_OFFSET 10 ++#define MXC_CCM_CGR1_I2C1_MASK (0x3 << 10) ++#define MXC_CCM_CGR1_I2C2_OFFSET 12 ++#define MXC_CCM_CGR1_I2C2_MASK (0x3 << 12) ++#define MXC_CCM_CGR1_I2C3_OFFSET 14 ++#define MXC_CCM_CGR1_I2C3_MASK (0x3 << 14) ++#define MXC_CCM_CGR1_IOMUXC_OFFSET 16 ++#define MXC_CCM_CGR1_IOMUXC_MASK (0x3 << 16) ++#define MXC_CCM_CGR1_IPU_OFFSET 18 ++#define MXC_CCM_CGR1_IPU_MASK (0x3 << 18) ++#define MXC_CCM_CGR1_KPP_OFFSET 20 ++#define MXC_CCM_CGR1_KPP_MASK (0x3 << 20) ++#define MXC_CCM_CGR1_MLB_OFFSET 22 ++#define MXC_CCM_CGR1_MLB_MASK (0x3 << 22) ++#define MXC_CCM_CGR1_MSHC_OFFSET 24 ++#define MXC_CCM_CGR1_MSHC_MASK (0x3 << 24) ++#define MXC_CCM_CGR1_OWIRE_OFFSET 26 ++#define MXC_CCM_CGR1_OWIRE_MASK (0x3 << 26) ++#define MXC_CCM_CGR1_PWM_OFFSET 28 ++#define MXC_CCM_CGR1_PWM_MASK (0x3 << 28) ++#define MXC_CCM_CGR1_RNGC_OFFSET 30 ++#define MXC_CCM_CGR1_RNGC_MASK (0x3 << 30) ++ ++#define MXC_CCM_CGR2_RTC_OFFSET 0 ++#define MXC_CCM_CGR2_RTC_MASK (0x3 << 0) ++#define MXC_CCM_CGR2_RTIC_OFFSET 2 ++#define MXC_CCM_CGR2_RTIC_MASK (0x3 << 2) ++#define MXC_CCM_CGR2_SCC_OFFSET 4 ++#define MXC_CCM_CGR2_SCC_MASK (0x3 << 4) ++#define MXC_CCM_CGR2_SDMA_OFFSET 6 ++#define MXC_CCM_CGR2_SDMA_MASK (0x3 << 6) ++#define MXC_CCM_CGR2_SPBA_OFFSET 8 ++#define MXC_CCM_CGR2_SPBA_MASK (0x3 << 8) ++#define MXC_CCM_CGR2_SPDIF_OFFSET 10 ++#define MXC_CCM_CGR2_SPDIF_MASK (0x3 << 10) ++#define MXC_CCM_CGR2_SSI1_OFFSET 12 ++#define MXC_CCM_CGR2_SSI1_MASK (0x3 << 12) ++#define MXC_CCM_CGR2_SSI2_OFFSET 14 ++#define MXC_CCM_CGR2_SSI2_MASK (0x3 << 14) ++#define MXC_CCM_CGR2_UART1_OFFSET 16 ++#define MXC_CCM_CGR2_UART1_MASK (0x3 << 16) ++#define MXC_CCM_CGR2_UART2_OFFSET 18 ++#define MXC_CCM_CGR2_UART2_MASK (0x3 << 18) ++#define MXC_CCM_CGR2_UART3_OFFSET 20 ++#define MXC_CCM_CGR2_UART3_MASK (0x3 << 20) ++#define MXC_CCM_CGR2_USBOTG_OFFSET 22 ++#define MXC_CCM_CGR2_USBOTG_MASK (0x3 << 22) ++#define MXC_CCM_CGR2_WDOG_OFFSET 24 ++#define MXC_CCM_CGR2_WDOG_MASK (0x3 << 24) ++#define MXC_CCM_CGR2_MAX_OFFSET 26 ++#define MXC_CCM_CGR2_MAX_MASK (0x3 << 26) ++#define MXC_CCM_CGR2_MAX_ENABLE (0x2 << 26) ++#define MXC_CCM_CGR2_AUDMUX_OFFSET 30 ++#define MXC_CCM_CGR2_AUDMUX_MASK (0x3 << 30) ++ ++#define MXC_CCM_CGR3_CSI_OFFSET 0 ++#define MXC_CCM_CGR3_CSI_MASK (0x3 << 0) ++#define MXC_CCM_CGR3_IIM_OFFSET 2 ++#define MXC_CCM_CGR3_IIM_MASK (0x3 << 2) ++#define MXC_CCM_CGR3_GPU2D_OFFSET 4 ++#define MXC_CCM_CGR3_GPU2D_MASK (0x3 << 4) ++ ++#define MXC_CCM_COSR_CLKOSEL_MASK 0x1F ++#define MXC_CCM_COSR_CLKOSEL_OFFSET 0 ++#define MXC_CCM_COSR_CLKOEN (1 << 5) ++#define MXC_CCM_COSR_CLKOUTDIV_1 (1 << 6) ++#define MXC_CCM_COSR_CLKOUT_PREDIV_MASK (0x7 << 10) ++#define MXC_CCM_COSR_CLKOUT_PREDIV_OFFSET 10 ++#define MXC_CCM_COSR_CLKOUT_PRODIV_MASK (0x7 << 13) ++#define MXC_CCM_COSR_CLKOUT_PRODIV_OFFSET 13 ++#define MXC_CCM_COSR_SSI1_RX_SRC_SEL_MASK (0x3 << 16) ++#define MXC_CCM_COSR_SSI1_RX_SRC_SEL_OFFSET 16 ++#define MXC_CCM_COSR_SSI1_TX_SRC_SEL_MASK (0x3 << 18) ++#define MXC_CCM_COSR_SSI1_TX_SRC_SEL_OFFSET 18 ++#define MXC_CCM_COSR_SSI2_RX_SRC_SEL_MASK (0x3 << 20) ++#define MXC_CCM_COSR_SSI2_RX_SRC_SEL_OFFSET 20 ++#define MXC_CCM_COSR_SSI2_TX_SRC_SEL_MASK (0x3 << 22) ++#define MXC_CCM_COSR_SSI2_TX_SRC_SEL_OFFSET 22 ++#define MXC_CCM_COSR_ASRC_AUDIO_EN (1 << 24) ++#define MXC_CCM_COSR_ASRC_AUDIO_PODF_MASK (0x3F << 26) ++#define MXC_CCM_COSR_ASRC_AUDIO_PODF_OFFSET 26 ++ ++#endif /* __CPU_ARM1136_MX35_CRM_REGS_H__ */ +diff --git a/cpu/arm1136/mx35/generic.c b/cpu/arm1136/mx35/generic.c +new file mode 100644 +index 0000000..d6ad6d7 +--- /dev/null ++++ b/cpu/arm1136/mx35/generic.c +@@ -0,0 +1,205 @@ ++/* ++ * (C) Copyright 2007 ++ * Sascha Hauer, Pengutronix ++ * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include "crm_regs.h" ++ ++#define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel)) ++#define CLK_CODE_ARM(c) (((c) >> 16) & 0xFF) ++#define CLK_CODE_AHB(c) (((c) >> 8) & 0xFF) ++#define CLK_CODE_PATH(c) ((c) & 0xFF) ++ ++#define CCM_GET_DIVIDER(x, m, o) (((x) & (m)) >> (o)) ++ ++static int g_clk_mux_auto[8] = { ++ CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1, ++ CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1, ++}; ++ ++static int g_clk_mux_consumer[16] = { ++ CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(1, 3, 1), -1, ++ -1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0), ++ CLK_CODE(1, 8, 1), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1, ++ -1, -1, CLK_CODE(4, 2, 0), -1, ++}; ++ ++static u32 __get_arm_div(u32 pdr0, u32 *fi, u32 *fd) ++{ ++ int *pclk_mux; ++ if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { ++ pclk_mux = g_clk_mux_consumer + ++ ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> ++ MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); ++ } else { ++ pclk_mux = g_clk_mux_auto + ++ ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >> ++ MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET); ++ } ++ ++ if ((*pclk_mux) == -1) ++ return -1; ++ ++ if (fi && fd) { ++ if (!CLK_CODE_PATH(*pclk_mux)) { ++ *fi = *fd = 1; ++ return CLK_CODE_ARM(*pclk_mux); ++ } ++ if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { ++ *fi = 3; ++ *fd = 4; ++ } else { ++ *fi = 2; ++ *fd = 3; ++ } ++ } ++ return CLK_CODE_ARM(*pclk_mux); ++} ++ ++static int __get_ahb_div(u32 pdr0) ++{ ++ int *pclk_mux; ++ if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { ++ pclk_mux = g_clk_mux_consumer + ++ ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> ++ MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); ++ } else { ++ pclk_mux = g_clk_mux_auto + ++ ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >> ++ MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET); ++ } ++ ++ if ((*pclk_mux) == -1) ++ return -1; ++ ++ return CLK_CODE_AHB(*pclk_mux); ++} ++ ++static u32 __decode_pll(u32 reg, u32 infreq) ++{ ++ u32 mfi = (reg >> 10) & 0xf; ++ u32 mfn = reg & 0x3f; ++ u32 mfd = (reg >> 16) & 0x3f; ++ u32 pd = (reg >> 26) & 0xf; ++ ++ mfi = mfi <= 5 ? 5 : mfi; ++ mfd += 1; ++ pd += 1; ++ ++ return ((2 * (infreq / 1000) * (mfi * mfd + mfn)) / (mfd * pd)) * 1000; ++} ++ ++static u32 __get_mcu_main_clk(void) ++{ ++ u32 arm_div, fi, fd; ++ arm_div = __get_arm_div(__REG(CCM_BASE_ADDR + CLKCTL_PDR0), &fi, &fd); ++ fi *= ++ __decode_pll(__REG(CCM_BASE_ADDR + CLKCTL_MPCTL), ++ CONFIG_MX35_HCLK_FREQ); ++ return fi / (arm_div * fd); ++} ++ ++static u32 __get_ipg_clk(void) ++{ ++ u32 freq = __get_mcu_main_clk(); ++ u32 pdr0 = __REG(CCM_BASE_ADDR + CLKCTL_PDR0); ++ ++ return freq / (__get_ahb_div(pdr0) * 2); ++} ++ ++static u32 __get_ipg_per_clk(void) ++{ ++ u32 freq = __get_mcu_main_clk(); ++ u32 pdr0 = __REG(CCM_BASE_ADDR + CLKCTL_PDR0); ++ u32 pdr4 = __REG(CCM_BASE_ADDR + CLKCTL_PDR4); ++ u32 div; ++ if (pdr0 & MXC_CCM_PDR0_PER_SEL) { ++ div = (CCM_GET_DIVIDER(pdr4, ++ MXC_CCM_PDR4_PER0_PRDF_MASK, ++ MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1) * ++ (CCM_GET_DIVIDER(pdr4, ++ MXC_CCM_PDR4_PER0_PODF_MASK, ++ MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1); ++ } else { ++ div = CCM_GET_DIVIDER(pdr0, ++ MXC_CCM_PDR0_PER_PODF_MASK, ++ MXC_CCM_PDR0_PER_PODF_OFFSET) + 1; ++ freq /= __get_ahb_div(pdr0); ++ } ++ return freq / div; ++} ++ ++static u32 __get_uart_clk(void) ++{ ++ u32 freq; ++ u32 pdr4 = __REG(CCM_BASE_ADDR + CLKCTL_PDR4); ++ ++ if (__REG(CCM_BASE_ADDR + CLKCTL_PDR3) & MXC_CCM_PDR3_UART_M_U) ++ freq = __get_mcu_main_clk(); ++ else ++ freq = __decode_pll(__REG(CCM_BASE_ADDR + CLKCTL_PPCTL), ++ CONFIG_MX35_HCLK_FREQ); ++ freq /= ((CCM_GET_DIVIDER(pdr4, ++ MXC_CCM_PDR4_UART_PRDF_MASK, ++ MXC_CCM_PDR4_UART_PRDF_OFFSET) + 1) * ++ (CCM_GET_DIVIDER(pdr4, ++ MXC_CCM_PDR4_UART_PODF_MASK, ++ MXC_CCM_PDR4_UART_PODF_OFFSET) + 1)); ++ return freq; ++} ++ ++unsigned int mxc_get_clock(enum mxc_clock clk) ++{ ++ switch (clk) { ++ case MXC_ARM_CLK: ++ return __get_mcu_main_clk(); ++ case MXC_AHB_CLK: ++ break; ++ case MXC_IPG_CLK: ++ return __get_ipg_clk(); ++ case MXC_IPG_PERCLK: ++ return __get_ipg_per_clk(); ++ case MXC_UART_CLK: ++ return __get_uart_clk(); ++ } ++ return -1; ++} ++ ++void mxc_dump_clocks(void) ++{ ++ u32 cpufreq = __get_mcu_main_clk(); ++ printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000); ++ printf("ipg clock : %dHz\n", __get_ipg_clk()); ++ printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); ++} ++ ++#if defined(CONFIG_DISPLAY_CPUINFO) ++int print_cpuinfo(void) ++{ ++ printf("CPU: Freescale i.MX35 at %d MHz\n", ++ __get_mcu_main_clk() / 1000000); ++ return 0; ++} ++#endif +diff --git a/cpu/arm1136/mx35/interrupts.c b/cpu/arm1136/mx35/interrupts.c +new file mode 100644 +index 0000000..28284b1 +--- /dev/null ++++ b/cpu/arm1136/mx35/interrupts.c +@@ -0,0 +1,110 @@ ++/* ++ * (C) Copyright 2007 ++ * Sascha Hauer, Pengutronix ++ * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++ ++/* General purpose timers registers */ ++#define GPTCR __REG(GPT1_BASE_ADDR) /* Control register */ ++#define GPTPR __REG(GPT1_BASE_ADDR + 0x4) /* Prescaler register */ ++#define GPTSR __REG(GPT1_BASE_ADDR + 0x8) /* Status register */ ++#define GPTCNT __REG(GPT1_BASE_ADDR + 0x24) /* Counter register */ ++ ++/* General purpose timers bitfields */ ++#define GPTCR_SWR (1<<15) /* Software reset */ ++#define GPTCR_FRR (1<<9) /* Freerun / restart */ ++#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ ++#define GPTCR_TEN (1) /* Timer enable */ ++ ++/* nothing really to do with interrupts, just starts up a counter. */ ++int interrupt_init(void) ++{ ++ int i; ++ ++ /* setup GP Timer 1 */ ++ GPTCR = GPTCR_SWR; ++ for (i = 0; i < 100; i++) ++ GPTCR = 0; /* We have no udelay by now */ ++ GPTPR = 0; /* 32Khz */ ++ /* Freerun Mode, PERCLK1 input */ ++ GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; ++ ++ return 0; ++} ++ ++void reset_timer_masked(void) ++{ ++ GPTCR = 0; ++ /* Freerun Mode, PERCLK1 input */ ++ GPTCR = GPTCR_CLKSOURCE_32 | GPTCR_TEN; ++} ++ ++ulong get_timer_masked(void) ++{ ++ ulong val = GPTCNT; ++ return val; ++} ++ ++ulong get_timer(ulong base) ++{ ++ return get_timer_masked() - base; ++} ++ ++void set_timer(ulong t) ++{ ++} ++ ++/* delay x useconds AND perserve advance timstamp value */ ++void udelay(unsigned long usec) ++{ ++ ulong tmo, tmp; ++ ++ /* if "big" number, spread normalization to seconds */ ++ if (usec >= 1000) { ++ /* start to normalize for usec to ticks per sec */ ++ tmo = usec / 1000; ++ /* find number of "ticks" to wait to achieve target */ ++ tmo *= CONFIG_SYS_HZ; ++ tmo /= 1000; /* finish normalize. */ ++ } else {/* else small number, don't kill it prior to HZ multiply */ ++ tmo = usec * CONFIG_SYS_HZ; ++ tmo /= (1000 * 1000); ++ } ++ ++ tmp = get_timer(0); /* get current timestamp */ ++ /* if setting this forward will roll time stamp */ ++ if ((tmo + tmp + 1) < tmp) ++ /* reset "advancing" timestamp to 0, set lastinc value */ ++ reset_timer_masked(); ++ else /* else, set advancing stamp wake up time */ ++ tmo += tmp; ++ while (get_timer_masked() < tmo) /* loop till event */ ++ /*NOP*/; ++} ++ ++void reset_cpu(ulong addr) ++{ ++ __REG16(WDOG_BASE_ADDR) = 4; ++} +diff --git a/cpu/arm1136/mx35/iomux.c b/cpu/arm1136/mx35/iomux.c +new file mode 100644 +index 0000000..e66332c +--- /dev/null ++++ b/cpu/arm1136/mx35/iomux.c +@@ -0,0 +1,149 @@ ++/* ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @defgroup GPIO_MX35 Board GPIO and Muxing Setup ++ * @ingroup MSL_MX35 ++ */ ++/*! ++ * @file mach-mx35/iomux.c ++ * ++ * @brief I/O Muxing control functions ++ * ++ * @ingroup GPIO_MX35 ++ */ ++#include ++#include ++#include ++#include ++ ++/*! ++ * IOMUX register (base) addresses ++ */ ++enum iomux_reg_addr { ++ IOMUXGPR = IOMUXC_BASE_ADDR, ++ /*!< General purpose */ ++ IOMUXSW_MUX_CTL = IOMUXC_BASE_ADDR + 4, ++ /*!< MUX control */ ++ IOMUXSW_MUX_END = IOMUXC_BASE_ADDR + 0x324, ++ /*!< last MUX control register */ ++ IOMUXSW_PAD_CTL = IOMUXC_BASE_ADDR + 0x328, ++ /*!< Pad control */ ++ IOMUXSW_PAD_END = IOMUXC_BASE_ADDR + 0x794, ++ /*!< last Pad control register */ ++ IOMUXSW_INPUT_CTL = IOMUXC_BASE_ADDR + 0x7AC, ++ /*!< input select register */ ++ IOMUXSW_INPUT_END = IOMUXC_BASE_ADDR + 0x9F4, ++ /*!< last input select register */ ++}; ++ ++#define MUX_PIN_NUM_MAX \ ++ (((IOMUXSW_PAD_END - IOMUXSW_PAD_CTL) >> 2) + 1) ++#define MUX_INPUT_NUM_MUX \ ++ (((IOMUXSW_INPUT_END - IOMUXSW_INPUT_CTL) >> 2) + 1) ++ ++#define PIN_TO_IOMUX_INDEX(pin) ((PIN_TO_IOMUX_PAD(pin) - 0x328) >> 2) ++ ++/*! ++ * This function is used to configure a pin through the IOMUX module. ++ * FIXED ME: for backward compatible. Will be static function! ++ * @param pin a pin number as defined in \b #iomux_pin_name_t ++ * @param cfg an output function as defined in \b #iomux_pin_cfg_t ++ * ++ * @return 0 if successful; Non-zero otherwise ++ */ ++static int iomux_config_mux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) ++{ ++ u32 mux_reg = PIN_TO_IOMUX_MUX(pin); ++ ++ if (mux_reg != NON_MUX_I) { ++ mux_reg += IOMUXGPR; ++ __REG(mux_reg) = cfg; ++ } ++ ++ return 0; ++} ++ ++/*! ++ * Request ownership for an IO pin. This function has to be the first one ++ * being called before that pin is used. The caller has to check the ++ * return value to make sure it returns 0. ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param cfg an input function as defined in \b #iomux_pin_cfg_t ++ * ++ * @return 0 if successful; Non-zero otherwise ++ */ ++int mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) ++{ ++ int ret = iomux_config_mux(pin, cfg); ++ return ret; ++} ++ ++/*! ++ * Release ownership for an IO pin ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param cfg an input function as defined in \b #iomux_pin_cfg_t ++ */ ++void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) ++{ ++} ++ ++/*! ++ * This function configures the pad value for a IOMUX pin. ++ * ++ * @param pin a pin number as defined in \b #iomux_pin_name_t ++ * @param config the ORed value of elements defined in \b #iomux_pad_config_t ++ */ ++void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config) ++{ ++ u32 pad_reg = IOMUXGPR + PIN_TO_IOMUX_PAD(pin); ++ ++ __REG(pad_reg) = config; ++} ++ ++/*! ++ * This function enables/disables the general purpose function for a particular ++ * signal. ++ * ++ * @param gp one signal as defined in \b #iomux_gp_func_t ++ * @param en \b #true to enable; \b #false to disable ++ */ ++void mxc_iomux_set_gpr(iomux_gp_func_t gp, int en) ++{ ++ u32 l; ++ ++ l = __REG(IOMUXGPR); ++ if (en) ++ l |= gp; ++ else ++ l &= ~gp; ++ ++ __REG(IOMUXGPR) = l; ++} ++ ++/*! ++ * This function configures input path. ++ * ++ * @param input index of input select register as defined in \b ++ * #iomux_input_select_t ++ * @param config the binary value of elements defined in \b ++ * #iomux_input_config_t ++ */ ++void mxc_iomux_set_input(iomux_input_select_t input, u32 config) ++{ ++ u32 reg = IOMUXSW_INPUT_CTL + (input << 2); ++ ++ __REG(reg) = config; ++} +diff --git a/cpu/arm1136/mx35/serial.c b/cpu/arm1136/mx35/serial.c +new file mode 100644 +index 0000000..f4f674a +--- /dev/null ++++ b/cpu/arm1136/mx35/serial.c +@@ -0,0 +1,220 @@ ++/* ++ * (c) 2007 Sascha Hauer ++ * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++ ++#if defined CONFIG_MX35_UART ++ ++#include ++ ++#define __REG(x) (*((volatile u32 *)(x))) ++ ++#define UART_PHYS CONFIG_MX35_UART ++ ++/* Register definitions */ ++#define URXD 0x0 /* Receiver Register */ ++#define UTXD 0x40 /* Transmitter Register */ ++#define UCR1 0x80 /* Control Register 1 */ ++#define UCR2 0x84 /* Control Register 2 */ ++#define UCR3 0x88 /* Control Register 3 */ ++#define UCR4 0x8c /* Control Register 4 */ ++#define UFCR 0x90 /* FIFO Control Register */ ++#define USR1 0x94 /* Status Register 1 */ ++#define USR2 0x98 /* Status Register 2 */ ++#define UESC 0x9c /* Escape Character Register */ ++#define UTIM 0xa0 /* Escape Timer Register */ ++#define UBIR 0xa4 /* BRM Incremental Register */ ++#define UBMR 0xa8 /* BRM Modulator Register */ ++#define UBRC 0xac /* Baud Rate Count Register */ ++#define UTS 0xb4 /* UART Test Register (mx31) */ ++ ++/* UART Control Register Bit Fields.*/ ++#define URXD_CHARRDY (1<<15) ++#define URXD_ERR (1<<14) ++#define URXD_OVRRUN (1<<13) ++#define URXD_FRMERR (1<<12) ++#define URXD_BRK (1<<11) ++#define URXD_PRERR (1<<10) ++#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ ++#define UCR1_ADBR (1<<14) /* Auto detect baud rate */ ++#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ ++#define UCR1_IDEN (1<<12) /* Idle condition interrupt */ ++#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ ++#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ ++#define UCR1_IREN (1<<7) /* Infrared interface enable */ ++#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ ++#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ ++#define UCR1_SNDBRK (1<<4) /* Send break */ ++#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ ++#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ ++#define UCR1_DOZE (1<<1) /* Doze */ ++#define UCR1_UARTEN (1<<0) /* UART enabled */ ++#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ ++#define UCR2_IRTS (1<<14) /* Ignore RTS pin */ ++#define UCR2_CTSC (1<<13) /* CTS pin control */ ++#define UCR2_CTS (1<<12) /* Clear to send */ ++#define UCR2_ESCEN (1<<11) /* Escape enable */ ++#define UCR2_PREN (1<<8) /* Parity enable */ ++#define UCR2_PROE (1<<7) /* Parity odd/even */ ++#define UCR2_STPB (1<<6) /* Stop */ ++#define UCR2_WS (1<<5) /* Word size */ ++#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ ++#define UCR2_TXEN (1<<2) /* Transmitter enabled */ ++#define UCR2_RXEN (1<<1) /* Receiver enabled */ ++#define UCR2_SRST (1<<0) /* SW reset */ ++#define UCR3_DTREN (1<<13) /* DTR interrupt enable */ ++#define UCR3_PARERREN (1<<12) /* Parity enable */ ++#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */ ++#define UCR3_DSR (1<<10) /* Data set ready */ ++#define UCR3_DCD (1<<9) /* Data carrier detect */ ++#define UCR3_RI (1<<8) /* Ring indicator */ ++#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */ ++#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ ++#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ ++#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ ++#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */ ++#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */ ++#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ ++#define UCR3_BPEN (1<<0) /* Preset registers enable */ ++#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ ++#define UCR4_INVR (1<<9) /* Inverted infrared reception */ ++#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ ++#define UCR4_WKEN (1<<7) /* Wake interrupt enable */ ++#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */ ++#define UCR4_IRSC (1<<5) /* IR special case */ ++#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */ ++#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */ ++#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ ++#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ ++#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ ++#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ ++#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ ++#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ ++#define USR1_RTSS (1<<14) /* RTS pin status */ ++#define USR1_TRDY (1<<13)/* Transmitter ready interrupt/dma flag */ ++#define USR1_RTSD (1<<12) /* RTS delta */ ++#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */ ++#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */ ++#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */ ++#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */ ++#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */ ++#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */ ++#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */ ++#define USR2_ADET (1<<15) /* Auto baud rate detect complete */ ++#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */ ++#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */ ++#define USR2_IDLE (1<<12) /* Idle condition */ ++#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */ ++#define USR2_WAKE (1<<7) /* Wake */ ++#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */ ++#define USR2_TXDC (1<<3) /* Transmitter complete */ ++#define USR2_BRCD (1<<2) /* Break condition */ ++#define USR2_ORE (1<<1) /* Overrun error */ ++#define USR2_RDR (1<<0) /* Recv data ready */ ++#define UTS_FRCPERR (1<<13) /* Force parity error */ ++#define UTS_LOOP (1<<12) /* Loop tx and rx */ ++#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ ++#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ ++#define UTS_TXFULL (1<<4) /* TxFIFO full */ ++#define UTS_RXFULL (1<<3) /* RxFIFO full */ ++#define UTS_SOFTRST (1<<0) /* Software reset */ ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++void serial_setbrg(void) ++{ ++ u32 clk = mxc_get_clock(MXC_UART_CLK); ++ ++ if (!gd->baudrate) ++ gd->baudrate = CONFIG_BAUDRATE; ++ __REG(UART_PHYS + UFCR) = 0x4 << 7; /* divide input clock by 2 */ ++ __REG(UART_PHYS + UBIR) = 0xf; ++ __REG(UART_PHYS + UBMR) = clk / (2 * gd->baudrate); ++} ++ ++int serial_getc(void) ++{ ++ while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) ++ ; ++ return __REG(UART_PHYS + URXD); ++} ++ ++void serial_putc(const char c) ++{ ++ __REG(UART_PHYS + UTXD) = c; ++ ++ /* wait for transmitter to be ready */ ++ while (!(__REG(UART_PHYS + UTS) & UTS_TXEMPTY)) ++ ; ++ ++ /* If \n, also do \r */ ++ if (c == '\n') ++ serial_putc('\r'); ++} ++ ++/* ++ * Test whether a character is in the RX buffer ++ */ ++int serial_tstc(void) ++{ ++ /* If receive fifo is empty, return false */ ++ if (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) ++ return 0; ++ return 1; ++} ++ ++void serial_puts(const char *s) ++{ ++ while (*s) ++ serial_putc(*s++); ++} ++ ++/* ++ * Initialise the serial port with the given baudrate. The settings ++ * are always 8 data bits, no parity, 1 stop bit, no start bits. ++ * ++ */ ++int serial_init(void) ++{ ++ __REG(UART_PHYS + UCR1) = 0x0; ++ __REG(UART_PHYS + UCR2) = 0x0; ++ ++ while (!(__REG(UART_PHYS + UCR2) & UCR2_SRST)) ++ ; ++ ++ __REG(UART_PHYS + UCR3) = 0x0704; ++ __REG(UART_PHYS + UCR4) = 0x8000; ++ __REG(UART_PHYS + UESC) = 0x002b; ++ __REG(UART_PHYS + UTIM) = 0x0; ++ ++ __REG(UART_PHYS + UTS) = 0x0; ++ ++ serial_setbrg(); ++ ++ __REG(UART_PHYS + UCR2) = ++ UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST; ++ ++ __REG(UART_PHYS + UCR1) = UCR1_UARTEN; ++ ++ return 0; ++} ++ ++#endif /* CONFIG_MX35 */ +diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c +index eedad06..860f0be 100644 +--- a/drivers/i2c/mxc_i2c.c ++++ b/drivers/i2c/mxc_i2c.c +@@ -3,6 +3,8 @@ + * + * (c) 2007 Pengutronix, Sascha Hauer + * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * + * See file CREDITS for list of people who contributed to this + * project. + * +@@ -26,8 +28,14 @@ + + #if defined(CONFIG_HARD_I2C) + ++#ifdef CONFIG_MX31 + #include + #include ++#elif defined(CONFIG_MX35) ++#include ++#else ++#error "Please include specific headfile " ++#endif + + #define IADR 0x00 + #define IFDR 0x04 +@@ -47,16 +55,17 @@ + #define I2SR_IIF (1 << 1) + #define I2SR_RX_NO_AK (1 << 0) + +-#ifdef CONFIG_SYS_I2C_MX31_PORT1 +-#define I2C_BASE 0x43f80000 +-#elif defined (CONFIG_SYS_I2C_MX31_PORT2) +-#define I2C_BASE 0x43f98000 +-#elif defined (CONFIG_SYS_I2C_MX31_PORT3) +-#define I2C_BASE 0x43f84000 ++#ifdef CONFIG_SYS_I2C_PORT ++# define I2C_BASE CONFIG_SYS_I2C_PORT + #else +-#error "define CONFIG_SYS_I2C_MX31_PORTx to use the mx31 I2C driver" ++# error "define CFG_I2C_PORT(I2C base address) to use the I2C driver" + #endif + ++#define I2C_MAX_TIMEOUT 100000 ++#define I2C_TIMEOUT_TICKET 1 ++ ++#undef DEBUG ++ + #ifdef DEBUG + #define DPRINTF(args...) printf(args) + #else +@@ -64,33 +73,77 @@ + #endif + + static u16 div[] = { 30, 32, 36, 42, 48, 52, 60, 72, 80, 88, 104, 128, 144, +- 160, 192, 240, 288, 320, 384, 480, 576, 640, 768, 960, +- 1152, 1280, 1536, 1920, 2304, 2560, 3072, 3840}; ++ 160, 192, 240, 288, 320, 384, 480, 576, 640, 768, 960, ++ 1152, 1280, 1536, 1920, 2304, 2560, 3072, 3840 ++}; ++ ++static inline void i2c_reset(void) ++{ ++ __REG16(I2C_BASE + I2CR) = 0; /* Reset module */ ++ __REG16(I2C_BASE + I2SR) = 0; ++ __REG16(I2C_BASE + I2CR) = I2CR_IEN; ++} + + void i2c_init(int speed, int unused) + { +- int freq = mx31_get_ipg_clk(); ++ int freq; + int i; + ++#ifdef CONFIG_MX31 ++ freq = mx31_get_ipg_clk(); ++#else ++ freq = mxc_get_clock(MXC_IPG_PERCLK); ++#endif + for (i = 0; i < 0x1f; i++) + if (freq / div[i] <= speed) + break; + +- DPRINTF("%s: speed: %d\n",__FUNCTION__, speed); ++ DPRINTF("%s: root clock: %d, speed: %d div: %x\n", ++ __func__, freq, speed, i); + +- __REG16(I2C_BASE + I2CR) = 0; /* Reset module */ + __REG16(I2C_BASE + IFDR) = i; +- __REG16(I2C_BASE + I2CR) = I2CR_IEN; +- __REG16(I2C_BASE + I2SR) = 0; ++ i2c_reset(); ++} ++ ++static int wait_idle(void) ++{ ++ int timeout = I2C_MAX_TIMEOUT; ++ ++ while ((__REG16(I2C_BASE + I2SR) & I2SR_IBB) && --timeout) { ++ __REG16(I2C_BASE + I2SR) = 0; ++ udelay(I2C_TIMEOUT_TICKET); ++ } ++ DPRINTF("%s:%x\n", __func__, __REG16(I2C_BASE + I2SR)); ++ return timeout ? timeout : (!(__REG16(I2C_BASE + I2SR) & I2SR_IBB)); + } + + static int wait_busy(void) + { +- int timeout = 10000; ++ int timeout = I2C_MAX_TIMEOUT; + +- while (!(__REG16(I2C_BASE + I2SR) & I2SR_IIF) && --timeout) +- udelay(1); +- __REG16(I2C_BASE + I2SR) = 0; /* clear interrupt */ ++ while ((!(__REG16(I2C_BASE + I2SR) & I2SR_IBB) && (--timeout))) { ++ __REG16(I2C_BASE + I2SR) = 0; ++ udelay(I2C_TIMEOUT_TICKET); ++ } ++ return timeout ? timeout : (__REG16(I2C_BASE + I2SR) & I2SR_IBB); ++} ++ ++static int wait_complete(void) ++{ ++ int timeout = I2C_MAX_TIMEOUT; ++ ++ while ((!(__REG16(I2C_BASE + I2SR) & I2SR_ICF)) && (--timeout)) { ++ __REG16(I2C_BASE + I2SR) = 0; ++ udelay(I2C_TIMEOUT_TICKET); ++ } ++ DPRINTF("%s:%x\n", __func__, __REG16(I2C_BASE + I2SR)); ++ { ++ int i; ++ for (i = 0; i < 200; i++) ++ udelay(10); ++ ++ } ++ __REG16(I2C_BASE + I2SR) = 0; /* clear interrupt */ + + return timeout; + } +@@ -99,90 +152,133 @@ static int tx_byte(u8 byte) + { + __REG16(I2C_BASE + I2DR) = byte; + +- if (!wait_busy() || __REG16(I2C_BASE + I2SR) & I2SR_RX_NO_AK) ++ if (!wait_complete() || __REG16(I2C_BASE + I2SR) & I2SR_RX_NO_AK) { ++ DPRINTF("%s:%x <= %x\n", __func__, __REG16(I2C_BASE + I2SR), ++ byte); + return -1; ++ } ++ DPRINTF("%s:%x\n", __func__, byte); + return 0; + } + +-static int rx_byte(void) ++static int rx_byte(u32 *pdata, int last) + { +- if (!wait_busy()) ++ if (!wait_complete()) + return -1; + +- return __REG16(I2C_BASE + I2DR); ++ if (last) ++ __REG16(I2C_BASE + I2CR) = I2CR_IEN; ++ ++ *pdata = __REG16(I2C_BASE + I2DR); ++ DPRINTF("%s:%x\n", __func__, *pdata); ++ return 0; + } + + int i2c_probe(uchar chip) + { + int ret; + +- __REG16(I2C_BASE + I2CR) = 0; /* Reset module */ ++ __REG16(I2C_BASE + I2CR) = 0; /* Reset module */ + __REG16(I2C_BASE + I2CR) = I2CR_IEN; +- +- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_MTX; ++ for (ret = 0; ret < 1000; ret++) ++ udelay(1); ++ __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_MTX; + ret = tx_byte(chip << 1); +- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MTX; ++ __REG16(I2C_BASE + I2CR) = I2CR_IEN; + + return ret; + } + + static int i2c_addr(uchar chip, uint addr, int alen) + { +- __REG16(I2C_BASE + I2SR) = 0; /* clear interrupt */ +- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_MTX; +- +- if (tx_byte(chip << 1)) ++ int i, retry = 0; ++ for (retry = 0; retry < 3; retry++) { ++ if (wait_idle()) ++ break; ++ i2c_reset(); ++ for (i = 0; i < I2C_MAX_TIMEOUT; i++) ++ udelay(I2C_TIMEOUT_TICKET); ++ } ++ if (retry >= 3) { ++ printf("%s:bus is busy(%x)\n", ++ __func__, __REG16(I2C_BASE + I2SR)); + return -1; +- ++ } ++ __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_MTX; ++ if (!wait_busy()) { ++ printf("%s:trigger start fail(%x)\n", ++ __func__, __REG16(I2C_BASE + I2SR)); ++ return -1; ++ } ++ if (tx_byte(chip << 1) || (__REG16(I2C_BASE + I2SR) & I2SR_RX_NO_AK)) { ++ printf("%s:chip address cycle fail(%x)\n", ++ __func__, __REG16(I2C_BASE + I2SR)); ++ return -1; ++ } + while (alen--) +- if (tx_byte((addr >> (alen * 8)) & 0xff)) ++ if (tx_byte((addr >> (alen * 8)) & 0xff) || ++ (__REG16(I2C_BASE + I2SR) & I2SR_RX_NO_AK)) { ++ printf("%s:device address cycle fail(%x)\n", ++ __func__, __REG16(I2C_BASE + I2SR)); + return -1; ++ } + return 0; + } + + int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len) + { +- int timeout = 10000; ++ int timeout = I2C_MAX_TIMEOUT; + int ret; + +- DPRINTF("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n",__FUNCTION__, chip, addr, alen, len); ++ DPRINTF("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n", ++ __func__, chip, addr, alen, len); + + if (i2c_addr(chip, addr, alen)) { + printf("i2c_addr failed\n"); + return -1; + } + +- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_MTX | I2CR_RSTA; ++ __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_MTX | I2CR_RSTA; + +- if (tx_byte(chip << 1 | 1)) ++ if (tx_byte(chip << 1 | 1) || ++ (__REG16(I2C_BASE + I2SR) & I2SR_RX_NO_AK)) { ++ printf("%s:Send 2th chip address fail(%x)\n", ++ __func__, __REG16(I2C_BASE + I2SR)); + return -1; +- +- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | ((len == 1) ? I2CR_TX_NO_AK : 0); +- ++ } ++ __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | ++ ((len == 1) ? I2CR_TX_NO_AK : 0); ++ DPRINTF("CR=%x\n", __REG16(I2C_BASE + I2CR)); + ret = __REG16(I2C_BASE + I2DR); + + while (len--) { +- if ((ret = rx_byte()) < 0) ++ if (len == 1) ++ __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | ++ I2CR_TX_NO_AK; ++ ++ if (rx_byte(&ret, len == 0) < 0) { ++ printf("Read: rx_byte fail\n"); + return -1; ++ } + *buf++ = ret; +- if (len <= 1) +- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_TX_NO_AK; + } + +- wait_busy(); +- +- __REG16(I2C_BASE + I2CR) = I2CR_IEN; +- +- while (__REG16(I2C_BASE + I2SR) & I2SR_IBB && --timeout) +- udelay(1); +- ++ while (__REG16(I2C_BASE + I2SR) & I2SR_IBB && --timeout) { ++ __REG16(I2C_BASE + I2SR) = 0; ++ udelay(I2C_TIMEOUT_TICKET); ++ } ++ if (!timeout) { ++ printf("%s:trigger stop fail(%x)\n", ++ __func__, __REG16(I2C_BASE + I2SR)); ++ } + return 0; + } + + int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len) + { +- int timeout = 10000; +- DPRINTF("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n",__FUNCTION__, chip, addr, alen, len); ++ int timeout = I2C_MAX_TIMEOUT; ++ DPRINTF("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n", ++ __func__, chip, addr, alen, len); + + if (i2c_addr(chip, addr, alen)) + return -1; +@@ -194,9 +290,9 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len) + __REG16(I2C_BASE + I2CR) = I2CR_IEN; + + while (__REG16(I2C_BASE + I2SR) & I2SR_IBB && --timeout) +- udelay(1); ++ udelay(I2C_TIMEOUT_TICKET); + + return 0; + } + +-#endif /* CONFIG_HARD_I2C */ ++#endif /* CONFIG_HARD_I2C */ +diff --git a/drivers/net/Makefile b/drivers/net/Makefile +index 631336a..7261bfd 100644 +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -44,6 +44,7 @@ COBJS-$(CONFIG_MACB) += macb.o + COBJS-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o + COBJS-$(CONFIG_MPC5xxx_FEC) += mpc5xxx_fec.o + COBJS-$(CONFIG_MPC512x_FEC) += mpc512x_fec.o ++COBJS-$(CONFIG_MXC_FEC) += mxc_fec.o + COBJS-$(CONFIG_NATSEMI) += natsemi.o + COBJS-$(CONFIG_DRIVER_NE2000) += ne2000.o ne2000_base.o + COBJS-$(CONFIG_DRIVER_AX88796L) += ax88796.o ne2000_base.o +diff --git a/drivers/net/mxc_fec.c b/drivers/net/mxc_fec.c +new file mode 100644 +index 0000000..676f89f +--- /dev/null ++++ b/drivers/net/mxc_fec.c +@@ -0,0 +1,733 @@ ++/* ++ * (C) Copyright 2000-2004 ++ * Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++ * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#undef ET_DEBUG ++#undef MII_DEBUG ++ ++/* Ethernet Transmit and Receive Buffers */ ++#define DBUF_LENGTH 1520 ++#define TX_BUF_CNT 2 ++#define PKT_MAXBUF_SIZE 1518 ++#define PKT_MINBUF_SIZE 64 ++#define PKT_MAXBLR_SIZE 1520 ++#define LAST_PKTBUFSRX (PKTBUFSRX - 1) ++#define BD_ENET_RX_W_E (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY) ++#define BD_ENET_TX_RDY_LST (BD_ENET_TX_READY | BD_ENET_TX_LAST) ++ ++/* the defins of MII operation */ ++#define FEC_MII_ST 0x40000000 ++#define FEC_MII_OP_OFF 28 ++#define FEC_MII_OP_MASK 0x03 ++#define FEC_MII_OP_RD 0x02 ++#define FEC_MII_OP_WR 0x01 ++#define FEC_MII_PA_OFF 23 ++#define FEC_MII_PA_MASK 0xFF ++#define FEC_MII_RA_OFF 18 ++#define FEC_MII_RA_MASK 0xFF ++#define FEC_MII_TA 0x00020000 ++#define FEC_MII_DATA_OFF 0 ++#define FEC_MII_DATA_MASK 0x0000FFFF ++ ++#define FEC_MII_FRAME (FEC_MII_ST | FEC_MII_TA) ++#define FEC_MII_OP(x) (((x) & FEC_MII_OP_MASK) << FEC_MII_OP_OFF) ++#define FEC_MII_PA(pa) (((pa) & FEC_MII_PA_MASK) << FEC_MII_PA_OFF) ++#define FEC_MII_RA(ra) (((ra) & FEC_MII_RA_MASK) << FEC_MII_RA_OFF) ++#define FEC_MII_SET_DATA(v) (((v) & FEC_MII_DATA_MASK) << FEC_MII_DATA_OFF) ++#define FEC_MII_GET_DATA(v) (((v) >> FEC_MII_DATA_OFF) & FEC_MII_DATA_MASK) ++#define FEC_MII_READ(pa, ra) ((FEC_MII_FRAME | FEC_MII_OP(FEC_MII_OP_RD)) |\ ++ FEC_MII_PA(pa) | FEC_MII_RA(ra)) ++#define FEC_MII_WRITE(pa, ra, v) (FEC_MII_FRAME | FEC_MII_OP(FEC_MII_OP_WR)|\ ++ FEC_MII_PA(pa) | FEC_MII_RA(ra) | FEC_MII_SET_DATA(v)) ++ ++#ifndef CONFIG_SYS_CACHELINE_SIZE ++#define CONFIG_SYS_CACHELINE_SIZE 32 ++#endif ++ ++#ifndef CONFIG_FEC_TIMEOUT ++#define FEC_MII_TIMEOUT 50000 ++#else ++#define FEC_MII_TIMEOUT CONFIG_FEC_TIMEOUT ++#endif ++ ++#ifndef CONFIG_FEC_TICKET ++#define FEC_MII_TICK 2 ++#else ++#define FEC_MII_TICK CONFIG_FEC_TICKET ++#endif ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) ++ ++struct fec_info_s fec_info[] = { ++ { ++ 0, /* index */ ++ CONFIG_FEC0_IOBASE, /* io base */ ++ CONFIG_FEC0_PHY_ADDR, /* phy_addr */ ++ 0, /* duplex and speed */ ++ 0, /* phy name */ ++ 0, /* phyname init */ ++ 0, /* RX BD */ ++ 0, /* TX BD */ ++ 0, /* rx Index */ ++ 0, /* tx Index */ ++ 0, /* tx buffer */ ++ 0, /* initialized flag */ ++ }, ++}; ++ ++int fec_send(struct eth_device *dev, volatile void *packet, int length); ++int fec_recv(struct eth_device *dev); ++int fec_init(struct eth_device *dev, bd_t *bd); ++void fec_halt(struct eth_device *dev); ++void fec_reset(struct eth_device *dev); ++ ++static void mxc_fec_mii_init(volatile fec_t *fecp) ++{ ++ u32 clk; ++ clk = mxc_get_clock(MXC_IPG_CLK); ++ ++ fecp->mscr = (fecp->mscr & (~0x7E)) | (((clk + 499999) / 5000000) << 1); ++} ++ ++static inline int __fec_mii_read(volatile fec_t *fecp, unsigned char addr, ++ unsigned char reg, unsigned short *value) ++{ ++ int waiting = FEC_MII_TIMEOUT; ++ if (fecp->eir & FEC_EIR_MII) ++ fecp->eir = FEC_EIR_MII; ++ ++ fecp->mmfr = FEC_MII_READ(addr, reg); ++ while (1) { ++ if (fecp->eir & FEC_EIR_MII) { ++ fecp->eir = FEC_EIR_MII; ++ break; ++ } ++ if ((waiting--) <= 0) ++ return -1; ++ udelay(FEC_MII_TICK); ++ } ++ *value = FEC_MII_GET_DATA(fecp->mmfr); ++ return 0; ++} ++ ++static inline int __fec_mii_write(volatile fec_t *fecp, unsigned char addr, ++ unsigned char reg, unsigned short value) ++{ ++ int waiting = FEC_MII_TIMEOUT; ++ if (fecp->eir & FEC_EIR_MII) ++ fecp->eir = FEC_EIR_MII; ++ ++ fecp->mmfr = FEC_MII_WRITE(addr, reg, value); ++ while (1) { ++ if (fecp->eir & FEC_EIR_MII) { ++ fecp->eir = FEC_EIR_MII; ++ break; ++ } ++ if ((waiting--) <= 0) ++ return -1; ++ udelay(FEC_MII_TICK); ++ } ++ return 0; ++} ++ ++static int mxc_fec_mii_read(char *devname, unsigned char addr, ++ unsigned char reg, unsigned short *value) ++{ ++ struct eth_device *dev = eth_get_dev_by_name(devname); ++ struct fec_info_s *info; ++ volatile fec_t *fecp; ++ ++ if (!dev) ++ return -1; ++ info = dev->priv; ++ fecp = (fec_t *) (info->iobase); ++ return __fec_mii_read(fecp, addr, reg, value); ++} ++ ++static int mxc_fec_mii_write(char *devname, unsigned char addr, ++ unsigned char reg, unsigned short value) ++{ ++ struct eth_device *dev = eth_get_dev_by_name(devname); ++ struct fec_info_s *info; ++ volatile fec_t *fecp; ++ if (!dev) ++ return -1; ++ info = dev->priv; ++ fecp = (fec_t *) (info->iobase); ++ return __fec_mii_write(fecp, addr, reg, value); ++} ++ ++#ifdef CONFIG_DISCOVER_PHY ++static inline int __fec_mii_info(volatile fec_t *fecp, unsigned char addr) ++{ ++ unsigned int id = 0; ++ unsigned short val; ++ if (__fec_mii_read(fecp, addr, PHY_PHYIDR2, &val) != 0) ++ return -1; ++ id = val; ++ if (id == 0xFFFF) ++ return -1; ++ ++ if (__fec_mii_read(fecp, addr, PHY_PHYIDR1, &val) != 0) ++ return -1; ++ ++ if (val == 0xFFFF) ++ return -1; ++ ++ id |= val << 16; ++ ++ printf("PHY indentify @ 0x%x = 0x%08x\n", addr, id); ++ return 0; ++} ++ ++static int mxc_fec_mii_discover_phy(struct eth_device *dev) ++{ ++ unsigned int addr; ++ struct fec_info_s *info = dev->priv; ++ volatile fec_t *fecp = (fec_t *) (info->iobase); ++ for (addr = 0; addr < 0x20; addr++) { ++ if (!__fec_mii_info(fecp, addr)) ++ return addr; ++ } ++ return -1; ++} ++#endif ++ ++static inline u16 getFecPhyStatus(volatile fec_t *fecp, unsigned char addr) ++{ ++ unsigned short val; ++ if (__fec_mii_read(fecp, addr, PHY_BMSR, &val) != 0) ++ return 0; ++ return val; ++} ++ ++static void setFecDuplexSpeed(volatile fec_t *fecp, unsigned char addr, ++ int dup_spd) ++{ ++ unsigned short val; ++ int ret; ++ ++ ret = __fec_mii_read(fecp, addr, PHY_BMCR, &val); ++ switch (dup_spd >> 16) { ++ case HALF: ++ val &= (~PHY_BMCR_DPLX); ++ break; ++ case FULL: ++ val |= PHY_BMCR_DPLX; ++ break; ++ default: ++ val |= PHY_BMCR_AUTON | PHY_BMCR_RST_NEG; ++ } ++ ret |= __fec_mii_write(fecp, addr, PHY_BMCR, val); ++ ++ if (!ret && (val & PHY_BMCR_AUTON)) { ++ ret = 0; ++ while (ret++ < 100) { ++ if (__fec_mii_read(fecp, addr, PHY_BMSR, &val)) ++ break; ++ if (!(val & PHY_BMSR_AUTN_ABLE)) ++ break; ++ if (val & PHY_BMSR_AUTN_COMP) ++ break; ++ }; ++ } ++ ++ if (__fec_mii_read(fecp, addr, PHY_BMSR, &val)) { ++ dup_spd = _100BASET | (FULL << 16); ++ } else { ++ if (val & (PHY_BMSR_100TXF | PHY_BMSR_100TXH | PHY_BMSR_100T4)) ++ dup_spd = _100BASET; ++ else ++ dup_spd = _10BASET; ++ if (val & (PHY_BMSR_100TXF | PHY_BMSR_10TF)) ++ dup_spd |= (FULL << 16); ++ else ++ dup_spd |= (HALF << 16); ++ } ++ ++ if ((dup_spd >> 16) == FULL) { ++ /* Set maximum frame length */ ++ fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | FEC_RCR_MII_MODE; ++ fecp->tcr = FEC_TCR_FDEN; ++ } else { ++ /* Half duplex mode */ ++ fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | ++ FEC_RCR_MII_MODE | FEC_RCR_DRT; ++ fecp->tcr &= ~FEC_TCR_FDEN; ++ } ++ ++#ifdef ET_DEBUG ++ if ((dup_spd & 0xFFFF) == _100BASET) { ++ printf("100Mbps\n"); ++ } else { ++ printf("10Mbps\n"); ++ } ++#endif ++} ++ ++int fec_send(struct eth_device *dev, volatile void *packet, int length) ++{ ++ struct fec_info_s *info = dev->priv; ++ volatile fec_t *fecp = (fec_t *) (info->iobase); ++ int j, rc; ++ u16 phyStatus; ++ ++ __fec_mii_read(fecp, info->phy_addr, PHY_BMSR, &phyStatus); ++ ++ if (!(phyStatus & PHY_BMSR_LS)) { ++ printf("FEC: Link is down %x\n", phyStatus); ++ return -1; ++ } ++ ++ /* section 16.9.23.3 ++ * Wait for ready ++ */ ++ j = 0; ++ while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) && ++ (j < FEC_MAX_TIMEOUT)) { ++ udelay(FEC_TIMEOUT_TICKET); ++ j++; ++ } ++ if (j >= FEC_MAX_TIMEOUT) ++ printf("TX not ready\n"); ++ ++ info->txbd[info->txIdx].cbd_bufaddr = (uint) packet; ++ info->txbd[info->txIdx].cbd_datlen = length; ++ info->txbd[info->txIdx].cbd_sc = ++ (info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_WRAP) | ++ BD_ENET_TX_TC | BD_ENET_TX_RDY_LST; ++ ++ /* Activate transmit Buffer Descriptor polling */ ++ fecp->tdar = 0x01000000; /* Descriptor polling active */ ++ ++ /* FEC fix for MCF5275, FEC unable to initial transmit data packet. ++ * A nop will ensure the descriptor polling active completed. ++ */ ++ __asm__("nop"); ++ ++#ifdef CONFIG_SYS_UNIFY_CACHE ++ icache_invalid(); ++#endif ++ j = 0; ++ ++ while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) && ++ (j < FEC_MAX_TIMEOUT)) { ++ udelay(FEC_TIMEOUT_TICKET); ++ j++; ++ } ++ if (j >= FEC_MAX_TIMEOUT) ++ printf("TX timeout packet at %x\n", packet); ++ ++#ifdef ET_DEBUG ++ printf("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n", ++ __FILE__, __LINE__, __func__, j, ++ info->txbd[info->txIdx].cbd_sc, ++ (info->txbd[info->txIdx].cbd_sc & 0x003C) >> 2); ++#endif ++ /* return only status bits */ ++ rc = (info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_STATS); ++ info->txIdx = (info->txIdx + 1) % TX_BUF_CNT; ++ ++ return rc; ++} ++ ++int fec_recv(struct eth_device *dev) ++{ ++ struct fec_info_s *info = dev->priv; ++ volatile fec_t *fecp = (fec_t *) (info->iobase); ++ int length; ++ ++ for (;;) { ++#ifdef CONFIG_SYS_UNIFY_CACHE ++ icache_invalid(); ++#endif ++ /* section 16.9.23.2 */ ++ if (info->rxbd[info->rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { ++ length = -1; ++ break; /* nothing received - leave for() loop */ ++ } ++ ++ length = info->rxbd[info->rxIdx].cbd_datlen; ++ ++ if (info->rxbd[info->rxIdx].cbd_sc & 0x003f) { ++#ifdef ET_DEBUG ++ printf("%s[%d] err: %x\n", ++ __func__, __LINE__, ++ info->rxbd[info->rxIdx].cbd_sc); ++#endif ++ } else { ++ length -= 4; ++ /* Pass the packet up to the protocol layers. */ ++ NetReceive(NetRxPackets[info->rxIdx], length); ++ ++ fecp->eir |= FEC_EIR_RXF; ++ } ++ ++ /* Give the buffer back to the FEC. */ ++ info->rxbd[info->rxIdx].cbd_datlen = 0; ++ ++ /* wrap around buffer index when necessary */ ++ if (info->rxIdx == LAST_PKTBUFSRX) { ++ info->rxbd[PKTBUFSRX - 1].cbd_sc = BD_ENET_RX_W_E; ++ info->rxIdx = 0; ++ } else { ++ info->rxbd[info->rxIdx].cbd_sc = BD_ENET_RX_EMPTY; ++ info->rxIdx++; ++ } ++ ++ /* Try to fill Buffer Descriptors */ ++ fecp->rdar = 0x01000000; /* Descriptor polling active */ ++ } ++ ++ return length; ++} ++ ++#ifdef ET_DEBUG ++void dbgFecRegs(struct eth_device *dev) ++{ ++ struct fec_info_s *info = dev->priv; ++ volatile fec_t *fecp = (fec_t *) (info->iobase); ++ ++ printf("=====\n"); ++ printf("ievent %x - %x\n", (int)&fecp->eir, fecp->eir); ++ printf("imask %x - %x\n", (int)&fecp->eimr, fecp->eimr); ++ printf("r_des_active %x - %x\n", (int)&fecp->rdar, fecp->rdar); ++ printf("x_des_active %x - %x\n", (int)&fecp->tdar, fecp->tdar); ++ printf("ecntrl %x - %x\n", (int)&fecp->ecr, fecp->ecr); ++ printf("mii_mframe %x - %x\n", (int)&fecp->mmfr, fecp->mmfr); ++ printf("mii_speed %x - %x\n", (int)&fecp->mscr, fecp->mscr); ++ printf("mii_ctrlstat %x - %x\n", (int)&fecp->mibc, fecp->mibc); ++ printf("r_cntrl %x - %x\n", (int)&fecp->rcr, fecp->rcr); ++ printf("x_cntrl %x - %x\n", (int)&fecp->tcr, fecp->tcr); ++ printf("padr_l %x - %x\n", (int)&fecp->palr, fecp->palr); ++ printf("padr_u %x - %x\n", (int)&fecp->paur, fecp->paur); ++ printf("op_pause %x - %x\n", (int)&fecp->opd, fecp->opd); ++ printf("iadr_u %x - %x\n", (int)&fecp->iaur, fecp->iaur); ++ printf("iadr_l %x - %x\n", (int)&fecp->ialr, fecp->ialr); ++ printf("gadr_u %x - %x\n", (int)&fecp->gaur, fecp->gaur); ++ printf("gadr_l %x - %x\n", (int)&fecp->galr, fecp->galr); ++ printf("x_wmrk %x - %x\n", (int)&fecp->tfwr, fecp->tfwr); ++ printf("r_bound %x - %x\n", (int)&fecp->frbr, fecp->frbr); ++ printf("r_fstart %x - %x\n", (int)&fecp->frsr, fecp->frsr); ++ printf("r_drng %x - %x\n", (int)&fecp->erdsr, fecp->erdsr); ++ printf("x_drng %x - %x\n", (int)&fecp->etdsr, fecp->etdsr); ++ printf("r_bufsz %x - %x\n", (int)&fecp->emrbr, fecp->emrbr); ++ ++ printf("\n"); ++ printf("rmon_t_drop %x - %x\n", (int)&fecp->rmon_t_drop, ++ fecp->rmon_t_drop); ++ printf("rmon_t_packets %x - %x\n", (int)&fecp->rmon_t_packets, ++ fecp->rmon_t_packets); ++ printf("rmon_t_bc_pkt %x - %x\n", (int)&fecp->rmon_t_bc_pkt, ++ fecp->rmon_t_bc_pkt); ++ printf("rmon_t_mc_pkt %x - %x\n", (int)&fecp->rmon_t_mc_pkt, ++ fecp->rmon_t_mc_pkt); ++ printf("rmon_t_crc_align %x - %x\n", (int)&fecp->rmon_t_crc_align, ++ fecp->rmon_t_crc_align); ++ printf("rmon_t_undersize %x - %x\n", (int)&fecp->rmon_t_undersize, ++ fecp->rmon_t_undersize); ++ printf("rmon_t_oversize %x - %x\n", (int)&fecp->rmon_t_oversize, ++ fecp->rmon_t_oversize); ++ printf("rmon_t_frag %x - %x\n", (int)&fecp->rmon_t_frag, ++ fecp->rmon_t_frag); ++ printf("rmon_t_jab %x - %x\n", (int)&fecp->rmon_t_jab, ++ fecp->rmon_t_jab); ++ printf("rmon_t_col %x - %x\n", (int)&fecp->rmon_t_col, ++ fecp->rmon_t_col); ++ printf("rmon_t_p64 %x - %x\n", (int)&fecp->rmon_t_p64, ++ fecp->rmon_t_p64); ++ printf("rmon_t_p65to127 %x - %x\n", (int)&fecp->rmon_t_p65to127, ++ fecp->rmon_t_p65to127); ++ printf("rmon_t_p128to255 %x - %x\n", (int)&fecp->rmon_t_p128to255, ++ fecp->rmon_t_p128to255); ++ printf("rmon_t_p256to511 %x - %x\n", (int)&fecp->rmon_t_p256to511, ++ fecp->rmon_t_p256to511); ++ printf("rmon_t_p512to1023 %x - %x\n", (int)&fecp->rmon_t_p512to1023, ++ fecp->rmon_t_p512to1023); ++ printf("rmon_t_p1024to2047 %x - %x\n", (int)&fecp->rmon_t_p1024to2047, ++ fecp->rmon_t_p1024to2047); ++ printf("rmon_t_p_gte2048 %x - %x\n", (int)&fecp->rmon_t_p_gte2048, ++ fecp->rmon_t_p_gte2048); ++ printf("rmon_t_octets %x - %x\n", (int)&fecp->rmon_t_octets, ++ fecp->rmon_t_octets); ++ ++ printf("\n"); ++ printf("ieee_t_drop %x - %x\n", (int)&fecp->ieee_t_drop, ++ fecp->ieee_t_drop); ++ printf("ieee_t_frame_ok %x - %x\n", (int)&fecp->ieee_t_frame_ok, ++ fecp->ieee_t_frame_ok); ++ printf("ieee_t_1col %x - %x\n", (int)&fecp->ieee_t_1col, ++ fecp->ieee_t_1col); ++ printf("ieee_t_mcol %x - %x\n", (int)&fecp->ieee_t_mcol, ++ fecp->ieee_t_mcol); ++ printf("ieee_t_def %x - %x\n", (int)&fecp->ieee_t_def, ++ fecp->ieee_t_def); ++ printf("ieee_t_lcol %x - %x\n", (int)&fecp->ieee_t_lcol, ++ fecp->ieee_t_lcol); ++ printf("ieee_t_excol %x - %x\n", (int)&fecp->ieee_t_excol, ++ fecp->ieee_t_excol); ++ printf("ieee_t_macerr %x - %x\n", (int)&fecp->ieee_t_macerr, ++ fecp->ieee_t_macerr); ++ printf("ieee_t_cserr %x - %x\n", (int)&fecp->ieee_t_cserr, ++ fecp->ieee_t_cserr); ++ printf("ieee_t_sqe %x - %x\n", (int)&fecp->ieee_t_sqe, ++ fecp->ieee_t_sqe); ++ printf("ieee_t_fdxfc %x - %x\n", (int)&fecp->ieee_t_fdxfc, ++ fecp->ieee_t_fdxfc); ++ printf("ieee_t_octets_ok %x - %x\n", (int)&fecp->ieee_t_octets_ok, ++ fecp->ieee_t_octets_ok); ++ ++ printf("\n"); ++ printf("rmon_r_drop %x - %x\n", (int)&fecp->rmon_r_drop, ++ fecp->rmon_r_drop); ++ printf("rmon_r_packets %x - %x\n", (int)&fecp->rmon_r_packets, ++ fecp->rmon_r_packets); ++ printf("rmon_r_bc_pkt %x - %x\n", (int)&fecp->rmon_r_bc_pkt, ++ fecp->rmon_r_bc_pkt); ++ printf("rmon_r_mc_pkt %x - %x\n", (int)&fecp->rmon_r_mc_pkt, ++ fecp->rmon_r_mc_pkt); ++ printf("rmon_r_crc_align %x - %x\n", (int)&fecp->rmon_r_crc_align, ++ fecp->rmon_r_crc_align); ++ printf("rmon_r_undersize %x - %x\n", (int)&fecp->rmon_r_undersize, ++ fecp->rmon_r_undersize); ++ printf("rmon_r_oversize %x - %x\n", (int)&fecp->rmon_r_oversize, ++ fecp->rmon_r_oversize); ++ printf("rmon_r_frag %x - %x\n", (int)&fecp->rmon_r_frag, ++ fecp->rmon_r_frag); ++ printf("rmon_r_jab %x - %x\n", (int)&fecp->rmon_r_jab, ++ fecp->rmon_r_jab); ++ printf("rmon_r_p64 %x - %x\n", (int)&fecp->rmon_r_p64, ++ fecp->rmon_r_p64); ++ printf("rmon_r_p65to127 %x - %x\n", (int)&fecp->rmon_r_p65to127, ++ fecp->rmon_r_p65to127); ++ printf("rmon_r_p128to255 %x - %x\n", (int)&fecp->rmon_r_p128to255, ++ fecp->rmon_r_p128to255); ++ printf("rmon_r_p256to511 %x - %x\n", (int)&fecp->rmon_r_p256to511, ++ fecp->rmon_r_p256to511); ++ printf("rmon_r_p512to1023 %x - %x\n", (int)&fecp->rmon_r_p512to1023, ++ fecp->rmon_r_p512to1023); ++ printf("rmon_r_p1024to2047 %x - %x\n", (int)&fecp->rmon_r_p1024to2047, ++ fecp->rmon_r_p1024to2047); ++ printf("rmon_r_p_gte2048 %x - %x\n", (int)&fecp->rmon_r_p_gte2048, ++ fecp->rmon_r_p_gte2048); ++ printf("rmon_r_octets %x - %x\n", (int)&fecp->rmon_r_octets, ++ fecp->rmon_r_octets); ++ ++ printf("\n"); ++ printf("ieee_r_drop %x - %x\n", (int)&fecp->ieee_r_drop, ++ fecp->ieee_r_drop); ++ printf("ieee_r_frame_ok %x - %x\n", (int)&fecp->ieee_r_frame_ok, ++ fecp->ieee_r_frame_ok); ++ printf("ieee_r_crc %x - %x\n", (int)&fecp->ieee_r_crc, ++ fecp->ieee_r_crc); ++ printf("ieee_r_align %x - %x\n", (int)&fecp->ieee_r_align, ++ fecp->ieee_r_align); ++ printf("ieee_r_macerr %x - %x\n", (int)&fecp->ieee_r_macerr, ++ fecp->ieee_r_macerr); ++ printf("ieee_r_fdxfc %x - %x\n", (int)&fecp->ieee_r_fdxfc, ++ fecp->ieee_r_fdxfc); ++ printf("ieee_r_octets_ok %x - %x\n", (int)&fecp->ieee_r_octets_ok, ++ fecp->ieee_r_octets_ok); ++ ++ printf("\n\n\n"); ++} ++#endif ++ ++int fec_init(struct eth_device *dev, bd_t *bd) ++{ ++ struct fec_info_s *info = dev->priv; ++ volatile fec_t *fecp = (fec_t *) (info->iobase); ++ int i; ++ u8 *ea = NULL; ++ ++ fec_reset(dev); ++ ++#if defined (CONFIG_CMD_MII) || defined (CONFIG_MII) || \ ++ defined (CONFIG_DISCOVER_PHY) ++ ++ mxc_fec_mii_init(fecp); ++#ifdef CONFIG_DISCOVER_PHY ++ if (info->phy_addr < 0 || info->phy_addr > 0x1F) ++ info->phy_addr = mxc_fec_mii_discover_phy(dev); ++#endif ++ setFecDuplexSpeed(fecp, bd, info->dup_spd); ++#else ++#ifndef CONFIG_DISCOVER_PHY ++ setFecDuplexSpeed(fecp, bd, (FECDUPLEX << 16) | FECSPEED); ++#endif /* ifndef CONFIG_SYS_DISCOVER_PHY */ ++#endif /* CONFIG_CMD_MII || CONFIG_MII */ ++ ++ /* We use strictly polling mode only */ ++ fecp->eimr = 0; ++ ++ /* Clear any pending interrupt */ ++ fecp->eir = 0xffffffff; ++ ++ /* Set station address */ ++ ea = dev->enetaddr; ++ fecp->palr = (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]); ++ fecp->paur = (ea[4] << 24) | (ea[5] << 16); ++ ++ /* Clear unicast address hash table */ ++ fecp->iaur = 0; ++ fecp->ialr = 0; ++ ++ /* Clear multicast address hash table */ ++ fecp->gaur = 0; ++ fecp->galr = 0; ++ ++ /* Set maximum receive buffer size. */ ++ fecp->emrbr = PKT_MAXBLR_SIZE; ++ ++ /* ++ * Setup Buffers and Buffer Desriptors ++ */ ++ info->rxIdx = 0; ++ info->txIdx = 0; ++ ++ /* ++ * Setup Receiver Buffer Descriptors (13.14.24.18) ++ * Settings: ++ * Empty, Wrap ++ */ ++ for (i = 0; i < PKTBUFSRX; i++) { ++ info->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; ++ info->rxbd[i].cbd_datlen = 0; /* Reset */ ++ info->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i]; ++ } ++ info->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; ++ ++ /* ++ * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) ++ * Settings: ++ * Last, Tx CRC ++ */ ++ for (i = 0; i < TX_BUF_CNT; i++) { ++ info->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC; ++ info->txbd[i].cbd_datlen = 0; /* Reset */ ++ info->txbd[i].cbd_bufaddr = (uint) (&info->txbuf[0]); ++ } ++ info->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; ++ ++ /* Set receive and transmit descriptor base */ ++ fecp->erdsr = (unsigned int)(&info->rxbd[0]); ++ fecp->etdsr = (unsigned int)(&info->txbd[0]); ++ ++ /* Now enable the transmit and receive processing */ ++ fecp->ecr |= FEC_ECR_ETHER_EN; ++ ++ /* And last, try to fill Rx Buffer Descriptors */ ++ fecp->rdar = 0x01000000; /* Descriptor polling active */ ++ ++ return 1; ++} ++ ++void fec_reset(struct eth_device *dev) ++{ ++ struct fec_info_s *info = dev->priv; ++ volatile fec_t *fecp = (fec_t *) (info->iobase); ++ int i; ++ ++ fecp->ecr = FEC_ECR_RESET; ++ for (i = 0; (fecp->ecr & FEC_ECR_RESET) && (i < FEC_RESET_DELAY); ++i) ++ udelay(1); ++ ++ if (i == FEC_RESET_DELAY) ++ printf("FEC_RESET_DELAY timeout\n"); ++ ++} ++ ++void fec_halt(struct eth_device *dev) ++{ ++ struct fec_info_s *info = dev->priv; ++ ++ fec_reset(dev); ++ ++ info->rxIdx = info->txIdx = 0; ++ memset(info->rxbd, 0, PKTBUFSRX * sizeof(cbd_t)); ++ memset(info->txbd, 0, TX_BUF_CNT * sizeof(cbd_t)); ++ memset(info->txbuf, 0, DBUF_LENGTH); ++} ++ ++int mxc_fec_initialize(bd_t *bis) ++{ ++ struct eth_device *dev; ++ int i; ++ ++ for (i = 0; i < sizeof(fec_info) / sizeof(fec_info[0]); i++) { ++ ++ dev = ++ (struct eth_device *)memalign(CONFIG_SYS_CACHELINE_SIZE, ++ sizeof *dev); ++ if (dev == NULL) ++ hang(); ++ ++ memset(dev, 0, sizeof(*dev)); ++ ++ sprintf(dev->name, "FEC%d", fec_info[i].index); ++ dev->priv = &fec_info[i]; ++ dev->init = fec_init; ++ dev->halt = fec_halt; ++ dev->send = fec_send; ++ dev->recv = fec_recv; ++ ++ /* setup Receive and Transmit buffer descriptor */ ++ fec_info[i].rxbd = ++ (cbd_t *) memalign(CONFIG_SYS_CACHELINE_SIZE, ++ (PKTBUFSRX * sizeof(cbd_t))); ++ fec_info[i].txbd = ++ (cbd_t *) memalign(CONFIG_SYS_CACHELINE_SIZE, ++ (TX_BUF_CNT * sizeof(cbd_t))); ++ fec_info[i].txbuf = ++ (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, DBUF_LENGTH); ++#ifdef ET_DEBUG ++ printf("%s: rxbd %x txbd %x ->%x\n", dev->name, ++ (int)fec_info[i].rxbd, (int)fec_info[i].txbd, ++ (int)fec_info[i].txbuf); ++#endif ++ ++ fec_info[i].phy_name = (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, 32); ++ ++ eth_register(dev); ++ ++#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) ++ miiphy_register(dev->name, mxc_fec_mii_read, mxc_fec_mii_write); ++#endif ++ } ++ ++ return 1; ++} ++ ++#endif /* CONFIG_CMD_NET, FEC_ENET & NET_MULTI */ +diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c +index 648c94c..e0794f2 100644 +--- a/drivers/net/smc911x.c ++++ b/drivers/net/smc911x.c +@@ -3,6 +3,8 @@ + * + * (c) 2007 Pengutronix, Sascha Hauer + * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * + * See file CREDITS for list of people who contributed to this + * project. + * +@@ -48,6 +50,7 @@ static inline u32 reg_read(u32 addr) + volatile u16 *addr_16 = (u16 *)addr; + return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16)); + } ++ + static inline void reg_write(u32 addr, u32 val) + { + *(volatile u16*)addr = (u16)val; +@@ -426,10 +429,9 @@ void smc911x_set_mac_csr(u8 reg, u32 data) + ; + } + +-static int smx911x_handle_mac_address(bd_t *bd) ++static int smx911x_handle_mac_address(unsigned char *m) + { + unsigned long addrh, addrl; +- unsigned char *m = bd->bi_enetaddr; + + /* if the environment has a valid mac address then use it */ + if ((m[0] | m[1] | m[2] | m[3] | m[4] | m[5])) { +@@ -594,7 +596,11 @@ static void smc911x_enable(void) + + } + ++#ifndef CONFIG_NET_MULTI + int eth_init(bd_t *bd) ++#else ++static int smc911x_eth_init(struct eth_device *dev, bd_t *bd) ++#endif + { + unsigned long val, i; + +@@ -622,7 +628,11 @@ int eth_init(bd_t *bd) + /* Configure the PHY, initialize the link state */ + smc911x_phy_configure(); + +- if (smx911x_handle_mac_address(bd)) ++#ifndef CONFIG_NET_MULTI ++ if (smx911x_handle_mac_address(bd->bi_enetaddr)) ++#else ++ if (smx911x_handle_mac_address(dev->enetaddr)) ++#endif + goto err_out; + + /* Turn on Tx + Rx */ +@@ -634,7 +644,12 @@ err_out: + return -1; + } + ++#ifndef CONFIG_NET_MULTI + int eth_send(volatile void *packet, int length) ++#else ++static int smc911x_eth_send(struct eth_device *dev, ++ volatile void *packet, int length) ++#endif + { + u32 *data = (u32*)packet; + u32 tmplen; +@@ -670,12 +685,20 @@ int eth_send(volatile void *packet, int length) + return -1; + } + ++#ifndef CONFIG_NET_MULTI + void eth_halt(void) ++#else ++static void smc911x_eth_halt(struct eth_device *dev) ++#endif + { + smc911x_reset(); + } + ++#ifndef CONFIG_NET_MULTI + int eth_rx(void) ++#else ++static int smc911x_eth_rx(struct eth_device *dev) ++#endif + { + u32 *data = (u32 *)NetRxPackets[0]; + u32 pktlen, tmplen; +@@ -701,3 +724,21 @@ int eth_rx(void) + + return 0; + } ++ ++#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) ++static struct eth_device smc911x_device; ++int smc911x_initialize(bd_t *bis) ++{ ++ memset(&smc911x_device, 0, sizeof(smc911x_device)); ++ ++ strcpy(smc911x_device.name, DRIVERNAME); ++ ++ smc911x_device.init = smc911x_eth_init; ++ smc911x_device.send = smc911x_eth_send; ++ smc911x_device.recv = smc911x_eth_rx; ++ smc911x_device.halt = smc911x_eth_halt; ++ ++ eth_register(&smc911x_device); ++ return 0; ++} ++#endif +diff --git a/include/asm-arm/arch-mx35/iomux.h b/include/asm-arm/arch-mx35/iomux.h +new file mode 100644 +index 0000000..0b9f6a9 +--- /dev/null ++++ b/include/asm-arm/arch-mx35/iomux.h +@@ -0,0 +1,290 @@ ++/* ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++#ifndef __MACH_MX35_IOMUX_H__ ++#define __MACH_MX35_IOMUX_H__ ++ ++#include ++ ++/*! ++ * @file mach-mx35/iomux.h ++ * ++ * @brief I/O Muxing control definitions and functions ++ * ++ * @ingroup GPIO_MX35 ++ */ ++ ++/*! ++ * various IOMUX functions ++ */ ++typedef enum iomux_pin_config { ++ MUX_CONFIG_FUNC = 0, /*!< used as function */ ++ MUX_CONFIG_ALT1, /*!< used as alternate function 1 */ ++ MUX_CONFIG_ALT2, /*!< used as alternate function 2 */ ++ MUX_CONFIG_ALT3, /*!< used as alternate function 3 */ ++ MUX_CONFIG_ALT4, /*!< used as alternate function 4 */ ++ MUX_CONFIG_ALT5, /*!< used as alternate function 5 */ ++ MUX_CONFIG_ALT6, /*!< used as alternate function 6 */ ++ MUX_CONFIG_ALT7, /*!< used as alternate function 7 */ ++ MUX_CONFIG_SION = 0x1 << 4, /*!< used as LOOPBACK:MUX SION bit */ ++ MUX_CONFIG_GPIO = MUX_CONFIG_ALT5, /*!< used as GPIO */ ++} iomux_pin_cfg_t; ++ ++/*! ++ * various IOMUX pad functions ++ */ ++typedef enum iomux_pad_config { ++ PAD_CTL_DRV_3_3V = 0x0 << 13, ++ PAD_CTL_DRV_1_8V = 0x1 << 13, ++ PAD_CTL_HYS_CMOS = 0x0 << 8, ++ PAD_CTL_HYS_SCHMITZ = 0x1 << 8, ++ PAD_CTL_PKE_NONE = 0x0 << 7, ++ PAD_CTL_PKE_ENABLE = 0x1 << 7, ++ PAD_CTL_PUE_KEEPER = 0x0 << 6, ++ PAD_CTL_PUE_PUD = 0x1 << 6, ++ PAD_CTL_100K_PD = 0x0 << 4, ++ PAD_CTL_47K_PU = 0x1 << 4, ++ PAD_CTL_100K_PU = 0x2 << 4, ++ PAD_CTL_22K_PU = 0x3 << 4, ++ PAD_CTL_ODE_CMOS = 0x0 << 3, ++ PAD_CTL_ODE_OpenDrain = 0x1 << 3, ++ PAD_CTL_DRV_NORMAL = 0x0 << 1, ++ PAD_CTL_DRV_HIGH = 0x1 << 1, ++ PAD_CTL_DRV_MAX = 0x2 << 1, ++ PAD_CTL_SRE_SLOW = 0x0 << 0, ++ PAD_CTL_SRE_FAST = 0x1 << 0 ++} iomux_pad_config_t; ++ ++/*! ++ * various IOMUX general purpose functions ++ */ ++typedef enum iomux_gp_func { ++ MUX_SDCTL_CSD0_SEL = 0x1 << 0, ++ MUX_SDCTL_CSD1_SEL = 0x1 << 1, ++ MUX_TAMPER_DETECT_EN = 0x1 << 2, ++} iomux_gp_func_t; ++ ++/*! ++ * various IOMUX input select register index ++ */ ++typedef enum iomux_input_select { ++ MUX_IN_AMX_P5_RXCLK = 0, ++ MUX_IN_AMX_P5_RXFS, ++ MUX_IN_AMX_P6_DA, ++ MUX_IN_AMX_P6_DB, ++ MUX_IN_AMX_P6_RXCLK, ++ MUX_IN_AMX_P6_RXFS, ++ MUX_IN_AMX_P6_TXCLK, ++ MUX_IN_AMX_P6_TXFS, ++ MUX_IN_CAN1_CANRX, ++ MUX_IN_CAN2_CANRX, ++ MUX_IN_CCM_32K_MUXED, ++ MUX_IN_CCM_PMIC_RDY, ++ MUX_IN_CSPI1_SS2_B, ++ MUX_IN_CSPI1_SS3_B, ++ MUX_IN_CSPI2_CLK_IN, ++ MUX_IN_CSPI2_DATAREADY_B, ++ MUX_IN_CSPI2_MISO, ++ MUX_IN_CSPI2_MOSI, ++ MUX_IN_CSPI2_SS0_B, ++ MUX_IN_CSPI2_SS1_B, ++ MUX_IN_CSPI2_SS2_B, ++ MUX_IN_CSPI2_SS3_B, ++ MUX_IN_EMI_WEIM_DTACK_B, ++ MUX_IN_ESDHC1_DAT4_IN, ++ MUX_IN_ESDHC1_DAT5_IN, ++ MUX_IN_ESDHC1_DAT6_IN, ++ MUX_IN_ESDHC1_DAT7_IN, ++ MUX_IN_ESDHC3_CARD_CLK_IN, ++ MUX_IN_ESDHC3_CMD_IN, ++ MUX_IN_ESDHC3_DAT0, ++ MUX_IN_ESDHC3_DAT1, ++ MUX_IN_ESDHC3_DAT2, ++ MUX_IN_ESDHC3_DAT3, ++ MUX_IN_GPIO1_IN_0, ++ MUX_IN_GPIO1_IN_10, ++ MUX_IN_GPIO1_IN_11, ++ MUX_IN_GPIO1_IN_1, ++ MUX_IN_GPIO1_IN_20, ++ MUX_IN_GPIO1_IN_21, ++ MUX_IN_GPIO1_IN_22, ++ MUX_IN_GPIO1_IN_2, ++ MUX_IN_GPIO1_IN_3, ++ MUX_IN_GPIO1_IN_4, ++ MUX_IN_GPIO1_IN_5, ++ MUX_IN_GPIO1_IN_6, ++ MUX_IN_GPIO1_IN_7, ++ MUX_IN_GPIO1_IN_8, ++ MUX_IN_GPIO1_IN_9, ++ MUX_IN_GPIO2_IN_0, ++ MUX_IN_GPIO2_IN_10, ++ MUX_IN_GPIO2_IN_11, ++ MUX_IN_GPIO2_IN_12, ++ MUX_IN_GPIO2_IN_13, ++ MUX_IN_GPIO2_IN_14, ++ MUX_IN_GPIO2_IN_15, ++ MUX_IN_GPIO2_IN_16, ++ MUX_IN_GPIO2_IN_17, ++ MUX_IN_GPIO2_IN_18, ++ MUX_IN_GPIO2_IN_19, ++ MUX_IN_GPIO2_IN_20, ++ MUX_IN_GPIO2_IN_21, ++ MUX_IN_GPIO2_IN_22, ++ MUX_IN_GPIO2_IN_23, ++ MUX_IN_GPIO2_IN_24, ++ MUX_IN_GPIO2_IN_25, ++ MUX_IN_GPIO2_IN_26, ++ MUX_IN_GPIO2_IN_27, ++ MUX_IN_GPIO2_IN_28, ++ MUX_IN_GPIO2_IN_29, ++ MUX_IN_GPIO2_IN_2, ++ MUX_IN_GPIO2_IN_30, ++ MUX_IN_GPIO2_IN_31, ++ MUX_IN_GPIO2_IN_3, ++ MUX_IN_GPIO2_IN_4, ++ MUX_IN_GPIO2_IN_5, ++ MUX_IN_GPIO2_IN_6, ++ MUX_IN_GPIO2_IN_7, ++ MUX_IN_GPIO2_IN_8, ++ MUX_IN_GPIO2_IN_9, ++ MUX_IN_GPIO3_IN_0, ++ MUX_IN_GPIO3_IN_10, ++ MUX_IN_GPIO3_IN_11, ++ MUX_IN_GPIO3_IN_12, ++ MUX_IN_GPIO3_IN_13, ++ MUX_IN_GPIO3_IN_14, ++ MUX_IN_GPIO3_IN_15, ++ MUX_IN_GPIO3_IN_4, ++ MUX_IN_GPIO3_IN_5, ++ MUX_IN_GPIO3_IN_6, ++ MUX_IN_GPIO3_IN_7, ++ MUX_IN_GPIO3_IN_8, ++ MUX_IN_GPIO3_IN_9, ++ MUX_IN_I2C3_SCL_IN, ++ MUX_IN_I2C3_SDA_IN, ++ MUX_IN_IPU_DISPB_D0_VSYNC, ++ MUX_IN_IPU_DISPB_D12_VSYNC, ++ MUX_IN_IPU_DISPB_SD_D, ++ MUX_IN_IPU_SENSB_DATA_0, ++ MUX_IN_IPU_SENSB_DATA_1, ++ MUX_IN_IPU_SENSB_DATA_2, ++ MUX_IN_IPU_SENSB_DATA_3, ++ MUX_IN_IPU_SENSB_DATA_4, ++ MUX_IN_IPU_SENSB_DATA_5, ++ MUX_IN_IPU_SENSB_DATA_6, ++ MUX_IN_IPU_SENSB_DATA_7, ++ MUX_IN_KPP_COL_0, ++ MUX_IN_KPP_COL_1, ++ MUX_IN_KPP_COL_2, ++ MUX_IN_KPP_COL_3, ++ MUX_IN_KPP_COL_4, ++ MUX_IN_KPP_COL_5, ++ MUX_IN_KPP_COL_6, ++ MUX_IN_KPP_COL_7, ++ MUX_IN_KPP_ROW_0, ++ MUX_IN_KPP_ROW_1, ++ MUX_IN_KPP_ROW_2, ++ MUX_IN_KPP_ROW_3, ++ MUX_IN_KPP_ROW_4, ++ MUX_IN_KPP_ROW_5, ++ MUX_IN_KPP_ROW_6, ++ MUX_IN_KPP_ROW_7, ++ MUX_IN_OWIRE_BATTERY_LINE, ++ MUX_IN_SPDIF_HCKT_CLK2, ++ MUX_IN_SPDIF_SPDIF_IN1, ++ MUX_IN_UART3_UART_RTS_B, ++ MUX_IN_UART3_UART_RXD_MUX, ++ MUX_IN_USB_OTG_DATA_0, ++ MUX_IN_USB_OTG_DATA_1, ++ MUX_IN_USB_OTG_DATA_2, ++ MUX_IN_USB_OTG_DATA_3, ++ MUX_IN_USB_OTG_DATA_4, ++ MUX_IN_USB_OTG_DATA_5, ++ MUX_IN_USB_OTG_DATA_6, ++ MUX_IN_USB_OTG_DATA_7, ++ MUX_IN_USB_OTG_DIR, ++ MUX_IN_USB_OTG_NXT, ++ MUX_IN_USB_UH2_DATA_0, ++ MUX_IN_USB_UH2_DATA_1, ++ MUX_IN_USB_UH2_DATA_2, ++ MUX_IN_USB_UH2_DATA_3, ++ MUX_IN_USB_UH2_DATA_4, ++ MUX_IN_USB_UH2_DATA_5, ++ MUX_IN_USB_UH2_DATA_6, ++ MUX_IN_USB_UH2_DATA_7, ++ MUX_IN_USB_UH2_DIR, ++ MUX_IN_USB_UH2_NXT, ++ MUX_IN_USB_UH2_USB_OC, ++} iomux_input_select_t; ++ ++/*! ++ * various IOMUX input functions ++ */ ++typedef enum iomux_input_config { ++ INPUT_CTL_PATH0 = 0x0, ++ INPUT_CTL_PATH1, ++ INPUT_CTL_PATH2, ++ INPUT_CTL_PATH3, ++ INPUT_CTL_PATH4, ++ INPUT_CTL_PATH5, ++ INPUT_CTL_PATH6, ++ INPUT_CTL_PATH7, ++} iomux_input_cfg_t; ++ ++/*! ++ * Request ownership for an IO pin. This function has to be the first one ++ * being called before that pin is used. The caller has to check the ++ * return value to make sure it returns 0. ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param cfg an input function as defined in \b #iomux_pin_cfg_t ++ * ++ * @return 0 if successful; Non-zero otherwise ++ */ ++int mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg); ++ ++/*! ++ * Release ownership for an IO pin ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param cfg an input function as defined in \b #iomux_pin_cfg_t ++ */ ++void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg); ++ ++/*! ++ * This function enables/disables the general purpose function for a particular ++ * signal. ++ * ++ * @param gp one signal as defined in \b #iomux_gp_func_t ++ * @param en \b #true to enable; \b #false to disable ++ */ ++void mxc_iomux_set_gpr(iomux_gp_func_t gp, int en); ++ ++/*! ++ * This function configures the pad value for a IOMUX pin. ++ * ++ * @param pin a pin number as defined in \b #iomux_pin_name_t ++ * @param config the ORed value of elements defined in \b ++ * #iomux_pad_config_t ++ */ ++void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config); ++ ++/*! ++ * This function configures input path. ++ * ++ * @param input index of input select register as defined in \b ++ * #iomux_input_select_t ++ * @param config the binary value of elements defined in \b ++ * #iomux_input_cfg_t ++ */ ++void mxc_iomux_set_input(iomux_input_select_t input, u32 config); ++#endif +diff --git a/include/asm-arm/arch-mx35/mx35.h b/include/asm-arm/arch-mx35/mx35.h +new file mode 100644 +index 0000000..a6af3c9 +--- /dev/null ++++ b/include/asm-arm/arch-mx35/mx35.h +@@ -0,0 +1,200 @@ ++/* ++ * ++ * (c) 2007 Pengutronix, Sascha Hauer ++ * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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_MX35_H ++#define __ASM_ARCH_MX35_H ++ ++#define __REG(x) (*((volatile u32 *)(x))) ++#define __REG16(x) (*((volatile u16 *)(x))) ++#define __REG8(x) (*((volatile u8 *)(x))) ++ ++#define L2CC_BASE_ADDR 0x30000000 ++ ++/* ++ * AIPS 1 ++ */ ++#define AIPS1_BASE_ADDR 0x43F00000 ++#define AIPS1_CTRL_BASE_ADDR AIPS1_BASE_ADDR ++#define MAX_BASE_ADDR 0x43F04000 ++#define EVTMON_BASE_ADDR 0x43F08000 ++#define CLKCTL_BASE_ADDR 0x43F0C000 ++#define I2C_BASE_ADDR 0x43F80000 ++#define I2C3_BASE_ADDR 0x43F84000 ++#define ATA_BASE_ADDR 0x43F8C000 ++#define UART1_BASE_ADDR 0x43F90000 ++#define UART2_BASE_ADDR 0x43F94000 ++#define I2C2_BASE_ADDR 0x43F98000 ++#define CSPI1_BASE_ADDR 0x43FA4000 ++#define IOMUXC_BASE_ADDR 0x43FAC000 ++ ++/* ++ * SPBA ++ */ ++#define SPBA_BASE_ADDR 0x50000000 ++#define UART3_BASE_ADDR 0x5000C000 ++#define CSPI2_BASE_ADDR 0x50010000 ++#define ATA_DMA_BASE_ADDR 0x50020000 ++#define FEC_BASE_ADDR 0x50038000 ++#define SPBA_CTRL_BASE_ADDR 0x5003C000 ++ ++/* ++ * AIPS 2 ++ */ ++#define AIPS2_BASE_ADDR 0x53F00000 ++#define AIPS2_CTRL_BASE_ADDR AIPS2_BASE_ADDR ++#define CCM_BASE_ADDR 0x53F80000 ++#define GPT1_BASE_ADDR 0x53F90000 ++#define EPIT1_BASE_ADDR 0x53F94000 ++#define EPIT2_BASE_ADDR 0x53F98000 ++#define GPIO3_BASE_ADDR 0x53FA4000 ++#define IPU_CTRL_BASE_ADDR 0x53FC0000 ++#define GPIO3_BASE_ADDR 0x53FA4000 ++#define GPIO1_BASE_ADDR 0x53FCC000 ++#define GPIO2_BASE_ADDR 0x53FD0000 ++#define SDMA_BASE_ADDR 0x53FD4000 ++#define RTC_BASE_ADDR 0x53FD8000 ++#define WDOG_BASE_ADDR 0x53FDC000 ++#define PWM_BASE_ADDR 0x53FE0000 ++#define RTIC_BASE_ADDR 0x53FEC000 ++#define IIM_BASE_ADDR 0x53FF0000 ++ ++/* ++ * ROMPATCH and AVIC ++ */ ++#define ROMPATCH_BASE_ADDR 0x60000000 ++#define AVIC_BASE_ADDR 0x68000000 ++ ++/* ++ * NAND, SDRAM, WEIM, M3IF, EMI controllers ++ */ ++#define EXT_MEM_CTRL_BASE 0xB8000000 ++#define ESDCTL_BASE_ADDR 0xB8001000 ++#define WEIM_BASE_ADDR 0xB8002000 ++#define WEIM_CTRL_CS0 WEIM_BASE_ADDR ++#define WEIM_CTRL_CS1 (WEIM_BASE_ADDR + 0x10) ++#define WEIM_CTRL_CS2 (WEIM_BASE_ADDR + 0x20) ++#define WEIM_CTRL_CS3 (WEIM_BASE_ADDR + 0x30) ++#define WEIM_CTRL_CS4 (WEIM_BASE_ADDR + 0x40) ++#define WEIM_CTRL_CS5 (WEIM_BASE_ADDR + 0x50) ++#define M3IF_BASE_ADDR 0xB8003000 ++#define EMI_BASE_ADDR 0xB8004000 ++ ++#define NFC_BASE_ADDR 0xBB000000 ++ ++/* ++ * Memory regions and CS ++ */ ++#define IPU_MEM_BASE_ADDR 0x70000000 ++#define CSD0_BASE_ADDR 0x80000000 ++#define CSD1_BASE_ADDR 0x90000000 ++#define CS0_BASE_ADDR 0xA0000000 ++#define CS1_BASE_ADDR 0xA8000000 ++#define CS2_BASE_ADDR 0xB0000000 ++#define CS3_BASE_ADDR 0xB2000000 ++#define CS4_BASE_ADDR 0xB4000000 ++#define CS5_BASE_ADDR 0xB6000000 ++ ++/* ++ * IRQ Controller Register Definitions. ++ */ ++#define AVIC_NIMASK 0x04 ++#define AVIC_INTTYPEH 0x18 ++#define AVIC_INTTYPEL 0x1C ++ ++/* L210 */ ++#define L2CC_BASE_ADDR 0x30000000 ++#define L2_CACHE_LINE_SIZE 32 ++#define L2_CACHE_CTL_REG 0x100 ++#define L2_CACHE_AUX_CTL_REG 0x104 ++#define L2_CACHE_SYNC_REG 0x730 ++#define L2_CACHE_INV_LINE_REG 0x770 ++#define L2_CACHE_INV_WAY_REG 0x77C ++#define L2_CACHE_CLEAN_LINE_REG 0x7B0 ++#define L2_CACHE_CLEAN_INV_LINE_REG 0x7F0 ++#define L2_CACHE_DBG_CTL_REG 0xF40 ++ ++/* CCM */ ++#define CLKCTL_CCMR 0x00 ++#define CLKCTL_PDR0 0x04 ++#define CLKCTL_PDR1 0x08 ++#define CLKCTL_PDR2 0x0C ++#define CLKCTL_PDR3 0x10 ++#define CLKCTL_PDR4 0x14 ++#define CLKCTL_RCSR 0x18 ++#define CLKCTL_MPCTL 0x1C ++#define CLKCTL_PPCTL 0x20 ++#define CLKCTL_ACMR 0x24 ++#define CLKCTL_COSR 0x28 ++#define CLKCTL_CGR0 0x2C ++#define CLKCTL_CGR1 0x30 ++#define CLKCTL_CGR2 0x34 ++#define CLKCTL_CGR3 0x38 ++ ++#define CLKMODE_AUTO 0 ++#define CLKMODE_CONSUMER 1 ++ ++#define PLL_PD(x) (((x) & 0xf) << 26) ++#define PLL_MFD(x) (((x) & 0x3ff) << 16) ++#define PLL_MFI(x) (((x) & 0xf) << 10) ++#define PLL_MFN(x) (((x) & 0x3ff) << 0) ++ ++#define CSCR_U(x) (WEIM_CTRL_CS#x + 0) ++#define CSCR_L(x) (WEIM_CTRL_CS#x + 4) ++#define CSCR_A(x) (WEIM_CTRL_CS#x + 8) ++ ++#define IPU_CONF IPU_CTRL_BASE_ADDR ++ ++#define IPU_CONF_PXL_ENDIAN (1<<8) ++#define IPU_CONF_DU_EN (1<<7) ++#define IPU_CONF_DI_EN (1<<6) ++#define IPU_CONF_ADC_EN (1<<5) ++#define IPU_CONF_SDC_EN (1<<4) ++#define IPU_CONF_PF_EN (1<<3) ++#define IPU_CONF_ROT_EN (1<<2) ++#define IPU_CONF_IC_EN (1<<1) ++#define IPU_CONF_SCI_EN (1<<0) ++ ++#define GPIO_PORT_NUM 3 ++#define GPIO_NUM_PIN 32 ++ ++#ifndef __ASSEMBLER__ ++ ++enum mxc_clock { ++MXC_ARM_CLK = 0, ++MXC_AHB_CLK, ++MXC_IPG_CLK, ++MXC_IPG_PERCLK, ++MXC_UART_CLK, ++}; ++ ++extern unsigned int mxc_get_clock(enum mxc_clock clk); ++ ++#define fixup_before_linux \ ++ { \ ++ volatile unsigned long *l2cc_ctl = (unsigned long *)0x30000100;\ ++ *l2cc_ctl = 1;\ ++ } ++#endif /* __ASSEMBLER__*/ ++#endif /* __ASM_ARCH_MX35_H */ +diff --git a/include/asm-arm/arch-mx35/mx35_pins.h b/include/asm-arm/arch-mx35/mx35_pins.h +new file mode 100644 +index 0000000..be4012b +--- /dev/null ++++ b/include/asm-arm/arch-mx35/mx35_pins.h +@@ -0,0 +1,342 @@ ++/* ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++#ifndef __ASM_ARCH_MXC_MX35_PINS_H__ ++#define __ASM_ARCH_MXC_MX35_PINS_H__ ++ ++/*! ++ * @file arch-mxc/mx35_pins.h ++ * ++ * @brief MX35 I/O Pin List ++ * ++ * @ingroup GPIO_MX35 ++ */ ++ ++#ifndef __ASSEMBLY__ ++ ++/*! ++ * @name IOMUX/PAD Bit field definitions ++ */ ++ ++/*! @{ */ ++ ++/*! ++ * In order to identify pins more effectively, each mux-controlled pin's ++ * enumerated value is constructed in the following way: ++ * ++ * ------------------------------------------------------------------- ++ * 31-29 | 28 - 24 |23 - 21| 20 - 10| 9 - 0 ++ * ------------------------------------------------------------------- ++ * IO_P | IO_I | RSVD | PAD_I | MUX_I ++ * ------------------------------------------------------------------- ++ * ++ * Bit 0 to 7 contains MUX_I used to identify the register ++ * offset (base is IOMUX_module_base ) defined in the Section ++ * "sw_pad_ctl & sw_mux_ctl details" of the IC Spec. The similar field ++ * definitions are used for the pad control register.the MX35_PIN_A0 is ++ * defined in the enumeration: ( 0x28 << MUX_I) |( 0x368 << PAD_I) ++ * So the absolute address is: IOMUX_module_base + 0x28. ++ * The pad control register offset is: 0x368. ++ */ ++ ++/*! ++ * Starting bit position within each entry of \b iomux_pins to represent the ++ * MUX control register offset ++ */ ++#define MUX_I 0 ++/*! ++ * Starting bit position within each entry of \b iomux_pins to represent the ++ * PAD control register offset ++ */ ++#define PAD_I 10 ++ ++/*! ++ * Starting bit position within each entry of \b iomux_pins to represent the ++ * reserved filed ++ */ ++#define RSVD_I 21 ++ ++#define MUX_IO_P 29 ++#define MUX_IO_I 24 ++#define IOMUX_TO_GPIO(pin) ((((unsigned int)pin >> MUX_IO_P) * \ ++ GPIO_NUM_PIN) + ((pin >> MUX_IO_I) &\ ++ ((1 << (MUX_IO_P - MUX_IO_I)) - 1))) ++#define IOMUX_TO_IRQ(pin) (MXC_GPIO_INT_BASE + IOMUX_TO_GPIO(pin)) ++#define GPIO_TO_PORT(n) (n / GPIO_NUM_PIN) ++#define GPIO_TO_INDEX(n) (n % GPIO_NUM_PIN) ++ ++#define NON_GPIO_I 0x7 ++#define PIN_TO_MUX_MASK ((1<<(PAD_I - MUX_I)) - 1) ++#define PIN_TO_PAD_MASK ((1<<(RSVD_I - PAD_I)) - 1) ++#define NON_MUX_I PIN_TO_MUX_MASK ++ ++#define _MXC_BUILD_PIN(gp, gi, mi, pi) \ ++ (((gp) << MUX_IO_P) | ((gi) << MUX_IO_I) | \ ++ ((mi) << MUX_I) | ((pi) << PAD_I)) ++ ++#define _MXC_BUILD_GPIO_PIN(gp, gi, mi, pi) \ ++ _MXC_BUILD_PIN(gp, gi, mi, pi) ++ ++#define _MXC_BUILD_NON_GPIO_PIN(mi, pi) \ ++ _MXC_BUILD_PIN(NON_GPIO_I, 0, mi, pi) ++ ++#define PIN_TO_IOMUX_MUX(pin) ((pin >> MUX_I) & PIN_TO_MUX_MASK) ++#define PIN_TO_IOMUX_PAD(pin) ((pin >> PAD_I) & PIN_TO_PAD_MASK) ++ ++/*! @} End IOMUX/PAD Bit field definitions */ ++ ++/*! ++ * This enumeration is constructed based on the Section ++ * "sw_pad_ctl & sw_mux_ctl details" of the MX35 IC Spec. Each enumerated ++ * value is constructed based on the rules described above. ++ */ ++typedef enum iomux_pins { ++ MX35_PIN_CAPTURE = _MXC_BUILD_GPIO_PIN(0, 4, 0x4, 0x328), ++ MX35_PIN_COMPARE = _MXC_BUILD_GPIO_PIN(0, 5, 0x8, 0x32C), ++ MX35_PIN_WATCHDOG_RST = _MXC_BUILD_GPIO_PIN(0, 6, 0xC, 0x330), ++ MX35_PIN_GPIO1_0 = _MXC_BUILD_GPIO_PIN(0, 0, 0x10, 0x334), ++ MX35_PIN_GPIO1_1 = _MXC_BUILD_GPIO_PIN(0, 1, 0x14, 0x338), ++ MX35_PIN_GPIO2_0 = _MXC_BUILD_GPIO_PIN(1, 0, 0x18, 0x33C), ++ MX35_PIN_GPIO3_0 = _MXC_BUILD_GPIO_PIN(2, 1, 0x1C, 0x340), ++ MX35_PIN_CLKO = _MXC_BUILD_GPIO_PIN(0, 8, 0x20, 0x34C), ++ ++ MX35_PIN_POWER_FAIL = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x360), ++ MX35_PIN_VSTBY = _MXC_BUILD_GPIO_PIN(0, 7, 0x24, 0x364), ++ MX35_PIN_A0 = _MXC_BUILD_NON_GPIO_PIN(0x28, 0x368), ++ MX35_PIN_A1 = _MXC_BUILD_NON_GPIO_PIN(0x2C, 0x36C), ++ MX35_PIN_A2 = _MXC_BUILD_NON_GPIO_PIN(0x30, 0x370), ++ MX35_PIN_A3 = _MXC_BUILD_NON_GPIO_PIN(0x34, 0x374), ++ MX35_PIN_A4 = _MXC_BUILD_NON_GPIO_PIN(0x38, 0x378), ++ MX35_PIN_A5 = _MXC_BUILD_NON_GPIO_PIN(0x3C, 0x37C), ++ MX35_PIN_A6 = _MXC_BUILD_NON_GPIO_PIN(0x40, 0x380), ++ MX35_PIN_A7 = _MXC_BUILD_NON_GPIO_PIN(0x44, 0x384), ++ MX35_PIN_A8 = _MXC_BUILD_NON_GPIO_PIN(0x48, 0x388), ++ MX35_PIN_A9 = _MXC_BUILD_NON_GPIO_PIN(0x4C, 0x38C), ++ MX35_PIN_A10 = _MXC_BUILD_NON_GPIO_PIN(0x50, 0x390), ++ MX35_PIN_MA10 = _MXC_BUILD_NON_GPIO_PIN(0x54, 0x394), ++ MX35_PIN_A11 = _MXC_BUILD_NON_GPIO_PIN(0x58, 0x398), ++ MX35_PIN_A12 = _MXC_BUILD_NON_GPIO_PIN(0x5C, 0x39C), ++ MX35_PIN_A13 = _MXC_BUILD_NON_GPIO_PIN(0x60, 0x3A0), ++ MX35_PIN_A14 = _MXC_BUILD_NON_GPIO_PIN(0x64, 0x3A4), ++ MX35_PIN_A15 = _MXC_BUILD_NON_GPIO_PIN(0x68, 0x3A8), ++ MX35_PIN_A16 = _MXC_BUILD_NON_GPIO_PIN(0x6C, 0x3AC), ++ MX35_PIN_A17 = _MXC_BUILD_NON_GPIO_PIN(0x70, 0x3B0), ++ MX35_PIN_A18 = _MXC_BUILD_NON_GPIO_PIN(0x74, 0x3B4), ++ MX35_PIN_A19 = _MXC_BUILD_NON_GPIO_PIN(0x78, 0x3B8), ++ MX35_PIN_A20 = _MXC_BUILD_NON_GPIO_PIN(0x7C, 0x3BC), ++ MX35_PIN_A21 = _MXC_BUILD_NON_GPIO_PIN(0x80, 0x3C0), ++ MX35_PIN_A22 = _MXC_BUILD_NON_GPIO_PIN(0x84, 0x3C4), ++ MX35_PIN_A23 = _MXC_BUILD_NON_GPIO_PIN(0x88, 0x3C8), ++ MX35_PIN_A24 = _MXC_BUILD_NON_GPIO_PIN(0x8C, 0x3CC), ++ MX35_PIN_A25 = _MXC_BUILD_NON_GPIO_PIN(0x90, 0x3D0), ++ ++ MX35_PIN_EB0 = _MXC_BUILD_NON_GPIO_PIN(0x94, 0x46C), ++ MX35_PIN_EB1 = _MXC_BUILD_NON_GPIO_PIN(0x98, 0x470), ++ MX35_PIN_OE = _MXC_BUILD_NON_GPIO_PIN(0x9C, 0x474), ++ MX35_PIN_CS0 = _MXC_BUILD_NON_GPIO_PIN(0xA0, 0x478), ++ MX35_PIN_CS1 = _MXC_BUILD_NON_GPIO_PIN(0xA4, 0x47C), ++ MX35_PIN_CS2 = _MXC_BUILD_NON_GPIO_PIN(0xA8, 0x480), ++ MX35_PIN_CS3 = _MXC_BUILD_NON_GPIO_PIN(0xAC, 0x484), ++ MX35_PIN_CS4 = _MXC_BUILD_GPIO_PIN(0, 20, 0xB0, 0x488), ++ MX35_PIN_CS5 = _MXC_BUILD_GPIO_PIN(0, 21, 0xB4, 0x48C), ++ MX35_PIN_NFCE_B = _MXC_BUILD_GPIO_PIN(0, 22, 0xB8, 0x490), ++ ++ MX35_PIN_LBA = _MXC_BUILD_NON_GPIO_PIN(0xBC, 0x498), ++ MX35_PIN_BCLK = _MXC_BUILD_NON_GPIO_PIN(0xC0, 0x49C), ++ MX35_PIN_RW = _MXC_BUILD_NON_GPIO_PIN(0xC4, 0x4A0), ++ ++ MX35_PIN_NFWE_B = _MXC_BUILD_GPIO_PIN(0, 18, 0xC8, 0x4CC), ++ MX35_PIN_NFRE_B = _MXC_BUILD_GPIO_PIN(0, 19, 0xCC, 0x4D0), ++ MX35_PIN_NFALE = _MXC_BUILD_GPIO_PIN(0, 20, 0xD0, 0x4D4), ++ MX35_PIN_NFCLE = _MXC_BUILD_GPIO_PIN(0, 21, 0xD4, 0x4D8), ++ MX35_PIN_NFWP_B = _MXC_BUILD_GPIO_PIN(0, 22, 0xD8, 0x4DC), ++ MX35_PIN_NFRB = _MXC_BUILD_GPIO_PIN(0, 23, 0xDC, 0x4E0), ++ ++ MX35_PIN_D15 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4E4), ++ MX35_PIN_D14 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4E8), ++ MX35_PIN_D13 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4EC), ++ MX35_PIN_D12 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4F0), ++ MX35_PIN_D11 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4F4), ++ MX35_PIN_D10 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4F8), ++ MX35_PIN_D9 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x4FC), ++ MX35_PIN_D8 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x500), ++ MX35_PIN_D7 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x504), ++ MX35_PIN_D6 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x508), ++ MX35_PIN_D5 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x50C), ++ MX35_PIN_D4 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x510), ++ MX35_PIN_D3 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x514), ++ MX35_PIN_D2 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x518), ++ MX35_PIN_D1 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x51C), ++ MX35_PIN_D0 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x520), ++ ++ MX35_PIN_CSI_D8 = _MXC_BUILD_GPIO_PIN(0, 20, 0xE0, 0x524), ++ MX35_PIN_CSI_D9 = _MXC_BUILD_GPIO_PIN(0, 21, 0xE4, 0x528), ++ MX35_PIN_CSI_D10 = _MXC_BUILD_GPIO_PIN(0, 22, 0xE8, 0x52C), ++ MX35_PIN_CSI_D11 = _MXC_BUILD_GPIO_PIN(0, 23, 0xEC, 0x530), ++ MX35_PIN_CSI_D12 = _MXC_BUILD_GPIO_PIN(0, 24, 0xF0, 0x534), ++ MX35_PIN_CSI_D13 = _MXC_BUILD_GPIO_PIN(0, 25, 0xF4, 0x538), ++ MX35_PIN_CSI_D14 = _MXC_BUILD_GPIO_PIN(0, 26, 0xF8, 0x53C), ++ MX35_PIN_CSI_D15 = _MXC_BUILD_GPIO_PIN(0, 27, 0xFC, 0x540), ++ MX35_PIN_CSI_MCLK = _MXC_BUILD_GPIO_PIN(0, 28, 0x100, 0x544), ++ MX35_PIN_CSI_VSYNC = _MXC_BUILD_GPIO_PIN(0, 29, 0x104, 0x548), ++ MX35_PIN_CSI_HSYNC = _MXC_BUILD_GPIO_PIN(0, 30, 0x108, 0x54C), ++ MX35_PIN_CSI_PIXCLK = _MXC_BUILD_GPIO_PIN(0, 31, 0x10C, 0x550), ++ ++ MX35_PIN_I2C1_CLK = _MXC_BUILD_GPIO_PIN(1, 24, 0x110, 0x554), ++ MX35_PIN_I2C1_DAT = _MXC_BUILD_GPIO_PIN(1, 25, 0x114, 0x558), ++ MX35_PIN_I2C2_CLK = _MXC_BUILD_GPIO_PIN(1, 26, 0x118, 0x55C), ++ MX35_PIN_I2C2_DAT = _MXC_BUILD_GPIO_PIN(1, 27, 0x11C, 0x560), ++ ++ MX35_PIN_STXD4 = _MXC_BUILD_GPIO_PIN(1, 28, 0x120, 0x564), ++ MX35_PIN_SRXD4 = _MXC_BUILD_GPIO_PIN(1, 29, 0x124, 0x568), ++ MX35_PIN_SCK4 = _MXC_BUILD_GPIO_PIN(1, 30, 0x128, 0x56C), ++ MX35_PIN_STXFS4 = _MXC_BUILD_GPIO_PIN(1, 31, 0x12C, 0x570), ++ MX35_PIN_STXD5 = _MXC_BUILD_GPIO_PIN(0, 0, 0x130, 0x574), ++ MX35_PIN_SRXD5 = _MXC_BUILD_GPIO_PIN(0, 1, 0x134, 0x578), ++ MX35_PIN_SCK5 = _MXC_BUILD_GPIO_PIN(0, 2, 0x138, 0x57C), ++ MX35_PIN_STXFS5 = _MXC_BUILD_GPIO_PIN(0, 3, 0x13C, 0x580), ++ ++ MX35_PIN_SCKR = _MXC_BUILD_GPIO_PIN(0, 4, 0x140, 0x584), ++ MX35_PIN_FSR = _MXC_BUILD_GPIO_PIN(0, 5, 0x144, 0x588), ++ MX35_PIN_HCKR = _MXC_BUILD_GPIO_PIN(0, 6, 0x148, 0x58C), ++ MX35_PIN_SCKT = _MXC_BUILD_GPIO_PIN(0, 7, 0x14C, 0x590), ++ MX35_PIN_FST = _MXC_BUILD_GPIO_PIN(0, 8, 0x150, 0x594), ++ MX35_PIN_HCKT = _MXC_BUILD_GPIO_PIN(0, 9, 0x154, 0x598), ++ MX35_PIN_TX5_RX0 = _MXC_BUILD_GPIO_PIN(0, 10, 0x158, 0x59C), ++ MX35_PIN_TX4_RX1 = _MXC_BUILD_GPIO_PIN(0, 11, 0x15C, 0x5A0), ++ MX35_PIN_TX3_RX2 = _MXC_BUILD_GPIO_PIN(0, 12, 0x160, 0x5A4), ++ MX35_PIN_TX2_RX3 = _MXC_BUILD_GPIO_PIN(0, 13, 0x164, 0x5A8), ++ MX35_PIN_TX1 = _MXC_BUILD_GPIO_PIN(0, 14, 0x168, 0x5AC), ++ MX35_PIN_TX0 = _MXC_BUILD_GPIO_PIN(0, 15, 0x16C, 0x5B0), ++ ++ MX35_PIN_CSPI1_MOSI = _MXC_BUILD_GPIO_PIN(0, 16, 0x170, 0x5B4), ++ MX35_PIN_CSPI1_MISO = _MXC_BUILD_GPIO_PIN(0, 17, 0x174, 0x5B8), ++ MX35_PIN_CSPI1_SS0 = _MXC_BUILD_GPIO_PIN(0, 18, 0x178, 0x5BC), ++ MX35_PIN_CSPI1_SS1 = _MXC_BUILD_GPIO_PIN(0, 19, 0x17C, 0x5C0), ++ MX35_PIN_CSPI1_SCLK = _MXC_BUILD_GPIO_PIN(2, 4, 0x180, 0x5C4), ++ MX35_PIN_CSPI1_SPI_RDY = _MXC_BUILD_GPIO_PIN(2, 5, 0x184, 0x5C8), ++ ++ MX35_PIN_RXD1 = _MXC_BUILD_GPIO_PIN(2, 6, 0x188, 0x5CC), ++ MX35_PIN_TXD1 = _MXC_BUILD_GPIO_PIN(2, 7, 0x18C, 0x5D0), ++ MX35_PIN_RTS1 = _MXC_BUILD_GPIO_PIN(2, 8, 0x190, 0x5D4), ++ MX35_PIN_CTS1 = _MXC_BUILD_GPIO_PIN(2, 9, 0x194, 0x5D8), ++ MX35_PIN_RXD2 = _MXC_BUILD_GPIO_PIN(2, 10, 0x198, 0x5DC), ++ MX35_PIN_TXD2 = _MXC_BUILD_GPIO_PIN(1, 11, 0x19C, 0x5E0), ++ MX35_PIN_RTS2 = _MXC_BUILD_GPIO_PIN(1, 12, 0x1A0, 0x5E4), ++ MX35_PIN_CTS2 = _MXC_BUILD_GPIO_PIN(1, 13, 0x1A4, 0x5E8), ++ ++ MX35_PIN_USBOTG_PWR = _MXC_BUILD_GPIO_PIN(2, 14, 0x1A8, 0x60C), ++ MX35_PIN_USBOTG_OC = _MXC_BUILD_GPIO_PIN(2, 15, 0x1AC, 0x610), ++ ++ MX35_PIN_LD0 = _MXC_BUILD_GPIO_PIN(1, 0, 0x1B0, 0x614), ++ MX35_PIN_LD1 = _MXC_BUILD_GPIO_PIN(1, 1, 0x1B4, 0x618), ++ MX35_PIN_LD2 = _MXC_BUILD_GPIO_PIN(1, 2, 0x1B8, 0x61C), ++ MX35_PIN_LD3 = _MXC_BUILD_GPIO_PIN(1, 3, 0x1BC, 0x620), ++ MX35_PIN_LD4 = _MXC_BUILD_GPIO_PIN(1, 4, 0x1C0, 0x624), ++ MX35_PIN_LD5 = _MXC_BUILD_GPIO_PIN(1, 5, 0x1C4, 0x628), ++ MX35_PIN_LD6 = _MXC_BUILD_GPIO_PIN(1, 6, 0x1C8, 0x62C), ++ MX35_PIN_LD7 = _MXC_BUILD_GPIO_PIN(1, 7, 0x1CC, 0x630), ++ MX35_PIN_LD8 = _MXC_BUILD_GPIO_PIN(1, 8, 0x1D0, 0x634), ++ MX35_PIN_LD9 = _MXC_BUILD_GPIO_PIN(1, 9, 0x1D4, 0x638), ++ MX35_PIN_LD10 = _MXC_BUILD_GPIO_PIN(1, 10, 0x1D8, 0x63C), ++ MX35_PIN_LD11 = _MXC_BUILD_GPIO_PIN(1, 11, 0x1DC, 0x640), ++ MX35_PIN_LD12 = _MXC_BUILD_GPIO_PIN(1, 12, 0x1E0, 0x644), ++ MX35_PIN_LD13 = _MXC_BUILD_GPIO_PIN(1, 13, 0x1E4, 0x648), ++ MX35_PIN_LD14 = _MXC_BUILD_GPIO_PIN(1, 14, 0x1E8, 0x64C), ++ MX35_PIN_LD15 = _MXC_BUILD_GPIO_PIN(1, 15, 0x1EC, 0x650), ++ MX35_PIN_LD16 = _MXC_BUILD_GPIO_PIN(1, 16, 0x1F0, 0x654), ++ MX35_PIN_LD17 = _MXC_BUILD_GPIO_PIN(1, 17, 0x1F4, 0x658), ++ MX35_PIN_LD18 = _MXC_BUILD_GPIO_PIN(2, 24, 0x1F8, 0x65C), ++ MX35_PIN_LD19 = _MXC_BUILD_GPIO_PIN(2, 25, 0x1FC, 0x660), ++ MX35_PIN_LD20 = _MXC_BUILD_GPIO_PIN(2, 26, 0x200, 0x664), ++ MX35_PIN_LD21 = _MXC_BUILD_GPIO_PIN(2, 27, 0x204, 0x668), ++ MX35_PIN_LD22 = _MXC_BUILD_GPIO_PIN(2, 28, 0x208, 0x66C), ++ MX35_PIN_LD23 = _MXC_BUILD_GPIO_PIN(2, 29, 0x20C, 0x670), ++ ++ MX35_PIN_D3_HSYNC = _MXC_BUILD_GPIO_PIN(2, 30, 0x210, 0x674), ++ MX35_PIN_D3_FPSHIFT = _MXC_BUILD_GPIO_PIN(2, 31, 0x214, 0x678), ++ MX35_PIN_D3_DRDY = _MXC_BUILD_GPIO_PIN(0, 0, 0x218, 0x67C), ++ MX35_PIN_CONTRAST = _MXC_BUILD_GPIO_PIN(0, 1, 0x21C, 0x680), ++ MX35_PIN_D3_VSYNC = _MXC_BUILD_GPIO_PIN(0, 2, 0x220, 0x684), ++ MX35_PIN_D3_REV = _MXC_BUILD_GPIO_PIN(0, 3, 0x224, 0x688), ++ MX35_PIN_D3_CLS = _MXC_BUILD_GPIO_PIN(0, 4, 0x228, 0x68C), ++ MX35_PIN_D3_SPL = _MXC_BUILD_GPIO_PIN(0, 5, 0x22C, 0x690), ++ ++ MX35_PIN_SD1_CMD = _MXC_BUILD_GPIO_PIN(0, 6, 0x230, 0x694), ++ MX35_PIN_SD1_CLK = _MXC_BUILD_GPIO_PIN(0, 7, 0x234, 0x698), ++ MX35_PIN_SD1_DATA0 = _MXC_BUILD_GPIO_PIN(0, 8, 0x238, 0x69C), ++ MX35_PIN_SD1_DATA1 = _MXC_BUILD_GPIO_PIN(0, 9, 0x23C, 0x6A0), ++ MX35_PIN_SD1_DATA2 = _MXC_BUILD_GPIO_PIN(0, 10, 0x240, 0x6A4), ++ MX35_PIN_SD1_DATA3 = _MXC_BUILD_GPIO_PIN(0, 11, 0x244, 0x6A8), ++ MX35_PIN_SD2_CMD = _MXC_BUILD_GPIO_PIN(1, 0, 0x248, 0x6AC), ++ MX35_PIN_SD2_CLK = _MXC_BUILD_GPIO_PIN(1, 1, 0x24C, 0x6B0), ++ MX35_PIN_SD2_DATA0 = _MXC_BUILD_GPIO_PIN(1, 2, 0x250, 0x6B4), ++ MX35_PIN_SD2_DATA1 = _MXC_BUILD_GPIO_PIN(1, 3, 0x254, 0x6B8), ++ MX35_PIN_SD2_DATA2 = _MXC_BUILD_GPIO_PIN(1, 4, 0x258, 0x6BC), ++ MX35_PIN_SD2_DATA3 = _MXC_BUILD_GPIO_PIN(1, 5, 0x25C, 0x6C0), ++ ++ MX35_PIN_ATA_CS0 = _MXC_BUILD_GPIO_PIN(1, 6, 0x260, 0x6C4), ++ MX35_PIN_ATA_CS1 = _MXC_BUILD_GPIO_PIN(1, 7, 0x264, 0x6C8), ++ MX35_PIN_ATA_DIOR = _MXC_BUILD_GPIO_PIN(1, 8, 0x268, 0x6CC), ++ MX35_PIN_ATA_DIOW = _MXC_BUILD_GPIO_PIN(1, 9, 0x26C, 0x6D0), ++ MX35_PIN_ATA_DMACK = _MXC_BUILD_GPIO_PIN(1, 10, 0x270, 0x6D4), ++ MX35_PIN_ATA_RESET_B = _MXC_BUILD_GPIO_PIN(1, 11, 0x274, 0x6D8), ++ MX35_PIN_ATA_IORDY = _MXC_BUILD_GPIO_PIN(1, 12, 0x278, 0x6DC), ++ MX35_PIN_ATA_DATA0 = _MXC_BUILD_GPIO_PIN(1, 13, 0x27C, 0x6E0), ++ MX35_PIN_ATA_DATA1 = _MXC_BUILD_GPIO_PIN(1, 14, 0x280, 0x6E4), ++ MX35_PIN_ATA_DATA2 = _MXC_BUILD_GPIO_PIN(1, 15, 0x284, 0x6E8), ++ MX35_PIN_ATA_DATA3 = _MXC_BUILD_GPIO_PIN(1, 16, 0x288, 0x6EC), ++ MX35_PIN_ATA_DATA4 = _MXC_BUILD_GPIO_PIN(1, 17, 0x28C, 0x6F0), ++ MX35_PIN_ATA_DATA5 = _MXC_BUILD_GPIO_PIN(1, 18, 0x290, 0x6F4), ++ MX35_PIN_ATA_DATA6 = _MXC_BUILD_GPIO_PIN(1, 19, 0x294, 0x6F8), ++ MX35_PIN_ATA_DATA7 = _MXC_BUILD_GPIO_PIN(1, 20, 0x298, 0x6FC), ++ MX35_PIN_ATA_DATA8 = _MXC_BUILD_GPIO_PIN(1, 21, 0x29C, 0x700), ++ MX35_PIN_ATA_DATA9 = _MXC_BUILD_GPIO_PIN(1, 22, 0x2A0, 0x704), ++ MX35_PIN_ATA_DATA10 = _MXC_BUILD_GPIO_PIN(1, 23, 0x2A4, 0x708), ++ MX35_PIN_ATA_DATA11 = _MXC_BUILD_GPIO_PIN(1, 24, 0x2A8, 0x70C), ++ MX35_PIN_ATA_DATA12 = _MXC_BUILD_GPIO_PIN(1, 25, 0x2AC, 0x710), ++ MX35_PIN_ATA_DATA13 = _MXC_BUILD_GPIO_PIN(1, 26, 0x2B0, 0x714), ++ MX35_PIN_ATA_DATA14 = _MXC_BUILD_GPIO_PIN(1, 27, 0x2B4, 0x718), ++ MX35_PIN_ATA_DATA15 = _MXC_BUILD_GPIO_PIN(1, 28, 0x2B8, 0x71C), ++ MX35_PIN_ATA_INTRQ = _MXC_BUILD_GPIO_PIN(1, 29, 0x2BC, 0x720), ++ MX35_PIN_ATA_BUFF_EN = _MXC_BUILD_GPIO_PIN(1, 30, 0x2C0, 0x724), ++ MX35_PIN_ATA_DMARQ = _MXC_BUILD_GPIO_PIN(1, 31, 0x2C4, 0x728), ++ MX35_PIN_ATA_DA0 = _MXC_BUILD_GPIO_PIN(2, 0, 0x2C8, 0x72C), ++ MX35_PIN_ATA_DA1 = _MXC_BUILD_GPIO_PIN(2, 1, 0x2CC, 0x730), ++ MX35_PIN_ATA_DA2 = _MXC_BUILD_GPIO_PIN(2, 2, 0x2D0, 0x734), ++ ++ MX35_PIN_MLB_CLK = _MXC_BUILD_GPIO_PIN(2, 3, 0x2D4, 0x738), ++ MX35_PIN_MLB_DAT = _MXC_BUILD_GPIO_PIN(2, 4, 0x2D8, 0x73C), ++ MX35_PIN_MLB_SIG = _MXC_BUILD_GPIO_PIN(2, 5, 0x2DC, 0x740), ++ ++ MX35_PIN_FEC_TX_CLK = _MXC_BUILD_GPIO_PIN(2, 6, 0x2E0, 0x744), ++ MX35_PIN_FEC_RX_CLK = _MXC_BUILD_GPIO_PIN(2, 7, 0x2E4, 0x748), ++ MX35_PIN_FEC_RX_DV = _MXC_BUILD_GPIO_PIN(2, 8, 0x2E8, 0x74C), ++ MX35_PIN_FEC_COL = _MXC_BUILD_GPIO_PIN(2, 9, 0x2EC, 0x750), ++ MX35_PIN_FEC_RDATA0 = _MXC_BUILD_GPIO_PIN(2, 10, 0x2F0, 0x754), ++ MX35_PIN_FEC_TDATA0 = _MXC_BUILD_GPIO_PIN(2, 11, 0x2F4, 0x758), ++ MX35_PIN_FEC_TX_EN = _MXC_BUILD_GPIO_PIN(2, 12, 0x2F8, 0x75C), ++ MX35_PIN_FEC_MDC = _MXC_BUILD_GPIO_PIN(2, 13, 0x2FC, 0x760), ++ MX35_PIN_FEC_MDIO = _MXC_BUILD_GPIO_PIN(2, 14, 0x300, 0x764), ++ MX35_PIN_FEC_TX_ERR = _MXC_BUILD_GPIO_PIN(2, 15, 0x304, 0x768), ++ MX35_PIN_FEC_RX_ERR = _MXC_BUILD_GPIO_PIN(2, 16, 0x308, 0x76C), ++ MX35_PIN_FEC_CRS = _MXC_BUILD_GPIO_PIN(2, 17, 0x30C, 0x770), ++ MX35_PIN_FEC_RDATA1 = _MXC_BUILD_GPIO_PIN(2, 18, 0x310, 0x774), ++ MX35_PIN_FEC_TDATA1 = _MXC_BUILD_GPIO_PIN(2, 19, 0x314, 0x778), ++ MX35_PIN_FEC_RDATA2 = _MXC_BUILD_GPIO_PIN(2, 20, 0x318, 0x77C), ++ MX35_PIN_FEC_TDATA2 = _MXC_BUILD_GPIO_PIN(2, 21, 0x31C, 0x780), ++ MX35_PIN_FEC_RDATA3 = _MXC_BUILD_GPIO_PIN(2, 22, 0x320, 0x784), ++ MX35_PIN_FEC_TDATA3 = _MXC_BUILD_GPIO_PIN(2, 23, 0x324, 0x788), ++} iomux_pin_name_t; ++ ++#endif ++#endif +diff --git a/include/asm-arm/fec.h b/include/asm-arm/fec.h +new file mode 100644 +index 0000000..58b4545 +--- /dev/null ++++ b/include/asm-arm/fec.h +@@ -0,0 +1,315 @@ ++/* ++ * fec.h -- Fast Ethernet Controller definitions ++ * ++ * Some definitions copied from commproc.h for MPC8xx: ++ * MPC8xx Communication Processor Module. ++ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) ++ * ++ * Add FEC Structure and definitions ++ * Copyright 2004-2009 Freescale Semiconductor, Inc. ++ * TsiChung Liew (Tsi-Chung.Liew@freescale.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 fec_h ++#define fec_h ++ ++/* Buffer descriptors used FEC. ++*/ ++typedef struct cpm_buf_desc { ++ ushort cbd_datlen; /* Data length in buffer */ ++ ushort cbd_sc; /* Status and Control */ ++ uint cbd_bufaddr; /* Buffer address in host memory */ ++} cbd_t; ++ ++#define BD_SC_EMPTY ((ushort)0x8000) /* Recieve is empty */ ++#define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */ ++#define BD_SC_WRAP ((ushort)0x2000)/* Last buffer descriptor */ ++#define BD_SC_INTRPT ((ushort)0x1000)/* Interrupt on change */ ++#define BD_SC_LAST ((ushort)0x0800)/* Last buffer in frame */ ++#define BD_SC_TC ((ushort)0x0400) /* Transmit CRC */ ++#define BD_SC_CM ((ushort)0x0200) /* Continous mode */ ++#define BD_SC_ID ((ushort)0x0100)/* Rec'd too many idles */ ++#define BD_SC_P ((ushort)0x0100) /* xmt preamble */ ++#define BD_SC_BR ((ushort)0x0020) /* Break received */ ++#define BD_SC_FR ((ushort)0x0010) /* Framing error */ ++#define BD_SC_PR ((ushort)0x0008) /* Parity error */ ++#define BD_SC_OV ((ushort)0x0002) /* Overrun */ ++#define BD_SC_CD ((ushort)0x0001)/* Carrier Detect lost */ ++ ++/* Buffer descriptor control/status used by Ethernet receive. ++*/ ++#define BD_ENET_RX_EMPTY ((ushort)0x8000) ++#define BD_ENET_RX_RO1 ((ushort)0x4000) ++#define BD_ENET_RX_WRAP ((ushort)0x2000) ++#define BD_ENET_RX_INTR ((ushort)0x1000) ++#define BD_ENET_RX_RO2 BD_ENET_RX_INTR ++#define BD_ENET_RX_LAST ((ushort)0x0800) ++#define BD_ENET_RX_FIRST ((ushort)0x0400) ++#define BD_ENET_RX_MISS ((ushort)0x0100) ++#define BD_ENET_RX_BC ((ushort)0x0080) ++#define BD_ENET_RX_MC ((ushort)0x0040) ++#define BD_ENET_RX_LG ((ushort)0x0020) ++#define BD_ENET_RX_NO ((ushort)0x0010) ++#define BD_ENET_RX_SH ((ushort)0x0008) ++#define BD_ENET_RX_CR ((ushort)0x0004) ++#define BD_ENET_RX_OV ((ushort)0x0002) ++#define BD_ENET_RX_CL ((ushort)0x0001) ++#define BD_ENET_RX_TR BD_ENET_RX_CL ++#define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */ ++ ++/* Buffer descriptor control/status used by Ethernet transmit. ++*/ ++#define BD_ENET_TX_READY ((ushort)0x8000) ++#define BD_ENET_TX_PAD ((ushort)0x4000) ++#define BD_ENET_TX_TO1 BD_ENET_TX_PAD ++#define BD_ENET_TX_WRAP ((ushort)0x2000) ++#define BD_ENET_TX_INTR ((ushort)0x1000) ++#define BD_ENET_TX_TO2 BD_ENET_TX_INTR_ ++#define BD_ENET_TX_LAST ((ushort)0x0800) ++#define BD_ENET_TX_TC ((ushort)0x0400) ++#define BD_ENET_TX_DEF ((ushort)0x0200) ++#define BD_ENET_TX_ABC BD_ENET_TX_DEF ++#define BD_ENET_TX_HB ((ushort)0x0100) ++#define BD_ENET_TX_LC ((ushort)0x0080) ++#define BD_ENET_TX_RL ((ushort)0x0040) ++#define BD_ENET_TX_RCMASK ((ushort)0x003c) ++#define BD_ENET_TX_UN ((ushort)0x0002) ++#define BD_ENET_TX_CSL ((ushort)0x0001) ++#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */ ++ ++/********************************************************************* ++* Fast Ethernet Controller (FEC) ++*********************************************************************/ ++/* FEC private information */ ++struct fec_info_s { ++ int index; ++ u32 iobase; ++ int phy_addr; ++ int dup_spd; ++ char *phy_name; ++ int phyname_init; ++ cbd_t *rxbd; /* Rx BD */ ++ cbd_t *txbd; /* Tx BD */ ++ uint rxIdx; ++ uint txIdx; ++ char *txbuf; ++ int initialized; ++ struct fec_info_s *next; ++}; ++ ++/* Register read/write struct */ ++typedef struct fec { ++ u32 resv0; ++ u32 eir; ++ u32 eimr; ++ u32 resv1; ++ u32 rdar; ++ u32 tdar; ++ u32 resv2[0x03]; ++ u32 ecr; ++ u32 resv3[0x06]; ++ u32 mmfr; ++ u32 mscr; ++ u32 resv4[0x07]; ++ u32 mibc; ++ u32 resv5[0x07]; ++ u32 rcr; ++ u32 resv6[0x0F]; ++ u32 tcr; ++ u32 resv7[0x07]; ++ u32 palr; ++ u32 paur; ++ u32 opd; ++ u32 resv8[0x0A]; ++ u32 iaur; ++ u32 ialr; ++ u32 gaur; ++ u32 galr; ++ u32 resv9[0x07]; ++ u32 tfwr; ++ u32 resv10; ++ u32 frbr; ++ u32 frsr; ++ u32 resv11[0x0B]; ++ u32 erdsr; ++ u32 etdsr; ++ u32 emrbr; ++ u32 resv12[0x1D]; ++ u32 rmon_t_drop; ++ u32 rmon_t_packets; ++ u32 rmon_t_bc_pkt; ++ u32 rmon_t_mc_pkt; ++ u32 rmon_t_crc_align; ++ u32 rmon_t_undersize; ++ u32 rmon_t_oversize; ++ u32 rmon_t_frag; ++ u32 rmon_t_jab; ++ u32 rmon_t_col; ++ u32 rmon_t_p64; ++ u32 rmon_t_p65to127; ++ u32 rmon_t_p128to255; ++ u32 rmon_t_p256to511; ++ u32 rmon_t_p512to1023; ++ u32 rmon_t_p1024to2047; ++ u32 rmon_t_p_gte2048; ++ u32 rmon_t_octets; ++ ++ u32 ieee_t_drop; ++ u32 ieee_t_frame_ok; ++ u32 ieee_t_1col; ++ u32 ieee_t_mcol; ++ u32 ieee_t_def; ++ u32 ieee_t_lcol; ++ u32 ieee_t_excol; ++ u32 ieee_t_macerr; ++ u32 ieee_t_cserr; ++ u32 ieee_t_sqe; ++ u32 ieee_t_fdxfc; ++ u32 ieee_t_octets_ok; ++ u32 resv13[0x02]; ++ ++ u32 rmon_r_drop; ++ u32 rmon_r_packets; ++ u32 rmon_r_bc_pkt; ++ u32 rmon_r_mc_pkt; ++ u32 rmon_r_crc_align; ++ u32 rmon_r_undersize; ++ u32 rmon_r_oversize; ++ u32 rmon_r_frag; ++ u32 rmon_r_jab; ++ u32 rmon_r_resvd_0; ++ u32 rmon_r_p64; ++ u32 rmon_r_p65to127; ++ u32 rmon_r_p128to255; ++ u32 rmon_r_p256to511; ++ u32 rmon_r_p512to1023; ++ u32 rmon_r_p1024to2047; ++ u32 rmon_r_p_gte2048; ++ u32 rmon_r_octets; ++ ++ u32 ieee_r_drop; ++ u32 ieee_r_frame_ok; ++ u32 ieee_r_crc; ++ u32 ieee_r_align; ++ u32 ieee_r_macerr; ++ u32 ieee_r_fdxfc; ++ u32 ieee_r_octets_ok; ++} fec_t; ++ ++/********************************************************************* ++* Fast Ethernet Controller (FEC) ++*********************************************************************/ ++/* Bit definitions and macros for FEC_EIR */ ++#define FEC_EIR_CLEAR_ALL (0xFFF80000) ++#define FEC_EIR_HBERR (0x80000000) ++#define FEC_EIR_BABR (0x40000000) ++#define FEC_EIR_BABT (0x20000000) ++#define FEC_EIR_GRA (0x10000000) ++#define FEC_EIR_TXF (0x08000000) ++#define FEC_EIR_TXB (0x04000000) ++#define FEC_EIR_RXF (0x02000000) ++#define FEC_EIR_RXB (0x01000000) ++#define FEC_EIR_MII (0x00800000) ++#define FEC_EIR_EBERR (0x00400000) ++#define FEC_EIR_LC (0x00200000) ++#define FEC_EIR_RL (0x00100000) ++#define FEC_EIR_UN (0x00080000) ++ ++/* Bit definitions and macros for FEC_RDAR */ ++#define FEC_RDAR_R_DES_ACTIVE (0x01000000) ++ ++/* Bit definitions and macros for FEC_TDAR */ ++#define FEC_TDAR_X_DES_ACTIVE (0x01000000) ++ ++/* Bit definitions and macros for FEC_ECR */ ++#define FEC_ECR_ETHER_EN (0x00000002) ++#define FEC_ECR_RESET (0x00000001) ++ ++/* Bit definitions and macros for FEC_MMFR */ ++#define FEC_MMFR_DATA(x) (((x)&0xFFFF)) ++#define FEC_MMFR_ST(x) (((x)&0x03)<<30) ++#define FEC_MMFR_ST_01 (0x40000000) ++#define FEC_MMFR_OP_RD (0x20000000) ++#define FEC_MMFR_OP_WR (0x10000000) ++#define FEC_MMFR_PA(x) (((x)&0x1F)<<23) ++#define FEC_MMFR_RA(x) (((x)&0x1F)<<18) ++#define FEC_MMFR_TA(x) (((x)&0x03)<<16) ++#define FEC_MMFR_TA_10 (0x00020000) ++ ++/* Bit definitions and macros for FEC_MSCR */ ++#define FEC_MSCR_DIS_PREAMBLE (0x00000080) ++#define FEC_MSCR_MII_SPEED(x) (((x)&0x3F)<<1) ++ ++/* Bit definitions and macros for FEC_MIBC */ ++#define FEC_MIBC_MIB_DISABLE (0x80000000) ++#define FEC_MIBC_MIB_IDLE (0x40000000) ++ ++/* Bit definitions and macros for FEC_RCR */ ++#define FEC_RCR_MAX_FL(x) (((x)&0x7FF)<<16) ++#define FEC_RCR_FCE (0x00000020) ++#define FEC_RCR_BC_REJ (0x00000010) ++#define FEC_RCR_PROM (0x00000008) ++#define FEC_RCR_MII_MODE (0x00000004) ++#define FEC_RCR_DRT (0x00000002) ++#define FEC_RCR_LOOP (0x00000001) ++ ++/* Bit definitions and macros for FEC_TCR */ ++#define FEC_TCR_RFC_PAUSE (0x00000010) ++#define FEC_TCR_TFC_PAUSE (0x00000008) ++#define FEC_TCR_FDEN (0x00000004) ++#define FEC_TCR_HBC (0x00000002) ++#define FEC_TCR_GTS (0x00000001) ++ ++/* Bit definitions and macros for FEC_PAUR */ ++#define FEC_PAUR_PADDR2(x) (((x)&0xFFFF)<<16) ++#define FEC_PAUR_TYPE(x) ((x)&0xFFFF) ++ ++/* Bit definitions and macros for FEC_OPD */ ++#define FEC_OPD_PAUSE_DUR(x) (((x)&0x0000FFFF)<<0) ++#define FEC_OPD_OPCODE(x) (((x)&0x0000FFFF)<<16) ++ ++/* Bit definitions and macros for FEC_TFWR */ ++#define FEC_TFWR_X_WMRK(x) ((x)&0x03) ++#define FEC_TFWR_X_WMRK_64 (0x01) ++#define FEC_TFWR_X_WMRK_128 (0x02) ++#define FEC_TFWR_X_WMRK_192 (0x03) ++ ++/* Bit definitions and macros for FEC_FRBR */ ++#define FEC_FRBR_R_BOUND(x) (((x)&0xFF)<<2) ++ ++/* Bit definitions and macros for FEC_FRSR */ ++#define FEC_FRSR_R_FSTART(x) (((x)&0xFF)<<2) ++ ++/* Bit definitions and macros for FEC_ERDSR */ ++#define FEC_ERDSR_R_DES_START(x) (((x)&0x3FFFFFFF)<<2) ++ ++/* Bit definitions and macros for FEC_ETDSR */ ++#define FEC_ETDSR_X_DES_START(x) (((x)&0x3FFFFFFF)<<2) ++ ++/* Bit definitions and macros for FEC_EMRBR */ ++#define FEC_EMRBR_R_BUF_SIZE(x) (((x)&0x7F)<<4) ++ ++#define FEC_RESET_DELAY 100 ++#define FEC_RX_TOUT 100 ++ ++#define FEC_MAX_TIMEOUT 50000 ++#define FEC_TIMEOUT_TICKET 2 ++#endif /* fec_h */ +diff --git a/include/configs/mx35_3stack.h b/include/configs/mx35_3stack.h +new file mode 100644 +index 0000000..96fef22 +--- /dev/null ++++ b/include/configs/mx35_3stack.h +@@ -0,0 +1,218 @@ ++/* ++ * Copyright (C) 2007, Guennadi Liakhovetski ++ * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * Configuration settings for the MX31ADS Freescale board. ++ * ++ * 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 ++ ++#include ++ ++ /* High Level Configuration Options */ ++#define CONFIG_ARM1136 1 /* This is an arm1136 CPU core */ ++#define CONFIG_MXC 1 ++#define CONFIG_MX35 1 /* in a mx31 */ ++#define CONFIG_MX35_HCLK_FREQ 24000000 /* RedBoot says 26MHz */ ++#define CONFIG_MX35_CLK32 32768 ++ ++#define CONFIG_DISPLAY_CPUINFO ++#define CONFIG_DISPLAY_BOARDINFO ++ ++#define BOARD_LATE_INIT ++/* ++ * Disabled for now due to build problems under Debian and a significant increase ++ * in the final file size: 144260 vs. 109536 Bytes. ++ */ ++#if 0 ++#define CONFIG_OF_LIBFDT 1 ++#define CONFIG_FIT 1 ++#define CONFIG_FIT_VERBOSE 1 ++#endif ++ ++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ ++#define CONFIG_SETUP_MEMORY_TAGS 1 ++#define CONFIG_INITRD_TAG 1 ++ ++/* ++ * Size of malloc() pool ++ */ ++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128 * 1024) ++#define CONFIG_SYS_GBL_DATA_SIZE 128/* size in bytes reserved for initial data */ ++ ++/* ++ * Hardware drivers ++ */ ++#define CONFIG_HARD_I2C 1 ++#define CONFIG_I2C_MXC 1 ++#define CONFIG_SYS_I2C_PORT I2C_BASE_ADDR ++#define CONFIG_SYS_I2C_SPEED 100000 ++#define CONFIG_SYS_I2C_SLAVE 0xfe ++ ++#define CONFIG_MX35_UART UART1_BASE_ADDR ++ ++/* allow to overwrite serial and ethaddr */ ++#define CONFIG_ENV_OVERWRITE ++#define CONFIG_CONS_INDEX 1 ++#define CONFIG_BAUDRATE 115200 ++#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200} ++ ++/*********************************************************** ++ * Command definition ++ ***********************************************************/ ++ ++#include ++ ++#define CONFIG_CMD_PING ++#define CONFIG_CMD_DHCP ++ ++#define CONFIG_CMD_I2C ++#define CONFIG_CMD_MII ++ ++#define CONFIG_BOOTDELAY 3 ++ ++#define CONFIG_LOADADDR 0x80800000 /* loadaddr env var */ ++ ++#define CONFIG_EXTRA_ENV_SETTINGS \ ++ "netdev=eth0\0" \ ++ "ethprime=smc911x\0" \ ++ "uboot_addr=0xa0000000\0" \ ++ "uboot=u-boot.bin\0" \ ++ "kernel=uImage\0" \ ++ "nfsroot=/opt/eldk/arm\0" \ ++ "bootargs_base=setenv bootargs console=ttymxc0,115200\0"\ ++ "bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs "\ ++ "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0"\ ++ "bootcmd=run bootcmd_net\0" \ ++ "bootcmd_net=run bootargs_base bootargs_nfs; " \ ++ "tftpboot ${loadaddr} ${kernel}; bootm\0" \ ++ "prg_uboot=tftpboot ${loadaddr} ${uboot}; " \ ++ "protect off ${uboot_addr} 0xa003ffff; " \ ++ "erase ${uboot_addr} 0xa003ffff; " \ ++ "cp.b ${loadaddr} ${uboot_addr} ${filesize}; " \ ++ "setenv filesize; saveenv\0" ++ ++/*Support LAN9217*/ ++#define CONFIG_DRIVER_SMC911X 1 ++#define CONFIG_DRIVER_SMC911X_16_BIT 1 ++#define CONFIG_DRIVER_SMC911X_BASE CS5_BASE_ADDR ++ ++#define CONFIG_HAS_ETH1 ++#define CONFIG_NET_MULTI 1 ++#define CONFIG_MXC_FEC ++#define CONFIG_MII ++#define CONFIG_DISCOVER_PHY ++ ++#define CONFIG_FEC0_IOBASE FEC_BASE_ADDR ++#define CONFIG_FEC0_PINMUX -1 ++#define CONFIG_FEC0_PHY_ADDR 0x1F ++#define CONFIG_FEC0_MIIBASE -1 ++ ++/* ++ * The MX31ADS board seems to have a hardware "peculiarity" confirmed under ++ * U-Boot, RedBoot and Linux: the ethernet Rx signal is reaching the CS8900A ++ * controller inverted. The controller is capable of detecting and correcting ++ * this, but it needs 4 network packets for that. Which means, at startup, you ++ * will not receive answers to the first 4 packest, unless there have been some ++ * broadcasts on the network, or your board is on a hub. Reducing the ARP ++ * timeout from default 5 seconds to 200ms we speed up the initial TFTP ++ * transfer, should the user wish one, significantly. ++ */ ++#define CONFIG_ARP_TIMEOUT 200UL ++ ++/* ++ * Miscellaneous configurable options ++ */ ++#define CONFIG_SYS_LONGHELP /* undef to save memory */ ++#define CONFIG_SYS_PROMPT "=> " ++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ ++/* Print Buffer Size */ ++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) ++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ ++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ ++ ++#define CONFIG_SYS_MEMTEST_START 0 /* memtest works on */ ++#define CONFIG_SYS_MEMTEST_END 0x10000 ++ ++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */ ++ ++#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR ++ ++#define CONFIG_SYS_HZ CONFIG_MX35_CLK32/* use 32kHz clock as source */ ++ ++#define CONFIG_CMDLINE_EDITING 1 ++ ++/*----------------------------------------------------------------------- ++ * Stack sizes ++ * ++ * The stack sizes are set up in start.S using the settings below ++ */ ++#define CONFIG_STACKSIZE (128 * 1024) /* regular stack */ ++ ++/*----------------------------------------------------------------------- ++ * Physical Memory Map ++ */ ++#define CONFIG_NR_DRAM_BANKS 1 ++#define PHYS_SDRAM_1 CSD0_BASE_ADDR ++#define PHYS_SDRAM_1_SIZE (128 * 1024 * 1024) ++ ++/*----------------------------------------------------------------------- ++ * FLASH and environment organization ++ */ ++#define CONFIG_SYS_FLASH_BASE CS0_BASE_ADDR ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of memory banks */ ++#define CONFIG_SYS_MAX_FLASH_SECT 512 /* max number of sectors on one chip */ ++/* Monitor at beginning of flash */ ++#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_FLASH_BASE ++#define CONFIG_SYS_MONITOR_LEN (512 * 1024) /* Reserve 256KiB */ ++ ++#define CONFIG_ENV_IS_IN_FLASH 1 ++#define CONFIG_ENV_SECT_SIZE (128 * 1024) ++#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE ++ ++/* Address and size of Redundant Environment Sector */ ++#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE) ++#define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE ++ ++/* ++ * S29WS256N NOR flash has 4 32KiB small sectors at the beginning and at the ++ * end. The rest of 32MiB is in 128KiB big sectors. U-Boot occupies the low ++ * 4 sectors, if we put environment next to it, we will have to occupy 128KiB ++ * for it. Putting it at the top of flash we use only 32KiB. ++ */ ++#define CONFIG_ENV_ADDR (CONFIG_SYS_MONITOR_BASE + CONFIG_ENV_SECT_SIZE) ++ ++/*----------------------------------------------------------------------- ++ * CFI FLASH driver setup ++ */ ++#define CONFIG_SYS_FLASH_CFI 1/* Flash memory is CFI compliant */ ++#define CONFIG_FLASH_CFI_DRIVER 1/* Use drivers/cfi_flash.c */ ++/* A non-standard buffered write algorithm */ ++#define CONFIG_FLASH_SPANSION_S29WS_N 1 ++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE 1/* Use buffered writes (~10x faster) */ ++#define CONFIG_SYS_FLASH_PROTECTION 1/* Use hardware sector protection */ ++ ++/* ++ * JFFS2 partitions ++ */ ++#undef CONFIG_JFFS2_CMDLINE ++#define CONFIG_JFFS2_DEV "nor0" ++ ++#endif /* __CONFIG_H */ +diff --git a/net/eth.c b/net/eth.c +index b7ef09f..32af7da 100644 +--- a/net/eth.c ++++ b/net/eth.c +@@ -2,6 +2,8 @@ + * (C) Copyright 2001-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * + * See file CREDITS for list of people who contributed to this + * project. + * +@@ -493,6 +495,9 @@ int eth_initialize(bd_t *bis) + #if defined(CONFIG_DRIVER_TI_EMAC) + davinci_eth_miiphy_initialize(bis); + #endif ++#if defined(CONFIG_DRIVER_SMC911X) ++ smc911x_initialize(bis); ++#endif + return 0; + } + #endif +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0020-ENGR00112845-spi-nor-boot-and-pmic-support-for-BBG2.patch +++ uboot-imx-2009.01/debian/patches/0020-ENGR00112845-spi-nor-boot-and-pmic-support-for-BBG2.patch @@ -0,0 +1,1507 @@ +From 554b9ee7a60aee06054503fc8bb6bb292ffab5fd Mon Sep 17 00:00:00 2001 +From: Terry Lv +Date: Wed, 27 May 2009 21:43:40 +0800 +Subject: [PATCH] ENGR00112845 spi nor boot and pmic support for BBG2. + +spi nor boot support for BBG2. + +Signed-off-by: Terry Lv +--- + board/freescale/imx51/imx51.c | 44 +++- + cpu/arm_cortexa8/mx51/generic.c | 57 +++- + drivers/mtd/spi/Makefile | 1 + + drivers/mtd/spi/imx_spi_nor.c | 558 ++++++++++++++++++++++++++++++ + drivers/mtd/spi/spi_flash.c | 5 + + drivers/mtd/spi/spi_flash_internal.h | 1 + + drivers/spi/Makefile | 2 + + drivers/spi/imx_spi.c | 329 ++++++++++++++++++ + drivers/spi/imx_spi_pmic.c | 127 +++++++ + include/asm-arm/arch-mx51/imx_spi.h | 66 ++++ + include/asm-arm/arch-mx51/imx_spi_nor.h | 54 +++ + include/asm-arm/arch-mx51/imx_spi_pmic.h | 33 ++ + include/asm-arm/arch-mx51/mx51.h | 1 + + include/configs/imx51.h | 27 ++- + 14 files changed, 1300 insertions(+), 5 deletions(-) + +diff --git a/board/freescale/imx51/imx51.c b/board/freescale/imx51/imx51.c +index c8fe23b..793afa2 100644 +--- a/board/freescale/imx51/imx51.c ++++ b/board/freescale/imx51/imx51.c +@@ -30,6 +30,7 @@ + #include + #include + #include "board-imx51.h" ++#include + + DECLARE_GLOBAL_DATA_PTR; + +@@ -159,7 +160,6 @@ static void setup_expio(void) + + int board_init(void) + { +- int pad; + setup_soc_rev(); + + gd->bd->bi_arch_number = MACH_TYPE_MX51_3DS; /* board id for linux */ +@@ -200,6 +200,48 @@ int checkboard(void) + return 0; + } + ++void spi_io_init(struct imx_spi_dev_t *dev) ++{ ++ switch (dev->base) { ++ case CSPI1_BASE_ADDR: ++ /* 000: Select mux mode: ALT0 mux port: MOSI of instance: ecspi1 */ ++ mxc_request_iomux(MX51_PIN_CSPI1_MOSI, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_CSPI1_MOSI, 0x105); ++ ++ /* 000: Select mux mode: ALT0 mux port: MISO of instance: ecspi1. */ ++ mxc_request_iomux(MX51_PIN_CSPI1_MISO, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_CSPI1_MISO, 0x105); ++ ++ if (dev->ss == 0) { ++ /* de-select SS1 of instance: ecspi1. */ ++ mxc_request_iomux(MX51_PIN_CSPI1_SS1, IOMUX_CONFIG_ALT3); ++ mxc_iomux_set_pad(MX51_PIN_CSPI1_SS1, 0x85); ++ /* 000: Select mux mode: ALT0 mux port: SS0 of instance: ecspi1. */ ++ mxc_request_iomux(MX51_PIN_CSPI1_SS0, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_CSPI1_SS0, 0x185); ++ } else if (dev->ss == 1) { ++ /* de-select SS0 of instance: ecspi1. */ ++ mxc_request_iomux(MX51_PIN_CSPI1_SS0, IOMUX_CONFIG_ALT3); ++ mxc_iomux_set_pad(MX51_PIN_CSPI1_SS0, 0x85); ++ /* 000: Select mux mode: ALT0 mux port: SS1 of instance: ecspi1. */ ++ mxc_request_iomux(MX51_PIN_CSPI1_SS1, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_CSPI1_SS1, 0x105); ++ } ++ ++ /* 000: Select mux mode: ALT0 mux port: RDY of instance: ecspi1. */ ++ mxc_request_iomux(MX51_PIN_CSPI1_RDY, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_CSPI1_RDY, 0x180); ++ ++ /* 000: Select mux mode: ALT0 mux port: SCLK of instance: ecspi1. */ ++ mxc_request_iomux(MX51_PIN_CSPI1_SCLK, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_CSPI1_SCLK, 0x105); ++ break; ++ case CSPI2_BASE_ADDR: ++ default: ++ break; ++ } ++} ++ + #ifdef CONFIG_NET_MULTI + int board_eth_init(bd_t *bis) + { +diff --git a/cpu/arm_cortexa8/mx51/generic.c b/cpu/arm_cortexa8/mx51/generic.c +index 8982a80..ef8ef98 100644 +--- a/cpu/arm_cortexa8/mx51/generic.c ++++ b/cpu/arm_cortexa8/mx51/generic.c +@@ -49,6 +49,7 @@ static u32 __decode_pll(enum pll_clocks pll, u32 infreq) + pd = (mfi & 0xF) + 1; + mfi = (mfi >> 4) & 0xF; + mfi = (mfi >= 5) ? mfi : 5; ++ + return ((4 * (infreq / 1000) * (mfi * mfd + mfn)) / (mfd * pd)) * 1000; + } + +@@ -136,9 +137,57 @@ static u32 __get_uart_clk(void) + podf = (reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >> + MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET; + freq /= (pred + 1) * (podf + 1); ++ + return freq; + } + ++/*! +++ * This function returns the low power audio clock. +++ */ ++u32 get_lp_apm(void) ++{ ++ u32 ret_val = 0; ++ u32 ccsr = __REG(MXC_CCM_CCSR); ++ ++ if (((ccsr >> 9) & 1) == 0) ++ ret_val = CONFIG_MX51_HCLK_FREQ; ++ else ++ ret_val = ((32768 * 1024)); ++ ++ return ret_val; ++} ++ ++static u32 __get_cspi_clk(void) ++{ ++ u32 ret_val = 0, pdf, pre_pdf, clk_sel; ++ u32 cscmr1 = __REG(MXC_CCM_CSCMR1); ++ u32 cscdr2 = __REG(MXC_CCM_CSCDR2); ++ ++ pre_pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) \ ++ >> MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET; ++ pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) \ ++ >> MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET; ++ clk_sel = (cscmr1 & MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK) \ ++ >> MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET; ++ ++ switch (clk_sel) { ++ case 0: ++ ret_val = __decode_pll(PLL1_CLK, CONFIG_MX51_HCLK_FREQ) / ((pre_pdf + 1) * (pdf + 1)); ++ break; ++ case 1: ++ ret_val = __decode_pll(PLL2_CLK, CONFIG_MX51_HCLK_FREQ) / ((pre_pdf + 1) * (pdf + 1)); ++ break; ++ case 2: ++ ret_val = __decode_pll(PLL3_CLK, CONFIG_MX51_HCLK_FREQ) / ((pre_pdf + 1) * (pdf + 1)); ++ break; ++ default: ++ ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1)); ++ break; ++ } ++ ++ return ret_val; ++} ++ + unsigned int mxc_get_clock(enum mxc_clock clk) + { + switch (clk) { +@@ -152,6 +201,8 @@ unsigned int mxc_get_clock(enum mxc_clock clk) + return __get_ipg_per_clk(); + case MXC_UART_CLK: + return __get_uart_clk(); ++ case MXC_CSPI_CLK: ++ return __get_cspi_clk(); + } + return -1; + } +@@ -165,8 +216,10 @@ void mxc_dump_clocks(void) + printf("mx51 pll2: %dMHz\n", freq / 1000000); + freq = __decode_pll(PLL3_CLK, CONFIG_MX51_HCLK_FREQ); + printf("mx51 pll3: %dMHz\n", freq / 1000000); +- printf("ipg clock : %dHz\n", __get_ipg_clk()); +- printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); ++ printf("ipg clock : %dHz\n", mxc_get_clock(MXC_IPG_CLK)); ++ printf("ipg per clock : %dHz\n", mxc_get_clock(MXC_IPG_PERCLK)); ++ printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); ++ printf("cspi clock : %dHz\n", mxc_get_clock(MXC_CSPI_CLK)); + } + + #if defined(CONFIG_DISPLAY_CPUINFO) +diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile +index 3d4f892..c062a87 100644 +--- a/drivers/mtd/spi/Makefile ++++ b/drivers/mtd/spi/Makefile +@@ -28,6 +28,7 @@ LIB := $(obj)libspi_flash.a + COBJS-$(CONFIG_SPI_FLASH) += spi_flash.o + COBJS-$(CONFIG_SPI_FLASH_ATMEL) += atmel.o + COBJS-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.o ++COBJS-$(CONFIG_SPI_FLASH_IMX) += imx_spi_nor.o + + COBJS := $(COBJS-y) + SRCS := $(COBJS:.o=.c) +diff --git a/drivers/mtd/spi/imx_spi_nor.c b/drivers/mtd/spi/imx_spi_nor.c +new file mode 100644 +index 0000000..24af8b2 +--- /dev/null ++++ b/drivers/mtd/spi/imx_spi_nor.c +@@ -0,0 +1,558 @@ ++/* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++static u8 g_tx_buf[256]; ++static u8 g_rx_buf[256]; ++ ++#define WRITE_ENABLE(a) spi_nor_cmd_1byte(a, WREN) ++#define WRITE_DISABLE(a) spi_nor_cmd_1byte(a, WRDI) ++#define ENABLE_WRITE_STATUS(a) spi_nor_cmd_1byte(a, EWSR) ++ ++struct imx_spi_flash_params { ++ u8 idcode1; ++ u32 block_size; ++ u32 block_count; ++ u32 device_size; ++ const char *name; ++}; ++ ++struct imx_spi_flash { ++ const struct imx_spi_flash_params *params; ++ struct spi_flash flash; ++}; ++ ++static inline struct imx_spi_flash * ++to_imx_spi_flash(struct spi_flash *flash) ++{ ++ return container_of(flash, struct imx_spi_flash, flash); ++} ++ ++static const struct imx_spi_flash_params imx_spi_flash_table[] = { ++ { ++ .idcode1 = 0x25, ++ .block_size = SZ_64K, ++ .block_count = 32, ++ .device_size = SZ_64K * 32, ++ .name = "SST25VF016B - 2MB", ++ }, ++}; ++ ++static s32 spi_nor_flash_query(struct spi_flash *flash, void* data) ++{ ++ u8 au8Tmp[4] = { 0 }; ++ u8 *pData = (u8 *)data; ++ ++ g_tx_buf[3] = JEDEC_ID; ++ ++ if (spi_xfer(flash->spi, (4 << 3), g_tx_buf, au8Tmp, ++ SPI_XFER_BEGIN | SPI_XFER_END)) { ++ return -1; ++ } ++ ++ printf("JEDEC ID: 0x%02x:0x%02x:0x%02x\n", ++ au8Tmp[2], au8Tmp[1], au8Tmp[0]); ++ ++ pData[0] = au8Tmp[2]; ++ pData[1] = au8Tmp[1]; ++ pData[2] = au8Tmp[0]; ++ ++ return 0; ++} ++ ++static s32 spi_nor_cmd_1byte(struct spi_flash *flash, u8 cmd) ++{ ++ g_tx_buf[0] = cmd; ++ ++ if (spi_xfer(flash->spi, (1 << 3), g_tx_buf, g_rx_buf, ++ SPI_XFER_BEGIN | SPI_XFER_END) != 0) { ++ printf("Error: %s(): %d\n", __func__, __LINE__); ++ return -1; ++ } ++ return 0; ++} ++ ++static s32 spi_nor_status(struct spi_flash *flash) ++{ ++ g_tx_buf[1] = RDSR; ++ ++ if (spi_xfer(flash->spi, 2 << 3, g_tx_buf, g_rx_buf, ++ SPI_XFER_BEGIN | SPI_XFER_END) != 0) { ++ printf("Error: %s(): %d\n", __func__, __LINE__); ++ return 0; ++ } ++ return g_rx_buf[0]; ++} ++ ++static int spi_nor_program_1byte(struct spi_flash *flash, ++ u8 data, void *addr) ++{ ++ u32 addr_val = (u32)addr; ++ ++ /* need to do write-enable command */ ++ if (WRITE_ENABLE(flash) != 0) { ++ printf("Error : %d\n", __LINE__); ++ return -1; ++ } ++ g_tx_buf[0] = BYTE_PROG; /* need to skip bytes 1, 2, 3 */ ++ g_tx_buf[4] = data; ++ g_tx_buf[5] = addr_val & 0xFF; ++ g_tx_buf[6] = (addr_val >> 8) & 0xFF; ++ g_tx_buf[7] = (addr_val >> 16) & 0xFF; ++ ++ debug("0x%x: 0x%x\n", *(u32 *)g_tx_buf, *(u32 *)(g_tx_buf + 4)); ++ debug("addr=0x%x\n", addr_val); ++ ++ if (spi_xfer(flash->spi, 5 << 3, g_tx_buf, g_rx_buf, ++ SPI_XFER_BEGIN | SPI_XFER_END) != 0) { ++ printf("Error: %s(%d): failed\n", __FILE__, __LINE__); ++ return -1; ++ } ++ ++ while (spi_nor_status(flash) & RDSR_BUSY) ++ ; ++ ++ return 0; ++} ++ ++/*! ++ * Write 'val' to flash WRSR (write status register) ++ */ ++static int spi_nor_write_status(struct spi_flash *flash, u8 val) ++{ ++ g_tx_buf[0] = val; ++ g_tx_buf[1] = WRSR; ++ ++ if (spi_xfer(flash->spi, 2 << 3, g_tx_buf, g_rx_buf, ++ SPI_XFER_BEGIN | SPI_XFER_END) != 0) { ++ printf("Error: %s(): %d\n", __func__, __LINE__); ++ return -1; ++ } ++ return 0; ++} ++ ++/*! ++ * Erase a block_size data from block_addr offset in the flash ++ */ ++static int spi_nor_erase_block(struct spi_flash *flash, ++ void *block_addr, u32 block_size) ++{ ++ u32 *cmd = (u32 *)g_tx_buf; ++ u32 addr = (u32) block_addr; ++ ++ if (block_size != SZ_64K && ++ block_size != SZ_32K && ++ block_size != SZ_4K) { ++ printf("Error - block_size is not " ++ "4kB, 32kB or 64kB: 0x%x\n", ++ block_size); ++ return -1; ++ } ++ ++ if ((addr & (block_size - 1)) != 0) { ++ printf("Error - block_addr is not " ++ "4kB, 32kB or 64kB aligned: %p\n", ++ block_addr); ++ return -1; ++ } ++ ++ if (ENABLE_WRITE_STATUS(flash) != 0 || ++ spi_nor_write_status(flash, 0) != 0) { ++ printf("Error: %s: %d\n", __func__, __LINE__); ++ return -1; ++ } ++ ++ /* need to do write-enable command */ ++ if (WRITE_ENABLE(flash) != 0) { ++ printf("Error : %d\n", __LINE__); ++ return -1; ++ } ++ ++ if (block_size == SZ_64K) ++ *cmd = (ERASE_64K << 24) | (addr & 0x00FFFFFF); ++ else if (block_size == SZ_32K) ++ *cmd = (ERASE_32K << 24) | (addr & 0x00FFFFFF); ++ else if (block_size == SZ_4K) ++ *cmd = (ERASE_4K << 24) | (addr & 0x00FFFFFF); ++ ++ /* now do the block erase */ ++ if (spi_xfer(flash->spi, 4 << 3, g_tx_buf, g_rx_buf, ++ SPI_XFER_BEGIN | SPI_XFER_END) != 0) { ++ return -1; ++ } ++ ++ while (spi_nor_status(flash) & RDSR_BUSY) ++ ; ++ ++ return 0; ++} ++ ++static int spi_nor_flash_read(struct spi_flash *flash, u32 offset, ++ size_t len, void *buf) ++{ ++ struct imx_spi_flash *imx_sf = to_imx_spi_flash(flash); ++ u32 *cmd = (u32 *)g_tx_buf; ++ u32 max_rx_sz = (MAX_SPI_BYTES) - 4; ++ u8 *d_buf = (u8 *)buf; ++ u8 *s_buf; ++ s32 s32remain_size = len; ++ int i; ++ ++ if (!(flash->spi)) ++ return -1; ++ ++ debug("%s(from flash=0x%08x to ram=%p len=0x%x)\n", ++ __func__, ++ offset, buf, len); ++ ++ if (len == 0) ++ return 0; ++ ++ *cmd = (READ << 24) | ((u32)offset & 0x00FFFFFF); ++ ++ for (; s32remain_size > 0; s32remain_size -= max_rx_sz, *cmd += max_rx_sz) { ++ debug("Addr:0x%p=>Offset:0x%08x, %d bytes transferred\n", ++ d_buf, ++ (*cmd & 0x00FFFFFF), ++ (len - s32remain_size)); ++ debug("%d%% completed\n", ((len - s32remain_size) * 100 / len)); ++ ++ if (s32remain_size < max_rx_sz) { ++ debug("100%% completed\n"); ++ ++ if (spi_xfer(flash->spi, (s32remain_size + 4) << 3, ++ g_tx_buf, g_rx_buf, ++ SPI_XFER_BEGIN | SPI_XFER_END) != 0) { ++ printf("Error: %s(%d): failed\n", __FILE__, __LINE__); ++ return -1; ++ } ++ /* throw away 4 bytes (5th received bytes is real) */ ++ s_buf = g_rx_buf + 4; ++ ++ /* now adjust the endianness */ ++ for (i = s32remain_size; i >= 0; i -= 4, s_buf += 4) { ++ if (i < 4) { ++ if (i == 1) { ++ *d_buf = s_buf[0]; ++ } else if (i == 2) { ++ *d_buf++ = s_buf[1]; ++ *d_buf++ = s_buf[0]; ++ } else if (i == 3) { ++ *d_buf++ = s_buf[2]; ++ *d_buf++ = s_buf[1]; ++ *d_buf++ = s_buf[0]; ++ } ++ printf("\n"); ++ return 0; ++ } ++ /* copy 4 bytes */ ++ *d_buf++ = s_buf[3]; ++ *d_buf++ = s_buf[2]; ++ *d_buf++ = s_buf[1]; ++ *d_buf++ = s_buf[0]; ++ } ++ } ++ ++ /* now grab max_rx_sz data (+4 is ++ *needed due to 4-throw away bytes */ ++ if (spi_xfer(flash->spi, (max_rx_sz + 4) << 3, ++ g_tx_buf, g_rx_buf, SPI_XFER_BEGIN | SPI_XFER_END) != 0) { ++ printf("Error: %s(%d): failed\n", __FILE__, __LINE__); ++ return -1; ++ } ++ /* throw away 4 bytes (5th received bytes is real) */ ++ s_buf = g_rx_buf + 4; ++ /* now adjust the endianness */ ++ for (i = 0; i < max_rx_sz; i += 4, s_buf += 4) { ++ *d_buf++ = s_buf[3]; ++ *d_buf++ = s_buf[2]; ++ *d_buf++ = s_buf[1]; ++ *d_buf++ = s_buf[0]; ++ } ++ ++ if ((s32remain_size % imx_sf->params->block_size) == 0) ++ printf("."); ++ } ++ printf("\n"); ++ ++ return -1; ++} ++ ++static int spi_nor_flash_write(struct spi_flash *flash, u32 offset, ++ size_t len, const void *buf) ++{ ++ struct imx_spi_flash *imx_sf = to_imx_spi_flash(flash); ++ u32 d_addr = offset; ++ u8 *s_buf = (u8 *)buf; ++ s32 s32remain_size = len; ++ ++ if (!(flash->spi)) ++ return -1; ++ ++ if (len == 0) ++ return 0; ++ ++ write("%s(flash addr=0x%08x, ram=%p, len=0x%x)\n", ++ __func__, offset, buf, len); ++ ++ if (ENABLE_WRITE_STATUS(flash) != 0 || ++ spi_nor_write_status(flash, 0) != 0) { ++ printf("Error: %s: %d\n", __func__, __LINE__); ++ return -1; ++ } ++ ++ if ((d_addr & 1) != 0) { ++ /* program 1st byte */ ++ if (spi_nor_program_1byte(flash, s_buf[0], ++ (void *)d_addr) != 0) { ++ printf("Error: %s(%d)\n", __func__, __LINE__); ++ return -1; ++ } ++ if (--s32remain_size == 0) ++ return 0; ++ d_addr++; ++ s_buf++; ++ } ++ ++ /* need to do write-enable command */ ++ if (WRITE_ENABLE(flash) != 0) { ++ printf("Error : %d\n", __LINE__); ++ return -1; ++ } ++ ++ /* ++ These two bytes write will be copied to txfifo first with ++ g_tx_buf[1] being shifted out and followed by g_tx_buf[0]. ++ The reason for this is we will specify burst len=6. So SPI will ++ do this kind of data movement. ++ */ ++ g_tx_buf[0] = d_addr >> 16; ++ g_tx_buf[1] = AAI_PROG; /* need to skip bytes 1, 2 */ ++ /* byte shifted order is: 7, 6, 5, 4 */ ++ g_tx_buf[4] = s_buf[1]; ++ g_tx_buf[5] = s_buf[0]; ++ g_tx_buf[6] = d_addr; ++ g_tx_buf[7] = d_addr >> 8; ++ if (spi_xfer(flash->spi, 6 << 3, g_tx_buf, g_rx_buf, ++ SPI_XFER_BEGIN | SPI_XFER_END) != 0) { ++ printf("Error: %s(%d): failed\n", ++ __FILE__, __LINE__); ++ return -1; ++ } ++ ++ while (spi_nor_status(flash) & RDSR_BUSY) ++ ; ++ ++ for (d_addr += 2, s_buf += 2, s32remain_size -= 2; ++ s32remain_size > 1; ++ d_addr += 2, s_buf += 2, s32remain_size -= 2) { ++ debug("%d%% transferred\n", ++ ((len - s32remain_size) * 100 / len)); ++ /* byte shifted order is: 2,1,0 */ ++ g_tx_buf[2] = AAI_PROG; ++ g_tx_buf[1] = s_buf[0]; ++ g_tx_buf[0] = s_buf[1]; ++ ++ if (spi_xfer(flash->spi, 3 << 3, g_tx_buf, g_rx_buf, ++ SPI_XFER_BEGIN | SPI_XFER_END) != 0) { ++ printf("Error: %s(%d): failed\n", ++ __FILE__, __LINE__); ++ return -1; ++ } ++ ++ while (spi_nor_status(flash) & RDSR_BUSY) ++ ; ++ ++ if ((s32remain_size % imx_sf->params->block_size) == 0) ++ printf("."); ++ } ++ printf("\n"); ++ debug("100%% transferred\n"); ++ ++ WRITE_DISABLE(flash); ++ while (spi_nor_status(flash) & RDSR_BUSY) ++ ; ++ ++ if (WRITE_ENABLE(flash) != 0) { ++ printf("Error : %d\n", __LINE__); ++ return -1; ++ } ++ ++ if (len == 1) { ++ /* need to do write-enable command */ ++ /* only 1 byte left */ ++ if (spi_nor_program_1byte(flash, s_buf[0], ++ (void *)d_addr) != 0) { ++ printf("Error: %s(%d)\n", ++ __func__, __LINE__); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static int spi_nor_flash_erase(struct spi_flash *flash, u32 offset, ++ size_t len) ++{ ++ struct imx_spi_flash *imx_sf = to_imx_spi_flash(flash); ++ s32 s32remain_size = len; ++ ++ if (!(flash->spi)) ++ return -1; ++ ++ if ((len % SZ_4K) != 0 || len == 0) { ++ printf("Error: size (0x%x) is not integer multiples of 4kB(0x1000)\n", ++ len); ++ return -1; ++ } ++ if ((offset & (SZ_4K - 1)) != 0) { ++ printf("Error - addr is not 4kB(0x1000) aligned: 0x%08x\n", ++ offset); ++ return -1; ++ } ++ for (; s32remain_size > 0; s32remain_size -= SZ_4K, offset += SZ_4K) { ++ debug("Erasing 0x%08x, %d%% erased\n", ++ offset, ++ ((len - s32remain_size) * 100 / len)); ++ if (spi_nor_erase_block(flash, ++ (void *)offset, SZ_4K) != 0) { ++ printf("Error: spi_nor_flash_erase(): %d\n", __LINE__); ++ return -1; ++ } ++ printf("."); ++ } ++ printf("\n"); ++ debug("100%% erased\n"); ++ return 0; ++} ++ ++struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int spi_mode) ++{ ++ struct spi_slave *spi = NULL; ++ const struct imx_spi_flash_params *params = NULL; ++ struct imx_spi_flash *imx_sf = NULL; ++ u8 idcode[4] = { 0 }; ++ u32 i = 0; ++ s32 ret = 0; ++ ++ if (CONFIG_SPI_FLASH_CS != cs) { ++ printf("Invalid cs for SPI NOR.\n"); ++ return NULL; ++ } ++ ++ spi = spi_setup_slave(bus, cs, max_hz, spi_mode); ++ ++ if (!spi) { ++ debug("SF: Failed to set up slave\n"); ++ return NULL; ++ } ++ ++ ret = spi_claim_bus(spi); ++ if (ret) { ++ debug("SF: Failed to claim SPI bus: %d\n", ret); ++ goto err_claim_bus; ++ } ++ ++ imx_sf = (struct imx_spi_flash *)malloc(sizeof(struct imx_spi_flash)); ++ ++ if (!imx_sf) { ++ debug("SF: Failed to allocate memory\n"); ++ spi_free_slave(spi); ++ return NULL; ++ } ++ ++ imx_sf->flash.spi = spi; ++ ++ /* Read the ID codes */ ++ ret = spi_nor_flash_query(&(imx_sf->flash), idcode); ++ if (ret) ++ goto err_read_id; ++ ++ for (i = 0; i < ARRAY_SIZE(imx_spi_flash_table); ++i) { ++ params = &imx_spi_flash_table[i]; ++ if (params->idcode1 == idcode[1]) ++ break; ++ } ++ ++ if (i == ARRAY_SIZE(imx_spi_flash_table)) { ++ debug("SF: Unsupported DataFlash ID %02x\n", ++ idcode[1]); ++ ++ goto err_invalid_dev; ++ } ++ ++ imx_sf->params = params; ++ ++ imx_sf->flash.name = params->name; ++ imx_sf->flash.size = params->device_size; ++ ++ imx_sf->flash.read = spi_nor_flash_read; ++ imx_sf->flash.write = spi_nor_flash_write; ++ imx_sf->flash.erase = spi_nor_flash_erase; ++ ++ debug("SF: Detected %s with block size %lu, " ++ "block count %lu, total %u bytes\n", ++ params->name, ++ params->block_size, ++ params->block_count, ++ params->device_size); ++ ++ return &(imx_sf->flash); ++ ++err_read_id: ++ spi_release_bus(spi); ++err_invalid_dev: ++ if (imx_sf) ++ free(imx_sf); ++err_claim_bus: ++ if (spi) ++ spi_free_slave(spi); ++ return NULL; ++} ++ ++void spi_flash_free(struct spi_flash *flash) ++{ ++ struct imx_spi_flash *imx_sf = NULL; ++ ++ if (!flash) ++ return; ++ ++ imx_sf = to_imx_spi_flash(flash); ++ ++ if (flash->spi) { ++ spi_free_slave(flash->spi); ++ flash->spi = NULL; ++ } ++ ++ free(imx_sf); ++} ++ +diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c +index d1d81af..9917e95 100644 +--- a/drivers/mtd/spi/spi_flash.c ++++ b/drivers/mtd/spi/spi_flash.c +@@ -139,6 +139,11 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, + flash = spi_flash_probe_stmicro(spi, idcode); + break; + #endif ++#ifdef CONFIG_SPI_FLASH_IMX ++ case 0xbf: ++ flash = spi_flash_probe_imx(spi, idcode); ++ break; ++#endif + default: + debug("SF: Unsupported manufacturer %02X\n", idcode[0]); + flash = NULL; +diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h +index 75f5900..07b1eb5 100644 +--- a/drivers/mtd/spi/spi_flash_internal.h ++++ b/drivers/mtd/spi/spi_flash_internal.h +@@ -44,3 +44,4 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, + struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode); + struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode); + struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode); ++struct spi_flash *spi_flash_probe_imx(struct spi_slave *spi, u8 *idcode); +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index 15e0f7a..5af44d5 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -29,6 +29,8 @@ COBJS-$(CONFIG_ATMEL_SPI) += atmel_spi.o + COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o + COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o + COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o ++COBJS-$(CONFIG_IMX_SPI) += imx_spi.o ++COBJS-$(CONFIG_IMX_SPI_PMIC) += imx_spi_pmic.o + + COBJS := $(COBJS-y) + SRCS := $(COBJS:.o=.c) +diff --git a/drivers/spi/imx_spi.c b/drivers/spi/imx_spi.c +new file mode 100644 +index 0000000..6146da9 +--- /dev/null ++++ b/drivers/spi/imx_spi.c +@@ -0,0 +1,329 @@ ++/* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifdef DEBUG ++ ++/* ----------------------------------------------- ++ * Helper functions to peek into tx and rx buffers ++ * ----------------------------------------------- */ ++static const char * const hex_digit = "0123456789ABCDEF"; ++ ++static char quickhex(int i) ++{ ++ return hex_digit[i]; ++} ++ ++static void memdump(const void *pv, int num) ++{ ++ ++} ++ ++#else /* !DEBUG */ ++ ++#define memdump(p, n) ++ ++#endif /* DEBUG */ ++ ++static inline struct imx_spi_dev_t *to_imx_spi_slave(struct spi_slave *slave) ++{ ++ return container_of(slave, struct imx_spi_dev_t, slave); ++} ++ ++static s32 spi_get_cfg(struct imx_spi_dev_t *dev) ++{ ++ switch (dev->slave.cs) { ++ case 0: ++ /* pmic */ ++ dev->base = CSPI1_BASE_ADDR; ++ dev->freq = 2500000; ++ dev->ss_pol = IMX_SPI_ACTIVE_HIGH; ++ dev->ss = 0; ++ dev->fifo_sz = 64 * 4; ++ dev->us_delay = 0; ++ break; ++ case 1: ++ /* spi_nor */ ++ dev->base = CSPI1_BASE_ADDR; ++ dev->freq = 2500000; ++ dev->ss_pol = IMX_SPI_ACTIVE_LOW; ++ dev->ss = 1; ++ dev->fifo_sz = 64 * 4; ++ dev->us_delay = 0; ++ break; ++ default: ++ printf("Invalid Bus ID! \n"); ++ break; ++ } ++ ++ return 0; ++} ++ ++static s32 spi_reset(struct spi_slave *slave) ++{ ++ u32 clk_src = mxc_get_clock(MXC_CSPI_CLK); ++ s32 pre_div = 0, post_div = 0, i, reg_ctrl, reg_config; ++ struct imx_spi_dev_t *dev = to_imx_spi_slave(slave); ++ struct spi_reg_t *reg = &(dev->reg); ++ ++ if (dev->freq == 0) { ++ printf("Error: desired clock is 0\n"); ++ return 1; ++ } ++ ++ reg_ctrl = readl(dev->base + SPI_CON_REG); ++ /* Reset spi */ ++ writel(0, dev->base + SPI_CON_REG); ++ writel((reg_ctrl | 0x1), dev->base + SPI_CON_REG); ++ ++ /* Control register setup */ ++ if (clk_src > dev->freq) { ++ pre_div = clk_src / dev->freq; ++ if (pre_div > 16) { ++ post_div = pre_div / 16; ++ pre_div = 15; ++ } ++ if (post_div != 0) { ++ for (i = 0; i < 16; i++) { ++ if ((1 << i) >= post_div) ++ break; ++ } ++ if (i == 16) { ++ printf("Error: no divider can meet the freq: %d\n", ++ dev->freq); ++ return -1; ++ } ++ post_div = i; ++ } ++ } ++ ++ debug("pre_div = %d, post_div=%d\n", pre_div, post_div); ++ reg_ctrl = (reg_ctrl & ~(3 << 18)) | dev->ss << 18; ++ reg_ctrl = (reg_ctrl & ~(0xF << 12)) | pre_div << 12; ++ reg_ctrl = (reg_ctrl & ~(0xF << 8)) | post_div << 8; ++ reg_ctrl |= 1 << (dev->ss + 4); /* always set to master mode !!!! */ ++ reg_ctrl &= ~0x1; /* disable spi */ ++ ++ reg_config = readl(dev->base + SPI_CFG_REG); ++ /* configuration register setup */ ++ reg_config = (reg_config & ~(1 << ((dev->ss + 12)))) | ++ (dev->ss_pol << (dev->ss + 12)); ++ reg_config = (reg_config & ~(1 << ((dev->ss + 20)))) | ++ (dev->in_sctl << (dev->ss + 20)); ++ reg_config = (reg_config & ~(1 << ((dev->ss + 16)))) | ++ (dev->in_dctl << (dev->ss + 16)); ++ reg_config = (reg_config & ~(1 << ((dev->ss + 8)))) | ++ (dev->ssctl << (dev->ss + 8)); ++ reg_config = (reg_config & ~(1 << ((dev->ss + 4)))) | ++ (dev->sclkpol << (dev->ss + 4)); ++ reg_config = (reg_config & ~(1 << ((dev->ss + 0)))) | ++ (dev->sclkpha << (dev->ss + 0)); ++ ++ debug("reg_ctrl = 0x%x\n", reg_ctrl); ++ writel(reg_ctrl, dev->base + SPI_CON_REG); ++ debug("reg_config = 0x%x\n", reg_config); ++ writel(reg_config, dev->base + SPI_CFG_REG); ++ ++ /* save config register and control register */ ++ reg->cfg_reg = reg_config; ++ reg->ctrl_reg = reg_ctrl; ++ ++ /* clear interrupt reg */ ++ writel(0, dev->base + SPI_INT_REG); ++ writel(3 << 6, dev->base + SPI_STAT_REG); ++ ++ return 0; ++} ++ ++void spi_init(void) ++{ ++} ++ ++struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, ++ unsigned int max_hz, unsigned int mode) ++{ ++ struct imx_spi_dev_t *imx_spi_slave = NULL; ++ ++ if (!spi_cs_is_valid(bus, cs)) ++ return NULL; ++ ++ imx_spi_slave = (struct imx_spi_dev_t *)malloc(sizeof(struct imx_spi_dev_t)); ++ if (!imx_spi_slave) ++ return NULL; ++ ++ imx_spi_slave->slave.bus = bus; ++ imx_spi_slave->slave.cs = cs; ++ ++ spi_get_cfg(imx_spi_slave); ++ ++ spi_io_init(imx_spi_slave); ++ ++ spi_reset(&(imx_spi_slave->slave)); ++ ++ return &(imx_spi_slave->slave); ++} ++ ++void spi_free_slave(struct spi_slave *slave) ++{ ++ struct imx_spi_dev_t *imx_spi_slave; ++ ++ if (slave) { ++ imx_spi_slave = to_imx_spi_slave(slave); ++ free(imx_spi_slave); ++ } ++} ++ ++int spi_claim_bus(struct spi_slave *slave) ++{ ++ return 0; ++} ++ ++void spi_release_bus(struct spi_slave *slave) ++{ ++ ++} ++ ++/* ++ * SPI transfer: ++ * ++ * See include/spi.h and http://www.altera.com/literature/ds/ds_nios_spi.pdf ++ * for more informations. ++ */ ++int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, ++ void *din, unsigned long flags) ++{ ++ s32 val = SPI_RETRY_TIMES; ++ u32 *p_buf; ++ u32 reg; ++ s32 len = 0, ++ ret_val = 0; ++ s32 burst_bytes = bitlen >> 3; ++ s32 tmp = 0; ++ struct imx_spi_dev_t *dev = to_imx_spi_slave(slave); ++ struct spi_reg_t *spi_reg = &(dev->reg); ++ ++ if (!slave) ++ return -1; ++ ++ if (burst_bytes > (MAX_SPI_BYTES)) { ++ printf("Error: maximum burst size is 0x%x bytes, asking 0x%x\n", ++ MAX_SPI_BYTES, burst_bytes); ++ return -1; ++ } ++ ++ if (flags & SPI_XFER_BEGIN) { ++ spi_cs_activate(slave); ++ ++ if (spi_reg->ctrl_reg == 0) { ++ printf("Error: spi(base=0x%x) has not been initialized yet\n", ++ dev->base); ++ return -1; ++ } ++ spi_reg->ctrl_reg = (spi_reg->ctrl_reg & ~0xFFF00000) | \ ++ ((burst_bytes * 8 - 1) << 20); ++ ++ writel(spi_reg->ctrl_reg | 0x1, dev->base + SPI_CON_REG); ++ writel(spi_reg->cfg_reg, dev->base + SPI_CFG_REG); ++ debug("ctrl_reg=0x%x, cfg_reg=0x%x\n", ++ readl(dev->base + SPI_CON_REG), ++ readl(dev->base + SPI_CFG_REG)); ++ ++ /* move data to the tx fifo */ ++ if (dout) { ++ for (p_buf = (u32 *)dout, len = burst_bytes; len > 0; ++ p_buf++, len -= 4) ++ writel(*p_buf, dev->base + SPI_TX_DATA); ++ } else { ++ for (len = burst_bytes; len > 0; len -= 4) ++ writel(tmp, dev->base + SPI_TX_DATA); ++ } ++ ++ reg = readl(dev->base + SPI_CON_REG); ++ reg |= (1 << 2); /* set xch bit */ ++ debug("control reg = 0x%08x\n", reg); ++ writel(reg, dev->base + SPI_CON_REG); ++ ++ /* poll on the TC bit (transfer complete) */ ++ while ((val-- > 0) && ++ (readl(dev->base + SPI_STAT_REG) & (1 << 7)) == 0) { ++ udelay(100); ++ } ++ ++ /* clear the TC bit */ ++ writel(3 << 6, dev->base + SPI_STAT_REG); ++ if (val <= 0) { ++ printf("Error: re-tried %d times without response. Give up\n", ++ SPI_RETRY_TIMES); ++ ret_val = -1; ++ goto error; ++ } ++ } ++ ++ /* move data in the rx buf */ ++ if (flags & SPI_XFER_END) { ++ if (din) { ++ for (p_buf = (u32 *)din, len = burst_bytes; len > 0; ++ ++p_buf, len -= 4) ++ *p_buf = readl(dev->base + SPI_RX_DATA); ++ } else { ++ for (len = burst_bytes; len > 0; len -= 4) ++ tmp = readl(dev->base + SPI_RX_DATA); ++ } ++ ++ spi_cs_deactivate(slave); ++ } ++ ++ return ret_val; ++ ++error: ++ spi_cs_deactivate(slave); ++ return ret_val; ++} ++ ++int spi_cs_is_valid(unsigned int bus, unsigned int cs) ++{ ++ return 1; ++} ++ ++void spi_cs_activate(struct spi_slave *slave) ++{ ++ struct imx_spi_dev_t *dev = to_imx_spi_slave(slave); ++ ++ spi_io_init(dev); ++} ++ ++void spi_cs_deactivate(struct spi_slave *slave) ++{ ++ struct imx_spi_dev_t *dev = to_imx_spi_slave(slave); ++ ++ writel(0, dev->base + SPI_CON_REG); ++} ++ +diff --git a/drivers/spi/imx_spi_pmic.c b/drivers/spi/imx_spi_pmic.c +new file mode 100644 +index 0000000..bce42c2 +--- /dev/null ++++ b/drivers/spi/imx_spi_pmic.c +@@ -0,0 +1,127 @@ ++/* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include ++ ++static u32 pmic_tx, pmic_rx; ++ ++/*! ++ * To read/write to a PMIC register. For write, it does another read for the ++ * actual register value. ++ * ++ * @param reg register number inside the PMIC ++ * @param val data to be written to the register; don't care for read ++ * @param write 0 for read; 1 for write ++ * ++ * @return the actual data in the PMIC register ++ */ ++u32 pmic_reg(struct spi_slave *slave, u32 reg, u32 val, u32 write) ++{ ++ if (!slave) ++ return 0; ++ ++ if (reg > 63 || write > 1) { ++ printf(" = %d is invalide. Should be less then 63\n", ++ reg); ++ return 0; ++ } ++ pmic_tx = (write << 31) | (reg << 25) | (val & 0x00FFFFFF); ++ printf("reg=0x%x, val=0x%08x\n", reg, pmic_tx); ++ ++ spi_xfer(slave, 4 << 3, (u8 *)&pmic_tx, ++ (u8 *)&pmic_rx, 0); ++ ++ if (write) { ++ pmic_tx &= ~(1 << 31); ++ spi_xfer(slave, 4 << 3, ++ (u8 *)&pmic_tx, (u8 *)&pmic_rx, 0); ++ } ++ ++ return pmic_rx; ++} ++ ++void show_pmic_info(struct spi_slave *slave) ++{ ++ volatile u32 rev_id; ++ ++ if (!slave) ++ return; ++ ++ rev_id = pmic_reg(slave, 7, 0, 0); ++ printf("PMIC ID: 0x%08x [Rev: ", rev_id); ++ switch (rev_id & 0x1F) { ++ case 0x1: ++ printf("1.0"); ++ break; ++ case 0x9: ++ printf("1.1"); ++ break; ++ case 0xA: ++ printf("1.2"); ++ break; ++ case 0x10: ++ printf("2.0"); ++ break; ++ case 0x11: ++ printf("2.1"); ++ break; ++ case 0x18: ++ printf("3.0"); ++ break; ++ case 0x19: ++ printf("3.1"); ++ break; ++ case 0x1A: ++ printf("3.2"); ++ break; ++ case 0x2: ++ printf("3.2A"); ++ break; ++ case 0x1B: ++ printf("3.3"); ++ break; ++ case 0x1D: ++ printf("3.5"); ++ break; ++ default: ++ printf("unknown"); ++ break; ++ } ++ printf("]\n"); ++} ++ ++struct spi_slave *spi_pmic_probe() ++{ ++ return spi_setup_slave(0, CONFIG_IMX_SPI_PMIC_CS, 2500000, 0); ++} ++ ++void spi_pmic_free(struct spi_slave *slave) ++{ ++ if (slave) ++ spi_free_slave(slave); ++} +diff --git a/include/asm-arm/arch-mx51/imx_spi.h b/include/asm-arm/arch-mx51/imx_spi.h +new file mode 100644 +index 0000000..c9d51e9 +--- /dev/null ++++ b/include/asm-arm/arch-mx51/imx_spi.h +@@ -0,0 +1,66 @@ ++/* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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_SPI_H__ ++#define __IMX_SPI_H__ ++ ++#include ++ ++#undef IMX_SPI_DEBUG ++ ++#define IMX_SPI_ACTIVE_HIGH 1 ++#define IMX_SPI_ACTIVE_LOW 0 ++#define SPI_RETRY_TIMES 100 ++ ++#define SPI_RX_DATA 0x0 ++#define SPI_TX_DATA 0x4 ++#define SPI_CON_REG 0x8 ++#define SPI_CFG_REG 0xc ++#define SPI_INT_REG 0x10 ++#define SPI_DMA_REG 0x14 ++#define SPI_STAT_REG 0x18 ++#define SPI_PERIOD_REG 0x1C ++ ++struct spi_reg_t { ++ u32 ctrl_reg; ++ u32 cfg_reg; ++}; ++ ++struct imx_spi_dev_t { ++ struct spi_slave slave; ++ u32 base; /* base address of SPI module the device is connected to */ ++ u32 freq; /* desired clock freq in Hz for this device */ ++ u32 ss_pol; /* ss polarity: 1=active high; 0=active low */ ++ u32 ss; /* slave select */ ++ u32 in_sctl; /* inactive sclk ctl: 1=stay low; 0=stay high */ ++ u32 in_dctl; /* inactive data ctl: 1=stay low; 0=stay high */ ++ u32 ssctl; /* single burst mode vs multiple: 0=single; 1=multi */ ++ u32 sclkpol; /* sclk polarity: active high=0; active low=1 */ ++ u32 sclkpha; /* sclk phase: 0=phase 0; 1=phase1 */ ++ u32 fifo_sz; /* fifo size in bytes for either tx or rx. Don't add them up! */ ++ u32 us_delay; /* us delay in each xfer */ ++ struct spi_reg_t reg; /* pointer to a set of SPI registers */ ++}; ++ ++extern void spi_io_init(struct imx_spi_dev_t *dev); ++ ++#endif /* __IMX_SPI_H__ */ +diff --git a/include/asm-arm/arch-mx51/imx_spi_nor.h b/include/asm-arm/arch-mx51/imx_spi_nor.h +new file mode 100644 +index 0000000..a12247b +--- /dev/null ++++ b/include/asm-arm/arch-mx51/imx_spi_nor.h +@@ -0,0 +1,54 @@ ++/* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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_SPI_NOR_H_ ++#define _IMX_SPI_NOR_H_ ++ ++#define READ 0x03 /* tx: 1 byte cmd + 3 byte addr; rx: variable bytes */ ++#define READ_HS 0x0B /* tx: 1 byte cmd + 3 byte addr + 1 byte dummy; rx: variable bytes */ ++#define RDSR 0x05 /* read status register 1 byte tx cmd + 1 byte rx status */ ++#define RDSR_BUSY (1 << 0) /* 1=write-in-progress (default 0) */ ++#define RDSR_WEL (1 << 1) /* 1=write enable (default 0) */ ++#define RDSR_BP0 (1 << 2) /* block write prot level (default 1) */ ++#define RDSR_BP1 (1 << 3) /* block write prot level (default 1) */ ++#define RDSR_BP2 (1 << 4) /* block write prot level (default 1) */ ++#define RDSR_BP3 (1 << 5) /* block write prot level (default 1) */ ++#define RDSR_AAI (1 << 6) /* 1=AAI prog mode; 0=byte prog (default 0) */ ++#define RDSR_BPL (1 << 7) /* 1=BP3,BP2,BP1,BP0 RO; 0=R/W (default 0) */ ++#define WREN 0x06 /* write enable. 1 byte tx cmd */ ++#define WRDI 0x04 /* write disable. 1 byte tx cmd */ ++#define EWSR 0x50 /* Enable write status. 1 byte tx cmd */ ++#define WRSR 0x01 /* Write status register. 1 byte tx cmd + 1 byte tx value */ ++#define ERASE_4K 0x20 /* sector erase. 1 byte cmd + 3 byte addr */ ++#define ERASE_32K 0x52 /* 32K block erase. 1 byte cmd + 3 byte addr */ ++#define ERASE_64K 0xD8 /* 64K block erase. 1 byte cmd + 3 byte addr */ ++#define ERASE_CHIP 0x60 /* whole chip erase */ ++#define BYTE_PROG 0x02 /* all tx: 1 cmd + 3 addr + 1 data */ ++#define AAI_PROG 0xAD /* all tx: [1 cmd + 3 addr + 2 data] + RDSR */ ++ /* + [1cmd + 2 data] + .. + [WRDI] + [RDSR] */ ++#define JEDEC_ID 0x9F /* read JEDEC ID. tx: 1 byte cmd; rx: 3 byte ID */ ++ ++#define SZ_64K 0x10000 ++#define SZ_32K 0x8000 ++#define SZ_4K 0x1000 ++ ++#endif /* _IMX_SPI_NOR_H_ */ +diff --git a/include/asm-arm/arch-mx51/imx_spi_pmic.h b/include/asm-arm/arch-mx51/imx_spi_pmic.h +new file mode 100644 +index 0000000..1c32a9e +--- /dev/null ++++ b/include/asm-arm/arch-mx51/imx_spi_pmic.h +@@ -0,0 +1,33 @@ ++/* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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_SPI_PMIC_H_ ++#define _IMX_SPI_PMIC_H_ ++ ++#include ++ ++struct spi_slave *spi_pmic_probe(); ++void spi_pmic_free(struct spi_slave *slave); ++u32 pmic_reg(struct spi_slave *slave, ++ u32 reg, u32 val, u32 write); ++ ++#endif /* _IMX_SPI_PMIC_H_ */ +diff --git a/include/asm-arm/arch-mx51/mx51.h b/include/asm-arm/arch-mx51/mx51.h +index 566251b..29120ab 100644 +--- a/include/asm-arm/arch-mx51/mx51.h ++++ b/include/asm-arm/arch-mx51/mx51.h +@@ -404,6 +404,7 @@ MXC_AHB_CLK, + MXC_IPG_CLK, + MXC_IPG_PERCLK, + MXC_UART_CLK, ++MXC_CSPI_CLK, + }; + + extern unsigned int mxc_get_clock(enum mxc_clock clk); +diff --git a/include/configs/imx51.h b/include/configs/imx51.h +index 4ab1acb..1808b67 100644 +--- a/include/configs/imx51.h ++++ b/include/configs/imx51.h +@@ -68,8 +68,25 @@ + #define CONFIG_MX51_UART 1 + #define CONFIG_MX51_UART1 1 + ++/* ++ * SPI Configs ++ * */ ++/* ++#define CONFIG_FSL_SF 1 ++#define CONFIG_CMD_SPI ++#define CONFIG_CMD_SF ++#define CONFIG_SPI_FLASH_IMX ++#define CONFIG_SPI_FLASH_CS 1 ++#define CONFIG_IMX_SPI ++#define CONFIG_IMX_SPI_PMIC ++#define CONFIG_IMX_SPI_PMIC_CS 0 ++ ++#define MAX_SPI_BYTES (64 * 4) ++*/ + +-/* #define CONFIG_CMD_SPI */ ++/* ++ * MMC Configs ++ * */ + + /* + #define CONFIG_FSL_MMC 1 +@@ -190,7 +207,9 @@ + #define CONFIG_SYS_NAND_BASE 0x40000000 + + /* Monitor at beginning of flash */ +-#if defined(CONFIG_FSL_MMC) ++#if defined(CONFIG_FSL_SF) ++ #define CONFIG_FSL_ENV_IN_SF ++#elif defined(CONFIG_FSL_MMC) + #define CONFIG_MMC 1 + #define CONFIG_CMD_MMC + /* +@@ -209,6 +228,10 @@ + #elif defined(CONFIG_FSL_ENV_IN_MMC) + #define CONFIG_ENV_IS_IN_MMC 1 + #define CONFIG_ENV_OFFSET (1024 * 1024) ++#elif defined(CONFIG_FSL_ENV_IN_SF) ++ #define CONFIG_ENV_IS_IN_SPI_FLASH 1 ++ #define CONFIG_ENV_SPI_CS 1 ++ #define CONFIG_ENV_OFFSET (1024 * 1024) + #else + #define CONFIG_ENV_IS_NOWHERE 1 + #endif +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0014-ENGR00108673-Add-i.MX25-core-to-U-Boot.patch +++ uboot-imx-2009.01/debian/patches/0014-ENGR00108673-Add-i.MX25-core-to-U-Boot.patch @@ -0,0 +1,2204 @@ +From d73d39d034c6483971f534ff0b3ba13925fcdf0c Mon Sep 17 00:00:00 2001 +From: Alan Carvalho de Assis +Date: Thu, 5 Mar 2009 09:23:43 -0300 +Subject: [PATCH] ENGR00108673 Add i.MX25 core to U-Boot + +This patch add support on U-Boot to i.MX25 processor. + +Signed-off-by: Alan Carvalho de Assis +--- + cpu/arm926ejs/interrupts.c | 2 +- + cpu/arm926ejs/mx25/Makefile | 45 ++++ + cpu/arm926ejs/mx25/generic.c | 116 ++++++++++ + cpu/arm926ejs/mx25/gpio.c | 113 ++++++++++ + cpu/arm926ejs/mx25/interrupts.c | 121 +++++++++++ + cpu/arm926ejs/mx25/iomux.c | 153 +++++++++++++ + cpu/arm926ejs/mx25/serial.c | 231 ++++++++++++++++++++ + cpu/arm926ejs/start.S | 2 +- + drivers/i2c/mxc_i2c.c | 5 +- + drivers/mtd/nand/Makefile | 1 + + drivers/net/mxc_fec.c | 40 ++++ + include/asm-arm/arch-mx25/gpio.h | 33 +++ + include/asm-arm/arch-mx25/iomux.h | 220 +++++++++++++++++++ + include/asm-arm/arch-mx25/mx25-regs.h | 380 +++++++++++++++++++++++++++++++++ + include/asm-arm/arch-mx25/mx25.h | 44 ++++ + include/asm-arm/arch-mx25/mx25_pins.h | 259 ++++++++++++++++++++++ + include/asm-arm/arch-mx25/mxc_nand.h | 198 +++++++++++++++++ + include/asm-arm/fec.h | 64 +----- + 18 files changed, 1964 insertions(+), 63 deletions(-) + +diff --git a/cpu/arm926ejs/interrupts.c b/cpu/arm926ejs/interrupts.c +index 7a41f0b..7f59e84 100644 +--- a/cpu/arm926ejs/interrupts.c ++++ b/cpu/arm926ejs/interrupts.c +@@ -38,7 +38,7 @@ + #include + #include + +-#ifdef CONFIG_INTEGRATOR ++#if defined(CONFIG_INTEGRATOR) || defined(CONFIG_MX25) + + /* Timer functionality supplied by Integrator board (AP or CP) */ + +diff --git a/cpu/arm926ejs/mx25/Makefile b/cpu/arm926ejs/mx25/Makefile +new file mode 100644 +index 0000000..74add9d +--- /dev/null ++++ b/cpu/arm926ejs/mx25/Makefile +@@ -0,0 +1,45 @@ ++# ++# (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 = interrupts.o serial.o generic.o iomux.o gpio.o ++ ++SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) ++OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) ++ ++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..23b5cce +--- /dev/null ++++ b/cpu/arm926ejs/mx25/generic.c +@@ -0,0 +1,116 @@ ++/* ++ * (C) Copyright 2007 ++ * Sascha Hauer, Pengutronix ++ * ++ * (C) Copyright 2009 Freescale Semiconductor ++ * ++ * 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 ++#include ++#include ++ ++static u32 mx25_decode_pll(u32 reg) ++{ ++ u32 mfi = (reg >> 10) & 0xf; ++ u32 mfn = reg & 0x3ff; ++ u32 mfd = (reg >> 16) & 0x3ff; ++ u32 pd = (reg >> 26) & 0xf; ++ ++ u32 ref_clk = PLL_REF_CLK; ++ ++ mfi = mfi <= 5 ? 5 : mfi; ++ mfd += 1; ++ pd += 1; ++ ++ return ((2 * (ref_clk >> 10) * (mfi * mfd + mfn)) / ++ (mfd * pd)) << 10; ++} ++ ++static u32 mx25_get_mcu_main_clk(void) ++{ ++ u32 cctl = __REG(CCM_CCTL); ++ u32 ret_val = mx25_decode_pll(__REG(CCM_MPCTL)); ++ ++ if (cctl & CRM_CCTL_ARM_SRC) { ++ ret_val *= 3; ++ ret_val /= 4; ++ } ++ ++ return ret_val; ++} ++ ++static u32 mx25_get_ahb_clk(void) ++{ ++ u32 cctl = __REG(CCM_CCTL); ++ u32 ahb_div = ((cctl >> CRM_CCTL_AHB_OFFSET) & 3) + 1; ++ ++ return mx25_get_mcu_main_clk()/ahb_div; ++} ++ ++unsigned int mx25_get_ipg_clk(void) ++{ ++ return mx25_get_ahb_clk()/2; ++} ++ ++void mx25_dump_clocks(void) ++{ ++ u32 cpufreq = mx25_get_mcu_main_clk(); ++ printf("mx25 cpu clock: %dMHz\n", cpufreq / 1000000); ++ printf("ipg clock : %dHz\n", mx25_get_ipg_clk()); ++} ++ ++unsigned int mxc_get_clock(enum mxc_clock clk) ++{ ++ switch (clk) { ++ case MXC_ARM_CLK: ++ return mx25_get_mcu_main_clk(); ++ case MXC_AHB_CLK: ++ return mx25_get_ahb_clk(); ++ break; ++ case MXC_IPG_PERCLK: ++ case MXC_IPG_CLK: ++ return mx25_get_ipg_clk(); ++ case MXC_UART_CLK: ++ break; ++ } ++ return -1; ++} ++ ++#if defined(CONFIG_DISPLAY_CPUINFO) ++int print_cpuinfo(void) ++{ ++ printf("CPU: Freescale i.MX25 at %d MHz\n", ++ mx25_get_mcu_main_clk() / 1000000); ++ return 0; ++} ++/* ++ * Initializes on-chip ethernet controllers. ++ * to override, implement board_eth_init() ++ */ ++int cpu_eth_init(bd_t *bis) ++{ ++ int rc = -ENODEV; ++#if defined(CONFIG_MXC_FEC) ++ rc = mxc_fec_initialize(bis); ++#endif ++ return rc; ++} ++#endif +diff --git a/cpu/arm926ejs/mx25/gpio.c b/cpu/arm926ejs/mx25/gpio.c +new file mode 100644 +index 0000000..560b3a4 +--- /dev/null ++++ b/cpu/arm926ejs/mx25/gpio.c +@@ -0,0 +1,113 @@ ++/* ++ * (c) Copyright 2009 Freescale Semiconductors ++ * ++ * 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 ++#include ++#include ++#include ++ ++enum gpio_reg { ++ DR = 0x00, ++ GDIR = 0x04, ++ PSR = 0x08, ++ ICR1 = 0x0C, ++ ICR2 = 0x10, ++ IMR = 0x14, ++ ISR = 0x18, ++}; ++ ++struct gpio_port_addr { ++ int num; ++ int base; ++}; ++ ++struct gpio_port_addr gpio_port[4] = { ++ {0, GPIO1_BASE}, ++ {1, GPIO2_BASE}, ++ {2, GPIO3_BASE}, ++ {3, GPIO4_BASE} ++ }; ++ ++/* ++ * Set a GPIO pin's direction ++ * @param port pointer to a gpio_port ++ * @param index gpio pin index value (0~31) ++ * @param is_input 0 for output; non-zero for input ++ */ ++static void _set_gpio_direction(u32 port, u32 index, int is_input) ++{ ++ u32 reg = gpio_port[port].base + GDIR; ++ u32 l; ++ ++ l = __REG(reg); ++ if (is_input) ++ l &= ~(1 << index); ++ else ++ l |= 1 << index; ++ __REG(reg) = l; ++} ++ ++ ++/*! ++ * Exported function to set a GPIO pin's direction ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param is_input 1 (or non-zero) for input; 0 for output ++ */ ++void mxc_set_gpio_direction(iomux_pin_name_t pin, int is_input) ++{ ++ u32 port; ++ u32 gpio = IOMUX_TO_GPIO(pin); ++ ++ port = GPIO_TO_PORT(gpio); ++ _set_gpio_direction(port, GPIO_TO_INDEX(gpio), is_input); ++} ++ ++/* ++ * Set a GPIO pin's data output ++ * @param port number of gpio port ++ * @param index gpio pin index value (0~31) ++ * @param data value to be set (only 0 or 1 is valid) ++ */ ++static void _set_gpio_dataout(u32 port, u32 index, u32 data) ++{ ++ u32 reg = gpio_port[port].base + DR; ++ u32 l = 0; ++ ++ l = (__REG(reg) & (~(1 << index))) | (data << index); ++ __REG(reg) = l; ++} ++ ++/*! ++ * Exported function to set a GPIO pin's data output ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param data value to be set (only 0 or 1 is valid) ++ */ ++ ++void mxc_set_gpio_dataout(iomux_pin_name_t pin, u32 data) ++{ ++ u32 port; ++ u32 gpio = IOMUX_TO_GPIO(pin); ++ ++ port = GPIO_TO_PORT(gpio); ++ _set_gpio_dataout(port, GPIO_TO_INDEX(gpio), (data == 0) ? 0 : 1); ++} ++ +diff --git a/cpu/arm926ejs/mx25/interrupts.c b/cpu/arm926ejs/mx25/interrupts.c +new file mode 100644 +index 0000000..cbd5d09 +--- /dev/null ++++ b/cpu/arm926ejs/mx25/interrupts.c +@@ -0,0 +1,121 @@ ++/* ++ * (C) Copyright 2007 ++ * Sascha Hauer, Pengutronix ++ * ++ * (C) Copyright 2009 Freescale Semiconductor ++ * ++ * 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 ++#include ++ ++#define TIMER_BASE 0x53f90000 /* General purpose timer 1 */ ++ ++/* General purpose timers registers */ ++#define GPTCR __REG(TIMER_BASE) /* Control register */ ++#define GPTPR __REG(TIMER_BASE + 0x4) /* Prescaler register */ ++#define GPTSR __REG(TIMER_BASE + 0x8) /* Status register */ ++#define GPTCNT __REG(TIMER_BASE + 0x24) /* Counter register */ ++ ++/* General purpose timers bitfields */ ++#define GPTCR_SWR (1<<15) /* Software reset */ ++#define GPTCR_FRR (1<<9) /* Freerun / restart */ ++#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ ++#define GPTCR_TEN (1) /* Timer enable */ ++ ++static ulong timestamp; ++static ulong lastinc; ++ ++/* nothing really to do with interrupts, just starts up a counter. */ ++int interrupt_init(void) ++{ ++ int i; ++ ++ /* setup GP Timer 1 */ ++ GPTCR = GPTCR_SWR; ++ for (i = 0; i < 100; i++) ++ GPTCR = 0; /* We have no udelay by now */ ++ GPTPR = 0; /* 32Khz */ ++ GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; /* Freerun Mode, PERCLK1 in */ ++ ++ return 0; ++} ++ ++void reset_timer_masked(void) ++{ ++ /* reset time */ ++ lastinc = GPTCNT; /* capture current incrementer value time */ ++ timestamp = 0; /* start "advancing" time stamp from 0 */ ++} ++ ++void reset_timer(void) ++{ ++ reset_timer_masked(); ++} ++ ++ulong get_timer_masked(void) ++{ ++ ulong now = GPTCNT; /* 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(ulong base) ++{ ++ return get_timer_masked() - base; ++} ++ ++void set_timer(ulong t) ++{ ++} ++ ++/* delay x useconds AND perserve advance timstamp value */ ++void udelay(unsigned long usec) ++{ ++ ulong tmo, tmp; ++ ++ if (usec >= 1000) { /* if "big" number, spread normalize to secs */ ++ tmo = usec / 1000; /* normalize usec to ticks per sec */ ++ tmo *= CONFIG_SYS_HZ; /* find number of "ticks" to wait */ ++ tmo /= 1000; /* finish normalize. */ ++ } else { /* don't kill prior to HZ multiply */ ++ tmo = usec * CONFIG_SYS_HZ; ++ tmo /= (1000*1000); ++ } ++ ++ tmp = get_timer(0); /* get current timestamp */ ++ if ((tmo + tmp + 1) < tmp) /* if overflow time stamp */ ++ reset_timer_masked(); /* reset "advancing" timestamp to 0 */ ++ else ++ tmo += tmp; /* else, set stamp wake up time */ ++ while (get_timer_masked() < tmo)/* loop till event */ ++ /*NOP*/; ++} ++ ++void reset_cpu(ulong addr) ++{ ++ __REG16(WDOG_BASE) = 4; ++} +diff --git a/cpu/arm926ejs/mx25/iomux.c b/cpu/arm926ejs/mx25/iomux.c +new file mode 100644 +index 0000000..c0805d3 +--- /dev/null ++++ b/cpu/arm926ejs/mx25/iomux.c +@@ -0,0 +1,153 @@ ++/* ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @defgroup GPIO_MX25 Board GPIO and Muxing Setup ++ * @ingroup MSL_MX25 ++ */ ++/*! ++ * @file mach-mx25/iomux.c ++ * ++ * @brief I/O Muxing control functions ++ * ++ * @ingroup GPIO_MX25 ++ */ ++ ++#include ++#include ++#include ++#include ++ ++/*! ++ * IOMUX register (base) addresses ++ */ ++enum iomux_reg_addr { ++ IOMUXGPR = IOMUXC_BASE, ++ /*!< General purpose */ ++ IOMUXSW_MUX_CTL = IOMUXC_BASE + 0x008, ++ /*!< MUX control */ ++ IOMUXSW_MUX_END = IOMUXC_BASE + 0x228, ++ /*!< last MUX control register */ ++ IOMUXSW_PAD_CTL = IOMUXC_BASE + 0x22C, ++ /*!< Pad control */ ++ IOMUXSW_PAD_END = IOMUXC_BASE + 0x414, ++ /*!< last Pad control register */ ++ IOMUXSW_INPUT_CTL = IOMUXC_BASE + 0x460, ++ /*!< input select register */ ++ IOMUXSW_INPUT_END = IOMUXC_BASE + 0x580, ++ /*!< last input select register */ ++}; ++ ++#define MUX_PIN_NUM_MAX \ ++ (((IOMUXSW_MUX_END - IOMUXSW_MUX_CTL) >> 2) + 1) ++#define MUX_INPUT_NUM_MUX \ ++ (((IOMUXSW_INPUT_END - IOMUXSW_INPUT_CTL) >> 2) + 1) ++ ++#define PIN_TO_IOMUX_INDEX(pin) (PIN_TO_IOMUX_MUX(pin) >> 2) ++ ++#define MUX_USED 0x80 ++ ++/*! ++ * This function is used to configure a pin through the IOMUX module. ++ * FIXED ME: for backward compatible. Will be static function! ++ * @param pin a pin number as defined in \b #iomux_pin_name_t ++ * @param cfg an output function as defined in \b #iomux_pin_cfg_t ++ * ++ * @return 0 if successful; Non-zero otherwise ++ */ ++static int iomux_config_mux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) ++{ ++ u32 mux_reg = PIN_TO_IOMUX_MUX(pin); ++ ++ if (mux_reg != NON_MUX_I) { ++ mux_reg += IOMUXGPR; ++ __REG(mux_reg) = cfg; ++ } ++ ++ return 0; ++} ++ ++/*! ++ * Request ownership for an IO pin. This function has to be the first one ++ * being called before that pin is used. The caller has to check the ++ * return value to make sure it returns 0. ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param cfg an input function as defined in \b #iomux_pin_cfg_t ++ * ++ * @return 0 if successful; Non-zero otherwise ++ */ ++int mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) ++{ ++ int ret = iomux_config_mux(pin, cfg); ++ return ret; ++} ++ ++/*! ++ * Release ownership for an IO pin ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param cfg an input function as defined in \b #iomux_pin_cfg_t ++ */ ++void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) ++{ ++} ++ ++/*! ++ * This function configures the pad value for a IOMUX pin. ++ * ++ * @param pin a pin number as defined in \b #iomux_pin_name_t ++ * @param config the ORed value of elements defined in \b #iomux_pad_config_t ++ */ ++void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config) ++{ ++ u32 pad_reg = IOMUXGPR + PIN_TO_IOMUX_PAD(pin); ++ ++ __REG(pad_reg) = config; ++} ++ ++/*! ++ * This function enables/disables the general purpose function for a particular ++ * signal. ++ * ++ * @param gp one signal as defined in \b #iomux_gp_func_t ++ * @param en \b #true to enable; \b #false to disable ++ */ ++void mxc_iomux_set_gpr(iomux_gp_func_t gp, int en) ++{ ++ u32 l; ++ ++ l = __REG(IOMUXGPR); ++ if (en) ++ l |= gp; ++ else ++ l &= ~gp; ++ ++ __REG(IOMUXGPR) = l; ++} ++ ++/*! ++ * This function configures input path. ++ * ++ * @param input index of input select register as defined in \b ++ * #iomux_input_select_t ++ * @param config the binary value of elements defined in \b ++ * #iomux_input_config_t ++ */ ++void mxc_iomux_set_input(iomux_input_select_t input, u32 config) ++{ ++ u32 reg = IOMUXSW_INPUT_CTL + (input << 2); ++ ++ __REG(reg) = config; ++} ++ +diff --git a/cpu/arm926ejs/mx25/serial.c b/cpu/arm926ejs/mx25/serial.c +new file mode 100644 +index 0000000..17a08c3 +--- /dev/null ++++ b/cpu/arm926ejs/mx25/serial.c +@@ -0,0 +1,231 @@ ++/* ++ * (c) 2007 Sascha Hauer ++ * ++ * (C) Copyright 2009 Freescale Semiconductor ++ * ++ * 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 ++ ++#if defined CONFIG_MX25_UART ++ ++#include ++ ++#define __REG(x) (*((volatile u32 *)(x))) ++ ++#ifdef CONFIG_MX25_UART1 ++#define UART_PHYS 0x43f90000 ++#else ++#error "define CONFIG_MX25_UARTx to use the mx25 UART driver" ++#endif ++ ++/* Register definitions */ ++#define URXD 0x0 /* Receiver Register */ ++#define UTXD 0x40 /* Transmitter Register */ ++#define UCR1 0x80 /* Control Register 1 */ ++#define UCR2 0x84 /* Control Register 2 */ ++#define UCR3 0x88 /* Control Register 3 */ ++#define UCR4 0x8c /* Control Register 4 */ ++#define UFCR 0x90 /* FIFO Control Register */ ++#define USR1 0x94 /* Status Register 1 */ ++#define USR2 0x98 /* Status Register 2 */ ++#define UESC 0x9c /* Escape Character Register */ ++#define UTIM 0xa0 /* Escape Timer Register */ ++#define UBIR 0xa4 /* BRM Incremental Register */ ++#define UBMR 0xa8 /* BRM Modulator Register */ ++#define UBRC 0xac /* Baud Rate Count Register */ ++#define UTS 0xb4 /* UART Test Register (mx25) */ ++ ++/* UART Control Register Bit Fields.*/ ++#define URXD_CHARRDY (1<<15) ++#define URXD_ERR (1<<14) ++#define URXD_OVRRUN (1<<13) ++#define URXD_FRMERR (1<<12) ++#define URXD_BRK (1<<11) ++#define URXD_PRERR (1<<10) ++#define URXD_RX_DATA (0xFF) ++#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ ++#define UCR1_ADBR (1<<14) /* Auto detect baud rate */ ++#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ ++#define UCR1_IDEN (1<<12) /* Idle condition interrupt */ ++#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ ++#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ ++#define UCR1_IREN (1<<7) /* Infrared interface enable */ ++#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ ++#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ ++#define UCR1_SNDBRK (1<<4) /* Send break */ ++#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ ++#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ ++#define UCR1_DOZE (1<<1) /* Doze */ ++#define UCR1_UARTEN (1<<0) /* UART enabled */ ++#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ ++#define UCR2_IRTS (1<<14) /* Ignore RTS pin */ ++#define UCR2_CTSC (1<<13) /* CTS pin control */ ++#define UCR2_CTS (1<<12) /* Clear to send */ ++#define UCR2_ESCEN (1<<11) /* Escape enable */ ++#define UCR2_PREN (1<<8) /* Parity enable */ ++#define UCR2_PROE (1<<7) /* Parity odd/even */ ++#define UCR2_STPB (1<<6) /* Stop */ ++#define UCR2_WS (1<<5) /* Word size */ ++#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ ++#define UCR2_TXEN (1<<2) /* Transmitter enabled */ ++#define UCR2_RXEN (1<<1) /* Receiver enabled */ ++#define UCR2_SRST (1<<0) /* SW reset */ ++#define UCR3_DTREN (1<<13) /* DTR interrupt enable */ ++#define UCR3_PARERREN (1<<12) /* Parity enable */ ++#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */ ++#define UCR3_DSR (1<<10) /* Data set ready */ ++#define UCR3_DCD (1<<9) /* Data carrier detect */ ++#define UCR3_RI (1<<8) /* Ring indicator */ ++#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */ ++#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ ++#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ ++#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ ++#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */ ++#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */ ++#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ ++#define UCR3_BPEN (1<<0) /* Preset registers enable */ ++#define UCR4_CTSTL_32 (32<<10)/* CTS trigger level (32 chars) */ ++#define UCR4_INVR (1<<9) /* Inverted infrared reception */ ++#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ ++#define UCR4_WKEN (1<<7) /* Wake interrupt enable */ ++#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */ ++#define UCR4_IRSC (1<<5) /* IR special case */ ++#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */ ++#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */ ++#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ ++#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ ++#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ ++#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ ++#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ ++#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ ++#define USR1_RTSS (1<<14) /* RTS pin status */ ++#define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */ ++#define USR1_RTSD (1<<12) /* RTS delta */ ++#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */ ++#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */ ++#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */ ++#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */ ++#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */ ++#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */ ++#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */ ++#define USR2_ADET (1<<15) /* Auto baud rate detect complete */ ++#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */ ++#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */ ++#define USR2_IDLE (1<<12) /* Idle condition */ ++#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */ ++#define USR2_WAKE (1<<7) /* Wake */ ++#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */ ++#define USR2_TXDC (1<<3) /* Transmitter complete */ ++#define USR2_BRCD (1<<2) /* Break condition */ ++#define USR2_ORE (1<<1) /* Overrun error */ ++#define USR2_RDR (1<<0) /* Recv data ready */ ++#define UTS_FRCPERR (1<<13) /* Force parity error */ ++#define UTS_LOOP (1<<12) /* Loop tx and rx */ ++#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ ++#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ ++#define UTS_TXFULL (1<<4) /* TxFIFO full */ ++#define UTS_RXFULL (1<<3) /* RxFIFO full */ ++#define UTS_SOFTRST (1<<0) /* Software reset */ ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++void serial_setbrg(void) ++{ ++ u32 clk = mx25_get_ipg_clk(); ++ ++ if (!gd->baudrate) ++ gd->baudrate = CONFIG_BAUDRATE; ++ ++ __REG(UART_PHYS + UFCR) = 4 << 7; /* divide input clock by 2 */ ++ __REG(UART_PHYS + UBIR) = 0xf; ++ __REG(UART_PHYS + UBMR) = clk / (2 * gd->baudrate); ++ ++} ++ ++int serial_getc(void) ++{ ++ while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) ++ ; ++ ++ /* mask out status from upper word */ ++ return (__REG(UART_PHYS + URXD) & URXD_RX_DATA) ++ ; ++} ++ ++void serial_putc(const char c) ++{ ++ __REG(UART_PHYS + UTXD) = c; ++ ++ /* wait for transmitter to be ready */ ++ while (!(__REG(UART_PHYS + UTS) & UTS_TXEMPTY)) ++ ; ++ ++ /* If \n, also do \r */ ++ if (c == '\n') ++ serial_putc('\r'); ++} ++ ++/* ++ * Test whether a character is in the RX buffer ++ */ ++int serial_tstc(void) ++{ ++ /* If receive fifo is empty, return false */ ++ if (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) ++ return 0; ++ return 1; ++} ++ ++void serial_puts(const char *s) ++{ ++ while (*s) ++ serial_putc(*s++); ++} ++ ++/* ++ * Initialise the serial port with the given baudrate. The settings ++ * are always 8 data bits, no parity, 1 stop bit, no start bits. ++ * ++ */ ++int serial_init(void) ++{ ++ __REG(UART_PHYS + UCR1) = 0x0; ++ __REG(UART_PHYS + UCR2) = 0x0; ++ ++ while (!(__REG(UART_PHYS + UCR2) & UCR2_SRST)) ++ ; ++ ++ __REG(UART_PHYS + UCR3) = 0x0704; ++ __REG(UART_PHYS + UCR4) = 0x8000; ++ __REG(UART_PHYS + UESC) = 0x002b; ++ __REG(UART_PHYS + UTIM) = 0x0; ++ ++ __REG(UART_PHYS + UTS) = 0x0; ++ ++ serial_setbrg(); ++ ++ __REG(UART_PHYS + UCR2) = UCR2_WS | UCR2_IRTS | UCR2_RXEN | ++ UCR2_TXEN | UCR2_SRST; ++ ++ __REG(UART_PHYS + UCR1) = UCR1_UARTEN; ++ ++ return 0; ++} ++ ++ ++#endif /* CONFIG_MX25 */ +diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S +index ed4932a..44a4c45 100644 +--- a/cpu/arm926ejs/start.S ++++ b/cpu/arm926ejs/start.S +@@ -125,7 +125,7 @@ FIQ_STACK_START: + /* + * the actual reset code + */ +- ++.globl reset + reset: + /* + * set the cpu to SVC32 mode +diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c +index 2b4fcb2..9009e44 100644 +--- a/drivers/i2c/mxc_i2c.c ++++ b/drivers/i2c/mxc_i2c.c +@@ -28,7 +28,10 @@ + + #if defined(CONFIG_HARD_I2C) + +-#ifdef CONFIG_MX31 ++#ifdef CONFIG_MX25 ++#include ++#include ++#elif defined(CONFIG_MX31) + #include + #include + #elif defined(CONFIG_MX35) +diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile +index eaf61f3..75fee7e 100644 +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -38,6 +38,7 @@ endif + COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o + COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o + COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o ++COBJS-$(CONFIG_MX25) += mxc_nand.o + COBJS-$(CONFIG_MX31_NAND) += mx31_nand.o + COBJS-$(CONFIG_MX35) += mxc_nand.o + COBJS-$(CONFIG_MX51) += mxc_nand.o +diff --git a/drivers/net/mxc_fec.c b/drivers/net/mxc_fec.c +index 676f89f..218c432 100644 +--- a/drivers/net/mxc_fec.c ++++ b/drivers/net/mxc_fec.c +@@ -88,6 +88,44 @@ + + DECLARE_GLOBAL_DATA_PTR; + ++#ifdef CONFIG_MX25 ++/* ++ * * i.MX25 allows RMII mode to be configured via a gasket ++ * */ ++#define FEC_MIIGSK_CFGR_FRCONT (1 << 6) ++#define FEC_MIIGSK_CFGR_LBMODE (1 << 4) ++#define FEC_MIIGSK_CFGR_EMODE (1 << 3) ++#define FEC_MIIGSK_CFGR_IF_MODE_MASK (3 << 0) ++#define FEC_MIIGSK_CFGR_IF_MODE_MII (0 << 0) ++#define FEC_MIIGSK_CFGR_IF_MODE_RMII (1 << 0) ++ ++#define FEC_MIIGSK_ENR_READY (1 << 2) ++#define FEC_MIIGSK_ENR_EN (1 << 1) ++ ++static inline void fec_localhw_setup(volatile fec_t *fecp) ++{ ++ /* ++ * Set up the MII gasket for RMII mode ++ */ ++ printf("FEC: enable RMII gasket\n"); ++ ++ /* disable the gasket and wait */ ++ fecp->fec_miigsk_enr = 0; ++ while (fecp->fec_miigsk_enr & FEC_MIIGSK_ENR_READY) ++ udelay(1); ++ ++ /* configure the gasket for RMII, 50 MHz, no loopback, no echo */ ++ fecp->fec_miigsk_cfgr = FEC_MIIGSK_CFGR_IF_MODE_RMII; ++ ++ /* re-enable the gasket */ ++ fecp->fec_miigsk_enr = FEC_MIIGSK_ENR_EN; ++} ++#else ++static inline void fec_localhw_setup(struct fec_t *fecp) ++{ ++} ++#endif ++ + #if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) + + struct fec_info_s fec_info[] = { +@@ -574,6 +612,8 @@ int fec_init(struct eth_device *dev, bd_t *bd) + + fec_reset(dev); + ++ fec_localhw_setup(fecp); ++ + #if defined (CONFIG_CMD_MII) || defined (CONFIG_MII) || \ + defined (CONFIG_DISCOVER_PHY) + +diff --git a/include/asm-arm/arch-mx25/gpio.h b/include/asm-arm/arch-mx25/gpio.h +new file mode 100644 +index 0000000..69eb987 +--- /dev/null ++++ b/include/asm-arm/arch-mx25/gpio.h +@@ -0,0 +1,33 @@ ++/* ++ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++#ifndef __MACH_MX25_GPIO_H__ ++#define __MACH_MX25_GPIO_H__ ++ ++#include ++ ++static void _set_gpio_direction(u32 port, u32 index, int is_input); ++ ++void mxc_set_gpio_direction(iomux_pin_name_t pin, int is_input); ++ ++static void _set_gpio_dataout(u32 port, u32 index, u32 data); ++ ++void mxc_set_gpio_dataout(iomux_pin_name_t pin, u32 data); ++ ++/*! ++ * @file mach-mx25/gpio.h ++ * ++ * @brief Simple GPIO definitions and functions ++ * ++ * @ingroup GPIO_MX25 ++ */ ++#endif +diff --git a/include/asm-arm/arch-mx25/iomux.h b/include/asm-arm/arch-mx25/iomux.h +new file mode 100644 +index 0000000..0719c79 +--- /dev/null ++++ b/include/asm-arm/arch-mx25/iomux.h +@@ -0,0 +1,220 @@ ++/* ++ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++#ifndef __MACH_MX25_IOMUX_H__ ++#define __MACH_MX25_IOMUX_H__ ++ ++#include ++ ++/*! ++ * @file mach-mx25/iomux.h ++ * ++ * @brief I/O Muxing control definitions and functions ++ * ++ * @ingroup GPIO_MX25 ++ */ ++ ++/*! ++ * IOMUX functions ++ * SW_MUX_CTL ++ */ ++typedef enum iomux_pin_config { ++ MUX_CONFIG_FUNC = 0, /*!< used as function */ ++ MUX_CONFIG_ALT1, /*!< used as alternate function 1 */ ++ MUX_CONFIG_ALT2, /*!< used as alternate function 2 */ ++ MUX_CONFIG_ALT3, /*!< used as alternate function 3 */ ++ MUX_CONFIG_ALT4, /*!< used as alternate function 4 */ ++ MUX_CONFIG_ALT5, /*!< used as alternate function 5 */ ++ MUX_CONFIG_ALT6, /*!< used as alternate function 6 */ ++ MUX_CONFIG_ALT7, /*!< used as alternate function 7 */ ++ MUX_CONFIG_SION = 0x1 << 4, /*!< used as LOOPBACK:MUX SION bit */ ++ MUX_CONFIG_GPIO = MUX_CONFIG_ALT5, /*!< used as GPIO */ ++} iomux_pin_cfg_t; ++ ++/*! ++ * IOMUX pad functions ++ * SW_PAD_CTL ++ */ ++typedef enum iomux_pad_config { ++ PAD_CTL_DRV_3_3V = 0x0 << 13, ++ PAD_CTL_DRV_1_8V = 0x1 << 13, ++ PAD_CTL_HYS_CMOS = 0x0 << 8, ++ PAD_CTL_HYS_SCHMITZ = 0x1 << 8, ++ PAD_CTL_PKE_NONE = 0x0 << 7, ++ PAD_CTL_PKE_ENABLE = 0x1 << 7, ++ PAD_CTL_PUE_KEEPER = 0x0 << 6, ++ PAD_CTL_PUE_PUD = 0x1 << 6, ++ PAD_CTL_100K_PD = 0x0 << 4, ++ PAD_CTL_47K_PU = 0x1 << 4, ++ PAD_CTL_100K_PU = 0x2 << 4, ++ PAD_CTL_22K_PU = 0x3 << 4, ++ PAD_CTL_ODE_CMOS = 0x0 << 3, ++ PAD_CTL_ODE_OpenDrain = 0x1 << 3, ++ PAD_CTL_DRV_NORMAL = 0x0 << 1, ++ PAD_CTL_DRV_HIGH = 0x1 << 1, ++ PAD_CTL_DRV_MAX = 0x2 << 1, ++ PAD_CTL_SRE_SLOW = 0x0 << 0, ++ PAD_CTL_SRE_FAST = 0x1 << 0 ++} iomux_pad_config_t; ++ ++/*! ++ * IOMUX general purpose functions ++ * IOMUXC_GPR1 ++ */ ++typedef enum iomux_gp_func { ++ MUX_SDCTL_CSD0_SEL = 0x1 << 0, ++ MUX_SDCTL_CSD1_SEL = 0x1 << 1, ++} iomux_gp_func_t; ++ ++/*! ++ * IOMUX SELECT_INPUT register index ++ * Base register is IOMUXSW_INPUT_CTL in iomux.c ++ */ ++typedef enum iomux_input_select { ++ MUX_IN_AUDMUX_P4_INPUT_DA_AMX = 0, ++ MUX_IN_AUDMUX_P4_INPUT_DB_AMX, ++ MUX_IN_AUDMUX_P4_INPUT_RXCLK_AMX, ++ MUX_IN_AUDMUX_P4_INPUT_RXFS_AMX, ++ MUX_IN_AUDMUX_P4_INPUT_TXCLK_AMX, ++ MUX_IN_AUDMUX_P4_INPUT_TXFS_AMX, ++ MUX_IN_AUDMUX_P7_INPUT_DA_AMX, ++ MUX_IN_AUDMUX_P7_INPUT_TXFS_AMX, ++ MUX_IN_CAN1_IPP_IND_CANRX, ++ MUX_IN_CAN2_IPP_IND_CANRX, ++ MUX_IN_CSI_IPP_CSI_D_0, ++ MUX_IN_CSI_IPP_CSI_D_1, ++ MUX_IN_CSPI1_IPP_IND_SS3_B, ++ MUX_IN_CSPI2_IPP_CSPI_CLK_IN, ++ MUX_IN_CSPI2_IPP_IND_DATAREADY_B, ++ MUX_IN_CSPI2_IPP_IND_MISO, ++ MUX_IN_CSPI2_IPP_IND_MOSI, ++ MUX_IN_CSPI2_IPP_IND_SS0_B, ++ MUX_IN_CSPI2_IPP_IND_SS1_B, ++ MUX_IN_CSPI3_IPP_CSPI_CLK_IN, ++ MUX_IN_CSPI3_IPP_IND_DATAREADY_B, ++ MUX_IN_CSPI3_IPP_IND_MISO, ++ MUX_IN_CSPI3_IPP_IND_MOSI, ++ MUX_IN_CSPI3_IPP_IND_SS0_B, ++ MUX_IN_CSPI3_IPP_IND_SS1_B, ++ MUX_IN_CSPI3_IPP_IND_SS2_B, ++ MUX_IN_CSPI3_IPP_IND_SS3_B, ++ MUX_IN_ESDHC1_IPP_DAT4_IN, ++ MUX_IN_ESDHC1_IPP_DAT5_IN, ++ MUX_IN_ESDHC1_IPP_DAT6_IN, ++ MUX_IN_ESDHC1_IPP_DAT7_IN, ++ MUX_IN_ESDHC2_IPP_CARD_CLK_IN, ++ MUX_IN_ESDHC2_IPP_CMD_IN, ++ MUX_IN_ESDHC2_IPP_DAT0_IN, ++ MUX_IN_ESDHC2_IPP_DAT1_IN, ++ MUX_IN_ESDHC2_IPP_DAT2_IN, ++ MUX_IN_ESDHC2_IPP_DAT3_IN, ++ MUX_IN_ESDHC2_IPP_DAT4_IN, ++ MUX_IN_ESDHC2_IPP_DAT5_IN, ++ MUX_IN_ESDHC2_IPP_DAT6_IN, ++ MUX_IN_ESDHC2_IPP_DAT7_IN, ++ MUX_IN_FEC_FEC_COL, ++ MUX_IN_FEC_FEC_CRS, ++ MUX_IN_FEC_FEC_RDATA_2, ++ MUX_IN_FEC_FEC_RDATA_3, ++ MUX_IN_FEC_FEC_RX_CLK, ++ MUX_IN_FEC_FEC_RX_ER, ++ MUX_IN_I2C2_IPP_SCL_IN, ++ MUX_IN_I2C2_IPP_SDA_IN, ++ MUX_IN_I2C3_IPP_SCL_IN, ++ MUX_IN_I2C3_IPP_SDA_IN, ++ MUX_IN_KPP_IPP_IND_COL_4, ++ MUX_IN_KPP_IPP_IND_COL_5, ++ MUX_IN_KPP_IPP_IND_COL_6, ++ MUX_IN_KPP_IPP_IND_COL_7, ++ MUX_IN_KPP_IPP_IND_ROW_4, ++ MUX_IN_KPP_IPP_IND_ROW_5, ++ MUX_IN_KPP_IPP_IND_ROW_6, ++ MUX_IN_KPP_IPP_IND_ROW_7, ++ MUX_IN_SIM1_PIN_SIM_RCVD1_IN, ++ MUX_IN_SIM1_PIN_SIM_SIMPD1, ++ MUX_IN_SIM1_SIM_RCVD1_IO, ++ MUX_IN_SIM2_PIN_SIM_RCVD1_IN, ++ MUX_IN_SIM2_PIN_SIM_SIMPD1, ++ MUX_IN_SIM2_SIM_RCVD1_IO, ++ MUX_IN_UART3_IPP_UART_RTS_B, ++ MUX_IN_UART3_IPP_UART_RXD_MUX, ++ MUX_IN_UART4_IPP_UART_RTS_B, ++ MUX_IN_UART4_IPP_UART_RXD_MUX, ++ MUX_IN_UART5_IPP_UART_RTS_B, ++ MUX_IN_UART5_IPP_UART_RXD_MUX, ++ MUX_IN_USB_TOP_IPP_IND_OTG_USB_OC, ++ MUX_IN_USB_TOP_IPP_IND_UH2_USB_OC, ++} iomux_input_select_t; ++ ++/*! ++ * IOMUX input functions ++ * SW_SELECT_INPUT bits 2-0 ++ */ ++typedef enum iomux_input_config { ++ INPUT_CTL_PATH0 = 0x0, ++ INPUT_CTL_PATH1, ++ INPUT_CTL_PATH2, ++ INPUT_CTL_PATH3, ++ INPUT_CTL_PATH4, ++ INPUT_CTL_PATH5, ++ INPUT_CTL_PATH6, ++ INPUT_CTL_PATH7, ++} iomux_input_cfg_t; ++ ++/*! ++ * Request ownership for an IO pin. This function has to be the first one ++ * being called before that pin is used. The caller has to check the ++ * return value to make sure it returns 0. ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param cfg an input function as defined in \b #iomux_pin_cfg_t ++ * ++ * @return 0 if successful; Non-zero otherwise ++ */ ++int mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg); ++ ++/*! ++ * Release ownership for an IO pin ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param cfg an input function as defined in \b #iomux_pin_cfg_t ++ */ ++void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg); ++ ++/*! ++ * This function enables/disables the general purpose function for a particular ++ * signal. ++ * ++ * @param gp one signal as defined in \b #iomux_gp_func_t ++ * @param en \b #true to enable; \b #false to disable ++ */ ++void mxc_iomux_set_gpr(iomux_gp_func_t gp, int en); ++ ++/*! ++ * This function configures the pad value for a IOMUX pin. ++ * ++ * @param pin a pin number as defined in \b #iomux_pin_name_t ++ * @param config the ORed value of elements defined in \b ++ * #iomux_pad_config_t ++ */ ++void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config); ++ ++/*! ++ * This function configures input path. ++ * ++ * @param input index of input select register as defined in \b ++ * #iomux_input_select_t ++ * @param config the binary value of elements defined in \b ++ * #iomux_input_cfg_t ++ */ ++void mxc_iomux_set_input(iomux_input_select_t input, u32 config); ++#endif +diff --git a/include/asm-arm/arch-mx25/mx25-regs.h b/include/asm-arm/arch-mx25/mx25-regs.h +new file mode 100644 +index 0000000..26f3031 +--- /dev/null ++++ b/include/asm-arm/arch-mx25/mx25-regs.h +@@ -0,0 +1,380 @@ ++/* ++ * ++ * (c) 2007 Pengutronix, Sascha Hauer ++ * ++ * (C) Copyright 2009 Freescale Semiconductor ++ * ++ * 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_MX25_REGS_H ++#define __ASM_ARCH_MX25_REGS_H ++ ++#define __REG(x) (*((volatile u32 *)(x))) ++#define __REG16(x) (*((volatile u16 *)(x))) ++#define __REG8(x) (*((volatile u8 *)(x))) ++ ++/* ++ * AIPS 1 ++ */ ++#define AIPS1_BASE 0x43F00000 ++#define AIPS1_CTRL_BASE AIPS1_BASE ++#define MAX_BASE 0x43F04000 ++#define CLKCTL_BASE 0x43F08000 ++#define ETB_SLOT4_BASE 0x43F0C000 ++#define ETB_SLOT5_BASE 0x43F1000l ++#define ECT_CTIO_BASE 0x43F18000 ++#define I2C1_BASE 0x43F80000 ++#define I2C3_BASE 0x43F84000 ++#define CAN1_BASE 0x43F88000 ++#define CAN2_BASE 0x43F8C000 ++#define UART1_BASE 0x43F90000 ++#define UART2_BASE 0x43F94000 ++#define I2C2_BASE 0x43F98000 ++#define OWIRE_BASE 0x43F9C000 ++#define CSPI1_BASE 0x43FA4000 ++#define KPP_BASE 0x43FA8000 ++#define IOMUXC_BASE 0x43FAC000 ++#define AUDMUX_BASE 0x43FB0000 ++#define ECT_IP1_BASE 0x43FB8000 ++#define ECT_IP2_BASE 0x43FBC000 ++ ++/* ++ * SPBA ++ */ ++#define SPBA_BASE 0x50000000 ++#define CSPI3_BASE 0x50040000 ++#define UART4_BASE 0x50008000 ++#define UART3_BASE 0x5000C000 ++#define CSPI2_BASE 0x50010000 ++#define SSI2_BASE 0x50014000 ++#define ESAI_BASE 0x50018000 ++#define ATA_DMA_BASE 0x50020000 ++#define SIM1_BASE 0x50024000 ++#define SIM2_BASE 0x50028000 ++#define UART5_BASE 0x5002C000 ++#define TSC_BASE 0x50030000 ++#define SSI1_BASE 0x50034000 ++#define FEC_BASE 0x50038000 ++#define SOC_FEC FEC_BASE ++#define SPBA_CTRL_BASE 0x5003C000 ++ ++/* ++ * AIPS 2 ++ */ ++#define AIPS2_BASE 0x53F00000 ++#define AIPS2_CTRL_BASE AIPS2_BASE ++#define CCM_BASE 0x53F80000 ++#define GPT4_BASE 0x53F84000 ++#define GPT3_BASE 0x53F88000 ++#define GPT2_BASE 0x53F8C000 ++#define GPT1_BASE 0x53F90000 ++#define EPIT1_BASE 0x53F94000 ++#define EPIT2_BASE 0x53F98000 ++#define GPIO4_BASE 0x53F9C000 ++#define PWM2_BASE 0x53FA0000 ++#define GPIO3_BASE 0x53FA4000 ++#define PWM3_BASE 0x53FA8000 ++#define SCC_BASE 0x53FAC000 ++#define SCM_BASE 0x53FAE000 ++#define SMN_BASE 0x53FAF000 ++#define RNGD_BASE 0x53FB0000 ++#define MMC_SDHC1_BASE 0x53FB4000 ++#define MMC_SDHC2_BASE 0x53FB8000 ++#define ESDHC1_REG_BASE MMC_SDHC1_BASE ++#define LCDC_BASE 0x53FBC000 ++#define SLCDC_BASE 0x53FC0000 ++#define PWM4_BASE 0x53FC8000 ++#define GPIO1_BASE 0x53FCC000 ++#define GPIO2_BASE 0x53FD0000 ++#define SDMA_BASE 0x53FD4000 ++#define WDOG_BASE 0x53FDC000 ++#define PWM1_BASE 0x53FE0000 ++#define RTIC_BASE 0x53FEC000 ++#define IIM_BASE 0x53FF0000 ++#define USB_BASE 0x53FF4000 ++#define CSI_BASE 0x53FF8000 ++#define DRYICE_BASE 0x53FFC000 ++ ++/* ++ * ROMPATCH and ASIC ++ */ ++#define ROMPATCH_BASE 0x60000000 ++#define ROMPATCH_REV 0x40 ++#define ASIC_BASE 0x68000000 ++ ++#define RAM_BASE 0x78000000 ++ ++/* ++ * NAND, SDRAM, WEIM, M3IF, EMI controllers ++ */ ++#define EXT_MEM_CTRL_BASE 0xB8000000 ++#define ESDCTL_BASE 0xB8001000 ++#define WEIM_BASE 0xB8002000 ++#define WEIM_CTRL_CS0 WEIM_BASE ++#define WEIM_CTRL_CS1 (WEIM_BASE + 0x10) ++#define WEIM_CTRL_CS2 (WEIM_BASE + 0x20) ++#define WEIM_CTRL_CS3 (WEIM_BASE + 0x30) ++#define WEIM_CTRL_CS4 (WEIM_BASE + 0x40) ++#define WEIM_CTRL_CS5 (WEIM_BASE + 0x50) ++#define M3IF_BASE 0xB8003000 ++#define EMI_BASE 0xB8004000 ++ ++#define NFC_BASE_ADDR 0xBB000000 ++/* ++ * Memory regions and CS ++ */ ++#define CSD0_BASE 0x80000000 ++#define CSD1_BASE 0x90000000 ++#define CS0_BASE 0xA0000000 ++#define CS1_BASE 0xA8000000 ++#define CS2_BASE 0xB0000000 ++#define CS3_BASE 0xB2000000 ++#define CS4_BASE 0xB4000000 ++#define CS5_BASE 0xB6000000 ++ ++/* CCM */ ++#define CCM_MPCTL (CCM_BASE + 0x00) ++#define CCM_UPCTL (CCM_BASE + 0x04) ++#define CCM_CCTL (CCM_BASE + 0x08) ++#define CCM_CGR0 (CCM_BASE + 0x0C) ++#define CCM_CGR1 (CCM_BASE + 0x10) ++#define CCM_CGR2 (CCM_BASE + 0x14) ++#define CCM_PCDR0 (CCM_BASE + 0x18) ++#define CCM_PCDR1 (CCM_BASE + 0x1C) ++#define CCM_PCDR2 (CCM_BASE + 0x20) ++#define CCM_PCDR3 (CCM_BASE + 0x24) ++#define CCM_RCSR (CCM_BASE + 0x28) ++#define CCM_CRDR (CCM_BASE + 0x2C) ++#define CCM_DCVR0 (CCM_BASE + 0x30) ++#define CCM_DCVR1 (CCM_BASE + 0x34) ++#define CCM_DCVR2 (CCM_BASE + 0x38) ++#define CCM_DCVR3 (CCM_BASE + 0x3C) ++#define CCM_LTR0 (CCM_BASE + 0x40) ++#define CCM_LTR1 (CCM_BASE + 0x44) ++#define CCM_LTR2 (CCM_BASE + 0x48) ++#define CCM_LTR3 (CCM_BASE + 0x4C) ++#define CCM_LTBR0 (CCM_BASE + 0x50) ++#define CCM_LTBR1 (CCM_BASE + 0x54) ++#define CCM_PCMR0 (CCM_BASE + 0x58) ++#define CCM_PCMR1 (CCM_BASE + 0x5C) ++#define CCM_PCMR2 (CCM_BASE + 0x60) ++#define CCM_MCR (CCM_BASE + 0x64) ++#define CCM_LPIMR0 (CCM_BASE + 0x68) ++#define CCM_LPIMR1 (CCM_BASE + 0x6C) ++ ++#define CRM_CCTL_ARM_SRC (1 << 14) ++#define CRM_CCTL_AHB_OFFSET 28 ++ ++ ++#define FREQ_24MHZ 24000000 ++#define PLL_REF_CLK FREQ_24MHZ ++ ++/* ++ * FIXME - Constants verified up to this point. ++ * Offsets and derived constants below should be confirmed. ++ */ ++ ++#define CLKMODE_AUTO 0 ++#define CLKMODE_CONSUMER 1 ++ ++/* WEIM - CS0 */ ++#define CSCRU 0x00 ++#define CSCRL 0x04 ++#define CSCRA 0x08 ++ ++#define CHIP_REV_1_0 0x0 /* PASS 1.0 */ ++#define CHIP_REV_1_1 0x1 /* PASS 1.1 */ ++#define CHIP_REV_2_0 0x2 /* PASS 2.0 */ ++#define CHIP_LATEST CHIP_REV_1_1 ++ ++#define IIM_STAT 0x00 ++#define IIM_STAT_BUSY (1 << 7) ++#define IIM_STAT_PRGD (1 << 1) ++#define IIM_STAT_SNSD (1 << 0) ++#define IIM_STATM 0x04 ++#define IIM_ERR 0x08 ++#define IIM_ERR_PRGE (1 << 7) ++#define IIM_ERR_WPE (1 << 6) ++#define IIM_ERR_OPE (1 << 5) ++#define IIM_ERR_RPE (1 << 4) ++#define IIM_ERR_WLRE (1 << 3) ++#define IIM_ERR_SNSE (1 << 2) ++#define IIM_ERR_PARITYE (1 << 1) ++#define IIM_EMASK 0x0C ++#define IIM_FCTL 0x10 ++#define IIM_UAF 0x14 ++#define IIM_LA 0x18 ++#define IIM_SDAT 0x1C ++#define IIM_PREV 0x20 ++#define IIM_SREV 0x24 ++#define IIM_PREG_P 0x28 ++#define IIM_SCS0 0x2C ++#define IIM_SCS1 0x30 ++#define IIM_SCS2 0x34 ++#define IIM_SCS3 0x38 ++ ++#define EPIT_BASE EPIT1_BASE ++#define EPITCR 0x00 ++#define EPITSR 0x04 ++#define EPITLR 0x08 ++#define EPITCMPR 0x0C ++#define EPITCNR 0x10 ++ ++#define GPT_BASE GPT1_BASE ++/*#define GPTCR 0x00 ++#define GPTPR 0x04 ++#define GPTSR 0x08 ++#define GPTIR 0x0C ++#define GPTOCR1 0x10 ++#define GPTOCR2 0x14 ++#define GPTOCR3 0x18 ++#define GPTICR1 0x1C ++#define GPTICR2 0x20 ++#define GPTCNT 0x24*/ ++ ++/* ESDCTL */ ++#define ESDCTL_ESDCTL0 0x00 ++#define ESDCTL_ESDCFG0 0x04 ++#define ESDCTL_ESDCTL1 0x08 ++#define ESDCTL_ESDCFG1 0x0C ++#define ESDCTL_ESDMISC 0x10 ++ ++/* DRYICE */ ++#define DRYICE_DTCMR 0x00 ++#define DRYICE_DTCLR 0x04 ++#define DRYICE_DCAMR 0x08 ++#define DRYICE_DCALR 0x0C ++#define DRYICE_DCR 0x10 ++#define DRYICE_DSR 0x14 ++#define DRYICE_DIER 0x18 ++#define DRYICE_DMCR 0x1C ++#define DRYICE_DKSR 0x20 ++#define DRYICE_DKCR 0x24 ++#define DRYICE_DTCR 0x28 ++#define DRYICE_DACR 0x2C ++#define DRYICE_DGPR 0x3C ++#define DRYICE_DPKR0 0x40 ++#define DRYICE_DPKR1 0x44 ++#define DRYICE_DPKR2 0x48 ++#define DRYICE_DPKR3 0x4C ++#define DRYICE_DPKR4 0x50 ++#define DRYICE_DPKR5 0x54 ++#define DRYICE_DPKR6 0x58 ++#define DRYICE_DPKR7 0x5C ++#define DRYICE_DRKR0 0x60 ++#define DRYICE_DRKR1 0x64 ++#define DRYICE_DRKR2 0x68 ++#define DRYICE_DRKR3 0x6C ++#define DRYICE_DRKR4 0x70 ++#define DRYICE_DRKR5 0x74 ++#define DRYICE_DRKR6 0x78 ++#define DRYICE_DRKR7 0x7C ++ ++/* GPIO */ ++#define GPIO_DR 0x00 ++#define GPIO_GDIR 0x04 ++#define GPIO_PSR0 0x08 ++#define GPIO_ICR1 0x0C ++#define GPIO_ICR2 0x10 ++#define GPIO_IMR 0x14 ++#define GPIO_ISR 0x18 ++#define GPIO_EDGE_SEL 0x1C ++ ++ ++#if (PLL_REF_CLK != 24000000) ++#error Wrong PLL reference clock! The following macros will not work. ++#endif ++ ++/* Assuming 24MHz input clock */ ++/* PD MFD MFI MFN */ ++#define MPCTL_PARAM_399 (((1-1) << 26) + ((16-1) << 16) + \ ++ (8 << 10) + (5 << 0)) ++#define MPCTL_PARAM_532 ((1 << 31) + ((1-1) << 26) + \ ++ ((12-1) << 16) + (11 << 10) + (1 << 0)) ++#define MPCTL_PARAM_665 (((1-1) << 26) + ((48-1) << 16) + \ ++ (13 << 10) + (41 << 0)) ++ ++/* UPCTL PD MFD MFI MFN */ ++#define UPCTL_PARAM_300 (((1-1) << 26) + ((4-1) << 16) + \ ++ (6 << 10) + (1 << 0)) ++ ++#define NFC_V1_1 ++ ++#define NAND_REG_BASE (NFC_BASE + 0x1E00) ++#define NFC_BUFSIZE_REG_OFF (0 + 0x00) ++#define RAM_BUFFER_ADDRESS_REG_OFF (0 + 0x04) ++#define NAND_FLASH_ADD_REG_OFF (0 + 0x06) ++#define NAND_FLASH_CMD_REG_OFF (0 + 0x08) ++#define NFC_CONFIGURATION_REG_OFF (0 + 0x0A) ++#define ECC_STATUS_RESULT_REG_OFF (0 + 0x0C) ++#define ECC_RSLT_MAIN_AREA_REG_OFF (0 + 0x0E) ++#define ECC_RSLT_SPARE_AREA_REG_OFF (0 + 0x10) ++#define NF_WR_PROT_REG_OFF (0 + 0x12) ++#define NAND_FLASH_WR_PR_ST_REG_OFF (0 + 0x18) ++#define NAND_FLASH_CONFIG1_REG_OFF (0 + 0x1A) ++#define NAND_FLASH_CONFIG2_REG_OFF (0 + 0x1C) ++#define UNLOCK_START_BLK_ADD_REG_OFF (0 + 0x20) ++#define UNLOCK_END_BLK_ADD_REG_OFF (0 + 0x22) ++#define RAM_BUFFER_ADDRESS_RBA_3 0x3 ++#define NFC_BUFSIZE_1KB 0x0 ++#define NFC_BUFSIZE_2KB 0x1 ++#define NFC_CONFIGURATION_UNLOCKED 0x2 ++#define ECC_STATUS_RESULT_NO_ERR 0x0 ++#define ECC_STATUS_RESULT_1BIT_ERR 0x1 ++#define ECC_STATUS_RESULT_2BIT_ERR 0x2 ++#define NF_WR_PROT_UNLOCK 0x4 ++#define NAND_FLASH_CONFIG1_FORCE_CE (1 << 7) ++#define NAND_FLASH_CONFIG1_RST (1 << 6) ++#define NAND_FLASH_CONFIG1_BIG (1 << 5) ++#define NAND_FLASH_CONFIG1_INT_MSK (1 << 4) ++#define NAND_FLASH_CONFIG1_ECC_EN (1 << 3) ++#define NAND_FLASH_CONFIG1_SP_EN (1 << 2) ++#define NAND_FLASH_CONFIG2_INT_DONE (1 << 15) ++#define NAND_FLASH_CONFIG2_FDO_PAGE (0 << 3) ++#define NAND_FLASH_CONFIG2_FDO_ID (2 << 3) ++#define NAND_FLASH_CONFIG2_FDO_STATUS (4 << 3) ++#define NAND_FLASH_CONFIG2_FDI_EN (1 << 2) ++#define NAND_FLASH_CONFIG2_FADD_EN (1 << 1) ++#define NAND_FLASH_CONFIG2_FCMD_EN (1 << 0) ++#define FDO_PAGE_SPARE_VAL 0x8 ++#define NAND_BUF_NUM 8 ++ ++#define MXC_NAND_BASE_DUMMY 0x00000000 ++#define MXC_MMC_BASE_DUMMY 0x00000000 ++#define NOR_FLASH_BOOT 0 ++#define NAND_FLASH_BOOT 0x10000000 ++#define SDRAM_NON_FLASH_BOOT 0x20000000 ++#define MMC_FLASH_BOOT 0x40000000 ++#define MXCBOOT_FLAG_REG (CSI_BASE_ADDR + 0x28) ++#define MXCFIS_NOTHING 0x00000000 ++#define MXCFIS_NAND 0x10000000 ++#define MXCFIS_NOR 0x20000000 ++#define MXCFIS_MMC 0x40000000 ++#define MXCFIS_FLAG_REG (CSI_BASE_ADDR + 0x2C) ++ ++/*! ++ * * NFMS bit in RCSR register for pagesize of nandflash ++ * */ ++#define NFMS (*((volatile u32 *)(CCM_BASE+0x18))) ++#define NFMS_BIT 8 ++#define NFMS_NF_DWIDTH 14 ++#define NFMS_NF_PG_SZ 8 ++ ++#endif +diff --git a/include/asm-arm/arch-mx25/mx25.h b/include/asm-arm/arch-mx25/mx25.h +new file mode 100644 +index 0000000..60e0de0 +--- /dev/null ++++ b/include/asm-arm/arch-mx25/mx25.h +@@ -0,0 +1,44 @@ ++/* ++ * ++ * (c) 2007 Pengutronix, Sascha Hauer ++ * ++ * (C) Copyright 2009 Freescale Semiconductor ++ * ++ * 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_MX25_H ++#define __ASM_ARCH_MX25_H ++#ifndef __ASSEMBLER__ ++ ++#define GPIO_PORT_NUM 3 ++#define GPIO_NUM_PIN 32 ++ ++enum mxc_clock { ++ MXC_ARM_CLK = 0, ++ MXC_AHB_CLK, ++ MXC_IPG_CLK, ++ MXC_IPG_PERCLK, ++ MXC_UART_CLK, ++}; ++ ++extern unsigned int mx25_get_ipg_clk(void); ++extern unsigned int mxc_get_clock(enum mxc_clock clk); ++#endif ++#endif /* __ASM_ARCH_MX25_H */ +diff --git a/include/asm-arm/arch-mx25/mx25_pins.h b/include/asm-arm/arch-mx25/mx25_pins.h +new file mode 100644 +index 0000000..984f55d +--- /dev/null ++++ b/include/asm-arm/arch-mx25/mx25_pins.h +@@ -0,0 +1,259 @@ ++/* ++ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++#ifndef __ASM_ARCH_MXC_MX25_PINS_H__ ++#define __ASM_ARCH_MXC_MX25_PINS_H__ ++ ++/*! ++ * @file arch-mxc/mx25_pins.h ++ * ++ * @brief MX25 I/O Pin List ++ * ++ * @ingroup GPIO_MX25 ++ */ ++ ++#ifndef __ASSEMBLY__ ++ ++/*! ++ * @name IOMUX/PAD Bit field definitions ++ */ ++ ++/*! @{ */ ++ ++/*! ++ * In order to identify pins more effectively, each mux-controlled pin's ++ * enumerated value is constructed in the following way: ++ * ++ * ------------------------------------------------------------------- ++ * 31-29 | 28 - 24 |23 - 21| 20 - 10| 9 - 0 ++ * ------------------------------------------------------------------- ++ * IO_P | IO_I | RSVD | PAD_I | MUX_I ++ * ------------------------------------------------------------------- ++ * ++ * Bit 0 to 7 contains MUX_I used to identify the register ++ * offset (base is IOMUX_module_base ) defined in the Section ++ * "sw_pad_ctl & sw_mux_ctl details" of the IC Spec. Similar field ++ * definitions are used for the pad control register. For example, ++ * MX25_PIN_A14 is defined in the enumeration: ++ * ( 0x10 << MUX_I) | ( 0x230 << PAD_I) ++ * So the absolute address is: IOMUX_module_base + 0x10. ++ * The pad control register offset is: 0x230. ++ */ ++ ++/*! ++ * Starting bit position within each entry of \b iomux_pins to represent the ++ * MUX control register offset ++ */ ++#define MUX_I 0 ++/*! ++ * Starting bit position within each entry of \b iomux_pins to represent the ++ * PAD control register offset ++ */ ++#define PAD_I 10 ++ ++/*! ++ * Starting bit position within each entry of \b iomux_pins to represent the ++ * reserved filed ++ */ ++#define RSVD_I 21 ++ ++#define MUX_IO_P 29 ++#define MUX_IO_I 24 ++#define IOMUX_TO_GPIO(pin) ((((unsigned int)pin >> MUX_IO_P) * \ ++ GPIO_NUM_PIN) + ((pin >> MUX_IO_I) &\ ++ ((1 << (MUX_IO_P - MUX_IO_I)) - 1))) ++#define IOMUX_TO_IRQ(pin) (MXC_GPIO_INT_BASE + IOMUX_TO_GPIO(pin)) ++#define GPIO_TO_PORT(n) (n / GPIO_NUM_PIN) ++#define GPIO_TO_INDEX(n) (n % GPIO_NUM_PIN) ++ ++#define NON_GPIO_I 0x7 ++#define PIN_TO_MUX_MASK ((1<<(PAD_I - MUX_I)) - 1) ++#define PIN_TO_PAD_MASK ((1<<(RSVD_I - PAD_I)) - 1) ++#define NON_MUX_I PIN_TO_MUX_MASK ++ ++#define _MXC_BUILD_PIN(gp, gi, mi, pi) \ ++ (((gp) << MUX_IO_P) | ((gi) << MUX_IO_I) | \ ++ ((mi) << MUX_I) | ((pi) << PAD_I)) ++ ++#define _MXC_BUILD_GPIO_PIN(gp, gi, mi, pi) \ ++ _MXC_BUILD_PIN(gp, gi, mi, pi) ++ ++#define _MXC_BUILD_NON_GPIO_PIN(mi, pi) \ ++ _MXC_BUILD_PIN(NON_GPIO_I, 0, mi, pi) ++ ++#define PIN_TO_IOMUX_MUX(pin) ((pin >> MUX_I) & PIN_TO_MUX_MASK) ++#define PIN_TO_IOMUX_PAD(pin) ((pin >> PAD_I) & PIN_TO_PAD_MASK) ++ ++/*! @} End IOMUX/PAD Bit field definitions */ ++ ++typedef enum iomux_pins { ++ MX25_PIN_A10 = _MXC_BUILD_GPIO_PIN(3, 0, 0x8, 0x0), ++ MX25_PIN_A13 = _MXC_BUILD_GPIO_PIN(3, 1, 0x0c, 0x22C), ++ MX25_PIN_A14 = _MXC_BUILD_GPIO_PIN(1, 0, 0x10, 0x230), ++ MX25_PIN_A15 = _MXC_BUILD_GPIO_PIN(1, 1, 0x14, 0x234), ++ MX25_PIN_A16 = _MXC_BUILD_GPIO_PIN(1, 2, 0x18, 0x0), ++ MX25_PIN_A17 = _MXC_BUILD_GPIO_PIN(1, 3, 0x1c, 0x238), ++ MX25_PIN_A18 = _MXC_BUILD_GPIO_PIN(1, 4, 0x20, 0x23c), ++ MX25_PIN_A19 = _MXC_BUILD_GPIO_PIN(1, 5, 0x24, 0x240), ++ MX25_PIN_A20 = _MXC_BUILD_GPIO_PIN(1, 6, 0x28, 0x244), ++ MX25_PIN_A21 = _MXC_BUILD_GPIO_PIN(1, 7, 0x2c, 0x248), ++ MX25_PIN_A22 = _MXC_BUILD_GPIO_PIN(1, 8, 0x30, 0x0), ++ MX25_PIN_A23 = _MXC_BUILD_GPIO_PIN(1, 9, 0x34, 0x24c), ++ MX25_PIN_A24 = _MXC_BUILD_GPIO_PIN(1, 10, 0x38, 0x250), ++ MX25_PIN_A25 = _MXC_BUILD_GPIO_PIN(1, 11, 0x3c, 0x254), ++ MX25_PIN_EB0 = _MXC_BUILD_GPIO_PIN(1, 12, 0x40, 0x258), ++ MX25_PIN_EB1 = _MXC_BUILD_GPIO_PIN(1, 13, 0x44, 0x25c), ++ MX25_PIN_OE = _MXC_BUILD_GPIO_PIN(1, 14, 0x48, 0x260), ++ MX25_PIN_CS0 = _MXC_BUILD_GPIO_PIN(3, 2, 0x4c, 0x0), ++ MX25_PIN_CS1 = _MXC_BUILD_GPIO_PIN(3, 3, 0x50, 0x0), ++ MX25_PIN_CS4 = _MXC_BUILD_GPIO_PIN(2, 20, 0x54, 0x264), ++ MX25_PIN_CS5 = _MXC_BUILD_GPIO_PIN(2, 21, 0x58, 0x268), ++ MX25_PIN_NF_CE0 = _MXC_BUILD_GPIO_PIN(2, 22, 0x5c, 0x26c), ++ MX25_PIN_ECB = _MXC_BUILD_GPIO_PIN(2, 23, 0x60, 0x270), ++ MX25_PIN_LBA = _MXC_BUILD_GPIO_PIN(2, 24, 0x64, 0x274), ++ MX25_PIN_BCLK = _MXC_BUILD_GPIO_PIN(3, 4, 0x68, 0x0), ++ MX25_PIN_RW = _MXC_BUILD_GPIO_PIN(2, 25, 0x6c, 0x278), ++ MX25_PIN_NFWE_B = _MXC_BUILD_GPIO_PIN(2, 26, 0x70, 0x0), ++ MX25_PIN_NFRE_B = _MXC_BUILD_GPIO_PIN(2, 27, 0x74, 0x0), ++ MX25_PIN_NFALE = _MXC_BUILD_GPIO_PIN(2, 28, 0x78, 0x0), ++ MX25_PIN_NFCLE = _MXC_BUILD_GPIO_PIN(2, 29, 0x7c, 0x0), ++ MX25_PIN_NFWP_B = _MXC_BUILD_GPIO_PIN(2, 30, 0x80, 0x0), ++ MX25_PIN_NFRB = _MXC_BUILD_GPIO_PIN(2, 31, 0x84, 0x27c), ++ MX25_PIN_D15 = _MXC_BUILD_GPIO_PIN(3, 5, 0x88, 0x280), ++ MX25_PIN_D14 = _MXC_BUILD_GPIO_PIN(3, 6, 0x8c, 0x284), ++ MX25_PIN_D13 = _MXC_BUILD_GPIO_PIN(3, 7, 0x90, 0x288), ++ MX25_PIN_D12 = _MXC_BUILD_GPIO_PIN(3, 8, 0x94, 0x28c), ++ MX25_PIN_D11 = _MXC_BUILD_GPIO_PIN(3, 9, 0x98, 0x290), ++ MX25_PIN_D10 = _MXC_BUILD_GPIO_PIN(3, 10, 0x9c, 0x294), ++ MX25_PIN_D9 = _MXC_BUILD_GPIO_PIN(3, 11, 0xa0, 0x298), ++ MX25_PIN_D8 = _MXC_BUILD_GPIO_PIN(3, 12, 0xa4, 0x29c), ++ MX25_PIN_D7 = _MXC_BUILD_GPIO_PIN(3, 13, 0xa8, 0x2a0), ++ MX25_PIN_D6 = _MXC_BUILD_GPIO_PIN(3, 14, 0xac, 0x2a4), ++ MX25_PIN_D5 = _MXC_BUILD_GPIO_PIN(3, 15, 0xb0, 0x2a8), ++ MX25_PIN_D4 = _MXC_BUILD_GPIO_PIN(3, 16, 0xb4, 0x2ac), ++ MX25_PIN_D3 = _MXC_BUILD_GPIO_PIN(3, 17, 0xb8, 0x2b0), ++ MX25_PIN_D2 = _MXC_BUILD_GPIO_PIN(3, 18, 0xbc, 0x2b4), ++ MX25_PIN_D1 = _MXC_BUILD_GPIO_PIN(3, 19, 0xc0, 0x2b8), ++ MX25_PIN_D0 = _MXC_BUILD_GPIO_PIN(3, 20, 0xc4, 0x2bc), ++ MX25_PIN_LD0 = _MXC_BUILD_GPIO_PIN(1, 15, 0xc8, 0x2c0), ++ MX25_PIN_LD1 = _MXC_BUILD_GPIO_PIN(1, 16, 0xcc, 0x2c4), ++ MX25_PIN_LD2 = _MXC_BUILD_GPIO_PIN(1, 17, 0xd0, 0x2c8), ++ MX25_PIN_LD3 = _MXC_BUILD_GPIO_PIN(1, 18, 0xd4, 0x2cc), ++ MX25_PIN_LD4 = _MXC_BUILD_GPIO_PIN(1, 19, 0xd8, 0x2d0), ++ MX25_PIN_LD5 = _MXC_BUILD_GPIO_PIN(0, 19, 0xdc, 0x2d4), ++ MX25_PIN_LD6 = _MXC_BUILD_GPIO_PIN(0, 20, 0xe0, 0x2d8), ++ MX25_PIN_LD7 = _MXC_BUILD_GPIO_PIN(0, 21, 0xe4, 0x2dc), ++ MX25_PIN_LD8 = _MXC_BUILD_NON_GPIO_PIN(0xe8, 0x2e0), ++ MX25_PIN_LD9 = _MXC_BUILD_NON_GPIO_PIN(0xec, 0x2e4), ++ MX25_PIN_LD10 = _MXC_BUILD_NON_GPIO_PIN(0xf0, 0x2e8), ++ MX25_PIN_LD11 = _MXC_BUILD_NON_GPIO_PIN(0xf4, 0x2ec), ++ MX25_PIN_LD12 = _MXC_BUILD_NON_GPIO_PIN(0xf8, 0x2f0), ++ MX25_PIN_LD13 = _MXC_BUILD_NON_GPIO_PIN(0xfc, 0x2f4), ++ MX25_PIN_LD14 = _MXC_BUILD_NON_GPIO_PIN(0x100, 0x2f8), ++ MX25_PIN_LD15 = _MXC_BUILD_NON_GPIO_PIN(0x104, 0x2fc), ++ MX25_PIN_HSYNC = _MXC_BUILD_GPIO_PIN(0, 22, 0x108, 0x300), ++ MX25_PIN_VSYNC = _MXC_BUILD_GPIO_PIN(0, 23, 0x10c, 0x304), ++ MX25_PIN_LSCLK = _MXC_BUILD_GPIO_PIN(0, 24, 0x110, 0x308), ++ MX25_PIN_OE_ACD = _MXC_BUILD_GPIO_PIN(0, 25, 0x114, 0x30c), ++ MX25_PIN_CONTRAST = _MXC_BUILD_NON_GPIO_PIN(0x118, 0x310), ++ MX25_PIN_PWM = _MXC_BUILD_GPIO_PIN(0, 26, 0x11c, 0x314), ++ MX25_PIN_CSI_D2 = _MXC_BUILD_GPIO_PIN(0, 27, 0x120, 0x318), ++ MX25_PIN_CSI_D3 = _MXC_BUILD_GPIO_PIN(0, 28, 0x124, 0x31c), ++ MX25_PIN_CSI_D4 = _MXC_BUILD_GPIO_PIN(0, 29, 0x128, 0x320), ++ MX25_PIN_CSI_D5 = _MXC_BUILD_GPIO_PIN(0, 30, 0x12c, 0x324), ++ MX25_PIN_CSI_D6 = _MXC_BUILD_GPIO_PIN(0, 31, 0x130, 0x328), ++ MX25_PIN_CSI_D7 = _MXC_BUILD_GPIO_PIN(0, 6, 0x134, 0x32c), ++ MX25_PIN_CSI_D8 = _MXC_BUILD_GPIO_PIN(0, 7, 0x138, 0x330), ++ MX25_PIN_CSI_D9 = _MXC_BUILD_GPIO_PIN(3, 21, 0x13c, 0x334), ++ MX25_PIN_CSI_MCLK = _MXC_BUILD_GPIO_PIN(0, 8, 0x140, 0x338), ++ MX25_PIN_CSI_VSYNC = _MXC_BUILD_GPIO_PIN(0, 9, 0x144, 0x33c), ++ MX25_PIN_CSI_HSYNC = _MXC_BUILD_GPIO_PIN(0, 10, 0x148, 0x340), ++ MX25_PIN_CSI_PIXCLK = _MXC_BUILD_GPIO_PIN(0, 11, 0x14c, 0x344), ++ MX25_PIN_I2C1_CLK = _MXC_BUILD_GPIO_PIN(0, 12, 0x150, 0x348), ++ MX25_PIN_I2C1_DAT = _MXC_BUILD_GPIO_PIN(0, 13, 0x154, 0x34c), ++ MX25_PIN_CSPI1_MOSI = _MXC_BUILD_GPIO_PIN(0, 14, 0x158, 0x350), ++ MX25_PIN_CSPI1_MISO = _MXC_BUILD_GPIO_PIN(0, 15, 0x15c, 0x354), ++ MX25_PIN_CSPI1_SS0 = _MXC_BUILD_GPIO_PIN(0, 16, 0x160, 0x358), ++ MX25_PIN_CSPI1_SS1 = _MXC_BUILD_GPIO_PIN(0, 17, 0x164, 0x35c), ++ MX25_PIN_CSPI1_SCLK = _MXC_BUILD_GPIO_PIN(0, 18, 0x168, 0x360), ++ MX25_PIN_CSPI1_RDY = _MXC_BUILD_GPIO_PIN(1, 22, 0x16c, 0x364), ++ MX25_PIN_UART1_RXD = _MXC_BUILD_GPIO_PIN(3, 22, 0x170, 0x368), ++ MX25_PIN_UART1_TXD = _MXC_BUILD_GPIO_PIN(3, 23, 0x174, 0x36c), ++ MX25_PIN_UART1_RTS = _MXC_BUILD_GPIO_PIN(3, 24, 0x178, 0x370), ++ MX25_PIN_UART1_CTS = _MXC_BUILD_GPIO_PIN(3, 25, 0x17c, 0x374), ++ MX25_PIN_UART2_RXD = _MXC_BUILD_GPIO_PIN(3, 26, 0x180, 0x378), ++ MX25_PIN_UART2_TXD = _MXC_BUILD_GPIO_PIN(3, 27, 0x184, 0x37c), ++ MX25_PIN_UART2_RTS = _MXC_BUILD_GPIO_PIN(3, 28, 0x188, 0x380), ++ MX25_PIN_UART2_CTS = _MXC_BUILD_GPIO_PIN(3, 29, 0x18c, 0x384), ++ MX25_PIN_SD1_CMD = _MXC_BUILD_GPIO_PIN(1, 23, 0x190, 0x388), ++ MX25_PIN_SD1_CLK = _MXC_BUILD_GPIO_PIN(1, 24, 0x194, 0x38c), ++ MX25_PIN_SD1_DATA0 = _MXC_BUILD_GPIO_PIN(1, 25, 0x198, 0x390), ++ MX25_PIN_SD1_DATA1 = _MXC_BUILD_GPIO_PIN(1, 26, 0x19c, 0x394), ++ MX25_PIN_SD1_DATA2 = _MXC_BUILD_GPIO_PIN(1, 27, 0x1a0, 0x398), ++ MX25_PIN_SD1_DATA3 = _MXC_BUILD_GPIO_PIN(1, 28, 0x1a4, 0x39c), ++ MX25_PIN_KPP_ROW0 = _MXC_BUILD_GPIO_PIN(1, 29, 0x1a8, 0x3a0), ++ MX25_PIN_KPP_ROW1 = _MXC_BUILD_GPIO_PIN(1, 30, 0x1ac, 0x3a4), ++ MX25_PIN_KPP_ROW2 = _MXC_BUILD_GPIO_PIN(1, 31, 0x1b0, 0x3a8), ++ MX25_PIN_KPP_ROW3 = _MXC_BUILD_GPIO_PIN(2, 0, 0x1b4, 0x3ac), ++ MX25_PIN_KPP_COL0 = _MXC_BUILD_GPIO_PIN(2, 1, 0x1b8, 0x3b0), ++ MX25_PIN_KPP_COL1 = _MXC_BUILD_GPIO_PIN(2, 2, 0x1bc, 0x3b4), ++ MX25_PIN_KPP_COL2 = _MXC_BUILD_GPIO_PIN(2, 3, 0x1c0, 0x3b8), ++ MX25_PIN_KPP_COL3 = _MXC_BUILD_GPIO_PIN(2, 4, 0x1c4, 0x3bc), ++ MX25_PIN_FEC_MDC = _MXC_BUILD_GPIO_PIN(2, 5, 0x1c8, 0x3c0), ++ MX25_PIN_FEC_MDIO = _MXC_BUILD_GPIO_PIN(2, 6, 0x1cc, 0x3c4), ++ MX25_PIN_FEC_TDATA0 = _MXC_BUILD_GPIO_PIN(2, 7, 0x1d0, 0x3c8), ++ MX25_PIN_FEC_TDATA1 = _MXC_BUILD_GPIO_PIN(2, 8, 0x1d4, 0x3cc), ++ MX25_PIN_FEC_TX_EN = _MXC_BUILD_GPIO_PIN(2, 9, 0x1d8, 0x3d0), ++ MX25_PIN_FEC_RDATA0 = _MXC_BUILD_GPIO_PIN(2, 10, 0x1dc, 0x3d4), ++ MX25_PIN_FEC_RDATA1 = _MXC_BUILD_GPIO_PIN(2, 11, 0x1e0, 0x3d8), ++ MX25_PIN_FEC_RX_DV = _MXC_BUILD_GPIO_PIN(2, 12, 0x1e4, 0x3dc), ++ MX25_PIN_FEC_TX_CLK = _MXC_BUILD_GPIO_PIN(2, 13, 0x1e8, 0x3e0), ++ MX25_PIN_RTCK = _MXC_BUILD_GPIO_PIN(2, 14, 0x1ec, 0x3e4), ++ MX25_PIN_DE_B = _MXC_BUILD_GPIO_PIN(1, 20, 0x1f0, 0x3ec), ++ MX25_PIN_TDO = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x3e8), ++ MX25_PIN_GPIO_A = _MXC_BUILD_GPIO_PIN(0, 0, 0x1f4, 0x3f0), ++ MX25_PIN_GPIO_B = _MXC_BUILD_GPIO_PIN(0, 1, 0x1f8, 0x3f4), ++ MX25_PIN_GPIO_C = _MXC_BUILD_GPIO_PIN(0, 2, 0x1fc, 0x3f8), ++ MX25_PIN_GPIO_D = _MXC_BUILD_GPIO_PIN(0, 3, 0x200, 0x3fc), ++ MX25_PIN_GPIO_E = _MXC_BUILD_GPIO_PIN(0, 4, 0x204, 0x400), ++ MX25_PIN_GPIO_F = _MXC_BUILD_GPIO_PIN(0, 5, 0x208, 0x404), ++ MX25_PIN_EXT_ARMCLK = _MXC_BUILD_GPIO_PIN(2, 15, 0x20c, 0x0), ++ MX25_PIN_UPLL_BYPCLK = _MXC_BUILD_GPIO_PIN(2, 16, 0x210, 0x0), ++ MX25_PIN_VSTBY_REQ = _MXC_BUILD_GPIO_PIN(2, 17, 0x214, 0x408), ++ MX25_PIN_VSTBY_ACK = _MXC_BUILD_GPIO_PIN(2, 18, 0x218, 0x40c), ++ MX25_PIN_POWER_FAIL = _MXC_BUILD_GPIO_PIN(2, 19, 0x21c, 0x410), ++ MX25_PIN_CLKO = _MXC_BUILD_GPIO_PIN(1, 21, 0x220, 0x414), ++ MX25_PIN_BOOT_MODE0 = _MXC_BUILD_GPIO_PIN(3, 30, 0x224, 0x0), ++ MX25_PIN_BOOT_MODE1 = _MXC_BUILD_GPIO_PIN(3, 31, 0x228, 0x0), ++ ++ MX25_PIN_CTL_GRP_DVS_MISC = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x418), ++ MX25_PIN_CTL_GRP_DSE_FEC = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x41c), ++ MX25_PIN_CTL_GRP_DVS_JTAG = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x420), ++ MX25_PIN_CTL_GRP_DSE_NFC = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x424), ++ MX25_PIN_CTL_GRP_DSE_CSI = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x428), ++ MX25_PIN_CTL_GRP_DSE_WEIM = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x42c), ++ MX25_PIN_CTL_GRP_DSE_DDR = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x430), ++ MX25_PIN_CTL_GRP_DVS_CRM = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x434), ++ MX25_PIN_CTL_GRP_DSE_KPP = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x438), ++ MX25_PIN_CTL_GRP_DSE_SDHC1 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x43c), ++ MX25_PIN_CTL_GRP_DSE_LCD = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x440), ++ MX25_PIN_CTL_GRP_DSE_UART = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x444), ++ MX25_PIN_CTL_GRP_DVS_NFC = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x448), ++ MX25_PIN_CTL_GRP_DVS_CSI = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x44c), ++ MX25_PIN_CTL_GRP_DSE_CSPI1 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x450), ++ MX25_PIN_CTL_GRP_DDRTYPE = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x454), ++ MX25_PIN_CTL_GRP_DVS_SDHC1 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x458), ++ MX25_PIN_CTL_GRP_DVS_LCD = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x45c) ++} iomux_pin_name_t; ++ ++#endif ++#endif +diff --git a/include/asm-arm/arch-mx25/mxc_nand.h b/include/asm-arm/arch-mx25/mxc_nand.h +new file mode 100644 +index 0000000..20a146c +--- /dev/null ++++ b/include/asm-arm/arch-mx25/mxc_nand.h +@@ -0,0 +1,198 @@ ++/* ++ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file mxc_nd2.h ++ * ++ * @brief This file contains the NAND Flash Controller register information. ++ * ++ * ++ * @ingroup NAND_MTD ++ */ ++ ++#ifndef __MXC_NAND_H__ ++#define __MXC_NAND_H__ ++ ++#include ++ ++#define IS_2K_PAGE_NAND ((mtd->writesize / info->num_of_intlv) \ ++ == NAND_PAGESIZE_2KB) ++#define IS_4K_PAGE_NAND ((mtd->writesize / info->num_of_intlv) \ ++ == NAND_PAGESIZE_4KB) ++#define IS_LARGE_PAGE_NAND ((mtd->writesize / info->num_of_intlv) > 512) ++ ++#define NAND_PAGESIZE_2KB 2048 ++#define NAND_PAGESIZE_4KB 4096 ++#define NAND_MAX_PAGESIZE 4096 ++ ++/* ++ * Addresses for NFC registers ++ */ ++#define NFC_REG_BASE (NFC_BASE_ADDR + 0x1000) ++#define NFC_BUF_ADDR (NFC_REG_BASE + 0xE04) ++#define NFC_FLASH_ADDR (NFC_REG_BASE + 0xE06) ++#define NFC_FLASH_CMD (NFC_REG_BASE + 0xE08) ++#define NFC_CONFIG (NFC_REG_BASE + 0xE0A) ++#define NFC_ECC_STATUS_RESULT (NFC_REG_BASE + 0xE0C) ++#define NFC_SPAS (NFC_REG_BASE + 0xE10) ++#define NFC_WRPROT (NFC_REG_BASE + 0xE12) ++#define NFC_UNLOCKSTART_BLKADDR (NFC_REG_BASE + 0xE20) ++#define NFC_UNLOCKEND_BLKADDR (NFC_REG_BASE + 0xE22) ++#define NFC_CONFIG1 (NFC_REG_BASE + 0xE1A) ++#define NFC_CONFIG2 (NFC_REG_BASE + 0xE1C) ++ ++/*! ++ * Addresses for NFC RAM BUFFER Main area 0 ++ */ ++#define MAIN_AREA0 (u16 *)(NFC_BASE_ADDR + 0x000) ++#define MAIN_AREA1 (u16 *)(NFC_BASE_ADDR + 0x200) ++ ++/*! ++ * Addresses for NFC SPARE BUFFER Spare area 0 ++ */ ++#define SPARE_AREA0 (u16 *)(NFC_BASE_ADDR + 0x1000) ++#define SPARE_LEN 64 ++#define SPARE_COUNT 8 ++#define SPARE_SIZE (SPARE_LEN * SPARE_COUNT) ++ ++ ++#define SPAS_SHIFT (0) ++#define SPAS_MASK (0xFF00) ++#define IS_4BIT_ECC \ ++ ((raw_read(REG_NFC_ECC_MODE) & NFC_ECC_MODE_4) >> 0) ++ ++#define NFC_SET_SPAS(v) \ ++ raw_write(((raw_read(REG_NFC_SPAS) & SPAS_MASK) | \ ++ ((v< +Date: Sun, 14 Dec 2008 09:47:14 +0100 +Subject: [PATCH] OMAP3: Add common clock, memory and low level code + +Add common clock, memory and low level code + +Signed-off-by: Dirk Behme +(cherry picked from commit 5ed3e8659e5373f6a229877ac506c0b00a054fb8) +--- + cpu/arm_cortexa8/omap3/clock.c | 381 ++++++++++++++++++++++++++++++++ + cpu/arm_cortexa8/omap3/lowlevel_init.S | 361 ++++++++++++++++++++++++++++++ + cpu/arm_cortexa8/omap3/mem.c | 284 ++++++++++++++++++++++++ + cpu/arm_cortexa8/omap3/syslib.c | 72 ++++++ + 4 files changed, 1098 insertions(+), 0 deletions(-) + +diff --git a/cpu/arm_cortexa8/omap3/clock.c b/cpu/arm_cortexa8/omap3/clock.c +new file mode 100644 +index 0000000..8ac31be +--- /dev/null ++++ b/cpu/arm_cortexa8/omap3/clock.c +@@ -0,0 +1,381 @@ ++/* ++ * (C) Copyright 2008 ++ * Texas Instruments, ++ * ++ * Author : ++ * Manikandan Pillai ++ * ++ * Derived from Beagle Board and OMAP3 SDP code by ++ * Richard Woodruff ++ * Syed Mohammed Khasim ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/****************************************************************************** ++ * get_sys_clk_speed() - determine reference oscillator speed ++ * based on known 32kHz clock and gptimer. ++ *****************************************************************************/ ++u32 get_osc_clk_speed(void) ++{ ++ u32 start, cstart, cend, cdiff, val; ++ prcm_t *prcm_base = (prcm_t *)PRCM_BASE; ++ prm_t *prm_base = (prm_t *)PRM_BASE; ++ gptimer_t *gpt1_base = (gptimer_t *)OMAP34XX_GPT1; ++ s32ktimer_t *s32k_base = (s32ktimer_t *)SYNC_32KTIMER_BASE; ++ ++ val = readl(&prm_base->clksrc_ctrl); ++ ++ /* If SYS_CLK is being divided by 2, remove for now */ ++ val = (val & (~SYSCLKDIV_2)) | SYSCLKDIV_1; ++ writel(val, &prm_base->clksrc_ctrl); ++ ++ /* enable timer2 */ ++ val = readl(&prcm_base->clksel_wkup) | CLKSEL_GPT1; ++ ++ /* select sys_clk for GPT1 */ ++ writel(val, &prcm_base->clksel_wkup); ++ ++ /* Enable I and F Clocks for GPT1 */ ++ val = readl(&prcm_base->iclken_wkup) | EN_GPT1 | EN_32KSYNC; ++ writel(val, &prcm_base->iclken_wkup); ++ val = readl(&prcm_base->fclken_wkup) | EN_GPT1; ++ writel(val, &prcm_base->fclken_wkup); ++ ++ writel(0, &gpt1_base->tldr); /* start counting at 0 */ ++ writel(GPT_EN, &gpt1_base->tclr); /* enable clock */ ++ ++ /* enable 32kHz source, determine sys_clk via gauging */ ++ ++ /* start time in 20 cycles */ ++ start = 20 + readl(&s32k_base->s32k_cr); ++ ++ /* dead loop till start time */ ++ while (readl(&s32k_base->s32k_cr) < start); ++ ++ /* get start sys_clk count */ ++ cstart = readl(&gpt1_base->tcrr); ++ ++ /* wait for 40 cycles */ ++ while (readl(&s32k_base->s32k_cr) < (start + 20)) ; ++ cend = readl(&gpt1_base->tcrr); /* get end sys_clk count */ ++ cdiff = cend - cstart; /* get elapsed ticks */ ++ ++ /* based on number of ticks assign speed */ ++ if (cdiff > 19000) ++ return S38_4M; ++ else if (cdiff > 15200) ++ return S26M; ++ else if (cdiff > 13000) ++ return S24M; ++ else if (cdiff > 9000) ++ return S19_2M; ++ else if (cdiff > 7600) ++ return S13M; ++ else ++ return S12M; ++} ++ ++/****************************************************************************** ++ * get_sys_clkin_sel() - returns the sys_clkin_sel field value based on ++ * input oscillator clock frequency. ++ *****************************************************************************/ ++void get_sys_clkin_sel(u32 osc_clk, u32 *sys_clkin_sel) ++{ ++ switch(osc_clk) { ++ case S38_4M: ++ *sys_clkin_sel = 4; ++ break; ++ case S26M: ++ *sys_clkin_sel = 3; ++ break; ++ case S19_2M: ++ *sys_clkin_sel = 2; ++ break; ++ case S13M: ++ *sys_clkin_sel = 1; ++ break; ++ case S12M: ++ default: ++ *sys_clkin_sel = 0; ++ } ++} ++ ++/****************************************************************************** ++ * prcm_init() - inits clocks for PRCM as defined in clocks.h ++ * called from SRAM, or Flash (using temp SRAM stack). ++ *****************************************************************************/ ++void prcm_init(void) ++{ ++ void (*f_lock_pll) (u32, u32, u32, u32); ++ int xip_safe, p0, p1, p2, p3; ++ u32 osc_clk = 0, sys_clkin_sel; ++ u32 clk_index, sil_index; ++ prm_t *prm_base = (prm_t *)PRM_BASE; ++ prcm_t *prcm_base = (prcm_t *)PRCM_BASE; ++ dpll_param *dpll_param_p; ++ ++ f_lock_pll = (void *) ((u32) &_end_vect - (u32) &_start + ++ SRAM_VECT_CODE); ++ ++ xip_safe = is_running_in_sram(); ++ ++ /* ++ * Gauge the input clock speed and find out the sys_clkin_sel ++ * value corresponding to the input clock. ++ */ ++ osc_clk = get_osc_clk_speed(); ++ get_sys_clkin_sel(osc_clk, &sys_clkin_sel); ++ ++ /* set input crystal speed */ ++ sr32(&prm_base->clksel, 0, 3, sys_clkin_sel); ++ ++ /* If the input clock is greater than 19.2M always divide/2 */ ++ if (sys_clkin_sel > 2) { ++ /* input clock divider */ ++ sr32(&prm_base->clksrc_ctrl, 6, 2, 2); ++ clk_index = sys_clkin_sel / 2; ++ } else { ++ /* input clock divider */ ++ sr32(&prm_base->clksrc_ctrl, 6, 2, 1); ++ clk_index = sys_clkin_sel; ++ } ++ ++ /* ++ * The DPLL tables are defined according to sysclk value and ++ * silicon revision. The clk_index value will be used to get ++ * the values for that input sysclk from the DPLL param table ++ * and sil_index will get the values for that SysClk for the ++ * appropriate silicon rev. ++ */ ++ sil_index = get_cpu_rev() - 1; ++ ++ /* Unlock MPU DPLL (slows things down, and needed later) */ ++ sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOW_POWER_BYPASS); ++ wait_on_value(ST_MPU_CLK, 0, &prcm_base->idlest_pll_mpu, LDELAY); ++ ++ /* Getting the base address of Core DPLL param table */ ++ dpll_param_p = (dpll_param *) get_core_dpll_param(); ++ ++ /* Moving it to the right sysclk and ES rev base */ ++ dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; ++ if (xip_safe) { ++ /* ++ * CORE DPLL ++ * sr32(CM_CLKSEL2_EMU) set override to work when asleep ++ */ ++ sr32(&prcm_base->clken_pll, 0, 3, PLL_FAST_RELOCK_BYPASS); ++ wait_on_value(ST_CORE_CLK, 0, &prcm_base->idlest_ckgen, ++ LDELAY); ++ ++ /* ++ * For OMAP3 ES1.0 Errata 1.50, default value directly doesn't ++ * work. write another value and then default value. ++ */ ++ ++ /* m3x2 */ ++ sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2 + 1); ++ /* m3x2 */ ++ sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2); ++ /* Set M2 */ ++ sr32(&prcm_base->clksel1_pll, 27, 2, dpll_param_p->m2); ++ /* Set M */ ++ sr32(&prcm_base->clksel1_pll, 16, 11, dpll_param_p->m); ++ /* Set N */ ++ sr32(&prcm_base->clksel1_pll, 8, 7, dpll_param_p->n); ++ /* 96M Src */ ++ sr32(&prcm_base->clksel1_pll, 6, 1, 0); ++ /* ssi */ ++ sr32(&prcm_base->clksel_core, 8, 4, CORE_SSI_DIV); ++ /* fsusb */ ++ sr32(&prcm_base->clksel_core, 4, 2, CORE_FUSB_DIV); ++ /* l4 */ ++ sr32(&prcm_base->clksel_core, 2, 2, CORE_L4_DIV); ++ /* l3 */ ++ sr32(&prcm_base->clksel_core, 0, 2, CORE_L3_DIV); ++ /* gfx */ ++ sr32(&prcm_base->clksel_gfx, 0, 3, GFX_DIV); ++ /* reset mgr */ ++ sr32(&prcm_base->clksel_wkup, 1, 2, WKUP_RSM); ++ /* FREQSEL */ ++ sr32(&prcm_base->clken_pll, 4, 4, dpll_param_p->fsel); ++ /* lock mode */ ++ sr32(&prcm_base->clken_pll, 0, 3, PLL_LOCK); ++ ++ wait_on_value(ST_CORE_CLK, 1, &prcm_base->idlest_ckgen, ++ LDELAY); ++ } else if (is_running_in_flash()) { ++ /* ++ * if running from flash, jump to small relocated code ++ * area in SRAM. ++ */ ++ p0 = readl(&prcm_base->clken_pll); ++ sr32(&p0, 0, 3, PLL_FAST_RELOCK_BYPASS); ++ sr32(&p0, 4, 4, dpll_param_p->fsel); /* FREQSEL */ ++ ++ p1 = readl(&prcm_base->clksel1_pll); ++ sr32(&p1, 27, 2, dpll_param_p->m2); /* Set M2 */ ++ sr32(&p1, 16, 11, dpll_param_p->m); /* Set M */ ++ sr32(&p1, 8, 7, dpll_param_p->n); /* Set N */ ++ sr32(&p1, 6, 1, 0); /* set source for 96M */ ++ ++ p2 = readl(&prcm_base->clksel_core); ++ sr32(&p2, 8, 4, CORE_SSI_DIV); /* ssi */ ++ sr32(&p2, 4, 2, CORE_FUSB_DIV); /* fsusb */ ++ sr32(&p2, 2, 2, CORE_L4_DIV); /* l4 */ ++ sr32(&p2, 0, 2, CORE_L3_DIV); /* l3 */ ++ ++ p3 = (u32)&prcm_base->idlest_ckgen; ++ ++ (*f_lock_pll) (p0, p1, p2, p3); ++ } ++ ++ /* PER DPLL */ ++ sr32(&prcm_base->clken_pll, 16, 3, PLL_STOP); ++ wait_on_value(ST_PERIPH_CLK, 0, &prcm_base->idlest_ckgen, LDELAY); ++ ++ /* Getting the base address to PER DPLL param table */ ++ ++ /* Set N */ ++ dpll_param_p = (dpll_param *) get_per_dpll_param(); ++ ++ /* Moving it to the right sysclk base */ ++ dpll_param_p = dpll_param_p + clk_index; ++ ++ /* ++ * Errata 1.50 Workaround for OMAP3 ES1.0 only ++ * If using default divisors, write default divisor + 1 ++ * and then the actual divisor value ++ */ ++ sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2 + 1); /* set M6 */ ++ sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2); /* set M6 */ ++ sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2 + 1); /* set M5 */ ++ sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2); /* set M5 */ ++ sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2 + 1); /* set M4 */ ++ sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2); /* set M4 */ ++ sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2 + 1); /* set M3 */ ++ sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2); /* set M3 */ ++ sr32(&prcm_base->clksel3_pll, 0, 5, dpll_param_p->m2 + 1); /* set M2 */ ++ sr32(&prcm_base->clksel3_pll, 0, 5, dpll_param_p->m2); /* set M2 */ ++ /* Workaround end */ ++ ++ sr32(&prcm_base->clksel2_pll, 8, 11, dpll_param_p->m); /* set m */ ++ sr32(&prcm_base->clksel2_pll, 0, 7, dpll_param_p->n); /* set n */ ++ sr32(&prcm_base->clken_pll, 20, 4, dpll_param_p->fsel); /* FREQSEL */ ++ sr32(&prcm_base->clken_pll, 16, 3, PLL_LOCK); /* lock mode */ ++ wait_on_value(ST_PERIPH_CLK, 2, &prcm_base->idlest_ckgen, LDELAY); ++ ++ /* Getting the base address to MPU DPLL param table */ ++ dpll_param_p = (dpll_param *) get_mpu_dpll_param(); ++ ++ /* Moving it to the right sysclk and ES rev base */ ++ dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; ++ ++ /* MPU DPLL (unlocked already) */ ++ ++ /* Set M2 */ ++ sr32(&prcm_base->clksel2_pll_mpu, 0, 5, dpll_param_p->m2); ++ /* Set M */ ++ sr32(&prcm_base->clksel1_pll_mpu, 8, 11, dpll_param_p->m); ++ /* Set N */ ++ sr32(&prcm_base->clksel1_pll_mpu, 0, 7, dpll_param_p->n); ++ /* FREQSEL */ ++ sr32(&prcm_base->clken_pll_mpu, 4, 4, dpll_param_p->fsel); ++ /* lock mode */ ++ sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOCK); ++ wait_on_value(ST_MPU_CLK, 1, &prcm_base->idlest_pll_mpu, LDELAY); ++ ++ /* Getting the base address to IVA DPLL param table */ ++ dpll_param_p = (dpll_param *) get_iva_dpll_param(); ++ ++ /* Moving it to the right sysclk and ES rev base */ ++ dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; ++ ++ /* IVA DPLL (set to 12*20=240MHz) */ ++ sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_STOP); ++ wait_on_value(ST_IVA2_CLK, 0, &prcm_base->idlest_pll_iva2, LDELAY); ++ /* set M2 */ ++ sr32(&prcm_base->clksel2_pll_iva2, 0, 5, dpll_param_p->m2); ++ /* set M */ ++ sr32(&prcm_base->clksel1_pll_iva2, 8, 11, dpll_param_p->m); ++ /* set N */ ++ sr32(&prcm_base->clksel1_pll_iva2, 0, 7, dpll_param_p->n); ++ /* FREQSEL */ ++ sr32(&prcm_base->clken_pll_iva2, 4, 4, dpll_param_p->fsel); ++ /* lock mode */ ++ sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_LOCK); ++ wait_on_value(ST_IVA2_CLK, 1, &prcm_base->idlest_pll_iva2, LDELAY); ++ ++ /* Set up GPTimers to sys_clk source only */ ++ sr32(&prcm_base->clksel_per, 0, 8, 0xff); ++ sr32(&prcm_base->clksel_wkup, 0, 1, 1); ++ ++ sdelay(5000); ++} ++ ++/****************************************************************************** ++ * peripheral_enable() - Enable the clks & power for perifs (GPT2, UART1,...) ++ *****************************************************************************/ ++void per_clocks_enable(void) ++{ ++ prcm_t *prcm_base = (prcm_t *)PRCM_BASE; ++ ++ /* Enable GP2 timer. */ ++ sr32(&prcm_base->clksel_per, 0, 1, 0x1); /* GPT2 = sys clk */ ++ sr32(&prcm_base->iclken_per, 3, 1, 0x1); /* ICKen GPT2 */ ++ sr32(&prcm_base->fclken_per, 3, 1, 0x1); /* FCKen GPT2 */ ++ ++#ifdef CONFIG_SYS_NS16550 ++ /* Enable UART1 clocks */ ++ sr32(&prcm_base->fclken1_core, 13, 1, 0x1); ++ sr32(&prcm_base->iclken1_core, 13, 1, 0x1); ++ ++ /* UART 3 Clocks */ ++ sr32(&prcm_base->fclken_per, 11, 1, 0x1); ++ sr32(&prcm_base->iclken_per, 11, 1, 0x1); ++#endif ++#ifdef CONFIG_DRIVER_OMAP34XX_I2C ++ /* Turn on all 3 I2C clocks */ ++ sr32(&prcm_base->fclken1_core, 15, 3, 0x7); ++ sr32(&prcm_base->iclken1_core, 15, 3, 0x7); /* I2C1,2,3 = on */ ++#endif ++ /* Enable the ICLK for 32K Sync Timer as its used in udelay */ ++ sr32(&prcm_base->iclken_wkup, 2, 1, 0x1); ++ ++ sr32(&prcm_base->fclken_iva2, 0, 32, FCK_IVA2_ON); ++ sr32(&prcm_base->fclken1_core, 0, 32, FCK_CORE1_ON); ++ sr32(&prcm_base->iclken1_core, 0, 32, ICK_CORE1_ON); ++ sr32(&prcm_base->iclken2_core, 0, 32, ICK_CORE2_ON); ++ sr32(&prcm_base->fclken_wkup, 0, 32, FCK_WKUP_ON); ++ sr32(&prcm_base->iclken_wkup, 0, 32, ICK_WKUP_ON); ++ sr32(&prcm_base->fclken_dss, 0, 32, FCK_DSS_ON); ++ sr32(&prcm_base->iclken_dss, 0, 32, ICK_DSS_ON); ++ sr32(&prcm_base->fclken_cam, 0, 32, FCK_CAM_ON); ++ sr32(&prcm_base->iclken_cam, 0, 32, ICK_CAM_ON); ++ sr32(&prcm_base->fclken_per, 0, 32, FCK_PER_ON); ++ sr32(&prcm_base->iclken_per, 0, 32, ICK_PER_ON); ++ ++ sdelay(1000); ++} +diff --git a/cpu/arm_cortexa8/omap3/lowlevel_init.S b/cpu/arm_cortexa8/omap3/lowlevel_init.S +new file mode 100644 +index 0000000..cf1f927 +--- /dev/null ++++ b/cpu/arm_cortexa8/omap3/lowlevel_init.S +@@ -0,0 +1,361 @@ ++/* ++ * Board specific setup info ++ * ++ * (C) Copyright 2008 ++ * Texas Instruments, ++ * ++ * Initial Code by: ++ * Richard Woodruff ++ * Syed Mohammed Khasim ++ * ++ * 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 ++#include ++#include ++#include ++ ++_TEXT_BASE: ++ .word TEXT_BASE /* sdram load addr from config.mk */ ++ ++#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_NAND_BOOT) ++/************************************************************************** ++ * cpy_clk_code: relocates clock code into SRAM where its safer to execute ++ * R1 = SRAM destination address. ++ *************************************************************************/ ++.global cpy_clk_code ++ cpy_clk_code: ++ /* Copy DPLL code into SRAM */ ++ adr r0, go_to_speed /* get addr of clock setting code */ ++ mov r2, #384 /* r2 size to copy (div by 32 bytes) */ ++ mov r1, r1 /* r1 <- dest address (passed in) */ ++ add r2, r2, r0 /* r2 <- source end address */ ++next2: ++ ldmia r0!, {r3 - r10} /* copy from source address [r0] */ ++ stmia r1!, {r3 - r10} /* copy to target address [r1] */ ++ cmp r0, r2 /* until source end address [r2] */ ++ bne next2 ++ mov pc, lr /* back to caller */ ++ ++/* *************************************************************************** ++ * go_to_speed: -Moves to bypass, -Commits clock dividers, -puts dpll at speed ++ * -executed from SRAM. ++ * R0 = CM_CLKEN_PLL-bypass value ++ * R1 = CM_CLKSEL1_PLL-m, n, and divider values ++ * R2 = CM_CLKSEL_CORE-divider values ++ * R3 = CM_IDLEST_CKGEN - addr dpll lock wait ++ * ++ * Note: If core unlocks/relocks and SDRAM is running fast already it gets ++ * confused. A reset of the controller gets it back. Taking away its ++ * L3 when its not in self refresh seems bad for it. Normally, this ++ * code runs from flash before SDR is init so that should be ok. ++ ****************************************************************************/ ++.global go_to_speed ++ go_to_speed: ++ stmfd sp!, {r4 - r6} ++ ++ /* move into fast relock bypass */ ++ ldr r4, pll_ctl_add ++ str r0, [r4] ++wait1: ++ ldr r5, [r3] /* get status */ ++ and r5, r5, #0x1 /* isolate core status */ ++ cmp r5, #0x1 /* still locked? */ ++ beq wait1 /* if lock, loop */ ++ ++ /* set new dpll dividers _after_ in bypass */ ++ ldr r5, pll_div_add1 ++ str r1, [r5] /* set m, n, m2 */ ++ ldr r5, pll_div_add2 ++ str r2, [r5] /* set l3/l4/.. dividers*/ ++ ldr r5, pll_div_add3 /* wkup */ ++ ldr r2, pll_div_val3 /* rsm val */ ++ str r2, [r5] ++ ldr r5, pll_div_add4 /* gfx */ ++ ldr r2, pll_div_val4 ++ str r2, [r5] ++ ldr r5, pll_div_add5 /* emu */ ++ ldr r2, pll_div_val5 ++ str r2, [r5] ++ ++ /* now prepare GPMC (flash) for new dpll speed */ ++ /* flash needs to be stable when we jump back to it */ ++ ldr r5, flash_cfg3_addr ++ ldr r2, flash_cfg3_val ++ str r2, [r5] ++ ldr r5, flash_cfg4_addr ++ ldr r2, flash_cfg4_val ++ str r2, [r5] ++ ldr r5, flash_cfg5_addr ++ ldr r2, flash_cfg5_val ++ str r2, [r5] ++ ldr r5, flash_cfg1_addr ++ ldr r2, [r5] ++ orr r2, r2, #0x3 /* up gpmc divider */ ++ str r2, [r5] ++ ++ /* lock DPLL3 and wait a bit */ ++ orr r0, r0, #0x7 /* set up for lock mode */ ++ str r0, [r4] /* lock */ ++ nop /* ARM slow at this point working at sys_clk */ ++ nop ++ nop ++ nop ++wait2: ++ ldr r5, [r3] /* get status */ ++ and r5, r5, #0x1 /* isolate core status */ ++ cmp r5, #0x1 /* still locked? */ ++ bne wait2 /* if lock, loop */ ++ nop ++ nop ++ nop ++ nop ++ ldmfd sp!, {r4 - r6} ++ mov pc, lr /* back to caller, locked */ ++ ++_go_to_speed: .word go_to_speed ++ ++/* these constants need to be close for PIC code */ ++/* The Nor has to be in the Flash Base CS0 for this condition to happen */ ++flash_cfg1_addr: ++ .word (GPMC_CONFIG_CS0 + GPMC_CONFIG1) ++flash_cfg3_addr: ++ .word (GPMC_CONFIG_CS0 + GPMC_CONFIG3) ++flash_cfg3_val: ++ .word STNOR_GPMC_CONFIG3 ++flash_cfg4_addr: ++ .word (GPMC_CONFIG_CS0 + GPMC_CONFIG4) ++flash_cfg4_val: ++ .word STNOR_GPMC_CONFIG4 ++flash_cfg5_val: ++ .word STNOR_GPMC_CONFIG5 ++flash_cfg5_addr: ++ .word (GPMC_CONFIG_CS0 + GPMC_CONFIG5) ++pll_ctl_add: ++ .word CM_CLKEN_PLL ++pll_div_add1: ++ .word CM_CLKSEL1_PLL ++pll_div_add2: ++ .word CM_CLKSEL_CORE ++pll_div_add3: ++ .word CM_CLKSEL_WKUP ++pll_div_val3: ++ .word (WKUP_RSM << 1) ++pll_div_add4: ++ .word CM_CLKSEL_GFX ++pll_div_val4: ++ .word (GFX_DIV << 0) ++pll_div_add5: ++ .word CM_CLKSEL1_EMU ++pll_div_val5: ++ .word CLSEL1_EMU_VAL ++ ++#endif ++ ++.globl lowlevel_init ++lowlevel_init: ++ ldr sp, SRAM_STACK ++ str ip, [sp] /* stash old link register */ ++ mov ip, lr /* save link reg across call */ ++ bl s_init /* go setup pll, mux, memory */ ++ ldr ip, [sp] /* restore save ip */ ++ mov lr, ip /* restore link reg */ ++ ++ /* back to arch calling code */ ++ mov pc, lr ++ ++ /* the literal pools origin */ ++ .ltorg ++ ++REG_CONTROL_STATUS: ++ .word CONTROL_STATUS ++SRAM_STACK: ++ .word LOW_LEVEL_SRAM_STACK ++ ++/* DPLL(1-4) PARAM TABLES */ ++ ++/* ++ * Each of the tables has M, N, FREQSEL, M2 values defined for nominal ++ * OPP (1.2V). The fields are defined according to dpll_param struct (clock.c). ++ * The values are defined for all possible sysclk and for ES1 and ES2. ++ */ ++ ++mpu_dpll_param: ++/* 12MHz */ ++/* ES1 */ ++.word MPU_M_12_ES1, MPU_N_12_ES1, MPU_FSEL_12_ES1, MPU_M2_12_ES1 ++/* ES2 */ ++.word MPU_M_12_ES2, MPU_N_12_ES2, MPU_FSEL_12_ES2, MPU_M2_ES2 ++/* 3410 */ ++.word MPU_M_12, MPU_N_12, MPU_FSEL_12, MPU_M2_12 ++ ++/* 13MHz */ ++/* ES1 */ ++.word MPU_M_13_ES1, MPU_N_13_ES1, MPU_FSEL_13_ES1, MPU_M2_13_ES1 ++/* ES2 */ ++.word MPU_M_13_ES2, MPU_N_13_ES2, MPU_FSEL_13_ES2, MPU_M2_13_ES2 ++/* 3410 */ ++.word MPU_M_13, MPU_N_13, MPU_FSEL_13, MPU_M2_13 ++ ++/* 19.2MHz */ ++/* ES1 */ ++.word MPU_M_19P2_ES1, MPU_N_19P2_ES1, MPU_FSEL_19P2_ES1, MPU_M2_19P2_ES1 ++/* ES2 */ ++.word MPU_M_19P2_ES2, MPU_N_19P2_ES2, MPU_FSEL_19P2_ES2, MPU_M2_19P2_ES2 ++/* 3410 */ ++.word MPU_M_19P2, MPU_N_19P2, MPU_FSEL_19P2, MPU_M2_19P2 ++ ++/* 26MHz */ ++/* ES1 */ ++.word MPU_M_26_ES1, MPU_N_26_ES1, MPU_FSEL_26_ES1, MPU_M2_26_ES1 ++/* ES2 */ ++.word MPU_M_26_ES2, MPU_N_26_ES2, MPU_FSEL_26_ES2, MPU_M2_26_ES2 ++/* 3410 */ ++.word MPU_M_26, MPU_N_26, MPU_FSEL_26, MPU_M2_26 ++ ++/* 38.4MHz */ ++/* ES1 */ ++.word MPU_M_38P4_ES1, MPU_N_38P4_ES1, MPU_FSEL_38P4_ES1, MPU_M2_38P4_ES1 ++/* ES2 */ ++.word MPU_M_38P4_ES2, MPU_N_38P4_ES2, MPU_FSEL_38P4_ES2, MPU_M2_38P4_ES2 ++/* 3410 */ ++.word MPU_M_38P4, MPU_N_38P4, MPU_FSEL_38P4, MPU_M2_38P4 ++ ++ ++.globl get_mpu_dpll_param ++get_mpu_dpll_param: ++ adr r0, mpu_dpll_param ++ mov pc, lr ++ ++iva_dpll_param: ++/* 12MHz */ ++/* ES1 */ ++.word IVA_M_12_ES1, IVA_N_12_ES1, IVA_FSEL_12_ES1, IVA_M2_12_ES1 ++/* ES2 */ ++.word IVA_M_12_ES2, IVA_N_12_ES2, IVA_FSEL_12_ES2, IVA_M2_12_ES2 ++/* 3410 */ ++.word IVA_M_12, IVA_N_12, IVA_FSEL_12, IVA_M2_12 ++ ++/* 13MHz */ ++/* ES1 */ ++.word IVA_M_13_ES1, IVA_N_13_ES1, IVA_FSEL_13_ES1, IVA_M2_13_ES1 ++/* ES2 */ ++.word IVA_M_13_ES2, IVA_N_13_ES2, IVA_FSEL_13_ES2, IVA_M2_13_ES2 ++/* 3410 */ ++.word IVA_M_13, IVA_N_13, IVA_FSEL_13, IVA_M2_13 ++ ++/* 19.2MHz */ ++/* ES1 */ ++.word IVA_M_19P2_ES1, IVA_N_19P2_ES1, IVA_FSEL_19P2_ES1, IVA_M2_19P2_ES1 ++/* ES2 */ ++.word IVA_M_19P2_ES2, IVA_N_19P2_ES2, IVA_FSEL_19P2_ES2, IVA_M2_19P2_ES2 ++/* 3410 */ ++.word IVA_M_19P2, IVA_N_19P2, IVA_FSEL_19P2, IVA_M2_19P2 ++ ++/* 26MHz */ ++/* ES1 */ ++.word IVA_M_26_ES1, IVA_N_26_ES1, IVA_FSEL_26_ES1, IVA_M2_26_ES1 ++/* ES2 */ ++.word IVA_M_26_ES2, IVA_N_26_ES2, IVA_FSEL_26_ES2, IVA_M2_26_ES2 ++/* 3410 */ ++.word IVA_M_26, IVA_N_26, IVA_FSEL_26, IVA_M2_26 ++ ++/* 38.4MHz */ ++/* ES1 */ ++.word IVA_M_38P4_ES1, IVA_N_38P4_ES1, IVA_FSEL_38P4_ES1, IVA_M2_38P4_ES1 ++/* ES2 */ ++.word IVA_M_38P4_ES2, IVA_N_38P4_ES2, IVA_FSEL_38P4_ES2, IVA_M2_38P4_ES2 ++/* 3410 */ ++.word IVA_M_38P4, IVA_N_38P4, IVA_FSEL_38P4, IVA_M2_38P4 ++ ++ ++.globl get_iva_dpll_param ++get_iva_dpll_param: ++ adr r0, iva_dpll_param ++ mov pc, lr ++ ++/* Core DPLL targets for L3 at 166 & L133 */ ++core_dpll_param: ++/* 12MHz */ ++/* ES1 */ ++.word CORE_M_12_ES1, CORE_N_12_ES1, CORE_FSL_12_ES1, CORE_M2_12_ES1 ++/* ES2 */ ++.word CORE_M_12, CORE_N_12, CORE_FSEL_12, CORE_M2_12 ++/* 3410 */ ++.word CORE_M_12, CORE_N_12, CORE_FSEL_12, CORE_M2_12 ++ ++/* 13MHz */ ++/* ES1 */ ++.word CORE_M_13_ES1, CORE_N_13_ES1, CORE_FSL_13_ES1, CORE_M2_13_ES1 ++/* ES2 */ ++.word CORE_M_13, CORE_N_13, CORE_FSEL_13, CORE_M2_13 ++/* 3410 */ ++.word CORE_M_13, CORE_N_13, CORE_FSEL_13, CORE_M2_13 ++ ++/* 19.2MHz */ ++/* ES1 */ ++.word CORE_M_19P2_ES1, CORE_N_19P2_ES1, CORE_FSL_19P2_ES1, CORE_M2_19P2_ES1 ++/* ES2 */ ++.word CORE_M_19P2, CORE_N_19P2, CORE_FSEL_19P2, CORE_M2_19P2 ++/* 3410 */ ++.word CORE_M_19P2, CORE_N_19P2, CORE_FSEL_19P2, CORE_M2_19P2 ++ ++/* 26MHz */ ++/* ES1 */ ++.word CORE_M_26_ES1, CORE_N_26_ES1, CORE_FSL_26_ES1, CORE_M2_26_ES1 ++/* ES2 */ ++.word CORE_M_26, CORE_N_26, CORE_FSEL_26, CORE_M2_26 ++/* 3410 */ ++.word CORE_M_26, CORE_N_26, CORE_FSEL_26, CORE_M2_26 ++ ++/* 38.4MHz */ ++/* ES1 */ ++.word CORE_M_38P4_ES1, CORE_N_38P4_ES1, CORE_FSL_38P4_ES1, CORE_M2_38P4_ES1 ++/* ES2 */ ++.word CORE_M_38P4, CORE_N_38P4, CORE_FSEL_38P4, CORE_M2_38P4 ++/* 3410 */ ++.word CORE_M_38P4, CORE_N_38P4, CORE_FSEL_38P4, CORE_M2_38P4 ++ ++.globl get_core_dpll_param ++get_core_dpll_param: ++ adr r0, core_dpll_param ++ mov pc, lr ++ ++/* PER DPLL values are same for both ES1 and ES2 */ ++per_dpll_param: ++/* 12MHz */ ++.word PER_M_12, PER_N_12, PER_FSEL_12, PER_M2_12 ++ ++/* 13MHz */ ++.word PER_M_13, PER_N_13, PER_FSEL_13, PER_M2_13 ++ ++/* 19.2MHz */ ++.word PER_M_19P2, PER_N_19P2, PER_FSEL_19P2, PER_M2_19P2 ++ ++/* 26MHz */ ++.word PER_M_26, PER_N_26, PER_FSEL_26, PER_M2_26 ++ ++/* 38.4MHz */ ++.word PER_M_38P4, PER_N_38P4, PER_FSEL_38P4, PER_M2_38P4 ++ ++.globl get_per_dpll_param ++get_per_dpll_param: ++ adr r0, per_dpll_param ++ mov pc, lr +diff --git a/cpu/arm_cortexa8/omap3/mem.c b/cpu/arm_cortexa8/omap3/mem.c +new file mode 100644 +index 0000000..3cc22c4 +--- /dev/null ++++ b/cpu/arm_cortexa8/omap3/mem.c +@@ -0,0 +1,284 @@ ++/* ++ * (C) Copyright 2008 ++ * Texas Instruments, ++ * ++ * Author : ++ * Manikandan Pillai ++ * ++ * Initial Code from: ++ * Richard Woodruff ++ * Syed Mohammed Khasim ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++/* ++ * Only One NAND allowed on board at a time. ++ * The GPMC CS Base for the same ++ */ ++unsigned int boot_flash_base; ++unsigned int boot_flash_off; ++unsigned int boot_flash_sec; ++unsigned int boot_flash_type; ++volatile unsigned int boot_flash_env_addr; ++ ++#if defined(CONFIG_CMD_NAND) ++static u32 gpmc_m_nand[GPMC_MAX_REG] = { ++ M_NAND_GPMC_CONFIG1, ++ M_NAND_GPMC_CONFIG2, ++ M_NAND_GPMC_CONFIG3, ++ M_NAND_GPMC_CONFIG4, ++ M_NAND_GPMC_CONFIG5, ++ M_NAND_GPMC_CONFIG6, 0 ++}; ++ ++gpmc_csx_t *nand_cs_base; ++gpmc_t *gpmc_cfg_base; ++ ++#if defined(CONFIG_ENV_IS_IN_NAND) ++#define GPMC_CS 0 ++#else ++#define GPMC_CS 1 ++#endif ++ ++#endif ++ ++#if defined(CONFIG_CMD_ONENAND) ++static u32 gpmc_onenand[GPMC_MAX_REG] = { ++ ONENAND_GPMC_CONFIG1, ++ ONENAND_GPMC_CONFIG2, ++ ONENAND_GPMC_CONFIG3, ++ ONENAND_GPMC_CONFIG4, ++ ONENAND_GPMC_CONFIG5, ++ ONENAND_GPMC_CONFIG6, 0 ++}; ++ ++gpmc_csx_t *onenand_cs_base; ++ ++#if defined(CONFIG_ENV_IS_IN_ONENAND) ++#define GPMC_CS 0 ++#else ++#define GPMC_CS 1 ++#endif ++ ++#endif ++ ++static sdrc_t *sdrc_base = (sdrc_t *)OMAP34XX_SDRC_BASE; ++ ++/************************************************************************** ++ * make_cs1_contiguous() - for es2 and above remap cs1 behind cs0 to allow ++ * command line mem=xyz use all memory with out discontinuous support ++ * compiled in. Could do it at the ATAG, but there really is two banks... ++ * Called as part of 2nd phase DDR init. ++ **************************************************************************/ ++void make_cs1_contiguous(void) ++{ ++ u32 size, a_add_low, a_add_high; ++ ++ size = get_sdr_cs_size(CS0); ++ size /= SZ_32M; /* find size to offset CS1 */ ++ a_add_high = (size & 3) << 8; /* set up low field */ ++ a_add_low = (size & 0x3C) >> 2; /* set up high field */ ++ writel((a_add_high | a_add_low), &sdrc_base->cs_cfg); ++ ++} ++ ++/******************************************************** ++ * mem_ok() - test used to see if timings are correct ++ * for a part. Helps in guessing which part ++ * we are currently using. ++ *******************************************************/ ++u32 mem_ok(u32 cs) ++{ ++ u32 val1, val2, addr; ++ u32 pattern = 0x12345678; ++ ++ addr = OMAP34XX_SDRC_CS0 + get_sdr_cs_offset(cs); ++ ++ writel(0x0, addr + 0x400); /* clear pos A */ ++ writel(pattern, addr); /* pattern to pos B */ ++ writel(0x0, addr + 4); /* remove pattern off the bus */ ++ val1 = readl(addr + 0x400); /* get pos A value */ ++ val2 = readl(addr); /* get val2 */ ++ ++ if ((val1 != 0) || (val2 != pattern)) /* see if pos A val changed */ ++ return 0; ++ else ++ return 1; ++} ++ ++/******************************************************** ++ * sdrc_init() - init the sdrc chip selects CS0 and CS1 ++ * - early init routines, called from flash or ++ * SRAM. ++ *******************************************************/ ++void sdrc_init(void) ++{ ++ /* only init up first bank here */ ++ do_sdrc_init(CS0, EARLY_INIT); ++} ++ ++/************************************************************************* ++ * do_sdrc_init(): initialize the SDRAM for use. ++ * -code sets up SDRAM basic SDRC timings for CS0 ++ * -optimal settings can be placed here, or redone after i2c ++ * inspection of board info ++ * ++ * - code called once in C-Stack only context for CS0 and a possible 2nd ++ * time depending on memory configuration from stack+global context ++ **************************************************************************/ ++ ++void do_sdrc_init(u32 cs, u32 early) ++{ ++ sdrc_actim_t *sdrc_actim_base; ++ ++ if(cs) ++ sdrc_actim_base = (sdrc_actim_t *)SDRC_ACTIM_CTRL1_BASE; ++ else ++ sdrc_actim_base = (sdrc_actim_t *)SDRC_ACTIM_CTRL0_BASE; ++ ++ if (early) { ++ /* reset sdrc controller */ ++ writel(SOFTRESET, &sdrc_base->sysconfig); ++ wait_on_value(RESETDONE, RESETDONE, &sdrc_base->status, ++ 12000000); ++ writel(0, &sdrc_base->sysconfig); ++ ++ /* setup sdrc to ball mux */ ++ writel(SDP_SDRC_SHARING, &sdrc_base->sharing); ++ ++ /* Disable Power Down of CKE cuz of 1 CKE on combo part */ ++ writel(SRFRONRESET | PAGEPOLICY_HIGH, &sdrc_base->power); ++ ++ writel(ENADLL | DLLPHASE_90, &sdrc_base->dlla_ctrl); ++ sdelay(0x20000); ++ } ++ ++ writel(RASWIDTH_13BITS | CASWIDTH_10BITS | ADDRMUXLEGACY | ++ RAMSIZE_128 | BANKALLOCATION | B32NOT16 | B32NOT16 | ++ DEEPPD | DDR_SDRAM, &sdrc_base->cs[cs].mcfg); ++ writel(ARCV | ARE_ARCV_1, &sdrc_base->cs[cs].rfr_ctrl); ++ writel(V_ACTIMA_165, &sdrc_actim_base->ctrla); ++ writel(V_ACTIMB_165, &sdrc_actim_base->ctrlb); ++ ++ writel(CMD_NOP, &sdrc_base ->cs[cs].manual); ++ writel(CMD_PRECHARGE, &sdrc_base->cs[cs].manual); ++ writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual); ++ writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual); ++ ++ /* ++ * CAS latency 3, Write Burst = Read Burst, Serial Mode, ++ * Burst length = 4 ++ */ ++ writel(CASL3 | BURSTLENGTH4, &sdrc_base->cs[cs].mr); ++ ++ if (!mem_ok(cs)) ++ writel(0, &sdrc_base->cs[cs].mcfg); ++} ++ ++void enable_gpmc_config(u32 *gpmc_config, gpmc_csx_t *gpmc_cs_base, u32 base, ++ u32 size) ++{ ++ writel(0, &gpmc_cs_base->config7); ++ sdelay(1000); ++ /* Delay for settling */ ++ writel(gpmc_config[0], &gpmc_cs_base->config1); ++ writel(gpmc_config[1], &gpmc_cs_base->config2); ++ writel(gpmc_config[2], &gpmc_cs_base->config3); ++ writel(gpmc_config[3], &gpmc_cs_base->config4); ++ writel(gpmc_config[4], &gpmc_cs_base->config5); ++ writel(gpmc_config[5], &gpmc_cs_base->config6); ++ /* Enable the config */ ++ writel((((size & 0xF) << 8) | ((base >> 24) & 0x3F) | ++ (1 << 6)), &gpmc_cs_base->config7); ++ sdelay(2000); ++} ++ ++/***************************************************** ++ * gpmc_init(): init gpmc bus ++ * Init GPMC for x16, MuxMode (SDRAM in x32). ++ * This code can only be executed from SRAM or SDRAM. ++ *****************************************************/ ++void gpmc_init(void) ++{ ++ /* putting a blanket check on GPMC based on ZeBu for now */ ++ u32 *gpmc_config = NULL; ++ gpmc_t *gpmc_base = (gpmc_t *)GPMC_BASE; ++ gpmc_csx_t *gpmc_cs_base = (gpmc_csx_t *)GPMC_CONFIG_CS0_BASE; ++ u32 base = 0; ++ u32 size = 0; ++ u32 f_off = CONFIG_SYS_MONITOR_LEN; ++ u32 f_sec = 0; ++ u32 config = 0; ++ ++ /* global settings */ ++ writel(0, &gpmc_base->irqenable); /* isr's sources masked */ ++ writel(0, &gpmc_base->timeout_control);/* timeout disable */ ++ ++ config = readl(&gpmc_base->config); ++ config &= (~0xf00); ++ writel(config, &gpmc_base->config); ++ ++ /* ++ * Disable the GPMC0 config set by ROM code ++ * It conflicts with our MPDB (both at 0x08000000) ++ */ ++ writel(0, &gpmc_cs_base->config7); ++ sdelay(1000); ++ ++#if defined(CONFIG_CMD_NAND) /* CS 0 */ ++ gpmc_config = gpmc_m_nand; ++ gpmc_cfg_base = gpmc_base; ++ nand_cs_base = (gpmc_csx_t *)(GPMC_CONFIG_CS0_BASE + ++ (GPMC_CS * GPMC_CONFIG_WIDTH)); ++ base = PISMO1_NAND_BASE; ++ size = PISMO1_NAND_SIZE; ++ enable_gpmc_config(gpmc_config, nand_cs_base, base, size); ++#if defined(CONFIG_ENV_IS_IN_NAND) ++ f_off = SMNAND_ENV_OFFSET; ++ f_sec = SZ_128K; ++ /* env setup */ ++ boot_flash_base = base; ++ boot_flash_off = f_off; ++ boot_flash_sec = f_sec; ++ boot_flash_env_addr = f_off; ++#endif ++#endif ++ ++#if defined(CONFIG_CMD_ONENAND) ++ gpmc_config = gpmc_onenand; ++ onenand_cs_base = (gpmc_csx_t *)(GPMC_CONFIG_CS0_BASE + ++ (GPMC_CS * GPMC_CONFIG_WIDTH)); ++ base = PISMO1_ONEN_BASE; ++ size = PISMO1_ONEN_SIZE; ++ enable_gpmc_config(gpmc_config, onenand_cs_base, base, size); ++#if defined(CONFIG_ENV_IS_IN_ONENAND) ++ f_off = ONENAND_ENV_OFFSET; ++ f_sec = SZ_128K; ++ /* env setup */ ++ boot_flash_base = base; ++ boot_flash_off = f_off; ++ boot_flash_sec = f_sec; ++ boot_flash_env_addr = f_off; ++#endif ++#endif ++} +diff --git a/cpu/arm_cortexa8/omap3/syslib.c b/cpu/arm_cortexa8/omap3/syslib.c +new file mode 100644 +index 0000000..9ced495 +--- /dev/null ++++ b/cpu/arm_cortexa8/omap3/syslib.c +@@ -0,0 +1,72 @@ ++/* ++ * (C) Copyright 2008 ++ * Texas Instruments, ++ * ++ * Richard Woodruff ++ * Syed Mohammed Khasim ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++/************************************************************ ++ * sdelay() - simple spin loop. Will be constant time as ++ * its generally used in bypass conditions only. This ++ * is necessary until timers are accessible. ++ * ++ * not inline to increase chances its in cache when called ++ *************************************************************/ ++void sdelay(unsigned long loops) ++{ ++ __asm__ volatile ("1:\n" "subs %0, %1, #1\n" ++ "bne 1b":"=r" (loops):"0"(loops)); ++} ++ ++/***************************************************************** ++ * sr32 - clear & set a value in a bit range for a 32 bit address ++ *****************************************************************/ ++void sr32(void *addr, u32 start_bit, u32 num_bits, u32 value) ++{ ++ u32 tmp, msk = 0; ++ msk = 1 << num_bits; ++ --msk; ++ tmp = readl((u32)addr) & ~(msk << start_bit); ++ tmp |= value << start_bit; ++ writel(tmp, (u32)addr); ++} ++ ++/********************************************************************* ++ * wait_on_value() - common routine to allow waiting for changes in ++ * volatile regs. ++ *********************************************************************/ ++u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr, ++ u32 bound) ++{ ++ u32 i = 0, val; ++ do { ++ ++i; ++ val = readl((u32)read_addr) & read_bit_mask; ++ if (val == match_value) ++ return 1; ++ if (i == bound) ++ return 0; ++ } while (1); ++} +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0022-ENGR00113439-BBG2-enable-SPI-NOR-and-MMC-in-one-im.patch +++ uboot-imx-2009.01/debian/patches/0022-ENGR00113439-BBG2-enable-SPI-NOR-and-MMC-in-one-im.patch @@ -0,0 +1,173 @@ +From bea1987d05758a4c79690c248799c1c0bd87c0e2 Mon Sep 17 00:00:00 2001 +From: Terry Lv +Date: Wed, 17 Jun 2009 18:46:13 +0800 +Subject: [PATCH] ENGR00113439: BBG2, enable SPI NOR and MMC in one image. + +BBG2, enable SPI NOR and MMC in one image. + +Signed-off-by: Terry Lv +--- + board/freescale/imx51/imx51.c | 1 - + drivers/mtd/spi/imx_spi_nor.c | 16 +++++++++++----- + include/asm-arm/arch-mx51/imx_spi_pmic.h | 6 +++--- + include/configs/imx51.h | 16 ++++++---------- + 4 files changed, 20 insertions(+), 19 deletions(-) + +diff --git a/board/freescale/imx51/imx51.c b/board/freescale/imx51/imx51.c +index 793afa2..b0bbf46 100644 +--- a/board/freescale/imx51/imx51.c ++++ b/board/freescale/imx51/imx51.c +@@ -258,7 +258,6 @@ int board_eth_init(bd_t *bis) + int sdhc_init(void) + { + u32 interface_esdhc = 0; +- u32 pad_val = 0; + s32 status = 0; + + interface_esdhc = (readl(SRC_BASE_ADDR + 0x4) & (0x00180000)) >> 19; +diff --git a/drivers/mtd/spi/imx_spi_nor.c b/drivers/mtd/spi/imx_spi_nor.c +index a912a3f..bd10ca4 100644 +--- a/drivers/mtd/spi/imx_spi_nor.c ++++ b/drivers/mtd/spi/imx_spi_nor.c +@@ -230,6 +230,8 @@ static int spi_nor_flash_read(struct spi_flash *flash, u32 offset, + if (!(flash->spi)) + return -1; + ++ printf("Reading SPI NOR flash 0x%x [0x%x bytes] -> ram 0x%p\n", ++ offset, len, buf); + debug("%s(from flash=0x%08x to ram=%p len=0x%x)\n", + __func__, + offset, buf, len); +@@ -271,7 +273,7 @@ static int spi_nor_flash_read(struct spi_flash *flash, u32 offset, + *d_buf++ = s_buf[1]; + *d_buf++ = s_buf[0]; + } +- printf("\n"); ++ printf("SUCCESS\n\n"); + return 0; + } + /* copy 4 bytes */ +@@ -302,7 +304,7 @@ static int spi_nor_flash_read(struct spi_flash *flash, u32 offset, + if ((s32remain_size % imx_sf->params->block_size) == 0) + printf("."); + } +- printf("\n"); ++ printf("SUCCESS\n\n"); + + return -1; + } +@@ -321,6 +323,8 @@ static int spi_nor_flash_write(struct spi_flash *flash, u32 offset, + if (len == 0) + return 0; + ++ printf("Writing SPI NOR flash 0x%x [0x%x bytes] <- ram 0x%p\n", ++ offset, len, buf); + debug("%s(flash addr=0x%08x, ram=%p, len=0x%x)\n", + __func__, offset, buf, len); + +@@ -395,7 +399,7 @@ static int spi_nor_flash_write(struct spi_flash *flash, u32 offset, + if ((s32remain_size % imx_sf->params->block_size) == 0) + printf("."); + } +- printf("\n"); ++ printf("SUCCESS\n\n"); + debug("100%% transferred\n"); + + WRITE_DISABLE(flash); +@@ -423,12 +427,14 @@ static int spi_nor_flash_write(struct spi_flash *flash, u32 offset, + static int spi_nor_flash_erase(struct spi_flash *flash, u32 offset, + size_t len) + { +- struct imx_spi_flash *imx_sf = to_imx_spi_flash(flash); + s32 s32remain_size = len; + + if (!(flash->spi)) + return -1; + ++ printf("Erasing SPI NOR flash 0x%x [0x%x bytes]\n", ++ offset, len); ++ + if ((len % SZ_4K) != 0 || len == 0) { + printf("Error: size (0x%x) is not integer multiples of 4kB(0x1000)\n", + len); +@@ -450,7 +456,7 @@ static int spi_nor_flash_erase(struct spi_flash *flash, u32 offset, + } + printf("."); + } +- printf("\n"); ++ printf("SUCCESS\n\n"); + debug("100%% erased\n"); + return 0; + } +diff --git a/include/asm-arm/arch-mx51/imx_spi_pmic.h b/include/asm-arm/arch-mx51/imx_spi_pmic.h +index 1c32a9e..acd8cbf 100644 +--- a/include/asm-arm/arch-mx51/imx_spi_pmic.h ++++ b/include/asm-arm/arch-mx51/imx_spi_pmic.h +@@ -25,9 +25,9 @@ + + #include + +-struct spi_slave *spi_pmic_probe(); +-void spi_pmic_free(struct spi_slave *slave); +-u32 pmic_reg(struct spi_slave *slave, ++extern struct spi_slave *spi_pmic_probe(); ++extern void spi_pmic_free(struct spi_slave *slave); ++extern u32 pmic_reg(struct spi_slave *slave, + u32 reg, u32 val, u32 write); + + #endif /* _IMX_SPI_PMIC_H_ */ +diff --git a/include/configs/imx51.h b/include/configs/imx51.h +index 238457e..7bd6c38 100644 +--- a/include/configs/imx51.h ++++ b/include/configs/imx51.h +@@ -68,10 +68,9 @@ + #define CONFIG_MX51_UART 1 + #define CONFIG_MX51_UART1 1 + +-#if defined(BOOT_MEDIA_SPI_NOR) + /* + * SPI Configs +- */ ++ * */ + #define CONFIG_FSL_SF 1 + #define CONFIG_CMD_SPI + #define CONFIG_CMD_SF +@@ -80,18 +79,19 @@ + #define CONFIG_IMX_SPI + #define CONFIG_IMX_SPI_PMIC + #define CONFIG_IMX_SPI_PMIC_CS 0 ++ + #define MAX_SPI_BYTES (64 * 4) + +-#elif defined(BOOT_MEDIA_MMC) + /* + * MMC Configs +- */ ++ * */ + #define CONFIG_FSL_MMC 1 ++ ++#define CONFIG_MMC 1 ++#define CONFIG_CMD_MMC + #define CONFIG_DOS_PARTITION 1 + #define CONFIG_CMD_FAT 1 + +-#endif +- + /* allow to overwrite serial and ethaddr */ + #define CONFIG_ENV_OVERWRITE + #define CONFIG_CONS_INDEX 1 +@@ -208,11 +208,7 @@ + #if defined(CONFIG_FSL_SF) + #define CONFIG_FSL_ENV_IN_SF + #elif defined(CONFIG_FSL_MMC) +- #define CONFIG_MMC 1 +- #define CONFIG_CMD_MMC +-/* + #define CONFIG_FSL_ENV_IN_MMC +-*/ + #elif defined(CONFIG_CMD_NAND) + #define CONFIG_FSL_ENV_IN_NAND + #endif +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0010-OMAP3-Add-common-cpu-and-start-code.patch +++ uboot-imx-2009.01/debian/patches/0010-OMAP3-Add-common-cpu-and-start-code.patch @@ -0,0 +1,981 @@ +From d1cce6ea3ede97440bddb0910ecbf3b050a43fcf Mon Sep 17 00:00:00 2001 +From: Dirk Behme +Date: Sun, 14 Dec 2008 09:47:13 +0100 +Subject: [PATCH] OMAP3: Add common cpu and start code + +Add common cpu and start code. + +Signed-off-by: Dirk Behme +(cherry picked from commit 0b02b184003e6a5023e05d5f31de54db279b1431) +--- + cpu/arm_cortexa8/Makefile | 47 ++++ + cpu/arm_cortexa8/config.mk | 36 +++ + cpu/arm_cortexa8/cpu.c | 241 ++++++++++++++++++ + cpu/arm_cortexa8/omap3/Makefile | 46 ++++ + cpu/arm_cortexa8/omap3/config.mk | 36 +++ + cpu/arm_cortexa8/start.S | 516 ++++++++++++++++++++++++++++++++++++++ + 6 files changed, 922 insertions(+), 0 deletions(-) + +diff --git a/cpu/arm_cortexa8/Makefile b/cpu/arm_cortexa8/Makefile +new file mode 100644 +index 0000000..ae20299 +--- /dev/null ++++ b/cpu/arm_cortexa8/Makefile +@@ -0,0 +1,47 @@ ++# ++# (C) Copyright 2000-2003 ++# 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$(CPU).a ++ ++START := start.o ++COBJS := cpu.o ++ ++SRCS := $(START:.o=.S) $(COBJS:.o=.c) ++OBJS := $(addprefix $(obj),$(COBJS)) ++START := $(addprefix $(obj),$(START)) ++ ++all: $(obj).depend $(START) $(LIB) ++ ++$(LIB): $(OBJS) ++ $(AR) $(ARFLAGS) $@ $(OBJS) ++ ++######################################################################### ++ ++# defines $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +\ No newline at end of file +diff --git a/cpu/arm_cortexa8/config.mk b/cpu/arm_cortexa8/config.mk +new file mode 100644 +index 0000000..b021762 +--- /dev/null ++++ b/cpu/arm_cortexa8/config.mk +@@ -0,0 +1,36 @@ ++# ++# (C) Copyright 2002 ++# Gary Jennejohn, 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 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 ++# ++PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ ++ -msoft-float ++ ++# Make ARMv5 to allow more compilers to work, even though its v7a. ++PLATFORM_CPPFLAGS += -march=armv5 ++# ========================================================================= ++# ++# Supply options according to compiler version ++# ++# ========================================================================= ++PLATFORM_CPPFLAGS +=$(call cc-option) ++PLATFORM_CPPFLAGS +=$(call cc-option,-mno-thumb-interwork,) ++PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,\ ++ $(call cc-option,-malignment-traps,)) +\ No newline at end of file +diff --git a/cpu/arm_cortexa8/cpu.c b/cpu/arm_cortexa8/cpu.c +new file mode 100644 +index 0000000..ebc5ea2 +--- /dev/null ++++ b/cpu/arm_cortexa8/cpu.c +@@ -0,0 +1,241 @@ ++/* ++ * (C) Copyright 2008 Texas Insturments ++ * ++ * (C) Copyright 2002 ++ * Sysgo Real-Time Solutions, GmbH ++ * Marius Groeger ++ * ++ * (C) Copyright 2002 ++ * Gary Jennejohn, 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 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 ++ */ ++ ++/* ++ * CPU specific code ++ */ ++ ++#include ++#include ++#include ++ ++#ifdef CONFIG_USE_IRQ ++DECLARE_GLOBAL_DATA_PTR; ++#endif ++ ++#ifndef CONFIG_L2_OFF ++void l2cache_disable(void); ++#endif ++ ++static void cache_flush(void); ++ ++/* read co-processor 15, register #1 (control register) */ ++static unsigned long read_p15_c1(void) ++{ ++ unsigned long value; ++ ++ __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 0\ ++ @ read control reg\n":"=r"(value) ++ ::"memory"); ++ return value; ++} ++ ++/* write to co-processor 15, register #1 (control register) */ ++static void write_p15_c1(unsigned long value) ++{ ++ __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 0\ ++ @ write it back\n"::"r"(value) ++ : "memory"); ++ ++ read_p15_c1(); ++} ++ ++static void cp_delay(void) ++{ ++ /* Many OMAP regs need at least 2 nops */ ++ asm("nop"); ++ asm("nop"); ++} ++ ++/* See also ARM Ref. Man. */ ++#define C1_MMU (1<<0) /* mmu off/on */ ++#define C1_ALIGN (1<<1) /* alignment faults off/on */ ++#define C1_DC (1<<2) /* dcache off/on */ ++#define C1_WB (1<<3) /* merging write buffer on/off */ ++#define C1_BIG_ENDIAN (1<<7) /* big endian off/on */ ++#define C1_SYS_PROT (1<<8) /* system protection */ ++#define C1_ROM_PROT (1<<9) /* ROM protection */ ++#define C1_IC (1<<12) /* icache off/on */ ++#define C1_HIGH_VECTORS (1<<13) /* location of vectors: low/high addresses */ ++#define RESERVED_1 (0xf << 3) /* must be 111b for R/W */ ++ ++int cpu_init(void) ++{ ++ /* ++ * setup up stacks if necessary ++ */ ++#ifdef CONFIG_USE_IRQ ++ IRQ_STACK_START = ++ _armboot_start - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_GBL_DATA_SIZE - 4; ++ FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; ++#endif ++ return 0; ++} ++ ++int cleanup_before_linux(void) ++{ ++ unsigned int i; ++ ++ /* ++ * this function is called just before we call linux ++ * it prepares the processor for linux ++ * ++ * we turn off caches etc ... ++ */ ++ disable_interrupts(); ++ ++ /* turn off I/D-cache */ ++ icache_disable(); ++ dcache_disable(); ++ ++ /* invalidate I-cache */ ++ cache_flush(); ++ ++#ifndef CONFIG_L2_OFF ++ /* turn off L2 cache */ ++ l2cache_disable(); ++ /* invalidate L2 cache also */ ++ v7_flush_dcache_all(get_device_type()); ++#endif ++ i = 0; ++ /* mem barrier to sync up things */ ++ asm("mcr p15, 0, %0, c7, c10, 4": :"r"(i)); ++ ++#ifndef CONFIG_L2_OFF ++ l2cache_enable(); ++#endif ++ ++ return 0; ++} ++ ++int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ++{ ++ disable_interrupts(); ++ reset_cpu(0); ++ ++ /* NOTREACHED */ ++ return 0; ++} ++ ++void icache_enable(void) ++{ ++ ulong reg; ++ ++ reg = read_p15_c1(); /* get control reg. */ ++ cp_delay(); ++ write_p15_c1(reg | C1_IC); ++} ++ ++void icache_disable(void) ++{ ++ ulong reg; ++ ++ reg = read_p15_c1(); ++ cp_delay(); ++ write_p15_c1(reg & ~C1_IC); ++} ++ ++void dcache_disable (void) ++{ ++ ulong reg; ++ ++ reg = read_p15_c1 (); ++ cp_delay (); ++ write_p15_c1 (reg & ~C1_DC); ++} ++ ++void l2cache_enable() ++{ ++ unsigned long i; ++ volatile unsigned int j; ++ ++ /* ES2 onwards we can disable/enable L2 ourselves */ ++ if (get_cpu_rev() == CPU_3430_ES2) { ++ __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i)); ++ __asm__ __volatile__("orr %0, %0, #0x2":"=r"(i)); ++ __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i)); ++ } else { ++ /* Save r0, r12 and restore them after usage */ ++ __asm__ __volatile__("mov %0, r12":"=r"(j)); ++ __asm__ __volatile__("mov %0, r0":"=r"(i)); ++ ++ /* ++ * GP Device ROM code API usage here ++ * r12 = AUXCR Write function and r0 value ++ */ ++ __asm__ __volatile__("mov r12, #0x3"); ++ __asm__ __volatile__("mrc p15, 0, r0, c1, c0, 1"); ++ __asm__ __volatile__("orr r0, r0, #0x2"); ++ /* SMI instruction to call ROM Code API */ ++ __asm__ __volatile__(".word 0xE1600070"); ++ __asm__ __volatile__("mov r0, %0":"=r"(i)); ++ __asm__ __volatile__("mov r12, %0":"=r"(j)); ++ } ++ ++} ++ ++void l2cache_disable() ++{ ++ unsigned long i; ++ volatile unsigned int j; ++ ++ /* ES2 onwards we can disable/enable L2 ourselves */ ++ if (get_cpu_rev() == CPU_3430_ES2) { ++ __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i)); ++ __asm__ __volatile__("bic %0, %0, #0x2":"=r"(i)); ++ __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i)); ++ } else { ++ /* Save r0, r12 and restore them after usage */ ++ __asm__ __volatile__("mov %0, r12":"=r"(j)); ++ __asm__ __volatile__("mov %0, r0":"=r"(i)); ++ ++ /* ++ * GP Device ROM code API usage here ++ * r12 = AUXCR Write function and r0 value ++ */ ++ __asm__ __volatile__("mov r12, #0x3"); ++ __asm__ __volatile__("mrc p15, 0, r0, c1, c0, 1"); ++ __asm__ __volatile__("bic r0, r0, #0x2"); ++ /* SMI instruction to call ROM Code API */ ++ __asm__ __volatile__(".word 0xE1600070"); ++ __asm__ __volatile__("mov r0, %0":"=r"(i)); ++ __asm__ __volatile__("mov r12, %0":"=r"(j)); ++ } ++} ++ ++int icache_status(void) ++{ ++ return (read_p15_c1() & C1_IC) != 0; ++} ++ ++static void cache_flush(void) ++{ ++ asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0)); ++} ++ +diff --git a/cpu/arm_cortexa8/omap3/Makefile b/cpu/arm_cortexa8/omap3/Makefile +new file mode 100644 +index 0000000..b96b3dd +--- /dev/null ++++ b/cpu/arm_cortexa8/omap3/Makefile +@@ -0,0 +1,46 @@ ++# ++# (C) Copyright 2000-2003 ++# 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 ++ ++SOBJS := lowlevel_init.o ++COBJS := sys_info.o board.o clock.o interrupts.o mem.o syslib.o ++ ++SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) ++OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) ++ ++all: $(obj).depend $(LIB) ++ ++$(LIB): $(OBJS) ++ $(AR) $(ARFLAGS) $@ $(OBJS) ++ ++######################################################################### ++ ++# defines $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +diff --git a/cpu/arm_cortexa8/omap3/config.mk b/cpu/arm_cortexa8/omap3/config.mk +new file mode 100644 +index 0000000..fbb753e +--- /dev/null ++++ b/cpu/arm_cortexa8/omap3/config.mk +@@ -0,0 +1,36 @@ ++# ++# (C) Copyright 2002 ++# Gary Jennejohn, 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 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 ++# ++PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ ++ -msoft-float ++ ++# Make ARMv5 to allow more compilers to work, even though its v7a. ++PLATFORM_CPPFLAGS += -march=armv5 ++# ========================================================================= ++# ++# Supply options according to compiler version ++# ++# ========================================================================= ++PLATFORM_CPPFLAGS +=$(call cc-option) ++PLATFORM_CPPFLAGS +=$(call cc-option,-mno-thumb-interwork,) ++PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,\ ++ $(call cc-option,-malignment-traps,)) +diff --git a/cpu/arm_cortexa8/start.S b/cpu/arm_cortexa8/start.S +new file mode 100644 +index 0000000..07acdbd +--- /dev/null ++++ b/cpu/arm_cortexa8/start.S +@@ -0,0 +1,516 @@ ++/* ++ * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core ++ * ++ * Copyright (c) 2004 Texas Instruments ++ * ++ * Copyright (c) 2001 Marius Gröger ++ * Copyright (c) 2002 Alex Züpke ++ * Copyright (c) 2002 Gary Jennejohn ++ * Copyright (c) 2003 Richard Woodruff ++ * Copyright (c) 2003 Kshitij ++ * Copyright (c) 2006-2008 Syed Mohammed Khasim ++ * ++ * 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 ++#include ++ ++.globl _start ++_start: b reset ++ ldr pc, _undefined_instruction ++ ldr pc, _software_interrupt ++ ldr pc, _prefetch_abort ++ ldr pc, _data_abort ++ ldr pc, _not_used ++ ldr pc, _irq ++ ldr pc, _fiq ++ ++_undefined_instruction: .word undefined_instruction ++_software_interrupt: .word software_interrupt ++_prefetch_abort: .word prefetch_abort ++_data_abort: .word data_abort ++_not_used: .word not_used ++_irq: .word irq ++_fiq: .word fiq ++_pad: .word 0x12345678 /* now 16*4=64 */ ++.global _end_vect ++_end_vect: ++ ++ .balignl 16,0xdeadbeef ++/************************************************************************* ++ * ++ * Startup Code (reset vector) ++ * ++ * do important init only if we don't start from memory! ++ * setup Memory and board specific bits prior to relocation. ++ * relocate armboot to ram ++ * setup stack ++ * ++ *************************************************************************/ ++ ++_TEXT_BASE: ++ .word TEXT_BASE ++ ++.globl _armboot_start ++_armboot_start: ++ .word _start ++ ++/* ++ * These are defined in the board-specific linker script. ++ */ ++.globl _bss_start ++_bss_start: ++ .word __bss_start ++ ++.globl _bss_end ++_bss_end: ++ .word _end ++ ++#ifdef CONFIG_USE_IRQ ++/* IRQ stack memory (calculated at run-time) */ ++.globl IRQ_STACK_START ++IRQ_STACK_START: ++ .word 0x0badc0de ++ ++/* IRQ stack memory (calculated at run-time) */ ++.globl FIQ_STACK_START ++FIQ_STACK_START: ++ .word 0x0badc0de ++#endif ++ ++/* ++ * the actual reset code ++ */ ++ ++reset: ++ /* ++ * set the cpu to SVC32 mode ++ */ ++ mrs r0, cpsr ++ bic r0, r0, #0x1f ++ orr r0, r0, #0xd3 ++ msr cpsr,r0 ++ ++#if (CONFIG_OMAP34XX) ++ /* Copy vectors to mask ROM indirect addr */ ++ adr r0, _start @ r0 <- current position of code ++ add r0, r0, #4 @ skip reset vector ++ mov r2, #64 @ r2 <- size to copy ++ add r2, r0, r2 @ r2 <- source end address ++ mov r1, #SRAM_OFFSET0 @ build vect addr ++ mov r3, #SRAM_OFFSET1 ++ add r1, r1, r3 ++ mov r3, #SRAM_OFFSET2 ++ add r1, r1, r3 ++next: ++ ldmia r0!, {r3 - r10} @ copy from source address [r0] ++ stmia r1!, {r3 - r10} @ copy to target address [r1] ++ cmp r0, r2 @ until source end address [r2] ++ bne next @ loop until equal */ ++#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT) ++ /* No need to copy/exec the clock code - DPLL adjust already done ++ * in NAND/oneNAND Boot. ++ */ ++ bl cpy_clk_code @ put dpll adjust code behind vectors ++#endif /* NAND Boot */ ++#endif ++ /* the mask ROM code should have PLL and others stable */ ++#ifndef CONFIG_SKIP_LOWLEVEL_INIT ++ bl cpu_init_crit ++#endif ++ ++#ifndef CONFIG_SKIP_RELOCATE_UBOOT ++relocate: @ relocate U-Boot to RAM ++ adr r0, _start @ r0 <- current position of code ++ 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 ++ add r2, r0, r2 @ r2 <- source end address ++ ++copy_loop: @ copy 32 bytes at a time ++ ldmia r0!, {r3 - r10} @ copy from source address [r0] ++ stmia r1!, {r3 - r10} @ copy to target address [r1] ++ cmp r0, r2 @ until source end addreee [r2] ++ ble copy_loop ++#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ ++ ++ /* Set up the stack */ ++stack_setup: ++ ldr r0, _TEXT_BASE @ upper 128 KiB: relocated uboot ++ 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 ++ sub sp, r0, #12 @ leave 3 words for abort-stack ++ and sp, sp, #~7 @ 8 byte alinged for (ldr/str)d ++ ++ /* Clear BSS (if any). Is below tx (watch load addr - need space) */ ++clear_bss: ++ ldr r0, _bss_start @ find start of bss segment ++ ldr r1, _bss_end @ stop here ++ mov r2, #0x00000000 @ clear value ++clbss_l: ++ str r2, [r0] @ clear BSS location ++ cmp r0, r1 @ are we at the end yet ++ add r0, r0, #4 @ increment clear index pointer ++ bne clbss_l @ keep clearing till at end ++ ++ ldr pc, _start_armboot @ jump to C code ++ ++_start_armboot: .word start_armboot ++ ++ ++/************************************************************************* ++ * ++ * CPU_init_critical registers ++ * ++ * setup important registers ++ * setup memory timing ++ * ++ *************************************************************************/ ++cpu_init_crit: ++ /* ++ * Invalidate L1 I/D ++ */ ++ mov r0, #0 @ set up for MCR ++ mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs ++ mcr p15, 0, r0, c7, c5, 0 @ invalidate icache ++ ++ /* ++ * disable MMU stuff and caches ++ */ ++ mrc p15, 0, r0, c1, c0, 0 ++ bic r0, r0, #0x00002000 @ clear bits 13 (--V-) ++ bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) ++ orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align ++ orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB ++ mcr p15, 0, r0, c1, c0, 0 ++ ++ /* ++ * Jump to board specific initialization... ++ * The Mask ROM will have already initialized ++ * basic memory. Go here to bump up clock rate and handle ++ * wake up conditions. ++ */ ++ mov ip, lr @ persevere link reg across call ++ bl lowlevel_init @ go setup pll,mux,memory ++ mov lr, ip @ restore link ++ mov pc, lr @ back to my caller ++/* ++ ************************************************************************* ++ * ++ * Interrupt handling ++ * ++ ************************************************************************* ++ */ ++@ ++@ IRQ stack frame. ++@ ++#define S_FRAME_SIZE 72 ++ ++#define S_OLD_R0 68 ++#define S_PSR 64 ++#define S_PC 60 ++#define S_LR 56 ++#define S_SP 52 ++ ++#define S_IP 48 ++#define S_FP 44 ++#define S_R10 40 ++#define S_R9 36 ++#define S_R8 32 ++#define S_R7 28 ++#define S_R6 24 ++#define S_R5 20 ++#define S_R4 16 ++#define S_R3 12 ++#define S_R2 8 ++#define S_R1 4 ++#define S_R0 0 ++ ++#define MODE_SVC 0x13 ++#define I_BIT 0x80 ++ ++/* ++ * use bad_save_user_regs for abort/prefetch/undef/swi ... ++ * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling ++ */ ++ ++ .macro bad_save_user_regs ++ sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current ++ @ user stack ++ stmia sp, {r0 - r12} @ Save user registers (now in ++ @ svc mode) r0-r12 ++ ++ ldr r2, _armboot_start ++ sub r2, r2, #(CONFIG_SYS_MALLOC_LEN) ++ sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ set base 2 words into abort ++ @ stack ++ ldmia r2, {r2 - r3} @ get values for "aborted" pc ++ @ and cpsr (into parm regs) ++ add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack ++ ++ add r5, sp, #S_SP ++ mov r1, lr ++ stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr ++ mov r0, sp @ save current stack into r0 ++ @ (param register) ++ .endm ++ ++ .macro irq_save_user_regs ++ sub sp, sp, #S_FRAME_SIZE ++ stmia sp, {r0 - r12} @ Calling r0-r12 ++ add r8, sp, #S_PC @ !! R8 NEEDS to be saved !! ++ @ a reserved stack spot would ++ @ be good. ++ stmdb r8, {sp, lr}^ @ Calling SP, LR ++ str lr, [r8, #0] @ Save calling PC ++ mrs r6, spsr ++ str r6, [r8, #4] @ Save CPSR ++ str r0, [r8, #8] @ Save OLD_R0 ++ mov r0, sp ++ .endm ++ ++ .macro irq_restore_user_regs ++ ldmia sp, {r0 - lr}^ @ Calling r0 - lr ++ mov r0, r0 ++ ldr lr, [sp, #S_PC] @ Get PC ++ add sp, sp, #S_FRAME_SIZE ++ subs pc, lr, #4 @ return & move spsr_svc into ++ @ cpsr ++ .endm ++ ++ .macro get_bad_stack ++ ldr r13, _armboot_start @ setup our mode stack (enter ++ @ in banked mode) ++ sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool ++ sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move to reserved a couple ++ @ spots for abort stack ++ ++ str lr, [r13] @ save caller lr in position 0 ++ @ of saved stack ++ mrs lr, spsr @ get the spsr ++ str lr, [r13, #4] @ save spsr in position 1 of ++ @ saved stack ++ ++ mov r13, #MODE_SVC @ prepare SVC-Mode ++ @ msr spsr_c, r13 ++ msr spsr, r13 @ switch modes, make sure ++ @ moves will execute ++ mov lr, pc @ capture return pc ++ movs pc, lr @ jump to next instruction & ++ @ switch modes. ++ .endm ++ ++ .macro get_bad_stack_swi ++ sub r13, r13, #4 @ space on current stack for ++ @ scratch reg. ++ str r0, [r13] @ save R0's value. ++ ldr r0, _armboot_start @ get data regions start ++ sub r0, r0, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool ++ sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move past gbl and a couple ++ @ spots for abort stack ++ str lr, [r0] @ save caller lr in position 0 ++ @ of saved stack ++ mrs r0, spsr @ get the spsr ++ str lr, [r0, #4] @ save spsr in position 1 of ++ @ saved stack ++ ldr r0, [r13] @ restore r0 ++ add r13, r13, #4 @ pop stack entry ++ .endm ++ ++ .macro get_irq_stack @ setup IRQ stack ++ ldr sp, IRQ_STACK_START ++ .endm ++ ++ .macro get_fiq_stack @ setup FIQ stack ++ ldr sp, FIQ_STACK_START ++ .endm ++ ++/* ++ * exception handlers ++ */ ++ .align 5 ++undefined_instruction: ++ get_bad_stack ++ bad_save_user_regs ++ bl do_undefined_instruction ++ ++ .align 5 ++software_interrupt: ++ get_bad_stack_swi ++ bad_save_user_regs ++ bl do_software_interrupt ++ ++ .align 5 ++prefetch_abort: ++ get_bad_stack ++ bad_save_user_regs ++ bl do_prefetch_abort ++ ++ .align 5 ++data_abort: ++ get_bad_stack ++ bad_save_user_regs ++ bl do_data_abort ++ ++ .align 5 ++not_used: ++ get_bad_stack ++ bad_save_user_regs ++ bl do_not_used ++ ++#ifdef CONFIG_USE_IRQ ++ ++ .align 5 ++irq: ++ get_irq_stack ++ irq_save_user_regs ++ bl do_irq ++ irq_restore_user_regs ++ ++ .align 5 ++fiq: ++ get_fiq_stack ++ /* someone ought to write a more effective fiq_save_user_regs */ ++ irq_save_user_regs ++ bl do_fiq ++ irq_restore_user_regs ++ ++#else ++ ++ .align 5 ++irq: ++ get_bad_stack ++ bad_save_user_regs ++ bl do_irq ++ ++ .align 5 ++fiq: ++ get_bad_stack ++ bad_save_user_regs ++ bl do_fiq ++ ++#endif ++ ++/* ++ * v7_flush_dcache_all() ++ * ++ * Flush the whole D-cache. ++ * ++ * Corrupted registers: r0-r5, r7, r9-r11 ++ * ++ * - mm - mm_struct describing address space ++ */ ++ .align 5 ++.global v7_flush_dcache_all ++v7_flush_dcache_all: ++ stmfd r13!, {r0 - r5, r7, r9 - r12, r14} ++ ++ mov r7, r0 @ take a backup of device type ++ cmp r0, #0x3 @ check if the device type is ++ @ GP ++ moveq r12, #0x1 @ set up to invalide L2 ++smi: .word 0x01600070 @ Call SMI monitor (smieq) ++ cmp r7, #0x3 @ compare again in case its ++ @ lost ++ beq finished_inval @ if GP device, inval done ++ @ above ++ ++ mrc p15, 1, r0, c0, c0, 1 @ read clidr ++ ands r3, r0, #0x7000000 @ extract loc from clidr ++ mov r3, r3, lsr #23 @ left align loc bit field ++ beq finished_inval @ if loc is 0, then no need to ++ @ clean ++ mov r10, #0 @ start clean at cache level 0 ++inval_loop1: ++ add r2, r10, r10, lsr #1 @ work out 3x current cache ++ @ level ++ mov r1, r0, lsr r2 @ extract cache type bits from ++ @ clidr ++ and r1, r1, #7 @ mask of the bits for current ++ @ cache only ++ cmp r1, #2 @ see what cache we have at ++ @ this level ++ blt skip_inval @ skip if no cache, or just ++ @ i-cache ++ mcr p15, 2, r10, c0, c0, 0 @ select current cache level ++ @ in cssr ++ mov r2, #0 @ operand for mcr SBZ ++ mcr p15, 0, r2, c7, c5, 4 @ flush prefetch buffer to ++ @ sych the new cssr&csidr, ++ @ with armv7 this is 'isb', ++ @ but we compile with armv5 ++ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr ++ and r2, r1, #7 @ extract the length of the ++ @ cache lines ++ add r2, r2, #4 @ add 4 (line length offset) ++ ldr r4, =0x3ff ++ ands r4, r4, r1, lsr #3 @ find maximum number on the ++ @ way size ++ clz r5, r4 @ find bit position of way ++ @ size increment ++ ldr r7, =0x7fff ++ ands r7, r7, r1, lsr #13 @ extract max number of the ++ @ index size ++inval_loop2: ++ mov r9, r4 @ create working copy of max ++ @ way size ++inval_loop3: ++ orr r11, r10, r9, lsl r5 @ factor way and cache number ++ @ into r11 ++ orr r11, r11, r7, lsl r2 @ factor index number into r11 ++ mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way ++ subs r9, r9, #1 @ decrement the way ++ bge inval_loop3 ++ subs r7, r7, #1 @ decrement the index ++ bge inval_loop2 ++skip_inval: ++ add r10, r10, #2 @ increment cache number ++ cmp r3, r10 ++ bgt inval_loop1 ++finished_inval: ++ mov r10, #0 @ swith back to cache level 0 ++ mcr p15, 2, r10, c0, c0, 0 @ select current cache level ++ @ in cssr ++ mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, ++ @ with armv7 this is 'isb', ++ @ but we compile with armv5 ++ ++ ldmfd r13!, {r0 - r5, r7, r9 - r12, pc} ++ ++ ++ .align 5 ++.global reset_cpu ++reset_cpu: ++ ldr r1, rstctl @ get addr for global reset ++ @ reg ++ mov r3, #0x2 @ full reset pll + mpu ++ str r3, [r1] @ force reset ++ mov r0, r0 ++_loop_forever: ++ b _loop_forever ++rstctl: ++ .word PRM_RSTCTRL +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0016-ENGR00109851-Add-nand-driver-for-MX51-uboot.patch +++ uboot-imx-2009.01/debian/patches/0016-ENGR00109851-Add-nand-driver-for-MX51-uboot.patch @@ -0,0 +1,1231 @@ +From 192e622a8108be75b66218ad2b0f17a7649d8223 Mon Sep 17 00:00:00 2001 +From: Jason +Date: Wed, 18 Mar 2009 18:24:24 +0800 +Subject: [PATCH] ENGR00109851 Add nand driver for MX51 uboot + +Add nand driver for MX51 uboot + +Signed-off-by:Jason Liu +--- + drivers/mtd/nand/mxc_nand.c | 461 +++++++++++++++++++--------------- + drivers/mtd/nand/nand.c | 2 +- + drivers/mtd/nand/nand_base.c | 8 +- + include/asm-arm/arch-mx35/mxc_nand.h | 1 - + include/asm-arm/arch-mx51/mx51.h | 8 - + include/asm-arm/arch-mx51/mxc_nand.h | 396 +++++++++++++++++++++--------- + include/configs/mx51_3stack.h | 14 +- + include/linux/mtd/nand.h | 4 +- + 8 files changed, 549 insertions(+), 345 deletions(-) + +diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c +index 7e224b7..953131d 100644 +--- a/drivers/mtd/nand/mxc_nand.c ++++ b/drivers/mtd/nand/mxc_nand.c +@@ -15,7 +15,7 @@ + #include + #include + #include +-#include ++#include + #include + + struct nand_info { +@@ -143,6 +143,96 @@ static void wait_op_done(int max_retries) + MTDDEBUG(MTD_DEBUG_LEVEL0, "wait: INT not set\n"); + } + ++/*! ++ * This function sends an address (or partial address) to the ++ * NAND device. The address is used to select the source/destination for ++ * a NAND command. ++ * ++ * @param addr address to be written to NFC. ++ * @param useirq True if IRQ should be used rather than polling ++ */ ++static void send_addr(u16 addr) ++{ ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(0x%x)\n", addr); ++ ++ /* fill address */ ++ raw_write((addr << NFC_FLASH_ADDR_SHIFT), REG_NFC_FLASH_ADDR); ++ ++ /* clear status */ ++ ACK_OPS; ++ ++ /* send out address */ ++ raw_write(NFC_ADDR, REG_NFC_OPS); ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++} ++ ++static void mxc_do_addr_cycle_auto(struct mtd_info *mtd, int column, ++ int page_addr) ++{ ++#ifdef CONFIG_MXC_NFC_SP_AUTO ++ if (page_addr != -1 && column != -1) { ++ u32 mask = 0xFFFF; ++ /* the column address */ ++ raw_write(column & mask, NFC_FLASH_ADDR0); ++ raw_write((raw_read(NFC_FLASH_ADDR0) | ++ ((page_addr & mask) << 16)), NFC_FLASH_ADDR0); ++ /* the row address */ ++ raw_write(((raw_read(NFC_FLASH_ADDR8) & (mask << 16)) | ++ ((page_addr & (mask << 16)) >> 16)), ++ NFC_FLASH_ADDR8); ++ } else if (page_addr != -1) { ++ raw_write(page_addr, NFC_FLASH_ADDR0); ++ } ++ ++ MTDDEBUG(MTD_DEBUG_LEVEL3, ++ "AutoMode:the ADDR REGS value is (0x%x, 0x%x)\n", ++ raw_read(NFC_FLASH_ADDR0), raw_read(NFC_FLASH_ADDR8)); ++#endif ++} ++ ++static void mxc_do_addr_cycle_atomic(struct mtd_info *mtd, int column, ++ int page_addr) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ u32 page_mask = info->page_mask; ++ ++ if (column != -1) { ++ send_addr(column & 0xFF); ++ if (IS_2K_PAGE_NAND) { ++ /* another col addr cycle for 2k page */ ++ send_addr((column >> 8) & 0xF); ++ } else if (IS_4K_PAGE_NAND) { ++ /* another col addr cycle for 4k page */ ++ send_addr((column >> 8) & 0x1F); ++ } ++ } ++ if (page_addr != -1) { ++ do { ++ send_addr(page_addr & 0xff); ++ page_mask >>= 8; ++ page_addr >>= 8; ++ } while (page_mask != 0); ++ } ++} ++ ++/* ++ * Function to perform the address cycles. ++ */ ++static void mxc_nand_addr_cycle(struct mtd_info *mtd, int column, int page_addr) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ if (info->auto_mode) ++ mxc_do_addr_cycle_auto(mtd, column, page_addr); ++ else ++ mxc_do_addr_cycle_atomic(mtd, column, page_addr); ++} ++ + static void send_cmd_atomic(struct mtd_info *mtd, u16 cmd) + { + /* fill command */ +@@ -158,37 +248,42 @@ static void send_cmd_atomic(struct mtd_info *mtd, u16 cmd) + wait_op_done(TROP_US_DELAY); + } + +-static void send_cmd_auto(struct mtd_info *mtd, u16 cmd) ++/* ++ * Function to record the ECC corrected/uncorrected errors resulted ++ * after a page read. This NFC detects and corrects upto to 4 symbols ++ * of 9-bits each. ++ */ ++static int mxc_nand_ecc_status(struct mtd_info *mtd) + { +-#ifdef CONFIG_MXC_NFC_SP_AUTO +- switch (cmd) { +- case NAND_CMD_READ0: +- case NAND_CMD_READOOB: +- raw_write(NAND_CMD_READ0, REG_NFC_FLASH_CMD); +- break; +- case NAND_CMD_SEQIN: +- case NAND_CMD_ERASE1: +- raw_write(cmd, REG_NFC_FLASH_CMD); +- break; +- case NAND_CMD_PAGEPROG: +- case NAND_CMD_ERASE2: +- case NAND_CMD_READSTART: +- raw_write(raw_read(REG_NFC_FLASH_CMD) | cmd << NFC_CMD_1_SHIFT, +- REG_NFC_FLASH_CMD); +- send_cmd_interleave(mtd, cmd); +- break; +- case NAND_CMD_READID: +- send_atomic_cmd(cmd); +- send_addr(0); +- break; +- case NAND_CMD_RESET: +- send_cmd_interleave(mtd, cmd); +- case NAND_CMD_STATUS: +- break; +- default: +- break; +- } +-#endif ++ u32 ecc_stat, err; ++ int no_subpages = 1; ++ int ret = 0; ++ u8 ecc_bit_mask, err_limit; ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ ecc_bit_mask = (IS_4BIT_ECC ? 0x7 : 0xf); ++ err_limit = (IS_4BIT_ECC ? 0x4 : 0x8); ++ ++ no_subpages = mtd->writesize >> 9; ++ ++ no_subpages /= info->num_of_intlv; ++ ++ ecc_stat = GET_NFC_ECC_STATUS(); ++ do { ++ err = ecc_stat & ecc_bit_mask; ++ if (err > err_limit) { ++ printk(KERN_WARNING "UnCorrectable RS-ECC Error\n"); ++ return -1; ++ } else { ++ ret += err; ++ } ++ ecc_stat >>= 4; ++ } while (--no_subpages); ++ ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "%d Symbol Correctable RS-ECC Error\n", ret); ++ ++ return ret; + } + + /*! +@@ -199,14 +294,15 @@ static void send_cmd_auto(struct mtd_info *mtd, u16 cmd) + static void send_cmd_interleave(struct mtd_info *mtd, u16 cmd) + { + #ifdef CONFIG_MXC_NFC_SP_AUTO +- u32 i; +- u32 j = num_of_intlv; ++ + struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; + u32 addr_low = raw_read(NFC_FLASH_ADDR0); + u32 addr_high = raw_read(NFC_FLASH_ADDR8); + u32 page_addr = addr_low >> 16 | addr_high << 16; +- u8 *dbuf = mtd->info.data_buf; +- u8 *obuf = mtd->info.oob_buf; ++ u32 i, j = info->num_of_intlv; ++ u8 *dbuf = info->data_buf; ++ u8 *obuf = info->oob_buf; + u32 dlen = mtd->writesize / j; + u32 olen = mtd->oobsize / j; + +@@ -218,9 +314,9 @@ static void send_cmd_interleave(struct mtd_info *mtd, u16 cmd) + else + page_addr *= this->numchips; + +- for (i = 0; i < j; i++) { +- if (cmd == NAND_CMD_PAGEPROG) { +- ++ switch (cmd) { ++ case NAND_CMD_PAGEPROG: ++ for (i = 0; i < j; i++) { + /* reset addr cycle */ + if (j > 1) + mxc_nand_addr_cycle(mtd, 0, page_addr++); +@@ -238,14 +334,16 @@ static void send_cmd_interleave(struct mtd_info *mtd, u16 cmd) + raw_write(NFC_AUTO_PROG, REG_NFC_OPS); + + /* wait auto_prog_done bit set */ +- if (i < j - 1) { +- while (! +- (raw_read(REG_NFC_OPS_STAT) & 1 << 30)) +- ; +- } else { +- wait_op_done(TROP_US_DELAY); +- } +- } else if (cmd == NAND_CMD_READSTART) { ++ while (!(raw_read(REG_NFC_OPS_STAT) & NFC_OP_DONE)) ++ ; ++ } ++ ++ wait_op_done(TROP_US_DELAY); ++ while (!(raw_read(REG_NFC_OPS_STAT) & NFC_RB)); ++ ++ break; ++ case NAND_CMD_READSTART: ++ for (i = 0; i < j; i++) { + /* reset addr cycle */ + if (j > 1) + mxc_nand_addr_cycle(mtd, 0, page_addr++); +@@ -265,18 +363,62 @@ static void send_cmd_interleave(struct mtd_info *mtd, u16 cmd) + /* update the value */ + dbuf += dlen; + obuf += olen; +- } else if (cmd == NAND_CMD_ERASE2) { ++ } ++ break; ++ case NAND_CMD_ERASE2: ++ for (i = 0; i < j; i++) { + if (!i) { + page_addr = addr_low; + page_addr *= (j > 1 ? j : this->numchips); + } + mxc_nand_addr_cycle(mtd, -1, page_addr++); ++ raw_write(0, REG_NFC_OPS_STAT); + raw_write(NFC_AUTO_ERASE, REG_NFC_OPS); + wait_op_done(TROP_US_DELAY); +- } else if (cmd == NAND_CMD_RESET) { +- NFC_SET_NFC_ACTIVE_CS(i); +- send_atomic_cmd(cmd); + } ++ break; ++ case NAND_CMD_RESET: ++ for (i = 0; i < j; i++) { ++ if (j > 1) ++ NFC_SET_NFC_ACTIVE_CS(i); ++ send_cmd_atomic(mtd, cmd); ++ } ++ break; ++ default: ++ break; ++ } ++#endif ++} ++ ++static void send_cmd_auto(struct mtd_info *mtd, u16 cmd) ++{ ++#ifdef CONFIG_MXC_NFC_SP_AUTO ++ switch (cmd) { ++ case NAND_CMD_READ0: ++ case NAND_CMD_READOOB: ++ raw_write(NAND_CMD_READ0, REG_NFC_FLASH_CMD); ++ break; ++ case NAND_CMD_SEQIN: ++ case NAND_CMD_ERASE1: ++ raw_write(cmd, REG_NFC_FLASH_CMD); ++ break; ++ case NAND_CMD_PAGEPROG: ++ case NAND_CMD_ERASE2: ++ case NAND_CMD_READSTART: ++ raw_write(raw_read(REG_NFC_FLASH_CMD) | cmd << NFC_CMD_1_SHIFT, ++ REG_NFC_FLASH_CMD); ++ send_cmd_interleave(mtd, cmd); ++ break; ++ case NAND_CMD_READID: ++ send_cmd_atomic(mtd, cmd); ++ send_addr(0); ++ break; ++ case NAND_CMD_RESET: ++ send_cmd_interleave(mtd, cmd); ++ case NAND_CMD_STATUS: ++ break; ++ default: ++ break; + } + #endif + } +@@ -299,32 +441,7 @@ static void send_cmd(struct mtd_info *mtd, u16 cmd) + else + send_cmd_atomic(mtd, cmd); + +- MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(0x%x, %d)\n", cmd); +-} +- +-/*! +- * This function sends an address (or partial address) to the +- * NAND device. The address is used to select the source/destination for +- * a NAND command. +- * +- * @param addr address to be written to NFC. +- * @param useirq True if IRQ should be used rather than polling +- */ +-static void send_addr(u16 addr) +-{ +- MTDDEBUG(MTD_DEBUG_LEVEL3, "send_addr(0x%x %d)\n", addr); +- +- /* fill address */ +- raw_write((addr << NFC_FLASH_ADDR_SHIFT), REG_NFC_FLASH_ADDR); +- +- /* clear status */ +- ACK_OPS; +- +- /* send out address */ +- raw_write(NFC_ADDR, REG_NFC_OPS); +- +- /* Wait for operation to complete */ +- wait_op_done(TROP_US_DELAY); ++ MTDDEBUG(MTD_DEBUG_LEVEL3, "send_cmd(0x%x)\n", cmd); + } + + /*! +@@ -420,7 +537,8 @@ static u16 mxc_do_status_auto(struct mtd_info *mtd) + /* set ative cs */ + NFC_SET_NFC_ACTIVE_CS(i); + +- raw_write(NFC_AUTO_STATE, REG_NFC_OPS); ++ /* clear status */ ++ ACK_OPS; + + /* FIXME, NFC Auto erase may have + * problem, have to pollingit until +@@ -428,6 +546,12 @@ static u16 mxc_do_status_auto(struct mtd_info *mtd) + * it may get error + */ + do { ++ raw_write(NFC_AUTO_STATE, REG_NFC_OPS); ++ #ifdef CONFIG_MX51 ++ /* mx51to2 NFC need wait the op done */ ++ if (is_soc_rev(CHIP_REV_2_0) == 0) ++ wait_op_done(TROP_US_DELAY); ++ #endif + status = (raw_read(NFC_CONFIG1) & mask) >> 16; + } while ((status & NAND_STATUS_READY) == 0); + +@@ -491,44 +615,6 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) + } + + /* +- * Function to record the ECC corrected/uncorrected errors resulted +- * after a page read. This NFC detects and corrects upto to 4 symbols +- * of 9-bits each. +- */ +-static int mxc_nand_ecc_status(struct mtd_info *mtd) +-{ +- u32 ecc_stat, err; +- int no_subpages = 1; +- int ret = 0; +- u8 ecc_bit_mask, err_limit; +- struct nand_chip *this = mtd->priv; +- struct nand_info *info = this->priv; +- +- ecc_bit_mask = (IS_4BIT_ECC ? 0x7 : 0xf); +- err_limit = (IS_4BIT_ECC ? 0x4 : 0x8); +- +- no_subpages = mtd->writesize >> 9; +- +- no_subpages /= info->num_of_intlv; +- +- ecc_stat = GET_NFC_ECC_STATUS(); +- do { +- err = ecc_stat & ecc_bit_mask; +- if (err > err_limit) { +- printk(KERN_WARNING "UnCorrectable RS-ECC Error\n"); +- return -1; +- } else { +- ret += err; +- } +- ecc_stat >>= 4; +- } while (--no_subpages); +- +- MTDDEBUG(MTD_DEBUG_LEVEL3, "%d Symbol Correctable RS-ECC Error\n", ret); +- +- return ret; +-} +- +-/* + * Function to correct the detected errors. This NFC corrects all the errors + * detected. So this function just return 0. + */ +@@ -645,25 +731,6 @@ static u16 mxc_nand_read_word(struct mtd_info *mtd) + } + + /*! +- * This function reads byte from the NAND Flash +- * +- * @param mtd MTD structure for the NAND Flash +- * +- * @return data read from the NAND Flash +- */ +-static u_char mxc_nand_read_byte16(struct mtd_info *mtd) +-{ +- struct nand_chip *this = mtd->priv; +- struct nand_info *info = this->priv; +- +- /* Check for status request */ +- if (info->status_req) +- return mxc_nand_get_status(mtd) & 0xFF; +- +- return mxc_nand_read_word(mtd) & 0xFF; +-} +- +-/*! + * This function writes data of length \b len from buffer \b buf to the NAND + * internal RAM buffer's MAIN area 0. + * +@@ -751,72 +818,6 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) + } + } + +-static void mxc_do_addr_cycle_auto(struct mtd_info *mtd, int column, +- int page_addr) +-{ +-#ifdef CONFIG_MXC_NFC_SP_AUTO +- if (page_addr != -1 && column != -1) { +- u32 mask = 0xFFFF; +- /* the column address */ +- raw_write(column & mask, NFC_FLASH_ADDR0); +- raw_write((raw_read(NFC_FLASH_ADDR0) | +- ((page_addr & mask) << 16)), NFC_FLASH_ADDR0); +- /* the row address */ +- raw_write(((raw_read(NFC_FLASH_ADDR8) & (mask << 16)) | +- ((page_addr & (mask << 16)) >> 16)), +- NFC_FLASH_ADDR8); +- } else if (page_addr != -1) { +- raw_write(page_addr, NFC_FLASH_ADDR0); +- } +- +- MTDDEBUG(MTD_DEBUG_LEVEL3, +- "AutoMode:the ADDR REGS value is (0x%x, 0x%x)\n", +- raw_read(NFC_FLASH_ADDR0), raw_read(NFC_FLASH_ADDR8)); +-#endif +-} +- +-static void mxc_do_addr_cycle_atomic(struct mtd_info *mtd, int column, +- int page_addr) +-{ +- struct nand_chip *this = mtd->priv; +- struct nand_info *info = this->priv; +- +- u32 page_mask = info->page_mask; +- +- if (column != -1) { +- send_addr(column & 0xFF); +- if (IS_2K_PAGE_NAND) { +- /* another col addr cycle for 2k page */ +- send_addr((column >> 8) & 0xF); +- } else if (IS_4K_PAGE_NAND) { +- /* another col addr cycle for 4k page */ +- send_addr((column >> 8) & 0x1F); +- } +- } +- if (page_addr != -1) { +- do { +- send_addr(page_addr & 0xff); +- page_mask >>= 8; +- page_addr >>= 8; +- } while (page_mask != 0); +- } +-} +- +- +-/* +- * Function to perform the address cycles. +- */ +-static void mxc_nand_addr_cycle(struct mtd_info *mtd, int column, int page_addr) +-{ +- struct nand_chip *this = mtd->priv; +- struct nand_info *info = this->priv; +- +- if (info->auto_mode) +- mxc_do_addr_cycle_auto(mtd, column, page_addr); +- else +- mxc_do_addr_cycle_atomic(mtd, column, page_addr); +-} +- + /*! + * This function is used by the upper layer to write command to NAND Flash for + * different operations to be carried out on NAND Flash +@@ -933,6 +934,50 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, + } + } + ++static int mxc_nand_read_oob(struct mtd_info *mtd, ++ struct nand_chip *chip, int page, int sndcmd) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ if (sndcmd) { ++ ++ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); ++ sndcmd = 0; ++ } ++ ++ memcpy(chip->oob_poi, info->oob_buf, mtd->oobsize); ++ ++ return sndcmd; ++} ++ ++static int mxc_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, ++ uint8_t *buf) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++#ifndef CONFIG_MXC_NFC_SP_AUTO ++ mxc_nand_ecc_status(mtd); ++#endif ++ ++ memcpy(buf, info->data_buf, mtd->writesize); ++ memcpy(chip->oob_poi, info->oob_buf, mtd->oobsize); ++ ++ return 0; ++} ++ ++static void mxc_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, ++ const uint8_t *buf) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ memcpy(info->data_buf, buf, mtd->writesize); ++ memcpy(info->oob_buf, chip->oob_poi, mtd->oobsize); ++ ++} ++ + /* Define some generic bad / good block scan pattern which are used + * while scanning a device for factory marked good / bad blocks. */ + static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; +@@ -1014,7 +1059,7 @@ static int mxc_nand_scan_bbt(struct mtd_info *mtd) + this->bbt_erase_shift = + this->phys_erase_shift = ffs(mtd->erasesize) - 1; + this->chip_shift = ffs(this->chipsize) - 1; +- /*this->oob_poi = this->buffers->databuf + mtd->writesize;*/ ++ this->oob_poi = this->buffers->databuf + mtd->writesize; + } + + /* propagate ecc.layout to mtd_info */ +@@ -1055,6 +1100,9 @@ static void mxc_nfc_init(void) + + /* Unlock Block Command for given address range */ + raw_write(NFC_SET_WPC(NFC_WPC_UNLOCK), REG_NFC_WPC); ++ ++ /* Enable hw ecc */ ++ raw_write((raw_read(REG_NFC_ECC_EN) | NFC_ECC_EN), REG_NFC_ECC_EN); + } + + static int mxc_alloc_buf(struct nand_info *info) +@@ -1080,12 +1128,6 @@ static int mxc_alloc_buf(struct nand_info *info) + return err; + } + +-static void mxc_free_buf(struct nand_info *info) +-{ +- kfree(info->data_buf); +- kfree(info->oob_buf); +-} +- + /*! + * This function is called during the driver binding process. + * +@@ -1132,13 +1174,16 @@ int board_nand_init(struct nand_chip *nand) + this->read_buf = mxc_nand_read_buf; + this->verify_buf = mxc_nand_verify_buf; + this->scan_bbt = mxc_nand_scan_bbt; ++ this->ecc.read_page = mxc_nand_read_page; ++ this->ecc.write_page = mxc_nand_write_page; ++ this->ecc.read_oob = mxc_nand_read_oob; + this->ecc.calculate = mxc_nand_calculate_ecc; + this->ecc.correct = mxc_nand_correct_data; + this->ecc.hwctl = mxc_nand_enable_hwecc; ++ this->ecc.layout = &nand_hw_eccoob_512; + this->ecc.mode = NAND_ECC_HW; + this->ecc.bytes = 9; + this->ecc.size = 512; + + return 0; +- + } +diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c +index eeb19ff..2f05141 100644 +--- a/drivers/mtd/nand/nand.c ++++ b/drivers/mtd/nand/nand.c +@@ -45,7 +45,7 @@ static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, + + nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr; + if (board_nand_init(nand) == 0) { +- if (nand_scan(mtd, 1) == 0) { ++ if (nand_scan(mtd, NAND_MAX_CHIPS) == 0) { + if (!mtd->name) + mtd->name = (char *)default_nand_name; + } else +diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c +index 3919ae1..fbf3925 100644 +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -2510,7 +2510,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, + mtd->writesize = 1024 << (extid & 0x3); + extid >>= 2; + /* Calc oobsize */ +- mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9); ++ mtd->oobsize = (*maf_id == 0x2c && dev_id == 0xd5) ? ++ 218 : (8 << (extid & 0x01)) * (mtd->writesize >> 9); + extid >>= 2; + /* Calc blocksize. Blocksize is multiples of 64KiB */ + mtd->erasesize = (64 * 1024) << (extid & 0x03); +@@ -2843,10 +2844,9 @@ int nand_scan_tail(struct mtd_info *mtd) + mtd->ecclayout = chip->ecc.layout; + + /* Check, if we should skip the bad block table scan */ +- if (chip->options & NAND_SKIP_BBTSCAN) +- chip->options |= NAND_BBT_SCANNED; ++ chip->options |= NAND_BBT_SCANNED; + +- return 0; ++ return chip->scan_bbt(mtd); + } + + /* module_text_address() isn't exported, and it's mostly a pointless +diff --git a/include/asm-arm/arch-mx35/mxc_nand.h b/include/asm-arm/arch-mx35/mxc_nand.h +index bc04c09..047b232 100644 +--- a/include/asm-arm/arch-mx35/mxc_nand.h ++++ b/include/asm-arm/arch-mx35/mxc_nand.h +@@ -33,7 +33,6 @@ + + #define NAND_PAGESIZE_2KB 2048 + #define NAND_PAGESIZE_4KB 4096 +-#define NAND_MAX_PAGESIZE 4096 + + /* + * Addresses for NFC registers +diff --git a/include/asm-arm/arch-mx51/mx51.h b/include/asm-arm/arch-mx51/mx51.h +index d9d8ef7..566251b 100644 +--- a/include/asm-arm/arch-mx51/mx51.h ++++ b/include/asm-arm/arch-mx51/mx51.h +@@ -406,14 +406,6 @@ MXC_IPG_PERCLK, + MXC_UART_CLK, + }; + +-/*! +- * NFMS bit in RCSR register for pagesize of nandflash +- */ +-#define NFMS (*((volatile u32 *)(CCM_BASE_ADDR+0x18))) +-#define NFMS_BIT 8 +-#define NFMS_NF_DWIDTH 14 +-#define NFMS_NF_PG_SZ 8 +- + extern unsigned int mxc_get_clock(enum mxc_clock clk); + extern unsigned int get_board_rev(void); + extern int is_soc_rev(int rev); +diff --git a/include/asm-arm/arch-mx51/mxc_nand.h b/include/asm-arm/arch-mx51/mxc_nand.h +index aad93d1..539d0fd 100644 +--- a/include/asm-arm/arch-mx51/mxc_nand.h ++++ b/include/asm-arm/arch-mx51/mxc_nand.h +@@ -12,7 +12,7 @@ + */ + + /*! +- * @file mxc_nd2.h ++ * @file mxc_nand.h + * + * @brief This file contains the NAND Flash Controller register information. + * +@@ -25,99 +25,100 @@ + + #include + +-#define IS_2K_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) \ ++#define IS_2K_PAGE_NAND ((mtd->writesize / info->num_of_intlv) \ + == NAND_PAGESIZE_2KB) +-#define IS_4K_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) \ ++#define IS_4K_PAGE_NAND ((mtd->writesize / info->num_of_intlv) \ + == NAND_PAGESIZE_4KB) +-#define IS_LARGE_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) > 512) ++#define IS_LARGE_PAGE_NAND ((mtd->writesize / info->num_of_intlv) > 512) ++ ++#define GET_NAND_OOB_SIZE (mtd->oobsize / info->num_of_intlv) + + #define NAND_PAGESIZE_2KB 2048 + #define NAND_PAGESIZE_4KB 4096 +-#define NAND_MAX_PAGESIZE 4096 + +-/* +- * Addresses for NFC registers +- */ +-#define NFC_REG_BASE (NFC_BASE_ADDR + 0x1000) +-#define NFC_BUF_ADDR (NFC_REG_BASE + 0xE04) +-#define NFC_FLASH_ADDR (NFC_REG_BASE + 0xE06) +-#define NFC_FLASH_CMD (NFC_REG_BASE + 0xE08) +-#define NFC_CONFIG (NFC_REG_BASE + 0xE0A) +-#define NFC_ECC_STATUS_RESULT (NFC_REG_BASE + 0xE0C) +-#define NFC_SPAS (NFC_REG_BASE + 0xE10) +-#define NFC_WRPROT (NFC_REG_BASE + 0xE12) +-#define NFC_UNLOCKSTART_BLKADDR (NFC_REG_BASE + 0xE20) +-#define NFC_UNLOCKEND_BLKADDR (NFC_REG_BASE + 0xE22) +-#define NFC_CONFIG1 (NFC_REG_BASE + 0xE1A) +-#define NFC_CONFIG2 (NFC_REG_BASE + 0xE1C) ++#define NFC_AXI_BASE_ADDR NFC_BASE_ADDR_AXI ++#define NFC_IP_BASE_ADDR NFC_BASE_ADDR ++#define MXC_INT_NANDFC MXC_INT_NFC ++#define CONFIG_MXC_NFC_SP_AUTO ++#define NFC_FLASH_CMD (NFC_AXI_BASE_ADDR + 0x1E00) ++#define NFC_FLASH_ADDR0 (NFC_AXI_BASE_ADDR + 0x1E04) ++#define NFC_FLASH_ADDR8 (NFC_AXI_BASE_ADDR + 0x1E24) ++#define NFC_CONFIG1 (NFC_AXI_BASE_ADDR + 0x1E34) ++#define NFC_ECC_STATUS_RESULT (NFC_AXI_BASE_ADDR + 0x1E38) ++#define NFC_ECC_STATUS_SUM (NFC_AXI_BASE_ADDR + 0x1E3C) ++#define LAUNCH_NFC (NFC_AXI_BASE_ADDR + 0x1E40) ++#define NFC_WRPROT (NFC_IP_BASE_ADDR + 0x00) ++#define NFC_WRPROT_UNLOCK_BLK_ADD0 (NFC_IP_BASE_ADDR + 0x04) ++#define NFC_CONFIG2 (NFC_IP_BASE_ADDR + 0x24) ++#define NFC_CONFIG3 (NFC_IP_BASE_ADDR + 0x28) ++#define NFC_IPC (NFC_IP_BASE_ADDR + 0x2C) + + /*! + * Addresses for NFC RAM BUFFER Main area 0 + */ +-#define MAIN_AREA0 (u16 *)(NFC_BASE_ADDR + 0x000) +-#define MAIN_AREA1 (u16 *)(NFC_BASE_ADDR + 0x200) ++#define MAIN_AREA0 ((u16 *)(NFC_AXI_BASE_ADDR + 0x000)) ++#define MAIN_AREA1 ((u16 *)(NFC_AXI_BASE_ADDR + 0x200)) + + /*! + * Addresses for NFC SPARE BUFFER Spare area 0 + */ +-#define SPARE_AREA0 (u16 *)(NFC_BASE_ADDR + 0x1000) ++#define SPARE_AREA0 ((u16 *)(NFC_AXI_BASE_ADDR + 0x1000)) + #define SPARE_LEN 64 + #define SPARE_COUNT 8 +-#define SPARE_SIZE (SPARE_LEN * SPARE_COUNT) ++#define SPARE_SIZE (SPARE_LEN * SPARE_COUNT) + ++#define NFC_SPAS_WIDTH 8 ++#define NFC_SPAS_SHIFT 16 + +-#define SPAS_SHIFT (0) +-#define SPAS_MASK (0xFF00) +-#define IS_4BIT_ECC \ +- ((raw_read(REG_NFC_ECC_MODE) & NFC_ECC_MODE_4) >> 0) ++#define IS_4BIT_ECC \ ++( \ ++ is_soc_rev(CHIP_REV_2_0) == 0 ? \ ++ !((raw_read(NFC_CONFIG2) & NFC_ECC_MODE_4) >> 6) : \ ++ ((raw_read(NFC_CONFIG2) & NFC_ECC_MODE_4) >> 6) \ ++) + + #define NFC_SET_SPAS(v) \ +- raw_write(((raw_read(REG_NFC_SPAS) & SPAS_MASK) | \ +- ((v<>1)) \ ++ ; \ ++ raw_write(val, reg); \ ++ raw_write(0, NFC_IPC); \ ++ } while (0) + +-#define WRITE_NFC_IP_REG(val, reg) \ +- raw_write((raw_read(REG_NFC_OPS_STAT) & ~NFC_OPS_STAT), \ +- REG_NFC_OPS_STAT) +- +-#define GET_NFC_ECC_STATUS() \ +- raw_read(REG_NFC_ECC_STATUS_RESULT); ++#define GET_NFC_ECC_STATUS() raw_read(REG_NFC_ECC_STATUS_RESULT); + + /*! +- * Set INT to 0, Set 1 to specific operation bit, rest to 0 in LAUNCH_NFC +- * Register for Specific operation ++ * Set 1 to specific operation bit, rest to 0 in LAUNCH_NFC Register for ++ * Specific operation + */ + #define NFC_CMD 0x1 + #define NFC_ADDR 0x2 +@@ -125,74 +126,241 @@ do { \ + #define NFC_OUTPUT 0x8 + #define NFC_ID 0x10 + #define NFC_STATUS 0x20 ++#define NFC_AUTO_PROG 0x40 ++#define NFC_AUTO_READ 0x80 ++#define NFC_AUTO_ERASE 0x200 ++#define NFC_COPY_BACK_0 0x400 ++#define NFC_COPY_BACK_1 0x800 ++#define NFC_AUTO_STATE 0x1000 ++ ++/* Bit Definitions for NFC_IPC*/ ++#define NFC_OPS_STAT (1 << 31) ++#define NFC_OP_DONE (1 << 30) ++#define NFC_RB (1 << 28) ++#define NFC_PS_WIDTH 2 ++#define NFC_PS_SHIFT 0 ++#define NFC_PS_512 0 ++#define NFC_PS_2K 1 ++#define NFC_PS_4K 2 ++ ++ ++#define NFC_ONE_CYCLE (1 << 2) ++#define NFC_INT_MSK (1 << 15) ++#define NFC_AUTO_PROG_DONE_MSK (1 << 14) ++#define NFC_NUM_ADDR_PHASE1_WIDTH 2 ++#define NFC_NUM_ADDR_PHASE1_SHIFT 12 ++#define NFC_NUM_ADDR_PHASE0_WIDTH 1 ++#define NFC_NUM_ADDR_PHASE0_SHIFT 5 ++#define NFC_ONE_LESS_PHASE1 0 ++#define NFC_TWO_LESS_PHASE1 1 ++#define NFC_FLASH_ADDR_SHIFT 0 ++#define NFC_UNLOCK_END_ADDR_SHIFT 16 ++ ++/* Bit definition for NFC_CONFIGRATION_1 */ ++#define NFC_SP_EN (1 << 0) ++#define NFC_CE (1 << 1) ++#define NFC_RST (1 << 2) ++#define NFC_ECC_EN (1 << 3) + +-/* Bit Definitions */ +-#define NFC_OPS_STAT (1 << 15) +-#define NFC_SP_EN (1 << 2) +-#define NFC_ECC_EN (1 << 3) +-#define NFC_INT_MSK (1 << 4) +-#define NFC_BIG (1 << 5) +-#define NFC_RST (1 << 6) +-#define NFC_CE (1 << 7) +-#define NFC_ONE_CYCLE (1 << 8) +-#define NFC_BLS_LOCKED 0 +-#define NFC_BLS_LOCKED_DEFAULT 1 +-#define NFC_BLS_UNLCOKED 2 ++#define NFC_FIELD_RESET(width, shift) (~(((1 << (width)) - 1) << (shift))) ++ ++#define NFC_RBA_SHIFT 4 ++#define NFC_RBA_WIDTH 3 ++ ++#define NFC_ITERATION_SHIFT 8 ++#define NFC_ITERATION_WIDTH 4 ++#define NFC_ACTIVE_CS_SHIFT 12 ++#define NFC_ACTIVE_CS_WIDTH 3 ++/* bit definition for CONFIGRATION3 */ ++#define NFC_NO_SDMA (1 << 20) ++#define NFC_FMP_SHIFT 16 ++#define NFC_FMP_WIDTH 4 ++#define NFC_RBB_MODE (1 << 15) ++#define NFC_NUM_OF_DEVICES_SHIFT 12 ++#define NFC_NUM_OF_DEVICES_WIDTH 4 ++#define NFC_DMA_MODE_SHIFT 11 ++#define NFC_DMA_MODE_WIDTH 1 ++#define NFC_SBB_SHIFT 8 ++#define NFC_SBB_WIDTH 3 ++#define NFC_BIG (1 << 7) ++#define NFC_SB2R_SHIFT 4 ++#define NFC_SB2R_WIDTH 3 ++#define NFC_FW_SHIFT 3 ++#define NFC_FW_WIDTH 1 ++#define NFC_TOO (1 << 2) ++#define NFC_ADD_OP_SHIFT 0 ++#define NFC_ADD_OP_WIDTH 2 ++#define NFC_FW_8 1 ++#define NFC_FW_16 0 ++#define NFC_ST_CMD_SHITF 24 ++#define NFC_ST_CMD_WIDTH 8 ++ ++#define NFC_PPB_32 (0 << 7) ++#define NFC_PPB_64 (1 << 7) ++#define NFC_PPB_128 (2 << 7) ++#define NFC_PPB_256 (3 << 7) ++#define NFC_PPB_RESET (~(3 << 7)) ++ ++#define NFC_BLS_LOCKED (0 << 16) ++#define NFC_BLS_LOCKED_DEFAULT (1 << 16) ++#define NFC_BLS_UNLCOKED (2 << 16) ++#define NFC_BLS_RESET (~(3 << 16)) + #define NFC_WPC_LOCK_TIGHT 1 + #define NFC_WPC_LOCK (1 << 1) + #define NFC_WPC_UNLOCK (1 << 2) +-#define NFC_FLASH_ADDR_SHIFT 0 +-#define NFC_UNLOCK_END_ADDR_SHIFT 0 +- +-#define NFC_ECC_MODE_4 (1<<0) +-#define NFC_ECC_MODE_8 (~(1<<0)) +-#define NFC_SPAS_16 8 +-#define NFC_SPAS_64 32 +-#define NFC_SPAS_128 64 +-#define NFC_SPAS_218 109 +- +-/* NFC Register Mapping */ +-#define REG_NFC_OPS_STAT NFC_CONFIG2 +-#define REG_NFC_INTRRUPT NFC_CONFIG1 +-#define REG_NFC_FLASH_ADDR NFC_FLASH_ADDR ++#define NFC_WPC_RESET (~(7)) ++#define NFC_ECC_MODE_4 (1 << 6) ++#define NFC_ECC_MODE_8 (~(1 << 6)) ++#define NFC_ECC_MODE_MASK (~(1 << 6)) ++#define NFC_SPAS_16 8 ++#define NFC_SPAS_64 32 ++#define NFC_SPAS_128 64 ++#define NFC_SPAS_112 56 ++#define NFC_SPAS_218 109 ++#define NFC_IPC_CREQ (1 << 0) ++#define NFC_IPC_ACK (1 << 1) ++ ++#define REG_NFC_OPS_STAT NFC_IPC ++#define REG_NFC_INTRRUPT NFC_CONFIG2 ++#define REG_NFC_FLASH_ADDR NFC_FLASH_ADDR0 + #define REG_NFC_FLASH_CMD NFC_FLASH_CMD +-#define REG_NFC_OPS NFC_CONFIG2 +-#define REG_NFC_SET_RBA NFC_BUF_ADDR +-#define REG_NFC_ECC_EN NFC_CONFIG1 +-#define REG_NFC_ECC_STATUS_RESULT NFC_ECC_STATUS_RESULT ++#define REG_NFC_OPS LAUNCH_NFC ++#define REG_NFC_SET_RBA NFC_CONFIG1 ++#define REG_NFC_RB NFC_IPC ++#define REG_NFC_ECC_EN NFC_CONFIG2 ++#define REG_NFC_ECC_STATUS_RESULT NFC_ECC_STATUS_RESULT + #define REG_NFC_CE NFC_CONFIG1 ++#define REG_NFC_RST NFC_CONFIG1 ++#define REG_NFC_PPB NFC_CONFIG2 + #define REG_NFC_SP_EN NFC_CONFIG1 +-#define REG_NFC_BLS NFC_CONFIG ++#define REG_NFC_BLS NFC_WRPROT ++#define REG_UNLOCK_BLK_ADD0 NFC_WRPROT_UNLOCK_BLK_ADD0 ++#define REG_UNLOCK_BLK_ADD1 NFC_WRPROT_UNLOCK_BLK_ADD1 ++#define REG_UNLOCK_BLK_ADD2 NFC_WRPROT_UNLOCK_BLK_ADD2 ++#define REG_UNLOCK_BLK_ADD3 NFC_WRPROT_UNLOCK_BLK_ADD3 + #define REG_NFC_WPC NFC_WRPROT +-#define REG_START_BLKADDR NFC_UNLOCKSTART_BLKADDR +-#define REG_END_BLKADDR NFC_UNLOCKEND_BLKADDR +-#define REG_NFC_RST NFC_CONFIG1 +-#define REG_NFC_ECC_MODE NFC_CONFIG1 +-#define REG_NFC_SPAS NFC_SPAS ++#define REG_NFC_ONE_CYCLE NFC_CONFIG2 ++ ++/* NFC V3 Specific MACRO functions definitions */ ++#define raw_write(v, a) __raw_writel(v, a) ++#define raw_read(a) __raw_readl(a) ++ ++/* Explcit ack ops status (if any), before issue of any command */ ++#define ACK_OPS \ ++ raw_write((raw_read(REG_NFC_OPS_STAT) & ~NFC_OPS_STAT), \ ++ REG_NFC_OPS_STAT); ++ ++/* Set RBA buffer id*/ ++#define NFC_SET_RBA(val) \ ++ raw_write((raw_read(REG_NFC_SET_RBA) & \ ++ (NFC_FIELD_RESET(NFC_RBA_WIDTH, NFC_RBA_SHIFT))) | \ ++ ((val) << NFC_RBA_SHIFT), REG_NFC_SET_RBA); ++ ++#define NFC_SET_PS(val) \ ++ raw_write((raw_read(NFC_CONFIG2) & \ ++ (NFC_FIELD_RESET(NFC_PS_WIDTH, NFC_PS_SHIFT))) | \ ++ ((val) << NFC_PS_SHIFT), NFC_CONFIG2); ++ ++#define UNLOCK_ADDR(start_addr, end_addr) \ ++{ \ ++ int i = 0; \ ++ for (; i < NAND_MAX_CHIPS; i++) \ ++ raw_write(start_addr | \ ++ (end_addr << NFC_UNLOCK_END_ADDR_SHIFT), \ ++ REG_UNLOCK_BLK_ADD0 + (i << 2)); \ ++} + ++#define NFC_SET_NFC_ACTIVE_CS(val) \ ++ raw_write((raw_read(NFC_CONFIG1) & \ ++ (NFC_FIELD_RESET(NFC_ACTIVE_CS_WIDTH, NFC_ACTIVE_CS_SHIFT))) | \ ++ ((val) << NFC_ACTIVE_CS_SHIFT), NFC_CONFIG1); + +-/* NFC V1/V2 Specific MACRO functions definitions */ ++#define NFC_GET_MAXCHIP_SP() 8 + +-#define raw_write(v, a) __raw_writew(v, a) +-#define raw_read(a) __raw_readw(a) ++#define NFC_SET_BLS(val) ((raw_read(REG_NFC_BLS) & NFC_BLS_RESET) | val) ++#define NFC_SET_WPC(val) ((raw_read(REG_NFC_WPC) & NFC_WPC_RESET) | val) ++#define CHECK_NFC_RB (raw_read(REG_NFC_RB) & NFC_RB) + +-#define NFC_SET_BLS(val) val ++#define NFC_SET_NFC_NUM_ADDR_PHASE1(val) \ ++ raw_write((raw_read(NFC_CONFIG2) & \ ++ (NFC_FIELD_RESET(NFC_NUM_ADDR_PHASE1_WIDTH, \ ++ NFC_NUM_ADDR_PHASE1_SHIFT))) | \ ++ ((val) << NFC_NUM_ADDR_PHASE1_SHIFT), NFC_CONFIG2); + +-#define UNLOCK_ADDR(start_addr, end_addr) \ ++#define NFC_SET_NFC_NUM_ADDR_PHASE0(val) \ ++ raw_write((raw_read(NFC_CONFIG2) & \ ++ (NFC_FIELD_RESET(NFC_NUM_ADDR_PHASE0_WIDTH, \ ++ NFC_NUM_ADDR_PHASE0_SHIFT))) | \ ++ ((val) << NFC_NUM_ADDR_PHASE0_SHIFT), NFC_CONFIG2); ++ ++#define NFC_SET_NFC_ITERATION(val) \ ++ raw_write((raw_read(NFC_CONFIG1) & \ ++ (NFC_FIELD_RESET(NFC_ITERATION_WIDTH, NFC_ITERATION_SHIFT))) | \ ++ ((val) << NFC_ITERATION_SHIFT), NFC_CONFIG1); ++ ++#define NFC_SET_FW(val) \ ++ raw_write((raw_read(NFC_CONFIG3) & \ ++ (NFC_FIELD_RESET(NFC_FW_WIDTH, NFC_FW_SHIFT))) | \ ++ ((val) << NFC_FW_SHIFT), NFC_CONFIG3); ++ ++#define NFC_SET_NUM_OF_DEVICE(val) \ ++ raw_write((raw_read(NFC_CONFIG3) & \ ++ (NFC_FIELD_RESET(NFC_NUM_OF_DEVICES_WIDTH, \ ++ NFC_NUM_OF_DEVICES_SHIFT))) | \ ++ ((val) << NFC_NUM_OF_DEVICES_SHIFT), NFC_CONFIG3); ++ ++#define NFC_SET_ADD_OP_MODE(val) \ ++ raw_write((raw_read(NFC_CONFIG3) & \ ++ (NFC_FIELD_RESET(NFC_ADD_OP_WIDTH, NFC_ADD_OP_SHIFT))) | \ ++ ((val) << NFC_ADD_OP_SHIFT), NFC_CONFIG3); ++ ++#define NFC_SET_ADD_CS_MODE(val) \ + { \ +- raw_write(start_addr, REG_START_BLKADDR); \ +- raw_write(end_addr, REG_END_BLKADDR); \ ++ NFC_SET_ADD_OP_MODE(val); \ ++ NFC_SET_NUM_OF_DEVICE(this->numchips - 1); \ + } + +-#define NFC_SET_NFC_ACTIVE_CS(val) +-#define NFC_SET_WPC(val) val ++#define NFC_SET_ST_CMD(val) \ ++ raw_write((raw_read(NFC_CONFIG2) & \ ++ (NFC_FIELD_RESET(NFC_ST_CMD_WIDTH, \ ++ NFC_ST_CMD_SHITF))) | \ ++ ((val) << NFC_ST_CMD_SHITF), NFC_CONFIG2); + +-/* NULL Definitions */ +-#define ACK_OPS +-#define NFC_SET_RBA(val) raw_write(val, REG_NFC_SET_RBA); ++#define NFMS_NF_DWIDTH 0 ++#define NFMS_NF_PG_SZ 1 ++#define NFC_CMD_1_SHIFT 8 ++ ++#define NUM_OF_ADDR_CYCLE ((ffs(~(info->page_mask)) - 1) >> 3) ++ ++/*should set the fw,ps,spas,ppb*/ ++#define NFC_SET_NFMS(v) \ ++do { \ ++ NFC_SET_FW(NFC_FW_8); \ ++ if (((v) & (1 << NFMS_NF_DWIDTH))) \ ++ NFC_SET_FW(NFC_FW_16); \ ++ if (((v) & (1 << NFMS_NF_PG_SZ))) { \ ++ if (IS_2K_PAGE_NAND) { \ ++ NFC_SET_PS(NFC_PS_2K); \ ++ NFC_SET_NFC_NUM_ADDR_PHASE1(NUM_OF_ADDR_CYCLE); \ ++ NFC_SET_NFC_NUM_ADDR_PHASE0(NFC_TWO_LESS_PHASE1); \ ++ } else if (IS_4K_PAGE_NAND) { \ ++ NFC_SET_PS(NFC_PS_4K); \ ++ NFC_SET_NFC_NUM_ADDR_PHASE1(NUM_OF_ADDR_CYCLE); \ ++ NFC_SET_NFC_NUM_ADDR_PHASE0(NFC_TWO_LESS_PHASE1); \ ++ } else { \ ++ NFC_SET_PS(NFC_PS_512); \ ++ NFC_SET_NFC_NUM_ADDR_PHASE1(NUM_OF_ADDR_CYCLE - 1); \ ++ NFC_SET_NFC_NUM_ADDR_PHASE0(NFC_ONE_LESS_PHASE1); \ ++ } \ ++ NFC_SET_ADD_CS_MODE(1); \ ++ NFC_SET_SPAS(GET_NAND_OOB_SIZE >> 1); \ ++ NFC_SET_ECC_MODE(GET_NAND_OOB_SIZE >> 1); \ ++ NFC_SET_ST_CMD(0x70); \ ++ raw_write(raw_read(NFC_CONFIG3) | 1 << 20, NFC_CONFIG3); \ ++ } \ ++} while (0) + + #define READ_PAGE() send_read_page(0) + #define PROG_PAGE() send_prog_page(0) +-#define CHECK_NFC_RB 1 + + #endif /* __MXC_NAND_H__ */ +diff --git a/include/configs/mx51_3stack.h b/include/configs/mx51_3stack.h +index ae91982..7446c39 100644 +--- a/include/configs/mx51_3stack.h ++++ b/include/configs/mx51_3stack.h +@@ -58,7 +58,7 @@ + /* + * Size of malloc() pool + */ +-#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 512 * 1024) ++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 2 * 1024 * 1024) + /* size in bytes reserved for initial data */ + #define CONFIG_SYS_GBL_DATA_SIZE 128 + +@@ -83,7 +83,8 @@ + #define CONFIG_CMD_PING + #define CONFIG_CMD_DHCP + /* Enable below configure when supporting nand */ +-/* #define CONFIG_CMD_NAND */ ++#define CONFIG_CMD_NAND ++#define CONFIG_CMD_ENV + #undef CONFIG_CMD_IMLS + + #define CONFIG_BOOTDELAY 3 +@@ -172,16 +173,15 @@ + /*----------------------------------------------------------------------- + * NAND FLASH driver setup + */ +-#define NAND_MAX_CHIPS 1 ++#define NAND_MAX_CHIPS 8 + #define CONFIG_SYS_MAX_NAND_DEVICE 1 + #define CONFIG_SYS_NAND_BASE 0x40000000 + + /* Monitor at beginning of flash */ +-#define CONFIG_ENV_IS_NOWHERE 1 +-#define CONFIG_ENV_SECT_SIZE (128 * 1024) ++#define CONFIG_ENV_IS_IN_NAND 1 ++#define CONFIG_ENV_SECT_SIZE (1024 * 1024) + #define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE +-/* #define CFG_ENV_ADDR (CFG_MONITOR_BASE + CFG_ENV_SECT_SIZE) */ +-#define CONFIG_ENV_OFFSET 0x40000 ++#define CONFIG_ENV_OFFSET 0x100000 + /* + * JFFS2 partitions + */ +diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h +index 24ad2bd..1ed2cb6 100644 +--- a/include/linux/mtd/nand.h ++++ b/include/linux/mtd/nand.h +@@ -55,8 +55,8 @@ extern void nand_wait_ready(struct mtd_info *mtd); + * is supported now. If you add a chip with bigger oobsize/page + * adjust this accordingly. + */ +-#define NAND_MAX_OOBSIZE 128 +-#define NAND_MAX_PAGESIZE 4096 ++#define NAND_MAX_OOBSIZE (218 * NAND_MAX_CHIPS) ++#define NAND_MAX_PAGESIZE (4096 * NAND_MAX_CHIPS) + + /* + * Constants for hardware specific CLE/ALE/NCE function +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0017-ENGR00110586-MX31-Resolve-Copyright-issue-for-mx31.patch +++ uboot-imx-2009.01/debian/patches/0017-ENGR00110586-MX31-Resolve-Copyright-issue-for-mx31.patch @@ -0,0 +1,37 @@ +From cb4c05f8d869406646a0d14152cb9bcacc5dd273 Mon Sep 17 00:00:00 2001 +From: r65388 +Date: Tue, 31 Mar 2009 16:21:41 +0800 +Subject: [PATCH] ENGR00110586 MX31: Resolve Copyright issue for mx31 files + +Add freescale copyright. + +Signed-off-by: r65388 +--- + cpu/arm1136/mx31/interrupts.c | 1 + + include/asm-arm/arch-mx31/mx31-regs.h | 1 + + 2 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/cpu/arm1136/mx31/interrupts.c b/cpu/arm1136/mx31/interrupts.c +index 7ad7001..82cc77f 100644 +--- a/cpu/arm1136/mx31/interrupts.c ++++ b/cpu/arm1136/mx31/interrupts.c +@@ -1,4 +1,5 @@ + /* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * +diff --git a/include/asm-arm/arch-mx31/mx31-regs.h b/include/asm-arm/arch-mx31/mx31-regs.h +index 83ac646..321c8b2 100644 +--- a/include/asm-arm/arch-mx31/mx31-regs.h ++++ b/include/asm-arm/arch-mx31/mx31-regs.h +@@ -1,5 +1,6 @@ + /* + * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. + * (c) 2007 Pengutronix, Sascha Hauer + * + * See file CREDITS for list of people who contributed to this +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0012-OMAP3-Add-common-board-interrupt-and-system-info.patch +++ uboot-imx-2009.01/debian/patches/0012-OMAP3-Add-common-board-interrupt-and-system-info.patch @@ -0,0 +1,950 @@ +From 81fba29f2fbfc821595ce327b88b35e769f563ad Mon Sep 17 00:00:00 2001 +From: Dirk Behme +Date: Sun, 14 Dec 2008 09:47:15 +0100 +Subject: [PATCH] OMAP3: Add common board, interrupt and system info + +Add common board, interrupt and system info code. + +Signed-off-by: Dirk Behme +(cherry picked from commit 91eee546737ae21d930af479530997174c342b13) +--- + cpu/arm_cortexa8/omap3/board.c | 344 +++++++++++++++++++++++++++++++++++ + cpu/arm_cortexa8/omap3/interrupts.c | 297 ++++++++++++++++++++++++++++++ + cpu/arm_cortexa8/omap3/sys_info.c | 254 ++++++++++++++++++++++++++ + examples/Makefile | 4 + + 4 files changed, 899 insertions(+), 0 deletions(-) + +diff --git a/cpu/arm_cortexa8/omap3/board.c b/cpu/arm_cortexa8/omap3/board.c +new file mode 100644 +index 0000000..7bb3e28 +--- /dev/null ++++ b/cpu/arm_cortexa8/omap3/board.c +@@ -0,0 +1,344 @@ ++/* ++ * ++ * Common board functions for OMAP3 based boards. ++ * ++ * (C) Copyright 2004-2008 ++ * Texas Instruments, ++ * ++ * Author : ++ * Sunil Kumar ++ * Shashi Ranjan ++ * ++ * Derived from Beagle Board and 3430 SDP code by ++ * Richard Woodruff ++ * Syed Mohammed Khasim ++ * ++ * ++ * 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 ++#include ++#include ++#include ++ ++extern omap3_sysinfo sysinfo; ++ ++/****************************************************************************** ++ * Routine: delay ++ * Description: spinning delay to use before udelay works ++ *****************************************************************************/ ++static inline void delay(unsigned long loops) ++{ ++ __asm__ volatile ("1:\n" "subs %0, %1, #1\n" ++ "bne 1b":"=r" (loops):"0"(loops)); ++} ++ ++/****************************************************************************** ++ * Routine: secure_unlock ++ * Description: Setup security registers for access ++ * (GP Device only) ++ *****************************************************************************/ ++void secure_unlock_mem(void) ++{ ++ pm_t *pm_rt_ape_base = (pm_t *)PM_RT_APE_BASE_ADDR_ARM; ++ pm_t *pm_gpmc_base = (pm_t *)PM_GPMC_BASE_ADDR_ARM; ++ pm_t *pm_ocm_ram_base = (pm_t *)PM_OCM_RAM_BASE_ADDR_ARM; ++ pm_t *pm_iva2_base = (pm_t *)PM_IVA2_BASE_ADDR_ARM; ++ sms_t *sms_base = (sms_t *)OMAP34XX_SMS_BASE; ++ ++ /* Protection Module Register Target APE (PM_RT) */ ++ writel(UNLOCK_1, &pm_rt_ape_base->req_info_permission_1); ++ writel(UNLOCK_1, &pm_rt_ape_base->read_permission_0); ++ writel(UNLOCK_1, &pm_rt_ape_base->wirte_permission_0); ++ writel(UNLOCK_2, &pm_rt_ape_base->addr_match_1); ++ ++ writel(UNLOCK_3, &pm_gpmc_base->req_info_permission_0); ++ writel(UNLOCK_3, &pm_gpmc_base->read_permission_0); ++ writel(UNLOCK_3, &pm_gpmc_base->wirte_permission_0); ++ ++ writel(UNLOCK_3, &pm_ocm_ram_base->req_info_permission_0); ++ writel(UNLOCK_3, &pm_ocm_ram_base->read_permission_0); ++ writel(UNLOCK_3, &pm_ocm_ram_base->wirte_permission_0); ++ writel(UNLOCK_2, &pm_ocm_ram_base->addr_match_2); ++ ++ /* IVA Changes */ ++ writel(UNLOCK_3, &pm_iva2_base->req_info_permission_0); ++ writel(UNLOCK_3, &pm_iva2_base->read_permission_0); ++ writel(UNLOCK_3, &pm_iva2_base->wirte_permission_0); ++ ++ /* SDRC region 0 public */ ++ writel(UNLOCK_1, &sms_base->rg_att0); ++} ++ ++/****************************************************************************** ++ * Routine: secureworld_exit() ++ * Description: If chip is EMU and boot type is external ++ * configure secure registers and exit secure world ++ * general use. ++ *****************************************************************************/ ++void secureworld_exit() ++{ ++ unsigned long i; ++ ++ /* configrue non-secure access control register */ ++ __asm__ __volatile__("mrc p15, 0, %0, c1, c1, 2":"=r"(i)); ++ /* enabling co-processor CP10 and CP11 accesses in NS world */ ++ __asm__ __volatile__("orr %0, %0, #0xC00":"=r"(i)); ++ /* ++ * allow allocation of locked TLBs and L2 lines in NS world ++ * allow use of PLE registers in NS world also ++ */ ++ __asm__ __volatile__("orr %0, %0, #0x70000":"=r"(i)); ++ __asm__ __volatile__("mcr p15, 0, %0, c1, c1, 2":"=r"(i)); ++ ++ /* Enable ASA in ACR register */ ++ __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i)); ++ __asm__ __volatile__("orr %0, %0, #0x10":"=r"(i)); ++ __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i)); ++ ++ /* Exiting secure world */ ++ __asm__ __volatile__("mrc p15, 0, %0, c1, c1, 0":"=r"(i)); ++ __asm__ __volatile__("orr %0, %0, #0x31":"=r"(i)); ++ __asm__ __volatile__("mcr p15, 0, %0, c1, c1, 0":"=r"(i)); ++} ++ ++/****************************************************************************** ++ * Routine: setup_auxcr() ++ * Description: Write to AuxCR desired value using SMI. ++ * general use. ++ *****************************************************************************/ ++void setup_auxcr() ++{ ++ unsigned long i; ++ volatile unsigned int j; ++ /* Save r0, r12 and restore them after usage */ ++ __asm__ __volatile__("mov %0, r12":"=r"(j)); ++ __asm__ __volatile__("mov %0, r0":"=r"(i)); ++ ++ /* ++ * GP Device ROM code API usage here ++ * r12 = AUXCR Write function and r0 value ++ */ ++ __asm__ __volatile__("mov r12, #0x3"); ++ __asm__ __volatile__("mrc p15, 0, r0, c1, c0, 1"); ++ /* Enabling ASA */ ++ __asm__ __volatile__("orr r0, r0, #0x10"); ++ /* Enable L1NEON */ ++ __asm__ __volatile__("orr r0, r0, #1 << 5"); ++ /* SMI instruction to call ROM Code API */ ++ __asm__ __volatile__(".word 0xE1600070"); ++ __asm__ __volatile__("mov r0, %0":"=r"(i)); ++ __asm__ __volatile__("mov r12, %0":"=r"(j)); ++} ++ ++/****************************************************************************** ++ * Routine: try_unlock_sram() ++ * Description: If chip is GP/EMU(special) type, unlock the SRAM for ++ * general use. ++ *****************************************************************************/ ++void try_unlock_memory() ++{ ++ int mode; ++ int in_sdram = is_running_in_sdram(); ++ ++ /* ++ * if GP device unlock device SRAM for general use ++ * secure code breaks for Secure/Emulation device - HS/E/T ++ */ ++ mode = get_device_type(); ++ if (mode == GP_DEVICE) ++ secure_unlock_mem(); ++ ++ /* ++ * If device is EMU and boot is XIP external booting ++ * Unlock firewalls and disable L2 and put chip ++ * out of secure world ++ * ++ * Assuming memories are unlocked by the demon who put us in SDRAM ++ */ ++ if ((mode <= EMU_DEVICE) && (get_boot_type() == 0x1F) ++ && (!in_sdram)) { ++ secure_unlock_mem(); ++ secureworld_exit(); ++ } ++ ++ return; ++} ++ ++/****************************************************************************** ++ * Routine: s_init ++ * Description: Does early system init of muxing and clocks. ++ * - Called path is with SRAM stack. ++ *****************************************************************************/ ++void s_init(void) ++{ ++ int in_sdram = is_running_in_sdram(); ++ ++ watchdog_init(); ++ ++ try_unlock_memory(); ++ ++ /* ++ * Right now flushing at low MPU speed. ++ * Need to move after clock init ++ */ ++ v7_flush_dcache_all(get_device_type()); ++#ifndef CONFIG_ICACHE_OFF ++ icache_enable(); ++#endif ++ ++#ifdef CONFIG_L2_OFF ++ l2cache_disable(); ++#else ++ l2cache_enable(); ++#endif ++ /* ++ * Writing to AuxCR in U-boot using SMI for GP DEV ++ * Currently SMI in Kernel on ES2 devices seems to have an issue ++ * Once that is resolved, we can postpone this config to kernel ++ */ ++ if (get_device_type() == GP_DEVICE) ++ setup_auxcr(); ++ ++ set_muxconf_regs(); ++ delay(100); ++ ++ prcm_init(); ++ ++ per_clocks_enable(); ++ ++ if (!in_sdram) ++ sdrc_init(); ++} ++ ++/****************************************************************************** ++ * Routine: wait_for_command_complete ++ * Description: Wait for posting to finish on watchdog ++ *****************************************************************************/ ++void wait_for_command_complete(watchdog_t *wd_base) ++{ ++ int pending = 1; ++ do { ++ pending = readl(&wd_base->wwps); ++ } while (pending); ++} ++ ++/****************************************************************************** ++ * Routine: watchdog_init ++ * Description: Shut down watch dogs ++ *****************************************************************************/ ++void watchdog_init(void) ++{ ++ watchdog_t *wd2_base = (watchdog_t *)WD2_BASE; ++ prcm_t *prcm_base = (prcm_t *)PRCM_BASE; ++ ++ /* ++ * There are 3 watch dogs WD1=Secure, WD2=MPU, WD3=IVA. WD1 is ++ * either taken care of by ROM (HS/EMU) or not accessible (GP). ++ * We need to take care of WD2-MPU or take a PRCM reset. WD3 ++ * should not be running and does not generate a PRCM reset. ++ */ ++ ++ sr32(&prcm_base->fclken_wkup, 5, 1, 1); ++ sr32(&prcm_base->iclken_wkup, 5, 1, 1); ++ wait_on_value(ST_WDT2, 0x20, &prcm_base->idlest_wkup, 5); ++ ++ writel(WD_UNLOCK1, &wd2_base->wspr); ++ wait_for_command_complete(wd2_base); ++ writel(WD_UNLOCK2, &wd2_base->wspr); ++} ++ ++/****************************************************************************** ++ * Routine: dram_init ++ * Description: sets uboots idea of sdram size ++ *****************************************************************************/ ++int dram_init(void) ++{ ++ DECLARE_GLOBAL_DATA_PTR; ++ unsigned int size0 = 0, size1 = 0; ++ u32 btype; ++ ++ btype = get_board_type(); ++ ++ display_board_info(btype); ++ ++ /* ++ * If a second bank of DDR is attached to CS1 this is ++ * where it can be started. Early init code will init ++ * memory on CS0. ++ */ ++ if ((sysinfo.mtype == DDR_COMBO) || (sysinfo.mtype == DDR_STACKED)) { ++ do_sdrc_init(CS1, NOT_EARLY); ++ make_cs1_contiguous(); ++ } ++ ++ size0 = get_sdr_cs_size(CS0); ++ size1 = get_sdr_cs_size(CS1); ++ ++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1; ++ gd->bd->bi_dram[0].size = size0; ++ gd->bd->bi_dram[1].start = PHYS_SDRAM_1 + get_sdr_cs_offset(CS1); ++ gd->bd->bi_dram[1].size = size1; ++ ++ return 0; ++} ++ ++/****************************************************************************** ++ * Dummy function to handle errors for EABI incompatibility ++ *****************************************************************************/ ++void raise(void) ++{ ++} ++ ++/****************************************************************************** ++ * Dummy function to handle errors for EABI incompatibility ++ *****************************************************************************/ ++void abort(void) ++{ ++} ++ ++#ifdef CONFIG_NAND_OMAP_GPMC ++/****************************************************************************** ++ * OMAP3 specific command to switch between NAND HW and SW ecc ++ *****************************************************************************/ ++static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) ++{ ++ if (argc != 2) ++ goto usage; ++ if (strncmp(argv[1], "hw", 2) == 0) ++ omap_nand_switch_ecc(1); ++ else if (strncmp(argv[1], "sw", 2) == 0) ++ omap_nand_switch_ecc(0); ++ else ++ goto usage; ++ ++ return 0; ++ ++usage: ++ printf ("Usage: nandecc %s\n", cmdtp->help); ++ return 1; ++} ++ ++U_BOOT_CMD( ++ nandecc, 2, 1, do_switch_ecc, ++ "nandecc - switch OMAP3 NAND ECC calculation algorithm\n", ++ "[hw/sw] - Switch between NAND hardware (hw) or software (sw) ecc algorithm\n" ++ ); ++ ++#endif /* CONFIG_NAND_OMAP_GPMC */ +diff --git a/cpu/arm_cortexa8/omap3/interrupts.c b/cpu/arm_cortexa8/omap3/interrupts.c +new file mode 100644 +index 0000000..9e9817d +--- /dev/null ++++ b/cpu/arm_cortexa8/omap3/interrupts.c +@@ -0,0 +1,297 @@ ++/* ++ * (C) Copyright 2008 ++ * Texas Instruments ++ * ++ * Richard Woodruff ++ * Syed Moahmmed Khasim ++ * ++ * (C) Copyright 2002 ++ * Sysgo Real-Time Solutions, GmbH ++ * Marius Groeger ++ * Alex Zuepke ++ * ++ * (C) Copyright 2002 ++ * Gary Jennejohn, 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 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 ++#include ++#include ++ ++#define TIMER_LOAD_VAL 0 ++ ++#ifdef CONFIG_USE_IRQ ++/* enable IRQ interrupts */ ++void enable_interrupts(void) ++{ ++ unsigned long temp; ++ __asm__ __volatile__("mrs %0, cpsr\n" ++ "bic %0, %0, #0x80\n" "msr cpsr_c, %0":"=r"(temp) ++ ::"memory"); ++} ++ ++/* ++ * disable IRQ/FIQ interrupts ++ * returns true if interrupts had been enabled before we disabled them ++ */ ++int disable_interrupts(void) ++{ ++ unsigned long old, temp; ++ __asm__ __volatile__("mrs %0, cpsr\n" ++ "orr %1, %0, #0xc0\n" ++ "msr cpsr_c, %1":"=r"(old), "=r"(temp) ++ ::"memory"); ++ return (old & 0x80) == 0; ++} ++#else ++void enable_interrupts(void) ++{ ++ return; ++} ++int disable_interrupts(void) ++{ ++ return 0; ++} ++#endif ++ ++void bad_mode(void) ++{ ++ panic("Resetting CPU ...\n"); ++ reset_cpu(0); ++} ++ ++void show_regs(struct pt_regs *regs) ++{ ++ unsigned long flags; ++ const char *processor_modes[] = { ++ "USER_26", "FIQ_26", "IRQ_26", "SVC_26", ++ "UK4_26", "UK5_26", "UK6_26", "UK7_26", ++ "UK8_26", "UK9_26", "UK10_26", "UK11_26", ++ "UK12_26", "UK13_26", "UK14_26", "UK15_26", ++ "USER_32", "FIQ_32", "IRQ_32", "SVC_32", ++ "UK4_32", "UK5_32", "UK6_32", "ABT_32", ++ "UK8_32", "UK9_32", "UK10_32", "UND_32", ++ "UK12_32", "UK13_32", "UK14_32", "SYS_32", ++ }; ++ ++ flags = condition_codes(regs); ++ ++ printf("pc : [<%08lx>] lr : [<%08lx>]\n" ++ "sp : %08lx ip : %08lx fp : %08lx\n", ++ instruction_pointer(regs), ++ regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); ++ printf("r10: %08lx r9 : %08lx r8 : %08lx\n", ++ regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); ++ printf("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", ++ regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); ++ printf("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", ++ regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); ++ printf("Flags: %c%c%c%c", ++ flags & CC_N_BIT ? 'N' : 'n', ++ flags & CC_Z_BIT ? 'Z' : 'z', ++ flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); ++ printf(" IRQs %s FIQs %s Mode %s%s\n", ++ interrupts_enabled(regs) ? "on" : "off", ++ fast_interrupts_enabled(regs) ? "on" : "off", ++ processor_modes[processor_mode(regs)], ++ thumb_mode(regs) ? " (T)" : ""); ++} ++ ++void do_undefined_instruction(struct pt_regs *pt_regs) ++{ ++ printf("undefined instruction\n"); ++ show_regs(pt_regs); ++ bad_mode(); ++} ++ ++void do_software_interrupt(struct pt_regs *pt_regs) ++{ ++ printf("software interrupt\n"); ++ show_regs(pt_regs); ++ bad_mode(); ++} ++ ++void do_prefetch_abort(struct pt_regs *pt_regs) ++{ ++ printf("prefetch abort\n"); ++ show_regs(pt_regs); ++ bad_mode(); ++} ++ ++void do_data_abort(struct pt_regs *pt_regs) ++{ ++ printf("data abort\n"); ++ show_regs(pt_regs); ++ bad_mode(); ++} ++ ++void do_not_used(struct pt_regs *pt_regs) ++{ ++ printf("not used\n"); ++ show_regs(pt_regs); ++ bad_mode(); ++} ++ ++void do_fiq(struct pt_regs *pt_regs) ++{ ++ printf("fast interrupt request\n"); ++ show_regs(pt_regs); ++ bad_mode(); ++} ++ ++void do_irq(struct pt_regs *pt_regs) ++{ ++ printf("interrupt request\n"); ++ show_regs(pt_regs); ++ bad_mode(); ++} ++ ++ ++static ulong timestamp; ++static ulong lastinc; ++static gptimer_t *timer_base = (gptimer_t *)CONFIG_SYS_TIMERBASE; ++ ++/* nothing really to do with interrupts, just starts up a counter. */ ++int interrupt_init(void) ++{ ++ /* start the counter ticking up, reload value on overflow */ ++ writel(TIMER_LOAD_VAL, &timer_base->tldr); ++ /* enable timer */ ++ writel((CONFIG_SYS_PVT << 2) | TCLR_PRE | TCLR_AR | TCLR_ST, ++ &timer_base->tclr); ++ ++ reset_timer_masked(); /* init the timestamp and lastinc value */ ++ ++ return 0; ++} ++ ++/* ++ * timer without interrupts ++ */ ++void reset_timer(void) ++{ ++ reset_timer_masked(); ++} ++ ++ulong get_timer(ulong base) ++{ ++ return get_timer_masked() - base; ++} ++ ++void set_timer(ulong t) ++{ ++ timestamp = t; ++} ++ ++/* delay x useconds AND perserve advance timstamp value */ ++void udelay(unsigned long usec) ++{ ++ ulong tmo, tmp; ++ ++ /* if "big" number, spread normalization to seconds */ ++ if (usec >= 1000) { ++ /* if "big" number, spread normalization to seconds */ ++ tmo = usec / 1000; ++ /* find number of "ticks" to wait to achieve target */ ++ tmo *= CONFIG_SYS_HZ; ++ tmo /= 1000; /* finish normalize. */ ++ } else {/* else small number, don't kill it prior to HZ multiply */ ++ tmo = usec * CONFIG_SYS_HZ; ++ tmo /= (1000 * 1000); ++ } ++ ++ tmp = get_timer(0); /* get current timestamp */ ++ /* if setting this forward will roll time stamp */ ++ if ((tmo + tmp + 1) < tmp) ++ /* reset "advancing" timestamp to 0, set lastinc value */ ++ reset_timer_masked(); ++ else ++ tmo += tmp; /* else, set advancing stamp wake up time */ ++ while (get_timer_masked() < tmo) /* loop till event */ ++ /*NOP*/; ++} ++ ++void reset_timer_masked(void) ++{ ++ /* reset time, capture current incrementer value time */ ++ lastinc = readl(&timer_base->tcrr); ++ timestamp = 0; /* start "advancing" time stamp from 0 */ ++} ++ ++ulong get_timer_masked(void) ++{ ++ ulong now = readl(&timer_base->tcrr); /* current tick value */ ++ ++ if (now >= lastinc) /* normal mode (non roll) */ ++ /* move stamp fordward with absoulte diff ticks */ ++ timestamp += (now - lastinc); ++ else /* we have rollover of incrementer */ ++ timestamp += (0xFFFFFFFF - lastinc) + now; ++ lastinc = now; ++ return timestamp; ++} ++ ++/* waits specified delay value and resets timestamp */ ++void udelay_masked(unsigned long usec) ++{ ++ ulong tmo; ++ ulong endtime; ++ signed long diff; ++ ++ /* if "big" number, spread normalization to seconds */ ++ if (usec >= 1000) { ++ /* start to normalize for usec to ticks per sec */ ++ tmo = usec / 1000; ++ /* find number of "ticks" to wait to achieve target */ ++ tmo *= CONFIG_SYS_HZ; ++ tmo /= 1000; /* finish normalize. */ ++ } else { /* else small number, */ ++ /* don't kill it prior to HZ multiply */ ++ tmo = usec * CONFIG_SYS_HZ; ++ tmo /= (1000 * 1000); ++ } ++ endtime = get_timer_masked() + tmo; ++ ++ do { ++ ulong now = get_timer_masked(); ++ diff = endtime - now; ++ } while (diff >= 0); ++} ++ ++/* ++ * This function is derived from PowerPC code (read timebase as long long). ++ * On ARM it just returns the timer value. ++ */ ++unsigned long long get_ticks(void) ++{ ++ return get_timer(0); ++} ++ ++/* ++ * This function is derived from PowerPC code (timebase clock frequency). ++ * On ARM it returns the number of timer ticks per second. ++ */ ++ulong get_tbclk(void) ++{ ++ ulong tbclk; ++ tbclk = CONFIG_SYS_HZ; ++ return tbclk; ++} +diff --git a/cpu/arm_cortexa8/omap3/sys_info.c b/cpu/arm_cortexa8/omap3/sys_info.c +new file mode 100644 +index 0000000..ab012b6 +--- /dev/null ++++ b/cpu/arm_cortexa8/omap3/sys_info.c +@@ -0,0 +1,254 @@ ++/* ++ * (C) Copyright 2008 ++ * Texas Instruments, ++ * ++ * Author : ++ * Manikandan Pillai ++ * ++ * Derived from Beagle Board and 3430 SDP code by ++ * Richard Woodruff ++ * Syed Mohammed Khasim ++ * ++ * 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 ++#include ++#include /* get mem tables */ ++#include ++#include ++ ++extern omap3_sysinfo sysinfo; ++static gpmc_csx_t *gpmc_cs_base = (gpmc_csx_t *)GPMC_CONFIG_CS0_BASE; ++static sdrc_t *sdrc_base = (sdrc_t *)OMAP34XX_SDRC_BASE; ++static ctrl_t *ctrl_base = (ctrl_t *)OMAP34XX_CTRL_BASE; ++ ++/****************************************** ++ * get_cpu_rev(void) - extract version info ++ ******************************************/ ++u32 get_cpu_rev(void) ++{ ++ u32 cpuid = 0; ++ ++ /* ++ * On ES1.0 the IDCODE register is not exposed on L4 ++ * so using CPU ID to differentiate ++ * between ES2.0 and ES1.0. ++ */ ++ __asm__ __volatile__("mrc p15, 0, %0, c0, c0, 0":"=r"(cpuid)); ++ if ((cpuid & 0xf) == 0x0) ++ return CPU_3430_ES1; ++ else ++ return CPU_3430_ES2; ++ ++} ++ ++/**************************************************** ++ * is_mem_sdr() - return 1 if mem type in use is SDR ++ ****************************************************/ ++u32 is_mem_sdr(void) ++{ ++ if (readl(&sdrc_base->cs[CS0].mr) == SDP_SDRC_MR_0_SDR) ++ return 1; ++ return 0; ++} ++ ++/*********************************************************************** ++ * get_cs0_size() - get size of chip select 0/1 ++ ************************************************************************/ ++u32 get_sdr_cs_size(u32 cs) ++{ ++ u32 size; ++ ++ /* get ram size field */ ++ size = readl(&sdrc_base->cs[cs].mcfg) >> 8; ++ size &= 0x3FF; /* remove unwanted bits */ ++ size *= SZ_2M; /* find size in MB */ ++ return size; ++} ++ ++/*********************************************************************** ++ * get_sdr_cs_offset() - get offset of cs from cs0 start ++ ************************************************************************/ ++u32 get_sdr_cs_offset(u32 cs) ++{ ++ u32 offset; ++ ++ if (!cs) ++ return 0; ++ ++ offset = readl(&sdrc_base->cs_cfg); ++ offset = (offset & 15) << 27 | (offset & 0x30) >> 17; ++ ++ return offset; ++} ++ ++/*********************************************************************** ++ * get_board_type() - get board type based on current production stats. ++ * - NOTE-1-: 2 I2C EEPROMs will someday be populated with proper info. ++ * when they are available we can get info from there. This should ++ * be correct of all known boards up until today. ++ * - NOTE-2- EEPROMs are populated but they are updated very slowly. To ++ * avoid waiting on them we will use ES version of the chip to get info. ++ * A later version of the FPGA migth solve their speed issue. ++ ************************************************************************/ ++u32 get_board_type(void) ++{ ++ if (get_cpu_rev() == CPU_3430_ES2) ++ return sysinfo.board_type_v2; ++ else ++ return sysinfo.board_type_v1; ++} ++ ++/*************************************************************************** ++ * get_gpmc0_base() - Return current address hardware will be ++ * fetching from. The below effectively gives what is correct, its a bit ++ * mis-leading compared to the TRM. For the most general case the mask ++ * needs to be also taken into account this does work in practice. ++ * - for u-boot we currently map: ++ * -- 0 to nothing, ++ * -- 4 to flash ++ * -- 8 to enent ++ * -- c to wifi ++ ****************************************************************************/ ++u32 get_gpmc0_base(void) ++{ ++ u32 b; ++ ++ b = readl(&gpmc_cs_base->config7); ++ b &= 0x1F; /* keep base [5:0] */ ++ b = b << 24; /* ret 0x0b000000 */ ++ return b; ++} ++ ++/******************************************************************* ++ * get_gpmc0_width() - See if bus is in x8 or x16 (mainly for nand) ++ *******************************************************************/ ++u32 get_gpmc0_width(void) ++{ ++ return WIDTH_16BIT; ++} ++ ++/************************************************************************* ++ * get_board_rev() - setup to pass kernel board revision information ++ * returns:(bit[0-3] sub version, higher bit[7-4] is higher version) ++ *************************************************************************/ ++u32 get_board_rev(void) ++{ ++ return 0x20; ++} ++ ++/********************************************************************* ++ * display_board_info() - print banner with board info. ++ *********************************************************************/ ++void display_board_info(u32 btype) ++{ ++ char *mem_s, *sec_s; ++ ++ if (is_mem_sdr()) ++ mem_s = "mSDR"; ++ else ++ mem_s = "LPDDR"; ++ ++ switch (get_device_type()) { ++ case TST_DEVICE: ++ sec_s = "TST"; ++ break; ++ case EMU_DEVICE: ++ sec_s = "EMU"; ++ break; ++ case HS_DEVICE: ++ sec_s = "HS"; ++ break; ++ case GP_DEVICE: ++ sec_s = "GP"; ++ break; ++ default: ++ sec_s = "?"; ++ } ++ ++ printf("OMAP%s-%s rev %d, CPU-OPP2 L3-165MHz\n", sysinfo.cpu_string, ++ sec_s, get_cpu_rev()); ++ printf("%s + %s/%s\n", sysinfo.board_string, ++ mem_s, sysinfo.nand_string); ++ ++} ++ ++/******************************************************** ++ * get_base(); get upper addr of current execution ++ *******************************************************/ ++u32 get_base(void) ++{ ++ u32 val; ++ ++ __asm__ __volatile__("mov %0, pc \n":"=r"(val)::"memory"); ++ val &= 0xF0000000; ++ val >>= 28; ++ return val; ++} ++ ++/******************************************************** ++ * is_running_in_flash() - tell if currently running in ++ * FLASH. ++ *******************************************************/ ++u32 is_running_in_flash(void) ++{ ++ if (get_base() < 4) ++ return 1; /* in FLASH */ ++ ++ return 0; /* running in SRAM or SDRAM */ ++} ++ ++/******************************************************** ++ * is_running_in_sram() - tell if currently running in ++ * SRAM. ++ *******************************************************/ ++u32 is_running_in_sram(void) ++{ ++ if (get_base() == 4) ++ return 1; /* in SRAM */ ++ ++ return 0; /* running in FLASH or SDRAM */ ++} ++ ++/******************************************************** ++ * is_running_in_sdram() - tell if currently running in ++ * SDRAM. ++ *******************************************************/ ++u32 is_running_in_sdram(void) ++{ ++ if (get_base() > 4) ++ return 1; /* in SDRAM */ ++ ++ return 0; /* running in SRAM or FLASH */ ++} ++ ++/*************************************************************** ++ * get_boot_type() - Is this an XIP type device or a stream one ++ * bits 4-0 specify type. Bit 5 says mem/perif ++ ***************************************************************/ ++u32 get_boot_type(void) ++{ ++ return (readl(&ctrl_base->status) & SYSBOOT_MASK); ++} ++ ++/************************************************************* ++ * get_device_type(): tell if GP/HS/EMU/TST ++ *************************************************************/ ++u32 get_device_type(void) ++{ ++ return ((readl(&ctrl_base->status) & (DEVICE_MASK)) >> 8); ++} +diff --git a/examples/Makefile b/examples/Makefile +index b0a8853..927010d 100644 +--- a/examples/Makefile ++++ b/examples/Makefile +@@ -33,9 +33,13 @@ ifeq ($(ARCH),arm) + ifeq ($(BOARD),omap2420h4) + LOAD_ADDR = 0x80300000 + else ++ifeq ($(CPU),omap3) ++LOAD_ADDR = 0x80300000 ++else + LOAD_ADDR = 0xc100000 + endif + endif ++endif + + ifeq ($(ARCH),mips) + LOAD_ADDR = 0x80200000 -T mips.lds +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0021-ENGR00113148-Add-build-option-to-uboot-for-different.patch +++ uboot-imx-2009.01/debian/patches/0021-ENGR00113148-Add-build-option-to-uboot-for-different.patch @@ -0,0 +1,107 @@ +From 8c653797987aeb6466fd23b1430cf7211fe120c5 Mon Sep 17 00:00:00 2001 +From: Jason +Date: Mon, 8 Jun 2009 20:13:39 +0800 +Subject: [PATCH] ENGR00113148 Add build option to uboot for different media type + +1. Add build option to uboot for different media type +2. fix the spi-nor link error + +Signed-off-by:Jason Liu +--- + config.mk | 6 ++++++ + drivers/mtd/spi/imx_spi_nor.c | 2 +- + include/configs/imx51.h | 14 ++++++-------- + tools/Makefile | 6 ++++++ + 4 files changed, 19 insertions(+), 9 deletions(-) + +diff --git a/config.mk b/config.mk +index b1254e9..7705e82 100644 +--- a/config.mk ++++ b/config.mk +@@ -124,6 +124,12 @@ gccincdir := $(shell $(CC) -print-file-name=include) + + CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) \ + -D__KERNEL__ ++ ++ifneq ($(BOOT_MEDIA),) ++ BOOT_MEDIA_MACRO = BOOT_MEDIA_$(shell echo $(BOOT_MEDIA) | tr '[a-z]' '[A-Z]') ++ CPPFLAGS += -D$(BOOT_MEDIA_MACRO) ++endif ++ + ifneq ($(TEXT_BASE),) + CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) + endif +diff --git a/drivers/mtd/spi/imx_spi_nor.c b/drivers/mtd/spi/imx_spi_nor.c +index 24af8b2..a912a3f 100644 +--- a/drivers/mtd/spi/imx_spi_nor.c ++++ b/drivers/mtd/spi/imx_spi_nor.c +@@ -321,7 +321,7 @@ static int spi_nor_flash_write(struct spi_flash *flash, u32 offset, + if (len == 0) + return 0; + +- write("%s(flash addr=0x%08x, ram=%p, len=0x%x)\n", ++ debug("%s(flash addr=0x%08x, ram=%p, len=0x%x)\n", + __func__, offset, buf, len); + + if (ENABLE_WRITE_STATUS(flash) != 0 || +diff --git a/include/configs/imx51.h b/include/configs/imx51.h +index 1808b67..238457e 100644 +--- a/include/configs/imx51.h ++++ b/include/configs/imx51.h +@@ -68,10 +68,10 @@ + #define CONFIG_MX51_UART 1 + #define CONFIG_MX51_UART1 1 + ++#if defined(BOOT_MEDIA_SPI_NOR) + /* + * SPI Configs +- * */ +-/* ++ */ + #define CONFIG_FSL_SF 1 + #define CONFIG_CMD_SPI + #define CONFIG_CMD_SF +@@ -80,19 +80,17 @@ + #define CONFIG_IMX_SPI + #define CONFIG_IMX_SPI_PMIC + #define CONFIG_IMX_SPI_PMIC_CS 0 +- + #define MAX_SPI_BYTES (64 * 4) +-*/ + ++#elif defined(BOOT_MEDIA_MMC) + /* + * MMC Configs +- * */ +- +-/* ++ */ + #define CONFIG_FSL_MMC 1 + #define CONFIG_DOS_PARTITION 1 + #define CONFIG_CMD_FAT 1 +-*/ ++ ++#endif + + /* allow to overwrite serial and ethaddr */ + #define CONFIG_ENV_OVERWRITE +diff --git a/tools/Makefile b/tools/Makefile +index 9e9ee15..27afc8d 100644 +--- a/tools/Makefile ++++ b/tools/Makefile +@@ -125,6 +125,12 @@ CPPFLAGS = -idirafter $(SRCTREE)/include \ + -idirafter $(OBJTREE)/include2 \ + -idirafter $(OBJTREE)/include \ + -DTEXT_BASE=$(TEXT_BASE) -DUSE_HOSTCC ++ ++ifneq ($(BOOT_MEDIA),) ++ BOOT_MEDIA_MACRO := BOOT_MEDIA_$(shell echo $(BOOT_MEDIA) | tr '[a-z]' '[A-Z]') ++ CPPFLAGS += -D$(BOOT_MEDIA_MACRO) ++endif ++ + CFLAGS = $(HOST_CFLAGS) $(CPPFLAGS) -O + + # No -pedantic switch to avoid libfdt compilation warnings +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0013-ENGR00108473-Porting-i.MX51-3stack-TO2-support-to-V2.patch +++ uboot-imx-2009.01/debian/patches/0013-ENGR00108473-Porting-i.MX51-3stack-TO2-support-to-V2.patch @@ -0,0 +1,4114 @@ +From c878dfb5f2f2e034c279a5a422f8cbfbd4af8f08 Mon Sep 17 00:00:00 2001 +From: Fred Fan +Date: Wed, 25 Feb 2009 13:53:30 +0800 +Subject: [PATCH] ENGR00108473 Porting i.MX51 3stack TO2 support to V2009.01 + +Support i.MX51 TO2.0 3stack board. And enable LAN9217 support. +NAND is not supported in this patch. + +Signed-off-by: Fred Fan +--- + Makefile | 3 + + board/freescale/mx51_3stack/Makefile | 49 ++ + board/freescale/mx51_3stack/board-mx51_3stack.h | 64 +++ + board/freescale/mx51_3stack/config.mk | 1 + + board/freescale/mx51_3stack/flash_header.S | 113 ++++ + board/freescale/mx51_3stack/lowlevel_init.S | 303 ++++++++++ + board/freescale/mx51_3stack/mx51_3stack.c | 211 +++++++ + board/freescale/mx51_3stack/u-boot.lds | 72 +++ + cpu/arm_cortexa8/config.mk | 6 +- + cpu/arm_cortexa8/cpu.c | 5 + + cpu/arm_cortexa8/mx51/Makefile | 48 ++ + cpu/arm_cortexa8/mx51/crm_regs.h | 669 +++++++++++++++++++++++ + cpu/arm_cortexa8/mx51/generic.c | 182 ++++++ + cpu/arm_cortexa8/mx51/interrupts.c | 113 ++++ + cpu/arm_cortexa8/mx51/iomux.c | 199 +++++++ + cpu/arm_cortexa8/mx51/mxc_nand_load.S | 167 ++++++ + cpu/arm_cortexa8/mx51/serial.c | 226 ++++++++ + cpu/arm_cortexa8/start.S | 4 +- + drivers/mtd/nand/Makefile | 1 + + drivers/net/smc911x.c | 9 + + include/asm-arm/arch-mx51/iomux.h | 240 ++++++++ + include/asm-arm/arch-mx51/mx51.h | 423 ++++++++++++++ + include/asm-arm/arch-mx51/mx51_pins.h | 370 +++++++++++++ + include/asm-arm/arch-mx51/mxc_nand.h | 198 +++++++ + include/configs/mx51_3stack.h | 191 +++++++ + 25 files changed, 3865 insertions(+), 2 deletions(-) + +diff --git a/Makefile b/Makefile +index f02e9c3..1b5172d 100644 +--- a/Makefile ++++ b/Makefile +@@ -2970,6 +2970,9 @@ mx31_3stack_config : unconfig + mx35_3stack_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm1136 mx35_3stack freescale mx35 + ++mx51_3stack_config : unconfig ++ @$(MKCONFIG) $(@:_config=) arm arm_cortexa8 mx51_3stack freescale mx51 ++ + omap2420h4_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm1136 omap2420h4 NULL omap24xx + +diff --git a/board/freescale/mx51_3stack/Makefile b/board/freescale/mx51_3stack/Makefile +new file mode 100644 +index 0000000..f665a2d +--- /dev/null ++++ b/board/freescale/mx51_3stack/Makefile +@@ -0,0 +1,49 @@ ++# ++# Copyright (C) 2007, Guennadi Liakhovetski ++# ++# (C) Copyright 2009 Freescale Semiconductor, Inc. ++# ++# 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 := mx51_3stack.o ++SOBJS := lowlevel_init.o flash_header.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 .depend ++ ++######################################################################### ++ ++# defines $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +diff --git a/board/freescale/mx51_3stack/board-mx51_3stack.h b/board/freescale/mx51_3stack/board-mx51_3stack.h +new file mode 100644 +index 0000000..d7c30c1 +--- /dev/null ++++ b/board/freescale/mx51_3stack/board-mx51_3stack.h +@@ -0,0 +1,64 @@ ++/* ++ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#ifndef __BOARD_FREESCALE_BOARD_MX51_3STACK_H__ ++#define __BOARD_FREESCALE_BOARD_MX51_3STACK_H__ ++ ++/*! ++ * @defgroup BRDCFG_MX51 Board Configuration Options ++ * @ingroup MSL_MX51 ++ */ ++ ++/*! ++ * @file mx51_3stack/board-mx51_3stack.h ++ * ++ * @brief This file contains all the board level configuration options. ++ * ++ * It currently hold the options defined for MX51 3Stack Platform. ++ * ++ * @ingroup BRDCFG_MX51 ++ */ ++ ++/* CPLD offsets */ ++#define PBC_LED_CTRL (0x20000) ++#define PBC_SB_STAT (0x20008) ++#define PBC_ID_AAAA (0x20040) ++#define PBC_ID_5555 (0x20048) ++#define PBC_VERSION (0x20050) ++#define PBC_ID_CAFE (0x20058) ++#define PBC_INT_STAT (0x20010) ++#define PBC_INT_MASK (0x20038) ++#define PBC_INT_REST (0x20020) ++#define PBC_SW_RESET (0x20060) ++ ++/* LED switchs */ ++#define LED_SWITCH_REG 0x00 ++/* buttons */ ++#define SWITCH_BUTTONS_REG 0x08 ++/* status, interrupt */ ++#define INTR_STATUS_REG 0x10 ++#define INTR_MASK_REG 0x38 ++#define INTR_RESET_REG 0x20 ++/* magic word for debug CPLD */ ++#define MAGIC_NUMBER1_REG 0x40 ++#define MAGIC_NUMBER2_REG 0x48 ++/* CPLD code version */ ++#define CPLD_CODE_VER_REG 0x50 ++/* magic word for debug CPLD */ ++#define MAGIC_NUMBER3_REG 0x58 ++/* module reset register*/ ++#define MODULE_RESET_REG 0x60 ++/* CPU ID and Personality ID */ ++#define MCU_BOARD_ID_REG 0x68 ++ ++#endif /* __BOARD_FREESCALE_BOARD_MX51_3STACK_H__ */ +diff --git a/board/freescale/mx51_3stack/config.mk b/board/freescale/mx51_3stack/config.mk +new file mode 100644 +index 0000000..ce7369d +--- /dev/null ++++ b/board/freescale/mx51_3stack/config.mk +@@ -0,0 +1 @@ ++TEXT_BASE = 0x97800000 +diff --git a/board/freescale/mx51_3stack/flash_header.S b/board/freescale/mx51_3stack/flash_header.S +new file mode 100644 +index 0000000..794ab6b +--- /dev/null ++++ b/board/freescale/mx51_3stack/flash_header.S +@@ -0,0 +1,113 @@ ++/* ++ * Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include "board-mx51_3stack.h" ++ ++#ifdef CONFIG_FLASH_HEADER ++#ifndef CONFIG_FLASH_HEADER_OFFSET ++# error "Must define the offset of flash header" ++#endif ++#define MXC_DCD_ITEM(i, type, addr, val) \ ++dcd_node_##i: \ ++ .word type ; \ ++ .word addr ; \ ++ .word val ; \ ++ ++.section ".text.flasheader", "x" ++ b _start ++ .org CONFIG_FLASH_HEADER_OFFSET ++app_code_jump_v: .word _start ++app_code_code_barker: .word CONFIG_FLASH_HEADER_BARKER ++app_code_csf: .word 0 ++dcd_ptr_ptr: .word dcd_ptr ++super_root_key: .word 0 ++dcd_ptr: .word dcd_array_start ++app_dest_ptr: .word TEXT_BASE ++dcd_array_start: ++magic: .word 0xB17219E9 ++dcd_array_size: .word dcd_data_end - dcd_array_start - 8 ++/* DCD */ ++/* DDR2 IOMUX configuration */ ++MXC_DCD_ITEM(1, 4, IOMUXC_BASE_ADDR + 0x8a0, 0x200) ++MXC_DCD_ITEM(2, 4, IOMUXC_BASE_ADDR + 0x50c, 0x20c5) ++MXC_DCD_ITEM(3, 4, IOMUXC_BASE_ADDR + 0x510, 0x20c5) ++MXC_DCD_ITEM(4, 4, IOMUXC_BASE_ADDR + 0x83c, 0x2) ++MXC_DCD_ITEM(5, 4, IOMUXC_BASE_ADDR + 0x848, 0x2) ++MXC_DCD_ITEM(6, 4, IOMUXC_BASE_ADDR + 0x4b8, 0xe7) ++MXC_DCD_ITEM(7, 4, IOMUXC_BASE_ADDR + 0x4bc, 0x45) ++MXC_DCD_ITEM(8, 4, IOMUXC_BASE_ADDR + 0x4c0, 0x45) ++MXC_DCD_ITEM(9, 4, IOMUXC_BASE_ADDR + 0x4c4, 0x45) ++MXC_DCD_ITEM(10, 4, IOMUXC_BASE_ADDR + 0x4c8, 0x45) ++MXC_DCD_ITEM(11, 4, IOMUXC_BASE_ADDR + 0x820, 0x0) ++MXC_DCD_ITEM(12, 4, IOMUXC_BASE_ADDR + 0x4a4, 0x3) ++MXC_DCD_ITEM(13, 4, IOMUXC_BASE_ADDR + 0x4a8, 0x3) ++MXC_DCD_ITEM(14, 4, IOMUXC_BASE_ADDR + 0x4ac, 0xe3) ++MXC_DCD_ITEM(15, 4, IOMUXC_BASE_ADDR + 0x4b0, 0xe3) ++MXC_DCD_ITEM(16, 4, IOMUXC_BASE_ADDR + 0x4b4, 0xe3) ++MXC_DCD_ITEM(17, 4, IOMUXC_BASE_ADDR + 0x4cc, 0xe3) ++MXC_DCD_ITEM(18, 4, IOMUXC_BASE_ADDR + 0x4d0, 0xe2) ++/* Set drive strength to MAX */ ++MXC_DCD_ITEM(19, 4, IOMUXC_BASE_ADDR + 0x82c, 0x6) ++MXC_DCD_ITEM(20, 4, IOMUXC_BASE_ADDR + 0x8a4, 0x6) ++MXC_DCD_ITEM(21, 4, IOMUXC_BASE_ADDR + 0x8ac, 0x6) ++MXC_DCD_ITEM(22, 4, IOMUXC_BASE_ADDR + 0x8b8, 0x6) ++/* 13 ROW, 10 COL, 32Bit, SREF=4 Micron Model */ ++/* CAS=3, BL=4 */ ++MXC_DCD_ITEM(23, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL0, 0x82a20000) ++MXC_DCD_ITEM(24, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL1, 0x82a20000) ++MXC_DCD_ITEM(25, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDMISC, 0x000ad0d0) ++MXC_DCD_ITEM(26, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCFG0, 0x333574aa) ++MXC_DCD_ITEM(27, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCFG1, 0x333574aa) ++/* Init DRAM on CS0 */ ++MXC_DCD_ITEM(28, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x04008008) ++MXC_DCD_ITEM(29, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801a) ++MXC_DCD_ITEM(30, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801b) ++MXC_DCD_ITEM(31, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00448019) ++MXC_DCD_ITEM(32, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x07328018) ++MXC_DCD_ITEM(33, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x04008008) ++MXC_DCD_ITEM(34, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008010) ++MXC_DCD_ITEM(35, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008010) ++MXC_DCD_ITEM(36, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x06328018) ++MXC_DCD_ITEM(37, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x03808019) ++MXC_DCD_ITEM(38, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00408019) ++MXC_DCD_ITEM(39, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008000) ++/* Init DRAM on CS1 */ ++MXC_DCD_ITEM(40, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0400800c) ++MXC_DCD_ITEM(41, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801e) ++MXC_DCD_ITEM(42, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801f) ++MXC_DCD_ITEM(43, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801d) ++MXC_DCD_ITEM(44, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0732801c) ++MXC_DCD_ITEM(45, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0400800c) ++MXC_DCD_ITEM(46, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008014) ++MXC_DCD_ITEM(47, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008014) ++MXC_DCD_ITEM(48, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0632801c) ++MXC_DCD_ITEM(49, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0380801d) ++MXC_DCD_ITEM(50, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0040801d) ++MXC_DCD_ITEM(51, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008004) ++MXC_DCD_ITEM(52, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL0, 0xb2a20000) ++MXC_DCD_ITEM(53, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL1, 0xb2a20000) ++MXC_DCD_ITEM(54, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDMISC, 0x000ad6d0) ++MXC_DCD_ITEM(55, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCDLYGD, 0x90000000) ++MXC_DCD_ITEM(56, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00000000) ++dcd_data_end: ++image_len: .word 0x40000 ++//image_len: .word _end - _start ++#endif +diff --git a/board/freescale/mx51_3stack/lowlevel_init.S b/board/freescale/mx51_3stack/lowlevel_init.S +new file mode 100644 +index 0000000..fa15ddf +--- /dev/null ++++ b/board/freescale/mx51_3stack/lowlevel_init.S +@@ -0,0 +1,303 @@ ++/* ++ * Copyright (C) 2007, Guennadi Liakhovetski ++ * ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include "board-mx51_3stack.h" ++ ++/* ++ * return soc version ++ * 0x10: TO1 ++ * 0x20: TO2 ++ * 0x30: TO3 ++ */ ++.macro check_soc_version ret, tmp ++.endm ++ ++/* ++ * L2CC Cache setup/invalidation/disable ++ */ ++.macro init_l2cc ++ /* reconfigure L2 cache aux control reg */ ++ ldr r0, =0x03C000C4 ++ mcr p15, 1, r0, c9, c0, 2 ++.endm /* init_l2cc */ ++ ++/* AIPS setup - Only setup MPROTx registers. ++ * The PACR default values are good.*/ ++.macro init_aips ++ /* ++ * Set all MPROTx to be non-bufferable, trusted for R/W, ++ * not forced to user-mode. ++ */ ++ ldr r0, =AIPS1_BASE_ADDR ++ ldr r1, =0x77777777 ++ str r1, [r0, #0x0] ++ str r1, [r0, #0x4] ++ ldr r0, =AIPS2_BASE_ADDR ++ str r1, [r0, #0x0] ++ str r1, [r0, #0x4] ++ /* ++ * Clear the on and off peripheral modules Supervisor Protect bit ++ * for SDMA to access them. Did not change the AIPS control registers ++ * (offset 0x20) access type ++ */ ++.endm /* init_aips */ ++ ++/* MAX (Multi-Layer AHB Crossbar Switch) setup */ ++.macro init_max ++.endm /* init_max */ ++ ++/* M4IF setup */ ++.macro init_m4if ++ /* VPU and IPU given higher priority (0x4) ++ * IPU accesses with ID=0x1 given highest priority (=0xA) ++ */ ++ ldr r0, =M4IF_BASE_ADDR ++ ldr r1, =0x00000a01 ++ str r1, [r0, #0x48] ++ ldr r1, =0x00000404 ++ str r1, [r0, #0x40] ++.endm /* init_m4if */ ++ ++/* To support 133MHz DDR */ ++.macro init_drive_strength ++.endm /* init_drive_strength */ ++ ++/* CPLD on CS5 setup */ ++.macro init_debug_board ++.endm /* init_debug_board */ ++ ++.macro setup_pll pll, freq ++ ldr r2, =\pll ++ ldr r1, =0x00001232 ++ str r1, [r2, #PLL_DP_CTL] /* Set DPLL ON (set UPEN bit): BRMO=1 */ ++ mov r1, #0x2 ++ str r1, [r2, #PLL_DP_CONFIG] /* Enable auto-restart AREN bit */ ++ ++ str r3, [r2, #PLL_DP_OP] ++ str r3, [r2, #PLL_DP_HFS_OP] ++ ++ str r4, [r2, #PLL_DP_MFD] ++ str r4, [r2, #PLL_DP_HFS_MFD] ++ ++ str r5, [r2, #PLL_DP_MFN] ++ str r5, [r2, #PLL_DP_HFS_MFN] ++ ++ ldr r1, =0x00001232 ++ str r1, [r2, #PLL_DP_CTL] ++1: ldr r1, [r2, #PLL_DP_CTL] ++ ands r1, r1, #0x1 ++ beq 1b ++.endm ++ ++.macro init_clock ++ ldr r0, =CCM_BASE_ADDR ++ mov r1, #0x00060000 ++ str r1, [r0, #CLKCTL_CCDR] ++ ++ /* Switch ARM to step clock */ ++ mov r1, #0x4 ++ str r1, [r0, #CLKCTL_CCSR] ++ ++ mov r3, #DP_OP_800 ++ mov r4, #DP_MFD_800 ++ mov r5, #DP_MFN_800 ++ setup_pll PLL1_BASE_ADDR ++ mov r3, #DP_OP_665 ++ mov r4, #DP_MFD_665 ++ mov r5, #DP_MFN_665 ++ setup_pll PLL3_BASE_ADDR ++ ++ /* Switch peripheral to PLL 3 */ ++ ldr r1, =0x0000D3C0 ++ str r1, [r0, #CLKCTL_CBCMR] ++ ldr r1, =0x033B9145 ++ str r1, [r0, #CLKCTL_CBCDR] ++ mov r3, #DP_OP_665 ++ mov r4, #DP_MFD_665 ++ mov r5, #DP_MFN_665 ++ setup_pll PLL2_BASE_ADDR ++ ++ /* Switch peripheral to PLL2 */ ++ ldr r1, =0x013B9145 ++ str r1, [r0, #CLKCTL_CBCDR] ++ ldr r1, =0x0000E3C0 ++ str r1, [r0, #CLKCTL_CBCMR] ++ ++ mov r3, #DP_OP_216 ++ mov r4, #DP_MFD_216 ++ mov r5, #DP_MFN_216 ++ setup_pll PLL3_BASE_ADDR ++ ++ /* Set the platform clock dividers */ ++ ldr r2, =ARM_BASE_ADDR ++ ldr r1, =0x00000725 ++ str r1, [r2, #0x14] ++ ++ /* Switch ARM back to PLL 1 */ ++ mov r1, #0 ++ str r1, [r0, #CLKCTL_CCSR] ++ str r1, [r0, #CLKCTL_CACRR] ++ ++ /* Use lp_apm (24MHz) source for perclk */ ++ mov r2, #0x48 ++ ldr r2, [r0] ++ cmp r2, #0x10 ++ ldrhs r1, =0x000020C2 ++ ldrlo r1, =0x0000E3C2 ++ str r1, [r0, #CLKCTL_CBCMR] ++ /* TO1.x emi = ahb, all perclk dividers are 1 since using 24MHz */ ++ /* TO2.x ddr from PLL1, all perclk dividers are 1 since using 24MHz */ ++ ldrhs r1, =0x59239100 ++ ldrlo r1, =0x013D9100 ++ strlo r1, [r0, #CLKCTL_CBCDR] ++ ++ /* use PLL2 for UART source, get 66.5MHz */ ++ ldr r1, =0xA5A2A020 ++ str r1, [r0, #CLKCTL_CSCMR1] ++ ldr r1, =0x00C30321 ++ str r1, [r0, #CLKCTL_CSCDR1] ++ ++ /* make sure divider effective */ ++1: ldr r1, [r0, #CLKCTL_CDHIPR] ++ cmp r1, #0 ++ bne 1b ++ ++ mov r1, #0x0 ++ str r1, [r0, #CLKCTL_CCDR] ++.endm ++ ++.macro setup_wdog ++ ldr r0, =WDOG1_BASE_ADDR ++ mov r1, #0x30 ++ strh r1, [r0] ++.endm ++ ++.macro setup_sdram ++ ldr r0, =ESDCTL_BASE_ADDR ++ mov r2, #0x48 ++ ldr r2, [r2] ++ cmp r2, #0x10 ++ bhs 1f ++ /* Set CSD0 */ ++ mov r1, #0x80000000 ++ str r1, [r0, #ESDCTL_ESDCTL0] ++ /* Precharge command */ ++ ldr r1, DDR_PERCHARGE_CMD ++ str r1, [r0, #ESDCTL_ESDSCR] ++ /* 2 refresh commands */ ++ ldr r1, DDR_REFRESH_CMD ++ str r1, [r0, #ESDCTL_ESDSCR] ++ str r1, [r0, #ESDCTL_ESDSCR] ++ /* LMR with CAS=3 and BL=3 */ ++ ldr r1, DDR_LMR1_W ++ str r1, [r0, #ESDCTL_ESDSCR] ++ /* 13 ROW, 10 COL, 32Bit, SREF=4 Micron Model */ ++ ldr r1, DDR_LMR_CMD ++ str r1, [r0, #ESDCTL_ESDCTL0] ++ /* Timing parameters */ ++ ldr r1, DDR_TIMING_W ++ str r1, [r0, #ESDCTL_ESDCFG0] ++ /* MDDR enable, RLAT=2 */ ++ ldr r1, DDR_MISC_W ++ str r1, [r0, #ESDCTL_ESDMISC] ++ /* Normal mode */ ++ mov r1, #0x00000000 ++ str r1, [r0, #ESDCTL_ESDSCR] ++1: ++.endm /* setup_sdram */ ++ ++.section ".text.init", "x" ++ ++.globl lowlevel_init ++lowlevel_init: ++ /* Platform CHIP level init*/ ++#ifdef TURN_OFF_IMPRECISE_ABORT ++ mrs r0, cpsr ++ bic r0, r0, #0x100 ++ msr cpsr, r0 ++#endif ++ ++ mrc 15, 0, r1, c1, c0, 0 ++ ++#ifndef BRANCH_PREDICTION_ENABLE ++ mrc 15, 0, r0, c1, c0, 1 ++ bic r0, r0, #7 ++ mcr 15, 0, r0, c1, c0, 1 ++#else ++ mrc 15, 0, r0, c1, c0, 1 ++ orr r0, r0, #7 ++ mcr 15, 0, r0, c1, c0, 1 ++ orr r1, r1, #(1<<11) ++#endif ++ ++#ifdef UNALIGNED_ACCESS_ENABLE ++ orr r1, r1, #(1<<22) ++#endif ++ ++#ifdef LOW_INT_LATENCY_ENABLE ++ orr r1, r1, #(1<<21) ++#endif ++ mcr 15, 0, r1, c1, c0, 0 ++ ++ mov r0, #0 ++#ifdef BRANCH_PREDICTION_ENABLE ++ mcr 15, 0, r0, c15, c2, 4 ++#endif ++ mcr 15, 0, r0, c7, c10, 4 /* Drain the write buffer */ ++ ++ init_l2cc ++ ++ init_aips ++ ++ setup_wdog ++ ++ init_max ++ ++ init_m4if ++ ++ init_drive_strength ++ ++ cmp pc, #PHYS_SDRAM_1 ++ blo do_sdram_setup ++ cmp pc, #(PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE) ++ blo init_clock_start ++ ++do_sdram_setup: ++ setup_sdram ++ ++init_clock_start: ++ init_clock ++ init_debug_board ++ /*init_sdram*/ ++ ++ /* return from mxc_nand_load */ ++ /* r12 saved upper lr*/ ++ b mxc_nand_load ++ ++/* Board level setting value */ ++DDR_PERCHARGE_CMD: .word 0x04008008 ++DDR_REFRESH_CMD: .word 0x00008010 ++DDR_LMR1_W: .word 0x00338018 ++DDR_LMR_CMD: .word 0xB2220000 ++DDR_TIMING_W: .word 0xB02567A9 ++DDR_MISC_W: .word 0x000A0104 +diff --git a/board/freescale/mx51_3stack/mx51_3stack.c b/board/freescale/mx51_3stack/mx51_3stack.c +new file mode 100644 +index 0000000..c7f93aa +--- /dev/null ++++ b/board/freescale/mx51_3stack/mx51_3stack.c +@@ -0,0 +1,211 @@ ++/* ++ * Copyright (C) 2007, Guennadi Liakhovetski ++ * ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include "board-mx51_3stack.h" ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++static u32 system_rev; ++u32 mx51_io_base_addr; ++ ++u32 get_board_rev(void) ++{ ++ return system_rev; ++} ++ ++static inline void setup_soc_rev(void) ++{ ++ int reg; ++ reg = __REG(ROM_SI_REV); ++ switch (reg) { ++ case 0x02: ++ system_rev = 0x51000 | CHIP_REV_1_1; ++ break; ++ case 0x10: ++ system_rev = 0x51000 | CHIP_REV_2_0; ++ break; ++ default: ++ system_rev = 0x51000 | CHIP_REV_1_0; ++ } ++} ++ ++static inline void set_board_rev(int rev) ++{ ++ system_rev |= (rev & 0xF) << 8; ++} ++ ++inline int is_soc_rev(int rev) ++{ ++ return (system_rev & 0xFF) - rev; ++} ++ ++int dram_init(void) ++{ ++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1; ++ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; ++ return 0; ++} ++ ++static void setup_uart(void) ++{ ++ unsigned int pad = PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | ++ PAD_CTL_PUE_PULL | PAD_CTL_DRV_HIGH; ++ mxc_request_iomux(MX51_PIN_UART1_RXD, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_UART1_RXD, pad | PAD_CTL_SRE_FAST); ++ mxc_request_iomux(MX51_PIN_UART1_TXD, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_UART1_TXD, pad | PAD_CTL_SRE_FAST); ++ mxc_request_iomux(MX51_PIN_UART1_RTS, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_UART1_RTS, pad); ++ mxc_request_iomux(MX51_PIN_UART1_CTS, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_UART1_CTS, pad); ++} ++ ++void setup_nfc(void) ++{ ++ /* Enable NFC IOMUX */ ++ mxc_request_iomux(MX51_PIN_NANDF_CS0, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS1, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS2, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS3, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS4, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS5, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS6, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS7, IOMUX_CONFIG_ALT0); ++} ++ ++static void setup_expio(void) ++{ ++ u32 reg; ++ /* CS5 setup */ ++ mxc_request_iomux(MX51_PIN_EIM_CS5, IOMUX_CONFIG_ALT0); ++ writel(0x00410089, WEIM_BASE_ADDR + 0x78 + CSGCR1); ++ writel(0x00000002, WEIM_BASE_ADDR + 0x78 + CSGCR2); ++ /* RWSC=50, RADVA=2, RADVN=6, OEA=0, OEN=0, RCSA=0, RCSN=0 */ ++ writel(0x32260000, WEIM_BASE_ADDR + 0x78 + CSRCR1); ++ /* APR = 0 */ ++ writel(0x00000000, WEIM_BASE_ADDR + 0x78 + CSRCR2); ++ /* WAL=0, WBED=1, WWSC=50, WADVA=2, WADVN=6, WEA=0, WEN=0, ++ * WCSA=0, WCSN=0 ++ */ ++ writel(0x72080F00, WEIM_BASE_ADDR + 0x78 + CSWCR1); ++ if ((readw(CS5_BASE_ADDR + PBC_ID_AAAA) == 0xAAAA) && ++ (readw(CS5_BASE_ADDR + PBC_ID_5555) == 0x5555)) { ++ if (is_soc_rev(CHIP_REV_2_0) < 0) { ++ reg = readl(CCM_BASE_ADDR + CLKCTL_CBCDR); ++ reg = (reg & (~0x70000)) | 0x30000; ++ writel(reg, CCM_BASE_ADDR + CLKCTL_CBCDR); ++ /* make sure divider effective */ ++ while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0) ++ ; ++ writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR); ++ } ++ mx51_io_base_addr = CS5_BASE_ADDR; ++ } else { ++ /* CS1 */ ++ writel(0x00410089, WEIM_BASE_ADDR + 0x18 + CSGCR1); ++ writel(0x00000002, WEIM_BASE_ADDR + 0x18 + CSGCR2); ++ /* RWSC=50, RADVA=2, RADVN=6, OEA=0, OEN=0, RCSA=0, RCSN=0 */ ++ writel(0x32260000, WEIM_BASE_ADDR + 0x18 + CSRCR1); ++ /* APR=0 */ ++ writel(0x00000000, WEIM_BASE_ADDR + 0x18 + CSRCR2); ++ /* WAL=0, WBED=1, WWSC=50, WADVA=2, WADVN=6, WEA=0, ++ * WEN=0, WCSA=0, WCSN=0 ++ */ ++ writel(0x72080F00, WEIM_BASE_ADDR + 0x18 + CSWCR1); ++ mx51_io_base_addr = CS1_BASE_ADDR; ++ } ++ ++ /* Reset interrupt status reg */ ++ writew(0x1F, mx51_io_base_addr + PBC_INT_REST); ++ writew(0x00, mx51_io_base_addr + PBC_INT_REST); ++ writew(0xFFFF, mx51_io_base_addr + PBC_INT_MASK); ++ ++ /* Reset the XUART and Ethernet controllers */ ++ reg = readw(mx51_io_base_addr + PBC_SW_RESET); ++ reg |= 0x9; ++ writew(reg, mx51_io_base_addr + PBC_SW_RESET); ++ reg &= ~0x9; ++ writew(reg, mx51_io_base_addr + PBC_SW_RESET); ++} ++ ++int board_init(void) ++{ ++ int pad; ++ setup_soc_rev(); ++ ++ gd->bd->bi_arch_number = MACH_TYPE_MX51_3DS; /* board id for linux */ ++ /* address of boot parameters */ ++ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; ++ ++ setup_uart(); ++ setup_nfc(); ++ setup_expio(); ++ return 0; ++} ++ ++#ifdef BOARD_LATE_INIT ++int board_late_init(void) ++{ ++ return 0; ++} ++#endif ++ ++int checkboard(void) ++{ ++ printf("Board: MX51 3STACK ["); ++ switch (__REG(SRC_BASE_ADDR + 0x8)) { ++ case 0x0001: ++ printf("POR"); ++ break; ++ case 0x0009: ++ printf("RST"); ++ break; ++ case 0x0010: ++ case 0x0011: ++ printf("WDOG"); ++ break; ++ default: ++ printf("unknown"); ++ } ++ printf("]\n"); ++ return 0; ++} ++ ++#ifdef CONFIG_NET_MULTI ++int board_eth_init(bd_t *bis) ++{ ++ int rc = -ENODEV; ++#if defined(CONFIG_DRIVER_SMC911X) ++ rc = smc911x_initialize(bis); ++#endif ++ return rc; ++} ++#endif +diff --git a/board/freescale/mx51_3stack/u-boot.lds b/board/freescale/mx51_3stack/u-boot.lds +new file mode 100644 +index 0000000..1cf3c3d +--- /dev/null ++++ b/board/freescale/mx51_3stack/u-boot.lds +@@ -0,0 +1,72 @@ ++/* ++ * January 2004 - Changed to support H4 device ++ * Copyright (c) 2004 Texas Instruments ++ * ++ * (C) Copyright 2002 ++ * Gary Jennejohn, DENX Software Engineering, ++ * ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 : ++ { ++ /* WARNING - the following is hand-optimized to fit within */ ++ /* the sector layout of our flash chips! XXX FIXME XXX */ ++ board/freescale/mx51_3stack/flash_header.o (.text.flasheader) ++ cpu/arm_cortexa8/start.o ++ board/freescale/mx51_3stack/libmx51_3stack.a (.text) ++ lib_arm/libarm.a (.text) ++ net/libnet.a (.text) ++ drivers/mtd/libmtd.a (.text) ++ ++ . = DEFINED(env_offset) ? env_offset : .; ++ common/env_embedded.o(.text) ++ ++ *(.text) ++ } ++ ++ . = 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 = .; ++} +diff --git a/cpu/arm_cortexa8/config.mk b/cpu/arm_cortexa8/config.mk +index b021762..5a1384c 100644 +--- a/cpu/arm_cortexa8/config.mk ++++ b/cpu/arm_cortexa8/config.mk +@@ -30,7 +30,11 @@ PLATFORM_CPPFLAGS += -march=armv5 + # Supply options according to compiler version + # + # ========================================================================= ++ifdef CONFIG_SYS_APCS_GNU ++PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) ++else + PLATFORM_CPPFLAGS +=$(call cc-option) ++endif + PLATFORM_CPPFLAGS +=$(call cc-option,-mno-thumb-interwork,) + PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,\ +- $(call cc-option,-malignment-traps,)) +\ No newline at end of file ++ $(call cc-option,-malignment-traps,)) +diff --git a/cpu/arm_cortexa8/cpu.c b/cpu/arm_cortexa8/cpu.c +index ebc5ea2..f1ea13c 100644 +--- a/cpu/arm_cortexa8/cpu.c ++++ b/cpu/arm_cortexa8/cpu.c +@@ -33,7 +33,10 @@ + + #include + #include ++ ++#ifndef CONFIG_MXC + #include ++#endif + + #ifdef CONFIG_USE_IRQ + DECLARE_GLOBAL_DATA_PTR; +@@ -170,6 +173,7 @@ void dcache_disable (void) + write_p15_c1 (reg & ~C1_DC); + } + ++#ifndef CONFIG_L2_OFF + void l2cache_enable() + { + unsigned long i; +@@ -228,6 +232,7 @@ void l2cache_disable() + __asm__ __volatile__("mov r12, %0":"=r"(j)); + } + } ++#endif + + int icache_status(void) + { +diff --git a/cpu/arm_cortexa8/mx51/Makefile b/cpu/arm_cortexa8/mx51/Makefile +new file mode 100644 +index 0000000..6f10e3e +--- /dev/null ++++ b/cpu/arm_cortexa8/mx51/Makefile +@@ -0,0 +1,48 @@ ++# ++# (C) Copyright 2000-2006 ++# Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++# ++# (C) Copyright 2009 Freescale Semiconductor, Inc. ++# ++# 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 = interrupts.o serial.o generic.o iomux.o ++SOBJS = mxc_nand_load.o ++ ++SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) ++OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) ++ ++all: $(obj).depend $(LIB) ++ ++$(LIB): $(OBJS) ++ $(AR) $(ARFLAGS) $@ $(OBJS) ++ ++######################################################################### ++ ++# defines $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +diff --git a/cpu/arm_cortexa8/mx51/crm_regs.h b/cpu/arm_cortexa8/mx51/crm_regs.h +new file mode 100644 +index 0000000..8a2b2dc +--- /dev/null ++++ b/cpu/arm_cortexa8/mx51/crm_regs.h +@@ -0,0 +1,669 @@ ++/* ++ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__ ++#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__ ++ ++#define MXC_CCM_BASE CCM_BASE_ADDR ++#define MXC_DPLL1_BASE PLL1_BASE_ADDR ++#define MXC_DPLL2_BASE PLL2_BASE_ADDR ++#define MXC_DPLL3_BASE PLL3_BASE_ADDR ++ ++/* PLL Register Offsets */ ++#define MXC_PLL_DP_CTL 0x00 ++#define MXC_PLL_DP_CONFIG 0x04 ++#define MXC_PLL_DP_OP 0x08 ++#define MXC_PLL_DP_MFD 0x0C ++#define MXC_PLL_DP_MFN 0x10 ++#define MXC_PLL_DP_MFNMINUS 0x14 ++#define MXC_PLL_DP_MFNPLUS 0x18 ++#define MXC_PLL_DP_HFS_OP 0x1C ++#define MXC_PLL_DP_HFS_MFD 0x20 ++#define MXC_PLL_DP_HFS_MFN 0x24 ++#define MXC_PLL_DP_MFN_TOGC 0x28 ++#define MXC_PLL_DP_DESTAT 0x2c ++ ++/* PLL Register Bit definitions */ ++#define MXC_PLL_DP_CTL_MUL_CTRL 0x2000 ++#define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000 ++#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET 12 ++#define MXC_PLL_DP_CTL_ADE 0x800 ++#define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400 ++#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8) ++#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET 8 ++#define MXC_PLL_DP_CTL_HFSM 0x80 ++#define MXC_PLL_DP_CTL_PRE 0x40 ++#define MXC_PLL_DP_CTL_UPEN 0x20 ++#define MXC_PLL_DP_CTL_RST 0x10 ++#define MXC_PLL_DP_CTL_RCP 0x8 ++#define MXC_PLL_DP_CTL_PLM 0x4 ++#define MXC_PLL_DP_CTL_BRM0 0x2 ++#define MXC_PLL_DP_CTL_LRF 0x1 ++ ++#define MXC_PLL_DP_CONFIG_BIST 0x8 ++#define MXC_PLL_DP_CONFIG_SJC_CE 0x4 ++#define MXC_PLL_DP_CONFIG_AREN 0x2 ++#define MXC_PLL_DP_CONFIG_LDREQ 0x1 ++ ++#define MXC_PLL_DP_OP_MFI_OFFSET 4 ++#define MXC_PLL_DP_OP_MFI_MASK (0xF << 4) ++#define MXC_PLL_DP_OP_PDF_OFFSET 0 ++#define MXC_PLL_DP_OP_PDF_MASK 0xF ++ ++#define MXC_PLL_DP_MFD_OFFSET 0 ++#define MXC_PLL_DP_MFD_MASK 0x07FFFFFF ++ ++#define MXC_PLL_DP_MFN_OFFSET 0x0 ++#define MXC_PLL_DP_MFN_MASK 0x07FFFFFF ++ ++#define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17) ++#define MXC_PLL_DP_MFN_TOGC_TOG_EN (1 << 16) ++#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET 0x0 ++#define MXC_PLL_DP_MFN_TOGC_CNT_MASK 0xFFFF ++ ++#define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31) ++#define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF ++ ++/* Register addresses of CCM*/ ++#define MXC_CCM_CCR (MXC_CCM_BASE + 0x00) ++#define MXC_CCM_CCDR (MXC_CCM_BASE + 0x04) ++#define MXC_CCM_CSR (MXC_CCM_BASE + 0x08) ++#define MXC_CCM_CCSR (MXC_CCM_BASE + 0x0C) ++#define MXC_CCM_CACRR (MXC_CCM_BASE + 0x10) ++#define MXC_CCM_CBCDR (MXC_CCM_BASE + 0x14) ++#define MXC_CCM_CBCMR (MXC_CCM_BASE + 0x18) ++#define MXC_CCM_CSCMR1 (MXC_CCM_BASE + 0x1C) ++#define MXC_CCM_CSCMR2 (MXC_CCM_BASE + 0x20) ++#define MXC_CCM_CSCDR1 (MXC_CCM_BASE + 0x24) ++#define MXC_CCM_CS1CDR (MXC_CCM_BASE + 0x28) ++#define MXC_CCM_CS2CDR (MXC_CCM_BASE + 0x2C) ++#define MXC_CCM_CDCDR (MXC_CCM_BASE + 0x30) ++#define MXC_CCM_CHSCDR (MXC_CCM_BASE + 0x34) ++#define MXC_CCM_CSCDR2 (MXC_CCM_BASE + 0x38) ++#define MXC_CCM_CSCDR3 (MXC_CCM_BASE + 0x3C) ++#define MXC_CCM_CSCDR4 (MXC_CCM_BASE + 0x40) ++#define MXC_CCM_CWDR (MXC_CCM_BASE + 0x44) ++#define MXC_CCM_CDHIPR (MXC_CCM_BASE + 0x48) ++#define MXC_CCM_CDCR (MXC_CCM_BASE + 0x4C) ++#define MXC_CCM_CTOR (MXC_CCM_BASE + 0x50) ++#define MXC_CCM_CLPCR (MXC_CCM_BASE + 0x54) ++#define MXC_CCM_CISR (MXC_CCM_BASE + 0x58) ++#define MXC_CCM_CIMR (MXC_CCM_BASE + 0x5C) ++#define MXC_CCM_CCOSR (MXC_CCM_BASE + 0x60) ++#define MXC_CCM_CGPR (MXC_CCM_BASE + 0x64) ++#define MXC_CCM_CCGR0 (MXC_CCM_BASE + 0x68) ++#define MXC_CCM_CCGR1 (MXC_CCM_BASE + 0x6C) ++#define MXC_CCM_CCGR2 (MXC_CCM_BASE + 0x70) ++#define MXC_CCM_CCGR3 (MXC_CCM_BASE + 0x74) ++#define MXC_CCM_CCGR4 (MXC_CCM_BASE + 0x78) ++#define MXC_CCM_CCGR5 (MXC_CCM_BASE + 0x7C) ++#define MXC_CCM_CCGR6 (MXC_CCM_BASE + 0x80) ++#define MXC_CCM_CMEOR (MXC_CCM_BASE + 0x84) ++ ++/* Define the bits in register CCR */ ++#define MXC_CCM_CCR_COSC_EN (1 << 12) ++#define MXC_CCM_CCR_FPM_MULT_MASK (1 << 11) ++#define MXC_CCM_CCR_CAMP2_EN (1 << 10) ++#define MXC_CCM_CCR_CAMP1_EN (1 << 9) ++#define MXC_CCM_CCR_FPM_EN (1 << 8) ++#define MXC_CCM_CCR_OSCNT_OFFSET (0) ++#define MXC_CCM_CCR_OSCNT_MASK (0xFF) ++ ++/* Define the bits in register CCDR */ ++#define MXC_CCM_CCDR_HSC_HS_MASK (0x1 << 18) ++#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17) ++#define MXC_CCM_CCDR_EMI_HS_MASK (0x1 << 16) ++ ++/* Define the bits in register CSR */ ++#define MXC_CCM_CSR_COSR_READY (1 << 5) ++#define MXC_CCM_CSR_LVS_VALUE (1 << 4) ++#define MXC_CCM_CSR_CAMP2_READY (1 << 3) ++#define MXC_CCM_CSR_CAMP1_READY (1 << 2) ++#define MXC_CCM_CSR_FPM_READY (1 << 1) ++#define MXC_CCM_CSR_REF_EN_B (1 << 0) ++ ++/* Define the bits in register CCSR */ ++#define MXC_CCM_CCSR_LP_APM_SEL (0x1 << 9) ++#define MXC_CCM_CCSR_STEP_SEL_OFFSET (7) ++#define MXC_CCM_CCSR_STEP_SEL_MASK (0x3 << 7) ++#define MXC_CCM_CCSR_PLL2_PODF_OFFSET (5) ++#define MXC_CCM_CCSR_PLL2_PODF_MASK (0x3 << 5) ++#define MXC_CCM_CCSR_PLL3_PODF_OFFSET (3) ++#define MXC_CCM_CCSR_PLL3_PODF_MASK (0x3 << 3) ++#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2) ++#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1) ++#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0) ++ ++/* Define the bits in register CACRR */ ++#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0) ++#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7) ++ ++/* Define the bits in register CBCDR */ ++#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26) ++#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25) ++#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22) ++#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22) ++#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19) ++#define MXC_CCM_CBCDR_AXI_B_PODF_MASK (0x7 << 19) ++#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET (16) ++#define MXC_CCM_CBCDR_AXI_A_PODF_MASK (0x7 << 16) ++#define MXC_CCM_CBCDR_NFC_PODF_OFFSET (13) ++#define MXC_CCM_CBCDR_NFC_PODF_MASK (0x7 << 13) ++#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10) ++#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10) ++#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8) ++#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8) ++#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6) ++#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK (0x3 << 6) ++#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3) ++#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK (0x7 << 3) ++#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0) ++#define MXC_CCM_CBCDR_PERCLK_PODF_MASK (0x7) ++ ++/* Define the bits in register CBCMR */ ++#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14) ++#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14) ++#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET (12) ++#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK (0x3 << 12) ++#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET (10) ++#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK (0x3 << 10) ++#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET (8) ++#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK (0x3 << 8) ++#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET (6) ++#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK (0x3 << 6) ++#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET (4) ++#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK (0x3 << 4) ++#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1) ++#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0) ++ ++/* Define the bits in register CSCMR1 */ ++#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30) ++#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK (0x3 << 30) ++#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET (28) ++#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK (0x3 << 28) ++#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET (26) ++#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL (0x1 << 26) ++#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24) ++#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24) ++#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET (22) ++#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK (0x3 << 22) ++#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET (20) ++#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK (0x3 << 20) ++#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL (0x1 << 19) ++#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 18) ++#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET (16) ++#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK (0x3 << 16) ++#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14) ++#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14) ++#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12) ++#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12) ++#define MXC_CCM_CSCMR1_SSI3_CLK_SEL (0x1 << 11) ++#define MXC_CCM_CSCMR1_VPU_RCLK_SEL (0x1 << 10) ++#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET (8) ++#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK (0x3 << 8) ++#define MXC_CCM_CSCMR1_TVE_CLK_SEL (0x1 << 7) ++#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL (0x1 << 6) ++#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4) ++#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4) ++#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET (2) ++#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK (0x3 << 2) ++#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1) ++#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1) ++ ++/* Define the bits in register CSCMR2 */ ++#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET (26) ++#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK (0x7 << 26) ++#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET (24) ++#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK (0x3 << 24) ++#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET (22) ++#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK (0x3 << 22) ++#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET (20) ++#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK (0x3 << 20) ++#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET (18) ++#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK (0x3 << 18) ++#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET (16) ++#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK (0x3 << 16) ++#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET (14) ++#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK (0x3 << 14) ++#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET (12) ++#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK (0x3 << 12) ++#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET (10) ++#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK (0x3 << 10) ++#define MXC_CCM_CSCMR2_SLIMBUS_COM (0x1 << 9) ++#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET (6) ++#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK (0x7 << 6) ++#define MXC_CCM_CSCMR2_SPDIF1_COM (1 << 5) ++#define MXC_CCM_CSCMR2_SPDIF0_COM (1 << 4) ++#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET (2) ++#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK (0x3 << 2) ++#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET (0) ++#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK (0x3) ++ ++/* Define the bits in register CSCDR1 */ ++#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET (22) ++#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22) ++#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET (19) ++#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19) ++#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET (16) ++#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK (0x7 << 16) ++#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14) ++#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14) ++#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET (11) ++#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK (0x7 << 11) ++#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8) ++#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8) ++#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6) ++#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6) ++#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET (3) ++#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3) ++#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0) ++#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7) ++ ++/* Define the bits in register CS1CDR and CS2CDR */ ++#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET (22) ++#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK (0x7 << 22) ++#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET (16) ++#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK (0x3F << 16) ++#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6) ++#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6) ++#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0) ++#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F) ++ ++#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET (22) ++#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK (0x7 << 22) ++#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET (16) ++#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK (0x3F << 16) ++#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6) ++#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6) ++#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0) ++#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F) ++ ++/* Define the bits in register CDCDR */ ++#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET (28) ++#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK (0x7 << 28) ++#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25) ++#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25) ++#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19) ++#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x3F << 19) ++#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (16) ++#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 16) ++#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9) ++#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x3F << 9) ++#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET (6) ++#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK (0x7 << 6) ++#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET (3) ++#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK (0x7 << 3) ++#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET (0) ++#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK (0x7) ++ ++/* Define the bits in register CHSCCDR */ ++#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET (12) ++#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK (0x7 << 12) ++#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET (6) ++#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK (0x3F << 6) ++#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET (3) ++#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK (0x7 << 3) ++#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET (0) ++#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK (0x7) ++ ++/* Define the bits in register CSCDR2 */ ++#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET (25) ++#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK (0x7 << 25) ++#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET (19) ++#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK (0x3F << 19) ++#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET (16) ++#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK (0x7 << 16) ++#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET (9) ++#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK (0x3F << 9) ++#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET (6) ++#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK (0x7 << 6) ++#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET (0) ++#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK (0x3F) ++ ++/* Define the bits in register CSCDR3 */ ++#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET (16) ++#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK (0x7 << 16) ++#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET (9) ++#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK (0x3F << 9) ++#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET (6) ++#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK (0x7 << 6) ++#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET (0) ++#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK (0x3F) ++ ++/* Define the bits in register CSCDR4 */ ++#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET (16) ++#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK (0x7 << 16) ++#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET (9) ++#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK (0x3F << 9) ++#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET (6) ++#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK (0x7 << 6) ++#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET (0) ++#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK (0x3F) ++ ++/* Define the bits in register CDHIPR */ ++#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16) ++#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY (1 << 6) ++#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5) ++#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY (1 << 4) ++#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 3) ++#define MXC_CCM_CDHIPR_EMI_PODF_BUSY (1 << 2) ++#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY (1 << 1) ++#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY (1 << 0) ++ ++/* Define the bits in register CDCR */ ++#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER (0x1 << 2) ++#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET (0) ++#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK (0x3) ++ ++/* Define the bits in register CLPCR */ ++#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS (0x1 << 23) ++#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS (0x1 << 22) ++#define MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 21) ++#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS (0x1 << 20) ++#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS (0x1 << 19) ++#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18) ++#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS (0x1 << 17) ++#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS (0x1 << 16) ++#define MXC_CCM_CLPCR_COSC_PWRDOWN (0x1 << 11) ++#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9) ++#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9) ++#define MXC_CCM_CLPCR_VSTBY (0x1 << 8) ++#define MXC_CCM_CLPCR_DIS_REF_OSC (0x1 << 7) ++#define MXC_CCM_CLPCR_SBYOS (0x1 << 6) ++#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) ++#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3) ++#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3) ++#define MXC_CCM_CLPCR_LPM_OFFSET (0) ++#define MXC_CCM_CLPCR_LPM_MASK (0x3) ++ ++/* Define the bits in register CISR */ ++#define MXC_CCM_CISR_ARM_PODF_LOADED (0x1 << 25) ++#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21) ++#define MXC_CCM_CISR_AHB_PODF_LOADED (0x1 << 20) ++#define MXC_CCM_CISR_EMI_PODF_LOADED (0x1 << 19) ++#define MXC_CCM_CISR_AXI_B_PODF_LOADED (0x1 << 18) ++#define MXC_CCM_CISR_AXI_A_PODF_LOADED (0x1 << 17) ++#define MXC_CCM_CISR_DIVIDER_LOADED (0x1 << 16) ++#define MXC_CCM_CISR_COSC_READY (0x1 << 6) ++#define MXC_CCM_CISR_CKIH2_READY (0x1 << 5) ++#define MXC_CCM_CISR_CKIH_READY (0x1 << 4) ++#define MXC_CCM_CISR_FPM_READY (0x1 << 3) ++#define MXC_CCM_CISR_LRF_PLL3 (0x1 << 2) ++#define MXC_CCM_CISR_LRF_PLL2 (0x1 << 1) ++#define MXC_CCM_CISR_LRF_PLL1 (0x1) ++ ++/* Define the bits in register CIMR */ ++#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (0x1 << 25) ++#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21) ++#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED (0x1 << 20) ++#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED (0x1 << 19) ++#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED (0x1 << 18) ++#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED (0x1 << 17) ++#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED (0x1 << 16) ++#define MXC_CCM_CIMR_MASK_COSC_READY (0x1 << 5) ++#define MXC_CCM_CIMR_MASK_CKIH_READY (0x1 << 4) ++#define MXC_CCM_CIMR_MASK_FPM_READY (0x1 << 3) ++#define MXC_CCM_CIMR_MASK_LRF_PLL3 (0x1 << 2) ++#define MXC_CCM_CIMR_MASK_LRF_PLL2 (0x1 << 1) ++#define MXC_CCM_CIMR_MASK_LRF_PLL1 (0x1) ++ ++/* Define the bits in register CCOSR */ ++#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (0x1 << 24) ++#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21) ++#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21) ++#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16) ++#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16) ++#define MXC_CCM_CCOSR_CKOL_EN (0x1 << 7) ++#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET (4) ++#define MXC_CCM_CCOSR_CKOL_DIV_MASK (0x7 << 4) ++#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET (0) ++#define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF) ++ ++/* Define the bits in registers CGPR */ ++#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (0x1 << 4) ++#define MXC_CCM_CGPR_FPM_SEL (0x1 << 3) ++#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET (0) ++#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK (0x7) ++ ++/* Define the bits in registers CCGRx */ ++#define MXC_CCM_CCGR_CG_MASK 0x3 ++ ++#define MXC_CCM_CCGR0_CG15_OFFSET 30 ++#define MXC_CCM_CCGR0_CG15_MASK (0x3 << 30) ++#define MXC_CCM_CCGR0_CG14_OFFSET 28 ++#define MXC_CCM_CCGR0_CG14_MASK (0x3 << 28) ++#define MXC_CCM_CCGR0_CG13_OFFSET 26 ++#define MXC_CCM_CCGR0_CG13_MASK (0x3 << 26) ++#define MXC_CCM_CCGR0_CG12_OFFSET 24 ++#define MXC_CCM_CCGR0_CG12_MASK (0x3 << 24) ++#define MXC_CCM_CCGR0_CG11_OFFSET 22 ++#define MXC_CCM_CCGR0_CG11_MASK (0x3 << 22) ++#define MXC_CCM_CCGR0_CG10_OFFSET 20 ++#define MXC_CCM_CCGR0_CG10_MASK (0x3 << 20) ++#define MXC_CCM_CCGR0_CG9_OFFSET 18 ++#define MXC_CCM_CCGR0_CG9_MASK (0x3 << 18) ++#define MXC_CCM_CCGR0_CG8_OFFSET 16 ++#define MXC_CCM_CCGR0_CG8_MASK (0x3 << 16) ++#define MXC_CCM_CCGR0_CG7_OFFSET 14 ++#define MXC_CCM_CCGR0_CG6_OFFSET 12 ++#define MXC_CCM_CCGR0_CG5_OFFSET 10 ++#define MXC_CCM_CCGR0_CG5_MASK (0x3 << 10) ++#define MXC_CCM_CCGR0_CG4_OFFSET 8 ++#define MXC_CCM_CCGR0_CG4_MASK (0x3 << 8) ++#define MXC_CCM_CCGR0_CG3_OFFSET 6 ++#define MXC_CCM_CCGR0_CG3_MASK (0x3 << 6) ++#define MXC_CCM_CCGR0_CG2_OFFSET 4 ++#define MXC_CCM_CCGR0_CG2_MASK (0x3 << 4) ++#define MXC_CCM_CCGR0_CG1_OFFSET 2 ++#define MXC_CCM_CCGR0_CG1_MASK (0x3 << 2) ++#define MXC_CCM_CCGR0_CG0_OFFSET 0 ++#define MXC_CCM_CCGR0_CG0_MASK 0x3 ++ ++#define MXC_CCM_CCGR1_CG15_OFFSET 30 ++#define MXC_CCM_CCGR1_CG14_OFFSET 28 ++#define MXC_CCM_CCGR1_CG13_OFFSET 26 ++#define MXC_CCM_CCGR1_CG12_OFFSET 24 ++#define MXC_CCM_CCGR1_CG11_OFFSET 22 ++#define MXC_CCM_CCGR1_CG10_OFFSET 20 ++#define MXC_CCM_CCGR1_CG9_OFFSET 18 ++#define MXC_CCM_CCGR1_CG8_OFFSET 16 ++#define MXC_CCM_CCGR1_CG7_OFFSET 14 ++#define MXC_CCM_CCGR1_CG6_OFFSET 12 ++#define MXC_CCM_CCGR1_CG5_OFFSET 10 ++#define MXC_CCM_CCGR1_CG4_OFFSET 8 ++#define MXC_CCM_CCGR1_CG3_OFFSET 6 ++#define MXC_CCM_CCGR1_CG2_OFFSET 4 ++#define MXC_CCM_CCGR1_CG1_OFFSET 2 ++#define MXC_CCM_CCGR1_CG0_OFFSET 0 ++ ++#define MXC_CCM_CCGR2_CG15_OFFSET 30 ++#define MXC_CCM_CCGR2_CG14_OFFSET 28 ++#define MXC_CCM_CCGR2_CG13_OFFSET 26 ++#define MXC_CCM_CCGR2_CG12_OFFSET 24 ++#define MXC_CCM_CCGR2_CG11_OFFSET 22 ++#define MXC_CCM_CCGR2_CG10_OFFSET 20 ++#define MXC_CCM_CCGR2_CG9_OFFSET 18 ++#define MXC_CCM_CCGR2_CG8_OFFSET 16 ++#define MXC_CCM_CCGR2_CG7_OFFSET 14 ++#define MXC_CCM_CCGR2_CG6_OFFSET 12 ++#define MXC_CCM_CCGR2_CG5_OFFSET 10 ++#define MXC_CCM_CCGR2_CG4_OFFSET 8 ++#define MXC_CCM_CCGR2_CG3_OFFSET 6 ++#define MXC_CCM_CCGR2_CG2_OFFSET 4 ++#define MXC_CCM_CCGR2_CG1_OFFSET 2 ++#define MXC_CCM_CCGR2_CG0_OFFSET 0 ++ ++#define MXC_CCM_CCGR3_CG15_OFFSET 30 ++#define MXC_CCM_CCGR3_CG14_OFFSET 28 ++#define MXC_CCM_CCGR3_CG13_OFFSET 26 ++#define MXC_CCM_CCGR3_CG12_OFFSET 24 ++#define MXC_CCM_CCGR3_CG11_OFFSET 22 ++#define MXC_CCM_CCGR3_CG10_OFFSET 20 ++#define MXC_CCM_CCGR3_CG9_OFFSET 18 ++#define MXC_CCM_CCGR3_CG8_OFFSET 16 ++#define MXC_CCM_CCGR3_CG7_OFFSET 14 ++#define MXC_CCM_CCGR3_CG6_OFFSET 12 ++#define MXC_CCM_CCGR3_CG5_OFFSET 10 ++#define MXC_CCM_CCGR3_CG4_OFFSET 8 ++#define MXC_CCM_CCGR3_CG3_OFFSET 6 ++#define MXC_CCM_CCGR3_CG2_OFFSET 4 ++#define MXC_CCM_CCGR3_CG1_OFFSET 2 ++#define MXC_CCM_CCGR3_CG0_OFFSET 0 ++ ++#define MXC_CCM_CCGR4_CG15_OFFSET 30 ++#define MXC_CCM_CCGR4_CG14_OFFSET 28 ++#define MXC_CCM_CCGR4_CG13_OFFSET 26 ++#define MXC_CCM_CCGR4_CG12_OFFSET 24 ++#define MXC_CCM_CCGR4_CG11_OFFSET 22 ++#define MXC_CCM_CCGR4_CG10_OFFSET 20 ++#define MXC_CCM_CCGR4_CG9_OFFSET 18 ++#define MXC_CCM_CCGR4_CG8_OFFSET 16 ++#define MXC_CCM_CCGR4_CG7_OFFSET 14 ++#define MXC_CCM_CCGR4_CG6_OFFSET 12 ++#define MXC_CCM_CCGR4_CG5_OFFSET 10 ++#define MXC_CCM_CCGR4_CG4_OFFSET 8 ++#define MXC_CCM_CCGR4_CG3_OFFSET 6 ++#define MXC_CCM_CCGR4_CG2_OFFSET 4 ++#define MXC_CCM_CCGR4_CG1_OFFSET 2 ++#define MXC_CCM_CCGR4_CG0_OFFSET 0 ++ ++#define MXC_CCM_CCGR5_CG15_OFFSET 30 ++#define MXC_CCM_CCGR5_CG14_OFFSET 28 ++#define MXC_CCM_CCGR5_CG14_MASK (0x3 << 28) ++#define MXC_CCM_CCGR5_CG13_OFFSET 26 ++#define MXC_CCM_CCGR5_CG13_MASK (0x3 << 26) ++#define MXC_CCM_CCGR5_CG12_OFFSET 24 ++#define MXC_CCM_CCGR5_CG12_MASK (0x3 << 24) ++#define MXC_CCM_CCGR5_CG11_OFFSET 22 ++#define MXC_CCM_CCGR5_CG11_MASK (0x3 << 22) ++#define MXC_CCM_CCGR5_CG10_OFFSET 20 ++#define MXC_CCM_CCGR5_CG10_MASK (0x3 << 20) ++#define MXC_CCM_CCGR5_CG9_OFFSET 18 ++#define MXC_CCM_CCGR5_CG9_MASK (0x3 << 18) ++#define MXC_CCM_CCGR5_CG8_OFFSET 16 ++#define MXC_CCM_CCGR5_CG8_MASK (0x3 << 16) ++#define MXC_CCM_CCGR5_CG7_OFFSET 14 ++#define MXC_CCM_CCGR5_CG7_MASK (0x3 << 14) ++#define MXC_CCM_CCGR5_CG6_OFFSET 12 ++#define MXC_CCM_CCGR5_CG5_OFFSET 10 ++#define MXC_CCM_CCGR5_CG4_OFFSET 8 ++#define MXC_CCM_CCGR5_CG3_OFFSET 6 ++#define MXC_CCM_CCGR5_CG2_OFFSET 4 ++#define MXC_CCM_CCGR5_CG2_MASK (0x3 << 4) ++#define MXC_CCM_CCGR5_CG1_OFFSET 2 ++#define MXC_CCM_CCGR5_CG0_OFFSET 0 ++ ++#define MXC_CCM_CCGR6_CG4_OFFSET 8 ++#define MXC_CCM_CCGR6_CG4_MASK (0x3 << 8) ++#define MXC_CCM_CCGR6_CG3_OFFSET 6 ++#define MXC_CCM_CCGR6_CG2_OFFSET 4 ++#define MXC_CCM_CCGR6_CG1_OFFSET 2 ++#define MXC_CCM_CCGR6_CG0_OFFSET 0 ++ ++#define MXC_CORTEXA8_BASE ARM_BASE_ADDR ++#define MXC_GPC_BASE GPC_BASE_ADDR ++#define MXC_DPTC_LP_BASE (GPC_BASE_ADDR + 0x80) ++#define MXC_DPTC_GP_BASE (GPC_BASE_ADDR + 0x100) ++#define MXC_DVFS_CORE_BASE (GPC_BASE_ADDR + 0x180) ++#define MXC_DPTC_PER_BASE (GPC_BASE_ADDR + 0x1C0) ++#define MXC_PGC_IPU_BASE (GPC_BASE_ADDR + 0x220) ++#define MXC_PGC_VPU_BASE (GPC_BASE_ADDR + 0x240) ++#define MXC_PGC_GPU_BASE (GPC_BASE_ADDR + 0x260) ++#define MXC_SRPG_NEON_BASE (GPC_BASE_ADDR + 0x280) ++#define MXC_SRPG_ARM_BASE (GPC_BASE_ADDR + 0x2A0) ++#define MXC_SRPG_EMPGC0_BASE (GPC_BASE_ADDR + 0x2C0) ++#define MXC_SRPG_EMPGC1_BASE (GPC_BASE_ADDR + 0x2D0) ++#define MXC_SRPG_MEGAMIX_BASE (GPC_BASE_ADDR + 0x2E0) ++#define MXC_SRPG_EMI_BASE (GPC_BASE_ADDR + 0x300) ++ ++/* CORTEXA8 platform */ ++#define MXC_CORTEXA8_PLAT_PVID (MXC_CORTEXA8_BASE + 0x0) ++#define MXC_CORTEXA8_PLAT_GPC (MXC_CORTEXA8_BASE + 0x4) ++#define MXC_CORTEXA8_PLAT_PIC (MXC_CORTEXA8_BASE + 0x8) ++#define MXC_CORTEXA8_PLAT_LPC (MXC_CORTEXA8_BASE + 0xC) ++#define MXC_CORTEXA8_PLAT_NEON_LPC (MXC_CORTEXA8_BASE + 0x10) ++#define MXC_CORTEXA8_PLAT_ICGC (MXC_CORTEXA8_BASE + 0x14) ++#define MXC_CORTEXA8_PLAT_AMC (MXC_CORTEXA8_BASE + 0x18) ++#define MXC_CORTEXA8_PLAT_NMC (MXC_CORTEXA8_BASE + 0x20) ++#define MXC_CORTEXA8_PLAT_NMS (MXC_CORTEXA8_BASE + 0x24) ++ ++/* DVFS CORE */ ++#define MXC_DVFSTHRS (MXC_DVFS_CORE_BASE + 0x00) ++#define MXC_DVFSCOUN (MXC_DVFS_CORE_BASE + 0x04) ++#define MXC_DVFSSIG1 (MXC_DVFS_CORE_BASE + 0x08) ++#define MXC_DVFSSIG0 (MXC_DVFS_CORE_BASE + 0x0C) ++#define MXC_DVFSGPC0 (MXC_DVFS_CORE_BASE + 0x10) ++#define MXC_DVFSGPC1 (MXC_DVFS_CORE_BASE + 0x14) ++#define MXC_DVFSGPBT (MXC_DVFS_CORE_BASE + 0x18) ++#define MXC_DVFSEMAC (MXC_DVFS_CORE_BASE + 0x1C) ++#define MXC_DVFSCNTR (MXC_DVFS_CORE_BASE + 0x20) ++#define MXC_DVFSLTR0_0 (MXC_DVFS_CORE_BASE + 0x24) ++#define MXC_DVFSLTR0_1 (MXC_DVFS_CORE_BASE + 0x28) ++#define MXC_DVFSLTR1_0 (MXC_DVFS_CORE_BASE + 0x2C) ++#define MXC_DVFSLTR1_1 (MXC_DVFS_CORE_BASE + 0x30) ++#define MXC_DVFSPT0 (MXC_DVFS_CORE_BASE + 0x34) ++#define MXC_DVFSPT1 (MXC_DVFS_CORE_BASE + 0x38) ++#define MXC_DVFSPT2 (MXC_DVFS_CORE_BASE + 0x3C) ++#define MXC_DVFSPT3 (MXC_DVFS_CORE_BASE + 0x40) ++ ++/* GPC */ ++#define MXC_GPC_CNTR (MXC_GPC_BASE + 0x0) ++#define MXC_GPC_PGR (MXC_GPC_BASE + 0x4) ++#define MXC_GPC_VCR (MXC_GPC_BASE + 0x8) ++#define MXC_GPC_ALL_PU (MXC_GPC_BASE + 0xC) ++#define MXC_GPC_NEON (MXC_GPC_BASE + 0x10) ++#define MXC_GPC_PGR_ARMPG_OFFSET 8 ++#define MXC_GPC_PGR_ARMPG_MASK (3 << 8) ++ ++/* PGC */ ++#define MXC_PGC_IPU_PGCR (MXC_PGC_IPU_BASE + 0x0) ++#define MXC_PGC_IPU_PGSR (MXC_PGC_IPU_BASE + 0xC) ++#define MXC_PGC_VPU_PGCR (MXC_PGC_VPU_BASE + 0x0) ++#define MXC_PGC_VPU_PGSR (MXC_PGC_VPU_BASE + 0xC) ++#define MXC_PGC_GPU_PGCR (MXC_PGC_GPU_BASE + 0x0) ++#define MXC_PGC_GPU_PGSR (MXC_PGC_GPU_BASE + 0xC) ++ ++#define MXC_PGCR_PCR 1 ++#define MXC_SRPGCR_PCR 1 ++#define MXC_EMPGCR_PCR 1 ++#define MXC_PGSR_PSR 1 ++ ++ ++#define MXC_CORTEXA8_PLAT_LPC_DSM (1 << 0) ++#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM (1 << 1) ++ ++/* SRPG */ ++#define MXC_SRPG_NEON_SRPGCR (MXC_SRPG_NEON_BASE + 0x0) ++#define MXC_SRPG_NEON_PUPSCR (MXC_SRPG_NEON_BASE + 0x4) ++#define MXC_SRPG_NEON_PDNSCR (MXC_SRPG_NEON_BASE + 0x8) ++ ++#define MXC_SRPG_ARM_SRPGCR (MXC_SRPG_ARM_BASE + 0x0) ++#define MXC_SRPG_ARM_PUPSCR (MXC_SRPG_ARM_BASE + 0x4) ++#define MXC_SRPG_ARM_PDNSCR (MXC_SRPG_ARM_BASE + 0x8) ++ ++#define MXC_SRPG_EMPGC0_SRPGCR (MXC_SRPG_EMPGC0_BASE + 0x0) ++#define MXC_SRPG_EMPGC0_PUPSCR (MXC_SRPG_EMPGC0_BASE + 0x4) ++#define MXC_SRPG_EMPGC0_PDNSCR (MXC_SRPG_EMPGC0_BASE + 0x8) ++ ++#define MXC_SRPG_EMPGC1_SRPGCR (MXC_SRPG_EMPGC1_BASE + 0x0) ++#define MXC_SRPG_EMPGC1_PUPSCR (MXC_SRPG_EMPGC1_BASE + 0x4) ++#define MXC_SRPG_EMPGC1_PDNSCR (MXC_SRPG_EMPGC1_BASE + 0x8) ++ ++#define MXC_SRPG_MEGAMIX_SRPGCR (MXC_SRPG_MEGAMIX_BASE + 0x0) ++#define MXC_SRPG_MEGAMIX_PUPSCR (MXC_SRPG_MEGAMIX_BASE + 0x4) ++#define MXC_SRPG_MEGAMIX_PDNSCR (MXC_SRPG_MEGAMIX_BASE + 0x8) ++ ++#define MXC_SRPGC_EMI_SRPGCR (MXC_SRPGC_EMI_BASE + 0x0) ++#define MXC_SRPGC_EMI_PUPSCR (MXC_SRPGC_EMI_BASE + 0x4) ++#define MXC_SRPGC_EMI_PDNSCR (MXC_SRPGC_EMI_BASE + 0x8) ++ ++#endif /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */ +diff --git a/cpu/arm_cortexa8/mx51/generic.c b/cpu/arm_cortexa8/mx51/generic.c +new file mode 100644 +index 0000000..8982a80 +--- /dev/null ++++ b/cpu/arm_cortexa8/mx51/generic.c +@@ -0,0 +1,182 @@ ++/* ++ * (C) Copyright 2007 ++ * Sascha Hauer, Pengutronix ++ * ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include "crm_regs.h" ++ ++enum pll_clocks { ++PLL1_CLK = MXC_DPLL1_BASE, ++PLL2_CLK = MXC_DPLL2_BASE, ++PLL3_CLK = MXC_DPLL3_BASE, ++}; ++ ++enum pll_sw_clocks { ++PLL1_SW_CLK, ++PLL2_SW_CLK, ++PLL3_SW_CLK, ++}; ++ ++static u32 __decode_pll(enum pll_clocks pll, u32 infreq) ++{ ++ u32 mfi, mfn, mfd, pd; ++ ++ mfn = __REG(pll + MXC_PLL_DP_MFN); ++ mfd = __REG(pll + MXC_PLL_DP_MFD) + 1; ++ mfi = __REG(pll + MXC_PLL_DP_OP); ++ pd = (mfi & 0xF) + 1; ++ mfi = (mfi >> 4) & 0xF; ++ mfi = (mfi >= 5) ? mfi : 5; ++ return ((4 * (infreq / 1000) * (mfi * mfd + mfn)) / (mfd * pd)) * 1000; ++} ++ ++static u32 __get_mcu_main_clk(void) ++{ ++ u32 reg, freq; ++ reg = (__REG(MXC_CCM_CACRR) & MXC_CCM_CACRR_ARM_PODF_MASK) >> ++ MXC_CCM_CACRR_ARM_PODF_OFFSET; ++ freq = __decode_pll(PLL1_CLK, CONFIG_MX51_HCLK_FREQ); ++ return freq / (reg + 1); ++} ++ ++static u32 __get_periph_clk(void) ++{ ++ u32 reg; ++ reg = __REG(MXC_CCM_CBCDR); ++ if (reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL) { ++ reg = __REG(MXC_CCM_CBCMR); ++ switch ((reg & MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK) >> ++ MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET) { ++ case 0: ++ return __decode_pll(PLL1_CLK, CONFIG_MX51_HCLK_FREQ); ++ case 1: ++ return __decode_pll(PLL3_CLK, CONFIG_MX51_HCLK_FREQ); ++ default: ++ return 0; ++ } ++ } ++ return __decode_pll(PLL2_CLK, CONFIG_MX51_HCLK_FREQ); ++} ++ ++static u32 __get_ipg_clk(void) ++{ ++ u32 ahb_podf, ipg_podf; ++ ++ ahb_podf = __REG(MXC_CCM_CBCDR); ++ ipg_podf = (ahb_podf & MXC_CCM_CBCDR_IPG_PODF_MASK) >> ++ MXC_CCM_CBCDR_IPG_PODF_OFFSET; ++ ahb_podf = (ahb_podf & MXC_CCM_CBCDR_AHB_PODF_MASK) >> ++ MXC_CCM_CBCDR_AHB_PODF_OFFSET; ++ return __get_periph_clk() / ((ahb_podf + 1) * (ipg_podf + 1)); ++} ++ ++static u32 __get_ipg_per_clk(void) ++{ ++ u32 pred1, pred2, podf; ++ if (__REG(MXC_CCM_CBCMR) & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL) ++ return __get_ipg_clk(); ++ /* Fixme: not handle what about lpm*/ ++ podf = __REG(MXC_CCM_CBCDR); ++ pred1 = (podf & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >> ++ MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET; ++ pred2 = (podf & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >> ++ MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET; ++ podf = (podf & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >> ++ MXC_CCM_CBCDR_PERCLK_PODF_OFFSET; ++ ++ return __get_periph_clk() / ((pred1 + 1) * (pred2 + 1) * (podf + 1)); ++} ++ ++static u32 __get_uart_clk(void) ++{ ++ unsigned int freq, reg, pred, podf; ++ reg = __REG(MXC_CCM_CSCMR1); ++ switch ((reg & MXC_CCM_CSCMR1_UART_CLK_SEL_MASK) >> ++ MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET) { ++ case 0x0: ++ freq = __decode_pll(PLL1_CLK, CONFIG_MX51_HCLK_FREQ); ++ break; ++ case 0x1: ++ freq = __decode_pll(PLL2_CLK, CONFIG_MX51_HCLK_FREQ); ++ break; ++ case 0x2: ++ freq = __decode_pll(PLL3_CLK, CONFIG_MX51_HCLK_FREQ); ++ break; ++ default: ++ return 66500000; ++ } ++ ++ reg = __REG(MXC_CCM_CSCDR1); ++ ++ pred = (reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >> ++ MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET; ++ ++ podf = (reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >> ++ MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET; ++ freq /= (pred + 1) * (podf + 1); ++ return freq; ++} ++ ++unsigned int mxc_get_clock(enum mxc_clock clk) ++{ ++ switch (clk) { ++ case MXC_ARM_CLK: ++ return __get_mcu_main_clk(); ++ case MXC_AHB_CLK: ++ break; ++ case MXC_IPG_CLK: ++ return __get_ipg_clk(); ++ case MXC_IPG_PERCLK: ++ return __get_ipg_per_clk(); ++ case MXC_UART_CLK: ++ return __get_uart_clk(); ++ } ++ return -1; ++} ++ ++void mxc_dump_clocks(void) ++{ ++ u32 freq; ++ freq = __decode_pll(PLL1_CLK, CONFIG_MX51_HCLK_FREQ); ++ printf("mx51 pll1: %dMHz\n", freq / 1000000); ++ freq = __decode_pll(PLL2_CLK, CONFIG_MX51_HCLK_FREQ); ++ printf("mx51 pll2: %dMHz\n", freq / 1000000); ++ freq = __decode_pll(PLL3_CLK, CONFIG_MX51_HCLK_FREQ); ++ printf("mx51 pll3: %dMHz\n", freq / 1000000); ++ printf("ipg clock : %dHz\n", __get_ipg_clk()); ++ printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); ++} ++ ++#if defined(CONFIG_DISPLAY_CPUINFO) ++int print_cpuinfo(void) ++{ ++ printf("CPU: Freescale i.MX51 family %d.%dV at %d MHz\n", ++ (get_board_rev() & 0xFF) >> 4, ++ (get_board_rev() & 0xF), ++ __get_mcu_main_clk() / 1000000); ++ mxc_dump_clocks(); ++ return 0; ++} ++#endif +diff --git a/cpu/arm_cortexa8/mx51/interrupts.c b/cpu/arm_cortexa8/mx51/interrupts.c +new file mode 100644 +index 0000000..1277d4e +--- /dev/null ++++ b/cpu/arm_cortexa8/mx51/interrupts.c +@@ -0,0 +1,113 @@ ++/* ++ * (C) Copyright 2007 ++ * Sascha Hauer, Pengutronix ++ * ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++ ++/* General purpose timers registers */ ++#define GPTCR __REG(GPT1_BASE_ADDR) /* Control register */ ++#define GPTPR __REG(GPT1_BASE_ADDR + 0x4) /* Prescaler register */ ++#define GPTSR __REG(GPT1_BASE_ADDR + 0x8) /* Status register */ ++#define GPTCNT __REG(GPT1_BASE_ADDR + 0x24) /* Counter register */ ++ ++/* General purpose timers bitfields */ ++#define GPTCR_SWR (1<<15) /* Software reset */ ++#define GPTCR_FRR (1<<9) /* Freerun / restart */ ++#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ ++#define GPTCR_TEN (1) /* Timer enable */ ++ ++/* nothing really to do with interrupts, just starts up a counter. */ ++int interrupt_init(void) ++{ ++ int i; ++ /* setup GP Timer 1 */ ++ GPTCR = GPTCR_SWR; ++ for (i = 0; i < 100; i++) ++ GPTCR = 0; /* We have no udelay by now */ ++ GPTPR = 0; /* 32Khz */ ++ /* Freerun Mode, PERCLK1 input */ ++ GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; ++ return 0; ++} ++ ++void reset_timer(void) ++{ ++ reset_timer_masked(); ++} ++ ++void reset_timer_masked(void) ++{ ++ GPTCR = 0; ++ /* Freerun Mode, PERCLK1 input */ ++ GPTCR = GPTCR_CLKSOURCE_32 | GPTCR_TEN; ++} ++ ++ulong get_timer_masked(void) ++{ ++ ulong val = GPTCNT; ++ return val; ++} ++ ++ulong get_timer(ulong base) ++{ ++ return get_timer_masked() - base; ++} ++ ++void set_timer(ulong t) ++{ ++} ++ ++/* delay x useconds AND perserve advance timstamp value */ ++void udelay(unsigned long usec) ++{ ++ ulong tmo, tmp; ++ ++ /* if "big" number, spread normalization to seconds */ ++ if (usec >= 1000) { ++ /* start to normalize for usec to ticks per sec */ ++ tmo = usec / 1000; ++ /* find number of "ticks" to wait to achieve target */ ++ tmo *= CONFIG_SYS_HZ; ++ tmo /= 1000; /* finish normalize. */ ++ } else {/* else small number, don't kill it prior to HZ multiply */ ++ tmo = usec * CONFIG_SYS_HZ; ++ tmo /= (1000 * 1000); ++ } ++ ++ tmp = get_timer(0); /* get current timestamp */ ++ /* if setting this forward will roll time stamp */ ++ if ((tmo + tmp + 1) < tmp) ++ /* reset "advancing" timestamp to 0, set lastinc value */ ++ reset_timer_masked(); ++ else /* else, set advancing stamp wake up time */ ++ tmo += tmp; ++ while (get_timer_masked() < tmo) /* loop till event */ ++ /*NOP*/; ++} ++ ++void reset_cpu(ulong addr) ++{ ++ __REG16(WDOG1_BASE_ADDR) = 4; ++} +diff --git a/cpu/arm_cortexa8/mx51/iomux.c b/cpu/arm_cortexa8/mx51/iomux.c +new file mode 100644 +index 0000000..2947085 +--- /dev/null ++++ b/cpu/arm_cortexa8/mx51/iomux.c +@@ -0,0 +1,199 @@ ++/* ++ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @defgroup GPIO_MX51 Board GPIO and Muxing Setup ++ * @ingroup MSL_MX51 ++ */ ++/*! ++ * @file mach-mx51/iomux.c ++ * ++ * @brief I/O Muxing control functions ++ * ++ * @ingroup GPIO_MX51 ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++/*! ++ * IOMUX register (base) addresses ++ */ ++enum iomux_reg_addr { ++ IOMUXGPR0 = IOMUXC_BASE_ADDR, ++ IOMUXGPR1 = IOMUXC_BASE_ADDR + 0x004, ++ IOMUXSW_MUX_CTL = IOMUXC_BASE_ADDR, ++ IOMUXSW_MUX_END = IOMUXC_BASE_ADDR + MUX_I_END, ++ IOMUXSW_PAD_CTL = IOMUXC_BASE_ADDR + PAD_I_START, ++ IOMUXSW_INPUT_CTL = IOMUXC_BASE_ADDR, ++}; ++ ++#define MUX_PIN_NUM_MAX (((MUX_I_END - MUX_I_START) >> 2) + 1) ++ ++static inline u32 _get_mux_reg(iomux_pin_name_t pin) ++{ ++ u32 mux_reg = PIN_TO_IOMUX_MUX(pin); ++ ++ if (is_soc_rev(CHIP_REV_2_0) < 0) { ++ if ((pin == MX51_PIN_NANDF_RB5) || ++ (pin == MX51_PIN_NANDF_RB6) || ++ (pin == MX51_PIN_NANDF_RB7)) ++ ; /* Do nothing */ ++ else if (mux_reg >= 0x2FC) ++ mux_reg += 8; ++ else if (mux_reg >= 0x130) ++ mux_reg += 0xC; ++ } ++ mux_reg += IOMUXSW_MUX_CTL; ++ return mux_reg; ++} ++ ++static inline u32 _get_pad_reg(iomux_pin_name_t pin) ++{ ++ u32 pad_reg = PIN_TO_IOMUX_PAD(pin); ++ ++ if (is_soc_rev(CHIP_REV_2_0) < 0) { ++ if ((pin == MX51_PIN_NANDF_RB5) || ++ (pin == MX51_PIN_NANDF_RB6) || ++ (pin == MX51_PIN_NANDF_RB7)) ++ ; /* Do nothing */ ++ else if (pad_reg == 0x4D0 - PAD_I_START) ++ pad_reg += 0x4C; ++ else if (pad_reg == 0x860 - PAD_I_START) ++ pad_reg += 0x9C; ++ else if (pad_reg >= 0x804 - PAD_I_START) ++ pad_reg += 0xB0; ++ else if (pad_reg >= 0x7FC - PAD_I_START) ++ pad_reg += 0xB4; ++ else if (pad_reg >= 0x4E4 - PAD_I_START) ++ pad_reg += 0xCC; ++ else ++ pad_reg += 8; ++ } ++ pad_reg += IOMUXSW_PAD_CTL; ++ return pad_reg; ++} ++ ++static inline u32 _get_mux_end() ++{ ++ if (is_soc_rev(CHIP_REV_2_0) < 0) ++ return IOMUXC_BASE_ADDR + (0x3F8 - 4); ++ else ++ return IOMUXC_BASE_ADDR + (0x3F0 - 4); ++} ++ ++/*! ++ * This function is used to configure a pin through the IOMUX module. ++ * FIXED ME: for backward compatible. Will be static function! ++ * @param pin a pin number as defined in \b #iomux_pin_name_t ++ * @param cfg an output function as defined in \b #iomux_pin_cfg_t ++ * ++ * @return 0 if successful; Non-zero otherwise ++ */ ++static int iomux_config_mux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) ++{ ++ u32 mux_reg = _get_mux_reg(pin); ++ ++ if ((mux_reg > _get_mux_end()) || (mux_reg < IOMUXSW_MUX_CTL)) ++ return -1; ++ if (cfg == IOMUX_CONFIG_GPIO) ++ writel(PIN_TO_ALT_GPIO(pin), mux_reg); ++ else ++ writel(cfg, mux_reg); ++ ++ return 0; ++} ++ ++/*! ++ * Request ownership for an IO pin. This function has to be the first one ++ * being called before that pin is used. The caller has to check the ++ * return value to make sure it returns 0. ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param cfg an input function as defined in \b #iomux_pin_cfg_t ++ * ++ * @return 0 if successful; Non-zero otherwise ++ */ ++int mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) ++{ ++ int ret = iomux_config_mux(pin, cfg); ++ return ret; ++} ++ ++/*! ++ * Release ownership for an IO pin ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param cfg an input function as defined in \b #iomux_pin_cfg_t ++ */ ++void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) ++{ ++} ++ ++/*! ++ * This function configures the pad value for a IOMUX pin. ++ * ++ * @param pin a pin number as defined in \b #iomux_pin_name_t ++ * @param config the ORed value of elements defined in \b #iomux_pad_config_t ++ */ ++void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config) ++{ ++ u32 pad_reg = _get_pad_reg(pin); ++ writel(config, pad_reg); ++} ++ ++unsigned int mxc_iomux_get_pad(iomux_pin_name_t pin) ++{ ++ u32 pad_reg = _get_pad_reg(pin); ++ return readl(pad_reg); ++} ++/*! ++ * This function configures input path. ++ * ++ * @param input index of input select register as defined in \b ++ * #iomux_input_select_t ++ * @param config the binary value of elements defined in \b ++ * #iomux_input_config_t ++ */ ++void mxc_iomux_set_input(iomux_input_select_t input, u32 config) ++{ ++ u32 reg = IOMUXSW_INPUT_CTL + (input << 2); ++ ++ if (is_soc_rev(CHIP_REV_2_0) < 0) { ++ if (input == MUX_IN_IPU_IPP_DI_0_IND_DISPB_SD_D_SELECT_INPUT) ++ input -= 4; ++ else if (input == ++ MUX_IN_IPU_IPP_DI_1_IND_DISPB_SD_D_SELECT_INPUT) ++ input -= 3; ++ else if (input >= MUX_IN_KPP_IPP_IND_COL_6_SELECT_INPUT) ++ input -= 2; ++ else if (input >= ++ MUX_IN_HSC_MIPI_MIX_PAR_SISG_TRIG_SELECT_INPUT) ++ input -= 5; ++ else if (input >= ++ MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS1_DATA_EN_SELECT_INPUT) ++ input -= 3; ++ else if (input >= MUX_IN_ECSPI2_IPP_IND_SS_B_3_SELECT_INPUT) ++ input -= 2; ++ else if (input >= MUX_IN_CCM_PLL1_BYPASS_CLK_SELECT_INPUT) ++ input -= 1; ++ ++ reg += INPUT_CTL_START_TO1; ++ } else { ++ reg += INPUT_CTL_START; ++ } ++ ++ writel(config, reg); ++} +diff --git a/cpu/arm_cortexa8/mx51/mxc_nand_load.S b/cpu/arm_cortexa8/mx51/mxc_nand_load.S +new file mode 100644 +index 0000000..ca1f07b +--- /dev/null ++++ b/cpu/arm_cortexa8/mx51/mxc_nand_load.S +@@ -0,0 +1,167 @@ ++/* ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++.macro do_wait_op_done ++1: ldr r7, [r3, #0x2C] ++ ands r7, r7, #0x80000000 ++ beq 1b ++ mov r7, #0x0 ++ str r7, [r3, #0x2C] ++.endm // do_wait_op_done ++ ++.section ".text.load", "x" ++.globl mxc_nand_load ++/* ++ * R0: NFC BUF base address ++ * R1: NFC BUF data end address ++ * R2: RAM destination offset address ++ * R3: NFC IP control register base ++ * R4: NAND block address ++ * R5: RAM destination end address ++ * R6: NFC DATA register base ++ * R7 - r14: 8 working buffer registers ++ */ ++mxc_nand_load: ++ ldr r0, =NFC_BASE_ADDR_AXI ++ add r1, r0, #NFC_BUF_SIZE ++ ++ /* For non-nand-boot, directly quit */ ++ cmp pc, r0 ++ movlo pc, lr ++ cmp pc, r1 ++ movhi pc, lr ++ ++ mov r4, #NFC_BUF_SIZE ++ /* Get NAND page size */ ++ ldr r3, =NFC_BASE_ADDR ++ ldr r2, [r3, #0x24] ++ and r2, r2, #0x3 ++ cmp r2, #1 ++ moveq r2, #0x800 ++ movlt r2, #0x200 ++ adrls r5, NFC_PAGE_MODE ++ strls r2, [r5] ++ /* Get actually pre-loading size*/ ++ subls r1, r1, #0x800 ++ subls r4, r4, #0x800 ++ ++ /* r1 ~ r3, r12, lr(r14) must not change in relocated operation */ ++ ldr r2, U_BOOT_NAND_START ++1: ldmia r0!, {r5-r11, r13} ++ stmia r2!, {r5-r11, r13} ++ cmp r0, r1 ++ blo 1b ++ ++ ldr r0, CONST_0X0FFF ++ ldr r5, U_BOOT_NAND_START ++ and lr, lr, r0 ++ add lr, lr, r5 ++ and r12, r12, r0 ++ add r12, r12, r5 ++ add r5, r5, #0x8 ++ and r0, pc, r0 ++ add pc, r5, r0 ++ nop ++ nop ++ nop ++ nop ++ nop ++ adr r0, SAVE_REGS /* Save r12 & R14(lr) */ ++ str r12, [r0] ++ str lr, [r0, #4] ++Copy_Main: ++ ldr r0, =NFC_BASE_ADDR_AXI ++ ++ add r6, r0, #0x1E00 ++ ldr r5, =_end /* Try get right image size */ ++ add r5, r2, #0x00040000 /* Fixme to get actual image size */ ++ ++ mov r7, #0xFF000000 ++ add r7, r7, #0x00FF0000 ++ str r7, [r3, #0x4] ++ str r7, [r3, #0x8] ++ str r7, [r3, #0xC] ++ str r7, [r3, #0x10] ++ str r7, [r3, #0x14] ++ str r7, [r3, #0x18] ++ str r7, [r3, #0x1C] ++ str r7, [r3, #0x20] ++ mov r8, #0x7 ++ mov r7, #0x84 ++1: add r9, r7, r8, lsr #3 ++ str r9, [r3, #0x0] ++ subs r8, r8, #0x01 ++ bne 1b ++ ++ mov r7, #0 ++ str r7, [r3, #0x2C] ++ ++ ldr r7, NFC_PAGE_MODE ++Read_Page: ++ /* start_nfc_addr_ops1(pg_no, pg_off) */ ++ cmp r7, #0x800 ++ movgt r7, r4, lsr #12 /* Get the page number for 4K page */ ++ moveq r7, r4, lsr #11 /* Get the page number for 2K page */ ++ mov r7, r7, lsl #16 ++ str r7, [r6, #0x04] /* Set the address */ ++ ++ /* writel((FLASH_Read_Mode1_LG << 8) | FLASH_Read_Mode1, NAND_CMD_REG)*/ ++ mov r7, #0x3000 ++ str r7, [r6,#0x0] ++ ++ /* writel(0x00000000, NAND_CONFIGURATION1_REG) */ ++ mov r7, #0x0 ++ str r7, [r6, #0x34] ++ ++ /* start auto-read ++ * writel(NAND_LAUNCH_AUTO_READ, NAND_LAUNCH_REG); ++ */ ++ mov r7, #0x80 ++ str r7, [r6, #0x40] ++ ++ do_wait_op_done ++ ++Copy_Good_Blk: ++1: ldmia r0!, {r7-r14} ++ stmia r2!, {r7-r14} ++ cmp r0, r1 ++ blo 1b ++ cmp r2, r5 ++ bge Copy_Main_done ++ ldr r7, NFC_PAGE_MODE ++ add r4, r4, r7 ++ ldr r0, =NFC_BASE_ADDR_AXI ++ b Read_Page ++ ++Copy_Main_done: ++ adr r0, SAVE_REGS ++ ldr r12, [r0] ++ ldr lr, [r0, #4] ++ mov pc, lr ++ ++U_BOOT_NAND_START: .word TEXT_BASE ++CONST_0X0FFF: .word 0x0FFF ++NFC_PAGE_MODE: .word 0x1000 ++SAVE_REGS: .word 0x0 ++ .word 0x0 +diff --git a/cpu/arm_cortexa8/mx51/serial.c b/cpu/arm_cortexa8/mx51/serial.c +new file mode 100644 +index 0000000..7fe74e5 +--- /dev/null ++++ b/cpu/arm_cortexa8/mx51/serial.c +@@ -0,0 +1,226 @@ ++/* ++ * (c) 2007 Sascha Hauer ++ * ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++ ++#if defined CONFIG_MX51_UART ++ ++#include ++ ++#ifdef CONFIG_MX51_UART1 ++#define UART_PHYS UART1_BASE_ADDR ++#elif defined(CONFIG_MX51_UART2) ++#define UART_PHYS UART2_BASE_ADDR ++#elif defined(CONFIG_MX51_UART3) ++#define UART_PHYS UART3_BASE_ADDR ++#else ++#error "define CFG_MX51_UARTx to use the mx51 UART driver" ++#endif ++ ++/* Register definitions */ ++#define URXD 0x0 /* Receiver Register */ ++#define UTXD 0x40 /* Transmitter Register */ ++#define UCR1 0x80 /* Control Register 1 */ ++#define UCR2 0x84 /* Control Register 2 */ ++#define UCR3 0x88 /* Control Register 3 */ ++#define UCR4 0x8c /* Control Register 4 */ ++#define UFCR 0x90 /* FIFO Control Register */ ++#define USR1 0x94 /* Status Register 1 */ ++#define USR2 0x98 /* Status Register 2 */ ++#define UESC 0x9c /* Escape Character Register */ ++#define UTIM 0xa0 /* Escape Timer Register */ ++#define UBIR 0xa4 /* BRM Incremental Register */ ++#define UBMR 0xa8 /* BRM Modulator Register */ ++#define UBRC 0xac /* Baud Rate Count Register */ ++#define UTS 0xb4 /* UART Test Register (mx31) */ ++ ++/* UART Control Register Bit Fields.*/ ++#define URXD_CHARRDY (1<<15) ++#define URXD_ERR (1<<14) ++#define URXD_OVRRUN (1<<13) ++#define URXD_FRMERR (1<<12) ++#define URXD_BRK (1<<11) ++#define URXD_PRERR (1<<10) ++#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ ++#define UCR1_ADBR (1<<14) /* Auto detect baud rate */ ++#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ ++#define UCR1_IDEN (1<<12) /* Idle condition interrupt */ ++#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ ++#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ ++#define UCR1_IREN (1<<7) /* Infrared interface enable */ ++#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ ++#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ ++#define UCR1_SNDBRK (1<<4) /* Send break */ ++#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ ++#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ ++#define UCR1_DOZE (1<<1) /* Doze */ ++#define UCR1_UARTEN (1<<0) /* UART enabled */ ++#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ ++#define UCR2_IRTS (1<<14) /* Ignore RTS pin */ ++#define UCR2_CTSC (1<<13) /* CTS pin control */ ++#define UCR2_CTS (1<<12) /* Clear to send */ ++#define UCR2_ESCEN (1<<11) /* Escape enable */ ++#define UCR2_PREN (1<<8) /* Parity enable */ ++#define UCR2_PROE (1<<7) /* Parity odd/even */ ++#define UCR2_STPB (1<<6) /* Stop */ ++#define UCR2_WS (1<<5) /* Word size */ ++#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ ++#define UCR2_TXEN (1<<2) /* Transmitter enabled */ ++#define UCR2_RXEN (1<<1) /* Receiver enabled */ ++#define UCR2_SRST (1<<0) /* SW reset */ ++#define UCR3_DTREN (1<<13) /* DTR interrupt enable */ ++#define UCR3_PARERREN (1<<12) /* Parity enable */ ++#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */ ++#define UCR3_DSR (1<<10) /* Data set ready */ ++#define UCR3_DCD (1<<9) /* Data carrier detect */ ++#define UCR3_RI (1<<8) /* Ring indicator */ ++#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */ ++#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ ++#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ ++#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ ++#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */ ++#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */ ++#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ ++#define UCR3_BPEN (1<<0) /* Preset registers enable */ ++#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ ++#define UCR4_INVR (1<<9) /* Inverted infrared reception */ ++#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ ++#define UCR4_WKEN (1<<7) /* Wake interrupt enable */ ++#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */ ++#define UCR4_IRSC (1<<5) /* IR special case */ ++#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */ ++#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */ ++#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ ++#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ ++#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ ++#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ ++#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ ++#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ ++#define USR1_RTSS (1<<14) /* RTS pin status */ ++#define USR1_TRDY (1<<13)/* Transmitter ready interrupt/dma flag */ ++#define USR1_RTSD (1<<12) /* RTS delta */ ++#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */ ++#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */ ++#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */ ++#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */ ++#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */ ++#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */ ++#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */ ++#define USR2_ADET (1<<15) /* Auto baud rate detect complete */ ++#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */ ++#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */ ++#define USR2_IDLE (1<<12) /* Idle condition */ ++#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */ ++#define USR2_WAKE (1<<7) /* Wake */ ++#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */ ++#define USR2_TXDC (1<<3) /* Transmitter complete */ ++#define USR2_BRCD (1<<2) /* Break condition */ ++#define USR2_ORE (1<<1) /* Overrun error */ ++#define USR2_RDR (1<<0) /* Recv data ready */ ++#define UTS_FRCPERR (1<<13) /* Force parity error */ ++#define UTS_LOOP (1<<12) /* Loop tx and rx */ ++#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ ++#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ ++#define UTS_TXFULL (1<<4) /* TxFIFO full */ ++#define UTS_RXFULL (1<<3) /* RxFIFO full */ ++#define UTS_SOFTRST (1<<0) /* Software reset */ ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++void serial_setbrg(void) ++{ ++ u32 clk = mxc_get_clock(MXC_UART_CLK); ++ ++ if (!gd->baudrate) ++ gd->baudrate = CONFIG_BAUDRATE; ++ __REG(UART_PHYS + UFCR) = 0x4 << 7; /* divide input clock by 2 */ ++ __REG(UART_PHYS + UBIR) = 0xf; ++ __REG(UART_PHYS + UBMR) = clk / (2 * gd->baudrate); ++} ++ ++int serial_getc(void) ++{ ++ while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) ++ ; ++ return __REG(UART_PHYS + URXD); ++} ++ ++void serial_putc(const char c) ++{ ++ __REG(UART_PHYS + UTXD) = c; ++ ++ /* wait for transmitter to be ready */ ++ while (!(__REG(UART_PHYS + UTS) & UTS_TXEMPTY)) ++ ; ++ ++ /* If \n, also do \r */ ++ if (c == '\n') ++ serial_putc('\r'); ++} ++ ++/* ++ * Test whether a character is in the RX buffer ++ */ ++int serial_tstc(void) ++{ ++ /* If receive fifo is empty, return false */ ++ if (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) ++ return 0; ++ return 1; ++} ++ ++void serial_puts(const char *s) ++{ ++ while (*s) ++ serial_putc(*s++); ++} ++ ++/* ++ * Initialise the serial port with the given baudrate. The settings ++ * are always 8 data bits, no parity, 1 stop bit, no start bits. ++ * ++ */ ++int serial_init(void) ++{ ++ __REG(UART_PHYS + UCR1) = 0x0; ++ __REG(UART_PHYS + UCR2) = 0x0; ++ ++ while (!(__REG(UART_PHYS + UCR2) & UCR2_SRST)) ++ ; ++ ++ __REG(UART_PHYS + UCR3) = 0x0704; ++ __REG(UART_PHYS + UCR4) = 0x8000; ++ __REG(UART_PHYS + UESC) = 0x002b; ++ __REG(UART_PHYS + UTIM) = 0x0; ++ ++ __REG(UART_PHYS + UTS) = 0x0; ++ ++ serial_setbrg(); ++ ++ __REG(UART_PHYS + UCR2) = ++ UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST; ++ ++ __REG(UART_PHYS + UCR1) = UCR1_UARTEN; ++ ++ return 0; ++} ++ ++#endif /* CONFIG_MX51_UART */ +diff --git a/cpu/arm_cortexa8/start.S b/cpu/arm_cortexa8/start.S +index 07acdbd..4a6e0ea 100644 +--- a/cpu/arm_cortexa8/start.S ++++ b/cpu/arm_cortexa8/start.S +@@ -9,6 +9,7 @@ + * Copyright (c) 2003 Richard Woodruff + * Copyright (c) 2003 Kshitij + * Copyright (c) 2006-2008 Syed Mohammed Khasim ++ * Copyright (c) 2009 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. +@@ -501,7 +502,7 @@ finished_inval: + + ldmfd r13!, {r0 - r5, r7, r9 - r12, pc} + +- ++#ifdef PRM_RSTCTRL + .align 5 + .global reset_cpu + reset_cpu: +@@ -514,3 +515,4 @@ _loop_forever: + b _loop_forever + rstctl: + .word PRM_RSTCTRL ++#endif +diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile +index 2260d31..eaf61f3 100644 +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -40,6 +40,7 @@ COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o + COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o + COBJS-$(CONFIG_MX31_NAND) += mx31_nand.o + COBJS-$(CONFIG_MX35) += mxc_nand.o ++COBJS-$(CONFIG_MX51) += mxc_nand.o + endif + + COBJS := $(COBJS-y) +diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c +index 790f35f..20682bb 100644 +--- a/drivers/net/smc911x.c ++++ b/drivers/net/smc911x.c +@@ -29,6 +29,15 @@ + #include + #include + ++#ifndef CONFIG_DRIVER_SMC911X_BASE ++#ifdef CONFIG_DRIVER_SMC911X_BASE_VARIABLE ++extern u32 CONFIG_DRIVER_SMC911X_BASE_VARIABLE; ++#define CONFIG_DRIVER_SMC911X_BASE CONFIG_DRIVER_SMC911X_BASE_VARIABLE ++#else ++#error "Please define base constant or variable!" ++#endif ++#endif ++ + #if defined (CONFIG_DRIVER_SMC911X_32_BIT) + static inline u32 reg_read(u32 addr) + { +diff --git a/include/asm-arm/arch-mx51/iomux.h b/include/asm-arm/arch-mx51/iomux.h +new file mode 100644 +index 0000000..fa02984 +--- /dev/null ++++ b/include/asm-arm/arch-mx51/iomux.h +@@ -0,0 +1,240 @@ ++/* ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++#ifndef __MACH_MX51_IOMUX_H__ ++#define __MACH_MX51_IOMUX_H__ ++ ++#include ++#include ++#include ++#include ++ ++/*! ++ * @file iomux.h ++ * ++ * @brief I/O Muxing control definitions and functions ++ * ++ * @ingroup GPIO_MX51 ++ */ ++ ++typedef unsigned int iomux_pin_name_t; ++ ++/*! ++ * various IOMUX output functions ++ */ ++typedef enum iomux_config { ++ IOMUX_CONFIG_ALT0, /*!< used as alternate function 0 */ ++ IOMUX_CONFIG_ALT1, /*!< used as alternate function 1 */ ++ IOMUX_CONFIG_ALT2, /*!< used as alternate function 2 */ ++ IOMUX_CONFIG_ALT3, /*!< used as alternate function 3 */ ++ IOMUX_CONFIG_ALT4, /*!< used as alternate function 4 */ ++ IOMUX_CONFIG_ALT5, /*!< used as alternate function 5 */ ++ IOMUX_CONFIG_ALT6, /*!< used as alternate function 6 */ ++ IOMUX_CONFIG_ALT7, /*!< used as alternate function 7 */ ++ IOMUX_CONFIG_GPIO, /*!< added to help user use GPIO mode */ ++ IOMUX_CONFIG_SION = 0x1 << 4, /*!< used as LOOPBACK:MUX SION bit */ ++} iomux_pin_cfg_t; ++ ++/*! ++ * various IOMUX pad functions ++ */ ++typedef enum iomux_pad_config { ++ PAD_CTL_SRE_SLOW = 0x0 << 0, ++ PAD_CTL_SRE_FAST = 0x1 << 0, ++ PAD_CTL_DRV_LOW = 0x0 << 1, ++ PAD_CTL_DRV_MEDIUM = 0x1 << 1, ++ PAD_CTL_DRV_HIGH = 0x2 << 1, ++ PAD_CTL_DRV_MAX = 0x3 << 1, ++ PAD_CTL_ODE_OPENDRAIN_NONE = 0x0 << 3, ++ PAD_CTL_ODE_OPENDRAIN_ENABLE = 0x1 << 3, ++ PAD_CTL_100K_PD = 0x0 << 4, ++ PAD_CTL_47K_PU = 0x1 << 4, ++ PAD_CTL_100K_PU = 0x2 << 4, ++ PAD_CTL_22K_PU = 0x3 << 4, ++ PAD_CTL_PUE_KEEPER = 0x0 << 6, ++ PAD_CTL_PUE_PULL = 0x1 << 6, ++ PAD_CTL_PKE_NONE = 0x0 << 7, ++ PAD_CTL_PKE_ENABLE = 0x1 << 7, ++ PAD_CTL_HYS_NONE = 0x0 << 8, ++ PAD_CTL_HYS_ENABLE = 0x1 << 8, ++ PAD_CTL_DDR_INPUT_CMOS = 0x0 << 9, ++ PAD_CTL_DDR_INPUT_DDR = 0x1 << 9, ++ PAD_CTL_DRV_VOT_LOW = 0x0 << 13, ++ PAD_CTL_DRV_VOT_HIGH = 0x1 << 13, ++} iomux_pad_config_t; ++ ++/*! ++ * various IOMUX input select register index ++ */ ++typedef enum iomux_input_select { ++ MUX_IN_AUDMUX_P4_INPUT_DA_AMX_SELECT_I = 0, ++ MUX_IN_AUDMUX_P4_INPUT_DB_AMX_SELECT_I, ++ MUX_IN_AUDMUX_P4_INPUT_TXCLK_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P4_INPUT_TXFS_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P5_INPUT_DA_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P5_INPUT_DB_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P5_INPUT_RXCLK_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P5_INPUT_RXFS_AMX_SELECT, ++ MUX_IN_AUDMUX_P5_INPUT_TXCLK_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P5_INPUT_TXFS_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P6_INPUT_DA_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P6_INPUT_DB_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P6_INPUT_RXCLK_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P6_INPUT_RXFS_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P6_INPUT_TXCLK_AMX_SELECT_INPUT, ++ MUX_IN_AUDMUX_P6_INPUT_TXFS_AMX_SELECT_INPUT, ++ MUX_IN_CCM_IPP_DI_CLK_SELECT_INPUT, ++ /* TO2 */ ++ MUX_IN_CCM_IPP_DI1_CLK_SELECT_INPUT, ++ MUX_IN_CCM_PLL1_BYPASS_CLK_SELECT_INPUT, ++ MUX_IN_CCM_PLL2_BYPASS_CLK_SELECT_INPUT, ++ MUX_IN_CSPI_IPP_CSPI_CLK_IN_SELECT_INPUT, ++ MUX_IN_CSPI_IPP_IND_MISO_SELECT_INPUT, ++ MUX_IN_CSPI_IPP_IND_MOSI_SELECT_INPUT, ++ MUX_IN_CSPI_IPP_IND_SS_B_1_SELECT_INPUT, ++ MUX_IN_CSPI_IPP_IND_SS_B_2_SELECT_INPUT, ++ MUX_IN_CSPI_IPP_IND_SS_B_3_SELECT_INPUT, ++ MUX_IN_DPLLIP1_L1T_TOG_EN_SELECT_INPUT, ++ /* TO2 */ ++ MUX_IN_ECSPI2_IPP_IND_SS_B_1_SELECT_INPUT, ++ MUX_IN_ECSPI2_IPP_IND_SS_B_3_SELECT_INPUT, ++ MUX_IN_EMI_IPP_IND_RDY_INT_SELECT_INPUT, ++ MUX_IN_ESDHC3_IPP_DAT0_IN_SELECT_INPUT, ++ MUX_IN_ESDHC3_IPP_DAT1_IN_SELECT_INPUT, ++ MUX_IN_ESDHC3_IPP_DAT2_IN_SELECT_INPUT, ++ MUX_IN_ESDHC3_IPP_DAT3_IN_SELECT_INPUT, ++ MUX_IN_FEC_FEC_COL_SELECT_INPUT, ++ MUX_IN_FEC_FEC_CRS_SELECT_INPUT, ++ MUX_IN_FEC_FEC_MDI_SELECT_INPUT, ++ MUX_IN_FEC_FEC_RDATA_0_SELECT_INPUT, ++ MUX_IN_FEC_FEC_RDATA_1_SELECT_INPUT, ++ MUX_IN_FEC_FEC_RDATA_2_SELECT_INPUT, ++ MUX_IN_FEC_FEC_RDATA_3_SELECT_INPUT, ++ MUX_IN_FEC_FEC_RX_CLK_SELECT_INPUT, ++ MUX_IN_FEC_FEC_RX_DV_SELECT_INPUT, ++ MUX_IN_FEC_FEC_RX_ER_SELECT_INPUT, ++ MUX_IN_FEC_FEC_TX_CLK_SELECT_INPUT, ++ MUX_IN_GPIO3_IPP_IND_G_IN_1_SELECT_INPUT, ++ MUX_IN_GPIO3_IPP_IND_G_IN_2_SELECT_INPUT, ++ MUX_IN_GPIO3_IPP_IND_G_IN_3_SELECT_INPUT, ++ MUX_IN_GPIO3_IPP_IND_G_IN_4_SELECT_INPUT, ++ MUX_IN_GPIO3_IPP_IND_G_IN_5_SELECT_INPUT, ++ MUX_IN_GPIO3_IPP_IND_G_IN_6_SELECT_INPUT, ++ MUX_IN_GPIO3_IPP_IND_G_IN_7_SELECT_INPUT, ++ MUX_IN_GPIO3_IPP_IND_G_IN_8_SELECT_INPUT, ++ /* TO2 */ ++ MUX_IN_GPIO3_IPP_IND_G_IN_12_SELECT_INPUT, ++ MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS1_DATA_EN_SELECT_INPUT, ++ MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS2_DATA_EN_SELECT_INPUT, ++ /* TO2 */ ++ MUX_IN_HSC_MIPI_MIX_PAR_VSYNC_SELECT_INPUT, ++ /* TO2 */ ++ MUX_IN_HSC_MIPI_MIX_PAR_DI_WAIT_SELECT_INPUT, ++ MUX_IN_HSC_MIPI_MIX_PAR_SISG_TRIG_SELECT_INPUT, ++ MUX_IN_I2C1_IPP_SCL_IN_SELECT_INPUT, ++ MUX_IN_I2C1_IPP_SDA_IN_SELECT_INPUT, ++ MUX_IN_I2C2_IPP_SCL_IN_SELECT_INPUT, ++ MUX_IN_I2C2_IPP_SDA_IN_SELECT_INPUT, ++ ++ MUX_IN_IPU_IPP_DI_0_IND_DISPB_SD_D_SELECT_INPUT, ++ ++ MUX_IN_IPU_IPP_DI_1_IND_DISPB_SD_D_SELECT_INPUT, ++ ++ MUX_IN_KPP_IPP_IND_COL_6_SELECT_INPUT, ++ MUX_IN_KPP_IPP_IND_COL_7_SELECT_INPUT, ++ MUX_IN_KPP_IPP_IND_ROW_4_SELECT_INPUT, ++ MUX_IN_KPP_IPP_IND_ROW_5_SELECT_INPUT, ++ MUX_IN_KPP_IPP_IND_ROW_6_SELECT_INPUT, ++ MUX_IN_KPP_IPP_IND_ROW_7_SELECT_INPUT, ++ MUX_IN_UART1_IPP_UART_RTS_B_SELECT_INPUT, ++ MUX_IN_UART1_IPP_UART_RXD_MUX_SELECT_INPUT, ++ MUX_IN_UART2_IPP_UART_RTS_B_SELECT_INPUT, ++ MUX_IN_UART2_IPP_UART_RXD_MUX_SELECT_INPUT, ++ MUX_IN_UART3_IPP_UART_RTS_B_SELECT_INPUT, ++ MUX_IN_UART3_IPP_UART_RXD_MUX_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_CLK_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_DATA_0_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_DATA_1_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_DATA_2_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_DATA_3_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_DATA_4_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_DATA_5_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_DATA_6_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_DATA_7_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_DIR_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_NXT_SELECT_INPUT, ++ MUX_IN_USBOH3_IPP_IND_UH3_STP_SELECT_INPUT, ++ MUX_INPUT_NUM_MUX, ++} iomux_input_select_t; ++ ++/*! ++ * various IOMUX input functions ++ */ ++typedef enum iomux_input_config { ++ INPUT_CTL_PATH0 = 0x0, ++ INPUT_CTL_PATH1, ++ INPUT_CTL_PATH2, ++ INPUT_CTL_PATH3, ++ INPUT_CTL_PATH4, ++ INPUT_CTL_PATH5, ++ INPUT_CTL_PATH6, ++ INPUT_CTL_PATH7, ++} iomux_input_config_t; ++ ++/*! ++ * Request ownership for an IO pin. This function has to be the first one ++ * being called before that pin is used. The caller has to check the ++ * return value to make sure it returns 0. ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param config config as defined in \b #iomux_pin_ocfg_t ++ * ++ * @return 0 if successful; Non-zero otherwise ++ */ ++int mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config); ++ ++/*! ++ * Release ownership for an IO pin ++ * ++ * @param pin a name defined by \b iomux_pin_name_t ++ * @param config config as defined in \b #iomux_pin_ocfg_t ++ */ ++void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config); ++ ++/*! ++ * This function configures the pad value for a IOMUX pin. ++ * ++ * @param pin a pin number as defined in \b #iomux_pin_name_t ++ * @param config the ORed value of elements defined in ++ * \b #iomux_pad_config_t ++ */ ++void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config); ++ ++/*! ++ * This function gets the current pad value for a IOMUX pin. ++ * ++ * @param pin a pin number as defined in \b #iomux_pin_name_t ++ * @return current pad value ++ */ ++unsigned int mxc_iomux_get_pad(iomux_pin_name_t pin); ++ ++/*! ++ * This function configures input path. ++ * ++ * @param input index of input select register as defined in ++ * \b #iomux_input_select_t ++ * @param config the binary value of elements defined in ++ * \b #iomux_input_config_t ++ */ ++void mxc_iomux_set_input(iomux_input_select_t input, u32 config); ++ ++#endif /* __MACH_MX51_IOMUX_H__ */ +diff --git a/include/asm-arm/arch-mx51/mx51.h b/include/asm-arm/arch-mx51/mx51.h +new file mode 100644 +index 0000000..d9d8ef7 +--- /dev/null ++++ b/include/asm-arm/arch-mx51/mx51.h +@@ -0,0 +1,423 @@ ++/* ++ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#ifndef __ASM_ARCH_MXC_MX51_H__ ++#define __ASM_ARCH_MXC_MX51_H__ ++ ++#define __REG(x) (*((volatile u32 *)(x))) ++#define __REG16(x) (*((volatile u16 *)(x))) ++#define __REG8(x) (*((volatile u8 *)(x))) ++/* ++ * IRAM ++ */ ++#define IRAM_BASE_ADDR 0x1FFE8000 /* internal ram */ ++/* ++ * Graphics Memory of GPU ++ */ ++#define GPU_BASE_ADDR 0x20000000 ++#define GPU_CTRL_BASE_ADDR 0x30000000 ++#define IPU_CTRL_BASE_ADDR 0x40000000 ++/* ++ * Debug ++ */ ++#define DEBUG_BASE_ADDR 0x60000000 ++#define ETB_BASE_ADDR (DEBUG_BASE_ADDR + 0x00001000) ++#define ETM_BASE_ADDR (DEBUG_BASE_ADDR + 0x00002000) ++#define TPIU_BASE_ADDR (DEBUG_BASE_ADDR + 0x00003000) ++#define CTI0_BASE_ADDR (DEBUG_BASE_ADDR + 0x00004000) ++#define CTI1_BASE_ADDR (DEBUG_BASE_ADDR + 0x00005000) ++#define CTI2_BASE_ADDR (DEBUG_BASE_ADDR + 0x00006000) ++#define CTI3_BASE_ADDR (DEBUG_BASE_ADDR + 0x00007000) ++#define CORTEX_DBG_BASE_ADDR (DEBUG_BASE_ADDR + 0x00008000) ++ ++/* ++ * SPBA global module enabled #0 ++ */ ++#define SPBA0_BASE_ADDR 0x70000000 ++ ++#define MMC_SDHC1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00004000) ++#define MMC_SDHC2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00008000) ++#define UART3_BASE_ADDR (SPBA0_BASE_ADDR + 0x0000C000) ++#define CSPI1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00010000) ++#define SSI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00014000) ++#define MMC_SDHC3_BASE_ADDR (SPBA0_BASE_ADDR + 0x00020000) ++#define MMC_SDHC4_BASE_ADDR (SPBA0_BASE_ADDR + 0x00024000) ++#define SPDIF_BASE_ADDR (SPBA0_BASE_ADDR + 0x00028000) ++#define ATA_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00030000) ++#define SLIM_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00034000) ++#define HSI2C_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00038000) ++#define SPBA_CTRL_BASE_ADDR (SPBA0_BASE_ADDR + 0x0003C000) ++ ++/* ++ * AIPS 1 ++ */ ++#define AIPS1_BASE_ADDR 0x73F00000 ++ ++#define OTG_BASE_ADDR (AIPS1_BASE_ADDR + 0x00080000) ++#define GPIO1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00084000) ++#define GPIO2_BASE_ADDR (AIPS1_BASE_ADDR + 0x00088000) ++#define GPIO3_BASE_ADDR (AIPS1_BASE_ADDR + 0x0008C000) ++#define GPIO4_BASE_ADDR (AIPS1_BASE_ADDR + 0x00090000) ++#define KPP_BASE_ADDR (AIPS1_BASE_ADDR + 0x00094000) ++#define WDOG1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00098000) ++#define WDOG2_BASE_ADDR (AIPS1_BASE_ADDR + 0x0009C000) ++#define GPT1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A0000) ++#define SRTC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A4000) ++#define IOMUXC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A8000) ++#define EPIT1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000AC000) ++#define EPIT2_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B0000) ++#define PWM1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B4000) ++#define PWM2_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B8000) ++#define UART1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000BC000) ++#define UART2_BASE_ADDR (AIPS1_BASE_ADDR + 0x000C0000) ++#define SRC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D0000) ++#define CCM_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D4000) ++#define GPC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D8000) ++ ++/* ++ * AIPS 2 ++ */ ++#define AIPS2_BASE_ADDR 0x83F00000 ++ ++#define PLL1_BASE_ADDR (AIPS2_BASE_ADDR + 0x00080000) ++#define PLL2_BASE_ADDR (AIPS2_BASE_ADDR + 0x00084000) ++#define PLL3_BASE_ADDR (AIPS2_BASE_ADDR + 0x00088000) ++#define AHBMAX_BASE_ADDR (AIPS2_BASE_ADDR + 0x00094000) ++#define IIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x00098000) ++#define CSU_BASE_ADDR (AIPS2_BASE_ADDR + 0x0009C000) ++#define ARM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A0000) ++#define OWIRE_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A4000) ++#define FIRI_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A8000) ++#define CSPI2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AC000) ++#define SDMA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B0000) ++#define SCC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B4000) ++#define ROMCP_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B8000) ++#define RTIC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000BC000) ++#define CSPI3_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C0000) ++#define I2C2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C4000) ++#define I2C1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C8000) ++#define SSI1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000CC000) ++#define AUDMUX_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D0000) ++#define M4IF_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D8000) ++#define ESDCTL_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D9000) ++#define WEIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DA000) ++#define NFC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DB000) ++#define EMI_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DBF00) ++#define MIPI_HSC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DC000) ++#define ATA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E0000) ++#define SIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E4000) ++#define SSI3BASE_ADDR (AIPS2_BASE_ADDR + 0x000E8000) ++#define FEC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000EC000) ++#define TVE_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F0000) ++#define VPU_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F4000) ++#define SAHARA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F8000) ++ ++#define TZIC_BASE_ADDR 0x8FFFC000 ++ ++/* ++ * Memory regions and CS ++ */ ++#define CSD0_BASE_ADDR 0x90000000 ++#define CSD1_BASE_ADDR 0xA0000000 ++#define CS0_BASE_ADDR 0xB0000000 ++#define CS1_BASE_ADDR 0xB8000000 ++#define CS2_BASE_ADDR 0xC0000000 ++#define CS3_BASE_ADDR 0xC8000000 ++#define CS4_BASE_ADDR 0xCC000000 ++#define CS5_BASE_ADDR 0xCE000000 ++ ++/* ++ * NFC ++ */ ++#define NFC_BASE_ADDR_AXI 0xCFFF0000 /* NAND flash AXI */ ++ ++/*! ++ * defines for SPBA modules ++ */ ++#define SPBA_SDHC1 0x04 ++#define SPBA_SDHC2 0x08 ++#define SPBA_UART3 0x0C ++#define SPBA_CSPI1 0x10 ++#define SPBA_SSI2 0x14 ++#define SPBA_SDHC3 0x20 ++#define SPBA_SDHC4 0x24 ++#define SPBA_SPDIF 0x28 ++#define SPBA_ATA 0x30 ++#define SPBA_SLIM 0x34 ++#define SPBA_HSI2C 0x38 ++#define SPBA_CTRL 0x3C ++ ++/* ++ * Interrupt numbers ++ */ ++#define MXC_INT_BASE 0 ++#define MXC_INT_RESV0 0 ++#define MXC_INT_MMC_SDHC1 1 ++#define MXC_INT_MMC_SDHC2 2 ++#define MXC_INT_MMC_SDHC3 3 ++#define MXC_INT_MMC_SDHC4 4 ++#define MXC_INT_RESV5 5 ++#define MXC_INT_SDMA 6 ++#define MXC_INT_IOMUX 7 ++#define MXC_INT_NFC 8 ++#define MXC_INT_VPU 9 ++#define MXC_INT_IPU_ERR 10 ++#define MXC_INT_IPU_SYN 11 ++#define MXC_INT_GPU 12 ++#define MXC_INT_RESV13 13 ++#define MXC_INT_USB_H1 14 ++#define MXC_INT_EMI 15 ++#define MXC_INT_USB_H2 16 ++#define MXC_INT_USB_H3 17 ++#define MXC_INT_USB_OTG 18 ++#define MXC_INT_SAHARA_H0 19 ++#define MXC_INT_SAHARA_H1 20 ++#define MXC_INT_SCC_SMN 21 ++#define MXC_INT_SCC_STZ 22 ++#define MXC_INT_SCC_SCM 23 ++#define MXC_INT_SRTC_NTZ 24 ++#define MXC_INT_SRTC_TZ 25 ++#define MXC_INT_RTIC 26 ++#define MXC_INT_CSU 27 ++#define MXC_INT_SLIM_B 28 ++#define MXC_INT_SSI1 29 ++#define MXC_INT_SSI2 30 ++#define MXC_INT_UART1 31 ++#define MXC_INT_UART2 32 ++#define MXC_INT_UART3 33 ++#define MXC_INT_RESV34 34 ++#define MXC_INT_RESV35 35 ++#define MXC_INT_CSPI1 36 ++#define MXC_INT_CSPI2 37 ++#define MXC_INT_CSPI 38 ++#define MXC_INT_GPT 39 ++#define MXC_INT_EPIT1 40 ++#define MXC_INT_EPIT2 41 ++#define MXC_INT_GPIO1_INT7 42 ++#define MXC_INT_GPIO1_INT6 43 ++#define MXC_INT_GPIO1_INT5 44 ++#define MXC_INT_GPIO1_INT4 45 ++#define MXC_INT_GPIO1_INT3 46 ++#define MXC_INT_GPIO1_INT2 47 ++#define MXC_INT_GPIO1_INT1 48 ++#define MXC_INT_GPIO1_INT0 49 ++#define MXC_INT_GPIO1_LOW 50 ++#define MXC_INT_GPIO1_HIGH 51 ++#define MXC_INT_GPIO2_LOW 52 ++#define MXC_INT_GPIO2_HIGH 53 ++#define MXC_INT_GPIO3_LOW 54 ++#define MXC_INT_GPIO3_HIGH 55 ++#define MXC_INT_GPIO4_LOW 56 ++#define MXC_INT_GPIO4_HIGH 57 ++#define MXC_INT_WDOG1 58 ++#define MXC_INT_WDOG2 59 ++#define MXC_INT_KPP 60 ++#define MXC_INT_PWM1 61 ++#define MXC_INT_I2C1 62 ++#define MXC_INT_I2C2 63 ++#define MXC_INT_HS_I2C 64 ++#define MXC_INT_RESV65 65 ++#define MXC_INT_RESV66 66 ++#define MXC_INT_SIM_IPB 67 ++#define MXC_INT_SIM_DAT 68 ++#define MXC_INT_IIM 69 ++#define MXC_INT_ATA 70 ++#define MXC_INT_CCM1 71 ++#define MXC_INT_CCM2 72 ++#define MXC_INT_GPC1 73 ++#define MXC_INT_GPC2 74 ++#define MXC_INT_SRC 75 ++#define MXC_INT_NM 76 ++#define MXC_INT_PMU 77 ++#define MXC_INT_CTI_IRQ 78 ++#define MXC_INT_CTI1_TG0 79 ++#define MXC_INT_CTI1_TG1 80 ++#define MXC_INT_MCG_ERR 81 ++#define MXC_INT_MCG_TMR 82 ++#define MXC_INT_MCG_FUNC 83 ++#define MXC_INT_RESV84 84 ++#define MXC_INT_RESV85 85 ++#define MXC_INT_RESV86 86 ++#define MXC_INT_FEC 87 ++#define MXC_INT_OWIRE 88 ++#define MXC_INT_CTI1_TG2 89 ++#define MXC_INT_SJC 90 ++#define MXC_INT_SPDIF 91 ++#define MXC_INT_TVE 92 ++#define MXC_INT_FIRI 93 ++#define MXC_INT_PWM2 94 ++#define MXC_INT_SLIM_EXP 95 ++#define MXC_INT_SSI3 96 ++#define MXC_INT_RESV97 97 ++#define MXC_INT_CTI1_TG3 98 ++#define MXC_INT_SMC_RX 99 ++#define MXC_INT_VPU_IDLE 100 ++#define MXC_INT_RESV101 101 ++#define MXC_INT_GPU_IDLE 102 ++ ++#define MXC_MAX_INT_LINES 128 ++ ++#define MXC_GPIO_INT_BASE (MXC_MAX_INT_LINES) ++ ++/*! ++ * Number of GPIO port as defined in the IC Spec ++ */ ++#define GPIO_PORT_NUM 4 ++/*! ++ * Number of GPIO pins per port ++ */ ++#define GPIO_NUM_PIN 32 ++ ++#define MXC_GPIO_SPLIT_IRQ_2 ++ ++#define IIM_SREV 0x24 ++#define ROM_SI_REV 0x48 ++ ++#define NFC_BUF_SIZE 0x1000 ++ ++/* WEIM registers */ ++#define CSGCR1 0x00 ++#define CSGCR2 0x04 ++#define CSRCR1 0x08 ++#define CSRCR2 0x0C ++#define CSWCR1 0x10 ++ ++/* M4IF */ ++#define M4IF_FBPM0 0x40 ++#define M4IF_FIDBP 0x48 ++ ++/* ESDCTL */ ++#define ESDCTL_ESDCTL0 0x00 ++#define ESDCTL_ESDCFG0 0x04 ++#define ESDCTL_ESDCTL1 0x08 ++#define ESDCTL_ESDCFG1 0x0C ++#define ESDCTL_ESDMISC 0x10 ++#define ESDCTL_ESDSCR 0x14 ++#define ESDCTL_ESDCDLY1 0x20 ++#define ESDCTL_ESDCDLY2 0x24 ++#define ESDCTL_ESDCDLY3 0x28 ++#define ESDCTL_ESDCDLY4 0x2C ++#define ESDCTL_ESDCDLY5 0x30 ++#define ESDCTL_ESDCDLYGD 0x34 ++ ++/* CCM */ ++#define CLKCTL_CCR 0x00 ++#define CLKCTL_CCDR 0x04 ++#define CLKCTL_CSR 0x08 ++#define CLKCTL_CCSR 0x0C ++#define CLKCTL_CACRR 0x10 ++#define CLKCTL_CBCDR 0x14 ++#define CLKCTL_CBCMR 0x18 ++#define CLKCTL_CSCMR1 0x1C ++#define CLKCTL_CSCMR2 0x20 ++#define CLKCTL_CSCDR1 0x24 ++#define CLKCTL_CS1CDR 0x28 ++#define CLKCTL_CS2CDR 0x2C ++#define CLKCTL_CDCDR 0x30 ++#define CLKCTL_CHSCCDR 0x34 ++#define CLKCTL_CSCDR2 0x38 ++#define CLKCTL_CSCDR3 0x3C ++#define CLKCTL_CSCDR4 0x40 ++#define CLKCTL_CWDR 0x44 ++#define CLKCTL_CDHIPR 0x48 ++#define CLKCTL_CDCR 0x4C ++#define CLKCTL_CTOR 0x50 ++#define CLKCTL_CLPCR 0x54 ++#define CLKCTL_CISR 0x58 ++#define CLKCTL_CIMR 0x5C ++#define CLKCTL_CCOSR 0x60 ++#define CLKCTL_CGPR 0x64 ++#define CLKCTL_CCGR0 0x68 ++#define CLKCTL_CCGR1 0x6C ++#define CLKCTL_CCGR2 0x70 ++#define CLKCTL_CCGR3 0x74 ++#define CLKCTL_CCGR4 0x78 ++#define CLKCTL_CCGR5 0x7C ++#define CLKCTL_CMEOR 0x84 ++ ++/* DPLL */ ++#define PLL_DP_CTL 0x00 ++#define PLL_DP_CONFIG 0x04 ++#define PLL_DP_OP 0x08 ++#define PLL_DP_MFD 0x0C ++#define PLL_DP_MFN 0x10 ++#define PLL_DP_MFNMINUS 0x14 ++#define PLL_DP_MFNPLUS 0x18 ++#define PLL_DP_HFS_OP 0x1C ++#define PLL_DP_HFS_MFD 0x20 ++#define PLL_DP_HFS_MFN 0x24 ++#define PLL_DP_TOGC 0x28 ++#define PLL_DP_DESTAT 0x2C ++ ++/* Assuming 24MHz input clock with doubler ON */ ++/* MFI PDF */ ++#define DP_OP_850 ((8 << 4) + ((1 - 1) << 0)) ++#define DP_MFD_850 (48 - 1) ++#define DP_MFN_850 41 ++ ++#define DP_OP_800 ((8 << 4) + ((1 - 1) << 0)) ++#define DP_MFD_800 (3 - 1) ++#define DP_MFN_800 1 ++ ++#define DP_OP_700 ((7 << 4) + ((1 - 1) << 0)) ++#define DP_MFD_700 (24 - 1) ++#define DP_MFN_700 7 ++ ++#define DP_OP_665 ((6 << 4) + ((1 - 1) << 0)) ++#define DP_MFD_665 (96 - 1) ++#define DP_MFN_665 89 ++ ++#define DP_OP_532 ((5 << 4) + ((1 - 1) << 0)) ++#define DP_MFD_532 (24 - 1) ++#define DP_MFN_532 13 ++ ++#define DP_OP_400 ((8 << 4) + ((2 - 1) << 0)) ++#define DP_MFD_400 (3 - 1) ++#define DP_MFN_400 1 ++ ++#define DP_OP_216 ((6 << 4) + ((3 - 1) << 0)) ++#define DP_MFD_216 (4 - 1) ++#define DP_MFN_216 3 ++ ++#define CHIP_REV_1_0 0x10 ++#define CHIP_REV_1_1 0x11 ++#define CHIP_REV_2_0 0x20 ++ ++#define BOARD_REV_1_0 0x0 ++#define BOARD_REV_2_0 0x1 ++ ++#ifndef __ASSEMBLER__ ++ ++enum mxc_clock { ++MXC_ARM_CLK = 0, ++MXC_AHB_CLK, ++MXC_IPG_CLK, ++MXC_IPG_PERCLK, ++MXC_UART_CLK, ++}; ++ ++/*! ++ * NFMS bit in RCSR register for pagesize of nandflash ++ */ ++#define NFMS (*((volatile u32 *)(CCM_BASE_ADDR+0x18))) ++#define NFMS_BIT 8 ++#define NFMS_NF_DWIDTH 14 ++#define NFMS_NF_PG_SZ 8 ++ ++extern unsigned int mxc_get_clock(enum mxc_clock clk); ++extern unsigned int get_board_rev(void); ++extern int is_soc_rev(int rev); ++ ++#endif /* __ASSEMBLER__*/ ++ ++#endif /* __ASM_ARCH_MXC_MX51_H__ */ +diff --git a/include/asm-arm/arch-mx51/mx51_pins.h b/include/asm-arm/arch-mx51/mx51_pins.h +new file mode 100644 +index 0000000..63fdd8c +--- /dev/null ++++ b/include/asm-arm/arch-mx51/mx51_pins.h +@@ -0,0 +1,370 @@ ++/* ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++#ifndef __ASM_ARCH_MXC_MX51_PINS_H__ ++#define __ASM_ARCH_MXC_MX51_PINS_H__ ++ ++/*! ++ * @file arch-mxc/mx51_pins.h ++ * ++ * @brief MX51 I/O Pin List ++ * ++ * @ingroup GPIO_MX51 ++ */ ++ ++#ifndef __ASSEMBLY__ ++ ++/*! ++ * @name IOMUX/PAD Bit field definitions ++ */ ++ ++/*! @{ */ ++ ++/*! ++ * In order to identify pins more effectively, each mux-controlled pin's ++ * enumerated value is constructed in the following way: ++ * ++ * ------------------------------------------------------------------- ++ * 31-29 | 28 - 24 | 23 - 21 | 20 - 10| 9 - 0 ++ * ------------------------------------------------------------------- ++ * IO_P | IO_I | GPIO_I | PAD_I | MUX_I ++ * ------------------------------------------------------------------- ++ * ++ * Bit 0 to 9 contains MUX_I used to identify the register ++ * offset (0-based. base is IOMUX_module_base) defined in the Section ++ * "sw_pad_ctl & sw_mux_ctl details" of the IC Spec. The ++ * similar field definitions are used for the pad control register. ++ * For example, the MX51_PIN_ETM_D0 is defined in the enumeration: ++ * ( (0x28 - MUX_I_START) << MUX_I)|( (0x250 - PAD_I_START) << PAD_I) ++ * It means the mux control register is at register offset 0x28. The pad control ++ * register offset is: 0x250 and also occupy the least significant bits ++ * within the register. ++ */ ++ ++/*! ++ * Starting bit position within each entry of \b iomux_pins to represent the ++ * MUX control register offset ++ */ ++#define MUX_I 0 ++/*! ++ * Starting bit position within each entry of \b iomux_pins to represent the ++ * PAD control register offset ++ */ ++#define PAD_I 10 ++/*! ++ * Starting bit position within each entry of \b iomux_pins to represent which ++ * mux mode is for GPIO (0-based) ++ */ ++#define GPIO_I 21 ++ ++#define MUX_IO_P 29 ++#define MUX_IO_I 24 ++#define IOMUX_TO_GPIO(pin) ((((unsigned int)pin >> MUX_IO_P) * \ ++ GPIO_NUM_PIN) + ((pin >> MUX_IO_I) &\ ++ ((1 << (MUX_IO_P - MUX_IO_I)) - 1))) ++#define IOMUX_TO_IRQ(pin) (MXC_GPIO_INT_BASE + IOMUX_TO_GPIO(pin)) ++#define GPIO_TO_PORT(n) (n / GPIO_NUM_PIN) ++#define GPIO_TO_INDEX(n) (n % GPIO_NUM_PIN) ++ ++#define NON_GPIO_PORT 0x7 ++#define PIN_TO_MUX_MASK ((1 << (PAD_I - MUX_I)) - 1) ++#define PIN_TO_PAD_MASK ((1 << (GPIO_I - PAD_I)) - 1) ++#define PIN_TO_ALT_GPIO_MASK ((1 << (MUX_IO_I - GPIO_I)) - 1) ++ ++#define NON_MUX_I PIN_TO_MUX_MASK ++#define MUX_I_START 0x001C ++#define PAD_I_START 0x3F0 ++#define INPUT_CTL_START 0x8C4 ++#define INPUT_CTL_START_TO1 0x928 ++#define MUX_I_END (PAD_I_START - 4) ++ ++#define _MXC_BUILD_PIN(gp, gi, ga, mi, pi) \ ++ (((gp) << MUX_IO_P) | ((gi) << MUX_IO_I) | \ ++ ((mi) << MUX_I) | \ ++ ((pi - PAD_I_START) << PAD_I) | \ ++ ((ga) << GPIO_I)) ++ ++#define _MXC_BUILD_GPIO_PIN(gp, gi, ga, mi, pi) \ ++ _MXC_BUILD_PIN(gp, gi, ga, mi, pi) ++ ++#define _MXC_BUILD_NON_GPIO_PIN(mi, pi) \ ++ _MXC_BUILD_PIN(NON_GPIO_PORT, 0, 0, mi, pi) ++ ++#define PIN_TO_IOMUX_MUX(pin) ((pin >> MUX_I) & PIN_TO_MUX_MASK) ++#define PIN_TO_IOMUX_PAD(pin) ((pin >> PAD_I) & PIN_TO_PAD_MASK) ++#define PIN_TO_ALT_GPIO(pin) ((pin >> GPIO_I) & PIN_TO_ALT_GPIO_MASK) ++#define PIN_TO_IOMUX_INDEX(pin) (PIN_TO_IOMUX_MUX(pin) >> 2) ++ ++/*! @} End IOMUX/PAD Bit field definitions */ ++ ++/*! ++ * This enumeration is constructed based on the Section ++ * "sw_pad_ctl & sw_mux_ctl details" of the MX51 IC Spec. Each enumerated ++ * value is constructed based on the rules described above. ++ */ ++enum iomux_pins { ++ MX51_PIN_EIM_DA0 = _MXC_BUILD_NON_GPIO_PIN(0x1C, 0x7A8), ++ MX51_PIN_EIM_DA1 = _MXC_BUILD_NON_GPIO_PIN(0x20, 0x7A8), ++ MX51_PIN_EIM_DA2 = _MXC_BUILD_NON_GPIO_PIN(0x24, 0x7A8), ++ MX51_PIN_EIM_DA3 = _MXC_BUILD_NON_GPIO_PIN(0x28, 0x7A8), ++ MX51_PIN_EIM_DA4 = _MXC_BUILD_NON_GPIO_PIN(0x2C, 0x7AC), ++ MX51_PIN_EIM_DA5 = _MXC_BUILD_NON_GPIO_PIN(0x30, 0x7AC), ++ MX51_PIN_EIM_DA6 = _MXC_BUILD_NON_GPIO_PIN(0x34, 0x7AC), ++ MX51_PIN_EIM_DA7 = _MXC_BUILD_NON_GPIO_PIN(0x38, 0x7AC), ++ MX51_PIN_EIM_DA8 = _MXC_BUILD_NON_GPIO_PIN(0x3C, 0x7B0), ++ MX51_PIN_EIM_DA9 = _MXC_BUILD_NON_GPIO_PIN(0x40, 0x7B0), ++ MX51_PIN_EIM_DA10 = _MXC_BUILD_NON_GPIO_PIN(0x44, 0x7B0), ++ MX51_PIN_EIM_DA11 = _MXC_BUILD_NON_GPIO_PIN(0x48, 0x7B0), ++ MX51_PIN_EIM_DA12 = _MXC_BUILD_NON_GPIO_PIN(0x4C, 0x7BC), ++ MX51_PIN_EIM_DA13 = _MXC_BUILD_NON_GPIO_PIN(0x50, 0x7BC), ++ MX51_PIN_EIM_DA14 = _MXC_BUILD_NON_GPIO_PIN(0x54, 0x7BC), ++ MX51_PIN_EIM_DA15 = _MXC_BUILD_NON_GPIO_PIN(0x58, 0x7BC), ++ MX51_PIN_EIM_D16 = _MXC_BUILD_GPIO_PIN(1, 0, 1, 0x5C, 0x3F0), ++ MX51_PIN_EIM_D17 = _MXC_BUILD_GPIO_PIN(1, 1, 1, 0x60, 0x3F4), ++ MX51_PIN_EIM_D18 = _MXC_BUILD_GPIO_PIN(1, 2, 1, 0x64, 0x3F8), ++ MX51_PIN_EIM_D19 = _MXC_BUILD_GPIO_PIN(1, 3, 1, 0x68, 0x3FC), ++ MX51_PIN_EIM_D20 = _MXC_BUILD_GPIO_PIN(1, 4, 1, 0x6C, 0x400), ++ MX51_PIN_EIM_D21 = _MXC_BUILD_GPIO_PIN(1, 5, 1, 0x70, 0x404), ++ MX51_PIN_EIM_D22 = _MXC_BUILD_GPIO_PIN(1, 6, 1, 0x74, 0x408), ++ MX51_PIN_EIM_D23 = _MXC_BUILD_GPIO_PIN(1, 7, 1, 0x78, 0x40C), ++ MX51_PIN_EIM_D24 = _MXC_BUILD_GPIO_PIN(1, 8, 1, 0x7C, 0x410), ++ MX51_PIN_EIM_D25 = _MXC_BUILD_NON_GPIO_PIN(0x80, 0x414), ++ MX51_PIN_EIM_D26 = _MXC_BUILD_NON_GPIO_PIN(0x84, 0x418), ++ MX51_PIN_EIM_D27 = _MXC_BUILD_GPIO_PIN(1, 9, 1, 0x88, 0x41C), ++ MX51_PIN_EIM_D28 = _MXC_BUILD_NON_GPIO_PIN(0x8C, 0x420), ++ MX51_PIN_EIM_D29 = _MXC_BUILD_NON_GPIO_PIN(0x90, 0x424), ++ MX51_PIN_EIM_D30 = _MXC_BUILD_NON_GPIO_PIN(0x94, 0x428), ++ MX51_PIN_EIM_D31 = _MXC_BUILD_NON_GPIO_PIN(0x98, 0x42C), ++ MX51_PIN_EIM_A16 = _MXC_BUILD_GPIO_PIN(1, 10, 1, 0x9C, 0x430), ++ MX51_PIN_EIM_A17 = _MXC_BUILD_GPIO_PIN(1, 11, 1, 0xA0, 0x434), ++ MX51_PIN_EIM_A18 = _MXC_BUILD_GPIO_PIN(1, 12, 1, 0xA4, 0x438), ++ MX51_PIN_EIM_A19 = _MXC_BUILD_GPIO_PIN(1, 13, 1, 0xA8, 0x43C), ++ MX51_PIN_EIM_A20 = _MXC_BUILD_GPIO_PIN(1, 14, 1, 0xAC, 0x440), ++ MX51_PIN_EIM_A21 = _MXC_BUILD_GPIO_PIN(1, 15, 1, 0xB0, 0x444), ++ MX51_PIN_EIM_A22 = _MXC_BUILD_GPIO_PIN(1, 16, 1, 0xB4, 0x448), ++ MX51_PIN_EIM_A23 = _MXC_BUILD_GPIO_PIN(1, 17, 1, 0xB8, 0x44C), ++ MX51_PIN_EIM_A24 = _MXC_BUILD_GPIO_PIN(1, 18, 1, 0xBC, 0x450), ++ MX51_PIN_EIM_A25 = _MXC_BUILD_GPIO_PIN(1, 19, 1, 0xC0, 0x454), ++ MX51_PIN_EIM_A26 = _MXC_BUILD_GPIO_PIN(1, 20, 1, 0xC4, 0x458), ++ MX51_PIN_EIM_A27 = _MXC_BUILD_GPIO_PIN(1, 21, 1, 0xC8, 0x45C), ++ MX51_PIN_EIM_EB0 = _MXC_BUILD_NON_GPIO_PIN(0xCC, 0x460), ++ MX51_PIN_EIM_EB1 = _MXC_BUILD_NON_GPIO_PIN(0xD0, 0x464), ++ MX51_PIN_EIM_EB2 = _MXC_BUILD_GPIO_PIN(1, 22, 1, 0xD4, 0x468), ++ MX51_PIN_EIM_EB3 = _MXC_BUILD_GPIO_PIN(1, 23, 1, 0xD8, 0x46C), ++ MX51_PIN_EIM_OE = _MXC_BUILD_GPIO_PIN(1, 24, 1, 0xDC, 0x470), ++ MX51_PIN_EIM_CS0 = _MXC_BUILD_GPIO_PIN(1, 25, 1, 0xE0, 0x474), ++ MX51_PIN_EIM_CS1 = _MXC_BUILD_GPIO_PIN(1, 26, 1, 0xE4, 0x478), ++ MX51_PIN_EIM_CS2 = _MXC_BUILD_GPIO_PIN(1, 27, 1, 0xE8, 0x47C), ++ MX51_PIN_EIM_CS3 = _MXC_BUILD_GPIO_PIN(1, 28, 1, 0xEC, 0x480), ++ MX51_PIN_EIM_CS4 = _MXC_BUILD_GPIO_PIN(1, 29, 1, 0xF0, 0x484), ++ MX51_PIN_EIM_CS5 = _MXC_BUILD_GPIO_PIN(1, 30, 1, 0xF4, 0x488), ++ MX51_PIN_EIM_DTACK = _MXC_BUILD_GPIO_PIN(1, 31, 1, 0xF8, 0x48C), ++ MX51_PIN_EIM_LBA = _MXC_BUILD_GPIO_PIN(2, 1, 1, 0xFC, 0x494), ++ MX51_PIN_EIM_CRE = _MXC_BUILD_GPIO_PIN(2, 2, 1, 0x100, 0x4A0), ++ MX51_PIN_DRAM_CS1 = _MXC_BUILD_NON_GPIO_PIN(0x104, 0x4D0), ++ MX51_PIN_NANDF_WE_B = _MXC_BUILD_GPIO_PIN(2, 3, 3, 0x108, 0x4E4), ++ MX51_PIN_NANDF_RE_B = _MXC_BUILD_GPIO_PIN(2, 4, 3, 0x10C, 0x4E8), ++ MX51_PIN_NANDF_ALE = _MXC_BUILD_GPIO_PIN(2, 5, 3, 0x110, 0x4EC), ++ MX51_PIN_NANDF_CLE = _MXC_BUILD_GPIO_PIN(2, 6, 3, 0x114, 0x4F0), ++ MX51_PIN_NANDF_WP_B = _MXC_BUILD_GPIO_PIN(2, 7, 3, 0x118, 0x4F4), ++ MX51_PIN_NANDF_RB0 = _MXC_BUILD_GPIO_PIN(2, 8, 3, 0x11C, 0x4F8), ++ MX51_PIN_NANDF_RB1 = _MXC_BUILD_GPIO_PIN(2, 9, 3, 0x120, 0x4FC), ++ MX51_PIN_NANDF_RB2 = _MXC_BUILD_GPIO_PIN(2, 10, 3, 0x124, 0x500), ++ MX51_PIN_NANDF_RB3 = _MXC_BUILD_GPIO_PIN(2, 11, 3, 0x128, 0x504), ++ MX51_PIN_GPIO_NAND = _MXC_BUILD_GPIO_PIN(2, 12, 3, 0x12C, 0x514), ++ MX51_PIN_NANDF_RB4 = MX51_PIN_GPIO_NAND, ++ MX51_PIN_NANDF_RB5 = _MXC_BUILD_GPIO_PIN(2, 13, 3, 0x130, 0x5D8), ++ MX51_PIN_NANDF_RB6 = _MXC_BUILD_GPIO_PIN(2, 14, 3, 0x134, 0x5DC), ++ MX51_PIN_NANDF_RB7 = _MXC_BUILD_GPIO_PIN(2, 15, 3, 0x138, 0x5E0), ++ MX51_PIN_NANDF_CS0 = _MXC_BUILD_GPIO_PIN(2, 16, 3, 0x130, 0x518), ++ MX51_PIN_NANDF_CS1 = _MXC_BUILD_GPIO_PIN(2, 17, 3, 0x134, 0x51C), ++ MX51_PIN_NANDF_CS2 = _MXC_BUILD_GPIO_PIN(2, 18, 3, 0x138, 0x520), ++ MX51_PIN_NANDF_CS3 = _MXC_BUILD_GPIO_PIN(2, 19, 3, 0x13C, 0x524), ++ MX51_PIN_NANDF_CS4 = _MXC_BUILD_GPIO_PIN(2, 20, 3, 0x140, 0x528), ++ MX51_PIN_NANDF_CS5 = _MXC_BUILD_GPIO_PIN(2, 21, 3, 0x144, 0x52C), ++ MX51_PIN_NANDF_CS6 = _MXC_BUILD_GPIO_PIN(2, 22, 3, 0x148, 0x530), ++ MX51_PIN_NANDF_CS7 = _MXC_BUILD_GPIO_PIN(2, 23, 3, 0x14C, 0x534), ++ MX51_PIN_NANDF_RDY_INT = _MXC_BUILD_GPIO_PIN(2, 24, 3, 0x150, 0x538), ++ MX51_PIN_NANDF_D15 = _MXC_BUILD_GPIO_PIN(2, 25, 3, 0x154, 0x53C), ++ MX51_PIN_NANDF_D14 = _MXC_BUILD_GPIO_PIN(2, 26, 3, 0x158, 0x540), ++ MX51_PIN_NANDF_D13 = _MXC_BUILD_GPIO_PIN(2, 27, 3, 0x15C, 0x544), ++ MX51_PIN_NANDF_D12 = _MXC_BUILD_GPIO_PIN(2, 28, 3, 0x160, 0x548), ++ MX51_PIN_NANDF_D11 = _MXC_BUILD_GPIO_PIN(2, 29, 3, 0x164, 0x54C), ++ MX51_PIN_NANDF_D10 = _MXC_BUILD_GPIO_PIN(2, 30, 3, 0x168, 0x550), ++ MX51_PIN_NANDF_D9 = _MXC_BUILD_GPIO_PIN(2, 31, 3, 0x16C, 0x554), ++ MX51_PIN_NANDF_D8 = _MXC_BUILD_GPIO_PIN(3, 0, 3, 0x170, 0x558), ++ MX51_PIN_NANDF_D7 = _MXC_BUILD_GPIO_PIN(3, 1, 3, 0x174, 0x55C), ++ MX51_PIN_NANDF_D6 = _MXC_BUILD_GPIO_PIN(3, 2, 3, 0x178, 0x560), ++ MX51_PIN_NANDF_D5 = _MXC_BUILD_GPIO_PIN(3, 3, 3, 0x17C, 0x564), ++ MX51_PIN_NANDF_D4 = _MXC_BUILD_GPIO_PIN(3, 4, 3, 0x180, 0x568), ++ MX51_PIN_NANDF_D3 = _MXC_BUILD_GPIO_PIN(3, 5, 3, 0x184, 0x56C), ++ MX51_PIN_NANDF_D2 = _MXC_BUILD_GPIO_PIN(3, 6, 3, 0x188, 0x570), ++ MX51_PIN_NANDF_D1 = _MXC_BUILD_GPIO_PIN(3, 7, 3, 0x18C, 0x574), ++ MX51_PIN_NANDF_D0 = _MXC_BUILD_GPIO_PIN(3, 8, 3, 0x190, 0x578), ++ MX51_PIN_CSI1_D8 = _MXC_BUILD_GPIO_PIN(2, 12, 3, 0x194, 0x57C), ++ MX51_PIN_CSI1_D9 = _MXC_BUILD_GPIO_PIN(2, 13, 3, 0x198, 0x580), ++ MX51_PIN_CSI1_D10 = _MXC_BUILD_NON_GPIO_PIN(0x19C, 0x584), ++ MX51_PIN_CSI1_D11 = _MXC_BUILD_NON_GPIO_PIN(0x1A0, 0x588), ++ MX51_PIN_CSI1_D12 = _MXC_BUILD_NON_GPIO_PIN(0x1A4, 0x58C), ++ MX51_PIN_CSI1_D13 = _MXC_BUILD_NON_GPIO_PIN(0x1A8, 0x590), ++ MX51_PIN_CSI1_D14 = _MXC_BUILD_NON_GPIO_PIN(0x1AC, 0x594), ++ MX51_PIN_CSI1_D15 = _MXC_BUILD_NON_GPIO_PIN(0x1B0, 0x598), ++ MX51_PIN_CSI1_D16 = _MXC_BUILD_NON_GPIO_PIN(0x1B4, 0x59C), ++ MX51_PIN_CSI1_D17 = _MXC_BUILD_NON_GPIO_PIN(0x1B8, 0x5A0), ++ MX51_PIN_CSI1_D18 = _MXC_BUILD_NON_GPIO_PIN(0x1BC, 0x5A4), ++ MX51_PIN_CSI1_D19 = _MXC_BUILD_NON_GPIO_PIN(0x1C0, 0x5A8), ++ MX51_PIN_CSI1_VSYNC = _MXC_BUILD_NON_GPIO_PIN(0x1C4, 0x5AC), ++ MX51_PIN_CSI1_HSYNC = _MXC_BUILD_NON_GPIO_PIN(0x1C8, 0x5B0), ++ MX51_PIN_CSI1_PIXCLK = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x5B4), ++ MX51_PIN_CSI1_MCLK = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x5B8), ++ MX51_PIN_CSI1_PKE0 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x860), ++ MX51_PIN_CSI2_D12 = _MXC_BUILD_GPIO_PIN(3, 9, 3, 0x1CC, 0x5BC), ++ MX51_PIN_CSI2_D13 = _MXC_BUILD_GPIO_PIN(3, 10, 3, 0x1D0, 0x5C0), ++ MX51_PIN_CSI2_D14 = _MXC_BUILD_GPIO_PIN(3, 11, 3, 0x1D4, 0x5C4), ++ MX51_PIN_CSI2_D15 = _MXC_BUILD_GPIO_PIN(3, 12, 3, 0x1D8, 0x5C8), ++ MX51_PIN_CSI2_D16 = _MXC_BUILD_GPIO_PIN(3, 11, 3, 0x1DC, 0x5CC), ++ MX51_PIN_CSI2_D17 = _MXC_BUILD_GPIO_PIN(3, 12, 3, 0x1E0, 0x5D0), ++ MX51_PIN_CSI2_D18 = _MXC_BUILD_GPIO_PIN(3, 11, 3, 0x1E4, 0x5D4), ++ MX51_PIN_CSI2_D19 = _MXC_BUILD_GPIO_PIN(3, 12, 3, 0x1E8, 0x5D8), ++ MX51_PIN_CSI2_VSYNC = _MXC_BUILD_GPIO_PIN(3, 13, 3, 0x1EC, 0x5DC), ++ MX51_PIN_CSI2_HSYNC = _MXC_BUILD_GPIO_PIN(3, 14, 3, 0x1F0, 0x5E0), ++ MX51_PIN_CSI2_PIXCLK = _MXC_BUILD_GPIO_PIN(3, 15, 3, 0x1F4, 0x5E4), ++ MX51_PIN_CSI2_PKE0 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x81C), ++ MX51_PIN_I2C1_CLK = _MXC_BUILD_GPIO_PIN(3, 16, 3, 0x1F8, 0x5E8), ++ MX51_PIN_I2C1_DAT = _MXC_BUILD_GPIO_PIN(3, 17, 3, 0x1FC, 0x5EC), ++ MX51_PIN_AUD3_BB_TXD = _MXC_BUILD_GPIO_PIN(3, 18, 3, 0x200, 0x5F0), ++ MX51_PIN_AUD3_BB_RXD = _MXC_BUILD_GPIO_PIN(3, 19, 3, 0x204, 0x5F4), ++ MX51_PIN_AUD3_BB_CK = _MXC_BUILD_GPIO_PIN(3, 20, 3, 0x208, 0x5F8), ++ MX51_PIN_AUD3_BB_FS = _MXC_BUILD_GPIO_PIN(3, 21, 3, 0x20C, 0x5FC), ++ MX51_PIN_CSPI1_MOSI = _MXC_BUILD_GPIO_PIN(3, 22, 3, 0x210, 0x600), ++ MX51_PIN_CSPI1_MISO = _MXC_BUILD_GPIO_PIN(3, 23, 3, 0x214, 0x604), ++ MX51_PIN_CSPI1_SS0 = _MXC_BUILD_GPIO_PIN(3, 24, 3, 0x218, 0x608), ++ MX51_PIN_CSPI1_SS1 = _MXC_BUILD_GPIO_PIN(3, 25, 3, 0x21C, 0x60C), ++ MX51_PIN_CSPI1_RDY = _MXC_BUILD_GPIO_PIN(3, 26, 3, 0x220, 0x610), ++ MX51_PIN_CSPI1_SCLK = _MXC_BUILD_GPIO_PIN(3, 27, 3, 0x224, 0x614), ++ MX51_PIN_UART1_RXD = _MXC_BUILD_GPIO_PIN(3, 28, 3, 0x228, 0x618), ++ MX51_PIN_UART1_TXD = _MXC_BUILD_GPIO_PIN(3, 29, 3, 0x22C, 0x61C), ++ MX51_PIN_UART1_RTS = _MXC_BUILD_GPIO_PIN(3, 30, 3, 0x230, 0x620), ++ MX51_PIN_UART1_CTS = _MXC_BUILD_GPIO_PIN(3, 31, 3, 0x234, 0x624), ++ MX51_PIN_UART2_RXD = _MXC_BUILD_GPIO_PIN(0, 20, 3, 0x238, 0x628), ++ MX51_PIN_UART2_TXD = _MXC_BUILD_GPIO_PIN(0, 21, 3, 0x23C, 0x62C), ++ MX51_PIN_UART3_RXD = _MXC_BUILD_GPIO_PIN(0, 22, 3, 0x240, 0x630), ++ MX51_PIN_UART3_TXD = _MXC_BUILD_GPIO_PIN(0, 23, 3, 0x244, 0x634), ++ MX51_PIN_OWIRE_LINE = _MXC_BUILD_GPIO_PIN(0, 24, 3, 0x248, 0x638), ++ MX51_PIN_KEY_ROW0 = _MXC_BUILD_NON_GPIO_PIN(0x24C, 0x63C), ++ MX51_PIN_KEY_ROW1 = _MXC_BUILD_NON_GPIO_PIN(0x250, 0x640), ++ MX51_PIN_KEY_ROW2 = _MXC_BUILD_NON_GPIO_PIN(0x254, 0x644), ++ MX51_PIN_KEY_ROW3 = _MXC_BUILD_NON_GPIO_PIN(0x258, 0x648), ++ MX51_PIN_KEY_COL0 = _MXC_BUILD_NON_GPIO_PIN(0x25C, 0x64C), ++ MX51_PIN_KEY_COL1 = _MXC_BUILD_NON_GPIO_PIN(0x260, 0x650), ++ MX51_PIN_KEY_COL2 = _MXC_BUILD_NON_GPIO_PIN(0x264, 0x654), ++ MX51_PIN_KEY_COL3 = _MXC_BUILD_NON_GPIO_PIN(0x268, 0x658), ++ MX51_PIN_KEY_COL4 = _MXC_BUILD_NON_GPIO_PIN(0x26C, 0x65C), ++ MX51_PIN_KEY_COL5 = _MXC_BUILD_NON_GPIO_PIN(0x270, 0x660), ++ MX51_PIN_USBH1_CLK = _MXC_BUILD_GPIO_PIN(0, 25, 2, 0x278, 0x678), ++ MX51_PIN_USBH1_DIR = _MXC_BUILD_GPIO_PIN(0, 26, 2, 0x27C, 0x67C), ++ MX51_PIN_USBH1_STP = _MXC_BUILD_GPIO_PIN(0, 27, 2, 0x280, 0x680), ++ MX51_PIN_USBH1_NXT = _MXC_BUILD_GPIO_PIN(0, 28, 2, 0x284, 0x684), ++ MX51_PIN_USBH1_DATA0 = _MXC_BUILD_GPIO_PIN(0, 11, 2, 0x288, 0x688), ++ MX51_PIN_USBH1_DATA1 = _MXC_BUILD_GPIO_PIN(0, 12, 2, 0x28C, 0x68C), ++ MX51_PIN_USBH1_DATA2 = _MXC_BUILD_GPIO_PIN(0, 13, 2, 0x290, 0x690), ++ MX51_PIN_USBH1_DATA3 = _MXC_BUILD_GPIO_PIN(0, 14, 2, 0x294, 0x694), ++ MX51_PIN_USBH1_DATA4 = _MXC_BUILD_GPIO_PIN(0, 15, 2, 0x298, 0x698), ++ MX51_PIN_USBH1_DATA5 = _MXC_BUILD_GPIO_PIN(0, 16, 2, 0x29C, 0x69C), ++ MX51_PIN_USBH1_DATA6 = _MXC_BUILD_GPIO_PIN(0, 17, 2, 0x2A0, 0x6A0), ++ MX51_PIN_USBH1_DATA7 = _MXC_BUILD_GPIO_PIN(0, 18, 2, 0x2A4, 0x6A4), ++ MX51_PIN_DI1_PIN11 = _MXC_BUILD_GPIO_PIN(2, 0, 4, 0x2A8, 0x6A8), ++ MX51_PIN_DI1_PIN12 = _MXC_BUILD_GPIO_PIN(2, 1, 4, 0x2AC, 0x6AC), ++ MX51_PIN_DI1_PIN13 = _MXC_BUILD_GPIO_PIN(2, 2, 4, 0x2B0, 0x6B0), ++ MX51_PIN_DI1_D0_CS = _MXC_BUILD_GPIO_PIN(2, 3, 4, 0x2B4, 0x6B4), ++ MX51_PIN_DI1_D1_CS = _MXC_BUILD_GPIO_PIN(2, 4, 4, 0x2B8, 0x6B8), ++ MX51_PIN_DISPB2_SER_DIN = _MXC_BUILD_GPIO_PIN(2, 5, 4, 0x2BC, 0x6BC), ++ MX51_PIN_DISPB2_SER_DIO = _MXC_BUILD_GPIO_PIN(2, 6, 4, 0x2C0, 0x6C0), ++ MX51_PIN_DISPB2_SER_CLK = _MXC_BUILD_GPIO_PIN(2, 7, 4, 0x2C4, 0x6C4), ++ MX51_PIN_DISPB2_SER_RS = _MXC_BUILD_GPIO_PIN(2, 8, 4, 0x2C8, 0x6C8), ++ MX51_PIN_DISP1_DAT0 = _MXC_BUILD_NON_GPIO_PIN(0x2CC, 0x6CC), ++ MX51_PIN_DISP1_DAT1 = _MXC_BUILD_NON_GPIO_PIN(0x2D0, 0x6D0), ++ MX51_PIN_DISP1_DAT2 = _MXC_BUILD_NON_GPIO_PIN(0x2D4, 0x6D4), ++ MX51_PIN_DISP1_DAT3 = _MXC_BUILD_NON_GPIO_PIN(0x2D8, 0x6D8), ++ MX51_PIN_DISP1_DAT4 = _MXC_BUILD_NON_GPIO_PIN(0x2DC, 0x6DC), ++ MX51_PIN_DISP1_DAT5 = _MXC_BUILD_NON_GPIO_PIN(0x2E0, 0x6E0), ++ MX51_PIN_DISP1_DAT6 = _MXC_BUILD_NON_GPIO_PIN(0x2E4, 0x6E4), ++ MX51_PIN_DISP1_DAT7 = _MXC_BUILD_NON_GPIO_PIN(0x2E8, 0x6E8), ++ MX51_PIN_DISP1_DAT8 = _MXC_BUILD_NON_GPIO_PIN(0x2EC, 0x6EC), ++ MX51_PIN_DISP1_DAT9 = _MXC_BUILD_NON_GPIO_PIN(0x2F0, 0x6F0), ++ MX51_PIN_DISP1_DAT10 = _MXC_BUILD_NON_GPIO_PIN(0x2F4, 0x6F4), ++ MX51_PIN_DISP1_DAT11 = _MXC_BUILD_NON_GPIO_PIN(0x2F8, 0x6F8), ++ MX51_PIN_DISP1_DAT12 = _MXC_BUILD_NON_GPIO_PIN(0x2FC, 0x6FC), ++ MX51_PIN_DISP1_DAT13 = _MXC_BUILD_NON_GPIO_PIN(0x300, 0x700), ++ MX51_PIN_DISP1_DAT14 = _MXC_BUILD_NON_GPIO_PIN(0x304, 0x704), ++ MX51_PIN_DISP1_DAT15 = _MXC_BUILD_NON_GPIO_PIN(0x308, 0x708), ++ MX51_PIN_DISP1_DAT16 = _MXC_BUILD_NON_GPIO_PIN(0x30C, 0x70C), ++ MX51_PIN_DISP1_DAT17 = _MXC_BUILD_NON_GPIO_PIN(0x310, 0x710), ++ MX51_PIN_DISP1_DAT18 = _MXC_BUILD_NON_GPIO_PIN(0x314, 0x714), ++ MX51_PIN_DISP1_DAT19 = _MXC_BUILD_NON_GPIO_PIN(0x318, 0x718), ++ MX51_PIN_DISP1_DAT20 = _MXC_BUILD_NON_GPIO_PIN(0x31C, 0x71C), ++ MX51_PIN_DISP1_DAT21 = _MXC_BUILD_NON_GPIO_PIN(0x320, 0x720), ++ MX51_PIN_DISP1_DAT22 = _MXC_BUILD_NON_GPIO_PIN(0x324, 0x724), ++ MX51_PIN_DISP1_DAT23 = _MXC_BUILD_NON_GPIO_PIN(0x328, 0x728), ++ MX51_PIN_DI1_PIN3 = _MXC_BUILD_NON_GPIO_PIN(0x32C, 0x72C), ++ MX51_PIN_DI1_PIN2 = _MXC_BUILD_NON_GPIO_PIN(0x330, 0x734), ++ MX51_PIN_DI_GP1 = _MXC_BUILD_NON_GPIO_PIN(0x334, 0x73C), ++ MX51_PIN_DI_GP2 = _MXC_BUILD_NON_GPIO_PIN(0x338, 0x740), ++ MX51_PIN_DI_GP3 = _MXC_BUILD_NON_GPIO_PIN(0x33C, 0x744), ++ MX51_PIN_DI2_PIN4 = _MXC_BUILD_NON_GPIO_PIN(0x340, 0x748), ++ MX51_PIN_DI2_PIN2 = _MXC_BUILD_NON_GPIO_PIN(0x344, 0x74C), ++ MX51_PIN_DI2_PIN3 = _MXC_BUILD_NON_GPIO_PIN(0x348, 0x750), ++ MX51_PIN_DI2_DISP_CLK = _MXC_BUILD_NON_GPIO_PIN(0x34C, 0x754), ++ MX51_PIN_DI_GP4 = _MXC_BUILD_NON_GPIO_PIN(0x350, 0x758), ++ MX51_PIN_DISP2_DAT0 = _MXC_BUILD_NON_GPIO_PIN(0x354, 0x75C), ++ MX51_PIN_DISP2_DAT1 = _MXC_BUILD_NON_GPIO_PIN(0x358, 0x760), ++ MX51_PIN_DISP2_DAT2 = _MXC_BUILD_NON_GPIO_PIN(0x35C, 0x764), ++ MX51_PIN_DISP2_DAT3 = _MXC_BUILD_NON_GPIO_PIN(0x360, 0x768), ++ MX51_PIN_DISP2_DAT4 = _MXC_BUILD_NON_GPIO_PIN(0x364, 0x76C), ++ MX51_PIN_DISP2_DAT5 = _MXC_BUILD_NON_GPIO_PIN(0x368, 0x770), ++ MX51_PIN_DISP2_DAT6 = _MXC_BUILD_GPIO_PIN(0, 19, 5, 0x36C, 0x774), ++ MX51_PIN_DISP2_DAT7 = _MXC_BUILD_GPIO_PIN(0, 29, 5, 0x370, 0x778), ++ MX51_PIN_DISP2_DAT8 = _MXC_BUILD_GPIO_PIN(0, 30, 5, 0x374, 0x77C), ++ MX51_PIN_DISP2_DAT9 = _MXC_BUILD_GPIO_PIN(0, 31, 5, 0x378, 0x780), ++ MX51_PIN_DISP2_DAT10 = _MXC_BUILD_NON_GPIO_PIN(0x37C, 0x784), ++ MX51_PIN_DISP2_DAT11 = _MXC_BUILD_NON_GPIO_PIN(0x380, 0x788), ++ MX51_PIN_DISP2_DAT12 = _MXC_BUILD_NON_GPIO_PIN(0x384, 0x78C), ++ MX51_PIN_DISP2_DAT13 = _MXC_BUILD_NON_GPIO_PIN(0x388, 0x790), ++ MX51_PIN_DISP2_DAT14 = _MXC_BUILD_NON_GPIO_PIN(0x38C, 0x794), ++ MX51_PIN_DISP2_DAT15 = _MXC_BUILD_NON_GPIO_PIN(0x390, 0x798), ++ MX51_PIN_SD1_CMD = _MXC_BUILD_NON_GPIO_PIN(0x394, 0x79C), ++ MX51_PIN_SD1_CLK = _MXC_BUILD_NON_GPIO_PIN(0x398, 0x7A0), ++ MX51_PIN_SD1_DATA0 = _MXC_BUILD_NON_GPIO_PIN(0x39C, 0x7A4), ++ MX51_PIN_SD1_DATA1 = _MXC_BUILD_NON_GPIO_PIN(0x3A0, 0x7A8), ++ MX51_PIN_SD1_DATA2 = _MXC_BUILD_NON_GPIO_PIN(0x3A4, 0x7AC), ++ MX51_PIN_SD1_DATA3 = _MXC_BUILD_NON_GPIO_PIN(0x3A8, 0x7B0), ++ MX51_PIN_GPIO1_0 = _MXC_BUILD_GPIO_PIN(0, 0, 1, 0x3AC, 0x7B4), ++ MX51_PIN_GPIO1_1 = _MXC_BUILD_GPIO_PIN(0, 1, 1, 0x3B0, 0x7B8), ++ MX51_PIN_SD2_CMD = _MXC_BUILD_NON_GPIO_PIN(0x3B4, 0x7BC), ++ MX51_PIN_SD2_CLK = _MXC_BUILD_NON_GPIO_PIN(0x3B8, 0x7C0), ++ MX51_PIN_SD2_DATA0 = _MXC_BUILD_NON_GPIO_PIN(0x3BC, 0x7C4), ++ MX51_PIN_SD2_DATA1 = _MXC_BUILD_NON_GPIO_PIN(0x3C0, 0x7C8), ++ MX51_PIN_SD2_DATA2 = _MXC_BUILD_NON_GPIO_PIN(0x3C4, 0x7CC), ++ MX51_PIN_SD2_DATA3 = _MXC_BUILD_NON_GPIO_PIN(0x3C8, 0x7D0), ++ MX51_PIN_GPIO1_2 = _MXC_BUILD_GPIO_PIN(0, 2, 0, 0x3CC, 0x7D4), ++ MX51_PIN_GPIO1_3 = _MXC_BUILD_GPIO_PIN(0, 3, 0, 0x3D0, 0x7D8), ++ MX51_PIN_PMIC_INT_REQ = _MXC_BUILD_NON_GPIO_PIN(0x3D4, 0x7FC), ++ MX51_PIN_GPIO1_4 = _MXC_BUILD_GPIO_PIN(0, 4, 0, 0x3D8, 0x804), ++ MX51_PIN_GPIO1_5 = _MXC_BUILD_GPIO_PIN(0, 5, 0, 0x3DC, 0x808), ++ MX51_PIN_GPIO1_6 = _MXC_BUILD_GPIO_PIN(0, 6, 0, 0x3E0, 0x80C), ++ MX51_PIN_GPIO1_7 = _MXC_BUILD_GPIO_PIN(0, 7, 0, 0x3E4, 0x810), ++ MX51_PIN_GPIO1_8 = _MXC_BUILD_GPIO_PIN(0, 8, 0, 0x3E8, 0x814), ++ MX51_PIN_GPIO1_9 = _MXC_BUILD_GPIO_PIN(0, 9, 0, 0x3EC, 0x818), ++}; ++ ++#endif /* __ASSEMBLY__ */ ++#endif /* __ASM_ARCH_MXC_MX51_PINS_H__ */ +diff --git a/include/asm-arm/arch-mx51/mxc_nand.h b/include/asm-arm/arch-mx51/mxc_nand.h +new file mode 100644 +index 0000000..aad93d1 +--- /dev/null ++++ b/include/asm-arm/arch-mx51/mxc_nand.h +@@ -0,0 +1,198 @@ ++/* ++ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file mxc_nd2.h ++ * ++ * @brief This file contains the NAND Flash Controller register information. ++ * ++ * ++ * @ingroup NAND_MTD ++ */ ++ ++#ifndef __MXC_NAND_H__ ++#define __MXC_NAND_H__ ++ ++#include ++ ++#define IS_2K_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) \ ++ == NAND_PAGESIZE_2KB) ++#define IS_4K_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) \ ++ == NAND_PAGESIZE_4KB) ++#define IS_LARGE_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) > 512) ++ ++#define NAND_PAGESIZE_2KB 2048 ++#define NAND_PAGESIZE_4KB 4096 ++#define NAND_MAX_PAGESIZE 4096 ++ ++/* ++ * Addresses for NFC registers ++ */ ++#define NFC_REG_BASE (NFC_BASE_ADDR + 0x1000) ++#define NFC_BUF_ADDR (NFC_REG_BASE + 0xE04) ++#define NFC_FLASH_ADDR (NFC_REG_BASE + 0xE06) ++#define NFC_FLASH_CMD (NFC_REG_BASE + 0xE08) ++#define NFC_CONFIG (NFC_REG_BASE + 0xE0A) ++#define NFC_ECC_STATUS_RESULT (NFC_REG_BASE + 0xE0C) ++#define NFC_SPAS (NFC_REG_BASE + 0xE10) ++#define NFC_WRPROT (NFC_REG_BASE + 0xE12) ++#define NFC_UNLOCKSTART_BLKADDR (NFC_REG_BASE + 0xE20) ++#define NFC_UNLOCKEND_BLKADDR (NFC_REG_BASE + 0xE22) ++#define NFC_CONFIG1 (NFC_REG_BASE + 0xE1A) ++#define NFC_CONFIG2 (NFC_REG_BASE + 0xE1C) ++ ++/*! ++ * Addresses for NFC RAM BUFFER Main area 0 ++ */ ++#define MAIN_AREA0 (u16 *)(NFC_BASE_ADDR + 0x000) ++#define MAIN_AREA1 (u16 *)(NFC_BASE_ADDR + 0x200) ++ ++/*! ++ * Addresses for NFC SPARE BUFFER Spare area 0 ++ */ ++#define SPARE_AREA0 (u16 *)(NFC_BASE_ADDR + 0x1000) ++#define SPARE_LEN 64 ++#define SPARE_COUNT 8 ++#define SPARE_SIZE (SPARE_LEN * SPARE_COUNT) ++ ++ ++#define SPAS_SHIFT (0) ++#define SPAS_MASK (0xFF00) ++#define IS_4BIT_ECC \ ++ ((raw_read(REG_NFC_ECC_MODE) & NFC_ECC_MODE_4) >> 0) ++ ++#define NFC_SET_SPAS(v) \ ++ raw_write(((raw_read(REG_NFC_SPAS) & SPAS_MASK) | \ ++ ((v< ++ * ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * Configuration settings for the MX31ADS Freescale board. ++ * ++ * 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 ++ ++#include ++ ++ /* High Level Configuration Options */ ++#define CONFIG_ARMV7 1 /* This is armv7 Cortex-A8 CPU core */ ++#define CONFIG_SYS_APCS_GNU ++#define CONFIG_L2_OFF ++ ++#define CONFIG_MXC 1 ++#define CONFIG_MX51 1 /* in a mx51 */ ++#define CONFIG_FLASH_HEADER 1 ++#define CONFIG_FLASH_HEADER_OFFSET 0x400 ++#define CONFIG_FLASH_HEADER_BARKER 0xB1 ++ ++#define CONFIG_SKIP_RELOCATE_UBOOT ++ ++#define CONFIG_MX51_HCLK_FREQ 24000000 /* RedBoot says 26MHz */ ++#define CONFIG_MX51_CLK32 32768 ++#define CONFIG_DISPLAY_CPUINFO ++#define CONFIG_DISPLAY_BOARDINFO ++ ++#define BOARD_LATE_INIT ++/* ++ * Disabled for now due to build problems under Debian and a significant ++ * increase in the final file size: 144260 vs. 109536 Bytes. ++ */ ++ ++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ ++#define CONFIG_REVISION_TAG 1 ++#define CONFIG_SETUP_MEMORY_TAGS 1 ++#define CONFIG_INITRD_TAG 1 ++ ++/* ++ * Size of malloc() pool ++ */ ++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 512 * 1024) ++/* size in bytes reserved for initial data */ ++#define CONFIG_SYS_GBL_DATA_SIZE 128 ++ ++/* ++ * Hardware drivers ++ */ ++#define CONFIG_MX51_UART 1 ++#define CONFIG_MX51_UART1 1 ++ ++/* allow to overwrite serial and ethaddr */ ++#define CONFIG_ENV_OVERWRITE ++#define CONFIG_CONS_INDEX 1 ++#define CONFIG_BAUDRATE 115200 ++#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200} ++ ++/*********************************************************** ++ * Command definition ++ ***********************************************************/ ++ ++#include ++ ++#define CONFIG_CMD_PING ++#define CONFIG_CMD_DHCP ++/* Enable below configure when supporting nand */ ++/* #define CONFIG_CMD_NAND */ ++#undef CONFIG_CMD_IMLS ++ ++#define CONFIG_BOOTDELAY 3 ++ ++#define CONFIG_LOADADDR 0x90800000 /* loadaddr env var */ ++ ++#define CONFIG_EXTRA_ENV_SETTINGS \ ++ "netdev=eth0\0" \ ++ "ethprime=smc911x\0" \ ++ "uboot_addr=0xa0000000\0" \ ++ "uboot=u-boot.bin\0" \ ++ "kernel=uImage\0" \ ++ "nfsroot=/opt/eldk/arm\0" \ ++ "bootargs_base=setenv bootargs console=ttymxc0,115200\0"\ ++ "bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs "\ ++ "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0"\ ++ "bootcmd=run bootcmd_net\0" \ ++ "bootcmd_net=run bootargs_base bootargs_nfs; " \ ++ "tftpboot ${loadaddr} ${kernel}; bootm\0" \ ++ "prg_uboot=tftpboot ${loadaddr} ${uboot}; " \ ++ "protect off ${uboot_addr} 0xa003ffff; " \ ++ "erase ${uboot_addr} 0xa003ffff; " \ ++ "cp.b ${loadaddr} ${uboot_addr} ${filesize}; " \ ++ "setenv filesize; saveenv\0" ++ ++/*Support LAN9217*/ ++#define CONFIG_DRIVER_SMC911X 1 ++#define CONFIG_DRIVER_SMC911X_16_BIT 1 ++#define CONFIG_DRIVER_SMC911X_BASE_VARIABLE mx51_io_base_addr ++ ++/* ++ * The MX51 3stack board seems to have a hardware "peculiarity" confirmed under ++ * U-Boot, RedBoot and Linux: the ethernet Rx signal is reaching the CS8900A ++ * controller inverted. The controller is capable of detecting and correcting ++ * this, but it needs 4 network packets for that. Which means, at startup, you ++ * will not receive answers to the first 4 packest, unless there have been some ++ * broadcasts on the network, or your board is on a hub. Reducing the ARP ++ * timeout from default 5 seconds to 200ms we speed up the initial TFTP ++ * transfer, should the user wish one, significantly. ++ */ ++#define CONFIG_ARP_TIMEOUT 200UL ++ ++/* ++ * Miscellaneous configurable options ++ */ ++#define CONFIG_SYS_LONGHELP /* undef to save memory */ ++#define CONFIG_SYS_PROMPT "=> " ++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ ++/* Print Buffer Size */ ++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) ++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ ++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ ++ ++#define CONFIG_SYS_MEMTEST_START 0 /* memtest works on */ ++#define CONFIG_SYS_MEMTEST_END 0x10000 ++ ++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */ ++ ++#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR ++ ++#define CONFIG_SYS_HZ CONFIG_MX51_CLK32/* use 32kHz clock as source */ ++ ++#define CONFIG_CMDLINE_EDITING 1 ++ ++/*----------------------------------------------------------------------- ++ * Stack sizes ++ * ++ * The stack sizes are set up in start.S using the settings below ++ */ ++#define CONFIG_STACKSIZE (128 * 1024) /* regular stack */ ++ ++/*----------------------------------------------------------------------- ++ * Physical Memory Map ++ */ ++#define CONFIG_NR_DRAM_BANKS 1 ++#define PHYS_SDRAM_1 CSD0_BASE_ADDR ++/* TO1 boards */ ++/* #define PHYS_SDRAM_1_SIZE (128 * 1024 * 1024) */ ++#define PHYS_SDRAM_1_SIZE (512 * 1024 * 1024) ++ ++/*----------------------------------------------------------------------- ++ * FLASH and environment organization ++ */ ++#define CONFIG_SYS_NO_FLASH ++ ++/*----------------------------------------------------------------------- ++ * NAND FLASH driver setup ++ */ ++#define NAND_MAX_CHIPS 1 ++#define CONFIG_SYS_MAX_NAND_DEVICE 1 ++#define CONFIG_SYS_NAND_BASE 0x40000000 ++ ++/* Monitor at beginning of flash */ ++#define CONFIG_ENV_IS_NOWHERE 1 ++#define CONFIG_ENV_SECT_SIZE (128 * 1024) ++#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE ++/* #define CFG_ENV_ADDR (CFG_MONITOR_BASE + CFG_ENV_SECT_SIZE) */ ++#define CONFIG_ENV_OFFSET 0x40000 ++/* ++ * JFFS2 partitions ++ */ ++#undef CONFIG_JFFS2_CMDLINE ++#define CONFIG_JFFS2_DEV "nand0" ++ ++#endif /* __CONFIG_H */ +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0006-ENGR00102788-Remove-CONFIG_NAND_BOOT-on-i.MX31-3stac.patch +++ uboot-imx-2009.01/debian/patches/0006-ENGR00102788-Remove-CONFIG_NAND_BOOT-on-i.MX31-3stac.patch @@ -0,0 +1,59 @@ +From 93af7d33b01d0af359e4a9643fca7e842415e862 Mon Sep 17 00:00:00 2001 +From: Fred Fan +Date: Mon, 23 Feb 2009 13:57:38 +0800 +Subject: [PATCH] ENGR00102788 Remove CONFIG_NAND_BOOT on i.MX31 3stack + +1. Change NAND driver Makefile to bulild individual nand driver on i.MX31 + and i.MX35. +2. Remove CONFIG_NAND_BOOT to common boot code which supports boot from nand + and nor. + +Signed-off-by: Fred Fan +--- + cpu/arm1136/mx31/Makefile | 2 -- + drivers/mtd/nand/Makefile | 2 +- + include/configs/mx31_3stack.h | 1 - + 3 files changed, 1 insertions(+), 4 deletions(-) + +diff --git a/cpu/arm1136/mx31/Makefile b/cpu/arm1136/mx31/Makefile +index 56313e0..50628af 100644 +--- a/cpu/arm1136/mx31/Makefile ++++ b/cpu/arm1136/mx31/Makefile +@@ -27,9 +27,7 @@ LIB = $(obj)lib$(SOC).a + + COBJS = interrupts.o serial.o generic.o + +-ifdef CONFIG_NAND_BOOT + SOBJS = nand_load.o +-endif + + SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) + OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile +index 4dc4483..2260d31 100644 +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -39,7 +39,7 @@ COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o + COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o + COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o + COBJS-$(CONFIG_MX31_NAND) += mx31_nand.o +-COBJS-y += mxc_nand.o ++COBJS-$(CONFIG_MX35) += mxc_nand.o + endif + + COBJS := $(COBJS-y) +diff --git a/include/configs/mx31_3stack.h b/include/configs/mx31_3stack.h +index 7aaef4f..887ffe3 100644 +--- a/include/configs/mx31_3stack.h ++++ b/include/configs/mx31_3stack.h +@@ -35,7 +35,6 @@ + #define CONFIG_DISPLAY_CPUINFO + #define CONFIG_DISPLAY_BOARDINFO + +-#define CONFIG_NAND_BOOT + #define CONFIG_SKIP_RELOCATE_UBOOT + + #define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0018-ENGR00112298-BBG2-Basic-boot.patch +++ uboot-imx-2009.01/debian/patches/0018-ENGR00112298-BBG2-Basic-boot.patch @@ -0,0 +1,1185 @@ +From 9cf764d379704260fb327d057dded5377188de16 Mon Sep 17 00:00:00 2001 +From: r65388 +Date: Wed, 13 May 2009 16:32:51 +0800 +Subject: [PATCH] ENGR00112298 BBG2: Basic boot. + +Basic boot on BBG2 board. + +Signed-off-by: r65388 +--- + Makefile | 3 + + board/freescale/imx51/Makefile | 49 ++++++ + board/freescale/imx51/board-imx51.h | 64 +++++++ + board/freescale/imx51/config.mk | 1 + + board/freescale/imx51/flash_header.S | 113 +++++++++++++ + board/freescale/imx51/imx51.c | 290 +++++++++++++++++++++++++++++++++ + board/freescale/imx51/lowlevel_init.S | 289 ++++++++++++++++++++++++++++++++ + board/freescale/imx51/u-boot.lds | 73 ++++++++ + include/configs/imx51.h | 221 +++++++++++++++++++++++++ + 9 files changed, 1103 insertions(+), 0 deletions(-) + +diff --git a/Makefile b/Makefile +index 46dd8fb..b1f1349 100644 +--- a/Makefile ++++ b/Makefile +@@ -2973,6 +2973,9 @@ mx31_3stack_config : unconfig + mx35_3stack_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm1136 mx35_3stack freescale mx35 + ++imx51_config : unconfig ++ @$(MKCONFIG) $(@:_config=) arm arm_cortexa8 imx51 freescale mx51 ++ + mx51_3stack_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm_cortexa8 mx51_3stack freescale mx51 + +diff --git a/board/freescale/imx51/Makefile b/board/freescale/imx51/Makefile +new file mode 100644 +index 0000000..fbd40f2 +--- /dev/null ++++ b/board/freescale/imx51/Makefile +@@ -0,0 +1,49 @@ ++# ++# Copyright (C) 2007, Guennadi Liakhovetski ++# ++# (C) Copyright 2009 Freescale Semiconductor, Inc. ++# ++# 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 := imx51.o ++SOBJS := lowlevel_init.o flash_header.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 .depend ++ ++######################################################################### ++ ++# defines $(obj).depend target ++include $(SRCTREE)/rules.mk ++ ++sinclude $(obj).depend ++ ++######################################################################### +diff --git a/board/freescale/imx51/board-imx51.h b/board/freescale/imx51/board-imx51.h +new file mode 100644 +index 0000000..7a2cae0 +--- /dev/null ++++ b/board/freescale/imx51/board-imx51.h +@@ -0,0 +1,64 @@ ++/* ++ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#ifndef __BOARD_FREESCALE_BOARD_IMX51_H__ ++#define __BOARD_FREESCALE_BOARD_IMX51_H__ ++ ++/*! ++ * @defgroup BRDCFG_MX51 Board Configuration Options ++ * @ingroup MSL_MX51 ++ */ ++ ++/*! ++ * @file mx51_3stack/board-imx51.h ++ * ++ * @brief This file contains all the board level configuration options. ++ * ++ * It currently hold the options defined for MX51 3Stack Platform. ++ * ++ * @ingroup BRDCFG_IMX51 ++ */ ++ ++/* CPLD offsets */ ++#define PBC_LED_CTRL (0x20000) ++#define PBC_SB_STAT (0x20008) ++#define PBC_ID_AAAA (0x20040) ++#define PBC_ID_5555 (0x20048) ++#define PBC_VERSION (0x20050) ++#define PBC_ID_CAFE (0x20058) ++#define PBC_INT_STAT (0x20010) ++#define PBC_INT_MASK (0x20038) ++#define PBC_INT_REST (0x20020) ++#define PBC_SW_RESET (0x20060) ++ ++/* LED switchs */ ++#define LED_SWITCH_REG 0x00 ++/* buttons */ ++#define SWITCH_BUTTONS_REG 0x08 ++/* status, interrupt */ ++#define INTR_STATUS_REG 0x10 ++#define INTR_MASK_REG 0x38 ++#define INTR_RESET_REG 0x20 ++/* magic word for debug CPLD */ ++#define MAGIC_NUMBER1_REG 0x40 ++#define MAGIC_NUMBER2_REG 0x48 ++/* CPLD code version */ ++#define CPLD_CODE_VER_REG 0x50 ++/* magic word for debug CPLD */ ++#define MAGIC_NUMBER3_REG 0x58 ++/* module reset register*/ ++#define MODULE_RESET_REG 0x60 ++/* CPU ID and Personality ID */ ++#define MCU_BOARD_ID_REG 0x68 ++ ++#endif /* __BOARD_FREESCALE_BOARD_IMX51_H__ */ +diff --git a/board/freescale/imx51/config.mk b/board/freescale/imx51/config.mk +new file mode 100644 +index 0000000..ce7369d +--- /dev/null ++++ b/board/freescale/imx51/config.mk +@@ -0,0 +1 @@ ++TEXT_BASE = 0x97800000 +diff --git a/board/freescale/imx51/flash_header.S b/board/freescale/imx51/flash_header.S +new file mode 100644 +index 0000000..6790679 +--- /dev/null ++++ b/board/freescale/imx51/flash_header.S +@@ -0,0 +1,113 @@ ++/* ++ * Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include "board-imx51.h" ++ ++#ifdef CONFIG_FLASH_HEADER ++#ifndef CONFIG_FLASH_HEADER_OFFSET ++# error "Must define the offset of flash header" ++#endif ++#define MXC_DCD_ITEM(i, type, addr, val) \ ++dcd_node_##i: \ ++ .word type ; \ ++ .word addr ; \ ++ .word val ; \ ++ ++.section ".text.flasheader", "x" ++ b _start ++ .org CONFIG_FLASH_HEADER_OFFSET ++app_code_jump_v: .word _start ++app_code_code_barker: .word CONFIG_FLASH_HEADER_BARKER ++app_code_csf: .word 0 ++dcd_ptr_ptr: .word dcd_ptr ++super_root_key: .word 0 ++dcd_ptr: .word dcd_array_start ++app_dest_ptr: .word TEXT_BASE ++dcd_array_start: ++magic: .word 0xB17219E9 ++dcd_array_size: .word dcd_data_end - dcd_array_start - 8 ++/* DCD */ ++/* DDR2 IOMUX configuration */ ++MXC_DCD_ITEM(1, 4, IOMUXC_BASE_ADDR + 0x8a0, 0x200) ++MXC_DCD_ITEM(2, 4, IOMUXC_BASE_ADDR + 0x50c, 0x20c5) ++MXC_DCD_ITEM(3, 4, IOMUXC_BASE_ADDR + 0x510, 0x20c5) ++MXC_DCD_ITEM(4, 4, IOMUXC_BASE_ADDR + 0x83c, 0x2) ++MXC_DCD_ITEM(5, 4, IOMUXC_BASE_ADDR + 0x848, 0x2) ++MXC_DCD_ITEM(6, 4, IOMUXC_BASE_ADDR + 0x4b8, 0xe7) ++MXC_DCD_ITEM(7, 4, IOMUXC_BASE_ADDR + 0x4bc, 0x45) ++MXC_DCD_ITEM(8, 4, IOMUXC_BASE_ADDR + 0x4c0, 0x45) ++MXC_DCD_ITEM(9, 4, IOMUXC_BASE_ADDR + 0x4c4, 0x45) ++MXC_DCD_ITEM(10, 4, IOMUXC_BASE_ADDR + 0x4c8, 0x45) ++MXC_DCD_ITEM(11, 4, IOMUXC_BASE_ADDR + 0x820, 0x0) ++MXC_DCD_ITEM(12, 4, IOMUXC_BASE_ADDR + 0x4a4, 0x3) ++MXC_DCD_ITEM(13, 4, IOMUXC_BASE_ADDR + 0x4a8, 0x3) ++MXC_DCD_ITEM(14, 4, IOMUXC_BASE_ADDR + 0x4ac, 0xe3) ++MXC_DCD_ITEM(15, 4, IOMUXC_BASE_ADDR + 0x4b0, 0xe3) ++MXC_DCD_ITEM(16, 4, IOMUXC_BASE_ADDR + 0x4b4, 0xe3) ++MXC_DCD_ITEM(17, 4, IOMUXC_BASE_ADDR + 0x4cc, 0xe3) ++MXC_DCD_ITEM(18, 4, IOMUXC_BASE_ADDR + 0x4d0, 0xe2) ++/* Set drive strength to MAX */ ++MXC_DCD_ITEM(19, 4, IOMUXC_BASE_ADDR + 0x82c, 0x6) ++MXC_DCD_ITEM(20, 4, IOMUXC_BASE_ADDR + 0x8a4, 0x6) ++MXC_DCD_ITEM(21, 4, IOMUXC_BASE_ADDR + 0x8ac, 0x6) ++MXC_DCD_ITEM(22, 4, IOMUXC_BASE_ADDR + 0x8b8, 0x6) ++/* 13 ROW, 10 COL, 32Bit, SREF=4 Micron Model */ ++/* CAS=3, BL=4 */ ++MXC_DCD_ITEM(23, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL0, 0x82a20000) ++MXC_DCD_ITEM(24, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL1, 0x82a20000) ++MXC_DCD_ITEM(25, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDMISC, 0x000ad0d0) ++MXC_DCD_ITEM(26, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCFG0, 0x333574aa) ++MXC_DCD_ITEM(27, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCFG1, 0x333574aa) ++/* Init DRAM on CS0 */ ++MXC_DCD_ITEM(28, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x04008008) ++MXC_DCD_ITEM(29, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801a) ++MXC_DCD_ITEM(30, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801b) ++MXC_DCD_ITEM(31, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00448019) ++MXC_DCD_ITEM(32, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x07328018) ++MXC_DCD_ITEM(33, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x04008008) ++MXC_DCD_ITEM(34, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008010) ++MXC_DCD_ITEM(35, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008010) ++MXC_DCD_ITEM(36, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x06328018) ++MXC_DCD_ITEM(37, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x03808019) ++MXC_DCD_ITEM(38, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00408019) ++MXC_DCD_ITEM(39, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008000) ++/* Init DRAM on CS1 */ ++MXC_DCD_ITEM(40, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0400800c) ++MXC_DCD_ITEM(41, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801e) ++MXC_DCD_ITEM(42, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801f) ++MXC_DCD_ITEM(43, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801d) ++MXC_DCD_ITEM(44, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0732801c) ++MXC_DCD_ITEM(45, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0400800c) ++MXC_DCD_ITEM(46, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008014) ++MXC_DCD_ITEM(47, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008014) ++MXC_DCD_ITEM(48, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0632801c) ++MXC_DCD_ITEM(49, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0380801d) ++MXC_DCD_ITEM(50, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0040801d) ++MXC_DCD_ITEM(51, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008004) ++MXC_DCD_ITEM(52, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL0, 0xb2a20000) ++MXC_DCD_ITEM(53, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL1, 0xb2a20000) ++MXC_DCD_ITEM(54, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDMISC, 0x000ad6d0) ++MXC_DCD_ITEM(55, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCDLYGD, 0x90000000) ++MXC_DCD_ITEM(56, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00000000) ++dcd_data_end: ++image_len: .word 0x100000 ++//image_len: .word _end - _start ++#endif +diff --git a/board/freescale/imx51/imx51.c b/board/freescale/imx51/imx51.c +new file mode 100644 +index 0000000..c8fe23b +--- /dev/null ++++ b/board/freescale/imx51/imx51.c +@@ -0,0 +1,290 @@ ++/* ++ * Copyright (C) 2007, Guennadi Liakhovetski ++ * ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include "board-imx51.h" ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++static u32 system_rev; ++u32 mx51_io_base_addr; ++volatile u32 *esdhc_base_pointer; ++ ++u32 get_board_rev(void) ++{ ++ return system_rev; ++} ++ ++static inline void setup_soc_rev(void) ++{ ++ int reg; ++ reg = __REG(ROM_SI_REV); ++ switch (reg) { ++ case 0x02: ++ system_rev = 0x51000 | CHIP_REV_1_1; ++ break; ++ case 0x10: ++ system_rev = 0x51000 | CHIP_REV_2_0; ++ break; ++ default: ++ system_rev = 0x51000 | CHIP_REV_1_0; ++ } ++} ++ ++static inline void set_board_rev(int rev) ++{ ++ system_rev |= (rev & 0xF) << 8; ++} ++ ++inline int is_soc_rev(int rev) ++{ ++ return (system_rev & 0xFF) - rev; ++} ++ ++int dram_init(void) ++{ ++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1; ++ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; ++ return 0; ++} ++ ++static void setup_uart(void) ++{ ++ unsigned int pad = PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | ++ PAD_CTL_PUE_PULL | PAD_CTL_DRV_HIGH; ++ mxc_request_iomux(MX51_PIN_UART1_RXD, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_UART1_RXD, pad | PAD_CTL_SRE_FAST); ++ mxc_request_iomux(MX51_PIN_UART1_TXD, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_UART1_TXD, pad | PAD_CTL_SRE_FAST); ++ mxc_request_iomux(MX51_PIN_UART1_RTS, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_UART1_RTS, pad); ++ mxc_request_iomux(MX51_PIN_UART1_CTS, IOMUX_CONFIG_ALT0); ++ mxc_iomux_set_pad(MX51_PIN_UART1_CTS, pad); ++} ++ ++void setup_nfc(void) ++{ ++ /* Enable NFC IOMUX */ ++ mxc_request_iomux(MX51_PIN_NANDF_CS0, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS1, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS2, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS3, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS4, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS5, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS6, IOMUX_CONFIG_ALT0); ++ mxc_request_iomux(MX51_PIN_NANDF_CS7, IOMUX_CONFIG_ALT0); ++} ++ ++static void setup_expio(void) ++{ ++ u32 reg; ++ /* CS5 setup */ ++ mxc_request_iomux(MX51_PIN_EIM_CS5, IOMUX_CONFIG_ALT0); ++ writel(0x00410089, WEIM_BASE_ADDR + 0x78 + CSGCR1); ++ writel(0x00000002, WEIM_BASE_ADDR + 0x78 + CSGCR2); ++ /* RWSC=50, RADVA=2, RADVN=6, OEA=0, OEN=0, RCSA=0, RCSN=0 */ ++ writel(0x32260000, WEIM_BASE_ADDR + 0x78 + CSRCR1); ++ /* APR = 0 */ ++ writel(0x00000000, WEIM_BASE_ADDR + 0x78 + CSRCR2); ++ /* WAL=0, WBED=1, WWSC=50, WADVA=2, WADVN=6, WEA=0, WEN=0, ++ * WCSA=0, WCSN=0 ++ */ ++ writel(0x72080F00, WEIM_BASE_ADDR + 0x78 + CSWCR1); ++ if ((readw(CS5_BASE_ADDR + PBC_ID_AAAA) == 0xAAAA) && ++ (readw(CS5_BASE_ADDR + PBC_ID_5555) == 0x5555)) { ++ if (is_soc_rev(CHIP_REV_2_0) < 0) { ++ reg = readl(CCM_BASE_ADDR + CLKCTL_CBCDR); ++ reg = (reg & (~0x70000)) | 0x30000; ++ writel(reg, CCM_BASE_ADDR + CLKCTL_CBCDR); ++ /* make sure divider effective */ ++ while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0) ++ ; ++ writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR); ++ } ++ mx51_io_base_addr = CS5_BASE_ADDR; ++ } else { ++ /* CS1 */ ++ writel(0x00410089, WEIM_BASE_ADDR + 0x18 + CSGCR1); ++ writel(0x00000002, WEIM_BASE_ADDR + 0x18 + CSGCR2); ++ /* RWSC=50, RADVA=2, RADVN=6, OEA=0, OEN=0, RCSA=0, RCSN=0 */ ++ writel(0x32260000, WEIM_BASE_ADDR + 0x18 + CSRCR1); ++ /* APR=0 */ ++ writel(0x00000000, WEIM_BASE_ADDR + 0x18 + CSRCR2); ++ /* WAL=0, WBED=1, WWSC=50, WADVA=2, WADVN=6, WEA=0, ++ * WEN=0, WCSA=0, WCSN=0 ++ */ ++ writel(0x72080F00, WEIM_BASE_ADDR + 0x18 + CSWCR1); ++ mx51_io_base_addr = CS1_BASE_ADDR; ++ } ++ ++ /* Reset interrupt status reg */ ++ writew(0x1F, mx51_io_base_addr + PBC_INT_REST); ++ writew(0x00, mx51_io_base_addr + PBC_INT_REST); ++ writew(0xFFFF, mx51_io_base_addr + PBC_INT_MASK); ++ ++ /* Reset the XUART and Ethernet controllers */ ++ reg = readw(mx51_io_base_addr + PBC_SW_RESET); ++ reg |= 0x9; ++ writew(reg, mx51_io_base_addr + PBC_SW_RESET); ++ reg &= ~0x9; ++ writew(reg, mx51_io_base_addr + PBC_SW_RESET); ++} ++ ++int board_init(void) ++{ ++ int pad; ++ setup_soc_rev(); ++ ++ gd->bd->bi_arch_number = MACH_TYPE_MX51_3DS; /* board id for linux */ ++ /* address of boot parameters */ ++ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; ++ ++ setup_uart(); ++ setup_nfc(); ++ setup_expio(); ++ return 0; ++} ++ ++#ifdef BOARD_LATE_INIT ++int board_late_init(void) ++{ ++ return 0; ++} ++#endif ++ ++int checkboard(void) ++{ ++ printf("Board: MX51 3STACK ["); ++ switch (__REG(SRC_BASE_ADDR + 0x8)) { ++ case 0x0001: ++ printf("POR"); ++ break; ++ case 0x0009: ++ printf("RST"); ++ break; ++ case 0x0010: ++ case 0x0011: ++ printf("WDOG"); ++ break; ++ default: ++ printf("unknown"); ++ } ++ printf("]\n"); ++ return 0; ++} ++ ++#ifdef CONFIG_NET_MULTI ++int board_eth_init(bd_t *bis) ++{ ++ int rc = -ENODEV; ++#if defined(CONFIG_DRIVER_SMC911X) ++ rc = smc911x_initialize(bis); ++#endif ++ return rc; ++} ++#endif ++ ++#ifdef CONFIG_FSL_MMC ++ ++int sdhc_init(void) ++{ ++ u32 interface_esdhc = 0; ++ u32 pad_val = 0; ++ s32 status = 0; ++ ++ interface_esdhc = (readl(SRC_BASE_ADDR + 0x4) & (0x00180000)) >> 19; ++ ++ switch (interface_esdhc) { ++ case 0: ++ ++ esdhc_base_pointer = (volatile u32 *)MMC_SDHC1_BASE_ADDR; ++ ++ mxc_request_iomux(MX51_PIN_SD1_CMD, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ mxc_request_iomux(MX51_PIN_SD1_CLK, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ ++ mxc_request_iomux(MX51_PIN_SD1_DATA0, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ mxc_request_iomux(MX51_PIN_SD1_DATA1, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ mxc_request_iomux(MX51_PIN_SD1_DATA2, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ mxc_request_iomux(MX51_PIN_SD1_DATA3, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ mxc_iomux_set_pad(MX51_PIN_SD1_CMD, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ mxc_iomux_set_pad(MX51_PIN_SD1_CLK, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_NONE | PAD_CTL_47K_PU | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ mxc_iomux_set_pad(MX51_PIN_SD1_DATA0, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ mxc_iomux_set_pad(MX51_PIN_SD1_DATA1, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ mxc_iomux_set_pad(MX51_PIN_SD1_DATA2, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ mxc_iomux_set_pad(MX51_PIN_SD1_DATA3, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PD | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ break; ++ case 1: ++ status = 1; ++ break; ++ case 2: ++ status = 1; ++ break; ++ case 3: ++ status = 1; ++ break; ++ default: ++ status = 1; ++ break; ++ } ++ ++ return status = 1; ++} ++ ++#endif +diff --git a/board/freescale/imx51/lowlevel_init.S b/board/freescale/imx51/lowlevel_init.S +new file mode 100644 +index 0000000..4fff3e5 +--- /dev/null ++++ b/board/freescale/imx51/lowlevel_init.S +@@ -0,0 +1,289 @@ ++/* ++ * Copyright (C) 2007, Guennadi Liakhovetski ++ * ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include "board-imx51.h" ++ ++/* ++ * return soc version ++ * 0x10: TO1 ++ * 0x20: TO2 ++ * 0x30: TO3 ++ */ ++.macro check_soc_version ret, tmp ++.endm ++ ++/* ++ * L2CC Cache setup/invalidation/disable ++ */ ++.macro init_l2cc ++ /* reconfigure L2 cache aux control reg */ ++ ldr r0, =0x03C000C4 ++ mcr p15, 1, r0, c9, c0, 2 ++.endm /* init_l2cc */ ++ ++/* AIPS setup - Only setup MPROTx registers. ++ * The PACR default values are good.*/ ++.macro init_aips ++ /* ++ * Set all MPROTx to be non-bufferable, trusted for R/W, ++ * not forced to user-mode. ++ */ ++ ldr r0, =AIPS1_BASE_ADDR ++ ldr r1, =0x77777777 ++ str r1, [r0, #0x0] ++ str r1, [r0, #0x4] ++ ldr r0, =AIPS2_BASE_ADDR ++ str r1, [r0, #0x0] ++ str r1, [r0, #0x4] ++ /* ++ * Clear the on and off peripheral modules Supervisor Protect bit ++ * for SDMA to access them. Did not change the AIPS control registers ++ * (offset 0x20) access type ++ */ ++.endm /* init_aips */ ++ ++/* MAX (Multi-Layer AHB Crossbar Switch) setup */ ++.macro init_max ++.endm /* init_max */ ++ ++/* M4IF setup */ ++.macro init_m4if ++ /* VPU and IPU given higher priority (0x4) ++ * IPU accesses with ID=0x1 given highest priority (=0xA) ++ */ ++ ldr r0, =M4IF_BASE_ADDR ++ ++ ldr r1, =0x00000203 ++ str r1, [r0, #0x40] ++ ++ ldr r1, =0x0 ++ str r1, [r0, #0x44] ++ ++ ldr r1, =0x00120125 ++ str r1, [r0, #0x9C] ++ ++ ldr r1, =0x001901A3 ++ str r1, [r0, #0x48] ++ ++/* ++ ldr r1, =0x00000a01 ++ str r1, [r0, #0x48] ++ ldr r1, =0x00000404 ++ str r1, [r0, #0x40] ++*/ ++.endm /* init_m4if */ ++ ++/* To support 133MHz DDR */ ++.macro init_drive_strength ++.endm /* init_drive_strength */ ++ ++/* CPLD on CS5 setup */ ++.macro init_debug_board ++.endm /* init_debug_board */ ++ ++.macro setup_pll pll, freq ++ ldr r2, =\pll ++ ldr r1, =0x00001232 ++ str r1, [r2, #PLL_DP_CTL] /* Set DPLL ON (set UPEN bit): BRMO=1 */ ++ mov r1, #0x2 ++ str r1, [r2, #PLL_DP_CONFIG] /* Enable auto-restart AREN bit */ ++ ++ str r3, [r2, #PLL_DP_OP] ++ str r3, [r2, #PLL_DP_HFS_OP] ++ ++ str r4, [r2, #PLL_DP_MFD] ++ str r4, [r2, #PLL_DP_HFS_MFD] ++ ++ str r5, [r2, #PLL_DP_MFN] ++ str r5, [r2, #PLL_DP_HFS_MFN] ++ ++ ldr r1, =0x00001232 ++ str r1, [r2, #PLL_DP_CTL] ++1: ldr r1, [r2, #PLL_DP_CTL] ++ ands r1, r1, #0x1 ++ beq 1b ++.endm ++ ++.macro init_clock ++ ldr r0, =CCM_BASE_ADDR ++ mov r1, #0x00060000 ++ str r1, [r0, #CLKCTL_CCDR] ++ ++ /* Switch ARM to step clock */ ++ mov r1, #0x4 ++ str r1, [r0, #CLKCTL_CCSR] ++ ++ mov r3, #DP_OP_800 ++ mov r4, #DP_MFD_800 ++ mov r5, #DP_MFN_800 ++ setup_pll PLL1_BASE_ADDR ++ mov r3, #DP_OP_665 ++ mov r4, #DP_MFD_665 ++ mov r5, #DP_MFN_665 ++ setup_pll PLL3_BASE_ADDR ++ ++ /* Switch peripheral to PLL 3 */ ++ ldr r1, =0x0000D3C0 ++ str r1, [r0, #CLKCTL_CBCMR] ++ ldr r1, =0x033B9145 ++ str r1, [r0, #CLKCTL_CBCDR] ++ mov r3, #DP_OP_665 ++ mov r4, #DP_MFD_665 ++ mov r5, #DP_MFN_665 ++ setup_pll PLL2_BASE_ADDR ++ ++ /* Switch peripheral to PLL2 */ ++ ldr r1, =0x013B9145 ++ str r1, [r0, #CLKCTL_CBCDR] ++ ldr r1, =0x0000E3C0 ++ str r1, [r0, #CLKCTL_CBCMR] ++ ++ mov r3, #DP_OP_216 ++ mov r4, #DP_MFD_216 ++ mov r5, #DP_MFN_216 ++ setup_pll PLL3_BASE_ADDR ++ ++ /* Set the platform clock dividers */ ++ ldr r2, =ARM_BASE_ADDR ++ ldr r1, =0x00000725 ++ str r1, [r2, #0x14] ++ ++ /* Switch ARM back to PLL 1 */ ++ mov r1, #0 ++ str r1, [r0, #CLKCTL_CCSR] ++ str r1, [r0, #CLKCTL_CACRR] ++ ++ /* Use lp_apm (24MHz) source for perclk */ ++ mov r2, #0x48 ++ ldr r2, [r0] ++ cmp r2, #0x10 ++ ldrhs r1, =0x000020C2 ++ ldrlo r1, =0x0000E3C2 ++ str r1, [r0, #CLKCTL_CBCMR] ++ /* TO1.x emi = ahb, all perclk dividers are 1 since using 24MHz */ ++ /* TO2.x ddr from PLL1, all perclk dividers are 1 since using 24MHz */ ++ ldrhs r1, =0x59239100 ++ ldrlo r1, =0x013D9100 ++ strlo r1, [r0, #CLKCTL_CBCDR] ++ ++ /* use PLL2 for UART source, get 66.5MHz */ ++ ldr r1, =0xA5A2A020 ++ str r1, [r0, #CLKCTL_CSCMR1] ++ ldr r1, =0x00C30321 ++ str r1, [r0, #CLKCTL_CSCDR1] ++ ++ /* make sure divider effective */ ++1: ldr r1, [r0, #CLKCTL_CDHIPR] ++ cmp r1, #0 ++ bne 1b ++ ++ mov r1, #0x0 ++ str r1, [r0, #CLKCTL_CCDR] ++.endm ++ ++.macro setup_wdog ++ ldr r0, =WDOG1_BASE_ADDR ++ mov r1, #0x30 ++ strh r1, [r0] ++.endm ++ ++.section ".text.init", "x" ++ ++.globl lowlevel_init ++lowlevel_init: ++ /* Platform CHIP level init*/ ++ ldr r0, =GPIO1_BASE_ADDR ++ ldr r1, [r0, #0x0] ++ orr r1, r1, #(1 << 23) ++ str r1, [r0, #0x0] ++ ldr r1, [r0, #0x4] ++ orr r1, r1, #(1 << 23) ++ str r1, [r0, #0x4] ++ ++#ifdef TURN_OFF_IMPRECISE_ABORT ++ mrs r0, cpsr ++ bic r0, r0, #0x100 ++ msr cpsr, r0 ++#endif ++ ++ mrc 15, 0, r1, c1, c0, 0 ++ ++#ifndef BRANCH_PREDICTION_ENABLE ++ mrc 15, 0, r0, c1, c0, 1 ++ bic r0, r0, #7 ++ mcr 15, 0, r0, c1, c0, 1 ++#else ++ mrc 15, 0, r0, c1, c0, 1 ++ orr r0, r0, #7 ++ mcr 15, 0, r0, c1, c0, 1 ++ orr r1, r1, #(1<<11) ++#endif ++ ++#ifdef UNALIGNED_ACCESS_ENABLE ++ orr r1, r1, #(1<<22) ++#endif ++ ++#ifdef LOW_INT_LATENCY_ENABLE ++ orr r1, r1, #(1<<21) ++#endif ++ mcr 15, 0, r1, c1, c0, 0 ++ ++ mov r0, #0 ++#ifdef BRANCH_PREDICTION_ENABLE ++ mcr 15, 0, r0, c15, c2, 4 ++#endif ++ mcr 15, 0, r0, c7, c10, 4 /* Drain the write buffer */ ++ ++ init_l2cc ++ ++ init_aips ++ ++ setup_wdog ++ ++ init_max ++ ++ init_m4if ++ ++ init_drive_strength ++ ++ cmp pc, #PHYS_SDRAM_1 ++ blo init_clock_start ++ cmp pc, #(PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE) ++ blo init_clock_start ++ ++init_clock_start: ++ init_clock ++ init_debug_board ++ /*init_sdram*/ ++ ++ /* return from mxc_nand_load */ ++ /* r12 saved upper lr*/ ++ b mxc_nand_load ++ ++/* Board level setting value */ ++DDR_PERCHARGE_CMD: .word 0x04008008 ++DDR_REFRESH_CMD: .word 0x00008010 ++DDR_LMR1_W: .word 0x00338018 ++DDR_LMR_CMD: .word 0xB2220000 ++DDR_TIMING_W: .word 0xB02567A9 ++DDR_MISC_W: .word 0x000A0104 +diff --git a/board/freescale/imx51/u-boot.lds b/board/freescale/imx51/u-boot.lds +new file mode 100644 +index 0000000..15d50ab +--- /dev/null ++++ b/board/freescale/imx51/u-boot.lds +@@ -0,0 +1,73 @@ ++/* ++ * January 2004 - Changed to support H4 device ++ * Copyright (c) 2004 Texas Instruments ++ * ++ * (C) Copyright 2002 ++ * Gary Jennejohn, DENX Software Engineering, ++ * ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 : ++ { ++ /* WARNING - the following is hand-optimized to fit within */ ++ /* the sector layout of our flash chips! XXX FIXME XXX */ ++ board/freescale/imx51/flash_header.o (.text.flasheader) ++ cpu/arm_cortexa8/start.o ++ board/freescale/imx51/libimx51.a (.text) ++ lib_arm/libarm.a (.text) ++ net/libnet.a (.text) ++ drivers/mtd/libmtd.a (.text) ++ drivers/mmc/libmmc.a (.text) ++ ++ . = DEFINED(env_offset) ? env_offset : .; ++ common/env_embedded.o(.text) ++ ++ *(.text) ++ } ++ ++ . = 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 = .; ++} +diff --git a/include/configs/imx51.h b/include/configs/imx51.h +new file mode 100644 +index 0000000..4ab1acb +--- /dev/null ++++ b/include/configs/imx51.h +@@ -0,0 +1,221 @@ ++/* ++ * Copyright (C) 2007, Guennadi Liakhovetski ++ * ++ * (C) Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * Configuration settings for the MX51-3Stack Freescale board. ++ * ++ * 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 ++ ++#include ++ ++ /* High Level Configuration Options */ ++#define CONFIG_ARMV7 1 /* This is armv7 Cortex-A8 CPU core */ ++#define CONFIG_SYS_APCS_GNU ++#define CONFIG_L2_OFF ++ ++#define CONFIG_MXC 1 ++#define CONFIG_MX51 1 /* in a mx51 */ ++#define CONFIG_FLASH_HEADER 1 ++#define CONFIG_FLASH_HEADER_OFFSET 0x400 ++#define CONFIG_FLASH_HEADER_BARKER 0xB1 ++ ++#define CONFIG_SKIP_RELOCATE_UBOOT ++ ++#define CONFIG_MX51_HCLK_FREQ 24000000 /* RedBoot says 26MHz */ ++#define CONFIG_MX51_CLK32 32768 ++#define CONFIG_DISPLAY_CPUINFO ++#define CONFIG_DISPLAY_BOARDINFO ++ ++#define BOARD_LATE_INIT ++/* ++ * Disabled for now due to build problems under Debian and a significant ++ * increase in the final file size: 144260 vs. 109536 Bytes. ++ */ ++ ++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ ++#define CONFIG_REVISION_TAG 1 ++#define CONFIG_SETUP_MEMORY_TAGS 1 ++#define CONFIG_INITRD_TAG 1 ++ ++/* ++ * Size of malloc() pool ++ */ ++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 2 * 1024 * 1024) ++/* size in bytes reserved for initial data */ ++#define CONFIG_SYS_GBL_DATA_SIZE 128 ++ ++/* ++ * Hardware drivers ++ */ ++#define CONFIG_MX51_UART 1 ++#define CONFIG_MX51_UART1 1 ++ ++ ++/* #define CONFIG_CMD_SPI */ ++ ++/* ++#define CONFIG_FSL_MMC 1 ++#define CONFIG_DOS_PARTITION 1 ++#define CONFIG_CMD_FAT 1 ++*/ ++ ++/* allow to overwrite serial and ethaddr */ ++#define CONFIG_ENV_OVERWRITE ++#define CONFIG_CONS_INDEX 1 ++#define CONFIG_BAUDRATE 115200 ++#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200} ++ ++#define CONFIG_MMC_BASE 0x0 ++ ++/*********************************************************** ++ * Command definition ++ ***********************************************************/ ++ ++#include ++ ++#define CONFIG_CMD_PING ++#define CONFIG_CMD_DHCP ++/* Enable below configure when supporting nand */ ++/* #define CONFIG_CMD_NAND */ ++/* #define CONFIG_CMD_ENV */ ++ ++#undef CONFIG_CMD_IMLS ++ ++#define CONFIG_BOOTDELAY 3 ++ ++#define CONFIG_LOADADDR 0x90800000 /* loadaddr env var */ ++ ++#define CONFIG_EXTRA_ENV_SETTINGS \ ++ "netdev=eth0\0" \ ++ "ethprime=smc911x\0" \ ++ "uboot_addr=0xa0000000\0" \ ++ "uboot=u-boot.bin\0" \ ++ "kernel=uImage\0" \ ++ "nfsroot=/opt/eldk/arm\0" \ ++ "bootargs_base=setenv bootargs console=ttymxc0,115200\0"\ ++ "bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs "\ ++ "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0"\ ++ "bootcmd=run bootcmd_net\0" \ ++ "bootcmd_net=run bootargs_base bootargs_nfs; " \ ++ "tftpboot ${loadaddr} ${kernel}; bootm\0" \ ++ "prg_uboot=tftpboot ${loadaddr} ${uboot}; " \ ++ "protect off ${uboot_addr} 0xa003ffff; " \ ++ "erase ${uboot_addr} 0xa003ffff; " \ ++ "cp.b ${loadaddr} ${uboot_addr} ${filesize}; " \ ++ "setenv filesize; saveenv\0" ++ ++/*Support LAN9217*/ ++#define CONFIG_DRIVER_SMC911X 1 ++#define CONFIG_DRIVER_SMC911X_16_BIT 1 ++#define CONFIG_DRIVER_SMC911X_BASE_VARIABLE mx51_io_base_addr ++ ++/* ++ * The MX51 3stack board seems to have a hardware "peculiarity" confirmed under ++ * U-Boot, RedBoot and Linux: the ethernet Rx signal is reaching the CS8900A ++ * controller inverted. The controller is capable of detecting and correcting ++ * this, but it needs 4 network packets for that. Which means, at startup, you ++ * will not receive answers to the first 4 packest, unless there have been some ++ * broadcasts on the network, or your board is on a hub. Reducing the ARP ++ * timeout from default 5 seconds to 200ms we speed up the initial TFTP ++ * transfer, should the user wish one, significantly. ++ */ ++#define CONFIG_ARP_TIMEOUT 200UL ++ ++/* ++ * Miscellaneous configurable options ++ */ ++#define CONFIG_SYS_LONGHELP /* undef to save memory */ ++#define CONFIG_SYS_PROMPT "=> " ++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ ++/* Print Buffer Size */ ++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) ++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ ++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ ++ ++#define CONFIG_SYS_MEMTEST_START 0 /* memtest works on */ ++#define CONFIG_SYS_MEMTEST_END 0x10000 ++ ++#undef CONFIG_SYS_CLKS_IN_HZ /* everything, incl board info, in Hz */ ++ ++#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR ++ ++#define CONFIG_SYS_HZ CONFIG_MX51_CLK32/* use 32kHz clock as source */ ++ ++#define CONFIG_CMDLINE_EDITING 1 ++ ++/*----------------------------------------------------------------------- ++ * Stack sizes ++ * ++ * The stack sizes are set up in start.S using the settings below ++ */ ++#define CONFIG_STACKSIZE (128 * 1024) /* regular stack */ ++ ++/*----------------------------------------------------------------------- ++ * Physical Memory Map ++ */ ++#define CONFIG_NR_DRAM_BANKS 1 ++#define PHYS_SDRAM_1 CSD0_BASE_ADDR ++/* TO1 boards */ ++/* #define PHYS_SDRAM_1_SIZE (128 * 1024 * 1024) */ ++#define PHYS_SDRAM_1_SIZE (512 * 1024 * 1024) ++ ++/*----------------------------------------------------------------------- ++ * FLASH and environment organization ++ */ ++#define CONFIG_SYS_NO_FLASH ++ ++/*----------------------------------------------------------------------- ++ * NAND FLASH driver setup ++ */ ++#define NAND_MAX_CHIPS 8 ++#define CONFIG_SYS_MAX_NAND_DEVICE 1 ++#define CONFIG_SYS_NAND_BASE 0x40000000 ++ ++/* Monitor at beginning of flash */ ++#if defined(CONFIG_FSL_MMC) ++ #define CONFIG_MMC 1 ++ #define CONFIG_CMD_MMC ++/* ++ #define CONFIG_FSL_ENV_IN_MMC ++*/ ++#elif defined(CONFIG_CMD_NAND) ++ #define CONFIG_FSL_ENV_IN_NAND ++#endif ++ ++#define CONFIG_ENV_SECT_SIZE (128 * 1024) ++#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE ++ ++#if defined(CONFIG_FSL_ENV_IN_NAND) ++ #define CONFIG_ENV_IS_IN_NAND 1 ++ #define CONFIG_ENV_OFFSET 0x100000 ++#elif defined(CONFIG_FSL_ENV_IN_MMC) ++ #define CONFIG_ENV_IS_IN_MMC 1 ++ #define CONFIG_ENV_OFFSET (1024 * 1024) ++#else ++ #define CONFIG_ENV_IS_NOWHERE 1 ++#endif ++/* ++ * JFFS2 partitions ++ */ ++#undef CONFIG_JFFS2_CMDLINE ++#define CONFIG_JFFS2_DEV "nand0" ++ ++#endif /* __CONFIG_H */ +-- +1.5.4.4 + --- uboot-imx-2009.01.orig/debian/patches/0004-ENGR00099697-Add-nand-driver-for-mx35.patch +++ uboot-imx-2009.01/debian/patches/0004-ENGR00099697-Add-nand-driver-for-mx35.patch @@ -0,0 +1,1528 @@ +From 7508ceeeabba926ffbe7640e3db583eb2664e5da Mon Sep 17 00:00:00 2001 +From: Fred Fan +Date: Mon, 23 Feb 2009 13:40:12 +0800 +Subject: [PATCH] ENGR00099697 Add nand driver for mx35 + +Add nand driver for mx35 + +Signed-off-by:Jason Liu +--- + board/freescale/mx35_3stack/config.mk | 2 +- + cpu/arm1136/mx35/interrupts.c | 5 + + drivers/mtd/nand/Makefile | 1 + + drivers/mtd/nand/mxc_nand.c | 1148 +++++++++++++++++++++++++++++++++ + drivers/mtd/nand/nand_base.c | 4 +- + drivers/mtd/nand/nand_ids.c | 17 +- + include/asm-arm/arch-mx35/mx35.h | 8 + + include/asm-arm/arch-mx35/mxc_nand.h | 198 ++++++ + include/configs/mx35_3stack.h | 11 +- + 9 files changed, 1380 insertions(+), 14 deletions(-) + +diff --git a/board/freescale/mx35_3stack/config.mk b/board/freescale/mx35_3stack/config.mk +index d34dc02..70b4271 100644 +--- a/board/freescale/mx35_3stack/config.mk ++++ b/board/freescale/mx35_3stack/config.mk +@@ -1 +1 @@ +-TEXT_BASE = 0x87f00000 ++TEXT_BASE = 0x87800000 +diff --git a/cpu/arm1136/mx35/interrupts.c b/cpu/arm1136/mx35/interrupts.c +index 28284b1..40b9d4c 100644 +--- a/cpu/arm1136/mx35/interrupts.c ++++ b/cpu/arm1136/mx35/interrupts.c +@@ -54,6 +54,11 @@ int interrupt_init(void) + return 0; + } + ++void reset_timer(void) ++{ ++ reset_timer_masked(); ++} ++ + void reset_timer_masked(void) + { + GPTCR = 0; +diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile +index 8537523..4dc4483 100644 +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -39,6 +39,7 @@ COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o + COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o + COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o + COBJS-$(CONFIG_MX31_NAND) += mx31_nand.o ++COBJS-y += mxc_nand.o + endif + + COBJS := $(COBJS-y) +diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c +new file mode 100644 +index 0000000..d458d0a +--- /dev/null ++++ b/drivers/mtd/nand/mxc_nand.c +@@ -0,0 +1,1148 @@ ++/* ++ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct nand_info { ++ int status_req; ++ int large_page; ++ int auto_mode; ++ u16 col_addr; ++ u8 num_of_intlv; ++ int page_mask; ++ int hw_ecc; ++ u8 *data_buf; ++ u8 *oob_buf; ++}; ++ ++/* ++ * Define delays in microsec for NAND device operations ++ */ ++#define TROP_US_DELAY 2000 ++ ++/* ++ * OOB placement block for use with hardware ecc generation ++ */ ++static struct nand_oobinfo nand_hw_eccoob_512 = { ++ .useecc = MTD_NANDECC_AUTOPL_USR, ++ .eccbytes = 9, ++ .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, ++ .oobfree = {{0, 4} } ++}; ++ ++static struct nand_oobinfo nand_hw_eccoob_2k = { ++ .useecc = MTD_NANDECC_AUTOPL_USR, ++ .eccbytes = 9, ++ .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, ++ .oobfree = {{2, 4} } ++}; ++ ++static struct nand_oobinfo nand_hw_eccoob_4k = { ++ .useecc = MTD_NANDECC_AUTOPL_USR, ++ .eccbytes = 9, ++ .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15}, ++ .oobfree = {{2, 4} } ++}; ++ ++/*! ++ * @defgroup NAND_MTD NAND Flash MTD Driver for MXC processors ++ */ ++ ++/*! ++ * @file mxc_nd2.c ++ * ++ * @brief This file contains the hardware specific layer for NAND Flash on ++ * MXC processor ++ * ++ * @ingroup NAND_MTD ++ */ ++ ++/*! ++ * Half word access.Added for U-boot. ++ */ ++static void *nfc_memcpy(void *dest, const void *src, size_t n) ++{ ++ u16 *dst_16 = (u16 *) dest; ++ const u16 *src_16 = (u16 *) src; ++ ++ while (n > 0) { ++ *dst_16++ = *src_16++; ++ n -= 2; ++ } ++ ++ return dest; ++} ++ ++/* ++ * Functions to transfer data to/from spare erea. ++ */ ++static void ++copy_spare(struct mtd_info *mtd, void *pbuf, void *pspare, int len, int bfrom) ++{ ++ u16 i, j; ++ u16 m = mtd->oobsize; ++ u16 n = mtd->oobblock >> 9; ++ u8 *d = (u8 *) pbuf; ++ u8 *s = (u8 *) pspare; ++ u16 t = SPARE_LEN; ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ m /= info->num_of_intlv; ++ n /= info->num_of_intlv; ++ ++ j = (m / n >> 1) << 1; ++ ++ if (bfrom) { ++ for (i = 0; i < n - 1; i++) ++ nfc_memcpy(&d[i * j], &s[i * t], j); ++ ++ /* the last section */ ++ nfc_memcpy(&d[i * j], &s[i * t], len - i * j); ++ } else { ++ for (i = 0; i < n - 1; i++) ++ nfc_memcpy(&s[i * t], &d[i * j], j); ++ ++ /* the last section */ ++ nfc_memcpy(&s[i * t], &d[i * j], len - i * j); ++ } ++} ++ ++/*! ++ * This function polls the NFC to wait for the basic operation to complete by ++ * checking the INT bit of config2 register. ++ * ++ * @param maxRetries number of retry attempts (separated by 1 us) ++ * @param useirq True if IRQ should be used rather than polling ++ */ ++static void wait_op_done(int max_retries) ++{ ++ ++ while (max_retries-- > 0) { ++ if (raw_read(REG_NFC_OPS_STAT) & NFC_OPS_STAT) { ++ WRITE_NFC_IP_REG((raw_read(REG_NFC_OPS_STAT) & ++ ~NFC_OPS_STAT), ++ REG_NFC_OPS_STAT); ++ break; ++ } ++ udelay(1); ++ } ++ if (max_retries <= 0) ++ DEBUG(MTD_DEBUG_LEVEL0, "wait: INT not set\n"); ++} ++ ++static void send_cmd_atomic(struct mtd_info *mtd, u16 cmd) ++{ ++ /* fill command */ ++ raw_write(cmd, REG_NFC_FLASH_CMD); ++ ++ /* clear status */ ++ ACK_OPS; ++ ++ /* send out command */ ++ raw_write(NFC_CMD, REG_NFC_OPS); ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++} ++ ++static void send_cmd_auto(struct mtd_info *mtd, u16 cmd) ++{ ++#ifdef CONFIG_MXC_NFC_SP_AUTO ++ switch (cmd) { ++ case NAND_CMD_READ0: ++ case NAND_CMD_READOOB: ++ raw_write(NAND_CMD_READ0, REG_NFC_FLASH_CMD); ++ break; ++ case NAND_CMD_SEQIN: ++ case NAND_CMD_ERASE1: ++ raw_write(cmd, REG_NFC_FLASH_CMD); ++ break; ++ case NAND_CMD_PAGEPROG: ++ case NAND_CMD_ERASE2: ++ case NAND_CMD_READSTART: ++ raw_write(raw_read(REG_NFC_FLASH_CMD) | cmd << NFC_CMD_1_SHIFT, ++ REG_NFC_FLASH_CMD); ++ send_cmd_interleave(mtd, cmd); ++ break; ++ case NAND_CMD_READID: ++ send_atomic_cmd(cmd); ++ send_addr(0); ++ break; ++ case NAND_CMD_RESET: ++ send_cmd_interleave(mtd, cmd); ++ case NAND_CMD_STATUS: ++ break; ++ default: ++ break; ++ } ++#endif ++} ++ ++/*! ++ * This function handle the interleave related work ++ * @param mtd mtd info ++ * @param cmd command ++ */ ++static void send_cmd_interleave(struct mtd_info *mtd, u16 cmd) ++{ ++#ifdef CONFIG_MXC_NFC_SP_AUTO ++ u32 i; ++ u32 j = num_of_intlv; ++ struct nand_chip *this = mtd->priv; ++ u32 addr_low = raw_read(NFC_FLASH_ADDR0); ++ u32 addr_high = raw_read(NFC_FLASH_ADDR8); ++ u32 page_addr = addr_low >> 16 | addr_high << 16; ++ u8 *dbuf = mtd->info.data_buf; ++ u8 *obuf = mtd->info.oob_buf; ++ u32 dlen = mtd->oobblock / j; ++ u32 olen = mtd->oobsize / j; ++ ++ /* adjust the addr value ++ * since ADD_OP mode is 01 ++ */ ++ if (j > 1) ++ page_addr *= j; ++ else ++ page_addr *= this->numchips; ++ ++ for (i = 0; i < j; i++) { ++ if (cmd == NAND_CMD_PAGEPROG) { ++ ++ /* reset addr cycle */ ++ if (j > 1) ++ mxc_nand_addr_cycle(mtd, 0, page_addr++); ++ ++ /* data transfer */ ++ nfc_memcpy(MAIN_AREA0, dbuf, dlen); ++ copy_spare(mtd, obuf, SPARE_AREA0, olen, 0); ++ ++ /* update the value */ ++ dbuf += dlen; ++ obuf += olen; ++ ++ NFC_SET_RBA(0); ++ raw_write(0, REG_NFC_OPS_STAT); ++ raw_write(NFC_AUTO_PROG, REG_NFC_OPS); ++ ++ /* wait auto_prog_done bit set */ ++ if (i < j - 1) { ++ while (! ++ (raw_read(REG_NFC_OPS_STAT) & 1 << 30)) ++ ; ++ } else { ++ wait_op_done(TROP_US_DELAY); ++ } ++ } else if (cmd == NAND_CMD_READSTART) { ++ /* reset addr cycle */ ++ if (j > 1) ++ mxc_nand_addr_cycle(mtd, 0, page_addr++); ++ ++ NFC_SET_RBA(0); ++ raw_write(0, REG_NFC_OPS_STAT); ++ raw_write(NFC_AUTO_READ, REG_NFC_OPS); ++ wait_op_done(TROP_US_DELAY); ++ ++ /* check ecc error */ ++ mxc_nand_ecc_status(mtd); ++ ++ /* data transfer */ ++ nfc_memcpy(dbuf, MAIN_AREA0, dlen); ++ copy_spare(mtd, obuf, SPARE_AREA0, olen, 1); ++ ++ /* update the value */ ++ dbuf += dlen; ++ obuf += olen; ++ } else if (cmd == NAND_CMD_ERASE2) { ++ if (!i) { ++ page_addr = addr_low; ++ page_addr *= (j > 1 ? j : this->numchips); ++ } ++ mxc_nand_addr_cycle(mtd, -1, page_addr++); ++ raw_write(NFC_AUTO_ERASE, REG_NFC_OPS); ++ wait_op_done(TROP_US_DELAY); ++ } else if (cmd == NAND_CMD_RESET) { ++ NFC_SET_NFC_ACTIVE_CS(i); ++ send_atomic_cmd(cmd); ++ } ++ } ++#endif ++} ++ ++/*! ++ * This function issues the specified command to the NAND device and ++ * waits for completion. ++ * ++ * @param cmd command for NAND Flash ++ * @param useirq True if IRQ should be used rather than polling ++ */ ++static void send_cmd(struct mtd_info *mtd, u16 cmd) ++{ ++ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ if (info->auto_mode) ++ send_cmd_auto(mtd, cmd); ++ else ++ send_cmd_atomic(mtd, cmd); ++ ++ DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(0x%x, %d)\n", cmd); ++} ++ ++/*! ++ * This function sends an address (or partial address) to the ++ * NAND device. The address is used to select the source/destination for ++ * a NAND command. ++ * ++ * @param addr address to be written to NFC. ++ * @param useirq True if IRQ should be used rather than polling ++ */ ++static void send_addr(u16 addr) ++{ ++ DEBUG(MTD_DEBUG_LEVEL3, "send_addr(0x%x %d)\n", addr); ++ ++ /* fill address */ ++ raw_write((addr << NFC_FLASH_ADDR_SHIFT), REG_NFC_FLASH_ADDR); ++ ++ /* clear status */ ++ ACK_OPS; ++ ++ /* send out address */ ++ raw_write(NFC_ADDR, REG_NFC_OPS); ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++} ++ ++/*! ++ * This function requests the NFC to initate the transfer ++ * of data currently in the NFC RAM buffer to the NAND device. ++ * ++ * @param buf_id Specify Internal RAM Buffer number ++ */ ++static void send_prog_page(struct mtd_info *mtd, u8 buf_id) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ if (!info->auto_mode) { ++ /* set ram buffer id */ ++ NFC_SET_RBA(buf_id); ++ ++ /* clear status */ ++ ACK_OPS; ++ ++ /* transfer data from NFC ram to nand */ ++ raw_write(NFC_INPUT, REG_NFC_OPS); ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++ ++ DEBUG(MTD_DEBUG_LEVEL3, "%s\n", __func__); ++ } ++} ++ ++/*! ++ * This function requests the NFC to initated the transfer ++ * of data from the NAND device into in the NFC ram buffer. ++ * ++ * @param buf_id Specify Internal RAM Buffer number ++ */ ++static void send_read_page(struct mtd_info *mtd, u8 buf_id) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ if (!info->auto_mode) { ++ ++ /* set ram buffer id */ ++ NFC_SET_RBA(buf_id); ++ ++ /* clear status */ ++ ACK_OPS; ++ ++ /* transfer data from nand to NFC ram */ ++ raw_write(NFC_OUTPUT, REG_NFC_OPS); ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++ ++ DEBUG(MTD_DEBUG_LEVEL3, "%s(%d)\n", __func__, buf_id); ++ ++ } ++ ++} ++ ++/*! ++ * This function requests the NFC to perform a read of the ++ * NAND device ID. ++ */ ++static void send_read_id(void) ++{ ++ /* Set RBA bits for BUFFER0 */ ++ NFC_SET_RBA(0); ++ ++ /* clear status */ ++ ACK_OPS; ++ ++ /* Read ID into main buffer */ ++ raw_write(NFC_ID, REG_NFC_OPS); ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++ ++} ++ ++static u16 mxc_do_status_auto(struct mtd_info *mtd) ++{ ++ u16 status = 0; ++#ifdef CONFIG_MXC_NFC_SP_AUTO ++ int i = 0; ++ u32 mask = 0xFF << 16; ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ for (; i < info->num_of_intlv; i++) { ++ ++ /* set ative cs */ ++ NFC_SET_NFC_ACTIVE_CS(i); ++ ++ raw_write(NFC_AUTO_STATE, REG_NFC_OPS); ++ ++ /* FIXME, NFC Auto erase may have ++ * problem, have to pollingit until ++ * the nand get idle, otherwise ++ * it may get error ++ */ ++ do { ++ status = (raw_read(NFC_CONFIG1) & mask) >> 16; ++ } while ((status & NAND_STATUS_READY) == 0); ++ ++ if (status & NAND_STATUS_FAIL) ++ break; ++ } ++#endif ++ return status; ++} ++ ++static u16 mxc_do_status_atomic(struct mtd_info *mtd) ++{ ++ volatile u16 *mainBuf = MAIN_AREA1; ++ u8 val = 1; ++ u16 ret; ++ ++ /* Set ram buffer id */ ++ NFC_SET_RBA(val); ++ ++ /* clear status */ ++ ACK_OPS; ++ ++ /* Read status into main buffer */ ++ raw_write(NFC_STATUS, REG_NFC_OPS); ++ ++ /* Wait for operation to complete */ ++ wait_op_done(TROP_US_DELAY); ++ ++ /* Status is placed in first word of main buffer */ ++ /* get status, then recovery area 1 data */ ++ ret = *mainBuf; ++ ++ return ret; ++} ++ ++/*! ++ * This function requests the NFC to perform a read of the ++ * NAND device status and returns the current status. ++ * ++ * @return device status ++ */ ++static u16 mxc_nand_get_status(struct mtd_info *mtd) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ u16 status; ++ ++ if (info->auto_mode) ++ status = mxc_do_status_auto(mtd); ++ else ++ status = mxc_do_status_atomic(mtd); ++ ++ return status; ++ ++} ++ ++static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) ++{ ++ raw_write((raw_read(REG_NFC_ECC_EN) | NFC_ECC_EN), REG_NFC_ECC_EN); ++ return; ++} ++ ++/* ++ * Function to record the ECC corrected/uncorrected errors resulted ++ * after a page read. This NFC detects and corrects upto to 4 symbols ++ * of 9-bits each. ++ */ ++static int mxc_nand_ecc_status(struct mtd_info *mtd) ++{ ++ u32 ecc_stat, err; ++ int no_subpages = 1; ++ int ret = 0; ++ u8 ecc_bit_mask, err_limit; ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ ecc_bit_mask = (IS_4BIT_ECC ? 0x7 : 0xf); ++ err_limit = (IS_4BIT_ECC ? 0x4 : 0x8); ++ ++ no_subpages = mtd->oobblock >> 9; ++ ++ no_subpages /= info->num_of_intlv; ++ ++ ecc_stat = GET_NFC_ECC_STATUS(); ++ do { ++ err = ecc_stat & ecc_bit_mask; ++ if (err > err_limit) { ++ printk(KERN_WARNING "UnCorrectable RS-ECC Error\n"); ++ return -1; ++ } else { ++ ret += err; ++ } ++ ecc_stat >>= 4; ++ } while (--no_subpages); ++ ++ DEBUG(MTD_DEBUG_LEVEL3, "%d Symbol Correctable RS-ECC Error\n", ret); ++ ++ return ret; ++} ++ ++/* ++ * Function to correct the detected errors. This NFC corrects all the errors ++ * detected. So this function just return 0. ++ */ ++static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, ++ u_char *read_ecc, u_char *calc_ecc) ++{ ++ return 0; ++} ++ ++/* ++ * Function to calculate the ECC for the data to be stored in the Nand device. ++ * This NFC has a hardware RS(511,503) ECC engine together with the RS ECC ++ * CONTROL blocks are responsible for detection and correction of up to ++ * 8 symbols of 9 bits each in 528 byte page. ++ * So this function is just return 0. ++ */ ++ ++static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, ++ u_char *ecc_code) ++{ ++ return 0; ++} ++ ++/*! ++ * This function id is used to read the data buffer from the NAND Flash. To ++ * read the data from NAND Flash first the data output cycle is initiated by ++ * the NFC, which copies the data to RAMbuffer. This data of length \b len is ++ * then copied to buffer \b buf. ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * @param buf data to be read from NAND Flash ++ * @param len number of bytes to be read ++ */ ++static void mxc_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ u16 col = info->col_addr; ++ u8 *data_buf = info->data_buf; ++ u8 *oob_buf = info->oob_buf; ++ ++ if (mtd->oobblock) { ++ ++ int j = mtd->oobblock - col; ++ int n = mtd->oobsize + j; ++ ++ n = min(n, len); ++ ++ if (j > 0) { ++ if (n > j) { ++ memcpy(buf, &data_buf[col], j); ++ memcpy(buf + j, &oob_buf[0], n - j); ++ } else { ++ memcpy(buf, &data_buf[col], n); ++ } ++ } else { ++ col -= mtd->oobblock; ++ memcpy(buf, &oob_buf[col], len); ++ } ++ ++ /* update */ ++ info->col_addr += n; ++ ++ } else { ++ /* At flash identify phase, ++ * mtd->oobblock has not been ++ * set correctly, it should ++ * be zero.And len will less 2 ++ */ ++ memcpy(buf, &data_buf[col], len); ++ ++ /* update */ ++ info->col_addr += len; ++ } ++ ++} ++ ++/*! ++ * This function reads byte from the NAND Flash ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * ++ * @return data read from the NAND Flash ++ */ ++static uint8_t mxc_nand_read_byte(struct mtd_info *mtd) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ uint8_t ret; ++ ++ /* Check for status request */ ++ if (info->status_req) ++ return mxc_nand_get_status(mtd) & 0xFF; ++ ++ mxc_nand_read_buf(mtd, &ret, 1); ++ ++ return ret; ++} ++ ++/*! ++ * This function reads word from the NAND Flash ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * ++ * @return data read from the NAND Flash ++ */ ++static u16 mxc_nand_read_word(struct mtd_info *mtd) ++{ ++ u16 ret; ++ ++ mxc_nand_read_buf(mtd, (uint8_t *) &ret, sizeof(u16)); ++ ++ return ret; ++} ++ ++/*! ++ * This function reads byte from the NAND Flash ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * ++ * @return data read from the NAND Flash ++ */ ++static u_char mxc_nand_read_byte16(struct mtd_info *mtd) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ /* Check for status request */ ++ if (info->status_req) ++ return mxc_nand_get_status(mtd) & 0xFF; ++ ++ return mxc_nand_read_word(mtd) & 0xFF; ++} ++ ++/*! ++ * This function writes data of length \b len from buffer \b buf to the NAND ++ * internal RAM buffer's MAIN area 0. ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * @param buf data to be written to NAND Flash ++ * @param len number of bytes to be written ++ */ ++static void mxc_nand_write_buf(struct mtd_info *mtd, ++ const u_char *buf, int len) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ u16 col = info->col_addr; ++ u8 *data_buf = info->data_buf; ++ u8 *oob_buf = info->oob_buf; ++ int j = mtd->oobblock - col; ++ int n = mtd->oobsize + j; ++ ++ n = min(n, len); ++ ++ if (j > 0) { ++ if (n > j) { ++ memcpy(&data_buf[col], buf, j); ++ memcpy(&oob_buf[0], buf + j, n - j); ++ } else { ++ memcpy(&data_buf[col], buf, n); ++ } ++ } else { ++ col -= mtd->oobblock; ++ memcpy(&oob_buf[col], buf, len); ++ } ++ ++ /* update */ ++ info->col_addr += n; ++} ++ ++/*! ++ * This function is used by the upper layer to verify the data in NAND Flash ++ * with the data in the \b buf. ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * @param buf data to be verified ++ * @param len length of the data to be verified ++ * ++ * @return -EFAULT if error else 0 ++ * ++ */ ++static int mxc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, ++ int len) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ u_char *s = info->data_buf; ++ ++ const u_char *p = buf; ++ ++ for (; len > 0; len--) { ++ if (*p++ != *s++) ++ return -1; ++ } ++ ++ return 0; ++} ++ ++/*! ++ * This function is used by upper layer for select and deselect of the NAND ++ * chip ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * @param chip val indicating select or deselect ++ */ ++static void mxc_nand_select_chip(struct mtd_info *mtd, int chip) ++{ ++ ++ switch (chip) { ++ case -1: ++ break; ++ ++ case 0 ... 7: ++ NFC_SET_NFC_ACTIVE_CS(chip); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static void mxc_do_addr_cycle_auto(struct mtd_info *mtd, int column, ++ int page_addr) ++{ ++#ifdef CONFIG_MXC_NFC_SP_AUTO ++ if (page_addr != -1 && column != -1) { ++ u32 mask = 0xFFFF; ++ /* the column address */ ++ raw_write(column & mask, NFC_FLASH_ADDR0); ++ raw_write((raw_read(NFC_FLASH_ADDR0) | ++ ((page_addr & mask) << 16)), NFC_FLASH_ADDR0); ++ /* the row address */ ++ raw_write(((raw_read(NFC_FLASH_ADDR8) & (mask << 16)) | ++ ((page_addr & (mask << 16)) >> 16)), ++ NFC_FLASH_ADDR8); ++ } else if (page_addr != -1) { ++ raw_write(page_addr, NFC_FLASH_ADDR0); ++ } ++ ++ DEBUG(MTD_DEBUG_LEVEL3, ++ "AutoMode:the ADDR REGS value is (0x%x, 0x%x)\n", ++ raw_read(NFC_FLASH_ADDR0), raw_read(NFC_FLASH_ADDR8)); ++#endif ++} ++ ++static void mxc_do_addr_cycle_atomic(struct mtd_info *mtd, int column, ++ int page_addr) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ u32 page_mask = info->page_mask; ++ ++ if (column != -1) { ++ send_addr(column & 0xFF); ++ if (IS_2K_PAGE_NAND) { ++ /* another col addr cycle for 2k page */ ++ send_addr((column >> 8) & 0xF); ++ } else if (IS_4K_PAGE_NAND) { ++ /* another col addr cycle for 4k page */ ++ send_addr((column >> 8) & 0x1F); ++ } ++ } ++ if (page_addr != -1) { ++ do { ++ send_addr(page_addr & 0xff); ++ page_mask >>= 8; ++ page_addr >>= 8; ++ } while (page_mask != 0); ++ } ++} ++ ++ ++/* ++ * Function to perform the address cycles. ++ */ ++static void mxc_nand_addr_cycle(struct mtd_info *mtd, int column, int page_addr) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ if (info->auto_mode) ++ mxc_do_addr_cycle_auto(mtd, column, page_addr); ++ else ++ mxc_do_addr_cycle_atomic(mtd, column, page_addr); ++} ++ ++/*! ++ * This function is used by the upper layer to write command to NAND Flash for ++ * different operations to be carried out on NAND Flash ++ * ++ * @param mtd MTD structure for the NAND Flash ++ * @param command command for NAND Flash ++ * @param column column offset for the page read ++ * @param page_addr page to be read from NAND Flash ++ */ ++static void mxc_nand_command(struct mtd_info *mtd, unsigned command, ++ int column, int page_addr) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ DEBUG(MTD_DEBUG_LEVEL3, ++ "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n", ++ command, column, page_addr); ++ /* ++ * Reset command state information ++ */ ++ info->status_req = 0; ++ ++ /* ++ * Command pre-processing step ++ */ ++ switch (command) { ++ case NAND_CMD_STATUS: ++ info->col_addr = 0; ++ info->status_req = 1; ++ break; ++ ++ case NAND_CMD_READ0: ++ info->col_addr = column; ++ break; ++ ++ case NAND_CMD_READOOB: ++ info->col_addr = column; ++ command = NAND_CMD_READ0; ++ break; ++ ++ case NAND_CMD_SEQIN: ++ if (column != 0) { ++ ++ /* FIXME: before send SEQIN command for ++ * partial write,We need read one page out. ++ * FSL NFC does not support partial write ++ * It alway send out 512+ecc+512+ecc ... ++ * for large page nand flash. But for small ++ * page nand flash, it did support SPARE ++ * ONLY operation. But to make driver ++ * simple. We take the same as large page,read ++ * whole page out and update. As for MLC nand ++ * NOP(num of operation) = 1. Partial written ++ * on one programed page is not allowed! We ++ * can't limit it on the driver, it need the ++ * upper layer applicaiton take care it ++ */ ++ ++ mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr); ++ } ++ ++ info->col_addr = column; ++ break; ++ ++ case NAND_CMD_PAGEPROG: ++ if (!info->auto_mode) { ++ nfc_memcpy(MAIN_AREA0, info->data_buf, mtd->oobblock); ++ copy_spare(mtd, info->oob_buf, SPARE_AREA0, ++ mtd->oobsize, 0); ++ } ++ ++ send_prog_page(mtd, 0); ++ break; ++ ++ case NAND_CMD_ERASE1: ++ case NAND_CMD_ERASE2: ++ break; ++ } ++ ++ /* ++ * Write out the command to the device. ++ */ ++ send_cmd(mtd, command); ++ ++ mxc_nand_addr_cycle(mtd, column, page_addr); ++ ++ /* ++ * Command post-processing step ++ */ ++ switch (command) { ++ ++ case NAND_CMD_READOOB: ++ case NAND_CMD_READ0: ++ if (info->large_page) ++ /* send read confirm command */ ++ send_cmd(mtd, NAND_CMD_READSTART); ++ ++ send_read_page(mtd, 0); ++ ++ if (!info->auto_mode) { ++ mxc_nand_ecc_status(mtd); ++ nfc_memcpy(info->data_buf, MAIN_AREA0, mtd->oobblock); ++ copy_spare(mtd, info->oob_buf, SPARE_AREA0, ++ mtd->oobsize, 1); ++ } ++ break; ++ ++ case NAND_CMD_READID: ++ send_read_id(); ++ info->col_addr = column; ++ nfc_memcpy(info->data_buf, MAIN_AREA0, 2048); ++ break; ++ } ++} ++ ++/* Define some generic bad / good block scan pattern which are used ++ * while scanning a device for factory marked good / bad blocks. */ ++static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; ++ ++static struct nand_bbt_descr smallpage_memorybased = { ++ .options = NAND_BBT_SCAN2NDPAGE, ++ .offs = 5, ++ .len = 1, ++ .pattern = scan_ff_pattern ++}; ++ ++static struct nand_bbt_descr largepage_memorybased = { ++ .options = 0, ++ .offs = 0, ++ .len = 2, ++ .pattern = scan_ff_pattern ++}; ++ ++/* Generic flash bbt decriptors ++*/ ++static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' }; ++static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' }; ++ ++static struct nand_bbt_descr bbt_main_descr = { ++ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE ++ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, ++ .offs = 0, ++ .len = 4, ++ .veroffs = 4, ++ .maxblocks = 4, ++ .pattern = bbt_pattern ++}; ++ ++static struct nand_bbt_descr bbt_mirror_descr = { ++ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE ++ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP, ++ .offs = 0, ++ .len = 4, ++ .veroffs = 4, ++ .maxblocks = 4, ++ .pattern = mirror_pattern ++}; ++ ++static int mxc_nand_scan_bbt(struct mtd_info *mtd) ++{ ++ struct nand_chip *this = mtd->priv; ++ struct nand_info *info = this->priv; ++ ++ info->page_mask = this->pagemask; ++ ++ if (IS_2K_PAGE_NAND) { ++ NFC_SET_NFMS(1 << NFMS_NF_PG_SZ); ++ this->autooob = &nand_hw_eccoob_2k; ++ info->large_page = 1; ++ } else if (IS_4K_PAGE_NAND) { ++ NFC_SET_NFMS(1 << NFMS_NF_PG_SZ); ++ this->autooob = &nand_hw_eccoob_4k; ++ info->large_page = 1; ++ } else { ++ this->autooob = &nand_hw_eccoob_512; ++ info->large_page = 0; ++ } ++ ++ /* reconfig for interleave mode */ ++ ++ if (this->numchips > 1 && info->auto_mode) { ++ info->num_of_intlv = this->numchips; ++ this->numchips = 1; ++ ++ /* FIXEME:need remove it ++ * when kernel support ++ * 4G larger space ++ */ ++ mtd->size = this->chipsize; ++ mtd->erasesize *= info->num_of_intlv; ++ mtd->oobblock *= info->num_of_intlv; ++ mtd->oobsize *= info->num_of_intlv; ++ this->page_shift = ffs(mtd->oobblock) - 1; ++ this->bbt_erase_shift = ++ this->phys_erase_shift = ffs(mtd->erasesize) - 1; ++ this->chip_shift = ffs(this->chipsize) - 1; ++ /*this->oob_poi = this->buffers->databuf + mtd->oobblock;*/ ++ } ++ ++ /* propagate ecc.layout to mtd_info */ ++ memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); ++ ++ /* jffs2 not write oob */ ++ /*mtd->flags &= ~MTD_OOB_WRITEABLE;*/ ++ ++ /* use flash based bbt */ ++ this->bbt_td = &bbt_main_descr; ++ this->bbt_md = &bbt_mirror_descr; ++ ++ /* update flash based bbt */ ++ this->options |= NAND_USE_FLASH_BBT; ++ ++ if (!this->badblock_pattern) { ++ this->badblock_pattern = (mtd->oobblock > 512) ? ++ &largepage_memorybased : &smallpage_memorybased; ++ } ++ ++ /* Build bad block table */ ++ return nand_scan_bbt(mtd, this->badblock_pattern); ++} ++ ++static void mxc_nfc_init(void) ++{ ++ /* Disable interrupt */ ++ raw_write((raw_read(REG_NFC_INTRRUPT) | NFC_INT_MSK), REG_NFC_INTRRUPT); ++ ++ /* disable spare enable */ ++ raw_write(raw_read(REG_NFC_SP_EN) & ~NFC_SP_EN, REG_NFC_SP_EN); ++ ++ /* Unlock the internal RAM Buffer */ ++ raw_write(NFC_SET_BLS(NFC_BLS_UNLCOKED), REG_NFC_BLS); ++ ++ /* Blocks to be unlocked */ ++ UNLOCK_ADDR(0x0, 0xFFFF); ++ ++ /* Unlock Block Command for given address range */ ++ raw_write(NFC_SET_WPC(NFC_WPC_UNLOCK), REG_NFC_WPC); ++} ++ ++static int mxc_alloc_buf(struct nand_info *info) ++{ ++ int err = 0; ++ ++ info->data_buf = kmalloc(NAND_MAX_PAGESIZE, GFP_KERNEL); ++ if (!info->data_buf) { ++ printk(KERN_ERR "%s: failed to allocate data_buf\n", __func__); ++ err = -ENOMEM; ++ return err; ++ } ++ memset(info->data_buf, 0, NAND_MAX_PAGESIZE); ++ ++ info->oob_buf = kmalloc(NAND_MAX_OOBSIZE, GFP_KERNEL); ++ if (!info->oob_buf) { ++ printk(KERN_ERR "%s: failed to allocate oob_buf\n", __func__); ++ err = -ENOMEM; ++ return err; ++ } ++ memset(info->oob_buf, 0, NAND_MAX_OOBSIZE); ++ ++ return err; ++} ++ ++static void mxc_free_buf(struct nand_info *info) ++{ ++ kfree(info->data_buf); ++ kfree(info->oob_buf); ++} ++ ++/*! ++ * This function is called during the driver binding process. ++ * ++ * @param pdev the device structure used to store device specific ++ * information that is used by the suspend, resume and ++ * remove functions ++ * ++ * @return The function always returns 0. ++ */ ++int board_nand_init(struct nand_chip *nand) ++{ ++ struct nand_info *info; ++ struct nand_chip *this = nand; ++ int err; ++ ++ info = kmalloc(sizeof(struct nand_info), GFP_KERNEL); ++ if (!info) { ++ printk(KERN_ERR "%s: failed to allocate nand_info\n", ++ __func__); ++ err = -ENOMEM; ++ return err; ++ } ++ memset(info, 0, sizeof(struct nand_info)); ++ ++ if (mxc_alloc_buf(info)) { ++ err = -ENOMEM; ++ return err; ++ } ++ ++ info->num_of_intlv = 1; ++ ++#ifdef CONFIG_MXC_NFC_SP_AUTO ++ info->auto_mode = 1; ++#endif ++ /* init the nfc */ ++ mxc_nfc_init(); ++ ++ this->priv = info; ++ this->cmdfunc = mxc_nand_command; ++ this->select_chip = mxc_nand_select_chip; ++ this->read_byte = mxc_nand_read_byte; ++ this->read_word = mxc_nand_read_word; ++ this->write_buf = mxc_nand_write_buf; ++ this->read_buf = mxc_nand_read_buf; ++ this->verify_buf = mxc_nand_verify_buf; ++ this->scan_bbt = mxc_nand_scan_bbt; ++ this->calculate_ecc = mxc_nand_calculate_ecc; ++ this->correct_data = mxc_nand_correct_data; ++ this->enable_hwecc = mxc_nand_enable_hwecc; ++ this->eccmode = NAND_ECC_HW3_512; ++ this->eccbytes = 9; ++ this->eccsize = 512; ++ ++ return 0; ++ ++} +diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c +index 94a65d4..3919ae1 100644 +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -848,8 +848,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this) + + while (1) { + if (get_timer(0) > timeo) { +- printf("Timeout!"); +- return 0x01; ++ /*printf("Timeout!");*/ ++ /*return 0x01;*/ + } + + if (this->dev_ready) { +diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c +index 077c305..f48cccb 100644 +--- a/drivers/mtd/nand/nand_ids.c ++++ b/drivers/mtd/nand/nand_ids.c +@@ -23,14 +23,13 @@ + * 512 512 Byte page size + */ + struct nand_flash_dev nand_flash_ids[] = { +- +-#ifdef CONFIG_MTD_NAND_MUSEUM_IDS +- {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, +- {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0}, +- {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0}, +- {"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0}, +- {"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0}, +- {"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0}, ++#if 0 ++ {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, ++ {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0}, ++ {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0}, ++ {"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0}, ++ {"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0}, ++ {"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0}, + {"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0}, + {"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0}, + {"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0}, +@@ -41,7 +40,6 @@ struct nand_flash_dev nand_flash_ids[] = { + {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16}, + {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16}, + #endif +- + {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0}, + {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0}, + {"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16}, +@@ -124,7 +122,6 @@ struct nand_flash_dev nand_flash_ids[] = { + NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY | + BBT_AUTO_REFRESH + }, +- + {NULL,} + }; + +diff --git a/include/asm-arm/arch-mx35/mx35.h b/include/asm-arm/arch-mx35/mx35.h +index a6af3c9..ba30597 100644 +--- a/include/asm-arm/arch-mx35/mx35.h ++++ b/include/asm-arm/arch-mx35/mx35.h +@@ -189,6 +189,14 @@ MXC_IPG_PERCLK, + MXC_UART_CLK, + }; + ++/*! ++ * NFMS bit in RCSR register for pagesize of nandflash ++ */ ++#define NFMS (*((volatile u32 *)(CCM_BASE_ADDR+0x18))) ++#define NFMS_BIT 8 ++#define NFMS_NF_DWIDTH 14 ++#define NFMS_NF_PG_SZ 8 ++ + extern unsigned int mxc_get_clock(enum mxc_clock clk); + + #define fixup_before_linux \ +diff --git a/include/asm-arm/arch-mx35/mxc_nand.h b/include/asm-arm/arch-mx35/mxc_nand.h +new file mode 100644 +index 0000000..f4d2ae7 +--- /dev/null ++++ b/include/asm-arm/arch-mx35/mxc_nand.h +@@ -0,0 +1,198 @@ ++/* ++ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file mxc_nd2.h ++ * ++ * @brief This file contains the NAND Flash Controller register information. ++ * ++ * ++ * @ingroup NAND_MTD ++ */ ++ ++#ifndef __MXC_NAND_H__ ++#define __MXC_NAND_H__ ++ ++#include ++ ++#define IS_2K_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) \ ++ == NAND_PAGESIZE_2KB) ++#define IS_4K_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) \ ++ == NAND_PAGESIZE_4KB) ++#define IS_LARGE_PAGE_NAND ((mtd->oobblock / info->num_of_intlv) > 512) ++ ++#define NAND_PAGESIZE_2KB 2048 ++#define NAND_PAGESIZE_4KB 4096 ++#define NAND_MAX_PAGESIZE 4096 ++ ++/* ++ * Addresses for NFC registers ++ */ ++#define NFC_REG_BASE (NFC_BASE_ADDR + 0x1000) ++#define NFC_BUF_ADDR (NFC_REG_BASE + 0xE04) ++#define NFC_FLASH_ADDR (NFC_REG_BASE + 0xE06) ++#define NFC_FLASH_CMD (NFC_REG_BASE + 0xE08) ++#define NFC_CONFIG (NFC_REG_BASE + 0xE0A) ++#define NFC_ECC_STATUS_RESULT (NFC_REG_BASE + 0xE0C) ++#define NFC_SPAS (NFC_REG_BASE + 0xE10) ++#define NFC_WRPROT (NFC_REG_BASE + 0xE12) ++#define NFC_UNLOCKSTART_BLKADDR (NFC_REG_BASE + 0xE20) ++#define NFC_UNLOCKEND_BLKADDR (NFC_REG_BASE + 0xE22) ++#define NFC_CONFIG1 (NFC_REG_BASE + 0xE1A) ++#define NFC_CONFIG2 (NFC_REG_BASE + 0xE1C) ++ ++/*! ++ * Addresses for NFC RAM BUFFER Main area 0 ++ */ ++#define MAIN_AREA0 (u16 *)(NFC_BASE_ADDR + 0x000) ++#define MAIN_AREA1 (u16 *)(NFC_BASE_ADDR + 0x200) ++ ++/*! ++ * Addresses for NFC SPARE BUFFER Spare area 0 ++ */ ++#define SPARE_AREA0 (u16 *)(NFC_BASE_ADDR + 0x1000) ++#define SPARE_LEN 64 ++#define SPARE_COUNT 8 ++#define SPARE_SIZE (SPARE_LEN * SPARE_COUNT) ++ ++ ++#define SPAS_SHIFT (0) ++#define SPAS_MASK (0xFF00) ++#define IS_4BIT_ECC \ ++ ((raw_read(REG_NFC_ECC_MODE) & NFC_ECC_MODE_4) >> 0) ++ ++#define NFC_SET_SPAS(v) \ ++ raw_write(((raw_read(REG_NFC_SPAS) & SPAS_MASK) | \ ++ ((v< +Date: Thu, 14 May 2009 16:38:57 +0800 +Subject: [PATCH] ENGR00112273 BBG2: MMC boot support. + +BBG2: MMC boot support. + +Signed-off-by: Terry Lv +--- + board/freescale/mx35_3stack/Makefile | 1 + + board/freescale/mx35_3stack/flash_header.S | 108 ++ + board/freescale/mx35_3stack/mx35_3stack.c | 123 +++ + board/freescale/mx35_3stack/u-boot.lds | 2 + + board/freescale/mx51_3stack/mx51_3stack.c | 79 ++ + board/freescale/mx51_3stack/u-boot.lds | 1 + + common/Makefile | 1 + + common/cmd_nvedit.c | 9 +- + common/env_common.c | 3 +- + common/env_mmc.c | 327 ++++++ + drivers/mmc/Makefile | 2 + + drivers/mmc/fsl_esdhc.c | 670 ++++++++++++ + drivers/mmc/fsl_mmc.c | 1565 ++++++++++++++++++++++++++++ + include/asm-arm/arch-mx35/mmc.h | 16 + + include/asm-arm/arch-mx35/mx35.h | 4 + + include/asm-arm/arch-mx35/sdhc.h | 218 ++++ + include/asm-arm/arch-mx51/mmc.h | 16 + + include/asm-arm/arch-mx51/sdhc.h | 218 ++++ + include/environment.h | 21 + + include/linux/mmc/card.h | 141 +++ + include/linux/mmc/core.h | 132 +++ + include/linux/mmc/mmc.h | 291 ++++++ + include/linux/mmc/sd.h | 95 ++ + include/linux/mmc/sdhci.h | 223 ++++ + 24 files changed, 4262 insertions(+), 4 deletions(-) + +diff --git a/board/freescale/mx35_3stack/Makefile b/board/freescale/mx35_3stack/Makefile +index 4c38a8b..d310b82 100644 +--- a/board/freescale/mx35_3stack/Makefile ++++ b/board/freescale/mx35_3stack/Makefile +@@ -25,6 +25,7 @@ LIB = $(obj)lib$(BOARD).a + + COBJS := mx35_3stack.o + SOBJS := lowlevel_init.o ++SOBJS += flash_header.o + + SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) + OBJS := $(addprefix $(obj),$(COBJS)) +diff --git a/board/freescale/mx35_3stack/flash_header.S b/board/freescale/mx35_3stack/flash_header.S +new file mode 100644 +index 0000000..6786e8d +--- /dev/null ++++ b/board/freescale/mx35_3stack/flash_header.S +@@ -0,0 +1,108 @@ ++/* ++ * Copyright 2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#include "board-mx35_3stack.h" ++ ++#ifdef CONFIG_FLASH_HEADER ++#ifndef FHEADER_OFFSET ++# error "Must define the offset of flash header" ++#endif ++ ++/* Flash header setup */ ++#define DCDGEN(i,type, addr, data) \ ++dcd_##i: ;\ ++ .long type ;\ ++ .long addr ;\ ++ .long data ++ ++#define GEN_FHEADERADDR(x) (x) ++ ++.section ".text.flasheader", "x" ++ b _start ++ .org FHEADER_OFFSET ++app_code_jump_v: .long GEN_FHEADERADDR(_start) ++app_code_barker: .long 0xB1 ++app_code_csf: .long 0 ++hwcfg_ptr_ptr: .long GEN_FHEADERADDR(hwcfg_ptr) ++super_root_key: .long 0 ++hwcfg_ptr: .long GEN_FHEADERADDR(dcd_data) ++app_dest_ptr: .long TEXT_BASE ++dcd_data: .long 0xB17219E9 ++#ifdef MEMORY_MDDR_ENABLE ++ .long (dcd_data_end - dcd_data - 8) ++ ++//WEIM config-CS5 init ++DCDGEN(1, 4, 0xB8002054, 0x444a4541) ++DCDGEN(1_1, 4, 0xB8002050, 0x0000dcf6) ++DCDGEN(1_2, 4, 0xB8002058, 0x44443302) ++//MDDR init ++//enable mDDR ++DCDGEN(2, 4, 0xB8001010, 0x00000004) ++//reset delay time ++DCDGEN(3, 4, 0xB8001010, 0x0000000C) ++DCDGEN(4, 4, 0xB800100C, 0x007ffc3f) ++DCDGEN(5, 4, 0xB800100C, 0x007ffc3f) ++DCDGEN(6, 4, 0xB8001004, 0x007ffc3f) ++DCDGEN(7, 4, 0xB8001000, 0x92220000) ++DCDGEN(8, 1, 0x80000400, 0xda) ++DCDGEN(9, 4, 0xB8001000, 0xA2220000) ++DCDGEN(10, 4, 0x80000000, 0x87654321) ++DCDGEN(11, 4, 0x80000000, 0x87654321) ++DCDGEN(12, 4, 0xB8001000, 0xB2220000) ++DCDGEN(13, 1, 0x80000033, 0xda) ++DCDGEN(14, 1, 0x82000000, 0xda) ++DCDGEN(15, 4, 0xB8001000, 0x82226080) ++DCDGEN(16, 4, 0xB8001010, 0x00000004) ++DCDGEN(17, 4, 0xB8001008, 0x00002000) ++ ++#else ++ .long 240 ++ ++//WEIM config-CS5 init ++DCDGEN(1, 4, 0xB8002050, 0x0000d843) ++DCDGEN(1_1, 4, 0xB8002054, 0x22252521) ++DCDGEN(1_2, 4, 0xB8002058, 0x22220a00) ++ ++//DDR2 init ++DCDGEN(2, 4, 0xB8001010, 0x00000304) ++DCDGEN(3, 4, 0xB8001010, 0x0000030C) ++DCDGEN(4, 4, 0xB8001004, 0x007ffc3f) ++DCDGEN(5, 4, 0xB8001000, 0x92220000) ++DCDGEN(6, 4, 0x80000400, 0x12345678) ++DCDGEN(7, 4, 0xB8001000, 0xA2220000) ++DCDGEN(8, 4, 0x80000000, 0x87654321) ++DCDGEN(9, 4, 0x80000000, 0x87654321) ++DCDGEN(10, 4, 0xB8001000, 0xB2220000) ++DCDGEN(11, 1, 0x80000233, 0xda) ++DCDGEN(12, 1, 0x82000780, 0xda) ++DCDGEN(13, 1, 0x82000400, 0xda) ++DCDGEN(14, 4, 0xB8001000, 0x82226080) ++DCDGEN(15, 4, 0xB8001004, 0x007ffc3f) ++DCDGEN(16, 4, 0xB800100C, 0x007ffc3f) ++DCDGEN(17, 4, 0xB8001010, 0x00000304) ++DCDGEN(18, 4, 0xB8001008, 0x00002000) ++ ++#endif ++dcd_data_end: ++ ++//CARD_FLASH_CFG_PARMS_T---length ++card_cfg: .long 0x100000 ++#endif +diff --git a/board/freescale/mx35_3stack/mx35_3stack.c b/board/freescale/mx35_3stack/mx35_3stack.c +index 41163f4..f7fb96a 100644 +--- a/board/freescale/mx35_3stack/mx35_3stack.c ++++ b/board/freescale/mx35_3stack/mx35_3stack.c +@@ -29,8 +29,13 @@ + #include + #include + #include ++#include + ++#ifdef CONFIG_MMC ++#include ++#endif + DECLARE_GLOBAL_DATA_PTR; ++volatile u32 *esdhc_base_pointer; + + static u32 system_rev; + +@@ -279,3 +284,121 @@ int board_eth_init(bd_t *bis) + #endif + return rc; + } ++ ++#ifdef CONFIG_FSL_MMC ++ ++int sdhc_init(void) ++{ ++ u32 interface_esdhc = 0; ++ u32 pad_val = 0; ++ ++ interface_esdhc = (readl(IIM_BASE_ADDR + 0x80c)) & (0x000000C0) >> 6; ++ ++ if (!is_soc_rev(CHIP_REV_1_0)) { ++ pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | ++ PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_MAX | ++ PAD_CTL_100K_PU | PAD_CTL_SRE_FAST; ++ ++ switch (interface_esdhc) { ++ case 0: ++ debug("TO1 ESDHC1\n"); ++ ++ esdhc_base_pointer = \ ++ (volatile u32 *)MMC_SDHC1_BASE_ADDR; ++ ++ mxc_iomux_set_pad(MX35_PIN_SD1_DATA3, pad_val); ++ break; ++ case 1: ++ debug("TO1 ESDHC2\n"); ++ ++ esdhc_base_pointer = \ ++ (volatile u32 *)MMC_SDHC2_BASE_ADDR; ++ ++ mxc_iomux_set_pad(MX35_PIN_SD2_DATA3, pad_val); ++ break; ++ case 2: ++ debug("TO1 ESDHC3\n"); ++ ++ esdhc_base_pointer = \ ++ (volatile u32 *)MMC_SDHC3_BASE_ADDR; ++ ++ printf("TO1 ESDHC3 not supported!"); ++ break; ++ default: ++ break; ++ } ++ } else if (!is_soc_rev(CHIP_REV_2_0)) { ++ /* IOMUX PROGRAMMING */ ++ switch (interface_esdhc) { ++ case 0: ++ debug("TO2 ESDHC1\n"); ++ ++ esdhc_base_pointer = \ ++ (volatile u32 *)MMC_SDHC1_BASE_ADDR; ++ ++ pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | ++ PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_HIGH | ++ PAD_CTL_47K_PU | PAD_CTL_SRE_FAST; ++ mxc_request_iomux(MX35_PIN_SD1_CLK, ++ MUX_CONFIG_FUNC | MUX_CONFIG_SION); ++ mxc_iomux_set_pad(MX35_PIN_SD1_CLK, pad_val); ++ ++ pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | ++ PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_HIGH | ++ PAD_CTL_100K_PU | PAD_CTL_SRE_FAST; ++ mxc_request_iomux(MX35_PIN_SD1_CMD, ++ MUX_CONFIG_FUNC | MUX_CONFIG_SION); ++ mxc_iomux_set_pad(MX35_PIN_SD1_CMD, pad_val); ++ mxc_request_iomux(MX35_PIN_SD1_DATA0, ++ MUX_CONFIG_FUNC); ++ mxc_iomux_set_pad(MX35_PIN_SD1_DATA0, pad_val); ++ mxc_request_iomux(MX35_PIN_SD1_DATA3, ++ MUX_CONFIG_FUNC); ++ mxc_iomux_set_pad(MX35_PIN_SD1_DATA3, pad_val); ++ ++ break; ++ case 1: ++ debug("TO2 ESDHC2\n"); ++ ++ esdhc_base_pointer = \ ++ (volatile u32 *)MMC_SDHC2_BASE_ADDR; ++ ++ mxc_request_iomux(MX35_PIN_SD2_CLK, ++ MUX_CONFIG_FUNC | MUX_CONFIG_SION); ++ mxc_request_iomux(MX35_PIN_SD2_CMD, ++ MUX_CONFIG_FUNC | MUX_CONFIG_SION); ++ mxc_request_iomux(MX35_PIN_SD2_DATA0, ++ MUX_CONFIG_FUNC); ++ mxc_request_iomux(MX35_PIN_SD2_DATA3, ++ MUX_CONFIG_FUNC); ++ ++ pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | ++ PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_MAX | ++ PAD_CTL_47K_PU | PAD_CTL_SRE_FAST; ++ mxc_iomux_set_pad(MX35_PIN_SD2_CLK, pad_val); ++ ++ pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | ++ PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_MAX | ++ PAD_CTL_100K_PU | PAD_CTL_SRE_FAST; ++ mxc_iomux_set_pad(MX35_PIN_SD2_CMD, pad_val); ++ mxc_iomux_set_pad(MX35_PIN_SD2_DATA0, pad_val); ++ mxc_iomux_set_pad(MX35_PIN_SD2_DATA3, pad_val); ++ ++ break; ++ case 2: ++ debug("TO2 ESDHC3\n"); ++ ++ esdhc_base_pointer = \ ++ (volatile u32 *)MMC_SDHC3_BASE_ADDR; ++ ++ printf("TO2 ESDHC3 not supported!"); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++#endif +diff --git a/board/freescale/mx35_3stack/u-boot.lds b/board/freescale/mx35_3stack/u-boot.lds +index 1b343be..c0156b5 100644 +--- a/board/freescale/mx35_3stack/u-boot.lds ++++ b/board/freescale/mx35_3stack/u-boot.lds +@@ -38,6 +38,7 @@ SECTIONS + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ ++ board/freescale/mx35_3stack/flash_header.o (.text.flasheader) + *(.text.head) /*arm startup code*/ + *(.text.init) /*platform lowlevel initial code*/ + *(.text.load) /*load bootloader*/ +@@ -47,6 +48,7 @@ SECTIONS + lib_arm/libarm.a (.text) + net/libnet.a (.text) + drivers/mtd/libmtd.a (.text) ++ drivers/mmc/libmmc.a (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/env_embedded.o(.text) +diff --git a/board/freescale/mx51_3stack/mx51_3stack.c b/board/freescale/mx51_3stack/mx51_3stack.c +index c7f93aa..9ddee40 100644 +--- a/board/freescale/mx51_3stack/mx51_3stack.c ++++ b/board/freescale/mx51_3stack/mx51_3stack.c +@@ -35,6 +35,7 @@ DECLARE_GLOBAL_DATA_PTR; + + static u32 system_rev; + u32 mx51_io_base_addr; ++volatile u32 *esdhc_base_pointer; + + u32 get_board_rev(void) + { +@@ -209,3 +210,81 @@ int board_eth_init(bd_t *bis) + return rc; + } + #endif ++ ++#ifdef CONFIG_FSL_MMC ++ ++int sdhc_init(void) ++{ ++ u32 interface_esdhc = 0; ++ u32 pad_val = 0; ++ s32 status = 0; ++ ++ interface_esdhc = (readl(SRC_BASE_ADDR + 0x4) & (0x00180000)) >> 19; ++ ++ switch (interface_esdhc) { ++ case 0: ++ ++ esdhc_base_pointer = (volatile u32 *)MMC_SDHC1_BASE_ADDR; ++ ++ mxc_request_iomux(MX51_PIN_SD1_CMD, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ mxc_request_iomux(MX51_PIN_SD1_CLK, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ ++ mxc_request_iomux(MX51_PIN_SD1_DATA0, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ mxc_request_iomux(MX51_PIN_SD1_DATA1, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ mxc_request_iomux(MX51_PIN_SD1_DATA2, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ mxc_request_iomux(MX51_PIN_SD1_DATA3, ++ IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); ++ mxc_iomux_set_pad(MX51_PIN_SD1_CMD, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ mxc_iomux_set_pad(MX51_PIN_SD1_CLK, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_NONE | PAD_CTL_47K_PU | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ mxc_iomux_set_pad(MX51_PIN_SD1_DATA0, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ mxc_iomux_set_pad(MX51_PIN_SD1_DATA1, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ mxc_iomux_set_pad(MX51_PIN_SD1_DATA2, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ mxc_iomux_set_pad(MX51_PIN_SD1_DATA3, ++ PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | ++ PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PD | ++ PAD_CTL_PUE_PULL | ++ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); ++ break; ++ case 1: ++ status = 1; ++ break; ++ case 2: ++ status = 1; ++ break; ++ case 3: ++ status = 1; ++ break; ++ default: ++ status = 1; ++ break; ++ } ++ ++ return status = 1; ++} ++ ++#endif +diff --git a/board/freescale/mx51_3stack/u-boot.lds b/board/freescale/mx51_3stack/u-boot.lds +index 1cf3c3d..8671fff 100644 +--- a/board/freescale/mx51_3stack/u-boot.lds ++++ b/board/freescale/mx51_3stack/u-boot.lds +@@ -44,6 +44,7 @@ SECTIONS + lib_arm/libarm.a (.text) + net/libnet.a (.text) + drivers/mtd/libmtd.a (.text) ++ drivers/mmc/libmmc.a (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/env_embedded.o(.text) +diff --git a/common/Makefile b/common/Makefile +index 93e3963..b128874 100644 +--- a/common/Makefile ++++ b/common/Makefile +@@ -57,6 +57,7 @@ COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o + COBJS-$(CONFIG_ENV_IS_IN_NVRAM) += env_nvram.o + COBJS-$(CONFIG_ENV_IS_IN_ONENAND) += env_onenand.o + COBJS-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o ++COBJS-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o + COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o + + # command +diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c +index 85025da..38d0698 100644 +--- a/common/cmd_nvedit.c ++++ b/common/cmd_nvedit.c +@@ -59,8 +59,9 @@ DECLARE_GLOBAL_DATA_PTR; + !defined(CONFIG_ENV_IS_IN_NAND) && \ + !defined(CONFIG_ENV_IS_IN_ONENAND) && \ + !defined(CONFIG_ENV_IS_IN_SPI_FLASH) && \ ++ !defined(CONFIG_ENV_IS_IN_MMC) && \ + !defined(CONFIG_ENV_IS_NOWHERE) +-# error Define one of CONFIG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|ONENAND|SPI_FLASH|NOWHERE} ++# error Define one of CONFIG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|ONENAND|SPI_FLASH|MMC|NOWHERE} + #endif + + #define XMK_STR(x) #x +@@ -549,7 +550,8 @@ int getenv_r (char *name, char *buf, unsigned len) + #if ((defined(CONFIG_ENV_IS_IN_NVRAM) || defined(CONFIG_ENV_IS_IN_EEPROM) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \ +- || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))) \ ++ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND)) \ ++ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_MMC))) \ + && !defined(CONFIG_ENV_IS_NOWHERE)) + int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) + { +@@ -605,7 +607,8 @@ U_BOOT_CMD( + #if ((defined(CONFIG_ENV_IS_IN_NVRAM) || defined(CONFIG_ENV_IS_IN_EEPROM) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_FLASH)) \ + || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_NAND)) \ +- || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND))) \ ++ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_ONENAND)) \ ++ || (defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_MMC))) \ + && !defined(CONFIG_ENV_IS_NOWHERE)) + U_BOOT_CMD( + saveenv, 1, 0, do_saveenv, +diff --git a/common/env_common.c b/common/env_common.c +index 6be3bb0..eb0b374 100644 +--- a/common/env_common.c ++++ b/common/env_common.c +@@ -140,7 +140,8 @@ uchar default_environment[] = { + }; + + #if defined(CONFIG_ENV_IS_IN_NAND) /* Environment is in Nand Flash */ \ +- || defined(CONFIG_ENV_IS_IN_SPI_FLASH) ++ || defined(CONFIG_ENV_IS_IN_SPI_FLASH) \ ++ || defined(CONFIG_ENV_IS_IN_MMC) + int default_environment_size = sizeof(default_environment); + #endif + +diff --git a/common/env_mmc.c b/common/env_mmc.c +new file mode 100644 +index 0000000..413a5c7 +--- /dev/null ++++ b/common/env_mmc.c +@@ -0,0 +1,327 @@ ++/* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ ++ * (C) Copyright 2000-2006 ++ * Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++ * ++ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH ++ * Andreas Heppel ++ ++ * 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 ++ */ ++ ++/* #define DEBUG */ ++ ++#include ++ ++#if defined(CONFIG_ENV_IS_IN_MMC) /* Environment is in MMC Flash */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(CONFIG_CMD_ENV) && defined(CONFIG_CMD_MMC) ++#define CMD_SAVEENV ++#elif defined(CONFIG_ENV_OFFSET_REDUND) ++#error Cannot use CONFIG_ENV_OFFSET_REDUND without CONFIG_CMD_ENV & CONFIG_CMD_MMC ++#endif ++ ++#if defined(CONFIG_ENV_SIZE_REDUND) && (CONFIG_ENV_SIZE_REDUND < CONFIG_ENV_SIZE) ++#error CONFIG_ENV_SIZE_REDUND should not be less then CONFIG_ENV_SIZE ++#endif ++ ++#ifdef CONFIG_INFERNO ++#error CONFIG_INFERNO not supported yet ++#endif ++ ++/* references to names in env_common.c */ ++extern uchar default_environment[]; ++extern int default_environment_size; ++ ++char *env_name_spec = "MMC"; ++ ++#ifdef ENV_IS_EMBEDDED ++extern uchar environment[]; ++env_t *env_ptr = (env_t *)(&environment[0]); ++#else /* ! ENV_IS_EMBEDDED */ ++env_t *env_ptr; ++#endif /* ENV_IS_EMBEDDED */ ++ ++/* local functions */ ++#if !defined(ENV_IS_EMBEDDED) ++static void use_default(void); ++#endif ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++uchar env_get_char_spec(int index) ++{ ++ return *((uchar *)(gd->env_addr + index)); ++} ++ ++ ++/* this is called before nand_init() ++ * so we can't read Nand to validate env data. ++ * Mark it OK for now. env_relocate() in env_common.c ++ * will call our relocate function which will does ++ * the real validation. ++ * ++ * When using a NAND boot image (like sequoia_nand), the environment ++ * can be embedded or attached to the U-Boot image in NAND flash. This way ++ * the SPL loads not only the U-Boot image from NAND but also the ++ * environment. ++ */ ++int env_init(void) ++{ ++#if defined(CONFIG_IS_EMBEDDED) ++ size_t total; ++ int crc1_ok = 0, crc2_ok = 0; ++ env_t *tmp_env1, *tmp_env2; ++ ++ total = CONFIG_ENV_SIZE; ++ ++ tmp_env1 = env_ptr; ++ tmp_env2 = (env_t *)((ulong)env_ptr + CONFIG_ENV_SIZE); ++ ++ crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); ++ crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); ++ ++ if (!crc1_ok && !crc2_ok) ++ gd->env_valid = 0; ++ else if (crc1_ok && !crc2_ok) ++ gd->env_valid = 1; ++ else if (!crc1_ok && crc2_ok) ++ gd->env_valid = 2; ++ else { ++ /* both ok - check serial */ ++ if (tmp_env1->flags == 255 && tmp_env2->flags == 0) ++ gd->env_valid = 2; ++ else if (tmp_env2->flags == 255 && tmp_env1->flags == 0) ++ gd->env_valid = 1; ++ else if (tmp_env1->flags > tmp_env2->flags) ++ gd->env_valid = 1; ++ else if (tmp_env2->flags > tmp_env1->flags) ++ gd->env_valid = 2; ++ else /* flags are equal - almost impossible */ ++ gd->env_valid = 1; ++ } ++ ++ if (gd->env_valid == 1) ++ env_ptr = tmp_env1; ++ else if (gd->env_valid == 2) ++ env_ptr = tmp_env2; ++ ++#else /* ENV_IS_EMBEDDED */ ++ gd->env_addr = (ulong)&default_environment[0]; ++ gd->env_valid = 1; ++ ++#endif /* ENV_IS_EMBEDDED */ ++ ++ return 0; ++} ++ ++#ifdef CMD_SAVEENV ++/* ++ * The legacy NAND code saved the environment in the first NAND device i.e., ++ * nand_dev_desc + 0. This is also the behaviour using the new NAND code. ++ */ ++#ifdef CONFIG_ENV_OFFSET_REDUND ++int saveenv(void) ++{ ++ size_t total; ++ int ret = 0; ++ ++ env_ptr->flags++; ++ total = CONFIG_ENV_SIZE; ++ ++ if (gd->env_valid == 1) { ++ puts("Writing to redundant MMC... "); ++ ret = mmc_write((u_char *)env_ptr, ++ CONFIG_ENV_OFFSET_REDUND, total); ++ } else { ++ puts("Writing to MMC... "); ++ ret = mmc_write((u_char *)env_ptr, ++ CONFIG_ENV_OFFSET, total); ++ } ++ if (ret || total != CONFIG_ENV_SIZE) { ++ puts("failed\n"); ++ return 1; ++ } ++ ++ puts("done\n"); ++ gd->env_valid = (gd->env_valid == 2 ? 1 : 2); ++ return ret; ++} ++#else /* ! CONFIG_ENV_OFFSET_REDUND */ ++int saveenv(void) ++{ ++ size_t total; ++ int ret = 0; ++ ++ puts("Writing to MMC... "); ++ total = CONFIG_ENV_SIZE; ++ ret = mmc_write((u_char *)env_ptr, CONFIG_ENV_OFFSET, total); ++ if (ret || total != CONFIG_ENV_SIZE) { ++ puts("failed\n"); ++ return 1; ++ } ++ ++ puts("done\n"); ++ return ret; ++} ++#endif /* CONFIG_ENV_OFFSET_REDUND */ ++#endif /* CMD_SAVEENV */ ++ ++#ifdef CONFIG_ENV_OFFSET_REDUND ++void env_relocate_spec(void) ++{ ++#if !defined(ENV_IS_EMBEDDED) ++ size_t total; ++ int crc1_ok = 0, crc2_ok = 0; ++ env_t *tmp_env1 = NULL, *tmp_env2 = NULL; ++ ++ puts("Initialing MMC card... \n"); ++ ++ if (mmc_init(1) != 0) { ++ puts("No MMC card found\n"); ++ goto use_default; ++ } ++ ++ total = CONFIG_ENV_SIZE; ++ ++ tmp_env1 = (env_t *)malloc(CONFIG_ENV_SIZE); ++ if (!tmp_env1) { ++ puts("Not enough memory!\n"); ++ goto use_default; ++ } ++ memset(tmp_env1, 0, CONFIG_ENV_SIZE); ++ ++ tmp_env2 = (env_t *)malloc(CONFIG_ENV_SIZE); ++ if (!tmp_env2) { ++ puts("Not enough memory!\n"); ++ goto use_default; ++ } ++ memset(tmp_env2, 0, CONFIG_ENV_SIZE); ++ ++ puts("Loading environment from mmc... "); ++ if (mmc_read(CONFIG_ENV_OFFSET, (uchar *)tmp_env1, total)) { ++ puts("failed\n"); ++ goto use_default; ++ } ++ puts("done\n"); ++ ++ puts("Loading redundant environment from mmc... "); ++ if (mmc_read(CONFIG_ENV_OFFSET_REDUND, (uchar *)tmp_env2, total)) { ++ puts("failed\n"); ++ goto use_default; ++ } ++ puts("done\n"); ++ ++ crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); ++ crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); ++ ++ if (!crc1_ok && !crc2_ok) ++ goto use_default; ++ else if (crc1_ok && !crc2_ok) ++ gd->env_valid = 1; ++ else if (!crc1_ok && crc2_ok) ++ gd->env_valid = 2; ++ else { ++ /* both ok - check serial */ ++ if (tmp_env1->flags == 255 && tmp_env2->flags == 0) ++ gd->env_valid = 2; ++ else if (tmp_env2->flags == 255 && tmp_env1->flags == 0) ++ gd->env_valid = 1; ++ else if (tmp_env1->flags > tmp_env2->flags) ++ gd->env_valid = 1; ++ else if (tmp_env2->flags > tmp_env1->flags) ++ gd->env_valid = 2; ++ else /* flags are equal - almost impossible */ ++ gd->env_valid = 1; ++ } ++ ++ free(env_ptr); ++ if (gd->env_valid == 1) { ++ env_ptr = tmp_env1; ++ free(tmp_env2); ++ } else { ++ env_ptr = tmp_env2; ++ free(tmp_env1); ++ } ++ ++ return; ++ ++use_default: ++ if (tmp_env1) ++ free(tmp_env1); ++ if (tmp_env2) ++ free(tmp_env2); ++ return use_default(); ++ ++#endif /* ! ENV_IS_EMBEDDED */ ++} ++#else /* ! CONFIG_ENV_OFFSET_REDUND */ ++/* ++ * The legacy NAND code saved the environment in the first NAND device i.e., ++ * nand_dev_desc + 0. This is also the behaviour using the new NAND code. ++ */ ++void env_relocate_spec(void) ++{ ++#if !defined(ENV_IS_EMBEDDED) ++ size_t total; ++ int ret; ++ ++ if (mmc_init(1) != 0) { ++ puts("No MMC card found\n"); ++ return; ++ } ++ ++ total = CONFIG_ENV_SIZE; ++ ret = mmc_read(CONFIG_ENV_OFFSET, (u_char *)env_ptr, &total); ++ if (ret || total != CONFIG_ENV_SIZE) ++ return use_default(); ++ ++ if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) ++ return use_default(); ++#endif /* ! ENV_IS_EMBEDDED */ ++} ++#endif /* CONFIG_ENV_OFFSET_REDUND */ ++ ++#if !defined(ENV_IS_EMBEDDED) ++static void use_default() ++{ ++ puts("*** Warning - bad CRC or MMC Card, using default environment\n\n"); ++ ++ if (default_environment_size > CONFIG_ENV_SIZE) { ++ puts("*** Error - default environment is too large\n\n"); ++ return; ++ } ++ ++ memset(env_ptr, 0, sizeof(env_t)); ++ memcpy(env_ptr->data, ++ default_environment, ++ default_environment_size); ++ env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); ++ gd->env_valid = 1; ++} ++#endif ++ ++#endif /* CONFIG_ENV_IS_IN_MMC */ +diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile +index 3dc031b..0dfadd2 100644 +--- a/drivers/mmc/Makefile ++++ b/drivers/mmc/Makefile +@@ -26,6 +26,8 @@ include $(TOPDIR)/config.mk + LIB := $(obj)libmmc.a + + COBJS-$(CONFIG_ATMEL_MCI) += atmel_mci.o ++COBJS-$(CONFIG_FSL_MMC) += fsl_mmc.o ++COBJS-$(CONFIG_FSL_MMC) += fsl_esdhc.o + + COBJS := $(COBJS-y) + SRCS := $(COBJS:.o=.c) +diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c +new file mode 100644 +index 0000000..465abf6 +--- /dev/null ++++ b/drivers/mmc/fsl_esdhc.c +@@ -0,0 +1,670 @@ ++/* ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++ */ ++ ++/*! ++ * @file esdhc.c ++ * ++ * @brief source code for the mmc card operation ++ * ++ * @ingroup mmc ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_MMC ++ ++#define RETRIES_TIMES 100 ++ ++#define REG_WRITE_OR(val, reg) { \ ++ u32 temp = 0; \ ++ temp = readl(reg); \ ++ (temp) |= (val); \ ++ writel((temp), (reg)); \ ++ } ++ ++#define REG_WRITE_AND(val, reg) { \ ++ u32 temp = 0; \ ++ temp = readl(reg); \ ++ (temp) &= (val); \ ++ writel((temp), (reg)); \ ++ } ++ ++#define SDHC_DELAY_BY_100(x) { \ ++ u32 i; \ ++ for (i = 0; i < x; ++i) \ ++ udelay(100); \ ++ } ++ ++ ++extern volatile u32 esdhc_base_pointer; ++ ++static void esdhc_cmd_config(esdhc_cmd_t *); ++static u32 esdhc_check_response(void); ++static u32 esdhc_wait_buf_rdy_intr(u32, u32); ++static void esdhc_wait_op_done_intr(void); ++static u32 esdhc_check_data(void); ++static void esdhc_set_data_transfer_width(u32 data_transfer_width); ++static u32 esdhc_poll_cihb_cdihb(data_present_select data_present); ++static void esdhc_set_endianness(u32 endian_mode); ++static void esdhc_clear_buf_rdy_intr(u32 mask); ++static u32 esdhc_check_data_crc_status(void); ++ ++/*! ++ * Send 80 SD clock to card and wait for INITA bit to get cleared. ++ */ ++void interface_initialization_active(void) ++{ ++ /* Send 80 clock ticks for card to power up */ ++ REG_WRITE_OR(ESDHC_SYSCTL_INITA, \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ ++ /* Start a general purpose timer */ ++ udelay(ESDHC_CARD_INIT_TIMEOUT); ++} ++ ++/*! ++ * Execute a software reset and set data bus width for eSDHC. ++ */ ++u32 interface_reset() ++{ ++ u32 reset_status = 0; ++ u32 u32Retries = 0; ++ u32 u32Temp = 0; ++ ++ debug("Entry: interface_reset"); ++ ++ /* Reset the entire host controller by writing ++ 1 to RSTA bit of SYSCTRL Register */ ++ REG_WRITE_OR(ESDHC_SOFTWARE_RESET, \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ ++ /* Start a general purpose timer (3 millsec delay) */ ++ /* udelay(ESDHC_OPER_TIMEOUT); */ ++ ++ /* Wait for clearance of CIHB and CDIHB Bits */ ++ for (u32Retries = RETRIES_TIMES; u32Retries > 0; --u32Retries) { ++ if (!is_soc_rev(CHIP_REV_1_0)) { ++ if (readl(esdhc_base_pointer + SDHCI_PRESENT_STATE) \ ++ & ESDHC_CMD_INHIBIT) { ++ reset_status = 1; ++ } else { ++ reset_status = 0; ++ break; ++ } ++ } else if (!is_soc_rev(CHIP_REV_2_0)) { ++ if (readl(esdhc_base_pointer + SDHCI_SYSTEM_CONTROL) \ ++ & ESDHC_SOFTWARE_RESET) { ++ reset_status = 1; ++ } else { ++ reset_status = 0; ++ break; ++ } ++ } ++ } ++ ++ if (!is_soc_rev(CHIP_REV_1_0)) { ++ /* send 80 clock ticks for card to power up */ ++ REG_WRITE_OR(ESDHC_SYSCTL_INITA, \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ } ++ ++ /* Set data bus width of ESDCH */ ++ esdhc_set_data_transfer_width(0x00000000); ++ ++ /* Set Endianness of ESDHC */ ++ esdhc_set_endianness(0x00000020); ++ ++ /* set data timeout delay to max */ ++ u32Temp = (readl(esdhc_base_pointer + SDHCI_SYSTEM_CONTROL) & \ ++ 0xfff0ffff) | 0x000e0000; ++ writel(u32Temp, esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ ++ return reset_status; ++} ++ ++/*! ++ * Clear interrupts at eSDHC level. ++ */ ++void interface_clear_interrupt(void) ++{ ++ /* Clear Interrupt status register */ ++ writel(ESDHC_CLEAR_INTERRUPT, esdhc_base_pointer + SDHCI_INT_STATUS); ++} ++ ++/*! ++ * Enable Clock and set operating frequency. ++ */ ++void interface_configure_clock(sdhc_freq_t frequency) ++{ ++ u32 ident_freq = 0; ++ u32 oper_freq = 0; ++ ++ if (!is_soc_rev(CHIP_REV_1_0)) { ++ /* Enable ipg_perclk, HCLK enable and IPG Clock enable. */ ++ REG_WRITE_OR(ESDHC_CLOCK_ENABLE, \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ /* Clear DTOCV SDCLKFS bits */ ++ REG_WRITE_OR(ESDHC_FREQ_MASK, \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ ident_freq = ESDHC_SYSCTL_IDENT_FREQ_TO1; ++ oper_freq = ESDHC_SYSCTL_OPERT_FREQ_TO1; ++ } else if (!is_soc_rev(CHIP_REV_2_0)) { ++ /* Clear SDCLKEN bit */ ++ REG_WRITE_OR((~ESDHC_SYSCTL_SDCLKEN_MASK), \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ ++ /* Clear DTOCV, SDCLKFS, DVFS bits */ ++ REG_WRITE_OR((~ESDHC_SYSCTL_FREQ_MASK), \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ ident_freq = ESDHC_SYSCTL_IDENT_FREQ_TO2; ++ oper_freq = ESDHC_SYSCTL_OPERT_FREQ_TO2; ++ } ++ ++ if (!is_soc_rev(CHIP_REV_2_0)) { ++ /* Disable the PEREN, HCKEN and IPGEN */ ++ REG_WRITE_OR((~ESDHC_SYSCTL_INPUT_CLOCK_MASK), \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ } ++ ++ if (frequency == IDENTIFICATION_FREQ) { ++ /* Input frequecy to eSDHC is 36 MHZ */ ++ /* PLL3 is the source of input frequency*/ ++ /*Set DTOCV and SDCLKFS bit to get SD_CLK ++ of frequency below 400 KHZ (70.31 KHZ) */ ++ REG_WRITE_OR(ident_freq, \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ } else if (frequency == OPERATING_FREQ) { ++ /*Set DTOCV and SDCLKFS bit to get SD_CLK ++ of frequency around 25 MHz.(18 MHz)*/ ++ REG_WRITE_OR(oper_freq, \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ } ++ ++ if (!is_soc_rev(CHIP_REV_2_0)) { ++ /* Start a general purpose timer */ ++ /* Wait for clock to be stable */ ++ SDHC_DELAY_BY_100(96); ++ ++ /* Set SDCLKEN bit to enable clock */ ++ REG_WRITE_OR(ESDHC_SYSCTL_SDCLKEN_MASK, \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ ++ /* Mask Data Timeout Error Status Enable Interrupt (DTOESEN) */ ++ REG_WRITE_AND((~ESDHC_IRQSTATEN_DTOESEN), \ ++ esdhc_base_pointer + SDHCI_INT_ENABLE); ++ ++ /* Set the Data Timeout Counter Value(DTOCV) */ ++ REG_WRITE_OR(ESDHC_SYSCTL_DTOCV_VAL, \ ++ esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); ++ ++ /* Enable Data Timeout Error Status ++ Enable Interrupt (DTOESEN) */ ++ REG_WRITE_OR(ESDHC_IRQSTATEN_DTOESEN, \ ++ esdhc_base_pointer + SDHCI_INT_ENABLE); ++ } ++} ++ ++/*! ++ * Set data transfer width for e-SDHC. ++ */ ++static void esdhc_set_data_transfer_width(u32 data_transfer_width) ++{ ++ ++ /* Set DWT bit of protocol control register according to bus_width */ ++ if (!is_soc_rev(CHIP_REV_2_0)) ++ REG_WRITE_AND((~ESDHC_BUS_WIDTH_MASK), \ ++ esdhc_base_pointer + SDHCI_HOST_CONTROL); ++ ++ REG_WRITE_OR((data_transfer_width), \ ++ esdhc_base_pointer + SDHCI_HOST_CONTROL); ++} ++ ++/*! ++ * Set endianness mode for e-SDHC. ++ */ ++static void esdhc_set_endianness(u32 endian_mode) ++{ ++ if (!is_soc_rev(CHIP_REV_2_0)) { ++ REG_WRITE_AND((~ESDHC_ENDIAN_MODE_MASK), \ ++ esdhc_base_pointer + SDHCI_HOST_CONTROL); ++ } ++ /* Set DWT bit of protocol control register according to bus_width */ ++ REG_WRITE_OR((endian_mode), \ ++ esdhc_base_pointer + SDHCI_HOST_CONTROL); ++} ++ ++/*! ++ * Poll the CIHB & CDIHB bits of the present ++ * state register and wait until it goes low. ++ */ ++static u32 esdhc_poll_cihb_cdihb(data_present_select data_present) ++{ ++ u32 init_status = 0; ++ u32 u32Retries = 0; ++ ++ /* Start a general purpose timer */ ++ for (u32Retries = RETRIES_TIMES; u32Retries > 0; u32Retries--) { ++ if (!(readl(esdhc_base_pointer + SDHCI_PRESENT_STATE) & \ ++ ESDHC_PRESENT_STATE_CIHB)) { ++ init_status = 0; ++ break; ++ } ++ SDHC_DELAY_BY_100(10); ++ } ++ ++ /* ++ * Wait for the data line to be free (poll the CDIHB bit of ++ * the present state register). ++ */ ++ if ((0 == init_status) && (data_present == DATA_PRESENT)) { ++ /* Start a general purpose timer */ ++ SDHC_DELAY_BY_100(32); ++ ++ if (readl(esdhc_base_pointer + SDHCI_PRESENT_STATE) & \ ++ ESDHC_PRESENT_STATE_CDIHB) { ++ init_status = 1; ++ } ++ } ++ ++ return init_status; ++} ++ ++/*! ++ * Wait until the command and data lines are free. ++ */ ++u32 interface_wait_cmd_data_lines(data_present_select data_present) ++{ ++ u32 cmd_status = 0; ++ ++ cmd_status = esdhc_poll_cihb_cdihb(data_present); ++ ++ return cmd_status; ++} ++ ++u32 interface_set_bus_width(u32 bus_width) ++{ ++ u32 tmp; ++ ++ tmp = readl(esdhc_base_pointer + SDHCI_HOST_CONTROL); ++ ++ tmp &= ~SDHCI_CTRL_8BITBUS; ++ tmp |= SDHCI_CTRL_4BITBUS; ++ ++ writel(tmp, esdhc_base_pointer + SDHCI_HOST_CONTROL); ++ ++ return 0; ++} ++ ++/*! ++ * Execute a command and wait for the response. ++ */ ++u32 interface_send_cmd_wait_resp(esdhc_cmd_t *cmd) ++{ ++ u32 cmd_status = 0; ++ ++ /* Clear Interrupt status register */ ++ writel(ESDHC_CLEAR_INTERRUPT, \ ++ esdhc_base_pointer + SDHCI_INT_STATUS); ++ ++ /* Enable Interrupt */ ++ REG_WRITE_OR(ESDHC_INTERRUPT_ENABLE, \ ++ esdhc_base_pointer + SDHCI_INT_ENABLE); ++ ++ if (!is_soc_rev(CHIP_REV_2_0)) { ++ cmd_status = interface_wait_cmd_data_lines(cmd->data_present); ++ ++ if (cmd_status == 1) ++ return 1; ++ } ++ ++ /* Configure Command */ ++ esdhc_cmd_config(cmd); ++ ++ /* Wait for interrupt CTOE or CC */ ++ SDHC_DELAY_BY_100(96); ++ ++ /* Mask all interrupts */ ++ writel(0, esdhc_base_pointer + SDHCI_SIGNAL_ENABLE); ++ ++ /* Check if an error occured */ ++ return esdhc_check_response(); ++} ++ ++/*! ++ * Configure ESDHC registers for sending a command to MMC. ++ */ ++static void esdhc_cmd_config(esdhc_cmd_t *cmd) ++{ ++ u32 u32Temp = 0; ++ ++ /* Write Command Argument in Command Argument Register */ ++ writel(cmd->arg, esdhc_base_pointer + SDHCI_ARGUMENT); ++ ++ /* ++ *Configure e-SDHC Register value according to Command ++ */ ++ u32Temp = \ ++ (((cmd->data_transfer)<response_format)<data_present)<crc_check) << ESDHC_CRC_CHECK_SHIFT) | ++ ((cmd->cmdindex_check) << ESDHC_CMD_INDEX_CHECK_SHIFT) | ++ ((cmd->command) << ESDHC_CMD_INDEX_SHIFT) | ++ ((cmd->block_count_enable_check) << \ ++ ESDHC_BLOCK_COUNT_ENABLE_SHIFT) | ++ ((cmd->multi_single_block) << \ ++ ESDHC_MULTI_SINGLE_BLOCK_SELECT_SHIFT)); ++ ++ writel(u32Temp, esdhc_base_pointer + SDHCI_TRANSFER_MODE); ++} ++ ++/*! ++ * Wait a END_CMD_RESP interrupt by interrupt status register. ++ * e-SDHC sets this bit after receving command response. ++ */ ++static u32 esdhc_check_response(void) ++{ ++ u32 status = 1; ++ ++ /* Check whether the interrupt is an END_CMD_RESP ++ * or a response time out or a CRC error ++ */ ++ if ((readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ ++ ESDHC_STATUS_END_CMD_RESP_MSK) && ++ !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ ++ ESDHC_STATUS_TIME_OUT_RESP_MSK) && ++ !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ ++ ESDHC_STATUS_RESP_CRC_ERR_MSK) && ++ !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ ++ ESDHC_STATUS_RESP_CMD_INDEX_ERR_MSK)) ++ status = 0; ++ ++ return status; ++} ++ ++/*! ++ * This function will read response from e-SDHC ++ * register according to reponse format. ++ */ ++void interface_read_response(esdhc_resp_t *cmd_resp) ++{ ++ /* get response values from e-SDHC CMDRSP registers.*/ ++ cmd_resp->cmd_rsp0 = (u32)readl(esdhc_base_pointer + SDHCI_RESPONSE); ++ cmd_resp->cmd_rsp1 = (u32)readl(esdhc_base_pointer + \ ++ SDHCI_RESPONSE + 4); ++ cmd_resp->cmd_rsp2 = (u32)readl(esdhc_base_pointer + \ ++ SDHCI_RESPONSE + 8); ++ cmd_resp->cmd_rsp3 = (u32)readl(esdhc_base_pointer + \ ++ SDHCI_RESPONSE + 12); ++} ++ ++/*! ++ * This function will read response from e-SDHC register ++ * according to reponse format. ++ */ ++u32 interface_data_read(u32 *dest_ptr, u32 blk_len) ++{ ++ u32 i = 0; ++ u32 j = 0; ++ u32 status = 1; ++ u32 *tmp_ptr = dest_ptr; ++ ++ debug("Entry: interface_data_read()\n"); ++ ++ /* Enable Interrupt */ ++ REG_WRITE_OR(ESDHC_INTERRUPT_ENABLE, \ ++ esdhc_base_pointer + SDHCI_INT_ENABLE); ++ ++ for (i = 0; i < (blk_len) / (ESDHC_FIFO_SIZE * 4); ++i) { ++ /* Wait for BRR bit to be set */ ++ status = esdhc_wait_buf_rdy_intr(ESDHC_STATUS_BUF_READ_RDY_MSK, ++ ESDHC_READ_DATA_TIME_OUT); ++ ++ debug("esdhc_wait_buf_rdy_intr: %d\n", status); ++ ++ if (!status) { ++ for (j = 0; j < ESDHC_FIFO_SIZE; ++j) { ++ *tmp_ptr++ = \ ++ readl(esdhc_base_pointer + SDHCI_BUFFER); ++ } ++ if (!is_soc_rev(CHIP_REV_2_0)) { ++ /* Clear the BRR */ ++ esdhc_clear_buf_rdy_intr(ESDHC_STATUS_BUF_READ_RDY_MSK); ++ } ++ } else { ++ debug("esdhc_wait_buf_rdy_intr failed\n"); ++ break; ++ } ++ } ++ ++ esdhc_wait_op_done_intr(); ++ ++ status = esdhc_check_data(); ++ ++ if (!is_soc_rev(CHIP_REV_2_0) && !status) ++ status = 0; ++ ++ debug("esdhc_check_data: %d\n", status); ++ ++ debug("Exit: interface_data_read()\n"); ++ ++ return status; ++} ++ ++/*! ++ * Wait a BUF_READ_READY interrupt by pooling STATUS register. ++ */ ++static u32 esdhc_wait_buf_rdy_intr(u32 mask, u32 multi_single_block) ++{ ++ u32 status = 0; ++ u32 u32Retries = 0; ++ ++ /* Wait interrupt (BUF_READ_RDY) ++ */ ++ ++ for (u32Retries = RETRIES_TIMES; u32Retries > 0; --u32Retries) { ++ if (!(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & mask)) { ++ status = 1; ++ } else { ++ status = 0; ++ break; ++ } ++ SDHC_DELAY_BY_100(10); ++ } ++ ++ if (multi_single_block == MULTIPLE && \ ++ readl(esdhc_base_pointer + SDHCI_INT_STATUS) & mask) ++ REG_WRITE_OR(mask, (esdhc_base_pointer + SDHCI_INT_STATUS)); ++ ++ return status; ++} ++ ++/*! ++ * Clear BUF_READ_READY/BUF_WRITE_READY interrupt ++ * by writing 1 to STATUS register. ++ */ ++static void esdhc_clear_buf_rdy_intr(u32 mask) ++{ ++ writel(mask, (esdhc_base_pointer + SDHCI_INT_STATUS)); ++} ++ ++/*! ++ * Wait for TC, DEBE, DCE or DTOE by polling Interrupt STATUS register. ++ */ ++static void esdhc_wait_op_done_intr(void) ++{ ++ while (!(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ ++ ESDHC_STATUS_TRANSFER_COMPLETE_MSK)) ++ ; ++} ++ ++/*! ++ * If READ_OP_DONE occured check ESDHC_STATUS_TIME_OUT_READ ++ * and RD_CRC_ERR_CODE and ++ * to determine if an error occured ++ */ ++static u32 esdhc_check_data(void) ++{ ++ ++ u32 status = 1; ++ ++ debug("Entry: esdhc_check_data()\n"); ++ ++ /* Check whether the interrupt is an OP_DONE ++ * or a data time out or a CRC error ++ */ ++ if ((readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ ++ ESDHC_STATUS_TRANSFER_COMPLETE_MSK) && ++ !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ ++ ESDHC_STATUS_TIME_OUT_READ_MASK) && ++ !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ ++ ESDHC_STATUS_READ_CRC_ERR_MSK)) { ++ if (!is_soc_rev(CHIP_REV_2_0)) { ++ writel(ESDHC_STATUS_TRANSFER_COMPLETE_MSK, \ ++ (esdhc_base_pointer + SDHCI_INT_STATUS)); ++ } ++ status = 0; ++ } else { ++ status = 1; ++ } ++ ++ debug("Exit: esdhc_check_data()\n"); ++ ++ return status; ++} ++ ++/*! ++ * Check for Data timeout error, data CRC error and data end bit error ++ * to determine if an error occured. ++ */ ++static u32 esdhc_check_data_crc_status(void) ++{ ++ u32 status = 1; ++ ++ /* Check whether the interrupt is DTOE/DCE/DEBE */ ++ if (!(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ ++ ESDHC_STATUS_TIME_OUT_READ_MASK) && ++ !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ ++ ESDHC_STATUS_READ_CRC_ERR_MSK) && ++ !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ ++ ESDHC_STATUS_RW_DATA_END_BIT_ERR_MSK)) { ++ status = 0; ++ } else { ++ status = 1; ++ } ++ ++ return status; ++} ++ ++/*! ++ * Set Block length. ++ */ ++void interface_config_block_info(u32 blk_len, u32 nob, u32 wml) ++{ ++ /* Configre block Attributes register */ ++ writel(((nob << ESDHC_BLOCK_SHIFT) | blk_len), \ ++ (esdhc_base_pointer + SDHCI_BLOCK_SIZE)); ++ ++ /* Set Read Water MArk Level register */ ++ writel(wml, esdhc_base_pointer + SDHCI_WML_LEV); ++} ++ ++/*! ++ * This function will write data to device attached to interface. ++ */ ++u32 interface_data_write(u32 *dest_ptr, u32 blk_len) ++{ ++ u32 i = 0; ++ u32 j = 0; ++ u32 status = 1; ++ u32 *tmp_ptr = dest_ptr; ++ ++ debug("Entry: interface_data_write()\n"); ++ ++ /* Enable Interrupt */ ++ REG_WRITE_OR(ESDHC_INTERRUPT_ENABLE, \ ++ (esdhc_base_pointer + SDHCI_INT_ENABLE)); ++ ++ for (i = 0; i < (blk_len) / (ESDHC_FIFO_SIZE * 4); ++i) { ++ /* Wait for BWR bit to be set */ ++ esdhc_wait_buf_rdy_intr(ESDHC_STATUS_BUF_WRITE_RDY_MSK, \ ++ SINGLE); ++ ++ for (j = 0; j < ESDHC_FIFO_SIZE; ++j) { ++ writel((*tmp_ptr), esdhc_base_pointer + SDHCI_BUFFER); ++ ++tmp_ptr; ++ } ++ esdhc_clear_buf_rdy_intr(ESDHC_STATUS_BUF_WRITE_RDY_MSK); ++ } ++ ++ /* Wait for transfer complete operation interrupt */ ++ esdhc_wait_op_done_intr(); ++ ++ /* Check for status errors */ ++ status = esdhc_check_data(); ++ ++ debug("Exit: interface_data_write()\n"); ++ ++ return status; ++} ++ ++/*! ++ * Configure the CMD line PAD configuration for strong or weak pull-up. ++ */ ++/* ++void esdhc_set_cmd_pullup(esdhc_pullup_t pull_up) ++{ ++ u32 interface_esdhc = 0; ++ u32 pad_val = 0; ++ ++ interface_esdhc = (readl(0x53ff080c)) & (0x000000C0) >> 6; ++ ++ if (pull_up == STRONG) { ++ pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | ++ PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_HIGH | ++ PAD_CTL_22K_PU | PAD_CTL_SRE_FAST; ++ } else { ++ pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | ++ PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_MAX | ++ PAD_CTL_100K_PU | PAD_CTL_SRE_FAST; ++ } ++ ++ switch (interface_esdhc) { ++ case ESDHC1: ++ mxc_iomux_set_pad(MX51_PIN_SD1_CMD, pad_val); ++ break; ++ case ESDHC2: ++ mxc_iomux_set_pad(MX51_PIN_SD2_CMD, pad_val); ++ break; ++ case ESDHC3: ++ default: ++ break; ++ } ++} ++*/ ++ ++#endif +diff --git a/drivers/mmc/fsl_mmc.c b/drivers/mmc/fsl_mmc.c +new file mode 100644 +index 0000000..2fbf4d6 +--- /dev/null ++++ b/drivers/mmc/fsl_mmc.c +@@ -0,0 +1,1565 @@ ++/* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 ++#include ++#ifdef CONFIG_MMC ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define CARD_SUPPORT_BYTE_MODE (0) ++#define CARD_SUPPORT_SECT_MODE (1) ++ ++#define RETRY_TIMEOUT (10) ++ ++ ++extern int fat_register_device(block_dev_desc_t *dev_desc, int part_no); ++ ++static block_dev_desc_t mmc_dev; ++ ++block_dev_desc_t *mmc_get_dev(int dev) ++{ ++ return (block_dev_desc_t *)&mmc_dev; ++} ++ ++/* ++ * FIXME needs to read cid and csd info to determine block size ++ * and other parameters ++ */ ++static int mmc_ready; ++static u32 g_Card_Address_Mode; ++static u32 g_Card_rca; ++ ++enum states { ++ IDLE, ++ READY, ++ IDENT, ++ STBY, ++ TRAN, ++ DATA, ++ RCV, ++ PRG, ++ DIS, ++ BTST, ++ SLP ++}; ++ ++static u32 mmc_cmd(struct mmc_command *cmd, u32 opcode, ++ u32 arg, u32 xfer, u32 fmt, u32 write, ++ u32 crc, u32 cmd_check_en); ++static u32 mmc_acmd(struct mmc_command *cmd, u32 opcode, ++ u32 arg, u32 xfer, u32 fmt, u32 write, ++ u32 crc, u32 cmd_check_en); ++static s32 mmc_decode_cid(struct mmc_card *card); ++static s32 mmc_decode_csd(struct mmc_card *card); ++static s32 sd_voltage_validation(void); ++static s32 mmc_voltage_validation(void); ++static s32 mmc_send_cid(struct mmc_card *card); ++static s32 mmc_send_csd(struct mmc_card *card, u32 u32CardRCA); ++static s32 mmc_select_card(u32 card_rca); ++static s32 mmcsd_check_status(u32 card_rca, u32 timeout, ++ u32 card_state, u32 status_bit); ++static s32 mmc_send_relative_addr(u32 *u32CardRCA); ++static s32 mmc_decode_scr(struct mmc_card *card); ++static s32 mmc_send_scr(struct mmc_card *card); ++static s32 mmc_set_relative_addr(u32 u32CardRCA); ++static s32 mmc_app_set_bus_width(s32 width); ++static s32 mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value); ++static s32 mmc_sd_switch(struct mmc_card *card, s32 mode, s32 group, ++ u8 value, u8 *resp); ++ ++static u32 mmc_cmd(struct mmc_command *cmd, u32 opcode, ++ u32 arg, u32 xfer, u32 fmt, ++ u32 write, u32 crc, u32 cmd_check_en) ++{ ++ struct mmc_command *pCmd = cmd; ++ ++ pCmd->cmd.command = opcode; ++ pCmd->cmd.arg = arg; ++ pCmd->cmd.data_transfer = xfer; ++ pCmd->cmd.response_format = pCmd->resp.format = fmt; ++ pCmd->cmd.data_present = write; ++ pCmd->cmd.crc_check = crc; ++ pCmd->cmd.cmdindex_check = cmd_check_en; ++ ++ if (MMC_READ_MULTIPLE_BLOCK == opcode || \ ++ MMC_WRITE_MULTIPLE_BLOCK == opcode) { ++ pCmd->cmd.block_count_enable_check = ENABLE; ++ pCmd->cmd.multi_single_block = MULTIPLE; ++ } else { ++ pCmd->cmd.block_count_enable_check = DISABLE; ++ pCmd->cmd.multi_single_block = SINGLE; ++ } ++ ++ if (interface_send_cmd_wait_resp(&(pCmd->cmd))) { ++ debug("interface_send_cmd_wait_resp Failed!"); ++ return EPERM; ++ } ++ ++ interface_read_response(&(pCmd->resp)); ++ ++ return 0; ++} ++ ++static u32 mmc_acmd(struct mmc_command *cmd, u32 opcode, ++ u32 arg, u32 xfer, u32 fmt, u32 write, ++ u32 crc, u32 cmd_check_en) ++{ ++ struct mmc_command *pCmd = cmd; ++ struct mmc_command stAPCmd; ++ ++ memset(&stAPCmd, 0, sizeof(struct mmc_command)); ++ ++ /* Send MMC_APP_CMD first to use ACMD */ ++ stAPCmd.cmd.command = MMC_APP_CMD; ++ stAPCmd.cmd.arg = (g_Card_rca << 16); ++ stAPCmd.cmd.data_transfer = READ; ++ stAPCmd.cmd.response_format = stAPCmd.resp.format = RESPONSE_48; ++ stAPCmd.cmd.data_present = DATA_PRESENT_NONE; ++ stAPCmd.cmd.crc_check = ENABLE; ++ stAPCmd.cmd.cmdindex_check = ENABLE; ++ ++ if (interface_send_cmd_wait_resp(&(stAPCmd.cmd))) { ++ debug("Send MMC_APP_CMD Failed! :("); ++ return EPERM; ++ } ++ ++ pCmd->cmd.command = opcode; ++ pCmd->cmd.arg = arg; ++ pCmd->cmd.data_transfer = xfer; ++ pCmd->cmd.response_format = pCmd->resp.format = fmt; ++ pCmd->cmd.data_present = write; ++ pCmd->cmd.crc_check = crc; ++ pCmd->cmd.cmdindex_check = cmd_check_en; ++ ++ if (interface_send_cmd_wait_resp(&(pCmd->cmd))) { ++ debug("interface_send_cmd_wait_resp Failed!, :("); ++ return EPERM; ++ } ++ ++ interface_read_response(&(pCmd->resp)); ++ ++ return 0; ++} ++ ++int ++/****************************************************/ ++mmc_read(ulong src, uchar *dst, int size) ++/****************************************************/ ++{ ++ struct mmc_command stCmd; ++ u32 u32Offset = src; ++ u32 *pu32Dst = (u32 *)dst; ++ s32 s32Rslt = EPERM; ++ s32 s32ReadRslt = 0; ++ u32 u32BlkLen = BLK_LEN; ++ u32 u32MultiBlkNum = 0; ++ ++ if (!mmc_ready) { ++ printf("Please initial the Card first\n"); ++ return EPERM; ++ } ++ ++ if (size == 0) ++ return 0; ++ ++ debug("Entry: mmc_read"); ++ ++ debug("src:%08x dst:%08x size:%d", src, dst, size); ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ if (g_Card_Address_Mode == CARD_SUPPORT_SECT_MODE) { ++ u32BlkLen = 1; ++ u32Offset /= BLK_LEN; ++ } ++ ++ u32MultiBlkNum = (size % BLK_LEN) ? ((size / BLK_LEN) + 1) \ ++ : (size / BLK_LEN); ++ ++ if (mmcsd_check_status(g_Card_rca, 96, TRAN, R1_ERROR)) { ++ debug("Can't wait for TRAN state! :(\n"); ++ return EPERM; ++ } ++ ++ interface_config_block_info(BLK_LEN, u32MultiBlkNum, \ ++ (u32)0x00000080); ++ ++ s32Rslt = mmc_cmd(&stCmd, ++ ((u32MultiBlkNum > 1) ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK), ++ u32Offset, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT, ++ ENABLE, ++ ENABLE); ++ ++ if (s32Rslt) { ++ debug("Send MMC_READ_MULTIPLE_BLOCK Failed! :(\n"); ++ return EPERM; ++ } ++ ++ s32Rslt = interface_data_read((u32 *)pu32Dst, BLK_LEN * u32MultiBlkNum); ++ ++ if (s32Rslt) { ++ debug("interface_data_read Failed! :(\n"); ++ return EPERM; ++ } ++ ++ if (u32MultiBlkNum > 1) { ++ s32Rslt = mmc_cmd(&stCmd, ++ MMC_STOP_TRANSMISSION, ++ 0, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ ENABLE); ++ ++ if (s32Rslt) { ++ debug("Send MMC_STOP_TRANSMISSION Failed! :(\n"); ++ return EPERM; ++ } ++ } ++ ++ debug("mmc_read succeed! :)"); ++ ++ debug("Exit: mmc_read"); ++ ++ return s32ReadRslt; ++} ++ ++int ++/****************************************************/ ++mmc_write(uchar *src, ulong dst, int size) ++/****************************************************/ ++{ ++ struct mmc_command stCmd; ++ u32 u32Offset = dst; ++ s32 s32Rslt = EPERM; ++ s32 s32WriteRslt = 0; ++ u32 u32BlkLen = BLK_LEN; ++ u32 *pu32Src = (u32 *)src; ++ u32 u32MultiBlkNum = 0; ++ ++ debug("Entry: mmc_write"); ++ ++ debug("src:%08x dst:%08x size:%d", src, dst, size); ++ ++ if (!mmc_ready) { ++ printf("Please initial the Card first\n"); ++ return -1; ++ } ++ ++ if (size == 0) ++ return 0; ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ if (g_Card_Address_Mode == CARD_SUPPORT_SECT_MODE) { ++ u32BlkLen = 1; ++ u32Offset /= BLK_LEN; ++ } ++ ++ u32MultiBlkNum = (size % BLK_LEN) ? ((size / BLK_LEN) + 1) \ ++ : (size / BLK_LEN); ++ ++ if (mmcsd_check_status(g_Card_rca, 96, TRAN, R1_ERROR)) { ++ debug("Can't wait for TRAN state! :(\n"); ++ return EPERM; ++ } ++ ++ interface_config_block_info(BLK_LEN, u32MultiBlkNum, \ ++ (u32)0x00800000); ++ ++ s32Rslt = mmc_cmd(&stCmd, ++ ((u32MultiBlkNum > 1) ? MMC_WRITE_MULTIPLE_BLOCK : MMC_WRITE_BLOCK), ++ u32Offset, ++ WRITE, ++ RESPONSE_48, ++ DATA_PRESENT, ++ ENABLE, ++ ENABLE); ++ ++ if (s32Rslt) { ++ debug("Send MMC_WRITE_BLOCK Failed! :("); ++ return EPERM; ++ } ++ ++ s32Rslt = interface_data_write((u32 *)pu32Src, ++ BLK_LEN * u32MultiBlkNum); ++ ++ if (s32Rslt) { ++ debug("interface_data_read Failed! :("); ++ return EPERM; ++ } ++ ++ if (u32MultiBlkNum > 1) { ++ s32Rslt = mmc_cmd(&stCmd, ++ MMC_STOP_TRANSMISSION, ++ 0, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ ENABLE); ++ ++ if (s32Rslt) { ++ debug("Send MMC_STOP_TRANSMISSION Failed! :("); ++ return EPERM; ++ } ++ } ++ ++ debug("mmc_write succeed! :)"); ++ ++ debug("Exit: mmc_write"); ++ ++ return s32WriteRslt; ++} ++ ++ulong ++/****************************************************/ ++mmc_bread(int dev, ulong blknr, lbaint_t blkcnt, void *dst) ++/****************************************************/ ++{ ++ int mmc_block_size = BLK_LEN; ++ ulong src = blknr * mmc_block_size + CONFIG_MMC_BASE; ++ ++ if (mmc_read(src, (uchar *)dst, blkcnt * mmc_block_size)) ++ return 0; ++ else ++ return blkcnt; ++} ++ ++ulong ++/****************************************************/ ++mmc_bwrite(int dev, ulong blknr, lbaint_t blkcnt, const void *src) ++/****************************************************/ ++{ ++ int mmc_block_size = BLK_LEN; ++ ulong dst = blknr * mmc_block_size + CONFIG_MMC_BASE; ++ ++ if (mmc_write((uchar *)src, dst, blkcnt * mmc_block_size)) ++ return 0; ++ else ++ return blkcnt; ++} ++ ++#define UNSTUFF_BITS(resp, start, size) \ ++ ({ \ ++ const int __size = size; \ ++ const uint32_t __mask = (__size < 32 ? 1 << __size : 0) - 1; \ ++ const int32_t __off = 3 - ((start) / 32); \ ++ const int32_t __shft = (start) & 31; \ ++ uint32_t __res; \ ++ \ ++ __res = resp[__off] >> __shft; \ ++ if (__size + __shft > 32) \ ++ __res |= resp[__off-1] << ((32 - __shft) % 32); \ ++ __res & __mask; \ ++ }) ++ ++static const unsigned int tran_exp[] = { ++ 10000, 100000, 1000000, 10000000, ++ 0, 0, 0, 0 ++}; ++ ++static const unsigned char tran_mant[] = { ++ 0, 10, 12, 13, 15, 20, 25, 30, ++ 35, 40, 45, 50, 55, 60, 70, 80, ++}; ++ ++static const unsigned int tacc_exp[] = { ++ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, ++}; ++ ++static const unsigned int tacc_mant[] = { ++ 0, 10, 12, 13, 15, 20, 25, 30, ++ 35, 40, 45, 50, 55, 60, 70, 80, ++}; ++ ++static s32 mmc_set_blk_len(u32 len) ++{ ++ s32 s32Rslt = 0; ++ struct mmc_command stCmd; ++ ++ debug("Entry: mmc_set_blk_len"); ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ s32Rslt = mmc_cmd(&stCmd, ++ MMC_SET_BLOCKLEN, ++ BLK_LEN, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ ENABLE); ++ ++ if (s32Rslt) { ++ debug("Send MMC_SET_BLOCKLEN Failed! :("); ++ return EPERM; ++ } ++ ++ debug("Exit: mmc_set_blk_len"); ++ ++ return s32Rslt; ++} ++ ++/* ++ * Given the decoded CSD structure, decode the raw CID to our CID structure. ++ */ ++static s32 mmc_decode_cid(struct mmc_card *card) ++{ ++ u32 *resp = card->raw_cid; ++ ++ debug("Entry: mmc_decode_cid"); ++ ++ if (!card) { ++ debug("NULL card pointer!"); ++ return EPERM; ++ } ++ ++ memset(&card->cid, 0, sizeof(struct mmc_cid)); ++ ++ switch (card->type) { ++ case MMC_TYPE_MMC: ++ debug("MMC Card!"); ++ /* ++ * The selection of the format here is based upon published ++ * specs from sandisk and from what people have reported. ++ */ ++ switch (card->csd.mmca_vsn) { ++ case 0: /* MMC v1.0 - v1.2 */ ++ case 1: /* MMC v1.4 */ ++ card->cid.manfid = \ ++ UNSTUFF_BITS(resp, 104, 24); ++ card->cid.prod_name[0] = \ ++ UNSTUFF_BITS(resp, 96, 8); ++ card->cid.prod_name[1] = \ ++ UNSTUFF_BITS(resp, 88, 8); ++ card->cid.prod_name[2] = \ ++ UNSTUFF_BITS(resp, 80, 8); ++ card->cid.prod_name[3] = \ ++ UNSTUFF_BITS(resp, 72, 8); ++ card->cid.prod_name[4] = \ ++ UNSTUFF_BITS(resp, 64, 8); ++ card->cid.prod_name[5] = \ ++ UNSTUFF_BITS(resp, 56, 8); ++ card->cid.prod_name[6] = \ ++ UNSTUFF_BITS(resp, 48, 8); ++ card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4); ++ card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4); ++ card->cid.serial = UNSTUFF_BITS(resp, 16, 24); ++ card->cid.month = UNSTUFF_BITS(resp, 12, 4); ++ card->cid.year = \ ++ UNSTUFF_BITS(resp, 8, 4) + 1997; ++ ++ sprintf((char *)mmc_dev.vendor, ++ "Man %08x \"%c%c%c%c%c%c%c\" Date %02u/%04u", ++ card->cid.manfid, ++ card->cid.prod_name[0], ++ card->cid.prod_name[1], ++ card->cid.prod_name[2], ++ card->cid.prod_name[3], ++ card->cid.prod_name[4], ++ card->cid.prod_name[5], ++ card->cid.prod_name[6], ++ card->cid.month, ++ card->cid.year); ++ sprintf((char *)mmc_dev.revision, "%d.%d", ++ card->cid.hwrev, ++ card->cid.fwrev); ++ sprintf((char *)mmc_dev.product, "%u", ++ card->cid.serial); ++ break; ++ case 2: /* MMC v2.0 - v2.2 */ ++ case 3: /* MMC v3.1 - v3.3 */ ++ case 4: /* MMC v4 */ ++ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); ++ card->cid.oemid.mmc_id = \ ++ UNSTUFF_BITS(resp, 104, 16); ++ card->cid.prod_name[0] = \ ++ UNSTUFF_BITS(resp, 96, 8); ++ card->cid.prod_name[1] = \ ++ UNSTUFF_BITS(resp, 88, 8); ++ card->cid.prod_name[2] = \ ++ UNSTUFF_BITS(resp, 80, 8); ++ card->cid.prod_name[3] = \ ++ UNSTUFF_BITS(resp, 72, 8); ++ card->cid.prod_name[4] = \ ++ UNSTUFF_BITS(resp, 64, 8); ++ card->cid.prod_name[5] = \ ++ UNSTUFF_BITS(resp, 56, 8); ++ card->cid.serial = UNSTUFF_BITS(resp, 16, 32); ++ card->cid.month = UNSTUFF_BITS(resp, 12, 4); ++ card->cid.year = \ ++ UNSTUFF_BITS(resp, 8, 4) + 1997; ++ ++ sprintf((char *)mmc_dev.vendor, ++ "Man %02x OEM %04x \"%c%c%c%c%c%c\" Date %02u/%04u", ++ card->cid.manfid, ++ card->cid.oemid.mmc_id, ++ card->cid.prod_name[0], ++ card->cid.prod_name[1], ++ card->cid.prod_name[2], ++ card->cid.prod_name[3], ++ card->cid.prod_name[4], ++ card->cid.prod_name[5], ++ card->cid.month, ++ card->cid.year); ++ sprintf((char *)mmc_dev.product, "%u", ++ card->cid.serial); ++ sprintf((char *)mmc_dev.revision, "N/A"); ++ break; ++ default: ++ printf("MMC card has unknown MMCA version %d\n", ++ card->csd.mmca_vsn); ++ return EPERM; ++ } ++ break; ++ ++ case MMC_TYPE_SD: ++ debug("SD Card!"); ++ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); ++ card->cid.oemid.sd_id[0] = UNSTUFF_BITS(resp, 112, 8); ++ card->cid.oemid.sd_id[1] = UNSTUFF_BITS(resp, 104, 8); ++ card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); ++ card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); ++ card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); ++ card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); ++ card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); ++ card->cid.hwrev = UNSTUFF_BITS(resp, 60, 4); ++ card->cid.fwrev = UNSTUFF_BITS(resp, 56, 4); ++ card->cid.serial = UNSTUFF_BITS(resp, 24, 32); ++ card->cid.year = UNSTUFF_BITS(resp, 12, 8); ++ card->cid.month = UNSTUFF_BITS(resp, 8, 4); ++ card->cid.year += 2000; /* SD cards year offset */ ++ ++ sprintf((char *)mmc_dev.vendor, ++ "Man %02x OEM %c%c \"%c%c%c%c%c\" Date %02u/%04u", ++ card->cid.manfid, ++ card->cid.oemid.sd_id[0], ++ card->cid.oemid.sd_id[1], ++ card->cid.prod_name[0], ++ card->cid.prod_name[1], ++ card->cid.prod_name[2], ++ card->cid.prod_name[3], ++ card->cid.prod_name[4], ++ card->cid.month, ++ card->cid.year); ++ sprintf((char *)mmc_dev.revision, "%d.%d", ++ card->cid.hwrev, card->cid.fwrev); ++ sprintf((char *)mmc_dev.product, "%u", ++ card->cid.serial); ++ break; ++ ++ default: ++ printf("unknown card type!"); ++ return EPERM; ++ } ++ ++ printf("%s card.\nVendor: %s\nProduct: %s\nRevision: %s\n", ++ (IF_TYPE_SD == mmc_dev.if_type) ? "SD" : "MMC", mmc_dev.vendor, ++ mmc_dev.product, mmc_dev.revision); ++ ++ debug("Exit: mmc_decode_cid"); ++ ++ return 0; ++} ++ ++/* ++ * Given a 128-bit response, decode to our card CSD structure. ++ */ ++static s32 mmc_decode_csd(struct mmc_card *card) ++{ ++ struct mmc_csd *csd = &card->csd; ++ u32 e, m, csd_struct; ++ u32 *resp = card->raw_csd; ++ ++ debug("Entry: mmc_decode_csd"); ++ ++ if (!card) { ++ debug("NULL card pointer!"); ++ return EPERM; ++ } ++ ++ switch (card->type) { ++ case MMC_TYPE_MMC: ++ /* ++ * We only understand CSD structure v1.1 and v1.2. ++ * v1.2 has extra information in bits 15, 11 and 10. ++ */ ++ csd_struct = UNSTUFF_BITS(resp, 126, 2); ++ if (csd_struct != 1 && csd_struct != 2) { ++ printf("unrecognised CSD structure version %d\n", ++ csd_struct); ++ return EPERM; ++ } ++ ++ csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4); ++ m = UNSTUFF_BITS(resp, 115, 4); ++ e = UNSTUFF_BITS(resp, 112, 3); ++ csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; ++ csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; ++ ++ m = UNSTUFF_BITS(resp, 99, 4); ++ e = UNSTUFF_BITS(resp, 96, 3); ++ csd->max_dtr = tran_exp[e] * tran_mant[m]; ++ csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); ++ ++ e = UNSTUFF_BITS(resp, 47, 3); ++ m = UNSTUFF_BITS(resp, 62, 12); ++ csd->capacity = (1 + m) << (e + 2); ++ ++ csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); ++ csd->read_partial = UNSTUFF_BITS(resp, 79, 1); ++ csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); ++ csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); ++ csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); ++ csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); ++ csd->write_partial = UNSTUFF_BITS(resp, 21, 1); ++ ++ mmc_dev.if_type = IF_TYPE_MMC; ++ ++ mmc_dev.lba = csd->capacity; ++ mmc_dev.blksz = 1 << csd->read_blkbits; ++ mmc_dev.part_type = PART_TYPE_DOS; ++ mmc_dev.dev = 0; ++ mmc_dev.lun = 0; ++ mmc_dev.type = DEV_TYPE_HARDDISK; ++ mmc_dev.removable = 0; ++ mmc_dev.block_read = mmc_bread; ++ mmc_dev.block_write = mmc_bwrite; ++ ++ break; ++ ++ case MMC_TYPE_SD: ++ csd_struct = UNSTUFF_BITS(resp, 126, 2); ++ ++ switch (csd_struct) { ++ case 0: ++ m = UNSTUFF_BITS(resp, 115, 4); ++ e = UNSTUFF_BITS(resp, 112, 3); ++ csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; ++ csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; ++ ++ m = UNSTUFF_BITS(resp, 99, 4); ++ e = UNSTUFF_BITS(resp, 96, 3); ++ csd->max_dtr = tran_exp[e] * tran_mant[m]; ++ csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); ++ ++ e = UNSTUFF_BITS(resp, 47, 3); ++ m = UNSTUFF_BITS(resp, 62, 12); ++ csd->capacity = (1 + m) << (e + 2); ++ ++ csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); ++ csd->read_partial = UNSTUFF_BITS(resp, 79, 1); ++ csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); ++ csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); ++ csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); ++ csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); ++ csd->write_partial = UNSTUFF_BITS(resp, 21, 1); ++ ++ mmc_dev.if_type = IF_TYPE_SD; ++ ++ mmc_dev.lba = csd->capacity; ++ mmc_dev.blksz = 1 << csd->read_blkbits; ++ mmc_dev.part_type = PART_TYPE_DOS; ++ mmc_dev.dev = 0; ++ mmc_dev.lun = 0; ++ mmc_dev.type = DEV_TYPE_HARDDISK; ++ mmc_dev.removable = 0; ++ mmc_dev.block_read = mmc_bread; ++ mmc_dev.block_write = mmc_bwrite; ++ ++ break; ++ case 1: ++ /* ++ * This is a block-addressed SDHC card. Most ++ * interesting fields are unused and have fixed ++ * values. To avoid getting tripped by buggy cards, ++ * we assume those fixed values ourselves. ++ */ ++ mmc_card_set_blockaddr(card); ++ ++ csd->tacc_ns = 0; /* Unused */ ++ csd->tacc_clks = 0; /* Unused */ ++ ++ m = UNSTUFF_BITS(resp, 99, 4); ++ e = UNSTUFF_BITS(resp, 96, 3); ++ csd->max_dtr = tran_exp[e] * tran_mant[m]; ++ csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); ++ ++ m = UNSTUFF_BITS(resp, 48, 22); ++ csd->capacity = (1 + m) << 10; ++ ++ csd->read_blkbits = 9; ++ csd->read_partial = 0; ++ csd->write_misalign = 0; ++ csd->read_misalign = 0; ++ csd->r2w_factor = 4; /* Unused */ ++ csd->write_blkbits = 9; ++ csd->write_partial = 0; ++ ++ mmc_dev.if_type = IF_TYPE_SD; ++ ++ mmc_dev.lba = csd->capacity; ++ mmc_dev.blksz = 512; ++ mmc_dev.part_type = PART_TYPE_DOS; ++ mmc_dev.dev = 0; ++ mmc_dev.lun = 0; ++ mmc_dev.type = DEV_TYPE_HARDDISK; ++ mmc_dev.removable = 0; ++ mmc_dev.block_read = mmc_bread; ++ ++ break; ++ default: ++ printf("unrecognised CSD structure version %d\n", ++ csd_struct); ++ return EPERM; ++ } ++ break; ++ ++ default: ++ printf("unknown card type!"); ++ return EPERM; ++ } ++ ++ debug("Exit: mmc_decode_csd"); ++ ++ return 0; ++} ++ ++/* ++ * Do SD voltage validation. ++ */ ++static s32 sd_voltage_validation(void) ++{ ++ struct mmc_command stCmd; ++ u32 u32OcrVal = 0; ++ u32 u32VoltageValidation = EPERM; ++ s32 s32Rslt = EPERM; ++ s32 s32Retries = 0; ++ /* Supported arguments for CMD8 */ ++ const u32 sd_if_cmd_arg[SD_IF_CMD_ARG_COUNT] = { ++ SD_IF_HV_COND_ARG, ++ SD_IF_LV_COND_ARG }; ++ const u32 sd_ocr_value[SD_OCR_VALUE_COUNT] = { ++ SD_OCR_VALUE_HV_HC, ++ SD_OCR_VALUE_LV_HC, ++ SD_OCR_VALUE_HV_LC }; ++ ++ debug("Entry: sd_voltage_validation"); ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ for (s32Retries = 0; s32Retries < SD_IF_CMD_ARG_COUNT; ++s32Retries) { ++ /* Configure CMD55 for SD card */ ++ /* This command expects defualt RCA 0x0000 as argument.*/ ++ s32Rslt = mmc_cmd(&stCmd, ++ SD_SEND_IF_COND, ++ sd_if_cmd_arg[s32Retries], ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ ENABLE); ++ ++ if (!s32Rslt) { ++ if (sd_if_cmd_arg[s32Retries] == \ ++ (stCmd.resp.cmd_rsp0 & sd_if_cmd_arg[s32Retries])) { ++ u32OcrVal = sd_ocr_value[s32Retries]; ++ } else { ++ u32OcrVal = 0; ++ } ++ break; ++ } ++ } ++ ++ if (s32Rslt) { ++ debug("Card is of SD-1.x spec with LC"); ++ u32OcrVal = SD_OCR_VALUE_HV_LC; ++ } ++ ++ for (s32Retries = RETRY_TIMEOUT; s32Retries; --s32Retries) { ++ /* Configure ACMD41 for SD card */ ++ /* This command expects operating voltage range as argument.*/ ++ s32Rslt = mmc_acmd(&stCmd, ++ SD_APP_OP_COND, ++ u32OcrVal, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ DISABLE, ++ DISABLE); ++ ++ /* Issue ACMD41 to SD Memory card to determine OCR value */ ++ if (s32Rslt == EPERM) { ++ debug("Send SD_APP_OP_COND Failed! :("); ++ break; ++ } ++ ++ /* Obtain OCR value from the response buffer ++ */ ++ u32OcrVal = stCmd.resp.cmd_rsp0; ++ ++ /* Check if card busy bit is cleared or not */ ++ if (!(u32OcrVal & MMC_CARD_BUSY)) ++ continue; ++ ++ u32VoltageValidation = 0; ++ ++ /* Check if volatge lies in range or not*/ ++ g_Card_Address_Mode = (u32OcrVal & 0x40000000) ? \ ++ CARD_SUPPORT_SECT_MODE : CARD_SUPPORT_BYTE_MODE; ++ break; ++ } ++ ++ debug("Exit: sd_voltage_validation"); ++ ++ return u32VoltageValidation; ++} ++ ++/* ++ * Do SD voltage validation. ++ */ ++static s32 mmc_voltage_validation(void) ++{ ++ struct mmc_command stCmd; ++ u32 u32Respones = 0; ++ u32 u32VoltageValidation = EPERM; ++ s32 s32Rslt = EPERM; ++ s32 s32Retries = 0; ++ ++ debug("Entry: mmc_voltage_validation"); ++ ++ for (s32Retries = RETRY_TIMEOUT; s32Retries; --s32Retries) { ++ s32Rslt = mmc_cmd(&stCmd, ++ MMC_SEND_OP_COND, ++ (u32)0x40FF8000, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ DISABLE, ++ DISABLE); ++ ++ /* Issue CMD55 to SD Memory card*/ ++ if (s32Rslt == EPERM) { ++ debug("Send MMC_SEND_OP_COND Failed! :("); ++ break; ++ } ++ ++ /* Obtain OCR value from the response buffer ++ */ ++ u32Respones = stCmd.resp.cmd_rsp0; ++ ++ /* Check if card busy bit is cleared or not */ ++ if (!(u32Respones & MMC_CARD_BUSY)) { ++ debug("Card Busy!"); ++ continue; ++ } ++ ++ u32VoltageValidation = 0; ++ ++ /* Check if volatge lies in range or not*/ ++ if (0x40000000 == (u32Respones & 0x60000000)) { ++ debug("Address_mode: SECT_MODE"); ++ g_Card_Address_Mode = CARD_SUPPORT_SECT_MODE; ++ } else { ++ debug("Address_mode: BYTE_MODE"); ++ g_Card_Address_Mode = CARD_SUPPORT_BYTE_MODE; ++ } ++ } ++ ++ debug("mmc_voltage_validation succeed! :)"); ++ ++ debug("Exit: mmc_voltage_validation"); ++ ++ return u32VoltageValidation; ++} ++ ++static s32 mmc_send_cid(struct mmc_card *card) ++{ ++ struct mmc_command stCmd; ++ s32 s32Rslt = EPERM; ++ ++ debug("Entry: mmc_send_cid"); ++ ++ if (!card) { ++ debug("NULL card pointer!"); ++ return EPERM; ++ } ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ s32Rslt = mmc_cmd(&stCmd, ++ MMC_ALL_SEND_CID, ++ 0, ++ READ, ++ RESPONSE_136, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ DISABLE); ++ ++ /* Issue CMD55 to SD Memory card*/ ++ if (s32Rslt) { ++ debug("Send MMC_ALL_SEND_CID Failed! :("); ++ return EPERM; ++ } ++ ++ /* ++ card->raw_cid[0] = stCmd.resp.cmd_rsp0; ++ card->raw_cid[1] = stCmd.resp.cmd_rsp1; ++ card->raw_cid[2] = stCmd.resp.cmd_rsp2; ++ card->raw_cid[3] = stCmd.resp.cmd_rsp3; ++ */ ++ ++ card->raw_cid[0] = (stCmd.resp.cmd_rsp3 << 8) | \ ++ (stCmd.resp.cmd_rsp2 >> 24); ++ card->raw_cid[1] = (stCmd.resp.cmd_rsp2 << 8) | \ ++ (stCmd.resp.cmd_rsp1 >> 24); ++ card->raw_cid[2] = (stCmd.resp.cmd_rsp1 << 8) | \ ++ (stCmd.resp.cmd_rsp0 >> 24); ++ card->raw_cid[3] = stCmd.resp.cmd_rsp0 << 8; ++ ++ debug("mmc_send_cid succeed! :)"); ++ ++ debug("Exit: mmc_send_cid"); ++ ++ return 0; ++} ++ ++static s32 mmc_send_csd(struct mmc_card *card, u32 u32CardRCA) ++{ ++ struct mmc_command stCmd; ++ s32 s32Rslt = EPERM; ++ ++ debug("Entry: mmc_send_csd"); ++ ++ if (!card) { ++ debug("NULL card pointer!"); ++ return s32Rslt; ++ } ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ s32Rslt = mmc_cmd(&stCmd, ++ MMC_SEND_CSD, ++ (u32CardRCA << 16), ++ READ, ++ RESPONSE_136, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ DISABLE); ++ ++ /* Issue CMD55 to SD Memory card*/ ++ if (s32Rslt) { ++ debug("Send MMC_SEND_CSD Failed! :("); ++ return EPERM; ++ } ++ ++ /* ++ card->raw_csd[0] = stCmd.resp.cmd_rsp0; ++ card->raw_csd[1] = stCmd.resp.cmd_rsp1; ++ card->raw_csd[2] = stCmd.resp.cmd_rsp2; ++ card->raw_csd[3] = stCmd.resp.cmd_rsp3; ++ */ ++ ++ card->raw_csd[0] = (stCmd.resp.cmd_rsp3 << 8) | \ ++ (stCmd.resp.cmd_rsp2 >> 24); ++ card->raw_csd[1] = (stCmd.resp.cmd_rsp2 << 8) | \ ++ (stCmd.resp.cmd_rsp1 >> 24); ++ card->raw_csd[2] = (stCmd.resp.cmd_rsp1 << 8) | \ ++ (stCmd.resp.cmd_rsp0 >> 24); ++ card->raw_csd[3] = stCmd.resp.cmd_rsp0 << 8; ++ ++ debug("mmc_send_csd succeed! :)"); ++ ++ debug("Exit: mmc_send_csd"); ++ ++ return 0; ++} ++ ++static s32 mmc_select_card(u32 card_rca) ++{ ++ struct mmc_command stCmd; ++ s32 s32Rslt = EPERM; ++ u32 u32CardAddr = card_rca << 16; ++ ++ debug("Entry: mmcsd_set_data_transfer_mode"); ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ s32Rslt = mmc_cmd(&stCmd, ++ MMC_SELECT_CARD, ++ u32CardAddr, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ ENABLE); ++ if (s32Rslt) { ++ debug("Send MMC_SELECT_CARD Failed! :("); ++ return EPERM; ++ } ++ ++ debug("Exit mmcsd_set_data_transfer_mode"); ++ ++ return mmcsd_check_status(card_rca, 96, TRAN, R1_ERROR); ++} ++ ++static s32 mmcsd_check_status(u32 card_rca, u32 timeout, \ ++ u32 card_state, u32 status_bit) ++{ ++ struct mmc_command stCmd; ++ s32 s32Rslt = EPERM; ++ s32 s32Retries = 0; ++ u32 u32CardAddr = card_rca << 16; ++ s32 s32Status = 1; ++ ++ debug("Entry: mmcsd_check_status"); ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ for (s32Retries = 10; s32Retries; --s32Retries) { ++ ++ udelay(timeout); ++ ++ s32Rslt = mmc_cmd(&stCmd, ++ MMC_SEND_STATUS, ++ u32CardAddr, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ ENABLE); ++ if (s32Rslt) { ++ debug("Send MMC_SEND_STATUS Failed! :("); ++ break; ++ } ++ ++ if (stCmd.resp.cmd_rsp0 & status_bit) { ++ debug("R1 Error! :("); ++ break; ++ } ++ ++ if (R1_CURRENT_STATE(stCmd.resp.cmd_rsp0) == card_state) { ++ debug("Get state! :)"); ++ s32Status = 0; ++ break; ++ } ++ } ++ ++ debug("Exit: mmcsd_check_status"); ++ ++ return s32Status; ++} ++ ++static s32 mmc_send_relative_addr(u32 *u32CardRCA) ++{ ++ struct mmc_command stCmd; ++ s32 s32Status = 1; ++ s32 s32Rslt = EPERM; ++ ++ debug("Entry: mmc_send_relative_addr"); ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ s32Rslt = mmc_cmd(&stCmd, ++ SD_SEND_RELATIVE_ADDR, ++ 0, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ ENABLE); ++ if (s32Rslt) { ++ debug("Send SD_SEND_RELATIVE_ADDR Failed! :("); ++ return s32Status; ++ } ++ ++ *u32CardRCA = (u32)stCmd.resp.cmd_rsp0 >> 16; ++ ++ if (R1_CURRENT_STATE(stCmd.resp.cmd_rsp0) != IDENT) { ++ debug("Invalid R1 State! :("); ++ return s32Status; ++ } ++ ++ debug("Exit: mmc_send_relative_addr"); ++ ++ return 0; ++} ++ ++static s32 mmc_set_relative_addr(u32 u32CardRCA) ++{ ++ struct mmc_command stCmd; ++ s32 s32Rslt = EPERM; ++ ++ debug("Entry: mmc_set_relative_addr"); ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ /* Set RCA */ ++ s32Rslt = mmc_cmd(&stCmd, ++ MMC_SET_RELATIVE_ADDR, ++ (u32CardRCA << 16), ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ ENABLE); ++ if (s32Rslt) { ++ debug("Send MMC_SET_RELATIVE_ADDR Failed! :("); ++ return 1; ++ } ++ ++ if (R1_CURRENT_STATE(stCmd.resp.cmd_rsp0) != IDENT) { ++ debug("Invalid R1 State! :("); ++ return 1; ++ } ++ ++ debug("Exit: mmc_set_relative_addr"); ++ ++ return 0; ++} ++ ++static s32 mmc_send_scr(struct mmc_card *card) ++{ ++ struct mmc_command stCmd; ++ s32 s32Rslt = EPERM; ++ ++ debug("Entry: mmc_app_send_scr"); ++ ++ if (!card) { ++ debug("NULL card pointer!"); ++ return s32Rslt; ++ } ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ s32Rslt = mmc_acmd(&stCmd, ++ SD_APP_SEND_SCR, ++ 0, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ ENABLE); ++ ++ /* Issue CMD55 to SD Memory card*/ ++ if (s32Rslt) { ++ debug("Send SD_APP_SEND_SCR Failed! :("); ++ return EPERM; ++ } ++ ++ card->raw_scr[0] = stCmd.resp.cmd_rsp0; ++ card->raw_scr[1] = stCmd.resp.cmd_rsp1; ++ ++ mmc_decode_scr(card); ++ ++ debug("mmc_send_scr succeed! :)"); ++ ++ debug("Exit: mmc_app_send_scr"); ++ ++ return 0; ++} ++ ++static s32 mmc_decode_scr(struct mmc_card *card) ++{ ++ struct sd_scr *scr = &card->scr; ++ unsigned int scr_struct; ++ u32 resp[4]; ++ ++ resp[3] = card->raw_scr[1]; ++ resp[2] = card->raw_scr[0]; ++ ++ scr_struct = UNSTUFF_BITS(resp, 60, 4); ++ if (scr_struct != 0) { ++ printf("Unrecognised SCR structure version %d\n", scr_struct); ++ return 1; ++ } ++ ++ scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4); ++ scr->bus_widths = UNSTUFF_BITS(resp, 48, 4); ++ ++ return 0; ++} ++ ++static s32 mmc_read_switch(struct mmc_card *card) ++{ ++ u8 status[64] = { 0 }; ++ ++ if (card->scr.sda_vsn < SCR_SPEC_VER_1) ++ return 0; ++ ++ if (!(card->csd.cmdclass & CCC_SWITCH)) { ++ printf("card lacks mandatory switch " ++ "function, performance might suffer.\n"); ++ return 0; ++ } ++ ++ if (mmc_sd_switch(card, 0, 0, 1, status)) { ++ /* ++ * We all hosts that cannot perform the command ++ * to fail more gracefully ++ */ ++ printf("problem reading switch " ++ "capabilities, performance might suffer.\n"); ++ ++ return 1; ++ } ++ ++ if (status[13] & 0x02) ++ card->sw_caps.hs_max_dtr = 50000000; ++ ++ return 0; ++} ++ ++static s32 mmc_sd_switch(struct mmc_card *card, s32 mode, s32 group, ++ u8 value, u8 *resp) ++{ ++ struct mmc_command stCmd; ++ s32 s32Rslt = EPERM; ++ u32 u32Args = 0; ++ ++ debug("Entry: mmc_sd_switch"); ++ ++ if (!card) { ++ debug("NULL card pointer!"); ++ return s32Rslt; ++ } ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ u32Args = mode << 31 | 0x00FFFFFF; ++ u32Args &= ~(0xF << (group * 4)); ++ u32Args |= value << (group * 4); ++ ++ s32Rslt = mmc_acmd(&stCmd, ++ SD_SWITCH, ++ u32Args, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT, ++ ENABLE, ++ ENABLE); ++ ++ /* Issue CMD55 to SD Memory card*/ ++ if (s32Rslt) { ++ debug("Send SD_SWITCH Failed! :("); ++ return EPERM; ++ } ++ ++ return 0; ++} ++ ++static s32 mmc_app_set_bus_width(s32 width) ++{ ++ struct mmc_command stCmd; ++ s32 s32Rslt = EPERM; ++ ++ debug("Entry: mmc_app_set_bus_width"); ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ s32Rslt = mmc_acmd(&stCmd, ++ SD_APP_SET_BUS_WIDTH, ++ width, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ ENABLE); ++ ++ if (s32Rslt) { ++ debug("Send SD_APP_SET_BUS_WIDTH Failed! :("); ++ return EPERM; ++ } ++ ++ debug("Exit: mmc_app_set_bus_width"); ++ ++ return 0; ++} ++ ++static s32 mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value) ++{ ++ struct mmc_command stCmd; ++ s32 s32Rslt = EPERM; ++ u32 u32Args = 0; ++ ++ debug("Entry: mmc_sd_switch"); ++ ++ if (!card) { ++ debug("NULL card pointer!"); ++ return s32Rslt; ++ } ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ ++ u32Args = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | ++ (index << 16) | (value << 8) | set; ++ ++ s32Rslt = mmc_cmd(&stCmd, ++ MMC_SWITCH, ++ u32Args, ++ READ, ++ RESPONSE_48, ++ DATA_PRESENT_NONE, ++ ENABLE, ++ ENABLE); ++ ++ /* Issue CMD55 to SD Memory card*/ ++ if (s32Rslt) { ++ debug("Send SD_SWITCH Failed! :("); ++ return EPERM; ++ } ++ ++ debug("Entry: mmc_sd_switch"); ++ ++ return 0; ++} ++ ++ ++static s32 mmc_init_sd(struct mmc_card *card) ++{ ++ u32 u32CardRCA = 0; ++ ++ if (mmc_send_cid(card)) { ++ debug("mmcsd_get_cid Failed! :("); ++ return 1; ++ } ++ ++ if (mmc_send_relative_addr(&u32CardRCA)) { ++ debug("sd_send_relative_addr Failed! :("); ++ return 1; ++ } ++ ++ if (mmc_send_csd(card, u32CardRCA)) { ++ debug("mmcsd_get_csd Failed! :("); ++ return 1; ++ } ++ ++ g_Card_rca = u32CardRCA; ++ ++ mmc_decode_csd(card); ++ mmc_decode_cid(card); ++ ++ /* Enable operating frequency */ ++ interface_configure_clock(OPERATING_FREQ); ++ ++ if (mmc_select_card(u32CardRCA)) { ++ debug("mmc_select_card Failed! :("); ++ return 1; ++ } ++ ++ if (mmcsd_check_status(g_Card_rca, 96, TRAN, R1_ERROR)) { ++ debug("Can't wait for TRAN state! :(\n"); ++ return EPERM; ++ } ++ ++ if (mmc_set_blk_len(BLK_LEN)) { ++ debug("mmc_set_blk_len Failed! :("); ++ return EPERM; ++ } ++ ++ /* ++ if (mmc_send_scr(card)) { ++ debug("mmc_send_scr Failed! :("); ++ return 1; ++ } ++ */ ++ ++ if (mmc_app_set_bus_width(SD_BUS_WIDTH_4)) { ++ /* Try to set 1 bit mode */ ++ if (mmc_app_set_bus_width(SD_BUS_WIDTH_1)) { ++ debug("mmc_app_set_bus_width Failed"); ++ return EPERM; ++ } ++ interface_set_bus_width(SD_BUS_WIDTH_1); ++ } else { ++ interface_set_bus_width(SD_BUS_WIDTH_4); ++ } ++ ++ return 0; ++} ++ ++static s32 mmc_init_mmc(struct mmc_card *card) ++{ ++ u32 u32CardRCA = 1; ++ ++ /* mmc init */ ++ if (mmc_send_cid(card)) { ++ debug("mmcsd_get_cid Failed! :("); ++ return 1; ++ } ++ ++ /* Set RCA */ ++ if (mmc_set_relative_addr(u32CardRCA)) { ++ debug("mmc_set_relative_addr Failed! :("); ++ return 1; ++ } ++ ++ if (mmc_send_csd(card, u32CardRCA)) { ++ debug("mmcsd_get_csd Failed! :("); ++ return 1; ++ } ++ ++ g_Card_rca = u32CardRCA; ++ ++ mmc_decode_csd(card); ++ mmc_decode_cid(card); ++ ++ /* Enable operating frequency */ ++ interface_configure_clock(OPERATING_FREQ); ++ ++ if (mmc_select_card(u32CardRCA)) { ++ debug("mmc_select_card Failed! :("); ++ return 1; ++ } ++ ++ if (mmcsd_check_status(g_Card_rca, 96, TRAN, R1_ERROR)) { ++ debug("Can't wait for TRAN state! :(\n"); ++ return EPERM; ++ } ++ ++ if (mmc_set_blk_len(BLK_LEN)) { ++ debug("mmc_set_blk_len Failed! :("); ++ return 1; ++ } ++ ++ if (card->csd.mmca_vsn >= CSD_SPEC_VER_4) { ++ if (mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, ++ EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4)) { ++ debug("Switch card to 4 bits failed! :(\n"); ++ return 1; ++ } ++ interface_set_bus_width(MMC_BUS_WIDTH_4); ++ } ++ ++ return 0; ++} ++ ++int ++/****************************************************/ ++mmc_init(int verbose) ++/****************************************************/ ++{ ++ struct mmc_command stCmd; ++ s32 s32InitStatus = -1; ++ struct mmc_card card; ++ s32 s32Rslt = EPERM; ++ ++ debug("Entry: mmc_init"); ++ ++ memset(&stCmd, 0, sizeof(struct mmc_command)); ++ memset(&card, 0, sizeof(struct mmc_card)); ++ ++ g_Card_rca = 0; ++ ++ /* Reset device interface type */ ++ mmc_dev.if_type = IF_TYPE_UNKNOWN; ++ ++ /* initialize Interface Controller */ ++ sdhc_init(); ++ ++ /* Software reset to Interface Controller */ ++ if (interface_reset()) { ++ debug("interface_reset failed! :("); ++ return s32InitStatus; ++ } ++ ++ /* Enable Identification Frequency */ ++ interface_configure_clock(IDENTIFICATION_FREQ); ++ ++ /* Software reset */ ++ s32Rslt = mmc_cmd(&stCmd, ++ MMC_GO_IDLE_STATE, ++ 0, ++ READ, ++ RESPONSE_NONE, ++ DATA_PRESENT_NONE, ++ DISABLE, ++ DISABLE); ++ ++ if (!sd_voltage_validation()) { ++ debug("SD Card Detected!"); ++ card.type = MMC_TYPE_SD; ++ ++ /* SD init */ ++ if (mmc_init_sd(&card)) { ++ debug("mmc_init_sd Failed! :("); ++ return s32InitStatus; ++ } ++ ++ s32InitStatus = 0; ++ mmc_ready = 1; ++ } else if (!mmc_voltage_validation()) { ++ debug("MMC Card Detected!"); ++ card.type = MMC_TYPE_MMC; ++ ++ /* mmc init */ ++ if (mmc_init_mmc(&card)) { ++ debug("mmc_init_mmc Failed! :("); ++ return s32InitStatus; ++ } ++ ++ s32InitStatus = 0; ++ mmc_ready = 1; ++ } else { ++ mmc_ready = 0; ++ return s32InitStatus; ++ } ++ ++ fat_register_device(&mmc_dev, 1); /* partitions start counting with 1 */ ++ ++ debug("Exit: mmc_init"); ++ ++ return s32InitStatus; ++} ++ ++int mmc_ident(block_dev_desc_t *dev) ++{ ++ return 0; ++} ++ ++int mmc2info(ulong addr) ++{ ++ /* Not avaiable for cp command now. */ ++ return 0; ++ ++ if (addr >= CONFIG_MMC_BASE ++ && addr < CONFIG_MMC_BASE + (mmc_dev.lba * mmc_dev.blksz)) { ++ return 1; ++ } ++ return 0; ++ ++} ++ ++#endif /* CONFIG_MMC */ ++ +diff --git a/include/asm-arm/arch-mx35/mmc.h b/include/asm-arm/arch-mx35/mmc.h +new file mode 100644 +index 0000000..8699f40 +--- /dev/null ++++ b/include/asm-arm/arch-mx35/mmc.h +@@ -0,0 +1,16 @@ ++/* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * linux/drivers/mmc/mmc.h ++ * ++ * Author: Vladimir Shebordaev, Igor Oblakov ++ * Copyright: MontaVista Software Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++#ifndef __MMC_MX35_3STACK_H__ ++#define __MMC_MX35_3STACK_H__ ++ ++#endif /* __MMC_MX35_3STACK_H__ */ +diff --git a/include/asm-arm/arch-mx35/mx35.h b/include/asm-arm/arch-mx35/mx35.h +index c96092c..9d1ae54 100644 +--- a/include/asm-arm/arch-mx35/mx35.h ++++ b/include/asm-arm/arch-mx35/mx35.h +@@ -69,6 +69,9 @@ + #define EPIT1_BASE_ADDR 0x53F94000 + #define EPIT2_BASE_ADDR 0x53F98000 + #define GPIO3_BASE_ADDR 0x53FA4000 ++#define MMC_SDHC1_BASE_ADDR 0x53FB4000 ++#define MMC_SDHC2_BASE_ADDR 0x53FB8000 ++#define MMC_SDHC3_BASE_ADDR 0x53FBC000 + #define IPU_CTRL_BASE_ADDR 0x53FC0000 + #define GPIO3_BASE_ADDR 0x53FA4000 + #define GPIO1_BASE_ADDR 0x53FCC000 +@@ -249,6 +252,7 @@ MXC_UART_CLK, + extern unsigned int mxc_get_clock(enum mxc_clock clk); + extern unsigned int get_board_rev(void); + extern int is_soc_rev(int rev); ++extern int sdhc_init(void); + + #define fixup_before_linux \ + { \ +diff --git a/include/asm-arm/arch-mx35/sdhc.h b/include/asm-arm/arch-mx35/sdhc.h +new file mode 100644 +index 0000000..5514ad4 +--- /dev/null ++++ b/include/asm-arm/arch-mx35/sdhc.h +@@ -0,0 +1,218 @@ ++/* ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 SDHC_H ++#define SDHC_H ++ ++#include ++ ++#define ESDHC_SOFTWARE_RESET_DATA ((u32)0x04000000) ++#define ESDHC_SOFTWARE_RESET_CMD ((u32)0x02000000) ++#define ESDHC_SOFTWARE_RESET ((u32)0x01000000) ++#define ESDHC_CMD_INHIBIT 0x00000003 ++#define ESDHC_SYSCTL_INITA ((u32)0x08000000) ++#define ESDHC_LITTLE_ENDIAN_MODE ((u32)0x00000020) ++#define ESDHC_HW_BIG_ENDIAN_MODE ((u32)0x00000010) ++#define ESDHC_BIG_ENDIAN_MODE ((u32)0x00000000) ++#define ESDHC_ONE_BIT_SUPPORT ((u32)0x00000000) ++#define ESDHC_FOUR_BIT_SUPPORT ((u32)0x00000002) ++#define ESDHC_EIGHT_BIT_SUPPORT ((u32)0x00000004) ++#define ESDHC_CLOCK_ENABLE 0x00000007 ++#define ESDHC_FREQ_MASK 0xffff0007 ++#define ESDHC_SYSCTL_FREQ_MASK ((u32)0x000FFFF0) ++#define ESDHC_SYSCTL_IDENT_FREQ_TO1 ((u32)0x0000800e) ++#define ESDHC_SYSCTL_OPERT_FREQ_TO1 ((u32)0x00000200) ++#define ESDHC_SYSCTL_IDENT_FREQ_TO2 ((u32)0x00002040) ++#define ESDHC_SYSCTL_OPERT_FREQ_TO2 ((u32)0x00000050) ++#define ESDHC_INTERRUPT_ENABLE ((u32)0x007f0133) ++#define ESDHC_CLEAR_INTERRUPT ((u32)0x117f01ff) ++#define ESDHC_SYSCTL_DTOCV_VAL ((u32)0x000E0000) ++#define ESDHC_IRQSTATEN_DTOESEN ((u32)0x00100000) ++#define ESDHC_ENDIAN_MODE_MASK ((u32)0x00000030) ++#define ESDHC_SYSCTRL_RSTC ((u32)0x02000000) ++#define ESDHC_SYSCTRL_RSTD ((u32)0x04000000) ++#define ESDHC_CONFIG_BLOCK 0x00010200 ++#define ESDHC_OPER_TIMEOUT (96 * 100) ++#define ESDHC_ACMD41_TIMEOUT (32000) ++#define ESDHC_CMD1_TIMEOUT (32000) ++#define ESDHC_BLOCK_SHIFT (16) ++#define ESDHC_CARD_INIT_TIMEOUT (64) ++ ++#define ESDHC_SYSCTL_SDCLKEN_MASK ((u32)0x00000008) ++#define ESDHC_PRSSTAT_SDSTB_BIT ((u32)0x00000008) ++#define ESDHC_SYSCTL_INPUT_CLOCK_MASK ((u32)0x00000007) ++ ++#define ESDHC_BUS_WIDTH_MASK ((u32)0x00000006) ++#define ESDHC_DATA_TRANSFER_SHIFT (4) ++#define ESDHC_RESPONSE_FORMAT_SHIFT (16) ++#define ESDHC_DATA_PRESENT_SHIFT (21) ++#define ESDHC_CRC_CHECK_SHIFT (19) ++#define ESDHC_CMD_INDEX_CHECK_SHIFT (20) ++#define ESDHC_CMD_INDEX_SHIFT (24) ++#define ESDHC_BLOCK_COUNT_ENABLE_SHIFT (1) ++#define ESDHC_MULTI_SINGLE_BLOCK_SELECT_SHIFT (5) ++#define BLK_LEN (512) ++#define ESDHC_READ_WATER_MARK_LEVEL_BL_4 ((u32)0x00000001) ++#define ESDHC_READ_WATER_MARK_LEVEL_BL_8 ((u32)0x00000002) ++#define ESDHC_READ_WATER_MARK_LEVEL_BL_16 ((u32)0x00000004) ++#define ESDHC_READ_WATER_MARK_LEVEL_BL_64 ((u32)0x00000010) ++#define ESDHC_READ_WATER_MARK_LEVEL_BL_512 ((u32)0x00000080) ++ ++#define ESDHC_WRITE_WATER_MARK_LEVEL_BL_4 ((u32)0x00010000) ++#define ESDHC_WRITE_WATER_MARK_LEVEL_BL_8 ((u32)0x00020000) ++#define ESDHC_WRITE_WATER_MARK_LEVEL_BL_16 ((u32)0x00040000) ++#define ESDHC_WRITE_WATER_MARK_LEVEL_BL_64 ((u32)0x00100000) ++#define ESDHC_WRITE_WATER_MARK_LEVEL_BL_512 ((u32)0x00800000) ++ ++#define WRITE_READ_WATER_MARK_LEVEL 0x00800080 ++ ++/* Present State register bit masks */ ++#define ESDHC_PRESENT_STATE_CIHB ((u32)0x00000001) ++#define ESDHC_PRESENT_STATE_CDIHB ((u32)0x00000002) ++#define ONE (1) ++#define ESDHC_FIFO_SIZE (128) ++ ++#define ESDHC_STATUS_END_CMD_RESP_MSK ((u32)0x00000001) ++#define ESDHC_STATUS_END_CMD_RESP_TIME_MSK ((u32)0x000F0001) ++#define ESDHC_STATUS_TIME_OUT_RESP_MSK ((u32)0x00010000) ++#define ESDHC_STATUS_RESP_CRC_ERR_MSK ((u32)0x00020000) ++#define ESDHC_STATUS_RESP_CMD_INDEX_ERR_MSK ((u32)0x00080000) ++#define ESDHC_STATUS_BUF_READ_RDY_MSK ((u32)0x00000020) ++#define ESDHC_STATUS_BUF_WRITE_RDY_MSK ((u32)0x00000010) ++#define ESDHC_STATUS_TRANSFER_COMPLETE_MSK ((u32)0x00000002) ++#define ESDHC_STATUS_DATA_RW_MSK ((u32)0x00700002) ++#define ESDHC_STATUS_TRANSFER_COMPLETE_MSK ((u32)0x00000002) ++#define ESDHC_STATUS_TIME_OUT_READ_MASK ((u32)0x00100000) ++#define ESDHC_STATUS_READ_CRC_ERR_MSK ((u32)0x00200000) ++#define ESDHC_STATUS_RESP_CMD_END_BIT_ERR_MSK ((u32)0x00040000) ++#define ESDHC_STATUS_RW_DATA_END_BIT_ERR_MSK ((u32)0x00400000) ++ ++#define ESDHC_STATUS_TIME_OUT_READ (3200) ++#define ESDHC_READ_DATA_TIME_OUT (3200) ++#define ESDHC_WRITE_DATA_TIME_OUT (8000) ++ ++#define ESDHC_CONFIG_BLOCK_512 ((u32)0x00000200) ++#define ESDHC_CONFIG_BLOCK_64 ((u32)0x00000040) ++#define ESDHC_CONFIG_BLOCK_8 ((u32)0x00000008) ++#define ESDHC_CONFIG_BLOCK_4 ((u32)0x00000004) ++ ++#define ESDHC_MAX_BLOCK_COUNT ((u32)0x0000ffff) ++ ++typedef enum { ++ ESDHC1, ++ ESDHC2, ++ ESDHC3 ++} esdhc_num_t; ++ ++typedef enum { ++ WRITE, ++ READ, ++} xfer_type_t; ++ ++typedef enum { ++ RESPONSE_NONE, ++ RESPONSE_136, ++ RESPONSE_48, ++ RESPONSE_48_CHECK_BUSY ++} response_format_t; ++ ++ ++typedef enum { ++ DATA_PRESENT_NONE, ++ DATA_PRESENT ++} data_present_select; ++ ++typedef enum { ++ DISABLE, ++ ENABLE ++} crc_check_enable, cmdindex_check_enable, block_count_enable; ++ ++typedef enum { ++ SINGLE, ++ MULTIPLE ++} multi_single_block_select; ++ ++typedef struct { ++ u32 command; ++ u32 arg; ++ xfer_type_t data_transfer; ++ response_format_t response_format; ++ data_present_select data_present; ++ crc_check_enable crc_check; ++ cmdindex_check_enable cmdindex_check; ++ block_count_enable block_count_enable_check; ++ multi_single_block_select multi_single_block; ++} esdhc_cmd_t; ++ ++typedef struct { ++ response_format_t format; ++ u32 cmd_rsp0; ++ u32 cmd_rsp1; ++ u32 cmd_rsp2; ++ u32 cmd_rsp3; ++} esdhc_resp_t; ++ ++typedef enum { ++ BIG_ENDIAN, ++ HALF_WORD_BIG_ENDIAN, ++ LITTLE_ENDIAN ++} endian_mode_t; ++ ++typedef enum { ++ OPERATING_FREQ = 20000, /* in kHz */ ++ IDENTIFICATION_FREQ = 400 /* in kHz */ ++} sdhc_freq_t; ++ ++enum esdhc_data_status { ++ ESDHC_DATA_ERR = 3, ++ ESDHC_DATA_OK = 4 ++}; ++ ++enum esdhc_int_cntr_val { ++ ESDHC_INT_CNTR_END_CD_RESP = 0x4, ++ ESDHC_INT_CNTR_BUF_WR_RDY = 0x8 ++}; ++ ++enum esdhc_reset_status { ++ ESDHC_WRONG_RESET = 0, ++ ESDHC_CORRECT_RESET = 1 ++}; ++ ++typedef enum { ++ WEAK = 0, ++ STRONG = 1 ++} esdhc_pullup_t; ++ ++extern u32 interface_reset(void); ++extern void interface_configure_clock(sdhc_freq_t); ++extern void interface_read_response(esdhc_resp_t *); ++extern u32 interface_send_cmd_wait_resp(esdhc_cmd_t *); ++extern u32 interface_data_read(u32 *, u32); ++extern void interface_config_block_info(u32, u32, u32); ++extern u32 interface_data_write(u32 *, u32); ++extern void interface_clear_interrupt(void); ++extern void interface_initialization_active(void); ++extern void esdhc_set_cmd_pullup(esdhc_pullup_t pull_up); ++extern void esdhc_soft_reset(u32 mask); ++extern u32 interface_set_bus_width(u32 bus_width); ++/*================================================================================================*/ ++#endif /* ESDHC_H */ +diff --git a/include/asm-arm/arch-mx51/mmc.h b/include/asm-arm/arch-mx51/mmc.h +new file mode 100644 +index 0000000..062c568 +--- /dev/null ++++ b/include/asm-arm/arch-mx51/mmc.h +@@ -0,0 +1,16 @@ ++/* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * linux/drivers/mmc/mmc.h ++ * ++ * Author: Vladimir Shebordaev, Igor Oblakov ++ * Copyright: MontaVista Software Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++#ifndef __MMC_MX51_3STACK_H__ ++#define __MMC_MX51_3STACK_H__ ++ ++#endif /* __MMC_MX51_3STACK_H__ */ +diff --git a/include/asm-arm/arch-mx51/sdhc.h b/include/asm-arm/arch-mx51/sdhc.h +new file mode 100644 +index 0000000..5514ad4 +--- /dev/null ++++ b/include/asm-arm/arch-mx51/sdhc.h +@@ -0,0 +1,218 @@ ++/* ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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 SDHC_H ++#define SDHC_H ++ ++#include ++ ++#define ESDHC_SOFTWARE_RESET_DATA ((u32)0x04000000) ++#define ESDHC_SOFTWARE_RESET_CMD ((u32)0x02000000) ++#define ESDHC_SOFTWARE_RESET ((u32)0x01000000) ++#define ESDHC_CMD_INHIBIT 0x00000003 ++#define ESDHC_SYSCTL_INITA ((u32)0x08000000) ++#define ESDHC_LITTLE_ENDIAN_MODE ((u32)0x00000020) ++#define ESDHC_HW_BIG_ENDIAN_MODE ((u32)0x00000010) ++#define ESDHC_BIG_ENDIAN_MODE ((u32)0x00000000) ++#define ESDHC_ONE_BIT_SUPPORT ((u32)0x00000000) ++#define ESDHC_FOUR_BIT_SUPPORT ((u32)0x00000002) ++#define ESDHC_EIGHT_BIT_SUPPORT ((u32)0x00000004) ++#define ESDHC_CLOCK_ENABLE 0x00000007 ++#define ESDHC_FREQ_MASK 0xffff0007 ++#define ESDHC_SYSCTL_FREQ_MASK ((u32)0x000FFFF0) ++#define ESDHC_SYSCTL_IDENT_FREQ_TO1 ((u32)0x0000800e) ++#define ESDHC_SYSCTL_OPERT_FREQ_TO1 ((u32)0x00000200) ++#define ESDHC_SYSCTL_IDENT_FREQ_TO2 ((u32)0x00002040) ++#define ESDHC_SYSCTL_OPERT_FREQ_TO2 ((u32)0x00000050) ++#define ESDHC_INTERRUPT_ENABLE ((u32)0x007f0133) ++#define ESDHC_CLEAR_INTERRUPT ((u32)0x117f01ff) ++#define ESDHC_SYSCTL_DTOCV_VAL ((u32)0x000E0000) ++#define ESDHC_IRQSTATEN_DTOESEN ((u32)0x00100000) ++#define ESDHC_ENDIAN_MODE_MASK ((u32)0x00000030) ++#define ESDHC_SYSCTRL_RSTC ((u32)0x02000000) ++#define ESDHC_SYSCTRL_RSTD ((u32)0x04000000) ++#define ESDHC_CONFIG_BLOCK 0x00010200 ++#define ESDHC_OPER_TIMEOUT (96 * 100) ++#define ESDHC_ACMD41_TIMEOUT (32000) ++#define ESDHC_CMD1_TIMEOUT (32000) ++#define ESDHC_BLOCK_SHIFT (16) ++#define ESDHC_CARD_INIT_TIMEOUT (64) ++ ++#define ESDHC_SYSCTL_SDCLKEN_MASK ((u32)0x00000008) ++#define ESDHC_PRSSTAT_SDSTB_BIT ((u32)0x00000008) ++#define ESDHC_SYSCTL_INPUT_CLOCK_MASK ((u32)0x00000007) ++ ++#define ESDHC_BUS_WIDTH_MASK ((u32)0x00000006) ++#define ESDHC_DATA_TRANSFER_SHIFT (4) ++#define ESDHC_RESPONSE_FORMAT_SHIFT (16) ++#define ESDHC_DATA_PRESENT_SHIFT (21) ++#define ESDHC_CRC_CHECK_SHIFT (19) ++#define ESDHC_CMD_INDEX_CHECK_SHIFT (20) ++#define ESDHC_CMD_INDEX_SHIFT (24) ++#define ESDHC_BLOCK_COUNT_ENABLE_SHIFT (1) ++#define ESDHC_MULTI_SINGLE_BLOCK_SELECT_SHIFT (5) ++#define BLK_LEN (512) ++#define ESDHC_READ_WATER_MARK_LEVEL_BL_4 ((u32)0x00000001) ++#define ESDHC_READ_WATER_MARK_LEVEL_BL_8 ((u32)0x00000002) ++#define ESDHC_READ_WATER_MARK_LEVEL_BL_16 ((u32)0x00000004) ++#define ESDHC_READ_WATER_MARK_LEVEL_BL_64 ((u32)0x00000010) ++#define ESDHC_READ_WATER_MARK_LEVEL_BL_512 ((u32)0x00000080) ++ ++#define ESDHC_WRITE_WATER_MARK_LEVEL_BL_4 ((u32)0x00010000) ++#define ESDHC_WRITE_WATER_MARK_LEVEL_BL_8 ((u32)0x00020000) ++#define ESDHC_WRITE_WATER_MARK_LEVEL_BL_16 ((u32)0x00040000) ++#define ESDHC_WRITE_WATER_MARK_LEVEL_BL_64 ((u32)0x00100000) ++#define ESDHC_WRITE_WATER_MARK_LEVEL_BL_512 ((u32)0x00800000) ++ ++#define WRITE_READ_WATER_MARK_LEVEL 0x00800080 ++ ++/* Present State register bit masks */ ++#define ESDHC_PRESENT_STATE_CIHB ((u32)0x00000001) ++#define ESDHC_PRESENT_STATE_CDIHB ((u32)0x00000002) ++#define ONE (1) ++#define ESDHC_FIFO_SIZE (128) ++ ++#define ESDHC_STATUS_END_CMD_RESP_MSK ((u32)0x00000001) ++#define ESDHC_STATUS_END_CMD_RESP_TIME_MSK ((u32)0x000F0001) ++#define ESDHC_STATUS_TIME_OUT_RESP_MSK ((u32)0x00010000) ++#define ESDHC_STATUS_RESP_CRC_ERR_MSK ((u32)0x00020000) ++#define ESDHC_STATUS_RESP_CMD_INDEX_ERR_MSK ((u32)0x00080000) ++#define ESDHC_STATUS_BUF_READ_RDY_MSK ((u32)0x00000020) ++#define ESDHC_STATUS_BUF_WRITE_RDY_MSK ((u32)0x00000010) ++#define ESDHC_STATUS_TRANSFER_COMPLETE_MSK ((u32)0x00000002) ++#define ESDHC_STATUS_DATA_RW_MSK ((u32)0x00700002) ++#define ESDHC_STATUS_TRANSFER_COMPLETE_MSK ((u32)0x00000002) ++#define ESDHC_STATUS_TIME_OUT_READ_MASK ((u32)0x00100000) ++#define ESDHC_STATUS_READ_CRC_ERR_MSK ((u32)0x00200000) ++#define ESDHC_STATUS_RESP_CMD_END_BIT_ERR_MSK ((u32)0x00040000) ++#define ESDHC_STATUS_RW_DATA_END_BIT_ERR_MSK ((u32)0x00400000) ++ ++#define ESDHC_STATUS_TIME_OUT_READ (3200) ++#define ESDHC_READ_DATA_TIME_OUT (3200) ++#define ESDHC_WRITE_DATA_TIME_OUT (8000) ++ ++#define ESDHC_CONFIG_BLOCK_512 ((u32)0x00000200) ++#define ESDHC_CONFIG_BLOCK_64 ((u32)0x00000040) ++#define ESDHC_CONFIG_BLOCK_8 ((u32)0x00000008) ++#define ESDHC_CONFIG_BLOCK_4 ((u32)0x00000004) ++ ++#define ESDHC_MAX_BLOCK_COUNT ((u32)0x0000ffff) ++ ++typedef enum { ++ ESDHC1, ++ ESDHC2, ++ ESDHC3 ++} esdhc_num_t; ++ ++typedef enum { ++ WRITE, ++ READ, ++} xfer_type_t; ++ ++typedef enum { ++ RESPONSE_NONE, ++ RESPONSE_136, ++ RESPONSE_48, ++ RESPONSE_48_CHECK_BUSY ++} response_format_t; ++ ++ ++typedef enum { ++ DATA_PRESENT_NONE, ++ DATA_PRESENT ++} data_present_select; ++ ++typedef enum { ++ DISABLE, ++ ENABLE ++} crc_check_enable, cmdindex_check_enable, block_count_enable; ++ ++typedef enum { ++ SINGLE, ++ MULTIPLE ++} multi_single_block_select; ++ ++typedef struct { ++ u32 command; ++ u32 arg; ++ xfer_type_t data_transfer; ++ response_format_t response_format; ++ data_present_select data_present; ++ crc_check_enable crc_check; ++ cmdindex_check_enable cmdindex_check; ++ block_count_enable block_count_enable_check; ++ multi_single_block_select multi_single_block; ++} esdhc_cmd_t; ++ ++typedef struct { ++ response_format_t format; ++ u32 cmd_rsp0; ++ u32 cmd_rsp1; ++ u32 cmd_rsp2; ++ u32 cmd_rsp3; ++} esdhc_resp_t; ++ ++typedef enum { ++ BIG_ENDIAN, ++ HALF_WORD_BIG_ENDIAN, ++ LITTLE_ENDIAN ++} endian_mode_t; ++ ++typedef enum { ++ OPERATING_FREQ = 20000, /* in kHz */ ++ IDENTIFICATION_FREQ = 400 /* in kHz */ ++} sdhc_freq_t; ++ ++enum esdhc_data_status { ++ ESDHC_DATA_ERR = 3, ++ ESDHC_DATA_OK = 4 ++}; ++ ++enum esdhc_int_cntr_val { ++ ESDHC_INT_CNTR_END_CD_RESP = 0x4, ++ ESDHC_INT_CNTR_BUF_WR_RDY = 0x8 ++}; ++ ++enum esdhc_reset_status { ++ ESDHC_WRONG_RESET = 0, ++ ESDHC_CORRECT_RESET = 1 ++}; ++ ++typedef enum { ++ WEAK = 0, ++ STRONG = 1 ++} esdhc_pullup_t; ++ ++extern u32 interface_reset(void); ++extern void interface_configure_clock(sdhc_freq_t); ++extern void interface_read_response(esdhc_resp_t *); ++extern u32 interface_send_cmd_wait_resp(esdhc_cmd_t *); ++extern u32 interface_data_read(u32 *, u32); ++extern void interface_config_block_info(u32, u32, u32); ++extern u32 interface_data_write(u32 *, u32); ++extern void interface_clear_interrupt(void); ++extern void interface_initialization_active(void); ++extern void esdhc_set_cmd_pullup(esdhc_pullup_t pull_up); ++extern void esdhc_soft_reset(u32 mask); ++extern u32 interface_set_bus_width(u32 bus_width); ++/*================================================================================================*/ ++#endif /* ESDHC_H */ +diff --git a/include/environment.h b/include/environment.h +index ea6b4d1..eb62ebc 100644 +--- a/include/environment.h ++++ b/include/environment.h +@@ -84,6 +84,27 @@ + # endif + #endif /* CONFIG_ENV_IS_IN_NAND */ + ++#if defined(CONFIG_ENV_IS_IN_MMC) ++#ifndef CONFIG_MMC_BASE ++# error "Need to define CONFIG_MMC_BASE when using CONFIG_ENV_IS_IN_MMC" ++#endif ++# ifndef CONFIG_ENV_OFFSET ++# error "Need to define CONFIG_ENV_OFFSET when using CONFIG_ENV_IS_IN_MMC" ++# endif ++# ifndef CONFIG_ENV_ADDR ++# define CONFIG_ENV_ADDR (CONFIG_MMC_BASE + CONFIG_ENV_OFFSET) ++# endif ++# ifndef CONFIG_ENV_OFFSET ++# define CONFIG_ENV_OFFSET (CONFIG_ENV_ADDR - CONFIG_MMC_BASE) ++# endif ++# ifdef CONFIG_ENV_OFFSET_REDUND ++# define CONFIG_SYS_REDUNDAND_ENVIRONMENT ++# endif ++# ifdef CONFIG_ENV_IS_EMBEDDED ++# define ENV_IS_EMBEDDED 1 ++# endif ++#endif /* CONFIG_ENV_IS_IN_NAND */ ++ + #ifdef USE_HOSTCC + # include + #else +diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h +new file mode 100644 +index 0000000..393d587 +--- /dev/null ++++ b/include/linux/mmc/card.h +@@ -0,0 +1,141 @@ ++/* ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * linux/include/linux/mmc/card.h ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Card driver specific definitions. ++ */ ++#ifndef LINUX_MMC_CARD_H ++#define LINUX_MMC_CARD_H ++ ++#include "core.h" ++ ++struct mmc_cid { ++ unsigned int manfid; ++ char prod_name[8]; ++ unsigned int serial; ++ union { ++ unsigned short mmc_id; ++ char sd_id[2]; ++ } oemid; ++ unsigned short year; ++ unsigned char hwrev; ++ unsigned char fwrev; ++ unsigned char month; ++}; ++ ++struct mmc_csd { ++ unsigned char mmca_vsn; ++ unsigned short cmdclass; ++ unsigned short tacc_clks; ++ unsigned int tacc_ns; ++ unsigned int r2w_factor; ++ unsigned int max_dtr; ++ unsigned int read_blkbits; ++ unsigned int write_blkbits; ++ unsigned int capacity; ++ unsigned int read_partial:1, ++ read_misalign:1, ++ write_partial:1, ++ write_misalign:1; ++}; ++ ++struct mmc_ext_csd { ++ unsigned int hs_max_dtr; ++ unsigned int sectors; ++}; ++ ++struct sd_scr { ++ unsigned char sda_vsn; ++ unsigned char bus_widths; ++#define SD_SCR_BUS_WIDTH_1 (1<<0) ++#define SD_SCR_BUS_WIDTH_4 (1<<2) ++}; ++ ++struct sd_switch_caps { ++ unsigned int hs_max_dtr; ++}; ++ ++struct sdio_cccr { ++ unsigned int sdio_vsn; ++ unsigned int sd_vsn; ++ unsigned int multi_block:1, ++ low_speed:1, ++ wide_bus:1, ++ high_power:1, ++ high_speed:1; ++}; ++ ++struct sdio_cis { ++ unsigned short vendor; ++ unsigned short device; ++ unsigned short blksize; ++ unsigned int max_dtr; ++}; ++ ++struct mmc_host; ++struct sdio_func; ++struct sdio_func_tuple; ++ ++#define SDIO_MAX_FUNCS 7 ++ ++/* ++ * MMC device ++ */ ++struct mmc_card { ++ unsigned int rca; /* relative card address of device */ ++ unsigned int type; /* card type */ ++#define MMC_TYPE_MMC 0 /* MMC card */ ++#define MMC_TYPE_SD 1 /* SD card */ ++#define MMC_TYPE_SDIO 2 /* SDIO card */ ++ unsigned int state; /* (our) card state */ ++#define MMC_STATE_PRESENT (1<<0) /* present in sysfs */ ++#define MMC_STATE_READONLY (1<<1) /* card is read-only */ ++#define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */ ++#define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */ ++ ++ u32 raw_cid[4]; /* raw card CID */ ++ u32 raw_csd[4]; /* raw card CSD */ ++ u32 raw_scr[2]; /* raw card SCR */ ++ struct mmc_cid cid; /* card identification */ ++ struct mmc_csd csd; /* card specific */ ++ struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */ ++ struct sd_scr scr; /* extra SD information */ ++ struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ ++ ++ unsigned int sdio_funcs; /* number of SDIO functions */ ++ struct sdio_cccr cccr; /* common card info */ ++ struct sdio_cis cis; /* common tuple info */ ++ /* SDIO functions (devices) */ ++ struct sdio_func *sdio_func[SDIO_MAX_FUNCS]; ++ unsigned num_info; /* number of info strings */ ++ const char **info; /* info strings */ ++ struct sdio_func_tuple *tuples; /* unknown common tuples */ ++}; ++ ++#define mmc_card_mmc(c) ((c)->type == MMC_TYPE_MMC) ++#define mmc_card_sd(c) ((c)->type == MMC_TYPE_SD) ++#define mmc_card_sdio(c) ((c)->type == MMC_TYPE_SDIO) ++ ++#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT) ++#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) ++#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED) ++#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) ++ ++#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) ++#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) ++#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED) ++#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR) ++ ++#define mmc_card_name(c) ((c)->cid.prod_name) ++#define mmc_card_id(c) ((c)->dev.bus_id) ++ ++#define mmc_list_to_card(l) container_of(l, struct mmc_card, node) ++#define mmc_get_drvdata(c) dev_get_drvdata(&(c)->dev) ++#define mmc_set_drvdata(c, d) dev_set_drvdata(&(c)->dev, d) ++ ++#endif +diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h +new file mode 100644 +index 0000000..7f0e786 +--- /dev/null ++++ b/include/linux/mmc/core.h +@@ -0,0 +1,132 @@ ++/* ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * linux/include/linux/mmc/core.h ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++#ifndef MMC_CORE_H ++#define MMC_CORE_H ++ ++#include ++ ++struct request; ++struct mmc_data; ++struct mmc_request; ++ ++struct mmc_command { ++ esdhc_cmd_t cmd; ++ esdhc_resp_t resp; ++#define MMC_RSP_PRESENT (1 << 0) ++#define MMC_RSP_136 (1 << 1) /* 136 bit response */ ++#define MMC_RSP_CRC (1 << 2) /* expect valid crc */ ++#define MMC_RSP_BUSY (1 << 3) /* card may send busy */ ++#define MMC_RSP_OPCODE (1 << 4) /* response contains opcode */ ++ ++#define MMC_CMD_MASK (3 << 5) /* non-SPI command type */ ++#define MMC_CMD_AC (0 << 5) ++#define MMC_CMD_ADTC (1 << 5) ++#define MMC_CMD_BC (2 << 5) ++#define MMC_CMD_BCR (3 << 5) ++ ++#define MMC_RSP_SPI_S1 (1 << 7) /* one status byte */ ++#define MMC_RSP_SPI_S2 (1 << 8) /* second byte */ ++#define MMC_RSP_SPI_B4 (1 << 9) /* four data bytes */ ++#define MMC_RSP_SPI_BUSY (1 << 10) /* card may send busy */ ++ ++/* ++ * These are the native response types, and correspond to valid bit ++ * patterns of the above flags. One additional valid pattern ++ * is all zeros, which means we don't expect a response. ++ */ ++#define MMC_RSP_NONE (0) ++#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) ++#define MMC_RSP_R1B (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY) ++#define MMC_RSP_R2 (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC) ++#define MMC_RSP_R3 (MMC_RSP_PRESENT) ++#define MMC_RSP_R4 (MMC_RSP_PRESENT) ++#define MMC_RSP_R5 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) ++#define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) ++#define MMC_RSP_R7 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) ++ ++#define mmc_resp_type(cmd) ((cmd)->flags & \ ++ (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC| \ ++ MMC_RSP_BUSY|MMC_RSP_OPCODE)) ++ ++#define MMC_KEEP_CLK_RUN (1 << 31) /* Keep card clock on after request */ ++ ++/* ++ * These are the SPI response types for MMC, SD, and SDIO cards. ++ * Commands return R1, with maybe more info. Zero is an error type; ++ * callers must always provide the appropriate MMC_RSP_SPI_Rx flags. ++ */ ++#define MMC_RSP_SPI_R1 (MMC_RSP_SPI_S1) ++#define MMC_RSP_SPI_R1B (MMC_RSP_SPI_S1|MMC_RSP_SPI_BUSY) ++#define MMC_RSP_SPI_R2 (MMC_RSP_SPI_S1|MMC_RSP_SPI_S2) ++#define MMC_RSP_SPI_R3 (MMC_RSP_SPI_S1|MMC_RSP_SPI_B4) ++#define MMC_RSP_SPI_R4 (MMC_RSP_SPI_S1|MMC_RSP_SPI_B4) ++#define MMC_RSP_SPI_R5 (MMC_RSP_SPI_S1|MMC_RSP_SPI_S2) ++#define MMC_RSP_SPI_R7 (MMC_RSP_SPI_S1|MMC_RSP_SPI_B4) ++ ++#define mmc_spi_resp_type(cmd) ((cmd)->flags & \ ++ (MMC_RSP_SPI_S1|MMC_RSP_SPI_BUSY|MMC_RSP_SPI_S2|MMC_RSP_SPI_B4)) ++ ++/* ++ * These are the command types. ++ */ ++#define mmc_cmd_type(cmd) ((cmd)->flags & MMC_CMD_MASK) ++ ++ unsigned int retries; /* max number of retries */ ++ unsigned int error; /* command error */ ++ ++/* ++ * Standard errno values are used for errors, but some have specific ++ * meaning in the MMC layer: ++ * ++ * ETIMEDOUT Card took too long to respond ++ * EILSEQ Basic format problem with the received or sent data ++ * (e.g. CRC check failed, incorrect opcode in response ++ * or bad end bit) ++ * EINVAL Request cannot be performed because of restrictions ++ * in hardware and/or the driver ++ * ENOMEDIUM Host can determine that the slot is empty and is ++ * actively failing requests ++ */ ++ ++ struct mmc_data *data; /* data segment associated with cmd */ ++ struct mmc_request *mrq; /* associated request */ ++}; ++ ++struct mmc_data { ++ unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */ ++ unsigned int timeout_clks; /* data timeout (in clocks) */ ++ unsigned int blksz; /* data block size */ ++ unsigned int blocks; /* number of blocks */ ++ unsigned int error; /* data error */ ++ unsigned int flags; ++ ++#define MMC_DATA_WRITE (1 << 8) ++#define MMC_DATA_READ (1 << 9) ++#define MMC_DATA_STREAM (1 << 10) ++ ++ unsigned int bytes_xfered; ++ ++ struct mmc_command *stop; /* stop command */ ++ struct mmc_request *mrq; /* associated request */ ++ ++ unsigned int sg_len; /* size of scatter list */ ++ struct scatterlist *sg; /* I/O scatter list */ ++}; ++ ++struct mmc_request { ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ struct mmc_command *stop; ++ ++ void *done_data; /* completion data */ ++ void (*done)(struct mmc_request *); /* completion function */ ++}; ++ ++#endif +diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h +new file mode 100644 +index 0000000..4b9bde9 +--- /dev/null ++++ b/include/linux/mmc/mmc.h +@@ -0,0 +1,291 @@ ++/* (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * Header for MultiMediaCard (MMC) ++ * ++ * Copyright 2002 Hewlett-Packard Company ++ * ++ * Use consistent with the GNU GPL is permitted, ++ * provided that this copyright notice is ++ * preserved in its entirety in all copies and derived works. ++ * ++ * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, ++ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS ++ * FITNESS FOR ANY PARTICULAR PURPOSE. ++ * ++ * Many thanks to Alessandro Rubini and Jonathan Corbet! ++ * ++ * Based strongly on code by: ++ * ++ * Author: Yong-iL Joh ++ * Date : $Date: 2002/06/18 12:37:30 $ ++ * ++ * Author: Andrew Christian ++ * 15 May 2002 ++ */ ++ ++#ifndef MMC_MMC_H ++#define MMC_MMC_H ++ ++/* Standard MMC commands (4.1) type argument response */ ++ /* class 1 */ ++#define MMC_GO_IDLE_STATE 0 /* bc */ ++#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ ++#define MMC_ALL_SEND_CID 2 /* bcr R2 */ ++#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ ++#define MMC_SET_DSR 4 /* bc [31:16] RCA */ ++#define MMC_SWITCH 6 /* ac [31:0] See below R1b */ ++#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ ++#define MMC_SEND_EXT_CSD 8 /* adtc R1 */ ++#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ ++#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ ++#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ ++#define MMC_STOP_TRANSMISSION 12 /* ac R1b */ ++#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ ++#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */ ++#define MMC_SPI_READ_OCR 58 /* spi spi_R3 */ ++#define MMC_SPI_CRC_ON_OFF 59 /* spi [0:0] flag spi_R1 */ ++ ++ /* class 2 */ ++#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ ++#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ ++#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ ++ ++ /* class 3 */ ++#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ ++ ++ /* class 4 */ ++#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */ ++#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */ ++#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */ ++#define MMC_PROGRAM_CID 26 /* adtc R1 */ ++#define MMC_PROGRAM_CSD 27 /* adtc R1 */ ++ ++ /* class 6 */ ++#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */ ++#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */ ++#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */ ++ ++ /* class 5 */ ++#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */ ++#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */ ++#define MMC_ERASE 38 /* ac R1b */ ++ ++ /* class 9 */ ++#define MMC_FAST_IO 39 /* ac R4 */ ++#define MMC_GO_IRQ_STATE 40 /* bcr R5 */ ++ ++ /* class 7 */ ++#define MMC_LOCK_UNLOCK 42 /* adtc R1b */ ++ ++ /* class 8 */ ++#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ ++#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ ++ ++/* ++ * MMC_SWITCH argument format: ++ * ++ * [31:26] Always 0 ++ * [25:24] Access Mode ++ * [23:16] Location of target Byte in EXT_CSD ++ * [15:08] Value Byte ++ * [07:03] Always 0 ++ * [02:00] Command Set ++ */ ++ ++#define MMC_BUS_WIDTH_1 0 ++#define MMC_BUS_WIDTH_4 2 ++#define MMC_BUS_WIDTH_8 3 ++ ++/* ++ MMC status in R1, for native mode (SPI bits are different) ++ Type ++ e : error bit ++ s : status bit ++ r : detected and set for the actual command response ++ x : detected and set during command execution. the host must poll ++ the card by sending status command in order to read these bits. ++ Clear condition ++ a : according to the card state ++ b : always related to the previous command. Reception of ++ a valid command will clear it (with a delay of one command) ++ c : clear by read ++ */ ++ ++#define R1_OUT_OF_RANGE (1 << 31) /* er, c */ ++#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ ++#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ ++#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ ++#define R1_ERASE_PARAM (1 << 27) /* ex, c */ ++#define R1_WP_VIOLATION (1 << 26) /* erx, c */ ++#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ ++#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ ++#define R1_COM_CRC_ERROR (1 << 23) /* er, b */ ++#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ ++#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ ++#define R1_CC_ERROR (1 << 20) /* erx, c */ ++#define R1_ERROR (1 << 19) /* erx, c */ ++#define R1_UNDERRUN (1 << 18) /* ex, c */ ++#define R1_OVERRUN (1 << 17) /* ex, c */ ++#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ ++#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ ++#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ ++#define R1_ERASE_RESET (1 << 13) /* sr, c */ ++#define R1_STATUS(x) (x & 0xFFFFE000) ++#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ ++#define R1_READY_FOR_DATA (1 << 8) /* sx, a */ ++#define R1_APP_CMD (1 << 5) /* sr, c */ ++ ++/* ++ * MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS ++ * R1 is the low order byte; R2 is the next highest byte, when present. ++ */ ++#define R1_SPI_IDLE (1 << 0) ++#define R1_SPI_ERASE_RESET (1 << 1) ++#define R1_SPI_ILLEGAL_COMMAND (1 << 2) ++#define R1_SPI_COM_CRC (1 << 3) ++#define R1_SPI_ERASE_SEQ (1 << 4) ++#define R1_SPI_ADDRESS (1 << 5) ++#define R1_SPI_PARAMETER (1 << 6) ++/* R1 bit 7 is always zero */ ++#define R2_SPI_CARD_LOCKED (1 << 8) ++#define R2_SPI_WP_ERASE_SKIP (1 << 9) /* or lock/unlock fail */ ++#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP ++#define R2_SPI_ERROR (1 << 10) ++#define R2_SPI_CC_ERROR (1 << 11) ++#define R2_SPI_CARD_ECC_ERROR (1 << 12) ++#define R2_SPI_WP_VIOLATION (1 << 13) ++#define R2_SPI_ERASE_PARAM (1 << 14) ++#define R2_SPI_OUT_OF_RANGE (1 << 15) /* or CSD overwrite */ ++#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE ++ ++/* These are unpacked versions of the actual responses */ ++ ++struct _mmc_csd { ++ u8 csd_structure; ++ u8 spec_vers; ++ u8 taac; ++ u8 nsac; ++ u8 tran_speed; ++ u16 ccc; ++ u8 read_bl_len; ++ u8 read_bl_partial; ++ u8 write_blk_misalign; ++ u8 read_blk_misalign; ++ u8 dsr_imp; ++ u16 c_size; ++ u8 vdd_r_curr_min; ++ u8 vdd_r_curr_max; ++ u8 vdd_w_curr_min; ++ u8 vdd_w_curr_max; ++ u8 c_size_mult; ++ union { ++ struct { /* MMC system specification version 3.1 */ ++ u8 erase_grp_size; ++ u8 erase_grp_mult; ++ } v31; ++ struct { /* MMC system specification version 2.2 */ ++ u8 sector_size; ++ u8 erase_grp_size; ++ } v22; ++ } erase; ++ u8 wp_grp_size; ++ u8 wp_grp_enable; ++ u8 default_ecc; ++ u8 r2w_factor; ++ u8 write_bl_len; ++ u8 write_bl_partial; ++ u8 file_format_grp; ++ u8 copy; ++ u8 perm_write_protect; ++ u8 tmp_write_protect; ++ u8 file_format; ++ u8 ecc; ++}; ++ ++/* ++ * OCR bits are mostly in host.h ++ */ ++#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ ++ ++/* ++ * Card Command Classes (CCC) ++ */ ++#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */ ++ /* (CMD0,1,2,3,4,7,9,10,12,13,15) */ ++ /* (and for SPI, CMD58,59) */ ++#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */ ++ /* (CMD11) */ ++#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */ ++ /* (CMD16,17,18) */ ++#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */ ++ /* (CMD20) */ ++#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */ ++ /* (CMD16,24,25,26,27) */ ++#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */ ++ /* (CMD32,33,34,35,36,37,38,39) */ ++#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */ ++ /* (CMD28,29,30) */ ++#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */ ++ /* (CMD16,CMD42) */ ++#define CCC_APP_SPEC (1<<8) /* (8) Application specific */ ++ /* (CMD55,56,57,ACMD*) */ ++#define CCC_IO_MODE (1<<9) /* (9) I/O mode */ ++ /* (CMD5,39,40,52,53) */ ++#define CCC_SWITCH (1<<10) /* (10) High speed switch */ ++ /* (CMD6,34,35,36,37,50) */ ++ /* (11) Reserved */ ++ /* (CMD?) */ ++ ++/* ++ * CSD field definitions ++ */ ++ ++#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ ++#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ ++/* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */ ++#define CSD_STRUCT_VER_1_2 2 ++/* Version is coded in CSD_STRUCTURE in EXT_CSD */ ++#define CSD_STRUCT_EXT_CSD 3 ++ ++#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */ ++#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */ ++#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */ ++#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */ ++#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */ ++ ++/* ++ * EXT_CSD fields ++ */ ++ ++#define EXT_CSD_BUS_WIDTH 183 /* R/W */ ++#define EXT_CSD_HS_TIMING 185 /* R/W */ ++#define EXT_CSD_CARD_TYPE 196 /* RO */ ++#define EXT_CSD_REV 192 /* RO */ ++#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ ++ ++/* ++ * EXT_CSD field definitions ++ */ ++ ++#define EXT_CSD_CMD_SET_NORMAL (1<<0) ++#define EXT_CSD_CMD_SET_SECURE (1<<1) ++#define EXT_CSD_CMD_SET_CPSECURE (1<<2) ++ ++#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ ++#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ ++ ++#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ ++#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ ++#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ ++ ++/* ++ * MMC_SWITCH access modes ++ */ ++ ++#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ ++#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */ ++#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */ ++#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ ++ ++#endif /* MMC_MMC_PROTOCOL_H */ ++ +diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h +new file mode 100644 +index 0000000..f236909 +--- /dev/null ++++ b/include/linux/mmc/sd.h +@@ -0,0 +1,95 @@ ++/* ++ * include/linux/mmc/sd.h ++ * ++ * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. ++ * ++ * Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * ++ * 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. ++ */ ++ ++#ifndef MMC_SD_H ++#define MMC_SD_H ++ ++/* SD commands type argument response */ ++ /* class 0 */ ++/* This is basically the same command as for MMC with some quirks. */ ++#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ ++#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ ++ ++ /* class 10 */ ++#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ ++ ++ /* Application commands */ ++#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ ++#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ ++#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ ++#define SD_APP_SEND_SCR 51 /* adtc R1 */ ++ ++#define SD_OCR_VALUE_HV_LC (0x00ff8000) ++#define SD_OCR_VALUE_HV_HC (0x40ff8000) ++#define SD_OCR_VALUE_LV_HC (0x40000080) ++#define SD_OCR_HC_RES (0x40000000) ++#define SD_IF_HV_COND_ARG (0x000001AA) ++#define SD_IF_LV_COND_ARG (0x000002AA) ++ ++#define SD_OCR_VALUE_COUNT (3) ++#define SD_IF_CMD_ARG_COUNT (2) ++ ++/* ++ * SD_SWITCH argument format: ++ * ++ * [31] Check (0) or switch (1) ++ * [30:24] Reserved (0) ++ * [23:20] Function group 6 ++ * [19:16] Function group 5 ++ * [15:12] Function group 4 ++ * [11:8] Function group 3 ++ * [7:4] Function group 2 ++ * [3:0] Function group 1 ++ */ ++ ++/* ++ * SD_SEND_IF_COND argument format: ++ * ++ * [31:12] Reserved (0) ++ * [11:8] Host Voltage Supply Flags ++ * [7:0] Check Pattern (0xAA) ++ */ ++ ++/* ++ * SCR field definitions ++ */ ++ ++#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ ++#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ ++#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00 */ ++ ++/* ++ * SD bus widths ++ */ ++#define SD_BUS_WIDTH_1 0 ++#define SD_BUS_WIDTH_4 2 ++ ++/* ++ * SD_SWITCH mode ++ */ ++#define SD_SWITCH_CHECK 0 ++#define SD_SWITCH_SET 1 ++ ++/* ++ * SD_SWITCH function groups ++ */ ++#define SD_SWITCH_GRP_ACCESS 0 ++ ++/* ++ * SD_SWITCH access modes ++ */ ++#define SD_SWITCH_ACCESS_DEF 0 ++#define SD_SWITCH_ACCESS_HS 1 ++ ++#endif ++ +diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h +new file mode 100644 +index 0000000..ee7fb26 +--- /dev/null ++++ b/include/linux/mmc/sdhci.h +@@ -0,0 +1,223 @@ ++/* ++ * linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver ++ * ++ * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. ++ * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. ++ * ++ * 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. ++ */ ++ ++/* ++ * PCI registers ++ */ ++ ++#define PCI_SDHCI_IFPIO 0x00 ++#define PCI_SDHCI_IFDMA 0x01 ++#define PCI_SDHCI_IFVENDOR 0x02 ++ ++#define PCI_SLOT_INFO 0x40 /* 8 bits */ ++#define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) ++#define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 ++ ++/* ++ * Controller registers ++ */ ++ ++#define SDHCI_DMA_ADDRESS 0x00 ++ ++#define SDHCI_BLOCK_SIZE 0x04 ++#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF)) ++ ++#define SDHCI_BLOCK_COUNT 0x06 ++ ++#define SDHCI_ARGUMENT 0x08 ++ ++#define SDHCI_TRANSFER_MODE 0x0C ++#define SDHCI_TRNS_DMA 0x01 ++#define SDHCI_TRNS_BLK_CNT_EN 0x02 ++#define SDHCI_TRNS_ACMD12 0x04 ++#define SDHCI_TRNS_READ 0x10 ++#define SDHCI_TRNS_MULTI 0x20 ++ ++#define SDHCI_COMMAND 0x0E ++#define SDHCI_CMD_RESP_MASK 0x03 ++#define SDHCI_CMD_CRC 0x08 ++#define SDHCI_CMD_INDEX 0x10 ++#define SDHCI_CMD_DATA 0x20 ++ ++#define SDHCI_CMD_RESP_NONE 0x00 ++#define SDHCI_CMD_RESP_LONG 0x01 ++#define SDHCI_CMD_RESP_SHORT 0x02 ++#define SDHCI_CMD_RESP_SHORT_BUSY 0x03 ++ ++#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff)) ++ ++#define SDHCI_RESPONSE 0x10 ++ ++#define SDHCI_BUFFER 0x20 ++ ++#define SDHCI_PRESENT_STATE 0x24 ++#define SDHCI_CMD_INHIBIT 0x00000001 ++#define SDHCI_DATA_INHIBIT 0x00000002 ++#define SDHCI_DOING_WRITE 0x00000100 ++#define SDHCI_DOING_READ 0x00000200 ++#define SDHCI_SPACE_AVAILABLE 0x00000400 ++#define SDHCI_DATA_AVAILABLE 0x00000800 ++#define SDHCI_CARD_PRESENT 0x00010000 ++#define SDHCI_WRITE_PROTECT 0x00080000 ++ ++#define SDHCI_HOST_CONTROL 0x28 ++#define SDHCI_CTRL_LED 0x01 ++#define SDHCI_CTRL_4BITBUS 0x00000002 ++#define SDHCI_CTRL_8BITBUS 0x00000004 ++#define SDHCI_CTRL_HISPD 0x04 ++ ++#define SDHCI_POWER_CONTROL 0x29 ++#define SDHCI_POWER_ON 0x01 ++#define SDHCI_POWER_180 0x0A ++#define SDHCI_POWER_300 0x0C ++#define SDHCI_POWER_330 0x0E ++ ++#define SDHCI_BLOCK_GAP_CONTROL 0x2A ++ ++#define SDHCI_WAKE_UP_CONTROL 0x2B ++ ++#define SDHCI_CLOCK_CONTROL 0x2C ++#define SDHCI_SYSTEM_CONTROL 0x2C ++#define SDHCI_DIVIDER_SHIFT 8 ++#define SDHCI_CLOCK_CARD_EN 0x0004 ++#define SDHCI_CLOCK_INT_STABLE 0x0002 ++#define SDHCI_CLOCK_INT_EN 0x0001 ++ ++#define SDHCI_TIMEOUT_CONTROL 0x2E ++ ++#define SDHCI_SOFTWARE_RESET 0x2F ++#define SDHCI_RESET_ALL 0x01 ++#define SDHCI_RESET_CMD 0x02 ++#define SDHCI_RESET_DATA 0x04 ++ ++#define SDHCI_INT_STATUS 0x30 ++#define SDHCI_INT_ENABLE 0x34 ++#define SDHCI_SIGNAL_ENABLE 0x38 ++#define SDHCI_INT_RESPONSE 0x00000001 ++#define SDHCI_INT_DATA_END 0x00000002 ++#define SDHCI_INT_DMA_END 0x00000008 ++#define SDHCI_INT_SPACE_AVAIL 0x00000010 ++#define SDHCI_INT_DATA_AVAIL 0x00000020 ++#define SDHCI_INT_CARD_INSERT 0x00000040 ++#define SDHCI_INT_CARD_REMOVE 0x00000080 ++#define SDHCI_INT_CARD_INT 0x00000100 ++#define SDHCI_INT_ERROR 0x00008000 ++#define SDHCI_INT_TIMEOUT 0x00010000 ++#define SDHCI_INT_CRC 0x00020000 ++#define SDHCI_INT_END_BIT 0x00040000 ++#define SDHCI_INT_INDEX 0x00080000 ++#define SDHCI_INT_DATA_TIMEOUT 0x00100000 ++#define SDHCI_INT_DATA_CRC 0x00200000 ++#define SDHCI_INT_DATA_END_BIT 0x00400000 ++#define SDHCI_INT_BUS_POWER 0x00800000 ++#define SDHCI_INT_ACMD12ERR 0x01000000 ++ ++#define SDHCI_INT_NORMAL_MASK 0x00007FFF ++#define SDHCI_INT_ERROR_MASK 0xFFFF8000 ++ ++#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \ ++ SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX) ++#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ ++ SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ ++ SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ ++ SDHCI_INT_DATA_END_BIT) ++ ++#define SDHCI_ACMD12_ERR 0x3C ++ ++/* 3E-3F reserved */ ++ ++#define SDHCI_CAPABILITIES 0x40 ++#define SDHCI_TIMEOUT_CLK_MASK 0x0000003F ++#define SDHCI_TIMEOUT_CLK_SHIFT 0 ++#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080 ++#define SDHCI_CLOCK_BASE_MASK 0x00003F00 ++#define SDHCI_CLOCK_BASE_SHIFT 8 ++#define SDHCI_MAX_BLOCK_MASK 0x00030000 ++#define SDHCI_MAX_BLOCK_SHIFT 16 ++#define SDHCI_CAN_DO_HISPD 0x00200000 ++#define SDHCI_CAN_DO_DMA 0x00400000 ++#define SDHCI_CAN_VDD_330 0x01000000 ++#define SDHCI_CAN_VDD_300 0x02000000 ++#define SDHCI_CAN_VDD_180 0x04000000 ++ ++/* 44-47 reserved for more caps */ ++#define SDHCI_WML_LEV 0x44 ++ ++#define SDHCI_MAX_CURRENT 0x48 ++ ++/* 4C-4F reserved for more max current */ ++ ++/* 50-FB reserved */ ++ ++#define SDHCI_SLOT_INT_STATUS 0xFC ++ ++#define SDHCI_HOST_VERSION 0xFE ++#define SDHCI_VENDOR_VER_MASK 0xFF00 ++#define SDHCI_VENDOR_VER_SHIFT 8 ++#define SDHCI_SPEC_VER_MASK 0x00FF ++#define SDHCI_SPEC_VER_SHIFT 0 ++ ++#if 0 ++ ++struct sdhci_chip; ++ ++struct sdhci_host { ++ struct sdhci_chip *chip; ++ struct mmc_host *mmc; /* MMC structure */ ++ ++#ifdef CONFIG_LEDS_CLASS ++ struct led_classdev led; /* LED control */ ++#endif ++ ++ spinlock_t lock; /* Mutex */ ++ ++ int flags; /* Host attributes */ ++#define SDHCI_USE_DMA (1<<0) /* Host is DMA capable */ ++#define SDHCI_REQ_USE_DMA (1<<1) /* Use DMA for this req. */ ++ ++ unsigned int max_clk; /* Max possible freq (MHz) */ ++ unsigned int timeout_clk; /* Timeout freq (KHz) */ ++ ++ unsigned int clock; /* Current clock (MHz) */ ++ unsigned short power; /* Current voltage */ ++ ++ struct mmc_request *mrq; /* Current request */ ++ struct mmc_command *cmd; /* Current command */ ++ struct mmc_data *data; /* Current data request */ ++ unsigned int data_early:1; /* Data finished before cmd */ ++ ++ struct scatterlist *cur_sg; /* We're working on this */ ++ int num_sg; /* Entries left */ ++ int offset; /* Offset into current sg */ ++ int remain; /* Bytes left in current */ ++ ++ int irq; /* Device IRQ */ ++ int bar; /* PCI BAR index */ ++ unsigned long addr; /* Bus address */ ++ void __iomem *ioaddr; /* Mapped address */ ++ ++ struct tasklet_struct card_tasklet; /* Tasklet structures */ ++ struct tasklet_struct finish_tasklet; ++ ++ struct timer_list timer; /* Timer for timeouts */ ++}; ++ ++struct sdhci_chip { ++ struct pci_dev *pdev; ++ ++ unsigned long quirks; ++ ++ int num_slots; /* Slots on controller */ ++ struct sdhci_host *hosts[0]; /* Pointers to hosts */ ++}; ++ ++#endif +-- +1.5.4.4 +