Compare commits

...

49 Commits

Author SHA1 Message Date
0cff1b3d3c ENGR00116925: Support MMC slot 2 in BBG.
Support MMC slot 2 boot and common
operations in MX51 BBG bootloader.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-10-13 15:22:31 +08:00
7142651386 ENGR00116924 Uboot: Boot up hang at detecting NAND when cold boot
Boot from MMC card failed at detecting NAND. The fix will
1. Set RBB_MODE to 1 and using atomic status command
2. Set FW correctly by adding CONFIG_NAND_FW_8 config
3. Correct the BLS register value

Signed-off-by:Jason Liu <r64343@freescale.com>
2009-10-12 15:05:19 +08:00
eea025d171 ENGR00116856: Set voltage and CACRR to make CPU run at 800MHz.
Set voltage and CACRR to make CPU run at 800MHz.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-09-27 16:52:33 +08:00
65243d8e35 ENGR00116825: Put esdhc header file as common file.
Put esdhc header file as common file.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-09-25 18:19:35 +08:00
ae238076c6 ENGR00116614: Set default config to nand for mx51 3ds.
Modify config file to make booting from nand
and saving env to nand as default.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-09-24 14:08:34 +08:00
c78103cfad ENGR00116733: Sync mx51 3stack low level init code with redboot.
Sync mx51 3stack low level init code with redboot.
Including l2cc, clock, dcd data.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-09-23 17:07:35 +08:00
63ce77b674 ENGR00116590: Improve sd/mmc performance.
Adjust clock settings to improve sd/mmc performance.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-09-21 14:39:02 +08:00
530e8cb237 ENGR00116504-2: Add mx51 bbg to3 support.
Add mx51 bbg to3 support.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-09-21 14:22:15 +08:00
f712613010 ENGR00116504-1: Sync clock and l2cc code with redboot.
Syc clock and l2cc code with redboot.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-09-18 13:41:08 +08:00
af97caf4ff ENGR00116243: I2C support for mx51 3ds board.
I2C support for mx51 3ds board.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-09-07 15:13:17 +08:00
f84be76de7 ENGR00116203: Change nand Makefile to use CONFIG_MXC_NAND.
Change nand Makefile to use CONFIG_MXC_NAND.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-09-03 18:14:01 +08:00
1e25a1c10c ENGR00116083: Recovery mode support for Android on mx51.
Recovery mode support for Android on mx51.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-09-03 17:13:28 +08:00
1e96c488d0 ENGR00116140 MX51 3stack low level does not set M4IF correctly
Copy babbage settings to 3stack

Signed-off-by: Xinyu Chen <xinyu.chen@freescale.com>
2009-09-02 15:29:22 +08:00
c2590273ef ENGR00115592: Replace whitespaces with tabs in Makefile
Replace whitespaces with tabs in Makefile.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-08-18 17:25:15 +08:00
5df28a62da ENGR00115046: Add new MMC config option for mx35.
Add new MMC config option for mx35.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-08-18 15:32:23 +08:00
f98076caf9 ENGR00115333: Enable cp command for MMC
Enable cp command for MMC.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-08-14 12:07:20 +08:00
993bd9f320 ENGR00113941 MX233: Make UBOOT v2009.01 work on EVK board
Porting MX233 UBOOT from 1.3.3 to V2009.01. Clear old cfg macro, such as
CFG_HZ. Change MAC address getting source from initial configuration to
On-Chip OTP.

Signed-off-by: Lionel Xu <r63889@freescale.com>
2009-08-04 18:17:02 +08:00
b68a633562 ENGR00114746: Disable flash header for mx35 nand boot
Disable flash header for mx35 nand boot.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-08-03 15:14:43 +00:00
bc1f6fa69a ENGR00114367: Add BABBAGE machine id, BBG2.5 rev id for rootfs init.
Update mach-types for BBG board.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-07-23 16:49:09 +08:00
20aa905324 ENGR00114393: Support Atmel AT45DB321D SPI NOR flash.
Support Atmel AT45DB321D SPI NOR flash.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-07-22 17:51:54 +08:00
70ec2b9f68 ENGR00114178 Support MMC/SD boot and enable dhcp in uboot on MX25
1. Support MMC/SD boot in uboot, however, it is disabled default and
 user needs to enable manually by changing mx25_3stack.h;
2. Enable dhcp for network.

Signed-off-by: Sammy He <r62914@freescale.com>
2009-07-16 15:11:42 +08:00
f732ca0913 ENGR00114201: Add MMC configs to mx35 3stack config file.
Add MMC configs to mx35 3stack config file.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-07-15 18:01:23 +08:00
3d891b4cfa ENGR00114236 Disable NAND driver interleave mode support
Disable NAND driver interleave mode support

Signed-off-by:Jason Liu <r64343@freescale.com>
2009-07-15 14:12:05 +08:00
35a888b8ef ENGR00114233 Add support for programming ubifs image on nand flash
Add support for programming ubifs image on nand flash

Signed-off-by:Jason Liu <r64343@freescale.com>
2009-07-15 14:06:44 +08:00
fd5482c4c0 ENGR00111465: Remove Watchdog disable codes in MX51 uboot.
Remove Watchdog disable codes in MX51 uboot.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-07-14 10:58:34 +08:00
d4d00b4ceb ENGR00113611: Add FEC support for BBG2.
Add FEC support for BBG2.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-06-26 18:12:49 +08:00
41876a59ea ENGR00113475: Add auto-complete and platform prompt for each platform.
Add auto-complete and platform prompt for each platform.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-06-26 11:46:25 +08:00
bea1987d05 ENGR00113439: BBG2, enable SPI NOR and MMC in one image.
BBG2, enable SPI NOR and MMC in one image.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-06-17 18:46:49 +08:00
8c65379798 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 <r64343@freescale.com>
2009-06-09 19:15:11 +08:00
554b9ee7a6 ENGR00112845 spi nor boot and pmic support for BBG2.
spi nor boot support for BBG2.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-06-04 21:01:34 +08:00
b05d6f097d ENGR00112273 BBG2: MMC boot support.
BBG2: MMC boot support.

Signed-off-by: Terry Lv <r65388@freescale.com>
2009-05-18 14:34:00 +08:00
9cf764d379 ENGR00112298 BBG2: Basic boot.
Basic boot on BBG2 board.

Signed-off-by: r65388 <r65388@freescale.com>
2009-05-14 14:27:30 +08:00
cb4c05f8d8 ENGR00110586 MX31: Resolve Copyright issue for mx31 files
Add freescale copyright.

Signed-off-by: r65388 <r65388@freescale.com>
2009-03-31 16:21:41 +08:00
192e622a81 ENGR00109851 Add nand driver for MX51 uboot
Add nand driver for MX51 uboot

Signed-off-by:Jason Liu <r64343@freescale.com>
2009-03-19 09:43:44 +08:00
5954b33250 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 <alan.assis@freescale.com>
2009-03-05 09:26:00 -03:00
d73d39d034 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 <alan.assis@freescale.com>
2009-03-05 09:23:43 -03:00
c878dfb5f2 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 <r01011@freescale.com>
2009-02-25 17:43:09 +08:00
81fba29f2f OMAP3: Add common board, interrupt and system info
Add common board, interrupt and system info code.

Signed-off-by: Dirk Behme <dirk.behme@googlemail.com>
(cherry picked from commit 91eee54673)
2009-02-24 17:34:08 +08:00
103c17735e OMAP3: Add common clock, memory and low level code
Add common clock, memory and low level code

Signed-off-by: Dirk Behme <dirk.behme@googlemail.com>
(cherry picked from commit 5ed3e8659e)
2009-02-24 17:32:49 +08:00
d1cce6ea3e OMAP3: Add common cpu and start code
Add common cpu and start code.

Signed-off-by: Dirk Behme <dirk.behme@googlemail.com>
(cherry picked from commit 0b02b18400)
2009-02-24 17:32:31 +08:00
4cd144513e 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 <r01011@freescale.com>
2009-02-23 14:54:54 +08:00
9ffbcea76f 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 <r01011@freescale.com>
2009-02-23 14:08:23 +08:00
ad3a535c6a 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 <r01011@freescale.com>
2009-02-23 13:59:58 +08:00
93af7d33b0 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 <r01011@freescale.com>
2009-02-23 13:57:38 +08:00
38107a4d85 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 <r01011@freescale.com>
2009-02-23 13:54:46 +08:00
7508ceeeab ENGR00099697 Add nand driver for mx35
Add nand driver for mx35

Signed-off-by:Jason Liu <r64343@freescale.com>
2009-02-23 13:50:40 +08:00
e5b3a2fa60 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 <xinyu.chen@freescale.com>
2009-02-23 13:38:34 +08:00
576faf1cc5 ENGR00094618 Update .gitignore configure file
Update .gitignore configure file to ignore vim swap and ctags file

Signed-off-by: Xinyu Chen <xinyu.chen@freescale.com>
2009-02-23 13:32:44 +08:00
6dff4beda2 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 <r01011@freescale.com>
2009-02-23 12:36:31 +08:00
170 changed files with 33304 additions and 191 deletions

1
.gitignore vendored
View File

@ -13,6 +13,7 @@
*~
*.swp
*.patch
*.swp
#
# Top-level generic files

View File

@ -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 \
@ -2731,6 +2734,9 @@ netstar_config: unconfig
omap1510inn_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm925t omap1510inn
stmp378x_dev_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm926ejs stmp378x_dev NULL stmp378x
xtract_omap1610xxx = $(subst _cs0boot,,$(subst _cs3boot,,$(subst _cs_autoboot,,$(subst _config,,$1))))
omap1610inn_config \
@ -2964,6 +2970,21 @@ 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 \
mx35_3stack_mmc_config: unconfig
@$(MKCONFIG) $(@:_config=) arm arm1136 mx35_3stack freescale mx35
imx51_android_config \
imx51_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm_cortexa8 imx51 freescale mx51
mx51_3stack_android_config \
mx51_3stack_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm_cortexa8 mx51_3stack freescale mx51
omap2420h4_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm1136 omap2420h4 NULL omap24xx

View File

@ -0,0 +1,49 @@
#
# Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
#
# (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
#########################################################################

View File

@ -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__ */

View File

@ -0,0 +1 @@
TEXT_BASE = 0x97800000

View File

@ -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 <config.h>
#include <asm/arch/mx51.h>
#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

View File

