import i96 uboot aka overwrite official uboot with orangepi's so i can have a diff to work with
This commit is contained in:
parent
1a78434253
commit
bd4d8f6906
|
@ -5,52 +5,61 @@
|
|||
#
|
||||
# Normal rules
|
||||
#
|
||||
|
||||
*.rej
|
||||
*.orig
|
||||
*.a
|
||||
.*
|
||||
*.o
|
||||
*.o.*
|
||||
*.a
|
||||
*.s
|
||||
*.su
|
||||
*~
|
||||
*.mod.c
|
||||
*.i
|
||||
*.lst
|
||||
*.order
|
||||
*.elf
|
||||
*.swp
|
||||
*.patch
|
||||
*.bin
|
||||
*.patch
|
||||
*.cfgtmp
|
||||
*.rda
|
||||
*.img
|
||||
|
||||
# host programs on Cygwin
|
||||
*.exe
|
||||
|
||||
# Build tree
|
||||
/build-*
|
||||
|
||||
#
|
||||
# Top-level generic files
|
||||
#
|
||||
|
||||
/MLO
|
||||
/MLO*
|
||||
/SPL
|
||||
/System.map
|
||||
/u-boot
|
||||
/u-boot.hex
|
||||
/u-boot.imx
|
||||
/u-boot.map
|
||||
/u-boot.srec
|
||||
/u-boot.ldr
|
||||
/u-boot.ldr.hex
|
||||
/u-boot.ldr.srec
|
||||
/u-boot.img
|
||||
/u-boot.kwb
|
||||
/u-boot.sha1
|
||||
/u-boot.dis
|
||||
/u-boot.lds
|
||||
/u-boot.ubl
|
||||
/u-boot.ais
|
||||
/u-boot.dtb
|
||||
/u-boot.sb
|
||||
/u-boot*
|
||||
|
||||
#
|
||||
# git files that we don't want to ignore even it they are dot-files
|
||||
#
|
||||
!.gitignore
|
||||
!.mailmap
|
||||
|
||||
#
|
||||
# Generated files
|
||||
#
|
||||
|
||||
*.depend*
|
||||
/LOG
|
||||
/errlog
|
||||
/reloc_off
|
||||
|
||||
/tpl/
|
||||
|
||||
#
|
||||
# Generated include files
|
||||
#
|
||||
/include/config/
|
||||
/include/generated/
|
||||
asm-offsets.s
|
||||
/include/spl-autoconf.mk
|
||||
/include/tpl-autoconf.mk
|
||||
|
||||
# stgit generated dirs
|
||||
patches-*
|
||||
|
@ -71,7 +80,15 @@ cscope.*
|
|||
/ctags
|
||||
/etags
|
||||
|
||||
# OneNAND IPL files
|
||||
/onenand_ipl/onenand-ipl*
|
||||
/onenand_ipl/board/*/onenand*
|
||||
/onenand_ipl/board/*/*.S
|
||||
# gnu global files
|
||||
GPATH
|
||||
GRTAGS
|
||||
GSYMS
|
||||
GTAGS
|
||||
|
||||
*.orig
|
||||
*~
|
||||
\#*#
|
||||
|
||||
/cur.log
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# Copyright (C) 2007 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# If you don't need to do a full clean build but would like to touch
|
||||
# a file or delete some intermediate files, add a clean step to the end
|
||||
# of the list. These steps will only be run once, if they haven't been
|
||||
# run before.
|
||||
#
|
||||
# E.g.:
|
||||
# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
|
||||
# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
|
||||
#
|
||||
# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
|
||||
# files that are missing or have been moved.
|
||||
#
|
||||
# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
|
||||
# Use $(OUT_DIR) to refer to the "out" directory.
|
||||
#
|
||||
# If you need to re-do something that's already mentioned, just copy
|
||||
# the command and add it to the bottom of the list. E.g., if a change
|
||||
# that you made last week required touching a file and a change you
|
||||
# made today requires touching the same file, just copy the old
|
||||
# touch step and add it to the end of the list.
|
||||
#
|
||||
# ************************************************
|
||||
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
|
||||
# ************************************************
|
||||
|
||||
# For example:
|
||||
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
|
||||
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
|
||||
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
|
||||
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
|
||||
|
||||
# ************************************************
|
||||
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
|
||||
# ************************************************
|
25
MAINTAINERS
25
MAINTAINERS
|
@ -777,6 +777,10 @@ Linus Walleij <linus.walleij@linaro.org>
|
|||
integratorap various
|
||||
integratorcp various
|
||||
|
||||
Luka Perkov <uboot@lukaperkov.net>
|
||||
|
||||
ib62x0 ARM926EJS
|
||||
|
||||
Dave Peverley <dpeverley@mpc-data.co.uk>
|
||||
|
||||
omap730p2 ARM926EJS
|
||||
|
@ -788,6 +792,16 @@ Stelian Pop <stelian@popies.net>
|
|||
at91sam9263ek ARM926EJS (AT91SAM9263 SoC)
|
||||
at91sam9rlek ARM926EJS (AT91SAM9RL SoC)
|
||||
|
||||
Dave Purdy <david.c.purdy@gmail.com>
|
||||
|
||||
pogo_e02 ARM926EJS (Kirkwood SoC)
|
||||
|
||||
Sricharan R <r.sricharan@ti.com>
|
||||
|
||||
omap4_panda ARM ARMV7 (OMAP4xx SoC)
|
||||
omap4_sdp4430 ARM ARMV7 (OMAP4xx SoC)
|
||||
omap5_evm ARM ARMV7 (OMAP5xx Soc)
|
||||
|
||||
Thierry Reding <thierry.reding@avionic-design.de>
|
||||
|
||||
plutux Tegra2 (ARM7 & A9 Dual Core)
|
||||
|
@ -860,12 +874,6 @@ Greg Ungerer <greg.ungerer@opengear.com>
|
|||
cm4116 ks8695p
|
||||
cm4148 ks8695p
|
||||
|
||||
Aneesh V <aneesh@ti.com>
|
||||
|
||||
omap4_panda ARM ARMV7 (OMAP4xx SoC)
|
||||
omap4_sdp4430 ARM ARMV7 (OMAP4xx SoC)
|
||||
omap5_evm ARM ARMV7 (OMAP5xx Soc)
|
||||
|
||||
Marek Vasut <marek.vasut@gmail.com>
|
||||
|
||||
balloon3 xscale/pxa
|
||||
|
@ -932,6 +940,10 @@ Sughosh Ganu <urwithsughosh@gmail.com>
|
|||
|
||||
hawkboard ARM926EJS (OMAP-L138)
|
||||
|
||||
Vladimir Zapolskiy <vz@mleia.com>
|
||||
|
||||
devkit3250 lpc32xx
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
Unknown / orphaned boards:
|
||||
|
@ -1191,6 +1203,7 @@ Macpaul Lin <macpaul@andestech.com>
|
|||
|
||||
ADP-AG101 N1213 (AG101 SoC)
|
||||
ADP-AG101P N1213 (AG101P XC5 FPGA)
|
||||
ADP-AG102 N1213f (AG102 SoC with FPU)
|
||||
|
||||
#########################################################################
|
||||
# OpenRISC Systems: #
|
||||
|
|
|
@ -34,6 +34,7 @@ usage()
|
|||
CROSS_COMPILE cross-compiler toolchain prefix (default: "")
|
||||
MAKEALL_LOGDIR output all logs to here (default: ./LOG/)
|
||||
BUILD_DIR output build directory (default: ./)
|
||||
BUILD_NBUILDS number of parallel targets (default: 1)
|
||||
|
||||
Examples:
|
||||
- build all Power Architecture boards:
|
||||
|
@ -178,18 +179,33 @@ else
|
|||
LOG_DIR="LOG"
|
||||
fi
|
||||
|
||||
if [ ! "${BUILD_DIR}" ] ; then
|
||||
BUILD_DIR="."
|
||||
: ${BUILD_NBUILDS:=1}
|
||||
BUILD_MANY=0
|
||||
|
||||
if [ "${BUILD_NBUILDS}" -gt 1 ] ; then
|
||||
BUILD_MANY=1
|
||||
: ${BUILD_DIR:=./build}
|
||||
mkdir -p "${BUILD_DIR}/ERR"
|
||||
find "${BUILD_DIR}/ERR/" -type f -exec rm -f {} +
|
||||
fi
|
||||
|
||||
[ -d ${LOG_DIR} ] || mkdir ${LOG_DIR} || exit 1
|
||||
: ${BUILD_DIR:=.}
|
||||
|
||||
OUTPUT_PREFIX="${BUILD_DIR}"
|
||||
|
||||
[ -d ${LOG_DIR} ] || mkdir "${LOG_DIR}" || exit 1
|
||||
find "${LOG_DIR}/" -type f -exec rm -f {} +
|
||||
|
||||
LIST=""
|
||||
|
||||
# Keep track of the number of builds and errors
|
||||
ERR_CNT=0
|
||||
ERR_LIST=""
|
||||
WRN_CNT=0
|
||||
WRN_LIST=""
|
||||
TOTAL_CNT=0
|
||||
CURRENT_CNT=0
|
||||
OLDEST_IDX=1
|
||||
RC=0
|
||||
|
||||
# Helper funcs for parsing boards.cfg
|
||||
|
@ -326,12 +342,7 @@ LIST_ARM9="$(boards_by_cpu arm920t) \
|
|||
#########################################################################
|
||||
## ARM11 Systems
|
||||
#########################################################################
|
||||
LIST_ARM11="$(boards_by_cpu arm1136) \
|
||||
imx31_phycore \
|
||||
imx31_phycore_eet \
|
||||
mx31pdk \
|
||||
smdk6400 \
|
||||
"
|
||||
LIST_ARM11="$(boards_by_cpu arm1136)"
|
||||
|
||||
#########################################################################
|
||||
## ARMV7 Systems
|
||||
|
@ -351,10 +362,7 @@ LIST_at91="$(boards_by_soc at91)"
|
|||
|
||||
LIST_pxa="$(boards_by_cpu pxa)"
|
||||
|
||||
LIST_ixp="$(boards_by_cpu ixp)
|
||||
pdnb3 \
|
||||
scpu \
|
||||
"
|
||||
LIST_ixp="$(boards_by_cpu ixp)"
|
||||
|
||||
#########################################################################
|
||||
## ARM groups
|
||||
|
@ -592,41 +600,106 @@ list_target() {
|
|||
echo ""
|
||||
}
|
||||
|
||||
# Each finished build will have a file called ${donep}${n},
|
||||
# where n is the index of the build. Each build
|
||||
# we've already noted as finished will have ${skipp}${n}.
|
||||
# The code managing the build process will use this information
|
||||
# to ensure that only BUILD_NBUILDS builds are in flight at once
|
||||
donep="${LOG_DIR}/._done_"
|
||||
skipp="${LOG_DIR}/._skip_"
|
||||
|
||||
build_target() {
|
||||
target=$1
|
||||
build_idx=$2
|
||||
|
||||
if [ "$ONLY_LIST" == 'y' ] ; then
|
||||
list_target ${target}
|
||||
return
|
||||
fi
|
||||
|
||||
if [ $BUILD_MANY == 1 ] ; then
|
||||
output_dir="${OUTPUT_PREFIX}/${target}"
|
||||
mkdir -p "${output_dir}"
|
||||
else
|
||||
output_dir="${OUTPUT_PREFIX}"
|
||||
fi
|
||||
|
||||
export BUILD_DIR="${output_dir}"
|
||||
|
||||
${MAKE} distclean >/dev/null
|
||||
${MAKE} -s ${target}_config
|
||||
|
||||
${MAKE} ${JOBS} all 2>&1 >${LOG_DIR}/$target.MAKELOG \
|
||||
| tee ${LOG_DIR}/$target.ERR
|
||||
${MAKE} ${JOBS} all \
|
||||
>${LOG_DIR}/$target.MAKELOG 2> ${LOG_DIR}/$target.ERR
|
||||
|
||||
# Check for 'make' errors
|
||||
if [ ${PIPESTATUS[0]} -ne 0 ] ; then
|
||||
RC=1
|
||||
fi
|
||||
|
||||
if [ -s ${LOG_DIR}/$target.ERR ] ; then
|
||||
ERR_CNT=$((ERR_CNT + 1))
|
||||
ERR_LIST="${ERR_LIST} $target"
|
||||
if [ $BUILD_MANY == 1 ] ; then
|
||||
${MAKE} tidy
|
||||
|
||||
if [ -s ${LOG_DIR}/${target}.ERR ] ; then
|
||||
cp ${LOG_DIR}/${target}.ERR ${OUTPUT_PREFIX}/ERR/${target}
|
||||
else
|
||||
rm ${LOG_DIR}/${target}.ERR
|
||||
fi
|
||||
else
|
||||
rm ${LOG_DIR}/$target.ERR
|
||||
if [ -s ${LOG_DIR}/${target}.ERR ] ; then
|
||||
if grep -iw error ${LOG_DIR}/${target}.ERR ; then
|
||||
: $(( ERR_CNT += 1 ))
|
||||
ERR_LIST="${ERR_LIST} $target"
|
||||
else
|
||||
: $(( WRN_CNT += 1 ))
|
||||
WRN_LIST="${WRN_LIST} $target"
|
||||
fi
|
||||
else
|
||||
rm ${LOG_DIR}/${target}.ERR
|
||||
fi
|
||||
fi
|
||||
|
||||
TOTAL_CNT=$((TOTAL_CNT + 1))
|
||||
|
||||
OBJS=${BUILD_DIR}/u-boot
|
||||
if [ -e ${BUILD_DIR}/spl/u-boot-spl ]; then
|
||||
OBJS="${OBJS} ${BUILD_DIR}/spl/u-boot-spl"
|
||||
OBJS=${output_dir}/u-boot
|
||||
if [ -e ${output_dir}/spl/u-boot-spl ]; then
|
||||
OBJS="${OBJS} ${output_dir}/spl/u-boot-spl"
|
||||
fi
|
||||
|
||||
${CROSS_COMPILE}size ${OBJS} | tee -a ${LOG_DIR}/$target.MAKELOG
|
||||
|
||||
[ -e "${LOG_DIR}/${target}.ERR" ] && cat "${LOG_DIR}/${target}.ERR"
|
||||
|
||||
touch "${donep}${build_idx}"
|
||||
}
|
||||
|
||||
manage_builds() {
|
||||
search_idx=${OLDEST_IDX}
|
||||
if [ "$ONLY_LIST" == 'y' ] ; then return ; fi
|
||||
|
||||
while true; do
|
||||
if [ -e "${donep}${search_idx}" ] ; then
|
||||
: $(( CURRENT_CNT-- ))
|
||||
[ ${OLDEST_IDX} -eq ${search_idx} ] &&
|
||||
: $(( OLDEST_IDX++ ))
|
||||
|
||||
# Only want to count it once
|
||||
rm -f "${donep}${search_idx}"
|
||||
touch "${skipp}${search_idx}"
|
||||
elif [ -e "${skipp}${search_idx}" ] ; then
|
||||
[ ${OLDEST_IDX} -eq ${search_idx} ] &&
|
||||
: $(( OLDEST_IDX++ ))
|
||||
fi
|
||||
: $(( search_idx++ ))
|
||||
if [ ${search_idx} -gt ${TOTAL_CNT} ] ; then
|
||||
if [ ${CURRENT_CNT} -ge ${BUILD_NBUILDS} ] ; then
|
||||
search_idx=${OLDEST_IDX}
|
||||
sleep 1
|
||||
else
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
build_targets() {
|
||||
for t in "$@" ; do
|
||||
# If a LIST_xxx var exists, use it. But avoid variable
|
||||
|
@ -639,23 +712,71 @@ build_targets() {
|
|||
if [ -n "${list}" ] ; then
|
||||
build_targets ${list}
|
||||
else
|
||||
build_target ${t}
|
||||
: $((TOTAL_CNT += 1))
|
||||
: $((CURRENT_CNT += 1))
|
||||
rm -f "${donep}${TOTAL_CNT}"
|
||||
rm -f "${skipp}${TOTAL_CNT}"
|
||||
if [ $BUILD_MANY == 1 ] ; then
|
||||
build_target ${t} ${TOTAL_CNT} &
|
||||
else
|
||||
build_target ${t} ${TOTAL_CNT}
|
||||
fi
|
||||
fi
|
||||
|
||||
# We maintain a running count of all the builds we have done.
|
||||
# Each finished build will have a file called ${donep}${n},
|
||||
# where n is the index of the build. Each build
|
||||
# we've already noted as finished will have ${skipp}${n}.
|
||||
# We track the current index via TOTAL_CNT, and the oldest
|
||||
# index. When we exceed the maximum number of parallel builds,
|
||||
# We look from oldest to current for builds that have completed,
|
||||
# and update the current count and oldest index as appropriate.
|
||||
# If we've gone through the entire list, wait a second, and
|
||||
# reprocess the entire list until we find a build that has
|
||||
# completed
|
||||
if [ ${CURRENT_CNT} -ge ${BUILD_NBUILDS} ] ; then
|
||||
manage_builds
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
kill_children() {
|
||||
kill -- "-$1"
|
||||
|
||||
exit
|
||||
}
|
||||
|
||||
print_stats() {
|
||||
if [ "$ONLY_LIST" == 'y' ] ; then return ; fi
|
||||
|
||||
rm -f ${donep}* ${skipp}*
|
||||
|
||||
if [ $BUILD_MANY == 1 ] && [ -e "${OUTPUT_PREFIX}/ERR" ] ; then
|
||||
ERR_LIST=`grep -iwl error ${OUTPUT_PREFIX}/ERR/*`
|
||||
ERR_LIST=`for f in $ERR_LIST ; do echo -n " $(basename $f)" ; done`
|
||||
ERR_CNT=`echo $ERR_LIST | wc -w | awk '{print $1}'`
|
||||
WRN_LIST=`grep -iwL error ${OUTPUT_PREFIX}/ERR/*`
|
||||
WRN_LIST=`for f in $WRN_LIST ; do echo -n " $(basename $f)" ; done`
|
||||
WRN_CNT=`echo $WRN_LIST | wc -w | awk '{print $1}'`
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "--------------------- SUMMARY ----------------------------"
|
||||
echo "Boards compiled: ${TOTAL_CNT}"
|
||||
if [ ${ERR_CNT} -gt 0 ] ; then
|
||||
echo "Boards with warnings or errors: ${ERR_CNT} (${ERR_LIST} )"
|
||||
echo "Boards with errors: ${ERR_CNT} (${ERR_LIST} )"
|
||||
fi
|
||||
if [ ${WRN_CNT} -gt 0 ] ; then
|
||||
echo "Boards with warnings but no errors: ${WRN_CNT} (${WRN_LIST} )"
|
||||
fi
|
||||
echo "----------------------------------------------------------"
|
||||
|
||||
if [ $BUILD_MANY == 1 ] ; then
|
||||
kill_children $$ &
|
||||
fi
|
||||
|
||||
exit $RC
|
||||
}
|
||||
|
||||
|
@ -666,3 +787,4 @@ set -- ${SELECTED} "$@"
|
|||
# run PowerPC by default
|
||||
[ $# = 0 ] && set -- powerpc
|
||||
build_targets "$@"
|
||||
wait
|
||||
|
|
112
Makefile
112
Makefile
|
@ -23,8 +23,8 @@
|
|||
|
||||
VERSION = 2012
|
||||
PATCHLEVEL = 04
|
||||
SUBLEVEL =
|
||||
EXTRAVERSION =
|
||||
SUBLEVEL = 442
|
||||
EXTRAVERSION = -rel5.0.2
|
||||
ifneq "$(SUBLEVEL)" ""
|
||||
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
|
||||
else
|
||||
|
@ -58,10 +58,15 @@ VENDOR=
|
|||
|
||||
#########################################################################
|
||||
# Allow for silent builds
|
||||
ifneq (1,$(V))
|
||||
export MAKEFLAGS += -s --no-print-directory
|
||||
export STDOUT_NULL := 1>/dev/null
|
||||
endif
|
||||
|
||||
ifeq (,$(findstring s,$(MAKEFLAGS)))
|
||||
XECHO = echo
|
||||
export XECHO = :
|
||||
else
|
||||
XECHO = :
|
||||
export XECHO = echo
|
||||
endif
|
||||
|
||||
#########################################################################
|
||||
|
@ -110,6 +115,7 @@ TOPDIR := $(SRCTREE)
|
|||
LNDIR := $(OBJTREE)
|
||||
export TOPDIR SRCTREE OBJTREE SPLTREE
|
||||
|
||||
|
||||
MKCONFIG := $(SRCTREE)/mkconfig
|
||||
export MKCONFIG
|
||||
|
||||
|
@ -140,7 +146,7 @@ unexport CDPATH
|
|||
# The "examples" conditionally depend on U-Boot (say, when USE_PRIVATE_LIBGCC
|
||||
# is "yes"), so compile examples after U-Boot is compiled.
|
||||
SUBDIR_TOOLS = tools
|
||||
SUBDIR_EXAMPLES = examples/standalone examples/api
|
||||
#SUBDIR_EXAMPLES = examples/standalone examples/api
|
||||
SUBDIRS = $(SUBDIR_TOOLS)
|
||||
|
||||
.PHONY : $(SUBDIRS) $(VERSION_FILE) $(TIMESTAMP_FILE)
|
||||
|
@ -301,6 +307,9 @@ LIBS += common/libcommon.o
|
|||
LIBS += lib/libfdt/libfdt.o
|
||||
LIBS += api/libapi.o
|
||||
LIBS += post/libpost.o
|
||||
LIBS += android/libandroid.o
|
||||
LIBS += pdl/common/libpdl_common.o
|
||||
LIBS += pdl/pdl-2/libpdl_stage.o
|
||||
|
||||
ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
|
||||
LIBS += $(CPUDIR)/omap-common/libomap-common.o
|
||||
|
@ -370,12 +379,13 @@ BOARD_SIZE_CHECK =
|
|||
endif
|
||||
|
||||
# Always append ALL so that arch config.mk's can add custom ones
|
||||
ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map
|
||||
ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(obj)u-boot.img
|
||||
|
||||
ALL-$(CONFIG_NAND_U_BOOT) += $(obj)u-boot-nand.bin
|
||||
ALL-$(CONFIG_ONENAND_U_BOOT) += $(obj)u-boot-onenand.bin
|
||||
ONENAND_BIN ?= $(obj)onenand_ipl/onenand-ipl-2k.bin
|
||||
ALL-$(CONFIG_SPL) += $(obj)spl/u-boot-spl.bin
|
||||
ALL-$(CONFIG_SPL) += $(obj)u-boot$(RDASIGN).rda $(obj)spl/u-boot-spl$(RDASIGN).img \
|
||||
$(obj)spl/u-boot-spl.bin
|
||||
ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb $(obj)u-boot-dtb.bin
|
||||
|
||||
all: $(ALL-y) $(SUBDIR_EXAMPLES)
|
||||
|
@ -409,41 +419,82 @@ $(obj)u-boot.ldr.srec: $(obj)u-boot.ldr
|
|||
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ -I binary
|
||||
|
||||
$(obj)u-boot.img: $(obj)u-boot.bin
|
||||
$(XECHO)
|
||||
$(XECHO) " GEN $(@F)"
|
||||
$(obj)tools/mkimage -A $(ARCH) -T firmware -C none \
|
||||
-O u-boot -a $(CONFIG_SYS_TEXT_BASE) -e 0 \
|
||||
-n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
|
||||
sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
|
||||
-d $< $@
|
||||
-d $< $@ $(STDOUT_NULL)
|
||||
|
||||
$(obj)u-boot.imx: $(obj)u-boot.bin
|
||||
$(XECHO)
|
||||
$(XECHO) " GEN $(@F)"
|
||||
$(obj)tools/mkimage -n $(CONFIG_IMX_CONFIG) -T imximage \
|
||||
-e $(CONFIG_SYS_TEXT_BASE) -d $< $@
|
||||
-e $(CONFIG_SYS_TEXT_BASE) -d $< $@ $(STDOUT_NULL)
|
||||
|
||||
$(obj)u-boot.kwb: $(obj)u-boot.bin
|
||||
$(XECHO)
|
||||
$(XECHO) " GEN $(@F)"
|
||||
$(obj)tools/mkimage -n $(CONFIG_SYS_KWD_CONFIG) -T kwbimage \
|
||||
-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) -d $< $@
|
||||
-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) -d \
|
||||
$< $@ $(STDOUT_NULL)
|
||||
|
||||
$(obj)u-boot.sha1: $(obj)u-boot.bin
|
||||
$(obj)tools/ubsha1 $(obj)u-boot.bin
|
||||
|
||||
ifeq ($(RDASIGN),)
|
||||
$(obj)pdl1$(RDASIGN).bin: $(obj)spl/u-boot-spl.bin
|
||||
cp $< $@
|
||||
else
|
||||
$(obj)pdl1$(RDASIGN).bin: $(obj)spl/u-boot-spl$(RDASIGN).img
|
||||
cp $< $@
|
||||
endif
|
||||
|
||||
$(obj)pdl2.bin: $(obj)u-boot.bin
|
||||
cp $< $@
|
||||
|
||||
.PHONY: PDL
|
||||
PDL: depend $(obj)pdl1$(RDASIGN).bin $(obj)pdl2$(RDASIGN).bin
|
||||
|
||||
$(obj)pdl2-sign.bin: $(obj)u-boot.bin
|
||||
@echo "Signing: $(notdir $@)"
|
||||
rdasign -Sba $(UBOOT_SIGN_FLAGS) -m $^ -x $@
|
||||
|
||||
$(obj)spl/u-boot-spl-sign.img: $(obj)spl/u-boot-spl.img
|
||||
rdacryptotool -m indirect $(SPL_SIGN_FLAGS) -i $^ -o $@
|
||||
|
||||
$(obj)u-boot-sign.img: $(obj)u-boot.img
|
||||
@echo "Signing: $(notdir $@)"
|
||||
rdasign -Sba $(UBOOT_SIGN_FLAGS) -m $^ -x $@
|
||||
|
||||
$(obj)u-boot.dis: $(obj)u-boot
|
||||
$(OBJDUMP) -d $< > $@
|
||||
|
||||
$(obj)u-boot.ubl: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin
|
||||
$(XECHO)
|
||||
$(XECHO) " GEN $(@F)"
|
||||
$(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $(obj)spl/u-boot-spl $(obj)spl/u-boot-spl-pad.bin
|
||||
cat $(obj)spl/u-boot-spl-pad.bin $(obj)u-boot.bin > $(obj)u-boot-ubl.bin
|
||||
$(obj)tools/mkimage -n $(UBL_CONFIG) -T ublimage \
|
||||
-e $(CONFIG_SYS_TEXT_BASE) -d $(obj)u-boot-ubl.bin $(obj)u-boot.ubl
|
||||
-e $(CONFIG_SYS_TEXT_BASE) -d $(obj)u-boot-ubl.bin \
|
||||
$(obj)u-boot.ubl $(STDOUT_NULL)
|
||||
rm $(obj)u-boot-ubl.bin
|
||||
rm $(obj)spl/u-boot-spl-pad.bin
|
||||
|
||||
$(obj)u-boot$(RDASIGN).rda: $(obj)spl/u-boot-spl$(RDASIGN).img $(obj)u-boot$(RDASIGN).img
|
||||
$(shell $(TOPDIR)/tools/mkrdaimage.sh $(BOARD_NAND_PAGE_SIZE) \
|
||||
$^ $(SPL_APPENDING_TO) $@)
|
||||
|
||||
$(obj)u-boot.ais: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin
|
||||
$(XECHO)
|
||||
$(XECHO) " GEN $(@F)"
|
||||
$(obj)tools/mkimage -s -n /dev/null -T aisimage \
|
||||
-e $(CONFIG_SPL_TEXT_BASE) \
|
||||
-d $(obj)spl/u-boot-spl.bin \
|
||||
$(obj)spl/u-boot-spl.ais
|
||||
$(obj)spl/u-boot-spl.ais $(STDOUT_NULL)
|
||||
$(OBJCOPY) ${OBJCFLAGS} -I binary \
|
||||
--pad-to=$(CONFIG_SPL_MAX_SIZE) -O binary \
|
||||
--pad-to=$(CONFIG_SPL_CODE_MAX_SIZE) -O binary \
|
||||
$(obj)spl/u-boot-spl.ais $(obj)spl/u-boot-spl-pad.ais
|
||||
cat $(obj)spl/u-boot-spl-pad.ais $(obj)u-boot.bin > \
|
||||
$(obj)u-boot.ais
|
||||
|
@ -479,26 +530,39 @@ ifeq ($(CONFIG_KALLSYMS),y)
|
|||
endif
|
||||
|
||||
$(OBJS): depend
|
||||
$(XECHO)
|
||||
$(XECHO) " MAKE $(subst $(obj),,$@)"
|
||||
$(MAKE) -C $(CPUDIR) $(if $(REMOTE_BUILD),$@,$(notdir $@))
|
||||
|
||||
$(LIBS): depend $(SUBDIR_TOOLS)
|
||||
$(XECHO)
|
||||
$(XECHO) " MAKE $(dir $(subst $(obj),,$@))"
|
||||
$(MAKE) -C $(dir $(subst $(obj),,$@))
|
||||
|
||||
$(LIBBOARD): depend $(LIBS)
|
||||
$(XECHO)
|
||||
$(XECHO) " MAKE $(dir $(subst $(obj),,$@))"
|
||||
$(MAKE) -C $(dir $(subst $(obj),,$@))
|
||||
|
||||
$(SUBDIRS): depend
|
||||
$(XECHO)
|
||||
$(XECHO) " MAKE $(subst $(obj),,$@)"
|
||||
$(MAKE) -C $@ all
|
||||
|
||||
$(SUBDIR_EXAMPLES): $(obj)u-boot
|
||||
|
||||
$(LDSCRIPT): depend
|
||||
$(XECHO)
|
||||
$(XECHO) " GEN $(notdir $@)"
|
||||
$(MAKE) -C $(dir $@) $(notdir $@)
|
||||
|
||||
$(obj)u-boot.lds: $(LDSCRIPT)
|
||||
$(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@
|
||||
|
||||
.PHONY: nand_spl
|
||||
nand_spl: $(TIMESTAMP_FILE) $(VERSION_FILE) depend
|
||||
$(XECHO)
|
||||
$(XECHO) " MAKE nand_spl/board/$(BOARDDIR)"
|
||||
$(MAKE) -C nand_spl/board/$(BOARDDIR) all
|
||||
|
||||
$(obj)u-boot-nand.bin: nand_spl $(obj)u-boot.bin
|
||||
|
@ -510,10 +574,21 @@ onenand_ipl: $(TIMESTAMP_FILE) $(VERSION_FILE) $(obj)include/autoconf.mk
|
|||
$(obj)u-boot-onenand.bin: onenand_ipl $(obj)u-boot.bin
|
||||
cat $(ONENAND_BIN) $(obj)u-boot.bin > $(obj)u-boot-onenand.bin
|
||||
|
||||
$(obj)spl/u-boot-spl.bin: $(SUBDIR_TOOLS) depend
|
||||
.PHONY: u-boot-spl
|
||||
u-boot-spl: $(SUBDIR_TOOLS) depend
|
||||
$(XECHO)
|
||||
$(XECHO) " MAKE $@"
|
||||
$(MAKE) -C spl all
|
||||
|
||||
$(obj)spl/u-boot-spl.img $(obj)spl/u-boot-spl.bin: u-boot-spl
|
||||
# The line below make dependencies work, no idea why.
|
||||
# Without the line you have to build twice to get get
|
||||
# the new version of u-boot-spl.img linked at this level.
|
||||
@echo "Build $(notdir $@)"
|
||||
|
||||
updater:
|
||||
$(XECHO)
|
||||
$(XECHO) " MAKE tools/updater"
|
||||
$(MAKE) -C tools/updater all
|
||||
|
||||
# Explicitly make _depend in subdirs containing multiple targets to prevent
|
||||
|
@ -556,6 +631,13 @@ SYSTEM_MAP = \
|
|||
$(obj)System.map: $(obj)u-boot
|
||||
@$(call SYSTEM_MAP,$<) > $(obj)System.map
|
||||
|
||||
checkthumb:
|
||||
@if test $(call cc-version) -lt 0404; then \
|
||||
echo -n '*** Your GCC does not produce working '; \
|
||||
echo 'binaries in THUMB mode.'; \
|
||||
echo '*** Your board is configured for THUMB mode.'; \
|
||||
false; \
|
||||
fi
|
||||
#
|
||||
# Auto-generate the autoconf.mk file (which is included by all makefiles)
|
||||
#
|
||||
|
@ -740,7 +822,7 @@ clean:
|
|||
@rm -f $(obj)onenand_ipl/onenand-{ipl,ipl.bin,ipl.map}
|
||||
@rm -f $(ONENAND_BIN)
|
||||
@rm -f $(obj)onenand_ipl/u-boot.lds
|
||||
@rm -f $(obj)spl/{u-boot-spl,u-boot-spl.bin,u-boot-spl.lds,u-boot-spl.map}
|
||||
@rm -f $(obj)spl/{u-boot-spl,u-boot-spl.bin,u-boot-spl.img,u-boot-spl.lds,u-boot-spl.map}
|
||||
@rm -f $(obj)MLO
|
||||
@rm -f $(TIMESTAMP_FILE) $(VERSION_FILE)
|
||||
@find $(OBJTREE) -type f \
|
||||
|
|
51
README
51
README
|
@ -432,6 +432,14 @@ The following options need to be configured:
|
|||
Select high exception vectors of the ARM core, e.g., do not
|
||||
clear the V bit of the c1 register of CP15.
|
||||
|
||||
CONFIG_SYS_THUMB_BUILD
|
||||
|
||||
Use this flag to build U-Boot using the Thumb instruction
|
||||
set for ARM architectures. Thumb instruction set provides
|
||||
better code density. For ARM architectures that support
|
||||
Thumb2 this flag will result in Thumb2 code generated by
|
||||
GCC.
|
||||
|
||||
- Linux Kernel Interface:
|
||||
CONFIG_CLOCKS_IN_MHZ
|
||||
|
||||
|
@ -777,6 +785,8 @@ The following options need to be configured:
|
|||
CONFIG_CMD_JFFS2 * JFFS2 Support
|
||||
CONFIG_CMD_KGDB * kgdb
|
||||
CONFIG_CMD_LDRINFO ldrinfo (display Blackfin loader)
|
||||
CONFIG_CMD_LINK_LOCAL * link-local IP address auto-configuration
|
||||
(169.254.*.*)
|
||||
CONFIG_CMD_LOADB loadb
|
||||
CONFIG_CMD_LOADS loads
|
||||
CONFIG_CMD_MD5SUM print md5 message digest
|
||||
|
@ -814,7 +824,7 @@ The following options need to be configured:
|
|||
CONFIG_CMD_TIME * run command and report execution time
|
||||
CONFIG_CMD_USB * USB support
|
||||
CONFIG_CMD_CDP * Cisco Discover Protocol support
|
||||
CONFIG_CMD_FSL * Microblaze FSL support
|
||||
CONFIG_CMD_MFSL * Microblaze FSL support
|
||||
|
||||
|
||||
EXAMPLE: If you want all functions except of network
|
||||
|
@ -1584,10 +1594,17 @@ The following options need to be configured:
|
|||
CONFIG_BOOTP_NTPSERVER
|
||||
CONFIG_BOOTP_TIMEOFFSET
|
||||
CONFIG_BOOTP_VENDOREX
|
||||
CONFIG_BOOTP_MAY_FAIL
|
||||
|
||||
CONFIG_BOOTP_SERVERIP - TFTP server will be the serverip
|
||||
environment variable, not the BOOTP server.
|
||||
|
||||
CONFIG_BOOTP_MAY_FAIL - If the DHCP server is not found
|
||||
after the configured retry count, the call will fail
|
||||
instead of starting over. This can be used to fail over
|
||||
to Link-local IP address configuration if the DHCP server
|
||||
is not available.
|
||||
|
||||
CONFIG_BOOTP_DNS2 - If a DHCP client requests the DNS
|
||||
serverip from a DHCP server, it is possible that more
|
||||
than one DNS serverip is offered to the client.
|
||||
|
@ -1618,6 +1635,14 @@ The following options need to be configured:
|
|||
the DHCP timeout and retry process takes a longer than
|
||||
this delay.
|
||||
|
||||
- Link-local IP address negotiation:
|
||||
Negotiate with other link-local clients on the local network
|
||||
for an address that doesn't require explicit configuration.
|
||||
This is especially useful if a DHCP server cannot be guaranteed
|
||||
to exist in all environments that the device must operate.
|
||||
|
||||
See doc/README.link-local for more information.
|
||||
|
||||
- CDP Options:
|
||||
CONFIG_CDP_DEVICE_ID
|
||||
|
||||
|
@ -3026,6 +3051,24 @@ to save the current settings.
|
|||
environment area within the total memory of your DataFlash placed
|
||||
at the specified address.
|
||||
|
||||
- CONFIG_ENV_IS_IN_REMOTE:
|
||||
|
||||
Define this if you have a remote memory space which you
|
||||
want to use for the local device's environment.
|
||||
|
||||
- CONFIG_ENV_ADDR:
|
||||
- CONFIG_ENV_SIZE:
|
||||
|
||||
These two #defines specify the address and size of the
|
||||
environment area within the remote memory space. The
|
||||
local device can get the environment from remote memory
|
||||
space by SRIO or other links.
|
||||
|
||||
BE CAREFUL! For some special cases, the local device can not use
|
||||
"saveenv" command. For example, the local device will get the
|
||||
environment stored in a remote NOR flash by SRIO link, but it can
|
||||
not erase, write this NOR flash by SRIO interface.
|
||||
|
||||
- CONFIG_ENV_IS_IN_NAND:
|
||||
|
||||
Define this if you have a NAND device which you want to use
|
||||
|
@ -3462,6 +3505,12 @@ within that device.
|
|||
Specifies that QE/FMAN firmware is located on the primary SPI
|
||||
device. CONFIG_SYS_FMAN_FW_ADDR is the byte offset on that device.
|
||||
|
||||
- CONFIG_SYS_QE_FMAN_FW_IN_REMOTE
|
||||
Specifies that QE/FMAN firmware is located in the remote (master)
|
||||
memory space. CONFIG_SYS_FMAN_FW_ADDR is a virtual address which
|
||||
can be mapped from slave TLB->slave LAW->slave SRIO outbound window
|
||||
->master inbound window->master LAW->the ucode address in master's
|
||||
NOR flash.
|
||||
|
||||
Building the Software:
|
||||
======================
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#
|
||||
# (C) Copyright 2004-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)libandroid.o
|
||||
|
||||
COBJS-y += android_boot.o
|
||||
|
||||
COBJS := $(sort $(COBJS-y))
|
||||
SRCS := $(COBJS:.o=.c) $(XCOBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(COBJS))
|
||||
|
||||
CPPFLAGS += -I..
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
$(LIB): $(obj).depend $(OBJS)
|
||||
$(call cmd_link_o_target, $(OBJS))
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
|
@ -0,0 +1,50 @@
|
|||
#include <common.h>
|
||||
#include <android/android_boot.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
void creat_atags(unsigned taddr, const char *cmdline,unsigned raddr, unsigned rsize)
|
||||
{
|
||||
unsigned n = 0;
|
||||
unsigned *tags = (unsigned *)taddr;
|
||||
|
||||
//ATAG_CORE
|
||||
tags[n++] = 2;
|
||||
tags[n++] = 0x54410001;
|
||||
|
||||
if(rsize) {
|
||||
//ATAG_INITRD2
|
||||
tags[n++] = 4;
|
||||
tags[n++] = 0x54420005;
|
||||
tags[n++] = raddr;
|
||||
tags[n++] = rsize;
|
||||
}
|
||||
if(cmdline && cmdline[0]) {
|
||||
const char *src;
|
||||
char *dst;
|
||||
unsigned len = 0;
|
||||
|
||||
dst = (char*) (tags + n + 2);
|
||||
src = cmdline;
|
||||
while((*dst++ = *src++)) len++;
|
||||
|
||||
len++;
|
||||
len = (len + 3) & (~3);
|
||||
|
||||
// ATAG_CMDLINE
|
||||
tags[n++] = 2 + (len / 4);
|
||||
tags[n++] = 0x54410009;
|
||||
|
||||
n += (len / 4);
|
||||
}
|
||||
|
||||
// ATAG_NONE
|
||||
tags[n++] = 0;
|
||||
tags[n++] = 0;
|
||||
}
|
||||
|
||||
void boot_linux(unsigned kaddr, unsigned taddr)
|
||||
{
|
||||
void (*entry)(unsigned,unsigned,unsigned) = (void*) kaddr;
|
||||
|
||||
entry(0, machine_arch_type, taddr);
|
||||
}
|
|
@ -21,38 +21,58 @@
|
|||
# MA 02111-1307 USA
|
||||
#
|
||||
|
||||
CROSS_COMPILE ?= arm-linux-
|
||||
CROSS_COMPILE ?= arm-eabi-
|
||||
|
||||
ifndef CONFIG_STANDALONE_LOAD_ADDR
|
||||
ifeq ($(SOC),omap3)
|
||||
CONFIG_STANDALONE_LOAD_ADDR = 0x80300000
|
||||
else
|
||||
CONFIG_STANDALONE_LOAD_ADDR = 0xc100000
|
||||
CONFIG_STANDALONE_LOAD_ADDR = 0x80008000
|
||||
endif
|
||||
endif
|
||||
|
||||
PLATFORM_CPPFLAGS += -DCONFIG_ARM -D__ARM__
|
||||
|
||||
# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
|
||||
PF_CPPFLAGS_ARM := $(call cc-option,-marm,)
|
||||
# Choose between ARM/Thumb instruction sets
|
||||
ifeq ($(CONFIG_SYS_THUMB_BUILD),y)
|
||||
PF_CPPFLAGS_ARM := $(call cc-option, -mthumb -mthumb-interwork,\
|
||||
$(call cc-option,-marm,)\
|
||||
$(call cc-option,-mno-thumb-interwork,)\
|
||||
)
|
||||
else
|
||||
PF_CPPFLAGS_ARM := $(call cc-option,-marm,) \
|
||||
$(call cc-option,-mno-thumb-interwork,)
|
||||
endif
|
||||
|
||||
# Only test once
|
||||
ifneq ($(CONFIG_SPL_BUILD),y)
|
||||
ALL-$(CONFIG_SYS_THUMB_BUILD) += checkthumb
|
||||
endif
|
||||
ifeq ($(CONFIG_SPL_BUILD),y)
|
||||
ifeq ($(CONFIG_SPL_THUMB_BUILD),y)
|
||||
PF_CPPFLAGS_ARM := $(call cc-option, -mthumb -mthumb-interwork,\
|
||||
$(call cc-option,-marm,)\
|
||||
$(call cc-option,-mno-thumb-interwork,)\
|
||||
)
|
||||
endif
|
||||
endif
|
||||
# Try if EABI is supported, else fall back to old API,
|
||||
# i. e. for example:
|
||||
# - with ELDK 4.2 (EABI supported), use:
|
||||
# -mabi=aapcs-linux -mno-thumb-interwork
|
||||
# -mabi=aapcs-linux
|
||||
# - with ELDK 4.1 (gcc 4.x, no EABI), use:
|
||||
# -mabi=apcs-gnu -mno-thumb-interwork
|
||||
# -mabi=apcs-gnu
|
||||
# - with ELDK 3.1 (gcc 3.x), use:
|
||||
# -mapcs-32 -mno-thumb-interwork
|
||||
# -mapcs-32
|
||||
PF_CPPFLAGS_ABI := $(call cc-option,\
|
||||
-mabi=aapcs-linux -mno-thumb-interwork,\
|
||||
$(call cc-option,\
|
||||
-mapcs-32,\
|
||||
-mabi=aapcs-linux,\
|
||||
$(call cc-option,\
|
||||
-mabi=apcs-gnu,\
|
||||
)\
|
||||
) $(call cc-option,-mno-thumb-interwork,)\
|
||||
)
|
||||
-mapcs-32,\
|
||||
$(call cc-option,\
|
||||
-mabi=apcs-gnu,\
|
||||
)\
|
||||
)\
|
||||
)
|
||||
PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARM) $(PF_CPPFLAGS_ABI)
|
||||
|
||||
# For EABI, make sure to provide raise()
|
||||
|
|
|
@ -31,3 +31,9 @@ PLATFORM_CPPFLAGS += -march=armv5te
|
|||
# =========================================================================
|
||||
PF_RELFLAGS_SLB_AT := $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,))
|
||||
PLATFORM_RELFLAGS += $(PF_RELFLAGS_SLB_AT)
|
||||
|
||||
ifneq ($(CONFIG_IMX_CONFIG),)
|
||||
|
||||
ALL-y += $(obj)u-boot.imx
|
||||
|
||||
endif
|
||||
|
|
|
@ -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., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
LIB = $(obj)lib$(SOC).o
|
||||
|
||||
COBJS = cpu.o clk.o devices.o timer.o
|
||||
|
||||
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
|
||||
|
||||
all: $(obj).depend $(LIB)
|
||||
|
||||
$(LIB): $(OBJS)
|
||||
$(call cmd_link_o_target, $(OBJS))
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.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., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <div64.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/clk.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
|
||||
|
||||
unsigned int get_sys_clk_rate(void)
|
||||
{
|
||||
if (readl(&clk->sysclk_ctrl) & CLK_SYSCLK_PLL397)
|
||||
return RTC_CLK_FREQUENCY * 397;
|
||||
else
|
||||
return OSC_CLK_FREQUENCY;
|
||||
}
|
||||
|
||||
unsigned int get_hclk_pll_rate(void)
|
||||
{
|
||||
unsigned long long fin, fref, fcco, fout;
|
||||
u32 val, m_div, n_div, p_div;
|
||||
|
||||
/*
|
||||
* Valid frequency ranges:
|
||||
* 1 * 10^6 <= Fin <= 20 * 10^6
|
||||
* 1 * 10^6 <= Fref <= 27 * 10^6
|
||||
* 156 * 10^6 <= Fcco <= 320 * 10^6
|
||||
*/
|
||||
|
||||
fref = fin = get_sys_clk_rate();
|
||||
if (fin > 20000000ULL || fin < 1000000ULL)
|
||||
return 0;
|
||||
|
||||
val = readl(&clk->hclkpll_ctrl);
|
||||
m_div = ((val & CLK_HCLK_PLL_FEEDBACK_DIV_MASK) >> 1) + 1;
|
||||
n_div = ((val & CLK_HCLK_PLL_PREDIV_MASK) >> 9) + 1;
|
||||
if (val & CLK_HCLK_PLL_DIRECT)
|
||||
p_div = 0;
|
||||
else
|
||||
p_div = ((val & CLK_HCLK_PLL_POSTDIV_MASK) >> 11) + 1;
|
||||
p_div = 1 << p_div;
|
||||
|
||||
if (val & CLK_HCLK_PLL_BYPASS) {
|
||||
do_div(fin, p_div);
|
||||
return fin;
|
||||
}
|
||||
|
||||
do_div(fref, n_div);
|
||||
if (fref > 27000000ULL || fref < 1000000ULL)
|
||||
return 0;
|
||||
|
||||
fout = fref * m_div;
|
||||
if (val & CLK_HCLK_PLL_FEEDBACK) {
|
||||
fcco = fout;
|
||||
do_div(fout, p_div);
|
||||
} else
|
||||
fcco = fout * p_div;
|
||||
|
||||
if (fcco > 320000000ULL || fcco < 156000000ULL)
|
||||
return 0;
|
||||
|
||||
return fout;
|
||||
}
|
||||
|
||||
unsigned int get_hclk_clk_div(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK;
|
||||
|
||||
return 1 << val;
|
||||
}
|
||||
|
||||
unsigned int get_hclk_clk_rate(void)
|
||||
{
|
||||
return get_hclk_pll_rate() / get_hclk_clk_div();
|
||||
}
|
||||
|
||||
unsigned int get_periph_clk_div(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(&clk->hclkdiv_ctrl) & CLK_HCLK_PERIPH_DIV_MASK;
|
||||
|
||||
return (val >> 2) + 1;
|
||||
}
|
||||
|
||||
unsigned int get_periph_clk_rate(void)
|
||||
{
|
||||
if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN))
|
||||
return get_sys_clk_rate();
|
||||
|
||||
return get_hclk_pll_rate() / get_periph_clk_div();
|
||||
}
|
||||
|
||||
int get_serial_clock(void)
|
||||
{
|
||||
return get_periph_clk_rate();
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.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., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/clk.h>
|
||||
#include <asm/arch/wdt.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
|
||||
static struct wdt_regs *wdt = (struct wdt_regs *)WDT_BASE;
|
||||
|
||||
void reset_cpu(ulong addr)
|
||||
{
|
||||
/* Enable watchdog clock */
|
||||
setbits_le32(&clk->timclk_ctrl, CLK_TIMCLK_WATCHDOG);
|
||||
|
||||
/* Reset pulse length is 13005 peripheral clock frames */
|
||||
writel(13000, &wdt->pulse);
|
||||
|
||||
/* Force WDOG_RESET2 and RESOUT_N signal active */
|
||||
writel(WDTIM_MCTRL_RESFRC2 | WDTIM_MCTRL_RESFRC1 | WDTIM_MCTRL_M_RES2,
|
||||
&wdt->mctrl);
|
||||
|
||||
while (1)
|
||||
/* NOP */;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_CPU_INIT)
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
/*
|
||||
* It might be necessary to flush data cache, if U-boot is loaded
|
||||
* from kickstart bootloader, e.g. from S1L loader
|
||||
*/
|
||||
flush_dcache_all();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#error "You have to select CONFIG_ARCH_CPU_INIT"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DISPLAY_CPUINFO)
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
printf("CPU: NXP LPC32XX\n");
|
||||
printf("CPU clock: %uMHz\n", get_hclk_pll_rate() / 1000000);
|
||||
printf("AHB bus clock: %uMHz\n", get_hclk_clk_rate() / 1000000);
|
||||
printf("Peripheral clock: %uMHz\n", get_periph_clk_rate() / 1000000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.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., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/clk.h>
|
||||
#include <asm/arch/uart.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
|
||||
static struct uart_ctrl_regs *ctrl = (struct uart_ctrl_regs *)UART_CTRL_BASE;
|
||||
|
||||
void lpc32xx_uart_init(unsigned int uart_id)
|
||||
{
|
||||
if (uart_id < 1 || uart_id > 7)
|
||||
return;
|
||||
|
||||
/* Disable loopback mode, if it is set by S1L bootloader */
|
||||
clrbits_le32(&ctrl->loop,
|
||||
UART_LOOPBACK(CONFIG_SYS_LPC32XX_UART));
|
||||
|
||||
if (uart_id < 3 || uart_id > 6)
|
||||
return;
|
||||
|
||||
/* Enable UART system clock */
|
||||
setbits_le32(&clk->uartclk_ctrl, CLK_UART(uart_id));
|
||||
|
||||
/* Set UART into autoclock mode */
|
||||
clrsetbits_le32(&ctrl->clkmode,
|
||||
UART_CLKMODE_MASK(uart_id),
|
||||
UART_CLKMODE_AUTO(uart_id));
|
||||
|
||||
/* Bypass pre-divider of UART clock */
|
||||
writel(CLK_UART_X_DIV(1) | CLK_UART_Y_DIV(1),
|
||||
&clk->u3clk + (uart_id - 3));
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Vladimir Zapolskiy <vz@mleia.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., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/clk.h>
|
||||
#include <asm/arch/timer.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static struct timer_regs *timer0 = (struct timer_regs *)TIMER0_BASE;
|
||||
static struct timer_regs *timer1 = (struct timer_regs *)TIMER1_BASE;
|
||||
static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
|
||||
|
||||
static void lpc32xx_timer_clock(u32 bit, int enable)
|
||||
{
|
||||
if (enable)
|
||||
setbits_le32(&clk->timclk_ctrl1, bit);
|
||||
else
|
||||
clrbits_le32(&clk->timclk_ctrl1, bit);
|
||||
}
|
||||
|
||||
static void lpc32xx_timer_reset(struct timer_regs *timer, u32 freq)
|
||||
{
|
||||
writel(TIMER_TCR_COUNTER_RESET, &timer->tcr);
|
||||
writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr);
|
||||
writel(0, &timer->tc);
|
||||
writel(0, &timer->pr);
|
||||
|
||||
/* Count mode is every rising PCLK edge */
|
||||
writel(TIMER_CTCR_MODE_TIMER, &timer->ctcr);
|
||||
|
||||
/* Set prescale counter value */
|
||||
writel((get_periph_clk_rate() / freq) - 1, &timer->pr);
|
||||
}
|
||||
|
||||
static void lpc32xx_timer_count(struct timer_regs *timer, int enable)
|
||||
{
|
||||
if (enable)
|
||||
writel(TIMER_TCR_COUNTER_ENABLE, &timer->tcr);
|
||||
else
|
||||
writel(TIMER_TCR_COUNTER_DISABLE, &timer->tcr);
|
||||
}
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
lpc32xx_timer_clock(CLK_TIMCLK_TIMER0, 1);
|
||||
lpc32xx_timer_reset(timer0, CONFIG_SYS_HZ);
|
||||
lpc32xx_timer_count(timer0, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ulong get_timer(ulong base)
|
||||
{
|
||||
return readl(&timer0->tc) - base;
|
||||
}
|
||||
|
||||
void __udelay(unsigned long usec)
|
||||
{
|
||||
lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 1);
|
||||
lpc32xx_timer_reset(timer1, CONFIG_SYS_HZ * 1000);
|
||||
lpc32xx_timer_count(timer1, 1);
|
||||
|
||||
while (readl(&timer1->tc) < usec)
|
||||
/* NOP */;
|
||||
|
||||
lpc32xx_timer_count(timer1, 0);
|
||||
lpc32xx_timer_clock(CLK_TIMCLK_TIMER1, 0);
|
||||
}
|
||||
|
||||
unsigned long long get_ticks(void)
|
||||
{
|
||||
return get_timer(0);
|
||||
}
|
||||
|
||||
ulong get_tbclk(void)
|
||||
{
|
||||
return CONFIG_SYS_HZ;
|
||||
}
|
|
@ -28,10 +28,15 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
#include <asm/arch/imx25-pinmux.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#ifdef CONFIG_MXC_MMC
|
||||
#include <asm/arch/mxcmmc.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* get the system pll clock in Hz
|
||||
*
|
||||
|
@ -105,6 +110,20 @@ ulong imx_get_perclk(int clk)
|
|||
return lldiv(fref, div);
|
||||
}
|
||||
|
||||
unsigned int mxc_get_clock(enum mxc_clock clk)
|
||||
{
|
||||
if (clk >= MXC_CLK_NUM)
|
||||
return -1;
|
||||
switch (clk) {
|
||||
case MXC_ARM_CLK:
|
||||
return imx_get_armclk();
|
||||
case MXC_FEC_CLK:
|
||||
return imx_get_ahbclk();
|
||||
default:
|
||||
return imx_get_perclk(clk);
|
||||
}
|
||||
}
|
||||
|
||||
u32 get_cpu_rev(void)
|
||||
{
|
||||
u32 srev;
|
||||
|
@ -182,6 +201,14 @@ int cpu_eth_init(bd_t *bis)
|
|||
#endif
|
||||
}
|
||||
|
||||
int get_clocks(void)
|
||||
{
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
gd->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes on-chip MMC controllers.
|
||||
* to override, implement board_mmc_init()
|
||||
|
|
|
@ -28,7 +28,7 @@ LIB = $(obj)lib$(SOC).o
|
|||
COBJS = clock.o mx28.o iomux.o timer.o
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
COBJS += spl_boot.o spl_mem_init.o spl_power_init.o
|
||||
COBJS += spl_boot.o spl_lradc_init.o spl_mem_init.o spl_power_init.o
|
||||
endif
|
||||
|
||||
SRCS := $(START:.o=.S) $(COBJS:.o=.c)
|
||||
|
|
|
@ -51,9 +51,16 @@ void reset_cpu(ulong ignored) __attribute__((noreturn));
|
|||
|
||||
void reset_cpu(ulong ignored)
|
||||
{
|
||||
|
||||
struct mx28_rtc_regs *rtc_regs =
|
||||
(struct mx28_rtc_regs *)MXS_RTC_BASE;
|
||||
struct mx28_lcdif_regs *lcdif_regs =
|
||||
(struct mx28_lcdif_regs *)MXS_LCDIF_BASE;
|
||||
|
||||
/*
|
||||
* Shut down the LCD controller as it interferes with BootROM boot mode
|
||||
* pads sampling.
|
||||
*/
|
||||
writel(LCDIF_CTRL_RUN, &lcdif_regs->hw_lcdif_ctrl_clr);
|
||||
|
||||
/* Wait 1 uS before doing the actual watchdog reset */
|
||||
writel(1, &rtc_regs->hw_rtc_watchdog);
|
||||
|
@ -185,8 +192,12 @@ int arch_cpu_init(void)
|
|||
#if defined(CONFIG_DISPLAY_CPUINFO)
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
struct mx28_spl_data *data = (struct mx28_spl_data *)
|
||||
((CONFIG_SYS_TEXT_BASE - sizeof(struct mx28_spl_data)) & ~0xf);
|
||||
|
||||
printf("Freescale i.MX28 family at %d MHz\n",
|
||||
mxc_get_clock(MXC_ARM_CLK) / 1000000);
|
||||
printf("BOOT: %s\n", mx28_boot_modes[data->boot_mode_idx].mode);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -279,22 +290,16 @@ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
|
|||
|
||||
int mx28_dram_init(void)
|
||||
{
|
||||
struct mx28_digctl_regs *digctl_regs =
|
||||
(struct mx28_digctl_regs *)MXS_DIGCTL_BASE;
|
||||
uint32_t sz[2];
|
||||
struct mx28_spl_data *data = (struct mx28_spl_data *)
|
||||
((CONFIG_SYS_TEXT_BASE - sizeof(struct mx28_spl_data)) & ~0xf);
|
||||
|
||||
sz[0] = readl(&digctl_regs->hw_digctl_scratch0);
|
||||
sz[1] = readl(&digctl_regs->hw_digctl_scratch1);
|
||||
|
||||
if (sz[0] != sz[1]) {
|
||||
if (data->mem_dram_size == 0) {
|
||||
printf("MX28:\n"
|
||||
"Error, the RAM size in HW_DIGCTRL_SCRATCH0 and\n"
|
||||
"HW_DIGCTRL_SCRATCH1 is not the same. Please\n"
|
||||
"verify these two registers contain valid RAM size!\n");
|
||||
"Error, the RAM size passed up from SPL is 0!\n");
|
||||
hang();
|
||||
}
|
||||
|
||||
gd->ram_size = sz[0];
|
||||
gd->ram_size = data->mem_dram_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,5 +37,9 @@ static inline void mx28_power_wait_pswitch(void) { }
|
|||
#endif
|
||||
|
||||
void mx28_mem_init(void);
|
||||
uint32_t mx28_mem_get_size(void);
|
||||
|
||||
void mx28_lradc_init(void);
|
||||
void mx28_lradc_enable_batt_measurement(void);
|
||||
|
||||
#endif /* __M28_INIT_H__ */
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/arch/iomux-mx28.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
#include "mx28_init.h"
|
||||
|
||||
|
@ -46,12 +48,65 @@ void early_delay(int delay)
|
|||
;
|
||||
}
|
||||
|
||||
#define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
|
||||
const iomux_cfg_t iomux_boot[] = {
|
||||
MX28_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD,
|
||||
MX28_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD,
|
||||
MX28_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD,
|
||||
MX28_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD,
|
||||
MX28_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD,
|
||||
MX28_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD,
|
||||
};
|
||||
|
||||
uint8_t mx28_get_bootmode_index(void)
|
||||
{
|
||||
uint8_t bootmode = 0;
|
||||
int i;
|
||||
uint8_t masked;
|
||||
|
||||
/* Setup IOMUX of bootmode pads to GPIO */
|
||||
mxs_iomux_setup_multiple_pads(iomux_boot, ARRAY_SIZE(iomux_boot));
|
||||
|
||||
/* Setup bootmode pins as GPIO input */
|
||||
gpio_direction_input(MX28_PAD_LCD_D00__GPIO_1_0);
|
||||
gpio_direction_input(MX28_PAD_LCD_D01__GPIO_1_1);
|
||||
gpio_direction_input(MX28_PAD_LCD_D02__GPIO_1_2);
|
||||
gpio_direction_input(MX28_PAD_LCD_D03__GPIO_1_3);
|
||||
gpio_direction_input(MX28_PAD_LCD_D04__GPIO_1_4);
|
||||
gpio_direction_input(MX28_PAD_LCD_D05__GPIO_1_5);
|
||||
|
||||
/* Read bootmode pads */
|
||||
bootmode |= (gpio_get_value(MX28_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0;
|
||||
bootmode |= (gpio_get_value(MX28_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1;
|
||||
bootmode |= (gpio_get_value(MX28_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2;
|
||||
bootmode |= (gpio_get_value(MX28_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3;
|
||||
bootmode |= (gpio_get_value(MX28_PAD_LCD_D04__GPIO_1_4) ? 1 : 0) << 4;
|
||||
bootmode |= (gpio_get_value(MX28_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mx28_boot_modes); i++) {
|
||||
masked = bootmode & mx28_boot_modes[i].boot_mask;
|
||||
if (masked == mx28_boot_modes[i].boot_pads)
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void mx28_common_spl_init(const iomux_cfg_t *iomux_setup,
|
||||
const unsigned int iomux_size)
|
||||
{
|
||||
struct mx28_spl_data *data = (struct mx28_spl_data *)
|
||||
((CONFIG_SYS_TEXT_BASE - sizeof(struct mx28_spl_data)) & ~0xf);
|
||||
uint8_t bootmode = mx28_get_bootmode_index();
|
||||
|
||||
mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
|
||||
mx28_power_init();
|
||||
|
||||
mx28_mem_init();
|
||||
data->mem_dram_size = mx28_mem_get_size();
|
||||
|
||||
data->boot_mode_idx = bootmode;
|
||||
|
||||
mx28_power_wait_pswitch();
|
||||
}
|
||||
|
||||
|
@ -68,8 +123,10 @@ inline void board_init_r(gd_t *id, ulong dest_addr)
|
|||
;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPL_SERIAL_SUPPORT
|
||||
void serial_putc(const char c) {}
|
||||
void serial_puts(const char *s) {}
|
||||
#endif
|
||||
void hang(void) __attribute__ ((noreturn));
|
||||
void hang(void)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Freescale i.MX28 Battery measurement init
|
||||
*
|
||||
* Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
|
||||
* on behalf of DENX Software Engineering GmbH
|
||||
*
|
||||
* 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 <config.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
|
||||
#include "mx28_init.h"
|
||||
|
||||
void mx28_lradc_init(void)
|
||||
{
|
||||
struct mx28_lradc_regs *regs = (struct mx28_lradc_regs *)MXS_LRADC_BASE;
|
||||
|
||||
writel(LRADC_CTRL0_SFTRST, ®s->hw_lradc_ctrl0_clr);
|
||||
writel(LRADC_CTRL0_CLKGATE, ®s->hw_lradc_ctrl0_clr);
|
||||
writel(LRADC_CTRL0_ONCHIP_GROUNDREF, ®s->hw_lradc_ctrl0_clr);
|
||||
|
||||
clrsetbits_le32(®s->hw_lradc_ctrl3,
|
||||
LRADC_CTRL3_CYCLE_TIME_MASK,
|
||||
LRADC_CTRL3_CYCLE_TIME_6MHZ);
|
||||
|
||||
clrsetbits_le32(®s->hw_lradc_ctrl4,
|
||||
LRADC_CTRL4_LRADC7SELECT_MASK |
|
||||
LRADC_CTRL4_LRADC6SELECT_MASK,
|
||||
LRADC_CTRL4_LRADC7SELECT_CHANNEL7 |
|
||||
LRADC_CTRL4_LRADC6SELECT_CHANNEL10);
|
||||
}
|
||||
|
||||
void mx28_lradc_enable_batt_measurement(void)
|
||||
{
|
||||
struct mx28_lradc_regs *regs = (struct mx28_lradc_regs *)MXS_LRADC_BASE;
|
||||
|
||||
/* Check if the channel is present at all. */
|
||||
if (!(readl(®s->hw_lradc_status) & LRADC_STATUS_CHANNEL7_PRESENT))
|
||||
return;
|
||||
|
||||
writel(LRADC_CTRL1_LRADC7_IRQ_EN, ®s->hw_lradc_ctrl1_clr);
|
||||
writel(LRADC_CTRL1_LRADC7_IRQ, ®s->hw_lradc_ctrl1_clr);
|
||||
|
||||
clrsetbits_le32(®s->hw_lradc_conversion,
|
||||
LRADC_CONVERSION_SCALE_FACTOR_MASK,
|
||||
LRADC_CONVERSION_SCALE_FACTOR_LI_ION);
|
||||
writel(LRADC_CONVERSION_AUTOMATIC, ®s->hw_lradc_conversion_set);
|
||||
|
||||
/* Configure the channel. */
|
||||
writel((1 << 7) << LRADC_CTRL2_DIVIDE_BY_TWO_OFFSET,
|
||||
®s->hw_lradc_ctrl2_clr);
|
||||
writel(0xffffffff, ®s->hw_lradc_ch7_clr);
|
||||
clrbits_le32(®s->hw_lradc_ch7, LRADC_CH_NUM_SAMPLES_MASK);
|
||||
writel(LRADC_CH_ACCUMULATE, ®s->hw_lradc_ch7_clr);
|
||||
|
||||
/* Schedule the channel. */
|
||||
writel(1 << 7, ®s->hw_lradc_ctrl0_set);
|
||||
|
||||
/* Start the channel sampling. */
|
||||
writel(((1 << 7) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) |
|
||||
((1 << 3) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) |
|
||||
100, ®s->hw_lradc_delay3);
|
||||
|
||||
writel(0xffffffff, ®s->hw_lradc_ch7_clr);
|
||||
|
||||
writel(LRADC_DELAY_KICK, ®s->hw_lradc_delay3_set);
|
||||
}
|
|
@ -39,7 +39,7 @@ uint32_t dram_vals[] = {
|
|||
0x00000000, 0x00000100, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00010101, 0x01010101,
|
||||
0x000f0f01, 0x0f02010a, 0x00000000, 0x00010101,
|
||||
0x000f0f01, 0x0f02020a, 0x00000000, 0x00010101,
|
||||
0x00000100, 0x00000100, 0x00000000, 0x00000002,
|
||||
0x01010000, 0x05060302, 0x06005003, 0x0a0000c8,
|
||||
0x02009c40, 0x0000030c, 0x0036a609, 0x031a0612,
|
||||
|
@ -149,6 +149,8 @@ void mx28_mem_setup_cpu_and_hbus(void)
|
|||
/* Disable CPU bypass */
|
||||
writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
|
||||
&clkctrl_regs->hw_clkctrl_clkseq_clr);
|
||||
|
||||
early_delay(15000);
|
||||
}
|
||||
|
||||
void mx28_mem_setup_vdda(void)
|
||||
|
@ -173,10 +175,8 @@ void mx28_mem_setup_vddd(void)
|
|||
&power_regs->hw_power_vdddctrl);
|
||||
}
|
||||
|
||||
void mx28_mem_get_size(void)
|
||||
uint32_t mx28_mem_get_size(void)
|
||||
{
|
||||
struct mx28_digctl_regs *digctl_regs =
|
||||
(struct mx28_digctl_regs *)MXS_DIGCTL_BASE;
|
||||
uint32_t sz, da;
|
||||
uint32_t *vt = (uint32_t *)0x20;
|
||||
/* The following is "subs pc, r14, #4", used as return from DABT. */
|
||||
|
@ -187,11 +187,11 @@ void mx28_mem_get_size(void)
|
|||
vt[4] = data_abort_memdetect_handler;
|
||||
|
||||
sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
|
||||
writel(sz, &digctl_regs->hw_digctl_scratch0);
|
||||
writel(sz, &digctl_regs->hw_digctl_scratch1);
|
||||
|
||||
/* Restore the old DABT handler. */
|
||||
vt[4] = da;
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
void mx28_mem_init(void)
|
||||
|
@ -239,6 +239,4 @@ void mx28_mem_init(void)
|
|||
early_delay(10000);
|
||||
|
||||
mx28_mem_setup_cpu_and_hbus();
|
||||
|
||||
mx28_mem_get_size();
|
||||
}
|
||||
|
|
|
@ -45,11 +45,11 @@ void mx28_power_clock2pll(void)
|
|||
struct mx28_clkctrl_regs *clkctrl_regs =
|
||||
(struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE;
|
||||
|
||||
writel(CLKCTRL_PLL0CTRL0_POWER,
|
||||
&clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
|
||||
setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0,
|
||||
CLKCTRL_PLL0CTRL0_POWER);
|
||||
early_delay(100);
|
||||
writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
|
||||
&clkctrl_regs->hw_clkctrl_clkseq_clr);
|
||||
setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq,
|
||||
CLKCTRL_CLKSEQ_BYPASS_CPU);
|
||||
}
|
||||
|
||||
void mx28_power_clear_auto_restart(void)
|
||||
|
@ -104,6 +104,62 @@ void mx28_power_set_linreg(void)
|
|||
POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW);
|
||||
}
|
||||
|
||||
int mx28_get_batt_volt(void)
|
||||
{
|
||||
struct mx28_power_regs *power_regs =
|
||||
(struct mx28_power_regs *)MXS_POWER_BASE;
|
||||
uint32_t volt = readl(&power_regs->hw_power_battmonitor);
|
||||
volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
|
||||
volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
|
||||
volt *= 8;
|
||||
return volt;
|
||||
}
|
||||
|
||||
int mx28_is_batt_ready(void)
|
||||
{
|
||||
return (mx28_get_batt_volt() >= 3600);
|
||||
}
|
||||
|
||||
int mx28_is_batt_good(void)
|
||||
{
|
||||
struct mx28_power_regs *power_regs =
|
||||
(struct mx28_power_regs *)MXS_POWER_BASE;
|
||||
uint32_t volt = mx28_get_batt_volt();
|
||||
|
||||
if ((volt >= 2400) && (volt <= 4300))
|
||||
return 1;
|
||||
|
||||
clrsetbits_le32(&power_regs->hw_power_5vctrl,
|
||||
POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
|
||||
0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
|
||||
writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
|
||||
&power_regs->hw_power_5vctrl_clr);
|
||||
|
||||
clrsetbits_le32(&power_regs->hw_power_charge,
|
||||
POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
|
||||
POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
|
||||
|
||||
writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
|
||||
writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
|
||||
&power_regs->hw_power_5vctrl_clr);
|
||||
|
||||
early_delay(500000);
|
||||
|
||||
volt = mx28_get_batt_volt();
|
||||
|
||||
if (volt >= 3500)
|
||||
return 0;
|
||||
|
||||
if (volt >= 2400)
|
||||
return 1;
|
||||
|
||||
writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
|
||||
&power_regs->hw_power_charge_clr);
|
||||
writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mx28_power_setup_5v_detect(void)
|
||||
{
|
||||
struct mx28_power_regs *power_regs =
|
||||
|
@ -399,9 +455,14 @@ void mx28_power_enable_4p2(void)
|
|||
mx28_power_init_4p2_regulator();
|
||||
|
||||
/* Shutdown battery (none present) */
|
||||
clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK);
|
||||
writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr);
|
||||
writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
|
||||
if (!mx28_is_batt_ready()) {
|
||||
clrbits_le32(&power_regs->hw_power_dcdc4p2,
|
||||
POWER_DCDC4P2_BO_MASK);
|
||||
writel(POWER_CTRL_DCDC4P2_BO_IRQ,
|
||||
&power_regs->hw_power_ctrl_clr);
|
||||
writel(POWER_CTRL_ENIRQ_DCDC4P2_BO,
|
||||
&power_regs->hw_power_ctrl_clr);
|
||||
}
|
||||
|
||||
mx28_power_init_dcdc_4p2_source();
|
||||
|
||||
|
@ -459,6 +520,50 @@ void mx28_powerdown(void)
|
|||
&power_regs->hw_power_reset);
|
||||
}
|
||||
|
||||
void mx28_batt_boot(void)
|
||||
{
|
||||
struct mx28_power_regs *power_regs =
|
||||
(struct mx28_power_regs *)MXS_POWER_BASE;
|
||||
|
||||
clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT);
|
||||
clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_ENABLE_DCDC);
|
||||
|
||||
clrbits_le32(&power_regs->hw_power_dcdc4p2,
|
||||
POWER_DCDC4P2_ENABLE_DCDC | POWER_DCDC4P2_ENABLE_4P2);
|
||||
writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_clr);
|
||||
|
||||
/* 5V to battery handoff. */
|
||||
setbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
|
||||
early_delay(30);
|
||||
clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_DCDC_XFER);
|
||||
|
||||
writel(POWER_CTRL_ENIRQ_DCDC4P2_BO, &power_regs->hw_power_ctrl_clr);
|
||||
|
||||
clrsetbits_le32(&power_regs->hw_power_minpwr,
|
||||
POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS);
|
||||
|
||||
mx28_power_set_linreg();
|
||||
|
||||
clrbits_le32(&power_regs->hw_power_vdddctrl,
|
||||
POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG);
|
||||
|
||||
clrbits_le32(&power_regs->hw_power_vddactrl,
|
||||
POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG);
|
||||
|
||||
clrbits_le32(&power_regs->hw_power_vddioctrl,
|
||||
POWER_VDDIOCTRL_DISABLE_FET);
|
||||
|
||||
setbits_le32(&power_regs->hw_power_5vctrl,
|
||||
POWER_5VCTRL_PWD_CHARGE_4P2_MASK);
|
||||
|
||||
setbits_le32(&power_regs->hw_power_5vctrl,
|
||||
POWER_5VCTRL_ENABLE_DCDC);
|
||||
|
||||
clrsetbits_le32(&power_regs->hw_power_5vctrl,
|
||||
POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
|
||||
0x8 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
|
||||
}
|
||||
|
||||
void mx28_handle_5v_conflict(void)
|
||||
{
|
||||
struct mx28_power_regs *power_regs =
|
||||
|
@ -483,25 +588,14 @@ void mx28_handle_5v_conflict(void)
|
|||
mx28_powerdown();
|
||||
break;
|
||||
}
|
||||
|
||||
if (tmp & POWER_STS_PSWITCH_MASK) {
|
||||
mx28_batt_boot();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int mx28_get_batt_volt(void)
|
||||
{
|
||||
struct mx28_power_regs *power_regs =
|
||||
(struct mx28_power_regs *)MXS_POWER_BASE;
|
||||
uint32_t volt = readl(&power_regs->hw_power_battmonitor);
|
||||
volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
|
||||
volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
|
||||
volt *= 8;
|
||||
return volt;
|
||||
}
|
||||
|
||||
int mx28_is_batt_ready(void)
|
||||
{
|
||||
return (mx28_get_batt_volt() >= 3600);
|
||||
}
|
||||
|
||||
void mx28_5v_boot(void)
|
||||
{
|
||||
struct mx28_power_regs *power_regs =
|
||||
|
@ -553,62 +647,44 @@ void mx28_switch_vddd_to_dcdc_source(void)
|
|||
POWER_VDDDCTRL_DISABLE_STEPPING);
|
||||
}
|
||||
|
||||
int mx28_is_batt_good(void)
|
||||
{
|
||||
struct mx28_power_regs *power_regs =
|
||||
(struct mx28_power_regs *)MXS_POWER_BASE;
|
||||
uint32_t volt;
|
||||
|
||||
volt = readl(&power_regs->hw_power_battmonitor);
|
||||
volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
|
||||
volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
|
||||
volt *= 8;
|
||||
|
||||
if ((volt >= 2400) && (volt <= 4300))
|
||||
return 1;
|
||||
|
||||
clrsetbits_le32(&power_regs->hw_power_5vctrl,
|
||||
POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK,
|
||||
0x3 << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET);
|
||||
writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
|
||||
&power_regs->hw_power_5vctrl_clr);
|
||||
|
||||
clrsetbits_le32(&power_regs->hw_power_charge,
|
||||
POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
|
||||
POWER_CHARGE_STOP_ILIMIT_10MA | 0x3);
|
||||
|
||||
writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_clr);
|
||||
writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK,
|
||||
&power_regs->hw_power_5vctrl_clr);
|
||||
|
||||
early_delay(500000);
|
||||
|
||||
volt = readl(&power_regs->hw_power_battmonitor);
|
||||
volt &= POWER_BATTMONITOR_BATT_VAL_MASK;
|
||||
volt >>= POWER_BATTMONITOR_BATT_VAL_OFFSET;
|
||||
volt *= 8;
|
||||
|
||||
if (volt >= 3500)
|
||||
return 0;
|
||||
|
||||
if (volt >= 2400)
|
||||
return 1;
|
||||
|
||||
writel(POWER_CHARGE_STOP_ILIMIT_MASK | POWER_CHARGE_BATTCHRG_I_MASK,
|
||||
&power_regs->hw_power_charge_clr);
|
||||
writel(POWER_CHARGE_PWD_BATTCHRG, &power_regs->hw_power_charge_set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mx28_power_configure_power_source(void)
|
||||
{
|
||||
int batt_ready, batt_good;
|
||||
struct mx28_power_regs *power_regs =
|
||||
(struct mx28_power_regs *)MXS_POWER_BASE;
|
||||
struct mx28_lradc_regs *lradc_regs =
|
||||
(struct mx28_lradc_regs *)MXS_LRADC_BASE;
|
||||
|
||||
mx28_src_power_init();
|
||||
|
||||
mx28_5v_boot();
|
||||
batt_ready = mx28_is_batt_ready();
|
||||
|
||||
if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) {
|
||||
batt_good = mx28_is_batt_good();
|
||||
if (batt_ready) {
|
||||
/* 5V source detected, good battery detected. */
|
||||
mx28_batt_boot();
|
||||
} else {
|
||||
if (batt_good) {
|
||||
/* 5V source detected, low battery detceted. */
|
||||
} else {
|
||||
/* 5V source detected, bad battery detected. */
|
||||
writel(LRADC_CONVERSION_AUTOMATIC,
|
||||
&lradc_regs->hw_lradc_conversion_clr);
|
||||
clrbits_le32(&power_regs->hw_power_battmonitor,
|
||||
POWER_BATTMONITOR_BATT_VAL_MASK);
|
||||
}
|
||||
mx28_5v_boot();
|
||||
}
|
||||
} else {
|
||||
/* 5V not detected, booting from battery. */
|
||||
mx28_batt_boot();
|
||||
}
|
||||
|
||||
mx28_power_clock2pll();
|
||||
|
||||
mx28_init_batt_bo();
|
||||
|
||||
mx28_switch_vddd_to_dcdc_source();
|
||||
}
|
||||
|
||||
|
@ -883,6 +959,13 @@ void mx28_power_set_vddd(uint32_t new_target, uint32_t new_brownout)
|
|||
new_brownout << POWER_VDDDCTRL_BO_OFFSET_OFFSET);
|
||||
}
|
||||
|
||||
void mx28_setup_batt_detect(void)
|
||||
{
|
||||
mx28_lradc_init();
|
||||
mx28_lradc_enable_batt_measurement();
|
||||
early_delay(10);
|
||||
}
|
||||
|
||||
void mx28_power_init(void)
|
||||
{
|
||||
struct mx28_power_regs *power_regs =
|
||||
|
@ -892,6 +975,9 @@ void mx28_power_init(void)
|
|||
mx28_power_clear_auto_restart();
|
||||
mx28_power_set_linreg();
|
||||
mx28_power_setup_5v_detect();
|
||||
|
||||
mx28_setup_batt_detect();
|
||||
|
||||
mx28_power_configure_power_source();
|
||||
mx28_enable_output_rail_protection();
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
#
|
||||
# (C) Copyright 2000-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
|
||||
#
|
||||
# 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).o
|
||||
|
||||
COBJS-y += timer.o serial.o ifc.o cpu.o
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
COBJS-y += spl.o
|
||||
endif
|
||||
|
||||
SOBJS = reset.o
|
||||
|
||||
ifndef CONFIG_SKIP_LOWLEVEL_INIT
|
||||
SOBJS += lowlevel_init.o
|
||||
endif
|
||||
|
||||
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(COBJS-y) $(SOBJS))
|
||||
START := $(addprefix $(obj),$(START))
|
||||
|
||||
all: $(obj).depend $(LIB)
|
||||
|
||||
$(LIB): $(OBJS)
|
||||
$(call cmd_link_o_target, $(OBJS))
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
|
@ -0,0 +1,32 @@
|
|||
#
|
||||
# (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-common -ffixed-r8 -msoft-float
|
||||
|
||||
PLATFORM_CPPFLAGS += -march=armv5te
|
||||
# =========================================================================
|
||||
#
|
||||
# Supply options according to compiler version
|
||||
#
|
||||
# =========================================================================
|
||||
PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,))
|
|
@ -0,0 +1,12 @@
|
|||
#include <common.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
|
||||
void enable_caches(void)
|
||||
{
|
||||
#ifndef CONFIG_SYS_ICACHE_OFF
|
||||
icache_enable();
|
||||
#endif
|
||||
#ifndef CONFIG_SYS_DCACHE_OFF
|
||||
dcache_enable();
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
#include "common.h"
|
||||
#include <errno.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/reg_ifc.h>
|
||||
#include <asm/arch/ifc.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <assert.h>
|
||||
#else
|
||||
#define assert(...)
|
||||
#endif
|
||||
|
||||
#define HAL_TRACE(...)
|
||||
|
||||
HAL_IFC_REQUEST_ID_T g_halModuleIfcChannelOwner[SYS_IFC_STD_CHAN_NB];
|
||||
|
||||
void hal_IfcOpen(void)
|
||||
{
|
||||
u8 channel;
|
||||
|
||||
// Initialize the channel table with unknown requests.
|
||||
for (channel = 0; channel < SYS_IFC_STD_CHAN_NB; channel++)
|
||||
{
|
||||
g_halModuleIfcChannelOwner[channel] = HAL_IFC_NO_REQWEST;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_IFC_REQUEST_ID_T hal_IfcGetOwner(u8 channel)
|
||||
{
|
||||
// Here, we consider the transfer as previously finished.
|
||||
if (channel == HAL_UNKNOWN_CHANNEL) return HAL_IFC_NO_REQWEST;
|
||||
|
||||
// Channel number too big.
|
||||
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
|
||||
|
||||
return g_halModuleIfcChannelOwner[channel];
|
||||
}
|
||||
|
||||
void hal_IfcChannelRelease(HAL_IFC_REQUEST_ID_T requestId, u8 channel)
|
||||
{
|
||||
//u32 status;
|
||||
|
||||
// Here, we consider the transfer as previously finished.
|
||||
if (channel == HAL_UNKNOWN_CHANNEL) return;
|
||||
|
||||
// Channel number too big.
|
||||
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
|
||||
|
||||
//status = hal_SysEnterCriticalSection();
|
||||
if (g_halModuleIfcChannelOwner[channel] == requestId)
|
||||
{
|
||||
// disable this channel
|
||||
hwp_sysIfc->std_ch[channel].control = (SYS_IFC_REQ_SRC(requestId)
|
||||
| SYS_IFC_CH_RD_HW_EXCH
|
||||
| SYS_IFC_DISABLE);
|
||||
// read the status of this channel
|
||||
if (hwp_sysIfc->std_ch[channel].status & SYS_IFC_ENABLE)
|
||||
{
|
||||
HAL_TRACE(_HAL | TSTDOUT,0," Strange, the released channel not disabled yet");
|
||||
}
|
||||
// Write the TC to 0 for next time the channel is re-enabled
|
||||
hwp_sysIfc->std_ch[channel].tc = 0;
|
||||
}
|
||||
//hal_SysExitCriticalSection(status);
|
||||
}
|
||||
|
||||
void hal_IfcChannelFlush(HAL_IFC_REQUEST_ID_T requestId, u8 channel)
|
||||
{
|
||||
//u32 status;
|
||||
|
||||
// Here, we consider the transfer as previously finished.
|
||||
if (channel == HAL_UNKNOWN_CHANNEL) return;
|
||||
|
||||
// Channel number too big.
|
||||
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
|
||||
|
||||
// Check that the channel is really owned by the peripheral
|
||||
// which is doing the request, it could have been release
|
||||
// automatically or by an IRQ handler.
|
||||
//status = hal_SysEnterCriticalSection();
|
||||
if (g_halModuleIfcChannelOwner[channel] == requestId)
|
||||
{
|
||||
// If fifo not empty, flush it.
|
||||
if ( !(hwp_sysIfc->std_ch[channel].status & SYS_IFC_FIFO_EMPTY) )
|
||||
{
|
||||
hwp_sysIfc->std_ch[channel].control =
|
||||
hwp_sysIfc->std_ch[channel].control | SYS_IFC_FLUSH;
|
||||
}
|
||||
}
|
||||
//hal_SysExitCriticalSection(status);
|
||||
}
|
||||
|
||||
BOOL hal_IfcChannelIsFifoEmpty(HAL_IFC_REQUEST_ID_T requestId, u8 channel)
|
||||
{
|
||||
//u32 status;
|
||||
BOOL fifoIsEmpty = TRUE;
|
||||
|
||||
// Here, we consider the transfer as previously finished.
|
||||
if (channel == HAL_UNKNOWN_CHANNEL) return fifoIsEmpty;
|
||||
|
||||
// Channel number too big.
|
||||
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
|
||||
|
||||
// Check that the channel is really owned by the peripheral
|
||||
// which is doing the request, it could have been release
|
||||
// automatically or by an IRQ handler.
|
||||
//status = hal_SysEnterCriticalSection();
|
||||
if (g_halModuleIfcChannelOwner[channel] == requestId)
|
||||
{
|
||||
fifoIsEmpty =
|
||||
(FALSE != (hwp_sysIfc->std_ch[channel].status & SYS_IFC_FIFO_EMPTY));
|
||||
}
|
||||
//hal_SysExitCriticalSection(status);
|
||||
|
||||
return fifoIsEmpty;
|
||||
}
|
||||
|
||||
u8 hal_IfcTransferStart(HAL_IFC_REQUEST_ID_T requestId, u8* memStartAddr, u32 xferSize, HAL_IFC_MODE_T ifcMode)
|
||||
{
|
||||
//u32 status = hal_SysEnterCriticalSection();
|
||||
u8 channel;
|
||||
u8 i;
|
||||
|
||||
// Check buffer alignment depending on the mode
|
||||
if (ifcMode != HAL_IFC_SIZE_8_MODE_MANUAL && ifcMode != HAL_IFC_SIZE_8_MODE_AUTO)
|
||||
{
|
||||
// Then ifcMode == HAL_IFC_SIZE_32, check word alignment
|
||||
assert(((u32)memStartAddr%4) == 0,
|
||||
"HAL IFC: 32 bits transfer misaligned 0x@%08X", memStartAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ifcMode == HAL_IFC_SIZE_8, nothing to check
|
||||
}
|
||||
|
||||
// Check the requested id is not currently already used.
|
||||
for (i = 0; i < SYS_IFC_STD_CHAN_NB ; i++)
|
||||
{
|
||||
if (GET_BITFIELD(hwp_sysIfc->std_ch[i].control, SYS_IFC_REQ_SRC) == requestId)
|
||||
{
|
||||
// This channel is or was used for the requestId request.
|
||||
// Check it is still in use.
|
||||
assert((hwp_sysIfc->std_ch[i].status & SYS_IFC_ENABLE) == 0,
|
||||
"HAL: Attempt to use the IFC to deal with a %d"
|
||||
" request still active on channel %d", requestId, i);
|
||||
}
|
||||
}
|
||||
|
||||
channel = SYS_IFC_CH_TO_USE(hwp_sysIfc->get_ch) ;
|
||||
|
||||
if (channel >= SYS_IFC_STD_CHAN_NB)
|
||||
{
|
||||
serial_puts("HAL_UNKNOWN_CHANNEL\n");
|
||||
//hal_SysExitCriticalSection(status);
|
||||
return HAL_UNKNOWN_CHANNEL;
|
||||
}
|
||||
|
||||
g_halModuleIfcChannelOwner[channel] = requestId;
|
||||
hwp_sysIfc->std_ch[channel].start_addr = (u32) memStartAddr;
|
||||
hwp_sysIfc->std_ch[channel].tc = xferSize;
|
||||
hwp_sysIfc->std_ch[channel].control = (SYS_IFC_REQ_SRC(requestId)
|
||||
| ifcMode
|
||||
| SYS_IFC_CH_RD_HW_EXCH
|
||||
| SYS_IFC_ENABLE);
|
||||
|
||||
//hal_SysExitCriticalSection(status);
|
||||
return channel;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Processor reset using WDT for TI TMS320DM644x 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:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
reset_cpu_loop:
|
||||
b reset_cpu_loop
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/rda_iomap.h>
|
||||
#include <asm/arch/reg_sysctrl.h>
|
||||
#include <asm/arch/reg_uart.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void _serial_set_baudrate(int rate)
|
||||
{
|
||||
hwp_sysCtrlAp->Cfg_Clk_Uart[2] = 0x36; // 115200 @ 26MHz
|
||||
//hwp_sysCtrlAp->Cfg_Clk_Uart[2] = 0x05; // 921600 @ 26MHz
|
||||
}
|
||||
|
||||
void _serial_enable_rtscts(void)
|
||||
{
|
||||
hwp_uart->ctrl |= UART_AUTO_FLOW_CONTROL;
|
||||
}
|
||||
|
||||
void _serial_disable_rtscts(void)
|
||||
{
|
||||
hwp_uart->ctrl &= ~UART_AUTO_FLOW_CONTROL;
|
||||
}
|
||||
|
||||
void _serial_init(void)
|
||||
{
|
||||
_serial_set_baudrate(CONFIG_BAUDRATE);
|
||||
hwp_uart->triggers = UART_AFC_LEVEL(1); //7 ?
|
||||
|
||||
hwp_uart->ctrl = UART_ENABLE | UART_DATA_BITS_8_BITS |
|
||||
UART_TX_STOP_BITS_1_BIT | UART_PARITY_ENABLE_NO;
|
||||
|
||||
/* Allow reception */
|
||||
hwp_uart->CMD_Set = UART_RTS;
|
||||
}
|
||||
|
||||
void _serial_deinit(void)
|
||||
{
|
||||
hwp_uart->ctrl = 0;
|
||||
hwp_uart->CMD_Clr = UART_RTS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether a character is in the RX buffer
|
||||
*/
|
||||
int _serial_tstc(const int port)
|
||||
{
|
||||
return (GET_BITFIELD(hwp_uart->status, UART_RX_FIFO_LEVEL));
|
||||
}
|
||||
|
||||
int _serial_getc(const int port)
|
||||
{
|
||||
/* wait for character to arrive */ ;
|
||||
while (!(GET_BITFIELD(hwp_uart->status, UART_RX_FIFO_LEVEL)))
|
||||
;
|
||||
|
||||
return (hwp_uart->rxtx_buffer & 0xff);
|
||||
}
|
||||
|
||||
void _serial_putc_hw(const char c, const int port)
|
||||
{
|
||||
// Place in the TX Fifo ?
|
||||
while (!(GET_BITFIELD(hwp_uart->status, UART_TX_FIFO_SPACE)))
|
||||
;
|
||||
hwp_uart->rxtx_buffer = (u32)c;
|
||||
}
|
||||
|
||||
void _serial_putc(const char c, const int port)
|
||||
{
|
||||
if (c == '\n') {
|
||||
_serial_putc_hw('\r', 0);
|
||||
}
|
||||
_serial_putc_hw(c, 0);
|
||||
}
|
||||
|
||||
void _serial_puts(const char *s, const int port)
|
||||
{
|
||||
while (*s) {
|
||||
_serial_putc(*s++, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int hwflow = 0; /* turned off by default */
|
||||
int hwflow_onoff(int on)
|
||||
{
|
||||
switch(on) {
|
||||
case 0:
|
||||
default:
|
||||
break; /* return current */
|
||||
case 1:
|
||||
hwflow = 1;
|
||||
_serial_enable_rtscts(); /* turn on */
|
||||
break;
|
||||
case -1:
|
||||
hwflow = 0;
|
||||
_serial_disable_rtscts(); /* turn off */
|
||||
break;
|
||||
}
|
||||
return hwflow;
|
||||
}
|
||||
|
||||
int serial_init(void)
|
||||
{
|
||||
//_serial_init(); // already init in boot_test
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serial_getc(void)
|
||||
{
|
||||
return _serial_getc(0);
|
||||
}
|
||||
|
||||
int serial_tstc(void)
|
||||
{
|
||||
return _serial_tstc(0);
|
||||
}
|
||||
|
||||
void serial_putc(const char c)
|
||||
{
|
||||
_serial_putc(c, 0);
|
||||
}
|
||||
|
||||
void serial_puts(const char *s)
|
||||
{
|
||||
_serial_puts(s, 0);
|
||||
}
|
||||
|
||||
void serial_setbrg (void)
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
#include <common.h>
|
||||
#include <asm/u-boot.h>
|
||||
#include <asm/utils.h>
|
||||
#include <nand.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
/* Define global data structure pointer to it*/
|
||||
static gd_t gdata __attribute__ ((section(".data")));
|
||||
static bd_t bdata __attribute__ ((section(".data")));
|
||||
|
||||
#else
|
||||
|
||||
void puts(const char *str)
|
||||
{
|
||||
while (*str)
|
||||
putc(*str++);
|
||||
}
|
||||
|
||||
void putc(char c)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SPL_LIBCOMMON_SUPPORT */
|
||||
|
||||
inline void hang(void)
|
||||
{
|
||||
puts("### ERROR ### Please RESET the board ###\n");
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
relocate_code(CONFIG_SPL_STACK, NULL, CONFIG_SPL_TEXT_BASE);
|
||||
}
|
||||
|
||||
void board_init_r(gd_t *id, ulong dummy)
|
||||
{
|
||||
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
|
||||
gd = &gdata;
|
||||
gd->bd = &bdata;
|
||||
gd->flags |= GD_FLG_RELOC;
|
||||
gd->baudrate = CONFIG_BAUDRATE;
|
||||
serial_init(); /* serial communications setup */
|
||||
gd->have_console = 1;
|
||||
#endif
|
||||
puts("board_init_r\n");
|
||||
while(1)
|
||||
;
|
||||
#if 0
|
||||
#ifdef CONFIG_SPL_NAND_LOAD
|
||||
nand_init();
|
||||
puts("Nand boot...\n");
|
||||
nand_boot();
|
||||
#endif
|
||||
#ifdef CONFIG_SPL_SPI_LOAD
|
||||
mem_malloc_init(CONFIG_SYS_TEXT_BASE - CONFIG_SYS_MALLOC_LEN,
|
||||
CONFIG_SYS_MALLOC_LEN);
|
||||
|
||||
gd = &gdata;
|
||||
gd->bd = &bdata;
|
||||
gd->flags |= GD_FLG_RELOC;
|
||||
gd->baudrate = CONFIG_BAUDRATE;
|
||||
serial_init(); /* serial communications setup */
|
||||
gd->have_console = 1;
|
||||
|
||||
puts("SPI boot...\n");
|
||||
spi_boot();
|
||||
#endif
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/rda_iomap.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
typedef volatile struct
|
||||
{
|
||||
REG32 OSTimer_Ctrl; //0x00000000
|
||||
REG32 OSTimer_CurVal; //0x00000004
|
||||
REG32 WDTimer_Ctrl; //0x00000008
|
||||
REG32 WDTimer_LoadVal; //0x0000000C
|
||||
REG32 HWTimer_Ctrl; //0x00000010
|
||||
REG32 HWTimer_CurVal; //0x00000014
|
||||
REG32 Timer_Irq_Mask_Set; //0x00000018
|
||||
REG32 Timer_Irq_Mask_Clr; //0x0000001C
|
||||
REG32 Timer_Irq_Clr; //0x00000020
|
||||
REG32 Timer_Irq_Cause; //0x00000024
|
||||
} HWP_TIMER_T;
|
||||
|
||||
#define hwp_timer ((HWP_TIMER_T*)(RDA_TIMER_BASE))
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
gd->timer_rate_hz = CONFIG_SYS_HZ_CLOCK;
|
||||
gd->timer_reset_value = 0;
|
||||
|
||||
/* We are using timer34 in unchained 32-bit mode, full speed */
|
||||
return(0);
|
||||
}
|
||||
|
||||
void reset_timer(void)
|
||||
{
|
||||
gd->timer_reset_value = get_ticks();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current 64 bit timer tick count
|
||||
*/
|
||||
unsigned long long get_ticks(void)
|
||||
{
|
||||
unsigned long now = hwp_timer->HWTimer_CurVal;
|
||||
|
||||
/* increment tbu if tbl has rolled over */
|
||||
if (now < gd->tbl)
|
||||
gd->tbu++;
|
||||
gd->tbl = now;
|
||||
|
||||
return (((unsigned long long)gd->tbu) << 32) | gd->tbl;
|
||||
}
|
||||
|
||||
ulong get_timer(ulong base)
|
||||
{
|
||||
unsigned long long timer_diff;
|
||||
|
||||
timer_diff = get_ticks() - gd->timer_reset_value;
|
||||
|
||||
return (timer_diff / (gd->timer_rate_hz / CONFIG_SYS_HZ)) - base;
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("O0")
|
||||
|
||||
void __udelay(unsigned long usec)
|
||||
{
|
||||
#if 0 /* our timer is 16kHz, can NOT support udelay */
|
||||
unsigned long long endtime;
|
||||
|
||||
endtime = ((unsigned long long)usec * gd->timer_rate_hz) / 1000000UL;
|
||||
endtime += get_ticks();
|
||||
|
||||
while (get_ticks() < endtime)
|
||||
;
|
||||
#else /* use loop instead */
|
||||
#define USEC_LOOP (1)
|
||||
int i, j;
|
||||
for (i=0;i<(usec);i++)
|
||||
for (j=0;j<USEC_LOOP;j++)
|
||||
;
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
return CONFIG_SYS_HZ;
|
||||
}
|
|
@ -105,7 +105,7 @@ void init_timer(void)
|
|||
#if defined(CONFIG_OMAP_HSMMC) && !defined(CONFIG_SPL_BUILD)
|
||||
int board_mmc_init(bd_t *bis)
|
||||
{
|
||||
return omap_mmc_init(0);
|
||||
return omap_mmc_init(0, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -22,8 +22,11 @@
|
|||
#
|
||||
PLATFORM_RELFLAGS += -fno-common -ffixed-r8 -msoft-float
|
||||
|
||||
# Make ARMv5 to allow more compilers to work, even though its v7a.
|
||||
PLATFORM_CPPFLAGS += -march=armv5
|
||||
# If armv7-a is not supported by GCC fall-back to armv5, which is
|
||||
# supported by more tool-chains
|
||||
PF_CPPFLAGS_ARMV7 := $(call cc-option, -march=armv7-a, -march=armv5)
|
||||
PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARMV7)
|
||||
|
||||
# =========================================================================
|
||||
#
|
||||
# Supply options according to compiler version
|
||||
|
|
|
@ -22,7 +22,7 @@ include $(TOPDIR)/config.mk
|
|||
|
||||
LIB = $(obj)lib$(SOC).o
|
||||
|
||||
COBJS += clock.o soc.o
|
||||
COBJS += clock.o power.o soc.o system.o
|
||||
|
||||
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
|
||||
|
|
|
@ -414,6 +414,170 @@ static void exynos5_set_mmc_clk(int dev_index, unsigned int div)
|
|||
writel(val, addr);
|
||||
}
|
||||
|
||||
/* get_lcd_clk: return lcd clock frequency */
|
||||
static unsigned long exynos4_get_lcd_clk(void)
|
||||
{
|
||||
struct exynos4_clock *clk =
|
||||
(struct exynos4_clock *)samsung_get_base_clock();
|
||||
unsigned long pclk, sclk;
|
||||
unsigned int sel;
|
||||
unsigned int ratio;
|
||||
|
||||
/*
|
||||
* CLK_SRC_LCD0
|
||||
* FIMD0_SEL [3:0]
|
||||
*/
|
||||
sel = readl(&clk->src_lcd0);
|
||||
sel = sel & 0xf;
|
||||
|
||||
/*
|
||||
* 0x6: SCLK_MPLL
|
||||
* 0x7: SCLK_EPLL
|
||||
* 0x8: SCLK_VPLL
|
||||
*/
|
||||
if (sel == 0x6)
|
||||
sclk = get_pll_clk(MPLL);
|
||||
else if (sel == 0x7)
|
||||
sclk = get_pll_clk(EPLL);
|
||||
else if (sel == 0x8)
|
||||
sclk = get_pll_clk(VPLL);
|
||||
else
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* CLK_DIV_LCD0
|
||||
* FIMD0_RATIO [3:0]
|
||||
*/
|
||||
ratio = readl(&clk->div_lcd0);
|
||||
ratio = ratio & 0xf;
|
||||
|
||||
pclk = sclk / (ratio + 1);
|
||||
|
||||
return pclk;
|
||||
}
|
||||
|
||||
void exynos4_set_lcd_clk(void)
|
||||
{
|
||||
struct exynos4_clock *clk =
|
||||
(struct exynos4_clock *)samsung_get_base_clock();
|
||||
unsigned int cfg = 0;
|
||||
|
||||
/*
|
||||
* CLK_GATE_BLOCK
|
||||
* CLK_CAM [0]
|
||||
* CLK_TV [1]
|
||||
* CLK_MFC [2]
|
||||
* CLK_G3D [3]
|
||||
* CLK_LCD0 [4]
|
||||
* CLK_LCD1 [5]
|
||||
* CLK_GPS [7]
|
||||
*/
|
||||
cfg = readl(&clk->gate_block);
|
||||
cfg |= 1 << 4;
|
||||
writel(cfg, &clk->gate_block);
|
||||
|
||||
/*
|
||||
* CLK_SRC_LCD0
|
||||
* FIMD0_SEL [3:0]
|
||||
* MDNIE0_SEL [7:4]
|
||||
* MDNIE_PWM0_SEL [8:11]
|
||||
* MIPI0_SEL [12:15]
|
||||
* set lcd0 src clock 0x6: SCLK_MPLL
|
||||
*/
|
||||
cfg = readl(&clk->src_lcd0);
|
||||
cfg &= ~(0xf);
|
||||
cfg |= 0x6;
|
||||
writel(cfg, &clk->src_lcd0);
|
||||
|
||||
/*
|
||||
* CLK_GATE_IP_LCD0
|
||||
* CLK_FIMD0 [0]
|
||||
* CLK_MIE0 [1]
|
||||
* CLK_MDNIE0 [2]
|
||||
* CLK_DSIM0 [3]
|
||||
* CLK_SMMUFIMD0 [4]
|
||||
* CLK_PPMULCD0 [5]
|
||||
* Gating all clocks for FIMD0
|
||||
*/
|
||||
cfg = readl(&clk->gate_ip_lcd0);
|
||||
cfg |= 1 << 0;
|
||||
writel(cfg, &clk->gate_ip_lcd0);
|
||||
|
||||
/*
|
||||
* CLK_DIV_LCD0
|
||||
* FIMD0_RATIO [3:0]
|
||||
* MDNIE0_RATIO [7:4]
|
||||
* MDNIE_PWM0_RATIO [11:8]
|
||||
* MDNIE_PWM_PRE_RATIO [15:12]
|
||||
* MIPI0_RATIO [19:16]
|
||||
* MIPI0_PRE_RATIO [23:20]
|
||||
* set fimd ratio
|
||||
*/
|
||||
cfg &= ~(0xf);
|
||||
cfg |= 0x1;
|
||||
writel(cfg, &clk->div_lcd0);
|
||||
}
|
||||
|
||||
void exynos4_set_mipi_clk(void)
|
||||
{
|
||||
struct exynos4_clock *clk =
|
||||
(struct exynos4_clock *)samsung_get_base_clock();
|
||||
unsigned int cfg = 0;
|
||||
|
||||
/*
|
||||
* CLK_SRC_LCD0
|
||||
* FIMD0_SEL [3:0]
|
||||
* MDNIE0_SEL [7:4]
|
||||
* MDNIE_PWM0_SEL [8:11]
|
||||
* MIPI0_SEL [12:15]
|
||||
* set mipi0 src clock 0x6: SCLK_MPLL
|
||||
*/
|
||||
cfg = readl(&clk->src_lcd0);
|
||||
cfg &= ~(0xf << 12);
|
||||
cfg |= (0x6 << 12);
|
||||
writel(cfg, &clk->src_lcd0);
|
||||
|
||||
/*
|
||||
* CLK_SRC_MASK_LCD0
|
||||
* FIMD0_MASK [0]
|
||||
* MDNIE0_MASK [4]
|
||||
* MDNIE_PWM0_MASK [8]
|
||||
* MIPI0_MASK [12]
|
||||
* set src mask mipi0 0x1: Unmask
|
||||
*/
|
||||
cfg = readl(&clk->src_mask_lcd0);
|
||||
cfg |= (0x1 << 12);
|
||||
writel(cfg, &clk->src_mask_lcd0);
|
||||
|
||||
/*
|
||||
* CLK_GATE_IP_LCD0
|
||||
* CLK_FIMD0 [0]
|
||||
* CLK_MIE0 [1]
|
||||
* CLK_MDNIE0 [2]
|
||||
* CLK_DSIM0 [3]
|
||||
* CLK_SMMUFIMD0 [4]
|
||||
* CLK_PPMULCD0 [5]
|
||||
* Gating all clocks for MIPI0
|
||||
*/
|
||||
cfg = readl(&clk->gate_ip_lcd0);
|
||||
cfg |= 1 << 3;
|
||||
writel(cfg, &clk->gate_ip_lcd0);
|
||||
|
||||
/*
|
||||
* CLK_DIV_LCD0
|
||||
* FIMD0_RATIO [3:0]
|
||||
* MDNIE0_RATIO [7:4]
|
||||
* MDNIE_PWM0_RATIO [11:8]
|
||||
* MDNIE_PWM_PRE_RATIO [15:12]
|
||||
* MIPI0_RATIO [19:16]
|
||||
* MIPI0_PRE_RATIO [23:20]
|
||||
* set mipi ratio
|
||||
*/
|
||||
cfg &= ~(0xf << 16);
|
||||
cfg |= (0x1 << 16);
|
||||
writel(cfg, &clk->div_lcd0);
|
||||
}
|
||||
|
||||
unsigned long get_pll_clk(int pllreg)
|
||||
{
|
||||
if (cpu_is_exynos5())
|
||||
|
@ -453,3 +617,23 @@ void set_mmc_clk(int dev_index, unsigned int div)
|
|||
else
|
||||
exynos4_set_mmc_clk(dev_index, div);
|
||||
}
|
||||
|
||||
unsigned long get_lcd_clk(void)
|
||||
{
|
||||
if (cpu_is_exynos4())
|
||||
return exynos4_get_lcd_clk();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_lcd_clk(void)
|
||||
{
|
||||
if (cpu_is_exynos4())
|
||||
exynos4_set_lcd_clk();
|
||||
}
|
||||
|
||||
void set_mipi_clk(void)
|
||||
{
|
||||
if (cpu_is_exynos4())
|
||||
exynos4_set_mipi_clk();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Samsung Electronics
|
||||
* Donghwa Lee <dh09.lee@samsung.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/power.h>
|
||||
|
||||
static void exynos4_mipi_phy_control(unsigned int dev_index,
|
||||
unsigned int enable)
|
||||
{
|
||||
struct exynos4_power *pmu =
|
||||
(struct exynos4_power *)samsung_get_base_power();
|
||||
unsigned int addr, cfg = 0;
|
||||
|
||||
if (dev_index == 0)
|
||||
addr = (unsigned int)&pmu->mipi_phy0_control;
|
||||
else
|
||||
addr = (unsigned int)&pmu->mipi_phy1_control;
|
||||
|
||||
|
||||
cfg = readl(addr);
|
||||
if (enable)
|
||||
cfg |= (EXYNOS_MIPI_PHY_MRESETN | EXYNOS_MIPI_PHY_ENABLE);
|
||||
else
|
||||
cfg &= ~(EXYNOS_MIPI_PHY_MRESETN | EXYNOS_MIPI_PHY_ENABLE);
|
||||
|
||||
writel(cfg, addr);
|
||||
}
|
||||
|
||||
void set_mipi_phy_ctrl(unsigned int dev_index, unsigned int enable)
|
||||
{
|
||||
if (cpu_is_exynos4())
|
||||
exynos4_mipi_phy_control(dev_index, enable);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Samsung Electronics
|
||||
* Donghwa Lee <dh09.lee@samsung.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/system.h>
|
||||
|
||||
static void exynos4_set_system_display(void)
|
||||
{
|
||||
struct exynos4_sysreg *sysreg =
|
||||
(struct exynos4_sysreg *)samsung_get_base_sysreg();
|
||||
unsigned int cfg = 0;
|
||||
|
||||
/*
|
||||
* system register path set
|
||||
* 0: MIE/MDNIE
|
||||
* 1: FIMD Bypass
|
||||
*/
|
||||
cfg = readl(&sysreg->display_ctrl);
|
||||
cfg |= (1 << 1);
|
||||
writel(cfg, &sysreg->display_ctrl);
|
||||
}
|
||||
|
||||
void set_system_display_ctrl(void)
|
||||
{
|
||||
if (cpu_is_exynos4())
|
||||
exynos4_set_system_display();
|
||||
}
|
|
@ -29,12 +29,13 @@
|
|||
#include <asm/arch/imx-regs.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/arch/crm_regs.h>
|
||||
|
||||
#ifdef CONFIG_FSL_ESDHC
|
||||
#include <fsl_esdhc.h>
|
||||
#endif
|
||||
|
||||
static char *get_reset_cause(void)
|
||||
char *get_reset_cause(void)
|
||||
{
|
||||
u32 cause;
|
||||
struct src *src_regs = (struct src *)SRC_BASE_ADDR;
|
||||
|
@ -127,3 +128,15 @@ void reset_cpu(ulong addr)
|
|||
{
|
||||
__raw_writew(4, WDOG1_BASE_ADDR);
|
||||
}
|
||||
|
||||
u32 get_ahb_clk(void)
|
||||
{
|
||||
struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
|
||||
u32 reg, ahb_podf;
|
||||
|
||||
reg = __raw_readl(&imx_ccm->cbcdr);
|
||||
reg &= MXC_CCM_CBCDR_AHB_PODF_MASK;
|
||||
ahb_podf = reg >> MXC_CCM_CBCDR_AHB_PODF_OFFSET;
|
||||
|
||||
return get_periph_clk() / (ahb_podf + 1);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <asm/arch/crm_regs.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <div64.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
|
||||
enum pll_clocks {
|
||||
PLL1_CLOCK = 0,
|
||||
|
@ -48,6 +49,42 @@ struct mxc_pll_reg *mxc_plls[PLL_CLOCKS] = {
|
|||
#endif
|
||||
};
|
||||
|
||||
#define AHB_CLK_ROOT 133333333
|
||||
#define SZ_DEC_1M 1000000
|
||||
#define PLL_PD_MAX 16 /* Actual pd+1 */
|
||||
#define PLL_MFI_MAX 15
|
||||
#define PLL_MFI_MIN 5
|
||||
#define ARM_DIV_MAX 8
|
||||
#define IPG_DIV_MAX 4
|
||||
#define AHB_DIV_MAX 8
|
||||
#define EMI_DIV_MAX 8
|
||||
#define NFC_DIV_MAX 8
|
||||
|
||||
#define MX5_CBCMR 0x00015154
|
||||
#define MX5_CBCDR 0x02888945
|
||||
|
||||
struct fixed_pll_mfd {
|
||||
u32 ref_clk_hz;
|
||||
u32 mfd;
|
||||
};
|
||||
|
||||
const struct fixed_pll_mfd fixed_mfd[] = {
|
||||
{CONFIG_SYS_MX5_HCLK, 24 * 16},
|
||||
};
|
||||
|
||||
struct pll_param {
|
||||
u32 pd;
|
||||
u32 mfi;
|
||||
u32 mfn;
|
||||
u32 mfd;
|
||||
};
|
||||
|
||||
#define PLL_FREQ_MAX(ref_clk) (4 * (ref_clk) * PLL_MFI_MAX)
|
||||
#define PLL_FREQ_MIN(ref_clk) \
|
||||
((2 * (ref_clk) * (PLL_MFI_MIN - 1)) / PLL_PD_MAX)
|
||||
#define MAX_DDR_CLK 420000000
|
||||
#define NFC_CLK_MAX 34000000
|
||||
|
||||
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)MXC_CCM_BASE;
|
||||
|
||||
void set_usboh3_clk(void)
|
||||
|
@ -192,7 +229,7 @@ u32 get_mcu_main_clk(void)
|
|||
/*
|
||||
* Get the rate of peripheral's root clock.
|
||||
*/
|
||||
static u32 get_periph_clk(void)
|
||||
u32 get_periph_clk(void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
|
@ -212,22 +249,6 @@ static u32 get_periph_clk(void)
|
|||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the rate of ahb clock.
|
||||
*/
|
||||
static u32 get_ahb_clk(void)
|
||||
{
|
||||
uint32_t freq, div, reg;
|
||||
|
||||
freq = get_periph_clk();
|
||||
|
||||
reg = __raw_readl(&mxc_ccm->cbcdr);
|
||||
div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
|
||||
MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
|
||||
|
||||
return freq / div;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the rate of ipg clock.
|
||||
*/
|
||||
|
@ -306,7 +327,7 @@ static u32 get_uart_clk(void)
|
|||
/*
|
||||
* This function returns the low power audio clock.
|
||||
*/
|
||||
u32 get_lp_apm(void)
|
||||
static u32 get_lp_apm(void)
|
||||
{
|
||||
u32 ret_val = 0;
|
||||
u32 ccsr = __raw_readl(&mxc_ccm->ccsr);
|
||||
|
@ -322,7 +343,7 @@ u32 get_lp_apm(void)
|
|||
/*
|
||||
* get cspi clock rate.
|
||||
*/
|
||||
u32 imx_get_cspiclk(void)
|
||||
static u32 imx_get_cspiclk(void)
|
||||
{
|
||||
u32 ret_val = 0, pdf, pre_pdf, clk_sel;
|
||||
u32 cscmr1 = __raw_readl(&mxc_ccm->cscmr1);
|
||||
|
@ -359,8 +380,77 @@ u32 imx_get_cspiclk(void)
|
|||
return ret_val;
|
||||
}
|
||||
|
||||
static u32 get_axi_a_clk(void)
|
||||
{
|
||||
u32 cbcdr = __raw_readl(&mxc_ccm->cbcdr);
|
||||
u32 pdf = (cbcdr & MXC_CCM_CBCDR_AXI_A_PODF_MASK) \
|
||||
>> MXC_CCM_CBCDR_AXI_A_PODF_OFFSET;
|
||||
|
||||
return get_periph_clk() / (pdf + 1);
|
||||
}
|
||||
|
||||
static u32 get_axi_b_clk(void)
|
||||
{
|
||||
u32 cbcdr = __raw_readl(&mxc_ccm->cbcdr);
|
||||
u32 pdf = (cbcdr & MXC_CCM_CBCDR_AXI_B_PODF_MASK) \
|
||||
>> MXC_CCM_CBCDR_AXI_B_PODF_OFFSET;
|
||||
|
||||
return get_periph_clk() / (pdf + 1);
|
||||
}
|
||||
|
||||
static u32 get_emi_slow_clk(void)
|
||||
{
|
||||
u32 cbcdr = __raw_readl(&mxc_ccm->cbcdr);
|
||||
u32 emi_clk_sel = cbcdr & MXC_CCM_CBCDR_EMI_CLK_SEL;
|
||||
u32 pdf = (cbcdr & MXC_CCM_CBCDR_EMI_PODF_MASK) \
|
||||
>> MXC_CCM_CBCDR_EMI_PODF_OFFSET;
|
||||
|
||||
if (emi_clk_sel)
|
||||
return get_ahb_clk() / (pdf + 1);
|
||||
|
||||
return get_periph_clk() / (pdf + 1);
|
||||
}
|
||||
|
||||
static u32 get_ddr_clk(void)
|
||||
{
|
||||
u32 ret_val = 0;
|
||||
u32 cbcmr = __raw_readl(&mxc_ccm->cbcmr);
|
||||
u32 ddr_clk_sel = (cbcmr & MXC_CCM_CBCMR_DDR_CLK_SEL_MASK) \
|
||||
>> MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET;
|
||||
#ifdef CONFIG_MX51
|
||||
u32 cbcdr = __raw_readl(&mxc_ccm->cbcdr);
|
||||
if (cbcdr & MXC_CCM_CBCDR_DDR_HIFREQ_SEL) {
|
||||
u32 ddr_clk_podf = (cbcdr & MXC_CCM_CBCDR_DDR_PODF_MASK) >> \
|
||||
MXC_CCM_CBCDR_DDR_PODF_OFFSET;
|
||||
|
||||
ret_val = decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_SYS_MX5_HCLK);
|
||||
ret_val /= ddr_clk_podf + 1;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
#endif
|
||||
switch (ddr_clk_sel) {
|
||||
case 0:
|
||||
ret_val = get_axi_a_clk();
|
||||
break;
|
||||
case 1:
|
||||
ret_val = get_axi_b_clk();
|
||||
break;
|
||||
case 2:
|
||||
ret_val = get_emi_slow_clk();
|
||||
break;
|
||||
case 3:
|
||||
ret_val = get_ahb_clk();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* The API of get mxc clockes.
|
||||
* The API of get mxc clocks.
|
||||
*/
|
||||
unsigned int mxc_get_clock(enum mxc_clock clk)
|
||||
{
|
||||
|
@ -380,10 +470,14 @@ unsigned int mxc_get_clock(enum mxc_clock clk)
|
|||
case MXC_FEC_CLK:
|
||||
return decode_pll(mxc_plls[PLL1_CLOCK],
|
||||
CONFIG_SYS_MX5_HCLK);
|
||||
case MXC_SATA_CLK:
|
||||
return get_ahb_clk();
|
||||
case MXC_DDR_CLK:
|
||||
return get_ddr_clk();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
u32 imx_get_uartclk(void)
|
||||
|
@ -397,6 +491,362 @@ u32 imx_get_fecclk(void)
|
|||
return mxc_get_clock(MXC_IPG_CLK);
|
||||
}
|
||||
|
||||
static int gcd(int m, int n)
|
||||
{
|
||||
int t;
|
||||
while (m > 0) {
|
||||
if (n > m) {
|
||||
t = m;
|
||||
m = n;
|
||||
n = t;
|
||||
} /* swap */
|
||||
m -= n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is to calculate various parameters based on reference clock and
|
||||
* targeted clock based on the equation:
|
||||
* t_clk = 2*ref_freq*(mfi + mfn/(mfd+1))/(pd+1)
|
||||
* This calculation is based on a fixed MFD value for simplicity.
|
||||
*/
|
||||
static int calc_pll_params(u32 ref, u32 target, struct pll_param *pll)
|
||||
{
|
||||
u64 pd, mfi = 1, mfn, mfd, t1;
|
||||
u32 n_target = target;
|
||||
u32 n_ref = ref, i;
|
||||
|
||||
/*
|
||||
* Make sure targeted freq is in the valid range.
|
||||
* Otherwise the following calculation might be wrong!!!
|
||||
*/
|
||||
if (n_target < PLL_FREQ_MIN(ref) ||
|
||||
n_target > PLL_FREQ_MAX(ref)) {
|
||||
printf("Targeted peripheral clock should be"
|
||||
"within [%d - %d]\n",
|
||||
PLL_FREQ_MIN(ref) / SZ_DEC_1M,
|
||||
PLL_FREQ_MAX(ref) / SZ_DEC_1M);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fixed_mfd); i++) {
|
||||
if (fixed_mfd[i].ref_clk_hz == ref) {
|
||||
mfd = fixed_mfd[i].mfd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(fixed_mfd))
|
||||
return -EINVAL;
|
||||
|
||||
/* Use n_target and n_ref to avoid overflow */
|
||||
for (pd = 1; pd <= PLL_PD_MAX; pd++) {
|
||||
t1 = n_target * pd;
|
||||
do_div(t1, (4 * n_ref));
|
||||
mfi = t1;
|
||||
if (mfi > PLL_MFI_MAX)
|
||||
return -EINVAL;
|
||||
else if (mfi < 5)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Now got pd and mfi already
|
||||
*
|
||||
* mfn = (((n_target * pd) / 4 - n_ref * mfi) * mfd) / n_ref;
|
||||
*/
|
||||
t1 = n_target * pd;
|
||||
do_div(t1, 4);
|
||||
t1 -= n_ref * mfi;
|
||||
t1 *= mfd;
|
||||
do_div(t1, n_ref);
|
||||
mfn = t1;
|
||||
debug("ref=%d, target=%d, pd=%d," "mfi=%d,mfn=%d, mfd=%d\n",
|
||||
ref, n_target, (u32)pd, (u32)mfi, (u32)mfn, (u32)mfd);
|
||||
i = 1;
|
||||
if (mfn != 0)
|
||||
i = gcd(mfd, mfn);
|
||||
pll->pd = (u32)pd;
|
||||
pll->mfi = (u32)mfi;
|
||||
do_div(mfn, i);
|
||||
pll->mfn = (u32)mfn;
|
||||
do_div(mfd, i);
|
||||
pll->mfd = (u32)mfd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define calc_div(tgt_clk, src_clk, limit) ({ \
|
||||
u32 v = 0; \
|
||||
if (((src_clk) % (tgt_clk)) <= 100) \
|
||||
v = (src_clk) / (tgt_clk); \
|
||||
else \
|
||||
v = ((src_clk) / (tgt_clk)) + 1;\
|
||||
if (v > limit) \
|
||||
v = limit; \
|
||||
(v - 1); \
|
||||
})
|
||||
|
||||
#define CHANGE_PLL_SETTINGS(pll, pd, fi, fn, fd) \
|
||||
{ \
|
||||
__raw_writel(0x1232, &pll->ctrl); \
|
||||
__raw_writel(0x2, &pll->config); \
|
||||
__raw_writel((((pd) - 1) << 0) | ((fi) << 4), \
|
||||
&pll->op); \
|
||||
__raw_writel(fn, &(pll->mfn)); \
|
||||
__raw_writel((fd) - 1, &pll->mfd); \
|
||||
__raw_writel((((pd) - 1) << 0) | ((fi) << 4), \
|
||||
&pll->hfs_op); \
|
||||
__raw_writel(fn, &pll->hfs_mfn); \
|
||||
__raw_writel((fd) - 1, &pll->hfs_mfd); \
|
||||
__raw_writel(0x1232, &pll->ctrl); \
|
||||
while (!__raw_readl(&pll->ctrl) & 0x1) \
|
||||
;\
|
||||
}
|
||||
|
||||
static int config_pll_clk(enum pll_clocks index, struct pll_param *pll_param)
|
||||
{
|
||||
u32 ccsr = __raw_readl(&mxc_ccm->ccsr);
|
||||
struct mxc_pll_reg *pll = mxc_plls[index];
|
||||
|
||||
switch (index) {
|
||||
case PLL1_CLOCK:
|
||||
/* Switch ARM to PLL2 clock */
|
||||
__raw_writel(ccsr | 0x4, &mxc_ccm->ccsr);
|
||||
CHANGE_PLL_SETTINGS(pll, pll_param->pd,
|
||||
pll_param->mfi, pll_param->mfn,
|
||||
pll_param->mfd);
|
||||
/* Switch back */
|
||||
__raw_writel(ccsr & ~0x4, &mxc_ccm->ccsr);
|
||||
break;
|
||||
case PLL2_CLOCK:
|
||||
/* Switch to pll2 bypass clock */
|
||||
__raw_writel(ccsr | 0x2, &mxc_ccm->ccsr);
|
||||
CHANGE_PLL_SETTINGS(pll, pll_param->pd,
|
||||
pll_param->mfi, pll_param->mfn,
|
||||
pll_param->mfd);
|
||||
/* Switch back */
|
||||
__raw_writel(ccsr & ~0x2, &mxc_ccm->ccsr);
|
||||
break;
|
||||
case PLL3_CLOCK:
|
||||
/* Switch to pll3 bypass clock */
|
||||
__raw_writel(ccsr | 0x1, &mxc_ccm->ccsr);
|
||||
CHANGE_PLL_SETTINGS(pll, pll_param->pd,
|
||||
pll_param->mfi, pll_param->mfn,
|
||||
pll_param->mfd);
|
||||
/* Switch back */
|
||||
__raw_writel(ccsr & ~0x1, &mxc_ccm->ccsr);
|
||||
break;
|
||||
case PLL4_CLOCK:
|
||||
/* Switch to pll4 bypass clock */
|
||||
__raw_writel(ccsr | 0x20, &mxc_ccm->ccsr);
|
||||
CHANGE_PLL_SETTINGS(pll, pll_param->pd,
|
||||
pll_param->mfi, pll_param->mfn,
|
||||
pll_param->mfd);
|
||||
/* Switch back */
|
||||
__raw_writel(ccsr & ~0x20, &mxc_ccm->ccsr);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Config CPU clock */
|
||||
static int config_core_clk(u32 ref, u32 freq)
|
||||
{
|
||||
int ret = 0;
|
||||
struct pll_param pll_param;
|
||||
|
||||
memset(&pll_param, 0, sizeof(struct pll_param));
|
||||
|
||||
/* The case that periph uses PLL1 is not considered here */
|
||||
ret = calc_pll_params(ref, freq, &pll_param);
|
||||
if (ret != 0) {
|
||||
printf("Error:Can't find pll parameters: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return config_pll_clk(PLL1_CLOCK, &pll_param);
|
||||
}
|
||||
|
||||
static int config_nfc_clk(u32 nfc_clk)
|
||||
{
|
||||
u32 reg;
|
||||
u32 parent_rate = get_emi_slow_clk();
|
||||
u32 div = parent_rate / nfc_clk;
|
||||
|
||||
if (nfc_clk <= 0)
|
||||
return -EINVAL;
|
||||
if (div == 0)
|
||||
div++;
|
||||
if (parent_rate / div > NFC_CLK_MAX)
|
||||
div++;
|
||||
reg = __raw_readl(&mxc_ccm->cbcdr);
|
||||
reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
|
||||
reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
|
||||
__raw_writel(reg, &mxc_ccm->cbcdr);
|
||||
while (__raw_readl(&mxc_ccm->cdhipr) != 0)
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Config main_bus_clock for periphs */
|
||||
static int config_periph_clk(u32 ref, u32 freq)
|
||||
{
|
||||
int ret = 0;
|
||||
struct pll_param pll_param;
|
||||
|
||||
memset(&pll_param, 0, sizeof(struct pll_param));
|
||||
|
||||
if (__raw_readl(&mxc_ccm->cbcdr) & MXC_CCM_CBCDR_PERIPH_CLK_SEL) {
|
||||
ret = calc_pll_params(ref, freq, &pll_param);
|
||||
if (ret != 0) {
|
||||
printf("Error:Can't find pll parameters: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
switch ((__raw_readl(&mxc_ccm->cbcmr) & \
|
||||
MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK) >> \
|
||||
MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET) {
|
||||
case 0:
|
||||
return config_pll_clk(PLL1_CLOCK, &pll_param);
|
||||
break;
|
||||
case 1:
|
||||
return config_pll_clk(PLL3_CLOCK, &pll_param);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_ddr_clk(u32 emi_clk)
|
||||
{
|
||||
u32 clk_src;
|
||||
s32 shift = 0, clk_sel, div = 1;
|
||||
u32 cbcmr = __raw_readl(&mxc_ccm->cbcmr);
|
||||
u32 cbcdr = __raw_readl(&mxc_ccm->cbcdr);
|
||||
|
||||
if (emi_clk > MAX_DDR_CLK) {
|
||||
printf("Warning:DDR clock should not exceed %d MHz\n",
|
||||
MAX_DDR_CLK / SZ_DEC_1M);
|
||||
emi_clk = MAX_DDR_CLK;
|
||||
}
|
||||
|
||||
clk_src = get_periph_clk();
|
||||
/* Find DDR clock input */
|
||||
clk_sel = (cbcmr >> 10) & 0x3;
|
||||
switch (clk_sel) {
|
||||
case 0:
|
||||
shift = 16;
|
||||
break;
|
||||
case 1:
|
||||
shift = 19;
|
||||
break;
|
||||
case 2:
|
||||
shift = 22;
|
||||
break;
|
||||
case 3:
|
||||
shift = 10;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((clk_src % emi_clk) < 10000000)
|
||||
div = clk_src / emi_clk;
|
||||
else
|
||||
div = (clk_src / emi_clk) + 1;
|
||||
if (div > 8)
|
||||
div = 8;
|
||||
|
||||
cbcdr = cbcdr & ~(0x7 << shift);
|
||||
cbcdr |= ((div - 1) << shift);
|
||||
__raw_writel(cbcdr, &mxc_ccm->cbcdr);
|
||||
while (__raw_readl(&mxc_ccm->cdhipr) != 0)
|
||||
;
|
||||
__raw_writel(0x0, &mxc_ccm->ccdr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function assumes the expected core clock has to be changed by
|
||||
* modifying the PLL. This is NOT true always but for most of the times,
|
||||
* it is. So it assumes the PLL output freq is the same as the expected
|
||||
* core clock (presc=1) unless the core clock is less than PLL_FREQ_MIN.
|
||||
* In the latter case, it will try to increase the presc value until
|
||||
* (presc*core_clk) is greater than PLL_FREQ_MIN. It then makes call to
|
||||
* calc_pll_params() and obtains the values of PD, MFI,MFN, MFD based
|
||||
* on the targeted PLL and reference input clock to the PLL. Lastly,
|
||||
* it sets the register based on these values along with the dividers.
|
||||
* Note 1) There is no value checking for the passed-in divider values
|
||||
* so the caller has to make sure those values are sensible.
|
||||
* 2) Also adjust the NFC divider such that the NFC clock doesn't
|
||||
* exceed NFC_CLK_MAX.
|
||||
* 3) IPU HSP clock is independent of AHB clock. Even it can go up to
|
||||
* 177MHz for higher voltage, this function fixes the max to 133MHz.
|
||||
* 4) This function should not have allowed diag_printf() calls since
|
||||
* the serial driver has been stoped. But leave then here to allow
|
||||
* easy debugging by NOT calling the cyg_hal_plf_serial_stop().
|
||||
*/
|
||||
int mxc_set_clock(u32 ref, u32 freq, enum mxc_clock clk)
|
||||
{
|
||||
freq *= SZ_DEC_1M;
|
||||
|
||||
switch (clk) {
|
||||
case MXC_ARM_CLK:
|
||||
if (config_core_clk(ref, freq))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case MXC_PERIPH_CLK:
|
||||
if (config_periph_clk(ref, freq))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case MXC_DDR_CLK:
|
||||
if (config_ddr_clk(freq))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case MXC_NFC_CLK:
|
||||
if (config_nfc_clk(freq))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
printf("Warning:Unsupported or invalid clock type\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MX53
|
||||
/*
|
||||
* The clock for the external interface can be set to use internal clock
|
||||
* if fuse bank 4, row 3, bit 2 is set.
|
||||
* This is an undocumented feature and it was confirmed by Freescale's support:
|
||||
* Fuses (but not pins) may be used to configure SATA clocks.
|
||||
* Particularly the i.MX53 Fuse_Map contains the next information
|
||||
* about configuring SATA clocks : SATA_ALT_REF_CLK[1:0] (offset 0x180C)
|
||||
* '00' - 100MHz (External)
|
||||
* '01' - 50MHz (External)
|
||||
* '10' - 120MHz, internal (USB PHY)
|
||||
* '11' - Reserved
|
||||
*/
|
||||
void mxc_set_sata_internal_clock(void)
|
||||
{
|
||||
u32 *tmp_base =
|
||||
(u32 *)(IIM_BASE_ADDR + 0x180c);
|
||||
|
||||
set_usb_phy1_clk();
|
||||
|
||||
writel((readl(tmp_base) & (~0x7)) | 0x4, tmp_base);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dump some core clockes.
|
||||
*/
|
||||
|
@ -419,6 +869,7 @@ int do_mx5_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||
printf("AHB %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000);
|
||||
printf("IPG %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000);
|
||||
printf("IPG PERCLK %8d kHz\n", mxc_get_clock(MXC_IPG_PERCLK) / 1000);
|
||||
printf("DDR %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <config.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
#include <generated/asm-offsets.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
/*
|
||||
* L2CC Cache setup/invalidation/disable
|
||||
|
@ -326,8 +327,7 @@
|
|||
|
||||
.section ".text.init", "x"
|
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
ENTRY(lowlevel_init)
|
||||
#if defined(CONFIG_MX51)
|
||||
ldr r0, =GPIO1_BASE_ADDR
|
||||
ldr r1, [r0, #0x0]
|
||||
|
@ -348,6 +348,7 @@ lowlevel_init:
|
|||
|
||||
/* r12 saved upper lr*/
|
||||
mov pc,lr
|
||||
ENDPROC(lowlevel_init)
|
||||
|
||||
/* Board level setting value */
|
||||
W_DP_OP_864: .word DP_OP_864
|
||||
|
|
|
@ -24,8 +24,9 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
#include <asm/arch/ccm_regs.h>
|
||||
#include <asm/arch/crm_regs.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
|
||||
enum pll_clocks {
|
||||
PLL_SYS, /* System PLL */
|
||||
|
@ -34,7 +35,7 @@ enum pll_clocks {
|
|||
PLL_ENET, /* ENET PLL */
|
||||
};
|
||||
|
||||
struct imx_ccm_reg *imx_ccm = (struct imx_ccm_reg *)CCM_BASE_ADDR;
|
||||
struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
|
||||
|
||||
void enable_usboh3_clk(unsigned char enable)
|
||||
{
|
||||
|
@ -92,7 +93,7 @@ static u32 get_mcu_main_clk(void)
|
|||
return freq / (reg + 1);
|
||||
}
|
||||
|
||||
static u32 get_periph_clk(void)
|
||||
u32 get_periph_clk(void)
|
||||
{
|
||||
u32 reg, freq = 0;
|
||||
|
||||
|
@ -139,18 +140,6 @@ static u32 get_periph_clk(void)
|
|||
return freq;
|
||||
}
|
||||
|
||||
|
||||
static u32 get_ahb_clk(void)
|
||||
{
|
||||
u32 reg, ahb_podf;
|
||||
|
||||
reg = __raw_readl(&imx_ccm->cbcdr);
|
||||
reg &= MXC_CCM_CBCDR_AHB_PODF_MASK;
|
||||
ahb_podf = reg >> MXC_CCM_CBCDR_AHB_PODF_OFFSET;
|
||||
|
||||
return get_periph_clk() / (ahb_podf + 1);
|
||||
}
|
||||
|
||||
static u32 get_ipg_clk(void)
|
||||
{
|
||||
u32 reg, ipg_podf;
|
||||
|
@ -303,6 +292,37 @@ u32 imx_get_fecclk(void)
|
|||
return decode_pll(PLL_ENET, CONFIG_SYS_MX6_HCLK);
|
||||
}
|
||||
|
||||
int enable_sata_clock(void)
|
||||
{
|
||||
u32 reg = 0;
|
||||
s32 timeout = 100000;
|
||||
struct mxc_ccm_reg *const imx_ccm
|
||||
= (struct mxc_ccm_reg *) CCM_BASE_ADDR;
|
||||
|
||||
/* Enable sata clock */
|
||||
reg = readl(&imx_ccm->CCGR5); /* CCGR5 */
|
||||
reg |= MXC_CCM_CCGR5_CG2_MASK;
|
||||
writel(reg, &imx_ccm->CCGR5);
|
||||
|
||||
/* Enable PLLs */
|
||||
reg = readl(&imx_ccm->analog_pll_enet);
|
||||
reg &= ~BM_ANADIG_PLL_SYS_POWERDOWN;
|
||||
writel(reg, &imx_ccm->analog_pll_enet);
|
||||
reg |= BM_ANADIG_PLL_SYS_ENABLE;
|
||||
while (timeout--) {
|
||||
if (readl(&imx_ccm->analog_pll_enet) & BM_ANADIG_PLL_SYS_LOCK)
|
||||
break;
|
||||
}
|
||||
if (timeout <= 0)
|
||||
return -EIO;
|
||||
reg &= ~BM_ANADIG_PLL_SYS_BYPASS;
|
||||
writel(reg, &imx_ccm->analog_pll_enet);
|
||||
reg |= BM_ANADIG_PLL_ENET_ENABLE_SATA;
|
||||
writel(reg, &imx_ccm->analog_pll_enet);
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
unsigned int mxc_get_clock(enum mxc_clock clk)
|
||||
{
|
||||
switch (clk) {
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
*/
|
||||
.section ".text.init", "x"
|
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
#include <linux/linkage.h>
|
||||
|
||||
ENTRY(lowlevel_init)
|
||||
mov pc, lr
|
||||
ENDPROC(lowlevel_init)
|
||||
|
|
|
@ -77,10 +77,40 @@ void init_aips(void)
|
|||
writel(0x00000000, &aips2->opacr4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the VDDSOC
|
||||
*
|
||||
* Mask out the REG_CORE[22:18] bits (REG2_TRIG) and set
|
||||
* them to the specified millivolt level.
|
||||
* Possible values are from 0.725V to 1.450V in steps of
|
||||
* 0.025V (25mV).
|
||||
*/
|
||||
void set_vddsoc(u32 mv)
|
||||
{
|
||||
struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR;
|
||||
u32 val, reg = readl(&anatop->reg_core);
|
||||
|
||||
if (mv < 725)
|
||||
val = 0x00; /* Power gated off */
|
||||
else if (mv > 1450)
|
||||
val = 0x1F; /* Power FET switched full on. No regulation */
|
||||
else
|
||||
val = (mv - 700) / 25;
|
||||
|
||||
/*
|
||||
* Mask out the REG_CORE[22:18] bits (REG2_TRIG)
|
||||
* and set them to the calculated value (0.7V + val * 0.25V)
|
||||
*/
|
||||
reg = (reg & ~(0x1F << 18)) | (val << 18);
|
||||
writel(reg, &anatop->reg_core);
|
||||
}
|
||||
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
init_aips();
|
||||
|
||||
set_vddsoc(1200); /* Set VDDSOC to 1.2V */
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -37,6 +37,7 @@ ifneq ($(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
|
|||
COBJS += hwinit-common.o
|
||||
COBJS += clocks-common.o
|
||||
COBJS += emif-common.o
|
||||
COBJS += vc.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
|
||||
|
|
|
@ -245,6 +245,11 @@ void configure_mpu_dpll(void)
|
|||
CM_CLKSEL_DCC_EN_MASK);
|
||||
}
|
||||
|
||||
setbits_le32(&prcm->cm_mpu_mpu_clkctrl,
|
||||
MPU_CLKCTRL_CLKSEL_EMIF_DIV_MODE_MASK);
|
||||
setbits_le32(&prcm->cm_mpu_mpu_clkctrl,
|
||||
MPU_CLKCTRL_CLKSEL_ABE_DIV_MODE_MASK);
|
||||
|
||||
params = get_mpu_dpll_params();
|
||||
|
||||
do_setup_dpll(&prcm->cm_clkmode_dpll_mpu, params, DPLL_LOCK, "mpu");
|
||||
|
@ -360,56 +365,51 @@ static void setup_non_essential_dplls(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
void do_scale_tps62361(u32 reg, u32 volt_mv)
|
||||
void do_scale_tps62361(int gpio, u32 reg, u32 volt_mv)
|
||||
{
|
||||
u32 temp, step;
|
||||
u32 step;
|
||||
int ret = 0;
|
||||
|
||||
/* See if we can first get the GPIO if needed */
|
||||
if (gpio >= 0)
|
||||
ret = gpio_request(gpio, "TPS62361_VSEL0_GPIO");
|
||||
if (ret < 0) {
|
||||
printf("%s: gpio %d request failed %d\n", __func__, gpio, ret);
|
||||
gpio = -1;
|
||||
}
|
||||
|
||||
/* Pull the GPIO low to select SET0 register, while we program SET1 */
|
||||
if (gpio >= 0)
|
||||
gpio_direction_output(gpio, 0);
|
||||
|
||||
step = volt_mv - TPS62361_BASE_VOLT_MV;
|
||||
step /= 10;
|
||||
|
||||
temp = TPS62361_I2C_SLAVE_ADDR |
|
||||
(reg << PRM_VC_VAL_BYPASS_REGADDR_SHIFT) |
|
||||
(step << PRM_VC_VAL_BYPASS_DATA_SHIFT) |
|
||||
PRM_VC_VAL_BYPASS_VALID_BIT;
|
||||
debug("do_scale_tps62361: volt - %d step - 0x%x\n", volt_mv, step);
|
||||
|
||||
writel(temp, &prcm->prm_vc_val_bypass);
|
||||
if (!wait_on_value(PRM_VC_VAL_BYPASS_VALID_BIT, 0,
|
||||
&prcm->prm_vc_val_bypass, LDELAY)) {
|
||||
if (omap_vc_bypass_send_value(TPS62361_I2C_SLAVE_ADDR, reg, step))
|
||||
puts("Scaling voltage failed for vdd_mpu from TPS\n");
|
||||
}
|
||||
|
||||
/* Pull the GPIO high to select SET1 register */
|
||||
if (gpio >= 0)
|
||||
gpio_direction_output(gpio, 1);
|
||||
}
|
||||
|
||||
void do_scale_vcore(u32 vcore_reg, u32 volt_mv)
|
||||
{
|
||||
u32 temp, offset_code;
|
||||
u32 step = 12660; /* 12.66 mV represented in uV */
|
||||
u32 offset_code;
|
||||
u32 offset = volt_mv;
|
||||
|
||||
/* convert to uV for better accuracy in the calculations */
|
||||
offset *= 1000;
|
||||
|
||||
if (omap_revision() == OMAP4430_ES1_0)
|
||||
offset -= PHOENIX_SMPS_BASE_VOLT_STD_MODE_UV;
|
||||
else
|
||||
offset -= PHOENIX_SMPS_BASE_VOLT_STD_MODE_WITH_OFFSET_UV;
|
||||
|
||||
offset_code = (offset + step - 1) / step;
|
||||
/* The code starts at 1 not 0 */
|
||||
offset_code++;
|
||||
offset_code = get_offset_code(offset);
|
||||
|
||||
debug("do_scale_vcore: volt - %d offset_code - 0x%x\n", volt_mv,
|
||||
offset_code);
|
||||
|
||||
temp = SMPS_I2C_SLAVE_ADDR |
|
||||
(vcore_reg << PRM_VC_VAL_BYPASS_REGADDR_SHIFT) |
|
||||
(offset_code << PRM_VC_VAL_BYPASS_DATA_SHIFT) |
|
||||
PRM_VC_VAL_BYPASS_VALID_BIT;
|
||||
writel(temp, &prcm->prm_vc_val_bypass);
|
||||
if (!wait_on_value(PRM_VC_VAL_BYPASS_VALID_BIT, 0,
|
||||
&prcm->prm_vc_val_bypass, LDELAY)) {
|
||||
if (omap_vc_bypass_send_value(SMPS_I2C_SLAVE_ADDR,
|
||||
vcore_reg, offset_code))
|
||||
printf("Scaling voltage failed for 0x%x\n", vcore_reg);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void enable_clock_domain(u32 *const clkctrl_reg, u32 enable_mode)
|
||||
|
@ -452,6 +452,7 @@ void freq_update_core(void)
|
|||
{
|
||||
u32 freq_config1 = 0;
|
||||
const struct dpll_params *core_dpll_params;
|
||||
u32 omap_rev = omap_revision();
|
||||
|
||||
core_dpll_params = get_core_dpll_params();
|
||||
/* Put EMIF clock domain in sw wakeup mode */
|
||||
|
@ -477,11 +478,18 @@ void freq_update_core(void)
|
|||
hang();
|
||||
}
|
||||
|
||||
/* Put EMIF clock domain back in hw auto mode */
|
||||
enable_clock_domain(&prcm->cm_memif_clkstctrl,
|
||||
CD_CLKCTRL_CLKTRCTRL_HW_AUTO);
|
||||
wait_for_clk_enable(&prcm->cm_memif_emif_1_clkctrl);
|
||||
wait_for_clk_enable(&prcm->cm_memif_emif_2_clkctrl);
|
||||
/*
|
||||
* Putting EMIF in HW_AUTO is seen to be causing issues with
|
||||
* EMIF clocks and the master DLL. Put EMIF in SW_WKUP
|
||||
* in OMAP5430 ES1.0 silicon
|
||||
*/
|
||||
if (omap_rev != OMAP5430_ES1_0) {
|
||||
/* Put EMIF clock domain back in hw auto mode */
|
||||
enable_clock_domain(&prcm->cm_memif_clkstctrl,
|
||||
CD_CLKCTRL_CLKTRCTRL_HW_AUTO);
|
||||
wait_for_clk_enable(&prcm->cm_memif_emif_1_clkctrl);
|
||||
wait_for_clk_enable(&prcm->cm_memif_emif_2_clkctrl);
|
||||
}
|
||||
}
|
||||
|
||||
void bypass_dpll(u32 *const base)
|
||||
|
@ -529,29 +537,6 @@ void setup_clocks_for_console(void)
|
|||
CD_CLKCTRL_CLKTRCTRL_SHIFT);
|
||||
}
|
||||
|
||||
void setup_sri2c(void)
|
||||
{
|
||||
u32 sys_clk_khz, cycles_hi, cycles_low, temp;
|
||||
|
||||
sys_clk_khz = get_sys_clk_freq() / 1000;
|
||||
|
||||
/*
|
||||
* Setup the dedicated I2C controller for Voltage Control
|
||||
* I2C clk - high period 40% low period 60%
|
||||
*/
|
||||
cycles_hi = sys_clk_khz * 4 / PRM_VC_I2C_CHANNEL_FREQ_KHZ / 10;
|
||||
cycles_low = sys_clk_khz * 6 / PRM_VC_I2C_CHANNEL_FREQ_KHZ / 10;
|
||||
/* values to be set in register - less by 5 & 7 respectively */
|
||||
cycles_hi -= 5;
|
||||
cycles_low -= 7;
|
||||
temp = (cycles_hi << PRM_VC_CFG_I2C_CLK_SCLH_SHIFT) |
|
||||
(cycles_low << PRM_VC_CFG_I2C_CLK_SCLL_SHIFT);
|
||||
writel(temp, &prcm->prm_vc_cfg_i2c_clk);
|
||||
|
||||
/* Disable high speed mode and all advanced features */
|
||||
writel(0x0, &prcm->prm_vc_cfg_i2c_mode);
|
||||
}
|
||||
|
||||
void do_enable_clocks(u32 *const *clk_domains,
|
||||
u32 *const *clk_modules_hw_auto,
|
||||
u32 *const *clk_modules_explicit_en,
|
||||
|
|
|
@ -90,20 +90,33 @@ static void do_lpddr2_init(u32 base, u32 cs)
|
|||
* tZQINIT = 1 us
|
||||
* Enough loops assuming a maximum of 2GHz
|
||||
*/
|
||||
|
||||
sdelay(2000);
|
||||
set_mr(base, cs, LPDDR2_MR1, MR1_BL_8_BT_SEQ_WRAP_EN_NWR_3);
|
||||
|
||||
if (omap_revision() >= OMAP5430_ES1_0)
|
||||
set_mr(base, cs, LPDDR2_MR1, MR1_BL_8_BT_SEQ_WRAP_EN_NWR_8);
|
||||
else
|
||||
set_mr(base, cs, LPDDR2_MR1, MR1_BL_8_BT_SEQ_WRAP_EN_NWR_3);
|
||||
|
||||
set_mr(base, cs, LPDDR2_MR16, MR16_REF_FULL_ARRAY);
|
||||
|
||||
/*
|
||||
* Enable refresh along with writing MR2
|
||||
* Encoding of RL in MR2 is (RL - 2)
|
||||
*/
|
||||
mr_addr = LPDDR2_MR2 | EMIF_REG_REFRESH_EN_MASK;
|
||||
set_mr(base, cs, mr_addr, RL_FINAL - 2);
|
||||
|
||||
if (omap_revision() >= OMAP5430_ES1_0)
|
||||
set_mr(base, cs, LPDDR2_MR3, 0x1);
|
||||
}
|
||||
|
||||
static void lpddr2_init(u32 base, const struct emif_regs *regs)
|
||||
{
|
||||
struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
|
||||
u32 *ext_phy_ctrl_base = 0;
|
||||
u32 *emif_ext_phy_ctrl_base = 0;
|
||||
u32 i = 0;
|
||||
|
||||
/* Not NVM */
|
||||
clrbits_le32(&emif->emif_lpddr2_nvm_config, EMIF_REG_CS1NVMEN_MASK);
|
||||
|
@ -119,7 +132,31 @@ static void lpddr2_init(u32 base, const struct emif_regs *regs)
|
|||
* un-locked frequency & default RL
|
||||
*/
|
||||
writel(regs->sdram_config_init, &emif->emif_sdram_config);
|
||||
writel(regs->emif_ddr_phy_ctlr_1_init, &emif->emif_ddr_phy_ctrl_1);
|
||||
writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1);
|
||||
|
||||
ext_phy_ctrl_base = (u32 *) &(regs->emif_ddr_ext_phy_ctrl_1);
|
||||
emif_ext_phy_ctrl_base = (u32 *) &(emif->emif_ddr_ext_phy_ctrl_1);
|
||||
|
||||
if (omap_revision() >= OMAP5430_ES1_0) {
|
||||
/* Configure external phy control timing registers */
|
||||
for (i = 0; i < EMIF_EXT_PHY_CTRL_TIMING_REG; i++) {
|
||||
writel(*ext_phy_ctrl_base, emif_ext_phy_ctrl_base++);
|
||||
/* Update shadow registers */
|
||||
writel(*ext_phy_ctrl_base++, emif_ext_phy_ctrl_base++);
|
||||
}
|
||||
|
||||
/*
|
||||
* external phy 6-24 registers do not change with
|
||||
* ddr frequency
|
||||
*/
|
||||
for (i = 0; i < EMIF_EXT_PHY_CTRL_CONST_REG; i++) {
|
||||
writel(ext_phy_ctrl_const_base[i],
|
||||
emif_ext_phy_ctrl_base++);
|
||||
/* Update shadow registers */
|
||||
writel(ext_phy_ctrl_const_base[i],
|
||||
emif_ext_phy_ctrl_base++);
|
||||
}
|
||||
}
|
||||
|
||||
do_lpddr2_init(base, CS0);
|
||||
if (regs->sdram_config & EMIF_REG_EBANK_MASK)
|
||||
|
|
|
@ -202,22 +202,16 @@ int checkboard(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called by start_armboot. You can reliably use static
|
||||
* data. Any boot-time function that require static data should be
|
||||
* called from here
|
||||
*/
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_device_type(): tell if GP/HS/EMU/TST
|
||||
*/
|
||||
u32 get_device_type(void)
|
||||
{
|
||||
return 0;
|
||||
struct omap_sys_ctrl_regs *ctrl =
|
||||
(struct omap_sys_ctrl_regs *) SYSCTRL_GENERAL_CORE_BASE;
|
||||
|
||||
return (readl(&ctrl->control_status) &
|
||||
(DEVICE_TYPE_MASK)) >> DEVICE_TYPE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
*/
|
||||
|
||||
#include <asm/arch/omap.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.global save_boot_params
|
||||
save_boot_params:
|
||||
ENTRY(save_boot_params)
|
||||
/*
|
||||
* See if the rom code passed pointer is valid:
|
||||
* It is not valid if it is not in non-secure SRAM
|
||||
|
@ -76,10 +76,9 @@ save_boot_params:
|
|||
strb r2, [r3, #CH_FLAGS_OFFSET]
|
||||
1:
|
||||
bx lr
|
||||
ENDPROC(save_boot_params)
|
||||
|
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
ENTRY(lowlevel_init)
|
||||
/*
|
||||
* Setup a temporary stack
|
||||
*/
|
||||
|
@ -95,12 +94,13 @@ lowlevel_init:
|
|||
*/
|
||||
bl s_init
|
||||
pop {ip, pc}
|
||||
ENDPROC(lowlevel_init)
|
||||
|
||||
.globl set_pl310_ctrl_reg
|
||||
set_pl310_ctrl_reg:
|
||||
ENTRY(set_pl310_ctrl_reg)
|
||||
PUSH {r4-r11, lr} @ save registers - ROM code may pollute
|
||||
@ our registers
|
||||
LDR r12, =0x102 @ Set PL310 control register - value in R0
|
||||
.word 0xe1600070 @ SMC #0 - hand assembled because -march=armv5
|
||||
@ call ROM Code API to set control register
|
||||
POP {r4-r11, pc}
|
||||
ENDPROC(set_pl310_ctrl_reg)
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
*
|
||||
* Common layer for reset related functionality of OMAP based socs.
|
||||
*
|
||||
* (C) Copyright 2012
|
||||
* Texas Instruments, <www.ti.com>
|
||||
*
|
||||
* Sricharan R <r.sricharan@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 <asm/io.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
void __weak reset_cpu(unsigned long ignored)
|
||||
{
|
||||
writel(PRM_RSTCTRL_RESET, PRM_RSTCTRL);
|
||||
}
|
|
@ -162,6 +162,7 @@ void board_init_r(gd_t *id, ulong dummy)
|
|||
#ifdef CONFIG_SPL_MMC_SUPPORT
|
||||
case BOOT_DEVICE_MMC1:
|
||||
case BOOT_DEVICE_MMC2:
|
||||
case BOOT_DEVICE_MMC2_2:
|
||||
spl_mmc_load_image();
|
||||
break;
|
||||
#endif
|
||||
|
|
|
@ -39,10 +39,11 @@ int board_mmc_init(bd_t *bis)
|
|||
{
|
||||
switch (omap_boot_device()) {
|
||||
case BOOT_DEVICE_MMC1:
|
||||
omap_mmc_init(0);
|
||||
omap_mmc_init(0, 0, 0);
|
||||
break;
|
||||
case BOOT_DEVICE_MMC2:
|
||||
omap_mmc_init(1);
|
||||
case BOOT_DEVICE_MMC2_2:
|
||||
omap_mmc_init(1, 0, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -54,7 +54,7 @@ void spl_nand_load_image(void)
|
|||
* load parameter image
|
||||
* load to temp position since nand_spl_load_image reads
|
||||
* a whole block which is typically larger than
|
||||
* CONFIG_CMD_SAVEBP_WRITE_SIZE therefore may overwrite
|
||||
* CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite
|
||||
* following sections like BSS
|
||||
*/
|
||||
nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS,
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Voltage Controller implementation for OMAP
|
||||
*
|
||||
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Nishanth Menon
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/omap_common.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
|
||||
/*
|
||||
* Define Master code if there are multiple masters on the I2C_SR bus.
|
||||
* Normally not required
|
||||
*/
|
||||
#ifndef CONFIG_OMAP_VC_I2C_HS_MCODE
|
||||
#define CONFIG_OMAP_VC_I2C_HS_MCODE 0x0
|
||||
#endif
|
||||
|
||||
/* Register defines and masks for VC IP Block */
|
||||
/* PRM_VC_CFG_I2C_MODE */
|
||||
#define PRM_VC_CFG_I2C_MODE_DFILTEREN_BIT (0x1 << 6)
|
||||
#define PRM_VC_CFG_I2C_MODE_SRMODEEN_BIT (0x1 << 4)
|
||||
#define PRM_VC_CFG_I2C_MODE_HSMODEEN_BIT (0x1 << 3)
|
||||
#define PRM_VC_CFG_I2C_MODE_HSMCODE_SHIFT 0x0
|
||||
#define PRM_VC_CFG_I2C_MODE_HSMCODE_MASK 0x3
|
||||
|
||||
/* PRM_VC_CFG_I2C_CLK */
|
||||
#define PRM_VC_CFG_I2C_CLK_HSCLL_SHIFT 24
|
||||
#define PRM_VC_CFG_I2C_CLK_HSCLL_MASK 0xFF
|
||||
#define PRM_VC_CFG_I2C_CLK_HSCLH_SHIFT 16
|
||||
#define PRM_VC_CFG_I2C_CLK_HSCLH_MASK 0xFF
|
||||
#define PRM_VC_CFG_I2C_CLK_SCLH_SHIFT 0
|
||||
#define PRM_VC_CFG_I2C_CLK_SCLH_MASK 0xFF
|
||||
#define PRM_VC_CFG_I2C_CLK_SCLL_SHIFT 8
|
||||
#define PRM_VC_CFG_I2C_CLK_SCLL_MASK (0xFF << 8)
|
||||
|
||||
/* PRM_VC_VAL_BYPASS */
|
||||
#define PRM_VC_VAL_BYPASS_VALID_BIT (0x1 << 24)
|
||||
#define PRM_VC_VAL_BYPASS_SLAVEADDR_SHIFT 0
|
||||
#define PRM_VC_VAL_BYPASS_SLAVEADDR_MASK 0x7F
|
||||
#define PRM_VC_VAL_BYPASS_REGADDR_SHIFT 8
|
||||
#define PRM_VC_VAL_BYPASS_REGADDR_MASK 0xFF
|
||||
#define PRM_VC_VAL_BYPASS_DATA_SHIFT 16
|
||||
#define PRM_VC_VAL_BYPASS_DATA_MASK 0xFF
|
||||
|
||||
/**
|
||||
* omap_vc_init() - Initialization for Voltage controller
|
||||
* @speed_khz: I2C buspeed in KHz
|
||||
*/
|
||||
void omap_vc_init(u16 speed_khz)
|
||||
{
|
||||
u32 val;
|
||||
u32 sys_clk_khz, cycles_hi, cycles_low;
|
||||
|
||||
sys_clk_khz = get_sys_clk_freq() / 1000;
|
||||
|
||||
if (speed_khz > 400) {
|
||||
puts("higher speed requested - throttle to 400Khz\n");
|
||||
speed_khz = 400;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the dedicated I2C controller for Voltage Control
|
||||
* I2C clk - high period 40% low period 60%
|
||||
*/
|
||||
speed_khz /= 10;
|
||||
cycles_hi = sys_clk_khz * 4 / speed_khz;
|
||||
cycles_low = sys_clk_khz * 6 / speed_khz;
|
||||
/* values to be set in register - less by 5 & 7 respectively */
|
||||
cycles_hi -= 5;
|
||||
cycles_low -= 7;
|
||||
val = (cycles_hi << PRM_VC_CFG_I2C_CLK_SCLH_SHIFT) |
|
||||
(cycles_low << PRM_VC_CFG_I2C_CLK_SCLL_SHIFT);
|
||||
writel(val, &prcm->prm_vc_cfg_i2c_clk);
|
||||
|
||||
val = CONFIG_OMAP_VC_I2C_HS_MCODE <<
|
||||
PRM_VC_CFG_I2C_MODE_HSMCODE_SHIFT;
|
||||
/* No HS mode for now */
|
||||
val &= ~PRM_VC_CFG_I2C_MODE_HSMODEEN_BIT;
|
||||
writel(val, &prcm->prm_vc_cfg_i2c_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* omap_vc_bypass_send_value() - Send a data using VC Bypass command
|
||||
* @sa: 7 bit I2C slave address of the PMIC
|
||||
* @reg_addr: I2C register address(8 bit) address in PMIC
|
||||
* @reg_data: what 8 bit data to write
|
||||
*/
|
||||
int omap_vc_bypass_send_value(u8 sa, u8 reg_addr, u8 reg_data)
|
||||
{
|
||||
/*
|
||||
* Unfortunately we need to loop here instead of a defined time
|
||||
* use arbitary large value
|
||||
*/
|
||||
u32 timeout = 0xFFFF;
|
||||
u32 reg_val;
|
||||
|
||||
sa &= PRM_VC_VAL_BYPASS_SLAVEADDR_MASK;
|
||||
reg_addr &= PRM_VC_VAL_BYPASS_REGADDR_MASK;
|
||||
reg_data &= PRM_VC_VAL_BYPASS_DATA_MASK;
|
||||
|
||||
/* program VC to send data */
|
||||
reg_val = sa << PRM_VC_VAL_BYPASS_SLAVEADDR_SHIFT |
|
||||
reg_addr << PRM_VC_VAL_BYPASS_REGADDR_SHIFT |
|
||||
reg_data << PRM_VC_VAL_BYPASS_DATA_SHIFT;
|
||||
writel(reg_val, &prcm->prm_vc_val_bypass);
|
||||
|
||||
/* Signal VC to send data */
|
||||
writel(reg_val | PRM_VC_VAL_BYPASS_VALID_BIT, &prcm->prm_vc_val_bypass);
|
||||
|
||||
/* Wait on VC to complete transmission */
|
||||
do {
|
||||
reg_val = readl(&prcm->prm_vc_val_bypass) &
|
||||
PRM_VC_VAL_BYPASS_VALID_BIT;
|
||||
if (!reg_val)
|
||||
break;
|
||||
|
||||
sdelay(100);
|
||||
} while (--timeout);
|
||||
|
||||
/* Optional: cleanup PRM_IRQSTATUS_Ax */
|
||||
/* In case we can do something about it in future.. */
|
||||
if (!timeout)
|
||||
return -1;
|
||||
|
||||
/* All good.. */
|
||||
return 0;
|
||||
}
|
|
@ -41,6 +41,7 @@
|
|||
#include <asm/arch/gpio.h>
|
||||
#include <asm/omap_common.h>
|
||||
#include <i2c.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
/* Declarations */
|
||||
extern omap3_sysinfo sysinfo;
|
||||
|
@ -244,6 +245,17 @@ void s_init(void)
|
|||
mem_init();
|
||||
}
|
||||
|
||||
/*
|
||||
* Routine: misc_init_r
|
||||
* Description: A basic misc_init_r that just displays the die ID
|
||||
*/
|
||||
int __weak misc_init_r(void)
|
||||
{
|
||||
dieid_num_r();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Routine: wait_for_command_complete
|
||||
* Description: Wait for posting to finish on watchdog
|
||||
|
|
|
@ -572,6 +572,22 @@ void prcm_init(void)
|
|||
}
|
||||
|
||||
if (get_cpu_family() == CPU_OMAP36XX) {
|
||||
/*
|
||||
* In warm reset conditions on OMAP36xx/AM/DM37xx
|
||||
* the rom code incorrectly sets the DPLL4 clock
|
||||
* input divider to /6.5. Section 3.5.3.3.3.2.1 of
|
||||
* the AM/DM37x TRM explains that the /6.5 divider
|
||||
* is used only when the input clock is 13MHz.
|
||||
*
|
||||
* If the part is in this cpu family *and* the input
|
||||
* clock *is not* 13 MHz, then reset the DPLL4 clock
|
||||
* input divider to /1 as it should never set to /6.5
|
||||
* in this case.
|
||||
*/
|
||||
if (sys_clkin_sel != 1) /* 13 MHz */
|
||||
/* Bit 8: DPLL4_CLKINP_DIV */
|
||||
sr32(&prm_base->clksrc_ctrl, 8, 1, 0);
|
||||
|
||||
/* 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,
|
||||
|
|
|
@ -31,22 +31,22 @@
|
|||
#include <version.h>
|
||||
#include <asm/arch/mem.h>
|
||||
#include <asm/arch/clocks_omap3.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
_TEXT_BASE:
|
||||
.word CONFIG_SYS_TEXT_BASE /* sdram load addr from config.mk */
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
.global save_boot_params
|
||||
save_boot_params:
|
||||
ENTRY(save_boot_params)
|
||||
ldr r4, =omap3_boot_device
|
||||
ldr r5, [r0, #0x4]
|
||||
and r5, r5, #0xff
|
||||
str r5, [r4]
|
||||
bx lr
|
||||
ENDPROC(save_boot_params)
|
||||
#endif
|
||||
|
||||
.global omap3_gp_romcode_call
|
||||
omap3_gp_romcode_call:
|
||||
ENTRY(omap3_gp_romcode_call)
|
||||
PUSH {r4-r12, lr} @ Save all registers from ROM code!
|
||||
MOV r12, r0 @ Copy the Service ID in R12
|
||||
MOV r0, r1 @ Copy parameter to R0
|
||||
|
@ -55,6 +55,7 @@ omap3_gp_romcode_call:
|
|||
.word 0xe1600070 @ SMC #0 to enter monitor - hand assembled
|
||||
@ because we use -march=armv5
|
||||
POP {r4-r12, pc}
|
||||
ENDPROC(omap3_gp_romcode_call)
|
||||
|
||||
/*
|
||||
* Funtion for making PPA HAL API calls in secure devices
|
||||
|
@ -62,8 +63,7 @@ omap3_gp_romcode_call:
|
|||
* R0 - Service ID
|
||||
* R1 - paramer list
|
||||
*/
|
||||
.global do_omap3_emu_romcode_call
|
||||
do_omap3_emu_romcode_call:
|
||||
ENTRY(do_omap3_emu_romcode_call)
|
||||
PUSH {r4-r12, lr} @ Save all registers from ROM code!
|
||||
MOV r12, r0 @ Copy the Secure Service ID in R12
|
||||
MOV r3, r1 @ Copy the pointer to va_list in R3
|
||||
|
@ -76,14 +76,14 @@ do_omap3_emu_romcode_call:
|
|||
.word 0xe1600071 @ SMC #1 to call PPA service - hand assembled
|
||||
@ because we use -march=armv5
|
||||
POP {r4-r12, pc}
|
||||
ENDPROC(do_omap3_emu_romcode_call)
|
||||
|
||||
#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:
|
||||
ENTRY(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) */
|
||||
|
@ -95,6 +95,7 @@ next2:
|
|||
cmp r0, r2 /* until source end address [r2] */
|
||||
bne next2
|
||||
mov pc, lr /* back to caller */
|
||||
ENDPROC(cpy_clk_code)
|
||||
|
||||
/* ***************************************************************************
|
||||
* go_to_speed: -Moves to bypass, -Commits clock dividers, -puts dpll at speed
|
||||
|
@ -109,8 +110,7 @@ next2:
|
|||
* 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:
|
||||
ENTRY(go_to_speed)
|
||||
stmfd sp!, {r4 - r6}
|
||||
|
||||
/* move into fast relock bypass */
|
||||
|
@ -171,6 +171,7 @@ wait2:
|
|||
nop
|
||||
ldmfd sp!, {r4 - r6}
|
||||
mov pc, lr /* back to caller, locked */
|
||||
ENDPROC(go_to_speed)
|
||||
|
||||
_go_to_speed: .word go_to_speed
|
||||
|
||||
|
@ -211,8 +212,7 @@ pll_div_val5:
|
|||
|
||||
#endif
|
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
ENTRY(lowlevel_init)
|
||||
ldr sp, SRAM_STACK
|
||||
str ip, [sp] /* stash old link register */
|
||||
mov ip, lr /* save link reg across call */
|
||||
|
@ -230,6 +230,7 @@ lowlevel_init:
|
|||
|
||||
/* back to arch calling code */
|
||||
mov pc, lr
|
||||
ENDPROC(lowlevel_init)
|
||||
|
||||
/* the literal pools origin */
|
||||
.ltorg
|
||||
|
@ -480,22 +481,22 @@ per_36x_dpll_param:
|
|||
.word 26000, 432, 12, 9, 16, 9, 4, 3, 1
|
||||
.word 38400, 360, 15, 9, 16, 5, 4, 3, 1
|
||||
|
||||
.globl get_36x_mpu_dpll_param
|
||||
get_36x_mpu_dpll_param:
|
||||
ENTRY(get_36x_mpu_dpll_param)
|
||||
adr r0, mpu_36x_dpll_param
|
||||
mov pc, lr
|
||||
ENDPROC(get_36x_mpu_dpll_param)
|
||||
|
||||
.globl get_36x_iva_dpll_param
|
||||
get_36x_iva_dpll_param:
|
||||
ENTRY(get_36x_iva_dpll_param)
|
||||
adr r0, iva_36x_dpll_param
|
||||
mov pc, lr
|
||||
ENDPROC(get_36x_iva_dpll_param)
|
||||
|
||||
.globl get_36x_core_dpll_param
|
||||
get_36x_core_dpll_param:
|
||||
ENTRY(get_36x_core_dpll_param)
|
||||
adr r0, core_36x_dpll_param
|
||||
mov pc, lr
|
||||
ENDPROC(get_36x_core_dpll_param)
|
||||
|
||||
.globl get_36x_per_dpll_param
|
||||
get_36x_per_dpll_param:
|
||||
ENTRY(get_36x_per_dpll_param)
|
||||
adr r0, per_36x_dpll_param
|
||||
mov pc, lr
|
||||
ENDPROC(get_36x_per_dpll_param)
|
||||
|
|
|
@ -46,8 +46,6 @@
|
|||
#define puts(s)
|
||||
#endif
|
||||
|
||||
#define abs(x) (((x) < 0) ? ((x)*-1) : (x))
|
||||
|
||||
struct omap4_prcm_regs *const prcm = (struct omap4_prcm_regs *)0x4A004100;
|
||||
|
||||
const u32 sys_clk_array[8] = {
|
||||
|
@ -275,49 +273,72 @@ void scale_vcores(void)
|
|||
{
|
||||
u32 volt, omap_rev;
|
||||
|
||||
setup_sri2c();
|
||||
omap_vc_init(PRM_VC_I2C_CHANNEL_FREQ_KHZ);
|
||||
|
||||
omap_rev = omap_revision();
|
||||
/* TPS - supplies vdd_mpu on 4460 */
|
||||
if (omap_rev >= OMAP4460_ES1_0) {
|
||||
volt = 1203;
|
||||
do_scale_tps62361(TPS62361_REG_ADDR_SET1, volt);
|
||||
}
|
||||
|
||||
/*
|
||||
* VCORE 1
|
||||
*
|
||||
* 4430 : supplies vdd_mpu
|
||||
* Setting a high voltage for Nitro mode as smart reflex is not enabled.
|
||||
* We use the maximum possible value in the AVS range because the next
|
||||
* higher voltage in the discrete range (code >= 0b111010) is way too
|
||||
* high
|
||||
*
|
||||
* 4460 : supplies vdd_core
|
||||
*/
|
||||
if (omap_rev < OMAP4460_ES1_0) {
|
||||
volt = 1325;
|
||||
do_scale_vcore(SMPS_REG_ADDR_VCORE1, volt);
|
||||
} else {
|
||||
volt = 1200;
|
||||
do_scale_vcore(SMPS_REG_ADDR_VCORE1, volt);
|
||||
}
|
||||
|
||||
/* VCORE 2 - supplies vdd_iva */
|
||||
volt = 1200;
|
||||
do_scale_vcore(SMPS_REG_ADDR_VCORE2, volt);
|
||||
|
||||
/*
|
||||
* VCORE 3
|
||||
* 4430 : supplies vdd_core
|
||||
* 4460 : not connected
|
||||
* Scale Voltage rails:
|
||||
* 1. VDD_CORE
|
||||
* 3. VDD_MPU
|
||||
* 3. VDD_IVA
|
||||
*/
|
||||
if (omap_rev < OMAP4460_ES1_0) {
|
||||
/*
|
||||
* OMAP4430:
|
||||
* VDD_CORE = TWL6030 VCORE3
|
||||
* VDD_MPU = TWL6030 VCORE1
|
||||
* VDD_IVA = TWL6030 VCORE2
|
||||
*/
|
||||
volt = 1200;
|
||||
do_scale_vcore(SMPS_REG_ADDR_VCORE3, volt);
|
||||
|
||||
/*
|
||||
* note on VDD_MPU:
|
||||
* Setting a high voltage for Nitro mode as smart reflex is not
|
||||
* enabled. We use the maximum possible value in the AVS range
|
||||
* because the next higher voltage in the discrete range
|
||||
* (code >= 0b111010) is way too high.
|
||||
*/
|
||||
volt = 1325;
|
||||
do_scale_vcore(SMPS_REG_ADDR_VCORE1, volt);
|
||||
volt = 1200;
|
||||
do_scale_vcore(SMPS_REG_ADDR_VCORE2, volt);
|
||||
|
||||
} else {
|
||||
/*
|
||||
* OMAP4460:
|
||||
* VDD_CORE = TWL6030 VCORE1
|
||||
* VDD_MPU = TPS62361
|
||||
* VDD_IVA = TWL6030 VCORE2
|
||||
*/
|
||||
volt = 1200;
|
||||
do_scale_vcore(SMPS_REG_ADDR_VCORE1, volt);
|
||||
/* TPS62361 */
|
||||
volt = 1203;
|
||||
do_scale_tps62361(TPS62361_VSEL0_GPIO,
|
||||
TPS62361_REG_ADDR_SET1, volt);
|
||||
/* VCORE 2 - supplies vdd_iva */
|
||||
volt = 1200;
|
||||
do_scale_vcore(SMPS_REG_ADDR_VCORE2, volt);
|
||||
}
|
||||
}
|
||||
|
||||
u32 get_offset_code(u32 offset)
|
||||
{
|
||||
u32 offset_code, step = 12660; /* 12.66 mV represented in uV */
|
||||
|
||||
if (omap_revision() == OMAP4430_ES1_0)
|
||||
offset -= PHOENIX_SMPS_BASE_VOLT_STD_MODE_UV;
|
||||
else
|
||||
offset -= PHOENIX_SMPS_BASE_VOLT_STD_MODE_WITH_OFFSET_UV;
|
||||
|
||||
offset_code = (offset + step - 1) / step;
|
||||
|
||||
/* The code starts at 1 not 0 */
|
||||
return ++offset_code;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable essential clock domains, modules and
|
||||
* do some additional special settings needed
|
||||
|
@ -355,7 +376,6 @@ void enable_basic_clocks(void)
|
|||
&prcm->cm_l4per_gptimer2_clkctrl,
|
||||
&prcm->cm_wkup_wdtimer2_clkctrl,
|
||||
&prcm->cm_l4per_uart3_clkctrl,
|
||||
&prcm->cm_l3init_fsusb_clkctrl,
|
||||
&prcm->cm_l3init_hsusbhost_clkctrl,
|
||||
0
|
||||
};
|
||||
|
@ -432,10 +452,6 @@ void enable_non_essential_clocks(void)
|
|||
};
|
||||
|
||||
u32 *const clk_modules_hw_auto_non_essential[] = {
|
||||
&prcm->cm_mpu_m3_mpu_m3_clkctrl,
|
||||
&prcm->cm_ivahd_ivahd_clkctrl,
|
||||
&prcm->cm_ivahd_sl2_clkctrl,
|
||||
&prcm->cm_dsp_dsp_clkctrl,
|
||||
&prcm->cm_l3_2_gpmc_clkctrl,
|
||||
&prcm->cm_l3instr_l3_3_clkctrl,
|
||||
&prcm->cm_l3instr_l3_instr_clkctrl,
|
||||
|
@ -482,7 +498,6 @@ void enable_non_essential_clocks(void)
|
|||
&prcm->cm_dss_dss_clkctrl,
|
||||
&prcm->cm_sgx_sgx_clkctrl,
|
||||
&prcm->cm_l3init_hsusbhost_clkctrl,
|
||||
&prcm->cm_l3init_fsusb_clkctrl,
|
||||
0
|
||||
};
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
u32 *const omap4_revision = (u32 *)OMAP4_SRAM_SCRATCH_OMAP4_REV;
|
||||
u32 *const omap_si_rev = (u32 *)OMAP4_SRAM_SCRATCH_OMAP4_REV;
|
||||
|
||||
static const struct gpio_bank gpio_bank_44xx[6] = {
|
||||
{ (void *)OMAP44XX_GPIO1_BASE, METHOD_GPIO_24XX },
|
||||
|
@ -59,8 +59,8 @@ void do_io_settings(void)
|
|||
u32 lpddr2io;
|
||||
struct control_lpddr2io_regs *lpddr2io_regs =
|
||||
(struct control_lpddr2io_regs *)LPDDR2_IO_REGS_BASE;
|
||||
struct omap4_sys_ctrl_regs *const ctrl =
|
||||
(struct omap4_sys_ctrl_regs *)SYSCTRL_GENERAL_CORE_BASE;
|
||||
struct omap_sys_ctrl_regs *const ctrl =
|
||||
(struct omap_sys_ctrl_regs *)SYSCTRL_GENERAL_CORE_BASE;
|
||||
|
||||
u32 omap4_rev = omap_revision();
|
||||
|
||||
|
@ -129,40 +129,40 @@ void init_omap_revision(void)
|
|||
|
||||
switch (arm_rev) {
|
||||
case MIDR_CORTEX_A9_R0P1:
|
||||
*omap4_revision = OMAP4430_ES1_0;
|
||||
*omap_si_rev = OMAP4430_ES1_0;
|
||||
break;
|
||||
case MIDR_CORTEX_A9_R1P2:
|
||||
switch (readl(CONTROL_ID_CODE)) {
|
||||
case OMAP4_CONTROL_ID_CODE_ES2_0:
|
||||
*omap4_revision = OMAP4430_ES2_0;
|
||||
*omap_si_rev = OMAP4430_ES2_0;
|
||||
break;
|
||||
case OMAP4_CONTROL_ID_CODE_ES2_1:
|
||||
*omap4_revision = OMAP4430_ES2_1;
|
||||
*omap_si_rev = OMAP4430_ES2_1;
|
||||
break;
|
||||
case OMAP4_CONTROL_ID_CODE_ES2_2:
|
||||
*omap4_revision = OMAP4430_ES2_2;
|
||||
*omap_si_rev = OMAP4430_ES2_2;
|
||||
break;
|
||||
default:
|
||||
*omap4_revision = OMAP4430_ES2_0;
|
||||
*omap_si_rev = OMAP4430_ES2_0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MIDR_CORTEX_A9_R1P3:
|
||||
*omap4_revision = OMAP4430_ES2_3;
|
||||
*omap_si_rev = OMAP4430_ES2_3;
|
||||
break;
|
||||
case MIDR_CORTEX_A9_R2P10:
|
||||
switch (readl(CONTROL_ID_CODE)) {
|
||||
case OMAP4460_CONTROL_ID_CODE_ES1_1:
|
||||
*omap4_revision = OMAP4460_ES1_1;
|
||||
*omap_si_rev = OMAP4460_ES1_1;
|
||||
break;
|
||||
case OMAP4460_CONTROL_ID_CODE_ES1_0:
|
||||
default:
|
||||
*omap4_revision = OMAP4460_ES1_0;
|
||||
*omap_si_rev = OMAP4460_ES1_0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*omap4_revision = OMAP4430_SILICON_ID_INVALID;
|
||||
*omap_si_rev = OMAP4430_SILICON_ID_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,6 +89,10 @@ const struct emif_regs emif_regs_elpida_400_mhz_2cs = {
|
|||
.emif_ddr_phy_ctlr_1_init = 0x049ffff5,
|
||||
.emif_ddr_phy_ctlr_1 = 0x049ff418
|
||||
};
|
||||
|
||||
/* Dummy registers for OMAP44xx */
|
||||
const u32 ext_phy_ctrl_const_base[EMIF_EXT_PHY_CTRL_CONST_REG];
|
||||
|
||||
const struct dmm_lisa_map_regs lisa_map_2G_x_1_x_2 = {
|
||||
.dmm_lisa_map_0 = 0xFF020100,
|
||||
.dmm_lisa_map_1 = 0,
|
||||
|
|
|
@ -28,7 +28,7 @@ LIB = $(obj)lib$(SOC).o
|
|||
COBJS += hwinit.o
|
||||
COBJS += clocks.o
|
||||
COBJS += emif.o
|
||||
COBJS += sdram_elpida.o
|
||||
COBJS += sdram.o
|
||||
|
||||
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS))
|
||||
|
|
|
@ -88,6 +88,26 @@ static const struct dpll_params mpu_dpll_params_1100mhz[NUM_SYS_CLKS] = {
|
|||
{1375, 47, 1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */
|
||||
};
|
||||
|
||||
static const struct dpll_params mpu_dpll_params_800mhz[NUM_SYS_CLKS] = {
|
||||
{200, 2, 1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
{1000, 20, 1, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */
|
||||
{375, 8, 1, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */
|
||||
{400, 12, 1, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */
|
||||
{375, 17, 1, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */
|
||||
};
|
||||
|
||||
static const struct dpll_params mpu_dpll_params_400mhz[NUM_SYS_CLKS] = {
|
||||
{200, 2, 2, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
{1000, 20, 2, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */
|
||||
{375, 8, 2, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */
|
||||
{400, 12, 2, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */
|
||||
{375, 17, 2, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */
|
||||
};
|
||||
|
||||
static const struct dpll_params mpu_dpll_params_550mhz[NUM_SYS_CLKS] = {
|
||||
{275, 2, 2, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
|
@ -100,17 +120,6 @@ static const struct dpll_params mpu_dpll_params_550mhz[NUM_SYS_CLKS] = {
|
|||
|
||||
static const struct dpll_params
|
||||
core_dpll_params_2128mhz_ddr532[NUM_SYS_CLKS] = {
|
||||
{266, 2, 1, 5, 8, 4, 62, 5, 5, 7}, /* 12 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
{570, 8, 1, 5, 8, 4, 62, 5, 5, 7}, /* 16.8 MHz */
|
||||
{665, 11, 1, 5, 8, 4, 62, 5, 5, 7}, /* 19.2 MHz */
|
||||
{532, 12, 1, 5, 8, 4, 62, 5, 5, 7}, /* 26 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */
|
||||
{665, 23, 1, 5, 8, 4, 62, 5, 5, 7} /* 38.4 MHz */
|
||||
};
|
||||
|
||||
static const struct dpll_params
|
||||
core_dpll_params_2128mhz_ddr266[NUM_SYS_CLKS] = {
|
||||
{266, 2, 2, 5, 8, 4, 62, 5, 5, 7}, /* 12 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
{570, 8, 2, 5, 8, 4, 62, 5, 5, 7}, /* 16.8 MHz */
|
||||
|
@ -120,6 +129,17 @@ static const struct dpll_params
|
|||
{665, 23, 2, 5, 8, 4, 62, 5, 5, 7} /* 38.4 MHz */
|
||||
};
|
||||
|
||||
static const struct dpll_params
|
||||
core_dpll_params_2128mhz_ddr266[NUM_SYS_CLKS] = {
|
||||
{266, 2, 4, 5, 8, 8, 62, 10, 10, 14}, /* 12 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
{570, 8, 4, 5, 8, 8, 62, 10, 10, 14}, /* 16.8 MHz */
|
||||
{665, 11, 4, 5, 8, 8, 62, 10, 10, 14}, /* 19.2 MHz */
|
||||
{532, 12, 4, 8, 8, 8, 62, 10, 10, 14}, /* 26 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */
|
||||
{665, 23, 4, 8, 8, 8, 62, 10, 10, 14} /* 38.4 MHz */
|
||||
};
|
||||
|
||||
static const struct dpll_params per_dpll_params_768mhz[NUM_SYS_CLKS] = {
|
||||
{32, 0, 4, 3, 6, 4, -1, 2, -1, -1}, /* 12 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
|
@ -131,40 +151,40 @@ static const struct dpll_params per_dpll_params_768mhz[NUM_SYS_CLKS] = {
|
|||
};
|
||||
|
||||
static const struct dpll_params iva_dpll_params_2330mhz[NUM_SYS_CLKS] = {
|
||||
{931, 11, -1, -1, 4, 7, -1, -1}, /* 12 MHz */
|
||||
{931, 12, -1, -1, 4, 7, -1, -1}, /* 13 MHz */
|
||||
{665, 11, -1, -1, 4, 7, -1, -1}, /* 16.8 MHz */
|
||||
{727, 14, -1, -1, 4, 7, -1, -1}, /* 19.2 MHz */
|
||||
{931, 25, -1, -1, 4, 7, -1, -1}, /* 26 MHz */
|
||||
{931, 26, -1, -1, 4, 7, -1, -1}, /* 27 MHz */
|
||||
{412, 16, -1, -1, 4, 7, -1, -1} /* 38.4 MHz */
|
||||
{1165, 11, -1, -1, 5, 6, -1, -1, -1, -1}, /* 12 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
{2011, 28, -1, -1, 5, 6, -1, -1, -1, -1}, /* 16.8 MHz */
|
||||
{1881, 30, -1, -1, 5, 6, -1, -1, -1, -1}, /* 19.2 MHz */
|
||||
{1165, 25, -1, -1, 5, 6, -1, -1, -1, -1}, /* 26 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */
|
||||
{1972, 64, -1, -1, 5, 6, -1, -1, -1, -1} /* 38.4 MHz */
|
||||
};
|
||||
|
||||
/* ABE M & N values with sys_clk as source */
|
||||
static const struct dpll_params
|
||||
abe_dpll_params_sysclk_196608khz[NUM_SYS_CLKS] = {
|
||||
{49, 5, 1, 1, -1, -1, -1, -1}, /* 12 MHz */
|
||||
{68, 8, 1, 1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
{35, 5, 1, 1, -1, -1, -1, -1}, /* 16.8 MHz */
|
||||
{46, 8, 1, 1, -1, -1, -1, -1}, /* 19.2 MHz */
|
||||
{34, 8, 1, 1, -1, -1, -1, -1}, /* 26 MHz */
|
||||
{29, 7, 1, 1, -1, -1, -1, -1}, /* 27 MHz */
|
||||
{64, 24, 1, 1, -1, -1, -1, -1} /* 38.4 MHz */
|
||||
{49, 5, 1, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
{35, 5, 1, 1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */
|
||||
{46, 8, 1, 1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */
|
||||
{34, 8, 1, 1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */
|
||||
{64, 24, 1, 1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */
|
||||
};
|
||||
|
||||
/* ABE M & N values with 32K clock as source */
|
||||
static const struct dpll_params abe_dpll_params_32k_196608khz = {
|
||||
750, 0, 1, 1, -1, -1, -1, -1
|
||||
750, 0, 1, 1, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
static const struct dpll_params usb_dpll_params_1920mhz[NUM_SYS_CLKS] = {
|
||||
{80, 0, 2, -1, -1, -1, -1, -1}, /* 12 MHz */
|
||||
{960, 12, 2, -1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
{400, 6, 2, -1, -1, -1, -1, -1}, /* 16.8 MHz */
|
||||
{50, 0, 2, -1, -1, -1, -1, -1}, /* 19.2 MHz */
|
||||
{480, 12, 2, -1, -1, -1, -1, -1}, /* 26 MHz */
|
||||
{320, 8, 2, -1, -1, -1, -1, -1}, /* 27 MHz */
|
||||
{25, 0, 2, -1, -1, -1, -1, -1} /* 38.4 MHz */
|
||||
{400, 4, 2, -1, -1, -1, -1, -1, -1, -1}, /* 12 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 13 MHz */
|
||||
{400, 6, 2, -1, -1, -1, -1, -1, -1, -1}, /* 16.8 MHz */
|
||||
{400, 7, 2, -1, -1, -1, -1, -1, -1, -1}, /* 19.2 MHz */
|
||||
{480, 12, 2, -1, -1, -1, -1, -1, -1, -1}, /* 26 MHz */
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* 27 MHz */
|
||||
{400, 15, 2, -1, -1, -1, -1, -1, -1, -1} /* 38.4 MHz */
|
||||
};
|
||||
|
||||
void setup_post_dividers(u32 *const base, const struct dpll_params *params)
|
||||
|
@ -193,7 +213,7 @@ void setup_post_dividers(u32 *const base, const struct dpll_params *params)
|
|||
const struct dpll_params *get_mpu_dpll_params(void)
|
||||
{
|
||||
u32 sysclk_ind = get_sys_clk_index();
|
||||
return &mpu_dpll_params_1100mhz[sysclk_ind];
|
||||
return &mpu_dpll_params_800mhz[sysclk_ind];
|
||||
}
|
||||
|
||||
const struct dpll_params *get_core_dpll_params(void)
|
||||
|
@ -201,8 +221,7 @@ const struct dpll_params *get_core_dpll_params(void)
|
|||
u32 sysclk_ind = get_sys_clk_index();
|
||||
|
||||
/* Configuring the DDR to be at 532mhz */
|
||||
return &core_dpll_params_2128mhz_ddr266[sysclk_ind];
|
||||
|
||||
return &core_dpll_params_2128mhz_ddr532[sysclk_ind];
|
||||
}
|
||||
|
||||
const struct dpll_params *get_per_dpll_params(void)
|
||||
|
@ -243,19 +262,33 @@ void scale_vcores(void)
|
|||
{
|
||||
u32 volt;
|
||||
|
||||
setup_sri2c();
|
||||
omap_vc_init(PRM_VC_I2C_CHANNEL_FREQ_KHZ);
|
||||
|
||||
/* Enable 1.22V from TPS for vdd_mpu */
|
||||
volt = 1220;
|
||||
do_scale_tps62361(TPS62361_REG_ADDR_SET1, volt);
|
||||
/* Palmas settings */
|
||||
volt = VDD_CORE;
|
||||
do_scale_vcore(SMPS_REG_ADDR_8_CORE, volt);
|
||||
|
||||
/* VCORE 1 - for vdd_core */
|
||||
volt = 1000;
|
||||
do_scale_vcore(SMPS_REG_ADDR_VCORE1, volt);
|
||||
volt = VDD_MPU;
|
||||
do_scale_vcore(SMPS_REG_ADDR_12_MPU, volt);
|
||||
|
||||
/* VCORE 2 - for vdd_MM */
|
||||
volt = 1125;
|
||||
do_scale_vcore(SMPS_REG_ADDR_VCORE2, volt);
|
||||
volt = VDD_MM;
|
||||
do_scale_vcore(SMPS_REG_ADDR_45_IVA, volt);
|
||||
|
||||
}
|
||||
|
||||
u32 get_offset_code(u32 volt_offset)
|
||||
{
|
||||
u32 offset_code, step = 10000; /* 10 mV represented in uV */
|
||||
|
||||
volt_offset -= PALMAS_SMPS_BASE_VOLT_UV;
|
||||
|
||||
offset_code = (volt_offset + step - 1) / step;
|
||||
|
||||
/*
|
||||
* Offset codes 1-6 all give the base voltage in Palmas
|
||||
* Offset code 0 switches OFF the SMPS
|
||||
*/
|
||||
return offset_code + 6;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -306,6 +339,12 @@ void enable_basic_clocks(void)
|
|||
setbits_le32(&prcm->cm_l3init_hsmmc2_clkctrl,
|
||||
HSMMC_CLKCTRL_CLKSEL_MASK);
|
||||
|
||||
/* Set the correct clock dividers for mmc */
|
||||
setbits_le32(&prcm->cm_l3init_hsmmc1_clkctrl,
|
||||
HSMMC_CLKCTRL_CLKSEL_DIV_MASK);
|
||||
setbits_le32(&prcm->cm_l3init_hsmmc2_clkctrl,
|
||||
HSMMC_CLKCTRL_CLKSEL_DIV_MASK);
|
||||
|
||||
/* Select 32KHz clock as the source of GPTIMER1 */
|
||||
setbits_le32(&prcm->cm_wkup_gptimer1_clkctrl,
|
||||
GPTIMER1_CLKCTRL_CLKSEL_MASK);
|
||||
|
@ -314,6 +353,18 @@ void enable_basic_clocks(void)
|
|||
clk_modules_hw_auto_essential,
|
||||
clk_modules_explicit_en_essential,
|
||||
1);
|
||||
|
||||
/* Select 384Mhz for GPU as its the POR for ES1.0 */
|
||||
setbits_le32(&prcm->cm_sgx_sgx_clkctrl,
|
||||
CLKSEL_GPU_HYD_GCLK_MASK);
|
||||
setbits_le32(&prcm->cm_sgx_sgx_clkctrl,
|
||||
CLKSEL_GPU_CORE_GCLK_MASK);
|
||||
|
||||
/* Enable SCRM OPT clocks for PER and CORE dpll */
|
||||
setbits_le32(&prcm->cm_wkupaon_scrm_clkctrl,
|
||||
OPTFCLKEN_SCRM_PER_MASK);
|
||||
setbits_le32(&prcm->cm_wkupaon_scrm_clkctrl,
|
||||
OPTFCLKEN_SCRM_CORE_MASK);
|
||||
}
|
||||
|
||||
void enable_basic_uboot_clocks(void)
|
||||
|
@ -371,6 +422,7 @@ void enable_non_essential_clocks(void)
|
|||
&prcm->cm_l3instr_intrconn_wp1_clkctrl,
|
||||
&prcm->cm_l3init_hsi_clkctrl,
|
||||
&prcm->cm_l3init_hsusbtll_clkctrl,
|
||||
&prcm->cm_l4per_hdq1w_clkctrl,
|
||||
0
|
||||
};
|
||||
|
||||
|
@ -393,7 +445,6 @@ void enable_non_essential_clocks(void)
|
|||
&prcm->cm_l4per_gptimer11_clkctrl,
|
||||
&prcm->cm_l4per_gptimer3_clkctrl,
|
||||
&prcm->cm_l4per_gptimer4_clkctrl,
|
||||
&prcm->cm_l4per_hdq1w_clkctrl,
|
||||
&prcm->cm_l4per_mcspi2_clkctrl,
|
||||
&prcm->cm_l4per_mcspi3_clkctrl,
|
||||
&prcm->cm_l4per_mcspi4_clkctrl,
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
u32 *const omap5_revision = (u32 *)OMAP5_SRAM_SCRATCH_OMAP5_REV;
|
||||
u32 *const omap_si_rev = (u32 *)OMAP5_SRAM_SCRATCH_OMAP5_REV;
|
||||
|
||||
static struct gpio_bank gpio_bank_54xx[6] = {
|
||||
{ (void *)OMAP54XX_GPIO1_BASE, METHOD_GPIO_24XX },
|
||||
|
@ -57,6 +57,89 @@ const struct gpio_bank *const omap_gpio_bank = gpio_bank_54xx;
|
|||
*/
|
||||
void do_io_settings(void)
|
||||
{
|
||||
u32 io_settings = 0, mask = 0;
|
||||
struct omap_sys_ctrl_regs *ioregs_base =
|
||||
(struct omap_sys_ctrl_regs *) SYSCTRL_GENERAL_CORE_BASE;
|
||||
|
||||
/* Impedance settings EMMC, C2C 1,2, hsi2 */
|
||||
mask = (ds_mask << 2) | (ds_mask << 8) |
|
||||
(ds_mask << 16) | (ds_mask << 18);
|
||||
io_settings = readl(&(ioregs_base->control_smart1io_padconf_0)) &
|
||||
(~mask);
|
||||
io_settings |= (ds_60_ohm << 8) | (ds_45_ohm << 16) |
|
||||
(ds_45_ohm << 18) | (ds_60_ohm << 2);
|
||||
writel(io_settings, &(ioregs_base->control_smart1io_padconf_0));
|
||||
|
||||
/* Impedance settings Mcspi2 */
|
||||
mask = (ds_mask << 30);
|
||||
io_settings = readl(&(ioregs_base->control_smart1io_padconf_1)) &
|
||||
(~mask);
|
||||
io_settings |= (ds_60_ohm << 30);
|
||||
writel(io_settings, &(ioregs_base->control_smart1io_padconf_1));
|
||||
|
||||
/* Impedance settings C2C 3,4 */
|
||||
mask = (ds_mask << 14) | (ds_mask << 16);
|
||||
io_settings = readl(&(ioregs_base->control_smart1io_padconf_2)) &
|
||||
(~mask);
|
||||
io_settings |= (ds_45_ohm << 14) | (ds_45_ohm << 16);
|
||||
writel(io_settings, &(ioregs_base->control_smart1io_padconf_2));
|
||||
|
||||
/* Slew rate settings EMMC, C2C 1,2 */
|
||||
mask = (sc_mask << 8) | (sc_mask << 16) | (sc_mask << 18);
|
||||
io_settings = readl(&(ioregs_base->control_smart2io_padconf_0)) &
|
||||
(~mask);
|
||||
io_settings |= (sc_fast << 8) | (sc_na << 16) | (sc_na << 18);
|
||||
writel(io_settings, &(ioregs_base->control_smart2io_padconf_0));
|
||||
|
||||
/* Slew rate settings hsi2, Mcspi2 */
|
||||
mask = (sc_mask << 24) | (sc_mask << 28);
|
||||
io_settings = readl(&(ioregs_base->control_smart2io_padconf_1)) &
|
||||
(~mask);
|
||||
io_settings |= (sc_fast << 28) | (sc_fast << 24);
|
||||
writel(io_settings, &(ioregs_base->control_smart2io_padconf_1));
|
||||
|
||||
/* Slew rate settings C2C 3,4 */
|
||||
mask = (sc_mask << 16) | (sc_mask << 18);
|
||||
io_settings = readl(&(ioregs_base->control_smart2io_padconf_2)) &
|
||||
(~mask);
|
||||
io_settings |= (sc_na << 16) | (sc_na << 18);
|
||||
writel(io_settings, &(ioregs_base->control_smart2io_padconf_2));
|
||||
|
||||
/* impedance and slew rate settings for usb */
|
||||
mask = (usb_i_mask << 29) | (usb_i_mask << 26) | (usb_i_mask << 23) |
|
||||
(usb_i_mask << 20) | (usb_i_mask << 17) | (usb_i_mask << 14);
|
||||
io_settings = readl(&(ioregs_base->control_smart3io_padconf_1)) &
|
||||
(~mask);
|
||||
io_settings |= (ds_60_ohm << 29) | (ds_60_ohm << 26) |
|
||||
(ds_60_ohm << 23) | (sc_fast << 20) |
|
||||
(sc_fast << 17) | (sc_fast << 14);
|
||||
writel(io_settings, &(ioregs_base->control_smart3io_padconf_1));
|
||||
|
||||
/* LPDDR2 io settings */
|
||||
writel(DDR_IO_I_34OHM_SR_FASTEST_WD_DQ_NO_PULL_DQS_PULL_DOWN,
|
||||
&(ioregs_base->control_ddrch1_0));
|
||||
writel(DDR_IO_I_34OHM_SR_FASTEST_WD_DQ_NO_PULL_DQS_PULL_DOWN,
|
||||
&(ioregs_base->control_ddrch1_1));
|
||||
writel(DDR_IO_I_34OHM_SR_FASTEST_WD_DQ_NO_PULL_DQS_PULL_DOWN,
|
||||
&(ioregs_base->control_ddrch2_0));
|
||||
writel(DDR_IO_I_34OHM_SR_FASTEST_WD_DQ_NO_PULL_DQS_PULL_DOWN,
|
||||
&(ioregs_base->control_ddrch2_1));
|
||||
writel(DDR_IO_I_34OHM_SR_FASTEST_WD_CK_CKE_NCS_CA_PULL_DOWN,
|
||||
&(ioregs_base->control_lpddr2ch1_0));
|
||||
writel(DDR_IO_I_34OHM_SR_FASTEST_WD_CK_CKE_NCS_CA_PULL_DOWN,
|
||||
&(ioregs_base->control_lpddr2ch1_1));
|
||||
writel(DDR_IO_0_DDR2_DQ_INT_EN_ALL_DDR3_CA_DIS_ALL,
|
||||
&(ioregs_base->control_ddrio_0));
|
||||
writel(DDR_IO_1_DQ_OUT_EN_ALL_DQ_INT_EN_ALL,
|
||||
&(ioregs_base->control_ddrio_1));
|
||||
writel(DDR_IO_2_CA_OUT_EN_ALL_CA_INT_EN_ALL,
|
||||
&(ioregs_base->control_ddrio_2));
|
||||
|
||||
/* Efuse settings */
|
||||
writel(EFUSE_1, &(ioregs_base->control_efuse_1));
|
||||
writel(EFUSE_2, &(ioregs_base->control_efuse_2));
|
||||
writel(EFUSE_3, &(ioregs_base->control_efuse_3));
|
||||
writel(EFUSE_4, &(ioregs_base->control_efuse_4));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -71,8 +154,23 @@ void init_omap_revision(void)
|
|||
|
||||
switch (rev) {
|
||||
case MIDR_CORTEX_A15_R0P0:
|
||||
*omap5_revision = OMAP5430_ES1_0;
|
||||
*omap_si_rev = OMAP5430_ES1_0;
|
||||
break;
|
||||
default:
|
||||
*omap5_revision = OMAP5430_SILICON_ID_INVALID;
|
||||
*omap_si_rev = OMAP5430_SILICON_ID_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
void reset_cpu(ulong ignored)
|
||||
{
|
||||
u32 omap_rev = omap_revision();
|
||||
|
||||
/*
|
||||
* WARM reset is not functional in case of OMAP5430 ES1.0 soc.
|
||||
* So use cold reset in case instead.
|
||||
*/
|
||||
if (omap_rev == OMAP5430_ES1_0)
|
||||
writel(PRM_RSTCTRL_RESET << 0x1, PRM_RSTCTRL);
|
||||
else
|
||||
writel(PRM_RSTCTRL_RESET, PRM_RSTCTRL);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Timing and Organization details of the ddr device parts used in OMAP5
|
||||
* EVM
|
||||
*
|
||||
* (C) Copyright 2010
|
||||
* Texas Instruments, <www.ti.com>
|
||||
*
|
||||
* Aneesh V <aneesh@ti.com>
|
||||
* Sricharan R <r.sricharan@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 <asm/emif.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
|
||||
/*
|
||||
* This file provides details of the LPDDR2 SDRAM parts used on OMAP5
|
||||
* EVM. Since the parts used and geometry are identical for
|
||||
* evm for a given OMAP5 revision, this information is kept
|
||||
* here instead of being in board directory. However the key functions
|
||||
* exported are weakly linked so that they can be over-ridden in the board
|
||||
* directory if there is a OMAP5 board in the future that uses a different
|
||||
* memory device or geometry.
|
||||
*
|
||||
* For any new board with different memory devices over-ride one or more
|
||||
* of the following functions as per the CONFIG flags you intend to enable:
|
||||
* - emif_get_reg_dump()
|
||||
* - emif_get_dmm_regs()
|
||||
* - emif_get_device_details()
|
||||
* - emif_get_device_timings()
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
|
||||
const struct emif_regs emif_regs_532_mhz_2cs = {
|
||||
.sdram_config_init = 0x80800EBA,
|
||||
.sdram_config = 0x808022BA,
|
||||
.ref_ctrl = 0x0000081A,
|
||||
.sdram_tim1 = 0x772F6873,
|
||||
.sdram_tim2 = 0x304a129a,
|
||||
.sdram_tim3 = 0x02f7e45f,
|
||||
.read_idle_ctrl = 0x00050000,
|
||||
.zq_config = 0x000b3215,
|
||||
.temp_alert_config = 0x08000a05,
|
||||
.emif_ddr_phy_ctlr_1_init = 0x0E28420d,
|
||||
.emif_ddr_phy_ctlr_1 = 0x0E28420d,
|
||||
.emif_ddr_ext_phy_ctrl_1 = 0x04020080,
|
||||
.emif_ddr_ext_phy_ctrl_2 = 0x28C518A3,
|
||||
.emif_ddr_ext_phy_ctrl_3 = 0x518A3146,
|
||||
.emif_ddr_ext_phy_ctrl_4 = 0x0014628C,
|
||||
.emif_ddr_ext_phy_ctrl_5 = 0x04010040
|
||||
};
|
||||
|
||||
const struct emif_regs emif_regs_266_mhz_2cs = {
|
||||
.sdram_config_init = 0x80800EBA,
|
||||
.sdram_config = 0x808022BA,
|
||||
.ref_ctrl = 0x0000040D,
|
||||
.sdram_tim1 = 0x2A86B419,
|
||||
.sdram_tim2 = 0x1025094A,
|
||||
.sdram_tim3 = 0x026BA22F,
|
||||
.read_idle_ctrl = 0x00050000,
|
||||
.zq_config = 0x000b3215,
|
||||
.temp_alert_config = 0x08000a05,
|
||||
.emif_ddr_phy_ctlr_1_init = 0x0E28420d,
|
||||
.emif_ddr_phy_ctlr_1 = 0x0E28420d,
|
||||
.emif_ddr_ext_phy_ctrl_1 = 0x04020080,
|
||||
.emif_ddr_ext_phy_ctrl_2 = 0x0A414829,
|
||||
.emif_ddr_ext_phy_ctrl_3 = 0x14829052,
|
||||
.emif_ddr_ext_phy_ctrl_4 = 0x000520A4,
|
||||
.emif_ddr_ext_phy_ctrl_5 = 0x04010040
|
||||
};
|
||||
|
||||
const struct dmm_lisa_map_regs lisa_map_4G_x_2_x_2 = {
|
||||
.dmm_lisa_map_0 = 0x0,
|
||||
.dmm_lisa_map_1 = 0,
|
||||
.dmm_lisa_map_2 = 0,
|
||||
.dmm_lisa_map_3 = 0x80740300
|
||||
};
|
||||
|
||||
const u32 ext_phy_ctrl_const_base[EMIF_EXT_PHY_CTRL_CONST_REG] = {
|
||||
0x01004010,
|
||||
0x00001004,
|
||||
0x04010040,
|
||||
0x01004010,
|
||||
0x00001004,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x80080080,
|
||||
0x00800800,
|
||||
0x08102040,
|
||||
0x00000001,
|
||||
0x540A8150,
|
||||
0xA81502a0,
|
||||
0x002A0540,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000077
|
||||
};
|
||||
|
||||
static void emif_get_reg_dump_sdp(u32 emif_nr, const struct emif_regs **regs)
|
||||
{
|
||||
*regs = &emif_regs_532_mhz_2cs;
|
||||
}
|
||||
void emif_get_reg_dump(u32 emif_nr, const struct emif_regs **regs)
|
||||
__attribute__((weak, alias("emif_get_reg_dump_sdp")));
|
||||
|
||||
static void emif_get_dmm_regs_sdp(const struct dmm_lisa_map_regs
|
||||
**dmm_lisa_regs)
|
||||
{
|
||||
*dmm_lisa_regs = &lisa_map_4G_x_2_x_2;
|
||||
}
|
||||
|
||||
void emif_get_dmm_regs(const struct dmm_lisa_map_regs **dmm_lisa_regs)
|
||||
__attribute__((weak, alias("emif_get_dmm_regs_sdp")));
|
||||
|
||||
#else
|
||||
|
||||
static const struct lpddr2_device_details dev_4G_S4_details = {
|
||||
.type = LPDDR2_TYPE_S4,
|
||||
.density = LPDDR2_DENSITY_4Gb,
|
||||
.io_width = LPDDR2_IO_WIDTH_32,
|
||||
.manufacturer = LPDDR2_MANUFACTURER_SAMSUNG
|
||||
};
|
||||
|
||||
static void emif_get_device_details_sdp(u32 emif_nr,
|
||||
struct lpddr2_device_details *cs0_device_details,
|
||||
struct lpddr2_device_details *cs1_device_details)
|
||||
{
|
||||
/* EMIF1 & EMIF2 have identical configuration */
|
||||
*cs0_device_details = dev_4G_S4_details;
|
||||
*cs1_device_details = dev_4G_S4_details;
|
||||
}
|
||||
|
||||
void emif_get_device_details(u32 emif_nr,
|
||||
struct lpddr2_device_details *cs0_device_details,
|
||||
struct lpddr2_device_details *cs1_device_details)
|
||||
__attribute__((weak, alias("emif_get_device_details_sdp")));
|
||||
|
||||
#endif /* CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS */
|
||||
|
||||
#ifndef CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS
|
||||
static const struct lpddr2_ac_timings timings_jedec_532_mhz = {
|
||||
.max_freq = 532000000,
|
||||
.RL = 8,
|
||||
.tRPab = 21,
|
||||
.tRCD = 18,
|
||||
.tWR = 15,
|
||||
.tRASmin = 42,
|
||||
.tRRD = 10,
|
||||
.tWTRx2 = 15,
|
||||
.tXSR = 140,
|
||||
.tXPx2 = 15,
|
||||
.tRFCab = 130,
|
||||
.tRTPx2 = 15,
|
||||
.tCKE = 3,
|
||||
.tCKESR = 15,
|
||||
.tZQCS = 90,
|
||||
.tZQCL = 360,
|
||||
.tZQINIT = 1000,
|
||||
.tDQSCKMAXx2 = 11,
|
||||
.tRASmax = 70,
|
||||
.tFAW = 50
|
||||
};
|
||||
|
||||
static const struct lpddr2_min_tck min_tck = {
|
||||
.tRL = 3,
|
||||
.tRP_AB = 3,
|
||||
.tRCD = 3,
|
||||
.tWR = 3,
|
||||
.tRAS_MIN = 3,
|
||||
.tRRD = 2,
|
||||
.tWTR = 2,
|
||||
.tXP = 2,
|
||||
.tRTP = 2,
|
||||
.tCKE = 3,
|
||||
.tCKESR = 3,
|
||||
.tFAW = 8
|
||||
};
|
||||
|
||||
static const struct lpddr2_ac_timings *ac_timings[MAX_NUM_SPEEDBINS] = {
|
||||
&timings_jedec_532_mhz
|
||||
};
|
||||
|
||||
static const struct lpddr2_device_timings dev_4G_S4_timings = {
|
||||
.ac_timings = ac_timings,
|
||||
.min_tck = &min_tck,
|
||||
};
|
||||
|
||||
void emif_get_device_timings_sdp(u32 emif_nr,
|
||||
const struct lpddr2_device_timings **cs0_device_timings,
|
||||
const struct lpddr2_device_timings **cs1_device_timings)
|
||||
{
|
||||
/* Identical devices on EMIF1 & EMIF2 */
|
||||
*cs0_device_timings = &dev_4G_S4_timings;
|
||||
*cs1_device_timings = &dev_4G_S4_timings;
|
||||
}
|
||||
|
||||
void emif_get_device_timings(u32 emif_nr,
|
||||
const struct lpddr2_device_timings **cs0_device_timings,
|
||||
const struct lpddr2_device_timings **cs1_device_timings)
|
||||
__attribute__((weak, alias("emif_get_device_timings_sdp")));
|
||||
|
||||
#endif /* CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS */
|
|
@ -0,0 +1,62 @@
|
|||
#
|
||||
# (C) Copyright 2000-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
|
||||
#
|
||||
# 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).o
|
||||
|
||||
COBJS-y += timer.o serial.o ifc.o cpu.o rda_sys.o ispi.o
|
||||
COBJS-$(CONFIG_SPL_SIGNATURE_CHECK_IMAGE) += rda_crypto.o rda_romapi.o
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
COBJS-y += spl.o
|
||||
COBJS-$(CONFIG_SPL_XMODEM_LOAD) += xmodem_boot.o
|
||||
else
|
||||
ifdef CONFIG_MDCOM
|
||||
COBJS-y += mdcom.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef CONFIG_SKIP_LOWLEVEL_INIT
|
||||
SOBJS += lowlevel_init.o
|
||||
endif
|
||||
|
||||
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(COBJS-y) $(SOBJS))
|
||||
START := $(addprefix $(obj),$(START))
|
||||
|
||||
all: $(obj).depend $(LIB)
|
||||
|
||||
$(LIB): $(OBJS)
|
||||
$(call cmd_link_o_target, $(OBJS))
|
||||
|
||||
#########################################################################
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
|
@ -0,0 +1,95 @@
|
|||
#
|
||||
# (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 $(TOPDIR)/slt.mk
|
||||
include $(TOPDIR)/customer.mk
|
||||
include $(TOPDIR)/board/$(SOC)/$(BOARD)/config.mk
|
||||
|
||||
image_flags :=
|
||||
|
||||
ifneq ($(TARGET_SYSTEMIMAGE_USE_UBIFS),)
|
||||
image_flags += -DUBIFS_SYSTEM_IMAGE
|
||||
endif
|
||||
|
||||
ifneq ($(TARGET_USERIMAGES_USE_UBIFS),)
|
||||
image_flags += -DUBIFS_USER_IMAGES
|
||||
endif
|
||||
|
||||
ifneq ($(TARGET_SYSTEMIMAGE_USE_EXT4),)
|
||||
image_flags += -DEXTFS_SYSTEM_IMAGE
|
||||
endif
|
||||
|
||||
ifneq ($(TARGET_USERIMAGES_USE_EXT4),)
|
||||
image_flags += -DEXTFS_USER_IMAGES
|
||||
endif
|
||||
|
||||
image_flags += -DSPL_APPENDING_TO=$(SPL_APPENDING_TO)
|
||||
|
||||
pdl_flags :=
|
||||
ifeq ($(pdl), 1)
|
||||
pdl_flags += -DCONFIG_RDA_PDL
|
||||
endif
|
||||
|
||||
nand_flags :=
|
||||
ifneq ($(BOARD_NAND_PAGE_SIZE),)
|
||||
nand_flags += -DNAND_PAGE_SIZE=$(BOARD_NAND_PAGE_SIZE)
|
||||
else
|
||||
nand_flags += -DNAND_PAGE_SIZE=4096
|
||||
endif
|
||||
ifneq ($(BOARD_FLASH_BLOCK_SIZE),)
|
||||
nand_flags += -DNAND_BLOCK_SIZE=$(BOARD_FLASH_BLOCK_SIZE)
|
||||
else
|
||||
nand_flags += -DNAND_BLOCK_SIZE=262144
|
||||
endif
|
||||
ifneq ($(BOARD_NAND_SPARE_SIZE),)
|
||||
nand_flags += -DNAND_SPARE_SIZE=$(BOARD_NAND_SPARE_SIZE)
|
||||
else
|
||||
nand_flags += -DNAND_SPARE_SIZE=218
|
||||
endif
|
||||
ifneq ($(BOARD_NAND_ECCMSGLEN),)
|
||||
nand_flags += -DNAND_ECCMSGLEN=$(BOARD_NAND_ECCMSGLEN)
|
||||
else
|
||||
nand_flags += -DNAND_ECCMSGLEN=1024
|
||||
endif
|
||||
ifneq ($(BOARD_NAND_ECCBITS),)
|
||||
nand_flags += -DNAND_ECCBITS=$(BOARD_NAND_ECCBITS)
|
||||
else
|
||||
nand_flags += -DNAND_ECCBITS=24
|
||||
endif
|
||||
ifneq ($(BOARD_NAND_OOB_SIZE),)
|
||||
nand_flags += -DNAND_OOBSIZE=$(BOARD_NAND_OOB_SIZE)
|
||||
else
|
||||
nand_flags += -DNAND_OOBSIZE=32
|
||||
endif
|
||||
|
||||
build_variant_flags :=
|
||||
|
||||
ifneq ($(UBOOT_VARIANT), user)
|
||||
build_variant_flags += -DCONFIG_UBOOT_VARIANT_DEBUG
|
||||
endif
|
||||
|
||||
ifneq ($(BUILD_DISPLAY_ID),)
|
||||
build_variant_flags += -DBUILD_DISPLAY_ID="\"$(BUILD_DISPLAY_ID)\""
|
||||
endif
|
||||
|
||||
PLATFORM_CPPFLAGS += $(image_flags) $(pdl_flags) $(build_variant_flags) $(nand_flags)
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#include <common.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
|
||||
void enable_neon(void)
|
||||
{
|
||||
/* enable cp10 and cp11 */
|
||||
uint32_t val;
|
||||
|
||||
__asm__ volatile("mrc p15, 0, %0, c1, c1, 2" : "=r" (val));
|
||||
printf("CPU: p15-c1-c1 (NSACR): 0x%08x", val);
|
||||
val |= (3<<10);
|
||||
val &= ~(3<<14);
|
||||
__asm__ volatile("mcr p15, 0, %0, c1, c1, 2" :: "r" (val));
|
||||
printf(" -> 0x%08x\n", val);
|
||||
|
||||
__asm__ volatile("mrc p15, 0, %0, c1, c0, 2" : "=r" (val));
|
||||
printf("CPU: p15-c1-c0 (CPACR): 0x%08x", val);
|
||||
val |= (3<<22)|(3<<20);
|
||||
__asm__ volatile("mcr p15, 0, %0, c1, c0, 2" :: "r" (val));
|
||||
printf(" -> 0x%08x\n", val);
|
||||
|
||||
/* set enable bit in fpexc */
|
||||
val = (1<<30);
|
||||
__asm__ volatile("mcr p10, 7, %0, c8, c0, 0" :: "r" (val));
|
||||
}
|
||||
|
||||
#if (defined(CONFIG_MACH_RDA8810E) \
|
||||
||defined(CONFIG_MACH_RDA8820) \
|
||||
||defined(CONFIG_MACH_RDA8810H) \
|
||||
||defined(CONFIG_MACH_RDA8850E))
|
||||
/* SMP MACHs */
|
||||
void smp_setup(void)
|
||||
{
|
||||
asm volatile(
|
||||
"mrc p15, 0, r0, c1, c0, 1\n"
|
||||
"orr r0, r0, #0x40\n"
|
||||
"mcr p15, 0, r0, c1, c0, 1\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
void enable_caches(void)
|
||||
{
|
||||
#if (defined(CONFIG_MACH_RDA8810E) \
|
||||
||defined(CONFIG_MACH_RDA8820) \
|
||||
||defined(CONFIG_MACH_RDA8810H) \
|
||||
||defined(CONFIG_MACH_RDA8850E))
|
||||
printf("CPU: enable smp\n");
|
||||
smp_setup();
|
||||
#endif
|
||||
#ifndef CONFIG_SYS_ICACHE_OFF
|
||||
printf("CPU: enable instruction caches\n");
|
||||
icache_enable();
|
||||
#endif
|
||||
#ifndef CONFIG_SYS_DCACHE_OFF
|
||||
printf("CPU: enable data caches\n");
|
||||
dcache_enable();
|
||||
#endif
|
||||
#ifndef CONFIG_SYS_NEON_OFF
|
||||
printf("CPU: enable neon\n");
|
||||
enable_neon();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DISPLAY_CPUINFO
|
||||
/* Print CPU information */
|
||||
int print_cpuinfo(void)
|
||||
{
|
||||
#if defined(CONFIG_MACH_RDAARM926EJS)
|
||||
printf("RDAARM926EJS FPGA\n");
|
||||
#elif defined(CONFIG_MACH_RDA8810)
|
||||
printf("RDA8810 SoC\n");
|
||||
#elif defined(CONFIG_MACH_RDA8810E)
|
||||
printf("RDA8810E SoC\n");
|
||||
#elif defined(CONFIG_MACH_RDA8820)
|
||||
printf("RDA8820 SoC\n");
|
||||
#elif defined(CONFIG_MACH_RDA8850)
|
||||
printf("RDA8850 SoC\n");
|
||||
#elif defined(CONFIG_MACH_RDA8850E)
|
||||
printf("RDA8850E SoC\n");
|
||||
#elif defined(CONFIG_MACH_RDA8810H)
|
||||
printf("RDA8810H SoC\n");
|
||||
#else
|
||||
#error "Unknown RDA CPU"
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DISPLAY_CPUINFO */
|
|
@ -0,0 +1,172 @@
|
|||
#include "common.h"
|
||||
#include <errno.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/reg_ifc.h>
|
||||
#include <asm/arch/ifc.h>
|
||||
|
||||
#undef assert
|
||||
#ifdef DEBUG
|
||||
#include <assert.h>
|
||||
#else
|
||||
#define assert(...)
|
||||
#endif
|
||||
|
||||
#define HAL_TRACE(...)
|
||||
|
||||
HAL_IFC_REQUEST_ID_T g_halModuleIfcChannelOwner[SYS_IFC_STD_CHAN_NB];
|
||||
|
||||
void hal_IfcOpen(void)
|
||||
{
|
||||
u8 channel;
|
||||
|
||||
// Initialize the channel table with unknown requests.
|
||||
for (channel = 0; channel < SYS_IFC_STD_CHAN_NB; channel++)
|
||||
{
|
||||
g_halModuleIfcChannelOwner[channel] = HAL_IFC_NO_REQWEST;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_IFC_REQUEST_ID_T hal_IfcGetOwner(u8 channel)
|
||||
{
|
||||
// Here, we consider the transfer as previously finished.
|
||||
if (channel == HAL_UNKNOWN_CHANNEL) return HAL_IFC_NO_REQWEST;
|
||||
|
||||
// Channel number too big.
|
||||
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
|
||||
|
||||
return g_halModuleIfcChannelOwner[channel];
|
||||
}
|
||||
|
||||
void hal_IfcChannelRelease(HAL_IFC_REQUEST_ID_T requestId, u8 channel)
|
||||
{
|
||||
//u32 status;
|
||||
|
||||
// Here, we consider the transfer as previously finished.
|
||||
if (channel == HAL_UNKNOWN_CHANNEL) return;
|
||||
|
||||
// Channel number too big.
|
||||
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
|
||||
|
||||
//status = hal_SysEnterCriticalSection();
|
||||
if (g_halModuleIfcChannelOwner[channel] == requestId)
|
||||
{
|
||||
// disable this channel
|
||||
hwp_sysIfc->std_ch[channel].control = (SYS_IFC_REQ_SRC(requestId)
|
||||
| SYS_IFC_CH_RD_HW_EXCH
|
||||
| SYS_IFC_DISABLE);
|
||||
// read the status of this channel
|
||||
if (hwp_sysIfc->std_ch[channel].status & SYS_IFC_ENABLE)
|
||||
{
|
||||
HAL_TRACE(_HAL | TSTDOUT,0," Strange, the released channel not disabled yet");
|
||||
}
|
||||
// Write the TC to 0 for next time the channel is re-enabled
|
||||
hwp_sysIfc->std_ch[channel].tc = 0;
|
||||
}
|
||||
//hal_SysExitCriticalSection(status);
|
||||
}
|
||||
|
||||
void hal_IfcChannelFlush(HAL_IFC_REQUEST_ID_T requestId, u8 channel)
|
||||
{
|
||||
//u32 status;
|
||||
|
||||
// Here, we consider the transfer as previously finished.
|
||||
if (channel == HAL_UNKNOWN_CHANNEL) return;
|
||||
|
||||
// Channel number too big.
|
||||
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
|
||||
|
||||
// Check that the channel is really owned by the peripheral
|
||||
// which is doing the request, it could have been release
|
||||
// automatically or by an IRQ handler.
|
||||
//status = hal_SysEnterCriticalSection();
|
||||
if (g_halModuleIfcChannelOwner[channel] == requestId)
|
||||
{
|
||||
// If fifo not empty, flush it.
|
||||
if ( !(hwp_sysIfc->std_ch[channel].status & SYS_IFC_FIFO_EMPTY) )
|
||||
{
|
||||
hwp_sysIfc->std_ch[channel].control =
|
||||
hwp_sysIfc->std_ch[channel].control | SYS_IFC_FLUSH;
|
||||
}
|
||||
}
|
||||
//hal_SysExitCriticalSection(status);
|
||||
}
|
||||
|
||||
BOOL hal_IfcChannelIsFifoEmpty(HAL_IFC_REQUEST_ID_T requestId, u8 channel)
|
||||
{
|
||||
//u32 status;
|
||||
BOOL fifoIsEmpty = TRUE;
|
||||
|
||||
// Here, we consider the transfer as previously finished.
|
||||
if (channel == HAL_UNKNOWN_CHANNEL) return fifoIsEmpty;
|
||||
|
||||
// Channel number too big.
|
||||
assert(channel < SYS_IFC_STD_CHAN_NB, channel);
|
||||
|
||||
// Check that the channel is really owned by the peripheral
|
||||
// which is doing the request, it could have been release
|
||||
// automatically or by an IRQ handler.
|
||||
//status = hal_SysEnterCriticalSection();
|
||||
if (g_halModuleIfcChannelOwner[channel] == requestId)
|
||||
{
|
||||
fifoIsEmpty =
|
||||
(FALSE != (hwp_sysIfc->std_ch[channel].status & SYS_IFC_FIFO_EMPTY));
|
||||
}
|
||||
//hal_SysExitCriticalSection(status);
|
||||
|
||||
return fifoIsEmpty;
|
||||
}
|
||||
|
||||
u8 hal_IfcTransferStart(HAL_IFC_REQUEST_ID_T requestId, u8* memStartAddr, u32 xferSize, HAL_IFC_MODE_T ifcMode)
|
||||
{
|
||||
//u32 status = hal_SysEnterCriticalSection();
|
||||
u8 channel;
|
||||
u8 i;
|
||||
|
||||
// Check buffer alignment depending on the mode
|
||||
if (ifcMode != HAL_IFC_SIZE_8_MODE_MANUAL && ifcMode != HAL_IFC_SIZE_8_MODE_AUTO)
|
||||
{
|
||||
// Then ifcMode == HAL_IFC_SIZE_32, check word alignment
|
||||
assert(((u32)memStartAddr%4) == 0,
|
||||
"HAL IFC: 32 bits transfer misaligned 0x@%08X", memStartAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ifcMode == HAL_IFC_SIZE_8, nothing to check
|
||||
}
|
||||
|
||||
// Check the requested id is not currently already used.
|
||||
for (i = 0; i < SYS_IFC_STD_CHAN_NB ; i++)
|
||||
{
|
||||
if (GET_BITFIELD(hwp_sysIfc->std_ch[i].control, SYS_IFC_REQ_SRC) == requestId)
|
||||
{
|
||||
// This channel is or was used for the requestId request.
|
||||
// Check it is still in use.
|
||||
assert((hwp_sysIfc->std_ch[i].status & SYS_IFC_ENABLE) == 0,
|
||||
"HAL: Attempt to use the IFC to deal with a %d"
|
||||
" request still active on channel %d", requestId, i);
|
||||
}
|
||||
}
|
||||
|
||||
channel = SYS_IFC_CH_TO_USE(hwp_sysIfc->get_ch) ;
|
||||
|
||||
if (channel >= SYS_IFC_STD_CHAN_NB)
|
||||
{
|
||||
serial_puts("HAL_UNKNOWN_CHANNEL\n");
|
||||
//hal_SysExitCriticalSection(status);
|
||||
return HAL_UNKNOWN_CHANNEL;
|
||||
}
|
||||
|
||||
g_halModuleIfcChannelOwner[channel] = requestId;
|
||||
hwp_sysIfc->std_ch[channel].start_addr = (u32) memStartAddr;
|
||||
hwp_sysIfc->std_ch[channel].tc = xferSize;
|
||||
hwp_sysIfc->std_ch[channel].control = (SYS_IFC_REQ_SRC(requestId)
|
||||
| ifcMode
|
||||
| SYS_IFC_CH_RD_HW_EXCH
|
||||
| SYS_IFC_ENABLE);
|
||||
|
||||
//hal_SysExitCriticalSection(status);
|
||||
return channel;
|
||||
}
|
||||
|
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
* (C) Copyright 2013
|
||||
* RDA Microelectronics Inc.
|
||||
*
|
||||
* Derived from drivers/spi/rda_ispi.c
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/arch/reg_spi.h>
|
||||
#include <asm/arch/ispi.h>
|
||||
|
||||
#ifdef CONFIG_MACH_RDA8850E
|
||||
#include <asm/arch/reg_rf_spi.h>
|
||||
|
||||
#define RDA6220_ADDR_MASK 0xFF
|
||||
#define RDA6220_ADDR_OFFSET 23
|
||||
#define RDA6220_DATA_MASK 0xFFFF
|
||||
#define RDA6220_DATA_OFFSET 7
|
||||
|
||||
#define RDA6220_WRITE_FMT(addr, data) (((addr & RDA6220_ADDR_MASK) << RDA6220_ADDR_OFFSET) |\
|
||||
((data & RDA6220_DATA_MASK) << RDA6220_DATA_OFFSET))
|
||||
|
||||
#define RDA6220_READ_FMT(addr, data) ( ((addr & RDA6220_ADDR_MASK) << RDA6220_ADDR_OFFSET)|\
|
||||
((data & RDA6220_DATA_MASK) << RDA6220_DATA_OFFSET)|\
|
||||
1<<31);
|
||||
|
||||
void modem_RfspiOpen(void)
|
||||
{
|
||||
// Setter
|
||||
hwp_rfSpi->Ctrl = 0x8fd82e45;
|
||||
|
||||
// To remove the "FORCE ZERO" in case of low-active CS
|
||||
hwp_rfSpi->Command = 0;
|
||||
hwp_rfSpi->Divider = RF_SPI_DIVIDER(23);
|
||||
}
|
||||
|
||||
void modem_rf_spiWrite(const u8 *Cmd, u32 CmdSize)
|
||||
{
|
||||
u32 loop=0;
|
||||
|
||||
// Flush the Tx fifo
|
||||
hwp_rfSpi->Command = RF_SPI_FLUSH_CMD_FIFO | RF_SPI_FLUSH_RX_FIFO;
|
||||
for (loop=0; loop<CmdSize; loop++)
|
||||
{
|
||||
hwp_rfSpi->Cmd_Data = Cmd[loop];
|
||||
}
|
||||
// Set the cmd size
|
||||
hwp_rfSpi->Cmd_Size = RF_SPI_CMD_SIZE(CmdSize);
|
||||
|
||||
// And send the command
|
||||
hwp_rfSpi->Command = RF_SPI_SEND_CMD;
|
||||
|
||||
// Wait for the SPI to start - at least one byte has been sent
|
||||
while(GET_BITFIELD(hwp_rfSpi->Status, RF_SPI_CMD_DATA_LEVEL) >= CmdSize);
|
||||
// Wait for the SPI to finish
|
||||
while((hwp_rfSpi->Status & RF_SPI_ACTIVE_STATUS) != 0);
|
||||
}
|
||||
|
||||
|
||||
void modem_RfspiWrite(const u8 addr, u32 data)
|
||||
{
|
||||
u8 cmd[4] = {0};
|
||||
u32 cmd_word = RDA6220_WRITE_FMT(addr, data);
|
||||
|
||||
cmd[0] = (cmd_word >> 24) & 0xff;
|
||||
cmd[1] = (cmd_word >>16) & 0xff;
|
||||
cmd[2] = (cmd_word >> 8) & 0xff;
|
||||
cmd[3] = (cmd_word >> 0) & 0xff;
|
||||
|
||||
modem_rf_spiWrite(cmd, 4);
|
||||
}
|
||||
|
||||
void modem_RfspiInit_624M(void)
|
||||
{
|
||||
modem_RfspiOpen();
|
||||
|
||||
modem_RfspiWrite(0x30, 0x5182);
|
||||
|
||||
mdelay(10); // delay 10 ms
|
||||
modem_RfspiWrite(0x30, 0x5187);
|
||||
mdelay(10); // delay 10 ms
|
||||
// xtal setting
|
||||
modem_RfspiWrite(0xb0, 0xe404);
|
||||
modem_RfspiWrite(0xb8, 0x1800);
|
||||
modem_RfspiWrite(0xba, 0x0401);
|
||||
modem_RfspiWrite(0xc0, 0x0008);
|
||||
modem_RfspiWrite(0xfe, 0x4000);
|
||||
modem_RfspiWrite(0x10, 0x0880);
|
||||
modem_RfspiWrite(0x20, 0x03e4);
|
||||
modem_RfspiWrite(0x22, 0x0488);
|
||||
modem_RfspiWrite(0xe8, 0x1000);
|
||||
modem_RfspiWrite(0xe6, 0x0000);
|
||||
modem_RfspiWrite(0xe4, 0x0c00);
|
||||
modem_RfspiWrite(0xe4, 0x8c00);
|
||||
modem_RfspiWrite(0xfe, 0x0000);
|
||||
modem_RfspiWrite(0x4e, 0xe538);
|
||||
modem_RfspiWrite(0x4c, 0x04b9);
|
||||
modem_RfspiWrite(0x4c, 0x84b9);
|
||||
|
||||
}
|
||||
|
||||
void modem_8850eeco2_RfspiInit_624M(void)
|
||||
{
|
||||
modem_RfspiOpen();
|
||||
|
||||
modem_RfspiWrite(0x30, 0x5182);
|
||||
|
||||
mdelay(10); // delay 10 ms
|
||||
modem_RfspiWrite(0x30, 0x5187);
|
||||
mdelay(10); // delay 10 ms
|
||||
// xtal setting
|
||||
|
||||
modem_RfspiWrite(0xfe, 0x4000);
|
||||
modem_RfspiWrite(0x10, 0x0880);
|
||||
modem_RfspiWrite(0xfe, 0x0000);
|
||||
}
|
||||
#endif
|
||||
|
||||
static HWP_SPI_T *hwp_ispi = hwp_spi3;
|
||||
|
||||
void ispi_open(int modemSpi)
|
||||
{
|
||||
u32 cfgReg = 0;
|
||||
u32 ctrlReg = 0;
|
||||
|
||||
// spi_clk_freq = APB2 / ((div+1)*2)
|
||||
// the maximum clock frequency is 7MHz~8MHz
|
||||
// the spi clock frequency is 5MHz when div is 0x13
|
||||
cfgReg = 0x130003;
|
||||
ctrlReg = 0x2019d821;
|
||||
|
||||
if (modemSpi)
|
||||
hwp_ispi = hwp_mspi2;
|
||||
else
|
||||
hwp_ispi = hwp_spi3;
|
||||
|
||||
// Activate the ISPI.
|
||||
hwp_ispi->cfg = cfgReg;
|
||||
hwp_ispi->ctrl = ctrlReg;
|
||||
|
||||
// No IRQ.
|
||||
hwp_ispi->irq = 0;
|
||||
}
|
||||
|
||||
static u8 ispi_tx_fifo_avail(void)
|
||||
{
|
||||
u8 freeRoom;
|
||||
|
||||
// Get avail level.
|
||||
freeRoom = GET_BITFIELD(hwp_ispi->status, SPI_TX_SPACE);
|
||||
|
||||
return freeRoom;
|
||||
}
|
||||
|
||||
static int ispi_tx_finished(void)
|
||||
{
|
||||
u32 spiStatus;
|
||||
spiStatus = hwp_ispi->status;
|
||||
|
||||
// If ISPI FSM is active and the TX Fifo is empty
|
||||
// (ie available space == Fifo size), the tf is not done
|
||||
if ((!(hwp_ispi->status & SPI_ACTIVE_STATUS))
|
||||
&& (SPI_TX_FIFO_SIZE == GET_BITFIELD(spiStatus, SPI_TX_SPACE))) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 ispi_send_data(u32 csId, u32 data, int read)
|
||||
{
|
||||
u32 freeRoom;
|
||||
|
||||
// Clear data upper bit to only keep the data frame.
|
||||
u32 reg = data & ~(SPI_CS_MASK | SPI_READ_ENA_MASK);
|
||||
|
||||
// Add CS and read mode bit
|
||||
reg |= SPI_CS(csId) | (read ? SPI_READ_ENA : 0);
|
||||
|
||||
// Enter critical section.
|
||||
//u32 status = hwp_sysIrq->SC;
|
||||
|
||||
// Check FIFO availability.
|
||||
freeRoom = GET_BITFIELD(hwp_ispi->status, SPI_TX_SPACE);
|
||||
|
||||
if (freeRoom > 0) {
|
||||
// Write data.
|
||||
hwp_ispi->rxtx_buffer = reg;
|
||||
|
||||
// Exit critical section.
|
||||
//hwp_sysIrq->SC = status;
|
||||
return 1;
|
||||
} else {
|
||||
// Exit critical section.
|
||||
//hwp_sysIrq->SC = status;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 ispi_get_data(u32 * recData)
|
||||
{
|
||||
u32 nbAvailable;
|
||||
|
||||
// Enter critical section.
|
||||
//u32 status = hwp_sysIrq->SC;
|
||||
|
||||
nbAvailable = GET_BITFIELD(hwp_ispi->status, SPI_RX_LEVEL);
|
||||
|
||||
if (nbAvailable > 0) {
|
||||
*recData = hwp_ispi->rxtx_buffer;
|
||||
|
||||
// Exit critical section.
|
||||
//hwp_sysIrq->SC = status;
|
||||
return 1;
|
||||
} else {
|
||||
// Exit critical section.
|
||||
//hwp_sysIrq->SC = status;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ispi_reg_write(u32 regIdx, u32 value)
|
||||
{
|
||||
u32 wrData;
|
||||
|
||||
wrData = (0 << 25) | ((regIdx & 0x1ff) << 16) | (value & 0xffff);
|
||||
|
||||
while (ispi_tx_fifo_avail() < 1 ||
|
||||
ispi_send_data(0, wrData, FALSE) == 0) ;
|
||||
|
||||
//wait until any previous transfers have ended
|
||||
while (!ispi_tx_finished()) ;
|
||||
}
|
||||
|
||||
u32 ispi_reg_read(u32 regIdx)
|
||||
{
|
||||
u32 wrData, rdData = 0;
|
||||
u32 count;
|
||||
|
||||
wrData = (1 << 25) | ((regIdx & 0x1ff) << 16) | 0;
|
||||
|
||||
while (ispi_tx_fifo_avail() < 1 ||
|
||||
ispi_send_data(0, wrData, TRUE) == 0) ;
|
||||
|
||||
//wait until any previous transfers have ended
|
||||
while (!ispi_tx_finished()) ;
|
||||
|
||||
count = ispi_get_data(&rdData);
|
||||
if (1 != count)
|
||||
serial_puts("ABB ISPI count err!");
|
||||
|
||||
rdData &= 0xffff;
|
||||
|
||||
return rdData;
|
||||
}
|
||||
|
||||
u16 rda_read_efuse(int page_index)
|
||||
{
|
||||
u16 rvalue, wvalue;
|
||||
|
||||
ispi_open(1);
|
||||
|
||||
wvalue = 0x2e0 | page_index;
|
||||
pmu_reg_write(0x51, wvalue);
|
||||
udelay(2000);
|
||||
wvalue = 0x2f0 | page_index;
|
||||
pmu_reg_write(0x51, wvalue);
|
||||
rvalue = pmu_reg_read(0x52);
|
||||
pmu_reg_write(0x51, 0x0200);
|
||||
|
||||
ispi_open(0);
|
||||
return rvalue;
|
||||
}
|
||||
|
||||
#ifdef EFUSE_DUMP
|
||||
void dump_efuse(void)
|
||||
{
|
||||
u16 rvalue,wvalue;
|
||||
int i;
|
||||
|
||||
ispi_open(1);
|
||||
|
||||
for(i = 0;i<16;i++){
|
||||
wvalue = 0x2e0 | i;
|
||||
pmu_reg_write(0x51, wvalue);
|
||||
udelay(2000);
|
||||
wvalue = 0x2f0 | i;
|
||||
pmu_reg_write(0x51, wvalue);
|
||||
rvalue = pmu_reg_read(0x52);
|
||||
pmu_reg_write(0x51, 0x0200);
|
||||
|
||||
printf("page%d = %d \n", i, rvalue);
|
||||
}
|
||||
ispi_open(0);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,877 @@
|
|||
#include "common.h"
|
||||
#include <errno.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/reg_sysctrl.h>
|
||||
#include <asm/arch/reg_mdcom.h>
|
||||
#include <asm/arch/reg_xcpu.h>
|
||||
#include <asm/arch/defs_mdcom.h>
|
||||
#include <asm/arch/mdcom.h>
|
||||
#include <asm/arch/factory.h>
|
||||
#include <asm/arch/rda_iomap.h>
|
||||
#include <asm/arch/reg_cfg_regs.h>
|
||||
|
||||
|
||||
static u32 modem_logic_base_addr = 0x02000000;
|
||||
void rda_mdcom_set_logic_base_addr(u32 base)
|
||||
{
|
||||
modem_logic_base_addr = base & 0xffff0000;
|
||||
printf("## Set modem logic base address %#x\n", modem_logic_base_addr);
|
||||
}
|
||||
|
||||
#define RDA_MODEM_IN_DDR(addr, modem_logic_base_addr) \
|
||||
(((u32)(addr) & 0x0F000000) == (modem_logic_base_addr & 0x0F000000))
|
||||
|
||||
/*
|
||||
* Convert a modem address to an AP address
|
||||
*/
|
||||
u32 rda_mdcom_address_modem2ap(u32 addr)
|
||||
{
|
||||
#if defined(_TGT_MODEM_MEM_SIZE) && (_TGT_MODEM_MEM_SIZE > 0)
|
||||
if (RDA_MODEM_IN_DDR(addr, modem_logic_base_addr))
|
||||
return (RDA_MODEM_RAM_BASE - modem_logic_base_addr + addr);
|
||||
else
|
||||
return RDA_ADD_M2A(addr);
|
||||
#else
|
||||
return RDA_ADD_M2A(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup modem running env
|
||||
*/
|
||||
int rda_mdcom_setup_run_env(u32 pc, u32 param)
|
||||
{
|
||||
RDA_BOOT_HST_MONITOR_X_CTX_T *ctx =
|
||||
(RDA_BOOT_HST_MONITOR_X_CTX_T *)RDA_BOOT_CTX_ADD;
|
||||
ctx->cmdType = 0xFF;
|
||||
ctx->pc = pc;
|
||||
ctx->sp = 0;
|
||||
ctx->param = (void *)param;
|
||||
ctx->returnedValue = (void *)0;
|
||||
|
||||
#if defined(_TGT_MODEM_MEM_SIZE) && (_TGT_MODEM_MEM_SIZE > 0)
|
||||
// Set DDR access offset
|
||||
if (RDA_MODEM_IN_DDR(pc, modem_logic_base_addr)) {
|
||||
#ifdef CONFIG_MACH_RDA8850E
|
||||
u32 offs = RDA_MODEM_RAM_BASE - modem_logic_base_addr;
|
||||
|
||||
/* 0x1000000 alignment */
|
||||
if(offs & 0xffffff) {
|
||||
printf("\nERROR: modem memory map offset %#x is not aligned to 0x1000000.\n", offs);
|
||||
printf("ERROR: modem cannot work, abort.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
hwp_configRegs->Mem_mode_Sel = 0;
|
||||
hwp_configRegs->H2X_DDR_Offset = offs;
|
||||
hwp_configRegs->H2X_WD_DDR_Offset = offs;
|
||||
#else
|
||||
u32 offs = CFG_REGS_H2X_DDR_OFFSET((RDA_MODEM_RAM_BASE - modem_logic_base_addr) >> 24);
|
||||
hwp_configRegs->H2X_DDR_Offset = offs;
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Modem calibration data section address
|
||||
*/
|
||||
void rda_mdcom_get_calib_section(u32 *addr, u32 *len)
|
||||
{
|
||||
if (addr)
|
||||
*addr = RDA_MODEM_CAL_ADDR;
|
||||
if (len)
|
||||
*len = RDA_MODEM_CAL_LEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Modem extended calibration data section address
|
||||
*/
|
||||
void rda_mdcom_get_ext_calib_section(u32 *addr, u32 *len)
|
||||
{
|
||||
if (addr)
|
||||
*addr = RDA_MODEM_EXT_CAL_ADDR;
|
||||
if (len)
|
||||
*len = RDA_MODEM_EXT_CAL_LEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Modem factory section address
|
||||
*/
|
||||
void rda_mdcom_get_factory_section(u32 *addr, u32 *len)
|
||||
{
|
||||
if (addr)
|
||||
*addr = RDA_MODEM_FACT_ADDR;
|
||||
if (len)
|
||||
*len = RDA_MODEM_FACT_LEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* AP factory section address
|
||||
*/
|
||||
void rda_mdcom_get_ap_factory_section(u32 *addr, u32 *len)
|
||||
{
|
||||
if (addr)
|
||||
*addr = RDA_AP_FACT_ADDR;
|
||||
if (len)
|
||||
*len = RDA_AP_FACT_LEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset cause
|
||||
*/
|
||||
u32 rda_mdcom_get_reset_cause(void)
|
||||
{
|
||||
return ((RDA_AP_MBX_HEARTBEAT_T *)RDA_AP_MBX_HEARTBEAT_ADD)->resetCause;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface version
|
||||
*/
|
||||
u32 rda_mdcom_get_interface_version(void)
|
||||
{
|
||||
return ((RDA_AP_MBX_HEARTBEAT_T *)RDA_AP_MBX_HEARTBEAT_ADD)->version;
|
||||
}
|
||||
|
||||
/*
|
||||
* Magic number
|
||||
*/
|
||||
int rda_mdcom_system_started_before(void)
|
||||
{
|
||||
RDA_AP_MBX_MAGIC_NUMBER_T *magic =
|
||||
(RDA_AP_MBX_MAGIC_NUMBER_T *)RDA_AP_MBX_MAGIC_NUMBER_ADD;
|
||||
return magic->sysStarted == RDA_MAGIC_SYSTEM_STARTED_FLAG;
|
||||
}
|
||||
|
||||
void rda_mdcom_set_system_started_flag(void)
|
||||
{
|
||||
RDA_AP_MBX_MAGIC_NUMBER_T *magic =
|
||||
(RDA_AP_MBX_MAGIC_NUMBER_T *)RDA_AP_MBX_MAGIC_NUMBER_ADD;
|
||||
magic->sysStarted = RDA_MAGIC_SYSTEM_STARTED_FLAG;
|
||||
}
|
||||
|
||||
int rda_mdcom_modem_crashed_before(void)
|
||||
{
|
||||
RDA_AP_MBX_MAGIC_NUMBER_T *magic =
|
||||
(RDA_AP_MBX_MAGIC_NUMBER_T *)RDA_AP_MBX_MAGIC_NUMBER_ADD;
|
||||
return magic->modemCrashed == RDA_MAGIC_MODEM_CRASH_FLAG;
|
||||
}
|
||||
|
||||
int rda_mdcom_calib_update_cmd_valid(void)
|
||||
{
|
||||
RDA_AP_MBX_MAGIC_NUMBER_T *magic =
|
||||
(RDA_AP_MBX_MAGIC_NUMBER_T *)RDA_AP_MBX_MAGIC_NUMBER_ADD;
|
||||
if (magic->factUpdateCmd == RDA_MAGIC_FACT_UPD_CMD_FLAG &&
|
||||
(magic->factUpdateType &
|
||||
RDA_MAGIC_FACT_UPD_TYPE_FLAG_MASK) ==
|
||||
RDA_MAGIC_FACT_UPD_TYPE_FLAG &&
|
||||
(magic->factUpdateType & RDA_MAGIC_FACT_UPD_TYPE_CALIB))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rda_mdcom_factory_update_cmd_valid(void)
|
||||
{
|
||||
RDA_AP_MBX_MAGIC_NUMBER_T *magic =
|
||||
(RDA_AP_MBX_MAGIC_NUMBER_T *)RDA_AP_MBX_MAGIC_NUMBER_ADD;
|
||||
if (magic->factUpdateCmd == RDA_MAGIC_FACT_UPD_CMD_FLAG &&
|
||||
(magic->factUpdateType &
|
||||
RDA_MAGIC_FACT_UPD_TYPE_FLAG_MASK) ==
|
||||
RDA_MAGIC_FACT_UPD_TYPE_FLAG &&
|
||||
(magic->factUpdateType & RDA_MAGIC_FACT_UPD_TYPE_FACT))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rda_mdcom_ap_factory_update_cmd_valid(void)
|
||||
{
|
||||
RDA_AP_MBX_MAGIC_NUMBER_T *magic =
|
||||
(RDA_AP_MBX_MAGIC_NUMBER_T *)RDA_AP_MBX_MAGIC_NUMBER_ADD;
|
||||
if (magic->factUpdateCmd == RDA_MAGIC_FACT_UPD_CMD_FLAG &&
|
||||
(magic->factUpdateType &
|
||||
RDA_MAGIC_FACT_UPD_TYPE_FLAG_MASK) ==
|
||||
RDA_MAGIC_FACT_UPD_TYPE_FLAG &&
|
||||
(magic->factUpdateType & RDA_MAGIC_FACT_UPD_TYPE_AP_FACT))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Modem log info
|
||||
*/
|
||||
static int rda_mdcom_modem_address_valid(u32 addr)
|
||||
{
|
||||
if ((addr >= RDA_MODEM_INTSRAM_BASE &&
|
||||
addr < RDA_MODEM_INTSRAM_END) ||
|
||||
(addr >= RDA_MODEM_RAM_BASE &&
|
||||
addr < RDA_MODEM_RAM_END)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rda_mdcom_init_all_log_info(void)
|
||||
{
|
||||
/* Init log info */
|
||||
RDA_AP_MBX_LOG_BUF_INFO_T *log =
|
||||
(RDA_AP_MBX_LOG_BUF_INFO_T *)RDA_AP_MBX_LOG_BUF_INFO_ADD;
|
||||
memset(log, 0, sizeof(*log));
|
||||
/* Init modem crash flag */
|
||||
RDA_AP_MBX_MAGIC_NUMBER_T *magic =
|
||||
(RDA_AP_MBX_MAGIC_NUMBER_T *)RDA_AP_MBX_MAGIC_NUMBER_ADD;
|
||||
magic->modemCrashed = 0;
|
||||
magic->factUpdateCmd = 0;
|
||||
magic->factUpdateType = 0;
|
||||
/* Init heartbeat structure members */
|
||||
memset((RDA_AP_MBX_HEARTBEAT_T *)RDA_AP_MBX_HEARTBEAT_ADD, 0,
|
||||
sizeof(RDA_AP_MBX_HEARTBEAT_T));
|
||||
}
|
||||
|
||||
void rda_mdcom_get_modem_log_info(u32 *addr, u32 *len)
|
||||
{
|
||||
RDA_AP_MBX_LOG_BUF_INFO_T *log =
|
||||
(RDA_AP_MBX_LOG_BUF_INFO_T *)RDA_AP_MBX_LOG_BUF_INFO_ADD;
|
||||
u32 log_addr = rda_mdcom_address_modem2ap(log->modemAddr);
|
||||
u32 log_len = log->modemLen;
|
||||
|
||||
/* Check whether the address is valid */
|
||||
if (!rda_mdcom_modem_address_valid(log_addr) ||
|
||||
log_len > RDA_AP_MBX_MAX_MODEM_LOG_LEN) {
|
||||
log_addr = 0;
|
||||
log_len = 0;
|
||||
}
|
||||
|
||||
if (addr)
|
||||
*addr = log_addr;
|
||||
if (len)
|
||||
*len = log_len;
|
||||
}
|
||||
|
||||
void rda_mdcom_get_modem_exception_info(u32 *addr, u32 *len)
|
||||
{
|
||||
RDA_AP_MBX_LOG_BUF_INFO_T *log =
|
||||
(RDA_AP_MBX_LOG_BUF_INFO_T *)RDA_AP_MBX_LOG_BUF_INFO_ADD;
|
||||
u32 exc_addr = RDA_ADD_M2A(log->modemExcAddr);
|
||||
u32 exc_len = log->modemExcLen;
|
||||
|
||||
/* Check whether the address is valid */
|
||||
if (!rda_mdcom_modem_address_valid(exc_addr) ||
|
||||
exc_len > RDA_AP_MBX_MAX_MODEM_EXC_LEN) {
|
||||
exc_addr = 0;
|
||||
exc_len = 0;
|
||||
}
|
||||
|
||||
if (addr)
|
||||
*addr = exc_addr;
|
||||
if (len)
|
||||
*len = exc_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Modem XCPU info
|
||||
*/
|
||||
void rda_mdcom_show_xcpu_info(void)
|
||||
{
|
||||
printf("\n");
|
||||
printf("Modem XCPU info:\n");
|
||||
printf("----------------\n");
|
||||
printf("Cause = 0x%08x\n", hwp_xcpu->cp0_Cause);
|
||||
printf("Status = 0x%08x\n", hwp_xcpu->cp0_Status);
|
||||
printf("BadAddr = 0x%08x\n", hwp_xcpu->cp0_BadVAddr);
|
||||
printf("EPC = 0x%08x\n", hwp_xcpu->cp0_EPC);
|
||||
printf("RA = 0x%08x\n", hwp_xcpu->Regfile_RA);
|
||||
printf("PC = 0x%08x\n", hwp_xcpu->rf0_addr);
|
||||
printf("----------------\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Modem software version info
|
||||
*/
|
||||
void rda_mdcom_show_software_version(void)
|
||||
{
|
||||
int i = 0;
|
||||
char buf[256];
|
||||
char *str;
|
||||
RDA_MODEM_MAP_VERSION_T *version;
|
||||
RDA_MODEM_MAP_MODULE_T *map;
|
||||
RDA_MODEM_MAP_MODULE_T **ptr =
|
||||
(RDA_MODEM_MAP_MODULE_T **)RDA_MODEM_MAP_PTR;
|
||||
|
||||
printf("\n");
|
||||
map = (RDA_MODEM_MAP_MODULE_T *)rda_mdcom_address_modem2ap(
|
||||
(u32)*ptr);
|
||||
if (!ptr || !rda_mdcom_modem_address_valid((u32)map)) {
|
||||
printf("No modem software versions\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Modem software versions:\n");
|
||||
printf("------------------------\n");
|
||||
for (i = 0; i < RDA_MODEM_MAP_QTY; i++, map++) {
|
||||
if (!map->version)
|
||||
continue;
|
||||
version = (RDA_MODEM_MAP_VERSION_T *)
|
||||
rda_mdcom_address_modem2ap((u32)map->version);
|
||||
if (!rda_mdcom_modem_address_valid((u32)version))
|
||||
continue;
|
||||
printf("[%02d]\n", i);
|
||||
printf("revision = %d / 0x %07x\n",
|
||||
version->revision,
|
||||
version->revision);
|
||||
printf("number = %d\n", version->number);
|
||||
printf("date = %d\n", version->date);
|
||||
str = (char *)rda_mdcom_address_modem2ap((u32)version->string);
|
||||
if (version->string &&
|
||||
rda_mdcom_modem_address_valid((u32)str)) {
|
||||
snprintf(buf, sizeof(buf), "%s", str);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
printf("string = %s\n", buf);
|
||||
} else {
|
||||
printf("string = <n/a>\n");
|
||||
}
|
||||
}
|
||||
printf("------------------------\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Communication channels
|
||||
*/
|
||||
static struct rda_mdcom_channel rda_rda_mdcom_chn[] = {
|
||||
/* AT command channel */
|
||||
{
|
||||
RDA_MDCOM_LINE_AT_CMD,
|
||||
RDA_MDCOM_LINE_AT_CMD_FC,
|
||||
(struct rda_mdcom_channel_head*)RDA_MDCOM_CHN_AT_HEAD_ADD_READ,
|
||||
(void *)RDA_MDCOM_CHN_AT_BUF_ADD_READ,
|
||||
RDA_MDCOM_CHN_AT_BUF_LEN_READ-1,
|
||||
(struct rda_mdcom_channel_head*)RDA_MDCOM_CHN_AT_HEAD_ADD_WRITE,
|
||||
(void *)RDA_MDCOM_CHN_AT_BUF_ADD_WRITE,
|
||||
RDA_MDCOM_CHN_AT_BUF_LEN_WRITE-1
|
||||
},
|
||||
|
||||
/* SYSTEM command channel */
|
||||
{
|
||||
RDA_MDCOM_LINE_SYSTEM,
|
||||
RDA_MDCOM_LINE_SYSTEM_FC,
|
||||
(struct rda_mdcom_channel_head*)RDA_MDCOM_CHN_SYS_HEAD_ADD_READ,
|
||||
(void *)RDA_MDCOM_CHN_SYS_BUF_ADD_READ,
|
||||
RDA_MDCOM_CHN_SYS_BUF_LEN_READ-1,
|
||||
(struct rda_mdcom_channel_head*)RDA_MDCOM_CHN_SYS_HEAD_ADD_WRITE,
|
||||
(void *)RDA_MDCOM_CHN_SYS_BUF_ADD_WRITE,
|
||||
RDA_MDCOM_CHN_SYS_BUF_LEN_WRITE-1
|
||||
},
|
||||
|
||||
/* TRACE communciation channel */
|
||||
{
|
||||
RDA_MDCOM_LINE_TRACE,
|
||||
RDA_MDCOM_LINE_TRACE_FC,
|
||||
(struct rda_mdcom_channel_head*)RDA_MDCOM_CHN_TRACE_HEAD_ADD_READ,
|
||||
(void *)RDA_MDCOM_CHN_TRACE_BUF_ADD_READ,
|
||||
RDA_MDCOM_CHN_TRACE_BUF_LEN_READ-1,
|
||||
(struct rda_mdcom_channel_head*)RDA_MDCOM_CHN_TRACE_HEAD_ADD_WRITE,
|
||||
(void *)RDA_MDCOM_CHN_TRACE_BUF_ADD_WRITE,
|
||||
RDA_MDCOM_CHN_TRACE_BUF_LEN_WRITE-1
|
||||
}
|
||||
};
|
||||
|
||||
int rda_mdcom_init_port(int port_id)
|
||||
{
|
||||
switch (port_id) {
|
||||
case RDA_MDCOM_PORT0:
|
||||
hwp_mdComregs->Mask_Set = COMREGS_IRQ0_MASK_SET(0);
|
||||
hwp_mdComregs->Mask_Clr = COMREGS_IRQ0_MASK_CLR(0xFF);
|
||||
hwp_mdComregs->ItReg_Set = COMREGS_IRQ0_SET(0);
|
||||
hwp_mdComregs->ItReg_Clr = COMREGS_IRQ0_CLR(0xFF);
|
||||
return 0;
|
||||
|
||||
case RDA_MDCOM_PORT1:
|
||||
hwp_mdComregs->Mask_Set = COMREGS_IRQ1_MASK_SET(0);
|
||||
hwp_mdComregs->Mask_Clr = COMREGS_IRQ1_MASK_CLR(0xFF);
|
||||
hwp_mdComregs->ItReg_Set = COMREGS_IRQ1_SET(0);
|
||||
hwp_mdComregs->ItReg_Clr = COMREGS_IRQ1_CLR(0xFF);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int rda_mdcom_line_set(int port_id, int line_id)
|
||||
{
|
||||
if (line_id & ~0x7) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (port_id) {
|
||||
case RDA_MDCOM_PORT0:
|
||||
hwp_mdComregs->ItReg_Set = COMREGS_IRQ0_SET(1 << line_id);
|
||||
return 0;
|
||||
|
||||
case RDA_MDCOM_PORT1:
|
||||
hwp_mdComregs->ItReg_Set = COMREGS_IRQ1_SET(1 << line_id);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int rda_mdcom_line_clear(int port_id, int line_id)
|
||||
{
|
||||
if (line_id & ~0x7) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (port_id) {
|
||||
case RDA_MDCOM_PORT0:
|
||||
hwp_mdComregs->ItReg_Clr = COMREGS_IRQ0_CLR(1 << line_id);
|
||||
return 0;
|
||||
|
||||
case RDA_MDCOM_PORT1:
|
||||
hwp_mdComregs->ItReg_Clr = COMREGS_IRQ0_CLR(1 << line_id);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int rda_mdcom_line_set_check(int port_id, int line_id)
|
||||
{
|
||||
if (line_id & ~0x7) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (port_id) {
|
||||
case RDA_MDCOM_PORT0:
|
||||
return !!(hwp_mdComregs->ItReg_Clr & COMREGS_IRQ0_CLR(1 << line_id));
|
||||
|
||||
case RDA_MDCOM_PORT1:
|
||||
return !!(hwp_mdComregs->ItReg_Clr & COMREGS_IRQ1_CLR(1 << line_id));
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int rda_mdcom_line_clear_check(int port_id, int line_id)
|
||||
{
|
||||
if (line_id & ~0x7) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (port_id) {
|
||||
case RDA_MDCOM_PORT0:
|
||||
return !(hwp_mdComregs->ItReg_Set & COMREGS_IRQ0_SET(1 << line_id));
|
||||
|
||||
case RDA_MDCOM_PORT1:
|
||||
return !(hwp_mdComregs->ItReg_Set & COMREGS_IRQ0_SET(1 << line_id));
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int rda_mdcom_line_set_wait(int port_id, int line_id, int waittime)
|
||||
{
|
||||
unsigned long end_time = get_ticks() + waittime;
|
||||
|
||||
if (line_id & ~0x7) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (port_id) {
|
||||
case RDA_MDCOM_PORT0:
|
||||
while (!(hwp_mdComregs->ItReg_Clr & COMREGS_IRQ0_CLR(1 << line_id))) {
|
||||
if ((waittime >= 0) && (end_time <= get_ticks()))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case RDA_MDCOM_PORT1:
|
||||
while (!(hwp_mdComregs->ItReg_Clr & COMREGS_IRQ1_CLR(1 << line_id))) {
|
||||
if ((waittime >= 0) && (end_time <= get_ticks()))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int rda_mdcom_line_clear_wait(int port_id, int line_id, int waittime)
|
||||
{
|
||||
unsigned long end_time = get_ticks() + waittime;
|
||||
|
||||
if (line_id & ~0x7) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (port_id) {
|
||||
case RDA_MDCOM_PORT0:
|
||||
while (hwp_mdComregs->ItReg_Set & COMREGS_IRQ0_SET(1 << line_id)) {
|
||||
if ((waittime >= 0) && (end_time <= get_ticks()))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case RDA_MDCOM_PORT1:
|
||||
while (hwp_mdComregs->ItReg_Set & COMREGS_IRQ0_SET(1 << line_id)) {
|
||||
if ((waittime >= 0) && (end_time <= get_ticks()))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rda_mdcom_port_show(void)
|
||||
{
|
||||
printf("RDA MDCOM ports stauts:\n");
|
||||
printf("REGISTER Cause = 0x%.16x\n", hwp_mdComregs->Cause);
|
||||
printf("REGISTER Mask_Set = 0x%.16x\n", hwp_mdComregs->Mask_Set);
|
||||
printf("REGISTER Mask_Clr = 0x%.16x\n", hwp_mdComregs->Mask_Clr);
|
||||
printf("REGISTER ItReg_Set = 0x%.16x\n", hwp_mdComregs->ItReg_Set);
|
||||
printf("REGISTER ItReg_Clr = 0x%.16x\n", hwp_mdComregs->ItReg_Clr);
|
||||
printf("RDA MDCOM ports stauts end.\n");
|
||||
}
|
||||
|
||||
int rda_mdcom_channel_init(const unsigned int channel)
|
||||
{
|
||||
if (channel >= sizeof(rda_rda_mdcom_chn) / sizeof(struct rda_mdcom_channel)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(rda_rda_mdcom_chn[channel].read_buf_head, 0,
|
||||
sizeof(struct rda_mdcom_channel_head));
|
||||
memset(rda_rda_mdcom_chn[channel].write_buf_head, 0,
|
||||
sizeof(struct rda_mdcom_channel_head));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rda_mdcom_channel_all_init(void)
|
||||
{
|
||||
return rda_mdcom_channel_init(RDA_MDCOM_CHANNEL_AT) ||
|
||||
rda_mdcom_channel_init(RDA_MDCOM_CHANNEL_SYSTEM) ||
|
||||
rda_mdcom_channel_init(RDA_MDCOM_CHANNEL_TRACE);
|
||||
}
|
||||
|
||||
int rda_mdcom_channel_buf_send_stream(const unsigned int channel, void *buf,
|
||||
int size, int waittime)
|
||||
{
|
||||
unsigned long end_time = get_ticks() + waittime;
|
||||
struct rda_mdcom_channel* channel_ptr;
|
||||
struct rda_mdcom_channel_head* channel_head_ptr;
|
||||
int buffer_size_mask;
|
||||
int count = 0;
|
||||
|
||||
if (channel >= sizeof(rda_rda_mdcom_chn) / sizeof(struct rda_mdcom_channel)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
channel_ptr = &rda_rda_mdcom_chn[channel];
|
||||
channel_head_ptr = channel_ptr->write_buf_head;
|
||||
buffer_size_mask = channel_ptr->write_buf_size_mask;
|
||||
|
||||
while (1) {
|
||||
int write_offset = channel_head_ptr->write_offset;
|
||||
int remain_len = (buffer_size_mask + 1) -
|
||||
((write_offset - channel_head_ptr->read_offset) & buffer_size_mask);
|
||||
|
||||
if (remain_len > buffer_size_mask + 1 - write_offset) {
|
||||
remain_len = buffer_size_mask + 1 - write_offset;
|
||||
}
|
||||
|
||||
if (remain_len) {
|
||||
if (remain_len > size) {
|
||||
remain_len = size;
|
||||
}
|
||||
|
||||
memcpy(((char*)channel_ptr->write_buf) + write_offset, buf, remain_len);
|
||||
channel_head_ptr->write_offset = (write_offset + remain_len) & buffer_size_mask;
|
||||
size -= remain_len;
|
||||
buf = (char*)buf + remain_len;
|
||||
count += remain_len;
|
||||
|
||||
if (!size) {
|
||||
return count;
|
||||
}
|
||||
} else if ((waittime >= 0) && (end_time <= get_ticks())) {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rda_mdcom_channel_buf_send_dgram(const unsigned int channel, void *buf,
|
||||
int size, int waittime)
|
||||
{
|
||||
unsigned long end_time = get_ticks() + waittime;
|
||||
struct rda_mdcom_channel* channel_ptr;
|
||||
struct rda_mdcom_channel_head* channel_head_ptr;
|
||||
int buffer_size_mask, write_offset;
|
||||
|
||||
if (channel >= sizeof(rda_rda_mdcom_chn) / sizeof(struct rda_mdcom_channel)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
channel_ptr = &rda_rda_mdcom_chn[channel];
|
||||
channel_head_ptr = channel_ptr->write_buf_head;
|
||||
buffer_size_mask = channel_ptr->write_buf_size_mask;
|
||||
write_offset = ALIGN(channel_head_ptr->write_offset, 4) & buffer_size_mask;
|
||||
|
||||
while (1) {
|
||||
int remain_len = (buffer_size_mask + 1) -
|
||||
((write_offset - channel_head_ptr->read_offset) & buffer_size_mask);
|
||||
|
||||
if (remain_len >= size) {
|
||||
remain_len = buffer_size_mask + 1 - write_offset;
|
||||
|
||||
if (remain_len > size) {
|
||||
remain_len = size;
|
||||
}
|
||||
|
||||
memcpy(((char*)channel_ptr->write_buf) + write_offset, buf,
|
||||
remain_len);
|
||||
|
||||
if (remain_len != size) {
|
||||
memcpy(channel_ptr->write_buf, (char*)buf + remain_len,
|
||||
size - remain_len);
|
||||
}
|
||||
channel_head_ptr->write_offset = (write_offset + size) &
|
||||
buffer_size_mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((waittime >= 0) && (end_time <= get_ticks())) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rda_mdcom_channel_buf_send_available(const unsigned int channel)
|
||||
{
|
||||
struct rda_mdcom_channel* channel_ptr;
|
||||
struct rda_mdcom_channel_head* channel_head_ptr;
|
||||
int buffer_size_mask;
|
||||
int read_offset;
|
||||
int write_offset;
|
||||
|
||||
if (channel >= sizeof(rda_rda_mdcom_chn)/sizeof(struct rda_mdcom_channel)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
channel_ptr = &rda_rda_mdcom_chn[channel];
|
||||
channel_head_ptr = channel_ptr->write_buf_head;
|
||||
buffer_size_mask = channel_ptr->write_buf_size_mask;
|
||||
read_offset = channel_head_ptr->read_offset;
|
||||
write_offset = channel_head_ptr->write_offset;
|
||||
|
||||
return ((buffer_size_mask + 1) - ((write_offset - read_offset) & buffer_size_mask));
|
||||
}
|
||||
|
||||
int rda_mdcom_channel_buf_recv_stream(const unsigned int channel, void *buf,
|
||||
int size, int waittime)
|
||||
{
|
||||
unsigned long end_time = get_ticks() + waittime;
|
||||
struct rda_mdcom_channel* channel_ptr;
|
||||
struct rda_mdcom_channel_head* channel_head_ptr;
|
||||
int buffer_size_mask;
|
||||
int count = 0;
|
||||
int buf_offset = 0;
|
||||
|
||||
if (channel >= sizeof(rda_rda_mdcom_chn) / sizeof(struct rda_mdcom_channel)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
channel_ptr = &rda_rda_mdcom_chn[channel];
|
||||
channel_head_ptr = channel_ptr->read_buf_head;
|
||||
buffer_size_mask = channel_ptr->read_buf_size_mask;
|
||||
|
||||
while (1) {
|
||||
int read_offset = channel_head_ptr->read_offset;
|
||||
int remain_len = channel_head_ptr->write_offset - read_offset;
|
||||
|
||||
if (remain_len < 0) {
|
||||
remain_len = buffer_size_mask + 1 - read_offset;
|
||||
}
|
||||
|
||||
if (remain_len) {
|
||||
if (remain_len > size) {
|
||||
remain_len = size;
|
||||
}
|
||||
|
||||
memcpy((char *)buf + buf_offset, ((char*)channel_ptr->read_buf) + read_offset, remain_len);
|
||||
channel_head_ptr->read_offset = (read_offset + remain_len) &
|
||||
buffer_size_mask;
|
||||
size -= remain_len;
|
||||
count += remain_len;
|
||||
buf_offset += remain_len;
|
||||
|
||||
if (!size) {
|
||||
return count;
|
||||
}
|
||||
} else if ((waittime >= 0) && (end_time <= get_ticks())) {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rda_mdcom_channel_buf_recv_dgram(const unsigned int channel, void *buf,
|
||||
int size, int waittime)
|
||||
{
|
||||
unsigned long end_time = get_ticks() + waittime;
|
||||
struct rda_mdcom_channel* channel_ptr;
|
||||
struct rda_mdcom_channel_head* channel_head_ptr;
|
||||
int buffer_size_mask, read_offset;
|
||||
|
||||
if (channel >= sizeof(rda_rda_mdcom_chn) / sizeof(struct rda_mdcom_channel)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
channel_ptr = &rda_rda_mdcom_chn[channel];
|
||||
channel_head_ptr = channel_ptr->read_buf_head;
|
||||
buffer_size_mask = channel_ptr->read_buf_size_mask;
|
||||
read_offset = ALIGN(channel_head_ptr->read_offset, 4) & buffer_size_mask;
|
||||
|
||||
while (1) {
|
||||
int remain_len = (channel_head_ptr->write_offset - read_offset +
|
||||
buffer_size_mask + 1) & buffer_size_mask;
|
||||
|
||||
if (remain_len >= size) {
|
||||
remain_len = buffer_size_mask + 1 - read_offset;
|
||||
|
||||
if (remain_len > size) {
|
||||
remain_len = size;
|
||||
}
|
||||
|
||||
memcpy(buf, ((char*)channel_ptr->read_buf) + read_offset, remain_len);
|
||||
|
||||
if (remain_len != size) {
|
||||
memcpy(((char *)buf + remain_len), channel_ptr->read_buf, size - remain_len);
|
||||
}
|
||||
channel_head_ptr->read_offset = (read_offset + size) & buffer_size_mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((waittime >= 0) && (end_time <= get_ticks())) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rda_mdcom_channel_buf_recv_available(const unsigned int channel)
|
||||
{
|
||||
struct rda_mdcom_channel* channel_ptr;
|
||||
struct rda_mdcom_channel_head* channel_head_ptr;
|
||||
int buffer_size_mask;
|
||||
int read_offset;
|
||||
int write_offset;
|
||||
|
||||
if (channel >= sizeof(rda_rda_mdcom_chn) / sizeof(struct rda_mdcom_channel)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
channel_ptr = &rda_rda_mdcom_chn[channel];
|
||||
channel_head_ptr = channel_ptr->write_buf_head;
|
||||
buffer_size_mask = channel_ptr->write_buf_size_mask;
|
||||
read_offset = channel_head_ptr->read_offset;
|
||||
write_offset = channel_head_ptr->write_offset;
|
||||
|
||||
return ((write_offset - read_offset) & buffer_size_mask);
|
||||
}
|
||||
|
||||
void rda_mdcom_channel_show(const unsigned int channel)
|
||||
{
|
||||
printf("RDA MDCOM channel %d stauts:\n", channel);
|
||||
|
||||
if (channel >= sizeof(rda_rda_mdcom_chn) / sizeof(struct rda_mdcom_channel)) {
|
||||
printf("Channel number is out of range, ERROR!\n");
|
||||
} else {
|
||||
struct rda_mdcom_channel* channel_ptr = &rda_rda_mdcom_chn[channel];
|
||||
struct rda_mdcom_channel_head* channel_head_ptr;
|
||||
printf("Read buffer head address = 0x%p\n",
|
||||
channel_ptr->read_buf_head);
|
||||
printf("Read buffer address = 0x%p\n",
|
||||
channel_ptr->read_buf);
|
||||
printf("Read buffer length = %d\n",
|
||||
channel_ptr->read_buf_size_mask + 1);
|
||||
channel_head_ptr = channel_ptr->read_buf_head;
|
||||
printf("Read buffer offset read = 0x%x\n",
|
||||
channel_head_ptr->read_offset);
|
||||
printf("Read buffer offset write = 0x%x\n",
|
||||
channel_head_ptr->write_offset);
|
||||
|
||||
printf("Write buffer head address = 0x%p\n",
|
||||
channel_ptr->write_buf_head);
|
||||
printf("Write buffer address = 0x%p\n",
|
||||
channel_ptr->write_buf);
|
||||
printf("Write buffer length = %d\n",
|
||||
channel_ptr->write_buf_size_mask + 1);
|
||||
channel_head_ptr = channel_ptr->write_buf_head;
|
||||
printf("Write buffer offset read = 0x%x\n",
|
||||
channel_head_ptr->read_offset);
|
||||
printf("Write buffer offset write = 0x%x\n",
|
||||
channel_head_ptr->write_offset);
|
||||
}
|
||||
|
||||
printf("RDA MDCOM channel %d stauts end.\n", channel);
|
||||
}
|
||||
|
||||
int rda_mdcom_tstc(const unsigned int channel)
|
||||
{
|
||||
struct rda_mdcom_channel_head* channel_head_ptr;
|
||||
|
||||
if (channel >= sizeof(rda_rda_mdcom_chn) / sizeof(struct rda_mdcom_channel)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
channel_head_ptr = rda_rda_mdcom_chn[channel].read_buf_head;
|
||||
|
||||
return (channel_head_ptr->write_offset != channel_head_ptr->read_offset);
|
||||
}
|
||||
|
||||
int rda_mdcom_getc(const unsigned int channel)
|
||||
{
|
||||
char c = 0;
|
||||
|
||||
rda_mdcom_channel_buf_recv_stream(channel, &c, 1, -1);
|
||||
return c;
|
||||
}
|
||||
|
||||
void rda_mdcom_putc(const char c, const unsigned int channel)
|
||||
{
|
||||
rda_mdcom_channel_buf_send_stream(channel, (void*)&c, 1, -1);
|
||||
}
|
||||
|
||||
void rda_mdcom_puts(const char *s, const unsigned int channel)
|
||||
{
|
||||
rda_mdcom_channel_buf_send_stream(channel, (void*)s, strlen(s), -1);
|
||||
}
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
#include <common.h>
|
||||
#include <asm/u-boot.h>
|
||||
#include <asm/utils.h>
|
||||
#include <nand.h>
|
||||
#include <malloc.h>
|
||||
#include <image.h>
|
||||
#include <usb/usbserial.h>
|
||||
#include <asm/arch/rda_sys.h>
|
||||
#include <asm/arch/rda_crypto.h>
|
||||
#include <pdl.h>
|
||||
|
||||
//#define RDA_CRYPTO_DEBUG
|
||||
|
||||
#ifdef CONFIG_SIGNATURE_CHECK_IMAGE
|
||||
|
||||
struct pubkey_cert_t {
|
||||
struct {
|
||||
uint16_t se_cfg; // vendor_id and key_index
|
||||
uint8_t dummy[94]; // 96
|
||||
struct pubkey pubkey; // +64
|
||||
} c;
|
||||
struct sig signature; // +96
|
||||
};
|
||||
|
||||
struct rda_cert_t {
|
||||
// R&D Certificate:
|
||||
// Create a signature with name[16] =
|
||||
// " R&D-CERT"(10)
|
||||
// "F:0000"(6)
|
||||
// zeros[16] = 0...
|
||||
// Then Hash:
|
||||
// sig.name, zeros, UNIQUE-ID
|
||||
struct sig rnd_cert; // 96
|
||||
|
||||
// free space without sign checking:
|
||||
uint8_t dummy[160]; // 160
|
||||
};
|
||||
|
||||
|
||||
struct rda_se_image {
|
||||
uint8_t spl_code[48128+160];
|
||||
struct sig image_signature; // 96
|
||||
struct rda_cert_t cert; // 256
|
||||
struct pubkey_cert_t vendor_pubkey_cert; // 256
|
||||
};
|
||||
|
||||
#ifdef RDA_CRYPTO_DEBUG
|
||||
# define puts_deb(a) puts(a)
|
||||
#else
|
||||
# define puts_deb(a)
|
||||
# define debug_dump_key_and_signature(h,pk,sig,d,l)
|
||||
#endif
|
||||
|
||||
#ifdef RDA_CRYPTO_DEBUG
|
||||
static void debug_dump_key_and_signature(
|
||||
const char *header, const struct pubkey *pk, const struct sig *sig,
|
||||
const void *data, unsigned data_len)
|
||||
{
|
||||
if (sig) {
|
||||
printf("%s signature:\n", header);
|
||||
rda_dump_buf((char *)sig, 96);
|
||||
}
|
||||
if (pk) {
|
||||
printf("%s public key:\n", header);
|
||||
rda_dump_buf((char *)pk, 64);
|
||||
}
|
||||
if (data) {
|
||||
printf("%s data:\n", header);
|
||||
rda_dump_buf((char *)data, data_len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int check_rnd_certificate(
|
||||
const struct rda_cert_t *certs,
|
||||
const struct pubkey *pubkey,
|
||||
struct spl_security_info *info)
|
||||
{
|
||||
int ret;
|
||||
const struct sig *rnd_signature = &certs->rnd_cert;
|
||||
struct {
|
||||
uint8_t message[32];
|
||||
struct chip_unique_id id;
|
||||
} hashme;
|
||||
|
||||
puts_deb("Checking R&D Certificate\n");
|
||||
|
||||
// create message
|
||||
memset(&hashme, 0, sizeof(hashme));
|
||||
memcpy(hashme.message, rnd_signature->name, 16);
|
||||
hashme.id = info->chip_unique_id;
|
||||
|
||||
// Dump the R&D hashme
|
||||
debug_dump_key_and_signature("R&D hashme", pubkey, rnd_signature,
|
||||
(char *)&hashme, sizeof(hashme));
|
||||
|
||||
ret = signature_check(
|
||||
(const uint8_t*)&hashme, sizeof(hashme),
|
||||
rnd_signature,
|
||||
pubkey);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void get_device_security_context(
|
||||
const struct rda_se_image *image,
|
||||
struct spl_security_info *info)
|
||||
{
|
||||
// Get ROM public key and context
|
||||
info->secure_mode = get_chip_security_context(
|
||||
&info->chip_security_context,
|
||||
&info->pubkey);
|
||||
|
||||
int flags = info->chip_security_context.flags;
|
||||
|
||||
// Fix the return code if security hasn't been enabled
|
||||
if ((flags & RDA_SE_CFG_SECURITY_ENABLE_BIT) == 0) {
|
||||
puts_deb("(Security disabled by efuse flags)\n");
|
||||
info->secure_mode = ROM_API_SECURITY_DISABLED;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we a using the customer public-key certificate
|
||||
if (flags & RDA_SE_CFG_INDIRECT_SIGN_BIT) {
|
||||
const struct pubkey_cert_t *vendor_cert = &image->vendor_pubkey_cert;
|
||||
puts_deb("(Using vendor pkcert as per efuse flags)\n");
|
||||
|
||||
// The vendor pkey cert has already been verified
|
||||
// by the bootrom. For debugging check again here:
|
||||
#ifdef RDA_CRYPTO_DEBUG
|
||||
// Dump the PKCERT data
|
||||
debug_dump_key_and_signature("PKCERT",
|
||||
&info->pubkey, &vendor_cert->signature,
|
||||
&vendor_cert->c, sizeof(vendor_cert->c));
|
||||
|
||||
int ret;
|
||||
ret = signature_check(
|
||||
(uint8_t*)&vendor_cert->c, sizeof(vendor_cert->c),
|
||||
&vendor_cert->signature,
|
||||
&info->pubkey);
|
||||
printf("PKCERT check return %d\n", ret);
|
||||
#endif
|
||||
// copy public key certificate
|
||||
info->pubkey = vendor_cert->c.pubkey;
|
||||
}
|
||||
|
||||
// Sanity check for PKEY
|
||||
if (memcmp(&info->pubkey, "RDASEd", 6) != 0) {
|
||||
puts_deb("(Public key for signature check invalid)\n");
|
||||
info->secure_mode = -1; // better: ROM_API_SECURITY_INVALID_PKEY
|
||||
return;
|
||||
}
|
||||
|
||||
// Dump the keys and signature when debugging
|
||||
debug_dump_key_and_signature("PDL1 -",
|
||||
&info->pubkey, &image->image_signature, NULL, 0);
|
||||
|
||||
// Check if device is in R&D mode
|
||||
int rnd_status = check_rnd_certificate(&image->cert, &info->pubkey, info);
|
||||
if (rnd_status == 0) {
|
||||
puts("(R&D mode override) ");
|
||||
// ... and disable security...
|
||||
info->secure_mode = ROM_API_SECURITY_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int set_security_context(struct spl_security_info *info, const void *_image)
|
||||
{
|
||||
const struct rda_se_image *image = _image;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
if (memcmp(romapi->magic, "RDA API", 8) != 0) {
|
||||
puts("Board security: Not present\n");
|
||||
info->secure_mode = ROM_API_SECURITY_UNAVAILABLE;
|
||||
}
|
||||
else {
|
||||
puts("Board security: present ");
|
||||
|
||||
info->version = romapi->version;
|
||||
get_chip_id(&info->chip_id);
|
||||
get_chip_true_random(info->random, 32);
|
||||
get_chip_unique(&info->chip_unique_id);
|
||||
|
||||
get_device_security_context(image, info);
|
||||
|
||||
switch (info->secure_mode) {
|
||||
case ROM_API_SECURITY_ENABLED:
|
||||
puts("and enabled.\n");
|
||||
break;
|
||||
case ROM_API_SECURITY_DISABLED:
|
||||
puts("but disabled.\n");
|
||||
break;
|
||||
case ROM_API_INVALID_KEYINDEX:
|
||||
case ROM_API_INVALID_VENDOR_ID:
|
||||
puts("but has invalid key-index or vendor-id!\n");
|
||||
break;
|
||||
default:
|
||||
puts("but has invalid configuration!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return info->secure_mode;
|
||||
}
|
||||
|
||||
int image_sign_verify(const uint8_t *buffer, uint32_t len)
|
||||
{
|
||||
spl_bd_t *spl_board_info = (spl_bd_t *)CONFIG_SPL_BOARD_INFO_ADDR;
|
||||
struct spl_security_info *info = &spl_board_info->spl_security_info;
|
||||
|
||||
len -= sizeof(struct sig);
|
||||
const struct sig *signature = (const struct sig *)(buffer + len);
|
||||
|
||||
puts("Verify image:\n");
|
||||
|
||||
// Check security mode
|
||||
int secure_mode = info->secure_mode;
|
||||
switch (secure_mode) {
|
||||
case ROM_API_SECURITY_ENABLED:
|
||||
// Check the signature of the image
|
||||
debug_dump_key_and_signature("bootloader -",
|
||||
&info->pubkey, signature, NULL, 0);
|
||||
return signature_check(buffer, len, signature, &info->pubkey);
|
||||
case ROM_API_SECURITY_DISABLED:
|
||||
case ROM_API_SECURITY_UNAVAILABLE:
|
||||
return 0;
|
||||
default:
|
||||
return secure_mode; // This is != 0 -> verify error
|
||||
}
|
||||
}
|
||||
|
||||
int image_sign_verify_uimage(image_header_t *hdr)
|
||||
{
|
||||
return image_sign_verify((const uint8_t *)hdr,
|
||||
image_get_image_size(hdr) + sizeof(struct sig));
|
||||
}
|
||||
|
||||
#else
|
||||
int set_security_context(struct spl_security_info *info, const void *_image)
|
||||
{
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
if (memcmp(romapi->magic, "RDA API", 8) == 0) {
|
||||
puts("Board security: present ");
|
||||
|
||||
info->version = romapi->version;
|
||||
get_chip_unique(&info->chip_unique_id);
|
||||
}
|
||||
return ROM_API_SECURITY_DISABLED;
|
||||
}
|
||||
|
||||
int image_sign_verify(const uint8_t *buffer, uint32_t len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Warning:
|
||||
*
|
||||
* This file is a mess of debugging and ROM bug workarounds.
|
||||
*/
|
||||
|
||||
/* Enable a workaround for a bug in the bootrom romapi. */
|
||||
#define RDA8810_VENDOR_EFUSE_WORKAROUND
|
||||
|
||||
/* Enable debugging certificates in pdl1: */
|
||||
//#define RDA_CRYPTO_DEBUG_FAKE_ROMCERT
|
||||
|
||||
|
||||
|
||||
#ifdef RDA_CRYPTO_DEBUG_FAKE_ROMCERT
|
||||
/*
|
||||
* Debugging version og get_chip_security_context().
|
||||
* This version is enabled with RDA_CRYPTO_DEBUG_FAKE_ROMCERT
|
||||
*
|
||||
TEST DATA
|
||||
Use this secret key (file: rdatest.sec, pw: pa$$w0rd):
|
||||
|
||||
"Comment: RDA PDL-Test-01 secret key
|
||||
UkRBU0VkQksAAAAq0Ai4xjiIrmda3G8qI6q3B4gPbVQMPISmUkRBIFBETC1UZXN0LTAxACU+PXqYnPYI
|
||||
gGYdDrpN5PljQAAht3pYTN4bNgtA6oRp/sEVIrSXZiEkZPRGsnqlGPGFRHn3MMsDZBz/FhZGdE1m2FnD
|
||||
YYgQMg=="
|
||||
*/
|
||||
int get_chip_security_context(
|
||||
struct chip_security_context *context,
|
||||
struct pubkey *pubkey)
|
||||
{
|
||||
const struct chip_security_context c = {
|
||||
3, 0x42,
|
||||
RDA_SE_CFG_SECURITY_ENABLE_BIT |
|
||||
RDA_SE_CFG_INDIRECT_SIGN_BIT |
|
||||
RDA_SE_CFG_UNLOCK_ALLOWED
|
||||
};
|
||||
const struct pubkey pk = {
|
||||
/* Public key: rdatest.pub */
|
||||
{'R','D','A','S'}, {'E','d'},{}, "RDA PDL-Test-01 ",
|
||||
{ 0x25,0x3e,0x3d,0x7a,0x98,0x9c,0xf6,0x08 },
|
||||
{ 0x7b,0x4a,0x5a,0xa8,0xa1,0xda,0x92,0xea,0x9e,0x90,0xa8,0x7e,
|
||||
0xfa,0x76,0x37,0x52,0xe0,0xe0,0x40,0x63,0x09,0x02,0xd3,0x86,
|
||||
0x8b,0x9d,0xe0,0xae,0xf3,0x57,0xd7,0x44 }
|
||||
};
|
||||
|
||||
// Set the hardcoded debug public key and context
|
||||
*context = c;
|
||||
*pubkey = pk;
|
||||
|
||||
return ROM_API_SECURITY_ENABLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef RDA8810_VENDOR_EFUSE_WORKAROUND
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/rda_crypto.h>
|
||||
#include <asm/arch/ispi.h>
|
||||
|
||||
#define RDA_EFUSE_INDEX_SECURITY (11)
|
||||
|
||||
/*
|
||||
Fuse layout:
|
||||
VVVVVVVV.T.H.I.S.KKKK
|
||||
VVVVVVVV: Vendor ID - 6bit + 2bit armour
|
||||
T: Trace disable
|
||||
H: Host serial disable
|
||||
I: Indirectly signed image
|
||||
S: Security enable
|
||||
KKKK: RDA Public Key Index - 3bit + 1 bit armour
|
||||
*/
|
||||
/* define bit for rda se config */
|
||||
#define RDA_SE_CFG_KEY_INDEX(n) (((n)&0xF)<<0)
|
||||
#define RDA_SE_CFG_GET_KEY_INDEX(r) (((r)>>0)&0xF)
|
||||
#define RDA_SE_CFG_SECURITY_ENABLE_BIT (1<<4)
|
||||
#define RDA_SE_CFG_INDIRECT_SIGN_BIT (1<<5)
|
||||
#define RDA_SE_CFG_HOST_DISABLE_BIT (1<<6)
|
||||
#define RDA_SE_CFG_TRACE_DISABLE_BIT (1<<7)
|
||||
#define RDA_SE_CFG_VENDOR_ID(n) (((n)&0xFF)<<8)
|
||||
#define RDA_SE_CFG_GET_VENDOR_ID(r) (((r)>>8)&0xFF)
|
||||
|
||||
// RDA Public Key index map
|
||||
// (armour 6 indexes in 4 bits)
|
||||
static const uint8_t keyindex_map[16] = {
|
||||
15, 15, 15, 0, 15, 1, 2, 15,
|
||||
15, 3, 4, 15, 5, 15, 15, 15
|
||||
};
|
||||
|
||||
// Vendor ID
|
||||
// (armour 50 vendor ID'd in 8 bits)
|
||||
static int valid_vendor_id( unsigned vendor )
|
||||
{
|
||||
unsigned c;
|
||||
unsigned i = vendor >> 2;
|
||||
c = ((i & 0xaa)>>1) + (i & 0x55);
|
||||
c = ((c & 0xcc)>>2) + (c & 0x33);
|
||||
c = ((c & 0xf0)>>4) + (c & 0x0f);
|
||||
return ((vendor & 3) + c) == 5;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef RDA_CRYPTO_DEBUG_FAKE_ROMCERT
|
||||
int get_chip_security_context(
|
||||
struct chip_security_context *context,
|
||||
struct pubkey *pubkey)
|
||||
{
|
||||
int ret = romapi->get_chip_security_context(context, pubkey);
|
||||
|
||||
#ifdef RDA8810_VENDOR_EFUSE_WORKAROUND
|
||||
if (ret == ROM_API_INVALID_VENDOR_ID && romapi->version == 100) {
|
||||
uint16_t sec = rda_read_efuse(RDA_EFUSE_INDEX_SECURITY);
|
||||
|
||||
// check validity of key index
|
||||
int key = keyindex_map[RDA_SE_CFG_GET_KEY_INDEX(sec)];
|
||||
|
||||
// check validity of vendor id
|
||||
int vendor = RDA_SE_CFG_GET_VENDOR_ID(sec);
|
||||
if (valid_vendor_id(vendor)) {
|
||||
context->rda_key_index = key;
|
||||
context->vendor_id = vendor;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,507 @@
|
|||
#include <common.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/reg_sysctrl.h>
|
||||
#include <asm/arch/reg_md_sysctrl.h>
|
||||
#include <asm/arch/reg_cfg_regs.h>
|
||||
#include <asm/arch/reg_keypad.h>
|
||||
#include <asm/arch/reg_gpio.h>
|
||||
#include <asm/arch/hwcfg.h>
|
||||
#include <asm/arch/ispi.h>
|
||||
#include <asm/arch/reg_md_sysctrl.h>
|
||||
#include <asm/arch/hwcfg.h>
|
||||
#include <asm/arch/rda_sys.h>
|
||||
#include <asm/arch/spl_board_info.h>
|
||||
#ifdef CONFIG_CMD_MISC
|
||||
#include <usb/usbserial.h>
|
||||
#include <asm/arch/mdcom.h>
|
||||
#endif
|
||||
|
||||
#define RDA_AP_MBX_HWCFG_SWCFG_ADD (RDA_MD_MAILBOX_BASE + 0x1AE0)
|
||||
#define RDA_HWCFG_SWCFG (*(u32 *)RDA_AP_MBX_HWCFG_SWCFG_ADD)
|
||||
|
||||
/*
|
||||
* Hardware and software configuration
|
||||
*/
|
||||
void hwcfg_swcfg_init(void)
|
||||
{
|
||||
u16 hwcfg, swcfg;
|
||||
|
||||
RDA_HWCFG_SWCFG = hwp_sysCtrlMd->Reset_Cause;
|
||||
|
||||
hwcfg = rda_hwcfg_reg_get();
|
||||
swcfg = rda_swcfg_reg_get();
|
||||
|
||||
/* clear the sw boot modes handled by bootloader */
|
||||
rda_swcfg_reg_set(swcfg & ~(RDA_SW_CFG_BIT_2 |
|
||||
RDA_SW_CFG_BIT_3 |
|
||||
RDA_SW_CFG_BIT_4 |
|
||||
RDA_SW_CFG_BIT_5 |
|
||||
RDA_SW_CFG_BIT_6));
|
||||
|
||||
/* clear the hw boot modes for download/factory modes */
|
||||
rda_hwcfg_reg_set(hwcfg & ~(RDA_HW_CFG_BIT_10 |
|
||||
RDA_HW_CFG_BIT_11 |
|
||||
RDA_HW_CFG_BIT_12 |
|
||||
RDA_HW_CFG_BIT_13 |
|
||||
RDA_HW_CFG_BIT_14 |
|
||||
RDA_HW_CFG_BIT_15));
|
||||
|
||||
}
|
||||
|
||||
void rda_hwcfg_reg_set(u16 hwcfg)
|
||||
{
|
||||
hwp_sysCtrlMd->Reset_Cause = SET_BITFIELD(hwp_sysCtrlMd->Reset_Cause,
|
||||
SYS_CTRL_BOOT_MODE, hwcfg);
|
||||
hwp_sysCtrlAp->Reset_Cause = hwp_sysCtrlMd->Reset_Cause;
|
||||
}
|
||||
|
||||
u16 rda_hwcfg_reg_get(void)
|
||||
{
|
||||
u16 hwcfg = GET_BITFIELD(hwp_sysCtrlMd->Reset_Cause, SYS_CTRL_BOOT_MODE);
|
||||
return hwcfg;
|
||||
}
|
||||
|
||||
u16 rda_hwcfg_get(void)
|
||||
{
|
||||
u16 hwcfg = GET_BITFIELD(RDA_HWCFG_SWCFG, SYS_CTRL_BOOT_MODE);
|
||||
return hwcfg;
|
||||
}
|
||||
|
||||
void rda_swcfg_reg_set(u16 swcfg)
|
||||
{
|
||||
hwp_sysCtrlMd->Reset_Cause = SET_BITFIELD(hwp_sysCtrlMd->Reset_Cause,
|
||||
SYS_CTRL_SW_BOOT_MODE, swcfg);
|
||||
hwp_sysCtrlAp->Reset_Cause = hwp_sysCtrlMd->Reset_Cause;
|
||||
}
|
||||
|
||||
u16 rda_swcfg_reg_get(void)
|
||||
{
|
||||
u16 swcfg = GET_BITFIELD(hwp_sysCtrlMd->Reset_Cause, SYS_CTRL_SW_BOOT_MODE);
|
||||
return swcfg;
|
||||
}
|
||||
|
||||
u16 rda_swcfg_get(void)
|
||||
{
|
||||
u16 swcfg = GET_BITFIELD(RDA_HWCFG_SWCFG, SYS_CTRL_SW_BOOT_MODE);
|
||||
return swcfg;
|
||||
}
|
||||
|
||||
u16 rda_prod_id_get(void)
|
||||
{
|
||||
u16 prod_id = GET_BITFIELD(hwp_configRegs->CHIP_ID, CFG_REGS_PROD_ID);
|
||||
return prod_id;
|
||||
}
|
||||
|
||||
u16 rda_metal_id_get(void)
|
||||
{
|
||||
u16 metal_id = GET_BITFIELD(hwp_configRegs->CHIP_ID, CFG_REGS_METAL_ID);
|
||||
return metal_id;
|
||||
}
|
||||
|
||||
u16 rda_bond_id_get(void)
|
||||
{
|
||||
u16 bond_id = GET_BITFIELD(hwp_configRegs->CHIP_ID, CFG_REGS_BOND_ID);
|
||||
return bond_id;
|
||||
}
|
||||
|
||||
void rda_nand_iodrive_set(void)
|
||||
{
|
||||
u32 value = hwp_configRegs->IO_Drive1_Select & (~ CFG_REGS_NFLSH_DRIVE_MASK);
|
||||
|
||||
hwp_configRegs->IO_Drive1_Select = value | CFG_REGS_NFLSH_DRIVE_SLOW_AND_WEAK;
|
||||
}
|
||||
|
||||
/*
|
||||
* System-level control
|
||||
*/
|
||||
enum media_type rda_media_get(void)
|
||||
{
|
||||
#ifdef CONFIG_SDMMC_BOOT
|
||||
return MEDIA_MMC;
|
||||
#else
|
||||
u16 hwcfg = rda_hwcfg_get();
|
||||
#ifdef CONFIG_MACH_RDA8810H
|
||||
/*
|
||||
* HW BOOT MODE
|
||||
*
|
||||
* BIT_2 BIT1 BIT0 MODE
|
||||
* 0 0 0 emmc
|
||||
* 0 0 1 spi nand
|
||||
* 0 1 0 spi nor
|
||||
* 0 1 1 t-card0(run)
|
||||
* 1 0 0 t-card1(update)
|
||||
* 1 0 1 nand 8bit
|
||||
* 1 1 0 nand 16bit
|
||||
* 1 1 1 reserved
|
||||
*/
|
||||
u32 bm_media = RDA_HW_CFG_GET_BM_IDX(hwcfg);
|
||||
|
||||
if (bm_media == RDA_MODE_EMMC)
|
||||
return MEDIA_MMC;
|
||||
else if (bm_media == RDA_MODE_SPINAND)
|
||||
return MEDIA_SPINAND;
|
||||
else if ((bm_media == RDA_MODE_NAND_8BIT)
|
||||
|| (bm_media == RDA_MODE_NAND_16BIT))
|
||||
return MEDIA_NAND;
|
||||
#else
|
||||
u16 metal_id = rda_metal_id_get();
|
||||
u16 prod_id = rda_prod_id_get();
|
||||
u16 metal_new_bm;
|
||||
|
||||
if (prod_id == 0x8810)
|
||||
metal_new_bm = 0xB;
|
||||
else if (prod_id == 0x810E || prod_id == 0x8850 || prod_id == 0x850E)
|
||||
metal_new_bm = 0x2;
|
||||
else
|
||||
metal_new_bm = 0;
|
||||
|
||||
if (metal_id < metal_new_bm) {
|
||||
/* SDMMC or SPI NAND */
|
||||
if (hwcfg & RDA_HW_CFG_BIT_3) {
|
||||
if (hwcfg & RDA_HW_CFG_BIT_7)
|
||||
return MEDIA_MMC;
|
||||
else
|
||||
return MEDIA_NAND;
|
||||
} else if (hwcfg & RDA_HW_CFG_BIT_4) {
|
||||
return MEDIA_MMC;
|
||||
}
|
||||
/* EMMC */
|
||||
if (hwcfg & RDA_HW_CFG_BIT_2)
|
||||
return MEDIA_MMC;
|
||||
/* PARALLEL NAND */
|
||||
if (!(hwcfg & RDA_HW_CFG_BIT_4))
|
||||
return MEDIA_NAND;
|
||||
|
||||
} else {
|
||||
/* SPI NAND */
|
||||
if (hwcfg & RDA_HW_CFG_BIT_3)
|
||||
return MEDIA_NAND;
|
||||
/* EMMC */
|
||||
if (hwcfg & RDA_HW_CFG_BIT_2)
|
||||
return MEDIA_MMC;
|
||||
/* PARALLEL NAND */
|
||||
if (!(hwcfg & RDA_HW_CFG_BIT_4))
|
||||
return MEDIA_NAND;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return MEDIA_UNKNOWN;
|
||||
}
|
||||
|
||||
void reset_cpu(ulong addr)
|
||||
{
|
||||
#ifdef CONFIG_RDA_PDL
|
||||
enable_charger(1);
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
/* to unlock first */
|
||||
hwp_sysCtrlMd->REG_DBG = 0xa50001;
|
||||
/* reset */
|
||||
hwp_sysCtrlMd->Sys_Rst_Set |= SYS_CTRL_SOFT_RST;
|
||||
}
|
||||
}
|
||||
|
||||
void shutdown_system(void)
|
||||
{
|
||||
#ifdef CONFIG_RDA_PDL
|
||||
enable_charger(1);
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
/* to unlock first */
|
||||
hwp_sysCtrlMd->REG_DBG = 0xa50001;
|
||||
/* shutdown */
|
||||
hwp_sysCtrlMd->WakeUp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int rda_bm_is_calib(void)
|
||||
{
|
||||
u16 swcfg = rda_swcfg_get();
|
||||
return !!(swcfg & RDA_SW_CFG_BIT_4);
|
||||
}
|
||||
|
||||
int rda_bm_is_autocall(void)
|
||||
{
|
||||
u16 swcfg = rda_swcfg_get();
|
||||
return !!(swcfg & RDA_SW_CFG_BIT_5);
|
||||
}
|
||||
|
||||
int rda_bm_is_download(void)
|
||||
{
|
||||
#ifdef CONFIG_RDA_PDL /* for PDL mode, always enable download mode */
|
||||
return 1;
|
||||
#else
|
||||
u16 hwcfg = rda_hwcfg_get();
|
||||
return !!(hwcfg & RDA_HW_CFG_BIT_11);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if download keys are pressed. */
|
||||
int rda_bm_download_key_pressed(void)
|
||||
{
|
||||
int key_power = !!(hwp_apKeypad->KP_STATUS & KEYPAD_KP_ON);
|
||||
int key_vol_up = !!(hwp_apGpioD->gpio_val & 0x40); /* GPIO D6 */
|
||||
#ifdef CONFIG_SDMMC_BOOT
|
||||
int key_vol_down = !!(hwp_apGpioD->gpio_val & 0x20); /* GPIO D5 */
|
||||
return (key_power && key_vol_up && !key_vol_down);
|
||||
#else
|
||||
return (key_power && key_vol_up);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rda_reboot(enum reboot_type type)
|
||||
{
|
||||
u16 hwcfg = rda_hwcfg_reg_get();
|
||||
u16 swcfg = rda_swcfg_reg_get();
|
||||
int key_vol_down;
|
||||
|
||||
hwcfg &= ~(RDA_HW_CFG_BIT_10 | RDA_HW_CFG_BIT_11 |
|
||||
RDA_HW_CFG_BIT_12 | RDA_HW_CFG_BIT_13 |
|
||||
RDA_HW_CFG_BIT_14 | RDA_HW_CFG_BIT_15);
|
||||
|
||||
switch (type) {
|
||||
case REBOOT_TO_DOWNLOAD_MODE:
|
||||
hwcfg |= RDA_HW_CFG_BIT_11 | RDA_HW_CFG_BIT_12 |
|
||||
RDA_HW_CFG_BIT_14;
|
||||
key_vol_down = !!(hwp_apGpioD->gpio_val & 0x20); /* GPIO D5 */
|
||||
if (key_vol_down)
|
||||
hwcfg |= RDA_HW_CFG_BIT_10 | RDA_HW_CFG_BIT_13;
|
||||
break;
|
||||
case REBOOT_TO_FASTBOOT_MODE:
|
||||
swcfg |= RDA_SW_CFG_BIT_2;
|
||||
break;
|
||||
case REBOOT_TO_RECOVERY_MODE:
|
||||
swcfg |= RDA_SW_CFG_BIT_3;
|
||||
break;
|
||||
case REBOOT_TO_CALIB_MODE:
|
||||
swcfg |= RDA_SW_CFG_BIT_4;
|
||||
break;
|
||||
case REBOOT_TO_PDL2_MODE:
|
||||
swcfg |= RDA_SW_CFG_BIT_6;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rda_hwcfg_reg_set(hwcfg);
|
||||
rda_swcfg_reg_set(swcfg);
|
||||
reset_cpu(0);
|
||||
}
|
||||
|
||||
void enable_vibrator(int enable)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
ispi_open(1);
|
||||
|
||||
value = ispi_reg_read(0x03);
|
||||
|
||||
if (enable)
|
||||
value |= 0x20;
|
||||
else
|
||||
value &= ~0x20;
|
||||
if (rda_metal_id_get() >= 9)
|
||||
value ^= 0x20;
|
||||
|
||||
ispi_reg_write(0x03, value);
|
||||
|
||||
ispi_open(0);
|
||||
}
|
||||
|
||||
void enable_charger(int enable)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
ispi_open(1);
|
||||
val = ispi_reg_read(0x15);
|
||||
if (enable) {
|
||||
val &= ~((1 << 15) | (1 << 14));
|
||||
} else {
|
||||
val |= (1 << 15);
|
||||
val &= ~(1 << 14);
|
||||
}
|
||||
ispi_reg_write(0x15, val);
|
||||
ispi_open(0);
|
||||
}
|
||||
|
||||
void rda_dump_buf(char *data, size_t len)
|
||||
{
|
||||
char temp_buf[64];
|
||||
size_t i, off = 0;
|
||||
|
||||
memset(temp_buf, 0, 64);
|
||||
for (i=0;i<len;i++) {
|
||||
if(i%8 == 0) {
|
||||
sprintf(&temp_buf[off], " ");
|
||||
off += 2;
|
||||
}
|
||||
sprintf(&temp_buf[off], "%02x ", data[i]);
|
||||
off += 3;
|
||||
if((i+1)%16 == 0 || (i+1) == len) {
|
||||
printf("%8d %s\n", (unsigned int)i/16,temp_buf);
|
||||
memset(temp_buf, 0, 64);
|
||||
off = 0;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void print_cur_time(void)
|
||||
{
|
||||
unsigned long long time = ticks2usec(get_ticks());
|
||||
printf("\n****** [CURRENT TIME: %3d.%06d] ******\n\n",
|
||||
(int)(time / 1000000),
|
||||
(int)(time % 1000000));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_MISC
|
||||
|
||||
int usb_cable_connected(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
ispi_open(1);
|
||||
val = ispi_reg_read(0x14);
|
||||
ispi_open(0);
|
||||
if (val & (1 << 8))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int system_rebooted(void)
|
||||
{
|
||||
static int system_rebooted_flag = -1;
|
||||
|
||||
if (system_rebooted_flag == -1) {
|
||||
if (rda_mdcom_system_started_before())
|
||||
system_rebooted_flag = 1;
|
||||
else
|
||||
system_rebooted_flag = 0;
|
||||
rda_mdcom_set_system_started_flag();
|
||||
}
|
||||
return system_rebooted_flag;
|
||||
}
|
||||
|
||||
static int boot_key_long_pressed = 0;
|
||||
|
||||
void save_current_boot_key_state(void)
|
||||
{
|
||||
int boot_key_on = ((hwp_apKeypad->KP_STATUS & KEYPAD_KP_ON) != 0);
|
||||
int start_by_boot_key = ((rda_hwcfg_get() & RDA_HW_CFG_BIT_12) != 0);
|
||||
boot_key_long_pressed = (boot_key_on && start_by_boot_key);
|
||||
}
|
||||
|
||||
int get_saved_boot_key_state(void)
|
||||
{
|
||||
return boot_key_long_pressed;
|
||||
}
|
||||
|
||||
void get_board_serial(struct tag_serialnr *serialnr)
|
||||
{
|
||||
struct spl_security_info *info = get_bd_spl_security_info();
|
||||
const uint32_t *id256 = (uint32_t *)info->chip_unique_id.id;
|
||||
|
||||
serialnr->low = id256[0];
|
||||
serialnr->high = id256[1];
|
||||
|
||||
if ((serialnr->low | serialnr->high) == 0) {
|
||||
serialnr->low = 0x90abcdef;
|
||||
serialnr->high = 0x12345678;
|
||||
}
|
||||
|
||||
/* Set serialno enviroment variable */
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%08x%08x", serialnr->high, serialnr->low);
|
||||
setenv("serialno", tmp);
|
||||
}
|
||||
|
||||
static int boot_mode = RDA_BM_NORMAL;
|
||||
|
||||
void rda_bm_init(void)
|
||||
{
|
||||
u16 hwcfg = rda_hwcfg_get();
|
||||
u16 swcfg = rda_swcfg_get();
|
||||
#ifndef CONFIG_RDA_PDL
|
||||
int rebooted = system_rebooted();
|
||||
u32 fastboot_key_mask, all_key_mask;
|
||||
#endif
|
||||
char str[2];
|
||||
struct tag_serialnr serialnr;
|
||||
get_board_serial(&serialnr);
|
||||
|
||||
printf("RDA: HW_CFG 0x%04x\n", hwcfg);
|
||||
printf("RDA: SW_CFG 0x%04x\n", swcfg);
|
||||
printf("RDA: ID PROD %04x M %03x B %01x\n",
|
||||
rda_prod_id_get(), rda_metal_id_get(),
|
||||
rda_bond_id_get());
|
||||
|
||||
#ifdef CONFIG_RDA_PDL
|
||||
/* PDL: always enable download mode */
|
||||
boot_mode = RDA_BM_FORCEDOWNLOAD;
|
||||
#else
|
||||
/* SPL */
|
||||
boot_mode = RDA_BM_NORMAL;
|
||||
|
||||
if (swcfg & RDA_SW_CFG_BIT_2) {
|
||||
boot_mode = RDA_BM_FASTBOOT;
|
||||
} else if (swcfg & RDA_SW_CFG_BIT_3) {
|
||||
boot_mode = RDA_BM_RECOVERY;
|
||||
} else if (swcfg & RDA_SW_CFG_BIT_4) {
|
||||
boot_mode = RDA_BM_CALIB;
|
||||
} else if (swcfg & RDA_SW_CFG_BIT_5) {
|
||||
boot_mode = RDA_BM_AUTOCALL;
|
||||
} else if (swcfg & RDA_SW_CFG_BIT_6) {
|
||||
/* force to 'pdl2', called by kernel */
|
||||
boot_mode = RDA_BM_FORCEDOWNLOAD;
|
||||
} else if ((hwcfg & RDA_HW_CFG_BIT_10) && (hwcfg & RDA_HW_CFG_BIT_11)) {
|
||||
/*
|
||||
* If power key, vol-up, and vol-down are all pressed, consider
|
||||
* it as normal boot (for T-Card)
|
||||
*/
|
||||
boot_mode = RDA_BM_NORMAL;
|
||||
} else if ((hwcfg & RDA_HW_CFG_BIT_10) && !rebooted) {
|
||||
/* Distinguish between factory mode and h/w force reset */
|
||||
boot_mode = RDA_BM_FACTORY;
|
||||
} else if (hwcfg & RDA_HW_CFG_BIT_11) {
|
||||
/* Force download mode for pdl2 */
|
||||
boot_mode = RDA_BM_FORCEDOWNLOAD;
|
||||
} else if (usb_cable_connected()) {
|
||||
all_key_mask = RDA_HW_CFG_BIT_15 | RDA_HW_CFG_BIT_14 |
|
||||
RDA_HW_CFG_BIT_13 | RDA_HW_CFG_BIT_12 |
|
||||
RDA_HW_CFG_BIT_11 | RDA_HW_CFG_BIT_10;
|
||||
/* Fastboot keys are volume-up + volume-down keys */
|
||||
fastboot_key_mask = RDA_HW_CFG_BIT_13 | RDA_HW_CFG_BIT_14;
|
||||
|
||||
if ((hwcfg & fastboot_key_mask) == fastboot_key_mask &&
|
||||
(hwcfg & all_key_mask & ~fastboot_key_mask) == 0) {
|
||||
/*
|
||||
* All the keys are up, except for the fastboot keys;
|
||||
* and the usb cable is plugged in
|
||||
*/
|
||||
boot_mode = RDA_BM_FASTBOOT;
|
||||
}
|
||||
}
|
||||
#endif /* !CONFIG_RDA_PDL */
|
||||
|
||||
printf("RDA: Boot_Mode %d\n", boot_mode);
|
||||
|
||||
sprintf(str, "%1d", boot_mode);
|
||||
setenv ("bootmode", str);
|
||||
}
|
||||
|
||||
enum rda_bm_type rda_bm_get(void)
|
||||
{
|
||||
return boot_mode;
|
||||
}
|
||||
|
||||
void rda_bm_set(enum rda_bm_type bm)
|
||||
{
|
||||
boot_mode = bm;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_CMD_MISC */
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/rda_iomap.h>
|
||||
#include <asm/arch/reg_sysctrl.h>
|
||||
#include <asm/arch/reg_uart.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void _serial_set_baudrate(int rate)
|
||||
{
|
||||
hwp_sysCtrlAp->Cfg_Clk_Uart[2] = 0x36; // 115200 @ 26MHz
|
||||
//hwp_sysCtrlAp->Cfg_Clk_Uart[2] = 0x05; // 921600 @ 26MHz
|
||||
}
|
||||
|
||||
void _serial_enable_rtscts(void)
|
||||
{
|
||||
hwp_uart->ctrl |= UART_AUTO_FLOW_CONTROL;
|
||||
}
|
||||
|
||||
void _serial_disable_rtscts(void)
|
||||
{
|
||||
hwp_uart->ctrl &= ~UART_AUTO_FLOW_CONTROL;
|
||||
}
|
||||
|
||||
void _serial_init(void)
|
||||
{
|
||||
_serial_set_baudrate(CONFIG_BAUDRATE);
|
||||
hwp_uart->triggers = UART_AFC_LEVEL(1); //7 ?
|
||||
|
||||
hwp_uart->ctrl = UART_ENABLE | UART_DATA_BITS_8_BITS |
|
||||
UART_TX_STOP_BITS_1_BIT | UART_PARITY_ENABLE_NO;
|
||||
|
||||
/* Allow reception */
|
||||
hwp_uart->CMD_Set = UART_RTS;
|
||||
}
|
||||
|
||||
void _serial_deinit(void)
|
||||
{
|
||||
hwp_uart->ctrl = 0;
|
||||
hwp_uart->CMD_Clr = UART_RTS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether a character is in the RX buffer
|
||||
*/
|
||||
int _serial_tstc(const int port)
|
||||
{
|
||||
return (GET_BITFIELD(hwp_uart->status, UART_RX_FIFO_LEVEL));
|
||||
}
|
||||
|
||||
int _serial_getc(const int port)
|
||||
{
|
||||
/* wait for character to arrive */ ;
|
||||
while (!(GET_BITFIELD(hwp_uart->status, UART_RX_FIFO_LEVEL)))
|
||||
;
|
||||
|
||||
return (hwp_uart->rxtx_buffer & 0xff);
|
||||
}
|
||||
|
||||
void _serial_putc_hw(const char c, const int port)
|
||||
{
|
||||
// Place in the TX Fifo ?
|
||||
while (!(GET_BITFIELD(hwp_uart->status, UART_TX_FIFO_SPACE)))
|
||||
;
|
||||
hwp_uart->rxtx_buffer = (u32)c;
|
||||
}
|
||||
|
||||
void _serial_putc(const char c, const int port)
|
||||
{
|
||||
if (c == '\n') {
|
||||
_serial_putc_hw('\r', 0);
|
||||
}
|
||||
_serial_putc_hw(c, 0);
|
||||
}
|
||||
|
||||
void _serial_puts(const char *s, const int port)
|
||||
{
|
||||
while (*s) {
|
||||
_serial_putc(*s++, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int hwflow = 0; /* turned off by default */
|
||||
int hwflow_onoff(int on)
|
||||
{
|
||||
switch(on) {
|
||||
case 0:
|
||||
default:
|
||||
break; /* return current */
|
||||
case 1:
|
||||
hwflow = 1;
|
||||
_serial_enable_rtscts(); /* turn on */
|
||||
break;
|
||||
case -1:
|
||||
hwflow = 0;
|
||||
_serial_disable_rtscts(); /* turn off */
|
||||
break;
|
||||
}
|
||||
return hwflow;
|
||||
}
|
||||
|
||||
int serial_init(void)
|
||||
{
|
||||
//_serial_init(); // already init in boot_test
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serial_getc(void)
|
||||
{
|
||||
return _serial_getc(0);
|
||||
}
|
||||
|
||||
int serial_tstc(void)
|
||||
{
|
||||
return _serial_tstc(0);
|
||||
}
|
||||
|
||||
void serial_putc(const char c)
|
||||
{
|
||||
_serial_putc(c, 0);
|
||||
}
|
||||
|
||||
void serial_puts(const char *s)
|
||||
{
|
||||
_serial_puts(s, 0);
|
||||
}
|
||||
|
||||
void serial_setbrg (void)
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
#include <common.h>
|
||||
#include <asm/u-boot.h>
|
||||
#include <asm/utils.h>
|
||||
#include <nand.h>
|
||||
#include <malloc.h>
|
||||
#include <image.h>
|
||||
#include <usb/usbserial.h>
|
||||
#include <asm/arch/rda_sys.h>
|
||||
#include <asm/arch/spl_board_info.h>
|
||||
#include <asm/arch/rda_crypto.h>
|
||||
#include <pdl.h>
|
||||
|
||||
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
/* Define global data structure pointer to it*/
|
||||
static gd_t gdata __attribute__ ((section(".data")));
|
||||
static bd_t bdata __attribute__ ((section(".data")));
|
||||
|
||||
#else
|
||||
|
||||
void puts(const char *str)
|
||||
{
|
||||
while (*str)
|
||||
putc(*str++);
|
||||
}
|
||||
|
||||
void putc(char c)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SPL_LIBCOMMON_SUPPORT */
|
||||
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
relocate_code(CONFIG_SPL_STACK, NULL, CONFIG_SPL_TEXT_BASE);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPL_CHECK_IMAGE
|
||||
int check_uimage(unsigned int *buf)
|
||||
{
|
||||
image_header_t *hdr = (image_header_t *)buf;
|
||||
puts("Check Image ");
|
||||
if (!image_check_magic(hdr)) {
|
||||
printf("Magic Error %x\n", image_get_magic(hdr));
|
||||
rda_dump_buf((char *)buf, 256);
|
||||
return -1;
|
||||
}
|
||||
puts(".");
|
||||
if (!image_check_hcrc(hdr)) {
|
||||
printf("HCRC Error %x\n", image_get_hcrc(hdr));
|
||||
rda_dump_buf((char *)buf, 256);
|
||||
return -2;
|
||||
}
|
||||
puts(".");
|
||||
if (!image_check_dcrc(hdr)) {
|
||||
printf("DCRC Error %x\n", image_get_dcrc(hdr));
|
||||
rda_dump_buf((char *)buf, 256);
|
||||
//rda_dump_buf(buf,
|
||||
// image_get_header_size() + image_get_size(hdr));
|
||||
return -3;
|
||||
}
|
||||
puts(".");
|
||||
#ifdef CONFIG_SIGNATURE_CHECK_IMAGE
|
||||
if (image_sign_verify_uimage(hdr) != 0) {
|
||||
printf("Image Signature check failed!\n");
|
||||
return -4;
|
||||
}
|
||||
#endif
|
||||
puts(" Done\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPL_EMMC_LOAD
|
||||
extern void emmc_init(void);
|
||||
extern void emmc_boot(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPL_XMODEM_LOAD
|
||||
extern void xmodem_boot(void);
|
||||
#endif
|
||||
|
||||
extern void hwcfg_swcfg_init(void);
|
||||
extern int clock_init(void);
|
||||
|
||||
|
||||
#ifdef CONFIG_SIGNATURE_CHECK_IMAGE
|
||||
static const uint8_t *get_spl_load_addr(void)
|
||||
{
|
||||
const uint8_t *spl_image = (uint8_t*)CONFIG_SPL_LOAD_ADDRESS + CONFIG_UIMAGEHDR_SIZE;
|
||||
return spl_image;
|
||||
}
|
||||
#endif
|
||||
|
||||
void board_init_r(gd_t *id, ulong dummy)
|
||||
{
|
||||
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
|
||||
gd = &gdata;
|
||||
gd->bd = &bdata;
|
||||
gd->flags |= GD_FLG_RELOC;
|
||||
gd->baudrate = CONFIG_BAUDRATE;
|
||||
serial_init(); /* serial communications setup */
|
||||
gd->have_console = 1;
|
||||
#endif
|
||||
hwcfg_swcfg_init();
|
||||
clock_init();
|
||||
|
||||
#ifdef CONFIG_SIGNATURE_CHECK_IMAGE
|
||||
// Set the security contex (or get the unique ID of the device)
|
||||
struct spl_security_info *info = get_bd_spl_security_info();
|
||||
const uint8_t *spl_image = get_spl_load_addr();
|
||||
|
||||
puts("SETTING SECURITY CONTEXT\n");
|
||||
set_security_context(info, spl_image);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_RDA_PDL
|
||||
/* Note BIT3 for SPINAND got higher priority */
|
||||
#ifdef CONFIG_SPL_EMMC_SUPPORT
|
||||
if (rda_media_get() == MEDIA_MMC) {
|
||||
puts("Init emmc ...\n");
|
||||
emmc_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPL_NAND_SUPPORT
|
||||
if (rda_media_get() == MEDIA_NAND || rda_media_get() == MEDIA_SPINAND) {
|
||||
puts("Init nand ...\n");
|
||||
nand_init();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RDA_PDL
|
||||
drv_usbser_init();
|
||||
pdl_main();
|
||||
#else
|
||||
/* A workaround to handle the timing issue when detecting
|
||||
* download mode in h/w */
|
||||
if( !rda_bm_is_autocall() &&
|
||||
!rda_bm_is_calib() &&
|
||||
!rda_bm_is_download() &&
|
||||
rda_bm_download_key_pressed()) {
|
||||
puts("Download key pressed. Enter download mode ...\n");
|
||||
rda_reboot(REBOOT_TO_DOWNLOAD_MODE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPL_EMMC_LOAD
|
||||
if (rda_media_get() == MEDIA_MMC) {
|
||||
puts("EMMC boot ...\n");
|
||||
emmc_boot();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPL_NAND_LOAD
|
||||
if (rda_media_get() == MEDIA_NAND || rda_media_get() == MEDIA_SPINAND) {
|
||||
puts("NAND boot ...\n");
|
||||
nand_boot();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPL_SPI_LOAD
|
||||
mem_malloc_init(CONFIG_SYS_TEXT_BASE - CONFIG_SYS_MALLOC_LEN,
|
||||
CONFIG_SYS_MALLOC_LEN);
|
||||
|
||||
gd = &gdata;
|
||||
gd->bd = &bdata;
|
||||
gd->flags |= GD_FLG_RELOC;
|
||||
gd->baudrate = CONFIG_BAUDRATE;
|
||||
serial_init(); /* serial communications setup */
|
||||
gd->have_console = 1;
|
||||
|
||||
puts("SPI boot...\n");
|
||||
spi_boot();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPL_XMODEM_LOAD
|
||||
puts("Xmodem boot ...\n");
|
||||
xmodem_boot();
|
||||
#endif
|
||||
|
||||
/*
|
||||
should never go here
|
||||
*/
|
||||
while(1)
|
||||
;
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/rda_iomap.h>
|
||||
#include <asm/arch/reg_timer.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
typedef union
|
||||
{
|
||||
unsigned long long timer;
|
||||
struct
|
||||
{
|
||||
unsigned long timer_l :32;
|
||||
unsigned long timer_h :32;
|
||||
} fields;
|
||||
} RDA_TIMER;
|
||||
|
||||
#if (CONFIG_SYS_HZ_CLOCK == 2000000)
|
||||
/* optimize for 2M Hz */
|
||||
static unsigned long tick_to_ms(unsigned long long tick) __attribute__((unused));
|
||||
static unsigned long tick_to_ms(unsigned long long tick)
|
||||
{
|
||||
return (u32)(tick >> 11); // divide 2048
|
||||
}
|
||||
|
||||
static unsigned long long ms_to_tick(unsigned long ms)
|
||||
{
|
||||
return (((unsigned long long)ms) << 11); // x 2048
|
||||
}
|
||||
|
||||
static unsigned long tick_to_us(unsigned long long tick)
|
||||
{
|
||||
return (unsigned long)(tick >> 1); // divide 2
|
||||
}
|
||||
|
||||
static unsigned long long us_to_tick(unsigned long ms)
|
||||
{
|
||||
return (((unsigned long long)ms) << 1); // x2
|
||||
}
|
||||
#else
|
||||
/* need to calc */
|
||||
#error "Timer is not 2M Hz"
|
||||
#endif
|
||||
|
||||
static void rda_timer_get(RDA_TIMER *timer)
|
||||
{
|
||||
/* always read low 32bit first */
|
||||
timer->fields.timer_l =
|
||||
(unsigned long)(hwp_apTimer->HWTimer_LockVal_L);
|
||||
timer->fields.timer_h =
|
||||
(unsigned long)(hwp_apTimer->HWTimer_LockVal_H);
|
||||
}
|
||||
|
||||
static void rda_timeout_setup_ms(RDA_TIMER *timer, unsigned long ms)
|
||||
__attribute__((unused));
|
||||
static void rda_timeout_setup_ms(RDA_TIMER *timer, unsigned long ms)
|
||||
{
|
||||
timer->timer = get_ticks() + ms_to_tick(ms);
|
||||
}
|
||||
|
||||
static void rda_timeout_setup_us(RDA_TIMER *timer, unsigned long us)
|
||||
{
|
||||
timer->timer = get_ticks() + us_to_tick(us);
|
||||
}
|
||||
|
||||
static int rda_timeout_check(RDA_TIMER *timer)
|
||||
{
|
||||
return (get_ticks() > timer->timer);
|
||||
}
|
||||
|
||||
int timer_init(void)
|
||||
{
|
||||
gd->timer_rate_hz = CONFIG_SYS_HZ_CLOCK;
|
||||
gd->timer_reset_value = 0;
|
||||
|
||||
/* We are using timer34 in unchained 32-bit mode, full speed */
|
||||
return(0);
|
||||
}
|
||||
|
||||
void reset_timer(void)
|
||||
{
|
||||
gd->timer_reset_value = get_ticks();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current 64 bit timer tick count
|
||||
*/
|
||||
unsigned long long get_ticks(void)
|
||||
{
|
||||
RDA_TIMER timer;
|
||||
|
||||
rda_timer_get(&timer);
|
||||
return timer.timer;
|
||||
}
|
||||
|
||||
ulong usec2ticks (unsigned long usec)
|
||||
{
|
||||
return (ulong)us_to_tick(usec);
|
||||
}
|
||||
|
||||
ulong ticks2usec (unsigned long ticks)
|
||||
{
|
||||
return tick_to_us(ticks);
|
||||
}
|
||||
|
||||
ulong get_timer(ulong base)
|
||||
{
|
||||
unsigned long long timer_diff;
|
||||
|
||||
timer_diff = get_ticks() - gd->timer_reset_value;
|
||||
|
||||
return (timer_diff / (gd->timer_rate_hz / CONFIG_SYS_HZ)) - base;
|
||||
}
|
||||
|
||||
void __udelay(unsigned long usec)
|
||||
{
|
||||
RDA_TIMER timer;
|
||||
|
||||
rda_timeout_setup_us(&timer, usec);
|
||||
while(!rda_timeout_check(&timer))
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
return CONFIG_SYS_HZ_CLOCK;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/u-boot.h>
|
||||
#include <asm/utils.h>
|
||||
#include <xyzModem.h>
|
||||
|
||||
void _serial_enable_rtscts(void);
|
||||
#ifdef CONFIG_SPL_CHECK_IMAGE
|
||||
int check_uimage(unsigned int *buf);
|
||||
#endif
|
||||
|
||||
static int getcxmodem(void) {
|
||||
if (tstc())
|
||||
return (getc());
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ulong load_serial_xmodem (ulong offset)
|
||||
{
|
||||
int size;
|
||||
int err;
|
||||
int res;
|
||||
connection_info_t info;
|
||||
char ymodemBuf[1024];
|
||||
ulong store_addr = ~0;
|
||||
ulong addr = 0;
|
||||
|
||||
size = 0;
|
||||
info.mode = xyzModem_xmodem;
|
||||
_serial_enable_rtscts();
|
||||
mdelay(10);
|
||||
res = xyzModem_stream_open (&info, &err);
|
||||
if (!res) {
|
||||
while ((res =
|
||||
xyzModem_stream_read (ymodemBuf, 1024, &err)) > 0) {
|
||||
store_addr = addr + offset;
|
||||
size += res;
|
||||
addr += res;
|
||||
memcpy ((char *) (store_addr), ymodemBuf,res);
|
||||
}
|
||||
} else {
|
||||
printf ("%s\n", xyzModem_error (err));
|
||||
}
|
||||
|
||||
xyzModem_stream_close (&err);
|
||||
xyzModem_stream_terminate (false, &getcxmodem);
|
||||
|
||||
|
||||
flush_cache (offset, size);
|
||||
printf("\nXmodem Download Success.\n");
|
||||
printf("Total Size = 0x%08x = %d Bytes\n", size, size);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void xmodem_boot(void)
|
||||
{
|
||||
__attribute__((noreturn)) void (*uboot)(void);
|
||||
|
||||
load_serial_xmodem(CONFIG_SYS_XMODEM_U_BOOT_DST);
|
||||
|
||||
#ifdef CONFIG_SPL_CHECK_IMAGE
|
||||
if (check_uimage((unsigned int*)CONFIG_SYS_XMODEM_U_BOOT_DST)) {
|
||||
printf("Xmodem boot failed.\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Jump to U-Boot image
|
||||
*/
|
||||
printf("Running U-Boot ...\n");
|
||||
uboot = (void *)CONFIG_SYS_XMODEM_U_BOOT_START;
|
||||
(*uboot)();
|
||||
}
|
|
@ -25,20 +25,22 @@
|
|||
|
||||
.align 5
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#ifndef CONFIG_SYS_L2CACHE_OFF
|
||||
.global v7_outer_cache_enable
|
||||
v7_outer_cache_enable:
|
||||
ENTRY(v7_outer_cache_enable)
|
||||
push {r0, r1, r2, lr}
|
||||
mrc 15, 0, r3, cr1, cr0, 1
|
||||
orr r3, r3, #2
|
||||
mcr 15, 0, r3, cr1, cr0, 1
|
||||
pop {r1, r2, r3, pc}
|
||||
ENDPROC(v7_outer_cache_enable)
|
||||
|
||||
.global v7_outer_cache_disable
|
||||
v7_outer_cache_disable:
|
||||
ENTRY(v7_outer_cache_disable)
|
||||
push {r0, r1, r2, lr}
|
||||
mrc 15, 0, r3, cr1, cr0, 1
|
||||
bic r3, r3, #2
|
||||
mcr 15, 0, r3, cr1, cr0, 1
|
||||
pop {r1, r2, r3, pc}
|
||||
ENDPROC(v7_outer_cache_disable)
|
||||
#endif
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
*/
|
||||
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#define S5PC100_SWRESET 0xE0200000
|
||||
#define S5PC110_SWRESET 0xE0102000
|
||||
|
||||
.globl reset_cpu
|
||||
reset_cpu:
|
||||
ENTRY(reset_cpu)
|
||||
ldr r1, =S5PC100_PRO_ID
|
||||
ldr r2, [r1]
|
||||
ldr r4, =0x00010000
|
||||
|
@ -45,3 +45,4 @@ reset_cpu:
|
|||
str r2, [r1]
|
||||
_loop_forever:
|
||||
b _loop_forever
|
||||
ENDPROC(reset_cpu)
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
|
||||
#include <asm-offsets.h>
|
||||
#include <config.h>
|
||||
#include <version.h>
|
||||
#include <asm/system.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.globl _start
|
||||
_start: b reset
|
||||
|
@ -158,7 +158,11 @@ reset:
|
|||
|
||||
/* Set stackpointer in internal RAM to call board_init_f */
|
||||
call_board_init_f:
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
ldr sp, =(CONFIG_SPL_STACK)
|
||||
#else
|
||||
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
|
||||
#endif
|
||||
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
|
||||
ldr r0,=0x00000000
|
||||
bl board_init_f
|
||||
|
@ -172,8 +176,7 @@ call_board_init_f:
|
|||
* after relocating the monitor code.
|
||||
*
|
||||
*/
|
||||
.globl relocate_code
|
||||
relocate_code:
|
||||
ENTRY(relocate_code)
|
||||
mov r4, r0 /* save addr_sp */
|
||||
mov r5, r1 /* save addr of gd */
|
||||
mov r6, r2 /* save addr of destination */
|
||||
|
@ -257,12 +260,17 @@ clear_bss:
|
|||
add r0, r0, r4
|
||||
add r1, r1, r4
|
||||
#endif
|
||||
|
||||
cmp r0, r1
|
||||
beq clbss_d
|
||||
|
||||
mov r2, #0x00000000 /* clear */
|
||||
|
||||
clbss_l:str r2, [r0] /* clear loop... */
|
||||
add r0, r0, #4
|
||||
cmp r0, r1
|
||||
bne clbss_l
|
||||
clbss_d:
|
||||
|
||||
/*
|
||||
* We are done. Do not return, instead branch to second part of board
|
||||
|
@ -289,6 +297,7 @@ jump_2_ram:
|
|||
|
||||
_board_init_r_ofs:
|
||||
.word board_init_r - _start
|
||||
ENDPROC(relocate_code)
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
|
@ -298,8 +307,7 @@ _board_init_r_ofs:
|
|||
* CONFIG_SYS_ICACHE_OFF is defined.
|
||||
*
|
||||
*************************************************************************/
|
||||
.globl cpu_init_cp15
|
||||
cpu_init_cp15:
|
||||
ENTRY(cpu_init_cp15)
|
||||
/*
|
||||
* Invalidate L1 I/D
|
||||
*/
|
||||
|
@ -325,7 +333,7 @@ cpu_init_cp15:
|
|||
#endif
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
mov pc, lr @ back to my caller
|
||||
|
||||
ENDPROC(cpu_init_cp15)
|
||||
|
||||
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
|
||||
/*************************************************************************
|
||||
|
@ -336,7 +344,7 @@ cpu_init_cp15:
|
|||
* setup memory timing
|
||||
*
|
||||
*************************************************************************/
|
||||
cpu_init_crit:
|
||||
ENTRY(cpu_init_crit)
|
||||
/*
|
||||
* Jump to board specific initialization...
|
||||
* The Mask ROM will have already initialized
|
||||
|
@ -347,6 +355,7 @@ cpu_init_crit:
|
|||
bl lowlevel_init @ go setup pll,mux,memory
|
||||
mov lr, ip @ restore link
|
||||
mov pc, lr @ back to my caller
|
||||
ENDPROC(cpu_init_crit)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
# flags for any startup files it might use.
|
||||
CFLAGS_arch/arm/cpu/armv7/tegra2/ap20.o += -march=armv4t
|
||||
CFLAGS_arch/arm/cpu/armv7/tegra2/clock.o += -march=armv4t
|
||||
CFLAGS_arch/arm/cpu/armv7/tegra2/warmboot_avp.o += -march=armv4t
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
|
||||
|
@ -34,7 +35,10 @@ LIB = $(obj)lib$(SOC).o
|
|||
|
||||
SOBJS := lowlevel_init.o
|
||||
COBJS-y := ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o
|
||||
COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
|
||||
COBJS-$(CONFIG_TEGRA_PMU) += pmu.o
|
||||
COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o
|
||||
COBJS-$(CONFIG_TEGRA2_LP0) += crypto.o warmboot.o warmboot_avp.o
|
||||
|
||||
COBJS := $(COBJS-y)
|
||||
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
|
||||
|
|
|
@ -21,16 +21,53 @@
|
|||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "ap20.h"
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/tegra2.h>
|
||||
#include <asm/arch/ap20.h>
|
||||
#include <asm/arch/clk_rst.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/fuse.h>
|
||||
#include <asm/arch/gp_padctrl.h>
|
||||
#include <asm/arch/pmc.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/scu.h>
|
||||
#include <asm/arch/warmboot.h>
|
||||
#include <common.h>
|
||||
|
||||
int tegra_get_chip_type(void)
|
||||
{
|
||||
struct apb_misc_gp_ctlr *gp;
|
||||
struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE;
|
||||
uint tegra_sku_id, rev;
|
||||
|
||||
/*
|
||||
* This is undocumented, Chip ID is bits 15:8 of the register
|
||||
* APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for
|
||||
* Tegra30
|
||||
*/
|
||||
gp = (struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE;
|
||||
rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT;
|
||||
|
||||
tegra_sku_id = readl(&fuse->sku_info) & 0xff;
|
||||
|
||||
switch (rev) {
|
||||
case CHIPID_TEGRA2:
|
||||
switch (tegra_sku_id) {
|
||||
case SKU_ID_T20:
|
||||
return TEGRA_SOC_T20;
|
||||
case SKU_ID_T25SE:
|
||||
case SKU_ID_AP25:
|
||||
case SKU_ID_T25:
|
||||
case SKU_ID_AP25E:
|
||||
case SKU_ID_T25E:
|
||||
return TEGRA_SOC_T25;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* unknown sku id */
|
||||
return TEGRA_SOC_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */
|
||||
static int ap20_cpu_is_cortexa9(void)
|
||||
{
|
||||
|
@ -286,6 +323,11 @@ void init_pmc_scratch(void)
|
|||
|
||||
/* ODMDATA is for kernel use to determine RAM size, LP config, etc. */
|
||||
writel(CONFIG_SYS_BOARD_ODMDATA, &pmc->pmc_scratch20);
|
||||
|
||||
#ifdef CONFIG_TEGRA2_LP0
|
||||
/* save Sdram params to PMC 2, 4, and 24 for WB0 */
|
||||
warmboot_save_sdram_params();
|
||||
#endif
|
||||
}
|
||||
|
||||
void tegra2_start(void)
|
||||
|
|
|
@ -23,12 +23,12 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include "ap20.h"
|
||||
#include <asm/arch/ap20.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/funcmux.h>
|
||||
#include <asm/arch/pmc.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/arch/tegra2.h>
|
||||
#include <asm/arch/pmc.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
|
|
@ -410,6 +410,16 @@ enum clock_osc_freq clock_get_osc_freq(void)
|
|||
return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
|
||||
}
|
||||
|
||||
int clock_get_osc_bypass(void)
|
||||
{
|
||||
struct clk_rst_ctlr *clkrst =
|
||||
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
|
||||
u32 reg;
|
||||
|
||||
reg = readl(&clkrst->crc_osc_ctrl);
|
||||
return (reg & OSC_XOBP_MASK) >> OSC_XOBP_SHIFT;
|
||||
}
|
||||
|
||||
/* Returns a pointer to the registers of the given pll */
|
||||
static struct clk_pll *get_pll(enum clock_id clkid)
|
||||
{
|
||||
|
@ -420,6 +430,28 @@ static struct clk_pll *get_pll(enum clock_id clkid)
|
|||
return &clkrst->crc_pll[clkid];
|
||||
}
|
||||
|
||||
int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
|
||||
u32 *divp, u32 *cpcon, u32 *lfcon)
|
||||
{
|
||||
struct clk_pll *pll = get_pll(clkid);
|
||||
u32 data;
|
||||
|
||||
assert(clkid != CLOCK_ID_USB);
|
||||
|
||||
/* Safety check, adds to code size but is small */
|
||||
if (!clock_id_isvalid(clkid) || clkid == CLOCK_ID_USB)
|
||||
return -1;
|
||||
data = readl(&pll->pll_base);
|
||||
*divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
|
||||
*divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT;
|
||||
*divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
|
||||
data = readl(&pll->pll_misc);
|
||||
*cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT;
|
||||
*lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
|
||||
u32 divp, u32 cpcon, u32 lfcon)
|
||||
{
|
||||
|
@ -1027,7 +1059,10 @@ void clock_early_init(void)
|
|||
clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
|
||||
break;
|
||||
|
||||
case CLOCK_OSC_FREQ_13_0:
|
||||
case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */
|
||||
clock_set_rate(CLOCK_ID_PERIPH, 432, 13, 1, 8);
|
||||
clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8);
|
||||
break;
|
||||
case CLOCK_OSC_FREQ_19_2:
|
||||
default:
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The Chromium OS Authors.
|
||||
* (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.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/errno.h>
|
||||
#include "crypto.h"
|
||||
#include "aes.h"
|
||||
|
||||
static u8 zero_key[16];
|
||||
|
||||
#define AES_CMAC_CONST_RB 0x87 /* from RFC 4493, Figure 2.2 */
|
||||
|
||||
enum security_op {
|
||||
SECURITY_SIGN = 1 << 0, /* Sign the data */
|
||||
SECURITY_ENCRYPT = 1 << 1, /* Encrypt the data */
|
||||
};
|
||||
|
||||
static void debug_print_vector(char *name, u32 num_bytes, u8 *data)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
debug("%s [%d] @0x%08x", name, num_bytes, (u32)data);
|
||||
for (i = 0; i < num_bytes; i++) {
|
||||
if (i % 16 == 0)
|
||||
debug(" = ");
|
||||
debug("%02x", data[i]);
|
||||
if ((i+1) % 16 != 0)
|
||||
debug(" ");
|
||||
}
|
||||
debug("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply chain data to the destination using EOR
|
||||
*
|
||||
* Each array is of length AES_AES_KEY_LENGTH.
|
||||
*
|
||||
* \param cbc_chain_data Chain data
|
||||
* \param src Source data
|
||||
* \param dst Destination data, which is modified here
|
||||
*/
|
||||
static void apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
*dst++ = *src++ ^ *cbc_chain_data++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt some data with AES.
|
||||
*
|
||||
* \param key_schedule Expanded key to use
|
||||
* \param src Source data to encrypt
|
||||
* \param dst Destination buffer
|
||||
* \param num_aes_blocks Number of AES blocks to encrypt
|
||||
*/
|
||||
static void encrypt_object(u8 *key_schedule, u8 *src, u8 *dst,
|
||||
u32 num_aes_blocks)
|
||||
{
|
||||
u8 tmp_data[AES_KEY_LENGTH];
|
||||
u8 *cbc_chain_data;
|
||||
u32 i;
|
||||
|
||||
cbc_chain_data = zero_key; /* Convenient array of 0's for IV */
|
||||
|
||||
for (i = 0; i < num_aes_blocks; i++) {
|
||||
debug("encrypt_object: block %d of %d\n", i, num_aes_blocks);
|
||||
debug_print_vector("AES Src", AES_KEY_LENGTH, src);
|
||||
|
||||
/* Apply the chain data */
|
||||
apply_cbc_chain_data(cbc_chain_data, src, tmp_data);
|
||||
debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data);
|
||||
|
||||
/* encrypt the AES block */
|
||||
aes_encrypt(tmp_data, key_schedule, dst);
|
||||
debug_print_vector("AES Dst", AES_KEY_LENGTH, dst);
|
||||
|
||||
/* Update pointers for next loop. */
|
||||
cbc_chain_data = dst;
|
||||
src += AES_KEY_LENGTH;
|
||||
dst += AES_KEY_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift a vector left by one bit
|
||||
*
|
||||
* \param in Input vector
|
||||
* \param out Output vector
|
||||
* \param size Length of vector in bytes
|
||||
*/
|
||||
static void left_shift_vector(u8 *in, u8 *out, int size)
|
||||
{
|
||||
int carry = 0;
|
||||
int i;
|
||||
|
||||
for (i = size - 1; i >= 0; i--) {
|
||||
out[i] = (in[i] << 1) | carry;
|
||||
carry = in[i] >> 7; /* get most significant bit */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign a block of data, putting the result into dst.
|
||||
*
|
||||
* \param key Input AES key, length AES_KEY_LENGTH
|
||||
* \param key_schedule Expanded key to use
|
||||
* \param src Source data of length 'num_aes_blocks' blocks
|
||||
* \param dst Destination buffer, length AES_KEY_LENGTH
|
||||
* \param num_aes_blocks Number of AES blocks to encrypt
|
||||
*/
|
||||
static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst,
|
||||
u32 num_aes_blocks)
|
||||
{
|
||||
u8 tmp_data[AES_KEY_LENGTH];
|
||||
u8 left[AES_KEY_LENGTH];
|
||||
u8 k1[AES_KEY_LENGTH];
|
||||
u8 *cbc_chain_data;
|
||||
unsigned i;
|
||||
|
||||
cbc_chain_data = zero_key; /* Convenient array of 0's for IV */
|
||||
|
||||
/* compute K1 constant needed by AES-CMAC calculation */
|
||||
for (i = 0; i < AES_KEY_LENGTH; i++)
|
||||
tmp_data[i] = 0;
|
||||
|
||||
encrypt_object(key_schedule, tmp_data, left, 1);
|
||||
debug_print_vector("AES(key, nonce)", AES_KEY_LENGTH, left);
|
||||
|
||||
left_shift_vector(left, k1, sizeof(left));
|
||||
debug_print_vector("L", AES_KEY_LENGTH, left);
|
||||
|
||||
if ((left[0] >> 7) != 0) /* get MSB of L */
|
||||
k1[AES_KEY_LENGTH-1] ^= AES_CMAC_CONST_RB;
|
||||
debug_print_vector("K1", AES_KEY_LENGTH, k1);
|
||||
|
||||
/* compute the AES-CMAC value */
|
||||
for (i = 0; i < num_aes_blocks; i++) {
|
||||
/* Apply the chain data */
|
||||
apply_cbc_chain_data(cbc_chain_data, src, tmp_data);
|
||||
|
||||
/* for the final block, XOR K1 into the IV */
|
||||
if (i == num_aes_blocks - 1)
|
||||
apply_cbc_chain_data(tmp_data, k1, tmp_data);
|
||||
|
||||
/* encrypt the AES block */
|
||||
aes_encrypt(tmp_data, key_schedule, dst);
|
||||
|
||||
debug("sign_obj: block %d of %d\n", i, num_aes_blocks);
|
||||
debug_print_vector("AES-CMAC Src", AES_KEY_LENGTH, src);
|
||||
debug_print_vector("AES-CMAC Xor", AES_KEY_LENGTH, tmp_data);
|
||||
debug_print_vector("AES-CMAC Dst", AES_KEY_LENGTH, dst);
|
||||
|
||||
/* Update pointers for next loop. */
|
||||
cbc_chain_data = dst;
|
||||
src += AES_KEY_LENGTH;
|
||||
}
|
||||
|
||||
debug_print_vector("AES-CMAC Hash", AES_KEY_LENGTH, dst);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt and sign a block of data (depending on security mode).
|
||||
*
|
||||
* \param key Input AES key, length AES_KEY_LENGTH
|
||||
* \param oper Security operations mask to perform (enum security_op)
|
||||
* \param src Source data
|
||||
* \param length Size of source data
|
||||
* \param sig_dst Destination address for signature, AES_KEY_LENGTH bytes
|
||||
*/
|
||||
static int encrypt_and_sign(u8 *key, enum security_op oper, u8 *src,
|
||||
u32 length, u8 *sig_dst)
|
||||
{
|
||||
u32 num_aes_blocks;
|
||||
u8 key_schedule[AES_EXPAND_KEY_LENGTH];
|
||||
|
||||
debug("encrypt_and_sign: length = %d\n", length);
|
||||
debug_print_vector("AES key", AES_KEY_LENGTH, key);
|
||||
|
||||
/*
|
||||
* The only need for a key is for signing/checksum purposes, so
|
||||
* if not encrypting, expand a key of 0s.
|
||||
*/
|
||||
aes_expand_key(oper & SECURITY_ENCRYPT ? key : zero_key, key_schedule);
|
||||
|
||||
num_aes_blocks = (length + AES_KEY_LENGTH - 1) / AES_KEY_LENGTH;
|
||||
|
||||
if (oper & SECURITY_ENCRYPT) {
|
||||
/* Perform this in place, resulting in src being encrypted. */
|
||||
debug("encrypt_and_sign: begin encryption\n");
|
||||
encrypt_object(key_schedule, src, src, num_aes_blocks);
|
||||
debug("encrypt_and_sign: end encryption\n");
|
||||
}
|
||||
|
||||
if (oper & SECURITY_SIGN) {
|
||||
/* encrypt the data, overwriting the result in signature. */
|
||||
debug("encrypt_and_sign: begin signing\n");
|
||||
sign_object(key, key_schedule, src, sig_dst, num_aes_blocks);
|
||||
debug("encrypt_and_sign: end signing\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sign_data_block(u8 *source, unsigned length, u8 *signature)
|
||||
{
|
||||
return encrypt_and_sign(zero_key, SECURITY_SIGN, source,
|
||||
length, signature);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The Chromium OS Authors.
|
||||
* (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTO_H_
|
||||
#define _CRYPTO_H_
|
||||
|
||||
/**
|
||||
* Sign a block of data
|
||||
*
|
||||
* \param source Source data
|
||||
* \param length Size of source data
|
||||
* \param signature Destination address for signature, AES_KEY_LENGTH bytes
|
||||
*/
|
||||
int sign_data_block(u8 *source, unsigned length, u8 *signature);
|
||||
|
||||
#endif /* #ifndef _CRYPTO_H_ */
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The Chromium OS Authors.
|
||||
*
|
||||
* 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 <fdtdec.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/ap20.h>
|
||||
#include <asm/arch/apb_misc.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/emc.h>
|
||||
#include <asm/arch/tegra2.h>
|
||||
|
||||
/*
|
||||
* The EMC registers have shadow registers. When the EMC clock is updated
|
||||
* in the clock controller, the shadow registers are copied to the active
|
||||
* registers, allowing glitchless memory bus frequency changes.
|
||||
* This function updates the shadow registers for a new clock frequency,
|
||||
* and relies on the clock lock on the emc clock to avoid races between
|
||||
* multiple frequency changes
|
||||
*/
|
||||
|
||||
/*
|
||||
* This table defines the ordering of the registers provided to
|
||||
* tegra_set_mmc()
|
||||
* TODO: Convert to fdt version once available
|
||||
*/
|
||||
static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
|
||||
0x2c, /* RC */
|
||||
0x30, /* RFC */
|
||||
0x34, /* RAS */
|
||||
0x38, /* RP */
|
||||
0x3c, /* R2W */
|
||||
0x40, /* W2R */
|
||||
0x44, /* R2P */
|
||||
0x48, /* W2P */
|
||||
0x4c, /* RD_RCD */
|
||||
0x50, /* WR_RCD */
|
||||
0x54, /* RRD */
|
||||
0x58, /* REXT */
|
||||
0x5c, /* WDV */
|
||||
0x60, /* QUSE */
|
||||
0x64, /* QRST */
|
||||
0x68, /* QSAFE */
|
||||
0x6c, /* RDV */
|
||||
0x70, /* REFRESH */
|
||||
0x74, /* BURST_REFRESH_NUM */
|
||||
0x78, /* PDEX2WR */
|
||||
0x7c, /* PDEX2RD */
|
||||
0x80, /* PCHG2PDEN */
|
||||
0x84, /* ACT2PDEN */
|
||||
0x88, /* AR2PDEN */
|
||||
0x8c, /* RW2PDEN */
|
||||
0x90, /* TXSR */
|
||||
0x94, /* TCKE */
|
||||
0x98, /* TFAW */
|
||||
0x9c, /* TRPAB */
|
||||
0xa0, /* TCLKSTABLE */
|
||||
0xa4, /* TCLKSTOP */
|
||||
0xa8, /* TREFBW */
|
||||
0xac, /* QUSE_EXTRA */
|
||||
0x114, /* FBIO_CFG6 */
|
||||
0xb0, /* ODT_WRITE */
|
||||
0xb4, /* ODT_READ */
|
||||
0x104, /* FBIO_CFG5 */
|
||||
0x2bc, /* CFG_DIG_DLL */
|
||||
0x2c0, /* DLL_XFORM_DQS */
|
||||
0x2c4, /* DLL_XFORM_QUSE */
|
||||
0x2e0, /* ZCAL_REF_CNT */
|
||||
0x2e4, /* ZCAL_WAIT_CNT */
|
||||
0x2a8, /* AUTO_CAL_INTERVAL */
|
||||
0x2d0, /* CFG_CLKTRIM_0 */
|
||||
0x2d4, /* CFG_CLKTRIM_1 */
|
||||
0x2d8, /* CFG_CLKTRIM_2 */
|
||||
};
|
||||
|
||||
struct emc_ctlr *emc_get_controller(const void *blob)
|
||||
{
|
||||
fdt_addr_t addr;
|
||||
int node;
|
||||
|
||||
node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC);
|
||||
if (node > 0) {
|
||||
addr = fdtdec_get_addr(blob, node, "reg");
|
||||
if (addr != FDT_ADDR_T_NONE)
|
||||
return (struct emc_ctlr *)addr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Error codes we use */
|
||||
enum {
|
||||
ERR_NO_EMC_NODE = -10,
|
||||
ERR_NO_EMC_REG,
|
||||
ERR_NO_FREQ,
|
||||
ERR_FREQ_NOT_FOUND,
|
||||
ERR_BAD_REGS,
|
||||
ERR_NO_RAM_CODE,
|
||||
ERR_RAM_CODE_NOT_FOUND,
|
||||
};
|
||||
|
||||
/**
|
||||
* Find EMC tables for the given ram code.
|
||||
*
|
||||
* The tegra EMC binding has two options, one using the ram code and one not.
|
||||
* We detect which is in use by looking for the nvidia,use-ram-code property.
|
||||
* If this is not present, then the EMC tables are directly below 'node',
|
||||
* otherwise we select the correct emc-tables subnode based on the 'ram_code'
|
||||
* value.
|
||||
*
|
||||
* @param blob Device tree blob
|
||||
* @param node EMC node (nvidia,tegra20-emc compatible string)
|
||||
* @param ram_code RAM code to select (0-3, or -1 if unknown)
|
||||
* @return 0 if ok, otherwise a -ve ERR_ code (see enum above)
|
||||
*/
|
||||
static int find_emc_tables(const void *blob, int node, int ram_code)
|
||||
{
|
||||
int need_ram_code;
|
||||
int depth;
|
||||
int offset;
|
||||
|
||||
/* If we are using RAM codes, scan through the tables for our code */
|
||||
need_ram_code = fdtdec_get_bool(blob, node, "nvidia,use-ram-code");
|
||||
if (!need_ram_code)
|
||||
return node;
|
||||
if (ram_code == -1) {
|
||||
debug("%s: RAM code required but not supplied\n", __func__);
|
||||
return ERR_NO_RAM_CODE;
|
||||
}
|
||||
|
||||
offset = node;
|
||||
depth = 0;
|
||||
do {
|
||||
/*
|
||||
* Sadly there is no compatible string so we cannot use
|
||||
* fdtdec_next_compatible_subnode().
|
||||
*/
|
||||
offset = fdt_next_node(blob, offset, &depth);
|
||||
if (depth <= 0)
|
||||
break;
|
||||
|
||||
/* Make sure this is a direct subnode */
|
||||
if (depth != 1)
|
||||
continue;
|
||||
if (strcmp("emc-tables", fdt_get_name(blob, offset, NULL)))
|
||||
continue;
|
||||
|
||||
if (fdtdec_get_int(blob, offset, "nvidia,ram-code", -1)
|
||||
== ram_code)
|
||||
return offset;
|
||||
} while (1);
|
||||
|
||||
debug("%s: Could not find tables for RAM code %d\n", __func__,
|
||||
ram_code);
|
||||
return ERR_RAM_CODE_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the EMC node of the device tree, returning a pointer to the emc
|
||||
* controller and the table to be used for the given rate.
|
||||
*
|
||||
* @param blob Device tree blob
|
||||
* @param rate Clock speed of memory controller in Hz (=2x memory bus rate)
|
||||
* @param emcp Returns address of EMC controller registers
|
||||
* @param tablep Returns pointer to table to program into EMC. There are
|
||||
* TEGRA_EMC_NUM_REGS entries, destined for offsets as per the
|
||||
* emc_reg_addr array.
|
||||
* @return 0 if ok, otherwise a -ve error code which will allow someone to
|
||||
* figure out roughly what went wrong by looking at this code.
|
||||
*/
|
||||
static int decode_emc(const void *blob, unsigned rate, struct emc_ctlr **emcp,
|
||||
const u32 **tablep)
|
||||
{
|
||||
struct apb_misc_pp_ctlr *pp =
|
||||
(struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE;
|
||||
int ram_code;
|
||||
int depth;
|
||||
int node;
|
||||
|
||||
ram_code = (readl(&pp->strapping_opt_a) & RAM_CODE_MASK)
|
||||
>> RAM_CODE_SHIFT;
|
||||
/*
|
||||
* The EMC clock rate is twice the bus rate, and the bus rate is
|
||||
* measured in kHz
|
||||
*/
|
||||
rate = rate / 2 / 1000;
|
||||
|
||||
node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC);
|
||||
if (node < 0) {
|
||||
debug("%s: No EMC node found in FDT\n", __func__);
|
||||
return ERR_NO_EMC_NODE;
|
||||
}
|
||||
*emcp = (struct emc_ctlr *)fdtdec_get_addr(blob, node, "reg");
|
||||
if (*emcp == (struct emc_ctlr *)FDT_ADDR_T_NONE) {
|
||||
debug("%s: No EMC node reg property\n", __func__);
|
||||
return ERR_NO_EMC_REG;
|
||||
}
|
||||
|
||||
/* Work out the parent node which contains our EMC tables */
|
||||
node = find_emc_tables(blob, node, ram_code & 3);
|
||||
if (node < 0)
|
||||
return node;
|
||||
|
||||
depth = 0;
|
||||
for (;;) {
|
||||
int node_rate;
|
||||
|
||||
node = fdtdec_next_compatible_subnode(blob, node,
|
||||
COMPAT_NVIDIA_TEGRA20_EMC_TABLE, &depth);
|
||||
if (node < 0)
|
||||
break;
|
||||
node_rate = fdtdec_get_int(blob, node, "clock-frequency", -1);
|
||||
if (node_rate == -1) {
|
||||
debug("%s: Missing clock-frequency\n", __func__);
|
||||
return ERR_NO_FREQ; /* we expect this property */
|
||||
}
|
||||
|
||||
if (node_rate == rate)
|
||||
break;
|
||||
}
|
||||
if (node < 0) {
|
||||
debug("%s: No node found for clock frequency %d\n", __func__,
|
||||
rate);
|
||||
return ERR_FREQ_NOT_FOUND;
|
||||
}
|
||||
|
||||
*tablep = fdtdec_locate_array(blob, node, "nvidia,emc-registers",
|
||||
TEGRA_EMC_NUM_REGS);
|
||||
if (!*tablep) {
|
||||
debug("%s: node '%s' array missing / wrong size\n", __func__,
|
||||
fdt_get_name(blob, node, NULL));
|
||||
return ERR_BAD_REGS;
|
||||
}
|
||||
|
||||
/* All seems well */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegra_set_emc(const void *blob, unsigned rate)
|
||||
{
|
||||
struct emc_ctlr *emc;
|
||||
const u32 *table;
|
||||
int err, i;
|
||||
|
||||
err = decode_emc(blob, rate, &emc, &table);
|
||||
if (err) {
|
||||
debug("Warning: no valid EMC (%d), memory timings unset\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
debug("%s: Table found, setting EMC values as follows:\n", __func__);
|
||||
for (i = 0; i < TEGRA_EMC_NUM_REGS; i++) {
|
||||
u32 value = fdt32_to_cpu(table[i]);
|
||||
u32 addr = (uintptr_t)emc + emc_reg_addr[i];
|
||||
|
||||
debug(" %#x: %#x\n", addr, value);
|
||||
writel(value, addr);
|
||||
}
|
||||
|
||||
/* trigger emc with new settings */
|
||||
clock_adjust_periph_pll_div(PERIPH_ID_EMC, CLOCK_ID_MEMORY,
|
||||
clock_get_rate(CLOCK_ID_MEMORY), NULL);
|
||||
debug("EMC clock set to %lu\n",
|
||||
clock_get_periph_rate(PERIPH_ID_EMC, CLOCK_ID_MEMORY));
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -169,6 +169,22 @@ int funcmux_select(enum periph_id id, int config)
|
|||
}
|
||||
break;
|
||||
|
||||
case PERIPH_ID_KBC:
|
||||
if (config == FUNCMUX_DEFAULT) {
|
||||
enum pmux_pingrp grp[] = {PINGRP_KBCA, PINGRP_KBCB,
|
||||
PINGRP_KBCC, PINGRP_KBCD, PINGRP_KBCE,
|
||||
PINGRP_KBCF};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(grp); i++) {
|
||||
pinmux_tristate_disable(grp[i]);
|
||||
pinmux_set_func(grp[i], PMUX_FUNC_KBC);
|
||||
pinmux_set_pullupdown(grp[i], PMUX_PULL_UP);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
debug("%s: invalid periph_id %d", __func__, id);
|
||||
return -1;
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
|
||||
#include <config.h>
|
||||
#include <version.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.align 5
|
||||
.global reset_cpu
|
||||
reset_cpu:
|
||||
ENTRY(reset_cpu)
|
||||
ldr r1, rstctl @ get addr for global reset
|
||||
@ reg
|
||||
ldr r3, [r1]
|
||||
|
@ -39,3 +39,4 @@ _loop_forever:
|
|||
b _loop_forever
|
||||
rstctl:
|
||||
.word PRM_RSTCTRL
|
||||
ENDPROC(reset_cpu)
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2011 The Chromium OS Authors.
|
||||
* (C) Copyright 2010,2011 NVIDIA Corporation <www.nvidia.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 <tps6586x.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/ap20.h>
|
||||
#include <asm/arch/tegra2.h>
|
||||
#include <asm/arch/tegra_i2c.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
|
||||
#define VDD_CORE_NOMINAL_T25 0x17 /* 1.3v */
|
||||
#define VDD_CPU_NOMINAL_T25 0x10 /* 1.125v */
|
||||
|
||||
#define VDD_CORE_NOMINAL_T20 0x16 /* 1.275v */
|
||||
#define VDD_CPU_NOMINAL_T20 0x0f /* 1.1v */
|
||||
|
||||
#define VDD_RELATION 0x02 /* 50mv */
|
||||
#define VDD_TRANSITION_STEP 0x06 /* 150mv */
|
||||
#define VDD_TRANSITION_RATE 0x06 /* 3.52mv/us */
|
||||
|
||||
int pmu_set_nominal(void)
|
||||
{
|
||||
int core, cpu, bus;
|
||||
|
||||
/* by default, the table has been filled with T25 settings */
|
||||
switch (tegra_get_chip_type()) {
|
||||
case TEGRA_SOC_T20:
|
||||
core = VDD_CORE_NOMINAL_T20;
|
||||
cpu = VDD_CPU_NOMINAL_T20;
|
||||
break;
|
||||
case TEGRA_SOC_T25:
|
||||
core = VDD_CORE_NOMINAL_T25;
|
||||
cpu = VDD_CPU_NOMINAL_T25;
|
||||
break;
|
||||
default:
|
||||
debug("%s: Unknown chip type\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bus = tegra_i2c_get_dvc_bus_num();
|
||||
if (bus == -1) {
|
||||
debug("%s: Cannot find DVC I2C bus\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
tps6586x_init(bus);
|
||||
tps6586x_set_pwm_mode(TPS6586X_PWM_SM1);
|
||||
return tps6586x_adjust_sm0_sm1(core, cpu, VDD_TRANSITION_STEP,
|
||||
VDD_TRANSITION_RATE, VDD_RELATION);
|
||||
}
|
|
@ -0,0 +1,386 @@
|
|||
/*
|
||||
* (C) Copyright 2010 - 2011
|
||||
* NVIDIA Corporation <www.nvidia.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/errno.h>
|
||||
#include <asm/arch/ap20.h>
|
||||
#include <asm/arch/clk_rst.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/pmc.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/tegra2.h>
|
||||
#include <asm/arch/fuse.h>
|
||||
#include <asm/arch/emc.h>
|
||||
#include <asm/arch/gp_padctrl.h>
|
||||
#include <asm/arch/warmboot.h>
|
||||
#include <asm/arch/sdram_param.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifndef CONFIG_TEGRA_CLOCK_SCALING
|
||||
#error "You must enable CONFIG_TEGRA_CLOCK_SCALING to use CONFIG_TEGRA2_LP0"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the place in SRAM where the SDRAM parameters are stored. There
|
||||
* are 4 blocks, one for each RAM code
|
||||
*/
|
||||
#define SDRAM_PARAMS_BASE (AP20_BASE_PA_SRAM + 0x188)
|
||||
|
||||
/* TODO: If we later add support for the Misc GP controller, refactor this */
|
||||
union xm2cfga_reg {
|
||||
struct {
|
||||
u32 reserved0:2;
|
||||
u32 hsm_en:1;
|
||||
u32 reserved1:2;
|
||||
u32 preemp_en:1;
|
||||
u32 vref_en:1;
|
||||
u32 reserved2:5;
|
||||
u32 cal_drvdn:5;
|
||||
u32 reserved3:3;
|
||||
u32 cal_drvup:5;
|
||||
u32 reserved4:3;
|
||||
u32 cal_drvdn_slwr:2;
|
||||
u32 cal_drvup_slwf:2;
|
||||
};
|
||||
u32 word;
|
||||
};
|
||||
|
||||
union xm2cfgd_reg {
|
||||
struct {
|
||||
u32 reserved0:2;
|
||||
u32 hsm_en:1;
|
||||
u32 schmt_en:1;
|
||||
u32 lpmd:2;
|
||||
u32 vref_en:1;
|
||||
u32 reserved1:5;
|
||||
u32 cal_drvdn:5;
|
||||
u32 reserved2:3;
|
||||
u32 cal_drvup:5;
|
||||
u32 reserved3:3;
|
||||
u32 cal_drvdn_slwr:2;
|
||||
u32 cal_drvup_slwf:2;
|
||||
};
|
||||
u32 word;
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO: This register is not documented in the TRM yet. We could move this
|
||||
* into the EMC and give it a proper interface, but not while it is
|
||||
* undocumented.
|
||||
*/
|
||||
union fbio_spare_reg {
|
||||
struct {
|
||||
u32 reserved:24;
|
||||
u32 cfg_wb0:8;
|
||||
};
|
||||
u32 word;
|
||||
};
|
||||
|
||||
/* We pack the resume information into these unions for later */
|
||||
union scratch2_reg {
|
||||
struct {
|
||||
u32 pllm_base_divm:5;
|
||||
u32 pllm_base_divn:10;
|
||||
u32 pllm_base_divp:3;
|
||||
u32 pllm_misc_lfcon:4;
|
||||
u32 pllm_misc_cpcon:4;
|
||||
u32 gp_xm2cfga_padctrl_preemp:1;
|
||||
u32 gp_xm2cfgd_padctrl_schmt:1;
|
||||
u32 osc_ctrl_xobp:1;
|
||||
u32 memory_type:3;
|
||||
};
|
||||
u32 word;
|
||||
};
|
||||
|
||||
union scratch4_reg {
|
||||
struct {
|
||||
u32 emc_clock_divider:8;
|
||||
u32 pllm_stable_time:8;
|
||||
u32 pllx_stable_time:8;
|
||||
u32 emc_fbio_spare_cfg_wb0:8;
|
||||
};
|
||||
u32 word;
|
||||
};
|
||||
|
||||
union scratch24_reg {
|
||||
struct {
|
||||
u32 emc_auto_cal_wait:8;
|
||||
u32 emc_pin_program_wait:8;
|
||||
u32 warmboot_wait:8;
|
||||
u32 reserved:8;
|
||||
};
|
||||
u32 word;
|
||||
};
|
||||
|
||||
int warmboot_save_sdram_params(void)
|
||||
{
|
||||
u32 ram_code;
|
||||
struct sdram_params sdram;
|
||||
struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
|
||||
struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
|
||||
struct apb_misc_gp_ctlr *gp =
|
||||
(struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE;
|
||||
struct emc_ctlr *emc = emc_get_controller(gd->fdt_blob);
|
||||
union scratch2_reg scratch2;
|
||||
union scratch4_reg scratch4;
|
||||
union scratch24_reg scratch24;
|
||||
union xm2cfga_reg xm2cfga;
|
||||
union xm2cfgd_reg xm2cfgd;
|
||||
union fbio_spare_reg fbio_spare;
|
||||
|
||||
/* get ram code that is used as index to array sdram_params in BCT */
|
||||
ram_code = (readl(&pmt->pmt_strap_opt_a) >>
|
||||
STRAP_OPT_A_RAM_CODE_SHIFT) & 3;
|
||||
memcpy(&sdram,
|
||||
(char *)((struct sdram_params *)SDRAM_PARAMS_BASE + ram_code),
|
||||
sizeof(sdram));
|
||||
|
||||
xm2cfga.word = readl(&gp->xm2cfga);
|
||||
xm2cfgd.word = readl(&gp->xm2cfgd);
|
||||
|
||||
scratch2.word = 0;
|
||||
scratch2.osc_ctrl_xobp = clock_get_osc_bypass();
|
||||
|
||||
/* Get the memory PLL settings */
|
||||
{
|
||||
u32 divm, divn, divp, cpcon, lfcon;
|
||||
|
||||
if (clock_ll_read_pll(CLOCK_ID_MEMORY, &divm, &divn, &divp,
|
||||
&cpcon, &lfcon))
|
||||
return -1;
|
||||
scratch2.pllm_base_divm = divm;
|
||||
scratch2.pllm_base_divn = divn;
|
||||
scratch2.pllm_base_divp = divp;
|
||||
scratch2.pllm_misc_cpcon = cpcon;
|
||||
scratch2.pllm_misc_lfcon = lfcon;
|
||||
}
|
||||
|
||||
scratch2.gp_xm2cfga_padctrl_preemp = xm2cfga.preemp_en;
|
||||
scratch2.gp_xm2cfgd_padctrl_schmt = xm2cfgd.schmt_en;
|
||||
scratch2.memory_type = sdram.memory_type;
|
||||
writel(scratch2.word, &pmc->pmc_scratch2);
|
||||
|
||||
/* collect data from various sources for pmc_scratch4 */
|
||||
fbio_spare.word = readl(&emc->fbio_spare);
|
||||
scratch4.word = 0;
|
||||
scratch4.emc_fbio_spare_cfg_wb0 = fbio_spare.cfg_wb0;
|
||||
scratch4.emc_clock_divider = sdram.emc_clock_divider;
|
||||
scratch4.pllm_stable_time = -1;
|
||||
scratch4.pllx_stable_time = -1;
|
||||
writel(scratch4.word, &pmc->pmc_scratch4);
|
||||
|
||||
/* collect various data from sdram for pmc_scratch24 */
|
||||
scratch24.word = 0;
|
||||
scratch24.emc_pin_program_wait = sdram.emc_pin_program_wait;
|
||||
scratch24.emc_auto_cal_wait = sdram.emc_auto_cal_wait;
|
||||
scratch24.warmboot_wait = sdram.warm_boot_wait;
|
||||
writel(scratch24.word, &pmc->pmc_scratch24);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 get_major_version(void)
|
||||
{
|
||||
u32 major_id;
|
||||
struct apb_misc_gp_ctlr *gp =
|
||||
(struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE;
|
||||
|
||||
major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >>
|
||||
HIDREV_MAJORPREV_SHIFT;
|
||||
return major_id;
|
||||
}
|
||||
|
||||
static int is_production_mode_fuse_set(struct fuse_regs *fuse)
|
||||
{
|
||||
return readl(&fuse->production_mode);
|
||||
}
|
||||
|
||||
static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse)
|
||||
{
|
||||
return readl(&fuse->security_mode);
|
||||
}
|
||||
|
||||
static int is_failure_analysis_mode(struct fuse_regs *fuse)
|
||||
{
|
||||
return readl(&fuse->fa);
|
||||
}
|
||||
|
||||
static int ap20_is_odm_production_mode(void)
|
||||
{
|
||||
struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE;
|
||||
|
||||
if (!is_failure_analysis_mode(fuse) &&
|
||||
is_odm_production_mode_fuse_set(fuse))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ap20_is_production_mode(void)
|
||||
{
|
||||
struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE;
|
||||
|
||||
if (get_major_version() == 0)
|
||||
return 1;
|
||||
|
||||
if (!is_failure_analysis_mode(fuse) &&
|
||||
is_production_mode_fuse_set(fuse) &&
|
||||
!is_odm_production_mode_fuse_set(fuse))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum fuse_operating_mode fuse_get_operation_mode(void)
|
||||
{
|
||||
u32 chip_id;
|
||||
struct apb_misc_gp_ctlr *gp =
|
||||
(struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE;
|
||||
|
||||
chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >>
|
||||
HIDREV_CHIPID_SHIFT;
|
||||
if (chip_id == CHIPID_TEGRA2) {
|
||||
if (ap20_is_odm_production_mode()) {
|
||||
printf("!! odm_production_mode is not supported !!\n");
|
||||
return MODE_UNDEFINED;
|
||||
} else
|
||||
if (ap20_is_production_mode())
|
||||
return MODE_PRODUCTION;
|
||||
else
|
||||
return MODE_UNDEFINED;
|
||||
}
|
||||
return MODE_UNDEFINED;
|
||||
}
|
||||
|
||||
static void determine_crypto_options(int *is_encrypted, int *is_signed,
|
||||
int *use_zero_key)
|
||||
{
|
||||
switch (fuse_get_operation_mode()) {
|
||||
case MODE_PRODUCTION:
|
||||
*is_encrypted = 0;
|
||||
*is_signed = 1;
|
||||
*use_zero_key = 1;
|
||||
break;
|
||||
case MODE_UNDEFINED:
|
||||
default:
|
||||
*is_encrypted = 0;
|
||||
*is_signed = 0;
|
||||
*use_zero_key = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int sign_wb_code(u32 start, u32 length, int use_zero_key)
|
||||
{
|
||||
int err;
|
||||
u8 *source; /* Pointer to source */
|
||||
u8 *hash;
|
||||
|
||||
/* Calculate AES block parameters. */
|
||||
source = (u8 *)(start + offsetof(struct wb_header, random_aes_block));
|
||||
length -= offsetof(struct wb_header, random_aes_block);
|
||||
hash = (u8 *)(start + offsetof(struct wb_header, hash));
|
||||
err = sign_data_block(source, length, hash);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int warmboot_prepare_code(u32 seg_address, u32 seg_length)
|
||||
{
|
||||
int err = 0;
|
||||
u32 length; /* length of the signed/encrypt code */
|
||||
struct wb_header *dst_header; /* Pointer to dest WB header */
|
||||
int is_encrypted; /* Segment is encrypted */
|
||||
int is_signed; /* Segment is signed */
|
||||
int use_zero_key; /* Use key of all zeros */
|
||||
|
||||
/* Determine crypto options. */
|
||||
determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key);
|
||||
|
||||
/* Get the actual code limits. */
|
||||
length = roundup(((u32)wb_end - (u32)wb_start), 16);
|
||||
|
||||
/*
|
||||
* The region specified by seg_address must be in SDRAM and must be
|
||||
* nonzero in length.
|
||||
*/
|
||||
if (seg_length == 0 || seg_address < NV_PA_SDRAM_BASE ||
|
||||
seg_address + seg_length >= NV_PA_SDRAM_BASE + gd->ram_size) {
|
||||
err = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Things must be 16-byte aligned. */
|
||||
if ((seg_length & 0xF) || (seg_address & 0xF)) {
|
||||
err = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Will the code fit? (destination includes wb_header + wb code) */
|
||||
if (seg_length < (length + sizeof(struct wb_header))) {
|
||||
err = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dst_header = (struct wb_header *)seg_address;
|
||||
memset((char *)dst_header, 0, sizeof(struct wb_header));
|
||||
|
||||
/* Populate the random_aes_block as requested. */
|
||||
{
|
||||
u32 *aes_block = (u32 *)&(dst_header->random_aes_block);
|
||||
u32 *end = (u32 *)(((u32)aes_block) +
|
||||
sizeof(dst_header->random_aes_block));
|
||||
|
||||
do {
|
||||
*aes_block++ = 0;
|
||||
} while (aes_block < end);
|
||||
}
|
||||
|
||||
/* Populate the header. */
|
||||
dst_header->length_insecure = length + sizeof(struct wb_header);
|
||||
dst_header->length_secure = length + sizeof(struct wb_header);
|
||||
dst_header->destination = AP20_WB_RUN_ADDRESS;
|
||||
dst_header->entry_point = AP20_WB_RUN_ADDRESS;
|
||||
dst_header->code_length = length;
|
||||
|
||||
if (is_encrypted) {
|
||||
printf("!!!! Encryption is not supported !!!!\n");
|
||||
dst_header->length_insecure = 0;
|
||||
err = -EACCES;
|
||||
goto fail;
|
||||
} else
|
||||
/* copy the wb code directly following dst_header. */
|
||||
memcpy((char *)(dst_header+1), (char *)wb_start, length);
|
||||
|
||||
if (is_signed)
|
||||
err = sign_wb_code(seg_address, dst_header->length_insecure,
|
||||
use_zero_key);
|
||||
|
||||
fail:
|
||||
if (err)
|
||||
printf("Warning: warmboot code copy failed (error=%d)\n", err);
|
||||
|
||||
return err;
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* (C) Copyright 2010 - 2011
|
||||
* NVIDIA Corporation <www.nvidia.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/ap20.h>
|
||||
#include <asm/arch/clk_rst.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/flow.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/pmc.h>
|
||||
#include <asm/arch/tegra2.h>
|
||||
#include <asm/arch/warmboot.h>
|
||||
#include "warmboot_avp.h"
|
||||
|
||||
#define DEBUG_RESET_CORESIGHT
|
||||
|
||||
void wb_start(void)
|
||||
{
|
||||
struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
|
||||
struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE;
|
||||
struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
|
||||
struct clk_rst_ctlr *clkrst =
|
||||
(struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
|
||||
union osc_ctrl_reg osc_ctrl;
|
||||
union pllx_base_reg pllx_base;
|
||||
union pllx_misc_reg pllx_misc;
|
||||
union scratch3_reg scratch3;
|
||||
u32 reg;
|
||||
|
||||
/* enable JTAG & TBE */
|
||||
writel(CONFIG_CTL_TBE | CONFIG_CTL_JTAG, &pmt->pmt_cfg_ctl);
|
||||
|
||||
/* Are we running where we're supposed to be? */
|
||||
asm volatile (
|
||||
"adr %0, wb_start;" /* reg: wb_start address */
|
||||
: "=r"(reg) /* output */
|
||||
/* no input, no clobber list */
|
||||
);
|
||||
|
||||
if (reg != AP20_WB_RUN_ADDRESS)
|
||||
goto do_reset;
|
||||
|
||||
/* Are we running with AVP? */
|
||||
if (readl(NV_PA_PG_UP_BASE + PG_UP_TAG_0) != PG_UP_TAG_AVP)
|
||||
goto do_reset;
|
||||
|
||||
#ifdef DEBUG_RESET_CORESIGHT
|
||||
/* Assert CoreSight reset */
|
||||
reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]);
|
||||
reg |= SWR_CSITE_RST;
|
||||
writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]);
|
||||
#endif
|
||||
|
||||
/* TODO: Set the drive strength - maybe make this a board parameter? */
|
||||
osc_ctrl.word = readl(&clkrst->crc_osc_ctrl);
|
||||
osc_ctrl.xofs = 4;
|
||||
osc_ctrl.xoe = 1;
|
||||
writel(osc_ctrl.word, &clkrst->crc_osc_ctrl);
|
||||
|
||||
/* Power up the CPU complex if necessary */
|
||||
if (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU)) {
|
||||
reg = PWRGATE_TOGGLE_PARTID_CPU | PWRGATE_TOGGLE_START;
|
||||
writel(reg, &pmc->pmc_pwrgate_toggle);
|
||||
while (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU))
|
||||
;
|
||||
}
|
||||
|
||||
/* Remove the I/O clamps from the CPU power partition. */
|
||||
reg = readl(&pmc->pmc_remove_clamping);
|
||||
reg |= CPU_CLMP;
|
||||
writel(reg, &pmc->pmc_remove_clamping);
|
||||
|
||||
reg = EVENT_ZERO_VAL_20 | EVENT_MSEC | EVENT_MODE_STOP;
|
||||
writel(reg, &flow->halt_cop_events);
|
||||
|
||||
/* Assert CPU complex reset */
|
||||
reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]);
|
||||
reg |= CPU_RST;
|
||||
writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
|
||||
|
||||
/* Hold both CPUs in reset */
|
||||
reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_CPURESET1 | CPU_CMPLX_DERESET0 |
|
||||
CPU_CMPLX_DERESET1 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DBGRESET1;
|
||||
writel(reg, &clkrst->crc_cpu_cmplx_set);
|
||||
|
||||
/* Halt CPU1 at the flow controller for uni-processor configurations */
|
||||
writel(EVENT_MODE_STOP, &flow->halt_cpu1_events);
|
||||
|
||||
/*
|
||||
* Set the CPU reset vector. SCRATCH41 contains the physical
|
||||
* address of the CPU-side restoration code.
|
||||
*/
|
||||
reg = readl(&pmc->pmc_scratch41);
|
||||
writel(reg, EXCEP_VECTOR_CPU_RESET_VECTOR);
|
||||
|
||||
/* Select CPU complex clock source */
|
||||
writel(CCLK_PLLP_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
|
||||
|
||||
/* Start the CPU0 clock and stop the CPU1 clock */
|
||||
reg = CPU_CMPLX_CPU_BRIDGE_CLKDIV_4 | CPU_CMPLX_CPU0_CLK_STP_RUN |
|
||||
CPU_CMPLX_CPU1_CLK_STP_STOP;
|
||||
writel(reg, &clkrst->crc_clk_cpu_cmplx);
|
||||
|
||||
/* Enable the CPU complex clock */
|
||||
reg = readl(&clkrst->crc_clk_out_enb[TEGRA_DEV_L]);
|
||||
reg |= CLK_ENB_CPU;
|
||||
writel(reg, &clkrst->crc_clk_out_enb[TEGRA_DEV_L]);
|
||||
|
||||
/* Make sure the resets were held for at least 2 microseconds */
|
||||
reg = readl(TIMER_USEC_CNTR);
|
||||
while (readl(TIMER_USEC_CNTR) <= (reg + 2))
|
||||
;
|
||||
|
||||
#ifdef DEBUG_RESET_CORESIGHT
|
||||
/*
|
||||
* De-assert CoreSight reset.
|
||||
* NOTE: We're leaving the CoreSight clock on the oscillator for
|
||||
* now. It will be restored to its original clock source
|
||||
* when the CPU-side restoration code runs.
|
||||
*/
|
||||
reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]);
|
||||
reg &= ~SWR_CSITE_RST;
|
||||
writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]);
|
||||
#endif
|
||||
|
||||
/* Unlock the CPU CoreSight interfaces */
|
||||
reg = 0xC5ACCE55;
|
||||
writel(reg, CSITE_CPU_DBG0_LAR);
|
||||
writel(reg, CSITE_CPU_DBG1_LAR);
|
||||
|
||||
/*
|
||||
* Sample the microsecond timestamp again. This is the time we must
|
||||
* use when returning from LP0 for PLL stabilization delays.
|
||||
*/
|
||||
reg = readl(TIMER_USEC_CNTR);
|
||||
writel(reg, &pmc->pmc_scratch1);
|
||||
|
||||
pllx_base.word = 0;
|
||||
pllx_misc.word = 0;
|
||||
scratch3.word = readl(&pmc->pmc_scratch3);
|
||||
|
||||
/* Get the OSC. For 19.2 MHz, use 19 to make the calculations easier */
|
||||
reg = (readl(TIMER_USEC_CFG) & USEC_CFG_DIVISOR_MASK) + 1;
|
||||
|
||||
/*
|
||||
* According to the TRM, for 19.2MHz OSC, the USEC_DIVISOR is 0x5f, and
|
||||
* USEC_DIVIDEND is 0x04. So, if USEC_DIVISOR > 26, OSC is 19.2 MHz.
|
||||
*
|
||||
* reg is used to calculate the pllx freq, which is used to determine if
|
||||
* to set dccon or not.
|
||||
*/
|
||||
if (reg > 26)
|
||||
reg = 19;
|
||||
|
||||
/* PLLX_BASE.PLLX_DIVM */
|
||||
if (scratch3.pllx_base_divm == reg)
|
||||
reg = 0;
|
||||
else
|
||||
reg = 1;
|
||||
|
||||
/* PLLX_BASE.PLLX_DIVN */
|
||||
pllx_base.divn = scratch3.pllx_base_divn;
|
||||
reg = scratch3.pllx_base_divn << reg;
|
||||
|
||||
/* PLLX_BASE.PLLX_DIVP */
|
||||
pllx_base.divp = scratch3.pllx_base_divp;
|
||||
reg = reg >> scratch3.pllx_base_divp;
|
||||
|
||||
pllx_base.bypass = 1;
|
||||
|
||||
/* PLLX_MISC_DCCON must be set for pllx frequency > 600 MHz. */
|
||||
if (reg > 600)
|
||||
pllx_misc.dccon = 1;
|
||||
|
||||
/* PLLX_MISC_LFCON */
|
||||
pllx_misc.lfcon = scratch3.pllx_misc_lfcon;
|
||||
|
||||
/* PLLX_MISC_CPCON */
|
||||
pllx_misc.cpcon = scratch3.pllx_misc_cpcon;
|
||||
|
||||
writel(pllx_misc.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_misc);
|
||||
writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
|
||||
|
||||
pllx_base.enable = 1;
|
||||
writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
|
||||
pllx_base.bypass = 0;
|
||||
writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
|
||||
|
||||
writel(0, flow->halt_cpu_events);
|
||||
|
||||
reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DERESET0;
|
||||
writel(reg, &clkrst->crc_cpu_cmplx_clr);
|
||||
|
||||
reg = PLLM_OUT1_RSTN_RESET_DISABLE | PLLM_OUT1_CLKEN_ENABLE |
|
||||
PLLM_OUT1_RATIO_VAL_8;
|
||||
writel(reg, &clkrst->crc_pll[CLOCK_ID_MEMORY].pll_out);
|
||||
|
||||
reg = SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 | SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 |
|
||||
SCLK_SWAKE_RUN_SRC_PLLM_OUT1 | SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 |
|
||||
SCLK_SYS_STATE_IDLE;
|
||||
writel(reg, &clkrst->crc_sclk_brst_pol);
|
||||
|
||||
/* avp_resume: no return after the write */
|
||||
reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]);
|
||||
reg &= ~CPU_RST;
|
||||
writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
|
||||
|
||||
/* avp_halt: */
|
||||
avp_halt:
|
||||
reg = EVENT_MODE_STOP | EVENT_JTAG;
|
||||
writel(reg, flow->halt_cop_events);
|
||||
goto avp_halt;
|
||||
|
||||
do_reset:
|
||||
/*
|
||||
* Execution comes here if something goes wrong. The chip is reset and
|
||||
* a cold boot is performed.
|
||||
*/
|
||||
writel(SWR_TRIG_SYS_RST, &clkrst->crc_rst_dev[TEGRA_DEV_L]);
|
||||
goto do_reset;
|
||||
}
|
||||
|
||||
/*
|
||||
* wb_end() is a dummy function, and must be directly following wb_start(),
|
||||
* and is used to calculate the size of wb_start().
|
||||
*/
|
||||
void wb_end(void)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* (C) Copyright 2010, 2011
|
||||
* NVIDIA Corporation <www.nvidia.com>
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _WARMBOOT_AVP_H_
|
||||
#define _WARMBOOT_AVP_H_
|
||||
|
||||
#define TEGRA_DEV_L 0
|
||||
#define TEGRA_DEV_H 1
|
||||
#define TEGRA_DEV_U 2
|
||||
|
||||
#define SIMPLE_PLLX (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE)
|
||||
#define SIMPLE_PLLE (CLOCK_ID_EPCI - CLOCK_ID_FIRST_SIMPLE)
|
||||
|
||||
#define TIMER_USEC_CNTR (NV_PA_TMRUS_BASE + 0)
|
||||
#define TIMER_USEC_CFG (NV_PA_TMRUS_BASE + 4)
|
||||
|
||||
#define USEC_CFG_DIVISOR_MASK 0xffff
|
||||
|
||||
#define CONFIG_CTL_TBE (1 << 7)
|
||||
#define CONFIG_CTL_JTAG (1 << 6)
|
||||
|
||||
#define CPU_RST (1 << 0)
|
||||
#define CLK_ENB_CPU (1 << 0)
|
||||
#define SWR_TRIG_SYS_RST (1 << 2)
|
||||
#define SWR_CSITE_RST (1 << 9)
|
||||
|
||||
#define PWRGATE_STATUS_CPU (1 << 0)
|
||||
#define PWRGATE_TOGGLE_PARTID_CPU (0 << 0)
|
||||
#define PWRGATE_TOGGLE_START (1 << 8)
|
||||
|
||||
#define CPU_CMPLX_CPU_BRIDGE_CLKDIV_4 (3 << 0)
|
||||
#define CPU_CMPLX_CPU0_CLK_STP_STOP (1 << 8)
|
||||
#define CPU_CMPLX_CPU0_CLK_STP_RUN (0 << 8)
|
||||
#define CPU_CMPLX_CPU1_CLK_STP_STOP (1 << 9)
|
||||
#define CPU_CMPLX_CPU1_CLK_STP_RUN (0 << 9)
|
||||
|
||||
#define CPU_CMPLX_CPURESET0 (1 << 0)
|
||||
#define CPU_CMPLX_CPURESET1 (1 << 1)
|
||||
#define CPU_CMPLX_DERESET0 (1 << 4)
|
||||
#define CPU_CMPLX_DERESET1 (1 << 5)
|
||||
#define CPU_CMPLX_DBGRESET0 (1 << 12)
|
||||
#define CPU_CMPLX_DBGRESET1 (1 << 13)
|
||||
|
||||
#define PLLM_OUT1_RSTN_RESET_DISABLE (1 << 0)
|
||||
#define PLLM_OUT1_CLKEN_ENABLE (1 << 1)
|
||||
#define PLLM_OUT1_RATIO_VAL_8 (8 << 8)
|
||||
|
||||
#define SCLK_SYS_STATE_IDLE (1 << 28)
|
||||
#define SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 (7 << 12)
|
||||
#define SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 (7 << 8)
|
||||
#define SCLK_SWAKE_RUN_SRC_PLLM_OUT1 (7 << 4)
|
||||
#define SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 (7 << 0)
|
||||
|
||||
#define EVENT_ZERO_VAL_20 (20 << 0)
|
||||
#define EVENT_MSEC (1 << 24)
|
||||
#define EVENT_JTAG (1 << 28)
|
||||
#define EVENT_MODE_STOP (2 << 29)
|
||||
|
||||
#define CCLK_PLLP_BURST_POLICY 0x20004444
|
||||
|
||||
#endif
|
|
@ -20,16 +20,17 @@
|
|||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.globl lowlevel_init
|
||||
lowlevel_init:
|
||||
ENTRY(lowlevel_init)
|
||||
mov pc, lr
|
||||
ENDPROC(lowlevel_init)
|
||||
|
||||
.align 5
|
||||
.globl reset_cpu
|
||||
reset_cpu:
|
||||
ENTRY(reset_cpu)
|
||||
ldr r0, =CFG_PRCMU_BASE
|
||||
ldr r1, =0x1
|
||||
str r1, [r0, #0x228]
|
||||
_loop_forever:
|
||||
b _loop_forever
|
||||
ENDPROC(reset_cpu)
|
||||
|
|
|
@ -518,7 +518,7 @@ static void npe_halt(struct eth_device *dev)
|
|||
}
|
||||
|
||||
|
||||
static int npe_send(struct eth_device *dev, volatile void *packet, int len)
|
||||
static int npe_send(struct eth_device *dev, void *packet, int len)
|
||||
{
|
||||
struct npe *p_npe = (struct npe *)dev->priv;
|
||||
u8 *dest;
|
||||
|
|
|
@ -193,4 +193,15 @@
|
|||
clocks = <&tegra_car 59>; /* PERIPH_ID_USB3 */
|
||||
};
|
||||
|
||||
emc@7000f400 {
|
||||
#address-cells = < 1 >;
|
||||
#size-cells = < 0 >;
|
||||
compatible = "nvidia,tegra20-emc";
|
||||
reg = <0x7000f400 0x200>;
|
||||
};
|
||||
|
||||
kbc@7000e200 {
|
||||
compatible = "nvidia,tegra20-kbc";
|
||||
reg = <0x7000e200 0x0078>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -159,6 +159,6 @@ typedef struct hsmmc {
|
|||
#define mmc_reg_out(addr, mask, val)\
|
||||
writel((readl(addr) & (~(mask))) | ((val) & (mask)), (addr))
|
||||
|
||||
int omap_mmc_init(int dev_index);
|
||||
int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max);
|
||||
|
||||
#endif /* MMC_HOST_DEF_H */
|
||||
|
|
|
@ -33,5 +33,8 @@ unsigned long get_arm_clk(void);
|
|||
unsigned long get_pwm_clk(void);
|
||||
unsigned long get_uart_clk(int dev_index);
|
||||
void set_mmc_clk(int dev_index, unsigned int div);
|
||||
unsigned long get_lcd_clk(void);
|
||||
void set_lcd_clk(void);
|
||||
void set_mipi_clk(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
/* EXYNOS4 */
|
||||
#define EXYNOS4_GPIO_PART3_BASE 0x03860000
|
||||
#define EXYNOS4_PRO_ID 0x10000000
|
||||
#define EXYNOS4_SYSREG_BASE 0x10010000
|
||||
#define EXYNOS4_POWER_BASE 0x10020000
|
||||
#define EXYNOS4_SWRESET 0x10020400
|
||||
#define EXYNOS4_CLOCK_BASE 0x10030000
|
||||
|
@ -40,6 +41,7 @@
|
|||
#define EXYNOS4_GPIO_PART2_BASE 0x11000000
|
||||
#define EXYNOS4_GPIO_PART1_BASE 0x11400000
|
||||
#define EXYNOS4_FIMD_BASE 0x11C00000
|
||||
#define EXYNOS4_MIPI_DSIM_BASE 0x11C80000
|
||||
#define EXYNOS4_USBOTG_BASE 0x12480000
|
||||
#define EXYNOS4_MMC_BASE 0x12510000
|
||||
#define EXYNOS4_SROMC_BASE 0x12570000
|
||||
|
@ -65,6 +67,7 @@
|
|||
#define EXYNOS5_GPIO_PART3_BASE 0x10D10000
|
||||
#define EXYNOS5_DMC_CTRL_BASE 0x10DD0000
|
||||
#define EXYNOS5_GPIO_PART1_BASE 0x11400000
|
||||
#define EXYNOS5_MIPI_DSIM_BASE 0x11D00000
|
||||
#define EXYNOS5_MMC_BASE 0x12200000
|
||||
#define EXYNOS5_SROMC_BASE 0x12250000
|
||||
#define EXYNOS5_USBOTG_BASE 0x12480000
|
||||
|
@ -127,7 +130,9 @@ static inline unsigned int samsung_get_base_##device(void) \
|
|||
|
||||
SAMSUNG_BASE(adc, ADC_BASE)
|
||||
SAMSUNG_BASE(clock, CLOCK_BASE)
|
||||
SAMSUNG_BASE(sysreg, SYSREG_BASE)
|
||||
SAMSUNG_BASE(fimd, FIMD_BASE)
|
||||
SAMSUNG_BASE(mipi_dsim, MIPI_DSIM_BASE)
|
||||
SAMSUNG_BASE(gpio_part1, GPIO_PART1_BASE)
|
||||
SAMSUNG_BASE(gpio_part2, GPIO_PART2_BASE)
|
||||
SAMSUNG_BASE(gpio_part3, GPIO_PART3_BASE)
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Samsung Electronics
|
||||
*
|
||||
* Author: InKi Dae <inki.dae@samsung.com>
|
||||
* Author: Donghwa Lee <dh09.lee@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARM_ARCH_DSIM_H_
|
||||
#define __ASM_ARM_ARCH_DSIM_H_
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
struct exynos_mipi_dsim {
|
||||
unsigned int status;
|
||||
unsigned int swrst;
|
||||
unsigned int clkctrl;
|
||||
unsigned int timeout;
|
||||
unsigned int config;
|
||||
unsigned int escmode;
|
||||
unsigned int mdresol;
|
||||
unsigned int mvporch;
|
||||
unsigned int mhporch;
|
||||
unsigned int msync;
|
||||
unsigned int sdresol;
|
||||
unsigned int intsrc;
|
||||
unsigned int intmsk;
|
||||
unsigned int pkthdr;
|
||||
unsigned int payload;
|
||||
unsigned int rxfifo;
|
||||
unsigned int fifothld;
|
||||
unsigned int fifoctrl;
|
||||
unsigned int memacchr;
|
||||
unsigned int pllctrl;
|
||||
unsigned int plltmr;
|
||||
unsigned int phyacchr;
|
||||
unsigned int phyacchr1;
|
||||
};
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
* Bit Definitions
|
||||
*/
|
||||
/* DSIM_STATUS */
|
||||
#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
|
||||
#define DSIM_STOP_STATE_CLK (1 << 8)
|
||||
#define DSIM_TX_READY_HS_CLK (1 << 10)
|
||||
#define DSIM_PLL_STABLE (1 << 31)
|
||||
|
||||
/* DSIM_SWRST */
|
||||
#define DSIM_FUNCRST (1 << 16)
|
||||
#define DSIM_SWRST (1 << 0)
|
||||
|
||||
/* EXYNOS_DSIM_TIMEOUT */
|
||||
#define DSIM_LPDR_TOUT_SHIFT (0)
|
||||
#define DSIM_BTA_TOUT_SHIFT (16)
|
||||
|
||||
/* EXYNOS_DSIM_CLKCTRL */
|
||||
#define DSIM_LANE_ESC_CLKEN_SHIFT (19)
|
||||
#define DSIM_BYTE_CLKEN_SHIFT (24)
|
||||
#define DSIM_BYTE_CLK_SRC_SHIFT (25)
|
||||
#define DSIM_PLL_BYPASS_SHIFT (27)
|
||||
#define DSIM_ESC_CLKEN_SHIFT (28)
|
||||
#define DSIM_TX_REQUEST_HSCLK_SHIFT (31)
|
||||
#define DSIM_LANE_ESC_CLKEN(x) (((x) & 0x1f) << \
|
||||
DSIM_LANE_ESC_CLKEN_SHIFT)
|
||||
#define DSIM_BYTE_CLK_ENABLE (1 << DSIM_BYTE_CLKEN_SHIFT)
|
||||
#define DSIM_BYTE_CLK_DISABLE (0 << DSIM_BYTE_CLKEN_SHIFT)
|
||||
#define DSIM_PLL_BYPASS_EXTERNAL (1 << DSIM_PLL_BYPASS_SHIFT)
|
||||
#define DSIM_ESC_CLKEN_ENABLE (1 << DSIM_ESC_CLKEN_SHIFT)
|
||||
#define DSIM_ESC_CLKEN_DISABLE (0 << DSIM_ESC_CLKEN_SHIFT)
|
||||
|
||||
/* EXYNOS_DSIM_CONFIG */
|
||||
#define DSIM_NUM_OF_DATALANE_SHIFT (5)
|
||||
#define DSIM_SUBPIX_SHIFT (8)
|
||||
#define DSIM_MAINPIX_SHIFT (12)
|
||||
#define DSIM_SUBVC_SHIFT (16)
|
||||
#define DSIM_MAINVC_SHIFT (18)
|
||||
#define DSIM_HSA_MODE_SHIFT (20)
|
||||
#define DSIM_HBP_MODE_SHIFT (21)
|
||||
#define DSIM_HFP_MODE_SHIFT (22)
|
||||
#define DSIM_HSE_MODE_SHIFT (23)
|
||||
#define DSIM_AUTO_MODE_SHIFT (24)
|
||||
#define DSIM_VIDEO_MODE_SHIFT (25)
|
||||
#define DSIM_BURST_MODE_SHIFT (26)
|
||||
#define DSIM_EOT_PACKET_SHIFT (28)
|
||||
#define DSIM_AUTO_FLUSH_SHIFT (29)
|
||||
#define DSIM_LANE_ENx(x) (((x) & 0x1f) << 0)
|
||||
|
||||
#define DSIM_NUM_OF_DATA_LANE(x) ((x) << DSIM_NUM_OF_DATALANE_SHIFT)
|
||||
|
||||
/* EXYNOS_DSIM_ESCMODE */
|
||||
#define DSIM_TX_LPDT_SHIFT (6)
|
||||
#define DSIM_CMD_LPDT_SHIFT (7)
|
||||
#define DSIM_TX_LPDT_LP (1 << DSIM_TX_LPDT_SHIFT)
|
||||
#define DSIM_CMD_LPDT_LP (1 << DSIM_CMD_LPDT_SHIFT)
|
||||
#define DSIM_STOP_STATE_CNT_SHIFT (21)
|
||||
#define DSIM_FORCE_STOP_STATE_SHIFT (20)
|
||||
|
||||
/* EXYNOS_DSIM_MDRESOL */
|
||||
#define DSIM_MAIN_STAND_BY (1 << 31)
|
||||
#define DSIM_MAIN_VRESOL(x) (((x) & 0x7ff) << 16)
|
||||
#define DSIM_MAIN_HRESOL(x) (((x) & 0X7ff) << 0)
|
||||
|
||||
/* EXYNOS_DSIM_MVPORCH */
|
||||
#define DSIM_CMD_ALLOW_SHIFT (28)
|
||||
#define DSIM_STABLE_VFP_SHIFT (16)
|
||||
#define DSIM_MAIN_VBP_SHIFT (0)
|
||||
#define DSIM_CMD_ALLOW_MASK (0xf << DSIM_CMD_ALLOW_SHIFT)
|
||||
#define DSIM_STABLE_VFP_MASK (0x7ff << DSIM_STABLE_VFP_SHIFT)
|
||||
#define DSIM_MAIN_VBP_MASK (0x7ff << DSIM_MAIN_VBP_SHIFT)
|
||||
|
||||
/* EXYNOS_DSIM_MHPORCH */
|
||||
#define DSIM_MAIN_HFP_SHIFT (16)
|
||||
#define DSIM_MAIN_HBP_SHIFT (0)
|
||||
#define DSIM_MAIN_HFP_MASK ((0xffff) << DSIM_MAIN_HFP_SHIFT)
|
||||
#define DSIM_MAIN_HBP_MASK ((0xffff) << DSIM_MAIN_HBP_SHIFT)
|
||||
|
||||
/* EXYNOS_DSIM_MSYNC */
|
||||
#define DSIM_MAIN_VSA_SHIFT (22)
|
||||
#define DSIM_MAIN_HSA_SHIFT (0)
|
||||
#define DSIM_MAIN_VSA_MASK ((0x3ff) << DSIM_MAIN_VSA_SHIFT)
|
||||
#define DSIM_MAIN_HSA_MASK ((0xffff) << DSIM_MAIN_HSA_SHIFT)
|
||||
|
||||
/* EXYNOS_DSIM_SDRESOL */
|
||||
#define DSIM_SUB_STANDY_SHIFT (31)
|
||||
#define DSIM_SUB_VRESOL_SHIFT (16)
|
||||
#define DSIM_SUB_HRESOL_SHIFT (0)
|
||||
#define DSIM_SUB_STANDY_MASK ((0x1) << DSIM_SUB_STANDY_SHIFT)
|
||||
#define DSIM_SUB_VRESOL_MASK ((0x7ff) << DSIM_SUB_VRESOL_SHIFT)
|
||||
#define DSIM_SUB_HRESOL_MASK ((0x7ff) << DSIM_SUB_HRESOL_SHIFT)
|
||||
|
||||
/* EXYNOS_DSIM_INTSRC */
|
||||
#define INTSRC_FRAME_DONE (1 << 24)
|
||||
#define INTSRC_PLL_STABLE (1 << 31)
|
||||
#define INTSRC_SWRST_RELEASE (1 << 30)
|
||||
|
||||
/* EXYNOS_DSIM_INTMSK */
|
||||
#define INTMSK_FRAME_DONE (1 << 24)
|
||||
|
||||
/* EXYNOS_DSIM_FIFOCTRL */
|
||||
#define SFR_HEADER_EMPTY (1 << 22)
|
||||
|
||||
/* EXYNOS_DSIM_PKTHDR */
|
||||
#define DSIM_PKTHDR_DI(x) (((x) & 0x3f) << 0)
|
||||
#define DSIM_PKTHDR_DAT0(x) ((x) << 8)
|
||||
#define DSIM_PKTHDR_DAT1(x) ((x) << 16)
|
||||
|
||||
/* EXYNOS_DSIM_PHYACCHR */
|
||||
#define DSIM_AFC_CTL(x) (((x) & 0x7) << 5)
|
||||
#define DSIM_AFC_CTL_SHIFT (5)
|
||||
#define DSIM_AFC_EN (1 << 14)
|
||||
|
||||
/* EXYNOS_DSIM_PHYACCHR1 */
|
||||
#define DSIM_DPDN_SWAP_DATA_SHIFT (0)
|
||||
|
||||
/* EXYNOS_DSIM_PLLCTRL */
|
||||
#define DSIM_SCALER_SHIFT (1)
|
||||
#define DSIM_MAIN_SHIFT (4)
|
||||
#define DSIM_PREDIV_SHIFT (13)
|
||||
#define DSIM_PRECTRL_SHIFT (20)
|
||||
#define DSIM_PLL_EN_SHIFT (23)
|
||||
#define DSIM_FREQ_BAND_SHIFT (24)
|
||||
#define DSIM_ZEROCTRL_SHIFT (28)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* SAMSUNG S5P USB HOST EHCI Controller
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics Co.Ltd
|
||||
* Vivek Gautam <gautam.vivek@samsung.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., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARM_ARCH_EXYNOS5_EHCI_S5P_H__
|
||||
#define __ASM_ARM_ARCH_EXYNOS5_EHCI_S5P_H__
|
||||
|
||||
#define CLK_24MHZ 5
|
||||
|
||||
#define HOST_CTRL0_PHYSWRSTALL (1 << 31)
|
||||
#define HOST_CTRL0_COMMONON_N (1 << 9)
|
||||
#define HOST_CTRL0_SIDDQ (1 << 6)
|
||||
#define HOST_CTRL0_FORCESLEEP (1 << 5)
|
||||
#define HOST_CTRL0_FORCESUSPEND (1 << 4)
|
||||
#define HOST_CTRL0_WORDINTERFACE (1 << 3)
|
||||
#define HOST_CTRL0_UTMISWRST (1 << 2)
|
||||
#define HOST_CTRL0_LINKSWRST (1 << 1)
|
||||
#define HOST_CTRL0_PHYSWRST (1 << 0)
|
||||
|
||||
#define HOST_CTRL0_FSEL_MASK (7 << 16)
|
||||
|
||||
#define EHCICTRL_ENAINCRXALIGN (1 << 29)
|
||||
#define EHCICTRL_ENAINCR4 (1 << 28)
|
||||
#define EHCICTRL_ENAINCR8 (1 << 27)
|
||||
#define EHCICTRL_ENAINCR16 (1 << 26)
|
||||
|
||||
/* Register map for PHY control */
|
||||
struct s5p_usb_phy {
|
||||
unsigned int usbphyctrl0;
|
||||
unsigned int usbphytune0;
|
||||
unsigned int reserved1[2];
|
||||
unsigned int hsicphyctrl1;
|
||||
unsigned int hsicphytune1;
|
||||
unsigned int reserved2[2];
|
||||
unsigned int hsicphyctrl2;
|
||||
unsigned int hsicphytune2;
|
||||
unsigned int reserved3[2];
|
||||
unsigned int ehcictrl;
|
||||
unsigned int ohcictrl;
|
||||
unsigned int usbotgsys;
|
||||
unsigned int reserved4;
|
||||
unsigned int usbotgtune;
|
||||
};
|
||||
|
||||
/* Switch on the VBUS power. */
|
||||
int board_usb_vbus_init(void);
|
||||
|
||||
#endif /* __ASM_ARM_ARCH_EXYNOS5_EHCI_S5P_H__ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue