Project import generated by Copybara. GitOrigin-RevId: fa3391ccde1707420482f0934a3143ec9d1d16b7
diff --git a/.checkpatch.conf b/.checkpatch.conf new file mode 100644 index 0000000..95f1963 --- /dev/null +++ b/.checkpatch.conf
@@ -0,0 +1,30 @@ +# Not Linux, so don't expect a Linux tree. +--no-tree + +# Temporary for false positive in checkpatch +--ignore COMPLEX_MACRO + +# For CONFIG_SYS_I2C_NOPROBES +--ignore MULTISTATEMENT_MACRO_USE_DO_WHILE + +# For simple_strtoul +--ignore CONSIDER_KSTRTO + +# For min/max +--ignore MINMAX + +# enable more tests +--strict + +# Not Linux, so we don't recommend usleep_range() over udelay() +--ignore USLEEP_RANGE + +# Ignore networking block comment style +--ignore NETWORKING_BLOCK_COMMENT_STYLE + +# Ignore "WARNING: Prefer ether_addr_copy() over memcpy() if the Ethernet +# addresses are __aligned(2)". +--ignore PREFER_ETHER_ADDR_COPY + +# A bit shorter of a description is OK with us. +--min-conf-desc-length=2
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..23599b9 --- /dev/null +++ b/.github/pull_request_template.md
@@ -0,0 +1,3 @@ +Please do not submit a Pull Request via github. Our project makes use of +mailing lists for patch submission and review. For more details please +see https://www.denx.de/wiki/U-Boot/Patches
diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000..1bee048 --- /dev/null +++ b/.mailmap
@@ -0,0 +1,38 @@ +# +# This list is used by git-shortlog to fix a few botched name translations +# in the git archive, either because the author's full name was messed up +# and/or not always written the same way, making contributions from the +# same person appearing not to be so or badly displayed. +# +# This file can be modified by hand or updated by the following command: +# scripts/mailmapper > tmp; mv tmp .mailmap +# + +Allen Martin <amartin@nvidia.com> +Andreas Bießmann <andreas.devel@googlemail.com> +Andreas Bießmann <andreas@biessmann.org> +Aneesh V <aneesh@ti.com> +Dirk Behme <dirk.behme@googlemail.com> +Fabio Estevam <fabio.estevam@nxp.com> +Jagan Teki <402jagan@gmail.com> +Jagan Teki <jaganna@gmail.com> +Jagan Teki <jaganna@xilinx.com> +Jagan Teki <jagannadh.teki@gmail.com> +Jagan Teki <jagannadha.sutradharudu-teki@xilinx.com> +Markus Klotzbuecher <mk@denx.de> +Paul Burton <paul.burton@mips.com> <paul.burton@imgtec.com> +Prabhakar Kushwaha <prabhakar@freescale.com> +Rajeshwari Shinde <rajeshwari.s@samsung.com> +Ricardo Ribalda <ricardo.ribalda@uam.es> +Ricardo Ribalda <ricardo.ribalda@gmail.com> +Sandeep Paulraj <s-paulraj@ti.com> +Shaohui Xie <Shaohui.Xie@freescale.com> +Stefan Roese <stroese> +Stefano Babic <sbabic@denx.de> +TsiChung Liew <Tsi-Chung.Liew@freescale.com> +Wolfgang Denk <wdenk> +York Sun <yorksun@freescale.com> +York Sun <york.sun@nxp.com> +Ćukasz Majewski <l.majewski@samsung.com> +Lukasz Majewski <lukma@denx.de> +Mirza <Taimoor_Mirza@mentor.com>
diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..321fd79 --- /dev/null +++ b/.travis.yml
@@ -0,0 +1,465 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright Roger Meier <r.meier@siemens.com> + +# build U-Boot on Travis CI - https://travis-ci.org/ + +sudo: required +dist: trusty + +language: c + +addons: + apt: + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-7 + packages: + - cppcheck + - sloccount + - sparse + - bc + - build-essential + - libsdl1.2-dev + - python + - python-virtualenv + - swig + - libpython-dev + - iasl + - grub-efi-ia32-bin + - grub-efi-amd64-bin + - rpm2cpio + - wget + - device-tree-compiler + - lzop + - liblz4-tool + - libisl15 + - clang-7 + +install: + # Clone uboot-test-hooks + - git clone --depth=1 git://github.com/swarren/uboot-test-hooks.git /tmp/uboot-test-hooks + - ln -s travis-ci /tmp/uboot-test-hooks/bin/`hostname` + - ln -s travis-ci /tmp/uboot-test-hooks/py/`hostname` + # prepare buildman environment + - echo -e "[toolchain]\nroot = /usr" > ~/.buildman + - echo -e "arc = /tmp/arc_gnu_2018.09_prebuilt_uclibc_le_archs_linux_install" >> ~/.buildman + - echo -e "\n[toolchain-alias]\nsh = sh2\n" >> ~/.buildman + - cat ~/.buildman + - virtualenv /tmp/venv + - . /tmp/venv/bin/activate + - pip install pytest==2.8.7 + - pip install python-subunit + - grub-mkimage -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd + - grub-mkimage -o ~/grub_x64.efi -O x86_64-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd + - mkdir ~/grub2-arm + - ( cd ~/grub2-arm; wget -O - http://download.opensuse.org/ports/armv7hl/distribution/leap/42.2/repo/oss/suse/armv7hl/grub2-arm-efi-2.02~beta2-87.1.armv7hl.rpm | rpm2cpio | cpio -di ) + - mkdir ~/grub2-arm64 + - ( cd ~/grub2-arm64; wget -O - http://download.opensuse.org/ports/aarch64/distribution/leap/42.2/repo/oss/suse/aarch64/grub2-arm64-efi-2.02~beta2-87.1.aarch64.rpm | rpm2cpio | cpio -di ) + +env: + global: + - PATH=/tmp/qemu-install/bin:/tmp/uboot-test-hooks/bin:/usr/bin:/bin + - PYTHONPATH=/tmp/uboot-test-hooks/py/travis-ci + - BUILD_DIR=build + - HOSTCC="cc" + - HOSTCXX="c++" + +before_script: + # install toolchains based on TOOLCHAIN} variable + - if [[ "${TOOLCHAIN}" == *m68k* ]]; then ./tools/buildman/buildman --fetch-arch m68k ; fi + - if [[ "${TOOLCHAIN}" == *microblaze* ]]; then ./tools/buildman/buildman --fetch-arch microblaze ; fi + - if [[ "${TOOLCHAIN}" == *mips* ]]; then ./tools/buildman/buildman --fetch-arch mips ; fi + - if [[ "${TOOLCHAIN}" == *sh* ]]; then ./tools/buildman/buildman --fetch-arch sh2 ; fi + - if [[ "${TOOLCHAIN}" == *i386* ]]; then + ./tools/buildman/buildman --fetch-arch i386; + echo -e "\n[toolchain-alias]\nx86 = i386" >> ~/.buildman; + fi + - if [[ "${TOOLCHAIN}" == arc ]]; then + wget https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases/download/arc-2018.09-release/arc_gnu_2018.09_prebuilt_uclibc_le_archs_linux_install.tar.gz && + tar -C /tmp -xf arc_gnu_2018.09_prebuilt_uclibc_le_archs_linux_install.tar.gz; + fi + - if [[ "${TOOLCHAIN}" == *xtensa* ]]; then + wget https://github.com/foss-xtensa/toolchain/releases/download/2018.02/x86_64-2018.02-${TOOLCHAIN}.tar.gz && + tar -C /tmp -xf x86_64-2018.02-${TOOLCHAIN}.tar.gz && + echo -e "\n[toolchain-prefix]\nxtensa = /tmp/2018.02/${TOOLCHAIN}/bin/${TOOLCHAIN}-" >> ~/.buildman; + fi + # If TOOLCHAIN is unset, we're on some flavour of ARM. + - if [[ "${TOOLCHAIN}" == "" ]]; then + ./tools/buildman/buildman --fetch-arch arm && + ./tools/buildman/buildman --fetch-arch aarch64; + fi + - if [[ "${TOOLCHAIN}" == "powerpc" ]]; then ./tools/buildman/buildman --fetch-arch powerpc; fi + - if [[ "${TOOLCHAIN}" == "riscv" ]]; then + ./tools/buildman/buildman --fetch-arch riscv64; + echo -e "\n[toolchain-alias]\nriscv = riscv64" >> ~/.buildman; + fi + - if [[ "${QEMU_TARGET}" != "" ]]; then + git clone git://git.qemu.org/qemu.git /tmp/qemu; + pushd /tmp/qemu; + git submodule update --init dtc && + git checkout v3.0.0 && + ./configure --prefix=/tmp/qemu-install --target-list=${QEMU_TARGET} && + make -j4 all install; + popd; + fi + +script: + # Comments must be outside the command strings below, or the Travis parser + # will get confused. + # + # From buildman, exit code 129 means warnings only. If we've been asked to + # use clang only do one configuration. + - if [[ "${TOOLCHAIN}" == "clang" ]]; then + ret=0; + make O=../.bm-work/${TEST_PY_BD} HOSTCC=clang-7 CC=clang-7 -j$(nproc) + KCFLAGS=-Werror sandbox_config all || ret=$?; + if [[ $ret -ne 0 ]]; then + exit $ret; + fi; + elif [[ "${BUILDMAN}" != "" ]]; then + ret=0; + tools/buildman/buildman -P -E ${BUILDMAN} || ret=$?; + if [[ $ret -ne 0 && $ret -ne 129 ]]; then + tools/buildman/buildman -sdeP ${BUILDMAN}; + exit $ret; + fi; + fi + # "not a_test_which_does_not_exist" is a dummy -k parameter which will + # never prevent any test from running. That way, we can always pass + # "-k something" even when $TEST_PY_TEST_SPEC doesnt need a custom + # value. + - export UBOOT_TRAVIS_BUILD_DIR=`cd .. && pwd`/.bm-work/${TEST_PY_BD}; + cp ~/grub_x86.efi $UBOOT_TRAVIS_BUILD_DIR/; + cp ~/grub_x64.efi $UBOOT_TRAVIS_BUILD_DIR/; + cp ~/grub2-arm/usr/lib/grub2/arm-efi/grub.efi $UBOOT_TRAVIS_BUILD_DIR/grub_arm.efi; + cp ~/grub2-arm64/usr/lib/grub2/arm64-efi/grub.efi $UBOOT_TRAVIS_BUILD_DIR/grub_arm64.efi; + if [[ "${TEST_PY_BD}" != "" ]]; then + ./test/py/test.py --bd ${TEST_PY_BD} ${TEST_PY_ID} + -k "${TEST_PY_TEST_SPEC:-not a_test_which_does_not_exist}" + --build-dir "$UBOOT_TRAVIS_BUILD_DIR"; + ret=$?; + if [[ $ret -ne 0 ]]; then + exit $ret; + fi; + fi; + if [[ -n "${TEST_PY_TOOLS}" ]]; then + PYTHONPATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc/pylibfdt" + PATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc:${PATH}" + ./tools/binman/binman -t && + ./tools/patman/patman --test && + ./tools/buildman/buildman -t && + PYTHONPATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc/pylibfdt" + PATH="${UBOOT_TRAVIS_BUILD_DIR}/scripts/dtc:${PATH}" + ./tools/dtoc/dtoc -t; + fi + +matrix: + include: + # we need to build by vendor due to 50min time limit for builds + # each env setting here is a dedicated build + - name: "buildman arc" + env: + - BUILDMAN="arc" + TOOLCHAIN="arc" + - name: "buildman arm11 arm7 arm920t arm946es" + env: + - BUILDMAN="arm11 arm7 arm920t arm946es" + - name: "buildman arm926ejs (non-freescale,siemens,atmel,kirkwood,spear)" + env: + - JOB="arm926ejs" + BUILDMAN="arm926ejs -x freescale,siemens,atmel,kirkwood,spear" + - name: "buildman atmel" + env: + - BUILDMAN="atmel" + - name: "buildman boundary engicam toradex" + env: + - BUILDMAN="boundary engicam toradex" + - name: "buildman Freescale ARM32" + env: + - BUILDMAN="freescale -x powerpc,m68k,aarch64" + - name: "buildman Freescale AArch64 LS10xx" + env: + - BUILDMAN="freescale&aarch64&&ls1" + - name: "buildman Freescale AArch64 LS20xx" + env: + - BUILDMAN="freescale&aarch64&&ls2" + - name: "buildman i.MX6 (non-Freescale)" + env: + - BUILDMAN="mx6 -x freescale,toradex,boundary,engicam" + - name: "buildman i.MX (non-Freescale,i.MX6,toradex)" + env: + - BUILDMAN="mx -x freescale,mx6,toradex" + - name: "buildman k2" + env: + - BUILDMAN="k2" + - name: "buildman samsung socfpga" + env: + - BUILDMAN="samsung socfpga" + - name: "buildman spear" + env: + - BUILDMAN="spear" + - name: "buildman sun4i" + env: + - BUILDMAN="sun4i" + - name: "buildman sun5i" + env: + - BUILDMAN="sun5i" + - name: "buildman sun6i" + env: + - BUILDMAN="sun6i" + - name: "buildman sun7i" + env: + - BUILDMAN="sun7i" + - name: "buildman sun8i" + env: + - BUILDMAN="sun8i" + - name: "buildman sun9i" + env: + - BUILDMAN="sun9i" + - name: "buildman sun50i" + env: + - BUILDMAN="sun50i" + - name: "buildman catch-all ARM" + env: + - BUILDMAN="arm -x arm11,arm7,arm9,aarch64,atmel,freescale,kirkwood,mvebu,siemens,tegra,uniphier,mx,samsung,sunxi,am33xx,omap,pxa,rockchip,toradex,socfpga,k2,xilinx" + - name: "buildman sandbox x86" + env: + - BUILDMAN="sandbox x86" + TOOLCHAIN="i386" + - name: "buildman kirkwood (excluding openrd)" + env: + - BUILDMAN="kirkwood -x openrd" + - name: "buildman mvebu" + env: + - BUILDMAN="mvebu" + - name: "buildman PXA (non-toradex)" + env: + - BUILDMAN="pxa -x toradex" + - name: "buildman m68k" + env: + - BUILDMAN="m68k" + TOOLCHAIN="m68k" + - name: "buildman microblaze" + env: + - BUILDMAN="microblaze" + TOOLCHAIN="microblaze" + - name: "buildman mips" + env: + - BUILDMAN="mips" + TOOLCHAIN="mips" + - name: "buildman non-Freescale PowerPC" + env: + - BUILDMAN="powerpc -x freescale" + TOOLCHAIN="powerpc" + - name: "buildman mpc85xx&freescale (excluding many)" + env: + - BUILDMAN="mpc85xx&freescale -x t208xrdb -x t4qds -x t102* -x p1_p2_rdb_pc -x p1010rdb -x corenet_ds -x b4860qds -x bsc91*" + TOOLCHAIN="powerpc" + - name: "buildman t208xrdb corenet_ds" + env: + - BUILDMAN="t208xrdb corenet_ds" + TOOLCHAIN="powerpc" + - name: "buildman Freescale PowerPC" + env: + - BUILDMAN="t4qds b4860qds mpc83xx&freescale mpc86xx&freescale" + TOOLCHAIN="powerpc" + - name: "buildman t102*" + env: + - BUILDMAN="t102*" + TOOLCHAIN="powerpc" + - name: "buildman p1_p2_rdb_pc" + env: + - BUILDMAN="p1_p2_rdb_pc" + TOOLCHAIN="powerpc" + - name: "buildman p1010rdb bsc91" + env: + - BUILDMAN="p1010rdb bsc91" + TOOLCHAIN="powerpc" + - name: "buildman siemens" + env: + - BUILDMAN="siemens" + - name: "buildman tegra" + env: + - BUILDMAN="tegra -x toradex" + - name: "buildman am33xx (no siemens)" + env: + - BUILDMAN="am33xx -x siemens" + - name: "buildman omap" + env: + - BUILDMAN="omap" + - name: "buildman uniphier" + env: + - BUILDMAN="uniphier" + - name: "buildman catch-all AArch64" + env: + - BUILDMAN="aarch64 -x tegra,ls1,ls2,mvebu,uniphier,sunxi,samsung,rockchip,xilinx" + - name: "buildman rockchip" + env: + - BUILDMAN="rockchip" + - name: "buildman sh" + env: + - BUILDMAN="sh -x arm" + TOOLCHAIN="sh" + - name: "buildman Xilinx (ARM)" + env: + - BUILDMAN="xilinx -x microblaze" + - name: "buildman xtensa" + env: + - BUILDMAN="xtensa" + TOOLCHAIN="xtensa-dc233c-elf" + - name: "buildman riscv" + env: + - BUILDMAN="riscv" + TOOLCHAIN="riscv" + + # QA jobs for code analytics + # static code analysis with cppcheck (we can add --enable=all later) + - name: "cppcheck" + script: + - cppcheck --force --quiet --inline-suppr . + # search for TODO within source tree + - name: "grep TODO" + script: + - grep -r TODO . + # search for FIXME within source tree + - name: "grep FIXME HACK" + script: + - grep -r FIXME . + # search for HACK within source tree and ignore HACKKIT board + script: + - grep -r HACK . | grep -v HACKKIT + # some statistics about the code base + - name: "sloccount" + script: + - sloccount . + # ensure all configs have MAINTAINERS entries + - name: "Check for configs without MAINTAINERS entry" + script: + - if [ `./tools/genboardscfg.py -f 2>&1 | wc -l` -ne 0 ]; then exit 1; fi + # Ensure host tools build + - name: "Build tools-only" + script: + - make tools-only_config tools-only -j$(nproc) + + # test/py + - name: "test/py sandbox" + env: + - TEST_PY_BD="sandbox" + BUILDMAN="^sandbox$" + TOOLCHAIN="i386" + - name: "test/py sandbox with clang" + env: + - TEST_PY_BD="sandbox" + BUILDMAN="^sandbox$" + TOOLCHAIN="clang" + - name: "test/py sandbox_spl" + env: + - TEST_PY_BD="sandbox_spl" + TEST_PY_TEST_SPEC="test_ofplatdata" + BUILDMAN="^sandbox$" + TOOLCHAIN="i386" + TEST_PY_TOOLS="yes" + - name: "test/py sandbox_flattree" + env: + - TEST_PY_BD="sandbox_flattree" + BUILDMAN="^sandbox_flattree$" + TOOLCHAIN="i386" + - name: "test/py vexpress_ca15_tc2" + env: + - TEST_PY_BD="vexpress_ca15_tc2" + TEST_PY_ID="--id qemu" + QEMU_TARGET="arm-softmmu" + BUILDMAN="^vexpress_ca15_tc2$" + - name: "test/py vexpress_ca9x4" + env: + - TEST_PY_BD="vexpress_ca9x4" + TEST_PY_ID="--id qemu" + QEMU_TARGET="arm-softmmu" + BUILDMAN="^vexpress_ca9x4$" + - name: "test/py integratorcp_cm926ejs" + env: + - TEST_PY_BD="integratorcp_cm926ejs" + TEST_PY_TEST_SPEC="not sleep" + TEST_PY_ID="--id qemu" + QEMU_TARGET="arm-softmmu" + BUILDMAN="^integratorcp_cm926ejs$" + - name: "test/py qemu_arm" + env: + - TEST_PY_BD="qemu_arm" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="arm-softmmu" + BUILDMAN="^qemu_arm$" + - name: "test/py qemu_arm64" + env: + - TEST_PY_BD="qemu_arm64" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="aarch64-softmmu" + BUILDMAN="^qemu_arm64$" + - name: "test/py qemu_mips" + env: + - TEST_PY_BD="qemu_mips" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="mips-softmmu" + BUILDMAN="^qemu_mips$" + TOOLCHAIN="mips" + - name: "test/py qemu_mipsel" + env: + - TEST_PY_BD="qemu_mipsel" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="mipsel-softmmu" + BUILDMAN="^qemu_mipsel$" + TOOLCHAIN="mips" + - name: "test/py qemu_mips64" + env: + - TEST_PY_BD="qemu_mips64" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="mips64-softmmu" + BUILDMAN="^qemu_mips64$" + TOOLCHAIN="mips" + - name: "test/py qemu_mips64el" + env: + - TEST_PY_BD="qemu_mips64el" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="mips64el-softmmu" + BUILDMAN="^qemu_mips64el$" + TOOLCHAIN="mips" + - name: "test/py qemu-ppce500" + env: + - TEST_PY_BD="qemu-ppce500" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="ppc-softmmu" + BUILDMAN="^qemu-ppce500$" + TOOLCHAIN="powerpc" + - name: "test/py qemu-x86" + env: + - TEST_PY_BD="qemu-x86" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="i386-softmmu" + BUILDMAN="^qemu-x86$" + TOOLCHAIN="i386" + BUILD_ROM="yes" + - name: "test/py qemu-x86_64" + env: + - TEST_PY_BD="qemu-x86_64" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="x86_64-softmmu" + BUILDMAN="^qemu-x86_64$" + TOOLCHAIN="i386" + BUILD_ROM="yes" + - name: "test/py zynq_zc702" + env: + - TEST_PY_BD="zynq_zc702" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="arm-softmmu" + TEST_PY_ID="--id qemu" + BUILDMAN="^zynq_zc702$" + - name: "test/py xtfpga" + env: + - TEST_PY_BD="xtfpga" + TEST_PY_TEST_SPEC="not sleep" + QEMU_TARGET="xtensa-softmmu" + TEST_PY_ID="--id qemu" + BUILDMAN="^xtfpga$" + TOOLCHAIN="xtensa-dc233c-elf" + +# TODO make it perfect ;-r
diff --git a/Documentation/.gitignore b/Documentation/.gitignore new file mode 100644 index 0000000..e74fec8 --- /dev/null +++ b/Documentation/.gitignore
@@ -0,0 +1,2 @@ +output +*.pyc
diff --git a/Documentation/Makefile b/Documentation/Makefile new file mode 100644 index 0000000..2ca77ad --- /dev/null +++ b/Documentation/Makefile
@@ -0,0 +1,124 @@ +# -*- makefile -*- +# Makefile for Sphinx documentation +# + +subdir-y := + +# You can set these variables from the command line. +SPHINXBUILD = sphinx-build +SPHINXOPTS = +SPHINXDIRS = . +_SPHINXDIRS = $(patsubst $(srctree)/Documentation/%/conf.py,%,$(wildcard $(srctree)/Documentation/*/conf.py)) +SPHINX_CONF = conf.py +PAPER = +BUILDDIR = $(obj)/output +PDFLATEX = xelatex +LATEXOPTS = -interaction=batchmode + +# User-friendly check for sphinx-build +HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi) + +ifeq ($(HAVE_SPHINX),0) + +.DEFAULT: + $(warning The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed and in PATH, or set the SPHINXBUILD make variable to point to the full path of the '$(SPHINXBUILD)' executable.) + @echo + @./scripts/sphinx-pre-install + @echo " SKIP Sphinx $@ target." + +else # HAVE_SPHINX + +# User-friendly check for pdflatex +HAVE_PDFLATEX := $(shell if which $(PDFLATEX) >/dev/null 2>&1; then echo 1; else echo 0; fi) + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +KERNELDOC = $(srctree)/scripts/kernel-doc +KERNELDOC_CONF = -D kerneldoc_srctree=$(srctree) -D kerneldoc_bin=$(KERNELDOC) +ALLSPHINXOPTS = $(KERNELDOC_CONF) $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +# commands; the 'cmd' from scripts/Kbuild.include is not *loopable* +loop_cmd = $(echo-cmd) $(cmd_$(1)) || exit; + +# $2 sphinx builder e.g. "html" +# $3 name of the build subfolder / e.g. "media", used as: +# * dest folder relative to $(BUILDDIR) and +# * cache folder relative to $(BUILDDIR)/.doctrees +# $4 dest subfolder e.g. "man" for man pages at media/man +# $5 reST source folder relative to $(srctree)/$(src), +# e.g. "media" for the linux-tv book-set at ./Documentation/media + +quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4) + cmd_sphinx = $(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media $2 && \ + PYTHONDONTWRITEBYTECODE=1 \ + BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \ + $(SPHINXBUILD) \ + -b $2 \ + -c $(abspath $(srctree)/$(src)) \ + -d $(abspath $(BUILDDIR)/.doctrees/$3) \ + -D version=$(KERNELVERSION) -D release=$(KERNELRELEASE) \ + $(ALLSPHINXOPTS) \ + $(abspath $(srctree)/$(src)/$5) \ + $(abspath $(BUILDDIR)/$3/$4) + +htmldocs: + @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var))) + +linkcheckdocs: + @$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,linkcheck,$(var),,$(var))) + +latexdocs: + @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,latex,$(var),latex,$(var))) + +ifeq ($(HAVE_PDFLATEX),0) + +pdfdocs: + $(warning The '$(PDFLATEX)' command was not found. Make sure you have it installed and in PATH to produce PDF output.) + @echo " SKIP Sphinx $@ target." + +else # HAVE_PDFLATEX + +pdfdocs: latexdocs + $(foreach var,$(SPHINXDIRS), $(MAKE) PDFLATEX=$(PDFLATEX) LATEXOPTS="$(LATEXOPTS)" -C $(BUILDDIR)/$(var)/latex || exit;) + +endif # HAVE_PDFLATEX + +epubdocs: + @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,epub,$(var),epub,$(var))) + +xmldocs: + @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,xml,$(var),xml,$(var))) + +endif # HAVE_SPHINX + +# The following targets are independent of HAVE_SPHINX, and the rules should +# work or silently pass without Sphinx. + +refcheckdocs: + $(Q)cd $(srctree);scripts/documentation-file-ref-check + +cleandocs: + $(Q)rm -rf $(BUILDDIR) + $(Q)$(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media clean + +dochelp: + @echo ' Linux kernel internal documentation in different formats from ReST:' + @echo ' htmldocs - HTML' + @echo ' latexdocs - LaTeX' + @echo ' pdfdocs - PDF' + @echo ' epubdocs - EPUB' + @echo ' xmldocs - XML' + @echo ' linkcheckdocs - check for broken external links (will connect to external hosts)' + @echo ' refcheckdocs - check for references to non-existing files under Documentation' + @echo ' cleandocs - clean all generated files' + @echo + @echo ' make SPHINXDIRS="s1 s2" [target] Generate only docs of folder s1, s2' + @echo ' valid values for SPHINXDIRS are: $(_SPHINXDIRS)' + @echo + @echo ' make SPHINX_CONF={conf-file} [target] use *additional* sphinx-build' + @echo ' configuration. This is e.g. useful to build with nit-picking config.' + @echo + @echo ' Default location for the generated documents is Documentation/output'
diff --git a/Documentation/conf.py b/Documentation/conf.py new file mode 100644 index 0000000..168c313 --- /dev/null +++ b/Documentation/conf.py
@@ -0,0 +1,528 @@ +# -*- coding: utf-8 -*- +# +# The U-Boot documentation build configuration file, created by +# sphinx-quickstart on Fri Feb 12 13:51:46 2016. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import sphinx + +# Get Sphinx version +major, minor, patch = sphinx.version_info[:3] + + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('sphinx')) +from load_config import loadConfig + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = '1.3' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain', 'kfigure'] + +# The name of the math extension changed on Sphinx 1.4 +if major == 1 and minor > 3: + extensions.append("sphinx.ext.imgmath") +else: + extensions.append("sphinx.ext.pngmath") + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'Das U-Boot' +copyright = 'The U-Boot development community' +author = 'The U-Boot development community' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# In a normal build, version and release are are set to KERNELVERSION and +# KERNELRELEASE, respectively, from the Makefile via Sphinx command line +# arguments. +# +# The following code tries to extract the information by reading the Makefile, +# when Sphinx is run directly (e.g. by Read the Docs). +try: + makefile_version = None + makefile_patchlevel = None + for line in open('../Makefile'): + key, val = [x.strip() for x in line.split('=', 2)] + if key == 'VERSION': + makefile_version = val + elif key == 'PATCHLEVEL': + makefile_patchlevel = val + if makefile_version and makefile_patchlevel: + break +except: + pass +finally: + if makefile_version and makefile_patchlevel: + version = release = makefile_version + '.' + makefile_patchlevel + else: + version = release = "unknown version" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['output'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + +primary_domain = 'c' +highlight_language = 'none' + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. + +# The Read the Docs theme is available from +# - https://github.com/snide/sphinx_rtd_theme +# - https://pypi.python.org/pypi/sphinx_rtd_theme +# - python-sphinx-rtd-theme package (on Debian) +try: + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +except ImportError: + sys.stderr.write('Warning: The Sphinx \'sphinx_rtd_theme\' HTML theme was not found. Make sure you have the theme installed to produce pretty HTML output. Falling back to the default theme.\n') + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". + +html_static_path = ['sphinx-static'] + +html_context = { + 'css_files': [ + '_static/theme_overrides.css', + ], +} + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'TheUBootdoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +'papersize': 'a4paper', + +# The font size ('10pt', '11pt' or '12pt'). +'pointsize': '8pt', + +# Latex figure (float) alignment +#'figure_align': 'htbp', + +# Don't mangle with UTF-8 chars +'inputenc': '', +'utf8extra': '', + +# Additional stuff for the LaTeX preamble. + 'preamble': ''' + % Use some font with UTF-8 support with XeLaTeX + \\usepackage{fontspec} + \\setsansfont{DejaVu Serif} + \\setromanfont{DejaVu Sans} + \\setmonofont{DejaVu Sans Mono} + + ''' +} + +# Fix reference escape troubles with Sphinx 1.4.x +if major == 1 and minor > 3: + latex_elements['preamble'] += '\\renewcommand*{\\DUrole}[2]{ #2 }\n' + +if major == 1 and minor <= 4: + latex_elements['preamble'] += '\\usepackage[margin=0.5in, top=1in, bottom=1in]{geometry}' +elif major == 1 and (minor > 5 or (minor == 5 and patch >= 3)): + latex_elements['sphinxsetup'] = 'hmargin=0.5in, vmargin=1in' + latex_elements['preamble'] += '\\fvset{fontsize=auto}\n' + +# Customize notice background colors on Sphinx < 1.6: +if major == 1 and minor < 6: + latex_elements['preamble'] += ''' + \\usepackage{ifthen} + + % Put notes in color and let them be inside a table + \\definecolor{NoteColor}{RGB}{204,255,255} + \\definecolor{WarningColor}{RGB}{255,204,204} + \\definecolor{AttentionColor}{RGB}{255,255,204} + \\definecolor{ImportantColor}{RGB}{192,255,204} + \\definecolor{OtherColor}{RGB}{204,204,204} + \\newlength{\\mynoticelength} + \\makeatletter\\newenvironment{coloredbox}[1]{% + \\setlength{\\fboxrule}{1pt} + \\setlength{\\fboxsep}{7pt} + \\setlength{\\mynoticelength}{\\linewidth} + \\addtolength{\\mynoticelength}{-2\\fboxsep} + \\addtolength{\\mynoticelength}{-2\\fboxrule} + \\begin{lrbox}{\\@tempboxa}\\begin{minipage}{\\mynoticelength}}{\\end{minipage}\\end{lrbox}% + \\ifthenelse% + {\\equal{\\py@noticetype}{note}}% + {\\colorbox{NoteColor}{\\usebox{\\@tempboxa}}}% + {% + \\ifthenelse% + {\\equal{\\py@noticetype}{warning}}% + {\\colorbox{WarningColor}{\\usebox{\\@tempboxa}}}% + {% + \\ifthenelse% + {\\equal{\\py@noticetype}{attention}}% + {\\colorbox{AttentionColor}{\\usebox{\\@tempboxa}}}% + {% + \\ifthenelse% + {\\equal{\\py@noticetype}{important}}% + {\\colorbox{ImportantColor}{\\usebox{\\@tempboxa}}}% + {\\colorbox{OtherColor}{\\usebox{\\@tempboxa}}}% + }% + }% + }% + }\\makeatother + + \\makeatletter + \\renewenvironment{notice}[2]{% + \\def\\py@noticetype{#1} + \\begin{coloredbox}{#1} + \\bf\\it + \\par\\strong{#2} + \\csname py@noticestart@#1\\endcsname + } + { + \\csname py@noticeend@\\py@noticetype\\endcsname + \\end{coloredbox} + } + \\makeatother + + ''' + +# With Sphinx 1.6, it is possible to change the Bg color directly +# by using: +# \definecolor{sphinxnoteBgColor}{RGB}{204,255,255} +# \definecolor{sphinxwarningBgColor}{RGB}{255,204,204} +# \definecolor{sphinxattentionBgColor}{RGB}{255,255,204} +# \definecolor{sphinximportantBgColor}{RGB}{192,255,204} +# +# However, it require to use sphinx heavy box with: +# +# \renewenvironment{sphinxlightbox} {% +# \\begin{sphinxheavybox} +# } +# \\end{sphinxheavybox} +# } +# +# Unfortunately, the implementation is buggy: if a note is inside a +# table, it isn't displayed well. So, for now, let's use boring +# black and white notes. + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +# Sorted in alphabetical order +latex_documents = [ + ('index', 'u-boot-hacker-manual.tex', 'U-Boot Hacker Manual', + 'The U-Boot development community', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'dasuboot', 'The U-Boot Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'DasUBoot', 'The U-Boot Documentation', + author, 'DasUBoot', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +# -- Options for Epub output ---------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project +epub_author = author +epub_publisher = author +epub_copyright = copyright + +# The basename for the epub file. It defaults to the project name. +#epub_basename = project + +# The HTML theme for the epub output. Since the default themes are not +# optimized for small screen space, using the same theme for HTML and epub +# output is usually not wise. This defaults to 'epub', a theme designed to save +# visual space. +#epub_theme = 'epub' + +# The language of the text. It defaults to the language option +# or 'en' if the language is not set. +#epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +#epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +#epub_identifier = '' + +# A unique identification for the text. +#epub_uid = '' + +# A tuple containing the cover image and cover page html template filenames. +#epub_cover = () + +# A sequence of (type, uri, title) tuples for the guide element of content.opf. +#epub_guide = () + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_pre_files = [] + +# HTML files that should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_post_files = [] + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + +# The depth of the table of contents in toc.ncx. +#epub_tocdepth = 3 + +# Allow duplicate toc entries. +#epub_tocdup = True + +# Choose between 'default' and 'includehidden'. +#epub_tocscope = 'default' + +# Fix unsupported image types using the Pillow. +#epub_fix_images = False + +# Scale large images. +#epub_max_image_width = 0 + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#epub_show_urls = 'inline' + +# If false, no index is generated. +#epub_use_index = True + +#======= +# rst2pdf +# +# Grouping the document tree into PDF files. List of tuples +# (source start file, target name, title, author, options). +# +# See the Sphinx chapter of http://ralsina.me/static/manual.pdf +# +# FIXME: Do not add the index file here; the result will be too big. Adding +# multiple PDF files here actually tries to get the cross-referencing right +# *between* PDF files. +pdf_documents = [ + ('uboot-documentation', u'U-Boot', u'U-Boot', u'J. Random Bozo'), +] + +# kernel-doc extension configuration for running Sphinx directly (e.g. by Read +# the Docs). In a normal build, these are supplied from the Makefile via command +# line arguments. +kerneldoc_bin = '../scripts/kernel-doc' +kerneldoc_srctree = '..' + +# ------------------------------------------------------------------------------ +# Since loadConfig overwrites settings from the global namespace, it has to be +# the last statement in the conf.py file +# ------------------------------------------------------------------------------ +loadConfig(globals())
diff --git a/Documentation/devicetree/bindings/axi/gdsys,ihs_axi.txt b/Documentation/devicetree/bindings/axi/gdsys,ihs_axi.txt new file mode 100644 index 0000000..110788f --- /dev/null +++ b/Documentation/devicetree/bindings/axi/gdsys,ihs_axi.txt
@@ -0,0 +1,22 @@ +gdsys AXI busses of IHS FPGA devices + +Certain gdsys IHS FPGAs offer a interface to their built-in AXI bus with which +the connected devices (usually IP cores) can be controlled via software. + +Required properties: +- compatible: must be "gdsys,ihs_axi" +- reg: describes the address and length of the AXI bus's register map (within + the FPGA's register space) + +Example: + +fpga0_axi_video0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "gdsys,ihs_axi"; + reg = <0x170 0x10>; + + axi_dev_1 { + ... + }; +};
diff --git a/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt b/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt new file mode 100644 index 0000000..28c1080 --- /dev/null +++ b/Documentation/devicetree/bindings/board/gdsys,board_gazerbeam.txt
@@ -0,0 +1,46 @@ +gdsys Gazerbeam board driver + +This driver provides capabilities to access the gdsys Gazerbeam board's device +information. Furthermore, phandles to some internal devices are provided for +the board files. + +Required properties: +- compatible: should be "gdsys,board_gazerbeam" +- csb: phandle to the board's coherent system bus (CSB) device node +- rxaui[0-3]: phandles to the rxaui control device nodes +- fpga[0-1]: phandles to the board's gdsys FPGA device nodes +- ioep[0-1]: phandles to the board's IO endpoint device nodes +- ver-gpios: GPIO list to read the hardware version from +- var-gpios: GPIO list to read the hardware variant information from +- reset-gpios: GPIO list for the board's reset GPIOs + +Example: + + +board { + compatible = "gdsys,board_gazerbeam"; + csb = <&board_soc>; + serdes = <&SERDES>; + rxaui0 = <&RXAUI0>; + rxaui1 = <&RXAUI1>; + rxaui2 = <&RXAUI2>; + rxaui3 = <&RXAUI3>; + fpga0 = <&FPGA0>; + fpga1 = <&FPGA1>; + ioep0 = <&IOEP0>; + ioep1 = <&IOEP1>; + + ver-gpios = <&PPCPCA 12 0 + &PPCPCA 13 0 + &PPCPCA 14 0 + &PPCPCA 15 0>; + + /* MC2/SC-Board */ + var-gpios-mc2 = <&GPIO_VB0 0 0 /* VAR-MC_SC */ + &GPIO_VB0 11 0>; /* VAR-CON */ + /* MC4-Board */ + var-gpios-mc4 = <&GPIO_VB1 0 0 /* VAR-MC_SC */ + &GPIO_VB1 11 0>; /* VAR-CON */ + + reset-gpios = <&gpio0 1 0 &gpio0 2 1>; +};
diff --git a/Documentation/devicetree/bindings/clk/fsl,mpc83xx-clk.txt b/Documentation/devicetree/bindings/clk/fsl,mpc83xx-clk.txt new file mode 100644 index 0000000..8313da8 --- /dev/null +++ b/Documentation/devicetree/bindings/clk/fsl,mpc83xx-clk.txt
@@ -0,0 +1,23 @@ +MPC83xx system clock devices + +MPC83xx SoCs supply a variety of clocks to drive various components of a +system. + +Required properties: +- compatible: must be one of "fsl,mpc8308-clk", + "fsl,mpc8309-clk", + "fsl,mpc8313-clk", + "fsl,mpc8315-clk", + "fsl,mpc832x-clk", + "fsl,mpc8349-clk", + "fsl,mpc8360-clk", + "fsl,mpc8379-clk" + depending on which SoC is employed +- #clock-cells: Must be 1 + +Example: + +socclocks: clocks { + compatible = "fsl,mpc832x-clk"; + #clock-cells = <1>; +};
diff --git a/Documentation/devicetree/bindings/cpu/fsl,mpc83xx.txt b/Documentation/devicetree/bindings/cpu/fsl,mpc83xx.txt new file mode 100644 index 0000000..ac563d9 --- /dev/null +++ b/Documentation/devicetree/bindings/cpu/fsl,mpc83xx.txt
@@ -0,0 +1,34 @@ +MPC83xx CPU devices + +MPC83xx SoCs contain a e300 core as their main processor. + +Required properties: +- compatible: must be one of "fsl,mpc83xx", + "fsl,mpc8308", + "fsl,mpc8309", + "fsl,mpc8313", + "fsl,mpc8315", + "fsl,mpc832x", + "fsl,mpc8349", + "fsl,mpc8360", + "fsl,mpc8379" +- clocks: has to have two entries, which must be the core clock at index 0 and + the CSB (Coherent System Bus) clock at index 1. Both are given by a suitable + "fsl,mpc83xx-clk" device + +Example: + +socclocks: clocks { + compatible = "fsl,mpc8315-clk"; + #clock-cells = <1>; +}; + +cpus { + compatible = "cpu_bus"; + + PowerPC,8315@0 { + compatible = "fsl,mpc8315"; + clocks = <&socclocks MPC83XX_CLK_CORE + &socclocks MPC83XX_CLK_CSB>; + }; +};
diff --git a/Documentation/devicetree/bindings/misc/fsl,mpc83xx-serdes.txt b/Documentation/devicetree/bindings/misc/fsl,mpc83xx-serdes.txt new file mode 100644 index 0000000..64a9b5b --- /dev/null +++ b/Documentation/devicetree/bindings/misc/fsl,mpc83xx-serdes.txt
@@ -0,0 +1,24 @@ +MPC83xx SerDes controller devices + +MPC83xx SoCs contain a built-in SerDes controller that determines which +protocols (SATA, PCI Express, SGMII, ...) are used on the system's serdes lines +and how the lines are configured. + +Required properties: +- compatible: must be "fsl,mpc83xx-serdes" +- reg: must point to the serdes controller's register map +- proto: selects for which protocol the serdes lines are configured. One of + "sata", "pex", "pex-x2", "sgmii" +- serdes-clk: determines the frequency the serdes lines are configured for. One + of 100, 125, 150. +- vdd: determines whether 1.0V core VDD is used or not + +Example: + +SERDES: serdes@e3000 { + reg = <0xe3000 0x200>; + compatible = "fsl,mpc83xx-serdes"; + proto = "pex"; + serdes-clk = <100>; + vdd; +};
diff --git a/Documentation/devicetree/bindings/misc/gdsys,io-endpoint.txt b/Documentation/devicetree/bindings/misc/gdsys,io-endpoint.txt new file mode 100644 index 0000000..db2ff8c --- /dev/null +++ b/Documentation/devicetree/bindings/misc/gdsys,io-endpoint.txt
@@ -0,0 +1,20 @@ +gdsys IO endpoint of IHS FPGA devices + +The IO endpoint of IHS FPGA devices is a packet-based transmission interface +that allows interconnected gdsys devices to send and receive data over the +FPGA's main ethernet connection. + +Required properties: +- compatible: must be "gdsys,io-endpoint" +- reg: describes the address and length of the endpoint's register map (within + the FPGA's register space) + +Example: + +fpga0_ep0 { + compatible = "gdsys,io-endpoint"; + reg = <0x020 0x10 + 0x320 0x10 + 0x340 0x10 + 0x360 0x10>; +};
diff --git a/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt b/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt new file mode 100644 index 0000000..acd466f --- /dev/null +++ b/Documentation/devicetree/bindings/misc/gdsys,iocon_fpga.txt
@@ -0,0 +1,19 @@ +gdsys IHS FPGA for CON devices + +The gdsys IHS FPGA is the main FPGA on gdsys CON devices. This driver provides +support for enabling and starting the FPGA, as well as verifying working bus +communication. + +Required properties: +- compatible: must be "gdsys,iocon_fpga" +- reset-gpios: List of GPIOs controlling the FPGA's reset +- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is + done + +Example: + +FPGA0 { + compatible = "gdsys,iocon_fpga"; + reset-gpios = <&PPCPCA 26 0>; + done-gpios = <&GPIO_VB0 19 0>; +};
diff --git a/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt b/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt new file mode 100644 index 0000000..819db22 --- /dev/null +++ b/Documentation/devicetree/bindings/misc/gdsys,iocpu_fpga.txt
@@ -0,0 +1,19 @@ +gdsys IHS FPGA for CPU devices + +The gdsys IHS FPGA is the main FPGA on gdsys CPU devices. This driver provides +support for enabling and starting the FPGA, as well as verifying working bus +communication. + +Required properties: +- compatible: must be "gdsys,iocpu_fpga" +- reset-gpios: List of GPIOs controlling the FPGA's reset +- done-gpios: List of GPIOs notifying whether the FPGA's reconfiguration is + done + +Example: + +FPGA0 { + compatible = "gdsys,iocpu_fpga"; + reset-gpios = <&PPCPCA 26 0>; + done-gpios = <&GPIO_VB0 19 0>; +};
diff --git a/Documentation/devicetree/bindings/misc/gdsys,soc.txt b/Documentation/devicetree/bindings/misc/gdsys,soc.txt new file mode 100644 index 0000000..278e935 --- /dev/null +++ b/Documentation/devicetree/bindings/misc/gdsys,soc.txt
@@ -0,0 +1,16 @@ +gdsys soc bus driver + +This driver provides a simple interface for the busses associated with gdsys +IHS FPGAs. The bus itself contains devices whose register maps are contained +within the FPGA's register space. + +Required properties: +- fpga: A phandle to the controlling IHS FPGA + +Example: + +FPGA0BUS: fpga0bus { + compatible = "gdsys,soc"; + ranges = <0x0 0xe0600000 0x00004000>; + fpga = <&FPGA0>; +};
diff --git a/Documentation/devicetree/bindings/ram/fsl,mpc83xx-mem-controller.txt b/Documentation/devicetree/bindings/ram/fsl,mpc83xx-mem-controller.txt new file mode 100644 index 0000000..da01fe9 --- /dev/null +++ b/Documentation/devicetree/bindings/ram/fsl,mpc83xx-mem-controller.txt
@@ -0,0 +1,314 @@ +MPC83xx RAM controller + +This driver supplies support for the embedded RAM controller on MCP83xx-series +SoCs. + +For static configuration mode, each controller node should have child nodes +describing the actual RAM modules installed. + +Controller node +=============== + +Required properties: +- compatible: Must be "fsl,mpc83xx-mem-controller" +- reg: The address of the RAM controller's register space +- #address-cells: Must be 2 +- #size-cells: Must be 1 +- driver_software_override: DDR driver software override is enabled (1) or + disabled (0) +- p_impedance_override: DDR driver software p-impedance override; possible + values: + * DSO_P_IMPEDANCE_HIGHEST_Z + * DSO_P_IMPEDANCE_MUCH_HIGHER_Z + * DSO_P_IMPEDANCE_HIGHER_Z + * DSO_P_IMPEDANCE_NOMINAL + * DSO_P_IMPEDANCE_LOWER_Z +- n_impedance_override: DDR driver software n-impedance override; possible + values: + * DSO_N_IMPEDANCE_HIGHEST_Z + * DSO_N_IMPEDANCE_MUCH_HIGHER_Z + * DSO_N_IMPEDANCE_HIGHER_Z + * DSO_N_IMPEDANCE_NOMINAL + * DSO_N_IMPEDANCE_LOWER_Z +- odt_termination_value: ODT termination value for I/Os; possible values: + * ODT_TERMINATION_75_OHM + * ODT_TERMINATION_150_OHM +- ddr_type: Selects voltage level for DDR pads; possible + values: + * DDR_TYPE_DDR2_1_8_VOLT + * DDR_TYPE_DDR1_2_5_VOLT +- mvref_sel: Determine where MVREF_SEL signal is generated; + possible values: + * MVREF_SEL_EXTERNAL + * MVREF_SEL_INTERNAL_GVDD +- m_odr: Disable memory transaction reordering; possible + values: + * M_ODR_ENABLE + * M_ODR_DISABLE +- clock_adjust: Clock adjust; possible values: + * CLOCK_ADJUST_025 + * CLOCK_ADJUST_05 + * CLOCK_ADJUST_075 + * CLOCK_ADJUST_1 +- ext_refresh_rec: Extended refresh recovery time; possible values: + 0, 16, 32, 48, 64, 80, 96, 112 +- read_to_write: Read-to-write turnaround; possible values: + 0, 1, 2, 3 +- write_to_read: Write-to-read turnaround; possible values: + 0, 1, 2, 3 +- read_to_read: Read-to-read turnaround; possible values: + 0, 1, 2, 3 +- write_to_write: Write-to-write turnaround; possible values: + 0, 1, 2, 3 +- active_powerdown_exit: Active powerdown exit timing; possible values: + 1, 2, 3, 4, 5, 6, 7 +- precharge_powerdown_exit: Precharge powerdown exit timing; possible values: + 1, 2, 3, 4, 5, 6, 7 +- odt_powerdown_exit: ODT powerdown exit timing; possible values: + 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15 +- mode_reg_set_cycle: Mode register set cycle time; possible values: + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +- precharge_to_activate: Precharge-to-acitvate interval; possible values: + 1, 2, 3, 4, 5, 6, 7 +- activate_to_precharge: Activate to precharge interval; possible values: + 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19 +- activate_to_readwrite: Activate to read/write interval for SDRAM; + possible values: + 1, 2, 3, 4, 5, 6, 7 +- mcas_latency: MCAS latency from READ command; possible values: + * CASLAT_20 + * CASLAT_25 + * CASLAT_30 + * CASLAT_35 + * CASLAT_40 + * CASLAT_45 + * CASLAT_50 + * CASLAT_55 + * CASLAT_60 + * CASLAT_65 + * CASLAT_70 + * CASLAT_75 + * CASLAT_80 +- refresh_recovery: Refresh recovery time; possible values: + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23 +- last_data_to_precharge: Last data to precharge minimum interval; possible + values: + 1, 2, 3, 4, 5, 6, 7 +- activate_to_activate: Activate-to-activate interval; possible values: + 1, 2, 3, 4, 5, 6, 7 +- last_write_data_to_read: Last write data pair to read command issue + interval; possible values: + 1, 2, 3, 4, 5, 6, 7 +- additive_latency: Additive latency; possible values: + 0, 1, 2, 3, 4, 5 +- mcas_to_preamble_override: MCAS-to-preamble-override; possible values: + * READ_LAT + * READ_LAT_PLUS_1_4 + * READ_LAT_PLUS_1_2 + * READ_LAT_PLUS_3_4 + * READ_LAT_PLUS_1 + * READ_LAT_PLUS_5_4 + * READ_LAT_PLUS_3_2 + * READ_LAT_PLUS_7_4 + * READ_LAT_PLUS_2 + * READ_LAT_PLUS_9_4 + * READ_LAT_PLUS_5_2 + * READ_LAT_PLUS_11_4 + * READ_LAT_PLUS_3 + * READ_LAT_PLUS_13_4 + * READ_LAT_PLUS_7_2 + * READ_LAT_PLUS_15_4 + * READ_LAT_PLUS_4 + * READ_LAT_PLUS_17_4 + * READ_LAT_PLUS_9_2 + * READ_LAT_PLUS_19_4 +- write_latency: Write latency; possible values: + 1, 2, 3, 4, 5, 6, 7 +- read_to_precharge: Read to precharge; possible values: + 1, 2, 3, 4 +- write_cmd_to_write_data: Write command to write data strobe timing + adjustment; possible values: + * CLOCK_DELAY_0 + * CLOCK_DELAY_1_4 + * CLOCK_DELAY_1_2 + * CLOCK_DELAY_3_4 + * CLOCK_DELAY_1 + * CLOCK_DELAY_5_4 + * CLOCK_DELAY_3_2 +- minimum_cke_pulse_width: Minimum CKE pulse width; possible values: + 1, 2, 3, 4 +- four_activates_window: Window for four activates; possible values: + 1, 2, 3, 4 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19 +- self_refresh: Self refresh (during sleep); possible values: + * SREN_DISABLE + * SREN_ENABLE +- ecc: Support for ECC; possible values: + * ECC_DISABLE + * ECC_ENABLE +- registered_dram: Support for registered DRAM; possible values: + * RD_DISABLE + * RD_ENABLE +- sdram_type: Type of SDRAM device to be used; possible values: + * TYPE_DDR1 + * TYPE_DDR2 +- dynamic_power_management: Dynamic power management mode; possible values: + * DYN_PWR_DISABLE + * DYN_PWR_ENABLE +- databus_width: DRAM data bus width; possible values + * DATA_BUS_WIDTH_16 + * DATA_BUS_WIDTH_32 +- nc_auto_precharge: Non-concurrent auto-precharge; possible values: + * NCAP_DISABLE + * NCAP_ENABLE +- timing_2t: 2T timing; possible values: + * TIMING_1T + * TIMING_2T +- bank_interleaving_ctrl: Bank (chip select) interleaving control; possible + values: + * INTERLEAVE_NONE + * INTERLEAVE_1_AND_2 +- precharge_bit_8: Precharge bin 8; possible values + * PRECHARGE_MA_10 + * PRECHARGE_MA_8 +- half_strength: Global half-strength override; possible values: + * STRENGTH_FULL + * STRENGTH_HALF +- bypass_initialization: Bypass initialization; possible values: + * INITIALIZATION_DONT_BYPASS + * INITIALIZATION_BYPASS +- force_self_refresh: Force self refresh; possible values: + * MODE_NORMAL + * MODE_REFRESH +- dll_reset: DLL reset; possible values: + * DLL_RESET_ENABLE + * DLL_RESET_DISABLE +- dqs_config: DQS configuration; possible values: + * DQS_TRUE +- odt_config: ODT configuration; possible values: + * ODT_ASSERT_NEVER + * ODT_ASSERT_WRITES + * ODT_ASSERT_READS + * ODT_ASSERT_ALWAYS +- posted_refreshes: Number of posted refreshes + 1, 2, 3, 4, 5, 6, 7, 8 +- sdmode: Initial value loaded into the DDR SDRAM mode + register +- esdmode: Initial value loaded into the DDR SDRAM extended + mode register +- esdmode2: Initial value loaded into the DDR SDRAM extended + mode 2 register +- esdmode3: Initial value loaded into the DDR SDRAM extended + mode 3 register +- refresh_interval: Refresh interval; possible values: + 0 - 65535 +- precharge_interval: Precharge interval; possible values: + 0 - 16383 + +RAM module node: +================ + +Required properties: +- reg: A triple <cs addr size>, which consists of: + * cs - the chipselect used to drive this RAM module + * addr - the address where this RAM module's memory is map + to in the global memory space + * size - the size of the RAM module's memory in bytes +- auto_precharge: Chip select auto-precharge; possible values: + * AUTO_PRECHARGE_ENABLE + * AUTO_PRECHARGE_DISABLE +- odt_rd_cfg: ODT for reads configuration; possible values: + * ODT_RD_NEVER + * ODT_RD_ONLY_CURRENT + * ODT_RD_ONLY_OTHER_CS + * ODT_RD_ONLY_OTHER_DIMM + * ODT_RD_ALL +- odt_wr_cfg: ODT for writes configuration; possible values: + * ODT_WR_NEVER + * ODT_WR_ONLY_CURRENT + * ODT_WR_ONLY_OTHER_CS + * ODT_WR_ONLY_OTHER_DIMM + * ODT_WR_ALL +- bank_bits: Number of bank bits for SDRAM on chip select; possible + values: + 2, 3 +- row_bits: Number of row bits for SDRAM on chip select; possible values: + 12, 13, 14 +- col_bits: Number of column bits for SDRAM on chip select; possible + values: + 8, 9, 10, 11 + +Example: + +memory@2000 { + #address-cells = <2>; + #size-cells = <1>; + compatible = "fsl,mpc83xx-mem-controller"; + reg = <0x2000 0x1000>; + device_type = "memory"; + u-boot,dm-pre-reloc; + + driver_software_override = <DSO_ENABLE>; + p_impedance_override = <DSO_P_IMPEDANCE_NOMINAL>; + n_impedance_override = <DSO_N_IMPEDANCE_NOMINAL>; + odt_termination_value = <ODT_TERMINATION_150_OHM>; + ddr_type = <DDR_TYPE_DDR2_1_8_VOLT>; + + clock_adjust = <CLOCK_ADJUST_05>; + + read_to_write = <0>; + write_to_read = <0>; + read_to_read = <0>; + write_to_write = <0>; + active_powerdown_exit = <2>; + precharge_powerdown_exit = <6>; + odt_powerdown_exit = <8>; + mode_reg_set_cycle = <2>; + + precharge_to_activate = <2>; + activate_to_precharge = <6>; + activate_to_readwrite = <2>; + mcas_latency = <CASLAT_40>; + refresh_recovery = <17>; + last_data_to_precharge = <2>; + activate_to_activate = <2>; + last_write_data_to_read = <2>; + + additive_latency = <0>; + mcas_to_preamble_override = <READ_LAT_PLUS_1_2>; + write_latency = <3>; + read_to_precharge = <2>; + write_cmd_to_write_data = <CLOCK_DELAY_1_2>; + minimum_cke_pulse_width = <3>; + four_activates_window = <5>; + + self_refresh = <SREN_ENABLE>; + sdram_type = <TYPE_DDR2>; + databus_width = <DATA_BUS_WIDTH_32>; + + force_self_refresh = <MODE_NORMAL>; + dll_reset = <DLL_RESET_ENABLE>; + dqs_config = <DQS_TRUE>; + odt_config = <ODT_ASSERT_READS>; + posted_refreshes = <1>; + + refresh_interval = <2084>; + precharge_interval = <256>; + + sdmode = <0x0242>; + esdmode = <0x0440>; + + ram@0 { + reg = <0x0 0x0 0x8000000>; + compatible = "nanya,nt5tu64m16hg"; + + odt_rd_cfg = <ODT_RD_NEVER>; + odt_wr_cfg = <ODT_WR_ONLY_CURRENT>; + bank_bits = <3>; + row_bits = <13>; + col_bits = <10>; + }; +};
diff --git a/Documentation/devicetree/bindings/timer/fsl,mpc83xx-timer.txt b/Documentation/devicetree/bindings/timer/fsl,mpc83xx-timer.txt new file mode 100644 index 0000000..608d241 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/fsl,mpc83xx-timer.txt
@@ -0,0 +1,21 @@ +MPC83xx timer devices + +MPC83xx SoCs offer a decrementer interrupt that can be used to implement delay +functionality, and periodically triggered actions. + +Required properties: +- compatible: must be "fsl,mpc83xx-timer" +- clocks: must be a reference to the system's CSB (coherent system bus) clock, + provided by one of the "fsl,mpc83xx-clk" devices + +Example: + +socclocks: clocks { + compatible = "fsl,mpc832x-clk"; + #clock-cells = <1>; +}; + +timer { + compatible = "fsl,mpc83xx-timer"; + clocks = <&socclocks MPC83XX_CLK_CSB>; +};
diff --git a/Documentation/efi.rst b/Documentation/efi.rst new file mode 100644 index 0000000..51c1de2 --- /dev/null +++ b/Documentation/efi.rst
@@ -0,0 +1,16 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +EFI subsystem +============= + +Boot services +------------- + +.. kernel-doc:: lib/efi_loader/efi_boottime.c + :internal: + +Runtime services +---------------- + +.. kernel-doc:: lib/efi_loader/efi_runtime.c + :internal:
diff --git a/Documentation/index.rst b/Documentation/index.rst new file mode 100644 index 0000000..0353c10 --- /dev/null +++ b/Documentation/index.rst
@@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +####################### +U-Boot Developer Manual +####################### + +.. toctree:: + + efi + linker_lists + serial
diff --git a/Documentation/linker_lists.rst b/Documentation/linker_lists.rst new file mode 100644 index 0000000..72f514e --- /dev/null +++ b/Documentation/linker_lists.rst
@@ -0,0 +1,100 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Linker-Generated Arrays +======================= + +A linker list is constructed by grouping together linker input +sections, each containing one entry of the list. Each input section +contains a constant initialized variable which holds the entry's +content. Linker list input sections are constructed from the list +and entry names, plus a prefix which allows grouping all lists +together. Assuming _list and _entry are the list and entry names, +then the corresponding input section name is + +:: + + .u_boot_list_ + 2_ + @_list + _2_ + @_entry + +and the C variable name is + +:: + + _u_boot_list + _2_ + @_list + _2_ + @_entry + +This ensures uniqueness for both input section and C variable name. + +Note that the names differ only in the first character, "." for the +section and "_" for the variable, so that the linker cannot confuse +section and symbol names. From now on, both names will be referred +to as + +:: + + %u_boot_list_ + 2_ + @_list + _2_ + @_entry + +Entry variables need never be referred to directly. + +The naming scheme for input sections allows grouping all linker lists +into a single linker output section and grouping all entries for a +single list. + +Note the two '_2_' constant components in the names: their presence +allows putting a start and end symbols around a list, by mapping +these symbols to sections names with components "1" (before) and +"3" (after) instead of "2" (within). +Start and end symbols for a list can generally be defined as + +:: + + %u_boot_list_2_ + @_list + _1_... + %u_boot_list_2_ + @_list + _3_... + +Start and end symbols for the whole of the linker lists area can be +defined as + +:: + + %u_boot_list_1_... + %u_boot_list_3_... + +Here is an example of the sorted sections which result from a list +"array" made up of three entries : "first", "second" and "third", +iterated at least once. + +:: + + .u_boot_list_2_array_1 + .u_boot_list_2_array_2_first + .u_boot_list_2_array_2_second + .u_boot_list_2_array_2_third + .u_boot_list_2_array_3 + +If lists must be divided into sublists (e.g. for iterating only on +part of a list), one can simply give the list a name of the form +'outer_2_inner', where 'outer' is the global list name and 'inner' +is the sub-list name. Iterators for the whole list should use the +global list name ("outer"); iterators for only a sub-list should use +the full sub-list name ("outer_2_inner"). + +Here is an example of the sections generated from a global list +named "drivers", two sub-lists named "i2c" and "pci", and iterators +defined for the whole list and each sub-list: + +:: + + %u_boot_list_2_drivers_1 + %u_boot_list_2_drivers_2_i2c_1 + %u_boot_list_2_drivers_2_i2c_2_first + %u_boot_list_2_drivers_2_i2c_2_first + %u_boot_list_2_drivers_2_i2c_2_second + %u_boot_list_2_drivers_2_i2c_2_third + %u_boot_list_2_drivers_2_i2c_3 + %u_boot_list_2_drivers_2_pci_1 + %u_boot_list_2_drivers_2_pci_2_first + %u_boot_list_2_drivers_2_pci_2_second + %u_boot_list_2_drivers_2_pci_2_third + %u_boot_list_2_drivers_2_pci_3 + %u_boot_list_2_drivers_3 + +.. kernel-doc:: include/linker_lists.h + :internal:
diff --git a/Documentation/media/Makefile b/Documentation/media/Makefile new file mode 100644 index 0000000..0efd18a --- /dev/null +++ b/Documentation/media/Makefile
@@ -0,0 +1,38 @@ +# Rules to convert a .h file to inline RST documentation + +SRC_DIR=$(srctree)/Documentation/media +PARSER = $(srctree)/Documentation/sphinx/parse-headers.pl +API = $(srctree)/include + +FILES = linker_lists.h.rst + +TARGETS := $(addprefix $(BUILDDIR)/, $(FILES)) + +gen_rst = \ + echo ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions; \ + ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions + +quiet_gen_rst = echo ' PARSE $(patsubst $(srctree)/%,%,$<)'; \ + ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions + +silent_gen_rst = ${gen_rst} + +$(BUILDDIR)/linker_lists.h.rst: ${API}/linker_lists.h ${PARSER} $(SRC_DIR)/linker_lists.h.rst.exceptions + @$($(quiet)gen_rst) + +# Media build rules + +.PHONY: all html epub xml latex + +all: $(IMGDOT) $(BUILDDIR) ${TARGETS} +html: all +epub: all +xml: all +latex: $(IMGPDF) all +linkcheck: + +clean: + -rm -f $(DOTTGT) $(IMGTGT) ${TARGETS} 2>/dev/null + +$(BUILDDIR): + $(Q)mkdir -p $@
diff --git a/Documentation/media/linker_lists.h.rst.exceptions b/Documentation/media/linker_lists.h.rst.exceptions new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Documentation/media/linker_lists.h.rst.exceptions
diff --git a/Documentation/serial.rst b/Documentation/serial.rst new file mode 100644 index 0000000..ed34e59 --- /dev/null +++ b/Documentation/serial.rst
@@ -0,0 +1,7 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Serial system +============= + +.. kernel-doc:: drivers/serial/serial.c + :internal:
diff --git a/Documentation/sphinx-static/theme_overrides.css b/Documentation/sphinx-static/theme_overrides.css new file mode 100644 index 0000000..522b6d4 --- /dev/null +++ b/Documentation/sphinx-static/theme_overrides.css
@@ -0,0 +1,89 @@ +/* -*- coding: utf-8; mode: css -*- + * + * Sphinx HTML theme customization: read the doc + * + */ + +/* Interim: Code-blocks with line nos - lines and line numbers don't line up. + * see: https://github.com/rtfd/sphinx_rtd_theme/issues/419 + */ + +div[class^="highlight"] pre { + line-height: normal; +} +.rst-content .highlight > pre { + line-height: normal; +} + +@media screen { + + /* content column + * + * RTD theme's default is 800px as max width for the content, but we have + * tables with tons of columns, which need the full width of the view-port. + */ + + .wy-nav-content{max-width: none; } + + /* table: + * + * - Sequences of whitespace should collapse into a single whitespace. + * - make the overflow auto (scrollbar if needed) + * - align caption "left" ("center" is unsuitable on vast tables) + */ + + .wy-table-responsive table td { white-space: normal; } + .wy-table-responsive { overflow: auto; } + .rst-content table.docutils caption { text-align: left; font-size: 100%; } + + /* captions: + * + * - captions should have 100% (not 85%) font size + * - hide the permalink symbol as long as link is not hovered + */ + + .toc-title { + font-size: 150%; + font-weight: bold; + } + + caption, .wy-table caption, .rst-content table.field-list caption { + font-size: 100%; + } + caption a.headerlink { opacity: 0; } + caption a.headerlink:hover { opacity: 1; } + + /* Menu selection and keystrokes */ + + span.menuselection { + color: blue; + font-family: "Courier New", Courier, monospace + } + + code.kbd, code.kbd span { + color: white; + background-color: darkblue; + font-weight: bold; + font-family: "Courier New", Courier, monospace + } + + /* fix bottom margin of lists items */ + + .rst-content .section ul li:last-child, .rst-content .section ul li p:last-child { + margin-bottom: 12px; + } + + /* inline literal: drop the borderbox, padding and red color */ + + code, .rst-content tt, .rst-content code { + color: inherit; + border: none; + padding: unset; + background: inherit; + font-size: 85%; + } + + .rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal { + color: inherit; + } +}
diff --git a/Documentation/sphinx/cdomain.py b/Documentation/sphinx/cdomain.py new file mode 100644 index 0000000..cf13ff3 --- /dev/null +++ b/Documentation/sphinx/cdomain.py
@@ -0,0 +1,165 @@ +# -*- coding: utf-8; mode: python -*- +# pylint: disable=W0141,C0113,C0103,C0325 +u""" + cdomain + ~~~~~~~ + + Replacement for the sphinx c-domain. + + :copyright: Copyright (C) 2016 Markus Heiser + :license: GPL Version 2, June 1991 see Linux/COPYING for details. + + List of customizations: + + * Moved the *duplicate C object description* warnings for function + declarations in the nitpicky mode. See Sphinx documentation for + the config values for ``nitpick`` and ``nitpick_ignore``. + + * Add option 'name' to the "c:function:" directive. With option 'name' the + ref-name of a function can be modified. E.g.:: + + .. c:function:: int ioctl( int fd, int request ) + :name: VIDIOC_LOG_STATUS + + The func-name (e.g. ioctl) remains in the output but the ref-name changed + from 'ioctl' to 'VIDIOC_LOG_STATUS'. The function is referenced by:: + + * :c:func:`VIDIOC_LOG_STATUS` or + * :any:`VIDIOC_LOG_STATUS` (``:any:`` needs sphinx 1.3) + + * Handle signatures of function-like macros well. Don't try to deduce + arguments types of function-like macros. + +""" + +from docutils import nodes +from docutils.parsers.rst import directives + +import sphinx +from sphinx import addnodes +from sphinx.domains.c import c_funcptr_sig_re, c_sig_re +from sphinx.domains.c import CObject as Base_CObject +from sphinx.domains.c import CDomain as Base_CDomain + +__version__ = '1.0' + +# Get Sphinx version +major, minor, patch = sphinx.version_info[:3] + +def setup(app): + + app.override_domain(CDomain) + + return dict( + version = __version__, + parallel_read_safe = True, + parallel_write_safe = True + ) + +class CObject(Base_CObject): + + """ + Description of a C language object. + """ + option_spec = { + "name" : directives.unchanged + } + + def handle_func_like_macro(self, sig, signode): + u"""Handles signatures of function-like macros. + + If the objtype is 'function' and the the signature ``sig`` is a + function-like macro, the name of the macro is returned. Otherwise + ``False`` is returned. """ + + if not self.objtype == 'function': + return False + + m = c_funcptr_sig_re.match(sig) + if m is None: + m = c_sig_re.match(sig) + if m is None: + raise ValueError('no match') + + rettype, fullname, arglist, _const = m.groups() + arglist = arglist.strip() + if rettype or not arglist: + return False + + arglist = arglist.replace('`', '').replace('\\ ', '') # remove markup + arglist = [a.strip() for a in arglist.split(",")] + + # has the first argument a type? + if len(arglist[0].split(" ")) > 1: + return False + + # This is a function-like macro, it's arguments are typeless! + signode += addnodes.desc_name(fullname, fullname) + paramlist = addnodes.desc_parameterlist() + signode += paramlist + + for argname in arglist: + param = addnodes.desc_parameter('', '', noemph=True) + # separate by non-breaking space in the output + param += nodes.emphasis(argname, argname) + paramlist += param + + return fullname + + def handle_signature(self, sig, signode): + """Transform a C signature into RST nodes.""" + + fullname = self.handle_func_like_macro(sig, signode) + if not fullname: + fullname = super(CObject, self).handle_signature(sig, signode) + + if "name" in self.options: + if self.objtype == 'function': + fullname = self.options["name"] + else: + # FIXME: handle :name: value of other declaration types? + pass + return fullname + + def add_target_and_index(self, name, sig, signode): + # for C API items we add a prefix since names are usually not qualified + # by a module name and so easily clash with e.g. section titles + targetname = 'c.' + name + if targetname not in self.state.document.ids: + signode['names'].append(targetname) + signode['ids'].append(targetname) + signode['first'] = (not self.names) + self.state.document.note_explicit_target(signode) + inv = self.env.domaindata['c']['objects'] + if (name in inv and self.env.config.nitpicky): + if self.objtype == 'function': + if ('c:func', name) not in self.env.config.nitpick_ignore: + self.state_machine.reporter.warning( + 'duplicate C object description of %s, ' % name + + 'other instance in ' + self.env.doc2path(inv[name][0]), + line=self.lineno) + inv[name] = (self.env.docname, self.objtype) + + indextext = self.get_index_text(name) + if indextext: + if major == 1 and minor < 4: + # indexnode's tuple changed in 1.4 + # https://github.com/sphinx-doc/sphinx/commit/e6a5a3a92e938fcd75866b4227db9e0524d58f7c + self.indexnode['entries'].append( + ('single', indextext, targetname, '')) + else: + self.indexnode['entries'].append( + ('single', indextext, targetname, '', None)) + +class CDomain(Base_CDomain): + + """C language domain.""" + name = 'c' + label = 'C' + directives = { + 'function': CObject, + 'member': CObject, + 'macro': CObject, + 'type': CObject, + 'var': CObject, + }
diff --git a/Documentation/sphinx/kernel_include.py b/Documentation/sphinx/kernel_include.py new file mode 100755 index 0000000..f523aa6 --- /dev/null +++ b/Documentation/sphinx/kernel_include.py
@@ -0,0 +1,190 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8; mode: python -*- +# pylint: disable=R0903, C0330, R0914, R0912, E0401 + +u""" + kernel-include + ~~~~~~~~~~~~~~ + + Implementation of the ``kernel-include`` reST-directive. + + :copyright: Copyright (C) 2016 Markus Heiser + :license: GPL Version 2, June 1991 see linux/COPYING for details. + + The ``kernel-include`` reST-directive is a replacement for the ``include`` + directive. The ``kernel-include`` directive expand environment variables in + the path name and allows to include files from arbitrary locations. + + .. hint:: + + Including files from arbitrary locations (e.g. from ``/etc``) is a + security risk for builders. This is why the ``include`` directive from + docutils *prohibit* pathnames pointing to locations *above* the filesystem + tree where the reST document with the include directive is placed. + + Substrings of the form $name or ${name} are replaced by the value of + environment variable name. Malformed variable names and references to + non-existing variables are left unchanged. +""" + +# ============================================================================== +# imports +# ============================================================================== + +import os.path + +from docutils import io, nodes, statemachine +from docutils.utils.error_reporting import SafeString, ErrorString +from docutils.parsers.rst import directives +from docutils.parsers.rst.directives.body import CodeBlock, NumberLines +from docutils.parsers.rst.directives.misc import Include + +__version__ = '1.0' + +# ============================================================================== +def setup(app): +# ============================================================================== + + app.add_directive("kernel-include", KernelInclude) + return dict( + version = __version__, + parallel_read_safe = True, + parallel_write_safe = True + ) + +# ============================================================================== +class KernelInclude(Include): +# ============================================================================== + + u"""KernelInclude (``kernel-include``) directive""" + + def run(self): + path = os.path.realpath( + os.path.expandvars(self.arguments[0])) + + # to get a bit security back, prohibit /etc: + if path.startswith(os.sep + "etc"): + raise self.severe( + 'Problems with "%s" directive, prohibited path: %s' + % (self.name, path)) + + self.arguments[0] = path + + #return super(KernelInclude, self).run() # won't work, see HINTs in _run() + return self._run() + + def _run(self): + """Include a file as part of the content of this reST file.""" + + # HINT: I had to copy&paste the whole Include.run method. I'am not happy + # with this, but due to security reasons, the Include.run method does + # not allow absolute or relative pathnames pointing to locations *above* + # the filesystem tree where the reST document is placed. + + if not self.state.document.settings.file_insertion_enabled: + raise self.warning('"%s" directive disabled.' % self.name) + source = self.state_machine.input_lines.source( + self.lineno - self.state_machine.input_offset - 1) + source_dir = os.path.dirname(os.path.abspath(source)) + path = directives.path(self.arguments[0]) + if path.startswith('<') and path.endswith('>'): + path = os.path.join(self.standard_include_path, path[1:-1]) + path = os.path.normpath(os.path.join(source_dir, path)) + + # HINT: this is the only line I had to change / commented out: + #path = utils.relative_path(None, path) + + path = nodes.reprunicode(path) + encoding = self.options.get( + 'encoding', self.state.document.settings.input_encoding) + e_handler=self.state.document.settings.input_encoding_error_handler + tab_width = self.options.get( + 'tab-width', self.state.document.settings.tab_width) + try: + self.state.document.settings.record_dependencies.add(path) + include_file = io.FileInput(source_path=path, + encoding=encoding, + error_handler=e_handler) + except UnicodeEncodeError as error: + raise self.severe('Problems with "%s" directive path:\n' + 'Cannot encode input file path "%s" ' + '(wrong locale?).' % + (self.name, SafeString(path))) + except IOError as error: + raise self.severe('Problems with "%s" directive path:\n%s.' % + (self.name, ErrorString(error))) + startline = self.options.get('start-line', None) + endline = self.options.get('end-line', None) + try: + if startline or (endline is not None): + lines = include_file.readlines() + rawtext = ''.join(lines[startline:endline]) + else: + rawtext = include_file.read() + except UnicodeError as error: + raise self.severe('Problem with "%s" directive:\n%s' % + (self.name, ErrorString(error))) + # start-after/end-before: no restrictions on newlines in match-text, + # and no restrictions on matching inside lines vs. line boundaries + after_text = self.options.get('start-after', None) + if after_text: + # skip content in rawtext before *and incl.* a matching text + after_index = rawtext.find(after_text) + if after_index < 0: + raise self.severe('Problem with "start-after" option of "%s" ' + 'directive:\nText not found.' % self.name) + rawtext = rawtext[after_index + len(after_text):] + before_text = self.options.get('end-before', None) + if before_text: + # skip content in rawtext after *and incl.* a matching text + before_index = rawtext.find(before_text) + if before_index < 0: + raise self.severe('Problem with "end-before" option of "%s" ' + 'directive:\nText not found.' % self.name) + rawtext = rawtext[:before_index] + + include_lines = statemachine.string2lines(rawtext, tab_width, + convert_whitespace=True) + if 'literal' in self.options: + # Convert tabs to spaces, if `tab_width` is positive. + if tab_width >= 0: + text = rawtext.expandtabs(tab_width) + else: + text = rawtext + literal_block = nodes.literal_block(rawtext, source=path, + classes=self.options.get('class', [])) + literal_block.line = 1 + self.add_name(literal_block) + if 'number-lines' in self.options: + try: + startline = int(self.options['number-lines'] or 1) + except ValueError: + raise self.error(':number-lines: with non-integer ' + 'start value') + endline = startline + len(include_lines) + if text.endswith('\n'): + text = text[:-1] + tokens = NumberLines([([], text)], startline, endline) + for classes, value in tokens: + if classes: + literal_block += nodes.inline(value, value, + classes=classes) + else: + literal_block += nodes.Text(value, value) + else: + literal_block += nodes.Text(text, text) + return [literal_block] + if 'code' in self.options: + self.options['source'] = path + codeblock = CodeBlock(self.name, + [self.options.pop('code')], # arguments + self.options, + include_lines, # content + self.lineno, + self.content_offset, + self.block_text, + self.state, + self.state_machine) + return codeblock.run() + self.state_machine.insert_input(include_lines, path) + return []
diff --git a/Documentation/sphinx/kerneldoc.py b/Documentation/sphinx/kerneldoc.py new file mode 100644 index 0000000..fbedcc3 --- /dev/null +++ b/Documentation/sphinx/kerneldoc.py
@@ -0,0 +1,146 @@ +# coding=utf-8 +# +# Copyright © 2016 Intel Corporation +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# Authors: +# Jani Nikula <jani.nikula@intel.com> +# +# Please make sure this works on both python2 and python3. +# + +import codecs +import os +import subprocess +import sys +import re +import glob + +from docutils import nodes, statemachine +from docutils.statemachine import ViewList +from docutils.parsers.rst import directives, Directive +from sphinx.ext.autodoc import AutodocReporter + +__version__ = '1.0' + +class KernelDocDirective(Directive): + """Extract kernel-doc comments from the specified file""" + required_argument = 1 + optional_arguments = 4 + option_spec = { + 'doc': directives.unchanged_required, + 'functions': directives.unchanged_required, + 'export': directives.unchanged, + 'internal': directives.unchanged, + } + has_content = False + + def run(self): + env = self.state.document.settings.env + cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno'] + + filename = env.config.kerneldoc_srctree + '/' + self.arguments[0] + export_file_patterns = [] + + # Tell sphinx of the dependency + env.note_dependency(os.path.abspath(filename)) + + tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) + + # FIXME: make this nicer and more robust against errors + if 'export' in self.options: + cmd += ['-export'] + export_file_patterns = str(self.options.get('export')).split() + elif 'internal' in self.options: + cmd += ['-internal'] + export_file_patterns = str(self.options.get('internal')).split() + elif 'doc' in self.options: + cmd += ['-function', str(self.options.get('doc'))] + elif 'functions' in self.options: + for f in str(self.options.get('functions')).split(): + cmd += ['-function', f] + + for pattern in export_file_patterns: + for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern): + env.note_dependency(os.path.abspath(f)) + cmd += ['-export-file', f] + + cmd += [filename] + + try: + env.app.verbose('calling kernel-doc \'%s\'' % (" ".join(cmd))) + + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + + out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8') + + if p.returncode != 0: + sys.stderr.write(err) + + env.app.warn('kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode)) + return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] + elif env.config.kerneldoc_verbosity > 0: + sys.stderr.write(err) + + lines = statemachine.string2lines(out, tab_width, convert_whitespace=True) + result = ViewList() + + lineoffset = 0; + line_regex = re.compile("^#define LINENO ([0-9]+)$") + for line in lines: + match = line_regex.search(line) + if match: + # sphinx counts lines from 0 + lineoffset = int(match.group(1)) - 1 + # we must eat our comments since the upset the markup + else: + result.append(line, filename, lineoffset) + lineoffset += 1 + + node = nodes.section() + buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter + self.state.memo.reporter = AutodocReporter(result, self.state.memo.reporter) + self.state.memo.title_styles, self.state.memo.section_level = [], 0 + try: + self.state.nested_parse(result, 0, node, match_titles=1) + finally: + self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf + + return node.children + + except Exception as e: # pylint: disable=W0703 + env.app.warn('kernel-doc \'%s\' processing failed with: %s' % + (" ".join(cmd), str(e))) + return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] + +def setup(app): + app.add_config_value('kerneldoc_bin', None, 'env') + app.add_config_value('kerneldoc_srctree', None, 'env') + app.add_config_value('kerneldoc_verbosity', 1, 'env') + + app.add_directive('kernel-doc', KernelDocDirective) + + return dict( + version = __version__, + parallel_read_safe = True, + parallel_write_safe = True + )
diff --git a/Documentation/sphinx/kfigure.py b/Documentation/sphinx/kfigure.py new file mode 100644 index 0000000..b97228d --- /dev/null +++ b/Documentation/sphinx/kfigure.py
@@ -0,0 +1,551 @@ +# -*- coding: utf-8; mode: python -*- +# pylint: disable=C0103, R0903, R0912, R0915 +u""" + scalable figure and image handling + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Sphinx extension which implements scalable image handling. + + :copyright: Copyright (C) 2016 Markus Heiser + :license: GPL Version 2, June 1991 see Linux/COPYING for details. + + The build for image formats depend on image's source format and output's + destination format. This extension implement methods to simplify image + handling from the author's POV. Directives like ``kernel-figure`` implement + methods *to* always get the best output-format even if some tools are not + installed. For more details take a look at ``convert_image(...)`` which is + the core of all conversions. + + * ``.. kernel-image``: for image handling / a ``.. image::`` replacement + + * ``.. kernel-figure``: for figure handling / a ``.. figure::`` replacement + + * ``.. kernel-render``: for render markup / a concept to embed *render* + markups (or languages). Supported markups (see ``RENDER_MARKUP_EXT``) + + - ``DOT``: render embedded Graphviz's **DOC** + - ``SVG``: render embedded Scalable Vector Graphics (**SVG**) + - ... *developable* + + Used tools: + + * ``dot(1)``: Graphviz (http://www.graphviz.org). If Graphviz is not + available, the DOT language is inserted as literal-block. + + * SVG to PDF: To generate PDF, you need at least one of this tools: + + - ``convert(1)``: ImageMagick (https://www.imagemagick.org) + + List of customizations: + + * generate PDF from SVG / used by PDF (LaTeX) builder + + * generate SVG (html-builder) and PDF (latex-builder) from DOT files. + DOT: see http://www.graphviz.org/content/dot-language + + """ + +import os +from os import path +import subprocess +from hashlib import sha1 +import sys + +from docutils import nodes +from docutils.statemachine import ViewList +from docutils.parsers.rst import directives +from docutils.parsers.rst.directives import images +import sphinx + +from sphinx.util.nodes import clean_astext +from six import iteritems + +PY3 = sys.version_info[0] == 3 + +if PY3: + _unicode = str +else: + _unicode = unicode + +# Get Sphinx version +major, minor, patch = sphinx.version_info[:3] +if major == 1 and minor > 3: + # patches.Figure only landed in Sphinx 1.4 + from sphinx.directives.patches import Figure # pylint: disable=C0413 +else: + Figure = images.Figure + +__version__ = '1.0.0' + +# simple helper +# ------------- + +def which(cmd): + """Searches the ``cmd`` in the ``PATH`` environment. + + This *which* searches the PATH for executable ``cmd`` . First match is + returned, if nothing is found, ``None` is returned. + """ + envpath = os.environ.get('PATH', None) or os.defpath + for folder in envpath.split(os.pathsep): + fname = folder + os.sep + cmd + if path.isfile(fname): + return fname + +def mkdir(folder, mode=0o775): + if not path.isdir(folder): + os.makedirs(folder, mode) + +def file2literal(fname): + with open(fname, "r") as src: + data = src.read() + node = nodes.literal_block(data, data) + return node + +def isNewer(path1, path2): + """Returns True if ``path1`` is newer than ``path2`` + + If ``path1`` exists and is newer than ``path2`` the function returns + ``True`` is returned otherwise ``False`` + """ + return (path.exists(path1) + and os.stat(path1).st_ctime > os.stat(path2).st_ctime) + +def pass_handle(self, node): # pylint: disable=W0613 + pass + +# setup conversion tools and sphinx extension +# ------------------------------------------- + +# Graphviz's dot(1) support +dot_cmd = None + +# ImageMagick' convert(1) support +convert_cmd = None + + +def setup(app): + # check toolchain first + app.connect('builder-inited', setupTools) + + # image handling + app.add_directive("kernel-image", KernelImage) + app.add_node(kernel_image, + html = (visit_kernel_image, pass_handle), + latex = (visit_kernel_image, pass_handle), + texinfo = (visit_kernel_image, pass_handle), + text = (visit_kernel_image, pass_handle), + man = (visit_kernel_image, pass_handle), ) + + # figure handling + app.add_directive("kernel-figure", KernelFigure) + app.add_node(kernel_figure, + html = (visit_kernel_figure, pass_handle), + latex = (visit_kernel_figure, pass_handle), + texinfo = (visit_kernel_figure, pass_handle), + text = (visit_kernel_figure, pass_handle), + man = (visit_kernel_figure, pass_handle), ) + + # render handling + app.add_directive('kernel-render', KernelRender) + app.add_node(kernel_render, + html = (visit_kernel_render, pass_handle), + latex = (visit_kernel_render, pass_handle), + texinfo = (visit_kernel_render, pass_handle), + text = (visit_kernel_render, pass_handle), + man = (visit_kernel_render, pass_handle), ) + + app.connect('doctree-read', add_kernel_figure_to_std_domain) + + return dict( + version = __version__, + parallel_read_safe = True, + parallel_write_safe = True + ) + + +def setupTools(app): + u""" + Check available build tools and log some *verbose* messages. + + This function is called once, when the builder is initiated. + """ + global dot_cmd, convert_cmd # pylint: disable=W0603 + app.verbose("kfigure: check installed tools ...") + + dot_cmd = which('dot') + convert_cmd = which('convert') + + if dot_cmd: + app.verbose("use dot(1) from: " + dot_cmd) + else: + app.warn("dot(1) not found, for better output quality install " + "graphviz from http://www.graphviz.org") + if convert_cmd: + app.verbose("use convert(1) from: " + convert_cmd) + else: + app.warn( + "convert(1) not found, for SVG to PDF conversion install " + "ImageMagick (https://www.imagemagick.org)") + + +# integrate conversion tools +# -------------------------- + +RENDER_MARKUP_EXT = { + # The '.ext' must be handled by convert_image(..) function's *in_ext* input. + # <name> : <.ext> + 'DOT' : '.dot', + 'SVG' : '.svg' +} + +def convert_image(img_node, translator, src_fname=None): + """Convert a image node for the builder. + + Different builder prefer different image formats, e.g. *latex* builder + prefer PDF while *html* builder prefer SVG format for images. + + This function handles output image formats in dependence of source the + format (of the image) and the translator's output format. + """ + app = translator.builder.app + + fname, in_ext = path.splitext(path.basename(img_node['uri'])) + if src_fname is None: + src_fname = path.join(translator.builder.srcdir, img_node['uri']) + if not path.exists(src_fname): + src_fname = path.join(translator.builder.outdir, img_node['uri']) + + dst_fname = None + + # in kernel builds, use 'make SPHINXOPTS=-v' to see verbose messages + + app.verbose('assert best format for: ' + img_node['uri']) + + if in_ext == '.dot': + + if not dot_cmd: + app.verbose("dot from graphviz not available / include DOT raw.") + img_node.replace_self(file2literal(src_fname)) + + elif translator.builder.format == 'latex': + dst_fname = path.join(translator.builder.outdir, fname + '.pdf') + img_node['uri'] = fname + '.pdf' + img_node['candidates'] = {'*': fname + '.pdf'} + + + elif translator.builder.format == 'html': + dst_fname = path.join( + translator.builder.outdir, + translator.builder.imagedir, + fname + '.svg') + img_node['uri'] = path.join( + translator.builder.imgpath, fname + '.svg') + img_node['candidates'] = { + '*': path.join(translator.builder.imgpath, fname + '.svg')} + + else: + # all other builder formats will include DOT as raw + img_node.replace_self(file2literal(src_fname)) + + elif in_ext == '.svg': + + if translator.builder.format == 'latex': + if convert_cmd is None: + app.verbose("no SVG to PDF conversion available / include SVG raw.") + img_node.replace_self(file2literal(src_fname)) + else: + dst_fname = path.join(translator.builder.outdir, fname + '.pdf') + img_node['uri'] = fname + '.pdf' + img_node['candidates'] = {'*': fname + '.pdf'} + + if dst_fname: + # the builder needs not to copy one more time, so pop it if exists. + translator.builder.images.pop(img_node['uri'], None) + _name = dst_fname[len(translator.builder.outdir) + 1:] + + if isNewer(dst_fname, src_fname): + app.verbose("convert: {out}/%s already exists and is newer" % _name) + + else: + ok = False + mkdir(path.dirname(dst_fname)) + + if in_ext == '.dot': + app.verbose('convert DOT to: {out}/' + _name) + ok = dot2format(app, src_fname, dst_fname) + + elif in_ext == '.svg': + app.verbose('convert SVG to: {out}/' + _name) + ok = svg2pdf(app, src_fname, dst_fname) + + if not ok: + img_node.replace_self(file2literal(src_fname)) + + +def dot2format(app, dot_fname, out_fname): + """Converts DOT file to ``out_fname`` using ``dot(1)``. + + * ``dot_fname`` pathname of the input DOT file, including extension ``.dot`` + * ``out_fname`` pathname of the output file, including format extension + + The *format extension* depends on the ``dot`` command (see ``man dot`` + option ``-Txxx``). Normally you will use one of the following extensions: + + - ``.ps`` for PostScript, + - ``.svg`` or ``svgz`` for Structured Vector Graphics, + - ``.fig`` for XFIG graphics and + - ``.png`` or ``gif`` for common bitmap graphics. + + """ + out_format = path.splitext(out_fname)[1][1:] + cmd = [dot_cmd, '-T%s' % out_format, dot_fname] + exit_code = 42 + + with open(out_fname, "w") as out: + exit_code = subprocess.call(cmd, stdout = out) + if exit_code != 0: + app.warn("Error #%d when calling: %s" % (exit_code, " ".join(cmd))) + return bool(exit_code == 0) + +def svg2pdf(app, svg_fname, pdf_fname): + """Converts SVG to PDF with ``convert(1)`` command. + + Uses ``convert(1)`` from ImageMagick (https://www.imagemagick.org) for + conversion. Returns ``True`` on success and ``False`` if an error occurred. + + * ``svg_fname`` pathname of the input SVG file with extension (``.svg``) + * ``pdf_name`` pathname of the output PDF file with extension (``.pdf``) + + """ + cmd = [convert_cmd, svg_fname, pdf_fname] + # use stdout and stderr from parent + exit_code = subprocess.call(cmd) + if exit_code != 0: + app.warn("Error #%d when calling: %s" % (exit_code, " ".join(cmd))) + return bool(exit_code == 0) + + +# image handling +# --------------------- + +def visit_kernel_image(self, node): # pylint: disable=W0613 + """Visitor of the ``kernel_image`` Node. + + Handles the ``image`` child-node with the ``convert_image(...)``. + """ + img_node = node[0] + convert_image(img_node, self) + +class kernel_image(nodes.image): + """Node for ``kernel-image`` directive.""" + pass + +class KernelImage(images.Image): + u"""KernelImage directive + + Earns everything from ``.. image::`` directive, except *remote URI* and + *glob* pattern. The KernelImage wraps a image node into a + kernel_image node. See ``visit_kernel_image``. + """ + + def run(self): + uri = self.arguments[0] + if uri.endswith('.*') or uri.find('://') != -1: + raise self.severe( + 'Error in "%s: %s": glob pattern and remote images are not allowed' + % (self.name, uri)) + result = images.Image.run(self) + if len(result) == 2 or isinstance(result[0], nodes.system_message): + return result + (image_node,) = result + # wrap image node into a kernel_image node / see visitors + node = kernel_image('', image_node) + return [node] + +# figure handling +# --------------------- + +def visit_kernel_figure(self, node): # pylint: disable=W0613 + """Visitor of the ``kernel_figure`` Node. + + Handles the ``image`` child-node with the ``convert_image(...)``. + """ + img_node = node[0][0] + convert_image(img_node, self) + +class kernel_figure(nodes.figure): + """Node for ``kernel-figure`` directive.""" + +class KernelFigure(Figure): + u"""KernelImage directive + + Earns everything from ``.. figure::`` directive, except *remote URI* and + *glob* pattern. The KernelFigure wraps a figure node into a kernel_figure + node. See ``visit_kernel_figure``. + """ + + def run(self): + uri = self.arguments[0] + if uri.endswith('.*') or uri.find('://') != -1: + raise self.severe( + 'Error in "%s: %s":' + ' glob pattern and remote images are not allowed' + % (self.name, uri)) + result = Figure.run(self) + if len(result) == 2 or isinstance(result[0], nodes.system_message): + return result + (figure_node,) = result + # wrap figure node into a kernel_figure node / see visitors + node = kernel_figure('', figure_node) + return [node] + + +# render handling +# --------------------- + +def visit_kernel_render(self, node): + """Visitor of the ``kernel_render`` Node. + + If rendering tools available, save the markup of the ``literal_block`` child + node into a file and replace the ``literal_block`` node with a new created + ``image`` node, pointing to the saved markup file. Afterwards, handle the + image child-node with the ``convert_image(...)``. + """ + app = self.builder.app + srclang = node.get('srclang') + + app.verbose('visit kernel-render node lang: "%s"' % (srclang)) + + tmp_ext = RENDER_MARKUP_EXT.get(srclang, None) + if tmp_ext is None: + app.warn('kernel-render: "%s" unknown / include raw.' % (srclang)) + return + + if not dot_cmd and tmp_ext == '.dot': + app.verbose("dot from graphviz not available / include raw.") + return + + literal_block = node[0] + + code = literal_block.astext() + hashobj = code.encode('utf-8') # str(node.attributes) + fname = path.join('%s-%s' % (srclang, sha1(hashobj).hexdigest())) + + tmp_fname = path.join( + self.builder.outdir, self.builder.imagedir, fname + tmp_ext) + + if not path.isfile(tmp_fname): + mkdir(path.dirname(tmp_fname)) + with open(tmp_fname, "w") as out: + out.write(code) + + img_node = nodes.image(node.rawsource, **node.attributes) + img_node['uri'] = path.join(self.builder.imgpath, fname + tmp_ext) + img_node['candidates'] = { + '*': path.join(self.builder.imgpath, fname + tmp_ext)} + + literal_block.replace_self(img_node) + convert_image(img_node, self, tmp_fname) + + +class kernel_render(nodes.General, nodes.Inline, nodes.Element): + """Node for ``kernel-render`` directive.""" + pass + +class KernelRender(Figure): + u"""KernelRender directive + + Render content by external tool. Has all the options known from the + *figure* directive, plus option ``caption``. If ``caption`` has a + value, a figure node with the *caption* is inserted. If not, a image node is + inserted. + + The KernelRender directive wraps the text of the directive into a + literal_block node and wraps it into a kernel_render node. See + ``visit_kernel_render``. + """ + has_content = True + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = False + + # earn options from 'figure' + option_spec = Figure.option_spec.copy() + option_spec['caption'] = directives.unchanged + + def run(self): + return [self.build_node()] + + def build_node(self): + + srclang = self.arguments[0].strip() + if srclang not in RENDER_MARKUP_EXT.keys(): + return [self.state_machine.reporter.warning( + 'Unknown source language "%s", use one of: %s.' % ( + srclang, ",".join(RENDER_MARKUP_EXT.keys())), + line=self.lineno)] + + code = '\n'.join(self.content) + if not code.strip(): + return [self.state_machine.reporter.warning( + 'Ignoring "%s" directive without content.' % ( + self.name), + line=self.lineno)] + + node = kernel_render() + node['alt'] = self.options.get('alt','') + node['srclang'] = srclang + literal_node = nodes.literal_block(code, code) + node += literal_node + + caption = self.options.get('caption') + if caption: + # parse caption's content + parsed = nodes.Element() + self.state.nested_parse( + ViewList([caption], source=''), self.content_offset, parsed) + caption_node = nodes.caption( + parsed[0].rawsource, '', *parsed[0].children) + caption_node.source = parsed[0].source + caption_node.line = parsed[0].line + + figure_node = nodes.figure('', node) + for k,v in self.options.items(): + figure_node[k] = v + figure_node += caption_node + + node = figure_node + + return node + +def add_kernel_figure_to_std_domain(app, doctree): + """Add kernel-figure anchors to 'std' domain. + + The ``StandardDomain.process_doc(..)`` method does not know how to resolve + the caption (label) of ``kernel-figure`` directive (it only knows about + standard nodes, e.g. table, figure etc.). Without any additional handling + this will result in a 'undefined label' for kernel-figures. + + This handle adds labels of kernel-figure to the 'std' domain labels. + """ + + std = app.env.domains["std"] + docname = app.env.docname + labels = std.data["labels"] + + for name, explicit in iteritems(doctree.nametypes): + if not explicit: + continue + labelid = doctree.nameids[name] + if labelid is None: + continue + node = doctree.ids[labelid] + + if node.tagname == 'kernel_figure': + for n in node.next_node(): + if n.tagname == 'caption': + sectname = clean_astext(n) + # add label to std domain + labels[name] = docname, labelid, sectname + break
diff --git a/Documentation/sphinx/load_config.py b/Documentation/sphinx/load_config.py new file mode 100644 index 0000000..301a21a --- /dev/null +++ b/Documentation/sphinx/load_config.py
@@ -0,0 +1,32 @@ +# -*- coding: utf-8; mode: python -*- +# pylint: disable=R0903, C0330, R0914, R0912, E0401 + +import os +import sys +from sphinx.util.pycompat import execfile_ + +# ------------------------------------------------------------------------------ +def loadConfig(namespace): +# ------------------------------------------------------------------------------ + + u"""Load an additional configuration file into *namespace*. + + The name of the configuration file is taken from the environment + ``SPHINX_CONF``. The external configuration file extends (or overwrites) the + configuration values from the origin ``conf.py``. With this you are able to + maintain *build themes*. """ + + config_file = os.environ.get("SPHINX_CONF", None) + if (config_file is not None + and os.path.normpath(namespace["__file__"]) != os.path.normpath(config_file) ): + config_file = os.path.abspath(config_file) + + if os.path.isfile(config_file): + sys.stdout.write("load additional sphinx-config: %s\n" % config_file) + config = namespace.copy() + config['__file__'] = config_file + execfile_(config_file, config) + del config['__file__'] + namespace.update(config) + else: + sys.stderr.write("WARNING: additional sphinx-config not found: %s\n" % config_file)
diff --git a/Documentation/sphinx/parse-headers.pl b/Documentation/sphinx/parse-headers.pl new file mode 100755 index 0000000..d410f47 --- /dev/null +++ b/Documentation/sphinx/parse-headers.pl
@@ -0,0 +1,401 @@ +#!/usr/bin/perl +use strict; +use Text::Tabs; +use Getopt::Long; +use Pod::Usage; + +my $debug; +my $help; +my $man; + +GetOptions( + "debug" => \$debug, + 'usage|?' => \$help, + 'help' => \$man +) or pod2usage(2); + +pod2usage(1) if $help; +pod2usage(-exitstatus => 0, -verbose => 2) if $man; +pod2usage(2) if (scalar @ARGV < 2 || scalar @ARGV > 3); + +my ($file_in, $file_out, $file_exceptions) = @ARGV; + +my $data; +my %ioctls; +my %defines; +my %typedefs; +my %enums; +my %enum_symbols; +my %structs; + +require Data::Dumper if ($debug); + +# +# read the file and get identifiers +# + +my $is_enum = 0; +my $is_comment = 0; +open IN, $file_in or die "Can't open $file_in"; +while (<IN>) { + $data .= $_; + + my $ln = $_; + if (!$is_comment) { + $ln =~ s,/\*.*(\*/),,g; + + $is_comment = 1 if ($ln =~ s,/\*.*,,); + } else { + if ($ln =~ s,^(.*\*/),,) { + $is_comment = 0; + } else { + next; + } + } + + if ($is_enum && $ln =~ m/^\s*([_\w][\w\d_]+)\s*[\,=]?/) { + my $s = $1; + my $n = $1; + $n =~ tr/A-Z/a-z/; + $n =~ tr/_/-/; + + $enum_symbols{$s} = "\\ :ref:`$s <$n>`\\ "; + + $is_enum = 0 if ($is_enum && m/\}/); + next; + } + $is_enum = 0 if ($is_enum && m/\}/); + + if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+_IO/) { + my $s = $1; + my $n = $1; + $n =~ tr/A-Z/a-z/; + + $ioctls{$s} = "\\ :ref:`$s <$n>`\\ "; + next; + } + + if ($ln =~ m/^\s*#\s*define\s+([_\w][\w\d_]+)\s+/) { + my $s = $1; + my $n = $1; + $n =~ tr/A-Z/a-z/; + $n =~ tr/_/-/; + + $defines{$s} = "\\ :ref:`$s <$n>`\\ "; + next; + } + + if ($ln =~ m/^\s*typedef\s+([_\w][\w\d_]+)\s+(.*)\s+([_\w][\w\d_]+);/) { + my $s = $2; + my $n = $3; + + $typedefs{$n} = "\\ :c:type:`$n <$s>`\\ "; + next; + } + if ($ln =~ m/^\s*enum\s+([_\w][\w\d_]+)\s+\{/ + || $ln =~ m/^\s*enum\s+([_\w][\w\d_]+)$/ + || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)\s+\{/ + || $ln =~ m/^\s*typedef\s*enum\s+([_\w][\w\d_]+)$/) { + my $s = $1; + + $enums{$s} = "enum :c:type:`$s`\\ "; + + $is_enum = $1; + next; + } + if ($ln =~ m/^\s*struct\s+([_\w][\w\d_]+)\s+\{/ + || $ln =~ m/^\s*struct\s+([[_\w][\w\d_]+)$/ + || $ln =~ m/^\s*typedef\s*struct\s+([_\w][\w\d_]+)\s+\{/ + || $ln =~ m/^\s*typedef\s*struct\s+([[_\w][\w\d_]+)$/ + ) { + my $s = $1; + + $structs{$s} = "struct :c:type:`$s`\\ "; + next; + } +} +close IN; + +# +# Handle multi-line typedefs +# + +my @matches = ($data =~ m/typedef\s+struct\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g, + $data =~ m/typedef\s+enum\s+\S+?\s*\{[^\}]+\}\s*(\S+)\s*\;/g,); +foreach my $m (@matches) { + my $s = $m; + + $typedefs{$s} = "\\ :c:type:`$s`\\ "; + next; +} + +# +# Handle exceptions, if any +# + +my %def_reftype = ( + "ioctl" => ":ref", + "define" => ":ref", + "symbol" => ":ref", + "typedef" => ":c:type", + "enum" => ":c:type", + "struct" => ":c:type", +); + +if ($file_exceptions) { + open IN, $file_exceptions or die "Can't read $file_exceptions"; + while (<IN>) { + next if (m/^\s*$/ || m/^\s*#/); + + # Parsers to ignore a symbol + + if (m/^ignore\s+ioctl\s+(\S+)/) { + delete $ioctls{$1} if (exists($ioctls{$1})); + next; + } + if (m/^ignore\s+define\s+(\S+)/) { + delete $defines{$1} if (exists($defines{$1})); + next; + } + if (m/^ignore\s+typedef\s+(\S+)/) { + delete $typedefs{$1} if (exists($typedefs{$1})); + next; + } + if (m/^ignore\s+enum\s+(\S+)/) { + delete $enums{$1} if (exists($enums{$1})); + next; + } + if (m/^ignore\s+struct\s+(\S+)/) { + delete $structs{$1} if (exists($structs{$1})); + next; + } + if (m/^ignore\s+symbol\s+(\S+)/) { + delete $enum_symbols{$1} if (exists($enum_symbols{$1})); + next; + } + + # Parsers to replace a symbol + my ($type, $old, $new, $reftype); + + if (m/^replace\s+(\S+)\s+(\S+)\s+(\S+)/) { + $type = $1; + $old = $2; + $new = $3; + } else { + die "Can't parse $file_exceptions: $_"; + } + + if ($new =~ m/^\:c\:(data|func|macro|type)\:\`(.+)\`/) { + $reftype = ":c:$1"; + $new = $2; + } elsif ($new =~ m/\:ref\:\`(.+)\`/) { + $reftype = ":ref"; + $new = $1; + } else { + $reftype = $def_reftype{$type}; + } + $new = "$reftype:`$old <$new>`"; + + if ($type eq "ioctl") { + $ioctls{$old} = $new if (exists($ioctls{$old})); + next; + } + if ($type eq "define") { + $defines{$old} = $new if (exists($defines{$old})); + next; + } + if ($type eq "symbol") { + $enum_symbols{$old} = $new if (exists($enum_symbols{$old})); + next; + } + if ($type eq "typedef") { + $typedefs{$old} = $new if (exists($typedefs{$old})); + next; + } + if ($type eq "enum") { + $enums{$old} = $new if (exists($enums{$old})); + next; + } + if ($type eq "struct") { + $structs{$old} = $new if (exists($structs{$old})); + next; + } + + die "Can't parse $file_exceptions: $_"; + } +} + +if ($debug) { + print Data::Dumper->Dump([\%ioctls], [qw(*ioctls)]) if (%ioctls); + print Data::Dumper->Dump([\%typedefs], [qw(*typedefs)]) if (%typedefs); + print Data::Dumper->Dump([\%enums], [qw(*enums)]) if (%enums); + print Data::Dumper->Dump([\%structs], [qw(*structs)]) if (%structs); + print Data::Dumper->Dump([\%defines], [qw(*defines)]) if (%defines); + print Data::Dumper->Dump([\%enum_symbols], [qw(*enum_symbols)]) if (%enum_symbols); +} + +# +# Align block +# +$data = expand($data); +$data = " " . $data; +$data =~ s/\n/\n /g; +$data =~ s/\n\s+$/\n/g; +$data =~ s/\n\s+\n/\n\n/g; + +# +# Add escape codes for special characters +# +$data =~ s,([\_\`\*\<\>\&\\\\:\/\|\%\$\#\{\}\~\^]),\\$1,g; + +$data =~ s,DEPRECATED,**DEPRECATED**,g; + +# +# Add references +# + +my $start_delim = "[ \n\t\(\=\*\@]"; +my $end_delim = "(\\s|,|\\\\=|\\\\:|\\;|\\\)|\\}|\\{)"; + +foreach my $r (keys %ioctls) { + my $s = $ioctls{$r}; + + $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; + + print "$r -> $s\n" if ($debug); + + $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; +} + +foreach my $r (keys %defines) { + my $s = $defines{$r}; + + $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; + + print "$r -> $s\n" if ($debug); + + $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; +} + +foreach my $r (keys %enum_symbols) { + my $s = $enum_symbols{$r}; + + $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; + + print "$r -> $s\n" if ($debug); + + $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; +} + +foreach my $r (keys %enums) { + my $s = $enums{$r}; + + $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; + + print "$r -> $s\n" if ($debug); + + $data =~ s/enum\s+($r)$end_delim/$s$2/g; +} + +foreach my $r (keys %structs) { + my $s = $structs{$r}; + + $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; + + print "$r -> $s\n" if ($debug); + + $data =~ s/struct\s+($r)$end_delim/$s$2/g; +} + +foreach my $r (keys %typedefs) { + my $s = $typedefs{$r}; + + $r =~ s,([\_\`\*\<\>\&\\\\:\/]),\\\\$1,g; + + print "$r -> $s\n" if ($debug); + $data =~ s/($start_delim)($r)$end_delim/$1$s$3/g; +} + +$data =~ s/\\ ([\n\s])/\1/g; + +# +# Generate output file +# + +my $title = $file_in; +$title =~ s,.*/,,; + +open OUT, "> $file_out" or die "Can't open $file_out"; +print OUT ".. -*- coding: utf-8; mode: rst -*-\n\n"; +print OUT "$title\n"; +print OUT "=" x length($title); +print OUT "\n\n.. parsed-literal::\n\n"; +print OUT $data; +close OUT; + +__END__ + +=head1 NAME + +parse_headers.pl - parse a C file, in order to identify functions, structs, +enums and defines and create cross-references to a Sphinx book. + +=head1 SYNOPSIS + +B<parse_headers.pl> [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>] + +Where <options> can be: --debug, --help or --man. + +=head1 OPTIONS + +=over 8 + +=item B<--debug> + +Put the script in verbose mode, useful for debugging. + +=item B<--usage> + +Prints a brief help message and exits. + +=item B<--help> + +Prints a more detailed help message and exits. + +=back + +=head1 DESCRIPTION + +Convert a C header or source file (C_FILE), into a ReStructured Text +included via ..parsed-literal block with cross-references for the +documentation files that describe the API. It accepts an optional +EXCEPTIONS_FILE with describes what elements will be either ignored or +be pointed to a non-default reference. + +The output is written at the (OUT_FILE). + +It is capable of identifying defines, functions, structs, typedefs, +enums and enum symbols and create cross-references for all of them. +It is also capable of distinguish #define used for specifying a Linux +ioctl. + +The EXCEPTIONS_FILE contain two rules to allow ignoring a symbol or +to replace the default references by a custom one. + +Please read Documentation/doc-guide/parse-headers.rst at the Kernel's +tree for more details. + +=head1 BUGS + +Report bugs to Mauro Carvalho Chehab <mchehab@kernel.org> + +=head1 COPYRIGHT + +Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab+samsung@kernel.org>. + +License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>. + +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + +=cut
diff --git a/Documentation/sphinx/requirements.txt b/Documentation/sphinx/requirements.txt new file mode 100644 index 0000000..742be3e --- /dev/null +++ b/Documentation/sphinx/requirements.txt
@@ -0,0 +1,3 @@ +docutils==0.12 +Sphinx==1.4.9 +sphinx_rtd_theme
diff --git a/Documentation/sphinx/rstFlatTable.py b/Documentation/sphinx/rstFlatTable.py new file mode 100755 index 0000000..25feb0d --- /dev/null +++ b/Documentation/sphinx/rstFlatTable.py
@@ -0,0 +1,376 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8; mode: python -*- +# pylint: disable=C0330, R0903, R0912 + +u""" + flat-table + ~~~~~~~~~~ + + Implementation of the ``flat-table`` reST-directive. + + :copyright: Copyright (C) 2016 Markus Heiser + :license: GPL Version 2, June 1991 see linux/COPYING for details. + + The ``flat-table`` (:py:class:`FlatTable`) is a double-stage list similar to + the ``list-table`` with some additional features: + + * *column-span*: with the role ``cspan`` a cell can be extended through + additional columns + + * *row-span*: with the role ``rspan`` a cell can be extended through + additional rows + + * *auto span* rightmost cell of a table row over the missing cells on the + right side of that table-row. With Option ``:fill-cells:`` this behavior + can changed from *auto span* to *auto fill*, which automaticly inserts + (empty) cells instead of spanning the last cell. + + Options: + + * header-rows: [int] count of header rows + * stub-columns: [int] count of stub columns + * widths: [[int] [int] ... ] widths of columns + * fill-cells: instead of autospann missing cells, insert missing cells + + roles: + + * cspan: [int] additionale columns (*morecols*) + * rspan: [int] additionale rows (*morerows*) +""" + +# ============================================================================== +# imports +# ============================================================================== + +import sys + +from docutils import nodes +from docutils.parsers.rst import directives, roles +from docutils.parsers.rst.directives.tables import Table +from docutils.utils import SystemMessagePropagation + +# ============================================================================== +# common globals +# ============================================================================== + +# The version numbering follows numbering of the specification +# (Documentation/books/kernel-doc-HOWTO). +__version__ = '1.0' + +PY3 = sys.version_info[0] == 3 +PY2 = sys.version_info[0] == 2 + +if PY3: + # pylint: disable=C0103, W0622 + unicode = str + basestring = str + +# ============================================================================== +def setup(app): +# ============================================================================== + + app.add_directive("flat-table", FlatTable) + roles.register_local_role('cspan', c_span) + roles.register_local_role('rspan', r_span) + + return dict( + version = __version__, + parallel_read_safe = True, + parallel_write_safe = True + ) + +# ============================================================================== +def c_span(name, rawtext, text, lineno, inliner, options=None, content=None): +# ============================================================================== + # pylint: disable=W0613 + + options = options if options is not None else {} + content = content if content is not None else [] + nodelist = [colSpan(span=int(text))] + msglist = [] + return nodelist, msglist + +# ============================================================================== +def r_span(name, rawtext, text, lineno, inliner, options=None, content=None): +# ============================================================================== + # pylint: disable=W0613 + + options = options if options is not None else {} + content = content if content is not None else [] + nodelist = [rowSpan(span=int(text))] + msglist = [] + return nodelist, msglist + + +# ============================================================================== +class rowSpan(nodes.General, nodes.Element): pass # pylint: disable=C0103,C0321 +class colSpan(nodes.General, nodes.Element): pass # pylint: disable=C0103,C0321 +# ============================================================================== + +# ============================================================================== +class FlatTable(Table): +# ============================================================================== + + u"""FlatTable (``flat-table``) directive""" + + option_spec = { + 'name': directives.unchanged + , 'class': directives.class_option + , 'header-rows': directives.nonnegative_int + , 'stub-columns': directives.nonnegative_int + , 'widths': directives.positive_int_list + , 'fill-cells' : directives.flag } + + def run(self): + + if not self.content: + error = self.state_machine.reporter.error( + 'The "%s" directive is empty; content required.' % self.name, + nodes.literal_block(self.block_text, self.block_text), + line=self.lineno) + return [error] + + title, messages = self.make_title() + node = nodes.Element() # anonymous container for parsing + self.state.nested_parse(self.content, self.content_offset, node) + + tableBuilder = ListTableBuilder(self) + tableBuilder.parseFlatTableNode(node) + tableNode = tableBuilder.buildTableNode() + # SDK.CONSOLE() # print --> tableNode.asdom().toprettyxml() + if title: + tableNode.insert(0, title) + return [tableNode] + messages + + +# ============================================================================== +class ListTableBuilder(object): +# ============================================================================== + + u"""Builds a table from a double-stage list""" + + def __init__(self, directive): + self.directive = directive + self.rows = [] + self.max_cols = 0 + + def buildTableNode(self): + + colwidths = self.directive.get_column_widths(self.max_cols) + if isinstance(colwidths, tuple): + # Since docutils 0.13, get_column_widths returns a (widths, + # colwidths) tuple, where widths is a string (i.e. 'auto'). + # See https://sourceforge.net/p/docutils/patches/120/. + colwidths = colwidths[1] + stub_columns = self.directive.options.get('stub-columns', 0) + header_rows = self.directive.options.get('header-rows', 0) + + table = nodes.table() + tgroup = nodes.tgroup(cols=len(colwidths)) + table += tgroup + + + for colwidth in colwidths: + colspec = nodes.colspec(colwidth=colwidth) + # FIXME: It seems, that the stub method only works well in the + # absence of rowspan (observed by the html buidler, the docutils-xml + # build seems OK). This is not extraordinary, because there exists + # no table directive (except *this* flat-table) which allows to + # define coexistent of rowspan and stubs (there was no use-case + # before flat-table). This should be reviewed (later). + if stub_columns: + colspec.attributes['stub'] = 1 + stub_columns -= 1 + tgroup += colspec + stub_columns = self.directive.options.get('stub-columns', 0) + + if header_rows: + thead = nodes.thead() + tgroup += thead + for row in self.rows[:header_rows]: + thead += self.buildTableRowNode(row) + + tbody = nodes.tbody() + tgroup += tbody + + for row in self.rows[header_rows:]: + tbody += self.buildTableRowNode(row) + return table + + def buildTableRowNode(self, row_data, classes=None): + classes = [] if classes is None else classes + row = nodes.row() + for cell in row_data: + if cell is None: + continue + cspan, rspan, cellElements = cell + + attributes = {"classes" : classes} + if rspan: + attributes['morerows'] = rspan + if cspan: + attributes['morecols'] = cspan + entry = nodes.entry(**attributes) + entry.extend(cellElements) + row += entry + return row + + def raiseError(self, msg): + error = self.directive.state_machine.reporter.error( + msg + , nodes.literal_block(self.directive.block_text + , self.directive.block_text) + , line = self.directive.lineno ) + raise SystemMessagePropagation(error) + + def parseFlatTableNode(self, node): + u"""parses the node from a :py:class:`FlatTable` directive's body""" + + if len(node) != 1 or not isinstance(node[0], nodes.bullet_list): + self.raiseError( + 'Error parsing content block for the "%s" directive: ' + 'exactly one bullet list expected.' % self.directive.name ) + + for rowNum, rowItem in enumerate(node[0]): + row = self.parseRowItem(rowItem, rowNum) + self.rows.append(row) + self.roundOffTableDefinition() + + def roundOffTableDefinition(self): + u"""Round off the table definition. + + This method rounds off the table definition in :py:member:`rows`. + + * This method inserts the needed ``None`` values for the missing cells + arising from spanning cells over rows and/or columns. + + * recount the :py:member:`max_cols` + + * Autospan or fill (option ``fill-cells``) missing cells on the right + side of the table-row + """ + + y = 0 + while y < len(self.rows): + x = 0 + + while x < len(self.rows[y]): + cell = self.rows[y][x] + if cell is None: + x += 1 + continue + cspan, rspan = cell[:2] + # handle colspan in current row + for c in range(cspan): + try: + self.rows[y].insert(x+c+1, None) + except: # pylint: disable=W0702 + # the user sets ambiguous rowspans + pass # SDK.CONSOLE() + # handle colspan in spanned rows + for r in range(rspan): + for c in range(cspan + 1): + try: + self.rows[y+r+1].insert(x+c, None) + except: # pylint: disable=W0702 + # the user sets ambiguous rowspans + pass # SDK.CONSOLE() + x += 1 + y += 1 + + # Insert the missing cells on the right side. For this, first + # re-calculate the max columns. + + for row in self.rows: + if self.max_cols < len(row): + self.max_cols = len(row) + + # fill with empty cells or cellspan? + + fill_cells = False + if 'fill-cells' in self.directive.options: + fill_cells = True + + for row in self.rows: + x = self.max_cols - len(row) + if x and not fill_cells: + if row[-1] is None: + row.append( ( x - 1, 0, []) ) + else: + cspan, rspan, content = row[-1] + row[-1] = (cspan + x, rspan, content) + elif x and fill_cells: + for i in range(x): + row.append( (0, 0, nodes.comment()) ) + + def pprint(self): + # for debugging + retVal = "[ " + for row in self.rows: + retVal += "[ " + for col in row: + if col is None: + retVal += ('%r' % col) + retVal += "\n , " + else: + content = col[2][0].astext() + if len (content) > 30: + content = content[:30] + "..." + retVal += ('(cspan=%s, rspan=%s, %r)' + % (col[0], col[1], content)) + retVal += "]\n , " + retVal = retVal[:-2] + retVal += "]\n , " + retVal = retVal[:-2] + return retVal + "]" + + def parseRowItem(self, rowItem, rowNum): + row = [] + childNo = 0 + error = False + cell = None + target = None + + for child in rowItem: + if (isinstance(child , nodes.comment) + or isinstance(child, nodes.system_message)): + pass + elif isinstance(child , nodes.target): + target = child + elif isinstance(child, nodes.bullet_list): + childNo += 1 + cell = child + else: + error = True + break + + if childNo != 1 or error: + self.raiseError( + 'Error parsing content block for the "%s" directive: ' + 'two-level bullet list expected, but row %s does not ' + 'contain a second-level bullet list.' + % (self.directive.name, rowNum + 1)) + + for cellItem in cell: + cspan, rspan, cellElements = self.parseCellItem(cellItem) + if target is not None: + cellElements.insert(0, target) + row.append( (cspan, rspan, cellElements) ) + return row + + def parseCellItem(self, cellItem): + # search and remove cspan, rspan colspec from the first element in + # this listItem (field). + cspan = rspan = 0 + if not len(cellItem): + return cspan, rspan, [] + for elem in cellItem[0]: + if isinstance(elem, colSpan): + cspan = elem.get("span") + elem.parent.remove(elem) + continue + if isinstance(elem, rowSpan): + rspan = elem.get("span") + elem.parent.remove(elem) + continue + return cspan, rspan, cellItem[:]
diff --git a/Kbuild b/Kbuild new file mode 100644 index 0000000..e2e3b29 --- /dev/null +++ b/Kbuild
@@ -0,0 +1,68 @@ +# +# Kbuild for top-level directory of U-Boot +# This file takes care of the following: +# 1) Generate generic-asm-offsets.h +# 2) Generate asm-offsets.h + +# Default sed regexp - multiline due to syntax constraints +define sed-y + "s:[[:space:]]*\.ascii[[:space:]]*\"\(.*\)\":\1:; \ + /^->/{s:->#\(.*\):/* \1 */:; \ + s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ + s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ + s:->::; p;}" +endef + +# Use filechk to avoid rebuilds when a header changes, but the resulting file +# does not +define filechk_offsets + (set -e; \ + echo "#ifndef $2"; \ + echo "#define $2"; \ + echo "/*"; \ + echo " * DO NOT MODIFY."; \ + echo " *"; \ + echo " * This file was generated by Kbuild"; \ + echo " */"; \ + echo ""; \ + sed -ne $(sed-y); \ + echo ""; \ + echo "#endif" ) +endef + +##### +# 1) Generate generic-asm-offsets.h + +generic-offsets-file := include/generated/generic-asm-offsets.h + +always := $(generic-offsets-file) +targets := lib/asm-offsets.s + +# We use internal kbuild rules to avoid the "is up to date" message from make +lib/asm-offsets.s: lib/asm-offsets.c FORCE + $(Q)mkdir -p $(dir $@) + $(call if_changed_dep,cc_s_c) + +$(obj)/$(generic-offsets-file): lib/asm-offsets.s FORCE + $(call filechk,offsets,__GENERIC_ASM_OFFSETS_H__) + +##### +# 2) Generate asm-offsets.h +# + +ifneq ($(wildcard $(srctree)/arch/$(ARCH)/lib/asm-offsets.c),) +offsets-file := include/generated/asm-offsets.h +endif + +always += $(offsets-file) +targets += arch/$(ARCH)/lib/asm-offsets.s + +CFLAGS_asm-offsets.o := -DDO_DEPS_ONLY + +# We use internal kbuild rules to avoid the "is up to date" message from make +arch/$(ARCH)/lib/asm-offsets.s: arch/$(ARCH)/lib/asm-offsets.c FORCE + $(Q)mkdir -p $(dir $@) + $(call if_changed_dep,cc_s_c) + +$(obj)/$(offsets-file): arch/$(ARCH)/lib/asm-offsets.s FORCE + $(call filechk,offsets,__ASM_OFFSETS_H__)
diff --git a/Kconfig b/Kconfig new file mode 100644 index 0000000..9278e59 --- /dev/null +++ b/Kconfig
@@ -0,0 +1,544 @@ +# +# For a description of the syntax of this configuration file, +# see the file Documentation/kbuild/kconfig-language.txt in the +# Linux kernel source tree. +# +mainmenu "U-Boot $UBOOTVERSION Configuration" + +config UBOOTVERSION + string + option env="UBOOTVERSION" + +# Allow defaults in arch-specific code to override any given here +source "arch/Kconfig" + +menu "General setup" + +config BROKEN + bool + help + This option cannot be enabled. It is used as dependency + for broken and incomplete features. + +config LOCALVERSION + string "Local version - append to U-Boot release" + help + Append an extra string to the end of your U-Boot version. + This will show up in your boot log, for example. + The string you set here will be appended after the contents of + any files with a filename matching localversion* in your + object and source tree, in that order. Your total string can + be a maximum of 64 characters. + +config LOCALVERSION_AUTO + bool "Automatically append version information to the version string" + default y + help + This will try to automatically determine if the current tree is a + release tree by looking for Git tags that belong to the current + top of tree revision. + + A string of the format -gxxxxxxxx will be added to the localversion + if a Git-based tree is found. The string generated by this will be + appended after any matching localversion* files, and after the value + set in CONFIG_LOCALVERSION. + + (The actual string used here is the first eight characters produced + by running the command: + + $ git rev-parse --verify HEAD + + which is done within the script "scripts/setlocalversion".) + +config CC_OPTIMIZE_FOR_SIZE + bool "Optimize for size" + default y + help + Enabling this option will pass "-Os" instead of "-O2" to gcc + resulting in a smaller U-Boot image. + + This option is enabled by default for U-Boot. + +config CC_COVERAGE + bool "Enable code coverage analysis" + depends on SANDBOX + help + Enabling this option will pass "--coverage" to gcc to compile + and link code instrumented for coverage analysis. + +config DISTRO_DEFAULTS + bool "Select defaults suitable for booting general purpose Linux distributions" + select AUTO_COMPLETE + select CMDLINE_EDITING + select CMD_BOOTI if ARM64 + select CMD_BOOTZ if ARM && !ARM64 + select CMD_DHCP if CMD_NET + select CMD_PING if CMD_NET + select CMD_ENV_EXISTS + select CMD_EXT4 + select CMD_FAT + select CMD_FS_GENERIC + select CMD_PART if PARTITIONS + select CMD_PING if CMD_NET + select CMD_PXE if NET + select ENV_VARS_UBOOT_CONFIG + select HUSH_PARSER + select SUPPORT_RAW_INITRD + select SYS_LONGHELP + imply CMD_MII if NET + imply USB_STORAGE + imply USE_BOOTCOMMAND + help + Select this to enable various options and commands which are suitable + for building u-boot for booting general purpose Linux distributions. + +config ENV_VARS_UBOOT_CONFIG + bool "Add arch, board, vendor and soc variables to default environment" + help + Define this in order to add variables describing the + U-Boot build configuration to the default environment. + These will be named arch, cpu, board, vendor, and soc. + Enabling this option will cause the following to be defined: + - CONFIG_SYS_ARCH + - CONFIG_SYS_CPU + - CONFIG_SYS_BOARD + - CONFIG_SYS_VENDOR + - CONFIG_SYS_SOC + +config NR_DRAM_BANKS + int "Number of DRAM banks" + default 4 + help + This defines the number of DRAM banks. + +config SYS_BOOT_GET_CMDLINE + bool "Enable kernel command line setup" + help + Enables allocating and saving kernel cmdline in space between + "bootm_low" and "bootm_low" + BOOTMAPSZ. + +config SYS_BOOT_GET_KBD + bool "Enable kernel board information setup" + help + Enables allocating and saving a kernel copy of the bd_info in + space between "bootm_low" and "bootm_low" + BOOTMAPSZ. + +config SYS_MALLOC_F + bool "Enable malloc() pool before relocation" + default y if DM + + help + Before relocation, memory is very limited on many platforms. Still, + we can provide a small malloc() pool if needed. Driver model in + particular needs this to operate, so that it can allocate the + initial serial device and any others that are needed. + +config SYS_MALLOC_F_LEN + hex "Size of malloc() pool before relocation" + depends on SYS_MALLOC_F + default 0x1000 if AM33XX + default 0x2800 if SANDBOX + default 0x400 + help + Before relocation, memory is very limited on many platforms. Still, + we can provide a small malloc() pool if needed. Driver model in + particular needs this to operate, so that it can allocate the + initial serial device and any others that are needed. + +config SYS_MALLOC_LEN + hex "Define memory for Dynamic allocation" + depends on ARCH_ZYNQ || ARCH_VERSAL + help + This defines memory to be allocated for Dynamic allocation + TODO: Use for other architectures + +config SPL_SYS_MALLOC_F_LEN + hex "Size of malloc() pool in SPL before relocation" + depends on SYS_MALLOC_F + default SYS_MALLOC_F_LEN + help + Before relocation, memory is very limited on many platforms. Still, + we can provide a small malloc() pool if needed. Driver model in + particular needs this to operate, so that it can allocate the + initial serial device and any others that are needed. + +config TPL_SYS_MALLOC_F_LEN + hex "Size of malloc() pool in TPL before relocation" + depends on SYS_MALLOC_F + default SYS_MALLOC_F_LEN + help + Before relocation, memory is very limited on many platforms. Still, + we can provide a small malloc() pool if needed. Driver model in + particular needs this to operate, so that it can allocate the + initial serial device and any others that are needed. + +menuconfig EXPERT + bool "Configure standard U-Boot features (expert users)" + default y + help + This option allows certain base U-Boot options and settings + to be disabled or tweaked. This is for specialized + environments which can tolerate a "non-standard" U-Boot. + Use this only if you really know what you are doing. + +if EXPERT + config SYS_MALLOC_CLEAR_ON_INIT + bool "Init with zeros the memory reserved for malloc (slow)" + default y + help + This setting is enabled by default. The reserved malloc + memory is initialized with zeros, so first malloc calls + will return the pointer to the zeroed memory. But this + slows the boot time. + + It is recommended to disable it, when CONFIG_SYS_MALLOC_LEN + value, has more than few MiB, e.g. when uses bzip2 or bmp logo. + Then the boot time can be significantly reduced. + Warning: + When disabling this, please check if malloc calls, maybe + should be replaced by calloc - if one expects zeroed memory. + +config TOOLS_DEBUG + bool "Enable debug information for tools" + help + Enable generation of debug information for tools such as mkimage. + This can be used for debugging purposes. With debug information + it is possible to set breakpoints on particular lines, single-step + debug through the source code, etc. + +endif # EXPERT + +config PHYS_64BIT + bool "64bit physical address support" + help + Say Y here to support 64bit physical memory address. + This can be used not only for 64bit SoCs, but also for + large physical address extention on 32bit SoCs. + +config BUILD_ROM + bool "Build U-Boot as BIOS replacement" + depends on X86 + help + This option allows to build a ROM version of U-Boot. + The build process generally requires several binary blobs + which are not shipped in the U-Boot source tree. + Please, see doc/README.x86 for details. + +endmenu # General setup + +menu "Boot images" + +config ANDROID_BOOT_IMAGE + bool "Enable support for Android Boot Images" + default y if FASTBOOT + help + This enables support for booting images which use the Android + image format header. + +config FIT + bool "Support Flattened Image Tree" + select MD5 + select SHA1 + help + This option allows you to boot the new uImage structure, + Flattened Image Tree. FIT is formally a FDT, which can include + images of various types (kernel, FDT blob, ramdisk, etc.) + in a single blob. To boot this new uImage structure, + pass the address of the blob to the "bootm" command. + FIT is very flexible, supporting compression, multiple images, + multiple configurations, verification through hashing and also + verified boot (secure boot using RSA). + +if FIT + +config FIT_EXTERNAL_OFFSET + hex "Text Base" + default 0x0 + help + This specifies a data offset in fit image. + The offset is from data payload offset to the beginning of + fit image header. When specifies a offset, specific data + could be put in the hole between data payload and fit image + header, such as CSF data on i.MX platform. + +config FIT_ENABLE_SHA256_SUPPORT + bool "Support SHA256 checksum of FIT image contents" + default y + select SHA256 + help + Enable this to support SHA256 checksum of FIT image contents. A + SHA256 checksum is a 256-bit (32-byte) hash value used to check that + the image contents have not been corrupted. SHA256 is recommended + for use in secure applications since (as at 2016) there is no known + feasible attack that could produce a 'collision' with differing + input data. Use this for the highest security. Note that only the + SHA256 variant is supported: SHA512 and others are not currently + supported in U-Boot. + +config FIT_FULL_CHECK + bool "Do a full check of the FIT before using it" + default y + help + Enable this do a full check of the FIT to make sure it is valid. This + helps to protect against carefully crafted FITs which take advantage + of bugs or omissions in the code. This includes a bad structure, + multiple root nodes and the like. + +config FIT_SIGNATURE + bool "Enable signature verification of FIT uImages" + depends on DM + select HASH + select FIT_FULL_CHECK + select RSA + help + This option enables signature verification of FIT uImages, + using a hash signed and verified using RSA. If + CONFIG_SHA_PROG_HW_ACCEL is defined, i.e support for progressive + hashing is available using hardware, then the RSA library will use + it. See doc/uImage.FIT/signature.txt for more details. + + WARNING: When relying on signed FIT images with a required signature + check the legacy image format is disabled by default, so that + unsigned images cannot be loaded. If a board needs the legacy image + format support in this case, enable it using + CONFIG_IMAGE_FORMAT_LEGACY. + +config FIT_SIGNATURE_MAX_SIZE + hex "Max size of signed FIT structures" + depends on FIT_SIGNATURE + default 0x10000000 + help + This option sets a max size in bytes for verified FIT uImages. + A sane value of 256MB protects corrupted DTB structures from overlapping + device memory. Assure this size does not extend past expected storage + space. + +config FIT_ENABLE_RSASSA_PSS_SUPPORT + bool "Support rsassa-pss signature scheme of FIT image contents" + depends on FIT_SIGNATURE + default n + help + Enable this to support the pss padding algorithm as described + in the rfc8017 (https://tools.ietf.org/html/rfc8017). + +config FIT_VERBOSE + bool "Show verbose messages when FIT images fail" + help + Generally a system will have valid FIT images so debug messages + are a waste of code space. If you are debugging your images then + you can enable this option to get more verbose information about + failures. + +config FIT_BEST_MATCH + bool "Select the best match for the kernel device tree" + help + When no configuration is explicitly selected, default to the + one whose fdt's compatibility field best matches that of + U-Boot itself. A match is considered "best" if it matches the + most specific compatibility entry of U-Boot's fdt's root node. + The order of entries in the configuration's fdt is ignored. + +config FIT_IMAGE_POST_PROCESS + bool "Enable post-processing of FIT artifacts after loading by U-Boot" + depends on TI_SECURE_DEVICE + help + Allows doing any sort of manipulation to blobs after they got extracted + from FIT images like stripping off headers or modifying the size of the + blob, verification, authentication, decryption etc. in a platform or + board specific way. In order to use this feature a platform or board- + specific implementation of board_fit_image_post_process() must be + provided. Also, anything done during this post-processing step would + need to be comprehended in how the images were prepared before being + injected into the FIT creation (i.e. the blobs would have been pre- + processed before being added to the FIT image). + +if SPL + +config SPL_FIT + bool "Support Flattened Image Tree within SPL" + depends on SPL + select SPL_OF_LIBFDT + +config SPL_FIT_PRINT + bool "Support FIT printing within SPL" + depends on SPL_FIT + help + Support printing the content of the fitImage in a verbose manner in SPL. + +config SPL_FIT_FULL_CHECK + bool "Do a full check of the FIT before using it" + help + Enable this do a full check of the FIT to make sure it is valid. This + helps to protect against carefully crafted FITs which take advantage + of bugs or omissions in the code. This includes a bad structure, + multiple root nodes and the like. + + +config SPL_FIT_SIGNATURE + bool "Enable signature verification of FIT firmware within SPL" + depends on SPL_DM + select SPL_FIT + select SPL_RSA + select SPL_FIT_FULL_CHECK + +config SPL_LOAD_FIT + bool "Enable SPL loading U-Boot as a FIT" + select SPL_FIT + help + Normally with the SPL framework a legacy image is generated as part + of the build. This contains U-Boot along with information as to + where it should be loaded. This option instead enables generation + of a FIT (Flat Image Tree) which provides more flexibility. In + particular it can handle selecting from multiple device tree + and passing the correct one to U-Boot. + +config SPL_LOAD_FIT_FULL + bool "Enable SPL loading U-Boot as a FIT" + select SPL_FIT + help + Normally with the SPL framework a legacy image is generated as part + of the build. This contains U-Boot along with information as to + where it should be loaded. This option instead enables generation + of a FIT (Flat Image Tree) which provides more flexibility. In + particular it can handle selecting from multiple device tree + and passing the correct one to U-Boot. + +config SPL_FIT_IMAGE_POST_PROCESS + bool "Enable post-processing of FIT artifacts after loading by the SPL" + depends on SPL_LOAD_FIT + help + Allows doing any sort of manipulation to blobs after they got extracted + from the U-Boot FIT image like stripping off headers or modifying the + size of the blob, verification, authentication, decryption etc. in a + platform or board specific way. In order to use this feature a platform + or board-specific implementation of board_fit_image_post_process() must + be provided. Also, anything done during this post-processing step would + need to be comprehended in how the images were prepared before being + injected into the FIT creation (i.e. the blobs would have been pre- + processed before being added to the FIT image). + +config SPL_FIT_SOURCE + string ".its source file for U-Boot FIT image" + depends on SPL_FIT + help + Specifies a (platform specific) FIT source file to generate the + U-Boot FIT image. This could specify further image to load and/or + execute. + +config SPL_FIT_GENERATOR + string ".its file generator script for U-Boot FIT image" + depends on SPL_FIT + default "board/sunxi/mksunxi_fit_atf.sh" if SPL_LOAD_FIT && ARCH_SUNXI + help + Specifies a (platform specific) script file to generate the FIT + source file used to build the U-Boot FIT image file. This gets + passed a list of supported device tree file stub names to + include in the generated image. + +endif # SPL + +endif # FIT + +config IMAGE_FORMAT_LEGACY + bool "Enable support for the legacy image format" + default y if !FIT_SIGNATURE + help + This option enables the legacy image format. It is enabled by + default for backward compatibility, unless FIT_SIGNATURE is + set where it is disabled so that unsigned images cannot be + loaded. If a board needs the legacy image format support in this + case, enable it here. + +config OF_BOARD_SETUP + bool "Set up board-specific details in device tree before boot" + depends on OF_LIBFDT + help + This causes U-Boot to call ft_board_setup() before booting into + the Operating System. This function can set up various + board-specific information in the device tree for use by the OS. + The device tree is then passed to the OS. + +config OF_SYSTEM_SETUP + bool "Set up system-specific details in device tree before boot" + depends on OF_LIBFDT + help + This causes U-Boot to call ft_system_setup() before booting into + the Operating System. This function can set up various + system-specific information in the device tree for use by the OS. + The device tree is then passed to the OS. + +config OF_STDOUT_VIA_ALIAS + bool "Update the device-tree stdout alias from U-Boot" + depends on OF_LIBFDT + help + This uses U-Boot's serial alias from the aliases node to update + the device tree passed to the OS. The "linux,stdout-path" property + in the chosen node is set to point to the correct serial node. + This option currently references CONFIG_CONS_INDEX, which is + incorrect when used with device tree as this option does not + exist / should not be used. + +config SYS_EXTRA_OPTIONS + string "Extra Options (DEPRECATED)" + help + The old configuration infrastructure (= mkconfig + boards.cfg) + provided the extra options field. If you have something like + "HAS_BAR,BAZ=64", the optional options + #define CONFIG_HAS + #define CONFIG_BAZ 64 + will be defined in include/config.h. + This option was prepared for the smooth migration from the old + configuration to Kconfig. Since this option will be removed sometime, + new boards should not use this option. + +config SYS_TEXT_BASE + depends on !NIOS2 && !XTENSA + depends on !EFI_APP + default 0x80800000 if ARCH_OMAP2PLUS || ARCH_K3 + default 0x4a000000 if ARCH_SUNXI && !MACH_SUN9I && !MACH_SUN8I_V3S + default 0x2a000000 if ARCH_SUNXI && MACH_SUN9I + default 0x42e00000 if ARCH_SUNXI && MACH_SUN8I_V3S + hex "Text Base" + help + The address in memory that U-Boot will be running from, initially. + + + +config SYS_CLK_FREQ + depends on ARC || ARCH_SUNXI + int "CPU clock frequency" + help + TODO: Move CONFIG_SYS_CLK_FREQ for all the architecture + +config ARCH_FIXUP_FDT_MEMORY + bool "Enable arch_fixup_memory_banks() call" + default y + help + Enable FDT memory map syncup before OS boot. This feature can be + used for booting OS with different memory setup where the part of + the memory location should be used for different purpose. + +endmenu # Boot images + +source "api/Kconfig" + +source "common/Kconfig" + +source "cmd/Kconfig" + +source "disk/Kconfig" + +source "dts/Kconfig" + +source "env/Kconfig" + +source "net/Kconfig" + +source "drivers/Kconfig" + +source "fs/Kconfig" + +source "lib/Kconfig" + +source "test/Kconfig" +
diff --git a/Licenses/Exceptions b/Licenses/Exceptions new file mode 100644 index 0000000..c9b3cd9 --- /dev/null +++ b/Licenses/Exceptions
@@ -0,0 +1,15 @@ + +GPL License Exception: + +Even though U-Boot in general is covered by the GPL-2.0/GPL-2.0+, +this does *not* cover the so-called "standalone" applications that +use U-Boot services by means of the jump table provided by U-Boot +exactly for this purpose - this is merely considered normal use of +U-Boot, and does *not* fall under the heading of "derived work". + + The header files "include/image.h" and "arch/*/include/asm/u-boot.h" +define interfaces to U-Boot. Including these (unmodified) header +files in another file is considered normal use of U-Boot, and does +*not* fall under the heading of "derived work". +-- Wolfgang Denk +
diff --git a/Licenses/OFL.txt b/Licenses/OFL.txt new file mode 100644 index 0000000..07c881f --- /dev/null +++ b/Licenses/OFL.txt
@@ -0,0 +1,97 @@ +Copyright (c) 2010, Andrey Makarov (makarov@bmstu.ru, mka-at-mailru@mail.ru), +with Reserved Font Name Anka/Coder Narrow. + +Copyright (c) 2011, Pablo Impallari (www.impallari.com|impallari@gmail.com), +Rodrigo Fuenzalida (www.rfuenzalida.com) with Reserved Font Name Cantora. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/Licenses/README b/Licenses/README new file mode 100644 index 0000000..486e18d --- /dev/null +++ b/Licenses/README
@@ -0,0 +1,153 @@ +SPDX-License-Identifier: GPL-2.0 + + U-Boot is Free Software. It is copyrighted by Wolfgang Denk and +many others who contributed code (see the actual source code and the +git commit messages for details). You can redistribute U-Boot and/or +modify it under the terms of version 2 of the GNU General Public +License as published by the Free Software Foundation. Most of it can +also be distributed, at your option, under any later version of the +GNU General Public License -- see individual files for exceptions. + + NOTE! This license does *not* cover the so-called "standalone" +applications that use U-Boot services by means of the jump table +provided by U-Boot exactly for this purpose - this is merely +considered normal use of U-Boot, and does *not* fall under the +heading of "derived work" -- see file Licenses/Exceptions for +details. + + Also note that the GPL and the other licenses are copyrighted by +the Free Software Foundation and other organizations, but the +instance of code that they refer to (the U-Boot source code) is +copyrighted by me and others who actually wrote it. +-- Wolfgang Denk + + +Like many other projects, U-Boot has a tradition of including big +blocks of License headers in all files. This not only blows up the +source code with mostly redundant information, but also makes it very +difficult to generate License Clearing Reports. An additional problem +is that even the same licenses are referred to by a number of +slightly varying text blocks (full, abbreviated, different +indentation, line wrapping and/or white space, with obsolete address +information, ...) which makes automatic processing a nightmare. + +To make this easier, such license headers in the source files will be +replaced with a single line reference to Unique License Identifiers +as defined by the Linux Foundation's SPDX project [1]. + +If a "SPDX-License-Identifier:" line references more than one Unique +License Identifier, then this means that the respective file can be +used under the terms of either of these licenses, i. e. with + + SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + +you can choose between GPL-2.0+ and BSD-3-Clause licensing. + +We use the SPDX Unique License Identifiers here; these are available +at [2]. + +License identifier syntax +------------------------- + +1. Placement: + + The SPDX license identifier in U-Boot files shall be added at the first + possible line in a file which can contain a comment. For the majority + or files this is the first line, except for scripts which require the + '#!PATH_TO_INTERPRETER' in the first line. For those scripts the SPDX + identifier goes into the second line. + +| + +2. Style: + + The SPDX license identifier is added in form of a comment. The comment + style depends on the file type:: + + C source: // SPDX-License-Identifier: <SPDX License Expression> + C header: /* SPDX-License-Identifier: <SPDX License Expression> */ + ASM: /* SPDX-License-Identifier: <SPDX License Expression> */ + scripts: # SPDX-License-Identifier: <SPDX License Expression> + .rst: .. SPDX-License-Identifier: <SPDX License Expression> + .dts{i}: // SPDX-License-Identifier: <SPDX License Expression> + + If a specific tool cannot handle the standard comment style, then the + appropriate comment mechanism which the tool accepts shall be used. This + is the reason for having the "/\* \*/" style comment in C header + files. There was build breakage observed with generated .lds files where + 'ld' failed to parse the C++ comment. This has been fixed by now, but + there are still older assembler tools which cannot handle C++ style + comments. + +| + +3. Syntax: + + A <SPDX License Expression> is either an SPDX short form license + identifier found on the SPDX License List, or the combination of two + SPDX short form license identifiers separated by "WITH" when a license + exception applies. When multiple licenses apply, an expression consists + of keywords "AND", "OR" separating sub-expressions and surrounded by + "(", ")" . + + License identifiers for licenses like [L]GPL with the 'or later' option + are constructed by using a "+" for indicating the 'or later' option.:: + + // SPDX-License-Identifier: GPL-2.0+ + // SPDX-License-Identifier: LGPL-2.1+ + + WITH should be used when there is a modifier to a license needed. + For example, the linux kernel UAPI files use the expression:: + + // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note + // SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note + + Other examples using WITH exceptions found in the linux kernel are:: + + // SPDX-License-Identifier: GPL-2.0 WITH mif-exception + // SPDX-License-Identifier: GPL-2.0+ WITH GCC-exception-2.0 + + Exceptions can only be used with particular License identifiers. The + valid License identifiers are listed in the tags of the exception text + file. + + OR should be used if the file is dual licensed and only one license is + to be selected. For example, some dtsi files are available under dual + licenses:: + + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + + Examples from U-Boot for license expressions in dual licensed files:: + + // SPDX-License-Identifier: GPL-2.0 OR MIT + // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + + AND should be used if the file has multiple licenses whose terms all + apply to use the file. For example, if code is inherited from another + project and permission has been given to put it in U-Boot, but the + original license terms need to remain in effect:: + + // SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) AND MIT + + Another other example where both sets of license terms need to be + adhered to is:: + + // SPDX-License-Identifier: GPL-1.0+ AND LGPL-2.1+ + +[1] http://spdx.org/ +[2] http://spdx.org/licenses/ + +Full name SPDX Identifier OSI Approved File name URI +======================================================================================================================================= +GNU General Public License v2.0 only GPL-2.0 Y gpl-2.0.txt http://www.gnu.org/licenses/gpl-2.0.txt +GNU General Public License v2.0 or later GPL-2.0+ Y gpl-2.0.txt http://www.gnu.org/licenses/gpl-2.0.txt +GNU Library General Public License v2 or later LGPL-2.0+ Y lgpl-2.0.txt http://www.gnu.org/licenses/old-licenses/lgpl-2.0.txt +GNU Lesser General Public License v2.1 or later LGPL-2.1+ Y lgpl-2.1.txt http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt +eCos license version 2.0 eCos-2.0 eCos-2.0.txt http://www.gnu.org/licenses/ecos-license.html +BSD 2-Clause License BSD-2-Clause Y bsd-2-clause.txt http://spdx.org/licenses/BSD-2-Clause +BSD 3-clause "New" or "Revised" License BSD-3-Clause Y bsd-3-clause.txt http://spdx.org/licenses/BSD-3-Clause#licenseText +IBM PIBS (PowerPC Initialization and IBM-pibs ibm-pibs.txt + Boot Software) license +ISC License ISC Y isc.txt https://spdx.org/licenses/ISC +SIL OPEN FONT LICENSE (OFL-1.1) OFL-1.1 Y OFL.txt https://spdx.org/licenses/OFL-1.1.html +X11 License X11 x11.txt https://spdx.org/licenses/X11.html
diff --git a/Licenses/bsd-2-clause.txt b/Licenses/bsd-2-clause.txt new file mode 100644 index 0000000..af69764 --- /dev/null +++ b/Licenses/bsd-2-clause.txt
@@ -0,0 +1,25 @@ +Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following +conditions are met: + +1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. +2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Licenses/bsd-3-clause.txt b/Licenses/bsd-3-clause.txt new file mode 100644 index 0000000..aac5e2a --- /dev/null +++ b/Licenses/bsd-3-clause.txt
@@ -0,0 +1,24 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions, and the following disclaimer, + without modification. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The names of the above-listed copyright holders may not be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Licenses/eCos-2.0.txt b/Licenses/eCos-2.0.txt new file mode 100644 index 0000000..8a12e20 --- /dev/null +++ b/Licenses/eCos-2.0.txt
@@ -0,0 +1,43 @@ + Note that this license is not endorsed by the Free Software Foundation. + It is available here as a convenience to readers of [1]the license + list. + +The eCos license version 2.0 + + This file is part of eCos, the Embedded Configurable Operating System. + Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. + + eCos 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 or (at your option) any later + version. + + eCos 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 eCos; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + As a special exception, if other files instantiate templates or use + macros or inline functions from this file, or you compile this file and + link it with other works to produce a work based on this file, this + file does not by itself cause the resulting work to be covered by the + GNU General Public License. However the source code for this file must + still be made available in accordance with section (3) of the GNU + General Public License. + + This exception does not invalidate any other reasons why a work based + on this file might be covered by the GNU General Public License. + + Alternative licenses for eCos may be arranged by contacting Red Hat, + Inc. at http://sources.redhat.com/ecos/ecos-license/ + ------------------------------------------- + + ####ECOSGPLCOPYRIGHTEND#### + +References + + 1. http://www.gnu.org/licenses/license-list.html
diff --git a/Licenses/gpl-2.0.txt b/Licenses/gpl-2.0.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/Licenses/gpl-2.0.txt
@@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License.
diff --git a/Licenses/ibm-pibs.txt b/Licenses/ibm-pibs.txt new file mode 100644 index 0000000..4cd7523 --- /dev/null +++ b/Licenses/ibm-pibs.txt
@@ -0,0 +1,17 @@ +This source code has been made available to you by IBM on an AS-IS +basis. Anyone receiving this source is licensed under IBM +copyrights to use it in any way he or she deems fit, including +copying it, modifying it, compiling it, and redistributing it either +with or without modifications. No license under IBM patents or +patent applications is to be implied by the copyright license. + +Any user of this software should understand that IBM cannot provide +technical support for this software and will not be responsible for +any consequences resulting from the use of this software. + +Any person who transfers this source code or any derivative work +must include the IBM copyright notice, this paragraph, and the +preceding two paragraphs in the transferred software. + +COPYRIGHT I B M CORPORATION 1995 +LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
diff --git a/Licenses/isc.txt b/Licenses/isc.txt new file mode 100644 index 0000000..4b7c2ba --- /dev/null +++ b/Licenses/isc.txt
@@ -0,0 +1,17 @@ +ISC License: +Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC") +Copyright (c) 1995-2003 by Internet Software Consortium + +Permission to use, copy, modify, and/or distribute this software +for any purpose with or without fee is hereby granted, +provided that the above copyright notice and this permission notice +appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE +FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE.
diff --git a/Licenses/lgpl-2.0.txt b/Licenses/lgpl-2.0.txt new file mode 100644 index 0000000..5bc8fb2 --- /dev/null +++ b/Licenses/lgpl-2.0.txt
@@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it!
diff --git a/Licenses/lgpl-2.1.txt b/Licenses/lgpl-2.1.txt new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/Licenses/lgpl-2.1.txt
@@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it!
diff --git a/Licenses/r8a779x_usb3.txt b/Licenses/r8a779x_usb3.txt new file mode 100644 index 0000000..e2afcc9 --- /dev/null +++ b/Licenses/r8a779x_usb3.txt
@@ -0,0 +1,26 @@ +Copyright (c) 2014, Renesas Electronics Corporation +All rights reserved. + +Redistribution and use in binary form, without modification, are permitted +provided that the following conditions are met: + +1. Redistribution in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +2. The name of Renesas Electronics Corporation may not be used to endorse or + promote products derived from this software without specific prior written + permission. +3. Reverse engineering, decompilation, or disassembly of this software is + not permitted. + +THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS ELECTRONICS CORPORATION DISCLAIMS +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL RENESAS ELECTRONICS +CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE.
diff --git a/Licenses/x11.txt b/Licenses/x11.txt new file mode 100644 index 0000000..23a3c63 --- /dev/null +++ b/Licenses/x11.txt
@@ -0,0 +1,25 @@ +X11 License +Copyright (C) 1996 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X +CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from the X Consortium. + +X Window System is a trademark of X Consortium, Inc.
diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 0000000..f86fdf9 --- /dev/null +++ b/MAINTAINERS
@@ -0,0 +1,742 @@ +Descriptions of section entries: + + P: Person (obsolete) + M: Mail patches to: FullName <address@domain> + R: Designated reviewer: FullName <address@domain> + These reviewers should be CCed on patches. + L: Mailing list that is relevant to this area + W: Web-page with status/info + Q: Patchwork web based patch tracking system site + T: SCM tree type and location. + Type is one of: git, hg, quilt, stgit, topgit + S: Status, one of the following: + Supported: Someone is actually paid to look after this. + Maintained: Someone actually looks after it. + Odd Fixes: It has a maintainer but they don't have time to do + much other than throw the odd patch in. See below.. + Orphan: No current maintainer [but maybe you could take the + role as you write your new code]. + Obsolete: Old code. Something tagged obsolete generally means + it has been replaced by a better system and you + should be using that. + F: Files and directories with wildcard patterns. + A trailing slash includes all files and subdirectory files. + F: drivers/net/ all files in and below drivers/net + F: drivers/net/* all files in drivers/net, but not below + F: */net/* all files in "any top level directory"/net + One pattern per line. Multiple F: lines acceptable. + N: Files and directories with regex patterns. + N: [^a-z]tegra all files whose path contains the word tegra + One pattern per line. Multiple N: lines acceptable. + scripts/get_maintainer.pl has different behavior for files that + match F: pattern and matches of N: patterns. By default, + get_maintainer will not look at git log history when an F: pattern + match occurs. When an N: match occurs, git log history is used + to also notify the people that have git commit signatures. + X: Files and directories that are NOT maintained, same rules as F: + Files exclusions are tested before file matches. + Can be useful for excluding a specific subdirectory, for instance: + F: net/ + X: net/ipv6/ + matches all files in and below net excluding net/ipv6/ + K: Keyword perl extended regex pattern to match content in a + patch or file. For instance: + K: of_get_profile + matches patches or files that contain "of_get_profile" + K: \b(printk|pr_(info|err))\b + matches patches or files that contain one or more of the words + printk, pr_info or pr_err + One regex pattern per line. Multiple K: lines acceptable. + +Note: For the hard of thinking, this list is meant to remain in alphabetical +order. If you could add yourselves to it in alphabetical order that would be +so much easier [Ed] + +Maintainers List (try to look for most precise areas first) + + ----------------------------------- +ARC +M: Alexey Brodkin <alexey.brodkin@synopsys.com> +M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> +S: Maintained +L: uboot-snps-arc@synopsys.com +T: git git://git.denx.de/u-boot-arc.git +F: arch/arc/ +F: board/synopsys/ + +ARC HSDK CGU CLOCK +M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> +S: Maintained +L: uboot-snps-arc@synopsys.com +F: drivers/clk/clk-hsdk-cgu.c +F: include/dt-bindings/clock/snps,hsdk-cgu.h +F: doc/device-tree-bindings/clock/snps,hsdk-cgu.txt + +ARC HSDK CREG GPIO +M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> +S: Maintained +L: uboot-snps-arc@synopsys.com +F: doc/device-tree-bindings/gpio/snps,creg-gpio.txt +F: drivers/gpio/hsdk-creg-gpio.c + +ARM +M: Albert Aribaud <albert.u.boot@aribaud.net> +S: Maintained +T: git git://git.denx.de/u-boot-arm.git +F: arch/arm/ + +ARM ALTERA SOCFPGA +M: Marek Vasut <marex@denx.de> +S: Maintainted +T: git git://git.denx.de/u-boot-socfpga.git +F: arch/arm/mach-socfpga/ + +ARM ATMEL AT91 +M: Andreas Bießmann <andreas@biessmann.org> +S: Maintained +T: git git://git.denx.de/u-boot-atmel.git +F: arch/arm/mach-at91/ + +ARM BROADCOM BCM283X +M: Alexander Graf <agraf@suse.de> +S: Maintained +F: arch/arm/mach-bcm283x/ +F: drivers/gpio/bcm2835_gpio.c +F: drivers/mmc/bcm2835_sdhci.c +F: drivers/mmc/bcm2835_sdhost.c +F: drivers/serial/serial_bcm283x_mu.c +F: drivers/serial/serial_bcm283x_pl011.c +F: drivers/video/bcm2835.c +F: include/dm/platform_data/serial_bcm283x_mu.h +F: drivers/pinctrl/broadcom/ + +ARM BROADCOM BCMSTB +M: Thomas Fitzsimmons <fitzsim@fitzsim.org> +S: Maintained +F: arch/arm/mach-bcmstb/ +F: board/broadcom/bcmstb/ +F: configs/bcm7*_defconfig +F: doc/README.bcm7xxx +F: drivers/mmc/bcmstb_sdhci.c +F: drivers/spi/bcmstb_spi.c + +ARM FREESCALE IMX +M: Stefano Babic <sbabic@denx.de> +M: Fabio Estevam <fabio.estevam@nxp.com> +R: NXP i.MX U-Boot Team <uboot-imx@nxp.com> +S: Maintained +T: git git://git.denx.de/u-boot-imx.git +F: arch/arm/cpu/arm1136/mx*/ +F: arch/arm/cpu/arm926ejs/mx*/ +F: arch/arm/cpu/armv7/vf610/ +F: arch/arm/mach-imx/ +F: arch/arm/include/asm/arch-imx/ +F: arch/arm/include/asm/arch-mx*/ +F: arch/arm/include/asm/arch-vf610/ +F: arch/arm/include/asm/mach-imx/ +F: board/freescale/*mx*/ + +ARM HISILICON +M: Peter Griffin <peter.griffin@linaro.org> +S: Maintained +F: arch/arm/cpu/armv8/hisilicon +F: arch/arm/include/asm/arch-hi6220/ + +ARM MARVELL KIRKWOOD ARMADA-XP ARMADA-38X ARMADA-37XX +M: Prafulla Wadaskar <prafulla@marvell.com> +M: Luka Perkov <luka.perkov@sartura.hr> +M: Stefan Roese <sr@denx.de> +S: Maintained +T: git git://git.denx.de/u-boot-marvell.git +F: arch/arm/mach-kirkwood/ +F: arch/arm/mach-mvebu/ +F: drivers/ata/ahci_mvebu.c +F: drivers/phy/marvell/ + +ARM MARVELL PXA +M: Marek Vasut <marex@denx.de> +S: Maintained +T: git git://git.denx.de/u-boot-pxa.git +F: arch/arm/cpu/pxa/ +F: arch/arm/include/asm/arch-pxa/ + +ARM MEDIATEK +M: Ryder Lee <ryder.lee@mediatek.com> +M: Weijie Gao <weijie.gao@mediatek.com> +S: Maintained +F: arch/arm/mach-mediatek/ +F: arch/arm/include/asm/arch-mediatek/ +F: board/mediatek/ +F: doc/README.mediatek +F: drivers/clk/mediatek/ +F: drivers/mmc/mtk-sd.c +F: drivers/pinctrl/mediatek/ +F: drivers/power/domain/mtk-power-domain.c +F: drivers/ram/mediatek/ +F: drivers/spi/mtk_qspi.c +F: drivers/timer/mtk_timer.c +F: drivers/watchdog/mtk_wdt.c +F: tools/mtk_image.c +F: tools/mtk_image.h +N: mediatek + +ARM OWL +M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> +S: Maintained +F: arch/arm/include/asm/arch-owl/ +F: arch/arm/mach-owl/ +F: board/ucRobotics/ +F: drivers/clk/owl/ +F: drivers/serial/serial_owl.c + +ARM RENESAS RMOBILE/R-CAR +M: Nobuhiro Iwamatsu <iwamatsu@nigauri.org> +M: Marek Vasut <marek.vasut+renesas@gmail.com> +S: Maintained +T: git git://git.denx.de/u-boot-sh.git +F: arch/arm/mach-rmobile/ + +ARM ROCKCHIP +M: Simon Glass <sjg@chromium.org> +M: Philipp Tomsich <philipp.tomsich@theobroma-systems.com> +S: Maintained +T: git git://git.denx.de/u-boot-rockchip.git +F: arch/arm/include/asm/arch-rockchip/ +F: arch/arm/mach-rockchip/ +F: board/rockchip/ +F: drivers/clk/rockchip/ +F: drivers/gpio/rk_gpio.c +F: drivers/misc/rockchip-efuse.c +F: drivers/mmc/rockchip_sdhci.c +F: drivers/mmc/rockchip_dw_mmc.c +F: drivers/pinctrl/rockchip/ +F: drivers/ram/rockchip/ +F: drivers/sysreset/sysreset_rockchip.c +F: drivers/video/rockchip/ +F: tools/rkcommon.c +F: tools/rkcommon.h +F: tools/rkimage.c +F: tools/rksd.c +F: tools/rkspi.c + +ARM SAMSUNG +M: Minkyu Kang <mk7.kang@samsung.com> +S: Maintained +T: git git://git.denx.de/u-boot-samsung.git +F: arch/arm/mach-exynos/ +F: arch/arm/mach-s5pc1xx/ +F: arch/arm/cpu/armv7/s5p-common/ + +ARM SNAPDRAGON +M: Ramon Fried <ramon.fried@gmail.com> +S: Maintained +F: arch/arm/mach-snapdragon/ +F: drivers/gpio/msm_gpio.c +F: drivers/mmc/msm_sdhci.c +F: drivers/phy/msm8916-usbh-phy.c +F: drivers/serial/serial_msm.c +F: drivers/smem/msm_smem.c +F: drivers/usb/host/ehci-msm.c + +ARM STI +M: Patrice Chotard <patrice.chotard@st.com> +S: Maintained +F: arch/arm/mach-sti/ +F: arch/arm/include/asm/arch-sti*/ + +ARM STM SPEAR +#M: Vipin Kumar <vipin.kumar@st.com> +S: Orphaned (Since 2016-02) +T: git git://git.denx.de/u-boot-stm.git +F: arch/arm/cpu/arm926ejs/spear/ +F: arch/arm/include/asm/arch-spear/ + +ARM STM STM32MP +M: Patrick Delaunay <patrick.delaunay@st.com> +M: Christophe Kerello <christophe.kerello@st.com> +M: Patrice Chotard <patrice.chotard@st.com> +L: uboot-stm32@st-md-mailman.stormreply.com (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-stm32mp +F: drivers/clk/clk_stm32mp1.c +F: drivers/i2c/stm32f7_i2c.c +F: drivers/misc/stm32mp_fuse.c +F: drivers/mmc/stm32_sdmmc2.c +F: drivers/phy/phy-stm32-usbphyc.c +F: drivers/pinctrl/pinctrl_stm32.c +F: drivers/power/regulator/stm32-vrefbuf.c +F: drivers/ram/stm32mp1/ +F: drivers/misc/stm32_rcc.c +F: drivers/reset/stm32-reset.c +F: drivers/spi/stm32_qspi.c + +ARM STM STV0991 +M: Vikas Manocha <vikas.manocha@st.com> +S: Maintained +F: arch/arm/cpu/armv7/stv0991/ +F: arch/arm/include/asm/arch-stv0991/ + +ARM SUNXI +M: Jagan Teki <jagan@openedev.com> +M: Maxime Ripard <maxime.ripard@bootlin.com> +S: Maintained +T: git git://git.denx.de/u-boot-sunxi.git +F: arch/arm/cpu/armv7/sunxi/ +F: arch/arm/include/asm/arch-sunxi/ +F: arch/arm/mach-sunxi/ +F: board/sunxi/ + +ARM TEGRA +M: Tom Warren <twarren@nvidia.com> +S: Maintained +T: git git://git.denx.de/u-boot-tegra.git +F: arch/arm/mach-tegra/ +F: arch/arm/include/asm/arch-tegra*/ + +ARM TI +M: Tom Rini <trini@konsulko.com> +S: Maintained +T: git git://git.denx.de/u-boot-ti.git +F: arch/arm/mach-davinci/ +F: arch/arm/mach-k3/ +F: arch/arm/mach-keystone/ +F: arch/arm/include/asm/arch-omap*/ +F: arch/arm/include/asm/ti-common/ + +ARM UNIPHIER +M: Masahiro Yamada <yamada.masahiro@socionext.com> +S: Maintained +T: git git://git.denx.de/u-boot-uniphier.git +F: arch/arm/mach-uniphier/ +F: configs/uniphier_*_defconfig +N: uniphier + +ARM VERSAL +M: Michal Simek <michal.simek@xilinx.com> +S: Maintained +T: git git://git.denx.de/u-boot-microblaze.git +F: arch/arm/mach-versal/ + +ARM VERSATILE EXPRESS DRIVERS +M: Liviu Dudau <liviu.dudau@foss.arm.com> +S: Maintained +T: git git://github.com/ARM-software/u-boot.git +F: drivers/misc/vexpress_config.c +N: vexpress + +ARM ZYNQ +M: Michal Simek <monstr@monstr.eu> +S: Maintained +T: git git://git.denx.de/u-boot-microblaze.git +F: arch/arm/mach-zynq/ +F: drivers/clk/clk_zynq.c +F: drivers/fpga/zynqpl.c +F: drivers/gpio/zynq_gpio.c +F: drivers/i2c/i2c-cdns.c +F: drivers/i2c/muxes/pca954x.c +F: drivers/i2c/zynq_i2c.c +F: drivers/mmc/zynq_sdhci.c +F: drivers/mtd/nand/raw/zynq_nand.c +F: drivers/net/phy/xilinx_phy.c +F: drivers/net/zynq_gem.c +F: drivers/serial/serial_zynq.c +F: drivers/spi/zynq_qspi.c +F: drivers/spi/zynq_spi.c +F: drivers/usb/host/ehci-zynq.c +F: drivers/watchdog/cdns_wdt.c +F: include/zynqpl.h +F: tools/zynqimage.c +N: zynq + +ARM ZYNQMP +M: Michal Simek <michal.simek@xilinx.com> +S: Maintained +T: git git://git.denx.de/u-boot-microblaze.git +F: arch/arm/cpu/armv8/zynqmp/ +F: drivers/clk/clk_zynqmp.c +F: drivers/fpga/zynqpl.c +F: drivers/gpio/zynq_gpio.c +F: drivers/i2c/i2c-cdns.c +F: drivers/i2c/muxes/pca954x.c +F: drivers/i2c/zynq_i2c.c +F: drivers/mmc/zynq_sdhci.c +F: drivers/mtd/nand/raw/zynq_nand.c +F: drivers/net/phy/xilinx_phy.c +F: drivers/net/zynq_gem.c +F: drivers/serial/serial_zynq.c +F: drivers/spi/zynq_qspi.c +F: drivers/spi/zynq_spi.c +F: drivers/timer/cadence-ttc.c +F: drivers/usb/host/ehci-zynq.c +F: drivers/watchdog/cdns_wdt.c +F: include/zynqmppl.h +F: tools/zynqmp* +N: ultra96 +N: zynqmp + +ARM ZYNQMP R5 +M: Michal Simek <michal.simek@xilinx.com> +S: Maintained +T: git git://git.denx.de/u-boot-microblaze.git +F: arch/arm/mach-zynqmp-r5/ + +BINMAN +M: Simon Glass <sjg@chromium.org> +S: Maintained +F: tools/binman/ + +BUILDMAN +M: Simon Glass <sjg@chromium.org> +S: Maintained +F: tools/buildman/ + +CFI FLASH +M: Stefan Roese <sr@denx.de> +S: Maintained +T: git git://git.denx.de/u-boot-cfi-flash.git +F: drivers/mtd/cfi_flash.c +F: drivers/mtd/jedec_flash.c + +COLDFIRE +M: Huan Wang <alison.wang@nxp.com> +M: Angelo Dureghello <angelo@sysam.it> +S: Maintained +T: git git://git.denx.de/u-boot-coldfire.git +F: arch/m68k/ + +DFU +M: Lukasz Majewski <lukma@denx.de> +S: Maintained +T: git git://git.denx.de/u-boot-dfu.git +F: drivers/dfu/ +F: drivers/usb/gadget/ + +DRIVER MODEL +M: Simon Glass <sjg@chromium.org> +S: Maintained +T: git git://git.denx.de/u-boot-dm.git +F: drivers/core/ +F: include/dm/ +F: test/dm/ + +EFI PAYLOAD +M: Alexander Graf <agraf@suse.de> +R: Heinrich Schuchardt <xypron.glpk@gmx.de> +S: Maintained +T: git git://github.com/agraf/u-boot.git +F: doc/README.uefi +F: doc/README.iscsi +F: Documentation/efi.rst +F: include/capitalization.h +F: include/cp1250.h +F: include/cp437.h +F: include/efi* +F: include/pe.h +F: include/asm-generic/pe.h +F: lib/charset.c +F: lib/efi*/ +F: test/py/tests/test_efi* +F: test/unicode_ut.c +F: cmd/bootefi.c +F: tools/file2include.c + +FPGA +M: Michal Simek <michal.simek@xilinx.com> +S: Maintained +T: git git://git.denx.de/u-boot-microblaze.git +F: drivers/fpga/ +F: cmd/fpga.c +F: include/fpga.h + +FLATTENED DEVICE TREE +M: Simon Glass <sjg@chromium.org> +S: Maintained +T: git git://git.denx.de/u-boot-fdt.git +F: lib/fdtdec* +F: lib/libfdt/ +F: include/fdt* +F: include/linux/libfdt* +F: cmd/fdt.c +F: common/fdt_support.c + +FREEBSD +M: Rafal Jaworowski <raj@semihalf.com> +S: Maintained +T: git git://git.denx.de/u-boot-freebsd.git + +FREESCALE QORIQ +M: York Sun <york.sun@nxp.com> +S: Maintained +T: git git://git.denx.de/u-boot-fsl-qoriq.git + +I2C +M: Heiko Schocher <hs@denx.de> +S: Maintained +T: git git://git.denx.de/u-boot-i2c.git +F: drivers/i2c/ + +LOGGING +M: Simon Glass <sjg@chromium.org> +S: Maintained +T: git git://git.denx.de/u-boot.git +F: common/log.c +F: cmd/log.c +F: test/log/log_test.c +F: test/py/tests/test_log.py + +MALI DISPLAY PROCESSORS +M: Liviu Dudau <liviu.dudau@foss.arm.com> +S: Supported +T: git git://github.com/ARM-software/u-boot.git +F: drivers/video/mali_dp.c +F: drivers/i2c/i2c-versatile.c + +MICROBLAZE +M: Michal Simek <monstr@monstr.eu> +S: Maintained +T: git git://git.denx.de/u-boot-microblaze.git +F: arch/microblaze/ +F: cmd/mfsl.c +F: drivers/gpio/xilinx_gpio.c +F: drivers/net/xilinx_axi_emac.c +F: drivers/net/xilinx_emaclite.c +F: drivers/serial/serial_xuartlite.c +F: drivers/spi/xilinx_spi.c +F: drivers/sysreset/sysreset_gpio.c +F: drivers/watchdog/xilinx_tb_wdt.c +N: xilinx + +MIPS +M: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> +S: Maintained +T: git git://git.denx.de/u-boot-mips.git +F: arch/mips/ + +MIPS MSCC +M: Gregory CLEMENT <gregory.clement@bootlin.com> +M: Lars Povlsen <lars.povlsen@microchip.com> +M: Horatiu Vultur <horatiu.vultur@microchip.com> +S: Maintained +F: arch/mips/mach-mscc/ +F: arch/mips/dts/luton* +F: arch/mips/dts/mscc* +F: arch/mips/dts/ocelot* +F: board/mscc/ +F: configs/mscc* +F: include/configs/vcoreiii.h + +MIPS JZ4780 +M: Ezequiel Garcia <ezequiel@collabora.com> +S: Maintained +F: arch/mips/mach-jz47xx/ + +MMC +M: Jaehoon Chung <jh80.chung@samsung.com> +S: Maintained +T: git git://git.denx.de/u-boot-mmc.git +F: drivers/mmc/ + +NAND FLASH +#M: Scott Wood <oss@buserror.net> +S: Orphaned (Since 2018-07) +T: git git://git.denx.de/u-boot-nand-flash.git +F: drivers/mtd/nand/raw/ + +NDS32 +M: Macpaul Lin <macpaul@andestech.com> +S: Maintained +T: git git://git.denx.de/u-boot-nds32.git +F: arch/nds32/ + +NETWORK +M: Joe Hershberger <joe.hershberger@ni.com> +S: Maintained +T: git git://git.denx.de/u-boot-net.git +F: drivers/net/ +F: net/ + +NIOS +M: Thomas Chou <thomas@wytron.com.tw> +S: Maintained +T: git git://git.denx.de/u-boot-nios.git +F: arch/nios2/ + +ONENAND +#M: Lukasz Majewski <l.majewski@majess.pl> +S: Orphaned (Since 2017-01) +T: git git://git.denx.de/u-boot-onenand.git +F: drivers/mtd/onenand/ + +PATMAN +M: Simon Glass <sjg@chromium.org> +S: Maintained +F: tools/patman/ + +POWER +M: Jaehoon Chung <jh80.chung@samsung.com> +S: Maintained +T: git git://git.denx.de/u-boot-pmic.git +F: drivers/power/ + +POWERPC +M: Wolfgang Denk <wd@denx.de> +S: Maintained +F: arch/powerpc/ + +POWERPC MPC8XX +M: Christophe Leroy <christophe.leroy@c-s.fr> +S: Maintained +T: git git://git.denx.de/u-boot-mpc8xx.git +F: arch/powerpc/cpu/mpc8xx/ + +POWERPC MPC83XX +M: Mario Six <mario.six@gdsys.cc> +S: Maintained +T: git git://git.denx.de/u-boot-mpc83xx.git +F: drivers/ram/mpc83xx_sdram.c +F: include/dt-bindings/memory/mpc83xx-sdram.h +F: drivers/sysreset/sysreset_mpc83xx.c +F: drivers/sysreset/sysreset_mpc83xx.h +F: drivers/clk/mpc83xx_clk.c +F: drivers/clk/mpc83xx_clk.h +F: include/dt-bindings/clk/mpc83xx-clk.h +F: drivers/timer/mpc83xx_timer.c +F: drivers/cpu/mpc83xx_cpu.c +F: drivers/cpu/mpc83xx_cpu.h +F: drivers/misc/mpc83xx_serdes.c +F: arch/powerpc/cpu/mpc83xx/ +F: arch/powerpc/include/asm/arch-mpc83xx/ + +POWERPC MPC85XX +M: York Sun <york.sun@nxp.com> +S: Maintained +T: git git://git.denx.de/u-boot-mpc85xx.git +F: arch/powerpc/cpu/mpc85xx/ + +POWERPC MPC86XX +M: York Sun <york.sun@nxp.com> +S: Maintained +T: git git://git.denx.de/u-boot-mpc86xx.git +F: arch/powerpc/cpu/mpc86xx/ + +RISC-V +M: Rick Chen <rick@andestech.com> +S: Maintained +T: git git://git.denx.de/u-boot-riscv.git +F: arch/riscv/ +F: tools/prelink-riscv.c + +ROCKUSB +M: Eddie Cai <eddie.cai.linux@gmail.com> +S: Maintained +F: drivers/usb/gadget/f_rockusb.c +F: cmd/rockusb.c +F: doc/README.rockusb + +SANDBOX +M: Simon Glass <sjg@chromium.org> +S: Maintained +F: arch/sandbox/ + +SH +M: Nobuhiro Iwamatsu <iwamatsu@nigauri.org> +S: Maintained +T: git git://git.denx.de/u-boot-sh.git +F: arch/sh/ + +SPI +M: Jagan Teki <jagan@openedev.com> +S: Maintained +T: git git://git.denx.de/u-boot-spi.git +F: drivers/mtd/spi/ +F: drivers/spi/ +F: include/spi* + +SPMI +M: Mateusz Kulikowski <mateusz.kulikowski@gmail.com> +S: Maintained +F: drivers/spmi/ +F: include/spmi/ + +TDA19988 HDMI ENCODER +M: Liviu Dudau <liviu.dudau@foss.arm.com> +S: Maintained +F: drivers/video/tda19988.c + +TI SYSTEM SECURITY +M: Andrew F. Davis <afd@ti.com> +S: Supported +F: arch/arm/mach-omap2/omap5/sec_entry_cpu1.S +F: arch/arm/mach-omap2/sec-common.c +F: arch/arm/mach-omap2/config_secure.mk +F: configs/am335x_hs_evm_defconfig +F: configs/am335x_hs_evm_uart_defconfig +F: configs/am43xx_hs_evm_defconfig +F: configs/am57xx_hs_evm_defconfig +F: configs/dra7xx_hs_evm_defconfig +F: configs/k2hk_hs_evm_defconfig +F: configs/k2e_hs_evm_defconfig +F: configs/k2g_hs_evm_defconfig +F: configs/k2l_hs_evm_defconfig + +TQ GROUP +#M: Martin Krause <martin.krause@tq-systems.de> +S: Orphaned (Since 2016-02) +T: git git://git.denx.de/u-boot-tq-group.git + +TEE +M: Jens Wiklander <jens.wiklander@linaro.org> +S: Maintained +F: drivers/tee/ +F: include/tee.h +F: include/tee/ + +UBI +M: Kyungmin Park <kmpark@infradead.org> +M: Heiko Schocher <hs@denx.de> +S: Maintained +T: git git://git.denx.de/u-boot-ubi.git +F: drivers/mtd/ubi/ + +USB +M: Marek Vasut <marex@denx.de> +S: Maintained +T: git git://git.denx.de/u-boot-usb.git +F: drivers/usb/ + +USB xHCI +M: Bin Meng <bmeng.cn@gmail.com> +S: Maintained +T: git git://git.denx.de/u-boot-usb.git topic-xhci +F: drivers/usb/host/xhci* + +VIDEO +M: Anatolij Gustschin <agust@denx.de> +S: Maintained +T: git git://git.denx.de/u-boot-video.git +F: drivers/video/ +F: common/lcd*.c +F: include/lcd*.h +F: include/video*.h + +X86 +M: Simon Glass <sjg@chromium.org> +M: Bin Meng <bmeng.cn@gmail.com> +S: Maintained +T: git git://git.denx.de/u-boot-x86.git +F: arch/x86/ + +XTENSA +M: Max Filippov <jcmvbkbc@gmail.com> +S: Maintained +F: arch/xtensa/ + +THE REST +M: Tom Rini <trini@konsulko.com> +L: u-boot@lists.denx.de +Q: http://patchwork.ozlabs.org/project/uboot/list/ +S: Maintained +T: git git://git.denx.de/u-boot.git +F: configs/tools-only_defconfig +F: * +F: */
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6dbe24c --- /dev/null +++ b/Makefile
@@ -0,0 +1,2027 @@ +# SPDX-License-Identifier: GPL-2.0+ + +VERSION = 2019 +PATCHLEVEL = 01 +SUBLEVEL = +EXTRAVERSION = +NAME = + +# *DOCUMENTATION* +# To see a list of typical targets execute "make help" +# More info can be located in ./README +# Comments in this file are targeted only to the developer, do not +# expect to learn how to build the kernel reading this file. + +# o Do not use make's built-in rules and variables +# (this increases performance and avoids hard-to-debug behaviour); +# o Look for make include files relative to root of kernel src +MAKEFLAGS += -rR --include-dir=$(CURDIR) + +# Avoid funny character set dependencies +unexport LC_ALL +LC_COLLATE=C +LC_NUMERIC=C +export LC_COLLATE LC_NUMERIC + +# Avoid interference with shell env settings +unexport GREP_OPTIONS + +# We are using a recursive build, so we need to do a little thinking +# to get the ordering right. +# +# Most importantly: sub-Makefiles should only ever modify files in +# their own directory. If in some directory we have a dependency on +# a file in another dir (which doesn't happen often, but it's often +# unavoidable when linking the built-in.o targets which finally +# turn into vmlinux), we will call a sub make in that other dir, and +# after that we are sure that everything which is in that other dir +# is now up to date. +# +# The only cases where we need to modify files which have global +# effects are thus separated out and done before the recursive +# descending is started. They are now explicitly listed as the +# prepare rule. + +# We use U_BOOT_DATE and U_BOOT_TIME to record u-boot build timestamp. +# make T=0 or by default to use local time (date) as build timestamp. +# make T=1 to use latest git commit time as build timestamp. +ifeq ("$(origin T)", "command line") + KBUILD_TIME_STAMP = $(T) +endif +ifndef KBUILD_TIME_STAMP + KBUILD_TIME_STAMP = 0 +endif + +# Beautify output +# --------------------------------------------------------------------------- +# +# Normally, we echo the whole command before executing it. By making +# that echo $($(quiet)$(cmd)), we now have the possibility to set +# $(quiet) to choose other forms of output instead, e.g. +# +# quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@ +# cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< +# +# If $(quiet) is empty, the whole command will be printed. +# If it is set to "quiet_", only the short version will be printed. +# If it is set to "silent_", nothing will be printed at all, since +# the variable $(silent_cmd_cc_o_c) doesn't exist. +# +# A simple variant is to prefix commands with $(Q) - that's useful +# for commands that shall be hidden in non-verbose mode. +# +# $(Q)ln $@ :< +# +# If KBUILD_VERBOSE equals 0 then the above command will be hidden. +# If KBUILD_VERBOSE equals 1 then the above command is displayed. +# +# To put more focus on warnings, be less verbose as default +# Use 'make V=1' to see the full commands + +ifeq ("$(origin V)", "command line") + KBUILD_VERBOSE = $(V) +endif +ifndef KBUILD_VERBOSE + KBUILD_VERBOSE = 0 +endif + +ifeq ($(KBUILD_VERBOSE),1) + quiet = + Q = +else + quiet=quiet_ + Q = @ +endif + +# If the user is running make -s (silent mode), suppress echoing of +# commands + +ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4 +ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),) + quiet=silent_ +endif +else # make-3.8x +ifneq ($(filter s% -s%,$(MAKEFLAGS)),) + quiet=silent_ +endif +endif + +export quiet Q KBUILD_VERBOSE + +# kbuild supports saving output files in a separate directory. +# To locate output files in a separate directory two syntaxes are supported. +# In both cases the working directory must be the root of the kernel src. +# 1) O= +# Use "make O=dir/to/store/output/files/" +# +# 2) Set KBUILD_OUTPUT +# Set the environment variable KBUILD_OUTPUT to point to the directory +# where the output files shall be placed. +# export KBUILD_OUTPUT=dir/to/store/output/files/ +# make +# +# The O= assignment takes precedence over the KBUILD_OUTPUT environment +# variable. + +# KBUILD_SRC is set on invocation of make in OBJ directory +# KBUILD_SRC is not intended to be used by the regular user (for now) +ifeq ($(KBUILD_SRC),) + +# OK, Make called in directory where kernel src resides +# Do we want to locate output files in a separate directory? +ifeq ("$(origin O)", "command line") + KBUILD_OUTPUT := $(O) +endif + +# That's our default target when none is given on the command line +PHONY := _all +_all: + +# Cancel implicit rules on top Makefile +$(CURDIR)/Makefile Makefile: ; + +ifneq ($(KBUILD_OUTPUT),) +# Invoke a second make in the output directory, passing relevant variables +# check that the output directory actually exists +saved-output := $(KBUILD_OUTPUT) +KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \ + && /bin/pwd) +$(if $(KBUILD_OUTPUT),, \ + $(error failed to create output directory "$(saved-output)")) + +PHONY += $(MAKECMDGOALS) sub-make + +$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make + @: + +sub-make: FORCE + $(Q)$(MAKE) -C $(KBUILD_OUTPUT) KBUILD_SRC=$(CURDIR) \ + -f $(CURDIR)/Makefile $(filter-out _all sub-make,$(MAKECMDGOALS)) + +# Leave processing to above invocation of make +skip-makefile := 1 +endif # ifneq ($(KBUILD_OUTPUT),) +endif # ifeq ($(KBUILD_SRC),) + +# We process the rest of the Makefile if this is the final invocation of make +ifeq ($(skip-makefile),) + +# Do not print "Entering directory ...", +# but we want to display it when entering to the output directory +# so that IDEs/editors are able to understand relative filenames. +MAKEFLAGS += --no-print-directory + +# Call a source code checker (by default, "sparse") as part of the +# C compilation. +# +# Use 'make C=1' to enable checking of only re-compiled files. +# Use 'make C=2' to enable checking of *all* source files, regardless +# of whether they are re-compiled or not. +# +# See the file "Documentation/sparse.txt" for more details, including +# where to get the "sparse" utility. + +ifeq ("$(origin C)", "command line") + KBUILD_CHECKSRC = $(C) +endif +ifndef KBUILD_CHECKSRC + KBUILD_CHECKSRC = 0 +endif + +# Use make M=dir to specify directory of external module to build +# Old syntax make ... SUBDIRS=$PWD is still supported +# Setting the environment variable KBUILD_EXTMOD take precedence +ifdef SUBDIRS + KBUILD_EXTMOD ?= $(SUBDIRS) +endif + +ifeq ("$(origin M)", "command line") + KBUILD_EXTMOD := $(M) +endif + +# If building an external module we do not care about the all: rule +# but instead _all depend on modules +PHONY += all +ifeq ($(KBUILD_EXTMOD),) +_all: all +else +_all: modules +endif + +ifeq ($(KBUILD_SRC),) + # building in the source tree + srctree := . +else + ifeq ($(KBUILD_SRC)/,$(dir $(CURDIR))) + # building in a subdirectory of the source tree + srctree := .. + else + srctree := $(KBUILD_SRC) + endif +endif +objtree := . +src := $(srctree) +obj := $(objtree) + +VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD)) + +buildsrc := $(abspath $(srctree)) +buildtree := $(abspath $(CURDIR)/$(KBUILD_OUTPUT)) + +export srctree objtree VPATH buildsrc buildtree + +# Make sure CDPATH settings don't interfere +unexport CDPATH + +######################################################################### + +HOSTARCH := $(shell uname -m | \ + sed -e s/i.86/x86/ \ + -e s/sun4u/sparc64/ \ + -e s/arm.*/arm/ \ + -e s/sa110/arm/ \ + -e s/ppc64/powerpc/ \ + -e s/ppc/powerpc/ \ + -e s/macppc/powerpc/\ + -e s/sh.*/sh/) + +HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \ + sed -e 's/\(cygwin\).*/cygwin/') + +export HOSTARCH HOSTOS + +######################################################################### + +# set default to nothing for native builds +ifeq ($(HOSTARCH),$(ARCH)) +CROSS_COMPILE ?= +endif + +KCONFIG_CONFIG ?= .config +export KCONFIG_CONFIG + +# SHELL used by kbuild +CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ + else if [ -x /bin/bash ]; then echo /bin/bash; \ + else echo sh; fi ; fi) + +HOSTCC = cc +HOSTCXX = c++ +HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer \ + $(if $(CONFIG_TOOLS_DEBUG),-g) +HOSTCXXFLAGS = -O2 + +# With the move to GCC 6, we have implicitly upgraded our language +# standard to GNU11 (see https://gcc.gnu.org/gcc-5/porting_to.html). +# Some Linux distributions (including RHEL7, SLES13, Debian 8) still +# have older compilers as their default, so we make it explicit for +# these that our host tools are GNU11 (i.e. C11 w/ GNU extensions). +CSTD_FLAG := -std=gnu11 +ifeq ($(HOSTOS),linux) +HOSTCFLAGS += $(CSTD_FLAG) +endif + +ifeq ($(HOSTOS),cygwin) +HOSTCFLAGS += -ansi +endif + +# Mac OS X / Darwin's C preprocessor is Apple specific. It +# generates numerous errors and warnings. We want to bypass it +# and use GNU C's cpp. To do this we pass the -traditional-cpp +# option to the compiler. Note that the -traditional-cpp flag +# DOES NOT have the same semantics as GNU C's flag, all it does +# is invoke the GNU preprocessor in stock ANSI/ISO C fashion. +# +# Apple's linker is similar, thanks to the new 2 stage linking +# multiple symbol definitions are treated as errors, hence the +# -multiply_defined suppress option to turn off this error. +# +ifeq ($(HOSTOS),darwin) +# get major and minor product version (e.g. '10' and '6' for Snow Leopard) +DARWIN_MAJOR_VERSION = $(shell sw_vers -productVersion | cut -f 1 -d '.') +DARWIN_MINOR_VERSION = $(shell sw_vers -productVersion | cut -f 2 -d '.') + +os_x_before = $(shell if [ $(DARWIN_MAJOR_VERSION) -le $(1) -a \ + $(DARWIN_MINOR_VERSION) -le $(2) ] ; then echo "$(3)"; else echo "$(4)"; fi ;) + +# Snow Leopards build environment has no longer restrictions as described above +HOSTCC = $(call os_x_before, 10, 5, "cc", "gcc") +HOSTCFLAGS += $(call os_x_before, 10, 4, "-traditional-cpp") +HOSTLDFLAGS += $(call os_x_before, 10, 5, "-multiply_defined suppress") + +# since Lion (10.7) ASLR is on by default, but we use linker generated lists +# in some host tools which is a problem then ... so disable ASLR for these +# tools +HOSTLDFLAGS += $(call os_x_before, 10, 7, "", "-Xlinker -no_pie") +endif + +# Decide whether to build built-in, modular, or both. +# Normally, just do built-in. + +KBUILD_MODULES := +KBUILD_BUILTIN := 1 + +# If we have only "make modules", don't compile built-in objects. +# When we're building modules with modversions, we need to consider +# the built-in objects during the descend as well, in order to +# make sure the checksums are up to date before we record them. + +ifeq ($(MAKECMDGOALS),modules) + KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1) +endif + +# If we have "make <whatever> modules", compile modules +# in addition to whatever we do anyway. +# Just "make" or "make all" shall build modules as well + +# U-Boot does not need modules +#ifneq ($(filter all _all modules,$(MAKECMDGOALS)),) +# KBUILD_MODULES := 1 +#endif + +#ifeq ($(MAKECMDGOALS),) +# KBUILD_MODULES := 1 +#endif + +export KBUILD_MODULES KBUILD_BUILTIN +export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD +export BL33_DEBUG + +# We need some generic definitions (do not try to remake the file). +scripts/Kbuild.include: ; +include scripts/Kbuild.include + +# Make variables (CC, etc...) + +AS = $(CROSS_COMPILE)as +# Always use GNU ld +ifneq ($(shell $(CROSS_COMPILE)ld.bfd -v 2> /dev/null),) +LD = $(CROSS_COMPILE)ld.bfd +else +LD = $(CROSS_COMPILE)ld +endif +CC = $(CROSS_COMPILE)gcc +CPP = $(CC) -E +AR = $(CROSS_COMPILE)ar +NM = $(CROSS_COMPILE)nm +LDR = $(CROSS_COMPILE)ldr +STRIP = $(CROSS_COMPILE)strip +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +LEX = flex +YACC = bison +AWK = awk +PERL = perl +PYTHON ?= python +PYTHON2 = python2 +PYTHON3 = python3 +DTC ?= $(objtree)/scripts/dtc/dtc +CHECK = sparse + +CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ + -Wbitwise -Wno-return-void -D__CHECK_ENDIAN__ $(CF) + +KBUILD_CPPFLAGS := -D__KERNEL__ -D__UBOOT__ + +KBUILD_CFLAGS := -Wall -Wstrict-prototypes \ + -Wno-format-security \ + -fno-builtin -ffreestanding $(CSTD_FLAG) +KBUILD_CFLAGS += -fshort-wchar -fno-strict-aliasing +KBUILD_AFLAGS := -D__ASSEMBLY__ +ifeq ($(BL33_DEBUG), 1) + KBUILD_CFLAGS+=-DBL33_DEBUG_PRINT +endif + +# Don't generate position independent code +KBUILD_CFLAGS += $(call cc-option,-fno-PIE) +KBUILD_AFLAGS += $(call cc-option,-fno-PIE) + +# Read UBOOTRELEASE from include/config/uboot.release (if it exists) +UBOOTRELEASE = $(shell cat include/config/uboot.release 2> /dev/null) +UBOOTVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) + +export VERSION PATCHLEVEL SUBLEVEL UBOOTRELEASE UBOOTVERSION +export ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR +export CONFIG_SHELL HOSTCC HOSTCFLAGS HOSTLDFLAGS CROSS_COMPILE AS LD CC +export CPP AR NM LDR STRIP OBJCOPY OBJDUMP +export MAKE LEX YACC AWK PERL PYTHON PYTHON2 PYTHON3 +export HOSTCXX HOSTCXXFLAGS CHECK CHECKFLAGS DTC DTC_FLAGS + +export KBUILD_CPPFLAGS NOSTDINC_FLAGS UBOOTINCLUDE OBJCOPYFLAGS LDFLAGS +export KBUILD_CFLAGS KBUILD_AFLAGS + +# When compiling out-of-tree modules, put MODVERDIR in the module +# tree rather than in the kernel tree. The kernel tree might +# even be read-only. +export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions + +# Files to ignore in find ... statements + +export RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o \ + -name CVS -o -name .pc -o -name .hg -o -name .git \) \ + -prune -o +export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \ + --exclude CVS --exclude .pc --exclude .hg --exclude .git + +# =========================================================================== +# Rules shared between *config targets and build targets + +# Basic helpers built in scripts/ +PHONY += scripts_basic +scripts_basic: + $(Q)$(MAKE) $(build)=scripts/basic + $(Q)rm -f .tmp_quiet_recordmcount + +# To avoid any implicit rule to kick in, define an empty command. +scripts/basic/%: scripts_basic ; + +PHONY += outputmakefile +# outputmakefile generates a Makefile in the output directory, if using a +# separate output directory. This allows convenient use of make in the +# output directory. +outputmakefile: +ifneq ($(KBUILD_SRC),) + $(Q)ln -fsn $(srctree) source + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \ + $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) +endif + +# To make sure we do not include .config for any of the *config targets +# catch them early, and hand them over to scripts/kconfig/Makefile +# It is allowed to specify more targets when calling make, including +# mixing *config targets and build targets. +# For example 'make oldconfig all'. +# Detect when mixed targets is specified, and make a second invocation +# of make so .config is not included in this case either (for *config). + +version_h := include/generated/version_autogenerated.h +timestamp_h := include/generated/timestamp_autogenerated.h +defaultenv_h := include/generated/defaultenv_autogenerated.h +timestamp_git_h := include/generated/timestamp_autogenerated.h + +no-dot-config-targets := clean clobber mrproper distclean \ + help %docs check% coccicheck \ + ubootversion backup tests check qcheck + +config-targets := 0 +mixed-targets := 0 +dot-config := 1 + +ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) + ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) + dot-config := 0 + endif +endif + +ifeq ($(KBUILD_EXTMOD),) + ifneq ($(filter config %config,$(MAKECMDGOALS)),) + config-targets := 1 + ifneq ($(words $(MAKECMDGOALS)),1) + mixed-targets := 1 + endif + endif +endif + +ifneq ($(ENABLE_UBOOT_UPDATE),1) + KBUILD_CFLAGS += -DAML_DISABLE_UPDATE_MODE +endif + +ifeq ($(mixed-targets),1) +# =========================================================================== +# We're called with mixed targets (*config and build targets). +# Handle them one by one. + +PHONY += $(MAKECMDGOALS) __build_one_by_one + +$(filter-out __build_one_by_one, $(MAKECMDGOALS)): __build_one_by_one + @: + +__build_one_by_one: + $(Q)set -e; \ + for i in $(MAKECMDGOALS); do \ + $(MAKE) -f $(srctree)/Makefile $$i; \ + done + +else +ifeq ($(config-targets),1) +# =========================================================================== +# *config targets only - make sure prerequisites are updated, and descend +# in scripts/kconfig to make the *config target + +KBUILD_DEFCONFIG := sandbox_defconfig +export KBUILD_DEFCONFIG KBUILD_KCONFIG + +config: scripts_basic outputmakefile FORCE + $(Q)$(MAKE) $(build)=scripts/kconfig $@ + +%config: scripts_basic outputmakefile FORCE + $(Q)$(MAKE) $(build)=scripts/kconfig $@ + +else +# =========================================================================== +# Build targets only - this includes vmlinux, arch specific targets, clean +# targets and others. In general all targets except *config targets. + +# Additional helpers built in scripts/ +# Carefully list dependencies so we do not try to build scripts twice +# in parallel +PHONY += scripts +scripts: scripts_basic include/config/auto.conf + $(Q)$(MAKE) $(build)=$(@) + +ifeq ($(dot-config),1) +# Read in config +-include include/config/auto.conf + +# Read in dependencies to all Kconfig* files, make sure to run +# oldconfig if changes are detected. +-include include/config/auto.conf.cmd + +# To avoid any implicit rule to kick in, define an empty command +$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ; + +# If .config is newer than include/config/auto.conf, someone tinkered +# with it and forgot to run make oldconfig. +# if auto.conf.cmd is missing then we are probably in a cleaned tree so +# we execute the config step to be sure to catch updated Kconfig files +include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd + $(Q)$(MAKE) -f $(srctree)/Makefile syncconfig + @# If the following part fails, include/config/auto.conf should be + @# deleted so "make silentoldconfig" will be re-run on the next build. + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf || \ + { rm -f include/config/auto.conf; false; } + @# include/config.h has been updated after "make silentoldconfig". + @# We need to touch include/config/auto.conf so it gets newer + @# than include/config.h. + @# Otherwise, 'make silentoldconfig' would be invoked twice. + $(Q)touch include/config/auto.conf + +u-boot.cfg spl/u-boot.cfg tpl/u-boot.cfg: include/config.h FORCE + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf $(@) + +-include include/autoconf.mk +-include include/autoconf.mk.dep + +# We want to include arch/$(ARCH)/config.mk only when include/config/auto.conf +# is up-to-date. When we switch to a different board configuration, old CONFIG +# macros are still remaining in include/config/auto.conf. Without the following +# gimmick, wrong config.mk would be included leading nasty warnings/errors. +ifneq ($(wildcard $(KCONFIG_CONFIG)),) +ifneq ($(wildcard include/config/auto.conf),) +autoconf_is_old := $(shell find . -path ./$(KCONFIG_CONFIG) -newer \ + include/config/auto.conf) +ifeq ($(autoconf_is_old),) +include config.mk +include arch/$(ARCH)/Makefile +endif +endif +endif + +# These are set by the arch-specific config.mk. Make sure they are exported +# so they can be used when building an EFI application. +export EFI_LDS # Filename of EFI link script in arch/$(ARCH)/lib +export EFI_CRT0 # Filename of EFI CRT0 in arch/$(ARCH)/lib +export EFI_RELOC # Filename of EFU relocation code in arch/$(ARCH)/lib +export CFLAGS_EFI # Compiler flags to add when building EFI app +export CFLAGS_NON_EFI # Compiler flags to remove when building EFI app +export EFI_TARGET # binutils target if EFI is natively supported + +# If board code explicitly specified LDSCRIPT or CONFIG_SYS_LDSCRIPT, use +# that (or fail if absent). Otherwise, search for a linker script in a +# standard location. + +ifndef LDSCRIPT + #LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot.lds.debug + ifdef CONFIG_SYS_LDSCRIPT + # need to strip off double quotes + LDSCRIPT := $(srctree)/$(CONFIG_SYS_LDSCRIPT:"%"=%) + endif +endif + +# If there is no specified link script, we look in a number of places for it +ifndef LDSCRIPT + ifeq ($(wildcard $(LDSCRIPT)),) + LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot.lds + endif + ifeq ($(wildcard $(LDSCRIPT)),) + LDSCRIPT := $(srctree)/$(CPUDIR)/u-boot.lds + endif + ifeq ($(wildcard $(LDSCRIPT)),) + LDSCRIPT := $(srctree)/arch/$(ARCH)/cpu/u-boot.lds + endif +endif + +else +# Dummy target needed, because used as prerequisite +include/config/auto.conf: ; +endif # $(dot-config) + +# +# Xtensa linker script cannot be preprocessed with -ansi because of +# preprocessor operations on strings that don't make C identifiers. +# +ifeq ($(CONFIG_XTENSA),) +LDPPFLAGS += -ansi +endif + +ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE +KBUILD_CFLAGS += -Os +else +KBUILD_CFLAGS += -O2 +endif + +KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector) +KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks) + +# change __FILE__ to the relative path from the srctree +KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=) + +KBUILD_CFLAGS += -g +# $(KBUILD_AFLAGS) sets -g, which causes gcc to pass a suitable -g<format> +# option to the assembler. +KBUILD_AFLAGS += -g + +# Report stack usage if supported +# ARC tools based on GCC 7.1 has an issue with stack usage +# with naked functions, see commit message for more details +ifndef CONFIG_ARC +ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-stack-usage.sh $(CC)),y) + KBUILD_CFLAGS += -fstack-usage +endif +endif + +KBUILD_CFLAGS += $(call cc-option,-Wno-format-nonliteral) +ifeq ($(cc-name),clang) +KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,) +KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier) +KBUILD_CFLAGS += $(call cc-disable-warning, gnu) +KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) +KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior) +endif + +# turn jbsr into jsr for m68k +ifeq ($(ARCH),m68k) +ifeq ($(findstring 3.4,$(shell $(CC) --version)),3.4) +KBUILD_AFLAGS += -Wa,-gstabs,-S +endif +endif + +# Prohibit date/time macros, which would make the build non-deterministic +KBUILD_CFLAGS += $(call cc-option,-Werror=date-time) + +include scripts/Makefile.extrawarn + +# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments +KBUILD_CPPFLAGS += $(KCPPFLAGS) +KBUILD_AFLAGS += $(KAFLAGS) +KBUILD_CFLAGS += $(KCFLAGS) + +ifdef BOARD_NAME +KBUILD_CFLAGS += -DBOARD_NAME='"$(BOARD_NAME)"' +endif + +# Use UBOOTINCLUDE when you must reference the include/ directory. +# Needed to be compatible with the O= option +UBOOTINCLUDE := \ + -Iinclude \ + $(if $(KBUILD_SRC), -I$(srctree)/include) \ + $(if $(CONFIG_$(SPL_)SYS_THUMB_BUILD), \ + $(if $(CONFIG_HAS_THUMB2),, \ + -I$(srctree)/arch/$(ARCH)/thumb1/include),) \ + -I$(srctree)/arch/$(ARCH)/include \ + -include $(srctree)/include/linux/kconfig.h + +NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) +CHECKFLAGS += $(NOSTDINC_FLAGS) + +# FIX ME +cpp_flags := $(KBUILD_CPPFLAGS) $(PLATFORM_CPPFLAGS) $(UBOOTINCLUDE) \ + $(NOSTDINC_FLAGS) +c_flags := $(KBUILD_CFLAGS) $(cpp_flags) + +######################################################################### +# U-Boot objects....order is important (i.e. start must be first) + +HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(srctree)/board/$(VENDOR)/common/Makefile),y,n) + +libs-y += lib/ +libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/ +libs-$(CONFIG_OF_EMBED) += dts/ +libs-y += fs/ +libs-y += net/ +libs-y += disk/ +libs-y += drivers/ +libs-y += drivers/dma/ +libs-y += drivers/gpio/ +libs-y += drivers/i2c/ +libs-y += drivers/mtd/ +libs-$(CONFIG_CMD_NAND) += drivers/mtd/nand/raw/ +libs-y += drivers/mtd/onenand/ +libs-$(CONFIG_CMD_UBI) += drivers/mtd/ubi/ +libs-y += drivers/mtd/spi/ +libs-y += drivers/net/ +libs-y += drivers/net/phy/ +libs-y += drivers/power/ \ + drivers/power/domain/ \ + drivers/power/fuel_gauge/ \ + drivers/power/mfd/ \ + drivers/power/pmic/ \ + drivers/power/battery/ \ + drivers/power/regulator/ +libs-y += drivers/spi/ +libs-$(CONFIG_FMAN_ENET) += drivers/net/fm/ +libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/ +libs-$(CONFIG_SYS_FSL_MMDC) += drivers/ddr/fsl/ +libs-$(CONFIG_ALTERA_SDRAM) += drivers/ddr/altera/ +libs-y += drivers/serial/ +libs-y += drivers/usb/dwc3/ +libs-y += drivers/usb/common/ +libs-y += drivers/usb/emul/ +libs-y += drivers/usb/eth/ +libs-$(CONFIG_USB_GADGET) += drivers/usb/gadget/ +libs-$(CONFIG_USB_GADGET) += drivers/usb/gadget/udc/ +libs-y += drivers/usb/host/ +libs-y += drivers/usb/musb/ +libs-y += drivers/usb/musb-new/ +libs-y += drivers/usb/phy/ +libs-y += drivers/usb/ulpi/ +libs-y += cmd/ +libs-y += common/ +libs-y += env/ +libs-$(CONFIG_API) += api/ +libs-$(CONFIG_HAS_POST) += post/ +libs-$(CONFIG_UNIT_TEST) += test/ test/dm/ +libs-$(CONFIG_UT_ENV) += test/env/ +libs-$(CONFIG_UT_OVERLAY) += test/overlay/ + +libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/) + +libs-y := $(sort $(libs-y)) + +u-boot-dirs := $(patsubst %/,%,$(filter %/, $(libs-y))) tools examples + +u-boot-alldirs := $(sort $(u-boot-dirs) $(patsubst %/,%,$(filter %/, $(libs-)))) + +libs-y := $(patsubst %/, %/built-in.o, $(libs-y)) + +u-boot-init := $(head-y) +u-boot-main := $(libs-y) + + +# Add GCC lib +ifeq ($(CONFIG_USE_PRIVATE_LIBGCC),y) +PLATFORM_LIBGCC = arch/$(ARCH)/lib/lib.a +else +PLATFORM_LIBGCC := -L $(shell dirname `$(CC) $(c_flags) -print-libgcc-file-name`) -lgcc +endif +PLATFORM_LIBS += $(PLATFORM_LIBGCC) + +ifdef CONFIG_CC_COVERAGE +KBUILD_CFLAGS += --coverage +PLATFORM_LIBGCC += -lgcov +endif + +export PLATFORM_LIBS +export PLATFORM_LIBGCC + +# Special flags for CPP when processing the linker script. +# Pass the version down so we can handle backwards compatibility +# on the fly. +LDPPFLAGS += \ + -include $(srctree)/include/u-boot/u-boot.lds.h \ + -DCPUDIR=$(CPUDIR) \ + $(shell $(LD) --version | \ + sed -ne 's/GNU ld version \([0-9][0-9]*\)\.\([0-9][0-9]*\).*/-DLD_MAJOR=\1 -DLD_MINOR=\2/p') + +######################################################################### +######################################################################### + +ifneq ($(CONFIG_BOARD_SIZE_LIMIT),) +BOARD_SIZE_CHECK = \ + @actual=`wc -c $@ | awk '{print $$1}'`; \ + limit=`printf "%d" $(CONFIG_BOARD_SIZE_LIMIT)`; \ + if test $$actual -gt $$limit; then \ + echo "$@ exceeds file size limit:" >&2 ; \ + echo " limit: $$limit bytes" >&2 ; \ + echo " actual: $$actual bytes" >&2 ; \ + echo " excess: $$((actual - limit)) bytes" >&2; \ + exit 1; \ + fi +else +BOARD_SIZE_CHECK = +endif + +# Statically apply RELA-style relocations (currently arm64 only) +# This is useful for arm64 where static relocation needs to be performed on +# the raw binary, but certain simulators only accept an ELF file (but don't +# do the relocation). +ifneq ($(CONFIG_STATIC_RELA),) +# $(1) is u-boot ELF, $(2) is u-boot bin, $(3) is text base +DO_STATIC_RELA = \ + start=$$($(NM) $(1) | grep __rel_dyn_start | cut -f 1 -d ' '); \ + end=$$($(NM) $(1) | grep __rel_dyn_end | cut -f 1 -d ' '); \ + tools/relocate-rela $(2) $(3) $$start $$end +else +DO_STATIC_RELA = +endif + +# Always append ALL so that arch config.mk's can add custom ones +ALL-y += u-boot.srec u-boot.bin u-boot.sym System.map binary_size_check +ALL-y += bl301.bin + +ALL-$(CONFIG_ONENAND_U_BOOT) += u-boot-onenand.bin +ifeq ($(CONFIG_SPL_FSL_PBL),y) +ALL-$(CONFIG_RAMBOOT_PBL) += u-boot-with-spl-pbl.bin +else +ifneq ($(CONFIG_SECURE_BOOT), y) +# For Secure Boot The Image needs to be signed and Header must also +# be included. So The image has to be built explicitly +ALL-$(CONFIG_RAMBOOT_PBL) += u-boot.pbl +endif +endif +ALL-$(CONFIG_SPL) += spl/u-boot-spl.bin +ifeq ($(CONFIG_MX6)$(CONFIG_SECURE_BOOT), yy) +ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot-ivt.img +else +ifeq ($(CONFIG_MX7)$(CONFIG_SECURE_BOOT), yy) +ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot-ivt.img +else +ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot.img +endif +endif +ALL-$(CONFIG_TPL) += tpl/u-boot-tpl.bin +ALL-$(CONFIG_OF_SEPARATE) += u-boot.dtb +ifeq ($(CONFIG_SPL_FRAMEWORK),y) +ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb.img +endif +ALL-$(CONFIG_OF_HOSTFILE) += u-boot.dtb +ifneq ($(CONFIG_SPL_TARGET),) +ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%) +endif +ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf +ALL-$(CONFIG_EFI_APP) += u-boot-app.efi +ALL-$(CONFIG_EFI_STUB) += u-boot-payload.efi + +ifneq ($(BUILD_ROM)$(CONFIG_BUILD_ROM),) +ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom +endif + +# Build a combined spl + u-boot image for sunxi +ifeq ($(CONFIG_ARCH_SUNXI)$(CONFIG_SPL),yy) +ALL-y += u-boot-sunxi-with-spl.bin +endif + +# enable combined SPL/u-boot/dtb rules for tegra +ifeq ($(CONFIG_TEGRA)$(CONFIG_SPL),yy) +ALL-y += u-boot-tegra.bin u-boot-nodtb-tegra.bin +ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb-tegra.bin +endif + +ALL-$(CONFIG_ARCH_MEDIATEK) += u-boot-mtk.bin + +# Add optional build target if defined in board/cpu/soc headers +ifneq ($(CONFIG_BUILD_TARGET),) +ALL-y += $(CONFIG_BUILD_TARGET:"%"=%) +endif + +ifneq ($(CONFIG_SYS_INIT_SP_BSS_OFFSET),) +ALL-y += init_sp_bss_offset_check +endif + +ifeq ($(CONFIG_MPC85xx)$(CONFIG_OF_SEPARATE),yy) +ALL-y += u-boot-with-dtb.bin +endif + +LDFLAGS_u-boot += $(LDFLAGS_FINAL) + +# Avoid 'Not enough room for program headers' error on binutils 2.28 onwards. +LDFLAGS_u-boot += $(call ld-option, --no-dynamic-linker) + +ifeq ($(CONFIG_ARC)$(CONFIG_NIOS2)$(CONFIG_X86)$(CONFIG_XTENSA),) +LDFLAGS_u-boot += -Ttext $(CONFIG_SYS_TEXT_BASE) +endif + +# Normally we fill empty space with 0xff +quiet_cmd_objcopy = OBJCOPY $@ +cmd_objcopy = $(OBJCOPY) --gap-fill=0xff $(OBJCOPYFLAGS) \ + $(OBJCOPYFLAGS_$(@F)) $< $@ + +# Provide a version which does not do this, for use by EFI +quiet_cmd_zobjcopy = OBJCOPY $@ +cmd_zobjcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@ + +quiet_cmd_efipayload = OBJCOPY $@ +cmd_efipayload = $(OBJCOPY) -I binary -O $(EFIPAYLOAD_BFDTARGET) -B $(EFIPAYLOAD_BFDARCH) $< $@ + +MKIMAGEOUTPUT ?= /dev/null + +quiet_cmd_mkimage = MKIMAGE $@ +cmd_mkimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -d $< $@ \ + >$(MKIMAGEOUTPUT) $(if $(KBUILD_VERBOSE:0=), && cat $(MKIMAGEOUTPUT)) + +quiet_cmd_mkfitimage = MKIMAGE $@ +cmd_mkfitimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -f $(U_BOOT_ITS) -E $@ -p $(CONFIG_FIT_EXTERNAL_OFFSET)\ + >$(MKIMAGEOUTPUT) $(if $(KBUILD_VERBOSE:0=), && cat $(MKIMAGEOUTPUT)) + +quiet_cmd_cat = CAT $@ +cmd_cat = cat $(filter-out $(PHONY), $^) > $@ + +append = cat $(filter-out $< $(PHONY), $^) >> $@ + +quiet_cmd_pad_cat = CAT $@ +cmd_pad_cat = $(cmd_objcopy) && $(append) || rm -f $@ + +cfg: u-boot.cfg + +quiet_cmd_cfgcheck = CFGCHK $2 +cmd_cfgcheck = $(srctree)/scripts/check-config.sh $2 \ + $(srctree)/scripts/config_whitelist.txt $(srctree) + +all: $(ALL-y) cfg +ifeq ($(CONFIG_DM_I2C_COMPAT)$(CONFIG_SANDBOX),y) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board uses CONFIG_DM_I2C_COMPAT. Please remove" + @echo >&2 "(possibly in a subsequent patch in your series)" + @echo >&2 "before sending patches to the mailing list." + @echo >&2 "====================================================" +endif +ifeq ($(CONFIG_MMC),y) +ifneq ($(CONFIG_DM_MMC)$(CONFIG_OF_CONTROL)$(CONFIG_BLK),yyy) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board does not use CONFIG_DM_MMC. Please update" + @echo >&2 "the board to use CONFIG_DM_MMC before the v2019.04 release." + @echo >&2 "Failure to update by the deadline may result in board removal." + @echo >&2 "See doc/driver-model/MIGRATION.txt for more info." + @echo >&2 "====================================================" +endif +endif +ifeq ($(CONFIG_USB),y) +ifneq ($(CONFIG_DM_USB)$(CONFIG_OF_CONTROL)$(CONFIG_BLK),yyy) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board does not use CONFIG_DM_USB. Please update" + @echo >&2 "the board to use CONFIG_DM_USB before the v2019.07 release." + @echo >&2 "Failure to update by the deadline may result in board removal." + @echo >&2 "See doc/driver-model/MIGRATION.txt for more info." + @echo >&2 "====================================================" +endif +endif +ifeq ($(CONFIG_LIBATA)$(CONFIG_MVSATA_IDE),y) +ifneq ($(CONFIG_DM_SCSI),y) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board does not use CONFIG_DM_SCSI. Please update" + @echo >&2 "the storage controller to use CONFIG_DM_SCSI before the v2019.07 release." + @echo >&2 "Failure to update by the deadline may result in board removal." + @echo >&2 "See doc/driver-model/MIGRATION.txt for more info." + @echo >&2 "====================================================" +endif +endif +ifeq ($(CONFIG_PCI),y) +ifneq ($(CONFIG_DM_PCI),y) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board does not use CONFIG_DM_PCI Please update" + @echo >&2 "the board to use CONFIG_DM_PCI before the v2019.07 release." + @echo >&2 "Failure to update by the deadline may result in board removal." + @echo >&2 "See doc/driver-model/MIGRATION.txt for more info." + @echo >&2 "====================================================" +endif +endif +ifneq ($(CONFIG_LCD)$(CONFIG_VIDEO),) +ifneq ($(CONFIG_DM_VIDEO),y) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board does not use CONFIG_DM_VIDEO Please update" + @echo >&2 "the board to use CONFIG_DM_VIDEO before the v2019.07 release." + @echo >&2 "Failure to update by the deadline may result in board removal." + @echo >&2 "See doc/driver-model/MIGRATION.txt for more info." + @echo >&2 "====================================================" +endif +endif +ifeq ($(CONFIG_OF_EMBED),y) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "CONFIG_OF_EMBED is enabled. This option should only" + @echo >&2 "be used for debugging purposes. Please use" + @echo >&2 "CONFIG_OF_SEPARATE for boards in mainline." + @echo >&2 "See doc/README.fdt-control for more info." + @echo >&2 "====================================================" +endif +ifeq ($(CONFIG_SPI),y) +ifneq ($(CONFIG_DM_SPI)$(CONFIG_OF_CONTROL),yy) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board does not use CONFIG_DM_SPI. Please update" + @echo >&2 "the board before v2019.04 for no dm conversion" + @echo >&2 "and v2019.07 for partially dm converted drivers." + @echo >&2 "Failure to update can lead to driver/board removal" + @echo >&2 "See doc/driver-model/MIGRATION.txt for more info." + @echo >&2 "====================================================" +endif +endif +ifeq ($(CONFIG_SPI_FLASH),y) +ifneq ($(CONFIG_DM_SPI_FLASH)$(CONFIG_OF_CONTROL),yy) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board does not use CONFIG_DM_SPI_FLASH. Please update" + @echo >&2 "the board to use CONFIG_SPI_FLASH before the v2019.07 release." + @echo >&2 "Failure to update by the deadline may result in board removal." + @echo >&2 "See doc/driver-model/MIGRATION.txt for more info." + @echo >&2 "====================================================" +endif +endif + @# Check that this build does not use CONFIG options that we do not + @# know about unless they are in Kconfig. All the existing CONFIG + @# options are whitelisted, so new ones should not be added. + $(call cmd,cfgcheck,u-boot.cfg) + +PHONY += dtbs +dtbs: dts/dt.dtb + @: +dts/dt.dtb: u-boot + $(Q)$(MAKE) $(build)=dts dtbs + +quiet_cmd_copy = COPY $@ + cmd_copy = cp $< $@ + +ifeq ($(CONFIG_MULTI_DTB_FIT),y) + +fit-dtb.blob: dts/dt.dtb FORCE + $(call if_changed,mkimage) + +MKIMAGEFLAGS_fit-dtb.blob = -f auto -A $(ARCH) -T firmware -C none -O u-boot \ + -a 0 -e 0 -E \ + $(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) -d /dev/null + +u-boot-fit-dtb.bin: u-boot-nodtb.bin fit-dtb.blob + $(call if_changed,cat) + +u-boot.bin: u-boot-fit-dtb.bin FORCE + $(call if_changed,copy) +else ifeq ($(CONFIG_OF_SEPARATE),y) +u-boot-dtb.bin: u-boot-nodtb.bin dts/dt.dtb FORCE + $(call if_changed,cat) + +u-boot.bin: u-boot-dtb.bin FORCE + $(call if_changed,copy) +else +u-boot.bin: u-boot-nodtb.bin FORCE + $(call if_changed,copy) +endif + +.PHONY : bl301.bin +bl301.bin: tools prepare acs.bin bl21.bin + $(Q)$(MAKE) -C $(srctree)/arch/arm/mach-meson/${SOC}/firmware/scp_task + +.PHONY : acs.bin +acs.bin: tools prepare u-boot.bin + $(Q)$(MAKE) -C $(srctree)/arch/arm/mach-meson/${SOC}/firmware/acs all FIRMWARE=$@ + +.PHONY : bl21.bin +bl21.bin: tools prepare u-boot.bin acs.bin + $(Q)$(MAKE) -C $(srctree)/arch/arm/mach-meson/${SOC}/firmware/bl21 all FIRMWARE=$@ + +%.imx: %.bin + $(Q)$(MAKE) $(build)=arch/arm/mach-imx $@ + +%.vyb: %.imx + $(Q)$(MAKE) $(build)=arch/arm/cpu/armv7/vf610 $@ + +quiet_cmd_copy = COPY $@ + cmd_copy = cp $< $@ + +u-boot.dtb: dts/dt.dtb + $(call cmd,copy) + +OBJCOPYFLAGS_u-boot.hex := -O ihex + +OBJCOPYFLAGS_u-boot.srec := -O srec + +u-boot.hex u-boot.srec: u-boot FORCE + $(call if_changed,objcopy) + +OBJCOPYFLAGS_u-boot-elf.srec := $(OBJCOPYFLAGS_u-boot.srec) + +u-boot-elf.srec: u-boot.elf FORCE + $(call if_changed,objcopy) + +OBJCOPYFLAGS_u-boot-spl.srec = $(OBJCOPYFLAGS_u-boot.srec) + +spl/u-boot-spl.srec: spl/u-boot-spl FORCE + $(call if_changed,objcopy) + +OBJCOPYFLAGS_u-boot-nodtb.bin := -O binary \ + $(if $(CONFIG_X86_16BIT_INIT),-R .start16 -R .resetvec) \ + $(if $(CONFIG_MPC85XX_HAVE_RESET_VECTOR),-R .bootpg -R .resetvec) + +OBJCOPYFLAGS_u-boot-spl.hex = $(OBJCOPYFLAGS_u-boot.hex) + +spl/u-boot-spl.hex: spl/u-boot-spl FORCE + $(call if_changed,objcopy) + +binary_size_check: u-boot-nodtb.bin FORCE + @file_size=$(shell wc -c u-boot-nodtb.bin | awk '{print $$1}') ; \ + map_size=$(shell cat u-boot.map | \ + awk '/_image_copy_start/ {start = $$1} /_image_binary_end/ {end = $$1} END {if (start != "" && end != "") print "ibase=16; " toupper(end) " - " toupper(start)}' \ + | sed 's/0X//g' \ + | bc); \ + if [ "" != "$$map_size" ]; then \ + if test $$map_size -ne $$file_size; then \ + echo "u-boot.map shows a binary size of $$map_size" >&2 ; \ + echo " but u-boot-nodtb.bin shows $$file_size" >&2 ; \ + exit 1; \ + fi \ + fi + +ifneq ($(CONFIG_SYS_INIT_SP_BSS_OFFSET),) +ifneq ($(CONFIG_SYS_MALLOC_F_LEN),) +subtract_sys_malloc_f_len = space=$$(($${space} - $(CONFIG_SYS_MALLOC_F_LEN))) +else +subtract_sys_malloc_f_len = true +endif +# The 1/4 margin below is somewhat arbitrary. The likely initial SP usage is +# so low that the DTB could probably use 90%+ of the available space, for +# current values of CONFIG_SYS_INIT_SP_BSS_OFFSET at least. However, let's be +# safe for now and tweak this later if space becomes tight. +# A rejected alternative would be to check that some absolute minimum stack +# space was available. However, since CONFIG_SYS_INIT_SP_BSS_OFFSET is +# deliberately build-specific, to take account of build-to-build stack usage +# differences due to different feature sets, there is no common absolute value +# to check against. +init_sp_bss_offset_check: u-boot.dtb FORCE + @dtb_size=$(shell wc -c u-boot.dtb | awk '{print $$1}') ; \ + space=$(CONFIG_SYS_INIT_SP_BSS_OFFSET) ; \ + $(subtract_sys_malloc_f_len) ; \ + quarter_space=$$(($${space} / 4)) ; \ + if [ $${dtb_size} -gt $${quarter_space} ]; then \ + echo "u-boot.dtb is larger than 1 quarter of " >&2 ; \ + echo "(CONFIG_SYS_INIT_SP_BSS_OFFSET - CONFIG_SYS_MALLOC_F_LEN)" >&2 ; \ + exit 1 ; \ + fi +endif + +u-boot-nodtb.bin: u-boot FORCE + $(call if_changed,objcopy) + $(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE)) + $(BOARD_SIZE_CHECK) + +u-boot.ldr: u-boot + $(CREATE_LDR_ENV) + $(LDR) -T $(CONFIG_CPU) -c $@ $< $(LDR_FLAGS) + $(BOARD_SIZE_CHECK) + +# binman +# --------------------------------------------------------------------------- +# Use 'make BINMAN_DEBUG=1' to enable debugging +quiet_cmd_binman = BINMAN $@ +cmd_binman = $(srctree)/tools/binman/binman -u -d u-boot.dtb -O . -m \ + -I . -I $(srctree) -I $(srctree)/board/$(BOARDDIR) \ + $(if $(BINMAN_DEBUG),-D) $(BINMAN_$(@F)) $< + +OBJCOPYFLAGS_u-boot.ldr.hex := -I binary -O ihex + +OBJCOPYFLAGS_u-boot.ldr.srec := -I binary -O srec + +u-boot.ldr.hex u-boot.ldr.srec: u-boot.ldr FORCE + $(call if_changed,objcopy) + +# +# U-Boot entry point, needed for booting of full-blown U-Boot +# from the SPL U-Boot version. +# +ifndef CONFIG_SYS_UBOOT_START +CONFIG_SYS_UBOOT_START := 0 +endif + +# Boards with more complex image requirments can provide an .its source file +# or a generator script +ifneq ($(CONFIG_SPL_FIT_SOURCE),"") +U_BOOT_ITS = $(subst ",,$(CONFIG_SPL_FIT_SOURCE)) +else +ifneq ($(CONFIG_SPL_FIT_GENERATOR),"") +U_BOOT_ITS := u-boot.its +ifeq ($(CONFIG_SPL_FIT_GENERATOR),"arch/arm/mach-imx/mkimage_fit_atf.sh") +U_BOOT_ITS_DEPS += u-boot-nodtb.bin +endif +ifeq ($(CONFIG_SPL_FIT_GENERATOR),"arch/arm/mach-rockchip/make_fit_atf.py") +U_BOOT_ITS_DEPS += u-boot +endif +$(U_BOOT_ITS): $(U_BOOT_ITS_DEPS) FORCE + $(srctree)/$(CONFIG_SPL_FIT_GENERATOR) \ + $(patsubst %,arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) > $@ +endif +endif + +ifdef CONFIG_SPL_LOAD_FIT +MKIMAGEFLAGS_u-boot.img = -f auto -A $(ARCH) -T firmware -C none -O u-boot \ + -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \ + -n "U-Boot $(UBOOTRELEASE) for $(BOARD) board" -E \ + $(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) +else +MKIMAGEFLAGS_u-boot.img = -A $(ARCH) -T firmware -C none -O u-boot \ + -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \ + -n "U-Boot $(UBOOTRELEASE) for $(BOARD) board" +MKIMAGEFLAGS_u-boot-ivt.img = -A $(ARCH) -T firmware_ivt -C none -O u-boot \ + -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \ + -n "U-Boot $(UBOOTRELEASE) for $(BOARD) board" +u-boot-ivt.img: MKIMAGEOUTPUT = u-boot-ivt.img.log +CLEAN_FILES += u-boot-ivt.img.log u-boot-dtb.imx.log SPL.log u-boot.imx.log +endif + +MKIMAGEFLAGS_u-boot-dtb.img = $(MKIMAGEFLAGS_u-boot.img) + +MKIMAGEFLAGS_u-boot.kwb = -n $(srctree)/$(CONFIG_SYS_KWD_CONFIG:"%"=%) \ + -T kwbimage -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) + +MKIMAGEFLAGS_u-boot-spl.kwb = -n $(srctree)/$(CONFIG_SYS_KWD_CONFIG:"%"=%) \ + -T kwbimage -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) \ + $(if $(KEYDIR),-k $(KEYDIR)) + +MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \ + -R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage + +u-boot-dtb.img u-boot.img u-boot.kwb u-boot.pbl u-boot-ivt.img: \ + $(if $(CONFIG_SPL_LOAD_FIT),u-boot-nodtb.bin dts/dt.dtb,u-boot.bin) FORCE + $(call if_changed,mkimage) + +u-boot.itb: u-boot-nodtb.bin dts/dt.dtb $(U_BOOT_ITS) FORCE + $(call if_changed,mkfitimage) + $(BOARD_SIZE_CHECK) + +u-boot-spl.kwb: u-boot.img spl/u-boot-spl.bin FORCE + $(call if_changed,mkimage) + +u-boot.sha1: u-boot.bin + tools/ubsha1 u-boot.bin + +u-boot.dis: u-boot + $(OBJDUMP) -d $< > $@ + +ifneq ($(CONFIG_SPL_PAYLOAD),) +SPL_PAYLOAD := $(CONFIG_SPL_PAYLOAD:"%"=%) +else +SPL_PAYLOAD := u-boot.bin +endif + +OBJCOPYFLAGS_u-boot-with-spl.bin = -I binary -O binary \ + --pad-to=$(CONFIG_SPL_PAD_TO) +u-boot-with-spl.bin: spl/u-boot-spl.bin $(SPL_PAYLOAD) FORCE + $(call if_changed,pad_cat) + +ifeq ($(CONFIG_ARCH_LPC32XX)$(CONFIG_SPL),yy) +MKIMAGEFLAGS_lpc32xx-spl.img = -T lpc32xximage -a $(CONFIG_SPL_TEXT_BASE) + +lpc32xx-spl.img: spl/u-boot-spl.bin FORCE + $(call if_changed,mkimage) + +OBJCOPYFLAGS_lpc32xx-boot-0.bin = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO) + +lpc32xx-boot-0.bin: lpc32xx-spl.img FORCE + $(call if_changed,objcopy) + +OBJCOPYFLAGS_lpc32xx-boot-1.bin = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO) + +lpc32xx-boot-1.bin: lpc32xx-spl.img FORCE + $(call if_changed,objcopy) + +lpc32xx-full.bin: lpc32xx-boot-0.bin lpc32xx-boot-1.bin u-boot.img FORCE + $(call if_changed,cat) + +CLEAN_FILES += lpc32xx-* +endif + +OBJCOPYFLAGS_u-boot-with-tpl.bin = -I binary -O binary \ + --pad-to=$(CONFIG_TPL_PAD_TO) +tpl/u-boot-with-tpl.bin: tpl/u-boot-tpl.bin u-boot.bin FORCE + $(call if_changed,pad_cat) + +SPL: spl/u-boot-spl.bin FORCE + $(Q)$(MAKE) $(build)=arch/arm/mach-imx $@ + +ifeq ($(CONFIG_ARCH_IMX8M), y) +flash.bin: spl/u-boot-spl.bin u-boot.itb FORCE + $(Q)$(MAKE) $(build)=arch/arm/mach-imx $@ +endif + +u-boot-with-spl.imx u-boot-with-nand-spl.imx: SPL u-boot.bin FORCE + $(Q)$(MAKE) $(build)=arch/arm/mach-imx $@ + +MKIMAGEFLAGS_u-boot.ubl = -n $(UBL_CONFIG) -T ublimage -e $(CONFIG_SYS_TEXT_BASE) + +u-boot.ubl: u-boot-with-spl.bin FORCE + $(call if_changed,mkimage) + +MKIMAGEFLAGS_u-boot-spl.ais = -s -n $(if $(CONFIG_AIS_CONFIG_FILE), \ + $(srctree)/$(CONFIG_AIS_CONFIG_FILE:"%"=%),"/dev/null") \ + -T aisimage -e $(CONFIG_SPL_TEXT_BASE) +spl/u-boot-spl.ais: spl/u-boot-spl.bin FORCE + $(call if_changed,mkimage) + +OBJCOPYFLAGS_u-boot.ais = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO) +u-boot.ais: spl/u-boot-spl.ais u-boot.img FORCE + $(call if_changed,pad_cat) + +u-boot-signed.sb: u-boot.bin spl/u-boot-spl.bin + $(Q)$(MAKE) $(build)=arch/arm/cpu/arm926ejs/mxs u-boot-signed.sb +u-boot.sb: u-boot.bin spl/u-boot-spl.bin + $(Q)$(MAKE) $(build)=arch/arm/cpu/arm926ejs/mxs u-boot.sb + +# On x600 (SPEAr600) U-Boot is appended to U-Boot SPL. +# Both images are created using mkimage (crc etc), so that the ROM +# bootloader can check its integrity. Padding needs to be done to the +# SPL image (with mkimage header) and not the binary. Otherwise the resulting image +# which is loaded/copied by the ROM bootloader to SRAM doesn't fit. +# The resulting image containing both U-Boot images is called u-boot.spr +MKIMAGEFLAGS_u-boot-spl.img = -A $(ARCH) -T firmware -C none \ + -a $(CONFIG_SPL_TEXT_BASE) -e $(CONFIG_SPL_TEXT_BASE) -n XLOADER +spl/u-boot-spl.img: spl/u-boot-spl.bin FORCE + $(call if_changed,mkimage) + +OBJCOPYFLAGS_u-boot.spr = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO) \ + --gap-fill=0xff +u-boot.spr: spl/u-boot-spl.img u-boot.img FORCE + $(call if_changed,pad_cat) + +ifneq ($(CONFIG_ARCH_SOCFPGA),) +quiet_cmd_socboot = SOCBOOT $@ +cmd_socboot = cat spl/u-boot-spl.sfp spl/u-boot-spl.sfp \ + spl/u-boot-spl.sfp spl/u-boot-spl.sfp \ + u-boot.img > $@ || rm -f $@ +u-boot-with-spl.sfp: spl/u-boot-spl.sfp u-boot.img FORCE + $(call if_changed,socboot) +endif + +ifeq ($(CONFIG_MPC85xx)$(CONFIG_OF_SEPARATE),yy) +u-boot-with-dtb.bin: u-boot.bin u-boot.dtb \ + $(if $(CONFIG_MPC85XX_HAVE_RESET_VECTOR), u-boot-br.bin) FORCE + $(call if_changed,binman) + +ifeq ($(CONFIG_MPC85XX_HAVE_RESET_VECTOR),y) +OBJCOPYFLAGS_u-boot-br.bin := -O binary -j .bootpg -j .resetvec +u-boot-br.bin: u-boot FORCE + $(call if_changed,objcopy) +endif +endif + +# x86 uses a large ROM. We fill it with 0xff, put the 16-bit stuff (including +# reset vector) at the top, Intel ME descriptor at the bottom, and U-Boot in +# the middle. This is handled by binman based on an image description in the +# board's device tree. +ifneq ($(CONFIG_X86_RESET_VECTOR),) +rom: u-boot.rom FORCE + +refcode.bin: $(srctree)/board/$(BOARDDIR)/refcode.bin FORCE + $(call if_changed,copy) + +quiet_cmd_ldr = LD $@ +cmd_ldr = $(LD) $(LDFLAGS_$(@F)) \ + $(filter-out FORCE,$^) -o $@ + +u-boot.rom: u-boot-x86-16bit.bin u-boot.bin \ + $(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \ + $(if $(CONFIG_HAVE_REFCODE),refcode.bin) FORCE + $(call if_changed,binman) + +OBJCOPYFLAGS_u-boot-x86-16bit.bin := -O binary -j .start16 -j .resetvec +u-boot-x86-16bit.bin: u-boot FORCE + $(call if_changed,objcopy) +endif + +ifneq ($(CONFIG_ARCH_SUNXI),) +ifeq ($(CONFIG_ARM64),) +u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.img u-boot.dtb FORCE + $(call if_changed,binman) +else +u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.itb FORCE + $(call if_changed,cat) +endif +endif + +ifneq ($(CONFIG_TEGRA),) +ifneq ($(CONFIG_BINMAN),) +# Makes u-boot-dtb-tegra.bin u-boot-tegra.bin u-boot-nodtb-tegra.bin +%-dtb-tegra.bin %-tegra.bin %-nodtb-tegra.bin: \ + spl/%-spl %.bin FORCE + $(call if_changed,binman) +else +OBJCOPYFLAGS_u-boot-nodtb-tegra.bin = -O binary --pad-to=$(CONFIG_SYS_TEXT_BASE) +u-boot-nodtb-tegra.bin: spl/u-boot-spl u-boot-nodtb.bin FORCE + $(call if_changed,pad_cat) + +OBJCOPYFLAGS_u-boot-tegra.bin = -O binary --pad-to=$(CONFIG_SYS_TEXT_BASE) +u-boot-tegra.bin: spl/u-boot-spl u-boot.bin FORCE + $(call if_changed,pad_cat) + +u-boot-dtb-tegra.bin: u-boot-tegra.bin FORCE + $(call if_changed,copy) +endif # binman +endif + +OBJCOPYFLAGS_u-boot-app.efi := $(OBJCOPYFLAGS_EFI) +u-boot-app.efi: u-boot FORCE + $(call if_changed,zobjcopy) + +u-boot.bin.o: u-boot.bin FORCE + $(call if_changed,efipayload) + +u-boot-payload.lds: $(LDSCRIPT_EFI) FORCE + $(call if_changed_dep,cpp_lds) + +# Rule to link the EFI payload which contains a stub and a U-Boot binary +quiet_cmd_u-boot_payload ?= LD $@ + cmd_u-boot_payload ?= $(LD) $(LDFLAGS_EFI_PAYLOAD) -o $@ \ + -T u-boot-payload.lds arch/x86/cpu/call32.o \ + lib/efi/efi.o lib/efi/efi_stub.o u-boot.bin.o \ + $(addprefix arch/$(ARCH)/lib/,$(EFISTUB)) + +u-boot-payload: u-boot.bin.o u-boot-payload.lds FORCE + $(call if_changed,u-boot_payload) + +OBJCOPYFLAGS_u-boot-payload.efi := $(OBJCOPYFLAGS_EFI) +u-boot-payload.efi: u-boot-payload FORCE + $(call if_changed,zobjcopy) + +u-boot-img.bin: spl/u-boot-spl.bin u-boot.img FORCE + $(call if_changed,cat) + +#Add a target to create boot binary having SPL binary in PBI format +#concatenated with u-boot binary. It is need by PowerPC SoC having +#internal SRAM <= 512KB. +MKIMAGEFLAGS_u-boot-spl.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \ + -R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage \ + -A $(ARCH) -a $(CONFIG_SPL_TEXT_BASE) + +spl/u-boot-spl.pbl: spl/u-boot-spl.bin FORCE + $(call if_changed,mkimage) + +ifeq ($(ARCH),arm) +UBOOT_BINLOAD := u-boot.img +else +ifeq ($(CONFIG_MPC85xx)$(CONFIG_OF_SEPARATE),yy) +UBOOT_BINLOAD := u-boot-with-dtb.bin +else +UBOOT_BINLOAD := u-boot.bin +endif +endif + +OBJCOPYFLAGS_u-boot-with-spl-pbl.bin = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO) \ + --gap-fill=0xff + +u-boot-with-spl-pbl.bin: spl/u-boot-spl.pbl $(UBOOT_BINLOAD) FORCE + $(call if_changed,pad_cat) + +# PPC4xx needs the SPL at the end of the image, since the reset vector +# is located at 0xfffffffc. So we can't use the "u-boot-img.bin" target +# and need to introduce a new build target with the full blown U-Boot +# at the start padded up to the start of the SPL image. And then concat +# the SPL image to the end. + +OBJCOPYFLAGS_u-boot-img-spl-at-end.bin := -I binary -O binary \ + --pad-to=$(CONFIG_UBOOT_PAD_TO) --gap-fill=0xff +u-boot-img-spl-at-end.bin: u-boot.img spl/u-boot-spl.bin FORCE + $(call if_changed,pad_cat) + +# Create a new ELF from a raw binary file. +ifndef PLATFORM_ELFENTRY + PLATFORM_ELFENTRY = "_start" +endif +quiet_cmd_u-boot-elf ?= LD $@ + cmd_u-boot-elf ?= $(LD) u-boot-elf.o -o $@ \ + --defsym=$(PLATFORM_ELFENTRY)=$(CONFIG_SYS_TEXT_BASE) \ + -Ttext=$(CONFIG_SYS_TEXT_BASE) +u-boot.elf: u-boot.bin + $(Q)$(OBJCOPY) -I binary $(PLATFORM_ELFFLAGS) $< u-boot-elf.o + $(call if_changed,u-boot-elf) + +# MediaTek's ARM-based u-boot needs a header to contains its load address +# which is parsed by the BootROM. +# If the SPL build is enabled, the header will be added to the spl binary, +# and the spl binary and the u-boot.img will be combined into one file. +# Otherwise the header will be added to the u-boot.bin directly. + +ifeq ($(CONFIG_SPL),y) +spl/u-boot-spl-mtk.bin: spl/u-boot-spl + +u-boot-mtk.bin: u-boot.dtb u-boot.img spl/u-boot-spl-mtk.bin FORCE + $(call if_changed,binman) +else +MKIMAGEFLAGS_u-boot-mtk.bin = -T mtk_image \ + -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) \ + -n "$(patsubst "%",%,$(CONFIG_MTK_BROM_HEADER_INFO))" + +u-boot-mtk.bin: u-boot.bin FORCE + $(call if_changed,mkimage) +endif + +ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(ARCH)/Makefile.postlink) + +# Rule to link u-boot +# May be overridden by arch/$(ARCH)/config.mk +quiet_cmd_u-boot__ ?= LD $@ + cmd_u-boot__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_u-boot) -o $@ \ + -T u-boot.lds $(u-boot-init) \ + --start-group $(u-boot-main) --end-group \ + $(PLATFORM_LIBS) -Map u-boot.map; \ + $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true) + +quiet_cmd_smap = GEN common/system_map.o +cmd_smap = \ + smap=`$(call SYSTEM_MAP,u-boot) | \ + awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "\\\\000"}'` ; \ + $(CC) $(c_flags) -DSYSTEM_MAP="\"$${smap}\"" \ + -c $(srctree)/common/system_map.c -o common/system_map.o + +u-boot: $(u-boot-init) $(u-boot-main) u-boot.lds FORCE + +$(call if_changed,u-boot__) +ifeq ($(CONFIG_KALLSYMS),y) + $(call cmd,smap) + $(call cmd,u-boot__) common/system_map.o +endif + +ifeq ($(CONFIG_RISCV),y) + @tools/prelink-riscv $@ 0 +endif + +quiet_cmd_sym ?= SYM $@ + cmd_sym ?= $(OBJDUMP) -t $< > $@ +u-boot.sym: u-boot FORCE + $(call if_changed,sym) + +# The actual objects are generated when descending, +# make sure no implicit rule kicks in +$(sort $(u-boot-init) $(u-boot-main)): $(u-boot-dirs) ; + +# Handle descending into subdirectories listed in $(vmlinux-dirs) +# Preset locale variables to speed up the build process. Limit locale +# tweaks to this spot to avoid wrong language settings when running +# make menuconfig etc. +# Error messages still appears in the original language + +PHONY += $(u-boot-dirs) +$(u-boot-dirs): prepare scripts + $(Q)$(MAKE) $(build)=$@ + +tools: prepare +# The "tools" are needed early +$(filter-out tools, $(u-boot-dirs)): tools +# The "examples" conditionally depend on U-Boot (say, when USE_PRIVATE_LIBGCC +# is "yes"), so compile examples after U-Boot is compiled. +examples: $(filter-out examples, $(u-boot-dirs)) + +define filechk_uboot.release + echo "$(UBOOTVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" +endef + +# Store (new) UBOOTRELEASE string in include/config/uboot.release +include/config/uboot.release: include/config/auto.conf FORCE + $(call filechk,uboot.release) + + +# Things we need to do before we recursively start building the kernel +# or the modules are listed in "prepare". +# A multi level approach is used. prepareN is processed before prepareN-1. +# archprepare is used in arch Makefiles and when processed asm symlink, +# version.h and scripts_basic is processed / created. + +# Listed in dependency order +PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3 + +# prepare3 is used to check if we are building in a separate output directory, +# and if so do: +# 1) Check that make has not been executed in the kernel src $(srctree) +prepare3: include/config/uboot.release +ifneq ($(KBUILD_SRC),) + @$(kecho) ' Using $(srctree) as source for U-Boot' + $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \ + echo >&2 " $(srctree) is not clean, please run 'make mrproper'"; \ + echo >&2 " in the '$(srctree)' directory.";\ + /bin/false; \ + fi; +endif + +# prepare2 creates a makefile if using a separate output directory +prepare2: prepare3 outputmakefile + +prepare1: prepare2 $(version_h) $(timestamp_h) \ + include/config/auto.conf +ifeq ($(wildcard $(LDSCRIPT)),) + @echo >&2 " Could not find linker script." + @/bin/false +endif + +ifeq ($(CONFIG_USE_DEFAULT_ENV_FILE),y) +prepare1: $(defaultenv_h) +endif + +archprepare: prepare1 scripts_basic + +prepare0: archprepare FORCE + $(Q)$(MAKE) $(build)=. + +# All the preparing.. +prepare: prepare0 + +# Generate some files +# --------------------------------------------------------------------------- + +define filechk_version.h + (echo \#define PLAIN_VERSION \"$(UBOOTRELEASE)\"; \ + echo \#define U_BOOT_VERSION \"U-Boot \" PLAIN_VERSION; \ + echo \#define CONFIG_SYSTEM_AS_ROOT \"${SYSTEMMODE}\"; \ + echo \#define CONFIG_AVB2 \"${AVBMODE}\"; \ + echo \#define CC_VERSION_STRING \"$$(LC_ALL=C $(CC) --version | head -n 1)\"; \ + echo \#define LD_VERSION_STRING \"$$(LC_ALL=C $(LD) --version | head -n 1)\"; ) +endef + +# The SOURCE_DATE_EPOCH mechanism requires a date that behaves like GNU date. +# The BSD date on the other hand behaves different and would produce errors +# with the misused '-d' switch. Respect that and search a working date with +# well known pre- and suffixes for the GNU variant of date. +define filechk_timestamp.h + (if test -n "$${SOURCE_DATE_EPOCH}"; then \ + SOURCE_DATE="@$${SOURCE_DATE_EPOCH}"; \ + DATE=""; \ + for date in gdate date.gnu date; do \ + $${date} -u -d "$${SOURCE_DATE}" >/dev/null 2>&1 && DATE="$${date}"; \ + done; \ + if test -n "$${DATE}"; then \ + LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_DATE "%b %d %C%y"'; \ + LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_TIME "%T"'; \ + LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_TZ "%z"'; \ + LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; \ + LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_BUILD_DATE 0x%Y%m%d'; \ + else \ + return 42; \ + fi; \ + else \ + LC_ALL=C date +'#define U_BOOT_DATE "%b %d %C%y"'; \ + LC_ALL=C date +'#define U_BOOT_TIME "%T"'; \ + LC_ALL=C date +'#define U_BOOT_TZ "%z"'; \ + LC_ALL=C date +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; \ + LC_ALL=C date +'#define U_BOOT_BUILD_DATE 0x%Y%m%d'; \ + fi) +endef + +define filechk_defaultenv.h + (grep -v '^#' | \ + grep -v '^$$' | \ + tr '\n' '\0' | \ + sed -e 's/\\\x0/\n/' | \ + xxd -i ; echo ", 0x00" ; ) +endef + +define filechk_timestamp_git.h + (echo \#define U_BOOT_DATE \"$(shell git log -1 --format=%cd --date=format:"%b %d %C%y")\"; \ + echo \#define U_BOOT_TIME \"$(shell git log -1 --format=%cd --date=format:"%T")\"; \ + echo \#define U_BOOT_TZ \"$(shell git log -1 --format=%cd --date=format:"%Z")\"; \ + echo \#define U_BOOT_DMI_DATE \"$(shell git log -1 --format=%cd --date=format:"%m/%d/%Y")\"; \ + echo \#define U_BOOT_BUILD_DATE \"$(shell git log -1 --format=%cd --date=format:"0x%Y%m%d")\";) +endef + +export U_BOOT_TIME_GIT=$(shell git log -1 --format=%cd --date=format:"%T") +export U_BOOT_DATE_GIT=$(shell git log -1 --format=%cd --date=format:"%b %d %C%y") + +$(version_h): include/config/uboot.release FORCE + $(call filechk,version.h) + + +ifeq ($(KBUILD_TIME_STAMP),0) +$(timestamp_h): $(srctree)/Makefile FORCE + $(call filechk,timestamp.h) +else +$(timestamp_git_h): $(srctree)/Makefile FORCE + $(call filechk,timestamp_git.h) +endif + +$(defaultenv_h): $(CONFIG_DEFAULT_ENV_FILE:"%"=%) FORCE + $(call filechk,defaultenv.h) + +# --------------------------------------------------------------------------- +quiet_cmd_cpp_lds = LDS $@ +cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) \ + -D__ASSEMBLY__ -x assembler-with-cpp -std=c99 -P -o $@ $< + +u-boot.lds: $(LDSCRIPT) prepare FORCE + $(call if_changed_dep,cpp_lds) + +spl/u-boot-spl.bin: spl/u-boot-spl + @: +spl/u-boot-spl: tools prepare \ + $(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb) \ + $(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_TPL_OF_PLATDATA),dts/dt.dtb) + $(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all + +spl/sunxi-spl.bin: spl/u-boot-spl + @: + +spl/sunxi-spl-with-ecc.bin: spl/sunxi-spl.bin + @: + +spl/u-boot-spl.sfp: spl/u-boot-spl + @: + +spl/boot.bin: spl/u-boot-spl + @: + +tpl/u-boot-tpl.bin: tools prepare \ + $(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb) + $(Q)$(MAKE) obj=tpl -f $(srctree)/scripts/Makefile.spl all + +TAG_SUBDIRS := $(patsubst %,$(srctree)/%,$(u-boot-dirs) include) + +FIND := find +FINDFLAGS := -L + +tags ctags: + ctags -w -o ctags `$(FIND) $(FINDFLAGS) $(TAG_SUBDIRS) \ + -name '*.[chS]' -print` + ln -s ctags tags + +etags: + etags -a -o etags `$(FIND) $(FINDFLAGS) $(TAG_SUBDIRS) \ + -name '*.[chS]' -print` +cscope: + $(FIND) $(FINDFLAGS) $(TAG_SUBDIRS) -name '*.[chS]' -print > \ + cscope.files + cscope -b -q -k + +SYSTEM_MAP = \ + $(NM) $1 | \ + grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \ + LC_ALL=C sort +System.map: u-boot + @$(call SYSTEM_MAP,$<) > $@ + +######################################################################### + +# ARM relocations should all be R_ARM_RELATIVE (32-bit) or +# R_AARCH64_RELATIVE (64-bit). +checkarmreloc: u-boot + @RELOC="`$(CROSS_COMPILE)readelf -r -W $< | cut -d ' ' -f 4 | \ + grep R_A | sort -u`"; \ + if test "$$RELOC" != "R_ARM_RELATIVE" -a \ + "$$RELOC" != "R_AARCH64_RELATIVE"; then \ + echo "$< contains unexpected relocations: $$RELOC"; \ + false; \ + fi + +envtools: scripts_basic $(version_h) $(timestamp_h) + $(Q)$(MAKE) $(build)=tools/env + +tools-only: scripts_basic $(version_h) $(timestamp_h) + $(Q)$(MAKE) $(build)=tools + +tools-all: export HOST_TOOLS_ALL=y +tools-all: envtools tools ; + +cross_tools: export CROSS_BUILD_TOOLS=y +cross_tools: tools ; + +.PHONY : CHANGELOG +CHANGELOG: + git log --no-merges U-Boot-1_1_5.. | \ + unexpand -a | sed -e 's/\s\s*$$//' > $@ + +######################################################################### + +### +# Cleaning is done on three levels. +# make clean Delete most generated files +# Leave enough to build external modules +# make mrproper Delete the current configuration, and all generated files +# make distclean Remove editor backup files, patch leftover files and the like + +# Directories & files removed with 'make clean' +CLEAN_DIRS += $(MODVERDIR) \ + $(foreach d, spl tpl, $(patsubst %,$d/%, \ + $(filter-out include, $(shell ls -1 $d 2>/dev/null)))) + +CLEAN_FILES += include/bmp_logo.h include/bmp_logo_data.h \ + u-boot.* MLO* SPL System.map fit-dtb.blob + +# Directories & files removed with 'make mrproper' +MRPROPER_DIRS += include/config include/generated spl tpl \ + .tmp_objdiff +MRPROPER_FILES += .config .config.old include/autoconf.mk* include/config.h \ + ctags etags tags + +# clean - Delete most, but leave enough to build external modules +# +clean: rm-dirs := $(CLEAN_DIRS) +clean: rm-files := $(CLEAN_FILES) + +clean-dirs := $(foreach f,$(u-boot-alldirs),$(if $(wildcard $(srctree)/$f/Makefile),$f)) + +clean-dirs := $(addprefix _clean_, $(clean-dirs)) + +PHONY += $(clean-dirs) clean archclean +$(clean-dirs): + $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) + +clean: $(clean-dirs) + $(call cmd,rmdirs) + $(call cmd,rmfiles) + @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ + \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ + -o -name '*.ko.*' -o -name '*.su' \ + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ + -o -name '*.lex.c' -o -name '*.tab.[ch]' \ + -o -name '*.symtypes' -o -name 'modules.order' \ + -o -name modules.builtin -o -name '.tmp_*.o.*' \ + -o -name 'dsdt.aml' -o -name 'dsdt.asl.tmp' -o -name 'dsdt.c' \ + -o -name '*.efi' -o -name '*.gcno' -o -name '*.so' \) \ + -type f -print | xargs rm -f + +# mrproper - Delete all generated files, including .config +# +mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS)) +mrproper: rm-files := $(wildcard $(MRPROPER_FILES)) +mrproper-dirs := $(addprefix _mrproper_,scripts) + +PHONY += $(mrproper-dirs) mrproper archmrproper +$(mrproper-dirs): + $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@) + +mrproper: clean $(mrproper-dirs) + $(call cmd,rmdirs) + $(call cmd,rmfiles) + @rm -f arch/*/include/asm/arch + +# distclean +# +PHONY += distclean + +distclean: mrproper + @find $(srctree) $(RCS_FIND_IGNORE) \ + \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ + -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ + -o -name '.*.rej' -o -name '*%' -o -name 'core' \ + -o -name '*.pyc' \) \ + -type f -print | xargs rm -f + @rm -f boards.cfg + +backup: + F=`basename $(srctree)` ; cd .. ; \ + gtar --force-local -zcvf `LC_ALL=C date "+$$F-%Y-%m-%d-%T.tar.gz"` $$F + +help: + @echo 'Cleaning targets:' + @echo ' clean - Remove most generated files but keep the config' + @echo ' mrproper - Remove all generated files + config + various backup files' + @echo ' distclean - mrproper + remove editor backup and patch files' + @echo '' + @echo 'Configuration targets:' + @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help + @echo '' + @echo 'Test targets:' + @echo '' + @echo ' check - Run all automated tests that use sandbox' + @echo ' qcheck - Run quick automated tests that use sandbox' + @echo '' + @echo 'Other generic targets:' + @echo ' all - Build all necessary images depending on configuration' + @echo ' tests - Build U-Boot for sandbox and run tests' + @echo '* u-boot - Build the bare u-boot' + @echo ' dir/ - Build all files in dir and below' + @echo ' dir/file.[oisS] - Build specified target only' + @echo ' dir/file.lst - Build specified mixed source/assembly target only' + @echo ' (requires a recent binutils and recent build (System.map))' + @echo ' tags/ctags - Generate ctags file for editors' + @echo ' etags - Generate etags file for editors' + @echo ' cscope - Generate cscope index' + @echo ' ubootrelease - Output the release version string (use with make -s)' + @echo ' ubootversion - Output the version stored in Makefile (use with make -s)' + @echo " cfg - Don't build, just create the .cfg files" + @echo " envtools - Build only the target-side environment tools" + @echo '' + @echo 'Static analysers' + @echo ' checkstack - Generate a list of stack hogs' + @echo ' coccicheck - Execute static code analysis with Coccinelle' + @echo '' + @echo 'Documentation targets:' + @$(MAKE) -f $(srctree)/Documentation/Makefile dochelp + @echo '' + @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build' + @echo ' make V=2 [targets] 2 => give reason for rebuild of target' + @echo ' make O=dir [targets] Locate all output files in "dir", including .config' + @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse by default)' + @echo ' make C=2 [targets] Force check of all c source with $$CHECK' + @echo ' make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections' + @echo ' make W=n [targets] Enable extra gcc checks, n=1,2,3 where' + @echo ' 1: warnings which may be relevant and do not occur too often' + @echo ' 2: warnings which occur quite often but may still be relevant' + @echo ' 3: more obscure warnings, can most likely be ignored' + @echo ' Multiple levels can be combined with W=12 or W=123' + @echo ' make T=0 [targets] 0 => use local time (date) as build timestamp' + @echo ' make T=1 [targets] 1 => use latest git commit time as build timestamp' + @echo '' + @echo 'Execute "make" or "make all" to build all targets marked with [*] ' + @echo 'For further info see the ./README file' + +tests check: + $(srctree)/test/run + +qcheck: + $(srctree)/test/run quick + +# Documentation targets +# --------------------------------------------------------------------------- +DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \ + linkcheckdocs dochelp refcheckdocs +PHONY += $(DOC_TARGETS) +$(DOC_TARGETS): scripts_basic FORCE + $(Q)$(MAKE) $(build)=Documentation $@ + +endif #ifeq ($(config-targets),1) +endif #ifeq ($(mixed-targets),1) + +PHONY += checkstack ubootrelease ubootversion + +checkstack: + $(OBJDUMP) -d u-boot $$(find . -name u-boot-spl) | \ + $(PERL) $(src)/scripts/checkstack.pl $(ARCH) + +ubootrelease: + @echo "$(UBOOTVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" + +ubootversion: + @echo $(UBOOTVERSION) + +# Single targets +# --------------------------------------------------------------------------- +# Single targets are compatible with: +# - build with mixed source and output +# - build with separate output dir 'make O=...' +# - external modules +# +# target-dir => where to store outputfile +# build-dir => directory in kernel source tree to use + +ifeq ($(KBUILD_EXTMOD),) + build-dir = $(patsubst %/,%,$(dir $@)) + target-dir = $(dir $@) +else + zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@))) + build-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash)) + target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@)) +endif + +%.s: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.i: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.o: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.lst: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.s: %.S prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.o: %.S prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.symtypes: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + +# Modules +/: prepare scripts FORCE + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) +%/: prepare scripts FORCE + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) +%.ko: prepare scripts FORCE + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) $(@:.ko=.o) + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + +# Consistency checks +# --------------------------------------------------------------------------- + +PHONY += coccicheck + +coccicheck: + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ + +# FIXME Should go into a make.lib or something +# =========================================================================== + +quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN $(wildcard $(rm-dirs))) + cmd_rmdirs = rm -rf $(rm-dirs) + +quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files))) + cmd_rmfiles = rm -f $(rm-files) + +# read all saved command lines + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + $(cmd_files): ; # Do not try to update included dependency files + include $(cmd_files) +endif + +endif # skip-makefile + +PHONY += FORCE +FORCE: + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable so we can use it in if_changed and friends. +.PHONY: $(PHONY)
diff --git a/README b/README new file mode 100644 index 0000000..17d56b8 --- /dev/null +++ b/README
@@ -0,0 +1,5050 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000 - 2013 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +Summary: +======== + +This directory contains the source code for U-Boot, a boot loader for +Embedded boards based on PowerPC, ARM, MIPS and several other +processors, which can be installed in a boot ROM and used to +initialize and test the hardware or to download and run application +code. + +The development of U-Boot is closely related to Linux: some parts of +the source code originate in the Linux source tree, we have some +header files in common, and special provision has been made to +support booting of Linux images. + +Some attention has been paid to make this software easily +configurable and extendable. For instance, all monitor commands are +implemented with the same call interface, so that it's very easy to +add new commands. Also, instead of permanently adding rarely used +code (for instance hardware test utilities) to the monitor, you can +load and run it dynamically. + + +Status: +======= + +In general, all boards for which a configuration option exists in the +Makefile have been tested to some extent and can be considered +"working". In fact, many of them are used in production systems. + +In case of problems see the CHANGELOG file to find out who contributed +the specific port. In addition, there are various MAINTAINERS files +scattered throughout the U-Boot source identifying the people or +companies responsible for various boards and subsystems. + +Note: As of August, 2010, there is no longer a CHANGELOG file in the +actual U-Boot source tree; however, it can be created dynamically +from the Git log using: + + make CHANGELOG + + +Where to get help: +================== + +In case you have questions about, problems with or contributions for +U-Boot, you should send a message to the U-Boot mailing list at +<u-boot@lists.denx.de>. There is also an archive of previous traffic +on the mailing list - please search the archive before asking FAQ's. +Please see http://lists.denx.de/pipermail/u-boot and +http://dir.gmane.org/gmane.comp.boot-loaders.u-boot + + +Where to get source code: +========================= + +The U-Boot source code is maintained in the Git repository at +git://www.denx.de/git/u-boot.git ; you can browse it online at +http://www.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=summary + +The "snapshot" links on this page allow you to download tarballs of +any version you might be interested in. Official releases are also +available for FTP download from the ftp://ftp.denx.de/pub/u-boot/ +directory. + +Pre-built (and tested) images are available from +ftp://ftp.denx.de/pub/u-boot/images/ + + +Where we come from: +=================== + +- start from 8xxrom sources +- create PPCBoot project (http://sourceforge.net/projects/ppcboot) +- clean up code +- make it easier to add custom boards +- make it possible to add other [PowerPC] CPUs +- extend functions, especially: + * Provide extended interface to Linux boot loader + * S-Record download + * network boot + * PCMCIA / CompactFlash / ATA disk / SCSI ... boot +- create ARMBoot project (http://sourceforge.net/projects/armboot) +- add other CPU families (starting with ARM) +- create U-Boot project (http://sourceforge.net/projects/u-boot) +- current project page: see http://www.denx.de/wiki/U-Boot + + +Names and Spelling: +=================== + +The "official" name of this project is "Das U-Boot". The spelling +"U-Boot" shall be used in all written text (documentation, comments +in source files etc.). Example: + + This is the README file for the U-Boot project. + +File names etc. shall be based on the string "u-boot". Examples: + + include/asm-ppc/u-boot.h + + #include <asm/u-boot.h> + +Variable names, preprocessor constants etc. shall be either based on +the string "u_boot" or on "U_BOOT". Example: + + U_BOOT_VERSION u_boot_logo + IH_OS_U_BOOT u_boot_hush_start + + +Versioning: +=========== + +Starting with the release in October 2008, the names of the releases +were changed from numerical release numbers without deeper meaning +into a time stamp based numbering. Regular releases are identified by +names consisting of the calendar year and month of the release date. +Additional fields (if present) indicate release candidates or bug fix +releases in "stable" maintenance trees. + +Examples: + U-Boot v2009.11 - Release November 2009 + U-Boot v2009.11.1 - Release 1 in version November 2009 stable tree + U-Boot v2010.09-rc1 - Release candidate 1 for September 2010 release + + +Directory Hierarchy: +==================== + +/arch Architecture specific files + /arc Files generic to ARC architecture + /arm Files generic to ARM architecture + /m68k Files generic to m68k architecture + /microblaze Files generic to microblaze architecture + /mips Files generic to MIPS architecture + /nds32 Files generic to NDS32 architecture + /nios2 Files generic to Altera NIOS2 architecture + /openrisc Files generic to OpenRISC architecture + /powerpc Files generic to PowerPC architecture + /riscv Files generic to RISC-V architecture + /sandbox Files generic to HW-independent "sandbox" + /sh Files generic to SH architecture + /x86 Files generic to x86 architecture +/api Machine/arch independent API for external apps +/board Board dependent files +/cmd U-Boot commands functions +/common Misc architecture independent functions +/configs Board default configuration files +/disk Code for disk drive partition handling +/doc Documentation (don't expect too much) +/drivers Commonly used device drivers +/dts Contains Makefile for building internal U-Boot fdt. +/examples Example code for standalone applications, etc. +/fs Filesystem code (cramfs, ext2, jffs2, etc.) +/include Header Files +/lib Library routines generic to all architectures +/Licenses Various license files +/net Networking code +/post Power On Self Test +/scripts Various build scripts and Makefiles +/test Various unit test files +/tools Tools to build S-Record or U-Boot images, etc. + +Software Configuration: +======================= + +Configuration is usually done using C preprocessor defines; the +rationale behind that is to avoid dead code whenever possible. + +There are two classes of configuration variables: + +* Configuration _OPTIONS_: + These are selectable by the user and have names beginning with + "CONFIG_". + +* Configuration _SETTINGS_: + These depend on the hardware etc. and should not be meddled with if + you don't know what you're doing; they have names beginning with + "CONFIG_SYS_". + +Previously, all configuration was done by hand, which involved creating +symbolic links and editing configuration files manually. More recently, +U-Boot has added the Kbuild infrastructure used by the Linux kernel, +allowing you to use the "make menuconfig" command to configure your +build. + + +Selection of Processor Architecture and Board Type: +--------------------------------------------------- + +For all supported boards there are ready-to-use default +configurations available; just type "make <board_name>_defconfig". + +Example: For a TQM823L module type: + + cd u-boot + make TQM823L_defconfig + +Note: If you're looking for the default configuration file for a board +you're sure used to be there but is now missing, check the file +doc/README.scrapyard for a list of no longer supported boards. + +Sandbox Environment: +-------------------- + +U-Boot can be built natively to run on a Linux host using the 'sandbox' +board. This allows feature development which is not board- or architecture- +specific to be undertaken on a native platform. The sandbox is also used to +run some of U-Boot's tests. + +See board/sandbox/README.sandbox for more details. + + +Board Initialisation Flow: +-------------------------- + +This is the intended start-up flow for boards. This should apply for both +SPL and U-Boot proper (i.e. they both follow the same rules). + +Note: "SPL" stands for "Secondary Program Loader," which is explained in +more detail later in this file. + +At present, SPL mostly uses a separate code path, but the function names +and roles of each function are the same. Some boards or architectures +may not conform to this. At least most ARM boards which use +CONFIG_SPL_FRAMEWORK conform to this. + +Execution typically starts with an architecture-specific (and possibly +CPU-specific) start.S file, such as: + + - arch/arm/cpu/armv7/start.S + - arch/powerpc/cpu/mpc83xx/start.S + - arch/mips/cpu/start.S + +and so on. From there, three functions are called; the purpose and +limitations of each of these functions are described below. + +lowlevel_init(): + - purpose: essential init to permit execution to reach board_init_f() + - no global_data or BSS + - there is no stack (ARMv7 may have one but it will soon be removed) + - must not set up SDRAM or use console + - must only do the bare minimum to allow execution to continue to + board_init_f() + - this is almost never needed + - return normally from this function + +board_init_f(): + - purpose: set up the machine ready for running board_init_r(): + i.e. SDRAM and serial UART + - global_data is available + - stack is in SRAM + - BSS is not available, so you cannot use global/static variables, + only stack variables and global_data + + Non-SPL-specific notes: + - dram_init() is called to set up DRAM. If already done in SPL this + can do nothing + + SPL-specific notes: + - you can override the entire board_init_f() function with your own + version as needed. + - preloader_console_init() can be called here in extremis + - should set up SDRAM, and anything needed to make the UART work + - these is no need to clear BSS, it will be done by crt0.S + - must return normally from this function (don't call board_init_r() + directly) + +Here the BSS is cleared. For SPL, if CONFIG_SPL_STACK_R is defined, then at +this point the stack and global_data are relocated to below +CONFIG_SPL_STACK_R_ADDR. For non-SPL, U-Boot is relocated to run at the top of +memory. + +board_init_r(): + - purpose: main execution, common code + - global_data is available + - SDRAM is available + - BSS is available, all static/global variables can be used + - execution eventually continues to main_loop() + + Non-SPL-specific notes: + - U-Boot is relocated to the top of memory and is now running from + there. + + SPL-specific notes: + - stack is optionally in SDRAM, if CONFIG_SPL_STACK_R is defined and + CONFIG_SPL_STACK_R_ADDR points into SDRAM + - preloader_console_init() can be called here - typically this is + done by selecting CONFIG_SPL_BOARD_INIT and then supplying a + spl_board_init() function containing this call + - loads U-Boot or (in falcon mode) Linux + + + +Configuration Options: +---------------------- + +Configuration depends on the combination of board and CPU type; all +such information is kept in a configuration file +"include/configs/<board_name>.h". + +Example: For a TQM823L module, all configuration settings are in +"include/configs/TQM823L.h". + + +Many of the options are named exactly as the corresponding Linux +kernel configuration options. The intention is to make it easier to +build a config tool - later. + +- ARM Platform Bus Type(CCI): + CoreLink Cache Coherent Interconnect (CCI) is ARM BUS which + provides full cache coherency between two clusters of multi-core + CPUs and I/O coherency for devices and I/O masters + + CONFIG_SYS_FSL_HAS_CCI400 + + Defined For SoC that has cache coherent interconnect + CCN-400 + + CONFIG_SYS_FSL_HAS_CCN504 + + Defined for SoC that has cache coherent interconnect CCN-504 + +The following options need to be configured: + +- CPU Type: Define exactly one, e.g. CONFIG_MPC85XX. + +- Board Type: Define exactly one, e.g. CONFIG_MPC8540ADS. + +- 85xx CPU Options: + CONFIG_SYS_PPC64 + + Specifies that the core is a 64-bit PowerPC implementation (implements + the "64" category of the Power ISA). This is necessary for ePAPR + compliance, among other possible reasons. + + CONFIG_SYS_FSL_TBCLK_DIV + + Defines the core time base clock divider ratio compared to the + system clock. On most PQ3 devices this is 8, on newer QorIQ + devices it can be 16 or 32. The ratio varies from SoC to Soc. + + CONFIG_SYS_FSL_PCIE_COMPAT + + Defines the string to utilize when trying to match PCIe device + tree nodes for the given platform. + + CONFIG_SYS_FSL_ERRATUM_A004510 + + Enables a workaround for erratum A004510. If set, + then CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV and + CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY must be set. + + CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV + CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2 (optional) + + Defines one or two SoC revisions (low 8 bits of SVR) + for which the A004510 workaround should be applied. + + The rest of SVR is either not relevant to the decision + of whether the erratum is present (e.g. p2040 versus + p2041) or is implied by the build target, which controls + whether CONFIG_SYS_FSL_ERRATUM_A004510 is set. + + See Freescale App Note 4493 for more information about + this erratum. + + CONFIG_A003399_NOR_WORKAROUND + Enables a workaround for IFC erratum A003399. It is only + required during NOR boot. + + CONFIG_A008044_WORKAROUND + Enables a workaround for T1040/T1042 erratum A008044. It is only + required during NAND boot and valid for Rev 1.0 SoC revision + + CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY + + This is the value to write into CCSR offset 0x18600 + according to the A004510 workaround. + + CONFIG_SYS_FSL_DSP_DDR_ADDR + This value denotes start offset of DDR memory which is + connected exclusively to the DSP cores. + + CONFIG_SYS_FSL_DSP_M2_RAM_ADDR + This value denotes start offset of M2 memory + which is directly connected to the DSP core. + + CONFIG_SYS_FSL_DSP_M3_RAM_ADDR + This value denotes start offset of M3 memory which is directly + connected to the DSP core. + + CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT + This value denotes start offset of DSP CCSR space. + + CONFIG_SYS_FSL_SINGLE_SOURCE_CLK + Single Source Clock is clocking mode present in some of FSL SoC's. + In this mode, a single differential clock is used to supply + clocks to the sysclock, ddrclock and usbclock. + + CONFIG_SYS_CPC_REINIT_F + This CONFIG is defined when the CPC is configured as SRAM at the + time of U-Boot entry and is required to be re-initialized. + + CONFIG_DEEP_SLEEP + Indicates this SoC supports deep sleep feature. If deep sleep is + supported, core will start to execute uboot when wakes up. + +- Generic CPU options: + CONFIG_SYS_BIG_ENDIAN, CONFIG_SYS_LITTLE_ENDIAN + + Defines the endianess of the CPU. Implementation of those + values is arch specific. + + CONFIG_SYS_FSL_DDR + Freescale DDR driver in use. This type of DDR controller is + found in mpc83xx, mpc85xx, mpc86xx as well as some ARM core + SoCs. + + CONFIG_SYS_FSL_DDR_ADDR + Freescale DDR memory-mapped register base. + + CONFIG_SYS_FSL_DDR_EMU + Specify emulator support for DDR. Some DDR features such as + deskew training are not available. + + CONFIG_SYS_FSL_DDRC_GEN1 + Freescale DDR1 controller. + + CONFIG_SYS_FSL_DDRC_GEN2 + Freescale DDR2 controller. + + CONFIG_SYS_FSL_DDRC_GEN3 + Freescale DDR3 controller. + + CONFIG_SYS_FSL_DDRC_GEN4 + Freescale DDR4 controller. + + CONFIG_SYS_FSL_DDRC_ARM_GEN3 + Freescale DDR3 controller for ARM-based SoCs. + + CONFIG_SYS_FSL_DDR1 + Board config to use DDR1. It can be enabled for SoCs with + Freescale DDR1 or DDR2 controllers, depending on the board + implemetation. + + CONFIG_SYS_FSL_DDR2 + Board config to use DDR2. It can be enabled for SoCs with + Freescale DDR2 or DDR3 controllers, depending on the board + implementation. + + CONFIG_SYS_FSL_DDR3 + Board config to use DDR3. It can be enabled for SoCs with + Freescale DDR3 or DDR3L controllers. + + CONFIG_SYS_FSL_DDR3L + Board config to use DDR3L. It can be enabled for SoCs with + DDR3L controllers. + + CONFIG_SYS_FSL_DDR4 + Board config to use DDR4. It can be enabled for SoCs with + DDR4 controllers. + + CONFIG_SYS_FSL_IFC_BE + Defines the IFC controller register space as Big Endian + + CONFIG_SYS_FSL_IFC_LE + Defines the IFC controller register space as Little Endian + + CONFIG_SYS_FSL_IFC_CLK_DIV + Defines divider of platform clock(clock input to IFC controller). + + CONFIG_SYS_FSL_LBC_CLK_DIV + Defines divider of platform clock(clock input to eLBC controller). + + CONFIG_SYS_FSL_PBL_PBI + It enables addition of RCW (Power on reset configuration) in built image. + Please refer doc/README.pblimage for more details + + CONFIG_SYS_FSL_PBL_RCW + It adds PBI(pre-boot instructions) commands in u-boot build image. + PBI commands can be used to configure SoC before it starts the execution. + Please refer doc/README.pblimage for more details + + CONFIG_SPL_FSL_PBL + It adds a target to create boot binary having SPL binary in PBI format + concatenated with u-boot binary. + + CONFIG_SYS_FSL_DDR_BE + Defines the DDR controller register space as Big Endian + + CONFIG_SYS_FSL_DDR_LE + Defines the DDR controller register space as Little Endian + + CONFIG_SYS_FSL_DDR_SDRAM_BASE_PHY + Physical address from the view of DDR controllers. It is the + same as CONFIG_SYS_DDR_SDRAM_BASE for all Power SoCs. But + it could be different for ARM SoCs. + + CONFIG_SYS_FSL_DDR_INTLV_256B + DDR controller interleaving on 256-byte. This is a special + interleaving mode, handled by Dickens for Freescale layerscape + SoCs with ARM core. + + CONFIG_SYS_FSL_DDR_MAIN_NUM_CTRLS + Number of controllers used as main memory. + + CONFIG_SYS_FSL_OTHER_DDR_NUM_CTRLS + Number of controllers used for other than main memory. + + CONFIG_SYS_FSL_HAS_DP_DDR + Defines the SoC has DP-DDR used for DPAA. + + CONFIG_SYS_FSL_SEC_BE + Defines the SEC controller register space as Big Endian + + CONFIG_SYS_FSL_SEC_LE + Defines the SEC controller register space as Little Endian + +- MIPS CPU options: + CONFIG_SYS_INIT_SP_OFFSET + + Offset relative to CONFIG_SYS_SDRAM_BASE for initial stack + pointer. This is needed for the temporary stack before + relocation. + + CONFIG_XWAY_SWAP_BYTES + + Enable compilation of tools/xway-swap-bytes needed for Lantiq + XWAY SoCs for booting from NOR flash. The U-Boot image needs to + be swapped if a flash programmer is used. + +- ARM options: + CONFIG_SYS_EXCEPTION_VECTORS_HIGH + + Select high exception vectors of the ARM core, e.g., do not + clear the V bit of the c1 register of CP15. + + COUNTER_FREQUENCY + Generic timer clock source frequency. + + COUNTER_FREQUENCY_REAL + Generic timer clock source frequency if the real clock is + different from COUNTER_FREQUENCY, and can only be determined + at run time. + +- Tegra SoC options: + CONFIG_TEGRA_SUPPORT_NON_SECURE + + Support executing U-Boot in non-secure (NS) mode. Certain + impossible actions will be skipped if the CPU is in NS mode, + such as ARM architectural timer initialization. + +- Linux Kernel Interface: + CONFIG_CLOCKS_IN_MHZ + + U-Boot stores all clock information in Hz + internally. For binary compatibility with older Linux + kernels (which expect the clocks passed in the + bd_info data to be in MHz) the environment variable + "clocks_in_mhz" can be defined so that U-Boot + converts clock data to MHZ before passing it to the + Linux kernel. + When CONFIG_CLOCKS_IN_MHZ is defined, a definition of + "clocks_in_mhz=1" is automatically included in the + default environment. + + CONFIG_MEMSIZE_IN_BYTES [relevant for MIPS only] + + When transferring memsize parameter to Linux, some versions + expect it to be in bytes, others in MB. + Define CONFIG_MEMSIZE_IN_BYTES to make it in bytes. + + CONFIG_OF_LIBFDT + + New kernel versions are expecting firmware settings to be + passed using flattened device trees (based on open firmware + concepts). + + CONFIG_OF_LIBFDT + * New libfdt-based support + * Adds the "fdt" command + * The bootm command automatically updates the fdt + + OF_TBCLK - The timebase frequency. + OF_STDOUT_PATH - The path to the console device + + boards with QUICC Engines require OF_QE to set UCC MAC + addresses + + CONFIG_OF_BOARD_SETUP + + Board code has addition modification that it wants to make + to the flat device tree before handing it off to the kernel + + CONFIG_OF_SYSTEM_SETUP + + Other code has addition modification that it wants to make + to the flat device tree before handing it off to the kernel. + This causes ft_system_setup() to be called before booting + the kernel. + + CONFIG_OF_IDE_FIXUP + + U-Boot can detect if an IDE device is present or not. + If not, and this new config option is activated, U-Boot + removes the ATA node from the DTS before booting Linux, + so the Linux IDE driver does not probe the device and + crash. This is needed for buggy hardware (uc101) where + no pull down resistor is connected to the signal IDE5V_DD7. + + CONFIG_MACH_TYPE [relevant for ARM only][mandatory] + + This setting is mandatory for all boards that have only one + machine type and must be used to specify the machine type + number as it appears in the ARM machine registry + (see http://www.arm.linux.org.uk/developer/machines/). + Only boards that have multiple machine types supported + in a single configuration file and the machine type is + runtime discoverable, do not have to use this setting. + +- vxWorks boot parameters: + + bootvx constructs a valid bootline using the following + environments variables: bootdev, bootfile, ipaddr, netmask, + serverip, gatewayip, hostname, othbootargs. + It loads the vxWorks image pointed bootfile. + + Note: If a "bootargs" environment is defined, it will overwride + the defaults discussed just above. + +- Cache Configuration: + CONFIG_SYS_ICACHE_OFF - Do not enable instruction cache in U-Boot + CONFIG_SYS_DCACHE_OFF - Do not enable data cache in U-Boot + CONFIG_SYS_L2CACHE_OFF- Do not enable L2 cache in U-Boot + +- Cache Configuration for ARM: + CONFIG_SYS_L2_PL310 - Enable support for ARM PL310 L2 cache + controller + CONFIG_SYS_PL310_BASE - Physical base address of PL310 + controller register space + +- Serial Ports: + CONFIG_PL010_SERIAL + + Define this if you want support for Amba PrimeCell PL010 UARTs. + + CONFIG_PL011_SERIAL + + Define this if you want support for Amba PrimeCell PL011 UARTs. + + CONFIG_PL011_CLOCK + + If you have Amba PrimeCell PL011 UARTs, set this variable to + the clock speed of the UARTs. + + CONFIG_PL01x_PORTS + + If you have Amba PrimeCell PL010 or PL011 UARTs on your board, + define this to a list of base addresses for each (supported) + port. See e.g. include/configs/versatile.h + + CONFIG_SERIAL_HW_FLOW_CONTROL + + Define this variable to enable hw flow control in serial driver. + Current user of this option is drivers/serial/nsl16550.c driver + +- Console Baudrate: + CONFIG_BAUDRATE - in bps + Select one of the baudrates listed in + CONFIG_SYS_BAUDRATE_TABLE, see below. + +- Autoboot Command: + CONFIG_BOOTCOMMAND + Only needed when CONFIG_BOOTDELAY is enabled; + define a command string that is automatically executed + when no character is read on the console interface + within "Boot Delay" after reset. + + CONFIG_RAMBOOT and CONFIG_NFSBOOT + The value of these goes into the environment as + "ramboot" and "nfsboot" respectively, and can be used + as a convenience, when switching between booting from + RAM and NFS. + +- Pre-Boot Commands: + CONFIG_PREBOOT + + When this option is #defined, the existence of the + environment variable "preboot" will be checked + immediately before starting the CONFIG_BOOTDELAY + countdown and/or running the auto-boot command resp. + entering interactive mode. + + This feature is especially useful when "preboot" is + automatically generated or modified. For an example + see the LWMON board specific code: here "preboot" is + modified when the user holds down a certain + combination of keys on the (special) keyboard when + booting the systems + +- Serial Download Echo Mode: + CONFIG_LOADS_ECHO + If defined to 1, all characters received during a + serial download (using the "loads" command) are + echoed back. This might be needed by some terminal + emulations (like "cu"), but may as well just take + time on others. This setting #define's the initial + value of the "loads_echo" environment variable. + +- Kgdb Serial Baudrate: (if CONFIG_CMD_KGDB is defined) + CONFIG_KGDB_BAUDRATE + Select one of the baudrates listed in + CONFIG_SYS_BAUDRATE_TABLE, see below. + +- Removal of commands + If no commands are needed to boot, you can disable + CONFIG_CMDLINE to remove them. In this case, the command line + will not be available, and when U-Boot wants to execute the + boot command (on start-up) it will call board_run_command() + instead. This can reduce image size significantly for very + simple boot procedures. + +- Regular expression support: + CONFIG_REGEX + If this variable is defined, U-Boot is linked against + the SLRE (Super Light Regular Expression) library, + which adds regex support to some commands, as for + example "env grep" and "setexpr". + +- Device tree: + CONFIG_OF_CONTROL + If this variable is defined, U-Boot will use a device tree + to configure its devices, instead of relying on statically + compiled #defines in the board file. This option is + experimental and only available on a few boards. The device + tree is available in the global data as gd->fdt_blob. + + U-Boot needs to get its device tree from somewhere. This can + be done using one of the three options below: + + CONFIG_OF_EMBED + If this variable is defined, U-Boot will embed a device tree + binary in its image. This device tree file should be in the + board directory and called <soc>-<board>.dts. The binary file + is then picked up in board_init_f() and made available through + the global data structure as gd->fdt_blob. + + CONFIG_OF_SEPARATE + If this variable is defined, U-Boot will build a device tree + binary. It will be called u-boot.dtb. Architecture-specific + code will locate it at run-time. Generally this works by: + + cat u-boot.bin u-boot.dtb >image.bin + + and in fact, U-Boot does this for you, creating a file called + u-boot-dtb.bin which is useful in the common case. You can + still use the individual files if you need something more + exotic. + + CONFIG_OF_BOARD + If this variable is defined, U-Boot will use the device tree + provided by the board at runtime instead of embedding one with + the image. Only boards defining board_fdt_blob_setup() support + this option (see include/fdtdec.h file). + +- Watchdog: + CONFIG_WATCHDOG + If this variable is defined, it enables watchdog + support for the SoC. There must be support in the SoC + specific code for a watchdog. For the 8xx + CPUs, the SIU Watchdog feature is enabled in the SYPCR + register. When supported for a specific SoC is + available, then no further board specific code should + be needed to use it. + + CONFIG_HW_WATCHDOG + When using a watchdog circuitry external to the used + SoC, then define this variable and provide board + specific code for the "hw_watchdog_reset" function. + + CONFIG_AT91_HW_WDT_TIMEOUT + specify the timeout in seconds. default 2 seconds. + +- Real-Time Clock: + + When CONFIG_CMD_DATE is selected, the type of the RTC + has to be selected, too. Define exactly one of the + following options: + + CONFIG_RTC_PCF8563 - use Philips PCF8563 RTC + CONFIG_RTC_MC13XXX - use MC13783 or MC13892 RTC + CONFIG_RTC_MC146818 - use MC146818 RTC + CONFIG_RTC_DS1307 - use Maxim, Inc. DS1307 RTC + CONFIG_RTC_DS1337 - use Maxim, Inc. DS1337 RTC + CONFIG_RTC_DS1338 - use Maxim, Inc. DS1338 RTC + CONFIG_RTC_DS1339 - use Maxim, Inc. DS1339 RTC + CONFIG_RTC_DS164x - use Dallas DS164x RTC + CONFIG_RTC_ISL1208 - use Intersil ISL1208 RTC + CONFIG_RTC_MAX6900 - use Maxim, Inc. MAX6900 RTC + CONFIG_RTC_DS1337_NOOSC - Turn off the OSC output for DS1337 + CONFIG_SYS_RV3029_TCR - enable trickle charger on + RV3029 RTC. + + Note that if the RTC uses I2C, then the I2C interface + must also be configured. See I2C Support, below. + +- GPIO Support: + CONFIG_PCA953X - use NXP's PCA953X series I2C GPIO + + The CONFIG_SYS_I2C_PCA953X_WIDTH option specifies a list of + chip-ngpio pairs that tell the PCA953X driver the number of + pins supported by a particular chip. + + Note that if the GPIO device uses I2C, then the I2C interface + must also be configured. See I2C Support, below. + +- I/O tracing: + When CONFIG_IO_TRACE is selected, U-Boot intercepts all I/O + accesses and can checksum them or write a list of them out + to memory. See the 'iotrace' command for details. This is + useful for testing device drivers since it can confirm that + the driver behaves the same way before and after a code + change. Currently this is supported on sandbox and arm. To + add support for your architecture, add '#include <iotrace.h>' + to the bottom of arch/<arch>/include/asm/io.h and test. + + Example output from the 'iotrace stats' command is below. + Note that if the trace buffer is exhausted, the checksum will + still continue to operate. + + iotrace is enabled + Start: 10000000 (buffer start address) + Size: 00010000 (buffer size) + Offset: 00000120 (current buffer offset) + Output: 10000120 (start + offset) + Count: 00000018 (number of trace records) + CRC32: 9526fb66 (CRC32 of all trace records) + +- Timestamp Support: + + When CONFIG_TIMESTAMP is selected, the timestamp + (date and time) of an image is printed by image + commands like bootm or iminfo. This option is + automatically enabled when you select CONFIG_CMD_DATE . + +- Partition Labels (disklabels) Supported: + Zero or more of the following: + CONFIG_MAC_PARTITION Apple's MacOS partition table. + CONFIG_ISO_PARTITION ISO partition table, used on CDROM etc. + CONFIG_EFI_PARTITION GPT partition table, common when EFI is the + bootloader. Note 2TB partition limit; see + disk/part_efi.c + CONFIG_SCSI) you must configure support for at + least one non-MTD partition type as well. + +- IDE Reset method: + CONFIG_IDE_RESET_ROUTINE - this is defined in several + board configurations files but used nowhere! + + CONFIG_IDE_RESET - is this is defined, IDE Reset will + be performed by calling the function + ide_set_reset(int reset) + which has to be defined in a board specific file + +- ATAPI Support: + CONFIG_ATAPI + + Set this to enable ATAPI support. + +- LBA48 Support + CONFIG_LBA48 + + Set this to enable support for disks larger than 137GB + Also look at CONFIG_SYS_64BIT_LBA. + Whithout these , LBA48 support uses 32bit variables and will 'only' + support disks up to 2.1TB. + + CONFIG_SYS_64BIT_LBA: + When enabled, makes the IDE subsystem use 64bit sector addresses. + Default is 32bit. + +- SCSI Support: + CONFIG_SYS_SCSI_MAX_LUN [8], CONFIG_SYS_SCSI_MAX_SCSI_ID [7] and + CONFIG_SYS_SCSI_MAX_DEVICE [CONFIG_SYS_SCSI_MAX_SCSI_ID * + CONFIG_SYS_SCSI_MAX_LUN] can be adjusted to define the + maximum numbers of LUNs, SCSI ID's and target + devices. + + The environment variable 'scsidevs' is set to the number of + SCSI devices found during the last scan. + +- NETWORK Support (PCI): + CONFIG_E1000 + Support for Intel 8254x/8257x gigabit chips. + + CONFIG_E1000_SPI + Utility code for direct access to the SPI bus on Intel 8257x. + This does not do anything useful unless you set at least one + of CONFIG_CMD_E1000 or CONFIG_E1000_SPI_GENERIC. + + CONFIG_E1000_SPI_GENERIC + Allow generic access to the SPI bus on the Intel 8257x, for + example with the "sspi" command. + + CONFIG_EEPRO100 + Support for Intel 82557/82559/82559ER chips. + Optional CONFIG_EEPRO100_SROM_WRITE enables EEPROM + write routine for first time initialisation. + + CONFIG_TULIP + Support for Digital 2114x chips. + Optional CONFIG_TULIP_SELECT_MEDIA for board specific + modem chip initialisation (KS8761/QS6611). + + CONFIG_NATSEMI + Support for National dp83815 chips. + + CONFIG_NS8382X + Support for National dp8382[01] gigabit chips. + +- NETWORK Support (other): + + CONFIG_DRIVER_AT91EMAC + Support for AT91RM9200 EMAC. + + CONFIG_RMII + Define this to use reduced MII inteface + + CONFIG_DRIVER_AT91EMAC_QUIET + If this defined, the driver is quiet. + The driver doen't show link status messages. + + CONFIG_CALXEDA_XGMAC + Support for the Calxeda XGMAC device + + CONFIG_LAN91C96 + Support for SMSC's LAN91C96 chips. + + CONFIG_LAN91C96_USE_32_BIT + Define this to enable 32 bit addressing + + CONFIG_SMC91111 + Support for SMSC's LAN91C111 chip + + CONFIG_SMC91111_BASE + Define this to hold the physical address + of the device (I/O space) + + CONFIG_SMC_USE_32_BIT + Define this if data bus is 32 bits + + CONFIG_SMC_USE_IOFUNCS + Define this to use i/o functions instead of macros + (some hardware wont work with macros) + + CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT + Define this if you have more then 3 PHYs. + + CONFIG_FTGMAC100 + Support for Faraday's FTGMAC100 Gigabit SoC Ethernet + + CONFIG_FTGMAC100_EGIGA + Define this to use GE link update with gigabit PHY. + Define this if FTGMAC100 is connected to gigabit PHY. + If your system has 10/100 PHY only, it might not occur + wrong behavior. Because PHY usually return timeout or + useless data when polling gigabit status and gigabit + control registers. This behavior won't affect the + correctnessof 10/100 link speed update. + + CONFIG_SH_ETHER + Support for Renesas on-chip Ethernet controller + + CONFIG_SH_ETHER_USE_PORT + Define the number of ports to be used + + CONFIG_SH_ETHER_PHY_ADDR + Define the ETH PHY's address + + CONFIG_SH_ETHER_CACHE_WRITEBACK + If this option is set, the driver enables cache flush. + +- PWM Support: + CONFIG_PWM_IMX + Support for PWM module on the imx6. + +- TPM Support: + CONFIG_TPM + Support TPM devices. + + CONFIG_TPM_TIS_INFINEON + Support for Infineon i2c bus TPM devices. Only one device + per system is supported at this time. + + CONFIG_TPM_TIS_I2C_BURST_LIMITATION + Define the burst count bytes upper limit + + CONFIG_TPM_ST33ZP24 + Support for STMicroelectronics TPM devices. Requires DM_TPM support. + + CONFIG_TPM_ST33ZP24_I2C + Support for STMicroelectronics ST33ZP24 I2C devices. + Requires TPM_ST33ZP24 and I2C. + + CONFIG_TPM_ST33ZP24_SPI + Support for STMicroelectronics ST33ZP24 SPI devices. + Requires TPM_ST33ZP24 and SPI. + + CONFIG_TPM_ATMEL_TWI + Support for Atmel TWI TPM device. Requires I2C support. + + CONFIG_TPM_TIS_LPC + Support for generic parallel port TPM devices. Only one device + per system is supported at this time. + + CONFIG_TPM_TIS_BASE_ADDRESS + Base address where the generic TPM device is mapped + to. Contemporary x86 systems usually map it at + 0xfed40000. + + CONFIG_TPM + Define this to enable the TPM support library which provides + functional interfaces to some TPM commands. + Requires support for a TPM device. + + CONFIG_TPM_AUTH_SESSIONS + Define this to enable authorized functions in the TPM library. + Requires CONFIG_TPM and CONFIG_SHA1. + +- USB Support: + At the moment only the UHCI host controller is + supported (PIP405, MIP405); define + CONFIG_USB_UHCI to enable it. + define CONFIG_USB_KEYBOARD to enable the USB Keyboard + and define CONFIG_USB_STORAGE to enable the USB + storage devices. + Note: + Supported are USB Keyboards and USB Floppy drives + (TEAC FD-05PUB). + + CONFIG_USB_EHCI_TXFIFO_THRESH enables setting of the + txfilltuning field in the EHCI controller on reset. + + CONFIG_USB_DWC2_REG_ADDR the physical CPU address of the DWC2 + HW module registers. + +- USB Device: + Define the below if you wish to use the USB console. + Once firmware is rebuilt from a serial console issue the + command "setenv stdin usbtty; setenv stdout usbtty" and + attach your USB cable. The Unix command "dmesg" should print + it has found a new device. The environment variable usbtty + can be set to gserial or cdc_acm to enable your device to + appear to a USB host as a Linux gserial device or a + Common Device Class Abstract Control Model serial device. + If you select usbtty = gserial you should be able to enumerate + a Linux host by + # modprobe usbserial vendor=0xVendorID product=0xProductID + else if using cdc_acm, simply setting the environment + variable usbtty to be cdc_acm should suffice. The following + might be defined in YourBoardName.h + + CONFIG_USB_DEVICE + Define this to build a UDC device + + CONFIG_USB_TTY + Define this to have a tty type of device available to + talk to the UDC device + + CONFIG_USBD_HS + Define this to enable the high speed support for usb + device and usbtty. If this feature is enabled, a routine + int is_usbd_high_speed(void) + also needs to be defined by the driver to dynamically poll + whether the enumeration has succeded at high speed or full + speed. + + CONFIG_SYS_CONSOLE_IS_IN_ENV + Define this if you want stdin, stdout &/or stderr to + be set to usbtty. + + If you have a USB-IF assigned VendorID then you may wish to + define your own vendor specific values either in BoardName.h + or directly in usbd_vendor_info.h. If you don't define + CONFIG_USBD_MANUFACTURER, CONFIG_USBD_PRODUCT_NAME, + CONFIG_USBD_VENDORID and CONFIG_USBD_PRODUCTID, then U-Boot + should pretend to be a Linux device to it's target host. + + CONFIG_USBD_MANUFACTURER + Define this string as the name of your company for + - CONFIG_USBD_MANUFACTURER "my company" + + CONFIG_USBD_PRODUCT_NAME + Define this string as the name of your product + - CONFIG_USBD_PRODUCT_NAME "acme usb device" + + CONFIG_USBD_VENDORID + Define this as your assigned Vendor ID from the USB + Implementors Forum. This *must* be a genuine Vendor ID + to avoid polluting the USB namespace. + - CONFIG_USBD_VENDORID 0xFFFF + + CONFIG_USBD_PRODUCTID + Define this as the unique Product ID + for your device + - CONFIG_USBD_PRODUCTID 0xFFFF + +- ULPI Layer Support: + The ULPI (UTMI Low Pin (count) Interface) PHYs are supported via + the generic ULPI layer. The generic layer accesses the ULPI PHY + via the platform viewport, so you need both the genric layer and + the viewport enabled. Currently only Chipidea/ARC based + viewport is supported. + To enable the ULPI layer support, define CONFIG_USB_ULPI and + CONFIG_USB_ULPI_VIEWPORT in your board configuration file. + If your ULPI phy needs a different reference clock than the + standard 24 MHz then you have to define CONFIG_ULPI_REF_CLK to + the appropriate value in Hz. + +- MMC Support: + The MMC controller on the Intel PXA is supported. To + enable this define CONFIG_MMC. The MMC can be + accessed from the boot prompt by mapping the device + to physical memory similar to flash. Command line is + enabled with CONFIG_CMD_MMC. The MMC driver also works with + the FAT fs. This is enabled with CONFIG_CMD_FAT. + + CONFIG_SH_MMCIF + Support for Renesas on-chip MMCIF controller + + CONFIG_SH_MMCIF_ADDR + Define the base address of MMCIF registers + + CONFIG_SH_MMCIF_CLK + Define the clock frequency for MMCIF + + CONFIG_SUPPORT_EMMC_BOOT + Enable some additional features of the eMMC boot partitions. + +- USB Device Firmware Update (DFU) class support: + CONFIG_DFU_OVER_USB + This enables the USB portion of the DFU USB class + + CONFIG_DFU_MMC + This enables support for exposing (e)MMC devices via DFU. + + CONFIG_DFU_NAND + This enables support for exposing NAND devices via DFU. + + CONFIG_DFU_RAM + This enables support for exposing RAM via DFU. + Note: DFU spec refer to non-volatile memory usage, but + allow usages beyond the scope of spec - here RAM usage, + one that would help mostly the developer. + + CONFIG_SYS_DFU_DATA_BUF_SIZE + Dfu transfer uses a buffer before writing data to the + raw storage device. Make the size (in bytes) of this buffer + configurable. The size of this buffer is also configurable + through the "dfu_bufsiz" environment variable. + + CONFIG_SYS_DFU_MAX_FILE_SIZE + When updating files rather than the raw storage device, + we use a static buffer to copy the file into and then write + the buffer once we've been given the whole file. Define + this to the maximum filesize (in bytes) for the buffer. + Default is 4 MiB if undefined. + + DFU_DEFAULT_POLL_TIMEOUT + Poll timeout [ms], is the timeout a device can send to the + host. The host must wait for this timeout before sending + a subsequent DFU_GET_STATUS request to the device. + + DFU_MANIFEST_POLL_TIMEOUT + Poll timeout [ms], which the device sends to the host when + entering dfuMANIFEST state. Host waits this timeout, before + sending again an USB request to the device. + +- Journaling Flash filesystem support: + CONFIG_JFFS2_NAND + Define these for a default partition on a NAND device + + CONFIG_SYS_JFFS2_FIRST_SECTOR, + CONFIG_SYS_JFFS2_FIRST_BANK, CONFIG_SYS_JFFS2_NUM_BANKS + Define these for a default partition on a NOR device + +- Keyboard Support: + See Kconfig help for available keyboard drivers. + + CONFIG_KEYBOARD + + Define this to enable a custom keyboard support. + This simply calls drv_keyboard_init() which must be + defined in your board-specific files. This option is deprecated + and is only used by novena. For new boards, use driver model + instead. + +- Video support: + CONFIG_FSL_DIU_FB + Enable the Freescale DIU video driver. Reference boards for + SOCs that have a DIU should define this macro to enable DIU + support, and should also define these other macros: + + CONFIG_SYS_DIU_ADDR + CONFIG_VIDEO + CONFIG_CFB_CONSOLE + CONFIG_VIDEO_SW_CURSOR + CONFIG_VGA_AS_SINGLE_DEVICE + CONFIG_VIDEO_LOGO + CONFIG_VIDEO_BMP_LOGO + + The DIU driver will look for the 'video-mode' environment + variable, and if defined, enable the DIU as a console during + boot. See the documentation file doc/README.video for a + description of this variable. + +- LCD Support: CONFIG_LCD + + Define this to enable LCD support (for output to LCD + display); also select one of the supported displays + by defining one of these: + + CONFIG_ATMEL_LCD: + + HITACHI TX09D70VM1CCA, 3.5", 240x320. + + CONFIG_NEC_NL6448AC33: + + NEC NL6448AC33-18. Active, color, single scan. + + CONFIG_NEC_NL6448BC20 + + NEC NL6448BC20-08. 6.5", 640x480. + Active, color, single scan. + + CONFIG_NEC_NL6448BC33_54 + + NEC NL6448BC33-54. 10.4", 640x480. + Active, color, single scan. + + CONFIG_SHARP_16x9 + + Sharp 320x240. Active, color, single scan. + It isn't 16x9, and I am not sure what it is. + + CONFIG_SHARP_LQ64D341 + + Sharp LQ64D341 display, 640x480. + Active, color, single scan. + + CONFIG_HLD1045 + + HLD1045 display, 640x480. + Active, color, single scan. + + CONFIG_OPTREX_BW + + Optrex CBL50840-2 NF-FW 99 22 M5 + or + Hitachi LMG6912RPFC-00T + or + Hitachi SP14Q002 + + 320x240. Black & white. + + CONFIG_LCD_ALIGNMENT + + Normally the LCD is page-aligned (typically 4KB). If this is + defined then the LCD will be aligned to this value instead. + For ARM it is sometimes useful to use MMU_SECTION_SIZE + here, since it is cheaper to change data cache settings on + a per-section basis. + + + CONFIG_LCD_ROTATION + + Sometimes, for example if the display is mounted in portrait + mode or even if it's mounted landscape but rotated by 180degree, + we need to rotate our content of the display relative to the + framebuffer, so that user can read the messages which are + printed out. + Once CONFIG_LCD_ROTATION is defined, the lcd_console will be + initialized with a given rotation from "vl_rot" out of + "vidinfo_t" which is provided by the board specific code. + The value for vl_rot is coded as following (matching to + fbcon=rotate:<n> linux-kernel commandline): + 0 = no rotation respectively 0 degree + 1 = 90 degree rotation + 2 = 180 degree rotation + 3 = 270 degree rotation + + If CONFIG_LCD_ROTATION is not defined, the console will be + initialized with 0degree rotation. + + CONFIG_LCD_BMP_RLE8 + + Support drawing of RLE8-compressed bitmaps on the LCD. + + CONFIG_I2C_EDID + + Enables an 'i2c edid' command which can read EDID + information over I2C from an attached LCD display. + +- Splash Screen Support: CONFIG_SPLASH_SCREEN + + If this option is set, the environment is checked for + a variable "splashimage". If found, the usual display + of logo, copyright and system information on the LCD + is suppressed and the BMP image at the address + specified in "splashimage" is loaded instead. The + console is redirected to the "nulldev", too. This + allows for a "silent" boot where a splash screen is + loaded very quickly after power-on. + + CONFIG_SPLASHIMAGE_GUARD + + If this option is set, then U-Boot will prevent the environment + variable "splashimage" from being set to a problematic address + (see doc/README.displaying-bmps). + This option is useful for targets where, due to alignment + restrictions, an improperly aligned BMP image will cause a data + abort. If you think you will not have problems with unaligned + accesses (for example because your toolchain prevents them) + there is no need to set this option. + + CONFIG_SPLASH_SCREEN_ALIGN + + If this option is set the splash image can be freely positioned + on the screen. Environment variable "splashpos" specifies the + position as "x,y". If a positive number is given it is used as + number of pixel from left/top. If a negative number is given it + is used as number of pixel from right/bottom. You can also + specify 'm' for centering the image. + + Example: + setenv splashpos m,m + => image at center of screen + + setenv splashpos 30,20 + => image at x = 30 and y = 20 + + setenv splashpos -10,m + => vertically centered image + at x = dspWidth - bmpWidth - 9 + +- Gzip compressed BMP image support: CONFIG_VIDEO_BMP_GZIP + + If this option is set, additionally to standard BMP + images, gzipped BMP images can be displayed via the + splashscreen support or the bmp command. + +- Run length encoded BMP image (RLE8) support: CONFIG_VIDEO_BMP_RLE8 + + If this option is set, 8-bit RLE compressed BMP images + can be displayed via the splashscreen support or the + bmp command. + +- Compression support: + CONFIG_GZIP + + Enabled by default to support gzip compressed images. + + CONFIG_BZIP2 + + If this option is set, support for bzip2 compressed + images is included. If not, only uncompressed and gzip + compressed images are supported. + + NOTE: the bzip2 algorithm requires a lot of RAM, so + the malloc area (as defined by CONFIG_SYS_MALLOC_LEN) should + be at least 4MB. + +- MII/PHY support: + CONFIG_PHY_CLOCK_FREQ (ppc4xx) + + The clock frequency of the MII bus + + CONFIG_PHY_RESET_DELAY + + Some PHY like Intel LXT971A need extra delay after + reset before any MII register access is possible. + For such PHY, set this option to the usec delay + required. (minimum 300usec for LXT971A) + + CONFIG_PHY_CMD_DELAY (ppc4xx) + + Some PHY like Intel LXT971A need extra delay after + command issued before MII status register can be read + +- IP address: + CONFIG_IPADDR + + Define a default value for the IP address to use for + the default Ethernet interface, in case this is not + determined through e.g. bootp. + (Environment variable "ipaddr") + +- Server IP address: + CONFIG_SERVERIP + + Defines a default value for the IP address of a TFTP + server to contact when using the "tftboot" command. + (Environment variable "serverip") + + CONFIG_KEEP_SERVERADDR + + Keeps the server's MAC address, in the env 'serveraddr' + for passing to bootargs (like Linux's netconsole option) + +- Gateway IP address: + CONFIG_GATEWAYIP + + Defines a default value for the IP address of the + default router where packets to other networks are + sent to. + (Environment variable "gatewayip") + +- Subnet mask: + CONFIG_NETMASK + + Defines a default value for the subnet mask (or + routing prefix) which is used to determine if an IP + address belongs to the local subnet or needs to be + forwarded through a router. + (Environment variable "netmask") + +- Multicast TFTP Mode: + CONFIG_MCAST_TFTP + + Defines whether you want to support multicast TFTP as per + rfc-2090; for example to work with atftp. Lets lots of targets + tftp down the same boot image concurrently. Note: the Ethernet + driver in use must provide a function: mcast() to join/leave a + multicast group. + +- BOOTP Recovery Mode: + CONFIG_BOOTP_RANDOM_DELAY + + If you have many targets in a network that try to + boot using BOOTP, you may want to avoid that all + systems send out BOOTP requests at precisely the same + moment (which would happen for instance at recovery + from a power failure, when all systems will try to + boot, thus flooding the BOOTP server. Defining + CONFIG_BOOTP_RANDOM_DELAY causes a random delay to be + inserted before sending out BOOTP requests. The + following delays are inserted then: + + 1st BOOTP request: delay 0 ... 1 sec + 2nd BOOTP request: delay 0 ... 2 sec + 3rd BOOTP request: delay 0 ... 4 sec + 4th and following + BOOTP requests: delay 0 ... 8 sec + + CONFIG_BOOTP_ID_CACHE_SIZE + + BOOTP packets are uniquely identified using a 32-bit ID. The + server will copy the ID from client requests to responses and + U-Boot will use this to determine if it is the destination of + an incoming response. Some servers will check that addresses + aren't in use before handing them out (usually using an ARP + ping) and therefore take up to a few hundred milliseconds to + respond. Network congestion may also influence the time it + takes for a response to make it back to the client. If that + time is too long, U-Boot will retransmit requests. In order + to allow earlier responses to still be accepted after these + retransmissions, U-Boot's BOOTP client keeps a small cache of + IDs. The CONFIG_BOOTP_ID_CACHE_SIZE controls the size of this + cache. The default is to keep IDs for up to four outstanding + requests. Increasing this will allow U-Boot to accept offers + from a BOOTP client in networks with unusually high latency. + +- DHCP Advanced Options: + You can fine tune the DHCP functionality by defining + CONFIG_BOOTP_* symbols: + + CONFIG_BOOTP_NISDOMAIN + CONFIG_BOOTP_BOOTFILESIZE + CONFIG_BOOTP_SEND_HOSTNAME + 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_SEND_HOSTNAME - Some DHCP servers are capable + to do a dynamic update of a DNS server. To do this, they + need the hostname of the DHCP requester. + If CONFIG_BOOTP_SEND_HOSTNAME is defined, the content + of the "hostname" environment variable is passed as + option 12 to the DHCP server. + + CONFIG_BOOTP_DHCP_REQUEST_DELAY + + A 32bit value in microseconds for a delay between + receiving a "DHCP Offer" and sending the "DHCP Request". + This fixes a problem with certain DHCP servers that don't + respond 100% of the time to a "DHCP request". E.g. On an + AT91RM9200 processor running at 180MHz, this delay needed + to be *at least* 15,000 usec before a Windows Server 2003 + DHCP server would reply 100% of the time. I recommend at + least 50,000 usec to be safe. The alternative is to hope + that one of the retries will be successful but note that + 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. + + - MAC address from environment variables + + FDT_SEQ_MACADDR_FROM_ENV + + Fix-up device tree with MAC addresses fetched sequentially from + environment variables. This config work on assumption that + non-usable ethernet node of device-tree are either not present + or their status has been marked as "disabled". + + - CDP Options: + CONFIG_CDP_DEVICE_ID + + The device id used in CDP trigger frames. + + CONFIG_CDP_DEVICE_ID_PREFIX + + A two character string which is prefixed to the MAC address + of the device. + + CONFIG_CDP_PORT_ID + + A printf format string which contains the ascii name of + the port. Normally is set to "eth%d" which sets + eth0 for the first Ethernet, eth1 for the second etc. + + CONFIG_CDP_CAPABILITIES + + A 32bit integer which indicates the device capabilities; + 0x00000010 for a normal host which does not forwards. + + CONFIG_CDP_VERSION + + An ascii string containing the version of the software. + + CONFIG_CDP_PLATFORM + + An ascii string containing the name of the platform. + + CONFIG_CDP_TRIGGER + + A 32bit integer sent on the trigger. + + CONFIG_CDP_POWER_CONSUMPTION + + A 16bit integer containing the power consumption of the + device in .1 of milliwatts. + + CONFIG_CDP_APPLIANCE_VLAN_TYPE + + A byte containing the id of the VLAN. + +- Status LED: CONFIG_LED_STATUS + + Several configurations allow to display the current + status using a LED. For instance, the LED will blink + fast while running U-Boot code, stop blinking as + soon as a reply to a BOOTP request was received, and + start blinking slow once the Linux kernel is running + (supported by a status LED driver in the Linux + kernel). Defining CONFIG_LED_STATUS enables this + feature in U-Boot. + + Additional options: + + CONFIG_LED_STATUS_GPIO + The status LED can be connected to a GPIO pin. + In such cases, the gpio_led driver can be used as a + status LED backend implementation. Define CONFIG_LED_STATUS_GPIO + to include the gpio_led driver in the U-Boot binary. + + CONFIG_GPIO_LED_INVERTED_TABLE + Some GPIO connected LEDs may have inverted polarity in which + case the GPIO high value corresponds to LED off state and + GPIO low value corresponds to LED on state. + In such cases CONFIG_GPIO_LED_INVERTED_TABLE may be defined + with a list of GPIO LEDs that have inverted polarity. + +- I2C Support: CONFIG_SYS_I2C + + This enable the NEW i2c subsystem, and will allow you to use + i2c commands at the u-boot command line (as long as you set + CONFIG_CMD_I2C in CONFIG_COMMANDS) and communicate with i2c + based realtime clock chips or other i2c devices. See + common/cmd_i2c.c for a description of the command line + interface. + + ported i2c driver to the new framework: + - drivers/i2c/soft_i2c.c: + - activate first bus with CONFIG_SYS_I2C_SOFT define + CONFIG_SYS_I2C_SOFT_SPEED and CONFIG_SYS_I2C_SOFT_SLAVE + for defining speed and slave address + - activate second bus with I2C_SOFT_DECLARATIONS2 define + CONFIG_SYS_I2C_SOFT_SPEED_2 and CONFIG_SYS_I2C_SOFT_SLAVE_2 + for defining speed and slave address + - activate third bus with I2C_SOFT_DECLARATIONS3 define + CONFIG_SYS_I2C_SOFT_SPEED_3 and CONFIG_SYS_I2C_SOFT_SLAVE_3 + for defining speed and slave address + - activate fourth bus with I2C_SOFT_DECLARATIONS4 define + CONFIG_SYS_I2C_SOFT_SPEED_4 and CONFIG_SYS_I2C_SOFT_SLAVE_4 + for defining speed and slave address + + - drivers/i2c/fsl_i2c.c: + - activate i2c driver with CONFIG_SYS_I2C_FSL + define CONFIG_SYS_FSL_I2C_OFFSET for setting the register + offset CONFIG_SYS_FSL_I2C_SPEED for the i2c speed and + CONFIG_SYS_FSL_I2C_SLAVE for the slave addr of the first + bus. + - If your board supports a second fsl i2c bus, define + CONFIG_SYS_FSL_I2C2_OFFSET for the register offset + CONFIG_SYS_FSL_I2C2_SPEED for the speed and + CONFIG_SYS_FSL_I2C2_SLAVE for the slave address of the + second bus. + + - drivers/i2c/tegra_i2c.c: + - activate this driver with CONFIG_SYS_I2C_TEGRA + - This driver adds 4 i2c buses with a fix speed from + 100000 and the slave addr 0! + + - drivers/i2c/ppc4xx_i2c.c + - activate this driver with CONFIG_SYS_I2C_PPC4XX + - CONFIG_SYS_I2C_PPC4XX_CH0 activate hardware channel 0 + - CONFIG_SYS_I2C_PPC4XX_CH1 activate hardware channel 1 + + - drivers/i2c/i2c_mxc.c + - activate this driver with CONFIG_SYS_I2C_MXC + - enable bus 1 with CONFIG_SYS_I2C_MXC_I2C1 + - enable bus 2 with CONFIG_SYS_I2C_MXC_I2C2 + - enable bus 3 with CONFIG_SYS_I2C_MXC_I2C3 + - enable bus 4 with CONFIG_SYS_I2C_MXC_I2C4 + - define speed for bus 1 with CONFIG_SYS_MXC_I2C1_SPEED + - define slave for bus 1 with CONFIG_SYS_MXC_I2C1_SLAVE + - define speed for bus 2 with CONFIG_SYS_MXC_I2C2_SPEED + - define slave for bus 2 with CONFIG_SYS_MXC_I2C2_SLAVE + - define speed for bus 3 with CONFIG_SYS_MXC_I2C3_SPEED + - define slave for bus 3 with CONFIG_SYS_MXC_I2C3_SLAVE + - define speed for bus 4 with CONFIG_SYS_MXC_I2C4_SPEED + - define slave for bus 4 with CONFIG_SYS_MXC_I2C4_SLAVE + If those defines are not set, default value is 100000 + for speed, and 0 for slave. + + - drivers/i2c/rcar_i2c.c: + - activate this driver with CONFIG_SYS_I2C_RCAR + - This driver adds 4 i2c buses + + - CONFIG_SYS_RCAR_I2C0_BASE for setting the register channel 0 + - CONFIG_SYS_RCAR_I2C0_SPEED for for the speed channel 0 + - CONFIG_SYS_RCAR_I2C1_BASE for setting the register channel 1 + - CONFIG_SYS_RCAR_I2C1_SPEED for for the speed channel 1 + - CONFIG_SYS_RCAR_I2C2_BASE for setting the register channel 2 + - CONFIG_SYS_RCAR_I2C2_SPEED for for the speed channel 2 + - CONFIG_SYS_RCAR_I2C3_BASE for setting the register channel 3 + - CONFIG_SYS_RCAR_I2C3_SPEED for for the speed channel 3 + - CONFIF_SYS_RCAR_I2C_NUM_CONTROLLERS for number of i2c buses + + - drivers/i2c/sh_i2c.c: + - activate this driver with CONFIG_SYS_I2C_SH + - This driver adds from 2 to 5 i2c buses + + - CONFIG_SYS_I2C_SH_BASE0 for setting the register channel 0 + - CONFIG_SYS_I2C_SH_SPEED0 for for the speed channel 0 + - CONFIG_SYS_I2C_SH_BASE1 for setting the register channel 1 + - CONFIG_SYS_I2C_SH_SPEED1 for for the speed channel 1 + - CONFIG_SYS_I2C_SH_BASE2 for setting the register channel 2 + - CONFIG_SYS_I2C_SH_SPEED2 for for the speed channel 2 + - CONFIG_SYS_I2C_SH_BASE3 for setting the register channel 3 + - CONFIG_SYS_I2C_SH_SPEED3 for for the speed channel 3 + - CONFIG_SYS_I2C_SH_BASE4 for setting the register channel 4 + - CONFIG_SYS_I2C_SH_SPEED4 for for the speed channel 4 + - CONFIG_SYS_I2C_SH_NUM_CONTROLLERS for number of i2c buses + + - drivers/i2c/omap24xx_i2c.c + - activate this driver with CONFIG_SYS_I2C_OMAP24XX + - CONFIG_SYS_OMAP24_I2C_SPEED speed channel 0 + - CONFIG_SYS_OMAP24_I2C_SLAVE slave addr channel 0 + - CONFIG_SYS_OMAP24_I2C_SPEED1 speed channel 1 + - CONFIG_SYS_OMAP24_I2C_SLAVE1 slave addr channel 1 + - CONFIG_SYS_OMAP24_I2C_SPEED2 speed channel 2 + - CONFIG_SYS_OMAP24_I2C_SLAVE2 slave addr channel 2 + - CONFIG_SYS_OMAP24_I2C_SPEED3 speed channel 3 + - CONFIG_SYS_OMAP24_I2C_SLAVE3 slave addr channel 3 + - CONFIG_SYS_OMAP24_I2C_SPEED4 speed channel 4 + - CONFIG_SYS_OMAP24_I2C_SLAVE4 slave addr channel 4 + + - drivers/i2c/zynq_i2c.c + - activate this driver with CONFIG_SYS_I2C_ZYNQ + - set CONFIG_SYS_I2C_ZYNQ_SPEED for speed setting + - set CONFIG_SYS_I2C_ZYNQ_SLAVE for slave addr + + - drivers/i2c/s3c24x0_i2c.c: + - activate this driver with CONFIG_SYS_I2C_S3C24X0 + - This driver adds i2c buses (11 for Exynos5250, Exynos5420 + 9 i2c buses for Exynos4 and 1 for S3C24X0 SoCs from Samsung) + with a fix speed from 100000 and the slave addr 0! + + - drivers/i2c/ihs_i2c.c + - activate this driver with CONFIG_SYS_I2C_IHS + - CONFIG_SYS_I2C_IHS_CH0 activate hardware channel 0 + - CONFIG_SYS_I2C_IHS_SPEED_0 speed channel 0 + - CONFIG_SYS_I2C_IHS_SLAVE_0 slave addr channel 0 + - CONFIG_SYS_I2C_IHS_CH1 activate hardware channel 1 + - CONFIG_SYS_I2C_IHS_SPEED_1 speed channel 1 + - CONFIG_SYS_I2C_IHS_SLAVE_1 slave addr channel 1 + - CONFIG_SYS_I2C_IHS_CH2 activate hardware channel 2 + - CONFIG_SYS_I2C_IHS_SPEED_2 speed channel 2 + - CONFIG_SYS_I2C_IHS_SLAVE_2 slave addr channel 2 + - CONFIG_SYS_I2C_IHS_CH3 activate hardware channel 3 + - CONFIG_SYS_I2C_IHS_SPEED_3 speed channel 3 + - CONFIG_SYS_I2C_IHS_SLAVE_3 slave addr channel 3 + - activate dual channel with CONFIG_SYS_I2C_IHS_DUAL + - CONFIG_SYS_I2C_IHS_SPEED_0_1 speed channel 0_1 + - CONFIG_SYS_I2C_IHS_SLAVE_0_1 slave addr channel 0_1 + - CONFIG_SYS_I2C_IHS_SPEED_1_1 speed channel 1_1 + - CONFIG_SYS_I2C_IHS_SLAVE_1_1 slave addr channel 1_1 + - CONFIG_SYS_I2C_IHS_SPEED_2_1 speed channel 2_1 + - CONFIG_SYS_I2C_IHS_SLAVE_2_1 slave addr channel 2_1 + - CONFIG_SYS_I2C_IHS_SPEED_3_1 speed channel 3_1 + - CONFIG_SYS_I2C_IHS_SLAVE_3_1 slave addr channel 3_1 + + additional defines: + + CONFIG_SYS_NUM_I2C_BUSES + Hold the number of i2c buses you want to use. + + CONFIG_SYS_I2C_DIRECT_BUS + define this, if you don't use i2c muxes on your hardware. + if CONFIG_SYS_I2C_MAX_HOPS is not defined or == 0 you can + omit this define. + + CONFIG_SYS_I2C_MAX_HOPS + define how many muxes are maximal consecutively connected + on one i2c bus. If you not use i2c muxes, omit this + define. + + CONFIG_SYS_I2C_BUSES + hold a list of buses you want to use, only used if + CONFIG_SYS_I2C_DIRECT_BUS is not defined, for example + a board with CONFIG_SYS_I2C_MAX_HOPS = 1 and + CONFIG_SYS_NUM_I2C_BUSES = 9: + + CONFIG_SYS_I2C_BUSES {{0, {I2C_NULL_HOP}}, \ + {0, {{I2C_MUX_PCA9547, 0x70, 1}}}, \ + {0, {{I2C_MUX_PCA9547, 0x70, 2}}}, \ + {0, {{I2C_MUX_PCA9547, 0x70, 3}}}, \ + {0, {{I2C_MUX_PCA9547, 0x70, 4}}}, \ + {0, {{I2C_MUX_PCA9547, 0x70, 5}}}, \ + {1, {I2C_NULL_HOP}}, \ + {1, {{I2C_MUX_PCA9544, 0x72, 1}}}, \ + {1, {{I2C_MUX_PCA9544, 0x72, 2}}}, \ + } + + which defines + bus 0 on adapter 0 without a mux + bus 1 on adapter 0 with a PCA9547 on address 0x70 port 1 + bus 2 on adapter 0 with a PCA9547 on address 0x70 port 2 + bus 3 on adapter 0 with a PCA9547 on address 0x70 port 3 + bus 4 on adapter 0 with a PCA9547 on address 0x70 port 4 + bus 5 on adapter 0 with a PCA9547 on address 0x70 port 5 + bus 6 on adapter 1 without a mux + bus 7 on adapter 1 with a PCA9544 on address 0x72 port 1 + bus 8 on adapter 1 with a PCA9544 on address 0x72 port 2 + + If you do not have i2c muxes on your board, omit this define. + +- Legacy I2C Support: + If you use the software i2c interface (CONFIG_SYS_I2C_SOFT) + then the following macros need to be defined (examples are + from include/configs/lwmon.h): + + I2C_INIT + + (Optional). Any commands necessary to enable the I2C + controller or configure ports. + + eg: #define I2C_INIT (immr->im_cpm.cp_pbdir |= PB_SCL) + + I2C_ACTIVE + + The code necessary to make the I2C data line active + (driven). If the data line is open collector, this + define can be null. + + eg: #define I2C_ACTIVE (immr->im_cpm.cp_pbdir |= PB_SDA) + + I2C_TRISTATE + + The code necessary to make the I2C data line tri-stated + (inactive). If the data line is open collector, this + define can be null. + + eg: #define I2C_TRISTATE (immr->im_cpm.cp_pbdir &= ~PB_SDA) + + I2C_READ + + Code that returns true if the I2C data line is high, + false if it is low. + + eg: #define I2C_READ ((immr->im_cpm.cp_pbdat & PB_SDA) != 0) + + I2C_SDA(bit) + + If <bit> is true, sets the I2C data line high. If it + is false, it clears it (low). + + eg: #define I2C_SDA(bit) \ + if(bit) immr->im_cpm.cp_pbdat |= PB_SDA; \ + else immr->im_cpm.cp_pbdat &= ~PB_SDA + + I2C_SCL(bit) + + If <bit> is true, sets the I2C clock line high. If it + is false, it clears it (low). + + eg: #define I2C_SCL(bit) \ + if(bit) immr->im_cpm.cp_pbdat |= PB_SCL; \ + else immr->im_cpm.cp_pbdat &= ~PB_SCL + + I2C_DELAY + + This delay is invoked four times per clock cycle so this + controls the rate of data transfer. The data rate thus + is 1 / (I2C_DELAY * 4). Often defined to be something + like: + + #define I2C_DELAY udelay(2) + + CONFIG_SOFT_I2C_GPIO_SCL / CONFIG_SOFT_I2C_GPIO_SDA + + If your arch supports the generic GPIO framework (asm/gpio.h), + then you may alternatively define the two GPIOs that are to be + used as SCL / SDA. Any of the previous I2C_xxx macros will + have GPIO-based defaults assigned to them as appropriate. + + You should define these to the GPIO value as given directly to + the generic GPIO functions. + + CONFIG_SYS_I2C_INIT_BOARD + + When a board is reset during an i2c bus transfer + chips might think that the current transfer is still + in progress. On some boards it is possible to access + the i2c SCLK line directly, either by using the + processor pin as a GPIO or by having a second pin + connected to the bus. If this option is defined a + custom i2c_init_board() routine in boards/xxx/board.c + is run early in the boot sequence. + + CONFIG_I2C_MULTI_BUS + + This option allows the use of multiple I2C buses, each of which + must have a controller. At any point in time, only one bus is + active. To switch to a different bus, use the 'i2c dev' command. + Note that bus numbering is zero-based. + + CONFIG_SYS_I2C_NOPROBES + + This option specifies a list of I2C devices that will be skipped + when the 'i2c probe' command is issued. If CONFIG_I2C_MULTI_BUS + is set, specify a list of bus-device pairs. Otherwise, specify + a 1D array of device addresses + + e.g. + #undef CONFIG_I2C_MULTI_BUS + #define CONFIG_SYS_I2C_NOPROBES {0x50,0x68} + + will skip addresses 0x50 and 0x68 on a board with one I2C bus + + #define CONFIG_I2C_MULTI_BUS + #define CONFIG_SYS_I2C_NOPROBES {{0,0x50},{0,0x68},{1,0x54}} + + will skip addresses 0x50 and 0x68 on bus 0 and address 0x54 on bus 1 + + CONFIG_SYS_SPD_BUS_NUM + + If defined, then this indicates the I2C bus number for DDR SPD. + If not defined, then U-Boot assumes that SPD is on I2C bus 0. + + CONFIG_SYS_RTC_BUS_NUM + + If defined, then this indicates the I2C bus number for the RTC. + If not defined, then U-Boot assumes that RTC is on I2C bus 0. + + CONFIG_SOFT_I2C_READ_REPEATED_START + + defining this will force the i2c_read() function in + the soft_i2c driver to perform an I2C repeated start + between writing the address pointer and reading the + data. If this define is omitted the default behaviour + of doing a stop-start sequence will be used. Most I2C + devices can use either method, but some require one or + the other. + +- SPI Support: CONFIG_SPI + + Enables SPI driver (so far only tested with + SPI EEPROM, also an instance works with Crystal A/D and + D/As on the SACSng board) + + CONFIG_SOFT_SPI + + Enables a software (bit-bang) SPI driver rather than + using hardware support. This is a general purpose + driver that only requires three general I/O port pins + (two outputs, one input) to function. If this is + defined, the board configuration must define several + SPI configuration items (port pins to use, etc). For + an example, see include/configs/sacsng.h. + + CONFIG_SYS_SPI_MXC_WAIT + Timeout for waiting until spi transfer completed. + default: (CONFIG_SYS_HZ/100) /* 10 ms */ + +- FPGA Support: CONFIG_FPGA + + Enables FPGA subsystem. + + CONFIG_FPGA_<vendor> + + Enables support for specific chip vendors. + (ALTERA, XILINX) + + CONFIG_FPGA_<family> + + Enables support for FPGA family. + (SPARTAN2, SPARTAN3, VIRTEX2, CYCLONE2, ACEX1K, ACEX) + + CONFIG_FPGA_COUNT + + Specify the number of FPGA devices to support. + + CONFIG_SYS_FPGA_PROG_FEEDBACK + + Enable printing of hash marks during FPGA configuration. + + CONFIG_SYS_FPGA_CHECK_BUSY + + Enable checks on FPGA configuration interface busy + status by the configuration function. This option + will require a board or device specific function to + be written. + + CONFIG_FPGA_DELAY + + If defined, a function that provides delays in the FPGA + configuration driver. + + CONFIG_SYS_FPGA_CHECK_CTRLC + Allow Control-C to interrupt FPGA configuration + + CONFIG_SYS_FPGA_CHECK_ERROR + + Check for configuration errors during FPGA bitfile + loading. For example, abort during Virtex II + configuration if the INIT_B line goes low (which + indicated a CRC error). + + CONFIG_SYS_FPGA_WAIT_INIT + + Maximum time to wait for the INIT_B line to de-assert + after PROB_B has been de-asserted during a Virtex II + FPGA configuration sequence. The default time is 500 + ms. + + CONFIG_SYS_FPGA_WAIT_BUSY + + Maximum time to wait for BUSY to de-assert during + Virtex II FPGA configuration. The default is 5 ms. + + CONFIG_SYS_FPGA_WAIT_CONFIG + + Time to wait after FPGA configuration. The default is + 200 ms. + +- Configuration Management: + CONFIG_BUILD_TARGET + + Some SoCs need special image types (e.g. U-Boot binary + with a special header) as build targets. By defining + CONFIG_BUILD_TARGET in the SoC / board header, this + special image will be automatically built upon calling + make / buildman. + + CONFIG_IDENT_STRING + + If defined, this string will be added to the U-Boot + version information (U_BOOT_VERSION) + +- Vendor Parameter Protection: + + U-Boot considers the values of the environment + variables "serial#" (Board Serial Number) and + "ethaddr" (Ethernet Address) to be parameters that + are set once by the board vendor / manufacturer, and + protects these variables from casual modification by + the user. Once set, these variables are read-only, + and write or delete attempts are rejected. You can + change this behaviour: + + If CONFIG_ENV_OVERWRITE is #defined in your config + file, the write protection for vendor parameters is + completely disabled. Anybody can change or delete + these parameters. + + Alternatively, if you define _both_ an ethaddr in the + default env _and_ CONFIG_OVERWRITE_ETHADDR_ONCE, a default + Ethernet address is installed in the environment, + which can be changed exactly ONCE by the user. [The + serial# is unaffected by this, i. e. it remains + read-only.] + + The same can be accomplished in a more flexible way + for any variable by configuring the type of access + to allow for those variables in the ".flags" variable + or define CONFIG_ENV_FLAGS_LIST_STATIC. + +- Protected RAM: + CONFIG_PRAM + + Define this variable to enable the reservation of + "protected RAM", i. e. RAM which is not overwritten + by U-Boot. Define CONFIG_PRAM to hold the number of + kB you want to reserve for pRAM. You can overwrite + this default value by defining an environment + variable "pram" to the number of kB you want to + reserve. Note that the board info structure will + still show the full amount of RAM. If pRAM is + reserved, a new environment variable "mem" will + automatically be defined to hold the amount of + remaining RAM in a form that can be passed as boot + argument to Linux, for instance like that: + + setenv bootargs ... mem=\${mem} + saveenv + + This way you can tell Linux not to use this memory, + either, which results in a memory region that will + not be affected by reboots. + + *WARNING* If your board configuration uses automatic + detection of the RAM size, you must make sure that + this memory test is non-destructive. So far, the + following board configurations are known to be + "pRAM-clean": + + IVMS8, IVML24, SPD8xx, + HERMES, IP860, RPXlite, LWMON, + FLAGADM + +- Access to physical memory region (> 4GB) + Some basic support is provided for operations on memory not + normally accessible to U-Boot - e.g. some architectures + support access to more than 4GB of memory on 32-bit + machines using physical address extension or similar. + Define CONFIG_PHYSMEM to access this basic support, which + currently only supports clearing the memory. + +- Error Recovery: + CONFIG_NET_RETRY_COUNT + + This variable defines the number of retries for + network operations like ARP, RARP, TFTP, or BOOTP + before giving up the operation. If not defined, a + default value of 5 is used. + + CONFIG_ARP_TIMEOUT + + Timeout waiting for an ARP reply in milliseconds. + + CONFIG_NFS_TIMEOUT + + Timeout in milliseconds used in NFS protocol. + If you encounter "ERROR: Cannot umount" in nfs command, + try longer timeout such as + #define CONFIG_NFS_TIMEOUT 10000UL + +- Command Interpreter: + CONFIG_SYS_PROMPT_HUSH_PS2 + + This defines the secondary prompt string, which is + printed when the command interpreter needs more input + to complete a command. Usually "> ". + + Note: + + In the current implementation, the local variables + space and global environment variables space are + separated. Local variables are those you define by + simply typing `name=value'. To access a local + variable later on, you have write `$name' or + `${name}'; to execute the contents of a variable + directly type `$name' at the command prompt. + + Global environment variables are those you use + setenv/printenv to work with. To run a command stored + in such a variable, you need to use the run command, + and you must not use the '$' sign to access them. + + To store commands and special characters in a + variable, please use double quotation marks + surrounding the whole text of the variable, instead + of the backslashes before semicolons and special + symbols. + +- Command Line Editing and History: + CONFIG_CMDLINE_PS_SUPPORT + + Enable support for changing the command prompt string + at run-time. Only static string is supported so far. + The string is obtained from environment variables PS1 + and PS2. + +- Default Environment: + CONFIG_EXTRA_ENV_SETTINGS + + Define this to contain any number of null terminated + strings (variable = value pairs) that will be part of + the default environment compiled into the boot image. + + For example, place something like this in your + board's config file: + + #define CONFIG_EXTRA_ENV_SETTINGS \ + "myvar1=value1\0" \ + "myvar2=value2\0" + + Warning: This method is based on knowledge about the + internal format how the environment is stored by the + U-Boot code. This is NOT an official, exported + interface! Although it is unlikely that this format + will change soon, there is no guarantee either. + You better know what you are doing here. + + Note: overly (ab)use of the default environment is + discouraged. Make sure to check other ways to preset + the environment like the "source" command or the + boot command first. + + CONFIG_DELAY_ENVIRONMENT + + Normally the environment is loaded when the board is + initialised so that it is available to U-Boot. This inhibits + that so that the environment is not available until + explicitly loaded later by U-Boot code. With CONFIG_OF_CONTROL + this is instead controlled by the value of + /config/load-environment. + +- Serial Flash support + Usage requires an initial 'sf probe' to define the serial + flash parameters, followed by read/write/erase/update + commands. + + The following defaults may be provided by the platform + to handle the common case when only a single serial + flash is present on the system. + + CONFIG_SF_DEFAULT_BUS Bus identifier + CONFIG_SF_DEFAULT_CS Chip-select + CONFIG_SF_DEFAULT_MODE (see include/spi.h) + CONFIG_SF_DEFAULT_SPEED in Hz + + +- TFTP Fixed UDP Port: + CONFIG_TFTP_PORT + + If this is defined, the environment variable tftpsrcp + is used to supply the TFTP UDP source port value. + If tftpsrcp isn't defined, the normal pseudo-random port + number generator is used. + + Also, the environment variable tftpdstp is used to supply + the TFTP UDP destination port value. If tftpdstp isn't + defined, the normal port 69 is used. + + The purpose for tftpsrcp is to allow a TFTP server to + blindly start the TFTP transfer using the pre-configured + target IP address and UDP port. This has the effect of + "punching through" the (Windows XP) firewall, allowing + the remainder of the TFTP transfer to proceed normally. + A better solution is to properly configure the firewall, + but sometimes that is not allowed. + +- Show boot progress: + CONFIG_SHOW_BOOT_PROGRESS + + Defining this option allows to add some board- + specific code (calling a user-provided function + "show_boot_progress(int)") that enables you to show + the system's boot progress on some display (for + example, some LED's) on your board. At the moment, + the following checkpoints are implemented: + + +Legacy uImage format: + + Arg Where When + 1 common/cmd_bootm.c before attempting to boot an image + -1 common/cmd_bootm.c Image header has bad magic number + 2 common/cmd_bootm.c Image header has correct magic number + -2 common/cmd_bootm.c Image header has bad checksum + 3 common/cmd_bootm.c Image header has correct checksum + -3 common/cmd_bootm.c Image data has bad checksum + 4 common/cmd_bootm.c Image data has correct checksum + -4 common/cmd_bootm.c Image is for unsupported architecture + 5 common/cmd_bootm.c Architecture check OK + -5 common/cmd_bootm.c Wrong Image Type (not kernel, multi) + 6 common/cmd_bootm.c Image Type check OK + -6 common/cmd_bootm.c gunzip uncompression error + -7 common/cmd_bootm.c Unimplemented compression type + 7 common/cmd_bootm.c Uncompression OK + 8 common/cmd_bootm.c No uncompress/copy overwrite error + -9 common/cmd_bootm.c Unsupported OS (not Linux, BSD, VxWorks, QNX) + + 9 common/image.c Start initial ramdisk verification + -10 common/image.c Ramdisk header has bad magic number + -11 common/image.c Ramdisk header has bad checksum + 10 common/image.c Ramdisk header is OK + -12 common/image.c Ramdisk data has bad checksum + 11 common/image.c Ramdisk data has correct checksum + 12 common/image.c Ramdisk verification complete, start loading + -13 common/image.c Wrong Image Type (not PPC Linux ramdisk) + 13 common/image.c Start multifile image verification + 14 common/image.c No initial ramdisk, no multifile, continue. + + 15 arch/<arch>/lib/bootm.c All preparation done, transferring control to OS + + -30 arch/powerpc/lib/board.c Fatal error, hang the system + -31 post/post.c POST test failed, detected by post_output_backlog() + -32 post/post.c POST test failed, detected by post_run_single() + + 34 common/cmd_doc.c before loading a Image from a DOC device + -35 common/cmd_doc.c Bad usage of "doc" command + 35 common/cmd_doc.c correct usage of "doc" command + -36 common/cmd_doc.c No boot device + 36 common/cmd_doc.c correct boot device + -37 common/cmd_doc.c Unknown Chip ID on boot device + 37 common/cmd_doc.c correct chip ID found, device available + -38 common/cmd_doc.c Read Error on boot device + 38 common/cmd_doc.c reading Image header from DOC device OK + -39 common/cmd_doc.c Image header has bad magic number + 39 common/cmd_doc.c Image header has correct magic number + -40 common/cmd_doc.c Error reading Image from DOC device + 40 common/cmd_doc.c Image header has correct magic number + 41 common/cmd_ide.c before loading a Image from a IDE device + -42 common/cmd_ide.c Bad usage of "ide" command + 42 common/cmd_ide.c correct usage of "ide" command + -43 common/cmd_ide.c No boot device + 43 common/cmd_ide.c boot device found + -44 common/cmd_ide.c Device not available + 44 common/cmd_ide.c Device available + -45 common/cmd_ide.c wrong partition selected + 45 common/cmd_ide.c partition selected + -46 common/cmd_ide.c Unknown partition table + 46 common/cmd_ide.c valid partition table found + -47 common/cmd_ide.c Invalid partition type + 47 common/cmd_ide.c correct partition type + -48 common/cmd_ide.c Error reading Image Header on boot device + 48 common/cmd_ide.c reading Image Header from IDE device OK + -49 common/cmd_ide.c Image header has bad magic number + 49 common/cmd_ide.c Image header has correct magic number + -50 common/cmd_ide.c Image header has bad checksum + 50 common/cmd_ide.c Image header has correct checksum + -51 common/cmd_ide.c Error reading Image from IDE device + 51 common/cmd_ide.c reading Image from IDE device OK + 52 common/cmd_nand.c before loading a Image from a NAND device + -53 common/cmd_nand.c Bad usage of "nand" command + 53 common/cmd_nand.c correct usage of "nand" command + -54 common/cmd_nand.c No boot device + 54 common/cmd_nand.c boot device found + -55 common/cmd_nand.c Unknown Chip ID on boot device + 55 common/cmd_nand.c correct chip ID found, device available + -56 common/cmd_nand.c Error reading Image Header on boot device + 56 common/cmd_nand.c reading Image Header from NAND device OK + -57 common/cmd_nand.c Image header has bad magic number + 57 common/cmd_nand.c Image header has correct magic number + -58 common/cmd_nand.c Error reading Image from NAND device + 58 common/cmd_nand.c reading Image from NAND device OK + + -60 common/env_common.c Environment has a bad CRC, using default + + 64 net/eth.c starting with Ethernet configuration. + -64 net/eth.c no Ethernet found. + 65 net/eth.c Ethernet found. + + -80 common/cmd_net.c usage wrong + 80 common/cmd_net.c before calling net_loop() + -81 common/cmd_net.c some error in net_loop() occurred + 81 common/cmd_net.c net_loop() back without error + -82 common/cmd_net.c size == 0 (File with size 0 loaded) + 82 common/cmd_net.c trying automatic boot + 83 common/cmd_net.c running "source" command + -83 common/cmd_net.c some error in automatic boot or "source" command + 84 common/cmd_net.c end without errors + +FIT uImage format: + + Arg Where When + 100 common/cmd_bootm.c Kernel FIT Image has correct format + -100 common/cmd_bootm.c Kernel FIT Image has incorrect format + 101 common/cmd_bootm.c No Kernel subimage unit name, using configuration + -101 common/cmd_bootm.c Can't get configuration for kernel subimage + 102 common/cmd_bootm.c Kernel unit name specified + -103 common/cmd_bootm.c Can't get kernel subimage node offset + 103 common/cmd_bootm.c Found configuration node + 104 common/cmd_bootm.c Got kernel subimage node offset + -104 common/cmd_bootm.c Kernel subimage hash verification failed + 105 common/cmd_bootm.c Kernel subimage hash verification OK + -105 common/cmd_bootm.c Kernel subimage is for unsupported architecture + 106 common/cmd_bootm.c Architecture check OK + -106 common/cmd_bootm.c Kernel subimage has wrong type + 107 common/cmd_bootm.c Kernel subimage type OK + -107 common/cmd_bootm.c Can't get kernel subimage data/size + 108 common/cmd_bootm.c Got kernel subimage data/size + -108 common/cmd_bootm.c Wrong image type (not legacy, FIT) + -109 common/cmd_bootm.c Can't get kernel subimage type + -110 common/cmd_bootm.c Can't get kernel subimage comp + -111 common/cmd_bootm.c Can't get kernel subimage os + -112 common/cmd_bootm.c Can't get kernel subimage load address + -113 common/cmd_bootm.c Image uncompress/copy overwrite error + + 120 common/image.c Start initial ramdisk verification + -120 common/image.c Ramdisk FIT image has incorrect format + 121 common/image.c Ramdisk FIT image has correct format + 122 common/image.c No ramdisk subimage unit name, using configuration + -122 common/image.c Can't get configuration for ramdisk subimage + 123 common/image.c Ramdisk unit name specified + -124 common/image.c Can't get ramdisk subimage node offset + 125 common/image.c Got ramdisk subimage node offset + -125 common/image.c Ramdisk subimage hash verification failed + 126 common/image.c Ramdisk subimage hash verification OK + -126 common/image.c Ramdisk subimage for unsupported architecture + 127 common/image.c Architecture check OK + -127 common/image.c Can't get ramdisk subimage data/size + 128 common/image.c Got ramdisk subimage data/size + 129 common/image.c Can't get ramdisk load address + -129 common/image.c Got ramdisk load address + + -130 common/cmd_doc.c Incorrect FIT image format + 131 common/cmd_doc.c FIT image format OK + + -140 common/cmd_ide.c Incorrect FIT image format + 141 common/cmd_ide.c FIT image format OK + + -150 common/cmd_nand.c Incorrect FIT image format + 151 common/cmd_nand.c FIT image format OK + +- Standalone program support: + CONFIG_STANDALONE_LOAD_ADDR + + This option defines a board specific value for the + address where standalone program gets loaded, thus + overwriting the architecture dependent default + settings. + +- Frame Buffer Address: + CONFIG_FB_ADDR + + Define CONFIG_FB_ADDR if you want to use specific + address for frame buffer. This is typically the case + when using a graphics controller has separate video + memory. U-Boot will then place the frame buffer at + the given address instead of dynamically reserving it + in system RAM by calling lcd_setmem(), which grabs + the memory for the frame buffer depending on the + configured panel size. + + Please see board_init_f function. + +- Automatic software updates via TFTP server + CONFIG_UPDATE_TFTP + CONFIG_UPDATE_TFTP_CNT_MAX + CONFIG_UPDATE_TFTP_MSEC_MAX + + These options enable and control the auto-update feature; + for a more detailed description refer to doc/README.update. + +- MTD Support (mtdparts command, UBI support) + CONFIG_MTD_UBI_WL_THRESHOLD + This parameter defines the maximum difference between the highest + erase counter value and the lowest erase counter value of eraseblocks + of UBI devices. When this threshold is exceeded, UBI starts performing + wear leveling by means of moving data from eraseblock with low erase + counter to eraseblocks with high erase counter. + + The default value should be OK for SLC NAND flashes, NOR flashes and + other flashes which have eraseblock life-cycle 100000 or more. + However, in case of MLC NAND flashes which typically have eraseblock + life-cycle less than 10000, the threshold should be lessened (e.g., + to 128 or 256, although it does not have to be power of 2). + + default: 4096 + + CONFIG_MTD_UBI_BEB_LIMIT + This option specifies the maximum bad physical eraseblocks UBI + expects on the MTD device (per 1024 eraseblocks). If the + underlying flash does not admit of bad eraseblocks (e.g. NOR + flash), this value is ignored. + + NAND datasheets often specify the minimum and maximum NVM + (Number of Valid Blocks) for the flashes' endurance lifetime. + The maximum expected bad eraseblocks per 1024 eraseblocks + then can be calculated as "1024 * (1 - MinNVB / MaxNVB)", + which gives 20 for most NANDs (MaxNVB is basically the total + count of eraseblocks on the chip). + + To put it differently, if this value is 20, UBI will try to + reserve about 1.9% of physical eraseblocks for bad blocks + handling. And that will be 1.9% of eraseblocks on the entire + NAND chip, not just the MTD partition UBI attaches. This means + that if you have, say, a NAND flash chip admits maximum 40 bad + eraseblocks, and it is split on two MTD partitions of the same + size, UBI will reserve 40 eraseblocks when attaching a + partition. + + default: 20 + + CONFIG_MTD_UBI_FASTMAP + Fastmap is a mechanism which allows attaching an UBI device + in nearly constant time. Instead of scanning the whole MTD device it + only has to locate a checkpoint (called fastmap) on the device. + The on-flash fastmap contains all information needed to attach + the device. Using fastmap makes only sense on large devices where + attaching by scanning takes long. UBI will not automatically install + a fastmap on old images, but you can set the UBI parameter + CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT to 1 if you want so. Please note + that fastmap-enabled images are still usable with UBI implementations + without fastmap support. On typical flash devices the whole fastmap + fits into one PEB. UBI will reserve PEBs to hold two fastmaps. + + CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT + Set this parameter to enable fastmap automatically on images + without a fastmap. + default: 0 + + CONFIG_MTD_UBI_FM_DEBUG + Enable UBI fastmap debug + default: 0 + +- SPL framework + CONFIG_SPL + Enable building of SPL globally. + + CONFIG_SPL_LDSCRIPT + LDSCRIPT for linking the SPL binary. + + CONFIG_SPL_MAX_FOOTPRINT + Maximum size in memory allocated to the SPL, BSS included. + When defined, the linker checks that the actual memory + used by SPL from _start to __bss_end does not exceed it. + CONFIG_SPL_MAX_FOOTPRINT and CONFIG_SPL_BSS_MAX_SIZE + must not be both defined at the same time. + + CONFIG_SPL_MAX_SIZE + Maximum size of the SPL image (text, data, rodata, and + linker lists sections), BSS excluded. + When defined, the linker checks that the actual size does + not exceed it. + + CONFIG_SPL_TEXT_BASE + TEXT_BASE for linking the SPL binary. + + CONFIG_SPL_RELOC_TEXT_BASE + Address to relocate to. If unspecified, this is equal to + CONFIG_SPL_TEXT_BASE (i.e. no relocation is done). + + CONFIG_SPL_BSS_START_ADDR + Link address for the BSS within the SPL binary. + + CONFIG_SPL_BSS_MAX_SIZE + Maximum size in memory allocated to the SPL BSS. + When defined, the linker checks that the actual memory used + by SPL from __bss_start to __bss_end does not exceed it. + CONFIG_SPL_MAX_FOOTPRINT and CONFIG_SPL_BSS_MAX_SIZE + must not be both defined at the same time. + + CONFIG_SPL_STACK + Adress of the start of the stack SPL will use + + CONFIG_SPL_PANIC_ON_RAW_IMAGE + When defined, SPL will panic() if the image it has + loaded does not have a signature. + Defining this is useful when code which loads images + in SPL cannot guarantee that absolutely all read errors + will be caught. + An example is the LPC32XX MLC NAND driver, which will + consider that a completely unreadable NAND block is bad, + and thus should be skipped silently. + + CONFIG_SPL_RELOC_STACK + Adress of the start of the stack SPL will use after + relocation. If unspecified, this is equal to + CONFIG_SPL_STACK. + + CONFIG_SYS_SPL_MALLOC_START + Starting address of the malloc pool used in SPL. + When this option is set the full malloc is used in SPL and + it is set up by spl_init() and before that, the simple malloc() + can be used if CONFIG_SYS_MALLOC_F is defined. + + CONFIG_SYS_SPL_MALLOC_SIZE + The size of the malloc pool used in SPL. + + CONFIG_SPL_OS_BOOT + Enable booting directly to an OS from SPL. + See also: doc/README.falcon + + CONFIG_SPL_DISPLAY_PRINT + For ARM, enable an optional function to print more information + about the running system. + + CONFIG_SPL_INIT_MINIMAL + Arch init code should be built for a very small image + + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION + Partition on the MMC to load U-Boot from when the MMC is being + used in raw mode + + CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR + Sector to load kernel uImage from when MMC is being + used in raw mode (for Falcon mode) + + CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, + CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS + Sector and number of sectors to load kernel argument + parameters from when MMC is being used in raw mode + (for falcon mode) + + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION + Partition on the MMC to load U-Boot from when the MMC is being + used in fs mode + + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME + Filename to read to load U-Boot when reading from filesystem + + CONFIG_SPL_FS_LOAD_KERNEL_NAME + Filename to read to load kernel uImage when reading + from filesystem (for Falcon mode) + + CONFIG_SPL_FS_LOAD_ARGS_NAME + Filename to read to load kernel argument parameters + when reading from filesystem (for Falcon mode) + + CONFIG_SPL_MPC83XX_WAIT_FOR_NAND + Set this for NAND SPL on PPC mpc83xx targets, so that + start.S waits for the rest of the SPL to load before + continuing (the hardware starts execution after just + loading the first page rather than the full 4K). + + CONFIG_SPL_SKIP_RELOCATE + Avoid SPL relocation + + CONFIG_SPL_NAND_BASE + Include nand_base.c in the SPL. Requires + CONFIG_SPL_NAND_DRIVERS. + + CONFIG_SPL_NAND_DRIVERS + SPL uses normal NAND drivers, not minimal drivers. + + CONFIG_SPL_NAND_IDENT + SPL uses the chip ID list to identify the NAND flash. + Requires CONFIG_SPL_NAND_BASE. + + CONFIG_SPL_NAND_ECC + Include standard software ECC in the SPL + + CONFIG_SPL_NAND_SIMPLE + Support for NAND boot using simple NAND drivers that + expose the cmd_ctrl() interface. + + CONFIG_SPL_UBI + Support for a lightweight UBI (fastmap) scanner and + loader + + CONFIG_SPL_NAND_RAW_ONLY + Support to boot only raw u-boot.bin images. Use this only + if you need to save space. + + CONFIG_SPL_COMMON_INIT_DDR + Set for common ddr init with serial presence detect in + SPL binary. + + CONFIG_SYS_NAND_5_ADDR_CYCLE, CONFIG_SYS_NAND_PAGE_COUNT, + CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE, + CONFIG_SYS_NAND_BLOCK_SIZE, CONFIG_SYS_NAND_BAD_BLOCK_POS, + CONFIG_SYS_NAND_ECCPOS, CONFIG_SYS_NAND_ECCSIZE, + CONFIG_SYS_NAND_ECCBYTES + Defines the size and behavior of the NAND that SPL uses + to read U-Boot + + CONFIG_SPL_NAND_BOOT + Add support NAND boot + + CONFIG_SYS_NAND_U_BOOT_OFFS + Location in NAND to read U-Boot from + + CONFIG_SYS_NAND_U_BOOT_DST + Location in memory to load U-Boot to + + CONFIG_SYS_NAND_U_BOOT_SIZE + Size of image to load + + CONFIG_SYS_NAND_U_BOOT_START + Entry point in loaded image to jump to + + CONFIG_SYS_NAND_HW_ECC_OOBFIRST + Define this if you need to first read the OOB and then the + data. This is used, for example, on davinci platforms. + + CONFIG_SPL_RAM_DEVICE + Support for running image already present in ram, in SPL binary + + CONFIG_SPL_PAD_TO + Image offset to which the SPL should be padded before appending + the SPL payload. By default, this is defined as + CONFIG_SPL_MAX_SIZE, or 0 if CONFIG_SPL_MAX_SIZE is undefined. + CONFIG_SPL_PAD_TO must be either 0, meaning to append the SPL + payload without any padding, or >= CONFIG_SPL_MAX_SIZE. + + CONFIG_SPL_TARGET + Final target image containing SPL and payload. Some SPLs + use an arch-specific makefile fragment instead, for + example if more than one image needs to be produced. + + CONFIG_SPL_FIT_PRINT + Printing information about a FIT image adds quite a bit of + code to SPL. So this is normally disabled in SPL. Use this + option to re-enable it. This will affect the output of the + bootm command when booting a FIT image. + +- TPL framework + CONFIG_TPL + Enable building of TPL globally. + + CONFIG_TPL_PAD_TO + Image offset to which the TPL should be padded before appending + the TPL payload. By default, this is defined as + CONFIG_SPL_MAX_SIZE, or 0 if CONFIG_SPL_MAX_SIZE is undefined. + CONFIG_SPL_PAD_TO must be either 0, meaning to append the SPL + payload without any padding, or >= CONFIG_SPL_MAX_SIZE. + +- Interrupt support (PPC): + + There are common interrupt_init() and timer_interrupt() + for all PPC archs. interrupt_init() calls interrupt_init_cpu() + for CPU specific initialization. interrupt_init_cpu() + should set decrementer_count to appropriate value. If + CPU resets decrementer automatically after interrupt + (ppc4xx) it should set decrementer_count to zero. + timer_interrupt() calls timer_interrupt_cpu() for CPU + specific handling. If board has watchdog / status_led + / other_activity_monitor it works automatically from + general timer_interrupt(). + + +Board initialization settings: +------------------------------ + +During Initialization u-boot calls a number of board specific functions +to allow the preparation of board specific prerequisites, e.g. pin setup +before drivers are initialized. To enable these callbacks the +following configuration macros have to be defined. Currently this is +architecture specific, so please check arch/your_architecture/lib/board.c +typically in board_init_f() and board_init_r(). + +- CONFIG_BOARD_EARLY_INIT_F: Call board_early_init_f() +- CONFIG_BOARD_EARLY_INIT_R: Call board_early_init_r() +- CONFIG_BOARD_LATE_INIT: Call board_late_init() +- CONFIG_BOARD_POSTCLK_INIT: Call board_postclk_init() + +Configuration Settings: +----------------------- + +- CONFIG_SYS_SUPPORT_64BIT_DATA: Defined automatically if compiled as 64-bit. + Optionally it can be defined to support 64-bit memory commands. + +- CONFIG_SYS_LONGHELP: Defined when you want long help messages included; + undefine this when you're short of memory. + +- CONFIG_SYS_HELP_CMD_WIDTH: Defined when you want to override the default + width of the commands listed in the 'help' command output. + +- CONFIG_SYS_PROMPT: This is what U-Boot prints on the console to + prompt for user input. + +- CONFIG_SYS_CBSIZE: Buffer size for input from the Console + +- CONFIG_SYS_PBSIZE: Buffer size for Console output + +- CONFIG_SYS_MAXARGS: max. Number of arguments accepted for monitor commands + +- CONFIG_SYS_BARGSIZE: Buffer size for Boot Arguments which are passed to + the application (usually a Linux kernel) when it is + booted + +- CONFIG_SYS_BAUDRATE_TABLE: + List of legal baudrate settings for this board. + +- CONFIG_SYS_MEMTEST_START, CONFIG_SYS_MEMTEST_END: + Begin and End addresses of the area used by the + simple memory test. + +- CONFIG_SYS_MEMTEST_SCRATCH: + Scratch address used by the alternate memory test + You only need to set this if address zero isn't writeable + +- CONFIG_SYS_MEM_RESERVE_SECURE + Only implemented for ARMv8 for now. + If defined, the size of CONFIG_SYS_MEM_RESERVE_SECURE memory + is substracted from total RAM and won't be reported to OS. + This memory can be used as secure memory. A variable + gd->arch.secure_ram is used to track the location. In systems + the RAM base is not zero, or RAM is divided into banks, + this variable needs to be recalcuated to get the address. + +- CONFIG_SYS_MEM_TOP_HIDE: + If CONFIG_SYS_MEM_TOP_HIDE is defined in the board config header, + this specified memory area will get subtracted from the top + (end) of RAM and won't get "touched" at all by U-Boot. By + fixing up gd->ram_size the Linux kernel should gets passed + the now "corrected" memory size and won't touch it either. + This should work for arch/ppc and arch/powerpc. Only Linux + board ports in arch/powerpc with bootwrapper support that + recalculate the memory size from the SDRAM controller setup + will have to get fixed in Linux additionally. + + This option can be used as a workaround for the 440EPx/GRx + CHIP 11 errata where the last 256 bytes in SDRAM shouldn't + be touched. + + WARNING: Please make sure that this value is a multiple of + the Linux page size (normally 4k). If this is not the case, + then the end address of the Linux memory will be located at a + non page size aligned address and this could cause major + problems. + +- CONFIG_SYS_LOADS_BAUD_CHANGE: + Enable temporary baudrate change while serial download + +- CONFIG_SYS_SDRAM_BASE: + Physical start address of SDRAM. _Must_ be 0 here. + +- CONFIG_SYS_FLASH_BASE: + Physical start address of Flash memory. + +- CONFIG_SYS_MONITOR_BASE: + Physical start address of boot monitor code (set by + make config files to be same as the text base address + (CONFIG_SYS_TEXT_BASE) used when linking) - same as + CONFIG_SYS_FLASH_BASE when booting from flash. + +- CONFIG_SYS_MONITOR_LEN: + Size of memory reserved for monitor code, used to + determine _at_compile_time_ (!) if the environment is + embedded within the U-Boot image, or in a separate + flash sector. + +- CONFIG_SYS_MALLOC_LEN: + Size of DRAM reserved for malloc() use. + +- CONFIG_SYS_MALLOC_F_LEN + Size of the malloc() pool for use before relocation. If + this is defined, then a very simple malloc() implementation + will become available before relocation. The address is just + below the global data, and the stack is moved down to make + space. + + This feature allocates regions with increasing addresses + within the region. calloc() is supported, but realloc() + is not available. free() is supported but does nothing. + The memory will be freed (or in fact just forgotten) when + U-Boot relocates itself. + +- CONFIG_SYS_MALLOC_SIMPLE + Provides a simple and small malloc() and calloc() for those + boards which do not use the full malloc in SPL (which is + enabled with CONFIG_SYS_SPL_MALLOC_START). + +- CONFIG_SYS_NONCACHED_MEMORY: + Size of non-cached memory area. This area of memory will be + typically located right below the malloc() area and mapped + uncached in the MMU. This is useful for drivers that would + otherwise require a lot of explicit cache maintenance. For + some drivers it's also impossible to properly maintain the + cache. For example if the regions that need to be flushed + are not a multiple of the cache-line size, *and* padding + cannot be allocated between the regions to align them (i.e. + if the HW requires a contiguous array of regions, and the + size of each region is not cache-aligned), then a flush of + one region may result in overwriting data that hardware has + written to another region in the same cache-line. This can + happen for example in network drivers where descriptors for + buffers are typically smaller than the CPU cache-line (e.g. + 16 bytes vs. 32 or 64 bytes). + + Non-cached memory is only supported on 32-bit ARM at present. + +- CONFIG_SYS_BOOTM_LEN: + Normally compressed uImages are limited to an + uncompressed size of 8 MBytes. If this is not enough, + you can define CONFIG_SYS_BOOTM_LEN in your board config file + to adjust this setting to your needs. + +- CONFIG_SYS_BOOTMAPSZ: + Maximum size of memory mapped by the startup code of + the Linux kernel; all data that must be processed by + the Linux kernel (bd_info, boot arguments, FDT blob if + used) must be put below this limit, unless "bootm_low" + environment variable is defined and non-zero. In such case + all data for the Linux kernel must be between "bootm_low" + and "bootm_low" + CONFIG_SYS_BOOTMAPSZ. The environment + variable "bootm_mapsize" will override the value of + CONFIG_SYS_BOOTMAPSZ. If CONFIG_SYS_BOOTMAPSZ is undefined, + then the value in "bootm_size" will be used instead. + +- CONFIG_SYS_BOOT_RAMDISK_HIGH: + Enable initrd_high functionality. If defined then the + initrd_high feature is enabled and the bootm ramdisk subcommand + is enabled. + +- CONFIG_SYS_BOOT_GET_CMDLINE: + Enables allocating and saving kernel cmdline in space between + "bootm_low" and "bootm_low" + BOOTMAPSZ. + +- CONFIG_SYS_BOOT_GET_KBD: + Enables allocating and saving a kernel copy of the bd_info in + space between "bootm_low" and "bootm_low" + BOOTMAPSZ. + +- CONFIG_SYS_MAX_FLASH_BANKS: + Max number of Flash memory banks + +- CONFIG_SYS_MAX_FLASH_SECT: + Max number of sectors on a Flash chip + +- CONFIG_SYS_FLASH_ERASE_TOUT: + Timeout for Flash erase operations (in ms) + +- CONFIG_SYS_FLASH_WRITE_TOUT: + Timeout for Flash write operations (in ms) + +- CONFIG_SYS_FLASH_LOCK_TOUT + Timeout for Flash set sector lock bit operation (in ms) + +- CONFIG_SYS_FLASH_UNLOCK_TOUT + Timeout for Flash clear lock bits operation (in ms) + +- CONFIG_SYS_FLASH_PROTECTION + If defined, hardware flash sectors protection is used + instead of U-Boot software protection. + +- CONFIG_SYS_DIRECT_FLASH_TFTP: + + Enable TFTP transfers directly to flash memory; + without this option such a download has to be + performed in two steps: (1) download to RAM, and (2) + copy from RAM to flash. + + The two-step approach is usually more reliable, since + you can check if the download worked before you erase + the flash, but in some situations (when system RAM is + too limited to allow for a temporary copy of the + downloaded image) this option may be very useful. + +- CONFIG_SYS_FLASH_CFI: + Define if the flash driver uses extra elements in the + common flash structure for storing flash geometry. + +- CONFIG_FLASH_CFI_DRIVER + This option also enables the building of the cfi_flash driver + in the drivers directory + +- CONFIG_FLASH_CFI_MTD + This option enables the building of the cfi_mtd driver + in the drivers directory. The driver exports CFI flash + to the MTD layer. + +- CONFIG_SYS_FLASH_USE_BUFFER_WRITE + Use buffered writes to flash. + +- CONFIG_FLASH_SPANSION_S29WS_N + s29ws-n MirrorBit flash has non-standard addresses for buffered + write commands. + +- CONFIG_SYS_FLASH_QUIET_TEST + If this option is defined, the common CFI flash doesn't + print it's warning upon not recognized FLASH banks. This + is useful, if some of the configured banks are only + optionally available. + +- CONFIG_FLASH_SHOW_PROGRESS + If defined (must be an integer), print out countdown + digits and dots. Recommended value: 45 (9..1) for 80 + column displays, 15 (3..1) for 40 column displays. + +- CONFIG_FLASH_VERIFY + If defined, the content of the flash (destination) is compared + against the source after the write operation. An error message + will be printed when the contents are not identical. + Please note that this option is useless in nearly all cases, + since such flash programming errors usually are detected earlier + while unprotecting/erasing/programming. Please only enable + this option if you really know what you are doing. + +- CONFIG_SYS_RX_ETH_BUFFER: + Defines the number of Ethernet receive buffers. On some + Ethernet controllers it is recommended to set this value + to 8 or even higher (EEPRO100 or 405 EMAC), since all + buffers can be full shortly after enabling the interface + on high Ethernet traffic. + Defaults to 4 if not defined. + +- CONFIG_ENV_MAX_ENTRIES + + Maximum number of entries in the hash table that is used + internally to store the environment settings. The default + setting is supposed to be generous and should work in most + cases. This setting can be used to tune behaviour; see + lib/hashtable.c for details. + +- CONFIG_ENV_FLAGS_LIST_DEFAULT +- CONFIG_ENV_FLAGS_LIST_STATIC + Enable validation of the values given to environment variables when + calling env set. Variables can be restricted to only decimal, + hexadecimal, or boolean. If CONFIG_CMD_NET is also defined, + the variables can also be restricted to IP address or MAC address. + + The format of the list is: + type_attribute = [s|d|x|b|i|m] + access_attribute = [a|r|o|c] + attributes = type_attribute[access_attribute] + entry = variable_name[:attributes] + list = entry[,list] + + The type attributes are: + s - String (default) + d - Decimal + x - Hexadecimal + b - Boolean ([1yYtT|0nNfF]) + i - IP address + m - MAC address + + The access attributes are: + a - Any (default) + r - Read-only + o - Write-once + c - Change-default + + - CONFIG_ENV_FLAGS_LIST_DEFAULT + Define this to a list (string) to define the ".flags" + environment variable in the default or embedded environment. + + - CONFIG_ENV_FLAGS_LIST_STATIC + Define this to a list (string) to define validation that + should be done if an entry is not found in the ".flags" + environment variable. To override a setting in the static + list, simply add an entry for the same variable name to the + ".flags" variable. + + If CONFIG_REGEX is defined, the variable_name above is evaluated as a + regular expression. This allows multiple variables to define the same + flags without explicitly listing them for each variable. + +- CONFIG_ENV_ACCESS_IGNORE_FORCE + If defined, don't allow the -f switch to env set override variable + access flags. + +The following definitions that deal with the placement and management +of environment data (variable area); in general, we support the +following configurations: + +- CONFIG_BUILD_ENVCRC: + + Builds up envcrc with the target environment so that external utils + may easily extract it and embed it in final U-Boot images. + +BE CAREFUL! The first access to the environment happens quite early +in U-Boot initialization (when we try to get the setting of for the +console baudrate). You *MUST* have mapped your NVRAM area then, or +U-Boot will hang. + +Please note that even with NVRAM we still use a copy of the +environment in RAM: we could work on NVRAM directly, but we want to +keep settings there always unmodified except somebody uses "saveenv" +to save the current settings. + +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 or PCIE link, +but it can not erase, write this NOR flash by SRIO or PCIE interface. + +- CONFIG_NAND_ENV_DST + + Defines address in RAM to which the nand_spl code should copy the + environment. If redundant environment is used, it will be copied to + CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE. + +Please note that the environment is read-only until the monitor +has been relocated to RAM and a RAM copy of the environment has been +created; also, when using EEPROM you will have to use env_get_f() +until then to read environment variables. + +The environment is protected by a CRC32 checksum. Before the monitor +is relocated into RAM, as a result of a bad CRC you will be working +with the compiled-in default environment - *silently*!!! [This is +necessary, because the first environment variable we need is the +"baudrate" setting for the console - if we have a bad CRC, we don't +have any device yet where we could complain.] + +Note: once the monitor has been relocated, then it will complain if +the default environment is used; a new CRC is computed as soon as you +use the "saveenv" command to store a valid environment. + +- CONFIG_SYS_FAULT_ECHO_LINK_DOWN: + Echo the inverted Ethernet link state to the fault LED. + + Note: If this option is active, then CONFIG_SYS_FAULT_MII_ADDR + also needs to be defined. + +- CONFIG_SYS_FAULT_MII_ADDR: + MII address of the PHY to check for the Ethernet link state. + +- CONFIG_NS16550_MIN_FUNCTIONS: + Define this if you desire to only have use of the NS16550_init + and NS16550_putc functions for the serial driver located at + drivers/serial/ns16550.c. This option is useful for saving + space for already greatly restricted images, including but not + limited to NAND_SPL configurations. + +- CONFIG_DISPLAY_BOARDINFO + Display information about the board that U-Boot is running on + when U-Boot starts up. The board function checkboard() is called + to do this. + +- CONFIG_DISPLAY_BOARDINFO_LATE + Similar to the previous option, but display this information + later, once stdio is running and output goes to the LCD, if + present. + +- CONFIG_BOARD_SIZE_LIMIT: + Maximum size of the U-Boot image. When defined, the + build system checks that the actual size does not + exceed it. + +Low Level (hardware related) configuration options: +--------------------------------------------------- + +- CONFIG_SYS_CACHELINE_SIZE: + Cache Line Size of the CPU. + +- CONFIG_SYS_CCSRBAR_DEFAULT: + Default (power-on reset) physical address of CCSR on Freescale + PowerPC SOCs. + +- CONFIG_SYS_CCSRBAR: + Virtual address of CCSR. On a 32-bit build, this is typically + the same value as CONFIG_SYS_CCSRBAR_DEFAULT. + +- CONFIG_SYS_CCSRBAR_PHYS: + Physical address of CCSR. CCSR can be relocated to a new + physical address, if desired. In this case, this macro should + be set to that address. Otherwise, it should be set to the + same value as CONFIG_SYS_CCSRBAR_DEFAULT. For example, CCSR + is typically relocated on 36-bit builds. It is recommended + that this macro be defined via the _HIGH and _LOW macros: + + #define CONFIG_SYS_CCSRBAR_PHYS ((CONFIG_SYS_CCSRBAR_PHYS_HIGH + * 1ull) << 32 | CONFIG_SYS_CCSRBAR_PHYS_LOW) + +- CONFIG_SYS_CCSRBAR_PHYS_HIGH: + Bits 33-36 of CONFIG_SYS_CCSRBAR_PHYS. This value is typically + either 0 (32-bit build) or 0xF (36-bit build). This macro is + used in assembly code, so it must not contain typecasts or + integer size suffixes (e.g. "ULL"). + +- CONFIG_SYS_CCSRBAR_PHYS_LOW: + Lower 32-bits of CONFIG_SYS_CCSRBAR_PHYS. This macro is + used in assembly code, so it must not contain typecasts or + integer size suffixes (e.g. "ULL"). + +- CONFIG_SYS_CCSR_DO_NOT_RELOCATE: + If this macro is defined, then CONFIG_SYS_CCSRBAR_PHYS will be + forced to a value that ensures that CCSR is not relocated. + +- Floppy Disk Support: + CONFIG_SYS_FDC_DRIVE_NUMBER + + the default drive number (default value 0) + + CONFIG_SYS_ISA_IO_STRIDE + + defines the spacing between FDC chipset registers + (default value 1) + + CONFIG_SYS_ISA_IO_OFFSET + + defines the offset of register from address. It + depends on which part of the data bus is connected to + the FDC chipset. (default value 0) + + If CONFIG_SYS_ISA_IO_STRIDE CONFIG_SYS_ISA_IO_OFFSET and + CONFIG_SYS_FDC_DRIVE_NUMBER are undefined, they take their + default value. + + if CONFIG_SYS_FDC_HW_INIT is defined, then the function + fdc_hw_init() is called at the beginning of the FDC + setup. fdc_hw_init() must be provided by the board + source code. It is used to make hardware-dependent + initializations. + +- CONFIG_IDE_AHB: + Most IDE controllers were designed to be connected with PCI + interface. Only few of them were designed for AHB interface. + When software is doing ATA command and data transfer to + IDE devices through IDE-AHB controller, some additional + registers accessing to these kind of IDE-AHB controller + is required. + +- CONFIG_SYS_IMMR: Physical address of the Internal Memory. + DO NOT CHANGE unless you know exactly what you're + doing! (11-4) [MPC8xx systems only] + +- CONFIG_SYS_INIT_RAM_ADDR: + + Start address of memory area that can be used for + initial data and stack; please note that this must be + writable memory that is working WITHOUT special + initialization, i. e. you CANNOT use normal RAM which + will become available only after programming the + memory controller and running certain initialization + sequences. + + U-Boot uses the following memory types: + - MPC8xx: IMMR (internal memory of the CPU) + +- CONFIG_SYS_GBL_DATA_OFFSET: + + Offset of the initial data structure in the memory + area defined by CONFIG_SYS_INIT_RAM_ADDR. Usually + CONFIG_SYS_GBL_DATA_OFFSET is chosen such that the initial + data is located at the end of the available space + (sometimes written as (CONFIG_SYS_INIT_RAM_SIZE - + GENERATED_GBL_DATA_SIZE), and the initial stack is just + below that area (growing from (CONFIG_SYS_INIT_RAM_ADDR + + CONFIG_SYS_GBL_DATA_OFFSET) downward. + + Note: + On the MPC824X (or other systems that use the data + cache for initial memory) the address chosen for + CONFIG_SYS_INIT_RAM_ADDR is basically arbitrary - it must + point to an otherwise UNUSED address space between + the top of RAM and the start of the PCI space. + +- CONFIG_SYS_SCCR: System Clock and reset Control Register (15-27) + +- CONFIG_SYS_OR_TIMING_SDRAM: + SDRAM timing + +- CONFIG_SYS_MAMR_PTA: + periodic timer for refresh + +- FLASH_BASE0_PRELIM, FLASH_BASE1_PRELIM, CONFIG_SYS_REMAP_OR_AM, + CONFIG_SYS_PRELIM_OR_AM, CONFIG_SYS_OR_TIMING_FLASH, CONFIG_SYS_OR0_REMAP, + CONFIG_SYS_OR0_PRELIM, CONFIG_SYS_BR0_PRELIM, CONFIG_SYS_OR1_REMAP, CONFIG_SYS_OR1_PRELIM, + CONFIG_SYS_BR1_PRELIM: + Memory Controller Definitions: BR0/1 and OR0/1 (FLASH) + +- SDRAM_BASE2_PRELIM, SDRAM_BASE3_PRELIM, SDRAM_MAX_SIZE, + CONFIG_SYS_OR_TIMING_SDRAM, CONFIG_SYS_OR2_PRELIM, CONFIG_SYS_BR2_PRELIM, + CONFIG_SYS_OR3_PRELIM, CONFIG_SYS_BR3_PRELIM: + Memory Controller Definitions: BR2/3 and OR2/3 (SDRAM) + +- CONFIG_PCI_ENUM_ONLY + Only scan through and get the devices on the buses. + Don't do any setup work, presumably because someone or + something has already done it, and we don't need to do it + a second time. Useful for platforms that are pre-booted + by coreboot or similar. + +- CONFIG_PCI_INDIRECT_BRIDGE: + Enable support for indirect PCI bridges. + +- CONFIG_SYS_SRIO: + Chip has SRIO or not + +- CONFIG_SRIO1: + Board has SRIO 1 port available + +- CONFIG_SRIO2: + Board has SRIO 2 port available + +- CONFIG_SRIO_PCIE_BOOT_MASTER + Board can support master function for Boot from SRIO and PCIE + +- CONFIG_SYS_SRIOn_MEM_VIRT: + Virtual Address of SRIO port 'n' memory region + +- CONFIG_SYS_SRIOn_MEM_PHYS: + Physical Address of SRIO port 'n' memory region + +- CONFIG_SYS_SRIOn_MEM_SIZE: + Size of SRIO port 'n' memory region + +- CONFIG_SYS_NAND_BUSWIDTH_16BIT + Defined to tell the NAND controller that the NAND chip is using + a 16 bit bus. + Not all NAND drivers use this symbol. + Example of drivers that use it: + - drivers/mtd/nand/raw/ndfc.c + - drivers/mtd/nand/raw/mxc_nand.c + +- CONFIG_SYS_NDFC_EBC0_CFG + Sets the EBC0_CFG register for the NDFC. If not defined + a default value will be used. + +- CONFIG_SPD_EEPROM + Get DDR timing information from an I2C EEPROM. Common + with pluggable memory modules such as SODIMMs + + SPD_EEPROM_ADDRESS + I2C address of the SPD EEPROM + +- CONFIG_SYS_SPD_BUS_NUM + If SPD EEPROM is on an I2C bus other than the first + one, specify here. Note that the value must resolve + to something your driver can deal with. + +- CONFIG_SYS_DDR_RAW_TIMING + Get DDR timing information from other than SPD. Common with + soldered DDR chips onboard without SPD. DDR raw timing + parameters are extracted from datasheet and hard-coded into + header files or board specific files. + +- CONFIG_FSL_DDR_INTERACTIVE + Enable interactive DDR debugging. See doc/README.fsl-ddr. + +- CONFIG_FSL_DDR_SYNC_REFRESH + Enable sync of refresh for multiple controllers. + +- CONFIG_FSL_DDR_BIST + Enable built-in memory test for Freescale DDR controllers. + +- CONFIG_SYS_83XX_DDR_USES_CS0 + Only for 83xx systems. If specified, then DDR should + be configured using CS0 and CS1 instead of CS2 and CS3. + +- CONFIG_RMII + Enable RMII mode for all FECs. + Note that this is a global option, we can't + have one FEC in standard MII mode and another in RMII mode. + +- CONFIG_CRC32_VERIFY + Add a verify option to the crc32 command. + The syntax is: + + => crc32 -v <address> <count> <crc32> + + Where address/count indicate a memory area + and crc32 is the correct crc32 which the + area should have. + +- CONFIG_LOOPW + Add the "loopw" memory command. This only takes effect if + the memory commands are activated globally (CONFIG_CMD_MEMORY). + +- CONFIG_MX_CYCLIC + Add the "mdc" and "mwc" memory commands. These are cyclic + "md/mw" commands. + Examples: + + => mdc.b 10 4 500 + This command will print 4 bytes (10,11,12,13) each 500 ms. + + => mwc.l 100 12345678 10 + This command will write 12345678 to address 100 all 10 ms. + + This only takes effect if the memory commands are activated + globally (CONFIG_CMD_MEMORY). + +- CONFIG_SKIP_LOWLEVEL_INIT + [ARM, NDS32, MIPS, RISC-V only] If this variable is defined, then certain + low level initializations (like setting up the memory + controller) are omitted and/or U-Boot does not + relocate itself into RAM. + + Normally this variable MUST NOT be defined. The only + exception is when U-Boot is loaded (to RAM) by some + other boot loader or by a debugger which performs + these initializations itself. + +- CONFIG_SKIP_LOWLEVEL_INIT_ONLY + [ARM926EJ-S only] This allows just the call to lowlevel_init() + to be skipped. The normal CP15 init (such as enabling the + instruction cache) is still performed. + +- CONFIG_SPL_BUILD + Modifies the behaviour of start.S when compiling a loader + that is executed before the actual U-Boot. E.g. when + compiling a NAND SPL. + +- CONFIG_TPL_BUILD + Modifies the behaviour of start.S when compiling a loader + that is executed after the SPL and before the actual U-Boot. + It is loaded by the SPL. + +- CONFIG_SYS_MPC85XX_NO_RESETVEC + Only for 85xx systems. If this variable is specified, the section + .resetvec is not kept and the section .bootpg is placed in the + previous 4k of the .text section. + +- CONFIG_ARCH_MAP_SYSMEM + Generally U-Boot (and in particular the md command) uses + effective address. It is therefore not necessary to regard + U-Boot address as virtual addresses that need to be translated + to physical addresses. However, sandbox requires this, since + it maintains its own little RAM buffer which contains all + addressable memory. This option causes some memory accesses + to be mapped through map_sysmem() / unmap_sysmem(). + +- CONFIG_X86_RESET_VECTOR + If defined, the x86 reset vector code is included. This is not + needed when U-Boot is running from Coreboot. + +- CONFIG_SYS_NAND_NO_SUBPAGE_WRITE + Option to disable subpage write in NAND driver + driver that uses this: + drivers/mtd/nand/raw/davinci_nand.c + +Freescale QE/FMAN Firmware Support: +----------------------------------- + +The Freescale QUICCEngine (QE) and Frame Manager (FMAN) both support the +loading of "firmware", which is encoded in the QE firmware binary format. +This firmware often needs to be loaded during U-Boot booting, so macros +are used to identify the storage device (NOR flash, SPI, etc) and the address +within that device. + +- CONFIG_SYS_FMAN_FW_ADDR + The address in the storage device where the FMAN microcode is located. The + meaning of this address depends on which CONFIG_SYS_QE_FW_IN_xxx macro + is also specified. + +- CONFIG_SYS_QE_FW_ADDR + The address in the storage device where the QE microcode is located. The + meaning of this address depends on which CONFIG_SYS_QE_FW_IN_xxx macro + is also specified. + +- CONFIG_SYS_QE_FMAN_FW_LENGTH + The maximum possible size of the firmware. The firmware binary format + has a field that specifies the actual size of the firmware, but it + might not be possible to read any part of the firmware unless some + local storage is allocated to hold the entire firmware first. + +- CONFIG_SYS_QE_FMAN_FW_IN_NOR + Specifies that QE/FMAN firmware is located in NOR flash, mapped as + normal addressable memory via the LBC. CONFIG_SYS_FMAN_FW_ADDR is the + virtual address in NOR flash. + +- CONFIG_SYS_QE_FMAN_FW_IN_NAND + Specifies that QE/FMAN firmware is located in NAND flash. + CONFIG_SYS_FMAN_FW_ADDR is the offset within NAND flash. + +- CONFIG_SYS_QE_FMAN_FW_IN_MMC + Specifies that QE/FMAN firmware is located on the primary SD/MMC + 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 or PCIE outbound + window->master inbound window->master LAW->the ucode address in + master's memory space. + +Freescale Layerscape Management Complex Firmware Support: +--------------------------------------------------------- +The Freescale Layerscape Management Complex (MC) supports the loading of +"firmware". +This firmware often needs to be loaded during U-Boot booting, so macros +are used to identify the storage device (NOR flash, SPI, etc) and the address +within that device. + +- CONFIG_FSL_MC_ENET + Enable the MC driver for Layerscape SoCs. + +Freescale Layerscape Debug Server Support: +------------------------------------------- +The Freescale Layerscape Debug Server Support supports the loading of +"Debug Server firmware" and triggering SP boot-rom. +This firmware often needs to be loaded during U-Boot booting. + +- CONFIG_SYS_MC_RSV_MEM_ALIGN + Define alignment of reserved memory MC requires + +Reproducible builds +------------------- + +In order to achieve reproducible builds, timestamps used in the U-Boot build +process have to be set to a fixed value. + +This is done using the SOURCE_DATE_EPOCH environment variable. +SOURCE_DATE_EPOCH is to be set on the build host's shell, not as a configuration +option for U-Boot or an environment variable in U-Boot. + +SOURCE_DATE_EPOCH should be set to a number of seconds since the epoch, in UTC. + +Building the Software: +====================== + +Building U-Boot has been tested in several native build environments +and in many different cross environments. Of course we cannot support +all possibly existing versions of cross development tools in all +(potentially obsolete) versions. In case of tool chain problems we +recommend to use the ELDK (see http://www.denx.de/wiki/DULG/ELDK) +which is extensively used to build and test U-Boot. + +If you are not using a native environment, it is assumed that you +have GNU cross compiling tools available in your path. In this case, +you must set the environment variable CROSS_COMPILE in your shell. +Note that no changes to the Makefile or any other source files are +necessary. For example using the ELDK on a 4xx CPU, please enter: + + $ CROSS_COMPILE=ppc_4xx- + $ export CROSS_COMPILE + +Note: If you wish to generate Windows versions of the utilities in + the tools directory you can use the MinGW toolchain + (http://www.mingw.org). Set your HOST tools to the MinGW + toolchain and execute 'make tools'. For example: + + $ make HOSTCC=i586-mingw32msvc-gcc HOSTSTRIP=i586-mingw32msvc-strip tools + + Binaries such as tools/mkimage.exe will be created which can + be executed on computers running Windows. + +U-Boot is intended to be simple to build. After installing the +sources you must configure U-Boot for one specific board type. This +is done by typing: + + make NAME_defconfig + +where "NAME_defconfig" is the name of one of the existing configu- +rations; see boards.cfg for supported names. + +Note: for some board special configuration names may exist; check if + additional information is available from the board vendor; for + instance, the TQM823L systems are available without (standard) + or with LCD support. You can select such additional "features" + when choosing the configuration, i. e. + + make TQM823L_defconfig + - will configure for a plain TQM823L, i. e. no LCD support + + make TQM823L_LCD_defconfig + - will configure for a TQM823L with U-Boot console on LCD + + etc. + + +Finally, type "make all", and you should get some working U-Boot +images ready for download to / installation on your system: + +- "u-boot.bin" is a raw binary image +- "u-boot" is an image in ELF binary format +- "u-boot.srec" is in Motorola S-Record format + +By default the build is performed locally and the objects are saved +in the source directory. One of the two methods can be used to change +this behavior and build U-Boot to some external directory: + +1. Add O= to the make command line invocations: + + make O=/tmp/build distclean + make O=/tmp/build NAME_defconfig + make O=/tmp/build all + +2. Set environment variable KBUILD_OUTPUT to point to the desired location: + + export KBUILD_OUTPUT=/tmp/build + make distclean + make NAME_defconfig + make all + +Note that the command line "O=" setting overrides the KBUILD_OUTPUT environment +variable. + +User specific CPPFLAGS, AFLAGS and CFLAGS can be passed to the compiler by +setting the according environment variables KCPPFLAGS, KAFLAGS and KCFLAGS. +For example to treat all compiler warnings as errors: + + make KCFLAGS=-Werror + +Please be aware that the Makefiles assume you are using GNU make, so +for instance on NetBSD you might need to use "gmake" instead of +native "make". + + +If the system board that you have is not listed, then you will need +to port U-Boot to your hardware platform. To do this, follow these +steps: + +1. Create a new directory to hold your board specific code. Add any + files you need. In your board directory, you will need at least + the "Makefile" and a "<board>.c". +2. Create a new configuration file "include/configs/<board>.h" for + your board. +3. If you're porting U-Boot to a new CPU, then also create a new + directory to hold your CPU specific code. Add any files you need. +4. Run "make <board>_defconfig" with your new name. +5. Type "make", and you should get a working "u-boot.srec" file + to be installed on your target system. +6. Debug and solve any problems that might arise. + [Of course, this last step is much harder than it sounds.] + + +Testing of U-Boot Modifications, Ports to New Hardware, etc.: +============================================================== + +If you have modified U-Boot sources (for instance added a new board +or support for new devices, a new CPU, etc.) you are expected to +provide feedback to the other developers. The feedback normally takes +the form of a "patch", i. e. a context diff against a certain (latest +official or latest in the git repository) version of U-Boot sources. + +But before you submit such a patch, please verify that your modifi- +cation did not break existing code. At least make sure that *ALL* of +the supported boards compile WITHOUT ANY compiler warnings. To do so, +just run the buildman script (tools/buildman/buildman), which will +configure and build U-Boot for ALL supported system. Be warned, this +will take a while. Please see the buildman README, or run 'buildman -H' +for documentation. + + +See also "U-Boot Porting Guide" below. + + +Monitor Commands - Overview: +============================ + +go - start application at address 'addr' +run - run commands in an environment variable +bootm - boot application image from memory +bootp - boot image via network using BootP/TFTP protocol +bootz - boot zImage from memory +tftpboot- boot image via network using TFTP protocol + and env variables "ipaddr" and "serverip" + (and eventually "gatewayip") +tftpput - upload a file via network using TFTP protocol +rarpboot- boot image via network using RARP/TFTP protocol +diskboot- boot from IDE devicebootd - boot default, i.e., run 'bootcmd' +loads - load S-Record file over serial line +loadb - load binary file over serial line (kermit mode) +md - memory display +mm - memory modify (auto-incrementing) +nm - memory modify (constant address) +mw - memory write (fill) +cp - memory copy +cmp - memory compare +crc32 - checksum calculation +i2c - I2C sub-system +sspi - SPI utility commands +base - print or set address offset +printenv- print environment variables +setenv - set environment variables +saveenv - save environment variables to persistent storage +protect - enable or disable FLASH write protection +erase - erase FLASH memory +flinfo - print FLASH memory information +nand - NAND memory operations (see doc/README.nand) +bdinfo - print Board Info structure +iminfo - print header information for application image +coninfo - print console devices and informations +ide - IDE sub-system +loop - infinite loop on address range +loopw - infinite write loop on address range +mtest - simple RAM test +icache - enable or disable instruction cache +dcache - enable or disable data cache +reset - Perform RESET of the CPU +echo - echo args to console +version - print monitor version +help - print online help +? - alias for 'help' + + +Monitor Commands - Detailed Description: +======================================== + +TODO. + +For now: just type "help <command>". + + +Environment Variables: +====================== + +U-Boot supports user configuration using Environment Variables which +can be made persistent by saving to Flash memory. + +Environment Variables are set using "setenv", printed using +"printenv", and saved to Flash using "saveenv". Using "setenv" +without a value can be used to delete a variable from the +environment. As long as you don't save the environment you are +working with an in-memory copy. In case the Flash area containing the +environment is erased by accident, a default environment is provided. + +Some configuration options can be set using Environment Variables. + +List of environment variables (most likely not complete): + + baudrate - see CONFIG_BAUDRATE + + bootdelay - see CONFIG_BOOTDELAY + + bootcmd - see CONFIG_BOOTCOMMAND + + bootargs - Boot arguments when booting an RTOS image + + bootfile - Name of the image to load with TFTP + + bootm_low - Memory range available for image processing in the bootm + command can be restricted. This variable is given as + a hexadecimal number and defines lowest address allowed + for use by the bootm command. See also "bootm_size" + environment variable. Address defined by "bootm_low" is + also the base of the initial memory mapping for the Linux + kernel -- see the description of CONFIG_SYS_BOOTMAPSZ and + bootm_mapsize. + + bootm_mapsize - Size of the initial memory mapping for the Linux kernel. + This variable is given as a hexadecimal number and it + defines the size of the memory region starting at base + address bootm_low that is accessible by the Linux kernel + during early boot. If unset, CONFIG_SYS_BOOTMAPSZ is used + as the default value if it is defined, and bootm_size is + used otherwise. + + bootm_size - Memory range available for image processing in the bootm + command can be restricted. This variable is given as + a hexadecimal number and defines the size of the region + allowed for use by the bootm command. See also "bootm_low" + environment variable. + + updatefile - Location of the software update file on a TFTP server, used + by the automatic software update feature. Please refer to + documentation in doc/README.update for more details. + + autoload - if set to "no" (any string beginning with 'n'), + "bootp" will just load perform a lookup of the + configuration from the BOOTP server, but not try to + load any image using TFTP + + autostart - if set to "yes", an image loaded using the "bootp", + "rarpboot", "tftpboot" or "diskboot" commands will + be automatically started (by internally calling + "bootm") + + If set to "no", a standalone image passed to the + "bootm" command will be copied to the load address + (and eventually uncompressed), but NOT be started. + This can be used to load and uncompress arbitrary + data. + + fdt_high - if set this restricts the maximum address that the + flattened device tree will be copied into upon boot. + For example, if you have a system with 1 GB memory + at physical address 0x10000000, while Linux kernel + only recognizes the first 704 MB as low memory, you + may need to set fdt_high as 0x3C000000 to have the + device tree blob be copied to the maximum address + of the 704 MB low memory, so that Linux kernel can + access it during the boot procedure. + + If this is set to the special value 0xFFFFFFFF then + the fdt will not be copied at all on boot. For this + to work it must reside in writable memory, have + sufficient padding on the end of it for u-boot to + add the information it needs into it, and the memory + must be accessible by the kernel. + + fdtcontroladdr- if set this is the address of the control flattened + device tree used by U-Boot when CONFIG_OF_CONTROL is + defined. + + i2cfast - (PPC405GP|PPC405EP only) + if set to 'y' configures Linux I2C driver for fast + mode (400kHZ). This environment variable is used in + initialization code. So, for changes to be effective + it must be saved and board must be reset. + + initrd_high - restrict positioning of initrd images: + If this variable is not set, initrd images will be + copied to the highest possible address in RAM; this + is usually what you want since it allows for + maximum initrd size. If for some reason you want to + make sure that the initrd image is loaded below the + CONFIG_SYS_BOOTMAPSZ limit, you can set this environment + variable to a value of "no" or "off" or "0". + Alternatively, you can set it to a maximum upper + address to use (U-Boot will still check that it + does not overwrite the U-Boot stack and data). + + For instance, when you have a system with 16 MB + RAM, and want to reserve 4 MB from use by Linux, + you can do this by adding "mem=12M" to the value of + the "bootargs" variable. However, now you must make + sure that the initrd image is placed in the first + 12 MB as well - this can be done with + + setenv initrd_high 00c00000 + + If you set initrd_high to 0xFFFFFFFF, this is an + indication to U-Boot that all addresses are legal + for the Linux kernel, including addresses in flash + memory. In this case U-Boot will NOT COPY the + ramdisk at all. This may be useful to reduce the + boot time on your system, but requires that this + feature is supported by your Linux kernel. + + ipaddr - IP address; needed for tftpboot command + + loadaddr - Default load address for commands like "bootp", + "rarpboot", "tftpboot", "loadb" or "diskboot" + + loads_echo - see CONFIG_LOADS_ECHO + + serverip - TFTP server IP address; needed for tftpboot command + + bootretry - see CONFIG_BOOT_RETRY_TIME + + bootdelaykey - see CONFIG_AUTOBOOT_DELAY_STR + + bootstopkey - see CONFIG_AUTOBOOT_STOP_STR + + ethprime - controls which interface is used first. + + ethact - controls which interface is currently active. + For example you can do the following + + => setenv ethact FEC + => ping 192.168.0.1 # traffic sent on FEC + => setenv ethact SCC + => ping 10.0.0.1 # traffic sent on SCC + + ethrotate - When set to "no" U-Boot does not go through all + available network interfaces. + It just stays at the currently selected interface. + + netretry - When set to "no" each network operation will + either succeed or fail without retrying. + When set to "once" the network operation will + fail when all the available network interfaces + are tried once without success. + Useful on scripts which control the retry operation + themselves. + + npe_ucode - set load address for the NPE microcode + + silent_linux - If set then Linux will be told to boot silently, by + changing the console to be empty. If "yes" it will be + made silent. If "no" it will not be made silent. If + unset, then it will be made silent if the U-Boot console + is silent. + + tftpsrcp - If this is set, the value is used for TFTP's + UDP source port. + + tftpdstp - If this is set, the value is used for TFTP's UDP + destination port instead of the Well Know Port 69. + + tftpblocksize - Block size to use for TFTP transfers; if not set, + we use the TFTP server's default block size + + tftptimeout - Retransmission timeout for TFTP packets (in milli- + seconds, minimum value is 1000 = 1 second). Defines + when a packet is considered to be lost so it has to + be retransmitted. The default is 5000 = 5 seconds. + Lowering this value may make downloads succeed + faster in networks with high packet loss rates or + with unreliable TFTP servers. + + tftptimeoutcountmax - maximum count of TFTP timeouts (no + unit, minimum value = 0). Defines how many timeouts + can happen during a single file transfer before that + transfer is aborted. The default is 10, and 0 means + 'no timeouts allowed'. Increasing this value may help + downloads succeed with high packet loss rates, or with + unreliable TFTP servers or client hardware. + + vlan - When set to a value < 4095 the traffic over + Ethernet is encapsulated/received over 802.1q + VLAN tagged frames. + + bootpretryperiod - Period during which BOOTP/DHCP sends retries. + Unsigned value, in milliseconds. If not set, the period will + be either the default (28000), or a value based on + CONFIG_NET_RETRY_COUNT, if defined. This value has + precedence over the valu based on CONFIG_NET_RETRY_COUNT. + +The following image location variables contain the location of images +used in booting. The "Image" column gives the role of the image and is +not an environment variable name. The other columns are environment +variable names. "File Name" gives the name of the file on a TFTP +server, "RAM Address" gives the location in RAM the image will be +loaded to, and "Flash Location" gives the image's address in NOR +flash or offset in NAND flash. + +*Note* - these variables don't have to be defined for all boards, some +boards currently use other variables for these purposes, and some +boards use these variables for other purposes. + +Image File Name RAM Address Flash Location +----- --------- ----------- -------------- +u-boot u-boot u-boot_addr_r u-boot_addr +Linux kernel bootfile kernel_addr_r kernel_addr +device tree blob fdtfile fdt_addr_r fdt_addr +ramdisk ramdiskfile ramdisk_addr_r ramdisk_addr + +The following environment variables may be used and automatically +updated by the network boot commands ("bootp" and "rarpboot"), +depending the information provided by your boot server: + + bootfile - see above + dnsip - IP address of your Domain Name Server + dnsip2 - IP address of your secondary Domain Name Server + gatewayip - IP address of the Gateway (Router) to use + hostname - Target hostname + ipaddr - see above + netmask - Subnet Mask + rootpath - Pathname of the root filesystem on the NFS server + serverip - see above + + +There are two special Environment Variables: + + serial# - contains hardware identification information such + as type string and/or serial number + ethaddr - Ethernet address + +These variables can be set only once (usually during manufacturing of +the board). U-Boot refuses to delete or overwrite these variables +once they have been set once. + + +Further special Environment Variables: + + ver - Contains the U-Boot version string as printed + with the "version" command. This variable is + readonly (see CONFIG_VERSION_VARIABLE). + + +Please note that changes to some configuration parameters may take +only effect after the next boot (yes, that's just like Windoze :-). + + +Callback functions for environment variables: +--------------------------------------------- + +For some environment variables, the behavior of u-boot needs to change +when their values are changed. This functionality allows functions to +be associated with arbitrary variables. On creation, overwrite, or +deletion, the callback will provide the opportunity for some side +effect to happen or for the change to be rejected. + +The callbacks are named and associated with a function using the +U_BOOT_ENV_CALLBACK macro in your board or driver code. + +These callbacks are associated with variables in one of two ways. The +static list can be added to by defining CONFIG_ENV_CALLBACK_LIST_STATIC +in the board configuration to a string that defines a list of +associations. The list must be in the following format: + + entry = variable_name[:callback_name] + list = entry[,list] + +If the callback name is not specified, then the callback is deleted. +Spaces are also allowed anywhere in the list. + +Callbacks can also be associated by defining the ".callbacks" variable +with the same list format above. Any association in ".callbacks" will +override any association in the static list. You can define +CONFIG_ENV_CALLBACK_LIST_DEFAULT to a list (string) to define the +".callbacks" environment variable in the default or embedded environment. + +If CONFIG_REGEX is defined, the variable_name above is evaluated as a +regular expression. This allows multiple variables to be connected to +the same callback without explicitly listing them all out. + +The signature of the callback functions is: + + int callback(const char *name, const char *value, enum env_op op, int flags) + +* name - changed environment variable +* value - new value of the environment variable +* op - operation (create, overwrite, or delete) +* flags - attributes of the environment variable change, see flags H_* in + include/search.h + +The return value is 0 if the variable change is accepted and 1 otherwise. + +Command Line Parsing: +===================== + +There are two different command line parsers available with U-Boot: +the old "simple" one, and the much more powerful "hush" shell: + +Old, simple command line parser: +-------------------------------- + +- supports environment variables (through setenv / saveenv commands) +- several commands on one line, separated by ';' +- variable substitution using "... ${name} ..." syntax +- special characters ('$', ';') can be escaped by prefixing with '\', + for example: + setenv bootcmd bootm \${address} +- You can also escape text by enclosing in single apostrophes, for example: + setenv addip 'setenv bootargs $bootargs ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname::off' + +Hush shell: +----------- + +- similar to Bourne shell, with control structures like + if...then...else...fi, for...do...done; while...do...done, + until...do...done, ... +- supports environment ("global") variables (through setenv / saveenv + commands) and local shell variables (through standard shell syntax + "name=value"); only environment variables can be used with "run" + command + +General rules: +-------------- + +(1) If a command line (or an environment variable executed by a "run" + command) contains several commands separated by semicolon, and + one of these commands fails, then the remaining commands will be + executed anyway. + +(2) If you execute several variables with one call to run (i. e. + calling run with a list of variables as arguments), any failing + command will cause "run" to terminate, i. e. the remaining + variables are not executed. + +Note for Redundant Ethernet Interfaces: +======================================= + +Some boards come with redundant Ethernet interfaces; U-Boot supports +such configurations and is capable of automatic selection of a +"working" interface when needed. MAC assignment works as follows: + +Network interfaces are numbered eth0, eth1, eth2, ... Corresponding +MAC addresses can be stored in the environment as "ethaddr" (=>eth0), +"eth1addr" (=>eth1), "eth2addr", ... + +If the network interface stores some valid MAC address (for instance +in SROM), this is used as default address if there is NO correspon- +ding setting in the environment; if the corresponding environment +variable is set, this overrides the settings in the card; that means: + +o If the SROM has a valid MAC address, and there is no address in the + environment, the SROM's address is used. + +o If there is no valid address in the SROM, and a definition in the + environment exists, then the value from the environment variable is + used. + +o If both the SROM and the environment contain a MAC address, and + both addresses are the same, this MAC address is used. + +o If both the SROM and the environment contain a MAC address, and the + addresses differ, the value from the environment is used and a + warning is printed. + +o If neither SROM nor the environment contain a MAC address, an error + is raised. If CONFIG_NET_RANDOM_ETHADDR is defined, then in this case + a random, locally-assigned MAC is used. + +If Ethernet drivers implement the 'write_hwaddr' function, valid MAC addresses +will be programmed into hardware as part of the initialization process. This +may be skipped by setting the appropriate 'ethmacskip' environment variable. +The naming convention is as follows: +"ethmacskip" (=>eth0), "eth1macskip" (=>eth1) etc. + +Image Formats: +============== + +U-Boot is capable of booting (and performing other auxiliary operations on) +images in two formats: + +New uImage format (FIT) +----------------------- + +Flexible and powerful format based on Flattened Image Tree -- FIT (similar +to Flattened Device Tree). It allows the use of images with multiple +components (several kernels, ramdisks, etc.), with contents protected by +SHA1, MD5 or CRC32. More details are found in the doc/uImage.FIT directory. + + +Old uImage format +----------------- + +Old image format is based on binary files which can be basically anything, +preceded by a special header; see the definitions in include/image.h for +details; basically, the header defines the following image properties: + +* Target Operating System (Provisions for OpenBSD, NetBSD, FreeBSD, + 4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, + LynxOS, pSOS, QNX, RTEMS, INTEGRITY; + Currently supported: Linux, NetBSD, VxWorks, QNX, RTEMS, LynxOS, + INTEGRITY). +* Target CPU Architecture (Provisions for Alpha, ARM, Intel x86, + IA64, MIPS, NDS32, Nios II, PowerPC, IBM S390, SuperH, Sparc, Sparc 64 Bit; + Currently supported: ARM, Intel x86, MIPS, NDS32, Nios II, PowerPC). +* Compression Type (uncompressed, gzip, bzip2) +* Load Address +* Entry Point +* Image Name +* Image Timestamp + +The header is marked by a special Magic Number, and both the header +and the data portions of the image are secured against corruption by +CRC32 checksums. + + +Linux Support: +============== + +Although U-Boot should support any OS or standalone application +easily, the main focus has always been on Linux during the design of +U-Boot. + +U-Boot includes many features that so far have been part of some +special "boot loader" code within the Linux kernel. Also, any +"initrd" images to be used are no longer part of one big Linux image; +instead, kernel and "initrd" are separate images. This implementation +serves several purposes: + +- the same features can be used for other OS or standalone + applications (for instance: using compressed images to reduce the + Flash memory footprint) + +- it becomes much easier to port new Linux kernel versions because + lots of low-level, hardware dependent stuff are done by U-Boot + +- the same Linux kernel image can now be used with different "initrd" + images; of course this also means that different kernel images can + be run with the same "initrd". This makes testing easier (you don't + have to build a new "zImage.initrd" Linux image when you just + change a file in your "initrd"). Also, a field-upgrade of the + software is easier now. + + +Linux HOWTO: +============ + +Porting Linux to U-Boot based systems: +--------------------------------------- + +U-Boot cannot save you from doing all the necessary modifications to +configure the Linux device drivers for use with your target hardware +(no, we don't intend to provide a full virtual machine interface to +Linux :-). + +But now you can ignore ALL boot loader code (in arch/powerpc/mbxboot). + +Just make sure your machine specific header file (for instance +include/asm-ppc/tqm8xx.h) includes the same definition of the Board +Information structure as we define in include/asm-<arch>/u-boot.h, +and make sure that your definition of IMAP_ADDR uses the same value +as your U-Boot configuration in CONFIG_SYS_IMMR. + +Note that U-Boot now has a driver model, a unified model for drivers. +If you are adding a new driver, plumb it into driver model. If there +is no uclass available, you are encouraged to create one. See +doc/driver-model. + + +Configuring the Linux kernel: +----------------------------- + +No specific requirements for U-Boot. Make sure you have some root +device (initial ramdisk, NFS) for your target system. + + +Building a Linux Image: +----------------------- + +With U-Boot, "normal" build targets like "zImage" or "bzImage" are +not used. If you use recent kernel source, a new build target +"uImage" will exist which automatically builds an image usable by +U-Boot. Most older kernels also have support for a "pImage" target, +which was introduced for our predecessor project PPCBoot and uses a +100% compatible format. + +Example: + + make TQM850L_defconfig + make oldconfig + make dep + make uImage + +The "uImage" build target uses a special tool (in 'tools/mkimage') to +encapsulate a compressed Linux kernel image with header information, +CRC32 checksum etc. for use with U-Boot. This is what we are doing: + +* build a standard "vmlinux" kernel image (in ELF binary format): + +* convert the kernel into a raw binary image: + + ${CROSS_COMPILE}-objcopy -O binary \ + -R .note -R .comment \ + -S vmlinux linux.bin + +* compress the binary image: + + gzip -9 linux.bin + +* package compressed binary image for U-Boot: + + mkimage -A ppc -O linux -T kernel -C gzip \ + -a 0 -e 0 -n "Linux Kernel Image" \ + -d linux.bin.gz uImage + + +The "mkimage" tool can also be used to create ramdisk images for use +with U-Boot, either separated from the Linux kernel image, or +combined into one file. "mkimage" encapsulates the images with a 64 +byte header containing information about target architecture, +operating system, image type, compression method, entry points, time +stamp, CRC32 checksums, etc. + +"mkimage" can be called in two ways: to verify existing images and +print the header information, or to build new images. + +In the first form (with "-l" option) mkimage lists the information +contained in the header of an existing U-Boot image; this includes +checksum verification: + + tools/mkimage -l image + -l ==> list image header information + +The second form (with "-d" option) is used to build a U-Boot image +from a "data file" which is used as image payload: + + tools/mkimage -A arch -O os -T type -C comp -a addr -e ep \ + -n name -d data_file image + -A ==> set architecture to 'arch' + -O ==> set operating system to 'os' + -T ==> set image type to 'type' + -C ==> set compression type 'comp' + -a ==> set load address to 'addr' (hex) + -e ==> set entry point to 'ep' (hex) + -n ==> set image name to 'name' + -d ==> use image data from 'datafile' + +Right now, all Linux kernels for PowerPC systems use the same load +address (0x00000000), but the entry point address depends on the +kernel version: + +- 2.2.x kernels have the entry point at 0x0000000C, +- 2.3.x and later kernels have the entry point at 0x00000000. + +So a typical call to build a U-Boot image would read: + + -> tools/mkimage -n '2.4.4 kernel for TQM850L' \ + > -A ppc -O linux -T kernel -C gzip -a 0 -e 0 \ + > -d /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux.gz \ + > examples/uImage.TQM850L + Image Name: 2.4.4 kernel for TQM850L + Created: Wed Jul 19 02:34:59 2000 + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 335725 Bytes = 327.86 kB = 0.32 MB + Load Address: 0x00000000 + Entry Point: 0x00000000 + +To verify the contents of the image (or check for corruption): + + -> tools/mkimage -l examples/uImage.TQM850L + Image Name: 2.4.4 kernel for TQM850L + Created: Wed Jul 19 02:34:59 2000 + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 335725 Bytes = 327.86 kB = 0.32 MB + Load Address: 0x00000000 + Entry Point: 0x00000000 + +NOTE: for embedded systems where boot time is critical you can trade +speed for memory and install an UNCOMPRESSED image instead: this +needs more space in Flash, but boots much faster since it does not +need to be uncompressed: + + -> gunzip /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux.gz + -> tools/mkimage -n '2.4.4 kernel for TQM850L' \ + > -A ppc -O linux -T kernel -C none -a 0 -e 0 \ + > -d /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux \ + > examples/uImage.TQM850L-uncompressed + Image Name: 2.4.4 kernel for TQM850L + Created: Wed Jul 19 02:34:59 2000 + Image Type: PowerPC Linux Kernel Image (uncompressed) + Data Size: 792160 Bytes = 773.59 kB = 0.76 MB + Load Address: 0x00000000 + Entry Point: 0x00000000 + + +Similar you can build U-Boot images from a 'ramdisk.image.gz' file +when your kernel is intended to use an initial ramdisk: + + -> tools/mkimage -n 'Simple Ramdisk Image' \ + > -A ppc -O linux -T ramdisk -C gzip \ + > -d /LinuxPPC/images/SIMPLE-ramdisk.image.gz examples/simple-initrd + Image Name: Simple Ramdisk Image + Created: Wed Jan 12 14:01:50 2000 + Image Type: PowerPC Linux RAMDisk Image (gzip compressed) + Data Size: 566530 Bytes = 553.25 kB = 0.54 MB + Load Address: 0x00000000 + Entry Point: 0x00000000 + +The "dumpimage" is a tool to disassemble images built by mkimage. Its "-i" +option performs the converse operation of the mkimage's second form (the "-d" +option). Given an image built by mkimage, the dumpimage extracts a "data file" +from the image: + + tools/dumpimage -i image -T type -p position data_file + -i ==> extract from the 'image' a specific 'data_file' + -T ==> set image type to 'type' + -p ==> 'position' (starting at 0) of the 'data_file' inside the 'image' + + +Installing a Linux Image: +------------------------- + +To downloading a U-Boot image over the serial (console) interface, +you must convert the image to S-Record format: + + objcopy -I binary -O srec examples/image examples/image.srec + +The 'objcopy' does not understand the information in the U-Boot +image header, so the resulting S-Record file will be relative to +address 0x00000000. To load it to a given address, you need to +specify the target address as 'offset' parameter with the 'loads' +command. + +Example: install the image to address 0x40100000 (which on the +TQM8xxL is in the first Flash bank): + + => erase 40100000 401FFFFF + + .......... done + Erased 8 sectors + + => loads 40100000 + ## Ready for S-Record download ... + ~>examples/image.srec + 1 2 3 4 5 6 7 8 9 10 11 12 13 ... + ... + 15989 15990 15991 15992 + [file transfer complete] + [connected] + ## Start Addr = 0x00000000 + + +You can check the success of the download using the 'iminfo' command; +this includes a checksum verification so you can be sure no data +corruption happened: + + => imi 40100000 + + ## Checking Image at 40100000 ... + Image Name: 2.2.13 for initrd on TQM850L + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 335725 Bytes = 327 kB = 0 MB + Load Address: 00000000 + Entry Point: 0000000c + Verifying Checksum ... OK + + +Boot Linux: +----------- + +The "bootm" command is used to boot an application that is stored in +memory (RAM or Flash). In case of a Linux kernel image, the contents +of the "bootargs" environment variable is passed to the kernel as +parameters. You can check and modify this variable using the +"printenv" and "setenv" commands: + + + => printenv bootargs + bootargs=root=/dev/ram + + => setenv bootargs root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2 + + => printenv bootargs + bootargs=root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2 + + => bootm 40020000 + ## Booting Linux kernel at 40020000 ... + Image Name: 2.2.13 for NFS on TQM850L + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 381681 Bytes = 372 kB = 0 MB + Load Address: 00000000 + Entry Point: 0000000c + Verifying Checksum ... OK + Uncompressing Kernel Image ... OK + Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:35:17 MEST 2000 + Boot arguments: root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2 + time_init: decrementer frequency = 187500000/60 + Calibrating delay loop... 49.77 BogoMIPS + Memory: 15208k available (700k kernel code, 444k data, 32k init) [c0000000,c1000000] + ... + +If you want to boot a Linux kernel with initial RAM disk, you pass +the memory addresses of both the kernel and the initrd image (PPBCOOT +format!) to the "bootm" command: + + => imi 40100000 40200000 + + ## Checking Image at 40100000 ... + Image Name: 2.2.13 for initrd on TQM850L + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 335725 Bytes = 327 kB = 0 MB + Load Address: 00000000 + Entry Point: 0000000c + Verifying Checksum ... OK + + ## Checking Image at 40200000 ... + Image Name: Simple Ramdisk Image + Image Type: PowerPC Linux RAMDisk Image (gzip compressed) + Data Size: 566530 Bytes = 553 kB = 0 MB + Load Address: 00000000 + Entry Point: 00000000 + Verifying Checksum ... OK + + => bootm 40100000 40200000 + ## Booting Linux kernel at 40100000 ... + Image Name: 2.2.13 for initrd on TQM850L + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 335725 Bytes = 327 kB = 0 MB + Load Address: 00000000 + Entry Point: 0000000c + Verifying Checksum ... OK + Uncompressing Kernel Image ... OK + ## Loading RAMDisk Image at 40200000 ... + Image Name: Simple Ramdisk Image + Image Type: PowerPC Linux RAMDisk Image (gzip compressed) + Data Size: 566530 Bytes = 553 kB = 0 MB + Load Address: 00000000 + Entry Point: 00000000 + Verifying Checksum ... OK + Loading Ramdisk ... OK + Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:32:08 MEST 2000 + Boot arguments: root=/dev/ram + time_init: decrementer frequency = 187500000/60 + Calibrating delay loop... 49.77 BogoMIPS + ... + RAMDISK: Compressed image found at block 0 + VFS: Mounted root (ext2 filesystem). + + bash# + +Boot Linux and pass a flat device tree: +----------- + +First, U-Boot must be compiled with the appropriate defines. See the section +titled "Linux Kernel Interface" above for a more in depth explanation. The +following is an example of how to start a kernel and pass an updated +flat device tree: + +=> print oftaddr +oftaddr=0x300000 +=> print oft +oft=oftrees/mpc8540ads.dtb +=> tftp $oftaddr $oft +Speed: 1000, full duplex +Using TSEC0 device +TFTP from server 192.168.1.1; our IP address is 192.168.1.101 +Filename 'oftrees/mpc8540ads.dtb'. +Load address: 0x300000 +Loading: # +done +Bytes transferred = 4106 (100a hex) +=> tftp $loadaddr $bootfile +Speed: 1000, full duplex +Using TSEC0 device +TFTP from server 192.168.1.1; our IP address is 192.168.1.2 +Filename 'uImage'. +Load address: 0x200000 +Loading:############ +done +Bytes transferred = 1029407 (fb51f hex) +=> print loadaddr +loadaddr=200000 +=> print oftaddr +oftaddr=0x300000 +=> bootm $loadaddr - $oftaddr +## Booting image at 00200000 ... + Image Name: Linux-2.6.17-dirty + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 1029343 Bytes = 1005.2 kB + Load Address: 00000000 + Entry Point: 00000000 + Verifying Checksum ... OK + Uncompressing Kernel Image ... OK +Booting using flat device tree at 0x300000 +Using MPC85xx ADS machine description +Memory CAM mapping: CAM0=256Mb, CAM1=256Mb, CAM2=0Mb residual: 0Mb +[snip] + + +More About U-Boot Image Types: +------------------------------ + +U-Boot supports the following image types: + + "Standalone Programs" are directly runnable in the environment + provided by U-Boot; it is expected that (if they behave + well) you can continue to work in U-Boot after return from + the Standalone Program. + "OS Kernel Images" are usually images of some Embedded OS which + will take over control completely. Usually these programs + will install their own set of exception handlers, device + drivers, set up the MMU, etc. - this means, that you cannot + expect to re-enter U-Boot except by resetting the CPU. + "RAMDisk Images" are more or less just data blocks, and their + parameters (address, size) are passed to an OS kernel that is + being started. + "Multi-File Images" contain several images, typically an OS + (Linux) kernel image and one or more data images like + RAMDisks. This construct is useful for instance when you want + to boot over the network using BOOTP etc., where the boot + server provides just a single image file, but you want to get + for instance an OS kernel and a RAMDisk image. + + "Multi-File Images" start with a list of image sizes, each + image size (in bytes) specified by an "uint32_t" in network + byte order. This list is terminated by an "(uint32_t)0". + Immediately after the terminating 0 follow the images, one by + one, all aligned on "uint32_t" boundaries (size rounded up to + a multiple of 4 bytes). + + "Firmware Images" are binary images containing firmware (like + U-Boot or FPGA images) which usually will be programmed to + flash memory. + + "Script files" are command sequences that will be executed by + U-Boot's command interpreter; this feature is especially + useful when you configure U-Boot to use a real shell (hush) + as command interpreter. + +Booting the Linux zImage: +------------------------- + +On some platforms, it's possible to boot Linux zImage. This is done +using the "bootz" command. The syntax of "bootz" command is the same +as the syntax of "bootm" command. + +Note, defining the CONFIG_SUPPORT_RAW_INITRD allows user to supply +kernel with raw initrd images. The syntax is slightly different, the +address of the initrd must be augmented by it's size, in the following +format: "<initrd addres>:<initrd size>". + + +Standalone HOWTO: +================= + +One of the features of U-Boot is that you can dynamically load and +run "standalone" applications, which can use some resources of +U-Boot like console I/O functions or interrupt services. + +Two simple examples are included with the sources: + +"Hello World" Demo: +------------------- + +'examples/hello_world.c' contains a small "Hello World" Demo +application; it is automatically compiled when you build U-Boot. +It's configured to run at address 0x00040004, so you can play with it +like that: + + => loads + ## Ready for S-Record download ... + ~>examples/hello_world.srec + 1 2 3 4 5 6 7 8 9 10 11 ... + [file transfer complete] + [connected] + ## Start Addr = 0x00040004 + + => go 40004 Hello World! This is a test. + ## Starting application at 0x00040004 ... + Hello World + argc = 7 + argv[0] = "40004" + argv[1] = "Hello" + argv[2] = "World!" + argv[3] = "This" + argv[4] = "is" + argv[5] = "a" + argv[6] = "test." + argv[7] = "<NULL>" + Hit any key to exit ... + + ## Application terminated, rc = 0x0 + +Another example, which demonstrates how to register a CPM interrupt +handler with the U-Boot code, can be found in 'examples/timer.c'. +Here, a CPM timer is set up to generate an interrupt every second. +The interrupt service routine is trivial, just printing a '.' +character, but this is just a demo program. The application can be +controlled by the following keys: + + ? - print current values og the CPM Timer registers + b - enable interrupts and start timer + e - stop timer and disable interrupts + q - quit application + + => loads + ## Ready for S-Record download ... + ~>examples/timer.srec + 1 2 3 4 5 6 7 8 9 10 11 ... + [file transfer complete] + [connected] + ## Start Addr = 0x00040004 + + => go 40004 + ## Starting application at 0x00040004 ... + TIMERS=0xfff00980 + Using timer 1 + tgcr @ 0xfff00980, tmr @ 0xfff00990, trr @ 0xfff00994, tcr @ 0xfff00998, tcn @ 0xfff0099c, ter @ 0xfff009b0 + +Hit 'b': + [q, b, e, ?] Set interval 1000000 us + Enabling timer +Hit '?': + [q, b, e, ?] ........ + tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0xef6, ter=0x0 +Hit '?': + [q, b, e, ?] . + tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x2ad4, ter=0x0 +Hit '?': + [q, b, e, ?] . + tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x1efc, ter=0x0 +Hit '?': + [q, b, e, ?] . + tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x169d, ter=0x0 +Hit 'e': + [q, b, e, ?] ...Stopping timer +Hit 'q': + [q, b, e, ?] ## Application terminated, rc = 0x0 + + +Minicom warning: +================ + +Over time, many people have reported problems when trying to use the +"minicom" terminal emulation program for serial download. I (wd) +consider minicom to be broken, and recommend not to use it. Under +Unix, I recommend to use C-Kermit for general purpose use (and +especially for kermit binary protocol download ("loadb" command), and +use "cu" for S-Record download ("loads" command). See +http://www.denx.de/wiki/view/DULG/SystemSetup#Section_4.3. +for help with kermit. + + +Nevertheless, if you absolutely want to use it try adding this +configuration to your "File transfer protocols" section: + + Name Program Name U/D FullScr IO-Red. Multi + X kermit /usr/bin/kermit -i -l %l -s Y U Y N N + Y kermit /usr/bin/kermit -i -l %l -r N D Y N N + + +NetBSD Notes: +============= + +Starting at version 0.9.2, U-Boot supports NetBSD both as host +(build U-Boot) and target system (boots NetBSD/mpc8xx). + +Building requires a cross environment; it is known to work on +NetBSD/i386 with the cross-powerpc-netbsd-1.3 package (you will also +need gmake since the Makefiles are not compatible with BSD make). +Note that the cross-powerpc package does not install include files; +attempting to build U-Boot will fail because <machine/ansi.h> is +missing. This file has to be installed and patched manually: + + # cd /usr/pkg/cross/powerpc-netbsd/include + # mkdir powerpc + # ln -s powerpc machine + # cp /usr/src/sys/arch/powerpc/include/ansi.h powerpc/ansi.h + # ${EDIT} powerpc/ansi.h ## must remove __va_list, _BSD_VA_LIST + +Native builds *don't* work due to incompatibilities between native +and U-Boot include files. + +Booting assumes that (the first part of) the image booted is a +stage-2 loader which in turn loads and then invokes the kernel +proper. Loader sources will eventually appear in the NetBSD source +tree (probably in sys/arc/mpc8xx/stand/u-boot_stage2/); in the +meantime, see ftp://ftp.denx.de/pub/u-boot/ppcboot_stage2.tar.gz + + +Implementation Internals: +========================= + +The following is not intended to be a complete description of every +implementation detail. However, it should help to understand the +inner workings of U-Boot and make it easier to port it to custom +hardware. + + +Initial Stack, Global Data: +--------------------------- + +The implementation of U-Boot is complicated by the fact that U-Boot +starts running out of ROM (flash memory), usually without access to +system RAM (because the memory controller is not initialized yet). +This means that we don't have writable Data or BSS segments, and BSS +is not initialized as zero. To be able to get a C environment working +at all, we have to allocate at least a minimal stack. Implementation +options for this are defined and restricted by the CPU used: Some CPU +models provide on-chip memory (like the IMMR area on MPC8xx and +MPC826x processors), on others (parts of) the data cache can be +locked as (mis-) used as memory, etc. + + Chris Hallinan posted a good summary of these issues to the + U-Boot mailing list: + + Subject: RE: [U-Boot-Users] RE: More On Memory Bank x (nothingness)? + From: "Chris Hallinan" <clh@net1plus.com> + Date: Mon, 10 Feb 2003 16:43:46 -0500 (22:43 MET) + ... + + Correct me if I'm wrong, folks, but the way I understand it + is this: Using DCACHE as initial RAM for Stack, etc, does not + require any physical RAM backing up the cache. The cleverness + is that the cache is being used as a temporary supply of + necessary storage before the SDRAM controller is setup. It's + beyond the scope of this list to explain the details, but you + can see how this works by studying the cache architecture and + operation in the architecture and processor-specific manuals. + + OCM is On Chip Memory, which I believe the 405GP has 4K. It + is another option for the system designer to use as an + initial stack/RAM area prior to SDRAM being available. Either + option should work for you. Using CS 4 should be fine if your + board designers haven't used it for something that would + cause you grief during the initial boot! It is frequently not + used. + + CONFIG_SYS_INIT_RAM_ADDR should be somewhere that won't interfere + with your processor/board/system design. The default value + you will find in any recent u-boot distribution in + walnut.h should work for you. I'd set it to a value larger + than your SDRAM module. If you have a 64MB SDRAM module, set + it above 400_0000. Just make sure your board has no resources + that are supposed to respond to that address! That code in + start.S has been around a while and should work as is when + you get the config right. + + -Chris Hallinan + DS4.COM, Inc. + +It is essential to remember this, since it has some impact on the C +code for the initialization procedures: + +* Initialized global data (data segment) is read-only. Do not attempt + to write it. + +* Do not use any uninitialized global data (or implicitly initialized + as zero data - BSS segment) at all - this is undefined, initiali- + zation is performed later (when relocating to RAM). + +* Stack space is very limited. Avoid big data buffers or things like + that. + +Having only the stack as writable memory limits means we cannot use +normal global data to share information between the code. But it +turned out that the implementation of U-Boot can be greatly +simplified by making a global data structure (gd_t) available to all +functions. We could pass a pointer to this data as argument to _all_ +functions, but this would bloat the code. Instead we use a feature of +the GCC compiler (Global Register Variables) to share the data: we +place a pointer (gd) to the global data into a register which we +reserve for this purpose. + +When choosing a register for such a purpose we are restricted by the +relevant (E)ABI specifications for the current architecture, and by +GCC's implementation. + +For PowerPC, the following registers have specific use: + R1: stack pointer + R2: reserved for system use + R3-R4: parameter passing and return values + R5-R10: parameter passing + R13: small data area pointer + R30: GOT pointer + R31: frame pointer + + (U-Boot also uses R12 as internal GOT pointer. r12 + is a volatile register so r12 needs to be reset when + going back and forth between asm and C) + + ==> U-Boot will use R2 to hold a pointer to the global data + + Note: on PPC, we could use a static initializer (since the + address of the global data structure is known at compile time), + but it turned out that reserving a register results in somewhat + smaller code - although the code savings are not that big (on + average for all boards 752 bytes for the whole U-Boot image, + 624 text + 127 data). + +On ARM, the following registers are used: + + R0: function argument word/integer result + R1-R3: function argument word + R9: platform specific + R10: stack limit (used only if stack checking is enabled) + R11: argument (frame) pointer + R12: temporary workspace + R13: stack pointer + R14: link register + R15: program counter + + ==> U-Boot will use R9 to hold a pointer to the global data + + Note: on ARM, only R_ARM_RELATIVE relocations are supported. + +On Nios II, the ABI is documented here: + http://www.altera.com/literature/hb/nios2/n2cpu_nii51016.pdf + + ==> U-Boot will use gp to hold a pointer to the global data + + Note: on Nios II, we give "-G0" option to gcc and don't use gp + to access small data sections, so gp is free. + +On NDS32, the following registers are used: + + R0-R1: argument/return + R2-R5: argument + R15: temporary register for assembler + R16: trampoline register + R28: frame pointer (FP) + R29: global pointer (GP) + R30: link register (LP) + R31: stack pointer (SP) + PC: program counter (PC) + + ==> U-Boot will use R10 to hold a pointer to the global data + +NOTE: DECLARE_GLOBAL_DATA_PTR must be used with file-global scope, +or current versions of GCC may "optimize" the code too much. + +On RISC-V, the following registers are used: + + x0: hard-wired zero (zero) + x1: return address (ra) + x2: stack pointer (sp) + x3: global pointer (gp) + x4: thread pointer (tp) + x5: link register (t0) + x8: frame pointer (fp) + x10-x11: arguments/return values (a0-1) + x12-x17: arguments (a2-7) + x28-31: temporaries (t3-6) + pc: program counter (pc) + + ==> U-Boot will use gp to hold a pointer to the global data + +Memory Management: +------------------ + +U-Boot runs in system state and uses physical addresses, i.e. the +MMU is not used either for address mapping nor for memory protection. + +The available memory is mapped to fixed addresses using the memory +controller. In this process, a contiguous block is formed for each +memory type (Flash, SDRAM, SRAM), even when it consists of several +physical memory banks. + +U-Boot is installed in the first 128 kB of the first Flash bank (on +TQM8xxL modules this is the range 0x40000000 ... 0x4001FFFF). After +booting and sizing and initializing DRAM, the code relocates itself +to the upper end of DRAM. Immediately below the U-Boot code some +memory is reserved for use by malloc() [see CONFIG_SYS_MALLOC_LEN +configuration setting]. Below that, a structure with global Board +Info data is placed, followed by the stack (growing downward). + +Additionally, some exception handler code is copied to the low 8 kB +of DRAM (0x00000000 ... 0x00001FFF). + +So a typical memory configuration with 16 MB of DRAM could look like +this: + + 0x0000 0000 Exception Vector code + : + 0x0000 1FFF + 0x0000 2000 Free for Application Use + : + : + + : + : + 0x00FB FF20 Monitor Stack (Growing downward) + 0x00FB FFAC Board Info Data and permanent copy of global data + 0x00FC 0000 Malloc Arena + : + 0x00FD FFFF + 0x00FE 0000 RAM Copy of Monitor Code + ... eventually: LCD or video framebuffer + ... eventually: pRAM (Protected RAM - unchanged by reset) + 0x00FF FFFF [End of RAM] + + +System Initialization: +---------------------- + +In the reset configuration, U-Boot starts at the reset entry point +(on most PowerPC systems at address 0x00000100). Because of the reset +configuration for CS0# this is a mirror of the on board Flash memory. +To be able to re-map memory U-Boot then jumps to its link address. +To be able to implement the initialization code in C, a (small!) +initial stack is set up in the internal Dual Ported RAM (in case CPUs +which provide such a feature like), or in a locked part of the data +cache. After that, U-Boot initializes the CPU core, the caches and +the SIU. + +Next, all (potentially) available memory banks are mapped using a +preliminary mapping. For example, we put them on 512 MB boundaries +(multiples of 0x20000000: SDRAM on 0x00000000 and 0x20000000, Flash +on 0x40000000 and 0x60000000, SRAM on 0x80000000). Then UPM A is +programmed for SDRAM access. Using the temporary configuration, a +simple memory test is run that determines the size of the SDRAM +banks. + +When there is more than one SDRAM bank, and the banks are of +different size, the largest is mapped first. For equal size, the first +bank (CS2#) is mapped first. The first mapping is always for address +0x00000000, with any additional banks following immediately to create +contiguous memory starting from 0. + +Then, the monitor installs itself at the upper end of the SDRAM area +and allocates memory for use by malloc() and for the global Board +Info data; also, the exception vector code is copied to the low RAM +pages, and the final stack is set up. + +Only after this relocation will you have a "normal" C environment; +until that you are restricted in several ways, mostly because you are +running from ROM, and because the code will have to be relocated to a +new address in RAM. + + +U-Boot Porting Guide: +---------------------- + +[Based on messages by Jerry Van Baren in the U-Boot-Users mailing +list, October 2002] + + +int main(int argc, char *argv[]) +{ + sighandler_t no_more_time; + + signal(SIGALRM, no_more_time); + alarm(PROJECT_DEADLINE - toSec (3 * WEEK)); + + if (available_money > available_manpower) { + Pay consultant to port U-Boot; + return 0; + } + + Download latest U-Boot source; + + Subscribe to u-boot mailing list; + + if (clueless) + email("Hi, I am new to U-Boot, how do I get started?"); + + while (learning) { + Read the README file in the top level directory; + Read http://www.denx.de/twiki/bin/view/DULG/Manual; + Read applicable doc/*.README; + Read the source, Luke; + /* find . -name "*.[chS]" | xargs grep -i <keyword> */ + } + + if (available_money > toLocalCurrency ($2500)) + Buy a BDI3000; + else + Add a lot of aggravation and time; + + if (a similar board exists) { /* hopefully... */ + cp -a board/<similar> board/<myboard> + cp include/configs/<similar>.h include/configs/<myboard>.h + } else { + Create your own board support subdirectory; + Create your own board include/configs/<myboard>.h file; + } + Edit new board/<myboard> files + Edit new include/configs/<myboard>.h + + while (!accepted) { + while (!running) { + do { + Add / modify source code; + } until (compiles); + Debug; + if (clueless) + email("Hi, I am having problems..."); + } + Send patch file to the U-Boot email list; + if (reasonable critiques) + Incorporate improvements from email list code review; + else + Defend code as written; + } + + return 0; +} + +void no_more_time (int sig) +{ + hire_a_guru(); +} + + +Coding Standards: +----------------- + +All contributions to U-Boot should conform to the Linux kernel +coding style; see the kernel coding style guide at +https://www.kernel.org/doc/html/latest/process/coding-style.html, and the +script "scripts/Lindent" in your Linux kernel source directory. + +Source files originating from a different project (for example the +MTD subsystem) are generally exempt from these guidelines and are not +reformatted to ease subsequent migration to newer versions of those +sources. + +Please note that U-Boot is implemented in C (and to some small parts in +Assembler); no C++ is used, so please do not use C++ style comments (//) +in your code. + +Please also stick to the following formatting rules: +- remove any trailing white space +- use TAB characters for indentation and vertical alignment, not spaces +- make sure NOT to use DOS '\r\n' line feeds +- do not add more than 2 consecutive empty lines to source files +- do not add trailing empty lines to source files + +Submissions which do not conform to the standards may be returned +with a request to reformat the changes. + + +Submitting Patches: +------------------- + +Since the number of patches for U-Boot is growing, we need to +establish some rules. Submissions which do not conform to these rules +may be rejected, even when they contain important and valuable stuff. + +Please see http://www.denx.de/wiki/U-Boot/Patches for details. + +Patches shall be sent to the u-boot mailing list <u-boot@lists.denx.de>; +see https://lists.denx.de/listinfo/u-boot + +When you send a patch, please include the following information with +it: + +* For bug fixes: a description of the bug and how your patch fixes + this bug. Please try to include a way of demonstrating that the + patch actually fixes something. + +* For new features: a description of the feature and your + implementation. + +* A CHANGELOG entry as plaintext (separate from the patch) + +* For major contributions, add a MAINTAINERS file with your + information and associated file and directory references. + +* When you add support for a new board, don't forget to add a + maintainer e-mail address to the boards.cfg file, too. + +* If your patch adds new configuration options, don't forget to + document these in the README file. + +* The patch itself. If you are using git (which is *strongly* + recommended) you can easily generate the patch using the + "git format-patch". If you then use "git send-email" to send it to + the U-Boot mailing list, you will avoid most of the common problems + with some other mail clients. + + If you cannot use git, use "diff -purN OLD NEW". If your version of + diff does not support these options, then get the latest version of + GNU diff. + + The current directory when running this command shall be the parent + directory of the U-Boot source tree (i. e. please make sure that + your patch includes sufficient directory information for the + affected files). + + We prefer patches as plain text. MIME attachments are discouraged, + and compressed attachments must not be used. + +* If one logical set of modifications affects or creates several + files, all these changes shall be submitted in a SINGLE patch file. + +* Changesets that contain different, unrelated modifications shall be + submitted as SEPARATE patches, one patch per changeset. + + +Notes: + +* Before sending the patch, run the buildman script on your patched + source tree and make sure that no errors or warnings are reported + for any of the boards. + +* Keep your modifications to the necessary minimum: A patch + containing several unrelated changes or arbitrary reformats will be + returned with a request to re-formatting / split it. + +* If you modify existing code, make sure that your new code does not + add to the memory footprint of the code ;-) Small is beautiful! + When adding new features, these should compile conditionally only + (using #ifdef), and the resulting code with the new feature + disabled must not need more memory than the old code without your + modification. + +* Remember that there is a size limit of 100 kB per message on the + u-boot mailing list. Bigger patches will be moderated. If they are + reasonable and not too big, they will be acknowledged. But patches + bigger than the size limit should be avoided.
diff --git a/api/Kconfig b/api/Kconfig new file mode 100644 index 0000000..e418adc --- /dev/null +++ b/api/Kconfig
@@ -0,0 +1,10 @@ +menu "API" + +config API + bool "Enable U-Boot API" + default n + help + This option enables the U-Boot API. See api/README for more information. + +endmenu +
diff --git a/api/Makefile b/api/Makefile new file mode 100644 index 0000000..bd2d035 --- /dev/null +++ b/api/Makefile
@@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2007 Semihalf + +obj-y += api.o api_display.o api_net.o api_storage.o +obj-$(CONFIG_ARM) += api_platform-arm.o +obj-$(CONFIG_PPC) += api_platform-powerpc.o +obj-$(CONFIG_MIPS) += api_platform-mips.o
diff --git a/api/README b/api/README new file mode 100644 index 0000000..6df225f --- /dev/null +++ b/api/README
@@ -0,0 +1,55 @@ +U-Boot machine/arch independent API for external apps +===================================================== + +1. Main assumptions + + - there is a single entry point (syscall) to the API + + - per current design the syscall is a C-callable function in the U-Boot + text, which might evolve into a real syscall using machine exception trap + once this initial version proves functional + + - the consumer app is responsible for producing appropriate context (call + number and arguments) + + - upon entry, the syscall dispatches the call to other (existing) U-Boot + functional areas like networking or storage operations + + - consumer application will recognize the API is available by searching + a specified (assumed by convention) range of address space for the + signature + + - the U-Boot integral part of the API is meant to be thin and non-intrusive, + leaving as much processing as possible on the consumer application side, + for example it doesn't keep states, but relies on hints from the app and + so on + + - optional (CONFIG_API) + + +2. Calls + + - console related (getc, putc, tstc etc.) + - system (reset, platform info) + - time (delay, current) + - env vars (enumerate all, get, set) + - devices (enumerate all, open, close, read, write); currently two classes + of devices are recognized and supported: network and storage (ide, scsi, + usb etc.) + + +3. Structure overview + + - core API, integral part of U-Boot, mandatory + - implements the single entry point (mimics UNIX syscall) + + - glue + - entry point at the consumer side, allows to make syscall, mandatory + part + + - helper conveniency wrappers so that consumer app does not have to use + the syscall directly, but in a more friendly manner (a la libc calls), + optional part + + - consumer application + - calls directly, or leverages the provided glue mid-layer
diff --git a/api/api.c b/api/api.c new file mode 100644 index 0000000..9f03f1a --- /dev/null +++ b/api/api.c
@@ -0,0 +1,693 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2007 Semihalf + * + * Written by: Rafal Jaworowski <raj@semihalf.com> + */ + +#include <config.h> +#include <command.h> +#include <common.h> +#include <malloc.h> +#include <environment.h> +#include <linux/types.h> +#include <api_public.h> + +#include "api_private.h" + +#define DEBUG +#undef DEBUG + +/***************************************************************************** + * + * This is the API core. + * + * API_ functions are part of U-Boot code and constitute the lowest level + * calls: + * + * - they know what values they need as arguments + * - their direct return value pertains to the API_ "shell" itself (0 on + * success, some error code otherwise) + * - if the call returns a value it is buried within arguments + * + ****************************************************************************/ + +#ifdef DEBUG +#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0) +#else +#define debugf(fmt, args...) +#endif + +typedef int (*cfp_t)(va_list argp); + +static int calls_no; + +/* + * pseudo signature: + * + * int API_getc(int *c) + */ +static int API_getc(va_list ap) +{ + int *c; + + if ((c = (int *)va_arg(ap, uintptr_t)) == NULL) + return API_EINVAL; + + *c = getc(); + return 0; +} + +/* + * pseudo signature: + * + * int API_tstc(int *c) + */ +static int API_tstc(va_list ap) +{ + int *t; + + if ((t = (int *)va_arg(ap, uintptr_t)) == NULL) + return API_EINVAL; + + *t = tstc(); + return 0; +} + +/* + * pseudo signature: + * + * int API_putc(char *ch) + */ +static int API_putc(va_list ap) +{ + char *c; + + if ((c = (char *)va_arg(ap, uintptr_t)) == NULL) + return API_EINVAL; + + putc(*c); + return 0; +} + +/* + * pseudo signature: + * + * int API_puts(char **s) + */ +static int API_puts(va_list ap) +{ + char *s; + + if ((s = (char *)va_arg(ap, uintptr_t)) == NULL) + return API_EINVAL; + + puts(s); + return 0; +} + +/* + * pseudo signature: + * + * int API_reset(void) + */ +static int API_reset(va_list ap) +{ + do_reset(NULL, 0, 0, NULL); + + /* NOT REACHED */ + return 0; +} + +/* + * pseudo signature: + * + * int API_get_sys_info(struct sys_info *si) + * + * fill out the sys_info struct containing selected parameters about the + * machine + */ +static int API_get_sys_info(va_list ap) +{ + struct sys_info *si; + + si = (struct sys_info *)va_arg(ap, uintptr_t); + if (si == NULL) + return API_ENOMEM; + + return (platform_sys_info(si)) ? 0 : API_ENODEV; +} + +/* + * pseudo signature: + * + * int API_udelay(unsigned long *udelay) + */ +static int API_udelay(va_list ap) +{ + unsigned long *d; + + if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL) + return API_EINVAL; + + udelay(*d); + return 0; +} + +/* + * pseudo signature: + * + * int API_get_timer(unsigned long *current, unsigned long *base) + */ +static int API_get_timer(va_list ap) +{ + unsigned long *base, *cur; + + cur = (unsigned long *)va_arg(ap, unsigned long); + if (cur == NULL) + return API_EINVAL; + + base = (unsigned long *)va_arg(ap, unsigned long); + if (base == NULL) + return API_EINVAL; + + *cur = get_timer(*base); + return 0; +} + + +/***************************************************************************** + * + * pseudo signature: + * + * int API_dev_enum(struct device_info *) + * + * + * cookies uniqely identify the previously enumerated device instance and + * provide a hint for what to inspect in current enum iteration: + * + * - net: ð_device struct address from list pointed to by eth_devices + * + * - storage: struct blk_desc struct address from &ide_dev_desc[n], + * &scsi_dev_desc[n] and similar tables + * + ****************************************************************************/ + +static int API_dev_enum(va_list ap) +{ + struct device_info *di; + + /* arg is ptr to the device_info struct we are going to fill out */ + di = (struct device_info *)va_arg(ap, uintptr_t); + if (di == NULL) + return API_EINVAL; + + if (di->cookie == NULL) { + /* start over - clean up enumeration */ + dev_enum_reset(); /* XXX shouldn't the name contain 'stor'? */ + debugf("RESTART ENUM\n"); + + /* net device enumeration first */ + if (dev_enum_net(di)) + return 0; + } + + /* + * The hidden assumption is there can only be one active network + * device and it is identified upon enumeration (re)start, so there's + * no point in trying to find network devices in other cases than the + * (re)start and hence the 'next' device can only be storage + */ + if (!dev_enum_storage(di)) + /* make sure we mark there are no more devices */ + di->cookie = NULL; + + return 0; +} + + +static int API_dev_open(va_list ap) +{ + struct device_info *di; + int err = 0; + + /* arg is ptr to the device_info struct */ + di = (struct device_info *)va_arg(ap, uintptr_t); + if (di == NULL) + return API_EINVAL; + + /* Allow only one consumer of the device at a time */ + if (di->state == DEV_STA_OPEN) + return API_EBUSY; + + if (di->cookie == NULL) + return API_ENODEV; + + if (di->type & DEV_TYP_STOR) + err = dev_open_stor(di->cookie); + + else if (di->type & DEV_TYP_NET) + err = dev_open_net(di->cookie); + else + err = API_ENODEV; + + if (!err) + di->state = DEV_STA_OPEN; + + return err; +} + + +static int API_dev_close(va_list ap) +{ + struct device_info *di; + int err = 0; + + /* arg is ptr to the device_info struct */ + di = (struct device_info *)va_arg(ap, uintptr_t); + if (di == NULL) + return API_EINVAL; + + if (di->state == DEV_STA_CLOSED) + return 0; + + if (di->cookie == NULL) + return API_ENODEV; + + if (di->type & DEV_TYP_STOR) + err = dev_close_stor(di->cookie); + + else if (di->type & DEV_TYP_NET) + err = dev_close_net(di->cookie); + else + /* + * In case of unknown device we cannot change its state, so + * only return error code + */ + err = API_ENODEV; + + if (!err) + di->state = DEV_STA_CLOSED; + + return err; +} + + +/* + * Notice: this is for sending network packets only, as U-Boot does not + * support writing to storage at the moment (12.2007) + * + * pseudo signature: + * + * int API_dev_write( + * struct device_info *di, + * void *buf, + * int *len + * ) + * + * buf: ptr to buffer from where to get the data to send + * + * len: length of packet to be sent (in bytes) + * + */ +static int API_dev_write(va_list ap) +{ + struct device_info *di; + void *buf; + int *len; + int err = 0; + + /* 1. arg is ptr to the device_info struct */ + di = (struct device_info *)va_arg(ap, uintptr_t); + if (di == NULL) + return API_EINVAL; + + /* XXX should we check if device is open? i.e. the ->state ? */ + + if (di->cookie == NULL) + return API_ENODEV; + + /* 2. arg is ptr to buffer from where to get data to write */ + buf = (void *)va_arg(ap, uintptr_t); + if (buf == NULL) + return API_EINVAL; + + /* 3. arg is length of buffer */ + len = (int *)va_arg(ap, uintptr_t); + if (len == NULL) + return API_EINVAL; + if (*len <= 0) + return API_EINVAL; + + if (di->type & DEV_TYP_STOR) + /* + * write to storage is currently not supported by U-Boot: + * no storage device implements block_write() method + */ + return API_ENODEV; + + else if (di->type & DEV_TYP_NET) + err = dev_write_net(di->cookie, buf, *len); + else + err = API_ENODEV; + + return err; +} + + +/* + * pseudo signature: + * + * int API_dev_read( + * struct device_info *di, + * void *buf, + * size_t *len, + * unsigned long *start + * size_t *act_len + * ) + * + * buf: ptr to buffer where to put the read data + * + * len: ptr to length to be read + * - network: len of packet to read (in bytes) + * - storage: # of blocks to read (can vary in size depending on define) + * + * start: ptr to start block (only used for storage devices, ignored for + * network) + * + * act_len: ptr to where to put the len actually read + */ +static int API_dev_read(va_list ap) +{ + struct device_info *di; + void *buf; + lbasize_t *len_stor, *act_len_stor; + lbastart_t *start; + int *len_net, *act_len_net; + + /* 1. arg is ptr to the device_info struct */ + di = (struct device_info *)va_arg(ap, uintptr_t); + if (di == NULL) + return API_EINVAL; + + /* XXX should we check if device is open? i.e. the ->state ? */ + + if (di->cookie == NULL) + return API_ENODEV; + + /* 2. arg is ptr to buffer from where to put the read data */ + buf = (void *)va_arg(ap, uintptr_t); + if (buf == NULL) + return API_EINVAL; + + if (di->type & DEV_TYP_STOR) { + /* 3. arg - ptr to var with # of blocks to read */ + len_stor = (lbasize_t *)va_arg(ap, uintptr_t); + if (!len_stor) + return API_EINVAL; + if (*len_stor <= 0) + return API_EINVAL; + + /* 4. arg - ptr to var with start block */ + start = (lbastart_t *)va_arg(ap, uintptr_t); + + /* 5. arg - ptr to var where to put the len actually read */ + act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t); + if (!act_len_stor) + return API_EINVAL; + + *act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start); + + } else if (di->type & DEV_TYP_NET) { + + /* 3. arg points to the var with length of packet to read */ + len_net = (int *)va_arg(ap, uintptr_t); + if (!len_net) + return API_EINVAL; + if (*len_net <= 0) + return API_EINVAL; + + /* 4. - ptr to var where to put the len actually read */ + act_len_net = (int *)va_arg(ap, uintptr_t); + if (!act_len_net) + return API_EINVAL; + + *act_len_net = dev_read_net(di->cookie, buf, *len_net); + + } else + return API_ENODEV; + + return 0; +} + + +/* + * pseudo signature: + * + * int API_env_get(const char *name, char **value) + * + * name: ptr to name of env var + */ +static int API_env_get(va_list ap) +{ + char *name, **value; + + if ((name = (char *)va_arg(ap, uintptr_t)) == NULL) + return API_EINVAL; + if ((value = (char **)va_arg(ap, uintptr_t)) == NULL) + return API_EINVAL; + + *value = env_get(name); + + return 0; +} + +/* + * pseudo signature: + * + * int API_env_set(const char *name, const char *value) + * + * name: ptr to name of env var + * + * value: ptr to value to be set + */ +static int API_env_set(va_list ap) +{ + char *name, *value; + + if ((name = (char *)va_arg(ap, uintptr_t)) == NULL) + return API_EINVAL; + if ((value = (char *)va_arg(ap, uintptr_t)) == NULL) + return API_EINVAL; + + env_set(name, value); + + return 0; +} + +/* + * pseudo signature: + * + * int API_env_enum(const char *last, char **next) + * + * last: ptr to name of env var found in last iteration + */ +static int API_env_enum(va_list ap) +{ + int i, buflen; + char *last, **next, *s; + ENTRY *match, search; + static char *var; + + last = (char *)va_arg(ap, unsigned long); + + if ((next = (char **)va_arg(ap, uintptr_t)) == NULL) + return API_EINVAL; + + if (last == NULL) { + var = NULL; + i = 0; + } else { + var = strdup(last); + s = strchr(var, '='); + if (s != NULL) + *s = 0; + search.key = var; + i = hsearch_r(search, FIND, &match, &env_htab, 0); + if (i == 0) { + i = API_EINVAL; + goto done; + } + } + + /* match the next entry after i */ + i = hmatch_r("", i, &match, &env_htab); + if (i == 0) + goto done; + buflen = strlen(match->key) + strlen(match->data) + 2; + var = realloc(var, buflen); + snprintf(var, buflen, "%s=%s", match->key, match->data); + *next = var; + return 0; + +done: + free(var); + var = NULL; + *next = NULL; + return i; +} + +/* + * pseudo signature: + * + * int API_display_get_info(int type, struct display_info *di) + */ +static int API_display_get_info(va_list ap) +{ + int type; + struct display_info *di; + + type = va_arg(ap, int); + di = va_arg(ap, struct display_info *); + + return display_get_info(type, di); +} + +/* + * pseudo signature: + * + * int API_display_draw_bitmap(ulong bitmap, int x, int y) + */ +static int API_display_draw_bitmap(va_list ap) +{ + ulong bitmap; + int x, y; + + bitmap = va_arg(ap, ulong); + x = va_arg(ap, int); + y = va_arg(ap, int); + + return display_draw_bitmap(bitmap, x, y); +} + +/* + * pseudo signature: + * + * void API_display_clear(void) + */ +static int API_display_clear(va_list ap) +{ + display_clear(); + return 0; +} + +static cfp_t calls_table[API_MAXCALL] = { NULL, }; + +/* + * The main syscall entry point - this is not reentrant, only one call is + * serviced until finished. + * + * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t); + * + * call: syscall number + * + * retval: points to the return value placeholder, this is the place the + * syscall puts its return value, if NULL the caller does not + * expect a return value + * + * ... syscall arguments (variable number) + * + * returns: 0 if the call not found, 1 if serviced + */ +int syscall(int call, int *retval, ...) +{ + va_list ap; + int rv; + + if (call < 0 || call >= calls_no) { + debugf("invalid call #%d\n", call); + return 0; + } + + if (calls_table[call] == NULL) { + debugf("syscall #%d does not have a handler\n", call); + return 0; + } + + va_start(ap, retval); + rv = calls_table[call](ap); + if (retval != NULL) + *retval = rv; + + return 1; +} + +void api_init(void) +{ + struct api_signature *sig; + + /* TODO put this into linker set one day... */ + calls_table[API_RSVD] = NULL; + calls_table[API_GETC] = &API_getc; + calls_table[API_PUTC] = &API_putc; + calls_table[API_TSTC] = &API_tstc; + calls_table[API_PUTS] = &API_puts; + calls_table[API_RESET] = &API_reset; + calls_table[API_GET_SYS_INFO] = &API_get_sys_info; + calls_table[API_UDELAY] = &API_udelay; + calls_table[API_GET_TIMER] = &API_get_timer; + calls_table[API_DEV_ENUM] = &API_dev_enum; + calls_table[API_DEV_OPEN] = &API_dev_open; + calls_table[API_DEV_CLOSE] = &API_dev_close; + calls_table[API_DEV_READ] = &API_dev_read; + calls_table[API_DEV_WRITE] = &API_dev_write; + calls_table[API_ENV_GET] = &API_env_get; + calls_table[API_ENV_SET] = &API_env_set; + calls_table[API_ENV_ENUM] = &API_env_enum; + calls_table[API_DISPLAY_GET_INFO] = &API_display_get_info; + calls_table[API_DISPLAY_DRAW_BITMAP] = &API_display_draw_bitmap; + calls_table[API_DISPLAY_CLEAR] = &API_display_clear; + calls_no = API_MAXCALL; + + debugf("API initialized with %d calls\n", calls_no); + + dev_stor_init(); + + /* + * Produce the signature so the API consumers can find it + */ + sig = malloc(sizeof(struct api_signature)); + if (sig == NULL) { + printf("API: could not allocate memory for the signature!\n"); + return; + } + + env_set_hex("api_address", (unsigned long)sig); + debugf("API sig @ 0x%lX\n", (unsigned long)sig); + memcpy(sig->magic, API_SIG_MAGIC, 8); + sig->version = API_SIG_VERSION; + sig->syscall = &syscall; + sig->checksum = 0; + sig->checksum = crc32(0, (unsigned char *)sig, + sizeof(struct api_signature)); + debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall); +} + +void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size, + int flags) +{ + int i; + + if (!si->mr || !size || (flags == 0)) + return; + + /* find free slot */ + for (i = 0; i < si->mr_no; i++) + if (si->mr[i].flags == 0) { + /* insert new mem region */ + si->mr[i].start = start; + si->mr[i].size = size; + si->mr[i].flags = flags; + return; + } +}
diff --git a/api/api_display.c b/api/api_display.c new file mode 100644 index 0000000..8ae358a --- /dev/null +++ b/api/api_display.c
@@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2011 The Chromium OS Authors. + */ + +#include <common.h> +#include <api_public.h> +#include <lcd.h> +#include <video_font.h> /* Get font width and height */ + +/* lcd.h needs BMP_LOGO_HEIGHT to calculate CONSOLE_ROWS */ +#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO) +#include <bmp_logo.h> +#endif + +/* TODO(clchiou): add support of video device */ + +int display_get_info(int type, struct display_info *di) +{ + if (!di) + return API_EINVAL; + + switch (type) { + default: + debug("%s: unsupport display device type: %d\n", + __FILE__, type); + return API_ENODEV; +#ifdef CONFIG_LCD + case DISPLAY_TYPE_LCD: + di->pixel_width = panel_info.vl_col; + di->pixel_height = panel_info.vl_row; + di->screen_rows = lcd_get_screen_rows(); + di->screen_cols = lcd_get_screen_columns(); + break; +#endif + } + + di->type = type; + return 0; +} + +int display_draw_bitmap(ulong bitmap, int x, int y) +{ + if (!bitmap) + return API_EINVAL; +#ifdef CONFIG_LCD + return lcd_display_bitmap(bitmap, x, y); +#else + return API_ENODEV; +#endif +} + +void display_clear(void) +{ +#ifdef CONFIG_LCD + lcd_clear(); +#endif +}
diff --git a/api/api_net.c b/api/api_net.c new file mode 100644 index 0000000..7515c26 --- /dev/null +++ b/api/api_net.c
@@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2007 Semihalf + * + * Written by: Rafal Jaworowski <raj@semihalf.com> + */ + +#include <config.h> +#include <common.h> +#include <net.h> +#include <linux/types.h> +#include <api_public.h> + +#define DEBUG +#undef DEBUG + +#ifdef DEBUG +#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0) +#else +#define debugf(fmt, args...) +#endif + +#define errf(fmt, args...) do { printf("ERROR @ %s(): ", __func__); printf(fmt, ##args); } while (0) + +#if defined(CONFIG_CMD_NET) && !defined(CONFIG_DM_ETH) + +static int dev_valid_net(void *cookie) +{ + return ((void *)eth_get_dev() == cookie) ? 1 : 0; +} + +int dev_open_net(void *cookie) +{ + if (!dev_valid_net(cookie)) + return API_ENODEV; + + if (eth_init() < 0) + return API_EIO; + + return 0; +} + +int dev_close_net(void *cookie) +{ + if (!dev_valid_net(cookie)) + return API_ENODEV; + + eth_halt(); + return 0; +} + +/* + * There can only be one active eth interface at a time - use what is + * currently set to eth_current + */ +int dev_enum_net(struct device_info *di) +{ + struct eth_device *eth_current = eth_get_dev(); + + di->type = DEV_TYP_NET; + di->cookie = (void *)eth_current; + if (di->cookie == NULL) + return 0; + + memcpy(di->di_net.hwaddr, eth_current->enetaddr, 6); + + debugf("device found, returning cookie 0x%08x\n", + (u_int32_t)di->cookie); + + return 1; +} + +int dev_write_net(void *cookie, void *buf, int len) +{ + /* XXX verify that cookie points to a valid net device??? */ + + return eth_send(buf, len); +} + +int dev_read_net(void *cookie, void *buf, int len) +{ + /* XXX verify that cookie points to a valid net device??? */ + + return eth_receive(buf, len); +} + +#else + +int dev_open_net(void *cookie) +{ + return API_ENODEV; +} + +int dev_close_net(void *cookie) +{ + return API_ENODEV; +} + +int dev_enum_net(struct device_info *di) +{ + return 0; +} + +int dev_write_net(void *cookie, void *buf, int len) +{ + return API_ENODEV; +} + +int dev_read_net(void *cookie, void *buf, int len) +{ + return API_ENODEV; +} + +#endif
diff --git a/api/api_platform-arm.c b/api/api_platform-arm.c new file mode 100644 index 0000000..6cfd9e6 --- /dev/null +++ b/api/api_platform-arm.c
@@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2007 Semihalf + * + * Written by: Rafal Jaworowski <raj@semihalf.com> + * + * This file contains routines that fetch data from ARM-dependent sources + * (bd_info etc.) + */ + +#include <config.h> +#include <linux/types.h> +#include <api_public.h> + +#include <asm/u-boot.h> +#include <asm/global_data.h> + +#include "api_private.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Important notice: handling of individual fields MUST be kept in sync with + * include/asm-arm/u-boot.h and include/asm-arm/global_data.h, so any changes + * need to reflect their current state and layout of structures involved! + */ +int platform_sys_info(struct sys_info *si) +{ + int i; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) + platform_set_mr(si, gd->bd->bi_dram[i].start, + gd->bd->bi_dram[i].size, MR_ATTR_DRAM); + + return 1; +}
diff --git a/api/api_platform-mips.c b/api/api_platform-mips.c new file mode 100644 index 0000000..51cd328 --- /dev/null +++ b/api/api_platform-mips.c
@@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2007 Stanislav Galabov <sgalabov@gmail.com> + * + * This file contains routines that fetch data from bd_info sources + */ + +#include <config.h> +#include <linux/types.h> +#include <api_public.h> + +#include <asm/u-boot.h> +#include <asm/global_data.h> + +#include "api_private.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Important notice: handling of individual fields MUST be kept in sync with + * include/asm-generic/u-boot.h, so any changes + * need to reflect their current state and layout of structures involved! + */ +int platform_sys_info(struct sys_info *si) +{ + + platform_set_mr(si, gd->bd->bi_memstart, + gd->bd->bi_memsize, MR_ATTR_DRAM); + + return 1; +}
diff --git a/api/api_platform-powerpc.c b/api/api_platform-powerpc.c new file mode 100644 index 0000000..15930cf --- /dev/null +++ b/api/api_platform-powerpc.c
@@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2007 Semihalf + * + * Written by: Rafal Jaworowski <raj@semihalf.com> + * + * This file contains routines that fetch data from PowerPC-dependent sources + * (bd_info etc.) + */ + +#include <config.h> +#include <linux/types.h> +#include <api_public.h> + +#include <asm/u-boot.h> +#include <asm/global_data.h> + +#include "api_private.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Important notice: handling of individual fields MUST be kept in sync with + * include/asm-ppc/u-boot.h and include/asm-ppc/global_data.h, so any changes + * need to reflect their current state and layout of structures involved! + */ +int platform_sys_info(struct sys_info *si) +{ + si->clk_bus = gd->bus_clk; + si->clk_cpu = gd->cpu_clk; + +#if defined(CONFIG_MPC8xx) || defined(CONFIG_E500) || defined(CONFIG_MPC86xx) +#define bi_bar bi_immr_base +#elif defined(CONFIG_MPC83xx) +#define bi_bar bi_immrbar +#endif + +#if defined(bi_bar) + si->bar = gd->bd->bi_bar; +#undef bi_bar +#else + si->bar = 0; +#endif + + platform_set_mr(si, gd->bd->bi_memstart, gd->bd->bi_memsize, MR_ATTR_DRAM); + platform_set_mr(si, gd->bd->bi_flashstart, gd->bd->bi_flashsize, MR_ATTR_FLASH); + platform_set_mr(si, gd->bd->bi_sramstart, gd->bd->bi_sramsize, MR_ATTR_SRAM); + + return 1; +}
diff --git a/api/api_private.h b/api/api_private.h new file mode 100644 index 0000000..8d97ca9 --- /dev/null +++ b/api/api_private.h
@@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2007 Semihalf + * + * Written by: Rafal Jaworowski <raj@semihalf.com> + */ + +#ifndef _API_PRIVATE_H_ +#define _API_PRIVATE_H_ + +void api_init(void); +void platform_set_mr(struct sys_info *, unsigned long, unsigned long, int); +int platform_sys_info(struct sys_info *); + +void dev_enum_reset(void); +int dev_enum_storage(struct device_info *); +int dev_enum_net(struct device_info *); + +int dev_open_stor(void *); +int dev_open_net(void *); +int dev_close_stor(void *); +int dev_close_net(void *); + +lbasize_t dev_read_stor(void *, void *, lbasize_t, lbastart_t); +int dev_read_net(void *, void *, int); +int dev_write_net(void *, void *, int); + +void dev_stor_init(void); + +int display_get_info(int type, struct display_info *di); +int display_draw_bitmap(ulong bitmap, int x, int y); +void display_clear(void); + +#endif /* _API_PRIVATE_H_ */
diff --git a/api/api_storage.c b/api/api_storage.c new file mode 100644 index 0000000..2b90c18 --- /dev/null +++ b/api/api_storage.c
@@ -0,0 +1,351 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2007-2008 Semihalf + * + * Written by: Rafal Jaworowski <raj@semihalf.com> + */ + +#include <config.h> +#include <common.h> +#include <api_public.h> + +#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) +#include <usb.h> +#endif + +#define DEBUG +#undef DEBUG + +#ifdef DEBUG +#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0) +#else +#define debugf(fmt, args...) +#endif + +#define errf(fmt, args...) do { printf("ERROR @ %s(): ", __func__); printf(fmt, ##args); } while (0) + + +#define ENUM_IDE 0 +#define ENUM_USB 1 +#define ENUM_SCSI 2 +#define ENUM_MMC 3 +#define ENUM_SATA 4 +#define ENUM_MAX 5 + +struct stor_spec { + int max_dev; + int enum_started; + int enum_ended; + int type; /* "external" type: DT_STOR_{IDE,USB,etc} */ + char *name; +}; + +static struct stor_spec specs[ENUM_MAX] = { { 0, 0, 0, 0, NULL }, }; + +#ifndef CONFIG_SYS_MMC_MAX_DEVICE +#define CONFIG_SYS_MMC_MAX_DEVICE 1 +#endif + +void dev_stor_init(void) +{ +#if defined(CONFIG_IDE) + specs[ENUM_IDE].max_dev = CONFIG_SYS_IDE_MAXDEVICE; + specs[ENUM_IDE].enum_started = 0; + specs[ENUM_IDE].enum_ended = 0; + specs[ENUM_IDE].type = DEV_TYP_STOR | DT_STOR_IDE; + specs[ENUM_IDE].name = "ide"; +#endif +#if defined(CONFIG_CMD_MMC) + specs[ENUM_MMC].max_dev = CONFIG_SYS_MMC_MAX_DEVICE; + specs[ENUM_MMC].enum_started = 0; + specs[ENUM_MMC].enum_ended = 0; + specs[ENUM_MMC].type = DEV_TYP_STOR | DT_STOR_MMC; + specs[ENUM_MMC].name = "mmc"; +#endif +#if defined(CONFIG_SATA) + specs[ENUM_SATA].max_dev = CONFIG_SYS_SATA_MAX_DEVICE; + specs[ENUM_SATA].enum_started = 0; + specs[ENUM_SATA].enum_ended = 0; + specs[ENUM_SATA].type = DEV_TYP_STOR | DT_STOR_SATA; + specs[ENUM_SATA].name = "sata"; +#endif +#if defined(CONFIG_SCSI) + specs[ENUM_SCSI].max_dev = CONFIG_SYS_SCSI_MAX_DEVICE; + specs[ENUM_SCSI].enum_started = 0; + specs[ENUM_SCSI].enum_ended = 0; + specs[ENUM_SCSI].type = DEV_TYP_STOR | DT_STOR_SCSI; + specs[ENUM_SCSI].name = "scsi"; +#endif +#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) + specs[ENUM_USB].max_dev = USB_MAX_STOR_DEV; + specs[ENUM_USB].enum_started = 0; + specs[ENUM_USB].enum_ended = 0; + specs[ENUM_USB].type = DEV_TYP_STOR | DT_STOR_USB; + specs[ENUM_USB].name = "usb"; +#endif +} + +/* + * Finds next available device in the storage group + * + * type: storage group type - ENUM_IDE, ENUM_SCSI etc. + * + * more: returns 0/1 depending if there are more devices in this group + * available (for future iterations) + * + * returns: 0/1 depending if device found in this iteration + */ +static int dev_stor_get(int type, int *more, struct device_info *di) +{ + struct blk_desc *dd; + int found = 0; + int found_last = 0; + int i = 0; + + /* Wasn't configured for this type, return 0 directly */ + if (specs[type].name == NULL) + return 0; + + if (di->cookie != NULL) { + /* Find the last device we've returned */ + for (i = 0; i < specs[type].max_dev; i++) { + if (di->cookie == + (void *)blk_get_dev(specs[type].name, i)) { + i += 1; + found_last = 1; + break; + } + } + + if (!found_last) + i = 0; + } + + for (; i < specs[type].max_dev; i++) { + di->cookie = (void *)blk_get_dev(specs[type].name, i); + + if (di->cookie != NULL) { + found = 1; + break; + } + } + + if (i == specs[type].max_dev) + *more = 0; + else + *more = 1; + + if (found) { + di->type = specs[type].type; + + dd = (struct blk_desc *)di->cookie; + if (dd->type == DEV_TYPE_UNKNOWN) { + debugf("device instance exists, but is not active.."); + found = 0; + } else { + di->di_stor.block_count = dd->lba; + di->di_stor.block_size = dd->blksz; + } + } else { + di->cookie = NULL; + } + + return found; +} + + +/* returns: ENUM_IDE, ENUM_USB etc. based on struct blk_desc */ + +static int dev_stor_type(struct blk_desc *dd) +{ + int i, j; + + for (i = ENUM_IDE; i < ENUM_MAX; i++) + for (j = 0; j < specs[i].max_dev; j++) + if (dd == blk_get_dev(specs[i].name, j)) + return i; + + return ENUM_MAX; +} + + +/* returns: 0/1 whether cookie points to some device in this group */ + +static int dev_is_stor(int type, struct device_info *di) +{ + return (dev_stor_type(di->cookie) == type) ? 1 : 0; +} + + +static int dev_enum_stor(int type, struct device_info *di) +{ + int found = 0, more = 0; + + debugf("called, type %d\n", type); + + /* + * Formulae for enumerating storage devices: + * 1. if cookie (hint from previous enum call) is NULL we start again + * with enumeration, so return the first available device, done. + * + * 2. if cookie is not NULL, check if it identifies some device in + * this group: + * + * 2a. if cookie is a storage device from our group (IDE, USB etc.), + * return next available (if exists) in this group + * + * 2b. if it isn't device from our group, check if such devices were + * ever enumerated before: + * - if not, return the first available device from this group + * - else return 0 + */ + + if (di->cookie == NULL) { + debugf("group%d - enum restart\n", type); + + /* + * 1. Enumeration (re-)started: take the first available + * device, if exists + */ + found = dev_stor_get(type, &more, di); + specs[type].enum_started = 1; + + } else if (dev_is_stor(type, di)) { + debugf("group%d - enum continued for the next device\n", type); + + if (specs[type].enum_ended) { + debugf("group%d - nothing more to enum!\n", type); + return 0; + } + + /* 2a. Attempt to take a next available device in the group */ + found = dev_stor_get(type, &more, di); + + } else { + if (specs[type].enum_ended) { + debugf("group %d - already enumerated, skipping\n", type); + return 0; + } + + debugf("group%d - first time enum\n", type); + + if (specs[type].enum_started == 0) { + /* + * 2b. If enumerating devices in this group did not + * happen before, it means the cookie pointed to a + * device from some other group (another storage + * group, or network); in this case try to take the + * first available device from our group + */ + specs[type].enum_started = 1; + + /* + * Attempt to take the first device in this group: + *'first element' flag is set + */ + found = dev_stor_get(type, &more, di); + + } else { + errf("group%d - out of order iteration\n", type); + found = 0; + more = 0; + } + } + + /* + * If there are no more devices in this group, consider its + * enumeration finished + */ + specs[type].enum_ended = (!more) ? 1 : 0; + + if (found) + debugf("device found, returning cookie 0x%08x\n", + (u_int32_t)di->cookie); + else + debugf("no device found\n"); + + return found; +} + +void dev_enum_reset(void) +{ + int i; + + for (i = 0; i < ENUM_MAX; i ++) { + specs[i].enum_started = 0; + specs[i].enum_ended = 0; + } +} + +int dev_enum_storage(struct device_info *di) +{ + int i; + + /* check: ide, usb, scsi, mmc */ + for (i = ENUM_IDE; i < ENUM_MAX; i ++) { + if (dev_enum_stor(i, di)) + return 1; + } + + return 0; +} + +static int dev_stor_is_valid(int type, struct blk_desc *dd) +{ + int i; + + for (i = 0; i < specs[type].max_dev; i++) + if (dd == blk_get_dev(specs[type].name, i)) + if (dd->type != DEV_TYPE_UNKNOWN) + return 1; + + return 0; +} + + +int dev_open_stor(void *cookie) +{ + int type = dev_stor_type(cookie); + + if (type == ENUM_MAX) + return API_ENODEV; + + if (dev_stor_is_valid(type, (struct blk_desc *)cookie)) + return 0; + + return API_ENODEV; +} + + +int dev_close_stor(void *cookie) +{ + /* + * Not much to do as we actually do not alter storage devices upon + * close + */ + return 0; +} + + +lbasize_t dev_read_stor(void *cookie, void *buf, lbasize_t len, lbastart_t start) +{ + int type; + struct blk_desc *dd = (struct blk_desc *)cookie; + + if ((type = dev_stor_type(dd)) == ENUM_MAX) + return 0; + + if (!dev_stor_is_valid(type, dd)) + return 0; + +#ifdef CONFIG_BLK + return blk_dread(dd, start, len, buf); +#else + if ((dd->block_read) == NULL) { + debugf("no block_read() for device 0x%08x\n", cookie); + return 0; + } + + return dd->block_read(dd, start, len, buf); +#endif /* defined(CONFIG_BLK) */ +}
diff --git a/arch/.gitignore b/arch/.gitignore new file mode 100644 index 0000000..2714b86 --- /dev/null +++ b/arch/.gitignore
@@ -0,0 +1 @@ +/*/include/asm/arch
diff --git a/arch/Kconfig b/arch/Kconfig new file mode 100644 index 0000000..11e7713 --- /dev/null +++ b/arch/Kconfig
@@ -0,0 +1,240 @@ +config CREATE_ARCH_SYMLINK + bool + +config HAVE_ARCH_IOREMAP + bool + +choice + prompt "Architecture select" + default SANDBOX + +config ARC + bool "ARC architecture" + select ARCH_EARLY_INIT_R + select ARC_TIMER + select CLK + select HAVE_PRIVATE_LIBGCC + select SUPPORT_OF_CONTROL + select TIMER + +config ARM + bool "ARM architecture" + select CREATE_ARCH_SYMLINK + select HAVE_PRIVATE_LIBGCC if !ARM64 + select SUPPORT_OF_CONTROL + +config M68K + bool "M68000 architecture" + select HAVE_PRIVATE_LIBGCC + select SYS_BOOT_GET_CMDLINE + select SYS_BOOT_GET_KBD + +config MICROBLAZE + bool "MicroBlaze architecture" + select SUPPORT_OF_CONTROL + imply CMD_IRQ + +config MIPS + bool "MIPS architecture" + select HAVE_ARCH_IOREMAP + select HAVE_PRIVATE_LIBGCC + select SUPPORT_OF_CONTROL + +config NDS32 + bool "NDS32 architecture" + select SUPPORT_OF_CONTROL + +config NIOS2 + bool "Nios II architecture" + select CPU + select DM + select OF_CONTROL + select SUPPORT_OF_CONTROL + imply CMD_DM + +config PPC + bool "PowerPC architecture" + select HAVE_PRIVATE_LIBGCC + select SUPPORT_OF_CONTROL + select SYS_BOOT_GET_CMDLINE + select SYS_BOOT_GET_KBD + +config RISCV + bool "RISC-V architecture" + select SUPPORT_OF_CONTROL + select OF_CONTROL + select DM + imply DM_SERIAL + imply DM_ETH + imply DM_MMC + imply DM_SPI + imply DM_SPI_FLASH + imply BLK + imply CLK + imply MTD + imply TIMER + imply CMD_DM + +config SANDBOX + bool "Sandbox" + select BOARD_LATE_INIT + select DM + select DM_GPIO + select DM_I2C + select DM_KEYBOARD + select DM_MMC + select DM_SERIAL + select DM_SPI + select DM_SPI_FLASH + select HAVE_BLOCK_DEVICE + select LZO + select SPI + select SUPPORT_OF_CONTROL + imply BITREVERSE + select BLOBLIST + imply CMD_DM + imply CMD_GETTIME + imply CMD_HASH + imply CMD_IO + imply CMD_IOTRACE + imply CMD_LZMADEC + imply CMD_SATA + imply CMD_SF_TEST + imply CRC32_VERIFY + imply FAT_WRITE + imply FIRMWARE + imply HASH_VERIFY + imply LZMA + imply SCSI + imply TEE + imply AVB_VERIFY + imply LIBAVB + imply CMD_AVB + imply UDP_FUNCTION_FASTBOOT + imply VIRTIO_MMIO + imply VIRTIO_PCI + imply VIRTIO_SANDBOX + imply VIRTIO_BLK + imply VIRTIO_NET + imply DM_SOUND + +config SH + bool "SuperH architecture" + select HAVE_PRIVATE_LIBGCC + +config X86 + bool "x86 architecture" + select CREATE_ARCH_SYMLINK + select DM + select DM_PCI + select HAVE_ARCH_IOMAP + select HAVE_PRIVATE_LIBGCC + select OF_CONTROL + select PCI + select SUPPORT_OF_CONTROL + select TIMER + select USE_PRIVATE_LIBGCC + select X86_TSC_TIMER + imply BLK + imply CMD_DM + imply CMD_FPGA_LOADMK + imply CMD_GETTIME + imply CMD_IO + imply CMD_IRQ + imply CMD_PCI + imply CMD_SF_TEST + imply CMD_ZBOOT + imply DM_ETH + imply DM_GPIO + imply DM_KEYBOARD + imply DM_MMC + imply DM_RTC + imply DM_SCSI + imply DM_SERIAL + imply DM_SPI + imply DM_SPI_FLASH + imply DM_USB + imply DM_VIDEO + imply SYSRESET + imply SYSRESET_X86 + imply USB_ETHER_ASIX + imply USB_ETHER_SMSC95XX + imply USB_HOST_ETHER + +config XTENSA + bool "Xtensa architecture" + select CREATE_ARCH_SYMLINK + select SUPPORT_OF_CONTROL + +endchoice + +config SYS_ARCH + string + help + This option should contain the architecture name to build the + appropriate arch/<CONFIG_SYS_ARCH> directory. + All the architectures should specify this option correctly. + +config SYS_CPU + string + help + This option should contain the CPU name to build the correct + arch/<CONFIG_SYS_ARCH>/cpu/<CONFIG_SYS_CPU> directory. + + This is optional. For those targets without the CPU directory, + leave this option empty. + +config SYS_SOC + string + help + This option should contain the SoC name to build the directory + arch/<CONFIG_SYS_ARCH>/cpu/<CONFIG_SYS_CPU>/<CONFIG_SYS_SOC>. + + This is optional. For those targets without the SoC directory, + leave this option empty. + +config SYS_VENDOR + string + help + This option should contain the vendor name of the target board. + If it is set and + board/<CONFIG_SYS_VENDOR>/common/Makefile exists, the vendor common + directory is compiled. + If CONFIG_SYS_BOARD is also set, the sources under + board/<CONFIG_SYS_VENDOR>/<CONFIG_SYS_BOARD> directory are compiled. + + This is optional. For those targets without the vendor directory, + leave this option empty. + +config SYS_BOARD + string + help + This option should contain the name of the target board. + If it is set, either board/<CONFIG_SYS_VENDOR>/<CONFIG_SYS_BOARD> + or board/<CONFIG_SYS_BOARD> directory is compiled depending on + whether CONFIG_SYS_VENDOR is set or not. + + This is optional. For those targets without the board directory, + leave this option empty. + +config SYS_CONFIG_NAME + string + help + This option should contain the base name of board header file. + The header file include/configs/<CONFIG_SYS_CONFIG_NAME>.h + should be included from include/config.h. + +source "arch/arc/Kconfig" +source "arch/arm/Kconfig" +source "arch/m68k/Kconfig" +source "arch/microblaze/Kconfig" +source "arch/mips/Kconfig" +source "arch/nds32/Kconfig" +source "arch/nios2/Kconfig" +source "arch/powerpc/Kconfig" +source "arch/sandbox/Kconfig" +source "arch/sh/Kconfig" +source "arch/x86/Kconfig" +source "arch/xtensa/Kconfig" +source "arch/riscv/Kconfig" +
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig new file mode 100644 index 0000000..38b6ffe --- /dev/null +++ b/arch/arc/Kconfig
@@ -0,0 +1,174 @@ +menu "ARC architecture" + depends on ARC + +config SYS_ARCH + default "arc" + +config SYS_CPU + default "arcv1" if ISA_ARCOMPACT + default "arcv2" if ISA_ARCV2 + +choice + prompt "ARC Instruction Set" + default ISA_ARCOMPACT + +config ISA_ARCOMPACT + bool "ARCompact ISA" + help + The original ARC ISA of ARC600/700 cores + +config ISA_ARCV2 + bool "ARC ISA v2" + help + ISA for the Next Generation ARC-HS cores + +endchoice + +choice + prompt "CPU selection" + default CPU_ARC770D if ISA_ARCOMPACT + default CPU_ARCHS38 if ISA_ARCV2 + +config CPU_ARC750D + bool "ARC 750D" + depends on ISA_ARCOMPACT + select ARC_MMU_V2 + help + Choose this option to build an U-Boot for ARC750D CPU. + +config CPU_ARC770D + bool "ARC 770D" + depends on ISA_ARCOMPACT + select ARC_MMU_V3 + help + Choose this option to build an U-Boot for ARC770D CPU. + +config CPU_ARCEM6 + bool "ARC EM6" + depends on ISA_ARCV2 + select ARC_MMU_ABSENT + help + Next Generation ARC Core based on ISA-v2 ISA without MMU. + +config CPU_ARCHS36 + bool "ARC HS36" + depends on ISA_ARCV2 + select ARC_MMU_ABSENT + help + Next Generation ARC Core based on ISA-v2 ISA without MMU. + +config CPU_ARCHS38 + bool "ARC HS38" + depends on ISA_ARCV2 + select ARC_MMU_V4 + help + Next Generation ARC Core based on ISA-v2 ISA with MMU. + +endchoice + +choice + prompt "MMU Version" + default ARC_MMU_V3 if CPU_ARC770D + default ARC_MMU_V2 if CPU_ARC750D + default ARC_MMU_ABSENT if CPU_ARCEM6 + default ARC_MMU_ABSENT if CPU_ARCHS36 + default ARC_MMU_V4 if CPU_ARCHS38 + +config ARC_MMU_ABSENT + bool "No MMU" + help + No MMU + +config ARC_MMU_V2 + bool "MMU v2" + depends on CPU_ARC750D + help + Fixed the deficiency of v1 - possible thrashing in memcpy sceanrio + when 2 D-TLB and 1 I-TLB entries index into same 2way set. + +config ARC_MMU_V3 + bool "MMU v3" + depends on CPU_ARC770D + help + Introduced with ARC700 4.10: New Features + Variable Page size (1k-16k), var JTLB size 128 x (2 or 4) + Shared Address Spaces (SASID) + +config ARC_MMU_V4 + bool "MMU v4" + depends on CPU_ARCHS38 + help + Introduced as a part of ARC HS38 release. + +endchoice + +config CPU_BIG_ENDIAN + bool "Enable Big Endian Mode" + default n + help + Build kernel for Big Endian Mode of ARC CPU + +config SYS_ICACHE_OFF + bool "Do not use Instruction Cache" + default n + +config SYS_DCACHE_OFF + bool "Do not use Data Cache" + default n + +menuconfig ARC_DBG + bool "ARC debugging" + default n + +if ARC_DBG + +config ARC_DBG_IOC_ENABLE + bool "Enable IO coherency unit" + depends on CPU_ARCHS38 + default n + help + Enable IO coherency unit to debug problems with caches and + DMA peripherals. + NOTE: as of today linux will not work properly if this option + is enabled in u-boot! + +endif + +choice + prompt "Target select" + default TARGET_AXS103 + +config TARGET_TB100 + bool "Support tb100" + +config TARGET_NSIM + bool "Support standalone nSIM & Free nSIM" + +config TARGET_AXS101 + bool "Support Synopsys Designware SDP board AXS101" + +config TARGET_AXS103 + bool "Support Synopsys Designware SDP board AXS103" + +config TARGET_EMSDP + bool "Synopsys EM Software Development Platform" + select CPU_ARCEM6 + +config TARGET_HSDK + bool "Support Synpsys HS DevelopmentKit board" + +config TARGET_IOT_DEVKIT + bool "Synopsys Brite IoT Development kit" + select CPU_ARCEM6 + +endchoice + +source "board/abilis/tb100/Kconfig" +source "board/synopsys/Kconfig" +source "board/synopsys/axs10x/Kconfig" +source "board/synopsys/emsdp/Kconfig" +source "board/synopsys/hsdk/Kconfig" +source "board/synopsys/iot_devkit/Kconfig" + +endmenu +
diff --git a/arch/arc/Makefile b/arch/arc/Makefile new file mode 100644 index 0000000..44568f8 --- /dev/null +++ b/arch/arc/Makefile
@@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0+ + +libs-y += arch/arc/cpu/$(CPU)/ +libs-y += arch/arc/lib/ + +# MetaWare debugger doesn't support PIE (position-independent executable) +# so the only way to load U-Boot in MDB is to fake it by: +# 1. Reset PIE flag in ELF header +# 2. Strip all debug information from elf +ifdef CONFIG_SYS_LITTLE_ENDIAN + EXEC_TYPE_OFFSET=16 +else + EXEC_TYPE_OFFSET=17 +endif + +mdbtrick: u-boot + $(Q)printf '\x02' | dd of=u-boot bs=1 seek=$(EXEC_TYPE_OFFSET) count=1 \ + conv=notrunc &> /dev/null + $(Q)$(CROSS_COMPILE)strip -g u-boot
diff --git a/arch/arc/config.mk b/arch/arc/config.mk new file mode 100644 index 0000000..18005d9 --- /dev/null +++ b/arch/arc/config.mk
@@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + +ifndef CONFIG_CPU_BIG_ENDIAN +CONFIG_SYS_LITTLE_ENDIAN = 1 +else +CONFIG_SYS_BIG_ENDIAN = 1 +endif + +ifdef CONFIG_SYS_LITTLE_ENDIAN +PLATFORM_LDFLAGS += -EL +PLATFORM_CPPFLAGS += -mlittle-endian +endif + +ifdef CONFIG_SYS_BIG_ENDIAN +PLATFORM_LDFLAGS += -EB +PLATFORM_CPPFLAGS += -mbig-endian +endif + +ifdef CONFIG_ARC_MMU_VER +CONFIG_MMU = 1 +endif + +ifdef CONFIG_CPU_ARC750D +PLATFORM_CPPFLAGS += -mcpu=arc700 +endif + +ifdef CONFIG_CPU_ARC770D +PLATFORM_CPPFLAGS += -mcpu=arc700 -mlock -mswape +endif + +ifdef CONFIG_CPU_ARCEM6 +PLATFORM_CPPFLAGS += -mcpu=arcem +endif + +ifdef CONFIG_CPU_ARCHS34 +PLATFORM_CPPFLAGS += -mcpu=archs +endif + +ifdef CONFIG_CPU_ARCHS38 +PLATFORM_CPPFLAGS += -mcpu=archs +endif + +PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -gdwarf-2 -mno-sdata +PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections -fno-common + +# Needed for relocation +LDFLAGS_FINAL += -pie --gc-sections + +# Load address for standalone apps +CONFIG_STANDALONE_LOAD_ADDR ?= 0x82000000
diff --git a/arch/arc/cpu/arcv1/Makefile b/arch/arc/cpu/arcv1/Makefile new file mode 100644 index 0000000..4d42ac6 --- /dev/null +++ b/arch/arc/cpu/arcv1/Makefile
@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + +obj-y += ivt.o
diff --git a/arch/arc/cpu/arcv1/ivt.S b/arch/arc/cpu/arcv1/ivt.S new file mode 100644 index 0000000..3d63430 --- /dev/null +++ b/arch/arc/cpu/arcv1/ivt.S
@@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +.section .ivt, "ax",@progbits +.align 4 +_ivt: + /* Critical system events */ + j _start /* 0 - 0x000 */ + j memory_error /* 1 - 0x008 */ + j instruction_error /* 2 - 0x010 */ + + /* Device interrupts */ +.rept 29 + j interrupt_handler /* 3:31 - 0x018:0xF8 */ +.endr + /* Exceptions */ + j EV_MachineCheck /* 0x100, Fatal Machine check (0x20) */ + j EV_TLBMissI /* 0x108, Intruction TLB miss (0x21) */ + j EV_TLBMissD /* 0x110, Data TLB miss (0x22) */ + j EV_TLBProtV /* 0x118, Protection Violation (0x23) + or Misaligned Access */ + j EV_PrivilegeV /* 0x120, Privilege Violation (0x24) */ + j EV_Trap /* 0x128, Trap exception (0x25) */ + j EV_Extension /* 0x130, Extn Intruction Excp (0x26) */
diff --git a/arch/arc/cpu/arcv2/Makefile b/arch/arc/cpu/arcv2/Makefile new file mode 100644 index 0000000..ab74026 --- /dev/null +++ b/arch/arc/cpu/arcv2/Makefile
@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved. + +obj-y += ivt.o
diff --git a/arch/arc/cpu/arcv2/ivt.S b/arch/arc/cpu/arcv2/ivt.S new file mode 100644 index 0000000..3f5b409 --- /dev/null +++ b/arch/arc/cpu/arcv2/ivt.S
@@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved. + */ + +.section .ivt, "a",@progbits +.align 4 + /* Critical system events */ +.word _start /* 0x00 - Reset */ +.word memory_error /* 0x01 - Memory Error */ +.word instruction_error /* 0x02 - Instruction Error */ + + /* Exceptions */ +.word EV_MachineCheck /* 0x03 - Fatal Machine check */ +.word EV_TLBMissI /* 0x04 - Intruction TLB miss */ +.word EV_TLBMissD /* 0x05 - Data TLB miss */ +.word EV_TLBProtV /* 0x06 - Protection Violation or Misaligned Access */ +.word EV_PrivilegeV /* 0x07 - Privilege Violation */ +.word EV_SWI /* 0x08 - Software Interrupt */ +.word EV_Trap /* 0x09 - Trap */ +.word EV_Extension /* 0x0A - Extension Intruction Exception */ +.word EV_DivZero /* 0x0B - Division by Zero */ +.word EV_DCError /* 0x0C - Data cache consistency error */ +.word EV_Maligned /* 0x0D - Misaligned data access */ +.word 0 /* 0x0E - Unused */ +.word 0 /* 0x0F - Unused */ + + /* Device interrupts */ +.rept 240 +.word interrupt_handler /* 0x10 - 0xFF */ +.endr
diff --git a/arch/arc/cpu/u-boot.lds b/arch/arc/cpu/u-boot.lds new file mode 100644 index 0000000..e12145c --- /dev/null +++ b/arch/arc/cpu/u-boot.lds
@@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#include <config.h> + +OUTPUT_FORMAT("elf32-littlearc", "elf32-bigarc", "elf32-littlearc") +OUTPUT_ARCH(arc) +ENTRY(_start) +SECTIONS +{ + . = CONFIG_SYS_TEXT_BASE; + __image_copy_start = .; + . = ALIGN(1024); + __ivt_start = .; + .ivt : + { + KEEP(*(.ivt)) + } + __ivt_end = .; + + . = ALIGN(1024); + __text_start = .; + .text : { + arch/arc/lib/start.o (.text*) + *(.text*) + } + __text_end = .; + + . = ALIGN(4); + .rodata : { + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + __rel_dyn_start = .; + .rela.dyn : { + *(.rela.dyn) + } + __rel_dyn_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss : { + *(.bss*) + } + __bss_end = .; + + . = ALIGN(4); + __image_copy_end = .; + __init_end = .; +}
diff --git a/arch/arc/dts/Makefile b/arch/arc/dts/Makefile new file mode 100644 index 0000000..4f1e463 --- /dev/null +++ b/arch/arc/dts/Makefile
@@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0+ + +dtb-$(CONFIG_TARGET_AXS101) += axs101.dtb +dtb-$(CONFIG_TARGET_AXS103) += axs103.dtb +dtb-$(CONFIG_TARGET_NSIM) += nsim.dtb +dtb-$(CONFIG_TARGET_TB100) += abilis_tb100.dtb +dtb-$(CONFIG_TARGET_EMSDP) += emsdp.dtb +dtb-$(CONFIG_TARGET_HSDK) += hsdk.dtb +dtb-$(CONFIG_TARGET_IOT_DEVKIT) += iot_devkit.dtb + +targets += $(dtb-y) + +DTC_FLAGS += -R 4 -p 0x1000 + +PHONY += dtbs +dtbs: $(addprefix $(obj)/, $(dtb-y)) + @: + +clean-files := *.dtb
diff --git a/arch/arc/dts/abilis_tb100.dts b/arch/arc/dts/abilis_tb100.dts new file mode 100644 index 0000000..19e45b9 --- /dev/null +++ b/arch/arc/dts/abilis_tb100.dts
@@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Synopsys, Inc. (www.synopsys.com) + */ +/dts-v1/; + +#include "skeleton.dtsi" + +/ { + model = "abilis,tb100"; + + aliases { + console = &uart0; + }; + + cpu_card { + core_clk: core_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <500000000>; + u-boot,dm-pre-reloc; + }; + }; + + uart0: serial@ff100000 { + compatible = "snps,dw-apb-uart"; + reg = <0xff100000 0x1000>; + reg-shift = <2>; + reg-io-width = <4>; + }; +};
diff --git a/arch/arc/dts/axc001.dtsi b/arch/arc/dts/axc001.dtsi new file mode 100644 index 0000000..412580a --- /dev/null +++ b/arch/arc/dts/axc001.dtsi
@@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Synopsys, Inc. All rights reserved. + */ + +/include/ "skeleton.dtsi" + +/ { + cpu_card { + core_clk: core_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <750000000>; + u-boot,dm-pre-reloc; + }; + }; +}; +
diff --git a/arch/arc/dts/axc003.dtsi b/arch/arc/dts/axc003.dtsi new file mode 100644 index 0000000..75a9de6 --- /dev/null +++ b/arch/arc/dts/axc003.dtsi
@@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Synopsys, Inc. All rights reserved. + */ + +/include/ "skeleton.dtsi" + +/ { + cpu_card { + core_clk: core_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <100000000>; + u-boot,dm-pre-reloc; + }; + }; +}; +
diff --git a/arch/arc/dts/axs101.dts b/arch/arc/dts/axs101.dts new file mode 100644 index 0000000..fc9fa93 --- /dev/null +++ b/arch/arc/dts/axs101.dts
@@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Synopsys, Inc. All rights reserved. + */ +/dts-v1/; + +/include/ "axc001.dtsi" +/include/ "axs10x_mb.dtsi" + + +/ { + model = "snps,axs101"; + + chosen { + stdout-path = &uart0; + }; +}; +
diff --git a/arch/arc/dts/axs103.dts b/arch/arc/dts/axs103.dts new file mode 100644 index 0000000..6e2dd00 --- /dev/null +++ b/arch/arc/dts/axs103.dts
@@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Synopsys, Inc. All rights reserved. + */ +/dts-v1/; + +/include/ "axc003.dtsi" +/include/ "axs10x_mb.dtsi" + + +/ { + model = "snps,axs103"; + + chosen { + stdout-path = &uart0; + }; +}; +
diff --git a/arch/arc/dts/axs10x_mb.dtsi b/arch/arc/dts/axs10x_mb.dtsi new file mode 100644 index 0000000..dfc0381 --- /dev/null +++ b/arch/arc/dts/axs10x_mb.dtsi
@@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Synopsys, Inc. All rights reserved. + */ + +/ { + aliases { + spi0 = &spi0; + }; + + axs10x_mb@e0000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0xe0000000 0x10000000>; + u-boot,dm-pre-reloc; + + clocks { + compatible = "simple-bus"; + u-boot,dm-pre-reloc; + + apbclk: apbclk { + compatible = "fixed-clock"; + clock-frequency = <50000000>; + #clock-cells = <0>; + }; + + uartclk: uartclk { + compatible = "fixed-clock"; + clock-frequency = <33333333>; + #clock-cells = <0>; + u-boot,dm-pre-reloc; + }; + }; + + ethernet@18000 { + compatible = "altr,socfpga-stmmac"; + reg = < 0x18000 0x2000 >; + phy-mode = "gmii"; + snps,pbl = < 32 >; + clocks = <&apbclk>; + clock-names = "stmmaceth"; + max-speed = <100>; + }; + + ehci@0x40000 { + compatible = "generic-ehci"; + reg = < 0x40000 0x100 >; + }; + + ohci@0x60000 { + compatible = "generic-ohci"; + reg = < 0x60000 0x100 >; + }; + + uart0: serial0@22000 { + compatible = "snps,dw-apb-uart"; + reg = <0x22000 0x100>; + clocks = <&uartclk>; + reg-shift = <2>; + reg-io-width = <4>; + }; + + spi0: spi@0 { + compatible = "snps,dw-apb-ssi"; + reg = <0x0 0x100>; + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <4000000>; + clocks = <&apbclk>; + clock-names = "spi_clk"; + cs-gpio = <&cs_gpio 0>; + spi_flash@0 { + compatible = "spi-flash"; + reg = <0>; + spi-max-frequency = <4000000>; + }; + }; + + cs_gpio: gpio@11218 { + compatible = "snps,creg-gpio"; + reg = <0x11218 0x4>; + gpio-controller; + #gpio-cells = <1>; + gpio-bank-name = "axs-spi-cs"; + gpio-count = <1>; + gpio-first-shift = <0>; + gpio-bit-per-line = <2>; + gpio-activate-val = <1>; + gpio-deactivate-val = <3>; + gpio-default-val = <1>; + }; + }; +};
diff --git a/arch/arc/dts/emsdp.dts b/arch/arc/dts/emsdp.dts new file mode 100644 index 0000000..d307b95 --- /dev/null +++ b/arch/arc/dts/emsdp.dts
@@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Synopsys, Inc. All rights reserved. + */ +/dts-v1/; + +#include "skeleton.dtsi" + +/ { + model = "snps,emsdp"; + + #address-cells = <1>; + #size-cells = <1>; + + aliases { + console = &uart0; + }; + + cpu_card { + core_clk: core_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <40000000>; + u-boot,dm-pre-reloc; + }; + }; + + uart0: serial0@f0004000 { + compatible = "snps,dw-apb-uart"; + clock-frequency = <100000000>; + reg = <0xf0004000 0x1000>; + reg-shift = <2>; + reg-io-width = <4>; + }; +};
diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts new file mode 100644 index 0000000..f024b96 --- /dev/null +++ b/arch/arc/dts/hsdk.dts
@@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Synopsys, Inc. All rights reserved. + */ +/dts-v1/; + +#include "skeleton.dtsi" +#include "dt-bindings/clock/snps,hsdk-cgu.h" + +/ { + model = "snps,hsdk"; + + #address-cells = <1>; + #size-cells = <1>; + + aliases { + console = &uart0; + spi0 = &spi0; + }; + + cpu_card { + core_clk: core_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <500000000>; + u-boot,dm-pre-reloc; + }; + }; + + clk-fmeas { + clocks = <&cgu_clk CLK_ARC_PLL>, <&cgu_clk CLK_SYS_PLL>, + <&cgu_clk CLK_TUN_PLL>, <&cgu_clk CLK_DDR_PLL>, + <&cgu_clk CLK_ARC>, <&cgu_clk CLK_HDMI_PLL>, + <&cgu_clk CLK_TUN_TUN>, <&cgu_clk CLK_HDMI>, + <&cgu_clk CLK_SYS_APB>, <&cgu_clk CLK_SYS_AXI>, + <&cgu_clk CLK_SYS_ETH>, <&cgu_clk CLK_SYS_USB>, + <&cgu_clk CLK_SYS_SDIO>, <&cgu_clk CLK_SYS_HDMI>, + <&cgu_clk CLK_SYS_GFX_CORE>, <&cgu_clk CLK_SYS_GFX_DMA>, + <&cgu_clk CLK_SYS_GFX_CFG>, <&cgu_clk CLK_SYS_DMAC_CORE>, + <&cgu_clk CLK_SYS_DMAC_CFG>, <&cgu_clk CLK_SYS_SDIO_REF>, + <&cgu_clk CLK_SYS_SPI_REF>, <&cgu_clk CLK_SYS_I2C_REF>, + <&cgu_clk CLK_SYS_UART_REF>, <&cgu_clk CLK_SYS_EBI_REF>, + <&cgu_clk CLK_TUN_ROM>, <&cgu_clk CLK_TUN_PWM>; + clock-names = "cpu-pll", "sys-pll", + "tun-pll", "ddr-clk", + "cpu-clk", "hdmi-pll", + "tun-clk", "hdmi-clk", + "apb-clk", "axi-clk", + "eth-clk", "usb-clk", + "sdio-clk", "hdmi-sys-clk", + "gfx-core-clk", "gfx-dma-clk", + "gfx-cfg-clk", "dmac-core-clk", + "dmac-cfg-clk", "sdio-ref-clk", + "spi-clk", "i2c-clk", + "uart-clk", "ebi-clk", + "rom-clk", "pwm-clk"; + }; + + cgu_clk: cgu-clk@f0000000 { + compatible = "snps,hsdk-cgu-clock"; + reg = <0xf0000000 0x10>, <0xf00014B8 0x4>; + #clock-cells = <1>; + }; + + uart0: serial0@f0005000 { + compatible = "snps,dw-apb-uart"; + reg = <0xf0005000 0x1000>; + reg-shift = <2>; + reg-io-width = <4>; + }; + + ethernet@f0008000 { + #interrupt-cells = <1>; + compatible = "altr,socfpga-stmmac"; + reg = <0xf0008000 0x2000>; + phy-mode = "gmii"; + }; + + ehci@0xf0040000 { + compatible = "generic-ehci"; + reg = <0xf0040000 0x100>; + }; + + ohci@0xf0060000 { + compatible = "generic-ohci"; + reg = <0xf0060000 0x100>; + }; + + spi0: spi@f0020000 { + compatible = "snps,dw-apb-ssi"; + reg = <0xf0020000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + spi-max-frequency = <4000000>; + clocks = <&cgu_clk CLK_SYS_SPI_REF>; + clock-names = "spi_clk"; + cs-gpio = <&cs_gpio 0>; + spi_flash@0 { + compatible = "spi-flash"; + reg = <0>; + spi-max-frequency = <4000000>; + }; + }; + + cs_gpio: gpio@f00014b0 { + compatible = "snps,creg-gpio"; + reg = <0xf00014b0 0x4>; + gpio-controller; + #gpio-cells = <1>; + gpio-bank-name = "hsdk-spi-cs"; + gpio-count = <1>; + gpio-first-shift = <0>; + gpio-bit-per-line = <2>; + gpio-activate-val = <2>; + gpio-deactivate-val = <3>; + gpio-default-val = <1>; + }; +};
diff --git a/arch/arc/dts/iot_devkit.dts b/arch/arc/dts/iot_devkit.dts new file mode 100644 index 0000000..ebf5a95 --- /dev/null +++ b/arch/arc/dts/iot_devkit.dts
@@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Synopsys, Inc. All rights reserved. + */ +/dts-v1/; + +#include "skeleton.dtsi" + +/ { + #address-cells = <1>; + #size-cells = <1>; + + aliases { + console = &uart0; + }; + + cpu_card { + core_clk: core_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <144000000>; + u-boot,dm-pre-reloc; + }; + }; + + uart0: serial0@80014000 { + compatible = "snps,dw-apb-uart"; + clock-frequency = <16000000>; + reg = <0x80014000 0x1000>; + reg-shift = <2>; + reg-io-width = <4>; + }; + + usb: usb@f0040000 { + compatible = "snps,dwc2"; + reg = <0xf0040000 0x10000>; + phys = <&usbphy>; + phy-names = "usb2-phy"; + }; + + usbphy: phy { + compatible = "nop-phy"; + #phy-cells = <0>; + }; +};
diff --git a/arch/arc/dts/nsim.dts b/arch/arc/dts/nsim.dts new file mode 100644 index 0000000..243ecb1 --- /dev/null +++ b/arch/arc/dts/nsim.dts
@@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com) + */ +/dts-v1/; + +#include "skeleton.dtsi" + +/ { + model = "snps,nsim"; + + aliases { + console = &arcuart0; + }; + + cpu_card { + core_clk: core_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <70000000>; + u-boot,dm-pre-reloc; + }; + }; + + arcuart0: serial@0xc0fc1000 { + compatible = "snps,arc-uart"; + reg = <0xc0fc1000 0x100>; + clock-frequency = <70000000>; + }; + +};
diff --git a/arch/arc/dts/skeleton.dtsi b/arch/arc/dts/skeleton.dtsi new file mode 100644 index 0000000..279fc6c --- /dev/null +++ b/arch/arc/dts/skeleton.dtsi
@@ -0,0 +1,30 @@ +/* + * Skeleton device tree; the bare minimum needed to boot; just include and + * add a compatible value. The bootloader will typically populate the memory + * node. + */ + +/ { + #address-cells = <1>; + #size-cells = <1>; + chosen { }; + aliases { }; + + cpu_card { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + u-boot,dm-pre-reloc; + + timer@0 { + compatible = "snps,arc-timer"; + clocks = <&core_clk>; + reg = <0 1>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256M */ + }; +};
diff --git a/arch/arc/include/asm/arc-bcr.h b/arch/arc/include/asm/arc-bcr.h new file mode 100644 index 0000000..823906d --- /dev/null +++ b/arch/arc/include/asm/arc-bcr.h
@@ -0,0 +1,77 @@ +/* + * ARC Build Configuration Registers, with encoded hardware config + * + * Copyright (C) 2018 Synopsys + * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ARC_BCR_H +#define __ARC_BCR_H +#ifndef __ASSEMBLY__ + +#include <config.h> + +union bcr_di_cache { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; +#else + unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; +#endif + } fields; + unsigned int word; +}; + +union bcr_slc_cfg { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:24, way:2, lsz:2, sz:4; +#else + unsigned int sz:4, lsz:2, way:2, pad:24; +#endif + } fields; + unsigned int word; +}; + +union bcr_generic { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:24, ver:8; +#else + unsigned int ver:8, pad:24; +#endif + } fields; + unsigned int word; +}; + +union bcr_clust_cfg { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; +#else + unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; +#endif + } fields; + unsigned int word; +}; + +union bcr_mmu_4 { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1, + n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3; +#else + /* DTLB ITLB JES JE JA */ + unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2, + pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8; +#endif + } fields; + unsigned int word; +}; + +#endif /* __ASSEMBLY__ */ +#endif /* __ARC_BCR_H */
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h new file mode 100644 index 0000000..fff6591 --- /dev/null +++ b/arch/arc/include/asm/arcregs.h
@@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. All rights reserved. + */ + +#ifndef _ASM_ARC_ARCREGS_H +#define _ASM_ARC_ARCREGS_H + +#include <asm/cache.h> +#include <config.h> + +/* + * ARC architecture has additional address space - auxiliary registers. + * These registers are mostly used for configuration purposes. + * These registers are not memory mapped and special commands are used for + * access: "lr"/"sr". + */ + +/* + * Typically 8 least significant bits of Build Configuration Register (BCR) + * describe version of the HW block in question. Moreover if decoded version + * is 0 this means given HW block is absent - this is especially useful because + * we may safely read BRC regardless HW block existence while an attempt to + * access any other AUX regs associated with this HW block lead to imediate + * "instruction error" exception. + * + * I.e. before using any cofigurable HW block it's required to make sure it + * exists at all, and for that we introduce a special macro below. + */ +#define ARC_BCR_VERSION_MASK GENMASK(7, 0) +#define ARC_FEATURE_EXISTS(bcr) !!(__builtin_arc_lr(bcr) & ARC_BCR_VERSION_MASK) + +#define ARC_AUX_IDENTITY 0x04 +#define ARC_AUX_STATUS32 0x0a + +/* STATUS32 Bits Positions */ +#define STATUS_AD_BIT 19 /* Enable unaligned access */ + +/* Instruction cache related auxiliary registers */ +#define ARC_AUX_IC_IVIC 0x10 +#define ARC_AUX_IC_CTRL 0x11 +#define ARC_AUX_IC_IVIL 0x19 +#if (CONFIG_ARC_MMU_VER == 3) +#define ARC_AUX_IC_PTAG 0x1E +#endif +#define ARC_BCR_IC_BUILD 0x77 +#define AUX_AUX_CACHE_LIMIT 0x5D +#define ARC_AUX_NON_VOLATILE_LIMIT 0x5E + +/* ICCM and DCCM auxiliary registers */ +#define ARC_AUX_DCCM_BASE 0x18 /* DCCM Base Addr ARCv2 */ +#define ARC_AUX_ICCM_BASE 0x208 /* ICCM Base Addr ARCv2 */ + +/* Timer related auxiliary registers */ +#define ARC_AUX_TIMER0_CNT 0x21 /* Timer 0 count */ +#define ARC_AUX_TIMER0_CTRL 0x22 /* Timer 0 control */ +#define ARC_AUX_TIMER0_LIMIT 0x23 /* Timer 0 limit */ + +#define ARC_AUX_TIMER1_CNT 0x100 /* Timer 1 count */ +#define ARC_AUX_TIMER1_CTRL 0x101 /* Timer 1 control */ +#define ARC_AUX_TIMER1_LIMIT 0x102 /* Timer 1 limit */ + +#define ARC_AUX_INTR_VEC_BASE 0x25 + +/* Data cache related auxiliary registers */ +#define ARC_AUX_DC_IVDC 0x47 +#define ARC_AUX_DC_CTRL 0x48 + +#define ARC_AUX_DC_IVDL 0x4A +#define ARC_AUX_DC_FLSH 0x4B +#define ARC_AUX_DC_FLDL 0x4C +#if (CONFIG_ARC_MMU_VER == 3) +#define ARC_AUX_DC_PTAG 0x5C +#endif +#define ARC_BCR_DC_BUILD 0x72 +#define ARC_BCR_SLC 0xce +#define ARC_AUX_SLC_CONFIG 0x901 +#define ARC_AUX_SLC_CTRL 0x903 +#define ARC_AUX_SLC_FLUSH 0x904 +#define ARC_AUX_SLC_INVALIDATE 0x905 +#define ARC_AUX_SLC_IVDL 0x910 +#define ARC_AUX_SLC_FLDL 0x912 +#define ARC_AUX_SLC_RGN_START 0x914 +#define ARC_AUX_SLC_RGN_START1 0x915 +#define ARC_AUX_SLC_RGN_END 0x916 +#define ARC_AUX_SLC_RGN_END1 0x917 +#define ARC_BCR_CLUSTER 0xcf + +/* MMU Management regs */ +#define ARC_AUX_MMU_BCR 0x6f + +/* IO coherency related auxiliary registers */ +#define ARC_AUX_IO_COH_ENABLE 0x500 +#define ARC_AUX_IO_COH_PARTIAL 0x501 +#define ARC_AUX_IO_COH_AP0_BASE 0x508 +#define ARC_AUX_IO_COH_AP0_SIZE 0x509 + +/* XY-memory related */ +#define ARC_AUX_XY_BUILD 0x79 + +/* DSP-extensions related auxiliary registers */ +#define ARC_AUX_DSP_BUILD 0x7A + +/* ARC Subsystems related auxiliary registers */ +#define ARC_AUX_SUBSYS_BUILD 0xF0 + +#ifndef __ASSEMBLY__ +/* Accessors for auxiliary registers */ +#define read_aux_reg(reg) __builtin_arc_lr(reg) + +/* gcc builtin sr needs reg param to be long immediate */ +#define write_aux_reg(reg_immed, val) \ + __builtin_arc_sr((unsigned int)val, reg_immed) + +/* ARCNUM [15:8] - field to identify each core in a multi-core system */ +#define CPU_ID_GET() ((read_aux_reg(ARC_AUX_IDENTITY) & 0xFF00) >> 8) + +static const inline int is_isa_arcv2(void) +{ + return IS_ENABLED(CONFIG_ISA_ARCV2); +} + +static const inline int is_isa_arcompact(void) +{ + return IS_ENABLED(CONFIG_ISA_ARCOMPACT); +} +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_ARC_ARCREGS_H */
diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h new file mode 100644 index 0000000..c6dd28e --- /dev/null +++ b/arch/arc/include/asm/bitops.h
@@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_BITOPS_H +#define __ASM_ARC_BITOPS_H + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +#include <asm-generic/bitops/fls.h> +#include <asm-generic/bitops/__fls.h> +#include <asm-generic/bitops/fls64.h> +#include <asm-generic/bitops/__ffs.h> + +#endif /* __ASM_ARC_BITOPS_H */
diff --git a/arch/arc/include/asm/byteorder.h b/arch/arc/include/asm/byteorder.h new file mode 100644 index 0000000..8c171bb --- /dev/null +++ b/arch/arc/include/asm/byteorder.h
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_BYTEORDER_H +#define __ASM_ARC_BYTEORDER_H + +#include <asm/types.h> + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) + #define __BYTEORDER_HAS_U64__ + #define __SWAB_64_THRU_32__ +#endif + +#ifdef __LITTLE_ENDIAN__ + #include <linux/byteorder/little_endian.h> +#else + #include <linux/byteorder/big_endian.h> +#endif /* CONFIG_SYS_BIG_ENDIAN */ + +#endif /* ASM_ARC_BYTEORDER_H */
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h new file mode 100644 index 0000000..1604cd0 --- /dev/null +++ b/arch/arc/include/asm/cache.h
@@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_CACHE_H +#define __ASM_ARC_CACHE_H + +#include <config.h> + +/* + * As of today we may handle any L1 cache line length right in software. + * For that essentially cache line length is a variable not constant. + * And to satisfy users of ARCH_DMA_MINALIGN we just use largest line length + * that may exist in either L1 or L2 (AKA SLC) caches on ARC. + */ +#define ARCH_DMA_MINALIGN 128 + +#if defined(ARC_MMU_ABSENT) +#define CONFIG_ARC_MMU_VER 0 +#elif defined(CONFIG_ARC_MMU_V2) +#define CONFIG_ARC_MMU_VER 2 +#elif defined(CONFIG_ARC_MMU_V3) +#define CONFIG_ARC_MMU_VER 3 +#elif defined(CONFIG_ARC_MMU_V4) +#define CONFIG_ARC_MMU_VER 4 +#endif + +#ifndef __ASSEMBLY__ + +void cache_init(void); +void flush_n_invalidate_dcache_all(void); +void sync_n_cleanup_cache_all(void); + +static const inline int is_ioc_enabled(void) +{ + return IS_ENABLED(CONFIG_ARC_DBG_IOC_ENABLE); +} + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_ARC_CACHE_H */
diff --git a/arch/arc/include/asm/config.h b/arch/arc/include/asm/config.h new file mode 100644 index 0000000..d88c361 --- /dev/null +++ b/arch/arc/include/asm/config.h
@@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_CONFIG_H_ +#define __ASM_ARC_CONFIG_H_ + +#define CONFIG_SYS_BOOT_RAMDISK_HIGH + +#define CONFIG_LMB + +#endif /*__ASM_ARC_CONFIG_H_ */
diff --git a/arch/arc/include/asm/global_data.h b/arch/arc/include/asm/global_data.h new file mode 100644 index 0000000..8f9c83d --- /dev/null +++ b/arch/arc/include/asm/global_data.h
@@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_GLOBAL_DATA_H +#define __ASM_ARC_GLOBAL_DATA_H + +#include <config.h> + +#ifndef __ASSEMBLY__ +/* Architecture-specific global data */ +struct arch_global_data { + int l1_line_sz; +#if defined(CONFIG_ISA_ARCV2) + int slc_line_sz; +#endif +}; +#endif /* __ASSEMBLY__ */ + +#include <asm-generic/global_data.h> + +#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r25") + +#endif /* __ASM_ARC_GLOBAL_DATA_H */
diff --git a/arch/arc/include/asm/gpio.h b/arch/arc/include/asm/gpio.h new file mode 100644 index 0000000..306ab4c --- /dev/null +++ b/arch/arc/include/asm/gpio.h
@@ -0,0 +1 @@ +#include <asm-generic/gpio.h>
diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h new file mode 100644 index 0000000..fa844b5 --- /dev/null +++ b/arch/arc/include/asm/io.h
@@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_IO_H +#define __ASM_ARC_IO_H + +#include <linux/types.h> +#include <asm/byteorder.h> + +#ifdef __ARCHS__ + +/* + * ARCv2 based HS38 cores are in-order issue, but still weakly ordered + * due to micro-arch buffering/queuing of load/store, cache hit vs. miss ... + * + * Explicit barrier provided by DMB instruction + * - Operand supports fine grained load/store/load+store semantics + * - Ensures that selected memory operation issued before it will complete + * before any subsequent memory operation of same type + * - DMB guarantees SMP as well as local barrier semantics + * (asm-generic/barrier.h ensures sane smp_*mb if not defined here, i.e. + * UP: barrier(), SMP: smp_*mb == *mb) + * - DSYNC provides DMB+completion_of_cache_bpu_maintenance_ops hence not needed + * in the general case. Plus it only provides full barrier. + */ + +#define mb() asm volatile("dmb 3\n" : : : "memory") +#define rmb() asm volatile("dmb 1\n" : : : "memory") +#define wmb() asm volatile("dmb 2\n" : : : "memory") + +#else + +/* + * ARCompact based cores (ARC700) only have SYNC instruction which is super + * heavy weight as it flushes the pipeline as well. + * There are no real SMP implementations of such cores. + */ + +#define mb() asm volatile("sync\n" : : : "memory") +#endif + +#ifdef __ARCHS__ +#define __iormb() rmb() +#define __iowmb() wmb() +#else +#define __iormb() asm volatile("" : : : "memory") +#define __iowmb() asm volatile("" : : : "memory") +#endif + +static inline void sync(void) +{ + /* Not yet implemented */ +} + +static inline u8 __raw_readb(const volatile void __iomem *addr) +{ + u8 b; + + __asm__ __volatile__("ldb%U1 %0, %1\n" + : "=r" (b) + : "m" (*(volatile u8 __force *)addr) + : "memory"); + return b; +} + +static inline u16 __raw_readw(const volatile void __iomem *addr) +{ + u16 s; + + __asm__ __volatile__("ldw%U1 %0, %1\n" + : "=r" (s) + : "m" (*(volatile u16 __force *)addr) + : "memory"); + return s; +} + +static inline u32 __raw_readl(const volatile void __iomem *addr) +{ + u32 w; + + __asm__ __volatile__("ld%U1 %0, %1\n" + : "=r" (w) + : "m" (*(volatile u32 __force *)addr) + : "memory"); + return w; +} + +static inline void __raw_writeb(u8 b, volatile void __iomem *addr) +{ + __asm__ __volatile__("stb%U1 %0, %1\n" + : + : "r" (b), "m" (*(volatile u8 __force *)addr) + : "memory"); +} + +static inline void __raw_writew(u16 s, volatile void __iomem *addr) +{ + __asm__ __volatile__("stw%U1 %0, %1\n" + : + : "r" (s), "m" (*(volatile u16 __force *)addr) + : "memory"); +} + +static inline void __raw_writel(u32 w, volatile void __iomem *addr) +{ + __asm__ __volatile__("st%U1 %0, %1\n" + : + : "r" (w), "m" (*(volatile u32 __force *)addr) + : "memory"); +} + +static inline int __raw_readsb(unsigned int addr, void *data, int bytelen) +{ + __asm__ __volatile__ ("1:ld.di r8, [r0]\n" + "sub.f r2, r2, 1\n" + "bnz.d 1b\n" + "stb.ab r8, [r1, 1]\n" + : + : "r" (addr), "r" (data), "r" (bytelen) + : "r8"); + return bytelen; +} + +static inline int __raw_readsw(unsigned int addr, void *data, int wordlen) +{ + __asm__ __volatile__ ("1:ld.di r8, [r0]\n" + "sub.f r2, r2, 1\n" + "bnz.d 1b\n" + "stw.ab r8, [r1, 2]\n" + : + : "r" (addr), "r" (data), "r" (wordlen) + : "r8"); + return wordlen; +} + +static inline int __raw_readsl(unsigned int addr, void *data, int longlen) +{ + __asm__ __volatile__ ("1:ld.di r8, [r0]\n" + "sub.f r2, r2, 1\n" + "bnz.d 1b\n" + "st.ab r8, [r1, 4]\n" + : + : "r" (addr), "r" (data), "r" (longlen) + : "r8"); + return longlen; +} + +static inline int __raw_writesb(unsigned int addr, void *data, int bytelen) +{ + __asm__ __volatile__ ("1:ldb.ab r8, [r1, 1]\n" + "sub.f r2, r2, 1\n" + "bnz.d 1b\n" + "st.di r8, [r0, 0]\n" + : + : "r" (addr), "r" (data), "r" (bytelen) + : "r8"); + return bytelen; +} + +static inline int __raw_writesw(unsigned int addr, void *data, int wordlen) +{ + __asm__ __volatile__ ("1:ldw.ab r8, [r1, 2]\n" + "sub.f r2, r2, 1\n" + "bnz.d 1b\n" + "st.ab.di r8, [r0, 0]\n" + : + : "r" (addr), "r" (data), "r" (wordlen) + : "r8"); + return wordlen; +} + +static inline int __raw_writesl(unsigned int addr, void *data, int longlen) +{ + __asm__ __volatile__ ("1:ld.ab r8, [r1, 4]\n" + "sub.f r2, r2, 1\n" + "bnz.d 1b\n" + "st.ab.di r8, [r0, 0]\n" + : + : "r" (addr), "r" (data), "r" (longlen) + : "r8"); + return longlen; +} + +/* + * MMIO can also get buffered/optimized in micro-arch, so barriers needed + * Based on ARM model for the typical use case + * + * <ST [DMA buffer]> + * <writel MMIO "go" reg> + * or: + * <readl MMIO "status" reg> + * <LD [DMA buffer]> + * + * http://lkml.kernel.org/r/20150622133656.GG1583@arm.com + */ +#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) +#define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) +#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) + +#define writeb(v,c) ({ __iowmb(); writeb_relaxed(v,c); }) +#define writew(v,c) ({ __iowmb(); writew_relaxed(v,c); }) +#define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); }) + +/* + * Relaxed API for drivers which can handle barrier ordering themselves + * + * Also these are defined to perform little endian accesses. + * To provide the typical device register semantics of fixed endian, + * swap the byte order for Big Endian + * + * http://lkml.kernel.org/r/201603100845.30602.arnd@arndb.de + */ +#define readb_relaxed(c) __raw_readb(c) +#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \ + __raw_readw(c)); __r; }) +#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ + __raw_readl(c)); __r; }) + +#define writeb_relaxed(v,c) __raw_writeb(v,c) +#define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c) +#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c) + +#define out_arch(type, endian, a, v) __raw_write##type(cpu_to_##endian(v), a) +#define in_arch(type, endian, a) endian##_to_cpu(__raw_read##type(a)) + +#define out_le32(a, v) out_arch(l, le32, a, v) +#define out_le16(a, v) out_arch(w, le16, a, v) + +#define in_le32(a) in_arch(l, le32, a) +#define in_le16(a) in_arch(w, le16, a) + +#define out_be32(a, v) out_arch(l, be32, a, v) +#define out_be16(a, v) out_arch(w, be16, a, v) + +#define in_be32(a) in_arch(l, be32, a) +#define in_be16(a) in_arch(w, be16, a) + +#define out_8(a, v) __raw_writeb(v, a) +#define in_8(a) __raw_readb(a) + +/* + * Clear and set bits in one shot. These macros can be used to clear and + * set multiple bits in a register using a single call. These macros can + * also be used to set a multiple-bit bit pattern using a mask, by + * specifying the mask in the 'clear' parameter and the new bit pattern + * in the 'set' parameter. + */ + +#define clrbits(type, addr, clear) \ + out_##type((addr), in_##type(addr) & ~(clear)) + +#define setbits(type, addr, set) \ + out_##type((addr), in_##type(addr) | (set)) + +#define clrsetbits(type, addr, clear, set) \ + out_##type((addr), (in_##type(addr) & ~(clear)) | (set)) + +#define clrbits_be32(addr, clear) clrbits(be32, addr, clear) +#define setbits_be32(addr, set) setbits(be32, addr, set) +#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set) + +#define clrbits_le32(addr, clear) clrbits(le32, addr, clear) +#define setbits_le32(addr, set) setbits(le32, addr, set) +#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) + +#define clrbits_be16(addr, clear) clrbits(be16, addr, clear) +#define setbits_be16(addr, set) setbits(be16, addr, set) +#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set) + +#define clrbits_le16(addr, clear) clrbits(le16, addr, clear) +#define setbits_le16(addr, set) setbits(le16, addr, set) +#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set) + +#define clrbits_8(addr, clear) clrbits(8, addr, clear) +#define setbits_8(addr, set) setbits(8, addr, set) +#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) + +#include <asm-generic/io.h> + +#endif /* __ASM_ARC_IO_H */
diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h new file mode 100644 index 0000000..2d42ed4 --- /dev/null +++ b/arch/arc/include/asm/linkage.h
@@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2004, 2007-2010, 2011-2015 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_LINKAGE_H +#define __ASM_ARC_LINKAGE_H + +#define ASM_NL ` /* use '`' to mark new line in macro */ + +#endif /* __ASM_ARC_LINKAGE_H */
diff --git a/arch/arc/include/asm/posix_types.h b/arch/arc/include/asm/posix_types.h new file mode 100644 index 0000000..13838cb --- /dev/null +++ b/arch/arc/include/asm/posix_types.h
@@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_POSIX_TYPES_H +#define __ASM_ARC_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +#ifdef __GNUC__ +typedef __SIZE_TYPE__ __kernel_size_t; +#else +typedef unsigned int __kernel_size_t; +#endif +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char *__kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +#endif /* __ASM_ARC_POSIX_TYPES_H */
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h new file mode 100644 index 0000000..03e31fb --- /dev/null +++ b/arch/arc/include/asm/processor.h
@@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2015 Synopsys, Inc. All rights reserved. + */ + +#ifndef _ASM_ARC_PROCESSOR_H +#define _ASM_ARC_PROCESSOR_H + +/* This file is required by some generic code like USB etc */ + +#endif /* _ASM_ARC_PROCESSOR_H */
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h new file mode 100644 index 0000000..6965e89 --- /dev/null +++ b/arch/arc/include/asm/ptrace.h
@@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_PTRACE_H +#define __ASM_ARC_PTRACE_H + +struct pt_regs { + long bta; + long lp_start; + long lp_end; + long lp_count; + long status32; + long ret; + long blink; + long fp; + long r26; /* gp */ + long r25; + long r24; + long r23; + long r22; + long r21; + long r20; + long r19; + long r18; + long r17; + long r16; + long r15; + long r14; + long r13; + long r12; + long r11; + long r10; + long r9; + long r8; + long r7; + long r6; + long r5; + long r4; + long r3; + long r2; + long r1; + long r0; + long sp; + long ecr; +}; + +#endif /* __ASM_ARC_PTRACE_H */
diff --git a/arch/arc/include/asm/sections.h b/arch/arc/include/asm/sections.h new file mode 100644 index 0000000..1c9c9db --- /dev/null +++ b/arch/arc/include/asm/sections.h
@@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_SECTIONS_H +#define __ASM_ARC_SECTIONS_H + +#include <asm-generic/sections.h> + +extern ulong __ivt_start; +extern ulong __ivt_end; + +#endif /* __ASM_ARC_SECTIONS_H */
diff --git a/arch/arc/include/asm/string.h b/arch/arc/include/asm/string.h new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/arch/arc/include/asm/string.h
@@ -0,0 +1 @@ +
diff --git a/arch/arc/include/asm/types.h b/arch/arc/include/asm/types.h new file mode 100644 index 0000000..f31dcdf --- /dev/null +++ b/arch/arc/include/asm/types.h
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_TYPES_H +#define __ASM_ARC_TYPES_H + +#include <asm-generic/int-ll64.h> + +typedef unsigned short umode_t; + +#define BITS_PER_LONG 32 + +/* Dma addresses are 32-bits wide. */ + +typedef u32 dma_addr_t; + +typedef unsigned long phys_addr_t; +typedef unsigned long phys_size_t; + +#endif /* __ASM_ARC_TYPES_H */
diff --git a/arch/arc/include/asm/u-boot-arc.h b/arch/arc/include/asm/u-boot-arc.h new file mode 100644 index 0000000..dd2c094 --- /dev/null +++ b/arch/arc/include/asm/u-boot-arc.h
@@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2014 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_U_BOOT_ARC_H__ +#define __ASM_ARC_U_BOOT_ARC_H__ + +int arch_early_init_r(void); + +void board_init_f_r_trampoline(ulong) __attribute__ ((noreturn)); +void board_init_f_r(void) __attribute__ ((noreturn)); + +#endif /* __ASM_ARC_U_BOOT_ARC_H__ */
diff --git a/arch/arc/include/asm/u-boot.h b/arch/arc/include/asm/u-boot.h new file mode 100644 index 0000000..36c2207 --- /dev/null +++ b/arch/arc/include/asm/u-boot.h
@@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#ifndef __ASM_ARC_U_BOOT_H__ +#define __ASM_ARC_U_BOOT_H__ + +#include <asm-generic/u-boot.h> +#include <asm/u-boot-arc.h> + +/* For image.h:image_check_target_arch() */ +#define IH_ARCH_DEFAULT IH_ARCH_ARC + +#endif /* __ASM_ARC_U_BOOT_H__ */
diff --git a/arch/arc/include/asm/unaligned.h b/arch/arc/include/asm/unaligned.h new file mode 100644 index 0000000..6cecbbb --- /dev/null +++ b/arch/arc/include/asm/unaligned.h
@@ -0,0 +1 @@ +#include <asm-generic/unaligned.h>
diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile new file mode 100644 index 0000000..0eb44bc --- /dev/null +++ b/arch/arc/lib/Makefile
@@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + +extra-y = start.o +head-y := start.o +obj-y += cache.o +obj-y += cpu.o +obj-y += interrupts.o +obj-y += relocate.o +obj-y += reset.o +obj-y += ints_low.o +obj-y += init_helpers.o + +obj-$(CONFIG_CMD_BOOTM) += bootm.o + +lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _millicodethunk.o libgcc2.o
diff --git a/arch/arc/lib/_millicodethunk.S b/arch/arc/lib/_millicodethunk.S new file mode 100644 index 0000000..4ad16ae --- /dev/null +++ b/arch/arc/lib/_millicodethunk.S
@@ -0,0 +1,225 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 1995, 1997, 2007-2013 Free Software Foundation, Inc. + */ + + /* ANSI concatenation macros. */ + + #define CONCAT1(a, b) CONCAT2(a, b) + #define CONCAT2(a, b) a ## b + + /* Use the right prefix for global labels. */ + + #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) + +#ifndef WORKING_ASSEMBLER +#define abs_l abs +#define asl_l asl +#define mov_l mov +#endif + +#define FUNC(X) .type SYM(X),@function +#define HIDDEN_FUNC(X) FUNC(X)` .hidden X +#define ENDFUNC0(X) .Lfe_##X: .size X,.Lfe_##X-X +#define ENDFUNC(X) ENDFUNC0(X) + + .section .text + .align 4 + .global SYM(__st_r13_to_r15) + .global SYM(__st_r13_to_r16) + .global SYM(__st_r13_to_r17) + .global SYM(__st_r13_to_r18) + .global SYM(__st_r13_to_r19) + .global SYM(__st_r13_to_r20) + .global SYM(__st_r13_to_r21) + .global SYM(__st_r13_to_r22) + .global SYM(__st_r13_to_r23) + .global SYM(__st_r13_to_r24) + .global SYM(__st_r13_to_r25) + HIDDEN_FUNC(__st_r13_to_r15) + HIDDEN_FUNC(__st_r13_to_r16) + HIDDEN_FUNC(__st_r13_to_r17) + HIDDEN_FUNC(__st_r13_to_r18) + HIDDEN_FUNC(__st_r13_to_r19) + HIDDEN_FUNC(__st_r13_to_r20) + HIDDEN_FUNC(__st_r13_to_r21) + HIDDEN_FUNC(__st_r13_to_r22) + HIDDEN_FUNC(__st_r13_to_r23) + HIDDEN_FUNC(__st_r13_to_r24) + HIDDEN_FUNC(__st_r13_to_r25) + .align 4 +SYM(__st_r13_to_r25): + st r25, [sp,48] +SYM(__st_r13_to_r24): + st r24, [sp,44] +SYM(__st_r13_to_r23): + st r23, [sp,40] +SYM(__st_r13_to_r22): + st r22, [sp,36] +SYM(__st_r13_to_r21): + st r21, [sp,32] +SYM(__st_r13_to_r20): + st r20, [sp,28] +SYM(__st_r13_to_r19): + st r19, [sp,24] +SYM(__st_r13_to_r18): + st r18, [sp,20] +SYM(__st_r13_to_r17): + st r17, [sp,16] +SYM(__st_r13_to_r16): + st r16, [sp,12] +SYM(__st_r13_to_r15): +#ifdef __ARC700__ + st r15, [sp,8] ; minimum function size to avoid stall: 6 bytes. +#else + st_s r15, [sp,8] +#endif + st_s r14, [sp,4] + j_s.d [%blink] + st_s r13, [sp,0] + ENDFUNC(__st_r13_to_r15) + ENDFUNC(__st_r13_to_r16) + ENDFUNC(__st_r13_to_r17) + ENDFUNC(__st_r13_to_r18) + ENDFUNC(__st_r13_to_r19) + ENDFUNC(__st_r13_to_r20) + ENDFUNC(__st_r13_to_r21) + ENDFUNC(__st_r13_to_r22) + ENDFUNC(__st_r13_to_r23) + ENDFUNC(__st_r13_to_r24) + ENDFUNC(__st_r13_to_r25) + + .section .text + .align 4 +; ================================== +; the loads + + .global SYM(__ld_r13_to_r15) + .global SYM(__ld_r13_to_r16) + .global SYM(__ld_r13_to_r17) + .global SYM(__ld_r13_to_r18) + .global SYM(__ld_r13_to_r19) + .global SYM(__ld_r13_to_r20) + .global SYM(__ld_r13_to_r21) + .global SYM(__ld_r13_to_r22) + .global SYM(__ld_r13_to_r23) + .global SYM(__ld_r13_to_r24) + .global SYM(__ld_r13_to_r25) + HIDDEN_FUNC(__ld_r13_to_r15) + HIDDEN_FUNC(__ld_r13_to_r16) + HIDDEN_FUNC(__ld_r13_to_r17) + HIDDEN_FUNC(__ld_r13_to_r18) + HIDDEN_FUNC(__ld_r13_to_r19) + HIDDEN_FUNC(__ld_r13_to_r20) + HIDDEN_FUNC(__ld_r13_to_r21) + HIDDEN_FUNC(__ld_r13_to_r22) + HIDDEN_FUNC(__ld_r13_to_r23) + HIDDEN_FUNC(__ld_r13_to_r24) + HIDDEN_FUNC(__ld_r13_to_r25) +SYM(__ld_r13_to_r25): + ld r25, [sp,48] +SYM(__ld_r13_to_r24): + ld r24, [sp,44] +SYM(__ld_r13_to_r23): + ld r23, [sp,40] +SYM(__ld_r13_to_r22): + ld r22, [sp,36] +SYM(__ld_r13_to_r21): + ld r21, [sp,32] +SYM(__ld_r13_to_r20): + ld r20, [sp,28] +SYM(__ld_r13_to_r19): + ld r19, [sp,24] +SYM(__ld_r13_to_r18): + ld r18, [sp,20] +SYM(__ld_r13_to_r17): + ld r17, [sp,16] +SYM(__ld_r13_to_r16): + ld r16, [sp,12] +SYM(__ld_r13_to_r15): +#ifdef __ARC700__ + ld r15, [sp,8] ; minimum function size to avoid stall: 6 bytes. +#else + ld_s r15, [sp,8] +#endif + ld_s r14, [sp,4] + j_s.d [%blink] + ld_s r13, [sp,0] + ENDFUNC(__ld_r13_to_r15) + ENDFUNC(__ld_r13_to_r16) + ENDFUNC(__ld_r13_to_r17) + ENDFUNC(__ld_r13_to_r18) + ENDFUNC(__ld_r13_to_r19) + ENDFUNC(__ld_r13_to_r20) + ENDFUNC(__ld_r13_to_r21) + ENDFUNC(__ld_r13_to_r22) + ENDFUNC(__ld_r13_to_r23) + ENDFUNC(__ld_r13_to_r24) + ENDFUNC(__ld_r13_to_r25) + + .global SYM(__ld_r13_to_r14_ret) + .global SYM(__ld_r13_to_r15_ret) + .global SYM(__ld_r13_to_r16_ret) + .global SYM(__ld_r13_to_r17_ret) + .global SYM(__ld_r13_to_r18_ret) + .global SYM(__ld_r13_to_r19_ret) + .global SYM(__ld_r13_to_r20_ret) + .global SYM(__ld_r13_to_r21_ret) + .global SYM(__ld_r13_to_r22_ret) + .global SYM(__ld_r13_to_r23_ret) + .global SYM(__ld_r13_to_r24_ret) + .global SYM(__ld_r13_to_r25_ret) + HIDDEN_FUNC(__ld_r13_to_r14_ret) + HIDDEN_FUNC(__ld_r13_to_r15_ret) + HIDDEN_FUNC(__ld_r13_to_r16_ret) + HIDDEN_FUNC(__ld_r13_to_r17_ret) + HIDDEN_FUNC(__ld_r13_to_r18_ret) + HIDDEN_FUNC(__ld_r13_to_r19_ret) + HIDDEN_FUNC(__ld_r13_to_r20_ret) + HIDDEN_FUNC(__ld_r13_to_r21_ret) + HIDDEN_FUNC(__ld_r13_to_r22_ret) + HIDDEN_FUNC(__ld_r13_to_r23_ret) + HIDDEN_FUNC(__ld_r13_to_r24_ret) + HIDDEN_FUNC(__ld_r13_to_r25_ret) + .section .text + .align 4 +SYM(__ld_r13_to_r25_ret): + ld r25, [sp,48] +SYM(__ld_r13_to_r24_ret): + ld r24, [sp,44] +SYM(__ld_r13_to_r23_ret): + ld r23, [sp,40] +SYM(__ld_r13_to_r22_ret): + ld r22, [sp,36] +SYM(__ld_r13_to_r21_ret): + ld r21, [sp,32] +SYM(__ld_r13_to_r20_ret): + ld r20, [sp,28] +SYM(__ld_r13_to_r19_ret): + ld r19, [sp,24] +SYM(__ld_r13_to_r18_ret): + ld r18, [sp,20] +SYM(__ld_r13_to_r17_ret): + ld r17, [sp,16] +SYM(__ld_r13_to_r16_ret): + ld r16, [sp,12] +SYM(__ld_r13_to_r15_ret): + ld r15, [sp,8] +SYM(__ld_r13_to_r14_ret): + ld blink,[sp,r12] + ld_s r14, [sp,4] + ld.ab r13, [sp,r12] + j_s.d [%blink] + add_s sp,sp,4 + ENDFUNC(__ld_r13_to_r14_ret) + ENDFUNC(__ld_r13_to_r15_ret) + ENDFUNC(__ld_r13_to_r16_ret) + ENDFUNC(__ld_r13_to_r17_ret) + ENDFUNC(__ld_r13_to_r18_ret) + ENDFUNC(__ld_r13_to_r19_ret) + ENDFUNC(__ld_r13_to_r20_ret) + ENDFUNC(__ld_r13_to_r21_ret) + ENDFUNC(__ld_r13_to_r22_ret) + ENDFUNC(__ld_r13_to_r23_ret) + ENDFUNC(__ld_r13_to_r24_ret) + ENDFUNC(__ld_r13_to_r25_ret)
diff --git a/arch/arc/lib/bootm.c b/arch/arc/lib/bootm.c new file mode 100644 index 0000000..254e028 --- /dev/null +++ b/arch/arc/lib/bootm.c
@@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#include <asm/cache.h> +#include <common.h> + +DECLARE_GLOBAL_DATA_PTR; + +static ulong get_sp(void) +{ + ulong ret; + + asm("mov %0, sp" : "=r"(ret) : ); + return ret; +} + +void arch_lmb_reserve(struct lmb *lmb) +{ + ulong sp; + + /* + * Booting a (Linux) kernel image + * + * Allocate space for command line and board info - the + * address should be as high as possible within the reach of + * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused + * memory, which means far enough below the current stack + * pointer. + */ + sp = get_sp(); + debug("## Current stack ends at 0x%08lx ", sp); + + /* adjust sp by 4K to be safe */ + sp -= 4096; + lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + gd->ram_size - sp)); +} + +static int cleanup_before_linux(void) +{ + disable_interrupts(); + sync_n_cleanup_cache_all(); + + return 0; +} + +__weak int board_prep_linux(bootm_headers_t *images) { return 0; } + +/* Subcommand: PREP */ +static int boot_prep_linux(bootm_headers_t *images) +{ + int ret; + + ret = image_setup_linux(images); + if (ret) + return ret; + + return board_prep_linux(images); +} + +/* Generic implementation for single core CPU */ +__weak void board_jump_and_run(ulong entry, int zero, int arch, uint params) +{ + void (*kernel_entry)(int zero, int arch, uint params); + + kernel_entry = (void (*)(int, int, uint))entry; + + kernel_entry(zero, arch, params); +} + +/* Subcommand: GO */ +static void boot_jump_linux(bootm_headers_t *images, int flag) +{ + ulong kernel_entry; + unsigned int r0, r2; + int fake = (flag & BOOTM_STATE_OS_FAKE_GO); + + kernel_entry = images->ep; + + debug("## Transferring control to Linux (at address %08lx)...\n", + kernel_entry); + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + printf("\nStarting kernel ...%s\n\n", fake ? + "(fake run for tracing)" : ""); + bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); + + if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) { + r0 = 2; + r2 = (unsigned int)images->ft_addr; + } else { + r0 = 1; + r2 = (unsigned int)env_get("bootargs"); + } + + cleanup_before_linux(); + + if (!fake) + board_jump_and_run(kernel_entry, r0, 0, r2); +} + +int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +{ + /* No need for those on ARC */ + if ((flag & BOOTM_STATE_OS_BD_T) || (flag & BOOTM_STATE_OS_CMDLINE)) + return -1; + + if (flag & BOOTM_STATE_OS_PREP) + return boot_prep_linux(images); + + if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) { + boot_jump_linux(images, flag); + return 0; + } + + return -1; +}
diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c new file mode 100644 index 0000000..8c1cb6e --- /dev/null +++ b/arch/arc/lib/cache.c
@@ -0,0 +1,719 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#include <config.h> +#include <common.h> +#include <linux/compiler.h> +#include <linux/kernel.h> +#include <linux/log2.h> +#include <asm/arcregs.h> +#include <asm/arc-bcr.h> +#include <asm/cache.h> + +/* + * [ NOTE 1 ]: + * Data cache (L1 D$ or SL$) entire invalidate operation or data cache disable + * operation may result in unexpected behavior and data loss even if we flush + * data cache right before invalidation. That may happens if we store any context + * on stack (like we store BLINK register on stack before function call). + * BLINK register is the register where return address is automatically saved + * when we do function call with instructions like 'bl'. + * + * There is the real example: + * We may hang in the next code as we store any BLINK register on stack in + * invalidate_dcache_all() function. + * + * void flush_dcache_all() { + * __dc_entire_op(OP_FLUSH); + * // Other code // + * } + * + * void invalidate_dcache_all() { + * __dc_entire_op(OP_INV); + * // Other code // + * } + * + * void foo(void) { + * flush_dcache_all(); + * invalidate_dcache_all(); + * } + * + * Now let's see what really happens during that code execution: + * + * foo() + * |->> call flush_dcache_all + * [return address is saved to BLINK register] + * [push BLINK] (save to stack) ![point 1] + * |->> call __dc_entire_op(OP_FLUSH) + * [return address is saved to BLINK register] + * [flush L1 D$] + * return [jump to BLINK] + * <<------ + * [other flush_dcache_all code] + * [pop BLINK] (get from stack) + * return [jump to BLINK] + * <<------ + * |->> call invalidate_dcache_all + * [return address is saved to BLINK register] + * [push BLINK] (save to stack) ![point 2] + * |->> call __dc_entire_op(OP_FLUSH) + * [return address is saved to BLINK register] + * [invalidate L1 D$] ![point 3] + * // Oops!!! + * // We lose return address from invalidate_dcache_all function: + * // we save it to stack and invalidate L1 D$ after that! + * return [jump to BLINK] + * <<------ + * [other invalidate_dcache_all code] + * [pop BLINK] (get from stack) + * // we don't have this data in L1 dcache as we invalidated it in [point 3] + * // so we get it from next memory level (for example DDR memory) + * // but in the memory we have value which we save in [point 1], which + * // is return address from flush_dcache_all function (instead of + * // address from current invalidate_dcache_all function which we + * // saved in [point 2] !) + * return [jump to BLINK] + * <<------ + * // As BLINK points to invalidate_dcache_all, we call it again and + * // loop forever. + * + * Fortunately we may fix that by using flush & invalidation of D$ with a single + * one instruction (instead of flush and invalidation instructions pair) and + * enabling force function inline with '__attribute__((always_inline))' gcc + * attribute to avoid any function call (and BLINK store) between cache flush + * and disable. + * + * + * [ NOTE 2 ]: + * As of today we only support the following cache configurations on ARC. + * Other configurations may exist in HW (for example, since version 3.0 HS + * supports SL$ (L2 system level cache) disable) but we don't support it in SW. + * Configuration 1: + * ______________________ + * | | + * | ARC CPU | + * |______________________| + * ___|___ ___|___ + * | | | | + * | L1 I$ | | L1 D$ | + * |_______| |_______| + * on/off on/off + * ___|______________|____ + * | | + * | main memory | + * |______________________| + * + * Configuration 2: + * ______________________ + * | | + * | ARC CPU | + * |______________________| + * ___|___ ___|___ + * | | | | + * | L1 I$ | | L1 D$ | + * |_______| |_______| + * on/off on/off + * ___|______________|____ + * | | + * | L2 (SL$) | + * |______________________| + * always must be on + * ___|______________|____ + * | | + * | main memory | + * |______________________| + * + * Configuration 3: + * ______________________ + * | | + * | ARC CPU | + * |______________________| + * ___|___ ___|___ + * | | | | + * | L1 I$ | | L1 D$ | + * |_______| |_______| + * on/off must be on + * ___|______________|____ _______ + * | | | | + * | L2 (SL$) |-----| IOC | + * |______________________| |_______| + * always must be on on/off + * ___|______________|____ + * | | + * | main memory | + * |______________________| + */ + +DECLARE_GLOBAL_DATA_PTR; + +/* Bit values in IC_CTRL */ +#define IC_CTRL_CACHE_DISABLE BIT(0) + +/* Bit values in DC_CTRL */ +#define DC_CTRL_CACHE_DISABLE BIT(0) +#define DC_CTRL_INV_MODE_FLUSH BIT(6) +#define DC_CTRL_FLUSH_STATUS BIT(8) + +#define OP_INV BIT(0) +#define OP_FLUSH BIT(1) +#define OP_FLUSH_N_INV (OP_FLUSH | OP_INV) + +/* Bit val in SLC_CONTROL */ +#define SLC_CTRL_DIS 0x001 +#define SLC_CTRL_IM 0x040 +#define SLC_CTRL_BUSY 0x100 +#define SLC_CTRL_RGN_OP_INV 0x200 + +#define CACHE_LINE_MASK (~(gd->arch.l1_line_sz - 1)) + +/* + * We don't want to use '__always_inline' macro here as it can be redefined + * to simple 'inline' in some cases which breaks stuff. See [ NOTE 1 ] for more + * details about the reasons we need to use always_inline functions. + */ +#define inlined_cachefunc inline __attribute__((always_inline)) + +static inlined_cachefunc void __ic_entire_invalidate(void); +static inlined_cachefunc void __dc_entire_op(const int cacheop); + +static inline bool pae_exists(void) +{ + /* TODO: should we compare mmu version from BCR and from CONFIG? */ +#if (CONFIG_ARC_MMU_VER >= 4) + union bcr_mmu_4 mmu4; + + mmu4.word = read_aux_reg(ARC_AUX_MMU_BCR); + + if (mmu4.fields.pae) + return true; +#endif /* (CONFIG_ARC_MMU_VER >= 4) */ + + return false; +} + +static inlined_cachefunc bool icache_exists(void) +{ + union bcr_di_cache ibcr; + + ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); + return !!ibcr.fields.ver; +} + +static inlined_cachefunc bool icache_enabled(void) +{ + if (!icache_exists()) + return false; + + return !(read_aux_reg(ARC_AUX_IC_CTRL) & IC_CTRL_CACHE_DISABLE); +} + +static inlined_cachefunc bool dcache_exists(void) +{ + union bcr_di_cache dbcr; + + dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); + return !!dbcr.fields.ver; +} + +static inlined_cachefunc bool dcache_enabled(void) +{ + if (!dcache_exists()) + return false; + + return !(read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_CACHE_DISABLE); +} + +static inlined_cachefunc bool slc_exists(void) +{ + if (is_isa_arcv2()) { + union bcr_generic sbcr; + + sbcr.word = read_aux_reg(ARC_BCR_SLC); + return !!sbcr.fields.ver; + } + + return false; +} + +static inlined_cachefunc bool slc_data_bypass(void) +{ + /* + * If L1 data cache is disabled SL$ is bypassed and all load/store + * requests are sent directly to main memory. + */ + return !dcache_enabled(); +} + +static inline bool ioc_exists(void) +{ + if (is_isa_arcv2()) { + union bcr_clust_cfg cbcr; + + cbcr.word = read_aux_reg(ARC_BCR_CLUSTER); + return cbcr.fields.c; + } + + return false; +} + +static inline bool ioc_enabled(void) +{ + /* + * We check only CONFIG option instead of IOC HW state check as IOC + * must be disabled by default. + */ + if (is_ioc_enabled()) + return ioc_exists(); + + return false; +} + +static inlined_cachefunc void __slc_entire_op(const int op) +{ + unsigned int ctrl; + + if (!slc_exists()) + return; + + ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); + + if (!(op & OP_FLUSH)) /* i.e. OP_INV */ + ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */ + else + ctrl |= SLC_CTRL_IM; + + write_aux_reg(ARC_AUX_SLC_CTRL, ctrl); + + if (op & OP_INV) /* Inv or flush-n-inv use same cmd reg */ + write_aux_reg(ARC_AUX_SLC_INVALIDATE, 0x1); + else + write_aux_reg(ARC_AUX_SLC_FLUSH, 0x1); + + /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ + read_aux_reg(ARC_AUX_SLC_CTRL); + + /* Important to wait for flush to complete */ + while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY); +} + +static void slc_upper_region_init(void) +{ + /* + * ARC_AUX_SLC_RGN_START1 and ARC_AUX_SLC_RGN_END1 register exist + * only if PAE exists in current HW. So we had to check pae_exist + * before using them. + */ + if (!pae_exists()) + return; + + /* + * ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1 are always == 0 + * as we don't use PAE40. + */ + write_aux_reg(ARC_AUX_SLC_RGN_END1, 0); + write_aux_reg(ARC_AUX_SLC_RGN_START1, 0); +} + +static void __slc_rgn_op(unsigned long paddr, unsigned long sz, const int op) +{ +#ifdef CONFIG_ISA_ARCV2 + + unsigned int ctrl; + unsigned long end; + + if (!slc_exists()) + return; + + /* + * The Region Flush operation is specified by CTRL.RGN_OP[11..9] + * - b'000 (default) is Flush, + * - b'001 is Invalidate if CTRL.IM == 0 + * - b'001 is Flush-n-Invalidate if CTRL.IM == 1 + */ + ctrl = read_aux_reg(ARC_AUX_SLC_CTRL); + + /* Don't rely on default value of IM bit */ + if (!(op & OP_FLUSH)) /* i.e. OP_INV */ + ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */ + else + ctrl |= SLC_CTRL_IM; + + if (op & OP_INV) + ctrl |= SLC_CTRL_RGN_OP_INV; /* Inv or flush-n-inv */ + else + ctrl &= ~SLC_CTRL_RGN_OP_INV; + + write_aux_reg(ARC_AUX_SLC_CTRL, ctrl); + + /* + * Lower bits are ignored, no need to clip + * END needs to be setup before START (latter triggers the operation) + * END can't be same as START, so add (l2_line_sz - 1) to sz + */ + end = paddr + sz + gd->arch.slc_line_sz - 1; + + /* + * Upper addresses (ARC_AUX_SLC_RGN_END1 and ARC_AUX_SLC_RGN_START1) + * are always == 0 as we don't use PAE40, so we only setup lower ones + * (ARC_AUX_SLC_RGN_END and ARC_AUX_SLC_RGN_START) + */ + write_aux_reg(ARC_AUX_SLC_RGN_END, end); + write_aux_reg(ARC_AUX_SLC_RGN_START, paddr); + + /* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */ + read_aux_reg(ARC_AUX_SLC_CTRL); + + while (read_aux_reg(ARC_AUX_SLC_CTRL) & SLC_CTRL_BUSY); + +#endif /* CONFIG_ISA_ARCV2 */ +} + +static void arc_ioc_setup(void) +{ + /* IOC Aperture start is equal to DDR start */ + unsigned int ap_base = CONFIG_SYS_SDRAM_BASE; + /* IOC Aperture size is equal to DDR size */ + long ap_size = CONFIG_SYS_SDRAM_SIZE; + + /* Unsupported configuration. See [ NOTE 2 ] for more details. */ + if (!slc_exists()) + panic("Try to enable IOC but SLC is not present"); + + /* Unsupported configuration. See [ NOTE 2 ] for more details. */ + if (!dcache_enabled()) + panic("Try to enable IOC but L1 D$ is disabled"); + + if (!is_power_of_2(ap_size) || ap_size < 4096) + panic("IOC Aperture size must be power of 2 and bigger 4Kib"); + + /* IOC Aperture start must be aligned to the size of the aperture */ + if (ap_base % ap_size != 0) + panic("IOC Aperture start must be aligned to the size of the aperture"); + + flush_n_invalidate_dcache_all(); + + /* + * IOC Aperture size decoded as 2 ^ (SIZE + 2) KB, + * so setting 0x11 implies 512M, 0x12 implies 1G... + */ + write_aux_reg(ARC_AUX_IO_COH_AP0_SIZE, + order_base_2(ap_size / 1024) - 2); + + write_aux_reg(ARC_AUX_IO_COH_AP0_BASE, ap_base >> 12); + write_aux_reg(ARC_AUX_IO_COH_PARTIAL, 1); + write_aux_reg(ARC_AUX_IO_COH_ENABLE, 1); +} + +static void read_decode_cache_bcr_arcv2(void) +{ +#ifdef CONFIG_ISA_ARCV2 + + union bcr_slc_cfg slc_cfg; + + if (slc_exists()) { + slc_cfg.word = read_aux_reg(ARC_AUX_SLC_CONFIG); + gd->arch.slc_line_sz = (slc_cfg.fields.lsz == 0) ? 128 : 64; + + /* + * We don't support configuration where L1 I$ or L1 D$ is + * absent but SL$ exists. See [ NOTE 2 ] for more details. + */ + if (!icache_exists() || !dcache_exists()) + panic("Unsupported cache configuration: SLC exists but one of L1 caches is absent"); + } + +#endif /* CONFIG_ISA_ARCV2 */ +} + +void read_decode_cache_bcr(void) +{ + int dc_line_sz = 0, ic_line_sz = 0; + union bcr_di_cache ibcr, dbcr; + + /* + * We don't care much about I$ line length really as there're + * no per-line ops on I$ instead we only do full invalidation of it + * on occasion of relocation and right before jumping to the OS. + * Still we check insane config with zero-encoded line length in + * presense of version field in I$ BCR. Just in case. + */ + ibcr.word = read_aux_reg(ARC_BCR_IC_BUILD); + if (ibcr.fields.ver) { + ic_line_sz = 8 << ibcr.fields.line_len; + if (!ic_line_sz) + panic("Instruction exists but line length is 0\n"); + } + + dbcr.word = read_aux_reg(ARC_BCR_DC_BUILD); + if (dbcr.fields.ver) { + gd->arch.l1_line_sz = dc_line_sz = 16 << dbcr.fields.line_len; + if (!dc_line_sz) + panic("Data cache exists but line length is 0\n"); + } +} + +void cache_init(void) +{ + read_decode_cache_bcr(); + + if (is_isa_arcv2()) + read_decode_cache_bcr_arcv2(); + + if (is_isa_arcv2() && ioc_enabled()) + arc_ioc_setup(); + + if (is_isa_arcv2() && slc_exists()) + slc_upper_region_init(); +} + +int icache_status(void) +{ + return icache_enabled(); +} + +void icache_enable(void) +{ + if (icache_exists()) + write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) & + ~IC_CTRL_CACHE_DISABLE); +} + +void icache_disable(void) +{ + if (!icache_exists()) + return; + + __ic_entire_invalidate(); + + write_aux_reg(ARC_AUX_IC_CTRL, read_aux_reg(ARC_AUX_IC_CTRL) | + IC_CTRL_CACHE_DISABLE); +} + +/* IC supports only invalidation */ +static inlined_cachefunc void __ic_entire_invalidate(void) +{ + if (!icache_enabled()) + return; + + /* Any write to IC_IVIC register triggers invalidation of entire I$ */ + write_aux_reg(ARC_AUX_IC_IVIC, 1); + /* + * As per ARC HS databook (see chapter 5.3.3.2) + * it is required to add 3 NOPs after each write to IC_IVIC. + */ + __builtin_arc_nop(); + __builtin_arc_nop(); + __builtin_arc_nop(); + read_aux_reg(ARC_AUX_IC_CTRL); /* blocks */ +} + +void invalidate_icache_all(void) +{ + __ic_entire_invalidate(); + + /* + * If SL$ is bypassed for data it is used only for instructions, + * so we need to invalidate it too. + * TODO: HS 3.0 supports SLC disable so we need to check slc + * enable/disable status here. + */ + if (is_isa_arcv2() && slc_data_bypass()) + __slc_entire_op(OP_INV); +} + +int dcache_status(void) +{ + return dcache_enabled(); +} + +void dcache_enable(void) +{ + if (!dcache_exists()) + return; + + write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) & + ~(DC_CTRL_INV_MODE_FLUSH | DC_CTRL_CACHE_DISABLE)); +} + +void dcache_disable(void) +{ + if (!dcache_exists()) + return; + + __dc_entire_op(OP_FLUSH_N_INV); + + /* + * As SLC will be bypassed for data after L1 D$ disable we need to + * flush it first before L1 D$ disable. Also we invalidate SLC to + * avoid any inconsistent data problems after enabling L1 D$ again with + * dcache_enable function. + */ + if (is_isa_arcv2()) + __slc_entire_op(OP_FLUSH_N_INV); + + write_aux_reg(ARC_AUX_DC_CTRL, read_aux_reg(ARC_AUX_DC_CTRL) | + DC_CTRL_CACHE_DISABLE); +} + +/* Common Helper for Line Operations on D-cache */ +static inline void __dcache_line_loop(unsigned long paddr, unsigned long sz, + const int cacheop) +{ + unsigned int aux_cmd; + int num_lines; + + /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ + aux_cmd = cacheop & OP_INV ? ARC_AUX_DC_IVDL : ARC_AUX_DC_FLDL; + + sz += paddr & ~CACHE_LINE_MASK; + paddr &= CACHE_LINE_MASK; + + num_lines = DIV_ROUND_UP(sz, gd->arch.l1_line_sz); + + while (num_lines-- > 0) { +#if (CONFIG_ARC_MMU_VER == 3) + write_aux_reg(ARC_AUX_DC_PTAG, paddr); +#endif + write_aux_reg(aux_cmd, paddr); + paddr += gd->arch.l1_line_sz; + } +} + +static inlined_cachefunc void __before_dc_op(const int op) +{ + unsigned int ctrl; + + ctrl = read_aux_reg(ARC_AUX_DC_CTRL); + + /* IM bit implies flush-n-inv, instead of vanilla inv */ + if (op == OP_INV) + ctrl &= ~DC_CTRL_INV_MODE_FLUSH; + else + ctrl |= DC_CTRL_INV_MODE_FLUSH; + + write_aux_reg(ARC_AUX_DC_CTRL, ctrl); +} + +static inlined_cachefunc void __after_dc_op(const int op) +{ + if (op & OP_FLUSH) /* flush / flush-n-inv both wait */ + while (read_aux_reg(ARC_AUX_DC_CTRL) & DC_CTRL_FLUSH_STATUS); +} + +static inlined_cachefunc void __dc_entire_op(const int cacheop) +{ + int aux; + + if (!dcache_enabled()) + return; + + __before_dc_op(cacheop); + + if (cacheop & OP_INV) /* Inv or flush-n-inv use same cmd reg */ + aux = ARC_AUX_DC_IVDC; + else + aux = ARC_AUX_DC_FLSH; + + write_aux_reg(aux, 0x1); + + __after_dc_op(cacheop); +} + +static inline void __dc_line_op(unsigned long paddr, unsigned long sz, + const int cacheop) +{ + if (!dcache_enabled()) + return; + + __before_dc_op(cacheop); + __dcache_line_loop(paddr, sz, cacheop); + __after_dc_op(cacheop); +} + +void invalidate_dcache_range(unsigned long start, unsigned long end) +{ + if (start >= end) + return; + + /* + * ARCv1 -> call __dc_line_op + * ARCv2 && L1 D$ disabled -> nothing + * ARCv2 && L1 D$ enabled && IOC enabled -> nothing + * ARCv2 && L1 D$ enabled && no IOC -> call __dc_line_op; call __slc_rgn_op + */ + if (!is_isa_arcv2() || !ioc_enabled()) + __dc_line_op(start, end - start, OP_INV); + + if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass()) + __slc_rgn_op(start, end - start, OP_INV); +} + +void flush_dcache_range(unsigned long start, unsigned long end) +{ + if (start >= end) + return; + + /* + * ARCv1 -> call __dc_line_op + * ARCv2 && L1 D$ disabled -> nothing + * ARCv2 && L1 D$ enabled && IOC enabled -> nothing + * ARCv2 && L1 D$ enabled && no IOC -> call __dc_line_op; call __slc_rgn_op + */ + if (!is_isa_arcv2() || !ioc_enabled()) + __dc_line_op(start, end - start, OP_FLUSH); + + if (is_isa_arcv2() && !ioc_enabled() && !slc_data_bypass()) + __slc_rgn_op(start, end - start, OP_FLUSH); +} + +void flush_cache(unsigned long start, unsigned long size) +{ + flush_dcache_range(start, start + size); +} + +/* + * As invalidate_dcache_all() is not used in generic U-Boot code and as we + * don't need it in arch/arc code alone (invalidate without flush) we implement + * flush_n_invalidate_dcache_all (flush and invalidate in 1 operation) because + * it's much safer. See [ NOTE 1 ] for more details. + */ +void flush_n_invalidate_dcache_all(void) +{ + __dc_entire_op(OP_FLUSH_N_INV); + + if (is_isa_arcv2() && !slc_data_bypass()) + __slc_entire_op(OP_FLUSH_N_INV); +} + +void flush_dcache_all(void) +{ + __dc_entire_op(OP_FLUSH); + + if (is_isa_arcv2() && !slc_data_bypass()) + __slc_entire_op(OP_FLUSH); +} + +/* + * This is function to cleanup all caches (and therefore sync I/D caches) which + * can be used for cleanup before linux launch or to sync caches during + * relocation. + */ +void sync_n_cleanup_cache_all(void) +{ + __dc_entire_op(OP_FLUSH_N_INV); + + /* + * If SL$ is bypassed for data it is used only for instructions, + * and we shouldn't flush it. So invalidate it instead of flush_n_inv. + */ + if (is_isa_arcv2()) { + if (slc_data_bypass()) + __slc_entire_op(OP_INV); + else + __slc_entire_op(OP_FLUSH_N_INV); + } + + __ic_entire_invalidate(); +}
diff --git a/arch/arc/lib/cpu.c b/arch/arc/lib/cpu.c new file mode 100644 index 0000000..07daaa8 --- /dev/null +++ b/arch/arc/lib/cpu.c
@@ -0,0 +1,228 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014, 2018 Synopsys, Inc. All rights reserved. + */ + +#include <common.h> +#include <malloc.h> +#include <asm/arcregs.h> +#include <asm/cache.h> + +DECLARE_GLOBAL_DATA_PTR; + +int arch_cpu_init(void) +{ + timer_init(); + + gd->cpu_clk = CONFIG_SYS_CLK_FREQ; + gd->ram_size = CONFIG_SYS_SDRAM_SIZE; + + cache_init(); + + return 0; +} + +int arch_early_init_r(void) +{ + gd->bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; + gd->bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE; + return 0; +} + +/* This is a dummy function on arc */ +int dram_init(void) +{ + return 0; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +const char *arc_700_version(int arcver, char *name, int name_len) +{ + const char *arc_ver; + + switch (arcver) { + case 0x32: + arc_ver = "v4.4-4.5"; + break; + case 0x33: + arc_ver = "v4.6-v4.9"; + break; + case 0x34: + arc_ver = "v4.10"; + break; + case 0x35: + arc_ver = "v4.11"; + break; + default: + arc_ver = "unknown version"; + } + + snprintf(name, name_len, "ARC 700 %s", arc_ver); + + return name; +} + +struct em_template_t { + const bool cache; + const bool dsp; + const bool xymem; + const char name[8]; +}; + +static const struct em_template_t em_versions[] = { + {false, false, false, "EM4"}, + {true, false, false, "EM6"}, + {false, true, false, "EM5D"}, + {true, true, false, "EM7D"}, + {false, true, true, "EM9D"}, + {true, true, true, "EM11D"}, +}; + +const char *arc_em_version(int arcver, char *name, int name_len) +{ + const char *arc_name = "EM"; + const char *arc_ver; + bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD); + bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD); + bool xymem = ARC_FEATURE_EXISTS(ARC_AUX_XY_BUILD); + int i; + + for (i = 0; i++ < sizeof(em_versions) / sizeof(struct em_template_t);) { + if (em_versions[i].cache == cache && + em_versions[i].dsp == dsp && + em_versions[i].xymem == xymem) { + arc_name = em_versions[i].name; + break; + } + } + + switch (arcver) { + case 0x41: + arc_ver = "v1.1a"; + break; + case 0x42: + arc_ver = "v3.0"; + break; + case 0x43: + arc_ver = "v4.0"; + break; + case 0x44: + arc_ver = "v5.0"; + break; + default: + arc_ver = "unknown version"; + } + + snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver); + + return name; +} + +struct hs_template_t { + const bool cache; + const bool mmu; + const bool dual_issue; + const bool dsp; + const char name[8]; +}; + +static const struct hs_template_t hs_versions[] = { + {false, false, false, false, "HS34"}, + {true, false, false, false, "HS36"}, + {true, true, false, false, "HS38"}, + {false, false, true, false, "HS44"}, + {true, false, true, false, "HS46"}, + {true, true, true, false, "HS48"}, + {false, false, true, true, "HS45D"}, + {true, false, true, true, "HS47D"}, +}; + +const char *arc_hs_version(int arcver, char *name, int name_len) +{ + const char *arc_name = "HS"; + const char *arc_ver; + bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD); + bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD); + bool mmu = !!read_aux_reg(ARC_AUX_MMU_BCR); + bool dual_issue = arcver == 0x54 ? true : false; + int i; + + for (i = 0; i++ < sizeof(hs_versions) / sizeof(struct hs_template_t);) { + if (hs_versions[i].cache == cache && + hs_versions[i].mmu == mmu && + hs_versions[i].dual_issue == dual_issue && + hs_versions[i].dsp == dsp) { + arc_name = hs_versions[i].name; + break; + } + } + + switch (arcver) { + case 0x50: + arc_ver = "v1.0"; + break; + case 0x51: + arc_ver = "v2.0"; + break; + case 0x52: + arc_ver = "v2.1c"; + break; + case 0x53: + arc_ver = "v3.0"; + break; + case 0x54: + arc_ver = "v4.0"; + break; + default: + arc_ver = "unknown version"; + } + + snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver); + + return name; +} + +const char *decode_identity(void) +{ +#define MAX_CPU_NAME_LEN 64 + + int arcver = read_aux_reg(ARC_AUX_IDENTITY) & 0xff; + char *name = malloc(MAX_CPU_NAME_LEN); + + if (arcver >= 0x50) + return arc_hs_version(arcver, name, MAX_CPU_NAME_LEN); + else if (arcver >= 0x40) + return arc_em_version(arcver, name, MAX_CPU_NAME_LEN); + else if (arcver >= 0x30) + return arc_700_version(arcver, name, MAX_CPU_NAME_LEN); + else + return "Unknown ARC core"; +} + +const char *decode_subsystem(void) +{ + int subsys_type = read_aux_reg(ARC_AUX_SUBSYS_BUILD) & GENMASK(3, 0); + + switch (subsys_type) { + case 0: return NULL; + case 2: return "ARC Sensor & Control IP Subsystem"; + case 3: return "ARC Data Fusion IP Subsystem"; + case 4: return "ARC Secure Subsystem"; + default: return "Unknown subsystem"; + }; +} + +__weak int print_cpuinfo(void) +{ + const char *subsys_name = decode_subsystem(); + char mhz[8]; + + printf("CPU: %s at %s MHz\n", decode_identity(), + strmhz(mhz, gd->cpu_clk)); + + if (subsys_name) + printf("Subsys:%s\n", subsys_name); + + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */
diff --git a/arch/arc/lib/init_helpers.c b/arch/arc/lib/init_helpers.c new file mode 100644 index 0000000..c853f25 --- /dev/null +++ b/arch/arc/lib/init_helpers.c
@@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved. + */ + +#include <asm/cache.h> +#include <common.h> + +int init_cache_f_r(void) +{ + sync_n_cleanup_cache_all(); + + return 0; +}
diff --git a/arch/arc/lib/interrupts.c b/arch/arc/lib/interrupts.c new file mode 100644 index 0000000..24ff751 --- /dev/null +++ b/arch/arc/lib/interrupts.c
@@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#include <common.h> +#include <asm/arcregs.h> +#include <asm/ptrace.h> + +/* Bit values in STATUS32 */ +#define E1_MASK (1 << 1) /* Level 1 interrupts enable */ +#define E2_MASK (1 << 2) /* Level 2 interrupts enable */ + +int interrupt_init(void) +{ + return 0; +} + +/* + * returns true if interrupts had been enabled before we disabled them + */ +int disable_interrupts(void) +{ + int status = read_aux_reg(ARC_AUX_STATUS32); + int state = (status & (E1_MASK | E2_MASK)) ? 1 : 0; + + status &= ~(E1_MASK | E2_MASK); + /* STATUS32 register is updated indirectly with "FLAG" instruction */ + __asm__("flag %0" : : "r" (status)); + return state; +} + +void enable_interrupts(void) +{ + unsigned int status = read_aux_reg(ARC_AUX_STATUS32); + + status |= E1_MASK | E2_MASK; + /* STATUS32 register is updated indirectly with "FLAG" instruction */ + __asm__("flag %0" : : "r" (status)); +} + +static void print_reg_file(long *reg_rev, int start_num) +{ + unsigned int i; + + /* Print 3 registers per line */ + for (i = start_num; i < start_num + 25; i++) { + printf("r%02u: 0x%08lx\t", i, (unsigned long)*reg_rev); + if (((i + 1) % 3) == 0) + printf("\n"); + + /* Because pt_regs has registers reversed */ + reg_rev--; + } + + /* Add new-line if none was inserted in the end of loop above */ + if (((i + 1) % 3) != 0) + printf("\n"); +} + +void show_regs(struct pt_regs *regs) +{ + printf("ECR:\t0x%08lx\n", regs->ecr); + printf("RET:\t0x%08lx\nBLINK:\t0x%08lx\nSTAT32:\t0x%08lx\n", + regs->ret, regs->blink, regs->status32); + printf("GP: 0x%08lx\t r25: 0x%08lx\t\n", regs->r26, regs->r25); + printf("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n", regs->bta, + regs->sp, regs->fp); + printf("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", regs->lp_start, + regs->lp_end, regs->lp_count); + + print_reg_file(&(regs->r0), 0); +} + +void bad_mode(struct pt_regs *regs) +{ + if (regs) + show_regs(regs); + + panic("Resetting CPU ...\n"); +} + +void do_memory_error(unsigned long address, struct pt_regs *regs) +{ + printf("Memory error exception @ 0x%lx\n", address); + bad_mode(regs); +} + +void do_instruction_error(unsigned long address, struct pt_regs *regs) +{ + printf("Instruction error exception @ 0x%lx\n", address); + bad_mode(regs); +} + +void do_machine_check_fault(unsigned long address, struct pt_regs *regs) +{ + printf("Machine check exception @ 0x%lx\n", address); + bad_mode(regs); +} + +void do_interrupt_handler(void) +{ + printf("Interrupt fired\n"); + bad_mode(0); +} + +void do_itlb_miss(struct pt_regs *regs) +{ + printf("I TLB miss exception\n"); + bad_mode(regs); +} + +void do_dtlb_miss(struct pt_regs *regs) +{ + printf("D TLB miss exception\n"); + bad_mode(regs); +} + +void do_tlb_prot_violation(unsigned long address, struct pt_regs *regs) +{ + printf("TLB protection violation or misaligned access @ 0x%lx\n", + address); + bad_mode(regs); +} + +void do_privilege_violation(struct pt_regs *regs) +{ + printf("Privilege violation exception\n"); + bad_mode(regs); +} + +void do_trap(struct pt_regs *regs) +{ + printf("Trap exception\n"); + bad_mode(regs); +} + +void do_extension(struct pt_regs *regs) +{ + printf("Extension instruction exception\n"); + bad_mode(regs); +} + +#ifdef CONFIG_ISA_ARCV2 +void do_swi(struct pt_regs *regs) +{ + printf("Software Interrupt exception\n"); + bad_mode(regs); +} + +void do_divzero(unsigned long address, struct pt_regs *regs) +{ + printf("Division by zero exception @ 0x%lx\n", address); + bad_mode(regs); +} + +void do_dcerror(struct pt_regs *regs) +{ + printf("Data cache consistency error exception\n"); + bad_mode(regs); +} + +void do_maligned(unsigned long address, struct pt_regs *regs) +{ + printf("Misaligned data access exception @ 0x%lx\n", address); + bad_mode(regs); +} +#endif
diff --git a/arch/arc/lib/ints_low.S b/arch/arc/lib/ints_low.S new file mode 100644 index 0000000..38c45c6 --- /dev/null +++ b/arch/arc/lib/ints_low.S
@@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved. + */ + +#include <linux/linkage.h> + +/* + * Note on the LD/ST addressing modes with address register write-back + * + * LD.a same as LD.aw + * + * LD.a reg1, [reg2, x] => Pre Incr + * Eff Addr for load = [reg2 + x] + * + * LD.ab reg1, [reg2, x] => Post Incr + * Eff Addr for load = [reg2] + */ + +.macro PUSH reg + st.a \reg, [%sp, -4] +.endm + +.macro PUSHAX aux + lr %r9, [\aux] + PUSH %r9 +.endm + +.macro SAVE_R1_TO_R24 + PUSH %r1 + PUSH %r2 + PUSH %r3 + PUSH %r4 + PUSH %r5 + PUSH %r6 + PUSH %r7 + PUSH %r8 + PUSH %r9 + PUSH %r10 + PUSH %r11 + PUSH %r12 + PUSH %r13 + PUSH %r14 + PUSH %r15 + PUSH %r16 + PUSH %r17 + PUSH %r18 + PUSH %r19 + PUSH %r20 + PUSH %r21 + PUSH %r22 + PUSH %r23 + PUSH %r24 +.endm + +.macro SAVE_ALL_SYS + /* saving %r0 to reg->r0 in advance since we read %ecr into it */ + st %r0, [%sp, -8] + lr %r0, [%ecr] /* all stack addressing is manual so far */ + st %r0, [%sp] + st %sp, [%sp, -4] + /* now move %sp to reg->r0 position so we can do "push" automatically */ + sub %sp, %sp, 8 + + SAVE_R1_TO_R24 + PUSH %r25 + PUSH %gp + PUSH %fp + PUSH %blink + PUSHAX %eret + PUSHAX %erstatus + PUSH %lp_count + PUSHAX %lp_end + PUSHAX %lp_start + PUSHAX %erbta +.endm + +.macro SAVE_EXCEPTION_SOURCE +#ifdef CONFIG_MMU + /* If MMU exists exception faulting address is loaded in EFA reg */ + lr %r0, [%efa] +#else + /* Otherwise in ERET (exception return) reg */ + lr %r0, [%eret] +#endif +.endm + +ENTRY(memory_error) + SAVE_ALL_SYS + SAVE_EXCEPTION_SOURCE + mov %r1, %sp + j do_memory_error +ENDPROC(memory_error) + +ENTRY(instruction_error) + SAVE_ALL_SYS + SAVE_EXCEPTION_SOURCE + mov %r1, %sp + j do_instruction_error +ENDPROC(instruction_error) + +ENTRY(interrupt_handler) + /* Todo - save and restore CPU context when interrupts will be in use */ + bl do_interrupt_handler + rtie +ENDPROC(interrupt_handler) + +ENTRY(EV_MachineCheck) + SAVE_ALL_SYS + SAVE_EXCEPTION_SOURCE + mov %r1, %sp + j do_machine_check_fault +ENDPROC(EV_MachineCheck) + +ENTRY(EV_TLBMissI) + SAVE_ALL_SYS + mov %r0, %sp + j do_itlb_miss +ENDPROC(EV_TLBMissI) + +ENTRY(EV_TLBMissD) + SAVE_ALL_SYS + mov %r0, %sp + j do_dtlb_miss +ENDPROC(EV_TLBMissD) + +ENTRY(EV_TLBProtV) + SAVE_ALL_SYS + SAVE_EXCEPTION_SOURCE + mov %r1, %sp + j do_tlb_prot_violation +ENDPROC(EV_TLBProtV) + +ENTRY(EV_PrivilegeV) + SAVE_ALL_SYS + mov %r0, %sp + j do_privilege_violation +ENDPROC(EV_PrivilegeV) + +ENTRY(EV_Trap) + SAVE_ALL_SYS + mov %r0, %sp + j do_trap +ENDPROC(EV_Trap) + +ENTRY(EV_Extension) + SAVE_ALL_SYS + mov %r0, %sp + j do_extension +ENDPROC(EV_Extension) + +#ifdef CONFIG_ISA_ARCV2 +ENTRY(EV_SWI) + SAVE_ALL_SYS + mov %r0, %sp + j do_swi +ENDPROC(EV_SWI) + +ENTRY(EV_DivZero) + SAVE_ALL_SYS + SAVE_EXCEPTION_SOURCE + mov %r1, %sp + j do_divzero +ENDPROC(EV_DivZero) + +ENTRY(EV_DCError) + SAVE_ALL_SYS + mov %r0, %sp + j do_dcerror +ENDPROC(EV_DCError) + +ENTRY(EV_Maligned) + SAVE_ALL_SYS + SAVE_EXCEPTION_SOURCE + mov %r1, %sp + j do_maligned +ENDPROC(EV_Maligned) +#endif
diff --git a/arch/arc/lib/libgcc2.c b/arch/arc/lib/libgcc2.c new file mode 100644 index 0000000..b92a841 --- /dev/null +++ b/arch/arc/lib/libgcc2.c
@@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 1989-2013 Free Software Foundation, Inc. + */ + +#include "libgcc2.h" + +DWtype +__ashldi3(DWtype u, shift_count_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const shift_count_type bm = W_TYPE_SIZE - b; + DWunion w; + + if (bm <= 0) { + w.s.low = 0; + w.s.high = (UWtype)uu.s.low << -bm; + } else { + const UWtype carries = (UWtype) uu.s.low >> bm; + + w.s.low = (UWtype)uu.s.low << b; + w.s.high = ((UWtype)uu.s.high << b) | carries; + } + + return w.ll; +} + +DWtype +__ashrdi3(DWtype u, shift_count_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const shift_count_type bm = W_TYPE_SIZE - b; + DWunion w; + + if (bm <= 0) { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = uu.s.high >> (W_TYPE_SIZE - 1); + w.s.low = uu.s.high >> -bm; + } else { + const UWtype carries = (UWtype) uu.s.high << bm; + + w.s.high = uu.s.high >> b; + w.s.low = ((UWtype)uu.s.low >> b) | carries; + } + + return w.ll; +} + +DWtype +__lshrdi3(DWtype u, shift_count_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const shift_count_type bm = W_TYPE_SIZE - b; + DWunion w; + + if (bm <= 0) { + w.s.high = 0; + w.s.low = (UWtype)uu.s.high >> -bm; + } else { + const UWtype carries = (UWtype)uu.s.high << bm; + + w.s.high = (UWtype)uu.s.high >> b; + w.s.low = ((UWtype)uu.s.low >> b) | carries; + } + + return w.ll; +} + +unsigned long +udivmodsi4(unsigned long num, unsigned long den, int modwanted) +{ + unsigned long bit = 1; + unsigned long res = 0; + + while (den < num && bit && !(den & (1L<<31))) { + den <<= 1; + bit <<= 1; + } + + while (bit) { + if (num >= den) { + num -= den; + res |= bit; + } + bit >>= 1; + den >>= 1; + } + + if (modwanted) + return num; + + return res; +} + +long +__divsi3(long a, long b) +{ + int neg = 0; + long res; + + if (a < 0) { + a = -a; + neg = !neg; + } + + if (b < 0) { + b = -b; + neg = !neg; + } + + res = udivmodsi4(a, b, 0); + + if (neg) + res = -res; + + return res; +} + +long +__modsi3(long a, long b) +{ + int neg = 0; + long res; + + if (a < 0) { + a = -a; + neg = 1; + } + + if (b < 0) + b = -b; + + res = udivmodsi4(a, b, 1); + + if (neg) + res = -res; + + return res; +} + +long +__udivsi3(long a, long b) +{ + return udivmodsi4(a, b, 0); +} + +long +__umodsi3(long a, long b) +{ + return udivmodsi4(a, b, 1); +}
diff --git a/arch/arc/lib/libgcc2.h b/arch/arc/lib/libgcc2.h new file mode 100644 index 0000000..9c3ce99 --- /dev/null +++ b/arch/arc/lib/libgcc2.h
@@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 1989-2013 Free Software Foundation, Inc. + */ + +#ifndef __ASM_LIBGCC_H +#define __ASM_LIBGCC_H + +#define UNITS_PER_WORD 4 /* for ARC */ +#define BITS_PER_UNIT 8 /* for ARC */ + +#define W_TYPE_SIZE (4 * BITS_PER_UNIT) + +#define MIN_UNITS_PER_WORD UNITS_PER_WORD + +/* Work out the largest "word" size that we can deal with on this target. */ +#if MIN_UNITS_PER_WORD > 4 +# define LIBGCC2_MAX_UNITS_PER_WORD 8 +#elif (MIN_UNITS_PER_WORD > 2 \ + || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4)) +# define LIBGCC2_MAX_UNITS_PER_WORD 4 +#else +# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD +#endif + +/* Work out what word size we are using for this compilation. + The value can be set on the command line. */ +#ifndef LIBGCC2_UNITS_PER_WORD +#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD +#endif + +typedef int QItype __attribute__ ((mode (QI))); +typedef unsigned int UQItype __attribute__ ((mode (QI))); +typedef int HItype __attribute__ ((mode (HI))); +typedef unsigned int UHItype __attribute__ ((mode (HI))); +#if MIN_UNITS_PER_WORD > 1 +/* These typedefs are usually forbidden on dsp's with UNITS_PER_WORD 1. */ +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +#if __SIZEOF_LONG_LONG__ > 4 +/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 2. */ +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +#if MIN_UNITS_PER_WORD > 4 +/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 4. */ +typedef int TItype __attribute__ ((mode (TI))); +typedef unsigned int UTItype __attribute__ ((mode (TI))); +#endif +#endif +#endif + +#if LIBGCC2_UNITS_PER_WORD == 8 +#define W_TYPE_SIZE (8 * BITS_PER_UNIT) +#define Wtype DItype +#define UWtype UDItype +#define HWtype DItype +#define UHWtype UDItype +#define DWtype TItype +#define UDWtype UTItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## di ## b +#define __NDW(a,b) __gnu_ ## a ## ti ## b +#else +#define __NW(a,b) __ ## a ## di ## b +#define __NDW(a,b) __ ## a ## ti ## b +#endif +#elif LIBGCC2_UNITS_PER_WORD == 4 +#define W_TYPE_SIZE (4 * BITS_PER_UNIT) +#define Wtype SItype +#define UWtype USItype +#define HWtype SItype +#define UHWtype USItype +#define DWtype DItype +#define UDWtype UDItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## si ## b +#define __NDW(a,b) __gnu_ ## a ## di ## b +#else +#define __NW(a,b) __ ## a ## si ## b +#define __NDW(a,b) __ ## a ## di ## b +#endif +#elif LIBGCC2_UNITS_PER_WORD == 2 +#define W_TYPE_SIZE (2 * BITS_PER_UNIT) +#define Wtype HItype +#define UWtype UHItype +#define HWtype HItype +#define UHWtype UHItype +#define DWtype SItype +#define UDWtype USItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## hi ## b +#define __NDW(a,b) __gnu_ ## a ## si ## b +#else +#define __NW(a,b) __ ## a ## hi ## b +#define __NDW(a,b) __ ## a ## si ## b +#endif +#else +#define W_TYPE_SIZE BITS_PER_UNIT +#define Wtype QItype +#define UWtype UQItype +#define HWtype QItype +#define UHWtype UQItype +#define DWtype HItype +#define UDWtype UHItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## qi ## b +#define __NDW(a,b) __gnu_ ## a ## hi ## b +#else +#define __NW(a,b) __ ## a ## qi ## b +#define __NDW(a,b) __ ## a ## hi ## b +#endif +#endif + +typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__))); + +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ + struct DWstruct {Wtype high, low;}; +#else + struct DWstruct {Wtype low, high;}; +#endif + +/* We need this union to unpack/pack DImode values, since we don't have + any arithmetic yet. Incoming DImode parameters are stored into the + `ll' field, and the unpacked result is read from the struct `s'. */ + +typedef union { + struct DWstruct s; + DWtype ll; +} DWunion; + +#endif /* __ASM_LIBGCC_H */
diff --git a/arch/arc/lib/relocate.c b/arch/arc/lib/relocate.c new file mode 100644 index 0000000..4ffba84 --- /dev/null +++ b/arch/arc/lib/relocate.c
@@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#include <common.h> +#include <elf.h> +#include <asm-generic/sections.h> + +extern ulong __image_copy_start; +extern ulong __ivt_start; +extern ulong __ivt_end; +extern ulong __text_end; + +DECLARE_GLOBAL_DATA_PTR; + +int copy_uboot_to_ram(void) +{ + size_t len = (size_t)&__image_copy_end - (size_t)&__image_copy_start; + + if (gd->flags & GD_FLG_SKIP_RELOC) + return 0; + + memcpy((void *)gd->relocaddr, (void *)&__image_copy_start, len); + + return 0; +} + +int clear_bss(void) +{ + ulong dst_addr = (ulong)&__bss_start + gd->reloc_off; + size_t len = (size_t)&__bss_end - (size_t)&__bss_start; + + memset((void *)dst_addr, 0x00, len); + + return 0; +} + +/* + * Base functionality is taken from x86 version with added ARC-specifics + */ +int do_elf_reloc_fixups(void) +{ + Elf32_Rela *re_src = (Elf32_Rela *)(&__rel_dyn_start); + Elf32_Rela *re_end = (Elf32_Rela *)(&__rel_dyn_end); + + if (gd->flags & GD_FLG_SKIP_RELOC) + return 0; + + debug("Section .rela.dyn is located at %08x-%08x\n", + (unsigned int)re_src, (unsigned int)re_end); + + Elf32_Addr *offset_ptr_rom; + Elf32_Addr *offset_ptr_ram; + + do { + /* Get the location from the relocation entry */ + offset_ptr_rom = (Elf32_Addr *)re_src->r_offset; + + /* Check that the location of the relocation is in .text */ + if (offset_ptr_rom >= (Elf32_Addr *)&__image_copy_start && + offset_ptr_rom < (Elf32_Addr *)&__image_copy_end) { + unsigned int val, do_swap = 0; + /* Switch to the in-RAM version */ + offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + + gd->reloc_off); + +#ifdef __LITTLE_ENDIAN__ + /* If location in ".text" section swap value */ + if (((u32)offset_ptr_rom >= (u32)&__text_start && + (u32)offset_ptr_rom <= (u32)&__text_end) +#if defined(__ARC700__) || defined(__ARC600__) + || ((u32)offset_ptr_rom >= (u32)&__ivt_start && + (u32)offset_ptr_rom <= (u32)&__ivt_end) +#endif + ) + do_swap = 1; +#endif + + debug("Patching value @ %08x (relocated to %08x)%s\n", + (unsigned int)offset_ptr_rom, + (unsigned int)offset_ptr_ram, + do_swap ? ", middle-endian encoded" : ""); + + /* + * Use "memcpy" because target location might be + * 16-bit aligned on ARC so we may need to read + * byte-by-byte. On attempt to read entire word by + * CPU throws an exception + */ + memcpy(&val, offset_ptr_ram, sizeof(int)); + + if (do_swap) + val = (val << 16) | (val >> 16); + + /* Check that the target points into executable */ + if (val < (unsigned int)&__image_copy_start || + val > (unsigned int)&__image_copy_end) { + /* TODO: Use panic() instead of debug() + * + * For some reason GCC might generate + * fake relocation even for LD/SC of constant + * inderectly. See an example below: + * ----------------------->8-------------------- + * static int setup_mon_len(void) + * { + * gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE; + * return 0; + * } + * ----------------------->8-------------------- + * + * And that's what we get in the binary: + * ----------------------->8-------------------- + * 10005cb4 <setup_mon_len>: + * 10005cb4: 193c 3f80 0003 2f80 st 0x32f80,[r25,60] + * 10005cb8: R_ARC_RELATIVE *ABS*-0x10000000 + * 10005cbc: 7fe0 j_s.d [blink] + * 10005cbe: 700c mov_s r0,0 + * ----------------------->8-------------------- + */ + debug("Relocation target %08x points outside of image\n", + val); + } + + val += gd->reloc_off; + + if (do_swap) + val = (val << 16) | (val >> 16); + + memcpy(offset_ptr_ram, &val, sizeof(int)); + } + } while (++re_src < re_end); + + return 0; +}
diff --git a/arch/arc/lib/reset.c b/arch/arc/lib/reset.c new file mode 100644 index 0000000..02e08df --- /dev/null +++ b/arch/arc/lib/reset.c
@@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#include <command.h> +#include <common.h> + +__weak void reset_cpu(ulong addr) +{ + /* Stop debug session here */ + __builtin_arc_brk(); +} + +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + printf("Resetting the board...\n"); + + reset_cpu(0); + + return 0; +}
diff --git a/arch/arc/lib/start.S b/arch/arc/lib/start.S new file mode 100644 index 0000000..84959b4 --- /dev/null +++ b/arch/arc/lib/start.S
@@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> +#include <asm/arcregs.h> + +ENTRY(_start) + /* Setup interrupt vector base that matches "__text_start" */ + sr __ivt_start, [ARC_AUX_INTR_VEC_BASE] + + ; Disable/enable I-cache according to configuration + lr r5, [ARC_BCR_IC_BUILD] + breq r5, 0, 1f ; I$ doesn't exist + lr r5, [ARC_AUX_IC_CTRL] +#ifndef CONFIG_SYS_ICACHE_OFF + bclr r5, r5, 0 ; 0 - Enable, 1 is Disable +#else + bset r5, r5, 0 ; I$ exists, but is not used +#endif + sr r5, [ARC_AUX_IC_CTRL] + + mov r5, 1 + sr r5, [ARC_AUX_IC_IVIC] + ; As per ARC HS databook (see chapter 5.3.3.2) + ; it is required to add 3 NOPs after each write to IC_IVIC. + nop + nop + nop + +1: + ; Disable/enable D-cache according to configuration + lr r5, [ARC_BCR_DC_BUILD] + breq r5, 0, 1f ; D$ doesn't exist + lr r5, [ARC_AUX_DC_CTRL] + bclr r5, r5, 6 ; Invalidate (discard w/o wback) +#ifndef CONFIG_SYS_DCACHE_OFF + bclr r5, r5, 0 ; Enable (+Inv) +#else + bset r5, r5, 0 ; Disable (+Inv) +#endif + sr r5, [ARC_AUX_DC_CTRL] + + mov r5, 1 + sr r5, [ARC_AUX_DC_IVDC] + + +1: +#ifdef CONFIG_ISA_ARCV2 + ; Disable System-Level Cache (SLC) + lr r5, [ARC_BCR_SLC] + breq r5, 0, 1f ; SLC doesn't exist + lr r5, [ARC_AUX_SLC_CTRL] + bclr r5, r5, 6 ; Invalidate (discard w/o wback) + bclr r5, r5, 0 ; Enable (+Inv) + sr r5, [ARC_AUX_SLC_CTRL] + +1: +#endif + +#ifdef __ARC_UNALIGNED__ + /* + * Enable handling of unaligned access in the CPU as by default + * this HW feature is disabled while GCC starting from 8.1.0 + * unconditionally uses it for ARC HS cores. + */ + flag 1 << STATUS_AD_BIT +#endif + + /* Establish C runtime stack and frame */ + mov %sp, CONFIG_SYS_INIT_SP_ADDR + mov %fp, %sp + + /* Allocate reserved area from current top of stack */ + mov %r0, %sp + bl board_init_f_alloc_reserve + /* Set stack below reserved area, adjust frame pointer accordingly */ + mov %sp, %r0 + mov %fp, %sp + + /* Initialize reserved area - note: r0 already contains address */ + bl board_init_f_init_reserve + +#ifdef CONFIG_DEBUG_UART + /* Earliest point to set up early debug uart */ + bl debug_uart_init +#endif + + /* Zero the one and only argument of "board_init_f" */ + mov_s %r0, 0 + bl board_init_f + + /* We only get here if relocation is disabled by GD_FLG_SKIP_RELOC */ + /* Make sure we don't lose GD overwritten by zero new GD */ + mov %r0, %r25 + mov %r1, 0 + bl board_init_r +ENDPROC(_start) + +/* + * void board_init_f_r_trampoline(stack-pointer address) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * r0 = new stack-pointer + */ +ENTRY(board_init_f_r_trampoline) + /* Set up the stack- and frame-pointers */ + mov %sp, %r0 + mov %fp, %sp + + /* Update position of intterupt vector table */ + lr %r0, [ARC_AUX_INTR_VEC_BASE] + ld %r1, [%r25, GD_RELOC_OFF] + add %r0, %r0, %r1 + sr %r0, [ARC_AUX_INTR_VEC_BASE] + + /* Re-enter U-Boot by calling board_init_f_r */ + j board_init_f_r +ENDPROC(board_init_f_r_trampoline)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig new file mode 100644 index 0000000..d6b1629 --- /dev/null +++ b/arch/arm/Kconfig
@@ -0,0 +1,1577 @@ +menu "ARM architecture" + depends on ARM + +config SYS_ARCH + default "arm" + +config ARM64 + bool + select PHYS_64BIT + select SYS_CACHE_SHIFT_6 + +if ARM64 +config POSITION_INDEPENDENT + bool "Generate position-independent pre-relocation code" + help + U-Boot expects to be linked to a specific hard-coded address, and to + be loaded to and run from that address. This option lifts that + restriction, thus allowing the code to be loaded to and executed + from almost any address. This logic relies on the relocation + information that is embedded into the binary to support U-Boot + relocating itself to the top-of-RAM later during execution. + +config SYS_INIT_SP_BSS_OFFSET + int + help + U-Boot typically uses a hard-coded value for the stack pointer + before relocation. Define this option to instead calculate the + initial SP at run-time. This is useful to avoid hard-coding addresses + into U-Boot, so that can be loaded and executed at arbitrary + addresses and thus avoid using arbitrary addresses at runtime. This + option's value is the offset added to &_bss_start in order to + calculate the stack pointer. This offset should be large enough so + that the early malloc region, global data (gd), and early stack usage + do not overlap any appended DTB. + +config LINUX_KERNEL_IMAGE_HEADER + bool + help + Place a Linux kernel image header at the start of the U-Boot binary. + The format of the header is described in the Linux kernel source at + Documentation/arm64/booting.txt. This feature is useful since the + image header reports the amount of memory (BSS and similar) that + U-Boot needs to use, but which isn't part of the binary. + +if LINUX_KERNEL_IMAGE_HEADER +config LNX_KRNL_IMG_TEXT_OFFSET_BASE + hex + help + The value subtracted from CONFIG_SYS_TEXT_BASE to calculate the + TEXT_OFFSET value written in to the Linux kernel image header. +endif +endif + +config STATIC_RELA + bool + default y if ARM64 && !POSITION_INDEPENDENT + +config DMA_ADDR_T_64BIT + bool + default y if ARM64 + +config HAS_VBAR + bool + +config HAS_THUMB2 + bool + +# Used for compatibility with asm files copied from the kernel +config ARM_ASM_UNIFIED + bool + default y + +# Used for compatibility with asm files copied from the kernel +config THUMB2_KERNEL + bool + +config SYS_ARM_CACHE_CP15 + bool "CP15 based cache enabling support" + help + Select this if your processor suports enabling caches by using + CP15 registers. + +config SYS_ARM_MMU + bool "MMU-based Paged Memory Management Support" + select SYS_ARM_CACHE_CP15 + help + Select if you want MMU-based virtualised addressing space + support by paged memory management. + +config SYS_ARM_MPU + bool 'Use the ARM v7 PMSA Compliant MPU' + help + Some ARM systems without an MMU have instead a Memory Protection + Unit (MPU) that defines the type and permissions for regions of + memory. + If your CPU has an MPU then you should choose 'y' here unless you + know that you do not want to use the MPU. + +# If set, the workarounds for these ARM errata are applied early during U-Boot +# startup. Note that in general these options force the workarounds to be +# applied; no CPU-type/version detection exists, unlike the similar options in +# the Linux kernel. Do not set these options unless they apply! Also note that +# the following can be machine specific errata. These do have ability to +# provide rudimentary version and machine specific checks, but expect no +# product checks: +# CONFIG_ARM_ERRATA_430973 +# CONFIG_ARM_ERRATA_454179 +# CONFIG_ARM_ERRATA_621766 +# CONFIG_ARM_ERRATA_798870 +# CONFIG_ARM_ERRATA_801819 +# CONFIG_ARM_CORTEX_A8_CVE_2017_5715 +# CONFIG_ARM_CORTEX_A15_CVE_2017_5715 + +config ARM_ERRATA_430973 + bool + +config ARM_ERRATA_454179 + bool + +config ARM_ERRATA_621766 + bool + +config ARM_ERRATA_716044 + bool + +config ARM_ERRATA_725233 + bool + +config ARM_ERRATA_742230 + bool + +config ARM_ERRATA_743622 + bool + +config ARM_ERRATA_751472 + bool + +config ARM_ERRATA_761320 + bool + +config ARM_ERRATA_773022 + bool + +config ARM_ERRATA_774769 + bool + +config ARM_ERRATA_794072 + bool + +config ARM_ERRATA_798870 + bool + +config ARM_ERRATA_801819 + bool + +config ARM_ERRATA_826974 + bool + +config ARM_ERRATA_828024 + bool + +config ARM_ERRATA_829520 + bool + +config ARM_ERRATA_833069 + bool + +config ARM_ERRATA_833471 + bool + +config ARM_ERRATA_845369 + bool + +config ARM_ERRATA_852421 + bool + +config ARM_ERRATA_852423 + bool + +config ARM_ERRATA_855873 + bool + +config ARM_CORTEX_A8_CVE_2017_5715 + bool + +config ARM_CORTEX_A15_CVE_2017_5715 + bool + +config CPU_ARM720T + bool + select SYS_CACHE_SHIFT_5 + imply SYS_ARM_MMU + +config CPU_ARM920T + bool + select SYS_CACHE_SHIFT_5 + imply SYS_ARM_MMU + +config CPU_ARM926EJS + bool + select SYS_CACHE_SHIFT_5 + imply SYS_ARM_MMU + +config CPU_ARM946ES + bool + select SYS_CACHE_SHIFT_5 + imply SYS_ARM_MMU + +config CPU_ARM1136 + bool + select SYS_CACHE_SHIFT_5 + imply SYS_ARM_MMU + +config CPU_ARM1176 + bool + select HAS_VBAR + select SYS_CACHE_SHIFT_5 + imply SYS_ARM_MMU + +config CPU_V7A + bool + select HAS_THUMB2 + select HAS_VBAR + select SYS_CACHE_SHIFT_6 + imply SYS_ARM_MMU + +config CPU_V7M + bool + select HAS_THUMB2 + select SYS_ARM_MPU + select SYS_CACHE_SHIFT_5 + select SYS_THUMB_BUILD + select THUMB2_KERNEL + +config CPU_V7R + bool + select HAS_THUMB2 + select SYS_ARM_CACHE_CP15 + select SYS_ARM_MPU + select SYS_CACHE_SHIFT_6 + +config CPU_PXA + bool + select SYS_CACHE_SHIFT_5 + imply SYS_ARM_MMU + +config CPU_SA1100 + bool + select SYS_CACHE_SHIFT_5 + imply SYS_ARM_MMU + +config SYS_CPU + default "arm720t" if CPU_ARM720T + default "arm920t" if CPU_ARM920T + default "arm926ejs" if CPU_ARM926EJS + default "arm946es" if CPU_ARM946ES + default "arm1136" if CPU_ARM1136 + default "arm1176" if CPU_ARM1176 + default "armv7" if CPU_V7A + default "armv7" if CPU_V7R + default "armv7m" if CPU_V7M + default "pxa" if CPU_PXA + default "sa1100" if CPU_SA1100 + default "armv8" if ARM64 + +config SYS_ARM_ARCH + int + default 4 if CPU_ARM720T + default 4 if CPU_ARM920T + default 5 if CPU_ARM926EJS + default 5 if CPU_ARM946ES + default 6 if CPU_ARM1136 + default 6 if CPU_ARM1176 + default 7 if CPU_V7A + default 7 if CPU_V7M + default 7 if CPU_V7R + default 5 if CPU_PXA + default 4 if CPU_SA1100 + default 8 if ARM64 + +config SYS_CACHE_SHIFT_5 + bool + +config SYS_CACHE_SHIFT_6 + bool + +config SYS_CACHE_SHIFT_7 + bool + +config SYS_CACHELINE_SIZE + int + default 128 if SYS_CACHE_SHIFT_7 + default 64 if SYS_CACHE_SHIFT_6 + default 32 if SYS_CACHE_SHIFT_5 + +config SYS_ARCH_TIMER + bool "ARM Generic Timer support" + depends on CPU_V7A || ARM64 + default y if ARM64 + help + The ARM Generic Timer (aka arch-timer) provides an architected + interface to a timer source on an SoC. + It is mandantory for ARMv8 implementation and widely available + on ARMv7 systems. + +config ARM_SMCCC + bool "Support for ARM SMC Calling Convention (SMCCC)" + depends on CPU_V7A || ARM64 + select ARM_PSCI_FW + help + Say Y here if you want to enable ARM SMC Calling Convention. + This should be enabled if U-Boot needs to communicate with system + firmware (for example, PSCI) according to SMCCC. + +config SEMIHOSTING + bool "support boot from semihosting" + help + In emulated environments, semihosting is a way for + the hosted environment to call out to the emulator to + retrieve files from the host machine. + +config SYS_THUMB_BUILD + bool "Build U-Boot using the Thumb instruction set" + depends on !ARM64 + help + 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. + +config SPL_SYS_THUMB_BUILD + bool "Build SPL using the Thumb instruction set" + default y if SYS_THUMB_BUILD + depends on !ARM64 + help + Use this flag to build SPL 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. + +config SYS_L2CACHE_OFF + bool "L2cache off" + help + If SoC does not support L2CACHE or one do not want to enable + L2CACHE, choose this option. + +config ENABLE_ARM_SOC_BOOT0_HOOK + bool "prepare BOOT0 header" + help + If the SoC's BOOT0 requires a header area filled with (magic) + values, then choose this option, and create a file included as + <asm/arch/boot0.h> which contains the required assembler code. + +config ARM_CORTEX_CPU_IS_UP + bool + default n + +config USE_ARCH_MEMCPY + bool "Use an assembly optimized implementation of memcpy" + default y + depends on !ARM64 + help + Enable the generation of an optimized version of memcpy. + Such implementation may be faster under some conditions + but may increase the binary size. + +config SPL_USE_ARCH_MEMCPY + bool "Use an assembly optimized implementation of memcpy for SPL" + default y if USE_ARCH_MEMCPY + depends on !ARM64 + help + Enable the generation of an optimized version of memcpy. + Such implementation may be faster under some conditions + but may increase the binary size. + +config USE_ARCH_MEMSET + bool "Use an assembly optimized implementation of memset" + default y + depends on !ARM64 + help + Enable the generation of an optimized version of memset. + Such implementation may be faster under some conditions + but may increase the binary size. + +config SPL_USE_ARCH_MEMSET + bool "Use an assembly optimized implementation of memset for SPL" + default y if USE_ARCH_MEMSET + depends on !ARM64 + help + Enable the generation of an optimized version of memset. + Such implementation may be faster under some conditions + but may increase the binary size. + +config ARM64_SUPPORT_AARCH32 + bool "ARM64 system support AArch32 execution state" + default y if ARM64 && !TARGET_THUNDERX_88XX + help + This ARM64 system supports AArch32 execution state. + +choice + prompt "Target select" + default TARGET_HIKEY + +config ARCH_AT91 + bool "Atmel AT91" + select SPL_BOARD_INIT if SPL && !TARGET_SMARTWEB + +config TARGET_EDB93XX + bool "Support edb93xx" + select CPU_ARM920T + select PL010_SERIAL + +config TARGET_ASPENITE + bool "Support aspenite" + select CPU_ARM926EJS + +config TARGET_GPLUGD + bool "Support gplugd" + select CPU_ARM926EJS + +config ARCH_DAVINCI + bool "TI DaVinci" + select CPU_ARM926EJS + imply CMD_SAVES + help + Support for TI's DaVinci platform. + +config KIRKWOOD + bool "Marvell Kirkwood" + select ARCH_MISC_INIT + select BOARD_EARLY_INIT_F + select CPU_ARM926EJS + +config ARCH_MVEBU + bool "Marvell MVEBU family (Armada XP/375/38x/3700/7K/8K)" + select DM + select DM_ETH + select DM_SERIAL + select DM_SPI + select DM_SPI_FLASH + select OF_CONTROL + select OF_SEPARATE + select SPI + imply CMD_DM + +config TARGET_APF27 + bool "Support apf27" + select CPU_ARM926EJS + select SUPPORT_SPL + +config ORION5X + bool "Marvell Orion" + select CPU_ARM926EJS + +config TARGET_SPEAR300 + bool "Support spear300" + select BOARD_EARLY_INIT_F + select CPU_ARM926EJS + select PL011_SERIAL + imply CMD_SAVES + +config TARGET_SPEAR310 + bool "Support spear310" + select BOARD_EARLY_INIT_F + select CPU_ARM926EJS + select PL011_SERIAL + imply CMD_SAVES + +config TARGET_SPEAR320 + bool "Support spear320" + select BOARD_EARLY_INIT_F + select CPU_ARM926EJS + select PL011_SERIAL + imply CMD_SAVES + +config TARGET_SPEAR600 + bool "Support spear600" + select BOARD_EARLY_INIT_F + select CPU_ARM926EJS + select PL011_SERIAL + imply CMD_SAVES + +config TARGET_STV0991 + bool "Support stv0991" + select CPU_V7A + select DM + select DM_SERIAL + select DM_SPI + select DM_SPI_FLASH + select PL01X_SERIAL + select SPI + select SPI_FLASH + imply CMD_DM + +config TARGET_X600 + bool "Support x600" + select BOARD_LATE_INIT + select CPU_ARM926EJS + select PL011_SERIAL + select SUPPORT_SPL + +config TARGET_WOODBURN + bool "Support woodburn" + select CPU_ARM1136 + +config TARGET_WOODBURN_SD + bool "Support woodburn_sd" + select CPU_ARM1136 + select SUPPORT_SPL + +config TARGET_FLEA3 + bool "Support flea3" + select CPU_ARM1136 + +config TARGET_MX35PDK + bool "Support mx35pdk" + select BOARD_LATE_INIT + select CPU_ARM1136 + +config ARCH_BCM283X + bool "Broadcom BCM283X family" + select DM + select DM_GPIO + select DM_SERIAL + select OF_CONTROL + select PL01X_SERIAL + select SERIAL_SEARCH_ALL + imply CMD_DM + imply FAT_WRITE + +config ARCH_BCM6858 + bool "Broadcom BCM6858 family" + select DM + select OF_CONTROL + imply CMD_DM + +config TARGET_VEXPRESS_CA15_TC2 + bool "Support vexpress_ca15_tc2" + select CPU_V7A + select CPU_V7_HAS_NONSEC + select CPU_V7_HAS_VIRT + select PL011_SERIAL + +config ARCH_BCMSTB + bool "Broadcom BCM7XXX family" + select CPU_V7A + select DM + select OF_CONTROL + select OF_PRIOR_STAGE + imply CMD_DM + help + This enables support for Broadcom ARM-based set-top box + chipsets, including the 7445 family of chips. + +config TARGET_VEXPRESS_CA5X2 + bool "Support vexpress_ca5x2" + select CPU_V7A + select PL011_SERIAL + +config TARGET_VEXPRESS_CA9X4 + bool "Support vexpress_ca9x4" + select CPU_V7A + select PL011_SERIAL + +config TARGET_BCM23550_W1D + bool "Support bcm23550_w1d" + select CPU_V7A + imply CRC32_VERIFY + imply FAT_WRITE + +config TARGET_BCM28155_AP + bool "Support bcm28155_ap" + select CPU_V7A + imply CRC32_VERIFY + imply FAT_WRITE + +config TARGET_BCMCYGNUS + bool "Support bcmcygnus" + select CPU_V7A + imply BCM_SF2_ETH + imply BCM_SF2_ETH_GMAC + imply CMD_HASH + imply CRC32_VERIFY + imply FAT_WRITE + imply HASH_VERIFY + imply NETDEVICES + +config TARGET_BCMNSP + bool "Support bcmnsp" + select CPU_V7A + +config TARGET_BCMNS2 + bool "Support Broadcom Northstar2" + select ARM64 + help + Support for Broadcom Northstar 2 SoCs. NS2 is a quad-core 64-bit + ARMv8 Cortex-A57 processors targeting a broad range of networking + applications + +config ARCH_EXYNOS + bool "Samsung EXYNOS" + select DM + select DM_GPIO + select DM_I2C + select DM_KEYBOARD + select DM_SERIAL + select DM_SPI + select DM_SPI_FLASH + select SPI + imply SYS_THUMB_BUILD + imply CMD_DM + imply FAT_WRITE + +config ARCH_S5PC1XX + bool "Samsung S5PC1XX" + select CPU_V7A + select DM + select DM_GPIO + select DM_I2C + select DM_SERIAL + imply CMD_DM + +config ARCH_HIGHBANK + bool "Calxeda Highbank" + select CPU_V7A + select PL011_SERIAL + +config ARCH_INTEGRATOR + bool "ARM Ltd. Integrator family" + select DM + select DM_SERIAL + select PL01X_SERIAL + imply CMD_DM + +config ARCH_KEYSTONE + bool "TI Keystone" + select CMD_POWEROFF + select CPU_V7A + select SUPPORT_SPL + select SYS_ARCH_TIMER + select SYS_THUMB_BUILD + imply CMD_MTDPARTS + imply CMD_SAVES + imply FIT + +config ARCH_K3 + bool "Texas Instruments' K3 Architecture" + select SPL + select SUPPORT_SPL + select FIT + +config ARCH_OMAP2PLUS + bool "TI OMAP2+" + select CPU_V7A + select SPL_BOARD_INIT if SPL + select SPL_STACK_R if SPL + select SUPPORT_SPL + imply FIT + +config ARCH_MESON + bool "Amlogic Meson" + imply DISTRO_DEFAULTS + help + Support for the Meson SoC family developed by Amlogic Inc., + targeted at media players and tablet computers. We currently + support the S905 (GXBaby) 64-bit SoC. + +config ARCH_MEDIATEK + bool "MediaTek SoCs" + select BINMAN + select DM + select OF_CONTROL + select SPL_DM if SPL + select SPL_LIBCOMMON_SUPPORT if SPL + select SPL_LIBGENERIC_SUPPORT if SPL + select SPL_OF_CONTROL if SPL + select SUPPORT_SPL + help + Support for the MediaTek SoCs family developed by MediaTek Inc. + Please refer to doc/README.mediatek for more information. + +config ARCH_LPC32XX + bool "NXP LPC32xx platform" + select CPU_ARM926EJS + select DM + select DM_GPIO + select DM_SERIAL + select SPL_DM if SPL + select SUPPORT_SPL + imply CMD_DM + +config ARCH_IMX8 + bool "NXP i.MX8 platform" + select ARM64 + select DM + select OF_CONTROL + +config ARCH_IMX8M + bool "NXP i.MX8M platform" + select ARM64 + select DM + select SUPPORT_SPL + imply CMD_DM + +config ARCH_MX23 + bool "NXP i.MX23 family" + select CPU_ARM926EJS + select PL011_SERIAL + select SUPPORT_SPL + +config ARCH_MX25 + bool "NXP MX25" + select CPU_ARM926EJS + imply MXC_GPIO + +config ARCH_MX28 + bool "NXP i.MX28 family" + select CPU_ARM926EJS + select PL011_SERIAL + select SUPPORT_SPL + +config ARCH_MX31 + bool "NXP i.MX31 family" + select CPU_ARM1136 + +config ARCH_MX7ULP + bool "NXP MX7ULP" + select CPU_V7A + select ROM_UNIFIED_SECTIONS + imply MXC_GPIO + +config ARCH_MX7 + bool "Freescale MX7" + select ARCH_MISC_INIT + select BOARD_EARLY_INIT_F + select CPU_V7A + select SYS_FSL_HAS_SEC if SECURE_BOOT + select SYS_FSL_SEC_COMPAT_4 + select SYS_FSL_SEC_LE + imply MXC_GPIO + +config ARCH_MX6 + bool "Freescale MX6" + select CPU_V7A + select SYS_FSL_HAS_SEC if SECURE_BOOT + select SYS_FSL_SEC_COMPAT_4 + select SYS_FSL_SEC_LE + select SYS_THUMB_BUILD if SPL + imply MXC_GPIO + +if ARCH_MX6 +config SPL_LDSCRIPT + default "arch/arm/mach-omap2/u-boot-spl.lds" +endif + +config ARCH_MX5 + bool "Freescale MX5" + select BOARD_EARLY_INIT_F + select CPU_V7A + imply MXC_GPIO + +config ARCH_OWL + bool "Actions Semi OWL SoCs" + select ARM64 + select DM + select DM_SERIAL + select OF_CONTROL + imply CMD_DM + +config ARCH_QEMU + bool "QEMU Virtual Platform" + select DM + select DM_SERIAL + select OF_CONTROL + select PL01X_SERIAL + imply CMD_DM + imply DM_RTC + imply RTC_PL031 + +config ARCH_RMOBILE + bool "Renesas ARM SoCs" + select BOARD_EARLY_INIT_F + select DM + select DM_SERIAL + imply CMD_DM + imply FAT_WRITE + imply SYS_THUMB_BUILD + imply ARCH_MISC_INIT if DISPLAY_CPUINFO + +config TARGET_S32V234EVB + bool "Support s32v234evb" + select ARM64 + select SYS_FSL_ERRATUM_ESDHC111 + +config ARCH_SNAPDRAGON + bool "Qualcomm Snapdragon SoCs" + select ARM64 + select DM + select DM_GPIO + select DM_SERIAL + select MSM_SMEM + select OF_CONTROL + select OF_SEPARATE + select SMEM + select SPMI + imply CMD_DM + +config ARCH_SOCFPGA + bool "Altera SOCFPGA family" + select ARCH_EARLY_INIT_R + select ARCH_MISC_INIT if !TARGET_SOCFPGA_ARRIA10 + select ARM64 if TARGET_SOCFPGA_STRATIX10 + select CPU_V7A if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10 + select DM + select DM_SERIAL + select ENABLE_ARM_SOC_BOOT0_HOOK if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10 + select OF_CONTROL + select SPL_DM_RESET if DM_RESET + select SPL_DM_SERIAL + select SPL_LIBCOMMON_SUPPORT + select SPL_LIBGENERIC_SUPPORT + select SPL_NAND_SUPPORT if SPL_NAND_DENALI + select SPL_OF_CONTROL + select SPL_SEPARATE_BSS if TARGET_SOCFPGA_STRATIX10 + select SPL_SERIAL_SUPPORT + select SPL_WATCHDOG_SUPPORT + select SUPPORT_SPL + select SYS_NS16550 + select SYS_THUMB_BUILD if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10 + imply CMD_DM + imply CMD_MTDPARTS + imply CRC32_VERIFY + imply DM_SPI + imply DM_SPI_FLASH + imply FAT_WRITE + imply SPL_LIBDISK_SUPPORT + imply SPL_MMC_SUPPORT + imply SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION + imply SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE + imply SPL_SPI_FLASH_SUPPORT + imply SPL_SPI_SUPPORT + +config ARCH_SUNXI + bool "Support sunxi (Allwinner) SoCs" + select BINMAN + select CMD_GPIO + select CMD_MMC if MMC + select CMD_USB if DISTRO_DEFAULTS + select DM + select DM_ETH + select DM_GPIO + select DM_KEYBOARD + select DM_SERIAL + select DM_USB if DISTRO_DEFAULTS + select OF_BOARD_SETUP + select OF_CONTROL + select OF_SEPARATE + select SPECIFY_CONSOLE_INDEX + select SPL_STACK_R if SPL + select SPL_SYS_MALLOC_SIMPLE if SPL + select SPL_SYS_THUMB_BUILD if !ARM64 + select SYS_NS16550 + select SYS_THUMB_BUILD if !ARM64 + select USB if DISTRO_DEFAULTS + select USB_KEYBOARD if DISTRO_DEFAULTS + select USB_STORAGE if DISTRO_DEFAULTS + select USE_TINY_PRINTF + imply CMD_DM + imply CMD_GPT + imply CMD_UBI if NAND + imply DISTRO_DEFAULTS + imply FAT_WRITE + imply FIT + imply OF_LIBFDT_OVERLAY + imply PRE_CONSOLE_BUFFER + imply SPL_GPIO_SUPPORT + imply SPL_LIBCOMMON_SUPPORT + imply SPL_LIBGENERIC_SUPPORT + imply SPL_MMC_SUPPORT if MMC + imply SPL_POWER_SUPPORT + imply SPL_SERIAL_SUPPORT + imply USB_GADGET + +config ARCH_VERSAL + bool "Support Xilinx Versal Platform" + select ARM64 + select CLK + select DM + select DM_SERIAL + select OF_CONTROL + +config ARCH_VF610 + bool "Freescale Vybrid" + select CPU_V7A + select SYS_FSL_ERRATUM_ESDHC111 + imply CMD_MTDPARTS + imply NAND + +config ARCH_ZYNQ + bool "Xilinx Zynq based platform" + select BOARD_EARLY_INIT_F if WDT + select CLK + select CLK_ZYNQ + select CPU_V7A + select DM + select DM_ETH if NET + select DM_MMC if MMC + select DM_SERIAL + select DM_SPI + select DM_SPI_FLASH + select DM_USB if USB + select OF_CONTROL + select SPI + select SPL_BOARD_INIT if SPL + select SPL_CLK if SPL + select SPL_DM if SPL + select SPL_OF_CONTROL if SPL + select SPL_SEPARATE_BSS if SPL + select SUPPORT_SPL + imply ARCH_EARLY_INIT_R + imply BOARD_LATE_INIT + imply CMD_CLK + imply CMD_DM + imply CMD_SPL + imply FAT_WRITE + +config ARCH_ZYNQMP_R5 + bool "Xilinx ZynqMP R5 based platform" + select CLK + select CPU_V7R + select DM + select DM_SERIAL + select OF_CONTROL + imply CMD_DM + imply DM_USB_GADGET + +config ARCH_ZYNQMP + bool "Xilinx ZynqMP based platform" + select ARM64 + select CLK + select DM + select DM_SERIAL + select DM_USB if USB + select OF_CONTROL + select SPL_BOARD_INIT if SPL + select SPL_CLK if SPL + select SPL_SEPARATE_BSS if SPL + select SUPPORT_SPL + imply BOARD_LATE_INIT + imply CMD_DM + imply FAT_WRITE + imply MP + imply DM_USB_GADGET + +config TEGRA + bool "NVIDIA Tegra" + imply DISTRO_DEFAULTS + imply FAT_WRITE + +config TARGET_VEXPRESS64_AEMV8A + bool "Support vexpress_aemv8a" + select ARM64 + select PL01X_SERIAL + +config TARGET_VEXPRESS64_BASE_FVP + bool "Support Versatile Express ARMv8a FVP BASE model" + select ARM64 + select PL01X_SERIAL + select SEMIHOSTING + +config TARGET_VEXPRESS64_BASE_FVP_DRAM + bool "Support Versatile Express ARMv8a FVP BASE model booting from DRAM" + select ARM64 + select PL01X_SERIAL + help + This target is derived from TARGET_VEXPRESS64_BASE_FVP and over-rides + the default config to allow the user to load the images directly into + DRAM using model parameters rather than by using semi-hosting to load + the files from the host filesystem. + +config TARGET_VEXPRESS64_JUNO + bool "Support Versatile Express Juno Development Platform" + select ARM64 + select PL01X_SERIAL + +config TARGET_LS2080A_EMU + bool "Support ls2080a_emu" + select ARCH_LS2080A + select ARCH_MISC_INIT + select ARM64 + select ARMV8_MULTIENTRY + help + Support for Freescale LS2080A_EMU platform + The LS2080A Development System (EMULATOR) is a pre silicon + development platform that supports the QorIQ LS2080A + Layerscape Architecture processor. + +config TARGET_LS2080A_SIMU + bool "Support ls2080a_simu" + select ARCH_LS2080A + select ARCH_MISC_INIT + select ARM64 + select ARMV8_MULTIENTRY + help + Support for Freescale LS2080A_SIMU platform + The LS2080A Development System (QDS) is a pre silicon + development platform that supports the QorIQ LS2080A + Layerscape Architecture processor. + +config TARGET_LS1088AQDS + bool "Support ls1088aqds" + select ARCH_LS1088A + select ARCH_MISC_INIT + select ARM64 + select ARMV8_MULTIENTRY + select BOARD_LATE_INIT + select SUPPORT_SPL + help + Support for NXP LS1088AQDS platform + The LS1088A Development System (QDS) is a high-performance + development platform that supports the QorIQ LS1088A + Layerscape Architecture processor. + +config TARGET_LS2080AQDS + bool "Support ls2080aqds" + select ARCH_LS2080A + select ARCH_MISC_INIT + select ARM64 + select ARMV8_MULTIENTRY + select BOARD_LATE_INIT + select SUPPORT_SPL + imply SCSI + imply SCSI_AHCI + help + Support for Freescale LS2080AQDS platform + The LS2080A Development System (QDS) is a high-performance + development platform that supports the QorIQ LS2080A + Layerscape Architecture processor. + +config TARGET_LS2080ARDB + bool "Support ls2080ardb" + select ARCH_LS2080A + select ARCH_MISC_INIT + select ARM64 + select ARMV8_MULTIENTRY + select BOARD_LATE_INIT + select SUPPORT_SPL + imply SCSI + imply SCSI_AHCI + help + Support for Freescale LS2080ARDB platform. + The LS2080A Reference design board (RDB) is a high-performance + development platform that supports the QorIQ LS2080A + Layerscape Architecture processor. + +config TARGET_LS2081ARDB + bool "Support ls2081ardb" + select ARCH_LS2080A + select ARCH_MISC_INIT + select ARM64 + select ARMV8_MULTIENTRY + select BOARD_LATE_INIT + select SUPPORT_SPL + help + Support for Freescale LS2081ARDB platform. + The LS2081A Reference design board (RDB) is a high-performance + development platform that supports the QorIQ LS2081A/LS2041A + Layerscape Architecture processor. + +config TARGET_HIKEY + bool "Support HiKey 96boards Consumer Edition Platform" + select ARM64 + select DM + select DM_GPIO + select DM_SERIAL + select OF_CONTROL + select PL01X_SERIAL + select SPECIFY_CONSOLE_INDEX + imply CMD_DM + help + Support for HiKey 96boards platform. It features a HI6220 + SoC, with 8xA53 CPU, mali450 gpu, and 1GB RAM. + +config TARGET_POPLAR + bool "Support Poplar 96boards Enterprise Edition Platform" + select ARM64 + select DM + select DM_SERIAL + select DM_USB + select OF_CONTROL + select PL01X_SERIAL + imply CMD_DM + help + Support for Poplar 96boards EE platform. It features a HI3798cv200 + SoC, with 4xA53 CPU, 1GB RAM and the high performance Mali T720 GPU + making it capable of running any commercial set-top solution based on + Linux or Android. + +config TARGET_LS1012AQDS + bool "Support ls1012aqds" + select ARCH_LS1012A + select ARM64 + select BOARD_LATE_INIT + help + Support for Freescale LS1012AQDS platform. + The LS1012A Development System (QDS) is a high-performance + development platform that supports the QorIQ LS1012A + Layerscape Architecture processor. + +config TARGET_LS1012ARDB + bool "Support ls1012ardb" + select ARCH_LS1012A + select ARM64 + select BOARD_LATE_INIT + imply SCSI + imply SCSI_AHCI + help + Support for Freescale LS1012ARDB platform. + The LS1012A Reference design board (RDB) is a high-performance + development platform that supports the QorIQ LS1012A + Layerscape Architecture processor. + +config TARGET_LS1012A2G5RDB + bool "Support ls1012a2g5rdb" + select ARCH_LS1012A + select ARM64 + select BOARD_LATE_INIT + imply SCSI + help + Support for Freescale LS1012A2G5RDB platform. + The LS1012A 2G5 Reference design board (RDB) is a high-performance + development platform that supports the QorIQ LS1012A + Layerscape Architecture processor. + +config TARGET_LS1012AFRWY + bool "Support ls1012afrwy" + select ARCH_LS1012A + select ARM64 + select BOARD_LATE_INIT + imply SCSI + imply SCSI_AHCI + help + Support for Freescale LS1012AFRWY platform. + The LS1012A FRWY board (FRWY) is a high-performance + development platform that supports the QorIQ LS1012A + Layerscape Architecture processor. + +config TARGET_LS1012AFRDM + bool "Support ls1012afrdm" + select ARCH_LS1012A + select ARM64 + help + Support for Freescale LS1012AFRDM platform. + The LS1012A Freedom board (FRDM) is a high-performance + development platform that supports the QorIQ LS1012A + Layerscape Architecture processor. + +config TARGET_LS1088ARDB + bool "Support ls1088ardb" + select ARCH_LS1088A + select ARCH_MISC_INIT + select ARM64 + select ARMV8_MULTIENTRY + select BOARD_LATE_INIT + select SUPPORT_SPL + help + Support for NXP LS1088ARDB platform. + The LS1088A Reference design board (RDB) is a high-performance + development platform that supports the QorIQ LS1088A + Layerscape Architecture processor. + +config TARGET_LS1021AQDS + bool "Support ls1021aqds" + select ARCH_LS1021A + select ARCH_SUPPORT_PSCI + select BOARD_EARLY_INIT_F + select BOARD_LATE_INIT + select CPU_V7A + select CPU_V7_HAS_NONSEC + select CPU_V7_HAS_VIRT + select LS1_DEEP_SLEEP + select SUPPORT_SPL + select SYS_FSL_DDR + imply SCSI + +config TARGET_LS1021ATWR + bool "Support ls1021atwr" + select ARCH_LS1021A + select ARCH_SUPPORT_PSCI + select BOARD_EARLY_INIT_F + select BOARD_LATE_INIT + select CPU_V7A + select CPU_V7_HAS_NONSEC + select CPU_V7_HAS_VIRT + select LS1_DEEP_SLEEP + select SUPPORT_SPL + imply SCSI + +config TARGET_LS1021AIOT + bool "Support ls1021aiot" + select ARCH_LS1021A + select ARCH_SUPPORT_PSCI + select BOARD_LATE_INIT + select CPU_V7A + select CPU_V7_HAS_NONSEC + select CPU_V7_HAS_VIRT + select SUPPORT_SPL + imply SCSI + help + Support for Freescale LS1021AIOT platform. + The LS1021A Freescale board (IOT) is a high-performance + development platform that supports the QorIQ LS1021A + Layerscape Architecture processor. + +config TARGET_LS1043AQDS + bool "Support ls1043aqds" + select ARCH_LS1043A + select ARM64 + select ARMV8_MULTIENTRY + select BOARD_EARLY_INIT_F + select BOARD_LATE_INIT + select SUPPORT_SPL + imply SCSI + help + Support for Freescale LS1043AQDS platform. + +config TARGET_LS1043ARDB + bool "Support ls1043ardb" + select ARCH_LS1043A + select ARM64 + select ARMV8_MULTIENTRY + select BOARD_EARLY_INIT_F + select BOARD_LATE_INIT + select SUPPORT_SPL + imply SCSI + help + Support for Freescale LS1043ARDB platform. + +config TARGET_LS1046AQDS + bool "Support ls1046aqds" + select ARCH_LS1046A + select ARM64 + select ARMV8_MULTIENTRY + select BOARD_EARLY_INIT_F + select BOARD_LATE_INIT + select DM_SPI_FLASH if DM_SPI + select SUPPORT_SPL + imply SCSI + help + Support for Freescale LS1046AQDS platform. + The LS1046A Development System (QDS) is a high-performance + development platform that supports the QorIQ LS1046A + Layerscape Architecture processor. + +config TARGET_LS1046ARDB + bool "Support ls1046ardb" + select ARCH_LS1046A + select ARM64 + select ARMV8_MULTIENTRY + select BOARD_EARLY_INIT_F + select BOARD_LATE_INIT + select DM_SPI_FLASH if DM_SPI + select POWER_MC34VR500 + select SUPPORT_SPL + imply SCSI + help + Support for Freescale LS1046ARDB platform. + The LS1046A Reference Design Board (RDB) is a high-performance + development platform that supports the QorIQ LS1046A + Layerscape Architecture processor. + +config TARGET_H2200 + bool "Support h2200" + select CPU_PXA + +config TARGET_ZIPITZ2 + bool "Support zipitz2" + select CPU_PXA + +config TARGET_COLIBRI_PXA270 + bool "Support colibri_pxa270" + select CPU_PXA + +config ARCH_UNIPHIER + bool "Socionext UniPhier SoCs" + select BOARD_LATE_INIT + select DM + select DM_GPIO + select DM_I2C + select DM_MMC + select DM_RESET + select DM_SERIAL + select DM_USB + select OF_BOARD_SETUP + select OF_CONTROL + select OF_LIBFDT + select PINCTRL + select SPL_BOARD_INIT if SPL + select SPL_DM if SPL + select SPL_LIBCOMMON_SUPPORT if SPL + select SPL_LIBGENERIC_SUPPORT if SPL + select SPL_OF_CONTROL if SPL + select SPL_PINCTRL if SPL + select SUPPORT_SPL + imply CMD_DM + imply DISTRO_DEFAULTS + imply FAT_WRITE + help + Support for UniPhier SoC family developed by Socionext Inc. + (formerly, System LSI Business Division of Panasonic Corporation) + +config STM32 + bool "Support STMicroelectronics STM32 MCU with cortex M" + select CPU_V7M + select DM + select DM_SERIAL + imply CMD_DM + +config ARCH_STI + bool "Support STMicrolectronics SoCs" + select BLK + select CPU_V7A + select DM + select DM_MMC + select DM_RESET + select DM_SERIAL + imply CMD_DM + help + Support for STMicroelectronics STiH407/10 SoC family. + This SoC is used on Linaro 96Board STiH410-B2260 + +config ARCH_STM32MP + bool "Support STMicroelectronics STM32MP Socs with cortex A" + select ARCH_MISC_INIT + select BOARD_LATE_INIT + select CLK + select DM + select DM_GPIO + select DM_RESET + select DM_SERIAL + select MISC + select OF_CONTROL + select OF_LIBFDT + select PINCTRL + select REGMAP + select SUPPORT_SPL + select SYSCON + select SYSRESET + select SYS_THUMB_BUILD + imply CMD_DM + help + Support for STM32MP SoC family developed by STMicroelectronics, + MPUs based on ARM cortex A core + U-BOOT is running in DDR and SPL support is the unsecure First Stage + BootLoader (FSBL) + +config ARCH_ROCKCHIP + bool "Support Rockchip SoCs" + select BLK + select DM + select DM_GPIO + select DM_I2C + select DM_MMC + select DM_PWM + select DM_REGULATOR + select DM_SERIAL + select DM_SPI + select DM_SPI_FLASH + select DM_USB if USB + select ENABLE_ARM_SOC_BOOT0_HOOK + select OF_CONTROL + select SPI + select SPL_DM if SPL + select SPL_SYS_MALLOC_SIMPLE if SPL + select SYS_MALLOC_F + select SYS_THUMB_BUILD if !ARM64 + imply ADC + imply CMD_DM + imply DISTRO_DEFAULTS + imply FAT_WRITE + imply SARADC_ROCKCHIP + imply SPL_SYSRESET + imply SYS_NS16550 + imply TPL_SYSRESET + imply USB_FUNCTION_FASTBOOT + +config TARGET_THUNDERX_88XX + bool "Support ThunderX 88xx" + select ARM64 + select OF_CONTROL + select PL01X_SERIAL + select SYS_CACHE_SHIFT_7 + +config ARCH_ASPEED + bool "Support Aspeed SoCs" + select DM + select OF_CONTROL + imply CMD_DM + +endchoice + +config TI_SECURE_DEVICE + bool "HS Device Type Support" + depends on ARCH_KEYSTONE || ARCH_OMAP2PLUS + help + If a high secure (HS) device type is being used, this config + must be set. This option impacts various aspects of the + build system (to create signed boot images that can be + authenticated) and the code. See the doc/README.ti-secure + file for further details. + +source "arch/arm/mach-aspeed/Kconfig" + +source "arch/arm/mach-at91/Kconfig" + +source "arch/arm/mach-bcm283x/Kconfig" + +source "arch/arm/mach-bcmstb/Kconfig" + +source "arch/arm/mach-davinci/Kconfig" + +source "arch/arm/mach-exynos/Kconfig" + +source "arch/arm/mach-highbank/Kconfig" + +source "arch/arm/mach-integrator/Kconfig" + +source "arch/arm/mach-k3/Kconfig" + +source "arch/arm/mach-keystone/Kconfig" + +source "arch/arm/mach-kirkwood/Kconfig" + +source "arch/arm/cpu/arm926ejs/lpc32xx/Kconfig" + +source "arch/arm/mach-mvebu/Kconfig" + +source "arch/arm/cpu/armv7/ls102xa/Kconfig" + +source "arch/arm/mach-imx/mx2/Kconfig" + +source "arch/arm/mach-imx/mx3/Kconfig" + +source "arch/arm/mach-imx/mx5/Kconfig" + +source "arch/arm/mach-imx/mx6/Kconfig" + +source "arch/arm/mach-imx/mx7/Kconfig" + +source "arch/arm/mach-imx/mx7ulp/Kconfig" + +source "arch/arm/mach-imx/imx8/Kconfig" + +source "arch/arm/mach-imx/imx8m/Kconfig" + +source "arch/arm/mach-imx/mxs/Kconfig" + +source "arch/arm/mach-omap2/Kconfig" + +source "arch/arm/cpu/armv8/fsl-layerscape/Kconfig" + +source "arch/arm/mach-orion5x/Kconfig" + +source "arch/arm/mach-owl/Kconfig" + +source "arch/arm/mach-rmobile/Kconfig" + +source "arch/arm/mach-meson/Kconfig" + +source "arch/arm/mach-mediatek/Kconfig" + +source "arch/arm/mach-qemu/Kconfig" + +source "arch/arm/mach-rockchip/Kconfig" + +source "arch/arm/mach-s5pc1xx/Kconfig" + +source "arch/arm/mach-snapdragon/Kconfig" + +source "arch/arm/mach-socfpga/Kconfig" + +source "arch/arm/mach-sti/Kconfig" + +source "arch/arm/mach-stm32/Kconfig" + +source "arch/arm/mach-stm32mp/Kconfig" + +source "arch/arm/mach-sunxi/Kconfig" + +source "arch/arm/mach-tegra/Kconfig" + +source "arch/arm/mach-uniphier/Kconfig" + +source "arch/arm/cpu/armv7/vf610/Kconfig" + +source "arch/arm/mach-zynq/Kconfig" + +source "arch/arm/mach-versal/Kconfig" + +source "arch/arm/mach-zynqmp-r5/Kconfig" + +source "arch/arm/cpu/armv7/Kconfig" + +source "arch/arm/cpu/armv8/zynqmp/Kconfig" + +source "arch/arm/cpu/armv8/Kconfig" + +source "arch/arm/mach-imx/Kconfig" + +source "board/bosch/shc/Kconfig" +source "board/CarMediaLab/flea3/Kconfig" +source "board/Marvell/aspenite/Kconfig" +source "board/Marvell/gplugd/Kconfig" +source "board/armadeus/apf27/Kconfig" +source "board/armltd/vexpress/Kconfig" +source "board/armltd/vexpress64/Kconfig" +source "board/broadcom/bcm23550_w1d/Kconfig" +source "board/broadcom/bcm28155_ap/Kconfig" +source "board/broadcom/bcm968580xref/Kconfig" +source "board/broadcom/bcmcygnus/Kconfig" +source "board/broadcom/bcmnsp/Kconfig" +source "board/broadcom/bcmns2/Kconfig" +source "board/cavium/thunderx/Kconfig" +source "board/cirrus/edb93xx/Kconfig" +source "board/eets/pdu001/Kconfig" +source "board/emulation/qemu-arm/Kconfig" +source "board/freescale/ls2080a/Kconfig" +source "board/freescale/ls2080aqds/Kconfig" +source "board/freescale/ls2080ardb/Kconfig" +source "board/freescale/ls1088a/Kconfig" +source "board/freescale/ls1021aqds/Kconfig" +source "board/freescale/ls1043aqds/Kconfig" +source "board/freescale/ls1021atwr/Kconfig" +source "board/freescale/ls1021aiot/Kconfig" +source "board/freescale/ls1046aqds/Kconfig" +source "board/freescale/ls1043ardb/Kconfig" +source "board/freescale/ls1046ardb/Kconfig" +source "board/freescale/ls1012aqds/Kconfig" +source "board/freescale/ls1012ardb/Kconfig" +source "board/freescale/ls1012afrdm/Kconfig" +source "board/freescale/mx35pdk/Kconfig" +source "board/freescale/s32v234evb/Kconfig" +source "board/grinn/chiliboard/Kconfig" +source "board/gumstix/pepper/Kconfig" +source "board/h2200/Kconfig" +source "board/hisilicon/hikey/Kconfig" +source "board/hisilicon/poplar/Kconfig" +source "board/isee/igep003x/Kconfig" +source "board/phytec/pcm051/Kconfig" +source "board/silica/pengwyn/Kconfig" +source "board/spear/spear300/Kconfig" +source "board/spear/spear310/Kconfig" +source "board/spear/spear320/Kconfig" +source "board/spear/spear600/Kconfig" +source "board/spear/x600/Kconfig" +source "board/st/stv0991/Kconfig" +source "board/tcl/sl50/Kconfig" +source "board/ucRobotics/bubblegum_96/Kconfig" +source "board/birdland/bav335x/Kconfig" +source "board/toradex/colibri_pxa270/Kconfig" +source "board/vscom/baltos/Kconfig" +source "board/woodburn/Kconfig" +source "board/xilinx/Kconfig" +source "board/xilinx/zynq/Kconfig" +source "board/xilinx/zynqmp/Kconfig" +source "board/zipitz2/Kconfig" + +source "arch/arm/Kconfig.debug" + +endmenu + +config SPL_LDSCRIPT + default "arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds" if (ARCH_MX23 || ARCH_MX28) && !SPL_FRAMEWORK + default "arch/arm/cpu/arm1136/u-boot-spl.lds" if CPU_ARM1136 + default "arch/arm/cpu/armv8/u-boot-spl.lds" if ARM64 + +
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug new file mode 100644 index 0000000..624bcf4 --- /dev/null +++ b/arch/arm/Kconfig.debug
@@ -0,0 +1,64 @@ +menu "ARM debug" + +config DEBUG_LL + bool "Low-level debugging functions" + depends on !ARM64 + help + Say Y here to include definitions of printascii, printch, printhex + in U-Boot. This is helpful if you are debugging code that + executes before the console is initialized. + +choice + prompt "Low-level debugging port" + depends on DEBUG_LL + + config DEBUG_LL_UART_8250 + bool "Low-level debugging via 8250 UART" + help + Say Y here if you wish the debug print routes to direct + their output to an 8250 UART. You can use this option + to provide the parameters for the 8250 UART rather than + selecting one of the platform specific options above if + you know the parameters for the port. + + This option is preferred over the platform specific + options; the platform specific options are deprecated + and will be soon removed. + +endchoice + +config DEBUG_LL_INCLUDE + string + depends on DEBUG_LL + default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250 + default "mach/debug-macro.S" + +# Compatibility options for 8250 +config DEBUG_UART_8250 + bool + +config DEBUG_UART_PHYS + hex "Physical base address of debug UART" + depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250 + +# This is not used in U-Boot +config DEBUG_UART_VIRT + hex + default DEBUG_UART_PHYS + depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250 + +config DEBUG_UART_8250_SHIFT + int "Register offset shift for the 8250 debug UART" + depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250 + default 2 + +config DEBUG_UART_8250_WORD + bool "Use 32-bit accesses for 8250 UART" + depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250 + depends on DEBUG_UART_8250_SHIFT >= 2 + +config DEBUG_UART_8250_FLOW_CONTROL + bool "Enable flow control for 8250 UART" + depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250 + +endmenu
diff --git a/arch/arm/Makefile b/arch/arm/Makefile new file mode 100644 index 0000000..87d9d4b --- /dev/null +++ b/arch/arm/Makefile
@@ -0,0 +1,120 @@ +# SPDX-License-Identifier: GPL-2.0+ + +ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TEGRA),yy) +CONFIG_CPU_V7A= +CONFIG_CPU_ARM720T=y +endif + +# This selects which instruction set is used. +arch-$(CONFIG_CPU_ARM720T) =-march=armv4 +arch-$(CONFIG_CPU_ARM920T) =-march=armv4t +arch-$(CONFIG_CPU_ARM926EJS) =-march=armv5te +arch-$(CONFIG_CPU_ARM946ES) =-march=armv5te +arch-$(CONFIG_CPU_SA1100) =-march=armv4 +arch-$(CONFIG_CPU_PXA) = +arch-$(CONFIG_CPU_ARM1136) =-march=armv5 +arch-$(CONFIG_CPU_ARM1176) =-march=armv5t +arch-$(CONFIG_CPU_V7A) =$(call cc-option, -march=armv7-a, \ + $(call cc-option, -march=armv7)) +arch-$(CONFIG_CPU_V7M) =-march=armv7-m +arch-$(CONFIG_CPU_V7R) =-march=armv7-r +arch-$(CONFIG_ARM64) =-march=armv8-a + +# On Tegra systems we must build SPL for the armv4 core on the device +# but otherwise we can use the value in CONFIG_SYS_ARM_ARCH +ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TEGRA),yy) +arch-y += -D__LINUX_ARM_ARCH__=4 +else +arch-y += -D__LINUX_ARM_ARCH__=$(CONFIG_SYS_ARM_ARCH) +endif + +# Evaluate arch cc-option calls now +arch-y := $(arch-y) + +# This selects how we optimise for the processor. +tune-$(CONFIG_CPU_ARM720T) =-mtune=arm7tdmi +tune-$(CONFIG_CPU_ARM920T) = +tune-$(CONFIG_CPU_ARM926EJS) = +tune-$(CONFIG_CPU_ARM946ES) = +tune-$(CONFIG_CPU_SA1100) =-mtune=strongarm1100 +tune-$(CONFIG_CPU_PXA) =-mcpu=xscale +tune-$(CONFIG_CPU_ARM1136) = +tune-$(CONFIG_CPU_ARM1176) = +tune-$(CONFIG_CPU_V7A) =-mtune=generic-armv7-a +tune-$(CONFIG_CPU_V7R) = +tune-$(CONFIG_ARM64) = + +# Evaluate tune cc-option calls now +tune-y := $(tune-y) + +PLATFORM_CPPFLAGS += $(arch-y) $(tune-y) + +# Machine directory name. This list is sorted alphanumerically +# by CONFIG_* macro name. +machine-$(CONFIG_ARCH_ASPEED) += aspeed +machine-$(CONFIG_ARCH_AT91) += at91 +machine-$(CONFIG_ARCH_BCM283X) += bcm283x +machine-$(CONFIG_ARCH_BCMSTB) += bcmstb +machine-$(CONFIG_ARCH_DAVINCI) += davinci +machine-$(CONFIG_ARCH_EXYNOS) += exynos +machine-$(CONFIG_ARCH_HIGHBANK) += highbank +machine-$(CONFIG_ARCH_K3) += k3 +machine-$(CONFIG_ARCH_KEYSTONE) += keystone +# TODO: rename CONFIG_KIRKWOOD -> CONFIG_ARCH_KIRKWOOD +machine-$(CONFIG_KIRKWOOD) += kirkwood +machine-$(CONFIG_ARCH_MEDIATEK) += mediatek +machine-$(CONFIG_ARCH_MESON) += meson +machine-$(CONFIG_ARCH_MVEBU) += mvebu +# TODO: rename CONFIG_TEGRA -> CONFIG_ARCH_TEGRA +# TODO: rename CONFIG_ORION5X -> CONFIG_ARCH_ORION5X +machine-$(CONFIG_ORION5X) += orion5x +machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2 +machine-$(CONFIG_ARCH_OWL) += owl +machine-$(CONFIG_ARCH_S5PC1XX) += s5pc1xx +machine-$(CONFIG_ARCH_SUNXI) += sunxi +machine-$(CONFIG_ARCH_SNAPDRAGON) += snapdragon +machine-$(CONFIG_ARCH_SOCFPGA) += socfpga +machine-$(CONFIG_ARCH_RMOBILE) += rmobile +machine-$(CONFIG_ARCH_ROCKCHIP) += rockchip +machine-$(CONFIG_STM32) += stm32 +machine-$(CONFIG_ARCH_STM32MP) += stm32mp +machine-$(CONFIG_TEGRA) += tegra +machine-$(CONFIG_ARCH_UNIPHIER) += uniphier +machine-$(CONFIG_ARCH_ZYNQ) += zynq +machine-$(CONFIG_ARCH_VERSAL) += versal +machine-$(CONFIG_ARCH_ZYNQMP_R5) += zynqmp-r5 + +machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y)) + +PLATFORM_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs)) + +libs-y += $(machdirs) + +head-y := arch/arm/cpu/$(CPU)/start.o + +ifeq ($(CONFIG_SPL_BUILD),y) +ifneq ($(CONFIG_SPL_START_S_PATH),) +head-y := $(CONFIG_SPL_START_S_PATH:"%"=%)/start.o +endif +endif + +libs-y += arch/arm/cpu/$(CPU)/ +libs-y += arch/arm/cpu/ +libs-y += arch/arm/lib/ + +ifeq ($(CONFIG_SPL_BUILD),y) +ifneq (,$(CONFIG_MX23)$(CONFIG_MX28)$(CONFIG_MX35)$(filter $(SOC), mx25 mx5 mx6 mx7 mx35 imx8m)) +libs-y += arch/arm/mach-imx/ +endif +else +ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx7 mx7ulp mx31 mx35 mxs imx8m imx8 vf610)) +libs-y += arch/arm/mach-imx/ +endif +endif + +ifneq (,$(filter $(SOC), kirkwood)) +libs-y += arch/arm/mach-mvebu/ +endif + +# deprecated +-include $(machdirs)/config.mk
diff --git a/arch/arm/config.mk b/arch/arm/config.mk new file mode 100644 index 0000000..f256031 --- /dev/null +++ b/arch/arm/config.mk
@@ -0,0 +1,173 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +ifndef CONFIG_STANDALONE_LOAD_ADDR +ifneq ($(CONFIG_ARCH_OMAP2PLUS),) +CONFIG_STANDALONE_LOAD_ADDR = 0x80300000 +else +CONFIG_STANDALONE_LOAD_ADDR = 0xc100000 +endif +endif + +CFLAGS_NON_EFI := -fno-pic -ffixed-r9 -ffunction-sections -fdata-sections +CFLAGS_EFI := -fpic -fshort-wchar + +LDFLAGS_FINAL += --gc-sections +PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections \ + -fno-common -ffixed-r9 +PLATFORM_RELFLAGS += $(call cc-option, -msoft-float) \ + $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) + +# LLVM support +LLVM_RELFLAGS := $(call cc-option,-mllvm,) \ + $(call cc-option,-mno-movt,) +PLATFORM_RELFLAGS += $(LLVM_RELFLAGS) + +PLATFORM_CPPFLAGS += -D__ARM__ + +ifdef CONFIG_ARM64 +PLATFORM_ELFFLAGS += -B aarch64 -O elf64-littleaarch64 +else +PLATFORM_ELFFLAGS += -B arm -O elf32-littlearm +endif + +# Choose between ARM/Thumb instruction sets +ifeq ($(CONFIG_$(SPL_)SYS_THUMB_BUILD),y) +AFLAGS_IMPLICIT_IT := $(call as-option,-Wa$(comma)-mimplicit-it=always) +PF_CPPFLAGS_ARM := $(AFLAGS_IMPLICIT_IT) \ + $(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 +ifeq ($(CONFIG_$(SPL_)SYS_THUMB_BUILD),y) +archprepare: checkthumb checkgcc6 + +checkthumb: + @if test "$(call cc-name)" = "gcc" -a \ + "$(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 +else +archprepare: checkgcc6 +endif + +checkgcc6: + @if test "$(call cc-name)" = "gcc" -a \ + "$(call cc-version)" -lt "0600"; then \ + echo '*** Your GCC is older than 6.0 and is not supported'; \ + false; \ + fi + + +# 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 +# - with ELDK 4.1 (gcc 4.x, no EABI), use: +# -mabi=apcs-gnu +# - with ELDK 3.1 (gcc 3.x), use: +# -mapcs-32 +PF_CPPFLAGS_ABI := $(call cc-option,\ + -mabi=aapcs-linux,\ + $(call cc-option,\ + -mapcs-32,\ + $(call cc-option,\ + -mabi=apcs-gnu,\ + )\ + )\ + ) +PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARM) $(PF_CPPFLAGS_ABI) + +# For EABI, make sure to provide raise() +ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS))) +# This file is parsed many times, so the string may get added multiple +# times. Also, the prefix needs to be different based on whether +# CONFIG_SPL_BUILD is defined or not. 'filter-out' the existing entry +# before adding the correct one. +PLATFORM_LIBS := arch/arm/lib/eabi_compat.o \ + $(filter-out arch/arm/lib/eabi_compat.o, $(PLATFORM_LIBS)) +endif + +# needed for relocation +LDFLAGS_u-boot += -pie + +# +# FIXME: binutils versions < 2.22 have a bug in the assembler where +# branches to weak symbols can be incorrectly optimized in thumb mode +# to a short branch (b.n instruction) that won't reach when the symbol +# gets preempted +# +# http://sourceware.org/bugzilla/show_bug.cgi?id=12532 +# +ifeq ($(CONFIG_$(SPL_)SYS_THUMB_BUILD),y) +ifeq ($(GAS_BUG_12532),) +export GAS_BUG_12532:=$(shell if [ $(call binutils-version) -lt 0222 ] ; \ + then echo y; else echo n; fi) +endif +ifeq ($(GAS_BUG_12532),y) +PLATFORM_RELFLAGS += -fno-optimize-sibling-calls +endif +endif + +ifneq ($(CONFIG_SPL_BUILD),y) +# Check that only R_ARM_RELATIVE relocations are generated. +ALL-y += checkarmreloc +# The movt / movw can hardcode 16 bit parts of the addresses in the +# instruction. Relocation is not supported for that case, so disable +# such usage by requiring word relocations. +PLATFORM_CPPFLAGS += $(call cc-option, -mword-relocations) +PLATFORM_CPPFLAGS += $(call cc-option, -fno-pic) +endif + +# limit ourselves to the sections we want in the .bin. +ifdef CONFIG_ARM64 +OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .data \ + -j .u_boot_list -j .rela.dyn -j .got -j .got.plt \ + -j .binman_sym_table -j .text_rest +else +OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .hash \ + -j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn \ + -j .binman_sym_table -j .text_rest +endif + +# if a dtb section exists we always have to include it +# there are only two cases where it is generated +# 1) OF_EMBEDED is turned on +# 2) unit tests include device tree blobs +OBJCOPYFLAGS += -j .dtb.init.rodata + +ifdef CONFIG_EFI_LOADER +OBJCOPYFLAGS += -j .efi_runtime -j .efi_runtime_rel +endif + +ifneq ($(CONFIG_IMX_CONFIG),) +ifdef CONFIG_SPL +ifndef CONFIG_SPL_BUILD +ALL-y += SPL +endif +else +ifeq ($(CONFIG_OF_SEPARATE),y) +ALL-y += u-boot-dtb.imx +else +ALL-y += u-boot.imx +endif +endif +ifneq ($(CONFIG_VF610),) +ALL-y += u-boot.vyb +endif +endif + +EFI_LDS := elf_arm_efi.lds +EFI_CRT0 := crt0_arm_efi.o +EFI_RELOC := reloc_arm_efi.o
diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile new file mode 100644 index 0000000..a0e1c2a --- /dev/null +++ b/arch/arm/cpu/Makefile
@@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj- += dummy.o
diff --git a/arch/arm/cpu/arm11/Makefile b/arch/arm/cpu/arm11/Makefile new file mode 100644 index 0000000..5d721fc --- /dev/null +++ b/arch/arm/cpu/arm11/Makefile
@@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +obj-y = cpu.o
diff --git a/arch/arm/cpu/arm11/cpu.c b/arch/arm/cpu/arm11/cpu.c new file mode 100644 index 0000000..41feeef --- /dev/null +++ b/arch/arm/cpu/arm11/cpu.c
@@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2004 Texas Insturments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> + +static void cache_flush(void); + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + disable_interrupts (); + + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + /* flush I/D-cache */ + cache_flush(); + + return 0; +} + +static void cache_flush(void) +{ + unsigned long i = 0; + /* clean entire data cache */ + asm volatile("mcr p15, 0, %0, c7, c10, 0" : : "r" (i)); + /* invalidate both caches and flush btb */ + asm volatile("mcr p15, 0, %0, c7, c7, 0" : : "r" (i)); + /* mem barrier to sync things */ + asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (i)); +} + +#ifndef CONFIG_SYS_DCACHE_OFF +void invalidate_dcache_all(void) +{ + asm volatile("mcr p15, 0, %0, c7, c6, 0" : : "r" (0)); +} + +void flush_dcache_all(void) +{ + asm volatile("mcr p15, 0, %0, c7, c10, 0" : : "r" (0)); + asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ + if (!check_cache_range(start, stop)) + return; + + while (start < stop) { + asm volatile("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)); + start += CONFIG_SYS_CACHELINE_SIZE; + } +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ + if (!check_cache_range(start, stop)) + return; + + while (start < stop) { + asm volatile("mcr p15, 0, %0, c7, c14, 1" : : "r" (start)); + start += CONFIG_SYS_CACHELINE_SIZE; + } + + asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); +} + +#else /* #ifndef CONFIG_SYS_DCACHE_OFF */ +void invalidate_dcache_all(void) +{ +} + +void flush_dcache_all(void) +{ +} +#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ + +#if !defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF) +void enable_caches(void) +{ +#ifndef CONFIG_SYS_ICACHE_OFF + icache_enable(); +#endif +#ifndef CONFIG_SYS_DCACHE_OFF + dcache_enable(); +#endif +} +#endif
diff --git a/arch/arm/cpu/arm1136/Makefile b/arch/arm/cpu/arm1136/Makefile new file mode 100644 index 0000000..24c3386 --- /dev/null +++ b/arch/arm/cpu/arm1136/Makefile
@@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-y = start.o + +obj-y += ../arm11/ +obj-$(CONFIG_MX31) += mx31/ +obj-$(CONFIG_MX35) += mx35/
diff --git a/arch/arm/cpu/arm1136/mx31/Makefile b/arch/arm/cpu/arm1136/mx31/Makefile new file mode 100644 index 0000000..67799ee --- /dev/null +++ b/arch/arm/cpu/arm1136/mx31/Makefile
@@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +obj-y += generic.o +obj-y += timer.o +obj-y += devices.o +obj-y += relocate.o
diff --git a/arch/arm/cpu/arm1136/mx31/devices.c b/arch/arm/cpu/arm1136/mx31/devices.c new file mode 100644 index 0000000..9997e8f --- /dev/null +++ b/arch/arm/cpu/arm1136/mx31/devices.c
@@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * + * (C) Copyright 2009 Magnus Lilja <lilja.magnus@gmail.com> + * + * (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> + */ + +#include <common.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> + +void mx31_uart1_hw_init(void) +{ + /* setup pins for UART1 */ + mx31_gpio_mux(MUX_RXD1__UART1_RXD_MUX); + mx31_gpio_mux(MUX_TXD1__UART1_TXD_MUX); + mx31_gpio_mux(MUX_RTS1__UART1_RTS_B); + mx31_gpio_mux(MUX_CTS1__UART1_CTS_B); +} + +void mx31_uart2_hw_init(void) +{ + /* setup pins for UART2 */ + mx31_gpio_mux(MUX_RXD2__UART2_RXD_MUX); + mx31_gpio_mux(MUX_TXD2__UART2_TXD_MUX); + mx31_gpio_mux(MUX_RTS2__UART2_RTS_B); + mx31_gpio_mux(MUX_CTS2__UART2_CTS_B); +} + +#ifdef CONFIG_MXC_SPI +/* + * Note: putting several spi setups here makes no sense as they may differ + * at board level (physical pin SS0 of CSPI2 may aswell be used as SS0 of CSPI3) + */ +void mx31_spi2_hw_init(void) +{ + /* SPI2 */ + mx31_gpio_mux(MUX_CSPI2_SS2__CSPI2_SS2_B); + mx31_gpio_mux(MUX_CSPI2_SCLK__CSPI2_CLK); + mx31_gpio_mux(MUX_CSPI2_SPI_RDY__CSPI2_DATAREADY_B); + mx31_gpio_mux(MUX_CSPI2_MOSI__CSPI2_MOSI); + mx31_gpio_mux(MUX_CSPI2_MISO__CSPI2_MISO); + mx31_gpio_mux(MUX_CSPI2_SS0__CSPI2_SS0_B); + mx31_gpio_mux(MUX_CSPI2_SS1__CSPI2_SS1_B); + + /* start SPI2 clock */ + __REG(CCM_CGR2) = __REG(CCM_CGR2) | (3 << 4); +} +#endif
diff --git a/arch/arm/cpu/arm1136/mx31/generic.c b/arch/arm/cpu/arm1136/mx31/generic.c new file mode 100644 index 0000000..3f6af6f --- /dev/null +++ b/arch/arm/cpu/arm1136/mx31/generic.c
@@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + */ + +#include <common.h> +#include <div64.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> + +static u32 mx31_decode_pll(u32 reg, u32 infreq) +{ + u32 mfi = GET_PLL_MFI(reg); + s32 mfn = GET_PLL_MFN(reg); + u32 mfd = GET_PLL_MFD(reg); + u32 pd = GET_PLL_PD(reg); + + mfi = mfi <= 5 ? 5 : mfi; + mfn = mfn >= 512 ? mfn - 1024 : mfn; + mfd += 1; + pd += 1; + + return lldiv(2 * (u64)infreq * (mfi * mfd + mfn), + mfd * pd); +} + +static u32 mx31_get_mpl_dpdgck_clk(void) +{ + u32 infreq; + + if ((readl(CCM_CCMR) & CCMR_PRCS_MASK) == CCMR_FPM) + infreq = MXC_CLK32 * 1024; + else + infreq = MXC_HCLK; + + return mx31_decode_pll(readl(CCM_MPCTL), infreq); +} + +static u32 mx31_get_mcu_main_clk(void) +{ + /* For now we assume mpl_dpdgck_clk == mcu_main_clk + * which should be correct for most boards + */ + return mx31_get_mpl_dpdgck_clk(); +} + +static u32 mx31_get_ipg_clk(void) +{ + u32 freq = mx31_get_mcu_main_clk(); + u32 pdr0 = readl(CCM_PDR0); + + freq /= GET_PDR0_MAX_PODF(pdr0) + 1; + freq /= GET_PDR0_IPG_PODF(pdr0) + 1; + + return freq; +} + +/* hsp is the clock for the ipu */ +static u32 mx31_get_hsp_clk(void) +{ + u32 freq = mx31_get_mcu_main_clk(); + u32 pdr0 = readl(CCM_PDR0); + + freq /= GET_PDR0_HSP_PODF(pdr0) + 1; + + return freq; +} + +void mx31_dump_clocks(void) +{ + u32 cpufreq = mx31_get_mcu_main_clk(); + printf("mx31 cpu clock: %dMHz\n", cpufreq / 1000000); + printf("ipg clock : %dHz\n", mx31_get_ipg_clk()); + printf("hsp clock : %dHz\n", mx31_get_hsp_clk()); +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return mx31_get_mcu_main_clk(); + case MXC_IPG_CLK: + case MXC_IPG_PERCLK: + case MXC_CSPI_CLK: + case MXC_UART_CLK: + case MXC_ESDHC_CLK: + case MXC_I2C_CLK: + return mx31_get_ipg_clk(); + case MXC_IPU_CLK: + return mx31_get_hsp_clk(); + } + return -1; +} + +u32 imx_get_uartclk(void) +{ + return mxc_get_clock(MXC_UART_CLK); +} + +void mx31_gpio_mux(unsigned long mode) +{ + unsigned long reg, shift, tmp; + + reg = IOMUXC_BASE + (mode & 0x1fc); + shift = (~mode & 0x3) * 8; + + tmp = readl(reg); + tmp &= ~(0xff << shift); + tmp |= ((mode >> IOMUX_MODE_POS) & 0xff) << shift; + writel(tmp, reg); +} + +void mx31_set_pad(enum iomux_pins pin, u32 config) +{ + u32 field, l, reg; + + pin &= IOMUX_PADNUM_MASK; + reg = (IOMUXC_BASE + 0x154) + (pin + 2) / 3 * 4; + field = (pin + 2) % 3; + + l = readl(reg); + l &= ~(0x1ff << (field * 10)); + l |= config << (field * 10); + writel(l, reg); + +} + +void mx31_set_gpr(enum iomux_gp_func gp, char en) +{ + u32 l; + struct iomuxc_regs *iomuxc = (struct iomuxc_regs *)IOMUXC_BASE; + + l = readl(&iomuxc->gpr); + if (en) + l |= gp; + else + l &= ~gp; + + writel(l, &iomuxc->gpr); +} + +void mxc_setup_weimcs(int cs, const struct mxc_weimcs *weimcs) +{ + struct mx31_weim *weim = (struct mx31_weim *) WEIM_BASE; + struct mx31_weim_cscr *cscr = &weim->cscr[cs]; + + writel(weimcs->upper, &cscr->upper); + writel(weimcs->lower, &cscr->lower); + writel(weimcs->additional, &cscr->additional); +} + +struct mx3_cpu_type mx31_cpu_type[] = { + { .srev = 0x00, .v = 0x10 }, + { .srev = 0x10, .v = 0x11 }, + { .srev = 0x11, .v = 0x11 }, + { .srev = 0x12, .v = 0x1F }, + { .srev = 0x13, .v = 0x1F }, + { .srev = 0x14, .v = 0x12 }, + { .srev = 0x15, .v = 0x12 }, + { .srev = 0x28, .v = 0x20 }, + { .srev = 0x29, .v = 0x20 }, +}; + +u32 get_cpu_rev(void) +{ + u32 i, srev; + + /* read SREV register from IIM module */ + struct iim_regs *iim = (struct iim_regs *)MX31_IIM_BASE_ADDR; + srev = readl(&iim->iim_srev); + + for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++) + if (srev == mx31_cpu_type[i].srev) + return mx31_cpu_type[i].v | (MXC_CPU_MX31 << 12); + + return srev | 0x8000; +} + +static char *get_reset_cause(void) +{ + /* read RCSR register from CCM module */ + struct clock_control_regs *ccm = + (struct clock_control_regs *)CCM_BASE; + + u32 cause = readl(&ccm->rcsr) & 0x07; + + switch (cause) { + case 0x0000: + return "POR"; + case 0x0001: + return "RST"; + case 0x0002: + return "WDOG"; + case 0x0006: + return "JTAG"; + case 0x0007: + return "ARM11P power gating"; + default: + return "unknown reset"; + } +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + u32 srev = get_cpu_rev(); + + printf("CPU: Freescale i.MX31 rev %d.%d%s at %d MHz.\n", + (srev & 0xF0) >> 4, (srev & 0x0F), + ((srev & 0x8000) ? " unknown" : ""), + mx31_get_mcu_main_clk() / 1000000); + printf("Reset cause: %s\n", get_reset_cause()); + return 0; +} +#endif
diff --git a/arch/arm/cpu/arm1136/mx31/relocate.S b/arch/arm/cpu/arm1136/mx31/relocate.S new file mode 100644 index 0000000..225e528 --- /dev/null +++ b/arch/arm/cpu/arm1136/mx31/relocate.S
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * relocate - i.MX31-specific vector relocation + * + * Copyright (c) 2013 Albert ARIBAUD <albert.u.boot@aribaud.net> + */ + +#include <linux/linkage.h> + +/* + * The i.MX31 SoC is very specific with respect to exceptions: it + * does not provide RAM at the high vectors address (0xFFFF0000), + * thus only the low address (0x00000000) is useable; but that is + * in ROM, so let's avoid relocating the vectors. + */ + .section .text.relocate_vectors,"ax",%progbits + +ENTRY(relocate_vectors) + + bx lr + +ENDPROC(relocate_vectors)
diff --git a/arch/arm/cpu/arm1136/mx31/timer.c b/arch/arm/cpu/arm1136/mx31/timer.c new file mode 100644 index 0000000..3d07ee6 --- /dev/null +++ b/arch/arm/cpu/arm1136/mx31/timer.c
@@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + */ + +#include <common.h> +#include <asm/arch/imx-regs.h> +#include <asm/io.h> + +#define TIMER_BASE 0x53f90000 /* General purpose timer 1 */ + +/* General purpose timers registers */ +#define GPTCR __REG(TIMER_BASE) /* Control register */ +#define GPTPR __REG(TIMER_BASE + 0x4) /* Prescaler register */ +#define GPTSR __REG(TIMER_BASE + 0x8) /* Status register */ +#define GPTCNT __REG(TIMER_BASE + 0x24) /* Counter register */ + +/* General purpose timers bitfields */ +#define GPTCR_SWR (1 << 15) /* Software reset */ +#define GPTCR_FRR (1 << 9) /* Freerun / restart */ +#define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source */ +#define GPTCR_TEN 1 /* Timer enable */ + +/* The 32768Hz 32-bit timer overruns in 131072 seconds */ +int timer_init(void) +{ + int i; + + /* setup GP Timer 1 */ + GPTCR = GPTCR_SWR; + for (i = 0; i < 100; i++) + GPTCR = 0; /* We have no udelay by now */ + GPTPR = 0; /* 32Khz */ + /* Freerun Mode, PERCLK1 input */ + GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; + + return 0; +} + +unsigned long timer_read_counter(void) +{ + return GPTCNT; +}
diff --git a/arch/arm/cpu/arm1136/mx35/Makefile b/arch/arm/cpu/arm1136/mx35/Makefile new file mode 100644 index 0000000..36568f9 --- /dev/null +++ b/arch/arm/cpu/arm1136/mx35/Makefile
@@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2008-2009 Freescale Semiconductor, Inc. + +obj-y += generic.o +obj-y += timer.o +obj-y += mx35_sdram.o +obj-y += relocate.o
diff --git a/arch/arm/cpu/arm1136/mx35/generic.c b/arch/arm/cpu/arm1136/mx35/generic.c new file mode 100644 index 0000000..cbc4364 --- /dev/null +++ b/arch/arm/cpu/arm1136/mx35/generic.c
@@ -0,0 +1,525 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (C) Copyright 2008-2010 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/crm_regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> +#endif +#include <netdev.h> +#include <spl.h> + +#define CLK_CODE(arm, ahb, sel) (((arm) << 16) + ((ahb) << 8) + (sel)) +#define CLK_CODE_ARM(c) (((c) >> 16) & 0xFF) +#define CLK_CODE_AHB(c) (((c) >> 8) & 0xFF) +#define CLK_CODE_PATH(c) ((c) & 0xFF) + +#define CCM_GET_DIVIDER(x, m, o) (((x) & (m)) >> (o)) + +#ifdef CONFIG_FSL_ESDHC +DECLARE_GLOBAL_DATA_PTR; +#endif + +static int g_clk_mux_auto[8] = { + CLK_CODE(1, 3, 0), CLK_CODE(1, 2, 1), CLK_CODE(2, 1, 1), -1, + CLK_CODE(1, 6, 0), CLK_CODE(1, 4, 1), CLK_CODE(2, 2, 1), -1, +}; + +static int g_clk_mux_consumer[16] = { + CLK_CODE(1, 4, 0), CLK_CODE(1, 3, 1), CLK_CODE(1, 3, 1), -1, + -1, -1, CLK_CODE(4, 1, 0), CLK_CODE(1, 5, 0), + CLK_CODE(1, 8, 1), CLK_CODE(1, 6, 1), CLK_CODE(2, 4, 0), -1, + -1, -1, CLK_CODE(4, 2, 0), -1, +}; + +static int hsp_div_table[3][16] = { + {4, 3, 2, -1, -1, -1, 1, 5, 4, 3, 2, -1, -1, -1, 1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, 8, 6, 4, -1, -1, -1, 2, -1}, + {3, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1}, +}; + +u32 get_cpu_rev(void) +{ + int reg; + struct iim_regs *iim = + (struct iim_regs *)IIM_BASE_ADDR; + reg = readl(&iim->iim_srev); + if (!reg) { + reg = readw(ROMPATCH_REV); + reg <<= 4; + } else { + reg += CHIP_REV_1_0; + } + + return 0x35000 + (reg & 0xFF); +} + +static u32 get_arm_div(u32 pdr0, u32 *fi, u32 *fd) +{ + int *pclk_mux; + if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { + pclk_mux = g_clk_mux_consumer + + ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> + MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); + } else { + pclk_mux = g_clk_mux_auto + + ((pdr0 & MXC_CCM_PDR0_AUTO_MUX_DIV_MASK) >> + MXC_CCM_PDR0_AUTO_MUX_DIV_OFFSET); + } + + if ((*pclk_mux) == -1) + return -1; + + if (fi && fd) { + if (!CLK_CODE_PATH(*pclk_mux)) { + *fi = *fd = 1; + return CLK_CODE_ARM(*pclk_mux); + } + if (pdr0 & MXC_CCM_PDR0_AUTO_CON) { + *fi = 3; + *fd = 4; + } else { + *fi = 2; + *fd = 3; + } + } + return CLK_CODE_ARM(*pclk_mux); +} + +static int get_ahb_div(u32 pdr0) +{ + int *pclk_mux; + + pclk_mux = g_clk_mux_consumer + + ((pdr0 & MXC_CCM_PDR0_CON_MUX_DIV_MASK) >> + MXC_CCM_PDR0_CON_MUX_DIV_OFFSET); + + if ((*pclk_mux) == -1) + return -1; + + return CLK_CODE_AHB(*pclk_mux); +} + +static u32 decode_pll(u32 reg, u32 infreq) +{ + u32 mfi = (reg >> 10) & 0xf; + s32 mfn = reg & 0x3ff; + u32 mfd = (reg >> 16) & 0x3ff; + u32 pd = (reg >> 26) & 0xf; + + mfi = mfi <= 5 ? 5 : mfi; + mfn = mfn >= 512 ? mfn - 1024 : mfn; + mfd += 1; + pd += 1; + + return lldiv(2 * (u64)infreq * (mfi * mfd + mfn), + mfd * pd); +} + +static u32 get_mcu_main_clk(void) +{ + u32 arm_div = 0, fi = 0, fd = 0; + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + arm_div = get_arm_div(readl(&ccm->pdr0), &fi, &fd); + fi *= decode_pll(readl(&ccm->mpctl), MXC_HCLK); + return fi / (arm_div * fd); +} + +static u32 get_ipg_clk(void) +{ + u32 freq = get_mcu_main_clk(); + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + u32 pdr0 = readl(&ccm->pdr0); + + return freq / (get_ahb_div(pdr0) * 2); +} + +static u32 get_ipg_per_clk(void) +{ + u32 freq = get_mcu_main_clk(); + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + u32 pdr0 = readl(&ccm->pdr0); + u32 pdr4 = readl(&ccm->pdr4); + u32 div; + if (pdr0 & MXC_CCM_PDR0_PER_SEL) { + div = CCM_GET_DIVIDER(pdr4, + MXC_CCM_PDR4_PER0_PODF_MASK, + MXC_CCM_PDR4_PER0_PODF_OFFSET) + 1; + } else { + div = CCM_GET_DIVIDER(pdr0, + MXC_CCM_PDR0_PER_PODF_MASK, + MXC_CCM_PDR0_PER_PODF_OFFSET) + 1; + div *= get_ahb_div(pdr0); + } + return freq / div; +} + +u32 imx_get_uartclk(void) +{ + u32 freq; + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + u32 pdr4 = readl(&ccm->pdr4); + + if (readl(&ccm->pdr3) & MXC_CCM_PDR3_UART_M_U) + freq = get_mcu_main_clk(); + else + freq = decode_pll(readl(&ccm->ppctl), MXC_HCLK); + freq /= CCM_GET_DIVIDER(pdr4, + MXC_CCM_PDR4_UART_PODF_MASK, + MXC_CCM_PDR4_UART_PODF_OFFSET) + 1; + return freq; +} + +unsigned int mxc_get_main_clock(enum mxc_main_clock clk) +{ + u32 nfc_pdf, hsp_podf; + u32 pll, ret_val = 0, usb_podf; + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + + u32 reg = readl(&ccm->pdr0); + u32 reg4 = readl(&ccm->pdr4); + + reg |= 0x1; + + switch (clk) { + case CPU_CLK: + ret_val = get_mcu_main_clk(); + break; + case AHB_CLK: + ret_val = get_mcu_main_clk(); + break; + case HSP_CLK: + if (reg & CLKMODE_CONSUMER) { + hsp_podf = (reg >> 20) & 0x3; + pll = get_mcu_main_clk(); + hsp_podf = hsp_div_table[hsp_podf][(reg>>16)&0xF]; + if (hsp_podf > 0) { + ret_val = pll / hsp_podf; + } else { + puts("mismatch HSP with ARM clock setting\n"); + ret_val = 0; + } + } else { + ret_val = get_mcu_main_clk(); + } + break; + case IPG_CLK: + ret_val = get_ipg_clk(); + break; + case IPG_PER_CLK: + ret_val = get_ipg_per_clk(); + break; + case NFC_CLK: + nfc_pdf = (reg4 >> 28) & 0xF; + pll = get_mcu_main_clk(); + /* AHB/nfc_pdf */ + ret_val = pll / (nfc_pdf + 1); + break; + case USB_CLK: + usb_podf = (reg4 >> 22) & 0x3F; + if (reg4 & 0x200) + pll = get_mcu_main_clk(); + else + pll = decode_pll(readl(&ccm->ppctl), MXC_HCLK); + + ret_val = pll / (usb_podf + 1); + break; + default: + printf("Unknown clock: %d\n", clk); + break; + } + + return ret_val; +} +unsigned int mxc_get_peri_clock(enum mxc_peri_clock clk) +{ + u32 ret_val = 0, pdf, pre_pdf, clk_sel; + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + u32 mpdr2 = readl(&ccm->pdr2); + u32 mpdr3 = readl(&ccm->pdr3); + u32 mpdr4 = readl(&ccm->pdr4); + + switch (clk) { + case UART1_BAUD: + case UART2_BAUD: + case UART3_BAUD: + clk_sel = mpdr3 & (1 << 14); + pdf = (mpdr4 >> 10) & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); + break; + case SSI1_BAUD: + pre_pdf = (mpdr2 >> 24) & 0x7; + pdf = mpdr2 & 0x3F; + clk_sel = mpdr2 & (1 << 6); + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / + ((pre_pdf + 1) * (pdf + 1)); + break; + case SSI2_BAUD: + pre_pdf = (mpdr2 >> 27) & 0x7; + pdf = (mpdr2 >> 8) & 0x3F; + clk_sel = mpdr2 & (1 << 6); + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / + ((pre_pdf + 1) * (pdf + 1)); + break; + case CSI_BAUD: + clk_sel = mpdr2 & (1 << 7); + pdf = (mpdr2 >> 16) & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); + break; + case MSHC_CLK: + pre_pdf = readl(&ccm->pdr1); + clk_sel = (pre_pdf & 0x80); + pdf = (pre_pdf >> 22) & 0x3F; + pre_pdf = (pre_pdf >> 28) & 0x7; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / + ((pre_pdf + 1) * (pdf + 1)); + break; + case ESDHC1_CLK: + clk_sel = mpdr3 & 0x40; + pdf = mpdr3 & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); + break; + case ESDHC2_CLK: + clk_sel = mpdr3 & 0x40; + pdf = (mpdr3 >> 8) & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); + break; + case ESDHC3_CLK: + clk_sel = mpdr3 & 0x40; + pdf = (mpdr3 >> 16) & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / (pdf + 1); + break; + case SPDIF_CLK: + clk_sel = mpdr3 & 0x400000; + pre_pdf = (mpdr3 >> 29) & 0x7; + pdf = (mpdr3 >> 23) & 0x3F; + ret_val = ((clk_sel != 0) ? mxc_get_main_clock(CPU_CLK) : + decode_pll(readl(&ccm->ppctl), MXC_HCLK)) / + ((pre_pdf + 1) * (pdf + 1)); + break; + default: + printf("%s(): This clock: %d not supported yet\n", + __func__, clk); + break; + } + + return ret_val; +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return get_mcu_main_clk(); + case MXC_AHB_CLK: + break; + case MXC_IPG_CLK: + return get_ipg_clk(); + case MXC_IPG_PERCLK: + case MXC_I2C_CLK: + return get_ipg_per_clk(); + case MXC_UART_CLK: + return imx_get_uartclk(); + case MXC_ESDHC1_CLK: + return mxc_get_peri_clock(ESDHC1_CLK); + case MXC_ESDHC2_CLK: + return mxc_get_peri_clock(ESDHC2_CLK); + case MXC_ESDHC3_CLK: + return mxc_get_peri_clock(ESDHC3_CLK); + case MXC_USB_CLK: + return mxc_get_main_clock(USB_CLK); + case MXC_FEC_CLK: + return get_ipg_clk(); + case MXC_CSPI_CLK: + return get_ipg_clk(); + } + return -1; +} + +#ifdef CONFIG_FEC_MXC +/* + * The MX35 has no fuse for MAC, return a NULL MAC + */ +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + memset(mac, 0, 6); +} + +u32 imx_get_fecclk(void) +{ + return mxc_get_clock(MXC_IPG_CLK); +} +#endif + +int do_mx35_showclocks(cmd_tbl_t *cmdtp, + int flag, int argc, char * const argv[]) +{ + u32 cpufreq = get_mcu_main_clk(); + printf("mx35 cpu clock: %dMHz\n", cpufreq / 1000000); + printf("ipg clock : %dHz\n", get_ipg_clk()); + printf("ipg per clock : %dHz\n", get_ipg_per_clk()); + printf("uart clock : %dHz\n", mxc_get_clock(MXC_UART_CLK)); + + return 0; +} + +U_BOOT_CMD( + clocks, CONFIG_SYS_MAXARGS, 1, do_mx35_showclocks, + "display clocks", + "" +); + +#if defined(CONFIG_DISPLAY_CPUINFO) +static char *get_reset_cause(void) +{ + /* read RCSR register from CCM module */ + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + + u32 cause = readl(&ccm->rcsr) & 0x0F; + + switch (cause) { + case 0x0000: + return "POR"; + case 0x0002: + return "JTAG"; + case 0x0004: + return "RST"; + case 0x0008: + return "WDOG"; + default: + return "unknown reset"; + } +} + +int print_cpuinfo(void) +{ + u32 srev = get_cpu_rev(); + + printf("CPU: Freescale i.MX35 rev %d.%d at %d MHz.\n", + (srev & 0xF0) >> 4, (srev & 0x0F), + get_mcu_main_clk() / 1000000); + + printf("Reset cause: %s\n", get_reset_cause()); + + return 0; +} +#endif + +/* + * Initializes on-chip ethernet controllers. + * to override, implement board_eth_init() + */ +int cpu_eth_init(bd_t *bis) +{ + int rc = -ENODEV; + +#if defined(CONFIG_FEC_MXC) + rc = fecmxc_initialize(bis); +#endif + + return rc; +} + +#ifdef CONFIG_FSL_ESDHC +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init(bd_t *bis) +{ + return fsl_esdhc_mmc_init(bis); +} +#endif + +int get_clocks(void) +{ +#ifdef CONFIG_FSL_ESDHC +#if CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC2_BASE_ADDR + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); +#elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC3_BASE_ADDR + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); +#else + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK); +#endif +#endif + return 0; +} + +#define RCSR_MEM_CTL_WEIM 0 +#define RCSR_MEM_CTL_NAND 1 +#define RCSR_MEM_CTL_ATA 2 +#define RCSR_MEM_CTL_EXPANSION 3 +#define RCSR_MEM_TYPE_NOR 0 +#define RCSR_MEM_TYPE_ONENAND 2 +#define RCSR_MEM_TYPE_SD 0 +#define RCSR_MEM_TYPE_I2C 2 +#define RCSR_MEM_TYPE_SPI 3 + +u32 spl_boot_device(void) +{ + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + + u32 rcsr = readl(&ccm->rcsr); + u32 mem_type, mem_ctl; + + /* In external mode, no boot device is returned */ + if ((rcsr >> 10) & 0x03) + return BOOT_DEVICE_NONE; + + mem_ctl = (rcsr >> 25) & 0x03; + mem_type = (rcsr >> 23) & 0x03; + + switch (mem_ctl) { + case RCSR_MEM_CTL_WEIM: + switch (mem_type) { + case RCSR_MEM_TYPE_NOR: + return BOOT_DEVICE_NOR; + case RCSR_MEM_TYPE_ONENAND: + return BOOT_DEVICE_ONENAND; + default: + return BOOT_DEVICE_NONE; + } + case RCSR_MEM_CTL_NAND: + return BOOT_DEVICE_NAND; + case RCSR_MEM_CTL_EXPANSION: + switch (mem_type) { + case RCSR_MEM_TYPE_SD: + return BOOT_DEVICE_MMC1; + case RCSR_MEM_TYPE_I2C: + return BOOT_DEVICE_I2C; + case RCSR_MEM_TYPE_SPI: + return BOOT_DEVICE_SPI; + default: + return BOOT_DEVICE_NONE; + } + } + + return BOOT_DEVICE_NONE; +}
diff --git a/arch/arm/cpu/arm1136/mx35/mx35_sdram.c b/arch/arm/cpu/arm1136/mx35/mx35_sdram.c new file mode 100644 index 0000000..f120e84 --- /dev/null +++ b/arch/arm/cpu/arm1136/mx35/mx35_sdram.c
@@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2012, Stefano Babic <sbabic@denx.de> + */ + +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/imx-regs.h> +#include <linux/types.h> +#include <asm/arch/sys_proto.h> + +#define ESDCTL_DDR2_EMR2 0x04000000 +#define ESDCTL_DDR2_EMR3 0x06000000 +#define ESDCTL_PRECHARGE 0x00000400 +#define ESDCTL_DDR2_EN_DLL 0x02000400 +#define ESDCTL_DDR2_RESET_DLL 0x00000333 +#define ESDCTL_DDR2_MR 0x00000233 +#define ESDCTL_DDR2_OCD_DEFAULT 0x02000780 + +enum { + SMODE_NORMAL = 0, + SMODE_PRECHARGE, + SMODE_AUTO_REFRESH, + SMODE_LOAD_REG, + SMODE_MANUAL_REFRESH +}; + +#define set_mode(x, en, m) (x | (en << 31) | (m << 28)) + +static inline void dram_wait(unsigned int count) +{ + volatile unsigned int wait = count; + + while (wait--) + ; + +} + +void mx3_setup_sdram_bank(u32 start_address, u32 ddr2_config, + u32 row, u32 col, u32 dsize, u32 refresh) +{ + struct esdc_regs *esdc = (struct esdc_regs *)ESDCTL_BASE_ADDR; + u32 *cfg_reg, *ctl_reg; + u32 val; + u32 ctlval; + + switch (start_address) { + case CSD0_BASE_ADDR: + cfg_reg = &esdc->esdcfg0; + ctl_reg = &esdc->esdctl0; + break; + case CSD1_BASE_ADDR: + cfg_reg = &esdc->esdcfg1; + ctl_reg = &esdc->esdctl1; + break; + default: + return; + } + + /* The MX35 supports 11 up to 14 rows */ + if (row < 11 || row > 14 || col < 8 || col > 10) + return; + ctlval = (row - 11) << 24 | (col - 8) << 20 | (dsize << 16); + + /* Initialize MISC register for DDR2 */ + val = ESDC_MISC_RST | ESDC_MISC_MDDR_EN | ESDC_MISC_MDDR_DL_RST | + ESDC_MISC_DDR_EN | ESDC_MISC_DDR2_EN; + writel(val, &esdc->esdmisc); + val &= ~(ESDC_MISC_RST | ESDC_MISC_MDDR_DL_RST); + writel(val, &esdc->esdmisc); + + /* + * according to DDR2 specs, wait a while before + * the PRECHARGE_ALL command + */ + dram_wait(0x20000); + + /* Load DDR2 config and timing */ + writel(ddr2_config, cfg_reg); + + /* Precharge ALL */ + writel(set_mode(ctlval, 1, SMODE_PRECHARGE), + ctl_reg); + writel(0xda, start_address + ESDCTL_PRECHARGE); + + /* Load mode */ + writel(set_mode(ctlval, 1, SMODE_LOAD_REG), + ctl_reg); + writeb(0xda, start_address + ESDCTL_DDR2_EMR2); /* EMRS2 */ + writeb(0xda, start_address + ESDCTL_DDR2_EMR3); /* EMRS3 */ + writeb(0xda, start_address + ESDCTL_DDR2_EN_DLL); /* Enable DLL */ + writeb(0xda, start_address + ESDCTL_DDR2_RESET_DLL); /* Reset DLL */ + + /* Precharge ALL */ + writel(set_mode(ctlval, 1, SMODE_PRECHARGE), + ctl_reg); + writel(0xda, start_address + ESDCTL_PRECHARGE); + + /* Set mode auto refresh : at least two refresh are required */ + writel(set_mode(ctlval, 1, SMODE_AUTO_REFRESH), + ctl_reg); + writel(0xda, start_address); + writel(0xda, start_address); + + writel(set_mode(ctlval, 1, SMODE_LOAD_REG), + ctl_reg); + writeb(0xda, start_address + ESDCTL_DDR2_MR); + writeb(0xda, start_address + ESDCTL_DDR2_OCD_DEFAULT); + + /* OCD mode exit */ + writeb(0xda, start_address + ESDCTL_DDR2_EN_DLL); /* Enable DLL */ + + /* Set normal mode */ + writel(set_mode(ctlval, 1, SMODE_NORMAL) | refresh, + ctl_reg); + + dram_wait(0x20000); + + /* Do not set delay lines, only for MDDR */ +}
diff --git a/arch/arm/cpu/arm1136/mx35/relocate.S b/arch/arm/cpu/arm1136/mx35/relocate.S new file mode 100644 index 0000000..e41e5a5 --- /dev/null +++ b/arch/arm/cpu/arm1136/mx35/relocate.S
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * relocate - i.MX35-specific vector relocation + * + * Copyright (c) 2013 Albert ARIBAUD <albert.u.boot@aribaud.net> + */ + +#include <linux/linkage.h> + +/* + * The i.MX35 SoC is very specific with respect to exceptions: it + * does not provide RAM at the high vectors address (0xFFFF0000), + * thus only the low address (0x00000000) is useable; but that is + * in ROM, so let's avoid relocating the vectors. + */ + .section .text.relocate_vectors,"ax",%progbits + +ENTRY(relocate_vectors) + + bx lr + +ENDPROC(relocate_vectors)
diff --git a/arch/arm/cpu/arm1136/mx35/timer.c b/arch/arm/cpu/arm1136/mx35/timer.c new file mode 100644 index 0000000..c1cdf35 --- /dev/null +++ b/arch/arm/cpu/arm1136/mx35/timer.c
@@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/crm_regs.h> + +/* General purpose timers bitfields */ +#define GPTCR_SWR (1<<15) /* Software reset */ +#define GPTCR_FRR (1<<9) /* Freerun / restart */ +#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ +#define GPTCR_TEN (1) /* Timer enable */ + +/* + * nothing really to do with interrupts, just starts up a counter. + * The 32KHz 32-bit timer overruns in 134217 seconds + */ +int timer_init(void) +{ + int i; + struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR; + struct ccm_regs *ccm = (struct ccm_regs *)CCM_BASE_ADDR; + + /* setup GP Timer 1 */ + writel(GPTCR_SWR, &gpt->ctrl); + + writel(readl(&ccm->cgr1) | 3 << MXC_CCM_CGR1_GPT_OFFSET, &ccm->cgr1); + + for (i = 0; i < 100; i++) + writel(0, &gpt->ctrl); /* We have no udelay by now */ + writel(0, &gpt->pre); /* prescaler = 1 */ + /* Freerun Mode, 32KHz input */ + writel(readl(&gpt->ctrl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR, + &gpt->ctrl); + writel(readl(&gpt->ctrl) | GPTCR_TEN, &gpt->ctrl); + + return 0; +}
diff --git a/arch/arm/cpu/arm1136/start.S b/arch/arm/cpu/arm1136/start.S new file mode 100644 index 0000000..da7278e --- /dev/null +++ b/arch/arm/cpu/arm1136/start.S
@@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * armboot - Startup Code for OMP2420/ARM1136 CPU-core + * + * Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com> + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + */ + +#include <asm-offsets.h> +#include <config.h> + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + + .globl reset + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* the mask ROM code should have PLL and others stable */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + bx lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit: + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* Invalidate I+D+BTB caches */ + mcr p15, 0, r0, c8, c7, 0 /* Invalidate Unified TLB */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) + bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) + orr r0, r0, #0x00000002 @ set bit 1 (A) Align + orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache + mcr p15, 0, r0, c1, c0, 0 + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY + /* + * Jump to board specific initialization... The Mask ROM will have already initialized + * basic memory. Go here to bump up clock rate and handle wake up conditions. + */ + mov ip, lr /* persevere link reg across call */ + bl lowlevel_init /* go setup pll,mux,memory */ + mov lr, ip /* restore link */ +#endif + mov pc, lr /* back to my caller */ +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
diff --git a/arch/arm/cpu/arm1136/u-boot-spl.lds b/arch/arm/cpu/arm1136/u-boot-spl.lds new file mode 100644 index 0000000..881275a --- /dev/null +++ b/arch/arm/cpu/arm1136/u-boot-spl.lds
@@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : + { + __start = .; + *(.vectors) + arch/arm/cpu/arm1136/start.o (.text*) + *(.text*) + } >.sram + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram + + . = ALIGN(4); + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram + . = ALIGN(4); + __image_copy_end = .; + + .end : + { + *(.__end) + } + + .bss : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } >.sdram +}
diff --git a/arch/arm/cpu/arm1176/Makefile b/arch/arm/cpu/arm1176/Makefile new file mode 100644 index 0000000..3233247 --- /dev/null +++ b/arch/arm/cpu/arm1176/Makefile
@@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2008 +# Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> + +obj- += dummy.o +extra-y = start.o + +obj-y += ../arm11/
diff --git a/arch/arm/cpu/arm1176/start.S b/arch/arm/cpu/arm1176/start.S new file mode 100644 index 0000000..1402924 --- /dev/null +++ b/arch/arm/cpu/arm1176/start.S
@@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * armboot - Startup Code for ARM1176 CPU-core + * + * Copyright (c) 2007 Samsung Electronics + * + * Copyright (C) 2008 + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> + * + * 2007-09-21 - Restructured codes by jsgood (jsgood.yang@samsung.com) + * 2007-09-21 - Added MoviNAND and OneNAND boot codes by + * jsgood (jsgood.yang@samsung.com) + * Base codes by scsuh (sc.suh) + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> + +#ifndef CONFIG_SYS_PHY_UBOOT_BASE +#define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE +#endif + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + + .globl reset + +reset: + /* Allow the board to save important registers */ + b save_boot_params +.globl save_boot_params_ret +save_boot_params_ret: + + /* + * set the cpu to SVC32 mode + */ + mrs r0, cpsr + bic r0, r0, #0x3f + orr r0, r0, #0xd3 + msr cpsr, r0 + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +cpu_init_crit: + /* + * When booting from NAND - it has definitely been a reset, so, no need + * to flush caches and disable the MMU + */ +#ifndef CONFIG_SPL_BUILD + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ + mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) + bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) + orr r0, r0, #0x00000002 @ set bit 1 (A) Align + orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache + + /* Prepare to disable the MMU */ + adr r2, mmu_disable_phys + sub r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - CONFIG_SYS_TEXT_BASE) + b mmu_disable + + .align 5 + /* Run in a single cache-line */ +mmu_disable: + mcr p15, 0, r0, c1, c0, 0 + nop + nop + mov pc, r2 +mmu_disable_phys: + +#endif + + /* + * Go setup Memory and board specific bits prior to relocation. + */ + bl lowlevel_init /* go setup pll,mux,memory */ + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + mov pc, lr + +WEAK(save_boot_params) + b save_boot_params_ret /* back to my caller */ +ENDPROC(save_boot_params)
diff --git a/arch/arm/cpu/arm720t/Makefile b/arch/arm/cpu/arm720t/Makefile new file mode 100644 index 0000000..e70b590 --- /dev/null +++ b/arch/arm/cpu/arm720t/Makefile
@@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-y = start.o +obj-y = interrupts.o cpu.o
diff --git a/arch/arm/cpu/arm720t/cpu.c b/arch/arm/cpu/arm720t/cpu.c new file mode 100644 index 0000000..ece09c8 --- /dev/null +++ b/arch/arm/cpu/arm720t/cpu.c
@@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + */ + +/* + * cleanup_before_linux() - Prepare the CPU to jump to Linux + * + * This function is called just before we call Linux, it + * prepares the processor for linux + */ +int cleanup_before_linux(void) +{ + return 0; +}
diff --git a/arch/arm/cpu/arm720t/interrupts.c b/arch/arm/cpu/arm720t/interrupts.c new file mode 100644 index 0000000..8437717 --- /dev/null +++ b/arch/arm/cpu/arm720t/interrupts.c
@@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + */ + +#include <common.h> + +#if defined(CONFIG_TEGRA) +static ulong timestamp; +static ulong lastdec; + +int timer_init (void) +{ + /* No timer routines for tegra as yet */ + lastdec = 0; + timestamp = 0; + + return 0; +} +#endif
diff --git a/arch/arm/cpu/arm720t/start.S b/arch/arm/cpu/arm720t/start.S new file mode 100644 index 0000000..ecb4e44 --- /dev/null +++ b/arch/arm/cpu/arm720t/start.S
@@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * armboot - Startup Code for ARM720 CPU-core + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + */ + +#include <asm-offsets.h> +#include <config.h> + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from RAM! + * relocate armboot to ram + * setup stack + * jump to second stage + * + ************************************************************************* + */ + + .globl reset + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && \ + !defined(CONFIG_SKIP_LOWLEVEL_INIT_ONLY) + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + mov pc, lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + +#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && \ + !defined(CONFIG_SKIP_LOWLEVEL_INIT_ONLY) +cpu_init_crit: + + mov ip, lr + /* + * before relocating, we have to setup RAM timing + * because memory timing is board-dependent, you will + * find a lowlevel_init.S in your board directory. + */ + bl lowlevel_init + mov lr, ip + + mov pc, lr +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
diff --git a/arch/arm/cpu/arm920t/Makefile b/arch/arm/cpu/arm920t/Makefile new file mode 100644 index 0000000..c63f578 --- /dev/null +++ b/arch/arm/cpu/arm920t/Makefile
@@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-y = start.o + +obj-y += cpu.o + +obj-$(CONFIG_EP93XX) += ep93xx/ +obj-$(CONFIG_IMX) += imx/ + +# some files can only build in ARM mode + +ifdef CONFIG_$(SPL_)SYS_THUMB_BUILD +CFLAGS_cpu.o := -marm +endif
diff --git a/arch/arm/cpu/arm920t/cpu.c b/arch/arm/cpu/arm920t/cpu.c new file mode 100644 index 0000000..2ef133f --- /dev/null +++ b/arch/arm/cpu/arm920t/cpu.c
@@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> + +static void cache_flush(void); + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + disable_interrupts (); + + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + /* flush I/D-cache */ + cache_flush(); + + return 0; +} + +/* flush I/D-cache */ +static void cache_flush (void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); +}
diff --git a/arch/arm/cpu/arm920t/ep93xx/Makefile b/arch/arm/cpu/arm920t/ep93xx/Makefile new file mode 100644 index 0000000..152b5e7 --- /dev/null +++ b/arch/arm/cpu/arm920t/ep93xx/Makefile
@@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Cirrus Logic EP93xx CPU-specific Makefile +# +# Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> +# +# Copyright (C) 2004, 2005 +# Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com> +# +# Copyright (C) 2006 +# Dominic Rath <Dominic.Rath@gmx.de> +# +# Based on an original Makefile, which is +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +obj-y = cpu.o led.o speed.o timer.o +obj-y += lowlevel_init.o
diff --git a/arch/arm/cpu/arm920t/ep93xx/cpu.c b/arch/arm/cpu/arm920t/ep93xx/cpu.c new file mode 100644 index 0000000..3aae12f --- /dev/null +++ b/arch/arm/cpu/arm920t/ep93xx/cpu.c
@@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Cirrus Logic EP93xx CPU-specific support. + * + * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * Copyright (C) 2004, 2005 + * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com> + */ + +#include <common.h> +#include <asm/arch/ep93xx.h> +#include <asm/io.h> + +/* We reset the CPU by generating a 1-->0 transition on DeviceCfg bit 31. */ +extern void reset_cpu(ulong addr) +{ + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + uint32_t value; + + /* Unlock DeviceCfg and set SWRST */ + writel(0xAA, &syscon->sysswlock); + value = readl(&syscon->devicecfg); + value |= SYSCON_DEVICECFG_SWRST; + writel(value, &syscon->devicecfg); + + /* Unlock DeviceCfg and clear SWRST */ + writel(0xAA, &syscon->sysswlock); + value = readl(&syscon->devicecfg); + value &= ~SYSCON_DEVICECFG_SWRST; + writel(value, &syscon->devicecfg); + + /* Dying... */ + while (1) + ; /* noop */ +}
diff --git a/arch/arm/cpu/arm920t/ep93xx/led.c b/arch/arm/cpu/arm920t/ep93xx/led.c new file mode 100644 index 0000000..862663a --- /dev/null +++ b/arch/arm/cpu/arm920t/ep93xx/led.c
@@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010, 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + */ + +#include <asm/io.h> +#include <asm/arch/ep93xx.h> +#include <config.h> +#include <status_led.h> + +static uint8_t saved_state[2] = {CONFIG_LED_STATUS_OFF, CONFIG_LED_STATUS_OFF}; +static uint32_t gpio_pin[2] = {1 << CONFIG_LED_STATUS_GREEN, + 1 << CONFIG_LED_STATUS_RED}; + +static inline void switch_LED_on(uint8_t led) +{ + register struct gpio_regs *gpio = (struct gpio_regs *)GPIO_BASE; + + writel(readl(&gpio->pedr) | gpio_pin[led], &gpio->pedr); + saved_state[led] = CONFIG_LED_STATUS_ON; +} + +static inline void switch_LED_off(uint8_t led) +{ + register struct gpio_regs *gpio = (struct gpio_regs *)GPIO_BASE; + + writel(readl(&gpio->pedr) & ~gpio_pin[led], &gpio->pedr); + saved_state[led] = CONFIG_LED_STATUS_OFF; +} + +void red_led_on(void) +{ + switch_LED_on(CONFIG_LED_STATUS_RED); +} + +void red_led_off(void) +{ + switch_LED_off(CONFIG_LED_STATUS_RED); +} + +void green_led_on(void) +{ + switch_LED_on(CONFIG_LED_STATUS_GREEN); +} + +void green_led_off(void) +{ + switch_LED_off(CONFIG_LED_STATUS_GREEN); +} + +void __led_init(led_id_t mask, int state) +{ + __led_set(mask, state); +} + +void __led_toggle(led_id_t mask) +{ + if (CONFIG_LED_STATUS_RED == mask) { + if (CONFIG_LED_STATUS_ON == saved_state[CONFIG_LED_STATUS_RED]) + red_led_off(); + else + red_led_on(); + } else if (CONFIG_LED_STATUS_GREEN == mask) { + if (CONFIG_LED_STATUS_ON == + saved_state[CONFIG_LED_STATUS_GREEN]) + green_led_off(); + else + green_led_on(); + } +} + +void __led_set(led_id_t mask, int state) +{ + if (CONFIG_LED_STATUS_RED == mask) { + if (CONFIG_LED_STATUS_ON == state) + red_led_on(); + else + red_led_off(); + } else if (CONFIG_LED_STATUS_GREEN == mask) { + if (CONFIG_LED_STATUS_ON == state) + green_led_on(); + else + green_led_off(); + } +}
diff --git a/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S b/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S new file mode 100644 index 0000000..5239b10 --- /dev/null +++ b/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S
@@ -0,0 +1,457 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Low-level initialization for EP93xx + * + * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * Copyright (C) 2013 + * Sergey Kostanabev <sergey.kostanbaev <at> fairwaves.ru> + * + * Copyright (C) 2006 Dominic Rath <Dominic.Rath@gmx.de> + * Copyright (C) 2006 Cirrus Logic Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + */ + +#include <config.h> +#include <asm/arch-ep93xx/ep93xx.h> + +/* +/* Configure the SDRAM based on the supplied settings. + * + * Input: r0 - SDRAM DEVCFG register + * r2 - configuration for SDRAM chips + * Output: none + * Modifies: r3, r4 + */ +ep93xx_sdram_config: + /* Program the SDRAM device configuration register. */ + ldr r3, =SDRAM_BASE +#ifdef CONFIG_EDB93XX_SDCS0 + str r0, [r3, #SDRAM_OFF_DEVCFG0] +#endif +#ifdef CONFIG_EDB93XX_SDCS1 + str r0, [r3, #SDRAM_OFF_DEVCFG1] +#endif +#ifdef CONFIG_EDB93XX_SDCS2 + str r0, [r3, #SDRAM_OFF_DEVCFG2] +#endif +#ifdef CONFIG_EDB93XX_SDCS3 + str r0, [r3, #SDRAM_OFF_DEVCFG3] +#endif + + /* Set the Initialize and MRS bits (issue continuous NOP commands + * (INIT & MRS set)) + */ + ldr r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_INIT | \ + EP93XX_SDRAMCTRL_GLOBALCFG_MRS | \ + EP93XX_SDRAMCTRL_GLOBALCFG_CKE) + str r4, [r3, #SDRAM_OFF_GLCONFIG] + + /* Delay for 200us. */ + mov r4, #0x3000 +delay1: + subs r4, r4, #1 + bne delay1 + + /* Clear the MRS bit to issue a precharge all. */ + ldr r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_INIT | \ + EP93XX_SDRAMCTRL_GLOBALCFG_CKE) + str r4, [r3, #SDRAM_OFF_GLCONFIG] + + /* Temporarily set the refresh timer to 0x10. Make it really low so + * that refresh cycles are generated. + */ + ldr r4, =0x10 + str r4, [r3, #SDRAM_OFF_REFRSHTIMR] + + /* Delay for at least 80 SDRAM clock cycles. */ + mov r4, #80 +delay2: + subs r4, r4, #1 + bne delay2 + + /* Set the refresh timer to the fastest required for any device + * that might be used. Set 9.6 ms refresh time. + */ + ldr r4, =0x01e0 + str r4, [r3, #SDRAM_OFF_REFRSHTIMR] + + /* Select mode register update mode. */ + ldr r4, =(EP93XX_SDRAMCTRL_GLOBALCFG_CKE | \ + EP93XX_SDRAMCTRL_GLOBALCFG_MRS) + str r4, [r3, #SDRAM_OFF_GLCONFIG] + + /* Program the mode register on the SDRAM by performing fake read */ + ldr r4, [r2] + + /* Select normal operating mode. */ + ldr r4, =EP93XX_SDRAMCTRL_GLOBALCFG_CKE + str r4, [r3, #SDRAM_OFF_GLCONFIG] + + /* Return to the caller. */ + mov pc, lr + +/* + * Test to see if the SDRAM has been configured in a usable mode. + * + * Input: r0 - Test address of SDRAM + * Output: r0 - 0 -- Test OK, -1 -- Failed + * Modifies: r0-r5 + */ +ep93xx_sdram_test: + /* Load the test patterns to be written to SDRAM. */ + ldr r1, =0xf00dface + ldr r2, =0xdeadbeef + ldr r3, =0x08675309 + ldr r4, =0xdeafc0ed + + /* Store the test patterns to SDRAM. */ + stmia r0, {r1-r4} + + /* Load the test patterns from SDRAM one at a time and compare them + * to the actual pattern. + */ + ldr r5, [r0] + cmp r5, r1 + ldreq r5, [r0, #0x0004] + cmpeq r5, r2 + ldreq r5, [r0, #0x0008] + cmpeq r5, r3 + ldreq r5, [r0, #0x000c] + cmpeq r5, r4 + + /* Return -1 if a mismatch was encountered, 0 otherwise. */ + mvnne r0, #0xffffffff + moveq r0, #0x00000000 + + /* Return to the caller. */ + mov pc, lr + +/* + * Determine the size of the SDRAM. Use data=address for the scan. + * + * Input: r0 - Start SDRAM address + * Return: r0 - Single block size + * r1 - Valid block mask + * r2 - Total block count + * Modifies: r0-r5 + */ +ep93xx_sdram_size: + /* Store zero at offset zero. */ + str r0, [r0] + + /* Start checking for an alias at 1MB into SDRAM. */ + ldr r1, =0x00100000 + + /* Store the offset at the current offset. */ +check_block_size: + str r1, [r0, r1] + + /* Read back from zero. */ + ldr r2, [r0] + + /* Stop searching of an alias was found. */ + cmp r1, r2 + beq found_block_size + + /* Advance to the next power of two boundary. */ + mov r1, r1, lsl #1 + + /* Loop back if the size has not reached 256MB. */ + cmp r1, #0x10000000 + bne check_block_size + + /* A full 256MB of memory was found, so return it now. */ + ldr r0, =0x10000000 + ldr r1, =0x00000000 + ldr r2, =0x00000001 + mov pc, lr + + /* An alias was found. See if the first block is 128MB in size. */ +found_block_size: + cmp r1, #0x08000000 + + /* The first block is 128MB, so there is no further memory. Return it + * now. + */ + ldreq r0, =0x08000000 + ldreq r1, =0x00000000 + ldreq r2, =0x00000001 + moveq pc, lr + + /* Save the block size, set the block address bits to zero, and + * initialize the block count to one. + */ + mov r3, r1 + ldr r4, =0x00000000 + ldr r5, =0x00000001 + + /* Look for additional blocks of memory by searching for non-aliases. */ +find_blocks: + /* Store zero back to address zero. It may be overwritten. */ + str r0, [r0] + + /* Advance to the next power of two boundary. */ + mov r1, r1, lsl #1 + + /* Store the offset at the current offset. */ + str r1, [r0, r1] + + /* Read back from zero. */ + ldr r2, [r0] + + /* See if a non-alias was found. */ + cmp r1, r2 + + /* If a non-alias was found, then or in the block address bit and + * multiply the block count by two (since there are two unique + * blocks, one with this bit zero and one with it one). + */ + orrne r4, r4, r1 + movne r5, r5, lsl #1 + + /* Continue searching if there are more address bits to check. */ + cmp r1, #0x08000000 + bne find_blocks + + /* Return the block size, address mask, and count. */ + mov r0, r3 + mov r1, r4 + mov r2, r5 + + /* Return to the caller. */ + mov pc, lr + + +.globl lowlevel_init +lowlevel_init: + + mov r6, lr + + /* Make sure caches are off and invalidated. */ + ldr r0, =0x00000000 + mcr p15, 0, r0, c1, c0, 0 + nop + nop + nop + nop + nop + + /* Turn off the green LED and turn on the red LED. If the red LED + * is left on for too long, the external reset circuit described + * by application note AN258 will cause the system to reset. + */ + ldr r1, =EP93XX_LED_DATA + ldr r0, [r1] + bic r0, r0, #EP93XX_LED_GREEN_ON + orr r0, r0, #EP93XX_LED_RED_ON + str r0, [r1] + + /* Undo the silly static memory controller programming performed + * by the boot rom. + */ + ldr r0, =SMC_BASE + + /* Set WST1 and WST2 to 31 HCLK cycles (slowest access) */ + ldr r1, =0x0000fbe0 + + /* Reset EP93XX_OFF_SMCBCR0 */ + ldr r2, [r0] + orr r2, r2, r1 + str r2, [r0] + + ldr r2, [r0, #EP93XX_OFF_SMCBCR1] + orr r2, r2, r1 + str r2, [r0, #EP93XX_OFF_SMCBCR1] + + ldr r2, [r0, #EP93XX_OFF_SMCBCR2] + orr r2, r2, r1 + str r2, [r0, #EP93XX_OFF_SMCBCR2] + + ldr r2, [r0, #EP93XX_OFF_SMCBCR3] + orr r2, r2, r1 + str r2, [r0, #EP93XX_OFF_SMCBCR3] + + ldr r2, [r0, #EP93XX_OFF_SMCBCR6] + orr r2, r2, r1 + str r2, [r0, #EP93XX_OFF_SMCBCR6] + + ldr r2, [r0, #EP93XX_OFF_SMCBCR7] + orr r2, r2, r1 + str r2, [r0, #EP93XX_OFF_SMCBCR7] + + /* Set the PLL1 and processor clock. */ + ldr r0, =SYSCON_BASE +#ifdef CONFIG_EDB9301 + /* 332MHz, giving a 166MHz processor clock. */ + ldr r1, = 0x02b49907 +#else + +#ifdef CONFIG_EDB93XX_INDUSTRIAL + /* 384MHz, giving a 196MHz processor clock. */ + ldr r1, =0x02a4bb38 +#else + /* 400MHz, giving a 200MHz processor clock. */ + ldr r1, =0x02a4e39e +#endif +#endif + str r1, [r0, #SYSCON_OFF_CLKSET1] + + nop + nop + nop + nop + nop + + /* Need to make sure that SDRAM is configured correctly before + * coping the code into it. + */ + +#ifdef CONFIG_EDB93XX_SDCS0 + mov r11, #SDRAM_DEVCFG0_BASE +#endif +#ifdef CONFIG_EDB93XX_SDCS1 + mov r11, #SDRAM_DEVCFG1_BASE +#endif +#ifdef CONFIG_EDB93XX_SDCS2 + mov r11, #SDRAM_DEVCFG2_BASE +#endif +#ifdef CONFIG_EDB93XX_SDCS3 + ldr r0, =SYSCON_BASE + ldr r0, [r0, #SYSCON_OFF_SYSCFG] + ands r0, r0, #SYSCON_SYSCFG_LASDO + moveq r11, #SDRAM_DEVCFG3_ASD0_BASE + movne r11, #SDRAM_DEVCFG3_ASD1_BASE +#endif + /* See Table 13-5 in EP93xx datasheet for more info about DRAM + * register mapping */ + + /* Try a 32-bit wide configuration of SDRAM. */ + ldr r0, =(EP93XX_SDRAMCTRL_DEVCFG_BANKCOUNT | \ + EP93XX_SDRAMCTRL_DEVCFG_SROMLL | \ + EP93XX_SDRAMCTRL_DEVCFG_CASLAT_2 | \ + EP93XX_SDRAMCTRL_DEVCFG_RASTOCAS_2) + + /* Set burst count: 4 and CAS: 2 + * Burst mode [A11:A10]; CAS [A16:A14] + */ + orr r2, r11, #0x00008800 + bl ep93xx_sdram_config + + /* Test the SDRAM. */ + mov r0, r11 + bl ep93xx_sdram_test + cmp r0, #0x00000000 + beq ep93xx_sdram_done + + /* Try a 16-bit wide configuration of SDRAM. */ + ldr r0, =(EP93XX_SDRAMCTRL_DEVCFG_BANKCOUNT | \ + EP93XX_SDRAMCTRL_DEVCFG_SROMLL | \ + EP93XX_SDRAMCTRL_DEVCFG_CASLAT_2 | \ + EP93XX_SDRAMCTRL_DEVCFG_RASTOCAS_2 | \ + EP93XX_SDRAMCTRL_DEVCFG_EXTBUSWIDTH) + + /* Set burst count: 8, CAS: 2, sequential burst + * Accoring to Table 13-3 for 16bit operations mapping must be shifted. + * Burst mode [A10:A9]; CAS [A15:A13] + */ + orr r2, r11, #0x00004600 + bl ep93xx_sdram_config + + /* Test the SDRAM. */ + mov r0, r11 + bl ep93xx_sdram_test + cmp r0, #0x00000000 + beq ep93xx_sdram_done + + /* Turn off the red LED. */ + ldr r0, =EP93XX_LED_DATA + ldr r1, [r0] + bic r1, r1, #EP93XX_LED_RED_ON + str r1, [r0] + + /* There is no SDRAM so flash the green LED. */ +flash_green: + orr r1, r1, #EP93XX_LED_GREEN_ON + str r1, [r0] + ldr r2, =0x00010000 +flash_green_delay_1: + subs r2, r2, #1 + bne flash_green_delay_1 + bic r1, r1, #EP93XX_LED_GREEN_ON + str r1, [r0] + ldr r2, =0x00010000 +flash_green_delay_2: + subs r2, r2, #1 + bne flash_green_delay_2 + orr r1, r1, #EP93XX_LED_GREEN_ON + str r1, [r0] + ldr r2, =0x00010000 +flash_green_delay_3: + subs r2, r2, #1 + bne flash_green_delay_3 + bic r1, r1, #EP93XX_LED_GREEN_ON + str r1, [r0] + ldr r2, =0x00050000 +flash_green_delay_4: + subs r2, r2, #1 + bne flash_green_delay_4 + b flash_green + + +ep93xx_sdram_done: + ldr r1, =EP93XX_LED_DATA + ldr r0, [r1] + bic r0, r0, #EP93XX_LED_RED_ON + str r0, [r1] + + /* Determine the size of the SDRAM. */ + mov r0, r11 + bl ep93xx_sdram_size + + /* Save the SDRAM characteristics. */ + mov r8, r0 + mov r9, r1 + mov r10, r2 + + /* Compute total memory size into r1 */ + mul r1, r8, r10 +#ifdef CONFIG_EDB93XX_SDCS0 + ldr r2, [r0, #SDRAM_OFF_DEVCFG0] +#endif +#ifdef CONFIG_EDB93XX_SDCS1 + ldr r2, [r0, #SDRAM_OFF_DEVCFG1] +#endif +#ifdef CONFIG_EDB93XX_SDCS2 + ldr r2, [r0, #SDRAM_OFF_DEVCFG2] +#endif +#ifdef CONFIG_EDB93XX_SDCS3 + ldr r2, [r0, #SDRAM_OFF_DEVCFG3] +#endif + + /* Consider small DRAM size as: + * < 32Mb for 32bit bus + * < 64Mb for 16bit bus + */ + tst r2, #EP93XX_SDRAMCTRL_DEVCFG_EXTBUSWIDTH + moveq r1, r1, lsr #1 + cmp r1, #0x02000000 + +#if defined(CONFIG_EDB9301) + /* Set refresh counter to 20ms for small DRAM size, otherwise 9.6ms */ + movlt r1, #0x03f0 + movge r1, #0x01e0 +#else + /* Set refresh counter to 30.7ms for small DRAM size, otherwise 15ms */ + movlt r1, #0x0600 + movge r1, #0x2f0 +#endif + str r1, [r0, #SDRAM_OFF_REFRSHTIMR] + + /* Save the memory configuration information. */ + orr r0, r11, #UBOOT_MEMORYCNF_BANK_SIZE + stmia r0, {r8-r11} + + mov lr, r6 + mov pc, lr
diff --git a/arch/arm/cpu/arm920t/ep93xx/speed.c b/arch/arm/cpu/arm920t/ep93xx/speed.c new file mode 100644 index 0000000..51e9dda --- /dev/null +++ b/arch/arm/cpu/arm920t/ep93xx/speed.c
@@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Cirrus Logic EP93xx PLL support. + * + * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + */ + +#include <common.h> +#include <asm/arch/ep93xx.h> +#include <asm/io.h> +#include <div64.h> + +/* + * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. + * + * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of + * the specified bus in HZ. + */ + +/* + * return the PLL output frequency + * + * PLL rate = CONFIG_SYS_CLK_FREQ * (X1FBD + 1) * (X2FBD + 1) + * / (X2IPD + 1) / 2^PS + */ +static ulong get_PLLCLK(uint32_t *pllreg) +{ + uint8_t i; + const uint32_t clkset = readl(pllreg); + uint64_t rate = CONFIG_SYS_CLK_FREQ; + rate *= ((clkset >> SYSCON_CLKSET_PLL_X1FBD1_SHIFT) & 0x1f) + 1; + rate *= ((clkset >> SYSCON_CLKSET_PLL_X2FBD2_SHIFT) & 0x3f) + 1; + do_div(rate, (clkset & 0x1f) + 1); /* X2IPD */ + for (i = 0; i < ((clkset >> SYSCON_CLKSET_PLL_PS_SHIFT) & 3); i++) + rate >>= 1; + + return (ulong)rate; +} + +/* return FCLK frequency */ +ulong get_FCLK(void) +{ + const uint8_t fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + + const uint32_t clkset1 = readl(&syscon->clkset1); + const uint8_t fclk_div = + fclk_divisors[(clkset1 >> SYSCON_CLKSET1_FCLK_DIV_SHIFT) & 7]; + const ulong fclk_rate = get_PLLCLK(&syscon->clkset1) / fclk_div; + + return fclk_rate; +} + +/* return HCLK frequency */ +ulong get_HCLK(void) +{ + const uint8_t hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + + const uint32_t clkset1 = readl(&syscon->clkset1); + const uint8_t hclk_div = + hclk_divisors[(clkset1 >> SYSCON_CLKSET1_HCLK_DIV_SHIFT) & 7]; + const ulong hclk_rate = get_PLLCLK(&syscon->clkset1) / hclk_div; + + return hclk_rate; +} + +/* return PCLK frequency */ +ulong get_PCLK(void) +{ + const uint8_t pclk_divisors[] = { 1, 2, 4, 8 }; + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + + const uint32_t clkset1 = readl(&syscon->clkset1); + const uint8_t pclk_div = + pclk_divisors[(clkset1 >> SYSCON_CLKSET1_PCLK_DIV_SHIFT) & 3]; + const ulong pclk_rate = get_HCLK() / pclk_div; + + return pclk_rate; +} + +/* return UCLK frequency */ +ulong get_UCLK(void) +{ + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + ulong uclk_rate; + + const uint32_t value = readl(&syscon->pwrcnt); + if (value & SYSCON_PWRCNT_UART_BAUD) + uclk_rate = CONFIG_SYS_CLK_FREQ; + else + uclk_rate = CONFIG_SYS_CLK_FREQ / 2; + + return uclk_rate; +}
diff --git a/arch/arm/cpu/arm920t/ep93xx/timer.c b/arch/arm/cpu/arm920t/ep93xx/timer.c new file mode 100644 index 0000000..49bf49b --- /dev/null +++ b/arch/arm/cpu/arm920t/ep93xx/timer.c
@@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Cirrus Logic EP93xx timer support. + * + * Copyright (C) 2009, 2010 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * Copyright (C) 2004, 2005 + * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com> + * + * Based on the original intr.c Cirrus Logic EP93xx Rev D. interrupt support, + * author unknown. + */ + +#include <common.h> +#include <linux/types.h> +#include <asm/arch/ep93xx.h> +#include <asm/io.h> +#include <div64.h> + +#define TIMER_CLKSEL (1 << 3) +#define TIMER_ENABLE (1 << 7) + +#define TIMER_FREQ 508469 /* ticks / second */ +#define TIMER_MAX_VAL 0xFFFFFFFF + +static struct ep93xx_timer +{ + unsigned long long ticks; + unsigned long last_read; +} timer; + +static inline unsigned long long usecs_to_ticks(unsigned long usecs) +{ + unsigned long long ticks = (unsigned long long)usecs * TIMER_FREQ; + do_div(ticks, 1000 * 1000); + + return ticks; +} + +static inline void read_timer(void) +{ + struct timer_regs *timer_regs = (struct timer_regs *)TIMER_BASE; + const unsigned long now = TIMER_MAX_VAL - readl(&timer_regs->timer3.value); + + if (now >= timer.last_read) + timer.ticks += now - timer.last_read; + else + /* an overflow occurred */ + timer.ticks += TIMER_MAX_VAL - timer.last_read + now; + + timer.last_read = now; +} + +/* + * Get the number of ticks (in CONFIG_SYS_HZ resolution) + */ +unsigned long long get_ticks(void) +{ + unsigned long long sys_ticks; + + read_timer(); + + sys_ticks = timer.ticks * CONFIG_SYS_HZ; + do_div(sys_ticks, TIMER_FREQ); + + return sys_ticks; +} + +unsigned long get_timer(unsigned long base) +{ + return get_ticks() - base; +} + +void __udelay(unsigned long usec) +{ + unsigned long long target; + + read_timer(); + + target = timer.ticks + usecs_to_ticks(usec); + + while (timer.ticks < target) + read_timer(); +} + +int timer_init(void) +{ + struct timer_regs *timer_regs = (struct timer_regs *)TIMER_BASE; + + /* use timer 3 with 508KHz and free running, not enabled now */ + writel(TIMER_CLKSEL, &timer_regs->timer3.control); + + /* set initial timer value */ + writel(TIMER_MAX_VAL, &timer_regs->timer3.load); + + /* Enable the timer */ + writel(TIMER_ENABLE | TIMER_CLKSEL, + &timer_regs->timer3.control); + + /* Reset the timer */ + read_timer(); + timer.ticks = 0; + + return 0; +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +unsigned long get_tbclk(void) +{ + return CONFIG_SYS_HZ; +}
diff --git a/arch/arm/cpu/arm920t/imx/Makefile b/arch/arm/cpu/arm920t/imx/Makefile new file mode 100644 index 0000000..04bc129 --- /dev/null +++ b/arch/arm/cpu/arm920t/imx/Makefile
@@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +obj-y += generic.o +obj-y += speed.o +obj-y += timer.o
diff --git a/arch/arm/cpu/arm920t/imx/generic.c b/arch/arm/cpu/arm920t/imx/generic.c new file mode 100644 index 0000000..dbb908e --- /dev/null +++ b/arch/arm/cpu/arm920t/imx/generic.c
@@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * arch/arm/mach-imx/generic.c + * + * author: Sascha Hauer + * Created: april 20th, 2004 + * Copyright: Synertronixx GmbH + * + * Common code for i.MX machines + */ + +#include <common.h> + +#ifdef CONFIG_IMX + +#include <asm/arch/imx-regs.h> + +void imx_gpio_mode(int gpio_mode) +{ + unsigned int pin = gpio_mode & GPIO_PIN_MASK; + unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> 5; + unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> 10; + unsigned int tmp; + + /* Pullup enable */ + if(gpio_mode & GPIO_PUEN) + PUEN(port) |= (1<<pin); + else + PUEN(port) &= ~(1<<pin); + + /* Data direction */ + if(gpio_mode & GPIO_OUT) + DDIR(port) |= 1<<pin; + else + DDIR(port) &= ~(1<<pin); + + /* Primary / alternate function */ + if(gpio_mode & GPIO_AF) + GPR(port) |= (1<<pin); + else + GPR(port) &= ~(1<<pin); + + /* use as gpio? */ + if( ocr == 3 ) + GIUS(port) |= (1<<pin); + else + GIUS(port) &= ~(1<<pin); + + /* Output / input configuration */ + /* FIXME: I'm not very sure about OCR and ICONF, someone + * should have a look over it + */ + if(pin<16) { + tmp = OCR1(port); + tmp &= ~( 3<<(pin*2)); + tmp |= (ocr << (pin*2)); + OCR1(port) = tmp; + + if( gpio_mode & GPIO_AOUT ) + ICONFA1(port) &= ~( 3<<(pin*2)); + if( gpio_mode & GPIO_BOUT ) + ICONFB1(port) &= ~( 3<<(pin*2)); + } else { + tmp = OCR2(port); + tmp &= ~( 3<<((pin-16)*2)); + tmp |= (ocr << ((pin-16)*2)); + OCR2(port) = tmp; + + if( gpio_mode & GPIO_AOUT ) + ICONFA2(port) &= ~( 3<<((pin-16)*2)); + if( gpio_mode & GPIO_BOUT ) + ICONFB2(port) &= ~( 3<<((pin-16)*2)); + } +} + +#endif /* CONFIG_IMX */
diff --git a/arch/arm/cpu/arm920t/imx/speed.c b/arch/arm/cpu/arm920t/imx/speed.c new file mode 100644 index 0000000..eff6113 --- /dev/null +++ b/arch/arm/cpu/arm920t/imx/speed.c
@@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * + * (c) 2004 Sascha Hauer <sascha@saschahauer.de> + */ + + +#include <common.h> +#if defined (CONFIG_IMX) + +#include <asm/arch/imx-regs.h> + +/* ------------------------------------------------------------------------- */ +/* NOTE: This describes the proper use of this file. + * + * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. + * SH FIXME: 16780000 in our case + * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of + * the specified bus in HZ. + */ +/* ------------------------------------------------------------------------- */ + +ulong get_systemPLLCLK(void) +{ + /* FIXME: We assume System_SEL = 0 here */ + u32 spctl0 = SPCTL0; + u32 mfi = (spctl0 >> 10) & 0xf; + u32 mfn = spctl0 & 0x3f; + u32 mfd = (spctl0 >> 16) & 0x3f; + u32 pd = (spctl0 >> 26) & 0xf; + + mfi = mfi<=5 ? 5 : mfi; + + return (2*(CONFIG_SYSPLL_CLK_FREQ>>10)*( (mfi<<10) + (mfn<<10)/(mfd+1)))/(pd+1); +} + +ulong get_mcuPLLCLK(void) +{ + /* FIXME: We assume System_SEL = 0 here */ + u32 mpctl0 = MPCTL0; + u32 mfi = (mpctl0 >> 10) & 0xf; + u32 mfn = mpctl0 & 0x3f; + u32 mfd = (mpctl0 >> 16) & 0x3f; + u32 pd = (mpctl0 >> 26) & 0xf; + + mfi = mfi<=5 ? 5 : mfi; + + return (2*(CONFIG_SYS_CLK_FREQ>>10)*( (mfi<<10) + (mfn<<10)/(mfd+1)))/(pd+1); +} + +ulong get_FCLK(void) +{ + return (( CSCR>>15)&1) ? get_mcuPLLCLK()>>1 : get_mcuPLLCLK(); +} + +/* return HCLK frequency */ +ulong get_HCLK(void) +{ + u32 bclkdiv = (( CSCR >> 10 ) & 0xf) + 1; + printf("bclkdiv: %d\n", bclkdiv); + return get_systemPLLCLK() / bclkdiv; +} + +/* return BCLK frequency */ +ulong get_BCLK(void) +{ + return get_HCLK(); +} + +ulong get_PERCLK1(void) +{ + return get_systemPLLCLK() / (((PCDR) & 0xf)+1); +} + +ulong get_PERCLK2(void) +{ + return get_systemPLLCLK() / (((PCDR>>4) & 0xf)+1); +} + +ulong get_PERCLK3(void) +{ + return get_systemPLLCLK() / (((PCDR>>16) & 0x7f)+1); +} + +#endif /* defined (CONFIG_IMX) */
diff --git a/arch/arm/cpu/arm920t/imx/timer.c b/arch/arm/cpu/arm920t/imx/timer.c new file mode 100644 index 0000000..96fff3f --- /dev/null +++ b/arch/arm/cpu/arm920t/imx/timer.c
@@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +#include <common.h> +#if defined (CONFIG_IMX) + +#include <asm/arch/imx-regs.h> + +int timer_init (void) +{ + int i; + /* setup GP Timer 1 */ + TCTL1 = TCTL_SWR; + for ( i=0; i<100; i++) TCTL1 = 0; /* We have no udelay by now */ + TPRER1 = get_PERCLK1() / 1000000; /* 1 MHz */ + TCTL1 |= TCTL_FRR | (1<<1); /* Freerun Mode, PERCLK1 input */ + + /* Reset the timer */ + TCTL1 &= ~TCTL_TEN; + TCTL1 |= TCTL_TEN; /* Enable timer */ + + return (0); +} + +/* + * timer without interrupts + */ +static ulong get_timer_masked (void) +{ + return TCN1; +} + +ulong get_timer (ulong base) +{ + return get_timer_masked() - base; +} + +void __udelay (unsigned long usec) +{ + ulong endtime = get_timer_masked() + usec; + signed long diff; + + do { + ulong now = get_timer_masked (); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + return CONFIG_SYS_HZ; +} + +/* + * Reset the cpu by setting up the watchdog timer and let him time out + */ +void reset_cpu (ulong ignored) +{ + /* Disable watchdog and set Time-Out field to 0 */ + WCR = 0x00000000; + + /* Write Service Sequence */ + WSR = 0x00005555; + WSR = 0x0000AAAA; + + /* Enable watchdog */ + WCR = 0x00000001; + + while (1); + /*NOTREACHED*/ +} + +#endif /* defined (CONFIG_IMX) */
diff --git a/arch/arm/cpu/arm920t/start.S b/arch/arm/cpu/arm920t/start.S new file mode 100644 index 0000000..e9326f4 --- /dev/null +++ b/arch/arm/cpu/arm920t/start.S
@@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * armboot - Startup Code for ARM920 CPU-core + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + */ + +#include <asm-offsets.h> +#include <common.h> +#include <config.h> + +/* + ************************************************************************* + * + * Startup Code (called from the ARM reset exception vector) + * + * do important init only if we don't start from memory! + * relocate armboot to ram + * setup stack + * jump to second stage + * + ************************************************************************* + */ + + .globl reset + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0xd3 + msr cpsr, r0 + +#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) + /* + * relocate exception table + */ + ldr r0, =_start + ldr r1, =0x0 + mov r2, #16 +copyex: + subs r2, r2, #1 + ldr r3, [r0], #4 + str r3, [r1], #4 + bne copyex +#endif + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + mov pc, lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit: + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ + mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) + bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) + orr r0, r0, #0x00000002 @ set bit 1 (A) Align + orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache + mcr p15, 0, r0, c1, c0, 0 + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY + /* + * before relocating, we have to setup RAM timing + * because memory timing is board-dependend, you will + * find a lowlevel_init.S in your board directory. + */ + mov ip, lr + + bl lowlevel_init + mov lr, ip +#endif + mov pc, lr +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
diff --git a/arch/arm/cpu/arm926ejs/Makefile b/arch/arm/cpu/arm926ejs/Makefile new file mode 100644 index 0000000..fdb0c92 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/Makefile
@@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-y = start.o +obj-y = cpu.o cache.o + +ifdef CONFIG_SPL_BUILD +ifdef CONFIG_SPL_NO_CPU_SUPPORT_CODE +extra-y := +endif +endif + +obj-$(CONFIG_ARMADA100) += armada100/ +obj-$(if $(filter lpc32xx,$(SOC)),y) += lpc32xx/ +obj-$(CONFIG_MX25) += mx25/ +obj-$(CONFIG_MX27) += mx27/ +obj-$(if $(filter mxs,$(SOC)),y) += mxs/ +obj-$(if $(filter spear,$(SOC)),y) += spear/ + +# some files can only build in ARM or THUMB2, not THUMB1 + +ifdef CONFIG_$(SPL_)SYS_THUMB_BUILD +ifndef CONFIG_HAS_THUMB2 + +CFLAGS_cpu.o := -marm +CFLAGS_cache.o := -marm + +endif +endif
diff --git a/arch/arm/cpu/arm926ejs/armada100/Makefile b/arch/arm/cpu/arm926ejs/armada100/Makefile new file mode 100644 index 0000000..77ac0e2 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/armada100/Makefile
@@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2010 +# Marvell Semiconductor <www.marvell.com> +# Written-by: Prafulla Wadaskar <prafulla@marvell.com> + +obj-y = cpu.o timer.o dram.o
diff --git a/arch/arm/cpu/arm926ejs/armada100/cpu.c b/arch/arm/cpu/arm926ejs/armada100/cpu.c new file mode 100644 index 0000000..4cd8511 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/armada100/cpu.c
@@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * Contributor: Mahavir Jain <mjain@marvell.com> + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/armada100.h> + +#define UARTCLK14745KHZ (APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(1)) +#define SET_MRVL_ID (1<<8) +#define L2C_RAM_SEL (1<<4) + +int arch_cpu_init(void) +{ + u32 val; + struct armd1cpu_registers *cpuregs = + (struct armd1cpu_registers *) ARMD1_CPU_BASE; + + struct armd1apb1_registers *apb1clkres = + (struct armd1apb1_registers *) ARMD1_APBC1_BASE; + + struct armd1mpmu_registers *mpmu = + (struct armd1mpmu_registers *) ARMD1_MPMU_BASE; + + /* set SEL_MRVL_ID bit in ARMADA100_CPU_CONF register */ + val = readl(&cpuregs->cpu_conf); + val = val | SET_MRVL_ID; + writel(val, &cpuregs->cpu_conf); + + /* Enable Clocks for all hardware units */ + writel(0xFFFFFFFF, &mpmu->acgr); + + /* Turn on AIB and AIB-APB Functional clock */ + writel(APBC_APBCLK | APBC_FNCLK, &apb1clkres->aib); + + /* ensure L2 cache is not mapped as SRAM */ + val = readl(&cpuregs->cpu_conf); + val = val & ~(L2C_RAM_SEL); + writel(val, &cpuregs->cpu_conf); + + /* Enable GPIO clock */ + writel(APBC_APBCLK, &apb1clkres->gpio); + +#ifdef CONFIG_I2C_MV + /* Enable general I2C clock */ + writel(APBC_RST | APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi0); + writel(APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi0); + + /* Enable power I2C clock */ + writel(APBC_RST | APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi1); + writel(APBC_FNCLK | APBC_APBCLK, &apb1clkres->twsi1); +#endif + + /* + * Enable Functional and APB clock at 14.7456MHz + * for configured UART console + */ +#if (CONFIG_SYS_NS16550_COM1 == ARMD1_UART3_BASE) + writel(UARTCLK14745KHZ, &apb1clkres->uart3); +#elif (CONFIG_SYS_NS16550_COM1 == ARMD1_UART2_BASE) + writel(UARTCLK14745KHZ, &apb1clkres->uart2); +#else + writel(UARTCLK14745KHZ, &apb1clkres->uart1); +#endif + icache_enable(); + + return 0; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + u32 id; + struct armd1cpu_registers *cpuregs = + (struct armd1cpu_registers *) ARMD1_CPU_BASE; + + id = readl(&cpuregs->chip_id); + printf("SoC: Armada 88AP%X-%X\n", (id & 0xFFF), (id >> 0x10)); + return 0; +} +#endif + +#ifdef CONFIG_I2C_MV +void i2c_clk_enable(void) +{ +} +#endif
diff --git a/arch/arm/cpu/arm926ejs/armada100/dram.c b/arch/arm/cpu/arm926ejs/armada100/dram.c new file mode 100644 index 0000000..f4e1f0d --- /dev/null +++ b/arch/arm/cpu/arm926ejs/armada100/dram.c
@@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com>, + * Contributor: Mahavir Jain <mjain@marvell.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/armada100.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * ARMADA100 DRAM controller supports upto 8 banks + * for chip select 0 and 1 + */ + +/* + * DDR Memory Control Registers + * Refer Datasheet Appendix A.17 + */ +struct armd1ddr_map_registers { + u32 cs; /* Memory Address Map Register -CS */ + u32 pad[3]; +}; + +struct armd1ddr_registers { + u8 pad[0x100 - 0x000]; + struct armd1ddr_map_registers mmap[2]; +}; + +/* + * armd1_sdram_base - reads SDRAM Base Address Register + */ +u32 armd1_sdram_base(int chip_sel) +{ + struct armd1ddr_registers *ddr_regs = + (struct armd1ddr_registers *)ARMD1_DRAM_BASE; + u32 result = 0; + u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); + + if (!CS_valid) + return 0; + + result = readl(&ddr_regs->mmap[chip_sel].cs) & 0xFF800000; + return result; +} + +/* + * armd1_sdram_size - reads SDRAM size + */ +u32 armd1_sdram_size(int chip_sel) +{ + struct armd1ddr_registers *ddr_regs = + (struct armd1ddr_registers *)ARMD1_DRAM_BASE; + u32 result = 0; + u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); + + if (!CS_valid) + return 0; + + result = readl(&ddr_regs->mmap[chip_sel].cs); + result = (result >> 16) & 0xF; + if (result < 0x7) { + printf("Unknown DRAM Size\n"); + return -1; + } else { + return ((0x8 << (result - 0x7)) * 1024 * 1024); + } +} + +int dram_init(void) +{ + int i; + + gd->ram_size = 0; + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + gd->bd->bi_dram[i].start = armd1_sdram_base(i); + gd->bd->bi_dram[i].size = armd1_sdram_size(i); + /* + * It is assumed that all memory banks are consecutive + * and without gaps. + * If the gap is found, ram_size will be reported for + * consecutive memory only + */ + if (gd->bd->bi_dram[i].start != gd->ram_size) + break; + + gd->ram_size += gd->bd->bi_dram[i].size; + + } + + for (; i < CONFIG_NR_DRAM_BANKS; i++) { + /* If above loop terminated prematurely, we need to set + * remaining banks' start address & size as 0. Otherwise other + * u-boot functions and Linux kernel gets wrong values which + * could result in crash */ + gd->bd->bi_dram[i].start = 0; + gd->bd->bi_dram[i].size = 0; + } + return 0; +} + +/* + * If this function is not defined here, + * board.c alters dram bank zero configuration defined above. + */ +int dram_init_banksize(void) +{ + dram_init(); + + return 0; +}
diff --git a/arch/arm/cpu/arm926ejs/armada100/timer.c b/arch/arm/cpu/arm926ejs/armada100/timer.c new file mode 100644 index 0000000..d2ecbd0 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/armada100/timer.c
@@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * Contributor: Mahavir Jain <mjain@marvell.com> + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/armada100.h> + +/* + * Timer registers + * Refer Section A.6 in Datasheet + */ +struct armd1tmr_registers { + u32 clk_ctrl; /* Timer clk control reg */ + u32 match[9]; /* Timer match registers */ + u32 count[3]; /* Timer count registers */ + u32 status[3]; + u32 ie[3]; + u32 preload[3]; /* Timer preload value */ + u32 preload_ctrl[3]; + u32 wdt_match_en; + u32 wdt_match_r; + u32 wdt_val; + u32 wdt_sts; + u32 icr[3]; + u32 wdt_icr; + u32 cer; /* Timer count enable reg */ + u32 cmr; + u32 ilr[3]; + u32 wcr; + u32 wfar; + u32 wsar; + u32 cvwr; +}; + +#define TIMER 0 /* Use TIMER 0 */ +/* Each timer has 3 match registers */ +#define MATCH_CMP(x) ((3 * TIMER) + x) +#define TIMER_LOAD_VAL 0xffffffff +#define COUNT_RD_REQ 0x1 + +DECLARE_GLOBAL_DATA_PTR; +/* Using gd->arch.tbu from timestamp and gd->arch.tbl for lastdec */ + +/* For preventing risk of instability in reading counter value, + * first set read request to register cvwr and then read same + * register after it captures counter value. + */ +ulong read_timer(void) +{ + struct armd1tmr_registers *armd1timers = + (struct armd1tmr_registers *) ARMD1_TIMER_BASE; + volatile int loop=100; + + writel(COUNT_RD_REQ, &armd1timers->cvwr); + while (loop--); + return(readl(&armd1timers->cvwr)); +} + +static ulong get_timer_masked(void) +{ + ulong now = read_timer(); + + if (now >= gd->arch.tbl) { + /* normal mode */ + gd->arch.tbu += now - gd->arch.tbl; + } else { + /* we have an overflow ... */ + gd->arch.tbu += now + TIMER_LOAD_VAL - gd->arch.tbl; + } + gd->arch.tbl = now; + + return gd->arch.tbu; +} + +ulong get_timer(ulong base) +{ + return ((get_timer_masked() / (CONFIG_SYS_HZ_CLOCK / 1000)) - + base); +} + +void __udelay(unsigned long usec) +{ + ulong delayticks; + ulong endtime; + + delayticks = (usec * (CONFIG_SYS_HZ_CLOCK / 1000000)); + endtime = get_timer_masked() + delayticks; + + while (get_timer_masked() < endtime); +} + +/* + * init the Timer + */ +int timer_init(void) +{ + struct armd1apb1_registers *apb1clkres = + (struct armd1apb1_registers *) ARMD1_APBC1_BASE; + struct armd1tmr_registers *armd1timers = + (struct armd1tmr_registers *) ARMD1_TIMER_BASE; + + /* Enable Timer clock at 3.25 MHZ */ + writel(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3), &apb1clkres->timers); + + /* load value into timer */ + writel(0x0, &armd1timers->clk_ctrl); + /* Use Timer 0 Match Resiger 0 */ + writel(TIMER_LOAD_VAL, &armd1timers->match[MATCH_CMP(0)]); + /* Preload value is 0 */ + writel(0x0, &armd1timers->preload[TIMER]); + /* Enable match comparator 0 for Timer 0 */ + writel(0x1, &armd1timers->preload_ctrl[TIMER]); + + /* Enable timer 0 */ + writel(0x1, &armd1timers->cer); + /* init the gd->arch.tbu and gd->arch.tbl value */ + gd->arch.tbl = read_timer(); + gd->arch.tbu = 0; + + return 0; +} + +#define MPMU_APRR_WDTR (1<<4) +#define TMR_WFAR 0xbaba /* WDT Register First key */ +#define TMP_WSAR 0xeb10 /* WDT Register Second key */ + +/* + * This function uses internal Watchdog Timer + * based reset mechanism. + * Steps to write watchdog registers (protected access) + * 1. Write key value to TMR_WFAR reg. + * 2. Write key value to TMP_WSAR reg. + * 3. Perform write operation. + */ +void reset_cpu (unsigned long ignored) +{ + struct armd1mpmu_registers *mpmu = + (struct armd1mpmu_registers *) ARMD1_MPMU_BASE; + struct armd1tmr_registers *armd1timers = + (struct armd1tmr_registers *) ARMD1_TIMER_BASE; + u32 val; + + /* negate hardware reset to the WDT after system reset */ + val = readl(&mpmu->aprr); + val = val | MPMU_APRR_WDTR; + writel(val, &mpmu->aprr); + + /* reset/enable WDT clock */ + writel(APBC_APBCLK | APBC_FNCLK | APBC_RST, &mpmu->wdtpcr); + readl(&mpmu->wdtpcr); + writel(APBC_APBCLK | APBC_FNCLK, &mpmu->wdtpcr); + readl(&mpmu->wdtpcr); + + /* clear previous WDT status */ + writel(TMR_WFAR, &armd1timers->wfar); + writel(TMP_WSAR, &armd1timers->wsar); + writel(0, &armd1timers->wdt_sts); + + /* set match counter */ + writel(TMR_WFAR, &armd1timers->wfar); + writel(TMP_WSAR, &armd1timers->wsar); + writel(0xf, &armd1timers->wdt_match_r); + + /* enable WDT reset */ + writel(TMR_WFAR, &armd1timers->wfar); + writel(TMP_WSAR, &armd1timers->wsar); + writel(0x3, &armd1timers->wdt_match_en); + + while(1); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + return (ulong)CONFIG_SYS_HZ; +}
diff --git a/arch/arm/cpu/arm926ejs/cache.c b/arch/arm/cpu/arm926ejs/cache.c new file mode 100644 index 0000000..22a55f5 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/cache.c
@@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2011 + * Ilya Yanok, EmCraft Systems + */ +#include <linux/types.h> +#include <common.h> + +#ifndef CONFIG_SYS_DCACHE_OFF +void invalidate_dcache_all(void) +{ + asm volatile("mcr p15, 0, %0, c7, c6, 0\n" : : "r"(0)); +} + +void flush_dcache_all(void) +{ + asm volatile( + "0:" + "mrc p15, 0, r15, c7, c14, 3\n" + "bne 0b\n" + "mcr p15, 0, %0, c7, c10, 4\n" + : : "r"(0) : "memory" + ); +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ + if (!check_cache_range(start, stop)) + return; + + while (start < stop) { + asm volatile("mcr p15, 0, %0, c7, c6, 1\n" : : "r"(start)); + start += CONFIG_SYS_CACHELINE_SIZE; + } +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ + if (!check_cache_range(start, stop)) + return; + + while (start < stop) { + asm volatile("mcr p15, 0, %0, c7, c14, 1\n" : : "r"(start)); + start += CONFIG_SYS_CACHELINE_SIZE; + } + + asm volatile("mcr p15, 0, %0, c7, c10, 4\n" : : "r"(0)); +} +#else /* #ifndef CONFIG_SYS_DCACHE_OFF */ +void invalidate_dcache_all(void) +{ +} + +void flush_dcache_all(void) +{ +} +#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ + +/* + * Stub implementations for l2 cache operations + */ + +__weak void l2_cache_disable(void) {} + +#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) +__weak void invalidate_l2_cache(void) {} +#endif + +#ifndef CONFIG_SYS_ICACHE_OFF +/* Invalidate entire I-cache and branch predictor array */ +void invalidate_icache_all(void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (i)); +} +#else +void invalidate_icache_all(void) {} +#endif + +void enable_caches(void) +{ +#ifndef CONFIG_SYS_ICACHE_OFF + icache_enable(); +#endif +#ifndef CONFIG_SYS_DCACHE_OFF + dcache_enable(); +#endif +} +
diff --git a/arch/arm/cpu/arm926ejs/cpu.c b/arch/arm/cpu/arm926ejs/cpu.c new file mode 100644 index 0000000..c3f1ee1 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/cpu.c
@@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> + +static void cache_flush(void); + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + disable_interrupts (); + + + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + l2_cache_disable(); + + /* flush I/D-cache */ + cache_flush(); + + return 0; +} + +/* flush I/D-cache */ +static void cache_flush (void) +{ +#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); +#endif +}
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/Kconfig b/arch/arm/cpu/arm926ejs/lpc32xx/Kconfig new file mode 100644 index 0000000..1db1262 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/lpc32xx/Kconfig
@@ -0,0 +1,21 @@ +if ARCH_LPC32XX + +config SYS_SOC + default "lpc32xx" + +choice + prompt "NXP LPC32xx board select" + +config TARGET_DEVKIT3250 + bool "Timll DevKit3250" + +config TARGET_WORK_92105 + bool "Work Microwave Work_92105" + +endchoice + +source "board/timll/devkit3250/Kconfig" +source "board/work-microwave/work_92105/Kconfig" + +endif +
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/Makefile b/arch/arm/cpu/arm926ejs/lpc32xx/Makefile new file mode 100644 index 0000000..6303570 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/lpc32xx/Makefile
@@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +obj-y = cpu.o clk.o devices.o timer.o + +obj-$(CONFIG_SPL_BUILD) += dram.o lowlevel_init.o
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/clk.c b/arch/arm/cpu/arm926ejs/lpc32xx/clk.c new file mode 100644 index 0000000..5eb630d --- /dev/null +++ b/arch/arm/cpu/arm926ejs/lpc32xx/clk.c
@@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com> + */ + +#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; + + fcco = fref * m_div; + fout = fcco; + if (val & CLK_HCLK_PLL_FEEDBACK) + fcco *= p_div; + else + do_div(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(); +} + +unsigned int get_sdram_clk_rate(void) +{ + unsigned int src_clk; + + if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN)) + return get_sys_clk_rate(); + + src_clk = get_hclk_pll_rate(); + + if (readl(&clk->sdramclk_ctrl) & CLK_SDRAM_DDR_SEL) { + /* using DDR */ + switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_DDRAM_MASK) { + case CLK_HCLK_DDRAM_HALF: + return src_clk/2; + case CLK_HCLK_DDRAM_NOMINAL: + return src_clk; + default: + return 0; + } + } else { + /* using SDR */ + switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK) { + case CLK_HCLK_ARM_PLL_DIV_4: + return src_clk/4; + case CLK_HCLK_ARM_PLL_DIV_2: + return src_clk/2; + case CLK_HCLK_ARM_PLL_DIV_1: + return src_clk; + default: + return 0; + } + } +} + +int get_serial_clock(void) +{ + return get_periph_clk_rate(); +}
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c b/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c new file mode 100644 index 0000000..5117177 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c
@@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011-2015 by Vladimir Zapolskiy <vz@mleia.com> + */ + +#include <common.h> +#include <netdev.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clk.h> +#include <asm/arch/wdt.h> +#include <asm/arch/sys_proto.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); + + /* To be compatible with the original U-Boot code: + * addr: - 0: perform hard reset. + * - !=0: perform a soft reset; i.e. "RESOUT_N" not asserted). */ + if (addr == 0) { + /* 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); + } else { + /* Force match output active */ + writel(0x01, &wdt->emr); + + /* Internal reset on match output (no pulse on "RESOUT_N") */ + writel(WDTIM_MCTRL_M_RES1, &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 + +#ifdef CONFIG_LPC32XX_ETH +int cpu_eth_init(bd_t *bis) +{ + lpc32xx_eth_initialize(bis); + return 0; +} +#endif
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/devices.c b/arch/arm/cpu/arm926ejs/lpc32xx/devices.c new file mode 100644 index 0000000..7e7646a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/lpc32xx/devices.c
@@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 by Vladimir Zapolskiy <vz@mleia.com> + */ + +#include <common.h> +#include <dm.h> +#include <ns16550.h> +#include <dm/platform_data/lpc32xx_hsuart.h> + +#include <asm/arch/clk.h> +#include <asm/arch/uart.h> +#include <asm/arch/mux.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; +static struct mux_regs *mux = (struct mux_regs *)MUX_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)); +} + +#if !CONFIG_IS_ENABLED(OF_CONTROL) +static const struct ns16550_platdata lpc32xx_uart[] = { + { .base = UART3_BASE, .reg_shift = 2, + .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, + { .base = UART4_BASE, .reg_shift = 2, + .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, + { .base = UART5_BASE, .reg_shift = 2, + .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, + { .base = UART6_BASE, .reg_shift = 2, + .clock = CONFIG_SYS_NS16550_CLK, .fcr = UART_FCR_DEFVAL, }, +}; + +#if defined(CONFIG_LPC32XX_HSUART) +static const struct lpc32xx_hsuart_platdata lpc32xx_hsuart[] = { + { HS_UART1_BASE, }, + { HS_UART2_BASE, }, + { HS_UART7_BASE, }, +}; +#endif + +U_BOOT_DEVICES(lpc32xx_uarts) = { +#if defined(CONFIG_LPC32XX_HSUART) + { "lpc32xx_hsuart", &lpc32xx_hsuart[0], }, + { "lpc32xx_hsuart", &lpc32xx_hsuart[1], }, +#endif + { "ns16550_serial", &lpc32xx_uart[0], }, + { "ns16550_serial", &lpc32xx_uart[1], }, + { "ns16550_serial", &lpc32xx_uart[2], }, + { "ns16550_serial", &lpc32xx_uart[3], }, +#if defined(CONFIG_LPC32XX_HSUART) + { "lpc32xx_hsuart", &lpc32xx_hsuart[2], }, +#endif +}; +#endif + +void lpc32xx_dma_init(void) +{ + /* Enable DMA interface */ + writel(CLK_DMA_ENABLE, &clk->dmaclk_ctrl); +} + +void lpc32xx_mac_init(void) +{ + /* Enable MAC interface */ + writel(CLK_MAC_REG | CLK_MAC_SLAVE | CLK_MAC_MASTER +#if defined(CONFIG_RMII) + | CLK_MAC_RMII, +#else + | CLK_MAC_MII, +#endif + &clk->macclk_ctrl); +} + +void lpc32xx_mlc_nand_init(void) +{ + /* Enable NAND interface */ + writel(CLK_NAND_MLC | CLK_NAND_MLC_INT, &clk->flashclk_ctrl); +} + +void lpc32xx_slc_nand_init(void) +{ + /* Enable SLC NAND interface */ + writel(CLK_NAND_SLC | CLK_NAND_SLC_SELECT, &clk->flashclk_ctrl); +} + +void lpc32xx_usb_init(void) +{ + /* Do not route the UART 5 Tx/Rx pins to the USB D+ and USB D- pins. */ + clrbits_le32(&ctrl->ctrl, UART_CTRL_UART5_USB_MODE); +} + +void lpc32xx_i2c_init(unsigned int devnum) +{ + /* Enable I2C interface */ + uint32_t ctrl = readl(&clk->i2cclk_ctrl); + if (devnum == 1) + ctrl |= CLK_I2C1_ENABLE; + if (devnum == 2) + ctrl |= CLK_I2C2_ENABLE; + writel(ctrl, &clk->i2cclk_ctrl); +} + +U_BOOT_DEVICE(lpc32xx_gpios) = { + .name = "gpio_lpc32xx" +}; + +/* Mux for SCK0, MISO0, MOSI0. We do not use SSEL0. */ + +#define P_MUX_SET_SSP0 0x1600 + +void lpc32xx_ssp_init(void) +{ + /* Enable SSP0 interface */ + writel(CLK_SSP0_ENABLE_CLOCK, &clk->ssp_ctrl); + /* Mux SSP0 pins */ + writel(P_MUX_SET_SSP0, &mux->p_mux_set); +}
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/dram.c b/arch/arm/cpu/arm926ejs/lpc32xx/dram.c new file mode 100644 index 0000000..4f97569 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/lpc32xx/dram.c
@@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * LPC32xx dram init + * + * (C) Copyright 2014 DENX Software Engineering GmbH + * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr> + * + * This is called by SPL to gain access to the SDR DRAM. + * + * This code runs from SRAM. + */ + +#include <common.h> +#include <netdev.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clk.h> +#include <asm/arch/wdt.h> +#include <asm/arch/emc.h> +#include <asm/io.h> + +static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; +static struct emc_regs *emc = (struct emc_regs *)EMC_BASE; + +void ddr_init(struct emc_dram_settings *dram) +{ + uint32_t ck; + + /* Enable EMC interface and choose little endian mode */ + writel(1, &emc->ctrl); + writel(0, &emc->config); + /* Select maximum EMC Dynamic Memory Refresh Time */ + writel(0x7FF, &emc->refresh); + /* Determine CLK */ + ck = get_sdram_clk_rate(); + /* Configure SDRAM */ + writel(dram->cmddelay, &clk->sdramclk_ctrl); + writel(dram->config0, &emc->config0); + writel(dram->rascas0, &emc->rascas0); + writel(dram->rdconfig, &emc->read_config); + /* Set timings */ + writel((ck / dram->trp) & 0x0000000F, &emc->t_rp); + writel((ck / dram->tras) & 0x0000000F, &emc->t_ras); + writel((ck / dram->tsrex) & 0x0000007F, &emc->t_srex); + writel((ck / dram->twr) & 0x0000000F, &emc->t_wr); + writel((ck / dram->trc) & 0x0000001F, &emc->t_rc); + writel((ck / dram->trfc) & 0x0000001F, &emc->t_rfc); + writel((ck / dram->txsr) & 0x000000FF, &emc->t_xsr); + writel(dram->trrd, &emc->t_rrd); + writel(dram->tmrd, &emc->t_mrd); + writel(dram->tcdlr, &emc->t_cdlr); + /* Dynamic refresh */ + writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh); + udelay(10); + /* Force all clocks, enable inverted ck, issue NOP command */ + writel(0x00000193, &emc->control); + udelay(100); + /* Keep all clocks enabled, issue a PRECHARGE ALL command */ + writel(0x00000113, &emc->control); + /* Fast dynamic refresh for at least a few SDRAM ck cycles */ + writel((((128) >> 4) & 0x7FF), &emc->refresh); + udelay(10); + /* set correct dynamic refresh timing */ + writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh); + udelay(10); + /* set normal mode to CAS=3 */ + writel(0x00000093, &emc->control); + readl(EMC_DYCS0_BASE | dram->mode); + /* set extended mode to all zeroes */ + writel(0x00000093, &emc->control); + readl(EMC_DYCS0_BASE | dram->emode); + /* stop forcing clocks, keep inverted clock, issue normal mode */ + writel(0x00000010, &emc->control); +}
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S b/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S new file mode 100644 index 0000000..d42da2b --- /dev/null +++ b/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S
@@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * WORK Microwave work_92105 board low level init + * + * (C) Copyright 2014 DENX Software Engineering GmbH + * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr> + * + * Low level init is called from SPL to set up the clocks. + * On entry, the LPC3250 is in Direct Run mode with all clocks + * running at 13 MHz; on exit, ARM clock is 208 MHz, HCLK is + * 104 MHz and PCLK is 13 MHz. + * + * This code must run from SRAM so that the clock changes do + * not prevent it from executing. + */ + +.globl lowlevel_init + +lowlevel_init: + + /* Set ARM, HCLK, PCLK dividers for normal mode */ + ldr r0, =0x0000003D + ldr r1, =0x40004040 + str r0, [r1] + + /* Start HCLK PLL for 208 MHz */ + ldr r0, =0x0001401E + ldr r1, =0x40004058 + str r0, [r1] + + /* wait for HCLK PLL to lock */ +1: + ldr r0, [r1] + ands r0, r0, #1 + beq 1b + + /* switch to normal mode */ + ldr r1, =0x40004044 + ldr r0, [r1] + orr r0, #0x00000004 + str r0, [r1] + + /* Return to U-Boot via saved link register */ + mov pc, lr
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/timer.c b/arch/arm/cpu/arm926ejs/lpc32xx/timer.c new file mode 100644 index 0000000..404ccbb --- /dev/null +++ b/arch/arm/cpu/arm926ejs/lpc32xx/timer.c
@@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 Vladimir Zapolskiy <vz@mleia.com> + */ + +#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; +}
diff --git a/arch/arm/cpu/arm926ejs/mx25/Makefile b/arch/arm/cpu/arm926ejs/mx25/Makefile new file mode 100644 index 0000000..ac5ebaf --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx25/Makefile
@@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# + +obj-y += generic.o timer.o reset.o relocate.o
diff --git a/arch/arm/cpu/arm926ejs/mx25/generic.c b/arch/arm/cpu/arm926ejs/mx25/generic.c new file mode 100644 index 0000000..2795a5f --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx25/generic.c
@@ -0,0 +1,269 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2009 DENX Software Engineering + * Author: John Rigby <jrigby@gmail.com> + * + * Based on mx27/generic.c: + * Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org> + * Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com> + */ + +#include <common.h> +#include <div64.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch-imx/cpu.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> + +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> + +DECLARE_GLOBAL_DATA_PTR; +#endif + +/* + * get the system pll clock in Hz + * + * mfi + mfn / (mfd +1) + * f = 2 * f_ref * -------------------- + * pd + 1 + */ +static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref) +{ + unsigned int mfi = (pll >> CCM_PLL_MFI_SHIFT) + & CCM_PLL_MFI_MASK; + int mfn = (pll >> CCM_PLL_MFN_SHIFT) + & CCM_PLL_MFN_MASK; + unsigned int mfd = (pll >> CCM_PLL_MFD_SHIFT) + & CCM_PLL_MFD_MASK; + unsigned int pd = (pll >> CCM_PLL_PD_SHIFT) + & CCM_PLL_PD_MASK; + + mfi = mfi <= 5 ? 5 : mfi; + mfn = mfn >= 512 ? mfn - 1024 : mfn; + mfd += 1; + pd += 1; + + return lldiv(2 * (u64) f_ref * (mfi * mfd + mfn), + mfd * pd); +} + +static ulong imx_get_mpllclk(void) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong fref = MXC_HCLK; + + return imx_decode_pll(readl(&ccm->mpctl), fref); +} + +static ulong imx_get_upllclk(void) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong fref = MXC_HCLK; + + return imx_decode_pll(readl(&ccm->upctl), fref); +} + +static ulong imx_get_armclk(void) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong cctl = readl(&ccm->cctl); + ulong fref = imx_get_mpllclk(); + ulong div; + + if (cctl & CCM_CCTL_ARM_SRC) + fref = lldiv((u64) fref * 3, 4); + + div = ((cctl >> CCM_CCTL_ARM_DIV_SHIFT) + & CCM_CCTL_ARM_DIV_MASK) + 1; + + return fref / div; +} + +static ulong imx_get_ahbclk(void) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong cctl = readl(&ccm->cctl); + ulong fref = imx_get_armclk(); + ulong div; + + div = ((cctl >> CCM_CCTL_AHB_DIV_SHIFT) + & CCM_CCTL_AHB_DIV_MASK) + 1; + + return fref / div; +} + +static ulong imx_get_ipgclk(void) +{ + return imx_get_ahbclk() / 2; +} + +static ulong imx_get_perclk(int clk) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong fref = readl(&ccm->mcr) & (1 << clk) ? imx_get_upllclk() : + imx_get_ahbclk(); + ulong div; + + div = readl(&ccm->pcdr[CCM_PERCLK_REG(clk)]); + div = ((div >> CCM_PERCLK_SHIFT(clk)) & CCM_PERCLK_MASK) + 1; + + return fref / div; +} + +int imx_set_perclk(enum mxc_clock clk, bool from_upll, unsigned int freq) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong fref = from_upll ? imx_get_upllclk() : imx_get_ahbclk(); + ulong div = (fref + freq - 1) / freq; + + if (clk > MXC_UART_CLK || !div || --div > CCM_PERCLK_MASK) + return -EINVAL; + + clrsetbits_le32(&ccm->pcdr[CCM_PERCLK_REG(clk)], + CCM_PERCLK_MASK << CCM_PERCLK_SHIFT(clk), + div << CCM_PERCLK_SHIFT(clk)); + if (from_upll) + setbits_le32(&ccm->mcr, 1 << clk); + else + clrbits_le32(&ccm->mcr, 1 << clk); + return 0; +} + +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_AHB_CLK: + return imx_get_ahbclk(); + case MXC_IPG_CLK: + case MXC_CSPI_CLK: + case MXC_FEC_CLK: + return imx_get_ipgclk(); + default: + return imx_get_perclk(clk); + } +} + +u32 get_cpu_rev(void) +{ + u32 srev; + u32 system_rev = 0x25000; + + /* read SREV register from IIM module */ + struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; + srev = readl(&iim->iim_srev); + + switch (srev) { + case 0x00: + system_rev |= CHIP_REV_1_0; + break; + case 0x01: + system_rev |= CHIP_REV_1_1; + break; + case 0x02: + system_rev |= CHIP_REV_1_2; + break; + default: + system_rev |= 0x8000; + break; + } + + return system_rev; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +static char *get_reset_cause(void) +{ + /* read RCSR register from CCM module */ + struct ccm_regs *ccm = + (struct ccm_regs *)IMX_CCM_BASE; + + u32 cause = readl(&ccm->rcsr) & 0x0f; + + if (cause == 0) + return "POR"; + else if (cause == 1) + return "RST"; + else if ((cause & 2) == 2) + return "WDOG"; + else if ((cause & 4) == 4) + return "SW RESET"; + else if ((cause & 8) == 8) + return "JTAG"; + else + return "unknown reset"; + +} + +int print_cpuinfo(void) +{ + char buf[32]; + u32 cpurev = get_cpu_rev(); + + printf("CPU: Freescale i.MX25 rev%d.%d%s at %s MHz\n", + (cpurev & 0xF0) >> 4, (cpurev & 0x0F), + ((cpurev & 0x8000) ? " unknown" : ""), + strmhz(buf, imx_get_armclk())); + printf("Reset cause: %s\n", get_reset_cause()); + return 0; +} +#endif + +#if defined(CONFIG_FEC_MXC) +/* + * Initializes on-chip ethernet controllers. + * to override, implement board_eth_init() + */ +int cpu_eth_init(bd_t *bis) +{ + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + ulong val; + + val = readl(&ccm->cgr0); + val |= (1 << 23); + writel(val, &ccm->cgr0); + return fecmxc_initialize(bis); +} +#endif + +int get_clocks(void) +{ +#ifdef CONFIG_FSL_ESDHC +#if CONFIG_SYS_FSL_ESDHC_ADDR == IMX_MMC_SDHC2_BASE + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); +#else + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK); +#endif +#endif + return 0; +} + +#ifdef CONFIG_FSL_ESDHC +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init(bd_t *bis) +{ + return fsl_esdhc_mmc_init(bis); +} +#endif + +#ifdef CONFIG_FEC_MXC +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + int i; + struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; + struct fuse_bank *bank = &iim->bank[0]; + struct fuse_bank0_regs *fuse = + (struct fuse_bank0_regs *)bank->fuse_regs; + + for (i = 0; i < 6; i++) + mac[i] = readl(&fuse->mac_addr[i]) & 0xff; +} +#endif /* CONFIG_FEC_MXC */
diff --git a/arch/arm/cpu/arm926ejs/mx25/relocate.S b/arch/arm/cpu/arm926ejs/mx25/relocate.S new file mode 100644 index 0000000..709e35c --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx25/relocate.S
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * relocate - i.MX25-specific vector relocation + * + * Copyright (c) 2013 Albert ARIBAUD <albert.u.boot@aribaud.net> + */ + +#include <linux/linkage.h> + +/* + * The i.MX25 SoC is very specific with respect to exceptions: it + * does not provide RAM at the high vectors address (0xFFFF0000), + * thus only the low address (0x00000000) is useable; but that is + * in ROM, so let's avoid relocating the vectors. + */ + .section .text.relocate_vectors,"ax",%progbits + +ENTRY(relocate_vectors) + + bx lr + +ENDPROC(relocate_vectors)
diff --git a/arch/arm/cpu/arm926ejs/mx25/reset.c b/arch/arm/cpu/arm926ejs/mx25/reset.c new file mode 100644 index 0000000..576f7fa --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx25/reset.c
@@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* + * Reset the cpu by setting up the watchdog timer and let it time out + */ +void reset_cpu(ulong ignored) +{ + struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE; + /* Disable watchdog and set Time-Out field to 0 */ + writew(0, ®s->wcr); + + /* Write Service Sequence */ + writew(WSR_UNLOCK1, ®s->wsr); + writew(WSR_UNLOCK2, ®s->wsr); + + /* Enable watchdog */ + writew(WCR_WDE, ®s->wcr); + + while (1) ; +}
diff --git a/arch/arm/cpu/arm926ejs/mx25/timer.c b/arch/arm/cpu/arm926ejs/mx25/timer.c new file mode 100644 index 0000000..04698fe --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx25/timer.c
@@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> + * + * (C) Copyright 2009 DENX Software Engineering + * Author: John Rigby <jrigby@gmail.com> + * Add support for MX25 + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* nothing really to do with interrupts, just starts up a counter. */ +/* The 32KHz 32-bit timer overruns in 134217 seconds */ +int timer_init(void) +{ + int i; + struct gpt_regs *gpt = (struct gpt_regs *)IMX_GPT1_BASE; + struct ccm_regs *ccm = (struct ccm_regs *)IMX_CCM_BASE; + + /* setup GP Timer 1 */ + writel(GPT_CTRL_SWR, &gpt->ctrl); + + writel(readl(&ccm->cgr1) | CCM_CGR1_GPT1, &ccm->cgr1); + + for (i = 0; i < 100; i++) + writel(0, &gpt->ctrl); /* We have no udelay by now */ + writel(0, &gpt->pre); /* prescaler = 1 */ + /* Freerun Mode, 32KHz input */ + writel(readl(&gpt->ctrl) | GPT_CTRL_CLKSOURCE_32 | GPT_CTRL_FRR, + &gpt->ctrl); + writel(readl(&gpt->ctrl) | GPT_CTRL_TEN, &gpt->ctrl); + + return 0; +}
diff --git a/arch/arm/cpu/arm926ejs/mx27/Makefile b/arch/arm/cpu/arm926ejs/mx27/Makefile new file mode 100644 index 0000000..ac5ebaf --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx27/Makefile
@@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# + +obj-y += generic.o timer.o reset.o relocate.o
diff --git a/arch/arm/cpu/arm926ejs/mx27/generic.c b/arch/arm/cpu/arm926ejs/mx27/generic.c new file mode 100644 index 0000000..08b1b4d --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx27/generic.c
@@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org> + * Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com> + */ + +#include <common.h> +#include <div64.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/gpio.h> +#include <asm/mach-imx/sys_proto.h> +#ifdef CONFIG_MMC_MXC +#include <asm/arch/mxcmmc.h> +#endif + +/* + * get the system pll clock in Hz + * + * mfi + mfn / (mfd +1) + * f = 2 * f_ref * -------------------- + * pd + 1 + */ +static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref) +{ + unsigned int mfi = (pll >> 10) & 0xf; + unsigned int mfn = pll & 0x3ff; + unsigned int mfd = (pll >> 16) & 0x3ff; + unsigned int pd = (pll >> 26) & 0xf; + + mfi = mfi <= 5 ? 5 : mfi; + + return lldiv(2 * (u64)f_ref * (mfi * (mfd + 1) + mfn), + (mfd + 1) * (pd + 1)); +} + +static ulong clk_in_32k(void) +{ + return 1024 * CONFIG_MX27_CLK32; +} + +static ulong clk_in_26m(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + if (readl(&pll->cscr) & CSCR_OSC26M_DIV1P5) { + /* divide by 1.5 */ + return 26000000 * 2 / 3; + } else { + return 26000000; + } +} + +static ulong imx_get_mpllclk(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + ulong cscr = readl(&pll->cscr); + ulong fref; + + if (cscr & CSCR_MCU_SEL) + fref = clk_in_26m(); + else + fref = clk_in_32k(); + + return imx_decode_pll(readl(&pll->mpctl0), fref); +} + +static ulong imx_get_armclk(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + ulong cscr = readl(&pll->cscr); + ulong fref = imx_get_mpllclk(); + ulong div; + + if (!(cscr & CSCR_ARM_SRC_MPLL)) + fref = lldiv((fref * 2), 3); + + div = ((cscr >> 12) & 0x3) + 1; + + return lldiv(fref, div); +} + +static ulong imx_get_ahbclk(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + ulong cscr = readl(&pll->cscr); + ulong fref = imx_get_mpllclk(); + ulong div; + + div = ((cscr >> 8) & 0x3) + 1; + + return lldiv(fref * 2, 3 * div); +} + +static __attribute__((unused)) ulong imx_get_spllclk(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + ulong cscr = readl(&pll->cscr); + ulong fref; + + if (cscr & CSCR_SP_SEL) + fref = clk_in_26m(); + else + fref = clk_in_32k(); + + return imx_decode_pll(readl(&pll->spctl0), fref); +} + +static ulong imx_decode_perclk(ulong div) +{ + return lldiv((imx_get_mpllclk() * 2), (div * 3)); +} + +static ulong imx_get_perclk1(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + return imx_decode_perclk((readl(&pll->pcdr1) & 0x3f) + 1); +} + +static ulong imx_get_perclk2(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + return imx_decode_perclk(((readl(&pll->pcdr1) >> 8) & 0x3f) + 1); +} + +static __attribute__((unused)) ulong imx_get_perclk3(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + return imx_decode_perclk(((readl(&pll->pcdr1) >> 16) & 0x3f) + 1); +} + +static __attribute__((unused)) ulong imx_get_perclk4(void) +{ + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + return imx_decode_perclk(((readl(&pll->pcdr1) >> 24) & 0x3f) + 1); +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return imx_get_armclk(); + case MXC_I2C_CLK: + return imx_get_ahbclk()/2; + case MXC_UART_CLK: + return imx_get_perclk1(); + case MXC_FEC_CLK: + return imx_get_ahbclk(); + case MXC_ESDHC_CLK: + return imx_get_perclk2(); + } + return -1; +} + + +u32 get_cpu_rev(void) +{ + return MXC_CPU_MX27 << 12; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo (void) +{ + char buf[32]; + + printf("CPU: Freescale i.MX27 at %s MHz\n\n", + strmhz(buf, imx_get_mpllclk())); + return 0; +} +#endif + +int cpu_eth_init(bd_t *bis) +{ +#if defined(CONFIG_FEC_MXC) + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + /* enable FEC clock */ + writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); + writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0); + return fecmxc_initialize(bis); +#else + return 0; +#endif +} + +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init(bd_t *bis) +{ +#ifdef CONFIG_MMC_MXC + return mxc_mmc_init(bis); +#else + return 0; +#endif +} + +void imx_gpio_mode(int gpio_mode) +{ + struct gpio_port_regs *regs = (struct gpio_port_regs *)IMX_GPIO_BASE; + unsigned int pin = gpio_mode & GPIO_PIN_MASK; + unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT; + unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT; + unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT; + unsigned int tmp; + + /* Pullup enable */ + if (gpio_mode & GPIO_PUEN) { + writel(readl(®s->port[port].puen) | (1 << pin), + ®s->port[port].puen); + } else { + writel(readl(®s->port[port].puen) & ~(1 << pin), + ®s->port[port].puen); + } + + /* Data direction */ + if (gpio_mode & GPIO_OUT) { + writel(readl(®s->port[port].gpio_dir) | 1 << pin, + ®s->port[port].gpio_dir); + } else { + writel(readl(®s->port[port].gpio_dir) & ~(1 << pin), + ®s->port[port].gpio_dir); + } + + /* Primary / alternate function */ + if (gpio_mode & GPIO_AF) { + writel(readl(®s->port[port].gpr) | (1 << pin), + ®s->port[port].gpr); + } else { + writel(readl(®s->port[port].gpr) & ~(1 << pin), + ®s->port[port].gpr); + } + + /* use as gpio? */ + if (!(gpio_mode & (GPIO_PF | GPIO_AF))) { + writel(readl(®s->port[port].gius) | (1 << pin), + ®s->port[port].gius); + } else { + writel(readl(®s->port[port].gius) & ~(1 << pin), + ®s->port[port].gius); + } + + /* Output / input configuration */ + if (pin < 16) { + tmp = readl(®s->port[port].ocr1); + tmp &= ~(3 << (pin * 2)); + tmp |= (ocr << (pin * 2)); + writel(tmp, ®s->port[port].ocr1); + + writel(readl(®s->port[port].iconfa1) & ~(3 << (pin * 2)), + ®s->port[port].iconfa1); + writel(readl(®s->port[port].iconfa1) | aout << (pin * 2), + ®s->port[port].iconfa1); + writel(readl(®s->port[port].iconfb1) & ~(3 << (pin * 2)), + ®s->port[port].iconfb1); + writel(readl(®s->port[port].iconfb1) | bout << (pin * 2), + ®s->port[port].iconfb1); + } else { + pin -= 16; + + tmp = readl(®s->port[port].ocr2); + tmp &= ~(3 << (pin * 2)); + tmp |= (ocr << (pin * 2)); + writel(tmp, ®s->port[port].ocr2); + + writel(readl(®s->port[port].iconfa2) & ~(3 << (pin * 2)), + ®s->port[port].iconfa2); + writel(readl(®s->port[port].iconfa2) | aout << (pin * 2), + ®s->port[port].iconfa2); + writel(readl(®s->port[port].iconfb2) & ~(3 << (pin * 2)), + ®s->port[port].iconfb2); + writel(readl(®s->port[port].iconfb2) | bout << (pin * 2), + ®s->port[port].iconfb2); + } +} + +#ifdef CONFIG_MXC_UART +void mx27_uart1_init_pins(void) +{ + int i; + unsigned int mode[] = { + PE12_PF_UART1_TXD, + PE13_PF_UART1_RXD, + }; + + for (i = 0; i < ARRAY_SIZE(mode); i++) + imx_gpio_mode(mode[i]); + +} +#endif /* CONFIG_MXC_UART */ + +#ifdef CONFIG_FEC_MXC +void mx27_fec_init_pins(void) +{ + int i; + unsigned int mode[] = { + PD0_AIN_FEC_TXD0, + PD1_AIN_FEC_TXD1, + PD2_AIN_FEC_TXD2, + PD3_AIN_FEC_TXD3, + PD4_AOUT_FEC_RX_ER, + PD5_AOUT_FEC_RXD1, + PD6_AOUT_FEC_RXD2, + PD7_AOUT_FEC_RXD3, + PD8_AF_FEC_MDIO, + PD9_AIN_FEC_MDC | GPIO_PUEN, + PD10_AOUT_FEC_CRS, + PD11_AOUT_FEC_TX_CLK, + PD12_AOUT_FEC_RXD0, + PD13_AOUT_FEC_RX_DV, + PD14_AOUT_FEC_CLR, + PD15_AOUT_FEC_COL, + PD16_AIN_FEC_TX_ER, + PF23_AIN_FEC_TX_EN, + }; + + for (i = 0; i < ARRAY_SIZE(mode); i++) + imx_gpio_mode(mode[i]); +} + +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + int i; + struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; + struct fuse_bank *bank = &iim->bank[0]; + struct fuse_bank0_regs *fuse = + (struct fuse_bank0_regs *)bank->fuse_regs; + + for (i = 0; i < 6; i++) + mac[6 - 1 - i] = readl(&fuse->mac_addr[i]) & 0xff; +} +#endif /* CONFIG_FEC_MXC */ + +#ifdef CONFIG_MMC_MXC +void mx27_sd1_init_pins(void) +{ + int i; + unsigned int mode[] = { + PE18_PF_SD1_D0, + PE19_PF_SD1_D1, + PE20_PF_SD1_D2, + PE21_PF_SD1_D3, + PE22_PF_SD1_CMD, + PE23_PF_SD1_CLK, + }; + + for (i = 0; i < ARRAY_SIZE(mode); i++) + imx_gpio_mode(mode[i]); + +} + +void mx27_sd2_init_pins(void) +{ + int i; + unsigned int mode[] = { + PB4_PF_SD2_D0, + PB5_PF_SD2_D1, + PB6_PF_SD2_D2, + PB7_PF_SD2_D3, + PB8_PF_SD2_CMD, + PB9_PF_SD2_CLK, + }; + + for (i = 0; i < ARRAY_SIZE(mode); i++) + imx_gpio_mode(mode[i]); + +} +#endif /* CONFIG_MMC_MXC */
diff --git a/arch/arm/cpu/arm926ejs/mx27/relocate.S b/arch/arm/cpu/arm926ejs/mx27/relocate.S new file mode 100644 index 0000000..5dfa272 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx27/relocate.S
@@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * relocate - i.MX27-specific vector relocation + * + * Copyright (c) 2013 Albert ARIBAUD <albert.u.boot@aribaud.net> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> + +/* + * The i.MX27 SoC is very specific with respect to exceptions: it + * does not provide RAM at the high vectors address (0xFFFF0000), + * thus only the low address (0x00000000) is useable; but that is + * in ROM. Therefore, vectors cannot be changed at all. + * + * However, these ROM-based vectors actually just perform indirect + * calls through pointers located in RAM at SoC-specific addresses, + * as follows: + * + * Offset Exception Use by ROM code + * 0x00000000 reset indirect branch to [0x00000014] + * 0x00000004 undefined instruction indirect branch to [0xfffffef0] + * 0x00000008 software interrupt indirect branch to [0xfffffef4] + * 0x0000000c prefetch abort indirect branch to [0xfffffef8] + * 0x00000010 data abort indirect branch to [0xfffffefc] + * 0x00000014 (reserved in ARMv5) vector to ROM reset: 0xc0000000 + * 0x00000018 IRQ indirect branch to [0xffffff00] + * 0x0000001c FIQ indirect branch to [0xffffff04] + * + * In order to initialize exceptions on i.MX27, we must copy U-Boot's + * indirect (not exception!) vector table into 0xfffffef0..0xffffff04 + * taking care not to copy vectors number 5 (reserved exception). + */ + + .section .text.relocate_vectors,"ax",%progbits + +ENTRY(relocate_vectors) + + ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ + ldr r1, =32 /* size of vector table */ + add r0, r0, r1 /* skip to indirect table */ + ldr r1, =0xFFFFFEF0 /* i.MX27 indirect table */ + ldmia r0!, {r2-r8} /* load indirect vectors 1..7 */ + stmia r1!, {r2-r5, r7,r8} /* write all but vector 5 */ + + bx lr + +ENDPROC(relocate_vectors)
diff --git a/arch/arm/cpu/arm926ejs/mx27/reset.c b/arch/arm/cpu/arm926ejs/mx27/reset.c new file mode 100644 index 0000000..e2437d1 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx27/reset.c
@@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* + * Reset the cpu by setting up the watchdog timer and let it time out + */ +void reset_cpu(ulong ignored) +{ + struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE; + /* Disable watchdog and set Time-Out field to 0 */ + writew(0x0000, ®s->wcr); + + /* Write Service Sequence */ + writew(0x5555, ®s->wsr); + writew(0xAAAA, ®s->wsr); + + /* Enable watchdog */ + writew(WCR_WDE, ®s->wcr); + + while (1); + /*NOTREACHED*/ +}
diff --git a/arch/arm/cpu/arm926ejs/mx27/timer.c b/arch/arm/cpu/arm926ejs/mx27/timer.c new file mode 100644 index 0000000..94b5d45 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mx27/timer.c
@@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2009 + * Ilya Yanok, Emcraft Systems Ltd, <yanok@emcraft.com> + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* General purpose timers bitfields */ +#define GPTCR_SWR (1 << 15) /* Software reset */ +#define GPTCR_FRR (1 << 8) /* Freerun / restart */ +#define GPTCR_CLKSOURCE_32 (4 << 1) /* Clock source */ +#define GPTCR_TEN 1 /* Timer enable */ + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp (gd->arch.tbl) +#define lastinc (gd->arch.lastinc) + +/* + * "time" is measured in 1 / CONFIG_SYS_HZ seconds, + * "tick" is internal timer period + */ +#ifdef CONFIG_MX27_TIMER_HIGH_PRECISION +/* ~0.4% error - measured with stop-watch on 100s boot-delay */ +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, CONFIG_MX27_CLK32); + return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ + time *= CONFIG_MX27_CLK32; + do_div(time, CONFIG_SYS_HZ); + return time; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ + us = us * CONFIG_MX27_CLK32 + 999999; + do_div(us, 1000000); + return us; +} +#else +/* ~2% error */ +#define TICK_PER_TIME ((CONFIG_MX27_CLK32 + CONFIG_SYS_HZ / 2) / \ + CONFIG_SYS_HZ) +#define US_PER_TICK (1000000 / CONFIG_MX27_CLK32) + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + do_div(tick, TICK_PER_TIME); + return tick; +} + +static inline unsigned long long time_to_tick(unsigned long long time) +{ + return time * TICK_PER_TIME; +} + +static inline unsigned long long us_to_tick(unsigned long long us) +{ + us += US_PER_TICK - 1; + do_div(us, US_PER_TICK); + return us; +} +#endif + +/* nothing really to do with interrupts, just starts up a counter. */ +/* The 32768Hz 32-bit timer overruns in 131072 seconds */ +int timer_init(void) +{ + int i; + struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE; + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; + + /* setup GP Timer 1 */ + writel(GPTCR_SWR, ®s->gpt_tctl); + + writel(readl(&pll->pccr0) | PCCR0_GPT1_EN, &pll->pccr0); + writel(readl(&pll->pccr1) | PCCR1_PERCLK1_EN, &pll->pccr1); + + for (i = 0; i < 100; i++) + writel(0, ®s->gpt_tctl); /* We have no udelay by now */ + writel(0, ®s->gpt_tprer); /* 32Khz */ + /* Freerun Mode, PERCLK1 input */ + writel(readl(®s->gpt_tctl) | GPTCR_CLKSOURCE_32 | GPTCR_FRR, + ®s->gpt_tctl); + writel(readl(®s->gpt_tctl) | GPTCR_TEN, ®s->gpt_tctl); + + return 0; +} + +unsigned long long get_ticks(void) +{ + struct gpt_regs *regs = (struct gpt_regs *)IMX_TIM1_BASE; + ulong now = readl(®s->gpt_tcn); /* current tick value */ + + if (now >= lastinc) { + /* + * normal mode (non roll) + * move stamp forward with absolut diff ticks + */ + timestamp += (now - lastinc); + } else { + /* we have rollover of incrementer */ + timestamp += (0xFFFFFFFF - lastinc) + now; + } + lastinc = now; + return timestamp; +} + +static ulong get_timer_masked(void) +{ + /* + * get_ticks() returns a long long (64 bit), it wraps in + * 2^64 / CONFIG_MX27_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ + * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in + * 5 * 10^6 days - long enough. + */ + return tick_to_time(get_ticks()); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* delay x useconds AND preserve advance timstamp value */ +void __udelay(unsigned long usec) +{ + unsigned long long tmp; + ulong tmo; + + tmo = us_to_tick(usec); + tmp = get_ticks() + tmo; /* get current timestamp */ + + while (get_ticks() < tmp) /* loop till event */ + /*NOP*/; +} + +ulong get_tbclk(void) +{ + return CONFIG_MX27_CLK32; +}
diff --git a/arch/arm/cpu/arm926ejs/mxs/Makefile b/arch/arm/cpu/arm926ejs/mxs/Makefile new file mode 100644 index 0000000..f60e61e --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/Makefile
@@ -0,0 +1,81 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-$(CONFIG_SPL_BUILD) := start.o + +obj-y = clock.o mxs.o iomux.o timer.o + +ifdef CONFIG_SPL_BUILD +obj-y += spl_boot.o spl_lradc_init.o spl_mem_init.o spl_power_init.o +endif + +# Specify the target for use in elftosb call +MKIMAGE_TARGET-$(CONFIG_MX23) = mxsimage$(CONFIG_SPL_FRAMEWORK:%=-spl).mx23.cfg +MKIMAGE_TARGET-$(CONFIG_MX28) = mxsimage$(CONFIG_SPL_FRAMEWORK:%=-spl).mx28.cfg + +# Generate HAB-capable IVT +# +# Note on computing the post-IVT size field value for the U-Boot binary. +# The value is the result of adding the following: +# -> The size of U-Boot binary aligned to 64B (u-boot.bin) +# -> The size of IVT block aligned to 64B (u-boot.ivt) +# -> The size of U-Boot signature (u-boot.sig), 3904 B +# -> The 64B hole in front of U-Boot binary for 'struct mxs_spl_data' passing +# +quiet_cmd_mkivt_mxs = MXSIVT $@ +cmd_mkivt_mxs = \ + sz=`expr \`stat -c "%s" $^\` + 64 + 3904 + 128` ; \ + echo -n "0x402000d1 $2 0 0 0 $3 $4 0 $$sz 0 0 0 0 0 0 0" | \ + tr -s " " | xargs -d " " -i printf "%08x\n" "{}" | rev | \ + sed "s/\(.\)\(.\)/\\\\\\\\x\2\1\n/g" | xargs -i printf "{}" >$@ + +# Align binary to 64B +quiet_cmd_mkalign_mxs = MXSALGN $@ +cmd_mkalign_mxs = \ + dd if=$^ of=$@ ibs=64 conv=sync 2>/dev/null && \ + mv $@ $^ + +# Assemble the CSF file +quiet_cmd_mkcsfreq_mxs = MXSCSFR $@ +cmd_mkcsfreq_mxs = \ + ivt=$(word 1,$^) ; \ + bin=$(word 2,$^) ; \ + csf=$(word 3,$^) ; \ + sed "s@VENDOR@$(VENDOR)@g;s@BOARD@$(BOARD)@g" "$$csf" | \ + sed '/^\#\#Blocks/ d' > $@ ; \ + echo " Blocks = $2 0x0 `stat -c '%s' $$bin` \"$$bin\" , \\" >> $@ ; \ + echo " $3 0x0 0x40 \"$$ivt\"" >> $@ + +# Sign files +quiet_cmd_mkcst_mxs = MXSCST $@ +cmd_mkcst_mxs = cst -o $@ < $^ \ + $(if $(KBUILD_VERBOSE:1=), >/dev/null) + +spl/u-boot-spl.ivt: spl/u-boot-spl.bin + $(call if_changed,mkalign_mxs) + $(call if_changed,mkivt_mxs,$(CONFIG_SPL_TEXT_BASE),\ + 0x00008000,0x00008040) + +u-boot.ivt: u-boot.bin + $(call if_changed,mkalign_mxs) + $(call if_changed,mkivt_mxs,$(CONFIG_SYS_TEXT_BASE),\ + 0x40001000,0x40001040) + +spl/u-boot-spl.csf: spl/u-boot-spl.ivt spl/u-boot-spl.bin board/$(VENDOR)/$(BOARD)/sign/u-boot-spl.csf + $(call if_changed,mkcsfreq_mxs,$(CONFIG_SPL_TEXT_BASE),0x8000) + +u-boot.csf: u-boot.ivt u-boot.bin board/$(VENDOR)/$(BOARD)/sign/u-boot.csf + $(call if_changed,mkcsfreq_mxs,$(CONFIG_SYS_TEXT_BASE),0x40001000) + +%.sig: %.csf + $(call if_changed,mkcst_mxs) + +MKIMAGEFLAGS_u-boot.sb = -n $< -T mxsimage +u-boot.sb: $(src)/$(MKIMAGE_TARGET-y) u-boot.bin spl/u-boot-spl.bin FORCE + $(call if_changed,mkimage) + +MKIMAGEFLAGS_u-boot-signed.sb = -n $< -T mxsimage +u-boot-signed.sb: $(src)/mxsimage-signed.cfg u-boot.ivt u-boot.sig spl/u-boot-spl.ivt spl/u-boot-spl.sig FORCE + $(call if_changed,mkimage)
diff --git a/arch/arm/cpu/arm926ejs/mxs/clock.c b/arch/arm/cpu/arm926ejs/mxs/clock.c new file mode 100644 index 0000000..43d044d --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/clock.c
@@ -0,0 +1,435 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Freescale i.MX23/i.MX28 clock setup code + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * Based on code from LTIB: + * Copyright (C) 2010 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <linux/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> + +/* + * The PLL frequency is 480MHz and XTAL frequency is 24MHz + * iMX23: datasheet section 4.2 + * iMX28: datasheet section 10.2 + */ +#define PLL_FREQ_KHZ 480000 +#define PLL_FREQ_COEF 18 +#define XTAL_FREQ_KHZ 24000 + +#define PLL_FREQ_MHZ (PLL_FREQ_KHZ / 1000) +#define XTAL_FREQ_MHZ (XTAL_FREQ_KHZ / 1000) + +#if defined(CONFIG_MX23) +#define MXC_SSPCLK_MAX MXC_SSPCLK0 +#elif defined(CONFIG_MX28) +#define MXC_SSPCLK_MAX MXC_SSPCLK3 +#endif + +static uint32_t mxs_get_pclk(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + uint32_t clkctrl, clkseq, div; + uint8_t clkfrac, frac; + + clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu); + + /* No support of fractional divider calculation */ + if (clkctrl & + (CLKCTRL_CPU_DIV_XTAL_FRAC_EN | CLKCTRL_CPU_DIV_CPU_FRAC_EN)) { + return 0; + } + + clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq); + + /* XTAL Path */ + if (clkseq & CLKCTRL_CLKSEQ_BYPASS_CPU) { + div = (clkctrl & CLKCTRL_CPU_DIV_XTAL_MASK) >> + CLKCTRL_CPU_DIV_XTAL_OFFSET; + return XTAL_FREQ_MHZ / div; + } + + /* REF Path */ + clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]); + frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK; + div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK; + return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div; +} + +static uint32_t mxs_get_hclk(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + uint32_t div; + uint32_t clkctrl; + + clkctrl = readl(&clkctrl_regs->hw_clkctrl_hbus); + + /* No support of fractional divider calculation */ + if (clkctrl & CLKCTRL_HBUS_DIV_FRAC_EN) + return 0; + + div = clkctrl & CLKCTRL_HBUS_DIV_MASK; + return mxs_get_pclk() / div; +} + +static uint32_t mxs_get_emiclk(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + uint32_t clkctrl, clkseq, div; + uint8_t clkfrac, frac; + + clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq); + clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi); + + /* XTAL Path */ + if (clkseq & CLKCTRL_CLKSEQ_BYPASS_EMI) { + div = (clkctrl & CLKCTRL_EMI_DIV_XTAL_MASK) >> + CLKCTRL_EMI_DIV_XTAL_OFFSET; + return XTAL_FREQ_MHZ / div; + } + + /* REF Path */ + clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]); + frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK; + div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK; + return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div; +} + +static uint32_t mxs_get_gpmiclk(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; +#if defined(CONFIG_MX23) + uint8_t *reg = + &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]; +#elif defined(CONFIG_MX28) + uint8_t *reg = + &clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_GPMI]; +#endif + uint32_t clkctrl, clkseq, div; + uint8_t clkfrac, frac; + + clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq); + clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi); + + /* XTAL Path */ + if (clkseq & CLKCTRL_CLKSEQ_BYPASS_GPMI) { + div = clkctrl & CLKCTRL_GPMI_DIV_MASK; + return XTAL_FREQ_MHZ / div; + } + + /* REF Path */ + clkfrac = readb(reg); + frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK; + div = clkctrl & CLKCTRL_GPMI_DIV_MASK; + return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div; +} + +/* + * Set IO clock frequency, in kHz + */ +void mxs_set_ioclk(enum mxs_ioclock io, uint32_t freq) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + uint32_t div; + int io_reg; + + if (freq == 0) + return; + + if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1)) + return; + + div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq; + + if (div < 18) + div = 18; + + if (div > 35) + div = 35; + + io_reg = CLKCTRL_FRAC0_IO0 - io; /* Register order is reversed */ + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_set[io_reg]); + writeb(CLKCTRL_FRAC_CLKGATE | (div & CLKCTRL_FRAC_FRAC_MASK), + &clkctrl_regs->hw_clkctrl_frac0[io_reg]); + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_clr[io_reg]); +} + +/* + * Get IO clock, returns IO clock in kHz + */ +static uint32_t mxs_get_ioclk(enum mxs_ioclock io) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + uint8_t ret; + int io_reg; + + if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1)) + return 0; + + io_reg = CLKCTRL_FRAC0_IO0 - io; /* Register order is reversed */ + + ret = readb(&clkctrl_regs->hw_clkctrl_frac0[io_reg]) & + CLKCTRL_FRAC_FRAC_MASK; + + return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret; +} + +/* + * Configure SSP clock frequency, in kHz + */ +void mxs_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + uint32_t clk, clkreg; + + if (ssp > MXC_SSPCLK_MAX) + return; + + clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) + + (ssp * sizeof(struct mxs_register_32)); + + clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE); + while (readl(clkreg) & CLKCTRL_SSP_CLKGATE) + ; + + if (xtal) + clk = XTAL_FREQ_KHZ; + else + clk = mxs_get_ioclk(ssp >> 1); + + if (freq > clk) + return; + + /* Calculate the divider and cap it if necessary */ + clk /= freq; + if (clk > CLKCTRL_SSP_DIV_MASK) + clk = CLKCTRL_SSP_DIV_MASK; + + clrsetbits_le32(clkreg, CLKCTRL_SSP_DIV_MASK, clk); + while (readl(clkreg) & CLKCTRL_SSP_BUSY) + ; + + if (xtal) + writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp, + &clkctrl_regs->hw_clkctrl_clkseq_set); + else + writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp, + &clkctrl_regs->hw_clkctrl_clkseq_clr); +} + +/* + * Return SSP frequency, in kHz + */ +static uint32_t mxs_get_sspclk(enum mxs_sspclock ssp) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + uint32_t clkreg; + uint32_t clk, tmp; + + if (ssp > MXC_SSPCLK_MAX) + return 0; + + tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq); + if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp)) + return XTAL_FREQ_KHZ; + + clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) + + (ssp * sizeof(struct mxs_register_32)); + + tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK; + + if (tmp == 0) + return 0; + + clk = mxs_get_ioclk(ssp >> 1); + + return clk / tmp; +} + +/* + * Set SSP/MMC bus frequency, in kHz) + */ +void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq) +{ + struct mxs_ssp_regs *ssp_regs; + const enum mxs_sspclock clk = mxs_ssp_clock_by_bus(bus); + const uint32_t sspclk = mxs_get_sspclk(clk); + uint32_t reg; + uint32_t divide, rate, tgtclk; + + ssp_regs = mxs_ssp_regs_by_bus(bus); + + /* + * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)), + * CLOCK_DIVIDE has to be an even value from 2 to 254, and + * CLOCK_RATE could be any integer from 0 to 255. + */ + for (divide = 2; divide < 254; divide += 2) { + rate = sspclk / freq / divide; + if (rate <= 256) + break; + } + + tgtclk = sspclk / divide / rate; + while (tgtclk > freq) { + rate++; + tgtclk = sspclk / divide / rate; + } + if (rate > 256) + rate = 256; + + /* Always set timeout the maximum */ + reg = SSP_TIMING_TIMEOUT_MASK | + (divide << SSP_TIMING_CLOCK_DIVIDE_OFFSET) | + ((rate - 1) << SSP_TIMING_CLOCK_RATE_OFFSET); + writel(reg, &ssp_regs->hw_ssp_timing); + + debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n", + bus, tgtclk, freq); +} + +void mxs_set_lcdclk(uint32_t __maybe_unused lcd_base, uint32_t freq) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + uint32_t fp, x, k_rest, k_best, x_best, tk; + int32_t k_best_l = 999, k_best_t = 0, x_best_l = 0xff, x_best_t = 0xff; + + if (freq == 0) + return; + +#if defined(CONFIG_MX23) + writel(CLKCTRL_CLKSEQ_BYPASS_PIX, &clkctrl_regs->hw_clkctrl_clkseq_clr); +#elif defined(CONFIG_MX28) + writel(CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF, &clkctrl_regs->hw_clkctrl_clkseq_clr); +#endif + + /* + * / 18 \ 1 1 + * freq kHz = | 480000000 Hz * -- | * --- * ------ + * \ x / k 1000 + * + * 480000000 Hz 18 + * ------------ * -- + * freq kHz x + * k = ------------------- + * 1000 + */ + + fp = ((PLL_FREQ_KHZ * 1000) / freq) * 18; + + for (x = 18; x <= 35; x++) { + tk = fp / x; + if ((tk / 1000 == 0) || (tk / 1000 > 255)) + continue; + + k_rest = tk % 1000; + + if (k_rest < (k_best_l % 1000)) { + k_best_l = tk; + x_best_l = x; + } + + if (k_rest > (k_best_t % 1000)) { + k_best_t = tk; + x_best_t = x; + } + } + + if (1000 - (k_best_t % 1000) > (k_best_l % 1000)) { + k_best = k_best_l; + x_best = x_best_l; + } else { + k_best = k_best_t; + x_best = x_best_t; + } + + k_best /= 1000; + +#if defined(CONFIG_MX23) + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_PIX]); + writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK), + &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_PIX]); + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_PIX]); + + writel(CLKCTRL_PIX_CLKGATE, + &clkctrl_regs->hw_clkctrl_pix_set); + clrsetbits_le32(&clkctrl_regs->hw_clkctrl_pix, + CLKCTRL_PIX_DIV_MASK | CLKCTRL_PIX_CLKGATE, + k_best << CLKCTRL_PIX_DIV_OFFSET); + + while (readl(&clkctrl_regs->hw_clkctrl_pix) & CLKCTRL_PIX_BUSY) + ; +#elif defined(CONFIG_MX28) + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac1_set[CLKCTRL_FRAC1_PIX]); + writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK), + &clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_PIX]); + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac1_clr[CLKCTRL_FRAC1_PIX]); + + writel(CLKCTRL_DIS_LCDIF_CLKGATE, + &clkctrl_regs->hw_clkctrl_lcdif_set); + clrsetbits_le32(&clkctrl_regs->hw_clkctrl_lcdif, + CLKCTRL_DIS_LCDIF_DIV_MASK | CLKCTRL_DIS_LCDIF_CLKGATE, + k_best << CLKCTRL_DIS_LCDIF_DIV_OFFSET); + + while (readl(&clkctrl_regs->hw_clkctrl_lcdif) & CLKCTRL_DIS_LCDIF_BUSY) + ; +#endif +} + +uint32_t mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return mxs_get_pclk() * 1000000; + case MXC_GPMI_CLK: + return mxs_get_gpmiclk() * 1000000; + case MXC_AHB_CLK: + case MXC_IPG_CLK: + return mxs_get_hclk() * 1000000; + case MXC_EMI_CLK: + return mxs_get_emiclk(); + case MXC_IO0_CLK: + return mxs_get_ioclk(MXC_IOCLK0); + case MXC_IO1_CLK: + return mxs_get_ioclk(MXC_IOCLK1); + case MXC_XTAL_CLK: + return XTAL_FREQ_KHZ * 1000; + case MXC_SSP0_CLK: + return mxs_get_sspclk(MXC_SSPCLK0); +#ifdef CONFIG_MX28 + case MXC_SSP1_CLK: + return mxs_get_sspclk(MXC_SSPCLK1); + case MXC_SSP2_CLK: + return mxs_get_sspclk(MXC_SSPCLK2); + case MXC_SSP3_CLK: + return mxs_get_sspclk(MXC_SSPCLK3); +#endif + } + + return 0; +}
diff --git a/arch/arm/cpu/arm926ejs/mxs/iomux.c b/arch/arm/cpu/arm926ejs/mxs/iomux.c new file mode 100644 index 0000000..381264b --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/iomux.c
@@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2004-2006,2010 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de> + * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH, + * <armlinux@phytec.de> + */ + +#include <common.h> +#include <linux/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/iomux.h> +#include <asm/arch/imx-regs.h> + +#if defined(CONFIG_MX23) +#define DRIVE_OFFSET 0x200 +#define PULL_OFFSET 0x400 +#elif defined(CONFIG_MX28) +#define DRIVE_OFFSET 0x300 +#define PULL_OFFSET 0x600 +#else +#error "Please select CONFIG_MX23 or CONFIG_MX28" +#endif + +/* + * configures a single pad in the iomuxer + */ +int mxs_iomux_setup_pad(iomux_cfg_t pad) +{ + u32 reg, ofs, bp, bm; + void *iomux_base = (void *)MXS_PINCTRL_BASE; + struct mxs_register_32 *mxs_reg; + + /* muxsel */ + ofs = 0x100; + ofs += PAD_BANK(pad) * 0x20 + PAD_PIN(pad) / 16 * 0x10; + bp = PAD_PIN(pad) % 16 * 2; + bm = 0x3 << bp; + reg = readl(iomux_base + ofs); + reg &= ~bm; + reg |= PAD_MUXSEL(pad) << bp; + writel(reg, iomux_base + ofs); + + /* drive */ + ofs = DRIVE_OFFSET; + ofs += PAD_BANK(pad) * 0x40 + PAD_PIN(pad) / 8 * 0x10; + /* mA */ + if (PAD_MA_VALID(pad)) { + bp = PAD_PIN(pad) % 8 * 4; + bm = 0x3 << bp; + reg = readl(iomux_base + ofs); + reg &= ~bm; + reg |= PAD_MA(pad) << bp; + writel(reg, iomux_base + ofs); + } + /* vol */ + if (PAD_VOL_VALID(pad)) { + bp = PAD_PIN(pad) % 8 * 4 + 2; + mxs_reg = (struct mxs_register_32 *)(iomux_base + ofs); + if (PAD_VOL(pad)) + writel(1 << bp, &mxs_reg->reg_set); + else + writel(1 << bp, &mxs_reg->reg_clr); + } + + /* pull */ + if (PAD_PULL_VALID(pad)) { + ofs = PULL_OFFSET; + ofs += PAD_BANK(pad) * 0x10; + bp = PAD_PIN(pad); + mxs_reg = (struct mxs_register_32 *)(iomux_base + ofs); + if (PAD_PULL(pad)) + writel(1 << bp, &mxs_reg->reg_set); + else + writel(1 << bp, &mxs_reg->reg_clr); + } + + return 0; +} + +int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count) +{ + const iomux_cfg_t *p = pad_list; + int i; + int ret; + + for (i = 0; i < count; i++) { + ret = mxs_iomux_setup_pad(*p); + if (ret) + return ret; + p++; + } + + return 0; +}
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxs.c b/arch/arm/cpu/arm926ejs/mxs/mxs.c new file mode 100644 index 0000000..85c65dc --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/mxs.c
@@ -0,0 +1,284 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Freescale i.MX23/i.MX28 common code + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * Based on code from LTIB: + * Copyright (C) 2010 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <linux/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/mach-imx/dma.h> +#include <asm/arch/gpio.h> +#include <asm/arch/iomux.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> +#include <linux/compiler.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Lowlevel init isn't used on i.MX28, so just have a dummy here */ +__weak void lowlevel_init(void) {} + +void reset_cpu(ulong ignored) __attribute__((noreturn)); + +void reset_cpu(ulong ignored) +{ + struct mxs_rtc_regs *rtc_regs = + (struct mxs_rtc_regs *)MXS_RTC_BASE; + struct mxs_lcdif_regs *lcdif_regs = + (struct mxs_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); + writel(RTC_CTRL_WATCHDOGEN, &rtc_regs->hw_rtc_ctrl_set); + + /* Endless loop, reset will exit from here */ + for (;;) + ; +} + +/* + * This function will craft a jumptable at 0x0 which will redirect interrupt + * vectoring to proper location of U-Boot in RAM. + * + * The structure of the jumptable will be as follows: + * ldr pc, [pc, #0x18] ..... for each vector, thus repeated 8 times + * <destination address> ... for each previous ldr, thus also repeated 8 times + * + * The "ldr pc, [pc, #0x18]" instruction above loads address from memory at + * offset 0x18 from current value of PC register. Note that PC is already + * incremented by 4 when computing the offset, so the effective offset is + * actually 0x20, this the associated <destination address>. Loading the PC + * register with an address performs a jump to that address. + */ +void mx28_fixup_vt(uint32_t start_addr) +{ + /* ldr pc, [pc, #0x18] */ + const uint32_t ldr_pc = 0xe59ff018; + /* Jumptable location is 0x0 */ + uint32_t *vt = (uint32_t *)0x0; + int i; + + for (i = 0; i < 8; i++) { + /* cppcheck-suppress nullPointer */ + vt[i] = ldr_pc; + /* cppcheck-suppress nullPointer */ + vt[i + 8] = start_addr + (4 * i); + } +} + +#ifdef CONFIG_ARCH_MISC_INIT +int arch_misc_init(void) +{ + mx28_fixup_vt(gd->relocaddr); + return 0; +} +#endif + +int arch_cpu_init(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + extern uint32_t _start; + + mx28_fixup_vt((uint32_t)&_start); + + /* + * Enable NAND clock + */ + /* Clear bypass bit */ + writel(CLKCTRL_CLKSEQ_BYPASS_GPMI, + &clkctrl_regs->hw_clkctrl_clkseq_set); + + /* Set GPMI clock to ref_gpmi / 12 */ + clrsetbits_le32(&clkctrl_regs->hw_clkctrl_gpmi, + CLKCTRL_GPMI_CLKGATE | CLKCTRL_GPMI_DIV_MASK, 1); + + udelay(1000); + + /* + * Configure GPIO unit + */ + mxs_gpio_init(); + +#ifdef CONFIG_APBH_DMA + /* Start APBH DMA */ + mxs_dma_init(); +#endif + + return 0; +} + +u32 get_cpu_rev(void) +{ + struct mxs_digctl_regs *digctl_regs = + (struct mxs_digctl_regs *)MXS_DIGCTL_BASE; + uint8_t rev = readl(&digctl_regs->hw_digctl_chipid) & 0x000000FF; + + switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) { + case HW_DIGCTL_CHIPID_MX23: + switch (rev) { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + case 0x4: + return (MXC_CPU_MX23 << 12) | (rev + 0x10); + default: + return 0; + } + case HW_DIGCTL_CHIPID_MX28: + switch (rev) { + case 0x1: + return (MXC_CPU_MX28 << 12) | 0x12; + default: + return 0; + } + default: + return 0; + } +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +const char *get_imx_type(u32 imxtype) +{ + switch (imxtype) { + case MXC_CPU_MX23: + return "23"; + case MXC_CPU_MX28: + return "28"; + default: + return "??"; + } +} + +int print_cpuinfo(void) +{ + u32 cpurev; + struct mxs_spl_data *data = MXS_SPL_DATA; + + cpurev = get_cpu_rev(); + printf("CPU: Freescale i.MX%s rev%d.%d at %d MHz\n", + get_imx_type((cpurev & 0xFF000) >> 12), + (cpurev & 0x000F0) >> 4, + (cpurev & 0x0000F) >> 0, + mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("BOOT: %s\n", mxs_boot_modes[data->boot_mode_idx].mode); + return 0; +} +#endif + +int do_mx28_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + printf("CPU: %3d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("BUS: %3d MHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000000); + printf("EMI: %3d MHz\n", mxc_get_clock(MXC_EMI_CLK)); + printf("GPMI: %3d MHz\n", mxc_get_clock(MXC_GPMI_CLK) / 1000000); + return 0; +} + +/* + * Initializes on-chip ethernet controllers. + */ +#if defined(CONFIG_MX28) && defined(CONFIG_CMD_NET) +int cpu_eth_init(bd_t *bis) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + /* Turn on ENET clocks */ + clrbits_le32(&clkctrl_regs->hw_clkctrl_enet, + CLKCTRL_ENET_SLEEP | CLKCTRL_ENET_DISABLE); + + /* Set up ENET PLL for 50 MHz */ + /* Power on ENET PLL */ + writel(CLKCTRL_PLL2CTRL0_POWER, + &clkctrl_regs->hw_clkctrl_pll2ctrl0_set); + + udelay(10); + + /* Gate on ENET PLL */ + writel(CLKCTRL_PLL2CTRL0_CLKGATE, + &clkctrl_regs->hw_clkctrl_pll2ctrl0_clr); + + /* Enable pad output */ + setbits_le32(&clkctrl_regs->hw_clkctrl_enet, CLKCTRL_ENET_CLK_OUT_EN); + + return 0; +} +#endif + +__weak void mx28_adjust_mac(int dev_id, unsigned char *mac) +{ + mac[0] = 0x00; + mac[1] = 0x04; /* Use FSL vendor MAC address by default */ + + if (dev_id == 1) /* Let MAC1 be MAC0 + 1 by default */ + mac[5] += 1; +} + +#ifdef CONFIG_MX28_FEC_MAC_IN_OCOTP + +#define MXS_OCOTP_MAX_TIMEOUT 1000000 +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + struct mxs_ocotp_regs *ocotp_regs = + (struct mxs_ocotp_regs *)MXS_OCOTP_BASE; + uint32_t data; + + memset(mac, 0, 6); + + writel(OCOTP_CTRL_RD_BANK_OPEN, &ocotp_regs->hw_ocotp_ctrl_set); + + if (mxs_wait_mask_clr(&ocotp_regs->hw_ocotp_ctrl_reg, OCOTP_CTRL_BUSY, + MXS_OCOTP_MAX_TIMEOUT)) { + printf("MXS FEC: Can't get MAC from OCOTP\n"); + return; + } + + data = readl(&ocotp_regs->hw_ocotp_cust0); + + mac[2] = (data >> 24) & 0xff; + mac[3] = (data >> 16) & 0xff; + mac[4] = (data >> 8) & 0xff; + mac[5] = data & 0xff; + mx28_adjust_mac(dev_id, mac); +} +#else +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + memset(mac, 0, 6); +} +#endif + +int mxs_dram_init(void) +{ + struct mxs_spl_data *data = MXS_SPL_DATA; + + if (data->mem_dram_size == 0) { + printf("MXS:\n" + "Error, the RAM size passed up from SPL is 0!\n"); + hang(); + } + + gd->ram_size = data->mem_dram_size; + return 0; +} + +U_BOOT_CMD( + clocks, CONFIG_SYS_MAXARGS, 1, do_mx28_showclocks, + "display clocks", + "" +);
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxs_init.h b/arch/arm/cpu/arm926ejs/mxs/mxs_init.h new file mode 100644 index 0000000..062deb7 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/mxs_init.h
@@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Freescale i.MX28 SPL functions + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + */ + +#ifndef __M28_INIT_H__ +#define __M28_INIT_H__ + +void early_delay(int delay); + +void mxs_power_init(void); + +#ifdef CONFIG_SPL_MXS_PSWITCH_WAIT +void mxs_power_wait_pswitch(void); +#else +static inline void mxs_power_wait_pswitch(void) { } +#endif + +void mxs_mem_init(void); +uint32_t mxs_mem_get_size(void); + +void mxs_lradc_init(void); +void mxs_lradc_enable_batt_measurement(void); + +#endif /* __M28_INIT_H__ */
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxsimage-signed.cfg b/arch/arm/cpu/arm926ejs/mxs/mxsimage-signed.cfg new file mode 100644 index 0000000..83953da --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/mxsimage-signed.cfg
@@ -0,0 +1,11 @@ +DISPLAYPROGRESS +SECTION 0x0 BOOTABLE + TAG LAST + LOAD 0x1000 spl/u-boot-spl.bin + LOAD 0x8000 spl/u-boot-spl.ivt + LOAD 0x8040 spl/u-boot-spl.sig + CALL HAB 0x8000 0x0 + LOAD 0x40002000 u-boot.bin + LOAD 0x40001000 u-boot.ivt + LOAD 0x40001040 u-boot.sig + CALL HAB 0x40001000 0x0
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx23.cfg b/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx23.cfg new file mode 100644 index 0000000..ab2183e --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx23.cfg
@@ -0,0 +1,5 @@ +DISPLAYPROGRESS +SECTION 0x0 BOOTABLE + TAG LAST + LOAD 0x1000 spl/u-boot-spl.bin + CALL 0x1000 0x0
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx28.cfg b/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx28.cfg new file mode 100644 index 0000000..0d95064 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/mxsimage-spl.mx28.cfg
@@ -0,0 +1,6 @@ +DISPLAYPROGRESS +SECTION 0x0 BOOTABLE + TAG LAST + LOAD 0x1000 spl/u-boot-spl.bin + LOAD IVT 0x8000 0x1000 + CALL HAB 0x8000 0x0
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx23.cfg b/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx23.cfg new file mode 100644 index 0000000..e702809 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx23.cfg
@@ -0,0 +1,7 @@ +DISPLAYPROGRESS +SECTION 0x0 BOOTABLE + TAG LAST + LOAD 0x1000 spl/u-boot-spl.bin + CALL 0x1000 0x0 + LOAD 0x40002000 u-boot.bin + CALL 0x40002000 0x0
diff --git a/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx28.cfg b/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx28.cfg new file mode 100644 index 0000000..3f7bf59 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/mxsimage.mx28.cfg
@@ -0,0 +1,9 @@ +DISPLAYPROGRESS +SECTION 0x0 BOOTABLE + TAG LAST + LOAD 0x1000 spl/u-boot-spl.bin + LOAD IVT 0x8000 0x1000 + CALL HAB 0x8000 0x0 + LOAD 0x40002000 u-boot.bin + LOAD IVT 0x8000 0x40002000 + CALL HAB 0x8000 0x0
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_boot.c b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c new file mode 100644 index 0000000..cb361ac --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/spl_boot.c
@@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Freescale i.MX28 Boot setup + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> +#include <asm/gpio.h> +#include <linux/compiler.h> + +#include "mxs_init.h" + +DECLARE_GLOBAL_DATA_PTR; +static gd_t gdata __section(".data"); +#ifdef CONFIG_SPL_SERIAL_SUPPORT +static bd_t bdata __section(".data"); +#endif + +/* + * This delay function is intended to be used only in early stage of boot, where + * clock are not set up yet. The timer used here is reset on every boot and + * takes a few seconds to roll. The boot doesn't take that long, so to keep the + * code simple, it doesn't take rolling into consideration. + */ +void early_delay(int delay) +{ + struct mxs_digctl_regs *digctl_regs = + (struct mxs_digctl_regs *)MXS_DIGCTL_BASE; + + uint32_t st = readl(&digctl_regs->hw_digctl_microseconds); + st += delay; + while (st > readl(&digctl_regs->hw_digctl_microseconds)) + ; +} + +#if defined(CONFIG_MX23) +#define MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL) +static const iomux_cfg_t iomux_boot[] = { + MX23_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD, + MX23_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD, + MX23_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD, + MX23_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD, + MX23_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD, + MX23_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD, +}; +#endif + +static uint8_t mxs_get_bootmode_index(void) +{ + uint8_t bootmode = 0; + int i; + uint8_t masked; + +#if defined(CONFIG_MX23) + /* 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(MX23_PAD_LCD_D00__GPIO_1_0); + gpio_direction_input(MX23_PAD_LCD_D01__GPIO_1_1); + gpio_direction_input(MX23_PAD_LCD_D02__GPIO_1_2); + gpio_direction_input(MX23_PAD_LCD_D03__GPIO_1_3); + gpio_direction_input(MX23_PAD_LCD_D05__GPIO_1_5); + + /* Read bootmode pads */ + bootmode |= (gpio_get_value(MX23_PAD_LCD_D00__GPIO_1_0) ? 1 : 0) << 0; + bootmode |= (gpio_get_value(MX23_PAD_LCD_D01__GPIO_1_1) ? 1 : 0) << 1; + bootmode |= (gpio_get_value(MX23_PAD_LCD_D02__GPIO_1_2) ? 1 : 0) << 2; + bootmode |= (gpio_get_value(MX23_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3; + bootmode |= (gpio_get_value(MX23_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5; +#elif defined(CONFIG_MX28) + /* The global boot mode will be detected by ROM code and its value + * is stored at the fixed address 0x00019BF0 in OCRAM. + */ +#define GLOBAL_BOOT_MODE_ADDR 0x00019BF0 + bootmode = __raw_readl(GLOBAL_BOOT_MODE_ADDR); +#endif + + for (i = 0; i < ARRAY_SIZE(mxs_boot_modes); i++) { + masked = bootmode & mxs_boot_modes[i].boot_mask; + if (masked == mxs_boot_modes[i].boot_pads) + break; + } + + return i; +} + +static void mxs_spl_fixup_vectors(void) +{ + /* + * Copy our vector table to 0x0, since due to HAB, we cannot + * be loaded to 0x0. We want to have working vectoring though, + * thus this fixup. Our vectoring table is PIC, so copying is + * fine. + */ + extern uint32_t _start; + + /* cppcheck-suppress nullPointer */ + memcpy(0x0, &_start, 0x60); +} + +static void mxs_spl_console_init(void) +{ +#ifdef CONFIG_SPL_SERIAL_SUPPORT + gd->bd = &bdata; + gd->baudrate = CONFIG_BAUDRATE; + serial_init(); + gd->have_console = 1; +#endif +} + +void mxs_common_spl_init(const uint32_t arg, const uint32_t *resptr, + const iomux_cfg_t *iomux_setup, + const unsigned int iomux_size) +{ + struct mxs_spl_data *data = MXS_SPL_DATA; + uint8_t bootmode = mxs_get_bootmode_index(); + gd = &gdata; + + mxs_spl_fixup_vectors(); + + mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size); + + mxs_spl_console_init(); + debug("SPL: Serial Console Initialised\n"); + + mxs_power_init(); + + mxs_mem_init(); + data->mem_dram_size = mxs_mem_get_size(); + + data->boot_mode_idx = bootmode; + + mxs_power_wait_pswitch(); + + if (mxs_boot_modes[data->boot_mode_idx].boot_pads == MXS_BM_JTAG) { + debug("SPL: Waiting for JTAG user\n"); + asm volatile ("x: b x"); + } +} + +#ifndef CONFIG_SPL_FRAMEWORK +/* Support aparatus */ +inline void board_init_f(unsigned long bootflag) +{ + for (;;) + ; +} + +inline void board_init_r(gd_t *id, ulong dest_addr) +{ + for (;;) + ; +} +#endif
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c new file mode 100644 index 0000000..cfd6c4a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/spl_lradc_init.c
@@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Freescale i.MX28 Battery measurement init + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +#include "mxs_init.h" + +void mxs_lradc_init(void) +{ + struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE; + + debug("SPL: Initialisating LRADC\n"); + + 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 mxs_lradc_enable_batt_measurement(void) +{ + struct mxs_lradc_regs *regs = (struct mxs_lradc_regs *)MXS_LRADC_BASE; + + debug("SPL: Enabling LRADC battery measurement\n"); + + /* Check if the channel is present at all. */ + if (!(readl(®s->hw_lradc_status) & LRADC_STATUS_CHANNEL7_PRESENT)) { + debug("SPL: LRADC channel 7 is not present - aborting\n"); + return; + } + + debug("SPL: LRADC channel 7 is present - configuring\n"); + + 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); + + debug("SPL: LRADC channel 7 configuration complete\n"); +}
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c new file mode 100644 index 0000000..7818d72 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
@@ -0,0 +1,359 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Freescale i.MX28 RAM init + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> +#include <linux/compiler.h> + +#include "mxs_init.h" + +__weak uint32_t mxs_dram_vals[] = { +/* + * i.MX28 DDR2 at 200MHz + */ +#if defined(CONFIG_MX28) + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000100, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00010101, 0x01010101, + 0x000f0f01, 0x0f02020a, 0x00000000, 0x00010101, + 0x00000100, 0x00000100, 0x00000000, 0x00000002, + 0x01010000, 0x07080403, 0x06005003, 0x0a0000c8, + 0x02009c40, 0x0002030c, 0x0036a609, 0x031a0612, + 0x02030202, 0x00c8001c, 0x00000000, 0x00000000, + 0x00012100, 0xffff0303, 0x00012100, 0xffff0303, + 0x00012100, 0xffff0303, 0x00012100, 0xffff0303, + 0x00000003, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000612, 0x01000F02, + 0x06120612, 0x00000200, 0x00020007, 0xf4004a27, + 0xf4004a27, 0xf4004a27, 0xf4004a27, 0x07000300, + 0x07000300, 0x07400300, 0x07400300, 0x00000005, + 0x00000000, 0x00000000, 0x01000000, 0x01020408, + 0x08040201, 0x000f1133, 0x00000000, 0x00001f04, + 0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04, + 0x00001f04, 0x00001f04, 0x00001f04, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00010000, 0x00030404, + 0x00000003, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x01010000, + 0x01000000, 0x03030000, 0x00010303, 0x01020202, + 0x00000000, 0x02040303, 0x21002103, 0x00061200, + 0x06120612, 0x04420442, 0x04420442, 0x00040004, + 0x00040004, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xffffffff + +/* + * i.MX23 DDR at 133MHz + */ +#elif defined(CONFIG_MX23) + 0x01010001, 0x00010100, 0x01000101, 0x00000001, + 0x00000101, 0x00000000, 0x00010000, 0x01000001, + 0x00000000, 0x00000001, 0x07000200, 0x00070202, + 0x02020000, 0x04040a01, 0x00000201, 0x02040000, + 0x02000000, 0x19000f08, 0x0d0d0000, 0x02021313, + 0x02061521, 0x0000000a, 0x00080008, 0x00200020, + 0x00200020, 0x00200020, 0x000003f7, 0x00000000, + 0x00000000, 0x00000020, 0x00000020, 0x00c80000, + 0x000a23cd, 0x000000c8, 0x00006665, 0x00000000, + 0x00000101, 0x00040001, 0x00000000, 0x00000000, + 0x00010000 +#else +#error Unsupported memory initialization +#endif +}; + +__weak void mxs_adjust_memory_params(uint32_t *dram_vals) +{ + debug("SPL: Using default SDRAM parameters\n"); +} + +#ifdef CONFIG_MX28 +static void initialize_dram_values(void) +{ + int i; + + debug("SPL: Setting mx28 board specific SDRAM parameters\n"); + mxs_adjust_memory_params(mxs_dram_vals); + + debug("SPL: Applying SDRAM parameters\n"); + for (i = 0; i < ARRAY_SIZE(mxs_dram_vals); i++) + writel(mxs_dram_vals[i], MXS_DRAM_BASE + (4 * i)); +} +#else +static void initialize_dram_values(void) +{ + int i; + + debug("SPL: Setting mx23 board specific SDRAM parameters\n"); + mxs_adjust_memory_params(mxs_dram_vals); + + /* + * HW_DRAM_CTL27, HW_DRAM_CTL28 and HW_DRAM_CTL35 are not initialized as + * per FSL bootlets code. + * + * mx23 Reference Manual marks HW_DRAM_CTL27 and HW_DRAM_CTL28 as + * "reserved". + * HW_DRAM_CTL8 is setup as the last element. + * So skip the initialization of these HW_DRAM_CTL registers. + */ + debug("SPL: Applying SDRAM parameters\n"); + for (i = 0; i < ARRAY_SIZE(mxs_dram_vals); i++) { + if (i == 8 || i == 27 || i == 28 || i == 35) + continue; + writel(mxs_dram_vals[i], MXS_DRAM_BASE + (4 * i)); + } + + /* + * Enable tRAS lockout in HW_DRAM_CTL08 ; it must be the last + * element to be set + */ + writel((1 << 24), MXS_DRAM_BASE + (4 * 8)); +} +#endif + +static void mxs_mem_init_clock(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; +#if defined(CONFIG_MX23) + /* Fractional divider for ref_emi is 33 ; 480 * 18 / 33 = 266MHz */ + const unsigned char divider = 33; +#elif defined(CONFIG_MX28) + /* Fractional divider for ref_emi is 21 ; 480 * 18 / 21 = 411MHz */ + const unsigned char divider = 21; +#endif + + debug("SPL: Initialising FRAC0\n"); + + /* Gate EMI clock */ + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]); + + /* Set fractional divider for ref_emi */ + writeb(CLKCTRL_FRAC_CLKGATE | (divider & CLKCTRL_FRAC_FRAC_MASK), + &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]); + + /* Ungate EMI clock */ + writeb(CLKCTRL_FRAC_CLKGATE, + &clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_EMI]); + + early_delay(11000); + + /* Set EMI clock divider for EMI clock to 411 / 2 = 205MHz */ + writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) | + (1 << CLKCTRL_EMI_DIV_XTAL_OFFSET), + &clkctrl_regs->hw_clkctrl_emi); + + /* Unbypass EMI */ + writel(CLKCTRL_CLKSEQ_BYPASS_EMI, + &clkctrl_regs->hw_clkctrl_clkseq_clr); + + early_delay(10000); + debug("SPL: FRAC0 Initialised\n"); +} + +static void mxs_mem_setup_cpu_and_hbus(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + debug("SPL: Setting CPU and HBUS clock frequencies\n"); + + /* Set fractional divider for ref_cpu to 480 * 18 / 19 = 454MHz + * and ungate CPU clock */ + writeb(19 & CLKCTRL_FRAC_FRAC_MASK, + (uint8_t *)&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]); + + /* Set CPU bypass */ + writel(CLKCTRL_CLKSEQ_BYPASS_CPU, + &clkctrl_regs->hw_clkctrl_clkseq_set); + + /* HBUS = 151MHz */ + writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set); + writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK, + &clkctrl_regs->hw_clkctrl_hbus_clr); + + early_delay(10000); + + /* CPU clock divider = 1 */ + clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu, + CLKCTRL_CPU_DIV_CPU_MASK, 1); + + /* Disable CPU bypass */ + writel(CLKCTRL_CLKSEQ_BYPASS_CPU, + &clkctrl_regs->hw_clkctrl_clkseq_clr); + + early_delay(15000); +} + +static void mxs_mem_setup_vdda(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Configuring VDDA\n"); + + writel((0xc << POWER_VDDACTRL_TRG_OFFSET) | + (0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) | + POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW, + &power_regs->hw_power_vddactrl); +} + +uint32_t mxs_mem_get_size(void) +{ + uint32_t sz, da; + uint32_t *vt = (uint32_t *)0x20; + /* The following is "subs pc, r14, #4", used as return from DABT. */ + const uint32_t data_abort_memdetect_handler = 0xe25ef004; + + /* Replace the DABT handler. */ + da = vt[4]; + vt[4] = data_abort_memdetect_handler; + + sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE); + + /* Restore the old DABT handler. */ + vt[4] = da; + + return sz; +} + +#ifdef CONFIG_MX23 +static void mx23_mem_setup_vddmem(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Setting mx23 VDDMEM\n"); + + /* We must wait before and after disabling the current limiter! */ + early_delay(10000); + + clrbits_le32(&power_regs->hw_power_vddmemctrl, + POWER_VDDMEMCTRL_ENABLE_ILIMIT); + + early_delay(10000); + +} + +static void mx23_mem_init(void) +{ + debug("SPL: Initialising mx23 SDRAM Controller\n"); + + /* + * Reset/ungate the EMI block. This is essential, otherwise the system + * suffers from memory instability. This thing is mx23 specific and is + * no longer present on mx28. + */ + mxs_reset_block((struct mxs_register_32 *)MXS_EMI_BASE); + + mx23_mem_setup_vddmem(); + + /* + * Configure the DRAM registers + */ + + /* Clear START and SREFRESH bit from DRAM_CTL8 */ + clrbits_le32(MXS_DRAM_BASE + 0x20, (1 << 16) | (1 << 8)); + + initialize_dram_values(); + + /* Set START bit in DRAM_CTL8 */ + setbits_le32(MXS_DRAM_BASE + 0x20, 1 << 16); + + clrbits_le32(MXS_DRAM_BASE + 0x40, 1 << 17); + + /* Wait for EMI_STAT bit DRAM_HALTED */ + for (;;) { + if (!(readl(MXS_EMI_BASE + 0x10) & (1 << 1))) + break; + early_delay(1000); + } + + /* Adjust EMI port priority. */ + clrsetbits_le32(0x80020000, 0x1f << 16, 0x2); + early_delay(20000); + + setbits_le32(MXS_DRAM_BASE + 0x40, 1 << 19); + setbits_le32(MXS_DRAM_BASE + 0x40, 1 << 11); +} +#endif + +#ifdef CONFIG_MX28 +static void mx28_mem_init(void) +{ + struct mxs_pinctrl_regs *pinctrl_regs = + (struct mxs_pinctrl_regs *)MXS_PINCTRL_BASE; + + debug("SPL: Initialising mx28 SDRAM Controller\n"); + + /* Set DDR2 mode */ + writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2, + &pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set); + + /* + * Configure the DRAM registers + */ + + /* Clear START bit from DRAM_CTL16 */ + clrbits_le32(MXS_DRAM_BASE + 0x40, 1); + + initialize_dram_values(); + + /* Clear SREFRESH bit from DRAM_CTL17 */ + clrbits_le32(MXS_DRAM_BASE + 0x44, 1); + + /* Set START bit in DRAM_CTL16 */ + setbits_le32(MXS_DRAM_BASE + 0x40, 1); + + /* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */ + while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20))) + ; +} +#endif + +void mxs_mem_init(void) +{ + early_delay(11000); + + mxs_mem_init_clock(); + + mxs_mem_setup_vdda(); + +#if defined(CONFIG_MX23) + mx23_mem_init(); +#elif defined(CONFIG_MX28) + mx28_mem_init(); +#endif + + early_delay(10000); + + mxs_mem_setup_cpu_and_hbus(); +}
diff --git a/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c new file mode 100644 index 0000000..a5c528a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
@@ -0,0 +1,1289 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Freescale i.MX28 Boot PMIC init + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +#include "mxs_init.h" + +#ifdef CONFIG_SYS_MXS_VDD5V_ONLY +#define DCDC4P2_DROPOUT_CONFIG POWER_DCDC4P2_DROPOUT_CTRL_100MV | \ + POWER_DCDC4P2_DROPOUT_CTRL_SRC_4P2 +#else +#define DCDC4P2_DROPOUT_CONFIG POWER_DCDC4P2_DROPOUT_CTRL_100MV | \ + POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL +#endif +/** + * mxs_power_clock2xtal() - Switch CPU core clock source to 24MHz XTAL + * + * This function switches the CPU core clock from PLL to 24MHz XTAL + * oscilator. This is necessary if the PLL is being reconfigured to + * prevent crash of the CPU core. + */ +static void mxs_power_clock2xtal(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + debug("SPL: Switching CPU clock to 24MHz XTAL\n"); + + /* Set XTAL as CPU reference clock */ + writel(CLKCTRL_CLKSEQ_BYPASS_CPU, + &clkctrl_regs->hw_clkctrl_clkseq_set); +} + +/** + * mxs_power_clock2pll() - Switch CPU core clock source to PLL + * + * This function switches the CPU core clock from 24MHz XTAL oscilator + * to PLL. This can only be called once the PLL has re-locked and once + * the PLL is stable after reconfiguration. + */ +static void mxs_power_clock2pll(void) +{ + struct mxs_clkctrl_regs *clkctrl_regs = + (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; + + debug("SPL: Switching CPU core clock source to PLL\n"); + + /* + * TODO: Are we really? It looks like we turn on PLL0, but we then + * set the CLKCTRL_CLKSEQ_BYPASS_CPU bit of the (which was already + * set by mxs_power_clock2xtal()). Clearing this bit here seems to + * introduce some instability (causing the CPU core to hang). Maybe + * we aren't giving PLL0 enough time to stabilise? + */ + setbits_le32(&clkctrl_regs->hw_clkctrl_pll0ctrl0, + CLKCTRL_PLL0CTRL0_POWER); + early_delay(100); + + /* + * TODO: Should the PLL0 FORCE_LOCK bit be set here followed be a + * wait on the PLL0 LOCK bit? + */ + setbits_le32(&clkctrl_regs->hw_clkctrl_clkseq, + CLKCTRL_CLKSEQ_BYPASS_CPU); +} + +/** + * mxs_power_set_auto_restart() - Set the auto-restart bit + * + * This function ungates the RTC block and sets the AUTO_RESTART + * bit to work around a design bug on MX28EVK Rev. A . + */ + +static void mxs_power_set_auto_restart(void) +{ + struct mxs_rtc_regs *rtc_regs = + (struct mxs_rtc_regs *)MXS_RTC_BASE; + + debug("SPL: Setting auto-restart bit\n"); + + writel(RTC_CTRL_SFTRST, &rtc_regs->hw_rtc_ctrl_clr); + while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_SFTRST) + ; + + writel(RTC_CTRL_CLKGATE, &rtc_regs->hw_rtc_ctrl_clr); + while (readl(&rtc_regs->hw_rtc_ctrl) & RTC_CTRL_CLKGATE) + ; + + /* Do nothing if flag already set */ + if (readl(&rtc_regs->hw_rtc_persistent0) & RTC_PERSISTENT0_AUTO_RESTART) + return; + + while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK) + ; + + setbits_le32(&rtc_regs->hw_rtc_persistent0, + RTC_PERSISTENT0_AUTO_RESTART); + writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_set); + writel(RTC_CTRL_FORCE_UPDATE, &rtc_regs->hw_rtc_ctrl_clr); + while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_NEW_REGS_MASK) + ; + while (readl(&rtc_regs->hw_rtc_stat) & RTC_STAT_STALE_REGS_MASK) + ; +} + +/** + * mxs_power_set_linreg() - Set linear regulators 25mV below DC-DC converter + * + * This function configures the VDDIO, VDDA and VDDD linear regulators output + * to be 25mV below the VDDIO, VDDA and VDDD output from the DC-DC switching + * converter. This is the recommended setting for the case where we use both + * linear regulators and DC-DC converter to power the VDDIO rail. + */ +static void mxs_power_set_linreg(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + /* Set linear regulator 25mV below switching converter */ + debug("SPL: Setting VDDD 25mV below DC-DC converters\n"); + clrsetbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_LINREG_OFFSET_MASK, + POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW); + + debug("SPL: Setting VDDA 25mV below DC-DC converters\n"); + clrsetbits_le32(&power_regs->hw_power_vddactrl, + POWER_VDDACTRL_LINREG_OFFSET_MASK, + POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW); + + debug("SPL: Setting VDDIO 25mV below DC-DC converters\n"); + clrsetbits_le32(&power_regs->hw_power_vddioctrl, + POWER_VDDIOCTRL_LINREG_OFFSET_MASK, + POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW); +} + +/** + * mxs_get_batt_volt() - Measure battery input voltage + * + * This function retrieves the battery input voltage and returns it. + */ +static int mxs_get_batt_volt(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_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; + + debug("SPL: Battery Voltage = %dmV\n", volt); + return volt; +} + +/** + * mxs_is_batt_ready() - Test if the battery provides enough voltage to boot + * + * This function checks if the battery input voltage is higher than 3.6V and + * therefore allows the system to successfully boot using this power source. + */ +static int mxs_is_batt_ready(void) +{ + return (mxs_get_batt_volt() >= 3600); +} + +/** + * mxs_is_batt_good() - Test if battery is operational at all + * + * This function starts recharging the battery and tests if the input current + * provided by the 5V input recharging the battery is also sufficient to power + * the DC-DC converter. + */ +static int mxs_is_batt_good(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t volt = mxs_get_batt_volt(); + + if ((volt >= 2400) && (volt <= 4300)) { + debug("SPL: Battery is good\n"); + 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 = mxs_get_batt_volt(); + + if (volt >= 3500) { + debug("SPL: Battery Voltage too high\n"); + return 0; + } + + if (volt >= 2400) { + debug("SPL: Battery is good\n"); + 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); + + debug("SPL: Battery Voltage too low\n"); + return 0; +} + +/** + * mxs_power_setup_5v_detect() - Start the 5V input detection comparator + * + * This function enables the 5V detection comparator and sets the 5V valid + * threshold to 4.4V . We use 4.4V threshold here to make sure that even + * under high load, the voltage drop on the 5V input won't be so critical + * to cause undervolt on the 4P2 linear regulator supplying the DC-DC + * converter and thus making the system crash. + */ +static void mxs_power_setup_5v_detect(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + /* Start 5V detection */ + debug("SPL: Starting 5V input detection comparator\n"); + clrsetbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_VBUSVALID_TRSH_MASK, + POWER_5VCTRL_VBUSVALID_TRSH_4V4 | + POWER_5VCTRL_PWRUP_VBUS_CMPS); +} + +/** + * mxs_power_switch_dcdc_clocksource() - Switch PLL clock for DC-DC converters + * @freqsel: One of the POWER_MISC_FREQSEL_xxx defines to select the clock + * + * This function configures and then enables an alternative PLL clock source + * for the DC-DC converters. + */ +void mxs_power_switch_dcdc_clocksource(uint32_t freqsel) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + /* Select clocksource for DC-DC converters */ + clrsetbits_le32(&power_regs->hw_power_misc, + POWER_MISC_FREQSEL_MASK, + freqsel); + setbits_le32(&power_regs->hw_power_misc, + POWER_MISC_SEL_PLLCLK); +} + +/** + * mxs_power_setup_dcdc_clocksource() - Setup PLL clock source for DC-DC converters + * + * Normally, there is no need to switch DC-DC clocksource. This is the reason, + * why this function is a stub and does nothing. However, boards can implement + * this function when required and call mxs_power_switch_dcdc_clocksource() to + * switch to an alternative clock source. + */ +__weak void mxs_power_setup_dcdc_clocksource(void) +{ + debug("SPL: Using default DC-DC clocksource\n"); +} + +/** + * mxs_src_power_init() - Preconfigure the power block + * + * This function configures reasonable values for the DC-DC control loop + * and battery monitor. + */ +static void mxs_src_power_init(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Pre-Configuring power block\n"); + + /* Improve efficieny and reduce transient ripple */ + writel(POWER_LOOPCTRL_TOGGLE_DIF | POWER_LOOPCTRL_EN_CM_HYST | + POWER_LOOPCTRL_EN_DF_HYST, &power_regs->hw_power_loopctrl_set); + + clrsetbits_le32(&power_regs->hw_power_dclimits, + POWER_DCLIMITS_POSLIMIT_BUCK_MASK, + 0x30 << POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET); + + setbits_le32(&power_regs->hw_power_battmonitor, + POWER_BATTMONITOR_EN_BATADJ); + + /* Increase the RCSCALE level for quick DCDC response to dynamic load */ + clrsetbits_le32(&power_regs->hw_power_loopctrl, + POWER_LOOPCTRL_EN_RCSCALE_MASK, + POWER_LOOPCTRL_RCSCALE_THRESH | + POWER_LOOPCTRL_EN_RCSCALE_8X); + + clrsetbits_le32(&power_regs->hw_power_minpwr, + POWER_MINPWR_HALFFETS, POWER_MINPWR_DOUBLE_FETS); + + /* 5V to battery handoff ... FIXME */ + 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); +} + +/** + * mxs_power_init_4p2_params() - Configure the parameters of the 4P2 regulator + * + * This function configures the necessary parameters for the 4P2 linear + * regulator to supply the DC-DC converter from 5V input. + */ +static void mxs_power_init_4p2_params(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Configuring common 4P2 regulator params\n"); + + /* Setup 4P2 parameters */ + clrsetbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_CMPTRIP_MASK | POWER_DCDC4P2_TRG_MASK, + POWER_DCDC4P2_TRG_4V2 | (31 << POWER_DCDC4P2_CMPTRIP_OFFSET)); + + clrsetbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_HEADROOM_ADJ_MASK, + 0x4 << POWER_5VCTRL_HEADROOM_ADJ_OFFSET); + + clrsetbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_DROPOUT_CTRL_MASK, + DCDC4P2_DROPOUT_CONFIG); + + clrsetbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK, + 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET); +} + +/** + * mxs_enable_4p2_dcdc_input() - Enable or disable the DCDC input from 4P2 + * @xfer: Select if the input shall be enabled or disabled + * + * This function enables or disables the 4P2 input into the DC-DC converter. + */ +static void mxs_enable_4p2_dcdc_input(int xfer) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo; + uint32_t prev_5v_brnout, prev_5v_droop; + + debug("SPL: %s 4P2 DC-DC Input\n", xfer ? "Enabling" : "Disabling"); + + if (xfer && (readl(&power_regs->hw_power_5vctrl) & + POWER_5VCTRL_ENABLE_DCDC)) { + return; + } + + prev_5v_brnout = readl(&power_regs->hw_power_5vctrl) & + POWER_5VCTRL_PWDN_5VBRNOUT; + prev_5v_droop = readl(&power_regs->hw_power_ctrl) & + POWER_CTRL_ENIRQ_VDD5V_DROOP; + + clrbits_le32(&power_regs->hw_power_5vctrl, POWER_5VCTRL_PWDN_5VBRNOUT); + writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF, + &power_regs->hw_power_reset); + + clrbits_le32(&power_regs->hw_power_ctrl, POWER_CTRL_ENIRQ_VDD5V_DROOP); + + /* + * Recording orignal values that will be modified temporarlily + * to handle a chip bug. See chip errata for CQ ENGR00115837 + */ + tmp = readl(&power_regs->hw_power_5vctrl); + vbus_thresh = tmp & POWER_5VCTRL_VBUSVALID_TRSH_MASK; + vbus_5vdetect = tmp & POWER_5VCTRL_VBUSVALID_5VDETECT; + + pwd_bo = readl(&power_regs->hw_power_minpwr) & POWER_MINPWR_PWD_BO; + + /* + * Disable mechanisms that get erroneously tripped by when setting + * the DCDC4P2 EN_DCDC + */ + clrbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_VBUSVALID_5VDETECT | + POWER_5VCTRL_VBUSVALID_TRSH_MASK); + + writel(POWER_MINPWR_PWD_BO, &power_regs->hw_power_minpwr_set); + + if (xfer) { + setbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_DCDC_XFER); + early_delay(20); + clrbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_DCDC_XFER); + + setbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_ENABLE_DCDC); + } else { + setbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_ENABLE_DCDC); + } + + early_delay(25); + + clrsetbits_le32(&power_regs->hw_power_5vctrl, + POWER_5VCTRL_VBUSVALID_TRSH_MASK, vbus_thresh); + + if (vbus_5vdetect) + writel(vbus_5vdetect, &power_regs->hw_power_5vctrl_set); + + if (!pwd_bo) + clrbits_le32(&power_regs->hw_power_minpwr, POWER_MINPWR_PWD_BO); + + while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) + writel(POWER_CTRL_VBUS_VALID_IRQ, + &power_regs->hw_power_ctrl_clr); + + if (prev_5v_brnout) { + writel(POWER_5VCTRL_PWDN_5VBRNOUT, + &power_regs->hw_power_5vctrl_set); + writel(POWER_RESET_UNLOCK_KEY, + &power_regs->hw_power_reset); + } else { + writel(POWER_5VCTRL_PWDN_5VBRNOUT, + &power_regs->hw_power_5vctrl_clr); + writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF, + &power_regs->hw_power_reset); + } + + while (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VDD5V_DROOP_IRQ) + writel(POWER_CTRL_VDD5V_DROOP_IRQ, + &power_regs->hw_power_ctrl_clr); + + if (prev_5v_droop) + clrbits_le32(&power_regs->hw_power_ctrl, + POWER_CTRL_ENIRQ_VDD5V_DROOP); + else + setbits_le32(&power_regs->hw_power_ctrl, + POWER_CTRL_ENIRQ_VDD5V_DROOP); +} + +/** + * mxs_power_init_4p2_regulator() - Start the 4P2 regulator + * + * This function enables the 4P2 regulator and switches the DC-DC converter + * to use the 4P2 input. + */ +static void mxs_power_init_4p2_regulator(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t tmp, tmp2; + + debug("SPL: Enabling 4P2 regulator\n"); + + setbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_ENABLE_4P2); + + writel(POWER_CHARGE_ENABLE_LOAD, &power_regs->hw_power_charge_set); + + writel(POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK, + &power_regs->hw_power_5vctrl_clr); + clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_TRG_MASK); + + /* Power up the 4p2 rail and logic/control */ + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK, + &power_regs->hw_power_5vctrl_clr); + + /* + * Start charging up the 4p2 capacitor. We ramp of this charge + * gradually to avoid large inrush current from the 5V cable which can + * cause transients/problems + */ + debug("SPL: Charging 4P2 capacitor\n"); + mxs_enable_4p2_dcdc_input(0); + + if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) { + /* + * If we arrived here, we were unable to recover from mx23 chip + * errata 5837. 4P2 is disabled and sufficient battery power is + * not present. Exiting to not enable DCDC power during 5V + * connected state. + */ + clrbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_ENABLE_DCDC); + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK, + &power_regs->hw_power_5vctrl_set); + + debug("SPL: Unable to recover from mx23 errata 5837\n"); + hang(); + } + + /* + * Here we set the 4p2 brownout level to something very close to 4.2V. + * We then check the brownout status. If the brownout status is false, + * the voltage is already close to the target voltage of 4.2V so we + * can go ahead and set the 4P2 current limit to our max target limit. + * If the brownout status is true, we need to ramp us the current limit + * so that we don't cause large inrush current issues. We step up the + * current limit until the brownout status is false or until we've + * reached our maximum defined 4p2 current limit. + */ + debug("SPL: Setting 4P2 brownout level\n"); + clrsetbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_BO_MASK, + 22 << POWER_DCDC4P2_BO_OFFSET); /* 4.15V */ + + if (!(readl(&power_regs->hw_power_sts) & POWER_STS_DCDC_4P2_BO)) { + setbits_le32(&power_regs->hw_power_5vctrl, + 0x3f << POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET); + } else { + tmp = (readl(&power_regs->hw_power_5vctrl) & + POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK) >> + POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET; + while (tmp < 0x3f) { + if (!(readl(&power_regs->hw_power_sts) & + POWER_STS_DCDC_4P2_BO)) { + tmp = readl(&power_regs->hw_power_5vctrl); + tmp |= POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK; + early_delay(100); + writel(tmp, &power_regs->hw_power_5vctrl); + break; + } else { + tmp++; + tmp2 = readl(&power_regs->hw_power_5vctrl); + tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK; + tmp2 |= tmp << + POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET; + writel(tmp2, &power_regs->hw_power_5vctrl); + early_delay(100); + } + } + } + + clrbits_le32(&power_regs->hw_power_dcdc4p2, POWER_DCDC4P2_BO_MASK); + writel(POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr); +} + +/** + * mxs_power_init_dcdc_4p2_source() - Switch DC-DC converter to 4P2 source + * + * This function configures the DC-DC converter to be supplied from the 4P2 + * linear regulator. + */ +static void mxs_power_init_dcdc_4p2_source(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Switching DC-DC converters to 4P2\n"); + + if (!(readl(&power_regs->hw_power_dcdc4p2) & + POWER_DCDC4P2_ENABLE_DCDC)) { + debug("SPL: Already switched - aborting\n"); + hang(); + } + + mxs_enable_4p2_dcdc_input(1); + + if (readl(&power_regs->hw_power_ctrl) & POWER_CTRL_VBUS_VALID_IRQ) { + clrbits_le32(&power_regs->hw_power_dcdc4p2, + POWER_DCDC4P2_ENABLE_DCDC); + writel(POWER_5VCTRL_ENABLE_DCDC, + &power_regs->hw_power_5vctrl_clr); + writel(POWER_5VCTRL_PWD_CHARGE_4P2_MASK, + &power_regs->hw_power_5vctrl_set); + } +} + +/** + * mxs_power_enable_4p2() - Power up the 4P2 regulator + * + * This function drives the process of powering up the 4P2 linear regulator + * and switching the DC-DC converter input over to the 4P2 linear regulator. + */ +static void mxs_power_enable_4p2(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t vdddctrl, vddactrl, vddioctrl; + uint32_t tmp; + + debug("SPL: Powering up 4P2 regulator\n"); + + vdddctrl = readl(&power_regs->hw_power_vdddctrl); + vddactrl = readl(&power_regs->hw_power_vddactrl); + vddioctrl = readl(&power_regs->hw_power_vddioctrl); + + setbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG | + POWER_VDDDCTRL_PWDN_BRNOUT); + + setbits_le32(&power_regs->hw_power_vddactrl, + POWER_VDDACTRL_DISABLE_FET | POWER_VDDACTRL_ENABLE_LINREG | + POWER_VDDACTRL_PWDN_BRNOUT); + + setbits_le32(&power_regs->hw_power_vddioctrl, + POWER_VDDIOCTRL_DISABLE_FET | POWER_VDDIOCTRL_PWDN_BRNOUT); + + mxs_power_init_4p2_params(); + mxs_power_init_4p2_regulator(); + + /* Shutdown battery (none present) */ + if (!mxs_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); + } + + mxs_power_init_dcdc_4p2_source(); + + writel(vdddctrl, &power_regs->hw_power_vdddctrl); + early_delay(20); + writel(vddactrl, &power_regs->hw_power_vddactrl); + early_delay(20); + writel(vddioctrl, &power_regs->hw_power_vddioctrl); + + /* + * Check if FET is enabled on either powerout and if so, + * disable load. + */ + tmp = 0; + tmp |= !(readl(&power_regs->hw_power_vdddctrl) & + POWER_VDDDCTRL_DISABLE_FET); + tmp |= !(readl(&power_regs->hw_power_vddactrl) & + POWER_VDDACTRL_DISABLE_FET); + tmp |= !(readl(&power_regs->hw_power_vddioctrl) & + POWER_VDDIOCTRL_DISABLE_FET); + if (tmp) + writel(POWER_CHARGE_ENABLE_LOAD, + &power_regs->hw_power_charge_clr); + + debug("SPL: 4P2 regulator powered-up\n"); +} + +/** + * mxs_boot_valid_5v() - Boot from 5V supply + * + * This function configures the power block to boot from valid 5V input. + * This is called only if the 5V is reliable and can properly supply the + * CPU. This function proceeds to configure the 4P2 converter to be supplied + * from the 5V input. + */ +static void mxs_boot_valid_5v(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Booting from 5V supply\n"); + + /* + * Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V + * disconnect event. FIXME + */ + writel(POWER_5VCTRL_VBUSVALID_5VDETECT, + &power_regs->hw_power_5vctrl_set); + + /* Configure polarity to check for 5V disconnection. */ + writel(POWER_CTRL_POLARITY_VBUSVALID | + POWER_CTRL_POLARITY_VDD5V_GT_VDDIO, + &power_regs->hw_power_ctrl_clr); + + writel(POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_VDD5V_GT_VDDIO_IRQ, + &power_regs->hw_power_ctrl_clr); + + mxs_power_enable_4p2(); +} + +/** + * mxs_powerdown() - Shut down the system + * + * This function powers down the CPU completely. + */ +static void mxs_powerdown(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("Powering Down\n"); + + writel(POWER_RESET_UNLOCK_KEY, &power_regs->hw_power_reset); + writel(POWER_RESET_UNLOCK_KEY | POWER_RESET_PWD_OFF, + &power_regs->hw_power_reset); +} + +/** + * mxs_batt_boot() - Configure the power block to boot from battery input + * + * This function configures the power block to boot from the battery voltage + * supply. + */ +static void mxs_batt_boot(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Configuring power block to boot from battery\n"); + + 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); + + mxs_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); + + mxs_power_enable_4p2(); +} + +/** + * mxs_handle_5v_conflict() - Test if the 5V input is reliable + * + * This function tests if the 5V input can reliably supply the system. If it + * can, then proceed to configuring the system to boot from 5V source, otherwise + * try booting from battery supply. If we can not boot from battery supply + * either, shut down the system. + */ +static void mxs_handle_5v_conflict(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t tmp; + + debug("SPL: Resolving 5V conflict\n"); + + setbits_le32(&power_regs->hw_power_vddioctrl, + POWER_VDDIOCTRL_BO_OFFSET_MASK); + + for (;;) { + tmp = readl(&power_regs->hw_power_sts); + + if (tmp & POWER_STS_VDDIO_BO) { + /* + * VDDIO has a brownout, then the VDD5V_GT_VDDIO becomes + * unreliable + */ + debug("SPL: VDDIO has a brownout\n"); + mxs_powerdown(); + break; + } + + if (tmp & POWER_STS_VDD5V_GT_VDDIO) { + debug("SPL: POWER_STS_VDD5V_GT_VDDIO is set\n"); + mxs_boot_valid_5v(); + break; + } else { + debug("SPL: POWER_STS_VDD5V_GT_VDDIO is not set\n"); + mxs_powerdown(); + break; + } + + /* + * TODO: I can't see this being reached. We'll either + * powerdown or boot from a stable 5V supply. + */ + if (tmp & POWER_STS_PSWITCH_MASK) { + debug("SPL: POWER_STS_PSWITCH_MASK is set\n"); + mxs_batt_boot(); + break; + } + } +} + +/** + * mxs_5v_boot() - Configure the power block to boot from 5V input + * + * This function handles configuration of the power block when supplied by + * a 5V input. + */ +static void mxs_5v_boot(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Configuring power block to boot from 5V input\n"); + + /* + * NOTE: In original IMX-Bootlets, this also checks for VBUSVALID, + * but their implementation always returns 1 so we omit it here. + */ + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + debug("SPL: 5V VDD good\n"); + mxs_boot_valid_5v(); + return; + } + + early_delay(1000); + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + debug("SPL: 5V VDD good (after delay)\n"); + mxs_boot_valid_5v(); + return; + } + + debug("SPL: 5V VDD not good\n"); + mxs_handle_5v_conflict(); +} + +/** + * mxs_init_batt_bo() - Configure battery brownout threshold + * + * This function configures the battery input brownout threshold. The value + * at which the battery brownout happens is configured to 3.0V in the code. + */ +static void mxs_init_batt_bo(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Initialising battery brown-out level to 3.0V\n"); + + /* Brownout at 3V */ + clrsetbits_le32(&power_regs->hw_power_battmonitor, + POWER_BATTMONITOR_BRWNOUT_LVL_MASK, + 15 << POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET); + + writel(POWER_CTRL_BATT_BO_IRQ, &power_regs->hw_power_ctrl_clr); + writel(POWER_CTRL_ENIRQ_BATT_BO, &power_regs->hw_power_ctrl_clr); +} + +/** + * mxs_switch_vddd_to_dcdc_source() - Switch VDDD rail to DC-DC converter + * + * This function turns off the VDDD linear regulator and therefore makes + * the VDDD rail be supplied only by the DC-DC converter. + */ +static void mxs_switch_vddd_to_dcdc_source(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Switching VDDD to DC-DC converters\n"); + + clrsetbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_LINREG_OFFSET_MASK, + POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW); + + clrbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_DISABLE_FET | POWER_VDDDCTRL_ENABLE_LINREG | + POWER_VDDDCTRL_DISABLE_STEPPING); +} + +/** + * mxs_power_configure_power_source() - Configure power block source + * + * This function is the core of the power configuration logic. The function + * selects the power block input source and configures the whole power block + * accordingly. After the configuration is complete and the system is stable + * again, the function switches the CPU clock source back to PLL. Finally, + * the function switches the voltage rails to DC-DC converter. + */ +static void mxs_power_configure_power_source(void) +{ + int batt_ready, batt_good; + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + struct mxs_lradc_regs *lradc_regs = + (struct mxs_lradc_regs *)MXS_LRADC_BASE; + + debug("SPL: Configuring power source\n"); + + mxs_power_setup_dcdc_clocksource(); + mxs_src_power_init(); + + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + batt_ready = mxs_is_batt_ready(); + if (batt_ready) { + /* 5V source detected, good battery detected. */ + mxs_batt_boot(); + } else { + batt_good = mxs_is_batt_good(); + if (!batt_good) { + /* 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); + } + mxs_5v_boot(); + } + } else { + /* 5V not detected, booting from battery. */ + mxs_batt_boot(); + } + + /* + * TODO: Do not switch CPU clock to PLL if we are VDD5V is sourced + * from USB VBUS + */ + mxs_power_clock2pll(); + + mxs_init_batt_bo(); + + mxs_switch_vddd_to_dcdc_source(); + +#ifdef CONFIG_MX23 + /* Fire up the VDDMEM LinReg now that we're all set. */ + debug("SPL: Enabling mx23 VDDMEM linear regulator\n"); + writel(POWER_VDDMEMCTRL_ENABLE_LINREG | POWER_VDDMEMCTRL_ENABLE_ILIMIT, + &power_regs->hw_power_vddmemctrl); +#endif +} + +/** + * mxs_enable_output_rail_protection() - Enable power rail protection + * + * This function enables overload protection on the power rails. This is + * triggered if the power rails' voltage drops rapidly due to overload and + * in such case, the supply to the powerrail is cut-off, protecting the + * CPU from damage. Note that under such condition, the system will likely + * crash or misbehave. + */ +static void mxs_enable_output_rail_protection(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Enabling output rail protection\n"); + + writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ | + POWER_CTRL_VDDIO_BO_IRQ, &power_regs->hw_power_ctrl_clr); + + setbits_le32(&power_regs->hw_power_vdddctrl, + POWER_VDDDCTRL_PWDN_BRNOUT); + + setbits_le32(&power_regs->hw_power_vddactrl, + POWER_VDDACTRL_PWDN_BRNOUT); + + setbits_le32(&power_regs->hw_power_vddioctrl, + POWER_VDDIOCTRL_PWDN_BRNOUT); +} + +/** + * mxs_get_vddio_power_source_off() - Get VDDIO rail power source + * + * This function tests if the VDDIO rail is supplied by linear regulator + * or by the DC-DC converter. Returns 1 if powered by linear regulator, + * returns 0 if powered by the DC-DC converter. + */ +static int mxs_get_vddio_power_source_off(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t tmp; + + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + tmp = readl(&power_regs->hw_power_vddioctrl); + if (tmp & POWER_VDDIOCTRL_DISABLE_FET) { + if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) == + POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) { + return 1; + } + } + + if (!(readl(&power_regs->hw_power_5vctrl) & + POWER_5VCTRL_ENABLE_DCDC)) { + if ((tmp & POWER_VDDIOCTRL_LINREG_OFFSET_MASK) == + POWER_VDDIOCTRL_LINREG_OFFSET_0STEPS) { + return 1; + } + } + } + + return 0; + +} + +/** + * mxs_get_vddd_power_source_off() - Get VDDD rail power source + * + * This function tests if the VDDD rail is supplied by linear regulator + * or by the DC-DC converter. Returns 1 if powered by linear regulator, + * returns 0 if powered by the DC-DC converter. + */ +static int mxs_get_vddd_power_source_off(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t tmp; + + tmp = readl(&power_regs->hw_power_vdddctrl); + if (tmp & POWER_VDDDCTRL_DISABLE_FET) { + if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) == + POWER_VDDDCTRL_LINREG_OFFSET_0STEPS) { + return 1; + } + } + + if (readl(&power_regs->hw_power_sts) & POWER_STS_VDD5V_GT_VDDIO) { + if (!(readl(&power_regs->hw_power_5vctrl) & + POWER_5VCTRL_ENABLE_DCDC)) { + return 1; + } + } + + if (!(tmp & POWER_VDDDCTRL_ENABLE_LINREG)) { + if ((tmp & POWER_VDDDCTRL_LINREG_OFFSET_MASK) == + POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW) { + return 1; + } + } + + return 0; +} + +struct mxs_vddx_cfg { + uint32_t *reg; + uint8_t step_mV; + uint16_t lowest_mV; + int (*powered_by_linreg)(void); + uint32_t trg_mask; + uint32_t bo_irq; + uint32_t bo_enirq; + uint32_t bo_offset_mask; + uint32_t bo_offset_offset; +}; + +static const struct mxs_vddx_cfg mxs_vddio_cfg = { + .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)-> + hw_power_vddioctrl), +#if defined(CONFIG_MX23) + .step_mV = 25, +#else + .step_mV = 50, +#endif + .lowest_mV = 2800, + .powered_by_linreg = mxs_get_vddio_power_source_off, + .trg_mask = POWER_VDDIOCTRL_TRG_MASK, + .bo_irq = POWER_CTRL_VDDIO_BO_IRQ, + .bo_enirq = POWER_CTRL_ENIRQ_VDDIO_BO, + .bo_offset_mask = POWER_VDDIOCTRL_BO_OFFSET_MASK, + .bo_offset_offset = POWER_VDDIOCTRL_BO_OFFSET_OFFSET, +}; + +static const struct mxs_vddx_cfg mxs_vddd_cfg = { + .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)-> + hw_power_vdddctrl), + .step_mV = 25, + .lowest_mV = 800, + .powered_by_linreg = mxs_get_vddd_power_source_off, + .trg_mask = POWER_VDDDCTRL_TRG_MASK, + .bo_irq = POWER_CTRL_VDDD_BO_IRQ, + .bo_enirq = POWER_CTRL_ENIRQ_VDDD_BO, + .bo_offset_mask = POWER_VDDDCTRL_BO_OFFSET_MASK, + .bo_offset_offset = POWER_VDDDCTRL_BO_OFFSET_OFFSET, +}; + +#ifdef CONFIG_MX23 +static const struct mxs_vddx_cfg mxs_vddmem_cfg = { + .reg = &(((struct mxs_power_regs *)MXS_POWER_BASE)-> + hw_power_vddmemctrl), + .step_mV = 50, + .lowest_mV = 1700, + .powered_by_linreg = NULL, + .trg_mask = POWER_VDDMEMCTRL_TRG_MASK, + .bo_irq = 0, + .bo_enirq = 0, + .bo_offset_mask = 0, + .bo_offset_offset = 0, +}; +#endif + +/** + * mxs_power_set_vddx() - Configure voltage on DC-DC converter rail + * @cfg: Configuration data of the DC-DC converter rail + * @new_target: New target voltage of the DC-DC converter rail + * @new_brownout: New brownout trigger voltage + * + * This function configures the output voltage on the DC-DC converter rail. + * The rail is selected by the @cfg argument. The new voltage target is + * selected by the @new_target and the voltage is specified in mV. The + * new brownout value is selected by the @new_brownout argument and the + * value is also in mV. + */ +static void mxs_power_set_vddx(const struct mxs_vddx_cfg *cfg, + uint32_t new_target, uint32_t new_brownout) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + uint32_t cur_target, diff, bo_int = 0; + uint32_t powered_by_linreg = 0; + int adjust_up, tmp; + + new_brownout = DIV_ROUND_CLOSEST(new_target - new_brownout, + cfg->step_mV); + + cur_target = readl(cfg->reg); + cur_target &= cfg->trg_mask; + cur_target *= cfg->step_mV; + cur_target += cfg->lowest_mV; + + adjust_up = new_target > cur_target; + if (cfg->powered_by_linreg) + powered_by_linreg = cfg->powered_by_linreg(); + + if (adjust_up && cfg->bo_irq) { + if (powered_by_linreg) { + bo_int = readl(cfg->reg); + clrbits_le32(cfg->reg, cfg->bo_enirq); + } + setbits_le32(cfg->reg, cfg->bo_offset_mask); + } + + do { + if (abs(new_target - cur_target) > 100) { + if (adjust_up) + diff = cur_target + 100; + else + diff = cur_target - 100; + } else { + diff = new_target; + } + + diff -= cfg->lowest_mV; + diff /= cfg->step_mV; + + clrsetbits_le32(cfg->reg, cfg->trg_mask, diff); + + if (powered_by_linreg || + (readl(&power_regs->hw_power_sts) & + POWER_STS_VDD5V_GT_VDDIO)) + early_delay(500); + else { + for (;;) { + tmp = readl(&power_regs->hw_power_sts); + if (tmp & POWER_STS_DC_OK) + break; + } + } + + cur_target = readl(cfg->reg); + cur_target &= cfg->trg_mask; + cur_target *= cfg->step_mV; + cur_target += cfg->lowest_mV; + } while (new_target > cur_target); + + if (cfg->bo_irq) { + if (adjust_up && powered_by_linreg) { + writel(cfg->bo_irq, &power_regs->hw_power_ctrl_clr); + if (bo_int & cfg->bo_enirq) + setbits_le32(cfg->reg, cfg->bo_enirq); + } + + clrsetbits_le32(cfg->reg, cfg->bo_offset_mask, + new_brownout << cfg->bo_offset_offset); + } +} + +/** + * mxs_setup_batt_detect() - Start the battery voltage measurement logic + * + * This function starts and configures the LRADC block. This allows the + * power initialization code to measure battery voltage and based on this + * knowledge, decide whether to boot at all, boot from battery or boot + * from 5V input. + */ +static void mxs_setup_batt_detect(void) +{ + debug("SPL: Starting battery voltage measurement logic\n"); + + mxs_lradc_init(); + mxs_lradc_enable_batt_measurement(); + early_delay(10); +} + +/** + * mxs_ungate_power() - Ungate the POWER block + * + * This function ungates clock to the power block. In case the power block + * was still gated at this point, it will not be possible to configure the + * block and therefore the power initialization would fail. This function + * is only needed on i.MX233, on i.MX28 the power block is always ungated. + */ +static void mxs_ungate_power(void) +{ +#ifdef CONFIG_MX23 + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + writel(POWER_CTRL_CLKGATE, &power_regs->hw_power_ctrl_clr); +#endif +} + +/** + * mxs_power_init() - The power block init main function + * + * This function calls all the power block initialization functions in + * proper sequence to start the power block. + */ +void mxs_power_init(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Initialising Power Block\n"); + + mxs_ungate_power(); + + mxs_power_clock2xtal(); + mxs_power_set_auto_restart(); + mxs_power_set_linreg(); + mxs_power_setup_5v_detect(); + + mxs_setup_batt_detect(); + + mxs_power_configure_power_source(); + mxs_enable_output_rail_protection(); + + debug("SPL: Setting VDDIO to 3V3 (brownout @ 3v15)\n"); + mxs_power_set_vddx(&mxs_vddio_cfg, 3300, 3150); + + debug("SPL: Setting VDDD to 1V5 (brownout @ 1v315)\n"); + mxs_power_set_vddx(&mxs_vddd_cfg, 1500, 1315); +#ifdef CONFIG_MX23 + debug("SPL: Setting mx23 VDDMEM to 2V5 (brownout @ 1v7)\n"); + mxs_power_set_vddx(&mxs_vddmem_cfg, 2500, 1700); +#endif + writel(POWER_CTRL_VDDD_BO_IRQ | POWER_CTRL_VDDA_BO_IRQ | + POWER_CTRL_VDDIO_BO_IRQ | POWER_CTRL_VDD5V_DROOP_IRQ | + POWER_CTRL_VBUS_VALID_IRQ | POWER_CTRL_BATT_BO_IRQ | + POWER_CTRL_DCDC4P2_BO_IRQ, &power_regs->hw_power_ctrl_clr); + + writel(POWER_5VCTRL_PWDN_5VBRNOUT, &power_regs->hw_power_5vctrl_set); + + early_delay(1000); +} + +#ifdef CONFIG_SPL_MXS_PSWITCH_WAIT +/** + * mxs_power_wait_pswitch() - Wait for power switch to be pressed + * + * This function waits until the power-switch was pressed to start booting + * the board. + */ +void mxs_power_wait_pswitch(void) +{ + struct mxs_power_regs *power_regs = + (struct mxs_power_regs *)MXS_POWER_BASE; + + debug("SPL: Waiting for power switch input\n"); + while (!(readl(&power_regs->hw_power_sts) & POWER_STS_PSWITCH_MASK)) + ; +} +#endif
diff --git a/arch/arm/cpu/arm926ejs/mxs/start.S b/arch/arm/cpu/arm926ejs/mxs/start.S new file mode 100644 index 0000000..adec2c8 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/start.S
@@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Groger <mag@sysgo.de> + * Copyright (c) 2002 Alex Zupke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * Copyright (c) 2010 Albert Aribaud <albert.u.boot@aribaud.net> + * + * Change to support call back into iMX28 bootrom + * Copyright (c) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + */ + +#include <asm-offsets.h> +#include <config.h> +#include <common.h> + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + + .globl reset +reset: + /* + * If the CPU is configured in "Wait JTAG connection mode", the stack + * pointer is not configured and is zero. This will cause crash when + * trying to push data onto stack right below here. Load the SP and make + * it point to the end of OCRAM if the SP is zero. + */ + cmp sp, #0x00000000 + ldreq sp, =CONFIG_SYS_INIT_SP_ADDR + + /* + * Store all registers on old stack pointer, this will allow us later to + * return to the BootROM and let the BootROM load U-Boot into RAM. + * + * WARNING: Register r0 and r1 are used by the BootROM to pass data + * to the called code. Register r0 will contain arbitrary + * data that are set in the BootStream. In case this code + * was started with CALL instruction, register r1 will contain + * pointer to the return value this function can then set. + * The code below MUST NOT CHANGE register r0 and r1 ! + */ + push {r0-r12,r14} + + /* Save control register c1 */ + mrc p15, 0, r2, c1, c0, 0 + push {r2} + + /* Set the cpu to SVC32 mode and store old CPSR register content. */ + mrs r2, cpsr + push {r2} + bic r2, r2, #0x1f + orr r2, r2, #0xd3 + msr cpsr, r2 + + bl board_init_ll + + /* Restore BootROM's CPU mode (especially FIQ). */ + pop {r2} + msr cpsr,r2 + + /* + * Restore c1 register. Especially set exception vector location + * back to BootROM space which is required by bootrom for USB boot. + */ + pop {r2} + mcr p15, 0, r2, c1, c0, 0 + + pop {r0-r12,r14} + + /* + * In case this code was started by the CALL instruction, the register + * r0 is examined by the BootROM after this code returns. The value in + * r0 must be set to 0 to indicate successful return. + */ + mov r0, #0 + + bx lr
diff --git a/arch/arm/cpu/arm926ejs/mxs/timer.c b/arch/arm/cpu/arm926ejs/mxs/timer.c new file mode 100644 index 0000000..7492ba4 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/timer.c
@@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Freescale i.MX28 timer driver + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * Based on code from LTIB: + * (C) Copyright 2009-2010 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> + +/* Maximum fixed count */ +#if defined(CONFIG_MX23) +#define TIMER_LOAD_VAL 0xffff +#elif defined(CONFIG_MX28) +#define TIMER_LOAD_VAL 0xffffffff +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp (gd->arch.tbl) +#define lastdec (gd->arch.lastinc) + +/* + * This driver uses 1kHz clock source. + */ +#define MXS_INCREMENTER_HZ 1000 + +static inline unsigned long tick_to_time(unsigned long tick) +{ + return tick / (MXS_INCREMENTER_HZ / CONFIG_SYS_HZ); +} + +static inline unsigned long time_to_tick(unsigned long time) +{ + return time * (MXS_INCREMENTER_HZ / CONFIG_SYS_HZ); +} + +/* Calculate how many ticks happen in "us" microseconds */ +static inline unsigned long us_to_tick(unsigned long us) +{ + return (us * MXS_INCREMENTER_HZ) / 1000000; +} + +int timer_init(void) +{ + struct mxs_timrot_regs *timrot_regs = + (struct mxs_timrot_regs *)MXS_TIMROT_BASE; + + /* Reset Timers and Rotary Encoder module */ + mxs_reset_block(&timrot_regs->hw_timrot_rotctrl_reg); + + /* Set fixed_count to 0 */ +#if defined(CONFIG_MX23) + writel(0, &timrot_regs->hw_timrot_timcount0); +#elif defined(CONFIG_MX28) + writel(0, &timrot_regs->hw_timrot_fixed_count0); +#endif + + /* Set UPDATE bit and 1Khz frequency */ + writel(TIMROT_TIMCTRLn_UPDATE | TIMROT_TIMCTRLn_RELOAD | + TIMROT_TIMCTRLn_SELECT_1KHZ_XTAL, + &timrot_regs->hw_timrot_timctrl0); + + /* Set fixed_count to maximal value */ +#if defined(CONFIG_MX23) + writel(TIMER_LOAD_VAL - 1, &timrot_regs->hw_timrot_timcount0); +#elif defined(CONFIG_MX28) + writel(TIMER_LOAD_VAL, &timrot_regs->hw_timrot_fixed_count0); +#endif + + return 0; +} + +unsigned long long get_ticks(void) +{ + struct mxs_timrot_regs *timrot_regs = + (struct mxs_timrot_regs *)MXS_TIMROT_BASE; + uint32_t now; + + /* Current tick value */ +#if defined(CONFIG_MX23) + /* Upper bits are the valid ones. */ + now = readl(&timrot_regs->hw_timrot_timcount0) >> + TIMROT_RUNNING_COUNTn_RUNNING_COUNT_OFFSET; +#elif defined(CONFIG_MX28) + now = readl(&timrot_regs->hw_timrot_running_count0); +#else +#error "Don't know how to read timrot_regs" +#endif + + if (lastdec >= now) { + /* + * normal mode (non roll) + * move stamp forward with absolut diff ticks + */ + timestamp += (lastdec - now); + } else { + /* we have rollover of decrementer */ + timestamp += (TIMER_LOAD_VAL - now) + lastdec; + + } + lastdec = now; + + return timestamp; +} + +ulong get_timer(ulong base) +{ + return tick_to_time(get_ticks()) - base; +} + +/* We use the HW_DIGCTL_MICROSECONDS register for sub-millisecond timer. */ +#define MXS_HW_DIGCTL_MICROSECONDS 0x8001c0c0 + +void __udelay(unsigned long usec) +{ + uint32_t old, new, incr; + uint32_t counter = 0; + + old = readl(MXS_HW_DIGCTL_MICROSECONDS); + + while (counter < usec) { + new = readl(MXS_HW_DIGCTL_MICROSECONDS); + + /* Check if the timer wrapped. */ + if (new < old) { + incr = 0xffffffff - old; + incr += new; + } else { + incr = new - old; + } + + /* + * Check if we are close to the maximum time and the counter + * would wrap if incremented. If that's the case, break out + * from the loop as the requested delay time passed. + */ + if (counter + incr < counter) + break; + + counter += incr; + old = new; + } +} + +ulong get_tbclk(void) +{ + return MXS_INCREMENTER_HZ; +}
diff --git a/arch/arm/cpu/arm926ejs/mxs/u-boot-imx23.bd b/arch/arm/cpu/arm926ejs/mxs/u-boot-imx23.bd new file mode 100644 index 0000000..3a51879 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/u-boot-imx23.bd
@@ -0,0 +1,18 @@ +options { + driveTag = 0x00; + flags = 0x01; +} + +sources { + u_boot_spl="spl/u-boot-spl.bin"; + u_boot="u-boot.bin"; +} + +section (0) { + load u_boot_spl > 0x0000; + load ivt (entry = 0x0014) > 0x8000; + call 0x8000; + + load u_boot > 0x40000100; + call 0x40000100; +}
diff --git a/arch/arm/cpu/arm926ejs/mxs/u-boot-imx28.bd b/arch/arm/cpu/arm926ejs/mxs/u-boot-imx28.bd new file mode 100644 index 0000000..c60615a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/u-boot-imx28.bd
@@ -0,0 +1,14 @@ +sources { + u_boot_spl="spl/u-boot-spl.bin"; + u_boot="u-boot.bin"; +} + +section (0) { + load u_boot_spl > 0x0000; + load ivt (entry = 0x0014) > 0x8000; + hab call 0x8000; + + load u_boot > 0x40000100; + load ivt (entry = 0x40000100) > 0x8000; + hab call 0x8000; +}
diff --git a/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds b/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds new file mode 100644 index 0000000..ffc70ce --- /dev/null +++ b/arch/arm/cpu/arm926ejs/mxs/u-boot-spl.lds
@@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * January 2004 - Changed to support H4 device + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = CONFIG_SPL_TEXT_BASE; + + . = ALIGN(4); + .text : + { + *(.vectors) + arch/arm/cpu/arm926ejs/mxs/start.o (.text*) + *(.text*) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + + .rel.dyn : { + __rel_dyn_start = .; + *(.rel*) + __rel_dyn_end = .; + } + + .bss : { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } + + .end : + { + *(.__end) + } + + _image_binary_end = .; + + .dynsym _image_binary_end : { *(.dynsym) } + .dynbss : { *(.dynbss) } + .dynstr : { *(.dynstr*) } + .dynamic : { *(.dynamic*) } + .hash : { *(.hash*) } + .plt : { *(.plt*) } + .interp : { *(.interp*) } + .gnu : { *(.gnu*) } + .ARM.exidx : { *(.ARM.exidx*) } +}
diff --git a/arch/arm/cpu/arm926ejs/orion5x/u-boot-spl.lds b/arch/arm/cpu/arm926ejs/orion5x/u-boot-spl.lds new file mode 100644 index 0000000..fbdb1d7 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/orion5x/u-boot-spl.lds
@@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2014 Albert ARIBAUD <albert.u.boot@aribaud.net> + * + * Based on: + * + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Tom Cubie <tangliang@allwinnertech.com> + * + * Based on omap-common/u-boot-spl.lds: + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + */ +MEMORY { .nor : ORIGIN = CONFIG_SPL_TEXT_BASE,\ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .bss : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : + { + __start = .; + *(.vectors) + CPUDIR/start.o (.text) + *(.text*) + } > .nor + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.nor + + . = ALIGN(4); + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.nor + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } > .nor + + . = ALIGN(4); + __image_copy_end = .; + _end = .; + + .bss : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } > .bss +}
diff --git a/arch/arm/cpu/arm926ejs/spear/Makefile b/arch/arm/cpu/arm926ejs/spear/Makefile new file mode 100644 index 0000000..b1b6b40 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/Makefile
@@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +obj-y := cpu.o \ + reset.o \ + timer.o + +ifdef CONFIG_SPL_BUILD +obj-y += spl.o +obj-$(CONFIG_SPEAR600) += spear600.o +obj-$(CONFIG_DDR_MT47H64M16) += spr600_mt47h64m16_3_333_cl5_psync.o +obj-$(CONFIG_DDR_MT47H32M16) += spr600_mt47h32m16_333_cl5_psync.o +obj-$(CONFIG_DDR_MT47H32M16) += spr600_mt47h32m16_37e_166_cl4_sync.o +obj-$(CONFIG_DDR_MT47H128M8) += spr600_mt47h128m8_3_266_cl5_async.o +else +obj-y += spr_misc.o spr_lowlevel_init.o +endif + +extra-$(CONFIG_SPL_BUILD) := start.o
diff --git a/arch/arm/cpu/arm926ejs/spear/cpu.c b/arch/arm/cpu/arm926ejs/spear/cpu.c new file mode 100644 index 0000000..51c4a73 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/cpu.c
@@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spr_misc.h> + +int arch_cpu_init(void) +{ + struct misc_regs *const misc_p = + (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 periph1_clken, periph_clk_cfg; + + periph1_clken = readl(&misc_p->periph1_clken); + +#if defined(CONFIG_SPEAR3XX) + periph1_clken |= MISC_GPT2ENB; +#elif defined(CONFIG_SPEAR600) + periph1_clken |= MISC_GPT3ENB; +#endif + +#if defined(CONFIG_PL011_SERIAL) + periph1_clken |= MISC_UART0ENB; + + periph_clk_cfg = readl(&misc_p->periph_clk_cfg); + periph_clk_cfg &= ~CONFIG_SPEAR_UARTCLKMSK; + periph_clk_cfg |= CONFIG_SPEAR_UART48M; + writel(periph_clk_cfg, &misc_p->periph_clk_cfg); +#endif +#if defined(CONFIG_ETH_DESIGNWARE) + periph1_clken |= MISC_ETHENB; +#endif +#if defined(CONFIG_DW_UDC) + periph1_clken |= MISC_USBDENB; +#endif +#if defined(CONFIG_SYS_I2C_DW) + periph1_clken |= MISC_I2CENB; +#endif +#if defined(CONFIG_ST_SMI) + periph1_clken |= MISC_SMIENB; +#endif +#if defined(CONFIG_NAND_FSMC) + periph1_clken |= MISC_FSMCENB; +#endif +#if defined(CONFIG_USB_EHCI_SPEAR) + periph1_clken |= PERIPH_USBH1 | PERIPH_USBH2; +#endif +#if defined(CONFIG_SPEAR_GPIO) + periph1_clken |= MISC_GPIO3ENB | MISC_GPIO4ENB; +#endif +#if defined(CONFIG_PL022_SPI) + periph1_clken |= MISC_SSP1ENB | MISC_SSP2ENB | MISC_SSP3ENB; +#endif + + writel(periph1_clken, &misc_p->periph1_clken); + + return 0; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ +#ifdef CONFIG_SPEAR300 + printf("CPU: SPEAr300\n"); +#elif defined(CONFIG_SPEAR310) + printf("CPU: SPEAr310\n"); +#elif defined(CONFIG_SPEAR320) + printf("CPU: SPEAr320\n"); +#elif defined(CONFIG_SPEAR600) + printf("CPU: SPEAr600\n"); +#else +#error CPU not supported in spear platform +#endif + return 0; +} +#endif + +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_NAND_ECC_BCH) && defined(CONFIG_NAND_FSMC) +static int do_switch_ecc(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (argc != 2) + goto usage; + + if (strncmp(argv[1], "hw", 2) == 0) { + /* 1-bit HW ECC */ + printf("Switching to 1-bit HW ECC\n"); + fsmc_nand_switch_ecc(1); + } else if (strncmp(argv[1], "bch4", 2) == 0) { + /* 4-bit SW ECC BCH4 */ + printf("Switching to 4-bit SW ECC (BCH4)\n"); + fsmc_nand_switch_ecc(4); + } else { + goto usage; + } + + return 0; + +usage: + printf("Usage: nandecc %s\n", cmdtp->usage); + return 1; +} + +U_BOOT_CMD( + nandecc, 2, 0, do_switch_ecc, + "switch NAND ECC calculation algorithm", + "hw|bch4 - Switch between NAND hardware 1-bit HW and" + " 4-bit SW BCH\n" +); +#endif
diff --git a/arch/arm/cpu/arm926ejs/spear/reset.c b/arch/arm/cpu/arm926ejs/spear/reset.c new file mode 100644 index 0000000..05c7ecd --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/reset.c
@@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2009 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spr_syscntl.h> + +void reset_cpu(ulong ignored) +{ + struct syscntl_regs *syscntl_regs_p = + (struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE; + + printf("System is going to reboot ...\n"); + + /* + * This 1 second delay will allow the above message + * to be printed before reset + */ + udelay((1000 * 1000)); + + /* Going into slow mode before resetting SOC */ + writel(0x02, &syscntl_regs_p->scctrl); + + /* + * Writing any value to the system status register will + * reset the SoC + */ + writel(0x00, &syscntl_regs_p->scsysstat); + + /* system will restart */ + while (1) + ; +}
diff --git a/arch/arm/cpu/arm926ejs/spear/spear600.c b/arch/arm/cpu/arm926ejs/spear/spear600.c new file mode 100644 index 0000000..b31ede5 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/spear600.c
@@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2000-2009 + * Viresh Kumar, ST Microelectronics, viresh.kumar@st.com + * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com + */ + +#include <common.h> +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/arch/spr_misc.h> +#include <asm/arch/spr_defs.h> + +void spear_late_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + + writel(0x80000007, &misc_p->arb_icm_ml1); + writel(0x80000007, &misc_p->arb_icm_ml2); + writel(0x80000007, &misc_p->arb_icm_ml3); + writel(0x80000007, &misc_p->arb_icm_ml4); + writel(0x80000007, &misc_p->arb_icm_ml5); + writel(0x80000007, &misc_p->arb_icm_ml6); + writel(0x80000007, &misc_p->arb_icm_ml7); + writel(0x80000007, &misc_p->arb_icm_ml8); + writel(0x80000007, &misc_p->arb_icm_ml9); +} + +static void sel_1v8(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 ddr1v8, ddr2v5; + + ddr2v5 = readl(&misc_p->ddr_2v5_compensation); + ddr2v5 &= 0x8080ffc0; + ddr2v5 |= 0x78000003; + writel(ddr2v5, &misc_p->ddr_2v5_compensation); + + ddr1v8 = readl(&misc_p->ddr_1v8_compensation); + ddr1v8 &= 0x8080ffc0; + ddr1v8 |= 0x78000010; + writel(ddr1v8, &misc_p->ddr_1v8_compensation); + + while (!(readl(&misc_p->ddr_1v8_compensation) & DDR_COMP_ACCURATE)) + ; +} + +static void sel_2v5(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 ddr1v8, ddr2v5; + + ddr1v8 = readl(&misc_p->ddr_1v8_compensation); + ddr1v8 &= 0x8080ffc0; + ddr1v8 |= 0x78000003; + writel(ddr1v8, &misc_p->ddr_1v8_compensation); + + ddr2v5 = readl(&misc_p->ddr_2v5_compensation); + ddr2v5 &= 0x8080ffc0; + ddr2v5 |= 0x78000010; + writel(ddr2v5, &misc_p->ddr_2v5_compensation); + + while (!(readl(&misc_p->ddr_2v5_compensation) & DDR_COMP_ACCURATE)) + ; +} + +/* + * plat_ddr_init: + */ +void plat_ddr_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 ddrpad; + u32 core3v3, ddr1v8, ddr2v5; + + /* DDR pad register configurations */ + ddrpad = readl(&misc_p->ddr_pad); + ddrpad &= ~DDR_PAD_CNF_MSK; + +#if (CONFIG_DDR_HCLK) + ddrpad |= 0xEAAB; +#elif (CONFIG_DDR_2HCLK) + ddrpad |= 0xEAAD; +#elif (CONFIG_DDR_PLL2) + ddrpad |= 0xEAAD; +#endif + writel(ddrpad, &misc_p->ddr_pad); + + /* Compensation register configurations */ + core3v3 = readl(&misc_p->core_3v3_compensation); + core3v3 &= 0x8080ffe0; + core3v3 |= 0x78000002; + writel(core3v3, &misc_p->core_3v3_compensation); + + ddr1v8 = readl(&misc_p->ddr_1v8_compensation); + ddr1v8 &= 0x8080ffc0; + ddr1v8 |= 0x78000004; + writel(ddr1v8, &misc_p->ddr_1v8_compensation); + + ddr2v5 = readl(&misc_p->ddr_2v5_compensation); + ddr2v5 &= 0x8080ffc0; + ddr2v5 |= 0x78000004; + writel(ddr2v5, &misc_p->ddr_2v5_compensation); + + if ((readl(&misc_p->ddr_pad) & DDR_PAD_SW_CONF) == DDR_PAD_SW_CONF) { + /* Software memory configuration */ + if (readl(&misc_p->ddr_pad) & DDR_PAD_SSTL_SEL) + sel_1v8(); + else + sel_2v5(); + } else { + /* Hardware memory configuration */ + if (readl(&misc_p->ddr_pad) & DDR_PAD_DRAM_TYPE) + sel_1v8(); + else + sel_2v5(); + } +} + +/* + * xxx_boot_selected: + * + * return true if the particular booting option is selected + * return false otherwise + */ +static u32 read_bootstrap(void) +{ + return (readl(CONFIG_SPEAR_BOOTSTRAPCFG) >> CONFIG_SPEAR_BOOTSTRAPSHFT) + & CONFIG_SPEAR_BOOTSTRAPMASK; +} + +int snor_boot_selected(void) +{ + u32 bootstrap = read_bootstrap(); + + if (SNOR_BOOT_SUPPORTED) { + /* Check whether SNOR boot is selected */ + if ((bootstrap & CONFIG_SPEAR_ONLYSNORBOOT) == + CONFIG_SPEAR_ONLYSNORBOOT) + return true; + + if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) == + CONFIG_SPEAR_NORNAND8BOOT) + return true; + + if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) == + CONFIG_SPEAR_NORNAND16BOOT) + return true; + } + + return false; +} + +int nand_boot_selected(void) +{ + u32 bootstrap = read_bootstrap(); + + if (NAND_BOOT_SUPPORTED) { + /* Check whether NAND boot is selected */ + if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) == + CONFIG_SPEAR_NORNAND8BOOT) + return true; + + if ((bootstrap & CONFIG_SPEAR_NORNANDBOOT) == + CONFIG_SPEAR_NORNAND16BOOT) + return true; + } + + return false; +} + +int pnor_boot_selected(void) +{ + /* Parallel NOR boot is not selected in any SPEAr600 revision */ + return false; +} + +int usb_boot_selected(void) +{ + u32 bootstrap = read_bootstrap(); + + if (USB_BOOT_SUPPORTED) { + /* Check whether USB boot is selected */ + if (!(bootstrap & CONFIG_SPEAR_USBBOOT)) + return true; + } + + return false; +} + +int tftp_boot_selected(void) +{ + /* TFTP boot is not selected in any SPEAr600 revision */ + return false; +} + +int uart_boot_selected(void) +{ + /* UART boot is not selected in any SPEAr600 revision */ + return false; +} + +int spi_boot_selected(void) +{ + /* SPI boot is not selected in any SPEAr600 revision */ + return false; +} + +int i2c_boot_selected(void) +{ + /* I2C boot is not selected in any SPEAr600 revision */ + return false; +} + +int mmc_boot_selected(void) +{ + return false; +} + +void plat_late_init(void) +{ + spear_late_init(); +}
diff --git a/arch/arm/cpu/arm926ejs/spear/spl.c b/arch/arm/cpu/arm926ejs/spear/spl.c new file mode 100644 index 0000000..d2bddb5 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/spl.c
@@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * Copyright (C) 2012 Stefan Roese <sr@denx.de> + */ + +#include <common.h> +#include <spl.h> +#include <version.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spr_defs.h> +#include <asm/arch/spr_misc.h> +#include <asm/arch/spr_syscntl.h> +#include <linux/mtd/st_smi.h> + +static void ddr_clock_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 clkenb, ddrpll; + + clkenb = readl(&misc_p->periph1_clken); + clkenb &= ~PERIPH_MPMCMSK; + clkenb |= PERIPH_MPMC_WE; + + /* Intentionally done twice */ + writel(clkenb, &misc_p->periph1_clken); + writel(clkenb, &misc_p->periph1_clken); + + ddrpll = readl(&misc_p->pll_ctr_reg); + ddrpll &= ~MEM_CLK_SEL_MSK; +#if (CONFIG_DDR_HCLK) + ddrpll |= MEM_CLK_HCLK; +#elif (CONFIG_DDR_2HCLK) + ddrpll |= MEM_CLK_2HCLK; +#elif (CONFIG_DDR_PLL2) + ddrpll |= MEM_CLK_PLL2; +#else +#error "please define one of CONFIG_DDR_(HCLK|2HCLK|PLL2)" +#endif + writel(ddrpll, &misc_p->pll_ctr_reg); + + writel(readl(&misc_p->periph1_clken) | PERIPH_MPMC_EN, + &misc_p->periph1_clken); +} + +static void mpmc_init_values(void) +{ + u32 i; + u32 *mpmc_reg_p = (u32 *)CONFIG_SPEAR_MPMCBASE; + u32 *mpmc_val_p = &mpmc_conf_vals[0]; + + for (i = 0; i < CONFIG_SPEAR_MPMCREGS; i++, mpmc_reg_p++, mpmc_val_p++) + writel(*mpmc_val_p, mpmc_reg_p); + + mpmc_reg_p = (u32 *)CONFIG_SPEAR_MPMCBASE; + + /* + * MPMC controller start + * MPMC waiting for DLLLOCKREG high + */ + writel(0x01000100, &mpmc_reg_p[7]); + + while (!(readl(&mpmc_reg_p[3]) & 0x10000)) + ; +} + +static void mpmc_init(void) +{ + /* Clock related settings for DDR */ + ddr_clock_init(); + + /* + * DDR pad register bits are different for different SoCs + * Compensation values are also handled separately + */ + plat_ddr_init(); + + /* Initialize mpmc register values */ + mpmc_init_values(); +} + +static void pll_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + + /* Initialize PLLs */ + writel(FREQ_332, &misc_p->pll1_frq); + writel(0x1C0A, &misc_p->pll1_cntl); + writel(0x1C0E, &misc_p->pll1_cntl); + writel(0x1C06, &misc_p->pll1_cntl); + writel(0x1C0E, &misc_p->pll1_cntl); + + writel(FREQ_332, &misc_p->pll2_frq); + writel(0x1C0A, &misc_p->pll2_cntl); + writel(0x1C0E, &misc_p->pll2_cntl); + writel(0x1C06, &misc_p->pll2_cntl); + writel(0x1C0E, &misc_p->pll2_cntl); + + /* wait for pll locks */ + while (!(readl(&misc_p->pll1_cntl) & 0x1)) + ; + while (!(readl(&misc_p->pll2_cntl) & 0x1)) + ; +} + +static void mac_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + + writel(readl(&misc_p->periph1_clken) & (~PERIPH_GMAC), + &misc_p->periph1_clken); + + writel(SYNTH23, &misc_p->gmac_synth_clk); + + switch (get_socrev()) { + case SOC_SPEAR600_AA: + case SOC_SPEAR600_AB: + case SOC_SPEAR600_BA: + case SOC_SPEAR600_BB: + case SOC_SPEAR600_BC: + case SOC_SPEAR600_BD: + writel(0x0, &misc_p->gmac_ctr_reg); + break; + + case SOC_SPEAR300: + case SOC_SPEAR310: + case SOC_SPEAR320: + writel(0x4, &misc_p->gmac_ctr_reg); + break; + } + + writel(readl(&misc_p->periph1_clken) | PERIPH_GMAC, + &misc_p->periph1_clken); + + writel(readl(&misc_p->periph1_rst) | PERIPH_GMAC, + &misc_p->periph1_rst); + writel(readl(&misc_p->periph1_rst) & (~PERIPH_GMAC), + &misc_p->periph1_rst); +} + +static void sys_init(void) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + struct syscntl_regs *syscntl_p = + (struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE; + + /* Set system state to SLOW */ + writel(SLOW, &syscntl_p->scctrl); + writel(PLL_TIM << 3, &syscntl_p->scpllctrl); + + /* Initialize PLLs */ + pll_init(); + + /* + * Ethernet configuration + * To be done only if the tftp boot is not selected already + * Boot code ensures the correct configuration in tftp booting + */ + if (!tftp_boot_selected()) + mac_init(); + + writel(RTC_DISABLE | PLLTIMEEN, &misc_p->periph_clk_cfg); + writel(0x555, &misc_p->amba_clk_cfg); + + writel(NORMAL, &syscntl_p->scctrl); + + /* Wait for system to switch to normal mode */ + while (((readl(&syscntl_p->scctrl) >> MODE_SHIFT) & MODE_MASK) + != NORMAL) + ; +} + +/* + * get_socrev + * + * Get SoC Revision. + * @return SOC_SPEARXXX + */ +int get_socrev(void) +{ +#if defined(CONFIG_SPEAR600) + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 soc_id = readl(&misc_p->soc_core_id); + u32 pri_socid = (soc_id >> SOC_PRI_SHFT) & 0xFF; + u32 sec_socid = (soc_id >> SOC_SEC_SHFT) & 0xFF; + + if ((pri_socid == 'B') && (sec_socid == 'B')) + return SOC_SPEAR600_BB; + else if ((pri_socid == 'B') && (sec_socid == 'C')) + return SOC_SPEAR600_BC; + else if ((pri_socid == 'B') && (sec_socid == 'D')) + return SOC_SPEAR600_BD; + else if (soc_id == 0) + return SOC_SPEAR600_BA; + else + return SOC_SPEAR_NA; +#elif defined(CONFIG_SPEAR300) + return SOC_SPEAR300; +#elif defined(CONFIG_SPEAR310) + return SOC_SPEAR310; +#elif defined(CONFIG_SPEAR320) + return SOC_SPEAR320; +#endif +} + +/* + * SNOR (Serial NOR flash) related functions + */ +static void snor_init(void) +{ + struct smi_regs *const smicntl = + (struct smi_regs * const)CONFIG_SYS_SMI_BASE; + + /* Setting the fast mode values. SMI working at 166/4 = 41.5 MHz */ + writel(HOLD1 | FAST_MODE | BANK_EN | DSEL_TIME | PRESCAL4, + &smicntl->smi_cr1); +} + +u32 spl_boot_device(void) +{ + u32 mode = 0; + + /* Currently only SNOR is supported as the only */ + if (snor_boot_selected()) { + /* SNOR-SMI initialization */ + snor_init(); + + mode = BOOT_DEVICE_NOR; + } + + return mode; +} + +void board_init_f(ulong dummy) +{ + struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + + /* Initialize PLLs */ + sys_init(); + + preloader_console_init(); + arch_cpu_init(); + + /* Enable IPs (release reset) */ + writel(PERIPH_RST_ALL, &misc_p->periph1_rst); + + /* Initialize MPMC */ + puts("Configure DDR\n"); + mpmc_init(); + spear_late_init(); + + board_init_r(NULL, 0); +}
diff --git a/arch/arm/cpu/arm926ejs/spear/spr600_mt47h128m8_3_266_cl5_async.c b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h128m8_3_266_cl5_async.c new file mode 100644 index 0000000..79ab2a7 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h128m8_3_266_cl5_async.c
@@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2000-2009 + * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com + */ + +#include <common.h> + +#if (CONFIG_DDR_PLL2) + +const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = { + 0x00000001, + 0x00000000, + 0x01000000, + 0x00000101, + 0x00000001, + 0x01000000, + 0x00010001, + 0x00000100, + 0x00010001, + 0x00000003, + 0x01000201, + 0x06000202, + 0x06060106, + 0x03050502, + 0x03040404, + 0x02020503, + 0x02010106, + 0x03000404, + 0x02030202, + 0x03000204, + 0x0707073f, + 0x07070707, + 0x06060607, + 0x06060606, + 0x05050506, + 0x05050505, + 0x04040405, + 0x04040404, + 0x03030304, + 0x03030303, + 0x02020203, + 0x02020202, + 0x01010102, + 0x01010101, + 0x08080a01, + 0x0000023f, + 0x00040800, + 0x00000000, + 0x00000f02, + 0x00001b1b, + 0x7f000000, + 0x005f0000, + 0x1c040b6a, + 0x00640064, + 0x00640064, + 0x00640064, + 0x00000064, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x000007ff, + 0x00000000, + 0x47ec00c8, + 0x00c8001f, + 0x00000000, + 0x0000cd98, + 0x00000000, + 0x03030100, + 0x03030303, + 0x03030303, + 0x03030303, + 0x00270000, + 0x00250027, + 0x00300000, + 0x008900b7, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; +#endif
diff --git a/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_333_cl5_psync.c b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_333_cl5_psync.c new file mode 100644 index 0000000..121b636 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_333_cl5_psync.c
@@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2000-2009 + * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com + */ + +#include <common.h> + +#if (CONFIG_DDR_PLL2 || CONFIG_DDR_2HCLK) + +const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = { +#if (CONFIG_DDR_PLL2) + 0x00000001, + 0x00000000, +#elif (CONFIG_DDR_2HCLK) + 0x02020201, + 0x02020202, +#endif + 0x01000000, + 0x00000101, + 0x00000101, + 0x01000000, + 0x00010001, + 0x00000100, + 0x01010001, + 0x00000201, + 0x01000101, + 0x06000002, + 0x06060106, + 0x03050502, + 0x03040404, + 0x02020503, + 0x02010106, + 0x03000405, + 0x03040202, + 0x04000305, + 0x0707073f, + 0x07070707, + 0x06060607, + 0x06060606, + 0x05050506, + 0x05050505, + 0x04040405, + 0x04040404, + 0x03030304, + 0x03030303, + 0x02020203, + 0x02020202, + 0x01010102, + 0x01010101, + 0x0a0a0a01, + 0x0000023f, + 0x00050a00, + 0x11000000, + 0x00001302, + 0x00000A0A, + 0x72000000, + 0x00550000, + 0x2b050e86, + 0x00640064, + 0x00640064, + 0x00640064, + 0x00000064, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00000a24, + 0x43C20000, + 0x5b1c00c8, + 0x00c8002e, + 0x00000000, + 0x0001046b, + 0x00000000, + 0x03030100, + 0x03030303, + 0x03030303, + 0x03030303, + 0x00210000, + 0x00010021, + 0x00200000, + 0x006c0090, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; +#endif
diff --git a/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_37e_166_cl4_sync.c b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_37e_166_cl4_sync.c new file mode 100644 index 0000000..64c8bab --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h32m16_37e_166_cl4_sync.c
@@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2000-2009 + * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com + */ + +#include <common.h> + +#if (CONFIG_DDR_HCLK) + +const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = { + 0x03030301, + 0x03030303, + 0x01000000, + 0x00000101, + 0x00000001, + 0x01000000, + 0x00010001, + 0x00000100, + 0x00010001, + 0x00000003, + 0x01000201, + 0x06000202, + 0x06060106, + 0x03050502, + 0x03040404, + 0x02020503, + 0x02010106, + 0x03000404, + 0x02020202, + 0x03000203, + 0x0707073f, + 0x07070707, + 0x06060607, + 0x06060606, + 0x05050506, + 0x05050505, + 0x04040405, + 0x04040404, + 0x03030304, + 0x03030303, + 0x02020203, + 0x02020202, + 0x01010102, + 0x01010101, + 0x08080a01, + 0x0000023f, + 0x00030600, + 0x00000000, + 0x00000a02, + 0x00001c1c, + 0x7f000000, + 0x005f0000, + 0x12030743, + 0x00640064, + 0x00640064, + 0x00640064, + 0x00000064, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x0000050e, + 0x00000000, + 0x2d8900c8, + 0x00c80014, + 0x00000000, + 0x00008236, + 0x00000000, + 0x03030100, + 0x03030303, + 0x03030303, + 0x03030303, + 0x00400000, + 0x003a0040, + 0x00680000, + 0x00d80120, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; +#endif
diff --git a/arch/arm/cpu/arm926ejs/spear/spr600_mt47h64m16_3_333_cl5_psync.c b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h64m16_3_333_cl5_psync.c new file mode 100644 index 0000000..8765466 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/spr600_mt47h64m16_3_333_cl5_psync.c
@@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2000-2009 + * Vipin Kumar, ST Microelectronics, vipin.kumar@st.com + */ + +#include <common.h> + +#if (CONFIG_DDR_PLL2 || CONFIG_DDR_2HCLK) + +const u32 mpmc_conf_vals[CONFIG_SPEAR_MPMCREGS] = { +#if (CONFIG_DDR_PLL2) + 0x00000001, + 0x00000000, +#elif (CONFIG_DDR_2HCLK) + 0x02020201, + 0x02020202, +#endif + 0x01000000, + 0x00000101, + 0x00000101, + 0x01000000, + 0x00010001, + 0x00000100, + 0x01010001, + 0x00000201, + 0x01000101, + 0x06000002, + 0x06060106, + 0x03050502, + 0x03040404, + 0x02020503, +#ifdef CONFIG_X600 + 0x02030206, +#else + 0x02010106, +#endif + 0x03000405, + 0x03040202, + 0x04000305, + 0x0707073f, + 0x07070707, + 0x06060607, + 0x06060606, + 0x05050506, + 0x05050505, + 0x04040405, + 0x04040404, + 0x03030304, + 0x03030303, + 0x02020203, + 0x02020202, + 0x01010102, + 0x01010101, + 0x0a0a0a01, + 0x0000023f, + 0x00050a00, + 0x11000000, + 0x00001302, + 0x00000A0A, +#ifdef CONFIG_X600 + 0x7f000000, + 0x005c0000, +#else + 0x72000000, + 0x00550000, +#endif + 0x2b050e86, + 0x00640064, + 0x00640064, + 0x00640064, + 0x00000064, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00200020, + 0x00000a24, + 0x43C20000, + 0x5b1c00c8, + 0x00c8002e, + 0x00000000, + 0x0001046b, + 0x00000000, + 0x03030100, + 0x03030303, + 0x03030303, + 0x03030303, + 0x00210000, + 0x00010021, + 0x00200000, + 0x006c0090, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x003fffff, + 0x003fffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; +#endif
diff --git a/arch/arm/cpu/arm926ejs/spear/spr_lowlevel_init.S b/arch/arm/cpu/arm926ejs/spear/spr_lowlevel_init.S new file mode 100644 index 0000000..417e87a --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/spr_lowlevel_init.S
@@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2006 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + */ + +#include <config.h> + +/* + * platform specific initializations are already done in Xloader + * Initializations already done include + * DDR, PLLs, IP's clock enable and reset release etc + */ +.globl lowlevel_init +lowlevel_init: + mov pc, lr + +/* void setfreq(unsigned int device, unsigned int frequency) */ +.global setfreq +setfreq: + stmfd sp!,{r14} + stmfd sp!,{r0-r12} + + mov r8,sp + ldr sp,SRAM_STACK_V + + /* Saving the function arguements for later use */ + mov r4,r0 + mov r5,r1 + + /* Putting DDR into self refresh */ + ldr r0,DDR_07_V + ldr r1,[r0] + ldr r2,DDR_ACTIVE_V + bic r1, r1, r2 + str r1,[r0] + ldr r0,DDR_57_V + ldr r1,[r0] + ldr r2,CYCLES_MASK_V + bic r1, r1, r2 + ldr r2,REFRESH_CYCLES_V + orr r1, r1, r2, lsl #16 + str r1,[r0] + ldr r0,DDR_07_V + ldr r1,[r0] + ldr r2,SREFRESH_MASK_V + orr r1, r1, r2 + str r1,[r0] + + /* flush pipeline */ + b flush + .align 5 +flush: + /* Delay to ensure self refresh mode */ + ldr r0,SREFRESH_DELAY_V +delay: + sub r0,r0,#1 + cmp r0,#0 + bne delay + + /* Putting system in slow mode */ + ldr r0,SCCTRL_V + mov r1,#2 + str r1,[r0] + + /* Changing PLL(1/2) frequency */ + mov r0,r4 + mov r1,r5 + + cmp r4,#0 + beq pll1_freq + + /* Change PLL2 (DDR frequency) */ + ldr r6,PLL2_FREQ_V + ldr r7,PLL2_CNTL_V + b pll2_freq + +pll1_freq: + /* Change PLL1 (CPU frequency) */ + ldr r6,PLL1_FREQ_V + ldr r7,PLL1_CNTL_V + +pll2_freq: + mov r0,r6 + ldr r1,[r0] + ldr r2,PLLFREQ_MASK_V + bic r1,r1,r2 + mov r2,r5,lsr#1 + orr r1,r1,r2,lsl#24 + str r1,[r0] + + mov r0,r7 + ldr r1,P1C0A_V + str r1,[r0] + ldr r1,P1C0E_V + str r1,[r0] + ldr r1,P1C06_V + str r1,[r0] + ldr r1,P1C0E_V + str r1,[r0] + +lock: + ldr r1,[r0] + and r1,r1,#1 + cmp r1,#0 + beq lock + + /* Putting system back to normal mode */ + ldr r0,SCCTRL_V + mov r1,#4 + str r1,[r0] + + /* Putting DDR back to normal */ + ldr r0,DDR_07_V + ldr r1,[R0] + ldr r2,SREFRESH_MASK_V + bic r1, r1, r2 + str r1,[r0] + ldr r2,DDR_ACTIVE_V + orr r1, r1, r2 + str r1,[r0] + + /* Delay to ensure self refresh mode */ + ldr r0,SREFRESH_DELAY_V +1: + sub r0,r0,#1 + cmp r0,#0 + bne 1b + + mov sp,r8 + /* Resuming back to code */ + ldmia sp!,{r0-r12} + ldmia sp!,{pc} + +SCCTRL_V: + .word 0xfca00000 +PLL1_FREQ_V: + .word 0xfca8000C +PLL1_CNTL_V: + .word 0xfca80008 +PLL2_FREQ_V: + .word 0xfca80018 +PLL2_CNTL_V: + .word 0xfca80014 +PLLFREQ_MASK_V: + .word 0xff000000 +P1C0A_V: + .word 0x1C0A +P1C0E_V: + .word 0x1C0E +P1C06_V: + .word 0x1C06 + +SREFRESH_DELAY_V: + .word 0x9999 +SRAM_STACK_V: + .word 0xD2800600 +DDR_07_V: + .word 0xfc60001c +DDR_ACTIVE_V: + .word 0x01000000 +DDR_57_V: + .word 0xfc6000e4 +CYCLES_MASK_V: + .word 0xffff0000 +REFRESH_CYCLES_V: + .word 0xf0f0 +SREFRESH_MASK_V: + .word 0x00010000 + +.global setfreq_sz +setfreq_sz: + .word setfreq_sz - setfreq
diff --git a/arch/arm/cpu/arm926ejs/spear/spr_misc.c b/arch/arm/cpu/arm926ejs/spear/spr_misc.c new file mode 100644 index 0000000..371dea5 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/spr_misc.c
@@ -0,0 +1,249 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2009 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + */ + +#include <common.h> +#include <command.h> +#include <environment.h> +#include <i2c.h> +#include <net.h> +#include <linux/mtd/st_smi.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spr_emi.h> +#include <asm/arch/spr_defs.h> + +#define CPU 0 +#define DDR 1 +#define SRAM_REL 0xD2801000 + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_CMD_NET) +static int i2c_read_mac(uchar *buffer); +#endif + +int dram_init(void) +{ + /* Store complete RAM size and return */ + gd->ram_size = get_ram_size(PHYS_SDRAM_1, PHYS_SDRAM_1_MAXSIZE); + + return 0; +} + +int dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = gd->ram_size; + + return 0; +} + +int board_early_init_f() +{ +#if defined(CONFIG_ST_SMI) + smi_init(); +#endif + return 0; +} +int misc_init_r(void) +{ +#if defined(CONFIG_CMD_NET) + uchar mac_id[6]; + + if (!eth_env_get_enetaddr("ethaddr", mac_id) && !i2c_read_mac(mac_id)) + eth_env_set_enetaddr("ethaddr", mac_id); +#endif + env_set("verify", "n"); + +#if defined(CONFIG_SPEAR_USBTTY) + env_set("stdin", "usbtty"); + env_set("stdout", "usbtty"); + env_set("stderr", "usbtty"); + +#ifndef CONFIG_SYS_NO_DCACHE + dcache_enable(); +#endif +#endif + return 0; +} + +#ifdef CONFIG_SPEAR_EMI +struct cust_emi_para { + unsigned int tap; + unsigned int tsdp; + unsigned int tdpw; + unsigned int tdpr; + unsigned int tdcs; +}; + +/* EMI timing setting of m28w640hc of linux kernel */ +const struct cust_emi_para emi_timing_m28w640hc = { + .tap = 0x10, + .tsdp = 0x05, + .tdpw = 0x0a, + .tdpr = 0x0a, + .tdcs = 0x05, +}; + +/* EMI timing setting of bootrom */ +const struct cust_emi_para emi_timing_bootrom = { + .tap = 0xf, + .tsdp = 0x0, + .tdpw = 0xff, + .tdpr = 0x111, + .tdcs = 0x02, +}; + +void spear_emi_init(void) +{ + const struct cust_emi_para *p = &emi_timing_m28w640hc; + struct emi_regs *emi_regs_p = (struct emi_regs *)CONFIG_SPEAR_EMIBASE; + unsigned int cs; + unsigned int val, tmp; + + val = readl(CONFIG_SPEAR_RASBASE); + + if (val & EMI_ACKMSK) + tmp = 0x3f; + else + tmp = 0x0; + + writel(tmp, &emi_regs_p->ack); + + for (cs = 0; cs < CONFIG_SYS_MAX_FLASH_BANKS; cs++) { + writel(p->tap, &emi_regs_p->bank_regs[cs].tap); + writel(p->tsdp, &emi_regs_p->bank_regs[cs].tsdp); + writel(p->tdpw, &emi_regs_p->bank_regs[cs].tdpw); + writel(p->tdpr, &emi_regs_p->bank_regs[cs].tdpr); + writel(p->tdcs, &emi_regs_p->bank_regs[cs].tdcs); + writel(EMI_CNTL_ENBBYTERW | ((val & 0x18) >> 3), + &emi_regs_p->bank_regs[cs].control); + } +} +#endif + +int spear_board_init(ulong mach_type) +{ + gd->bd->bi_arch_number = mach_type; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = CONFIG_BOOT_PARAMS_ADDR; + +#ifdef CONFIG_SPEAR_EMI + spear_emi_init(); +#endif + return 0; +} + +#if defined(CONFIG_CMD_NET) +static int i2c_read_mac(uchar *buffer) +{ + u8 buf[2]; + + i2c_read(CONFIG_I2C_CHIPADDRESS, MAGIC_OFF, 1, buf, MAGIC_LEN); + + /* Check if mac in i2c memory is valid */ + if ((buf[0] == MAGIC_BYTE0) && (buf[1] == MAGIC_BYTE1)) { + /* Valid mac address is saved in i2c eeprom */ + i2c_read(CONFIG_I2C_CHIPADDRESS, MAC_OFF, 1, buffer, MAC_LEN); + return 0; + } + + return -1; +} + +static int write_mac(uchar *mac) +{ + u8 buf[2]; + + buf[0] = (u8)MAGIC_BYTE0; + buf[1] = (u8)MAGIC_BYTE1; + i2c_write(CONFIG_I2C_CHIPADDRESS, MAGIC_OFF, 1, buf, MAGIC_LEN); + + buf[0] = (u8)~MAGIC_BYTE0; + buf[1] = (u8)~MAGIC_BYTE1; + + i2c_read(CONFIG_I2C_CHIPADDRESS, MAGIC_OFF, 1, buf, MAGIC_LEN); + + /* check if valid MAC address is saved in I2C EEPROM or not? */ + if ((buf[0] == MAGIC_BYTE0) && (buf[1] == MAGIC_BYTE1)) { + i2c_write(CONFIG_I2C_CHIPADDRESS, MAC_OFF, 1, mac, MAC_LEN); + puts("I2C EEPROM written with mac address \n"); + return 0; + } + + puts("I2C EEPROM writing failed\n"); + return -1; +} +#endif + +int do_chip_config(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + void (*sram_setfreq) (unsigned int, unsigned int); + unsigned int frequency; +#if defined(CONFIG_CMD_NET) + unsigned char mac[6]; +#endif + + if ((argc > 3) || (argc < 2)) + return cmd_usage(cmdtp); + + if ((!strcmp(argv[1], "cpufreq")) || (!strcmp(argv[1], "ddrfreq"))) { + + frequency = simple_strtoul(argv[2], NULL, 0); + + if (frequency > 333) { + printf("Frequency is limited to 333MHz\n"); + return 1; + } + + sram_setfreq = memcpy((void *)SRAM_REL, setfreq, setfreq_sz); + + if (!strcmp(argv[1], "cpufreq")) { + sram_setfreq(CPU, frequency); + printf("CPU frequency changed to %u\n", frequency); + } else { + sram_setfreq(DDR, frequency); + printf("DDR frequency changed to %u\n", frequency); + } + + return 0; + +#if defined(CONFIG_CMD_NET) + } else if (!strcmp(argv[1], "ethaddr")) { + + u32 reg; + char *e, *s = argv[2]; + for (reg = 0; reg < 6; ++reg) { + mac[reg] = s ? simple_strtoul(s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + write_mac(mac); + + return 0; +#endif + } else if (!strcmp(argv[1], "print")) { +#if defined(CONFIG_CMD_NET) + if (!i2c_read_mac(mac)) { + printf("Ethaddr (from i2c mem) = %pM\n", mac); + } else { + printf("Ethaddr (from i2c mem) = Not set\n"); + } +#endif + return 0; + } + + return cmd_usage(cmdtp); +} + +U_BOOT_CMD(chip_config, 3, 1, do_chip_config, + "configure chip", + "chip_config cpufreq/ddrfreq frequency\n" +#if defined(CONFIG_CMD_NET) + "chip_config ethaddr XX:XX:XX:XX:XX:XX\n" +#endif + "chip_config print");
diff --git a/arch/arm/cpu/arm926ejs/spear/start.S b/arch/arm/cpu/arm926ejs/spear/start.S new file mode 100644 index 0000000..1cab4ca --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/start.S
@@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + */ + + +#include <config.h> + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * Below are the critical initializations already taken place in BootROM. + * So, these are not taken care in Xloader + * 1. Relocation to RAM + * 2. Initializing stacks + * + ************************************************************************* + */ + + .globl reset + +reset: +/* + * Xloader has to return back to BootROM in a few cases. + * eg. Ethernet boot, UART boot, USB boot + * Saving registers for returning back + */ + stmdb sp!, {r0-r12,r14} + bl cpu_init_crit +/* + * Clearing bss area is not done in Xloader. + * BSS area lies in the DDR location which is not yet initialized + * bss is assumed to be uninitialized. + */ + ldmia sp!, {r0-r12,pc} + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ +cpu_init_crit: + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ + mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ + + /* + * enable instruction cache + */ + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ + mcr p15, 0, r0, c1, c0, 0 + + /* + * Go setup Memory and board specific bits prior to relocation. + */ + stmdb sp!, {lr} + bl _main /* _main will call board_init_f */ + ldmia sp!, {pc}
diff --git a/arch/arm/cpu/arm926ejs/spear/timer.c b/arch/arm/cpu/arm926ejs/spear/timer.c new file mode 100644 index 0000000..e7b5bda --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/timer.c
@@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2009 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/spr_gpt.h> +#include <asm/arch/spr_misc.h> + +#define GPT_RESOLUTION (CONFIG_SPEAR_HZ_CLOCK / CONFIG_SPEAR_HZ) +#define READ_TIMER() (readl(&gpt_regs_p->count) & GPT_FREE_RUNNING) + +static struct gpt_regs *const gpt_regs_p = + (struct gpt_regs *)CONFIG_SPEAR_TIMERBASE; + +static struct misc_regs *const misc_regs_p = + (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + +DECLARE_GLOBAL_DATA_PTR; + +static ulong get_timer_masked(void); + +#define timestamp gd->arch.tbl +#define lastdec gd->arch.lastinc + +int timer_init(void) +{ + u32 synth; + + /* Prescaler setting */ +#if defined(CONFIG_SPEAR3XX) + writel(MISC_PRSC_CFG, &misc_regs_p->prsc2_clk_cfg); + synth = MISC_GPT4SYNTH; +#elif defined(CONFIG_SPEAR600) + writel(MISC_PRSC_CFG, &misc_regs_p->prsc1_clk_cfg); + synth = MISC_GPT3SYNTH; +#else +# error Incorrect config. Can only be SPEAR{600|300|310|320} +#endif + + writel(readl(&misc_regs_p->periph_clk_cfg) | synth, + &misc_regs_p->periph_clk_cfg); + + /* disable timers */ + writel(GPT_PRESCALER_1 | GPT_MODE_AUTO_RELOAD, &gpt_regs_p->control); + + /* load value for free running */ + writel(GPT_FREE_RUNNING, &gpt_regs_p->compare); + + /* auto reload, start timer */ + writel(readl(&gpt_regs_p->control) | GPT_ENABLE, &gpt_regs_p->control); + + /* Reset the timer */ + lastdec = READ_TIMER(); + timestamp = 0; + + return 0; +} + +/* + * timer without interrupts + */ +ulong get_timer(ulong base) +{ + return (get_timer_masked() / GPT_RESOLUTION) - base; +} + +void __udelay(unsigned long usec) +{ + ulong tmo; + ulong start = get_timer_masked(); + ulong tenudelcnt = CONFIG_SPEAR_HZ_CLOCK / (1000 * 100); + ulong rndoff; + + rndoff = (usec % 10) ? 1 : 0; + + /* tenudelcnt timer tick gives 10 microsecconds delay */ + tmo = ((usec / 10) + rndoff) * tenudelcnt; + + while ((ulong) (get_timer_masked() - start) < tmo) + ; +} + +static ulong get_timer_masked(void) +{ + ulong now = READ_TIMER(); + + if (now >= lastdec) { + /* normal mode */ + timestamp += now - lastdec; + } else { + /* we have an overflow ... */ + timestamp += now + GPT_FREE_RUNNING - lastdec; + } + lastdec = now; + + return timestamp; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CONFIG_SPEAR_HZ; +}
diff --git a/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds b/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds new file mode 100644 index 0000000..569704c --- /dev/null +++ b/arch/arm/cpu/arm926ejs/spear/u-boot-spl.lds
@@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2015 Stefan Roese <sr@denx.de> + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * on behalf of DENX Software Engineering GmbH + * + * January 2004 - Changed to support H4 device + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ + LENGTH = CONFIG_SPL_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : + { + __start = .; + *(.vectors) + CPUDIR/spear/start.o (.text*) + *(.text*) + } > .sram + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram + + . = ALIGN(4); + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } > .sram + + . = ALIGN(4); + __image_copy_end = .; + _end = .; + + .bss : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } > .sram +}
diff --git a/arch/arm/cpu/arm926ejs/start.S b/arch/arm/cpu/arm926ejs/start.S new file mode 100644 index 0000000..1045673 --- /dev/null +++ b/arch/arm/cpu/arm926ejs/start.S
@@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * Copyright (c) 2010 Albert Aribaud <albert.u.boot@aribaud.net> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <common.h> + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + + .globl reset + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + bx lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit: + /* + * flush D cache before disabling it + */ + mov r0, #0 +flush_dcache: + mrc p15, 0, r15, c7, c10, 3 + bne flush_dcache + + mcr p15, 0, r0, c8, c7, 0 /* invalidate TLB */ + mcr p15, 0, r0, c7, c5, 0 /* invalidate I Cache */ + + /* + * disable MMU and D cache + * enable I cache if CONFIG_SYS_ICACHE_OFF is not defined + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00000300 /* clear bits 9:8 (---- --RS) */ + bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ +#ifdef CONFIG_SYS_EXCEPTION_VECTORS_HIGH + orr r0, r0, #0x00002000 /* set bit 13 (--V- ----) */ +#else + bic r0, r0, #0x00002000 /* clear bit 13 (--V- ----) */ +#endif + orr r0, r0, #0x00000002 /* set bit 1 (A) Align */ +#ifndef CONFIG_SYS_ICACHE_OFF + orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ +#endif + mcr p15, 0, r0, c1, c0, 0 + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY + /* + * Go setup Memory and board specific bits prior to relocation. + */ + mov r4, lr /* perserve link reg across call */ + bl lowlevel_init /* go setup pll,mux,memory */ + mov lr, r4 /* restore link */ +#endif + mov pc, lr /* back to my caller */ +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
diff --git a/arch/arm/cpu/arm946es/Makefile b/arch/arm/cpu/arm946es/Makefile new file mode 100644 index 0000000..24cebe3 --- /dev/null +++ b/arch/arm/cpu/arm946es/Makefile
@@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-y = start.o + +obj-y = cpu.o
diff --git a/arch/arm/cpu/arm946es/cpu.c b/arch/arm/cpu/arm946es/cpu.c new file mode 100644 index 0000000..3b4f5de --- /dev/null +++ b/arch/arm/cpu/arm946es/cpu.c
@@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> +#include <asm/io.h> + +static void cache_flush(void); + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + + disable_interrupts (); + + /* ARM926E-S needs the protection unit enabled for the icache to have + * been enabled - left for possible later use + * should turn off the protection unit as well.... + */ + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + /* flush I/D-cache */ + cache_flush(); + + return 0; +} + +/* flush I/D-cache */ +static void cache_flush (void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (i)); + asm ("mcr p15, 0, %0, c7, c6, 0": :"r" (i)); +} + +#ifndef CONFIG_ARCH_INTEGRATOR + +__attribute__((noreturn)) void reset_cpu(ulong addr __attribute__((unused))) +{ + writew(0x0, 0xfffece10); + writew(0x8, 0xfffece10); + for (;;) + ; +} + +#endif /* #ifdef CONFIG_ARCH_INTEGRATOR */
diff --git a/arch/arm/cpu/arm946es/start.S b/arch/arm/cpu/arm946es/start.S new file mode 100644 index 0000000..0ec340b --- /dev/null +++ b/arch/arm/cpu/arm946es/start.S
@@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * Copyright (c) 2010 Albert Aribaud <albert.u.boot@aribaud.net> + */ + +#include <asm-offsets.h> +#include <config.h> + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + + .globl reset + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + mov pc, lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit: + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 /* flush v4 I-cache */ + mcr p15, 0, r0, c7, c6, 0 /* flush v4 D-cache */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ + bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ + orr r0, r0, #0x00000002 /* set bit 1 (A) Align */ + orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ + mcr p15, 0, r0, c1, c0, 0 + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY + /* + * Go setup Memory and board specific bits prior to relocation. + */ + mov ip, lr /* perserve link reg across call */ + bl lowlevel_init /* go setup memory */ + mov lr, ip /* restore link */ +#endif + mov pc, lr /* back to my caller */ +#endif
diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig new file mode 100644 index 0000000..4d0dcee --- /dev/null +++ b/arch/arm/cpu/armv7/Kconfig
@@ -0,0 +1,62 @@ +if CPU_V7A + +config CPU_V7_HAS_NONSEC + bool + +config CPU_V7_HAS_VIRT + bool + +config ARCH_SUPPORT_PSCI + bool + +config ARMV7_NONSEC + bool "Enable support for booting in non-secure mode" if EXPERT + depends on CPU_V7_HAS_NONSEC + default y + ---help--- + Say Y here to enable support for booting in non-secure / SVC mode. + +config ARMV7_BOOT_SEC_DEFAULT + bool "Boot in secure mode by default" if EXPERT + depends on ARMV7_NONSEC + default y if TEGRA + ---help--- + Say Y here to boot in secure mode by default even if non-secure mode + is supported. This option is useful to boot kernels which do not + suppport booting in non-secure mode. Only set this if you need it. + This can be overridden at run-time by setting the bootm_boot_mode env. + variable to "sec" or "nonsec". + +config ARMV7_VIRT + bool "Enable support for hardware virtualization" if EXPERT + depends on CPU_V7_HAS_VIRT && ARMV7_NONSEC + default y + ---help--- + Say Y here to boot in hypervisor (HYP) mode when booting non-secure. + +config ARMV7_PSCI + bool "Enable PSCI support" if EXPERT + depends on ARMV7_NONSEC && ARCH_SUPPORT_PSCI + default y + help + Say Y here to enable PSCI support. + +config ARMV7_PSCI_NR_CPUS + int "Maximum supported CPUs for PSCI" + depends on ARMV7_NONSEC + default 4 + help + The maximum number of CPUs supported in the PSCI firmware. + It is no problem to set a larger value than the number of + CPUs in the actual hardware implementation. + +config ARMV7_LPAE + bool "Use LPAE page table format" if EXPERT + depends on CPU_V7A + default y if ARMV7_VIRT + ---help--- + Say Y here to use the long descriptor page table format. This is + required if U-Boot runs in HYP mode. + +endif +
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile new file mode 100644 index 0000000..4f4647c --- /dev/null +++ b/arch/arm/cpu/armv7/Makefile
@@ -0,0 +1,43 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-y := start.o + +obj-y += cache_v7.o cache_v7_asm.o + +obj-y += cpu.o cp15.o +obj-y += syslib.o + +obj-$(CONFIG_SYS_ARM_MPU) += mpu_v7r.o + +ifneq ($(CONFIG_SPL_BUILD),y) +obj-$(CONFIG_EFI_LOADER) += sctlr.o +endif + +ifneq ($(CONFIG_SKIP_LOWLEVEL_INIT),y) +obj-y += lowlevel_init.o +endif + +obj-$(CONFIG_ARM_SMCCC) += smccc-call.o +obj-$(CONFIG_ARMV7_NONSEC) += nonsec_virt.o virt-v7.o virt-dt.o +obj-$(CONFIG_ARMV7_PSCI) += psci.o psci-common.o + +obj-$(CONFIG_IPROC) += iproc-common/ +obj-$(CONFIG_KONA) += kona-common/ +obj-$(CONFIG_SYS_ARCH_TIMER) += arch_timer.o + +ifneq (,$(filter s5pc1xx exynos,$(SOC))) +obj-y += s5p-common/ +endif + +obj-$(if $(filter bcm235xx,$(SOC)),y) += bcm235xx/ +obj-$(if $(filter bcm281xx,$(SOC)),y) += bcm281xx/ +obj-$(if $(filter bcmcygnus,$(SOC)),y) += bcmcygnus/ +obj-$(if $(filter bcmnsp,$(SOC)),y) += bcmnsp/ +obj-$(if $(filter ls102xa,$(SOC)),y) += ls102xa/ +obj-$(CONFIG_RMOBILE) += rmobile/ +obj-$(if $(filter stv0991,$(SOC)),y) += stv0991/ +obj-$(CONFIG_ARCH_SUNXI) += sunxi/ +obj-$(CONFIG_VF610) += vf610/
diff --git a/arch/arm/cpu/armv7/arch_timer.c b/arch/arm/cpu/armv7/arch_timer.c new file mode 100644 index 0000000..3db31c0 --- /dev/null +++ b/arch/arm/cpu/armv7/arch_timer.c
@@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, <www.ti.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <div64.h> +#include <bootstage.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_HZ_CLOCK +static inline u32 read_cntfrq(void) +{ + u32 frq; + + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (frq)); + return frq; +} +#endif + +int timer_init(void) +{ + gd->arch.tbl = 0; + gd->arch.tbu = 0; + +#ifdef CONFIG_SYS_HZ_CLOCK + gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK; +#else + gd->arch.timer_rate_hz = read_cntfrq(); +#endif + return 0; +} + +unsigned long long get_ticks(void) +{ + ulong nowl, nowu; + + asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (nowl), "=r" (nowu)); + + gd->arch.tbl = nowl; + gd->arch.tbu = nowu; + + return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl; +} + + +ulong timer_get_boot_us(void) +{ + return lldiv(get_ticks(), gd->arch.timer_rate_hz / 1000000); +} + +ulong get_tbclk(void) +{ + return gd->arch.timer_rate_hz; +}
diff --git a/arch/arm/cpu/armv7/bcm235xx/Makefile b/arch/arm/cpu/armv7/bcm235xx/Makefile new file mode 100644 index 0000000..3d09126 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm235xx/Makefile
@@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2013 Broadcom Corporation. + +obj-y += clk-core.o +obj-y += clk-bcm235xx.o +obj-y += clk-sdio.o +obj-y += clk-bsc.o +obj-$(CONFIG_BCM_SF2_ETH) += clk-eth.o +obj-y += clk-usb-otg.o
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-bcm235xx.c b/arch/arm/cpu/armv7/bcm235xx/clk-bcm235xx.c new file mode 100644 index 0000000..39217c5 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm235xx/clk-bcm235xx.c
@@ -0,0 +1,568 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Broadcom Corporation. + */ + +/* + * + * bcm235xx-specific clock tables + * + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +#define CLOCK_1K 1000 +#define CLOCK_1M (CLOCK_1K * 1000) + +/* declare a reference clock */ +#define DECLARE_REF_CLK(clk_name, clk_parent, clk_rate, clk_div) \ +static struct refclk clk_name = { \ + .clk = { \ + .name = #clk_name, \ + .parent = clk_parent, \ + .rate = clk_rate, \ + .div = clk_div, \ + .ops = &ref_clk_ops, \ + }, \ +} + +/* + * Reference clocks + */ + +/* Declare a list of reference clocks */ +DECLARE_REF_CLK(ref_crystal, 0, 26 * CLOCK_1M, 1); +DECLARE_REF_CLK(var_96m, 0, 96 * CLOCK_1M, 1); +DECLARE_REF_CLK(ref_96m, 0, 96 * CLOCK_1M, 1); +DECLARE_REF_CLK(ref_312m, 0, 312 * CLOCK_1M, 0); +DECLARE_REF_CLK(ref_104m, &ref_312m.clk, 104 * CLOCK_1M, 3); +DECLARE_REF_CLK(ref_52m, &ref_104m.clk, 52 * CLOCK_1M, 2); +DECLARE_REF_CLK(ref_13m, &ref_52m.clk, 13 * CLOCK_1M, 4); +DECLARE_REF_CLK(var_312m, 0, 312 * CLOCK_1M, 0); +DECLARE_REF_CLK(var_104m, &var_312m.clk, 104 * CLOCK_1M, 3); +DECLARE_REF_CLK(var_52m, &var_104m.clk, 52 * CLOCK_1M, 2); +DECLARE_REF_CLK(var_13m, &var_52m.clk, 13 * CLOCK_1M, 4); + +struct refclk_lkup { + struct refclk *procclk; + const char *name; +}; + +/* Lookup table for string to clk tranlation */ +#define MKSTR(x) {&x, #x} +static struct refclk_lkup refclk_str_tbl[] = { + MKSTR(ref_crystal), MKSTR(var_96m), MKSTR(ref_96m), + MKSTR(ref_312m), MKSTR(ref_104m), MKSTR(ref_52m), + MKSTR(ref_13m), MKSTR(var_312m), MKSTR(var_104m), + MKSTR(var_52m), MKSTR(var_13m), +}; + +int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]); + +/* convert ref clock string to clock structure pointer */ +struct refclk *refclk_str_to_clk(const char *name) +{ + int i; + struct refclk_lkup *tblp = refclk_str_tbl; + for (i = 0; i < refclk_entries; i++, tblp++) { + if (!(strcmp(name, tblp->name))) + return tblp->procclk; + } + return NULL; +} + +/* frequency tables indexed by freq_id */ +unsigned long master_axi_freq_tbl[8] = { + 26 * CLOCK_1M, + 52 * CLOCK_1M, + 104 * CLOCK_1M, + 156 * CLOCK_1M, + 156 * CLOCK_1M, + 208 * CLOCK_1M, + 312 * CLOCK_1M, + 312 * CLOCK_1M +}; + +unsigned long master_ahb_freq_tbl[8] = { + 26 * CLOCK_1M, + 52 * CLOCK_1M, + 52 * CLOCK_1M, + 52 * CLOCK_1M, + 78 * CLOCK_1M, + 104 * CLOCK_1M, + 104 * CLOCK_1M, + 156 * CLOCK_1M +}; + +unsigned long slave_axi_freq_tbl[8] = { + 26 * CLOCK_1M, + 52 * CLOCK_1M, + 78 * CLOCK_1M, + 104 * CLOCK_1M, + 156 * CLOCK_1M, + 156 * CLOCK_1M +}; + +unsigned long slave_apb_freq_tbl[8] = { + 26 * CLOCK_1M, + 26 * CLOCK_1M, + 39 * CLOCK_1M, + 52 * CLOCK_1M, + 52 * CLOCK_1M, + 78 * CLOCK_1M +}; + +unsigned long esub_freq_tbl[8] = { + 78 * CLOCK_1M, + 156 * CLOCK_1M, + 156 * CLOCK_1M, + 156 * CLOCK_1M, + 208 * CLOCK_1M, + 208 * CLOCK_1M, + 208 * CLOCK_1M +}; + +static struct bus_clk_data bsc1_apb_data = { + .gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1), +}; + +static struct bus_clk_data bsc2_apb_data = { + .gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1), +}; + +static struct bus_clk_data bsc3_apb_data = { + .gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1), +}; + +/* * Master CCU clocks */ +static struct peri_clk_data sdio1_data = { + .gate = HW_SW_GATE(0x0358, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a28, 0, 3), + .div = DIVIDER(0x0a28, 4, 14), + .trig = TRIGGER(0x0afc, 9), +}; + +static struct peri_clk_data sdio2_data = { + .gate = HW_SW_GATE(0x035c, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a2c, 0, 3), + .div = DIVIDER(0x0a2c, 4, 14), + .trig = TRIGGER(0x0afc, 10), +}; + +static struct peri_clk_data sdio3_data = { + .gate = HW_SW_GATE(0x0364, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a34, 0, 3), + .div = DIVIDER(0x0a34, 4, 14), + .trig = TRIGGER(0x0afc, 12), +}; + +static struct peri_clk_data sdio4_data = { + .gate = HW_SW_GATE(0x0360, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a30, 0, 3), + .div = DIVIDER(0x0a30, 4, 14), + .trig = TRIGGER(0x0afc, 11), +}; + +static struct peri_clk_data sdio1_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x0358, 20, 4), +}; + +static struct peri_clk_data sdio2_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x035c, 20, 4), +}; + +static struct peri_clk_data sdio3_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x0364, 20, 4), +}; + +static struct peri_clk_data sdio4_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x0360, 20, 4), +}; + +static struct bus_clk_data usb_otg_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0348, 16, 0, 1), +}; + +static struct bus_clk_data sdio1_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0358, 16, 0, 1), +}; + +static struct bus_clk_data sdio2_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x035c, 16, 0, 1), +}; + +static struct bus_clk_data sdio3_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0364, 16, 0, 1), +}; + +static struct bus_clk_data sdio4_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0360, 16, 0, 1), +}; + +/* * Slave CCU clocks */ +static struct peri_clk_data bsc1_data = { + .gate = HW_SW_GATE(0x0458, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_104m", + "ref_104m", + "var_13m", + "ref_13m"), + .sel = SELECTOR(0x0a64, 0, 3), + .trig = TRIGGER(0x0afc, 23), +}; + +static struct peri_clk_data bsc2_data = { + .gate = HW_SW_GATE(0x045c, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_104m", + "ref_104m", + "var_13m", + "ref_13m"), + .sel = SELECTOR(0x0a68, 0, 3), + .trig = TRIGGER(0x0afc, 24), +}; + +static struct peri_clk_data bsc3_data = { + .gate = HW_SW_GATE(0x0484, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_104m", + "ref_104m", + "var_13m", + "ref_13m"), + .sel = SELECTOR(0x0a84, 0, 3), + .trig = TRIGGER(0x0b00, 2), +}; + +/* + * CCU clocks + */ + +static struct ccu_clock kpm_ccu_clk = { + .clk = { + .name = "kpm_ccu_clk", + .ops = &ccu_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .num_policy_masks = 1, + .policy_freq_offset = 0x00000008, + .freq_bit_shift = 8, + .policy_ctl_offset = 0x0000000c, + .policy0_mask_offset = 0x00000010, + .policy1_mask_offset = 0x00000014, + .policy2_mask_offset = 0x00000018, + .policy3_mask_offset = 0x0000001c, + .lvm_en_offset = 0x00000034, + .freq_id = 2, + .freq_tbl = master_axi_freq_tbl, +}; + +static struct ccu_clock kps_ccu_clk = { + .clk = { + .name = "kps_ccu_clk", + .ops = &ccu_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .num_policy_masks = 1, + .policy_freq_offset = 0x00000008, + .freq_bit_shift = 8, + .policy_ctl_offset = 0x0000000c, + .policy0_mask_offset = 0x00000010, + .policy1_mask_offset = 0x00000014, + .policy2_mask_offset = 0x00000018, + .policy3_mask_offset = 0x0000001c, + .lvm_en_offset = 0x00000034, + .freq_id = 2, + .freq_tbl = slave_axi_freq_tbl, +}; + +#ifdef CONFIG_BCM_SF2_ETH +static struct ccu_clock esub_ccu_clk = { + .clk = { + .name = "esub_ccu_clk", + .ops = &ccu_clk_ops, + .ccu_clk_mgr_base = ESUB_CLK_BASE_ADDR, + }, + .num_policy_masks = 1, + .policy_freq_offset = 0x00000008, + .freq_bit_shift = 8, + .policy_ctl_offset = 0x0000000c, + .policy0_mask_offset = 0x00000010, + .policy1_mask_offset = 0x00000014, + .policy2_mask_offset = 0x00000018, + .policy3_mask_offset = 0x0000001c, + .lvm_en_offset = 0x00000034, + .freq_id = 2, + .freq_tbl = esub_freq_tbl, +}; +#endif + +/* + * Bus clocks + */ + +/* KPM bus clocks */ +static struct bus_clock usb_otg_ahb_clk = { + .clk = { + .name = "usb_otg_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &usb_otg_ahb_data, +}; + +static struct bus_clock sdio1_ahb_clk = { + .clk = { + .name = "sdio1_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio1_ahb_data, +}; + +static struct bus_clock sdio2_ahb_clk = { + .clk = { + .name = "sdio2_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio2_ahb_data, +}; + +static struct bus_clock sdio3_ahb_clk = { + .clk = { + .name = "sdio3_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio3_ahb_data, +}; + +static struct bus_clock sdio4_ahb_clk = { + .clk = { + .name = "sdio4_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio4_ahb_data, +}; + +static struct bus_clock bsc1_apb_clk = { + .clk = { + .name = "bsc1_apb_clk", + .parent = &kps_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .freq_tbl = slave_apb_freq_tbl, + .data = &bsc1_apb_data, +}; + +static struct bus_clock bsc2_apb_clk = { + .clk = { + .name = "bsc2_apb_clk", + .parent = &kps_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .freq_tbl = slave_apb_freq_tbl, + .data = &bsc2_apb_data, +}; + +static struct bus_clock bsc3_apb_clk = { + .clk = { + .name = "bsc3_apb_clk", + .parent = &kps_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .freq_tbl = slave_apb_freq_tbl, + .data = &bsc3_apb_data, +}; + +/* KPM peripheral */ +static struct peri_clock sdio1_clk = { + .clk = { + .name = "sdio1_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio1_data, +}; + +static struct peri_clock sdio2_clk = { + .clk = { + .name = "sdio2_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio2_data, +}; + +static struct peri_clock sdio3_clk = { + .clk = { + .name = "sdio3_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio3_data, +}; + +static struct peri_clock sdio4_clk = { + .clk = { + .name = "sdio4_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio4_data, +}; + +static struct peri_clock sdio1_sleep_clk = { + .clk = { + .name = "sdio1_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio1_sleep_data, +}; + +static struct peri_clock sdio2_sleep_clk = { + .clk = { + .name = "sdio2_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio2_sleep_data, +}; + +static struct peri_clock sdio3_sleep_clk = { + .clk = { + .name = "sdio3_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio3_sleep_data, +}; + +static struct peri_clock sdio4_sleep_clk = { + .clk = { + .name = "sdio4_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio4_sleep_data, +}; + +/* KPS peripheral clock */ +static struct peri_clock bsc1_clk = { + .clk = { + .name = "bsc1_clk", + .parent = &ref_13m.clk, + .rate = 13 * CLOCK_1M, + .div = 1, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .data = &bsc1_data, +}; + +static struct peri_clock bsc2_clk = { + .clk = { + .name = "bsc2_clk", + .parent = &ref_13m.clk, + .rate = 13 * CLOCK_1M, + .div = 1, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .data = &bsc2_data, +}; + +static struct peri_clock bsc3_clk = { + .clk = { + .name = "bsc3_clk", + .parent = &ref_13m.clk, + .rate = 13 * CLOCK_1M, + .div = 1, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .data = &bsc3_data, +}; + +/* public table for registering clocks */ +struct clk_lookup arch_clk_tbl[] = { + /* Peripheral clocks */ + CLK_LK(sdio1), + CLK_LK(sdio2), + CLK_LK(sdio3), + CLK_LK(sdio4), + CLK_LK(sdio1_sleep), + CLK_LK(sdio2_sleep), + CLK_LK(sdio3_sleep), + CLK_LK(sdio4_sleep), + CLK_LK(bsc1), + CLK_LK(bsc2), + CLK_LK(bsc3), + /* Bus clocks */ + CLK_LK(usb_otg_ahb), + CLK_LK(sdio1_ahb), + CLK_LK(sdio2_ahb), + CLK_LK(sdio3_ahb), + CLK_LK(sdio4_ahb), + CLK_LK(bsc1_apb), + CLK_LK(bsc2_apb), + CLK_LK(bsc3_apb), +#ifdef CONFIG_BCM_SF2_ETH + CLK_LK(esub_ccu), +#endif +}; + +/* public array size */ +unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-bsc.c b/arch/arm/cpu/armv7/bcm235xx/clk-bsc.c new file mode 100644 index 0000000..1b3f36a --- /dev/null +++ b/arch/arm/cpu/armv7/bcm235xx/clk-bsc.c
@@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Broadcom Corporation. + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +/* Enable appropriate clocks for a BSC/I2C port */ +int clk_bsc_enable(void *base) +{ + int ret; + char *bscstr, *apbstr; + + switch ((u32) base) { + case PMU_BSC_BASE_ADDR: + /* PMU clock is always enabled */ + return 0; + case BSC1_BASE_ADDR: + bscstr = "bsc1_clk"; + apbstr = "bsc1_apb_clk"; + break; + case BSC2_BASE_ADDR: + bscstr = "bsc2_clk"; + apbstr = "bsc2_apb_clk"; + break; + case BSC3_BASE_ADDR: + bscstr = "bsc3_clk"; + apbstr = "bsc3_apb_clk"; + break; + default: + printf("%s: base 0x%p not found\n", __func__, base); + return -EINVAL; + } + + /* Note that the bus clock must be enabled first */ + + ret = clk_get_and_enable(apbstr); + if (ret) + return ret; + + ret = clk_get_and_enable(bscstr); + if (ret) + return ret; + + return 0; +}
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-core.c b/arch/arm/cpu/armv7/bcm235xx/clk-core.c new file mode 100644 index 0000000..72f8eb7 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm235xx/clk-core.c
@@ -0,0 +1,512 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Broadcom Corporation. + */ + +/* + * + * bcm235xx architecture clock framework + * + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <bitfield.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +#define CLK_WR_ACCESS_PASSWORD 0x00a5a501 +#define WR_ACCESS_OFFSET 0 /* common to all clock blocks */ +#define POLICY_CTL_GO 1 /* Load and refresh policy masks */ +#define POLICY_CTL_GO_ATL 4 /* Active Load */ + +/* Helper function */ +int clk_get_and_enable(char *clkstr) +{ + int ret = 0; + struct clk *c; + + debug("%s: %s\n", __func__, clkstr); + + c = clk_get(clkstr); + if (c) { + ret = clk_enable(c); + if (ret) + return ret; + } else { + printf("%s: Couldn't find %s\n", __func__, clkstr); + return -EINVAL; + } + return ret; +} + +/* + * Poll a register in a CCU's address space, returning when the + * specified bit in that register's value is set (or clear). Delay + * a microsecond after each read of the register. Returns true if + * successful, or false if we gave up trying. + * + * Caller must ensure the CCU lock is held. + */ +#define CLK_GATE_DELAY_USEC 2000 +static inline int wait_bit(void *base, u32 offset, u32 bit, bool want) +{ + unsigned int tries; + u32 bit_mask = 1 << bit; + + for (tries = 0; tries < CLK_GATE_DELAY_USEC; tries++) { + u32 val; + bool bit_val; + + val = readl(base + offset); + bit_val = (val & bit_mask) ? 1 : 0; + if (bit_val == want) + return 0; /* success */ + udelay(1); + } + + debug("%s: timeout on addr 0x%p, waiting for bit %d to go to %d\n", + __func__, base + offset, bit, want); + + return -ETIMEDOUT; +} + +/* Enable a peripheral clock */ +static int peri_clk_enable(struct clk *c, int enable) +{ + int ret = 0; + u32 reg; + struct peri_clock *peri_clk = to_peri_clk(c); + struct peri_clk_data *cd = peri_clk->data; + struct bcm_clk_gate *gate = &cd->gate; + void *base = (void *)c->ccu_clk_mgr_base; + + + debug("%s: %s\n", __func__, c->name); + + clk_get_rate(c); /* Make sure rate and sel are filled in */ + + /* enable access */ + writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET); + + if (enable) { + debug("%s %s set rate %lu div %lu sel %d parent %lu\n", + __func__, c->name, c->rate, c->div, c->sel, + c->parent->rate); + + /* + * clkgate - only software controllable gates are + * supported by u-boot which includes all clocks + * that matter. This avoids bringing in a lot of extra + * complexity as done in the kernel framework. + */ + if (gate_exists(gate)) { + reg = readl(base + cd->gate.offset); + reg |= (1 << cd->gate.en_bit); + writel(reg, base + cd->gate.offset); + } + + /* div and pll select */ + if (divider_exists(&cd->div)) { + reg = readl(base + cd->div.offset); + bitfield_replace(reg, cd->div.shift, cd->div.width, + c->div - 1); + writel(reg, base + cd->div.offset); + } + + /* frequency selector */ + if (selector_exists(&cd->sel)) { + reg = readl(base + cd->sel.offset); + bitfield_replace(reg, cd->sel.shift, cd->sel.width, + c->sel); + writel(reg, base + cd->sel.offset); + } + + /* trigger */ + if (trigger_exists(&cd->trig)) { + writel((1 << cd->trig.bit), base + cd->trig.offset); + + /* wait for trigger status bit to go to 0 */ + ret = wait_bit(base, cd->trig.offset, cd->trig.bit, 0); + if (ret) + return ret; + } + + /* wait for running (status_bit = 1) */ + ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 1); + if (ret) + return ret; + } else { + debug("%s disable clock %s\n", __func__, c->name); + + /* clkgate */ + reg = readl(base + cd->gate.offset); + reg &= ~(1 << cd->gate.en_bit); + writel(reg, base + cd->gate.offset); + + /* wait for stop (status_bit = 0) */ + ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 0); + } + + /* disable access */ + writel(0, base + WR_ACCESS_OFFSET); + + return ret; +} + +/* Set the rate of a peripheral clock */ +static int peri_clk_set_rate(struct clk *c, unsigned long rate) +{ + int ret = 0; + int i; + unsigned long diff; + unsigned long new_rate = 0, div = 1; + struct peri_clock *peri_clk = to_peri_clk(c); + struct peri_clk_data *cd = peri_clk->data; + const char **clock; + + debug("%s: %s\n", __func__, c->name); + diff = rate; + + i = 0; + for (clock = cd->clocks; *clock; clock++, i++) { + struct refclk *ref = refclk_str_to_clk(*clock); + if (!ref) { + printf("%s: Lookup of %s failed\n", __func__, *clock); + return -EINVAL; + } + + /* round to the new rate */ + div = ref->clk.rate / rate; + if (div == 0) + div = 1; + + new_rate = ref->clk.rate / div; + + /* get the min diff */ + if (abs(new_rate - rate) < diff) { + diff = abs(new_rate - rate); + c->sel = i; + c->parent = &ref->clk; + c->rate = new_rate; + c->div = div; + } + } + + debug("%s %s set rate %lu div %lu sel %d parent %lu\n", __func__, + c->name, c->rate, c->div, c->sel, c->parent->rate); + return ret; +} + +/* Get the rate of a peripheral clock */ +static unsigned long peri_clk_get_rate(struct clk *c) +{ + struct peri_clock *peri_clk = to_peri_clk(c); + struct peri_clk_data *cd = peri_clk->data; + void *base = (void *)c->ccu_clk_mgr_base; + int div = 1; + const char **clock; + struct refclk *ref; + u32 reg; + + debug("%s: %s\n", __func__, c->name); + if (selector_exists(&cd->sel)) { + reg = readl(base + cd->sel.offset); + c->sel = bitfield_extract(reg, cd->sel.shift, cd->sel.width); + } else { + /* + * For peri clocks that don't have a selector, the single + * reference clock will always exist at index 0. + */ + c->sel = 0; + } + + if (divider_exists(&cd->div)) { + reg = readl(base + cd->div.offset); + div = bitfield_extract(reg, cd->div.shift, cd->div.width); + div += 1; + } + + clock = cd->clocks; + ref = refclk_str_to_clk(clock[c->sel]); + if (!ref) { + printf("%s: Can't lookup %s\n", __func__, clock[c->sel]); + return 0; + } + + c->parent = &ref->clk; + c->div = div; + c->rate = c->parent->rate / c->div; + debug("%s parent rate %lu div %d sel %d rate %lu\n", __func__, + c->parent->rate, div, c->sel, c->rate); + + return c->rate; +} + +/* Peripheral clock operations */ +struct clk_ops peri_clk_ops = { + .enable = peri_clk_enable, + .set_rate = peri_clk_set_rate, + .get_rate = peri_clk_get_rate, +}; + +/* Enable a CCU clock */ +static int ccu_clk_enable(struct clk *c, int enable) +{ + struct ccu_clock *ccu_clk = to_ccu_clk(c); + void *base = (void *)c->ccu_clk_mgr_base; + int ret = 0; + u32 reg; + + debug("%s: %s\n", __func__, c->name); + if (!enable) + return -EINVAL; /* CCU clock cannot shutdown */ + + /* enable access */ + writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET); + + /* config enable for policy engine */ + writel(1, base + ccu_clk->lvm_en_offset); + + /* wait for bit to go to 0 */ + ret = wait_bit(base, ccu_clk->lvm_en_offset, 0, 0); + if (ret) + return ret; + + /* freq ID */ + if (!ccu_clk->freq_bit_shift) + ccu_clk->freq_bit_shift = 8; + + /* Set frequency id for each of the 4 policies */ + reg = ccu_clk->freq_id | + (ccu_clk->freq_id << (ccu_clk->freq_bit_shift)) | + (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 2)) | + (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 3)); + writel(reg, base + ccu_clk->policy_freq_offset); + + /* enable all clock mask */ + writel(0x7fffffff, base + ccu_clk->policy0_mask_offset); + writel(0x7fffffff, base + ccu_clk->policy1_mask_offset); + writel(0x7fffffff, base + ccu_clk->policy2_mask_offset); + writel(0x7fffffff, base + ccu_clk->policy3_mask_offset); + + if (ccu_clk->num_policy_masks == 2) { + writel(0x7fffffff, base + ccu_clk->policy0_mask2_offset); + writel(0x7fffffff, base + ccu_clk->policy1_mask2_offset); + writel(0x7fffffff, base + ccu_clk->policy2_mask2_offset); + writel(0x7fffffff, base + ccu_clk->policy3_mask2_offset); + } + + /* start policy engine */ + reg = readl(base + ccu_clk->policy_ctl_offset); + reg |= (POLICY_CTL_GO + POLICY_CTL_GO_ATL); + writel(reg, base + ccu_clk->policy_ctl_offset); + + /* wait till started */ + ret = wait_bit(base, ccu_clk->policy_ctl_offset, 0, 0); + if (ret) + return ret; + + /* disable access */ + writel(0, base + WR_ACCESS_OFFSET); + + return ret; +} + +/* Get the CCU clock rate */ +static unsigned long ccu_clk_get_rate(struct clk *c) +{ + struct ccu_clock *ccu_clk = to_ccu_clk(c); + debug("%s: %s\n", __func__, c->name); + c->rate = ccu_clk->freq_tbl[ccu_clk->freq_id]; + return c->rate; +} + +/* CCU clock operations */ +struct clk_ops ccu_clk_ops = { + .enable = ccu_clk_enable, + .get_rate = ccu_clk_get_rate, +}; + +/* Enable a bus clock */ +static int bus_clk_enable(struct clk *c, int enable) +{ + struct bus_clock *bus_clk = to_bus_clk(c); + struct bus_clk_data *cd = bus_clk->data; + void *base = (void *)c->ccu_clk_mgr_base; + int ret = 0; + u32 reg; + + debug("%s: %s\n", __func__, c->name); + /* enable access */ + writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET); + + /* enable gating */ + reg = readl(base + cd->gate.offset); + if (!!(reg & (1 << cd->gate.status_bit)) == !!enable) + debug("%s already %s\n", c->name, + enable ? "enabled" : "disabled"); + else { + int want = (enable) ? 1 : 0; + reg |= (1 << cd->gate.hw_sw_sel_bit); + + if (enable) + reg |= (1 << cd->gate.en_bit); + else + reg &= ~(1 << cd->gate.en_bit); + + writel(reg, base + cd->gate.offset); + ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, + want); + if (ret) + return ret; + } + + /* disable access */ + writel(0, base + WR_ACCESS_OFFSET); + + return ret; +} + +/* Get the rate of a bus clock */ +static unsigned long bus_clk_get_rate(struct clk *c) +{ + struct bus_clock *bus_clk = to_bus_clk(c); + struct ccu_clock *ccu_clk; + + debug("%s: %s\n", __func__, c->name); + ccu_clk = to_ccu_clk(c->parent); + + c->rate = bus_clk->freq_tbl[ccu_clk->freq_id]; + c->div = ccu_clk->freq_tbl[ccu_clk->freq_id] / c->rate; + return c->rate; +} + +/* Bus clock operations */ +struct clk_ops bus_clk_ops = { + .enable = bus_clk_enable, + .get_rate = bus_clk_get_rate, +}; + +/* Enable a reference clock */ +static int ref_clk_enable(struct clk *c, int enable) +{ + debug("%s: %s\n", __func__, c->name); + return 0; +} + +/* Reference clock operations */ +struct clk_ops ref_clk_ops = { + .enable = ref_clk_enable, +}; + +/* + * clk.h implementation follows + */ + +/* Initialize the clock framework */ +int clk_init(void) +{ + debug("%s:\n", __func__); + return 0; +} + +/* Get a clock handle, give a name string */ +struct clk *clk_get(const char *con_id) +{ + int i; + struct clk_lookup *clk_tblp; + + debug("%s: %s\n", __func__, con_id); + + clk_tblp = arch_clk_tbl; + for (i = 0; i < arch_clk_tbl_array_size; i++, clk_tblp++) { + if (clk_tblp->con_id) { + if (!con_id || strcmp(clk_tblp->con_id, con_id)) + continue; + return clk_tblp->clk; + } + } + return NULL; +} + +/* Enable a clock */ +int clk_enable(struct clk *c) +{ + int ret = 0; + + debug("%s: %s\n", __func__, c->name); + if (!c->ops || !c->ops->enable) + return -1; + + /* enable parent clock first */ + if (c->parent) + ret = clk_enable(c->parent); + + if (ret) + return ret; + + if (!c->use_cnt) + ret = c->ops->enable(c, 1); + c->use_cnt++; + + return ret; +} + +/* Disable a clock */ +void clk_disable(struct clk *c) +{ + debug("%s: %s\n", __func__, c->name); + if (!c->ops || !c->ops->enable) + return; + + if (c->use_cnt > 0) { + c->use_cnt--; + if (c->use_cnt == 0) + c->ops->enable(c, 0); + } + + /* disable parent */ + if (c->parent) + clk_disable(c->parent); +} + +/* Get the clock rate */ +unsigned long clk_get_rate(struct clk *c) +{ + unsigned long rate; + + if (!c || !c->ops || !c->ops->get_rate) + return 0; + debug("%s: %s\n", __func__, c->name); + + rate = c->ops->get_rate(c); + debug("%s: rate = %ld\n", __func__, rate); + return rate; +} + +/* Set the clock rate */ +int clk_set_rate(struct clk *c, unsigned long rate) +{ + int ret; + + if (!c || !c->ops || !c->ops->set_rate) + return -EINVAL; + debug("%s: %s rate=%ld\n", __func__, c->name, rate); + + if (c->use_cnt) + return -EINVAL; + + ret = c->ops->set_rate(c, rate); + + return ret; +} + +/* Not required for this arch */ +/* +long clk_round_rate(struct clk *clk, unsigned long rate); +int clk_set_parent(struct clk *clk, struct clk *parent); +struct clk *clk_get_parent(struct clk *clk); +*/
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-core.h b/arch/arm/cpu/armv7/bcm235xx/clk-core.h new file mode 100644 index 0000000..ac475b6 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm235xx/clk-core.h
@@ -0,0 +1,490 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2013 Broadcom Corporation. + */ + +#include <linux/stddef.h> + +#ifdef CONFIG_CLK_DEBUG +#undef writel +#undef readl +static inline void writel(u32 val, void *addr) +{ + printf("Write [0x%p] = 0x%08x\n", addr, val); + *(u32 *)addr = val; +} + +static inline u32 readl(void *addr) +{ + u32 val = *(u32 *)addr; + printf("Read [0x%p] = 0x%08x\n", addr, val); + return val; +} +#endif + +struct clk; + +struct clk_lookup { + const char *dev_id; + const char *con_id; + struct clk *clk; +}; + +extern struct clk_lookup arch_clk_tbl[]; +extern unsigned int arch_clk_tbl_array_size; + +/** + * struct clk_ops - standard clock operations + * @enable: enable/disable clock, see clk_enable() and clk_disable() + * @set_rate: set the clock rate, see clk_set_rate(). + * @get_rate: get the clock rate, see clk_get_rate(). + * @round_rate: round a given clock rate, see clk_round_rate(). + * @set_parent: set the clock's parent, see clk_set_parent(). + * + * Group the common clock implementations together so that we + * don't have to keep setting the same fiels again. We leave + * enable in struct clk. + * + */ +struct clk_ops { + int (*enable)(struct clk *c, int enable); + int (*set_rate)(struct clk *c, unsigned long rate); + unsigned long (*get_rate)(struct clk *c); + unsigned long (*round_rate)(struct clk *c, unsigned long rate); + int (*set_parent)(struct clk *c, struct clk *parent); +}; + +struct clk { + struct clk *parent; + const char *name; + int use_cnt; + unsigned long rate; /* in HZ */ + + /* programmable divider. 0 means fixed ratio to parent clock */ + unsigned long div; + + struct clk_src *src; + struct clk_ops *ops; + + unsigned long ccu_clk_mgr_base; + int sel; +}; + +struct refclk *refclk_str_to_clk(const char *name); + +/* The common clock framework uses u8 to represent a parent index */ +#define PARENT_COUNT_MAX ((u32)U8_MAX) + +#define BAD_CLK_INDEX U8_MAX /* Can't ever be valid */ +#define BAD_CLK_NAME ((const char *)-1) + +#define BAD_SCALED_DIV_VALUE U64_MAX + +/* + * Utility macros for object flag management. If possible, flags + * should be defined such that 0 is the desired default value. + */ +#define FLAG(type, flag) BCM_CLK_ ## type ## _FLAGS_ ## flag +#define FLAG_SET(obj, type, flag) ((obj)->flags |= FLAG(type, flag)) +#define FLAG_CLEAR(obj, type, flag) ((obj)->flags &= ~(FLAG(type, flag))) +#define FLAG_FLIP(obj, type, flag) ((obj)->flags ^= FLAG(type, flag)) +#define FLAG_TEST(obj, type, flag) (!!((obj)->flags & FLAG(type, flag))) + +/* Clock field state tests */ + +#define gate_exists(gate) FLAG_TEST(gate, GATE, EXISTS) +#define gate_is_enabled(gate) FLAG_TEST(gate, GATE, ENABLED) +#define gate_is_hw_controllable(gate) FLAG_TEST(gate, GATE, HW) +#define gate_is_sw_controllable(gate) FLAG_TEST(gate, GATE, SW) +#define gate_is_sw_managed(gate) FLAG_TEST(gate, GATE, SW_MANAGED) +#define gate_is_no_disable(gate) FLAG_TEST(gate, GATE, NO_DISABLE) + +#define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED) + +#define divider_exists(div) FLAG_TEST(div, DIV, EXISTS) +#define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED) +#define divider_has_fraction(div) (!divider_is_fixed(div) && \ + (div)->frac_width > 0) + +#define selector_exists(sel) ((sel)->width != 0) +#define trigger_exists(trig) FLAG_TEST(trig, TRIG, EXISTS) + +/* Clock type, used to tell common block what it's part of */ +enum bcm_clk_type { + bcm_clk_none, /* undefined clock type */ + bcm_clk_bus, + bcm_clk_core, + bcm_clk_peri +}; + +/* + * Gating control and status is managed by a 32-bit gate register. + * + * There are several types of gating available: + * - (no gate) + * A clock with no gate is assumed to be always enabled. + * - hardware-only gating (auto-gating) + * Enabling or disabling clocks with this type of gate is + * managed automatically by the hardware. Such clocks can be + * considered by the software to be enabled. The current status + * of auto-gated clocks can be read from the gate status bit. + * - software-only gating + * Auto-gating is not available for this type of clock. + * Instead, software manages whether it's enabled by setting or + * clearing the enable bit. The current gate status of a gate + * under software control can be read from the gate status bit. + * To ensure a change to the gating status is complete, the + * status bit can be polled to verify that the gate has entered + * the desired state. + * - selectable hardware or software gating + * Gating for this type of clock can be configured to be either + * under software or hardware control. Which type is in use is + * determined by the hw_sw_sel bit of the gate register. + */ +struct bcm_clk_gate { + u32 offset; /* gate register offset */ + u32 status_bit; /* 0: gate is disabled; 0: gatge is enabled */ + u32 en_bit; /* 0: disable; 1: enable */ + u32 hw_sw_sel_bit; /* 0: hardware gating; 1: software gating */ + u32 flags; /* BCM_CLK_GATE_FLAGS_* below */ +}; + +/* + * Gate flags: + * HW means this gate can be auto-gated + * SW means the state of this gate can be software controlled + * NO_DISABLE means this gate is (only) enabled if under software control + * SW_MANAGED means the status of this gate is under software control + * ENABLED means this software-managed gate is *supposed* to be enabled + */ +#define BCM_CLK_GATE_FLAGS_EXISTS ((u32)1 << 0) /* Gate is valid */ +#define BCM_CLK_GATE_FLAGS_HW ((u32)1 << 1) /* Can auto-gate */ +#define BCM_CLK_GATE_FLAGS_SW ((u32)1 << 2) /* Software control */ +#define BCM_CLK_GATE_FLAGS_NO_DISABLE ((u32)1 << 3) /* HW or enabled */ +#define BCM_CLK_GATE_FLAGS_SW_MANAGED ((u32)1 << 4) /* SW now in control */ +#define BCM_CLK_GATE_FLAGS_ENABLED ((u32)1 << 5) /* If SW_MANAGED */ + +/* + * Gate initialization macros. + * + * Any gate initially under software control will be enabled. + */ + +/* A hardware/software gate initially under software control */ +#define HW_SW_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .hw_sw_sel_bit = (_hw_sw_sel_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ + FLAG(GATE, SW_MANAGED)|FLAG(GATE, ENABLED)| \ + FLAG(GATE, EXISTS), \ + } + +/* A hardware/software gate initially under hardware control */ +#define HW_SW_GATE_AUTO(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .hw_sw_sel_bit = (_hw_sw_sel_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ + FLAG(GATE, EXISTS), \ + } + +/* A hardware-or-enabled gate (enabled if not under hardware control) */ +#define HW_ENABLE_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .hw_sw_sel_bit = (_hw_sw_sel_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ + FLAG(GATE, NO_DISABLE)|FLAG(GATE, EXISTS), \ + } + +/* A software-only gate */ +#define SW_ONLY_GATE(_offset, _status_bit, _en_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .flags = FLAG(GATE, SW)|FLAG(GATE, SW_MANAGED)| \ + FLAG(GATE, ENABLED)|FLAG(GATE, EXISTS), \ + } + +/* A hardware-only gate */ +#define HW_ONLY_GATE(_offset, _status_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \ + } + +/* + * Each clock can have zero, one, or two dividers which change the + * output rate of the clock. Each divider can be either fixed or + * variable. If there are two dividers, they are the "pre-divider" + * and the "regular" or "downstream" divider. If there is only one, + * there is no pre-divider. + * + * A fixed divider is any non-zero (positive) value, and it + * indicates how the input rate is affected by the divider. + * + * The value of a variable divider is maintained in a sub-field of a + * 32-bit divider register. The position of the field in the + * register is defined by its offset and width. The value recorded + * in this field is always 1 less than the value it represents. + * + * In addition, a variable divider can indicate that some subset + * of its bits represent a "fractional" part of the divider. Such + * bits comprise the low-order portion of the divider field, and can + * be viewed as representing the portion of the divider that lies to + * the right of the decimal point. Most variable dividers have zero + * fractional bits. Variable dividers with non-zero fraction width + * still record a value 1 less than the value they represent; the + * added 1 does *not* affect the low-order bit in this case, it + * affects the bits above the fractional part only. (Often in this + * code a divider field value is distinguished from the value it + * represents by referring to the latter as a "divisor".) + * + * In order to avoid dealing with fractions, divider arithmetic is + * performed using "scaled" values. A scaled value is one that's + * been left-shifted by the fractional width of a divider. Dividing + * a scaled value by a scaled divisor produces the desired quotient + * without loss of precision and without any other special handling + * for fractions. + * + * The recorded value of a variable divider can be modified. To + * modify either divider (or both), a clock must be enabled (i.e., + * using its gate). In addition, a trigger register (described + * below) must be used to commit the change, and polled to verify + * the change is complete. + */ +struct bcm_clk_div { + union { + struct { /* variable divider */ + u32 offset; /* divider register offset */ + u32 shift; /* field shift */ + u32 width; /* field width */ + u32 frac_width; /* field fraction width */ + + u64 scaled_div; /* scaled divider value */ + }; + u32 fixed; /* non-zero fixed divider value */ + }; + u32 flags; /* BCM_CLK_DIV_FLAGS_* below */ +}; + +/* + * Divider flags: + * EXISTS means this divider exists + * FIXED means it is a fixed-rate divider + */ +#define BCM_CLK_DIV_FLAGS_EXISTS ((u32)1 << 0) /* Divider is valid */ +#define BCM_CLK_DIV_FLAGS_FIXED ((u32)1 << 1) /* Fixed-value */ + +/* Divider initialization macros */ + +/* A fixed (non-zero) divider */ +#define FIXED_DIVIDER(_value) \ + { \ + .fixed = (_value), \ + .flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED), \ + } + +/* A divider with an integral divisor */ +#define DIVIDER(_offset, _shift, _width) \ + { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .scaled_div = BAD_SCALED_DIV_VALUE, \ + .flags = FLAG(DIV, EXISTS), \ + } + +/* A divider whose divisor has an integer and fractional part */ +#define FRAC_DIVIDER(_offset, _shift, _width, _frac_width) \ + { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .frac_width = (_frac_width), \ + .scaled_div = BAD_SCALED_DIV_VALUE, \ + .flags = FLAG(DIV, EXISTS), \ + } + +/* + * Clocks may have multiple "parent" clocks. If there is more than + * one, a selector must be specified to define which of the parent + * clocks is currently in use. The selected clock is indicated in a + * sub-field of a 32-bit selector register. The range of + * representable selector values typically exceeds the number of + * available parent clocks. Occasionally the reset value of a + * selector field is explicitly set to a (specific) value that does + * not correspond to a defined input clock. + * + * We register all known parent clocks with the common clock code + * using a packed array (i.e., no empty slots) of (parent) clock + * names, and refer to them later using indexes into that array. + * We maintain an array of selector values indexed by common clock + * index values in order to map between these common clock indexes + * and the selector values used by the hardware. + * + * Like dividers, a selector can be modified, but to do so a clock + * must be enabled, and a trigger must be used to commit the change. + */ +struct bcm_clk_sel { + u32 offset; /* selector register offset */ + u32 shift; /* field shift */ + u32 width; /* field width */ + + u32 parent_count; /* number of entries in parent_sel[] */ + u32 *parent_sel; /* array of parent selector values */ + u8 clk_index; /* current selected index in parent_sel[] */ +}; + +/* Selector initialization macro */ +#define SELECTOR(_offset, _shift, _width) \ + { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .clk_index = BAD_CLK_INDEX, \ + } + +/* + * Making changes to a variable divider or a selector for a clock + * requires the use of a trigger. A trigger is defined by a single + * bit within a register. To signal a change, a 1 is written into + * that bit. To determine when the change has been completed, that + * trigger bit is polled; the read value will be 1 while the change + * is in progress, and 0 when it is complete. + * + * Occasionally a clock will have more than one trigger. In this + * case, the "pre-trigger" will be used when changing a clock's + * selector and/or its pre-divider. + */ +struct bcm_clk_trig { + u32 offset; /* trigger register offset */ + u32 bit; /* trigger bit */ + u32 flags; /* BCM_CLK_TRIG_FLAGS_* below */ +}; + +/* + * Trigger flags: + * EXISTS means this trigger exists + */ +#define BCM_CLK_TRIG_FLAGS_EXISTS ((u32)1 << 0) /* Trigger is valid */ + +/* Trigger initialization macro */ +#define TRIGGER(_offset, _bit) \ + { \ + .offset = (_offset), \ + .bit = (_bit), \ + .flags = FLAG(TRIG, EXISTS), \ + } + +struct bus_clk_data { + struct bcm_clk_gate gate; +}; + +struct core_clk_data { + struct bcm_clk_gate gate; +}; + +struct peri_clk_data { + struct bcm_clk_gate gate; + struct bcm_clk_trig pre_trig; + struct bcm_clk_div pre_div; + struct bcm_clk_trig trig; + struct bcm_clk_div div; + struct bcm_clk_sel sel; + const char *clocks[]; /* must be last; use CLOCKS() to declare */ +}; +#define CLOCKS(...) { __VA_ARGS__, NULL, } +#define NO_CLOCKS { NULL, } /* Must use of no parent clocks */ + +struct refclk { + struct clk clk; +}; + +struct peri_clock { + struct clk clk; + struct peri_clk_data *data; +}; + +struct ccu_clock { + struct clk clk; + + int num_policy_masks; + unsigned long policy_freq_offset; + int freq_bit_shift; /* 8 for most CCUs */ + unsigned long policy_ctl_offset; + unsigned long policy0_mask_offset; + unsigned long policy1_mask_offset; + unsigned long policy2_mask_offset; + unsigned long policy3_mask_offset; + unsigned long policy0_mask2_offset; + unsigned long policy1_mask2_offset; + unsigned long policy2_mask2_offset; + unsigned long policy3_mask2_offset; + unsigned long lvm_en_offset; + + int freq_id; + unsigned long *freq_tbl; +}; + +struct bus_clock { + struct clk clk; + struct bus_clk_data *data; + unsigned long *freq_tbl; +}; + +struct ref_clock { + struct clk clk; +}; + +static inline int is_same_clock(struct clk *a, struct clk *b) +{ + return a == b; +} + +#define to_clk(p) (&((p)->clk)) +#define name_to_clk(name) (&((name##_clk).clk)) +/* declare a struct clk_lookup */ +#define CLK_LK(name) \ +{.con_id = __stringify(name##_clk), .clk = name_to_clk(name),} + +static inline struct refclk *to_refclk(struct clk *clock) +{ + return container_of(clock, struct refclk, clk); +} + +static inline struct peri_clock *to_peri_clk(struct clk *clock) +{ + return container_of(clock, struct peri_clock, clk); +} + +static inline struct ccu_clock *to_ccu_clk(struct clk *clock) +{ + return container_of(clock, struct ccu_clock, clk); +} + +static inline struct bus_clock *to_bus_clk(struct clk *clock) +{ + return container_of(clock, struct bus_clock, clk); +} + +static inline struct ref_clock *to_ref_clk(struct clk *clock) +{ + return container_of(clock, struct ref_clock, clk); +} + +extern struct clk_ops peri_clk_ops; +extern struct clk_ops ccu_clk_ops; +extern struct clk_ops bus_clk_ops; +extern struct clk_ops ref_clk_ops; + +int clk_get_and_enable(char *clkstr);
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-eth.c b/arch/arm/cpu/armv7/bcm235xx/clk-eth.c new file mode 100644 index 0000000..618af70 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm235xx/clk-eth.c
@@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Broadcom Corporation. + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +#define WR_ACCESS_ADDR ESUB_CLK_BASE_ADDR +#define WR_ACCESS_PASSWORD 0xA5A500 + +#define PLLE_POST_RESETB_ADDR (ESUB_CLK_BASE_ADDR + 0x00000C00) + +#define PLLE_RESETB_ADDR (ESUB_CLK_BASE_ADDR + 0x00000C58) +#define PLLE_RESETB_I_PLL_RESETB_PLLE_MASK 0x00010000 +#define PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK 0x00000001 + +#define PLL_LOCK_ADDR (ESUB_CLK_BASE_ADDR + 0x00000C38) +#define PLL_LOCK_PLL_LOCK_PLLE_MASK 0x00000001 + +#define ESW_SYS_DIV_ADDR (ESUB_CLK_BASE_ADDR + 0x00000A04) +#define ESW_SYS_DIV_PLL_SELECT_MASK 0x00000300 +#define ESW_SYS_DIV_DIV_MASK 0x0000001C +#define ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT 0x00000100 +#define ESW_SYS_DIV_DIV_SELECT 0x4 +#define ESW_SYS_DIV_TRIGGER_MASK 0x00000001 + +#define ESUB_AXI_DIV_DEBUG_ADDR (ESUB_CLK_BASE_ADDR + 0x00000E04) +#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK 0x0000001C +#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK 0x00000040 +#define ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT 0x0 +#define ESUB_AXI_DIV_DEBUG_TRIGGER_MASK 0x00000001 + +#define PLL_MAX_RETRY 100 + +/* Enable appropriate clocks for Ethernet */ +int clk_eth_enable(void) +{ + int rc = -1; + int retry_count = 0; + rc = clk_get_and_enable("esub_ccu_clk"); + + /* Enable Access to CCU registers */ + writel((1 | WR_ACCESS_PASSWORD), WR_ACCESS_ADDR); + + writel(readl(PLLE_POST_RESETB_ADDR) & + ~PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK, + PLLE_POST_RESETB_ADDR); + + /* Take PLL out of reset and put into normal mode */ + writel(readl(PLLE_RESETB_ADDR) | PLLE_RESETB_I_PLL_RESETB_PLLE_MASK, + PLLE_RESETB_ADDR); + + /* Wait for PLL lock */ + rc = -1; + while (retry_count < PLL_MAX_RETRY) { + udelay(100); + if (readl(PLL_LOCK_ADDR) & PLL_LOCK_PLL_LOCK_PLLE_MASK) { + rc = 0; + break; + } + retry_count++; + } + + if (rc == -1) { + printf("%s: ETH-PLL lock timeout, Ethernet is not enabled!\n", + __func__); + return -1; + } + + writel(readl(PLLE_POST_RESETB_ADDR) | + PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK, + PLLE_POST_RESETB_ADDR); + + /* Switch esw_sys_clk to use 104MHz(208MHz/2) clock */ + writel((readl(ESW_SYS_DIV_ADDR) & + ~(ESW_SYS_DIV_PLL_SELECT_MASK | ESW_SYS_DIV_DIV_MASK)) | + ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT | ESW_SYS_DIV_DIV_SELECT, + ESW_SYS_DIV_ADDR); + + writel(readl(ESW_SYS_DIV_ADDR) | ESW_SYS_DIV_TRIGGER_MASK, + ESW_SYS_DIV_ADDR); + + /* Wait for trigger complete */ + rc = -1; + retry_count = 0; + while (retry_count < PLL_MAX_RETRY) { + udelay(100); + if (!(readl(ESW_SYS_DIV_ADDR) & ESW_SYS_DIV_TRIGGER_MASK)) { + rc = 0; + break; + } + retry_count++; + } + + if (rc == -1) { + printf("%s: SYS CLK Trigger timeout, Ethernet is not enabled!\n", + __func__); + return -1; + } + + /* switch Esub AXI clock to 208MHz */ + writel((readl(ESUB_AXI_DIV_DEBUG_ADDR) & + ~(ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK | + ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK | + ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) | + ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT | + ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK, + ESUB_AXI_DIV_DEBUG_ADDR); + + writel(readl(ESUB_AXI_DIV_DEBUG_ADDR) | + ESUB_AXI_DIV_DEBUG_TRIGGER_MASK, + ESUB_AXI_DIV_DEBUG_ADDR); + + /* Wait for trigger complete */ + rc = -1; + retry_count = 0; + while (retry_count < PLL_MAX_RETRY) { + udelay(100); + if (!(readl(ESUB_AXI_DIV_DEBUG_ADDR) & + ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) { + rc = 0; + break; + } + retry_count++; + } + + if (rc == -1) { + printf("%s: AXI CLK Trigger timeout, Ethernet is not enabled!\n", + __func__); + return -1; + } + + /* Disable Access to CCU registers */ + writel(WR_ACCESS_PASSWORD, WR_ACCESS_ADDR); + + return rc; +}
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-sdio.c b/arch/arm/cpu/armv7/bcm235xx/clk-sdio.c new file mode 100644 index 0000000..f2ba354 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm235xx/clk-sdio.c
@@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Broadcom Corporation. + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +/* Enable appropriate clocks for an SDIO port */ +int clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep) +{ + int ret; + struct clk *c; + + char *clkstr; + char *slpstr; + char *ahbstr; + + switch ((u32) base) { + case CONFIG_SYS_SDIO_BASE0: + clkstr = CONFIG_SYS_SDIO0 "_clk"; + ahbstr = CONFIG_SYS_SDIO0 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO0 "_sleep_clk"; + break; + case CONFIG_SYS_SDIO_BASE1: + clkstr = CONFIG_SYS_SDIO1 "_clk"; + ahbstr = CONFIG_SYS_SDIO1 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO1 "_sleep_clk"; + break; + case CONFIG_SYS_SDIO_BASE2: + clkstr = CONFIG_SYS_SDIO2 "_clk"; + ahbstr = CONFIG_SYS_SDIO2 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO2 "_sleep_clk"; + break; + case CONFIG_SYS_SDIO_BASE3: + clkstr = CONFIG_SYS_SDIO3 "_clk"; + ahbstr = CONFIG_SYS_SDIO3 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO3 "_sleep_clk"; + break; + default: + printf("%s: base 0x%p not found\n", __func__, base); + return -EINVAL; + } + + ret = clk_get_and_enable(ahbstr); + if (ret) + return ret; + + ret = clk_get_and_enable(slpstr); + if (ret) + return ret; + + c = clk_get(clkstr); + if (c) { + ret = clk_set_rate(c, rate); + if (ret) + return ret; + + ret = clk_enable(c); + if (ret) + return ret; + } else { + printf("%s: Couldn't find %s\n", __func__, clkstr); + return -EINVAL; + } + *actual_ratep = rate; + return 0; +}
diff --git a/arch/arm/cpu/armv7/bcm235xx/clk-usb-otg.c b/arch/arm/cpu/armv7/bcm235xx/clk-usb-otg.c new file mode 100644 index 0000000..f604aec --- /dev/null +++ b/arch/arm/cpu/armv7/bcm235xx/clk-usb-otg.c
@@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Broadcom Corporation. + */ + +#include <common.h> +#include <linux/errno.h> +#include <asm/arch/sysmap.h> +#include "clk-core.h" + +/* Enable appropriate clocks for the USB OTG port */ +int clk_usb_otg_enable(void *base) +{ + char *ahbstr; + + switch ((u32) base) { + case HSOTG_BASE_ADDR: + ahbstr = "usb_otg_ahb_clk"; + break; + default: + printf("%s: base 0x%p not found\n", __func__, base); + return -EINVAL; + } + + return clk_get_and_enable(ahbstr); +}
diff --git a/arch/arm/cpu/armv7/bcm281xx/Makefile b/arch/arm/cpu/armv7/bcm281xx/Makefile new file mode 100644 index 0000000..e509997 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm281xx/Makefile
@@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2013 Broadcom Corporation. + +obj-y += reset.o +obj-y += clk-core.o +obj-y += clk-bcm281xx.o +obj-y += clk-sdio.o +obj-y += clk-bsc.o +obj-$(CONFIG_BCM_SF2_ETH) += clk-eth.o +obj-y += clk-usb-otg.o
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c b/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c new file mode 100644 index 0000000..8f6260e --- /dev/null +++ b/arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c
@@ -0,0 +1,572 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Broadcom Corporation. + */ + +/* + * + * bcm281xx-specific clock tables + * + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +#define CLOCK_1K 1000 +#define CLOCK_1M (CLOCK_1K * 1000) + +/* declare a reference clock */ +#define DECLARE_REF_CLK(clk_name, clk_parent, clk_rate, clk_div) \ +static struct refclk clk_name = { \ + .clk = { \ + .name = #clk_name, \ + .parent = clk_parent, \ + .rate = clk_rate, \ + .div = clk_div, \ + .ops = &ref_clk_ops, \ + }, \ +} + +/* + * Reference clocks + */ + +/* Declare a list of reference clocks */ +DECLARE_REF_CLK(ref_crystal, 0, 26 * CLOCK_1M, 1); +DECLARE_REF_CLK(var_96m, 0, 96 * CLOCK_1M, 1); +DECLARE_REF_CLK(ref_96m, 0, 96 * CLOCK_1M, 1); +DECLARE_REF_CLK(ref_312m, 0, 312 * CLOCK_1M, 0); +DECLARE_REF_CLK(ref_104m, &ref_312m.clk, 104 * CLOCK_1M, 3); +DECLARE_REF_CLK(ref_52m, &ref_104m.clk, 52 * CLOCK_1M, 2); +DECLARE_REF_CLK(ref_13m, &ref_52m.clk, 13 * CLOCK_1M, 4); +DECLARE_REF_CLK(var_312m, 0, 312 * CLOCK_1M, 0); +DECLARE_REF_CLK(var_104m, &var_312m.clk, 104 * CLOCK_1M, 3); +DECLARE_REF_CLK(var_52m, &var_104m.clk, 52 * CLOCK_1M, 2); +DECLARE_REF_CLK(var_13m, &var_52m.clk, 13 * CLOCK_1M, 4); + +struct refclk_lkup { + struct refclk *procclk; + const char *name; +}; + +/* Lookup table for string to clk tranlation */ +#define MKSTR(x) {&x, #x} +static struct refclk_lkup refclk_str_tbl[] = { + MKSTR(ref_crystal), MKSTR(var_96m), MKSTR(ref_96m), + MKSTR(ref_312m), MKSTR(ref_104m), MKSTR(ref_52m), + MKSTR(ref_13m), MKSTR(var_312m), MKSTR(var_104m), + MKSTR(var_52m), MKSTR(var_13m), +}; + +int refclk_entries = sizeof(refclk_str_tbl)/sizeof(refclk_str_tbl[0]); + +/* convert ref clock string to clock structure pointer */ +struct refclk *refclk_str_to_clk(const char *name) +{ + int i; + struct refclk_lkup *tblp = refclk_str_tbl; + for (i = 0; i < refclk_entries; i++, tblp++) { + if (!(strcmp(name, tblp->name))) + return tblp->procclk; + } + return NULL; +} + +/* frequency tables indexed by freq_id */ +unsigned long master_axi_freq_tbl[8] = { + 26 * CLOCK_1M, + 52 * CLOCK_1M, + 104 * CLOCK_1M, + 156 * CLOCK_1M, + 156 * CLOCK_1M, + 208 * CLOCK_1M, + 312 * CLOCK_1M, + 312 * CLOCK_1M +}; + +unsigned long master_ahb_freq_tbl[8] = { + 26 * CLOCK_1M, + 52 * CLOCK_1M, + 52 * CLOCK_1M, + 52 * CLOCK_1M, + 78 * CLOCK_1M, + 104 * CLOCK_1M, + 104 * CLOCK_1M, + 156 * CLOCK_1M +}; + +unsigned long slave_axi_freq_tbl[8] = { + 26 * CLOCK_1M, + 52 * CLOCK_1M, + 78 * CLOCK_1M, + 104 * CLOCK_1M, + 156 * CLOCK_1M, + 156 * CLOCK_1M +}; + +unsigned long slave_apb_freq_tbl[8] = { + 26 * CLOCK_1M, + 26 * CLOCK_1M, + 39 * CLOCK_1M, + 52 * CLOCK_1M, + 52 * CLOCK_1M, + 78 * CLOCK_1M +}; + +unsigned long esub_freq_tbl[8] = { + 78 * CLOCK_1M, + 156 * CLOCK_1M, + 156 * CLOCK_1M, + 156 * CLOCK_1M, + 208 * CLOCK_1M, + 208 * CLOCK_1M, + 208 * CLOCK_1M +}; + +static struct bus_clk_data bsc1_apb_data = { + .gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1), +}; + +static struct bus_clk_data bsc2_apb_data = { + .gate = HW_SW_GATE_AUTO(0x045c, 16, 0, 1), +}; + +static struct bus_clk_data bsc3_apb_data = { + .gate = HW_SW_GATE_AUTO(0x0484, 16, 0, 1), +}; + +/* * Master CCU clocks */ +static struct peri_clk_data sdio1_data = { + .gate = HW_SW_GATE(0x0358, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a28, 0, 3), + .div = DIVIDER(0x0a28, 4, 14), + .trig = TRIGGER(0x0afc, 9), +}; + +static struct peri_clk_data sdio2_data = { + .gate = HW_SW_GATE(0x035c, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a2c, 0, 3), + .div = DIVIDER(0x0a2c, 4, 14), + .trig = TRIGGER(0x0afc, 10), +}; + +static struct peri_clk_data sdio3_data = { + .gate = HW_SW_GATE(0x0364, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a34, 0, 3), + .div = DIVIDER(0x0a34, 4, 14), + .trig = TRIGGER(0x0afc, 12), +}; + +static struct peri_clk_data sdio4_data = { + .gate = HW_SW_GATE(0x0360, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_52m", + "ref_52m", + "var_96m", + "ref_96m"), + .sel = SELECTOR(0x0a30, 0, 3), + .div = DIVIDER(0x0a30, 4, 14), + .trig = TRIGGER(0x0afc, 11), +}; + +static struct peri_clk_data sdio1_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x0358, 20, 4), +}; + +static struct peri_clk_data sdio2_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x035c, 20, 4), +}; + +static struct peri_clk_data sdio3_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x0364, 20, 4), +}; + +static struct peri_clk_data sdio4_sleep_data = { + .clocks = CLOCKS("ref_32k"), + .gate = SW_ONLY_GATE(0x0360, 20, 4), +}; + +static struct bus_clk_data usb_otg_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0348, 16, 0, 1), +}; + +static struct bus_clk_data sdio1_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0358, 16, 0, 1), +}; + +static struct bus_clk_data sdio2_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x035c, 16, 0, 1), +}; + +static struct bus_clk_data sdio3_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0364, 16, 0, 1), +}; + +static struct bus_clk_data sdio4_ahb_data = { + .gate = HW_SW_GATE_AUTO(0x0360, 16, 0, 1), +}; + +/* * Slave CCU clocks */ +static struct peri_clk_data bsc1_data = { + .gate = HW_SW_GATE(0x0458, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_104m", + "ref_104m", + "var_13m", + "ref_13m"), + .sel = SELECTOR(0x0a64, 0, 3), + .trig = TRIGGER(0x0afc, 23), +}; + +static struct peri_clk_data bsc2_data = { + .gate = HW_SW_GATE(0x045c, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_104m", + "ref_104m", + "var_13m", + "ref_13m"), + .sel = SELECTOR(0x0a68, 0, 3), + .trig = TRIGGER(0x0afc, 24), +}; + +static struct peri_clk_data bsc3_data = { + .gate = HW_SW_GATE(0x0484, 18, 2, 3), + .clocks = CLOCKS("ref_crystal", + "var_104m", + "ref_104m", + "var_13m", + "ref_13m"), + .sel = SELECTOR(0x0a84, 0, 3), + .trig = TRIGGER(0x0b00, 2), +}; + +/* + * CCU clocks + */ + +static struct ccu_clock kpm_ccu_clk = { + .clk = { + .name = "kpm_ccu_clk", + .ops = &ccu_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .num_policy_masks = 1, + .policy_freq_offset = 0x00000008, + .freq_bit_shift = 8, + .policy_ctl_offset = 0x0000000c, + .policy0_mask_offset = 0x00000010, + .policy1_mask_offset = 0x00000014, + .policy2_mask_offset = 0x00000018, + .policy3_mask_offset = 0x0000001c, + .lvm_en_offset = 0x00000034, + .freq_id = 2, + .freq_tbl = master_axi_freq_tbl, +}; + +static struct ccu_clock kps_ccu_clk = { + .clk = { + .name = "kps_ccu_clk", + .ops = &ccu_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .num_policy_masks = 2, + .policy_freq_offset = 0x00000008, + .freq_bit_shift = 8, + .policy_ctl_offset = 0x0000000c, + .policy0_mask_offset = 0x00000010, + .policy1_mask_offset = 0x00000014, + .policy2_mask_offset = 0x00000018, + .policy3_mask_offset = 0x0000001c, + .policy0_mask2_offset = 0x00000048, + .policy1_mask2_offset = 0x0000004c, + .policy2_mask2_offset = 0x00000050, + .policy3_mask2_offset = 0x00000054, + .lvm_en_offset = 0x00000034, + .freq_id = 2, + .freq_tbl = slave_axi_freq_tbl, +}; + +#ifdef CONFIG_BCM_SF2_ETH +static struct ccu_clock esub_ccu_clk = { + .clk = { + .name = "esub_ccu_clk", + .ops = &ccu_clk_ops, + .ccu_clk_mgr_base = ESUB_CLK_BASE_ADDR, + }, + .num_policy_masks = 1, + .policy_freq_offset = 0x00000008, + .freq_bit_shift = 8, + .policy_ctl_offset = 0x0000000c, + .policy0_mask_offset = 0x00000010, + .policy1_mask_offset = 0x00000014, + .policy2_mask_offset = 0x00000018, + .policy3_mask_offset = 0x0000001c, + .lvm_en_offset = 0x00000034, + .freq_id = 2, + .freq_tbl = esub_freq_tbl, +}; +#endif + +/* + * Bus clocks + */ + +/* KPM bus clocks */ +static struct bus_clock usb_otg_ahb_clk = { + .clk = { + .name = "usb_otg_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &usb_otg_ahb_data, +}; + +static struct bus_clock sdio1_ahb_clk = { + .clk = { + .name = "sdio1_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio1_ahb_data, +}; + +static struct bus_clock sdio2_ahb_clk = { + .clk = { + .name = "sdio2_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio2_ahb_data, +}; + +static struct bus_clock sdio3_ahb_clk = { + .clk = { + .name = "sdio3_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio3_ahb_data, +}; + +static struct bus_clock sdio4_ahb_clk = { + .clk = { + .name = "sdio4_ahb_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .freq_tbl = master_ahb_freq_tbl, + .data = &sdio4_ahb_data, +}; + +static struct bus_clock bsc1_apb_clk = { + .clk = { + .name = "bsc1_apb_clk", + .parent = &kps_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .freq_tbl = slave_apb_freq_tbl, + .data = &bsc1_apb_data, +}; + +static struct bus_clock bsc2_apb_clk = { + .clk = { + .name = "bsc2_apb_clk", + .parent = &kps_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .freq_tbl = slave_apb_freq_tbl, + .data = &bsc2_apb_data, +}; + +static struct bus_clock bsc3_apb_clk = { + .clk = { + .name = "bsc3_apb_clk", + .parent = &kps_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .freq_tbl = slave_apb_freq_tbl, + .data = &bsc3_apb_data, +}; + +/* KPM peripheral */ +static struct peri_clock sdio1_clk = { + .clk = { + .name = "sdio1_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio1_data, +}; + +static struct peri_clock sdio2_clk = { + .clk = { + .name = "sdio2_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio2_data, +}; + +static struct peri_clock sdio3_clk = { + .clk = { + .name = "sdio3_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio3_data, +}; + +static struct peri_clock sdio4_clk = { + .clk = { + .name = "sdio4_clk", + .parent = &ref_52m.clk, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio4_data, +}; + +static struct peri_clock sdio1_sleep_clk = { + .clk = { + .name = "sdio1_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio1_sleep_data, +}; + +static struct peri_clock sdio2_sleep_clk = { + .clk = { + .name = "sdio2_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio2_sleep_data, +}; + +static struct peri_clock sdio3_sleep_clk = { + .clk = { + .name = "sdio3_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio3_sleep_data, +}; + +static struct peri_clock sdio4_sleep_clk = { + .clk = { + .name = "sdio4_sleep_clk", + .parent = &kpm_ccu_clk.clk, + .ops = &bus_clk_ops, + .ccu_clk_mgr_base = KONA_MST_CLK_BASE_ADDR, + }, + .data = &sdio4_sleep_data, +}; + +/* KPS peripheral clock */ +static struct peri_clock bsc1_clk = { + .clk = { + .name = "bsc1_clk", + .parent = &ref_13m.clk, + .rate = 13 * CLOCK_1M, + .div = 1, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .data = &bsc1_data, +}; + +static struct peri_clock bsc2_clk = { + .clk = { + .name = "bsc2_clk", + .parent = &ref_13m.clk, + .rate = 13 * CLOCK_1M, + .div = 1, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .data = &bsc2_data, +}; + +static struct peri_clock bsc3_clk = { + .clk = { + .name = "bsc3_clk", + .parent = &ref_13m.clk, + .rate = 13 * CLOCK_1M, + .div = 1, + .ops = &peri_clk_ops, + .ccu_clk_mgr_base = KONA_SLV_CLK_BASE_ADDR, + }, + .data = &bsc3_data, +}; + +/* public table for registering clocks */ +struct clk_lookup arch_clk_tbl[] = { + /* Peripheral clocks */ + CLK_LK(sdio1), + CLK_LK(sdio2), + CLK_LK(sdio3), + CLK_LK(sdio4), + CLK_LK(sdio1_sleep), + CLK_LK(sdio2_sleep), + CLK_LK(sdio3_sleep), + CLK_LK(sdio4_sleep), + CLK_LK(bsc1), + CLK_LK(bsc2), + CLK_LK(bsc3), + /* Bus clocks */ + CLK_LK(usb_otg_ahb), + CLK_LK(sdio1_ahb), + CLK_LK(sdio2_ahb), + CLK_LK(sdio3_ahb), + CLK_LK(sdio4_ahb), + CLK_LK(bsc1_apb), + CLK_LK(bsc2_apb), + CLK_LK(bsc3_apb), +#ifdef CONFIG_BCM_SF2_ETH + CLK_LK(esub_ccu), +#endif +}; + +/* public array size */ +unsigned int arch_clk_tbl_array_size = ARRAY_SIZE(arch_clk_tbl);
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-bsc.c b/arch/arm/cpu/armv7/bcm281xx/clk-bsc.c new file mode 100644 index 0000000..1b3f36a --- /dev/null +++ b/arch/arm/cpu/armv7/bcm281xx/clk-bsc.c
@@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Broadcom Corporation. + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +/* Enable appropriate clocks for a BSC/I2C port */ +int clk_bsc_enable(void *base) +{ + int ret; + char *bscstr, *apbstr; + + switch ((u32) base) { + case PMU_BSC_BASE_ADDR: + /* PMU clock is always enabled */ + return 0; + case BSC1_BASE_ADDR: + bscstr = "bsc1_clk"; + apbstr = "bsc1_apb_clk"; + break; + case BSC2_BASE_ADDR: + bscstr = "bsc2_clk"; + apbstr = "bsc2_apb_clk"; + break; + case BSC3_BASE_ADDR: + bscstr = "bsc3_clk"; + apbstr = "bsc3_apb_clk"; + break; + default: + printf("%s: base 0x%p not found\n", __func__, base); + return -EINVAL; + } + + /* Note that the bus clock must be enabled first */ + + ret = clk_get_and_enable(apbstr); + if (ret) + return ret; + + ret = clk_get_and_enable(bscstr); + if (ret) + return ret; + + return 0; +}
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-core.c b/arch/arm/cpu/armv7/bcm281xx/clk-core.c new file mode 100644 index 0000000..6a36f94 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm281xx/clk-core.c
@@ -0,0 +1,512 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Broadcom Corporation. + */ + +/* + * + * bcm281xx architecture clock framework + * + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <bitfield.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +#define CLK_WR_ACCESS_PASSWORD 0x00a5a501 +#define WR_ACCESS_OFFSET 0 /* common to all clock blocks */ +#define POLICY_CTL_GO 1 /* Load and refresh policy masks */ +#define POLICY_CTL_GO_ATL 4 /* Active Load */ + +/* Helper function */ +int clk_get_and_enable(char *clkstr) +{ + int ret = 0; + struct clk *c; + + debug("%s: %s\n", __func__, clkstr); + + c = clk_get(clkstr); + if (c) { + ret = clk_enable(c); + if (ret) + return ret; + } else { + printf("%s: Couldn't find %s\n", __func__, clkstr); + return -EINVAL; + } + return ret; +} + +/* + * Poll a register in a CCU's address space, returning when the + * specified bit in that register's value is set (or clear). Delay + * a microsecond after each read of the register. Returns true if + * successful, or false if we gave up trying. + * + * Caller must ensure the CCU lock is held. + */ +#define CLK_GATE_DELAY_USEC 2000 +static inline int wait_bit(void *base, u32 offset, u32 bit, bool want) +{ + unsigned int tries; + u32 bit_mask = 1 << bit; + + for (tries = 0; tries < CLK_GATE_DELAY_USEC; tries++) { + u32 val; + bool bit_val; + + val = readl(base + offset); + bit_val = (val & bit_mask) ? 1 : 0; + if (bit_val == want) + return 0; /* success */ + udelay(1); + } + + debug("%s: timeout on addr 0x%p, waiting for bit %d to go to %d\n", + __func__, base + offset, bit, want); + + return -ETIMEDOUT; +} + +/* Enable a peripheral clock */ +static int peri_clk_enable(struct clk *c, int enable) +{ + int ret = 0; + u32 reg; + struct peri_clock *peri_clk = to_peri_clk(c); + struct peri_clk_data *cd = peri_clk->data; + struct bcm_clk_gate *gate = &cd->gate; + void *base = (void *)c->ccu_clk_mgr_base; + + + debug("%s: %s\n", __func__, c->name); + + clk_get_rate(c); /* Make sure rate and sel are filled in */ + + /* enable access */ + writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET); + + if (enable) { + debug("%s %s set rate %lu div %lu sel %d parent %lu\n", + __func__, c->name, c->rate, c->div, c->sel, + c->parent->rate); + + /* + * clkgate - only software controllable gates are + * supported by u-boot which includes all clocks + * that matter. This avoids bringing in a lot of extra + * complexity as done in the kernel framework. + */ + if (gate_exists(gate)) { + reg = readl(base + cd->gate.offset); + reg |= (1 << cd->gate.en_bit); + writel(reg, base + cd->gate.offset); + } + + /* div and pll select */ + if (divider_exists(&cd->div)) { + reg = readl(base + cd->div.offset); + bitfield_replace(reg, cd->div.shift, cd->div.width, + c->div - 1); + writel(reg, base + cd->div.offset); + } + + /* frequency selector */ + if (selector_exists(&cd->sel)) { + reg = readl(base + cd->sel.offset); + bitfield_replace(reg, cd->sel.shift, cd->sel.width, + c->sel); + writel(reg, base + cd->sel.offset); + } + + /* trigger */ + if (trigger_exists(&cd->trig)) { + writel((1 << cd->trig.bit), base + cd->trig.offset); + + /* wait for trigger status bit to go to 0 */ + ret = wait_bit(base, cd->trig.offset, cd->trig.bit, 0); + if (ret) + return ret; + } + + /* wait for running (status_bit = 1) */ + ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 1); + if (ret) + return ret; + } else { + debug("%s disable clock %s\n", __func__, c->name); + + /* clkgate */ + reg = readl(base + cd->gate.offset); + reg &= ~(1 << cd->gate.en_bit); + writel(reg, base + cd->gate.offset); + + /* wait for stop (status_bit = 0) */ + ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 0); + } + + /* disable access */ + writel(0, base + WR_ACCESS_OFFSET); + + return ret; +} + +/* Set the rate of a peripheral clock */ +static int peri_clk_set_rate(struct clk *c, unsigned long rate) +{ + int ret = 0; + int i; + unsigned long diff; + unsigned long new_rate = 0, div = 1; + struct peri_clock *peri_clk = to_peri_clk(c); + struct peri_clk_data *cd = peri_clk->data; + const char **clock; + + debug("%s: %s\n", __func__, c->name); + diff = rate; + + i = 0; + for (clock = cd->clocks; *clock; clock++, i++) { + struct refclk *ref = refclk_str_to_clk(*clock); + if (!ref) { + printf("%s: Lookup of %s failed\n", __func__, *clock); + return -EINVAL; + } + + /* round to the new rate */ + div = ref->clk.rate / rate; + if (div == 0) + div = 1; + + new_rate = ref->clk.rate / div; + + /* get the min diff */ + if (abs(new_rate - rate) < diff) { + diff = abs(new_rate - rate); + c->sel = i; + c->parent = &ref->clk; + c->rate = new_rate; + c->div = div; + } + } + + debug("%s %s set rate %lu div %lu sel %d parent %lu\n", __func__, + c->name, c->rate, c->div, c->sel, c->parent->rate); + return ret; +} + +/* Get the rate of a peripheral clock */ +static unsigned long peri_clk_get_rate(struct clk *c) +{ + struct peri_clock *peri_clk = to_peri_clk(c); + struct peri_clk_data *cd = peri_clk->data; + void *base = (void *)c->ccu_clk_mgr_base; + int div = 1; + const char **clock; + struct refclk *ref; + u32 reg; + + debug("%s: %s\n", __func__, c->name); + if (selector_exists(&cd->sel)) { + reg = readl(base + cd->sel.offset); + c->sel = bitfield_extract(reg, cd->sel.shift, cd->sel.width); + } else { + /* + * For peri clocks that don't have a selector, the single + * reference clock will always exist at index 0. + */ + c->sel = 0; + } + + if (divider_exists(&cd->div)) { + reg = readl(base + cd->div.offset); + div = bitfield_extract(reg, cd->div.shift, cd->div.width); + div += 1; + } + + clock = cd->clocks; + ref = refclk_str_to_clk(clock[c->sel]); + if (!ref) { + printf("%s: Can't lookup %s\n", __func__, clock[c->sel]); + return 0; + } + + c->parent = &ref->clk; + c->div = div; + c->rate = c->parent->rate / c->div; + debug("%s parent rate %lu div %d sel %d rate %lu\n", __func__, + c->parent->rate, div, c->sel, c->rate); + + return c->rate; +} + +/* Peripheral clock operations */ +struct clk_ops peri_clk_ops = { + .enable = peri_clk_enable, + .set_rate = peri_clk_set_rate, + .get_rate = peri_clk_get_rate, +}; + +/* Enable a CCU clock */ +static int ccu_clk_enable(struct clk *c, int enable) +{ + struct ccu_clock *ccu_clk = to_ccu_clk(c); + void *base = (void *)c->ccu_clk_mgr_base; + int ret = 0; + u32 reg; + + debug("%s: %s\n", __func__, c->name); + if (!enable) + return -EINVAL; /* CCU clock cannot shutdown */ + + /* enable access */ + writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET); + + /* config enable for policy engine */ + writel(1, base + ccu_clk->lvm_en_offset); + + /* wait for bit to go to 0 */ + ret = wait_bit(base, ccu_clk->lvm_en_offset, 0, 0); + if (ret) + return ret; + + /* freq ID */ + if (!ccu_clk->freq_bit_shift) + ccu_clk->freq_bit_shift = 8; + + /* Set frequency id for each of the 4 policies */ + reg = ccu_clk->freq_id | + (ccu_clk->freq_id << (ccu_clk->freq_bit_shift)) | + (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 2)) | + (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 3)); + writel(reg, base + ccu_clk->policy_freq_offset); + + /* enable all clock mask */ + writel(0x7fffffff, base + ccu_clk->policy0_mask_offset); + writel(0x7fffffff, base + ccu_clk->policy1_mask_offset); + writel(0x7fffffff, base + ccu_clk->policy2_mask_offset); + writel(0x7fffffff, base + ccu_clk->policy3_mask_offset); + + if (ccu_clk->num_policy_masks == 2) { + writel(0x7fffffff, base + ccu_clk->policy0_mask2_offset); + writel(0x7fffffff, base + ccu_clk->policy1_mask2_offset); + writel(0x7fffffff, base + ccu_clk->policy2_mask2_offset); + writel(0x7fffffff, base + ccu_clk->policy3_mask2_offset); + } + + /* start policy engine */ + reg = readl(base + ccu_clk->policy_ctl_offset); + reg |= (POLICY_CTL_GO + POLICY_CTL_GO_ATL); + writel(reg, base + ccu_clk->policy_ctl_offset); + + /* wait till started */ + ret = wait_bit(base, ccu_clk->policy_ctl_offset, 0, 0); + if (ret) + return ret; + + /* disable access */ + writel(0, base + WR_ACCESS_OFFSET); + + return ret; +} + +/* Get the CCU clock rate */ +static unsigned long ccu_clk_get_rate(struct clk *c) +{ + struct ccu_clock *ccu_clk = to_ccu_clk(c); + debug("%s: %s\n", __func__, c->name); + c->rate = ccu_clk->freq_tbl[ccu_clk->freq_id]; + return c->rate; +} + +/* CCU clock operations */ +struct clk_ops ccu_clk_ops = { + .enable = ccu_clk_enable, + .get_rate = ccu_clk_get_rate, +}; + +/* Enable a bus clock */ +static int bus_clk_enable(struct clk *c, int enable) +{ + struct bus_clock *bus_clk = to_bus_clk(c); + struct bus_clk_data *cd = bus_clk->data; + void *base = (void *)c->ccu_clk_mgr_base; + int ret = 0; + u32 reg; + + debug("%s: %s\n", __func__, c->name); + /* enable access */ + writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET); + + /* enable gating */ + reg = readl(base + cd->gate.offset); + if (!!(reg & (1 << cd->gate.status_bit)) == !!enable) + debug("%s already %s\n", c->name, + enable ? "enabled" : "disabled"); + else { + int want = (enable) ? 1 : 0; + reg |= (1 << cd->gate.hw_sw_sel_bit); + + if (enable) + reg |= (1 << cd->gate.en_bit); + else + reg &= ~(1 << cd->gate.en_bit); + + writel(reg, base + cd->gate.offset); + ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, + want); + if (ret) + return ret; + } + + /* disable access */ + writel(0, base + WR_ACCESS_OFFSET); + + return ret; +} + +/* Get the rate of a bus clock */ +static unsigned long bus_clk_get_rate(struct clk *c) +{ + struct bus_clock *bus_clk = to_bus_clk(c); + struct ccu_clock *ccu_clk; + + debug("%s: %s\n", __func__, c->name); + ccu_clk = to_ccu_clk(c->parent); + + c->rate = bus_clk->freq_tbl[ccu_clk->freq_id]; + c->div = ccu_clk->freq_tbl[ccu_clk->freq_id] / c->rate; + return c->rate; +} + +/* Bus clock operations */ +struct clk_ops bus_clk_ops = { + .enable = bus_clk_enable, + .get_rate = bus_clk_get_rate, +}; + +/* Enable a reference clock */ +static int ref_clk_enable(struct clk *c, int enable) +{ + debug("%s: %s\n", __func__, c->name); + return 0; +} + +/* Reference clock operations */ +struct clk_ops ref_clk_ops = { + .enable = ref_clk_enable, +}; + +/* + * clk.h implementation follows + */ + +/* Initialize the clock framework */ +int clk_init(void) +{ + debug("%s:\n", __func__); + return 0; +} + +/* Get a clock handle, give a name string */ +struct clk *clk_get(const char *con_id) +{ + int i; + struct clk_lookup *clk_tblp; + + debug("%s: %s\n", __func__, con_id); + + clk_tblp = arch_clk_tbl; + for (i = 0; i < arch_clk_tbl_array_size; i++, clk_tblp++) { + if (clk_tblp->con_id) { + if (!con_id || strcmp(clk_tblp->con_id, con_id)) + continue; + return clk_tblp->clk; + } + } + return NULL; +} + +/* Enable a clock */ +int clk_enable(struct clk *c) +{ + int ret = 0; + + debug("%s: %s\n", __func__, c->name); + if (!c->ops || !c->ops->enable) + return -1; + + /* enable parent clock first */ + if (c->parent) + ret = clk_enable(c->parent); + + if (ret) + return ret; + + if (!c->use_cnt) { + c->use_cnt++; + ret = c->ops->enable(c, 1); + } + + return ret; +} + +/* Disable a clock */ +void clk_disable(struct clk *c) +{ + debug("%s: %s\n", __func__, c->name); + if (!c->ops || !c->ops->enable) + return; + + if (c->use_cnt) { + c->use_cnt--; + c->ops->enable(c, 0); + } + + /* disable parent */ + if (c->parent) + clk_disable(c->parent); +} + +/* Get the clock rate */ +unsigned long clk_get_rate(struct clk *c) +{ + unsigned long rate; + + if (!c || !c->ops || !c->ops->get_rate) + return 0; + debug("%s: %s\n", __func__, c->name); + + rate = c->ops->get_rate(c); + debug("%s: rate = %ld\n", __func__, rate); + return rate; +} + +/* Set the clock rate */ +int clk_set_rate(struct clk *c, unsigned long rate) +{ + int ret; + + if (!c || !c->ops || !c->ops->set_rate) + return -EINVAL; + debug("%s: %s rate=%ld\n", __func__, c->name, rate); + + if (c->use_cnt) + return -EINVAL; + + ret = c->ops->set_rate(c, rate); + + return ret; +} + +/* Not required for this arch */ +/* +long clk_round_rate(struct clk *clk, unsigned long rate); +int clk_set_parent(struct clk *clk, struct clk *parent); +struct clk *clk_get_parent(struct clk *clk); +*/
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-core.h b/arch/arm/cpu/armv7/bcm281xx/clk-core.h new file mode 100644 index 0000000..a736ae9 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm281xx/clk-core.h
@@ -0,0 +1,490 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2013 Broadcom Corporation. + */ + +#include <linux/stddef.h> + +#ifdef CONFIG_CLK_DEBUG +#undef writel +#undef readl +static inline void writel(u32 val, void *addr) +{ + printf("Write [0x%p] = 0x%08x\n", addr, val); + *(u32 *)addr = val; +} + +static inline u32 readl(void *addr) +{ + u32 val = *(u32 *)addr; + printf("Read [0x%p] = 0x%08x\n", addr, val); + return val; +} +#endif + +struct clk; + +struct clk_lookup { + const char *dev_id; + const char *con_id; + struct clk *clk; +}; + +extern struct clk_lookup arch_clk_tbl[]; +extern unsigned int arch_clk_tbl_array_size; + +/** + * struct clk_ops - standard clock operations + * @enable: enable/disable clock, see clk_enable() and clk_disable() + * @set_rate: set the clock rate, see clk_set_rate(). + * @get_rate: get the clock rate, see clk_get_rate(). + * @round_rate: round a given clock rate, see clk_round_rate(). + * @set_parent: set the clock's parent, see clk_set_parent(). + * + * Group the common clock implementations together so that we + * don't have to keep setting the same fiels again. We leave + * enable in struct clk. + * + */ +struct clk_ops { + int (*enable) (struct clk *c, int enable); + int (*set_rate) (struct clk *c, unsigned long rate); + unsigned long (*get_rate) (struct clk *c); + unsigned long (*round_rate) (struct clk *c, unsigned long rate); + int (*set_parent) (struct clk *c, struct clk *parent); +}; + +struct clk { + struct clk *parent; + const char *name; + int use_cnt; + unsigned long rate; /* in HZ */ + + /* programmable divider. 0 means fixed ratio to parent clock */ + unsigned long div; + + struct clk_src *src; + struct clk_ops *ops; + + unsigned long ccu_clk_mgr_base; + int sel; +}; + +struct refclk *refclk_str_to_clk(const char *name); + +/* The common clock framework uses u8 to represent a parent index */ +#define PARENT_COUNT_MAX ((u32)U8_MAX) + +#define BAD_CLK_INDEX U8_MAX /* Can't ever be valid */ +#define BAD_CLK_NAME ((const char *)-1) + +#define BAD_SCALED_DIV_VALUE U64_MAX + +/* + * Utility macros for object flag management. If possible, flags + * should be defined such that 0 is the desired default value. + */ +#define FLAG(type, flag) BCM_CLK_ ## type ## _FLAGS_ ## flag +#define FLAG_SET(obj, type, flag) ((obj)->flags |= FLAG(type, flag)) +#define FLAG_CLEAR(obj, type, flag) ((obj)->flags &= ~(FLAG(type, flag))) +#define FLAG_FLIP(obj, type, flag) ((obj)->flags ^= FLAG(type, flag)) +#define FLAG_TEST(obj, type, flag) (!!((obj)->flags & FLAG(type, flag))) + +/* Clock field state tests */ + +#define gate_exists(gate) FLAG_TEST(gate, GATE, EXISTS) +#define gate_is_enabled(gate) FLAG_TEST(gate, GATE, ENABLED) +#define gate_is_hw_controllable(gate) FLAG_TEST(gate, GATE, HW) +#define gate_is_sw_controllable(gate) FLAG_TEST(gate, GATE, SW) +#define gate_is_sw_managed(gate) FLAG_TEST(gate, GATE, SW_MANAGED) +#define gate_is_no_disable(gate) FLAG_TEST(gate, GATE, NO_DISABLE) + +#define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED) + +#define divider_exists(div) FLAG_TEST(div, DIV, EXISTS) +#define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED) +#define divider_has_fraction(div) (!divider_is_fixed(div) && \ + (div)->frac_width > 0) + +#define selector_exists(sel) ((sel)->width != 0) +#define trigger_exists(trig) FLAG_TEST(trig, TRIG, EXISTS) + +/* Clock type, used to tell common block what it's part of */ +enum bcm_clk_type { + bcm_clk_none, /* undefined clock type */ + bcm_clk_bus, + bcm_clk_core, + bcm_clk_peri +}; + +/* + * Gating control and status is managed by a 32-bit gate register. + * + * There are several types of gating available: + * - (no gate) + * A clock with no gate is assumed to be always enabled. + * - hardware-only gating (auto-gating) + * Enabling or disabling clocks with this type of gate is + * managed automatically by the hardware. Such clocks can be + * considered by the software to be enabled. The current status + * of auto-gated clocks can be read from the gate status bit. + * - software-only gating + * Auto-gating is not available for this type of clock. + * Instead, software manages whether it's enabled by setting or + * clearing the enable bit. The current gate status of a gate + * under software control can be read from the gate status bit. + * To ensure a change to the gating status is complete, the + * status bit can be polled to verify that the gate has entered + * the desired state. + * - selectable hardware or software gating + * Gating for this type of clock can be configured to be either + * under software or hardware control. Which type is in use is + * determined by the hw_sw_sel bit of the gate register. + */ +struct bcm_clk_gate { + u32 offset; /* gate register offset */ + u32 status_bit; /* 0: gate is disabled; 0: gatge is enabled */ + u32 en_bit; /* 0: disable; 1: enable */ + u32 hw_sw_sel_bit; /* 0: hardware gating; 1: software gating */ + u32 flags; /* BCM_CLK_GATE_FLAGS_* below */ +}; + +/* + * Gate flags: + * HW means this gate can be auto-gated + * SW means the state of this gate can be software controlled + * NO_DISABLE means this gate is (only) enabled if under software control + * SW_MANAGED means the status of this gate is under software control + * ENABLED means this software-managed gate is *supposed* to be enabled + */ +#define BCM_CLK_GATE_FLAGS_EXISTS ((u32)1 << 0) /* Gate is valid */ +#define BCM_CLK_GATE_FLAGS_HW ((u32)1 << 1) /* Can auto-gate */ +#define BCM_CLK_GATE_FLAGS_SW ((u32)1 << 2) /* Software control */ +#define BCM_CLK_GATE_FLAGS_NO_DISABLE ((u32)1 << 3) /* HW or enabled */ +#define BCM_CLK_GATE_FLAGS_SW_MANAGED ((u32)1 << 4) /* SW now in control */ +#define BCM_CLK_GATE_FLAGS_ENABLED ((u32)1 << 5) /* If SW_MANAGED */ + +/* + * Gate initialization macros. + * + * Any gate initially under software control will be enabled. + */ + +/* A hardware/software gate initially under software control */ +#define HW_SW_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .hw_sw_sel_bit = (_hw_sw_sel_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ + FLAG(GATE, SW_MANAGED)|FLAG(GATE, ENABLED)| \ + FLAG(GATE, EXISTS), \ + } + +/* A hardware/software gate initially under hardware control */ +#define HW_SW_GATE_AUTO(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .hw_sw_sel_bit = (_hw_sw_sel_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ + FLAG(GATE, EXISTS), \ + } + +/* A hardware-or-enabled gate (enabled if not under hardware control) */ +#define HW_ENABLE_GATE(_offset, _status_bit, _en_bit, _hw_sw_sel_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .hw_sw_sel_bit = (_hw_sw_sel_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, SW)| \ + FLAG(GATE, NO_DISABLE)|FLAG(GATE, EXISTS), \ + } + +/* A software-only gate */ +#define SW_ONLY_GATE(_offset, _status_bit, _en_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .en_bit = (_en_bit), \ + .flags = FLAG(GATE, SW)|FLAG(GATE, SW_MANAGED)| \ + FLAG(GATE, ENABLED)|FLAG(GATE, EXISTS), \ + } + +/* A hardware-only gate */ +#define HW_ONLY_GATE(_offset, _status_bit) \ + { \ + .offset = (_offset), \ + .status_bit = (_status_bit), \ + .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \ + } + +/* + * Each clock can have zero, one, or two dividers which change the + * output rate of the clock. Each divider can be either fixed or + * variable. If there are two dividers, they are the "pre-divider" + * and the "regular" or "downstream" divider. If there is only one, + * there is no pre-divider. + * + * A fixed divider is any non-zero (positive) value, and it + * indicates how the input rate is affected by the divider. + * + * The value of a variable divider is maintained in a sub-field of a + * 32-bit divider register. The position of the field in the + * register is defined by its offset and width. The value recorded + * in this field is always 1 less than the value it represents. + * + * In addition, a variable divider can indicate that some subset + * of its bits represent a "fractional" part of the divider. Such + * bits comprise the low-order portion of the divider field, and can + * be viewed as representing the portion of the divider that lies to + * the right of the decimal point. Most variable dividers have zero + * fractional bits. Variable dividers with non-zero fraction width + * still record a value 1 less than the value they represent; the + * added 1 does *not* affect the low-order bit in this case, it + * affects the bits above the fractional part only. (Often in this + * code a divider field value is distinguished from the value it + * represents by referring to the latter as a "divisor".) + * + * In order to avoid dealing with fractions, divider arithmetic is + * performed using "scaled" values. A scaled value is one that's + * been left-shifted by the fractional width of a divider. Dividing + * a scaled value by a scaled divisor produces the desired quotient + * without loss of precision and without any other special handling + * for fractions. + * + * The recorded value of a variable divider can be modified. To + * modify either divider (or both), a clock must be enabled (i.e., + * using its gate). In addition, a trigger register (described + * below) must be used to commit the change, and polled to verify + * the change is complete. + */ +struct bcm_clk_div { + union { + struct { /* variable divider */ + u32 offset; /* divider register offset */ + u32 shift; /* field shift */ + u32 width; /* field width */ + u32 frac_width; /* field fraction width */ + + u64 scaled_div; /* scaled divider value */ + }; + u32 fixed; /* non-zero fixed divider value */ + }; + u32 flags; /* BCM_CLK_DIV_FLAGS_* below */ +}; + +/* + * Divider flags: + * EXISTS means this divider exists + * FIXED means it is a fixed-rate divider + */ +#define BCM_CLK_DIV_FLAGS_EXISTS ((u32)1 << 0) /* Divider is valid */ +#define BCM_CLK_DIV_FLAGS_FIXED ((u32)1 << 1) /* Fixed-value */ + +/* Divider initialization macros */ + +/* A fixed (non-zero) divider */ +#define FIXED_DIVIDER(_value) \ + { \ + .fixed = (_value), \ + .flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED), \ + } + +/* A divider with an integral divisor */ +#define DIVIDER(_offset, _shift, _width) \ + { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .scaled_div = BAD_SCALED_DIV_VALUE, \ + .flags = FLAG(DIV, EXISTS), \ + } + +/* A divider whose divisor has an integer and fractional part */ +#define FRAC_DIVIDER(_offset, _shift, _width, _frac_width) \ + { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .frac_width = (_frac_width), \ + .scaled_div = BAD_SCALED_DIV_VALUE, \ + .flags = FLAG(DIV, EXISTS), \ + } + +/* + * Clocks may have multiple "parent" clocks. If there is more than + * one, a selector must be specified to define which of the parent + * clocks is currently in use. The selected clock is indicated in a + * sub-field of a 32-bit selector register. The range of + * representable selector values typically exceeds the number of + * available parent clocks. Occasionally the reset value of a + * selector field is explicitly set to a (specific) value that does + * not correspond to a defined input clock. + * + * We register all known parent clocks with the common clock code + * using a packed array (i.e., no empty slots) of (parent) clock + * names, and refer to them later using indexes into that array. + * We maintain an array of selector values indexed by common clock + * index values in order to map between these common clock indexes + * and the selector values used by the hardware. + * + * Like dividers, a selector can be modified, but to do so a clock + * must be enabled, and a trigger must be used to commit the change. + */ +struct bcm_clk_sel { + u32 offset; /* selector register offset */ + u32 shift; /* field shift */ + u32 width; /* field width */ + + u32 parent_count; /* number of entries in parent_sel[] */ + u32 *parent_sel; /* array of parent selector values */ + u8 clk_index; /* current selected index in parent_sel[] */ +}; + +/* Selector initialization macro */ +#define SELECTOR(_offset, _shift, _width) \ + { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .clk_index = BAD_CLK_INDEX, \ + } + +/* + * Making changes to a variable divider or a selector for a clock + * requires the use of a trigger. A trigger is defined by a single + * bit within a register. To signal a change, a 1 is written into + * that bit. To determine when the change has been completed, that + * trigger bit is polled; the read value will be 1 while the change + * is in progress, and 0 when it is complete. + * + * Occasionally a clock will have more than one trigger. In this + * case, the "pre-trigger" will be used when changing a clock's + * selector and/or its pre-divider. + */ +struct bcm_clk_trig { + u32 offset; /* trigger register offset */ + u32 bit; /* trigger bit */ + u32 flags; /* BCM_CLK_TRIG_FLAGS_* below */ +}; + +/* + * Trigger flags: + * EXISTS means this trigger exists + */ +#define BCM_CLK_TRIG_FLAGS_EXISTS ((u32)1 << 0) /* Trigger is valid */ + +/* Trigger initialization macro */ +#define TRIGGER(_offset, _bit) \ + { \ + .offset = (_offset), \ + .bit = (_bit), \ + .flags = FLAG(TRIG, EXISTS), \ + } + +struct bus_clk_data { + struct bcm_clk_gate gate; +}; + +struct core_clk_data { + struct bcm_clk_gate gate; +}; + +struct peri_clk_data { + struct bcm_clk_gate gate; + struct bcm_clk_trig pre_trig; + struct bcm_clk_div pre_div; + struct bcm_clk_trig trig; + struct bcm_clk_div div; + struct bcm_clk_sel sel; + const char *clocks[]; /* must be last; use CLOCKS() to declare */ +}; +#define CLOCKS(...) { __VA_ARGS__, NULL, } +#define NO_CLOCKS { NULL, } /* Must use of no parent clocks */ + +struct refclk { + struct clk clk; +}; + +struct peri_clock { + struct clk clk; + struct peri_clk_data *data; +}; + +struct ccu_clock { + struct clk clk; + + int num_policy_masks; + unsigned long policy_freq_offset; + int freq_bit_shift; /* 8 for most CCUs */ + unsigned long policy_ctl_offset; + unsigned long policy0_mask_offset; + unsigned long policy1_mask_offset; + unsigned long policy2_mask_offset; + unsigned long policy3_mask_offset; + unsigned long policy0_mask2_offset; + unsigned long policy1_mask2_offset; + unsigned long policy2_mask2_offset; + unsigned long policy3_mask2_offset; + unsigned long lvm_en_offset; + + int freq_id; + unsigned long *freq_tbl; +}; + +struct bus_clock { + struct clk clk; + struct bus_clk_data *data; + unsigned long *freq_tbl; +}; + +struct ref_clock { + struct clk clk; +}; + +static inline int is_same_clock(struct clk *a, struct clk *b) +{ + return (a == b); +} + +#define to_clk(p) (&((p)->clk)) +#define name_to_clk(name) (&((name##_clk).clk)) +/* declare a struct clk_lookup */ +#define CLK_LK(name) \ +{.con_id = __stringify(name##_clk), .clk = name_to_clk(name),} + +static inline struct refclk *to_refclk(struct clk *clock) +{ + return container_of(clock, struct refclk, clk); +} + +static inline struct peri_clock *to_peri_clk(struct clk *clock) +{ + return container_of(clock, struct peri_clock, clk); +} + +static inline struct ccu_clock *to_ccu_clk(struct clk *clock) +{ + return container_of(clock, struct ccu_clock, clk); +} + +static inline struct bus_clock *to_bus_clk(struct clk *clock) +{ + return container_of(clock, struct bus_clock, clk); +} + +static inline struct ref_clock *to_ref_clk(struct clk *clock) +{ + return container_of(clock, struct ref_clock, clk); +} + +extern struct clk_ops peri_clk_ops; +extern struct clk_ops ccu_clk_ops; +extern struct clk_ops bus_clk_ops; +extern struct clk_ops ref_clk_ops; + +extern int clk_get_and_enable(char *clkstr);
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-eth.c b/arch/arm/cpu/armv7/bcm281xx/clk-eth.c new file mode 100644 index 0000000..618af70 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm281xx/clk-eth.c
@@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Broadcom Corporation. + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +#define WR_ACCESS_ADDR ESUB_CLK_BASE_ADDR +#define WR_ACCESS_PASSWORD 0xA5A500 + +#define PLLE_POST_RESETB_ADDR (ESUB_CLK_BASE_ADDR + 0x00000C00) + +#define PLLE_RESETB_ADDR (ESUB_CLK_BASE_ADDR + 0x00000C58) +#define PLLE_RESETB_I_PLL_RESETB_PLLE_MASK 0x00010000 +#define PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK 0x00000001 + +#define PLL_LOCK_ADDR (ESUB_CLK_BASE_ADDR + 0x00000C38) +#define PLL_LOCK_PLL_LOCK_PLLE_MASK 0x00000001 + +#define ESW_SYS_DIV_ADDR (ESUB_CLK_BASE_ADDR + 0x00000A04) +#define ESW_SYS_DIV_PLL_SELECT_MASK 0x00000300 +#define ESW_SYS_DIV_DIV_MASK 0x0000001C +#define ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT 0x00000100 +#define ESW_SYS_DIV_DIV_SELECT 0x4 +#define ESW_SYS_DIV_TRIGGER_MASK 0x00000001 + +#define ESUB_AXI_DIV_DEBUG_ADDR (ESUB_CLK_BASE_ADDR + 0x00000E04) +#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK 0x0000001C +#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK 0x00000040 +#define ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT 0x0 +#define ESUB_AXI_DIV_DEBUG_TRIGGER_MASK 0x00000001 + +#define PLL_MAX_RETRY 100 + +/* Enable appropriate clocks for Ethernet */ +int clk_eth_enable(void) +{ + int rc = -1; + int retry_count = 0; + rc = clk_get_and_enable("esub_ccu_clk"); + + /* Enable Access to CCU registers */ + writel((1 | WR_ACCESS_PASSWORD), WR_ACCESS_ADDR); + + writel(readl(PLLE_POST_RESETB_ADDR) & + ~PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK, + PLLE_POST_RESETB_ADDR); + + /* Take PLL out of reset and put into normal mode */ + writel(readl(PLLE_RESETB_ADDR) | PLLE_RESETB_I_PLL_RESETB_PLLE_MASK, + PLLE_RESETB_ADDR); + + /* Wait for PLL lock */ + rc = -1; + while (retry_count < PLL_MAX_RETRY) { + udelay(100); + if (readl(PLL_LOCK_ADDR) & PLL_LOCK_PLL_LOCK_PLLE_MASK) { + rc = 0; + break; + } + retry_count++; + } + + if (rc == -1) { + printf("%s: ETH-PLL lock timeout, Ethernet is not enabled!\n", + __func__); + return -1; + } + + writel(readl(PLLE_POST_RESETB_ADDR) | + PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK, + PLLE_POST_RESETB_ADDR); + + /* Switch esw_sys_clk to use 104MHz(208MHz/2) clock */ + writel((readl(ESW_SYS_DIV_ADDR) & + ~(ESW_SYS_DIV_PLL_SELECT_MASK | ESW_SYS_DIV_DIV_MASK)) | + ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT | ESW_SYS_DIV_DIV_SELECT, + ESW_SYS_DIV_ADDR); + + writel(readl(ESW_SYS_DIV_ADDR) | ESW_SYS_DIV_TRIGGER_MASK, + ESW_SYS_DIV_ADDR); + + /* Wait for trigger complete */ + rc = -1; + retry_count = 0; + while (retry_count < PLL_MAX_RETRY) { + udelay(100); + if (!(readl(ESW_SYS_DIV_ADDR) & ESW_SYS_DIV_TRIGGER_MASK)) { + rc = 0; + break; + } + retry_count++; + } + + if (rc == -1) { + printf("%s: SYS CLK Trigger timeout, Ethernet is not enabled!\n", + __func__); + return -1; + } + + /* switch Esub AXI clock to 208MHz */ + writel((readl(ESUB_AXI_DIV_DEBUG_ADDR) & + ~(ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK | + ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK | + ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) | + ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT | + ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK, + ESUB_AXI_DIV_DEBUG_ADDR); + + writel(readl(ESUB_AXI_DIV_DEBUG_ADDR) | + ESUB_AXI_DIV_DEBUG_TRIGGER_MASK, + ESUB_AXI_DIV_DEBUG_ADDR); + + /* Wait for trigger complete */ + rc = -1; + retry_count = 0; + while (retry_count < PLL_MAX_RETRY) { + udelay(100); + if (!(readl(ESUB_AXI_DIV_DEBUG_ADDR) & + ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) { + rc = 0; + break; + } + retry_count++; + } + + if (rc == -1) { + printf("%s: AXI CLK Trigger timeout, Ethernet is not enabled!\n", + __func__); + return -1; + } + + /* Disable Access to CCU registers */ + writel(WR_ACCESS_PASSWORD, WR_ACCESS_ADDR); + + return rc; +}
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-sdio.c b/arch/arm/cpu/armv7/bcm281xx/clk-sdio.c new file mode 100644 index 0000000..f2ba354 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm281xx/clk-sdio.c
@@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Broadcom Corporation. + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/sysmap.h> +#include <asm/kona-common/clk.h> +#include "clk-core.h" + +/* Enable appropriate clocks for an SDIO port */ +int clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep) +{ + int ret; + struct clk *c; + + char *clkstr; + char *slpstr; + char *ahbstr; + + switch ((u32) base) { + case CONFIG_SYS_SDIO_BASE0: + clkstr = CONFIG_SYS_SDIO0 "_clk"; + ahbstr = CONFIG_SYS_SDIO0 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO0 "_sleep_clk"; + break; + case CONFIG_SYS_SDIO_BASE1: + clkstr = CONFIG_SYS_SDIO1 "_clk"; + ahbstr = CONFIG_SYS_SDIO1 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO1 "_sleep_clk"; + break; + case CONFIG_SYS_SDIO_BASE2: + clkstr = CONFIG_SYS_SDIO2 "_clk"; + ahbstr = CONFIG_SYS_SDIO2 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO2 "_sleep_clk"; + break; + case CONFIG_SYS_SDIO_BASE3: + clkstr = CONFIG_SYS_SDIO3 "_clk"; + ahbstr = CONFIG_SYS_SDIO3 "_ahb_clk"; + slpstr = CONFIG_SYS_SDIO3 "_sleep_clk"; + break; + default: + printf("%s: base 0x%p not found\n", __func__, base); + return -EINVAL; + } + + ret = clk_get_and_enable(ahbstr); + if (ret) + return ret; + + ret = clk_get_and_enable(slpstr); + if (ret) + return ret; + + c = clk_get(clkstr); + if (c) { + ret = clk_set_rate(c, rate); + if (ret) + return ret; + + ret = clk_enable(c); + if (ret) + return ret; + } else { + printf("%s: Couldn't find %s\n", __func__, clkstr); + return -EINVAL; + } + *actual_ratep = rate; + return 0; +}
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-usb-otg.c b/arch/arm/cpu/armv7/bcm281xx/clk-usb-otg.c new file mode 100644 index 0000000..f604aec --- /dev/null +++ b/arch/arm/cpu/armv7/bcm281xx/clk-usb-otg.c
@@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Broadcom Corporation. + */ + +#include <common.h> +#include <linux/errno.h> +#include <asm/arch/sysmap.h> +#include "clk-core.h" + +/* Enable appropriate clocks for the USB OTG port */ +int clk_usb_otg_enable(void *base) +{ + char *ahbstr; + + switch ((u32) base) { + case HSOTG_BASE_ADDR: + ahbstr = "usb_otg_ahb_clk"; + break; + default: + printf("%s: base 0x%p not found\n", __func__, base); + return -EINVAL; + } + + return clk_get_and_enable(ahbstr); +}
diff --git a/arch/arm/cpu/armv7/bcm281xx/reset.c b/arch/arm/cpu/armv7/bcm281xx/reset.c new file mode 100644 index 0000000..fbdeea4 --- /dev/null +++ b/arch/arm/cpu/armv7/bcm281xx/reset.c
@@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Broadcom Corporation. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/sysmap.h> + +#define EN_MASK 0x08000000 /* Enable timer */ +#define SRSTEN_MASK 0x04000000 /* Enable soft reset */ +#define CLKS_SHIFT 20 /* Clock period shift */ +#define LD_SHIFT 0 /* Reload value shift */ + +void reset_cpu(ulong ignored) +{ + /* + * Set WD enable, RST enable, + * 3.9 msec clock period (8), reload value (8*3.9ms) + */ + u32 reg = EN_MASK + SRSTEN_MASK + (8 << CLKS_SHIFT) + (8 << LD_SHIFT); + writel(reg, SECWD2_BASE_ADDR); + + while (1) + ; /* loop forever till reset */ +}
diff --git a/arch/arm/cpu/armv7/bcmcygnus/Makefile b/arch/arm/cpu/armv7/bcmcygnus/Makefile new file mode 100644 index 0000000..3496bcd --- /dev/null +++ b/arch/arm/cpu/armv7/bcmcygnus/Makefile
@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2014 Broadcom Corporation. + +obj-y += reset.o
diff --git a/arch/arm/cpu/armv7/bcmcygnus/reset.c b/arch/arm/cpu/armv7/bcmcygnus/reset.c new file mode 100644 index 0000000..7f3f405 --- /dev/null +++ b/arch/arm/cpu/armv7/bcmcygnus/reset.c
@@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Broadcom Corporation. + */ + +#include <common.h> +#include <asm/io.h> + +#define CRMU_MAIL_BOX1 0x03024028 +#define CRMU_SOFT_RESET_CMD 0xFFFFFFFF + +void reset_cpu(ulong ignored) +{ + /* Send soft reset command via Mailbox. */ + writel(CRMU_SOFT_RESET_CMD, CRMU_MAIL_BOX1); + + while (1) + ; /* loop forever till reset */ +}
diff --git a/arch/arm/cpu/armv7/bcmnsp/Makefile b/arch/arm/cpu/armv7/bcmnsp/Makefile new file mode 100644 index 0000000..3496bcd --- /dev/null +++ b/arch/arm/cpu/armv7/bcmnsp/Makefile
@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2014 Broadcom Corporation. + +obj-y += reset.o
diff --git a/arch/arm/cpu/armv7/bcmnsp/reset.c b/arch/arm/cpu/armv7/bcmnsp/reset.c new file mode 100644 index 0000000..674166d --- /dev/null +++ b/arch/arm/cpu/armv7/bcmnsp/reset.c
@@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Broadcom Corporation. + */ + +#include <common.h> +#include <asm/io.h> + +#define CRU_RESET_OFFSET 0x1803F184 + +void reset_cpu(ulong ignored) +{ + /* Reset the cpu by setting software reset request bit */ + writel(0x1, CRU_RESET_OFFSET); + + while (1) + ; /* loop forever till reset */ +}
diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c new file mode 100644 index 0000000..99484c2 --- /dev/null +++ b/arch/arm/cpu/armv7/cache_v7.c
@@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + */ +#include <linux/types.h> +#include <common.h> +#include <asm/armv7.h> +#include <asm/utils.h> + +#define ARMV7_DCACHE_INVAL_RANGE 1 +#define ARMV7_DCACHE_CLEAN_INVAL_RANGE 2 + +#ifndef CONFIG_SYS_DCACHE_OFF + +/* Asm functions from cache_v7_asm.S */ +void v7_flush_dcache_all(void); +void v7_invalidate_dcache_all(void); + +static u32 get_ccsidr(void) +{ + u32 ccsidr; + + /* Read current CP15 Cache Size ID Register */ + asm volatile ("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr)); + return ccsidr; +} + +static void v7_dcache_clean_inval_range(u32 start, u32 stop, u32 line_len) +{ + u32 mva; + + /* Align start to cache line boundary */ + start &= ~(line_len - 1); + for (mva = start; mva < stop; mva = mva + line_len) { + /* DCCIMVAC - Clean & Invalidate data cache by MVA to PoC */ + asm volatile ("mcr p15, 0, %0, c7, c14, 1" : : "r" (mva)); + } +} + +static void v7_dcache_inval_range(u32 start, u32 stop, u32 line_len) +{ + u32 mva; + + if (!check_cache_range(start, stop)) + return; + + for (mva = start; mva < stop; mva = mva + line_len) { + /* DCIMVAC - Invalidate data cache by MVA to PoC */ + asm volatile ("mcr p15, 0, %0, c7, c6, 1" : : "r" (mva)); + } +} + +static void v7_dcache_maint_range(u32 start, u32 stop, u32 range_op) +{ + u32 line_len, ccsidr; + + ccsidr = get_ccsidr(); + line_len = ((ccsidr & CCSIDR_LINE_SIZE_MASK) >> + CCSIDR_LINE_SIZE_OFFSET) + 2; + /* Converting from words to bytes */ + line_len += 2; + /* converting from log2(linelen) to linelen */ + line_len = 1 << line_len; + + switch (range_op) { + case ARMV7_DCACHE_CLEAN_INVAL_RANGE: + v7_dcache_clean_inval_range(start, stop, line_len); + break; + case ARMV7_DCACHE_INVAL_RANGE: + v7_dcache_inval_range(start, stop, line_len); + break; + } + + /* DSB to make sure the operation is complete */ + dsb(); +} + +/* Invalidate TLB */ +static void v7_inval_tlb(void) +{ + /* Invalidate entire unified TLB */ + asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0)); + /* Invalidate entire data TLB */ + asm volatile ("mcr p15, 0, %0, c8, c6, 0" : : "r" (0)); + /* Invalidate entire instruction TLB */ + asm volatile ("mcr p15, 0, %0, c8, c5, 0" : : "r" (0)); + /* Full system DSB - make sure that the invalidation is complete */ + dsb(); + /* Full system ISB - make sure the instruction stream sees it */ + isb(); +} + +void invalidate_dcache_all(void) +{ + v7_invalidate_dcache_all(); + + v7_outer_cache_inval_all(); +} + +/* + * Performs a clean & invalidation of the entire data cache + * at all levels + */ +void flush_dcache_all(void) +{ + v7_flush_dcache_all(); + + v7_outer_cache_flush_all(); +} + +/* + * Invalidates range in all levels of D-cache/unified cache used: + * Affects the range [start, stop - 1] + */ +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ + check_cache_range(start, stop); + + v7_dcache_maint_range(start, stop, ARMV7_DCACHE_INVAL_RANGE); + + v7_outer_cache_inval_range(start, stop); +} + +/* + * Flush range(clean & invalidate) from all levels of D-cache/unified + * cache used: + * Affects the range [start, stop - 1] + */ +void flush_dcache_range(unsigned long start, unsigned long stop) +{ + check_cache_range(start, stop); + + v7_dcache_maint_range(start, stop, ARMV7_DCACHE_CLEAN_INVAL_RANGE); + + v7_outer_cache_flush_range(start, stop); +} + +void arm_init_before_mmu(void) +{ + v7_outer_cache_enable(); + invalidate_dcache_all(); + v7_inval_tlb(); +} + +void mmu_page_table_flush(unsigned long start, unsigned long stop) +{ + flush_dcache_range(start, stop); + v7_inval_tlb(); +} +#else /* #ifndef CONFIG_SYS_DCACHE_OFF */ +void invalidate_dcache_all(void) +{ +} + +void flush_dcache_all(void) +{ +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void arm_init_before_mmu(void) +{ +} + +void mmu_page_table_flush(unsigned long start, unsigned long stop) +{ +} + +void arm_init_domains(void) +{ +} +#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ + +#ifndef CONFIG_SYS_ICACHE_OFF +/* Invalidate entire I-cache and branch predictor array */ +void invalidate_icache_all(void) +{ + /* + * Invalidate all instruction caches to PoU. + * Also flushes branch target cache. + */ + asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); + + /* Invalidate entire branch predictor array */ + asm volatile ("mcr p15, 0, %0, c7, c5, 6" : : "r" (0)); + + /* Full system DSB - make sure that the invalidation is complete */ + dsb(); + + /* ISB - make sure the instruction stream sees it */ + isb(); +} +#else +void invalidate_icache_all(void) +{ +} +#endif + +/* Stub implementations for outer cache operations */ +__weak void v7_outer_cache_enable(void) {} +__weak void v7_outer_cache_disable(void) {} +__weak void v7_outer_cache_flush_all(void) {} +__weak void v7_outer_cache_inval_all(void) {} +__weak void v7_outer_cache_flush_range(u32 start, u32 end) {} +__weak void v7_outer_cache_inval_range(u32 start, u32 end) {}
diff --git a/arch/arm/cpu/armv7/cache_v7_asm.S b/arch/arm/cpu/armv7/cache_v7_asm.S new file mode 100644 index 0000000..e38d72f --- /dev/null +++ b/arch/arm/cpu/armv7/cache_v7_asm.S
@@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include <config.h> +#include <linux/linkage.h> +#include <linux/sizes.h> +#include <asm/system.h> + +#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) +#define ARM(x...) +#define THUMB(x...) x +#else +#define ARM(x...) x +#define THUMB(x...) +#endif + +/* + * v7_flush_dcache_all() + * + * Flush the whole D-cache. + * + * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) + * + * Note: copied from arch/arm/mm/cache-v7.S of Linux 4.4 + */ +ENTRY(__v7_flush_dcache_all) + dmb @ ensure ordering with previous memory accesses + mrc p15, 1, r0, c0, c0, 1 @ read clidr + mov r3, r0, lsr #23 @ move LoC into position + ands r3, r3, #7 << 1 @ extract LoC*2 from clidr + beq finished @ if loc is 0, then no need to clean +start_flush_levels: + mov r10, #0 @ start clean at cache level 0 +flush_levels: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt skip @ skip if no cache, or just i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + isb @ isb to sych the new cssr&csidr + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + movw r4, #0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + clz r5, r4 @ find bit position of way size increment + movw r7, #0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +loop1: + mov r9, r7 @ create working copy of max index +loop2: + ARM( orr r11, r10, r4, lsl r5 ) @ factor way and cache number into r11 + THUMB( lsl r6, r4, r5 ) + THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 + ARM( orr r11, r11, r9, lsl r2 ) @ factor index number into r11 + THUMB( lsl r6, r9, r2 ) + THUMB( orr r11, r11, r6 ) @ factor index number into r11 + mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way + subs r9, r9, #1 @ decrement the index + bge loop2 + subs r4, r4, #1 @ decrement the way + bge loop1 +skip: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt flush_levels +finished: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + dsb st + isb + bx lr +ENDPROC(__v7_flush_dcache_all) + +ENTRY(v7_flush_dcache_all) + ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) + bl __v7_flush_dcache_all + ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) + bx lr +ENDPROC(v7_flush_dcache_all) + +/* + * v7_invalidate_dcache_all() + * + * Invalidate the whole D-cache. + * + * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) + * + * Note: copied from __v7_flush_dcache_all above with + * mcr p15, 0, r11, c7, c14, 2 + * Replaced with: + * mcr p15, 0, r11, c7, c6, 2 + */ +ENTRY(__v7_invalidate_dcache_all) + dmb @ ensure ordering with previous memory accesses + mrc p15, 1, r0, c0, c0, 1 @ read clidr + mov r3, r0, lsr #23 @ move LoC into position + ands r3, r3, #7 << 1 @ extract LoC*2 from clidr + beq inval_finished @ if loc is 0, then no need to clean + mov r10, #0 @ start clean at cache level 0 +inval_levels: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt inval_skip @ skip if no cache, or just i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + isb @ isb to sych the new cssr&csidr + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + movw r4, #0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + clz r5, r4 @ find bit position of way size increment + movw r7, #0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +inval_loop1: + mov r9, r7 @ create working copy of max index +inval_loop2: + ARM( orr r11, r10, r4, lsl r5 ) @ factor way and cache number into r11 + THUMB( lsl r6, r4, r5 ) + THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 + ARM( orr r11, r11, r9, lsl r2 ) @ factor index number into r11 + THUMB( lsl r6, r9, r2 ) + THUMB( orr r11, r11, r6 ) @ factor index number into r11 + mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way + subs r9, r9, #1 @ decrement the index + bge inval_loop2 + subs r4, r4, #1 @ decrement the way + bge inval_loop1 +inval_skip: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt inval_levels +inval_finished: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + dsb st + isb + bx lr +ENDPROC(__v7_invalidate_dcache_all) + +ENTRY(v7_invalidate_dcache_all) + ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) + bl __v7_invalidate_dcache_all + ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) + bx lr +ENDPROC(v7_invalidate_dcache_all)
diff --git a/arch/arm/cpu/armv7/config.mk b/arch/arm/cpu/armv7/config.mk new file mode 100644 index 0000000..68036d6 --- /dev/null +++ b/arch/arm/cpu/armv7/config.mk
@@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + +# On supported platforms we set the bit which causes us to trap on unaligned +# memory access. This is the opposite of what the compiler expects to be +# the default so we must pass in -mno-unaligned-access so that it is aware +# of our decision. +PF_NO_UNALIGNED := $(call cc-option, -mno-unaligned-access,) +PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED)
diff --git a/arch/arm/cpu/armv7/cp15.c b/arch/arm/cpu/armv7/cp15.c new file mode 100644 index 0000000..0ac4e7b --- /dev/null +++ b/arch/arm/cpu/armv7/cp15.c
@@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2015 Texas Insturments + */ + +/* + * CP15 specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> +#include <asm/cache.h> +#include <asm/armv7.h> +#include <linux/compiler.h> + +void __weak v7_arch_cp15_set_l2aux_ctrl(u32 l2actlr, u32 cpu_midr, + u32 cpu_rev_comb, u32 cpu_variant, + u32 cpu_rev) +{ + asm volatile ("mcr p15, 1, %0, c15, c0, 0\n\t" : : "r"(l2actlr)); +} + +void __weak v7_arch_cp15_set_acr(u32 acr, u32 cpu_midr, u32 cpu_rev_comb, + u32 cpu_variant, u32 cpu_rev) +{ + asm volatile ("mcr p15, 0, %0, c1, c0, 1\n\t" : : "r"(acr)); +}
diff --git a/arch/arm/cpu/armv7/cpu.c b/arch/arm/cpu/armv7/cpu.c new file mode 100644 index 0000000..44f2757 --- /dev/null +++ b/arch/arm/cpu/armv7/cpu.c
@@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2008 Texas Insturments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> +#include <asm/cache.h> +#include <asm/armv7.h> +#include <linux/compiler.h> + +void __weak cpu_cache_initialization(void){} + +int cleanup_before_linux_select(int flags) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ +#ifndef CONFIG_SPL_BUILD + disable_interrupts(); +#endif + + if (flags & CBL_DISABLE_CACHES) { + /* + * turn off D-cache + * dcache_disable() in turn flushes the d-cache and disables MMU + */ + dcache_disable(); + v7_outer_cache_disable(); + + /* + * After D-cache is flushed and before it is disabled there may + * be some new valid entries brought into the cache. We are + * sure that these lines are not dirty and will not affect our + * execution. (because unwinding the call-stack and setting a + * bit in CP15 SCTRL is all we did during this. We have not + * pushed anything on to the stack. Neither have we affected + * any static data) So just invalidate the entire d-cache again + * to avoid coherency problems for kernel + */ + invalidate_dcache_all(); + + icache_disable(); + invalidate_icache_all(); + } else { + /* + * Turn off I-cache and invalidate it + */ + icache_disable(); + invalidate_icache_all(); + + flush_dcache_all(); + invalidate_icache_all(); + icache_enable(); + } + + /* + * Some CPU need more cache attention before starting the kernel. + */ + cpu_cache_initialization(); + + return 0; +} + +int cleanup_before_linux(void) +{ + return cleanup_before_linux_select(CBL_ALL); +}
diff --git a/arch/arm/cpu/armv7/iproc-common/Makefile b/arch/arm/cpu/armv7/iproc-common/Makefile new file mode 100644 index 0000000..6f5c837 --- /dev/null +++ b/arch/arm/cpu/armv7/iproc-common/Makefile
@@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2014 Broadcom Corporation. + +obj-y += armpll.o +obj-y += hwinit-common.o +obj-y += timer.o
diff --git a/arch/arm/cpu/armv7/iproc-common/armpll.c b/arch/arm/cpu/armv7/iproc-common/armpll.c new file mode 100644 index 0000000..efa3d9e --- /dev/null +++ b/arch/arm/cpu/armv7/iproc-common/armpll.c
@@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Broadcom Corporation. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/iproc-common/armpll.h> +#include <asm/iproc-common/sysmap.h> + +#define NELEMS(x) (sizeof(x) / sizeof(x[0])) + +struct armpll_parameters { + unsigned int mode; + unsigned int ndiv_int; + unsigned int ndiv_frac; + unsigned int pdiv; + unsigned int freqid; +}; + +struct armpll_parameters armpll_clk_tab[] = { + { 25, 64, 1, 1, 0}, + { 100, 64, 1, 1, 2}, + { 400, 64, 1, 1, 6}, + { 448, 71, 713050, 1, 6}, + { 500, 80, 1, 1, 6}, + { 560, 89, 629145, 1, 6}, + { 600, 96, 1, 1, 6}, + { 800, 64, 1, 1, 7}, + { 896, 71, 713050, 1, 7}, + { 1000, 80, 1, 1, 7}, + { 1100, 88, 1, 1, 7}, + { 1120, 89, 629145, 1, 7}, + { 1200, 96, 1, 1, 7}, +}; + +uint32_t armpll_config(uint32_t clkmhz) +{ + uint32_t freqid; + uint32_t ndiv_frac; + uint32_t pll; + uint32_t status = 1; + uint32_t timeout_countdown; + int i; + + for (i = 0; i < NELEMS(armpll_clk_tab); i++) { + if (armpll_clk_tab[i].mode == clkmhz) { + status = 0; + break; + } + } + + if (status) { + printf("Error: Clock configuration not supported\n"); + goto armpll_config_done; + } + + /* Enable write access */ + writel(IPROC_REG_WRITE_ACCESS, IHOST_PROC_CLK_WR_ACCESS); + + if (clkmhz == 25) + freqid = 0; + else + freqid = 2; + + /* Bypass ARM clock and run on sysclk */ + writel(1 << IHOST_PROC_CLK_POLICY_FREQ__PRIV_ACCESS_MODE | + freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY3_FREQ_R | + freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY2_FREQ_R | + freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY1_FREQ_R | + freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY0_FREQ_R, + IHOST_PROC_CLK_POLICY_FREQ); + + writel(1 << IHOST_PROC_CLK_POLICY_CTL__GO | + 1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC, + IHOST_PROC_CLK_POLICY_CTL); + + /* Poll CCU until operation complete */ + timeout_countdown = 0x100000; + while (readl(IHOST_PROC_CLK_POLICY_CTL) & + (1 << IHOST_PROC_CLK_POLICY_CTL__GO)) { + timeout_countdown--; + if (timeout_countdown == 0) { + printf("CCU polling timedout\n"); + status = 1; + goto armpll_config_done; + } + } + + if (clkmhz == 25 || clkmhz == 100) { + status = 0; + goto armpll_config_done; + } + + /* Now it is safe to program the PLL */ + pll = readl(IHOST_PROC_CLK_PLLARMB); + pll &= ~((1 << IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_WIDTH) - 1); + ndiv_frac = + ((1 << IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_WIDTH) - 1) & + (armpll_clk_tab[i].ndiv_frac << + IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_R); + pll |= ndiv_frac; + writel(pll, IHOST_PROC_CLK_PLLARMB); + + writel(1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK | + armpll_clk_tab[i].ndiv_int << + IHOST_PROC_CLK_PLLARMA__PLLARM_NDIV_INT_R | + armpll_clk_tab[i].pdiv << + IHOST_PROC_CLK_PLLARMA__PLLARM_PDIV_R | + 1 << IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_RESETB, + IHOST_PROC_CLK_PLLARMA); + + /* Poll ARM PLL Lock until operation complete */ + timeout_countdown = 0x100000; + while (readl(IHOST_PROC_CLK_PLLARMA) & + (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK)) { + timeout_countdown--; + if (timeout_countdown == 0) { + printf("ARM PLL lock failed\n"); + status = 1; + goto armpll_config_done; + } + } + + pll = readl(IHOST_PROC_CLK_PLLARMA); + pll |= (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_POST_RESETB); + writel(pll, IHOST_PROC_CLK_PLLARMA); + + /* Set the policy */ + writel(1 << IHOST_PROC_CLK_POLICY_FREQ__PRIV_ACCESS_MODE | + armpll_clk_tab[i].freqid << + IHOST_PROC_CLK_POLICY_FREQ__POLICY3_FREQ_R | + armpll_clk_tab[i].freqid << + IHOST_PROC_CLK_POLICY_FREQ__POLICY2_FREQ_R | + armpll_clk_tab[i].freqid << + IHOST_PROC_CLK_POLICY_FREQ__POLICY1_FREQ_R | + armpll_clk_tab[i+4].freqid << + IHOST_PROC_CLK_POLICY_FREQ__POLICY0_FREQ_R, + IHOST_PROC_CLK_POLICY_FREQ); + + writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_CORE0_CLKGATE); + writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_CORE1_CLKGATE); + writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_ARM_SWITCH_CLKGATE); + writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_ARM_PERIPH_CLKGATE); + writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_APB0_CLKGATE); + + writel(1 << IHOST_PROC_CLK_POLICY_CTL__GO | + 1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC, + IHOST_PROC_CLK_POLICY_CTL); + + /* Poll CCU until operation complete */ + timeout_countdown = 0x100000; + while (readl(IHOST_PROC_CLK_POLICY_CTL) & + (1 << IHOST_PROC_CLK_POLICY_CTL__GO)) { + timeout_countdown--; + if (timeout_countdown == 0) { + printf("CCU polling failed\n"); + status = 1; + goto armpll_config_done; + } + } + + status = 0; +armpll_config_done: + /* Disable access to PLL registers */ + writel(0, IHOST_PROC_CLK_WR_ACCESS); + + return status; +}
diff --git a/arch/arm/cpu/armv7/iproc-common/hwinit-common.c b/arch/arm/cpu/armv7/iproc-common/hwinit-common.c new file mode 100644 index 0000000..8bf06a3 --- /dev/null +++ b/arch/arm/cpu/armv7/iproc-common/hwinit-common.c
@@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Broadcom Corporation. + */ + +#include <common.h> + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif
diff --git a/arch/arm/cpu/armv7/iproc-common/timer.c b/arch/arm/cpu/armv7/iproc-common/timer.c new file mode 100644 index 0000000..aaa767d --- /dev/null +++ b/arch/arm/cpu/armv7/iproc-common/timer.c
@@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Broadcom Corporation. + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <asm/iproc-common/timer.h> +#include <asm/iproc-common/sysmap.h> + +static inline uint64_t timer_global_read(void) +{ + uint64_t cur_tick; + uint32_t count_h; + uint32_t count_l; + + do { + count_h = readl(IPROC_PERIPH_GLB_TIM_REG_BASE + + TIMER_GLB_HI_OFFSET); + count_l = readl(IPROC_PERIPH_GLB_TIM_REG_BASE + + TIMER_GLB_LOW_OFFSET); + cur_tick = readl(IPROC_PERIPH_GLB_TIM_REG_BASE + + TIMER_GLB_HI_OFFSET); + } while (cur_tick != count_h); + + return (cur_tick << 32) + count_l; +} + +void timer_global_init(void) +{ + writel(0, IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_CTRL_OFFSET); + writel(0, IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_LOW_OFFSET); + writel(0, IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_HI_OFFSET); + writel(TIMER_GLB_TIM_CTRL_TIM_EN, + IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_CTRL_OFFSET); +} + +int timer_init(void) +{ + timer_global_init(); + return 0; +} + +unsigned long get_timer(unsigned long base) +{ + uint64_t count; + uint64_t ret; + uint64_t tim_clk; + uint64_t periph_clk; + + count = timer_global_read(); + + /* default arm clk is 1GHz, periph_clk=arm_clk/2, tick per msec */ + periph_clk = 500000; + tim_clk = lldiv(periph_clk, + (((readl(IPROC_PERIPH_GLB_TIM_REG_BASE + + TIMER_GLB_CTRL_OFFSET) & + TIMER_GLB_TIM_CTRL_PRESC_MASK) >> 8) + 1)); + + ret = lldiv(count, (uint32_t)tim_clk); + + /* returns msec */ + return ret - base; +} + +void __udelay(unsigned long usec) +{ + uint64_t cur_tick, end_tick; + uint64_t tim_clk; + uint64_t periph_clk; + + /* default arm clk is 1GHz, periph_clk=arm_clk/2, tick per usec */ + periph_clk = 500; + + tim_clk = lldiv(periph_clk, + (((readl(IPROC_PERIPH_GLB_TIM_REG_BASE + + TIMER_GLB_CTRL_OFFSET) & + TIMER_GLB_TIM_CTRL_PRESC_MASK) >> 8) + 1)); + + cur_tick = timer_global_read(); + + end_tick = tim_clk; + end_tick *= usec; + end_tick += cur_tick; + + do { + cur_tick = timer_global_read(); + + } while (cur_tick < end_tick); +} + +void timer_systick_init(uint32_t tick_ms) +{ + /* Disable timer and clear interrupt status*/ + writel(0, IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_CTRL_OFFSET); + writel(TIMER_PVT_TIM_INT_STATUS_SET, + IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_STATUS_OFFSET); + writel((PLL_AXI_CLK/1000) * tick_ms, + IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_LOAD_OFFSET); + writel(TIMER_PVT_TIM_CTRL_INT_EN | + TIMER_PVT_TIM_CTRL_AUTO_RELD | + TIMER_PVT_TIM_CTRL_TIM_EN, + IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_CTRL_OFFSET); +} + +void timer_systick_isr(void *data) +{ + writel(TIMER_PVT_TIM_INT_STATUS_SET, + IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_STATUS_OFFSET); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value in msec. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This is used in conjuction with get_ticks, which returns msec as ticks. + * Here we just return ticks/sec = msec/sec = 1000 + */ +ulong get_tbclk(void) +{ + return 1000; +}
diff --git a/arch/arm/cpu/armv7/kona-common/Makefile b/arch/arm/cpu/armv7/kona-common/Makefile new file mode 100644 index 0000000..56de3d1 --- /dev/null +++ b/arch/arm/cpu/armv7/kona-common/Makefile
@@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2013 Broadcom Corporation. + +obj-y += s_init.o +obj-y += hwinit-common.o +obj-y += clk-stubs.o +obj-${CONFIG_KONA_RESET_S} += reset.o
diff --git a/arch/arm/cpu/armv7/kona-common/clk-stubs.c b/arch/arm/cpu/armv7/kona-common/clk-stubs.c new file mode 100644 index 0000000..2dfa3f7 --- /dev/null +++ b/arch/arm/cpu/armv7/kona-common/clk-stubs.c
@@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Broadcom Corporation. + */ + +#include <common.h> + +/* + * These weak functions are available to kona architectures that don't + * require clock enables from the driver code. + */ +int __weak clk_sdio_enable(void *base, u32 rate, u32 *actual_ratep) +{ + return 0; +} + +int __weak clk_bsc_enable(void *base, u32 rate, u32 *actual_ratep) +{ + return 0; +} + +int __weak clk_usb_otg_enable(void *base) +{ + return 0; +}
diff --git a/arch/arm/cpu/armv7/kona-common/hwinit-common.c b/arch/arm/cpu/armv7/kona-common/hwinit-common.c new file mode 100644 index 0000000..8783893 --- /dev/null +++ b/arch/arm/cpu/armv7/kona-common/hwinit-common.c
@@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Broadcom Corporation. + */ + +#include <common.h> +#include <linux/sizes.h> + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif
diff --git a/arch/arm/cpu/armv7/kona-common/reset.S b/arch/arm/cpu/armv7/kona-common/reset.S new file mode 100644 index 0000000..eea835b --- /dev/null +++ b/arch/arm/cpu/armv7/kona-common/reset.S
@@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2013 Broadcom Corporation. + */ + +.globl reset_cpu +reset_cpu: + ldr r1, =0x35001f00 + ldr r2, [r1] + ldr r4, =0x80000000 + and r4, r2, r4 + ldr r3, =0xA5A500 + orr r4, r4, r3 + orr r4, r4, #0x1 + + str r4, [r1] + + ldr r1, =0x35001f04 + ldr r2, [r1] + ldr r4, =0x80000000 + and r4, r2, r4 + str r4, [r1] + +_loop_forever: + b _loop_forever
diff --git a/arch/arm/cpu/armv7/kona-common/s_init.c b/arch/arm/cpu/armv7/kona-common/s_init.c new file mode 100644 index 0000000..778b917 --- /dev/null +++ b/arch/arm/cpu/armv7/kona-common/s_init.c
@@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Broadcom Corporation. + */ + +/* + * Early system init. Currently empty. + */ +void s_init(void) +{ +}
diff --git a/arch/arm/cpu/armv7/lowlevel_init.S b/arch/arm/cpu/armv7/lowlevel_init.S new file mode 100644 index 0000000..ba4b374 --- /dev/null +++ b/arch/arm/cpu/armv7/lowlevel_init.S
@@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * A lowlevel_init function that sets up the stack to call a C function to + * perform further init. + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Author : + * Aneesh V <aneesh@ti.com> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> + +.pushsection .text.s_init, "ax" +WEAK(s_init) + bx lr +ENDPROC(s_init) +.popsection + +.pushsection .text.lowlevel_init, "ax" +WEAK(lowlevel_init) + /* + * Setup a temporary stack. Global data is not available yet. + */ +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) + ldr sp, =CONFIG_SPL_STACK +#else + ldr sp, =CONFIG_SYS_INIT_SP_ADDR +#endif + bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ +#ifdef CONFIG_SPL_DM + mov r9, #0 +#else + /* + * Set up global data for boards that still need it. This will be + * removed soon. + */ +#ifdef CONFIG_SPL_BUILD + ldr r9, =gdata +#else + sub sp, sp, #GD_SIZE + bic sp, sp, #7 + mov r9, sp +#endif +#endif + /* + * Save the old lr(passed in ip) and the current lr to stack + */ + push {ip, lr} + + /* + * Call the very early init function. This should do only the + * absolute bare minimum to get started. It should not: + * + * - set up DRAM + * - use global_data + * - clear BSS + * - try to start a console + * + * For boards with SPL this should be empty since SPL can do all of + * this init in the SPL board_init_f() function which is called + * immediately after this. + */ + bl s_init + pop {ip, pc} +ENDPROC(lowlevel_init) +.popsection
diff --git a/arch/arm/cpu/armv7/ls102xa/Kconfig b/arch/arm/cpu/armv7/ls102xa/Kconfig new file mode 100644 index 0000000..4ffde9a --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/Kconfig
@@ -0,0 +1,110 @@ +config ARCH_LS1021A + bool + select SYS_FSL_DDR_BE if SYS_FSL_DDR + select SYS_FSL_DDR_VER_50 if SYS_FSL_DDR + select SYS_FSL_ERRATUM_A008378 + select SYS_FSL_ERRATUM_A008407 + select SYS_FSL_ERRATUM_A008997 + select SYS_FSL_ERRATUM_A009007 + select SYS_FSL_ERRATUM_A009008 + select SYS_FSL_ERRATUM_A009663 + select SYS_FSL_ERRATUM_A009798 + select SYS_FSL_ERRATUM_A009942 + select SYS_FSL_ERRATUM_A010315 + select SYS_FSL_HAS_CCI400 + select SYS_FSL_HAS_DDR3 if SYS_FSL_DDR + select SYS_FSL_HAS_DDR4 if SYS_FSL_DDR + select SYS_FSL_HAS_SEC + select SYS_FSL_SEC_COMPAT_5 + select SYS_FSL_SEC_LE + select SYS_FSL_SRDS_1 + select SYS_HAS_SERDES + imply CMD_PCI + imply SCSI + imply SCSI_AHCI + +menu "LS102xA architecture" + depends on ARCH_LS1021A + +config FSL_PCIE_COMPAT + string "PCIe compatible of Kernel DT" + depends on PCIE_LAYERSCAPE + default "fsl,ls1021a-pcie" if ARCH_LS1021A + help + This compatible is used to find pci controller node in Kernel DT + to complete fixup. + +config LS1_DEEP_SLEEP + bool "Deep sleep" + depends on ARCH_LS1021A + +config MAX_CPUS + int "Maximum number of CPUs permitted for LS102xA" + depends on ARCH_LS1021A + default 2 + help + Set this number to the maximum number of possible CPUs in the SoC. + SoCs may have multiple clusters with each cluster may have multiple + ports. If some ports are reserved but higher ports are used for + cores, count the reserved ports. This will allocate enough memory + in spin table to properly handle all cores. + +config SECURE_BOOT + bool "Secure Boot" + help + Enable Freescale Secure Boot feature. Normally selected + by defconfig. If unsure, do not change. + +config SYS_CCI400_OFFSET + hex "Offset for CCI400 base" + depends on SYS_FSL_HAS_CCI400 + default 0x180000 + help + Offset for CCI400 base. + CCI400 base addr = CCSRBAR + CCI400_OFFSET + +config SYS_FSL_ERRATUM_A008997 + bool + help + Workaround for USB PHY erratum A008997 + +config SYS_FSL_ERRATUM_A009007 + bool + help + Workaround for USB PHY erratum A009007 + +config SYS_FSL_ERRATUM_A009008 + bool + help + Workaround for USB PHY erratum A009008 + +config SYS_FSL_ERRATUM_A009798 + bool + help + Workaround for USB PHY erratum A009798 + +config SYS_FSL_ERRATUM_A010315 + bool "Workaround for PCIe erratum A010315" + +config SYS_FSL_HAS_CCI400 + bool + +config SYS_FSL_SRDS_1 + bool + +config SYS_FSL_SRDS_2 + bool + +config SYS_HAS_SERDES + bool + +config SYS_FSL_IFC_BANK_COUNT + int "Maximum banks of Integrated flash controller" + depends on ARCH_LS1021A + default 8 + +config SYS_FSL_ERRATUM_A008407 + bool + +endmenu +
diff --git a/arch/arm/cpu/armv7/ls102xa/Makefile b/arch/arm/cpu/armv7/ls102xa/Makefile new file mode 100644 index 0000000..0c1596f --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/Makefile
@@ -0,0 +1,19 @@ +# +# Copyright 2014 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += cpu.o +obj-y += clock.o +obj-y += timer.o +obj-y += fsl_epu.o +obj-y += soc.o + +obj-$(CONFIG_OF_LIBFDT) += fdt.o +obj-$(CONFIG_SYS_HAS_SERDES) += fsl_ls1_serdes.o ls102xa_serdes.o +obj-$(CONFIG_SPL) += spl.o + +ifdef CONFIG_ARMV7_PSCI +obj-y += psci.o ls102xa_psci.o +endif
diff --git a/arch/arm/cpu/armv7/ls102xa/clock.c b/arch/arm/cpu/armv7/ls102xa/clock.c new file mode 100644 index 0000000..30c7b37 --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/clock.c
@@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/immap_ls102xa.h> +#include <asm/arch/clock.h> +#include <fsl_ifc.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS +#define CONFIG_SYS_FSL_NUM_CC_PLLS 2 +#endif + +void get_sys_info(struct sys_info *sys_info) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_LS1_CLK_ADDR); + unsigned int cpu; + const u8 core_cplx_pll[6] = { + [0] = 0, /* CC1 PPL / 1 */ + [1] = 0, /* CC1 PPL / 2 */ + [4] = 1, /* CC2 PPL / 1 */ + [5] = 1, /* CC2 PPL / 2 */ + }; + + const u8 core_cplx_pll_div[6] = { + [0] = 1, /* CC1 PPL / 1 */ + [1] = 2, /* CC1 PPL / 2 */ + [4] = 1, /* CC2 PPL / 1 */ + [5] = 2, /* CC2 PPL / 2 */ + }; + + uint i; + uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS]; + uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS]; + unsigned long sysclk = CONFIG_SYS_CLK_FREQ; + + sys_info->freq_systembus = sysclk; +#ifdef CONFIG_DDR_CLK_FREQ + sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ; +#else + sys_info->freq_ddrbus = sysclk; +#endif + + sys_info->freq_systembus *= (in_be32(&gur->rcwsr[0]) >> + RCWSR0_SYS_PLL_RAT_SHIFT) & RCWSR0_SYS_PLL_RAT_MASK; + sys_info->freq_ddrbus *= (in_be32(&gur->rcwsr[0]) >> + RCWSR0_MEM_PLL_RAT_SHIFT) & RCWSR0_MEM_PLL_RAT_MASK; + + for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) { + ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0x3f; + if (ratio[i] > 4) + freq_c_pll[i] = sysclk * ratio[i]; + else + freq_c_pll[i] = sys_info->freq_systembus * ratio[i]; + } + + for (cpu = 0; cpu < CONFIG_MAX_CPUS; cpu++) { + u32 c_pll_sel = (in_be32(&clk->clkcsr[cpu].clkcncsr) >> 27) + & 0xf; + u32 cplx_pll = core_cplx_pll[c_pll_sel]; + + sys_info->freq_processor[cpu] = + freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel]; + } + +#if defined(CONFIG_FSL_IFC) + sys_info->freq_localbus = sys_info->freq_systembus; +#endif +} + +int get_clocks(void) +{ + struct sys_info sys_info; + + get_sys_info(&sys_info); + gd->cpu_clk = sys_info.freq_processor[0]; + gd->bus_clk = sys_info.freq_systembus; + gd->mem_clk = sys_info.freq_ddrbus * 2; + +#if defined(CONFIG_FSL_ESDHC) + gd->arch.sdhc_clk = gd->bus_clk; +#endif + + return 0; +} + +ulong get_bus_freq(ulong dummy) +{ + return gd->bus_clk; +} + +ulong get_ddr_freq(ulong dummy) +{ + return gd->mem_clk; +} + +int get_serial_clock(void) +{ + return gd->bus_clk / 2; +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_I2C_CLK: + return get_bus_freq(0) / 2; + case MXC_ESDHC_CLK: + return get_bus_freq(0); + case MXC_DSPI_CLK: + return get_bus_freq(0) / 2; + case MXC_UART_CLK: + return get_bus_freq(0) / 2; + default: + printf("Unsupported clock\n"); + } + return 0; +}
diff --git a/arch/arm/cpu/armv7/ls102xa/cpu.c b/arch/arm/cpu/armv7/ls102xa/cpu.c new file mode 100644 index 0000000..7c4018e --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/cpu.c
@@ -0,0 +1,391 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/io.h> +#include <asm/arch/immap_ls102xa.h> +#include <asm/cache.h> +#include <asm/system.h> +#include <tsec.h> +#include <netdev.h> +#include <fsl_esdhc.h> +#include <config.h> +#include <fsl_wdog.h> + +#include "fsl_epu.h" + +#define DCSR_RCPM2_BLOCK_OFFSET 0x223000 +#define DCSR_RCPM2_CPMFSMCR0 0x400 +#define DCSR_RCPM2_CPMFSMSR0 0x404 +#define DCSR_RCPM2_CPMFSMCR1 0x414 +#define DCSR_RCPM2_CPMFSMSR1 0x418 +#define CPMFSMSR_FSM_STATE_MASK 0x7f + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_DCACHE_OFF + +/* + * Bit[1] of the descriptor indicates the descriptor type, + * and bit[0] indicates whether the descriptor is valid. + */ +#define PMD_TYPE_TABLE 0x3 +#define PMD_TYPE_SECT 0x1 + +/* AttrIndx[2:0] */ +#define PMD_ATTRINDX(t) ((t) << 2) + +/* Section */ +#define PMD_SECT_AF (1 << 10) + +#define BLOCK_SIZE_L1 (1UL << 30) +#define BLOCK_SIZE_L2 (1UL << 21) + +/* TTBCR flags */ +#define TTBCR_EAE (1 << 31) +#define TTBCR_T0SZ(x) ((x) << 0) +#define TTBCR_T1SZ(x) ((x) << 16) +#define TTBCR_USING_TTBR0 (TTBCR_T0SZ(0) | TTBCR_T1SZ(0)) +#define TTBCR_IRGN0_NC (0 << 8) +#define TTBCR_IRGN0_WBWA (1 << 8) +#define TTBCR_IRGN0_WT (2 << 8) +#define TTBCR_IRGN0_WBNWA (3 << 8) +#define TTBCR_IRGN0_MASK (3 << 8) +#define TTBCR_ORGN0_NC (0 << 10) +#define TTBCR_ORGN0_WBWA (1 << 10) +#define TTBCR_ORGN0_WT (2 << 10) +#define TTBCR_ORGN0_WBNWA (3 << 10) +#define TTBCR_ORGN0_MASK (3 << 10) +#define TTBCR_SHARED_NON (0 << 12) +#define TTBCR_SHARED_OUTER (2 << 12) +#define TTBCR_SHARED_INNER (3 << 12) +#define TTBCR_EPD0 (0 << 7) +#define TTBCR (TTBCR_SHARED_NON | \ + TTBCR_ORGN0_NC | \ + TTBCR_IRGN0_NC | \ + TTBCR_USING_TTBR0 | \ + TTBCR_EAE) + +/* + * Memory region attributes for LPAE (defined in pgtable): + * + * n = AttrIndx[2:0] + * + * n MAIR + * UNCACHED 000 00000000 + * BUFFERABLE 001 01000100 + * DEV_WC 001 01000100 + * WRITETHROUGH 010 10101010 + * WRITEBACK 011 11101110 + * DEV_CACHED 011 11101110 + * DEV_SHARED 100 00000100 + * DEV_NONSHARED 100 00000100 + * unused 101 + * unused 110 + * WRITEALLOC 111 11111111 + */ +#define MT_MAIR0 0xeeaa4400 +#define MT_MAIR1 0xff000004 +#define MT_STRONLY_ORDER 0 +#define MT_NORMAL_NC 1 +#define MT_DEVICE_MEM 4 +#define MT_NORMAL 7 + +/* The phy_addr must be aligned to 4KB */ +static inline void set_pgtable(u32 *page_table, u32 index, u32 phy_addr) +{ + u32 value = phy_addr | PMD_TYPE_TABLE; + + page_table[2 * index] = value; + page_table[2 * index + 1] = 0; +} + +/* The phy_addr must be aligned to 4KB */ +static inline void set_pgsection(u32 *page_table, u32 index, u64 phy_addr, + u32 memory_type) +{ + u64 value; + + value = phy_addr | PMD_TYPE_SECT | PMD_SECT_AF; + value |= PMD_ATTRINDX(memory_type); + page_table[2 * index] = value & 0xFFFFFFFF; + page_table[2 * index + 1] = (value >> 32) & 0xFFFFFFFF; +} + +/* + * Start MMU after DDR is available, we create MMU table in DRAM. + * The base address of TTLB is gd->arch.tlb_addr. We use two + * levels of translation tables here to cover 40-bit address space. + * + * The TTLBs are located at PHY 2G~4G. + * + * VA mapping: + * + * ------- <---- 0GB + * | | + * | | + * |-------| <---- 0x24000000 + * |///////| ===> 192MB VA map for PCIe1 with offset 0x40_0000_0000 + * |-------| <---- 0x300000000 + * | | + * |-------| <---- 0x34000000 + * |///////| ===> 192MB VA map for PCIe2 with offset 0x48_0000_0000 + * |-------| <---- 0x40000000 + * | | + * |-------| <---- 0x80000000 DDR0 space start + * |\\\\\\\| + *.|\\\\\\\| ===> 2GB VA map for 2GB DDR0 Memory space + * |\\\\\\\| + * ------- <---- 4GB DDR0 space end + */ +static void mmu_setup(void) +{ + u32 *level0_table = (u32 *)gd->arch.tlb_addr; + u32 *level1_table = (u32 *)(gd->arch.tlb_addr + 0x1000); + u64 va_start = 0; + u32 reg; + int i; + + /* Level 0 Table 2-3 are used to map DDR */ + set_pgsection(level0_table, 3, 3 * BLOCK_SIZE_L1, MT_NORMAL); + set_pgsection(level0_table, 2, 2 * BLOCK_SIZE_L1, MT_NORMAL); + /* Level 0 Table 1 is used to map device */ + set_pgsection(level0_table, 1, 1 * BLOCK_SIZE_L1, MT_DEVICE_MEM); + /* Level 0 Table 0 is used to map device including PCIe MEM */ + set_pgtable(level0_table, 0, (u32)level1_table); + + /* Level 1 has 512 entries */ + for (i = 0; i < 512; i++) { + /* Mapping for PCIe 1 */ + if (va_start >= CONFIG_SYS_PCIE1_VIRT_ADDR && + va_start < (CONFIG_SYS_PCIE1_VIRT_ADDR + + CONFIG_SYS_PCIE_MMAP_SIZE)) + set_pgsection(level1_table, i, + CONFIG_SYS_PCIE1_PHYS_BASE + va_start, + MT_DEVICE_MEM); + /* Mapping for PCIe 2 */ + else if (va_start >= CONFIG_SYS_PCIE2_VIRT_ADDR && + va_start < (CONFIG_SYS_PCIE2_VIRT_ADDR + + CONFIG_SYS_PCIE_MMAP_SIZE)) + set_pgsection(level1_table, i, + CONFIG_SYS_PCIE2_PHYS_BASE + va_start, + MT_DEVICE_MEM); + else + set_pgsection(level1_table, i, + va_start, + MT_DEVICE_MEM); + va_start += BLOCK_SIZE_L2; + } + + asm volatile("dsb sy;isb"); + asm volatile("mcr p15, 0, %0, c2, c0, 2" /* Write RT to TTBCR */ + : : "r" (TTBCR) : "memory"); + asm volatile("mcrr p15, 0, %0, %1, c2" /* TTBR 0 */ + : : "r" ((u32)level0_table), "r" (0) : "memory"); + asm volatile("mcr p15, 0, %0, c10, c2, 0" /* write MAIR 0 */ + : : "r" (MT_MAIR0) : "memory"); + asm volatile("mcr p15, 0, %0, c10, c2, 1" /* write MAIR 1 */ + : : "r" (MT_MAIR1) : "memory"); + + /* Set the access control to all-supervisor */ + asm volatile("mcr p15, 0, %0, c3, c0, 0" + : : "r" (~0)); + + /* Enable the mmu */ + reg = get_cr(); + set_cr(reg | CR_M); +} + +/* + * This function is called from lib/board.c. It recreates MMU + * table in main memory. MMU and i/d-cache are enabled here. + */ +void enable_caches(void) +{ + /* Invalidate all TLB */ + mmu_page_table_flush(gd->arch.tlb_addr, + gd->arch.tlb_addr + gd->arch.tlb_size); + /* Set up and enable mmu */ + mmu_setup(); + + /* Invalidate & Enable d-cache */ + invalidate_dcache_all(); + set_cr(get_cr() | CR_C); +} +#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ + + +uint get_svr(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + + return in_be32(&gur->svr); +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + char buf1[32], buf2[32]; + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + unsigned int svr, major, minor, ver, i; + + svr = in_be32(&gur->svr); + major = SVR_MAJ(svr); + minor = SVR_MIN(svr); + + puts("CPU: Freescale LayerScape "); + + ver = SVR_SOC_VER(svr); + switch (ver) { + case SOC_VER_SLS1020: + puts("SLS1020"); + break; + case SOC_VER_LS1020: + puts("LS1020"); + break; + case SOC_VER_LS1021: + puts("LS1021"); + break; + case SOC_VER_LS1022: + puts("LS1022"); + break; + default: + puts("Unknown"); + break; + } + + if (IS_E_PROCESSOR(svr) && (ver != SOC_VER_SLS1020)) + puts("E"); + + printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr); + + puts("Clock Configuration:"); + + printf("\n CPU0(ARMV7):%-4s MHz, ", strmhz(buf1, gd->cpu_clk)); + printf("\n Bus:%-4s MHz, ", strmhz(buf1, gd->bus_clk)); + printf("DDR:%-4s MHz (%s MT/s data rate), ", + strmhz(buf1, gd->mem_clk/2), strmhz(buf2, gd->mem_clk)); + puts("\n"); + + /* Display the RCW, so that no one gets confused as to what RCW + * we're actually using for this boot. + */ + puts("Reset Configuration Word (RCW):"); + for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) { + u32 rcw = in_be32(&gur->rcwsr[i]); + + if ((i % 4) == 0) + printf("\n %08x:", i * 4); + printf(" %08x", rcw); + } + puts("\n"); + + return 0; +} +#endif + +#ifdef CONFIG_FSL_ESDHC +int cpu_mmc_init(bd_t *bis) +{ + return fsl_esdhc_mmc_init(bis); +} +#endif + +int cpu_eth_init(bd_t *bis) +{ +#ifdef CONFIG_TSEC_ENET + tsec_standard_init(bis); +#endif + + return 0; +} + +int arch_cpu_init(void) +{ + void *epu_base = (void *)(CONFIG_SYS_DCSRBAR + EPU_BLOCK_OFFSET); + void *rcpm2_base = + (void *)(CONFIG_SYS_DCSRBAR + DCSR_RCPM2_BLOCK_OFFSET); + struct ccsr_scfg *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + u32 state; + + /* + * The RCPM FSM state may not be reset after power-on. + * So, reset them. + */ + state = in_be32(rcpm2_base + DCSR_RCPM2_CPMFSMSR0) & + CPMFSMSR_FSM_STATE_MASK; + if (state != 0) { + out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR0, 0x80); + out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR0, 0x0); + } + + state = in_be32(rcpm2_base + DCSR_RCPM2_CPMFSMSR1) & + CPMFSMSR_FSM_STATE_MASK; + if (state != 0) { + out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR1, 0x80); + out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR1, 0x0); + } + + /* + * After wakeup from deep sleep, Clear EPU registers + * as early as possible to prevent from possible issue. + * It's also safe to clear at normal boot. + */ + fsl_epu_clean(epu_base); + + setbits_be32(&scfg->snpcnfgcr, SCFG_SNPCNFGCR_SEC_RD_WR); + + return 0; +} + +#ifdef CONFIG_ARMV7_NONSEC +/* Set the address at which the secondary core starts from.*/ +void smp_set_core_boot_addr(unsigned long addr, int corenr) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + + out_be32(&gur->scratchrw[0], addr); +} + +/* Release the secondary core from holdoff state and kick it */ +void smp_kick_all_cpus(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + + out_be32(&gur->brrl, 0x2); + + /* + * LS1 STANDBYWFE is not captured outside the ARM module in the soc. + * So add a delay to wait bootrom execute WFE. + */ + udelay(1); + + asm volatile("sev"); +} +#endif + +void reset_cpu(ulong addr) +{ + struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; + + clrbits_be16(&wdog->wcr, WCR_SRS); + + while (1) { + /* + * Let the watchdog trigger + */ + } +} + +void arch_preboot_os(void) +{ + unsigned long ctrl; + + /* Disable PL1 Physical Timer */ + asm("mrc p15, 0, %0, c14, c2, 1" : "=r" (ctrl)); + ctrl &= ~ARCH_TIMER_CTRL_ENABLE; + asm("mcr p15, 0, %0, c14, c2, 1" : : "r" (ctrl)); +}
diff --git a/arch/arm/cpu/armv7/ls102xa/fdt.c b/arch/arm/cpu/armv7/ls102xa/fdt.c new file mode 100644 index 0000000..8bf9c42 --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/fdt.c
@@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <linux/libfdt.h> +#include <fdt_support.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/arch/clock.h> +#include <linux/ctype.h> +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> +#endif +#include <tsec.h> +#include <asm/arch/immap_ls102xa.h> +#include <fsl_sec.h> + +DECLARE_GLOBAL_DATA_PTR; + +void ft_fixup_enet_phy_connect_type(void *fdt) +{ + struct eth_device *dev; + struct tsec_private *priv; + const char *enet_path, *phy_path; + char enet[16]; + char phy[16]; + int phy_node; + int i = 0; + uint32_t ph; + char *name[3] = { "eTSEC1", "eTSEC2", "eTSEC3" }; + + for (; i < ARRAY_SIZE(name); i++) { + dev = eth_get_dev_by_name(name[i]); + if (dev) { + sprintf(enet, "ethernet%d", i); + sprintf(phy, "enet%d_rgmii_phy", i); + } else { + continue; + } + + priv = dev->priv; + if (priv->flags & TSEC_SGMII) + continue; + + enet_path = fdt_get_alias(fdt, enet); + if (!enet_path) + continue; + + phy_path = fdt_get_alias(fdt, phy); + if (!phy_path) + continue; + + phy_node = fdt_path_offset(fdt, phy_path); + if (phy_node < 0) + continue; + + ph = fdt_create_phandle(fdt, phy_node); + if (ph) + do_fixup_by_path_u32(fdt, enet_path, + "phy-handle", ph, 1); + + do_fixup_by_path(fdt, enet_path, "phy-connection-type", + phy_string_for_interface( + PHY_INTERFACE_MODE_RGMII_ID), + strlen(phy_string_for_interface( + PHY_INTERFACE_MODE_RGMII_ID)) + 1, + 1); + } +} + +void ft_cpu_setup(void *blob, bd_t *bd) +{ + int off; + int val; + const char *sysclk_path; + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + unsigned int svr; + svr = in_be32(&gur->svr); + + unsigned long busclk = get_bus_freq(0); + + /* delete crypto node if not on an E-processor */ + if (!IS_E_PROCESSOR(svr)) + fdt_fixup_crypto_node(blob, 0); +#if CONFIG_SYS_FSL_SEC_COMPAT >= 4 + else { + ccsr_sec_t __iomem *sec; + + sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR; + fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms)); + } +#endif + + off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); + while (off != -FDT_ERR_NOTFOUND) { + val = gd->cpu_clk; + fdt_setprop(blob, off, "clock-frequency", &val, 4); + off = fdt_node_offset_by_prop_value(blob, off, + "device_type", "cpu", 4); + } + + do_fixup_by_prop_u32(blob, "device_type", "soc", + 4, "bus-frequency", busclk, 1); + + ft_fixup_enet_phy_connect_type(blob); + +#ifdef CONFIG_SYS_NS16550 + do_fixup_by_compat_u32(blob, "fsl,16550-FIFO64", + "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); +#endif + + sysclk_path = fdt_get_alias(blob, "sysclk"); + if (sysclk_path) + do_fixup_by_path_u32(blob, sysclk_path, "clock-frequency", + CONFIG_SYS_CLK_FREQ, 1); + do_fixup_by_compat_u32(blob, "fsl,qoriq-sysclk-2.0", + "clock-frequency", CONFIG_SYS_CLK_FREQ, 1); + +#if defined(CONFIG_DEEP_SLEEP) && defined(CONFIG_SD_BOOT) +#define UBOOT_HEAD_LEN 0x1000 + /* + * Reserved memory in SD boot deep sleep case. + * Second stage uboot binary and malloc space should be reserved. + * If the memory they occupied has not been reserved, then this + * space would be used by kernel and overwritten in uboot when + * deep sleep resume, which cause deep sleep failed. + * Since second uboot binary has a head, that space need to be + * reserved either(assuming its size is less than 0x1000). + */ + off = fdt_add_mem_rsv(blob, CONFIG_SYS_TEXT_BASE - UBOOT_HEAD_LEN, + CONFIG_SYS_MONITOR_LEN + CONFIG_SYS_SPL_MALLOC_SIZE + + UBOOT_HEAD_LEN); + if (off < 0) + printf("Failed to reserve memory for SD boot deep sleep: %s\n", + fdt_strerror(off)); +#endif + +#if defined(CONFIG_FSL_ESDHC) + fdt_fixup_esdhc(blob, bd); +#endif + + /* + * platform bus clock = system bus clock/2 + * Here busclk = system bus clock + * We are using the platform bus clock as 1588 Timer reference + * clock source select + */ + do_fixup_by_compat_u32(blob, "fsl, gianfar-ptp-timer", + "timer-frequency", busclk / 2, 1); + + /* + * clock-freq should change to clock-frequency and + * flexcan-v1.0 should change to p1010-flexcan respectively + * in the future. + */ + do_fixup_by_compat_u32(blob, "fsl, flexcan-v1.0", + "clock_freq", busclk / 2, 1); + + do_fixup_by_compat_u32(blob, "fsl, flexcan-v1.0", + "clock-frequency", busclk / 2, 1); + + do_fixup_by_compat_u32(blob, "fsl, ls1021a-flexcan", + "clock-frequency", busclk / 2, 1); + +#if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI) + off = fdt_node_offset_by_compat_reg(blob, FSL_IFC_COMPAT, + CONFIG_SYS_IFC_ADDR); + fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); +#else + off = fdt_node_offset_by_compat_reg(blob, FSL_QSPI_COMPAT, + QSPI0_BASE_ADDR); + fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); + off = fdt_node_offset_by_compat_reg(blob, FSL_DSPI_COMPAT, + DSPI1_BASE_ADDR); + fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); +#endif +}
diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_epu.c b/arch/arm/cpu/armv7/ls102xa/fsl_epu.c new file mode 100644 index 0000000..e31a4fb --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/fsl_epu.c
@@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> + +#include "fsl_epu.h" + +struct fsm_reg_vals epu_default_val[] = { + /* EPGCR (Event Processor Global Control Register) */ + {EPGCR, 0}, + /* EPECR (Event Processor Event Control Registers) */ + {EPECR0 + EPECR_STRIDE * 0, 0}, + {EPECR0 + EPECR_STRIDE * 1, 0}, + {EPECR0 + EPECR_STRIDE * 2, 0xF0004004}, + {EPECR0 + EPECR_STRIDE * 3, 0x80000084}, + {EPECR0 + EPECR_STRIDE * 4, 0x20000084}, + {EPECR0 + EPECR_STRIDE * 5, 0x08000004}, + {EPECR0 + EPECR_STRIDE * 6, 0x80000084}, + {EPECR0 + EPECR_STRIDE * 7, 0x80000084}, + {EPECR0 + EPECR_STRIDE * 8, 0x60000084}, + {EPECR0 + EPECR_STRIDE * 9, 0x08000084}, + {EPECR0 + EPECR_STRIDE * 10, 0x42000084}, + {EPECR0 + EPECR_STRIDE * 11, 0x90000084}, + {EPECR0 + EPECR_STRIDE * 12, 0x80000084}, + {EPECR0 + EPECR_STRIDE * 13, 0x08000084}, + {EPECR0 + EPECR_STRIDE * 14, 0x02000084}, + {EPECR0 + EPECR_STRIDE * 15, 0x00000004}, + /* + * EPEVTCR (Event Processor EVT Pin Control Registers) + * SCU8 triger EVT2, and SCU11 triger EVT9 + */ + {EPEVTCR0 + EPEVTCR_STRIDE * 0, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 1, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x80000001}, + {EPEVTCR0 + EPEVTCR_STRIDE * 3, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 4, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 5, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 6, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 7, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 8, 0}, + {EPEVTCR0 + EPEVTCR_STRIDE * 9, 0xB0000001}, + /* EPCMPR (Event Processor Counter Compare Registers) */ + {EPCMPR0 + EPCMPR_STRIDE * 0, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 1, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 2, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 3, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 4, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 5, 0x00000020}, + {EPCMPR0 + EPCMPR_STRIDE * 6, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 7, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 8, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 9, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 10, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 11, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 12, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 13, 0}, + {EPCMPR0 + EPCMPR_STRIDE * 14, 0x000000FF}, + {EPCMPR0 + EPCMPR_STRIDE * 15, 0x000000FF}, + /* EPCCR (Event Processor Counter Control Registers) */ + {EPCCR0 + EPCCR_STRIDE * 0, 0}, + {EPCCR0 + EPCCR_STRIDE * 1, 0}, + {EPCCR0 + EPCCR_STRIDE * 2, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 3, 0}, + {EPCCR0 + EPCCR_STRIDE * 4, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 5, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 6, 0}, + {EPCCR0 + EPCCR_STRIDE * 7, 0}, + {EPCCR0 + EPCCR_STRIDE * 8, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 9, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 10, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 11, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 12, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 13, 0}, + {EPCCR0 + EPCCR_STRIDE * 14, 0x92840000}, + {EPCCR0 + EPCCR_STRIDE * 15, 0x92840000}, + /* EPSMCR (Event Processor SCU Mux Control Registers) */ + {EPSMCR0 + EPSMCR_STRIDE * 0, 0}, + {EPSMCR0 + EPSMCR_STRIDE * 1, 0}, + {EPSMCR0 + EPSMCR_STRIDE * 2, 0x6C700000}, + {EPSMCR0 + EPSMCR_STRIDE * 3, 0x2F000000}, + {EPSMCR0 + EPSMCR_STRIDE * 4, 0x002F0000}, + {EPSMCR0 + EPSMCR_STRIDE * 5, 0x00002E00}, + {EPSMCR0 + EPSMCR_STRIDE * 6, 0x7C000000}, + {EPSMCR0 + EPSMCR_STRIDE * 7, 0x30000000}, + {EPSMCR0 + EPSMCR_STRIDE * 8, 0x64300000}, + {EPSMCR0 + EPSMCR_STRIDE * 9, 0x00003000}, + {EPSMCR0 + EPSMCR_STRIDE * 10, 0x65000030}, + {EPSMCR0 + EPSMCR_STRIDE * 11, 0x31740000}, + {EPSMCR0 + EPSMCR_STRIDE * 12, 0x7F000000}, + {EPSMCR0 + EPSMCR_STRIDE * 13, 0x00003100}, + {EPSMCR0 + EPSMCR_STRIDE * 14, 0x00000031}, + {EPSMCR0 + EPSMCR_STRIDE * 15, 0x76000000}, + /* EPACR (Event Processor Action Control Registers) */ + {EPACR0 + EPACR_STRIDE * 0, 0}, + {EPACR0 + EPACR_STRIDE * 1, 0}, + {EPACR0 + EPACR_STRIDE * 2, 0}, + {EPACR0 + EPACR_STRIDE * 3, 0x00000080}, + {EPACR0 + EPACR_STRIDE * 4, 0}, + {EPACR0 + EPACR_STRIDE * 5, 0x00000040}, + {EPACR0 + EPACR_STRIDE * 6, 0}, + {EPACR0 + EPACR_STRIDE * 7, 0}, + {EPACR0 + EPACR_STRIDE * 8, 0}, + {EPACR0 + EPACR_STRIDE * 9, 0x0000001C}, + {EPACR0 + EPACR_STRIDE * 10, 0x00000020}, + {EPACR0 + EPACR_STRIDE * 11, 0}, + {EPACR0 + EPACR_STRIDE * 12, 0x00000003}, + {EPACR0 + EPACR_STRIDE * 13, 0x06000000}, + {EPACR0 + EPACR_STRIDE * 14, 0x04000000}, + {EPACR0 + EPACR_STRIDE * 15, 0x02000000}, + /* EPIMCR (Event Processor Input Mux Control Registers) */ + {EPIMCR0 + EPIMCR_STRIDE * 0, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 1, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 2, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 3, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 4, 0x44000000}, + {EPIMCR0 + EPIMCR_STRIDE * 5, 0x40000000}, + {EPIMCR0 + EPIMCR_STRIDE * 6, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 7, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 8, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 9, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 10, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 11, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 12, 0x44000000}, + {EPIMCR0 + EPIMCR_STRIDE * 13, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 14, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 15, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 16, 0x6A000000}, + {EPIMCR0 + EPIMCR_STRIDE * 17, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 18, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 19, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 20, 0x48000000}, + {EPIMCR0 + EPIMCR_STRIDE * 21, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 22, 0x6C000000}, + {EPIMCR0 + EPIMCR_STRIDE * 23, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 24, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 25, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 26, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 27, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 28, 0x76000000}, + {EPIMCR0 + EPIMCR_STRIDE * 29, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 30, 0}, + {EPIMCR0 + EPIMCR_STRIDE * 31, 0x76000000}, + /* EPXTRIGCR (Event Processor Crosstrigger Control Register) */ + {EPXTRIGCR, 0x0000FFDF}, + /* end */ + {FSM_END_FLAG, 0}, +}; + +/** + * fsl_epu_setup - Setup EPU registers to default values + */ +void fsl_epu_setup(void *epu_base) +{ + struct fsm_reg_vals *data = epu_default_val; + + if (!epu_base || !data) + return; + + while (data->offset != FSM_END_FLAG) { + out_be32(epu_base + data->offset, data->value); + data++; + } +} + +/** + * fsl_epu_clean - Clear EPU registers + */ +void fsl_epu_clean(void *epu_base) +{ + u32 offset; + + /* follow the exact sequence to clear the registers */ + /* Clear EPACRn */ + for (offset = EPACR0; offset <= EPACR15; offset += EPACR_STRIDE) + out_be32(epu_base + offset, 0); + + /* Clear EPEVTCRn */ + for (offset = EPEVTCR0; offset <= EPEVTCR9; offset += EPEVTCR_STRIDE) + out_be32(epu_base + offset, 0); + + /* Clear EPGCR */ + out_be32(epu_base + EPGCR, 0); + + /* Clear EPSMCRn */ + for (offset = EPSMCR0; offset <= EPSMCR15; offset += EPSMCR_STRIDE) + out_be32(epu_base + offset, 0); + + /* Clear EPCCRn */ + for (offset = EPCCR0; offset <= EPCCR31; offset += EPCCR_STRIDE) + out_be32(epu_base + offset, 0); + + /* Clear EPCMPRn */ + for (offset = EPCMPR0; offset <= EPCMPR31; offset += EPCMPR_STRIDE) + out_be32(epu_base + offset, 0); + + /* Clear EPCTRn */ + for (offset = EPCTR0; offset <= EPCTR31; offset += EPCTR_STRIDE) + out_be32(epu_base + offset, 0); + + /* Clear EPIMCRn */ + for (offset = EPIMCR0; offset <= EPIMCR31; offset += EPIMCR_STRIDE) + out_be32(epu_base + offset, 0); + + /* Clear EPXTRIGCRn */ + out_be32(epu_base + EPXTRIGCR, 0); + + /* Clear EPECRn */ + for (offset = EPECR0; offset <= EPECR15; offset += EPECR_STRIDE) + out_be32(epu_base + offset, 0); +}
diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_epu.h b/arch/arm/cpu/armv7/ls102xa/fsl_epu.h new file mode 100644 index 0000000..711eea5 --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/fsl_epu.h
@@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#ifndef __FSL_EPU_H +#define __FSL_EPU_H + +#include <asm/types.h> + +#define FSL_STRIDE_4B 4 +#define FSL_STRIDE_8B 8 + +/* Block offsets */ +#define EPU_BLOCK_OFFSET 0x00000000 + +/* EPGCR (Event Processor Global Control Register) */ +#define EPGCR 0x000 + +/* EPEVTCR0-9 (Event Processor EVT Pin Control Registers) */ +#define EPEVTCR0 0x050 +#define EPEVTCR9 0x074 +#define EPEVTCR_STRIDE FSL_STRIDE_4B + +/* EPXTRIGCR (Event Processor Crosstrigger Control Register) */ +#define EPXTRIGCR 0x090 + +/* EPIMCR0-31 (Event Processor Input Mux Control Registers) */ +#define EPIMCR0 0x100 +#define EPIMCR31 0x17C +#define EPIMCR_STRIDE FSL_STRIDE_4B + +/* EPSMCR0-15 (Event Processor SCU Mux Control Registers) */ +#define EPSMCR0 0x200 +#define EPSMCR15 0x278 +#define EPSMCR_STRIDE FSL_STRIDE_8B + +/* EPECR0-15 (Event Processor Event Control Registers) */ +#define EPECR0 0x300 +#define EPECR15 0x33C +#define EPECR_STRIDE FSL_STRIDE_4B + +/* EPACR0-15 (Event Processor Action Control Registers) */ +#define EPACR0 0x400 +#define EPACR15 0x43C +#define EPACR_STRIDE FSL_STRIDE_4B + +/* EPCCRi0-15 (Event Processor Counter Control Registers) */ +#define EPCCR0 0x800 +#define EPCCR15 0x83C +#define EPCCR31 0x87C +#define EPCCR_STRIDE FSL_STRIDE_4B + +/* EPCMPR0-15 (Event Processor Counter Compare Registers) */ +#define EPCMPR0 0x900 +#define EPCMPR15 0x93C +#define EPCMPR31 0x97C +#define EPCMPR_STRIDE FSL_STRIDE_4B + +/* EPCTR0-31 (Event Processor Counter Register) */ +#define EPCTR0 0xA00 +#define EPCTR31 0xA7C +#define EPCTR_STRIDE FSL_STRIDE_4B + +#define FSM_END_FLAG 0xFFFFFFFFUL + +struct fsm_reg_vals { + u32 offset; + u32 value; +}; + +void fsl_epu_setup(void *epu_base); +void fsl_epu_clean(void *epu_base); + +#endif
diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c b/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c new file mode 100644 index 0000000..caf51e1 --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.c
@@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch/immap_ls102xa.h> +#include <linux/errno.h> +#include <asm/io.h> +#include "fsl_ls1_serdes.h" + +#ifdef CONFIG_SYS_FSL_SRDS_1 +static u64 serdes1_prtcl_map; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 +static u64 serdes2_prtcl_map; +#endif + +int is_serdes_configured(enum srds_prtcl device) +{ + u64 ret = 0; + +#ifdef CONFIG_SYS_FSL_SRDS_1 + if (!(serdes1_prtcl_map & (1ULL << NONE))) + fsl_serdes_init(); + + ret |= (1ULL << device) & serdes1_prtcl_map; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + if (!(serdes2_prtcl_map & (1ULL << NONE))) + fsl_serdes_init(); + + ret |= (1ULL << device) & serdes2_prtcl_map; +#endif + + return !!ret; +} + +int serdes_get_first_lane(u32 sd, enum srds_prtcl device) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 cfg = in_be32(&gur->rcwsr[4]); + int i; + + switch (sd) { +#ifdef CONFIG_SYS_FSL_SRDS_1 + case FSL_SRDS_1: + cfg &= RCWSR4_SRDS1_PRTCL_MASK; + cfg >>= RCWSR4_SRDS1_PRTCL_SHIFT; + break; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + case FSL_SRDS_2: + cfg &= RCWSR4_SRDS2_PRTCL_MASK; + cfg >>= RCWSR4_SRDS2_PRTCL_SHIFT; + break; +#endif + default: + printf("invalid SerDes%d\n", sd); + break; + } + /* Is serdes enabled at all? */ + if (unlikely(cfg == 0)) + return -ENODEV; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (serdes_get_prtcl(sd, cfg, i) == device) + return i; + } + + return -ENODEV; +} + +u64 serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u64 serdes_prtcl_map = 0; + u32 cfg; + int lane; + + cfg = in_be32(&gur->rcwsr[4]) & sd_prctl_mask; + cfg >>= sd_prctl_shift; + printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg); + + if (!is_serdes_prtcl_valid(sd, cfg)) + printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg); + + for (lane = 0; lane < SRDS_MAX_LANES; lane++) { + enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane); + + serdes_prtcl_map |= (1ULL << lane_prtcl); + } + + /* Set the first bit to indicate serdes has been initialized */ + serdes_prtcl_map |= (1ULL << NONE); + + return serdes_prtcl_map; +} + +void fsl_serdes_init(void) +{ +#ifdef CONFIG_SYS_FSL_SRDS_1 + if (!(serdes1_prtcl_map & (1ULL << NONE))) + serdes1_prtcl_map = serdes_init(FSL_SRDS_1, + CONFIG_SYS_FSL_SERDES_ADDR, + RCWSR4_SRDS1_PRTCL_MASK, + RCWSR4_SRDS1_PRTCL_SHIFT); +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + if (!(serdes2_prtcl_map & (1ULL << NONE))) + serdes2_prtcl_map = serdes_init(FSL_SRDS_2, + CONFIG_SYS_FSL_SERDES_ADDR + + FSL_SRDS_2 * 0x1000, + RCWSR4_SRDS2_PRTCL_MASK, + RCWSR4_SRDS2_PRTCL_SHIFT); +#endif +} + +const char *serdes_clock_to_string(u32 clock) +{ + switch (clock) { + case SRDS_PLLCR0_RFCK_SEL_100: + return "100"; + case SRDS_PLLCR0_RFCK_SEL_125: + return "125"; + default: + return "100"; + } +}
diff --git a/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.h b/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.h new file mode 100644 index 0000000..7382aef --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/fsl_ls1_serdes.h
@@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#ifndef __FSL_LS1_SERDES_H +#define __FSL_LS1_SERDES_H + +int is_serdes_prtcl_valid(int serdes, u32 prtcl); +int serdes_lane_enabled(int lane); +#endif /* __FSL_LS1_SERDES_H */
diff --git a/arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c b/arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c new file mode 100644 index 0000000..bb169aa --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/ls102xa_psci.c
@@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + * Author: Hongbo Zhang <hongbo.zhang@nxp.com> + * This file implements LS102X platform PSCI SYSTEM-SUSPEND function + */ + +#include <config.h> +#include <asm/io.h> +#include <asm/psci.h> +#include <asm/arch/immap_ls102xa.h> +#include <fsl_immap.h> +#include "fsl_epu.h" + +#define __secure __attribute__((section("._secure.text"))) + +#define CCSR_GICD_CTLR 0x1000 +#define CCSR_GICC_CTLR 0x2000 +#define DCSR_RCPM_CG1CR0 0x31c +#define DCSR_RCPM_CSTTACR0 0xb00 +#define DCFG_CRSTSR_WDRFR 0x8 +#define DDR_RESV_LEN 128 + +#ifdef CONFIG_LS1_DEEP_SLEEP +/* + * DDR controller initialization training breaks the first 128 bytes of DDR, + * save them so that the bootloader can restore them while resuming. + */ +static void __secure ls1_save_ddr_head(void) +{ + const char *src = (const char *)CONFIG_SYS_SDRAM_BASE; + char *dest = (char *)(OCRAM_BASE_S_ADDR + OCRAM_S_SIZE - DDR_RESV_LEN); + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + int i; + + out_le32(&scfg->sparecr[2], dest); + + for (i = 0; i < DDR_RESV_LEN; i++) + *dest++ = *src++; +} + +static void __secure ls1_fsm_setup(void) +{ + void *dcsr_epu_base = (void *)(CONFIG_SYS_DCSRBAR + EPU_BLOCK_OFFSET); + void *dcsr_rcpm_base = (void *)SYS_FSL_DCSR_RCPM_ADDR; + + out_be32(dcsr_rcpm_base + DCSR_RCPM_CSTTACR0, 0x00001001); + out_be32(dcsr_rcpm_base + DCSR_RCPM_CG1CR0, 0x00000001); + + fsl_epu_setup((void *)dcsr_epu_base); + + /* Pull MCKE signal low before enabling deep sleep signal in FPGA */ + out_be32(dcsr_epu_base + EPECR0, 0x5); + out_be32(dcsr_epu_base + EPSMCR15, 0x76300000); +} + +static void __secure ls1_deepsleep_irq_cfg(void) +{ + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + struct ccsr_rcpm __iomem *rcpm = (void *)CONFIG_SYS_FSL_RCPM_ADDR; + u32 ippdexpcr0, ippdexpcr1, pmcintecr = 0; + + /* Mask interrupts from GIC */ + out_be32(&rcpm->nfiqoutr, 0x0ffffffff); + out_be32(&rcpm->nirqoutr, 0x0ffffffff); + /* Mask deep sleep wake-up interrupts while entering deep sleep */ + out_be32(&rcpm->dsimskr, 0x0ffffffff); + + ippdexpcr0 = in_be32(&rcpm->ippdexpcr0); + /* + * Workaround: There is bug of register ippdexpcr1, when read it always + * returns zero, so its value is saved to a scrachpad register to be + * read, that is why we don't read it from register ippdexpcr1 itself. + */ + ippdexpcr1 = in_le32(&scfg->sparecr[7]); + out_be32(&rcpm->ippdexpcr1, ippdexpcr1); + + if (ippdexpcr0 & RCPM_IPPDEXPCR0_ETSEC) + pmcintecr |= SCFG_PMCINTECR_ETSECRXG0 | + SCFG_PMCINTECR_ETSECRXG1 | + SCFG_PMCINTECR_ETSECERRG0 | + SCFG_PMCINTECR_ETSECERRG1; + + if (ippdexpcr0 & RCPM_IPPDEXPCR0_GPIO) + pmcintecr |= SCFG_PMCINTECR_GPIO; + + if (ippdexpcr1 & RCPM_IPPDEXPCR1_LPUART) + pmcintecr |= SCFG_PMCINTECR_LPUART; + + if (ippdexpcr1 & RCPM_IPPDEXPCR1_FLEXTIMER) + pmcintecr |= SCFG_PMCINTECR_FTM; + + /* Always set external IRQ pins as wakeup source */ + pmcintecr |= SCFG_PMCINTECR_IRQ0 | SCFG_PMCINTECR_IRQ1; + + out_be32(&scfg->pmcintlecr, 0); + /* Clear PMC interrupt status */ + out_be32(&scfg->pmcintsr, 0xffffffff); + /* Enable wakeup interrupt during deep sleep */ + out_be32(&scfg->pmcintecr, pmcintecr); +} + +static void __secure ls1_delay(unsigned int loop) +{ + while (loop--) { + int i = 1000; + while (i--) + ; + } +} + +static void __secure ls1_start_fsm(void) +{ + void *dcsr_epu_base = (void *)(CONFIG_SYS_DCSRBAR + EPU_BLOCK_OFFSET); + void *ccsr_gic_base = (void *)SYS_FSL_GIC_ADDR; + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + + /* Set HRSTCR */ + setbits_be32(&scfg->hrstcr, 0x80000000); + + /* Place DDR controller in self refresh mode */ + setbits_be32(&ddr->sdram_cfg_2, 0x80000000); + + ls1_delay(2000); + + /* Set EVT4_B to lock the signal MCKE down */ + out_be32(dcsr_epu_base + EPECR0, 0x0); + + ls1_delay(2000); + + out_be32(ccsr_gic_base + CCSR_GICD_CTLR, 0x0); + out_be32(ccsr_gic_base + CCSR_GICC_CTLR, 0x0); + + /* Enable all EPU Counters */ + setbits_be32(dcsr_epu_base + EPGCR, 0x80000000); + + /* Enable SCU15 */ + setbits_be32(dcsr_epu_base + EPECR15, 0x90000004); + + /* Enter WFI mode, and EPU FSM will start */ + __asm__ __volatile__ ("wfi" : : : "memory"); + + /* NEVER ENTER HERE */ + while (1) + ; +} + +static void __secure ls1_deep_sleep(u32 entry_point) +{ + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + struct ccsr_rcpm __iomem *rcpm = (void *)CONFIG_SYS_FSL_RCPM_ADDR; +#ifdef QIXIS_BASE + u32 tmp; + void *qixis_base = (void *)QIXIS_BASE; +#endif + + /* Enable cluster to enter the PCL10 state */ + out_be32(&scfg->clusterpmcr, SCFG_CLUSTERPMCR_WFIL2EN); + + /* Save the first 128 bytes of DDR data */ + ls1_save_ddr_head(); + + /* Save the kernel resume entry */ + out_le32(&scfg->sparecr[3], entry_point); + + /* Request to put cluster 0 in PCL10 state */ + setbits_be32(&rcpm->clpcl10setr, RCPM_CLPCL10SETR_C0); + + /* Setup the registers of the EPU FSM for deep sleep */ + ls1_fsm_setup(); + +#ifdef QIXIS_BASE + /* Connect the EVENT button to IRQ in FPGA */ + tmp = in_8(qixis_base + QIXIS_CTL_SYS); + tmp &= ~QIXIS_CTL_SYS_EVTSW_MASK; + tmp |= QIXIS_CTL_SYS_EVTSW_IRQ; + out_8(qixis_base + QIXIS_CTL_SYS, tmp); + + /* Enable deep sleep signals in FPGA */ + tmp = in_8(qixis_base + QIXIS_PWR_CTL2); + tmp |= QIXIS_PWR_CTL2_PCTL; + out_8(qixis_base + QIXIS_PWR_CTL2, tmp); + + /* Pull down PCIe RST# */ + tmp = in_8(qixis_base + QIXIS_RST_FORCE_3); + tmp |= QIXIS_RST_FORCE_3_PCIESLOT1; + out_8(qixis_base + QIXIS_RST_FORCE_3, tmp); +#endif + + /* Enable Warm Device Reset */ + setbits_be32(&scfg->dpslpcr, SCFG_DPSLPCR_WDRR_EN); + setbits_be32(&gur->crstsr, DCFG_CRSTSR_WDRFR); + + /* Disable QE */ + setbits_be32(&gur->devdisr, CCSR_DEVDISR1_QE); + + ls1_deepsleep_irq_cfg(); + + psci_v7_flush_dcache_all(); + + ls1_start_fsm(); +} + +#else +static void __secure ls1_sleep(void) +{ + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + struct ccsr_rcpm __iomem *rcpm = (void *)CONFIG_SYS_FSL_RCPM_ADDR; + +#ifdef QIXIS_BASE + u32 tmp; + void *qixis_base = (void *)QIXIS_BASE; + + /* Connect the EVENT button to IRQ in FPGA */ + tmp = in_8(qixis_base + QIXIS_CTL_SYS); + tmp &= ~QIXIS_CTL_SYS_EVTSW_MASK; + tmp |= QIXIS_CTL_SYS_EVTSW_IRQ; + out_8(qixis_base + QIXIS_CTL_SYS, tmp); +#endif + + /* Enable cluster to enter the PCL10 state */ + out_be32(&scfg->clusterpmcr, SCFG_CLUSTERPMCR_WFIL2EN); + + setbits_be32(&rcpm->powmgtcsr, RCPM_POWMGTCSR_LPM20_REQ); + + __asm__ __volatile__ ("wfi" : : : "memory"); +} +#endif + +void __secure ls1_system_suspend(u32 fn, u32 entry_point, u32 context_id) +{ +#ifdef CONFIG_LS1_DEEP_SLEEP + ls1_deep_sleep(entry_point); +#else + ls1_sleep(); +#endif +}
diff --git a/arch/arm/cpu/armv7/ls102xa/ls102xa_serdes.c b/arch/arm/cpu/armv7/ls102xa/ls102xa_serdes.c new file mode 100644 index 0000000..8c030be --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/ls102xa_serdes.c
@@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch/immap_ls102xa.h> + +static u8 serdes_cfg_tbl[][SRDS_MAX_LANES] = { + [0x00] = {PCIE1, PCIE1, PCIE1, PCIE1}, + [0x10] = {PCIE1, SATA1, PCIE2, PCIE2}, + [0x20] = {PCIE1, SGMII_TSEC1, PCIE2, SGMII_TSEC2}, + [0x30] = {PCIE1, SATA1, SGMII_TSEC1, SGMII_TSEC2}, + [0x40] = {PCIE1, PCIE1, SATA1, SGMII_TSEC2}, + [0x50] = {PCIE1, PCIE1, PCIE2, SGMII_TSEC2}, + [0x60] = {PCIE1, PCIE1, SGMII_TSEC1, SGMII_TSEC2}, + [0x70] = {PCIE1, SATA1, PCIE2, SGMII_TSEC2}, + [0x80] = {PCIE2, PCIE2, PCIE2, PCIE2}, +}; + +enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane) +{ + return serdes_cfg_tbl[cfg][lane]; +} + +int is_serdes_prtcl_valid(int serdes, u32 prtcl) +{ + int i; + + if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (serdes_cfg_tbl[prtcl][i] != NONE) + return 1; + } + + return 0; +}
diff --git a/arch/arm/cpu/armv7/ls102xa/psci.S b/arch/arm/cpu/armv7/ls102xa/psci.S new file mode 100644 index 0000000..531cfb0 --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/psci.S
@@ -0,0 +1,257 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + * Author: Wang Dongsheng <dongsheng.wang@freescale.com> + */ + +#include <config.h> +#include <linux/linkage.h> + +#include <asm/armv7.h> +#include <asm/arch-armv7/generictimer.h> +#include <asm/psci.h> + +#define RCPM_TWAITSR 0x04C + +#define SCFG_CORE0_SFT_RST 0x130 +#define SCFG_CORESRENCR 0x204 + +#define DCFG_CCSR_RSTCR 0x0B0 +#define DCFG_CCSR_RSTCR_RESET_REQ 0x2 +#define DCFG_CCSR_BRR 0x0E4 +#define DCFG_CCSR_SCRATCHRW1 0x200 + +#define PSCI_FN_PSCI_VERSION_FEATURE_MASK 0x0 +#define PSCI_FN_CPU_SUSPEND_FEATURE_MASK 0x0 +#define PSCI_FN_CPU_OFF_FEATURE_MASK 0x0 +#define PSCI_FN_CPU_ON_FEATURE_MASK 0x0 +#define PSCI_FN_AFFINITY_INFO_FEATURE_MASK 0x0 +#define PSCI_FN_SYSTEM_OFF_FEATURE_MASK 0x0 +#define PSCI_FN_SYSTEM_RESET_FEATURE_MASK 0x0 +#define PSCI_FN_SYSTEM_SUSPEND_FEATURE_MASK 0x0 + + .pushsection ._secure.text, "ax" + + .arch_extension sec + + .align 5 + +#define ONE_MS (COUNTER_FREQUENCY / 1000) +#define RESET_WAIT (30 * ONE_MS) + +.globl psci_version +psci_version: + movw r0, #0 + movt r0, #1 + + bx lr + +_ls102x_psci_supported_table: + .word ARM_PSCI_0_2_FN_PSCI_VERSION + .word PSCI_FN_PSCI_VERSION_FEATURE_MASK + .word ARM_PSCI_0_2_FN_CPU_SUSPEND + .word PSCI_FN_CPU_SUSPEND_FEATURE_MASK + .word ARM_PSCI_0_2_FN_CPU_OFF + .word PSCI_FN_CPU_OFF_FEATURE_MASK + .word ARM_PSCI_0_2_FN_CPU_ON + .word PSCI_FN_CPU_ON_FEATURE_MASK + .word ARM_PSCI_0_2_FN_AFFINITY_INFO + .word PSCI_FN_AFFINITY_INFO_FEATURE_MASK + .word ARM_PSCI_0_2_FN_SYSTEM_OFF + .word PSCI_FN_SYSTEM_OFF_FEATURE_MASK + .word ARM_PSCI_0_2_FN_SYSTEM_RESET + .word PSCI_FN_SYSTEM_RESET_FEATURE_MASK + .word ARM_PSCI_1_0_FN_SYSTEM_SUSPEND + .word PSCI_FN_SYSTEM_SUSPEND_FEATURE_MASK + .word 0 + .word ARM_PSCI_RET_NI + +.globl psci_features +psci_features: + adr r2, _ls102x_psci_supported_table +1: ldr r3, [r2] + cmp r3, #0 + beq out_psci_features + cmp r1, r3 + addne r2, r2, #8 + bne 1b + +out_psci_features: + ldr r0, [r2, #4] + bx lr + +@ r0: return value ARM_PSCI_RET_SUCCESS or ARM_PSCI_RET_INVAL +@ r1: input target CPU ID in MPIDR format, original value in r1 may be dropped +@ r4: output validated CPU ID if ARM_PSCI_RET_SUCCESS returns, meaningless for +@ ARM_PSCI_RET_INVAL,suppose caller saves r4 before calling +LENTRY(psci_check_target_cpu_id) + @ Get the real CPU number + and r4, r1, #0xff + mov r0, #ARM_PSCI_RET_INVAL + + @ Bit[31:24], bits must be zero. + tst r1, #0xff000000 + bxne lr + + @ Affinity level 2 - Cluster: only one cluster in LS1021xa. + tst r1, #0xff0000 + bxne lr + + @ Affinity level 1 - Processors: should be in 0xf00 format. + lsr r1, r1, #8 + teq r1, #0xf + bxne lr + + @ Affinity level 0 - CPU: only 0, 1 are valid in LS1021xa. + cmp r4, #2 + bxge lr + + mov r0, #ARM_PSCI_RET_SUCCESS + bx lr +ENDPROC(psci_check_target_cpu_id) + + @ r1 = target CPU + @ r2 = target PC +.globl psci_cpu_on +psci_cpu_on: + push {r4, r5, r6, lr} + + @ Clear and Get the correct CPU number + @ r1 = 0xf01 + bl psci_check_target_cpu_id + cmp r0, #ARM_PSCI_RET_INVAL + beq out_psci_cpu_on + + mov r0, r4 + mov r1, r2 + mov r2, r3 + bl psci_save + mov r1, r4 + + @ Get DCFG base address + movw r4, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff) + movt r4, #(CONFIG_SYS_FSL_GUTS_ADDR >> 16) + + @ Detect target CPU state + ldr r2, [r4, #DCFG_CCSR_BRR] + rev r2, r2 + lsr r2, r2, r1 + ands r2, r2, #1 + beq holdoff_release + + @ Reset target CPU + @ Get SCFG base address + movw r0, #(CONFIG_SYS_FSL_SCFG_ADDR & 0xffff) + movt r0, #(CONFIG_SYS_FSL_SCFG_ADDR >> 16) + + @ Enable CORE Soft Reset + movw r5, #0 + movt r5, #(1 << 15) + rev r5, r5 + str r5, [r0, #SCFG_CORESRENCR] + + @ Get CPUx offset register + mov r6, #0x4 + mul r6, r6, r1 + add r2, r0, r6 + + @ Do reset on target CPU + movw r5, #0 + movt r5, #(1 << 15) + rev r5, r5 + str r5, [r2, #SCFG_CORE0_SFT_RST] + + @ Wait target CPU up + timer_wait r2, RESET_WAIT + + @ Disable CORE soft reset + mov r5, #0 + str r5, [r0, #SCFG_CORESRENCR] + +holdoff_release: + @ Release on target CPU + ldr r2, [r4, #DCFG_CCSR_BRR] + mov r6, #1 + lsl r6, r6, r1 @ 32 bytes per CPU + + rev r6, r6 + orr r2, r2, r6 + str r2, [r4, #DCFG_CCSR_BRR] + + @ Set secondary boot entry + ldr r6, =psci_cpu_entry + rev r6, r6 + str r6, [r4, #DCFG_CCSR_SCRATCHRW1] + + isb + dsb + + @ Return + mov r0, #ARM_PSCI_RET_SUCCESS + +out_psci_cpu_on: + pop {r4, r5, r6, lr} + bx lr + +.globl psci_cpu_off +psci_cpu_off: + bl psci_cpu_off_common + +1: wfi + b 1b + +.globl psci_affinity_info +psci_affinity_info: + push {lr} + + mov r0, #ARM_PSCI_RET_INVAL + + @ Verify Affinity level + cmp r2, #0 + bne out_affinity_info + + bl psci_check_target_cpu_id + cmp r0, #ARM_PSCI_RET_INVAL + beq out_affinity_info + mov r1, r4 + + @ Get RCPM base address + movw r4, #(CONFIG_SYS_FSL_RCPM_ADDR & 0xffff) + movt r4, #(CONFIG_SYS_FSL_RCPM_ADDR >> 16) + + mov r0, #PSCI_AFFINITY_LEVEL_ON + + @ Detect target CPU state + ldr r2, [r4, #RCPM_TWAITSR] + rev r2, r2 + lsr r2, r2, r1 + ands r2, r2, #1 + beq out_affinity_info + + mov r0, #PSCI_AFFINITY_LEVEL_OFF + +out_affinity_info: + pop {pc} + +.globl psci_system_reset +psci_system_reset: + @ Get DCFG base address + movw r1, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff) + movt r1, #(CONFIG_SYS_FSL_GUTS_ADDR >> 16) + + mov r2, #DCFG_CCSR_RSTCR_RESET_REQ + rev r2, r2 + str r2, [r1, #DCFG_CCSR_RSTCR] + +1: wfi + b 1b + +.globl psci_system_suspend +psci_system_suspend: + push {lr} + + bl ls1_system_suspend + + pop {pc} + + .popsection
diff --git a/arch/arm/cpu/armv7/ls102xa/soc.c b/arch/arm/cpu/armv7/ls102xa/soc.c new file mode 100644 index 0000000..448d951 --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/soc.c
@@ -0,0 +1,211 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/io.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch/immap_ls102xa.h> +#include <asm/arch/ls102xa_soc.h> +#include <asm/arch/ls102xa_stream_id.h> +#include <fsl_csu.h> + +struct liodn_id_table sec_liodn_tbl[] = { + SET_SEC_JR_LIODN_ENTRY(0, 0x10, 0x10), + SET_SEC_JR_LIODN_ENTRY(1, 0x10, 0x10), + SET_SEC_JR_LIODN_ENTRY(2, 0x10, 0x10), + SET_SEC_JR_LIODN_ENTRY(3, 0x10, 0x10), + SET_SEC_RTIC_LIODN_ENTRY(a, 0x10), + SET_SEC_RTIC_LIODN_ENTRY(b, 0x10), + SET_SEC_RTIC_LIODN_ENTRY(c, 0x10), + SET_SEC_RTIC_LIODN_ENTRY(d, 0x10), + SET_SEC_DECO_LIODN_ENTRY(0, 0x10, 0x10), + SET_SEC_DECO_LIODN_ENTRY(1, 0x10, 0x10), + SET_SEC_DECO_LIODN_ENTRY(2, 0x10, 0x10), + SET_SEC_DECO_LIODN_ENTRY(3, 0x10, 0x10), + SET_SEC_DECO_LIODN_ENTRY(4, 0x10, 0x10), + SET_SEC_DECO_LIODN_ENTRY(5, 0x10, 0x10), + SET_SEC_DECO_LIODN_ENTRY(6, 0x10, 0x10), + SET_SEC_DECO_LIODN_ENTRY(7, 0x10, 0x10), +}; + +struct smmu_stream_id dev_stream_id[] = { + { 0x100, 0x01, "ETSEC MAC1" }, + { 0x104, 0x02, "ETSEC MAC2" }, + { 0x108, 0x03, "ETSEC MAC3" }, + { 0x10c, 0x04, "PEX1" }, + { 0x110, 0x05, "PEX2" }, + { 0x114, 0x06, "qDMA" }, + { 0x118, 0x07, "SATA" }, + { 0x11c, 0x08, "USB3" }, + { 0x120, 0x09, "QE" }, + { 0x124, 0x0a, "eSDHC" }, + { 0x128, 0x0b, "eMA" }, + { 0x14c, 0x0c, "2D-ACE" }, + { 0x150, 0x0d, "USB2" }, + { 0x18c, 0x0e, "DEBUG" }, +}; + +unsigned int get_soc_major_rev(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + unsigned int svr, major; + + svr = in_be32(&gur->svr); + major = SVR_MAJ(svr); + + return major; +} + +static void erratum_a009008(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009008 + u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE; + + clrsetbits_be32(scfg + SCFG_USB3PRM1CR / 4, + 0xF << 6, + SCFG_USB_TXVREFTUNE << 6); +#endif /* CONFIG_SYS_FSL_ERRATUM_A009008 */ +} + +static void erratum_a009798(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009798 + u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE; + + clrbits_be32(scfg + SCFG_USB3PRM1CR / 4, + SCFG_USB_SQRXTUNE_MASK << 23); +#endif /* CONFIG_SYS_FSL_ERRATUM_A009798 */ +} + +static void erratum_a008997(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008997 + u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE; + + clrsetbits_be32(scfg + SCFG_USB3PRM2CR / 4, + SCFG_USB_PCSTXSWINGFULL_MASK, + SCFG_USB_PCSTXSWINGFULL_VAL); +#endif /* CONFIG_SYS_FSL_ERRATUM_A008997 */ +} + +static void erratum_a009007(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009007 + void __iomem *usb_phy = (void __iomem *)USB_PHY_BASE; + + out_le16(usb_phy + USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_1); + out_le16(usb_phy + USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_2); + out_le16(usb_phy + USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_3); + out_le16(usb_phy + USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_4); +#endif /* CONFIG_SYS_FSL_ERRATUM_A009007 */ +} + +void s_init(void) +{ +} + +#ifdef CONFIG_SYS_FSL_ERRATUM_A010315 +void erratum_a010315(void) +{ + int i; + + for (i = PCIE1; i <= PCIE2; i++) + if (!is_serdes_configured(i)) { + debug("PCIe%d: disabled all R/W permission!\n", i); + set_pcie_ns_access(i, 0); + } +} +#endif + +int arch_soc_init(void) +{ + struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR; + struct ccsr_cci400 *cci = (struct ccsr_cci400 *)(CONFIG_SYS_IMMR + + CONFIG_SYS_CCI400_OFFSET); + unsigned int major; + +#ifdef CONFIG_LAYERSCAPE_NS_ACCESS + enable_layerscape_ns_access(); +#endif + +#ifdef CONFIG_FSL_QSPI + out_be32(&scfg->qspi_cfg, SCFG_QSPI_CLKSEL); +#endif + +#ifdef CONFIG_VIDEO_FSL_DCU_FB + out_be32(&scfg->pixclkcr, SCFG_PIXCLKCR_PXCKEN); +#endif + + /* Configure Little endian for SAI, ASRC and SPDIF */ + out_be32(&scfg->endiancr, SCFG_ENDIANCR_LE); + + /* + * Enable snoop requests and DVM message requests for + * All the slave insterfaces. + */ + out_le32(&cci->slave[0].snoop_ctrl, + CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN); + out_le32(&cci->slave[1].snoop_ctrl, + CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN); + out_le32(&cci->slave[2].snoop_ctrl, + CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN); + out_le32(&cci->slave[4].snoop_ctrl, + CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN); + + major = get_soc_major_rev(); + if (major == SOC_MAJOR_VER_1_0) { + /* + * Set CCI-400 Slave interface S1, S2 Shareable Override + * Register All transactions are treated as non-shareable + */ + out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE); + out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE); + + /* Workaround for the issue that DDR could not respond to + * barrier transaction which is generated by executing DSB/ISB + * instruction. Set CCI-400 control override register to + * terminate the barrier transaction. After DDR is initialized, + * allow barrier transaction to DDR again */ + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER); + } + + /* Enable all the snoop signal for various masters */ + out_be32(&scfg->snpcnfgcr, SCFG_SNPCNFGCR_SEC_RD_WR | + SCFG_SNPCNFGCR_DCU_RD_WR | + SCFG_SNPCNFGCR_SATA_RD_WR | + SCFG_SNPCNFGCR_USB3_RD_WR | + SCFG_SNPCNFGCR_DBG_RD_WR | + SCFG_SNPCNFGCR_EDMA_SNP); + + /* + * Memory controller require a register write before being enabled. + * Affects: DDR + * Register: EDDRTQCFG + * Description: Memory controller performance is not optimal with + * default internal target queue register values. + * Workaround: Write a value of 63b2_0042h to address: 157_020Ch. + */ + out_be32(&scfg->eddrtqcfg, 0x63b20042); + + /* Erratum */ + erratum_a009008(); + erratum_a009798(); + erratum_a008997(); + erratum_a009007(); + + return 0; +} + +int ls102xa_smmu_stream_id_init(void) +{ + ls1021x_config_caam_stream_id(sec_liodn_tbl, + ARRAY_SIZE(sec_liodn_tbl)); + + ls102xa_config_smmu_stream_id(dev_stream_id, + ARRAY_SIZE(dev_stream_id)); + + return 0; +}
diff --git a/arch/arm/cpu/armv7/ls102xa/spl.c b/arch/arm/cpu/armv7/ls102xa/spl.c new file mode 100644 index 0000000..308536c --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/spl.c
@@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <spl.h> + +u32 spl_boot_device(void) +{ +#ifdef CONFIG_SPL_MMC_SUPPORT + return BOOT_DEVICE_MMC1; +#endif + return BOOT_DEVICE_NAND; +}
diff --git a/arch/arm/cpu/armv7/ls102xa/timer.c b/arch/arm/cpu/armv7/ls102xa/timer.c new file mode 100644 index 0000000..e79360a --- /dev/null +++ b/arch/arm/cpu/armv7/ls102xa/timer.c
@@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <div64.h> +#include <asm/arch/immap_ls102xa.h> +#include <asm/arch/clock.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * This function is intended for SHORT delays only. + * It will overflow at around 10 seconds @ 400MHz, + * or 20 seconds @ 200MHz. + */ +unsigned long usec2ticks(unsigned long usec) +{ + ulong ticks; + + if (usec < 1000) + ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000; + else + ticks = ((usec / 10) * (get_tbclk() / 100000)); + + return ticks; +} + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + unsigned long freq; + + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq)); + + tick *= CONFIG_SYS_HZ; + do_div(tick, freq); + + return tick; +} + +static inline unsigned long long us_to_tick(unsigned long long usec) +{ + unsigned long freq; + + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq)); + + usec = usec * freq + 999999; + do_div(usec, 1000000); + + return usec; +} + +int timer_init(void) +{ + struct sctr_regs *sctr = (struct sctr_regs *)SCTR_BASE_ADDR; + unsigned long ctrl, freq; + unsigned long long val; + + /* Enable System Counter */ + writel(SYS_COUNTER_CTRL_ENABLE, &sctr->cntcr); + + freq = COUNTER_FREQUENCY; + asm("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq)); + + /* Set PL1 Physical Timer Ctrl */ + ctrl = ARCH_TIMER_CTRL_ENABLE; + asm("mcr p15, 0, %0, c14, c2, 1" : : "r" (ctrl)); + + /* Set PL1 Physical Comp Value */ + val = TIMER_COMP_VAL; + asm("mcrr p15, 2, %Q0, %R0, c14" : : "r" (val)); + + gd->arch.tbl = 0; + gd->arch.tbu = 0; + + return 0; +} + +unsigned long long get_ticks(void) +{ + unsigned long long now; + + asm("mrrc p15, 0, %Q0, %R0, c14" : "=r" (now)); + + gd->arch.tbl = (unsigned long)(now & 0xffffffff); + gd->arch.tbu = (unsigned long)(now >> 32); + + return now; +} + +unsigned long get_timer(ulong base) +{ + return tick_to_time(get_ticks()) - base; +} + +/* delay x useconds and preserve advance timstamp value */ +void __udelay(unsigned long usec) +{ + unsigned long long start; + unsigned long tmo; + + start = get_ticks(); /* get current timestamp */ + tmo = us_to_tick(usec); /* convert usecs to ticks */ + + while ((get_ticks() - start) < tmo) + ; /* loop till time has passed */ +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +unsigned long get_tbclk(void) +{ + unsigned long freq; + + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (freq)); + + return freq; +}
diff --git a/arch/arm/cpu/armv7/mpu_v7r.c b/arch/arm/cpu/armv7/mpu_v7r.c new file mode 100644 index 0000000..7adecff --- /dev/null +++ b/arch/arm/cpu/armv7/mpu_v7r.c
@@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Cortex-R Memory Protection Unit specific code + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + */ + +#include <common.h> +#include <command.h> +#include <asm/armv7.h> +#include <asm/system.h> +#include <asm/barriers.h> +#include <linux/compiler.h> + +#include <asm/armv7_mpu.h> + +/* MPU Type register definitions */ +#define MPUIR_S_SHIFT 0 +#define MPUIR_S_MASK BIT(MPUIR_S_SHIFT) +#define MPUIR_DREGION_SHIFT 8 +#define MPUIR_DREGION_MASK (0xff << 8) + +/** + * Note: + * The Memory Protection Unit(MPU) allows to partition memory into regions + * and set individual protection attributes for each region. In absence + * of MPU a default map[1] will take effect. make sure to run this code + * from a region which has execution permissions by default. + * [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0460d/I1002400.html + */ + +void disable_mpu(void) +{ + u32 reg; + + reg = get_cr(); + reg &= ~CR_M; + dsb(); + set_cr(reg); + isb(); +} + +void enable_mpu(void) +{ + u32 reg; + + reg = get_cr(); + reg |= CR_M; + dsb(); + set_cr(reg); + isb(); +} + +int mpu_enabled(void) +{ + return get_cr() & CR_M; +} + +void mpu_config(struct mpu_region_config *rgn) +{ + u32 attr, val; + + attr = get_attr_encoding(rgn->mr_attr); + + /* MPU Region Number Register */ + asm volatile ("mcr p15, 0, %0, c6, c2, 0" : : "r" (rgn->region_no)); + + /* MPU Region Base Address Register */ + asm volatile ("mcr p15, 0, %0, c6, c1, 0" : : "r" (rgn->start_addr)); + + /* MPU Region Size and Enable Register */ + if (rgn->reg_size) + val = (rgn->reg_size << REGION_SIZE_SHIFT) | ENABLE_REGION; + else + val = DISABLE_REGION; + asm volatile ("mcr p15, 0, %0, c6, c1, 2" : : "r" (val)); + + /* MPU Region Access Control Register */ + val = rgn->xn << XN_SHIFT | rgn->ap << AP_SHIFT | attr; + asm volatile ("mcr p15, 0, %0, c6, c1, 4" : : "r" (val)); +} + +void setup_mpu_regions(struct mpu_region_config *rgns, u32 num_rgns) +{ + u32 num, i; + + asm volatile ("mrc p15, 0, %0, c0, c0, 4" : "=r" (num)); + num = (num & MPUIR_DREGION_MASK) >> MPUIR_DREGION_SHIFT; + /* Regions to be configured cannot be greater than available regions */ + if (num < num_rgns) + num_rgns = num; + /** + * Assuming dcache might not be enabled at this point, disabling + * and invalidating only icache. + */ + icache_disable(); + invalidate_icache_all(); + + disable_mpu(); + + for (i = 0; i < num_rgns; i++) + mpu_config(&rgns[i]); + + enable_mpu(); + + icache_enable(); +} + +void enable_caches(void) +{ + /* + * setup_mpu_regions() might have enabled Icache. So add a check + * before enabling Icache + */ + if (!icache_status()) + icache_enable(); + dcache_enable(); +}
diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S new file mode 100644 index 0000000..1773fae --- /dev/null +++ b/arch/arm/cpu/armv7/nonsec_virt.S
@@ -0,0 +1,225 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * code for switching cores into non-secure state and into HYP mode + * + * Copyright (c) 2013 Andre Przywara <andre.przywara@linaro.org> + */ + +#include <config.h> +#include <linux/linkage.h> +#include <asm/gic.h> +#include <asm/armv7.h> +#include <asm/proc-armv/ptrace.h> + +.arch_extension sec +.arch_extension virt + + .pushsection ._secure.text, "ax" + + .align 5 +/* the vector table for secure state and HYP mode */ +_monitor_vectors: + .word 0 /* reset */ + .word 0 /* undef */ + adr pc, _secure_monitor + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + +.macro is_cpu_virt_capable tmp + mrc p15, 0, \tmp, c0, c1, 1 @ read ID_PFR1 + and \tmp, \tmp, #CPUID_ARM_VIRT_MASK @ mask virtualization bits + cmp \tmp, #(1 << CPUID_ARM_VIRT_SHIFT) +.endm + +/* + * secure monitor handler + * U-Boot calls this "software interrupt" in start.S + * This is executed on a "smc" instruction, we use a "smc #0" to switch + * to non-secure state. + * r0, r1, r2: passed to the callee + * ip: target PC + */ +_secure_monitor: +#ifdef CONFIG_ARMV7_PSCI + ldr r5, =_psci_vectors @ Switch to the next monitor + mcr p15, 0, r5, c12, c0, 1 + isb + + @ Obtain a secure stack + bl psci_stack_setup + + @ Configure the PSCI backend + push {r0, r1, r2, ip} + bl psci_arch_init + pop {r0, r1, r2, ip} +#endif + +#ifdef CONFIG_ARM_ERRATA_773022 + mrc p15, 0, r5, c1, c0, 1 + orr r5, r5, #(1 << 1) + mcr p15, 0, r5, c1, c0, 1 + isb +#endif + +#ifdef CONFIG_ARM_ERRATA_774769 + mrc p15, 0, r5, c1, c0, 1 + orr r5, r5, #(1 << 25) + mcr p15, 0, r5, c1, c0, 1 + isb +#endif + + mrc p15, 0, r5, c1, c1, 0 @ read SCR + bic r5, r5, #0x4a @ clear IRQ, EA, nET bits + orr r5, r5, #0x31 @ enable NS, AW, FW bits + @ FIQ preserved for secure mode + mov r6, #SVC_MODE @ default mode is SVC + is_cpu_virt_capable r4 +#ifdef CONFIG_ARMV7_VIRT + orreq r5, r5, #0x100 @ allow HVC instruction + moveq r6, #HYP_MODE @ Enter the kernel as HYP + mrseq r3, sp_svc + msreq sp_hyp, r3 @ migrate SP +#endif + + mcr p15, 0, r5, c1, c1, 0 @ write SCR (with NS bit set) + isb + + bne 1f + + @ Reset CNTVOFF to 0 before leaving monitor mode + mrc p15, 0, r4, c0, c1, 1 @ read ID_PFR1 + ands r4, r4, #CPUID_ARM_GENTIMER_MASK @ test arch timer bits + movne r4, #0 + mcrrne p15, 4, r4, r4, c14 @ Reset CNTVOFF to zero +1: + mov lr, ip + mov ip, #(F_BIT | I_BIT | A_BIT) @ Set A, I and F + tst lr, #1 @ Check for Thumb PC + orrne ip, ip, #T_BIT @ Set T if Thumb + orr ip, ip, r6 @ Slot target mode in + msr spsr_cxfs, ip @ Set full SPSR + movs pc, lr @ ERET to non-secure + +ENTRY(_do_nonsec_entry) + mov ip, r0 + mov r0, r1 + mov r1, r2 + mov r2, r3 + smc #0 +ENDPROC(_do_nonsec_entry) + +.macro get_cbar_addr addr +#ifdef CONFIG_ARM_GIC_BASE_ADDRESS + ldr \addr, =CONFIG_ARM_GIC_BASE_ADDRESS +#else + mrc p15, 4, \addr, c15, c0, 0 @ read CBAR + bfc \addr, #0, #15 @ clear reserved bits +#endif +.endm + +.macro get_gicd_addr addr + get_cbar_addr \addr + add \addr, \addr, #GIC_DIST_OFFSET @ GIC dist i/f offset +.endm + +.macro get_gicc_addr addr, tmp + get_cbar_addr \addr + is_cpu_virt_capable \tmp + movne \tmp, #GIC_CPU_OFFSET_A9 @ GIC CPU offset for A9 + moveq \tmp, #GIC_CPU_OFFSET_A15 @ GIC CPU offset for A15/A7 + add \addr, \addr, \tmp +.endm + +#ifndef CONFIG_ARMV7_PSCI +/* + * Secondary CPUs start here and call the code for the core specific parts + * of the non-secure and HYP mode transition. The GIC distributor specific + * code has already been executed by a C function before. + * Then they go back to wfi and wait to be woken up by the kernel again. + */ +ENTRY(_smp_pen) + cpsid i + cpsid f + + bl _nonsec_init + + adr r0, _smp_pen @ do not use this address again + b smp_waitloop @ wait for IPIs, board specific +ENDPROC(_smp_pen) +#endif + +/* + * Switch a core to non-secure state. + * + * 1. initialize the GIC per-core interface + * 2. allow coprocessor access in non-secure modes + * + * Called from smp_pen by secondary cores and directly by the BSP. + * Do not assume that the stack is available and only use registers + * r0-r3 and r12. + * + * PERIPHBASE is used to get the GIC address. This could be 40 bits long, + * though, but we check this in C before calling this function. + */ +ENTRY(_nonsec_init) + get_gicd_addr r3 + + mvn r1, #0 @ all bits to 1 + str r1, [r3, #GICD_IGROUPRn] @ allow private interrupts + + get_gicc_addr r3, r1 + + mov r1, #3 @ Enable both groups + str r1, [r3, #GICC_CTLR] @ and clear all other bits + mov r1, #0xff + str r1, [r3, #GICC_PMR] @ set priority mask register + + mrc p15, 0, r0, c1, c1, 2 + movw r1, #0x3fff + movt r1, #0x0004 + orr r0, r0, r1 + mcr p15, 0, r0, c1, c1, 2 @ NSACR = all copros to non-sec + +/* The CNTFRQ register of the generic timer needs to be + * programmed in secure state. Some primary bootloaders / firmware + * omit this, so if the frequency is provided in the configuration, + * we do this here instead. + * But first check if we have the generic timer. + */ +#ifdef COUNTER_FREQUENCY + mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1 + and r0, r0, #CPUID_ARM_GENTIMER_MASK @ mask arch timer bits + cmp r0, #(1 << CPUID_ARM_GENTIMER_SHIFT) + ldreq r1, =COUNTER_FREQUENCY + mcreq p15, 0, r1, c14, c0, 0 @ write CNTFRQ +#endif + + adr r1, _monitor_vectors + mcr p15, 0, r1, c12, c0, 1 @ set MVBAR to secure vectors + isb + + mov r0, r3 @ return GICC address + bx lr +ENDPROC(_nonsec_init) + +#ifdef CONFIG_SMP_PEN_ADDR +/* void __weak smp_waitloop(unsigned previous_address); */ +ENTRY(smp_waitloop) + wfi + ldr r1, =CONFIG_SMP_PEN_ADDR @ load start address + ldr r1, [r1] +#ifdef CONFIG_PEN_ADDR_BIG_ENDIAN + rev r1, r1 +#endif + cmp r0, r1 @ make sure we dont execute this code + beq smp_waitloop @ again (due to a spurious wakeup) + mov r0, r1 + b _do_nonsec_entry +ENDPROC(smp_waitloop) +.weak smp_waitloop +#endif + + .popsection
diff --git a/arch/arm/cpu/armv7/psci-common.c b/arch/arm/cpu/armv7/psci-common.c new file mode 100644 index 0000000..a328b2b --- /dev/null +++ b/arch/arm/cpu/armv7/psci-common.c
@@ -0,0 +1,46 @@ +/* + * Common PSCI functions + * + * Copyright (C) 2016 Chen-Yu Tsai + * Author: Chen-Yu Tsai <wens@csie.org> + * + * 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 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, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <asm/armv7.h> +#include <asm/macro.h> +#include <asm/psci.h> +#include <asm/secure.h> +#include <linux/linkage.h> + +static u32 psci_target_pc[CONFIG_ARMV7_PSCI_NR_CPUS] __secure_data = { 0 }; +static u32 psci_context_id[CONFIG_ARMV7_PSCI_NR_CPUS] __secure_data = { 0 }; + +void __secure psci_save(int cpu, u32 pc, u32 context_id) +{ + psci_target_pc[cpu] = pc; + psci_context_id[cpu] = context_id; + dsb(); +} + +u32 __secure psci_get_target_pc(int cpu) +{ + return psci_target_pc[cpu]; +} + +u32 __secure psci_get_context_id(int cpu) +{ + return psci_context_id[cpu]; +} +
diff --git a/arch/arm/cpu/armv7/psci.S b/arch/arm/cpu/armv7/psci.S new file mode 100644 index 0000000..983cd90 --- /dev/null +++ b/arch/arm/cpu/armv7/psci.S
@@ -0,0 +1,347 @@ +/* + * Copyright (C) 2013,2014 - ARM Ltd + * Author: Marc Zyngier <marc.zyngier@arm.com> + * + * 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 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, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <linux/linkage.h> +#include <asm/macro.h> +#include <asm/psci.h> + + .pushsection ._secure.text, "ax" + + .arch_extension sec + + .align 5 + .globl _psci_vectors +_psci_vectors: + b default_psci_vector @ reset + b default_psci_vector @ undef + b _smc_psci @ smc + b default_psci_vector @ pabort + b default_psci_vector @ dabort + b default_psci_vector @ hyp + b default_psci_vector @ irq + b psci_fiq_enter @ fiq + +ENTRY(psci_fiq_enter) + movs pc, lr +ENDPROC(psci_fiq_enter) +.weak psci_fiq_enter + +ENTRY(default_psci_vector) + movs pc, lr +ENDPROC(default_psci_vector) +.weak default_psci_vector + +ENTRY(psci_version) +ENTRY(psci_cpu_suspend) +ENTRY(psci_cpu_off) +ENTRY(psci_cpu_on) +ENTRY(psci_affinity_info) +ENTRY(psci_migrate) +ENTRY(psci_migrate_info_type) +ENTRY(psci_migrate_info_up_cpu) +ENTRY(psci_system_off) +ENTRY(psci_system_reset) +ENTRY(psci_features) +ENTRY(psci_cpu_freeze) +ENTRY(psci_cpu_default_suspend) +ENTRY(psci_node_hw_state) +ENTRY(psci_system_suspend) +ENTRY(psci_set_suspend_mode) +ENTRY(psi_stat_residency) +ENTRY(psci_stat_count) + mov r0, #ARM_PSCI_RET_NI @ Return -1 (Not Implemented) + mov pc, lr +ENDPROC(psci_stat_count) +ENDPROC(psi_stat_residency) +ENDPROC(psci_set_suspend_mode) +ENDPROC(psci_system_suspend) +ENDPROC(psci_node_hw_state) +ENDPROC(psci_cpu_default_suspend) +ENDPROC(psci_cpu_freeze) +ENDPROC(psci_features) +ENDPROC(psci_system_reset) +ENDPROC(psci_system_off) +ENDPROC(psci_migrate_info_up_cpu) +ENDPROC(psci_migrate_info_type) +ENDPROC(psci_migrate) +ENDPROC(psci_affinity_info) +ENDPROC(psci_cpu_on) +ENDPROC(psci_cpu_off) +ENDPROC(psci_cpu_suspend) +ENDPROC(psci_version) +.weak psci_version +.weak psci_cpu_suspend +.weak psci_cpu_off +.weak psci_cpu_on +.weak psci_affinity_info +.weak psci_migrate +.weak psci_migrate_info_type +.weak psci_migrate_info_up_cpu +.weak psci_system_off +.weak psci_system_reset +.weak psci_features +.weak psci_cpu_freeze +.weak psci_cpu_default_suspend +.weak psci_node_hw_state +.weak psci_system_suspend +.weak psci_set_suspend_mode +.weak psi_stat_residency +.weak psci_stat_count + +_psci_table: + .word ARM_PSCI_FN_CPU_SUSPEND + .word psci_cpu_suspend + .word ARM_PSCI_FN_CPU_OFF + .word psci_cpu_off + .word ARM_PSCI_FN_CPU_ON + .word psci_cpu_on + .word ARM_PSCI_FN_MIGRATE + .word psci_migrate + .word ARM_PSCI_0_2_FN_PSCI_VERSION + .word psci_version + .word ARM_PSCI_0_2_FN_CPU_SUSPEND + .word psci_cpu_suspend + .word ARM_PSCI_0_2_FN_CPU_OFF + .word psci_cpu_off + .word ARM_PSCI_0_2_FN_CPU_ON + .word psci_cpu_on + .word ARM_PSCI_0_2_FN_AFFINITY_INFO + .word psci_affinity_info + .word ARM_PSCI_0_2_FN_MIGRATE + .word psci_migrate + .word ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE + .word psci_migrate_info_type + .word ARM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU + .word psci_migrate_info_up_cpu + .word ARM_PSCI_0_2_FN_SYSTEM_OFF + .word psci_system_off + .word ARM_PSCI_0_2_FN_SYSTEM_RESET + .word psci_system_reset + .word ARM_PSCI_1_0_FN_PSCI_FEATURES + .word psci_features + .word ARM_PSCI_1_0_FN_CPU_FREEZE + .word psci_cpu_freeze + .word ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND + .word psci_cpu_default_suspend + .word ARM_PSCI_1_0_FN_NODE_HW_STATE + .word psci_node_hw_state + .word ARM_PSCI_1_0_FN_SYSTEM_SUSPEND + .word psci_system_suspend + .word ARM_PSCI_1_0_FN_SET_SUSPEND_MODE + .word psci_set_suspend_mode + .word ARM_PSCI_1_0_FN_STAT_RESIDENCY + .word psi_stat_residency + .word ARM_PSCI_1_0_FN_STAT_COUNT + .word psci_stat_count + .word 0 + .word 0 + +_smc_psci: + push {r4-r7,lr} + + @ Switch to secure + mrc p15, 0, r7, c1, c1, 0 + bic r4, r7, #1 + mcr p15, 0, r4, c1, c1, 0 + isb + + adr r4, _psci_table +1: ldr r5, [r4] @ Load PSCI function ID + ldr r6, [r4, #4] @ Load target PC + cmp r5, #0 @ If reach the end, bail out + moveq r0, #ARM_PSCI_RET_INVAL @ Return -2 (Invalid) + beq 2f + cmp r0, r5 @ If not matching, try next entry + addne r4, r4, #8 + bne 1b + + blx r6 @ Execute PSCI function + + @ Switch back to non-secure +2: mcr p15, 0, r7, c1, c1, 0 + + pop {r4-r7, lr} + movs pc, lr @ Return to the kernel + +@ Requires dense and single-cluster CPU ID space +ENTRY(psci_get_cpu_id) + mrc p15, 0, r0, c0, c0, 5 /* read MPIDR */ + and r0, r0, #0xff /* return CPU ID in cluster */ + bx lr +ENDPROC(psci_get_cpu_id) +.weak psci_get_cpu_id + +/* Imported from Linux kernel */ +ENTRY(psci_v7_flush_dcache_all) + stmfd sp!, {r4-r5, r7, r9-r11, lr} + dmb @ ensure ordering with previous memory accesses + mrc p15, 1, r0, c0, c0, 1 @ read clidr + ands r3, r0, #0x7000000 @ extract loc from clidr + mov r3, r3, lsr #23 @ left align loc bit field + beq finished @ if loc is 0, then no need to clean + mov r10, #0 @ start clean at cache level 0 +flush_levels: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt skip @ skip if no cache, or just i-cache + mrs r9, cpsr @ make cssr&csidr read atomic + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + isb @ isb to sych the new cssr&csidr + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + msr cpsr_c, r9 + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + clz r5, r4 @ find bit position of way size increment + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +loop1: + mov r9, r7 @ create working copy of max index +loop2: + orr r11, r10, r4, lsl r5 @ factor way and cache number into r11 + orr r11, r11, r9, lsl r2 @ factor index number into r11 + mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way + subs r9, r9, #1 @ decrement the index + bge loop2 + subs r4, r4, #1 @ decrement the way + bge loop1 +skip: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt flush_levels +finished: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + dsb st + isb + ldmfd sp!, {r4-r5, r7, r9-r11, lr} + bx lr +ENDPROC(psci_v7_flush_dcache_all) + +ENTRY(psci_disable_smp) + mrc p15, 0, r0, c1, c0, 1 @ ACTLR + bic r0, r0, #(1 << 6) @ Clear SMP bit + mcr p15, 0, r0, c1, c0, 1 @ ACTLR + isb + dsb + bx lr +ENDPROC(psci_disable_smp) +.weak psci_disable_smp + +ENTRY(psci_enable_smp) + mrc p15, 0, r0, c1, c0, 1 @ ACTLR + orr r0, r0, #(1 << 6) @ Set SMP bit + mcr p15, 0, r0, c1, c0, 1 @ ACTLR + isb + bx lr +ENDPROC(psci_enable_smp) +.weak psci_enable_smp + +ENTRY(psci_cpu_off_common) + push {lr} + + bl psci_v7_flush_dcache_all + + clrex @ Why??? + + mrc p15, 0, r0, c1, c0, 0 @ SCTLR + bic r0, r0, #(1 << 2) @ Clear C bit + mcr p15, 0, r0, c1, c0, 0 @ SCTLR + isb + dsb + + bl psci_v7_flush_dcache_all + + clrex @ Why??? + + bl psci_disable_smp + + pop {lr} + bx lr +ENDPROC(psci_cpu_off_common) + +@ The stacks are allocated in reverse order, i.e. +@ the stack for CPU0 has the highest memory address. +@ +@ -------------------- __secure_stack_end +@ | CPU0 target PC | +@ |------------------| +@ | | +@ | CPU0 stack | +@ | | +@ |------------------| __secure_stack_end - 1KB +@ | . | +@ | . | +@ | . | +@ | . | +@ -------------------- __secure_stack_start +@ +@ This expects CPU ID in r0 and returns stack top in r0 +LENTRY(psci_get_cpu_stack_top) + @ stack top = __secure_stack_end - (cpuid << ARM_PSCI_STACK_SHIFT) + ldr r3, =__secure_stack_end + sub r0, r3, r0, LSL #ARM_PSCI_STACK_SHIFT + sub r0, r0, #4 @ Save space for target PC + bx lr +ENDPROC(psci_get_cpu_stack_top) + +@ {r0, r1, r2, ip} from _do_nonsec_entry(kernel_entry, 0, machid, r2) in +@ arch/arm/lib/bootm.c:boot_jump_linux() must remain unchanged across +@ this function. +ENTRY(psci_stack_setup) + mov r6, lr + mov r7, r0 + bl psci_get_cpu_id @ CPU ID => r0 + bl psci_get_cpu_stack_top @ stack top => r0 + mov sp, r0 + mov r0, r7 + bx r6 +ENDPROC(psci_stack_setup) + +ENTRY(psci_arch_init) + mov pc, lr +ENDPROC(psci_arch_init) +.weak psci_arch_init + +ENTRY(psci_arch_cpu_entry) + mov pc, lr +ENDPROC(psci_arch_cpu_entry) +.weak psci_arch_cpu_entry + +ENTRY(psci_cpu_entry) + bl psci_enable_smp + + bl _nonsec_init + + bl psci_stack_setup + + bl psci_arch_cpu_entry + + bl psci_get_cpu_id @ CPU ID => r0 + mov r2, r0 @ CPU ID => r2 + bl psci_get_context_id @ context id => r0 + mov r1, r0 @ context id => r1 + mov r0, r2 @ CPU ID => r0 + bl psci_get_target_pc @ target PC => r0 + b _do_nonsec_entry +ENDPROC(psci_cpu_entry) + + .popsection
diff --git a/arch/arm/cpu/armv7/s5p-common/Makefile b/arch/arm/cpu/armv7/s5p-common/Makefile new file mode 100644 index 0000000..12cf804 --- /dev/null +++ b/arch/arm/cpu/armv7/s5p-common/Makefile
@@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2009 Samsung Electronics +# Minkyu Kang <mk7.kang@samsung.com> + +obj-y += cpu_info.o +ifndef CONFIG_SPL_BUILD +obj-y += timer.o +obj-y += sromc.o +obj-$(CONFIG_PWM) += pwm.o +endif
diff --git a/arch/arm/cpu/armv7/s5p-common/cpu_info.c b/arch/arm/cpu/armv7/s5p-common/cpu_info.c new file mode 100644 index 0000000..5f4076d --- /dev/null +++ b/arch/arm/cpu/armv7/s5p-common/cpu_info.c
@@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang <mk7.kang@samsung.com> + */ +#include <common.h> +#include <fdtdec.h> +#include <asm/io.h> +#include <asm/arch/clk.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Default is s5pc100 */ +unsigned int s5p_cpu_id = 0xC100; +/* Default is EVT1 */ +unsigned int s5p_cpu_rev = 1; + +#ifdef CONFIG_ARCH_CPU_INIT +int arch_cpu_init(void) +{ + s5p_set_cpu_id(); + + return 0; +} +#endif + +u32 get_device_type(void) +{ + return s5p_cpu_id; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ + const char *cpu_model; + int len; + + /* For SoC with no real CPU ID in naming convention. */ + cpu_model = fdt_getprop(gd->fdt_blob, 0, "cpu-model", &len); + if (cpu_model) + printf("CPU: %.*s @ ", len, cpu_model); + else + printf("CPU: %s%X @ ", s5p_get_cpu_name(), s5p_cpu_id); + + print_freq(get_arm_clk(), "\n"); + + return 0; +} +#endif
diff --git a/arch/arm/cpu/armv7/s5p-common/pwm.c b/arch/arm/cpu/armv7/s5p-common/pwm.c new file mode 100644 index 0000000..6b9e865 --- /dev/null +++ b/arch/arm/cpu/armv7/s5p-common/pwm.c
@@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 Samsung Electronics + * + * Donghwa Lee <dh09.lee@samsung.com> + */ + +#include <common.h> +#include <errno.h> +#include <pwm.h> +#include <asm/io.h> +#include <asm/arch/pwm.h> +#include <asm/arch/clk.h> + +int pwm_enable(int pwm_id) +{ + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long tcon; + + tcon = readl(&pwm->tcon); + tcon |= TCON_START(pwm_id); + + writel(tcon, &pwm->tcon); + + return 0; +} + +void pwm_disable(int pwm_id) +{ + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long tcon; + + tcon = readl(&pwm->tcon); + tcon &= ~TCON_START(pwm_id); + + writel(tcon, &pwm->tcon); +} + +static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq) +{ + unsigned long tin_parent_rate; + unsigned int div; + + tin_parent_rate = get_pwm_clk(); + + for (div = 2; div <= 16; div *= 2) { + if ((tin_parent_rate / (div << 16)) < freq) + return tin_parent_rate / div; + } + + return tin_parent_rate / 16; +} + +#define NS_IN_SEC 1000000000UL + +int pwm_config(int pwm_id, int duty_ns, int period_ns) +{ + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned int offset; + unsigned long tin_rate; + unsigned long tin_ns; + unsigned long frequency; + unsigned long tcon; + unsigned long tcnt; + unsigned long tcmp; + + /* + * We currently avoid using 64bit arithmetic by using the + * fact that anything faster than 1GHz is easily representable + * by 32bits. + */ + if (period_ns > NS_IN_SEC || duty_ns > NS_IN_SEC || period_ns == 0) + return -ERANGE; + + if (duty_ns > period_ns) + return -EINVAL; + + frequency = NS_IN_SEC / period_ns; + + /* Check to see if we are changing the clock rate of the PWM */ + tin_rate = pwm_calc_tin(pwm_id, frequency); + + tin_ns = NS_IN_SEC / tin_rate; + tcnt = period_ns / tin_ns; + + /* Note, counters count down */ + tcmp = duty_ns / tin_ns; + tcmp = tcnt - tcmp; + + /* Update the PWM register block. */ + offset = pwm_id * 3; + if (pwm_id < 4) { + writel(tcnt, &pwm->tcntb0 + offset); + writel(tcmp, &pwm->tcmpb0 + offset); + } + + tcon = readl(&pwm->tcon); + tcon |= TCON_UPDATE(pwm_id); + if (pwm_id < 4) + tcon |= TCON_AUTO_RELOAD(pwm_id); + else + tcon |= TCON4_AUTO_RELOAD; + writel(tcon, &pwm->tcon); + + tcon &= ~TCON_UPDATE(pwm_id); + writel(tcon, &pwm->tcon); + + return 0; +} + +int pwm_init(int pwm_id, int div, int invert) +{ + u32 val; + const struct s5p_timer *pwm = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long ticks_per_period; + unsigned int offset, prescaler; + + /* + * Timer Freq(HZ) = + * PWM_CLK / { (prescaler_value + 1) * (divider_value) } + */ + + val = readl(&pwm->tcfg0); + if (pwm_id < 2) { + prescaler = PRESCALER_0; + val &= ~0xff; + val |= (prescaler & 0xff); + } else { + prescaler = PRESCALER_1; + val &= ~(0xff << 8); + val |= (prescaler & 0xff) << 8; + } + writel(val, &pwm->tcfg0); + val = readl(&pwm->tcfg1); + val &= ~(0xf << MUX_DIV_SHIFT(pwm_id)); + val |= (div & 0xf) << MUX_DIV_SHIFT(pwm_id); + writel(val, &pwm->tcfg1); + + if (pwm_id == 4) { + /* + * TODO(sjg): Use this as a countdown timer for now. We count + * down from the maximum value to 0, then reset. + */ + ticks_per_period = -1UL; + } else { + const unsigned long pwm_hz = 1000; + unsigned long timer_rate_hz = get_pwm_clk() / + ((prescaler + 1) * (1 << div)); + + ticks_per_period = timer_rate_hz / pwm_hz; + } + + /* set count value */ + offset = pwm_id * 3; + + writel(ticks_per_period, &pwm->tcntb0 + offset); + + val = readl(&pwm->tcon) & ~(0xf << TCON_OFFSET(pwm_id)); + if (invert && (pwm_id < 4)) + val |= TCON_INVERTER(pwm_id); + writel(val, &pwm->tcon); + + pwm_enable(pwm_id); + + return 0; +}
diff --git a/arch/arm/cpu/armv7/s5p-common/sromc.c b/arch/arm/cpu/armv7/s5p-common/sromc.c new file mode 100644 index 0000000..0fc1709 --- /dev/null +++ b/arch/arm/cpu/armv7/s5p-common/sromc.c
@@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2010 Samsung Electronics + * Naveen Krishna Ch <ch.naveen@samsung.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/sromc.h> + +/* + * s5p_config_sromc() - select the proper SROMC Bank and configure the + * band width control and bank control registers + * srom_bank - SROM + * srom_bw_conf - SMC Band witdh reg configuration value + * srom_bc_conf - SMC Bank Control reg configuration value + */ +void s5p_config_sromc(u32 srom_bank, u32 srom_bw_conf, u32 srom_bc_conf) +{ + u32 tmp; + struct s5p_sromc *srom = + (struct s5p_sromc *)samsung_get_base_sromc(); + + /* Configure SMC_BW register to handle proper SROMC bank */ + tmp = srom->bw; + tmp &= ~(0xF << (srom_bank * 4)); + tmp |= srom_bw_conf; + srom->bw = tmp; + + /* Configure SMC_BC register */ + srom->bc[srom_bank] = srom_bc_conf; +}
diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c new file mode 100644 index 0000000..0048cd8 --- /dev/null +++ b/arch/arm/cpu/armv7/s5p-common/timer.c
@@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2009 Samsung Electronics + * Heungjun Kim <riverful.kim@samsung.com> + * Inki Dae <inki.dae@samsung.com> + * Minkyu Kang <mk7.kang@samsung.com> + */ + +#include <common.h> +#include <div64.h> +#include <asm/io.h> +#include <asm/arch/pwm.h> +#include <asm/arch/clk.h> + +/* Use the old PWM interface for now */ +#undef CONFIG_DM_PWM +#include <pwm.h> + +DECLARE_GLOBAL_DATA_PTR; + +unsigned long get_current_tick(void); +static void reset_timer_masked(void); + +/* macro to read the 16 bit timer */ +static inline struct s5p_timer *s5p_get_base_timer(void) +{ + return (struct s5p_timer *)samsung_get_base_timer(); +} + +/** + * Read the countdown timer. + * + * This operates at 1MHz and counts downwards. It will wrap about every + * hour (2^32 microseconds). + * + * @return current value of timer + */ +static unsigned long timer_get_us_down(void) +{ + struct s5p_timer *const timer = s5p_get_base_timer(); + + return readl(&timer->tcnto4); +} + +int timer_init(void) +{ + /* PWM Timer 4 */ + pwm_init(4, MUX_DIV_4, 0); + pwm_config(4, 100000, 100000); + pwm_enable(4); + + /* Use this as the current monotonic time in us */ + gd->arch.timer_reset_value = 0; + + /* Use this as the last timer value we saw */ + gd->arch.lastinc = timer_get_us_down(); + reset_timer_masked(); + + return 0; +} + +/* + * timer without interrupts + */ +unsigned long get_timer(unsigned long base) +{ + unsigned long long time_ms; + + ulong now = timer_get_us_down(); + + /* + * Increment the time by the amount elapsed since the last read. + * The timer may have wrapped around, but it makes no difference to + * our arithmetic here. + */ + gd->arch.timer_reset_value += gd->arch.lastinc - now; + gd->arch.lastinc = now; + + /* Divide by 1000 to convert from us to ms */ + time_ms = gd->arch.timer_reset_value; + do_div(time_ms, 1000); + return time_ms - base; +} + +unsigned long __attribute__((no_instrument_function)) timer_get_us(void) +{ + static unsigned long base_time_us; + + struct s5p_timer *const timer = + (struct s5p_timer *)samsung_get_base_timer(); + unsigned long now_downward_us = readl(&timer->tcnto4); + + if (!base_time_us) + base_time_us = now_downward_us; + + /* Note that this timer counts downward. */ + return base_time_us - now_downward_us; +} + +/* delay x useconds */ +void __udelay(unsigned long usec) +{ + unsigned long count_value; + + count_value = timer_get_us_down(); + while ((int)(count_value - timer_get_us_down()) < (int)usec) + ; +} + +static void reset_timer_masked(void) +{ + struct s5p_timer *const timer = s5p_get_base_timer(); + + /* reset time */ + gd->arch.lastinc = readl(&timer->tcnto4); + gd->arch.tbl = 0; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +unsigned long get_tbclk(void) +{ + return CONFIG_SYS_HZ; +}
diff --git a/arch/arm/cpu/armv7/sctlr.S b/arch/arm/cpu/armv7/sctlr.S new file mode 100644 index 0000000..bd56e41 --- /dev/null +++ b/arch/arm/cpu/armv7/sctlr.S
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Routines to access the system control register + * + * Copyright (c) 2018 Heinrich Schuchardt + */ + +#include <linux/linkage.h> + +/* + * void allow_unaligned(void) - allow unaligned access + * + * This routine clears the aligned flag in the system control register. + * After calling this routine unaligned access does no longer lead to a + * data abort but is handled by the CPU. + */ +ENTRY(allow_unaligned) + mrc p15, 0, r0, c1, c0, 0 @ load system control register + bic r0, r0, #2 @ clear aligned flag + mcr p15, 0, r0, c1, c0, 0 @ write system control register + bx lr @ return +ENDPROC(allow_unaligned)
diff --git a/arch/arm/cpu/armv7/smccc-call.S b/arch/arm/cpu/armv7/smccc-call.S new file mode 100644 index 0000000..eae69e3 --- /dev/null +++ b/arch/arm/cpu/armv7/smccc-call.S
@@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#include <linux/linkage.h> + +#include <asm/opcodes-sec.h> +#include <asm/opcodes-virt.h> + + .section .text.efi_runtime + +#define UNWIND(x...) + /* + * Wrap c macros in asm macros to delay expansion until after the + * SMCCC asm macro is expanded. + */ + .macro SMCCC_SMC + __SMC(0) + .endm + + .macro SMCCC_HVC + __HVC(0) + .endm + + .macro SMCCC instr +UNWIND( .fnstart) + mov r12, sp + push {r4-r7} +UNWIND( .save {r4-r7}) + ldm r12, {r4-r7} + \instr + pop {r4-r7} + ldr r12, [sp, #(4 * 4)] + stm r12, {r0-r3} + bx lr +UNWIND( .fnend) + .endm + +/* + * void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, + * unsigned long a3, unsigned long a4, unsigned long a5, + * unsigned long a6, unsigned long a7, struct arm_smccc_res *res, + * struct arm_smccc_quirk *quirk) + */ +ENTRY(__arm_smccc_smc) + SMCCC SMCCC_SMC +ENDPROC(__arm_smccc_smc) + +/* + * void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2, + * unsigned long a3, unsigned long a4, unsigned long a5, + * unsigned long a6, unsigned long a7, struct arm_smccc_res *res, + * struct arm_smccc_quirk *quirk) + */ +ENTRY(__arm_smccc_hvc) + SMCCC SMCCC_HVC +ENDPROC(__arm_smccc_hvc)
diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S new file mode 100644 index 0000000..0cb6dd3 --- /dev/null +++ b/arch/arm/cpu/armv7/start.S
@@ -0,0 +1,342 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core + * + * Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com> + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <asm/system.h> +#include <linux/linkage.h> +#include <asm/armv7.h> + +/************************************************************************* + * + * Startup Code (reset vector) + * + * Do important init only if we don't start from memory! + * Setup memory and board specific bits prior to relocation. + * Relocate armboot to ram. Setup stack. + * + *************************************************************************/ + + .globl reset + .globl save_boot_params_ret + .type save_boot_params_ret,%function +#ifdef CONFIG_ARMV7_LPAE + .global switch_to_hypervisor_ret +#endif + +reset: + /* Allow the board to save important registers */ + b save_boot_params +save_boot_params_ret: +#ifdef CONFIG_ARMV7_LPAE +/* + * check for Hypervisor support + */ + mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1 + and r0, r0, #CPUID_ARM_VIRT_MASK @ mask virtualization bits + cmp r0, #(1 << CPUID_ARM_VIRT_SHIFT) + beq switch_to_hypervisor +switch_to_hypervisor_ret: +#endif + /* + * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode, + * except if in HYP mode already + */ + mrs r0, cpsr + and r1, r0, #0x1f @ mask mode bits + teq r1, #0x1a @ test for HYP mode + bicne r0, r0, #0x1f @ clear all mode bits + orrne r0, r0, #0x13 @ set SVC mode + orr r0, r0, #0xc0 @ disable FIQ and IRQ + msr cpsr,r0 + +/* + * Setup vector: + * (OMAP4 spl TEXT_BASE is not 32 byte aligned. + * Continue to use ROM code vector only in OMAP4 spl) + */ +#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD)) + /* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */ + mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTLR Register + bic r0, #CR_V @ V = 0 + mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTLR Register + +#ifdef CONFIG_HAS_VBAR + /* Set vector address in CP15 VBAR register */ + ldr r0, =_start + mcr p15, 0, r0, c12, c0, 0 @Set VBAR +#endif +#endif + + /* the mask ROM code should have PLL and others stable */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +#ifdef CONFIG_CPU_V7A + bl cpu_init_cp15 +#endif +#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY + bl cpu_init_crit +#endif +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + +ENTRY(c_runtime_cpu_setup) +/* + * If I-cache is enabled invalidate it + */ +#ifndef CONFIG_SYS_ICACHE_OFF + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB +#endif + + bx lr + +ENDPROC(c_runtime_cpu_setup) + +/************************************************************************* + * + * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) + * __attribute__((weak)); + * + * Stack pointer is not yet initialized at this moment + * Don't save anything to stack even if compiled with -O0 + * + *************************************************************************/ +ENTRY(save_boot_params) + b save_boot_params_ret @ back to my caller +ENDPROC(save_boot_params) + .weak save_boot_params + +#ifdef CONFIG_ARMV7_LPAE +ENTRY(switch_to_hypervisor) + b switch_to_hypervisor_ret +ENDPROC(switch_to_hypervisor) + .weak switch_to_hypervisor +#endif + +/************************************************************************* + * + * cpu_init_cp15 + * + * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless + * CONFIG_SYS_ICACHE_OFF is defined. + * + *************************************************************************/ +ENTRY(cpu_init_cp15) + /* + * Invalidate L1 I/D + */ + mov r0, #0 @ set up for MCR + mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002000 @ clear bits 13 (--V-) + bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) + orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB +#ifdef CONFIG_SYS_ICACHE_OFF + bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache +#else + orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache +#endif + mcr p15, 0, r0, c1, c0, 0 + +#ifdef CONFIG_ARM_ERRATA_716044 + mrc p15, 0, r0, c1, c0, 0 @ read system control register + orr r0, r0, #1 << 11 @ set bit #11 + mcr p15, 0, r0, c1, c0, 0 @ write system control register +#endif + +#if (defined(CONFIG_ARM_ERRATA_742230) || defined(CONFIG_ARM_ERRATA_794072)) + mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register + orr r0, r0, #1 << 4 @ set bit #4 + mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register +#endif + +#ifdef CONFIG_ARM_ERRATA_743622 + mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register + orr r0, r0, #1 << 6 @ set bit #6 + mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register +#endif + +#ifdef CONFIG_ARM_ERRATA_751472 + mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register + orr r0, r0, #1 << 11 @ set bit #11 + mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register +#endif +#ifdef CONFIG_ARM_ERRATA_761320 + mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register + orr r0, r0, #1 << 21 @ set bit #21 + mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register +#endif + +#ifdef CONFIG_ARM_ERRATA_845369 + mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register + orr r0, r0, #1 << 22 @ set bit #22 + mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register +#endif + + mov r5, lr @ Store my Caller + mrc p15, 0, r1, c0, c0, 0 @ r1 has Read Main ID Register (MIDR) + mov r3, r1, lsr #20 @ get variant field + and r3, r3, #0xf @ r3 has CPU variant + and r4, r1, #0xf @ r4 has CPU revision + mov r2, r3, lsl #4 @ shift variant field for combined value + orr r2, r4, r2 @ r2 has combined CPU variant + revision + +/* Early stack for ERRATA that needs into call C code */ +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) + ldr r0, =(CONFIG_SPL_STACK) +#else + ldr r0, =(CONFIG_SYS_INIT_SP_ADDR) +#endif + bic r0, r0, #7 /* 8-byte alignment for ABI compliance */ + mov sp, r0 + +#ifdef CONFIG_ARM_ERRATA_798870 + cmp r2, #0x30 @ Applies to lower than R3p0 + bge skip_errata_798870 @ skip if not affected rev + cmp r2, #0x20 @ Applies to including and above R2p0 + blt skip_errata_798870 @ skip if not affected rev + + mrc p15, 1, r0, c15, c0, 0 @ read l2 aux ctrl reg + orr r0, r0, #1 << 7 @ Enable hazard-detect timeout + push {r1-r5} @ Save the cpu info registers + bl v7_arch_cp15_set_l2aux_ctrl + isb @ Recommended ISB after l2actlr update + pop {r1-r5} @ Restore the cpu info - fall through +skip_errata_798870: +#endif + +#ifdef CONFIG_ARM_ERRATA_801819 + cmp r2, #0x24 @ Applies to lt including R2p4 + bgt skip_errata_801819 @ skip if not affected rev + cmp r2, #0x20 @ Applies to including and above R2p0 + blt skip_errata_801819 @ skip if not affected rev + mrc p15, 0, r0, c0, c0, 6 @ pick up REVIDR reg + and r0, r0, #1 << 3 @ check REVIDR[3] + cmp r0, #1 << 3 + beq skip_errata_801819 @ skip erratum if REVIDR[3] is set + + mrc p15, 0, r0, c1, c0, 1 @ read auxilary control register + orr r0, r0, #3 << 27 @ Disables streaming. All write-allocate + @ lines allocate in the L1 or L2 cache. + orr r0, r0, #3 << 25 @ Disables streaming. All write-allocate + @ lines allocate in the L1 cache. + push {r1-r5} @ Save the cpu info registers + bl v7_arch_cp15_set_acr + pop {r1-r5} @ Restore the cpu info - fall through +skip_errata_801819: +#endif + +#ifdef CONFIG_ARM_CORTEX_A15_CVE_2017_5715 + mrc p15, 0, r0, c1, c0, 1 @ read auxilary control register + orr r0, r0, #1 << 0 @ Enable invalidates of BTB + push {r1-r5} @ Save the cpu info registers + bl v7_arch_cp15_set_acr + pop {r1-r5} @ Restore the cpu info - fall through +#endif + +#ifdef CONFIG_ARM_ERRATA_454179 + mrc p15, 0, r0, c1, c0, 1 @ Read ACR + + cmp r2, #0x21 @ Only on < r2p1 + orrlt r0, r0, #(0x3 << 6) @ Set DBSM(BIT7) and IBE(BIT6) bits + + push {r1-r5} @ Save the cpu info registers + bl v7_arch_cp15_set_acr + pop {r1-r5} @ Restore the cpu info - fall through +#endif + +#if defined(CONFIG_ARM_ERRATA_430973) || defined (CONFIG_ARM_CORTEX_A8_CVE_2017_5715) + mrc p15, 0, r0, c1, c0, 1 @ Read ACR + +#ifdef CONFIG_ARM_CORTEX_A8_CVE_2017_5715 + orr r0, r0, #(0x1 << 6) @ Set IBE bit always to enable OS WA +#else + cmp r2, #0x21 @ Only on < r2p1 + orrlt r0, r0, #(0x1 << 6) @ Set IBE bit +#endif + push {r1-r5} @ Save the cpu info registers + bl v7_arch_cp15_set_acr + pop {r1-r5} @ Restore the cpu info - fall through +#endif + +#ifdef CONFIG_ARM_ERRATA_621766 + mrc p15, 0, r0, c1, c0, 1 @ Read ACR + + cmp r2, #0x21 @ Only on < r2p1 + orrlt r0, r0, #(0x1 << 5) @ Set L1NEON bit + + push {r1-r5} @ Save the cpu info registers + bl v7_arch_cp15_set_acr + pop {r1-r5} @ Restore the cpu info - fall through +#endif + +#ifdef CONFIG_ARM_ERRATA_725233 + mrc p15, 1, r0, c9, c0, 2 @ Read L2ACR + + cmp r2, #0x21 @ Only on < r2p1 (Cortex A8) + orrlt r0, r0, #(0x1 << 27) @ L2 PLD data forwarding disable + + push {r1-r5} @ Save the cpu info registers + bl v7_arch_cp15_set_l2aux_ctrl + pop {r1-r5} @ Restore the cpu info - fall through +#endif + +#ifdef CONFIG_ARM_ERRATA_852421 + mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register + orr r0, r0, #1 << 24 @ set bit #24 + mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register +#endif + +#ifdef CONFIG_ARM_ERRATA_852423 + mrc p15, 0, r0, c15, c0, 1 @ read diagnostic register + orr r0, r0, #1 << 12 @ set bit #12 + mcr p15, 0, r0, c15, c0, 1 @ write diagnostic register +#endif + + mov pc, r5 @ back to my caller +ENDPROC(cpu_init_cp15) + +#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && \ + !defined(CONFIG_SKIP_LOWLEVEL_INIT_ONLY) +/************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + *************************************************************************/ +ENTRY(cpu_init_crit) + /* + * Jump to board specific initialization... + * The Mask ROM will have already initialized + * basic memory. Go here to bump up clock rate and handle + * wake up conditions. + */ + b lowlevel_init @ go setup pll,mux,memory +ENDPROC(cpu_init_crit) +#endif
diff --git a/arch/arm/cpu/armv7/stv0991/Makefile b/arch/arm/cpu/armv7/stv0991/Makefile new file mode 100644 index 0000000..3be5eba --- /dev/null +++ b/arch/arm/cpu/armv7/stv0991/Makefile
@@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2014, STMicroelectronics - All Rights Reserved +# Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. + +obj-y := timer.o clock.o pinmux.o reset.o +obj-y += lowlevel.o
diff --git a/arch/arm/cpu/armv7/stv0991/clock.c b/arch/arm/cpu/armv7/stv0991/clock.c new file mode 100644 index 0000000..1e35dee --- /dev/null +++ b/arch/arm/cpu/armv7/stv0991/clock.c
@@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014, STMicroelectronics - All Rights Reserved + * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. + */ + +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/stv0991_cgu.h> +#include<asm/arch/stv0991_periph.h> + +static struct stv0991_cgu_regs *const stv0991_cgu_regs = \ + (struct stv0991_cgu_regs *) (CGU_BASE_ADDR); + +void enable_pll1(void) +{ + /* pll1 already configured for 1000Mhz, just need to enable it */ + writel(readl(&stv0991_cgu_regs->pll1_ctrl) & ~(0x01), + &stv0991_cgu_regs->pll1_ctrl); +} + +void clock_setup(int peripheral) +{ + switch (peripheral) { + case UART_CLOCK_CFG: + writel(UART_CLK_CFG, &stv0991_cgu_regs->uart_freq); + break; + case ETH_CLOCK_CFG: + enable_pll1(); + writel(ETH_CLK_CFG, &stv0991_cgu_regs->eth_freq); + + /* Clock selection for ethernet tx_clk & rx_clk*/ + writel((readl(&stv0991_cgu_regs->eth_ctrl) & ETH_CLK_MASK) + | ETH_CLK_CTRL, &stv0991_cgu_regs->eth_ctrl); + break; + case QSPI_CLOCK_CFG: + writel(QSPI_CLK_CTRL, &stv0991_cgu_regs->qspi_freq); + break; + default: + break; + } +}
diff --git a/arch/arm/cpu/armv7/stv0991/lowlevel.S b/arch/arm/cpu/armv7/stv0991/lowlevel.S new file mode 100644 index 0000000..218ac70 --- /dev/null +++ b/arch/arm/cpu/armv7/stv0991/lowlevel.S
@@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2014 stmicroelectronics + */ + +#include <config.h> +#include <linux/linkage.h> + +ENTRY(lowlevel_init) + mov pc, lr +ENDPROC(lowlevel_init)
diff --git a/arch/arm/cpu/armv7/stv0991/pinmux.c b/arch/arm/cpu/armv7/stv0991/pinmux.c new file mode 100644 index 0000000..6c44ffe --- /dev/null +++ b/arch/arm/cpu/armv7/stv0991/pinmux.c
@@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014, STMicroelectronics - All Rights Reserved + * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. + */ + +#include <asm/io.h> +#include <asm/arch/stv0991_creg.h> +#include <asm/arch/stv0991_periph.h> +#include <asm/arch/hardware.h> + +static struct stv0991_creg *const stv0991_creg = \ + (struct stv0991_creg *)CREG_BASE_ADDR; + +int stv0991_pinmux_config(int peripheral) +{ + switch (peripheral) { + case UART_GPIOC_30_31: + /* SSDA/SSCL pad muxing to UART Rx/Dx */ + writel((readl(&stv0991_creg->mux12) & GPIOC_31_MUX_MASK) | + CFG_GPIOC_31_UART_RX, + &stv0991_creg->mux12); + writel((readl(&stv0991_creg->mux12) & GPIOC_30_MUX_MASK) | + CFG_GPIOC_30_UART_TX, + &stv0991_creg->mux12); + /* SSDA/SSCL pad config to push pull*/ + writel((readl(&stv0991_creg->cfg_pad6) & GPIOC_31_MODE_MASK) | + CFG_GPIOC_31_MODE_PP, + &stv0991_creg->cfg_pad6); + writel((readl(&stv0991_creg->cfg_pad6) & GPIOC_30_MODE_MASK) | + CFG_GPIOC_30_MODE_HIGH, + &stv0991_creg->cfg_pad6); + break; + case UART_GPIOB_16_17: + /* ethernet rx_6/7 to UART Rx/Dx */ + writel((readl(&stv0991_creg->mux7) & GPIOB_17_MUX_MASK) | + CFG_GPIOB_17_UART_RX, + &stv0991_creg->mux7); + writel((readl(&stv0991_creg->mux7) & GPIOB_16_MUX_MASK) | + CFG_GPIOB_16_UART_TX, + &stv0991_creg->mux7); + break; + case ETH_GPIOB_10_31_C_0_4: + writel(readl(&stv0991_creg->mux6) & 0x000000FF, + &stv0991_creg->mux6); + writel(0x00000000, &stv0991_creg->mux7); + writel(0x00000000, &stv0991_creg->mux8); + writel(readl(&stv0991_creg->mux9) & 0xFFF00000, + &stv0991_creg->mux9); + /* Ethernet Voltage configuration to 1.8V*/ + writel((readl(&stv0991_creg->vdd_pad1) & VDD_ETH_PS_MASK) | + ETH_VDD_CFG, &stv0991_creg->vdd_pad1); + writel((readl(&stv0991_creg->vdd_pad1) & VDD_ETH_PS_MASK) | + ETH_M_VDD_CFG, &stv0991_creg->vdd_pad1); + + break; + case QSPI_CS_CLK_PAD: + writel((readl(&stv0991_creg->mux13) & FLASH_CS_NC_MASK) | + CFG_FLASH_CS_NC, &stv0991_creg->mux13); + writel((readl(&stv0991_creg->mux13) & FLASH_CLK_MASK) | + CFG_FLASH_CLK, &stv0991_creg->mux13); + default: + break; + } + return 0; +}
diff --git a/arch/arm/cpu/armv7/stv0991/reset.c b/arch/arm/cpu/armv7/stv0991/reset.c new file mode 100644 index 0000000..d4b3ab7 --- /dev/null +++ b/arch/arm/cpu/armv7/stv0991/reset.c
@@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014, STMicroelectronics - All Rights Reserved + * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/stv0991_wdru.h> +void reset_cpu(ulong ignored) +{ + puts("System is going to reboot ...\n"); + /* + * This 1 second delay will allow the above message + * to be printed before reset + */ + udelay((1000 * 1000)); + + /* Setting bit 1 of the WDRU unit will reset the SoC */ + writel(WDRU_RST_SYS, &stv0991_wd_ru_ptr->wdru_ctrl1); + + /* system will restart */ + while (1) + ; +}
diff --git a/arch/arm/cpu/armv7/stv0991/timer.c b/arch/arm/cpu/armv7/stv0991/timer.c new file mode 100644 index 0000000..d1b763d --- /dev/null +++ b/arch/arm/cpu/armv7/stv0991/timer.c
@@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014, STMicroelectronics - All Rights Reserved + * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch-stv0991/hardware.h> +#include <asm/arch-stv0991/stv0991_cgu.h> +#include <asm/arch-stv0991/stv0991_gpt.h> + +static struct stv0991_cgu_regs *const stv0991_cgu_regs = \ + (struct stv0991_cgu_regs *) (CGU_BASE_ADDR); + +#define READ_TIMER() (readl(&gpt1_regs_ptr->cnt) & GPT_FREE_RUNNING) +#define GPT_RESOLUTION (CONFIG_STV0991_HZ_CLOCK / CONFIG_STV0991_HZ) + +DECLARE_GLOBAL_DATA_PTR; + +#define timestamp gd->arch.tbl +#define lastdec gd->arch.lastinc + +static ulong get_timer_masked(void); + +int timer_init(void) +{ + /* Timer1 clock configuration */ + writel(TIMER1_CLK_CFG, &stv0991_cgu_regs->tim_freq); + writel(readl(&stv0991_cgu_regs->cgu_enable_2) | + TIMER1_CLK_EN, &stv0991_cgu_regs->cgu_enable_2); + + /* Stop the timer */ + writel(readl(&gpt1_regs_ptr->cr1) & ~GPT_CR1_CEN, &gpt1_regs_ptr->cr1); + writel(GPT_PRESCALER_128, &gpt1_regs_ptr->psc); + /* Configure timer for auto-reload */ + writel(readl(&gpt1_regs_ptr->cr1) | GPT_MODE_AUTO_RELOAD, + &gpt1_regs_ptr->cr1); + + /* load value for free running */ + writel(GPT_FREE_RUNNING, &gpt1_regs_ptr->arr); + + /* start timer */ + writel(readl(&gpt1_regs_ptr->cr1) | GPT_CR1_CEN, + &gpt1_regs_ptr->cr1); + + /* Reset the timer */ + lastdec = READ_TIMER(); + timestamp = 0; + + return 0; +} + +/* + * timer without interrupts + */ +ulong get_timer(ulong base) +{ + return (get_timer_masked() / GPT_RESOLUTION) - base; +} + +void __udelay(unsigned long usec) +{ + ulong tmo; + ulong start = get_timer_masked(); + ulong tenudelcnt = CONFIG_STV0991_HZ_CLOCK / (1000 * 100); + ulong rndoff; + + rndoff = (usec % 10) ? 1 : 0; + + /* tenudelcnt timer tick gives 10 microsecconds delay */ + tmo = ((usec / 10) + rndoff) * tenudelcnt; + + while ((ulong) (get_timer_masked() - start) < tmo) + ; +} + +static ulong get_timer_masked(void) +{ + ulong now = READ_TIMER(); + + if (now >= lastdec) { + /* normal mode */ + timestamp += now - lastdec; + } else { + /* we have an overflow ... */ + timestamp += now + GPT_FREE_RUNNING - lastdec; + } + lastdec = now; + + return timestamp; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CONFIG_STV0991_HZ; +}
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile new file mode 100644 index 0000000..1d40d6a --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net> +# +# Based on some other Makefile +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +obj-y += timer.o + +obj-$(CONFIG_MACH_SUN6I) += tzpc.o +obj-$(CONFIG_MACH_SUN8I_H3) += tzpc.o + +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_ARMV7_PSCI) += psci.o +endif + +ifdef CONFIG_SPL_BUILD +obj-y += fel_utils.o +endif
diff --git a/arch/arm/cpu/armv7/sunxi/fel_utils.S b/arch/arm/cpu/armv7/sunxi/fel_utils.S new file mode 100644 index 0000000..b231075 --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/fel_utils.S
@@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Utility functions for FEL mode. + * + * Copyright (c) 2015 Google, Inc + */ + +#include <asm-offsets.h> +#include <config.h> +#include <asm/system.h> +#include <linux/linkage.h> + +ENTRY(save_boot_params) + ldr r0, =fel_stash + str sp, [r0, #0] + str lr, [r0, #4] + mrs lr, cpsr @ Read CPSR + str lr, [r0, #8] + mrc p15, 0, lr, c1, c0, 0 @ Read CP15 SCTLR Register + str lr, [r0, #12] + mrc p15, 0, lr, c12, c0, 0 @ Read VBAR + str lr, [r0, #16] + mrc p15, 0, lr, c1, c0, 0 @ Read CP15 Control Register + str lr, [r0, #20] + b save_boot_params_ret +ENDPROC(save_boot_params) + +ENTRY(return_to_fel) + mov sp, r0 + mov lr, r1 + ldr r0, =fel_stash + ldr r1, [r0, #20] + mcr p15, 0, r1, c1, c0, 0 @ Write CP15 Control Register + ldr r1, [r0, #16] + mcr p15, 0, r1, c12, c0, 0 @ Write VBAR + ldr r1, [r0, #12] + mcr p15, 0, r1, c1, c0, 0 @ Write CP15 SCTLR Register + ldr r1, [r0, #8] + msr cpsr, r1 @ Write CPSR + bx lr +ENDPROC(return_to_fel)
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c new file mode 100644 index 0000000..f3e8f99 --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -0,0 +1,312 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016 + * Author: Chen-Yu Tsai <wens@csie.org> + * + * Based on assembly code by Marc Zyngier <marc.zyngier@arm.com>, + * which was based on code by Carl van Schaik <carl@ok-labs.com>. + */ +#include <config.h> +#include <common.h> + +#include <asm/arch/cpu.h> +#include <asm/arch/cpucfg.h> +#include <asm/arch/prcm.h> +#include <asm/armv7.h> +#include <asm/gic.h> +#include <asm/io.h> +#include <asm/psci.h> +#include <asm/secure.h> +#include <asm/system.h> + +#include <linux/bitops.h> + +#define __irq __attribute__ ((interrupt ("IRQ"))) + +#define GICD_BASE (SUNXI_GIC400_BASE + GIC_DIST_OFFSET) +#define GICC_BASE (SUNXI_GIC400_BASE + GIC_CPU_OFFSET_A15) + +/* + * R40 is different from other single cluster SoCs. + * + * The power clamps are located in the unused space after the per-core + * reset controls for core 3. The secondary core entry address register + * is in the SRAM controller address range. + */ +#define SUN8I_R40_PWROFF (0x110) +#define SUN8I_R40_PWR_CLAMP(cpu) (0x120 + (cpu) * 0x4) +#define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0 (0xbc) + +static void __secure cp15_write_cntp_tval(u32 tval) +{ + asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval)); +} + +static void __secure cp15_write_cntp_ctl(u32 val) +{ + asm volatile ("mcr p15, 0, %0, c14, c2, 1" : : "r" (val)); +} + +static u32 __secure cp15_read_cntp_ctl(void) +{ + u32 val; + + asm volatile ("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); + + return val; +} + +#define ONE_MS (COUNTER_FREQUENCY / 1000) + +static void __secure __mdelay(u32 ms) +{ + u32 reg = ONE_MS * ms; + + cp15_write_cntp_tval(reg); + isb(); + cp15_write_cntp_ctl(3); + + do { + isb(); + reg = cp15_read_cntp_ctl(); + } while (!(reg & BIT(2))); + + cp15_write_cntp_ctl(0); + isb(); +} + +static void __secure clamp_release(u32 __maybe_unused *clamp) +{ +#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \ + defined(CONFIG_MACH_SUN8I_H3) || \ + defined(CONFIG_MACH_SUN8I_R40) + u32 tmp = 0x1ff; + do { + tmp >>= 1; + writel(tmp, clamp); + } while (tmp); + + __mdelay(10); +#endif +} + +static void __secure clamp_set(u32 __maybe_unused *clamp) +{ +#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \ + defined(CONFIG_MACH_SUN8I_H3) || \ + defined(CONFIG_MACH_SUN8I_R40) + writel(0xff, clamp); +#endif +} + +static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on, + int cpu) +{ + if (on) { + /* Release power clamp */ + clamp_release(clamp); + + /* Clear power gating */ + clrbits_le32(pwroff, BIT(cpu)); + } else { + /* Set power gating */ + setbits_le32(pwroff, BIT(cpu)); + + /* Activate power clamp */ + clamp_set(clamp); + } +} + +#ifdef CONFIG_MACH_SUN8I_R40 +/* secondary core entry address is programmed differently on R40 */ +static void __secure sunxi_set_entry_address(void *entry) +{ + writel((u32)entry, + SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0); +} +#else +static void __secure sunxi_set_entry_address(void *entry) +{ + struct sunxi_cpucfg_reg *cpucfg = + (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE; + + writel((u32)entry, &cpucfg->priv0); +} +#endif + +#ifdef CONFIG_MACH_SUN7I +/* sun7i (A20) is different from other single cluster SoCs */ +static void __secure sunxi_cpu_set_power(int __always_unused cpu, bool on) +{ + struct sunxi_cpucfg_reg *cpucfg = + (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE; + + sunxi_power_switch(&cpucfg->cpu1_pwr_clamp, &cpucfg->cpu1_pwroff, + on, 0); +} +#elif defined CONFIG_MACH_SUN8I_R40 +static void __secure sunxi_cpu_set_power(int cpu, bool on) +{ + struct sunxi_cpucfg_reg *cpucfg = + (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE; + + sunxi_power_switch((void *)cpucfg + SUN8I_R40_PWR_CLAMP(cpu), + (void *)cpucfg + SUN8I_R40_PWROFF, + on, 0); +} +#else /* ! CONFIG_MACH_SUN7I && ! CONFIG_MACH_SUN8I_R40 */ +static void __secure sunxi_cpu_set_power(int cpu, bool on) +{ + struct sunxi_prcm_reg *prcm = + (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE; + + sunxi_power_switch(&prcm->cpu_pwr_clamp[cpu], &prcm->cpu_pwroff, + on, cpu); +} +#endif /* CONFIG_MACH_SUN7I */ + +void __secure sunxi_cpu_power_off(u32 cpuid) +{ + struct sunxi_cpucfg_reg *cpucfg = + (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE; + u32 cpu = cpuid & 0x3; + + /* Wait for the core to enter WFI */ + while (1) { + if (readl(&cpucfg->cpu[cpu].status) & BIT(2)) + break; + __mdelay(1); + } + + /* Assert reset on target CPU */ + writel(0, &cpucfg->cpu[cpu].rst); + + /* Lock CPU (Disable external debug access) */ + clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu)); + + /* Power down CPU */ + sunxi_cpu_set_power(cpuid, false); + + /* Unlock CPU (Disable external debug access) */ + setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu)); +} + +static u32 __secure cp15_read_scr(void) +{ + u32 scr; + + asm volatile ("mrc p15, 0, %0, c1, c1, 0" : "=r" (scr)); + + return scr; +} + +static void __secure cp15_write_scr(u32 scr) +{ + asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (scr)); + isb(); +} + +/* + * Although this is an FIQ handler, the FIQ is processed in monitor mode, + * which means there's no FIQ banked registers. This is the same as IRQ + * mode, so use the IRQ attribute to ask the compiler to handler entry + * and return. + */ +void __secure __irq psci_fiq_enter(void) +{ + u32 scr, reg, cpu; + + /* Switch to secure mode */ + scr = cp15_read_scr(); + cp15_write_scr(scr & ~BIT(0)); + + /* Validate reason based on IAR and acknowledge */ + reg = readl(GICC_BASE + GICC_IAR); + + /* Skip spurious interrupts 1022 and 1023 */ + if (reg == 1023 || reg == 1022) + goto out; + + /* End of interrupt */ + writel(reg, GICC_BASE + GICC_EOIR); + dsb(); + + /* Get CPU number */ + cpu = (reg >> 10) & 0x7; + + /* Power off the CPU */ + sunxi_cpu_power_off(cpu); + +out: + /* Restore security level */ + cp15_write_scr(scr); +} + +int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc, + u32 context_id) +{ + struct sunxi_cpucfg_reg *cpucfg = + (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE; + u32 cpu = (mpidr & 0x3); + + /* store target PC and context id */ + psci_save(cpu, pc, context_id); + + /* Set secondary core power on PC */ + sunxi_set_entry_address(&psci_cpu_entry); + + /* Assert reset on target CPU */ + writel(0, &cpucfg->cpu[cpu].rst); + + /* Invalidate L1 cache */ + clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu)); + + /* Lock CPU (Disable external debug access) */ + clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu)); + + /* Power up target CPU */ + sunxi_cpu_set_power(cpu, true); + + /* De-assert reset on target CPU */ + writel(BIT(1) | BIT(0), &cpucfg->cpu[cpu].rst); + + /* Unlock CPU (Disable external debug access) */ + setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu)); + + return ARM_PSCI_RET_SUCCESS; +} + +void __secure psci_cpu_off(void) +{ + psci_cpu_off_common(); + + /* Ask CPU0 via SGI15 to pull the rug... */ + writel(BIT(16) | 15, GICD_BASE + GICD_SGIR); + dsb(); + + /* Wait to be turned off */ + while (1) + wfi(); +} + +void __secure psci_arch_init(void) +{ + u32 reg; + + /* SGI15 as Group-0 */ + clrbits_le32(GICD_BASE + GICD_IGROUPRn, BIT(15)); + + /* Set SGI15 priority to 0 */ + writeb(0, GICD_BASE + GICD_IPRIORITYRn + 15); + + /* Be cool with non-secure */ + writel(0xff, GICC_BASE + GICC_PMR); + + /* Switch FIQEn on */ + setbits_le32(GICC_BASE + GICC_CTLR, BIT(3)); + + reg = cp15_read_scr(); + reg |= BIT(2); /* Enable FIQ in monitor mode */ + reg &= ~BIT(0); /* Secure mode */ + cp15_write_scr(reg); +}
diff --git a/arch/arm/cpu/armv7/sunxi/start.c b/arch/arm/cpu/armv7/sunxi/start.c new file mode 100644 index 0000000..6b392fa --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/start.c
@@ -0,0 +1 @@ +/* Intentionally empty. Only needed to get FEL SPL link line right */
diff --git a/arch/arm/cpu/armv7/sunxi/timer.c b/arch/arm/cpu/armv7/sunxi/timer.c new file mode 100644 index 0000000..304c1ac --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/timer.c
@@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2007-2011 + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Tom Cubie <tangliang@allwinnertech.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/timer.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define TIMER_MODE (0x0 << 7) /* continuous mode */ +#define TIMER_DIV (0x0 << 4) /* pre scale 1 */ +#define TIMER_SRC (0x1 << 2) /* osc24m */ +#define TIMER_RELOAD (0x1 << 1) /* reload internal value */ +#define TIMER_EN (0x1 << 0) /* enable timer */ + +#define TIMER_CLOCK (24 * 1000 * 1000) +#define COUNT_TO_USEC(x) ((x) / 24) +#define USEC_TO_COUNT(x) ((x) * 24) +#define TICKS_PER_HZ (TIMER_CLOCK / CONFIG_SYS_HZ) +#define TICKS_TO_HZ(x) ((x) / TICKS_PER_HZ) + +#define TIMER_LOAD_VAL 0xffffffff + +#define TIMER_NUM 0 /* we use timer 0 */ + +/* read the 32-bit timer */ +static ulong read_timer(void) +{ + struct sunxi_timer_reg *timers = + (struct sunxi_timer_reg *)SUNXI_TIMER_BASE; + struct sunxi_timer *timer = &timers->timer[TIMER_NUM]; + + /* + * The hardware timer counts down, therefore we invert to + * produce an incrementing timer. + */ + return ~readl(&timer->val); +} + +/* init timer register */ +int timer_init(void) +{ + struct sunxi_timer_reg *timers = + (struct sunxi_timer_reg *)SUNXI_TIMER_BASE; + struct sunxi_timer *timer = &timers->timer[TIMER_NUM]; + writel(TIMER_LOAD_VAL, &timer->inter); + writel(TIMER_MODE | TIMER_DIV | TIMER_SRC | TIMER_RELOAD | TIMER_EN, + &timer->ctl); + + return 0; +} + +/* timer without interrupts */ +static ulong get_timer_masked(void) +{ + /* current tick value */ + ulong now = TICKS_TO_HZ(read_timer()); + + if (now >= gd->arch.lastinc) /* normal (non rollover) */ + gd->arch.tbl += (now - gd->arch.lastinc); + else { + /* rollover */ + gd->arch.tbl += (TICKS_TO_HZ(TIMER_LOAD_VAL) + - gd->arch.lastinc) + now; + } + gd->arch.lastinc = now; + + return gd->arch.tbl; +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* delay x useconds */ +void __udelay(unsigned long usec) +{ + long tmo = USEC_TO_COUNT(usec); + ulong now, last = read_timer(); + + while (tmo > 0) { + now = read_timer(); + if (now > last) /* normal (non rollover) */ + tmo -= now - last; + else /* rollover */ + tmo -= TIMER_LOAD_VAL - last + now; + last = now; + } +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ; +}
diff --git a/arch/arm/cpu/armv7/sunxi/tzpc.c b/arch/arm/cpu/armv7/sunxi/tzpc.c new file mode 100644 index 0000000..0c86a21 --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/tzpc.c
@@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2015 Chen-Yu Tsai <wens@csie.org> + */ + +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/tzpc.h> + +/* Configure Trust Zone Protection Controller */ +void tzpc_init(void) +{ + struct sunxi_tzpc *tzpc = (struct sunxi_tzpc *)SUNXI_TZPC_BASE; + +#ifdef CONFIG_MACH_SUN6I + /* Enable non-secure access to the RTC */ + writel(SUN6I_TZPC_DECPORT0_RTC, &tzpc->decport0_set); +#endif + +#ifdef CONFIG_MACH_SUN8I_H3 + /* Enable non-secure access to all peripherals */ + writel(SUN8I_H3_TZPC_DECPORT0_ALL, &tzpc->decport0_set); + writel(SUN8I_H3_TZPC_DECPORT1_ALL, &tzpc->decport1_set); + writel(SUN8I_H3_TZPC_DECPORT2_ALL, &tzpc->decport2_set); +#endif +}
diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds new file mode 100644 index 0000000..5d7f3f5 --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
@@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2012 + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * Tom Cubie <tangliang@allwinnertech.com> + * + * Based on omap-common/u-boot-spl.lds: + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + */ +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text : + { + __start = .; + *(.vectors) + arch/arm/cpu/armv7/start.o (.text) + *(.text*) + } > .sram + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram + + . = ALIGN(4); + .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } > .sram + + . = ALIGN(4); + __image_copy_end = .; + _end = .; + + .bss : + { + . = ALIGN(4); + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } > .sdram +}
diff --git a/arch/arm/cpu/armv7/syslib.c b/arch/arm/cpu/armv7/syslib.c new file mode 100644 index 0000000..7e29636 --- /dev/null +++ b/arch/arm/cpu/armv7/syslib.c
@@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + */ + +#include <common.h> +#include <asm/io.h> + +/************************************************************ + * sdelay() - simple spin loop. Will be constant time as + * its generally used in bypass conditions only. This + * is necessary until timers are accessible. + * + * not inline to increase chances its in cache when called + *************************************************************/ +void sdelay(unsigned long loops) +{ + __asm__ volatile ("1:\n" "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0"(loops)); +} + +/********************************************************************* + * wait_on_value() - common routine to allow waiting for changes in + * volatile regs. + *********************************************************************/ +u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr, + u32 bound) +{ + u32 i = 0, val; + do { + ++i; + val = readl((u32)read_addr) & read_bit_mask; + if (val == match_value) + return 1; + if (i == bound) + return 0; + } while (1); +}
diff --git a/arch/arm/cpu/armv7/vf610/Kconfig b/arch/arm/cpu/armv7/vf610/Kconfig new file mode 100644 index 0000000..764d1fb --- /dev/null +++ b/arch/arm/cpu/armv7/vf610/Kconfig
@@ -0,0 +1,37 @@ +if ARCH_VF610 + +config VF610 + bool + default y + +choice + prompt "Vybrid board select" + +config TARGET_VF610TWR + bool "TWR-VF65GS10-DS5" + +config TARGET_COLIBRI_VF + bool "Colibri VF50/61" + select BOARD_LATE_INIT + +config TARGET_PCM052 + bool "PCM-052" + select SYS_FSL_ERRATUM_ESDHC135 + select SYS_FSL_ERRATUM_ESDHC_A001 + +config TARGET_BK4R1 + bool "BK4r1" + select SYS_FSL_ERRATUM_ESDHC135 + select SYS_FSL_ERRATUM_ESDHC_A001 + +endchoice + +config SYS_SOC + default "vf610" + +source "board/freescale/vf610twr/Kconfig" +source "board/phytec/pcm052/Kconfig" +source "board/toradex/colibri_vf/Kconfig" + +endif +
diff --git a/arch/arm/cpu/armv7/vf610/Makefile b/arch/arm/cpu/armv7/vf610/Makefile new file mode 100644 index 0000000..b5b479b --- /dev/null +++ b/arch/arm/cpu/armv7/vf610/Makefile
@@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2013 Freescale Semiconductor, Inc. + +obj-y += generic.o +obj-y += timer.o + +MKIMAGEFLAGS_u-boot.vyb = -T vybridimage + +u-boot.vyb: u-boot.imx + $(call if_changed,mkimage)
diff --git a/arch/arm/cpu/armv7/vf610/generic.c b/arch/arm/cpu/armv7/vf610/generic.c new file mode 100644 index 0000000..cbd3391 --- /dev/null +++ b/arch/arm/cpu/armv7/vf610/generic.c
@@ -0,0 +1,377 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/crm_regs.h> +#include <asm/mach-imx/sys_proto.h> +#include <netdev.h> +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> +#endif + +#ifdef CONFIG_FSL_ESDHC +DECLARE_GLOBAL_DATA_PTR; +#endif + +static char soc_type[] = "xx0"; + +#ifdef CONFIG_MXC_OCOTP +void enable_ocotp_clk(unsigned char enable) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 reg; + + reg = readl(&ccm->ccgr6); + if (enable) + reg |= CCM_CCGR6_OCOTP_CTRL_MASK; + else + reg &= ~CCM_CCGR6_OCOTP_CTRL_MASK; + writel(reg, &ccm->ccgr6); +} +#endif + +static u32 get_mcu_main_clk(void) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 ccm_ccsr, ccm_cacrr, armclk_div; + u32 sysclk_sel, pll_pfd_sel = 0; + u32 freq = 0; + + ccm_ccsr = readl(&ccm->ccsr); + sysclk_sel = ccm_ccsr & CCM_CCSR_SYS_CLK_SEL_MASK; + sysclk_sel >>= CCM_CCSR_SYS_CLK_SEL_OFFSET; + + ccm_cacrr = readl(&ccm->cacrr); + armclk_div = ccm_cacrr & CCM_CACRR_ARM_CLK_DIV_MASK; + armclk_div >>= CCM_CACRR_ARM_CLK_DIV_OFFSET; + armclk_div += 1; + + switch (sysclk_sel) { + case 0: + freq = FASE_CLK_FREQ; + break; + case 1: + freq = SLOW_CLK_FREQ; + break; + case 2: + pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL2_PFD_CLK_SEL_MASK; + pll_pfd_sel >>= CCM_CCSR_PLL2_PFD_CLK_SEL_OFFSET; + if (pll_pfd_sel == 0) + freq = PLL2_MAIN_FREQ; + else if (pll_pfd_sel == 1) + freq = PLL2_PFD1_FREQ; + else if (pll_pfd_sel == 2) + freq = PLL2_PFD2_FREQ; + else if (pll_pfd_sel == 3) + freq = PLL2_PFD3_FREQ; + else if (pll_pfd_sel == 4) + freq = PLL2_PFD4_FREQ; + break; + case 3: + freq = PLL2_MAIN_FREQ; + break; + case 4: + pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL1_PFD_CLK_SEL_MASK; + pll_pfd_sel >>= CCM_CCSR_PLL1_PFD_CLK_SEL_OFFSET; + if (pll_pfd_sel == 0) + freq = PLL1_MAIN_FREQ; + else if (pll_pfd_sel == 1) + freq = PLL1_PFD1_FREQ; + else if (pll_pfd_sel == 2) + freq = PLL1_PFD2_FREQ; + else if (pll_pfd_sel == 3) + freq = PLL1_PFD3_FREQ; + else if (pll_pfd_sel == 4) + freq = PLL1_PFD4_FREQ; + break; + case 5: + freq = PLL3_MAIN_FREQ; + break; + default: + printf("unsupported system clock select\n"); + } + + return freq / armclk_div; +} + +static u32 get_bus_clk(void) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 ccm_cacrr, busclk_div; + + ccm_cacrr = readl(&ccm->cacrr); + + busclk_div = ccm_cacrr & CCM_CACRR_BUS_CLK_DIV_MASK; + busclk_div >>= CCM_CACRR_BUS_CLK_DIV_OFFSET; + busclk_div += 1; + + return get_mcu_main_clk() / busclk_div; +} + +static u32 get_ipg_clk(void) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 ccm_cacrr, ipgclk_div; + + ccm_cacrr = readl(&ccm->cacrr); + + ipgclk_div = ccm_cacrr & CCM_CACRR_IPG_CLK_DIV_MASK; + ipgclk_div >>= CCM_CACRR_IPG_CLK_DIV_OFFSET; + ipgclk_div += 1; + + return get_bus_clk() / ipgclk_div; +} + +static u32 get_uart_clk(void) +{ + return get_ipg_clk(); +} + +static u32 get_sdhc_clk(void) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 ccm_cscmr1, ccm_cscdr2, sdhc_clk_sel, sdhc_clk_div; + u32 freq = 0; + + ccm_cscmr1 = readl(&ccm->cscmr1); + sdhc_clk_sel = ccm_cscmr1 & CCM_CSCMR1_ESDHC1_CLK_SEL_MASK; + sdhc_clk_sel >>= CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET; + + ccm_cscdr2 = readl(&ccm->cscdr2); + sdhc_clk_div = ccm_cscdr2 & CCM_CSCDR2_ESDHC1_CLK_DIV_MASK; + sdhc_clk_div >>= CCM_CSCDR2_ESDHC1_CLK_DIV_OFFSET; + sdhc_clk_div += 1; + + switch (sdhc_clk_sel) { + case 0: + freq = PLL3_MAIN_FREQ; + break; + case 1: + freq = PLL3_PFD3_FREQ; + break; + case 2: + freq = PLL1_PFD3_FREQ; + break; + case 3: + freq = get_bus_clk(); + break; + } + + return freq / sdhc_clk_div; +} + +u32 get_fec_clk(void) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + u32 ccm_cscmr2, rmii_clk_sel; + u32 freq = 0; + + ccm_cscmr2 = readl(&ccm->cscmr2); + rmii_clk_sel = ccm_cscmr2 & CCM_CSCMR2_RMII_CLK_SEL_MASK; + rmii_clk_sel >>= CCM_CSCMR2_RMII_CLK_SEL_OFFSET; + + switch (rmii_clk_sel) { + case 0: + freq = ENET_EXTERNAL_CLK; + break; + case 1: + freq = AUDIO_EXTERNAL_CLK; + break; + case 2: + freq = PLL5_MAIN_FREQ; + break; + case 3: + freq = PLL5_MAIN_FREQ / 2; + break; + } + + return freq; +} + +static u32 get_i2c_clk(void) +{ + return get_ipg_clk(); +} + +static u32 get_dspi_clk(void) +{ + return get_ipg_clk(); +} + +u32 get_lpuart_clk(void) +{ + return get_uart_clk(); +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return get_mcu_main_clk(); + case MXC_BUS_CLK: + return get_bus_clk(); + case MXC_IPG_CLK: + return get_ipg_clk(); + case MXC_UART_CLK: + return get_uart_clk(); + case MXC_ESDHC_CLK: + return get_sdhc_clk(); + case MXC_FEC_CLK: + return get_fec_clk(); + case MXC_I2C_CLK: + return get_i2c_clk(); + case MXC_DSPI_CLK: + return get_dspi_clk(); + default: + break; + } + return -1; +} + +/* Dump some core clocks */ +int do_vf610_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + printf("\n"); + printf("cpu clock : %8d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("bus clock : %8d MHz\n", mxc_get_clock(MXC_BUS_CLK) / 1000000); + printf("ipg clock : %8d MHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000000); + + return 0; +} + +U_BOOT_CMD( + clocks, CONFIG_SYS_MAXARGS, 1, do_vf610_showclocks, + "display clocks", + "" +); + +#ifdef CONFIG_FEC_MXC +void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) +{ + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[4]; + struct fuse_bank4_regs *fuse = + (struct fuse_bank4_regs *)bank->fuse_regs; + + u32 value = readl(&fuse->mac_addr0); + mac[0] = (value >> 8); + mac[1] = value; + + value = readl(&fuse->mac_addr1); + mac[2] = value >> 24; + mac[3] = value >> 16; + mac[4] = value >> 8; + mac[5] = value; +} +#endif + +u32 get_cpu_rev(void) +{ + return MXC_CPU_VF610 << 12; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +static char *get_reset_cause(void) +{ + u32 cause; + struct src *src_regs = (struct src *)SRC_BASE_ADDR; + + cause = readl(&src_regs->srsr); + writel(cause, &src_regs->srsr); + + if (cause & SRC_SRSR_POR_RST) + return "POWER ON RESET"; + else if (cause & SRC_SRSR_WDOG_A5) + return "WDOG A5"; + else if (cause & SRC_SRSR_WDOG_M4) + return "WDOG M4"; + else if (cause & SRC_SRSR_JTAG_RST) + return "JTAG HIGH-Z"; + else if (cause & SRC_SRSR_SW_RST) + return "SW RESET"; + else if (cause & SRC_SRSR_RESETB) + return "EXTERNAL RESET"; + else + return "unknown reset"; +} + +int print_cpuinfo(void) +{ + printf("CPU: Freescale Vybrid VF%s at %d MHz\n", + soc_type, mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("Reset cause: %s\n", get_reset_cause()); + + return 0; +} +#endif + +int arch_cpu_init(void) +{ + struct mscm *mscm = (struct mscm *)MSCM_BASE_ADDR; + + soc_type[0] = mscm->cpxcount ? '6' : '5'; /*Dual Core => VF6x0 */ + soc_type[1] = mscm->cpxcfg1 ? '1' : '0'; /* L2 Cache => VFx10 */ + + return 0; +} + +#ifdef CONFIG_ARCH_MISC_INIT +int arch_misc_init(void) +{ + char soc[6]; + + strcpy(soc, "vf"); + strcat(soc, soc_type); + env_set("soc", soc); + + return 0; +} +#endif + +int cpu_eth_init(bd_t *bis) +{ + int rc = -ENODEV; + +#if defined(CONFIG_FEC_MXC) + rc = fecmxc_initialize(bis); +#endif + + return rc; +} + +#ifdef CONFIG_FSL_ESDHC +int cpu_mmc_init(bd_t *bis) +{ + return fsl_esdhc_mmc_init(bis); +} +#endif + +int get_clocks(void) +{ +#ifdef CONFIG_FSL_ESDHC + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); +#endif + return 0; +} + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ +#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) + enum dcache_option option = DCACHE_WRITETHROUGH; +#else + enum dcache_option option = DCACHE_WRITEBACK; +#endif + dcache_enable(); + icache_enable(); + + /* Enable caching on OCRAM */ + mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR, IRAM_SIZE, option); +} +#endif
diff --git a/arch/arm/cpu/armv7/vf610/timer.c b/arch/arm/cpu/armv7/vf610/timer.c new file mode 100644 index 0000000..821a279 --- /dev/null +++ b/arch/arm/cpu/armv7/vf610/timer.c
@@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <div64.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> + +static struct pit_reg *cur_pit = (struct pit_reg *)PIT_BASE_ADDR; + +DECLARE_GLOBAL_DATA_PTR; + +#define TIMER_LOAD_VAL 0xffffffff + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, mxc_get_clock(MXC_IPG_CLK)); + + return tick; +} + +static inline unsigned long long us_to_tick(unsigned long long usec) +{ + usec = usec * mxc_get_clock(MXC_IPG_CLK) + 999999; + do_div(usec, 1000000); + + return usec; +} + +int timer_init(void) +{ + __raw_writel(0, &cur_pit->mcr); + + __raw_writel(TIMER_LOAD_VAL, &cur_pit->ldval1); + __raw_writel(0, &cur_pit->tctrl1); + __raw_writel(1, &cur_pit->tctrl1); + + gd->arch.tbl = 0; + gd->arch.tbu = 0; + + return 0; +} + +unsigned long long get_ticks(void) +{ + ulong now = TIMER_LOAD_VAL - __raw_readl(&cur_pit->cval1); + + /* increment tbu if tbl has rolled over */ + if (now < gd->arch.tbl) + gd->arch.tbu++; + gd->arch.tbl = now; + + return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl; +} + +ulong get_timer(ulong base) +{ + return tick_to_time(get_ticks()) - base; +} + +/* delay x useconds AND preserve advance timstamp value */ +void __udelay(unsigned long usec) +{ + unsigned long long start; + ulong tmo; + + start = get_ticks(); /* get current timestamp */ + tmo = us_to_tick(usec); /* convert usecs to ticks */ + while ((get_ticks() - start) < tmo) + ; /* loop till time has passed */ +} + +/* + * 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 mxc_get_clock(MXC_IPG_CLK); +}
diff --git a/arch/arm/cpu/armv7/virt-dt.c b/arch/arm/cpu/armv7/virt-dt.c new file mode 100644 index 0000000..204187c --- /dev/null +++ b/arch/arm/cpu/armv7/virt-dt.c
@@ -0,0 +1,70 @@ +/* + * Copyright (C) 2013 - ARM Ltd + * Author: Marc Zyngier <marc.zyngier@arm.com> + * + * 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 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, see <http://www.gnu.org/licenses/>. + */ + +#include <common.h> +#include <errno.h> +#include <stdio_dev.h> +#include <linux/ctype.h> +#include <linux/types.h> +#include <asm/global_data.h> +#include <linux/libfdt.h> +#include <fdt_support.h> +#include <asm/armv7.h> +#include <asm/psci.h> + +int armv7_apply_memory_carveout(u64 *start, u64 *size) +{ +#ifdef CONFIG_ARMV7_SECURE_RESERVE_SIZE + if (*start + *size < CONFIG_ARMV7_SECURE_BASE || + *start >= (u64)CONFIG_ARMV7_SECURE_BASE + + CONFIG_ARMV7_SECURE_RESERVE_SIZE) + return 0; + + /* carveout must be at the beginning or the end of the bank */ + if (*start == CONFIG_ARMV7_SECURE_BASE || + *start + *size == (u64)CONFIG_ARMV7_SECURE_BASE + + CONFIG_ARMV7_SECURE_RESERVE_SIZE) { + if (*size < CONFIG_ARMV7_SECURE_RESERVE_SIZE) { + debug("Secure monitor larger than RAM bank!?\n"); + return -EINVAL; + } + *size -= CONFIG_ARMV7_SECURE_RESERVE_SIZE; + if (*start == CONFIG_ARMV7_SECURE_BASE) + *start += CONFIG_ARMV7_SECURE_RESERVE_SIZE; + return 0; + } + debug("Secure monitor not located at beginning or end of RAM bank\n"); + return -EINVAL; +#else /* !CONFIG_ARMV7_SECURE_RESERVE_SIZE */ + return 0; +#endif +} + +int psci_update_dt(void *fdt) +{ +#ifdef CONFIG_ARMV7_NONSEC + if (!armv7_boot_nonsec()) + return 0; +#endif +#ifndef CONFIG_ARMV7_SECURE_BASE + /* secure code lives in RAM, keep it alive */ + fdt_add_mem_rsv(fdt, (unsigned long)__secure_start, + __secure_end - __secure_start); +#endif + + return fdt_psci(fdt); +}
diff --git a/arch/arm/cpu/armv7/virt-v7.c b/arch/arm/cpu/armv7/virt-v7.c new file mode 100644 index 0000000..be14eb9 --- /dev/null +++ b/arch/arm/cpu/armv7/virt-v7.c
@@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2013 + * Andre Przywara, Linaro <andre.przywara@linaro.org> + * + * Routines to transition ARMv7 processors from secure into non-secure state + * and from non-secure SVC into HYP mode + * needed to enable ARMv7 virtualization for current hypervisors + */ + +#include <common.h> +#include <asm/armv7.h> +#include <asm/gic.h> +#include <asm/io.h> +#include <asm/secure.h> + +static unsigned int read_id_pfr1(void) +{ + unsigned int reg; + + asm("mrc p15, 0, %0, c0, c1, 1\n" : "=r"(reg)); + return reg; +} + +static unsigned long get_gicd_base_address(void) +{ +#ifdef CONFIG_ARM_GIC_BASE_ADDRESS + return CONFIG_ARM_GIC_BASE_ADDRESS + GIC_DIST_OFFSET; +#else + unsigned periphbase; + + /* get the GIC base address from the CBAR register */ + asm("mrc p15, 4, %0, c15, c0, 0\n" : "=r" (periphbase)); + + /* the PERIPHBASE can be mapped above 4 GB (lower 8 bits used to + * encode this). Bail out here since we cannot access this without + * enabling paging. + */ + if ((periphbase & 0xff) != 0) { + printf("nonsec: PERIPHBASE is above 4 GB, no access.\n"); + return -1; + } + + return (periphbase & CBAR_MASK) + GIC_DIST_OFFSET; +#endif +} + +/* Define a specific version of this function to enable any available + * hardware protections for the reserved region */ +void __weak protect_secure_section(void) {} + +static void relocate_secure_section(void) +{ +#ifdef CONFIG_ARMV7_SECURE_BASE + size_t sz = __secure_end - __secure_start; + unsigned long szflush = ALIGN(sz + 1, CONFIG_SYS_CACHELINE_SIZE); + + memcpy((void *)CONFIG_ARMV7_SECURE_BASE, __secure_start, sz); + + flush_dcache_range(CONFIG_ARMV7_SECURE_BASE, + CONFIG_ARMV7_SECURE_BASE + szflush); + protect_secure_section(); + invalidate_icache_all(); +#endif +} + +static void kick_secondary_cpus_gic(unsigned long gicdaddr) +{ + /* kick all CPUs (except this one) by writing to GICD_SGIR */ + writel(1U << 24, gicdaddr + GICD_SGIR); +} + +void __weak smp_kick_all_cpus(void) +{ + unsigned long gic_dist_addr; + + gic_dist_addr = get_gicd_base_address(); + if (gic_dist_addr == -1) + return; + + kick_secondary_cpus_gic(gic_dist_addr); +} + +__weak void psci_board_init(void) +{ +} + +int armv7_init_nonsec(void) +{ + unsigned int reg; + unsigned itlinesnr, i; + unsigned long gic_dist_addr; + + /* check whether the CPU supports the security extensions */ + reg = read_id_pfr1(); + if ((reg & 0xF0) == 0) { + printf("nonsec: Security extensions not implemented.\n"); + return -1; + } + + /* the SCR register will be set directly in the monitor mode handler, + * according to the spec one should not tinker with it in secure state + * in SVC mode. Do not try to read it once in non-secure state, + * any access to it will trap. + */ + + gic_dist_addr = get_gicd_base_address(); + if (gic_dist_addr == -1) + return -1; + + /* enable the GIC distributor */ + writel(readl(gic_dist_addr + GICD_CTLR) | 0x03, + gic_dist_addr + GICD_CTLR); + + /* TYPER[4:0] contains an encoded number of available interrupts */ + itlinesnr = readl(gic_dist_addr + GICD_TYPER) & 0x1f; + + /* set all bits in the GIC group registers to one to allow access + * from non-secure state. The first 32 interrupts are private per + * CPU and will be set later when enabling the GIC for each core + */ + for (i = 1; i <= itlinesnr; i++) + writel((unsigned)-1, gic_dist_addr + GICD_IGROUPRn + 4 * i); + + psci_board_init(); + + /* + * Relocate secure section before any cpu runs in secure ram. + * smp_kick_all_cpus may enable other cores and runs into secure + * ram, so need to relocate secure section before enabling other + * cores. + */ + relocate_secure_section(); + +#ifndef CONFIG_ARMV7_PSCI + smp_set_core_boot_addr((unsigned long)secure_ram_addr(_smp_pen), -1); + smp_kick_all_cpus(); +#endif + + /* call the non-sec switching code on this CPU also */ + secure_ram_addr(_nonsec_init)(); + return 0; +}
diff --git a/arch/arm/cpu/armv7m/Makefile b/arch/arm/cpu/armv7m/Makefile new file mode 100644 index 0000000..baeac93 --- /dev/null +++ b/arch/arm/cpu/armv7m/Makefile
@@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-y := start.o +obj-y += cpu.o cache.o +obj-$(CONFIG_SYS_ARM_MPU) += mpu.o +obj-$(CONFIG_SYS_ARCH_TIMER) += systick-timer.o
diff --git a/arch/arm/cpu/armv7m/cache.c b/arch/arm/cpu/armv7m/cache.c new file mode 100644 index 0000000..815e623 --- /dev/null +++ b/arch/arm/cpu/armv7m/cache.c
@@ -0,0 +1,358 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved + * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. + */ + +#include <common.h> +#include <errno.h> +#include <asm/armv7m.h> +#include <asm/io.h> + +/* Cache maintenance operation registers */ + +#define V7M_CACHE_REG_ICIALLU ((u32 *)(V7M_CACHE_MAINT_BASE + 0x00)) +#define INVAL_ICACHE_POU 0 +#define V7M_CACHE_REG_ICIMVALU ((u32 *)(V7M_CACHE_MAINT_BASE + 0x08)) +#define V7M_CACHE_REG_DCIMVAC ((u32 *)(V7M_CACHE_MAINT_BASE + 0x0C)) +#define V7M_CACHE_REG_DCISW ((u32 *)(V7M_CACHE_MAINT_BASE + 0x10)) +#define V7M_CACHE_REG_DCCMVAU ((u32 *)(V7M_CACHE_MAINT_BASE + 0x14)) +#define V7M_CACHE_REG_DCCMVAC ((u32 *)(V7M_CACHE_MAINT_BASE + 0x18)) +#define V7M_CACHE_REG_DCCSW ((u32 *)(V7M_CACHE_MAINT_BASE + 0x1C)) +#define V7M_CACHE_REG_DCCIMVAC ((u32 *)(V7M_CACHE_MAINT_BASE + 0x20)) +#define V7M_CACHE_REG_DCCISW ((u32 *)(V7M_CACHE_MAINT_BASE + 0x24)) +#define WAYS_SHIFT 30 +#define SETS_SHIFT 5 + +/* armv7m processor feature registers */ + +#define V7M_PROC_REG_CLIDR ((u32 *)(V7M_PROC_FTR_BASE + 0x00)) +#define V7M_PROC_REG_CTR ((u32 *)(V7M_PROC_FTR_BASE + 0x04)) +#define V7M_PROC_REG_CCSIDR ((u32 *)(V7M_PROC_FTR_BASE + 0x08)) +#define MASK_NUM_WAYS GENMASK(12, 3) +#define MASK_NUM_SETS GENMASK(27, 13) +#define CLINE_SIZE_MASK GENMASK(2, 0) +#define NUM_WAYS_SHIFT 3 +#define NUM_SETS_SHIFT 13 +#define V7M_PROC_REG_CSSELR ((u32 *)(V7M_PROC_FTR_BASE + 0x0C)) +#define SEL_I_OR_D BIT(0) + +enum cache_type { + DCACHE, + ICACHE, +}; + +/* PoU : Point of Unification, Poc: Point of Coherency */ +enum cache_action { + INVALIDATE_POU, /* i-cache invalidate by address */ + INVALIDATE_POC, /* d-cache invalidate by address */ + INVALIDATE_SET_WAY, /* d-cache invalidate by sets/ways */ + FLUSH_POU, /* d-cache clean by address to the PoU */ + FLUSH_POC, /* d-cache clean by address to the PoC */ + FLUSH_SET_WAY, /* d-cache clean by sets/ways */ + FLUSH_INVAL_POC, /* d-cache clean & invalidate by addr to PoC */ + FLUSH_INVAL_SET_WAY, /* d-cache clean & invalidate by set/ways */ +}; + +#ifndef CONFIG_SYS_DCACHE_OFF +struct dcache_config { + u32 ways; + u32 sets; +}; + +static void get_cache_ways_sets(struct dcache_config *cache) +{ + u32 cache_size_id = readl(V7M_PROC_REG_CCSIDR); + + cache->ways = (cache_size_id & MASK_NUM_WAYS) >> NUM_WAYS_SHIFT; + cache->sets = (cache_size_id & MASK_NUM_SETS) >> NUM_SETS_SHIFT; +} + +/* + * Return the io register to perform required cache action like clean or clean + * & invalidate by sets/ways. + */ +static u32 *get_action_reg_set_ways(enum cache_action action) +{ + switch (action) { + case INVALIDATE_SET_WAY: + return V7M_CACHE_REG_DCISW; + case FLUSH_SET_WAY: + return V7M_CACHE_REG_DCCSW; + case FLUSH_INVAL_SET_WAY: + return V7M_CACHE_REG_DCCISW; + default: + break; + }; + + return NULL; +} + +/* + * Return the io register to perform required cache action like clean or clean + * & invalidate by adddress or range. + */ +static u32 *get_action_reg_range(enum cache_action action) +{ + switch (action) { + case INVALIDATE_POU: + return V7M_CACHE_REG_ICIMVALU; + case INVALIDATE_POC: + return V7M_CACHE_REG_DCIMVAC; + case FLUSH_POU: + return V7M_CACHE_REG_DCCMVAU; + case FLUSH_POC: + return V7M_CACHE_REG_DCCMVAC; + case FLUSH_INVAL_POC: + return V7M_CACHE_REG_DCCIMVAC; + default: + break; + } + + return NULL; +} + +static u32 get_cline_size(enum cache_type type) +{ + u32 size; + + if (type == DCACHE) + clrbits_le32(V7M_PROC_REG_CSSELR, BIT(SEL_I_OR_D)); + else if (type == ICACHE) + setbits_le32(V7M_PROC_REG_CSSELR, BIT(SEL_I_OR_D)); + /* Make sure cache selection is effective for next memory access */ + dsb(); + + size = readl(V7M_PROC_REG_CCSIDR) & CLINE_SIZE_MASK; + /* Size enocoded as 2 less than log(no_of_words_in_cache_line) base 2 */ + size = 1 << (size + 2); + debug("cache line size is %d\n", size); + + return size; +} + +/* Perform the action like invalidate/clean on a range of cache addresses */ +static int action_cache_range(enum cache_action action, u32 start_addr, + int64_t size) +{ + u32 cline_size; + u32 *action_reg; + enum cache_type type; + + action_reg = get_action_reg_range(action); + if (!action_reg) + return -EINVAL; + if (action == INVALIDATE_POU) + type = ICACHE; + else + type = DCACHE; + + /* Cache line size is minium size for the cache action */ + cline_size = get_cline_size(type); + /* Align start address to cache line boundary */ + start_addr &= ~(cline_size - 1); + debug("total size for cache action = %llx\n", size); + do { + writel(start_addr, action_reg); + size -= cline_size; + start_addr += cline_size; + } while (size > cline_size); + + /* Make sure cache action is effective for next memory access */ + dsb(); + isb(); /* Make sure instruction stream sees it */ + debug("cache action on range done\n"); + + return 0; +} + +/* Perform the action like invalidate/clean on all cached addresses */ +static int action_dcache_all(enum cache_action action) +{ + struct dcache_config cache; + u32 *action_reg; + int i, j; + + action_reg = get_action_reg_set_ways(action); + if (!action_reg) + return -EINVAL; + + clrbits_le32(V7M_PROC_REG_CSSELR, BIT(SEL_I_OR_D)); + /* Make sure cache selection is effective for next memory access */ + dsb(); + + get_cache_ways_sets(&cache); /* Get number of ways & sets */ + debug("cache: ways= %d, sets= %d\n", cache.ways + 1, cache.sets + 1); + for (i = cache.sets; i >= 0; i--) { + for (j = cache.ways; j >= 0; j--) { + writel((j << WAYS_SHIFT) | (i << SETS_SHIFT), + action_reg); + } + } + + /* Make sure cache action is effective for next memory access */ + dsb(); + isb(); /* Make sure instruction stream sees it */ + + return 0; +} + +void dcache_enable(void) +{ + if (dcache_status()) /* return if cache already enabled */ + return; + + if (action_dcache_all(INVALIDATE_SET_WAY)) { + printf("ERR: D-cache not enabled\n"); + return; + } + + setbits_le32(&V7M_SCB->ccr, BIT(V7M_CCR_DCACHE)); + + /* Make sure cache action is effective for next memory access */ + dsb(); + isb(); /* Make sure instruction stream sees it */ +} + +void dcache_disable(void) +{ + if (!dcache_status()) + return; + + /* if dcache is enabled-> dcache disable & then flush */ + if (action_dcache_all(FLUSH_SET_WAY)) { + printf("ERR: D-cache not flushed\n"); + return; + } + + clrbits_le32(&V7M_SCB->ccr, BIT(V7M_CCR_DCACHE)); + + /* Make sure cache action is effective for next memory access */ + dsb(); + isb(); /* Make sure instruction stream sees it */ +} + +int dcache_status(void) +{ + return (readl(&V7M_SCB->ccr) & BIT(V7M_CCR_DCACHE)) != 0; +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ + if (action_cache_range(INVALIDATE_POC, start, stop - start)) { + printf("ERR: D-cache not invalidated\n"); + return; + } +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ + if (action_cache_range(FLUSH_POC, start, stop - start)) { + printf("ERR: D-cache not flushed\n"); + return; + } +} +void flush_dcache_all(void) +{ + if (action_dcache_all(FLUSH_SET_WAY)) { + printf("ERR: D-cache not flushed\n"); + return; + } +} + +void invalidate_dcache_all(void) +{ + if (action_dcache_all(INVALIDATE_SET_WAY)) { + printf("ERR: D-cache not invalidated\n"); + return; + } +} +#else +void dcache_enable(void) +{ + return; +} + +void dcache_disable(void) +{ + return; +} + +int dcache_status(void) +{ + return 0; +} + +void flush_dcache_all(void) +{ +} + +void invalidate_dcache_all(void) +{ +} +#endif + +#ifndef CONFIG_SYS_ICACHE_OFF + +void invalidate_icache_all(void) +{ + writel(INVAL_ICACHE_POU, V7M_CACHE_REG_ICIALLU); + + /* Make sure cache action is effective for next memory access */ + dsb(); + isb(); /* Make sure instruction stream sees it */ +} + +void icache_enable(void) +{ + if (icache_status()) + return; + + invalidate_icache_all(); + setbits_le32(&V7M_SCB->ccr, BIT(V7M_CCR_ICACHE)); + + /* Make sure cache action is effective for next memory access */ + dsb(); + isb(); /* Make sure instruction stream sees it */ +} + +int icache_status(void) +{ + return (readl(&V7M_SCB->ccr) & BIT(V7M_CCR_ICACHE)) != 0; +} + +void icache_disable(void) +{ + if (!icache_status()) + return; + + isb(); /* flush pipeline */ + clrbits_le32(&V7M_SCB->ccr, BIT(V7M_CCR_ICACHE)); + isb(); /* subsequent instructions fetch see cache disable effect */ +} +#else +void icache_enable(void) +{ + return; +} + +void icache_disable(void) +{ + return; +} + +int icache_status(void) +{ + return 0; +} +#endif + +void enable_caches(void) +{ +#ifndef CONFIG_SYS_ICACHE_OFF + icache_enable(); +#endif +#ifndef CONFIG_SYS_DCACHE_OFF + dcache_enable(); +#endif +}
diff --git a/arch/arm/cpu/armv7m/config.mk b/arch/arm/cpu/armv7m/config.mk new file mode 100644 index 0000000..f50964c --- /dev/null +++ b/arch/arm/cpu/armv7m/config.mk
@@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2015 +# Kamil Lulko, <kamil.lulko@gmail.com> + +PLATFORM_CPPFLAGS += -mno-unaligned-access
diff --git a/arch/arm/cpu/armv7m/cpu.c b/arch/arm/cpu/armv7m/cpu.c new file mode 100644 index 0000000..55ea078 --- /dev/null +++ b/arch/arm/cpu/armv7m/cpu.c
@@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2010,2011 + * Vladimir Khusainov, Emcraft Systems, vlad@emcraft.com + * + * (C) Copyright 2015 + * Kamil Lulko, <kamil.lulko@gmail.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/armv7m.h> + +/* + * This is called right before passing control to + * the Linux kernel point. + */ +int cleanup_before_linux(void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * disable interrupt and turn off caches etc ... + */ + disable_interrupts(); + /* + * turn off D-cache + * dcache_disable() in turn flushes the d-cache + * MPU is still enabled & can't be disabled as the u-boot + * code might be running in sdram which by default is not + * executable area. + */ + dcache_disable(); + /* invalidate to make sure no cache line gets dirty between + * dcache flushing and disabling dcache */ + invalidate_dcache_all(); + + icache_disable(); + invalidate_icache_all(); + + return 0; +} + +/* + * Perform the low-level reset. + */ +void reset_cpu(ulong addr) +{ + /* + * Perform reset but keep priority group unchanged. + */ + writel((V7M_AIRCR_VECTKEY << V7M_AIRCR_VECTKEY_SHIFT) + | (V7M_SCB->aircr & V7M_AIRCR_PRIGROUP_MSK) + | V7M_AIRCR_SYSRESET, &V7M_SCB->aircr); +}
diff --git a/arch/arm/cpu/armv7m/mpu.c b/arch/arm/cpu/armv7m/mpu.c new file mode 100644 index 0000000..81e7492 --- /dev/null +++ b/arch/arm/cpu/armv7m/mpu.c
@@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved + * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. + */ + +#include <linux/bitops.h> +#include <asm/armv7m.h> +#include <asm/armv7_mpu.h> +#include <asm/io.h> + +#define V7M_MPU_CTRL_ENABLE BIT(0) +#define V7M_MPU_CTRL_DISABLE (0 << 0) +#define V7M_MPU_CTRL_HFNMIENA BIT(1) +#define V7M_MPU_CTRL_PRIVDEFENA BIT(2) +#define VALID_REGION BIT(4) + +void disable_mpu(void) +{ + writel(0, &V7M_MPU->ctrl); +} + +void enable_mpu(void) +{ + writel(V7M_MPU_CTRL_ENABLE | V7M_MPU_CTRL_PRIVDEFENA, &V7M_MPU->ctrl); + + /* Make sure new mpu config is effective for next memory access */ + dsb(); + isb(); /* Make sure instruction stream sees it */ +} + +void mpu_config(struct mpu_region_config *reg_config) +{ + uint32_t attr; + + attr = get_attr_encoding(reg_config->mr_attr); + + writel(reg_config->start_addr | VALID_REGION | reg_config->region_no, + &V7M_MPU->rbar); + + writel(reg_config->xn << XN_SHIFT | reg_config->ap << AP_SHIFT | attr + | reg_config->reg_size << REGION_SIZE_SHIFT | ENABLE_REGION + , &V7M_MPU->rasr); +}
diff --git a/arch/arm/cpu/armv7m/start.S b/arch/arm/cpu/armv7m/start.S new file mode 100644 index 0000000..0c07f21 --- /dev/null +++ b/arch/arm/cpu/armv7m/start.S
@@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2015 + * Kamil Lulko, <kamil.lulko@gmail.com> + */ + +#include <asm/assembler.h> + +.globl reset +.type reset, %function +reset: + W(b) _main + +.globl c_runtime_cpu_setup +c_runtime_cpu_setup: + mov pc, lr
diff --git a/arch/arm/cpu/armv7m/systick-timer.c b/arch/arm/cpu/armv7m/systick-timer.c new file mode 100644 index 0000000..d04f67a --- /dev/null +++ b/arch/arm/cpu/armv7m/systick-timer.c
@@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * ARM Cortex M3/M4/M7 SysTick timer driver + * (C) Copyright 2017 Renesas Electronics Europe Ltd + * + * Based on arch/arm/mach-stm32/stm32f1/timer.c + * (C) Copyright 2015 + * Kamil Lulko, <kamil.lulko@gmail.com> + * + * Copyright 2015 ATS Advanced Telematics Systems GmbH + * Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com> + * + * The SysTick timer is a 24-bit count down timer. The clock can be either the + * CPU clock or a reference clock. Since the timer will wrap around very quickly + * when using the CPU clock, and we do not handle the timer interrupts, it is + * expected that this driver is only ever used with a slow reference clock. + * + * The number of reference clock ticks that correspond to 10ms is normally + * defined in the SysTick Calibration register's TENMS field. However, on some + * devices this is wrong, so this driver allows the clock rate to be defined + * using CONFIG_SYS_HZ_CLOCK. + */ + +#include <common.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* SysTick Base Address - fixed for all Cortex M3, M4 and M7 devices */ +#define SYSTICK_BASE 0xE000E010 + +struct cm3_systick { + uint32_t ctrl; + uint32_t reload_val; + uint32_t current_val; + uint32_t calibration; +}; + +#define TIMER_MAX_VAL 0x00FFFFFF +#define SYSTICK_CTRL_EN BIT(0) +/* Clock source: 0 = Ref clock, 1 = CPU clock */ +#define SYSTICK_CTRL_CPU_CLK BIT(2) +#define SYSTICK_CAL_NOREF BIT(31) +#define SYSTICK_CAL_SKEW BIT(30) +#define SYSTICK_CAL_TENMS_MASK 0x00FFFFFF + +/* read the 24-bit timer */ +static ulong read_timer(void) +{ + struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE; + + /* The timer counts down, therefore convert to an incrementing timer */ + return TIMER_MAX_VAL - readl(&systick->current_val); +} + +int timer_init(void) +{ + struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE; + u32 cal; + + writel(TIMER_MAX_VAL, &systick->reload_val); + /* Any write to current_val reg clears it to 0 */ + writel(0, &systick->current_val); + + cal = readl(&systick->calibration); + if (cal & SYSTICK_CAL_NOREF) + /* Use CPU clock, no interrupts */ + writel(SYSTICK_CTRL_EN | SYSTICK_CTRL_CPU_CLK, &systick->ctrl); + else + /* Use external clock, no interrupts */ + writel(SYSTICK_CTRL_EN, &systick->ctrl); + + /* + * If the TENMS field is inexact or wrong, specify the clock rate using + * CONFIG_SYS_HZ_CLOCK. + */ +#if defined(CONFIG_SYS_HZ_CLOCK) + gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK; +#else + gd->arch.timer_rate_hz = (cal & SYSTICK_CAL_TENMS_MASK) * 100; +#endif + + gd->arch.tbl = 0; + gd->arch.tbu = 0; + gd->arch.lastinc = read_timer(); + + return 0; +} + +/* return milli-seconds timer value */ +ulong get_timer(ulong base) +{ + unsigned long long t = get_ticks() * 1000; + + return (ulong)((t / gd->arch.timer_rate_hz)) - base; +} + +unsigned long long get_ticks(void) +{ + u32 now = read_timer(); + + if (now >= gd->arch.lastinc) + gd->arch.tbl += (now - gd->arch.lastinc); + else + gd->arch.tbl += (TIMER_MAX_VAL - gd->arch.lastinc) + now; + + gd->arch.lastinc = now; + + return gd->arch.tbl; +} + +ulong get_tbclk(void) +{ + return gd->arch.timer_rate_hz; +}
diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig new file mode 100644 index 0000000..d5a9158 --- /dev/null +++ b/arch/arm/cpu/armv8/Kconfig
@@ -0,0 +1,169 @@ +if ARM64 + +config ARMV8_SPL_EXCEPTION_VECTORS + bool "Install crash dump exception vectors" + depends on SPL + default y + help + The default exception vector table is only used for the crash + dump, but still takes quite a lot of space in the image size. + + Say N here if you are running out of code space in the image + and want to save some space at the cost of less debugging info. + +config ARMV8_MULTIENTRY + bool "Enable multiple CPUs to enter into U-Boot" + +config ARMV8_SET_SMPEN + bool "Enable data coherency with other cores in cluster" + help + Say Y here if there is not any trust firmware to set + CPUECTLR_EL1.SMPEN bit before U-Boot. + + For A53, it enables data coherency with other cores in the + cluster, and for A57/A72, it enables receiving of instruction + cache and TLB maintenance operations. + Cortex A53/57/72 cores require CPUECTLR_EL1.SMPEN set even + for single core systems. Unfortunately write access to this + register may be controlled by EL3/EL2 firmware. To be more + precise, by default (if there is EL2/EL3 firmware running) + this register is RO for NS EL1. + This switch can be used to avoid writing to CPUECTLR_EL1, + it can be safely enabled when EL2/EL3 initialized SMPEN bit + or when CPU implementation doesn't include that register. + +config ARMV8_SPIN_TABLE + bool "Support spin-table enable method" + depends on ARMV8_MULTIENTRY && OF_LIBFDT + help + Say Y here to support "spin-table" enable method for booting Linux. + + To use this feature, you must do: + - Specify enable-method = "spin-table" in each CPU node in the + Device Tree you are using to boot the kernel + - Bring secondary CPUs into U-Boot proper in a board specific + manner. This must be done *after* relocation. Otherwise, the + secondary CPUs will spin in unprotected memory area because the + master CPU protects the relocated spin code. + + U-Boot automatically does: + - Set "cpu-release-addr" property of each CPU node + (overwrites it if already exists). + - Reserve the code for the spin-table and the release address + via a /memreserve/ region in the Device Tree. + +menu "ARMv8 secure monitor firmware" +config ARMV8_SEC_FIRMWARE_SUPPORT + bool "Enable ARMv8 secure monitor firmware framework support" + select FIT + select OF_LIBFDT + help + This framework is aimed at making secure monitor firmware load + process brief. + Note: Only FIT format image is supported. + You should prepare and provide the below information: + - Address of secure firmware. + - Address to hold the return address from secure firmware. + - Secure firmware FIT image related information. + Such as: SEC_FIRMWARE_FIT_IMAGE and SEC_FIRMEWARE_FIT_CNF_NAME + - The target exception level that secure monitor firmware will + return to. + +config SPL_ARMV8_SEC_FIRMWARE_SUPPORT + bool "Enable ARMv8 secure monitor firmware framework support for SPL" + select SPL_FIT + select SPL_OF_LIBFDT + help + Say Y here to support this framework in SPL phase. + +config SEC_FIRMWARE_ARMV8_PSCI + bool "PSCI implementation in secure monitor firmware" + depends on ARMV8_SEC_FIRMWARE_SUPPORT || SPL_ARMV8_SEC_FIRMWARE_SUPPORT + help + This config enables the ARMv8 PSCI implementation in secure monitor + firmware. This is a private PSCI implementation and different from + those implemented under the common ARMv8 PSCI framework. + +config ARMV8_SEC_FIRMWARE_ERET_ADDR_REVERT + bool "ARMv8 secure monitor firmware ERET address byteorder swap" + depends on ARMV8_SEC_FIRMWARE_SUPPORT || SPL_ARMV8_SEC_FIRMWARE_SUPPORT + help + Say Y here when the endianness of the register or memory holding the + Secure firmware exception return address is different with core's. + +endmenu + +config PSCI_RESET + bool "Use PSCI for reset and shutdown" + default n + select ARM_SMCCC if OF_CONTROL + depends on !ARCH_EXYNOS7 && !ARCH_BCM283X && \ + !TARGET_LS2080A_SIMU && !TARGET_LS2080AQDS && \ + !TARGET_LS2080ARDB && !TARGET_LS2080A_EMU && \ + !TARGET_LS1088ARDB && !TARGET_LS1088AQDS && \ + !TARGET_LS1012ARDB && !TARGET_LS1012AFRDM && \ + !TARGET_LS1012A2G5RDB && !TARGET_LS1012AQDS && \ + !TARGET_LS1012AFRWY && \ + !TARGET_LS1043ARDB && !TARGET_LS1043AQDS && \ + !TARGET_LS1046ARDB && !TARGET_LS1046AQDS && \ + !TARGET_LS2081ARDB && \ + !ARCH_UNIPHIER && !TARGET_S32V234EVB + help + Most armv8 systems have PSCI support enabled in EL3, either through + ARM Trusted Firmware or other firmware. + + On these systems, we do not need to implement system reset manually, + but can instead rely on higher level firmware to deal with it. + + Select Y here to make use of PSCI calls for system reset + +config ARMV8_PSCI + bool "Enable PSCI support" if EXPERT + default n + help + PSCI is Power State Coordination Interface defined by ARM. + The PSCI in U-boot provides a general framework and each platform + can implement their own specific PSCI functions. + Say Y here to enable PSCI support on ARMv8 platform. + +config ARMV8_PSCI_NR_CPUS + int "Maximum supported CPUs for PSCI" + depends on ARMV8_PSCI + default 4 + help + The maximum number of CPUs supported in the PSCI firmware. + It is no problem to set a larger value than the number of CPUs in + the actual hardware implementation. + +config ARMV8_PSCI_CPUS_PER_CLUSTER + int "Number of CPUs per cluster" + depends on ARMV8_PSCI + default 0 + help + The number of CPUs per cluster, suppose each cluster has same number + of CPU cores, platforms with asymmetric clusters don't apply here. + A value 0 or no definition of it works for single cluster system. + System with multi-cluster should difine their own exact value. + +config ARMV8_EA_EL3_FIRST + bool "External aborts and SError interrupt exception are taken in EL3" + default n + help + Exception handling at all exception levels for External Abort and + SError interrupt exception are taken in EL3. + +if SYS_HAS_ARMV8_SECURE_BASE + +config ARMV8_SECURE_BASE + hex "Secure address for PSCI image" + depends on ARMV8_PSCI + help + Address for placing the PSCI text, data and stack sections. + If not defined, the PSCI sections are placed together with the u-boot + but platform can choose to place PSCI code image separately in other + places such as some secure RAM built-in SOC etc. + +endif + +endif +
diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile new file mode 100644 index 0000000..a807d1f --- /dev/null +++ b/arch/arm/cpu/armv8/Makefile
@@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-y := start.o + +obj-y += cpu.o +ifndef CONFIG_$(SPL_TPL_)TIMER +obj-$(CONFIG_SYS_ARCH_TIMER) += generic_timer.o +endif +obj-y += cache_v8.o +ifdef CONFIG_SPL_BUILD +obj-$(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) += exceptions.o +else +obj-y += exceptions.o +endif +obj-y += cache.o +obj-y += tlb.o +obj-y += transition.o +obj-y += fwcall.o +obj-y += cpu-dt.o +obj-$(CONFIG_ARM_SMCCC) += smccc-call.o + +obj-y += a32_kernel_pre_entry.o + +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o +endif +obj-$(CONFIG_$(SPL_)ARMV8_SEC_FIRMWARE_SUPPORT) += sec_firmware.o sec_firmware_asm.o + +obj-$(CONFIG_FSL_LAYERSCAPE) += fsl-layerscape/ +obj-$(CONFIG_S32V234) += s32v234/ +obj-$(CONFIG_ARCH_ZYNQMP) += zynqmp/ +obj-$(CONFIG_TARGET_HIKEY) += hisilicon/ +obj-$(CONFIG_ARMV8_PSCI) += psci.o +obj-$(CONFIG_ARCH_SUNXI) += lowlevel_init.o
diff --git a/arch/arm/cpu/armv8/a32_kernel_pre_entry.S b/arch/arm/cpu/armv8/a32_kernel_pre_entry.S new file mode 100644 index 0000000..ac4220e --- /dev/null +++ b/arch/arm/cpu/armv8/a32_kernel_pre_entry.S
@@ -0,0 +1,85 @@ +#include <asm-offsets.h> +#include <config.h> +#include <version.h> +#include <asm/macro.h> +#include <linux/linkage.h> + +#define HCR_RW (1 << 31) +#define HCR_TGE (1 << 27) +#define HCR_E2H (1 << 34) + + +/* AArch32 SPSR*/ +#define AARCH32_SPSR_MODE (3 << 0) +#define AARCH32_SPSR_STATE (1 << 4) +#define AARCH32_SPSR_DAIF (7 << 6) + +/* + * void jump_to_a32_kernel(kernel_ep, machid, dtb pointer) +*/ +ENTRY(jump_to_a32_kernel) + mov x20, x0 + mov x21, x1 + mov x22, x2 + + mrs x0, sctlr_el2 + bic x0, x0, #(1 << 25) + msr sctlr_el2, x0 + + mov x2, xzr + + /* sctlr_el1 */ + mov x0, #0x0878 // Set/clear RES{1,0} bits + movk x0, #0x00c5, lsl #16 // Clear EE and E0E on LE systems + msr sctlr_el1, x0 + +#if 0 + /* Generic timers. */ + mrs x0, cnthctl_el2 + orr x0, x0, #3 // Enable EL1 physical timers + msr cnthctl_el2, x0 + msr cntvoff_el2, xzr // Clear virtual offset + + /* Populate ID registers. */ + mrs x0, midr_el1 + mrs x1, mpidr_el1 + msr vpidr_el2, x0 + msr vmpidr_el2, x1 + + /* Coprocessor traps. */ + mov x0, #0x33ff + msr cptr_el2, x0 // Disable copro. traps to EL2 + + msr hstr_el2, xzr // Disable CP15 traps to EL2 + + /* EL2 debug */ + mrs x0, id_aa64dfr0_el1 // Check ID_AA64DFR0_EL1 PMUVer + sbfx x0, x0, #8, #4 + cmp x0, #1 + b.lt 4f // Skip if no PMU present + mrs x0, pmcr_el0 // Disable debug access traps + ubfx x0, x0, #11, #5 // to EL2 and allow access to +4: + csel x0, xzr, x0, lt // all PMU counters from EL1 + msr mdcr_el2, x0 // (if they exist) + + /* Stage-2 translation */ + msr vttbr_el2, xzr +#endif + + /* Hyp configuration. */ + mov x0, #0 // 32-bit EL1 HCR_EL2.RW=0 + msr hcr_el2, x0 + isb + + /* spsr */ + mov x0, #(AARCH32_SPSR_MODE | \ + AARCH32_SPSR_STATE | \ + AARCH32_SPSR_DAIF) + msr spsr_el2, x0 + msr elr_el2, x20 + mov x0, #0 + mov x1, x21 + mov x2, x22 + eret +ENDPROC(jump_to_a32_kernel)
diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S new file mode 100644 index 0000000..443d94c --- /dev/null +++ b/arch/arm/cpu/armv8/cache.S
@@ -0,0 +1,267 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * This file is based on sample code from ARMv8 ARM. + */ + +#include <asm-offsets.h> +#include <config.h> +#include <asm/macro.h> +#include <asm/system.h> +#include <linux/linkage.h> + +/* + * void __asm_dcache_level(level) + * + * flush or invalidate one level cache. + * + * x0: cache level + * x1: 0 clean & invalidate, 1 invalidate only + * x2~x9: clobbered + */ +.pushsection .text.__asm_dcache_level, "ax" +ENTRY(__asm_dcache_level) + lsl x12, x0, #1 + msr csselr_el1, x12 /* select cache level */ + isb /* sync change of cssidr_el1 */ + mrs x6, ccsidr_el1 /* read the new cssidr_el1 */ + and x2, x6, #7 /* x2 <- log2(cache line size)-4 */ + add x2, x2, #4 /* x2 <- log2(cache line size) */ + mov x3, #0x3ff + and x3, x3, x6, lsr #3 /* x3 <- max number of #ways */ + clz w5, w3 /* bit position of #ways */ + mov x4, #0x7fff + and x4, x4, x6, lsr #13 /* x4 <- max number of #sets */ + /* x12 <- cache level << 1 */ + /* x2 <- line length offset */ + /* x3 <- number of cache ways - 1 */ + /* x4 <- number of cache sets - 1 */ + /* x5 <- bit position of #ways */ + +loop_set: + mov x6, x3 /* x6 <- working copy of #ways */ +loop_way: + lsl x7, x6, x5 + orr x9, x12, x7 /* map way and level to cisw value */ + lsl x7, x4, x2 + orr x9, x9, x7 /* map set number to cisw value */ + tbz w1, #0, 1f + dc isw, x9 + b 2f +1: dc cisw, x9 /* clean & invalidate by set/way */ +2: subs x6, x6, #1 /* decrement the way */ + b.ge loop_way + subs x4, x4, #1 /* decrement the set */ + b.ge loop_set + + ret +ENDPROC(__asm_dcache_level) +.popsection + +/* + * void __asm_flush_dcache_all(int invalidate_only) + * + * x0: 0 clean & invalidate, 1 invalidate only + * + * flush or invalidate all data cache by SET/WAY. + */ +.pushsection .text.__asm_dcache_all, "ax" +ENTRY(__asm_dcache_all) + mov x1, x0 + dsb sy + mrs x10, clidr_el1 /* read clidr_el1 */ + lsr x11, x10, #24 + and x11, x11, #0x7 /* x11 <- loc */ + cbz x11, finished /* if loc is 0, exit */ + mov x15, lr + mov x0, #0 /* start flush at cache level 0 */ + /* x0 <- cache level */ + /* x10 <- clidr_el1 */ + /* x11 <- loc */ + /* x15 <- return address */ + +loop_level: + lsl x12, x0, #1 + add x12, x12, x0 /* x0 <- tripled cache level */ + lsr x12, x10, x12 + and x12, x12, #7 /* x12 <- cache type */ + cmp x12, #2 + b.lt skip /* skip if no cache or icache */ + bl __asm_dcache_level /* x1 = 0 flush, 1 invalidate */ +skip: + add x0, x0, #1 /* increment cache level */ + cmp x11, x0 + b.gt loop_level + + mov x0, #0 + msr csselr_el1, x0 /* restore csselr_el1 */ + dsb sy + isb + mov lr, x15 + +finished: + ret +ENDPROC(__asm_dcache_all) +.popsection + +.pushsection .text.__asm_flush_dcache_all, "ax" +ENTRY(__asm_flush_dcache_all) + mov x0, #0 + b __asm_dcache_all +ENDPROC(__asm_flush_dcache_all) +.popsection + +.pushsection .text.__asm_invalidate_dcache_all, "ax" +ENTRY(__asm_invalidate_dcache_all) + mov x0, #0x1 + b __asm_dcache_all +ENDPROC(__asm_invalidate_dcache_all) +.popsection + +/* + * void __asm_flush_dcache_range(start, end) + * + * clean & invalidate data cache in the range + * + * x0: start address + * x1: end address + */ +.pushsection .text.__asm_flush_dcache_range, "ax" +ENTRY(__asm_flush_dcache_range) + mrs x3, ctr_el0 + lsr x3, x3, #16 + and x3, x3, #0xf + mov x2, #4 + lsl x2, x2, x3 /* cache line size */ + + /* x2 <- minimal cache line size in cache system */ + sub x3, x2, #1 + bic x0, x0, x3 +1: dc civac, x0 /* clean & invalidate data or unified cache */ + add x0, x0, x2 + cmp x0, x1 + b.lo 1b + dsb sy + ret +ENDPROC(__asm_flush_dcache_range) +.popsection +/* + * void __asm_invalidate_dcache_range(start, end) + * + * invalidate data cache in the range + * + * x0: start address + * x1: end address + */ +.pushsection .text.__asm_invalidate_dcache_range, "ax" +ENTRY(__asm_invalidate_dcache_range) + mrs x3, ctr_el0 + ubfm x3, x3, #16, #19 + mov x2, #4 + lsl x2, x2, x3 /* cache line size */ + + /* x2 <- minimal cache line size in cache system */ + sub x3, x2, #1 + bic x0, x0, x3 +1: dc ivac, x0 /* invalidate data or unified cache */ + add x0, x0, x2 + cmp x0, x1 + b.lo 1b + dsb sy + ret +ENDPROC(__asm_invalidate_dcache_range) +.popsection + +/* + * void __asm_invalidate_icache_all(void) + * + * invalidate all tlb entries. + */ +.pushsection .text.__asm_invalidate_icache_all, "ax" +ENTRY(__asm_invalidate_icache_all) + ic ialluis + isb sy + ret +ENDPROC(__asm_invalidate_icache_all) +.popsection + +.pushsection .text.__asm_invalidate_l3_dcache, "ax" +ENTRY(__asm_invalidate_l3_dcache) + mov x0, #0 /* return status as success */ + ret +ENDPROC(__asm_invalidate_l3_dcache) + .weak __asm_invalidate_l3_dcache +.popsection + +.pushsection .text.__asm_flush_l3_dcache, "ax" +ENTRY(__asm_flush_l3_dcache) + mov x0, #0 /* return status as success */ + ret +ENDPROC(__asm_flush_l3_dcache) + .weak __asm_flush_l3_dcache +.popsection + +.pushsection .text.__asm_invalidate_l3_icache, "ax" +ENTRY(__asm_invalidate_l3_icache) + mov x0, #0 /* return status as success */ + ret +ENDPROC(__asm_invalidate_l3_icache) + .weak __asm_invalidate_l3_icache +.popsection + +/* + * void __asm_switch_ttbr(ulong new_ttbr) + * + * Safely switches to a new page table. + */ +.pushsection .text.__asm_switch_ttbr, "ax" +ENTRY(__asm_switch_ttbr) + /* x2 = SCTLR (alive throghout the function) */ + switch_el x4, 3f, 2f, 1f +3: mrs x2, sctlr_el3 + b 0f +2: mrs x2, sctlr_el2 + b 0f +1: mrs x2, sctlr_el1 +0: + + /* Unset CR_M | CR_C | CR_I from SCTLR to disable all caches */ + movn x1, #(CR_M | CR_C | CR_I) + and x1, x2, x1 + switch_el x4, 3f, 2f, 1f +3: msr sctlr_el3, x1 + b 0f +2: msr sctlr_el2, x1 + b 0f +1: msr sctlr_el1, x1 +0: isb + + /* This call only clobbers x30 (lr) and x9 (unused) */ + mov x3, x30 + bl __asm_invalidate_tlb_all + + /* From here on we're running safely with caches disabled */ + + /* Set TTBR to our first argument */ + switch_el x4, 3f, 2f, 1f +3: msr ttbr0_el3, x0 + b 0f +2: msr ttbr0_el2, x0 + b 0f +1: msr ttbr0_el1, x0 +0: isb + + /* Restore original SCTLR and thus enable caches again */ + switch_el x4, 3f, 2f, 1f +3: msr sctlr_el3, x2 + b 0f +2: msr sctlr_el2, x2 + b 0f +1: msr sctlr_el1, x2 +0: isb + + ret x3 +ENDPROC(__asm_switch_ttbr) +.popsection
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c new file mode 100644 index 0000000..0384051 --- /dev/null +++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -0,0 +1,742 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * (C) Copyright 2016 + * Alexander Graf <agraf@suse.de> + */ + +#include <common.h> +#include <asm/system.h> +#include <asm/armv8/mmu.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_DCACHE_OFF + +/* + * With 4k page granule, a virtual address is split into 4 lookup parts + * spanning 9 bits each: + * + * _______________________________________________ + * | | | | | | | + * | 0 | Lv0 | Lv1 | Lv2 | Lv3 | off | + * |_______|_______|_______|_______|_______|_______| + * 63-48 47-39 38-30 29-21 20-12 11-00 + * + * mask page size + * + * Lv0: FF8000000000 -- + * Lv1: 7FC0000000 1G + * Lv2: 3FE00000 2M + * Lv3: 1FF000 4K + * off: FFF + */ + +u64 get_tcr(int el, u64 *pips, u64 *pva_bits) +{ + u64 max_addr = 0; + u64 ips, va_bits; + u64 tcr; + int i; + + /* Find the largest address we need to support */ + for (i = 0; mem_map[i].size || mem_map[i].attrs; i++) + max_addr = max(max_addr, mem_map[i].virt + mem_map[i].size); + + /* Calculate the maximum physical (and thus virtual) address */ + if (max_addr > (1ULL << 44)) { + ips = 5; + va_bits = 48; + } else if (max_addr > (1ULL << 42)) { + ips = 4; + va_bits = 44; + } else if (max_addr > (1ULL << 40)) { + ips = 3; + va_bits = 42; + } else if (max_addr > (1ULL << 36)) { + ips = 2; + va_bits = 40; + } else if (max_addr > (1ULL << 32)) { + ips = 1; + va_bits = 36; + } else { + ips = 0; + va_bits = 32; + } + + if (el == 1) { + tcr = TCR_EL1_RSVD | (ips << 32) | TCR_EPD1_DISABLE; + } else if (el == 2) { + tcr = TCR_EL2_RSVD | (ips << 16); + } else { + tcr = TCR_EL3_RSVD | (ips << 16); + } + + /* PTWs cacheable, inner/outer WBWA and inner shareable */ + tcr |= TCR_TG0_4K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA; + tcr |= TCR_T0SZ(va_bits); + + if (pips) + *pips = ips; + if (pva_bits) + *pva_bits = va_bits; + + return tcr; +} + +#define MAX_PTE_ENTRIES 512 + +static int pte_type(u64 *pte) +{ + return *pte & PTE_TYPE_MASK; +} + +/* Returns the LSB number for a PTE on level <level> */ +static int level2shift(int level) +{ + /* Page is 12 bits wide, every level translates 9 bits */ + return (12 + 9 * (3 - level)); +} + +static u64 *find_pte(u64 addr, int level) +{ + int start_level = 0; + u64 *pte; + u64 idx; + u64 va_bits; + int i; + + debug("addr=%llx level=%d\n", addr, level); + + get_tcr(0, NULL, &va_bits); + if (va_bits < 39) + start_level = 1; + + if (level < start_level) + return NULL; + + /* Walk through all page table levels to find our PTE */ + pte = (u64*)gd->arch.tlb_addr; + for (i = start_level; i < 4; i++) { + idx = (addr >> level2shift(i)) & 0x1FF; + pte += idx; + debug("idx=%llx PTE %p at level %d: %llx\n", idx, pte, i, *pte); + + /* Found it */ + if (i == level) + return pte; + /* PTE is no table (either invalid or block), can't traverse */ + if (pte_type(pte) != PTE_TYPE_TABLE) + return NULL; + /* Off to the next level */ + pte = (u64*)(*pte & 0x0000fffffffff000ULL); + } + + /* Should never reach here */ + return NULL; +} + +/* Returns and creates a new full table (512 entries) */ +static u64 *create_table(void) +{ + u64 *new_table = (u64*)gd->arch.tlb_fillptr; + u64 pt_len = MAX_PTE_ENTRIES * sizeof(u64); + + /* Allocate MAX_PTE_ENTRIES pte entries */ + gd->arch.tlb_fillptr += pt_len; + + if (gd->arch.tlb_fillptr - gd->arch.tlb_addr > gd->arch.tlb_size) + panic("Insufficient RAM for page table: 0x%lx > 0x%lx. " + "Please increase the size in get_page_table_size()", + gd->arch.tlb_fillptr - gd->arch.tlb_addr, + gd->arch.tlb_size); + + /* Mark all entries as invalid */ + memset(new_table, 0, pt_len); + + return new_table; +} + +static void set_pte_table(u64 *pte, u64 *table) +{ + /* Point *pte to the new table */ + debug("Setting %p to addr=%p\n", pte, table); + *pte = PTE_TYPE_TABLE | (ulong)table; +} + +/* Splits a block PTE into table with subpages spanning the old block */ +static void split_block(u64 *pte, int level) +{ + u64 old_pte = *pte; + u64 *new_table; + u64 i = 0; + /* level describes the parent level, we need the child ones */ + int levelshift = level2shift(level + 1); + + if (pte_type(pte) != PTE_TYPE_BLOCK) + panic("PTE %p (%llx) is not a block. Some driver code wants to " + "modify dcache settings for an range not covered in " + "mem_map.", pte, old_pte); + + new_table = create_table(); + debug("Splitting pte %p (%llx) into %p\n", pte, old_pte, new_table); + + for (i = 0; i < MAX_PTE_ENTRIES; i++) { + new_table[i] = old_pte | (i << levelshift); + + /* Level 3 block PTEs have the table type */ + if ((level + 1) == 3) + new_table[i] |= PTE_TYPE_TABLE; + + debug("Setting new_table[%lld] = %llx\n", i, new_table[i]); + } + + /* Set the new table into effect */ + set_pte_table(pte, new_table); +} + +/* Add one mm_region map entry to the page tables */ +static void add_map(struct mm_region *map) +{ + u64 *pte; + u64 virt = map->virt; + u64 phys = map->phys; + u64 size = map->size; + u64 attrs = map->attrs | PTE_TYPE_BLOCK | PTE_BLOCK_AF; + u64 blocksize; + int level; + u64 *new_table; + + while (size) { + pte = find_pte(virt, 0); + if (pte && (pte_type(pte) == PTE_TYPE_FAULT)) { + debug("Creating table for virt 0x%llx\n", virt); + new_table = create_table(); + set_pte_table(pte, new_table); + } + + for (level = 1; level < 4; level++) { + pte = find_pte(virt, level); + if (!pte) + panic("pte not found\n"); + + blocksize = 1ULL << level2shift(level); + debug("Checking if pte fits for virt=%llx size=%llx blocksize=%llx\n", + virt, size, blocksize); + if (size >= blocksize && !(virt & (blocksize - 1))) { + /* Page fits, create block PTE */ + debug("Setting PTE %p to block virt=%llx\n", + pte, virt); + if (level == 3) + *pte = phys | attrs | PTE_TYPE_PAGE; + else + *pte = phys | attrs; + virt += blocksize; + phys += blocksize; + size -= blocksize; + break; + } else if (pte_type(pte) == PTE_TYPE_FAULT) { + /* Page doesn't fit, create subpages */ + debug("Creating subtable for virt 0x%llx blksize=%llx\n", + virt, blocksize); + new_table = create_table(); + set_pte_table(pte, new_table); + } else if (pte_type(pte) == PTE_TYPE_BLOCK) { + debug("Split block into subtable for virt 0x%llx blksize=0x%llx\n", + virt, blocksize); + split_block(pte, level); + } + } + } +} + +enum pte_type { + PTE_INVAL, + PTE_BLOCK, + PTE_LEVEL, +}; + +/* + * This is a recursively called function to count the number of + * page tables we need to cover a particular PTE range. If you + * call this with level = -1 you basically get the full 48 bit + * coverage. + */ +static int count_required_pts(u64 addr, int level, u64 maxaddr) +{ + int levelshift = level2shift(level); + u64 levelsize = 1ULL << levelshift; + u64 levelmask = levelsize - 1; + u64 levelend = addr + levelsize; + int r = 0; + int i; + enum pte_type pte_type = PTE_INVAL; + + for (i = 0; mem_map[i].size || mem_map[i].attrs; i++) { + struct mm_region *map = &mem_map[i]; + u64 start = map->virt; + u64 end = start + map->size; + + /* Check if the PTE would overlap with the map */ + if (max(addr, start) <= min(levelend, end)) { + start = max(addr, start); + end = min(levelend, end); + + /* We need a sub-pt for this level */ + if ((start & levelmask) || (end & levelmask)) { + pte_type = PTE_LEVEL; + break; + } + + /* Lv0 can not do block PTEs, so do levels here too */ + if (level <= 0) { + pte_type = PTE_LEVEL; + break; + } + + /* PTE is active, but fits into a block */ + pte_type = PTE_BLOCK; + } + } + + /* + * Block PTEs at this level are already covered by the parent page + * table, so we only need to count sub page tables. + */ + if (pte_type == PTE_LEVEL) { + int sublevel = level + 1; + u64 sublevelsize = 1ULL << level2shift(sublevel); + + /* Account for the new sub page table ... */ + r = 1; + + /* ... and for all child page tables that one might have */ + for (i = 0; i < MAX_PTE_ENTRIES; i++) { + r += count_required_pts(addr, sublevel, maxaddr); + addr += sublevelsize; + + if (addr >= maxaddr) { + /* + * We reached the end of address space, no need + * to look any further. + */ + break; + } + } + } + + return r; +} + +/* Returns the estimated required size of all page tables */ +__weak u64 get_page_table_size(void) +{ + u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64); + u64 size = 0; + u64 va_bits; + int start_level = 0; + + get_tcr(0, NULL, &va_bits); + if (va_bits < 39) + start_level = 1; + + /* Account for all page tables we would need to cover our memory map */ + size = one_pt * count_required_pts(0, start_level - 1, 1ULL << va_bits); + + /* + * We need to duplicate our page table once to have an emergency pt to + * resort to when splitting page tables later on + */ + size *= 2; + + /* + * We may need to split page tables later on if dcache settings change, + * so reserve up to 4 (random pick) page tables for that. + */ + size += one_pt * 4; + + return size; +} + +void setup_pgtables(void) +{ + int i; + + if (!gd->arch.tlb_fillptr || !gd->arch.tlb_addr) + panic("Page table pointer not setup."); + + /* + * Allocate the first level we're on with invalidate entries. + * If the starting level is 0 (va_bits >= 39), then this is our + * Lv0 page table, otherwise it's the entry Lv1 page table. + */ + create_table(); + + /* Now add all MMU table entries one after another to the table */ + for (i = 0; mem_map[i].size || mem_map[i].attrs; i++) + add_map(&mem_map[i]); +} + +static void setup_all_pgtables(void) +{ + u64 tlb_addr = gd->arch.tlb_addr; + u64 tlb_size = gd->arch.tlb_size; + + /* Reset the fill ptr */ + gd->arch.tlb_fillptr = tlb_addr; + + /* Create normal system page tables */ + setup_pgtables(); + + /* Create emergency page tables */ + gd->arch.tlb_size -= (uintptr_t)gd->arch.tlb_fillptr - + (uintptr_t)gd->arch.tlb_addr; + gd->arch.tlb_addr = gd->arch.tlb_fillptr; + setup_pgtables(); + gd->arch.tlb_emerg = gd->arch.tlb_addr; + gd->arch.tlb_addr = tlb_addr; + gd->arch.tlb_size = tlb_size; +} + +/* to activate the MMU we need to set up virtual memory */ +__weak void mmu_setup(void) +{ + int el; + + /* Set up page tables only once */ + if (!gd->arch.tlb_fillptr) + setup_all_pgtables(); + + el = current_el(); + set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL), + MEMORY_ATTRIBUTES); + + /* enable the mmu */ + set_sctlr(get_sctlr() | CR_M); +} + +/* + * Performs a invalidation of the entire data cache at all levels + */ +void invalidate_dcache_all(void) +{ + __asm_invalidate_dcache_all(); + __asm_invalidate_l3_dcache(); +} + +/* + * Performs a clean & invalidation of the entire data cache at all levels. + * This function needs to be inline to avoid using stack. + * __asm_flush_l3_dcache return status of timeout + */ +inline void flush_dcache_all(void) +{ + int ret; + + __asm_flush_dcache_all(); + ret = __asm_flush_l3_dcache(); + if (ret) + debug("flushing dcache returns 0x%x\n", ret); + else + debug("flushing dcache successfully.\n"); +} + +/* + * Invalidates range in all levels of D-cache/unified cache + */ +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ + __asm_invalidate_dcache_range(start, stop); +} + +/* + * Flush range(clean & invalidate) from all levels of D-cache/unified cache + */ +void flush_dcache_range(unsigned long start, unsigned long stop) +{ + __asm_flush_dcache_range(start, stop); +} + +void dcache_enable(void) +{ + /* The data cache is not active unless the mmu is enabled */ + if (!(get_sctlr() & CR_M)) { + invalidate_dcache_all(); + __asm_invalidate_tlb_all(); + mmu_setup(); + } + + set_sctlr(get_sctlr() | CR_C); +} + +void dcache_disable(void) +{ + uint32_t sctlr; + + sctlr = get_sctlr(); + + /* if cache isn't enabled no need to disable */ + if (!(sctlr & CR_C)) + return; + + set_sctlr(sctlr & ~(CR_C|CR_M)); + + flush_dcache_all(); + __asm_invalidate_tlb_all(); +} + +int dcache_status(void) +{ + return (get_sctlr() & CR_C) != 0; +} + +u64 *__weak arch_get_page_table(void) { + puts("No page table offset defined\n"); + + return NULL; +} + +static bool is_aligned(u64 addr, u64 size, u64 align) +{ + return !(addr & (align - 1)) && !(size & (align - 1)); +} + +/* Use flag to indicate if attrs has more than d-cache attributes */ +static u64 set_one_region(u64 start, u64 size, u64 attrs, bool flag, int level) +{ + int levelshift = level2shift(level); + u64 levelsize = 1ULL << levelshift; + u64 *pte = find_pte(start, level); + + /* Can we can just modify the current level block PTE? */ + if (is_aligned(start, size, levelsize)) { + if (flag) { + *pte &= ~PMD_ATTRMASK; + *pte |= attrs & PMD_ATTRMASK; + } else { + *pte &= ~PMD_ATTRINDX_MASK; + *pte |= attrs & PMD_ATTRINDX_MASK; + } + debug("Set attrs=%llx pte=%p level=%d\n", attrs, pte, level); + + return levelsize; + } + + /* Unaligned or doesn't fit, maybe split block into table */ + debug("addr=%llx level=%d pte=%p (%llx)\n", start, level, pte, *pte); + + /* Maybe we need to split the block into a table */ + if (pte_type(pte) == PTE_TYPE_BLOCK) + split_block(pte, level); + + /* And then double-check it became a table or already is one */ + if (pte_type(pte) != PTE_TYPE_TABLE) + panic("PTE %p (%llx) for addr=%llx should be a table", + pte, *pte, start); + + /* Roll on to the next page table level */ + return 0; +} + +void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, + enum dcache_option option) +{ + u64 attrs = PMD_ATTRINDX(option); + u64 real_start = start; + u64 real_size = size; + + debug("start=%lx size=%lx\n", (ulong)start, (ulong)size); + + if (!gd->arch.tlb_emerg) + panic("Emergency page table not setup."); + + /* + * We can not modify page tables that we're currently running on, + * so we first need to switch to the "emergency" page tables where + * we can safely modify our primary page tables and then switch back + */ + __asm_switch_ttbr(gd->arch.tlb_emerg); + + /* + * Loop through the address range until we find a page granule that fits + * our alignment constraints, then set it to the new cache attributes + */ + while (size > 0) { + int level; + u64 r; + + for (level = 1; level < 4; level++) { + /* Set d-cache attributes only */ + r = set_one_region(start, size, attrs, false, level); + if (r) { + /* PTE successfully replaced */ + size -= r; + start += r; + break; + } + } + + } + + /* We're done modifying page tables, switch back to our primary ones */ + __asm_switch_ttbr(gd->arch.tlb_addr); + + /* + * Make sure there's nothing stale in dcache for a region that might + * have caches off now + */ + flush_dcache_range(real_start, real_start + real_size); +} + +/* + * Modify MMU table for a region with updated PXN/UXN/Memory type/valid bits. + * The procecess is break-before-make. The target region will be marked as + * invalid during the process of changing. + */ +void mmu_change_region_attr(phys_addr_t addr, size_t siz, u64 attrs) +{ + int level; + u64 r, size, start; + + start = addr; + size = siz; + /* + * Loop through the address range until we find a page granule that fits + * our alignment constraints, then set it to "invalid". + */ + while (size > 0) { + for (level = 1; level < 4; level++) { + /* Set PTE to fault */ + r = set_one_region(start, size, PTE_TYPE_FAULT, true, + level); + if (r) { + /* PTE successfully invalidated */ + size -= r; + start += r; + break; + } + } + } + + flush_dcache_range(gd->arch.tlb_addr, + gd->arch.tlb_addr + gd->arch.tlb_size); + __asm_invalidate_tlb_all(); + + /* + * Loop through the address range until we find a page granule that fits + * our alignment constraints, then set it to the new cache attributes + */ + start = addr; + size = siz; + while (size > 0) { + for (level = 1; level < 4; level++) { + /* Set PTE to new attributes */ + r = set_one_region(start, size, attrs, true, level); + if (r) { + /* PTE successfully updated */ + size -= r; + start += r; + break; + } + } + } + flush_dcache_range(gd->arch.tlb_addr, + gd->arch.tlb_addr + gd->arch.tlb_size); + __asm_invalidate_tlb_all(); +} + +#else /* CONFIG_SYS_DCACHE_OFF */ + +/* + * For SPL builds, we may want to not have dcache enabled. Any real U-Boot + * running however really wants to have dcache and the MMU active. Check that + * everything is sane and give the developer a hint if it isn't. + */ +#ifndef CONFIG_SPL_BUILD +#error Please describe your MMU layout in CONFIG_SYS_MEM_MAP and enable dcache. +#endif + +void invalidate_dcache_all(void) +{ +} + +void flush_dcache_all(void) +{ +} + +void dcache_enable(void) +{ +} + +void dcache_disable(void) +{ +} + +int dcache_status(void) +{ + return 0; +} + +void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, + enum dcache_option option) +{ +} + +#endif /* CONFIG_SYS_DCACHE_OFF */ + +#ifndef CONFIG_SYS_ICACHE_OFF + +void icache_enable(void) +{ + invalidate_icache_all(); + set_sctlr(get_sctlr() | CR_I); +} + +void icache_disable(void) +{ + set_sctlr(get_sctlr() & ~CR_I); +} + +int icache_status(void) +{ + return (get_sctlr() & CR_I) != 0; +} + +void invalidate_icache_all(void) +{ + __asm_invalidate_icache_all(); + __asm_invalidate_l3_icache(); +} + +#else /* CONFIG_SYS_ICACHE_OFF */ + +void icache_enable(void) +{ +} + +void icache_disable(void) +{ +} + +int icache_status(void) +{ + return 0; +} + +void invalidate_icache_all(void) +{ +} + +#endif /* CONFIG_SYS_ICACHE_OFF */ + +/* + * Enable dCache & iCache, whether cache is actually enabled + * depend on CONFIG_SYS_DCACHE_OFF and CONFIG_SYS_ICACHE_OFF + */ +void __weak enable_caches(void) +{ + icache_enable(); + dcache_enable(); +}
diff --git a/arch/arm/cpu/armv8/config.mk b/arch/arm/cpu/armv8/config.mk new file mode 100644 index 0000000..6f90931 --- /dev/null +++ b/arch/arm/cpu/armv8/config.mk
@@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> +PLATFORM_RELFLAGS += -fno-common -ffixed-x18 + +PF_NO_UNALIGNED := $(call cc-option, -mstrict-align) +PLATFORM_CPPFLAGS += $(PF_NO_UNALIGNED) + +EFI_LDS := elf_aarch64_efi.lds +EFI_CRT0 := crt0_aarch64_efi.o +EFI_RELOC := reloc_aarch64_efi.o
diff --git a/arch/arm/cpu/armv8/cpu-dt.c b/arch/arm/cpu/armv8/cpu-dt.c new file mode 100644 index 0000000..267abb8 --- /dev/null +++ b/arch/arm/cpu/armv8/cpu-dt.c
@@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2016 NXP Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/psci.h> +#include <asm/system.h> +#include <asm/armv8/sec_firmware.h> + +#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT +int psci_update_dt(void *fdt) +{ + /* + * If the PSCI in SEC Firmware didn't work, avoid to update the + * device node of PSCI. But still return 0 instead of an error + * number to support detecting PSCI dynamically and then switching + * the SMP boot method between PSCI and spin-table. + */ + if (sec_firmware_support_psci_version() == PSCI_INVALID_VER) + return 0; + fdt_psci(fdt); + +#if defined(CONFIG_ARMV8_PSCI) && !defined(CONFIG_ARMV8_SECURE_BASE) + /* secure code lives in RAM, keep it alive */ + fdt_add_mem_rsv(fdt, (unsigned long)__secure_start, + __secure_end - __secure_start); +#endif + + return 0; +} +#endif
diff --git a/arch/arm/cpu/armv8/cpu.c b/arch/arm/cpu/armv8/cpu.c new file mode 100644 index 0000000..b312b3b --- /dev/null +++ b/arch/arm/cpu/armv8/cpu.c
@@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2008 Texas Insturments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> +#include <asm/secure.h> +#include <linux/compiler.h> + +/* + * sdelay() - simple spin loop. + * + * Will delay execution by roughly (@loops * 2) cycles. + * This is necessary to be used before timers are accessible. + * + * A value of "0" will results in 2^64 loops. + */ +void sdelay(unsigned long loops) +{ + __asm__ volatile ("1:\n" "subs %0, %0, #1\n" + "b.ne 1b" : "=r" (loops) : "0"(loops) : "cc"); +} + +int cleanup_before_linux(void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * disable interrupt and turn off caches etc ... + */ + disable_interrupts(); + + /* + * Turn off I-cache and invalidate it + */ + icache_disable(); + invalidate_icache_all(); + + /* + * turn off D-cache + * dcache_disable() in turn flushes the d-cache and disables MMU + */ + dcache_disable(); + invalidate_dcache_all(); + + return 0; +} + +#ifdef CONFIG_ARMV8_PSCI +static void relocate_secure_section(void) +{ +#ifdef CONFIG_ARMV8_SECURE_BASE + size_t sz = __secure_end - __secure_start; + + memcpy((void *)CONFIG_ARMV8_SECURE_BASE, __secure_start, sz); + flush_dcache_range(CONFIG_ARMV8_SECURE_BASE, + CONFIG_ARMV8_SECURE_BASE + sz + 1); + invalidate_icache_all(); +#endif +} + +void armv8_setup_psci(void) +{ + relocate_secure_section(); + secure_ram_addr(psci_setup_vectors)(); + secure_ram_addr(psci_arch_init)(); +} +#endif
diff --git a/arch/arm/cpu/armv8/exceptions.S b/arch/arm/cpu/armv8/exceptions.S new file mode 100644 index 0000000..a15af72 --- /dev/null +++ b/arch/arm/cpu/armv8/exceptions.S
@@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <asm/ptrace.h> +#include <asm/macro.h> +#include <linux/linkage.h> + +/* + * AArch64 exception vectors: + * We have four types of exceptions: + * - synchronous: traps, data aborts, undefined instructions, ... + * - IRQ: group 1 (normal) interrupts + * - FIQ: group 0 or secure interrupts + * - SError: fatal system errors + * There are entries for all four of those for different contexts: + * - from same exception level, when using the SP_EL0 stack pointer + * - from same exception level, when using the SP_ELx stack pointer + * - from lower exception level, when this is AArch64 + * - from lower exception level, when this is AArch32 + * Each of those 16 entries have space for 32 instructions, each entry must + * be 128 byte aligned, the whole table must be 2K aligned. + * The 32 instructions are not enough to save and restore all registers and + * to branch to the actual handler, so we split this up: + * Each entry saves the LR, branches to the save routine, then to the actual + * handler, then to the restore routine. The save and restore routines are + * each split in half and stuffed in the unused gap between the entries. + * Also as we do not run anything in a lower exception level, we just provide + * the first 8 entries for exceptions from the same EL. + */ + .align 11 + .globl vectors +vectors: + .align 7 /* Current EL Synchronous Thread */ + stp x29, x30, [sp, #-16]! + bl _exception_entry + bl do_bad_sync + b exception_exit + +/* + * Save (most of) the GP registers to the stack frame. + * This is the first part of the shared routine called into from all entries. + */ +_exception_entry: + stp x27, x28, [sp, #-16]! + stp x25, x26, [sp, #-16]! + stp x23, x24, [sp, #-16]! + stp x21, x22, [sp, #-16]! + stp x19, x20, [sp, #-16]! + stp x17, x18, [sp, #-16]! + stp x15, x16, [sp, #-16]! + stp x13, x14, [sp, #-16]! + stp x11, x12, [sp, #-16]! + stp x9, x10, [sp, #-16]! + stp x7, x8, [sp, #-16]! + stp x5, x6, [sp, #-16]! + stp x3, x4, [sp, #-16]! + stp x1, x2, [sp, #-16]! + b _save_el_regs /* jump to the second part */ + + .align 7 /* Current EL IRQ Thread */ + stp x29, x30, [sp, #-16]! + bl _exception_entry + bl do_bad_irq + b exception_exit + +/* + * Save exception specific context: ESR and ELR, for all exception levels. + * This is the second part of the shared routine called into from all entries. + */ +_save_el_regs: + /* Could be running at EL3/EL2/EL1 */ + switch_el x11, 3f, 2f, 1f +3: mrs x1, esr_el3 + mrs x2, elr_el3 + b 0f +2: mrs x1, esr_el2 + mrs x2, elr_el2 + b 0f +1: mrs x1, esr_el1 + mrs x2, elr_el1 +0: + stp x2, x0, [sp, #-16]! + mov x0, sp + ret + + .align 7 /* Current EL FIQ Thread */ + stp x29, x30, [sp, #-16]! + bl _exception_entry + bl do_bad_fiq + /* falling through to _exception_exit */ +/* + * Restore the exception return address, for all exception levels. + * This is the first part of the shared routine called into from all entries. + */ +exception_exit: + ldp x2, x0, [sp],#16 + switch_el x11, 3f, 2f, 1f +3: msr elr_el3, x2 + b _restore_regs +2: msr elr_el2, x2 + b _restore_regs +1: msr elr_el1, x2 + b _restore_regs /* jump to the second part */ + + .align 7 /* Current EL Error Thread */ + stp x29, x30, [sp, #-16]! + bl _exception_entry + bl do_bad_error + b exception_exit + +/* + * Restore the general purpose registers from the exception stack, then return. + * This is the second part of the shared routine called into from all entries. + */ +_restore_regs: + ldp x1, x2, [sp],#16 + ldp x3, x4, [sp],#16 + ldp x5, x6, [sp],#16 + ldp x7, x8, [sp],#16 + ldp x9, x10, [sp],#16 + ldp x11, x12, [sp],#16 + ldp x13, x14, [sp],#16 + ldp x15, x16, [sp],#16 + ldp x17, x18, [sp],#16 + ldp x19, x20, [sp],#16 + ldp x21, x22, [sp],#16 + ldp x23, x24, [sp],#16 + ldp x25, x26, [sp],#16 + ldp x27, x28, [sp],#16 + ldp x29, x30, [sp],#16 + eret + + .align 7 /* Current EL (SP_ELx) Synchronous Handler */ + stp x29, x30, [sp, #-16]! + bl _exception_entry + bl do_sync + b exception_exit + + .align 7 /* Current EL (SP_ELx) IRQ Handler */ + stp x29, x30, [sp, #-16]! + bl _exception_entry + bl do_irq + b exception_exit + + .align 7 /* Current EL (SP_ELx) FIQ Handler */ + stp x29, x30, [sp, #-16]! + bl _exception_entry + bl do_fiq + b exception_exit + + .align 7 /* Current EL (SP_ELx) Error Handler */ + stp x29, x30, [sp, #-16]! + bl _exception_entry + bl do_error + b exception_exit
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig new file mode 100644 index 0000000..b55b36c --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -0,0 +1,574 @@ +config ARCH_LS1012A + bool + select ARMV8_SET_SMPEN + select ARM_ERRATA_855873 if !TFABOOT + select FSL_LSCH2 + select SYS_FSL_SRDS_1 + select SYS_HAS_SERDES + select SYS_FSL_DDR_BE + select SYS_FSL_MMDC + select SYS_FSL_ERRATUM_A010315 + select SYS_FSL_ERRATUM_A009798 + select SYS_FSL_ERRATUM_A008997 + select SYS_FSL_ERRATUM_A009007 + select SYS_FSL_ERRATUM_A009008 + select ARCH_EARLY_INIT_R + select BOARD_EARLY_INIT_F + select SYS_I2C_MXC + select SYS_I2C_MXC_I2C1 + select SYS_I2C_MXC_I2C2 + imply PANIC_HANG + +config ARCH_LS1043A + bool + select ARMV8_SET_SMPEN + select ARM_ERRATA_855873 if !TFABOOT + select FSL_LSCH2 + select SYS_FSL_SRDS_1 + select SYS_HAS_SERDES + select SYS_FSL_DDR + select SYS_FSL_DDR_BE + select SYS_FSL_DDR_VER_50 + select SYS_FSL_ERRATUM_A008850 if !TFABOOT + select SYS_FSL_ERRATUM_A008997 + select SYS_FSL_ERRATUM_A009007 + select SYS_FSL_ERRATUM_A009008 + select SYS_FSL_ERRATUM_A009660 if !TFABOOT + select SYS_FSL_ERRATUM_A009663 if !TFABOOT + select SYS_FSL_ERRATUM_A009798 + select SYS_FSL_ERRATUM_A009929 + select SYS_FSL_ERRATUM_A009942 if !TFABOOT + select SYS_FSL_ERRATUM_A010315 + select SYS_FSL_ERRATUM_A010539 + select SYS_FSL_HAS_DDR3 + select SYS_FSL_HAS_DDR4 + select ARCH_EARLY_INIT_R + select BOARD_EARLY_INIT_F + select SYS_I2C_MXC + select SYS_I2C_MXC_I2C1 + select SYS_I2C_MXC_I2C2 + select SYS_I2C_MXC_I2C3 + select SYS_I2C_MXC_I2C4 + imply SCSI + imply SCSI_AHCI + imply CMD_PCI + +config ARCH_LS1046A + bool + select ARMV8_SET_SMPEN + select FSL_LSCH2 + select SYS_FSL_SRDS_1 + select SYS_HAS_SERDES + select SYS_FSL_DDR + select SYS_FSL_DDR_BE + select SYS_FSL_DDR_VER_50 + select SYS_FSL_ERRATUM_A008336 if !TFABOOT + select SYS_FSL_ERRATUM_A008511 if !TFABOOT + select SYS_FSL_ERRATUM_A008850 if !TFABOOT + select SYS_FSL_ERRATUM_A008997 + select SYS_FSL_ERRATUM_A009007 + select SYS_FSL_ERRATUM_A009008 + select SYS_FSL_ERRATUM_A009798 + select SYS_FSL_ERRATUM_A009801 + select SYS_FSL_ERRATUM_A009803 if !TFABOOT + select SYS_FSL_ERRATUM_A009942 if !TFABOOT + select SYS_FSL_ERRATUM_A010165 if !TFABOOT + select SYS_FSL_ERRATUM_A010539 + select SYS_FSL_HAS_DDR4 + select SYS_FSL_SRDS_2 + select ARCH_EARLY_INIT_R + select BOARD_EARLY_INIT_F + select SYS_I2C_MXC + select SYS_I2C_MXC_I2C1 + select SYS_I2C_MXC_I2C2 + select SYS_I2C_MXC_I2C3 + select SYS_I2C_MXC_I2C4 + imply SCSI + imply SCSI_AHCI + +config ARCH_LS1088A + bool + select ARMV8_SET_SMPEN + select ARM_ERRATA_855873 + select FSL_LSCH3 + select SYS_FSL_SRDS_1 + select SYS_HAS_SERDES + select SYS_FSL_DDR + select SYS_FSL_DDR_LE + select SYS_FSL_DDR_VER_50 + select SYS_FSL_EC1 + select SYS_FSL_EC2 + select SYS_FSL_ERRATUM_A009803 + select SYS_FSL_ERRATUM_A009942 + select SYS_FSL_ERRATUM_A010165 + select SYS_FSL_ERRATUM_A008511 + select SYS_FSL_ERRATUM_A008850 + select SYS_FSL_ERRATUM_A009007 + select SYS_FSL_HAS_CCI400 + select SYS_FSL_HAS_DDR4 + select SYS_FSL_HAS_RGMII + select SYS_FSL_HAS_SEC + select SYS_FSL_SEC_COMPAT_5 + select SYS_FSL_SEC_LE + select SYS_FSL_SRDS_1 + select SYS_FSL_SRDS_2 + select FSL_TZASC_1 + select ARCH_EARLY_INIT_R + select BOARD_EARLY_INIT_F + select SYS_I2C_MXC + select SYS_I2C_MXC_I2C1 + select SYS_I2C_MXC_I2C2 + select SYS_I2C_MXC_I2C3 + select SYS_I2C_MXC_I2C4 + imply SCSI + imply PANIC_HANG + +config ARCH_LS2080A + bool + select ARMV8_SET_SMPEN + select ARM_ERRATA_826974 + select ARM_ERRATA_828024 + select ARM_ERRATA_829520 + select ARM_ERRATA_833471 + select FSL_LSCH3 + select SYS_FSL_SRDS_1 + select SYS_HAS_SERDES + select SYS_FSL_DDR + select SYS_FSL_DDR_LE + select SYS_FSL_DDR_VER_50 + select SYS_FSL_HAS_CCN504 + select SYS_FSL_HAS_DP_DDR + select SYS_FSL_HAS_SEC + select SYS_FSL_HAS_DDR4 + select SYS_FSL_SEC_COMPAT_5 + select SYS_FSL_SEC_LE + select SYS_FSL_SRDS_2 + select FSL_TZASC_1 + select FSL_TZASC_2 + select SYS_FSL_ERRATUM_A008336 + select SYS_FSL_ERRATUM_A008511 + select SYS_FSL_ERRATUM_A008514 + select SYS_FSL_ERRATUM_A008585 + select SYS_FSL_ERRATUM_A008997 + select SYS_FSL_ERRATUM_A009007 + select SYS_FSL_ERRATUM_A009008 + select SYS_FSL_ERRATUM_A009635 + select SYS_FSL_ERRATUM_A009663 + select SYS_FSL_ERRATUM_A009798 + select SYS_FSL_ERRATUM_A009801 + select SYS_FSL_ERRATUM_A009803 + select SYS_FSL_ERRATUM_A009942 + select SYS_FSL_ERRATUM_A010165 + select SYS_FSL_ERRATUM_A009203 + select ARCH_EARLY_INIT_R + select BOARD_EARLY_INIT_F + select SYS_I2C_MXC + select SYS_I2C_MXC_I2C1 + select SYS_I2C_MXC_I2C2 + select SYS_I2C_MXC_I2C3 + select SYS_I2C_MXC_I2C4 + imply DISTRO_DEFAULTS + imply PANIC_HANG + +config ARCH_LX2160A + bool + select ARMV8_SET_SMPEN + select FSL_LSCH3 + select NXP_LSCH3_2 + select SYS_HAS_SERDES + select SYS_FSL_SRDS_1 + select SYS_FSL_SRDS_2 + select SYS_NXP_SRDS_3 + select SYS_FSL_DDR + select SYS_FSL_DDR_LE + select SYS_FSL_DDR_VER_50 + select SYS_FSL_EC1 + select SYS_FSL_EC2 + select SYS_FSL_HAS_RGMII + select SYS_FSL_HAS_SEC + select SYS_FSL_HAS_CCN508 + select SYS_FSL_HAS_DDR4 + select SYS_FSL_SEC_COMPAT_5 + select SYS_FSL_SEC_LE + select ARCH_EARLY_INIT_R + select BOARD_EARLY_INIT_F + select SYS_I2C_MXC + select SYS_I2C_MXC_I2C1 + select SYS_I2C_MXC_I2C2 + select SYS_I2C_MXC_I2C3 + select SYS_I2C_MXC_I2C4 + select SYS_I2C_MXC_I2C5 + select SYS_I2C_MXC_I2C6 + select SYS_I2C_MXC_I2C7 + select SYS_I2C_MXC_I2C8 + imply DISTRO_DEFAULTS + imply PANIC_HANG + imply SCSI + imply SCSI_AHCI + +config FSL_LSCH2 + bool + select SYS_FSL_HAS_CCI400 + select SYS_FSL_HAS_SEC + select SYS_FSL_SEC_COMPAT_5 + select SYS_FSL_SEC_BE + +config FSL_LSCH3 + bool + +config NXP_LSCH3_2 + bool + +config FSL_MC_ENET + bool "Management Complex network" + depends on ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A + default y + select RESV_RAM + help + Enable Management Complex (MC) network + +menu "Layerscape architecture" + depends on FSL_LSCH2 || FSL_LSCH3 + +config FSL_PCIE_COMPAT + string "PCIe compatible of Kernel DT" + depends on PCIE_LAYERSCAPE + default "fsl,ls1012a-pcie" if ARCH_LS1012A + default "fsl,ls1043a-pcie" if ARCH_LS1043A + default "fsl,ls1046a-pcie" if ARCH_LS1046A + default "fsl,ls2080a-pcie" if ARCH_LS2080A + default "fsl,ls1088a-pcie" if ARCH_LS1088A + default "fsl,lx2160a-pcie" if ARCH_LX2160A + help + This compatible is used to find pci controller node in Kernel DT + to complete fixup. + +config HAS_FEATURE_GIC64K_ALIGN + bool + default y if ARCH_LS1043A + +config HAS_FEATURE_ENHANCED_MSI + bool + default y if ARCH_LS1043A + +menu "Layerscape PPA" +config FSL_LS_PPA + bool "FSL Layerscape PPA firmware support" + depends on !ARMV8_PSCI + select ARMV8_SEC_FIRMWARE_SUPPORT + select SEC_FIRMWARE_ARMV8_PSCI + select ARMV8_SEC_FIRMWARE_ERET_ADDR_REVERT if FSL_LSCH2 + help + The FSL Primary Protected Application (PPA) is a software component + which is loaded during boot stage, and then remains resident in RAM + and runs in the TrustZone after boot. + Say y to enable it. + +config SPL_FSL_LS_PPA + bool "FSL Layerscape PPA firmware support for SPL build" + depends on !ARMV8_PSCI + select SPL_ARMV8_SEC_FIRMWARE_SUPPORT + select SEC_FIRMWARE_ARMV8_PSCI + select ARMV8_SEC_FIRMWARE_ERET_ADDR_REVERT if FSL_LSCH2 + help + The FSL Primary Protected Application (PPA) is a software component + which is loaded during boot stage, and then remains resident in RAM + and runs in the TrustZone after boot. This is to load PPA during SPL + stage instead of the RAM version of U-Boot. Once PPA is initialized, + the rest of U-Boot (including RAM version) runs at EL2. +choice + prompt "FSL Layerscape PPA firmware loading-media select" + depends on FSL_LS_PPA + default SYS_LS_PPA_FW_IN_MMC if SD_BOOT + default SYS_LS_PPA_FW_IN_NAND if NAND_BOOT + default SYS_LS_PPA_FW_IN_XIP + +config SYS_LS_PPA_FW_IN_XIP + bool "XIP" + help + Say Y here if the PPA firmware locate at XIP flash, such + as NOR or QSPI flash. + +config SYS_LS_PPA_FW_IN_MMC + bool "eMMC or SD Card" + help + Say Y here if the PPA firmware locate at eMMC/SD card. + +config SYS_LS_PPA_FW_IN_NAND + bool "NAND" + help + Say Y here if the PPA firmware locate at NAND flash. + +endchoice + +config LS_PPA_ESBC_HDR_SIZE + hex "Length of PPA ESBC header" + depends on FSL_LS_PPA && CHAIN_OF_TRUST && !SYS_LS_PPA_FW_IN_XIP + default 0x2000 + help + Length (in bytes) of PPA ESBC header to be copied from MMC/SD or + NAND to memory to validate PPA image. + +endmenu + +config SYS_FSL_ERRATUM_A008997 + bool "Workaround for USB PHY erratum A008997" + +config SYS_FSL_ERRATUM_A009007 + bool + help + Workaround for USB PHY erratum A009007 + +config SYS_FSL_ERRATUM_A009008 + bool "Workaround for USB PHY erratum A009008" + +config SYS_FSL_ERRATUM_A009798 + bool "Workaround for USB PHY erratum A009798" + +config SYS_FSL_ERRATUM_A010315 + bool "Workaround for PCIe erratum A010315" + +config SYS_FSL_ERRATUM_A010539 + bool "Workaround for PIN MUX erratum A010539" + +config MAX_CPUS + int "Maximum number of CPUs permitted for Layerscape" + default 4 if ARCH_LS1043A + default 4 if ARCH_LS1046A + default 16 if ARCH_LS2080A + default 8 if ARCH_LS1088A + default 16 if ARCH_LX2160A + default 1 + help + Set this number to the maximum number of possible CPUs in the SoC. + SoCs may have multiple clusters with each cluster may have multiple + ports. If some ports are reserved but higher ports are used for + cores, count the reserved ports. This will allocate enough memory + in spin table to properly handle all cores. + +config SECURE_BOOT + bool "Secure Boot" + help + Enable Freescale Secure Boot feature + +config QSPI_AHB_INIT + bool "Init the QSPI AHB bus" + help + The default setting for QSPI AHB bus just support 3bytes addressing. + But some QSPI flash size up to 64MBytes, so initialize the QSPI AHB + bus for those flashes to support the full QSPI flash size. + +config SYS_CCI400_OFFSET + hex "Offset for CCI400 base" + depends on SYS_FSL_HAS_CCI400 + default 0x3090000 if ARCH_LS1088A + default 0x180000 if FSL_LSCH2 + help + Offset for CCI400 base + CCI400 base addr = CCSRBAR + CCI400_OFFSET + +config SYS_FSL_IFC_BANK_COUNT + int "Maximum banks of Integrated flash controller" + depends on ARCH_LS1043A || ARCH_LS1046A || ARCH_LS2080A || ARCH_LS1088A + default 4 if ARCH_LS1043A + default 4 if ARCH_LS1046A + default 8 if ARCH_LS2080A || ARCH_LS1088A + +config SYS_FSL_HAS_CCI400 + bool + +config SYS_FSL_HAS_CCN504 + bool + +config SYS_FSL_HAS_CCN508 + bool + +config SYS_FSL_HAS_DP_DDR + bool + +config SYS_FSL_SRDS_1 + bool + +config SYS_FSL_SRDS_2 + bool + +config SYS_NXP_SRDS_3 + bool + +config SYS_HAS_SERDES + bool + +config FSL_TZASC_1 + bool + +config FSL_TZASC_2 + bool + +endmenu + +menu "Layerscape clock tree configuration" + depends on FSL_LSCH2 || FSL_LSCH3 + +config SYS_FSL_CLK + bool "Enable clock tree initialization" + default y + +config CLUSTER_CLK_FREQ + int "Reference clock of core cluster" + depends on ARCH_LS1012A + default 100000000 + help + This number is the reference clock frequency of core PLL. + For most platforms, the core PLL and Platform PLL have the same + reference clock, but for some platforms, LS1012A for instance, + they are provided sepatately. + +config SYS_FSL_PCLK_DIV + int "Platform clock divider" + default 1 if ARCH_LS1043A + default 1 if ARCH_LS1046A + default 1 if ARCH_LS1088A + default 2 + help + This is the divider that is used to derive Platform clock from + Platform PLL, in another word: + Platform_clk = Platform_PLL_freq / this_divider + +config SYS_FSL_DSPI_CLK_DIV + int "DSPI clock divider" + default 1 if ARCH_LS1043A + default 2 + help + This is the divider that is used to derive DSPI clock from Platform + clock, in another word DSPI_clk = Platform_clk / this_divider. + +config SYS_FSL_DUART_CLK_DIV + int "DUART clock divider" + default 1 if ARCH_LS1043A + default 4 if ARCH_LX2160A + default 2 + help + This is the divider that is used to derive DUART clock from Platform + clock, in another word DUART_clk = Platform_clk / this_divider. + +config SYS_FSL_I2C_CLK_DIV + int "I2C clock divider" + default 1 if ARCH_LS1043A + default 2 + help + This is the divider that is used to derive I2C clock from Platform + clock, in another word I2C_clk = Platform_clk / this_divider. + +config SYS_FSL_IFC_CLK_DIV + int "IFC clock divider" + default 1 if ARCH_LS1043A + default 2 + help + This is the divider that is used to derive IFC clock from Platform + clock, in another word IFC_clk = Platform_clk / this_divider. + +config SYS_FSL_LPUART_CLK_DIV + int "LPUART clock divider" + default 1 if ARCH_LS1043A + default 2 + help + This is the divider that is used to derive LPUART clock from Platform + clock, in another word LPUART_clk = Platform_clk / this_divider. + +config SYS_FSL_SDHC_CLK_DIV + int "SDHC clock divider" + default 1 if ARCH_LS1043A + default 1 if ARCH_LS1012A + default 2 + help + This is the divider that is used to derive SDHC clock from Platform + clock, in another word SDHC_clk = Platform_clk / this_divider. + +config SYS_FSL_QMAN_CLK_DIV + int "QMAN clock divider" + default 1 if ARCH_LS1043A + default 2 + help + This is the divider that is used to derive QMAN clock from Platform + clock, in another word QMAN_clk = Platform_clk / this_divider. +endmenu + +config RESV_RAM + bool + help + Reserve memory from the top, tracked by gd->arch.resv_ram. This + reserved RAM can be used by special driver that resides in memory + after U-Boot exits. It's up to implementation to allocate and allow + access to this reserved memory. For example, the reserved RAM can + be at the high end of physical memory. The reserve RAM may be + excluded from memory bank(s) passed to OS, or marked as reserved. + +config SYS_FSL_EC1 + bool + help + Ethernet controller 1, this is connected to + MAC17 for LX2160A or to MAC3 for other SoCs + Provides DPAA2 capabilities + +config SYS_FSL_EC2 + bool + help + Ethernet controller 2, this is connected to + MAC18 for LX2160A or to MAC4 for other SoCs + Provides DPAA2 capabilities + +config SYS_FSL_ERRATUM_A008336 + bool + +config SYS_FSL_ERRATUM_A008514 + bool + +config SYS_FSL_ERRATUM_A008585 + bool + +config SYS_FSL_ERRATUM_A008850 + bool + +config SYS_FSL_ERRATUM_A009203 + bool + +config SYS_FSL_ERRATUM_A009635 + bool + +config SYS_FSL_ERRATUM_A009660 + bool + +config SYS_FSL_ERRATUM_A009929 + bool + + +config SYS_FSL_HAS_RGMII + bool + depends on SYS_FSL_EC1 || SYS_FSL_EC2 + + +config SYS_MC_RSV_MEM_ALIGN + hex "Management Complex reserved memory alignment" + depends on RESV_RAM + default 0x20000000 if ARCH_LS2080A || ARCH_LS1088A || ARCH_LX2160A + help + Reserved memory needs to be aligned for MC to use. Default value + is 512MB. + +config SPL_LDSCRIPT + default "arch/arm/cpu/armv8/u-boot-spl.lds" if ARCH_LS1043A || ARCH_LS1046A || ARCH_LS2080A + +config HAS_FSL_XHCI_USB + bool + default y if ARCH_LS1043A || ARCH_LS1046A + help + For some SoC(such as LS1043A and LS1046A), USB and QE-HDLC multiplex use + pins, select it when the pins are assigned to USB. + +config TFABOOT + bool "Support for booting from TFA" + default n + help + Enabling this will make a U-Boot binary that is capable of being + booted via TFA. +
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Makefile b/arch/arm/cpu/armv8/fsl-layerscape/Makefile new file mode 100644 index 0000000..e9bc987 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
@@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright 2016-2018 NXP +# Copyright 2014-2015, Freescale Semiconductor + +obj-y += cpu.o +obj-y += lowlevel.o +obj-y += soc.o +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_MP) += mp.o +obj-$(CONFIG_OF_LIBFDT) += fdt.o +endif +obj-$(CONFIG_SPL) += spl.o +obj-$(CONFIG_$(SPL_)FSL_LS_PPA) += ppa.o + +ifneq ($(CONFIG_FSL_LSCH3),) +obj-y += fsl_lsch3_speed.o +obj-$(CONFIG_SYS_HAS_SERDES) += fsl_lsch3_serdes.o +else +ifneq ($(CONFIG_FSL_LSCH2),) +obj-y += fsl_lsch2_speed.o +obj-$(CONFIG_SYS_HAS_SERDES) += fsl_lsch2_serdes.o +endif +endif + +ifneq ($(CONFIG_ARCH_LX2160A),) +obj-$(CONFIG_SYS_HAS_SERDES) += lx2160a_serdes.o +endif + +ifneq ($(CONFIG_ARCH_LS2080A),) +obj-$(CONFIG_SYS_HAS_SERDES) += ls2080a_serdes.o +endif + +ifneq ($(CONFIG_ARCH_LS1043A),) +obj-$(CONFIG_SYS_HAS_SERDES) += ls1043a_serdes.o +obj-$(CONFIG_ARMV8_PSCI) += ls1043a_psci.o +obj-y += icid.o ls1043_ids.o +endif + +ifneq ($(CONFIG_ARCH_LS1012A),) +obj-$(CONFIG_SYS_HAS_SERDES) += ls1012a_serdes.o +endif + +ifneq ($(CONFIG_ARCH_LS1046A),) +obj-$(CONFIG_SYS_HAS_SERDES) += ls1046a_serdes.o +obj-y += icid.o ls1046_ids.o +endif + +ifneq ($(CONFIG_ARCH_LS1088A),) +obj-$(CONFIG_SYS_HAS_SERDES) += ls1088a_serdes.o +endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c new file mode 100644 index 0000000..1fc025b --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -0,0 +1,1580 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017 NXP + * Copyright 2014-2015 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <fsl_ddr_sdram.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/system.h> +#include <fm_eth.h> +#include <asm/armv8/mmu.h> +#include <asm/io.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch/soc.h> +#include <asm/arch/cpu.h> +#include <asm/arch/speed.h> +#include <fsl_immap.h> +#include <asm/arch/mp.h> +#include <efi_loader.h> +#include <fsl-mc/fsl_mc.h> +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> +#endif +#include <asm/armv8/sec_firmware.h> +#ifdef CONFIG_SYS_FSL_DDR +#include <fsl_ddr.h> +#endif +#include <asm/arch/clock.h> +#include <hwconfig.h> +#include <fsl_qbman.h> + +#ifdef CONFIG_TFABOOT +#include <environment.h> +#ifdef CONFIG_CHAIN_OF_TRUST +#include <fsl_validate.h> +#endif +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static struct cpu_type cpu_type_list[] = { + CPU_TYPE_ENTRY(LS2080A, LS2080A, 8), + CPU_TYPE_ENTRY(LS2085A, LS2085A, 8), + CPU_TYPE_ENTRY(LS2045A, LS2045A, 4), + CPU_TYPE_ENTRY(LS2088A, LS2088A, 8), + CPU_TYPE_ENTRY(LS2084A, LS2084A, 8), + CPU_TYPE_ENTRY(LS2048A, LS2048A, 4), + CPU_TYPE_ENTRY(LS2044A, LS2044A, 4), + CPU_TYPE_ENTRY(LS2081A, LS2081A, 8), + CPU_TYPE_ENTRY(LS2041A, LS2041A, 4), + CPU_TYPE_ENTRY(LS1043A, LS1043A, 4), + CPU_TYPE_ENTRY(LS1023A, LS1023A, 2), + CPU_TYPE_ENTRY(LS1046A, LS1046A, 4), + CPU_TYPE_ENTRY(LS1026A, LS1026A, 2), + CPU_TYPE_ENTRY(LS2040A, LS2040A, 4), + CPU_TYPE_ENTRY(LS1012A, LS1012A, 1), + CPU_TYPE_ENTRY(LS1088A, LS1088A, 8), + CPU_TYPE_ENTRY(LS1084A, LS1084A, 8), + CPU_TYPE_ENTRY(LS1048A, LS1048A, 4), + CPU_TYPE_ENTRY(LS1044A, LS1044A, 4), + CPU_TYPE_ENTRY(LX2160A, LX2160A, 16), + CPU_TYPE_ENTRY(LX2120A, LX2120A, 12), + CPU_TYPE_ENTRY(LX2080A, LX2080A, 8), +}; + +#define EARLY_PGTABLE_SIZE 0x5000 +static struct mm_region early_map[] = { +#ifdef CONFIG_FSL_LSCH3 + { CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE, + CONFIG_SYS_FSL_CCSR_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE, + SYS_FSL_OCRAM_SPACE_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE + }, + { CONFIG_SYS_FSL_QSPI_BASE1, CONFIG_SYS_FSL_QSPI_BASE1, + CONFIG_SYS_FSL_QSPI_SIZE1, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE}, +#ifdef CONFIG_FSL_IFC + /* For IFC Region #1, only the first 4MB is cache-enabled */ + { CONFIG_SYS_FSL_IFC_BASE1, CONFIG_SYS_FSL_IFC_BASE1, + CONFIG_SYS_FSL_IFC_SIZE1_1, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE + }, + { CONFIG_SYS_FSL_IFC_BASE1 + CONFIG_SYS_FSL_IFC_SIZE1_1, + CONFIG_SYS_FSL_IFC_BASE1 + CONFIG_SYS_FSL_IFC_SIZE1_1, + CONFIG_SYS_FSL_IFC_SIZE1 - CONFIG_SYS_FSL_IFC_SIZE1_1, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE + }, + { CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FSL_IFC_BASE1, + CONFIG_SYS_FSL_IFC_SIZE1, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE + }, +#endif + { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1, + CONFIG_SYS_FSL_DRAM_SIZE1, +#if defined(CONFIG_TFABOOT) || \ + (defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)) + PTE_BLOCK_MEMTYPE(MT_NORMAL) | +#else /* Start with nGnRnE and PXN and UXN to prevent speculative access */ + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN | +#endif + PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS + }, +#ifdef CONFIG_FSL_IFC + /* Map IFC region #2 up to CONFIG_SYS_FLASH_BASE for NAND boot */ + { CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2, + CONFIG_SYS_FLASH_BASE - CONFIG_SYS_FSL_IFC_BASE2, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE + }, +#endif + { CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE, + CONFIG_SYS_FSL_DCSR_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2, + CONFIG_SYS_FSL_DRAM_SIZE2, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN | + PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS + }, +#ifdef CONFIG_SYS_FSL_DRAM_BASE3 + { CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3, + CONFIG_SYS_FSL_DRAM_SIZE3, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN | + PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS + }, +#endif +#elif defined(CONFIG_FSL_LSCH2) + { CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE, + CONFIG_SYS_FSL_CCSR_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE, + SYS_FSL_OCRAM_SPACE_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE + }, + { CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE, + CONFIG_SYS_FSL_DCSR_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_QSPI_BASE, CONFIG_SYS_FSL_QSPI_BASE, + CONFIG_SYS_FSL_QSPI_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE + }, +#ifdef CONFIG_FSL_IFC + { CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE, + CONFIG_SYS_FSL_IFC_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE + }, +#endif + { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1, + CONFIG_SYS_FSL_DRAM_SIZE1, +#if defined(CONFIG_TFABOOT) || \ + (defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)) + PTE_BLOCK_MEMTYPE(MT_NORMAL) | +#else /* Start with nGnRnE and PXN and UXN to prevent speculative access */ + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN | +#endif + PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS + }, + { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2, + CONFIG_SYS_FSL_DRAM_SIZE2, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN | + PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS + }, +#endif + {}, /* list terminator */ +}; + +static struct mm_region final_map[] = { +#ifdef CONFIG_FSL_LSCH3 + { CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE, + CONFIG_SYS_FSL_CCSR_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE, + SYS_FSL_OCRAM_SPACE_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE + }, + { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1, + CONFIG_SYS_FSL_DRAM_SIZE1, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS + }, + { CONFIG_SYS_FSL_QSPI_BASE1, CONFIG_SYS_FSL_QSPI_BASE1, + CONFIG_SYS_FSL_QSPI_SIZE1, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_QSPI_BASE2, CONFIG_SYS_FSL_QSPI_BASE2, + CONFIG_SYS_FSL_QSPI_SIZE2, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, +#ifdef CONFIG_FSL_IFC + { CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2, + CONFIG_SYS_FSL_IFC_SIZE2, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, +#endif + { CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE, + CONFIG_SYS_FSL_DCSR_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_MC_BASE, CONFIG_SYS_FSL_MC_BASE, + CONFIG_SYS_FSL_MC_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_NI_BASE, CONFIG_SYS_FSL_NI_BASE, + CONFIG_SYS_FSL_NI_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + /* For QBMAN portal, only the first 64MB is cache-enabled */ + { CONFIG_SYS_FSL_QBMAN_BASE, CONFIG_SYS_FSL_QBMAN_BASE, + CONFIG_SYS_FSL_QBMAN_SIZE_1, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_BLOCK_NS + }, + { CONFIG_SYS_FSL_QBMAN_BASE + CONFIG_SYS_FSL_QBMAN_SIZE_1, + CONFIG_SYS_FSL_QBMAN_BASE + CONFIG_SYS_FSL_QBMAN_SIZE_1, + CONFIG_SYS_FSL_QBMAN_SIZE - CONFIG_SYS_FSL_QBMAN_SIZE_1, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_PCIE1_PHYS_ADDR, CONFIG_SYS_PCIE1_PHYS_ADDR, + CONFIG_SYS_PCIE1_PHYS_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_PCIE2_PHYS_ADDR, CONFIG_SYS_PCIE2_PHYS_ADDR, + CONFIG_SYS_PCIE2_PHYS_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_PCIE3_PHYS_ADDR, CONFIG_SYS_PCIE3_PHYS_ADDR, + CONFIG_SYS_PCIE3_PHYS_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, +#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LX2160A) + { CONFIG_SYS_PCIE4_PHYS_ADDR, CONFIG_SYS_PCIE4_PHYS_ADDR, + CONFIG_SYS_PCIE4_PHYS_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, +#endif + { CONFIG_SYS_FSL_WRIOP1_BASE, CONFIG_SYS_FSL_WRIOP1_BASE, + CONFIG_SYS_FSL_WRIOP1_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_AIOP1_BASE, CONFIG_SYS_FSL_AIOP1_BASE, + CONFIG_SYS_FSL_AIOP1_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_PEBUF_BASE, CONFIG_SYS_FSL_PEBUF_BASE, + CONFIG_SYS_FSL_PEBUF_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2, + CONFIG_SYS_FSL_DRAM_SIZE2, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS + }, +#ifdef CONFIG_SYS_FSL_DRAM_BASE3 + { CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3, + CONFIG_SYS_FSL_DRAM_SIZE3, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS + }, +#endif +#elif defined(CONFIG_FSL_LSCH2) + { CONFIG_SYS_FSL_BOOTROM_BASE, CONFIG_SYS_FSL_BOOTROM_BASE, + CONFIG_SYS_FSL_BOOTROM_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE, + CONFIG_SYS_FSL_CCSR_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_OCRAM_BASE, CONFIG_SYS_FSL_OCRAM_BASE, + SYS_FSL_OCRAM_SPACE_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE + }, + { CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE, + CONFIG_SYS_FSL_DCSR_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_QSPI_BASE, CONFIG_SYS_FSL_QSPI_BASE, + CONFIG_SYS_FSL_QSPI_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, +#ifdef CONFIG_FSL_IFC + { CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE, + CONFIG_SYS_FSL_IFC_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE + }, +#endif + { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1, + CONFIG_SYS_FSL_DRAM_SIZE1, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS + }, + { CONFIG_SYS_FSL_QBMAN_BASE, CONFIG_SYS_FSL_QBMAN_BASE, + CONFIG_SYS_FSL_QBMAN_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2, + CONFIG_SYS_FSL_DRAM_SIZE2, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS + }, + { CONFIG_SYS_PCIE1_PHYS_ADDR, CONFIG_SYS_PCIE1_PHYS_ADDR, + CONFIG_SYS_PCIE1_PHYS_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_PCIE2_PHYS_ADDR, CONFIG_SYS_PCIE2_PHYS_ADDR, + CONFIG_SYS_PCIE2_PHYS_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_PCIE3_PHYS_ADDR, CONFIG_SYS_PCIE3_PHYS_ADDR, + CONFIG_SYS_PCIE3_PHYS_SIZE, + PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, + { CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3, + CONFIG_SYS_FSL_DRAM_SIZE3, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS + }, +#endif +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE + {}, /* space holder for secure mem */ +#endif + {}, +}; + +struct mm_region *mem_map = early_map; + +void cpu_name(char *name) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + unsigned int i, svr, ver; + + svr = gur_in32(&gur->svr); + ver = SVR_SOC_VER(svr); + + for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++) + if ((cpu_type_list[i].soc_ver & SVR_WO_E) == ver) { + strcpy(name, cpu_type_list[i].name); +#ifdef CONFIG_ARCH_LX2160A + if (IS_C_PROCESSOR(svr)) + strcat(name, "C"); +#endif + + if (IS_E_PROCESSOR(svr)) + strcat(name, "E"); + + sprintf(name + strlen(name), " Rev%d.%d", + SVR_MAJ(svr), SVR_MIN(svr)); + break; + } + + if (i == ARRAY_SIZE(cpu_type_list)) + strcpy(name, "unknown"); +} + +#ifndef CONFIG_SYS_DCACHE_OFF +/* + * To start MMU before DDR is available, we create MMU table in SRAM. + * The base address of SRAM is CONFIG_SYS_FSL_OCRAM_BASE. We use three + * levels of translation tables here to cover 40-bit address space. + * We use 4KB granule size, with 40 bits physical address, T0SZ=24 + * Address above EARLY_PGTABLE_SIZE (0x5000) is free for other purpose. + * Note, the debug print in cache_v8.c is not usable for debugging + * these early MMU tables because UART is not yet available. + */ +static inline void early_mmu_setup(void) +{ + unsigned int el = current_el(); + + /* global data is already setup, no allocation yet */ + if (el == 3) + gd->arch.tlb_addr = CONFIG_SYS_FSL_OCRAM_BASE; + else + gd->arch.tlb_addr = CONFIG_SYS_DDR_SDRAM_BASE; + gd->arch.tlb_fillptr = gd->arch.tlb_addr; + gd->arch.tlb_size = EARLY_PGTABLE_SIZE; + + /* Create early page tables */ + setup_pgtables(); + + /* point TTBR to the new table */ + set_ttbr_tcr_mair(el, gd->arch.tlb_addr, + get_tcr(el, NULL, NULL) & + ~(TCR_ORGN_MASK | TCR_IRGN_MASK), + MEMORY_ATTRIBUTES); + + set_sctlr(get_sctlr() | CR_M); +} + +static void fix_pcie_mmu_map(void) +{ +#ifdef CONFIG_ARCH_LS2080A + unsigned int i; + u32 svr, ver; + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + + svr = gur_in32(&gur->svr); + ver = SVR_SOC_VER(svr); + + /* Fix PCIE base and size for LS2088A */ + if ((ver == SVR_LS2088A) || (ver == SVR_LS2084A) || + (ver == SVR_LS2048A) || (ver == SVR_LS2044A) || + (ver == SVR_LS2081A) || (ver == SVR_LS2041A)) { + for (i = 0; i < ARRAY_SIZE(final_map); i++) { + switch (final_map[i].phys) { + case CONFIG_SYS_PCIE1_PHYS_ADDR: + final_map[i].phys = 0x2000000000ULL; + final_map[i].virt = 0x2000000000ULL; + final_map[i].size = 0x800000000ULL; + break; + case CONFIG_SYS_PCIE2_PHYS_ADDR: + final_map[i].phys = 0x2800000000ULL; + final_map[i].virt = 0x2800000000ULL; + final_map[i].size = 0x800000000ULL; + break; + case CONFIG_SYS_PCIE3_PHYS_ADDR: + final_map[i].phys = 0x3000000000ULL; + final_map[i].virt = 0x3000000000ULL; + final_map[i].size = 0x800000000ULL; + break; + case CONFIG_SYS_PCIE4_PHYS_ADDR: + final_map[i].phys = 0x3800000000ULL; + final_map[i].virt = 0x3800000000ULL; + final_map[i].size = 0x800000000ULL; + break; + default: + break; + } + } + } +#endif +} + +/* + * The final tables look similar to early tables, but different in detail. + * These tables are in DRAM. Sub tables are added to enable cache for + * QBMan and OCRAM. + * + * Put the MMU table in secure memory if gd->arch.secure_ram is valid. + * OCRAM will be not used for this purpose so gd->arch.secure_ram can't be 0. + */ +static inline void final_mmu_setup(void) +{ + u64 tlb_addr_save = gd->arch.tlb_addr; + unsigned int el = current_el(); + int index; + + /* fix the final_map before filling in the block entries */ + fix_pcie_mmu_map(); + + mem_map = final_map; + + /* Update mapping for DDR to actual size */ + for (index = 0; index < ARRAY_SIZE(final_map) - 2; index++) { + /* + * Find the entry for DDR mapping and update the address and + * size. Zero-sized mapping will be skipped when creating MMU + * table. + */ + switch (final_map[index].virt) { + case CONFIG_SYS_FSL_DRAM_BASE1: + final_map[index].virt = gd->bd->bi_dram[0].start; + final_map[index].phys = gd->bd->bi_dram[0].start; + final_map[index].size = gd->bd->bi_dram[0].size; + break; +#ifdef CONFIG_SYS_FSL_DRAM_BASE2 + case CONFIG_SYS_FSL_DRAM_BASE2: +#if (CONFIG_NR_DRAM_BANKS >= 2) + final_map[index].virt = gd->bd->bi_dram[1].start; + final_map[index].phys = gd->bd->bi_dram[1].start; + final_map[index].size = gd->bd->bi_dram[1].size; +#else + final_map[index].size = 0; +#endif + break; +#endif +#ifdef CONFIG_SYS_FSL_DRAM_BASE3 + case CONFIG_SYS_FSL_DRAM_BASE3: +#if (CONFIG_NR_DRAM_BANKS >= 3) + final_map[index].virt = gd->bd->bi_dram[2].start; + final_map[index].phys = gd->bd->bi_dram[2].start; + final_map[index].size = gd->bd->bi_dram[2].size; +#else + final_map[index].size = 0; +#endif + break; +#endif + default: + break; + } + } + +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE + if (gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED) { + if (el == 3) { + /* + * Only use gd->arch.secure_ram if the address is + * recalculated. Align to 4KB for MMU table. + */ + /* put page tables in secure ram */ + index = ARRAY_SIZE(final_map) - 2; + gd->arch.tlb_addr = gd->arch.secure_ram & ~0xfff; + final_map[index].virt = gd->arch.secure_ram & ~0x3; + final_map[index].phys = final_map[index].virt; + final_map[index].size = CONFIG_SYS_MEM_RESERVE_SECURE; + final_map[index].attrs = PTE_BLOCK_OUTER_SHARE; + gd->arch.secure_ram |= MEM_RESERVE_SECURE_SECURED; + tlb_addr_save = gd->arch.tlb_addr; + } else { + /* Use allocated (board_f.c) memory for TLB */ + tlb_addr_save = gd->arch.tlb_allocated; + gd->arch.tlb_addr = tlb_addr_save; + } + } +#endif + + /* Reset the fill ptr */ + gd->arch.tlb_fillptr = tlb_addr_save; + + /* Create normal system page tables */ + setup_pgtables(); + + /* Create emergency page tables */ + gd->arch.tlb_addr = gd->arch.tlb_fillptr; + gd->arch.tlb_emerg = gd->arch.tlb_addr; + setup_pgtables(); + gd->arch.tlb_addr = tlb_addr_save; + + /* Disable cache and MMU */ + dcache_disable(); /* TLBs are invalidated */ + invalidate_icache_all(); + + /* point TTBR to the new table */ + set_ttbr_tcr_mair(el, gd->arch.tlb_addr, get_tcr(el, NULL, NULL), + MEMORY_ATTRIBUTES); + + set_sctlr(get_sctlr() | CR_M); +} + +u64 get_page_table_size(void) +{ + return 0x10000; +} + +int arch_cpu_init(void) +{ + /* + * This function is called before U-Boot relocates itself to speed up + * on system running. It is not necessary to run if performance is not + * critical. Skip if MMU is already enabled by SPL or other means. + */ + if (get_sctlr() & CR_M) + return 0; + + icache_enable(); + __asm_invalidate_dcache_all(); + __asm_invalidate_tlb_all(); + early_mmu_setup(); + set_sctlr(get_sctlr() | CR_C); + return 0; +} + +void mmu_setup(void) +{ + final_mmu_setup(); +} + +/* + * This function is called from common/board_r.c. + * It recreates MMU table in main memory. + */ +void enable_caches(void) +{ + mmu_setup(); + __asm_invalidate_tlb_all(); + icache_enable(); + dcache_enable(); +} +#endif /* CONFIG_SYS_DCACHE_OFF */ + +#ifdef CONFIG_TFABOOT +enum boot_src __get_boot_src(u32 porsr1) +{ + enum boot_src src = BOOT_SOURCE_RESERVED; + u32 rcw_src = (porsr1 & RCW_SRC_MASK) >> RCW_SRC_BIT; +#if !defined(CONFIG_NXP_LSCH3_2) + u32 val; +#endif + debug("%s: rcw_src 0x%x\n", __func__, rcw_src); + +#if defined(CONFIG_FSL_LSCH3) +#if defined(CONFIG_NXP_LSCH3_2) + switch (rcw_src) { + case RCW_SRC_SDHC1_VAL: + src = BOOT_SOURCE_SD_MMC; + break; + case RCW_SRC_SDHC2_VAL: + src = BOOT_SOURCE_SD_MMC2; + break; + case RCW_SRC_I2C1_VAL: + src = BOOT_SOURCE_I2C1_EXTENDED; + break; + case RCW_SRC_FLEXSPI_NAND2K_VAL: + src = BOOT_SOURCE_XSPI_NAND; + break; + case RCW_SRC_FLEXSPI_NAND4K_VAL: + src = BOOT_SOURCE_XSPI_NAND; + break; + case RCW_SRC_RESERVED_1_VAL: + src = BOOT_SOURCE_RESERVED; + break; + case RCW_SRC_FLEXSPI_NOR_24B: + src = BOOT_SOURCE_XSPI_NOR; + break; + default: + src = BOOT_SOURCE_RESERVED; + } +#else + val = rcw_src & RCW_SRC_TYPE_MASK; + if (val == RCW_SRC_NOR_VAL) { + val = rcw_src & NOR_TYPE_MASK; + + switch (val) { + case NOR_16B_VAL: + case NOR_32B_VAL: + src = BOOT_SOURCE_IFC_NOR; + break; + default: + src = BOOT_SOURCE_RESERVED; + } + } else { + /* RCW SRC Serial Flash */ + val = rcw_src & RCW_SRC_SERIAL_MASK; + switch (val) { + case RCW_SRC_QSPI_VAL: + /* RCW SRC Serial NOR (QSPI) */ + src = BOOT_SOURCE_QSPI_NOR; + break; + case RCW_SRC_SD_CARD_VAL: + /* RCW SRC SD Card */ + src = BOOT_SOURCE_SD_MMC; + break; + case RCW_SRC_EMMC_VAL: + /* RCW SRC EMMC */ + src = BOOT_SOURCE_SD_MMC2; + break; + case RCW_SRC_I2C1_VAL: + /* RCW SRC I2C1 Extended */ + src = BOOT_SOURCE_I2C1_EXTENDED; + break; + default: + src = BOOT_SOURCE_RESERVED; + } + } +#endif +#elif defined(CONFIG_FSL_LSCH2) + /* RCW SRC NAND */ + val = rcw_src & RCW_SRC_NAND_MASK; + if (val == RCW_SRC_NAND_VAL) { + val = rcw_src & NAND_RESERVED_MASK; + if (val != NAND_RESERVED_1 && val != NAND_RESERVED_2) + src = BOOT_SOURCE_IFC_NAND; + + } else { + /* RCW SRC NOR */ + val = rcw_src & RCW_SRC_NOR_MASK; + if (val == NOR_8B_VAL || val == NOR_16B_VAL) { + src = BOOT_SOURCE_IFC_NOR; + } else { + switch (rcw_src) { + case QSPI_VAL1: + case QSPI_VAL2: + src = BOOT_SOURCE_QSPI_NOR; + break; + case SD_VAL: + src = BOOT_SOURCE_SD_MMC; + break; + default: + src = BOOT_SOURCE_RESERVED; + } + } + } +#endif + + if (CONFIG_IS_ENABLED(SYS_FSL_ERRATUM_A010539) && !rcw_src) + src = BOOT_SOURCE_QSPI_NOR; + + debug("%s: src 0x%x\n", __func__, src); + return src; +} + +enum boot_src get_boot_src(void) +{ + struct pt_regs regs; + u32 porsr1 = 0; + +#if defined(CONFIG_FSL_LSCH3) + u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE; +#elif defined(CONFIG_FSL_LSCH2) + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); +#endif + + if (current_el() == 2) { + regs.regs[0] = SIP_SVC_RCW; + + smc_call(®s); + if (!regs.regs[0]) + porsr1 = regs.regs[1]; + } + + if (current_el() == 3 || !porsr1) { +#ifdef CONFIG_FSL_LSCH3 + porsr1 = in_le32(dcfg_ccsr + DCFG_PORSR1 / 4); +#elif defined(CONFIG_FSL_LSCH2) + porsr1 = in_be32(&gur->porsr1); +#endif + } + + debug("%s: porsr1 0x%x\n", __func__, porsr1); + + return __get_boot_src(porsr1); +} + +#ifdef CONFIG_ENV_IS_IN_MMC +int mmc_get_env_dev(void) +{ + enum boot_src src = get_boot_src(); + int dev = CONFIG_SYS_MMC_ENV_DEV; + + switch (src) { + case BOOT_SOURCE_SD_MMC: + dev = 0; + break; + case BOOT_SOURCE_SD_MMC2: + dev = 1; + break; + default: + break; + } + + return dev; +} +#endif + +enum env_location env_get_location(enum env_operation op, int prio) +{ + enum boot_src src = get_boot_src(); + enum env_location env_loc = ENVL_NOWHERE; + + if (prio) + return ENVL_UNKNOWN; + +#ifdef CONFIG_CHAIN_OF_TRUST + /* Check Boot Mode + * If Boot Mode is Secure, return ENVL_NOWHERE + */ + if (fsl_check_boot_mode_secure() == 1) + goto done; +#endif + + switch (src) { + case BOOT_SOURCE_IFC_NOR: + env_loc = ENVL_FLASH; + break; + case BOOT_SOURCE_QSPI_NOR: + /* FALLTHROUGH */ + case BOOT_SOURCE_XSPI_NOR: + env_loc = ENVL_SPI_FLASH; + break; + case BOOT_SOURCE_IFC_NAND: + /* FALLTHROUGH */ + case BOOT_SOURCE_QSPI_NAND: + /* FALLTHROUGH */ + case BOOT_SOURCE_XSPI_NAND: + env_loc = ENVL_NAND; + break; + case BOOT_SOURCE_SD_MMC: + /* FALLTHROUGH */ + case BOOT_SOURCE_SD_MMC2: + env_loc = ENVL_MMC; + break; + case BOOT_SOURCE_I2C1_EXTENDED: + /* FALLTHROUGH */ + default: + break; + } + +#ifdef CONFIG_CHAIN_OF_TRUST +done: +#endif + return env_loc; +} +#endif /* CONFIG_TFABOOT */ + +u32 initiator_type(u32 cluster, int init_id) +{ + struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 idx = (cluster >> (init_id * 8)) & TP_CLUSTER_INIT_MASK; + u32 type = 0; + + type = gur_in32(&gur->tp_ityp[idx]); + if (type & TP_ITYP_AV) + return type; + + return 0; +} + +u32 cpu_pos_mask(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + int i = 0; + u32 cluster, type, mask = 0; + + do { + int j; + + cluster = gur_in32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + type = initiator_type(cluster, j); + if (type && (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM)) + mask |= 1 << (i * TP_INIT_PER_CLUSTER + j); + } + i++; + } while ((cluster & TP_CLUSTER_EOC) == 0x0); + + return mask; +} + +u32 cpu_mask(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + int i = 0, count = 0; + u32 cluster, type, mask = 0; + + do { + int j; + + cluster = gur_in32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + type = initiator_type(cluster, j); + if (type) { + if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM) + mask |= 1 << count; + count++; + } + } + i++; + } while ((cluster & TP_CLUSTER_EOC) == 0x0); + + return mask; +} + +/* + * Return the number of cores on this SOC. + */ +int cpu_numcores(void) +{ + return hweight32(cpu_mask()); +} + +int fsl_qoriq_core_to_cluster(unsigned int core) +{ + struct ccsr_gur __iomem *gur = + (void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR); + int i = 0, count = 0; + u32 cluster; + + do { + int j; + + cluster = gur_in32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + if (initiator_type(cluster, j)) { + if (count == core) + return i; + count++; + } + } + i++; + } while ((cluster & TP_CLUSTER_EOC) == 0x0); + + return -1; /* cannot identify the cluster */ +} + +u32 fsl_qoriq_core_to_type(unsigned int core) +{ + struct ccsr_gur __iomem *gur = + (void __iomem *)(CONFIG_SYS_FSL_GUTS_ADDR); + int i = 0, count = 0; + u32 cluster, type; + + do { + int j; + + cluster = gur_in32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + type = initiator_type(cluster, j); + if (type) { + if (count == core) + return type; + count++; + } + } + i++; + } while ((cluster & TP_CLUSTER_EOC) == 0x0); + + return -1; /* cannot identify the cluster */ +} + +#ifndef CONFIG_FSL_LSCH3 +uint get_svr(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + + return gur_in32(&gur->svr); +} +#endif + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + struct sys_info sysinfo; + char buf[32]; + unsigned int i, core; + u32 type, rcw, svr = gur_in32(&gur->svr); + + puts("SoC: "); + + cpu_name(buf); + printf(" %s (0x%x)\n", buf, svr); + memset((u8 *)buf, 0x00, ARRAY_SIZE(buf)); + get_sys_info(&sysinfo); + puts("Clock Configuration:"); + for_each_cpu(i, core, cpu_numcores(), cpu_mask()) { + if (!(i % 3)) + puts("\n "); + type = TP_ITYP_VER(fsl_qoriq_core_to_type(core)); + printf("CPU%d(%s):%-4s MHz ", core, + type == TY_ITYP_VER_A7 ? "A7 " : + (type == TY_ITYP_VER_A53 ? "A53" : + (type == TY_ITYP_VER_A57 ? "A57" : + (type == TY_ITYP_VER_A72 ? "A72" : " "))), + strmhz(buf, sysinfo.freq_processor[core])); + } + /* Display platform clock as Bus frequency. */ + printf("\n Bus: %-4s MHz ", + strmhz(buf, sysinfo.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV)); + printf("DDR: %-4s MT/s", strmhz(buf, sysinfo.freq_ddrbus)); +#ifdef CONFIG_SYS_DPAA_FMAN + printf(" FMAN: %-4s MHz", strmhz(buf, sysinfo.freq_fman[0])); +#endif +#ifdef CONFIG_SYS_FSL_HAS_DP_DDR + if (soc_has_dp_ddr()) { + printf(" DP-DDR: %-4s MT/s", + strmhz(buf, sysinfo.freq_ddrbus2)); + } +#endif + puts("\n"); + + /* + * Display the RCW, so that no one gets confused as to what RCW + * we're actually using for this boot. + */ + puts("Reset Configuration Word (RCW):"); + for (i = 0; i < ARRAY_SIZE(gur->rcwsr); i++) { + rcw = gur_in32(&gur->rcwsr[i]); + if ((i % 4) == 0) + printf("\n %08x:", i * 4); + printf(" %08x", rcw); + } + puts("\n"); + + return 0; +} +#endif + +#ifdef CONFIG_FSL_ESDHC +int cpu_mmc_init(bd_t *bis) +{ + return fsl_esdhc_mmc_init(bis); +} +#endif + +int cpu_eth_init(bd_t *bis) +{ + int error = 0; + +#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) + error = fsl_mc_ldpaa_init(bis); +#endif +#ifdef CONFIG_FMAN_ENET + fm_standard_init(bis); +#endif + return error; +} + +static inline int check_psci(void) +{ + unsigned int psci_ver; + + psci_ver = sec_firmware_support_psci_version(); + if (psci_ver == PSCI_INVALID_VER) + return 1; + + return 0; +} + +static void config_core_prefetch(void) +{ + char *buf = NULL; + char buffer[HWCONFIG_BUFFER_SIZE]; + const char *prefetch_arg = NULL; + size_t arglen; + unsigned int mask; + struct pt_regs regs; + + if (env_get_f("hwconfig", buffer, sizeof(buffer)) > 0) + buf = buffer; + + prefetch_arg = hwconfig_subarg_f("core_prefetch", "disable", + &arglen, buf); + + if (prefetch_arg) { + mask = simple_strtoul(prefetch_arg, NULL, 0) & 0xff; + if (mask & 0x1) { + printf("Core0 prefetch can't be disabled\n"); + return; + } + +#define SIP_PREFETCH_DISABLE_64 0xC200FF13 + regs.regs[0] = SIP_PREFETCH_DISABLE_64; + regs.regs[1] = mask; + smc_call(®s); + + if (regs.regs[0]) + printf("Prefetch disable config failed for mask "); + else + printf("Prefetch disable config passed for mask "); + printf("0x%x\n", mask); + } +} + +int arch_early_init_r(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009635 + u32 svr_dev_id; + /* + * erratum A009635 is valid only for LS2080A SoC and + * its personalitiesi + */ + svr_dev_id = get_svr(); + if (IS_SVR_DEV(svr_dev_id, SVR_DEV(SVR_LS2080A))) + erratum_a009635(); +#endif +#if defined(CONFIG_SYS_FSL_ERRATUM_A009942) && defined(CONFIG_SYS_FSL_DDR) + erratum_a009942_check_cpo(); +#endif + if (check_psci()) { + debug("PSCI: PSCI does not exist.\n"); + + /* if PSCI does not exist, boot secondary cores here */ + if (fsl_layerscape_wake_seconday_cores()) + printf("Did not wake secondary cores\n"); + } + +#ifdef CONFIG_SYS_FSL_HAS_RGMII + fsl_rgmii_init(); +#endif + + config_core_prefetch(); + +#ifdef CONFIG_SYS_HAS_SERDES + fsl_serdes_init(); +#endif +#ifdef CONFIG_FMAN_ENET + fman_enet_init(); +#endif +#ifdef CONFIG_SYS_DPAA_QBMAN + setup_qbman_portals(); +#endif + return 0; +} + +int timer_init(void) +{ + u32 __iomem *cntcr = (u32 *)CONFIG_SYS_FSL_TIMER_ADDR; +#ifdef CONFIG_FSL_LSCH3 + u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR; +#endif +#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A) + u32 __iomem *pctbenr = (u32 *)FSL_PMU_PCTBENR_OFFSET; + u32 svr_dev_id; +#endif +#ifdef COUNTER_FREQUENCY_REAL + unsigned long cntfrq = COUNTER_FREQUENCY_REAL; + + /* Update with accurate clock frequency */ + if (current_el() == 3) + asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory"); +#endif + +#ifdef CONFIG_FSL_LSCH3 + /* Enable timebase for all clusters. + * It is safe to do so even some clusters are not enabled. + */ + out_le32(cltbenr, 0xf); +#endif + +#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A) + /* + * In certain Layerscape SoCs, the clock for each core's + * has an enable bit in the PMU Physical Core Time Base Enable + * Register (PCTBENR), which allows the watchdog to operate. + */ + setbits_le32(pctbenr, 0xff); + /* + * For LS2080A SoC and its personalities, timer controller + * offset is different + */ + svr_dev_id = get_svr(); + if (IS_SVR_DEV(svr_dev_id, SVR_DEV(SVR_LS2080A))) + cntcr = (u32 *)SYS_FSL_LS2080A_LS2085A_TIMER_ADDR; + +#endif + + /* Enable clock for timer + * This is a global setting. + */ + out_le32(cntcr, 0x1); + + return 0; +} + +__efi_runtime_data u32 __iomem *rstcr = (u32 *)CONFIG_SYS_FSL_RST_ADDR; + +void __efi_runtime reset_cpu(ulong addr) +{ + u32 val; + +#ifdef CONFIG_ARCH_LX2160A + val = in_le32(rstcr); + val |= 0x01; + out_le32(rstcr, val); +#else + /* Raise RESET_REQ_B */ + val = scfg_in32(rstcr); + val |= 0x02; + scfg_out32(rstcr, val); +#endif +} + +#ifdef CONFIG_EFI_LOADER + +void __efi_runtime EFIAPI efi_reset_system( + enum efi_reset_type reset_type, + efi_status_t reset_status, + unsigned long data_size, void *reset_data) +{ + switch (reset_type) { + case EFI_RESET_COLD: + case EFI_RESET_WARM: + case EFI_RESET_PLATFORM_SPECIFIC: + reset_cpu(0); + break; + case EFI_RESET_SHUTDOWN: + /* Nothing we can do */ + break; + } + + while (1) { } +} + +efi_status_t efi_reset_system_init(void) +{ + return efi_add_runtime_mmio(&rstcr, sizeof(*rstcr)); +} + +#endif + +/* + * Calculate reserved memory with given memory bank + * Return aligned memory size on success + * Return (ram_size + needed size) for failure + */ +phys_size_t board_reserve_ram_top(phys_size_t ram_size) +{ + phys_size_t ram_top = ram_size; + +#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) + ram_top = mc_get_dram_block_size(); + if (ram_top > ram_size) + return ram_size + ram_top; + + ram_top = ram_size - ram_top; + /* The start address of MC reserved memory needs to be aligned. */ + ram_top &= ~(CONFIG_SYS_MC_RSV_MEM_ALIGN - 1); +#endif + + return ram_size - ram_top; +} + +phys_size_t get_effective_memsize(void) +{ + phys_size_t ea_size, rem = 0; + + /* + * For ARMv8 SoCs, DDR memory is split into two or three regions. The + * first region is 2GB space at 0x8000_0000. Secure memory needs to + * allocated from first region. If the memory extends to the second + * region (or the third region if applicable), Management Complex (MC) + * memory should be put into the highest region, i.e. the end of DDR + * memory. CONFIG_MAX_MEM_MAPPED is set to the size of first region so + * U-Boot doesn't relocate itself into higher address. Should DDR be + * configured to skip the first region, this function needs to be + * adjusted. + */ + if (gd->ram_size > CONFIG_MAX_MEM_MAPPED) { + ea_size = CONFIG_MAX_MEM_MAPPED; + rem = gd->ram_size - ea_size; + } else { + ea_size = gd->ram_size; + } + +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE + /* Check if we have enough space for secure memory */ + if (ea_size > CONFIG_SYS_MEM_RESERVE_SECURE) + ea_size -= CONFIG_SYS_MEM_RESERVE_SECURE; + else + printf("Error: No enough space for secure memory.\n"); +#endif + /* Check if we have enough memory for MC */ + if (rem < board_reserve_ram_top(rem)) { + /* Not enough memory in high region to reserve */ + if (ea_size > board_reserve_ram_top(ea_size)) + ea_size -= board_reserve_ram_top(ea_size); + else + printf("Error: No enough space for reserved memory.\n"); + } + + return ea_size; +} + +#ifdef CONFIG_TFABOOT +phys_size_t tfa_get_dram_size(void) +{ + struct pt_regs regs; + phys_size_t dram_size = 0; + + regs.regs[0] = SMC_DRAM_BANK_INFO; + regs.regs[1] = -1; + + smc_call(®s); + if (regs.regs[0]) + return 0; + + dram_size = regs.regs[1]; + return dram_size; +} + +static int tfa_dram_init_banksize(void) +{ + int i = 0, ret = 0; + struct pt_regs regs; + phys_size_t dram_size = tfa_get_dram_size(); + + debug("dram_size %llx\n", dram_size); + + if (!dram_size) + return -EINVAL; + + do { + regs.regs[0] = SMC_DRAM_BANK_INFO; + regs.regs[1] = i; + + smc_call(®s); + if (regs.regs[0]) { + ret = -EINVAL; + break; + } + + debug("bank[%d]: start %lx, size %lx\n", i, regs.regs[1], + regs.regs[2]); + gd->bd->bi_dram[i].start = regs.regs[1]; + gd->bd->bi_dram[i].size = regs.regs[2]; + + dram_size -= gd->bd->bi_dram[i].size; + + i++; + } while (dram_size); + + if (i > 0) + ret = 0; + +#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) + /* Assign memory for MC */ +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE + if (gd->bd->bi_dram[2].size >= + board_reserve_ram_top(gd->bd->bi_dram[2].size)) { + gd->arch.resv_ram = gd->bd->bi_dram[2].start + + gd->bd->bi_dram[2].size - + board_reserve_ram_top(gd->bd->bi_dram[2].size); + } else +#endif + { + if (gd->bd->bi_dram[1].size >= + board_reserve_ram_top(gd->bd->bi_dram[1].size)) { + gd->arch.resv_ram = gd->bd->bi_dram[1].start + + gd->bd->bi_dram[1].size - + board_reserve_ram_top(gd->bd->bi_dram[1].size); + } else if (gd->bd->bi_dram[0].size > + board_reserve_ram_top(gd->bd->bi_dram[0].size)) { + gd->arch.resv_ram = gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size - + board_reserve_ram_top(gd->bd->bi_dram[0].size); + } + } +#endif /* CONFIG_FSL_MC_ENET */ + + return ret; +} +#endif + +int dram_init_banksize(void) +{ +#ifdef CONFIG_SYS_DP_DDR_BASE_PHY + phys_size_t dp_ddr_size; +#endif + +#ifdef CONFIG_TFABOOT + if (!tfa_dram_init_banksize()) + return 0; +#endif + /* + * gd->ram_size has the total size of DDR memory, less reserved secure + * memory. The DDR extends from low region to high region(s) presuming + * no hole is created with DDR configuration. gd->arch.secure_ram tracks + * the location of secure memory. gd->arch.resv_ram tracks the location + * of reserved memory for Management Complex (MC). Because gd->ram_size + * is reduced by this function if secure memory is reserved, checking + * gd->arch.secure_ram should be done to avoid running it repeatedly. + */ + +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE + if (gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED) { + debug("No need to run again, skip %s\n", __func__); + + return 0; + } +#endif + + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + if (gd->ram_size > CONFIG_SYS_DDR_BLOCK1_SIZE) { + gd->bd->bi_dram[0].size = CONFIG_SYS_DDR_BLOCK1_SIZE; + gd->bd->bi_dram[1].start = CONFIG_SYS_DDR_BLOCK2_BASE; + gd->bd->bi_dram[1].size = gd->ram_size - + CONFIG_SYS_DDR_BLOCK1_SIZE; +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE + if (gd->bi_dram[1].size > CONFIG_SYS_DDR_BLOCK2_SIZE) { + gd->bd->bi_dram[2].start = CONFIG_SYS_DDR_BLOCK3_BASE; + gd->bd->bi_dram[2].size = gd->bd->bi_dram[1].size - + CONFIG_SYS_DDR_BLOCK2_SIZE; + gd->bd->bi_dram[1].size = CONFIG_SYS_DDR_BLOCK2_SIZE; + } +#endif + } else { + gd->bd->bi_dram[0].size = gd->ram_size; + } +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE + if (gd->bd->bi_dram[0].size > + CONFIG_SYS_MEM_RESERVE_SECURE) { + gd->bd->bi_dram[0].size -= + CONFIG_SYS_MEM_RESERVE_SECURE; + gd->arch.secure_ram = gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size; + gd->arch.secure_ram |= MEM_RESERVE_SECURE_MAINTAINED; + gd->ram_size -= CONFIG_SYS_MEM_RESERVE_SECURE; + } +#endif /* CONFIG_SYS_MEM_RESERVE_SECURE */ + +#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) + /* Assign memory for MC */ +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE + if (gd->bd->bi_dram[2].size >= + board_reserve_ram_top(gd->bd->bi_dram[2].size)) { + gd->arch.resv_ram = gd->bd->bi_dram[2].start + + gd->bd->bi_dram[2].size - + board_reserve_ram_top(gd->bd->bi_dram[2].size); + } else +#endif + { + if (gd->bd->bi_dram[1].size >= + board_reserve_ram_top(gd->bd->bi_dram[1].size)) { + gd->arch.resv_ram = gd->bd->bi_dram[1].start + + gd->bd->bi_dram[1].size - + board_reserve_ram_top(gd->bd->bi_dram[1].size); + } else if (gd->bd->bi_dram[0].size > + board_reserve_ram_top(gd->bd->bi_dram[0].size)) { + gd->arch.resv_ram = gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size - + board_reserve_ram_top(gd->bd->bi_dram[0].size); + } + } +#endif /* CONFIG_FSL_MC_ENET */ + +#ifdef CONFIG_SYS_DP_DDR_BASE_PHY +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE +#error "This SoC shouldn't have DP DDR" +#endif + if (soc_has_dp_ddr()) { + /* initialize DP-DDR here */ + puts("DP-DDR: "); + /* + * DDR controller use 0 as the base address for binding. + * It is mapped to CONFIG_SYS_DP_DDR_BASE for core to access. + */ + dp_ddr_size = fsl_other_ddr_sdram(CONFIG_SYS_DP_DDR_BASE_PHY, + CONFIG_DP_DDR_CTRL, + CONFIG_DP_DDR_NUM_CTRLS, + CONFIG_DP_DDR_DIMM_SLOTS_PER_CTLR, + NULL, NULL, NULL); + if (dp_ddr_size) { + gd->bd->bi_dram[2].start = CONFIG_SYS_DP_DDR_BASE; + gd->bd->bi_dram[2].size = dp_ddr_size; + } else { + puts("Not detected"); + } + } +#endif + +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE + debug("%s is called. gd->ram_size is reduced to %lu\n", + __func__, (ulong)gd->ram_size); +#endif + + return 0; +} + +#if CONFIG_IS_ENABLED(EFI_LOADER) +void efi_add_known_memory(void) +{ + int i; + phys_addr_t ram_start, start; + phys_size_t ram_size; + u64 pages; + + /* Add RAM */ + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { +#ifdef CONFIG_SYS_DP_DDR_BASE_PHY +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE +#error "This SoC shouldn't have DP DDR" +#endif + if (i == 2) + continue; /* skip DP-DDR */ +#endif + ram_start = gd->bd->bi_dram[i].start; + ram_size = gd->bd->bi_dram[i].size; +#ifdef CONFIG_RESV_RAM + if (gd->arch.resv_ram >= ram_start && + gd->arch.resv_ram < ram_start + ram_size) + ram_size = gd->arch.resv_ram - ram_start; +#endif + start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK; + pages = (ram_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; + + efi_add_memory_map(start, pages, EFI_CONVENTIONAL_MEMORY, + false); + } +} +#endif + +/* + * Before DDR size is known, early MMU table have DDR mapped as device memory + * to avoid speculative access. To relocate U-Boot to DDR, "normal memory" + * needs to be set for these mappings. + * If a special case configures DDR with holes in the mapping, the holes need + * to be marked as invalid. This is not implemented in this function. + */ +void update_early_mmu_table(void) +{ + if (!gd->arch.tlb_addr) + return; + + if (gd->ram_size <= CONFIG_SYS_FSL_DRAM_SIZE1) { + mmu_change_region_attr( + CONFIG_SYS_SDRAM_BASE, + gd->ram_size, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | + PTE_BLOCK_NS | + PTE_TYPE_VALID); + } else { + mmu_change_region_attr( + CONFIG_SYS_SDRAM_BASE, + CONFIG_SYS_DDR_BLOCK1_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | + PTE_BLOCK_NS | + PTE_TYPE_VALID); +#ifdef CONFIG_SYS_DDR_BLOCK3_BASE +#ifndef CONFIG_SYS_DDR_BLOCK2_SIZE +#error "Missing CONFIG_SYS_DDR_BLOCK2_SIZE" +#endif + if (gd->ram_size - CONFIG_SYS_DDR_BLOCK1_SIZE > + CONFIG_SYS_DDR_BLOCK2_SIZE) { + mmu_change_region_attr( + CONFIG_SYS_DDR_BLOCK2_BASE, + CONFIG_SYS_DDR_BLOCK2_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | + PTE_BLOCK_NS | + PTE_TYPE_VALID); + mmu_change_region_attr( + CONFIG_SYS_DDR_BLOCK3_BASE, + gd->ram_size - + CONFIG_SYS_DDR_BLOCK1_SIZE - + CONFIG_SYS_DDR_BLOCK2_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | + PTE_BLOCK_NS | + PTE_TYPE_VALID); + } else +#endif + { + mmu_change_region_attr( + CONFIG_SYS_DDR_BLOCK2_BASE, + gd->ram_size - + CONFIG_SYS_DDR_BLOCK1_SIZE, + PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE | + PTE_BLOCK_NS | + PTE_TYPE_VALID); + } + } +} + +__weak int dram_init(void) +{ + fsl_initdram(); +#if (!defined(CONFIG_SPL) && !defined(CONFIG_TFABOOT)) || \ + defined(CONFIG_SPL_BUILD) + /* This will break-before-make MMU for DDR */ + update_early_mmu_table(); +#endif + + return 0; +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.h b/arch/arm/cpu/armv8/fsl-layerscape/cpu.h new file mode 100644 index 0000000..dca5fd0 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.h
@@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2014-2015, Freescale Semiconductor + */ + +int fsl_qoriq_core_to_cluster(unsigned int core); +u32 initiator_type(u32 cluster, int init_id); +u32 cpu_mask(void);
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.core_prefetch b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.core_prefetch new file mode 100644 index 0000000..85cf6ab --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.core_prefetch
@@ -0,0 +1,20 @@ +Core instruction prefetch disable +--------------------------------- +To disable instruction prefetch of core; hwconfig needs to be updated. +for e.g. +setenv hwconfig 'fsl_ddr:bank_intlv=auto;core_prefetch:disable=0x02' + +Here 0x02 can be replaced with any valid value except Mask[0] bit. It +represents 64 bit mask. The 64-bit Mask has one bit for each core. +Mask[0] = core0 +Mask[1] = core1 +Mask[2] = core2 +etc +If the bit is set ('b1) in the mask, then prefetch is disabled for +that core when it is released from reset. + +core0 prefetch should not be disabled i.e. Mask[0] should never be set. +Setting Mask[0] may lead to undefined behavior. + +Once disabled, prefetch remains disabled until the next reset. +There is no function to re-enable prefetch.
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.falcon b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.falcon new file mode 100644 index 0000000..b3c6693 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.falcon
@@ -0,0 +1,150 @@ +Falcon boot option +------------------ +Falcon boot is a short cut boot method for SD/eMMC targets. It skips loading the +RAM version U-Boot. Instead, it loads FIT image and boot directly to Linux. +CONFIG_SPL_OS_BOOT enables falcon boot. CONFIG_SPL_LOAD_FIT enables the FIT +image support (also need CONFIG_SPL_OF_LIBFDT, CONFIG_SPL_FIT and optionally +CONFIG_SPL_GZIP). + +To enable falcon boot, a hook function spl_start_uboot() returns 0 to indicate +booting U-Boot is not the first choice. The kernel FIT image needs to be put +at CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR. SPL mmc driver reads the header to +determine if this is a FIT image. If true, FIT image components are parsed and +copied or decompressed (if applicable) to their destinations. If FIT image is +not found, normal U-Boot flow will follow. + +An important part of falcon boot is to prepare the device tree. A normal U-Boot +does FDT fixups when booting Linux. For falcon boot, Linux boots directly from +SPL, skipping the normal U-Boot. The device tree has to be prepared in advance. +A command "spl export" should be called under the normal RAM version U-Boot. +It is equivalent to go through "bootm" step-by-step until device tree fixup is +done. The device tree in memory is the one needed for falcon boot. Falcon boot +flow suggests to save this image to SD/eMMC at the location pointed by macro +CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, with maximum size specified by macro +CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS. However, when FIT image is used for +Linux, the device tree stored in FIT image overwrites the memory loaded by spl +driver from these sectors. We could change this loading order to favor the +stored sectors. But when secure boot is enabled, these sectors are used for +signature header and needs to be loaded before the FIT image. So it is important +to understand the device tree in FIT image should be the one actually used, or +leave it absent to favor the stored sectors. It is easier to deploy the FIT +image with embedded static device tree to multiple boards. + +Macro CONFIG_SYS_SPL_ARGS_ADDR serves two purposes. One is the pointer to load +the stored sectors to. Normally this is the static device tree. The second +purpose is the memory location of signature header for secure boot. After the +FIT image is loaded into memory, it is validated against the signature header +before individual components are extracted (and optionally decompressed) into +their final memory locations, respectively. After the validation, the header +is no longer used. The static device tree is copied into this location. So +this macro is passed as the location of device tree when booting Linux. + +Steps to prepare static device tree +----------------------------------- +To prepare the static device tree for Layerscape boards, it is important to +understand the fixups in U-Boot. Memory size and location, as well as reserved +memory blocks are added/updated. Ethernet MAC addressed are updated. FMan +microcode (if used) is embedded in the device tree. Kernel command line and +initrd information are embedded. Others including CPU status, boot method, +Ethernet port status, etc. are also updated. + +Following normal booting process, all variables are set, all images are loaded +before "bootm" command would be issued to boot, run command + +spl export fdt <address> + +where the address is the location of FIT image. U-Boot goes through the booting +process as if "bootm start", "bootm loados", "bootm ramdisk"... commands but +stops before "bootm go". There we have the fixed-up device tree in memory. +We can check the device tree header by these commands + +fdt addr <fdt address> +fdt header + +Where the fdt address is the device tree in memory. It is printed by U-Boot. +It is useful to know the exact size. One way to extract this static device +tree is to save it to eMMC/SD using command in U-Boot, and extract under Linux +with these commands, repectively + +mmc write <address> <sector> <sectors> +dd if=/dev/mmcblk0 of=<filename> bs=512 skip=<sector> count=<sectors> + +Note, U-Boot takes values as hexadecimals while Linux takes them as decimals by +default. If using NAND or other storage, the commands are slightly different. +When we have the static device tree image, we can re-make the FIT image with +it. It is important to specify the load addresses in FIT image for every +components. Otherwise U-Boot cannot load them correctly. + +Generate FIT image with static device tree +------------------------------------------ +Example: + +/dts-v1/; + +/ { + description = "Image file for the LS1043A Linux Kernel"; + #address-cells = <1>; + + images { + kernel { + description = "ARM64 Linux kernel"; + data = /incbin/("./arch/arm64/boot/Image.gz"); + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "gzip"; + load = <0x80080000>; + entry = <0x80080000>; + }; + fdt-1 { + description = "Flattened Device Tree blob"; + data = /incbin/("./fsl-ls1043ardb-static.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + load = <0x90000000>; + }; + ramdisk { + description = "LS1043 Ramdisk"; + data = /incbin/("./rootfs.cpio.gz"); + type = "ramdisk"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0xa0000000>; + }; + }; + + configurations { + default = "config-1"; + config-1 { + description = "Boot Linux kernel"; + kernel = "kernel"; + fdt = "fdt-1"; + ramdisk = "ramdisk"; + loadables = "fdt", "ramdisk"; + }; + }; +}; + +The "loadables" is not optional. It tells SPL which images to load into memory. + +Falcon mode with QSPI boot +-------------------------- +To use falcon mode with QSPI boot, SPL needs to be enabled. Similar to SD or +NAND boot, a RAM version full feature U-Boot is needed. Unlike SD or NAND boot, +SPL with QSPI doesn't need to combine SPL image with RAM version image. Two +separated images are used, u-boot-spl.pbl and u-boot.img. The former is SPL +image with RCW and PBI commands to load the SPL payload into On-Chip RAM. The +latter is RAM version U-Boot in FIT format (or legacy format if FIT is not +used). + +Other things to consider +----------------------- +Falcon boot skips a lot of initialization in U-Boot. If Linux expects the +hardware to be initialized by U-Boot, the related code should be ported to SPL +build. For example, if Linux expect Ethernet PHY to be initialized in U-Boot +(which is not a common case), the PHY initialization has to be included in +falcon boot. This increases the SPL image size and should be handled carefully. +If Linux has PHY driver enabled, it still depends on the correct MDIO bus setup +in U-Boot. Normal U-Boot sets the MDC ratio to generate a proper clock signal.
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch2 b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch2 new file mode 100644 index 0000000..9583bf7 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch2
@@ -0,0 +1,21 @@ +# +# Copyright 2015 Freescale Semiconductor +# +# SPDX-License-Identifier: GPL-2.0+ +# + +Freescale LayerScape with Chassis Generation 2 + +This architecture supports Freescale ARMv8 SoCs with Chassis generation 2, +for example LS1043A. + +Watchdog support Overview +------------------- +Support watchdog driver for LSCH2. The driver is disabled in default. +You can enable it by setting CONFIG_IMX_WATCHDOG. +Use following config to set watchdog timeout, if this config is not defined, +the default timeout value is 128s which is the maximum. Set 10 seconds for +example: + #define CONFIG_WATCHDOG_TIMEOUT_MSECS 10000 +Set CONFIG_WATCHDOG_RESET_DISABLE to disable reset watchdog, so that the +watchdog will not be fed in u-boot.
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3 new file mode 100644 index 0000000..6c98d99 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3
@@ -0,0 +1,400 @@ +# +# Copyright 2014-2015 Freescale Semiconductor +# +# SPDX-License-Identifier: GPL-2.0+ +# + +Freescale LayerScape with Chassis Generation 3 + +This architecture supports Freescale ARMv8 SoCs with Chassis generation 3, +for example LS2080A. + +DDR Layout +============ +Entire DDR region splits into two regions. + - Region 1 is at address 0x8000_0000 to 0xffff_ffff. + - Region 2 is at 0x80_8000_0000 to the top of total memory, + for example 16GB, 0x83_ffff_ffff. + +All DDR memory is marked as cache-enabled. + +When MC and Debug server is enabled, they carve 512MB away from the high +end of DDR. For example, if the total DDR is 16GB, it shrinks to 15.5GB +with MC and Debug server enabled. Linux only sees 15.5GB. + +The reserved 512MB layout looks like + + +---------------+ <-- top/end of memory + | 256MB | debug server + +---------------+ + | 256MB | MC + +---------------+ + | ... | + +MC requires the memory to be aligned with 512MB, so even debug server is +not enabled, 512MB is reserved, not 256MB. + +Flash Layout +============ + +(1) A typical layout of various images (including Linux and other firmware images) + is shown below considering a 32MB NOR flash device present on most + pre-silicon platforms (simulator and emulator): + + ------------------------- + | FIT Image | + | (linux + DTB + RFS) | + ------------------------- ----> 0x0120_0000 + | Debug Server FW | + ------------------------- ----> 0x00C0_0000 + | AIOP FW | + ------------------------- ----> 0x0070_0000 + | MC FW | + ------------------------- ----> 0x006C_0000 + | MC DPL Blob | + ------------------------- ----> 0x0020_0000 + | BootLoader + Env| + ------------------------- ----> 0x0000_1000 + | PBI | + ------------------------- ----> 0x0000_0080 + | RCW | + ------------------------- ----> 0x0000_0000 + + 32-MB NOR flash layout for pre-silicon platforms (simulator and emulator) + +(2) A typical layout of various images (including Linux and other firmware images) + is shown below considering a 128MB NOR flash device present on QDS and RDB + boards: + ----------------------------------------- ----> 0x5_8800_0000 --- + | .. Unused .. (7M) | | + ----------------------------------------- ----> 0x5_8790_0000 | + | FIT Image (linux + DTB + RFS) (40M) | | + ----------------------------------------- ----> 0x5_8510_0000 | + | PHY firmware (2M) | | + ----------------------------------------- ----> 0x5_84F0_0000 | 64K + | Debug Server FW (2M) | | Alt + ----------------------------------------- ----> 0x5_84D0_0000 | Bank + | AIOP FW (4M) | | + ----------------------------------------- ----> 0x5_8490_0000 (vbank4) + | MC DPC Blob (1M) | | + ----------------------------------------- ----> 0x5_8480_0000 | + | MC DPL Blob (1M) | | + ----------------------------------------- ----> 0x5_8470_0000 | + | MC FW (4M) | | + ----------------------------------------- ----> 0x5_8430_0000 | + | BootLoader Environment (1M) | | + ----------------------------------------- ----> 0x5_8420_0000 | + | BootLoader (1M) | | + ----------------------------------------- ----> 0x5_8410_0000 | + | RCW and PBI (1M) | | + ----------------------------------------- ----> 0x5_8400_0000 --- + | .. Unused .. (7M) | | + ----------------------------------------- ----> 0x5_8390_0000 | + | FIT Image (linux + DTB + RFS) (40M) | | + ----------------------------------------- ----> 0x5_8110_0000 | + | PHY firmware (2M) | | + ----------------------------------------- ----> 0x5_80F0_0000 | 64K + | Debug Server FW (2M) | | Bank + ----------------------------------------- ----> 0x5_80D0_0000 | + | AIOP FW (4M) | | + ----------------------------------------- ----> 0x5_8090_0000 (vbank0) + | MC DPC Blob (1M) | | + ----------------------------------------- ----> 0x5_8080_0000 | + | MC DPL Blob (1M) | | + ----------------------------------------- ----> 0x5_8070_0000 | + | MC FW (4M) | | + ----------------------------------------- ----> 0x5_8030_0000 | + | BootLoader Environment (1M) | | + ----------------------------------------- ----> 0x5_8020_0000 | + | BootLoader (1M) | | + ----------------------------------------- ----> 0x5_8010_0000 | + | RCW and PBI (1M) | | + ----------------------------------------- ----> 0x5_8000_0000 --- + + 128-MB NOR flash layout for QDS and RDB boards + +Environment Variables +===================== +mcboottimeout: MC boot timeout in milliseconds. If this variable is not defined + the value CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS will be assumed. + +mcmemsize: MC DRAM block size in hex. If this variable is not defined, the value + CONFIG_SYS_LS_MC_DRAM_BLOCK_MIN_SIZE will be assumed. + +mcinitcmd: This environment variable is defined to initiate MC and DPL deployment + from the location where it is stored(NOR, NAND, SD, SATA, USB)during + u-boot booting.If this variable is not defined then MC_BOOT_ENV_VAR + will be null and MC will not be booted and DPL will not be applied + during U-boot booting.However the MC, DPC and DPL can be applied from + console independently. + The variable needs to be set from the console once and then on + rebooting the parameters set in the variable will automatically be + executed. The commmand is demostrated taking an example of mc boot + using NOR Flash i.e. MC, DPL, and DPC is stored in the NOR flash: + + cp.b 0xa0000000 0x580300000 $filesize + cp.b 0x80000000 0x580800000 $filesize + cp.b 0x90000000 0x580700000 $filesize + + setenv mcinitcmd 'fsl_mc start mc 0x580300000 0x580800000' + + If only linux is to be booted then the mcinitcmd environment should be set as + + setenv mcinitcmd 'fsl_mc start mc 0x580300000 0x580800000;fsl_mc apply DPL 0x580700000' + + Here the addresses 0xa0000000, 0x80000000, 0x80000000 are of DDR to where + MC binary, DPC binary and DPL binary are stored and 0x580300000, 0x580800000 + and 0x580700000 are addresses in NOR where these are copied. It is to be + noted that these addresses in 'fsl_mc start mc 0x580300000 0x580800000;fsl_mc apply DPL 0x580700000' + can be replaced with the addresses of DDR to + which these will be copied in case of these binaries being stored in other + devices like SATA, USB, NAND, SD etc. + +Booting from NAND +------------------- +Booting from NAND requires two images, RCW and u-boot-with-spl.bin. +The difference between NAND boot RCW image and NOR boot image is the PBI +command sequence. Below is one example for PBI commands for LS2085AQDS which +uses NAND device with 2KB/page, block size 128KB. + +1) CCSR 4-byte write to 0x00e00404, data=0x00000000 +2) CCSR 4-byte write to 0x00e00400, data=0x1800a000 +The above two commands set bootloc register to 0x00000000_1800a000 where +the u-boot code will be running in OCRAM. + +3) Block Copy: SRC=0x0107, SRC_ADDR=0x00020000, DEST_ADDR=0x1800a000, +BLOCK_SIZE=0x00014000 +This command copies u-boot image from NAND device into OCRAM. The values need +to adjust accordingly. + +SRC should match the cfg_rcw_src, the reset config pins. It depends + on the NAND device. See reference manual for cfg_rcw_src. +SRC_ADDR is the offset of u-boot-with-spl.bin image in NAND device. In + the example above, 128KB. For easy maintenance, we put it at + the beginning of next block from RCW. +DEST_ADDR is fixed at 0x1800a000, matching bootloc set above. +BLOCK_SIZE is the size to be copied by PBI. + +RCW image should be written to the beginning of NAND device. Example of using +u-boot command + +nand write <rcw image in memory> 0 <size of rcw image> + +To form the NAND image, build u-boot with NAND config, for example, +ls2080aqds_nand_defconfig. The image needed is u-boot-with-spl.bin. +The u-boot image should be written to match SRC_ADDR, in above example 0x20000. + +nand write <u-boot image in memory> 200000 <size of u-boot image> + +With these two images in NAND device, the board can boot from NAND. + +Another example for LS2085ARDB boards, + +1) CCSR 4-byte write to 0x00e00404, data=0x00000000 +2) CCSR 4-byte write to 0x00e00400, data=0x1800a000 +3) Block Copy: SRC=0x0119, SRC_ADDR=0x00080000, DEST_ADDR=0x1800a000, +BLOCK_SIZE=0x00014000 + +nand write <rcw image in memory> 0 <size of rcw image> +nand write <u-boot image in memory> 80000 <size of u-boot image> + +Notice the difference from QDS is SRC, SRC_ADDR and the offset of u-boot image +to match board NAND device with 4KB/page, block size 512KB. + +Note, LS2088A and LS1088A don't support booting from NAND. + +Booting from SD/eMMC +------------------- +Booting from SD/eMMC requires two images, RCW and u-boot-with-spl.bin. +The difference between SD boot RCW image and QSPI-NOR boot image is the +PBI command sequence. Below is one example for PBI commands for RDB +and QDS which uses SD device with block size 512. Block location can be +calculated by dividing offset with block size. + +1) Block Copy: SRC=0x0040, SRC_ADDR=0x00100000, DEST_ADDR=0x1800a000, +BLOCK_SIZE=0x00016000 + +This command copies u-boot image from SD device into OCRAM. The values +need to adjust accordingly for SD/eMMC + +SRC should match the cfg_rcw_src, the reset config pins. + The value for source(SRC) can be 0x0040 or 0x0041 + depending upon SD or eMMC. +SRC_ADDR is the offset of u-boot-with-spl.bin image in SD device. + In the example above, 1MB. This is same as QSPI-NOR. +DEST_ADDR is configured at 0x1800a000, matching bootloc set above. +BLOCK_SIZE is the size to be copied by PBI. + +2) CCSR 4-byte write to 0x01e00404, data=0x00000000 +3) CCSR 4-byte write to 0x01e00400, data=0x1800a000 +The above two commands set bootloc register to 0x00000000_1800a000 where +the u-boot code will be running in OCRAM. + + +RCW image should be written at 8th block of device(SD/eMMC). Example of +using u-boot command + +mmc erase 0x8 0x10 +mmc write <rcw image in memory> 0x8 <size of rcw in block count typical value=10> + +To form the SD-Boot image, build u-boot with SD config, for example, +ls1088ardb_sdcard_qspi_defconfig. The image needed is u-boot-with-spl.bin. +The u-boot image should be written to match SRC_ADDR, in above example +offset 0x100000 in other work it means block location 0x800 + +mmc erase 0x800 0x1800 +mmc write <u-boot image in memory> 0x800 <size of u-boot image in block count> + +With these two images in SD/eMMC device, the board can boot from SD/eMMC. + +MMU Translation Tables +====================== + +(1) Early MMU Tables: + + Level 0 Level 1 Level 2 +------------------ ------------------ ------------------ +| 0x00_0000_0000 | -----> | 0x00_0000_0000 | -----> | 0x00_0000_0000 | +------------------ ------------------ ------------------ +| 0x80_0000_0000 | --| | 0x00_4000_0000 | | 0x00_0020_0000 | +------------------ | ------------------ ------------------ +| invalid | | | 0x00_8000_0000 | | 0x00_0040_0000 | +------------------ | ------------------ ------------------ + | | 0x00_c000_0000 | | 0x00_0060_0000 | + | ------------------ ------------------ + | | 0x01_0000_0000 | | 0x00_0080_0000 | + | ------------------ ------------------ + | ... ... + | ------------------ + | | 0x05_8000_0000 | --| + | ------------------ | + | | 0x05_c000_0000 | | + | ------------------ | + | ... | + | ------------------ | ------------------ + |--> | 0x80_0000_0000 | |-> | 0x00_3000_0000 | + ------------------ ------------------ + | 0x80_4000_0000 | | 0x00_3020_0000 | + ------------------ ------------------ + | 0x80_8000_0000 | | 0x00_3040_0000 | + ------------------ ------------------ + | 0x80_c000_0000 | | 0x00_3060_0000 | + ------------------ ------------------ + | 0x81_0000_0000 | | 0x00_3080_0000 | + ------------------ ------------------ + ... ... + +(2) Final MMU Tables: + + Level 0 Level 1 Level 2 +------------------ ------------------ ------------------ +| 0x00_0000_0000 | -----> | 0x00_0000_0000 | -----> | 0x00_0000_0000 | +------------------ ------------------ ------------------ +| 0x80_0000_0000 | --| | 0x00_4000_0000 | | 0x00_0020_0000 | +------------------ | ------------------ ------------------ +| invalid | | | 0x00_8000_0000 | | 0x00_0040_0000 | +------------------ | ------------------ ------------------ + | | 0x00_c000_0000 | | 0x00_0060_0000 | + | ------------------ ------------------ + | | 0x01_0000_0000 | | 0x00_0080_0000 | + | ------------------ ------------------ + | ... ... + | ------------------ + | | 0x08_0000_0000 | --| + | ------------------ | + | | 0x08_4000_0000 | | + | ------------------ | + | ... | + | ------------------ | ------------------ + |--> | 0x80_0000_0000 | |--> | 0x08_0000_0000 | + ------------------ ------------------ + | 0x80_4000_0000 | | 0x08_0020_0000 | + ------------------ ------------------ + | 0x80_8000_0000 | | 0x08_0040_0000 | + ------------------ ------------------ + | 0x80_c000_0000 | | 0x08_0060_0000 | + ------------------ ------------------ + | 0x81_0000_0000 | | 0x08_0080_0000 | + ------------------ ------------------ + ... ... + + +DPAA2 commands to manage Management Complex (MC) +------------------------------------------------ +DPAA2 commands has been introduced to manage Management Complex +(MC). These commands are used to start mc, aiop and apply DPL +from u-boot command prompt. + +Please note Management complex Firmware(MC), DPL and DPC are no +more deployed during u-boot boot-sequence. + +Commands: +a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex +b) fsl_mc apply DPL <DPL_addr> - Apply DPL file +c) fsl_mc start aiop <FW_addr> - Start AIOP + +How to use commands :- +1. Command sequence for u-boot ethernet: + a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex + b) DPMAC net-devices are now available for use + + Example- + Assumption: MC firmware, DPL and DPC dtb is already programmed + on NOR flash. + + => fsl_mc start mc 580300000 580800000 + => setenv ethact DPMAC1@xgmii + => ping $serverip + +2. Command sequence for Linux boot: + a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex + b) fsl_mc apply DPL <DPL_addr> - Apply DPL file + c) No DPMAC net-devices are available for use in u-boot + d) boot Linux + + Example- + Assumption: MC firmware, DPL and DPC dtb is already programmed + on NOR flash. + + => fsl_mc start mc 580300000 580800000 + => setenv ethact DPMAC1@xgmii + => tftp a0000000 kernel.itb + => fsl_mc apply dpl 580700000 + => bootm a0000000 + +3. Command sequence for AIOP boot: + a) fsl_mc start mc <FW_addr> <DPC_addr> - Start Management Complex + b) fsl_mc start aiop <FW_addr> - Start AIOP + c) fsl_mc apply DPL <DPL_addr> - Apply DPL file + d) No DPMAC net-devices are availabe for use in u-boot + Please note actual AIOP start will happen during DPL parsing of + Management complex + + Example- + Assumption: MC firmware, DPL, DPC dtb and AIOP firmware is already + programmed on NOR flash. + + => fsl_mc start mc 580300000 580800000 + => fsl_mc start aiop 0x580900000 + => setenv ethact DPMAC1@xgmii + => fsl_mc apply dpl 580700000 + +Errata A009635 +--------------- +If the core runs at higher than x3 speed of the platform, there is +possiblity about sev instruction to getting missed by other cores. +This is because of SoC Run Control block may not able to sample +the EVENTI(Sev) signals. + +Workaround: Configure Run Control and EPU to periodically send out EVENTI signals to +wake up A57 cores + +Errata workaround uses Env variable "a009635_interval_val". It uses decimal +value. +- Default value of env variable is platform clock (MHz) + +- User can modify default value by updating the env variable + setenv a009635_interval_val 600; saveenv; + It configure platform clock as 600 MHz + +- Env variable as 0 signifies no workaround
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3_2 b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3_2 new file mode 100644 index 0000000..6d4bd0b --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3_2
@@ -0,0 +1,27 @@ +# +# Copyright 2018 NXP +# +# SPDX-License-Identifier: GPL-2.0+ +# + +NXP LayerScape with Chassis Generation 3.2 + +This architecture supports NXP ARMv8 SoCs with Chassis generation 3.2 +for example LX2160A. + +This architecture is enhancement over Chassis Generation 3 with +few differences mentioned below + +1)DDR Layout +============ +Entire DDR region splits into three regions. + - Region 1 is at address 0x8000_0000 to 0xffff_ffff. + - Region 2 is at address 0x20_8000_0000 to 0x3f_ffff_ffff, + - Region 3 is at address 0x60_0000_0000 to the top of memory, + for example 140GB, 0x63_7fff_ffff. + +All DDR memory is marked as cache-enabled. + +2)IFC is removed + +3)Number of I2C controllers increased to 8
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.qspi b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.qspi new file mode 100644 index 0000000..de86f4b --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.qspi
@@ -0,0 +1,42 @@ +QSPI Boot source support Overview +------------------- + 1. LS1043A + LS1043AQDS + 2. LS2080A + LS2080AQDS + 3. LS1012A + LS1012AQDS + LS1012ARDB + 4. LS1046A + LS1046AQDS + LS1046ARDB + +Booting from QSPI +------------------- +Booting from QSPI requires two images, RCW and u-boot-dtb.bin. +The difference between QSPI boot RCW image and NOR boot image is the PBI +command sequence for setting the boot location pointer. It's should point +to the address for u-boot in QSPI flash. + +RCW image should be written to the beginning of QSPI flash device. +Example of using u-boot command + +=> sf probe 0:0 +SF: Detected S25FL256S_64K with page size 256 Bytes, erase size 64 KiB, total 32 MiB +=> sf erase 0 +<size of rcw image> +SF: 65536 bytes @ 0x0 Erased: OK +=> sf write <rcw image in memory> 0 <size of rcw image> +SF: 164 bytes @ 0x0 Written: OK + +To get the QSPI image, build u-boot with QSPI config, for example, +<board_name>_qspi_defconfig. The image needed is u-boot-dtb.bin. +The u-boot image should be written to 0x10000(but 0x1000 for LS1043A, LS2080A). + +=> sf probe 0:0 +SF: Detected S25FL256S_64K with page size 256 Bytes, erase size 64 KiB, total 32 MiB +=> sf erase 10000 +<size of u-boot image> +SF: 589824 bytes @ 0x10000 Erased: OK +=> sf write <u-boot image in memory> 10000 <size of u-boot image> +SF: 580966 bytes @ 0x10000 Written: OK + +With these two images in QSPI flash device, the board can boot from QSPI.
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc new file mode 100644 index 0000000..a0e2621 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
@@ -0,0 +1,330 @@ +SoC overview + + 1. LS1043A + 2. LS1088A + 3. LS2080A + 4. LS1012A + 5. LS1046A + 6. LS2088A + 7. LS2081A + 8. LX2160A + +LS1043A +--------- +The LS1043A integrated multicore processor combines four ARM Cortex-A53 +processor cores with datapath acceleration optimized for L2/3 packet +processing, single pass security offload and robust traffic management +and quality of service. + +The LS1043A SoC includes the following function and features: + - Four 64-bit ARM Cortex-A53 CPUs + - 1 MB unified L2 Cache + - One 32-bit DDR3L/DDR4 SDRAM memory controllers with ECC and interleaving + support + - Data Path Acceleration Architecture (DPAA) incorporating acceleration the + the following functions: + - Packet parsing, classification, and distribution (FMan) + - Queue management for scheduling, packet sequencing, and congestion + management (QMan) + - Hardware buffer management for buffer allocation and de-allocation (BMan) + - Cryptography acceleration (SEC) + - Ethernet interfaces by FMan + - Up to 1 x XFI supporting 10G interface + - Up to 1 x QSGMII + - Up to 4 x SGMII supporting 1000Mbps + - Up to 2 x SGMII supporting 2500Mbps + - Up to 2 x RGMII supporting 1000Mbps + - High-speed peripheral interfaces + - Three PCIe 2.0 controllers, one supporting x4 operation + - One serial ATA (SATA 3.0) controllers + - Additional peripheral interfaces + - Three high-speed USB 3.0 controllers with integrated PHY + - Enhanced secure digital host controller (eSDXC/eMMC) + - Quad Serial Peripheral Interface (QSPI) Controller + - Serial peripheral interface (SPI) controller + - Four I2C controllers + - Two DUARTs + - Integrated flash controller supporting NAND and NOR flash + - QorIQ platform's trust architecture 2.1 + +LS1088A +-------- +The QorIQ LS1088A processor is built on the Layerscape +architecture combining eight ARM A53 processor cores +with advanced, high-performance datapath acceleration +and networks, peripheral interfaces required for +networking, wireless infrastructure, and general-purpose +embedded applications. + +LS1088A is compliant with the Layerscape Chassis Generation 3. + +Features summary: + - 8 32-bit / 64-bit ARM v8 Cortex-A53 CPUs + - Cores are in 2 cluster of 4-cores each + - 1MB L2 - Cache per cluster + - Cache coherent interconnect (CCI-400) + - 1 64-bit DDR4 SDRAM memory controller with ECC + - Data path acceleration architecture 2.0 (DPAA2) + - 4-Lane 10GHz SerDes comprising of WRIOP + - 4-Lane 10GHz SerDes comprising of PCI, SATA, uQE(TDM/HLDC/UART) + - Ethernet interfaces: SGMIIs, RGMIIs, QSGMIIs, XFIs + - QSPI, SPI, IFC2.0 supporting NAND, NOR flash + - 3 PCIe3.0 , 1 SATA3.0, 2 USB3.0, 1 SDXC, 2 DUARTs etc + - 2 DUARTs + - 4 I2C, GPIO + - Thermal monitor unit(TMU) + - 4 Flextimers and 1 generic timer + - Support for hardware virtualization and partitioning enforcement + - QorIQ platform's trust architecture 3.0 + - Service processor (SP) provides pre-boot initialization and secure-boot + capabilities + +LS2080A +-------- +The LS2080A integrated multicore processor combines eight ARM Cortex-A57 +processor cores with high-performance data path acceleration logic and network +and peripheral bus interfaces required for networking, telecom/datacom, +wireless infrastructure, and mil/aerospace applications. + +The LS2080A SoC includes the following function and features: + + - Eight 64-bit ARM Cortex-A57 CPUs + - 1 MB platform cache with ECC + - Two 64-bit DDR4 SDRAM memory controllers with ECC and interleaving support + - One secondary 32-bit DDR4 SDRAM memory controller, intended for use by + the AIOP + - Data path acceleration architecture (DPAA2) incorporating acceleration for + the following functions: + - Packet parsing, classification, and distribution (WRIOP) + - Queue and Hardware buffer management for scheduling, packet sequencing, and + congestion management, buffer allocation and de-allocation (QBMan) + - Cryptography acceleration (SEC) at up to 10 Gbps + - RegEx pattern matching acceleration (PME) at up to 10 Gbps + - Decompression/compression acceleration (DCE) at up to 20 Gbps + - Accelerated I/O processing (AIOP) at up to 20 Gbps + - QDMA engine + - 16 SerDes lanes at up to 10.3125 GHz + - Ethernet interfaces + - Up to eight 10 Gbps Ethernet MACs + - Up to eight 1 / 2.5 Gbps Ethernet MACs + - High-speed peripheral interfaces + - Four PCIe 3.0 controllers, one supporting SR-IOV + - Additional peripheral interfaces + - Two serial ATA (SATA 3.0) controllers + - Two high-speed USB 3.0 controllers with integrated PHY + - Enhanced secure digital host controller (eSDXC/eMMC) + - Serial peripheral interface (SPI) controller + - Quad Serial Peripheral Interface (QSPI) Controller + - Four I2C controllers + - Two DUARTs + - Integrated flash controller (IFC 2.0) supporting NAND and NOR flash + - Support for hardware virtualization and partitioning enforcement + - QorIQ platform's trust architecture 3.0 + - Service processor (SP) provides pre-boot initialization and secure-boot + capabilities + +LS1012A +-------- +The LS1012A features an advanced 64-bit ARM v8 Cortex- +A53 processor, with 32 KB of parity protected L1-I cache, +32 KB of ECC protected L1-D cache, as well as 256 KB of +ECC protected L2 cache. + +The LS1012A SoC includes the following function and features: + - One 64-bit ARM v8 Cortex-A53 core with the following capabilities: + - ARM v8 cryptography extensions + - One 16-bit DDR3L SDRAM memory controller, Up to 1.0 GT/s, Supports + 16-/8-bit operation (no ECC support) + - ARM core-link CCI-400 cache coherent interconnect + - Packet Forwarding Engine (PFE) + - Cryptography acceleration (SEC) + - Ethernet interfaces supported by PFE: + - One Configurable x3 SerDes: + Two Serdes PLLs supported for usage by any SerDes data lane + Support for up to 6 GBaud operation + - High-speed peripheral interfaces: + - One PCI Express Gen2 controller, supporting x1 operation + - One serial ATA (SATA Gen 3.0) controller + - One USB 3.0/2.0 controller with integrated PHY + - One USB 2.0 controller with ULPI interface. . + - Additional peripheral interfaces: + - One quad serial peripheral interface (QuadSPI) controller + - One serial peripheral interface (SPI) controller + - Two enhanced secure digital host controllers + - Two I2C controllers + - One 16550 compliant DUART (two UART interfaces) + - Two general purpose IOs (GPIO) + - Two FlexTimers + - Five synchronous audio interfaces (SAI) + - Pre-boot loader (PBL) provides pre-boot initialization and RCW loading + - Single-source clocking solution enabling generation of core, platform, + DDR, SerDes, and USB clocks from a single external crystal and internal + crystaloscillator + - Thermal monitor unit (TMU) with +/- 3C accuracy + - Two WatchDog timers + - ARM generic timer + - QorIQ platform's trust architecture 2.1 + +LS1046A +-------- +The LS1046A integrated multicore processor combines four ARM Cortex-A72 +processor cores with datapath acceleration optimized for L2/3 packet +processing, single pass security offload and robust traffic management +and quality of service. + +The LS1046A SoC includes the following function and features: + - Four 64-bit ARM Cortex-A72 CPUs + - 2 MB unified L2 Cache + - One 64-bit DDR4 SDRAM memory controllers with ECC and interleaving + support + - Data Path Acceleration Architecture (DPAA) incorporating acceleration the + the following functions: + - Packet parsing, classification, and distribution (FMan) + - Queue management for scheduling, packet sequencing, and congestion + management (QMan) + - Hardware buffer management for buffer allocation and de-allocation (BMan) + - Cryptography acceleration (SEC) + - Two Configurable x4 SerDes + - Two PLLs per four-lane SerDes + - Support for 10G operation + - Ethernet interfaces by FMan + - Up to 2 x XFI supporting 10G interface (MAC 9, 10) + - Up to 1 x QSGMII (MAC 5, 6, 10, 1) + - Up to 4 x SGMII supporting 1000Mbps (MAC 5, 6, 9, 10) + - Up to 3 x SGMII supporting 2500Mbps (MAC 5, 9, 10) + - Up to 2 x RGMII supporting 1000Mbps (MAC 3, 4) + - High-speed peripheral interfaces + - Three PCIe 3.0 controllers, one supporting x4 operation + - One serial ATA (SATA 3.0) controllers + - Additional peripheral interfaces + - Three high-speed USB 3.0 controllers with integrated PHY + - Enhanced secure digital host controller (eSDXC/eMMC) + - Quad Serial Peripheral Interface (QSPI) Controller + - Serial peripheral interface (SPI) controller + - Four I2C controllers + - Two DUARTs + - Integrated flash controller (IFC) supporting NAND and NOR flash + - QorIQ platform's trust architecture 2.1 + +LS2088A +-------- +The LS2088A integrated multicore processor combines eight ARM Cortex-A72 +processor cores with high-performance data path acceleration logic and network +and peripheral bus interfaces required for networking, telecom/datacom, +wireless infrastructure, and mil/aerospace applications. + +The LS2088A SoC includes the following function and features: + + - Eight 64-bit ARM Cortex-A72 CPUs + - 1 MB platform cache with ECC + - Two 64-bit DDR4 SDRAM memory controllers with ECC and interleaving support + - One secondary 32-bit DDR4 SDRAM memory controller, intended for use by + the AIOP + - Data path acceleration architecture (DPAA2) incorporating acceleration for + the following functions: + - Packet parsing, classification, and distribution (WRIOP) + - Queue and Hardware buffer management for scheduling, packet sequencing, and + congestion management, buffer allocation and de-allocation (QBMan) + - Cryptography acceleration (SEC) at up to 10 Gbps + - RegEx pattern matching acceleration (PME) at up to 10 Gbps + - Decompression/compression acceleration (DCE) at up to 20 Gbps + - Accelerated I/O processing (AIOP) at up to 20 Gbps + - QDMA engine + - 16 SerDes lanes at up to 10.3125 GHz + - Ethernet interfaces + - Up to eight 10 Gbps Ethernet MACs + - Up to eight 1 / 2.5 Gbps Ethernet MACs + - High-speed peripheral interfaces + - Four PCIe 3.0 controllers, one supporting SR-IOV + - Additional peripheral interfaces + - Two serial ATA (SATA 3.0) controllers + - Two high-speed USB 3.0 controllers with integrated PHY + - Enhanced secure digital host controller (eSDXC/eMMC) + - Serial peripheral interface (SPI) controller + - Quad Serial Peripheral Interface (QSPI) Controller + - Four I2C controllers + - Two DUARTs + - Integrated flash controller (IFC 2.0) supporting NAND and NOR flash + - Support for hardware virtualization and partitioning enforcement + - QorIQ platform's trust architecture 3.0 + - Service processor (SP) provides pre-boot initialization and secure-boot + capabilities + +LS2088A SoC has 3 more similar SoC personalities +1)LS2048A, few difference w.r.t. LS2088A: + a) Four 64-bit ARM v8 Cortex-A72 CPUs + +2)LS2084A, few difference w.r.t. LS2088A: + a) No AIOP + b) No 32-bit DDR3 SDRAM memory + c) 5 * 1/10G + 5 *1G WRIOP + d) No L2 switch + +3)LS2044A, few difference w.r.t. LS2084A: + a) Four 64-bit ARM v8 Cortex-A72 CPUs + +LS2081A +-------- +LS2081A is 40-pin derivative of LS2084A. +So feature-wise it is same as LS2084A. +Refer to LS2084A(LS2088A) section above for details. + +It has one more similar SoC personality +1)LS2041A, few difference w.r.t. LS2081A: + a) Four 64-bit ARM v8 Cortex-A72 CPUs + +LX2160A +-------- +The QorIQ LX2160A processor is built in the 16FFC process on +the Layerscape architecture combining sixteen ARM A72 processor +cores with advanced, high-performance datapath acceleration and +network, peripheral interfaces required for networking, wireless +infrastructure, storage, and general-purpose embedded applications. + +LX2160A is compliant with the Layerscape Chassis Generation 3.2. + +The LX2160A SoC includes the following function and features: + Sixteen 32-bit / 64-bit ARM v8 A72 CPUs + Cache Coherent Interconnect Fabric (CCN508 aka “Eliot”) + Two 64-bit 3.2GT/s DDR4 SDRAM memory controllers with ECC. + Data path acceleration architecture (DPAA2) + 24 Serdes lanes at up to 25 GHz + Ethernet interfaces + Single WRIOP tile supporting 130Gbps using 18 MACs + Support for 10G-SXGMII (aka USXGMII). + Support for SGMII (and 1000Base-KX) + Support for XFI (and 10GBase-KR) + Support for CAUI4 (100G); CAUI2 (50G) and 25G-AUI(25G). + Support for XLAUI (and 40GBase-KR4) for 40G. + Support for two RGMII parallel interfaces. + Energy efficient Ethernet support (802.3az) + IEEE 1588 support. + High-speed peripheral interfaces + Two PCIe Gen 4.0 8-lane controllers supporting SR-IOV, + Four PCIe Gen 4.0 4-lane controllers. + Four serial ATA (SATA 3.0) controllers. + Two USB 3.0 controllers with integrated PHY + Two Enhanced secure digital host controllers + Two Controller Area Network (CAN) modules + Flexible Serial peripheral interface (FlexSPI) controller. + Three Serial peripheral interface (SPI) controllers. + Eight I2C Controllers. + Four PL011 UARTs supporting two 4-pin UART ports or four 2-pin UART ports. + General Purpose IO (GPIO) + Support for hardware virtualization and partitioning (ARM MMU-500) + Support for GIC (ARM GIC-500) + QorIQ platform Trust Architecture 3.0 + One Secure WatchDog timer and one Non-Secure Watchdog timer. + ARM Generic Timer + Two Flextimers + Debug supporting run control, data acquisition, high-speed trace, + performance/event monitoring + Thermal Monitor Unit (TMU) with +/- 2C accuracy + Support for Voltage ID (VID) for yield improvement + +LX2160A SoC has 2 more similar SoC personalities +1)LX2120A, few difference w.r.t. LX2160A: + a) Twelve 64-bit ARM v8 Cortex-A72 CPUs + +2)LX2080A, few difference w.r.t. LX2160A: + a) Eight 64-bit ARM v8 Cortex-A72 CPUs
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c new file mode 100644 index 0000000..c9c2c3f --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
@@ -0,0 +1,465 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014-2015 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <efi_loader.h> +#include <linux/libfdt.h> +#include <fdt_support.h> +#include <phy.h> +#ifdef CONFIG_FSL_LSCH3 +#include <asm/arch/fdt.h> +#endif +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> +#endif +#ifdef CONFIG_SYS_DPAA_FMAN +#include <fsl_fman.h> +#endif +#ifdef CONFIG_MP +#include <asm/arch/mp.h> +#endif +#include <fsl_sec.h> +#include <asm/arch-fsl-layerscape/soc.h> +#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT +#include <asm/armv8/sec_firmware.h> +#endif +#include <asm/arch/speed.h> +#include <fsl_qbman.h> + +int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc) +{ + return fdt_setprop_string(blob, offset, "phy-connection-type", + phy_string_for_interface(phyc)); +} + +#ifdef CONFIG_MP +void ft_fixup_cpu(void *blob) +{ + int off; + __maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr(); + fdt32_t *reg; + int addr_cells; + u64 val, core_id; + size_t *boot_code_size = &(__secondary_boot_code_size); + u32 mask = cpu_pos_mask(); + int off_prev = -1; + + off = fdt_path_offset(blob, "/cpus"); + if (off < 0) { + puts("couldn't find /cpus node\n"); + return; + } + + fdt_support_default_count_cells(blob, off, &addr_cells, NULL); + + off = fdt_node_offset_by_prop_value(blob, off_prev, "device_type", + "cpu", 4); + while (off != -FDT_ERR_NOTFOUND) { + reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0); + if (reg) { + core_id = fdt_read_number(reg, addr_cells); + if (!test_bit(id_to_core(core_id), &mask)) { + fdt_del_node(blob, off); + off = off_prev; + } + } + off_prev = off; + off = fdt_node_offset_by_prop_value(blob, off_prev, + "device_type", "cpu", 4); + } + +#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && \ + defined(CONFIG_SEC_FIRMWARE_ARMV8_PSCI) + int node; + u32 psci_ver; + + /* Check the psci version to determine if the psci is supported */ + psci_ver = sec_firmware_support_psci_version(); + if (psci_ver == 0xffffffff) { + /* remove psci DT node */ + node = fdt_path_offset(blob, "/psci"); + if (node >= 0) + goto remove_psci_node; + + node = fdt_node_offset_by_compatible(blob, -1, "arm,psci"); + if (node >= 0) + goto remove_psci_node; + + node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-0.2"); + if (node >= 0) + goto remove_psci_node; + + node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-1.0"); + if (node >= 0) + goto remove_psci_node; + +remove_psci_node: + if (node >= 0) + fdt_del_node(blob, node); + } else { + return; + } +#endif + off = fdt_path_offset(blob, "/cpus"); + if (off < 0) { + puts("couldn't find /cpus node\n"); + return; + } + fdt_support_default_count_cells(blob, off, &addr_cells, NULL); + + off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); + while (off != -FDT_ERR_NOTFOUND) { + reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0); + if (reg) { + core_id = fdt_read_number(reg, addr_cells); + if (core_id == 0 || (is_core_online(core_id))) { + val = spin_tbl_addr; + val += id_to_core(core_id) * + SPIN_TABLE_ELEM_SIZE; + val = cpu_to_fdt64(val); + fdt_setprop_string(blob, off, "enable-method", + "spin-table"); + fdt_setprop(blob, off, "cpu-release-addr", + &val, sizeof(val)); + } else { + debug("skipping offline core\n"); + } + } else { + puts("Warning: found cpu node without reg property\n"); + } + off = fdt_node_offset_by_prop_value(blob, off, "device_type", + "cpu", 4); + } + + fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code, + *boot_code_size); +#if CONFIG_IS_ENABLED(EFI_LOADER) + efi_add_memory_map((uintptr_t)&secondary_boot_code, + ALIGN(*boot_code_size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT, + EFI_RESERVED_MEMORY_TYPE, false); +#endif +} +#endif + +void fsl_fdt_disable_usb(void *blob) +{ + int off; + /* + * SYSCLK is used as a reference clock for USB. When the USB + * controller is used, SYSCLK must meet the additional requirement + * of 100 MHz. + */ + if (CONFIG_SYS_CLK_FREQ != 100000000) { + off = fdt_node_offset_by_compatible(blob, -1, "snps,dwc3"); + while (off != -FDT_ERR_NOTFOUND) { + fdt_status_disabled(blob, off); + off = fdt_node_offset_by_compatible(blob, off, + "snps,dwc3"); + } + } +} + +#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN +static void fdt_fixup_gic(void *blob) +{ + int offset, err; + u64 reg[8]; + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + unsigned int val; + struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR; + int align_64k = 0; + + val = gur_in32(&gur->svr); + + if (!IS_SVR_DEV(val, SVR_DEV(SVR_LS1043A))) { + align_64k = 1; + } else if (SVR_REV(val) != REV1_0) { + val = scfg_in32(&scfg->gic_align) & (0x01 << GIC_ADDR_BIT); + if (!val) + align_64k = 1; + } + + offset = fdt_subnode_offset(blob, 0, "interrupt-controller@1400000"); + if (offset < 0) { + printf("WARNING: fdt_subnode_offset can't find node %s: %s\n", + "interrupt-controller@1400000", fdt_strerror(offset)); + return; + } + + /* Fixup gic node align with 64K */ + if (align_64k) { + reg[0] = cpu_to_fdt64(GICD_BASE_64K); + reg[1] = cpu_to_fdt64(GICD_SIZE_64K); + reg[2] = cpu_to_fdt64(GICC_BASE_64K); + reg[3] = cpu_to_fdt64(GICC_SIZE_64K); + reg[4] = cpu_to_fdt64(GICH_BASE_64K); + reg[5] = cpu_to_fdt64(GICH_SIZE_64K); + reg[6] = cpu_to_fdt64(GICV_BASE_64K); + reg[7] = cpu_to_fdt64(GICV_SIZE_64K); + } else { + /* Fixup gic node align with default */ + reg[0] = cpu_to_fdt64(GICD_BASE); + reg[1] = cpu_to_fdt64(GICD_SIZE); + reg[2] = cpu_to_fdt64(GICC_BASE); + reg[3] = cpu_to_fdt64(GICC_SIZE); + reg[4] = cpu_to_fdt64(GICH_BASE); + reg[5] = cpu_to_fdt64(GICH_SIZE); + reg[6] = cpu_to_fdt64(GICV_BASE); + reg[7] = cpu_to_fdt64(GICV_SIZE); + } + + err = fdt_setprop(blob, offset, "reg", reg, sizeof(reg)); + if (err < 0) { + printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", + "reg", "interrupt-controller@1400000", + fdt_strerror(err)); + return; + } + + return; +} +#endif + +#ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI +static int _fdt_fixup_msi_node(void *blob, const char *name, + int irq_0, int irq_1, int rev) +{ + int err, offset, len; + u32 tmp[4][3]; + void *p; + + offset = fdt_path_offset(blob, name); + if (offset < 0) { + printf("WARNING: fdt_path_offset can't find path %s: %s\n", + name, fdt_strerror(offset)); + return 0; + } + + /*fixup the property of interrupts*/ + + tmp[0][0] = cpu_to_fdt32(0x0); + tmp[0][1] = cpu_to_fdt32(irq_0); + tmp[0][2] = cpu_to_fdt32(0x4); + + if (rev > REV1_0) { + tmp[1][0] = cpu_to_fdt32(0x0); + tmp[1][1] = cpu_to_fdt32(irq_1); + tmp[1][2] = cpu_to_fdt32(0x4); + tmp[2][0] = cpu_to_fdt32(0x0); + tmp[2][1] = cpu_to_fdt32(irq_1 + 1); + tmp[2][2] = cpu_to_fdt32(0x4); + tmp[3][0] = cpu_to_fdt32(0x0); + tmp[3][1] = cpu_to_fdt32(irq_1 + 2); + tmp[3][2] = cpu_to_fdt32(0x4); + len = sizeof(tmp); + } else { + len = sizeof(tmp[0]); + } + + err = fdt_setprop(blob, offset, "interrupts", tmp, len); + if (err < 0) { + printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", + "interrupts", name, fdt_strerror(err)); + return 0; + } + + /*fixup the property of reg*/ + p = (char *)fdt_getprop(blob, offset, "reg", &len); + if (!p) { + printf("WARNING: fdt_getprop can't get %s from node %s\n", + "reg", name); + return 0; + } + + memcpy((char *)tmp, p, len); + + if (rev > REV1_0) + *((u32 *)tmp + 3) = cpu_to_fdt32(0x1000); + else + *((u32 *)tmp + 3) = cpu_to_fdt32(0x8); + + err = fdt_setprop(blob, offset, "reg", tmp, len); + if (err < 0) { + printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", + "reg", name, fdt_strerror(err)); + return 0; + } + + /*fixup the property of compatible*/ + if (rev > REV1_0) + err = fdt_setprop_string(blob, offset, "compatible", + "fsl,ls1043a-v1.1-msi"); + else + err = fdt_setprop_string(blob, offset, "compatible", + "fsl,ls1043a-msi"); + if (err < 0) { + printf("WARNING: fdt_setprop can't set %s from node %s: %s\n", + "compatible", name, fdt_strerror(err)); + return 0; + } + + return 1; +} + +static int _fdt_fixup_pci_msi(void *blob, const char *name, int rev) +{ + int offset, len, err; + void *p; + int val; + u32 tmp[4][8]; + + offset = fdt_path_offset(blob, name); + if (offset < 0) { + printf("WARNING: fdt_path_offset can't find path %s: %s\n", + name, fdt_strerror(offset)); + return 0; + } + + p = (char *)fdt_getprop(blob, offset, "interrupt-map", &len); + if (!p || len != sizeof(tmp)) { + printf("WARNING: fdt_getprop can't get %s from node %s\n", + "interrupt-map", name); + return 0; + } + + memcpy((char *)tmp, p, len); + + val = fdt32_to_cpu(tmp[0][6]); + if (rev > REV1_0) { + tmp[1][6] = cpu_to_fdt32(val + 1); + tmp[2][6] = cpu_to_fdt32(val + 2); + tmp[3][6] = cpu_to_fdt32(val + 3); + } else { + tmp[1][6] = cpu_to_fdt32(val); + tmp[2][6] = cpu_to_fdt32(val); + tmp[3][6] = cpu_to_fdt32(val); + } + + err = fdt_setprop(blob, offset, "interrupt-map", tmp, sizeof(tmp)); + if (err < 0) { + printf("WARNING: fdt_setprop can't set %s from node %s: %s.\n", + "interrupt-map", name, fdt_strerror(err)); + return 0; + } + return 1; +} + +/* Fixup msi node for ls1043a rev1.1*/ + +static void fdt_fixup_msi(void *blob) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + unsigned int rev; + + rev = gur_in32(&gur->svr); + + if (!IS_SVR_DEV(rev, SVR_DEV(SVR_LS1043A))) + return; + + rev = SVR_REV(rev); + + _fdt_fixup_msi_node(blob, "/soc/msi-controller1@1571000", + 116, 111, rev); + _fdt_fixup_msi_node(blob, "/soc/msi-controller2@1572000", + 126, 121, rev); + _fdt_fixup_msi_node(blob, "/soc/msi-controller3@1573000", + 160, 155, rev); + + _fdt_fixup_pci_msi(blob, "/soc/pcie@3400000", rev); + _fdt_fixup_pci_msi(blob, "/soc/pcie@3500000", rev); + _fdt_fixup_pci_msi(blob, "/soc/pcie@3600000", rev); +} +#endif + +#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT +/* Remove JR node used by SEC firmware */ +void fdt_fixup_remove_jr(void *blob) +{ + int jr_node, addr_cells, len; + int crypto_node = fdt_path_offset(blob, "crypto"); + u64 jr_offset, used_jr; + fdt32_t *reg; + + used_jr = sec_firmware_used_jobring_offset(); + fdt_support_default_count_cells(blob, crypto_node, &addr_cells, NULL); + + jr_node = fdt_node_offset_by_compatible(blob, crypto_node, + "fsl,sec-v4.0-job-ring"); + + while (jr_node != -FDT_ERR_NOTFOUND) { + reg = (fdt32_t *)fdt_getprop(blob, jr_node, "reg", &len); + jr_offset = fdt_read_number(reg, addr_cells); + if (jr_offset == used_jr) { + fdt_del_node(blob, jr_node); + break; + } + jr_node = fdt_node_offset_by_compatible(blob, jr_node, + "fsl,sec-v4.0-job-ring"); + } +} +#endif + +void ft_cpu_setup(void *blob, bd_t *bd) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + unsigned int svr = gur_in32(&gur->svr); + + /* delete crypto node if not on an E-processor */ + if (!IS_E_PROCESSOR(svr)) + fdt_fixup_crypto_node(blob, 0); +#if CONFIG_SYS_FSL_SEC_COMPAT >= 4 + else { + ccsr_sec_t __iomem *sec; + +#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT + fdt_fixup_remove_jr(blob); + fdt_fixup_kaslr(blob); +#endif + + sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR; + fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms)); + } +#endif + +#ifdef CONFIG_MP + ft_fixup_cpu(blob); +#endif + +#ifdef CONFIG_SYS_NS16550 + do_fixup_by_compat_u32(blob, "fsl,ns16550", + "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); +#endif + + do_fixup_by_path_u32(blob, "/sysclk", "clock-frequency", + CONFIG_SYS_CLK_FREQ, 1); + +#ifdef CONFIG_PCI + ft_pci_setup(blob, bd); +#endif + +#ifdef CONFIG_FSL_ESDHC + fdt_fixup_esdhc(blob, bd); +#endif + +#ifdef CONFIG_SYS_DPAA_QBMAN + fdt_fixup_bportals(blob); + fdt_fixup_qportals(blob); + do_fixup_by_compat_u32(blob, "fsl,qman", + "clock-frequency", get_qman_freq(), 1); +#endif + +#ifdef CONFIG_SYS_DPAA_FMAN + fdt_fixup_fman_firmware(blob); +#endif +#ifndef CONFIG_ARCH_LS1012A + fsl_fdt_disable_usb(blob); +#endif +#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN + fdt_fixup_gic(blob); +#endif +#ifdef CONFIG_HAS_FEATURE_ENHANCED_MSI + fdt_fixup_msi(blob); +#endif +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c new file mode 100644 index 0000000..cb64cc2 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_serdes.c
@@ -0,0 +1,419 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch/soc.h> + +#ifdef CONFIG_SYS_FSL_SRDS_1 +static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT]; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 +static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT]; +#endif + +int is_serdes_configured(enum srds_prtcl device) +{ + int ret = 0; + +#ifdef CONFIG_SYS_FSL_SRDS_1 + if (!serdes1_prtcl_map[NONE]) + fsl_serdes_init(); + + ret |= serdes1_prtcl_map[device]; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + if (!serdes2_prtcl_map[NONE]) + fsl_serdes_init(); + + ret |= serdes2_prtcl_map[device]; +#endif + + return !!ret; +} + +int serdes_get_first_lane(u32 sd, enum srds_prtcl device) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 cfg = gur_in32(&gur->rcwsr[4]); + int i; + + switch (sd) { +#ifdef CONFIG_SYS_FSL_SRDS_1 + case FSL_SRDS_1: + cfg &= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; + cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; + break; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + case FSL_SRDS_2: + cfg &= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK; + cfg >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT; + break; +#endif + default: + printf("invalid SerDes%d\n", sd); + break; + } + + /* Is serdes enabled at all? */ + if (unlikely(cfg == 0)) + return -ENODEV; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (serdes_get_prtcl(sd, cfg, i) == device) + return i; + } + + return -ENODEV; +} + +int get_serdes_protocol(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 cfg = gur_in32(&gur->rcwsr[4]) & + FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; + cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; + + return cfg; +} + +const char *serdes_clock_to_string(u32 clock) +{ + switch (clock) { + case SRDS_PLLCR0_RFCK_SEL_100: + return "100"; + case SRDS_PLLCR0_RFCK_SEL_125: + return "125"; + case SRDS_PLLCR0_RFCK_SEL_156_25: + return "156.25"; + default: + return "100"; + } +} + +void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift, + u8 serdes_prtcl_map[SERDES_PRCTL_COUNT]) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 cfg; + int lane; + + if (serdes_prtcl_map[NONE]) + return; + + memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT); + + cfg = gur_in32(&gur->rcwsr[4]) & sd_prctl_mask; + cfg >>= sd_prctl_shift; + printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg); + + if (!is_serdes_prtcl_valid(sd, cfg)) + printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg); + + for (lane = 0; lane < SRDS_MAX_LANES; lane++) { + enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane); + + if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT)) + debug("Unknown SerDes lane protocol %d\n", lane_prtcl); + else + serdes_prtcl_map[lane_prtcl] = 1; + } + + /* Set the first element to indicate serdes has been initialized */ + serdes_prtcl_map[NONE] = 1; +} + +__weak int get_serdes_volt(void) +{ + return -1; +} + +__weak int set_serdes_volt(int svdd) +{ + return -1; +} + +int setup_serdes_volt(u32 svdd) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + struct ccsr_serdes *serdes1_base; +#ifdef CONFIG_SYS_FSL_SRDS_2 + struct ccsr_serdes *serdes2_base; +#endif + u32 cfg_rcw4 = gur_in32(&gur->rcwsr[4]); + u32 cfg_rcw5 = gur_in32(&gur->rcwsr[5]); + u32 cfg_tmp, reg = 0; + int svdd_cur, svdd_tar; + int ret; + int i; + + /* Only support switch SVDD to 900mV/1000mV */ + if (svdd != 900 && svdd != 1000) + return -EINVAL; + + svdd_tar = svdd; + svdd_cur = get_serdes_volt(); + if (svdd_cur < 0) + return -EINVAL; + + debug("%s: current SVDD: %dmV; target SVDD: %dmV\n", + __func__, svdd_cur, svdd_tar); + if (svdd_cur == svdd_tar) + return 0; + + serdes1_base = (void *)CONFIG_SYS_FSL_SERDES_ADDR; +#ifdef CONFIG_SYS_FSL_SRDS_2 + serdes2_base = (void *)serdes1_base + 0x10000; +#endif + + /* Put the all enabled lanes in reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; + cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; + + for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) { + reg = in_be32(&serdes1_base->lane[i].gcr0); + reg &= 0xFF9FFFFF; + out_be32(&serdes1_base->lane[i].gcr0, reg); + } +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK; + cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT; + + for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) { + reg = in_be32(&serdes2_base->lane[i].gcr0); + reg &= 0xFF9FFFFF; + out_be32(&serdes2_base->lane[i].gcr0, reg); + } +#endif + + /* Put the all enabled PLL in reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = (cfg_rcw5 >> 22) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg &= 0xFFFFFFBF; + reg |= 0x10000000; + out_be32(&serdes1_base->bank[i].rstctl, reg); + udelay(1); + + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg &= 0xFFFFFF1F; + out_be32(&serdes1_base->bank[i].rstctl, reg); + } + udelay(1); +#endif + +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = (cfg_rcw5 >> 20) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg &= 0xFFFFFFBF; + reg |= 0x10000000; + out_be32(&serdes2_base->bank[i].rstctl, reg); + udelay(1); + + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg &= 0xFFFFFF1F; + out_be32(&serdes2_base->bank[i].rstctl, reg); + } + udelay(1); +#endif + + /* Put the Rx/Tx calibration into reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + reg = in_be32(&serdes1_base->srdstcalcr); + reg &= 0xF7FFFFFF; + out_be32(&serdes1_base->srdstcalcr, reg); + reg = in_be32(&serdes1_base->srdsrcalcr); + reg &= 0xF7FFFFFF; + out_be32(&serdes1_base->srdsrcalcr, reg); + +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + reg = in_be32(&serdes2_base->srdstcalcr); + reg &= 0xF7FFFFFF; + out_be32(&serdes2_base->srdstcalcr, reg); + reg = in_be32(&serdes2_base->srdsrcalcr); + reg &= 0xF7FFFFFF; + out_be32(&serdes2_base->srdsrcalcr, reg); +#endif + + /* + * If SVDD set failed, will not return directly, so that the + * serdes lanes can complete reseting. + */ + ret = set_serdes_volt(svdd_tar); + if (ret) + printf("%s: Failed to set SVDD\n", __func__); + + /* Wait for SVDD to stabilize */ + udelay(100); + + /* For each PLL that’s not disabled via RCW */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = (cfg_rcw5 >> 22) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg |= 0x00000020; + out_be32(&serdes1_base->bank[i].rstctl, reg); + udelay(1); + + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg |= 0x00000080; + out_be32(&serdes1_base->bank[i].rstctl, reg); + + /* Take the Rx/Tx calibration out of reset */ + if (!(cfg_tmp == 0x3 && i == 1)) { + udelay(1); + reg = in_be32(&serdes1_base->srdstcalcr); + reg |= 0x08000000; + out_be32(&serdes1_base->srdstcalcr, reg); + reg = in_be32(&serdes1_base->srdsrcalcr); + reg |= 0x08000000; + out_be32(&serdes1_base->srdsrcalcr, reg); + } + } + udelay(1); +#endif + +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = (cfg_rcw5 >> 20) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg |= 0x00000020; + out_be32(&serdes2_base->bank[i].rstctl, reg); + udelay(1); + + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg |= 0x00000080; + out_be32(&serdes2_base->bank[i].rstctl, reg); + + /* Take the Rx/Tx calibration out of reset */ + if (!(cfg_tmp == 0x3 && i == 1)) { + udelay(1); + reg = in_be32(&serdes2_base->srdstcalcr); + reg |= 0x08000000; + out_be32(&serdes2_base->srdstcalcr, reg); + reg = in_be32(&serdes2_base->srdsrcalcr); + reg |= 0x08000000; + out_be32(&serdes2_base->srdsrcalcr, reg); + } + } + udelay(1); + +#endif + + /* Wait for at lesat 625us to ensure the PLLs being reset are locked */ + udelay(800); + +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = (cfg_rcw5 >> 22) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + /* if the PLL is not locked, set RST_ERR */ + reg = in_be32(&serdes1_base->bank[i].pllcr0); + if (!((reg >> 23) & 0x1)) { + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg |= 0x20000000; + out_be32(&serdes1_base->bank[i].rstctl, reg); + } else { + udelay(1); + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg &= 0xFFFFFFEF; + reg |= 0x00000040; + out_be32(&serdes1_base->bank[i].rstctl, reg); + udelay(1); + } + } +#endif + +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = (cfg_rcw5 >> 20) & 0x3; + for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) { + reg = in_be32(&serdes2_base->bank[i].pllcr0); + if (!((reg >> 23) & 0x1)) { + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg |= 0x20000000; + out_be32(&serdes2_base->bank[i].rstctl, reg); + } else { + udelay(1); + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg &= 0xFFFFFFEF; + reg |= 0x00000040; + out_be32(&serdes2_base->bank[i].rstctl, reg); + udelay(1); + } + } +#endif + + /* Take the all enabled lanes out of reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; + cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; + + for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) { + reg = in_be32(&serdes1_base->lane[i].gcr0); + reg |= 0x00600000; + out_be32(&serdes1_base->lane[i].gcr0, reg); + } +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK; + cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT; + + for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) { + reg = in_be32(&serdes2_base->lane[i].gcr0); + reg |= 0x00600000; + out_be32(&serdes2_base->lane[i].gcr0, reg); + } +#endif + /* For each PLL being reset, and achieved PLL lock set RST_DONE */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = (cfg_rcw5 >> 22) & 0x3; + for (i = 0; i < 2; i++) { + reg = in_be32(&serdes1_base->bank[i].pllcr0); + if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) { + reg = in_be32(&serdes1_base->bank[i].rstctl); + reg |= 0x40000000; + out_be32(&serdes1_base->bank[i].rstctl, reg); + } + } +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = (cfg_rcw5 >> 20) & 0x3; + for (i = 0; i < 2; i++) { + reg = in_be32(&serdes2_base->bank[i].pllcr0); + if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) { + reg = in_be32(&serdes2_base->bank[i].rstctl); + reg |= 0x40000000; + out_be32(&serdes2_base->bank[i].rstctl, reg); + } + } +#endif + + return ret; +} + +void fsl_serdes_init(void) +{ +#ifdef CONFIG_SYS_FSL_SRDS_1 + serdes_init(FSL_SRDS_1, + CONFIG_SYS_FSL_SERDES_ADDR, + FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK, + FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT, + serdes1_prtcl_map); +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + serdes_init(FSL_SRDS_2, + CONFIG_SYS_FSL_SERDES_ADDR, + FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK, + FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT, + serdes2_prtcl_map); +#endif +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c new file mode 100644 index 0000000..723d7ea --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
@@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <linux/compiler.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/arch/clock.h> +#include <asm/arch/soc.h> +#include <fsl_ifc.h> +#include "cpu.h" + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS +#define CONFIG_SYS_FSL_NUM_CC_PLLS 2 +#endif + +void get_sys_info(struct sys_info *sys_info) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); +#if (defined(CONFIG_FSL_ESDHC) &&\ + defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK)) ||\ + defined(CONFIG_SYS_DPAA_FMAN) + + u32 rcw_tmp; +#endif + struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_CLK_ADDR); + unsigned int cpu; + const u8 core_cplx_pll[8] = { + [0] = 0, /* CC1 PPL / 1 */ + [1] = 0, /* CC1 PPL / 2 */ + [4] = 1, /* CC2 PPL / 1 */ + [5] = 1, /* CC2 PPL / 2 */ + }; + + const u8 core_cplx_pll_div[8] = { + [0] = 1, /* CC1 PPL / 1 */ + [1] = 2, /* CC1 PPL / 2 */ + [4] = 1, /* CC2 PPL / 1 */ + [5] = 2, /* CC2 PPL / 2 */ + }; + + uint i, cluster; + uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS]; + uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS]; + unsigned long sysclk = CONFIG_SYS_CLK_FREQ; + unsigned long cluster_clk; + + sys_info->freq_systembus = sysclk; +#ifndef CONFIG_CLUSTER_CLK_FREQ +#define CONFIG_CLUSTER_CLK_FREQ CONFIG_SYS_CLK_FREQ +#endif + cluster_clk = CONFIG_CLUSTER_CLK_FREQ; + +#ifdef CONFIG_DDR_CLK_FREQ + sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ; +#else + sys_info->freq_ddrbus = sysclk; +#endif + + /* The freq_systembus is used to record frequency of platform PLL */ + sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >> + FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) & + FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK; + +#ifdef CONFIG_ARCH_LS1012A + sys_info->freq_ddrbus = 2 * sys_info->freq_systembus; +#else + sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >> + FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT) & + FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK; +#endif + + for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) { + ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0xff; + if (ratio[i] > 4) + freq_c_pll[i] = cluster_clk * ratio[i]; + else + freq_c_pll[i] = sys_info->freq_systembus * ratio[i]; + } + + for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) { + cluster = fsl_qoriq_core_to_cluster(cpu); + u32 c_pll_sel = (in_be32(&clk->clkcsr[cluster].clkcncsr) >> 27) + & 0xf; + u32 cplx_pll = core_cplx_pll[c_pll_sel]; + + sys_info->freq_processor[cpu] = + freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel]; + } + +#define HWA_CGA_M1_CLK_SEL 0xe0000000 +#define HWA_CGA_M1_CLK_SHIFT 29 +#ifdef CONFIG_SYS_DPAA_FMAN + rcw_tmp = in_be32(&gur->rcwsr[7]); + switch ((rcw_tmp & HWA_CGA_M1_CLK_SEL) >> HWA_CGA_M1_CLK_SHIFT) { + case 2: + sys_info->freq_fman[0] = freq_c_pll[0] / 2; + break; + case 3: + sys_info->freq_fman[0] = freq_c_pll[0] / 3; + break; + case 4: + sys_info->freq_fman[0] = freq_c_pll[0] / 4; + break; + case 5: + sys_info->freq_fman[0] = sys_info->freq_systembus; + break; + case 6: + sys_info->freq_fman[0] = freq_c_pll[1] / 2; + break; + case 7: + sys_info->freq_fman[0] = freq_c_pll[1] / 3; + break; + default: + printf("Error: Unknown FMan1 clock select!\n"); + break; + } +#endif + +#define HWA_CGA_M2_CLK_SEL 0x00000007 +#define HWA_CGA_M2_CLK_SHIFT 0 +#ifdef CONFIG_FSL_ESDHC +#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK + rcw_tmp = in_be32(&gur->rcwsr[15]); + switch ((rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT) { + case 1: + sys_info->freq_sdhc = freq_c_pll[1]; + break; + case 2: + sys_info->freq_sdhc = freq_c_pll[1] / 2; + break; + case 3: + sys_info->freq_sdhc = freq_c_pll[1] / 3; + break; + case 6: + sys_info->freq_sdhc = freq_c_pll[0] / 2; + break; + default: + printf("Error: Unknown ESDHC clock select!\n"); + break; + } +#else + sys_info->freq_sdhc = (sys_info->freq_systembus / + CONFIG_SYS_FSL_PCLK_DIV) / + CONFIG_SYS_FSL_SDHC_CLK_DIV; +#endif +#endif + +#if defined(CONFIG_FSL_IFC) + sys_info->freq_localbus = sys_info->freq_systembus / + CONFIG_SYS_FSL_IFC_CLK_DIV; +#endif +#ifdef CONFIG_SYS_DPAA_QBMAN + sys_info->freq_qman = (sys_info->freq_systembus / + CONFIG_SYS_FSL_PCLK_DIV) / + CONFIG_SYS_FSL_QMAN_CLK_DIV; +#endif +} + +#ifdef CONFIG_SYS_DPAA_QBMAN +unsigned long get_qman_freq(void) +{ + struct sys_info sys_info; + + get_sys_info(&sys_info); + + return sys_info.freq_qman; +} +#endif + +int get_clocks(void) +{ + struct sys_info sys_info; + + get_sys_info(&sys_info); + gd->cpu_clk = sys_info.freq_processor[0]; + gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV; + gd->mem_clk = sys_info.freq_ddrbus; + +#ifdef CONFIG_FSL_ESDHC + gd->arch.sdhc_clk = sys_info.freq_sdhc; +#endif + + if (gd->cpu_clk != 0) + return 0; + else + return 1; +} + +/******************************************** + * get_bus_freq + * return platform clock in Hz + *********************************************/ +ulong get_bus_freq(ulong dummy) +{ + if (!gd->bus_clk) + get_clocks(); + + return gd->bus_clk; +} + +ulong get_ddr_freq(ulong dummy) +{ + if (!gd->mem_clk) + get_clocks(); + + return gd->mem_clk; +} + +#ifdef CONFIG_FSL_ESDHC +int get_sdhc_freq(ulong dummy) +{ + if (!gd->arch.sdhc_clk) + get_clocks(); + + return gd->arch.sdhc_clk; +} +#endif + +int get_serial_clock(void) +{ + return get_bus_freq(0) / CONFIG_SYS_FSL_DUART_CLK_DIV; +} + +int get_i2c_freq(ulong dummy) +{ + return get_bus_freq(0) / CONFIG_SYS_FSL_I2C_CLK_DIV; +} + +int get_dspi_freq(ulong dummy) +{ + return get_bus_freq(0) / CONFIG_SYS_FSL_DSPI_CLK_DIV; +} + +#ifdef CONFIG_FSL_LPUART +int get_uart_freq(ulong dummy) +{ + return get_bus_freq(0) / CONFIG_SYS_FSL_LPUART_CLK_DIV; +} +#endif + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_I2C_CLK: + return get_i2c_freq(0); +#if defined(CONFIG_FSL_ESDHC) + case MXC_ESDHC_CLK: + return get_sdhc_freq(0); +#endif + case MXC_DSPI_CLK: + return get_dspi_freq(0); +#ifdef CONFIG_FSL_LPUART + case MXC_UART_CLK: + return get_uart_freq(0); +#endif + default: + printf("Unsupported clock\n"); + } + return 0; +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c new file mode 100644 index 0000000..ab1be3f --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
@@ -0,0 +1,582 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2016-2018 NXP + * Copyright 2014-2015 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/errno.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch/soc.h> +#include <fsl-mc/ldpaa_wriop.h> + +#ifdef CONFIG_SYS_FSL_SRDS_1 +static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT]; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 +static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT]; +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 +static u8 serdes3_prtcl_map[SERDES_PRCTL_COUNT]; +#endif + +#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) +#ifdef CONFIG_ARCH_LX2160A +int xfi_dpmac[XFI14 + 1]; +int sgmii_dpmac[SGMII18 + 1]; +int a25gaui_dpmac[_25GE10 + 1]; +int xlaui_dpmac[_40GE2 + 1]; +int caui2_dpmac[_50GE2 + 1]; +int caui4_dpmac[_100GE2 + 1]; +#else +int xfi_dpmac[XFI8 + 1]; +int sgmii_dpmac[SGMII16 + 1]; +#endif +#endif + +__weak void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl) +{ + return; +} + +/* + *The return value of this func is the serdes protocol used. + *Typically this function is called number of times depending + *upon the number of serdes blocks in the Silicon. + *Zero is used to denote that no serdes was enabled, + *this is the case when golden RCW was used where DPAA2 bring was + *intentionally removed to achieve boot to prompt +*/ + +__weak int serdes_get_number(int serdes, int cfg) +{ + return cfg; +} + +int is_serdes_configured(enum srds_prtcl device) +{ + int ret = 0; + +#ifdef CONFIG_SYS_FSL_SRDS_1 + if (!serdes1_prtcl_map[NONE]) + fsl_serdes_init(); + + ret |= serdes1_prtcl_map[device]; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + if (!serdes2_prtcl_map[NONE]) + fsl_serdes_init(); + + ret |= serdes2_prtcl_map[device]; +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + if (!serdes3_prtcl_map[NONE]) + fsl_serdes_init(); + + ret |= serdes3_prtcl_map[device]; +#endif + + return !!ret; +} + +int serdes_get_first_lane(u32 sd, enum srds_prtcl device) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 cfg = 0; + int i; + + switch (sd) { +#ifdef CONFIG_SYS_FSL_SRDS_1 + case FSL_SRDS_1: + cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]); + cfg &= FSL_CHASSIS3_SRDS1_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT; + break; +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + case FSL_SRDS_2: + cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]); + cfg &= FSL_CHASSIS3_SRDS2_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_SRDS2_PRTCL_SHIFT; + break; +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + case NXP_SRDS_3: + cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS3_REGSR - 1]); + cfg &= FSL_CHASSIS3_SRDS3_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_SRDS3_PRTCL_SHIFT; + break; +#endif + default: + printf("invalid SerDes%d\n", sd); + break; + } + + cfg = serdes_get_number(sd, cfg); + + /* Is serdes enabled at all? */ + if (cfg == 0) + return -ENODEV; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (serdes_get_prtcl(sd, cfg, i) == device) + return i; + } + + return -ENODEV; +} + +void serdes_init(u32 sd, u32 sd_addr, u32 rcwsr, u32 sd_prctl_mask, + u32 sd_prctl_shift, u8 serdes_prtcl_map[SERDES_PRCTL_COUNT]) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 cfg; + int lane; + + if (serdes_prtcl_map[NONE]) + return; + + memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT); + + cfg = gur_in32(&gur->rcwsr[rcwsr - 1]) & sd_prctl_mask; + cfg >>= sd_prctl_shift; + + cfg = serdes_get_number(sd, cfg); + printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg); + + if (!is_serdes_prtcl_valid(sd, cfg)) + printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg); + + for (lane = 0; lane < SRDS_MAX_LANES; lane++) { + enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane); + if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT)) + debug("Unknown SerDes lane protocol %d\n", lane_prtcl); + else { + serdes_prtcl_map[lane_prtcl] = 1; +#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) +#ifdef CONFIG_ARCH_LX2160A + if (lane_prtcl >= XFI1 && lane_prtcl <= XFI14) + wriop_init_dpmac(sd, xfi_dpmac[lane_prtcl], + (int)lane_prtcl); + + if (lane_prtcl >= SGMII1 && lane_prtcl <= SGMII18) + wriop_init_dpmac(sd, sgmii_dpmac[lane_prtcl], + (int)lane_prtcl); + + if (lane_prtcl >= _25GE1 && lane_prtcl <= _25GE10) + wriop_init_dpmac(sd, a25gaui_dpmac[lane_prtcl], + (int)lane_prtcl); + + if (lane_prtcl >= _40GE1 && lane_prtcl <= _40GE2) + wriop_init_dpmac(sd, xlaui_dpmac[lane_prtcl], + (int)lane_prtcl); + + if (lane_prtcl >= _50GE1 && lane_prtcl <= _50GE2) + wriop_init_dpmac(sd, caui2_dpmac[lane_prtcl], + (int)lane_prtcl); + + if (lane_prtcl >= _100GE1 && lane_prtcl <= _100GE2) + wriop_init_dpmac(sd, caui4_dpmac[lane_prtcl], + (int)lane_prtcl); + +#else + switch (lane_prtcl) { + case QSGMII_A: + case QSGMII_B: + case QSGMII_C: + case QSGMII_D: + wriop_init_dpmac_qsgmii(sd, (int)lane_prtcl); + break; + default: + if (lane_prtcl >= XFI1 && lane_prtcl <= XFI8) + wriop_init_dpmac(sd, + xfi_dpmac[lane_prtcl], + (int)lane_prtcl); + + if (lane_prtcl >= SGMII1 && + lane_prtcl <= SGMII16) + wriop_init_dpmac(sd, sgmii_dpmac[ + lane_prtcl], + (int)lane_prtcl); + break; + } +#endif +#endif + } + } + + /* Set the first element to indicate serdes has been initialized */ + serdes_prtcl_map[NONE] = 1; +} + +__weak int get_serdes_volt(void) +{ + return -1; +} + +__weak int set_serdes_volt(int svdd) +{ + return -1; +} + +#define LNAGCR0_RT_RSTB 0x00600000 + +#define RSTCTL_RESET_MASK 0x000000E0 + +#define RSTCTL_RSTREQ 0x80000000 +#define RSTCTL_RST_DONE 0x40000000 +#define RSTCTL_RSTERR 0x20000000 + +#define RSTCTL_SDEN 0x00000020 +#define RSTCTL_SDRST_B 0x00000040 +#define RSTCTL_PLLRST_B 0x00000080 + +#define TCALCR_CALRST_B 0x08000000 + +struct serdes_prctl_info { + u32 id; + u32 mask; + u32 shift; +}; + +struct serdes_prctl_info srds_prctl_info[] = { +#ifdef CONFIG_SYS_FSL_SRDS_1 + {.id = 1, + .mask = FSL_CHASSIS3_SRDS1_PRTCL_MASK, + .shift = FSL_CHASSIS3_SRDS1_PRTCL_SHIFT + }, + +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + {.id = 2, + .mask = FSL_CHASSIS3_SRDS2_PRTCL_MASK, + .shift = FSL_CHASSIS3_SRDS2_PRTCL_SHIFT + }, +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + {.id = 3, + .mask = FSL_CHASSIS3_SRDS3_PRTCL_MASK, + .shift = FSL_CHASSIS3_SRDS3_PRTCL_SHIFT + }, +#endif + {} /* NULL ENTRY */ +}; + +static int get_serdes_prctl_info_idx(u32 serdes_id) +{ + int pos = 0; + struct serdes_prctl_info *srds_info; + + /* loop until NULL ENTRY defined by .id=0 */ + for (srds_info = srds_prctl_info; srds_info->id != 0; + srds_info++, pos++) { + if (srds_info->id == serdes_id) + return pos; + } + + return -1; +} + +static void do_enabled_lanes_reset(u32 serdes_id, u32 cfg, + struct ccsr_serdes __iomem *serdes_base, + bool cmplt) +{ + int i, pos; + u32 cfg_tmp; + + pos = get_serdes_prctl_info_idx(serdes_id); + if (pos == -1) { + printf("invalid serdes_id %d\n", serdes_id); + return; + } + + cfg_tmp = cfg & srds_prctl_info[pos].mask; + cfg_tmp >>= srds_prctl_info[pos].shift; + + for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) { + if (cmplt) + setbits_le32(&serdes_base->lane[i].gcr0, + LNAGCR0_RT_RSTB); + else + clrbits_le32(&serdes_base->lane[i].gcr0, + LNAGCR0_RT_RSTB); + } +} + +static void do_pll_reset(u32 cfg, + struct ccsr_serdes __iomem *serdes_base) +{ + int i; + + for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) { + clrbits_le32(&serdes_base->bank[i].rstctl, + RSTCTL_RESET_MASK); + udelay(1); + + setbits_le32(&serdes_base->bank[i].rstctl, + RSTCTL_RSTREQ); + } + udelay(1); +} + +static void do_rx_tx_cal_reset(struct ccsr_serdes __iomem *serdes_base) +{ + clrbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B); + clrbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B); +} + +static void do_rx_tx_cal_reset_comp(u32 cfg, int i, + struct ccsr_serdes __iomem *serdes_base) +{ + if (!(cfg == 0x3 && i == 1)) { + udelay(1); + setbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B); + setbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B); + } + udelay(1); +} + +static void do_pll_reset_done(u32 cfg, + struct ccsr_serdes __iomem *serdes_base) +{ + int i; + u32 reg = 0; + + for (i = 0; i < 2; i++) { + reg = in_le32(&serdes_base->bank[i].pllcr0); + if (!(cfg & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) { + setbits_le32(&serdes_base->bank[i].rstctl, + RSTCTL_RST_DONE); + } + } +} + +static void do_serdes_enable(u32 cfg, + struct ccsr_serdes __iomem *serdes_base) +{ + int i; + + for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) { + setbits_le32(&serdes_base->bank[i].rstctl, RSTCTL_SDEN); + udelay(1); + + setbits_le32(&serdes_base->bank[i].rstctl, RSTCTL_PLLRST_B); + udelay(1); + /* Take the Rx/Tx calibration out of reset */ + do_rx_tx_cal_reset_comp(cfg, i, serdes_base); + } +} + +static void do_pll_lock(u32 cfg, + struct ccsr_serdes __iomem *serdes_base) +{ + int i; + u32 reg = 0; + + for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) { + /* if the PLL is not locked, set RST_ERR */ + reg = in_le32(&serdes_base->bank[i].pllcr0); + if (!((reg >> 23) & 0x1)) { + setbits_le32(&serdes_base->bank[i].rstctl, + RSTCTL_RSTERR); + } else { + udelay(1); + setbits_le32(&serdes_base->bank[i].rstctl, + RSTCTL_SDRST_B); + udelay(1); + } + } +} + +int setup_serdes_volt(u32 svdd) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + struct ccsr_serdes __iomem *serdes1_base = + (void *)CONFIG_SYS_FSL_LSCH3_SERDES_ADDR; + u32 cfg_rcwsrds1 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]); +#ifdef CONFIG_SYS_FSL_SRDS_2 + struct ccsr_serdes __iomem *serdes2_base = + (void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x10000); + u32 cfg_rcwsrds2 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]); +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + struct ccsr_serdes __iomem *serdes3_base = + (void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x20000); + u32 cfg_rcwsrds3 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS3_REGSR - 1]); +#endif + u32 cfg_tmp; + int svdd_cur, svdd_tar; + int ret = 1; + + /* Only support switch SVDD to 900mV */ + if (svdd != 900) + return -EINVAL; + + /* Scale up to the LTC resolution is 1/4096V */ + svdd = (svdd * 4096) / 1000; + + svdd_tar = svdd; + svdd_cur = get_serdes_volt(); + if (svdd_cur < 0) + return -EINVAL; + + debug("%s: current SVDD: %x; target SVDD: %x\n", + __func__, svdd_cur, svdd_tar); + if (svdd_cur == svdd_tar) + return 0; + + /* Put the all enabled lanes in reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + do_enabled_lanes_reset(1, cfg_rcwsrds1, serdes1_base, false); +#endif + +#ifdef CONFIG_SYS_FSL_SRDS_2 + do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, false); +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + do_enabled_lanes_reset(3, cfg_rcwsrds3, serdes3_base, false); +#endif + + /* Put the all enabled PLL in reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = cfg_rcwsrds1 & 0x3; + do_pll_reset(cfg_tmp, serdes1_base); +#endif + +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = cfg_rcwsrds1 & 0xC; + cfg_tmp >>= 2; + do_pll_reset(cfg_tmp, serdes2_base); +#endif + +#ifdef CONFIG_SYS_NXP_SRDS_3 + cfg_tmp = cfg_rcwsrds3 & 0x30; + cfg_tmp >>= 4; + do_pll_reset(cfg_tmp, serdes3_base); +#endif + + /* Put the Rx/Tx calibration into reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + do_rx_tx_cal_reset(serdes1_base); +#endif + +#ifdef CONFIG_SYS_FSL_SRDS_2 + do_rx_tx_cal_reset(serdes2_base); +#endif + +#ifdef CONFIG_SYS_NXP_SRDS_3 + do_rx_tx_cal_reset(serdes3_base); +#endif + + ret = set_serdes_volt(svdd); + if (ret < 0) { + printf("could not change SVDD\n"); + ret = -1; + } + + /* For each PLL that’s not disabled via RCW enable the SERDES */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = cfg_rcwsrds1 & 0x3; + do_serdes_enable(cfg_tmp, serdes1_base); +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = cfg_rcwsrds1 & 0xC; + cfg_tmp >>= 2; + do_serdes_enable(cfg_tmp, serdes2_base); +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + cfg_tmp = cfg_rcwsrds3 & 0x30; + cfg_tmp >>= 4; + do_serdes_enable(cfg_tmp, serdes3_base); +#endif + + /* Wait for at at least 625us, ensure the PLLs being reset are locked */ + udelay(800); + +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = cfg_rcwsrds1 & 0x3; + do_pll_lock(cfg_tmp, serdes1_base); +#endif + +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = cfg_rcwsrds1 & 0xC; + cfg_tmp >>= 2; + do_pll_lock(cfg_tmp, serdes2_base); +#endif + +#ifdef CONFIG_SYS_NXP_SRDS_3 + cfg_tmp = cfg_rcwsrds3 & 0x30; + cfg_tmp >>= 4; + do_pll_lock(cfg_tmp, serdes3_base); +#endif + + /* Take the all enabled lanes out of reset */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + do_enabled_lanes_reset(1, cfg_rcwsrds1, serdes1_base, true); +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, true); +#endif + +#ifdef CONFIG_SYS_NXP_SRDS_3 + do_enabled_lanes_reset(3, cfg_rcwsrds3, serdes3_base, true); +#endif + + /* For each PLL being reset, and achieved PLL lock set RST_DONE */ +#ifdef CONFIG_SYS_FSL_SRDS_1 + cfg_tmp = cfg_rcwsrds1 & 0x3; + do_pll_reset_done(cfg_tmp, serdes1_base); +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + cfg_tmp = cfg_rcwsrds1 & 0xC; + cfg_tmp >>= 2; + do_pll_reset_done(cfg_tmp, serdes2_base); +#endif + +#ifdef CONFIG_SYS_NXP_SRDS_3 + cfg_tmp = cfg_rcwsrds3 & 0x30; + cfg_tmp >>= 4; + do_pll_reset_done(cfg_tmp, serdes3_base); +#endif + + return ret; +} + +void fsl_serdes_init(void) +{ +#if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD) + int i , j; + + for (i = XFI1, j = 1; i <= XFI8; i++, j++) + xfi_dpmac[i] = j; + + for (i = SGMII1, j = 1; i <= SGMII16; i++, j++) + sgmii_dpmac[i] = j; +#endif + +#ifdef CONFIG_SYS_FSL_SRDS_1 + serdes_init(FSL_SRDS_1, + CONFIG_SYS_FSL_LSCH3_SERDES_ADDR, + FSL_CHASSIS3_SRDS1_REGSR, + FSL_CHASSIS3_SRDS1_PRTCL_MASK, + FSL_CHASSIS3_SRDS1_PRTCL_SHIFT, + serdes1_prtcl_map); +#endif +#ifdef CONFIG_SYS_FSL_SRDS_2 + serdes_init(FSL_SRDS_2, + CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + FSL_SRDS_2 * 0x10000, + FSL_CHASSIS3_SRDS2_REGSR, + FSL_CHASSIS3_SRDS2_PRTCL_MASK, + FSL_CHASSIS3_SRDS2_PRTCL_SHIFT, + serdes2_prtcl_map); +#endif +#ifdef CONFIG_SYS_NXP_SRDS_3 + serdes_init(NXP_SRDS_3, + CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + NXP_SRDS_3 * 0x10000, + FSL_CHASSIS3_SRDS3_REGSR, + FSL_CHASSIS3_SRDS3_PRTCL_MASK, + FSL_CHASSIS3_SRDS3_PRTCL_SHIFT, + serdes3_prtcl_map); +#endif +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c new file mode 100644 index 0000000..bc268e2 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_speed.c
@@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014-2015, Freescale Semiconductor, Inc. + * + * Derived from arch/power/cpu/mpc85xx/speed.c + */ + +#include <common.h> +#include <linux/compiler.h> +#include <fsl_ifc.h> +#include <asm/processor.h> +#include <asm/io.h> +#include <asm/arch-fsl-layerscape/immap_lsch3.h> +#include <asm/arch/clock.h> +#include <asm/arch/soc.h> +#include "cpu.h" + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SYS_FSL_NUM_CC_PLLS +#define CONFIG_SYS_FSL_NUM_CC_PLLS 6 +#endif + + +void get_sys_info(struct sys_info *sys_info) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + struct ccsr_clk_cluster_group __iomem *clk_grp[2] = { + (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPA_ADDR), + (void *)(CONFIG_SYS_FSL_CH3_CLK_GRPB_ADDR) + }; + struct ccsr_clk_ctrl __iomem *clk_ctrl = + (void *)(CONFIG_SYS_FSL_CH3_CLK_CTRL_ADDR); + unsigned int cpu; + const u8 core_cplx_pll[16] = { + [0] = 0, /* CC1 PPL / 1 */ + [1] = 0, /* CC1 PPL / 2 */ + [2] = 0, /* CC1 PPL / 4 */ + [4] = 1, /* CC2 PPL / 1 */ + [5] = 1, /* CC2 PPL / 2 */ + [6] = 1, /* CC2 PPL / 4 */ + [8] = 2, /* CC3 PPL / 1 */ + [9] = 2, /* CC3 PPL / 2 */ + [10] = 2, /* CC3 PPL / 4 */ + [12] = 3, /* CC4 PPL / 1 */ + [13] = 3, /* CC4 PPL / 2 */ + [14] = 3, /* CC4 PPL / 4 */ + }; + + const u8 core_cplx_pll_div[16] = { + [0] = 1, /* CC1 PPL / 1 */ + [1] = 2, /* CC1 PPL / 2 */ + [2] = 4, /* CC1 PPL / 4 */ + [4] = 1, /* CC2 PPL / 1 */ + [5] = 2, /* CC2 PPL / 2 */ + [6] = 4, /* CC2 PPL / 4 */ + [8] = 1, /* CC3 PPL / 1 */ + [9] = 2, /* CC3 PPL / 2 */ + [10] = 4, /* CC3 PPL / 4 */ + [12] = 1, /* CC4 PPL / 1 */ + [13] = 2, /* CC4 PPL / 2 */ + [14] = 4, /* CC4 PPL / 4 */ + }; + + uint i, cluster; + uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS]; + uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS]; + unsigned long sysclk = CONFIG_SYS_CLK_FREQ; + int cc_group[12] = CONFIG_SYS_FSL_CLUSTER_CLOCKS; + u32 c_pll_sel, cplx_pll; + void *offset; + + sys_info->freq_systembus = sysclk; +#ifdef CONFIG_DDR_CLK_FREQ + sys_info->freq_ddrbus = CONFIG_DDR_CLK_FREQ; +#ifdef CONFIG_SYS_FSL_HAS_DP_DDR + sys_info->freq_ddrbus2 = CONFIG_DDR_CLK_FREQ; +#endif +#else + sys_info->freq_ddrbus = sysclk; +#ifdef CONFIG_SYS_FSL_HAS_DP_DDR + sys_info->freq_ddrbus2 = sysclk; +#endif +#endif + + /* The freq_systembus is used to record frequency of platform PLL */ + sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >> + FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_SHIFT) & + FSL_CHASSIS3_RCWSR0_SYS_PLL_RAT_MASK; + sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >> + FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_SHIFT) & + FSL_CHASSIS3_RCWSR0_MEM_PLL_RAT_MASK; +#ifdef CONFIG_SYS_FSL_HAS_DP_DDR + if (soc_has_dp_ddr()) { + sys_info->freq_ddrbus2 *= (gur_in32(&gur->rcwsr[0]) >> + FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_SHIFT) & + FSL_CHASSIS3_RCWSR0_MEM2_PLL_RAT_MASK; + } else { + sys_info->freq_ddrbus2 = 0; + } +#endif + + for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) { + /* + * fixme: prefer to combine the following into one line, but + * cannot pass compiling without warning about in_le32. + */ + offset = (void *)((size_t)clk_grp[i/3] + + offsetof(struct ccsr_clk_cluster_group, + pllngsr[i%3].gsr)); + ratio[i] = (in_le32(offset) >> 1) & 0x3f; + freq_c_pll[i] = sysclk * ratio[i]; + } + + for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) { + cluster = fsl_qoriq_core_to_cluster(cpu); + c_pll_sel = (in_le32(&clk_ctrl->clkcncsr[cluster].csr) >> 27) + & 0xf; + cplx_pll = core_cplx_pll[c_pll_sel]; + cplx_pll += cc_group[cluster] - 1; + sys_info->freq_processor[cpu] = + freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel]; + } + +#if defined(CONFIG_FSL_IFC) + sys_info->freq_localbus = sys_info->freq_systembus / + CONFIG_SYS_FSL_IFC_CLK_DIV; +#endif +} + + +int get_clocks(void) +{ + struct sys_info sys_info; + get_sys_info(&sys_info); + gd->cpu_clk = sys_info.freq_processor[0]; + gd->bus_clk = sys_info.freq_systembus / CONFIG_SYS_FSL_PCLK_DIV; + gd->mem_clk = sys_info.freq_ddrbus; +#ifdef CONFIG_SYS_FSL_HAS_DP_DDR + gd->arch.mem2_clk = sys_info.freq_ddrbus2; +#endif +#if defined(CONFIG_FSL_ESDHC) + gd->arch.sdhc_clk = gd->bus_clk / CONFIG_SYS_FSL_SDHC_CLK_DIV; +#endif /* defined(CONFIG_FSL_ESDHC) */ + + if (gd->cpu_clk != 0) + return 0; + else + return 1; +} + +/******************************************** + * get_bus_freq + * return platform clock in Hz + *********************************************/ +ulong get_bus_freq(ulong dummy) +{ + if (!gd->bus_clk) + get_clocks(); + + return gd->bus_clk; +} + +/******************************************** + * get_ddr_freq + * return ddr bus freq in Hz + *********************************************/ +ulong get_ddr_freq(ulong ctrl_num) +{ + if (!gd->mem_clk) + get_clocks(); + + /* + * DDR controller 0 & 1 are on memory complex 0 + * DDR controller 2 is on memory complext 1 + */ +#ifdef CONFIG_SYS_FSL_HAS_DP_DDR + if (ctrl_num >= 2) + return gd->arch.mem2_clk; +#endif + + return gd->mem_clk; +} + +int get_i2c_freq(ulong dummy) +{ + return get_bus_freq(0) / CONFIG_SYS_FSL_I2C_CLK_DIV; +} + +int get_dspi_freq(ulong dummy) +{ + return get_bus_freq(0) / CONFIG_SYS_FSL_DSPI_CLK_DIV; +} + +#ifdef CONFIG_FSL_ESDHC +int get_sdhc_freq(ulong dummy) +{ + if (!gd->arch.sdhc_clk) + get_clocks(); + + return gd->arch.sdhc_clk; +} +#endif + +int get_serial_clock(void) +{ + return get_bus_freq(0) / CONFIG_SYS_FSL_DUART_CLK_DIV; +} + +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_I2C_CLK: + return get_i2c_freq(0); +#if defined(CONFIG_FSL_ESDHC) + case MXC_ESDHC_CLK: + return get_sdhc_freq(0); +#endif + case MXC_DSPI_CLK: + return get_dspi_freq(0); + default: + printf("Unsupported clock\n"); + } + return 0; +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/icid.c b/arch/arm/cpu/armv8/fsl-layerscape/icid.c new file mode 100644 index 0000000..b1a950e --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/icid.c
@@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 NXP + */ + +#include <common.h> +#include <linux/libfdt.h> +#include <fdt_support.h> + +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/arch-fsl-layerscape/fsl_icid.h> +#include <fsl_fman.h> + +static void set_icid(struct icid_id_table *tbl, int size) +{ + int i; + + for (i = 0; i < size; i++) + out_be32((u32 *)(tbl[i].reg_addr), tbl[i].reg); +} + +#ifdef CONFIG_SYS_DPAA_FMAN +void set_fman_icids(struct fman_icid_id_table *tbl, int size) +{ + int i; + ccsr_fman_t *fm = (void *)CONFIG_SYS_FSL_FM1_ADDR; + + for (i = 0; i < size; i++) { + out_be32(&fm->fm_bmi_common.fmbm_ppid[tbl[i].port_id - 1], + tbl[i].icid); + } +} +#endif + +void set_icids(void) +{ + /* setup general icid offsets */ + set_icid(icid_tbl, icid_tbl_sz); + +#ifdef CONFIG_SYS_DPAA_FMAN + set_fman_icids(fman_icid_tbl, fman_icid_tbl_sz); +#endif +} + +int fdt_set_iommu_prop(void *blob, int off, int smmu_ph, u32 *ids, int num_ids) +{ + int i, ret; + u32 prop[8]; + + /* + * Note: The "iommus" property definition mentions Stream IDs while + * this code handles ICIDs. The current implementation assumes that + * ICIDs and Stream IDs are equal. + */ + for (i = 0; i < num_ids; i++) { + prop[i * 2] = cpu_to_fdt32(smmu_ph); + prop[i * 2 + 1] = cpu_to_fdt32(ids[i]); + } + ret = fdt_setprop(blob, off, "iommus", + prop, sizeof(u32) * num_ids * 2); + if (ret) { + printf("WARNING unable to set iommus: %s\n", fdt_strerror(ret)); + return ret; + } + + return 0; +} + +int fdt_fixup_icid_tbl(void *blob, int smmu_ph, + struct icid_id_table *tbl, int size) +{ + int i, err, off; + + for (i = 0; i < size; i++) { + if (!tbl[i].compat) + continue; + + off = fdt_node_offset_by_compat_reg(blob, + tbl[i].compat, + tbl[i].compat_addr); + if (off > 0) { + err = fdt_set_iommu_prop(blob, off, smmu_ph, + &tbl[i].id, 1); + if (err) + return err; + } else { + printf("WARNING could not find node %s: %s.\n", + tbl[i].compat, fdt_strerror(off)); + } + } + + return 0; +} + +#ifdef CONFIG_SYS_DPAA_FMAN +int get_fman_port_icid(int port_id, struct fman_icid_id_table *tbl, + const int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (tbl[i].port_id == port_id) + return tbl[i].icid; + } + + return -1; +} + +void fdt_fixup_fman_port_icid_by_compat(void *blob, int smmu_ph, + const char *compat) +{ + int noff, len, icid; + const u32 *prop; + + noff = fdt_node_offset_by_compatible(blob, -1, compat); + while (noff > 0) { + prop = fdt_getprop(blob, noff, "cell-index", &len); + if (!prop) { + printf("WARNING missing cell-index for fman port\n"); + continue; + } + if (len != 4) { + printf("WARNING bad cell-index size for fman port\n"); + continue; + } + + icid = get_fman_port_icid(fdt32_to_cpu(*prop), + fman_icid_tbl, fman_icid_tbl_sz); + if (icid < 0) { + printf("WARNING unknown ICID for fman port %d\n", + *prop); + continue; + } + + fdt_set_iommu_prop(blob, noff, smmu_ph, (u32 *)&icid, 1); + + noff = fdt_node_offset_by_compatible(blob, noff, compat); + } +} + +void fdt_fixup_fman_icids(void *blob, int smmu_ph) +{ + static const char * const compats[] = { + "fsl,fman-v3-port-oh", + "fsl,fman-v3-port-rx", + "fsl,fman-v3-port-tx", + }; + int i; + + for (i = 0; i < ARRAY_SIZE(compats); i++) + fdt_fixup_fman_port_icid_by_compat(blob, smmu_ph, compats[i]); +} +#endif + +int fdt_get_smmu_phandle(void *blob) +{ + int noff, smmu_ph; + + noff = fdt_node_offset_by_compatible(blob, -1, "arm,mmu-500"); + if (noff < 0) { + printf("WARNING failed to get smmu node: %s\n", + fdt_strerror(noff)); + return noff; + } + + smmu_ph = fdt_get_phandle(blob, noff); + if (!smmu_ph) { + smmu_ph = fdt_create_phandle(blob, noff); + if (!smmu_ph) { + printf("WARNING failed to get smmu phandle\n"); + return -1; + } + } + + return smmu_ph; +} + +void fdt_fixup_icid(void *blob) +{ + int smmu_ph; + + smmu_ph = fdt_get_smmu_phandle(blob); + if (smmu_ph < 0) + return; + + fdt_fixup_icid_tbl(blob, smmu_ph, icid_tbl, icid_tbl_sz); + +#ifdef CONFIG_SYS_DPAA_FMAN + fdt_fixup_fman_icids(blob, smmu_ph); +#endif +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S new file mode 100644 index 0000000..6721a57 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
@@ -0,0 +1,583 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2014-2015 Freescale Semiconductor + * + * Extracted from armv8/start.S + */ + +#include <config.h> +#include <linux/linkage.h> +#include <asm/gic.h> +#include <asm/macro.h> +#include <asm/arch-fsl-layerscape/soc.h> +#ifdef CONFIG_MP +#include <asm/arch/mp.h> +#endif +#ifdef CONFIG_FSL_LSCH3 +#include <asm/arch-fsl-layerscape/immap_lsch3.h> +#endif +#include <asm/u-boot.h> + +/* Get GIC offset +* For LS1043a rev1.0, GIC base address align with 4k. +* For LS1043a rev1.1, if DCFG_GIC400_ALIGN[GIC_ADDR_BIT] +* is set, GIC base address align with 4K, or else align +* with 64k. +* output: +* x0: the base address of GICD +* x1: the base address of GICC +*/ +ENTRY(get_gic_offset) + ldr x0, =GICD_BASE +#ifdef CONFIG_GICV2 + ldr x1, =GICC_BASE +#endif +#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN + ldr x2, =DCFG_CCSR_SVR + ldr w2, [x2] + rev w2, w2 + lsr w3, w2, #16 + ldr w4, =SVR_DEV(SVR_LS1043A) + cmp w3, w4 + b.ne 1f + ands w2, w2, #0xff + cmp w2, #REV1_0 + b.eq 1f + ldr x2, =SCFG_GIC400_ALIGN + ldr w2, [x2] + rev w2, w2 + tbnz w2, #GIC_ADDR_BIT, 1f + ldr x0, =GICD_BASE_64K +#ifdef CONFIG_GICV2 + ldr x1, =GICC_BASE_64K +#endif +1: +#endif + ret +ENDPROC(get_gic_offset) + +ENTRY(smp_kick_all_cpus) + /* Kick secondary cpus up by SGI 0 interrupt */ +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) + mov x29, lr /* Save LR */ + bl get_gic_offset + bl gic_kick_secondary_cpus + mov lr, x29 /* Restore LR */ +#endif + ret +ENDPROC(smp_kick_all_cpus) + + +ENTRY(lowlevel_init) + mov x29, lr /* Save LR */ + + /* unmask SError and abort */ + msr daifclr, #4 + + /* Set HCR_EL2[AMO] so SError @EL2 is taken */ + mrs x0, hcr_el2 + orr x0, x0, #0x20 /* AMO */ + msr hcr_el2, x0 + isb + + switch_el x1, 1f, 100f, 100f /* skip if not in EL3 */ +1: + +#if defined (CONFIG_SYS_FSL_HAS_CCN504) + + /* Set Wuo bit for RN-I 20 */ +#ifdef CONFIG_ARCH_LS2080A + ldr x0, =CCI_AUX_CONTROL_BASE(20) + ldr x1, =0x00000010 + bl ccn504_set_aux + + /* + * Set forced-order mode in RNI-6, RNI-20 + * This is required for performance optimization on LS2088A + * LS2080A family does not support setting forced-order mode, + * so skip this operation for LS2080A family + */ + bl get_svr + lsr w0, w0, #16 + ldr w1, =SVR_DEV(SVR_LS2080A) + cmp w0, w1 + b.eq 1f + + ldr x0, =CCI_AUX_CONTROL_BASE(6) + ldr x1, =0x00000020 + bl ccn504_set_aux + ldr x0, =CCI_AUX_CONTROL_BASE(20) + ldr x1, =0x00000020 + bl ccn504_set_aux +1: +#endif + + /* Add fully-coherent masters to DVM domain */ + ldr x0, =CCI_MN_BASE + ldr x1, =CCI_MN_RNF_NODEID_LIST + ldr x2, =CCI_MN_DVM_DOMAIN_CTL_SET + bl ccn504_add_masters_to_dvm + + /* Set all RN-I ports to QoS of 15 */ + ldr x0, =CCI_S0_QOS_CONTROL_BASE(0) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S1_QOS_CONTROL_BASE(0) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S2_QOS_CONTROL_BASE(0) + ldr x1, =0x00FF000C + bl ccn504_set_qos + + ldr x0, =CCI_S0_QOS_CONTROL_BASE(2) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S1_QOS_CONTROL_BASE(2) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S2_QOS_CONTROL_BASE(2) + ldr x1, =0x00FF000C + bl ccn504_set_qos + + ldr x0, =CCI_S0_QOS_CONTROL_BASE(6) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S1_QOS_CONTROL_BASE(6) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S2_QOS_CONTROL_BASE(6) + ldr x1, =0x00FF000C + bl ccn504_set_qos + + ldr x0, =CCI_S0_QOS_CONTROL_BASE(12) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S1_QOS_CONTROL_BASE(12) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S2_QOS_CONTROL_BASE(12) + ldr x1, =0x00FF000C + bl ccn504_set_qos + + ldr x0, =CCI_S0_QOS_CONTROL_BASE(16) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S1_QOS_CONTROL_BASE(16) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S2_QOS_CONTROL_BASE(16) + ldr x1, =0x00FF000C + bl ccn504_set_qos + + ldr x0, =CCI_S0_QOS_CONTROL_BASE(20) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S1_QOS_CONTROL_BASE(20) + ldr x1, =0x00FF000C + bl ccn504_set_qos + ldr x0, =CCI_S2_QOS_CONTROL_BASE(20) + ldr x1, =0x00FF000C + bl ccn504_set_qos +#endif /* CONFIG_SYS_FSL_HAS_CCN504 */ + +#ifdef SMMU_BASE + /* Set the SMMU page size in the sACR register */ + ldr x1, =SMMU_BASE + ldr w0, [x1, #0x10] + orr w0, w0, #1 << 16 /* set sACR.pagesize to indicate 64K page */ + str w0, [x1, #0x10] +#endif + + /* Initialize GIC Secure Bank Status */ +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) + branch_if_slave x0, 1f + bl get_gic_offset + bl gic_init_secure +1: +#ifdef CONFIG_GICV3 + ldr x0, =GICR_BASE + bl gic_init_secure_percpu +#elif defined(CONFIG_GICV2) + bl get_gic_offset + bl gic_init_secure_percpu +#endif +#endif + +100: + branch_if_master x0, x1, 2f + +#if defined(CONFIG_MP) && defined(CONFIG_ARMV8_MULTIENTRY) + ldr x0, =secondary_boot_func + blr x0 +#endif + +2: + switch_el x1, 1f, 100f, 100f /* skip if not in EL3 */ +1: +#ifdef CONFIG_FSL_TZPC_BP147 + /* Set Non Secure access for all devices protected via TZPC */ + ldr x1, =TZPCDECPROT_0_SET_BASE /* Decode Protection-0 Set Reg */ + orr w0, w0, #1 << 3 /* DCFG_RESET is accessible from NS world */ + str w0, [x1] + + isb + dsb sy +#endif + +#ifdef CONFIG_FSL_TZASC_400 + /* + * LS2080 and its personalities does not support TZASC + * So skip TZASC related operations + */ + bl get_svr + lsr w0, w0, #16 + ldr w1, =SVR_DEV(SVR_LS2080A) + cmp w0, w1 + b.eq 1f + + /* Set TZASC so that: + * a. We use only Region0 whose global secure write/read is EN + * b. We use only Region0 whose NSAID write/read is EN + * + * NOTE: As per the CCSR map doc, TZASC 3 and TZASC 4 are just + * placeholders. + */ + +.macro tzasc_prog, xreg + + mov x12, TZASC1_BASE + mov x16, #0x10000 + mul x14, \xreg, x16 + add x14, x14,x12 + mov x1, #0x8 + add x1, x1, x14 + + ldr w0, [x1] /* Filter 0 Gate Keeper Register */ + orr w0, w0, #1 << 0 /* Set open_request for Filter 0 */ + str w0, [x1] + + mov x1, #0x110 + add x1, x1, x14 + + ldr w0, [x1] /* Region-0 Attributes Register */ + orr w0, w0, #1 << 31 /* Set Sec global write en, Bit[31] */ + orr w0, w0, #1 << 30 /* Set Sec global read en, Bit[30] */ + str w0, [x1] + + mov x1, #0x114 + add x1, x1, x14 + + ldr w0, [x1] /* Region-0 Access Register */ + mov w0, #0xFFFFFFFF /* Set nsaid_wr_en and nsaid_rd_en */ + str w0, [x1] +.endm + +#ifdef CONFIG_FSL_TZASC_1 + mov x13, #0 + tzasc_prog x13 + +#endif +#ifdef CONFIG_FSL_TZASC_2 + mov x13, #1 + tzasc_prog x13 + +#endif + isb + dsb sy +#endif +100: +1: +#ifdef CONFIG_ARCH_LS1046A + switch_el x1, 1f, 100f, 100f /* skip if not in EL3 */ +1: + /* Initialize the L2 RAM latency */ + mrs x1, S3_1_c11_c0_2 + mov x0, #0x1C7 + /* Clear L2 Tag RAM latency and L2 Data RAM latency */ + bic x1, x1, x0 + /* Set L2 data ram latency bits [2:0] */ + orr x1, x1, #0x2 + /* set L2 tag ram latency bits [8:6] */ + orr x1, x1, #0x80 + msr S3_1_c11_c0_2, x1 + isb +100: +#endif + +#if !defined(CONFIG_TFABOOT) && \ + (defined(CONFIG_FSL_LSCH2) && !defined(CONFIG_SPL_BUILD)) + bl fsl_ocram_init +#endif + + mov lr, x29 /* Restore LR */ + ret +ENDPROC(lowlevel_init) + +#if defined(CONFIG_FSL_LSCH2) && !defined(CONFIG_SPL_BUILD) +ENTRY(fsl_ocram_init) + mov x28, lr /* Save LR */ + bl fsl_clear_ocram + bl fsl_ocram_clear_ecc_err + mov lr, x28 /* Restore LR */ + ret +ENDPROC(fsl_ocram_init) + +ENTRY(fsl_clear_ocram) +/* Clear OCRAM */ + ldr x0, =CONFIG_SYS_FSL_OCRAM_BASE + ldr x1, =(CONFIG_SYS_FSL_OCRAM_BASE + CONFIG_SYS_FSL_OCRAM_SIZE) + mov x2, #0 +clear_loop: + str x2, [x0] + add x0, x0, #8 + cmp x0, x1 + b.lo clear_loop + ret +ENDPROC(fsl_clear_ocram) + +ENTRY(fsl_ocram_clear_ecc_err) + /* OCRAM1/2 ECC status bit */ + mov w1, #0x60 + ldr x0, =DCSR_DCFG_SBEESR2 + str w1, [x0] + ldr x0, =DCSR_DCFG_MBEESR2 + str w1, [x0] + ret +ENDPROC(fsl_ocram_init) +#endif + +#ifdef CONFIG_FSL_LSCH3 + .globl get_svr +get_svr: + ldr x1, =FSL_LSCH3_SVR + ldr w0, [x1] + ret +#endif + +#if defined(CONFIG_SYS_FSL_HAS_CCN504) || defined(CONFIG_SYS_FSL_HAS_CCN508) +hnf_pstate_poll: + /* x0 has the desired status, return 0 for success, 1 for timeout + * clobber x1, x2, x3, x4, x6, x7 + */ + mov x1, x0 + mov x7, #0 /* flag for timeout */ + mrs x3, cntpct_el0 /* read timer */ + add x3, x3, #1200 /* timeout after 100 microseconds */ + mov x0, #0x18 + movk x0, #0x420, lsl #16 /* HNF0_PSTATE_STATUS */ + mov w6, #8 /* HN-F node count */ +1: + ldr x2, [x0] + cmp x2, x1 /* check status */ + b.eq 2f + mrs x4, cntpct_el0 + cmp x4, x3 + b.ls 1b + mov x7, #1 /* timeout */ + b 3f +2: + add x0, x0, #0x10000 /* move to next node */ + subs w6, w6, #1 + cbnz w6, 1b +3: + mov x0, x7 + ret + +hnf_set_pstate: + /* x0 has the desired state, clobber x1, x2, x6 */ + mov x1, x0 + /* power state to SFONLY */ + mov w6, #8 /* HN-F node count */ + mov x0, #0x10 + movk x0, #0x420, lsl #16 /* HNF0_PSTATE_REQ */ +1: /* set pstate to sfonly */ + ldr x2, [x0] + and x2, x2, #0xfffffffffffffffc /* & HNFPSTAT_MASK */ + orr x2, x2, x1 + str x2, [x0] + add x0, x0, #0x10000 /* move to next node */ + subs w6, w6, #1 + cbnz w6, 1b + + ret + +ENTRY(__asm_flush_l3_dcache) + /* + * Return status in x0 + * success 0 + * timeout 1 for setting SFONLY, 2 for FAM, 3 for both + */ + mov x29, lr + mov x8, #0 + + dsb sy + mov x0, #0x1 /* HNFPSTAT_SFONLY */ + bl hnf_set_pstate + + mov x0, #0x4 /* SFONLY status */ + bl hnf_pstate_poll + cbz x0, 1f + mov x8, #1 /* timeout */ +1: + dsb sy + mov x0, #0x3 /* HNFPSTAT_FAM */ + bl hnf_set_pstate + + mov x0, #0xc /* FAM status */ + bl hnf_pstate_poll + cbz x0, 1f + add x8, x8, #0x2 +1: + mov x0, x8 + mov lr, x29 + ret +ENDPROC(__asm_flush_l3_dcache) +#endif /* CONFIG_SYS_FSL_HAS_CCN504 */ + +#ifdef CONFIG_MP + /* Keep literals not used by the secondary boot code outside it */ + .ltorg + + /* Using 64 bit alignment since the spin table is accessed as data */ + .align 4 + .global secondary_boot_code + /* Secondary Boot Code starts here */ +secondary_boot_code: + .global __spin_table +__spin_table: + .space CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE + + .align 2 +ENTRY(secondary_boot_func) + /* + * MPIDR_EL1 Fields: + * MPIDR[1:0] = AFF0_CPUID <- Core ID (0,1) + * MPIDR[7:2] = AFF0_RES + * MPIDR[15:8] = AFF1_CLUSTERID <- Cluster ID (0,1,2,3) + * MPIDR[23:16] = AFF2_CLUSTERID + * MPIDR[24] = MT + * MPIDR[29:25] = RES0 + * MPIDR[30] = U + * MPIDR[31] = ME + * MPIDR[39:32] = AFF3 + * + * Linear Processor ID (LPID) calculation from MPIDR_EL1: + * (We only use AFF0_CPUID and AFF1_CLUSTERID for now + * until AFF2_CLUSTERID and AFF3 have non-zero values) + * + * LPID = MPIDR[15:8] | MPIDR[1:0] + */ + mrs x0, mpidr_el1 + ubfm x1, x0, #8, #15 + ubfm x2, x0, #0, #1 + orr x10, x2, x1, lsl #2 /* x10 has LPID */ + ubfm x9, x0, #0, #15 /* x9 contains MPIDR[15:0] */ + /* + * offset of the spin table element for this core from start of spin + * table (each elem is padded to 64 bytes) + */ + lsl x1, x10, #6 + ldr x0, =__spin_table + /* physical address of this cpus spin table element */ + add x11, x1, x0 + + ldr x0, =__real_cntfrq + ldr x0, [x0] + msr cntfrq_el0, x0 /* set with real frequency */ + str x9, [x11, #16] /* LPID */ + mov x4, #1 + str x4, [x11, #8] /* STATUS */ + dsb sy +#if defined(CONFIG_GICV3) + gic_wait_for_interrupt_m x0 +#elif defined(CONFIG_GICV2) + bl get_gic_offset + mov x0, x1 + gic_wait_for_interrupt_m x0, w1 +#endif + +slave_cpu: + wfe + ldr x0, [x11] + cbz x0, slave_cpu +#ifndef CONFIG_ARMV8_SWITCH_TO_EL1 + mrs x1, sctlr_el2 +#else + mrs x1, sctlr_el1 +#endif + tbz x1, #25, cpu_is_le + rev x0, x0 /* BE to LE conversion */ +cpu_is_le: + ldr x5, [x11, #24] + cbz x5, 1f + +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + adr x4, secondary_switch_to_el1 + ldr x5, =ES_TO_AARCH64 +#else + ldr x4, [x11] + ldr x5, =ES_TO_AARCH32 +#endif + bl secondary_switch_to_el2 + +1: +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + adr x4, secondary_switch_to_el1 +#else + ldr x4, [x11] +#endif + ldr x5, =ES_TO_AARCH64 + bl secondary_switch_to_el2 + +ENDPROC(secondary_boot_func) + +ENTRY(secondary_switch_to_el2) + switch_el x6, 1f, 0f, 0f +0: ret +1: armv8_switch_to_el2_m x4, x5, x6 +ENDPROC(secondary_switch_to_el2) + +ENTRY(secondary_switch_to_el1) + mrs x0, mpidr_el1 + ubfm x1, x0, #8, #15 + ubfm x2, x0, #0, #1 + orr x10, x2, x1, lsl #2 /* x10 has LPID */ + + lsl x1, x10, #6 + ldr x0, =__spin_table + /* physical address of this cpus spin table element */ + add x11, x1, x0 + + ldr x4, [x11] + + ldr x5, [x11, #24] + cbz x5, 2f + + ldr x5, =ES_TO_AARCH32 + bl switch_to_el1 + +2: ldr x5, =ES_TO_AARCH64 + +switch_to_el1: + switch_el x6, 0f, 1f, 0f +0: ret +1: armv8_switch_to_el1_m x4, x5, x6 +ENDPROC(secondary_switch_to_el1) + + /* Ensure that the literals used by the secondary boot code are + * assembled within it (this is required so that we can protect + * this area with a single memreserve region + */ + .ltorg + + /* 64 bit alignment for elements accessed as data */ + .align 4 + .global __real_cntfrq +__real_cntfrq: + .quad COUNTER_FREQUENCY + .globl __secondary_boot_code_size + .type __secondary_boot_code_size, %object + /* Secondary Boot Code ends here */ +__secondary_boot_code_size: + .quad .-secondary_boot_code +#endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1012a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1012a_serdes.c new file mode 100644 index 0000000..8d7beca --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1012a_serdes.c
@@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch/immap_lsch2.h> + +struct serdes_config { + u32 protocol; + u8 lanes[SRDS_MAX_LANES]; +}; + +static struct serdes_config serdes1_cfg_tbl[] = { + {0x2208, {SGMII_2500_FM1_DTSEC1, SGMII_2500_FM1_DTSEC2, NONE, SATA1} }, + {0x0008, {NONE, NONE, NONE, SATA1} }, + {0x3508, {SGMII_FM1_DTSEC1, PCIE1, NONE, SATA1} }, + {0x3305, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, NONE, PCIE1} }, + {0x2205, {SGMII_2500_FM1_DTSEC1, SGMII_2500_FM1_DTSEC2, NONE, PCIE1} }, + {0x2305, {SGMII_2500_FM1_DTSEC1, SGMII_FM1_DTSEC2, NONE, PCIE1} }, + {0x9508, {TX_CLK, PCIE1, NONE, SATA1} }, + {0x3905, {SGMII_FM1_DTSEC1, TX_CLK, NONE, PCIE1} }, + {0x9305, {TX_CLK, SGMII_FM1_DTSEC2, NONE, PCIE1} }, + {} +}; + +static struct serdes_config *serdes_cfg_tbl[] = { + serdes1_cfg_tbl, +}; + +enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane) +{ + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == cfg) + return ptr->lanes[lane]; + ptr++; + } + + return 0; +} + +int is_serdes_prtcl_valid(int serdes, u32 prtcl) +{ + int i; + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == prtcl) + break; + ptr++; + } + + if (!ptr->protocol) + return 0; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (ptr->lanes[i] != NONE) + return 1; + } + + return 0; +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1043_ids.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1043_ids.c new file mode 100644 index 0000000..0e86494 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1043_ids.c
@@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 NXP + */ + +#include <common.h> +#include <asm/arch-fsl-layerscape/immap_lsch2.h> +#include <asm/arch-fsl-layerscape/fsl_icid.h> +#include <asm/arch-fsl-layerscape/fsl_portals.h> +#include <fsl_sec.h> + +#ifdef CONFIG_SYS_DPAA_QBMAN +struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = { + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), +}; +#endif + +struct icid_id_table icid_tbl[] = { +#ifdef CONFIG_SYS_DPAA_QBMAN + SET_QMAN_ICID(FSL_DPAA1_STREAM_ID_START), + SET_BMAN_ICID(FSL_DPAA1_STREAM_ID_START + 1), +#endif + + SET_SDHC_ICID(FSL_SDHC_STREAM_ID), + + SET_USB_ICID(1, "snps,dwc3", FSL_USB1_STREAM_ID), + SET_USB_ICID(2, "snps,dwc3", FSL_USB2_STREAM_ID), + SET_USB_ICID(3, "snps,dwc3", FSL_USB3_STREAM_ID), + + SET_SATA_ICID("fsl,ls1043a-ahci", FSL_SATA_STREAM_ID), + SET_QDMA_ICID("fsl,ls1043a-qdma", FSL_QDMA_STREAM_ID), + SET_EDMA_ICID(FSL_EDMA_STREAM_ID), + SET_ETR_ICID(FSL_ETR_STREAM_ID), + SET_DEBUG_ICID(FSL_DEBUG_STREAM_ID), + SET_QE_ICID(FSL_QE_STREAM_ID), +#ifdef CONFIG_FSL_CAAM + SET_SEC_QI_ICID(FSL_DPAA1_STREAM_ID_START + 2), + SET_SEC_JR_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 3), + SET_SEC_JR_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 4), + SET_SEC_JR_ICID_ENTRY(2, FSL_DPAA1_STREAM_ID_START + 5), + SET_SEC_JR_ICID_ENTRY(3, FSL_DPAA1_STREAM_ID_START + 6), + SET_SEC_RTIC_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 7), + SET_SEC_RTIC_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 8), + SET_SEC_RTIC_ICID_ENTRY(2, FSL_DPAA1_STREAM_ID_START + 9), + SET_SEC_RTIC_ICID_ENTRY(3, FSL_DPAA1_STREAM_ID_START + 10), + SET_SEC_DECO_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 11), + SET_SEC_DECO_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 12), +#endif +}; + +int icid_tbl_sz = ARRAY_SIZE(icid_tbl); + +#ifdef CONFIG_SYS_DPAA_FMAN +struct fman_icid_id_table fman_icid_tbl[] = { + /* port id, icid */ + SET_FMAN_ICID_ENTRY(0x02, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x03, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x04, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x05, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x06, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x07, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x08, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x09, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x0a, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x0b, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x0c, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x0d, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x28, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x29, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x2a, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x2b, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x2c, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x2d, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x10, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x11, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x30, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x31, FSL_DPAA1_STREAM_ID_END), +}; + +int fman_icid_tbl_sz = ARRAY_SIZE(fman_icid_tbl); +#endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_psci.S b/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_psci.S new file mode 100644 index 0000000..b4c7d6f --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_psci.S
@@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + * Author: Hongbo Zhang <hongbo.zhang@nxp.com> + * This file implements LS102X platform PSCI SYSTEM-SUSPEND function + */ + +#include <config.h> +#include <linux/linkage.h> +#include <asm/psci.h> + + .pushsection ._secure.text, "ax" + +.globl psci_version +psci_version: + ldr w0, =0x00010000 /* PSCI v1.0 */ + ret + + .popsection
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_serdes.c new file mode 100644 index 0000000..6c5e52e --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1043a_serdes.c
@@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2015 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch/immap_lsch2.h> + +struct serdes_config { + u32 protocol; + u8 lanes[SRDS_MAX_LANES]; +}; + +static struct serdes_config serdes1_cfg_tbl[] = { + /* SerDes 1 */ + {0x1555, {XFI_FM1_MAC9, PCIE1, PCIE2, PCIE3} }, + {0x2555, {SGMII_2500_FM1_DTSEC9, PCIE1, PCIE2, PCIE3} }, + {0x4555, {QSGMII_FM1_A, PCIE1, PCIE2, PCIE3} }, + {0x4558, {QSGMII_FM1_A, PCIE1, PCIE2, SATA1} }, + {0x1355, {XFI_FM1_MAC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3} }, + {0x2355, {SGMII_2500_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3} }, + {0x3335, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC5, + PCIE3} }, + {0x3355, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, PCIE3} }, + {0x3358, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, PCIE2, SATA1} }, + {0x3555, {SGMII_FM1_DTSEC9, PCIE1, PCIE2, PCIE3} }, + {0x3558, {SGMII_FM1_DTSEC9, PCIE1, PCIE2, SATA1} }, + {0x7000, {PCIE1, PCIE1, PCIE1, PCIE1} }, + {0x9998, {PCIE1, PCIE2, PCIE3, SATA1} }, + {0x6058, {PCIE1, PCIE1, PCIE2, SATA1} }, + {0x1455, {XFI_FM1_MAC9, QSGMII_FM1_A, PCIE2, PCIE3} }, + {0x2455, {SGMII_2500_FM1_DTSEC9, QSGMII_FM1_A, PCIE2, PCIE3} }, + {0x2255, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC2, PCIE2, PCIE3} }, + {0x3333, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC5, + SGMII_FM1_DTSEC6} }, + {} +}; + +static struct serdes_config *serdes_cfg_tbl[] = { + serdes1_cfg_tbl, +}; + +enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane) +{ + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == cfg) + return ptr->lanes[lane]; + ptr++; + } + + return 0; +} + +int is_serdes_prtcl_valid(int serdes, u32 prtcl) +{ + int i; + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == prtcl) + break; + ptr++; + } + + if (!ptr->protocol) + return 0; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (ptr->lanes[i] != NONE) + return 1; + } + + return 0; +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1046_ids.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1046_ids.c new file mode 100644 index 0000000..2da9ada --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1046_ids.c
@@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 NXP + */ + +#include <common.h> +#include <asm/arch-fsl-layerscape/immap_lsch2.h> +#include <asm/arch-fsl-layerscape/fsl_icid.h> +#include <asm/arch-fsl-layerscape/fsl_portals.h> + +#ifdef CONFIG_SYS_DPAA_QBMAN +struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = { + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), + SET_QP_INFO(FSL_DPAA1_STREAM_ID_END, 0), +}; +#endif + +struct icid_id_table icid_tbl[] = { +#ifdef CONFIG_SYS_DPAA_QBMAN + SET_QMAN_ICID(FSL_DPAA1_STREAM_ID_START), + SET_BMAN_ICID(FSL_DPAA1_STREAM_ID_START + 1), +#endif + + SET_SDHC_ICID(FSL_SDHC_STREAM_ID), + + SET_USB_ICID(1, "snps,dwc3", FSL_USB1_STREAM_ID), + SET_USB_ICID(2, "snps,dwc3", FSL_USB2_STREAM_ID), + SET_USB_ICID(3, "snps,dwc3", FSL_USB3_STREAM_ID), + + SET_SATA_ICID("fsl,ls1046a-ahci", FSL_SATA_STREAM_ID), + SET_QDMA_ICID("fsl,ls1046a-qdma", FSL_QDMA_STREAM_ID), + SET_EDMA_ICID(FSL_EDMA_STREAM_ID), + SET_ETR_ICID(FSL_ETR_STREAM_ID), + SET_DEBUG_ICID(FSL_DEBUG_STREAM_ID), +#ifdef CONFIG_FSL_CAAM + SET_SEC_QI_ICID(FSL_DPAA1_STREAM_ID_START + 2), + SET_SEC_JR_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 3), + SET_SEC_JR_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 4), + SET_SEC_JR_ICID_ENTRY(2, FSL_DPAA1_STREAM_ID_START + 5), + SET_SEC_JR_ICID_ENTRY(3, FSL_DPAA1_STREAM_ID_START + 6), + SET_SEC_RTIC_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 7), + SET_SEC_RTIC_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 8), + SET_SEC_RTIC_ICID_ENTRY(2, FSL_DPAA1_STREAM_ID_START + 9), + SET_SEC_RTIC_ICID_ENTRY(3, FSL_DPAA1_STREAM_ID_START + 10), + SET_SEC_DECO_ICID_ENTRY(0, FSL_DPAA1_STREAM_ID_START + 11), + SET_SEC_DECO_ICID_ENTRY(1, FSL_DPAA1_STREAM_ID_START + 12), + SET_SEC_DECO_ICID_ENTRY(2, FSL_DPAA1_STREAM_ID_START + 13), +#endif +}; + +int icid_tbl_sz = ARRAY_SIZE(icid_tbl); + +#ifdef CONFIG_SYS_DPAA_FMAN +struct fman_icid_id_table fman_icid_tbl[] = { + /* port id, icid */ + SET_FMAN_ICID_ENTRY(0x02, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x03, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x04, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x05, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x06, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x07, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x08, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x09, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x0a, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x0b, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x0c, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x0d, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x28, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x29, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x2a, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x2b, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x2c, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x2d, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x10, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x11, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x30, FSL_DPAA1_STREAM_ID_END), + SET_FMAN_ICID_ENTRY(0x31, FSL_DPAA1_STREAM_ID_END), +}; + +int fman_icid_tbl_sz = ARRAY_SIZE(fman_icid_tbl); +#endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1046a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1046a_serdes.c new file mode 100644 index 0000000..f8310f2 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1046a_serdes.c
@@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch/immap_lsch2.h> + +struct serdes_config { + u32 protocol; + u8 lanes[SRDS_MAX_LANES]; +}; + +static struct serdes_config serdes1_cfg_tbl[] = { + /* SerDes 1 */ + {0x3333, {SGMII_FM1_DTSEC9, SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC5, + SGMII_FM1_DTSEC6} }, + {0x1133, {XFI_FM1_MAC9, XFI_FM1_MAC10, SGMII_FM1_DTSEC5, + SGMII_FM1_DTSEC6} }, + {0x1333, {XFI_FM1_MAC9, SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC5, + SGMII_FM1_DTSEC6} }, + {0x2333, {SGMII_2500_FM1_DTSEC9, SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC5, + SGMII_FM1_DTSEC6} }, + {0x2233, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC10, + SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6} }, + {0x1040, {XFI_FM1_MAC9, NONE, QSGMII_FM1_A, NONE} }, + {0x2040, {SGMII_2500_FM1_DTSEC9, NONE, QSGMII_FM1_A, NONE} }, + {0x1163, {XFI_FM1_MAC9, XFI_FM1_MAC10, PCIE1, SGMII_FM1_DTSEC6} }, + {0x2263, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC10, PCIE1, + SGMII_FM1_DTSEC6} }, + {0x3363, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6, PCIE1, + SGMII_FM1_DTSEC6} }, + {0x2223, {SGMII_2500_FM1_DTSEC9, SGMII_2500_FM1_DTSEC10, + SGMII_2500_FM1_DTSEC5, SGMII_FM1_DTSEC6} }, + {} +}; + +static struct serdes_config serdes2_cfg_tbl[] = { + /* SerDes 2 */ + {0x8888, {PCIE1, PCIE1, PCIE1, PCIE1} }, + {0x5559, {PCIE1, PCIE2, PCIE3, SATA1} }, + {0x5577, {PCIE1, PCIE2, PCIE3, PCIE3} }, + {0x5506, {PCIE1, PCIE2, NONE, PCIE3} }, + {0x0506, {NONE, PCIE2, NONE, PCIE3} }, + {0x0559, {NONE, PCIE2, PCIE3, SATA1} }, + {0x5A59, {PCIE1, SGMII_FM1_DTSEC2, PCIE3, SATA1} }, + {0x5A06, {PCIE1, SGMII_FM1_DTSEC2, NONE, PCIE3} }, + {} +}; + +static struct serdes_config *serdes_cfg_tbl[] = { + serdes1_cfg_tbl, + serdes2_cfg_tbl, +}; + +enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane) +{ + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == cfg) + return ptr->lanes[lane]; + ptr++; + } + + return 0; +} + +int is_serdes_prtcl_valid(int serdes, u32 prtcl) +{ + int i; + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == prtcl) + break; + ptr++; + } + + if (!ptr->protocol) + return 0; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (ptr->lanes[i] != NONE) + return 1; + } + + return 0; +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c new file mode 100644 index 0000000..8e8b45a --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1088a_serdes.c
@@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017 NXP + */ + +#include <common.h> +#include <asm/arch/fsl_serdes.h> + +struct serdes_config { + u8 ip_protocol; + u8 lanes[SRDS_MAX_LANES]; + u8 rcw_lanes[SRDS_MAX_LANES]; +}; + +static struct serdes_config serdes1_cfg_tbl[] = { + /* SerDes 1 */ + {0x12, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 3, 3 } }, + {0x15, {SGMII3, SGMII7, XFI1, XFI2 }, {3, 3, 1, 1 } }, + {0x16, {SGMII3, SGMII7, SGMII1, XFI2 }, {3, 3, 3, 1 } }, + {0x17, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 3, 2 } }, + {0x18, {SGMII3, SGMII7, SGMII1, SGMII2 }, {3, 3, 2, 2 } }, + {0x19, {SGMII3, QSGMII_B, XFI1, XFI2}, {3, 4, 1, 1 } }, + {0x1A, {SGMII3, QSGMII_B, SGMII1, XFI2 }, {3, 4, 3, 1 } }, + {0x1B, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 3, 2 } }, + {0x1C, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 2, 2 } }, + {0x1D, {QSGMII_A, QSGMII_B, XFI1, XFI2 }, {4, 4, 1, 1 } }, + {0x1E, {QSGMII_A, QSGMII_B, SGMII1, XFI2 }, {4, 4, 3, 1 } }, + {0x1F, {QSGMII_A, QSGMII_B, SGMII1, SGMII2 }, {4, 4, 3, 2 } }, + {0x20, {QSGMII_A, QSGMII_B, SGMII1, SGMII2 }, {4, 4, 2, 2 } }, + {0x35, {SGMII3, QSGMII_B, SGMII1, SGMII2 }, {3, 4, 3, 3 } }, + {0x36, {QSGMII_A, QSGMII_B, SGMII1, SGMII2 }, {4, 4, 3, 3 } }, + {0x3A, {SGMII3, PCIE1, SGMII1, SGMII2 }, {3, 5, 3, 3 } }, + {} +}; +static struct serdes_config serdes2_cfg_tbl[] = { + /* SerDes 2 */ + {0x0C, {PCIE1, PCIE1, PCIE1, PCIE1 }, {8, 8, 8, 8 } }, + {0x0D, {PCIE1, PCIE2, PCIE3, SATA1 }, {5, 5, 5, 9 } }, + {0x0E, {PCIE1, PCIE1, PCIE2, SATA1 }, {7, 7, 6, 9 } }, + {0x13, {PCIE1, PCIE1, PCIE3, PCIE3 }, {7, 7, 7, 7 } }, + {0x14, {PCIE1, PCIE2, PCIE3, PCIE3 }, {5, 5, 7, 7 } }, + {0x3C, {NONE, PCIE2, NONE, PCIE3 }, {0, 5, 0, 6 } }, + {} +}; + +static struct serdes_config *serdes_cfg_tbl[] = { + serdes1_cfg_tbl, + serdes2_cfg_tbl, +}; + +int serdes_get_number(int serdes, int cfg) +{ + struct serdes_config *ptr; + int i, j, index, lnk; + int is_found, max_lane = SRDS_MAX_LANES; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + + while (ptr->ip_protocol) { + is_found = 1; + for (i = 0, j = max_lane - 1; i < max_lane; i++, j--) { + lnk = cfg & (0xf << 4 * i); + lnk = lnk >> (4 * i); + + index = (serdes == FSL_SRDS_1) ? j : i; + + if (ptr->rcw_lanes[index] == lnk && is_found) + is_found = 1; + else + is_found = 0; + } + + if (is_found) + return ptr->ip_protocol; + ptr++; + } + + return 0; +} + +enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane) +{ + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->ip_protocol) { + if (ptr->ip_protocol == cfg) + return ptr->lanes[lane]; + ptr++; + } + + return 0; +} + +int is_serdes_prtcl_valid(int serdes, u32 prtcl) +{ + int i; + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->ip_protocol) { + if (ptr->ip_protocol == prtcl) + break; + ptr++; + } + + if (!ptr->ip_protocol) + return 0; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (ptr->lanes[i] != NONE) + return 1; + } + + return 0; +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls2080a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls2080a_serdes.c new file mode 100644 index 0000000..7997422 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/ls2080a_serdes.c
@@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014-2015 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/arch/fsl_serdes.h> + +struct serdes_config { + u8 protocol; + u8 lanes[SRDS_MAX_LANES]; +}; + +static struct serdes_config serdes1_cfg_tbl[] = { + /* SerDes 1 */ + {0x03, {PCIE2, PCIE2, PCIE2, PCIE2, PCIE1, PCIE1, PCIE1, PCIE1 } }, + {0x05, {PCIE2, PCIE2, PCIE2, PCIE2, SGMII4, SGMII3, SGMII2, SGMII1 } }, + {0x07, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2, + SGMII1 } }, + {0x09, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2, + SGMII1 } }, + {0x0A, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2, + SGMII1 } }, + {0x0C, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2, + SGMII1 } }, + {0x0E, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, SGMII2, + SGMII1 } }, + {0x26, {SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, SGMII3, XFI2, XFI1 } }, + {0x28, {SGMII8, SGMII7, SGMII6, SGMII5, XFI4, XFI3, XFI2, XFI1 } }, + {0x2A, {XFI8, XFI7, XFI6, XFI5, XFI4, XFI3, XFI2, XFI1 } }, + {0x2B, {SGMII8, SGMII7, SGMII6, SGMII5, XAUI1, XAUI1, XAUI1, XAUI1 } }, + {0x32, {XAUI2, XAUI2, XAUI2, XAUI2, XAUI1, XAUI1, XAUI1, XAUI1 } }, + {0x33, {PCIE2, PCIE2, PCIE2, PCIE2, QSGMII_D, QSGMII_C, QSGMII_B, + QSGMII_A} }, + {0x35, {QSGMII_D, QSGMII_C, QSGMII_B, PCIE2, XFI4, XFI3, XFI2, XFI1 } }, + {0x39, {SGMII8, SGMII7, SGMII6, PCIE2, SGMII4, SGMII3, SGMII2, + PCIE1 } }, + {0x3B, {XFI8, XFI7, XFI6, PCIE2, XFI4, XFI3, XFI2, PCIE1 } }, + {0x4B, {PCIE2, PCIE2, PCIE2, PCIE2, XFI4, XFI3, XFI2, XFI1 } }, + {0x4C, {XFI8, XFI7, XFI6, XFI5, PCIE1, PCIE1, PCIE1, PCIE1 } }, + {0x4D, {SGMII8, SGMII7, PCIE2, PCIE2, SGMII4, SGMII3, PCIE1, PCIE1 } }, + {} +}; +static struct serdes_config serdes2_cfg_tbl[] = { + /* SerDes 2 */ + {0x07, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15, + SGMII16 } }, + {0x09, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15, + SGMII16 } }, + {0x0A, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15, + SGMII16 } }, + {0x0C, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15, + SGMII16 } }, + {0x0E, {SGMII9, SGMII10, SGMII11, SGMII12, SGMII13, SGMII14, SGMII15, + SGMII16 } }, + {0x3D, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } }, + {0x3E, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } }, + {0x3F, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } }, + {0x40, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } }, + {0x41, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } }, + {0x42, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } }, + {0x43, {PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE, SATA1, SATA2 } }, + {0x44, {PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE, SATA1, SATA2 } }, + {0x45, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, PCIE4, + PCIE4 } }, + {0x47, {PCIE3, SGMII10, SGMII11, SGMII12, PCIE4, SGMII14, SGMII15, + SGMII16 } }, + {0x49, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, SATA1, + SATA2 } }, + {0x4A, {SGMII9, SGMII10, SGMII11, SGMII12, PCIE4, PCIE4, SATA1, + SATA2 } }, + {0x51, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } }, + {0x57, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SGMII15, SGMII16 } }, + {} +}; + +static struct serdes_config *serdes_cfg_tbl[] = { + serdes1_cfg_tbl, + serdes2_cfg_tbl, +}; + +enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane) +{ + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == cfg) + return ptr->lanes[lane]; + ptr++; + } + + return 0; +} + +int is_serdes_prtcl_valid(int serdes, u32 prtcl) +{ + int i; + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == prtcl) + break; + ptr++; + } + + if (!ptr->protocol) + return 0; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (ptr->lanes[i] != NONE) + return 1; + } + + return 0; +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c new file mode 100644 index 0000000..a04a370 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/lx2160a_serdes.c
@@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 NXP + */ + +#include <common.h> +#include <asm/arch/fsl_serdes.h> + +struct serdes_config { + u8 protocol; + u8 lanes[SRDS_MAX_LANES]; +}; + +static struct serdes_config serdes1_cfg_tbl[] = { + /* SerDes 1 */ + {0x01, {PCIE2, PCIE2, PCIE2, PCIE2, PCIE1, PCIE1, PCIE1, PCIE1 } }, + {0x02, {PCIE2, PCIE2, PCIE2, PCIE2, SGMII6, SGMII5, SGMII4, SGMII3 } }, + {0x03, {PCIE2, PCIE2, PCIE2, PCIE2, XFI6, XFI5, XFI4, + XFI3 } }, + {0x04, {SGMII10, SGMII9, SGMII8, SGMII7, SGMII6, SGMII5, SGMII4, + SGMII3 } }, + {0x05, {XFI10, XFI9, XFI8, XFI7, PCIE1, PCIE1, PCIE1, + PCIE1 } }, + {0x06, {SGMII10, SGMII9, SGMII8, SGMII7, SGMII6, SGMII5, XFI4, + XFI3 } }, + {0x07, {SGMII10, SGMII9, SGMII8, SGMII7, XFI6, XFI5, XFI4, + XFI3 } }, + {0x08, {XFI10, XFI9, XFI8, XFI7, XFI6, XFI5, XFI4, XFI3 } }, + {0x09, {SGMII10, SGMII9, SGMII8, PCIE2, SGMII6, SGMII5, SGMII4, + PCIE1 } }, + {0x0A, {XFI10, XFI9, XFI8, PCIE2, XFI6, XFI5, XFI4, PCIE1 } }, + {0x0B, {SGMII10, SGMII9, PCIE2, PCIE2, SGMII6, SGMII5, PCIE1, PCIE1 } }, + {0x0C, {SGMII10, SGMII9, PCIE2, PCIE2, PCIE1, PCIE1, PCIE1, PCIE1 } }, + {0x0D, {_100GE2, _100GE2, _100GE2, _100GE2, _100GE1, _100GE1, _100GE1, + _100GE1 } }, + {0x0E, {PCIE2, PCIE2, PCIE2, PCIE2, _100GE1, _100GE1, _100GE1, + _100GE1 } }, + {0x0F, {PCIE2, PCIE2, PCIE2, PCIE2, _50GE2, _50GE2, _50GE1, _50GE1 } }, + {0x10, {PCIE2, PCIE2, PCIE2, PCIE2, _25GE6, _25GE5, _50GE1, _50GE1 } }, + {0x11, {PCIE2, PCIE2, PCIE2, PCIE2, _25GE6, _25GE5, _25GE4, _25GE3 } }, + {0x12, {XFI10, XFI9, XFI8, XFI7, _25GE6, _25GE5, XFI4, + XFI3 } }, + {0x13, {_40GE2, _40GE2, _40GE2, _40GE2, _25GE6, _25GE5, XFI4, XFI3 } }, + {0x14, {_40GE2, _40GE2, _40GE2, _40GE2, _40GE1, _40GE1, _40GE1, + _40GE1 } }, + {0x15, {_25GE10, _25GE9, PCIE2, PCIE2, _25GE6, _25GE5, _25GE4, + _25GE3 } }, + {0x16, {XFI10, XFI9, PCIE2, PCIE2, XFI6, XFI5, XFI4, XFI3 } }, + {} +}; + +static struct serdes_config serdes2_cfg_tbl[] = { + /* SerDes 2 */ + {0x01, {PCIE3, PCIE3, SATA1, SATA2, PCIE4, PCIE4, PCIE4, PCIE4 } }, + {0x02, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3 } }, + {0x03, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4 } }, + {0x04, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2 } }, + {0x05, {PCIE3, PCIE3, PCIE3, PCIE3, SATA3, SATA4, SATA1, SATA2 } }, + {0x06, {PCIE3, PCIE3, PCIE3, PCIE3, SGMII15, SGMII16, XFI13, + XFI14 } }, + {0x07, {PCIE3, SGMII12, SGMII17, SGMII18, PCIE4, SGMII16, XFI13, + XFI14 } }, + {0x08, {NONE, NONE, SATA1, SATA2, SATA3, SATA4, XFI13, XFI14 } }, + {0x09, {SGMII11, SGMII12, SGMII17, SGMII18, SGMII15, SGMII16, SGMII13, + SGMII14} }, + {0x0A, {SGMII11, SGMII12, SGMII17, SGMII18, PCIE4, PCIE4, PCIE4, + PCIE4 } }, + {0x0B, {PCIE3, SGMII12, SGMII17, SGMII18, PCIE4, SGMII16, SGMII13, + SGMII14 } }, + {0x0C, {SGMII11, SGMII12, SGMII17, SGMII18, PCIE4, PCIE4, SATA1, + SATA2 } }, + {0x0D, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SGMII13, SGMII14 } }, + {0x0E, {PCIE3, PCIE3, SGMII17, SGMII18, PCIE4, PCIE4, SGMII13, + SGMII14 } }, + {} +}; + +static struct serdes_config serdes3_cfg_tbl[] = { + /* SerDes 3 */ + {0x02, {PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5, PCIE5 } }, + {0x03, {PCIE5, PCIE5, PCIE5, PCIE5, PCIE6, PCIE6, PCIE6, PCIE6 } }, + {} +}; + +static struct serdes_config *serdes_cfg_tbl[] = { + serdes1_cfg_tbl, + serdes2_cfg_tbl, + serdes3_cfg_tbl, +}; + +enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane) +{ + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == cfg) + return ptr->lanes[lane]; + ptr++; + } + + return 0; +} + +int is_serdes_prtcl_valid(int serdes, u32 prtcl) +{ + int i; + struct serdes_config *ptr; + + if (serdes >= ARRAY_SIZE(serdes_cfg_tbl)) + return 0; + + ptr = serdes_cfg_tbl[serdes]; + while (ptr->protocol) { + if (ptr->protocol == prtcl) + break; + ptr++; + } + + if (!ptr->protocol) + return 0; + + for (i = 0; i < SRDS_MAX_LANES; i++) { + if (ptr->lanes[i] != NONE) + return 1; + } + + return 0; +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/mp.c b/arch/arm/cpu/armv8/fsl-layerscape/mp.c new file mode 100644 index 0000000..7627fd1 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/mp.c
@@ -0,0 +1,285 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014-2015 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/arch/mp.h> +#include <asm/arch/soc.h> +#include "cpu.h" +#include <asm/arch-fsl-layerscape/soc.h> + +DECLARE_GLOBAL_DATA_PTR; + +void *get_spin_tbl_addr(void) +{ + return &__spin_table; +} + +phys_addr_t determine_mp_bootpg(void) +{ + return (phys_addr_t)&secondary_boot_code; +} + +void update_os_arch_secondary_cores(uint8_t os_arch) +{ + u64 *table = get_spin_tbl_addr(); + int i; + + for (i = 1; i < CONFIG_MAX_CPUS; i++) { + if (os_arch == IH_ARCH_DEFAULT) + table[i * WORDS_PER_SPIN_TABLE_ENTRY + + SPIN_TABLE_ELEM_ARCH_COMP_IDX] = OS_ARCH_SAME; + else + table[i * WORDS_PER_SPIN_TABLE_ENTRY + + SPIN_TABLE_ELEM_ARCH_COMP_IDX] = OS_ARCH_DIFF; + } +} + +#ifdef CONFIG_FSL_LSCH3 +void wake_secondary_core_n(int cluster, int core, int cluster_cores) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + struct ccsr_reset __iomem *rst = (void *)(CONFIG_SYS_FSL_RST_ADDR); + u32 mpidr = 0; + + mpidr = ((cluster << 8) | core); + /* + * mpidr_el1 register value of core which needs to be released + * is written to scratchrw[6] register + */ + gur_out32(&gur->scratchrw[6], mpidr); + asm volatile("dsb st" : : : "memory"); + rst->brrl |= 1 << ((cluster * cluster_cores) + core); + asm volatile("dsb st" : : : "memory"); + /* + * scratchrw[6] register value is polled + * when the value becomes zero, this means that this core is up + * and running, next core can be released now + */ + while (gur_in32(&gur->scratchrw[6]) != 0) + ; +} +#endif + +int fsl_layerscape_wake_seconday_cores(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); +#ifdef CONFIG_FSL_LSCH3 + struct ccsr_reset __iomem *rst = (void *)(CONFIG_SYS_FSL_RST_ADDR); + u32 svr, ver, cluster, type; + int j = 0, cluster_cores = 0; +#elif defined(CONFIG_FSL_LSCH2) + struct ccsr_scfg __iomem *scfg = (void *)(CONFIG_SYS_FSL_SCFG_ADDR); +#endif + u32 cores, cpu_up_mask = 1; + int i, timeout = 10; + u64 *table = get_spin_tbl_addr(); + +#ifdef COUNTER_FREQUENCY_REAL + /* update for secondary cores */ + __real_cntfrq = COUNTER_FREQUENCY_REAL; + flush_dcache_range((unsigned long)&__real_cntfrq, + (unsigned long)&__real_cntfrq + 8); +#endif + + cores = cpu_mask(); + /* Clear spin table so that secondary processors + * observe the correct value after waking up from wfe. + */ + memset(table, 0, CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE); + flush_dcache_range((unsigned long)table, + (unsigned long)table + + (CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE)); + + printf("Waking secondary cores to start from %lx\n", gd->relocaddr); + +#ifdef CONFIG_FSL_LSCH3 + gur_out32(&gur->bootlocptrh, (u32)(gd->relocaddr >> 32)); + gur_out32(&gur->bootlocptrl, (u32)gd->relocaddr); + + svr = gur_in32(&gur->svr); + ver = SVR_SOC_VER(svr); + if (ver == SVR_LS2080A || ver == SVR_LS2085A) { + gur_out32(&gur->scratchrw[6], 1); + asm volatile("dsb st" : : : "memory"); + rst->brrl = cores; + asm volatile("dsb st" : : : "memory"); + } else { + /* + * Release the cores out of reset one-at-a-time to avoid + * power spikes + */ + i = 0; + cluster = in_le32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + type = initiator_type(cluster, j); + if (type && + TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM) + cluster_cores++; + } + + do { + cluster = in_le32(&gur->tp_cluster[i].lower); + for (j = 0; j < TP_INIT_PER_CLUSTER; j++) { + type = initiator_type(cluster, j); + if (type && + TP_ITYP_TYPE(type) == TP_ITYP_TYPE_ARM) + wake_secondary_core_n(i, j, + cluster_cores); + } + i++; + } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC); + } +#elif defined(CONFIG_FSL_LSCH2) + scfg_out32(&scfg->scratchrw[0], (u32)(gd->relocaddr >> 32)); + scfg_out32(&scfg->scratchrw[1], (u32)gd->relocaddr); + asm volatile("dsb st" : : : "memory"); + gur_out32(&gur->brrl, cores); + asm volatile("dsb st" : : : "memory"); + + /* Bootup online cores */ + scfg_out32(&scfg->corebcr, cores); +#endif + /* This is needed as a precautionary measure. + * If some code before this has accidentally released the secondary + * cores then the pre-bootloader code will trap them in a "wfe" unless + * the scratchrw[6] is set. In this case we need a sev here to get these + * cores moving again. + */ + asm volatile("sev"); + + while (timeout--) { + flush_dcache_range((unsigned long)table, (unsigned long)table + + CONFIG_MAX_CPUS * 64); + for (i = 1; i < CONFIG_MAX_CPUS; i++) { + if (table[i * WORDS_PER_SPIN_TABLE_ENTRY + + SPIN_TABLE_ELEM_STATUS_IDX]) + cpu_up_mask |= 1 << i; + } + if (hweight32(cpu_up_mask) == hweight32(cores)) + break; + udelay(10); + } + if (timeout <= 0) { + printf("Not all cores (0x%x) are up (0x%x)\n", + cores, cpu_up_mask); + return 1; + } + printf("All (%d) cores are up.\n", hweight32(cores)); + + return 0; +} + +int is_core_valid(unsigned int core) +{ + return !!((1 << core) & cpu_mask()); +} + +static int is_pos_valid(unsigned int pos) +{ + return !!((1 << pos) & cpu_pos_mask()); +} + +int is_core_online(u64 cpu_id) +{ + u64 *table; + int pos = id_to_core(cpu_id); + table = (u64 *)get_spin_tbl_addr() + pos * WORDS_PER_SPIN_TABLE_ENTRY; + return table[SPIN_TABLE_ELEM_STATUS_IDX] == 1; +} + +int cpu_reset(u32 nr) +{ + puts("Feature is not implemented.\n"); + + return 0; +} + +int cpu_disable(u32 nr) +{ + puts("Feature is not implemented.\n"); + + return 0; +} + +static int core_to_pos(int nr) +{ + u32 cores = cpu_pos_mask(); + int i, count = 0; + + if (nr == 0) { + return 0; + } else if (nr >= hweight32(cores)) { + puts("Not a valid core number.\n"); + return -1; + } + + for (i = 1; i < 32; i++) { + if (is_pos_valid(i)) { + count++; + if (count == nr) + break; + } + } + + if (count != nr) + return -1; + + return i; +} + +int cpu_status(u32 nr) +{ + u64 *table; + int pos; + + if (nr == 0) { + table = (u64 *)get_spin_tbl_addr(); + printf("table base @ 0x%p\n", table); + } else { + pos = core_to_pos(nr); + if (pos < 0) + return -1; + table = (u64 *)get_spin_tbl_addr() + pos * + WORDS_PER_SPIN_TABLE_ENTRY; + printf("table @ 0x%p\n", table); + printf(" addr - 0x%016llx\n", + table[SPIN_TABLE_ELEM_ENTRY_ADDR_IDX]); + printf(" status - 0x%016llx\n", + table[SPIN_TABLE_ELEM_STATUS_IDX]); + printf(" lpid - 0x%016llx\n", + table[SPIN_TABLE_ELEM_LPID_IDX]); + } + + return 0; +} + +int cpu_release(u32 nr, int argc, char * const argv[]) +{ + u64 boot_addr; + u64 *table = (u64 *)get_spin_tbl_addr(); + int pos; + + pos = core_to_pos(nr); + if (pos <= 0) + return -1; + + table += pos * WORDS_PER_SPIN_TABLE_ENTRY; + boot_addr = simple_strtoull(argv[0], NULL, 16); + table[SPIN_TABLE_ELEM_ENTRY_ADDR_IDX] = boot_addr; + flush_dcache_range((unsigned long)table, + (unsigned long)table + SPIN_TABLE_ELEM_SIZE); + asm volatile("dsb st"); + smp_kick_all_cpus(); /* only those with entry addr set will run */ + /* + * When the first release command runs, all cores are set to go. Those + * without a valid entry address will be trapped by "wfe". "sev" kicks + * them off to check the address again. When set, they continue to run. + */ + asm volatile("sev"); + + return 0; +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c new file mode 100644 index 0000000..d391f93 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
@@ -0,0 +1,281 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2016 NXP Semiconductor, Inc. + */ +#include <common.h> +#include <malloc.h> +#include <config.h> +#include <errno.h> +#include <asm/system.h> +#include <asm/types.h> +#include <asm/arch/soc.h> +#ifdef CONFIG_FSL_LSCH3 +#include <asm/arch/immap_lsch3.h> +#elif defined(CONFIG_FSL_LSCH2) +#include <asm/arch/immap_lsch2.h> +#endif +#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT +#include <asm/armv8/sec_firmware.h> +#endif +#ifdef CONFIG_CHAIN_OF_TRUST +#include <fsl_validate.h> +#endif + +#ifdef CONFIG_SYS_LS_PPA_FW_IN_NAND +#include <nand.h> +#elif defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) +#include <mmc.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +int ppa_init(void) +{ + unsigned int el = current_el(); + void *ppa_fit_addr; + u32 *boot_loc_ptr_l, *boot_loc_ptr_h; + u32 *loadable_l, *loadable_h; + int ret; + +#ifdef CONFIG_CHAIN_OF_TRUST + uintptr_t ppa_esbc_hdr = 0; + uintptr_t ppa_img_addr = 0; +#if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \ + defined(CONFIG_SYS_LS_PPA_FW_IN_NAND) + void *ppa_hdr_ddr; +#endif +#endif + + /* Skip if running at lower exception level */ + if (el < 3) { + debug("Skipping PPA init, running at EL%d\n", el); + return 0; + } + +#ifdef CONFIG_SYS_LS_PPA_FW_IN_XIP + ppa_fit_addr = (void *)CONFIG_SYS_LS_PPA_FW_ADDR; + debug("%s: PPA image load from XIP\n", __func__); +#ifdef CONFIG_CHAIN_OF_TRUST + ppa_esbc_hdr = CONFIG_SYS_LS_PPA_ESBC_ADDR; +#endif +#else /* !CONFIG_SYS_LS_PPA_FW_IN_XIP */ + size_t fw_length, fdt_header_len = sizeof(struct fdt_header); + + /* Copy PPA image from MMC/SD/NAND to allocated memory */ +#ifdef CONFIG_SYS_LS_PPA_FW_IN_MMC + struct mmc *mmc; + int dev = CONFIG_SYS_MMC_ENV_DEV; + struct fdt_header *fitp; + u32 cnt; + u32 blk; + + debug("%s: PPA image load from eMMC/SD\n", __func__); + + ret = mmc_initialize(gd->bd); + if (ret) { + printf("%s: mmc_initialize() failed\n", __func__); + return ret; + } + mmc = find_mmc_device(dev); + if (!mmc) { + printf("PPA: MMC cannot find device for PPA firmware\n"); + return -ENODEV; + } + + ret = mmc_init(mmc); + if (ret) { + printf("%s: mmc_init() failed\n", __func__); + return ret; + } + + fitp = malloc(roundup(fdt_header_len, 512)); + if (!fitp) { + printf("PPA: malloc failed for FIT header(size 0x%zx)\n", + roundup(fdt_header_len, 512)); + return -ENOMEM; + } + + blk = CONFIG_SYS_LS_PPA_FW_ADDR / 512; + cnt = DIV_ROUND_UP(fdt_header_len, 512); + debug("%s: MMC read PPA FIT header: dev # %u, block # %u, count %u\n", + __func__, dev, blk, cnt); + ret = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, fitp); + if (ret != cnt) { + free(fitp); + printf("MMC/SD read of PPA FIT header at offset 0x%x failed\n", + CONFIG_SYS_LS_PPA_FW_ADDR); + return -EIO; + } + + ret = fdt_check_header(fitp); + if (ret) { + free(fitp); + printf("%s: fdt_check_header() failed\n", __func__); + return ret; + } + +#ifdef CONFIG_CHAIN_OF_TRUST + ppa_hdr_ddr = malloc(CONFIG_LS_PPA_ESBC_HDR_SIZE); + if (!ppa_hdr_ddr) { + printf("PPA: malloc failed for PPA header\n"); + return -ENOMEM; + } + + blk = CONFIG_SYS_LS_PPA_ESBC_ADDR >> 9; + cnt = DIV_ROUND_UP(CONFIG_LS_PPA_ESBC_HDR_SIZE, 512); + ret = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, ppa_hdr_ddr); + if (ret != cnt) { + free(ppa_hdr_ddr); + printf("MMC/SD read of PPA header failed\n"); + return -EIO; + } + debug("Read PPA header to 0x%p\n", ppa_hdr_ddr); + + ppa_esbc_hdr = (uintptr_t)ppa_hdr_ddr; +#endif + + fw_length = fdt_totalsize(fitp); + free(fitp); + + fw_length = roundup(fw_length, 512); + ppa_fit_addr = malloc(fw_length); + if (!ppa_fit_addr) { + printf("PPA: malloc failed for PPA image(size 0x%zx)\n", + fw_length); + return -ENOMEM; + } + + blk = CONFIG_SYS_LS_PPA_FW_ADDR / 512; + cnt = DIV_ROUND_UP(fw_length, 512); + debug("%s: MMC read PPA FIT image: dev # %u, block # %u, count %u\n", + __func__, dev, blk, cnt); + ret = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, ppa_fit_addr); + if (ret != cnt) { + free(ppa_fit_addr); + printf("MMC/SD read of PPA FIT header at offset 0x%x failed\n", + CONFIG_SYS_LS_PPA_FW_ADDR); + return -EIO; + } + +#elif defined(CONFIG_SYS_LS_PPA_FW_IN_NAND) + struct fdt_header fit; + + debug("%s: PPA image load from NAND\n", __func__); + + nand_init(); + ret = nand_read(get_nand_dev_by_index(0), + (loff_t)CONFIG_SYS_LS_PPA_FW_ADDR, + &fdt_header_len, (u_char *)&fit); + if (ret == -EUCLEAN) { + printf("NAND read of PPA FIT header at offset 0x%x failed\n", + CONFIG_SYS_LS_PPA_FW_ADDR); + return -EIO; + } + + ret = fdt_check_header(&fit); + if (ret) { + printf("%s: fdt_check_header() failed\n", __func__); + return ret; + } + +#ifdef CONFIG_CHAIN_OF_TRUST + ppa_hdr_ddr = malloc(CONFIG_LS_PPA_ESBC_HDR_SIZE); + if (!ppa_hdr_ddr) { + printf("PPA: malloc failed for PPA header\n"); + return -ENOMEM; + } + + fw_length = CONFIG_LS_PPA_ESBC_HDR_SIZE; + + ret = nand_read(get_nand_dev_by_index(0), + (loff_t)CONFIG_SYS_LS_PPA_ESBC_ADDR, + &fw_length, (u_char *)ppa_hdr_ddr); + if (ret == -EUCLEAN) { + free(ppa_hdr_ddr); + printf("NAND read of PPA firmware at offset 0x%x failed\n", + CONFIG_SYS_LS_PPA_FW_ADDR); + return -EIO; + } + debug("Read PPA header to 0x%p\n", ppa_hdr_ddr); + + ppa_esbc_hdr = (uintptr_t)ppa_hdr_ddr; +#endif + + fw_length = fdt_totalsize(&fit); + + ppa_fit_addr = malloc(fw_length); + if (!ppa_fit_addr) { + printf("PPA: malloc failed for PPA image(size 0x%zx)\n", + fw_length); + return -ENOMEM; + } + + ret = nand_read(get_nand_dev_by_index(0), + (loff_t)CONFIG_SYS_LS_PPA_FW_ADDR, + &fw_length, (u_char *)ppa_fit_addr); + if (ret == -EUCLEAN) { + free(ppa_fit_addr); + printf("NAND read of PPA firmware at offset 0x%x failed\n", + CONFIG_SYS_LS_PPA_FW_ADDR); + return -EIO; + } +#else +#error "No CONFIG_SYS_LS_PPA_FW_IN_xxx defined" +#endif + +#endif + +#ifdef CONFIG_CHAIN_OF_TRUST + ppa_img_addr = (uintptr_t)ppa_fit_addr; + if (fsl_check_boot_mode_secure() != 0) { + /* + * In case of failure in validation, fsl_secboot_validate + * would not return back in case of Production environment + * with ITS=1. In Development environment (ITS=0 and + * SB_EN=1), the function may return back in case of + * non-fatal failures. + */ + ret = fsl_secboot_validate(ppa_esbc_hdr, + PPA_KEY_HASH, + &ppa_img_addr); + if (ret != 0) + printf("SEC firmware(s) validation failed\n"); + else + printf("SEC firmware(s) validation Successful\n"); + } +#if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \ + defined(CONFIG_SYS_LS_PPA_FW_IN_NAND) + free(ppa_hdr_ddr); +#endif +#endif + +#ifdef CONFIG_FSL_LSCH3 + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + boot_loc_ptr_l = &gur->bootlocptrl; + boot_loc_ptr_h = &gur->bootlocptrh; + + /* Assign addresses to loadable ptrs */ + loadable_l = &gur->scratchrw[4]; + loadable_h = &gur->scratchrw[5]; +#elif defined(CONFIG_FSL_LSCH2) + struct ccsr_scfg __iomem *scfg = (void *)(CONFIG_SYS_FSL_SCFG_ADDR); + boot_loc_ptr_l = &scfg->scratchrw[1]; + boot_loc_ptr_h = &scfg->scratchrw[0]; + + /* Assign addresses to loadable ptrs */ + loadable_l = &scfg->scratchrw[2]; + loadable_h = &scfg->scratchrw[3]; +#endif + + debug("fsl-ppa: boot_loc_ptr_l = 0x%p, boot_loc_ptr_h =0x%p\n", + boot_loc_ptr_l, boot_loc_ptr_h); + ret = sec_firmware_init(ppa_fit_addr, boot_loc_ptr_l, boot_loc_ptr_h, + loadable_l, loadable_h); + +#if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \ + defined(CONFIG_SYS_LS_PPA_FW_IN_NAND) + free(ppa_fit_addr); +#endif + + return ret; +}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c new file mode 100644 index 0000000..0092a22 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
@@ -0,0 +1,822 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014-2015 Freescale Semiconductor + */ + +#include <common.h> +#include <fsl_immap.h> +#include <fsl_ifc.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch/soc.h> +#include <asm/io.h> +#include <asm/global_data.h> +#include <asm/arch-fsl-layerscape/config.h> +#include <asm/arch-fsl-layerscape/ns_access.h> +#include <asm/arch-fsl-layerscape/fsl_icid.h> +#ifdef CONFIG_LAYERSCAPE_NS_ACCESS +#include <fsl_csu.h> +#endif +#ifdef CONFIG_SYS_FSL_DDR +#include <fsl_ddr_sdram.h> +#include <fsl_ddr.h> +#endif +#ifdef CONFIG_CHAIN_OF_TRUST +#include <fsl_validate.h> +#endif +#include <fsl_immap.h> +#ifdef CONFIG_TFABOOT +#include <environment.h> +DECLARE_GLOBAL_DATA_PTR; +#endif + +bool soc_has_dp_ddr(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 svr = gur_in32(&gur->svr); + + /* LS2085A, LS2088A, LS2048A has DP_DDR */ + if ((SVR_SOC_VER(svr) == SVR_LS2085A) || + (SVR_SOC_VER(svr) == SVR_LS2088A) || + (SVR_SOC_VER(svr) == SVR_LS2048A)) + return true; + + return false; +} + +bool soc_has_aiop(void) +{ + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 svr = gur_in32(&gur->svr); + + /* LS2085A has AIOP */ + if (SVR_SOC_VER(svr) == SVR_LS2085A) + return true; + + return false; +} + +static inline void set_usb_txvreftune(u32 __iomem *scfg, u32 offset) +{ + scfg_clrsetbits32(scfg + offset / 4, + 0xF << 6, + SCFG_USB_TXVREFTUNE << 6); +} + +static void erratum_a009008(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009008 + u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE; + +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) + set_usb_txvreftune(scfg, SCFG_USB3PRM1CR_USB1); +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) + set_usb_txvreftune(scfg, SCFG_USB3PRM1CR_USB2); + set_usb_txvreftune(scfg, SCFG_USB3PRM1CR_USB3); +#endif +#elif defined(CONFIG_ARCH_LS2080A) + set_usb_txvreftune(scfg, SCFG_USB3PRM1CR); +#endif +#endif /* CONFIG_SYS_FSL_ERRATUM_A009008 */ +} + +static inline void set_usb_sqrxtune(u32 __iomem *scfg, u32 offset) +{ + scfg_clrbits32(scfg + offset / 4, + SCFG_USB_SQRXTUNE_MASK << 23); +} + +static void erratum_a009798(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009798 + u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE; + +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) + set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR_USB1); +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) + set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR_USB2); + set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR_USB3); +#endif +#elif defined(CONFIG_ARCH_LS2080A) + set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR); +#endif +#endif /* CONFIG_SYS_FSL_ERRATUM_A009798 */ +} + +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) +static inline void set_usb_pcstxswingfull(u32 __iomem *scfg, u32 offset) +{ + scfg_clrsetbits32(scfg + offset / 4, + 0x7F << 9, + SCFG_USB_PCSTXSWINGFULL << 9); +} +#endif + +static void erratum_a008997(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008997 +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) + u32 __iomem *scfg = (u32 __iomem *)SCFG_BASE; + + set_usb_pcstxswingfull(scfg, SCFG_USB3PRM2CR_USB1); +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) + set_usb_pcstxswingfull(scfg, SCFG_USB3PRM2CR_USB2); + set_usb_pcstxswingfull(scfg, SCFG_USB3PRM2CR_USB3); +#endif +#endif +#endif /* CONFIG_SYS_FSL_ERRATUM_A008997 */ +} + +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) + +#define PROGRAM_USB_PHY_RX_OVRD_IN_HI(phy) \ + out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_1); \ + out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_2); \ + out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_3); \ + out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_4) + +#elif defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A) + +#define PROGRAM_USB_PHY_RX_OVRD_IN_HI(phy) \ + out_le16((phy) + DCSR_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_1); \ + out_le16((phy) + DCSR_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_2); \ + out_le16((phy) + DCSR_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_3); \ + out_le16((phy) + DCSR_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_4) + +#endif + +static void erratum_a009007(void) +{ +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) || \ + defined(CONFIG_ARCH_LS1012A) + void __iomem *usb_phy = (void __iomem *)SCFG_USB_PHY1; + + PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy); +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) + usb_phy = (void __iomem *)SCFG_USB_PHY2; + PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy); + + usb_phy = (void __iomem *)SCFG_USB_PHY3; + PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy); +#endif +#elif defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A) + void __iomem *dcsr = (void __iomem *)DCSR_BASE; + + PROGRAM_USB_PHY_RX_OVRD_IN_HI(dcsr + DCSR_USB_PHY1); + PROGRAM_USB_PHY_RX_OVRD_IN_HI(dcsr + DCSR_USB_PHY2); +#endif /* CONFIG_SYS_FSL_ERRATUM_A009007 */ +} + +#if defined(CONFIG_FSL_LSCH3) +/* + * This erratum requires setting a value to eddrtqcr1 to + * optimal the DDR performance. + */ +static void erratum_a008336(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008336 + u32 *eddrtqcr1; + +#ifdef CONFIG_SYS_FSL_DCSR_DDR_ADDR + eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR_ADDR + 0x800; + if (fsl_ddr_get_version(0) == 0x50200) + out_le32(eddrtqcr1, 0x63b30002); +#endif +#ifdef CONFIG_SYS_FSL_DCSR_DDR2_ADDR + eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR2_ADDR + 0x800; + if (fsl_ddr_get_version(0) == 0x50200) + out_le32(eddrtqcr1, 0x63b30002); +#endif +#endif +} + +/* + * This erratum requires a register write before being Memory + * controller 3 being enabled. + */ +static void erratum_a008514(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008514 + u32 *eddrtqcr1; + +#ifdef CONFIG_SYS_FSL_DCSR_DDR3_ADDR + eddrtqcr1 = (void *)CONFIG_SYS_FSL_DCSR_DDR3_ADDR + 0x800; + out_le32(eddrtqcr1, 0x63b20002); +#endif +#endif +} +#ifdef CONFIG_SYS_FSL_ERRATUM_A009635 +#define PLATFORM_CYCLE_ENV_VAR "a009635_interval_val" + +static unsigned long get_internval_val_mhz(void) +{ + char *interval = env_get(PLATFORM_CYCLE_ENV_VAR); + /* + * interval is the number of platform cycles(MHz) between + * wake up events generated by EPU. + */ + ulong interval_mhz = get_bus_freq(0) / (1000 * 1000); + + if (interval) + interval_mhz = simple_strtoul(interval, NULL, 10); + + return interval_mhz; +} + +void erratum_a009635(void) +{ + u32 val; + unsigned long interval_mhz = get_internval_val_mhz(); + + if (!interval_mhz) + return; + + val = in_le32(DCSR_CGACRE5); + writel(val | 0x00000200, DCSR_CGACRE5); + + val = in_le32(EPU_EPCMPR5); + writel(interval_mhz, EPU_EPCMPR5); + val = in_le32(EPU_EPCCR5); + writel(val | 0x82820000, EPU_EPCCR5); + val = in_le32(EPU_EPSMCR5); + writel(val | 0x002f0000, EPU_EPSMCR5); + val = in_le32(EPU_EPECR5); + writel(val | 0x20000000, EPU_EPECR5); + val = in_le32(EPU_EPGCR); + writel(val | 0x80000000, EPU_EPGCR); +} +#endif /* CONFIG_SYS_FSL_ERRATUM_A009635 */ + +static void erratum_rcw_src(void) +{ +#if defined(CONFIG_SPL) && defined(CONFIG_NAND_BOOT) + u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE; + u32 __iomem *dcfg_dcsr = (u32 __iomem *)DCFG_DCSR_BASE; + u32 val; + + val = in_le32(dcfg_ccsr + DCFG_PORSR1 / 4); + val &= ~DCFG_PORSR1_RCW_SRC; + val |= DCFG_PORSR1_RCW_SRC_NOR; + out_le32(dcfg_dcsr + DCFG_DCSR_PORCR1 / 4, val); +#endif +} + +#define I2C_DEBUG_REG 0x6 +#define I2C_GLITCH_EN 0x8 +/* + * This erratum requires setting glitch_en bit to enable + * digital glitch filter to improve clock stability. + */ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009203 +static void erratum_a009203(void) +{ +#ifdef CONFIG_SYS_I2C + u8 __iomem *ptr; +#ifdef I2C1_BASE_ADDR + ptr = (u8 __iomem *)(I2C1_BASE_ADDR + I2C_DEBUG_REG); + + writeb(I2C_GLITCH_EN, ptr); +#endif +#ifdef I2C2_BASE_ADDR + ptr = (u8 __iomem *)(I2C2_BASE_ADDR + I2C_DEBUG_REG); + + writeb(I2C_GLITCH_EN, ptr); +#endif +#ifdef I2C3_BASE_ADDR + ptr = (u8 __iomem *)(I2C3_BASE_ADDR + I2C_DEBUG_REG); + + writeb(I2C_GLITCH_EN, ptr); +#endif +#ifdef I2C4_BASE_ADDR + ptr = (u8 __iomem *)(I2C4_BASE_ADDR + I2C_DEBUG_REG); + + writeb(I2C_GLITCH_EN, ptr); +#endif +#endif +} +#endif + +void bypass_smmu(void) +{ + u32 val; + val = (in_le32(SMMU_SCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK); + out_le32(SMMU_SCR0, val); + val = (in_le32(SMMU_NSCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK); + out_le32(SMMU_NSCR0, val); +} +void fsl_lsch3_early_init_f(void) +{ + erratum_rcw_src(); +#ifdef CONFIG_FSL_IFC + init_early_memctl_regs(); /* tighten IFC timing */ +#endif +#ifdef CONFIG_SYS_FSL_ERRATUM_A009203 + erratum_a009203(); +#endif + erratum_a008514(); + erratum_a008336(); + erratum_a009008(); + erratum_a009798(); + erratum_a008997(); + erratum_a009007(); +#ifdef CONFIG_CHAIN_OF_TRUST + /* In case of Secure Boot, the IBR configures the SMMU + * to allow only Secure transactions. + * SMMU must be reset in bypass mode. + * Set the ClientPD bit and Clear the USFCFG Bit + */ + if (fsl_check_boot_mode_secure() == 1) + bypass_smmu(); +#endif +} + +/* Get VDD in the unit mV from voltage ID */ +int get_core_volt_from_fuse(void) +{ + struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + int vdd; + u32 fusesr; + u8 vid; + + /* get the voltage ID from fuse status register */ + fusesr = in_le32(&gur->dcfg_fusesr); + debug("%s: fusesr = 0x%x\n", __func__, fusesr); + vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT) & + FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK; + if ((vid == 0) || (vid == FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK)) { + vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT) & + FSL_CHASSIS3_DCFG_FUSESR_VID_MASK; + } + debug("%s: VID = 0x%x\n", __func__, vid); + switch (vid) { + case 0x00: /* VID isn't supported */ + vdd = -EINVAL; + debug("%s: The VID feature is not supported\n", __func__); + break; + case 0x08: /* 0.9V silicon */ + vdd = 900; + break; + case 0x10: /* 1.0V silicon */ + vdd = 1000; + break; + default: /* Other core voltage */ + vdd = -EINVAL; + debug("%s: The VID(%x) isn't supported\n", __func__, vid); + break; + } + debug("%s: The required minimum volt of CORE is %dmV\n", __func__, vdd); + + return vdd; +} + +#elif defined(CONFIG_FSL_LSCH2) + +static void erratum_a009929(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009929 + struct ccsr_gur *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + u32 __iomem *dcsr_cop_ccp = (void *)CONFIG_SYS_DCSR_COP_CCP_ADDR; + u32 rstrqmr1 = gur_in32(&gur->rstrqmr1); + + rstrqmr1 |= 0x00000400; + gur_out32(&gur->rstrqmr1, rstrqmr1); + writel(0x01000000, dcsr_cop_ccp); +#endif +} + +/* + * This erratum requires setting a value to eddrtqcr1 to optimal + * the DDR performance. The eddrtqcr1 register is in SCFG space + * of LS1043A and the offset is 0x157_020c. + */ +#if defined(CONFIG_SYS_FSL_ERRATUM_A009660) \ + && defined(CONFIG_SYS_FSL_ERRATUM_A008514) +#error A009660 and A008514 can not be both enabled. +#endif + +static void erratum_a009660(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A009660 + u32 *eddrtqcr1 = (void *)CONFIG_SYS_FSL_SCFG_ADDR + 0x20c; + out_be32(eddrtqcr1, 0x63b20042); +#endif +} + +static void erratum_a008850_early(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008850 + /* part 1 of 2 */ + struct ccsr_cci400 __iomem *cci = (void *)(CONFIG_SYS_IMMR + + CONFIG_SYS_CCI400_OFFSET); + struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + + /* Skip if running at lower exception level */ + if (current_el() < 3) + return; + + /* disables propagation of barrier transactions to DDRC from CCI400 */ + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER); + + /* disable the re-ordering in DDRC */ + ddr_out32(&ddr->eor, DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS); +#endif +} + +void erratum_a008850_post(void) +{ +#ifdef CONFIG_SYS_FSL_ERRATUM_A008850 + /* part 2 of 2 */ + struct ccsr_cci400 __iomem *cci = (void *)(CONFIG_SYS_IMMR + + CONFIG_SYS_CCI400_OFFSET); + struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + u32 tmp; + + /* Skip if running at lower exception level */ + if (current_el() < 3) + return; + + /* enable propagation of barrier transactions to DDRC from CCI400 */ + out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER); + + /* enable the re-ordering in DDRC */ + tmp = ddr_in32(&ddr->eor); + tmp &= ~(DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS); + ddr_out32(&ddr->eor, tmp); +#endif +} + +#ifdef CONFIG_SYS_FSL_ERRATUM_A010315 +void erratum_a010315(void) +{ + int i; + + for (i = PCIE1; i <= PCIE4; i++) + if (!is_serdes_configured(i)) { + debug("PCIe%d: disabled all R/W permission!\n", i); + set_pcie_ns_access(i, 0); + } +} +#endif + +static void erratum_a010539(void) +{ +#if defined(CONFIG_SYS_FSL_ERRATUM_A010539) && defined(CONFIG_QSPI_BOOT) + struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + u32 porsr1; + + porsr1 = in_be32(&gur->porsr1); + porsr1 &= ~FSL_CHASSIS2_CCSR_PORSR1_RCW_MASK; + out_be32((void *)(CONFIG_SYS_DCSR_DCFG_ADDR + DCFG_DCSR_PORCR1), + porsr1); + out_be32((void *)(CONFIG_SYS_FSL_SCFG_ADDR + 0x1a8), 0xffffffff); +#endif +} + +/* Get VDD in the unit mV from voltage ID */ +int get_core_volt_from_fuse(void) +{ + struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + int vdd; + u32 fusesr; + u8 vid; + + fusesr = in_be32(&gur->dcfg_fusesr); + debug("%s: fusesr = 0x%x\n", __func__, fusesr); + vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_ALTVID_SHIFT) & + FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK; + if ((vid == 0) || (vid == FSL_CHASSIS2_DCFG_FUSESR_ALTVID_MASK)) { + vid = (fusesr >> FSL_CHASSIS2_DCFG_FUSESR_VID_SHIFT) & + FSL_CHASSIS2_DCFG_FUSESR_VID_MASK; + } + debug("%s: VID = 0x%x\n", __func__, vid); + switch (vid) { + case 0x00: /* VID isn't supported */ + vdd = -EINVAL; + debug("%s: The VID feature is not supported\n", __func__); + break; + case 0x08: /* 0.9V silicon */ + vdd = 900; + break; + case 0x10: /* 1.0V silicon */ + vdd = 1000; + break; + default: /* Other core voltage */ + vdd = -EINVAL; + printf("%s: The VID(%x) isn't supported\n", __func__, vid); + break; + } + debug("%s: The required minimum volt of CORE is %dmV\n", __func__, vdd); + + return vdd; +} + +__weak int board_switch_core_volt(u32 vdd) +{ + return 0; +} + +static int setup_core_volt(u32 vdd) +{ + return board_setup_core_volt(vdd); +} + +#ifdef CONFIG_SYS_FSL_DDR +static void ddr_enable_0v9_volt(bool en) +{ + struct ccsr_ddr __iomem *ddr = (void *)CONFIG_SYS_FSL_DDR_ADDR; + u32 tmp; + + tmp = ddr_in32(&ddr->ddr_cdr1); + + if (en) + tmp |= DDR_CDR1_V0PT9_EN; + else + tmp &= ~DDR_CDR1_V0PT9_EN; + + ddr_out32(&ddr->ddr_cdr1, tmp); +} +#endif + +int setup_chip_volt(void) +{ + int vdd; + + vdd = get_core_volt_from_fuse(); + /* Nothing to do for silicons doesn't support VID */ + if (vdd < 0) + return vdd; + + if (setup_core_volt(vdd)) + printf("%s: Switch core VDD to %dmV failed\n", __func__, vdd); +#ifdef CONFIG_SYS_HAS_SERDES + if (setup_serdes_volt(vdd)) + printf("%s: Switch SVDD to %dmV failed\n", __func__, vdd); +#endif + +#ifdef CONFIG_SYS_FSL_DDR + if (vdd == 900) + ddr_enable_0v9_volt(true); +#endif + + return 0; +} + +#ifdef CONFIG_FSL_PFE +void init_pfe_scfg_dcfg_regs(void) +{ + struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR; + u32 ecccr2; + + out_be32(&scfg->pfeasbcr, + in_be32(&scfg->pfeasbcr) | SCFG_PFEASBCR_AWCACHE0); + out_be32(&scfg->pfebsbcr, + in_be32(&scfg->pfebsbcr) | SCFG_PFEASBCR_AWCACHE0); + + /* CCI-400 QoS settings for PFE */ + out_be32(&scfg->wr_qos1, (unsigned int)(SCFG_WR_QOS1_PFE1_QOS + | SCFG_WR_QOS1_PFE2_QOS)); + out_be32(&scfg->rd_qos1, (unsigned int)(SCFG_RD_QOS1_PFE1_QOS + | SCFG_RD_QOS1_PFE2_QOS)); + + ecccr2 = in_be32(CONFIG_SYS_DCSR_DCFG_ADDR + DCFG_DCSR_ECCCR2); + out_be32((void *)CONFIG_SYS_DCSR_DCFG_ADDR + DCFG_DCSR_ECCCR2, + ecccr2 | (unsigned int)DISABLE_PFE_ECC); +} +#endif + +void fsl_lsch2_early_init_f(void) +{ + struct ccsr_cci400 *cci = (struct ccsr_cci400 *)(CONFIG_SYS_IMMR + + CONFIG_SYS_CCI400_OFFSET); + struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR; + +#ifdef CONFIG_LAYERSCAPE_NS_ACCESS + enable_layerscape_ns_access(); +#endif + +#ifdef CONFIG_FSL_IFC + init_early_memctl_regs(); /* tighten IFC timing */ +#endif + +#if defined(CONFIG_FSL_QSPI) && !defined(CONFIG_QSPI_BOOT) + out_be32(&scfg->qspi_cfg, SCFG_QSPI_CLKSEL); +#endif + /* Make SEC reads and writes snoopable */ + setbits_be32(&scfg->snpcnfgcr, SCFG_SNPCNFGCR_SECRDSNP | + SCFG_SNPCNFGCR_SECWRSNP | + SCFG_SNPCNFGCR_SATARDSNP | + SCFG_SNPCNFGCR_SATAWRSNP); + + /* + * Enable snoop requests and DVM message requests for + * Slave insterface S4 (A53 core cluster) + */ + if (current_el() == 3) { + out_le32(&cci->slave[4].snoop_ctrl, + CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN); + } + + /* + * Program Central Security Unit (CSU) to grant access + * permission for USB 2.0 controller + */ +#if defined(CONFIG_ARCH_LS1012A) && defined(CONFIG_USB_EHCI_FSL) + if (current_el() == 3) + set_devices_ns_access(CSU_CSLX_USB_2, CSU_ALL_RW); +#endif + /* Erratum */ + erratum_a008850_early(); /* part 1 of 2 */ + erratum_a009929(); + erratum_a009660(); + erratum_a010539(); + erratum_a009008(); + erratum_a009798(); + erratum_a008997(); + erratum_a009007(); + +#if defined(CONFIG_ARCH_LS1043A) || defined(CONFIG_ARCH_LS1046A) + set_icids(); +#endif +} +#endif + +#ifdef CONFIG_QSPI_AHB_INIT +/* Enable 4bytes address support and fast read */ +int qspi_ahb_init(void) +{ + u32 *qspi_lut, lut_key, *qspi_key; + + qspi_key = (void *)SYS_FSL_QSPI_ADDR + 0x300; + qspi_lut = (void *)SYS_FSL_QSPI_ADDR + 0x310; + + lut_key = in_be32(qspi_key); + + if (lut_key == 0x5af05af0) { + /* That means the register is BE */ + out_be32(qspi_key, 0x5af05af0); + /* Unlock the lut table */ + out_be32(qspi_key + 1, 0x00000002); + out_be32(qspi_lut, 0x0820040c); + out_be32(qspi_lut + 1, 0x1c080c08); + out_be32(qspi_lut + 2, 0x00002400); + /* Lock the lut table */ + out_be32(qspi_key, 0x5af05af0); + out_be32(qspi_key + 1, 0x00000001); + } else { + /* That means the register is LE */ + out_le32(qspi_key, 0x5af05af0); + /* Unlock the lut table */ + out_le32(qspi_key + 1, 0x00000002); + out_le32(qspi_lut, 0x0820040c); + out_le32(qspi_lut + 1, 0x1c080c08); + out_le32(qspi_lut + 2, 0x00002400); + /* Lock the lut table */ + out_le32(qspi_key, 0x5af05af0); + out_le32(qspi_key + 1, 0x00000001); + } + + return 0; +} +#endif + +#ifdef CONFIG_TFABOOT +#define MAX_BOOTCMD_SIZE 256 + +int fsl_setenv_bootcmd(void) +{ + int ret; + enum boot_src src = get_boot_src(); + char bootcmd_str[MAX_BOOTCMD_SIZE]; + + switch (src) { +#ifdef IFC_NOR_BOOTCOMMAND + case BOOT_SOURCE_IFC_NOR: + sprintf(bootcmd_str, IFC_NOR_BOOTCOMMAND); + break; +#endif +#ifdef QSPI_NOR_BOOTCOMMAND + case BOOT_SOURCE_QSPI_NOR: + sprintf(bootcmd_str, QSPI_NOR_BOOTCOMMAND); + break; +#endif +#ifdef XSPI_NOR_BOOTCOMMAND + case BOOT_SOURCE_XSPI_NOR: + sprintf(bootcmd_str, XSPI_NOR_BOOTCOMMAND); + break; +#endif +#ifdef IFC_NAND_BOOTCOMMAND + case BOOT_SOURCE_IFC_NAND: + sprintf(bootcmd_str, IFC_NAND_BOOTCOMMAND); + break; +#endif +#ifdef QSPI_NAND_BOOTCOMMAND + case BOOT_SOURCE_QSPI_NAND: + sprintf(bootcmd_str, QSPI_NAND_BOOTCOMMAND); + break; +#endif +#ifdef XSPI_NAND_BOOTCOMMAND + case BOOT_SOURCE_XSPI_NAND: + sprintf(bootcmd_str, XSPI_NAND_BOOTCOMMAND); + break; +#endif +#ifdef SD_BOOTCOMMAND + case BOOT_SOURCE_SD_MMC: + sprintf(bootcmd_str, SD_BOOTCOMMAND); + break; +#endif +#ifdef SD2_BOOTCOMMAND + case BOOT_SOURCE_SD_MMC2: + sprintf(bootcmd_str, SD2_BOOTCOMMAND); + break; +#endif + default: +#ifdef QSPI_NOR_BOOTCOMMAND + sprintf(bootcmd_str, QSPI_NOR_BOOTCOMMAND); +#endif + break; + } + + ret = env_set("bootcmd", bootcmd_str); + if (ret) { + printf("Failed to set bootcmd: ret = %d\n", ret); + return ret; + } + return 0; +} + +int fsl_setenv_mcinitcmd(void) +{ + int ret = 0; + enum boot_src src = get_boot_src(); + + switch (src) { +#ifdef IFC_MC_INIT_CMD + case BOOT_SOURCE_IFC_NAND: + case BOOT_SOURCE_IFC_NOR: + ret = env_set("mcinitcmd", IFC_MC_INIT_CMD); + break; +#endif +#ifdef QSPI_MC_INIT_CMD + case BOOT_SOURCE_QSPI_NAND: + case BOOT_SOURCE_QSPI_NOR: + ret = env_set("mcinitcmd", QSPI_MC_INIT_CMD); + break; +#endif +#ifdef XSPI_MC_INIT_CMD + case BOOT_SOURCE_XSPI_NAND: + case BOOT_SOURCE_XSPI_NOR: + ret = env_set("mcinitcmd", XSPI_MC_INIT_CMD); + break; +#endif +#ifdef SD_MC_INIT_CMD + case BOOT_SOURCE_SD_MMC: + ret = env_set("mcinitcmd", SD_MC_INIT_CMD); + break; +#endif +#ifdef SD2_MC_INIT_CMD + case BOOT_SOURCE_SD_MMC2: + ret = env_set("mcinitcmd", SD2_MC_INIT_CMD); + break; +#endif + default: +#ifdef QSPI_MC_INIT_CMD + ret = env_set("mcinitcmd", QSPI_MC_INIT_CMD); +#endif + break; + } + + if (ret) { + printf("Failed to set mcinitcmd: ret = %d\n", ret); + return ret; + } + return 0; +} +#endif + +#ifdef CONFIG_BOARD_LATE_INIT +int board_late_init(void) +{ +#ifdef CONFIG_CHAIN_OF_TRUST + fsl_setenv_chain_of_trust(); +#endif +#ifdef CONFIG_TFABOOT + /* + * check if gd->env_addr is default_environment; then setenv bootcmd + * and mcinitcmd. + */ + if (gd->env_addr + gd->reloc_off == (ulong)&default_environment[0]) { + fsl_setenv_bootcmd(); + fsl_setenv_mcinitcmd(); + } +#endif +#ifdef CONFIG_QSPI_AHB_INIT + qspi_ahb_init(); +#endif + + return 0; +} +#endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/spl.c b/arch/arm/cpu/armv8/fsl-layerscape/spl.c new file mode 100644 index 0000000..3e53084 --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/spl.c
@@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2014-2015 Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <spl.h> +#include <asm/io.h> +#include <fsl_ifc.h> +#include <i2c.h> +#include <fsl_csu.h> +#include <asm/arch/fdt.h> +#include <asm/arch/ppa.h> +#include <asm/arch/soc.h> + +DECLARE_GLOBAL_DATA_PTR; + +u32 spl_boot_device(void) +{ +#ifdef CONFIG_SPL_MMC_SUPPORT + return BOOT_DEVICE_MMC1; +#endif +#ifdef CONFIG_SPL_NAND_SUPPORT + return BOOT_DEVICE_NAND; +#endif +#ifdef CONFIG_QSPI_BOOT + return BOOT_DEVICE_NOR; +#endif + return 0; +} + +#ifdef CONFIG_SPL_BUILD + +void spl_board_init(void) +{ +#if defined(CONFIG_SECURE_BOOT) && defined(CONFIG_FSL_LSCH2) + /* + * In case of Secure Boot, the IBR configures the SMMU + * to allow only Secure transactions. + * SMMU must be reset in bypass mode. + * Set the ClientPD bit and Clear the USFCFG Bit + */ + u32 val; + val = (in_le32(SMMU_SCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK); + out_le32(SMMU_SCR0, val); + val = (in_le32(SMMU_NSCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK); + out_le32(SMMU_NSCR0, val); +#endif +#ifdef CONFIG_LAYERSCAPE_NS_ACCESS + enable_layerscape_ns_access(); +#endif +#ifdef CONFIG_SPL_FSL_LS_PPA + ppa_init(); +#endif +} + +void board_init_f(ulong dummy) +{ + icache_enable(); + /* Clear global data */ + memset((void *)gd, 0, sizeof(gd_t)); + board_early_init_f(); + timer_init(); +#ifdef CONFIG_ARCH_LS2080A + env_init(); +#endif + get_clocks(); + + preloader_console_init(); + spl_set_bd(); + +#ifdef CONFIG_SPL_I2C_SUPPORT + i2c_init_all(); +#endif +#ifdef CONFIG_VID + init_func_vid(); +#endif + dram_init(); +#ifdef CONFIG_SPL_FSL_LS_PPA +#ifndef CONFIG_SYS_MEM_RESERVE_SECURE +#error Need secure RAM for PPA +#endif + /* + * Secure memory location is determined in dram_init_banksize(). + * gd->ram_size is deducted by the size of secure ram. + */ + dram_init_banksize(); + + /* + * After dram_init_bank_size(), we know U-Boot only uses the first + * memory bank regardless how big the memory is. + */ + gd->ram_top = gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size; + + /* + * If PPA is loaded, U-Boot will resume running at EL2. + * Cache and MMU will be enabled. Need a place for TLB. + * U-Boot will be relocated to the end of available memory + * in first bank. At this point, we cannot know how much + * memory U-Boot uses. Put TLB table lower by SPL_TLB_SETBACK + * to avoid overlapping. As soon as the RAM version U-Boot sets + * up new MMU, this space is no longer needed. + */ + gd->ram_top -= SPL_TLB_SETBACK; + gd->arch.tlb_size = PGTABLE_SIZE; + gd->arch.tlb_addr = (gd->ram_top - gd->arch.tlb_size) & ~(0x10000 - 1); + gd->arch.tlb_allocated = gd->arch.tlb_addr; +#endif /* CONFIG_SPL_FSL_LS_PPA */ +#if defined(CONFIG_QSPI_AHB_INIT) && defined(CONFIG_QSPI_BOOT) + qspi_ahb_init(); +#endif +} + +#ifdef CONFIG_SPL_OS_BOOT +/* + * Return + * 0 if booting into OS is selected + * 1 if booting into U-Boot is selected + */ +int spl_start_uboot(void) +{ + env_init(); + if (env_get_yesno("boot_os") != 0) + return 0; + + return 1; +} +#endif /* CONFIG_SPL_OS_BOOT */ +#ifdef CONFIG_SPL_LOAD_FIT +int board_fit_config_name_match(const char *name) +{ + /* Just empty function now - can't decide what to choose */ + debug("%s: %s\n", __func__, name); + + return 0; +} +#endif +#endif /* CONFIG_SPL_BUILD */
diff --git a/arch/arm/cpu/armv8/fwcall.c b/arch/arm/cpu/armv8/fwcall.c new file mode 100644 index 0000000..9957c29 --- /dev/null +++ b/arch/arm/cpu/armv8/fwcall.c
@@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/** + * (C) Copyright 2014, Cavium Inc. + * (C) Copyright 2017, Xilinx Inc. + * +**/ + +#include <asm-offsets.h> +#include <config.h> +#include <version.h> +#include <asm/macro.h> +#include <asm/psci.h> +#include <asm/system.h> + +/* + * Issue the hypervisor call + * + * x0~x7: input arguments + * x0~x3: output arguments + */ +static void hvc_call(struct pt_regs *args) +{ + asm volatile( + "ldr x0, %0\n" + "ldr x1, %1\n" + "ldr x2, %2\n" + "ldr x3, %3\n" + "ldr x4, %4\n" + "ldr x5, %5\n" + "ldr x6, %6\n" + "ldr x7, %7\n" + "hvc #0\n" + "str x0, %0\n" + "str x1, %1\n" + "str x2, %2\n" + "str x3, %3\n" + : "+m" (args->regs[0]), "+m" (args->regs[1]), + "+m" (args->regs[2]), "+m" (args->regs[3]) + : "m" (args->regs[4]), "m" (args->regs[5]), + "m" (args->regs[6]), "m" (args->regs[7]) + : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", + "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", + "x16", "x17"); +} + +/* + * void smc_call(arg0, arg1...arg7) + * + * issue the secure monitor call + * + * x0~x7: input arguments + * x0~x3: output arguments + */ + +void smc_call(struct pt_regs *args) +{ + asm volatile( + "ldr x0, %0\n" + "ldr x1, %1\n" + "ldr x2, %2\n" + "ldr x3, %3\n" + "ldr x4, %4\n" + "ldr x5, %5\n" + "ldr x6, %6\n" + "smc #0\n" + "str x0, %0\n" + "str x1, %1\n" + "str x2, %2\n" + "str x3, %3\n" + : "+m" (args->regs[0]), "+m" (args->regs[1]), + "+m" (args->regs[2]), "+m" (args->regs[3]) + : "m" (args->regs[4]), "m" (args->regs[5]), + "m" (args->regs[6]) + : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", + "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", + "x16", "x17"); +} + +/* + * For now, all systems we support run at least in EL2 and thus + * trigger PSCI calls to EL3 using SMC. If anyone ever wants to + * use PSCI on U-Boot running below a hypervisor, please detect + * this and set the flag accordingly. + */ +static const bool use_smc_for_psci = true; + +void __noreturn psci_system_reset(void) +{ + struct pt_regs regs; + + regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_RESET; + + if (use_smc_for_psci) + smc_call(®s); + else + hvc_call(®s); + + while (1) + ; +} + +void __noreturn psci_system_off(void) +{ + struct pt_regs regs; + + regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_OFF; + + if (use_smc_for_psci) + smc_call(®s); + else + hvc_call(®s); + + while (1) + ; +}
diff --git a/arch/arm/cpu/armv8/generic_timer.c b/arch/arm/cpu/armv8/generic_timer.c new file mode 100644 index 0000000..c1706dc --- /dev/null +++ b/arch/arm/cpu/armv8/generic_timer.c
@@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Generic timer implementation of get_tbclk() + */ +unsigned long get_tbclk(void) +{ + unsigned long cntfrq; + asm volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq)); + return cntfrq; +} + +#ifdef CONFIG_SYS_FSL_ERRATUM_A008585 +/* + * FSL erratum A-008585 says that the ARM generic timer counter "has the + * potential to contain an erroneous value for a small number of core + * clock cycles every time the timer value changes". + * This sometimes leads to a consecutive counter read returning a lower + * value than the previous one, thus reporting the time to go backwards. + * The workaround is to read the counter twice and only return when the value + * was the same in both reads. + * Assumes that the CPU runs in much higher frequency than the timer. + */ +unsigned long timer_read_counter(void) +{ + unsigned long cntpct; + unsigned long temp; + + isb(); + asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); + asm volatile("mrs %0, cntpct_el0" : "=r" (temp)); + while (temp != cntpct) { + asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); + asm volatile("mrs %0, cntpct_el0" : "=r" (temp)); + } + + return cntpct; +} +#elif CONFIG_SUNXI_A64_TIMER_ERRATUM +/* + * This erratum sometimes flips the lower 11 bits of the counter value + * to all 0's or all 1's, leading to jumps forwards or backwards. + * Backwards jumps might be interpreted all roll-overs and be treated as + * huge jumps forward. + * The workaround is to check whether the lower 11 bits of the counter are + * all 0 or all 1, then discard this value and read again. + * This occasionally discards valid values, but will catch all erroneous + * reads and fixes the problem reliably. Also this mostly requires only a + * single read, so does not have any significant overhead. + * The algorithm was conceived by Samuel Holland. + */ +unsigned long timer_read_counter(void) +{ + unsigned long cntpct; + + isb(); + do { + asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); + } while (((cntpct + 1) & GENMASK(10, 0)) <= 1); + + return cntpct; +} +#else +/* + * timer_read_counter() using the Arm Generic Timer (aka arch timer). + */ +unsigned long timer_read_counter(void) +{ + unsigned long cntpct; + + isb(); + asm volatile("mrs %0, cntpct_el0" : "=r" (cntpct)); + + return cntpct; +} +#endif + +uint64_t get_ticks(void) +{ + unsigned long ticks = timer_read_counter(); + + gd->arch.tbl = ticks; + + return ticks; +} + +unsigned long usec2ticks(unsigned long usec) +{ + ulong ticks; + if (usec < 1000) + ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000; + else + ticks = ((usec / 10) * (get_tbclk() / 100000)); + + return ticks; +} + +ulong timer_get_boot_us(void) +{ + u64 val = get_ticks() * 1000000; + + return val / get_tbclk(); +}
diff --git a/arch/arm/cpu/armv8/hisilicon/Makefile b/arch/arm/cpu/armv8/hisilicon/Makefile new file mode 100644 index 0000000..cf2fe05 --- /dev/null +++ b/arch/arm/cpu/armv8/hisilicon/Makefile
@@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2015 Linaro +# Peter Griffin <peter.griffin@linaro.org> + +obj-y += pinmux.o
diff --git a/arch/arm/cpu/armv8/hisilicon/pinmux.c b/arch/arm/cpu/armv8/hisilicon/pinmux.c new file mode 100644 index 0000000..c549ddb --- /dev/null +++ b/arch/arm/cpu/armv8/hisilicon/pinmux.c
@@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Linaro. + * Peter Griffin <peter.griffin@linaro.org> + */ + +#include <common.h> +#include <fdtdec.h> +#include <asm/gpio.h> +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +struct hi6220_pinmux0_regs *pmx0 = + (struct hi6220_pinmux0_regs *)HI6220_PINMUX0_BASE; + +struct hi6220_pinmux1_regs *pmx1 = + (struct hi6220_pinmux1_regs *)HI6220_PINMUX1_BASE; + +static void hi6220_uart_config(int peripheral) +{ + switch (peripheral) { + case PERIPH_ID_UART0: + writel(MUX_M0, &pmx0->iomg[48]); /* UART0_RXD */ + writel(MUX_M0, &pmx0->iomg[49]); /* UART0_TXD */ + + writel(DRIVE1_02MA | PULL_UP, &pmx1->iocfg[49]); /* UART0_RXD */ + writel(DRIVE1_02MA | PULL_UP, &pmx1->iocfg[50]); /* UART0_TXD */ + break; + + case PERIPH_ID_UART1: + writel(MUX_M0, &pmx0->iomg[50]); /* UART1_CTS_N */ + writel(MUX_M0, &pmx0->iomg[51]); /* UART1_RTS_N */ + writel(MUX_M0, &pmx0->iomg[52]); /* UART1_RXD */ + writel(MUX_M0, &pmx0->iomg[53]); /* UART1_TXD */ + + writel(DRIVE1_02MA | PULL_UP, &pmx1->iocfg[51]); /*UART1_CTS_N*/ + writel(DRIVE1_02MA | PULL_UP, &pmx1->iocfg[53]); /* UART1_RXD */ + writel(DRIVE1_02MA, &pmx1->iocfg[52]); /* UART1_RTS_N */ + writel(DRIVE1_02MA, &pmx1->iocfg[54]); /* UART1_TXD */ + break; + + case PERIPH_ID_UART2: + writel(MUX_M0, &pmx0->iomg[54]); /* UART2_CTS_N */ + writel(MUX_M0, &pmx0->iomg[55]); /* UART2_RTS_N */ + writel(MUX_M0, &pmx0->iomg[56]); /* UART2_RXD */ + writel(MUX_M0, &pmx0->iomg[57]); /* UART2_TXD */ + + writel(DRIVE1_02MA, &pmx1->iocfg[55]); /* UART2_CTS_N */ + writel(DRIVE1_02MA, &pmx1->iocfg[56]); /* UART2_RTS_N */ + writel(DRIVE1_02MA, &pmx1->iocfg[57]); /* UART2_RXD */ + writel(DRIVE1_02MA, &pmx1->iocfg[58]); /* UART2_TXD */ + break; + + case PERIPH_ID_UART3: + writel(MUX_M1, &pmx0->iomg[96]); /* UART3_CTS_N */ + writel(MUX_M1, &pmx0->iomg[97]); /* UART3_RTS_N */ + writel(MUX_M1, &pmx0->iomg[98]); /* UART3_RXD */ + writel(MUX_M1, &pmx0->iomg[99]); /* UART3_TXD */ + + /* UART3_TXD */ + writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[100]); + /* UART3_RTS_N */ + writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[101]); + /* UART3_RXD */ + writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[102]); + /* UART3_TXD */ + writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[103]); + break; + + case PERIPH_ID_UART4: + writel(MUX_M1, &pmx0->iomg[116]); /* UART4_CTS_N */ + writel(MUX_M1, &pmx0->iomg[117]); /* UART4_RTS_N */ + writel(MUX_M1, &pmx0->iomg[118]); /* UART4_RXD */ + writel(MUX_M1, &pmx0->iomg[119]); /* UART4_TXD */ + + /* UART4_CTS_N */ + writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[120]); + /* UART4_RTS_N */ + writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[121]); + /* UART4_RXD */ + writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[122]); + /* UART4_TXD */ + writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[123]); + break; + case PERIPH_ID_UART5: + writel(MUX_M1, &pmx0->iomg[114]); /* UART5_RXD */ + writel(MUX_M1, &pmx0->iomg[115]); /* UART5_TXD */ + + /* UART5_RXD */ + writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[118]); + /* UART5_TXD */ + writel(DRIVE1_02MA | PULL_DOWN, &pmx1->iocfg[119]); + + break; + + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return; + } +} + +static int hi6220_mmc_config(int peripheral) +{ + u32 tmp; + + switch (peripheral) { + case PERIPH_ID_SDMMC0: + + /* eMMC pinmux config */ + writel(MUX_M0, &pmx0->iomg[64]); /* EMMC_CLK */ + writel(MUX_M0, &pmx0->iomg[65]); /* EMMC_CMD */ + writel(MUX_M0, &pmx0->iomg[66]); /* EMMC_DATA0 */ + writel(MUX_M0, &pmx0->iomg[67]); /* EMMC_DATA1 */ + writel(MUX_M0, &pmx0->iomg[68]); /* EMMC_DATA2 */ + writel(MUX_M0, &pmx0->iomg[69]); /* EMMC_DATA3 */ + writel(MUX_M0, &pmx0->iomg[70]); /* EMMC_DATA4 */ + writel(MUX_M0, &pmx0->iomg[71]); /* EMMC_DATA5 */ + writel(MUX_M0, &pmx0->iomg[72]); /* EMMC_DATA6 */ + writel(MUX_M0, &pmx0->iomg[73]); /* EMMC_DATA7 */ + + /*eMMC configure up/down/drive */ + writel(DRIVE1_08MA, &pmx1->iocfg[65]); /* EMMC_CLK */ + + tmp = DRIVE1_04MA | PULL_UP; + writel(tmp, &pmx1->iocfg[65]); /* EMMC_CMD */ + writel(tmp, &pmx1->iocfg[66]); /* EMMC_DATA0 */ + writel(tmp, &pmx1->iocfg[67]); /* EMMC_DATA1 */ + writel(tmp, &pmx1->iocfg[68]); /* EMMC_DATA2 */ + writel(tmp, &pmx1->iocfg[69]); /* EMMC_DATA3 */ + writel(tmp, &pmx1->iocfg[70]); /* EMMC_DATA4 */ + writel(tmp, &pmx1->iocfg[71]); /* EMMC_DATA5 */ + writel(tmp, &pmx1->iocfg[72]); /* EMMC_DATA6 */ + writel(tmp, &pmx1->iocfg[73]); /* EMMC_DATA7 */ + + writel(DRIVE1_04MA, &pmx1->iocfg[73]); /* EMMC_RST_N */ + break; + + case PERIPH_ID_SDMMC1: + + writel(MUX_M0, &pmx0->iomg[3]); /* SD_CLK */ + writel(MUX_M0, &pmx0->iomg[4]); /* SD_CMD */ + writel(MUX_M0, &pmx0->iomg[5]); /* SD_DATA0 */ + writel(MUX_M0, &pmx0->iomg[6]); /* SD_DATA1 */ + writel(MUX_M0, &pmx0->iomg[7]); /* SD_DATA2 */ + writel(MUX_M0, &pmx0->iomg[8]); /* SD_DATA3 */ + + writel(DRIVE1_10MA | BIT(2), &pmx1->iocfg[3]); /*SD_CLK*/ + writel(DRIVE1_08MA | BIT(2), &pmx1->iocfg[4]); /*SD_CMD*/ + writel(DRIVE1_08MA | BIT(2), &pmx1->iocfg[5]); /*SD_DATA0*/ + writel(DRIVE1_08MA | BIT(2), &pmx1->iocfg[6]); /*SD_DATA1*/ + writel(DRIVE1_08MA | BIT(2), &pmx1->iocfg[7]); /*SD_DATA2*/ + writel(DRIVE1_08MA | BIT(2), &pmx1->iocfg[8]); /*SD_DATA3*/ + break; + + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + + return 0; +} + +int hi6220_pinmux_config(int peripheral) +{ + switch (peripheral) { + case PERIPH_ID_UART0: + case PERIPH_ID_UART1: + case PERIPH_ID_UART2: + case PERIPH_ID_UART3: + hi6220_uart_config(peripheral); + break; + case PERIPH_ID_SDMMC0: + case PERIPH_ID_SDMMC1: + return hi6220_mmc_config(peripheral); + default: + debug("%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + + return 0; +} + +
diff --git a/arch/arm/cpu/armv8/linux-kernel-image-header-vars.h b/arch/arm/cpu/armv8/linux-kernel-image-header-vars.h new file mode 100644 index 0000000..fa6e86d --- /dev/null +++ b/arch/arm/cpu/armv8/linux-kernel-image-header-vars.h
@@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * (C) Copyright 2017 NVIDIA Corporation <www.nvidia.com> + * + * Derived from Linux kernel v4.14 files: + * + * arch/arm64/include/asm/assembler.h: + * Based on arch/arm/include/asm/assembler.h, arch/arm/mm/proc-macros.S + * Copyright (C) 1996-2000 Russell King + * Copyright (C) 2012 ARM Ltd. + * + * arch/arm64/kernel/head.S: + * Based on arch/arm/kernel/head.S + * Copyright (C) 1994-2002 Russell King + * Copyright (C) 2003-2012 ARM Ltd. + * Authors: Catalin Marinas <catalin.marinas@arm.com> + * Will Deacon <will.deacon@arm.com> + * + * arch/arm64/kernel/image.h: + * Copyright (C) 2014 ARM Ltd. + */ + +/* + * There aren't any ELF relocations we can use to endian-swap values known only + * at link time (e.g. the subtraction of two symbol addresses), so we must get + * the linker to endian-swap certain values before emitting them. + * + * Note that, in order for this to work when building the ELF64 PIE executable + * (for KASLR), these values should not be referenced via R_AARCH64_ABS64 + * relocations, since these are fixed up at runtime rather than at build time + * when PIE is in effect. So we need to split them up in 32-bit high and low + * words. + */ +#ifdef CONFIG_CPU_BIG_ENDIAN +#define DATA_LE32(data) \ + ((((data) & 0x000000ff) << 24) | \ + (((data) & 0x0000ff00) << 8) | \ + (((data) & 0x00ff0000) >> 8) | \ + (((data) & 0xff000000) >> 24)) +#else +#define DATA_LE32(data) ((data) & 0xffffffff) +#endif + +#define DEFINE_IMAGE_LE64(sym, data) \ + sym##_lo32 = DATA_LE32((data) & 0xffffffff); \ + sym##_hi32 = DATA_LE32((data) >> 32) + +#define __MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define __CODE_DATA_SIZE (__bss_start - _start) +#define __BSS_SIZE (__bss_end - __bss_start) +#ifdef CONFIG_SYS_INIT_SP_BSS_OFFSET +#define __MAX_EXTRA_RAM_USAGE __MAX(__BSS_SIZE, CONFIG_SYS_INIT_SP_BSS_OFFSET) +#else +#define __MAX_EXTRA_RAM_USAGE __BSS_SIZE +#endif +#define __MEM_USAGE (__CODE_DATA_SIZE + __MAX_EXTRA_RAM_USAGE) + +#ifdef CONFIG_CPU_BIG_ENDIAN +#define __HEAD_FLAG_BE 1 +#else +#define __HEAD_FLAG_BE 0 +#endif + +#define __HEAD_FLAG_PAGE_SIZE 1 /* 4K hard-coded */ + +#define __HEAD_FLAG_PHYS_BASE 1 + +#define __HEAD_FLAGS ((__HEAD_FLAG_BE << 0) | \ + (__HEAD_FLAG_PAGE_SIZE << 1) | \ + (__HEAD_FLAG_PHYS_BASE << 3)) + +#define TEXT_OFFSET (CONFIG_SYS_TEXT_BASE - \ + CONFIG_LNX_KRNL_IMG_TEXT_OFFSET_BASE) + +/* + * These will output as part of the Image header, which should be little-endian + * regardless of the endianness of the kernel. While constant values could be + * endian swapped in head.S, all are done here for consistency. + */ +#define HEAD_SYMBOLS \ + DEFINE_IMAGE_LE64(_kernel_size_le, __MEM_USAGE); \ + DEFINE_IMAGE_LE64(_kernel_offset_le, TEXT_OFFSET); \ + DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS); + + HEAD_SYMBOLS
diff --git a/arch/arm/cpu/armv8/lowlevel_init.S b/arch/arm/cpu/armv8/lowlevel_init.S new file mode 100644 index 0000000..f4f0cdc --- /dev/null +++ b/arch/arm/cpu/armv8/lowlevel_init.S
@@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * A lowlevel_init function that sets up the stack to call a C function to + * perform further init. + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> + +ENTRY(lowlevel_init) + /* + * Setup a temporary stack. Global data is not available yet. + */ +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) + ldr w0, =CONFIG_SPL_STACK +#else + ldr w0, =CONFIG_SYS_INIT_SP_ADDR +#endif + bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */ + + /* + * Save the old LR(passed in x29) and the current LR to stack + */ + stp x29, x30, [sp, #-16]! + + /* + * Call the very early init function. This should do only the + * absolute bare minimum to get started. It should not: + * + * - set up DRAM + * - use global_data + * - clear BSS + * - try to start a console + * + * For boards with SPL this should be empty since SPL can do all of + * this init in the SPL board_init_f() function which is called + * immediately after this. + */ + bl s_init + ldp x29, x30, [sp] + ret +ENDPROC(lowlevel_init)
diff --git a/arch/arm/cpu/armv8/psci.S b/arch/arm/cpu/armv8/psci.S new file mode 100644 index 0000000..358df8f --- /dev/null +++ b/arch/arm/cpu/armv8/psci.S
@@ -0,0 +1,311 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2016 Freescale Semiconductor, Inc. + * Author: Hongbo Zhang <hongbo.zhang@nxp.com> + * This file implements LS102X platform PSCI SYSTEM-SUSPEND function + */ + +#include <config.h> +#include <linux/linkage.h> +#include <asm/psci.h> + +/* Default PSCI function, return -1, Not Implemented */ +#define PSCI_DEFAULT(__fn) \ + ENTRY(__fn); \ + mov w0, #ARM_PSCI_RET_NI; \ + ret; \ + ENDPROC(__fn); \ + .weak __fn + +/* PSCI function and ID table definition*/ +#define PSCI_TABLE(__id, __fn) \ + .word __id; \ + .word __fn + +.pushsection ._secure.text, "ax" + +/* 32 bits PSCI default functions */ +PSCI_DEFAULT(psci_version) +PSCI_DEFAULT(psci_cpu_suspend) +PSCI_DEFAULT(psci_cpu_off) +PSCI_DEFAULT(psci_cpu_on) +PSCI_DEFAULT(psci_affinity_info) +PSCI_DEFAULT(psci_migrate) +PSCI_DEFAULT(psci_migrate_info_type) +PSCI_DEFAULT(psci_migrate_info_up_cpu) +PSCI_DEFAULT(psci_system_off) +PSCI_DEFAULT(psci_system_reset) +PSCI_DEFAULT(psci_features) +PSCI_DEFAULT(psci_cpu_freeze) +PSCI_DEFAULT(psci_cpu_default_suspend) +PSCI_DEFAULT(psci_node_hw_state) +PSCI_DEFAULT(psci_system_suspend) +PSCI_DEFAULT(psci_set_suspend_mode) +PSCI_DEFAULT(psi_stat_residency) +PSCI_DEFAULT(psci_stat_count) + +.align 3 +_psci_32_table: +PSCI_TABLE(ARM_PSCI_FN_CPU_SUSPEND, psci_cpu_suspend) +PSCI_TABLE(ARM_PSCI_FN_CPU_OFF, psci_cpu_off) +PSCI_TABLE(ARM_PSCI_FN_CPU_ON, psci_cpu_on) +PSCI_TABLE(ARM_PSCI_FN_MIGRATE, psci_migrate) +PSCI_TABLE(ARM_PSCI_0_2_FN_PSCI_VERSION, psci_version) +PSCI_TABLE(ARM_PSCI_0_2_FN_CPU_SUSPEND, psci_cpu_suspend) +PSCI_TABLE(ARM_PSCI_0_2_FN_CPU_OFF, psci_cpu_off) +PSCI_TABLE(ARM_PSCI_0_2_FN_CPU_ON, psci_cpu_on) +PSCI_TABLE(ARM_PSCI_0_2_FN_AFFINITY_INFO, psci_affinity_info) +PSCI_TABLE(ARM_PSCI_0_2_FN_MIGRATE, psci_migrate) +PSCI_TABLE(ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE, psci_migrate_info_type) +PSCI_TABLE(ARM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU, psci_migrate_info_up_cpu) +PSCI_TABLE(ARM_PSCI_0_2_FN_SYSTEM_OFF, psci_system_off) +PSCI_TABLE(ARM_PSCI_0_2_FN_SYSTEM_RESET, psci_system_reset) +PSCI_TABLE(ARM_PSCI_1_0_FN_PSCI_FEATURES, psci_features) +PSCI_TABLE(ARM_PSCI_1_0_FN_CPU_FREEZE, psci_cpu_freeze) +PSCI_TABLE(ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND, psci_cpu_default_suspend) +PSCI_TABLE(ARM_PSCI_1_0_FN_NODE_HW_STATE, psci_node_hw_state) +PSCI_TABLE(ARM_PSCI_1_0_FN_SYSTEM_SUSPEND, psci_system_suspend) +PSCI_TABLE(ARM_PSCI_1_0_FN_SET_SUSPEND_MODE, psci_set_suspend_mode) +PSCI_TABLE(ARM_PSCI_1_0_FN_STAT_RESIDENCY, psi_stat_residency) +PSCI_TABLE(ARM_PSCI_1_0_FN_STAT_COUNT, psci_stat_count) +PSCI_TABLE(0, 0) + +/* 64 bits PSCI default functions */ +PSCI_DEFAULT(psci_cpu_suspend_64) +PSCI_DEFAULT(psci_cpu_on_64) +PSCI_DEFAULT(psci_affinity_info_64) +PSCI_DEFAULT(psci_migrate_64) +PSCI_DEFAULT(psci_migrate_info_up_cpu_64) +PSCI_DEFAULT(psci_cpu_default_suspend_64) +PSCI_DEFAULT(psci_node_hw_state_64) +PSCI_DEFAULT(psci_system_suspend_64) +PSCI_DEFAULT(psci_stat_residency_64) +PSCI_DEFAULT(psci_stat_count_64) + +.align 3 +_psci_64_table: +PSCI_TABLE(ARM_PSCI_0_2_FN64_CPU_SUSPEND, psci_cpu_suspend_64) +PSCI_TABLE(ARM_PSCI_0_2_FN64_CPU_ON, psci_cpu_on_64) +PSCI_TABLE(ARM_PSCI_0_2_FN64_AFFINITY_INFO, psci_affinity_info_64) +PSCI_TABLE(ARM_PSCI_0_2_FN64_MIGRATE, psci_migrate_64) +PSCI_TABLE(ARM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU, psci_migrate_info_up_cpu_64) +PSCI_TABLE(ARM_PSCI_1_0_FN64_CPU_DEFAULT_SUSPEND, psci_cpu_default_suspend_64) +PSCI_TABLE(ARM_PSCI_1_0_FN64_NODE_HW_STATE, psci_node_hw_state_64) +PSCI_TABLE(ARM_PSCI_1_0_FN64_SYSTEM_SUSPEND, psci_system_suspend_64) +PSCI_TABLE(ARM_PSCI_1_0_FN64_STAT_RESIDENCY, psci_stat_residency_64) +PSCI_TABLE(ARM_PSCI_1_0_FN64_STAT_COUNT, psci_stat_count_64) +PSCI_TABLE(0, 0) + +.macro psci_enter + /* PSCI call is Fast Call(atomic), so mask DAIF */ + mrs x15, DAIF + stp x15, xzr, [sp, #-16]! + ldr x15, =0x3C0 + msr DAIF, x15 + /* SMC convention, x18 ~ x30 should be saved by callee */ + stp x29, x30, [sp, #-16]! + stp x27, x28, [sp, #-16]! + stp x25, x26, [sp, #-16]! + stp x23, x24, [sp, #-16]! + stp x21, x22, [sp, #-16]! + stp x19, x20, [sp, #-16]! + mrs x15, elr_el3 + stp x18, x15, [sp, #-16]! +.endm + +.macro psci_return + /* restore registers */ + ldp x18, x15, [sp], #16 + msr elr_el3, x15 + ldp x19, x20, [sp], #16 + ldp x21, x22, [sp], #16 + ldp x23, x24, [sp], #16 + ldp x25, x26, [sp], #16 + ldp x27, x28, [sp], #16 + ldp x29, x30, [sp], #16 + /* restore DAIF */ + ldp x15, xzr, [sp], #16 + msr DAIF, x15 + eret +.endm + +/* Caller must put PSCI function-ID table base in x9 */ +handle_psci: + psci_enter +1: ldr x10, [x9] /* Load PSCI function table */ + ubfx x11, x10, #32, #32 + ubfx x10, x10, #0, #32 + cbz x10, 3f /* If reach the end, bail out */ + cmp x10, x0 + b.eq 2f /* PSCI function found */ + add x9, x9, #8 /* If not match, try next entry */ + b 1b + +2: blr x11 /* Call PSCI function */ + psci_return + +3: mov x0, #ARM_PSCI_RET_NI + psci_return + +unknown_smc_id: + ldr x0, =0xFFFFFFFF + eret + +handle_smc32: + /* SMC function ID 0x84000000-0x8400001F: 32 bits PSCI */ + ldr w9, =0x8400001F + cmp w0, w9 + b.gt unknown_smc_id + ldr w9, =0x84000000 + cmp w0, w9 + b.lt unknown_smc_id + + adr x9, _psci_32_table + b handle_psci + +handle_smc64: + /* check SMC32 or SMC64 calls */ + ubfx x9, x0, #30, #1 + cbz x9, handle_smc32 + + /* SMC function ID 0xC4000000-0xC400001F: 64 bits PSCI */ + ldr x9, =0xC400001F + cmp x0, x9 + b.gt unknown_smc_id + ldr x9, =0xC4000000 + cmp x0, x9 + b.lt unknown_smc_id + + adr x9, _psci_64_table + b handle_psci + +/* + * Get CPU ID from MPIDR, suppose every cluster has same number of CPU cores, + * Platform with asymmetric clusters should implement their own interface. + * In case this function being called by other platform's C code, the ARM + * Architecture Procedure Call Standard is considered, e.g. register X0 is + * used for the return value, while in this PSCI environment, X0 usually holds + * the SMC function identifier, so X0 should be saved by caller function. + */ +ENTRY(psci_get_cpu_id) +#ifdef CONFIG_ARMV8_PSCI_CPUS_PER_CLUSTER + mrs x9, MPIDR_EL1 + ubfx x9, x9, #8, #8 + ldr x10, =CONFIG_ARMV8_PSCI_CPUS_PER_CLUSTER + mul x9, x10, x9 +#else + mov x9, xzr +#endif + mrs x10, MPIDR_EL1 + ubfx x10, x10, #0, #8 + add x0, x10, x9 + ret +ENDPROC(psci_get_cpu_id) +.weak psci_get_cpu_id + +/* CPU ID input in x0, stack top output in x0*/ +LENTRY(psci_get_cpu_stack_top) + adr x9, __secure_stack_end + lsl x0, x0, #ARM_PSCI_STACK_SHIFT + sub x0, x9, x0 + ret +ENDPROC(psci_get_cpu_stack_top) + +unhandled_exception: + b unhandled_exception /* simply dead loop */ + +handle_sync: + mov x15, x30 + mov x14, x0 + + bl psci_get_cpu_id + bl psci_get_cpu_stack_top + mov x9, #1 + msr spsel, x9 + mov sp, x0 + + mov x0, x14 + mov x30, x15 + + mrs x9, esr_el3 + ubfx x9, x9, #26, #6 + cmp x9, #0x13 + b.eq handle_smc32 + cmp x9, #0x17 + b.eq handle_smc64 + + b unhandled_exception + +#ifdef CONFIG_ARMV8_EA_EL3_FIRST +/* + * Override this function if custom error handling is + * needed for asynchronous aborts + */ +ENTRY(plat_error_handler) + ret +ENDPROC(plat_error_handler) +.weak plat_error_handler + +handle_error: + bl psci_get_cpu_id + bl psci_get_cpu_stack_top + mov x9, #1 + msr spsel, x9 + mov sp, x0 + + bl plat_error_handler /* Platform specific error handling */ +deadloop: + b deadloop /* Never return */ +#endif + + .align 11 + .globl el3_exception_vectors +el3_exception_vectors: + b unhandled_exception /* Sync, Current EL using SP0 */ + .align 7 + b unhandled_exception /* IRQ, Current EL using SP0 */ + .align 7 + b unhandled_exception /* FIQ, Current EL using SP0 */ + .align 7 + b unhandled_exception /* SError, Current EL using SP0 */ + .align 7 + b unhandled_exception /* Sync, Current EL using SPx */ + .align 7 + b unhandled_exception /* IRQ, Current EL using SPx */ + .align 7 + b unhandled_exception /* FIQ, Current EL using SPx */ + .align 7 + b unhandled_exception /* SError, Current EL using SPx */ + .align 7 + b handle_sync /* Sync, Lower EL using AArch64 */ + .align 7 + b unhandled_exception /* IRQ, Lower EL using AArch64 */ + .align 7 + b unhandled_exception /* FIQ, Lower EL using AArch64 */ + .align 7 +#ifdef CONFIG_ARMV8_EA_EL3_FIRST + b handle_error /* SError, Lower EL using AArch64 */ +#else + b unhandled_exception /* SError, Lower EL using AArch64 */ +#endif + .align 7 + b unhandled_exception /* Sync, Lower EL using AArch32 */ + .align 7 + b unhandled_exception /* IRQ, Lower EL using AArch32 */ + .align 7 + b unhandled_exception /* FIQ, Lower EL using AArch32 */ + .align 7 + b unhandled_exception /* SError, Lower EL using AArch32 */ + +ENTRY(psci_setup_vectors) + adr x0, el3_exception_vectors + msr vbar_el3, x0 + ret +ENDPROC(psci_setup_vectors) + +ENTRY(psci_arch_init) + ret +ENDPROC(psci_arch_init) +.weak psci_arch_init + +.popsection
diff --git a/arch/arm/cpu/armv8/s32v234/Makefile b/arch/arm/cpu/armv8/s32v234/Makefile new file mode 100644 index 0000000..3bdb98d --- /dev/null +++ b/arch/arm/cpu/armv8/s32v234/Makefile
@@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2013-2016, Freescale Semiconductor, Inc. + +obj-y += generic.o +obj-y += cpu.o
diff --git a/arch/arm/cpu/armv8/s32v234/cpu.c b/arch/arm/cpu/armv8/s32v234/cpu.c new file mode 100644 index 0000000..1fa6841 --- /dev/null +++ b/arch/arm/cpu/armv8/s32v234/cpu.c
@@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2014-2016, Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/armv8/mmu.h> +#include <asm/io.h> +#include <asm/arch/mc_me_regs.h> +#include "cpu.h" + +u32 cpu_mask(void) +{ + return readl(MC_ME_CS); +} + +#ifndef CONFIG_SYS_DCACHE_OFF + +#define S32V234_IRAM_BASE 0x3e800000UL +#define S32V234_IRAM_SIZE 0x800000UL +#define S32V234_DRAM_BASE1 0x80000000UL +#define S32V234_DRAM_SIZE1 0x40000000UL +#define S32V234_DRAM_BASE2 0xC0000000UL +#define S32V234_DRAM_SIZE2 0x20000000UL +#define S32V234_PERIPH_BASE 0x40000000UL +#define S32V234_PERIPH_SIZE 0x40000000UL + +static struct mm_region s32v234_mem_map[] = { + { + .virt = S32V234_IRAM_BASE, + .phys = S32V234_IRAM_BASE, + .size = S32V234_IRAM_SIZE, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE + }, { + .virt = S32V234_DRAM_BASE1, + .phys = S32V234_DRAM_BASE1, + .size = S32V234_DRAM_SIZE1, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_OUTER_SHARE + }, { + .virt = S32V234_PERIPH_BASE, + .phys = S32V234_PERIPH_BASE, + .size = S32V234_PERIPH_SIZE, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE + /* TODO: Do we need these? */ + /* | PTE_BLOCK_PXN | PTE_BLOCK_UXN */ + }, { + .virt = S32V234_DRAM_BASE2, + .phys = S32V234_DRAM_BASE2, + .size = S32V234_DRAM_SIZE2, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) | + PTE_BLOCK_OUTER_SHARE + }, { + /* List terminator */ + 0, + } +}; + +struct mm_region *mem_map = s32v234_mem_map; + +#endif + +/* + * Return the number of cores on this SOC. + */ +int cpu_numcores(void) +{ + int numcores; + u32 mask; + + mask = cpu_mask(); + numcores = hweight32(cpu_mask()); + + /* Verify if M4 is deactivated */ + if (mask & 0x1) + numcores--; + + return numcores; +} + +#if defined(CONFIG_ARCH_EARLY_INIT_R) +int arch_early_init_r(void) +{ + int rv; + asm volatile ("dsb sy"); + rv = fsl_s32v234_wake_seconday_cores(); + + if (rv) + printf("Did not wake secondary cores\n"); + + asm volatile ("sev"); + return 0; +} +#endif /* CONFIG_ARCH_EARLY_INIT_R */
diff --git a/arch/arm/cpu/armv8/s32v234/cpu.h b/arch/arm/cpu/armv8/s32v234/cpu.h new file mode 100644 index 0000000..11c3a6b --- /dev/null +++ b/arch/arm/cpu/armv8/s32v234/cpu.h
@@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2014-2016, Freescale Semiconductor, Inc. + */ + +u32 cpu_mask(void); +int cpu_numcores(void);
diff --git a/arch/arm/cpu/armv8/s32v234/generic.c b/arch/arm/cpu/armv8/s32v234/generic.c new file mode 100644 index 0000000..273b88e --- /dev/null +++ b/arch/arm/cpu/armv8/s32v234/generic.c
@@ -0,0 +1,349 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2013-2016, Freescale Semiconductor, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/mc_cgm_regs.h> +#include <asm/arch/mc_me_regs.h> +#include <asm/arch/mc_rgm_regs.h> +#include <netdev.h> +#include <div64.h> +#include <errno.h> + +u32 get_cpu_rev(void) +{ + struct mscm_ir *mscmir = (struct mscm_ir *)MSCM_BASE_ADDR; + u32 cpu = readl(&mscmir->cpxtype); + + return cpu; +} + +DECLARE_GLOBAL_DATA_PTR; + +static uintptr_t get_pllfreq(u32 pll, u32 refclk_freq, u32 plldv, + u32 pllfd, u32 selected_output) +{ + u32 vco = 0, plldv_prediv = 0, plldv_mfd = 0, pllfd_mfn = 0; + u32 plldv_rfdphi_div = 0, fout = 0; + u32 dfs_portn = 0, dfs_mfn = 0, dfs_mfi = 0; + + if (selected_output > DFS_MAXNUMBER) { + return -1; + } + + plldv_prediv = + (plldv & PLLDIG_PLLDV_PREDIV_MASK) >> PLLDIG_PLLDV_PREDIV_OFFSET; + plldv_mfd = (plldv & PLLDIG_PLLDV_MFD_MASK); + + pllfd_mfn = (pllfd & PLLDIG_PLLFD_MFN_MASK); + + plldv_prediv = plldv_prediv == 0 ? 1 : plldv_prediv; + + /* The formula for VCO is from TR manual, rev. D */ + vco = refclk_freq / plldv_prediv * (plldv_mfd + pllfd_mfn / 20481); + + if (selected_output != 0) { + /* Determine the RFDPHI for PHI1 */ + plldv_rfdphi_div = + (plldv & PLLDIG_PLLDV_RFDPHI1_MASK) >> + PLLDIG_PLLDV_RFDPHI1_OFFSET; + plldv_rfdphi_div = plldv_rfdphi_div == 0 ? 1 : plldv_rfdphi_div; + if (pll == ARM_PLL || pll == ENET_PLL || pll == DDR_PLL) { + dfs_portn = + readl(DFS_DVPORTn(pll, selected_output - 1)); + dfs_mfi = + (dfs_portn & DFS_DVPORTn_MFI_MASK) >> + DFS_DVPORTn_MFI_OFFSET; + dfs_mfn = + (dfs_portn & DFS_DVPORTn_MFI_MASK) >> + DFS_DVPORTn_MFI_OFFSET; + fout = vco / (dfs_mfi + (dfs_mfn / 256)); + } else { + fout = vco / plldv_rfdphi_div; + } + + } else { + /* Determine the RFDPHI for PHI0 */ + plldv_rfdphi_div = + (plldv & PLLDIG_PLLDV_RFDPHI_MASK) >> + PLLDIG_PLLDV_RFDPHI_OFFSET; + fout = vco / plldv_rfdphi_div; + } + + return fout; + +} + +/* Implemented for ARMPLL, PERIPH_PLL, ENET_PLL, DDR_PLL, VIDEO_LL */ +static uintptr_t decode_pll(enum pll_type pll, u32 refclk_freq, + u32 selected_output) +{ + u32 plldv, pllfd; + + plldv = readl(PLLDIG_PLLDV(pll)); + pllfd = readl(PLLDIG_PLLFD(pll)); + + return get_pllfreq(pll, refclk_freq, plldv, pllfd, selected_output); +} + +static u32 get_mcu_main_clk(void) +{ + u32 coreclk_div; + u32 sysclk_sel; + u32 freq = 0; + + sysclk_sel = readl(CGM_SC_SS(MC_CGM1_BASE_ADDR)) & MC_CGM_SC_SEL_MASK; + sysclk_sel >>= MC_CGM_SC_SEL_OFFSET; + + coreclk_div = + readl(CGM_SC_DCn(MC_CGM1_BASE_ADDR, 0)) & MC_CGM_SC_DCn_PREDIV_MASK; + coreclk_div >>= MC_CGM_SC_DCn_PREDIV_OFFSET; + coreclk_div += 1; + + switch (sysclk_sel) { + case MC_CGM_SC_SEL_FIRC: + freq = FIRC_CLK_FREQ; + break; + case MC_CGM_SC_SEL_XOSC: + freq = XOSC_CLK_FREQ; + break; + case MC_CGM_SC_SEL_ARMPLL: + /* ARMPLL has as source XOSC and CORE_CLK has as input PHI0 */ + freq = decode_pll(ARM_PLL, XOSC_CLK_FREQ, 0); + break; + case MC_CGM_SC_SEL_CLKDISABLE: + printf("Sysclk is disabled\n"); + break; + default: + printf("unsupported system clock select\n"); + } + + return freq / coreclk_div; +} + +static u32 get_sys_clk(u32 number) +{ + u32 sysclk_div, sysclk_div_number; + u32 sysclk_sel; + u32 freq = 0; + + switch (number) { + case 3: + sysclk_div_number = 0; + break; + case 6: + sysclk_div_number = 1; + break; + default: + printf("unsupported system clock \n"); + return -1; + } + sysclk_sel = readl(CGM_SC_SS(MC_CGM0_BASE_ADDR)) & MC_CGM_SC_SEL_MASK; + sysclk_sel >>= MC_CGM_SC_SEL_OFFSET; + + sysclk_div = + readl(CGM_SC_DCn(MC_CGM1_BASE_ADDR, sysclk_div_number)) & + MC_CGM_SC_DCn_PREDIV_MASK; + sysclk_div >>= MC_CGM_SC_DCn_PREDIV_OFFSET; + sysclk_div += 1; + + switch (sysclk_sel) { + case MC_CGM_SC_SEL_FIRC: + freq = FIRC_CLK_FREQ; + break; + case MC_CGM_SC_SEL_XOSC: + freq = XOSC_CLK_FREQ; + break; + case MC_CGM_SC_SEL_ARMPLL: + /* ARMPLL has as source XOSC and SYSn_CLK has as input DFS1 */ + freq = decode_pll(ARM_PLL, XOSC_CLK_FREQ, 1); + break; + case MC_CGM_SC_SEL_CLKDISABLE: + printf("Sysclk is disabled\n"); + break; + default: + printf("unsupported system clock select\n"); + } + + return freq / sysclk_div; +} + +static u32 get_peripherals_clk(void) +{ + u32 aux5clk_div; + u32 freq = 0; + + aux5clk_div = + readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 5, 0)) & + MC_CGM_ACn_DCm_PREDIV_MASK; + aux5clk_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET; + aux5clk_div += 1; + + freq = decode_pll(PERIPH_PLL, XOSC_CLK_FREQ, 0); + + return freq / aux5clk_div; + +} + +static u32 get_uart_clk(void) +{ + u32 auxclk3_div, auxclk3_sel, freq = 0; + + auxclk3_sel = + readl(CGM_ACn_SS(MC_CGM0_BASE_ADDR, 3)) & MC_CGM_ACn_SEL_MASK; + auxclk3_sel >>= MC_CGM_ACn_SEL_OFFSET; + + auxclk3_div = + readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 3, 0)) & + MC_CGM_ACn_DCm_PREDIV_MASK; + auxclk3_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET; + auxclk3_div += 1; + + switch (auxclk3_sel) { + case MC_CGM_ACn_SEL_FIRC: + freq = FIRC_CLK_FREQ; + break; + case MC_CGM_ACn_SEL_XOSC: + freq = XOSC_CLK_FREQ; + break; + case MC_CGM_ACn_SEL_PERPLLDIVX: + freq = get_peripherals_clk() / 3; + break; + case MC_CGM_ACn_SEL_SYSCLK: + freq = get_sys_clk(6); + break; + default: + printf("unsupported system clock select\n"); + } + + return freq / auxclk3_div; +} + +static u32 get_fec_clk(void) +{ + u32 aux2clk_div; + u32 freq = 0; + + aux2clk_div = + readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 2, 0)) & + MC_CGM_ACn_DCm_PREDIV_MASK; + aux2clk_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET; + aux2clk_div += 1; + + freq = decode_pll(ENET_PLL, XOSC_CLK_FREQ, 0); + + return freq / aux2clk_div; +} + +static u32 get_usdhc_clk(void) +{ + u32 aux15clk_div; + u32 freq = 0; + + aux15clk_div = + readl(CGM_ACn_DCm(MC_CGM0_BASE_ADDR, 15, 0)) & + MC_CGM_ACn_DCm_PREDIV_MASK; + aux15clk_div >>= MC_CGM_ACn_DCm_PREDIV_OFFSET; + aux15clk_div += 1; + + freq = decode_pll(ENET_PLL, XOSC_CLK_FREQ, 4); + + return freq / aux15clk_div; +} + +static u32 get_i2c_clk(void) +{ + return get_peripherals_clk(); +} + +/* return clocks in Hz */ +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return get_mcu_main_clk(); + case MXC_PERIPHERALS_CLK: + return get_peripherals_clk(); + case MXC_UART_CLK: + return get_uart_clk(); + case MXC_FEC_CLK: + return get_fec_clk(); + case MXC_I2C_CLK: + return get_i2c_clk(); + case MXC_USDHC_CLK: + return get_usdhc_clk(); + default: + break; + } + printf("Error: Unsupported function to read the frequency! \ + Please define it correctly!"); + return -1; +} + +/* Not yet implemented - int soc_clk_dump(); */ + +#if defined(CONFIG_DISPLAY_CPUINFO) +static char *get_reset_cause(void) +{ + u32 cause = readl(MC_RGM_BASE_ADDR + 0x300); + + switch (cause) { + case F_SWT4: + return "WDOG"; + case F_JTAG: + return "JTAG"; + case F_FCCU_SOFT: + return "FCCU soft reaction"; + case F_FCCU_HARD: + return "FCCU hard reaction"; + case F_SOFT_FUNC: + return "Software Functional reset"; + case F_ST_DONE: + return "Self Test done reset"; + case F_EXT_RST: + return "External reset"; + default: + return "unknown reset"; + } + +} + +#define SRC_SCR_SW_RST (1<<12) + +void reset_cpu(ulong addr) +{ + printf("Feature not supported.\n"); +}; + +int print_cpuinfo(void) +{ + printf("CPU: Freescale Treerunner S32V234 at %d MHz\n", + mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("Reset cause: %s\n", get_reset_cause()); + + return 0; +} +#endif + +int cpu_eth_init(bd_t * bis) +{ + int rc = -ENODEV; + +#if defined(CONFIG_FEC_MXC) + rc = fecmxc_initialize(bis); +#endif + + return rc; +} + +int get_clocks(void) +{ +#ifdef CONFIG_FSL_ESDHC + gd->arch.sdhc_clk = mxc_get_clock(MXC_USDHC_CLK); +#endif + return 0; +}
diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c new file mode 100644 index 0000000..3c52495 --- /dev/null +++ b/arch/arm/cpu/armv8/sec_firmware.c
@@ -0,0 +1,497 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2016 NXP Semiconductor, Inc. + */ + +#include <common.h> +#include <errno.h> +#include <linux/kernel.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/types.h> +#include <asm/macro.h> +#include <asm/armv8/sec_firmware.h> + +DECLARE_GLOBAL_DATA_PTR; +extern void c_runtime_cpu_setup(void); + +#define SEC_FIRMWARE_LOADED 0x1 +#define SEC_FIRMWARE_RUNNING 0x2 +#define SEC_FIRMWARE_ADDR_MASK (~0x3) +/* + * Secure firmware load addr + * Flags used: 0x1 secure firmware has been loaded to secure memory + * 0x2 secure firmware is running + */ +phys_addr_t sec_firmware_addr; + +#ifndef SEC_FIRMWARE_FIT_IMAGE +#define SEC_FIRMWARE_FIT_IMAGE "firmware" +#endif +#ifndef SEC_FIRMEWARE_FIT_CNF_NAME +#define SEC_FIRMEWARE_FIT_CNF_NAME "config-1" +#endif +#ifndef SEC_FIRMWARE_TARGET_EL +#define SEC_FIRMWARE_TARGET_EL 2 +#endif + +static int sec_firmware_get_data(const void *sec_firmware_img, + const void **data, size_t *size) +{ + int conf_node_off, fw_node_off; + char *conf_node_name = NULL; + char *desc; + int ret; + + conf_node_name = SEC_FIRMEWARE_FIT_CNF_NAME; + + conf_node_off = fit_conf_get_node(sec_firmware_img, conf_node_name); + if (conf_node_off < 0) { + printf("SEC Firmware: %s: no such config\n", conf_node_name); + return -ENOENT; + } + + fw_node_off = fit_conf_get_prop_node(sec_firmware_img, conf_node_off, + SEC_FIRMWARE_FIT_IMAGE); + if (fw_node_off < 0) { + printf("SEC Firmware: No '%s' in config\n", + SEC_FIRMWARE_FIT_IMAGE); + return -ENOLINK; + } + + /* Verify secure firmware image */ + if (!(fit_image_verify(sec_firmware_img, fw_node_off))) { + printf("SEC Firmware: Bad firmware image (bad CRC)\n"); + return -EINVAL; + } + + if (fit_image_get_data(sec_firmware_img, fw_node_off, data, size)) { + printf("SEC Firmware: Can't get %s subimage data/size", + SEC_FIRMWARE_FIT_IMAGE); + return -ENOENT; + } + + ret = fit_get_desc(sec_firmware_img, fw_node_off, &desc); + if (ret) + printf("SEC Firmware: Can't get description\n"); + else + printf("%s\n", desc); + + return ret; +} + +/* + * SEC Firmware FIT image parser checks if the image is in FIT + * format, verifies integrity of the image and calculates raw + * image address and size values. + * + * Returns 0 on success and a negative errno on error task fail. + */ +static int sec_firmware_parse_image(const void *sec_firmware_img, + const void **raw_image_addr, + size_t *raw_image_size) +{ + int ret; + + ret = sec_firmware_get_data(sec_firmware_img, raw_image_addr, + raw_image_size); + if (ret) + return ret; + + debug("SEC Firmware: raw_image_addr = 0x%p, raw_image_size = 0x%lx\n", + *raw_image_addr, *raw_image_size); + + return 0; +} + +/* + * SEC Firmware FIT image parser to check if any loadable is + * present. If present, verify integrity of the loadable and + * copy loadable to address provided in (loadable_h, loadable_l). + * + * Returns 0 on success and a negative errno on error task fail. + */ +static int sec_firmware_check_copy_loadable(const void *sec_firmware_img, + u32 *loadable_l, u32 *loadable_h) +{ + phys_addr_t sec_firmware_loadable_addr = 0; + int conf_node_off, ld_node_off, images; + char *conf_node_name = NULL; + const void *data; + size_t size; + ulong load; + const char *name, *str, *type; + int len; + + conf_node_name = SEC_FIRMEWARE_FIT_CNF_NAME; + + conf_node_off = fit_conf_get_node(sec_firmware_img, conf_node_name); + if (conf_node_off < 0) { + printf("SEC Firmware: %s: no such config\n", conf_node_name); + return -ENOENT; + } + + /* find the node holding the images information */ + images = fdt_path_offset(sec_firmware_img, FIT_IMAGES_PATH); + if (images < 0) { + printf("%s: Cannot find /images node: %d\n", __func__, images); + return -1; + } + + type = FIT_LOADABLE_PROP; + + name = fdt_getprop(sec_firmware_img, conf_node_off, type, &len); + if (!name) { + /* Loadables not present */ + return 0; + } + + printf("SEC Firmware: '%s' present in config\n", type); + + for (str = name; str && ((str - name) < len); + str = strchr(str, '\0') + 1) { + printf("%s: '%s'\n", type, str); + ld_node_off = fdt_subnode_offset(sec_firmware_img, images, str); + if (ld_node_off < 0) { + printf("cannot find image node '%s': %d\n", str, + ld_node_off); + return -EINVAL; + } + + /* Verify secure firmware image */ + if (!(fit_image_verify(sec_firmware_img, ld_node_off))) { + printf("SEC Loadable: Bad loadable image (bad CRC)\n"); + return -EINVAL; + } + + if (fit_image_get_data(sec_firmware_img, ld_node_off, + &data, &size)) { + printf("SEC Loadable: Can't get subimage data/size"); + return -ENOENT; + } + + /* Get load address, treated as load offset to secure memory */ + if (fit_image_get_load(sec_firmware_img, ld_node_off, &load)) { + printf("SEC Loadable: Can't get subimage load"); + return -ENOENT; + } + + /* Compute load address for loadable in secure memory */ + sec_firmware_loadable_addr = (sec_firmware_addr - + gd->arch.tlb_size) + load; + + /* Copy loadable to secure memory and flush dcache */ + debug("%s copied to address 0x%p\n", + FIT_LOADABLE_PROP, (void *)sec_firmware_loadable_addr); + memcpy((void *)sec_firmware_loadable_addr, data, size); + flush_dcache_range(sec_firmware_loadable_addr, + sec_firmware_loadable_addr + size); + + /* Populate loadable address only for Trusted OS */ + if (!strcmp(str, "trustedOS@1")) { + /* + * Populate address ptrs for loadable image with + * loadbale addr + */ + out_le32(loadable_l, (sec_firmware_loadable_addr & + WORD_MASK)); + out_le32(loadable_h, (sec_firmware_loadable_addr >> + WORD_SHIFT)); + } + } + + return 0; +} + +static int sec_firmware_copy_image(const char *title, + u64 image_addr, u32 image_size, u64 sec_firmware) +{ + debug("%s copied to address 0x%p\n", title, (void *)sec_firmware); + memcpy((void *)sec_firmware, (void *)image_addr, image_size); + flush_dcache_range(sec_firmware, sec_firmware + image_size); + + return 0; +} + +/* + * This function will parse the SEC Firmware image, and then load it + * to secure memory. Also load any loadable if present along with SEC + * Firmware image. + */ +static int sec_firmware_load_image(const void *sec_firmware_img, + u32 *loadable_l, u32 *loadable_h) +{ + const void *raw_image_addr; + size_t raw_image_size = 0; + int ret; + + /* + * The Excetpion Level must be EL3 to load and initialize + * the SEC Firmware. + */ + if (current_el() != 3) { + ret = -EACCES; + goto out; + } + +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE + /* + * The SEC Firmware must be stored in secure memory. + * Append SEC Firmware to secure mmu table. + */ + if (!(gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED)) { + ret = -ENXIO; + goto out; + } + + sec_firmware_addr = (gd->arch.secure_ram & MEM_RESERVE_SECURE_ADDR_MASK) + + gd->arch.tlb_size; +#else +#error "The CONFIG_SYS_MEM_RESERVE_SECURE must be defined when enabled SEC Firmware support" +#endif + + /* Align SEC Firmware base address to 4K */ + sec_firmware_addr = (sec_firmware_addr + 0xfff) & ~0xfff; + debug("SEC Firmware: Load address: 0x%llx\n", + sec_firmware_addr & SEC_FIRMWARE_ADDR_MASK); + + ret = sec_firmware_parse_image(sec_firmware_img, &raw_image_addr, + &raw_image_size); + if (ret) + goto out; + + /* TODO: + * Check if the end addr of SEC Firmware has been extend the secure + * memory. + */ + + /* Copy the secure firmware to secure memory */ + ret = sec_firmware_copy_image("SEC Firmware", (u64)raw_image_addr, + raw_image_size, sec_firmware_addr & + SEC_FIRMWARE_ADDR_MASK); + if (ret) + goto out; + + /* + * Check if any loadable are present along with firmware image, if + * present load them. + */ + ret = sec_firmware_check_copy_loadable(sec_firmware_img, loadable_l, + loadable_h); + if (ret) + goto out; + + sec_firmware_addr |= SEC_FIRMWARE_LOADED; + debug("SEC Firmware: Entry point: 0x%llx\n", + sec_firmware_addr & SEC_FIRMWARE_ADDR_MASK); + + return 0; + +out: + printf("SEC Firmware: error (%d)\n", ret); + sec_firmware_addr = 0; + + return ret; +} + +static int sec_firmware_entry(u32 *eret_hold_l, u32 *eret_hold_h) +{ + const void *entry = (void *)(sec_firmware_addr & + SEC_FIRMWARE_ADDR_MASK); + + return _sec_firmware_entry(entry, eret_hold_l, eret_hold_h); +} + +/* Check the secure firmware FIT image */ +__weak bool sec_firmware_is_valid(const void *sec_firmware_img) +{ + if (fdt_check_header(sec_firmware_img)) { + printf("SEC Firmware: Bad firmware image (not a FIT image)\n"); + return false; + } + + if (fit_check_format(sec_firmware_img, IMAGE_SIZE_INVAL)) { + printf("SEC Firmware: Bad firmware image (bad FIT header)\n"); + return false; + } + + return true; +} + +#ifdef CONFIG_SEC_FIRMWARE_ARMV8_PSCI +/* + * The PSCI_VERSION function is added from PSCI v0.2. When the PSCI + * v0.1 received this function, the NOT_SUPPORTED (0xffff_ffff) error + * number will be returned according to SMC Calling Conventions. But + * when getting the NOT_SUPPORTED error number, we cannot ensure if + * the PSCI version is v0.1 or other error occurred. So, PSCI v0.1 + * won't be supported by this framework. + * And if the secure firmware isn't running, return NOT_SUPPORTED. + * + * The return value on success is PSCI version in format + * major[31:16]:minor[15:0]. + */ +unsigned int sec_firmware_support_psci_version(void) +{ + if (current_el() == SEC_FIRMWARE_TARGET_EL) + return _sec_firmware_support_psci_version(); + + return PSCI_INVALID_VER; +} +#endif + +/* + * Check with sec_firmware if it supports random number generation + * via HW RNG + * + * The return value will be true if it is supported + */ +bool sec_firmware_support_hwrng(void) +{ +#ifdef CONFIG_TFABOOT + /* return true as TFA has one job ring reserved */ + return true; +#endif + if (sec_firmware_addr & SEC_FIRMWARE_RUNNING) { + return true; + } + + return false; +} + +/* + * sec_firmware_get_random - Get a random number from SEC Firmware + * @rand: random number buffer to be filled + * @bytes: Number of bytes of random number to be supported + * @eret: -1 in case of error, 0 for success + */ +int sec_firmware_get_random(uint8_t *rand, int bytes) +{ + unsigned long long num; + struct pt_regs regs; + int param1; + + if (!bytes || bytes > 8) { + printf("Max Random bytes genration supported is 8\n"); + return -1; + } +#define SIP_RNG_64 0xC200FF11 + regs.regs[0] = SIP_RNG_64; + + if (bytes <= 4) + param1 = 0; + else + param1 = 1; + regs.regs[1] = param1; + + smc_call(®s); + + if (regs.regs[0]) + return -1; + + num = regs.regs[1]; + memcpy(rand, &num, bytes); + + return 0; +} + +/* + * sec_firmware_init - Initialize the SEC Firmware + * @sec_firmware_img: the SEC Firmware image address + * @eret_hold_l: the address to hold exception return address low + * @eret_hold_h: the address to hold exception return address high + * @loadable_l: the address to hold loadable address low + * @loadable_h: the address to hold loadable address high + */ +int sec_firmware_init(const void *sec_firmware_img, + u32 *eret_hold_l, + u32 *eret_hold_h, + u32 *loadable_l, + u32 *loadable_h) +{ + int ret; + + if (!sec_firmware_is_valid(sec_firmware_img)) + return -EINVAL; + + ret = sec_firmware_load_image(sec_firmware_img, loadable_l, + loadable_h); + if (ret) { + printf("SEC Firmware: Failed to load image\n"); + return ret; + } else if (sec_firmware_addr & SEC_FIRMWARE_LOADED) { + ret = sec_firmware_entry(eret_hold_l, eret_hold_h); + if (ret) { + printf("SEC Firmware: Failed to initialize\n"); + return ret; + } + } + + debug("SEC Firmware: Return from SEC Firmware: current_el = %d\n", + current_el()); + + /* + * The PE will be turned into target EL when returned from + * SEC Firmware. + */ + if (current_el() != SEC_FIRMWARE_TARGET_EL) + return -EACCES; + + sec_firmware_addr |= SEC_FIRMWARE_RUNNING; + + /* Set exception table and enable caches if it isn't EL3 */ + if (current_el() != 3) { + c_runtime_cpu_setup(); + enable_caches(); + } + + return 0; +} + +/* + * fdt_fix_kaslr - Add kalsr-seed node in Device tree + * @fdt: Device tree + * @eret: 0 in case of error, 1 for success + */ +int fdt_fixup_kaslr(void *fdt) +{ + int nodeoffset; + int err, ret = 0; + u8 rand[8]; + +#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) + /* Check if random seed generation is supported */ + if (sec_firmware_support_hwrng() == false) { + printf("WARNING: SEC firmware not running, no kaslr-seed\n"); + return 0; + } + + ret = sec_firmware_get_random(rand, 8); + if (ret < 0) { + printf("WARNING: No random number to set kaslr-seed\n"); + return 0; + } + + err = fdt_check_header(fdt); + if (err < 0) { + printf("fdt_chosen: %s\n", fdt_strerror(err)); + return 0; + } + + /* find or create "/chosen" node. */ + nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); + if (nodeoffset < 0) + return 0; + + err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", rand, + sizeof(rand)); + if (err < 0) { + printf("WARNING: can't set kaslr-seed %s.\n", + fdt_strerror(err)); + return 0; + } + ret = 1; +#endif + + return ret; +}
diff --git a/arch/arm/cpu/armv8/sec_firmware_asm.S b/arch/arm/cpu/armv8/sec_firmware_asm.S new file mode 100644 index 0000000..af1b2da --- /dev/null +++ b/arch/arm/cpu/armv8/sec_firmware_asm.S
@@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2016 NXP Semiconductor, Inc. + */ + +#include <config.h> +#include <linux/linkage.h> +#include <asm/system.h> +#include <asm/macro.h> + +WEAK(_sec_firmware_entry) + /* + * x0: Secure Firmware entry point + * x1: Exception return address Low + * x2: Exception return address High + */ + + /* Save stack pointer for EL2 */ + mov x3, sp + msr sp_el2, x3 + + /* Set exception return address hold pointer */ + adr x4, 1f + mov x3, x4 +#ifdef CONFIG_ARMV8_SEC_FIRMWARE_ERET_ADDR_REVERT + rev w3, w3 +#endif + str w3, [x1] + lsr x3, x4, #32 +#ifdef CONFIG_ARMV8_SEC_FIRMWARE_ERET_ADDR_REVERT + rev w3, w3 +#endif + str w3, [x2] + + /* Call SEC monitor */ + br x0 + +1: + mov x0, #0 + ret +ENDPROC(_sec_firmware_entry) + +#ifdef CONFIG_SEC_FIRMWARE_ARMV8_PSCI +ENTRY(_sec_firmware_support_psci_version) + mov x0, 0x84000000 + mov x1, 0x0 + mov x2, 0x0 + mov x3, 0x0 + smc #0 + ret +ENDPROC(_sec_firmware_support_psci_version) + +/* + * Switch from AArch64 EL2 to AArch32 EL2 + * @param inputs: + * x0: argument, zero + * x1: machine nr + * x2: fdt address + * x3: input argument + * x4: kernel entry point + * @param outputs for secure firmware: + * x0: function id + * x1: kernel entry point + * x2: machine nr + * x3: fdt address +*/ +ENTRY(armv8_el2_to_aarch32) + mov x3, x2 + mov x2, x1 + mov x1, x4 + ldr x0, =0xc200ff17 + smc #0 + ret +ENDPROC(armv8_el2_to_aarch32) +#endif
diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S new file mode 100644 index 0000000..86de4b4 --- /dev/null +++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#include <linux/linkage.h> +#include <linux/arm-smccc.h> +#include <generated/asm-offsets.h> + + .section .text.efi_runtime + + .macro SMCCC instr + .cfi_startproc + \instr #0 + ldr x4, [sp] + stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS] + stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS] + ldr x4, [sp, #8] + cbz x4, 1f /* no quirk structure */ + ldr x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS] + cmp x9, #ARM_SMCCC_QUIRK_QCOM_A6 + b.ne 1f + str x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS] +1: ret + .cfi_endproc + .endm + +/* + * void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, + * unsigned long a3, unsigned long a4, unsigned long a5, + * unsigned long a6, unsigned long a7, struct arm_smccc_res *res, + * struct arm_smccc_quirk *quirk) + */ +ENTRY(__arm_smccc_smc) + SMCCC smc +ENDPROC(__arm_smccc_smc) + +/* + * void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2, + * unsigned long a3, unsigned long a4, unsigned long a5, + * unsigned long a6, unsigned long a7, struct arm_smccc_res *res, + * struct arm_smccc_quirk *quirk) + */ +ENTRY(__arm_smccc_hvc) + SMCCC hvc +ENDPROC(__arm_smccc_hvc)
diff --git a/arch/arm/cpu/armv8/spin_table.c b/arch/arm/cpu/armv8/spin_table.c new file mode 100644 index 0000000..42a0962 --- /dev/null +++ b/arch/arm/cpu/armv8/spin_table.c
@@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <common.h> +#include <linux/libfdt.h> +#include <asm/spin_table.h> + +int spin_table_update_dt(void *fdt) +{ + int cpus_offset, offset; + const char *prop; + int ret; + unsigned long rsv_addr = (unsigned long)&spin_table_reserve_begin; + unsigned long rsv_size = &spin_table_reserve_end - + &spin_table_reserve_begin; + + cpus_offset = fdt_path_offset(fdt, "/cpus"); + if (cpus_offset < 0) + return -ENODEV; + + for (offset = fdt_first_subnode(fdt, cpus_offset); + offset >= 0; + offset = fdt_next_subnode(fdt, offset)) { + prop = fdt_getprop(fdt, offset, "device_type", NULL); + if (!prop || strcmp(prop, "cpu")) + continue; + + /* + * In the first loop, we check if every CPU node specifies + * spin-table. Otherwise, just return successfully to not + * disturb other methods, like psci. + */ + prop = fdt_getprop(fdt, offset, "enable-method", NULL); + if (!prop || strcmp(prop, "spin-table")) + return 0; + } + + for (offset = fdt_first_subnode(fdt, cpus_offset); + offset >= 0; + offset = fdt_next_subnode(fdt, offset)) { + prop = fdt_getprop(fdt, offset, "device_type", NULL); + if (!prop || strcmp(prop, "cpu")) + continue; + + ret = fdt_setprop_u64(fdt, offset, "cpu-release-addr", + (unsigned long)&spin_table_cpu_release_addr); + if (ret) + return -ENOSPC; + } + + ret = fdt_add_mem_rsv(fdt, rsv_addr, rsv_size); + if (ret) + return -ENOSPC; + + printf(" Reserved memory region for spin-table: addr=%lx size=%lx\n", + rsv_addr, rsv_size); + + return 0; +}
diff --git a/arch/arm/cpu/armv8/spin_table_v8.S b/arch/arm/cpu/armv8/spin_table_v8.S new file mode 100644 index 0000000..6d26843 --- /dev/null +++ b/arch/arm/cpu/armv8/spin_table_v8.S
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + */ + +#include <linux/linkage.h> + +ENTRY(spin_table_secondary_jump) +.globl spin_table_reserve_begin +spin_table_reserve_begin: +0: wfe + ldr x0, spin_table_cpu_release_addr + cbz x0, 0b + br x0 +.globl spin_table_cpu_release_addr + .align 3 +spin_table_cpu_release_addr: + .quad 0 +.globl spin_table_reserve_end +spin_table_reserve_end: +ENDPROC(spin_table_secondary_jump)
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S new file mode 100644 index 0000000..12a78ee --- /dev/null +++ b/arch/arm/cpu/armv8/start.S
@@ -0,0 +1,374 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> +#include <asm/macro.h> +#include <asm/armv8/mmu.h> + +/************************************************************************* + * + * Startup Code (reset vector) + * + *************************************************************************/ + +.globl _start +_start: +#if defined(LINUX_KERNEL_IMAGE_HEADER) +#include <asm/boot0-linux-kernel-header.h> +#elif defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) +/* + * Various SoCs need something special and SoC-specific up front in + * order to boot, allow them to set that in their boot0.h file and then + * use it here. + */ +#include <asm/arch/boot0.h> +#else + b reset +#endif + + .align 3 + +.globl _TEXT_BASE +_TEXT_BASE: + .quad CONFIG_SYS_TEXT_BASE + +/* + * These are defined in the linker script. + */ +.globl _end_ofs +_end_ofs: + .quad _end - _start + +.globl _bss_start_ofs +_bss_start_ofs: + .quad __bss_start - _start + +.globl _bss_end_ofs +_bss_end_ofs: + .quad __bss_end - _start + +reset: + /* Allow the board to save important registers */ + b save_boot_params +.globl save_boot_params_ret +save_boot_params_ret: + +#if CONFIG_POSITION_INDEPENDENT + /* + * Fix .rela.dyn relocations. This allows U-Boot to be loaded to and + * executed at a different address than it was linked at. + */ +pie_fixup: + adr x0, _start /* x0 <- Runtime value of _start */ + ldr x1, _TEXT_BASE /* x1 <- Linked value of _start */ + sub x9, x0, x1 /* x9 <- Run-vs-link offset */ + adr x2, __rel_dyn_start /* x2 <- Runtime &__rel_dyn_start */ + adr x3, __rel_dyn_end /* x3 <- Runtime &__rel_dyn_end */ +pie_fix_loop: + ldp x0, x1, [x2], #16 /* (x0, x1) <- (Link location, fixup) */ + ldr x4, [x2], #8 /* x4 <- addend */ + cmp w1, #1027 /* relative fixup? */ + bne pie_skip_reloc + /* relative fix: store addend plus offset at dest location */ + add x0, x0, x9 + add x4, x4, x9 + str x4, [x0] +pie_skip_reloc: + cmp x2, x3 + b.lo pie_fix_loop +pie_fixup_done: +#endif + +#ifdef CONFIG_SYS_RESET_SCTRL + bl reset_sctrl +#endif + +#if defined(CONFIG_ARMV8__SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD) +.macro set_vbar, regname, reg + msr \regname, \reg +.endm + adr x0, vectors +#else +.macro set_vbar, regname, reg +.endm +#endif + /* + * Could be EL3/EL2/EL1, Initial State: + * Little Endian, MMU Disabled, i/dCache Disabled + */ + switch_el x1, 3f, 2f, 1f +3: set_vbar vbar_el3, x0 + mrs x0, scr_el3 + orr x0, x0, #0xf /* SCR_EL3.NS|IRQ|FIQ|EA */ + msr scr_el3, x0 + msr cptr_el3, xzr /* Enable FP/SIMD */ +#ifdef COUNTER_FREQUENCY + ldr x0, =COUNTER_FREQUENCY + msr cntfrq_el0, x0 /* Initialize CNTFRQ */ +#endif + b 0f +2: set_vbar vbar_el2, x0 + mov x0, #0x33ff + msr cptr_el2, x0 /* Enable FP/SIMD */ + b 0f +1: set_vbar vbar_el1, x0 + mov x0, #3 << 20 + msr cpacr_el1, x0 /* Enable FP/SIMD */ +0: + + /* + * Enable SMPEN bit for coherency. + * This register is not architectural but at the moment + * this bit should be set for A53/A57/A72. + */ +#ifdef CONFIG_ARMV8_SET_SMPEN + switch_el x1, 3f, 1f, 1f +3: + mrs x0, S3_1_c15_c2_1 /* cpuectlr_el1 */ + orr x0, x0, #0x40 + msr S3_1_c15_c2_1, x0 +1: +#endif + + /* Apply ARM core specific erratas */ + bl apply_core_errata + + /* + * Cache/BPB/TLB Invalidate + * i-cache is invalidated before enabled in icache_enable() + * tlb is invalidated before mmu is enabled in dcache_enable() + * d-cache is invalidated before enabled in dcache_enable() + */ + + /* Processor specific initialization */ + bl lowlevel_init + +#if defined(CONFIG_ARMV8_SPIN_TABLE) && !defined(CONFIG_SPL_BUILD) + branch_if_master x0, x1, master_cpu + b spin_table_secondary_jump + /* never return */ +#elif defined(CONFIG_ARMV8_MULTIENTRY) + branch_if_master x0, x1, master_cpu + + /* + * Slave CPUs + */ +slave_cpu: + wfe + ldr x1, =CPU_RELEASE_ADDR + ldr x0, [x1] + cbz x0, slave_cpu + br x0 /* branch to the given address */ +#endif /* CONFIG_ARMV8_MULTIENTRY */ +master_cpu: + bl _main + +#ifdef CONFIG_SYS_RESET_SCTRL +reset_sctrl: + switch_el x1, 3f, 2f, 1f +3: + mrs x0, sctlr_el3 + b 0f +2: + mrs x0, sctlr_el2 + b 0f +1: + mrs x0, sctlr_el1 + +0: + ldr x1, =0xfdfffffa + and x0, x0, x1 + + switch_el x1, 6f, 5f, 4f +6: + msr sctlr_el3, x0 + b 7f +5: + msr sctlr_el2, x0 + b 7f +4: + msr sctlr_el1, x0 + +7: + dsb sy + isb + b __asm_invalidate_tlb_all + ret +#endif + +/*-----------------------------------------------------------------------*/ + +WEAK(apply_core_errata) + + mov x29, lr /* Save LR */ + /* For now, we support Cortex-A53, Cortex-A57 specific errata */ + + /* Check if we are running on a Cortex-A53 core */ + branch_if_a53_core x0, apply_a53_core_errata + + /* Check if we are running on a Cortex-A57 core */ + branch_if_a57_core x0, apply_a57_core_errata +0: + mov lr, x29 /* Restore LR */ + ret + +apply_a53_core_errata: + +#ifdef CONFIG_ARM_ERRATA_855873 + mrs x0, midr_el1 + tst x0, #(0xf << 20) + b.ne 0b + + mrs x0, midr_el1 + and x0, x0, #0xf + cmp x0, #3 + b.lt 0b + + mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */ + /* Enable data cache clean as data cache clean/invalidate */ + orr x0, x0, #1 << 44 + msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */ +#endif + b 0b + +apply_a57_core_errata: + +#ifdef CONFIG_ARM_ERRATA_828024 + mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */ + /* Disable non-allocate hint of w-b-n-a memory type */ + orr x0, x0, #1 << 49 + /* Disable write streaming no L1-allocate threshold */ + orr x0, x0, #3 << 25 + /* Disable write streaming no-allocate threshold */ + orr x0, x0, #3 << 27 + msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */ +#endif + +#ifdef CONFIG_ARM_ERRATA_826974 + mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */ + /* Disable speculative load execution ahead of a DMB */ + orr x0, x0, #1 << 59 + msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */ +#endif + +#ifdef CONFIG_ARM_ERRATA_833471 + mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */ + /* FPSCR write flush. + * Note that in some cases where a flush is unnecessary this + could impact performance. */ + orr x0, x0, #1 << 38 + msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */ +#endif + +#ifdef CONFIG_ARM_ERRATA_829520 + mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */ + /* Disable Indirect Predictor bit will prevent this erratum + from occurring + * Note that in some cases where a flush is unnecessary this + could impact performance. */ + orr x0, x0, #1 << 4 + msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */ +#endif + +#ifdef CONFIG_ARM_ERRATA_833069 + mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */ + /* Disable Enable Invalidates of BTB bit */ + and x0, x0, #0xE + msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */ +#endif + b 0b +ENDPROC(apply_core_errata) + +/*-----------------------------------------------------------------------*/ + +WEAK(lowlevel_init) + mov x29, lr /* Save LR */ + +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) + branch_if_slave x0, 1f + ldr x0, =GICD_BASE + bl gic_init_secure +1: +#if defined(CONFIG_GICV3) + ldr x0, =GICR_BASE + bl gic_init_secure_percpu +#elif defined(CONFIG_GICV2) + ldr x0, =GICD_BASE + ldr x1, =GICC_BASE + bl gic_init_secure_percpu +#endif +#endif + +#ifdef CONFIG_ARMV8_MULTIENTRY + branch_if_master x0, x1, 2f + + /* + * Slave should wait for master clearing spin table. + * This sync prevent salves observing incorrect + * value of spin table and jumping to wrong place. + */ +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) +#ifdef CONFIG_GICV2 + ldr x0, =GICC_BASE +#endif + bl gic_wait_for_interrupt +#endif + + /* + * All slaves will enter EL2 and optionally EL1. + */ + adr x4, lowlevel_in_el2 + ldr x5, =ES_TO_AARCH64 + bl armv8_switch_to_el2 + +lowlevel_in_el2: +#ifdef CONFIG_ARMV8_SWITCH_TO_EL1 + adr x4, lowlevel_in_el1 + ldr x5, =ES_TO_AARCH64 + bl armv8_switch_to_el1 + +lowlevel_in_el1: +#endif + +#endif /* CONFIG_ARMV8_MULTIENTRY */ + +2: + mov lr, x29 /* Restore LR */ + ret +ENDPROC(lowlevel_init) + +WEAK(smp_kick_all_cpus) + /* Kick secondary cpus up by SGI 0 interrupt */ +#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) + ldr x0, =GICD_BASE + b gic_kick_secondary_cpus +#endif + ret +ENDPROC(smp_kick_all_cpus) + +/*-----------------------------------------------------------------------*/ + +ENTRY(c_runtime_cpu_setup) +#if defined(CONFIG_ARMV8__SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD) + /* Relocate vBAR */ + adr x0, vectors + switch_el x1, 3f, 2f, 1f +3: msr vbar_el3, x0 + b 0f +2: msr vbar_el2, x0 + b 0f +1: msr vbar_el1, x0 +0: +#endif + + ret +ENDPROC(c_runtime_cpu_setup) + +WEAK(save_boot_params) + b save_boot_params_ret /* back to my caller */ +ENDPROC(save_boot_params)
diff --git a/arch/arm/cpu/armv8/tlb.S b/arch/arm/cpu/armv8/tlb.S new file mode 100644 index 0000000..46a0d7d --- /dev/null +++ b/arch/arm/cpu/armv8/tlb.S
@@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> +#include <asm/macro.h> + +/* + * void __asm_invalidate_tlb_all(void) + * + * invalidate all tlb entries. +*/ +.pushsection .text.__asm_invalidate_tlb_all, "ax" +ENTRY(__asm_invalidate_tlb_all) + switch_el x9, 3f, 2f, 1f +3: tlbi alle3 + dsb sy + isb + b 0f +2: tlbi alle2 + dsb sy + isb + b 0f +1: tlbi vmalle1 + dsb sy + isb +0: + ret +ENDPROC(__asm_invalidate_tlb_all) +.popsection
diff --git a/arch/arm/cpu/armv8/transition.S b/arch/arm/cpu/armv8/transition.S new file mode 100644 index 0000000..a31af4f --- /dev/null +++ b/arch/arm/cpu/armv8/transition.S
@@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> +#include <asm/macro.h> + +.pushsection .text.armv8_switch_to_el2, "ax" +ENTRY(armv8_switch_to_el2) + switch_el x6, 1f, 0f, 0f +0: + cmp x5, #ES_TO_AARCH64 + b.eq 2f + /* + * When loading 32-bit kernel, it will jump + * to secure firmware again, and never return. + */ + bl armv8_el2_to_aarch32 +2: + /* + * x4 is kernel entry point or switch_to_el1 + * if CONFIG_ARMV8_SWITCH_TO_EL1 is defined. + * When running in EL2 now, jump to the + * address saved in x4. + */ + br x4 +1: armv8_switch_to_el2_m x4, x5, x6 +ENDPROC(armv8_switch_to_el2) +.popsection + +.pushsection .text.armv8_switch_to_el1, "ax" +ENTRY(armv8_switch_to_el1) + switch_el x6, 0f, 1f, 0f +0: + /* x4 is kernel entry point. When running in EL1 + * now, jump to the address saved in x4. + */ + br x4 +1: armv8_switch_to_el1_m x4, x5, x6 +ENDPROC(armv8_switch_to_el1) +.popsection + +.pushsection .text.armv8_el2_to_aarch32, "ax" +WEAK(armv8_el2_to_aarch32) + ret +ENDPROC(armv8_el2_to_aarch32) +.popsection
diff --git a/arch/arm/cpu/armv8/u-boot-spl.lds b/arch/arm/cpu/armv8/u-boot-spl.lds new file mode 100644 index 0000000..4e48da5 --- /dev/null +++ b/arch/arm/cpu/armv8/u-boot-spl.lds
@@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V <aneesh@ti.com> + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE, + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SECTIONS +{ + .text : { + . = ALIGN(8); + *(.__image_copy_start) + CPUDIR/start.o (.text*) + *(.text*) + } >.sram + + .rodata : { + . = ALIGN(8); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } >.sram + + .data : { + . = ALIGN(8); + *(.data*) + } >.sram + + .u_boot_list : { + . = ALIGN(8); + KEEP(*(SORT(.u_boot_list*))); + } >.sram + + .image_copy_end : { + . = ALIGN(8); + *(.__image_copy_end) + } >.sram + + .end : { + . = ALIGN(8); + *(.__end) + } >.sram + + _image_binary_end = .; + + .bss_start (NOLOAD) : { + . = ALIGN(8); + KEEP(*(.__bss_start)); + } >.sdram + + .bss (NOLOAD) : { + *(.bss*) + . = ALIGN(8); + } >.sdram + + .bss_end (NOLOAD) : { + KEEP(*(.__bss_end)); + } >.sdram + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +}
diff --git a/arch/arm/cpu/armv8/u-boot.lds b/arch/arm/cpu/armv8/u-boot.lds new file mode 100644 index 0000000..53de80f --- /dev/null +++ b/arch/arm/cpu/armv8/u-boot.lds
@@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2013 + * David Feng <fenghua@phytium.com.cn> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +#include <config.h> +#include <asm/psci.h> + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SECTIONS +{ +#ifdef CONFIG_ARMV8_SECURE_BASE + /DISCARD/ : { *(.rela._secure*) } +#endif + . = 0x00000000; + + . = ALIGN(8); + .text : + { + *(.__image_copy_start) + CPUDIR/start.o (.text*) + } + + /* This needs to come before *(.text*) */ + .efi_runtime : { + __efi_runtime_start = .; + *(.text.efi_runtime*) + *(.rodata.efi_runtime*) + *(.data.efi_runtime*) + __efi_runtime_stop = .; + } + + .text_rest : + { + *(.text*) + } + +#ifdef CONFIG_ARMV8_PSCI + .__secure_start : +#ifndef CONFIG_ARMV8_SECURE_BASE + ALIGN(CONSTANT(COMMONPAGESIZE)) +#endif + { + KEEP(*(.__secure_start)) + } + +#ifndef CONFIG_ARMV8_SECURE_BASE +#define CONFIG_ARMV8_SECURE_BASE +#define __ARMV8_PSCI_STACK_IN_RAM +#endif + .secure_text CONFIG_ARMV8_SECURE_BASE : + AT(ADDR(.__secure_start) + SIZEOF(.__secure_start)) + { + *(._secure.text) + } + + .secure_data : AT(LOADADDR(.secure_text) + SIZEOF(.secure_text)) + { + *(._secure.data) + } + + .secure_stack ALIGN(ADDR(.secure_data) + SIZEOF(.secure_data), + CONSTANT(COMMONPAGESIZE)) (NOLOAD) : +#ifdef __ARMV8_PSCI_STACK_IN_RAM + AT(ADDR(.secure_stack)) +#else + AT(LOADADDR(.secure_data) + SIZEOF(.secure_data)) +#endif + { + KEEP(*(.__secure_stack_start)) + + . = . + CONFIG_ARMV8_PSCI_NR_CPUS * ARM_PSCI_STACK_SIZE; + + . = ALIGN(CONSTANT(COMMONPAGESIZE)); + + KEEP(*(.__secure_stack_end)) + } + +#ifndef __ARMV8_PSCI_STACK_IN_RAM + . = LOADADDR(.secure_stack); +#endif + + .__secure_end : AT(ADDR(.__secure_end)) { + KEEP(*(.__secure_end)) + LONG(0x1d1071c); /* Must output something to reset LMA */ + } +#endif + + . = ALIGN(8); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(8); + .data : { + *(.data*) + } + + . = ALIGN(8); + + . = .; + + . = ALIGN(8); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(8); + + .efi_runtime_rel : { + __efi_runtime_rel_start = .; + *(.rel*.efi_runtime) + *(.rel*.efi_runtime.*) + __efi_runtime_rel_stop = .; + } + + . = ALIGN(8); + + .image_copy_end : + { + *(.__image_copy_end) + } + + . = ALIGN(8); + + .rel_dyn_start : + { + *(.__rel_dyn_start) + } + + .rela.dyn : { + *(.rela*) + } + + .rel_dyn_end : + { + *(.__rel_dyn_end) + } + + _end = .; + + . = ALIGN(8); + + .bss_start : { + KEEP(*(.__bss_start)); + } + + .bss : { + *(.bss*) + . = ALIGN(8); + } + + .bss_end : { + KEEP(*(.__bss_end)); + } + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } + +#ifdef CONFIG_LINUX_KERNEL_IMAGE_HEADER +#include "linux-kernel-image-header-vars.h" +#endif +}
diff --git a/arch/arm/cpu/armv8/zynqmp/Kconfig b/arch/arm/cpu/armv8/zynqmp/Kconfig new file mode 100644 index 0000000..91b017a --- /dev/null +++ b/arch/arm/cpu/armv8/zynqmp/Kconfig
@@ -0,0 +1,157 @@ +if ARCH_ZYNQMP + +config SPL_FAT_SUPPORT + default y + +config SPL_LIBCOMMON_SUPPORT + default y + +config SPL_LIBDISK_SUPPORT + default y + +config SPL_LIBGENERIC_SUPPORT + default y + +config SPL_MMC_SUPPORT + default y if MMC_SDHCI_ZYNQ + +config SPL_SERIAL_SUPPORT + default y + +config SPL_SPI_FLASH_SUPPORT + default y if ZYNQ_QSPI + +config SPL_SPI_SUPPORT + default y if ZYNQ_QSPI + +config SYS_BOARD + default "zynqmp" + +config SYS_VENDOR + string "Vendor name" + default "xilinx" + +config SYS_SOC + default "zynqmp" + +config SYS_CONFIG_NAME + string "Board configuration name" + default "xilinx_zynqmp" + help + This option contains information about board configuration name. + Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header + will be used for board configuration. + +config SYS_MEM_RSVD_FOR_MMU + bool "Reserve memory for MMU Table" + help + If defined this option is used to setup different space for + MMU table than the one which will be allocated during + relocation. + +config BOOT_INIT_FILE + string "boot.bin init register filename" + depends on SPL + default "" + help + Add register writes to boot.bin format (max 256 pairs). + Expect a table of register-value pairs, e.g. "0x12345678 0x4321" + +config PMUFW_INIT_FILE + string "PMU firmware" + depends on SPL + default "" + help + Include external PMUFW (Platform Management Unit FirmWare) to + a Xilinx bootable image (boot.bin). + +config ZYNQMP_USB + bool "Configure ZynqMP USB" + +config ZYNQMP_NO_DDR + bool "Disable DDR MMU mapping" + help + This option configures MMU with no DDR to avoid speculative + access to DDR memory where DDR is not present. + +config SYS_MALLOC_F_LEN + default 0x600 + +config DEFINE_TCM_OCM_MMAP + bool "Define TCM and OCM memory in MMU Table" + default y if MP + help + This option if enabled defines the TCM and OCM memory and its + memory attributes in MMU table entry. + +config ZYNQMP_PSU_INIT_ENABLED + bool "Include psu_init" + help + Include psu_init to full u-boot. SPL include psu_init by default. + +config SPL_ZYNQMP_ALT_BOOTMODE_ENABLED + bool "Overwrite SPL bootmode" + depends on SPL + help + Overwrite bootmode selected via boot mode pins to tell SPL what should + be the next boot device. + +config ZYNQ_SDHCI_MAX_FREQ + default 200000000 + +config SPL_ZYNQMP_ALT_BOOTMODE + hex + default 0x0 if JTAG_MODE + default 0x1 if QSPI_MODE_24BIT + default 0x2 if QSPI_MODE_32BIT + default 0x3 if SD_MODE + default 0x4 if NAND_MODE + default 0x5 if SD_MODE1 + default 0x6 if EMMC_MODE + default 0x7 if USB_MODE + default 0xa if SW_USBHOST_MODE + default 0xb if SW_SATA_MODE + default 0xe if SD1_LSHFT_MODE + +choice + prompt "Boot mode" + depends on SPL_ZYNQMP_ALT_BOOTMODE_ENABLED + default JTAG_MODE + +config JTAG_MODE + bool "JTAG_MODE" + +config QSPI_MODE_24BIT + bool "QSPI_MODE_24BIT" + +config QSPI_MODE_32BIT + bool "QSPI_MODE_32BIT" + +config SD_MODE + bool "SD_MODE" + +config SD_MODE1 + bool "SD_MODE1" + +config NAND_MODE + bool "NAND_MODE" + +config EMMC_MODE + bool "EMMC_MODE" + +config USB_MODE + bool "USB" + +config SW_USBHOST_MODE + bool "SW USBHOST_MODE" + +config SW_SATA_MODE + bool "SW SATA_MODE" + +config SD1_LSHFT_MODE + bool "SD1_LSHFT_MODE" + +endchoice + +endif +
diff --git a/arch/arm/cpu/armv8/zynqmp/Makefile b/arch/arm/cpu/armv8/zynqmp/Makefile new file mode 100644 index 0000000..8a3b074 --- /dev/null +++ b/arch/arm/cpu/armv8/zynqmp/Makefile
@@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2014 - 2015 Xilinx, Inc. +# Michal Simek <michal.simek@xilinx.com> + +obj-y += clk.o +obj-y += cpu.o +obj-$(CONFIG_MP) += mp.o +obj-$(CONFIG_SPL_BUILD) += spl.o handoff.o +obj-$(CONFIG_ZYNQMP_PSU_INIT_ENABLED) += psu_spl_init.o
diff --git a/arch/arm/cpu/armv8/zynqmp/clk.c b/arch/arm/cpu/armv8/zynqmp/clk.c new file mode 100644 index 0000000..0593b63 --- /dev/null +++ b/arch/arm/cpu/armv8/zynqmp/clk.c
@@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2014 - 2015 Xilinx, Inc. + * Michal Simek <michal.simek@xilinx.com> + */ + +#include <common.h> +#include <asm/arch/clk.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> + +DECLARE_GLOBAL_DATA_PTR; + +unsigned long zynqmp_get_system_timer_freq(void) +{ + u32 ver = zynqmp_get_silicon_version(); + + switch (ver) { + case ZYNQMP_CSU_VERSION_QEMU: + return 50000000; + } + + return 100000000; +} + +#ifdef CONFIG_CLOCKS +/** + * set_cpu_clk_info() - Initialize clock framework + * Always returns zero. + * + * This function is called from common code after relocation and sets up the + * clock framework. The framework must not be used before this function had been + * called. + */ +int set_cpu_clk_info(void) +{ + gd->cpu_clk = get_tbclk(); + + gd->bd->bi_arm_freq = gd->cpu_clk / 1000000; + + gd->bd->bi_dsp_freq = 0; + + return 0; +} +#endif
diff --git a/arch/arm/cpu/armv8/zynqmp/cpu.c b/arch/arm/cpu/armv8/zynqmp/cpu.c new file mode 100644 index 0000000..4ee8e3f --- /dev/null +++ b/arch/arm/cpu/armv8/zynqmp/cpu.c
@@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2014 - 2015 Xilinx, Inc. + * Michal Simek <michal.simek@xilinx.com> + */ + +#include <common.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> +#include <asm/armv8/mmu.h> +#include <asm/io.h> + +#define ZYNQ_SILICON_VER_MASK 0xF000 +#define ZYNQ_SILICON_VER_SHIFT 12 + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Number of filled static entries and also the first empty + * slot in zynqmp_mem_map. + */ +#define ZYNQMP_MEM_MAP_USED 4 + +#if !defined(CONFIG_ZYNQMP_NO_DDR) +#define DRAM_BANKS CONFIG_NR_DRAM_BANKS +#else +#define DRAM_BANKS 0 +#endif + +#if defined(CONFIG_DEFINE_TCM_OCM_MMAP) +#define TCM_MAP 1 +#else +#define TCM_MAP 0 +#endif + +/* +1 is end of list which needs to be empty */ +#define ZYNQMP_MEM_MAP_MAX (ZYNQMP_MEM_MAP_USED + DRAM_BANKS + TCM_MAP + 1) + +static struct mm_region zynqmp_mem_map[ZYNQMP_MEM_MAP_MAX] = { + { + .virt = 0x80000000UL, + .phys = 0x80000000UL, + .size = 0x70000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + .virt = 0xf8000000UL, + .phys = 0xf8000000UL, + .size = 0x07e00000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + .virt = 0x400000000UL, + .phys = 0x400000000UL, + .size = 0x400000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + .virt = 0x1000000000UL, + .phys = 0x1000000000UL, + .size = 0xf000000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + } +}; + +void mem_map_fill(void) +{ + int banks = ZYNQMP_MEM_MAP_USED; + +#if defined(CONFIG_DEFINE_TCM_OCM_MMAP) + zynqmp_mem_map[banks].virt = 0xffe00000UL; + zynqmp_mem_map[banks].phys = 0xffe00000UL; + zynqmp_mem_map[banks].size = 0x00200000UL; + zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE; + banks = banks + 1; +#endif + +#if !defined(CONFIG_ZYNQMP_NO_DDR) + for (int i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + /* Zero size means no more DDR that's this is end */ + if (!gd->bd->bi_dram[i].size) + break; + + zynqmp_mem_map[banks].virt = gd->bd->bi_dram[i].start; + zynqmp_mem_map[banks].phys = gd->bd->bi_dram[i].start; + zynqmp_mem_map[banks].size = gd->bd->bi_dram[i].size; + zynqmp_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE; + banks = banks + 1; + } +#endif +} + +struct mm_region *mem_map = zynqmp_mem_map; + +u64 get_page_table_size(void) +{ + return 0x14000; +} + +#if defined(CONFIG_SYS_MEM_RSVD_FOR_MMU) || defined(CONFIG_DEFINE_TCM_OCM_MMAP) +void tcm_init(u8 mode) +{ + puts("WARNING: Initializing TCM overwrites TCM content\n"); + initialize_tcm(mode); + memset((void *)ZYNQMP_TCM_BASE_ADDR, 0, ZYNQMP_TCM_SIZE); +} +#endif + +#ifdef CONFIG_SYS_MEM_RSVD_FOR_MMU +int reserve_mmu(void) +{ + tcm_init(TCM_LOCK); + gd->arch.tlb_size = PGTABLE_SIZE; + gd->arch.tlb_addr = ZYNQMP_TCM_BASE_ADDR; + + return 0; +} +#endif + +static unsigned int zynqmp_get_silicon_version_secure(void) +{ + u32 ver; + + ver = readl(&csu_base->version); + ver &= ZYNQMP_SILICON_VER_MASK; + ver >>= ZYNQMP_SILICON_VER_SHIFT; + + return ver; +} + +unsigned int zynqmp_get_silicon_version(void) +{ + if (current_el() == 3) + return zynqmp_get_silicon_version_secure(); + + gd->cpu_clk = get_tbclk(); + + switch (gd->cpu_clk) { + case 50000000: + return ZYNQMP_CSU_VERSION_QEMU; + } + + return ZYNQMP_CSU_VERSION_SILICON; +} + +#define ZYNQMP_MMIO_READ 0xC2000014 +#define ZYNQMP_MMIO_WRITE 0xC2000013 + +int __maybe_unused invoke_smc(u32 pm_api_id, u32 arg0, u32 arg1, u32 arg2, + u32 arg3, u32 *ret_payload) +{ + /* + * Added SIP service call Function Identifier + * Make sure to stay in x0 register + */ + struct pt_regs regs; + + regs.regs[0] = pm_api_id; + regs.regs[1] = ((u64)arg1 << 32) | arg0; + regs.regs[2] = ((u64)arg3 << 32) | arg2; + + smc_call(®s); + + if (ret_payload != NULL) { + ret_payload[0] = (u32)regs.regs[0]; + ret_payload[1] = upper_32_bits(regs.regs[0]); + ret_payload[2] = (u32)regs.regs[1]; + ret_payload[3] = upper_32_bits(regs.regs[1]); + ret_payload[4] = (u32)regs.regs[2]; + } + + return regs.regs[0]; +} + +#if defined(CONFIG_CLK_ZYNQMP) +unsigned int zynqmp_pmufw_version(void) +{ + int ret; + u32 ret_payload[PAYLOAD_ARG_CNT]; + static u32 pm_api_version = ZYNQMP_PM_VERSION_INVALID; + + /* + * Get PMU version only once and later + * just return stored values instead of + * asking PMUFW again. + */ + if (pm_api_version == ZYNQMP_PM_VERSION_INVALID) { + ret = invoke_smc(ZYNQMP_SIP_SVC_GET_API_VERSION, 0, 0, 0, 0, + ret_payload); + pm_api_version = ret_payload[1]; + + if (ret) + panic("PMUFW is not found - Please load it!\n"); + } + + return pm_api_version; +} +#endif + +static int zynqmp_mmio_rawwrite(const u32 address, + const u32 mask, + const u32 value) +{ + u32 data; + u32 value_local = value; + int ret; + + ret = zynqmp_mmio_read(address, &data); + if (ret) + return ret; + + data &= ~mask; + value_local &= mask; + value_local |= data; + writel(value_local, (ulong)address); + return 0; +} + +static int zynqmp_mmio_rawread(const u32 address, u32 *value) +{ + *value = readl((ulong)address); + return 0; +} + +int zynqmp_mmio_write(const u32 address, + const u32 mask, + const u32 value) +{ + if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) + return zynqmp_mmio_rawwrite(address, mask, value); + else + return invoke_smc(ZYNQMP_MMIO_WRITE, address, mask, + value, 0, NULL); + + return -EINVAL; +} + +int zynqmp_mmio_read(const u32 address, u32 *value) +{ + u32 ret_payload[PAYLOAD_ARG_CNT]; + u32 ret; + + if (!value) + return -EINVAL; + + if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) { + ret = zynqmp_mmio_rawread(address, value); + } else { + ret = invoke_smc(ZYNQMP_MMIO_READ, address, 0, 0, + 0, ret_payload); + *value = ret_payload[1]; + } + + return ret; +}
diff --git a/arch/arm/cpu/armv8/zynqmp/handoff.c b/arch/arm/cpu/armv8/zynqmp/handoff.c new file mode 100644 index 0000000..f71ff7b --- /dev/null +++ b/arch/arm/cpu/armv8/zynqmp/handoff.c
@@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2016 - 2017 Xilinx, Inc. + * + * Michal Simek <michal.simek@xilinx.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> + +/* + * atfhandoffparams + * Parameter bitfield encoding + * ----------------------------------------------------------------------------- + * Exec State 0 0 -> Aarch64, 1-> Aarch32 + * endianness 1 0 -> LE, 1 -> BE + * secure (TZ) 2 0 -> Non secure, 1 -> secure + * EL 3:4 00 -> EL0, 01 -> EL1, 10 -> EL2, 11 -> EL3 + * CPU# 5:6 00 -> A53_0, 01 -> A53_1, 10 -> A53_2, 11 -> A53_3 + */ + +#define FSBL_FLAGS_ESTATE_SHIFT 0 +#define FSBL_FLAGS_ESTATE_MASK (1 << FSBL_FLAGS_ESTATE_SHIFT) +#define FSBL_FLAGS_ESTATE_A64 0 +#define FSBL_FLAGS_ESTATE_A32 1 + +#define FSBL_FLAGS_ENDIAN_SHIFT 1 +#define FSBL_FLAGS_ENDIAN_MASK (1 << FSBL_FLAGS_ENDIAN_SHIFT) +#define FSBL_FLAGS_ENDIAN_LE 0 +#define FSBL_FLAGS_ENDIAN_BE 1 + +#define FSBL_FLAGS_TZ_SHIFT 2 +#define FSBL_FLAGS_TZ_MASK (1 << FSBL_FLAGS_TZ_SHIFT) +#define FSBL_FLAGS_NON_SECURE 0 +#define FSBL_FLAGS_SECURE 1 + +#define FSBL_FLAGS_EL_SHIFT 3 +#define FSBL_FLAGS_EL_MASK (3 << FSBL_FLAGS_EL_SHIFT) +#define FSBL_FLAGS_EL0 0 +#define FSBL_FLAGS_EL1 1 +#define FSBL_FLAGS_EL2 2 +#define FSBL_FLAGS_EL3 3 + +#define FSBL_FLAGS_CPU_SHIFT 5 +#define FSBL_FLAGS_CPU_MASK (3 << FSBL_FLAGS_CPU_SHIFT) +#define FSBL_FLAGS_A53_0 0 +#define FSBL_FLAGS_A53_1 1 +#define FSBL_FLAGS_A53_2 2 +#define FSBL_FLAGS_A53_3 3 + +#define FSBL_MAX_PARTITIONS 8 + +/* Structure corresponding to each partition entry */ +struct xfsbl_partition { + uint64_t entry_point; + uint64_t flags; +}; + +/* Structure for handoff parameters to ARM Trusted Firmware (ATF) */ +struct xfsbl_atf_handoff_params { + uint8_t magic[4]; + uint32_t num_entries; + struct xfsbl_partition partition[FSBL_MAX_PARTITIONS]; +}; + +#ifdef CONFIG_SPL_OS_BOOT +void handoff_setup(void) +{ + struct xfsbl_atf_handoff_params *atfhandoffparams; + + atfhandoffparams = (void *)CONFIG_SPL_TEXT_BASE; + atfhandoffparams->magic[0] = 'X'; + atfhandoffparams->magic[1] = 'L'; + atfhandoffparams->magic[2] = 'N'; + atfhandoffparams->magic[3] = 'X'; + + atfhandoffparams->num_entries = 1; + atfhandoffparams->partition[0].entry_point = CONFIG_SYS_TEXT_BASE; + atfhandoffparams->partition[0].flags = FSBL_FLAGS_EL2 << + FSBL_FLAGS_EL_SHIFT; + + writel(CONFIG_SPL_TEXT_BASE, &pmu_base->gen_storage6); +} +#endif
diff --git a/arch/arm/cpu/armv8/zynqmp/mp.c b/arch/arm/cpu/armv8/zynqmp/mp.c new file mode 100644 index 0000000..2a71870 --- /dev/null +++ b/arch/arm/cpu/armv8/zynqmp/mp.c
@@ -0,0 +1,297 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2014 - 2015 Xilinx, Inc. + * Michal Simek <michal.simek@xilinx.com> + */ + +#include <common.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> + +#define LOCK 0 +#define SPLIT 1 + +#define HALT 0 +#define RELEASE 1 + +#define ZYNQMP_BOOTADDR_HIGH_MASK 0xFFFFFFFF +#define ZYNQMP_R5_HIVEC_ADDR 0xFFFF0000 +#define ZYNQMP_R5_LOVEC_ADDR 0x0 +#define ZYNQMP_RPU_CFG_CPU_HALT_MASK 0x01 +#define ZYNQMP_RPU_CFG_HIVEC_MASK 0x04 +#define ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK 0x08 +#define ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK 0x40 +#define ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK 0x10 + +#define ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK 0x04 +#define ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK 0x01 +#define ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK 0x02 +#define ZYNQMP_CRLAPB_CPU_R5_CTRL_CLKACT_MASK 0x1000000 + +#define ZYNQMP_TCM_START_ADDRESS 0xFFE00000 +#define ZYNQMP_TCM_BOTH_SIZE 0x40000 + +#define ZYNQMP_CORE_APU0 0 +#define ZYNQMP_CORE_APU3 3 + +#define ZYNQMP_MAX_CORES 6 + +int is_core_valid(unsigned int core) +{ + if (core < ZYNQMP_MAX_CORES) + return 1; + + return 0; +} + +int cpu_reset(u32 nr) +{ + puts("Feature is not implemented.\n"); + return 0; +} + +static void set_r5_halt_mode(u8 halt, u8 mode) +{ + u32 tmp; + + tmp = readl(&rpu_base->rpu0_cfg); + if (halt == HALT) + tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK; + else + tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK; + writel(tmp, &rpu_base->rpu0_cfg); + + if (mode == LOCK) { + tmp = readl(&rpu_base->rpu1_cfg); + if (halt == HALT) + tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK; + else + tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK; + writel(tmp, &rpu_base->rpu1_cfg); + } +} + +static void set_r5_tcm_mode(u8 mode) +{ + u32 tmp; + + tmp = readl(&rpu_base->rpu_glbl_ctrl); + if (mode == LOCK) { + tmp &= ~ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK; + tmp |= ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK | + ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK; + } else { + tmp |= ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK; + tmp &= ~(ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK | + ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK); + } + + writel(tmp, &rpu_base->rpu_glbl_ctrl); +} + +static void set_r5_reset(u8 mode) +{ + u32 tmp; + + tmp = readl(&crlapb_base->rst_lpd_top); + tmp |= (ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK | + ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK); + + if (mode == LOCK) + tmp |= ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK; + + writel(tmp, &crlapb_base->rst_lpd_top); +} + +static void release_r5_reset(u8 mode) +{ + u32 tmp; + + tmp = readl(&crlapb_base->rst_lpd_top); + tmp &= ~(ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK | + ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK); + + if (mode == LOCK) + tmp &= ~ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK; + + writel(tmp, &crlapb_base->rst_lpd_top); +} + +static void enable_clock_r5(void) +{ + u32 tmp; + + tmp = readl(&crlapb_base->cpu_r5_ctrl); + tmp |= ZYNQMP_CRLAPB_CPU_R5_CTRL_CLKACT_MASK; + writel(tmp, &crlapb_base->cpu_r5_ctrl); + + /* Give some delay for clock + * to propagate */ + udelay(0x500); +} + +int cpu_disable(u32 nr) +{ + if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) { + u32 val = readl(&crfapb_base->rst_fpd_apu); + val |= 1 << nr; + writel(val, &crfapb_base->rst_fpd_apu); + } else { + set_r5_reset(LOCK); + } + + return 0; +} + +int cpu_status(u32 nr) +{ + if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) { + u32 addr_low = readl(((u8 *)&apu_base->rvbar_addr0_l) + nr * 8); + u32 addr_high = readl(((u8 *)&apu_base->rvbar_addr0_h) + + nr * 8); + u32 val = readl(&crfapb_base->rst_fpd_apu); + val &= 1 << nr; + printf("APU CPU%d %s - starting address HI: %x, LOW: %x\n", + nr, val ? "OFF" : "ON" , addr_high, addr_low); + } else { + u32 val = readl(&crlapb_base->rst_lpd_top); + val &= 1 << (nr - 4); + printf("RPU CPU%d %s\n", nr - 4, val ? "OFF" : "ON"); + } + + return 0; +} + +static void set_r5_start(u8 high) +{ + u32 tmp; + + tmp = readl(&rpu_base->rpu0_cfg); + if (high) + tmp |= ZYNQMP_RPU_CFG_HIVEC_MASK; + else + tmp &= ~ZYNQMP_RPU_CFG_HIVEC_MASK; + writel(tmp, &rpu_base->rpu0_cfg); + + tmp = readl(&rpu_base->rpu1_cfg); + if (high) + tmp |= ZYNQMP_RPU_CFG_HIVEC_MASK; + else + tmp &= ~ZYNQMP_RPU_CFG_HIVEC_MASK; + writel(tmp, &rpu_base->rpu1_cfg); +} + +static void write_tcm_boot_trampoline(u32 boot_addr) +{ + if (boot_addr) { + /* + * Boot trampoline is simple ASM code below. + * + * b over; + * label: + * .word 0 + * over: ldr r0, =label + * ldr r1, [r0] + * bx r1 + */ + debug("Write boot trampoline for %x\n", boot_addr); + writel(0xea000000, ZYNQMP_TCM_START_ADDRESS); + writel(boot_addr, ZYNQMP_TCM_START_ADDRESS + 0x4); + writel(0xe59f0004, ZYNQMP_TCM_START_ADDRESS + 0x8); + writel(0xe5901000, ZYNQMP_TCM_START_ADDRESS + 0xc); + writel(0xe12fff11, ZYNQMP_TCM_START_ADDRESS + 0x10); + writel(0x00000004, ZYNQMP_TCM_START_ADDRESS + 0x14); // address for + } +} + +void initialize_tcm(bool mode) +{ + if (!mode) { + set_r5_tcm_mode(LOCK); + set_r5_halt_mode(HALT, LOCK); + enable_clock_r5(); + release_r5_reset(LOCK); + } else { + set_r5_tcm_mode(SPLIT); + set_r5_halt_mode(HALT, SPLIT); + enable_clock_r5(); + release_r5_reset(SPLIT); + } +} + +int cpu_release(u32 nr, int argc, char * const argv[]) +{ + if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) { + u64 boot_addr = simple_strtoull(argv[0], NULL, 16); + /* HIGH */ + writel((u32)(boot_addr >> 32), + ((u8 *)&apu_base->rvbar_addr0_h) + nr * 8); + /* LOW */ + writel((u32)(boot_addr & ZYNQMP_BOOTADDR_HIGH_MASK), + ((u8 *)&apu_base->rvbar_addr0_l) + nr * 8); + + u32 val = readl(&crfapb_base->rst_fpd_apu); + val &= ~(1 << nr); + writel(val, &crfapb_base->rst_fpd_apu); + } else { + if (argc != 2) { + printf("Invalid number of arguments to release.\n"); + printf("<addr> <mode>-Start addr lockstep or split\n"); + return 1; + } + + u32 boot_addr = simple_strtoul(argv[0], NULL, 16); + u32 boot_addr_uniq = 0; + if (!(boot_addr == ZYNQMP_R5_LOVEC_ADDR || + boot_addr == ZYNQMP_R5_HIVEC_ADDR)) { + printf("Using TCM jump trampoline for address 0x%x\n", + boot_addr); + /* Save boot address for later usage */ + boot_addr_uniq = boot_addr; + /* + * R5 needs to start from LOVEC at TCM + * OCM will be probably occupied by ATF + */ + boot_addr = ZYNQMP_R5_LOVEC_ADDR; + } + + /* + * Since we don't know where the user may have loaded the image + * for an R5 we have to flush all the data cache to ensure + * the R5 sees it. + */ + flush_dcache_all(); + + if (!strncmp(argv[1], "lockstep", 8)) { + printf("R5 lockstep mode\n"); + set_r5_reset(LOCK); + set_r5_tcm_mode(LOCK); + set_r5_halt_mode(HALT, LOCK); + set_r5_start(boot_addr); + enable_clock_r5(); + release_r5_reset(LOCK); + dcache_disable(); + write_tcm_boot_trampoline(boot_addr_uniq); + dcache_enable(); + set_r5_halt_mode(RELEASE, LOCK); + } else if (!strncmp(argv[1], "split", 5)) { + printf("R5 split mode\n"); + set_r5_reset(SPLIT); + set_r5_tcm_mode(SPLIT); + set_r5_halt_mode(HALT, SPLIT); + set_r5_start(boot_addr); + enable_clock_r5(); + release_r5_reset(SPLIT); + dcache_disable(); + write_tcm_boot_trampoline(boot_addr_uniq); + dcache_enable(); + set_r5_halt_mode(RELEASE, SPLIT); + } else { + printf("Unsupported mode\n"); + return 1; + } + } + + return 0; +}
diff --git a/arch/arm/cpu/armv8/zynqmp/psu_spl_init.c b/arch/arm/cpu/armv8/zynqmp/psu_spl_init.c new file mode 100644 index 0000000..b357de3 --- /dev/null +++ b/arch/arm/cpu/armv8/zynqmp/psu_spl_init.c
@@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 Xilinx, Inc. + * + * Michal Simek <michal.simek@xilinx.com> + */ +#include <common.h> +#include <asm/io.h> +#include <asm/arch/psu_init_gpl.h> + +#define PSU_MASK_POLL_TIME 1100000 + +int __maybe_unused mask_pollonvalue(unsigned long add, u32 mask, u32 value) +{ + int i = 0; + + while ((__raw_readl(add) & mask) != value) { + if (i == PSU_MASK_POLL_TIME) + return 0; + i++; + } + return 1; +} + +__weak int mask_poll(u32 add, u32 mask) +{ + int i = 0; + unsigned long addr = add; + + while (!(__raw_readl(addr) & mask)) { + if (i == PSU_MASK_POLL_TIME) + return 0; + i++; + } + return 1; +} + +__weak u32 mask_read(u32 add, u32 mask) +{ + unsigned long addr = add; + + return __raw_readl(addr) & mask; +} + +__weak void mask_delay(u32 delay) +{ + udelay(delay); +} + +__weak void psu_mask_write(unsigned long offset, unsigned long mask, + unsigned long val) +{ + unsigned long regval = 0; + + regval = readl(offset); + regval &= ~(mask); + regval |= (val & mask); + writel(regval, offset); +} + +__weak void prog_reg(unsigned long addr, unsigned long mask, + unsigned long shift, unsigned long value) +{ + int rdata = 0; + + rdata = readl(addr); + rdata = rdata & (~mask); + rdata = rdata | (value << shift); + writel(rdata, addr); +} + +__weak int psu_init(void) +{ + /* + * This function is overridden by the one in + * board/xilinx/zynqmp/(platform)/psu_init_gpl.c, if it exists. + */ + return -1; +}
diff --git a/arch/arm/cpu/armv8/zynqmp/spl.c b/arch/arm/cpu/armv8/zynqmp/spl.c new file mode 100644 index 0000000..01f31d0 --- /dev/null +++ b/arch/arm/cpu/armv8/zynqmp/spl.c
@@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2015 - 2016 Xilinx, Inc. + * + * Michal Simek <michal.simek@xilinx.com> + */ + +#include <common.h> +#include <debug_uart.h> +#include <spl.h> + +#include <asm/io.h> +#include <asm/spl.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> + +void board_init_f(ulong dummy) +{ + board_early_init_f(); + board_early_init_r(); + +#ifdef CONFIG_DEBUG_UART + /* Uart debug for sure */ + debug_uart_init(); + puts("Debug uart enabled\n"); /* or printch() */ +#endif + /* Delay is required for clocks to be propagated */ + udelay(1000000); + + /* Clear the BSS */ + memset(__bss_start, 0, __bss_end - __bss_start); + + /* No need to call timer init - it is empty for ZynqMP */ + board_init_r(NULL, 0); +} + +static void ps_mode_reset(ulong mode) +{ + writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT, + &crlapb_base->boot_pin_ctrl); + udelay(5); + writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_VAL_SHIFT | + mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT, + &crlapb_base->boot_pin_ctrl); +} + +/* + * Set default PS_MODE1 which is used for USB ULPI phy reset + * Also other resets can be connected to this certain pin + */ +#ifndef MODE_RESET +# define MODE_RESET PS_MODE1 +#endif + +#ifdef CONFIG_SPL_BOARD_INIT +void spl_board_init(void) +{ + preloader_console_init(); + ps_mode_reset(MODE_RESET); + board_init(); +} +#endif + +u32 spl_boot_device(void) +{ + u32 reg = 0; + u8 bootmode; + +#if defined(CONFIG_SPL_ZYNQMP_ALT_BOOTMODE_ENABLED) + /* Change default boot mode at run-time */ + writel(CONFIG_SPL_ZYNQMP_ALT_BOOTMODE << BOOT_MODE_ALT_SHIFT, + &crlapb_base->boot_mode); +#endif + + reg = readl(&crlapb_base->boot_mode); + if (reg >> BOOT_MODE_ALT_SHIFT) + reg >>= BOOT_MODE_ALT_SHIFT; + + bootmode = reg & BOOT_MODES_MASK; + + switch (bootmode) { + case JTAG_MODE: + return BOOT_DEVICE_RAM; +#ifdef CONFIG_SPL_MMC_SUPPORT + case SD_MODE1: + case SD1_LSHFT_MODE: /* not working on silicon v1 */ +/* if both controllers enabled, then these two are the second controller */ +#if defined(CONFIG_ZYNQ_SDHCI0) && defined(CONFIG_ZYNQ_SDHCI1) + return BOOT_DEVICE_MMC2; +/* else, fall through, the one SDHCI controller that is enabled is number 1 */ +#endif + case SD_MODE: + case EMMC_MODE: + return BOOT_DEVICE_MMC1; +#endif +#ifdef CONFIG_SPL_DFU_SUPPORT + case USB_MODE: + return BOOT_DEVICE_DFU; +#endif +#ifdef CONFIG_SPL_SATA_SUPPORT + case SW_SATA_MODE: + return BOOT_DEVICE_SATA; +#endif +#ifdef CONFIG_SPL_SPI_SUPPORT + case QSPI_MODE_24BIT: + case QSPI_MODE_32BIT: + return BOOT_DEVICE_SPI; +#endif + default: + printf("Invalid Boot Mode:0x%x\n", bootmode); + break; + } + + return 0; +} + +#ifdef CONFIG_SPL_OS_BOOT +int spl_start_uboot(void) +{ + handoff_setup(); + + return 0; +} +#endif + +#ifdef CONFIG_SPL_LOAD_FIT +int board_fit_config_name_match(const char *name) +{ + /* Just empty function now - can't decide what to choose */ + debug("%s: %s\n", __func__, name); + + return 0; +} +#endif
diff --git a/arch/arm/cpu/pxa/Makefile b/arch/arm/cpu/pxa/Makefile new file mode 100644 index 0000000..263d9dd --- /dev/null +++ b/arch/arm/cpu/pxa/Makefile
@@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-y = start.o + +obj-$(CONFIG_CPU_PXA25X) += pxa2xx.o +obj-$(CONFIG_CPU_PXA27X) += pxa2xx.o + +obj-y += cpuinfo.o +obj-y += timer.o +obj-y += usb.o +obj-y += relocate.o +obj-y += cache.o
diff --git a/arch/arm/cpu/pxa/cache.c b/arch/arm/cpu/pxa/cache.c new file mode 100644 index 0000000..8b932b1 --- /dev/null +++ b/arch/arm/cpu/pxa/cache.c
@@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2016 Vasily Khoruzhick <anarsoul@gmail.com> + */ + +#include <linux/types.h> +#include <common.h> + +#ifndef CONFIG_SYS_DCACHE_OFF +void invalidate_dcache_all(void) +{ + /* Flush/Invalidate I cache */ + asm volatile("mcr p15, 0, %0, c7, c5, 0\n" : : "r"(0)); + /* Flush/Invalidate D cache */ + asm volatile("mcr p15, 0, %0, c7, c6, 0\n" : : "r"(0)); +} + +void flush_dcache_all(void) +{ + return invalidate_dcache_all(); +} + +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ + start &= ~(CONFIG_SYS_CACHELINE_SIZE - 1); + stop &= ~(CONFIG_SYS_CACHELINE_SIZE - 1); + + while (start <= stop) { + asm volatile("mcr p15, 0, %0, c7, c6, 1\n" : : "r"(start)); + start += CONFIG_SYS_CACHELINE_SIZE; + } +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ + return invalidate_dcache_range(start, stop); +} +#else /* #ifndef CONFIG_SYS_DCACHE_OFF */ +void invalidate_dcache_all(void) +{ +} + +void flush_dcache_all(void) +{ +} +#endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ + +/* + * Stub implementations for l2 cache operations + */ + +__weak void l2_cache_disable(void) {} + +#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) +__weak void invalidate_l2_cache(void) {} +#endif
diff --git a/arch/arm/cpu/pxa/config.mk b/arch/arm/cpu/pxa/config.mk new file mode 100644 index 0000000..e7b1836 --- /dev/null +++ b/arch/arm/cpu/pxa/config.mk
@@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2002 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.de> + +# +# !WARNING! +# The PXA's OneNAND SPL uses .text.0 and .text.1 segments to allow booting from +# really small OneNAND memories where the mmap'd window is only 1KiB big. The +# .text.0 contains only the bare minimum needed to load the real SPL into SRAM. +# Add .text.0 and .text.1 into OBJFLAGS, so when the SPL is being objcopy'd, +# they are not discarded. +# + +#ifdef CONFIG_SPL_BUILD +OBJCOPYFLAGS += -j .text.0 -j .text.1 +#endif
diff --git a/arch/arm/cpu/pxa/cpuinfo.c b/arch/arm/cpu/pxa/cpuinfo.c new file mode 100644 index 0000000..5379e13 --- /dev/null +++ b/arch/arm/cpu/pxa/cpuinfo.c
@@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * PXA CPU information display + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <errno.h> +#include <linux/compiler.h> + +#ifdef CONFIG_CPU_PXA25X +#if ((CONFIG_SYS_INIT_SP_ADDR) != 0xfffff800) +#error "Init SP address must be set to 0xfffff800 for PXA250" +#endif +#endif + +#define CPU_MASK_PXA_PRODID 0x000003f0 +#define CPU_MASK_PXA_REVID 0x0000000f + +#define CPU_MASK_PRODREV (CPU_MASK_PXA_PRODID | CPU_MASK_PXA_REVID) + +#define CPU_VALUE_PXA25X 0x100 +#define CPU_VALUE_PXA27X 0x110 + +static uint32_t pxa_get_cpuid(void) +{ + uint32_t cpuid; + asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r"(cpuid)); + return cpuid; +} + +int cpu_is_pxa25x(void) +{ + uint32_t id = pxa_get_cpuid(); + id &= CPU_MASK_PXA_PRODID; + return id == CPU_VALUE_PXA25X; +} + +int cpu_is_pxa27x(void) +{ + uint32_t id = pxa_get_cpuid(); + id &= CPU_MASK_PXA_PRODID; + return id == CPU_VALUE_PXA27X; +} + +int cpu_is_pxa27xm(void) +{ + uint32_t id = pxa_get_cpuid(); + return ((id & CPU_MASK_PXA_PRODID) == CPU_VALUE_PXA27X) && + ((id & CPU_MASK_PXA_REVID) == 8); +} + +uint32_t pxa_get_cpu_revision(void) +{ + return pxa_get_cpuid() & CPU_MASK_PRODREV; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +static const char *pxa25x_get_revision(void) +{ + static __maybe_unused const char * const revs_25x[] = { "A0" }; + static __maybe_unused const char * const revs_26x[] = { + "A0", "B0", "B1" + }; + static const char *unknown = "Unknown"; + uint32_t id; + + if (!cpu_is_pxa25x()) + return unknown; + + id = pxa_get_cpuid() & CPU_MASK_PXA_REVID; + +/* PXA26x is a sick special case as it can't be told apart from PXA25x :-( */ +#ifdef CONFIG_CPU_PXA26X + switch (id) { + case 3: return revs_26x[0]; + case 5: return revs_26x[1]; + case 6: return revs_26x[2]; + } +#else + if (id == 6) + return revs_25x[0]; +#endif + return unknown; +} + +static const char *pxa27x_get_revision(void) +{ + static const char *const rev[] = { "A0", "A1", "B0", "B1", "C0", "C5" }; + static const char *unknown = "Unknown"; + uint32_t id; + + if (!cpu_is_pxa27x()) + return unknown; + + id = pxa_get_cpuid() & CPU_MASK_PXA_REVID; + + if ((id == 5) || (id == 6) || (id > 8)) + return unknown; + + /* Cap the special PXA270 C5 case. */ + if (id == 7) + id = 5; + + /* Cap the special PXA270M A1 case. */ + if (id == 8) + id = 1; + + return rev[id]; +} + +static int print_cpuinfo_pxa2xx(void) +{ + if (cpu_is_pxa25x()) { + puts("Marvell PXA25x rev. "); + puts(pxa25x_get_revision()); + } else if (cpu_is_pxa27x()) { + puts("Marvell PXA27x"); + if (cpu_is_pxa27xm()) puts("M"); + puts(" rev. "); + puts(pxa27x_get_revision()); + } else + return -EINVAL; + + puts("\n"); + + return 0; +} + +int print_cpuinfo(void) +{ + int ret; + + puts("CPU: "); + + ret = print_cpuinfo_pxa2xx(); + if (!ret) + return ret; + + return ret; +} +#endif
diff --git a/arch/arm/cpu/pxa/pxa2xx.c b/arch/arm/cpu/pxa/pxa2xx.c new file mode 100644 index 0000000..b9fd41e --- /dev/null +++ b/arch/arm/cpu/pxa/pxa2xx.c
@@ -0,0 +1,295 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + */ + +#include <common.h> +#include <asm/arch/pxa-regs.h> +#include <asm/io.h> +#include <asm/system.h> +#include <command.h> + +/* Flush I/D-cache */ +static void cache_flush(void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (i)); +} + +int cleanup_before_linux(void) +{ + /* + * This function is called just before we call Linux. It prepares + * the processor for Linux by just disabling everything that can + * disturb booting Linux. + */ + + disable_interrupts(); + icache_disable(); + dcache_disable(); + cache_flush(); + + return 0; +} + +void pxa_wait_ticks(int ticks) +{ + writel(0, OSCR); + while (readl(OSCR) < ticks) + asm volatile("" : : : "memory"); +} + +inline void writelrb(uint32_t val, uint32_t addr) +{ + writel(val, addr); + asm volatile("" : : : "memory"); + readl(addr); + asm volatile("" : : : "memory"); +} + +void pxa2xx_dram_init(void) +{ + uint32_t tmp; + int i; + /* + * 1) Initialize Asynchronous static memory controller + */ + + writelrb(CONFIG_SYS_MSC0_VAL, MSC0); + writelrb(CONFIG_SYS_MSC1_VAL, MSC1); + writelrb(CONFIG_SYS_MSC2_VAL, MSC2); + /* + * 2) Initialize Card Interface + */ + + /* MECR: Memory Expansion Card Register */ + writelrb(CONFIG_SYS_MECR_VAL, MECR); + /* MCMEM0: Card Interface slot 0 timing */ + writelrb(CONFIG_SYS_MCMEM0_VAL, MCMEM0); + /* MCMEM1: Card Interface slot 1 timing */ + writelrb(CONFIG_SYS_MCMEM1_VAL, MCMEM1); + /* MCATT0: Card Interface Attribute Space Timing, slot 0 */ + writelrb(CONFIG_SYS_MCATT0_VAL, MCATT0); + /* MCATT1: Card Interface Attribute Space Timing, slot 1 */ + writelrb(CONFIG_SYS_MCATT1_VAL, MCATT1); + /* MCIO0: Card Interface I/O Space Timing, slot 0 */ + writelrb(CONFIG_SYS_MCIO0_VAL, MCIO0); + /* MCIO1: Card Interface I/O Space Timing, slot 1 */ + writelrb(CONFIG_SYS_MCIO1_VAL, MCIO1); + + /* + * 3) Configure Fly-By DMA register + */ + + writelrb(CONFIG_SYS_FLYCNFG_VAL, FLYCNFG); + + /* + * 4) Initialize Timing for Sync Memory (SDCLK0) + */ + + /* + * Before accessing MDREFR we need a valid DRI field, so we set + * this to power on defaults + DRI field. + */ + + /* Read current MDREFR config and zero out DRI */ + tmp = readl(MDREFR) & ~0xfff; + /* Add user-specified DRI */ + tmp |= CONFIG_SYS_MDREFR_VAL & 0xfff; + /* Configure important bits */ + tmp |= MDREFR_K0RUN | MDREFR_SLFRSH; + tmp &= ~(MDREFR_APD | MDREFR_E1PIN); + + /* Write MDREFR back */ + writelrb(tmp, MDREFR); + + /* + * 5) Initialize Synchronous Static Memory (Flash/Peripherals) + */ + + /* Initialize SXCNFG register. Assert the enable bits. + * + * Write SXMRS to cause an MRS command to all enabled banks of + * synchronous static memory. Note that SXLCR need not be written + * at this time. + */ + writelrb(CONFIG_SYS_SXCNFG_VAL, SXCNFG); + + /* + * 6) Initialize SDRAM + */ + + writelrb(CONFIG_SYS_MDREFR_VAL & ~MDREFR_SLFRSH, MDREFR); + writelrb(CONFIG_SYS_MDREFR_VAL | MDREFR_E1PIN, MDREFR); + + /* + * 7) Write MDCNFG with MDCNFG:DEx deasserted (set to 0), to configure + * but not enable each SDRAM partition pair. + */ + + writelrb(CONFIG_SYS_MDCNFG_VAL & + ~(MDCNFG_DE0 | MDCNFG_DE1 | MDCNFG_DE2 | MDCNFG_DE3), MDCNFG); + /* Wait for the clock to the SDRAMs to stabilize, 100..200 usec. */ + pxa_wait_ticks(0x300); + + /* + * 8) Trigger a number (usually 8) refresh cycles by attempting + * non-burst read or write accesses to disabled SDRAM, as commonly + * specified in the power up sequence documented in SDRAM data + * sheets. The address(es) used for this purpose must not be + * cacheable. + */ + for (i = 9; i >= 0; i--) { + writel(i, 0xa0000000); + asm volatile("" : : : "memory"); + } + /* + * 9) Write MDCNFG with enable bits asserted (MDCNFG:DEx set to 1). + */ + + tmp = CONFIG_SYS_MDCNFG_VAL & + (MDCNFG_DE0 | MDCNFG_DE1 | MDCNFG_DE2 | MDCNFG_DE3); + tmp |= readl(MDCNFG); + writelrb(tmp, MDCNFG); + + /* + * 10) Write MDMRS. + */ + + writelrb(CONFIG_SYS_MDMRS_VAL, MDMRS); + + /* + * 11) Enable APD + */ + + if (CONFIG_SYS_MDREFR_VAL & MDREFR_APD) { + tmp = readl(MDREFR); + tmp |= MDREFR_APD; + writelrb(tmp, MDREFR); + } +} + +void pxa_gpio_setup(void) +{ + writel(CONFIG_SYS_GPSR0_VAL, GPSR0); + writel(CONFIG_SYS_GPSR1_VAL, GPSR1); + writel(CONFIG_SYS_GPSR2_VAL, GPSR2); +#if defined(CONFIG_CPU_PXA27X) + writel(CONFIG_SYS_GPSR3_VAL, GPSR3); +#endif + + writel(CONFIG_SYS_GPCR0_VAL, GPCR0); + writel(CONFIG_SYS_GPCR1_VAL, GPCR1); + writel(CONFIG_SYS_GPCR2_VAL, GPCR2); +#if defined(CONFIG_CPU_PXA27X) + writel(CONFIG_SYS_GPCR3_VAL, GPCR3); +#endif + + writel(CONFIG_SYS_GPDR0_VAL, GPDR0); + writel(CONFIG_SYS_GPDR1_VAL, GPDR1); + writel(CONFIG_SYS_GPDR2_VAL, GPDR2); +#if defined(CONFIG_CPU_PXA27X) + writel(CONFIG_SYS_GPDR3_VAL, GPDR3); +#endif + + writel(CONFIG_SYS_GAFR0_L_VAL, GAFR0_L); + writel(CONFIG_SYS_GAFR0_U_VAL, GAFR0_U); + writel(CONFIG_SYS_GAFR1_L_VAL, GAFR1_L); + writel(CONFIG_SYS_GAFR1_U_VAL, GAFR1_U); + writel(CONFIG_SYS_GAFR2_L_VAL, GAFR2_L); + writel(CONFIG_SYS_GAFR2_U_VAL, GAFR2_U); +#if defined(CONFIG_CPU_PXA27X) + writel(CONFIG_SYS_GAFR3_L_VAL, GAFR3_L); + writel(CONFIG_SYS_GAFR3_U_VAL, GAFR3_U); +#endif + + writel(CONFIG_SYS_PSSR_VAL, PSSR); +} + +void pxa_interrupt_setup(void) +{ + writel(0, ICLR); + writel(0, ICMR); +#if defined(CONFIG_CPU_PXA27X) + writel(0, ICLR2); + writel(0, ICMR2); +#endif +} + +void pxa_clock_setup(void) +{ + writel(CONFIG_SYS_CKEN, CKEN); + writel(CONFIG_SYS_CCCR, CCCR); + asm volatile("mcr p14, 0, %0, c6, c0, 0" : : "r"(0x0b)); + + /* enable the 32Khz oscillator for RTC and PowerManager */ + writel(OSCC_OON, OSCC); + while (!(readl(OSCC) & OSCC_OOK)) + asm volatile("" : : : "memory"); +} + +void pxa_wakeup(void) +{ + uint32_t rcsr; + + rcsr = readl(RCSR); + writel(rcsr & (RCSR_GPR | RCSR_SMR | RCSR_WDR | RCSR_HWR), RCSR); + + /* Wakeup */ + if (rcsr & RCSR_SMR) { + writel(PSSR_PH, PSSR); + pxa2xx_dram_init(); + icache_disable(); + dcache_disable(); + asm volatile("mov pc, %0" : : "r"(readl(PSPR))); + } +} + +int arch_cpu_init(void) +{ + pxa_gpio_setup(); + pxa_wakeup(); + pxa_interrupt_setup(); + pxa_clock_setup(); + return 0; +} + +void i2c_clk_enable(void) +{ + /* Set the global I2C clock on */ + writel(readl(CKEN) | CKEN14_I2C, CKEN); +} + +void __attribute__((weak)) reset_cpu(ulong ignored) __attribute__((noreturn)); + +void reset_cpu(ulong ignored) +{ + uint32_t tmp; + + setbits_le32(OWER, OWER_WME); + + tmp = readl(OSCR); + tmp += 0x1000; + writel(tmp, OSMR3); + writel(MDREFR_SLFRSH, MDREFR); + + for (;;) + ; +} + +void enable_caches(void) +{ +#ifndef CONFIG_SYS_ICACHE_OFF + icache_enable(); +#endif +#ifndef CONFIG_SYS_DCACHE_OFF + dcache_enable(); +#endif +}
diff --git a/arch/arm/cpu/pxa/relocate.S b/arch/arm/cpu/pxa/relocate.S new file mode 100644 index 0000000..778cd45 --- /dev/null +++ b/arch/arm/cpu/pxa/relocate.S
@@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * relocate - PXA270 vector relocation + * + * Copyright (c) 2013 Albert ARIBAUD <albert.u.boot@aribaud.net> + */ + +#include <linux/linkage.h> + +/* + * The PXA SoC is very specific with respect to exceptions: it + * does not provide RAM at the high vectors address (0xFFFF0000), + * thus only the low address (0x00000000) is useable; but that is + * in ROM, so let's avoid relocating the vectors. + */ + .section .text.relocate_vectors,"ax",%progbits + +ENTRY(relocate_vectors) + + bx lr + +ENDPROC(relocate_vectors)
diff --git a/arch/arm/cpu/pxa/start.S b/arch/arm/cpu/pxa/start.S new file mode 100644 index 0000000..575abac --- /dev/null +++ b/arch/arm/cpu/pxa/start.S
@@ -0,0 +1,205 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * armboot - Startup Code for XScale CPU-core + * + * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> + * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> + * Copyright (C) 2000 Wolfgang Denk <wd@denx.de> + * Copyright (C) 2001 Alex Zuepke <azu@sysgo.de> + * Copyright (C) 2001 Marius Groger <mag@sysgo.de> + * Copyright (C) 2002 Alex Zupke <azu@sysgo.de> + * Copyright (C) 2002 Gary Jennejohn <garyj@denx.de> + * Copyright (C) 2002 Kyle Harris <kharris@nexus-tech.net> + * Copyright (C) 2003 Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de> + * Copyright (C) 2003 Kshitij <kshitij@ti.com> + * Copyright (C) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de> + * Copyright (C) 2004 Texas Instruments <r-woodruff2@ti.com> + * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com> + */ + +#include <asm-offsets.h> +#include <config.h> + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + + .globl reset + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + +#ifdef CONFIG_CPU_PXA25X + bl lock_cache_for_stack +#endif +#ifdef CONFIG_CPU_PXA27X + /* + * enable clock for SRAM + */ + ldr r0,=CKEN + ldr r1,[r0] + orr r1,r1,#(1 << 20) + str r1,[r0] +#endif + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + +#ifdef CONFIG_CPU_PXA25X + /* + * Unlock (actually, disable) the cache now that board_init_f + * is done. We could do this earlier but we would need to add + * a new C runtime hook, whereas c_runtime_cpu_setup already + * exists. + * As this routine is just a call to cpu_init_crit, let us + * tail-optimize and do a simple branch here. + */ + b cpu_init_crit +#else + bx lr +#endif + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ +#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) || defined(CONFIG_CPU_PXA25X) +cpu_init_crit: + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* Invalidate I+D+BTB caches */ + mcr p15, 0, r0, c8, c7, 0 /* Invalidate Unified TLB */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00003300 @ clear bits 13:12, 9:8 (--VI --RS) + bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) + orr r0, r0, #0x00000002 @ set bit 1 (A) Align + mcr p15, 0, r0, c1, c0, 0 + + mov pc, lr /* back to my caller */ +#endif /* !CONFIG_SKIP_LOWLEVEL_INIT || CONFIG_CPU_PXA25X */ + +/* + * Enable MMU to use DCache as DRAM. + * + * This is useful on PXA25x and PXA26x in early bootstages, where there is no + * other possible memory available to hold stack. + */ +#ifdef CONFIG_CPU_PXA25X +.macro CPWAIT reg + mrc p15, 0, \reg, c2, c0, 0 + mov \reg, \reg + sub pc, pc, #4 +.endm +lock_cache_for_stack: + /* Domain access -- enable for all CPs */ + ldr r0, =0x0000ffff + mcr p15, 0, r0, c3, c0, 0 + + /* Point TTBR to MMU table */ + ldr r0, =mmutable + mcr p15, 0, r0, c2, c0, 0 + + /* Kick in MMU, ICache, DCache, BTB */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, #0x1b00 + bic r0, #0x0087 + orr r0, #0x1800 + orr r0, #0x0005 + mcr p15, 0, r0, c1, c0, 0 + CPWAIT r0 + + /* Unlock Icache, Dcache */ + mcr p15, 0, r0, c9, c1, 1 + mcr p15, 0, r0, c9, c2, 1 + + /* Flush Icache, Dcache, BTB */ + mcr p15, 0, r0, c7, c7, 0 + + /* Unlock I-TLB, D-TLB */ + mcr p15, 0, r0, c10, c4, 1 + mcr p15, 0, r0, c10, c8, 1 + + /* Flush TLB */ + mcr p15, 0, r0, c8, c7, 0 + + /* Allocate 4096 bytes of Dcache as RAM */ + + /* Drain pending loads and stores */ + mcr p15, 0, r0, c7, c10, 4 + + mov r4, #0x00 + mov r5, #0x00 + mov r2, #0x01 + mcr p15, 0, r0, c9, c2, 0 + CPWAIT r0 + + /* 128 lines reserved (128 x 32bytes = 4096 bytes total) */ + mov r0, #128 + ldr r1, =0xfffff000 + +alloc: + mcr p15, 0, r1, c7, c2, 5 + /* Drain pending loads and stores */ + mcr p15, 0, r0, c7, c10, 4 + strd r4, [r1], #8 + strd r4, [r1], #8 + strd r4, [r1], #8 + strd r4, [r1], #8 + subs r0, #0x01 + bne alloc + /* Drain pending loads and stores */ + mcr p15, 0, r0, c7, c10, 4 + mov r2, #0x00 + mcr p15, 0, r2, c9, c2, 0 + CPWAIT r0 + + mov pc, lr + +.section .mmutable, "a" +mmutable: + .align 14 + /* 0x00000000 - 0xffe00000 : 1:1, uncached mapping */ + .set __base, 0 + .rept 0xfff + .word (__base << 20) | 0xc12 + .set __base, __base + 1 + .endr + + /* 0xfff00000 : 1:1, cached mapping */ + .word (0xfff << 20) | 0x1c1e +#endif /* CONFIG_CPU_PXA25X */
diff --git a/arch/arm/cpu/pxa/timer.c b/arch/arm/cpu/pxa/timer.c new file mode 100644 index 0000000..169fed8 --- /dev/null +++ b/arch/arm/cpu/pxa/timer.c
@@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Marvell PXA2xx/3xx timer driver + * + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + */ + +#include <common.h> +#include <asm/io.h> + +int timer_init(void) +{ + writel(0, CONFIG_SYS_TIMER_COUNTER); + return 0; +}
diff --git a/arch/arm/cpu/pxa/usb.c b/arch/arm/cpu/pxa/usb.c new file mode 100644 index 0000000..80a5977 --- /dev/null +++ b/arch/arm/cpu/pxa/usb.c
@@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2006 + * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de> + */ + +#include <common.h> + +#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) +# if defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_CPU_PXA27X) + +#include <asm/arch/pxa-regs.h> +#include <asm/io.h> +#include <usb.h> + +int usb_cpu_init(void) +{ +#if defined(CONFIG_CPU_MONAHANS) + /* Enable USB host clock. */ + writel(readl(CKENA) | CKENA_2_USBHOST | CKENA_20_UDC, CKENA); + udelay(100); +#endif +#if defined(CONFIG_CPU_PXA27X) + /* Enable USB host clock. */ + writel(readl(CKEN) | CKEN10_USBHOST, CKEN); +#endif + +#if defined(CONFIG_CPU_MONAHANS) + /* Configure Port 2 for Host (USB Client Registers) */ + writel(0x3000c, UP2OCR); +#endif + + writel(readl(UHCHR) | UHCHR_FHR, UHCHR); + mdelay(11); + writel(readl(UHCHR) & ~UHCHR_FHR, UHCHR); + + writel(readl(UHCHR) | UHCHR_FSBIR, UHCHR); + while (readl(UHCHR) & UHCHR_FSBIR) + udelay(1); + +#if defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_PXA27X) + writel(readl(UHCHR) & ~UHCHR_SSEP0, UHCHR); +#endif +#if defined(CONFIG_CPU_PXA27X) + writel(readl(UHCHR) & ~UHCHR_SSEP2, UHCHR); +#endif + writel(readl(UHCHR) & ~(UHCHR_SSEP1 | UHCHR_SSE), UHCHR); + + return 0; +} + +int usb_cpu_stop(void) +{ + writel(readl(UHCHR) | UHCHR_FHR, UHCHR); + udelay(11); + writel(readl(UHCHR) & ~UHCHR_FHR, UHCHR); + + writel(readl(UHCCOMS) | UHCCOMS_HCR, UHCCOMS); + udelay(10); + +#if defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_PXA27X) + writel(readl(UHCHR) | UHCHR_SSEP0, UHCHR); +#endif +#if defined(CONFIG_CPU_PXA27X) + writel(readl(UHCHR) | UHCHR_SSEP2, UHCHR); +#endif + writel(readl(UHCHR) | UHCHR_SSEP1 | UHCHR_SSE, UHCHR); + +#if defined(CONFIG_CPU_MONAHANS) + /* Disable USB host clock. */ + writel(readl(CKENA) & ~(CKENA_2_USBHOST | CKENA_20_UDC), CKENA); + udelay(100); +#endif +#if defined(CONFIG_CPU_PXA27X) + /* Disable USB host clock. */ + writel(readl(CKEN) & ~CKEN10_USBHOST, CKEN); +#endif + + return 0; +} + +int usb_cpu_init_fail(void) +{ + return usb_cpu_stop(); +} + +# endif /* defined(CONFIG_CPU_MONAHANS) || defined(CONFIG_CPU_PXA27X) */ +#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */
diff --git a/arch/arm/cpu/sa1100/Makefile b/arch/arm/cpu/sa1100/Makefile new file mode 100644 index 0000000..3819309 --- /dev/null +++ b/arch/arm/cpu/sa1100/Makefile
@@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. + +extra-y = start.o + +obj-y += cpu.o +obj-y += timer.o
diff --git a/arch/arm/cpu/sa1100/cpu.c b/arch/arm/cpu/sa1100/cpu.c new file mode 100644 index 0000000..f81ebc9 --- /dev/null +++ b/arch/arm/cpu/sa1100/cpu.c
@@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/system.h> +#include <asm/io.h> + +static void cache_flush(void); + +int cleanup_before_linux (void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * just disable everything that can disturb booting linux + */ + + disable_interrupts (); + + /* turn off I-cache */ + icache_disable(); + dcache_disable(); + + /* flush I-cache */ + cache_flush(); + + return (0); +} + +/* flush I/D-cache */ +static void cache_flush (void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (i)); +} + +#define RST_BASE 0x90030000 +#define RSRR 0x00 +#define RCSR 0x04 + +__attribute__((noreturn)) void reset_cpu(ulong addr __attribute__((unused))) +{ + /* repeat endlessly */ + while (1) { + writel(0, RST_BASE + RCSR); + writel(1, RST_BASE + RSRR); + } +}
diff --git a/arch/arm/cpu/sa1100/start.S b/arch/arm/cpu/sa1100/start.S new file mode 100644 index 0000000..8eb0053 --- /dev/null +++ b/arch/arm/cpu/sa1100/start.S
@@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * armboot - Startup Code for SA1100 CPU + * + * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> + * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> + * Copyright (C) 2000 Wolfgang Denk <wd@denx.de> + * Copyright (c) 2001 Alex Züpke <azu@sysgo.de> + */ + +#include <asm-offsets.h> +#include <config.h> + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * relocate armboot to ram + * setup stack + * jump to second stage + * + ************************************************************************* + */ + + .globl reset + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl _main + +/*------------------------------------------------------------------------------*/ + + .globl c_runtime_cpu_setup +c_runtime_cpu_setup: + + mov pc, lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + + +/* Interrupt-Controller base address */ +IC_BASE: .word 0x90050000 +#define ICMR 0x04 + + +/* Reset-Controller */ +RST_BASE: .word 0x90030000 +#define RSRR 0x00 +#define RCSR 0x04 + + +/* PWR */ +PWR_BASE: .word 0x90020000 +#define PSPR 0x08 +#define PPCR 0x14 +cpuspeed: .word CONFIG_SYS_CPUSPEED + + +cpu_init_crit: + /* + * mask all IRQs + */ + ldr r0, IC_BASE + mov r1, #0x00 + str r1, [r0, #ICMR] + + /* set clock speed */ + ldr r0, PWR_BASE + ldr r1, cpuspeed + str r1, [r0, #PPCR] + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY + /* + * before relocating, we have to setup RAM timing + * because memory timing is board-dependend, you will + * find a lowlevel_init.S in your board directory. + */ + mov ip, lr + bl lowlevel_init + mov lr, ip +#endif + + /* + * disable MMU stuff and enable I-cache + */ + mrc p15,0,r0,c1,c0 + bic r0, r0, #0x00002000 @ clear bit 13 (X) + bic r0, r0, #0x0000000f @ clear bits 3-0 (WCAM) + orr r0, r0, #0x00001000 @ set bit 12 (I) Icache + orr r0, r0, #0x00000002 @ set bit 1 (A) Align + mcr p15,0,r0,c1,c0 + + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ + mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ + + mov pc, lr
diff --git a/arch/arm/cpu/sa1100/timer.c b/arch/arm/cpu/sa1100/timer.c new file mode 100644 index 0000000..0fac5c1 --- /dev/null +++ b/arch/arm/cpu/sa1100/timer.c
@@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + */ + +#include <common.h> +#include <SA-1100.h> + +static ulong get_timer_masked (void) +{ + return OSCR; +} + +ulong get_timer (ulong base) +{ + return get_timer_masked (); +} + +void __udelay (unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + if (usec >= 1000) { + tmo = usec / 1000; + tmo *= CONFIG_SYS_HZ; + tmo /= 1000; + } else { + tmo = usec * CONFIG_SYS_HZ; + tmo /= (1000*1000); + } + + endtime = get_timer_masked () + tmo; + + do { + ulong now = get_timer_masked (); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + return CONFIG_SYS_HZ; +}
diff --git a/arch/arm/cpu/u-boot-spl.lds b/arch/arm/cpu/u-boot-spl.lds new file mode 100644 index 0000000..9d13331 --- /dev/null +++ b/arch/arm/cpu/u-boot-spl.lds
@@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + __image_copy_start = .; + *(.vectors) + CPUDIR/start.o (.text*) + *(.text*) + *(.glue*) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + .binman_sym_table : { + __binman_sym_start = .; + KEEP(*(SORT(.binman_sym*))); + __binman_sym_end = .; + } + + . = ALIGN(4); + + __image_copy_end = .; + + .rel.dyn : { + __rel_dyn_start = .; + *(.rel*) + __rel_dyn_end = .; + } + + .end : + { + *(.__end) + } + + _image_binary_end = .; + + .bss __rel_dyn_start (OVERLAY) : { + __bss_start = .; + *(.bss*) + . = ALIGN(4); + __bss_end = .; + } + __bss_size = __bss_end - __bss_start; + .dynsym _image_binary_end : { *(.dynsym) } + .dynbss : { *(.dynbss) } + .dynstr : { *(.dynstr*) } + .dynamic : { *(.dynamic*) } + .hash : { *(.hash*) } + .plt : { *(.plt*) } + .interp : { *(.interp*) } + .gnu : { *(.gnu*) } + .ARM.exidx : { *(.ARM.exidx*) } +} + +#if defined(CONFIG_SPL_MAX_SIZE) +ASSERT(__image_copy_end - __image_copy_start < (CONFIG_SPL_MAX_SIZE), \ + "SPL image too big"); +#endif + +#if defined(CONFIG_SPL_BSS_MAX_SIZE) +ASSERT(__bss_end - __bss_start < (CONFIG_SPL_BSS_MAX_SIZE), \ + "SPL image BSS too big"); +#endif + +#if defined(CONFIG_SPL_MAX_FOOTPRINT) +ASSERT(__bss_end - _start < (CONFIG_SPL_MAX_FOOTPRINT), \ + "SPL image plus BSS too big"); +#endif
diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds new file mode 100644 index 0000000..0eb164d --- /dev/null +++ b/arch/arm/cpu/u-boot.lds
@@ -0,0 +1,240 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + */ + +#include <config.h> +#include <asm/psci.h> + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ +#ifndef CONFIG_CMDLINE + /DISCARD/ : { *(.u_boot_list_2_cmd_*) } +#endif +#if defined(CONFIG_ARMV7_SECURE_BASE) && defined(CONFIG_ARMV7_NONSEC) + /* + * If CONFIG_ARMV7_SECURE_BASE is true, secure code will not + * bundle with u-boot, and code offsets are fixed. Secure zone + * only needs to be copied from the loading address to + * CONFIG_ARMV7_SECURE_BASE, which is the linking and running + * address for secure code. + * + * If CONFIG_ARMV7_SECURE_BASE is undefined, the secure zone will + * be included in u-boot address space, and some absolute address + * were used in secure code. The absolute addresses of the secure + * code also needs to be relocated along with the accompanying u-boot + * code. + * + * So DISCARD is only for CONFIG_ARMV7_SECURE_BASE. + */ + /DISCARD/ : { *(.rel._secure*) } +#endif + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.__image_copy_start) + *(.vectors) + CPUDIR/start.o (.text*) + } + + /* This needs to come before *(.text*) */ + .__efi_runtime_start : { + *(.__efi_runtime_start) + } + + .efi_runtime : { + *(.text.efi_runtime*) + *(.rodata.efi_runtime*) + *(.data.efi_runtime*) + } + + .__efi_runtime_stop : { + *(.__efi_runtime_stop) + } + + .text_rest : + { + *(.text*) + } + +#ifdef CONFIG_ARMV7_NONSEC + + /* Align the secure section only if we're going to use it in situ */ + .__secure_start +#ifndef CONFIG_ARMV7_SECURE_BASE + ALIGN(CONSTANT(COMMONPAGESIZE)) +#endif + : { + KEEP(*(.__secure_start)) + } + +#ifndef CONFIG_ARMV7_SECURE_BASE +#define CONFIG_ARMV7_SECURE_BASE +#define __ARMV7_PSCI_STACK_IN_RAM +#endif + + .secure_text CONFIG_ARMV7_SECURE_BASE : + AT(ADDR(.__secure_start) + SIZEOF(.__secure_start)) + { + *(._secure.text) + } + + .secure_data : AT(LOADADDR(.secure_text) + SIZEOF(.secure_text)) + { + *(._secure.data) + } + +#ifdef CONFIG_ARMV7_PSCI + .secure_stack ALIGN(ADDR(.secure_data) + SIZEOF(.secure_data), + CONSTANT(COMMONPAGESIZE)) (NOLOAD) : +#ifdef __ARMV7_PSCI_STACK_IN_RAM + AT(ADDR(.secure_stack)) +#else + AT(LOADADDR(.secure_data) + SIZEOF(.secure_data)) +#endif + { + KEEP(*(.__secure_stack_start)) + + /* Skip addreses for stack */ + . = . + CONFIG_ARMV7_PSCI_NR_CPUS * ARM_PSCI_STACK_SIZE; + + /* Align end of stack section to page boundary */ + . = ALIGN(CONSTANT(COMMONPAGESIZE)); + + KEEP(*(.__secure_stack_end)) + +#ifdef CONFIG_ARMV7_SECURE_MAX_SIZE + /* + * We are not checking (__secure_end - __secure_start) here, + * as these are the load addresses, and do not include the + * stack section. Instead, use the end of the stack section + * and the start of the text section. + */ + ASSERT((. - ADDR(.secure_text)) <= CONFIG_ARMV7_SECURE_MAX_SIZE, + "Error: secure section exceeds secure memory size"); +#endif + } + +#ifndef __ARMV7_PSCI_STACK_IN_RAM + /* Reset VMA but don't allocate space if we have secure SRAM */ + . = LOADADDR(.secure_stack); +#endif + +#endif + + .__secure_end : AT(ADDR(.__secure_end)) { + *(.__secure_end) + LONG(0x1d1071c); /* Must output something to reset LMA */ + } +#endif + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + + . = .; + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + + .efi_runtime_rel_start : + { + *(.__efi_runtime_rel_start) + } + + .efi_runtime_rel : { + *(.rel*.efi_runtime) + *(.rel*.efi_runtime.*) + } + + .efi_runtime_rel_stop : + { + *(.__efi_runtime_rel_stop) + } + + . = ALIGN(4); + + .image_copy_end : + { + *(.__image_copy_end) + } + + .rel_dyn_start : + { + *(.__rel_dyn_start) + } + + .rel.dyn : { + *(.rel*) + } + + .rel_dyn_end : + { + *(.__rel_dyn_end) + } + + .end : + { + *(.__end) + } + + _image_binary_end = .; + + /* + * Deprecated: this MMU section is used by pxa at present but + * should not be used by new boards/CPUs. + */ + . = ALIGN(4096); + .mmutable : { + *(.mmutable) + } + +/* + * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c + * __bss_base and __bss_limit are for linker only (overlay ordering) + */ + + .bss_start __rel_dyn_start (OVERLAY) : { + KEEP(*(.__bss_start)); + __bss_base = .; + } + + .bss __bss_base (OVERLAY) : { + *(.bss*) + . = ALIGN(4); + __bss_limit = .; + } + + .bss_end __bss_limit (OVERLAY) : { + KEEP(*(.__bss_end)); + } + + .dynsym _image_binary_end : { *(.dynsym) } + .dynbss : { *(.dynbss) } + .dynstr : { *(.dynstr*) } + .dynamic : { *(.dynamic*) } + .plt : { *(.plt*) } + .interp : { *(.interp*) } + .gnu.hash : { *(.gnu.hash) } + .gnu : { *(.gnu*) } + .ARM.exidx : { *(.ARM.exidx*) } + .gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) } +}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile new file mode 100644 index 0000000..dda4e59 --- /dev/null +++ b/arch/arm/dts/Makefile
@@ -0,0 +1,586 @@ +# SPDX-License-Identifier: GPL-2.0+ + +dtb-$(CONFIG_TARGET_SMARTWEB) += at91sam9260-smartweb.dtb +dtb-$(CONFIG_TARGET_TAURUS) += at91sam9g20-taurus.dtb +dtb-$(CONFIG_TARGET_CORVUS) += at91sam9g45-corvus.dtb +dtb-$(CONFIG_TARGET_GURNARD) += at91sam9g45-gurnard.dtb + +dtb-$(CONFIG_S5PC100) += s5pc1xx-smdkc100.dtb +dtb-$(CONFIG_S5PC110) += s5pc1xx-goni.dtb +dtb-$(CONFIG_EXYNOS4) += exynos4210-origen.dtb \ + exynos4210-smdkv310.dtb \ + exynos4210-universal_c210.dtb \ + exynos4210-trats.dtb \ + exynos4412-trats2.dtb \ + exynos4412-odroid.dtb + +dtb-$(CONFIG_TARGET_HIKEY) += hi6220-hikey.dtb + +dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \ + exynos5250-snow.dtb \ + exynos5250-spring.dtb \ + exynos5250-smdk5250.dtb \ + exynos5420-smdk5420.dtb \ + exynos5420-peach-pit.dtb \ + exynos5800-peach-pi.dtb \ + exynos5422-odroidxu3.dtb +dtb-$(CONFIG_EXYNOS7420) += exynos7420-espresso7420.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += \ + rk3036-sdk.dtb \ + rk3128-evb.dtb \ + rk3188-radxarock.dtb \ + rk3288-evb.dtb \ + rk3288-fennec.dtb \ + rk3288-firefly.dtb \ + rk3288-miqi.dtb \ + rk3288-phycore-rdk.dtb \ + rk3288-popmetal.dtb \ + rk3288-rock2-square.dtb \ + rk3288-tinker.dtb \ + rk3288-veyron-jerry.dtb \ + rk3288-veyron-mickey.dtb \ + rk3288-veyron-minnie.dtb \ + rk3288-vyasa.dtb \ + rk3328-evb.dtb \ + rk3399-ficus.dtb \ + rk3368-lion.dtb \ + rk3368-sheep.dtb \ + rk3368-geekbox.dtb \ + rk3368-px5-evb.dtb \ + rk3399-evb.dtb \ + rk3399-firefly.dtb \ + rk3399-puma-ddr1333.dtb \ + rk3399-puma-ddr1600.dtb \ + rk3399-puma-ddr1866.dtb \ + rk3399-rock960.dtb \ + rv1108-elgin-r1.dtb \ + rv1108-evb.dtb +dtb-$(CONFIG_ARCH_MESON) += \ + meson-gxbb-nanopi-k2.dtb \ + meson-gxbb-odroidc2.dtb \ + meson-gxbb-nanopi-k2.dtb \ + meson-gxl-s905x-p212.dtb \ + meson-gxl-s905x-libretech-cc.dtb \ + meson-gxl-s905x-khadas-vim.dtb \ + meson-gxm-khadas-vim2.dtb \ + meson-axg-s400.dtb +dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \ + tegra20-medcom-wide.dtb \ + tegra20-paz00.dtb \ + tegra20-plutux.dtb \ + tegra20-seaboard.dtb \ + tegra20-tec.dtb \ + tegra20-trimslice.dtb \ + tegra20-ventana.dtb \ + tegra20-colibri.dtb \ + tegra30-apalis.dtb \ + tegra30-beaver.dtb \ + tegra30-cardhu.dtb \ + tegra30-colibri.dtb \ + tegra30-tec-ng.dtb \ + tegra114-dalmore.dtb \ + tegra124-apalis.dtb \ + tegra124-jetson-tk1.dtb \ + tegra124-nyan-big.dtb \ + tegra124-cei-tk1-som.dtb \ + tegra124-venice2.dtb \ + tegra186-p2771-0000-000.dtb \ + tegra186-p2771-0000-500.dtb \ + tegra210-e2220-1170.dtb \ + tegra210-p2371-0000.dtb \ + tegra210-p2371-2180.dtb \ + tegra210-p2571.dtb + +dtb-$(CONFIG_ARCH_MVEBU) += \ + armada-3720-db.dtb \ + armada-3720-espressobin.dtb \ + armada-3720-turris-mox.dtb \ + armada-375-db.dtb \ + armada-388-clearfog.dtb \ + armada-388-gp.dtb \ + armada-388-helios4.dtb \ + armada-385-amc.dtb \ + armada-7040-db.dtb \ + armada-7040-db-nand.dtb \ + armada-8040-db.dtb \ + armada-8040-mcbin.dtb \ + armada-8040-clearfog-gt-8k.dtb \ + armada-xp-gp.dtb \ + armada-xp-maxbcm.dtb \ + armada-xp-synology-ds414.dtb \ + armada-xp-theadorable.dtb \ + armada-38x-controlcenterdc.dtb + +dtb-$(CONFIG_ARCH_UNIPHIER_LD11) += \ + uniphier-ld11-global.dtb \ + uniphier-ld11-ref.dtb +dtb-$(CONFIG_ARCH_UNIPHIER_LD20) += \ + uniphier-ld20-global.dtb \ + uniphier-ld20-ref.dtb +dtb-$(CONFIG_ARCH_UNIPHIER_LD4) += \ + uniphier-ld4-ref.dtb +dtb-$(CONFIG_ARCH_UNIPHIER_LD6B) += \ + uniphier-ld6b-ref.dtb +dtb-$(CONFIG_ARCH_UNIPHIER_PRO4) += \ + uniphier-pro4-ace.dtb \ + uniphier-pro4-ref.dtb \ + uniphier-pro4-sanji.dtb +dtb-$(CONFIG_ARCH_UNIPHIER_PRO5) += \ + uniphier-pro5-4kbox.dtb +dtb-$(CONFIG_ARCH_UNIPHIER_PXS2) += \ + uniphier-pxs2-gentil.dtb \ + uniphier-pxs2-vodka.dtb +dtb-$(CONFIG_ARCH_UNIPHIER_PXS3) += \ + uniphier-pxs3-ref.dtb +dtb-$(CONFIG_ARCH_UNIPHIER_SLD8) += \ + uniphier-sld8-ref.dtb + +dtb-$(CONFIG_ARCH_ZYNQ) += \ + zynq-cc108.dtb \ + zynq-cse-nand.dtb \ + zynq-cse-nor.dtb \ + zynq-cse-qspi-single.dtb \ + zynq-dlc20-rev1.0.dtb \ + zynq-microzed.dtb \ + zynq-minized.dtb \ + zynq-picozed.dtb \ + zynq-syzygy-hub.dtb \ + zynq-topic-miami.dtb \ + zynq-topic-miamilite.dtb \ + zynq-topic-miamiplus.dtb \ + zynq-zc702.dtb \ + zynq-zc706.dtb \ + zynq-zc770-xm010.dtb \ + zynq-zc770-xm011.dtb \ + zynq-zc770-xm012.dtb \ + zynq-zc770-xm013.dtb \ + zynq-zed.dtb \ + zynq-zturn.dtb \ + zynq-zybo.dtb \ + zynq-zybo-z7.dtb +dtb-$(CONFIG_ARCH_ZYNQMP) += \ + avnet-ultra96-rev1.dtb \ + zynqmp-mini.dtb \ + zynqmp-mini-emmc0.dtb \ + zynqmp-mini-emmc1.dtb \ + zynqmp-mini-nand.dtb \ + zynqmp-mini-qspi.dtb \ + zynqmp-zcu100-revC.dtb \ + zynqmp-zcu102-revA.dtb \ + zynqmp-zcu102-revB.dtb \ + zynqmp-zcu102-rev1.0.dtb \ + zynqmp-zcu104-revA.dtb \ + zynqmp-zcu104-revC.dtb \ + zynqmp-zcu106-revA.dtb \ + zynqmp-zcu111-revA.dtb \ + zynqmp-zc1232-revA.dtb \ + zynqmp-zc1254-revA.dtb \ + zynqmp-zc1275-revA.dtb \ + zynqmp-zc1275-revB.dtb \ + zynqmp-zc1751-xm015-dc1.dtb \ + zynqmp-zc1751-xm016-dc2.dtb \ + zynqmp-zc1751-xm017-dc3.dtb \ + zynqmp-zc1751-xm018-dc4.dtb \ + zynqmp-zc1751-xm019-dc5.dtb +dtb-$(CONFIG_ARCH_ZYNQMP_R5) += \ + zynqmp-r5.dtb +dtb-$(CONFIG_AM33XX) += am335x-boneblack.dtb am335x-bone.dtb \ + am335x-draco.dtb \ + am335x-evm.dtb \ + am335x-evmsk.dtb \ + am335x-bonegreen.dtb \ + am335x-icev2.dtb \ + am335x-pxm50.dtb \ + am335x-rut.dtb \ + am335x-pdu001.dtb \ + am335x-chiliboard.dtb +dtb-$(CONFIG_AM43XX) += am437x-gp-evm.dtb am437x-sk-evm.dtb \ + am43x-epos-evm.dtb \ + am437x-idk-evm.dtb \ + am4372-generic.dtb +dtb-$(CONFIG_TI816X) += dm8168-evm.dtb +dtb-$(CONFIG_THUNDERX) += thunderx-88xx.dtb + +dtb-$(CONFIG_ARCH_SOCFPGA) += \ + socfpga_arria5_socdk.dtb \ + socfpga_arria10_socdk_sdmmc.dtb \ + socfpga_cyclone5_is1.dtb \ + socfpga_cyclone5_socdk.dtb \ + socfpga_cyclone5_dbm_soc1.dtb \ + socfpga_cyclone5_de0_nano_soc.dtb \ + socfpga_cyclone5_de1_soc.dtb \ + socfpga_cyclone5_de10_nano.dtb \ + socfpga_cyclone5_sockit.dtb \ + socfpga_cyclone5_socrates.dtb \ + socfpga_cyclone5_sr1500.dtb \ + socfpga_cyclone5_vining_fpga.dtb \ + socfpga_stratix10_socdk.dtb + +dtb-$(CONFIG_TARGET_DRA7XX_EVM) += dra72-evm.dtb dra7-evm.dtb \ + dra72-evm-revc.dtb dra71-evm.dtb dra76-evm.dtb +dtb-$(CONFIG_TARGET_AM57XX_EVM) += am57xx-beagle-x15.dtb \ + am57xx-beagle-x15-revb1.dtb \ + am57xx-beagle-x15-revc.dtb \ + am574x-idk.dtb \ + am572x-idk.dtb \ + am571x-idk.dtb +dtb-$(CONFIG_TARGET_STV0991) += stv0991.dtb + +dtb-$(CONFIG_ARCH_LS1021A) += ls1021a-qds-duart.dtb \ + ls1021a-qds-lpuart.dtb \ + ls1021a-twr-duart.dtb ls1021a-twr-lpuart.dtb \ + ls1021a-iot-duart.dtb +dtb-$(CONFIG_FSL_LSCH3) += fsl-ls2080a-qds.dtb \ + fsl-ls2080a-rdb.dtb \ + fsl-ls2081a-rdb.dtb \ + fsl-ls2088a-rdb-qspi.dtb \ + fsl-ls1088a-rdb.dtb \ + fsl-ls1088a-qds.dtb +dtb-$(CONFIG_FSL_LSCH2) += fsl-ls1043a-qds-duart.dtb \ + fsl-ls1043a-qds-lpuart.dtb \ + fsl-ls1043a-rdb.dtb \ + fsl-ls1046a-qds-duart.dtb \ + fsl-ls1046a-qds-lpuart.dtb \ + fsl-ls1046a-rdb.dtb \ + fsl-ls1012a-qds.dtb \ + fsl-ls1012a-rdb.dtb \ + fsl-ls1012a-2g5rdb.dtb \ + fsl-ls1012a-frdm.dtb \ + fsl-ls1012a-frwy.dtb + +dtb-$(CONFIG_TARGET_DRAGONBOARD410C) += dragonboard410c.dtb +dtb-$(CONFIG_TARGET_DRAGONBOARD820C) += dragonboard820c.dtb + +dtb-$(CONFIG_STM32F4) += stm32f429-disco.dtb \ + stm32429i-eval.dtb \ + stm32f469-disco.dtb + +dtb-$(CONFIG_STM32F7) += stm32f746-disco.dtb \ + stm32f769-disco.dtb \ + stm32746g-eval.dtb +dtb-$(CONFIG_STM32H7) += stm32h743i-disco.dtb \ + stm32h743i-eval.dtb + +dtb-$(CONFIG_MACH_SUN4I) += \ + sun4i-a10-a1000.dtb \ + sun4i-a10-ba10-tvbox.dtb \ + sun4i-a10-chuwi-v7-cw0825.dtb \ + sun4i-a10-cubieboard.dtb \ + sun4i-a10-dserve-dsrv9703c.dtb \ + sun4i-a10-gemei-g9.dtb \ + sun4i-a10-hackberry.dtb \ + sun4i-a10-hyundai-a7hd.dtb \ + sun4i-a10-inet1.dtb \ + sun4i-a10-inet-3f.dtb \ + sun4i-a10-inet-3w.dtb \ + sun4i-a10-inet97fv2.dtb \ + sun4i-a10-inet9f-rev03.dtb \ + sun4i-a10-itead-iteaduino-plus.dtb \ + sun4i-a10-jesurun-q5.dtb \ + sun4i-a10-marsboard.dtb \ + sun4i-a10-mini-xplus.dtb \ + sun4i-a10-mk802.dtb \ + sun4i-a10-mk802ii.dtb \ + sun4i-a10-olinuxino-lime.dtb \ + sun4i-a10-pcduino.dtb \ + sun4i-a10-pcduino2.dtb \ + sun4i-a10-pov-protab2-ips9.dtb +dtb-$(CONFIG_MACH_SUN5I) += \ + sun5i-a10s-auxtek-t003.dtb \ + sun5i-a10s-auxtek-t004.dtb \ + sun5i-a10s-mk802.dtb \ + sun5i-a10s-olinuxino-micro.dtb \ + sun5i-a10s-r7-tv-dongle.dtb \ + sun5i-a10s-wobo-i5.dtb \ + sun5i-a13-ampe-a76.dtb \ + sun5i-a13-difrnce-dit4350.dtb \ + sun5i-a13-empire-electronix-d709.dtb \ + sun5i-a13-empire-electronix-m712.dtb \ + sun5i-a13-hsg-h702.dtb \ + sun5i-a13-inet-86vs.dtb \ + sun5i-a13-inet-98v-rev2.dtb \ + sun5i-a13-olinuxino.dtb \ + sun5i-a13-olinuxino-micro.dtb \ + sun5i-a13-q8-tablet.dtb \ + sun5i-a13-utoo-p66.dtb \ + sun5i-gr8-chip-pro.dtb \ + sun5i-r8-chip.dtb +dtb-$(CONFIG_MACH_SUN6I) += \ + sun6i-a31-app4-evb1.dtb \ + sun6i-a31-colombus.dtb \ + sun6i-a31-hummingbird.dtb \ + sun6i-a31-i7.dtb \ + sun6i-a31-m9.dtb \ + sun6i-a31-mele-a1000g-quad.dtb \ + sun6i-a31-mixtile-loftq.dtb \ + sun6i-a31s-colorfly-e708-q1.dtb \ + sun6i-a31s-cs908.dtb \ + sun6i-a31s-inet-q972.dtb \ + sun6i-a31s-primo81.dtb \ + sun6i-a31s-sina31s.dtb \ + sun6i-a31s-sinovoip-bpi-m2.dtb \ + sun6i-a31s-yones-toptech-bs1078-v2.dtb +dtb-$(CONFIG_MACH_SUN7I) += \ + sun7i-a20-ainol-aw1.dtb \ + sun7i-a20-bananapi.dtb \ + sun7i-a20-bananapi-m1-plus.dtb \ + sun7i-a20-bananapro.dtb \ + sun7i-a20-cubieboard2.dtb \ + sun7i-a20-cubietruck.dtb \ + sun7i-a20-hummingbird.dtb \ + sun7i-a20-i12-tvbox.dtb \ + sun7i-a20-icnova-swac.dtb \ + sun7i-a20-itead-ibox.dtb \ + sun7i-a20-lamobo-r1.dtb \ + sun7i-a20-m3.dtb \ + sun7i-a20-m5.dtb \ + sun7i-a20-mk808c.dtb \ + sun7i-a20-olimex-som-evb.dtb \ + sun7i-a20-olimex-som204-evb.dtb \ + sun7i-a20-olimex-som204-evb-emmc.dtb \ + sun7i-a20-olinuxino-lime.dtb \ + sun7i-a20-olinuxino-lime2.dtb \ + sun7i-a20-olinuxino-lime2-emmc.dtb \ + sun7i-a20-olinuxino-micro.dtb \ + sun7i-a20-orangepi.dtb \ + sun7i-a20-orangepi-mini.dtb \ + sun7i-a20-pcduino3.dtb \ + sun7i-a20-pcduino3-nano.dtb \ + sun7i-a20-primo73.dtb \ + sun7i-a20-wexler-tab7200.dtb \ + sun7i-a20-wits-pro-a20-dkt.dtb \ + sun7i-a20-yones-toptech-bd1078.dtb +dtb-$(CONFIG_MACH_SUN8I_A23) += \ + sun8i-a23-evb.dtb \ + sun8i-a23-gt90h-v4.dtb \ + sun8i-a23-inet86dz.dtb \ + sun8i-a23-polaroid-mid2407pxe03.dtb \ + sun8i-a23-polaroid-mid2809pxe04.dtb \ + sun8i-a23-q8-tablet.dtb +dtb-$(CONFIG_MACH_SUN8I_A33) += \ + sun8i-a33-ga10h-v1.1.dtb \ + sun8i-a33-inet-d978-rev2.dtb \ + sun8i-a33-olinuxino.dtb \ + sun8i-a33-q8-tablet.dtb \ + sun8i-a33-sinlinx-sina33.dtb \ + sun8i-r16-bananapi-m2m.dtb \ + sun8i-r16-nintendo-nes-classic-edition.dtb \ + sun8i-r16-parrot.dtb +dtb-$(CONFIG_MACH_SUN8I_A83T) += \ + sun8i-a83t-allwinner-h8homlet-v2.dtb \ + sun8i-a83t-bananapi-m3.dtb \ + sun8i-a83t-cubietruck-plus.dtb \ + sun8i-a83t-tbs-a711.dts +dtb-$(CONFIG_MACH_SUN8I_H3) += \ + sun8i-h2-plus-bananapi-m2-zero.dtb \ + sun8i-h2-plus-libretech-all-h3-cc.dtb \ + sun8i-h2-plus-orangepi-r1.dtb \ + sun8i-h2-plus-orangepi-zero.dtb \ + sun8i-h3-bananapi-m2-plus.dtb \ + sun8i-h3-libretech-all-h3-cc.dtb \ + sun8i-h3-nanopi-m1.dtb \ + sun8i-h3-nanopi-m1-plus.dtb \ + sun8i-h3-nanopi-neo.dtb \ + sun8i-h3-nanopi-neo-air.dtb \ + sun8i-h3-orangepi-2.dtb \ + sun8i-h3-orangepi-lite.dtb \ + sun8i-h3-orangepi-one.dtb \ + sun8i-h3-orangepi-pc.dtb \ + sun8i-h3-orangepi-pc-plus.dtb \ + sun8i-h3-orangepi-plus.dtb \ + sun8i-h3-orangepi-plus2e.dtb +dtb-$(CONFIG_MACH_SUN8I_R40) += \ + sun8i-r40-bananapi-m2-ultra.dtb \ + sun8i-v40-bananapi-m2-berry.dtb +dtb-$(CONFIG_MACH_SUN8I_V3S) += \ + sun8i-v3s-licheepi-zero.dtb +dtb-$(CONFIG_MACH_SUN50I_H5) += \ + sun50i-h5-libretech-all-h3-cc.dtb \ + sun50i-h5-nanopi-neo2.dtb \ + sun50i-h5-nanopi-neo-plus2.dtb \ + sun50i-h5-orangepi-zero-plus.dtb \ + sun50i-h5-orangepi-pc2.dtb \ + sun50i-h5-orangepi-prime.dtb \ + sun50i-h5-orangepi-zero-plus2.dtb +dtb-$(CONFIG_MACH_SUN50I_H6) += \ + sun50i-h6-orangepi-lite2.dtb \ + sun50i-h6-orangepi-one-plus.dtb \ + sun50i-h6-pine-h64.dtb +dtb-$(CONFIG_MACH_SUN50I) += \ + sun50i-a64-amarula-relic.dtb \ + sun50i-a64-bananapi-m64.dtb \ + sun50i-a64-nanopi-a64.dtb \ + sun50i-a64-olinuxino.dtb \ + sun50i-a64-orangepi-win.dtb \ + sun50i-a64-pine64-plus.dtb \ + sun50i-a64-pine64.dtb \ + sun50i-a64-pinebook.dtb \ + sun50i-a64-sopine-baseboard.dtb +dtb-$(CONFIG_MACH_SUN9I) += \ + sun9i-a80-optimus.dtb \ + sun9i-a80-cubieboard4.dtb \ + sun9i-a80-cx-a99.dtb + +dtb-$(CONFIG_VF610) += vf500-colibri.dtb \ + vf610-colibri.dtb \ + vf610-twr.dtb \ + pcm052.dtb \ + bk4r1.dtb + +dtb-$(CONFIG_MX53) += imx53-cx9020.dtb + +dtb-$(CONFIG_MX6QDL) += \ + imx6dl-icore.dtb \ + imx6dl-icore-mipi.dtb \ + imx6dl-icore-rqs.dtb \ + imx6dl-mamoj.dtb \ + imx6q-cm-fx6.dtb \ + imx6q-icore.dtb \ + imx6q-icore-mipi.dtb \ + imx6q-icore-rqs.dtb \ + imx6q-logicpd.dtb + +dtb-$(CONFIG_MX6SL) += imx6sl-evk.dtb + +dtb-$(CONFIG_MX6SL) += imx6sll-evk.dtb + +dtb-$(CONFIG_MX6SX) += \ + imx6sx-sabreauto.dtb \ + imx6sx-sdb.dtb + +dtb-$(CONFIG_MX6UL) += \ + imx6ul-geam.dtb \ + imx6ul-isiot-emmc.dtb \ + imx6ul-isiot-nand.dtb \ + imx6ul-opos6uldev.dtb \ + imx6ul-14x14-evk.dtb \ + imx6ul-9x9-evk.dtb + +dtb-$(CONFIG_MX6ULL) += imx6ull-14x14-evk.dtb + +dtb-$(CONFIG_MX7) += imx7-colibri.dtb \ + imx7d-sdb.dtb \ + imx7d-sdb-qspi.dtb + +dtb-$(CONFIG_ARCH_MX7ULP) += imx7ulp-evk.dtb + +dtb-$(CONFIG_ARCH_IMX8) += fsl-imx8qxp-mek.dtb + +dtb-$(CONFIG_ARCH_IMX8M) += fsl-imx8mq-evk.dtb + +dtb-$(CONFIG_RCAR_GEN3) += \ + r8a7795-h3ulcb-u-boot.dtb \ + r8a7795-salvator-x-u-boot.dtb \ + r8a7796-m3ulcb-u-boot.dtb \ + r8a7796-salvator-x-u-boot.dtb \ + r8a77965-salvator-x-u-boot.dtb \ + r8a77970-eagle-u-boot.dtb \ + r8a77990-ebisu-u-boot.dtb \ + r8a77995-draak-u-boot.dtb + +dtb-$(CONFIG_SOC_KEYSTONE) += keystone-k2hk-evm.dtb \ + keystone-k2l-evm.dtb \ + keystone-k2e-evm.dtb \ + keystone-k2g-evm.dtb \ + keystone-k2g-generic.dtb \ + keystone-k2g-ice.dtb + +dtb-$(CONFIG_TARGET_AT91SAM9261EK) += at91sam9261ek.dtb + +dtb-$(CONFIG_TARGET_PM9263) += at91sam9263ek.dtb + +dtb-$(CONFIG_TARGET_AT91SAM9263EK) += at91sam9263ek.dtb + +dtb-$(CONFIG_TARGET_AT91SAM9RLEK) += at91sam9rlek.dtb + +dtb-$(CONFIG_TARGET_AT91SAM9260EK) += \ + at91sam9260ek.dtb \ + at91sam9g20ek.dtb \ + at91sam9g20ek_2mmc.dtb + +dtb-$(CONFIG_TARGET_AT91SAM9M10G45EK) += at91sam9m10g45ek.dtb + +dtb-$(CONFIG_TARGET_AT91SAM9X5EK) += \ + at91sam9g15ek.dtb \ + at91sam9g25ek.dtb \ + at91sam9g35ek.dtb \ + at91sam9x25ek.dtb \ + at91sam9x35ek.dtb + +dtb-$(CONFIG_TARGET_AT91SAM9N12EK) += at91sam9n12ek.dtb + +dtb-$(CONFIG_TARGET_OMAP3_LOGIC) += \ + logicpd-torpedo-37xx-devkit.dtb \ + logicpd-som-lv-37xx-devkit.dtb + +dtb-$(CONFIG_TARGET_OMAP3_EVM) += \ + omap3-evm-37xx.dtb \ + omap3-evm.dtb + +dtb-$(CONFIG_TARGET_OMAP3_BEAGLE) += \ + omap3-beagle-xm-ab.dtb \ + omap3-beagle-xm.dtb \ + omap3-beagle.dtb + +dtb-$(CONFIG_TARGET_SAMA5D2_PTC_EK) += \ + at91-sama5d2_ptc_ek.dtb + +dtb-$(CONFIG_TARGET_SAMA5D2_XPLAINED) += \ + at91-sama5d2_xplained.dtb + +dtb-$(CONFIG_TARGET_SAMA5D27_SOM1_EK) += \ + at91-sama5d27_som1_ek.dtb + +dtb-$(CONFIG_TARGET_SAMA5D3XEK) += \ + sama5d31ek.dtb \ + sama5d33ek.dtb \ + sama5d34ek.dtb \ + sama5d35ek.dtb \ + sama5d36ek.dtb \ + sama5d36ek_cmp.dtb + +dtb-$(CONFIG_TARGET_SAMA5D3_XPLAINED) += \ + at91-sama5d3_xplained.dtb + +dtb-$(CONFIG_TARGET_SAMA5D4EK) += \ + at91-sama5d4ek.dtb + +dtb-$(CONFIG_TARGET_SAMA5D4_XPLAINED) += \ + at91-sama5d4_xplained.dtb + +dtb-$(CONFIG_TARGET_VINCO) += \ + at91-vinco.dtb + +dtb-$(CONFIG_ARCH_BCM283X) += \ + bcm2835-rpi-a-plus.dtb \ + bcm2835-rpi-a.dtb \ + bcm2835-rpi-b-plus.dtb \ + bcm2835-rpi-b-rev2.dtb \ + bcm2835-rpi-b.dtb \ + bcm2836-rpi-2-b.dtb \ + bcm2837-rpi-3-b.dtb + +dtb-$(CONFIG_ARCH_ASPEED) += ast2500-evb.dtb + +dtb-$(CONFIG_ARCH_STI) += stih410-b2260.dtb + +dtb-$(CONFIG_TARGET_STM32MP1) += \ + stm32mp157c-ed1.dtb \ + stm32mp157c-ev1.dtb + +dtb-$(CONFIG_SOC_K3_AM6) += k3-am654-base-board.dtb k3-am654-r5-base-board.dtb + +dtb-$(CONFIG_ARCH_MEDIATEK) += \ + mt7623n-bananapi-bpi-r2.dtb \ + mt7629-rfb.dtb + +targets += $(dtb-y) + +# Add any required device tree compiler flags here +DTC_FLAGS += + +PHONY += dtbs +dtbs: $(addprefix $(obj)/, $(dtb-y)) + @: + +clean-files := *.dtb
diff --git a/arch/arm/dts/am335x-baltos.dts b/arch/arm/dts/am335x-baltos.dts new file mode 100644 index 0000000..f939cf6 --- /dev/null +++ b/arch/arm/dts/am335x-baltos.dts
@@ -0,0 +1,439 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +/* + * VScom OnRISC + * http://www.vscom.de + */ + +/dts-v1/; + +#include "am33xx.dtsi" +#include <dt-bindings/pwm/pwm.h> + +/ { + model = "OnRISC Baltos"; + compatible = "vscom,onrisc", "ti,am33xx"; + + chosen { + stdout-path = &uart0; + }; + + cpus { + cpu@0 { + cpu0-supply = <&vdd1_reg>; + }; + }; + + vbat: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + }; +}; + +&am33xx_pinmux { + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + 0xf0 (MUX_MODE0 | INPUT_EN | PULL_UP) /* mmc0_dat3.mmc0_dat3 */ + 0xf4 (MUX_MODE0 | INPUT_EN | PULL_UP) /* mmc0_dat2.mmc0_dat2 */ + 0xf8 (MUX_MODE0 | INPUT_EN | PULL_UP) /* mmc0_dat1.mmc0_dat1 */ + 0xfc (MUX_MODE0 | INPUT_EN | PULL_UP) /* mmc0_dat0.mmc0_dat0 */ + 0x100 (MUX_MODE0 | INPUT_EN | PULL_UP) /* mmc0_clk.mmc0_clk */ + 0x104 (MUX_MODE0 | INPUT_EN | PULL_UP) /* mmc0_cmd.mmc0_cmd */ + >; + }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + 0x158 0x2a /* spi0_d1.i2c1_sda_mux3, INPUT | MODE2 */ + 0x15c 0x2a /* spi0_cs0.i2c1_scl_mux3, INPUT | MODE2 */ + >; + }; + + tps65910_pins: pinmux_tps65910_pins { + pinctrl-single,pins = < + 0x078 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_ben1.gpio1[28] */ + >; + + }; + tca6416_pins: pinmux_tca6416_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE7) /* xdma_event_intr1.gpio0[20] tca6416 stuff */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs_dv */ + 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_tx_en.rmii1_txen */ + 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */ + 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */ + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */ + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */ + 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii1_refclk */ + + + /* Slave 2 */ + 0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */ + 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rctl */ + 0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */ + 0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */ + 0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */ + 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */ + 0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */ + 0x5c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */ + 0x60 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */ + 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */ + 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */ + 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7) + + /* Slave 2 reset value*/ + 0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + nandflash_pins_s0: nandflash_pins_s0 { + pinctrl-single,pins = < + 0x0 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ + 0x4 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ + 0x8 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */ + 0xc (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */ + 0x10 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */ + 0x14 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */ + 0x18 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */ + 0x1c (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */ + 0x70 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */ + 0x74 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */ + 0x7c (PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */ + 0x90 (PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */ + 0x94 (PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */ + 0x98 (PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */ + 0x9c (PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */ + >; + }; +}; + +&elm { + status = "okay"; +}; + +&gpmc { + pinctrl-names = "default"; + pinctrl-0 = <&nandflash_pins_s0>; + ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */ + status = "okay"; + + nand@0,0 { + reg = <0 0 0>; /* CS0, offset 0 */ + nand-bus-width = <8>; + ti,nand-ecc-opt = "bch8"; + ti,nand-xfer-type = "polled"; + + gpmc,device-nand = "true"; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <40>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,wait-on-read = "true"; + gpmc,wait-on-write = "true"; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wait-monitoring-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + + #address-cells = <1>; + #size-cells = <1>; + elm_id = <&elm>; + + boot@0 { + label = "SPL"; + reg = <0x0 0x20000>; + }; + boot@20000{ + label = "SPL.backup1"; + reg = <0x20000 0x20000>; + }; + boot@40000 { + label = "SPL.backup2"; + reg = <0x40000 0x20000>; + }; + boot@60000 { + label = "SPL.backup3"; + reg = <0x60000 0x20000>; + }; + boot@80000 { + label = "u-boot"; + reg = <0x80000 0x1e0000>; + }; + boot@260000 { + label = "UBI"; + reg = <0x260000 0xfda0000>; + }; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + + status = "okay"; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + + status = "okay"; + clock-frequency = <1000>; + + tps: tps@2d { + reg = <0x2d>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gpio1>; + interrupts = <28 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&tps65910_pins>; + }; + + at24@50 { + compatible = "at24,24c02"; + pagesize = <8>; + reg = <0x50>; + }; + + tca6416: gpio@20 { + compatible = "ti,tca6416"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&gpio0>; + interrupts = <20 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&tca6416_pins>; + }; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&cppi41dma { + status = "okay"; +}; + +/include/ "tps65910.dtsi" + +&tps { + vcc1-supply = <&vbat>; + vcc2-supply = <&vbat>; + vcc3-supply = <&vbat>; + vcc4-supply = <&vbat>; + vcc5-supply = <&vbat>; + vcc6-supply = <&vbat>; + vcc7-supply = <&vbat>; + vccio-supply = <&vbat>; + + ti,en-ck32k-xtal = <1>; + + regulators { + vrtc_reg: regulator@0 { + regulator-always-on; + }; + + vio_reg: regulator@1 { + regulator-always-on; + }; + + vdd1_reg: regulator@2 { + /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1312500>; + regulator-boot-on; + regulator-always-on; + }; + + vdd2_reg: regulator@3 { + /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd3_reg: regulator@4 { + regulator-always-on; + }; + + vdig1_reg: regulator@5 { + regulator-always-on; + }; + + vdig2_reg: regulator@6 { + regulator-always-on; + }; + + vpll_reg: regulator@7 { + regulator-always-on; + }; + + vdac_reg: regulator@8 { + regulator-always-on; + }; + + vaux1_reg: regulator@9 { + regulator-always-on; + }; + + vaux2_reg: regulator@10 { + regulator-always-on; + }; + + vaux33_reg: regulator@11 { + regulator-always-on; + }; + + vmmc_reg: regulator@12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + dual_emac = <1>; + + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rmii"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <7>; + phy-mode = "rgmii-txid"; + dual_emac_res_vlan = <2>; +}; + +&phy_sel { + rmii-clock-ext = <1>; +}; + +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + vmmc-supply = <&vmmc_reg>; + status = "okay"; +}; + +&gpio0 { + ti,no-reset-on-init; +};
diff --git a/arch/arm/dts/am335x-bone-common.dtsi b/arch/arm/dts/am335x-bone-common.dtsi new file mode 100644 index 0000000..40a3c35 --- /dev/null +++ b/arch/arm/dts/am335x-bone-common.dtsi
@@ -0,0 +1,400 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +/ { + cpus { + cpu@0 { + cpu0-supply = <&dcdc2_reg>; + }; + }; + + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + leds { + pinctrl-names = "default"; + pinctrl-0 = <&user_leds_s0>; + + compatible = "gpio-leds"; + + led@2 { + label = "beaglebone:green:heartbeat"; + gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + + led@3 { + label = "beaglebone:green:mmc0"; + gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + default-state = "off"; + }; + + led@4 { + label = "beaglebone:green:usr2"; + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "cpu0"; + default-state = "off"; + }; + + led@5 { + label = "beaglebone:green:usr3"; + gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc1"; + default-state = "off"; + }; + }; + + vmmcsd_fixed: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vmmcsd_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&clkout2_pin>; + + user_leds_s0: user_leds_s0 { + pinctrl-single,pins = < + 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */ + 0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a6.gpio1_22 */ + 0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a7.gpio1_23 */ + 0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a8.gpio1_24 */ + >; + }; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + 0x178 (PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_ctsn.i2c2_sda */ + 0x17c (PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_rtsn.i2c2_scl */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + clkout2_pin: pinmux_clkout2_pin { + pinctrl-single,pins = < + 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + 0x110 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxerr.mii1_rxerr */ + 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */ + 0x118 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */ + 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */ + 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */ + 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */ + 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */ + 0x12c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_txclk.mii1_txclk */ + 0x130 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */ + 0x134 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */ + 0x138 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */ + 0x13c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */ + 0x140 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + 0x160 (PIN_INPUT | MUX_MODE7) /* GPIO0_6 */ + >; + }; + + emmc_pins: pinmux_emmc_pins { + pinctrl-single,pins = < + 0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */ + 0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ + 0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */ + 0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */ + 0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */ + 0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */ + 0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */ + 0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */ + 0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */ + 0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */ + >; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "peripheral"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&cppi41dma { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + + status = "okay"; + clock-frequency = <400000>; + + tps: tps@24 { + reg = <0x24>; + }; + + baseboard_eeprom: baseboard_eeprom@50 { + compatible = "at,24c256"; + reg = <0x50>; + + #address-cells = <1>; + #size-cells = <1>; + baseboard_data: baseboard_data@0 { + reg = <0 0x100>; + }; + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + + status = "okay"; + clock-frequency = <100000>; + + cape_eeprom0: cape_eeprom0@54 { + compatible = "at,24c256"; + reg = <0x54>; + #address-cells = <1>; + #size-cells = <1>; + cape0_data: cape_data@0 { + reg = <0 0x100>; + }; + }; + + cape_eeprom1: cape_eeprom1@55 { + compatible = "at,24c256"; + reg = <0x55>; + #address-cells = <1>; + #size-cells = <1>; + cape1_data: cape_data@0 { + reg = <0 0x100>; + }; + }; + + cape_eeprom2: cape_eeprom2@56 { + compatible = "at,24c256"; + reg = <0x56>; + #address-cells = <1>; + #size-cells = <1>; + cape2_data: cape_data@0 { + reg = <0 0x100>; + }; + }; + + cape_eeprom3: cape_eeprom3@57 { + compatible = "at,24c256"; + reg = <0x57>; + #address-cells = <1>; + #size-cells = <1>; + cape3_data: cape_data@0 { + reg = <0 0x100>; + }; + }; +}; + + +/include/ "tps65217.dtsi" + +&tps { + /* + * Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only + * mode") at poweroff. Most BeagleBone versions do not support RTC-only + * mode and risk hardware damage if this mode is entered. + * + * For details, see linux-omap mailing list May 2015 thread + * [PATCH] ARM: dts: am335x-bone* enable pmic-shutdown-controller + * In particular, messages: + * http://www.spinics.net/lists/linux-omap/msg118585.html + * http://www.spinics.net/lists/linux-omap/msg118615.html + * + * You can override this later with + * &tps { /delete-property/ ti,pmic-shutdown-controller; } + * if you want to use RTC-only mode and made sure you are not affected + * by the hardware problems. (Tip: double-check by performing a current + * measurement after shutdown: it should be less than 1 mA.) + */ + ti,pmic-shutdown-controller; + + regulators { + dcdc1_reg: regulator@0 { + regulator-name = "vdds_dpr"; + regulator-always-on; + }; + + dcdc2_reg: regulator@1 { + /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <1325000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc3_reg: regulator@2 { + /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1_reg: regulator@3 { + regulator-name = "vio,vrtc,vdds"; + regulator-always-on; + }; + + ldo2_reg: regulator@4 { + regulator-name = "vdd_3v3aux"; + regulator-always-on; + }; + + ldo3_reg: regulator@5 { + regulator-name = "vdd_1v8"; + regulator-always-on; + }; + + ldo4_reg: regulator@6 { + regulator-name = "vdd_3v3a"; + regulator-always-on; + }; + }; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "mii"; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "mii"; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; +}; + +&mmc1 { + status = "okay"; + bus-width = <0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; +}; + +&aes { + status = "okay"; +}; + +&sham { + status = "okay"; +};
diff --git a/arch/arm/dts/am335x-bone.dts b/arch/arm/dts/am335x-bone.dts new file mode 100644 index 0000000..6b84937 --- /dev/null +++ b/arch/arm/dts/am335x-bone.dts
@@ -0,0 +1,26 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +#include "am33xx.dtsi" +#include "am335x-bone-common.dtsi" + +/ { + model = "TI AM335x BeagleBone"; + compatible = "ti,am335x-bone", "ti,am33xx"; +}; + +&ldo3_reg { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; +}; + +&mmc1 { + vmmc-supply = <&ldo3_reg>; +};
diff --git a/arch/arm/dts/am335x-boneblack.dts b/arch/arm/dts/am335x-boneblack.dts new file mode 100644 index 0000000..27ebe4a --- /dev/null +++ b/arch/arm/dts/am335x-boneblack.dts
@@ -0,0 +1,90 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +#include "am33xx.dtsi" +#include "am335x-bone-common.dtsi" + +/ { + model = "TI AM335x BeagleBone Black"; + compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; +}; + +&ldo3_reg { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; +}; + +&mmc1 { + vmmc-supply = <&vmmcsd_fixed>; +}; + +&mmc2 { + vmmc-supply = <&vmmcsd_fixed>; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_pins>; + bus-width = <8>; + status = "okay"; +}; + +&am33xx_pinmux { + nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins { + pinctrl-single,pins = < + 0x1b0 0x03 /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */ + 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ + 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ + 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ + 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ + 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ + >; + }; + nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins { + pinctrl-single,pins = < + 0x1b0 0x03 /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */ + >; + }; +}; + +&lcdc { + status = "okay"; +}; + +/ { + hdmi { + compatible = "ti,tilcdc,slave"; + i2c = <&i2c0>; + pinctrl-names = "default", "off"; + pinctrl-0 = <&nxp_hdmi_bonelt_pins>; + pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>; + status = "okay"; + }; +}; + +&rtc { + system-power-controller; +};
diff --git a/arch/arm/dts/am335x-bonegreen.dts b/arch/arm/dts/am335x-bonegreen.dts new file mode 100644 index 0000000..9c59da9 --- /dev/null +++ b/arch/arm/dts/am335x-bonegreen.dts
@@ -0,0 +1,57 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +#include "am33xx.dtsi" +#include "am335x-bone-common.dtsi" + +/ { + model = "TI AM335x BeagleBone Green"; + compatible = "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; +}; + +&ldo3_reg { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; +}; + +&mmc1 { + vmmc-supply = <&vmmcsd_fixed>; +}; + +&mmc2 { + vmmc-supply = <&vmmcsd_fixed>; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_pins>; + bus-width = <8>; + status = "okay"; +}; + +&am33xx_pinmux { + uart2_pins: uart2_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1) /* spi0_sclk.uart2_rxd */ + AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1) /* spi0_d0.uart2_txd */ + >; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "okay"; +}; + +&rtc { + system-power-controller; +};
diff --git a/arch/arm/dts/am335x-brppt1-mmc.dts b/arch/arm/dts/am335x-brppt1-mmc.dts new file mode 100644 index 0000000..9be34d9 --- /dev/null +++ b/arch/arm/dts/am335x-brppt1-mmc.dts
@@ -0,0 +1,345 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 B&R Industrial Automation GmbH + * http://www.br-automation.com + * + */ +/dts-v1/; + +#include "am33xx.dtsi" + +/ { + model = "BRPPT1 (MMC) Panel"; + compatible = "ti,am33xx"; + + fset: factory-settings { + bl-version = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890"; + version = <0x0100>; + order-no = "6PPT30 (MMC)"; + hw-revision = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890"; + serial-no = "0"; + device-id = <0x0>; + parent-id = <0x0>; + hw-variant = <0x1>; + }; + + aliases { + ds1bkl0 = &pwmbacklight; + ds1bkl1 = &tps_bl; + ds1timing = &timing0; + ds1ctrl = &lcdc; + gpmc = &gpmc; + mmc = &mmc2; + fset = &fset; + }; + + chosen { + bootargs = "console=ttyO0,115200 earlyprintk"; + stdout-path = &uart0; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + panel { + status = "disabled"; + + compatible = "ti,tilcdc,panel"; + enable-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + + backlight = <&pwmbacklight>; + bkl-pwm = <&pwmbacklight>; + bkl-tps = <&tps_bl>; + + panel-info { + ac-bias = <255>; + ac-bias-intrpt = <0>; + dma-burst-sz = <16>; + bpp = <32>; + fdd = <0x80>; + sync-edge = <0>; + sync-ctrl = <1>; + raster-order = <0>; + fifo-th = <0>; + }; + + display-timings { + native-mode = <&timing0>; + timing0: lcd { + clock-frequency = <32000000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <2>; + hback-porch = <192>; + hsync-len = <1>; + vfront-porch = <20>; + vback-porch = <2>; + vsync-len = <1>; + hsync-active = <1>; + vsync-active = <1>; + pupdelay = <10>; + pondelay = <10>; + }; + }; + }; + + vmmcsd_fixed: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vmmcsd_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + pwm0: omap-pwm@timer5 { + compatible = "ti,omap-dmtimer-pwm"; + ti,timers = <&timer5>; + #pwm-cells = <3>; + }; + + pwm1: omap-pwm@timer6 { + compatible = "ti,omap-dmtimer-pwm"; + ti,timers = <&timer6>; + #pwm-cells = <3>; + }; + + beeper: pwm-beep { + compatible = "pwm-beeper"; + pwms = <&pwm0 0 0 0>; + }; + + pwmbacklight: pwm-bkl { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 5000000 0>; + + default-brightness-level = <255>; + brightness-levels = <0 16 32 64 128 170 202 234 255>; + + power-supply = <&vmmcsd_fixed>; + enable-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + }; +}; + +&uart0 { /* console uart */ + u-boot,dm-spl; + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&i2c0 { + u-boot,dm-spl; + status = "okay"; + clock-frequency = <400000>; + + tps: tps@24 { /* PMIC controller */ + u-boot,dm-spl; + reg = <0x24>; + compatible = "ti,tps65217"; + + tps_bl: backlight { + compatible = "ti,tps65217-bl"; + isel = <1>; /* 1 - ISET1, 2 ISET2 */ + fdim = <1000>; /* TPS65217_BL_FDIM_1kHZ */ + default-brightness = <50>; + }; + }; +}; + +&i2c2 { + status = "okay"; + clock-frequency = <100000>; +}; + +&edma { + status = "okay"; +}; + +&cppi41dma { + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&davinci_mdio { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <1>; + }; + + phy1: ethernet-phy@1 { + reg = <2>; + }; +}; + +&mac { + status = "okay"; +}; + +&cpsw_emac0 { + phy-handle = <&phy0>; + dual_emac_res_vlan = <1>; + phy-mode = "mii"; +}; + +&cpsw_emac1 { + phy-handle = <&phy1>; + dual_emac_res_vlan = <2>; + phy-mode = "mii"; +}; + +&mmc1 { + u-boot,dm-spl; + vmmc-supply = <&vmmcsd_fixed>; + bus-width = <0x4>; + ti,non-removable; + ti,needs-special-hs-handling; + ti,vcc-aux-disable-is-sleep; + status = "okay"; +}; + +&mmc2 { + u-boot,dm-spl; + vmmc-supply = <&vmmcsd_fixed>; + bus-width = <0x8>; + ti,non-removable; + ti,needs-special-hs-handling; + ti,vcc-aux-disable-is-sleep; + status = "okay"; +}; + +&lcdc { + status = "disabled"; +}; + +&elm { + status = "okay"; +}; + +&sham { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&gpio0 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio1 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio2 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio3 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&wdt2 { + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&tscadc { + status = "okay"; + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; + ti,zx-cutoff-ratio = <40>; + ti,min_deviation = <60>; + ti,max_deviation = <600>; + ti,coordinate-readouts = <5>; + ti,wire-config = <0x00 0x11 0x22 0x33>; + + bnr-buttons { + Home-Button {}; + }; + }; + + adc { + ti,adc-channels = <5 6 7>; + }; +}; + +&timer6 { /* used for cpsw end device */ + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&timer7 { /* used for cpsw end device */ + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&wdt2 { + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&epwmss0 { + status = "okay"; +}; + +&tscadc { + status = "okay"; +}; + +&dcan0 { + status = "okay"; +}; + +&dcan1 { + status = "okay"; +}; + +&sham { + status = "disabled"; +}; + +&aes { + status = "disabled"; +}; + +&rng { + status = "disabled"; +};
diff --git a/arch/arm/dts/am335x-brppt1-nand.dts b/arch/arm/dts/am335x-brppt1-nand.dts new file mode 100644 index 0000000..11bd5c5 --- /dev/null +++ b/arch/arm/dts/am335x-brppt1-nand.dts
@@ -0,0 +1,363 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 B&R Industrial Automation GmbH + * http://www.br-automation.com + * + */ +/dts-v1/; + +#include "am33xx.dtsi" + +/ { + model = "BRPPT1 (NAND) Panel"; + compatible = "ti,am33xx"; + + fset: factory-settings { + bl-version = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890"; + version = <0x0100>; + order-no = "6PPT30 (NAND)"; + hw-revision = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890"; + serial-no = "0"; + device-id = <0x0>; + parent-id = <0x0>; + hw-variant = <0x1>; + }; + + aliases { + ds1bkl0 = &pwmbacklight; + ds1bkl1 = &tps_bl; + ds1timing = &timing0; + ds1ctrl = &lcdc; + gpmc = &gpmc; + mmc = &mmc2; + fset = &fset; + }; + + chosen { + bootargs = "console=ttyO0,115200 earlyprintk"; + stdout-path = &uart0; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + panel { + status = "disabled"; + + compatible = "ti,tilcdc,panel"; + enable-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + + backlight = <&pwmbacklight>; + bkl-pwm = <&pwmbacklight>; + bkl-tps = <&tps_bl>; + + panel-info { + ac-bias = <255>; + ac-bias-intrpt = <0>; + dma-burst-sz = <16>; + bpp = <32>; + fdd = <0x80>; + sync-edge = <0>; + sync-ctrl = <1>; + raster-order = <0>; + fifo-th = <0>; + }; + + display-timings { + native-mode = <&timing0>; + timing0: lcd { + clock-frequency = <32000000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <2>; + hback-porch = <192>; + hsync-len = <1>; + vfront-porch = <20>; + vback-porch = <2>; + vsync-len = <1>; + hsync-active = <1>; + vsync-active = <1>; + pupdelay = <10>; + pondelay = <10>; + }; + }; + }; + + vmmcsd_fixed: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vmmcsd_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + pwm0: omap-pwm@timer5 { + compatible = "ti,omap-dmtimer-pwm"; + ti,timers = <&timer5>; + #pwm-cells = <3>; + }; + + pwm1: omap-pwm@timer6 { + compatible = "ti,omap-dmtimer-pwm"; + ti,timers = <&timer6>; + #pwm-cells = <3>; + }; + + beeper: pwm-beep { + compatible = "pwm-beeper"; + pwms = <&pwm0 0 0 0>; + }; + + pwmbacklight: pwm-bkl { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 5000000 0>; + + default-brightness-level = <255>; + brightness-levels = <0 16 32 64 128 170 202 234 255>; + + power-supply = <&vmmcsd_fixed>; + enable-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + }; +}; + +&uart0 { /* console uart */ + u-boot,dm-spl; + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&i2c0 { + u-boot,dm-spl; + status = "okay"; + clock-frequency = <400000>; + + tps: tps@24 { /* PMIC controller */ + u-boot,dm-spl; + reg = <0x24>; + compatible = "ti,tps65217"; + + tps_bl: backlight { + compatible = "ti,tps65217-bl"; + isel = <1>; /* 1 - ISET1, 2 ISET2 */ + fdim = <1000>; /* TPS65217_BL_FDIM_1kHZ */ + default-brightness = <50>; + }; + }; +}; + +&i2c2 { + status = "okay"; + clock-frequency = <100000>; +}; + +&edma { + status = "okay"; +}; + +&cppi41dma { + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&davinci_mdio { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <1>; + }; + + phy1: ethernet-phy@1 { + reg = <2>; + }; +}; + +&mac { + dual_emac; + status = "okay"; +}; + +&cpsw_emac0 { + phy-handle = <&phy0>; + dual_emac_res_vlan = <1>; + phy-mode = "mii"; +}; + +&cpsw_emac1 { + phy-handle = <&phy1>; + dual_emac_res_vlan = <2>; + phy-mode = "mii"; +}; + +&mmc2 { + vmmc-supply = <&vmmcsd_fixed>; + bus-width = <0x4>; + ti,non-removable; + ti,needs-special-hs-handling; + ti,vcc-aux-disable-is-sleep; + status = "disabled"; +}; + +&lcdc { + status = "disabled"; +}; + +&elm { + status = "okay"; +}; + +&sham { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&gpio0 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio1 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio2 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio3 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&wdt2 { + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&tscadc { + status = "okay"; + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; + ti,zx-cutoff-ratio = <40>; + ti,min_deviation = <60>; + ti,max_deviation = <600>; + ti,coordinate-readouts = <5>; + ti,wire-config = <0x00 0x11 0x22 0x33>; + + bnr-buttons { + Home-Button {}; + }; + }; + + adc { + ti,adc-channels = <5 6 7>; + }; +}; + +&gpmc { + u-boot,dm-spl; + status = "okay"; + pinctrl-names = "default"; + ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */ + nand@0,0 { + compatible = "ti,omap2-nand"; + reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ + interrupt-parent = <&gpmc>; + rb-gpios = <&gpmc 1 GPIO_ACTIVE_HIGH>; /* gpmc_wait1 */ + ti,nand-ecc-opt = "bch8"; + ti,elm-id = <&elm>; + nand-bus-width = <8>; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <40>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,wait-on-read = "true"; + gpmc,wait-on-write = "true"; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wait-monitoring-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + gpmc,wait-pin = <1>; + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + label = "NAND.MLO"; + reg = <0x00000000 0x000020000>; + }; + partition@1 { + label = "NAND.cfgscr"; + reg = <0x00020000 0x00020000>; + }; + partition@2 { + label = "NAND.dtb"; + reg = <0x00040000 0x00020000>; + }; + partition@3 { + label = "NAND.u-boot-env"; + reg = <0x00060000 0x00020000>; + }; + partition@4 { + label = "NAND.u-boot"; + reg = <0x00080000 0x00080000>; + }; + partition@5 { + label = "NAND.kernel"; + reg = <0x00100000 0x00400000>; + }; + partition@6 { + label = "NAND.rootfs"; + reg = <0x00500000 0x08000000>; + }; + partition@7 { + label = "NAND.user"; + reg = <0x08500000 0x17b00000>; + }; + }; +};
diff --git a/arch/arm/dts/am335x-brppt1-spi.dts b/arch/arm/dts/am335x-brppt1-spi.dts new file mode 100644 index 0000000..522ed50 --- /dev/null +++ b/arch/arm/dts/am335x-brppt1-spi.dts
@@ -0,0 +1,366 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 B&R Industrial Automation GmbH + * http://www.br-automation.com + * + */ +/dts-v1/; + +#include "am33xx.dtsi" + +/ { + model = "BRPPT1 (MMC) Panel"; + compatible = "ti,am33xx"; + + fset: factory-settings { + bl-version = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890"; + version = <0x0100>; + order-no = "6PPT30 (SPI)"; + hw-revision = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456890"; + serial-no = "0"; + device-id = <0x0>; + parent-id = <0x0>; + hw-variant = <0x1>; + }; + + aliases { + ds1bkl0 = &pwmbacklight; + ds1bkl1 = &tps_bl; + ds1timing = &timing0; + ds1ctrl = &lcdc; + gpmc = &gpmc; + mmc = &mmc2; + spi0 = &spi0; + fset = &fset; + }; + + chosen { + bootargs = "console=ttyO0,115200 earlyprintk"; + stdout-path = &uart0; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + panel { + status = "disabled"; + + compatible = "ti,tilcdc,panel"; + enable-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + + backlight = <&pwmbacklight>; + bkl-pwm = <&pwmbacklight>; + bkl-tps = <&tps_bl>; + + panel-info { + ac-bias = <255>; + ac-bias-intrpt = <0>; + dma-burst-sz = <16>; + bpp = <32>; + fdd = <0x80>; + sync-edge = <0>; + sync-ctrl = <1>; + raster-order = <0>; + fifo-th = <0>; + }; + + display-timings { + native-mode = <&timing0>; + timing0: lcd { + clock-frequency = <32000000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <2>; + hback-porch = <192>; + hsync-len = <1>; + vfront-porch = <20>; + vback-porch = <2>; + vsync-len = <1>; + hsync-active = <1>; + vsync-active = <1>; + pupdelay = <10>; + pondelay = <10>; + }; + }; + }; + + vmmcsd_fixed: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vmmcsd_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + pwm0: omap-pwm@timer5 { + compatible = "ti,omap-dmtimer-pwm"; + ti,timers = <&timer5>; + #pwm-cells = <3>; + }; + + pwm1: omap-pwm@timer6 { + compatible = "ti,omap-dmtimer-pwm"; + ti,timers = <&timer6>; + #pwm-cells = <3>; + }; + + beeper: pwm-beep { + compatible = "pwm-beeper"; + pwms = <&pwm0 0 0 0>; + }; + + pwmbacklight: pwm-bkl { + compatible = "pwm-backlight"; + pwms = <&pwm1 0 5000000 0>; + + default-brightness-level = <255>; + brightness-levels = <0 16 32 64 128 170 202 234 255>; + + power-supply = <&vmmcsd_fixed>; + enable-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + }; +}; + +&uart0 { /* console uart */ + u-boot,dm-spl; + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&i2c0 { + u-boot,dm-spl; + status = "okay"; + clock-frequency = <400000>; + + tps: tps@24 { /* PMIC controller */ + u-boot,dm-spl; + reg = <0x24>; + compatible = "ti,tps65217"; + + tps_bl: backlight { + compatible = "ti,tps65217-bl"; + isel = <1>; /* 1 - ISET1, 2 ISET2 */ + fdim = <1000>; /* TPS65217_BL_FDIM_1kHZ */ + default-brightness = <50>; + }; + }; +}; + +&i2c2 { + status = "okay"; + clock-frequency = <100000>; +}; + +&spi0 { + u-boot,dm-spl; + status = "okay"; + + cs-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>, + <&gpio0 6 GPIO_ACTIVE_HIGH>, + <0>, + <0>; + + spi-max-frequency = <24000000>; + + spi_flash: spiflash@0 { + u-boot,dm-spl; + u-boot,dm-pre-reloc; + compatible = "spidev", "spi-flash"; + spi-max-frequency = <24000000>; + reg = <0>; + }; +}; + +&edma { + status = "okay"; +}; + +&cppi41dma { + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&davinci_mdio { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <1>; + }; + + phy1: ethernet-phy@1 { + reg = <2>; + }; +}; + +&mac { + status = "okay"; +}; + +&cpsw_emac0 { + phy-handle = <&phy0>; + dual_emac_res_vlan = <1>; + phy-mode = "mii"; +}; + +&cpsw_emac1 { + phy-handle = <&phy1>; + dual_emac_res_vlan = <2>; + phy-mode = "mii"; +}; + +&mmc1 { + u-boot,dm-spl; + vmmc-supply = <&vmmcsd_fixed>; + bus-width = <0x4>; + ti,non-removable; + ti,needs-special-hs-handling; + ti,vcc-aux-disable-is-sleep; + status = "okay"; +}; + +&mmc2 { + u-boot,dm-spl; + vmmc-supply = <&vmmcsd_fixed>; + bus-width = <0x8>; + ti,non-removable; + ti,needs-special-hs-handling; + ti,vcc-aux-disable-is-sleep; + status = "okay"; +}; + +&lcdc { + status = "disabled"; +}; + +&elm { + status = "okay"; +}; + +&sham { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&gpio0 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio1 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio2 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio3 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&wdt2 { + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&tscadc { + status = "okay"; + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; + ti,zx-cutoff-ratio = <40>; + ti,min_deviation = <60>; + ti,max_deviation = <600>; + ti,coordinate-readouts = <5>; + ti,wire-config = <0x00 0x11 0x22 0x33>; + + bnr-buttons { + Home-Button {}; + }; + }; + + adc { + ti,adc-channels = <5 6 7>; + }; +}; + +&timer6 { /* used for cpsw end device */ + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&timer7 { /* used for cpsw end device */ + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&wdt2 { + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&epwmss0 { + status = "okay"; +}; + +&tscadc { + status = "okay"; +}; + +&dcan0 { + status = "okay"; +}; + +&dcan1 { + status = "okay"; +}; + +&sham { + status = "disabled"; +}; + +&aes { + status = "disabled"; +}; + +&rng { + status = "disabled"; +};
diff --git a/arch/arm/dts/am335x-chiliboard-u-boot.dtsi b/arch/arm/dts/am335x-chiliboard-u-boot.dtsi new file mode 100644 index 0000000..4f9d308 --- /dev/null +++ b/arch/arm/dts/am335x-chiliboard-u-boot.dtsi
@@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0+ or X11 +/* + * Copyright (C) 2018 Grinn Sp. z o.o. -- http://www.grinn-global.com/ + * Author: Marcin Niestroj <m.niestroj@grinn-global.com> + */ + +/ { + chosen { + stdout-path = &uart0; + }; +};
diff --git a/arch/arm/dts/am335x-chiliboard.dts b/arch/arm/dts/am335x-chiliboard.dts new file mode 100644 index 0000000..59431b2 --- /dev/null +++ b/arch/arm/dts/am335x-chiliboard.dts
@@ -0,0 +1,200 @@ +/* + * Copyright (C) 2015 Jablotron s.r.o. -- http://www.jablotron.com/ + * Author: Rostislav Lisovy <lisovy@jablotron.cz> + * + * 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. + */ +/dts-v1/; +#include "am335x-chilisom.dtsi" + +/ { + model = "AM335x Chiliboard"; + compatible = "grinn,am335x-chiliboard", "grinn,am335x-chilisom", + "ti,am33xx"; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_gpio_pins>; + + led0 { + label = "led0"; + gpios = <&gpio3 7 GPIO_ACTIVE_LOW>; + default-state = "keep"; + linux,default-trigger = "heartbeat"; + }; + + led1 { + label = "led1"; + gpios = <&gpio3 8 GPIO_ACTIVE_LOW>; + default-state = "keep"; + }; + }; +}; + +&am33xx_pinmux { + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs */ + AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxerr.rmii1_rxerr */ + AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txen.rmii1_txen */ + AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */ + AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */ + AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */ + AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */ + AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii_ref_clk */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* mdio_data.mdio_data */ + AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) + /* mdio_clk.mdio_clk */ + AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + usb1_drvvbus: usb1_drvvbus { + pinctrl-single,pins = < + AM33XX_IOPAD(0xa34, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usb1_drvvbus.usb1_drvvbus */ + >; + }; + + sd_pins: pinmux_sd_card { + pinctrl-single,pins = < + AM33XX_IOPAD(0x8f0, PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */ + AM33XX_IOPAD(0x8f4, PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */ + AM33XX_IOPAD(0x8f8, PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */ + AM33XX_IOPAD(0x8fc, PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */ + AM33XX_IOPAD(0x900, PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */ + AM33XX_IOPAD(0x904, PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */ + AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ + >; + }; + + led_gpio_pins: led_gpio_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9e4, PIN_OUTPUT | MUX_MODE7) /* emu0.gpio3_7 */ + AM33XX_IOPAD(0x9e8, PIN_OUTPUT | MUX_MODE7) /* emu1.gpio3_8 */ + >; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + + status = "okay"; +}; + +&ldo4_reg { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; +}; + +/* Ethernet */ +&mac { + slaves = <1>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rmii"; +}; + +&phy_sel { + rmii-clock-ext; +}; + +/* USB */ +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb1 { + pinctrl-names = "default"; + pinctrl-0 = <&usb1_drvvbus>; + + status = "okay"; + dr_mode = "host"; +}; + +&cppi41dma { + status = "okay"; +}; + +/* microSD */ +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sd_pins>; + vmmc-supply = <&ldo4_reg>; + bus-width = <0x4>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&tps { + interrupt-parent = <&intc>; + interrupts = <7>; /* NNMI */ + + charger { + status = "okay"; + }; + + pwrbutton { + status = "okay"; + }; +};
diff --git a/arch/arm/dts/am335x-chilisom.dtsi b/arch/arm/dts/am335x-chilisom.dtsi new file mode 100644 index 0000000..1b43ebd --- /dev/null +++ b/arch/arm/dts/am335x-chilisom.dtsi
@@ -0,0 +1,178 @@ +/* + * Copyright (C) 2015 Jablotron s.r.o. -- http://www.jablotron.com/ + * Author: Rostislav Lisovy <lisovy@jablotron.cz> + * + * 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. + */ +#include "am33xx.dtsi" +#include <dt-bindings/interrupt-controller/irq.h> + +/ { + model = "Grinn AM335x ChiliSOM"; + compatible = "grinn,am335x-chilisom", "ti,am33xx"; + + cpus { + cpu@0 { + cpu0-supply = <&dcdc2_reg>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x20000000>; /* 512 MB */ + }; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + nandflash_pins: nandflash_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x800, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ + AM33XX_IOPAD(0x804, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ + AM33XX_IOPAD(0x808, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */ + AM33XX_IOPAD(0x80c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */ + AM33XX_IOPAD(0x810, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */ + AM33XX_IOPAD(0x814, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */ + AM33XX_IOPAD(0x818, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */ + AM33XX_IOPAD(0x81c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */ + + AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */ + AM33XX_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */ + AM33XX_IOPAD(0x890, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */ + AM33XX_IOPAD(0x894, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */ + AM33XX_IOPAD(0x898, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_wen.gpmc_wen */ + AM33XX_IOPAD(0x89c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */ + >; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + + status = "okay"; + clock-frequency = <400000>; + + tps: tps@24 { + reg = <0x24>; + }; + +}; + +/include/ "tps65217.dtsi" + +&tps { + regulators { + dcdc1_reg: regulator@0 { + regulator-name = "vdds_dpr"; + regulator-always-on; + }; + + dcdc2_reg: regulator@1 { + /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <1325000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc3_reg: regulator@2 { + /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1_reg: regulator@3 { + regulator-name = "vio,vrtc,vdds"; + regulator-boot-on; + regulator-always-on; + }; + + ldo2_reg: regulator@4 { + regulator-name = "vdd_3v3aux"; + regulator-boot-on; + regulator-always-on; + }; + + ldo3_reg: regulator@5 { + regulator-name = "vdd_1v8"; + regulator-boot-on; + regulator-always-on; + }; + + ldo4_reg: regulator@6 { + regulator-name = "vdd_3v3d"; + regulator-boot-on; + regulator-always-on; + }; + }; +}; + +&rtc { + system-power-controller; + + pinctrl-0 = <&ext_wakeup>; + pinctrl-names = "default"; + + ext_wakeup: ext-wakeup { + pins = "ext_wakeup0"; + input-enable; + }; +}; + +/* NAND Flash */ +&elm { + status = "okay"; +}; + +&gpmc { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&nandflash_pins>; + ranges = <0 0 0x08000000 0x01000000>; /* CS0 0 @addr 0x08000000, size 0x01000000 */ + nand@0,0 { + compatible = "ti,omap2-nand"; + reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ + interrupt-parent = <&gpmc>; + interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ + <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ + ti,nand-ecc-opt = "bch8"; + ti,elm-id = <&elm>; + nand-bus-width = <8>; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <40>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + }; +};
diff --git a/arch/arm/dts/am335x-draco.dts b/arch/arm/dts/am335x-draco.dts new file mode 100644 index 0000000..25d0480 --- /dev/null +++ b/arch/arm/dts/am335x-draco.dts
@@ -0,0 +1,152 @@ +/* + * Support for Siemens DRACO board + * + * Copyright (C) 2014 - Lukas Stockmann <lukas.stockmann@siemens.com> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/dts-v1/; + +#include "am33xx.dtsi" +#include "am335x-draco.dtsi" +#include <dt-bindings/input/input.h> + +/ { + model = "Siemens DRACO"; + compatible = "siemens,draco", "ti,am33xx"; + + /* ethernet alias is needed for the MAC address passing from U-Boot */ + aliases { + ethernet0 = &cpsw_emac0; + mdio-gpio0 = &mdio0; + }; + + gpio-keys { + compatible = "gpio-keys"; + button0 { + label = "button0"; + gpios = <&gpio0 27 GPIO_ACTIVE_LOW>; + linux,code = <KEY_F1>; /* button0 */ + }; + button1 { + label = "button1"; + gpios = <&gpio2 23 GPIO_ACTIVE_LOW>; + linux,code = <KEY_F2>; /* button1 */ + }; + }; + + ocp { + debugss: debugss@4b000000 { + compatible = "ti,debugss"; + ti,hwmods = "debugss"; + reg = <0x4b000000 1000000>; + status = "disabled"; + }; + }; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&gpio_mux_pins>; + + gpio_mux_pins: gpio_mux_pins { + pinctrl-single,pins = < + 0x1d0 (PIN_INPUT | MUX_MODE0) /* tms jtag */ + 0x1d4 (PIN_INPUT | MUX_MODE0) /* tdi jtag */ + 0x1d8 (PIN_OUTPUT | MUX_MODE0) /* tdo jtag */ + 0x1dc (PIN_INPUT | MUX_MODE0) /* tck jtag */ + 0x1e0 (PIN_INPUT | MUX_MODE0) /* trstn jtag */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + 0x0E8 (PIN_INPUT_PULLUP | MUX_MODE7) /* lcd_plck FIX STO should be a OUTPUT driven high*/ + 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs_dv */ + 0x114 (PIN_OUTPUT | MUX_MODE1) /* mii1_txen.mii1_txen */ + 0x124 (PIN_OUTPUT | MUX_MODE1) /* mii1_txd1.mii1_txd1 */ + 0x128 (PIN_OUTPUT | MUX_MODE1) /* mii1_txd0.mii1_txd0 */ + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd1.mii1_rxd1 */ + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd0.mii1_rxd0 */ + 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_refclk.rmii1_refclk */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + 0x148 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + 0x14c (PIN_OUTPUT | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + gpio_mdio_default: gpio_mdio_default { + pinctrl-single,pins = < + /* MDIO via GPIO */ + 0x148 (PIN_INPUT | MUX_MODE7) /* mdio_data.mdio_data GPIO0_0 */ + 0x14c (PIN_OUTPUT | MUX_MODE7) /* mdio_clk.mdio_clk GPIO0_1 */ + >; + }; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + slaves = <1>; /* use only one emac if */ + + mdio0: gpio { + compatible = "virtual,mdio-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&gpio_mdio_default>; + + #address-cells = <1>; + #size-cells = <0>; + gpios = <&gpio0 1 GPIO_ACTIVE_HIGH /* MDIO-CLK */ + &gpio0 0 GPIO_ACTIVE_HIGH>; /* MDIO-DATA */ + + phy0: ethernet-phy@1 { + reg = <0>; + }; + }; +}; + +/* Disable davinci/am335x mdio interface on this platform */ +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "disabled"; +}; + +&cpsw_emac0 { + phy_id = <&mdio0>, <0>; + phy-mode = "rmii"; +}; + +&phy_sel { + rmii-clock-ext; +};
diff --git a/arch/arm/dts/am335x-draco.dtsi b/arch/arm/dts/am335x-draco.dtsi new file mode 100644 index 0000000..b38ff55 --- /dev/null +++ b/arch/arm/dts/am335x-draco.dtsi
@@ -0,0 +1,169 @@ +/* + * Common support for Siemens Draco SOM (AM335x based) + * + * Copyright (C) 2013,2014 - Stefan Roese <sr@denx.de> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/ { + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x08000000>; /* 128 MB */ + }; + + ocp { + uart0: serial@44e09000 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; + }; + + i2c0: i2c@44e0b000 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + + status = "okay"; + clock-frequency = <400000>; + + eeprom: eeprom@50 { + compatible = "atmel,24c128"; + reg = <0x50>; + pagesize = <64>; + }; + }; + + musb: usb@47400000 { + status = "okay"; + + control@44e10620 { + status = "okay"; + }; + + usb-phy@47401300 { + status = "okay"; + }; + + usb-phy@47401b00 { + status = "okay"; + }; + + usb@47401000 { + status = "okay"; + }; + + usb@47401800 { + status = "okay"; + dr_mode = "host"; + }; + + dma-controller@47402000 { + status = "okay"; + }; + }; + }; +}; + +&am33xx_pinmux { + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + nandflash_pins: nandflash_pins { + pinctrl-single,pins = < + 0x0 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ + 0x4 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ + 0x8 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */ + 0xc (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */ + 0x10 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */ + 0x14 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */ + 0x18 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */ + 0x1c (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */ + 0x70 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */ + 0x74 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */ + 0x7c (PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */ + 0x90 (PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */ + 0x94 (PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */ + 0x98 (PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */ + 0x9c (PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */ + >; + }; + }; + + +&timer3 { + status = "disabled"; +}; + +&uart4 { + status = "disabled"; +}; + +&elm { + status = "okay"; +}; + +&gpmc { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&nandflash_pins>; + + ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */ + + nand@0,0 { + reg = <0 0 0>; /* CS0, offset 0 */ + nand-bus-width = <8>; + ti,nand-ecc-opt = "bch8"; + gpmc,device-nand = "true"; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <40>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,wait-on-read = "true"; + gpmc,wait-on-write = "true"; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wait-monitoring-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + + #address-cells = <1>; + #size-cells = <1>; + elm_id = <&elm>; + }; +}; + +/* disable the RTC node as its not accessible on the draco/dxr2 board */ +&rtc { + status = "disabled"; + ti,hwmods = "disabled"; +};
diff --git a/arch/arm/dts/am335x-evm-u-boot.dtsi b/arch/arm/dts/am335x-evm-u-boot.dtsi new file mode 100644 index 0000000..0341600 --- /dev/null +++ b/arch/arm/dts/am335x-evm-u-boot.dtsi
@@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + */ + + +&mmc3 { + status = "disabled"; +};
diff --git a/arch/arm/dts/am335x-evm.dts b/arch/arm/dts/am335x-evm.dts new file mode 100644 index 0000000..fe27207 --- /dev/null +++ b/arch/arm/dts/am335x-evm.dts
@@ -0,0 +1,764 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +#include "am33xx.dtsi" +#include <dt-bindings/interrupt-controller/irq.h> + +/ { + model = "TI AM335x EVM"; + compatible = "ti,am335x-evm", "ti,am33xx"; + + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; + + cpus { + cpu@0 { + cpu0-supply = <&vdd1_reg>; + }; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + vbat: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + }; + + lis3_reg: fixedregulator@1 { + compatible = "regulator-fixed"; + regulator-name = "lis3_reg"; + regulator-boot-on; + }; + + wlan_en_reg: fixedregulator@2 { + compatible = "regulator-fixed"; + regulator-name = "wlan-en-regulator"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + /* WLAN_EN GPIO for this board - Bank1, pin16 */ + gpio = <&gpio1 16 0>; + + /* WLAN card specific delay */ + startup-delay-us = <70000>; + enable-active-high; + }; + + matrix_keypad: matrix_keypad@0 { + compatible = "gpio-matrix-keypad"; + debounce-delay-ms = <5>; + col-scan-delay-us = <2>; + + row-gpios = <&gpio1 25 GPIO_ACTIVE_HIGH /* Bank1, pin25 */ + &gpio1 26 GPIO_ACTIVE_HIGH /* Bank1, pin26 */ + &gpio1 27 GPIO_ACTIVE_HIGH>; /* Bank1, pin27 */ + + col-gpios = <&gpio1 21 GPIO_ACTIVE_HIGH /* Bank1, pin21 */ + &gpio1 22 GPIO_ACTIVE_HIGH>; /* Bank1, pin22 */ + + linux,keymap = <0x0000008b /* MENU */ + 0x0100009e /* BACK */ + 0x02000069 /* LEFT */ + 0x0001006a /* RIGHT */ + 0x0101001c /* ENTER */ + 0x0201006c>; /* DOWN */ + }; + + gpio_keys: volume_keys@0 { + compatible = "gpio-keys"; + autorepeat; + + switch@9 { + label = "volume-up"; + linux,code = <115>; + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + gpio-key,wakeup; + }; + + switch@10 { + label = "volume-down"; + linux,code = <114>; + gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + gpio-key,wakeup; + }; + }; + + backlight { + compatible = "pwm-backlight"; + pwms = <&ecap0 0 50000 0>; + brightness-levels = <0 51 53 56 62 75 101 152 255>; + default-brightness-level = <8>; + }; + + panel { + compatible = "ti,tilcdc,panel"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_pins_s0>; + panel-info { + ac-bias = <255>; + ac-bias-intrpt = <0>; + dma-burst-sz = <16>; + bpp = <32>; + fdd = <0x80>; + sync-edge = <0>; + sync-ctrl = <1>; + raster-order = <0>; + fifo-th = <0>; + }; + + display-timings { + 800x480p62 { + clock-frequency = <30000000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <39>; + hback-porch = <39>; + hsync-len = <47>; + vback-porch = <29>; + vfront-porch = <13>; + vsync-len = <2>; + hsync-active = <1>; + vsync-active = <1>; + }; + }; + }; + + sound { + compatible = "ti,da830-evm-audio"; + ti,model = "AM335x-EVM"; + ti,audio-codec = <&tlv320aic3106>; + ti,mcasp-controller = <&mcasp1>; + ti,codec-clock-rate = <12000000>; + ti,audio-routing = + "Headphone Jack", "HPLOUT", + "Headphone Jack", "HPROUT", + "LINE1L", "Line In", + "LINE1R", "Line In"; + }; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &clkout2_pin>; + + matrix_keypad_s0: matrix_keypad_s0 { + pinctrl-single,pins = < + 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */ + 0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a6.gpio1_22 */ + 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a9.gpio1_25 */ + 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a10.gpio1_26 */ + 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.gpio1_27 */ + >; + }; + + volume_keys_s0: volume_keys_s0 { + pinctrl-single,pins = < + 0x150 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* spi0_sclk.gpio0_2 */ + 0x154 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* spi0_d0.gpio0_3 */ + >; + }; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + 0x158 (PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_d1.i2c1_sda */ + 0x15c (PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_cs0.i2c1_scl */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + uart1_pins: pinmux_uart1_pins { + pinctrl-single,pins = < + 0x178 (PIN_INPUT | MUX_MODE0) /* uart1_ctsn.uart1_ctsn */ + 0x17C (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn.uart1_rtsn */ + 0x180 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_rxd.uart1_rxd */ + 0x184 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_txd.uart1_txd */ + >; + }; + + clkout2_pin: pinmux_clkout2_pin { + pinctrl-single,pins = < + 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */ + >; + }; + + nandflash_pins_s0: nandflash_pins_s0 { + pinctrl-single,pins = < + 0x0 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ + 0x4 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ + 0x8 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */ + 0xc (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */ + 0x10 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */ + 0x14 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */ + 0x18 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */ + 0x1c (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */ + 0x70 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */ + 0x74 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */ + 0x7c (PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */ + 0x90 (PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */ + 0x94 (PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */ + 0x98 (PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */ + 0x9c (PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */ + >; + }; + + ecap0_pins: backlight_pins { + pinctrl-single,pins = < + 0x164 0x0 /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */ + 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */ + 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */ + 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */ + 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */ + 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */ + 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */ + 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */ + 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */ + 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */ + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */ + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ + >; + }; + + mmc3_pins: pinmux_mmc3_pins { + pinctrl-single,pins = < + 0x44 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a1.mmc2_dat0, INPUT_PULLUP | MODE3 */ + 0x48 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a2.mmc2_dat1, INPUT_PULLUP | MODE3 */ + 0x4C (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a3.mmc2_dat2, INPUT_PULLUP | MODE3 */ + 0x78 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_ben1.mmc2_dat3, INPUT_PULLUP | MODE3 */ + 0x88 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_csn3.mmc2_cmd, INPUT_PULLUP | MODE3 */ + 0x8C (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_clk.mmc2_clk, INPUT_PULLUP | MODE3 */ + >; + }; + + wlan_pins: pinmux_wlan_pins { + pinctrl-single,pins = < + 0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a0.gpio1_16 */ + 0x19C (PIN_INPUT | MUX_MODE7) /* mcasp0_ahclkr.gpio3_17 */ + 0x1AC (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* mcasp0_ahclkx.gpio3_21 */ + >; + }; + + lcd_pins_s0: lcd_pins_s0 { + pinctrl-single,pins = < + 0x20 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad8.lcd_data23 */ + 0x24 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad9.lcd_data22 */ + 0x28 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad10.lcd_data21 */ + 0x2c (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad11.lcd_data20 */ + 0x30 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad12.lcd_data19 */ + 0x34 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad13.lcd_data18 */ + 0x38 (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad14.lcd_data17 */ + 0x3c (PIN_OUTPUT | MUX_MODE1) /* gpmc_ad15.lcd_data16 */ + 0xa0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */ + 0xa4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */ + 0xa8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */ + 0xac (PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */ + 0xb0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */ + 0xb4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */ + 0xb8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */ + 0xbc (PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */ + 0xc0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */ + 0xc4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */ + 0xc8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */ + 0xcc (PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */ + 0xd0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */ + 0xd4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */ + 0xd8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */ + 0xdc (PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */ + 0xe0 (PIN_OUTPUT | MUX_MODE0) /* lcd_vsync.lcd_vsync */ + 0xe4 (PIN_OUTPUT | MUX_MODE0) /* lcd_hsync.lcd_hsync */ + 0xe8 (PIN_OUTPUT | MUX_MODE0) /* lcd_pclk.lcd_pclk */ + 0xec (PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */ + >; + }; + + am335x_evm_audio_pins: am335x_evm_audio_pins { + pinctrl-single,pins = < + 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ + 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */ + 0x108 (PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */ + 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */ + >; + }; + + dcan1_pins_default: dcan1_pins_default { + pinctrl-single,pins = < + 0x168 (PIN_OUTPUT | MUX_MODE2) /* uart0_ctsn.d_can1_tx */ + 0x16c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* uart0_rtsn.d_can1_rx */ + >; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + + status = "okay"; + clock-frequency = <400000>; + + tps: tps@2d { + reg = <0x2d>; + }; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&cppi41dma { + status = "okay"; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + + status = "okay"; + clock-frequency = <100000>; + + lis331dlh: lis331dlh@18 { + compatible = "st,lis331dlh", "st,lis3lv02d"; + reg = <0x18>; + Vdd-supply = <&lis3_reg>; + Vdd_IO-supply = <&lis3_reg>; + + st,click-single-x; + st,click-single-y; + st,click-single-z; + st,click-thresh-x = <10>; + st,click-thresh-y = <10>; + st,click-thresh-z = <10>; + st,irq1-click; + st,irq2-click; + st,wakeup-x-lo; + st,wakeup-x-hi; + st,wakeup-y-lo; + st,wakeup-y-hi; + st,wakeup-z-lo; + st,wakeup-z-hi; + st,min-limit-x = <120>; + st,min-limit-y = <120>; + st,min-limit-z = <140>; + st,max-limit-x = <550>; + st,max-limit-y = <550>; + st,max-limit-z = <750>; + }; + + tsl2550: tsl2550@39 { + compatible = "taos,tsl2550"; + reg = <0x39>; + }; + + tmp275: tmp275@48 { + compatible = "ti,tmp275"; + reg = <0x48>; + }; + + tlv320aic3106: tlv320aic3106@1b { + compatible = "ti,tlv320aic3106"; + reg = <0x1b>; + status = "okay"; + + /* Regulators */ + AVDD-supply = <&vaux2_reg>; + IOVDD-supply = <&vaux2_reg>; + DRVDD-supply = <&vaux2_reg>; + DVDD-supply = <&vbat>; + }; +}; + +&lcdc { + status = "okay"; +}; + +&elm { + status = "okay"; +}; + +&epwmss0 { + status = "okay"; + + ecap0: ecap@48300100 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ecap0_pins>; + }; +}; + +&gpmc { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&nandflash_pins_s0>; + ranges = <0 0 0x08000000 0x1000000>; /* CS0: 16MB for NAND */ + nand@0,0 { + reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ + ti,nand-ecc-opt = "bch8"; + ti,elm-id = <&elm>; + nand-bus-width = <8>; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <40>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,wait-on-read = "true"; + gpmc,wait-on-write = "true"; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wait-monitoring-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + /* MTD partition table */ + /* All SPL-* partitions are sized to minimal length + * which can be independently programmable. For + * NAND flash this is equal to size of erase-block */ + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + label = "NAND.SPL"; + reg = <0x00000000 0x000020000>; + }; + partition@1 { + label = "NAND.SPL.backup1"; + reg = <0x00020000 0x00020000>; + }; + partition@2 { + label = "NAND.SPL.backup2"; + reg = <0x00040000 0x00020000>; + }; + partition@3 { + label = "NAND.SPL.backup3"; + reg = <0x00060000 0x00020000>; + }; + partition@4 { + label = "NAND.u-boot-spl-os"; + reg = <0x00080000 0x00040000>; + }; + partition@5 { + label = "NAND.u-boot"; + reg = <0x000C0000 0x00100000>; + }; + partition@6 { + label = "NAND.u-boot-env"; + reg = <0x001C0000 0x00020000>; + }; + partition@7 { + label = "NAND.u-boot-env.backup1"; + reg = <0x001E0000 0x00020000>; + }; + partition@8 { + label = "NAND.kernel"; + reg = <0x00200000 0x00800000>; + }; + partition@9 { + label = "NAND.file-system"; + reg = <0x00A00000 0x0F600000>; + }; + }; +}; + +#include "tps65910.dtsi" + +&mcasp1 { + pinctrl-names = "default"; + pinctrl-0 = <&am335x_evm_audio_pins>; + + status = "okay"; + + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; + /* 4 serializers */ + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 0 0 1 2 + >; + tx-num-evt = <32>; + rx-num-evt = <32>; +}; + +&tps { + vcc1-supply = <&vbat>; + vcc2-supply = <&vbat>; + vcc3-supply = <&vbat>; + vcc4-supply = <&vbat>; + vcc5-supply = <&vbat>; + vcc6-supply = <&vbat>; + vcc7-supply = <&vbat>; + vccio-supply = <&vbat>; + + regulators { + vrtc_reg: regulator@0 { + regulator-always-on; + }; + + vio_reg: regulator@1 { + regulator-always-on; + }; + + vdd1_reg: regulator@2 { + /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1312500>; + regulator-boot-on; + regulator-always-on; + }; + + vdd2_reg: regulator@3 { + /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd3_reg: regulator@4 { + regulator-always-on; + }; + + vdig1_reg: regulator@5 { + regulator-always-on; + }; + + vdig2_reg: regulator@6 { + regulator-always-on; + }; + + vpll_reg: regulator@7 { + regulator-always-on; + }; + + vdac_reg: regulator@8 { + regulator-always-on; + }; + + vaux1_reg: regulator@9 { + regulator-always-on; + }; + + vaux2_reg: regulator@10 { + regulator-always-on; + }; + + vaux33_reg: regulator@11 { + regulator-always-on; + }; + + vmmc_reg: regulator@12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii-txid"; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii-txid"; +}; + +&tscadc { + status = "okay"; + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; + ti,coordinate-readouts = <5>; + ti,wire-config = <0x00 0x11 0x22 0x33>; + ti,charge-delay = <0x400>; + }; + + adc { + ti,adc-channels = <4 5 6 7>; + }; +}; + +&mmc1 { + status = "okay"; + vmmc-supply = <&vmmc_reg>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; +}; + +&mmc3 { + /* these are on the crossbar and are outlined in the + xbar-event-map element */ + dmas = <&edma 12 0 + &edma 13 0>; + dma-names = "tx", "rx"; + status = "okay"; + vmmc-supply = <&wlan_en_reg>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins &wlan_pins>; + ti,non-removable; + ti,needs-special-hs-handling; + cap-power-off-card; + keep-power-in-suspend; + + #address-cells = <1>; + #size-cells = <0>; + wlcore: wlcore@0 { + compatible = "ti,wl1835"; + reg = <2>; + interrupt-parent = <&gpio3>; + interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&edma { + ti,edma-xbar-event-map = /bits/ 16 <1 12 + 2 13>; +}; + +&sham { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&dcan1 { + status = "disabled"; /* Enable only if Profile 1 is selected */ + pinctrl-names = "default"; + pinctrl-0 = <&dcan1_pins_default>; +};
diff --git a/arch/arm/dts/am335x-evmsk.dts b/arch/arm/dts/am335x-evmsk.dts new file mode 100644 index 0000000..0767578 --- /dev/null +++ b/arch/arm/dts/am335x-evmsk.dts
@@ -0,0 +1,718 @@ +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +/* + * AM335x Starter Kit + * http://www.ti.com/tool/tmdssk3358 + */ + +/dts-v1/; + +#include "am33xx.dtsi" +#include <dt-bindings/pwm/pwm.h> +#include <dt-bindings/interrupt-controller/irq.h> + +/ { + model = "TI AM335x EVM-SK"; + compatible = "ti,am335x-evmsk", "ti,am33xx"; + + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; + + cpus { + cpu@0 { + cpu0-supply = <&vdd1_reg>; + }; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + vbat: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + }; + + lis3_reg: fixedregulator@1 { + compatible = "regulator-fixed"; + regulator-name = "lis3_reg"; + regulator-boot-on; + }; + + wl12xx_vmmc: fixedregulator@2 { + pinctrl-names = "default"; + pinctrl-0 = <&wl12xx_gpio>; + compatible = "regulator-fixed"; + regulator-name = "vwl1271"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&gpio1 29 0>; + startup-delay-us = <70000>; + enable-active-high; + }; + + vtt_fixed: fixedregulator@3 { + compatible = "regulator-fixed"; + regulator-name = "vtt"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + gpio = <&gpio0 7 GPIO_ACTIVE_HIGH>; + regulator-always-on; + regulator-boot-on; + enable-active-high; + }; + + leds { + pinctrl-names = "default"; + pinctrl-0 = <&user_leds_s0>; + + compatible = "gpio-leds"; + + led@1 { + label = "evmsk:green:usr0"; + gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@2 { + label = "evmsk:green:usr1"; + gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@3 { + label = "evmsk:green:mmc0"; + gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + default-state = "off"; + }; + + led@4 { + label = "evmsk:green:heartbeat"; + gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + }; + + gpio_buttons: gpio_buttons@0 { + compatible = "gpio-keys"; + + switch@1 { + label = "button0"; + linux,code = <0x100>; + gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; + }; + + switch@2 { + label = "button1"; + linux,code = <0x101>; + gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>; + }; + + switch@3 { + label = "button2"; + linux,code = <0x102>; + gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>; + wakeup-source; + }; + + switch@4 { + label = "button3"; + linux,code = <0x103>; + gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; + }; + }; + + backlight { + compatible = "pwm-backlight"; + pwms = <&ecap2 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 58 61 66 75 90 125 170 255>; + default-brightness-level = <8>; + }; + + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "AM335x-EVMSK"; + simple-audio-card,widgets = + "Headphone", "Headphone Jack"; + simple-audio-card,routing = + "Headphone Jack", "HPLOUT", + "Headphone Jack", "HPROUT"; + simple-audio-card,format = "dsp_b"; + simple-audio-card,bitclock-master = <&sound_master>; + simple-audio-card,frame-master = <&sound_master>; + simple-audio-card,bitclock-inversion; + + simple-audio-card,cpu { + sound-dai = <&mcasp1>; + }; + + sound_master: simple-audio-card,codec { + sound-dai = <&tlv320aic3106>; + system-clock-frequency = <24000000>; + }; + }; + + panel { + compatible = "ti,tilcdc,panel"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&lcd_pins_default>; + pinctrl-1 = <&lcd_pins_sleep>; + status = "okay"; + panel-info { + ac-bias = <255>; + ac-bias-intrpt = <0>; + dma-burst-sz = <16>; + bpp = <32>; + fdd = <0x80>; + sync-edge = <0>; + sync-ctrl = <1>; + raster-order = <0>; + fifo-th = <0>; + }; + display-timings { + 480x272 { + hactive = <480>; + vactive = <272>; + hback-porch = <43>; + hfront-porch = <8>; + hsync-len = <4>; + vback-porch = <12>; + vfront-porch = <4>; + vsync-len = <10>; + clock-frequency = <9000000>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; + }; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>; + + lcd_pins_default: lcd_pins_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad8.lcd_data23 */ + AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad9.lcd_data22 */ + AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad10.lcd_data21 */ + AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad11.lcd_data20 */ + AM33XX_IOPAD(0x830, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad12.lcd_data19 */ + AM33XX_IOPAD(0x834, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad13.lcd_data18 */ + AM33XX_IOPAD(0x838, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad14.lcd_data17 */ + AM33XX_IOPAD(0x83c, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad15.lcd_data16 */ + AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */ + AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */ + AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */ + AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */ + AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */ + AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */ + AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */ + AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */ + AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */ + AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */ + AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */ + AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */ + AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */ + AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */ + AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */ + AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */ + AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0) /* lcd_vsync.lcd_vsync */ + AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0) /* lcd_hsync.lcd_hsync */ + AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0) /* lcd_pclk.lcd_pclk */ + AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */ + >; + }; + + lcd_pins_sleep: lcd_pins_sleep { + pinctrl-single,pins = < + AM33XX_IOPAD(0x820, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad8.lcd_data23 */ + AM33XX_IOPAD(0x824, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad9.lcd_data22 */ + AM33XX_IOPAD(0x828, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad10.lcd_data21 */ + AM33XX_IOPAD(0x82c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad11.lcd_data20 */ + AM33XX_IOPAD(0x830, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad12.lcd_data19 */ + AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad13.lcd_data18 */ + AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad14.lcd_data17 */ + AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad15.lcd_data16 */ + AM33XX_IOPAD(0x8a0, PULL_DISABLE | MUX_MODE7) /* lcd_data0.lcd_data0 */ + AM33XX_IOPAD(0x8a4, PULL_DISABLE | MUX_MODE7) /* lcd_data1.lcd_data1 */ + AM33XX_IOPAD(0x8a8, PULL_DISABLE | MUX_MODE7) /* lcd_data2.lcd_data2 */ + AM33XX_IOPAD(0x8ac, PULL_DISABLE | MUX_MODE7) /* lcd_data3.lcd_data3 */ + AM33XX_IOPAD(0x8b0, PULL_DISABLE | MUX_MODE7) /* lcd_data4.lcd_data4 */ + AM33XX_IOPAD(0x8b4, PULL_DISABLE | MUX_MODE7) /* lcd_data5.lcd_data5 */ + AM33XX_IOPAD(0x8b8, PULL_DISABLE | MUX_MODE7) /* lcd_data6.lcd_data6 */ + AM33XX_IOPAD(0x8bc, PULL_DISABLE | MUX_MODE7) /* lcd_data7.lcd_data7 */ + AM33XX_IOPAD(0x8c0, PULL_DISABLE | MUX_MODE7) /* lcd_data8.lcd_data8 */ + AM33XX_IOPAD(0x8c4, PULL_DISABLE | MUX_MODE7) /* lcd_data9.lcd_data9 */ + AM33XX_IOPAD(0x8c8, PULL_DISABLE | MUX_MODE7) /* lcd_data10.lcd_data10 */ + AM33XX_IOPAD(0x8cc, PULL_DISABLE | MUX_MODE7) /* lcd_data11.lcd_data11 */ + AM33XX_IOPAD(0x8d0, PULL_DISABLE | MUX_MODE7) /* lcd_data12.lcd_data12 */ + AM33XX_IOPAD(0x8d4, PULL_DISABLE | MUX_MODE7) /* lcd_data13.lcd_data13 */ + AM33XX_IOPAD(0x8d8, PULL_DISABLE | MUX_MODE7) /* lcd_data14.lcd_data14 */ + AM33XX_IOPAD(0x8dc, PULL_DISABLE | MUX_MODE7) /* lcd_data15.lcd_data15 */ + AM33XX_IOPAD(0x8e0, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_vsync.lcd_vsync */ + AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.lcd_hsync */ + AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_pclk.lcd_pclk */ + AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_ac_bias_en.lcd_ac_bias_en */ + >; + }; + + + user_leds_s0: user_leds_s0 { + pinctrl-single,pins = < + AM33XX_IOPAD(0x810, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad4.gpio1_4 */ + AM33XX_IOPAD(0x814, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad5.gpio1_5 */ + AM33XX_IOPAD(0x818, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad6.gpio1_6 */ + AM33XX_IOPAD(0x81c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad7.gpio1_7 */ + >; + }; + + gpio_keys_s0: gpio_keys_s0 { + pinctrl-single,pins = < + AM33XX_IOPAD(0x894, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_oen_ren.gpio2_3 */ + AM33XX_IOPAD(0x890, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_advn_ale.gpio2_2 */ + AM33XX_IOPAD(0x870, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_wait0.gpio0_30 */ + AM33XX_IOPAD(0x89c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ben0_cle.gpio2_5 */ + >; + }; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + clkout2_pin: pinmux_clkout2_pin { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */ + >; + }; + + ecap2_pins: backlight_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x99c, MUX_MODE4) /* mcasp0_ahclkr.ecap2_in_pwm2_out */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */ + AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */ + AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */ + AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */ + AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */ + AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */ + AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */ + AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */ + AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */ + AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */ + AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */ + AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */ + + /* Slave 2 */ + AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */ + AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rctl */ + AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */ + AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */ + AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */ + AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */ + AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */ + AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */ + AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */ + AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */ + AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */ + AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7) + + /* Slave 2 reset value*/ + AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ + >; + }; + + mcasp1_pins: mcasp1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ + AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */ + AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */ + AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */ + >; + }; + + mcasp1_pins_sleep: mcasp1_pins_sleep { + pinctrl-single,pins = < + AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + mmc2_pins: pinmux_mmc2_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_31 */ + AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */ + AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ + AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */ + AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */ + AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */ + AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */ + >; + }; + + wl12xx_gpio: pinmux_wl12xx_gpio { + pinctrl-single,pins = < + AM33XX_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_csn0.gpio1_29 */ + >; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + + status = "okay"; + clock-frequency = <400000>; + + tps: tps@2d { + reg = <0x2d>; + }; + + lis331dlh: lis331dlh@18 { + compatible = "st,lis331dlh", "st,lis3lv02d"; + reg = <0x18>; + Vdd-supply = <&lis3_reg>; + Vdd_IO-supply = <&lis3_reg>; + + st,click-single-x; + st,click-single-y; + st,click-single-z; + st,click-thresh-x = <10>; + st,click-thresh-y = <10>; + st,click-thresh-z = <10>; + st,irq1-click; + st,irq2-click; + st,wakeup-x-lo; + st,wakeup-x-hi; + st,wakeup-y-lo; + st,wakeup-y-hi; + st,wakeup-z-lo; + st,wakeup-z-hi; + st,min-limit-x = <120>; + st,min-limit-y = <120>; + st,min-limit-z = <140>; + st,max-limit-x = <550>; + st,max-limit-y = <550>; + st,max-limit-z = <750>; + }; + + tlv320aic3106: tlv320aic3106@1b { + #sound-dai-cells = <0>; + compatible = "ti,tlv320aic3106"; + reg = <0x1b>; + status = "okay"; + + /* Regulators */ + AVDD-supply = <&vaux2_reg>; + IOVDD-supply = <&vaux2_reg>; + DRVDD-supply = <&vaux2_reg>; + DVDD-supply = <&vbat>; + }; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&cppi41dma { + status = "okay"; +}; + +&epwmss2 { + status = "okay"; + + ecap2: ecap@48304100 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ecap2_pins>; + }; +}; + +#include "tps65910.dtsi" + +&tps { + vcc1-supply = <&vbat>; + vcc2-supply = <&vbat>; + vcc3-supply = <&vbat>; + vcc4-supply = <&vbat>; + vcc5-supply = <&vbat>; + vcc6-supply = <&vbat>; + vcc7-supply = <&vbat>; + vccio-supply = <&vbat>; + + regulators { + vrtc_reg: regulator@0 { + regulator-always-on; + }; + + vio_reg: regulator@1 { + regulator-always-on; + }; + + vdd1_reg: regulator@2 { + /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1312500>; + regulator-boot-on; + regulator-always-on; + }; + + vdd2_reg: regulator@3 { + /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd3_reg: regulator@4 { + regulator-always-on; + }; + + vdig1_reg: regulator@5 { + regulator-always-on; + }; + + vdig2_reg: regulator@6 { + regulator-always-on; + }; + + vpll_reg: regulator@7 { + regulator-always-on; + }; + + vdac_reg: regulator@8 { + regulator-always-on; + }; + + vaux1_reg: regulator@9 { + regulator-always-on; + }; + + vaux2_reg: regulator@10 { + regulator-always-on; + }; + + vaux33_reg: regulator@11 { + regulator-always-on; + }; + + vmmc_reg: regulator@12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + dual_emac = <1>; + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii-txid"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii-txid"; + dual_emac_res_vlan = <2>; +}; + +&mmc1 { + status = "okay"; + vmmc-supply = <&vmmc_reg>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; +}; + +&sham { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&gpio0 { + ti,no-reset-on-init; +}; + +&mmc2 { + status = "okay"; + vmmc-supply = <&wl12xx_vmmc>; + ti,non-removable; + bus-width = <4>; + cap-power-off-card; + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + + #address-cells = <1>; + #size-cells = <0>; + wlcore: wlcore@2 { + compatible = "ti,wl1271"; + reg = <2>; + interrupt-parent = <&gpio0>; + interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; /* gpio 31 */ + ref-clock-frequency = <38400000>; + }; +}; + +&mcasp1 { + #sound-dai-cells = <0>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&mcasp1_pins>; + pinctrl-1 = <&mcasp1_pins_sleep>; + + status = "okay"; + + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; + /* 4 serializers */ + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 0 0 1 2 + >; + tx-num-evt = <32>; + rx-num-evt = <32>; +}; + +&tscadc { + status = "okay"; + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; + ti,coordinate-readouts = <5>; + ti,wire-config = <0x00 0x11 0x22 0x33>; + }; +}; + +&lcdc { + status = "okay"; +};
diff --git a/arch/arm/dts/am335x-icev2.dts b/arch/arm/dts/am335x-icev2.dts new file mode 100644 index 0000000..debc6f6 --- /dev/null +++ b/arch/arm/dts/am335x-icev2.dts
@@ -0,0 +1,430 @@ +/* + * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +/* + * AM335x ICE V2 board + * http://www.ti.com/tool/tmdsice3359 + */ + +/dts-v1/; + +#include "am33xx.dtsi" + +/ { + model = "TI AM3359 ICE-V2"; + compatible = "ti,am3359-icev2", "ti,am33xx"; + + chosen { + stdout-path = &uart3; + tick-timer = &timer2; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + vbat: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + }; + + vtt_fixed: fixedregulator@1 { + compatible = "regulator-fixed"; + regulator-name = "vtt"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + gpio = <&gpio0 18 GPIO_ACTIVE_HIGH>; + regulator-always-on; + regulator-boot-on; + enable-active-high; + }; + + leds@0 { + compatible = "gpio-leds"; + + led@0 { + label = "out0"; + gpios = <&tpic2810 0 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@1 { + label = "out1"; + gpios = <&tpic2810 1 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@2 { + label = "out2"; + gpios = <&tpic2810 2 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@3 { + label = "out3"; + gpios = <&tpic2810 3 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@4 { + label = "out4"; + gpios = <&tpic2810 4 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@5 { + label = "out5"; + gpios = <&tpic2810 5 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@6 { + label = "out6"; + gpios = <&tpic2810 6 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@7 { + label = "out7"; + gpios = <&tpic2810 7 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + /* Tricolor status LEDs */ + leds@1 { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&user_leds>; + + led@0 { + label = "status0:red:cpu0"; + gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "cpu0"; + }; + + led@1 { + label = "status0:green:usr"; + gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@2 { + label = "status0:yellow:usr"; + gpios = <&gpio3 9 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@3 { + label = "status1:red:mmc0"; + gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "mmc0"; + }; + + led@4 { + label = "status1:green:usr"; + gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led@5 { + label = "status1:yellow:usr"; + gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; +}; + +&am33xx_pinmux { + user_leds: user_leds { + pinctrl-single,pins = < + AM33XX_IOPAD(0x91c, PIN_OUTPUT | MUX_MODE7) /* (J18) gmii1_txd3.gpio0[16] */ + AM33XX_IOPAD(0x920, PIN_OUTPUT | MUX_MODE7) /* (K15) gmii1_txd2.gpio0[17] */ + AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE7) /* (A15) xdma_event_intr0.gpio0[19] */ + AM33XX_IOPAD(0x9b4, PIN_OUTPUT | MUX_MODE7) /* (D14) xdma_event_intr1.gpio0[20] */ + AM33XX_IOPAD(0x880, PIN_OUTPUT | MUX_MODE7) /* (U9) gpmc_csn1.gpio1[30] */ + AM33XX_IOPAD(0x92c, PIN_OUTPUT | MUX_MODE7) /* (K18) gmii1_txclk.gpio3[9] */ + >; + }; + + mmc0_pins_default: mmc0_pins_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* (F17) mmc0_dat3.mmc0_dat3 */ + AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* (F18) mmc0_dat2.mmc0_dat2 */ + AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* (G15) mmc0_dat1.mmc0_dat1 */ + AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* (G16) mmc0_dat0.mmc0_dat0 */ + AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* (G17) mmc0_clk.mmc0_clk */ + AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* (G18) mmc0_cmd.mmc0_cmd */ + AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE5) /* (C15) spi0_cs1.mmc0_sdcd */ + >; + }; + + i2c0_pins_default: i2c0_pins_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0) /* (C17) I2C0_SDA.I2C0_SDA */ + AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0) /* (C16) I2C0_SCL.I2C0_SCL */ + >; + }; + + spi0_pins_default: spi0_pins_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* (A17) spi0_sclk.spi0_sclk */ + AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* (B17) spi0_d0.spi0_d0 */ + AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* (B16) spi0_d1.spi0_d1 */ + AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0) /* (A16) spi0_cs0.spi0_cs0 */ + >; + }; + + uart3_pins_default: uart3_pins_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1) /* (L17) gmii1_rxd3.uart3_rxd */ + AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLUP | MUX_MODE1) /* (L16) gmii1_rxd2.uart3_txd */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1, RMII mode */ + AM33XX_IOPAD(0x90c, (PIN_INPUT_PULLUP | MUX_MODE1)) /* mii1_crs.rmii1_crs_dv */ + AM33XX_IOPAD(0x944, (PIN_INPUT_PULLUP | MUX_MODE0)) /* rmii1_refclk.rmii1_refclk */ + AM33XX_IOPAD(0x940, (PIN_INPUT_PULLUP | MUX_MODE1)) /* mii1_rxd0.rmii1_rxd0 */ + AM33XX_IOPAD(0x93c, (PIN_INPUT_PULLUP | MUX_MODE1)) /* mii1_rxd1.rmii1_rxd1 */ + AM33XX_IOPAD(0x910, (PIN_INPUT_PULLUP | MUX_MODE1)) /* mii1_rxerr.rmii1_rxerr */ + AM33XX_IOPAD(0x928, (PIN_OUTPUT_PULLDOWN | MUX_MODE1)) /* mii1_txd0.rmii1_txd0 */ + AM33XX_IOPAD(0x924, (PIN_OUTPUT_PULLDOWN | MUX_MODE1)) /* mii1_txd1.rmii1_txd1 */ + AM33XX_IOPAD(0x914, (PIN_OUTPUT_PULLDOWN | MUX_MODE1)) /* mii1_txen.rmii1_txen */ + /* Slave 2, RMII mode */ + AM33XX_IOPAD(0x870, (PIN_INPUT_PULLUP | MUX_MODE3)) /* gpmc_wait0.rmii2_crs_dv */ + AM33XX_IOPAD(0x908, (PIN_INPUT_PULLUP | MUX_MODE1)) /* mii1_col.rmii2_refclk */ + AM33XX_IOPAD(0x86c, (PIN_INPUT_PULLUP | MUX_MODE3)) /* gpmc_a11.rmii2_rxd0 */ + AM33XX_IOPAD(0x868, (PIN_INPUT_PULLUP | MUX_MODE3)) /* gpmc_a10.rmii2_rxd1 */ + AM33XX_IOPAD(0x874, (PIN_INPUT_PULLUP | MUX_MODE3)) /* gpmc_wpn.rmii2_rxerr */ + AM33XX_IOPAD(0x854, (PIN_OUTPUT_PULLDOWN | MUX_MODE3)) /* gpmc_a5.rmii2_txd0 */ + AM33XX_IOPAD(0x850, (PIN_OUTPUT_PULLDOWN | MUX_MODE3)) /* gpmc_a4.rmii2_txd1 */ + AM33XX_IOPAD(0x840, (PIN_OUTPUT_PULLDOWN | MUX_MODE3)) /* gpmc_a0.rmii2_txen */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + AM33XX_IOPAD(0x90c, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x944, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x940, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x93c, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x910, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x928, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x924, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x914, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + + /* Slave 2 reset value */ + AM33XX_IOPAD(0x870, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x908, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x86c, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x868, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x874, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x854, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x850, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x840, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + AM33XX_IOPAD(0x948, (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)) /* mdio_data.mdio_data */ + AM33XX_IOPAD(0x94c, (PIN_OUTPUT_PULLUP | MUX_MODE0)) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + AM33XX_IOPAD(0x948, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + AM33XX_IOPAD(0x94c, (PIN_INPUT_PULLDOWN | MUX_MODE7)) + >; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins_default>; + + status = "okay"; + clock-frequency = <400000>; + + tps: power-controller@2d { + reg = <0x2d>; + }; + + tpic2810: gpio@60 { + compatible = "ti,tpic2810"; + reg = <0x60>; + gpio-controller; + #gpio-cells = <2>; + }; +}; + +#include "tps65910.dtsi" + +&tps { + vcc1-supply = <&vbat>; + vcc2-supply = <&vbat>; + vcc3-supply = <&vbat>; + vcc4-supply = <&vbat>; + vcc5-supply = <&vbat>; + vcc6-supply = <&vbat>; + vcc7-supply = <&vbat>; + vccio-supply = <&vbat>; + + regulators { + vrtc_reg: regulator@0 { + regulator-always-on; + }; + + vio_reg: regulator@1 { + regulator-always-on; + }; + + vdd1_reg: regulator@2 { + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1326000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd2_reg: regulator@3 { + regulator-name = "vdd_core"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1144000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd3_reg: regulator@4 { + regulator-always-on; + }; + + vdig1_reg: regulator@5 { + regulator-always-on; + }; + + vdig2_reg: regulator@6 { + regulator-always-on; + }; + + vpll_reg: regulator@7 { + regulator-always-on; + }; + + vdac_reg: regulator@8 { + regulator-always-on; + }; + + vaux1_reg: regulator@9 { + regulator-always-on; + }; + + vaux2_reg: regulator@10 { + regulator-always-on; + }; + + vaux33_reg: regulator@11 { + regulator-always-on; + }; + + vmmc_reg: regulator@12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +}; + +&mmc1 { + status = "okay"; + vmmc-supply = <&vmmc_reg>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins_default>; +}; + +&gpio0 { + /* Do not idle the GPIO used for holding the VTT regulator */ + ti,no-reset-on-init; + ti,no-idle-on-init; + + p7 { + gpio-hog; + gpios = <7 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "FET_SWITCH_CTRL"; + }; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins_default>; + status = "okay"; +}; + +&gpio3 { + p4 { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "PR1_MII_CTRL"; + }; + + p10 { + gpio-hog; + gpios = <10 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "MUX_MII_CTRL"; + }; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rmii"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <3>; + phy-mode = "rmii"; + dual_emac_res_vlan = <2>; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + status = "okay"; + dual_emac; +}; + +&phy_sel { + rmii-clock-ext; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; + reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; + reset-delay-us = <2>; /* PHY datasheet states 1uS min */ +};
diff --git a/arch/arm/dts/am335x-pdu001-u-boot.dtsi b/arch/arm/dts/am335x-pdu001-u-boot.dtsi new file mode 100644 index 0000000..84a07bd --- /dev/null +++ b/arch/arm/dts/am335x-pdu001-u-boot.dtsi
@@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 EETS GmbH - https://www.eets.ch/ + */ + +/ { + ocp { + u-boot,dm-pre-reloc; + }; +}; + +&l4_wkup { + u-boot,dm-pre-reloc; +}; + +&scm { + u-boot,dm-pre-reloc; +}; + +&am33xx_pinmux { + u-boot,dm-pre-reloc; +}; + +&uart3_pins { + u-boot,dm-pre-reloc; +}; + +&uart3 { + u-boot,dm-pre-reloc; +}; + +&mmc1 { + u-boot,dm-pre-reloc; +}; + +&mmc1_pins { + u-boot,dm-pre-reloc; +}; + +&mmc2 { + u-boot,dm-pre-reloc; +}; + +&mmc2_pins { + u-boot,dm-pre-reloc; +};
diff --git a/arch/arm/dts/am335x-pdu001.dts b/arch/arm/dts/am335x-pdu001.dts new file mode 100644 index 0000000..3a5e952 --- /dev/null +++ b/arch/arm/dts/am335x-pdu001.dts
@@ -0,0 +1,594 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * pdu001.dts + * + * EETS GmbH PDU001 board device tree file + * + * Copyright (C) 2018 EETS GmbH - http://www.eets.ch/ + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + */ + +/dts-v1/; + +#include "am33xx.dtsi" +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/leds/leds-pca9532.h> + +/ { + model = "EETS,PDU001"; + compatible = "eets,pdu001", "ti,am33xx"; + + chosen { + stdout-path = &uart3; + }; + + cpus { + cpu@0 { + cpu0-supply = <&vdd1_reg>; + }; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + vbat: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <3600000>; + regulator-max-microvolt = <3600000>; + regulator-boot-on; + }; + + lis3_reg: fixedregulator@1 { + compatible = "regulator-fixed"; + regulator-name = "lis3_reg"; + regulator-boot-on; + }; + + panel { + compatible = "ti,tilcdc,panel"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_pins_s0>; + panel-info { + ac-bias = <255>; + ac-bias-intrpt = <0>; + dma-burst-sz = <16>; + bpp = <16>; + fdd = <0x80>; + sync-edge = <0>; + sync-ctrl = <1>; + raster-order = <0>; + fifo-th = <0>; + }; + + display-timings { + 240x320p16 { + clock-frequency = <6500000>; + hactive = <240>; + vactive = <320>; + hfront-porch = <6>; + hback-porch = <6>; + hsync-len = <1>; + vback-porch = <6>; + vfront-porch = <6>; + vsync-len = <1>; + hsync-active = <0>; + vsync-active = <0>; + pixelclk-active = <1>; + de-active = <0>; + }; + }; + }; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&clkout2_pin>; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_d1.i2c1_sda */ + AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_cs0.i2c1_scl */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_clk.i2c2_sda */ + AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_d0.i2c2_scl */ + >; + }; + + spi1_pins: pinmux_spi1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x990, PIN_OUTPUT | MUX_MODE3) /* mcasp0_aclkx.spi1_sclk */ + AM33XX_IOPAD(0x994, PIN_OUTPUT | MUX_MODE3) /* mcasp0_fsx.spi1_d0 */ + AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcasp0_axr0.spi1_d1 */ + AM33XX_IOPAD(0x99C, PIN_OUTPUT | MUX_MODE3) /* mcasp0_ahclkr.spi1_cs0 */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x96C, PIN_OUTPUT | MUX_MODE7) /* uart0_rtsn.gpio1_9 */ + AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + uart1_pins: pinmux_uart1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_rxd.uart1_rxd */ + AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_txd.uart1_txd */ + >; + }; + + uart3_pins: pinmux_uart3_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE1) /* spi0_cs1.uart3_rxd */ + AM33XX_IOPAD(0x964, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* ecap0_in_pwm0_out.uart3_txd */ + >; + }; + + clkout2_pin: pinmux_clkout2_pin { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Port 1 (emac0) */ + AM33XX_IOPAD(0x908, PIN_INPUT | MUX_MODE0) /* mii1_col.mii1_col */ + AM33XX_IOPAD(0x90C, PIN_INPUT | MUX_MODE0) /* mii1_crs.mii1_crs */ + AM33XX_IOPAD(0x910, PIN_INPUT | MUX_MODE0) /* mii1_rxer.mii1_rxer */ + AM33XX_IOPAD(0x914, PIN_OUTPUT | MUX_MODE0) /* mii1_txen.mii1_txen */ + AM33XX_IOPAD(0x918, PIN_INPUT | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */ + AM33XX_IOPAD(0x91c, PIN_OUTPUT | MUX_MODE0) /* mii1_txd3.mii1_txd3 */ + AM33XX_IOPAD(0x920, PIN_OUTPUT | MUX_MODE0) /* mii1_txd2.mii1_txd2 */ + AM33XX_IOPAD(0x924, PIN_OUTPUT | MUX_MODE0) /* mii1_txd1.mii1_txd1 */ + AM33XX_IOPAD(0x928, PIN_OUTPUT | MUX_MODE0) /* mii1_txd0.mii1_txd0 */ + AM33XX_IOPAD(0x92c, PIN_INPUT | MUX_MODE0) /* mii1_txclk.mii1_txclk */ + AM33XX_IOPAD(0x930, PIN_INPUT | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */ + AM33XX_IOPAD(0x934, PIN_INPUT | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */ + AM33XX_IOPAD(0x938, PIN_INPUT | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */ + AM33XX_IOPAD(0x93c, PIN_INPUT | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */ + AM33XX_IOPAD(0x940, PIN_INPUT | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */ + + /* Port 2 (emac1) */ + AM33XX_IOPAD(0x840, PIN_OUTPUT | MUX_MODE1) /* mii2_txen.gpmc_a0 */ + AM33XX_IOPAD(0x844, PIN_INPUT | MUX_MODE1) /* mii2_rxdv.gpmc_a1 */ + AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE1) /* mii2_txd3.gpmc_a2 */ + AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE1) /* mii2_txd2.gpmc_a3 */ + AM33XX_IOPAD(0x850, PIN_OUTPUT | MUX_MODE1) /* mii2_txd1.gpmc_a4 */ + AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE1) /* mii2_txd0.gpmc_a5 */ + AM33XX_IOPAD(0x858, PIN_INPUT | MUX_MODE1) /* mii2_txclk.gpmc_a6 */ + AM33XX_IOPAD(0x85c, PIN_INPUT | MUX_MODE1) /* mii2_rxclk.gpmc_a7 */ + AM33XX_IOPAD(0x860, PIN_INPUT | MUX_MODE1) /* mii2_rxd3.gpmc_a8 */ + AM33XX_IOPAD(0x864, PIN_INPUT | MUX_MODE1) /* mii2_rxd2.gpmc_a9 */ + AM33XX_IOPAD(0x868, PIN_INPUT | MUX_MODE1) /* mii2_rxd1.gpmc_a10 */ + AM33XX_IOPAD(0x86C, PIN_INPUT | MUX_MODE1) /* mii2_rxd0.gpmc_a11 */ + AM33XX_IOPAD(0x870, PIN_INPUT | MUX_MODE1) /* mii2_crs.gpmc_wait0 */ + AM33XX_IOPAD(0x874, PIN_INPUT | MUX_MODE1) /* mii2_rxer.gpmc_wpn */ + AM33XX_IOPAD(0x878, PIN_INPUT | MUX_MODE1) /* mii2_col.gpmc_ben1 */ + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + /* eMMC */ + pinctrl-single,pins = < + AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3 */ + AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2 */ + AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1 */ + AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0 */ + AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk */ + AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd */ + >; + }; + + mmc2_pins: pinmux_mmc2_pins { + /* SD cardcage */ + pinctrl-single,pins = < + AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */ + AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */ + AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */ + AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */ + AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */ + AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ + /* card change signal for frontpanel SD cardcage */ + AM33XX_IOPAD(0x890, PIN_INPUT | MUX_MODE7) /* gpmc_advn_ale.gpio2_2 */ + >; + }; + + lcd_pins_s0: lcd_pins_s0 { + pinctrl-single,pins = < + AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */ + AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */ + AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */ + AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */ + AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */ + AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */ + AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */ + AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */ + AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */ + AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */ + AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */ + AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */ + AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */ + AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */ + AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */ + AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */ + AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0) /* lcd_vsync.lcd_vsync */ + AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0) /* lcd_hsync.lcd_hsync */ + AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0) /* lcd_pclk.lcd_pclk */ + AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */ + >; + }; + + dcan0_pins: pinmux_dcan0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x978, PIN_OUTPUT | MUX_MODE2) /* uart1_ctsn.d_can0_tx */ + AM33XX_IOPAD(0x97c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* uart1_rtsn.d_can0_rx */ + >; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + + rts-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>; + rs485-rts-active-high; + rs485-rts-delay = <0 0>; + linux,rs485-enabled-at-boot-time; + + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; + + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + + status = "okay"; + clock-frequency = <400000>; + + tps: tps@2d { + reg = <0x2d>; + }; + + m2_eeprom: m2_eeprom@50 { + compatible = "atmel,24c256"; + reg = <0x50>; + status = "okay"; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + + status = "okay"; + clock-frequency = <100000>; + + board_24aa025e48: board_24aa025e48@50 { + compatible = "microchip,24aa025e48"; + reg = <0x50>; + }; + + backplane_24aa025e48: backplane_24aa025e48@53 { + compatible = "microchip,24aa025e48"; + reg = <0x53>; + }; + + pca9532: pca9532@60 { + compatible = "nxp,pca9532"; + reg = <0x60>; + psc0 = <0x97>; + pwm0 = <0x80>; + psc1 = <0x97>; + pwm1 = <0x10>; + + run.red@0 { + type = <PCA9532_TYPE_LED>; + }; + run.green@1 { + type = <PCA9532_TYPE_LED>; + default-state = "on"; + }; + s2.red@2 { + type = <PCA9532_TYPE_LED>; + }; + s2.green@3 { + type = <PCA9532_TYPE_LED>; + }; + s1.yellow@4 { + type = <PCA9532_TYPE_LED>; + }; + s1.green@5 { + type = <PCA9532_TYPE_LED>; + }; + }; + + pca9530: pca9530@61 { + compatible = "nxp,pca9530"; + reg = <0x61>; + + tft-panel@0 { + type = <PCA9532_TYPE_LED>; + linux,default-trigger = "backlight"; + default-state = "on"; + }; + }; + + mcp79400: mcp79400@6f { + compatible = "microchip,mcp7940x"; + reg = <0x6f>; + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + + status = "okay"; + clock-frequency = <100000>; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + ti,pindir-d0-out-d1-in; + status = "okay"; + + cfaf240320a032t { + compatible = "orise,otm3225a"; + reg = <0>; + spi-max-frequency = <1000000>; + // SPI mode 3 + spi-cpol; + spi-cpha; + status = "okay"; + }; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +&cppi41dma { + status = "okay"; +}; + +/* + * Disable soc's rtc as we have no VBAT for it. This makes the board + * rtc (Microchip MCP79400) the default rtc device 'rtc0'. + */ +&rtc { + status = "disabled"; +}; + +&lcdc { + status = "okay"; +}; + +&elm { + status = "okay"; +}; + +#include "tps65910.dtsi" + +&tps { + vcc1-supply = <&vbat>; + vcc2-supply = <&vbat>; + vcc3-supply = <&vbat>; + vcc4-supply = <&vbat>; + vcc5-supply = <&vbat>; + vcc6-supply = <&vbat>; + vcc7-supply = <&vbat>; + vccio-supply = <&vbat>; + + regulators { + vrtc_reg: regulator@0 { + regulator-name = "ldo_vrtc"; + regulator-always-on; + }; + + vio_reg: regulator@1 { + regulator-name = "buck_vdd_ddr"; + regulator-always-on; + }; + + vdd1_reg: regulator@2 { + /* VDD_MPU voltage limits */ + regulator-name = "buck_vdd_mpu"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1312500>; + regulator-boot-on; + regulator-always-on; + }; + + vdd2_reg: regulator@3 { + /* VDD_CORE voltage limits */ + regulator-name = "buck_vdd_core"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd3_reg: regulator@4 { + regulator-name = "boost_res"; + regulator-always-on; + }; + + vdig1_reg: regulator@5 { + regulator-name = "ldo_vdig1"; + regulator-always-on; + }; + + vdig2_reg: regulator@6 { + regulator-name = "ldo_vdig2"; + regulator-always-on; + }; + + vpll_reg: regulator@7 { + regulator-name = "ldo_vpll"; + regulator-always-on; + }; + + vdac_reg: regulator@8 { + regulator-name = "ldo_vdac"; + regulator-always-on; + }; + + vaux1_reg: regulator@9 { + regulator-name = "ldo_vaux1"; + regulator-always-on; + }; + + vaux2_reg: regulator@10 { + regulator-name = "ldo_vaux2"; + regulator-always-on; + }; + + vaux33_reg: regulator@11 { + regulator-name = "ldo_vaux33"; + regulator-always-on; + }; + + vmmc_reg: regulator@12 { + regulator-name = "ldo_vmmc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vbb_reg: regulator@13 { + regulator-name = "bat_vbb"; + }; + }; +}; + +&mac { + pinctrl-names = "default"; + pinctrl-0 = <&cpsw_default>; + dual_emac; /* no switch, two distinct MACs */ + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default"; + pinctrl-0 = <&davinci_mdio_default>; + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "mii"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "mii"; + dual_emac_res_vlan = <2>; +}; + +&tscadc { + status = "okay"; + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; + ti,coordinate-readouts = <5>; + ti,wire-config = <0x01 0x10 0x22 0x33>; + ti,charge-delay = <0x400>; + }; + + adc { + ti,adc-channels = <4 5 6 7>; + }; +}; + +&mmc1 { + status = "okay"; + vmmc-supply = <&vmmc_reg>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + non-removable; +}; + +&mmc2 { + status = "okay"; + vmmc-supply = <&vmmc_reg>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + cd-gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>; +}; + +&sham { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&dcan0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&dcan0_pins>; +};
diff --git a/arch/arm/dts/am335x-pxm2.dtsi b/arch/arm/dts/am335x-pxm2.dtsi new file mode 100644 index 0000000..d9243d5 --- /dev/null +++ b/arch/arm/dts/am335x-pxm2.dtsi
@@ -0,0 +1,537 @@ +/* + * Copyright (C) 2014 DENX Software Engineering GmbH + * Heiko Schocher <hs@denx.de> + * + * Based on: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +#include "am33xx.dtsi" +#include <dt-bindings/input/input.h> + +/ { + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; + + cpus { + cpu@0 { + cpu0-supply = <&vdd1_reg>; + }; + }; + + backlight0: backlight { + compatible = "pwm-backlight"; + pwms = <&ecap0 0 50000 0>; + brightness-levels = <0 2 5 7 10 12 15 17 20 22 25 28 30 33 35 + 38 40 43 45 48 51 53 56 58 61 63 66 68 71 + 73 76 79 81 84 86 89 91 94 96 99 102 104 + 107 109 112 114 117 119 122 124 127 130 + 132 135 137 140 142 145 147 150 153 155 + 158 160 163 165 168 170 173 175 178 181 + 183 186 188 191 193 196 198 201 204 206 + 209 211 214 216 219 221 224 226 229 232 + 234 237 239 242 244 247 249 252 255>; + default-brightness-level = <80>; + power-supply = <&backlight_reg>; + enable-gpios = <&gpio3 16 0>; + }; + + backlight_reg: fixedregulator0 { + compatible = "regulator-fixed"; + regulator-name = "backlight_reg"; + regulator-boot-on; + }; + + gpio_keys: restart-keys { + compatible = "gpio-keys"; + autorepeat; + + restart0 { + label = "restart"; + linux,code = <KEY_RESTART>; + gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; + gpio-key,wakeup; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_blue { + label = "blue"; + gpios = <&gpio3 20 0>; + }; + led_green { + label = "green"; + gpios = <&gpio1 31 0>; + }; + led_red { + label = "red"; + gpios = <&gpio3 21 0>; + }; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + reg_lcd_3v3: fixedregulator1 { + compatible = "regulator-gpio"; + regulator-name = "lcd-3v3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-type = "voltage"; + startup-delay-us = <100>; + states = <1800000 0x1 + 2900000 0x0>; + enable-at-boot; + gpios = <&gpio3 19 0>; + enable-active-high; + }; + + vbat: fixedregulator2 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + }; + + vmmc: fixedregulator3 { + compatible = "regulator-fixed"; + regulator-name = "vmmc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&cppi41dma { + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii-txid"; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii-txid"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; +}; + +&elm { + status = "okay"; +}; + +&epwmss0 { + status = "okay"; + + ecap0: ecap@48300100 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ecap0_pins>; + }; +}; + +&gpmc { + pinctrl-names = "default"; + pinctrl-0 = <&nandflash_pins>; + status = "okay"; + + ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */ + + nand@0,0 { + reg = <0 0 0>; /* CS0, offset 0 */ + nand-bus-width = <8>; + ti,nand-ecc-opt = "bch8"; + gpmc,device-nand = "true"; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <40>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,wait-on-read = "true"; + gpmc,wait-on-write = "true"; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wait-monitoring-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + + #address-cells = <1>; + #size-cells = <1>; + elm_id = <&elm>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <400000>; + status = "okay"; + + tps: tps@2d { + reg = <0x2d>; + }; + eeprom: eeprom@50 { + compatible = "atmel,24c128"; + reg = <0x50>; + pagesize = <32>; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + clock-frequency = <100000>; + status = "okay"; + + tsl2563: tsl2563@49 { + compatible = "amstaos,tsl2563"; + reg = <0x49>; + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + clock-frequency = <100000>; + status = "okay"; + + egalax_ts@04 { + compatible = "eeti,egalax_ts"; + reg = <0x04>; + interrupt-parent = <&gpio1>; + interrupts = <24 2>; + wakeup-gpios = <&gpio1 25 0>; + }; +}; + +&lcdc { + status = "okay"; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + status = "okay"; +}; + +&mmc1 { + vmmc-supply = <&vmmc>; + bus-width = <4>; + cd-gpios = <&gpio0 6 0>; + wp-gpios = <&gpio3 18 0>; + status = "okay"; +}; + +&phy_sel { + rgmii-no-delay; +}; + +#include "tps65910.dtsi" + +&tps { + vcc1-supply = <&vbat>; + vcc2-supply = <&vbat>; + vcc3-supply = <&vbat>; + vcc4-supply = <&vbat>; + vcc5-supply = <&vbat>; + vcc6-supply = <&vbat>; + vcc7-supply = <&vbat>; + vccio-supply = <&vbat>; + + regulators { + vrtc_reg: regulator@0 { + regulator-always-on; + }; + + vio_reg: regulator@1 { + regulator-always-on; + }; + + vdd1_reg: regulator@2 { + /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1312500>; + regulator-boot-on; + regulator-always-on; + }; + + vdd2_reg: regulator@3 { + /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd3_reg: regulator@4 { + regulator-always-on; + }; + + vdig1_reg: regulator@5 { + regulator-always-on; + }; + + vdig2_reg: regulator@6 { + regulator-always-on; + }; + + vpll_reg: regulator@7 { + regulator-always-on; + }; + + vdac_reg: regulator@8 { + regulator-always-on; + }; + + vaux1_reg: regulator@9 { + regulator-always-on; + }; + + vaux2_reg: regulator@10 { + regulator-always-on; + }; + + vaux33_reg: regulator@11 { + regulator-always-on; + }; + + vmmc_reg: regulator@12 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + dr_mode = "host"; + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&clkout2_pin &gpio_pin>; + + clkout2_pin: pinmux_clkout2_pin { + pinctrl-single,pins = < + 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */ + 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */ + 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */ + 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */ + 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */ + 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */ + 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */ + 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */ + 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */ + 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */ + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */ + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + ecap0_pins: ecap_pins { + pinctrl-single,pins = < + 0x198 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* mcasp0_axr0.gpio3_16 Backlight enable */ + 0x164 (MUX_MODE0) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */ + >; + }; + + + gpio_pin: gpio_pin { + pinctrl-single,pins = < + 0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a6.gpio1_22 touch reset */ + 0x60 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a8.gpio1_24 touch irq */ + 0x64 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a9.gpio1_25 touch power */ + 0x6c (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a11.gpio1_27 pad14 to DFU */ + 0x21c (MUX_MODE0) /* usb0_drvvbus */ + 0x234 (MUX_MODE0) /* usb1_drvvbus */ + 0x1a0 (PIN_INPUT_PULLUP | MUX_MODE4) /* mcasp0_aclkr.mmc0_sdwp */ + 0x160 (PIN_INPUT_PULLUP | MUX_MODE5) /* spi0_cs1.mmc0_sdcd */ + >; + }; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + 0x158 (PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_d1.i2c1_sda */ + 0x15c (PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_cs0.i2c1_scl */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + 0x150 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_sclk.i2c2_sda */ + 0x154 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_cs0.i2c2_scl */ + >; + }; + + lcd_pins_s0: lcd_pins_s0 { + pinctrl-single,pins = < + 0x20 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad8.lcd_data23 */ + 0x24 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad9.lcd_data22 */ + 0x28 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad10.lcd_data21 */ + 0x2c (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad11.lcd_data20 */ + 0x30 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad12.lcd_data19 */ + 0x34 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad13.lcd_data18 */ + 0x38 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad14.lcd_data17 */ + 0x3c (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad15.lcd_data16 */ + 0xa0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */ + 0xa4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */ + 0xa8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */ + 0xac (PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */ + 0xb0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */ + 0xb4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */ + 0xb8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */ + 0xbc (PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */ + 0xc0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */ + 0xc4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */ + 0xc8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */ + 0xcc (PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */ + 0xd0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */ + 0xd4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */ + 0xd8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */ + 0xdc (PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */ + 0xe0 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_vsync.lcd_vsync */ + 0xe4 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_hsync.lcd_hsync */ + 0xe8 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_pclk.lcd_pclk */ + 0xec (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */ + 0x194 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* mcasp0_fsx.gpio3_15 LCD enable */ + >; + }; + + nandflash_pins: pinmux_nandflash_pins { + pinctrl-single,pins = < + 0x0 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ + 0x4 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ + 0x8 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */ + 0xc (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */ + 0x10 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */ + 0x14 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */ + 0x18 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */ + 0x1c (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */ + 0x70 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */ + 0x74 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */ + 0x7c (PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */ + 0x90 (PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */ + 0x94 (PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */ + 0x98 (PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */ + 0x9c (PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; +}; + +&wdt2 { + wdt-keep-enabled; +};
diff --git a/arch/arm/dts/am335x-pxm50.dts b/arch/arm/dts/am335x-pxm50.dts new file mode 100644 index 0000000..f4e66d2 --- /dev/null +++ b/arch/arm/dts/am335x-pxm50.dts
@@ -0,0 +1,59 @@ +/* + * Copyright (C) 2014 DENX Software Engineering GmbH + * Heiko Schocher <hs@denx.de> + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +#include "am335x-pxm2.dtsi" + +/ { + model = "PXM2/PXM50"; + compatible = "ti,am335x-evm", "ti,am33xx"; + + panel { + compatible = "ti,tilcdc,panel"; + backlight = <&backlight0>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_pins_s0>; + enable-gpios = <&gpio3 15 0>; + status = "okay"; + + panel-info { + ac-bias = <255>; + ac-bias-intrpt = <0>; + dma-burst-sz = <16>; + bpp = <32>; + fdd = <0x80>; + sync-edge = <0>; + sync-ctrl = <1>; + raster-order = <0>; + fifo-th = <0>; + tft-alt-mode = <0>; + invert-pxl-clk = <0>; + }; + + display-timings { + native-mode = <&timing1>; + + timing1: 1376x768p50 { + clock-frequency = <60000000>; + hactive = <1376>; + vactive = <768>; + hfront-porch = <14>; + hback-porch = <64>; + hsync-len = <56>; + vback-porch = <28>; + vfront-porch = <1>; + vsync-len = <6>; + hsync-active = <1>; + vsync-active = <1>; + }; + }; + }; +};
diff --git a/arch/arm/dts/am335x-rut.dts b/arch/arm/dts/am335x-rut.dts new file mode 100644 index 0000000..a5716a9 --- /dev/null +++ b/arch/arm/dts/am335x-rut.dts
@@ -0,0 +1,605 @@ +/* + * Copyright (C) 2014 DENX Software Engineering GmbH + * Heiko Schocher <hs@denx.de> + * + * Based on: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +#include "am33xx.dtsi" +#include <dt-bindings/input/input.h> + +/ { + model = "RUT"; + compatible = "ti,am335x-evm", "ti,am33xx"; + + buzzer { + compatible = "pwm-beeper"; + pwms = <&ecap0 0 16000 0>; + }; + + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; + + cpus { + cpu@0 { + cpu0-supply = <&dcdc2_reg>; + }; + }; + + gpio_keys: powerfail-keys { + compatible = "gpio-keys"; + autorepeat; + + pwr-fail0 { + label = "power-fail"; + linux,code = <KEY_POWER>; + gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>; + gpio-key,wakeup; + }; + + pwr-fail1 { + label = "power-fail-redundant"; + linux,code = <KEY_POWER>; + gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>; + gpio-key,wakeup; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_green { + label = "rut:green:debug:run_mode"; + gpios = <&gpio3 20 1>; + /* activelow = 1, default trigger heartbeat */ + }; + led_yellow { + label = "rut:debug:yellow:osc_ch1"; + gpios = <&gpio0 17 1>; + /* activelow = 1, default trigger mmc0 */ + }; + led_red { + label = "rut:debug:red:osc_ch2"; + gpios = <&gpio0 16 1>; + /* activelow = 1, default trigger debug_osc_ch2 */ + }; + /* optional */ + led_alive { + label = "rut:alive"; + gpios = <&gpio0 15 1>; + linux,default-trigger = "heartbeat"; + /* activelow = 1, default trigger heartbeat */ + }; + + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + panel { + compatible = "ti,tilcdc,panel"; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_pins_s0>; + status = "okay"; + + /* FORMIKE_KWH043ST20_F01 */ + panel-info { + ac-bias = <255>; + ac-bias-intrpt = <0>; + dma-burst-sz = <16>; + bpp = <16>; + fdd = <0x80>; + sync-edge = <0>; + sync-ctrl = <1>; + raster-order = <0>; + fifo-th = <0>; + tft-alt-mode = <0>; + invert-pxl-clk = <1>; + }; + + display-timings { + native-mode = <&timing1>; + timing1: 480x800p60 { + clock-frequency = <29925000>; + hactive = <480>; + vactive = <800>; + hfront-porch = <50>; + hback-porch = <50>; + hsync-len = <50>; + vback-porch = <50>; + vfront-porch = <50>; + vsync-len = <50>; + hsync-active = <1>; + vsync-active = <1>; + }; + }; + }; + + vmmc: fixedregulator3 { + compatible = "regulator-fixed"; + regulator-name = "vmmc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + watchdog { + compatible = "linux,wdt-gpio"; + gpios = <&gpio0 14 0>; + hw_algo = "level"; + hw_margin_ms = <30000>; + }; +}; + +&aes { + status = "okay"; +}; + +&cppi41dma { + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rmii"; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rmii"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; + gpios = <&gpio2 18 0>; + + ethernet_phy: ethernet-phy@1 { + compatible = "ethernet-phy-id2000.5ce1"; + reg = <1>; + natsemi,master_mode_fixup; + }; +}; + +&elm { + status = "okay"; +}; + +&epwmss0 { + status = "okay"; + + ecap0: ecap@48300100 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ecap0_pins>; + }; +}; + +&epwmss1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&epwmss1_pins>; +}; + +&gpmc { + pinctrl-names = "default"; + pinctrl-0 = <&nandflash_pins>; + status = "okay"; + + ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */ + + nand@0,0 { + reg = <0 0 0>; /* CS0, offset 0 */ + nand-bus-width = <8>; + ti,nand-ecc-opt = "bch8"; + gpmc,device-nand = "true"; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <57>; + gpmc,cs-wr-off-ns = <57>; + gpmc,adv-on-ns = <0>; + gpmc,adv-rd-off-ns = <57>; + gpmc,adv-wr-off-ns = <57>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <48>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <57>; + gpmc,access-ns = <38>; + gpmc,rd-cycle-ns = <67>; + gpmc,wr-cycle-ns = <67>; + gpmc,wait-on-read = "true"; + gpmc,wait-on-write = "true"; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wait-monitoring-ns = <0>; + gpmc,wr-access-ns = <96>; + gpmc,wr-data-mux-bus-ns = <0>; + + #address-cells = <1>; + #size-cells = <1>; + elm_id = <&elm>; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <400000>; + status = "okay"; + + eeprom: eeprom@50 { + compatible = "atmel,24c128"; + reg = <0x50>; + pagesize = <32>; + }; + + tps: tps@24 { + reg = <0x24>; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + clock-frequency = <100000>; + status = "okay"; + + atmel: atmel_mxt_ts@4a { + compatible = "atmel,maxtouch"; + reg = <0x4a>; + interrupt-parent = <&gpio1>; + interrupts = <28 8>; + gpios = <&gpio3 18 GPIO_ACTIVE_HIGH>; + }; + + temp@48 { + compatible = "st,ds75"; + reg = <0x4c>; + }; +}; + +&lcdc { + status = "okay"; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + status = "okay"; +}; + +&mmc1 { + vmmc-supply = <&vmmc>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + status = "okay"; +}; + +&phy_sel { + rmii-clock-ext; +}; + +&sham { + status = "okay"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + status = "okay"; + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l25635e"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <24000000>; + + partition@0 { + label = "dummy"; + reg = <0x0000000 0x8000>; + }; + }; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + status = "okay"; + + lcd_init: lcd@0 { + compatible = "formike,kwh043st20"; + reg = <0>; + reset-gpios = <&gpio3 19 0>; + spi-max-frequency = <1200000>; + spi-cpol; + spi-cpha; + power-on-delay = <10>; + reset-delay = <10>; + }; +}; + +/include/ "tps65217.dtsi" + +&tps { + backlight0: backlight { + isel = <1>; /* 1 - ISET1, 2 ISET2 */ + fdim = <1000>; /* TPS65217_BL_FDIM_100HZ */ + default-brightness = <80>; + }; + + regulators { + dcdc1_reg: regulator@0 { + regulator-always-on; + }; + + dcdc2_reg: regulator@1 { + /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <1325000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc3_reg: regulator@2 { + /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1_reg: regulator@3 { + regulator-always-on; + }; + + ldo2_reg: regulator@4 { + regulator-always-on; + }; + + ldo3_reg: regulator@5 { + regulator-always-on; + }; + + ldo4_reg: regulator@6 { + regulator-always-on; + }; + }; +}; + +&tscadc { + status = "okay"; + adc { + ti,adc-channels = <4 5 6 7>; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0 { + dr_mode = "device"; + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&clkout2_pin &gpio_pin>; + + clkout2_pin: pinmux_clkout2_pin { + pinctrl-single,pins = < + 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs_dv */ + 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxerr.mii1_rxerr */ + 0x114 (MUX_MODE1) /* mii1_txen.mii1_txen */ + 0x124 (MUX_MODE1) /* mii1_txd1.mii1_txd1 */ + 0x128 (MUX_MODE1) /* mii1_txd0.mii1_txd0 */ + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd1.mii1_rxd1 */ + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd0.mii1_rxd0 */ + 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii1_refclk */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + ecap0_pins: ecap_pins { + pinctrl-single,pins = < + 0x164 (MUX_MODE0) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 buzzer frequency: ecap.0 */ + >; + }; + + epwmss1_pins: epwmss_pins { + pinctrl-single,pins = < + 0x48 (PIN_INPUT | MUX_MODE7) /* gpmc_a2.gpio1_18 buzzer frequency: ehrpwm1A high-Z due to connected to ecap0 by R0469 */ + 0x4c (MUX_MODE6) /* gpmc_a3.ehrpwm1B buzzer volume pwm */ + >; + }; + + gpio_pin: gpio_pin { + pinctrl-single,pins = < + 0x6c (PIN_INPUT | MUX_MODE7) /* gpmc_a11.gpio1_27 PWR_FAIL_GPIO_SPARE */ + 0x78 (PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7) /* gpmc_be1n.gpio1_28 TOUCH_CHANGE_N */ + 0x88 (PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7) /* gpmc_csn3.gpio2_0 RUT_GPIO0_GPIO */ + 0x118 (PIN_INPUT | MUX_MODE7) /* gmii1_rxdv.gpio3_4 PWR_FAIL_GPIO */ + 0x11c (MUX_MODE7) /* mii1_txd3.gpio0_16 DEBUG_OSC_CH2_GPIO */ + 0x120 (MUX_MODE7) /* mii1_txd2.gpio0_17 DEBUG_OSC_CH1_GPIO */ + 0x134 (MUX_MODE7) /* gmii1_rxd3.gpio2_18 PHY_RSTn_GPIO */ + 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gmii1_rxd2.gpio2_19 PHY_INT_GPIO */ + 0x180 (MUX_MODE7) /* uart1_rxd.gpio0_14 WATCHDOG_TRIGGER_GPIO */ + 0x184 (MUX_MODE7) /* uart1_txd.gpio0_15 ALIVE_LED_N_GPIO */ + 0x1a0 (MUX_MODE7) /* mcasp0_aclkr.gpio3_18 MAXTOUCH_RESET_GPIO */ + 0x1a4 (MUX_MODE7) /* mcasp0_fsr.gpio3_19 DISPLAY_RESET_GPIO */ + 0x1a8 (MUX_MODE7) /* mcasp0_axr1.gpio3_20 DEBUG_RUN_MODE_GPIO */ + 0x1ac (PIN_INPUT_PULLDOWN | MUX_MODE7) /* mcasp0_ahclkx.gpio3_21 NORFLASH_WP_GPIO */ + 0x1b0 (PIN_OUTPUT | MUX_MODE3) /* xdma_event_intr0.clkout1 */ + >; + }; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + 0x168 (PIN_INPUT | MUX_MODE3) /* uart0_ctsn.i2c1_sda */ + 0x16c (PIN_INPUT | MUX_MODE3) /* uart0.rtsn.i2c1_scl */ + >; + }; + + lcd_pins_s0: lcd_pins_s0 { + pinctrl-single,pins = < + 0x20 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad8.lcd_data23 */ + 0x24 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad9.lcd_data22 */ + 0x28 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad10.lcd_data21 */ + 0x2c (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad11.lcd_data20 */ + 0x30 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad12.lcd_data19 */ + 0x34 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad13.lcd_data18 */ + 0x38 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad14.lcd_data17 */ + 0x3c (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_ad15.lcd_data16 */ + 0xa0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */ + 0xa4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */ + 0xa8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */ + 0xac (PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */ + 0xb0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */ + 0xb4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */ + 0xb8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */ + 0xbc (PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */ + 0xc0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */ + 0xc4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */ + 0xc8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */ + 0xcc (PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */ + 0xd0 (PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */ + 0xd4 (PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */ + 0xd8 (PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */ + 0xdc (PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */ + 0xe0 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_vsync.lcd_vsync */ + 0xe4 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_hsync.lcd_hsync */ + 0xe8 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_pclk.lcd_pclk */ + 0xec (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */ + >; + }; + + mmc1_pins: mmc1_pins { + pinctrl-single,pins = < + 0xf0 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */ + 0xf4 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */ + 0xf8 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */ + 0xfc (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */ + 0x100 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk.mmc0_clk */ + 0x104 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */ + >; + }; + + nandflash_pins: pinmux_nandflash_pins { + pinctrl-single,pins = < + 0x0 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ + 0x4 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ + 0x8 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */ + 0xc (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */ + 0x10 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */ + 0x14 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */ + 0x18 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */ + 0x1c (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */ + 0x70 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */ + 0x74 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */ + 0x7c (PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */ + 0x90 (PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */ + 0x94 (PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */ + 0x98 (PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */ + 0x9c (PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */ + >; + }; + + spi0_pins: pinmux_spi0_pins { + pinctrl-single,pins = < + 0x150 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* spi0_sclk.spi0_sclk */ + 0x154 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0.spi0_d0 */ + 0x158 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* spi0_d1.spi0_d1 */ + 0x15c (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_CS0.spi0_CS0 */ + >; + }; + + spi1_pins: pinmux_spi1_pins { + pinctrl-single,pins = < + 0x190 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcasp0_aclkx.spi1_sclk */ + 0x194 (PIN_INPUT_PULLUP | MUX_MODE3) /* mcasp0_fsx.spi1_d0 */ + 0x198 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcasp0_axr0.spi1_d1 */ + 0x19c (PIN_INPUT_PULLUP | MUX_MODE3) /* mcasp0_ahclkr.spi1_cs0 */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + 0x170 (PIN_INPUT | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + 0x174 (PIN_OUTPUT | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; +};
diff --git a/arch/arm/dts/am33xx-clocks.dtsi b/arch/arm/dts/am33xx-clocks.dtsi new file mode 100644 index 0000000..95d5c9d --- /dev/null +++ b/arch/arm/dts/am33xx-clocks.dtsi
@@ -0,0 +1,625 @@ +/* + * Device Tree Source for AM33xx clock data + * + * Copyright (C) 2013 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +&scm_clocks { + sys_clkin_ck: sys_clkin_ck@40 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>; + ti,bit-shift = <22>; + reg = <0x0040>; + }; + + adc_tsc_fck: adc_tsc_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + dcan0_fck: dcan0_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + dcan1_fck: dcan1_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + mcasp0_fck: mcasp0_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + mcasp1_fck: mcasp1_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + smartreflex0_fck: smartreflex0_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + smartreflex1_fck: smartreflex1_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + sha0_fck: sha0_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + aes0_fck: aes0_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + rng_fck: rng_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + ehrpwm0_tbclk: ehrpwm0_tbclk@44e10664 { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&l4ls_gclk>; + ti,bit-shift = <0>; + reg = <0x0664>; + }; + + ehrpwm1_tbclk: ehrpwm1_tbclk@44e10664 { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&l4ls_gclk>; + ti,bit-shift = <1>; + reg = <0x0664>; + }; + + ehrpwm2_tbclk: ehrpwm2_tbclk@44e10664 { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&l4ls_gclk>; + ti,bit-shift = <2>; + reg = <0x0664>; + }; +}; +&prcm_clocks { + clk_32768_ck: clk_32768_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_rc32k_ck: clk_rc32k_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32000>; + }; + + virt_19200000_ck: virt_19200000_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <19200000>; + }; + + virt_24000000_ck: virt_24000000_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + virt_25000000_ck: virt_25000000_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25000000>; + }; + + virt_26000000_ck: virt_26000000_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <26000000>; + }; + + tclkin_ck: tclkin_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <12000000>; + }; + + dpll_core_ck: dpll_core_ck@490 { + #clock-cells = <0>; + compatible = "ti,am3-dpll-core-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x0490>, <0x045c>, <0x0468>; + }; + + dpll_core_x2_ck: dpll_core_x2_ck { + #clock-cells = <0>; + compatible = "ti,am3-dpll-x2-clock"; + clocks = <&dpll_core_ck>; + }; + + dpll_core_m4_ck: dpll_core_m4_ck@480 { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_core_x2_ck>; + ti,max-div = <31>; + reg = <0x0480>; + ti,index-starts-at-one; + }; + + dpll_core_m5_ck: dpll_core_m5_ck@484 { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_core_x2_ck>; + ti,max-div = <31>; + reg = <0x0484>; + ti,index-starts-at-one; + }; + + dpll_core_m6_ck: dpll_core_m6_ck@4d8 { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_core_x2_ck>; + ti,max-div = <31>; + reg = <0x04d8>; + ti,index-starts-at-one; + }; + + dpll_mpu_ck: dpll_mpu_ck@488 { + #clock-cells = <0>; + compatible = "ti,am3-dpll-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x0488>, <0x0420>, <0x042c>; + }; + + dpll_mpu_m2_ck: dpll_mpu_m2_ck@4a8 { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_mpu_ck>; + ti,max-div = <31>; + reg = <0x04a8>; + ti,index-starts-at-one; + }; + + dpll_ddr_ck: dpll_ddr_ck@494 { + #clock-cells = <0>; + compatible = "ti,am3-dpll-no-gate-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x0494>, <0x0434>, <0x0440>; + }; + + dpll_ddr_m2_ck: dpll_ddr_m2_ck@4a0 { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_ddr_ck>; + ti,max-div = <31>; + reg = <0x04a0>; + ti,index-starts-at-one; + }; + + dpll_ddr_m2_div2_ck: dpll_ddr_m2_div2_ck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_ddr_m2_ck>; + clock-mult = <1>; + clock-div = <2>; + }; + + dpll_disp_ck: dpll_disp_ck@498 { + #clock-cells = <0>; + compatible = "ti,am3-dpll-no-gate-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x0498>, <0x0448>, <0x0454>; + }; + + dpll_disp_m2_ck: dpll_disp_m2_ck@4a4 { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_disp_ck>; + ti,max-div = <31>; + reg = <0x04a4>; + ti,index-starts-at-one; + ti,set-rate-parent; + }; + + dpll_per_ck: dpll_per_ck@48c { + #clock-cells = <0>; + compatible = "ti,am3-dpll-no-gate-j-type-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x048c>, <0x0470>, <0x049c>; + }; + + dpll_per_m2_ck: dpll_per_m2_ck@4ac { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_per_ck>; + ti,max-div = <31>; + reg = <0x04ac>; + ti,index-starts-at-one; + }; + + dpll_per_m2_div4_wkupdm_ck: dpll_per_m2_div4_wkupdm_ck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_per_m2_ck>; + clock-mult = <1>; + clock-div = <4>; + }; + + dpll_per_m2_div4_ck: dpll_per_m2_div4_ck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_per_m2_ck>; + clock-mult = <1>; + clock-div = <4>; + }; + + clk_24mhz: clk_24mhz { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_per_m2_ck>; + clock-mult = <1>; + clock-div = <8>; + }; + + clkdiv32k_ck: clkdiv32k_ck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&clk_24mhz>; + clock-mult = <1>; + clock-div = <732>; + }; + + l3_gclk: l3_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + pruss_ocp_gclk: pruss_ocp_gclk@530 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&l3_gclk>, <&dpll_disp_m2_ck>; + reg = <0x0530>; + }; + + mmu_fck: mmu_fck@914 { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&dpll_core_m4_ck>; + ti,bit-shift = <1>; + reg = <0x0914>; + }; + + timer1_fck: timer1_fck@528 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>; + reg = <0x0528>; + }; + + timer2_fck: timer2_fck@508 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + reg = <0x0508>; + }; + + timer3_fck: timer3_fck@50c { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + reg = <0x050c>; + }; + + timer4_fck: timer4_fck@510 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + reg = <0x0510>; + }; + + timer5_fck: timer5_fck@518 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + reg = <0x0518>; + }; + + timer6_fck: timer6_fck@51c { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + reg = <0x051c>; + }; + + timer7_fck: timer7_fck@504 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + reg = <0x0504>; + }; + + usbotg_fck: usbotg_fck@47c { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&dpll_per_ck>; + ti,bit-shift = <8>; + reg = <0x047c>; + }; + + dpll_core_m4_div2_ck: dpll_core_m4_div2_ck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_ck>; + clock-mult = <1>; + clock-div = <2>; + }; + + ieee5000_fck: ieee5000_fck@e4 { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&dpll_core_m4_div2_ck>; + ti,bit-shift = <1>; + reg = <0x00e4>; + }; + + wdt1_fck: wdt1_fck@538 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&clk_rc32k_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + reg = <0x0538>; + }; + + l4_rtc_gclk: l4_rtc_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_ck>; + clock-mult = <1>; + clock-div = <2>; + }; + + l4hs_gclk: l4hs_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + l3s_gclk: l3s_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_div2_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + l4fw_gclk: l4fw_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_div2_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + l4ls_gclk: l4ls_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_div2_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + sysclk_div_ck: sysclk_div_ck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + cpsw_125mhz_gclk: cpsw_125mhz_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m5_ck>; + clock-mult = <1>; + clock-div = <2>; + }; + + cpsw_cpts_rft_clk: cpsw_cpts_rft_clk@520 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&dpll_core_m5_ck>, <&dpll_core_m4_ck>; + reg = <0x0520>; + }; + + gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck@53c { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + reg = <0x053c>; + }; + + lcd_gclk: lcd_gclk@534 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>; + reg = <0x0534>; + ti,set-rate-parent; + }; + + mmc_clk: mmc_clk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_per_m2_ck>; + clock-mult = <1>; + clock-div = <2>; + }; + + gfx_fclk_clksel_ck: gfx_fclk_clksel_ck@52c { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&dpll_core_m4_ck>, <&dpll_per_m2_ck>; + ti,bit-shift = <1>; + reg = <0x052c>; + }; + + gfx_fck_div_ck: gfx_fck_div_ck@52c { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&gfx_fclk_clksel_ck>; + reg = <0x052c>; + ti,max-div = <2>; + }; + + sysclkout_pre_ck: sysclkout_pre_ck@700 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&clk_32768_ck>, <&l3_gclk>, <&dpll_ddr_m2_ck>, <&dpll_per_m2_ck>, <&lcd_gclk>; + reg = <0x0700>; + }; + + clkout2_div_ck: clkout2_div_ck@700 { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&sysclkout_pre_ck>; + ti,bit-shift = <3>; + ti,max-div = <8>; + reg = <0x0700>; + }; + + clkout2_ck: clkout2_ck@700 { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&clkout2_div_ck>; + ti,bit-shift = <7>; + reg = <0x0700>; + }; +}; + +&prcm { + l4_per_cm: l4_per_cm@0 { + compatible = "ti,omap4-cm"; + reg = <0x0 0x200>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x200>; + + l4_per_clkctrl: clk@14 { + compatible = "ti,clkctrl"; + reg = <0x14 0x13c>; + #clock-cells = <2>; + }; + }; + + l4_wkup_cm: l4_wkup_cm@400 { + compatible = "ti,omap4-cm"; + reg = <0x400 0x100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x400 0x100>; + + l4_wkup_clkctrl: clk@4 { + compatible = "ti,clkctrl"; + reg = <0x4 0xd4>; + #clock-cells = <2>; + }; + }; + + mpu_cm: mpu_cm@600 { + compatible = "ti,omap4-cm"; + reg = <0x600 0x100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x600 0x100>; + + mpu_clkctrl: clk@4 { + compatible = "ti,clkctrl"; + reg = <0x4 0x4>; + #clock-cells = <2>; + }; + }; + + l4_rtc_cm: l4_rtc_cm@800 { + compatible = "ti,omap4-cm"; + reg = <0x800 0x100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x800 0x100>; + + l4_rtc_clkctrl: clk@0 { + compatible = "ti,clkctrl"; + reg = <0x0 0x4>; + #clock-cells = <2>; + }; + }; + + gfx_l3_cm: gfx_l3_cm@900 { + compatible = "ti,omap4-cm"; + reg = <0x900 0x100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x900 0x100>; + + gfx_l3_clkctrl: clk@4 { + compatible = "ti,clkctrl"; + reg = <0x4 0x4>; + #clock-cells = <2>; + }; + }; + + l4_cefuse_cm: l4_cefuse_cm@a00 { + compatible = "ti,omap4-cm"; + reg = <0xa00 0x100>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0xa00 0x100>; + + l4_cefuse_clkctrl: clk@20 { + compatible = "ti,clkctrl"; + reg = <0x20 0x4>; + #clock-cells = <2>; + }; + }; +};
diff --git a/arch/arm/dts/am33xx.dtsi b/arch/arm/dts/am33xx.dtsi new file mode 100644 index 0000000..d3dd6a1 --- /dev/null +++ b/arch/arm/dts/am33xx.dtsi
@@ -0,0 +1,1046 @@ +/* + * Device Tree Source for AM33XX SoC + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/pinctrl/am33xx.h> +#include <dt-bindings/clock/am3.h> + +/ { + compatible = "ti,am33xx"; + interrupt-parent = <&intc>; + #address-cells = <1>; + #size-cells = <1>; + chosen { }; + + aliases { + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + serial5 = &uart5; + d-can0 = &dcan0; + d-can1 = &dcan1; + usb0 = &usb0; + usb1 = &usb1; + phy0 = &usb0_phy; + phy1 = &usb1_phy; + ethernet0 = &cpsw_emac0; + ethernet1 = &cpsw_emac1; + spi0 = &spi0; + spi1 = &spi1; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + compatible = "arm,cortex-a8"; + device_type = "cpu"; + reg = <0>; + + operating-points-v2 = <&cpu0_opp_table>; + + clocks = <&dpll_mpu_ck>; + clock-names = "cpu"; + + clock-latency = <300000>; /* From omap-cpufreq driver */ + }; + }; + + cpu0_opp_table: opp-table { + compatible = "operating-points-v2-ti-cpu"; + syscon = <&scm_conf>; + + /* + * The three following nodes are marked with opp-suspend + * because the can not be enabled simultaneously on a + * single SoC. + */ + opp50-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <950000 931000 969000>; + opp-supported-hw = <0x06 0x0010>; + opp-suspend; + }; + + opp100-275000000 { + opp-hz = /bits/ 64 <275000000>; + opp-microvolt = <1100000 1078000 1122000>; + opp-supported-hw = <0x01 0x00FF>; + opp-suspend; + }; + + opp100-300000000 { + opp-hz = /bits/ 64 <300000000>; + opp-microvolt = <1100000 1078000 1122000>; + opp-supported-hw = <0x06 0x0020>; + opp-suspend; + }; + + opp100-500000000 { + opp-hz = /bits/ 64 <500000000>; + opp-microvolt = <1100000 1078000 1122000>; + opp-supported-hw = <0x01 0xFFFF>; + }; + + opp100-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <1100000 1078000 1122000>; + opp-supported-hw = <0x06 0x0040>; + }; + + opp120-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <1200000 1176000 1224000>; + opp-supported-hw = <0x01 0xFFFF>; + }; + + opp120-720000000 { + opp-hz = /bits/ 64 <720000000>; + opp-microvolt = <1200000 1176000 1224000>; + opp-supported-hw = <0x06 0x0080>; + }; + + oppturbo-720000000 { + opp-hz = /bits/ 64 <720000000>; + opp-microvolt = <1260000 1234800 1285200>; + opp-supported-hw = <0x01 0xFFFF>; + }; + + oppturbo-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1260000 1234800 1285200>; + opp-supported-hw = <0x06 0x0100>; + }; + + oppnitro-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <1325000 1298500 1351500>; + opp-supported-hw = <0x04 0x0200>; + }; + }; + + pmu@4b000000 { + compatible = "arm,cortex-a8-pmu"; + interrupts = <3>; + reg = <0x4b000000 0x1000000>; + ti,hwmods = "debugss"; + }; + + /* + * The soc node represents the soc top level view. It is used for IPs + * that are not memory mapped in the MPU view or for the MPU itself. + */ + soc { + compatible = "ti,omap-infra"; + mpu { + compatible = "ti,omap3-mpu"; + ti,hwmods = "mpu"; + pm-sram = <&pm_sram_code + &pm_sram_data>; + }; + }; + + /* + * XXX: Use a flat representation of the AM33XX interconnect. + * The real AM33XX interconnect network is quite complex. Since + * it will not bring real advantage to represent that in DT + * for the moment, just use a fake OCP bus entry to represent + * the whole bus hierarchy. + */ + ocp { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "l3_main"; + + l4_wkup: l4_wkup@44c00000 { + compatible = "ti,am3-l4-wkup", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x44c00000 0x280000>; + + wkup_m3: wkup_m3@100000 { + compatible = "ti,am3352-wkup-m3"; + reg = <0x100000 0x4000>, + <0x180000 0x2000>; + reg-names = "umem", "dmem"; + ti,hwmods = "wkup_m3"; + ti,pm-firmware = "am335x-pm-firmware.elf"; + }; + + prcm: prcm@200000 { + compatible = "ti,am3-prcm", "simple-bus"; + reg = <0x200000 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x200000 0x4000>; + + prcm_clocks: clocks { + #address-cells = <1>; + #size-cells = <0>; + }; + + prcm_clockdomains: clockdomains { + }; + }; + + scm: scm@210000 { + compatible = "ti,am3-scm", "simple-bus"; + reg = <0x210000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + #pinctrl-cells = <1>; + ranges = <0 0x210000 0x2000>; + + am33xx_pinmux: pinmux@800 { + compatible = "pinctrl-single"; + reg = <0x800 0x238>; + #address-cells = <1>; + #size-cells = <0>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x7f>; + }; + + scm_conf: scm_conf@0 { + compatible = "syscon", "simple-bus"; + reg = <0x0 0x800>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0x800>; + + scm_clocks: clocks { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + wkup_m3_ipc: wkup_m3_ipc@1324 { + compatible = "ti,am3352-wkup-m3-ipc"; + reg = <0x1324 0x24>; + interrupts = <78>; + ti,rproc = <&wkup_m3>; + mboxes = <&mailbox &mbox_wkupm3>; + }; + + edma_xbar: dma-router@f90 { + compatible = "ti,am335x-edma-crossbar"; + reg = <0xf90 0x40>; + #dma-cells = <3>; + dma-requests = <32>; + dma-masters = <&edma>; + }; + + scm_clockdomains: clockdomains { + }; + }; + }; + + intc: interrupt-controller@48200000 { + compatible = "ti,am33xx-intc"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x48200000 0x1000>; + }; + + edma: edma@49000000 { + compatible = "ti,edma3-tpcc"; + ti,hwmods = "tpcc"; + reg = <0x49000000 0x10000>; + reg-names = "edma3_cc"; + interrupts = <12 13 14>; + interrupt-names = "edma3_ccint", "edma3_mperr", + "edma3_ccerrint"; + dma-requests = <64>; + #dma-cells = <2>; + + ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 5>, + <&edma_tptc2 0>; + + ti,edma-memcpy-channels = <20 21>; + }; + + edma_tptc0: tptc@49800000 { + compatible = "ti,edma3-tptc"; + ti,hwmods = "tptc0"; + reg = <0x49800000 0x100000>; + interrupts = <112>; + interrupt-names = "edma3_tcerrint"; + }; + + edma_tptc1: tptc@49900000 { + compatible = "ti,edma3-tptc"; + ti,hwmods = "tptc1"; + reg = <0x49900000 0x100000>; + interrupts = <113>; + interrupt-names = "edma3_tcerrint"; + }; + + edma_tptc2: tptc@49a00000 { + compatible = "ti,edma3-tptc"; + ti,hwmods = "tptc2"; + reg = <0x49a00000 0x100000>; + interrupts = <114>; + interrupt-names = "edma3_tcerrint"; + }; + + gpio0: gpio@44e07000 { + compatible = "ti,omap4-gpio"; + ti,hwmods = "gpio1"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x44e07000 0x1000>; + interrupts = <96>; + }; + + gpio1: gpio@4804c000 { + compatible = "ti,omap4-gpio"; + ti,hwmods = "gpio2"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x4804c000 0x1000>; + interrupts = <98>; + }; + + gpio2: gpio@481ac000 { + compatible = "ti,omap4-gpio"; + ti,hwmods = "gpio3"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x481ac000 0x1000>; + interrupts = <32>; + }; + + gpio3: gpio@481ae000 { + compatible = "ti,omap4-gpio"; + ti,hwmods = "gpio4"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x481ae000 0x1000>; + interrupts = <62>; + }; + + uart0: serial@44e09000 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + ti,hwmods = "uart1"; + clock-frequency = <48000000>; + reg = <0x44e09000 0x2000>; + interrupts = <72>; + status = "disabled"; + dmas = <&edma 26 0>, <&edma 27 0>; + dma-names = "tx", "rx"; + }; + + uart1: serial@48022000 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + ti,hwmods = "uart2"; + clock-frequency = <48000000>; + reg = <0x48022000 0x2000>; + interrupts = <73>; + status = "disabled"; + dmas = <&edma 28 0>, <&edma 29 0>; + dma-names = "tx", "rx"; + }; + + uart2: serial@48024000 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + ti,hwmods = "uart3"; + clock-frequency = <48000000>; + reg = <0x48024000 0x2000>; + interrupts = <74>; + status = "disabled"; + dmas = <&edma 30 0>, <&edma 31 0>; + dma-names = "tx", "rx"; + }; + + uart3: serial@481a6000 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + ti,hwmods = "uart4"; + clock-frequency = <48000000>; + reg = <0x481a6000 0x2000>; + interrupts = <44>; + status = "disabled"; + }; + + uart4: serial@481a8000 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + ti,hwmods = "uart5"; + clock-frequency = <48000000>; + reg = <0x481a8000 0x2000>; + interrupts = <45>; + status = "disabled"; + }; + + uart5: serial@481aa000 { + compatible = "ti,am3352-uart", "ti,omap3-uart"; + ti,hwmods = "uart6"; + clock-frequency = <48000000>; + reg = <0x481aa000 0x2000>; + interrupts = <46>; + status = "disabled"; + }; + + i2c0: i2c@44e0b000 { + compatible = "ti,omap4-i2c"; + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c1"; + reg = <0x44e0b000 0x1000>; + interrupts = <70>; + status = "disabled"; + }; + + i2c1: i2c@4802a000 { + compatible = "ti,omap4-i2c"; + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c2"; + reg = <0x4802a000 0x1000>; + interrupts = <71>; + status = "disabled"; + }; + + i2c2: i2c@4819c000 { + compatible = "ti,omap4-i2c"; + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c3"; + reg = <0x4819c000 0x1000>; + interrupts = <30>; + status = "disabled"; + }; + + mmc1: mmc@48060000 { + compatible = "ti,omap4-hsmmc"; + ti,hwmods = "mmc1"; + ti,dual-volt; + ti,needs-special-reset; + ti,needs-special-hs-handling; + dmas = <&edma_xbar 24 0 0 + &edma_xbar 25 0 0>; + dma-names = "tx", "rx"; + interrupts = <64>; + reg = <0x48060000 0x1000>; + status = "disabled"; + }; + + mmc2: mmc@481d8000 { + compatible = "ti,omap4-hsmmc"; + ti,hwmods = "mmc2"; + ti,needs-special-reset; + dmas = <&edma 2 0 + &edma 3 0>; + dma-names = "tx", "rx"; + interrupts = <28>; + reg = <0x481d8000 0x1000>; + status = "disabled"; + }; + + mmc3: mmc@47810000 { + compatible = "ti,omap4-hsmmc"; + ti,hwmods = "mmc3"; + ti,needs-special-reset; + interrupts = <29>; + reg = <0x47810000 0x1000>; + status = "disabled"; + }; + + hwspinlock: spinlock@480ca000 { + compatible = "ti,omap4-hwspinlock"; + reg = <0x480ca000 0x1000>; + ti,hwmods = "spinlock"; + #hwlock-cells = <1>; + }; + + wdt2: wdt@44e35000 { + compatible = "ti,omap3-wdt"; + ti,hwmods = "wd_timer2"; + reg = <0x44e35000 0x1000>; + interrupts = <91>; + }; + + dcan0: can@481cc000 { + compatible = "ti,am3352-d_can"; + ti,hwmods = "d_can0"; + reg = <0x481cc000 0x2000>; + clocks = <&dcan0_fck>; + clock-names = "fck"; + syscon-raminit = <&scm_conf 0x644 0>; + interrupts = <52>; + status = "disabled"; + }; + + dcan1: can@481d0000 { + compatible = "ti,am3352-d_can"; + ti,hwmods = "d_can1"; + reg = <0x481d0000 0x2000>; + clocks = <&dcan1_fck>; + clock-names = "fck"; + syscon-raminit = <&scm_conf 0x644 1>; + interrupts = <55>; + status = "disabled"; + }; + + mailbox: mailbox@480c8000 { + compatible = "ti,omap4-mailbox"; + reg = <0x480C8000 0x200>; + interrupts = <77>; + ti,hwmods = "mailbox"; + #mbox-cells = <1>; + ti,mbox-num-users = <4>; + ti,mbox-num-fifos = <8>; + mbox_wkupm3: wkup_m3 { + ti,mbox-send-noirq; + ti,mbox-tx = <0 0 0>; + ti,mbox-rx = <0 0 3>; + }; + }; + + timer1: timer@44e31000 { + compatible = "ti,am335x-timer-1ms"; + reg = <0x44e31000 0x400>; + interrupts = <67>; + ti,hwmods = "timer1"; + ti,timer-alwon; + clocks = <&timer1_fck>; + clock-names = "fck"; + }; + + timer2: timer@48040000 { + compatible = "ti,am335x-timer"; + reg = <0x48040000 0x400>; + interrupts = <68>; + ti,hwmods = "timer2"; + clocks = <&timer2_fck>; + clock-names = "fck"; + }; + + timer3: timer@48042000 { + compatible = "ti,am335x-timer"; + reg = <0x48042000 0x400>; + interrupts = <69>; + ti,hwmods = "timer3"; + }; + + timer4: timer@48044000 { + compatible = "ti,am335x-timer"; + reg = <0x48044000 0x400>; + interrupts = <92>; + ti,hwmods = "timer4"; + ti,timer-pwm; + }; + + timer5: timer@48046000 { + compatible = "ti,am335x-timer"; + reg = <0x48046000 0x400>; + interrupts = <93>; + ti,hwmods = "timer5"; + ti,timer-pwm; + }; + + timer6: timer@48048000 { + compatible = "ti,am335x-timer"; + reg = <0x48048000 0x400>; + interrupts = <94>; + ti,hwmods = "timer6"; + ti,timer-pwm; + }; + + timer7: timer@4804a000 { + compatible = "ti,am335x-timer"; + reg = <0x4804a000 0x400>; + interrupts = <95>; + ti,hwmods = "timer7"; + ti,timer-pwm; + }; + + rtc: rtc@44e3e000 { + compatible = "ti,am3352-rtc", "ti,da830-rtc"; + reg = <0x44e3e000 0x1000>; + interrupts = <75 + 76>; + ti,hwmods = "rtc"; + clocks = <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + clock-names = "int-clk"; + }; + + spi0: spi@48030000 { + compatible = "ti,omap4-mcspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x48030000 0x400>; + interrupts = <65>; + ti,spi-num-cs = <2>; + ti,hwmods = "spi0"; + dmas = <&edma 16 0 + &edma 17 0 + &edma 18 0 + &edma 19 0>; + dma-names = "tx0", "rx0", "tx1", "rx1"; + status = "disabled"; + }; + + spi1: spi@481a0000 { + compatible = "ti,omap4-mcspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x481a0000 0x400>; + interrupts = <125>; + ti,spi-num-cs = <2>; + ti,hwmods = "spi1"; + dmas = <&edma 42 0 + &edma 43 0 + &edma 44 0 + &edma 45 0>; + dma-names = "tx0", "rx0", "tx1", "rx1"; + status = "disabled"; + }; + + usb: usb@47400000 { + compatible = "ti,am33xx-usb"; + reg = <0x47400000 0x1000>; + ranges; + #address-cells = <1>; + #size-cells = <1>; + ti,hwmods = "usb_otg_hs"; + status = "disabled"; + + usb_ctrl_mod: control@44e10620 { + compatible = "ti,am335x-usb-ctrl-module"; + reg = <0x44e10620 0x10 + 0x44e10648 0x4>; + reg-names = "phy_ctrl", "wakeup"; + status = "disabled"; + }; + + usb0_phy: usb-phy@47401300 { + compatible = "ti,am335x-usb-phy"; + reg = <0x47401300 0x100>; + reg-names = "phy"; + status = "disabled"; + ti,ctrl_mod = <&usb_ctrl_mod>; + #phy-cells = <0>; + }; + + usb0: usb@47401000 { + compatible = "ti,musb-am33xx"; + status = "disabled"; + reg = <0x47401400 0x400 + 0x47401000 0x200>; + reg-names = "mc", "control"; + + interrupts = <18>; + interrupt-names = "mc"; + dr_mode = "otg"; + mentor,multipoint = <1>; + mentor,num-eps = <16>; + mentor,ram-bits = <12>; + mentor,power = <500>; + phys = <&usb0_phy>; + + dmas = <&cppi41dma 0 0 &cppi41dma 1 0 + &cppi41dma 2 0 &cppi41dma 3 0 + &cppi41dma 4 0 &cppi41dma 5 0 + &cppi41dma 6 0 &cppi41dma 7 0 + &cppi41dma 8 0 &cppi41dma 9 0 + &cppi41dma 10 0 &cppi41dma 11 0 + &cppi41dma 12 0 &cppi41dma 13 0 + &cppi41dma 14 0 &cppi41dma 0 1 + &cppi41dma 1 1 &cppi41dma 2 1 + &cppi41dma 3 1 &cppi41dma 4 1 + &cppi41dma 5 1 &cppi41dma 6 1 + &cppi41dma 7 1 &cppi41dma 8 1 + &cppi41dma 9 1 &cppi41dma 10 1 + &cppi41dma 11 1 &cppi41dma 12 1 + &cppi41dma 13 1 &cppi41dma 14 1>; + dma-names = + "rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7", + "rx8", "rx9", "rx10", "rx11", "rx12", "rx13", + "rx14", "rx15", + "tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7", + "tx8", "tx9", "tx10", "tx11", "tx12", "tx13", + "tx14", "tx15"; + }; + + usb1_phy: usb-phy@47401b00 { + compatible = "ti,am335x-usb-phy"; + reg = <0x47401b00 0x100>; + reg-names = "phy"; + status = "disabled"; + ti,ctrl_mod = <&usb_ctrl_mod>; + #phy-cells = <0>; + }; + + usb1: usb@47401800 { + compatible = "ti,musb-am33xx"; + status = "disabled"; + reg = <0x47401c00 0x400 + 0x47401800 0x200>; + reg-names = "mc", "control"; + interrupts = <19>; + interrupt-names = "mc"; + dr_mode = "otg"; + mentor,multipoint = <1>; + mentor,num-eps = <16>; + mentor,ram-bits = <12>; + mentor,power = <500>; + phys = <&usb1_phy>; + + dmas = <&cppi41dma 15 0 &cppi41dma 16 0 + &cppi41dma 17 0 &cppi41dma 18 0 + &cppi41dma 19 0 &cppi41dma 20 0 + &cppi41dma 21 0 &cppi41dma 22 0 + &cppi41dma 23 0 &cppi41dma 24 0 + &cppi41dma 25 0 &cppi41dma 26 0 + &cppi41dma 27 0 &cppi41dma 28 0 + &cppi41dma 29 0 &cppi41dma 15 1 + &cppi41dma 16 1 &cppi41dma 17 1 + &cppi41dma 18 1 &cppi41dma 19 1 + &cppi41dma 20 1 &cppi41dma 21 1 + &cppi41dma 22 1 &cppi41dma 23 1 + &cppi41dma 24 1 &cppi41dma 25 1 + &cppi41dma 26 1 &cppi41dma 27 1 + &cppi41dma 28 1 &cppi41dma 29 1>; + dma-names = + "rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7", + "rx8", "rx9", "rx10", "rx11", "rx12", "rx13", + "rx14", "rx15", + "tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7", + "tx8", "tx9", "tx10", "tx11", "tx12", "tx13", + "tx14", "tx15"; + }; + + cppi41dma: dma-controller@47402000 { + compatible = "ti,am3359-cppi41"; + reg = <0x47400000 0x1000 + 0x47402000 0x1000 + 0x47403000 0x1000 + 0x47404000 0x4000>; + reg-names = "glue", "controller", "scheduler", "queuemgr"; + interrupts = <17>; + interrupt-names = "glue"; + #dma-cells = <2>; + #dma-channels = <30>; + #dma-requests = <256>; + status = "disabled"; + }; + }; + + epwmss0: epwmss@48300000 { + compatible = "ti,am33xx-pwmss"; + reg = <0x48300000 0x10>; + ti,hwmods = "epwmss0"; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + ranges = <0x48300100 0x48300100 0x80 /* ECAP */ + 0x48300180 0x48300180 0x80 /* EQEP */ + 0x48300200 0x48300200 0x80>; /* EHRPWM */ + + ecap0: ecap@48300100 { + compatible = "ti,am3352-ecap", + "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x48300100 0x80>; + clocks = <&l4ls_gclk>; + clock-names = "fck"; + interrupts = <31>; + interrupt-names = "ecap0"; + status = "disabled"; + }; + + ehrpwm0: pwm@48300200 { + compatible = "ti,am3352-ehrpwm", + "ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x48300200 0x80>; + clocks = <&ehrpwm0_tbclk>, <&l4ls_gclk>; + clock-names = "tbclk", "fck"; + status = "disabled"; + }; + }; + + epwmss1: epwmss@48302000 { + compatible = "ti,am33xx-pwmss"; + reg = <0x48302000 0x10>; + ti,hwmods = "epwmss1"; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + ranges = <0x48302100 0x48302100 0x80 /* ECAP */ + 0x48302180 0x48302180 0x80 /* EQEP */ + 0x48302200 0x48302200 0x80>; /* EHRPWM */ + + ecap1: ecap@48302100 { + compatible = "ti,am3352-ecap", + "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x48302100 0x80>; + clocks = <&l4ls_gclk>; + clock-names = "fck"; + interrupts = <47>; + interrupt-names = "ecap1"; + status = "disabled"; + }; + + ehrpwm1: pwm@48302200 { + compatible = "ti,am3352-ehrpwm", + "ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x48302200 0x80>; + clocks = <&ehrpwm1_tbclk>, <&l4ls_gclk>; + clock-names = "tbclk", "fck"; + status = "disabled"; + }; + }; + + epwmss2: epwmss@48304000 { + compatible = "ti,am33xx-pwmss"; + reg = <0x48304000 0x10>; + ti,hwmods = "epwmss2"; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + ranges = <0x48304100 0x48304100 0x80 /* ECAP */ + 0x48304180 0x48304180 0x80 /* EQEP */ + 0x48304200 0x48304200 0x80>; /* EHRPWM */ + + ecap2: ecap@48304100 { + compatible = "ti,am3352-ecap", + "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x48304100 0x80>; + clocks = <&l4ls_gclk>; + clock-names = "fck"; + interrupts = <61>; + interrupt-names = "ecap2"; + status = "disabled"; + }; + + ehrpwm2: pwm@48304200 { + compatible = "ti,am3352-ehrpwm", + "ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x48304200 0x80>; + clocks = <&ehrpwm2_tbclk>, <&l4ls_gclk>; + clock-names = "tbclk", "fck"; + status = "disabled"; + }; + }; + + mac: ethernet@4a100000 { + compatible = "ti,am335x-cpsw","ti,cpsw"; + ti,hwmods = "cpgmac0"; + clocks = <&cpsw_125mhz_gclk>, <&cpsw_cpts_rft_clk>; + clock-names = "fck", "cpts"; + cpdma_channels = <8>; + ale_entries = <1024>; + bd_ram_size = <0x2000>; + mac_control = <0x20>; + slaves = <2>; + active_slave = <0>; + cpts_clock_mult = <0x80000000>; + cpts_clock_shift = <29>; + reg = <0x4a100000 0x800 + 0x4a101200 0x100>; + #address-cells = <1>; + #size-cells = <1>; + /* + * c0_rx_thresh_pend + * c0_rx_pend + * c0_tx_pend + * c0_misc_pend + */ + interrupts = <40 41 42 43>; + ranges; + syscon = <&scm_conf>; + status = "disabled"; + + davinci_mdio: mdio@4a101000 { + compatible = "ti,cpsw-mdio","ti,davinci_mdio"; + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "davinci_mdio"; + bus_freq = <1000000>; + reg = <0x4a101000 0x100>; + status = "disabled"; + }; + + cpsw_emac0: slave@4a100200 { + /* Filled in by U-Boot */ + mac-address = [ 00 00 00 00 00 00 ]; + }; + + cpsw_emac1: slave@4a100300 { + /* Filled in by U-Boot */ + mac-address = [ 00 00 00 00 00 00 ]; + }; + + phy_sel: cpsw-phy-sel@44e10650 { + compatible = "ti,am3352-cpsw-phy-sel"; + reg= <0x44e10650 0x4>; + reg-names = "gmii-sel"; + }; + }; + + ocmcram: ocmcram@40300000 { + compatible = "mmio-sram"; + reg = <0x40300000 0x10000>; /* 64k */ + ranges = <0x0 0x40300000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + + pm_sram_code: pm-sram-code@0 { + compatible = "ti,sram"; + reg = <0x0 0x1000>; + protect-exec; + }; + + pm_sram_data: pm-sram-data@1000 { + compatible = "ti,sram"; + reg = <0x1000 0x1000>; + pool; + }; + }; + + elm: elm@48080000 { + compatible = "ti,am3352-elm"; + reg = <0x48080000 0x2000>; + interrupts = <4>; + ti,hwmods = "elm"; + status = "disabled"; + }; + + lcdc: lcdc@4830e000 { + compatible = "ti,am33xx-tilcdc"; + reg = <0x4830e000 0x1000>; + interrupts = <36>; + ti,hwmods = "lcdc"; + status = "disabled"; + }; + + tscadc: tscadc@44e0d000 { + compatible = "ti,am3359-tscadc"; + reg = <0x44e0d000 0x1000>; + interrupts = <16>; + ti,hwmods = "adc_tsc"; + status = "disabled"; + dmas = <&edma 53 0>, <&edma 57 0>; + dma-names = "fifo0", "fifo1"; + + tsc { + compatible = "ti,am3359-tsc"; + }; + am335x_adc: adc { + #io-channel-cells = <1>; + compatible = "ti,am3359-adc"; + }; + }; + + emif: emif@4c000000 { + compatible = "ti,emif-am3352"; + reg = <0x4c000000 0x1000000>; + ti,hwmods = "emif"; + interrupts = <101>; + sram = <&pm_sram_code + &pm_sram_data>; + ti,no-idle; + }; + + gpmc: gpmc@50000000 { + compatible = "ti,am3352-gpmc"; + ti,hwmods = "gpmc"; + ti,no-idle-on-init; + reg = <0x50000000 0x2000>; + interrupts = <100>; + dmas = <&edma 52 0>; + dma-names = "rxtx"; + gpmc,num-cs = <7>; + gpmc,num-waitpins = <2>; + #address-cells = <2>; + #size-cells = <1>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + }; + + sham: sham@53100000 { + compatible = "ti,omap4-sham"; + ti,hwmods = "sham"; + reg = <0x53100000 0x200>; + interrupts = <109>; + dmas = <&edma 36 0>; + dma-names = "rx"; + }; + + aes: aes@53500000 { + compatible = "ti,omap4-aes"; + ti,hwmods = "aes"; + reg = <0x53500000 0xa0>; + interrupts = <103>; + dmas = <&edma 6 0>, + <&edma 5 0>; + dma-names = "tx", "rx"; + }; + + mcasp0: mcasp@48038000 { + compatible = "ti,am33xx-mcasp-audio"; + ti,hwmods = "mcasp0"; + reg = <0x48038000 0x2000>, + <0x46000000 0x400000>; + reg-names = "mpu", "dat"; + interrupts = <80>, <81>; + interrupt-names = "tx", "rx"; + status = "disabled"; + dmas = <&edma 8 2>, + <&edma 9 2>; + dma-names = "tx", "rx"; + }; + + mcasp1: mcasp@4803c000 { + compatible = "ti,am33xx-mcasp-audio"; + ti,hwmods = "mcasp1"; + reg = <0x4803C000 0x2000>, + <0x46400000 0x400000>; + reg-names = "mpu", "dat"; + interrupts = <82>, <83>; + interrupt-names = "tx", "rx"; + status = "disabled"; + dmas = <&edma 10 2>, + <&edma 11 2>; + dma-names = "tx", "rx"; + }; + + rng: rng@48310000 { + compatible = "ti,omap4-rng"; + ti,hwmods = "rng"; + reg = <0x48310000 0x2000>; + interrupts = <111>; + }; + }; +}; + +#include "am33xx-clocks.dtsi"
diff --git a/arch/arm/dts/am3517-evm-u-boot.dtsi b/arch/arm/dts/am3517-evm-u-boot.dtsi new file mode 100644 index 0000000..59df819 --- /dev/null +++ b/arch/arm/dts/am3517-evm-u-boot.dtsi
@@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 + * Logic PD - http://www.logicpd.com + */ + +/ { + chosen { + stdout-path = &uart3; + }; +}; + +&uart1 { + reg-shift = <2>; +}; + +&uart2 { + reg-shift = <2>; +}; + +&uart3 { + reg-shift = <2>; +};
diff --git a/arch/arm/dts/am3517-evm-ui.dtsi b/arch/arm/dts/am3517-evm-ui.dtsi new file mode 100644 index 0000000..e841918 --- /dev/null +++ b/arch/arm/dts/am3517-evm-ui.dtsi
@@ -0,0 +1,220 @@ +/* + * Copyright (C) 2018 Logic PD, Inc - http://www.logicpd.com/ + * + * 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. + */ + +#include <dt-bindings/input/input.h> + +/ { + codec1 { + compatible = "simple-audio-card"; + simple-audio-card,name = "tlv320aic23-hifi"; + + simple-audio-card,widgets = + "Microphone", "Mic In", + "Line", "Line In", + "Line", "Line Out"; + + simple-audio-card,routing = + "Line Out", "LOUT", + "Line Out", "ROUT", + "LLINEIN", "Line In", + "RLINEIN", "Line In", + "MICIN", "Mic In"; + + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&sound_master>; + simple-audio-card,frame-master = <&sound_master>; + + simple-audio-card,cpu { + sound-dai = <&mcbsp1>; + }; + + sound_master: simple-audio-card,codec { + sound-dai = <&tlv320aic23_1>; + system-clock-frequency = <12000000>; + }; + }; + + codec2 { + compatible = "simple-audio-card"; + simple-audio-card,name = "tlv320aic23-hifi"; + + simple-audio-card,widgets = + "Microphone", "Mic In", + "Line", "Line In", + "Line", "Line Out"; + + simple-audio-card,routing = + "Line Out", "LOUT", + "Line Out", "ROUT", + "LLINEIN", "Line In", + "RLINEIN", "Line In", + "MICIN", "Mic In"; + + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&sound_master2>; + simple-audio-card,frame-master = <&sound_master2>; + + simple-audio-card,cpu { + sound-dai = <&mcbsp2>; + }; + + sound_master2: simple-audio-card,codec { + sound-dai = <&tlv320aic23_2>; + system-clock-frequency = <12000000>; + }; + }; + + expander-keys { + compatible = "gpio-keys-polled"; + poll-interval = <100>; + + record { + label = "Record"; + /* linux,code = <BTN_0>; */ + gpios = <&tca6416_2 15 GPIO_ACTIVE_LOW>; + }; + + play { + label = "Play"; + linux,code = <KEY_PLAY>; + gpios = <&tca6416_2 14 GPIO_ACTIVE_LOW>; + }; + + Stop { + label = "Stop"; + linux,code = <KEY_STOP>; + gpios = <&tca6416_2 13 GPIO_ACTIVE_LOW>; + }; + + fwd { + label = "FWD"; + linux,code = <KEY_FASTFORWARD>; + gpios = <&tca6416_2 12 GPIO_ACTIVE_LOW>; + }; + + rwd { + label = "RWD"; + linux,code = <KEY_REWIND>; + gpios = <&tca6416_2 11 GPIO_ACTIVE_LOW>; + }; + + shift { + label = "Shift"; + linux,code = <KEY_LEFTSHIFT>; + gpios = <&tca6416_2 10 GPIO_ACTIVE_LOW>; + }; + + Mode { + label = "Mode"; + linux,code = <BTN_MODE>; + gpios = <&tca6416_2 9 GPIO_ACTIVE_LOW>; + }; + + Menu { + label = "Menu"; + linux,code = <KEY_MENU>; + gpios = <&tca6416_2 8 GPIO_ACTIVE_LOW>; + }; + + Up { + label = "Up"; + linux,code = <KEY_UP>; + gpios = <&tca6416_2 7 GPIO_ACTIVE_LOW>; + }; + + Down { + label = "Down"; + linux,code = <KEY_DOWN>; + gpios = <&tca6416_2 6 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&i2c2 { + /* Audio codecs */ + tlv320aic23_1: codec@1a { + compatible = "ti,tlv320aic23"; + reg = <0x1a>; + #sound-dai-cells= <0>; + status = "okay"; + }; + + tlv320aic23_2: codec@1b { + compatible = "ti,tlv320aic23"; + reg = <0x1b>; + #sound-dai-cells= <0>; + status = "okay"; + }; +}; + +&i2c3 { + /* Audio codecs */ + tlv320aic23_3: codec@1a { + compatible = "ti,tlv320aic23"; + reg = <0x1a>; + #sound-dai-cells= <0>; + status = "okay"; + }; + + /* GPIO Expanders */ + tca6416_2: gpio@20 { + compatible = "ti,tca6416"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + vcc-supply = <&vdd_io_reg>; + }; + + tca6416_3: gpio@21 { + compatible = "ti,tca6416"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + vcc-supply = <&vdd_io_reg>; + }; + + /* TVP5146 Analog Video decoder input */ + tvp5146@5c { + compatible = "ti,tvp5146m2"; + reg = <0x5c>; + }; +}; + +&mcbsp1 { + status = "ok"; + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp1_pins>; +}; + +&mcbsp2 { + status = "ok"; + #sound-dai-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp2_pins>; +}; + +&omap3_pmx_core { + mcbsp1_pins: pinmux_mcbsp1_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2190, PIN_OUTPUT | MUX_MODE0) /* mcbsp1_dx.mcbsp1_dx */ + OMAP3_CORE1_IOPAD(0x2192, PIN_INPUT | MUX_MODE0) /* mcbsp1_dx.mcbsp1_dr */ + OMAP3_CORE1_IOPAD(0x2196, PIN_INPUT | MUX_MODE0) /* mcbsp_clks.mcbsp1_fsx */ + OMAP3_CORE1_IOPAD(0x2198, PIN_INPUT | MUX_MODE0) /* mcbsp1_clkx.mcbsp1_clkx */ + >; + }; + + mcbsp2_pins: pinmux_mcbsp2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx.mcbsp2_fsx */ + OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0) /* mcbsp2_clkx.mcbsp2_clkx */ + OMAP3_CORE1_IOPAD(0x2140, PIN_INPUT | MUX_MODE0) /* mcbsp2_dr.mcbsp2.dr */ + OMAP3_CORE1_IOPAD(0x2142, PIN_OUTPUT | MUX_MODE0) /* mcbsp2_dx.mcbsp2_dx */ + >; + }; +};
diff --git a/arch/arm/dts/am3517-evm.dts b/arch/arm/dts/am3517-evm.dts new file mode 100644 index 0000000..1e2bb68 --- /dev/null +++ b/arch/arm/dts/am3517-evm.dts
@@ -0,0 +1,335 @@ +/* + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +#include "am3517.dtsi" +#include "am3517-som.dtsi" +#include "am3517-evm-ui.dtsi" +#include <dt-bindings/input/input.h> + +/ { + model = "TI AM3517 EVM (AM3517/05 TMDSEVM3517)"; + compatible = "ti,am3517-evm", "ti,am3517", "ti,omap3"; + + aliases { + display0 = &lcd0; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + vmmc_fixed: vmmc { + compatible = "regulator-fixed"; + regulator-name = "vmmc_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + gpio-keys { + compatible = "gpio-keys-polled"; + poll-interval = <100>; + + user_pb { + label = "User Push Button"; + linux,code = <BTN_0>; + gpios = <&tca6416 5 GPIO_ACTIVE_LOW>; + }; + + user_sw_1 { + label = "User Switch 1"; + linux,code = <BTN_1>; + gpios = <&tca6416 8 GPIO_ACTIVE_LOW>; + }; + + user_sw_2 { + label = "User Switch 2"; + linux,code = <BTN_2>; + gpios = <&tca6416 9 GPIO_ACTIVE_LOW>; + }; + + user_sw_3 { + label = "User Switch 3"; + linux,code = <BTN_3>; + gpios = <&tca6416 10 GPIO_ACTIVE_LOW>; + }; + + user_sw_4 { + label = "User Switch 4"; + linux,code = <BTN_4>; + gpios = <&tca6416 11 GPIO_ACTIVE_LOW>; + }; + + user_sw_5 { + label = "User Switch 5"; + linux,code = <BTN_5>; + gpios = <&tca6416 12 GPIO_ACTIVE_LOW>; + }; + + user_sw_6 { + label = "User Switch 6"; + linux,code = <BTN_6>; + gpios = <&tca6416 13 GPIO_ACTIVE_LOW>; + }; + + user_sw_7 { + label = "User Switch 7"; + linux,code = <BTN_7>; + gpios = <&tca6416 14 GPIO_ACTIVE_LOW>; + }; + + user_sw_8 { + label = "User Switch 8"; + linux,code = <BTN_8>; + gpios = <&tca6416 15 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + pinctrl-names = "default"; + pinctrl-0 = <&leds_pins>; + + user_led_1 { + label = "am3517evm:green:user_led_1"; + gpios = <&tca6416 7 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + user_led_2 { + label = "am3517evm:green:user_led_2"; + gpios = <&tca6416 6 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + user_led_3 { + label = "am3517evm:green:user_led_3"; + gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; /* SD/MMC card activity */ + }; + + user_led_4 { + label = "am3517evm:green:user_led_4"; + gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + lcd0: display@0 { + compatible = "panel-dpi"; + label = "15"; + status = "okay"; + pinctrl-names = "default"; + enable-gpios = <&gpio6 16 GPIO_ACTIVE_HIGH>; /* gpio176, lcd INI */ + vcc-supply = <&vdd_io_reg>; + + port { + lcd_in: endpoint { + remote-endpoint = <&dpi_out>; + }; + }; + + panel-timing { + clock-frequency = <9000000>; + hactive = <480>; + vactive = <272>; + hfront-porch = <3>; + hback-porch = <2>; + hsync-len = <42>; + vback-porch = <3>; + vfront-porch = <4>; + vsync-len = <11>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + }; + + bl: backlight { + compatible = "pwm-backlight"; + pinctrl-names = "default"; + power-supply = <&vdd_io_reg>; + pinctrl-0 = <&backlight_pins>; + pwms = <&pwm11 0 5000000 0>; + brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>; + default-brightness-level = <7>; + enable-gpios = <&gpio6 22 GPIO_ACTIVE_HIGH>; /* gpio_182 */ + }; + + pwm11: dmtimer-pwm@11 { + compatible = "ti,omap-dmtimer-pwm"; + pinctrl-names = "default"; + pinctrl-0 = <&pwm_pins>; + ti,timers = <&timer11>; + #pwm-cells = <3>; + }; + + /* HS USB Host PHY on PORT 1 */ + hsusb1_phy: hsusb1_phy { + compatible = "usb-nop-xceiv"; + reset-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>; /* gpio_57 */ + #phy-cells = <0>; + }; +}; + +&davinci_emac { + status = "okay"; +}; + +&davinci_mdio { + status = "okay"; +}; + +&dss { + status = "ok"; + + pinctrl-names = "default"; + pinctrl-0 = <&dss_dpi_pins>; + + vdds_dsi-supply = <&vdd_io_reg>; + vdda_video-supply = <&vdd_io_reg>; + + port { + dpi_out: endpoint { + remote-endpoint = <&lcd_in>; + data-lines = <16>; + }; + }; +}; + +&i2c2 { + clock-frequency = <400000>; + /* User DIP swithes [1:8] / User LEDS [1:2] */ + tca6416: gpio@21 { + compatible = "ti,tca6416"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + vcc-supply = <&vdd_io_reg>; + }; +}; + +&i2c3 { + clock-frequency = <400000>; +}; + +&mmc1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + vmmc-supply = <&vmmc_fixed>; + bus-width = <4>; + wp-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>; /* gpio_126 */ + cd-gpios = <&gpio4 31 GPIO_ACTIVE_LOW>; /* gpio_127 */ +}; + +&mmc3 { + status = "disabled"; +}; + +&usbhshost { + port1-mode = "ehci-phy"; +}; + +&usbhsehci { + phys = <&hsusb1_phy>; +}; + +&omap3_pmx_core { + pinctrl-names = "default"; + pinctrl-0 = <&hsusb1_rst_pins>; + + leds_pins: pinmux_leds_pins { + pinctrl-single,pins = < + OMAP3_WKUP_IOPAD(0x2a24, PIN_OUTPUT_PULLUP | MUX_MODE4) /* jtag_emu0.gpio_11 */ + OMAP3_WKUP_IOPAD(0x2a26, PIN_OUTPUT_PULLUP | MUX_MODE4) /* jtag_emu1.gpio_31 */ + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ + OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ + OMAP3_CORE1_IOPAD(0x2148, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat0.sdmmc1_dat0 */ + OMAP3_CORE1_IOPAD(0x214a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat1.sdmmc1_dat1 */ + OMAP3_CORE1_IOPAD(0x214c, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat2.sdmmc1_dat2 */ + OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat3.sdmmc1_dat3 */ + OMAP3_CORE1_IOPAD(0x2150, PIN_INPUT_PULLUP | MUX_MODE4) /* sdmmc1_dat4.gpio_126 */ + OMAP3_CORE1_IOPAD(0x2152, PIN_INPUT_PULLUP | MUX_MODE4) /* sdmmc1_dat5.gpio_127 */ + >; + }; + + pwm_pins: pinmux_pwm_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21dc, PIN_OUTPUT | MUX_MODE1) /* mcspi2_cs0.gpt11_pwm */ + >; + }; + + backlight_pins: pinmux_backlight_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21de, PIN_OUTPUT | MUX_MODE4) /* mcspi2_cs1.gpio_182 */ + >; + }; + + dss_dpi_pins: pinmux_dss_dpi_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21d2, PIN_OUTPUT | MUX_MODE4) /* mcspi1_cs2.gpio_176 */ + OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ + OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ + OMAP3_CORE1_IOPAD(0x20d8, PIN_OUTPUT | MUX_MODE0) /* dss_vsync.dss_vsync */ + OMAP3_CORE1_IOPAD(0x20da, PIN_OUTPUT | MUX_MODE0) /* dss_acbias.dss_acbias */ + OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE0) /* dss_data0.dss_data0 */ + OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE0) /* dss_data1.dss_data1 */ + OMAP3_CORE1_IOPAD(0x20e0, PIN_OUTPUT | MUX_MODE0) /* dss_data2.dss_data2 */ + OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE0) /* dss_data3.dss_data3 */ + OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE0) /* dss_data4.dss_data4 */ + OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE0) /* dss_data5.dss_data5 */ + OMAP3_CORE1_IOPAD(0x20e8, PIN_OUTPUT | MUX_MODE0) /* dss_data6.dss_data6 */ + OMAP3_CORE1_IOPAD(0x20ea, PIN_OUTPUT | MUX_MODE0) /* dss_data7.dss_data7 */ + OMAP3_CORE1_IOPAD(0x20ec, PIN_OUTPUT | MUX_MODE0) /* dss_data8.dss_data8 */ + OMAP3_CORE1_IOPAD(0x20ee, PIN_OUTPUT | MUX_MODE0) /* dss_data9.dss_data9 */ + OMAP3_CORE1_IOPAD(0x20f0, PIN_OUTPUT | MUX_MODE0) /* dss_data10.dss_data10 */ + OMAP3_CORE1_IOPAD(0x20f2, PIN_OUTPUT | MUX_MODE0) /* dss_data11.dss_data11 */ + OMAP3_CORE1_IOPAD(0x20f4, PIN_OUTPUT | MUX_MODE0) /* dss_data12.dss_data12 */ + OMAP3_CORE1_IOPAD(0x20f6, PIN_OUTPUT | MUX_MODE0) /* dss_data13.dss_data13 */ + OMAP3_CORE1_IOPAD(0x20f8, PIN_OUTPUT | MUX_MODE0) /* dss_data14.dss_data14 */ + OMAP3_CORE1_IOPAD(0x20fa, PIN_OUTPUT | MUX_MODE0) /* dss_data15.dss_data15 */ + >; + }; + + hsusb1_rst_pins: pinmux_hsusb1_rst_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x20ba, PIN_OUTPUT | MUX_MODE4) /* gpmc_ncs6.gpio_57 */ + >; + }; +}; + +&omap3_pmx_core2 { + pinctrl-names = "default"; + pinctrl-0 = <&hsusb1_pins>; + + hsusb1_pins: pinmux_hsusb1_pins { + pinctrl-single,pins = < + OMAP3430_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE3) /* etk_clk.hsusb1_stp */ + OMAP3430_CORE2_IOPAD(0x25da, PIN_OUTPUT | MUX_MODE3) /* etk_ctl.hsusb1_clk */ + OMAP3430_CORE2_IOPAD(0x25ec, PIN_INPUT | MUX_MODE3) /* etk_d8.hsusb1_dir */ + OMAP3430_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE3) /* etk_d9.hsusb1_nxt */ + OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE3) /* etk_d0.hsusb1_data0 */ + OMAP3430_CORE2_IOPAD(0x25de, PIN_INPUT | MUX_MODE3) /* etk_d1.hsusb1_data1 */ + OMAP3430_CORE2_IOPAD(0x25e0, PIN_INPUT | MUX_MODE3) /* etk_d2.hsusb1_data2 */ + OMAP3430_CORE2_IOPAD(0x25ea, PIN_INPUT | MUX_MODE3) /* etk_d7.hsusb1_data3 */ + OMAP3430_CORE2_IOPAD(0x25e4, PIN_INPUT | MUX_MODE3) /* etk_d4.hsusb1_data4 */ + OMAP3430_CORE2_IOPAD(0x25e6, PIN_INPUT | MUX_MODE3) /* etk_d5.hsusb1_data5 */ + OMAP3430_CORE2_IOPAD(0x25e8, PIN_INPUT | MUX_MODE3) /* etk_d6.hsusb1_data6 */ + OMAP3430_CORE2_IOPAD(0x25e2, PIN_INPUT | MUX_MODE3) /* etk_d3.hsusb1_data7 */ + >; + }; +};
diff --git a/arch/arm/dts/am3517-som.dtsi b/arch/arm/dts/am3517-som.dtsi new file mode 100644 index 0000000..b1c988e --- /dev/null +++ b/arch/arm/dts/am3517-som.dtsi
@@ -0,0 +1,237 @@ +/* + * Copyright (C) 2016 Derald D. Woods <woods.technical@gmail.com> + * + * Based on am3517-evm.dts + * + * 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. + */ + +/ { + cpus { + cpu@0 { + cpu0-supply = <&vdd_core_reg>; + }; + }; + + wl12xx_buffer: wl12xx_buf { + compatible = "regulator-fixed"; + regulator-name = "wl1271_buf"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + pinctrl-names = "default"; + pinctrl-0 = <&wl12xx_buffer_pins>; + gpio = <&gpio5 1 GPIO_ACTIVE_LOW>; /* gpio 129 */ + regulator-always-on; + vin-supply = <&vdd_1v8_reg>; + }; + + wl12xx_vmmc2: wl12xx_vmmc2 { + compatible = "regulator-fixed"; + regulator-name = "vwl1271"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + pinctrl-names = "default"; + pinctrl-0 = <&wl12xx_wkup_pins>; + gpio = <&gpio1 3 GPIO_ACTIVE_HIGH >; /* gpio 3 */ + startup-delay-us = <70000>; + enable-active-high; + regulator-always-on; + vin-supply = <&wl12xx_buffer>; + }; +}; + +&gpmc { + ranges = <0 0 0x30000000 0x1000000>; /* CS0: 16MB for NAND */ + + nand@0,0 { + compatible = "ti,omap2-nand"; + linux,mtd-name = "micron,mt29f4g16abchch"; + reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ + nand-bus-width = <16>; + ti,nand-ecc-opt = "bch8"; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-off-ns = <40>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + gpmc,device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&i2c1 { + clock-frequency = <400000>; + + s35390a: s35390a@30 { + compatible = "sii,s35390a"; + reg = <0x30>; + + pinctrl-names = "default"; + pinctrl-0 = <&rtc_pins>; + interrupts-extended = <&gpio2 23 IRQ_TYPE_EDGE_FALLING>; /* gpio_55 */ + }; + + tps: tps65023@48 { + compatible = "ti,tps65023"; + reg = <0x48>; + + regulators { + vdd_core_reg: VDCDC1 { + regulator-name = "vdd_core"; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + vdd_io_reg: VDCDC2 { + regulator-name = "vdd_io"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdd_1v8_reg: VDCDC3 { + regulator-name = "vdd_1v8"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vdd_usb18_reg: LDO1 { + regulator-name = "vdd_usb18"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vdd_usb33_reg: LDO2 { + regulator-name = "vdd_usb33"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; + + touchscreen: tsc2004@4b { + compatible = "ti,tsc2004"; + reg = <0x4b>; + + vio-supply = <&vdd_io_reg>; + + pinctrl-names = "default"; + pinctrl-0 = <&tsc2004_pins>; + interrupts-extended = <&gpio3 1 IRQ_TYPE_EDGE_RISING>; /* gpio_65 */ + + touchscreen-fuzz-x = <4>; + touchscreen-fuzz-y = <7>; + touchscreen-fuzz-pressure = <2>; + touchscreen-size-x = <480>; + touchscreen-size-y = <272>; + touchscreen-max-pressure = <2048>; + + ti,x-plate-ohms = <280>; + ti,esd-recovery-timeout-ms = <8000>; + }; +}; + +&mmc2 { + interrupts-extended = <&intc 86 /* &omap3_pmx_core 0x12c */>; + + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + vmmc-supply = <&wl12xx_vmmc2>; + non-removable; + bus-width = <4>; + cap-power-off-card; + #address-cells = <1>; + #size-cells = <0>; + wlcore: wlcore@2 { + compatible = "ti,wl1271"; + reg = <2>; + interrupt-parent = <&gpio6>; + interrupts = <10 IRQ_TYPE_EDGE_RISING>; /* gpio_170 */ + ref-clock-frequency = <26000000>; + tcxo-clock-frequency = <26000000>; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + + bluetooth { + compatible = "ti,wl1271-st"; + enable-gpios = <&gpio2 24 GPIO_ACTIVE_HIGH>; /* gpio 56 */ + max-speed = <3000000>; + }; +}; + +&omap3_pmx_core { + + wl12xx_buffer_pins: pinmux_wl12xx_buffer_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2156, PIN_OUTPUT | MUX_MODE4) /* mmc1_dat7.gpio_129 */ + >; + }; + + mmc2_pins: pinmux_mmc2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc2_clk.mmc2_clk */ + OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc2_cmd.mmc2_cmd */ + OMAP3_CORE1_IOPAD(0x215c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc2_dat0.mmc2_dat0 */ + OMAP3_CORE1_IOPAD(0x215e, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc2_dat1.mmc2_dat1 */ + OMAP3_CORE1_IOPAD(0x2160, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc2_dat2.mmc2_dat2 */ + OMAP3_CORE1_IOPAD(0x2162, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc2_dat3.mmc2_dat3 */ + OMAP3_CORE1_IOPAD(0x2164, PIN_OUTPUT | MUX_MODE1) /* mmc2_dat4.mmc2_dir_dat0 */ + OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE1) /* mmc2_dat5.mmc2_dir_dat1 */ + OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE1) /* mmc2_dat6.mmc2_dir_cmd */ + OMAP3_CORE1_IOPAD(0x216a, PIN_INPUT | MUX_MODE1) /* mmc2_dat7.mmc2_clkin */ + OMAP3_CORE1_IOPAD(0x21c6, PIN_INPUT_PULLUP | MUX_MODE4) /* hdq_sio.gpio_170 */ + >; + }; + + rtc_pins: pinmux_rtc_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x20b6, PIN_INPUT_PULLUP | MUX_MODE4) /* gpmc_ncs4.gpio_55 */ + >; + }; + + tsc2004_pins: pinmux_tsc2004_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x20d2, PIN_INPUT | MUX_MODE4) /* gpmc_wait3.gpio_65 */ + >; + }; + + uart2_pins: pinmux_uart2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts */ + OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT_PULLUP | MUX_MODE0) /* uart2_rts */ + OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0) /* uart2_tx */ + OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0) /* uart2_rx */ + OMAP3_CORE1_IOPAD(0x20b8, PIN_INPUT | MUX_MODE0) /* gpio_56 */ + >; + }; +}; + +&omap3_pmx_wkup { + + wl12xx_wkup_pins: pinmux_wl12xx_wkup_pins { + pinctrl-single,pins = < + OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE4) /* sys_boot1.gpio_3 */ + >; + }; +};
diff --git a/arch/arm/dts/am3517-u-boot.dtsi b/arch/arm/dts/am3517-u-boot.dtsi new file mode 100644 index 0000000..374499d --- /dev/null +++ b/arch/arm/dts/am3517-u-boot.dtsi
@@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 + * Logic PD - http://www.logicpd.com + */ + +&uart4 { + reg-shift = <2>; +};
diff --git a/arch/arm/dts/am3517.dtsi b/arch/arm/dts/am3517.dtsi new file mode 100644 index 0000000..23ea381 --- /dev/null +++ b/arch/arm/dts/am3517.dtsi
@@ -0,0 +1,112 @@ +/* + * Device Tree Source for am3517 SoC + * + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include "omap3.dtsi" + +/ { + aliases { + serial3 = &uart4; + can = &hecc; + }; + + ocp@68000000 { + am35x_otg_hs: am35x_otg_hs@5c040000 { + compatible = "ti,omap3-musb"; + ti,hwmods = "am35x_otg_hs"; + status = "disabled"; + reg = <0x5c040000 0x1000>; + interrupts = <71>; + interrupt-names = "mc"; + }; + + davinci_emac: ethernet@5c000000 { + compatible = "ti,am3517-emac"; + ti,hwmods = "davinci_emac"; + status = "disabled"; + reg = <0x5c000000 0x30000>; + interrupts = <67 68 69 70>; + syscon = <&scm_conf>; + ti,davinci-ctrl-reg-offset = <0x10000>; + ti,davinci-ctrl-mod-reg-offset = <0>; + ti,davinci-ctrl-ram-offset = <0x20000>; + ti,davinci-ctrl-ram-size = <0x2000>; + ti,davinci-rmii-en = /bits/ 8 <1>; + local-mac-address = [ 00 00 00 00 00 00 ]; + clocks = <&emac_ick>; + clock-names = "ick"; + }; + + davinci_mdio: ethernet@5c030000 { + compatible = "ti,davinci_mdio"; + ti,hwmods = "davinci_mdio"; + status = "disabled"; + reg = <0x5c030000 0x1000>; + bus_freq = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&emac_fck>; + clock-names = "fck"; + }; + + uart4: serial@4809e000 { + compatible = "ti,omap3-uart"; + ti,hwmods = "uart4"; + status = "disabled"; + reg = <0x4809e000 0x400>; + interrupts = <84>; + dmas = <&sdma 55 &sdma 54>; + dma-names = "tx", "rx"; + clock-frequency = <48000000>; + }; + + omap3_pmx_core2: pinmux@480025d8 { + compatible = "ti,omap3-padconf", "pinctrl-single"; + reg = <0x480025d8 0x24>; + #address-cells = <1>; + #size-cells = <0>; + #pinctrl-cells = <1>; + #interrupt-cells = <1>; + interrupt-controller; + pinctrl-single,register-width = <16>; + pinctrl-single,function-mask = <0xff1f>; + }; + + hecc: can@5c050000 { + compatible = "ti,am3517-hecc"; + status = "disabled"; + reg = <0x5c050000 0x80>, + <0x5c053000 0x180>, + <0x5c052000 0x200>; + reg-names = "hecc", "hecc-ram", "mbx"; + interrupts = <24>; + clocks = <&hecc_ck>; + }; + }; +}; + +/* Table Table 5-79 of the TRM shows 480ab000 is reserved */ +&usb_otg_hs { + status = "disabled"; +}; + +&iva { + status = "disabled"; +}; + +&mailbox { + status = "disabled"; +}; + +&mmu_isp { + status = "disabled"; +}; + +/include/ "am35xx-clocks.dtsi" +/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
diff --git a/arch/arm/dts/am35xx-clocks.dtsi b/arch/arm/dts/am35xx-clocks.dtsi new file mode 100644 index 0000000..00dd1f0 --- /dev/null +++ b/arch/arm/dts/am35xx-clocks.dtsi
@@ -0,0 +1,128 @@ +/* + * Device Tree Source for OMAP3 clock data + * + * Copyright (C) 2013 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +&scm_clocks { + emac_ick: emac_ick@32c { + #clock-cells = <0>; + compatible = "ti,am35xx-gate-clock"; + clocks = <&ipss_ick>; + reg = <0x032c>; + ti,bit-shift = <1>; + }; + + emac_fck: emac_fck@32c { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&rmii_ck>; + reg = <0x032c>; + ti,bit-shift = <9>; + }; + + vpfe_ick: vpfe_ick@32c { + #clock-cells = <0>; + compatible = "ti,am35xx-gate-clock"; + clocks = <&ipss_ick>; + reg = <0x032c>; + ti,bit-shift = <2>; + }; + + vpfe_fck: vpfe_fck@32c { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&pclk_ck>; + reg = <0x032c>; + ti,bit-shift = <10>; + }; + + hsotgusb_ick_am35xx: hsotgusb_ick_am35xx@32c { + #clock-cells = <0>; + compatible = "ti,am35xx-gate-clock"; + clocks = <&ipss_ick>; + reg = <0x032c>; + ti,bit-shift = <0>; + }; + + hsotgusb_fck_am35xx: hsotgusb_fck_am35xx@32c { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&sys_ck>; + reg = <0x032c>; + ti,bit-shift = <8>; + }; + + hecc_ck: hecc_ck@32c { + #clock-cells = <0>; + compatible = "ti,am35xx-gate-clock"; + clocks = <&sys_ck>; + reg = <0x032c>; + ti,bit-shift = <3>; + }; +}; +&cm_clocks { + ipss_ick: ipss_ick@a10 { + #clock-cells = <0>; + compatible = "ti,am35xx-interface-clock"; + clocks = <&core_l3_ick>; + reg = <0x0a10>; + ti,bit-shift = <4>; + }; + + rmii_ck: rmii_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <50000000>; + }; + + pclk_ck: pclk_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <27000000>; + }; + + uart4_ick_am35xx: uart4_ick_am35xx@a10 { + #clock-cells = <0>; + compatible = "ti,omap3-interface-clock"; + clocks = <&core_l4_ick>; + reg = <0x0a10>; + ti,bit-shift = <23>; + }; + + uart4_fck_am35xx: uart4_fck_am35xx@a00 { + #clock-cells = <0>; + compatible = "ti,wait-gate-clock"; + clocks = <&core_48m_fck>; + reg = <0x0a00>; + ti,bit-shift = <23>; + }; +}; + +&cm_clockdomains { + core_l3_clkdm: core_l3_clkdm { + compatible = "ti,clockdomain"; + clocks = <&sdrc_ick>, <&ipss_ick>, <&emac_ick>, <&vpfe_ick>, + <&hsotgusb_ick_am35xx>, <&hsotgusb_fck_am35xx>, + <&hecc_ck>; + }; + + core_l4_clkdm: core_l4_clkdm { + compatible = "ti,clockdomain"; + clocks = <&cpefuse_fck>, <&ts_fck>, <&usbtll_fck>, + <&usbtll_ick>, <&mmchs3_ick>, <&mmchs3_fck>, + <&mmchs2_fck>, <&mmchs1_fck>, <&i2c3_fck>, <&i2c2_fck>, + <&i2c1_fck>, <&mcspi4_fck>, <&mcspi3_fck>, + <&mcspi2_fck>, <&mcspi1_fck>, <&uart2_fck>, + <&uart1_fck>, <&hdq_fck>, <&mmchs2_ick>, <&mmchs1_ick>, + <&hdq_ick>, <&mcspi4_ick>, <&mcspi3_ick>, + <&mcspi2_ick>, <&mcspi1_ick>, <&i2c3_ick>, <&i2c2_ick>, + <&i2c1_ick>, <&uart2_ick>, <&uart1_ick>, <&gpt11_ick>, + <&gpt10_ick>, <&mcbsp5_ick>, <&mcbsp1_ick>, + <&omapctrl_ick>, <&aes2_ick>, <&sha12_ick>, + <&uart4_ick_am35xx>, <&uart4_fck_am35xx>; + }; +};
diff --git a/arch/arm/dts/am4372-generic-u-boot.dtsi b/arch/arm/dts/am4372-generic-u-boot.dtsi new file mode 100644 index 0000000..6ba5c16 --- /dev/null +++ b/arch/arm/dts/am4372-generic-u-boot.dtsi
@@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include "am4372-u-boot.dtsi" + +/{ + ocp { + u-boot,dm-pre-reloc; + }; +}; + +&i2c0 { + u-boot,dm-pre-reloc; +};
diff --git a/arch/arm/dts/am4372-generic.dts b/arch/arm/dts/am4372-generic.dts new file mode 100644 index 0000000..b8a2bb8 --- /dev/null +++ b/arch/arm/dts/am4372-generic.dts
@@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Device Tree Source for Generic AM4372 EVM + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +/dts-v1/; + +#include "am4372.dtsi" + +/ { + compatible = "ti,am4372", "ti,am43"; + model = "Texas Instruments AM4372 Generic"; + + chosen { + stdout-path = &uart0; + }; +}; + +&i2c0 { + status = "okay"; +};
diff --git a/arch/arm/dts/am4372-u-boot.dtsi b/arch/arm/dts/am4372-u-boot.dtsi new file mode 100644 index 0000000..99922ca --- /dev/null +++ b/arch/arm/dts/am4372-u-boot.dtsi
@@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +&am43xx_control_usb2phy1 { + compatible = "ti,control-phy-usb2-am437", "syscon"; +}; + +&am43xx_control_usb2phy2 { + compatible = "ti,control-phy-usb2-am437", "syscon"; +}; + +&ocp2scp0 { + compatible = "ti,am437x-ocp2scp", "ti,omap-ocp2scp", "simple-bus"; +}; + +&ocp2scp1 { + compatible = "ti,am437x-ocp2scp", "ti,omap-ocp2scp", "simple-bus"; +}; + +&dwc3_1 { + u-boot,dm-spl; +}; + +&usb1 { + u-boot,dm-spl; +}; + +&usb2_phy1 { + u-boot,dm-spl; +}; + +&am43xx_control_usb2phy1 { + u-boot,dm-spl; +}; + +&ocp2scp0 { + u-boot,dm-spl; +};
diff --git a/arch/arm/dts/am4372.dtsi b/arch/arm/dts/am4372.dtsi new file mode 100644 index 0000000..6f60a32 --- /dev/null +++ b/arch/arm/dts/am4372.dtsi
@@ -0,0 +1,1009 @@ +/* + * Device Tree Source for AM4372 SoC + * + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> + +#include "skeleton.dtsi" + +/ { + compatible = "ti,am4372", "ti,am43"; + interrupt-parent = <&wakeupgen>; + + + aliases { + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; + serial0 = &uart0; + ethernet0 = &cpsw_emac0; + ethernet1 = &cpsw_emac1; + spi0 = &qspi; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu: cpu@0 { + compatible = "arm,cortex-a9"; + device_type = "cpu"; + reg = <0>; + + clocks = <&dpll_mpu_ck>; + clock-names = "cpu"; + + clock-latency = <300000>; /* From omap-cpufreq driver */ + }; + }; + + gic: interrupt-controller@48241000 { + compatible = "arm,cortex-a9-gic"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x48241000 0x1000>, + <0x48240100 0x0100>; + interrupt-parent = <&gic>; + }; + + wakeupgen: interrupt-controller@48281000 { + compatible = "ti,omap4-wugen-mpu"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x48281000 0x1000>; + interrupt-parent = <&gic>; + }; + + l2-cache-controller@48242000 { + compatible = "arm,pl310-cache"; + reg = <0x48242000 0x1000>; + cache-unified; + cache-level = <2>; + }; + + ocp { + compatible = "ti,am4372-l3-noc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "l3_main"; + reg = <0x44000000 0x400000 + 0x44800000 0x400000>; + interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; + + l4_wkup: l4_wkup@44c00000 { + compatible = "ti,am4-l4-wkup", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x44c00000 0x287000>; + + prcm: prcm@1f0000 { + compatible = "ti,am4-prcm"; + reg = <0x1f0000 0x11000>; + + prcm_clocks: clocks { + #address-cells = <1>; + #size-cells = <0>; + }; + + prcm_clockdomains: clockdomains { + }; + }; + + scm: scm@210000 { + compatible = "ti,am4-scm", "simple-bus"; + reg = <0x210000 0x4000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x210000 0x4000>; + + am43xx_pinmux: pinmux@800 { + compatible = "ti,am437-padconf", + "pinctrl-single"; + reg = <0x800 0x31c>; + #interrupt-cells = <1>; + interrupt-controller; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + scm_conf: scm_conf@0 { + compatible = "syscon"; + reg = <0x0 0x800>; + + scm_clocks: clocks { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + scm_clockdomains: clockdomains { + }; + }; + }; + + emif: emif@4c000000 { + compatible = "ti,emif-am4372"; + reg = <0x4c000000 0x1000000>; + ti,hwmods = "emif"; + }; + + edma: edma@49000000 { + compatible = "ti,edma3"; + ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2"; + reg = <0x49000000 0x10000>, + <0x44e10f90 0x10>; + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; + #dma-cells = <1>; + }; + + uart0: serial@44e09000 { + compatible = "ti,am4372-uart","ti,omap2-uart"; + reg = <0x44e09000 0x2000>; + reg-shift = <2>; + interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart1"; + }; + + uart1: serial@48022000 { + compatible = "ti,am4372-uart","ti,omap2-uart"; + reg = <0x48022000 0x2000>; + reg-shift = <2>; + interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart2"; + status = "disabled"; + }; + + uart2: serial@48024000 { + compatible = "ti,am4372-uart","ti,omap2-uart"; + reg = <0x48024000 0x2000>; + reg-shift = <2>; + interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart3"; + status = "disabled"; + }; + + uart3: serial@481a6000 { + compatible = "ti,am4372-uart","ti,omap2-uart"; + reg = <0x481a6000 0x2000>; + reg-shift = <2>; + interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart4"; + status = "disabled"; + }; + + uart4: serial@481a8000 { + compatible = "ti,am4372-uart","ti,omap2-uart"; + reg = <0x481a8000 0x2000>; + reg-shift = <2>; + interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart5"; + status = "disabled"; + }; + + uart5: serial@481aa000 { + compatible = "ti,am4372-uart","ti,omap2-uart"; + reg = <0x481aa000 0x2000>; + reg-shift = <2>; + interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart6"; + status = "disabled"; + }; + + mailbox: mailbox@480C8000 { + compatible = "ti,omap4-mailbox"; + reg = <0x480C8000 0x200>; + interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mailbox"; + #mbox-cells = <1>; + ti,mbox-num-users = <4>; + ti,mbox-num-fifos = <8>; + mbox_wkupm3: wkup_m3 { + ti,mbox-tx = <0 0 0>; + ti,mbox-rx = <0 0 3>; + }; + }; + + timer1: timer@44e31000 { + compatible = "ti,am4372-timer-1ms","ti,am335x-timer-1ms"; + reg = <0x44e31000 0x400>; + interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; + ti,timer-alwon; + ti,hwmods = "timer1"; + }; + + timer2: timer@48040000 { + compatible = "ti,am4372-timer","ti,am335x-timer"; + reg = <0x48040000 0x400>; + interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer2"; + }; + + timer3: timer@48042000 { + compatible = "ti,am4372-timer","ti,am335x-timer"; + reg = <0x48042000 0x400>; + interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer3"; + status = "disabled"; + }; + + timer4: timer@48044000 { + compatible = "ti,am4372-timer","ti,am335x-timer"; + reg = <0x48044000 0x400>; + interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; + ti,timer-pwm; + ti,hwmods = "timer4"; + status = "disabled"; + }; + + timer5: timer@48046000 { + compatible = "ti,am4372-timer","ti,am335x-timer"; + reg = <0x48046000 0x400>; + interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>; + ti,timer-pwm; + ti,hwmods = "timer5"; + status = "disabled"; + }; + + timer6: timer@48048000 { + compatible = "ti,am4372-timer","ti,am335x-timer"; + reg = <0x48048000 0x400>; + interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>; + ti,timer-pwm; + ti,hwmods = "timer6"; + status = "disabled"; + }; + + timer7: timer@4804a000 { + compatible = "ti,am4372-timer","ti,am335x-timer"; + reg = <0x4804a000 0x400>; + interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>; + ti,timer-pwm; + ti,hwmods = "timer7"; + status = "disabled"; + }; + + timer8: timer@481c1000 { + compatible = "ti,am4372-timer","ti,am335x-timer"; + reg = <0x481c1000 0x400>; + interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer8"; + status = "disabled"; + }; + + timer9: timer@4833d000 { + compatible = "ti,am4372-timer","ti,am335x-timer"; + reg = <0x4833d000 0x400>; + interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer9"; + status = "disabled"; + }; + + timer10: timer@4833f000 { + compatible = "ti,am4372-timer","ti,am335x-timer"; + reg = <0x4833f000 0x400>; + interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer10"; + status = "disabled"; + }; + + timer11: timer@48341000 { + compatible = "ti,am4372-timer","ti,am335x-timer"; + reg = <0x48341000 0x400>; + interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer11"; + status = "disabled"; + }; + + counter32k: counter@44e86000 { + compatible = "ti,am4372-counter32k","ti,omap-counter32k"; + reg = <0x44e86000 0x40>; + ti,hwmods = "counter_32k"; + }; + + rtc: rtc@44e3e000 { + compatible = "ti,am4372-rtc","ti,da830-rtc"; + reg = <0x44e3e000 0x1000>; + interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "rtc"; + status = "disabled"; + }; + + wdt: wdt@44e35000 { + compatible = "ti,am4372-wdt","ti,omap3-wdt"; + reg = <0x44e35000 0x1000>; + interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "wd_timer2"; + }; + + gpio0: gpio@44e07000 { + compatible = "ti,am4372-gpio","ti,omap4-gpio"; + reg = <0x44e07000 0x1000>; + interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + ti,hwmods = "gpio1"; + status = "disabled"; + }; + + gpio1: gpio@4804c000 { + compatible = "ti,am4372-gpio","ti,omap4-gpio"; + reg = <0x4804c000 0x1000>; + interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + ti,hwmods = "gpio2"; + status = "disabled"; + }; + + gpio2: gpio@481ac000 { + compatible = "ti,am4372-gpio","ti,omap4-gpio"; + reg = <0x481ac000 0x1000>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + ti,hwmods = "gpio3"; + status = "disabled"; + }; + + gpio3: gpio@481ae000 { + compatible = "ti,am4372-gpio","ti,omap4-gpio"; + reg = <0x481ae000 0x1000>; + interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + ti,hwmods = "gpio4"; + status = "disabled"; + }; + + gpio4: gpio@48320000 { + compatible = "ti,am4372-gpio","ti,omap4-gpio"; + reg = <0x48320000 0x1000>; + interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + ti,hwmods = "gpio5"; + status = "disabled"; + }; + + gpio5: gpio@48322000 { + compatible = "ti,am4372-gpio","ti,omap4-gpio"; + reg = <0x48322000 0x1000>; + interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + ti,hwmods = "gpio6"; + status = "disabled"; + }; + + hwspinlock: spinlock@480ca000 { + compatible = "ti,omap4-hwspinlock"; + reg = <0x480ca000 0x1000>; + ti,hwmods = "spinlock"; + #hwlock-cells = <1>; + }; + + i2c0: i2c@44e0b000 { + compatible = "ti,am4372-i2c","ti,omap4-i2c"; + reg = <0x44e0b000 0x1000>; + interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "i2c1"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@4802a000 { + compatible = "ti,am4372-i2c","ti,omap4-i2c"; + reg = <0x4802a000 0x1000>; + interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "i2c2"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@4819c000 { + compatible = "ti,am4372-i2c","ti,omap4-i2c"; + reg = <0x4819c000 0x1000>; + interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "i2c3"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi0: spi@48030000 { + compatible = "ti,am4372-mcspi","ti,omap4-mcspi"; + reg = <0x48030000 0x400>; + interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "spi0"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + mmc1: mmc@48060000 { + compatible = "ti,omap4-hsmmc"; + reg = <0x48060000 0x1000>; + ti,hwmods = "mmc1"; + ti,dual-volt; + ti,needs-special-reset; + dmas = <&edma 24 + &edma 25>; + dma-names = "tx", "rx"; + interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + mmc2: mmc@481d8000 { + compatible = "ti,omap4-hsmmc"; + reg = <0x481d8000 0x1000>; + ti,hwmods = "mmc2"; + ti,needs-special-reset; + dmas = <&edma 2 + &edma 3>; + dma-names = "tx", "rx"; + interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + mmc3: mmc@47810000 { + compatible = "ti,omap4-hsmmc"; + reg = <0x47810000 0x1000>; + ti,hwmods = "mmc3"; + ti,needs-special-reset; + interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + spi1: spi@481a0000 { + compatible = "ti,am4372-mcspi","ti,omap4-mcspi"; + reg = <0x481a0000 0x400>; + interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "spi1"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi2: spi@481a2000 { + compatible = "ti,am4372-mcspi","ti,omap4-mcspi"; + reg = <0x481a2000 0x400>; + interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "spi2"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi3: spi@481a4000 { + compatible = "ti,am4372-mcspi","ti,omap4-mcspi"; + reg = <0x481a4000 0x400>; + interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "spi3"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi4: spi@48345000 { + compatible = "ti,am4372-mcspi","ti,omap4-mcspi"; + reg = <0x48345000 0x400>; + interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "spi4"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + mac: ethernet@4a100000 { + compatible = "ti,am4372-cpsw","ti,cpsw"; + reg = <0x4a100000 0x800 + 0x4a101200 0x100>; + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <1>; + ti,hwmods = "cpgmac0"; + clocks = <&cpsw_125mhz_gclk>, <&cpsw_cpts_rft_clk>; + clock-names = "fck", "cpts"; + status = "disabled"; + cpdma_channels = <8>; + ale_entries = <1024>; + bd_ram_size = <0x2000>; + no_bd_ram = <0>; + rx_descs = <64>; + mac_control = <0x20>; + slaves = <2>; + active_slave = <0>; + cpts_clock_mult = <0x80000000>; + cpts_clock_shift = <29>; + syscon = <&scm_conf>; + ranges; + + davinci_mdio: mdio@4a101000 { + compatible = "ti,am4372-mdio","ti,davinci_mdio"; + reg = <0x4a101000 0x100>; + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "davinci_mdio"; + bus_freq = <1000000>; + status = "disabled"; + }; + + cpsw_emac0: slave@4a100200 { + /* Filled in by U-Boot */ + mac-address = [ 00 00 00 00 00 00 ]; + }; + + cpsw_emac1: slave@4a100300 { + /* Filled in by U-Boot */ + mac-address = [ 00 00 00 00 00 00 ]; + }; + + phy_sel: cpsw-phy-sel@44e10650 { + compatible = "ti,am43xx-cpsw-phy-sel"; + reg= <0x44e10650 0x4>; + reg-names = "gmii-sel"; + }; + }; + + epwmss0: epwmss@48300000 { + compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; + reg = <0x48300000 0x10>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "epwmss0"; + status = "disabled"; + + ecap0: ecap@48300100 { + compatible = "ti,am4372-ecap","ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x48300100 0x80>; + ti,hwmods = "ecap0"; + status = "disabled"; + }; + + ehrpwm0: ehrpwm@48300200 { + compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x48300200 0x80>; + ti,hwmods = "ehrpwm0"; + status = "disabled"; + }; + }; + + epwmss1: epwmss@48302000 { + compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; + reg = <0x48302000 0x10>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "epwmss1"; + status = "disabled"; + + ecap1: ecap@48302100 { + compatible = "ti,am4372-ecap","ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x48302100 0x80>; + ti,hwmods = "ecap1"; + status = "disabled"; + }; + + ehrpwm1: ehrpwm@48302200 { + compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x48302200 0x80>; + ti,hwmods = "ehrpwm1"; + status = "disabled"; + }; + }; + + epwmss2: epwmss@48304000 { + compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; + reg = <0x48304000 0x10>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "epwmss2"; + status = "disabled"; + + ecap2: ecap@48304100 { + compatible = "ti,am4372-ecap","ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x48304100 0x80>; + ti,hwmods = "ecap2"; + status = "disabled"; + }; + + ehrpwm2: ehrpwm@48304200 { + compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x48304200 0x80>; + ti,hwmods = "ehrpwm2"; + status = "disabled"; + }; + }; + + epwmss3: epwmss@48306000 { + compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; + reg = <0x48306000 0x10>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "epwmss3"; + status = "disabled"; + + ehrpwm3: ehrpwm@48306200 { + compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x48306200 0x80>; + ti,hwmods = "ehrpwm3"; + status = "disabled"; + }; + }; + + epwmss4: epwmss@48308000 { + compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; + reg = <0x48308000 0x10>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "epwmss4"; + status = "disabled"; + + ehrpwm4: ehrpwm@48308200 { + compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x48308200 0x80>; + ti,hwmods = "ehrpwm4"; + status = "disabled"; + }; + }; + + epwmss5: epwmss@4830a000 { + compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; + reg = <0x4830a000 0x10>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "epwmss5"; + status = "disabled"; + + ehrpwm5: ehrpwm@4830a200 { + compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x4830a200 0x80>; + ti,hwmods = "ehrpwm5"; + status = "disabled"; + }; + }; + + tscadc: tscadc@44e0d000 { + compatible = "ti,am3359-tscadc"; + reg = <0x44e0d000 0x1000>; + ti,hwmods = "adc_tsc"; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&adc_tsc_fck>; + clock-names = "fck"; + status = "disabled"; + + tsc { + compatible = "ti,am3359-tsc"; + }; + + adc { + #io-channel-cells = <1>; + compatible = "ti,am3359-adc"; + }; + + }; + + sham: sham@53100000 { + compatible = "ti,omap5-sham"; + ti,hwmods = "sham"; + reg = <0x53100000 0x300>; + dmas = <&edma 36>; + dma-names = "rx"; + interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; + }; + + aes: aes@53501000 { + compatible = "ti,omap4-aes"; + ti,hwmods = "aes"; + reg = <0x53501000 0xa0>; + interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&edma 6 + &edma 5>; + dma-names = "tx", "rx"; + }; + + des: des@53701000 { + compatible = "ti,omap4-des"; + ti,hwmods = "des"; + reg = <0x53701000 0xa0>; + interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&edma 34 + &edma 33>; + dma-names = "tx", "rx"; + }; + + mcasp0: mcasp@48038000 { + compatible = "ti,am33xx-mcasp-audio"; + ti,hwmods = "mcasp0"; + reg = <0x48038000 0x2000>, + <0x46000000 0x400000>; + reg-names = "mpu", "dat"; + interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tx", "rx"; + status = "disabled"; + dmas = <&edma 8>, + <&edma 9>; + dma-names = "tx", "rx"; + }; + + mcasp1: mcasp@4803C000 { + compatible = "ti,am33xx-mcasp-audio"; + ti,hwmods = "mcasp1"; + reg = <0x4803C000 0x2000>, + <0x46400000 0x400000>; + reg-names = "mpu", "dat"; + interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "tx", "rx"; + status = "disabled"; + dmas = <&edma 10>, + <&edma 11>; + dma-names = "tx", "rx"; + }; + + elm: elm@48080000 { + compatible = "ti,am3352-elm"; + reg = <0x48080000 0x2000>; + interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "elm"; + clocks = <&l4ls_gclk>; + clock-names = "fck"; + status = "disabled"; + }; + + gpmc: gpmc@50000000 { + compatible = "ti,am3352-gpmc"; + ti,hwmods = "gpmc"; + clocks = <&l3s_gclk>; + clock-names = "fck"; + reg = <0x50000000 0x2000>; + interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; + gpmc,num-cs = <7>; + gpmc,num-waitpins = <2>; + #address-cells = <2>; + #size-cells = <1>; + interrupt-controller; + #interrupt-cells = <2>; + status = "disabled"; + }; + + am43xx_control_usb2phy1: control-phy@44e10620 { + compatible = "ti,control-phy-usb2-am437"; + reg = <0x44e10620 0x4>; + reg-names = "power"; + }; + + am43xx_control_usb2phy2: control-phy@0x44e10628 { + compatible = "ti,control-phy-usb2-am437"; + reg = <0x44e10628 0x4>; + reg-names = "power"; + }; + + ocp2scp0: ocp2scp@483a8000 { + compatible = "ti,am437x-ocp2scp", "ti,omap-ocp2scp"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "ocp2scp0"; + + usb2_phy1: phy@483a8000 { + compatible = "ti,am437x-usb2"; + reg = <0x483a8000 0x8000>; + ctrl-module = <&am43xx_control_usb2phy1>; + clocks = <&usb_phy0_always_on_clk32k>, + <&usb_otg_ss0_refclk960m>; + clock-names = "wkupclk", "refclk"; + #phy-cells = <0>; + status = "disabled"; + }; + }; + + ocp2scp1: ocp2scp@483e8000 { + compatible = "ti,am437x-ocp2scp", "ti,omap-ocp2scp"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "ocp2scp1"; + + usb2_phy2: phy@483e8000 { + compatible = "ti,am437x-usb2"; + reg = <0x483e8000 0x8000>; + ctrl-module = <&am43xx_control_usb2phy2>; + clocks = <&usb_phy1_always_on_clk32k>, + <&usb_otg_ss1_refclk960m>; + clock-names = "wkupclk", "refclk"; + #phy-cells = <0>; + status = "disabled"; + }; + }; + + dwc3_1: omap_dwc3@48380000 { + compatible = "ti,am437x-dwc3"; + ti,hwmods = "usb_otg_ss0"; + reg = <0x48380000 0x10000>; + interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <1>; + utmi-mode = <1>; + ranges; + + usb1: usb@48390000 { + compatible = "synopsys,dwc3"; + reg = <0x48390000 0x10000>; + interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; + phys = <&usb2_phy1>; + phy-names = "usb2-phy"; + maximum-speed = "high-speed"; + dr_mode = "otg"; + status = "disabled"; + snps,dis_u3_susphy_quirk; + snps,dis_u2_susphy_quirk; + }; + }; + + dwc3_2: omap_dwc3@483c0000 { + compatible = "ti,am437x-dwc3"; + ti,hwmods = "usb_otg_ss1"; + reg = <0x483c0000 0x10000>; + interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <1>; + utmi-mode = <1>; + ranges; + + usb2: usb@483d0000 { + compatible = "synopsys,dwc3"; + reg = <0x483d0000 0x10000>; + interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; + phys = <&usb2_phy2>; + phy-names = "usb2-phy"; + maximum-speed = "high-speed"; + dr_mode = "otg"; + status = "disabled"; + snps,dis_u3_susphy_quirk; + snps,dis_u2_susphy_quirk; + }; + }; + + qspi: qspi@47900000 { + compatible = "ti,am4372-qspi"; + reg = <0x47900000 0x100>, + <0x30000000 0x4000000>; + reg-names = "qspi_base", "qspi_mmap"; + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "qspi"; + interrupts = <0 138 0x4>; + num-cs = <4>; + status = "disabled"; + }; + + hdq: hdq@48347000 { + compatible = "ti,am4372-hdq"; + reg = <0x48347000 0x1000>; + interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&func_12m_clk>; + clock-names = "fck"; + ti,hwmods = "hdq1w"; + status = "disabled"; + }; + + dss: dss@4832a000 { + compatible = "ti,omap3-dss"; + reg = <0x4832a000 0x200>; + status = "disabled"; + ti,hwmods = "dss_core"; + clocks = <&disp_clk>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + dispc: dispc@4832a400 { + compatible = "ti,omap3-dispc"; + reg = <0x4832a400 0x400>; + interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "dss_dispc"; + clocks = <&disp_clk>; + clock-names = "fck"; + }; + + rfbi: rfbi@4832a800 { + compatible = "ti,omap3-rfbi"; + reg = <0x4832a800 0x100>; + ti,hwmods = "dss_rfbi"; + clocks = <&disp_clk>; + clock-names = "fck"; + status = "disabled"; + }; + }; + + ocmcram: ocmcram@40300000 { + compatible = "mmio-sram"; + reg = <0x40300000 0x40000>; /* 256k */ + }; + + dcan0: can@481cc000 { + compatible = "ti,am4372-d_can", "ti,am3352-d_can"; + ti,hwmods = "d_can0"; + clocks = <&dcan0_fck>; + clock-names = "fck"; + reg = <0x481cc000 0x2000>; + syscon-raminit = <&scm_conf 0x644 0>; + interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + dcan1: can@481d0000 { + compatible = "ti,am4372-d_can", "ti,am3352-d_can"; + ti,hwmods = "d_can1"; + clocks = <&dcan1_fck>; + clock-names = "fck"; + reg = <0x481d0000 0x2000>; + syscon-raminit = <&scm_conf 0x644 1>; + interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + vpfe0: vpfe@48326000 { + compatible = "ti,am437x-vpfe"; + reg = <0x48326000 0x2000>; + interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "vpfe0"; + status = "disabled"; + }; + + vpfe1: vpfe@48328000 { + compatible = "ti,am437x-vpfe"; + reg = <0x48328000 0x2000>; + interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "vpfe1"; + status = "disabled"; + }; + }; +}; + +/include/ "am43xx-clocks.dtsi"
diff --git a/arch/arm/dts/am437x-gp-evm-u-boot.dtsi b/arch/arm/dts/am437x-gp-evm-u-boot.dtsi new file mode 100644 index 0000000..d950d32 --- /dev/null +++ b/arch/arm/dts/am437x-gp-evm-u-boot.dtsi
@@ -0,0 +1,44 @@ +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + * Based on "dra7.dtsi" + */ + +#include "am4372-u-boot.dtsi" + +/{ + ocp { + u-boot,dm-spl; + }; +}; + +&uart0 { + u-boot,dm-spl; +}; + +&mmc1 { + u-boot,dm-spl; +}; + +&mac { + u-boot,dm-spl; +}; + +&davinci_mdio { + u-boot,dm-spl; +}; + +&cpsw_emac0 { + u-boot,dm-spl; +}; + +&phy_sel { + u-boot,dm-spl; +}; + +&i2c0 { + u-boot,dm-spl; +};
diff --git a/arch/arm/dts/am437x-gp-evm.dts b/arch/arm/dts/am437x-gp-evm.dts new file mode 100644 index 0000000..142bfc5 --- /dev/null +++ b/arch/arm/dts/am437x-gp-evm.dts
@@ -0,0 +1,798 @@ +/* + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +/* AM437x GP EVM */ + +/dts-v1/; + +#include "am4372.dtsi" +#include <dt-bindings/pinctrl/am43xx.h> +#include <dt-bindings/pwm/pwm.h> +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "TI AM437x GP EVM"; + compatible = "ti,am437x-gp-evm","ti,am4372","ti,am43"; + + aliases { + display0 = &lcd0; + serial3 = &uart3; + }; + + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; + + vmmcsd_fixed: fixedregulator-sd { + compatible = "regulator-fixed"; + regulator-name = "vmmcsd_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + }; + + vtt_fixed: fixedregulator-vtt { + compatible = "regulator-fixed"; + regulator-name = "vtt_fixed"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + enable-active-high; + gpio = <&gpio5 7 GPIO_ACTIVE_HIGH>; + }; + + vmmcwl_fixed: fixedregulator-mmcwl { + compatible = "regulator-fixed"; + regulator-name = "vmmcwl_fixed"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&gpio1 20 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + backlight { + compatible = "pwm-backlight"; + pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 51 53 56 62 75 101 152 255>; + default-brightness-level = <8>; + }; + + matrix_keypad: matrix_keypad@0 { + compatible = "gpio-matrix-keypad"; + debounce-delay-ms = <5>; + col-scan-delay-us = <2>; + + row-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH /* Bank3, pin21 */ + &gpio4 3 GPIO_ACTIVE_HIGH /* Bank4, pin3 */ + &gpio4 2 GPIO_ACTIVE_HIGH>; /* Bank4, pin2 */ + + col-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH /* Bank3, pin19 */ + &gpio3 20 GPIO_ACTIVE_HIGH>; /* Bank3, pin20 */ + + linux,keymap = <0x00000201 /* P1 */ + 0x00010202 /* P2 */ + 0x01000067 /* UP */ + 0x0101006a /* RIGHT */ + 0x02000069 /* LEFT */ + 0x0201006c>; /* DOWN */ + }; + + lcd0: display { + compatible = "osddisplays,osd057T0559-34ts", "panel-dpi"; + label = "lcd"; + + pinctrl-names = "default"; + pinctrl-0 = <&lcd_pins>; + + /* + * SelLCDorHDMI, LOW to select HDMI. This is not really the + * panel's enable GPIO, but we don't have HDMI driver support nor + * support to switch between two displays, so using this gpio as + * panel's enable should be safe. + */ + enable-gpios = <&gpio5 8 GPIO_ACTIVE_HIGH>; + + panel-timing { + clock-frequency = <33000000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <210>; + hback-porch = <16>; + hsync-len = <30>; + vback-porch = <10>; + vfront-porch = <22>; + vsync-len = <13>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + port { + lcd_in: endpoint { + remote-endpoint = <&dpi_out>; + }; + }; + }; + + /* fixed 12MHz oscillator */ + refclk: oscillator { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <12000000>; + }; + +}; + +&am43xx_pinmux { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&wlan_pins_default>; + pinctrl-1 = <&wlan_pins_sleep>; + + i2c0_pins: i2c0_pins { + pinctrl-single,pins = < + 0x188 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + 0x18c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + i2c1_pins: i2c1_pins { + pinctrl-single,pins = < + 0x15c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_cs0.i2c1_scl */ + 0x158 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_d1.i2c1_sda */ + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ + >; + }; + + ecap0_pins: backlight_pins { + pinctrl-single,pins = < + 0x164 MUX_MODE0 /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */ + >; + }; + + pixcir_ts_pins: pixcir_ts_pins { + pinctrl-single,pins = < + 0x264 (PIN_INPUT_PULLUP | MUX_MODE7) /* spi2_d0.gpio3_22 */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_txen */ + 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rxctl */ + 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_txd3 */ + 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_txd2 */ + 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_txd1 */ + 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_txd0 */ + 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rmii1_tclk */ + 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rmii1_rclk */ + 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rxd3 */ + 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rxd2 */ + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rxd1 */ + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rxd0 */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + nand_flash_x8: nand_flash_x8 { + pinctrl-single,pins = < + 0x26c(PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* spi2_cs0.gpio/eMMCorNANDsel */ + 0x0 (PIN_INPUT | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ + 0x4 (PIN_INPUT | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ + 0x8 (PIN_INPUT | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */ + 0xc (PIN_INPUT | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */ + 0x10 (PIN_INPUT | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */ + 0x14 (PIN_INPUT | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */ + 0x18 (PIN_INPUT | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */ + 0x1c (PIN_INPUT | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */ + 0x70 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */ + 0x74 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpmc_wpn */ + 0x7c (PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */ + 0x90 (PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */ + 0x94 (PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */ + 0x98 (PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */ + 0x9c (PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */ + >; + }; + + dss_pins: dss_pins { + pinctrl-single,pins = < + 0x020 (PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 8 -> DSS DATA 23 */ + 0x024 (PIN_OUTPUT_PULLUP | MUX_MODE1) + 0x028 (PIN_OUTPUT_PULLUP | MUX_MODE1) + 0x02c (PIN_OUTPUT_PULLUP | MUX_MODE1) + 0x030 (PIN_OUTPUT_PULLUP | MUX_MODE1) + 0x034 (PIN_OUTPUT_PULLUP | MUX_MODE1) + 0x038 (PIN_OUTPUT_PULLUP | MUX_MODE1) + 0x03c (PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 15 -> DSS DATA 16 */ + 0x0a0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 0 */ + 0x0a4 (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0a8 (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0ac (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0b0 (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0b4 (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0b8 (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0bc (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0c0 (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0c4 (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0c8 (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0cc (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0d0 (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0d4 (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0d8 (PIN_OUTPUT_PULLUP | MUX_MODE0) + 0x0dc (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 15 */ + 0x0e0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS VSYNC */ + 0x0e4 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS HSYNC */ + 0x0e8 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS PCLK */ + 0x0ec (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS AC BIAS EN */ + + >; + }; + + lcd_pins: lcd_pins { + pinctrl-single,pins = < + /* GPIO 5_8 to select LCD / HDMI */ + 0x238 (PIN_OUTPUT_PULLUP | MUX_MODE7) + >; + }; + + dcan0_default: dcan0_default_pins { + pinctrl-single,pins = < + 0x178 (PIN_OUTPUT | MUX_MODE2) /* uart1_ctsn.d_can0_tx */ + 0x17c (PIN_INPUT_PULLUP | MUX_MODE2) /* uart1_rtsn.d_can0_rx */ + >; + }; + + dcan1_default: dcan1_default_pins { + pinctrl-single,pins = < + 0x180 (PIN_OUTPUT | MUX_MODE2) /* uart1_rxd.d_can1_tx */ + 0x184 (PIN_INPUT_PULLUP | MUX_MODE2) /* uart1_txd.d_can1_rx */ + >; + }; + + vpfe0_pins_default: vpfe0_pins_default { + pinctrl-single,pins = < + 0x1B0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_hd mode 0*/ + 0x1B4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_vd mode 0*/ + 0x1C0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_pclk mode 0*/ + 0x1C4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data8 mode 0*/ + 0x1C8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data9 mode 0*/ + 0x208 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data0 mode 0*/ + 0x20C (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data1 mode 0*/ + 0x210 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data2 mode 0*/ + 0x214 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data3 mode 0*/ + 0x218 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data4 mode 0*/ + 0x21C (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data5 mode 0*/ + 0x220 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data6 mode 0*/ + 0x224 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data7 mode 0*/ + >; + }; + + vpfe0_pins_sleep: vpfe0_pins_sleep { + pinctrl-single,pins = < + 0x1B0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_hd mode 0*/ + 0x1B4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_vd mode 0*/ + 0x1C0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_pclk mode 0*/ + 0x1C4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data8 mode 0*/ + 0x1C8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data9 mode 0*/ + 0x208 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data0 mode 0*/ + 0x20C (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data1 mode 0*/ + 0x210 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data2 mode 0*/ + 0x214 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data3 mode 0*/ + 0x218 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data4 mode 0*/ + 0x21C (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data5 mode 0*/ + 0x220 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data6 mode 0*/ + 0x224 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data7 mode 0*/ + >; + }; + + vpfe1_pins_default: vpfe1_pins_default { + pinctrl-single,pins = < + 0x1CC (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data9 mode 0*/ + 0x1D0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data8 mode 0*/ + 0x1D4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_hd mode 0*/ + 0x1D8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_vd mode 0*/ + 0x1DC (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_pclk mode 0*/ + 0x1E8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data0 mode 0*/ + 0x1EC (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data1 mode 0*/ + 0x1F0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data2 mode 0*/ + 0x1F4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data3 mode 0*/ + 0x1F8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data4 mode 0*/ + 0x1FC (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data5 mode 0*/ + 0x200 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data6 mode 0*/ + 0x204 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data7 mode 0*/ + >; + }; + + vpfe1_pins_sleep: vpfe1_pins_sleep { + pinctrl-single,pins = < + 0x1CC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data9 mode 0*/ + 0x1D0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data8 mode 0*/ + 0x1D4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_hd mode 0*/ + 0x1D8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_vd mode 0*/ + 0x1DC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_pclk mode 0*/ + 0x1E8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data0 mode 0*/ + 0x1EC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data1 mode 0*/ + 0x1F0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data2 mode 0*/ + 0x1F4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data3 mode 0*/ + 0x1F8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data4 mode 0*/ + 0x1FC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data5 mode 0*/ + 0x200 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data6 mode 0*/ + 0x204 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data7 mode 0*/ + >; + }; + + mmc3_pins_default: pinmux_mmc3_pins_default { + pinctrl-single,pins = < + 0x8c (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_clk.mmc2_clk */ + 0x88 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_csn3.mmc2_cmd */ + 0x44 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a1.mmc2_dat0 */ + 0x48 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a2.mmc2_dat1 */ + 0x4c (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a3.mmc2_dat2 */ + 0x78 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_be1n.mmc2_dat3 */ + >; + }; + + mmc3_pins_sleep: pinmux_mmc3_pins_sleep { + pinctrl-single,pins = < + 0x8c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_clk.mmc2_clk */ + 0x88 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn3.mmc2_cmd */ + 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a1.mmc2_dat0 */ + 0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a2.mmc2_dat1 */ + 0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a3.mmc2_dat2 */ + 0x78 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_be1n.mmc2_dat3 */ + >; + }; + + wlan_pins_default: pinmux_wlan_pins_default { + pinctrl-single,pins = < + 0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a4.gpio1_20 WL_EN */ + 0x5c (PIN_INPUT | WAKEUP_ENABLE | MUX_MODE7) /* gpmc_a7.gpio1_23 WL_IRQ*/ + 0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a0.gpio1_16 BT_EN*/ + >; + }; + + wlan_pins_sleep: pinmux_wlan_pins_sleep { + pinctrl-single,pins = < + 0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a4.gpio1_20 WL_EN */ + 0x5c (PIN_INPUT | WAKEUP_ENABLE | MUX_MODE7) /* gpmc_a7.gpio1_23 WL_IRQ*/ + 0x40 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a0.gpio1_16 BT_EN*/ + >; + }; + + uart3_pins: uart3_pins { + pinctrl-single,pins = < + 0x228 (PIN_INPUT | MUX_MODE0) /* uart3_rxd.uart3_rxd */ + 0x22c (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart3_txd.uart3_txd */ + 0x230 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart3_ctsn.uart3_ctsn */ + 0x234 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart3_rtsn.uart3_rtsn */ + >; + }; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <100000>; + + tps65218: tps65218@24 { + reg = <0x24>; + compatible = "ti,tps65218"; + interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */ + interrupt-controller; + #interrupt-cells = <2>; + + dcdc1: regulator-dcdc1 { + compatible = "ti,tps65218-dcdc1"; + regulator-name = "vdd_core"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <1144000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc2: regulator-dcdc2 { + compatible = "ti,tps65218-dcdc2"; + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <1378000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc3: regulator-dcdc3 { + compatible = "ti,tps65218-dcdc3"; + regulator-name = "vdcdc3"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + }; + dcdc5: regulator-dcdc5 { + compatible = "ti,tps65218-dcdc5"; + regulator-name = "v1_0bat"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + + dcdc6: regulator-dcdc6 { + compatible = "ti,tps65218-dcdc6"; + regulator-name = "v1_8bat"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo1: regulator-ldo1 { + compatible = "ti,tps65218-ldo1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + }; + + ov2659@30 { + compatible = "ovti,ov2659"; + reg = <0x30>; + + clocks = <&refclk 0>; + clock-names = "xvclk"; + + port { + ov2659_0: endpoint { + remote-endpoint = <&vpfe1_ep>; + link-frequencies = /bits/ 64 <70000000>; + }; + }; + }; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + pixcir_ts@5c { + compatible = "pixcir,pixcir_tangoc"; + pinctrl-names = "default"; + pinctrl-0 = <&pixcir_ts_pins>; + reg = <0x5c>; + interrupt-parent = <&gpio3>; + interrupts = <22 0>; + + attb-gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>; + + touchscreen-size-x = <1024>; + touchscreen-size-y = <600>; + }; + + ov2659@30 { + compatible = "ovti,ov2659"; + reg = <0x30>; + + clocks = <&refclk 0>; + clock-names = "xvclk"; + + port { + ov2659_1: endpoint { + remote-endpoint = <&vpfe0_ep>; + link-frequencies = /bits/ 64 <70000000>; + }; + }; + }; +}; + +&epwmss0 { + status = "okay"; +}; + +&tscadc { + status = "okay"; + + adc { + ti,adc-channels = <0 1 2 3 4 5 6 7>; + }; +}; + +&ecap0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ecap0_pins>; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; + +&gpio4 { + status = "okay"; +}; + +&gpio5 { + status = "okay"; + ti,no-reset-on-init; +}; + +&mmc1 { + status = "okay"; + vmmc-supply = <&vmmcsd_fixed>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; +}; + +&mmc3 { + /* disable MMC3 as SDIO is not supported in U-Boot */ + status = "disabled"; + /* these are on the crossbar and are outlined in the + xbar-event-map element */ + dmas = <&edma 30 + &edma 31>; + dma-names = "tx", "rx"; + vmmc-supply = <&vmmcwl_fixed>; + bus-width = <4>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&mmc3_pins_default>; + pinctrl-1 = <&mmc3_pins_sleep>; + cap-power-off-card; + keep-power-in-suspend; + ti,non-removable; + + #address-cells = <1>; + #size-cells = <0>; + wlcore: wlcore@0 { + compatible = "ti,wl1835"; + reg = <2>; + interrupt-parent = <&gpio1>; + interrupts = <23 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&edma { + ti,edma-xbar-event-map = /bits/ 16 <1 30 + 2 31>; +}; + +&uart3 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; +}; + +&usb2_phy1 { + status = "okay"; +}; + +&usb1 { + dr_mode = "peripheral"; + status = "okay"; +}; + +&usb2_phy2 { + status = "okay"; +}; + +&usb2 { + dr_mode = "host"; + status = "okay"; +}; + +&mac { + slaves = <1>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii"; +}; + +&elm { + status = "okay"; +}; + +&gpmc { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&nand_flash_x8>; + ranges = <0 0 0 0x01000000>; /* minimum GPMC partition = 16MB */ + nand@0,0 { + reg = <0 0 4>; /* device IO registers */ + ti,nand-ecc-opt = "bch16"; + ti,elm-id = <&elm>; + nand-bus-width = <8>; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <40>; + gpmc,cs-wr-off-ns = <40>; + gpmc,adv-on-ns = <0>; + gpmc,adv-rd-off-ns = <25>; + gpmc,adv-wr-off-ns = <25>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <20>; + gpmc,oe-on-ns = <3>; + gpmc,oe-off-ns = <30>; + gpmc,access-ns = <30>; + gpmc,rd-cycle-ns = <40>; + gpmc,wr-cycle-ns = <40>; + gpmc,wait-pin = <0>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wait-monitoring-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + /* MTD partition table */ + /* All SPL-* partitions are sized to minimal length + * which can be independently programmable. For + * NAND flash this is equal to size of erase-block */ + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + label = "NAND.SPL"; + reg = <0x00000000 0x00040000>; + }; + partition@1 { + label = "NAND.SPL.backup1"; + reg = <0x00040000 0x00040000>; + }; + partition@2 { + label = "NAND.SPL.backup2"; + reg = <0x00080000 0x00040000>; + }; + partition@3 { + label = "NAND.SPL.backup3"; + reg = <0x000c0000 0x00040000>; + }; + partition@4 { + label = "NAND.u-boot-spl-os"; + reg = <0x00100000 0x00080000>; + }; + partition@5 { + label = "NAND.u-boot"; + reg = <0x00180000 0x00100000>; + }; + partition@6 { + label = "NAND.u-boot-env"; + reg = <0x00280000 0x00040000>; + }; + partition@7 { + label = "NAND.u-boot-env.backup1"; + reg = <0x002c0000 0x00040000>; + }; + partition@8 { + label = "NAND.kernel"; + reg = <0x00300000 0x00700000>; + }; + partition@9 { + label = "NAND.file-system"; + reg = <0x00a00000 0x1f600000>; + }; + }; +}; + +&dss { + status = "ok"; + + pinctrl-names = "default"; + pinctrl-0 = <&dss_pins>; + + port { + dpi_out: endpoint@0 { + remote-endpoint = <&lcd_in>; + data-lines = <24>; + }; + }; +}; + +&dcan0 { + pinctrl-names = "default"; + pinctrl-0 = <&dcan0_default>; + status = "okay"; +}; + +&dcan1 { + pinctrl-names = "default"; + pinctrl-0 = <&dcan1_default>; + status = "okay"; +}; + +&vpfe0 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&vpfe0_pins_default>; + pinctrl-1 = <&vpfe0_pins_sleep>; + + port { + vpfe0_ep: endpoint { + remote-endpoint = <&ov2659_1>; + ti,am437x-vpfe-interface = <0>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; +}; + +&vpfe1 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&vpfe1_pins_default>; + pinctrl-1 = <&vpfe1_pins_sleep>; + + port { + vpfe1_ep: endpoint { + remote-endpoint = <&ov2659_0>; + ti,am437x-vpfe-interface = <0>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; +};
diff --git a/arch/arm/dts/am437x-idk-evm-u-boot.dtsi b/arch/arm/dts/am437x-idk-evm-u-boot.dtsi new file mode 100644 index 0000000..3aa9195 --- /dev/null +++ b/arch/arm/dts/am437x-idk-evm-u-boot.dtsi
@@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include "am4372-u-boot.dtsi" + +/{ + ocp { + u-boot,dm-spl; + }; +}; + +&uart0 { + u-boot,dm-spl; +}; + +&i2c0 { + u-boot,dm-spl; +}; + +&mmc1 { + u-boot,dm-spl; +};
diff --git a/arch/arm/dts/am437x-idk-evm.dts b/arch/arm/dts/am437x-idk-evm.dts new file mode 100644 index 0000000..28e3e1b --- /dev/null +++ b/arch/arm/dts/am437x-idk-evm.dts
@@ -0,0 +1,418 @@ +/* + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +/dts-v1/; + +#include "am4372.dtsi" +#include <dt-bindings/pinctrl/am43xx.h> +#include <dt-bindings/pwm/pwm.h> +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +/ { + model = "TI AM437x Industrial Development Kit"; + compatible = "ti,am437x-idk-evm","ti,am4372","ti,am43"; + + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; + + v24_0d: fixed-regulator-v24_0d { + compatible = "regulator-fixed"; + regulator-name = "V24_0D"; + regulator-min-microvolt = <24000000>; + regulator-max-microvolt = <24000000>; + regulator-always-on; + regulator-boot-on; + }; + + v3_3d: fixed-regulator-v3_3d { + compatible = "regulator-fixed"; + regulator-name = "V3_3D"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v24_0d>; + }; + + vdd_corereg: fixed-regulator-vdd_corereg { + compatible = "regulator-fixed"; + regulator-name = "VDD_COREREG"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v24_0d>; + }; + + vdd_core: fixed-regulator-vdd_core { + compatible = "regulator-fixed"; + regulator-name = "VDD_CORE"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vdd_corereg>; + }; + + v1_8dreg: fixed-regulator-v1_8dreg{ + compatible = "regulator-fixed"; + regulator-name = "V1_8DREG"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v24_0d>; + }; + + v1_8d: fixed-regulator-v1_8d{ + compatible = "regulator-fixed"; + regulator-name = "V1_8D"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v1_8dreg>; + }; + + v1_5dreg: fixed-regulator-v1_5dreg{ + compatible = "regulator-fixed"; + regulator-name = "V1_5DREG"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v24_0d>; + }; + + v1_5d: fixed-regulator-v1_5d{ + compatible = "regulator-fixed"; + regulator-name = "V1_5D"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v1_5dreg>; + }; + + gpio_keys: gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&gpio_keys_pins_default>; + + switch@0 { + label = "power-button"; + linux,code = <KEY_POWER>; + gpios = <&gpio4 2 GPIO_ACTIVE_LOW>; + }; + }; + + /* fixed 32k external oscillator clock */ + clk_32k_rtc: clk_32k_rtc { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; +}; + +&am43xx_pinmux { + gpio_keys_pins_default: gpio_keys_pins_default { + pinctrl-single,pins = < + AM4372_IOPAD(0x9b8, PIN_INPUT | MUX_MODE7) /* cam0_field.gpio4_2 */ + >; + }; + + i2c0_pins_default: i2c0_pins_default { + pinctrl-single,pins = < + AM4372_IOPAD(0x988, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + AM4372_IOPAD(0x98c, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + i2c0_pins_sleep: i2c0_pins_sleep { + pinctrl-single,pins = < + AM4372_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x98c, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + i2c2_pins_default: i2c2_pins_default { + pinctrl-single,pins = < + AM4372_IOPAD(0x9e8, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE3) /* cam1_data1.i2c2_scl */ + AM4372_IOPAD(0x9ec, PIN_INPUT | SLEWCTRL_FAST | MUX_MODE3) /* cam1_data0.i2c2_sda */ + >; + }; + + i2c2_pins_sleep: i2c2_pins_sleep { + pinctrl-single,pins = < + AM4372_IOPAD(0x9e8, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x9ec, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + mmc1_pins_default: pinmux_mmc1_pins_default { + pinctrl-single,pins = < + AM4372_IOPAD(0x900, PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */ + AM4372_IOPAD(0x904, PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */ + AM4372_IOPAD(0x9f0, PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */ + AM4372_IOPAD(0x9f4, PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */ + AM4372_IOPAD(0x9f8, PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */ + AM4372_IOPAD(0x9fc, PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */ + AM4372_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ + >; + }; + + mmc1_pins_sleep: pinmux_mmc1_pins_sleep { + pinctrl-single,pins = < + AM4372_IOPAD(0x900, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x904, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x9f0, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x9f4, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x9f8, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x9fc, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x960, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + ecap0_pins_default: backlight_pins_default { + pinctrl-single,pins = < + AM4372_IOPAD(0x964, PIN_OUTPUT | MUX_MODE0) /* ecap0_in_pwm0_out.ecap0_in_pwm0_out */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + AM4372_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */ + AM4372_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */ + AM4372_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */ + AM4372_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */ + AM4372_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td2 */ + AM4372_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td3 */ + AM4372_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rmii1_rclk */ + AM4372_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */ + AM4372_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */ + AM4372_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */ + AM4372_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd2 */ + AM4372_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd3 */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + AM4372_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + AM4372_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + AM4372_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + AM4372_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + qspi_pins_default: qspi_pins_default { + pinctrl-single,pins = < + AM4372_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE3) /* gpmc_csn0.qspi_csn */ + AM4372_IOPAD(0x888, PIN_OUTPUT | MUX_MODE2) /* gpmc_csn3.qspi_clk */ + AM4372_IOPAD(0x890, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_advn_ale.qspi_d0 */ + AM4372_IOPAD(0x894, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_oen_ren.qspi_d1 */ + AM4372_IOPAD(0x898, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_wen.qspi_d2 */ + AM4372_IOPAD(0x89c, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_be0n_cle.qspi_d3 */ + >; + }; + + qspi_pins_sleep: qspi_pins_sleep{ + pinctrl-single,pins = < + AM4372_IOPAD(0x87c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x888, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x890, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x894, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x898, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x89c, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c0_pins_default>; + pinctrl-1 = <&i2c0_pins_sleep>; + clock-frequency = <400000>; + + at24@50 { + compatible = "at24,24c256"; + pagesize = <64>; + reg = <0x50>; + }; + + tps: tps62362@60 { + compatible = "ti,tps62362"; + reg = <0x60>; + regulator-name = "VDD_MPU"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1330000>; + regulator-boot-on; + regulator-always-on; + ti,vsel0-state-high; + ti,vsel1-state-high; + vin-supply = <&v3_3d>; + }; +}; + +&i2c2 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c2_pins_default>; + pinctrl-1 = <&i2c2_pins_sleep>; + clock-frequency = <100000>; +}; + +&epwmss0 { + status = "okay"; +}; + +&ecap0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ecap0_pins_default>; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio4 { + status = "okay"; +}; + +&gpio5 { + status = "okay"; +}; + +&mmc1 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&mmc1_pins_default>; + pinctrl-1 = <&mmc1_pins_sleep>; + vmmc-supply = <&v3_3d>; + bus-width = <4>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; +}; + +&qspi { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qspi_pins_default>; + pinctrl-1 = <&qspi_pins_sleep>; + + spi-max-frequency = <48000000>; + m25p80@0 { + compatible = "mx66l51235l", "spi-flash"; + spi-max-frequency = <48000000>; + reg = <0>; + spi-cpol; + spi-cpha; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + #address-cells = <1>; + #size-cells = <1>; + + /* + * MTD partition table. The ROM checks the first 512KiB for a + * valid file to boot(XIP). + */ + partition@0 { + label = "QSPI.U_BOOT"; + reg = <0x00000000 0x000080000>; + }; + partition@1 { + label = "QSPI.U_BOOT.backup"; + reg = <0x00080000 0x00080000>; + }; + partition@2 { + label = "QSPI.U-BOOT-SPL_OS"; + reg = <0x00100000 0x00010000>; + }; + partition@3 { + label = "QSPI.U_BOOT_ENV"; + reg = <0x00110000 0x00010000>; + }; + partition@4 { + label = "QSPI.U-BOOT-ENV.backup"; + reg = <0x00120000 0x00010000>; + }; + partition@5 { + label = "QSPI.KERNEL"; + reg = <0x00130000 0x0800000>; + }; + partition@6 { + label = "QSPI.FILESYSTEM"; + reg = <0x00930000 0x36D0000>; + }; + }; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii"; +}; + +&rtc { + clocks = <&clk_32k_rtc>, <&clk_32768_ck>; + clock-names = "ext-clk", "int-clk"; + status = "okay"; +}; + +&wdt { + status = "okay"; +}; + +&cpu { + cpu0-supply = <&tps>; +};
diff --git a/arch/arm/dts/am437x-sk-evm-u-boot.dtsi b/arch/arm/dts/am437x-sk-evm-u-boot.dtsi new file mode 100644 index 0000000..3aa9195 --- /dev/null +++ b/arch/arm/dts/am437x-sk-evm-u-boot.dtsi
@@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include "am4372-u-boot.dtsi" + +/{ + ocp { + u-boot,dm-spl; + }; +}; + +&uart0 { + u-boot,dm-spl; +}; + +&i2c0 { + u-boot,dm-spl; +}; + +&mmc1 { + u-boot,dm-spl; +};
diff --git a/arch/arm/dts/am437x-sk-evm.dts b/arch/arm/dts/am437x-sk-evm.dts new file mode 100644 index 0000000..927d8d3 --- /dev/null +++ b/arch/arm/dts/am437x-sk-evm.dts
@@ -0,0 +1,705 @@ +/* + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +/* AM437x SK EVM */ + +/dts-v1/; + +#include "am4372.dtsi" +#include <dt-bindings/pinctrl/am43xx.h> +#include <dt-bindings/pwm/pwm.h> +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +/ { + model = "TI AM437x SK EVM"; + compatible = "ti,am437x-sk-evm","ti,am4372","ti,am43"; + + aliases { + display0 = &lcd0; + }; + + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; + + backlight { + compatible = "pwm-backlight"; + pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 51 53 56 62 75 101 152 255>; + default-brightness-level = <8>; + }; + + sound { + compatible = "ti,da830-evm-audio"; + ti,model = "AM437x-SK-EVM"; + ti,audio-codec = <&tlv320aic3106>; + ti,mcasp-controller = <&mcasp1>; + ti,codec-clock-rate = <24000000>; + ti,audio-routing = + "Headphone Jack", "HPLOUT", + "Headphone Jack", "HPROUT"; + }; + + matrix_keypad: matrix_keypad@0 { + compatible = "gpio-matrix-keypad"; + + pinctrl-names = "default"; + pinctrl-0 = <&matrix_keypad_pins>; + + debounce-delay-ms = <5>; + col-scan-delay-us = <5>; + + row-gpios = <&gpio5 5 GPIO_ACTIVE_HIGH /* Bank5, pin5 */ + &gpio5 6 GPIO_ACTIVE_HIGH>; /* Bank5, pin6 */ + + col-gpios = <&gpio5 13 GPIO_ACTIVE_HIGH /* Bank5, pin13 */ + &gpio5 4 GPIO_ACTIVE_HIGH>; /* Bank5, pin4 */ + + linux,keymap = < + MATRIX_KEY(0, 0, KEY_DOWN) + MATRIX_KEY(0, 1, KEY_RIGHT) + MATRIX_KEY(1, 0, KEY_LEFT) + MATRIX_KEY(1, 1, KEY_UP) + >; + }; + + leds { + compatible = "gpio-leds"; + + pinctrl-names = "default"; + pinctrl-0 = <&leds_pins>; + + led@0 { + label = "am437x-sk:red:heartbeat"; + gpios = <&gpio5 0 GPIO_ACTIVE_HIGH>; /* Bank 5, pin 0 */ + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + + led@1 { + label = "am437x-sk:green:mmc1"; + gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; /* Bank 5, pin 1 */ + linux,default-trigger = "mmc0"; + default-state = "off"; + }; + + led@2 { + label = "am437x-sk:blue:cpu0"; + gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>; /* Bank 5, pin 2 */ + linux,default-trigger = "cpu0"; + default-state = "off"; + }; + + led@3 { + label = "am437x-sk:blue:usr3"; + gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>; /* Bank 5, pin 3 */ + default-state = "off"; + }; + }; + + lcd0: display { + compatible = "newhaven,nhd-4.3-480272ef-atxl", "panel-dpi"; + label = "lcd"; + + pinctrl-names = "default"; + pinctrl-0 = <&lcd_pins>; + + enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; + + panel-timing { + clock-frequency = <9000000>; + hactive = <480>; + vactive = <272>; + hfront-porch = <2>; + hback-porch = <2>; + hsync-len = <41>; + vfront-porch = <2>; + vback-porch = <2>; + vsync-len = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + port { + lcd_in: endpoint { + remote-endpoint = <&dpi_out>; + }; + }; + }; +}; + +&am43xx_pinmux { + matrix_keypad_pins: matrix_keypad_pins { + pinctrl-single,pins = < + 0x24c (PIN_OUTPUT | MUX_MODE7) /* gpio5_13.gpio5_13 */ + 0x250 (PIN_OUTPUT | MUX_MODE7) /* spi4_sclk.gpio5_4 */ + 0x254 (PIN_INPUT | MUX_MODE7) /* spi4_d0.gpio5_5 */ + 0x258 (PIN_INPUT | MUX_MODE7) /* spi4_d1.gpio5_5 */ + >; + }; + + leds_pins: leds_pins { + pinctrl-single,pins = < + 0x228 (PIN_OUTPUT | MUX_MODE7) /* uart3_rxd.gpio5_2 */ + 0x22c (PIN_OUTPUT | MUX_MODE7) /* uart3_txd.gpio5_3 */ + 0x230 (PIN_OUTPUT | MUX_MODE7) /* uart3_ctsn.gpio5_0 */ + 0x234 (PIN_OUTPUT | MUX_MODE7) /* uart3_rtsn.gpio5_1 */ + >; + }; + + i2c0_pins: i2c0_pins { + pinctrl-single,pins = < + 0x188 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + 0x18c (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + i2c1_pins: i2c1_pins { + pinctrl-single,pins = < + 0x15c (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE2) /* spi0_cs0.i2c1_scl */ + 0x158 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE2) /* spi0_d1.i2c1_sda */ + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + 0x0f0 (PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */ + 0x0f4 (PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */ + 0x0f8 (PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */ + 0x0fc (PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */ + 0x100 (PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */ + 0x104 (PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */ + 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ + >; + }; + + ecap0_pins: backlight_pins { + pinctrl-single,pins = < + 0x164 (PIN_OUTPUT | MUX_MODE0) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out */ + >; + }; + + edt_ft5306_ts_pins: edt_ft5306_ts_pins { + pinctrl-single,pins = < + 0x74 (PIN_INPUT | MUX_MODE7) /* gpmc_wpn.gpio0_31 */ + 0x78 (PIN_OUTPUT | MUX_MODE7) /* gpmc_be1n.gpio1_28 */ + >; + }; + + vpfe0_pins_default: vpfe0_pins_default { + pinctrl-single,pins = < + 0x1b0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_hd mode 0*/ + 0x1b4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_vd mode 0*/ + 0x1b8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_field mode 0*/ + 0x1bc (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_wen mode 0*/ + 0x1c0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_pclk mode 0*/ + 0x1c4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data8 mode 0*/ + 0x1c8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data9 mode 0*/ + 0x208 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data0 mode 0*/ + 0x20c (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data1 mode 0*/ + 0x210 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data2 mode 0*/ + 0x214 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data3 mode 0*/ + 0x218 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data4 mode 0*/ + 0x21c (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data5 mode 0*/ + 0x220 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data6 mode 0*/ + 0x224 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data7 mode 0*/ + >; + }; + + vpfe0_pins_sleep: vpfe0_pins_sleep { + pinctrl-single,pins = < + 0x1b0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1b4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1b8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1bc (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1c0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1c4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1c8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x208 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x20c (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x210 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x214 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x218 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x21c (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x220 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x224 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + 0x12c (PIN_OUTPUT | MUX_MODE2) /* mii1_txclk.rmii1_tclk */ + 0x114 (PIN_OUTPUT | MUX_MODE2) /* mii1_txen.rgmii1_tctl */ + 0x128 (PIN_OUTPUT | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */ + 0x124 (PIN_OUTPUT | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */ + 0x120 (PIN_OUTPUT | MUX_MODE2) /* mii1_txd0.rgmii1_td2 */ + 0x11c (PIN_OUTPUT | MUX_MODE2) /* mii1_txd1.rgmii1_td3 */ + 0x130 (PIN_INPUT | MUX_MODE2) /* mii1_rxclk.rmii1_rclk */ + 0x118 (PIN_INPUT | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */ + 0x140 (PIN_INPUT | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */ + 0x13c (PIN_INPUT | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */ + 0x138 (PIN_INPUT | MUX_MODE2) /* mii1_rxd0.rgmii1_rd2 */ + 0x134 (PIN_INPUT | MUX_MODE2) /* mii1_rxd1.rgmii1_rd3 */ + + /* Slave 2 */ + 0x58 (PIN_OUTPUT | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */ + 0x40 (PIN_OUTPUT | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */ + 0x54 (PIN_OUTPUT | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */ + 0x50 (PIN_OUTPUT | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */ + 0x4c (PIN_OUTPUT | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */ + 0x48 (PIN_OUTPUT | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */ + 0x5c (PIN_INPUT | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */ + 0x44 (PIN_INPUT | MUX_MODE2) /* gpmc_a1.rgmii2_rtcl */ + 0x6c (PIN_INPUT | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */ + 0x68 (PIN_INPUT | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */ + 0x64 (PIN_INPUT | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */ + 0x60 (PIN_INPUT | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) + + /* Slave 2 reset value */ + 0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + 0x148 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + 0x14c (PIN_OUTPUT | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + dss_pins: dss_pins { + pinctrl-single,pins = < + 0x020 (PIN_OUTPUT | MUX_MODE1) /* gpmc ad 8 -> DSS DATA 23 */ + 0x024 (PIN_OUTPUT | MUX_MODE1) + 0x028 (PIN_OUTPUT | MUX_MODE1) + 0x02c (PIN_OUTPUT | MUX_MODE1) + 0x030 (PIN_OUTPUT | MUX_MODE1) + 0x034 (PIN_OUTPUT | MUX_MODE1) + 0x038 (PIN_OUTPUT | MUX_MODE1) + 0x03c (PIN_OUTPUT | MUX_MODE1) /* gpmc ad 15 -> DSS DATA 16 */ + 0x0a0 (PIN_OUTPUT | MUX_MODE0) /* DSS DATA 0 */ + 0x0a4 (PIN_OUTPUT | MUX_MODE0) + 0x0a8 (PIN_OUTPUT | MUX_MODE0) + 0x0ac (PIN_OUTPUT | MUX_MODE0) + 0x0b0 (PIN_OUTPUT | MUX_MODE0) + 0x0b4 (PIN_OUTPUT | MUX_MODE0) + 0x0b8 (PIN_OUTPUT | MUX_MODE0) + 0x0bc (PIN_OUTPUT | MUX_MODE0) + 0x0c0 (PIN_OUTPUT | MUX_MODE0) + 0x0c4 (PIN_OUTPUT | MUX_MODE0) + 0x0c8 (PIN_OUTPUT | MUX_MODE0) + 0x0cc (PIN_OUTPUT | MUX_MODE0) + 0x0d0 (PIN_OUTPUT | MUX_MODE0) + 0x0d4 (PIN_OUTPUT | MUX_MODE0) + 0x0d8 (PIN_OUTPUT | MUX_MODE0) + 0x0dc (PIN_OUTPUT | MUX_MODE0) /* DSS DATA 15 */ + 0x0e0 (PIN_OUTPUT | MUX_MODE0) /* DSS VSYNC */ + 0x0e4 (PIN_OUTPUT | MUX_MODE0) /* DSS HSYNC */ + 0x0e8 (PIN_OUTPUT | MUX_MODE0) /* DSS PCLK */ + 0x0ec (PIN_OUTPUT | MUX_MODE0) /* DSS AC BIAS EN */ + + >; + }; + + qspi_pins: qspi_pins { + pinctrl-single,pins = < + 0x7c (PIN_OUTPUT | MUX_MODE3) /* gpmc_csn0.qspi_csn */ + 0x88 (PIN_OUTPUT | MUX_MODE2) /* gpmc_csn3.qspi_clk */ + 0x90 (PIN_INPUT | MUX_MODE3) /* gpmc_advn_ale.qspi_d0 */ + 0x94 (PIN_INPUT | MUX_MODE3) /* gpmc_oen_ren.qspi_d1 */ + 0x98 (PIN_INPUT | MUX_MODE3) /* gpmc_wen.qspi_d2 */ + 0x9c (PIN_INPUT | MUX_MODE3) /* gpmc_be0n_cle.qspi_d3 */ + >; + }; + + mcasp1_pins: mcasp1_pins { + pinctrl-single,pins = < + 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ + 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */ + 0x108 (PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */ + 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */ + >; + }; + + lcd_pins: lcd_pins { + pinctrl-single,pins = < + 0x1c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpcm_ad7.gpio1_7 */ + >; + }; + + usb1_pins: usb1_pins { + pinctrl-single,pins = < + 0x2c0 (PIN_OUTPUT | MUX_MODE0) /* usb0_drvvbus.usb0_drvvbus */ + >; + }; + + usb2_pins: usb2_pins { + pinctrl-single,pins = < + 0x2c4 (PIN_OUTPUT | MUX_MODE0) /* usb0_drvvbus.usb0_drvvbus */ + >; + }; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <400000>; + + tps@24 { + compatible = "ti,tps65218"; + reg = <0x24>; + interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <2>; + + dcdc1: regulator-dcdc1 { + compatible = "ti,tps65218-dcdc1"; + /* VDD_CORE limits min of OPP50 and max of OPP100 */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <1144000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc2: regulator-dcdc2 { + compatible = "ti,tps65218-dcdc2"; + /* VDD_MPU limits min of OPP50 and max of OPP_NITRO */ + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <1378000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc3: regulator-dcdc3 { + compatible = "ti,tps65218-dcdc3"; + regulator-name = "vdds_ddr"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc4: regulator-dcdc4 { + compatible = "ti,tps65218-dcdc4"; + regulator-name = "v3_3d"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1: regulator-ldo1 { + compatible = "ti,tps65218-ldo1"; + regulator-name = "v1_8d"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + + power-button { + compatible = "ti,tps65218-pwrbutton"; + status = "okay"; + interrupts = <3 IRQ_TYPE_EDGE_BOTH>; + }; + }; + + at24@50 { + compatible = "at24,24c256"; + pagesize = <64>; + reg = <0x50>; + }; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + clock-frequency = <400000>; + + edt-ft5306@38 { + status = "okay"; + compatible = "edt,edt-ft5306", "edt,edt-ft5x06"; + pinctrl-names = "default"; + pinctrl-0 = <&edt_ft5306_ts_pins>; + + reg = <0x38>; + interrupt-parent = <&gpio0>; + interrupts = <31 0>; + + reset-gpios = <&gpio1 28 GPIO_ACTIVE_LOW>; + + touchscreen-size-x = <480>; + touchscreen-size-y = <272>; + }; + + tlv320aic3106: tlv320aic3106@1b { + compatible = "ti,tlv320aic3106"; + reg = <0x1b>; + status = "okay"; + + /* Regulators */ + AVDD-supply = <&dcdc4>; + IOVDD-supply = <&dcdc4>; + DRVDD-supply = <&dcdc4>; + DVDD-supply = <&ldo1>; + }; + + lis331dlh@18 { + compatible = "st,lis331dlh"; + reg = <0x18>; + status = "okay"; + + Vdd-supply = <&dcdc4>; + Vdd_IO-supply = <&dcdc4>; + interrupts-extended = <&gpio1 6 0>, <&gpio2 1 0>; + }; +}; + +&epwmss0 { + status = "okay"; +}; + +&ecap0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ecap0_pins>; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio5 { + status = "okay"; +}; + +&mmc1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + + vmmc-supply = <&dcdc4>; + bus-width = <4>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; +}; + +&usb2_phy1 { + status = "okay"; +}; + +&usb1 { + dr_mode = "peripheral"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&usb1_pins>; +}; + +&usb2_phy2 { + status = "okay"; +}; + +&usb2 { + dr_mode = "host"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&usb2_pins>; +}; + +&qspi { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&qspi_pins>; + + spi-max-frequency = <48000000>; + m25p80@0 { + compatible = "mx66l51235l","spi-flash"; + spi-max-frequency = <48000000>; + reg = <0>; + spi-cpol; + spi-cpha; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + #address-cells = <1>; + #size-cells = <1>; + + /* MTD partition table. + * The ROM checks the first 512KiB + * for a valid file to boot(XIP). + */ + partition@0 { + label = "QSPI.U_BOOT"; + reg = <0x00000000 0x000080000>; + }; + partition@1 { + label = "QSPI.U_BOOT.backup"; + reg = <0x00080000 0x00080000>; + }; + partition@2 { + label = "QSPI.U-BOOT-SPL_OS"; + reg = <0x00100000 0x00010000>; + }; + partition@3 { + label = "QSPI.U_BOOT_ENV"; + reg = <0x00110000 0x00010000>; + }; + partition@4 { + label = "QSPI.U-BOOT-ENV.backup"; + reg = <0x00120000 0x00010000>; + }; + partition@5 { + label = "QSPI.KERNEL"; + reg = <0x00130000 0x0800000>; + }; + partition@6 { + label = "QSPI.FILESYSTEM"; + reg = <0x00930000 0x36D0000>; + }; + }; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + dual_emac = <1>; + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <4>; + phy-mode = "rgmii"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <5>; + phy-mode = "rgmii"; + dual_emac_res_vlan = <2>; +}; + +&elm { + status = "okay"; +}; + +&mcasp1 { + pinctrl-names = "default"; + pinctrl-0 = <&mcasp1_pins>; + + status = "okay"; + + op-mode = <0>; + tdm-slots = <2>; + serial-dir = < + 0 0 1 2 + >; + + tx-num-evt = <1>; + rx-num-evt = <1>; +}; + +&dss { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&dss_pins>; + + port { + dpi_out: endpoint@0 { + remote-endpoint = <&lcd_in>; + data-lines = <24>; + }; + }; +}; + +&rtc { + status = "okay"; +}; + +&wdt { + status = "okay"; +}; + +&cpu { + cpu0-supply = <&dcdc2>; +}; + +&vpfe0 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&vpfe0_pins_default>; + pinctrl-1 = <&vpfe0_pins_sleep>; + + /* Camera port */ + port { + vpfe0_ep: endpoint { + /* remote-endpoint = <&sensor>; add once we have it */ + ti,am437x-vpfe-interface = <0>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; +};
diff --git a/arch/arm/dts/am43x-epos-evm.dts b/arch/arm/dts/am43x-epos-evm.dts new file mode 100644 index 0000000..fa4d1e3 --- /dev/null +++ b/arch/arm/dts/am43x-epos-evm.dts
@@ -0,0 +1,806 @@ +/* + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +/* AM43x EPOS EVM */ + +/dts-v1/; + +#include "am4372.dtsi" +#include <dt-bindings/pinctrl/am43xx.h> +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/pwm/pwm.h> +#include <dt-bindings/sound/tlv320aic31xx-micbias.h> + +/ { + model = "TI AM43x EPOS EVM"; + compatible = "ti,am43x-epos-evm","ti,am438x","ti,am43"; + + aliases { + display0 = &lcd0; + }; + + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; + + vmmcsd_fixed: fixedregulator-sd { + compatible = "regulator-fixed"; + regulator-name = "vmmcsd_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + }; + + vbat: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + }; + + lcd0: display { + compatible = "osddisplays,osd057T0559-34ts", "panel-dpi"; + label = "lcd"; + + panel-timing { + clock-frequency = <33000000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <210>; + hback-porch = <16>; + hsync-len = <30>; + vback-porch = <10>; + vfront-porch = <22>; + vsync-len = <13>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + port { + lcd_in: endpoint { + remote-endpoint = <&dpi_out>; + }; + }; + }; + + matrix_keypad: matrix_keypad@0 { + compatible = "gpio-matrix-keypad"; + debounce-delay-ms = <5>; + col-scan-delay-us = <2>; + + row-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH /* Bank0, pin12 */ + &gpio0 13 GPIO_ACTIVE_HIGH /* Bank0, pin13 */ + &gpio0 14 GPIO_ACTIVE_HIGH /* Bank0, pin14 */ + &gpio0 15 GPIO_ACTIVE_HIGH>; /* Bank0, pin15 */ + + col-gpios = <&gpio3 9 GPIO_ACTIVE_HIGH /* Bank3, pin9 */ + &gpio3 10 GPIO_ACTIVE_HIGH /* Bank3, pin10 */ + &gpio2 18 GPIO_ACTIVE_HIGH /* Bank2, pin18 */ + &gpio2 19 GPIO_ACTIVE_HIGH>; /* Bank2, pin19 */ + + linux,keymap = <0x00000201 /* P1 */ + 0x01000204 /* P4 */ + 0x02000207 /* P7 */ + 0x0300020a /* NUMERIC_STAR */ + 0x00010202 /* P2 */ + 0x01010205 /* P5 */ + 0x02010208 /* P8 */ + 0x03010200 /* P0 */ + 0x00020203 /* P3 */ + 0x01020206 /* P6 */ + 0x02020209 /* P9 */ + 0x0302020b /* NUMERIC_POUND */ + 0x00030067 /* UP */ + 0x0103006a /* RIGHT */ + 0x0203006c /* DOWN */ + 0x03030069>; /* LEFT */ + }; + + backlight { + compatible = "pwm-backlight"; + pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>; + brightness-levels = <0 51 53 56 62 75 101 152 255>; + default-brightness-level = <8>; + }; + + sound0: sound@0 { + compatible = "simple-audio-card"; + simple-audio-card,name = "AM43-EPOS-EVM"; + simple-audio-card,widgets = + "Microphone", "Microphone Jack", + "Headphone", "Headphone Jack", + "Speaker", "Speaker"; + simple-audio-card,routing = + "MIC1LP", "Microphone Jack", + "MIC1RP", "Microphone Jack", + "MIC1LP", "MICBIAS", + "MIC1RP", "MICBIAS", + "Headphone Jack", "HPL", + "Headphone Jack", "HPR", + "Speaker", "SPL", + "Speaker", "SPR"; + simple-audio-card,format = "dsp_b"; + simple-audio-card,bitclock-master = <&sound0_master>; + simple-audio-card,frame-master = <&sound0_master>; + simple-audio-card,bitclock-inversion; + + simple-audio-card,cpu { + sound-dai = <&mcasp1>; + system-clock-frequency = <12000000>; + }; + + sound0_master: simple-audio-card,codec { + sound-dai = <&tlv320aic3111>; + system-clock-frequency = <12000000>; + }; + }; +}; + +&am43xx_pinmux { + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + AM4372_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs */ + AM4372_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxerr.rmii1_rxerr */ + AM4372_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txen.rmii1_txen */ + AM4372_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxdv.rmii1_rxdv */ + AM4372_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */ + AM4372_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */ + AM4372_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */ + AM4372_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */ + AM4372_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_refclk.rmii1_refclk */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + AM4372_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + AM4372_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + AM4372_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + AM4372_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + AM4372_IOPAD(0x988, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + AM4372_IOPAD(0x98c, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + nand_flash_x8: nand_flash_x8 { + pinctrl-single,pins = < + AM4372_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a0.SELQSPIorNAND/GPIO */ + AM4372_IOPAD(0x800, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ + AM4372_IOPAD(0x804, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ + AM4372_IOPAD(0x808, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */ + AM4372_IOPAD(0x80c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */ + AM4372_IOPAD(0x810, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */ + AM4372_IOPAD(0x814, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */ + AM4372_IOPAD(0x818, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */ + AM4372_IOPAD(0x81c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */ + AM4372_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */ + AM4372_IOPAD(0x874, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpmc_wpn */ + AM4372_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */ + AM4372_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */ + AM4372_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */ + AM4372_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */ + AM4372_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */ + >; + }; + + ecap0_pins: backlight_pins { + pinctrl-single,pins = < + AM4372_IOPAD(0x964, MUX_MODE0) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + AM4372_IOPAD(0x9c0, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE8) /* i2c2_sda.i2c2_sda */ + AM4372_IOPAD(0x9c4, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE8) /* i2c2_scl.i2c2_scl */ + >; + }; + + spi0_pins: pinmux_spi0_pins { + pinctrl-single,pins = < + AM4372_IOPAD(0x950, PIN_INPUT | MUX_MODE0) /* spi0_clk.spi0_clk */ + AM4372_IOPAD(0x954, PIN_OUTPUT | MUX_MODE0) /* spi0_d0.spi0_d0 */ + AM4372_IOPAD(0x958, PIN_INPUT | MUX_MODE0) /* spi0_d1.spi0_d1 */ + AM4372_IOPAD(0x95c, PIN_OUTPUT | MUX_MODE0) /* spi0_cs0.spi0_cs0 */ + >; + }; + + spi1_pins: pinmux_spi1_pins { + pinctrl-single,pins = < + AM4372_IOPAD(0x990, PIN_INPUT | MUX_MODE3) /* mcasp0_aclkx.spi1_clk */ + AM4372_IOPAD(0x994, PIN_OUTPUT | MUX_MODE3) /* mcasp0_fsx.spi1_d0 */ + AM4372_IOPAD(0x998, PIN_INPUT | MUX_MODE3) /* mcasp0_axr0.spi1_d1 */ + AM4372_IOPAD(0x99c, PIN_OUTPUT | MUX_MODE3) /* mcasp0_ahclkr.spi1_cs0 */ + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + AM4372_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ + >; + }; + + qspi1_default: qspi1_default { + pinctrl-single,pins = < + AM4372_IOPAD(0x87c, PIN_INPUT_PULLUP | MUX_MODE3) + AM4372_IOPAD(0x888, PIN_INPUT_PULLUP | MUX_MODE2) + AM4372_IOPAD(0x890, PIN_INPUT_PULLUP | MUX_MODE3) + AM4372_IOPAD(0x894, PIN_INPUT_PULLUP | MUX_MODE3) + AM4372_IOPAD(0x898, PIN_INPUT_PULLUP | MUX_MODE3) + AM4372_IOPAD(0x89c, PIN_INPUT_PULLUP | MUX_MODE3) + >; + }; + + pixcir_ts_pins: pixcir_ts_pins { + pinctrl-single,pins = < + AM4372_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a1.gpio1_17 */ + >; + }; + + hdq_pins: pinmux_hdq_pins { + pinctrl-single,pins = < + AM4372_IOPAD(0xa34, PIN_INPUT_PULLUP | MUX_MODE1) /* cam1_wen.hdq_gpio */ + >; + }; + + dss_pins: dss_pins { + pinctrl-single,pins = < + AM4372_IOPAD(0x820, PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 8 -> DSS DATA 23 */ + AM4372_IOPAD(0x824, PIN_OUTPUT_PULLUP | MUX_MODE1) + AM4372_IOPAD(0x828, PIN_OUTPUT_PULLUP | MUX_MODE1) + AM4372_IOPAD(0x82c, PIN_OUTPUT_PULLUP | MUX_MODE1) + AM4372_IOPAD(0x830, PIN_OUTPUT_PULLUP | MUX_MODE1) + AM4372_IOPAD(0x834, PIN_OUTPUT_PULLUP | MUX_MODE1) + AM4372_IOPAD(0x838, PIN_OUTPUT_PULLUP | MUX_MODE1) + AM4372_IOPAD(0x83c, PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 15 -> DSS DATA 16 */ + AM4372_IOPAD(0x8a0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 0 */ + AM4372_IOPAD(0x8a4, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8a8, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8ac, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8b0, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8b4, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8B8, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8bc, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8c0, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8c4, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8c8, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8cc, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8d0, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8d4, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8d8, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM4372_IOPAD(0x8dc, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 15 */ + AM4372_IOPAD(0x8e0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS VSYNC */ + AM4372_IOPAD(0x8e4, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS HSYNC */ + AM4372_IOPAD(0x8e8, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS PCLK */ + AM4372_IOPAD(0x8ec, PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS AC BIAS EN */ + >; + }; + + display_mux_pins: display_mux_pins { + pinctrl-single,pins = < + /* GPMC CLK -> GPIO 2_1 to select LCD / HDMI */ + AM4372_IOPAD(0x88C, PIN_OUTPUT_PULLUP | MUX_MODE7) + >; + }; + + vpfe1_pins_default: vpfe1_pins_default { + pinctrl-single,pins = < + AM4372_IOPAD(0x9cc, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data9 mode 0 */ + AM4372_IOPAD(0x9d0, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data8 mode 0 */ + AM4372_IOPAD(0x9d4, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_hd mode 0 */ + AM4372_IOPAD(0x9d8, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_vd mode 0 */ + AM4372_IOPAD(0x9dc, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_pclk mode 0 */ + AM4372_IOPAD(0x9e8, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data0 mode 0 */ + AM4372_IOPAD(0x9ec, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data1 mode 0 */ + AM4372_IOPAD(0x9f0, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data2 mode 0 */ + AM4372_IOPAD(0x9f4, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data3 mode 0 */ + AM4372_IOPAD(0x9f8, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data4 mode 0 */ + AM4372_IOPAD(0x9fc, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data5 mode 0 */ + AM4372_IOPAD(0xa00, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data6 mode 0 */ + AM4372_IOPAD(0xa04, PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data7 mode 0 */ + >; + }; + + vpfe1_pins_sleep: vpfe1_pins_sleep { + pinctrl-single,pins = < + AM4372_IOPAD(0x9cc, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0x9d0, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0x9d4, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0x9d8, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0x9dc, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0x9e8, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0x9ec, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0x9f0, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0x9f4, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0x9f8, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0x9fc, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0xa00, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + AM4372_IOPAD(0xa04, DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + >; + }; + + mcasp1_pins: mcasp1_pins { + pinctrl-single,pins = < + AM4372_IOPAD(0x9a0, PIN_INPUT_PULLDOWN | MUX_MODE3) /* MCASP0_ACLKR/MCASP1_ACLKX */ + AM4372_IOPAD(0x9a4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* MCASP0_FSR/MCASP1_FSX */ + AM4372_IOPAD(0x9a8, PIN_OUTPUT_PULLDOWN | MUX_MODE3)/* MCASP0_AXR1/MCASP1_AXR0 */ + AM4372_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE3) /* MCASP0_AHCLKX/MCASP1_AXR1 */ + >; + }; + + mcasp1_sleep_pins: mcasp1_sleep_pins { + pinctrl-single,pins = < + AM4372_IOPAD(0x9a0, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x9a4, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x9a8, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM4372_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; +}; + +&mmc1 { + status = "okay"; + vmmc-supply = <&vmmcsd_fixed>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <16>; + phy-mode = "rmii"; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rmii"; +}; + +&phy_sel { + rmii-clock-ext; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <400000>; + + tps65218: tps65218@24 { + reg = <0x24>; + compatible = "ti,tps65218"; + interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */ + interrupt-controller; + #interrupt-cells = <2>; + + dcdc1: regulator-dcdc1 { + compatible = "ti,tps65218-dcdc1"; + regulator-name = "vdd_core"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <1144000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc2: regulator-dcdc2 { + compatible = "ti,tps65218-dcdc2"; + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <1378000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc3: regulator-dcdc3 { + compatible = "ti,tps65218-dcdc3"; + regulator-name = "vdcdc3"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc4: regulator-dcdc4 { + compatible = "ti,tps65218-dcdc4"; + regulator-name = "vdcdc4"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc5: regulator-dcdc5 { + compatible = "ti,tps65218-dcdc5"; + regulator-name = "v1_0bat"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + + dcdc6: regulator-dcdc6 { + compatible = "ti,tps65218-dcdc6"; + regulator-name = "v1_8bat"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo1: regulator-ldo1 { + compatible = "ti,tps65218-ldo1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + }; + }; + + at24@50 { + compatible = "at24,24c256"; + pagesize = <64>; + reg = <0x50>; + }; + + pixcir_ts@5c { + compatible = "pixcir,pixcir_tangoc"; + pinctrl-names = "default"; + pinctrl-0 = <&pixcir_ts_pins>; + reg = <0x5c>; + interrupt-parent = <&gpio1>; + interrupts = <17 IRQ_TYPE_EDGE_FALLING>; + + attb-gpio = <&gpio1 17 GPIO_ACTIVE_HIGH>; + + touchscreen-size-x = <1024>; + touchscreen-size-y = <600>; + }; + + tlv320aic3111: tlv320aic3111@18 { + #sound-dai-cells = <0>; + compatible = "ti,tlv320aic3111"; + reg = <0x18>; + status = "okay"; + + ai31xx-micbias-vg = <MICBIAS_2_0V>; + + /* Regulators */ + HPVDD-supply = <&dcdc4>; /* v3_3AUD -> V3_3D -> DCDC4 */ + SPRVDD-supply = <&vbat>; /* vbat */ + SPLVDD-supply = <&vbat>; /* vbat */ + AVDD-supply = <&dcdc4>; /* v3_3AUD -> V3_3D -> DCDC4 */ + IOVDD-supply = <&dcdc4>; /* V3_3D -> DCDC4 */ + DVDD-supply = <&ldo1>; /* V1_8AUD -> V1_8D -> LDO1 */ + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + pinctrl-names = "default"; + pinctrl-0 = <&display_mux_pins>; + status = "okay"; + + p1 { + /* + * SelLCDorHDMI selects between display and audio paths: + * Low: HDMI display with audio via HDMI + * High: LCD display with analog audio via aic3111 codec + */ + gpio-hog; + gpios = <1 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "SelLCDorHDMI"; + }; +}; + +&gpio3 { + status = "okay"; +}; + +&elm { + status = "okay"; +}; + +&gpmc { + status = "okay"; /* Disable QSPI when enabling GPMC (NAND) */ + pinctrl-names = "default"; + pinctrl-0 = <&nand_flash_x8>; + ranges = <0 0 0x08000000 0x01000000>; /* CS0 space. Min partition = 16MB */ + nand@0,0 { + compatible = "ti,omap2-nand"; + reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ + interrupt-parent = <&gpmc>; + interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ + <1 IRQ_TYPE_NONE>; /* termcount */ + ti,nand-ecc-opt = "bch16"; + ti,elm-id = <&elm>; + nand-bus-width = <8>; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <40>; /* tCEA + tCHZ + 1 */ + gpmc,cs-wr-off-ns = <40>; + gpmc,adv-on-ns = <0>; /* cs-on-ns */ + gpmc,adv-rd-off-ns = <25>; /* min( tALH + tALS + 1) */ + gpmc,adv-wr-off-ns = <25>; /* min( tALH + tALS + 1) */ + gpmc,we-on-ns = <0>; /* cs-on-ns */ + gpmc,we-off-ns = <20>; /* we-on-time + tWP + 2 */ + gpmc,oe-on-ns = <3>; /* cs-on-ns + tRR + 2 */ + gpmc,oe-off-ns = <30>; /* oe-on-ns + tRP + 2 */ + gpmc,access-ns = <30>; /* tCEA + 4*/ + gpmc,rd-cycle-ns = <40>; + gpmc,wr-cycle-ns = <40>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + /* MTD partition table */ + /* All SPL-* partitions are sized to minimal length + * which can be independently programmable. For + * NAND flash this is equal to size of erase-block */ + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + label = "NAND.SPL"; + reg = <0x00000000 0x00040000>; + }; + partition@1 { + label = "NAND.SPL.backup1"; + reg = <0x00040000 0x00040000>; + }; + partition@2 { + label = "NAND.SPL.backup2"; + reg = <0x00080000 0x00040000>; + }; + partition@3 { + label = "NAND.SPL.backup3"; + reg = <0x000C0000 0x00040000>; + }; + partition@4 { + label = "NAND.u-boot-spl-os"; + reg = <0x00100000 0x00080000>; + }; + partition@5 { + label = "NAND.u-boot"; + reg = <0x00180000 0x00100000>; + }; + partition@6 { + label = "NAND.u-boot-env"; + reg = <0x00280000 0x00040000>; + }; + partition@7 { + label = "NAND.u-boot-env.backup1"; + reg = <0x002C0000 0x00040000>; + }; + partition@8 { + label = "NAND.kernel"; + reg = <0x00300000 0x00700000>; + }; + partition@9 { + label = "NAND.file-system"; + reg = <0x00a00000 0x1f600000>; + }; + }; +}; + +&epwmss0 { + status = "okay"; +}; + +&tscadc { + status = "okay"; + + adc { + ti,adc-channels = <0 1 2 3 4 5 6 7>; + }; +}; + +&ecap0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ecap0_pins>; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + status = "okay"; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + status = "okay"; +}; + +&usb2_phy1 { + status = "okay"; +}; + +&usb1 { + dr_mode = "peripheral"; + status = "okay"; +}; + +&usb2_phy2 { + status = "okay"; +}; + +&usb2 { + dr_mode = "host"; + status = "okay"; +}; + +&qspi { + status = "disabled"; /* Disable GPMC (NAND) when enabling QSPI */ + pinctrl-names = "default"; + pinctrl-0 = <&qspi1_default>; + + spi-max-frequency = <48000000>; + m25p80@0 { + compatible = "mx66l51235l"; + spi-max-frequency = <48000000>; + reg = <0>; + spi-cpol; + spi-cpha; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + #address-cells = <1>; + #size-cells = <1>; + + /* MTD partition table. + * The ROM checks the first 512KiB + * for a valid file to boot(XIP). + */ + partition@0 { + label = "QSPI.U_BOOT"; + reg = <0x00000000 0x000080000>; + }; + partition@1 { + label = "QSPI.U_BOOT.backup"; + reg = <0x00080000 0x00080000>; + }; + partition@2 { + label = "QSPI.U-BOOT-SPL_OS"; + reg = <0x00100000 0x00010000>; + }; + partition@3 { + label = "QSPI.U_BOOT_ENV"; + reg = <0x00110000 0x00010000>; + }; + partition@4 { + label = "QSPI.U-BOOT-ENV.backup"; + reg = <0x00120000 0x00010000>; + }; + partition@5 { + label = "QSPI.KERNEL"; + reg = <0x00130000 0x0800000>; + }; + partition@6 { + label = "QSPI.FILESYSTEM"; + reg = <0x00930000 0x36D0000>; + }; + }; +}; + +&hdq { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdq_pins>; +}; + +&dss { + status = "ok"; + + pinctrl-names = "default"; + pinctrl-0 = <&dss_pins>; + + port { + dpi_out: endpoint@0 { + remote-endpoint = <&lcd_in>; + data-lines = <24>; + }; + }; +}; + +&vpfe1 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&vpfe1_pins_default>; + pinctrl-1 = <&vpfe1_pins_sleep>; + + port { + vpfe1_ep: endpoint { + /* remote-endpoint = <&sensor>; add once we have it */ + ti,am437x-vpfe-interface = <0>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; +}; + +&mcasp1 { + #sound-dai-cells = <0>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&mcasp1_pins>; + pinctrl-1 = <&mcasp1_sleep_pins>; + + status = "okay"; + + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; + /* 4 serializer */ + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 1 2 0 0 + >; + tx-num-evt = <32>; + rx-num-evt = <32>; +}; + +&synctimer_32kclk { + assigned-clocks = <&mux_synctimer32k_ck>; + assigned-clock-parents = <&clkdiv32k_ick>; +};
diff --git a/arch/arm/dts/am43xx-clocks.dtsi b/arch/arm/dts/am43xx-clocks.dtsi new file mode 100644 index 0000000..d0c0dfa --- /dev/null +++ b/arch/arm/dts/am43xx-clocks.dtsi
@@ -0,0 +1,757 @@ +/* + * Device Tree Source for AM43xx clock data + * + * Copyright (C) 2013 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +&scm_clocks { + sys_clkin_ck: sys_clkin_ck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&sysboot_freq_sel_ck>, <&crystal_freq_sel_ck>; + ti,bit-shift = <31>; + reg = <0x0040>; + }; + + crystal_freq_sel_ck: crystal_freq_sel_ck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>; + ti,bit-shift = <29>; + reg = <0x0040>; + }; + + sysboot_freq_sel_ck: sysboot_freq_sel_ck@44e10040 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>; + ti,bit-shift = <22>; + reg = <0x0040>; + }; + + adc_tsc_fck: adc_tsc_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + dcan0_fck: dcan0_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + dcan1_fck: dcan1_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + mcasp0_fck: mcasp0_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + mcasp1_fck: mcasp1_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + smartreflex0_fck: smartreflex0_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + smartreflex1_fck: smartreflex1_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + sha0_fck: sha0_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + aes0_fck: aes0_fck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + ehrpwm0_tbclk: ehrpwm0_tbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&l4ls_gclk>; + ti,bit-shift = <0>; + reg = <0x0664>; + }; + + ehrpwm1_tbclk: ehrpwm1_tbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&l4ls_gclk>; + ti,bit-shift = <1>; + reg = <0x0664>; + }; + + ehrpwm2_tbclk: ehrpwm2_tbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&l4ls_gclk>; + ti,bit-shift = <2>; + reg = <0x0664>; + }; + + ehrpwm3_tbclk: ehrpwm3_tbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&l4ls_gclk>; + ti,bit-shift = <4>; + reg = <0x0664>; + }; + + ehrpwm4_tbclk: ehrpwm4_tbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&l4ls_gclk>; + ti,bit-shift = <5>; + reg = <0x0664>; + }; + + ehrpwm5_tbclk: ehrpwm5_tbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&l4ls_gclk>; + ti,bit-shift = <6>; + reg = <0x0664>; + }; +}; +&prcm_clocks { + clk_32768_ck: clk_32768_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_rc32k_ck: clk_rc32k_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + virt_19200000_ck: virt_19200000_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <19200000>; + }; + + virt_24000000_ck: virt_24000000_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + virt_25000000_ck: virt_25000000_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25000000>; + }; + + virt_26000000_ck: virt_26000000_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <26000000>; + }; + + tclkin_ck: tclkin_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <26000000>; + }; + + dpll_core_ck: dpll_core_ck { + #clock-cells = <0>; + compatible = "ti,am3-dpll-core-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x2d20>, <0x2d24>, <0x2d2c>; + }; + + dpll_core_x2_ck: dpll_core_x2_ck { + #clock-cells = <0>; + compatible = "ti,am3-dpll-x2-clock"; + clocks = <&dpll_core_ck>; + }; + + dpll_core_m4_ck: dpll_core_m4_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_core_x2_ck>; + ti,max-div = <31>; + ti,autoidle-shift = <8>; + reg = <0x2d38>; + ti,index-starts-at-one; + ti,invert-autoidle-bit; + }; + + dpll_core_m5_ck: dpll_core_m5_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_core_x2_ck>; + ti,max-div = <31>; + ti,autoidle-shift = <8>; + reg = <0x2d3c>; + ti,index-starts-at-one; + ti,invert-autoidle-bit; + }; + + dpll_core_m6_ck: dpll_core_m6_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_core_x2_ck>; + ti,max-div = <31>; + ti,autoidle-shift = <8>; + reg = <0x2d40>; + ti,index-starts-at-one; + ti,invert-autoidle-bit; + }; + + dpll_mpu_ck: dpll_mpu_ck { + #clock-cells = <0>; + compatible = "ti,am3-dpll-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x2d60>, <0x2d64>, <0x2d6c>; + }; + + dpll_mpu_m2_ck: dpll_mpu_m2_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_mpu_ck>; + ti,max-div = <31>; + ti,autoidle-shift = <8>; + reg = <0x2d70>; + ti,index-starts-at-one; + ti,invert-autoidle-bit; + }; + + dpll_ddr_ck: dpll_ddr_ck { + #clock-cells = <0>; + compatible = "ti,am3-dpll-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x2da0>, <0x2da4>, <0x2dac>; + }; + + dpll_ddr_m2_ck: dpll_ddr_m2_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_ddr_ck>; + ti,max-div = <31>; + ti,autoidle-shift = <8>; + reg = <0x2db0>; + ti,index-starts-at-one; + ti,invert-autoidle-bit; + }; + + dpll_disp_ck: dpll_disp_ck { + #clock-cells = <0>; + compatible = "ti,am3-dpll-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x2e20>, <0x2e24>, <0x2e2c>; + }; + + dpll_disp_m2_ck: dpll_disp_m2_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_disp_ck>; + ti,max-div = <31>; + ti,autoidle-shift = <8>; + reg = <0x2e30>; + ti,index-starts-at-one; + ti,invert-autoidle-bit; + ti,set-rate-parent; + }; + + dpll_per_ck: dpll_per_ck { + #clock-cells = <0>; + compatible = "ti,am3-dpll-j-type-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x2de0>, <0x2de4>, <0x2dec>; + }; + + dpll_per_m2_ck: dpll_per_m2_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_per_ck>; + ti,max-div = <127>; + ti,autoidle-shift = <8>; + reg = <0x2df0>; + ti,index-starts-at-one; + ti,invert-autoidle-bit; + }; + + dpll_per_m2_div4_wkupdm_ck: dpll_per_m2_div4_wkupdm_ck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_per_m2_ck>; + clock-mult = <1>; + clock-div = <4>; + }; + + dpll_per_m2_div4_ck: dpll_per_m2_div4_ck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_per_m2_ck>; + clock-mult = <1>; + clock-div = <4>; + }; + + clk_24mhz: clk_24mhz { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_per_m2_ck>; + clock-mult = <1>; + clock-div = <8>; + }; + + clkdiv32k_ck: clkdiv32k_ck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&clk_24mhz>; + clock-mult = <1>; + clock-div = <732>; + }; + + clkdiv32k_ick: clkdiv32k_ick { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&clkdiv32k_ck>; + ti,bit-shift = <8>; + reg = <0x2a38>; + }; + + sysclk_div: sysclk_div { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + pruss_ocp_gclk: pruss_ocp_gclk { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&sysclk_div>, <&dpll_disp_m2_ck>; + reg = <0x4248>; + }; + + clk_32k_tpm_ck: clk_32k_tpm_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + timer1_fck: timer1_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>, <&clk_32k_tpm_ck>; + reg = <0x4200>; + }; + + timer2_fck: timer2_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; + reg = <0x4204>; + }; + + timer3_fck: timer3_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; + reg = <0x4208>; + }; + + timer4_fck: timer4_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; + reg = <0x420c>; + }; + + timer5_fck: timer5_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; + reg = <0x4210>; + }; + + timer6_fck: timer6_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; + reg = <0x4214>; + }; + + timer7_fck: timer7_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; + reg = <0x4218>; + }; + + wdt1_fck: wdt1_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>; + reg = <0x422c>; + }; + + l3_gclk: l3_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + dpll_core_m4_div2_ck: dpll_core_m4_div2_ck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sysclk_div>; + clock-mult = <1>; + clock-div = <2>; + }; + + l4hs_gclk: l4hs_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + l3s_gclk: l3s_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_div2_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + l4ls_gclk: l4ls_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m4_div2_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + cpsw_125mhz_gclk: cpsw_125mhz_gclk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m5_ck>; + clock-mult = <1>; + clock-div = <2>; + }; + + cpsw_cpts_rft_clk: cpsw_cpts_rft_clk { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&sysclk_div>, <&dpll_core_m5_ck>, <&dpll_disp_m2_ck>; + reg = <0x4238>; + }; + + clk_32k_mosc_ck: clk_32k_mosc_ck { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clkdiv32k_ick>, <&clk_32k_mosc_ck>, <&clk_32k_tpm_ck>; + reg = <0x4240>; + }; + + gpio0_dbclk: gpio0_dbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&gpio0_dbclk_mux_ck>; + ti,bit-shift = <8>; + reg = <0x2b68>; + }; + + gpio1_dbclk: gpio1_dbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&clkdiv32k_ick>; + ti,bit-shift = <8>; + reg = <0x8c78>; + }; + + gpio2_dbclk: gpio2_dbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&clkdiv32k_ick>; + ti,bit-shift = <8>; + reg = <0x8c80>; + }; + + gpio3_dbclk: gpio3_dbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&clkdiv32k_ick>; + ti,bit-shift = <8>; + reg = <0x8c88>; + }; + + gpio4_dbclk: gpio4_dbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&clkdiv32k_ick>; + ti,bit-shift = <8>; + reg = <0x8c90>; + }; + + gpio5_dbclk: gpio5_dbclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&clkdiv32k_ick>; + ti,bit-shift = <8>; + reg = <0x8c98>; + }; + + mmc_clk: mmc_clk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_per_m2_ck>; + clock-mult = <1>; + clock-div = <2>; + }; + + gfx_fclk_clksel_ck: gfx_fclk_clksel_ck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&sysclk_div>, <&dpll_per_m2_ck>; + ti,bit-shift = <1>; + reg = <0x423c>; + }; + + gfx_fck_div_ck: gfx_fck_div_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&gfx_fclk_clksel_ck>; + reg = <0x423c>; + ti,max-div = <2>; + }; + + disp_clk: disp_clk { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>; + reg = <0x4244>; + ti,set-rate-parent; + }; + + dpll_extdev_ck: dpll_extdev_ck { + #clock-cells = <0>; + compatible = "ti,am3-dpll-clock"; + clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; + reg = <0x2e60>, <0x2e64>, <0x2e6c>; + }; + + dpll_extdev_m2_ck: dpll_extdev_m2_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_extdev_ck>; + ti,max-div = <127>; + ti,autoidle-shift = <8>; + reg = <0x2e70>; + ti,index-starts-at-one; + ti,invert-autoidle-bit; + }; + + mux_synctimer32k_ck: mux_synctimer32k_ck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>, <&clkdiv32k_ick>; + reg = <0x4230>; + }; + + synctimer_32kclk: synctimer_32kclk { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&mux_synctimer32k_ck>; + ti,bit-shift = <8>; + reg = <0x2a30>; + }; + + timer8_fck: timer8_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; + reg = <0x421c>; + }; + + timer9_fck: timer9_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; + reg = <0x4220>; + }; + + timer10_fck: timer10_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; + reg = <0x4224>; + }; + + timer11_fck: timer11_fck { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; + reg = <0x4228>; + }; + + cpsw_50m_clkdiv: cpsw_50m_clkdiv { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_core_m5_ck>; + clock-mult = <1>; + clock-div = <1>; + }; + + cpsw_5m_clkdiv: cpsw_5m_clkdiv { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&cpsw_50m_clkdiv>; + clock-mult = <1>; + clock-div = <10>; + }; + + dpll_ddr_x2_ck: dpll_ddr_x2_ck { + #clock-cells = <0>; + compatible = "ti,am3-dpll-x2-clock"; + clocks = <&dpll_ddr_ck>; + }; + + dpll_ddr_m4_ck: dpll_ddr_m4_ck { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_ddr_x2_ck>; + ti,max-div = <31>; + ti,autoidle-shift = <8>; + reg = <0x2db8>; + ti,index-starts-at-one; + ti,invert-autoidle-bit; + }; + + dpll_per_clkdcoldo: dpll_per_clkdcoldo { + #clock-cells = <0>; + compatible = "ti,fixed-factor-clock"; + clocks = <&dpll_per_ck>; + ti,clock-mult = <1>; + ti,clock-div = <1>; + ti,autoidle-shift = <8>; + reg = <0x2e14>; + ti,invert-autoidle-bit; + }; + + dll_aging_clk_div: dll_aging_clk_div { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&sys_clkin_ck>; + reg = <0x4250>; + ti,dividers = <8>, <16>, <32>; + }; + + div_core_25m_ck: div_core_25m_ck { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sysclk_div>; + clock-mult = <1>; + clock-div = <8>; + }; + + func_12m_clk: func_12m_clk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&dpll_per_m2_ck>; + clock-mult = <1>; + clock-div = <16>; + }; + + vtp_clk_div: vtp_clk_div { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&sys_clkin_ck>; + clock-mult = <1>; + clock-div = <2>; + }; + + usbphy_32khz_clkmux: usbphy_32khz_clkmux { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>; + reg = <0x4260>; + }; + + usb_phy0_always_on_clk32k: usb_phy0_always_on_clk32k { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&usbphy_32khz_clkmux>; + ti,bit-shift = <8>; + reg = <0x2a40>; + }; + + usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&usbphy_32khz_clkmux>; + ti,bit-shift = <8>; + reg = <0x2a48>; + }; + + usb_otg_ss0_refclk960m: usb_otg_ss0_refclk960m { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&dpll_per_clkdcoldo>; + ti,bit-shift = <8>; + reg = <0x8a60>; + }; + + usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&dpll_per_clkdcoldo>; + ti,bit-shift = <8>; + reg = <0x8a68>; + }; +};
diff --git a/arch/arm/dts/am571x-idk.dts b/arch/arm/dts/am571x-idk.dts new file mode 100644 index 0000000..debf946 --- /dev/null +++ b/arch/arm/dts/am571x-idk.dts
@@ -0,0 +1,119 @@ +/* + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +#include "dra72x.dtsi" +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include "am57xx-idk-common.dtsi" +#include "dra72x-mmc-iodelay.dtsi" + +/ { + model = "TI AM5718 IDK"; + compatible = "ti,am5718-idk", "ti,am5718", "ti,dra7"; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x40000000>; + }; + + leds { + compatible = "gpio-leds"; + cpu0-led { + label = "status0:red:cpu0"; + gpios = <&gpio2 25 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "cpu0"; + }; + + usr0-led { + label = "status0:green:usr"; + gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + heartbeat-led { + label = "status0:blue:heartbeat"; + gpios = <&gpio2 27 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "heartbeat"; + }; + + usr1-led { + label = "status1:red:usr"; + gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + usr2-led { + label = "status1:green:usr"; + gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + mmc0-led { + label = "status1:blue:mmc0"; + gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "mmc0"; + }; + }; +}; + +&omap_dwc3_2 { + extcon = <&extcon_usb2>; +}; + +&extcon_usb2 { + id-gpio = <&gpio5 7 GPIO_ACTIVE_HIGH>; + vbus-gpio = <&gpio7 22 GPIO_ACTIVE_HIGH>; +}; + +&mailbox5 { + status = "okay"; + mbox_ipu1_ipc3x: mbox_ipu1_ipc3x { + status = "okay"; + }; + mbox_dsp1_ipc3x: mbox_dsp1_ipc3x { + status = "okay"; + }; +}; + +&mailbox6 { + status = "okay"; + mbox_ipu2_ipc3x: mbox_ipu2_ipc3x { + status = "okay"; + }; +}; + +&pcie1_rc { + status = "okay"; + gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>; +}; + +&pcie1_ep { + gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>; +}; + +&mmc1 { + pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104"; + pinctrl-0 = <&mmc1_pins_default>; + pinctrl-1 = <&mmc1_pins_hs>; + pinctrl-2 = <&mmc1_pins_sdr12>; + pinctrl-3 = <&mmc1_pins_sdr25>; + pinctrl-4 = <&mmc1_pins_sdr50>; + pinctrl-5 = <&mmc1_pins_ddr50_rev20 &mmc1_iodelay_ddr50_conf>; + pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>; +}; + +&mmc2 { + pinctrl-names = "default", "hs", "ddr_1_8v"; + pinctrl-0 = <&mmc2_pins_default>; + pinctrl-1 = <&mmc2_pins_hs>; + pinctrl-2 = <&mmc2_pins_ddr_rev20 &mmc2_iodelay_ddr_conf>; +};
diff --git a/arch/arm/dts/am572x-idk-common.dtsi b/arch/arm/dts/am572x-idk-common.dtsi new file mode 100644 index 0000000..c6d858b --- /dev/null +++ b/arch/arm/dts/am572x-idk-common.dtsi
@@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include "am57xx-idk-common.dtsi" + +/ { + memory@0 { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x80000000>; + }; + + status-leds { + compatible = "gpio-leds"; + cpu0-led { + label = "status0:red:cpu0"; + gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "cpu0"; + }; + + usr0-led { + label = "status0:green:usr"; + gpios = <&gpio3 11 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + heartbeat-led { + label = "status0:blue:heartbeat"; + gpios = <&gpio3 12 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "heartbeat"; + }; + + cpu1-led { + label = "status1:red:cpu1"; + gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "cpu1"; + }; + + usr1-led { + label = "status1:green:usr"; + gpios = <&gpio7 23 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + mmc0-led { + label = "status1:blue:mmc0"; + gpios = <&gpio7 22 GPIO_ACTIVE_HIGH>; + default-state = "off"; + linux,default-trigger = "mmc0"; + }; + }; +}; + +&omap_dwc3_2 { + extcon = <&extcon_usb2>; +}; + +&extcon_usb2 { + id-gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>; + vbus-gpio = <&gpio3 26 GPIO_ACTIVE_HIGH>; +}; + +&sn65hvs882 { + load-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; +}; + +&pcie1_rc { + status = "okay"; + gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>; +}; + +&pcie1_ep { + gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>; +}; + +&mailbox5 { + status = "okay"; + mbox_ipu1_ipc3x: mbox_ipu1_ipc3x { + status = "okay"; + }; + mbox_dsp1_ipc3x: mbox_dsp1_ipc3x { + status = "okay"; + }; +}; + +&mailbox6 { + status = "okay"; + mbox_ipu2_ipc3x: mbox_ipu2_ipc3x { + status = "okay"; + }; + mbox_dsp2_ipc3x: mbox_dsp2_ipc3x { + status = "okay"; + }; +};
diff --git a/arch/arm/dts/am572x-idk.dts b/arch/arm/dts/am572x-idk.dts new file mode 100644 index 0000000..9212931 --- /dev/null +++ b/arch/arm/dts/am572x-idk.dts
@@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +/dts-v1/; + +#include "dra74x.dtsi" +#include "am572x-idk-common.dtsi" +#include "am57xx-idk-common.dtsi" +#include "dra74x-mmc-iodelay.dtsi" + +/ { + model = "TI AM5728 IDK"; + compatible = "ti,am5728-idk", "ti,am5728", "ti,dra742", "ti,dra74", + "ti,dra7"; +}; + +&mmc1 { + pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104"; + pinctrl-0 = <&mmc1_pins_default>; + pinctrl-1 = <&mmc1_pins_hs>; + pinctrl-2 = <&mmc1_pins_sdr12>; + pinctrl-3 = <&mmc1_pins_sdr25>; + pinctrl-4 = <&mmc1_pins_sdr50>; + pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev20_conf>; + pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>; +}; + +&mmc2 { + pinctrl-names = "default", "hs", "ddr_1_8v"; + pinctrl-0 = <&mmc2_pins_default>; + pinctrl-1 = <&mmc2_pins_hs>; + pinctrl-2 = <&mmc2_pins_ddr_rev20>; +};
diff --git a/arch/arm/dts/am574x-idk.dts b/arch/arm/dts/am574x-idk.dts new file mode 100644 index 0000000..41e12a3 --- /dev/null +++ b/arch/arm/dts/am574x-idk.dts
@@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + */ + + +/dts-v1/; + +#include "dra76x.dtsi" +#include "am572x-idk-common.dtsi" + +/ { + model = "TI AM5748 IDK"; + compatible = "ti,am5728-idk", "ti,dra762", "ti,dra7"; +}; + +&qspi { + spi-max-frequency = <96000000>; + m25p80@0 { + spi-max-frequency = <96000000>; + }; +};
diff --git a/arch/arm/dts/am57xx-beagle-x15-common.dtsi b/arch/arm/dts/am57xx-beagle-x15-common.dtsi new file mode 100644 index 0000000..49aeecd --- /dev/null +++ b/arch/arm/dts/am57xx-beagle-x15-common.dtsi
@@ -0,0 +1,589 @@ +/* + * Copyright (C) 2014-2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ +/dts-v1/; + +#include "dra74x.dtsi" +#include "am57xx-commercial-grade.dtsi" +#include "dra74x-mmc-iodelay.dtsi" +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/irq.h> + +/ { + compatible = "ti,am572x-beagle-x15", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7"; + + aliases { + rtc0 = &mcp_rtc; + rtc1 = &tps659038_rtc; + rtc2 = &rtc; + display0 = &hdmi0; + }; + + chosen { + stdout-path = &uart3; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x80000000>; + }; + + vdd_3v3: fixedregulator-vdd_3v3 { + compatible = "regulator-fixed"; + regulator-name = "vdd_3v3"; + vin-supply = <®en1>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + aic_dvdd: fixedregulator-aic_dvdd { + compatible = "regulator-fixed"; + regulator-name = "aic_dvdd_fixed"; + vin-supply = <&vdd_3v3>; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vtt_fixed: fixedregulator-vtt { + /* TPS51200 */ + compatible = "regulator-fixed"; + regulator-name = "vtt_fixed"; + vin-supply = <&smps3_reg>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + enable-active-high; + gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>; + }; + + leds { + compatible = "gpio-leds"; + + led0 { + label = "beagle-x15:usr0"; + gpios = <&gpio7 9 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + + led1 { + label = "beagle-x15:usr1"; + gpios = <&gpio7 8 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "cpu0"; + default-state = "off"; + }; + + led2 { + label = "beagle-x15:usr2"; + gpios = <&gpio7 14 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + default-state = "off"; + }; + + led3 { + label = "beagle-x15:usr3"; + gpios = <&gpio7 15 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "disk-activity"; + default-state = "off"; + }; + }; + + gpio_fan: gpio_fan { + /* Based on 5v 500mA AFB02505HHB */ + compatible = "gpio-fan"; + gpios = <&tps659038_gpio 2 GPIO_ACTIVE_HIGH>; + gpio-fan,speed-map = <0 0>, + <13000 1>; + #cooling-cells = <2>; + }; + + hdmi0: connector { + compatible = "hdmi-connector"; + label = "hdmi"; + + type = "a"; + + port { + hdmi_connector_in: endpoint { + remote-endpoint = <&tpd12s015_out>; + }; + }; + }; + + tpd12s015: encoder { + compatible = "ti,tpd12s015"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tpd12s015_in: endpoint { + remote-endpoint = <&hdmi_out>; + }; + }; + + port@1 { + reg = <1>; + + tpd12s015_out: endpoint { + remote-endpoint = <&hdmi_connector_in>; + }; + }; + }; + }; + + sound0: sound0 { + compatible = "simple-audio-card"; + simple-audio-card,name = "BeagleBoard-X15"; + simple-audio-card,widgets = + "Line", "Line Out", + "Line", "Line In"; + simple-audio-card,routing = + "Line Out", "LLOUT", + "Line Out", "RLOUT", + "MIC2L", "Line In", + "MIC2R", "Line In"; + simple-audio-card,format = "dsp_b"; + simple-audio-card,bitclock-master = <&sound0_master>; + simple-audio-card,frame-master = <&sound0_master>; + simple-audio-card,bitclock-inversion; + + simple-audio-card,cpu { + sound-dai = <&mcasp3>; + }; + + sound0_master: simple-audio-card,codec { + sound-dai = <&tlv320aic3104>; + clocks = <&clkout2_clk>; + }; + }; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <400000>; + + tps659038: tps659038@58 { + compatible = "ti,tps659038"; + reg = <0x58>; + interrupt-parent = <&gpio1>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + + #interrupt-cells = <2>; + interrupt-controller; + + ti,system-power-controller; + ti,palmas-override-powerhold; + + tps659038_pmic { + compatible = "ti,tps659038-pmic"; + + regulators { + smps12_reg: smps12 { + /* VDD_MPU */ + regulator-name = "smps12"; + regulator-min-microvolt = < 850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps3_reg: smps3 { + /* VDD_DDR */ + regulator-name = "smps3"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + }; + + smps45_reg: smps45 { + /* VDD_DSPEVE, VDD_IVA, VDD_GPU */ + regulator-name = "smps45"; + regulator-min-microvolt = < 850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps6_reg: smps6 { + /* VDD_CORE */ + regulator-name = "smps6"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1150000>; + regulator-always-on; + regulator-boot-on; + }; + + /* SMPS7 unused */ + + smps8_reg: smps8 { + /* VDD_1V8 */ + regulator-name = "smps8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + /* SMPS9 unused */ + + ldo1_reg: ldo1 { + /* VDD_SD / VDDSHV8 */ + regulator-name = "ldo1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo2_reg: ldo2 { + /* VDD_SHV5 */ + regulator-name = "ldo2"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo3_reg: ldo3 { + /* VDDA_1V8_PHYA */ + regulator-name = "ldo3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo4_reg: ldo4 { + /* VDDA_1V8_PHYB */ + regulator-name = "ldo4"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo9_reg: ldo9 { + /* VDD_RTC */ + regulator-name = "ldo9"; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; + regulator-always-on; + regulator-boot-on; + }; + + ldoln_reg: ldoln { + /* VDDA_1V8_PLL */ + regulator-name = "ldoln"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldousb_reg: ldousb { + /* VDDA_3V_USB: VDDA_USBHS33 */ + regulator-name = "ldousb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + regen1: regen1 { + /* VDD_3V3_ON */ + regulator-name = "regen1"; + regulator-boot-on; + regulator-always-on; + }; + }; + }; + + tps659038_rtc: tps659038_rtc { + compatible = "ti,palmas-rtc"; + interrupt-parent = <&tps659038>; + interrupts = <8 IRQ_TYPE_EDGE_FALLING>; + wakeup-source; + }; + + tps659038_pwr_button: tps659038_pwr_button { + compatible = "ti,palmas-pwrbutton"; + interrupt-parent = <&tps659038>; + interrupts = <1 IRQ_TYPE_EDGE_FALLING>; + wakeup-source; + ti,palmas-long-press-seconds = <12>; + }; + + tps659038_gpio: tps659038_gpio { + compatible = "ti,palmas-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + + extcon_usb2: tps659038_usb { + compatible = "ti,palmas-usb-vid"; + ti,enable-vbus-detection; + vbus-gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>; + }; + + }; + + tmp102: tmp102@48 { + compatible = "ti,tmp102"; + reg = <0x48>; + interrupt-parent = <&gpio7>; + interrupts = <16 IRQ_TYPE_LEVEL_LOW>; + #thermal-sensor-cells = <1>; + }; + + tlv320aic3104: tlv320aic3104@18 { + #sound-dai-cells = <0>; + compatible = "ti,tlv320aic3104"; + reg = <0x18>; + assigned-clocks = <&clkoutmux2_clk_mux>; + assigned-clock-parents = <&sys_clk2_dclk_div>; + + status = "okay"; + adc-settle-ms = <40>; + + AVDD-supply = <&vdd_3v3>; + IOVDD-supply = <&vdd_3v3>; + DRVDD-supply = <&vdd_3v3>; + DVDD-supply = <&aic_dvdd>; + }; + + eeprom: eeprom@50 { + compatible = "atmel,24c32"; + reg = <0x50>; + }; +}; + +&i2c3 { + status = "okay"; + clock-frequency = <400000>; + + mcp_rtc: rtc@6f { + compatible = "microchip,mcp7941x"; + reg = <0x6f>; + interrupts-extended = <&crossbar_mpu GIC_SPI 2 IRQ_TYPE_EDGE_RISING>, + <&dra7_pmx_core 0x424>; + interrupt-names = "irq", "wakeup"; + + vcc-supply = <&vdd_3v3>; + wakeup-source; + }; +}; + +&gpio7 { + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&cpu0 { + cpu0-supply = <&smps12_reg>; + voltage-tolerance = <1>; +}; + +&uart3 { + status = "okay"; + interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>, + <&dra7_pmx_core 0x3f8>; +}; + +&davinci_mdio { + phy0: ethernet-phy@1 { + reg = <1>; + }; + + phy1: ethernet-phy@2 { + reg = <2>; + }; +}; + +&mac { + status = "okay"; + dual_emac; +}; + +&cpsw_emac0 { + phy-handle = <&phy0>; + phy-mode = "rgmii"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy-handle = <&phy1>; + phy-mode = "rgmii"; + dual_emac_res_vlan = <2>; +}; + +&mmc1 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins_default>; + + bus-width = <4>; + cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; /* gpio 219 */ +}; + +&mmc2 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins_default>; + + vmmc-supply = <&vdd_3v3>; + bus-width = <8>; + ti,non-removable; + cap-mmc-dual-data-rate; +}; + +&sata { + status = "okay"; +}; + +&usb2_phy1 { + phy-supply = <&ldousb_reg>; +}; + +&usb2_phy2 { + phy-supply = <&ldousb_reg>; +}; + +&usb1 { + dr_mode = "host"; +}; + +&omap_dwc3_2 { + extcon = <&extcon_usb2>; +}; + +&usb2 { + /* + * Stand alone usage is peripheral only. + * However, with some resistor modifications + * this port can be used via expansion connectors + * as "host" or "dual-role". If so, provide + * the necessary dr_mode override in the expansion + * board's DT. + */ + dr_mode = "peripheral"; +}; + +&cpu_trips { + cpu_alert1: cpu_alert1 { + temperature = <50000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "active"; + }; +}; + +&cpu_cooling_maps { + map1 { + trip = <&cpu_alert1>; + cooling-device = <&gpio_fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; +}; + +&thermal_zones { + board_thermal: board_thermal { + polling-delay-passive = <1250>; /* milliseconds */ + polling-delay = <1500>; /* milliseconds */ + + /* sensor ID */ + thermal-sensors = <&tmp102 0>; + + board_trips: trips { + board_alert0: board_alert { + temperature = <40000>; /* millicelsius */ + hysteresis = <2000>; /* millicelsius */ + type = "active"; + }; + + board_crit: board_crit { + temperature = <105000>; /* millicelsius */ + hysteresis = <0>; /* millicelsius */ + type = "critical"; + }; + }; + + board_cooling_maps: cooling-maps { + map0 { + trip = <&board_alert0>; + cooling-device = + <&gpio_fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; +}; + +&dss { + status = "ok"; + + vdda_video-supply = <&ldoln_reg>; +}; + +&hdmi { + status = "ok"; + vdda-supply = <&ldo4_reg>; + + port { + hdmi_out: endpoint { + remote-endpoint = <&tpd12s015_in>; + }; + }; +}; + +&pcie1_rc { + status = "ok"; + gpios = <&gpio2 8 GPIO_ACTIVE_LOW>; +}; + +&pcie1_ep { + gpios = <&gpio2 8 GPIO_ACTIVE_LOW>; +}; + +&mcasp3 { + #sound-dai-cells = <0>; + assigned-clocks = <&mcasp3_ahclkx_mux>; + assigned-clock-parents = <&sys_clkin2>; + status = "okay"; + + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; + /* 4 serializers */ + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 1 2 0 0 + >; + tx-num-evt = <32>; + rx-num-evt = <32>; +}; + +&mailbox5 { + status = "okay"; + mbox_ipu1_ipc3x: mbox_ipu1_ipc3x { + status = "okay"; + }; + mbox_dsp1_ipc3x: mbox_dsp1_ipc3x { + status = "okay"; + }; +}; + +&mailbox6 { + status = "okay"; + mbox_ipu2_ipc3x: mbox_ipu2_ipc3x { + status = "okay"; + }; + mbox_dsp2_ipc3x: mbox_dsp2_ipc3x { + status = "okay"; + }; +};
diff --git a/arch/arm/dts/am57xx-beagle-x15-revb1.dts b/arch/arm/dts/am57xx-beagle-x15-revb1.dts new file mode 100644 index 0000000..5a77b33 --- /dev/null +++ b/arch/arm/dts/am57xx-beagle-x15-revb1.dts
@@ -0,0 +1,44 @@ +/* + * Copyright (C) 2014-2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +#include "am57xx-beagle-x15-common.dtsi" + +/ { + model = "TI AM5728 BeagleBoard-X15 rev B1"; +}; + +&tpd12s015 { + gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>, /* gpio7_10, CT CP HPD */ + <&gpio2 30 GPIO_ACTIVE_HIGH>, /* gpio2_30, LS OE */ + <&gpio7 12 GPIO_ACTIVE_HIGH>; /* gpio7_12/sp1_cs2, HPD */ +}; + +&mmc1 { + pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104"; + pinctrl-0 = <&mmc1_pins_default>; + pinctrl-1 = <&mmc1_pins_hs>; + pinctrl-2 = <&mmc1_pins_sdr12>; + pinctrl-3 = <&mmc1_pins_sdr25>; + pinctrl-4 = <&mmc1_pins_sdr50>; + pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev11_conf>; + pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev11_conf>; + vmmc-supply = <&vdd_3v3>; + vqmmc-supply = <&ldo1_reg>; +}; + +&mmc2 { + pinctrl-names = "default", "hs", "ddr_1_8v"; + pinctrl-0 = <&mmc2_pins_default>; + pinctrl-1 = <&mmc2_pins_hs>; + pinctrl-2 = <&mmc2_pins_ddr_3_3v_rev11 &mmc2_iodelay_ddr_3_3v_rev11_conf>; +}; + +/* errata i880 "Ethernet RGMII2 Limited to 10/100 Mbps" */ +&phy1 { + max-speed = <100>; +};
diff --git a/arch/arm/dts/am57xx-beagle-x15-revc.dts b/arch/arm/dts/am57xx-beagle-x15-revc.dts new file mode 100644 index 0000000..17c41da --- /dev/null +++ b/arch/arm/dts/am57xx-beagle-x15-revc.dts
@@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +#include "am57xx-beagle-x15-common.dtsi" + +/ { + model = "TI AM5728 BeagleBoard-X15 rev C"; +}; + +&tpd12s015 { + gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>, /* gpio7_10, CT CP HPD */ + <&gpio2 30 GPIO_ACTIVE_HIGH>, /* gpio2_30, LS OE */ + <&gpio7 12 GPIO_ACTIVE_HIGH>; /* gpio7_12/sp1_cs2, HPD */ +}; + +&mmc1 { + pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104"; + pinctrl-0 = <&mmc1_pins_default>; + pinctrl-1 = <&mmc1_pins_hs>; + pinctrl-2 = <&mmc1_pins_sdr12>; + pinctrl-3 = <&mmc1_pins_sdr25>; + pinctrl-4 = <&mmc1_pins_sdr50>; + pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_rev20_conf>; + pinctrl-6 = <&mmc1_pins_sdr104 &mmc1_iodelay_sdr104_rev20_conf>; + vmmc-supply = <&vdd_3v3>; + vqmmc-supply = <&ldo1_reg>; +}; + +&mmc2 { + pinctrl-names = "default", "hs", "ddr_1_8v"; + pinctrl-0 = <&mmc2_pins_default>; + pinctrl-1 = <&mmc2_pins_hs>; + pinctrl-2 = <&mmc2_pins_ddr_rev20>; +};
diff --git a/arch/arm/dts/am57xx-beagle-x15.dts b/arch/arm/dts/am57xx-beagle-x15.dts new file mode 100644 index 0000000..8d9bdf1 --- /dev/null +++ b/arch/arm/dts/am57xx-beagle-x15.dts
@@ -0,0 +1,46 @@ +/* + * Copyright (C) 2014-2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +#include "am57xx-beagle-x15-common.dtsi" + +/ { + /* NOTE: This describes the "original" pre-production A2 revision */ + model = "TI AM5728 BeagleBoard-X15"; +}; + +&tpd12s015 { + gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>, /* gpio7_10, CT CP HPD */ + <&gpio6 28 GPIO_ACTIVE_HIGH>, /* gpio6_28, LS OE */ + <&gpio7 12 GPIO_ACTIVE_HIGH>; /* gpio7_12/sp1_cs2, HPD */ +}; + +&mmc1 { + pinctrl-names = "default", "hs"; + pinctrl-0 = <&mmc1_pins_default>; + pinctrl-1 = <&mmc1_pins_hs>; + + vmmc-supply = <&ldo1_reg>; + /delete-property/ sd-uhs-sdr104; + /delete-property/ sd-uhs-sdr50; + /delete-property/ sd-uhs-ddr50; + /delete-property/ sd-uhs-sdr25; + /delete-property/ sd-uhs-sdr12; +}; + +&mmc2 { + pinctrl-names = "default", "hs", "ddr_1_8v"; + pinctrl-0 = <&mmc2_pins_default>; + pinctrl-1 = <&mmc2_pins_hs>; + pinctrl-2 = <&mmc2_pins_ddr_3_3v_rev11 &mmc2_iodelay_ddr_3_3v_rev11_conf>; + /delete-property/ mmc-hs200-1_8v; +}; + +/* errata i880 "Ethernet RGMII2 Limited to 10/100 Mbps" */ +&phy1 { + max-speed = <100>; +};
diff --git a/arch/arm/dts/am57xx-cl-som-am57x.dts b/arch/arm/dts/am57xx-cl-som-am57x.dts new file mode 100644 index 0000000..203266f --- /dev/null +++ b/arch/arm/dts/am57xx-cl-som-am57x.dts
@@ -0,0 +1,617 @@ +/* + * Support for CompuLab CL-SOM-AM57x System-on-Module + * + * Copyright (C) 2015 CompuLab Ltd. - http://www.compulab.co.il/ + * Author: Dmitry Lifshitz <lifshitz@compulab.co.il> + * + * 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. + */ + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include "dra74x.dtsi" + +/ { + model = "CompuLab CL-SOM-AM57x"; + compatible = "compulab,cl-som-am57x", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x20000000>; /* 512 MB - minimal configuration */ + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&leds_pins_default>; + + led0 { + label = "cl-som-am57x:green"; + gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + }; + + vdd_3v3: fixedregulator-vdd_3v3 { + compatible = "regulator-fixed"; + regulator-name = "vdd_3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + ads7846reg: fixedregulator-ads7846-reg { + compatible = "regulator-fixed"; + regulator-name = "ads7846-reg"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + sound0: sound0 { + compatible = "simple-audio-card"; + simple-audio-card,name = "CL-SOM-AM57x-Sound-Card"; + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&dailink0_master>; + simple-audio-card,frame-master = <&dailink0_master>; + simple-audio-card,widgets = + "Headphone", "Headphone Jack", + "Microphone", "Microphone Jack", + "Line", "Line Jack"; + simple-audio-card,routing = + "Headphone Jack", "RHPOUT", + "Headphone Jack", "LHPOUT", + "LLINEIN", "Line Jack", + "MICIN", "Mic Bias", + "Mic Bias", "Microphone Jack"; + + dailink0_master: simple-audio-card,cpu { + sound-dai = <&mcasp3>; + }; + + simple-audio-card,codec { + sound-dai = <&wm8731>; + system-clock-frequency = <12000000>; + }; + }; +}; + +&dra7_pmx_core { + leds_pins_default: leds_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x347c, PIN_OUTPUT | MUX_MODE14) /* gpmc_a15.gpio2_5 */ + >; + }; + + i2c1_pins_default: i2c1_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3800, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda.sda */ + DRA7XX_CORE_IOPAD(0x3804, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl.scl */ + >; + }; + + i2c3_pins_default: i2c3_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x36a4, PIN_INPUT| MUX_MODE10) /* mcasp1_aclkx.i2c3_sda */ + DRA7XX_CORE_IOPAD(0x36a8, PIN_INPUT| MUX_MODE10) /* mcasp1_fsx.i2c3_scl */ + >; + }; + + i2c4_pins_default: i2c4_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x36ac, PIN_INPUT| MUX_MODE10) /* mcasp1_acl.i2c4_sda */ + DRA7XX_CORE_IOPAD(0x36b0, PIN_INPUT| MUX_MODE10) /* mcasp1_fsr.i2c4_scl */ + >; + }; + + tps659038_pins_default: tps659038_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3818, PIN_INPUT_PULLUP | MUX_MODE14) /* wakeup0.gpio1_0 */ + >; + }; + + mmc2_pins_default: mmc2_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */ + DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */ + DRA7XX_CORE_IOPAD(0x34a0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */ + DRA7XX_CORE_IOPAD(0x34a4, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */ + DRA7XX_CORE_IOPAD(0x34a8, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */ + DRA7XX_CORE_IOPAD(0x34ac, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */ + DRA7XX_CORE_IOPAD(0x348c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */ + DRA7XX_CORE_IOPAD(0x3490, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */ + DRA7XX_CORE_IOPAD(0x3494, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */ + DRA7XX_CORE_IOPAD(0x3498, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */ + >; + }; + + qspi1_pins: pinmux_qspi1_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3474, PIN_INPUT | MUX_MODE1) /* gpmc_a13.qspi1_rtclk */ + DRA7XX_CORE_IOPAD(0x3480, PIN_INPUT | MUX_MODE1) /* gpmc_a16.qspi1_d0 */ + DRA7XX_CORE_IOPAD(0x3484, PIN_INPUT | MUX_MODE1) /* gpmc_a17.qspi1_d1 */ + DRA7XX_CORE_IOPAD(0x3488, PIN_INPUT | MUX_MODE1) /* qpmc_a18.qspi1_sclk */ + DRA7XX_CORE_IOPAD(0x34b8, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs2.qspi1_cs0 */ + DRA7XX_CORE_IOPAD(0x34bc, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs3.qspi1_cs1 */ + >; + }; + + cpsw_pins_default: cpsw_pins_default { + pinctrl-single,pins = < + /* Slave at addr 0x0 */ + DRA7XX_CORE_IOPAD(0x3650, PIN_OUTPUT | MUX_MODE0) /* rgmii0_tclk */ + DRA7XX_CORE_IOPAD(0x3654, PIN_OUTPUT | MUX_MODE0) /* rgmii0_tctl */ + DRA7XX_CORE_IOPAD(0x3658, PIN_OUTPUT | MUX_MODE0) /* rgmii0_td3 */ + DRA7XX_CORE_IOPAD(0x365c, PIN_OUTPUT | MUX_MODE0) /* rgmii0_td2 */ + DRA7XX_CORE_IOPAD(0x3660, PIN_OUTPUT | MUX_MODE0) /* rgmii0_td1 */ + DRA7XX_CORE_IOPAD(0x3664, PIN_OUTPUT | MUX_MODE0) /* rgmii0_td0 */ + DRA7XX_CORE_IOPAD(0x3668, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rclk */ + DRA7XX_CORE_IOPAD(0x366c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rctl */ + DRA7XX_CORE_IOPAD(0x3670, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rd3 */ + DRA7XX_CORE_IOPAD(0x3674, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rd2 */ + DRA7XX_CORE_IOPAD(0x3678, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rd1 */ + DRA7XX_CORE_IOPAD(0x367c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rgmii0_rd0 */ + + /* Slave at addr 0x1 */ + DRA7XX_CORE_IOPAD(0x3598, PIN_OUTPUT | MUX_MODE3) /* vin2a_d12.rgmii1_tclk */ + DRA7XX_CORE_IOPAD(0x359c, PIN_OUTPUT | MUX_MODE3) /* vin2a_d13.rgmii1_tctl */ + DRA7XX_CORE_IOPAD(0x35a0, PIN_OUTPUT | MUX_MODE3) /* vin2a_d14.rgmii1_td3 */ + DRA7XX_CORE_IOPAD(0x35a4, PIN_OUTPUT | MUX_MODE3) /* vin2a_d15.rgmii1_td2 */ + DRA7XX_CORE_IOPAD(0x35a8, PIN_OUTPUT | MUX_MODE3) /* vin2a_d16.rgmii1_td1 */ + DRA7XX_CORE_IOPAD(0x35ac, PIN_OUTPUT | MUX_MODE3) /* vin2a_d17.rgmii1_td0 */ + DRA7XX_CORE_IOPAD(0x35b0, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d18.rgmii1_rclk */ + DRA7XX_CORE_IOPAD(0x35b4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d19.rgmii1_rctl */ + DRA7XX_CORE_IOPAD(0x35b8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d20.rgmii1_rd3 */ + DRA7XX_CORE_IOPAD(0x35bc, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d21.rgmii1_rd2 */ + DRA7XX_CORE_IOPAD(0x35c0, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d22.rgmii1_rd1 */ + DRA7XX_CORE_IOPAD(0x35c4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* vin2a_d23.rgmii1_rd0 */ + >; + }; + + cpsw_pins_sleep: cpsw_pins_sleep { + pinctrl-single,pins = < + /* Slave 1 */ + DRA7XX_CORE_IOPAD(0x3650, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3654, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3658, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x365c, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3660, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3664, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3668, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x366c, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3670, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3674, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3678, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x367c, PIN_INPUT | MUX_MODE15) + + /* Slave 2 */ + DRA7XX_CORE_IOPAD(0x3598, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x359c, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35a0, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35a4, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35a8, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35ac, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35b0, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35b4, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35b8, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35bc, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35c0, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x35c4, PIN_INPUT | MUX_MODE15) + >; + }; + + davinci_mdio_pins_default: davinci_mdio_pins_default { + pinctrl-single,pins = < + /* MDIO */ + DRA7XX_CORE_IOPAD(0x3590, PIN_OUTPUT_PULLUP | MUX_MODE3)/* vin2a_d10.mdio_mclk */ + DRA7XX_CORE_IOPAD(0x3594, PIN_INPUT_PULLUP | MUX_MODE3) /* vin2a_d11.mdio_d */ + >; + }; + + davinci_mdio_pins_sleep: davinci_mdio_pins_sleep { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3590, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3594, PIN_INPUT | MUX_MODE15) + >; + }; + + ads7846_pins: pinmux_ads7846_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3464, PIN_INPUT_PULLDOWN | MUX_MODE14) /* gpmc_a9.gpio1_31 */ + >; + }; + + mcasp3_pins_default: mcasp3_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3724, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp3_aclkx.mcasp3_aclkx */ + DRA7XX_CORE_IOPAD(0x3728, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp3_fsx.mcasp3_fsx */ + DRA7XX_CORE_IOPAD(0x372c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp3_axr0.mcasp3_axr0 */ + DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp3_axr1.mcasp3_axr1 */ + >; + }; + + mcasp3_pins_sleep: mcasp3_pins_sleep { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3724, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3728, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x372c, PIN_INPUT | MUX_MODE15) + DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT | MUX_MODE15) + >; + }; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_default>; + clock-frequency = <400000>; +}; + +&i2c3 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins_default>; + clock-frequency = <400000>; +}; + +&i2c4 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_default>; + clock-frequency = <400000>; + + tps659038: tps659038@58 { + compatible = "ti,tps659038"; + reg = <0x58>; + interrupt-parent = <&gpio1>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-names = "default"; + pinctrl-0 = <&tps659038_pins_default>; + + #interrupt-cells = <2>; + interrupt-controller; + + ti,system-power-controller; + + tps659038_pmic { + compatible = "ti,tps659038-pmic"; + + regulators { + smps12_reg: smps12 { + /* VDD_MPU */ + regulator-name = "smps12"; + regulator-min-microvolt = < 850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps3_reg: smps3 { + /* VDD_DDR */ + regulator-name = "smps3"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + }; + + smps45_reg: smps45 { + /* VDD_DSPEVE */ + regulator-name = "smps45"; + regulator-min-microvolt = < 850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps6_reg: smps6 { + /* VDD_GPU */ + regulator-name = "smps6"; + regulator-min-microvolt = < 850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps7_reg: smps7 { + /* VDD_CORE */ + regulator-name = "smps7"; + regulator-min-microvolt = < 850000>; + regulator-max-microvolt = <1160000>; + regulator-always-on; + regulator-boot-on; + }; + + smps8_reg: smps8 { + /* VDD_IVA */ + regulator-name = "smps8"; + regulator-min-microvolt = < 850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps9_reg: smps9 { + /* PMIC_3V3 */ + regulator-name = "smps9"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + + ldo1_reg: ldo1 { + /* VDD_SD / VDDSHV8 */ + regulator-name = "ldo1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo2_reg: ldo2 { + /* VDD_1V8 */ + regulator-name = "ldo2"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo3_reg: ldo3 { + /* VDDA_1V8_PHYA - supplies VDDA_SATA, VDDA_USB1/2/3 */ + regulator-name = "ldo3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo4_reg: ldo4 { + /* VDDA_1V8_PHYB - supplies VDDA_HDMI, VDDA_PCIE/0/1 */ + regulator-name = "ldo4"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo9_reg: ldo9 { + /* VDD_RTC */ + regulator-name = "ldo9"; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; + regulator-always-on; + regulator-boot-on; + }; + + ldoln_reg: ldoln { + /* VDDA_1V8_PLL */ + regulator-name = "ldoln"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldousb_reg: ldousb { + /* VDDA_3V_USB: VDDA_USBHS33 */ + regulator-name = "ldousb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + /* regen1 not used */ + }; + }; + + tps659038_pwr_button: tps659038_pwr_button { + compatible = "ti,palmas-pwrbutton"; + interrupt-parent = <&tps659038>; + interrupts = <1 IRQ_TYPE_EDGE_FALLING>; + wakeup-source; + ti,palmas-long-press-seconds = <12>; + }; + + tps659038_gpio: tps659038_gpio { + compatible = "ti,palmas-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + rtc0: rtc@56 { + compatible = "emmicro,em3027"; + reg = <0x56>; + }; + + eeprom_module: atmel@50 { + compatible = "atmel,24c08"; + reg = <0x50>; + pagesize = <16>; + }; + + wm8731: wm8731@1a { + #sound-dai-cells = <0>; + compatible = "wlf,wm8731"; + reg = <0x1a>; + status = "okay"; + }; +}; + +&cpu0 { + cpu0-supply = <&smps12_reg>; + voltage-tolerance = <1>; +}; + +&sata { + status = "okay"; +}; + +&mailbox5 { + status = "okay"; + mbox_ipu1_ipc3x: mbox_ipu1_ipc3x { + status = "okay"; + }; + mbox_dsp1_ipc3x: mbox_dsp1_ipc3x { + status = "okay"; + }; +}; + +&mailbox6 { + status = "okay"; + mbox_ipu2_ipc3x: mbox_ipu2_ipc3x { + status = "okay"; + }; + mbox_dsp2_ipc3x: mbox_dsp2_ipc3x { + status = "okay"; + }; +}; + +&mmc2 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins_default>; + + vmmc-supply = <&vdd_3v3>; + bus-width = <8>; + ti,non-removable; + cap-mmc-dual-data-rate; +}; + +&qspi { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&qspi1_pins>; + + spi-max-frequency = <48000000>; + + spi_flash: spi_flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spansion,m25p80", "jedec,spi-nor"; + reg = <0>; /* CS0 */ + spi-max-frequency = <48000000>; + + partition@0 { + label = "uboot"; + reg = <0x0 0xc0000>; + }; + + partition@c0000 { + label = "uboot environment"; + reg = <0xc0000 0x40000>; + }; + + partition@100000 { + label = "reserved"; + reg = <0x100000 0x0>; + }; + }; + + /* touch controller */ + ads7846@0 { + pinctrl-names = "default"; + pinctrl-0 = <&ads7846_pins>; + + compatible = "ti,ads7846"; + vcc-supply = <&ads7846reg>; + + reg = <1>; /* CS1 */ + spi-max-frequency = <1500000>; + + interrupt-parent = <&gpio1>; + interrupts = <31 0>; + pendown-gpio = <&gpio1 31 0>; + + + ti,x-min = /bits/ 16 <0x0>; + ti,x-max = /bits/ 16 <0x0fff>; + ti,y-min = /bits/ 16 <0x0>; + ti,y-max = /bits/ 16 <0x0fff>; + + ti,x-plate-ohms = /bits/ 16 <180>; + ti,pressure-max = /bits/ 16 <255>; + + ti,debounce-max = /bits/ 16 <30>; + ti,debounce-tol = /bits/ 16 <10>; + ti,debounce-rep = /bits/ 16 <1>; + + wakeup-source; + }; +}; + +&mac { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_pins_default>; + pinctrl-1 = <&cpsw_pins_sleep>; + dual_emac; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii-txid"; + dual_emac_res_vlan = <0>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii-txid"; + dual_emac_res_vlan = <1>; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_pins_default>; + pinctrl-1 = <&davinci_mdio_pins_sleep>; +}; + +&usb2_phy1 { + phy-supply = <&ldousb_reg>; +}; + +&usb2_phy2 { + phy-supply = <&ldousb_reg>; +}; + +&usb1 { + dr_mode = "host"; +}; + +&usb2 { + dr_mode = "host"; +}; + +&mcasp3 { + #sound-dai-cells = <0>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&mcasp3_pins_default>; + pinctrl-1 = <&mcasp3_pins_sleep>; + status = "okay"; + + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; + /* 4 serializers */ + serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ + 1 2 0 0 + >; +}; + +&gpio3 { + status = "okay"; + ti,no-reset-on-init; +}; + +&gpio2 { + status = "okay"; + ti,no-reset-on-init; +};
diff --git a/arch/arm/dts/am57xx-commercial-grade.dtsi b/arch/arm/dts/am57xx-commercial-grade.dtsi new file mode 100644 index 0000000..3eed6e0 --- /dev/null +++ b/arch/arm/dts/am57xx-commercial-grade.dtsi
@@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 +&cpu_alert0 { + temperature = <80000>; /* milliCelsius */ +}; + +&cpu_crit { + temperature = <90000>; /* milliCelsius */ +}; + +&gpu_crit { + temperature = <90000>; /* milliCelsius */ +}; + +&core_crit { + temperature = <90000>; /* milliCelsius */ +}; + +&dspeve_crit { + temperature = <90000>; /* milliCelsius */ +}; + +&iva_crit { + temperature = <90000>; /* milliCelsius */ +};
diff --git a/arch/arm/dts/am57xx-idk-common.dtsi b/arch/arm/dts/am57xx-idk-common.dtsi new file mode 100644 index 0000000..fa5a078 --- /dev/null +++ b/arch/arm/dts/am57xx-idk-common.dtsi
@@ -0,0 +1,475 @@ +/* + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + */ + +#include "am57xx-industrial-grade.dtsi" + +/ { + aliases { + rtc0 = &tps659038_rtc; + rtc1 = &rtc; + }; + + chosen { + stdout-path = &uart3; + }; + + vmain: fixedregulator-vmain { + compatible = "regulator-fixed"; + regulator-name = "VMAIN"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; + + v3_3d: fixedregulator-v3_3d { + compatible = "regulator-fixed"; + regulator-name = "V3_3D"; + vin-supply = <&smps9_reg>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + vtt_fixed: fixedregulator-vtt { + /* TPS51200 */ + compatible = "regulator-fixed"; + regulator-name = "vtt_fixed"; + vin-supply = <&v3_3d>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + leds-iio { + status = "disabled"; + compatible = "gpio-leds"; + led-out0 { + label = "out0"; + gpios = <&tpic2810 0 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led-out1 { + label = "out1"; + gpios = <&tpic2810 1 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led-out2 { + label = "out2"; + gpios = <&tpic2810 2 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led-out3 { + label = "out3"; + gpios = <&tpic2810 3 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led-out4 { + label = "out4"; + gpios = <&tpic2810 4 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led-out5 { + label = "out5"; + gpios = <&tpic2810 5 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led-out6 { + label = "out6"; + gpios = <&tpic2810 6 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led-out7 { + label = "out7"; + gpios = <&tpic2810 7 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; +}; + +&dra7_pmx_core { + dcan1_pins_default: dcan1_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* dcan1_tx */ + DRA7XX_CORE_IOPAD(0x37d4, PIN_INPUT_PULLUP | MUX_MODE0) /* dcan1_rx */ + >; + }; + + dcan1_pins_sleep: dcan1_pins_sleep { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x37d0, MUX_MODE15 | PULL_UP) /* dcan1_tx.off */ + DRA7XX_CORE_IOPAD(0x37d4, MUX_MODE15 | PULL_UP) /* dcan1_rx.off */ + >; + }; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <400000>; + + tps659038: tps659038@58 { + compatible = "ti,tps659038"; + reg = <0x58>; + interrupts-extended = <&gpio6 16 IRQ_TYPE_LEVEL_HIGH + &dra7_pmx_core 0x418>; + #interrupt-cells = <2>; + interrupt-controller; + ti,system-power-controller; + ti,palmas-override-powerhold; + + tps659038_pmic { + compatible = "ti,tps659038-pmic"; + + smps12-in-supply = <&vmain>; + smps3-in-supply = <&vmain>; + smps45-in-supply = <&vmain>; + smps6-in-supply = <&vmain>; + smps7-in-supply = <&vmain>; + smps8-in-supply = <&vmain>; + smps9-in-supply = <&vmain>; + ldo1-in-supply = <&vmain>; + ldo2-in-supply = <&vmain>; + ldo3-in-supply = <&vmain>; + ldo4-in-supply = <&vmain>; + ldo9-in-supply = <&vmain>; + ldoln-in-supply = <&vmain>; + ldousb-in-supply = <&vmain>; + ldortc-in-supply = <&vmain>; + + regulators { + smps12_reg: smps12 { + /* VDD_MPU */ + regulator-name = "smps12"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps3_reg: smps3 { + /* VDD_DDR EMIF1 EMIF2 */ + regulator-name = "smps3"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + }; + + smps45_reg: smps45 { + /* VDD_DSPEVE on AM572 */ + /* VDD_IVA + VDD_DSP on AM571 */ + regulator-name = "smps45"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps6_reg: smps6 { + /* VDD_GPU */ + regulator-name = "smps6"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-boot-on; + }; + + smps7_reg: smps7 { + /* VDD_CORE */ + regulator-name = "smps7"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <1150000>; + regulator-always-on; + regulator-boot-on; + }; + + smps8_reg: smps8 { + /* 5728 - VDD_IVAHD */ + /* 5718 - N.C. test point */ + regulator-name = "smps8"; + }; + + smps9_reg: smps9 { + /* VDD_3_3D */ + regulator-name = "smps9"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo1_reg: ldo1 { + /* VDDSHV8 - VSDMMC */ + /* NOTE: on rev 1.3a, data supply */ + regulator-name = "ldo1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo2_reg: ldo2 { + /* VDDSH18V */ + regulator-name = "ldo2"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo3_reg: ldo3 { + /* R1.3a 572x V1_8PHY_LDO3: USB, SATA */ + regulator-name = "ldo3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldo4_reg: ldo4 { + /* R1.3a 572x V1_8PHY_LDO4: PCIE, HDMI*/ + regulator-name = "ldo4"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + /* LDO5-8 unused */ + + ldo9_reg: ldo9 { + /* VDD_RTC */ + regulator-name = "ldo9"; + regulator-min-microvolt = <840000>; + regulator-max-microvolt = <1160000>; + regulator-always-on; + regulator-boot-on; + }; + + ldoln_reg: ldoln { + /* VDDA_1V8_PLL */ + regulator-name = "ldoln"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + ldousb_reg: ldousb { + /* VDDA_3V_USB: VDDA_USBHS33 */ + regulator-name = "ldousb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + ldortc_reg: ldortc { + /* VDDA_RTC */ + regulator-name = "ldortc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + regen1: regen1 { + /* VDD_3V3_ON */ + regulator-name = "regen1"; + regulator-boot-on; + regulator-always-on; + }; + + regen2: regen2 { + /* Needed for PMIC internal resource */ + regulator-name = "regen2"; + regulator-boot-on; + regulator-always-on; + }; + }; + }; + + tps659038_rtc: tps659038_rtc { + compatible = "ti,palmas-rtc"; + interrupt-parent = <&tps659038>; + interrupts = <8 IRQ_TYPE_EDGE_FALLING>; + wakeup-source; + }; + + tps659038_pwr_button: tps659038_pwr_button { + compatible = "ti,palmas-pwrbutton"; + interrupt-parent = <&tps659038>; + interrupts = <1 IRQ_TYPE_EDGE_FALLING>; + wakeup-source; + ti,palmas-long-press-seconds = <12>; + }; + + tps659038_gpio: tps659038_gpio { + compatible = "ti,palmas-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + + extcon_usb2: tps659038_usb { + compatible = "ti,palmas-usb-vid"; + ti,enable-vbus-detection; + ti,enable-id-detection; + /* ID & VBUS GPIOs provided in board dts */ + }; + }; + + tpic2810: tpic2810@60 { + compatible = "ti,tpic2810"; + reg = <0x60>; + gpio-controller; + #gpio-cells = <2>; + }; +}; + +&mcspi3 { + status = "okay"; + ti,pindir-d0-out-d1-in; + + sn65hvs882: sn65hvs882@0 { + compatible = "pisosr-gpio"; + gpio-controller; + #gpio-cells = <2>; + + reg = <0>; + spi-max-frequency = <1000000>; + spi-cpol; + }; +}; + +&uart3 { + status = "okay"; + interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH + &dra7_pmx_core 0x248>; +}; + +&rtc { + status = "okay"; + ext-clk-src; +}; + +&mac { + status = "okay"; + dual_emac; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii"; + dual_emac_res_vlan = <2>; +}; + +&usb2_phy1 { + phy-supply = <&ldousb_reg>; +}; + +&usb2_phy2 { + phy-supply = <&ldousb_reg>; +}; + +&usb1 { + dr_mode = "host"; +}; + +&usb2 { + dr_mode = "peripheral"; +}; + +&mmc1 { + status = "okay"; + vmmc-supply = <&v3_3d>; + vqmmc-supply = <&ldo1_reg>; + bus-width = <4>; + cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; /* gpio 219 */ +}; + +&mmc2 { + status = "okay"; + vmmc-supply = <&v3_3d>; + bus-width = <8>; + ti,non-removable; + max-frequency = <96000000>; + no-1-8-v; + /delete-property/ mmc-hs200-1_8v; +}; + +&dcan1 { + status = "okay"; + pinctrl-names = "default", "sleep", "active"; + pinctrl-0 = <&dcan1_pins_sleep>; + pinctrl-1 = <&dcan1_pins_sleep>; + pinctrl-2 = <&dcan1_pins_default>; +}; + +&qspi { + status = "okay"; + + spi-max-frequency = <76800000>; + m25p80@0 { + compatible = "s25fl256s1", "jedec,spi-nor"; + spi-max-frequency = <76800000>; + reg = <0>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + #address-cells = <1>; + #size-cells = <1>; + + /* MTD partition table. + * The ROM checks the first four physical blocks + * for a valid file to boot and the flash here is + * 64KiB block size. + */ + partition@0 { + label = "QSPI.SPL"; + reg = <0x00000000 0x000040000>; + }; + partition@1 { + label = "QSPI.u-boot"; + reg = <0x00040000 0x00100000>; + }; + partition@2 { + label = "QSPI.u-boot-spl-os"; + reg = <0x00140000 0x00080000>; + }; + partition@3 { + label = "QSPI.u-boot-env"; + reg = <0x001c0000 0x00010000>; + }; + partition@4 { + label = "QSPI.u-boot-env.backup1"; + reg = <0x001d0000 0x0010000>; + }; + partition@5 { + label = "QSPI.kernel"; + reg = <0x001e0000 0x0800000>; + }; + partition@6 { + label = "QSPI.file-system"; + reg = <0x009e0000 0x01620000>; + }; + }; +};
diff --git a/arch/arm/dts/am57xx-industrial-grade.dtsi b/arch/arm/dts/am57xx-industrial-grade.dtsi new file mode 100644 index 0000000..422f953 --- /dev/null +++ b/arch/arm/dts/am57xx-industrial-grade.dtsi
@@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 +&cpu_alert0 { + temperature = <90000>; /* milliCelsius */ +}; + +&cpu_crit { + temperature = <105000>; /* milliCelsius */ +}; + +&gpu_crit { + temperature = <105000>; /* milliCelsius */ +}; + +&core_crit { + temperature = <105000>; /* milliCelsius */ +}; + +&dspeve_crit { + temperature = <105000>; /* milliCelsius */ +}; + +&iva_crit { + temperature = <105000>; /* milliCelsius */ +};
diff --git a/arch/arm/dts/am57xx-sbc-am57x.dts b/arch/arm/dts/am57xx-sbc-am57x.dts new file mode 100644 index 0000000..31f9be6 --- /dev/null +++ b/arch/arm/dts/am57xx-sbc-am57x.dts
@@ -0,0 +1,179 @@ +/* + * Support for CompuLab SBC-AM57x single board computer + * + * Copyright (C) 2015 CompuLab Ltd. - http://www.compulab.co.il/ + * Author: Dmitry Lifshitz <lifshitz@compulab.co.il> + * + * 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. + */ + +#include "am57xx-cl-som-am57x.dts" +#include "compulab-sb-som.dtsi" + +/ { + model = "CompuLab CL-SOM-AM57x on SB-SOM-AM57x"; + compatible = "compulab,sbc-am57x", "compulab,cl-som-am57x", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7"; + + aliases { + display0 = &lcd0; + display1 = &hdmi; + }; +}; + +&dra7_pmx_core { + uart3_pins_default: uart3_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3648, PIN_INPUT_SLEW | MUX_MODE0) /* uart3_rxd */ + DRA7XX_CORE_IOPAD(0x364c, PIN_INPUT_SLEW | MUX_MODE0) /* uart3_txd */ + >; + }; + + mmc1_pins_default: mmc1_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */ + DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */ + DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */ + DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */ + DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */ + DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */ + DRA7XX_CORE_IOPAD(0x376c, PIN_INPUT | MUX_MODE14) /* mmc1_sdcd.gpio6_27 */ + DRA7XX_CORE_IOPAD(0x377c, PIN_INPUT | MUX_MODE14) /* mmc1_sdwp.gpio6_28 */ + >; + }; + + usb1_pins: pinmux_usb1_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3680, PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */ + >; + }; + + i2c5_pins_default: i2c5_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT| MUX_MODE10) /* mcasp1_axr0.i2c5_sda */ + DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT| MUX_MODE10) /* mcasp1_axr1.i2c5_scl */ + >; + }; + + lcd_pins_default: lcd_pins_default { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3564, PIN_OUTPUT | MUX_MODE14) /* vin2a_vsync0.gpio4_0 */ + >; + }; + + hdmi_pins: pinmux_hdmi_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE1) /* i2c2_sda.hdmi1_ddc_scl */ + DRA7XX_CORE_IOPAD(0x380c, PIN_INPUT | MUX_MODE1) /* i2c2_scl.hdmi1_ddc_sda */ + >; + }; + + hdmi_conn_pins: pinmux_hdmi_conn_pins { + pinctrl-single,pins = < + DRA7XX_CORE_IOPAD(0x37b8, PIN_INPUT | MUX_MODE14) /* spi1_cs2.gpio7_12 */ + >; + }; +}; + +&uart3 { + status = "okay"; + interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>, + <&dra7_pmx_core 0x3f8>; + + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins_default>; +}; + +&mmc1 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins_default>; + + vmmc-supply = <&ldo1_reg>; + bus-width = <4>; + cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio6 28 GPIO_ACTIVE_HIGH>; +}; + +&usb1 { + pinctrl-names = "default"; + pinctrl-0 = <&usb1_pins>; +}; + +&i2c5 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_pins_default>; + clock-frequency = <400000>; + + eeprom_base: atmel@54 { + compatible = "atmel,24c08"; + reg = <0x54>; + pagesize = <16>; + }; + + pca9555: pca9555@20 { + compatible = "nxp,pca9555"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + }; +}; + +&dss { + status = "ok"; + + vdda_video-supply = <&ldoln_reg>; + + port { + dpi_lcd_out: endpoint { + remote-endpoint = <&lcd_in>; + data-lines = <24>; + }; + }; +}; + +&lcd0 { + pinctrl-names = "default"; + pinctrl-0 = <&lcd_pins_default>; + + enable-gpios = <&pca9555 14 GPIO_ACTIVE_HIGH + &gpio4 0 GPIO_ACTIVE_HIGH>; + + port { + lcd_in: endpoint { + remote-endpoint = <&dpi_lcd_out>; + data-lines = <24>; + }; + }; +}; + +&hdmi { + status = "ok"; + vdda-supply = <&ldo4_reg>; + + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_pins>; + + port { + hdmi_out: endpoint { + remote-endpoint = <&hdmi_connector_in>; + lanes = <1 0 3 2 5 4 7 6>; + }; + }; +}; + +&hdmi_conn { + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_conn_pins>; + + hpd-gpios = <&gpio7 12 GPIO_ACTIVE_HIGH>; + + port { + hdmi_connector_in: endpoint { + remote-endpoint = <&hdmi_out>; + }; + }; +};
diff --git a/arch/arm/dts/armada-370-xp.dtsi b/arch/arm/dts/armada-370-xp.dtsi new file mode 100644 index 0000000..0b2a78d --- /dev/null +++ b/arch/arm/dts/armada-370-xp.dtsi
@@ -0,0 +1,334 @@ +/* + * Device Tree Include file for Marvell Armada 370 and Armada XP SoC + * + * Copyright (C) 2012 Marvell + * + * Lior Amsalem <alior@marvell.com> + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * Ben Dooks <ben.dooks@codethink.co.uk> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file contains the definitions that are common to the Armada + * 370 and Armada XP SoC. + */ + +/include/ "skeleton64.dtsi" + +#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16)) + +/ { + model = "Marvell Armada 370 and XP SoC"; + compatible = "marvell,armada-370-xp"; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + compatible = "marvell,sheeva-v7"; + device_type = "cpu"; + reg = <0>; + }; + }; + + pmu { + compatible = "arm,cortex-a9-pmu"; + interrupts-extended = <&mpic 3>; + }; + + soc { + #address-cells = <2>; + #size-cells = <1>; + controller = <&mbusc>; + interrupt-parent = <&mpic>; + pcie-mem-aperture = <0xf8000000 0x7e00000>; + pcie-io-aperture = <0xffe00000 0x100000>; + + devbus-bootcs { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>; + ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs0 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>; + ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs1 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>; + ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs2 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>; + ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs3 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>; + ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + internal-regs { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>; + u-boot,dm-pre-reloc; + + rtc@10300 { + compatible = "marvell,orion-rtc"; + reg = <0x10300 0x20>; + interrupts = <50>; + }; + + spi0: spi@10600 { + reg = <0x10600 0x28>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + interrupts = <30>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + spi1: spi@10680 { + reg = <0x10680 0x28>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + interrupts = <92>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + i2c0: i2c@11000 { + compatible = "marvell,mv64xxx-i2c"; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <31>; + timeout-ms = <1000>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + i2c1: i2c@11100 { + compatible = "marvell,mv64xxx-i2c"; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <32>; + timeout-ms = <1000>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + uart0: serial@12000 { + compatible = "snps,dw-apb-uart"; + reg = <0x12000 0x100>; + reg-shift = <2>; + interrupts = <41>; + reg-io-width = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + uart1: serial@12100 { + compatible = "snps,dw-apb-uart"; + reg = <0x12100 0x100>; + reg-shift = <2>; + interrupts = <42>; + reg-io-width = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + pinctrl: pin-ctrl@18000 { + reg = <0x18000 0x38>; + }; + + coredivclk: corediv-clock@18740 { + compatible = "marvell,armada-370-corediv-clock"; + reg = <0x18740 0xc>; + #clock-cells = <1>; + clocks = <&mainpll>; + clock-output-names = "nand"; + }; + + mbusc: mbus-controller@20000 { + compatible = "marvell,mbus-controller"; + reg = <0x20000 0x100>, <0x20180 0x20>, + <0x20250 0x8>; + }; + + mpic: interrupt-controller@20a00 { + compatible = "marvell,mpic"; + #interrupt-cells = <1>; + #size-cells = <1>; + interrupt-controller; + msi-controller; + }; + + coherency-fabric@20200 { + compatible = "marvell,coherency-fabric"; + reg = <0x20200 0xb0>, <0x21010 0x1c>; + }; + + timer@20300 { + reg = <0x20300 0x30>, <0x21040 0x30>; + interrupts = <37>, <38>, <39>, <40>, <5>, <6>; + }; + + watchdog@20300 { + reg = <0x20300 0x34>, <0x20704 0x4>; + }; + + pmsu@22000 { + compatible = "marvell,armada-370-pmsu"; + reg = <0x22000 0x1000>; + }; + + usb@50000 { + compatible = "marvell,orion-ehci"; + reg = <0x50000 0x500>; + interrupts = <45>; + status = "disabled"; + }; + + usb@51000 { + compatible = "marvell,orion-ehci"; + reg = <0x51000 0x500>; + interrupts = <46>; + status = "disabled"; + }; + + eth0: ethernet@70000 { + reg = <0x70000 0x4000>; + interrupts = <8>; + clocks = <&gateclk 4>; + status = "disabled"; + }; + + mdio: mdio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "marvell,orion-mdio"; + reg = <0x72004 0x4>; + clocks = <&gateclk 4>; + }; + + eth1: ethernet@74000 { + reg = <0x74000 0x4000>; + interrupts = <10>; + clocks = <&gateclk 3>; + status = "disabled"; + }; + + sata@a0000 { + compatible = "marvell,armada-370-sata"; + reg = <0xa0000 0x5000>; + interrupts = <55>; + clocks = <&gateclk 15>, <&gateclk 30>; + clock-names = "0", "1"; + status = "disabled"; + }; + + nand@d0000 { + compatible = "marvell,armada370-nand"; + reg = <0xd0000 0x54>; + #address-cells = <1>; + #size-cells = <1>; + interrupts = <113>; + clocks = <&coredivclk 0>; + status = "disabled"; + }; + + mvsdio@d4000 { + compatible = "marvell,orion-sdio"; + reg = <0xd4000 0x200>; + interrupts = <54>; + clocks = <&gateclk 17>; + bus-width = <4>; + cap-sdio-irq; + cap-sd-highspeed; + cap-mmc-highspeed; + status = "disabled"; + }; + }; + }; + + clocks { + /* 2 GHz fixed main PLL */ + mainpll: mainpll { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <2000000000>; + }; + }; + };
diff --git a/arch/arm/dts/armada-371x.dtsi b/arch/arm/dts/armada-371x.dtsi new file mode 100644 index 0000000..c9e5325 --- /dev/null +++ b/arch/arm/dts/armada-371x.dtsi
@@ -0,0 +1,53 @@ +/* + * Device Tree Include file for Marvell Armada 371x family of SoCs + * (also named 88F3710) + * + * Copyright (C) 2016 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "armada-37xx.dtsi" + +/ { + model = "Marvell Armada 3710 SoC"; + compatible = "marvell,armada3710", "marvell,armada3700"; +};
diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts new file mode 100644 index 0000000..770c08a --- /dev/null +++ b/arch/arm/dts/armada-3720-db.dts
@@ -0,0 +1,164 @@ +/* + * Device Tree file for Marvell Armada 3720 development board + * (DB-88F3720-DDR3) + * Copyright (C) 2016 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "armada-372x.dtsi" + +/ { + model = "Marvell Armada 3720 Development Board DB-88F3720-DDR3"; + compatible = "marvell,armada-3720-db", "marvell,armada3720", "marvell,armada3710"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + ethernet0 = ð0; + i2c0 = &i2c0; + spi0 = &spi0; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x00000000 0x00000000 0x20000000>; + }; +}; + +&comphy { + phy0 { + phy-type = <PHY_TYPE_PEX0>; + phy-speed = <PHY_SPEED_2_5G>; + }; + + phy1 { + phy-type = <PHY_TYPE_USB3_HOST0>; + phy-speed = <PHY_SPEED_5G>; + }; +}; + +ð0 { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>, <&smi_pins>; + status = "okay"; + phy-mode = "rgmii"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "okay"; +}; + +/* CON3 */ +&sata { + status = "okay"; +}; + +&sdhci0 { + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&sdio_pins>; + status = "okay"; +}; + +&sdhci1 { + non-removable; + bus-width = <8>; + mmc-ddr-1_8v; + mmc-hs400-1_8v; + marvell,pad-type = "fixed-1-8v"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc_pins>; + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + mmccard: mmccard@0 { + compatible = "mmc-card"; + reg = <0>; + }; +}; + +&spi0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi_quad_pins>; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,m25p128", "spi-flash"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <50000000>; + m25p,fast-read; + }; +}; + +/* Exported on the micro USB connector CON32 through an FTDI */ +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +}; + +/* CON29 */ +&usb2 { + status = "okay"; +}; + +/* CON31 */ +&usb3 { + status = "okay"; +}; + +/* CON17 */ +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + reset-gpio = <&gpiosb 3 GPIO_ACTIVE_HIGH>; + status = "okay"; +};
diff --git a/arch/arm/dts/armada-3720-espressobin.dts b/arch/arm/dts/armada-3720-espressobin.dts new file mode 100644 index 0000000..7bfccb0 --- /dev/null +++ b/arch/arm/dts/armada-3720-espressobin.dts
@@ -0,0 +1,150 @@ +/* + * Device Tree file for Marvell Armada 3720 community board + * (ESPRESSOBin) + * Copyright (C) 2016 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * Konstantin Porotchkin <kostap@marvell.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; + +#include "armada-372x.dtsi" + +/ { + model = "Marvell Armada 3720 Community Board ESPRESSOBin"; + compatible = "marvell,armada-3720-espressobin", "marvell,armada3720", "marvell,armada3710"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + ethernet0 = ð0; + i2c0 = &i2c0; + spi0 = &spi0; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x00000000 0x00000000 0x20000000>; + }; +}; + +&comphy { + max-lanes = <3>; + phy0 { + phy-type = <PHY_TYPE_PEX0>; + phy-speed = <PHY_SPEED_2_5G>; + }; + + phy1 { + phy-type = <PHY_TYPE_USB3_HOST0>; + phy-speed = <PHY_SPEED_5G>; + }; + + phy2 { + phy-type = <PHY_TYPE_SATA0>; + phy-speed = <PHY_SPEED_5G>; + }; +}; + +ð0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>, <&smi_pins>; + phy-mode = "rgmii"; + phy_addr = <0x1>; + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "okay"; +}; + +/* CON3 */ +&sata { + status = "okay"; +}; + +&spi0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi_quad_pins>; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,m25p128", "spi-flash"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <50000000>; + m25p,fast-read; + }; +}; + +/* Exported on the micro USB connector CON32 through an FTDI */ +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +}; + +/* CON29 */ +&usb2 { + status = "okay"; +}; + +/* CON31 */ +&usb3 { + status = "okay"; +}; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + reset-gpio = <&gpiosb 3 GPIO_ACTIVE_HIGH>; + status = "okay"; +};
diff --git a/arch/arm/dts/armada-3720-turris-mox.dts b/arch/arm/dts/armada-3720-turris-mox.dts new file mode 100644 index 0000000..7babc16 --- /dev/null +++ b/arch/arm/dts/armada-3720-turris-mox.dts
@@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0+ or X11 +/* + * Device Tree file for CZ.NIC Turris Mox Board + * 2018 by Marek Behun <marek.behun@nic.cz> + * + * Based on armada-3720-espressobin.dts by: + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * Konstantin Porotchkin <kostap@marvell.com> + */ + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include "armada-372x.dtsi" + +/ { + model = "CZ.NIC Turris Mox Board"; + compatible = "cznic,turris-mox", "marvell,armada3720", + "marvell,armada3710"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + ethernet0 = ð0; + i2c0 = &i2c0; + spi0 = &spi0; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x00000000 0x00000000 0x20000000>; + }; + + reg_usb3_vbus: usb3_vbus@0 { + compatible = "regulator-fixed"; + regulator-name = "usb3-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + shutdown-delay-us = <1000000>; + gpio = <&gpiosb 0 GPIO_ACTIVE_HIGH>; + regulator-boot-on; + }; + + mdio { + eth_phy1: ethernet-phy@1 { + reg = <1>; + }; + }; +}; + +&comphy { + max-lanes = <3>; + phy0 { + phy-type = <PHY_TYPE_SGMII1>; + phy-speed = <PHY_SPEED_3_125G>; + }; + + phy1 { + phy-type = <PHY_TYPE_PEX0>; + phy-speed = <PHY_SPEED_2_5G>; + }; + + phy2 { + phy-type = <PHY_TYPE_USB3_HOST0>; + phy-speed = <PHY_SPEED_5G>; + }; +}; + +ð0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>, <&smi_pins>; + phy-mode = "rgmii"; + phy = <ð_phy1>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "okay"; +}; + +&sdhci1 { + bus-width = <4>; + status = "okay"; +}; + +&pinctrl_nb { + spi_cs1_pins: spi-cs1-pins { + groups = "spi_cs1"; + function = "spi"; + }; +}; + +&spi0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi_cs1_pins>; + assigned-clocks = <&nb_periph_clk 7>; + assigned-clock-parents = <&tbg 1>; + assigned-clock-rates = <20000000>; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,s25fl064l", "spi-flash"; + reg = <0>; + spi-max-frequency = <20000000>; + m25p,fast-read; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +}; + +&usb2 { + status = "okay"; +}; + +&usb3 { + vbus-supply = <®_usb3_vbus>; + status = "okay"; +}; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + reset-gpio = <&gpiosb 3 GPIO_ACTIVE_HIGH>; + status = "disabled"; +};
diff --git a/arch/arm/dts/armada-372x.dtsi b/arch/arm/dts/armada-372x.dtsi new file mode 100644 index 0000000..5120296 --- /dev/null +++ b/arch/arm/dts/armada-372x.dtsi
@@ -0,0 +1,62 @@ +/* + * Device Tree Include file for Marvell Armada 372x family of SoCs + * (also named 88F3720) + * + * Copyright (C) 2016 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "armada-37xx.dtsi" + +/ { + model = "Marvell Armada 3720 SoC"; + compatible = "marvell,armada3720", "marvell,armada3710"; + + cpus { + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53","arm,armv8"; + reg = <0x1>; + enable-method = "psci"; + }; + }; +};
diff --git a/arch/arm/dts/armada-375-db.dts b/arch/arm/dts/armada-375-db.dts new file mode 100644 index 0000000..343349b --- /dev/null +++ b/arch/arm/dts/armada-375-db.dts
@@ -0,0 +1,216 @@ +/* + * Device Tree file for Marvell Armada 375 evaluation board + * (DB-88F6720) + * + * Copyright (C) 2014 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include <dt-bindings/gpio/gpio.h> +#include "armada-375.dtsi" + +/ { + model = "Marvell Armada 375 Development Board"; + compatible = "marvell,a375-db", "marvell,armada375"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + /* So that mvebu u-boot can update the MAC addresses */ + ethernet0 = ð0; + ethernet1 = ð1; + spi0 = &spi0; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x40000000>; /* 1 GB */ + }; + + soc { + ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x09) 0 0xf1100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0xf1110000 0x10000>; + + internal-regs { + spi@10600 { + pinctrl-0 = <&spi0_pins>; + pinctrl-names = "default"; + /* + * SPI conflicts with NAND, so we disable it + * here, and select NAND as the enabled device + * by default. + */ + status = "okay"; + u-boot,dm-pre-reloc; + + spi-flash@0 { + u-boot,dm-pre-reloc; + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a13", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; + }; + }; + + i2c@11000 { + status = "okay"; + clock-frequency = <100000>; + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + }; + + i2c@11100 { + status = "okay"; + clock-frequency = <100000>; + pinctrl-0 = <&i2c1_pins>; + pinctrl-names = "default"; + }; + + serial@12000 { + u-boot,dm-pre-reloc; + status = "okay"; + }; + + pinctrl { + sdio_st_pins: sdio-st-pins { + marvell,pins = "mpp44", "mpp45"; + marvell,function = "gpio"; + }; + }; + + sata@a0000 { + status = "okay"; + nr-ports = <2>; + }; + + nand: nand@d0000 { + pinctrl-0 = <&nand_pins>; + pinctrl-names = "default"; + status = "okay"; + num-cs = <1>; + marvell,nand-keep-config; + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + + partition@0 { + label = "U-Boot"; + reg = <0 0x800000>; + }; + partition@800000 { + label = "Linux"; + reg = <0x800000 0x800000>; + }; + partition@1000000 { + label = "Filesystem"; + reg = <0x1000000 0x3f000000>; + }; + }; + + usb@54000 { + status = "okay"; + }; + + usb3@58000 { + status = "okay"; + }; + + mvsdio@d4000 { + pinctrl-0 = <&sdio_pins &sdio_st_pins>; + pinctrl-names = "default"; + status = "okay"; + cd-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>; + wp-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + }; + + mdio { + phy0: ethernet-phy@0 { + reg = <0>; + }; + + phy3: ethernet-phy@3 { + reg = <3>; + }; + }; + + ethernet@f0000 { + status = "okay"; + + eth0@c4000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + + eth1@c5000 { + status = "okay"; + phy = <&phy3>; + phy-mode = "gmii"; + }; + }; + }; + + pcie-controller { + status = "okay"; + /* + * The two PCIe units are accessible through + * standard PCIe slots on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + pcie@2,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; + }; + }; +};
diff --git a/arch/arm/dts/armada-375.dtsi b/arch/arm/dts/armada-375.dtsi new file mode 100644 index 0000000..249c41c --- /dev/null +++ b/arch/arm/dts/armada-375.dtsi
@@ -0,0 +1,658 @@ +/* + * Device Tree Include file for Marvell Armada 375 family SoC + * + * Copyright (C) 2014 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "skeleton.dtsi" +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/phy/phy.h> + +#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16)) + +/ { + model = "Marvell Armada 375 family SoC"; + compatible = "marvell,armada375"; + + aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + serial0 = &uart0; + serial1 = &uart1; + }; + + clocks { + /* 2 GHz fixed main PLL */ + mainpll: mainpll { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000000>; + }; + /* 25 MHz reference crystal */ + refclk: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "marvell,armada-375-smp"; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <1>; + }; + }; + + pmu { + compatible = "arm,cortex-a9-pmu"; + interrupts-extended = <&mpic 3>; + }; + + soc { + compatible = "marvell,armada375-mbus", "simple-bus"; + u-boot,dm-pre-reloc; + #address-cells = <2>; + #size-cells = <1>; + controller = <&mbusc>; + interrupt-parent = <&gic>; + pcie-mem-aperture = <0xe0000000 0x8000000>; + pcie-io-aperture = <0xe8000000 0x100000>; + + bootrom { + compatible = "marvell,bootrom"; + reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>; + }; + + devbus-bootcs { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>; + ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs0 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>; + ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs1 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>; + ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs2 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>; + ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs3 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>; + ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + internal-regs { + compatible = "simple-bus"; + u-boot,dm-pre-reloc; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>; + + L2: cache-controller@8000 { + compatible = "arm,pl310-cache"; + reg = <0x8000 0x1000>; + cache-unified; + cache-level = <2>; + arm,double-linefill-incr = <1>; + arm,double-linefill-wrap = <0>; + arm,double-linefill = <1>; + prefetch-data = <1>; + }; + + scu@c000 { + compatible = "arm,cortex-a9-scu"; + reg = <0xc000 0x58>; + }; + + timer@c600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0xc600 0x20>; + interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2))>; + clocks = <&coreclk 2>; + }; + + gic: interrupt-controller@d000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #size-cells = <0>; + interrupt-controller; + reg = <0xd000 0x1000>, + <0xc100 0x100>; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "marvell,orion-mdio"; + reg = <0xc0054 0x4>; + clocks = <&gateclk 19>; + }; + + /* Network controller */ + ethernet@f0000 { + compatible = "marvell,armada-375-pp2"; + reg = <0xf0000 0xa000>, /* Packet Processor regs */ + <0xc0000 0x3060>, /* LMS regs */ + <0xc4000 0x100>, /* eth0 regs */ + <0xc5000 0x100>; /* eth1 regs */ + clocks = <&gateclk 3>, <&gateclk 19>; + clock-names = "pp_clk", "gop_clk"; + status = "disabled"; + + eth0: eth0@c4000 { + interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; + port-id = <0>; + status = "disabled"; + }; + + eth1: eth1@c5000 { + interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; + port-id = <1>; + status = "disabled"; + }; + }; + + rtc@10300 { + compatible = "marvell,orion-rtc"; + reg = <0x10300 0x20>; + interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; + }; + + spi0: spi@10600 { + compatible = "marvell,armada-375-spi", + "marvell,orion-spi"; + reg = <0x10600 0x50>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + spi1: spi@10680 { + compatible = "marvell,armada-375-spi", + "marvell,orion-spi"; + reg = <0x10680 0x50>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + i2c0: i2c@11000 { + compatible = "marvell,mv64xxx-i2c"; + reg = <0x11000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; + timeout-ms = <1000>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + i2c1: i2c@11100 { + compatible = "marvell,mv64xxx-i2c"; + reg = <0x11100 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; + timeout-ms = <1000>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + uart0: serial@12000 { + compatible = "snps,dw-apb-uart"; + reg = <0x12000 0x100>; + reg-shift = <2>; + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; + reg-io-width = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + uart1: serial@12100 { + compatible = "snps,dw-apb-uart"; + reg = <0x12100 0x100>; + reg-shift = <2>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; + reg-io-width = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + pinctrl { + compatible = "marvell,mv88f6720-pinctrl"; + reg = <0x18000 0x24>; + + i2c0_pins: i2c0-pins { + marvell,pins = "mpp14", "mpp15"; + marvell,function = "i2c0"; + }; + + i2c1_pins: i2c1-pins { + marvell,pins = "mpp61", "mpp62"; + marvell,function = "i2c1"; + }; + + nand_pins: nand-pins { + marvell,pins = "mpp0", "mpp1", "mpp2", + "mpp3", "mpp4", "mpp5", + "mpp6", "mpp7", "mpp8", + "mpp9", "mpp10", "mpp11", + "mpp12", "mpp13"; + marvell,function = "nand"; + }; + + sdio_pins: sdio-pins { + marvell,pins = "mpp24", "mpp25", "mpp26", + "mpp27", "mpp28", "mpp29"; + marvell,function = "sd"; + }; + + spi0_pins: spi0-pins { + marvell,pins = "mpp0", "mpp1", "mpp4", + "mpp5", "mpp8", "mpp9"; + marvell,function = "spi0"; + }; + }; + + gpio0: gpio@18100 { + compatible = "marvell,orion-gpio"; + reg = <0x18100 0x40>; + ngpios = <32>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>; + }; + + gpio1: gpio@18140 { + compatible = "marvell,orion-gpio"; + reg = <0x18140 0x40>; + ngpios = <32>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; + }; + + gpio2: gpio@18180 { + compatible = "marvell,orion-gpio"; + reg = <0x18180 0x40>; + ngpios = <3>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; + }; + + system-controller@18200 { + compatible = "marvell,armada-375-system-controller"; + reg = <0x18200 0x100>; + }; + + gateclk: clock-gating-control@18220 { + compatible = "marvell,armada-375-gating-clock"; + reg = <0x18220 0x4>; + clocks = <&coreclk 0>; + #clock-cells = <1>; + }; + + usbcluster: usb-cluster@18400 { + compatible = "marvell,armada-375-usb-cluster"; + reg = <0x18400 0x4>; + #phy-cells = <1>; + }; + + mbusc: mbus-controller@20000 { + compatible = "marvell,mbus-controller"; + reg = <0x20000 0x100>, <0x20180 0x20>; + }; + + mpic: interrupt-controller@20a00 { + compatible = "marvell,mpic"; + reg = <0x20a00 0x2d0>, <0x21070 0x58>; + #interrupt-cells = <1>; + #size-cells = <1>; + interrupt-controller; + msi-controller; + interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>; + }; + + timer@20300 { + compatible = "marvell,armada-375-timer", "marvell,armada-370-timer"; + reg = <0x20300 0x30>, <0x21040 0x30>; + interrupts-extended = <&gic GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, + <&mpic 5>, + <&mpic 6>; + clocks = <&coreclk 0>, <&refclk>; + clock-names = "nbclk", "fixed"; + }; + + watchdog@20300 { + compatible = "marvell,armada-375-wdt"; + reg = <0x20300 0x34>, <0x20704 0x4>, <0x18254 0x4>; + clocks = <&coreclk 0>, <&refclk>; + clock-names = "nbclk", "fixed"; + }; + + cpurst@20800 { + compatible = "marvell,armada-370-cpu-reset"; + reg = <0x20800 0x10>; + }; + + coherency-fabric@21010 { + compatible = "marvell,armada-375-coherency-fabric"; + reg = <0x21010 0x1c>; + }; + + usb@50000 { + compatible = "marvell,orion-ehci"; + reg = <0x50000 0x500>; + interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 18>; + phys = <&usbcluster PHY_TYPE_USB2>; + phy-names = "usb"; + status = "disabled"; + }; + + usb@54000 { + compatible = "marvell,orion-ehci"; + reg = <0x54000 0x500>; + interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 26>; + status = "disabled"; + }; + + usb3@58000 { + compatible = "marvell,armada-375-xhci"; + reg = <0x58000 0x20000>,<0x5b880 0x80>; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 16>; + phys = <&usbcluster PHY_TYPE_USB3>; + phy-names = "usb"; + status = "disabled"; + }; + + xor@60800 { + compatible = "marvell,orion-xor"; + reg = <0x60800 0x100 + 0x60A00 0x100>; + clocks = <&gateclk 22>; + status = "okay"; + + xor00 { + interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>; + dmacap,memcpy; + dmacap,xor; + }; + xor01 { + interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>; + dmacap,memcpy; + dmacap,xor; + dmacap,memset; + }; + }; + + xor@60900 { + compatible = "marvell,orion-xor"; + reg = <0x60900 0x100 + 0x60b00 0x100>; + clocks = <&gateclk 23>; + status = "okay"; + + xor10 { + interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; + dmacap,memcpy; + dmacap,xor; + }; + xor11 { + interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>; + dmacap,memcpy; + dmacap,xor; + dmacap,memset; + }; + }; + + crypto@90000 { + compatible = "marvell,armada-375-crypto"; + reg = <0x90000 0x10000>; + reg-names = "regs"; + interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 30>, <&gateclk 31>, + <&gateclk 28>, <&gateclk 29>; + clock-names = "cesa0", "cesa1", + "cesaz0", "cesaz1"; + marvell,crypto-srams = <&crypto_sram0>, + <&crypto_sram1>; + marvell,crypto-sram-size = <0x800>; + }; + + sata@a0000 { + compatible = "marvell,orion-sata"; + reg = <0xa0000 0x5000>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 14>, <&gateclk 20>; + clock-names = "0", "1"; + status = "disabled"; + }; + + nand@d0000 { + compatible = "marvell,armada370-nand"; + reg = <0xd0000 0x54>; + #address-cells = <1>; + #size-cells = <1>; + interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 11>; + status = "disabled"; + }; + + mvsdio@d4000 { + compatible = "marvell,orion-sdio"; + reg = <0xd4000 0x200>; + interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 17>; + bus-width = <4>; + cap-sdio-irq; + cap-sd-highspeed; + cap-mmc-highspeed; + status = "disabled"; + }; + + thermal@e8078 { + compatible = "marvell,armada375-thermal"; + reg = <0xe8078 0x4>, <0xe807c 0x8>; + status = "okay"; + }; + + coreclk: mvebu-sar@e8204 { + compatible = "marvell,armada-375-core-clock"; + reg = <0xe8204 0x04>; + #clock-cells = <1>; + }; + + coredivclk: corediv-clock@e8250 { + compatible = "marvell,armada-375-corediv-clock"; + reg = <0xe8250 0xc>; + #clock-cells = <1>; + clocks = <&mainpll>; + clock-output-names = "nand"; + }; + }; + + pcie-controller { + compatible = "marvell,armada-370-pcie"; + status = "disabled"; + device_type = "pci"; + + #address-cells = <3>; + #size-cells = <2>; + + msi-parent = <&mpic>; + bus-range = <0x00 0xff>; + + ranges = + <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 + 0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000 + 0x82000000 0x1 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0 MEM */ + 0x81000000 0x1 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0 IO */ + 0x82000000 0x2 0 MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 1 MEM */ + 0x81000000 0x2 0 MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 1 IO */>; + + pcie@1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0 + 0x81000000 0 0 0x81000000 0x1 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 5>; + status = "disabled"; + }; + + pcie@2,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0 + 0x81000000 0 0 0x81000000 0x2 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <1>; + clocks = <&gateclk 6>; + status = "disabled"; + }; + + }; + + crypto_sram0: sa-sram0 { + compatible = "mmio-sram"; + reg = <MBUS_ID(0x09, 0x09) 0 0x800>; + clocks = <&gateclk 30>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0x09, 0x09) 0 0x800>; + }; + + crypto_sram1: sa-sram1 { + compatible = "mmio-sram"; + reg = <MBUS_ID(0x09, 0x05) 0 0x800>; + clocks = <&gateclk 31>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0x09, 0x05) 0 0x800>; + }; + }; +};
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi new file mode 100644 index 0000000..a1052ad --- /dev/null +++ b/arch/arm/dts/armada-37xx.dtsi
@@ -0,0 +1,341 @@ +/* + * Device Tree Include file for Marvell Armada 37xx family of SoCs. + * + * Copyright (C) 2016 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/comphy/comphy_data.h> +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "Marvell Armada 37xx SoC"; + compatible = "marvell,armada3700"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart0; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0>; + enable-method = "psci"; + }; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 + (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 14 + (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 11 + (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>, + <GIC_PPI 10 + (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + internal-regs { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + /* 32M internal register @ 0xd000_0000 */ + ranges = <0x0 0x0 0xd0000000 0x2000000>; + + uart0: serial@12000 { + compatible = "marvell,armada-3700-uart"; + reg = <0x12000 0x400>; + interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + wdt: watchdog-timer@8300 { + compatible = "marvell,armada-3700-wdt"; + reg = <0xd064 0x4>, + <0x8300 0x40>; + }; + + nb_periph_clk: nb-periph-clk@13000 { + compatible = "marvell,armada-3700-periph-clock-nb"; + reg = <0x13000 0x100>; + clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>, <&tbg 3>; + #clock-cells = <1>; + }; + + sb_periph_clk: sb-periph-clk@18000 { + compatible = "marvell,armada-3700-periph-clock-sb"; + reg = <0x18000 0x100>; + clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>, <&tbg 3>; + #clock-cells = <1>; + }; + + tbg: tbg@13200 { + compatible = "marvell,armada-3700-tbg-clock"; + reg = <0x13200 0x100>; + #clock-cells = <1>; + }; + + pinctrl_nb: pinctrl-nb@13800 { + compatible = "marvell,armada3710-nb-pinctrl", + "syscon", "simple-mfd"; + reg = <0x13800 0x100>, <0x13C00 0x20>; + gpionb: gpionb { + #gpio-cells = <2>; + gpio-ranges = <&pinctrl_nb 0 0 36>; + gpio-controller; + interrupts = + <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>; + + }; + + spi_quad_pins: spi-quad-pins { + groups = "spi_quad"; + function = "spi"; + }; + + i2c1_pins: i2c1-pins { + groups = "i2c1"; + function = "i2c"; + }; + + i2c2_pins: i2c2-pins { + groups = "i2c2"; + function = "i2c"; + }; + + uart1_pins: uart1-pins { + groups = "uart1"; + function = "uart"; + }; + + uart2_pins: uart2-pins { + groups = "uart2"; + function = "uart"; + }; + + mmc_pins: mmc-pins { + groups = "emmc_nb"; + function = "emmc"; + }; + }; + + pinctrl_sb: pinctrl-sb@18800 { + compatible = "marvell,armada3710-sb-pinctrl", + "syscon", "simple-mfd"; + reg = <0x18800 0x100>, <0x18C00 0x20>; + gpiosb: gpiosb { + #gpio-cells = <2>; + gpio-ranges = <&pinctrl_sb 0 0 30>; + gpio-controller; + interrupts = + <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>; + }; + + rgmii_pins: mii-pins { + groups = "rgmii"; + function = "mii"; + }; + + smi_pins: smi-pins { + groups = "smi"; + function = "smi"; + }; + + sdio_pins: sdio-pins { + groups = "sdio_sb"; + function = "sdio"; + }; + + pcie_pins: pcie-pins { + groups = "pcie1"; + function = "gpio"; + }; + }; + + usb3: usb@58000 { + compatible = "marvell,armada3700-xhci", + "generic-xhci"; + reg = <0x58000 0x4000>; + interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + usb2: usb@5e000 { + compatible = "marvell,armada3700-ehci"; + reg = <0x5e000 0x450>; + status = "disabled"; + }; + + xor@60900 { + compatible = "marvell,armada-3700-xor"; + reg = <0x60900 0x100 + 0x60b00 0x100>; + + xor10 { + interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>; + }; + xor11 { + interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; + }; + }; + + sdhci0: sdhci@d0000 { + compatible = "marvell,armada-3700-sdhci", + "marvell,sdhci-xenon"; + reg = <0xd0000 0x300 + 0x1e808 0x4>; + status = "disabled"; + }; + + sdhci1: sdhci@d8000 { + compatible = "marvell,armada-3700-sdhci", + "marvell,sdhci-xenon"; + reg = <0xd8000 0x300 + 0x17808 0x4>; + status = "disabled"; + }; + + sata: sata@e0000 { + compatible = "marvell,armada-3700-ahci"; + reg = <0xe0000 0x2000>; + interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + gic: interrupt-controller@1d00000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x1d00000 0x10000>, /* GICD */ + <0x1d40000 0x40000>; /* GICR */ + }; + + eth0: neta@30000 { + compatible = "marvell,armada-3700-neta"; + reg = <0x30000 0x20>; + status = "disabled"; + }; + + eth1: neta@40000 { + compatible = "marvell,armada-3700-neta"; + reg = <0x40000 0x20>; + status = "disabled"; + }; + + i2c0: i2c@11000 { + compatible = "marvell,armada-3700-i2c"; + reg = <0x11000 0x100>; + status = "disabled"; + }; + + spi0: spi@10600 { + compatible = "marvell,armada-3700-spi"; + reg = <0x10600 0x50>; + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <0>; + spi-max-frequency = <50000000>; + clocks = <&nb_periph_clk 7>; + status = "disabled"; + }; + + comphy: comphy@18300 { + compatible = "marvell,mvebu-comphy", "marvell,comphy-armada-3700"; + reg = <0x18300 0x28>, + <0x1f300 0x3d000>; + mux-bitcount = <4>; + mux-lane-order = <1 0 2>; + max-lanes = <3>; + }; + }; + + pcie0: pcie@d0070000 { + compatible = "marvell,armada-37xx-pcie"; + reg = <0 0xd0070000 0 0x20000>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + num-lanes = <1>; + status = "disabled"; + + bus-range = <0 0xff>; + ranges = <0x82000000 0 0xe8000000 + 0 0xe8000000 0 0x1000000 /* Port 0 MEM */ + 0x81000000 0 0xe9000000 + 0 0xe9000000 0 0x10000>; /* Port 0 IO*/ + }; + }; +};
diff --git a/arch/arm/dts/armada-380.dtsi b/arch/arm/dts/armada-380.dtsi new file mode 100644 index 0000000..5102d19 --- /dev/null +++ b/arch/arm/dts/armada-380.dtsi
@@ -0,0 +1,152 @@ +/* + * Device Tree Include file for Marvell Armada 380 SoC. + * + * Copyright (C) 2014 Marvell + * + * Lior Amsalem <alior@marvell.com> + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "armada-38x.dtsi" + +/ { + model = "Marvell Armada 380 family SoC"; + compatible = "marvell,armada380"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "marvell,armada-380-smp"; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0>; + }; + }; + + soc { + internal-regs { + pinctrl@18000 { + compatible = "marvell,mv88f6810-pinctrl"; + }; + }; + + pcie-controller { + compatible = "marvell,armada-370-pcie"; + status = "disabled"; + device_type = "pci"; + + #address-cells = <3>; + #size-cells = <2>; + + msi-parent = <&mpic>; + bus-range = <0x00 0xff>; + + ranges = + <0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000 + 0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 + 0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000 + 0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 + 0x82000000 0x1 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 0 MEM */ + 0x81000000 0x1 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 0 IO */ + 0x82000000 0x2 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 1 MEM */ + 0x81000000 0x2 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 1 IO */ + 0x82000000 0x3 0 MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 2 MEM */ + 0x81000000 0x3 0 MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 2 IO */>; + + /* x1 port */ + pcie@1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x80000 0 0x2000>; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0 + 0x81000000 0 0 0x81000000 0x1 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 8>; + status = "disabled"; + }; + + /* x1 port */ + pcie@2,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0 + 0x81000000 0 0 0x81000000 0x2 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 5>; + status = "disabled"; + }; + + /* x1 port */ + pcie@3,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0 + 0x81000000 0 0 0x81000000 0x3 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; + marvell,pcie-port = <2>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 6>; + status = "disabled"; + }; + }; + }; +};
diff --git a/arch/arm/dts/armada-385-amc.dts b/arch/arm/dts/armada-385-amc.dts new file mode 100644 index 0000000..d4d127f --- /dev/null +++ b/arch/arm/dts/armada-385-amc.dts
@@ -0,0 +1,166 @@ +/* + * Device Tree file for Marvell Armada 385 development board + * (DB-88F6820-AMC) + * + * Copyright (C) 2014 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "armada-385.dtsi" +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "Marvell Armada 385 AMC"; + compatible = "marvell,a385-amc", "marvell,armada385", "marvell,armada380"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + ethernet0 = ð0; + ethernet1 = ð2; + i2c0 = &i2c0; + spi1 = &spi1; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x80000000>; /* 2 GB */ + }; + + soc { + ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>; + + internal-regs { + i2c@11000 { + clock-frequency = <100000>; + u-boot,i2c-slave-addr = <0x0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + }; + + serial@12000 { + /* + * Exported on the micro USB connector CON16 + * through an FTDI + */ + + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; + u-boot,dm-pre-reloc; + }; + + ethernet@34000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "sgmii"; + }; + + usb@58000 { + status = "okay"; + }; + + ethernet@70000 { + pinctrl-names = "default"; + /* + * The Reference Clock 0 is used to provide a + * clock to the PHY + */ + pinctrl-0 = <&ge0_rgmii_pins>, <&ref_clk0_pins>; + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + + + mdio@72004 { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + phy0: ethernet-phy@1 { + reg = <1>; + }; + + phy1: ethernet-phy@0 { + reg = <0>; + }; + }; + + flash@d0000 { + status = "okay"; + num-cs = <1>; + marvell,nand-keep-config; + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + }; + }; + + pcie-controller { + status = "okay"; + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + + }; + }; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + status = "okay"; + u-boot,dm-pre-reloc; + + spi-flash@0 { + u-boot,dm-pre-reloc; + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,m25p128", "jedec,spi-nor", "spi-flash"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <50000000>; + m25p,fast-read; + }; +}; + +&refclk { + clock-frequency = <20000000>; +};
diff --git a/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi new file mode 100644 index 0000000..904429b --- /dev/null +++ b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi
@@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz> + */ + +/ { + aliases { + i2c0 = &i2c0; + i2c1 = &i2cmux; + spi0 = &spi0; + }; +}; + +&i2c0 { + u-boot,dm-pre-reloc; + + i2cmux: i2cmux@70 { + u-boot,dm-pre-reloc; + + i2c@0 { + u-boot,dm-pre-reloc; + }; + + i2c@1 { + u-boot,dm-pre-reloc; + }; + + i2c@5 { + u-boot,dm-pre-reloc; + + /* ATSHA204A at address 0x64 */ + atsha204a@64 { + u-boot,dm-pre-reloc; + compatible = "atmel,atsha204a"; + reg = <0x64>; + }; + }; + }; +}; + +&spi0 { + u-boot,dm-pre-reloc; + + spi-flash@0 { + compatible = "spi-flash"; + reg = <0>; + spi-max-frequency = <40000000>; + u-boot,dm-pre-reloc; + }; +}; + +&uart0 { + u-boot,dm-pre-reloc; +};
diff --git a/arch/arm/dts/armada-385-turris-omnia.dts b/arch/arm/dts/armada-385-turris-omnia.dts new file mode 100644 index 0000000..28eede1 --- /dev/null +++ b/arch/arm/dts/armada-385-turris-omnia.dts
@@ -0,0 +1,392 @@ +/* + * Device Tree file for the Turris Omnia + * + * Copyright (C) 2016 Uwe Kleine-König <uwe@kleine-koenig.org> + * Copyright (C) 2016 Tomas Hlavacek <tmshlvkc@gmail.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Schematic available at https://www.turris.cz/doc/_media/rtrom01-schema.pdf + */ + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include "armada-385.dtsi" + +/ { + model = "Turris Omnia"; + compatible = "cznic,turris-omnia", "marvell,armada385", "marvell,armada380"; + + chosen { + stdout-path = &uart0; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x40000000>; /* 1024 MB */ + }; + + soc { + ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 + MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; + + internal-regs { + + /* USB part of the PCIe2/USB 2.0 port */ + usb@58000 { + status = "okay"; + }; + + sata@a8000 { + status = "okay"; + }; + + sdhci@d8000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdhci_pins>; + status = "okay"; + + bus-width = <8>; + no-1-8-v; + non-removable; + }; + + usb3@f0000 { + status = "okay"; + }; + + usb3@f8000 { + status = "okay"; + }; + }; + + pcie-controller { + status = "okay"; + + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + + pcie@2,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; + + pcie@3,0 { + /* Port 2, Lane 0 */ + status = "okay"; + }; + }; + }; +}; + +/* Connected to 88E6176 switch, port 6 */ +ð0 { + pinctrl-names = "default"; + pinctrl-0 = <&ge0_rgmii_pins>; + status = "okay"; + phy-mode = "rgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +/* Connected to 88E6176 switch, port 5 */ +ð1 { + pinctrl-names = "default"; + pinctrl-0 = <&ge1_rgmii_pins>; + status = "okay"; + phy-mode = "rgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +/* WAN port */ +ð2 { + status = "okay"; + phy-mode = "sgmii"; + phy = <&phy1>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + i2cmux@70 { + compatible = "nxp,pca9547"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + status = "okay"; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + /* STM32F0 command interface at address 0x2a */ + /* leds device (in STM32F0) at address 0x2b */ + + eeprom@54 { + compatible = "at,24c64"; + reg = <0x54>; + + /* The EEPROM contains data for bootloader. + * Contents: + * struct omnia_eeprom { + * u32 magic; (=0x0341a034 in LE) + * u32 ramsize; (in GiB) + * char regdomain[4]; + * u32 crc32; + * }; + */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + /* routed to PCIe0/mSATA connector (CN7A) */ + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + /* routed to PCIe1/USB2 connector (CN61A) */ + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + /* routed to PCIe2 connector (CN62A) */ + }; + + i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + + /* routed to SFP+ */ + }; + + i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + + /* ATSHA204A at address 0x64 */ + }; + + i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; + + /* exposed on pin header */ + }; + + i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + + pcawan: gpio@71 { + /* + * GPIO expander for SFP+ signals and + * and phy irq + */ + compatible = "nxp,pca9538"; + reg = <0x71>; + + pinctrl-names = "default"; + pinctrl-0 = <&pcawan_pins>; + + interrupt-parent = <&gpio1>; + interrupts = <14 IRQ_TYPE_LEVEL_LOW>; + + gpio-controller; + #gpio-cells = <2>; + }; + }; + }; +}; + +&mdio { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + status = "okay"; + + phy1: phy@1 { + status = "okay"; + compatible = "ethernet-phy-id0141.0DD1", "ethernet-phy-ieee802.3-c22"; + reg = <1>; + + /* irq is connected to &pcawan pin 7 */ + }; + + /* Switch MV88E6176 at address 0x10 */ + switch@10 { + compatible = "marvell,mv88e6085"; + #address-cells = <1>; + #size-cells = <0>; + dsa,member = <0 0>; + + reg = <0x10>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + ports@0 { + reg = <0>; + label = "lan0"; + }; + + ports@1 { + reg = <1>; + label = "lan1"; + }; + + ports@2 { + reg = <2>; + label = "lan2"; + }; + + ports@3 { + reg = <3>; + label = "lan3"; + }; + + ports@4 { + reg = <4>; + label = "lan4"; + }; + + ports@5 { + reg = <5>; + label = "cpu"; + ethernet = <ð1>; + phy-mode = "rgmii-id"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + /* port 6 is connected to eth0 */ + }; + }; +}; + +&pinctrl { + pcawan_pins: pcawan-pins { + marvell,pins = "mpp46"; + marvell,function = "gpio"; + }; + + spi0cs0_pins: spi0cs0-pins { + marvell,pins = "mpp25"; + marvell,function = "spi0"; + }; + + spi0cs1_pins: spi0cs1-pins { + marvell,pins = "mpp26"; + marvell,function = "spi0"; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins &spi0cs0_pins>; + status = "okay"; + + spi-nor@0 { + compatible = "spansion,s25fl164k", "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <40000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x00100000>; + label = "U-Boot"; + }; + + partition@100000 { + reg = <0x00100000 0x00700000>; + label = "Rescue system"; + }; + }; + }; + + /* MISO, MOSI, SCLK and CS1 are routed to pin header CN11 */ +}; + +&uart0 { + /* Pin header CN10 */ + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&uart1 { + /* Pin header CN11 */ + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +};
diff --git a/arch/arm/dts/armada-385.dtsi b/arch/arm/dts/armada-385.dtsi new file mode 100644 index 0000000..8e67d2c --- /dev/null +++ b/arch/arm/dts/armada-385.dtsi
@@ -0,0 +1,184 @@ +/* + * Device Tree Include file for Marvell Armada 385 SoC. + * + * Copyright (C) 2014 Marvell + * + * Lior Amsalem <alior@marvell.com> + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "armada-38x.dtsi" + +/ { + model = "Marvell Armada 385 family SoC"; + compatible = "marvell,armada385", "marvell,armada380"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "marvell,armada-380-smp"; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <0>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + reg = <1>; + }; + }; + + soc { + internal-regs { + pinctrl@18000 { + compatible = "marvell,mv88f6820-pinctrl"; + }; + }; + + pcie-controller { + compatible = "marvell,armada-370-pcie"; + status = "disabled"; + device_type = "pci"; + + #address-cells = <3>; + #size-cells = <2>; + + msi-parent = <&mpic>; + bus-range = <0x00 0xff>; + + ranges = + <0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000 + 0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 + 0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000 + 0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000 + 0x82000000 0x1 0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 0 MEM */ + 0x81000000 0x1 0 MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 0 IO */ + 0x82000000 0x2 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 1 MEM */ + 0x81000000 0x2 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 1 IO */ + 0x82000000 0x3 0 MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 2 MEM */ + 0x81000000 0x3 0 MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 2 IO */ + 0x82000000 0x4 0 MBUS_ID(0x04, 0xb8) 0 1 0 /* Port 3 MEM */ + 0x81000000 0x4 0 MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 3 IO */>; + + /* + * This port can be either x4 or x1. When + * configured in x4 by the bootloader, then + * pcie@4,0 is not available. + */ + pcie@1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x80000 0 0x2000>; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0 + 0x81000000 0 0 0x81000000 0x1 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 8>; + status = "disabled"; + }; + + /* x1 port */ + pcie@2,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0 + 0x81000000 0 0 0x81000000 0x2 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 5>; + status = "disabled"; + }; + + /* x1 port */ + pcie@3,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0 + 0x81000000 0 0 0x81000000 0x3 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; + marvell,pcie-port = <2>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 6>; + status = "disabled"; + }; + + /* + * x1 port only available when pcie@1,0 is + * configured as a x1 port + */ + pcie@4,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0 + 0x81000000 0 0 0x81000000 0x4 0 1 0>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; + marvell,pcie-port = <3>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 7>; + status = "disabled"; + }; + }; + }; +};
diff --git a/arch/arm/dts/armada-388-clearfog-u-boot.dtsi b/arch/arm/dts/armada-388-clearfog-u-boot.dtsi new file mode 100644 index 0000000..f31691e --- /dev/null +++ b/arch/arm/dts/armada-388-clearfog-u-boot.dtsi
@@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ + +&spi1 { + u-boot,dm-spl; + + spi-flash@0 { + u-boot,dm-spl; + }; +};
diff --git a/arch/arm/dts/armada-388-clearfog.dts b/arch/arm/dts/armada-388-clearfog.dts new file mode 100644 index 0000000..16a47d5 --- /dev/null +++ b/arch/arm/dts/armada-388-clearfog.dts
@@ -0,0 +1,374 @@ +/* + * Device Tree file for SolidRun Clearfog revision A1 rev 2.0 (88F6828) + * + * Copyright (C) 2015 Russell King + * + * This board is in development; the contents of this file work with + * the A1 rev 2.0 of the board, which does not represent final + * production board. Things will change, don't expect this file to + * remain compatible info the future. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include <dt-bindings/input/input.h> +#include <dt-bindings/gpio/gpio.h> +#include "armada-388.dtsi" +#include "armada-38x-solidrun-microsom.dtsi" + +/ { + model = "SolidRun Clearfog A1"; + compatible = "solidrun,clearfog-a1", "marvell,armada388", + "marvell,armada385", "marvell,armada380"; + + aliases { + /* So that mvebu u-boot can update the MAC addresses */ + ethernet1 = ð0; + ethernet2 = ð1; + ethernet3 = ð2; + spi1 = &spi1; + i2c0 = &i2c0; + i2c1 = &i2c1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + soc { + internal-regs { + rtc@a3800 { + /* + * If the rtc doesn't work, run "date reset" + * twice in u-boot. + */ + status = "okay"; + }; + + sata@a8000 { + /* pinctrl? */ + status = "okay"; + }; + + sata@e0000 { + /* pinctrl? */ + status = "okay"; + }; + + sdhci@d8000 { + bus-width = <4>; + cd-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; + no-1-8-v; + pinctrl-0 = <µsom_sdhci_pins + &clearfog_sdhci_cd_pins>; + pinctrl-names = "default"; + status = "okay"; + vmmc = <®_3p3v>; + wp-inverted; + }; + + serial@12100 { + /* mikrobus uart */ + pinctrl-0 = <&mikro_uart_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + spi1: spi@10680 { + /* + * CS0: W25Q32 + * CS1: + * CS2: mikrobus + */ + pinctrl-0 = <&spi1_pins &clearfog_spi1_cs_pins &mikro_spi_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + usb0: usb3@f8000 { + /* CON7, USB-A port on back of device */ + status = "okay"; + }; + }; + + pcie-controller { + status = "okay"; + /* + * The two PCIe units are accessible through + * the mini-PCIe connectors on the board. + */ + pcie@2,0 { + /* Port 1, Lane 0. CONN3, nearest power. */ + reset-gpios = <&expander0 1 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + pcie@3,0 { + /* Port 2, Lane 0. CONN2, nearest CPU. */ + reset-gpios = <&expander0 2 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-0 = <&rear_button_pins>; + pinctrl-names = "default"; + + button_0 { + /* The rear SW3 button */ + label = "Rear Button"; + gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; + linux,can-disable; + linux,code = <BTN_0>; + }; + }; +}; + +&w25q32 { + status = "okay"; +}; + +ð1 { + managed = "in-band-status"; + phy-mode = "sgmii"; + status = "okay"; +}; + +ð2 { + phy-mode = "sgmii"; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + status = "okay"; + + /* + * PCA9655 GPIO expander, up to 1MHz clock. + * 0-CON3 CLKREQ# + * 1-CON3 PERST# + * 2-CON2 PERST# + * 3-CON3 W_DISABLE + * 4-CON2 CLKREQ# + * 5-USB3 overcurrent + * 6-USB3 power + * 7-CON2 W_DISABLE + * 8-JP4 P1 + * 9-JP4 P4 + * 10-JP4 P5 + * 11-m.2 DEVSLP + * 12-SFP_LOS + * 13-SFP_TX_FAULT + * 14-SFP_TX_DISABLE + * 15-SFP_MOD_DEF0 + */ + expander0: gpio-expander@20 { + /* + * This is how it should be: + * compatible = "onnn,pca9655", + * "nxp,pca9555"; + * but you can't do this because of + * the way I2C works. + */ + compatible = "nxp,pca9555"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x20>; + + pcie1_0_clkreq { + gpio-hog; + gpios = <0 GPIO_ACTIVE_LOW>; + input; + line-name = "pcie1.0-clkreq"; + }; + pcie1_0_w_disable { + gpio-hog; + gpios = <3 GPIO_ACTIVE_LOW>; + output-low; + line-name = "pcie1.0-w-disable"; + }; + pcie2_0_clkreq { + gpio-hog; + gpios = <4 GPIO_ACTIVE_LOW>; + input; + line-name = "pcie2.0-clkreq"; + }; + pcie2_0_w_disable { + gpio-hog; + gpios = <7 GPIO_ACTIVE_LOW>; + output-low; + line-name = "pcie2.0-w-disable"; + }; + usb3_ilimit { + gpio-hog; + gpios = <5 GPIO_ACTIVE_LOW>; + input; + line-name = "usb3-current-limit"; + }; + usb3_power { + gpio-hog; + gpios = <6 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "usb3-power"; + }; + m2_devslp { + gpio-hog; + gpios = <11 GPIO_ACTIVE_HIGH>; + output-low; + line-name = "m.2 devslp"; + }; + }; + + mikrobus_adc: mcp3021@4c { + compatible = "microchip,mcp3021"; + reg = <0x4c>; + }; +}; + +&i2c1 { + /* + * Routed to SFP, mikrobus, and PCIe. + * SFP limits this to 100kHz, and requires + * an AT24C01A/02/04 with address pins tied + * low, which takes addresses 0x50 and 0x51. + * Mikrobus doesn't specify beyond an I2C + * bus being present. + * PCIe uses ARP to assign addresses, or + * 0x63-0x64. + */ + clock-frequency = <100000>; + pinctrl-0 = <&clearfog_i2c1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&pinctrl { + clearfog_i2c1_pins: i2c1-pins { + /* SFP, PCIe, mSATA, mikrobus */ + marvell,pins = "mpp26", "mpp27"; + marvell,function = "i2c1"; + }; + clearfog_sdhci_cd_pins: clearfog-sdhci-cd-pins { + marvell,pins = "mpp20"; + marvell,function = "gpio"; + }; + clearfog_spi1_cs_pins: spi1-cs-pins { + marvell,pins = "mpp55"; + marvell,function = "spi1"; + }; + mikro_pins: mikro-pins { + /* int: mpp22 rst: mpp29 */ + marvell,pins = "mpp22", "mpp29"; + marvell,function = "gpio"; + }; + mikro_spi_pins: mikro-spi-pins { + marvell,pins = "mpp43"; + marvell,function = "spi1"; + }; + mikro_uart_pins: mikro-uart-pins { + marvell,pins = "mpp24", "mpp25"; + marvell,function = "ua1"; + }; + rear_button_pins: rear-button-pins { + marvell,pins = "mpp34"; + marvell,function = "gpio"; + }; +}; + +/* ++#define A38x_CUSTOMER_BOARD_1_MPP16_23 0x00400011 +MPP18: gpio ? (pca9655 int?) +MPP19: gpio ? (clkreq?) +MPP20: gpio ? (sd0 detect) +MPP21: sd0:cmd x sd0 +MPP22: gpio x mikro int +MPP23: gpio x switch irq ++#define A38x_CUSTOMER_BOARD_1_MPP24_31 0x22043333 +MPP24: ua1:rxd x mikro rx +MPP25: ua1:txd x mikro tx +MPP26: i2c1:sck x mikro sck +MPP27: i2c1:sda x mikro sda +MPP28: sd0:clk x sd0 +MPP29: gpio x mikro rst +MPP30: ge1:txd2 ? (config) +MPP31: ge1:txd3 ? (config) ++#define A38x_CUSTOMER_BOARD_1_MPP32_39 0x44400002 +MPP32: ge1:txctl ? (unused) +MPP33: gpio ? (pic_com0) +MPP34: gpio x rear button (pic_com1) +MPP35: gpio ? (pic_com2) +MPP36: gpio ? (unused) +MPP37: sd0:d3 x sd0 +MPP38: sd0:d0 x sd0 +MPP39: sd0:d1 x sd0 ++#define A38x_CUSTOMER_BOARD_1_MPP40_47 0x41144004 +MPP40: sd0:d2 x sd0 +MPP41: gpio x switch reset +MPP42: gpio ? sw1-1 +MPP43: spi1:cs2 x mikro cs +MPP44: sata3:prsnt ? (unused) +MPP45: ref:clk_out0 ? +MPP46: ref:clk_out1 x switch clk +MPP47: 4 ? (unused) ++#define A38x_CUSTOMER_BOARD_1_MPP48_55 0x40333333 +MPP48: tdm:pclk +MPP49: tdm:fsync +MPP50: tdm:drx +MPP51: tdm:dtx +MPP52: tdm:int +MPP53: tdm:rst +MPP54: gpio ? (pwm) +MPP55: spi1:cs1 x slic ++#define A38x_CUSTOMER_BOARD_1_MPP56_63 0x00004444 +MPP56: spi1:mosi x mikro mosi +MPP57: spi1:sck x mikro sck +MPP58: spi1:miso x mikro miso +MPP59: spi1:cs0 x w25q32 +*/
diff --git a/arch/arm/dts/armada-388-gp.dts b/arch/arm/dts/armada-388-gp.dts new file mode 100644 index 0000000..7bc878f --- /dev/null +++ b/arch/arm/dts/armada-388-gp.dts
@@ -0,0 +1,422 @@ +/* + * Device Tree file for Marvell Armada 385 development board + * (RD-88F6820-GP) + * + * Copyright (C) 2014 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "armada-388.dtsi" +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "Marvell Armada 385 GP"; + compatible = "marvell,a385-gp", "marvell,armada388", "marvell,armada380"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + ethernet0 = ð0; + ethernet1 = ð1; + spi0 = &spi0; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x80000000>; /* 2 GB */ + }; + + soc { + ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>; + + internal-regs { + spi@10600 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + status = "okay"; + u-boot,dm-pre-reloc; + + spi-flash@0 { + u-boot,dm-pre-reloc; + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,m25p128", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <50000000>; + m25p,fast-read; + }; + }; + + i2c@11000 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + clock-frequency = <100000>; + /* + * The EEPROM located at adresse 54 is needed + * for the boot - DO NOT ERASE IT - + */ + + expander0: pca9555@20 { + compatible = "nxp,pca9555"; + pinctrl-names = "default"; + pinctrl-0 = <&pca0_pins>; + interrupt-parent = <&gpio0>; + interrupts = <18 IRQ_TYPE_EDGE_FALLING>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x20>; + }; + + expander1: pca9555@21 { + compatible = "nxp,pca9555"; + pinctrl-names = "default"; + interrupt-parent = <&gpio0>; + interrupts = <18 IRQ_TYPE_EDGE_FALLING>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x21>; + }; + + }; + + serial@12000 { + /* + * Exported on the micro USB connector CON16 + * through an FTDI + */ + + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; + u-boot,dm-pre-reloc; + }; + + /* GE1 CON15 */ + ethernet@30000 { + pinctrl-names = "default"; + pinctrl-0 = <&ge1_rgmii_pins>; + status = "okay"; + phy = <&phy1>; + phy-mode = "rgmii-id"; + }; + + /* CON4 */ + usb@58000 { + vcc-supply = <®_usb2_0_vbus>; + status = "okay"; + }; + + /* GE0 CON1 */ + ethernet@70000 { + pinctrl-names = "default"; + /* + * The Reference Clock 0 is used to provide a + * clock to the PHY + */ + pinctrl-0 = <&ge0_rgmii_pins>, <&ref_clk0_pins>; + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + + + mdio@72004 { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + phy0: ethernet-phy@1 { + reg = <1>; + }; + + phy1: ethernet-phy@0 { + reg = <0>; + }; + }; + + sata@a8000 { + pinctrl-names = "default"; + pinctrl-0 = <&sata0_pins>, <&sata1_pins>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + sata0: sata-port@0 { + reg = <0>; + target-supply = <®_5v_sata0>; + }; + + sata1: sata-port@1 { + reg = <1>; + target-supply = <®_5v_sata1>; + }; + }; + + sata@e0000 { + pinctrl-names = "default"; + pinctrl-0 = <&sata2_pins>, <&sata3_pins>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + sata2: sata-port@0 { + reg = <0>; + target-supply = <®_5v_sata2>; + }; + + sata3: sata-port@1 { + reg = <1>; + target-supply = <®_5v_sata3>; + }; + }; + + sdhci@d8000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdhci_pins>; + cd-gpios = <&expander0 5 GPIO_ACTIVE_LOW>; + no-1-8-v; + wp-inverted; + bus-width = <8>; + status = "okay"; + }; + + /* CON5 */ + usb3@f0000 { + vcc-supply = <®_usb2_1_vbus>; + status = "okay"; + }; + + /* CON7 */ + usb3@f8000 { + vcc-supply = <®_usb3_vbus>; + status = "okay"; + }; + }; + + pcie-controller { + status = "okay"; + /* + * One PCIe units is accessible through + * standard PCIe slot on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + + /* + * The two other PCIe units are accessible + * through mini PCIe slot on the board. + */ + pcie@2,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; + pcie@3,0 { + /* Port 2, Lane 0 */ + status = "okay"; + }; + }; + + gpio-fan { + compatible = "gpio-fan"; + gpios = <&expander1 3 GPIO_ACTIVE_HIGH>; + gpio-fan,speed-map = < 0 0 + 3000 1>; + }; + }; + + reg_usb3_vbus: usb3-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb3-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + gpio = <&expander1 15 GPIO_ACTIVE_HIGH>; + }; + + reg_usb2_0_vbus: v5-vbus0 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-vbus0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + gpio = <&expander1 14 GPIO_ACTIVE_HIGH>; + }; + + reg_usb2_1_vbus: v5-vbus1 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-vbus1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + gpio = <&expander0 4 GPIO_ACTIVE_HIGH>; + }; + + reg_usb2_1_vbus: v5-vbus1 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-vbus1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + gpio = <&expander0 4 GPIO_ACTIVE_HIGH>; + }; + + reg_sata0: pwr-sata0 { + compatible = "regulator-fixed"; + regulator-name = "pwr_en_sata0"; + enable-active-high; + regulator-always-on; + + }; + + reg_5v_sata0: v5-sata0 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <®_sata0>; + }; + + reg_12v_sata0: v12-sata0 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata0"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-always-on; + vin-supply = <®_sata0>; + }; + + reg_sata1: pwr-sata1 { + regulator-name = "pwr_en_sata1"; + compatible = "regulator-fixed"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + regulator-always-on; + gpio = <&expander0 3 GPIO_ACTIVE_HIGH>; + }; + + reg_5v_sata1: v5-sata1 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <®_sata1>; + }; + + reg_12v_sata1: v12-sata1 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata1"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-always-on; + vin-supply = <®_sata1>; + }; + + reg_sata2: pwr-sata2 { + compatible = "regulator-fixed"; + regulator-name = "pwr_en_sata2"; + enable-active-high; + regulator-always-on; + gpio = <&expander0 11 GPIO_ACTIVE_HIGH>; + }; + + reg_5v_sata2: v5-sata2 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata2"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <®_sata2>; + }; + + reg_12v_sata2: v12-sata2 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata2"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-always-on; + vin-supply = <®_sata2>; + }; + + reg_sata3: pwr-sata3 { + compatible = "regulator-fixed"; + regulator-name = "pwr_en_sata3"; + enable-active-high; + regulator-always-on; + gpio = <&expander0 12 GPIO_ACTIVE_HIGH>; + }; + + reg_5v_sata3: v5-sata3 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata3"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <®_sata3>; + }; + + reg_12v_sata3: v12-sata3 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata3"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-always-on; + vin-supply = <®_sata3>; + }; +}; + +&pinctrl { + pca0_pins: pca0_pins { + marvell,pins = "mpp18"; + marvell,function = "gpio"; + }; +};
diff --git a/arch/arm/dts/armada-388-helios4-u-boot.dtsi b/arch/arm/dts/armada-388-helios4-u-boot.dtsi new file mode 100644 index 0000000..4b20610 --- /dev/null +++ b/arch/arm/dts/armada-388-helios4-u-boot.dtsi
@@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/ { + aliases { + i2c0 = &i2c0; + i2c1 = &i2c1; + spi1 = &spi1; + }; +}; + +ð0 { + phy-reset-gpios = <&gpio0 19 GPIO_ACTIVE_LOW>; +}; + +&spi1 { + u-boot,dm-spl; +}; + +&w25q32 { + status = "okay"; + u-boot,dm-spl; +};
diff --git a/arch/arm/dts/armada-388-helios4.dts b/arch/arm/dts/armada-388-helios4.dts new file mode 100644 index 0000000..a154e0f --- /dev/null +++ b/arch/arm/dts/armada-388-helios4.dts
@@ -0,0 +1,308 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Device Tree file for Helios4 + * based on SolidRun Clearfog revision A1 rev 2.0 (88F6828) + * + * Copyright (C) 2017 Aditya Prayoga <aditya@kobol.io> + * + */ + +/dts-v1/; +#include "armada-388.dtsi" +#include "armada-38x-solidrun-microsom.dtsi" + +/ { + model = "Helios4"; + compatible = "kobol,helios4", "marvell,armada388", + "marvell,armada385", "marvell,armada380"; + + memory { + device_type = "memory"; + reg = <0x00000000 0x80000000>; /* 2 GB */ + }; + + aliases { + /* So that mvebu u-boot can update the MAC addresses */ + ethernet1 = ð0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + reg_12v: regulator-12v { + compatible = "regulator-fixed"; + regulator-name = "power_brick_12V"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + regulator-always-on; + }; + + reg_3p3v: regulator-3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + vin-supply = <®_12v>; + }; + + reg_5p0v_hdd: regulator-5v-hdd { + compatible = "regulator-fixed"; + regulator-name = "5V_HDD"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + vin-supply = <®_12v>; + }; + + reg_5p0v_usb: regulator-5v-usb { + compatible = "regulator-fixed"; + regulator-name = "USB-PWR"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + regulator-always-on; + enable-active-high; + gpio = <&expander0 6 GPIO_ACTIVE_HIGH>; + vin-supply = <®_12v>; + }; + + system-leds { + compatible = "gpio-leds"; + status-led { + label = "helios4:green:status"; + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + linux,default-trigger = "heartbeat"; + default-state = "on"; + }; + + fault-led { + label = "helios4:red:fault"; + gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + default-state = "keep"; + }; + }; + + io-leds { + compatible = "gpio-leds"; + sata1-led { + label = "helios4:green:ata1"; + gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; + linux,default-trigger = "ata1"; + default-state = "off"; + }; + sata2-led { + label = "helios4:green:ata2"; + gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; + linux,default-trigger = "ata2"; + default-state = "off"; + }; + sata3-led { + label = "helios4:green:ata3"; + gpios = <&gpio1 20 GPIO_ACTIVE_LOW>; + linux,default-trigger = "ata3"; + default-state = "off"; + }; + sata4-led { + label = "helios4:green:ata4"; + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; + linux,default-trigger = "ata4"; + default-state = "off"; + }; + usb-led { + label = "helios4:green:usb"; + gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; + linux,default-trigger = "usb-host"; + default-state = "off"; + }; + }; + + fan1: j10-pwm { + compatible = "pwm-fan"; + pwms = <&gpio1 9 40000>; /* Target freq:25 kHz */ + }; + + fan2: j17-pwm { + compatible = "pwm-fan"; + pwms = <&gpio1 23 40000>; /* Target freq:25 kHz */ + }; + + usb2_phy: usb2-phy { + compatible = "usb-nop-xceiv"; + vbus-regulator = <®_5p0v_usb>; + }; + + usb3_phy: usb3-phy { + compatible = "usb-nop-xceiv"; + }; + + soc { + internal-regs { + i2c@11000 { + clock-frequency = <400000>; + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + status = "okay"; + + /* + * PCA9655 GPIO expander, up to 1MHz clock. + * 0-Board Revision bit 0 # + * 1-Board Revision bit 1 # + * 5-USB3 overcurrent + * 6-USB3 power + */ + expander0: gpio-expander@20 { + /* + * This is how it should be: + * compatible = "onnn,pca9655", + * "nxp,pca9555"; + * but you can't do this because of + * the way I2C works. + */ + compatible = "nxp,pca9555"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x20>; + pinctrl-names = "default"; + pinctrl-0 = <&pca0_pins>; + interrupt-parent = <&gpio0>; + interrupts = <23 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + + board_rev_bit_0 { + gpio-hog; + gpios = <0 GPIO_ACTIVE_LOW>; + input; + line-name = "board-rev-0"; + }; + board_rev_bit_1 { + gpio-hog; + gpios = <1 GPIO_ACTIVE_LOW>; + input; + line-name = "board-rev-1"; + }; + usb3_ilimit { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + input; + line-name = + "usb-overcurrent-status"; + }; + }; + + temp_sensor: temp@4c { + compatible = "ti,lm75"; + reg = <0x4c>; + vcc-supply = <®_3p3v>; + }; + }; + + i2c@11100 { + /* + * External I2C Bus for user peripheral + */ + clock-frequency = <400000>; + pinctrl-0 = <&helios_i2c1_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + sata@a8000 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + sata0: sata-port@0 { + reg = <0>; + }; + + sata1: sata-port@1 { + reg = <1>; + }; + }; + + sata@e0000 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + sata2: sata-port@0 { + reg = <0>; + }; + + sata3: sata-port@1 { + reg = <1>; + }; + }; + + spi@10680 { + pinctrl-0 = <&spi1_pins + µsom_spi1_cs_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + sdhci@d8000 { + bus-width = <4>; + cd-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; + no-1-8-v; + pinctrl-0 = <µsom_sdhci_pins + &helios_sdhci_cd_pins>; + pinctrl-names = "default"; + status = "okay"; + vmmc = <®_3p3v>; + wp-inverted; + }; + + usb@58000 { + usb-phy = <&usb2_phy>; + status = "okay"; + }; + + usb3@f0000 { + status = "okay"; + }; + + usb3@f8000 { + status = "okay"; + }; + + pinctrl@18000 { + pca0_pins: pca0-pins { + marvell,pins = "mpp23"; + marvell,function = "gpio"; + }; + microsom_phy0_int_pins: microsom-phy0-int-pins { + marvell,pins = "mpp18"; + marvell,function = "gpio"; + }; + helios_i2c1_pins: i2c1-pins { + marvell,pins = "mpp26", "mpp27"; + marvell,function = "i2c1"; + }; + helios_sdhci_cd_pins: helios-sdhci-cd-pins { + marvell,pins = "mpp20"; + marvell,function = "gpio"; + }; + helios_led_pins: helios-led-pins { + marvell,pins = "mpp24", "mpp25", + "mpp49", "mpp50", + "mpp52", "mpp53", + "mpp54"; + marvell,function = "gpio"; + }; + helios_fan_pins: helios-fan-pins { + marvell,pins = "mpp41", "mpp43", + "mpp48", "mpp55"; + marvell,function = "gpio"; + }; + microsom_spi1_cs_pins: spi1-cs-pins { + marvell,pins = "mpp59"; + marvell,function = "spi1"; + }; + }; + }; + }; +};
diff --git a/arch/arm/dts/armada-388.dtsi b/arch/arm/dts/armada-388.dtsi new file mode 100644 index 0000000..564fa59 --- /dev/null +++ b/arch/arm/dts/armada-388.dtsi
@@ -0,0 +1,70 @@ +/* + * Device Tree Include file for Marvell Armada 388 SoC. + * + * Copyright (C) 2015 Marvell + * + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * + * The main difference with the Armada 385 is that the 388 can handle two more + * SATA ports. So we can reuse the dtsi of the Armada 385, override the pinctrl + * property and the name of the SoC, and add the second SATA host which control + * the 2 other ports. + */ + +#include "armada-385.dtsi" + +/ { + model = "Marvell Armada 388 family SoC"; + compatible = "marvell,armada388", "marvell,armada385", + "marvell,armada380"; + + soc { + internal-regs { + pinctrl@18000 { + compatible = "marvell,mv88f6828-pinctrl"; + }; + + sata@e0000 { + compatible = "marvell,armada-380-ahci"; + reg = <0xe0000 0x2000>; + interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 30>; + status = "disabled"; + }; + + }; + }; +};
diff --git a/arch/arm/dts/armada-38x-controlcenterdc.dts b/arch/arm/dts/armada-38x-controlcenterdc.dts new file mode 100644 index 0000000..2cc9968 --- /dev/null +++ b/arch/arm/dts/armada-38x-controlcenterdc.dts
@@ -0,0 +1,588 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Device Tree file for the Guntermann & Drunck ControlCenter-Compact board + * + * Copyright (C) 2016 Mario Six <mario.six@gdsys.cc> + * + * based on the Device Tree file for Marvell Armada 388 evaluation board + * (DB-88F6820), which is + * + * Copyright (C) 2014 Marvell + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + */ + +/dts-v1/; + +#include "armada-388.dtsi" + +&gpio0 { + u-boot,dm-pre-reloc; +}; + +&gpio1 { + u-boot,dm-pre-reloc; +}; + +&uart0 { + u-boot,dm-pre-reloc; +}; + +&uart1 { + u-boot,dm-pre-reloc; +}; + +/ { + model = "Controlcenter Digital Compact"; + compatible = "marvell,a385-db", "marvell,armada388", + "marvell,armada385", "marvell,armada380"; + + chosen { + bootargs = "console=ttyS1,115200 earlyprintk"; + stdout-path = "/soc/internal-regs/serial@12100"; + }; + + aliases { + ethernet0 = ð0; + ethernet2 = ð2; + mdio-gpio0 = &MDIO0; + mdio-gpio1 = &MDIO1; + mdio-gpio2 = &MDIO2; + spi0 = &spi0; + spi1 = &spi1; + i2c0 = &I2C0; + i2c1 = &I2C1; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x10000000>; /* 256 MB */ + }; + + clocks { + sc16isclk: sc16isclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <11059200>; + }; + }; + + soc { + ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>; + + internal-regs { + spi0: spi@10600 { + status = "okay"; + sc16is741: sc16is741@0 { + compatible = "nxp,sc16is741"; + reg = <0>; + clocks = <&sc16isclk>; + spi-max-frequency = <4000000>; + interrupt-parent = <&gpio0>; + interrupts = <11 IRQ_TYPE_EDGE_FALLING>; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + spi1: spi@10680 { + status = "okay"; + u-boot,dm-pre-reloc; + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q016a", "spi-flash"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; + }; + spi-flash@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a11", "spi-flash"; + reg = <1>; /* Chip select 1 */ + spi-max-frequency = <108000000>; + u-boot,dm-pre-reloc; + }; + }; + + I2C0: i2c@11000 { + status = "okay"; + clock-frequency = <1000000>; + u-boot,dm-pre-reloc; + PCA21: pca9698@21 { + compatible = "nxp,pca9698"; + reg = <0x21>; + #gpio-cells = <2>; + gpio-controller; + }; + PCA22: pca9698@22 { + compatible = "nxp,pca9698"; + u-boot,dm-pre-reloc; + reg = <0x22>; + #gpio-cells = <2>; + gpio-controller; + }; + PCA23: pca9698@23 { + compatible = "nxp,pca9698"; + reg = <0x23>; + #gpio-cells = <2>; + gpio-controller; + }; + PCA24: pca9698@24 { + compatible = "nxp,pca9698"; + reg = <0x24>; + #gpio-cells = <2>; + gpio-controller; + }; + PCA25: pca9698@25 { + compatible = "nxp,pca9698"; + reg = <0x25>; + #gpio-cells = <2>; + gpio-controller; + }; + PCA26: pca9698@26 { + compatible = "nxp,pca9698"; + reg = <0x26>; + #gpio-cells = <2>; + gpio-controller; + }; + }; + + I2C1: i2c@11100 { + status = "okay"; + clock-frequency = <400000>; + at97sc3205t@29 { + compatible = "atmel,at97sc3204t"; + reg = <0x29>; + u-boot,i2c-offset-len = <0>; + }; + emc2305@2d { + compatible = "smsc,emc2305"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2d>; + fan@0 { + reg = <0>; + }; + fan@1 { + reg = <1>; + }; + fan@2 { + reg = <2>; + }; + fan@3 { + reg = <3>; + }; + fan@4 { + reg = <4>; + }; + }; + lm77@48 { + compatible = "national,lm77"; + reg = <0x48>; + }; + ads1015@49 { + compatible = "ti,ads1015"; + reg = <0x49>; + }; + lm77@4a { + compatible = "national,lm77"; + reg = <0x4a>; + }; + ads1015@4b { + compatible = "ti,ads1015"; + reg = <0x4b>; + }; + emc2305@4c { + compatible = "smsc,emc2305"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x4c>; + fan@0 { + reg = <0>; + }; + fan@1 { + reg = <1>; + }; + fan@2 { + reg = <2>; + }; + fan@3 { + reg = <3>; + }; + fan@4 { + reg = <4>; + }; + }; + at24c512@54 { + compatible = "atmel,24c512"; + reg = <0x54>; + u-boot,i2c-offset-len = <2>; + }; + ds1339@68 { + compatible = "dallas,ds1339"; + reg = <0x68>; + }; + }; + + serial@12000 { + status = "okay"; + }; + + serial@12100 { + status = "okay"; + }; + + ethernet@34000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "sgmii"; + }; + + usb@58000 { + status = "ok"; + }; + + ethernet@70000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "sgmii"; + }; + + mdio@72004 { + phy0: ethernet-phy@0 { + reg = <1>; + }; + + phy1: ethernet-phy@1 { + reg = <0>; + }; + }; + + sata@a8000 { + status = "okay"; + }; + + sdhci@d8000 { + broken-cd; + wp-inverted; + bus-width = <4>; + status = "okay"; + no-1-8-v; + }; + + usb3@f0000 { + status = "okay"; + }; + }; + + pcie-controller { + status = "okay"; + /* + * The two PCIe units are accessible through + * standard PCIe slots on the board. + */ + pcie@3,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + }; + + MDIO0: mdio0 { + compatible = "virtual,mdio-gpio"; + #address-cells = <1>; + #size-cells = <0>; + gpios = < /*MDC*/ &gpio0 13 0 + /*MDIO*/ &gpio0 14 0>; + mv88e1240@0 { + reg = <0x0>; + }; + mv88e1240@1 { + reg = <0x1>; + }; + mv88e1240@2 { + reg = <0x2>; + }; + mv88e1240@3 { + reg = <0x3>; + }; + mv88e1240@4 { + reg = <0x4>; + }; + mv88e1240@5 { + reg = <0x5>; + }; + mv88e1240@6 { + reg = <0x6>; + }; + mv88e1240@7 { + reg = <0x7>; + }; + mv88e1240@8 { + reg = <0x8>; + }; + mv88e1240@9 { + reg = <0x9>; + }; + mv88e1240@a { + reg = <0xa>; + }; + mv88e1240@b { + reg = <0xb>; + }; + mv88e1240@c { + reg = <0xc>; + }; + mv88e1240@d { + reg = <0xd>; + }; + mv88e1240@e { + reg = <0xe>; + }; + mv88e1240@f { + reg = <0xf>; + }; + mv88e1240@10 { + reg = <0x10>; + }; + mv88e1240@11 { + reg = <0x11>; + }; + mv88e1240@12 { + reg = <0x12>; + }; + mv88e1240@13 { + reg = <0x13>; + }; + mv88e1240@14 { + reg = <0x14>; + }; + mv88e1240@15 { + reg = <0x15>; + }; + mv88e1240@16 { + reg = <0x16>; + }; + mv88e1240@17 { + reg = <0x17>; + }; + mv88e1240@18 { + reg = <0x18>; + }; + mv88e1240@19 { + reg = <0x19>; + }; + mv88e1240@1a { + reg = <0x1a>; + }; + mv88e1240@1b { + reg = <0x1b>; + }; + mv88e1240@1c { + reg = <0x1c>; + }; + mv88e1240@1d { + reg = <0x1d>; + }; + mv88e1240@1e { + reg = <0x1e>; + }; + mv88e1240@1f { + reg = <0x1f>; + }; + }; + + MDIO1: mdio1 { + compatible = "virtual,mdio-gpio"; + #address-cells = <1>; + #size-cells = <0>; + gpios = < /*MDC*/ &gpio0 25 0 + /*MDIO*/ &gpio1 13 0>; + mv88e1240@0 { + reg = <0x0>; + }; + mv88e1240@1 { + reg = <0x1>; + }; + mv88e1240@2 { + reg = <0x2>; + }; + mv88e1240@3 { + reg = <0x3>; + }; + mv88e1240@4 { + reg = <0x4>; + }; + mv88e1240@5 { + reg = <0x5>; + }; + mv88e1240@6 { + reg = <0x6>; + }; + mv88e1240@7 { + reg = <0x7>; + }; + mv88e1240@8 { + reg = <0x8>; + }; + mv88e1240@9 { + reg = <0x9>; + }; + mv88e1240@a { + reg = <0xa>; + }; + mv88e1240@b { + reg = <0xb>; + }; + mv88e1240@c { + reg = <0xc>; + }; + mv88e1240@d { + reg = <0xd>; + }; + mv88e1240@e { + reg = <0xe>; + }; + mv88e1240@f { + reg = <0xf>; + }; + mv88e1240@10 { + reg = <0x10>; + }; + mv88e1240@11 { + reg = <0x11>; + }; + mv88e1240@12 { + reg = <0x12>; + }; + mv88e1240@13 { + reg = <0x13>; + }; + mv88e1240@14 { + reg = <0x14>; + }; + mv88e1240@15 { + reg = <0x15>; + }; + mv88e1240@16 { + reg = <0x16>; + }; + mv88e1240@17 { + reg = <0x17>; + }; + mv88e1240@18 { + reg = <0x18>; + }; + mv88e1240@19 { + reg = <0x19>; + }; + mv88e1240@1a { + reg = <0x1a>; + }; + mv88e1240@1b { + reg = <0x1b>; + }; + mv88e1240@1c { + reg = <0x1c>; + }; + mv88e1240@1d { + reg = <0x1d>; + }; + mv88e1240@1e { + reg = <0x1e>; + }; + mv88e1240@1f { + reg = <0x1f>; + }; + }; + + MDIO2: mdio2 { + compatible = "virtual,mdio-gpio"; + #address-cells = <1>; + #size-cells = <0>; + gpios = < /*MDC*/ &gpio1 14 0 + /*MDIO*/ &gpio0 24 0>; + mv88e1240@0 { + reg = <0x0>; + }; + mv88e1240@1 { + reg = <0x1>; + }; + mv88e1240@2 { + reg = <0x2>; + }; + mv88e1240@3 { + reg = <0x3>; + }; + mv88e1240@4 { + reg = <0x4>; + }; + mv88e1240@5 { + reg = <0x5>; + }; + mv88e1240@6 { + reg = <0x6>; + }; + mv88e1240@7 { + reg = <0x7>; + }; + mv88e1240@8 { + reg = <0x8>; + }; + mv88e1240@9 { + reg = <0x9>; + }; + mv88e1240@a { + reg = <0xa>; + }; + mv88e1240@b { + reg = <0xb>; + }; + mv88e1240@c { + reg = <0xc>; + }; + mv88e1240@d { + reg = <0xd>; + }; + mv88e1240@e { + reg = <0xe>; + }; + mv88e1240@f { + reg = <0xf>; + }; + mv88e1240@10 { + reg = <0x10>; + }; + mv88e1240@11 { + reg = <0x11>; + }; + mv88e1240@12 { + reg = <0x12>; + }; + mv88e1240@13 { + reg = <0x13>; + }; + mv88e1240@14 { + reg = <0x14>; + }; + mv88e1240@15 { + reg = <0x15>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + finder_led { + label = "finder-led"; + gpios = <&PCA22 25 0>; + }; + + status_led { + label = "status-led"; + gpios = <&gpio0 29 0>; + }; + }; +};
diff --git a/arch/arm/dts/armada-38x-solidrun-microsom.dtsi b/arch/arm/dts/armada-38x-solidrun-microsom.dtsi new file mode 100644 index 0000000..74f58de --- /dev/null +++ b/arch/arm/dts/armada-38x-solidrun-microsom.dtsi
@@ -0,0 +1,101 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Device Tree file for SolidRun Armada 38x Microsom + * + * Copyright (C) 2015 Russell King + * + * This board is in development; the contents of this file work with + * the A1 rev 2.0 of the board, which does not represent final + * production board. Things will change, don't expect this file to + * remain compatible info the future. + */ +#include <dt-bindings/input/input.h> +#include <dt-bindings/gpio/gpio.h> + +/ { + memory { + device_type = "memory"; + reg = <0x00000000 0x10000000>; /* 256 MB */ + }; + + soc { + ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 + MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 + MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; + + internal-regs { + rtc@a3800 { + /* + * If the rtc doesn't work, run "date reset" + * twice in u-boot. + */ + status = "okay"; + }; + }; + }; +}; + +ð0 { + /* ethernet@70000 */ + mac-address = [00 50 43 02 02 01]; + pinctrl-0 = <&ge0_rgmii_pins>; + pinctrl-names = "default"; + phy = <&phy_dedicated>; + phy-mode = "rgmii-id"; + status = "okay"; +}; + +&mdio { + /* + * Add the phy clock here, so the phy can be accessed to read its + * IDs prior to binding with the driver. + */ + pinctrl-0 = <&mdio_pins µsom_phy_clk_pins>; + pinctrl-names = "default"; + + phy_dedicated: ethernet-phy@0 { + /* + * Annoyingly, the marvell phy driver configures the LED + * register, rather than preserving reset-loaded setting. + * We undo that rubbish here. + */ + marvell,reg-init = <3 16 0 0x101e>; + reg = <0>; + }; +}; + +&pinctrl { + microsom_phy_clk_pins: microsom-phy-clk-pins { + marvell,pins = "mpp45"; + marvell,function = "ref"; + }; + /* Optional eMMC */ + microsom_sdhci_pins: microsom-sdhci-pins { + marvell,pins = "mpp21", "mpp28", "mpp37", + "mpp38", "mpp39", "mpp40"; + marvell,function = "sd0"; + }; +}; + +&spi1 { + /* The microsom has an optional W25Q32 on board, connected to CS0 */ + pinctrl-0 = <&spi1_pins>; + + w25q32: spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q32", "jedec,spi-nor", "spi-flash"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <3000000>; + status = "disabled"; + }; +}; + +&uart0 { + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; + status = "okay"; + u-boot,dm-pre-reloc; +};
diff --git a/arch/arm/dts/armada-38x.dtsi b/arch/arm/dts/armada-38x.dtsi new file mode 100644 index 0000000..5e5a158 --- /dev/null +++ b/arch/arm/dts/armada-38x.dtsi
@@ -0,0 +1,615 @@ +/* + * Device Tree Include file for Marvell Armada 38x family of SoCs. + * + * Copyright (C) 2014 Marvell + * + * Lior Amsalem <alior@marvell.com> + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "skeleton.dtsi" +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/interrupt-controller/irq.h> + +#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16)) + +/ { + model = "Marvell Armada 38x family SoC"; + compatible = "marvell,armada380"; + + aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + serial0 = &uart0; + serial1 = &uart1; + }; + + pmu { + compatible = "arm,cortex-a9-pmu"; + interrupts-extended = <&mpic 3>; + }; + + soc { + compatible = "marvell,armada380-mbus", "simple-bus"; + u-boot,dm-pre-reloc; + #address-cells = <2>; + #size-cells = <1>; + controller = <&mbusc>; + interrupt-parent = <&gic>; + pcie-mem-aperture = <0xe0000000 0x8000000>; + pcie-io-aperture = <0xe8000000 0x100000>; + + bootrom { + compatible = "marvell,bootrom"; + reg = <MBUS_ID(0x01, 0x1d) 0 0x200000>; + }; + + devbus-bootcs { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>; + ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs0 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>; + ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs1 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>; + ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs2 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>; + ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs3 { + compatible = "marvell,mvebu-devbus"; + reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>; + ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + internal-regs { + compatible = "simple-bus"; + u-boot,dm-pre-reloc; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>; + + L2: cache-controller@8000 { + compatible = "arm,pl310-cache"; + reg = <0x8000 0x1000>; + cache-unified; + cache-level = <2>; + }; + + scu@c000 { + compatible = "arm,cortex-a9-scu"; + reg = <0xc000 0x58>; + }; + + timer@c600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0xc600 0x20>; + interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2))>; + clocks = <&coreclk 2>; + }; + + gic: interrupt-controller@d000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #size-cells = <0>; + interrupt-controller; + reg = <0xd000 0x1000>, + <0xc100 0x100>; + }; + + spi0: spi@10600 { + compatible = "marvell,armada-380-spi", + "marvell,orion-spi"; + reg = <0x10600 0x50>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + spi1: spi@10680 { + compatible = "marvell,armada-380-spi", + "marvell,orion-spi"; + reg = <0x10680 0x50>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + i2c0: i2c@11000 { + compatible = "marvell,mv64xxx-i2c"; + reg = <0x11000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; + timeout-ms = <1000>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + i2c1: i2c@11100 { + compatible = "marvell,mv64xxx-i2c"; + reg = <0x11100 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; + timeout-ms = <1000>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + uart0: serial@12000 { + compatible = "snps,dw-apb-uart"; + reg = <0x12000 0x100>; + reg-shift = <2>; + interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; + reg-io-width = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + uart1: serial@12100 { + compatible = "snps,dw-apb-uart"; + reg = <0x12100 0x100>; + reg-shift = <2>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; + reg-io-width = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + pinctrl: pinctrl@18000 { + reg = <0x18000 0x20>; + + ge0_rgmii_pins: ge-rgmii-pins-0 { + marvell,pins = "mpp6", "mpp7", "mpp8", + "mpp9", "mpp10", "mpp11", + "mpp12", "mpp13", "mpp14", + "mpp15", "mpp16", "mpp17"; + marvell,function = "ge0"; + }; + + ge1_rgmii_pins: ge-rgmii-pins-1 { + marvell,pins = "mpp21", "mpp27", "mpp28", + "mpp29", "mpp30", "mpp31", + "mpp32", "mpp37", "mpp38", + "mpp39", "mpp40", "mpp41"; + marvell,function = "ge1"; + }; + + i2c0_pins: i2c-pins-0 { + marvell,pins = "mpp2", "mpp3"; + marvell,function = "i2c0"; + }; + + nand_pins: nand-pins { + marvell,pins = "mpp22", "mpp34", "mpp23", "mpp33", + "mpp38", "mpp28", "mpp40", "mpp42", + "mpp35", "mpp36", "mpp25", "mpp30", + "mpp32"; + marvell,function = "dev"; + }; + + nand_rb: nand-rb { + marvell,pins = "mpp41"; + marvell,function = "nand"; + }; + + mdio_pins: mdio-pins { + marvell,pins = "mpp4", "mpp5"; + marvell,function = "ge"; + }; + + ref_clk0_pins: ref-clk-pins-0 { + marvell,pins = "mpp45"; + marvell,function = "ref"; + }; + + ref_clk1_pins: ref-clk-pins-1 { + marvell,pins = "mpp46"; + marvell,function = "ref"; + }; + + spi0_pins: spi-pins-0 { + marvell,pins = "mpp22", "mpp23", "mpp24", + "mpp25"; + marvell,function = "spi0"; + }; + + spi1_pins: spi-pins-1 { + marvell,pins = "mpp56", "mpp57", "mpp58", + "mpp59"; + marvell,function = "spi1"; + }; + + uart0_pins: uart-pins-0 { + marvell,pins = "mpp0", "mpp1"; + marvell,function = "ua0"; + }; + + uart1_pins: uart-pins-1 { + marvell,pins = "mpp19", "mpp20"; + marvell,function = "ua1"; + }; + + sdhci_pins: sdhci-pins { + marvell,pins = "mpp48", "mpp49", "mpp50", + "mpp52", "mpp53", "mpp54", + "mpp55", "mpp57", "mpp58", + "mpp59"; + marvell,function = "sd0"; + }; + + sata0_pins: sata-pins-0 { + marvell,pins = "mpp20"; + marvell,function = "sata0"; + }; + + sata1_pins: sata-pins-1 { + marvell,pins = "mpp19"; + marvell,function = "sata1"; + }; + + sata2_pins: sata-pins-2 { + marvell,pins = "mpp47"; + marvell,function = "sata2"; + }; + + sata3_pins: sata-pins-3 { + marvell,pins = "mpp44"; + marvell,function = "sata3"; + }; + }; + + gpio0: gpio@18100 { + compatible = "marvell,orion-gpio"; + reg = <0x18100 0x40>; + ngpios = <32>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>; + }; + + gpio1: gpio@18140 { + compatible = "marvell,orion-gpio"; + reg = <0x18140 0x40>; + ngpios = <28>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; + }; + + system-controller@18200 { + compatible = "marvell,armada-380-system-controller", + "marvell,armada-370-xp-system-controller"; + reg = <0x18200 0x100>; + }; + + gateclk: clock-gating-control@18220 { + compatible = "marvell,armada-380-gating-clock"; + reg = <0x18220 0x4>; + clocks = <&coreclk 0>; + #clock-cells = <1>; + }; + + coreclk: mvebu-sar@18600 { + compatible = "marvell,armada-380-core-clock"; + reg = <0x18600 0x04>; + #clock-cells = <1>; + }; + + mbusc: mbus-controller@20000 { + compatible = "marvell,mbus-controller"; + reg = <0x20000 0x100>, <0x20180 0x20>; + }; + + mpic: interrupt-controller@20a00 { + compatible = "marvell,mpic"; + reg = <0x20a00 0x2d0>, <0x21070 0x58>; + #interrupt-cells = <1>; + #size-cells = <1>; + interrupt-controller; + msi-controller; + interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>; + }; + + timer@20300 { + compatible = "marvell,armada-380-timer", + "marvell,armada-xp-timer"; + reg = <0x20300 0x30>, <0x21040 0x30>; + interrupts-extended = <&gic GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>, + <&gic GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, + <&mpic 5>, + <&mpic 6>; + clocks = <&coreclk 2>, <&refclk>; + clock-names = "nbclk", "fixed"; + }; + + watchdog@20300 { + compatible = "marvell,armada-380-wdt"; + reg = <0x20300 0x34>, <0x20704 0x4>, <0x18260 0x4>; + clocks = <&coreclk 2>, <&refclk>; + clock-names = "nbclk", "fixed"; + }; + + cpurst@20800 { + compatible = "marvell,armada-370-cpu-reset"; + reg = <0x20800 0x10>; + }; + + mpcore-soc-ctrl@20d20 { + compatible = "marvell,armada-380-mpcore-soc-ctrl"; + reg = <0x20d20 0x6c>; + }; + + coherency-fabric@21010 { + compatible = "marvell,armada-380-coherency-fabric"; + reg = <0x21010 0x1c>; + }; + + pmsu@22000 { + compatible = "marvell,armada-380-pmsu"; + reg = <0x22000 0x1000>; + }; + + eth1: ethernet@30000 { + compatible = "marvell,armada-370-neta"; + reg = <0x30000 0x4000>; + interrupts-extended = <&mpic 10>; + clocks = <&gateclk 3>; + status = "disabled"; + }; + + eth2: ethernet@34000 { + compatible = "marvell,armada-370-neta"; + reg = <0x34000 0x4000>; + interrupts-extended = <&mpic 12>; + clocks = <&gateclk 2>; + status = "disabled"; + }; + + usb@58000 { + compatible = "marvell,orion-ehci"; + reg = <0x58000 0x500>; + interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 18>; + status = "disabled"; + }; + + xor@60800 { + compatible = "marvell,orion-xor"; + reg = <0x60800 0x100 + 0x60a00 0x100>; + clocks = <&gateclk 22>; + status = "okay"; + + xor00 { + interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>; + dmacap,memcpy; + dmacap,xor; + }; + xor01 { + interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>; + dmacap,memcpy; + dmacap,xor; + dmacap,memset; + }; + }; + + xor@60900 { + compatible = "marvell,orion-xor"; + reg = <0x60900 0x100 + 0x60b00 0x100>; + clocks = <&gateclk 28>; + status = "okay"; + + xor10 { + interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; + dmacap,memcpy; + dmacap,xor; + }; + xor11 { + interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>; + dmacap,memcpy; + dmacap,xor; + dmacap,memset; + }; + }; + + eth0: ethernet@70000 { + compatible = "marvell,armada-370-neta"; + reg = <0x70000 0x4000>; + interrupts-extended = <&mpic 8>; + clocks = <&gateclk 4>; + status = "disabled"; + }; + + mdio: mdio@72004 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "marvell,orion-mdio"; + reg = <0x72004 0x4>; + clocks = <&gateclk 4>; + }; + + rtc@a3800 { + compatible = "marvell,armada-380-rtc"; + reg = <0xa3800 0x20>, <0x184a0 0x0c>; + reg-names = "rtc", "rtc-soc"; + interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; + }; + + sata@a8000 { + compatible = "marvell,armada-380-ahci"; + reg = <0xa8000 0x2000>; + interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 15>; + status = "disabled"; + }; + + sata@e0000 { + compatible = "marvell,armada-380-ahci"; + reg = <0xe0000 0x2000>; + interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 30>; + status = "disabled"; + }; + + coredivclk: clock@e4250 { + compatible = "marvell,armada-380-corediv-clock"; + reg = <0xe4250 0xc>; + #clock-cells = <1>; + clocks = <&mainpll>; + clock-output-names = "nand"; + }; + + thermal@e8078 { + compatible = "marvell,armada380-thermal"; + reg = <0xe4078 0x4>, <0xe4074 0x4>; + status = "okay"; + }; + + flash@d0000 { + compatible = "marvell,armada370-nand","marvell,mvebu-pxa3xx-nand"; + reg = <0xd0000 0x54>; + #address-cells = <1>; + #size-cells = <1>; + interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&coredivclk 0>; + status = "disabled"; + }; + + sdhci@d8000 { + compatible = "marvell,armada-380-sdhci"; + reg-names = "sdhci", "mbus", "conf-sdio3"; + reg = <0xd8000 0x1000>, + <0xdc000 0x100>, + <0x18454 0x4>; + interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 17>; + mrvl,clk-delay-cycles = <0x1F>; + status = "disabled"; + }; + + usb3@f0000 { + compatible = "marvell,armada-380-xhci"; + reg = <0xf0000 0x4000>,<0xf4000 0x4000>; + interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 9>; + status = "disabled"; + }; + + usb3@f8000 { + compatible = "marvell,armada-380-xhci"; + reg = <0xf8000 0x4000>,<0xfc000 0x4000>; + interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&gateclk 10>; + status = "disabled"; + }; + }; + }; + + clocks { + /* 2 GHz fixed main PLL */ + mainpll: mainpll { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000000>; + }; + + /* 25 MHz reference crystal */ + refclk: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + }; +};
diff --git a/arch/arm/dts/armada-7040-db-nand.dts b/arch/arm/dts/armada-7040-db-nand.dts new file mode 100644 index 0000000..3a9df21 --- /dev/null +++ b/arch/arm/dts/armada-7040-db-nand.dts
@@ -0,0 +1,223 @@ +/* + * Copyright (C) 2017 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This library 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 library 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Device Tree file for Marvell Armada 7040 Development board platform + * Boot device: NAND, 0xE (SW3) + */ + +#include "armada-7040.dtsi" + +/ { + model = "Marvell Armada 7040 DB board with NAND"; + compatible = "marvell,armada7040-db-nand", "marvell,armada7040-db", + "marvell,armada7040", "marvell,armada-ap806-quad", + "marvell,armada-ap806"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + i2c0 = &cpm_i2c0; + spi0 = &cpm_spi1; + }; + + memory@00000000 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; +}; + +&ap_pinctl { + /* MPP Bus: + * SDIO [0-5] + * UART0 [11,19] + */ + /* 0 1 2 3 4 5 6 7 8 9 */ + pin-func = < 0x1 0x1 0x1 0x1 0x1 0x1 0x0 0x0 0x0 0x0 + 0x0 0x3 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x3 >; +}; + +&uart0 { + status = "okay"; +}; + + +&cpm_pcie2 { + status = "okay"; +}; + +&cpm_i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&cpm_i2c0_pins>; + status = "okay"; + clock-frequency = <100000>; +}; + +&cpm_pinctl { + /* MPP Bus: + * AUDIO [0-5] + * GBE [6-11] + * SS_PWDN [12] + * NF_RBn [13] + * GPIO [14] + * DEV_BUS [15-27] + * SATA1 [28] + * UART0 [29-30] + * MSS_VTT_EN [31] + * SMI [32,34] + * XSMI [35-36] + * I2C [37-38] + * RGMII1 [44-55] + * SD [56-61] + * GPIO [62] + */ + /* 0 1 2 3 4 5 6 7 8 9 */ + pin-func = < 0x2 0x2 0x2 0x2 0x2 0x2 0x3 0x3 0x3 0x3 + 0x3 0x3 0x0 0x2 0x0 0x1 0x1 0x1 0x1 0x1 + 0x1 0x1 0x1 0x1 0x1 0x1 0x1 0x1 0x9 0xa + 0xa 0x0 0x7 0x0 0x7 0x7 0x7 0x2 0x2 0x0 + 0x0 0x0 0x0 0x0 0x1 0x1 0x1 0x1 0x1 0x1 +