@ -0,0 +1,706 @@
/*
* Copyright (C) 2007, Guennadi Liakhovetski <lg@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 <common.h>
#include <asm/io.h>
#include <asm/arch/mx51.h>
#include <asm/arch/mx51_pins.h>
#include <asm/arch/iomux.h>
#include <asm/errno.h>
#include <i2c.h>
#include <mxc_keyb.h>
#include <asm/arch/keypad.h>
#include "board-imx51.h"
#include <asm/arch/imx_spi.h>
#include <asm/arch/imx_spi_pmic.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:
if ((__REG(GPIO1_BASE_ADDR + 0x0) & (0x1 << 22)) == 0) {
system_rev = 0x51000 | CHIP_REV_2_5;
} else {
system_rev = 0x51000 | CHIP_REV_2_0;
}
break;
case 0x20:
system_rev = 0x51000 | CHIP_REV_3_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);
/* enable GPIO1_9 for CLK0 and GPIO1_8 for CLK02 */
writel(0x00000004, 0x73fa83e8);
writel(0x00000004, 0x73fa83ec);
}
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);
}
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;
}
}
static void setup_fec(void)
{
/*FEC_MDIO*/
writel(0x3, IOMUXC_BASE_ADDR + 0x0D4);
writel(0x1FD, IOMUXC_BASE_ADDR + 0x0468);
writel(0x0, IOMUXC_BASE_ADDR + 0x0954);
/*FEC_MDC*/
writel(0x2, IOMUXC_BASE_ADDR + 0x13C);
writel(0x2004, IOMUXC_BASE_ADDR + 0x0524);
/* FEC RDATA[3] */
writel(0x3, IOMUXC_BASE_ADDR + 0x0EC);
writel(0x180, IOMUXC_BASE_ADDR + 0x0480);
writel(0x0, IOMUXC_BASE_ADDR + 0x0964);
/* FEC RDATA[2] */
writel(0x3, IOMUXC_BASE_ADDR + 0x0E8);
writel(0x180, IOMUXC_BASE_ADDR + 0x047C);
writel(0x0, IOMUXC_BASE_ADDR + 0x0960);
/* FEC RDATA[1] */
writel(0x3, IOMUXC_BASE_ADDR + 0x0d8);
writel(0x180, IOMUXC_BASE_ADDR + 0x046C);
writel(0x0, IOMUXC_BASE_ADDR + 0x095C);
/* FEC RDATA[0] */
writel(0x2, IOMUXC_BASE_ADDR + 0x016C);
writel(0x2180, IOMUXC_BASE_ADDR + 0x0554);
writel(0x0, IOMUXC_BASE_ADDR + 0x0958);
/* FEC TDATA[3] */
writel(0x2, IOMUXC_BASE_ADDR + 0x148);
writel(0x2004, IOMUXC_BASE_ADDR + 0x0530);
/* FEC TDATA[2] */
writel(0x2, IOMUXC_BASE_ADDR + 0x144);
writel(0x2004, IOMUXC_BASE_ADDR + 0x052C);
/* FEC TDATA[1] */
writel(0x2, IOMUXC_BASE_ADDR + 0x140);
writel(0x2004, IOMUXC_BASE_ADDR + 0x0528);
/* FEC TDATA[0] */
writel(0x2, IOMUXC_BASE_ADDR + 0x0170);
writel(0x2004, IOMUXC_BASE_ADDR + 0x0558);
/* FEC TX_EN */
writel(0x1, IOMUXC_BASE_ADDR + 0x014C);
writel(0x2004, IOMUXC_BASE_ADDR + 0x0534);
/* FEC TX_ER */
writel(0x2, IOMUXC_BASE_ADDR + 0x0138);
writel(0x2004, IOMUXC_BASE_ADDR + 0x0520);
/* FEC TX_CLK */
writel(0x1, IOMUXC_BASE_ADDR + 0x0150);
writel(0x2180, IOMUXC_BASE_ADDR + 0x0538);
writel(0x0, IOMUXC_BASE_ADDR + 0x0974);
/* FEC COL */
writel(0x1, IOMUXC_BASE_ADDR + 0x0124);
writel(0x2180, IOMUXC_BASE_ADDR + 0x0500);
writel(0x0, IOMUXC_BASE_ADDR + 0x094c);
/* FEC RX_CLK */
writel(0x1, IOMUXC_BASE_ADDR + 0x0128);
writel(0x2180, IOMUXC_BASE_ADDR + 0x0504);
writel(0x0, IOMUXC_BASE_ADDR + 0x0968);
/* FEC CRS */
writel(0x3, IOMUXC_BASE_ADDR + 0x0f4);
writel(0x180, IOMUXC_BASE_ADDR + 0x0488);
writel(0x0, IOMUXC_BASE_ADDR + 0x0950);
/* FEC RX_ER */
writel(0x3, IOMUXC_BASE_ADDR + 0x0f0);
writel(0x180, IOMUXC_BASE_ADDR + 0x0484);
writel(0x0, IOMUXC_BASE_ADDR + 0x0970);
/* FEC RX_DV */
writel(0x2, IOMUXC_BASE_ADDR + 0x164);
writel(0x2180, IOMUXC_BASE_ADDR + 0x054C);
writel(0x0, IOMUXC_BASE_ADDR + 0x096C);
}
static void power_init(void)
{
struct spi_slave *slave;
unsigned int val;
unsigned int reg;
#define REV_ATLAS_LITE_1_0 0x8
#define REV_ATLAS_LITE_1_1 0x9
#define REV_ATLAS_LITE_2_0 0x10
#define REV_ATLAS_LITE_2_1 0x11
slave = spi_pmic_probe();
/* Write needed to Power Gate 2 register */
val = pmic_reg(slave, 34, 0, 0);
val &= ~0x10000;
pmic_reg(slave, 34, val, 1);
/* Write needed to update Charger 0 */
pmic_reg(slave, 48, 0x0023807F, 1);
/* power up the system first */
pmic_reg(slave, 34, 0x00200000, 1);
if (is_soc_rev(CHIP_REV_2_0) >= 0) {
/* Set core voltage to 1.1V */
val = pmic_reg(slave, 24, 0, 0);
val = (val & (~0x1F)) | 0x14;
pmic_reg(slave, 24, val, 1);
/* Setup VCC (SW2) to 1.25 */
val = pmic_reg(slave, 25, 0, 0);
val = (val & (~0x1F)) | 0x1A;
pmic_reg(slave, 25, val, 1);
/* Setup 1V2_DIG1 (SW3) to 1.25 */
val = pmic_reg(slave, 26, 0, 0);
val = (val & (~0x1F)) | 0x1A;
pmic_reg(slave, 26, val, 1);
udelay(50);
/* Raise the core frequency to 800MHz */
writel(0x0, CCM_BASE_ADDR + CLKCTL_CACRR);
} else {
/* TO 3.0 */
/* Setup VCC (SW2) to 1.225 */
val = pmic_reg(slave, 25, 0, 0);
val = (val & (~0x1F)) | 0x19;
pmic_reg(slave, 25, val, 1);
/* Setup 1V2_DIG1 (SW3) to 1.2 */
val = pmic_reg(slave, 26, 0, 0);
val = (val & (~0x1F)) | 0x18;
pmic_reg(slave, 26, val, 1);
}
if (((pmic_reg(slave, 7, 0, 0) & 0x1F) < REV_ATLAS_LITE_2_0) ||
(((pmic_reg(slave, 7, 0, 0) >> 9) & 0x3) == 0)) {
/* Set switchers in PWM mode for Atlas 2.0 and lower */
/* Setup the switcher mode for SW1 & SW2*/
val = pmic_reg(slave, 28, 0, 0);
val = (val & (~0x3C0F)) | 0x1405;
pmic_reg(slave, 28, val, 1);
/* Setup the switcher mode for SW3 & SW4 */
val = pmic_reg(slave, 29, 0, 0);
val = (val & (~0xF0F)) | 0x505;
pmic_reg(slave, 29, val, 1);
} else {
/* Set switchers in Auto in NORMAL mode & STANDBY mode for Atlas 2.0a */
/* Setup the switcher mode for SW1 & SW2*/
val = pmic_reg(slave, 28, 0, 0);
val = (val & (~0x3C0F)) | 0x2008;
pmic_reg(slave, 28, val, 1);
/* Setup the switcher mode for SW3 & SW4 */
val = pmic_reg(slave, 29, 0, 0);
val = (val & (~0xF0F)) | 0x808;
pmic_reg(slave, 29, val, 1);
}
/* Set VDIG to 1.65V, VGEN3 to 1.8V, VCAM to 2.5V */
val = pmic_reg(slave, 30, 0, 0);
val &= ~0x34030;
val |= 0x10020;
pmic_reg(slave, 30, val, 1);
/* Set VVIDEO to 2.775V, VAUDIO to 3V, VSD to 3.15V */
val = pmic_reg(slave, 31, 0, 0);
val &= ~0x1FC;
val |= 0x1F4;
pmic_reg(slave, 31, val, 1);
/* Configure VGEN3 and VCAM regulators to use external PNP */
val = 0x208;
pmic_reg(slave, 33, val, 1);
udelay(200);
reg = readl(GPIO2_BASE_ADDR + 0x0);
reg &= ~0x4000; /* Lower reset line */
writel(reg, GPIO2_BASE_ADDR + 0x0);
reg = readl(GPIO2_BASE_ADDR + 0x4);
reg |= 0x4000; /* configure GPIO lines as output */
writel(reg, GPIO2_BASE_ADDR + 0x4);
/* Reset the ethernet controller over GPIO */
writel(0x1, IOMUXC_BASE_ADDR + 0x0AC);
/* Enable VGEN3, VCAM, VAUDIO, VVIDEO, VSD regulators */
val = 0x49249;
pmic_reg(slave, 33, val, 1);
udelay(500);
reg = readl(GPIO2_BASE_ADDR + 0x0);
reg |= 0x4000;
writel(reg, GPIO2_BASE_ADDR + 0x0);
spi_pmic_free(slave);
}
#ifdef CONFIG_NET_MULTI
#if defined(CONFIG_DRIVER_SMC911X)
extern int smc911x_initialize(bd_t *bis);
#endif
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;
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:
esdhc_base_pointer = (volatile u32 *)MMC_SDHC2_BASE_ADDR;
mxc_request_iomux(MX51_PIN_SD2_CMD,
IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION);
mxc_request_iomux(MX51_PIN_SD2_CLK,
IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION);
mxc_request_iomux(MX51_PIN_SD2_DATA0,
IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_SD2_DATA1,
IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_SD2_DATA2,
IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_SD2_DATA3,
IOMUX_CONFIG_ALT0);
mxc_iomux_set_pad(MX51_PIN_SD2_CMD,
PAD_CTL_DRV_MAX | PAD_CTL_22K_PU |
PAD_CTL_SRE_FAST);
mxc_iomux_set_pad(MX51_PIN_SD2_CLK,
PAD_CTL_DRV_MAX | PAD_CTL_22K_PU |
PAD_CTL_SRE_FAST);
mxc_iomux_set_pad(MX51_PIN_SD2_DATA0,
PAD_CTL_DRV_MAX | PAD_CTL_22K_PU |
PAD_CTL_SRE_FAST);
mxc_iomux_set_pad(MX51_PIN_SD2_DATA1,
PAD_CTL_DRV_MAX | PAD_CTL_22K_PU |
PAD_CTL_SRE_FAST);
mxc_iomux_set_pad(MX51_PIN_SD2_DATA2,
PAD_CTL_DRV_MAX | PAD_CTL_22K_PU |
PAD_CTL_SRE_FAST);
mxc_iomux_set_pad(MX51_PIN_SD2_DATA3,
PAD_CTL_DRV_MAX | PAD_CTL_22K_PU |
PAD_CTL_SRE_FAST);
break;
case 2:
status = 1;
break;
case 3:
status = 1;
break;
default:
status = 1;
break;
}
return status = 1;
}
#endif
#if defined(CONFIG_MXC_KPD)
int setup_mxc_kpd()
{
mxc_request_iomux(MX51_PIN_KEY_COL0, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_COL1, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_COL2, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_COL3, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_COL4, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_COL5, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_ROW0, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_ROW1, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_ROW2, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_ROW3, IOMUX_CONFIG_ALT0);
return 0;
}
#endif
int board_init(void)
{
setup_soc_rev();
gd->bd->bi_arch_number = MACH_TYPE_MX51_BABBAGE; /* board id for linux */
/* address of boot parameters */
gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
setup_uart();
setup_nfc();
setup_expio();
setup_fec();
return 0;
}
#ifdef BOARD_LATE_INIT
int board_late_init(void)
{
#if defined(CONFIG_FSL_ANDROID) && defined(CONFIG_MXC_KPD)
struct kpp_key_info key_info = {0, 0};
int switch_delay = CONFIG_ANDROID_BOOTMOD_DELAY;
int state = 0, boot_mode_switch = 0;
#endif
power_init();
#if defined(CONFIG_FSL_ANDROID) && defined(CONFIG_MXC_KPD)
mxc_kpp_init();
puts("Press home + power to enter recovery mode ...\n");
while ((switch_delay > 0) && (!boot_mode_switch)) {
int i;
--switch_delay;
/* delay 100 * 10ms */
for (i = 0; !boot_mode_switch && i < 100; ++i) {
/* A state machine to scan home + power key */
/* Check for home + power */
if (mxc_kpp_getc(&key_info)) {
switch (state) {
case 0:
/* First press */
if (TEST_HOME_KEY_DEPRESS(key_info.val, key_info.evt)) {
/* Press Home */
state = 1;
} else if (TEST_POWER_KEY_DEPRESS(key_info.val, key_info.evt)) {
state = 2;
} else {
state = 0;
}
break;
case 1:
/* Home is already pressed, try to detect Power */
if (TEST_POWER_KEY_DEPRESS(key_info.val,
key_info.evt)) {
boot_mode_switch = 1;
} else {
if (TEST_HOME_KEY_DEPRESS(key_info.val,
key_info.evt))
state = 1;
else
state = 0;
}
break;
case 2:
/* Power is already pressed, try to detect Home */
if (TEST_HOME_KEY_DEPRESS(key_info.val,
key_info.evt)) {
boot_mode_switch = 1;
} else {
if (TEST_POWER_KEY_DEPRESS(key_info.val,
key_info.evt))
state = 2;
else
state = 0;
}
break;
default:
break;
}
if (1 == boot_mode_switch) {
printf("Boot mode switched to recovery mode!\n");
/* Set env to recovery mode */
setenv("bootargs_android", CONFIG_ANDROID_RECOVERY_BOOTARGS);
setenv("bootcmd_android", CONFIG_ANDROID_RECOVERY_BOOTCMD);
setenv("bootcmd", "run bootcmd_android");
break;
}
}
}
for (i = 0; i < 100; ++i)
udelay(10000);
}
#endif
return 0;
}
#endif
int checkboard(void)
{
printf("Board: MX51 BABBAGE ");
switch (system_rev & 0xff) {
case CHIP_REV_3_0:
printf("3.0 [");
break;
case CHIP_REV_2_5:
printf("2.5 [");
break;
case CHIP_REV_2_0:
printf("2.0 [");
break;
case CHIP_REV_1_1:
printf("1.1 [");
break;
case CHIP_REV_1_0:
default:
printf("1.0 [");
break;
}
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;
}

View File

@ -0,0 +1,319 @@
/*
* Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
*
* (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 <config.h>
#include <asm/arch/mx51.h>
#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
/* explicitly disable L2 cache */
mrc 15, 0, r0, c1, c0, 1
bic r0, r0, #0x2
mcr 15, 0, r0, c1, c0, 1
/* reconfigure L2 cache aux control reg */
mov r0, #0xC0 /* tag RAM */
add r0, r0, #0x4 /* data RAM */
orr r0, r0, #(1 << 24) /* disable write allocate delay */
orr r0, r0, #(1 << 23) /* disable write allocate combine */
orr r0, r0, #(1 << 22) /* disable write allocate */
cmp r3, #0x10 /* r3 contains the silicon rev */
orrls r0, r0, #(1 << 25) /* disable write combine for TO 2 and lower revs */
mcr 15, 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
/* Gate of clocks to the peripherals first */
ldr r1, =0x3FFFFFFF
str r1, [r0, #CLKCTL_CCGR0]
ldr r1, =0x0
str r1, [r0, #CLKCTL_CCGR1]
str r1, [r0, #CLKCTL_CCGR2]
str r1, [r0, #CLKCTL_CCGR3]
ldr r1, =0x00030000
str r1, [r0, #CLKCTL_CCGR4]
ldr r1, =0x00FFF030
str r1, [r0, #CLKCTL_CCGR5]
ldr r1, =0x00000300
str r1, [r0, #CLKCTL_CCGR6]
/* Disable IPU and HSC dividers */
mov r1, #0x60000
str r1, [r0, #CLKCTL_CCDR]
/* Make sure to switch the DDR away from PLL 1 */
ldr r1, =0x19239145
str r1, [r0, #CLKCTL_CBCDR]
/* make sure divider effective */
1: ldr r1, [r0, #CLKCTL_CDHIPR]
cmp r1, #0x0
bne 1b
/* 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 r0, =CCM_BASE_ADDR
ldr r1, =0x000010C0
str r1, [r0, #CLKCTL_CBCMR]
ldr r1, =0x13239145
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 r0, =CCM_BASE_ADDR
ldr r1, =0x19239145
str r1, [r0, #CLKCTL_CBCDR]
ldr r1, =0x000020C0
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 r0, =ARM_BASE_ADDR
ldr r1, =0x00000725
str r1, [r0, #0x14]
ldr r0, =CCM_BASE_ADDR
/* Run TO 3.0 at Full speed, for other TO's wait till we increase VDDGP */
ldr r1, =0x0
ldr r3, [r1, #ROM_SI_REV]
cmp r3, #0x10
movls r1, #0x1
movhi r1, #0
str r1, [r0, #CLKCTL_CACRR]
/* Switch ARM back to PLL 1 */
mov r1, #0
str r1, [r0, #CLKCTL_CCSR]
/* setup the rest */
/* Use lp_apm (24MHz) source for perclk */
ldr r1, =0x000020C2
str r1, [r0, #CLKCTL_CBCMR]
/* ddr clock from PLL 1, all perclk dividers are 1 since using 24MHz */
ldr r1, =0x59E35100
str r1, [r0, #CLKCTL_CBCDR]
/* Restore the default values in the Gate registers */
ldr r1, =0xFFFFFFFF
str r1, [r0, #CLKCTL_CCGR0]
str r1, [r0, #CLKCTL_CCGR1]
str r1, [r0, #CLKCTL_CCGR2]
str r1, [r0, #CLKCTL_CCGR3]
str r1, [r0, #CLKCTL_CCGR4]
str r1, [r0, #CLKCTL_CCGR5]
str r1, [r0, #CLKCTL_CCGR6]
/* Use PLL 2 for UART's, get 66.5MHz from it */
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, #0x0
bne 1b
mov r1, #0x0
str r1, [r0, #CLKCTL_CCDR]
/* for cko - for ARM div by 8 */
mov r1, #0x000A0000
add r1, r1, #0x00000F0
str r1, [r0, #CLKCTL_CCOSR]
.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:
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 ENABLE_IMPRECISE_ABORT
mrs r1, spsr /* save old spsr */
mrs r0, cpsr /* read out the cpsr */
bic r0, r0, #0x100 /* clear the A bit */
msr spsr, r0 /* update spsr */
add lr, pc, #0x8 /* update lr */
movs pc, lr /* update cpsr */
nop
nop
nop
nop
msr spsr, r1 /* restore old spsr */
#endif
init_l2cc
init_aips
init_max
init_m4if
init_drive_strength
init_clock
init_debug_board
/* 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

View File

@ -0,0 +1,73 @@
/*
* January 2004 - Changed to support H4 device
* Copyright (c) 2004 Texas Instruments
*
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <gj@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
*/
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 = .;
}

View File

@ -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
#########################################################################

View File

@ -0,0 +1 @@
TEXT_BASE = 0x83F00000

View File

@ -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 <config.h>
#include <version.h>
.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

View File

@ -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 <asm/arch/mx25-regs.h>
.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

View File

@ -0,0 +1,272 @@
/*
* (c) Copyright 2009 Freescale Semiconductor
*
* (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.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 <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/mx25.h>
#include <asm/arch/mx25-regs.h>
#include <asm/arch/mx25_pins.h>
#include <asm/arch/iomux.h>
#include <asm/arch/gpio.h>
DECLARE_GLOBAL_DATA_PTR;
static u32 system_rev;
volatile u32 *esdhc_base_pointer;
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);
}
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;
}
#ifdef CONFIG_FSL_MMC
int sdhc_init(void)
{
u32 interface_esdhc = 0, val = 0;
interface_esdhc = (readl(CCM_RCSR) & (0x00300000)) >> 20;
switch (interface_esdhc) {
case 0:
esdhc_base_pointer = (volatile u32 *)MMC_SDHC1_BASE;
/* Pins */
writel(0x10, IOMUXC_BASE + 0x190); /* SD1_CMD */
writel(0x10, IOMUXC_BASE + 0x194); /* SD1_CLK */
writel(0x00, IOMUXC_BASE + 0x198); /* SD1_DATA0 */
writel(0x00, IOMUXC_BASE + 0x19c); /* SD1_DATA1 */
writel(0x00, IOMUXC_BASE + 0x1a0); /* SD1_DATA2 */
writel(0x00, IOMUXC_BASE + 0x1a4); /* SD1_DATA3 */
writel(0x06, IOMUXC_BASE + 0x094); /* D12 (SD1_DATA4) */
writel(0x06, IOMUXC_BASE + 0x090); /* D13 (SD1_DATA5) */
writel(0x06, IOMUXC_BASE + 0x08c); /* D14 (SD1_DATA6) */
writel(0x06, IOMUXC_BASE + 0x088); /* D15 (SD1_DATA7) */
writel(0x05, IOMUXC_BASE + 0x010); /* A14 (SD1_WP) */
writel(0x05, IOMUXC_BASE + 0x014); /* A15 (SD1_DET) */
/* Pads */
writel(0xD1, IOMUXC_BASE + 0x388); /* SD1_CMD */
writel(0xD1, IOMUXC_BASE + 0x38c); /* SD1_CLK */
writel(0xD1, IOMUXC_BASE + 0x390); /* SD1_DATA0 */
writel(0xD1, IOMUXC_BASE + 0x394); /* SD1_DATA1 */
writel(0xD1, IOMUXC_BASE + 0x398); /* SD1_DATA2 */
writel(0xD1, IOMUXC_BASE + 0x39c); /* SD1_DATA3 */
writel(0xD1, IOMUXC_BASE + 0x28c); /* D12 (SD1_DATA4) */
writel(0xD1, IOMUXC_BASE + 0x288); /* D13 (SD1_DATA5) */
writel(0xD1, IOMUXC_BASE + 0x284); /* D14 (SD1_DATA6) */
writel(0xD1, IOMUXC_BASE + 0x280); /* D15 (SD1_DATA7) */
writel(0xD1, IOMUXC_BASE + 0x230); /* A14 (SD1_WP) */
writel(0xD1, IOMUXC_BASE + 0x234); /* A15 (SD1_DET) */
/*
* Set write protect and card detect gpio as inputs
* A14 (SD1_WP) and A15 (SD1_DET)
*/
val = ~(3 << 0) & readl(GPIO1_BASE + GPIO_GDIR);
writel(val, GPIO1_BASE + GPIO_GDIR);
break;
case 1:
esdhc_base_pointer = (volatile u32 *)MMC_SDHC2_BASE;
/* Pins */
writel(0x16, IOMUXC_BASE + 0x0e8); /* LD8 (SD1_CMD) */
writel(0x16, IOMUXC_BASE + 0x0ec); /* LD9 (SD1_CLK) */
writel(0x06, IOMUXC_BASE + 0x0f0); /* LD10 (SD1_DATA0) */
writel(0x06, IOMUXC_BASE + 0x0f4); /* LD11 (SD1_DATA1) */
writel(0x06, IOMUXC_BASE + 0x0f8); /* LD12 (SD1_DATA2) */
writel(0x06, IOMUXC_BASE + 0x0fc); /* LD13 (SD1_DATA3) */
writel(0x02, IOMUXC_BASE + 0x120); /* CSI_D2 (SD1_DATA4) */
writel(0x02, IOMUXC_BASE + 0x124); /* CSI_D3 (SD1_DATA5) */
writel(0x02, IOMUXC_BASE + 0x128); /* CSI_D4 (SD1_DATA6) */
writel(0x02, IOMUXC_BASE + 0x12c); /* CSI_D5 (SD1_DATA7) */
/* Pads */
writel(0xD1, IOMUXC_BASE + 0x2e0); /* LD8 (SD1_CMD) */
writel(0xD1, IOMUXC_BASE + 0x2e4); /* LD9 (SD1_CLK) */
writel(0xD1, IOMUXC_BASE + 0x2e8); /* LD10 (SD1_DATA0) */
writel(0xD1, IOMUXC_BASE + 0x2ec); /* LD11 (SD1_DATA1) */
writel(0xD1, IOMUXC_BASE + 0x2f0); /* LD12 (SD1_DATA2) */
writel(0xD1, IOMUXC_BASE + 0x2f4); /* LD13 (SD1_DATA3) */
writel(0xD1, IOMUXC_BASE + 0x318); /* CSI_D2 (SD1_DATA4) */
writel(0xD1, IOMUXC_BASE + 0x31c); /* CSI_D3 (SD1_DATA5) */
writel(0xD1, IOMUXC_BASE + 0x320); /* CSI_D4 (SD1_DATA6) */
writel(0xD1, IOMUXC_BASE + 0x324); /* CSI_D5 (SD1_DATA7) */
break;
default:
break;
}
return 0;
}
#endif
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;
}

View File

@ -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, <gj@denx.de>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
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 = .;
}

View File

@ -0,0 +1,47 @@
#
# Copyright (C) 2008, Guennadi Liakhovetski <lg@denx.de>
#
# 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
#########################################################################

View File

@ -0,0 +1 @@
TEXT_BASE = 0x87f00000

View File

@ -0,0 +1,248 @@
/*
* Copyright (C) 2008, Guennadi Liakhovetski <lg@denx.de>
* 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 <asm/arch/mx31-regs.h>
.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))

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2008, Guennadi Liakhovetski <lg@denx.de>
* 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 <common.h>
#include <asm/io.h>
#include <asm/arch/mx31.h>
#include <asm/arch/mx31-regs.h>
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_CTS1__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;
}

View File

@ -0,0 +1,72 @@
/*
* Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
*
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(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/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 = .;
}

View File

@ -0,0 +1,50 @@
#
# Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
#
# (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
SOBJS += 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
#########################################################################

View File

@ -0,0 +1,107 @@
/*
*
* (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.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
*/
#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 */

View File

@ -0,0 +1 @@
TEXT_BASE = 0x87800000

View File

@ -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 <config.h>
#include <asm/arch/mx35.h>
#include "board-mx35_3stack.h"
#ifdef CONFIG_FLASH_HEADER
#ifndef CONFIG_FLASH_HEADER_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 CONFIG_FLASH_HEADER_OFFSET
app_code_jump_v: .long GEN_FHEADERADDR(_start)
app_code_barker: .long CONFIG_FLASH_HEADER_BARKER
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

View File

@ -0,0 +1,441 @@
/*
* Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
*
* (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 <config.h>
#include <asm/arch/mx35.h>
#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_REV
ldreq \ret, [\tmp]
moveq \ret, \ret, lsl #4
addne \ret, \ret, #0x10
.endm
/*
* 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 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]
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]
check_soc_version r1, r2
cmp r1, #CHIP_REV_2_0
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
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
check_soc_version r3, r4
cmp r1, #CHIP_REV_2_0
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 */
.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 */
/* 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_l2cc
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 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
* 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

View File

@ -0,0 +1,402 @@
/*
* Copyright (C) 2007, Guennadi Liakhovetski <lg@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 <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/mx35.h>
#include <asm/arch/mx35_pins.h>
#include <asm/arch/iomux.h>
#include <i2c.h>
#include <linux/types.h>
DECLARE_GLOBAL_DATA_PTR;
volatile u32 *esdhc_base_pointer;
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_REV);
reg <<= 4;
} else
reg += CHIP_REV_1_0;
system_rev = 0x35000 + (reg & 0xFF);
}
static inline void set_board_rev(int rev)
{
int reg;
system_rev = (system_rev & ~(0xF << 8)) | (rev & 0xF) << 8;
}
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;
}
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;
/* 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
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;
}
set_board_rev(0);
return 0;
}
int board_late_init(void)
{
u8 reg[3];
int i;
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[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, reg, 1) < 0) {
printf("board_late_init: read PMIC@0x69:0x1A fail\n");
return 0;
}
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[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;
}
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;
}
int board_eth_init(bd_t *bis)
{
int rc = -ENODEV;
#if defined(CONFIG_DRIVER_SMC911X)
rc = smc911x_initialize(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

View File

@ -0,0 +1,77 @@
/*
* January 2004 - Changed to support H4 device
* Copyright (c) 2004 Texas Instruments
*
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <gj@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
*/
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/mx35_3stack/flash_header.o (.text.flasheader)
*(.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)
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 = .;
}

View File

@ -0,0 +1,49 @@
#
# Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
#
# (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
#########################################################################

View File

@ -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__ */

View File

@ -0,0 +1 @@
TEXT_BASE = 0x97800000

View File

@ -0,0 +1,164 @@
/*
* 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 <config.h>
#include <asm/arch/mx51.h>
#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 */
#ifdef CONFIG_IMX51_MDDR
/* Control, Data, Address pads are in their default state: HIGH DS, FAST SR.*/
+MXC_DCD_ITEM(1, 4, IOMUXC_BASE_ADDR + 0x4b8, 0x000000e7) /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK MAX DS */
+MXC_DCD_ITEM(2, 4, IOMUXC_BASE_ADDR + 0x4d4, 0x000000e4) /* DQM0 DS high, slew rate slow */
+MXC_DCD_ITEM(3, 4, IOMUXC_BASE_ADDR + 0x4d8, 0x000000e4) /* DQM1 DS high, slew rate slow */
+MXC_DCD_ITEM(4, 4, IOMUXC_BASE_ADDR + 0x4dc, 0x000000e4) /* DQM2 DS high, slew rate slow */
+MXC_DCD_ITEM(5, 4, IOMUXC_BASE_ADDR + 0x4e0, 0x000000e4) /* DQM3 DS high, slew rate slow */
+MXC_DCD_ITEM(6, 4, IOMUXC_BASE_ADDR + 0x4bc, 0x000000c4) /* SDQS0 DS high, slew rate slow */
+MXC_DCD_ITEM(7, 4, IOMUXC_BASE_ADDR + 0x4c0, 0x000000c4) /* SDQS1 DS high, slew rate slow */
+MXC_DCD_ITEM(8, 4, IOMUXC_BASE_ADDR + 0x4c4, 0x000000c4) /* SDQS2 DS high, slew rate slow */
+MXC_DCD_ITEM(9, 4, IOMUXC_BASE_ADDR + 0x4c8, 0x000000c4) /* SDQS3 DS high, slew rate slow */
+MXC_DCD_ITEM(10, 4, IOMUXC_BASE_ADDR + 0x8a4, 0x00000004) /* DRAM_B0 */
+MXC_DCD_ITEM(11, 4, IOMUXC_BASE_ADDR + 0x8ac, 0x00000004) /* DRAM_B1 */
+MXC_DCD_ITEM(12, 4, IOMUXC_BASE_ADDR + 0x8b8, 0x00000004) /* DRAM_B2 */
+MXC_DCD_ITEM(13, 4, IOMUXC_BASE_ADDR + 0x82c, 0x00000004) /* DRAM_B3 */
+MXC_DCD_ITEM(14, 4, IOMUXC_BASE_ADDR + 0x878, 0x00000000) /* DRAM_B0_SR */
+MXC_DCD_ITEM(15, 4, IOMUXC_BASE_ADDR + 0x880, 0x00000000) /* DRAM_B1_SR */
+MXC_DCD_ITEM(16, 4, IOMUXC_BASE_ADDR + 0x88c, 0x00000000) /* DRAM_B2_SR */
+MXC_DCD_ITEM(17, 4, IOMUXC_BASE_ADDR + 0x89c, 0x00000000) /* DRAM_B3_SR */
+// Configure CS0
+MXC_DCD_ITEM(18, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL0, 0x83220000) /* ESDCTL0: Enable controller */
+MXC_DCD_ITEM(19, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x04008008) /* ESDSCR: Precharge command */
+MXC_DCD_ITEM(20, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008010) /* ESDSCR: Refresh command */
+MXC_DCD_ITEM(21, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008010) /* ESDSCR: Refresh command */
+MXC_DCD_ITEM(22, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00338018) /* ESDSCR: LMR with CAS=3 and BL=3 (Burst Length = 8) */
+MXC_DCD_ITEM(23, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0060801a) /* ESDSCR: EMR with Half Drive strength */
+MXC_DCD_ITEM(24, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008000) /* ESDSCR */
+MXC_DCD_ITEM(25, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL0, 0xC3220000) /* ESDCTL0: 14 ROW, 10 COL, 32Bit, SREF=8 */
+/* ESDCFG0: tRFC:22clks, tXSR:28clks, tXP:2clks, tWTR:2clk, tRP:3clks, tMRD:2clks
+/* tRAS:8clks, tRRD:2clks, tWR:3clks, tRCD:3clks, tRC:11clks */
+MXC_DCD_ITEM(26, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCFG0, 0xC33574AA)
+MXC_DCD_ITEM(27, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDMISC, 0x000a1700) /* ESDMISC: AP=10, Bank interleaving on, MIF3 en, RALAT=2 */
+/* Configure CS1 */
+MXC_DCD_ITEM(28, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL1, 0x83220000) /* ESDCTL1: Enable controller */
+MXC_DCD_ITEM(29, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0400800c) /* ESDSCR: Precharge command */
+MXC_DCD_ITEM(30, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008014) /* ESDSCR: Refresh command */
+MXC_DCD_ITEM(31, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008014) /* ESDSCR: Refresh command */
+MXC_DCD_ITEM(32, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0033801c) /* ESDSCR: LMR with CAS=3 and BL=3 (Burst Length = 8) */
+MXC_DCD_ITEM(33, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0060801e) /* ESDSCR: EMR with Half Drive strength */
+MXC_DCD_ITEM(34, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008004) /* ESDSCR */
+MXC_DCD_ITEM(35, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL1, 0xC3220000) /* ESDCTL1: 14 ROW, 10 COL, 32Bit, SREF=8 */
+/* ESDCFG0: tRFC:22clks, tXSR:28clks, tXP:2clks, tWTR:2clk, tRP:3clks, tMRD:2clks */
+/* tRAS:8clks, tRRD:2clks, tWR:3clks, tRCD:3clks, tRC:11clks */
+MXC_DCD_ITEM(36, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCFG1, 0xC33574AA)
+MXC_DCD_ITEM(37, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00000000) /* ESDSCR - clear "configuration request" bit */
+MXC_DCD_ITEM(38, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCDLY5, 0x00f58000) /*Delay line write - -11 */
#else
/* 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)
/* 13 ROW, 10 COL, 32Bit, SREF=4 Micron Model */
/* CAS=3, BL=4 */
MXC_DCD_ITEM(19, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL0, 0x82a20000)
MXC_DCD_ITEM(20, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL1, 0x82a20000)
MXC_DCD_ITEM(21, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDMISC, 0x000ad0d0)
MXC_DCD_ITEM(22, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCFG0, 0x333574aa)
MXC_DCD_ITEM(23, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCFG1, 0x333574aa)
/* Init DRAM on CS0 */
MXC_DCD_ITEM(24, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x04008008)
MXC_DCD_ITEM(25, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801a)
MXC_DCD_ITEM(26, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801b)
MXC_DCD_ITEM(27, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00448019)
MXC_DCD_ITEM(28, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x07328018)
MXC_DCD_ITEM(29, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x04008008)
MXC_DCD_ITEM(30, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008010)
MXC_DCD_ITEM(31, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008010)
MXC_DCD_ITEM(32, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x06328018)
MXC_DCD_ITEM(33, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x03808019)
MXC_DCD_ITEM(34, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00408019)
MXC_DCD_ITEM(35, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008000)
/* Init DRAM on CS1 */
MXC_DCD_ITEM(36, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0400800c)
MXC_DCD_ITEM(37, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801e)
MXC_DCD_ITEM(39, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801f)
MXC_DCD_ITEM(40, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0000801d)
MXC_DCD_ITEM(41, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0732801c)
MXC_DCD_ITEM(42, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0400800c)
MXC_DCD_ITEM(43, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008014)
MXC_DCD_ITEM(44, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008014)
MXC_DCD_ITEM(45, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0632801c)
MXC_DCD_ITEM(46, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0380801d)
MXC_DCD_ITEM(47, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x0040801d)
MXC_DCD_ITEM(48, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00008004)
MXC_DCD_ITEM(49, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL0, 0xb2a20000)
MXC_DCD_ITEM(50, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCTL1, 0xb2a20000)
MXC_DCD_ITEM(51, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDMISC, 0x000ad6d0)
MXC_DCD_ITEM(52, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCDLYGD, 0x90000000)
MXC_DCD_ITEM(53, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDSCR, 0x00000000)
/* Delay settings */
MXC_DCD_ITEM(57, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCDLY1, 0x00048000)
MXC_DCD_ITEM(58, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCDLY2, 0x000e8000)
MXC_DCD_ITEM(59, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCDLY3, 0x00ff8000)
MXC_DCD_ITEM(60, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCDLY4, 0x00fa8000)
MXC_DCD_ITEM(61, 4, ESDCTL_BASE_ADDR + ESDCTL_ESDCDLY5, 0x00ed8000)
#endif
dcd_data_end:
image_len: .word 0x40000
//image_len: .word _end - _start
#endif

View File

@ -0,0 +1,348 @@
/*
* Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
*
* (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 <config.h>
#include <asm/arch/mx51.h>
#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
/* explicitly disable L2 cache */
mrc 15, 0, r0, c1, c0, 1
bic r0, r0, #0x2
mcr 15, 0, r0, c1, c0, 1
/* reconfigure L2 cache aux control reg */
mov r0, #0xC0 /* tag RAM */
add r0, r0, #0x4 /* data RAM */
orr r0, r0, #(1 << 24) /* disable write allocate delay */
orr r0, r0, #(1 << 23) /* disable write allocate combine */
orr r0, r0, #(1 << 22) /* disable write allocate */
ldr r1, =0x00000000
ldr r3, [r1, #ROM_SI_REV]
cmp r3, #0x10
orrls r0, r0, #(1 << 25) /* disable write combine for TO 2 and lower revs */
mcr 15, 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]
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
/* Gate of clocks to the peripherals first */
ldr r1, =0x3FFFFFFF
str r1, [r0, #CLKCTL_CCGR0]
ldr r1, =0x0
str r1, [r0, #CLKCTL_CCGR1]
str r1, [r0, #CLKCTL_CCGR2]
str r1, [r0, #CLKCTL_CCGR3]
ldr r1, =0x00030000
str r1, [r0, #CLKCTL_CCGR4]
ldr r1, =0x00FFF030
str r1, [r0, #CLKCTL_CCGR5]
ldr r1, =0x00000300
str r1, [r0, #CLKCTL_CCGR6]
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 r0, =CCM_BASE_ADDR
ldr r1, =0x000010C0
str r1, [r0, #CLKCTL_CBCMR]
ldr r1, =0x13239145
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 r0, =CCM_BASE_ADDR
ldr r1, =0x19239145
str r1, [r0, #CLKCTL_CBCDR]
ldr r1, =0x000020C0
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]
ldr r0, =CCM_BASE_ADDR
/* Run TO 3.0 at Full speed, for other TO's wait till we increase VDDGP */
ldr r1, =0x00000000
ldr r3, [r1, #ROM_SI_REV]
cmp r3, #0x10
movls r1, #0x1
movhi r1, #0
str r1, [r0, #CLKCTL_CACRR]
/* Switch ARM back to PLL 1 */
mov r1, #0
str r1, [r0, #CLKCTL_CCSR]
/* setup the rest */
/* Use lp_apm (24MHz) source for perclk */
ldr r1, =0x000020C2
str r1, [r0, #CLKCTL_CBCMR]
/* ddr clock from PLL 1, all perclk dividers are 1 since using 24MHz */
#ifdef CONFIG_IMX51_MDDR
ldr r1, =0x61E35100
#else
ldr r1, =0x59E35100
#endif
str r1, [r0, #CLKCTL_CBCDR]
/* Restore the default values in the Gate registers */
ldr r1, =0xFFFFFFFF
str r1, [r0, #CLKCTL_CCGR0]
str r1, [r0, #CLKCTL_CCGR1]
str r1, [r0, #CLKCTL_CCGR2]
str r1, [r0, #CLKCTL_CCGR3]
str r1, [r0, #CLKCTL_CCGR4]
str r1, [r0, #CLKCTL_CCGR5]
str r1, [r0, #CLKCTL_CCGR6]
/* Use PLL 2 for UART's, get 66.5MHz from it */
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]
/* for cko - for ARM div by 8 */
mov r1, #0x000A0000
add r1, r1, #0x00000F0
str r1, [r0, #CLKCTL_CCOSR]
.endm
.macro setup_wdog
ldr r0, =WDOG1_BASE_ADDR
mov r1, #0x30
strh r1, [r0]
.endm
.macro setup_sdram
ldr r0, =ESDCTL_BASE_ADDR
/* 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*/
ldr r0, =GPC_BASE_ADDR
ldr r1, =0x1FC00000
str r1, [r0, #4]
#ifdef ENABLE_IMPRECISE_ABORT
mrs r1, spsr /* save old spsr */
mrs r0, cpsr /* read out the cpsr */
bic r0, r0, #0x100 /* clear the A bit */
msr spsr, r0 /* update spsr */
add lr, pc, #0x8 /* update lr */
movs pc, lr /* update cpsr */
nop
nop
nop
nop
msr spsr, r1 /* restore old spsr */
#endif
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

View File

@ -0,0 +1,590 @@
/*
* Copyright (C) 2007, Guennadi Liakhovetski <lg@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 <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/mx51.h>
#include <asm/arch/mx51_pins.h>
#include <asm/arch/iomux.h>
#ifdef CONFIG_I2C_MXC
#include <i2c.h>
#endif
#include <mxc_keyb.h>
#include <asm/arch/keypad.h>
#include "board-mx51_3stack.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);
}
#ifdef CONFIG_I2C_MXC
static void setup_i2c(unsigned int module_base)
{
unsigned int reg;
switch (module_base) {
case I2C1_BASE_ADDR:
reg = IOMUXC_BASE_ADDR + 0x210; /* i2c SDA */
writel(0x11, reg);
reg = IOMUXC_BASE_ADDR + 0x600;
writel(0x1ad, reg);
reg = IOMUXC_BASE_ADDR + 0x9B4;
writel(0x1, reg);
reg = IOMUXC_BASE_ADDR + 0x224; /* i2c SCL */
writel(0x11, reg);
reg = IOMUXC_BASE_ADDR + 0x614;
writel(0x1ad, reg);
reg = IOMUXC_BASE_ADDR + 0x9B0;
writel(0x1, reg);
break;
case I2C2_BASE_ADDR:
/* Workaround for Atlas Lite */
writel(0x0, IOMUXC_BASE_ADDR + 0x3CC); /* i2c SCL */
writel(0x0, IOMUXC_BASE_ADDR + 0x3D0); /* i2c SDA */
reg = readl(GPIO1_BASE_ADDR + 0x0);
reg |= 0xC; /* write a 1 on the SCL and SDA lines */
writel(reg, GPIO1_BASE_ADDR + 0x0);
reg = readl(GPIO1_BASE_ADDR + 0x4);
reg |= 0xC; /* configure GPIO lines as output */
writel(reg, GPIO1_BASE_ADDR + 0x4);
reg = readl(GPIO1_BASE_ADDR + 0x0);
reg &= ~0x4 ; /* set SCL low for a few milliseconds */
writel(reg, GPIO1_BASE_ADDR + 0x0);
udelay(20000);
reg |= 0x4;
writel(reg, GPIO1_BASE_ADDR + 0x0);
udelay(10);
reg = readl(GPIO1_BASE_ADDR + 0x4);
reg &= ~0xC; /* configure GPIO lines back as input */
writel(reg, GPIO1_BASE_ADDR + 0x4);
writel(0x12, IOMUXC_BASE_ADDR + 0x3CC); /* i2c SCL */
writel(0x3, IOMUXC_BASE_ADDR + 0x9B8);
writel(0x1ed, IOMUXC_BASE_ADDR + 0x7D4);
writel(0x12, IOMUXC_BASE_ADDR + 0x3D0); /* i2c SDA */
writel(0x3, IOMUXC_BASE_ADDR + 0x9BC);
writel(0x1ed, IOMUXC_BASE_ADDR + 0x7D8);
break;
default:
printf("Invalid I2C base: 0x%x\n", module_base);
break;
}
}
#define REV_ATLAS_LITE_1_0 0x8
#define REV_ATLAS_LITE_1_1 0x9
#define REV_ATLAS_LITE_2_0 0x10
#define REV_ATLAS_LITE_2_1 0x11
void setup_core_voltages(void)
{
unsigned char buf[4] = { 0 };
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
if (is_soc_rev(CHIP_REV_2_0) <= 0) {
/* Set core voltage to 1.1V */
if (i2c_read(0x8, 24, 1, buf, 3)) {
puts("setup_core_voltages: read PMIC@0x08:0x18 fail\n");
return;
}
buf[2] = (buf[2] & (~0x1F)) | 0x14;
if (i2c_write(0x8, 24, 1, buf, 3)) {
puts("setup_core_voltages: write PMIC@0x08:0x18 fail\n");
return;
}
/* Setup VCC (SW2) to 1.25 */
if (i2c_read(0x8, 25, 1, buf, 3)) {
puts("setup_core_voltages: read PMIC@0x08:0x19 fail\n");
return;
}
buf[2] = (buf[2] & (~0x1F)) | 0x1A;
if (i2c_write(0x8, 25, 1, buf, 3)) {
puts("setup_core_voltages: write PMIC@0x08:0x19 fail\n");
return;
}
/* Setup 1V2_DIG1 (SW3) to 1.25 */
if (i2c_read(0x8, 26, 1, buf, 3)) {
puts("setup_core_voltages: read PMIC@0x08:0x1A fail\n");
return;
}
buf[2] = (buf[2] & (~0x1F)) | 0x1A;
if (i2c_write(0x8, 26, 1, buf, 3)) {
puts("setup_core_voltages: write PMIC@0x08:0x1A fail\n");
return;
}
udelay(50);
/* Raise the core frequency to 800MHz */
writel(0x0, CCM_BASE_ADDR + CLKCTL_CACRR);
} else {
/* TO 3.0 */
/* Setup VCC (SW2) to 1.225 */
if (i2c_read(0x8, 25, 1, buf, 3)) {
puts("setup_core_voltages: read PMIC@0x08:0x19 fail\n");
return;
}
buf[2] = (buf[2] & (~0x1F)) | 0x19;
if (i2c_write(0x8, 25, 1, buf, 3)) {
puts("setup_core_voltages: write PMIC@0x08:0x19 fail\n");
return;
}
/* Setup 1V2_DIG1 (SW3) to 1.2 */
if (i2c_read(0x8, 26, 1, buf, 3)) {
puts("setup_core_voltages: read PMIC@0x08:0x1A fail\n");
return;
}
buf[2] = (buf[2] & (~0x1F)) | 0x18;
if (i2c_write(0x8, 26, 1, buf, 3)) {
puts("setup_core_voltages: write PMIC@0x08:0x1A fail\n");
return;
}
}
if (i2c_read(0x8, 7, 1, buf, 3)) {
puts("setup_core_voltages: read PMIC@0x08:0x07 fail\n");
return;
}
if (((buf[2] & 0x1F) < REV_ATLAS_LITE_2_0) || (((buf[1] >> 1) & 0x3) == 0)) {
/* Set switchers in PWM mode for Atlas 2.0 and lower */
/* Setup the switcher mode for SW1 & SW2*/
if (i2c_read(0x8, 28, 1, buf, 3)) {
puts("setup_core_voltages: read PMIC@0x08:0x1C fail\n");
return;
}
buf[2] = (buf[2] & (~0xF)) | 0x5;
buf[1] = (buf[1] & (~0x3C)) | 0x14;
if (i2c_write(0x8, 28, 1, buf, 3)) {
puts("setup_core_voltages: write PMIC@0x08:0x1C fail\n");
return;
}
/* Setup the switcher mode for SW3 & SW4*/
if (i2c_read(0x8, 29, 1, buf, 3)) {
puts("setup_core_voltages: read PMIC@0x08:0x1D fail\n");
return;
}
buf[2] = (buf[2] & (~0xF)) | 0x5;
buf[1] = (buf[1] & (~0xF)) | 0x5;
if (i2c_write(0x8, 29, 1, buf, 3)) {
puts("setup_core_voltages: write PMIC@0x08:0x1D fail\n");
return;
}
} else {
/* Set switchers in Auto in NORMAL mode & STANDBY mode for Atlas 2.0a */
/* Setup the switcher mode for SW1 & SW2*/
if (i2c_read(0x8, 28, 1, buf, 3)) {
puts("setup_core_voltages: read PMIC@0x08:0x1C fail\n");
return;
}
buf[2] = (buf[2] & (~0xF)) | 0x8;
buf[1] = (buf[1] & (~0x3C)) | 0x20;
if (i2c_write(0x8, 28, 1, buf, 3)) {
puts("setup_core_voltages: write PMIC@0x08:0x1C fail\n");
return;
}
/* Setup the switcher mode for SW3 & SW4*/
if (i2c_read(0x8, 29, 1, buf, 3)) {
puts("setup_core_voltages: read PMIC@0x08:0x1D fail\n");
return;
}
buf[2] = (buf[2] & (~0xF)) | 0x8;
buf[1] = (buf[1] & (~0xF)) | 0x8;
if (i2c_write(0x8, 29, 1, buf, 3)) {
puts("setup_core_voltages: write PMIC@0x08:0x1D fail\n");
return;
}
}
}
#endif
int board_init(void)
{
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();
#ifdef CONFIG_I2C_MXC
setup_i2c(I2C2_BASE_ADDR);
setup_core_voltages();
#endif
return 0;
}
#ifdef BOARD_LATE_INIT
int board_late_init(void)
{
#if defined(CONFIG_FSL_ANDROID) && defined(CONFIG_MXC_KPD)
struct kpp_key_info key_info = {0, 0};
int switch_delay = CONFIG_ANDROID_BOOTMOD_DELAY;
int state = 0, boot_mode_switch = 0;
#endif
#if defined(CONFIG_FSL_ANDROID) && defined(CONFIG_MXC_KPD)
mxc_kpp_init();
puts("Press home + power to enter recovery mode ...\n");
while ((switch_delay > 0) && (!boot_mode_switch)) {
int i;
--switch_delay;
/* delay 100 * 10ms */
for (i = 0; !boot_mode_switch && i < 100; ++i) {
/* A state machine to scan home + power key */
/* Check for home + power */
if (mxc_kpp_getc(&key_info)) {
switch (state) {
case 0:
/* First press */
if (TEST_HOME_KEY_DEPRESS(key_info.val, key_info.evt)) {
/* Press Home */
state = 1;
} else if (TEST_POWER_KEY_DEPRESS(key_info.val, key_info.evt)) {
state = 2;
} else {
state = 0;
}
break;
case 1:
/* Home is already pressed, try to detect Power */
if (TEST_POWER_KEY_DEPRESS(key_info.val,
key_info.evt)) {
boot_mode_switch = 1;
} else {
if (TEST_HOME_KEY_DEPRESS(key_info.val,
key_info.evt))
state = 2;
else
state = 0;
}
break;
case 2:
/* Power is already pressed, try to detect Home */
if (TEST_HOME_KEY_DEPRESS(key_info.val,
key_info.evt)) {
boot_mode_switch = 1;
} else {
if (TEST_POWER_KEY_DEPRESS(key_info.val,
key_info.evt))
state = 1;
else
state = 0;
}
break;
default:
break;
}
if (1 == boot_mode_switch) {
printf("Boot mode switched to recovery mode!\n");
/* Set env to recovery mode */
setenv("bootargs_android", CONFIG_ANDROID_RECOVERY_BOOTARGS);
setenv("bootcmd_android", CONFIG_ANDROID_RECOVERY_BOOTCMD);
setenv("bootcmd", "run bootcmd_android");
break;
}
}
}
for (i = 0; i < 100; ++i)
udelay(10000);
}
#endif
return 0;
}
#endif
int checkboard(void)
{
printf("Board: MX51 3STACK ");
if (system_rev & CHIP_REV_2_0) {
printf("2.0 [");
} else if (system_rev & CHIP_REV_1_1) {
printf("1.1 [");
} else {
printf("1.0 [");
}
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;
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
#if defined(CONFIG_MXC_KPD)
int setup_mxc_kpd()
{
mxc_request_iomux(MX51_PIN_KEY_COL0, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_COL1, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_COL2, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_COL3, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_COL4, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_COL5, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_ROW0, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_ROW1, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_ROW2, IOMUX_CONFIG_ALT0);
mxc_request_iomux(MX51_PIN_KEY_ROW3, IOMUX_CONFIG_ALT0);
return 0;
}
#endif

View File

@ -0,0 +1,73 @@
/*
* January 2004 - Changed to support H4 device
* Copyright (c) 2004 Texas Instruments
*
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <gj@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
*/
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)
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 = .;
}

View File

@ -0,0 +1,52 @@
#
# (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 := stmp378x_dev.o
SOBJS := lowlevel_init.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
SOBJS := $(addprefix $(obj),$(SOBJS))
$(LIB): $(obj).depend $(OBJS) $(SOBJS)
$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)
clean:
rm -f $(SOBJS) $(OBJS)
distclean: clean
rm -f $(LIB) core *.bak $(obj).depend
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View File

@ -0,0 +1,5 @@
#
# image should be loaded at 0x41008000
#
TEXT_BASE = 0x41008000

View File

@ -0,0 +1,34 @@
/*
* Board specific setup info
*
* (C) Copyright 2003, ARM Ltd.
* Philippe Robin, <philippe.robin@arm.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <config.h>
#include <version.h>
/* Set up the platform, once the cpu has been initialized */
.globl lowlevel_init
lowlevel_init:
/* All SDRAM settings are done by sdram_prep */
mov pc, lr

View File

@ -0,0 +1,158 @@
/*
*
* (c) 2008 Embedded Alley Solutions, Inc.
*
* (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 <common.h>
#include <asm/arch/stmp378x.h>
#include <asm/arch/clkctrl.h>
#include <asm/arch/pinmux.h>
#include <asm/arch/spi.h>
DECLARE_GLOBAL_DATA_PTR;
#define KHz 1000
#define MHz (1000 * KHz)
static void set_pinmux(void)
{
#if defined(CONFIG_SPI_SSP1)
/* Configure SSP1 pins for ENC28j60: 8maA */
REG_CLR(PINCTRL_BASE + PINCTRL_MUXSEL(4), 0x00003fff);
REG_CLR(PINCTRL_BASE + PINCTRL_DRIVE(8), 0X03333333);
REG_SET(PINCTRL_BASE + PINCTRL_DRIVE(8), 0x01111111);
REG_CLR(PINCTRL_BASE + PINCTRL_PULL(2), 0x0000003f);
#endif
#if defined(CONFIG_SPI_SSP2)
/* Configure SSP2 pins for ENC28j60: 8maA */
REG_CLR(PINCTRL_BASE + PINCTRL_MUXSEL(0), 0x00000fc3);
REG_SET(PINCTRL_BASE + PINCTRL_MUXSEL(0), 0x00000a82);
REG_CLR(PINCTRL_BASE + PINCTRL_MUXSEL(1), 0x00030300);
REG_SET(PINCTRL_BASE + PINCTRL_MUXSEL(1), 0x00020200);
REG_CLR(PINCTRL_BASE + PINCTRL_DRIVE(0), 0X00333003);
REG_SET(PINCTRL_BASE + PINCTRL_DRIVE(0), 0x00111001);
REG_CLR(PINCTRL_BASE + PINCTRL_DRIVE(2), 0x00030000);
REG_SET(PINCTRL_BASE + PINCTRL_DRIVE(2), 0x00010000);
REG_CLR(PINCTRL_BASE + PINCTRL_DRIVE(3), 0x00000003);
REG_SET(PINCTRL_BASE + PINCTRL_DRIVE(3), 0x00000001);
REG_CLR(PINCTRL_BASE + PINCTRL_PULL(0), 0x00100039);
#endif
}
#define IO_DIVIDER 18
static void set_clocks(void)
{
u32 ssp_source_clk, ssp_clk;
u32 ssp_div = 1;
u32 val = 0;
/*
* Configure 480Mhz IO clock
*/
/* Ungate IO_CLK and set divider */
REG_CLR(CLKCTRL_BASE + CLKCTRL_FRAC, FRAC_CLKGATEIO);
REG_CLR(CLKCTRL_BASE + CLKCTRL_FRAC, 0x3f << FRAC_IOFRAC);
REG_SET(CLKCTRL_BASE + CLKCTRL_FRAC, IO_DIVIDER << FRAC_IOFRAC);
/*
* Set SSP CLK to desired value
*/
/* Calculate SSP_CLK divider relatively to 480Mhz IO_CLK*/
ssp_source_clk = 480 * MHz;
ssp_clk = CONFIG_SSP_CLK;
ssp_div = (ssp_source_clk + ssp_clk - 1) / ssp_clk;
/* Enable SSP clock */
val = REG_RD(CLKCTRL_BASE + CLKCTRL_SSP);
val &= ~SSP_CLKGATE;
REG_WR(CLKCTRL_BASE + CLKCTRL_SSP, val);
/* Wait while clock is gated */
while (REG_RD(CLKCTRL_BASE + CLKCTRL_SSP) & SSP_CLKGATE)
;
/* Set SSP clock divider */
val &= ~(0x1ff << SSP_DIV);
val |= ssp_div << SSP_DIV;
REG_WR(CLKCTRL_BASE + CLKCTRL_SSP, val);
/* Wait until new divider value is set */
while (REG_RD(CLKCTRL_BASE + CLKCTRL_SSP) & SSP_BUSY)
;
/* Set SSP clock source to IO_CLK */
REG_SET(CLKCTRL_BASE + CLKCTRL_CLKSEQ, CLKSEQ_BYPASS_SSP);
REG_CLR(CLKCTRL_BASE + CLKCTRL_CLKSEQ, CLKSEQ_BYPASS_SSP);
}
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)
{
/* arch number of Freescale STMP 378x development board */
gd->bd->bi_arch_number = MACH_TYPE_STMP378X;
/* adress of boot parameters */
gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR;
set_clocks();
set_pinmux();
/* Configure SPI on SSP1 or SSP2 */
spi_init();
return 0;
}
int misc_init_r(void)
{
return 0;
}
int checkboard(void)
{
printf("Board: STMP378x dev. \n");
return 0;
}

View File

@ -0,0 +1,51 @@
/*
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
cpu/arm926ejs/start.o (.text)
*(.text)
}
.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 (NOLOAD) : { *(.bss) }
_end = .;
}

View File

@ -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

View File

@ -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,

View File

@ -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

327
common/env_mmc.c Normal file
View File

@ -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 <www.elinos.com>
* Andreas Heppel <aheppel@sysgo.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
*/
/* #define DEBUG */
#include <common.h>
#if defined(CONFIG_ENV_IS_IN_MMC) /* Environment is in MMC Flash */
#include <command.h>
#include <environment.h>
#include <linux/stddef.h>
#include <malloc.h>
#include <mmc.h>
#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 */

View File

@ -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

View File

@ -8,6 +8,8 @@
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
*
* (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);
}

View File

@ -27,6 +27,8 @@ LIB = $(obj)lib$(SOC).a
COBJS = interrupts.o serial.o generic.o
SOBJS = nand_load.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))

View File

@ -1,4 +1,5 @@
/*
* (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
* (C) Copyright 2007
* Sascha Hauer, Pengutronix
*
@ -34,10 +35,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 +95,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;
}

View File

@ -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 <config.h>
#include <asm/arch/mx31-regs.h>
.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

48
cpu/arm1136/mx35/Makefile Normal file
View File

@ -0,0 +1,48 @@
#
# (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
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
#########################################################################

258
cpu/arm1136/mx35/crm_regs.h Normal file
View File

@ -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__ */

219
cpu/arm1136/mx35/generic.c Normal file
View File

@ -0,0 +1,219 @@
/*
* (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 <common.h>
#include <asm/errno.h>
#include <asm/arch/mx35.h>
#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
/*
* 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;
}

View File

@ -0,0 +1,115 @@
/*
* (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 <common.h>
#include <asm/arch/mx35.h>
/* 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(WDOG_BASE_ADDR) = 4;
}

149
cpu/arm1136/mx35/iomux.c Normal file
View File

@ -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 <common.h>
#include <asm/arch/mx35.h>
#include <asm/arch/mx35_pins.h>
#include <asm/arch/iomux.h>
/*!
* 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;
}

View File

@ -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 <config.h>
#include <asm/arch/mx35.h>
.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

220
cpu/arm1136/mx35/serial.c Normal file
View File

@ -0,0 +1,220 @@
/*
* (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>
*
* (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 <common.h>
#if defined CONFIG_MX35_UART
#include <asm/arch/mx35.h>
#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 */

View File

@ -30,8 +30,14 @@
#include <config.h>
#include <version.h>
.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
@ -85,6 +91,86 @@ _end_vect:
*************************************************************************
*/
/*
* the actual reset code
*/
.section ".text.head", "ax"
.globl reset
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
#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 */
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 */
bl cpy_clk_code /* put dpll adjust code behind vectors */
#endif
/* the mask ROM code should have PLL and others stable */
#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 */
.section ".text.setup", "ax"
.globl _TEXT_BASE
_TEXT_BASE:
.word TEXT_BASE
@ -115,51 +201,20 @@ 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
#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 */
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 */
bl cpy_clk_code /* put dpll adjust code behind vectors */
#endif
/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
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 */
@ -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
/*
*************************************************************************

View File

@ -38,7 +38,7 @@
#include <common.h>
#include <arm926ejs.h>
#ifdef CONFIG_INTEGRATOR
#if defined(CONFIG_INTEGRATOR) || defined(CONFIG_MX25)
/* Timer functionality supplied by Integrator board (AP or CP) */

View File

@ -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
#########################################################################

View File

@ -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 <common.h>
#include <asm/errno.h>
#include <asm/arch/mx25-regs.h>
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

113
cpu/arm926ejs/mx25/gpio.c Normal file
View File

@ -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 <common.h>
#include <asm/arch/mx25.h>
#include <asm/arch/mx25_pins.h>
#include <asm/arch/gpio.h>
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);
}

View File

@ -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 <common.h>
#include <asm/arch/mx25-regs.h>
#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;
}

153
cpu/arm926ejs/mx25/iomux.c Normal file
View File

@ -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 <common.h>
#include <asm/arch/mx25.h>
#include <asm/arch/mx25_pins.h>
#include <asm/arch/iomux.h>
/*!
* 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;
}

231
cpu/arm926ejs/mx25/serial.c Normal file
View File

@ -0,0 +1,231 @@
/*
* (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>
*
* (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 <common.h>
#if defined CONFIG_MX25_UART
#include <asm/arch/mx25.h>
#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 */

View File

@ -125,7 +125,7 @@ FIQ_STACK_START:
/*
* the actual reset code
*/
.globl reset
reset:
/*
* set the cpu to SVC32 mode

View File

@ -0,0 +1,47 @@
#
# (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 = timer.o spi.o
SOBJS = reset.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
START := $(addprefix $(obj),$(START))
all: $(obj).depend $(LIB)
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View File

@ -0,0 +1,2 @@
PLATFORM_CPPFLAGS += -march=armv5te
PLATFORM_CPPFLAGS += $(call cc-option,-mtune=arm926ejs,)

View File

@ -0,0 +1,43 @@
/*
* Processor reset for Freescale STMP378x SoC.
*
* Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
*
* -----------------------------------------------------
*
* 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
*/
.globl reset_cpu
reset_cpu:
ldr r0, POWER_CHARGE
mov r1, #0x0
str r1, [r0]
ldr r0, POWER_MINPWR
str r1, [r0]
ldr r0, CLKCTRL_RESET
mov r1, #0x1
str r1, [r0]
_loop_forever:
b _loop_forever
POWER_MINPWR:
.word 0x80044020
POWER_CHARGE:
.word 0x80044030
CLKCTRL_RESET:
.word 0x80040120

View File

@ -0,0 +1,255 @@
/*
* Copyright (C) 2008 Embedded Alley Solutions Inc.
*
* (C) Copyright 2009 Freescale Semiconductor, Inc.
*
* Freescale STMP378x SSP/SPI driver
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <asm/arch/spi.h>
#define SPI_NUM_BUSES 2
#define SPI_NUM_SLAVES 3
/* Initalized in spi_init() depending on SSP port configuration */
static unsigned long ssp_bases[SPI_NUM_BUSES];
/* Set in spi_set_cfg() depending on which SSP port is being used */
static unsigned long ssp_base = SSP1_BASE;
/*
* Init SSP port: SSP1 (@bus = 0) or SSP2 (@bus == 1)
*/
static void ssp_spi_init(unsigned int bus)
{
u32 spi_div;
u32 val = 0;
if (bus >= SPI_NUM_BUSES) {
printf("SPI bus %d doesn't exist\n", bus);
return;
}
ssp_base = ssp_bases[bus];
/* Reset block */
/* Clear SFTRST */
REG_CLR(ssp_base + SSP_CTRL0, CTRL0_SFTRST);
while (REG_RD(ssp_base + SSP_CTRL0) & CTRL0_SFTRST)
;
/* Clear CLKGATE */
REG_CLR(ssp_base + SSP_CTRL0, CTRL0_CLKGATE);
/* Set SFTRST and wait until CLKGATE is set */
REG_SET(ssp_base + SSP_CTRL0, CTRL0_SFTRST);
while (!(REG_RD(ssp_base + SSP_CTRL0) & CTRL0_CLKGATE))
;
/* Clear SFTRST and CLKGATE */
REG_CLR(ssp_base + SSP_CTRL0, CTRL0_SFTRST);
REG_CLR(ssp_base + SSP_CTRL0, CTRL0_CLKGATE);
/*
* Set CLK to desired value
*/
spi_div = ((CONFIG_SSP_CLK>>1) + CONFIG_SPI_CLK - 1) / CONFIG_SPI_CLK;
val = (2 << TIMING_CLOCK_DIVIDE) | ((spi_div - 1) << TIMING_CLOCK_RATE);
REG_WR(ssp_base + SSP_TIMING, val);
/* Set transfer parameters */
/* Set SSP SPI Master mode and word length to 8 bit */
REG_WR(ssp_base + SSP_CTRL1, WORD_LENGTH8 | SSP_MODE_SPI);
/* Set BUS_WIDTH to 1 bit and XFER_COUNT to 1 byte */
REG_WR(ssp_base + SSP_CTRL0,
BUS_WIDTH_SPI1 | (0x1 << CTRL0_XFER_COUNT));
/*
* Set BLOCK_SIZE and BLOCK_COUNT to 0, so that XFER_COUNT
* reflects number of bytes to send. Disalbe other bits as
* well
*/
REG_WR(ssp_base + SSP_CMD0, 0x0);
}
/*
* Init SSP ports, must be called first and only once
*/
void spi_init(void)
{
#ifdef CONFIG_SPI_SSP1
ssp_bases[0] = SSP1_BASE;
ssp_spi_init(0);
#endif
#ifdef CONFIG_SPI_SSP2
ssp_bases[1] = SSP2_BASE;
ssp_spi_init(1);
#endif
}
void spi_set_cfg(unsigned int bus, unsigned int cs, unsigned long mode)
{
u32 clr_mask = 0;
u32 set_mask = 0;
if (bus >= SPI_NUM_BUSES || cs >= SPI_NUM_SLAVES) {
printf("SPI device %d:%d doesn't exist", bus, cs);
return;
}
if (ssp_bases[bus] == 0) {
printf("SSP port %d isn't in SPI mode\n", bus + 1);
return;
}
/* Set SSP port to use */
ssp_base = ssp_bases[bus];
/* Set phase and polarity: HW_SSP_CTRL1 */
if (mode & SPI_PHASE)
set_mask |= CTRL1_PHASE;
else
clr_mask |= CTRL1_PHASE;
if (mode & SPI_POLARITY)
set_mask |= CTRL1_POLARITY;
else
clr_mask |= CTRL1_POLARITY;
REG_SET(ssp_base + SSP_CTRL1, set_mask);
REG_CLR(ssp_base + SSP_CTRL1, clr_mask);
/* Set SSn number: HW_SSP_CTRL0 */
REG_CLR(ssp_base + SSP_CTRL0, SPI_CS_CLR_MASK);
switch (cs) {
case 0:
set_mask = SPI_CS0;
break;
case 1:
set_mask = SPI_CS1;
break;
case 2:
set_mask = SPI_CS2;
break;
}
REG_SET(ssp_base + SSP_CTRL0, set_mask);
}
/* Read single data byte */
static unsigned char spi_read(void)
{
unsigned char b = 0;
/* Set XFER_LENGTH to 1 */
REG_CLR(ssp_base + SSP_CTRL0, 0xffff);
REG_SET(ssp_base + SSP_CTRL0, 1);
/* Enable READ mode */
REG_SET(ssp_base + SSP_CTRL0, CTRL0_READ);
/* Set RUN bit */
REG_SET(ssp_base + SSP_CTRL0, CTRL0_RUN);
/* Set transfer */
REG_SET(ssp_base + SSP_CTRL0, CTRL0_DATA_XFER);
while (REG_RD(ssp_base + SSP_STATUS) & STATUS_FIFO_EMPTY)
;
/* Read data byte */
b = REG_RD(ssp_base + SSP_DATA) & 0xff;
/* Wait until RUN bit is cleared */
while (REG_RD(ssp_base + SSP_CTRL0) & CTRL0_RUN)
;
return b;
}
/* Write single data byte */
static void spi_write(unsigned char b)
{
/* Set XFER_LENGTH to 1 */
REG_CLR(ssp_base + SSP_CTRL0, 0xffff);
REG_SET(ssp_base + SSP_CTRL0, 1);
/* Enable WRITE mode */
REG_CLR(ssp_base + SSP_CTRL0, CTRL0_READ);
/* Set RUN bit */
REG_SET(ssp_base + SSP_CTRL0, CTRL0_RUN);
/* Write data byte */
REG_WR(ssp_base + SSP_DATA, b);
/* Set transfer */
REG_SET(ssp_base + SSP_CTRL0, CTRL0_DATA_XFER);
/* Wait until RUN bit is cleared */
while (REG_RD(ssp_base + SSP_CTRL0) & CTRL0_RUN)
;
}
static void spi_lock_cs(void)
{
REG_CLR(ssp_base + SSP_CTRL0, CTRL0_IGNORE_CRC);
REG_SET(ssp_base + SSP_CTRL0, CTRL0_LOCK_CS);
}
static void spi_unlock_cs(void)
{
REG_CLR(ssp_base + SSP_CTRL0, CTRL0_LOCK_CS);
REG_SET(ssp_base + SSP_CTRL0, CTRL0_IGNORE_CRC);
}
void spi_txrx(const char *dout, unsigned int tx_len, char *din,
unsigned int rx_len, unsigned long flags)
{
int i;
if (tx_len == 0 && rx_len == 0)
return;
if (flags & SPI_START)
spi_lock_cs();
for (i = 0; i < tx_len; i++) {
/* Check if it is last data byte to transfer */
if (flags & SPI_STOP && rx_len == 0 && i == tx_len - 1)
spi_unlock_cs();
spi_write(dout[i]);
}
for (i = 0; i < rx_len; i++) {
/* Check if it is last data byte to transfer */
if (flags & SPI_STOP && i == rx_len - 1)
spi_unlock_cs();
din[i] = spi_read();
}
}

View File

@ -0,0 +1,246 @@
/*
* (C) Copyright 2003
* Texas Instruments <www.ti.com>
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Alex Zuepke <azu@sysgo.de>
*
* (C) Copyright 2002-2004
* Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
*
* (C) Copyright 2004
* Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
*
* (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 <common.h>
#include <arm926ejs.h>
#include <asm/arch/stmp378x.h>
#include <asm/arch/timrot.h>
#define CONFIG_USE_TIMER0
#if defined(CONFIG_USE_TIMER0)
#define TIMCTRL TIMCTRL0
#define TIMCOUNT TIMCOUNT0
#elif defined(CONFIG_USE_TIMER1)
#define TIMCTRL TIMCTRL1
#define TIMCOUNT TIMCOUNT1
#elif defined(CONFIG_USE_TIMER2)
#define TIMCTRL TIMCTRL2
#define TIMCOUNT TIMCOUNT2
#elif defined(CONFIG_USE_TIMER3)
#define TIMCTRL TIMCTRL3
#define TIMCOUNT TIMCOUNT3
#else
#error "Define which STMP378x timer to use"
#endif
#define TIMER_LOAD_VAL 0x0000ffff
/* macro to read the 16 bit timer */
#define READ_TIMER ((REG_RD(TIMROT_BASE + TIMCOUNT) & 0xffff0000) >> 16)
static ulong timestamp;
static ulong lastdec;
int timer_init(void)
{
u32 val;
/*
* Reset Timers and Rotary Encoder module
*/
/* Clear SFTRST */
REG_CLR(TIMROT_BASE + ROTCTRL, 1 << 31);
while (REG_RD(TIMROT_BASE + ROTCTRL) & (1 << 31))
;
/* Clear CLKGATE */
REG_CLR(TIMROT_BASE + ROTCTRL, 1 << 30);
/* Set SFTRST and wait until CLKGATE is set */
REG_SET(TIMROT_BASE + ROTCTRL, 1 << 31);
while (!(REG_RD(TIMROT_BASE + ROTCTRL) & (1 << 30)))
;
/* Clear SFTRST and CLKGATE */
REG_CLR(TIMROT_BASE + ROTCTRL, 1 << 31);
REG_CLR(TIMROT_BASE + ROTCTRL, 1 << 30);
/*
* Now initialize timer
*/
/* Set fixed_count to 0 */
REG_WR(TIMROT_BASE + TIMCOUNT, 0);
/* set UPDATE bit and 1Khz frequency */
REG_WR(TIMROT_BASE + TIMCTRL,
TIMCTRL_RELOAD | TIMCTRL_UPDATE | TIMCTRL_SELECT_1KHZ);
/* Set fixed_count to maximal value */
REG_WR(TIMROT_BASE + TIMCOUNT, TIMER_LOAD_VAL);
/* init the timestamp and lastdec value */
reset_timer_masked();
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 (usec >= 1000) {
/* if "big" number, spread normalization to seconds */
tmo = usec / 1000;
/* start to normalize for usec to ticks per sec */
tmo *= CONFIG_SYS_HZ;
/* find number of "ticks" to wait to achieve target */
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 ((tmo + tmp + 1) < tmp)
/* if setting this fordward will roll time stamp */
reset_timer_masked();
/* reset "advancing" timestamp to 0, set lastdec value */
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 */
lastdec = READ_TIMER; /* capure current decrementer value time */
timestamp = 0; /* start "advancing" time stamp from 0 */
}
ulong get_timer_masked(void)
{
ulong now = READ_TIMER; /* current tick value */
if (lastdec >= now) { /* normal mode (non roll) */
/* normal mode */
timestamp += lastdec - now;
/* move stamp fordward with absoulte diff ticks */
} else {
/* we have overflow of the count down timer */
/* nts = ts + ld + (TLV - now)
* ts=old stamp, ld=time that passed before passing through -1
* (TLV-now) amount of time after passing though -1
* nts = new "advancing time stamp"...it could also roll
* and cause problems.
*/
timestamp += lastdec + TIMER_LOAD_VAL - now + 1;
}
lastdec = now;
return timestamp;
}
/* waits specified delay value and resets timestamp */
void udelay_masked(unsigned long usec)
{
ulong tmo;
ulong endtime;
signed long diff;
if (usec >= 1000) {
/* if "big" number, spread normalization to seconds */
tmo = usec / 1000;
/* start to normalize for usec to ticks per sec */
tmo *= CONFIG_SYS_HZ;
/* find number of "ticks" to wait to achieve target */
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;
}

47
cpu/arm_cortexa8/Makefile Normal file
View File

@ -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
#########################################################################

View File

@ -0,0 +1,40 @@
#
# (C) Copyright 2002
# Gary Jennejohn, DENX Software Engineering, <gj@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
#
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
#
# =========================================================================
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,))

246
cpu/arm_cortexa8/cpu.c Normal file
View File

@ -0,0 +1,246 @@
/*
* (C) Copyright 2008 Texas Insturments
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
*
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <gj@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
*/
/*
* CPU specific code
*/
#include <common.h>
#include <command.h>
#ifndef CONFIG_MXC
#include <asm/arch/sys_proto.h>
#endif
#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);
}
#ifndef CONFIG_L2_OFF
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));
}
}
#endif
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));
}

View File

@ -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
#########################################################################

View File

@ -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__ */

View File

@ -0,0 +1,260 @@
/*
* (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 <common.h>
#include <asm/arch/mx51.h>
#include <asm/errno.h>
#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;
}
/*!
+ * 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) {
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();
case MXC_CSPI_CLK:
return __get_cspi_clk();
case MXC_FEC_CLK:
return __decode_pll(PLL1_CLK, CONFIG_MX51_HCLK_FREQ);
default:
break;
}
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", 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)
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
/*
* Initializes on-chip ethernet controllers.
* to override, implement board_eth_init()
*/
#if defined(CONFIG_MXC_FEC)
extern int mxc_fec_initialize(bd_t *bis);
#endif
int cpu_eth_init(bd_t *bis)
{
int rc = -ENODEV;
#if defined(CONFIG_MXC_FEC)
rc = mxc_fec_initialize(bis);
#endif
return rc;
}

View File

@ -0,0 +1,128 @@
/*
* (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 <common.h>
#include <asm/arch/mx51.h>
/* 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 */
static inline void setup_gpt()
{
int i;
static int init_done;
if (init_done)
return;
init_done = 1;
/* 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;
}
/* nothing really to do with interrupts, just starts up a counter. */
int interrupt_init(void)
{
setup_gpt();
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;
setup_gpt();
/* 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;
}

View File

@ -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 <common.h>
#include <asm/io.h>
#include <asm/arch/mx51.h>
#include <asm/arch/mx51_pins.h>
#include <asm/arch/iomux.h>
/*!
* 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);
}

View File

@ -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 <config.h>
#include <asm/arch/mx51.h>
.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

View File

@ -0,0 +1,226 @@
/*
* (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>
*
* (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 <common.h>
#if defined CONFIG_MX51_UART
#include <asm/arch/mx51.h>
#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 */

View File

@ -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
#########################################################################

View File

@ -0,0 +1,344 @@
/*
*
* Common board functions for OMAP3 based boards.
*
* (C) Copyright 2004-2008
* Texas Instruments, <www.ti.com>
*
* Author :
* Sunil Kumar <sunilsaini05@gmail.com>
* Shashi Ranjan <shashiranjanmca05@gmail.com>
*
* Derived from Beagle Board and 3430 SDP code by
* Richard Woodruff <r-woodruff2@ti.com>
* Syed Mohammed Khasim <khasim@ti.com>
*
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/mem.h>
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 */

View File

@ -0,0 +1,381 @@
/*
* (C) Copyright 2008
* Texas Instruments, <www.ti.com>
*
* Author :
* Manikandan Pillai <mani.pillai@ti.com>
*
* Derived from Beagle Board and OMAP3 SDP code by
* Richard Woodruff <r-woodruff2@ti.com>
* Syed Mohammed Khasim <khasim@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/clocks.h>
#include <asm/arch/clocks_omap3.h>
#include <asm/arch/mem.h>
#include <asm/arch/sys_proto.h>
#include <environment.h>
#include <command.h>
/******************************************************************************
* 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);
}

View File

@ -0,0 +1,36 @@
#
# (C) Copyright 2002
# Gary Jennejohn, DENX Software Engineering, <gj@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
#
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,))

View File

@ -0,0 +1,297 @@
/*
* (C) Copyright 2008
* Texas Instruments
*
* Richard Woodruff <r-woodruff2@ti.com>
* Syed Moahmmed Khasim <khasim@ti.com>
*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
* Alex Zuepke <azu@sysgo.de>
*
* (C) Copyright 2002
* Gary Jennejohn, DENX Software Engineering, <gj@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 <common.h>
#include <asm/io.h>
#include <asm/proc-armv/ptrace.h>
#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;
}

View File

@ -0,0 +1,361 @@
/*
* Board specific setup info
*
* (C) Copyright 2008
* Texas Instruments, <www.ti.com>
*
* Initial Code by:
* Richard Woodruff <r-woodruff2@ti.com>
* Syed Mohammed Khasim <khasim@ti.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <config.h>
#include <version.h>
#include <asm/arch/mem.h>
#include <asm/arch/clocks_omap3.h>
_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

View File

@ -0,0 +1,284 @@
/*
* (C) Copyright 2008
* Texas Instruments, <www.ti.com>
*
* Author :
* Manikandan Pillai <mani.pillai@ti.com>
*
* Initial Code from:
* Richard Woodruff <r-woodruff2@ti.com>
* Syed Mohammed Khasim <khasim@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/mem.h>
#include <asm/arch/sys_proto.h>
#include <command.h>
/*
* 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
}

View File

@ -0,0 +1,254 @@
/*
* (C) Copyright 2008
* Texas Instruments, <www.ti.com>
*
* Author :
* Manikandan Pillai <mani.pillai@ti.com>
*
* Derived from Beagle Board and 3430 SDP code by
* Richard Woodruff <r-woodruff2@ti.com>
* Syed Mohammed Khasim <khasim@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/mem.h> /* get mem tables */
#include <asm/arch/sys_proto.h>
#include <i2c.h>
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);
}

View File

@ -0,0 +1,72 @@
/*
* (C) Copyright 2008
* Texas Instruments, <www.ti.com>
*
* Richard Woodruff <r-woodruff2@ti.com>
* Syed Mohammed Khasim <khasim@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/mem.h>
#include <asm/arch/clocks.h>
#include <asm/arch/sys_proto.h>
/************************************************************
* 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);
}

518
cpu/arm_cortexa8/start.S Normal file
View File

@ -0,0 +1,518 @@
/*
* armboot - Startup Code for OMAP3530/ARM Cortex CPU-core
*
* Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com>
*
* Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
* Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
* Copyright (c) 2002 Gary Jennejohn <gj@denx.de>
* Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
* Copyright (c) 2003 Kshitij <kshitij@ti.com>
* Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com>
* Copyright (c) 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 <config.h>
#include <version.h>
.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}
#ifdef PRM_RSTCTRL
.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
#endif

View File

@ -3,6 +3,8 @@
*
* (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
*
* (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
@ -26,8 +28,19 @@
#if defined(CONFIG_HARD_I2C)
#ifdef CONFIG_MX25
#include <asm/arch/mx25.h>
#include <asm/arch/mx25-regs.h>
#elif defined(CONFIG_MX31)
#include <asm/arch/mx31.h>
#include <asm/arch/mx31-regs.h>
#elif defined(CONFIG_MX35)
#include <asm/arch/mx35.h>
#elif defined(CONFIG_MX51_3DS)
#include <asm/arch/mx51.h>
#else
#error "Please include specific headfile "
#endif
#define IADR 0x00
#define IFDR 0x04
@ -47,16 +60,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 CONFIG_SYS_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 +78,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 +157,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 +295,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 */

View File

@ -30,6 +30,7 @@ ifdef CONFIG_PS2KBD
COBJS-y += keyboard.o pc_keyb.o
COBJS-$(CONFIG_PS2MULT) += ps2mult.o ps2ser.o
endif
COBJS-${CONFIG_MXC_KPD} += mxc_keyb.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)

598
drivers/input/mxc_keyb.c Normal file
View File

@ -0,0 +1,598 @@
/*
* 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_keyb.c
*
* @brief Driver for the Freescale Semiconductor MXC keypad port.
*
* The keypad driver is designed as a standard Input driver which interacts
* with low level keypad port hardware. Upon opening, the Keypad driver
* initializes the keypad port. When the keypad interrupt happens the driver
* calles keypad polling timer and scans the keypad matrix for key
* press/release. If all key press/release happened it comes out of timer and
* waits for key press interrupt. The scancode for key press and release events
* are passed to Input subsytem.
*
* @ingroup keypad
*/
#include <asm/io.h>
#include <common.h>
#include <asm/errno.h>
#include <asm/arch/keypad.h>
#include <linux/types.h>
#include <malloc.h>
/*
* * Module header file
* */
#include <mxc_keyb.h>
/*!
* Comment KPP_DEBUG to disable debug messages
*/
#undef KPP_DEBUG
#ifdef KPP_DEBUG
#define KPP_PRINTF(fmt, args...) printf(fmt , ##args)
static void mxc_kpp_dump_regs()
{
unsigned short t1, t2, t3;
t1 = __raw_readw(KPCR);
t2 = __raw_readw(KPSR);
t3 = __raw_readw(KDDR);
/*
KPP_PRINTF("KPCR=0x%04x, KPSR=0x%04x, KDDR=0x%04x\n",
t1, t2, t3);
*/
}
#else
#define KPP_PRINTF(fmt, args...)
#endif
static u16 mxc_key_mapping[] = CONFIG_MXC_KEYMAPPING;
/*!
* This structure holds the keypad private data structure.
*/
static struct keypad_priv kpp_dev;
/*! Indicates if the key pad device is enabled. */
/*! This static variable indicates whether a key event is pressed/released. */
static unsigned short KPress;
/*! cur_rcmap and prev_rcmap array is used to detect key press and release. */
static unsigned short *cur_rcmap; /* max 64 bits (8x8 matrix) */
static unsigned short *prev_rcmap;
/*!
* Debounce polling period(10ms) in system ticks.
*/
static unsigned short KScanRate = (10 * CONFIG_SYS_HZ) / 1000;
/*!
* These arrays are used to store press and release scancodes.
*/
static short **press_scancode;
static short **release_scancode;
static const unsigned short *mxckpd_keycodes;
static unsigned short mxckpd_keycodes_size;
/*!
* These functions are used to configure and the GPIO pins for keypad to
* activate and deactivate it.
*/
extern void setup_mxc_kpd(void);
/*!
* This function is called to scan the keypad matrix to find out the key press
* and key release events. Make scancode and break scancode are generated for
* key press and key release events.
*
* The following scanning sequence are done for
* keypad row and column scanning,
* -# Write 1's to KPDR[15:8], setting column data to 1's
* -# Configure columns as totem pole outputs(for quick discharging of keypad
* capacitance)
* -# Configure columns as open-drain
* -# Write a single column to 0, others to 1.
* -# Sample row inputs and save data. Multiple key presses can be detected on
* a single column.
* -# Repeat steps the above steps for remaining columns.
* -# Return all columns to 0 in preparation for standby mode.
* -# Clear KPKD and KPKR status bit(s) by writing to a 1,
* Set the KPKR synchronizer chain by writing "1" to KRSS register,
* Clear the KPKD synchronizer chain by writing "1" to KDSC register
*
* @result Number of key pressed/released.
*/
static int mxc_kpp_scan_matrix()
{
unsigned short reg_val;
int col, row;
short scancode = 0;
int keycnt = 0; /* How many keys are still pressed */
/*
* wmb() linux kernel function which guarantees orderings in write
* operations
*/
/* wmb(); */
/* save cur keypad matrix to prev */
memcpy(prev_rcmap, cur_rcmap, kpp_dev.kpp_rows * sizeof(prev_rcmap[0]));
memset(cur_rcmap, 0, kpp_dev.kpp_rows * sizeof(cur_rcmap[0]));
for (col = 0; col < kpp_dev.kpp_cols; col++) { /* Col */
/* 2. Write 1.s to KPDR[15:8] setting column data to 1.s */
reg_val = __raw_readw(KPDR);
reg_val |= 0xff00;
__raw_writew(reg_val, KPDR);
/*
* 3. Configure columns as totem pole outputs(for quick
* discharging of keypad capacitance)
*/
reg_val = __raw_readw(KPCR);
reg_val &= 0x00ff;
__raw_writew(reg_val, KPCR);
udelay(2);
#ifdef KPP_DEBUG
mxc_kpp_dump_regs();
#endif
/*
* 4. Configure columns as open-drain
*/
reg_val = __raw_readw(KPCR);
reg_val |= ((1 << kpp_dev.kpp_cols) - 1) << 8;
__raw_writew(reg_val, KPCR);
/*
* 5. Write a single column to 0, others to 1.
* 6. Sample row inputs and save data. Multiple key presses
* can be detected on a single column.
* 7. Repeat steps 2 - 6 for remaining columns.
*/
/* Col bit starts at 8th bit in KPDR */
reg_val = __raw_readw(KPDR);
reg_val &= ~(1 << (8 + col));
__raw_writew(reg_val, KPDR);
/* Delay added to avoid propagating the 0 from column to row
* when scanning. */
udelay(5);
#ifdef KPP_DEBUG
mxc_kpp_dump_regs();
#endif
/* Read row input */
reg_val = __raw_readw(KPDR);
for (row = 0; row < kpp_dev.kpp_rows; row++) { /* sample row */
if (TEST_BIT(reg_val, row) == 0) {
cur_rcmap[row] = BITSET(cur_rcmap[row], col);
keycnt++;
}
}
}
/*
* 8. Return all columns to 0 in preparation for standby mode.
* 9. Clear KPKD and KPKR status bit(s) by writing to a .1.,
* set the KPKR synchronizer chain by writing "1" to KRSS register,
* clear the KPKD synchronizer chain by writing "1" to KDSC register
*/
reg_val = 0x00;
__raw_writew(reg_val, KPDR);
reg_val = __raw_readw(KPDR);
reg_val = __raw_readw(KPSR);
reg_val |= KBD_STAT_KPKD | KBD_STAT_KPKR | KBD_STAT_KRSS |
KBD_STAT_KDSC;
__raw_writew(reg_val, KPSR);
#ifdef KPP_DEBUG
mxc_kpp_dump_regs();
#endif
/* Check key press status change */
/*
* prev_rcmap array will contain the previous status of the keypad
* matrix. cur_rcmap array will contains the present status of the
* keypad matrix. If a bit is set in the array, that (row, col) bit is
* pressed, else it is not pressed.
*
* XORing these two variables will give us the change in bit for
* particular row and column. If a bit is set in XOR output, then that
* (row, col) has a change of status from the previous state. From
* the diff variable the key press and key release of row and column
* are found out.
*
* If the key press is determined then scancode for key pressed
* can be generated using the following statement:
* scancode = ((row * 8) + col);
*
* If the key release is determined then scancode for key release
* can be generated using the following statement:
* scancode = ((row * 8) + col) + MXC_KEYRELEASE;
*/
for (row = 0; row < kpp_dev.kpp_rows; row++) {
unsigned char diff;
/*
* Calculate the change in the keypad row status
*/
diff = prev_rcmap[row] ^ cur_rcmap[row];
for (col = 0; col < kpp_dev.kpp_cols; col++) {
if ((diff >> col) & 0x1) {
/* There is a status change on col */
if ((prev_rcmap[row] & BITSET(0, col)) == 0) {
/*
* Previous state is 0, so now
* a key is pressed
*/
scancode =
((row * kpp_dev.kpp_cols) +
col);
KPress = 1;
kpp_dev.iKeyState = KStateUp;
KPP_PRINTF("Press (%d, %d) scan=%d "
"Kpress=%d\n",
row, col, scancode, KPress);
press_scancode[row][col] =
(short)scancode;
} else {
/*
* Previous state is not 0, so
* now a key is released
*/
scancode =
(row * kpp_dev.kpp_cols) +
col + MXC_KEYRELEASE;
KPress = 0;
kpp_dev.iKeyState = KStateDown;
KPP_PRINTF
("Release (%d, %d) scan=%d Kpress=%d\n",
row, col, scancode, KPress);
release_scancode[row][col] =
(short)scancode;
keycnt++;
}
}
}
}
return keycnt;
}
static int mxc_kpp_reset()
{
unsigned short reg_val;
int i;
/*
* Stop scanning and wait for interrupt.
* Enable press interrupt and disable release interrupt.
*/
__raw_writew(0x00FF, KPDR);
reg_val = __raw_readw(KPSR);
reg_val |= (KBD_STAT_KPKR | KBD_STAT_KPKD);
reg_val |= KBD_STAT_KRSS | KBD_STAT_KDSC;
__raw_writew(reg_val, KPSR);
reg_val |= KBD_STAT_KDIE;
reg_val &= ~KBD_STAT_KRIE;
__raw_writew(reg_val, KPSR);
#ifdef KPP_DEBUG
mxc_kpp_dump_regs();
#endif
/*
* No more keys pressed... make sure unwanted key codes are
* not given upstairs
*/
for (i = 0; i < kpp_dev.kpp_rows; i++) {
memset(press_scancode[i], -1,
sizeof(press_scancode[0][0]) * kpp_dev.kpp_cols);
memset(release_scancode[i], -1,
sizeof(release_scancode[0][0]) *
kpp_dev.kpp_cols);
}
return 0;
}
int mxc_kpp_getc(struct kpp_key_info *key_info)
{
int col, row;
static int key_cnt;
unsigned short reg_val;
short scancode = 0;
reg_val = __raw_readw(KPSR);
if (!key_cnt) {
if (reg_val & KBD_STAT_KPKD) {
/*
* Disable key press(KDIE status bit) interrupt
*/
reg_val &= ~KBD_STAT_KDIE;
__raw_writew(reg_val, KPSR);
#ifdef KPP_DEBUG
mxc_kpp_dump_regs();
#endif
key_cnt = mxc_kpp_scan_matrix();
} else {
return 0;
}
}
/*
* This switch case statement is the
* implementation of state machine of debounc
* logic for key press/release.
* The explaination of state machine is as
* follows:
*
* KStateUp State:
* This is in intial state of the state machine
* this state it checks for any key presses.
* The key press can be checked using the
* variable KPress. If KPress is set, then key
* press is identified and switches the to
* KStateFirstDown state for key press to
* debounce.
*
* KStateFirstDown:
* After debounce delay(10ms), if the KPress is
* still set then pass scancode generated to
* input device and change the state to
* KStateDown, else key press debounce is not
* satisfied so change the state to KStateUp.
*
* KStateDown:
* In this state it checks for any key release.
* If KPress variable is cleared, then key
* release is indicated and so, switch the
* state to KStateFirstUp else to state
* KStateDown.
*
* KStateFirstUp:
* After debounce delay(10ms), if the KPress is
* still reset then pass the key release
* scancode to input device and change
* the state to KStateUp else key release is
* not satisfied so change the state to
* KStateDown.
*/
for (row = 0; row < kpp_dev.kpp_rows; row++) {
for (col = 0; col < kpp_dev.kpp_cols; col++) {
if ((press_scancode[row][col] != -1)) {
/* Still Down, so add scancode */
scancode =
press_scancode[row][col];
key_info->val = mxckpd_keycodes[scancode];
key_info->evt = KDepress;
KPP_PRINTF("KStateFirstDown: scan=%d val=%d\n",
scancode, mxckpd_keycodes[scancode]);
kpp_dev.iKeyState = KStateDown;
press_scancode[row][col] = -1;
goto key_detect;
}
}
}
for (row = 0; row < kpp_dev.kpp_rows; row++) {
for (col = 0; col < kpp_dev.kpp_cols; col++) {
if ((release_scancode[row][col] != -1)) {
scancode =
release_scancode[row][col];
scancode =
scancode - MXC_KEYRELEASE;
key_info->val = mxckpd_keycodes[scancode];
key_info->evt = KRelease;
KPP_PRINTF("KStateFirstUp: scan=%d val=%d\n",
scancode, mxckpd_keycodes[scancode]);
kpp_dev.iKeyState = KStateUp;
release_scancode[row][col] = -1;
goto key_detect;
}
}
}
return 0;
key_detect:
/* udelay(KScanRate); */
key_cnt = mxc_kpp_scan_matrix();
if (0 == key_cnt)
mxc_kpp_reset();
return 1;
}
/*!
* This function is called to free the allocated memory for local arrays
*/
static void mxc_kpp_free_allocated(void)
{
int i;
if (press_scancode) {
for (i = 0; i < kpp_dev.kpp_rows; i++) {
if (press_scancode[i])
free(press_scancode[i]);
}
free(press_scancode);
}
if (release_scancode) {
for (i = 0; i < kpp_dev.kpp_rows; i++) {
if (release_scancode[i])
free(release_scancode[i]);
}
free(release_scancode);
}
if (cur_rcmap)
free(cur_rcmap);
if (prev_rcmap)
free(prev_rcmap);
}
/*!
* 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 returns 0 on successful registration. Otherwise returns
* specific error code.
*/
int mxc_kpp_init()
{
int i;
int retval;
unsigned int reg_val;
kpp_dev.kpp_cols = CONFIG_MXC_KPD_COLMAX;
kpp_dev.kpp_rows = CONFIG_MXC_KPD_ROWMAX;
/* clock and IOMUX configuration for keypad */
setup_mxc_kpd();
/* Configure keypad */
/* Enable number of rows in keypad (KPCR[7:0])
* Configure keypad columns as open-drain (KPCR[15:8])
*
* Configure the rows/cols in KPP
* LSB nibble in KPP is for 8 rows
* MSB nibble in KPP is for 8 cols
*/
reg_val = __raw_readw(KPCR);
reg_val |= (1 << kpp_dev.kpp_rows) - 1; /* LSB */
reg_val |= ((1 << kpp_dev.kpp_cols) - 1) << 8; /* MSB */
__raw_writew(reg_val, KPCR);
/* Write 0's to KPDR[15:8] */
reg_val = __raw_readw(KPDR);
reg_val &= 0x00ff;
__raw_writew(reg_val, KPDR);
/* Configure columns as output,
* rows as input (KDDR[15:0]) */
reg_val = __raw_readw(KDDR);
reg_val |= 0xff00;
reg_val &= 0xff00;
__raw_writew(reg_val, KDDR);
/* Clear the KPKD Status Flag
* and Synchronizer chain. */
reg_val = __raw_readw(KPSR);
reg_val &= ~(KBD_STAT_KPKR | KBD_STAT_KPKD);
reg_val |= KBD_STAT_KPKD;
reg_val |= KBD_STAT_KRSS | KBD_STAT_KDSC;
__raw_writew(reg_val, KPSR);
/* Set the KDIE control bit, and clear the KRIE
* control bit (avoid false release events). */
reg_val |= KBD_STAT_KDIE;
reg_val &= ~KBD_STAT_KRIE;
__raw_writew(reg_val, KPSR);
#ifdef KPP_DEBUG
mxc_kpp_dump_regs();
#endif
mxckpd_keycodes = mxc_key_mapping;
mxckpd_keycodes_size = kpp_dev.kpp_cols * kpp_dev.kpp_rows;
if ((mxckpd_keycodes == (void *)0)
|| (mxckpd_keycodes_size == 0)) {
retval = -ENODEV;
goto err;
}
/* allocate required memory */
press_scancode = (short **)malloc(kpp_dev.kpp_rows * sizeof(press_scancode[0]));
release_scancode = (short **)malloc(kpp_dev.kpp_rows * sizeof(release_scancode[0]));
if (!press_scancode || !release_scancode) {
retval = -ENOMEM;
goto err;
}
for (i = 0; i < kpp_dev.kpp_rows; i++) {
press_scancode[i] = (short *)malloc(kpp_dev.kpp_cols
* sizeof(press_scancode[0][0]));
release_scancode[i] =
(short *)malloc(kpp_dev.kpp_cols * sizeof(release_scancode[0][0]));
if (!press_scancode[i] || !release_scancode[i]) {
retval = -ENOMEM;
goto err;
}
}
cur_rcmap =
(unsigned short *)malloc(kpp_dev.kpp_rows * sizeof(cur_rcmap[0]));
prev_rcmap =
(unsigned short *)malloc(kpp_dev.kpp_rows * sizeof(prev_rcmap[0]));
if (!cur_rcmap || !prev_rcmap) {
retval = -ENOMEM;
goto err;
}
for (i = 0; i < kpp_dev.kpp_rows; i++) {
memset(press_scancode[i], -1,
sizeof(press_scancode[0][0]) * kpp_dev.kpp_cols);
memset(release_scancode[i], -1,
sizeof(release_scancode[0][0]) * kpp_dev.kpp_cols);
}
memset(cur_rcmap, 0, kpp_dev.kpp_rows * sizeof(cur_rcmap[0]));
memset(prev_rcmap, 0, kpp_dev.kpp_rows * sizeof(prev_rcmap[0]));
return 0;
err:
mxc_kpp_free_allocated();
return retval;
}

View File

@ -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)

630
drivers/mmc/fsl_esdhc.c Normal file
View File

@ -0,0 +1,630 @@
/*
* 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 <asm/fsl_esdhc.h>
#include <linux/mmc/sdhci.h>
#include <asm/errno.h>
#include <common.h>
#include <linux/types.h>
#include <asm/io.h>
#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 (readl(esdhc_base_pointer + SDHCI_SYSTEM_CONTROL) \
& ESDHC_SOFTWARE_RESET) {
reset_status = 1;
} else {
reset_status = 0;
break;
}
}
/* 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;
/* Clear SDCLKEN bit */
REG_WRITE_AND((~ESDHC_SYSCTL_SDCLKEN_MASK), \
esdhc_base_pointer + SDHCI_SYSTEM_CONTROL);
/* Clear DTOCV, SDCLKFS, DVFS bits */
REG_WRITE_AND((~ESDHC_SYSCTL_FREQ_MASK), \
esdhc_base_pointer + SDHCI_SYSTEM_CONTROL);
ident_freq = ESDHC_SYSCTL_IDENT_FREQ;
oper_freq = ESDHC_SYSCTL_OPERT_FREQ;
/* Disable the PEREN, HCKEN and IPGEN */
REG_WRITE_AND((~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);
}
/* 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 */
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)
{
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);
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)<<ESDHC_DATA_TRANSFER_SHIFT) |
((cmd->response_format)<<ESDHC_RESPONSE_FORMAT_SHIFT) |
((cmd->data_present)<<ESDHC_DATA_PRESENT_SHIFT) |
((cmd->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);
}
/* 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 (!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)) {
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

1569
drivers/mmc/fsl_mmc.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,9 @@ 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_MXC_NAND) += mxc_nand.o
endif
COBJS := $(COBJS-y)

View File

@ -0,0 +1,968 @@
/*
* 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 <common.h>
#include <nand.h>
#include <asm-arm/arch/mx31-regs.h>
/*
* 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_ecclayout nand_hw_eccoob_8 = {
.eccbytes = 5,
.eccpos = {6, 7, 8, 9, 10},
.oobfree = {
{0, 5},
{11, 5}
}
};
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},
.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)
MTDDEBUG(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)
{
MTDDEBUG(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)
{
MTDDEBUG(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)
{
MTDDEBUG(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 */
MTDDEBUG(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;
MTDDEBUG(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)
{
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;
/* 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)) {
MTDDEBUG(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;
MTDDEBUG(MTD_DEBUG_LEVEL3, "mxc_nand_read_word(col = %d)\n", nandinfo.col);
col = nandinfo.col;
/* Adjust saved column address */
if (col < mtd->writesize && nandinfo.oob)
col += mtd->writesize;
if (col < mtd->writesize)
p = (MAIN_AREA0) + (col >> 1);
else
p = (SPARE_AREA0) + ((col - mtd->writesize) >> 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;
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->writesize && nandinfo.oob)
col += mtd->writesize;
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);
MTDDEBUG(MTD_DEBUG_LEVEL3,
"%s:%d: col = %d, n = %d\n", __FUNCTION__, __LINE__, col, n);
while (n) {
volatile u32 *p;
if (col < mtd->writesize)
p = (volatile u32 *)((ulong) (MAIN_AREA0) + (col & ~3));
else
p = (volatile u32 *)((ulong) (SPARE_AREA0) -
mtd->writesize + (col & ~3));
MTDDEBUG(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->writesize - col;
if (col >= mtd->writesize)
m += mtd->oobsize;
m = min(n, m) & ~3;
MTDDEBUG(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;
MTDDEBUG(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->writesize && nandinfo.oob)
col += mtd->writesize;
n = mtd->writesize + mtd->oobsize - col;
n = min(len, n);
while (n) {
volatile u32 *p;
if (col < mtd->writesize)
p = (volatile u32 *)((ulong) (MAIN_AREA0) + (col & ~3));
else
p = (volatile u32 *)((ulong) (SPARE_AREA0) -
mtd->writesize + (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->writesize - col;
if (col >= mtd->writesize)
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)
{
MTDDEBUG(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->writesize) {
/* 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->writesize;
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();
nandinfo.col = column;
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->writesize */
if (mtd->writesize == 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->writesize > 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->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;
/* 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->ecc.layout = &nand_hw_eccoob_2k;
} else {
nandinfo.largepage = 0;
nand->ecc.layout = &nand_hw_eccoob_8;
}
return 0;
}

1277
drivers/mtd/nand/mxc_nand.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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) {
@ -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

Some files were not shown because too many files have changed in this diff Show More