Merge branch 'master' of git://git.denx.de/u-boot-arm
authorTom Rini <trini@ti.com>
Tue, 12 Feb 2013 15:18:31 +0000 (10:18 -0500)
committerTom Rini <trini@ti.com>
Tue, 12 Feb 2013 15:18:31 +0000 (10:18 -0500)
198 files changed:
.gitignore
MAINTAINERS
Makefile
arch/arm/cpu/arm720t/tegra-common/Makefile
arch/arm/cpu/arm720t/tegra-common/cpu.c [new file with mode: 0644]
arch/arm/cpu/arm720t/tegra-common/cpu.h
arch/arm/cpu/arm720t/tegra-common/spl.c
arch/arm/cpu/arm720t/tegra114/Makefile [new file with mode: 0644]
arch/arm/cpu/arm720t/tegra114/config.mk [new file with mode: 0644]
arch/arm/cpu/arm720t/tegra114/cpu.c [new file with mode: 0644]
arch/arm/cpu/arm720t/tegra20/cpu.c
arch/arm/cpu/arm720t/tegra30/Makefile [new file with mode: 0644]
arch/arm/cpu/arm720t/tegra30/config.mk [new file with mode: 0644]
arch/arm/cpu/arm720t/tegra30/cpu.c [new file with mode: 0644]
arch/arm/cpu/arm926ejs/config.mk
arch/arm/cpu/arm926ejs/mxs/clock.c
arch/arm/cpu/arm926ejs/mxs/mxs.c
arch/arm/cpu/arm926ejs/mxs/spl_boot.c
arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
arch/arm/cpu/arm926ejs/mxs/spl_power_init.c
arch/arm/cpu/arm926ejs/mxs/u-boot-imx23.bd [new file with mode: 0644]
arch/arm/cpu/armv7/Makefile
arch/arm/cpu/armv7/config.mk
arch/arm/cpu/armv7/start.S
arch/arm/cpu/armv7/tegra114/Makefile [new file with mode: 0644]
arch/arm/cpu/armv7/tegra114/config.mk [new file with mode: 0644]
arch/arm/cpu/armv7/tegra30/Makefile [new file with mode: 0644]
arch/arm/cpu/armv7/tegra30/config.mk [new file with mode: 0644]
arch/arm/cpu/tegra-common/Makefile
arch/arm/cpu/tegra-common/ap.c
arch/arm/cpu/tegra-common/board.c
arch/arm/cpu/tegra-common/clock.c [new file with mode: 0644]
arch/arm/cpu/tegra-common/sys_info.c
arch/arm/cpu/tegra114-common/Makefile [new file with mode: 0644]
arch/arm/cpu/tegra114-common/clock.c [new file with mode: 0644]
arch/arm/cpu/tegra114-common/funcmux.c [new file with mode: 0644]
arch/arm/cpu/tegra114-common/pinmux.c [new file with mode: 0644]
arch/arm/cpu/tegra20-common/clock.c
arch/arm/cpu/tegra20-common/funcmux.c
arch/arm/cpu/tegra20-common/pinmux.c
arch/arm/cpu/tegra20-common/warmboot.c
arch/arm/cpu/tegra30-common/Makefile [new file with mode: 0644]
arch/arm/cpu/tegra30-common/clock.c [new file with mode: 0644]
arch/arm/cpu/tegra30-common/funcmux.c [new file with mode: 0644]
arch/arm/cpu/tegra30-common/pinmux.c [new file with mode: 0644]
arch/arm/dts/tegra114.dtsi [new file with mode: 0644]
arch/arm/dts/tegra20.dtsi
arch/arm/dts/tegra30.dtsi [new file with mode: 0644]
arch/arm/imx-common/Makefile
arch/arm/include/asm/arch-am33xx/ddr_defs.h
arch/arm/include/asm/arch-am33xx/mux.h
arch/arm/include/asm/arch-mxs/clock.h
arch/arm/include/asm/arch-mxs/imx-regs.h
arch/arm/include/asm/arch-mxs/iomux-mx23.h [new file with mode: 0644]
arch/arm/include/asm/arch-mxs/regs-apbh.h
arch/arm/include/asm/arch-mxs/regs-base.h
arch/arm/include/asm/arch-mxs/regs-clkctrl-mx23.h [new file with mode: 0644]
arch/arm/include/asm/arch-mxs/regs-digctl.h
arch/arm/include/asm/arch-mxs/regs-power-mx23.h [new file with mode: 0644]
arch/arm/include/asm/arch-mxs/regs-ssp.h
arch/arm/include/asm/arch-mxs/sys_proto.h
arch/arm/include/asm/arch-tegra/ap.h
arch/arm/include/asm/arch-tegra/board.h
arch/arm/include/asm/arch-tegra/clk_rst.h
arch/arm/include/asm/arch-tegra/clock.h
arch/arm/include/asm/arch-tegra/funcmux.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra/gp_padctrl.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra/pmc.h
arch/arm/include/asm/arch-tegra/tegra.h
arch/arm/include/asm/arch-tegra/tegra_slink.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/clock-tables.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/clock.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/flow.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/funcmux.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/gp_padctrl.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/gpio.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/hardware.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/pinmux.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/pmu.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/spl.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra114/tegra.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra20/clock-tables.h
arch/arm/include/asm/arch-tegra20/clock.h
arch/arm/include/asm/arch-tegra20/funcmux.h
arch/arm/include/asm/arch-tegra20/gp_padctrl.h
arch/arm/include/asm/arch-tegra20/pinmux.h
arch/arm/include/asm/arch-tegra20/tegra.h
arch/arm/include/asm/arch-tegra30/clock-tables.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/clock.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/flow.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/funcmux.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/gp_padctrl.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/gpio.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/hardware.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/pinmux.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/pmu.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/spl.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra30/tegra.h [new file with mode: 0644]
arch/arm/include/asm/system.h
board/avionic-design/dts/tegra20-medcom-wide.dts
board/avionic-design/dts/tegra20-plutux.dts
board/avionic-design/dts/tegra20-tec.dts
board/bluegiga/apx4devkit/apx4devkit.c
board/compal/dts/tegra20-paz00.dts
board/compal/paz00/paz00.c
board/compulab/dts/tegra20-trimslice.dts
board/denx/m28evk/m28evk.c
board/esg/ima3-mx53/imximage.cfg
board/freescale/imx/ddr/mx6q_4x_mt41j128.cfg
board/freescale/mx23evk/Makefile [moved from board/isee/igep0030/Makefile with 92% similarity]
board/freescale/mx23evk/mx23evk.c [new file with mode: 0644]
board/freescale/mx23evk/spl_boot.c [new file with mode: 0644]
board/freescale/mx25pdk/imximage.cfg
board/freescale/mx28evk/mx28evk.c
board/freescale/mx51evk/imximage.cfg
board/freescale/mx53ard/imximage_dd3.cfg
board/freescale/mx53evk/imximage.cfg
board/freescale/mx53loco/imximage.cfg
board/freescale/mx53smd/imximage.cfg
board/freescale/mx6qarm2/imximage.cfg
board/freescale/mx6qsabreauto/imximage.cfg
board/freescale/mx6qsabrelite/mx6qsabrelite.c
board/genesi/mx51_efikamx/imximage_mx.cfg
board/genesi/mx51_efikamx/imximage_sb.cfg
board/highbank/highbank.c
board/isee/igep0020/igep0020.h [deleted file]
board/isee/igep0030/igep0030.c [deleted file]
board/isee/igep00x0/Makefile [moved from board/isee/igep0020/Makefile with 98% similarity]
board/isee/igep00x0/igep00x0.c [moved from board/isee/igep0020/igep0020.c with 86% similarity]
board/isee/igep00x0/igep00x0.h [moved from board/isee/igep0030/igep0030.h with 93% similarity]
board/kmc/kzm9g/kzm9g.c
board/nvidia/cardhu/Makefile [new file with mode: 0644]
board/nvidia/cardhu/cardhu.c [new file with mode: 0644]
board/nvidia/cardhu/cardhu.c.mmc [new file with mode: 0644]
board/nvidia/cardhu/pinmux-config-cardhu.h [new file with mode: 0644]
board/nvidia/common/board.c
board/nvidia/dalmore/Makefile [new file with mode: 0644]
board/nvidia/dalmore/dalmore.c [new file with mode: 0644]
board/nvidia/dalmore/pinmux-config-dalmore.h [new file with mode: 0644]
board/nvidia/dts/tegra114-dalmore.dts [new file with mode: 0644]
board/nvidia/dts/tegra20-harmony.dts
board/nvidia/dts/tegra20-seaboard.dts
board/nvidia/dts/tegra20-ventana.dts
board/nvidia/dts/tegra20-whistler.dts
board/nvidia/dts/tegra30-cardhu.dts [new file with mode: 0644]
board/olimex/mx23_olinuxino/Makefile [new file with mode: 0644]
board/olimex/mx23_olinuxino/mx23_olinuxino.c [new file with mode: 0644]
board/olimex/mx23_olinuxino/spl_boot.c [new file with mode: 0644]
board/phytec/pcm051/Makefile [new file with mode: 0644]
board/phytec/pcm051/board.c [new file with mode: 0644]
board/phytec/pcm051/board.h [new file with mode: 0644]
board/phytec/pcm051/mux.c [new file with mode: 0644]
board/schulercontrol/sc_sps_1/sc_sps_1.c
board/ti/am335x/board.c
board/ttcontrol/vision2/imximage_hynix.cfg
board/woodburn/imximage.cfg
board/woodburn/woodburn.c
boards.cfg
doc/README.fec_mxc [new file with mode: 0644]
drivers/dma/apbh_dma.c
drivers/mmc/mxsmmc.c
drivers/net/fec_mxc.c
drivers/net/fec_mxc.h
drivers/net/phy/phy.c
drivers/spi/Makefile
drivers/spi/mxs_spi.c
drivers/spi/tegra_slink.c [new file with mode: 0644]
drivers/spi/tegra_spi.c
drivers/video/tegra.c
include/configs/am335x_evm.h
include/configs/cardhu.h [new file with mode: 0644]
include/configs/dalmore.h [new file with mode: 0644]
include/configs/igep00x0.h
include/configs/m28evk.h
include/configs/medcom-wide.h
include/configs/mx23_olinuxino.h [new file with mode: 0644]
include/configs/mx23evk.h [new file with mode: 0644]
include/configs/mx28evk.h
include/configs/mx6qsabre_common.h
include/configs/mx6qsabreauto.h
include/configs/omap4_common.h
include/configs/paz00.h
include/configs/pcm051.h [new file with mode: 0644]
include/configs/sc_sps_1.h
include/configs/tec.h
include/configs/tegra-common-post.h
include/configs/tegra-common.h [new file with mode: 0644]
include/configs/tegra114-common.h [new file with mode: 0644]
include/configs/tegra20-common.h
include/configs/tegra30-common.h [new file with mode: 0644]
include/fdtdec.h
include/netdev.h
include/phy.h
include/serial.h
lib/fdtdec.c
spl/Makefile
tools/Makefile
tools/imximage.c

index a163728832eb0fc7b01ece5d81c6239f3b824671..e40eb7b6690f9c37eb27c2454770516fa6d01a9c 100644 (file)
@@ -15,6 +15,7 @@
 *.swp
 *.patch
 *.bin
+*.cfgtmp
 
 # Build tree
 /build-*
index d3ed3905eac3fa66d73460c47de326c29ac68a5b..45e2dd45411fda77564c0b1a1781efe17d76889d 100644 (file)
@@ -819,6 +819,9 @@ Dave Peverley <dpeverley@mpc-data.co.uk>
 
        omap730p2       ARM926EJS
 
+Lars Poeschel <poeschel@lemonage.de>
+       pcm051          ARM ARMV7 (AM33xx Soc)
+
 Mathieu Poirier <mathieu.poirier@linaro.org>
 
        snowball        ARM ARMV7 (u8500 SoC)
@@ -939,6 +942,7 @@ Marek Vasut <marek.vasut@gmail.com>
        palmtc          xscale/pxa
        vpac270         xscale/pxa
        zipitz2         xscale/pxa
+       mx23_olinuxino  i.MX23
        m28evk          i.MX28
        sc_sps_1        i.MX28
 
@@ -950,6 +954,10 @@ Matt Waddel <matt.waddel@linaro.org>
 
        ca9x4_ct_vxp    ARM ARMV7 (Quad Core)
 
+Otavio Salvador <otavio@ossystems.com.br>
+
+       mx23evk         i.MX23
+
 Prafulla Wadaskar <prafulla@marvell.com>
 
        aspenite        ARM926EJS (ARMADA100 88AP168 SoC)
index 51bd918475c513c29b282ef8a434946ebeacde70..35eee704dd18aed084a06e1b6cc464499ab3a29e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -348,7 +348,7 @@ endif
 ifeq ($(SOC),exynos)
 LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o
 endif
-ifeq ($(SOC),tegra20)
+ifneq ($(CONFIG_TEGRA),)
 LIBS-y += arch/$(ARCH)/cpu/$(SOC)-common/lib$(SOC)-common.o
 LIBS-y += arch/$(ARCH)/cpu/tegra-common/libcputegra-common.o
 LIBS-y += $(CPUDIR)/tegra-common/libtegra-common.o
@@ -413,7 +413,7 @@ ALL-$(CONFIG_SPL) += $(obj)$(subst ",,$(CONFIG_SPL_TARGET))
 ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb $(obj)u-boot-dtb.bin
 
 # enable combined SPL/u-boot/dtb rules for tegra
-ifeq ($(SOC),tegra20)
+ifneq ($(CONFIG_TEGRA),)
 ifeq ($(CONFIG_OF_SEPARATE),y)
 ALL-y += $(obj)u-boot-dtb-tegra.bin
 else
@@ -467,9 +467,8 @@ $(obj)u-boot.img:   $(obj)u-boot.bin
                        sed -e 's/"[     ]*$$/ for $(BOARD) board"/') \
                -d $< $@
 
-$(obj)u-boot.imx:       $(obj)u-boot.bin
-               $(obj)tools/mkimage -n  $(CONFIG_IMX_CONFIG) -T imximage \
-               -e $(CONFIG_SYS_TEXT_BASE) -d $< $@
+$(OBJTREE)/u-boot.imx : $(obj)u-boot.bin $(SUBDIR_TOOLS) depend
+               $(MAKE) -C $(SRCTREE)/arch/arm/imx-common $@
 
 $(obj)u-boot.kwb:       $(obj)u-boot.bin
                $(obj)tools/mkimage -n $(CONFIG_SYS_KWD_CONFIG) -T kwbimage \
@@ -512,6 +511,7 @@ $(obj)u-boot.ais:       $(obj)spl/u-boot-spl.bin $(obj)u-boot.img
                        $(obj)u-boot.ais
 
 # Specify the target for use in elftosb call
+ELFTOSB_TARGET-$(CONFIG_MX23) = imx23
 ELFTOSB_TARGET-$(CONFIG_MX28) = imx28
 
 $(obj)u-boot.sb:       $(obj)u-boot.bin $(obj)spl/u-boot-spl.bin
@@ -534,7 +534,7 @@ $(obj)u-boot.spr:   $(obj)u-boot.img $(obj)spl/u-boot-spl.bin
                        conv=notrunc 2>/dev/null
                cat $(obj)spl/u-boot-spl-pad.img $(obj)u-boot.img > $@
 
-ifeq ($(SOC),tegra20)
+ifneq ($(CONFIG_TEGRA),)
 ifeq ($(CONFIG_OF_SEPARATE),y)
 nodtb=dtb
 dtbfile=$(obj)u-boot.dtb
@@ -847,7 +847,8 @@ clean:
        @$(MAKE) -s -C doc/DocBook/ cleandocs
        @find $(OBJTREE) -type f \
                \( -name 'core' -o -name '*.bak' -o -name '*~' -o -name '*.su' \
-               -o -name '*.o'  -o -name '*.a' -o -name '*.exe' \) -print \
+               -o -name '*.o'  -o -name '*.a' -o -name '*.exe' \
+               -o -name '*.cfgtmp' \) -print \
                | xargs rm -f
 
 # Removes everything not needed for testing u-boot
index febd2e301fd9f0bc86777b2860cfbe6b16bcc63b..6cbc6adaa16667b0c77b7c1436e561c6853d7510 100644 (file)
@@ -28,6 +28,7 @@ include $(TOPDIR)/config.mk
 LIB    = $(obj)libtegra-common.o
 
 COBJS-$(CONFIG_SPL_BUILD) += spl.o
+COBJS-y        += cpu.o
 
 SRCS   := $(COBJS-y:.o=.c)
 OBJS   := $(addprefix $(obj),$(COBJS-y))
diff --git a/arch/arm/cpu/arm720t/tegra-common/cpu.c b/arch/arm/cpu/arm720t/tegra-common/cpu.c
new file mode 100644 (file)
index 0000000..119342e
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gp_padctrl.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/pmc.h>
+#include <asm/arch-tegra/scu.h>
+#include "cpu.h"
+
+int get_num_cpus(void)
+{
+       struct apb_misc_gp_ctlr *gp;
+       uint rev;
+
+       gp = (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
+       rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT;
+
+       switch (rev) {
+       case CHIPID_TEGRA20:
+               return 2;
+               break;
+       case CHIPID_TEGRA30:
+       case CHIPID_TEGRA114:
+       default:
+               return 4;
+               break;
+       }
+}
+
+/*
+ * Timing tables for each SOC for all four oscillator options.
+ */
+struct clk_pll_table tegra_pll_x_table[TEGRA_SOC_CNT][CLOCK_OSC_FREQ_COUNT] = {
+       /* T20: 1 GHz */
+       /*  n,  m, p, cpcon */
+       {{ 1000, 13, 0, 12},    /* OSC 13M */
+        { 625,  12, 0, 8},     /* OSC 19.2M */
+        { 1000, 12, 0, 12},    /* OSC 12M */
+        { 1000, 26, 0, 12},    /* OSC 26M */
+       },
+
+       /* T25: 1.2 GHz */
+       {{ 923, 10, 0, 12},
+        { 750, 12, 0, 8},
+        { 600,  6, 0, 12},
+        { 600, 13, 0, 12},
+       },
+
+       /* T30: 1.4 GHz */
+       {{ 862, 8, 0, 8},
+        { 583, 8, 0, 4},
+        { 700, 6, 0, 8},
+        { 700, 13, 0, 8},
+       },
+
+       /* T114: 1.4 GHz */
+       {{ 862, 8, 0, 8},
+        { 583, 8, 0, 4},
+        { 696, 12, 0, 8},
+        { 700, 13, 0, 8},
+       },
+};
+
+void adjust_pllp_out_freqs(void)
+{
+       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_PERIPH];
+       u32 reg;
+
+       /* Set T30 PLLP_OUT1, 2, 3 & 4 freqs to 9.6, 48, 102 & 204MHz */
+       reg = readl(&pll->pll_out[0]);  /* OUTA, contains OUT2 / OUT1 */
+       reg |= (IN_408_OUT_48_DIVISOR << PLLP_OUT2_RATIO) | PLLP_OUT2_OVR
+               | (IN_408_OUT_9_6_DIVISOR << PLLP_OUT1_RATIO) | PLLP_OUT1_OVR;
+       writel(reg, &pll->pll_out[0]);
+
+       reg = readl(&pll->pll_out[1]);   /* OUTB, contains OUT4 / OUT3 */
+       reg |= (IN_408_OUT_204_DIVISOR << PLLP_OUT4_RATIO) | PLLP_OUT4_OVR
+               | (IN_408_OUT_102_DIVISOR << PLLP_OUT3_RATIO) | PLLP_OUT3_OVR;
+       writel(reg, &pll->pll_out[1]);
+}
+
+int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm,
+               u32 divp, u32 cpcon)
+{
+       u32 reg;
+
+       /* If PLLX is already enabled, just return */
+       if (readl(&pll->pll_base) & PLL_ENABLE_MASK) {
+               debug("pllx_set_rate: PLLX already enabled, returning\n");
+               return 0;
+       }
+
+       debug(" pllx_set_rate entry\n");
+
+       /* Set BYPASS, m, n and p to PLLX_BASE */
+       reg = PLL_BYPASS_MASK | (divm << PLL_DIVM_SHIFT);
+       reg |= ((divn << PLL_DIVN_SHIFT) | (divp << PLL_DIVP_SHIFT));
+       writel(reg, &pll->pll_base);
+
+       /* Set cpcon to PLLX_MISC */
+       reg = (cpcon << PLL_CPCON_SHIFT);
+
+       /* Set dccon to PLLX_MISC if freq > 600MHz */
+       if (divn > 600)
+               reg |= (1 << PLL_DCCON_SHIFT);
+       writel(reg, &pll->pll_misc);
+
+       /* Enable PLLX */
+       reg = readl(&pll->pll_base);
+       reg |= PLL_ENABLE_MASK;
+
+       /* Disable BYPASS */
+       reg &= ~PLL_BYPASS_MASK;
+       writel(reg, &pll->pll_base);
+
+       /* Set lock_enable to PLLX_MISC */
+       reg = readl(&pll->pll_misc);
+       reg |= PLL_LOCK_ENABLE_MASK;
+       writel(reg, &pll->pll_misc);
+
+       return 0;
+}
+
+void init_pllx(void)
+{
+       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       struct clk_pll_simple *pll = &clkrst->crc_pll_simple[SIMPLE_PLLX];
+       int chip_type;
+       enum clock_osc_freq osc;
+       struct clk_pll_table *sel;
+
+       debug("init_pllx entry\n");
+
+       /* get chip type */
+       chip_type = tegra_get_chip_type();
+       debug(" init_pllx: chip_type = %d\n", chip_type);
+
+       /* get osc freq */
+       osc = clock_get_osc_freq();
+       debug("  init_pllx: osc = %d\n", osc);
+
+       /* set pllx */
+       sel = &tegra_pll_x_table[chip_type][osc];
+       pllx_set_rate(pll, sel->n, sel->m, sel->p, sel->cpcon);
+
+       /* adjust PLLP_out1-4 on T30/T114 */
+       if (chip_type == TEGRA_SOC_T30 || chip_type == TEGRA_SOC_T114) {
+               debug("  init_pllx: adjusting PLLP out freqs\n");
+               adjust_pllp_out_freqs();
+       }
+}
+
+void enable_cpu_clock(int enable)
+{
+       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 clk;
+
+       /*
+        * NOTE:
+        * Regardless of whether the request is to enable or disable the CPU
+        * clock, every processor in the CPU complex except the master (CPU 0)
+        * will have it's clock stopped because the AVP only talks to the
+        * master.
+        */
+
+       if (enable) {
+               /* Initialize PLLX */
+               init_pllx();
+
+               /* Wait until all clocks are stable */
+               udelay(PLL_STABILIZATION_DELAY);
+
+               writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
+               writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
+       }
+
+       /*
+        * Read the register containing the individual CPU clock enables and
+        * always stop the clocks to CPUs > 0.
+        */
+       clk = readl(&clkrst->crc_clk_cpu_cmplx);
+       clk |= 1 << CPU1_CLK_STP_SHIFT;
+       if (get_num_cpus() == 4)
+               clk |= (1 << CPU2_CLK_STP_SHIFT) + (1 << CPU3_CLK_STP_SHIFT);
+
+       /* Stop/Unstop the CPU clock */
+       clk &= ~CPU0_CLK_STP_MASK;
+       clk |= !enable << CPU0_CLK_STP_SHIFT;
+       writel(clk, &clkrst->crc_clk_cpu_cmplx);
+
+       clock_enable(PERIPH_ID_CPU);
+}
+
+static int is_cpu_powered(void)
+{
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+
+       return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
+}
+
+static void remove_cpu_io_clamps(void)
+{
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       u32 reg;
+
+       /* Remove the clamps on the CPU I/O signals */
+       reg = readl(&pmc->pmc_remove_clamping);
+       reg |= CPU_CLMP;
+       writel(reg, &pmc->pmc_remove_clamping);
+
+       /* Give I/O signals time to stabilize */
+       udelay(IO_STABILIZATION_DELAY);
+}
+
+void powerup_cpu(void)
+{
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       u32 reg;
+       int timeout = IO_STABILIZATION_DELAY;
+
+       if (!is_cpu_powered()) {
+               /* Toggle the CPU power state (OFF -> ON) */
+               reg = readl(&pmc->pmc_pwrgate_toggle);
+               reg &= PARTID_CP;
+               reg |= START_CP;
+               writel(reg, &pmc->pmc_pwrgate_toggle);
+
+               /* Wait for the power to come up */
+               while (!is_cpu_powered()) {
+                       if (timeout-- == 0)
+                               printf("CPU failed to power up!\n");
+                       else
+                               udelay(10);
+               }
+
+               /*
+                * Remove the I/O clamps from CPU power partition.
+                * Recommended only on a Warm boot, if the CPU partition gets
+                * power gated. Shouldn't cause any harm when called after a
+                * cold boot according to HW, probably just redundant.
+                */
+               remove_cpu_io_clamps();
+       }
+}
+
+void reset_A9_cpu(int reset)
+{
+       /*
+       * NOTE:  Regardless of whether the request is to hold the CPU in reset
+       *        or take it out of reset, every processor in the CPU complex
+       *        except the master (CPU 0) will be held in reset because the
+       *        AVP only talks to the master. The AVP does not know that there
+       *        are multiple processors in the CPU complex.
+       */
+       int mask = crc_rst_cpu | crc_rst_de | crc_rst_debug;
+       int num_cpus = get_num_cpus();
+       int cpu;
+
+       debug("reset_a9_cpu entry\n");
+       /* Hold CPUs 1 onwards in reset, and CPU 0 if asked */
+       for (cpu = 1; cpu < num_cpus; cpu++)
+               reset_cmplx_set_enable(cpu, mask, 1);
+       reset_cmplx_set_enable(0, mask, reset);
+
+       /* Enable/Disable master CPU reset */
+       reset_set_enable(PERIPH_ID_CPU, reset);
+}
+
+void clock_enable_coresight(int enable)
+{
+       u32 rst, src = 2;
+       int chip;
+
+       debug("clock_enable_coresight entry\n");
+       clock_set_enable(PERIPH_ID_CORESIGHT, enable);
+       reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
+
+       if (enable) {
+               /*
+                * Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down by
+                *  1.5, giving an effective frequency of 144MHz.
+                * Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor
+                *  (bits 7:0), so 00000001b == 1.5 (n+1 + .5)
+                *
+                * Clock divider request for 204MHz would setup CSITE clock as
+                * 144MHz for PLLP base 216MHz and 204MHz for PLLP base 408MHz
+                */
+               chip = tegra_get_chip_type();
+               if (chip == TEGRA_SOC_T30 || chip == TEGRA_SOC_T114)
+                       src = CLK_DIVIDER(NVBL_PLLP_KHZ, 204000);
+               else if (chip == TEGRA_SOC_T20 || chip == TEGRA_SOC_T25)
+                       src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000);
+               else
+                       printf("%s: Unknown chip type %X!\n", __func__, chip);
+               clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src);
+
+               /* Unlock the CPU CoreSight interfaces */
+               rst = CORESIGHT_UNLOCK;
+               writel(rst, CSITE_CPU_DBG0_LAR);
+               writel(rst, CSITE_CPU_DBG1_LAR);
+               if (get_num_cpus() == 4) {
+                       writel(rst, CSITE_CPU_DBG2_LAR);
+                       writel(rst, CSITE_CPU_DBG3_LAR);
+               }
+       }
+}
+
+void halt_avp(void)
+{
+       for (;;) {
+               writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
+                       | HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)),
+                       FLOW_CTLR_HALT_COP_EVENTS);
+       }
+}
index 6804cd7a3df7159172e1486e3207750d9e5be9c9..e8e05d77aab1c807f6fed6aaef1dd2d26d59c404 100644 (file)
 #define PLL_STABILIZATION_DELAY (300)
 #define IO_STABILIZATION_DELAY (1000)
 
+#if defined(CONFIG_TEGRA20)
 #define NVBL_PLLP_KHZ  (216000)
+#elif defined(CONFIG_TEGRA30) || defined(CONFIG_TEGRA114)
+#define NVBL_PLLP_KHZ  (408000)
+#else
+#error "Unknown Tegra chip!"
+#endif
 
 #define PLLX_ENABLED           (1 << 30)
 #define CCLK_BURST_POLICY      0x20008888
 
 #define CORESIGHT_UNLOCK       0xC5ACCE55;
 
-/* AP20-Specific Base Addresses */
-
-/* AP20 Base physical address of SDRAM. */
-#define AP20_BASE_PA_SDRAM      0x00000000
-/* AP20 Base physical address of internal SRAM. */
-#define AP20_BASE_PA_SRAM       0x40000000
-/* AP20 Size of internal SRAM (256KB). */
-#define AP20_BASE_PA_SRAM_SIZE  0x00040000
-/* AP20 Base physical address of flash. */
-#define AP20_BASE_PA_NOR_FLASH  0xD0000000
-/* AP20 Base physical address of boot information table. */
-#define AP20_BASE_PA_BOOT_INFO  AP20_BASE_PA_SRAM
-
-/*
- * Super-temporary stacks for EXTREMELY early startup. The values chosen for
- * these addresses must be valid on ALL SOCs because this value is used before
- * we are able to differentiate between the SOC types.
- *
- * NOTE: The since CPU's stack will eventually be moved from IRAM to SDRAM, its
- *       stack is placed below the AVP stack. Once the CPU stack has been moved,
- *       the AVP is free to use the IRAM the CPU stack previously occupied if
- *       it should need to do so.
- *
- * NOTE: In multi-processor CPU complex configurations, each processor will have
- *       its own stack of size CPU_EARLY_BOOT_STACK_SIZE. CPU 0 will have a
- *       limit of CPU_EARLY_BOOT_STACK_LIMIT. Each successive CPU will have a
- *       stack limit that is CPU_EARLY_BOOT_STACK_SIZE less then the previous
- *       CPU.
- */
-
-/* Common AVP early boot stack limit */
-#define AVP_EARLY_BOOT_STACK_LIMIT     \
-       (AP20_BASE_PA_SRAM + (AP20_BASE_PA_SRAM_SIZE/2))
-/* Common AVP early boot stack size */
-#define AVP_EARLY_BOOT_STACK_SIZE      0x1000
-/* Common CPU early boot stack limit */
-#define CPU_EARLY_BOOT_STACK_LIMIT     \
-       (AVP_EARLY_BOOT_STACK_LIMIT - AVP_EARLY_BOOT_STACK_SIZE)
-/* Common CPU early boot stack size */
-#define CPU_EARLY_BOOT_STACK_SIZE      0x1000
-
 #define EXCEP_VECTOR_CPU_RESET_VECTOR  (NV_PA_EVP_BASE + 0x100)
 #define CSITE_CPU_DBG0_LAR             (NV_PA_CSITE_BASE + 0x10FB0)
 #define CSITE_CPU_DBG1_LAR             (NV_PA_CSITE_BASE + 0x12FB0)
+#define CSITE_CPU_DBG2_LAR             (NV_PA_CSITE_BASE + 0x14FB0)
+#define CSITE_CPU_DBG3_LAR             (NV_PA_CSITE_BASE + 0x16FB0)
 
 #define FLOW_CTLR_HALT_COP_EVENTS      (NV_PA_FLOW_BASE + 4)
 #define FLOW_MODE_STOP                 2
 #define HALT_COP_EVENT_IRQ_1           (1 << 11)
 #define HALT_COP_EVENT_FIQ_1           (1 << 9)
 
-void start_cpu(u32 reset_vector);
-int ap20_cpu_is_cortexa9(void);
+#define FLOW_MODE_NONE         0
+
+#define SIMPLE_PLLX     (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE)
+
+struct clk_pll_table {
+       u16     n;
+       u16     m;
+       u8      p;
+       u8      cpcon;
+};
+
+void clock_enable_coresight(int enable);
+void enable_cpu_clock(int enable);
 void halt_avp(void)  __attribute__ ((noreturn));
+void init_pllx(void);
+void powerup_cpu(void);
+void reset_A9_cpu(int reset);
+void start_cpu(u32 reset_vector);
+int tegra_get_chip_type(void);
+void adjust_pllp_out_freqs(void);
index c280ab7d0f9c89bc60fec15077709087999da0fe..a9a1c39c73e0ef31175242e488a7910d56c2ea0c 100644 (file)
@@ -23,7 +23,6 @@
  * MA 02111-1307 USA
  */
 #include <common.h>
-#include "cpu.h"
 #include <spl.h>
 
 #include <asm/io.h>
@@ -32,7 +31,7 @@
 #include <asm/arch/tegra.h>
 #include <asm/arch-tegra/board.h>
 #include <asm/arch/spl.h>
-
+#include "cpu.h"
 
 void spl_board_init(void)
 {
diff --git a/arch/arm/cpu/arm720t/tegra114/Makefile b/arch/arm/cpu/arm720t/tegra114/Makefile
new file mode 100644 (file)
index 0000000..6cf7fe9
--- /dev/null
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope 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 $(TOPDIR)/config.mk
+
+LIB    = $(obj)lib$(SOC).o
+
+#COBJS-y       += cpu.o t11x.o
+COBJS-y        += cpu.o
+
+SRCS   := $(COBJS-y:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS-y))
+
+all:   $(obj).depend $(LIB)
+
+$(LIB):        $(OBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/arm720t/tegra114/config.mk b/arch/arm/cpu/arm720t/tegra114/config.mk
new file mode 100644 (file)
index 0000000..7947b50
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+#
+# (C) Copyright 2002
+# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope 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/>.
+#
+USE_PRIVATE_LIBGCC = yes
diff --git a/arch/arm/cpu/arm720t/tegra114/cpu.c b/arch/arm/cpu/arm720t/tegra114/cpu.c
new file mode 100644 (file)
index 0000000..5962e15
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/flow.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/pmc.h>
+#include "../tegra-common/cpu.h"
+
+/* Tegra114-specific CPU init code */
+static void enable_cpu_power_rail(void)
+{
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 reg;
+
+       debug("enable_cpu_power_rail entry\n");
+
+       /* un-tristate PWR_I2C SCL/SDA, rest of the defaults are correct */
+       pinmux_tristate_disable(PINGRP_PWR_I2C_SCL);
+       pinmux_tristate_disable(PINGRP_PWR_I2C_SDA);
+
+       /*
+        * Set CPUPWRGOOD_TIMER - APB clock is 1/2 of SCLK (102MHz),
+        * set it for 25ms (102MHz * .025)
+        */
+       reg = 0x26E8F0;
+       writel(reg, &pmc->pmc_cpupwrgood_timer);
+
+       /* Set polarity to 0 (normal) and enable CPUPWRREQ_OE */
+       clrbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_POL);
+       setbits_le32(&pmc->pmc_cntrl, CPUPWRREQ_OE);
+
+       /*
+        * Set CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2_0_CAR2PMC_CPU_ACK_WIDTH
+        * to 408 to satisfy the requirement of having at least 16 CPU clock
+        * cycles before clamp removal.
+        */
+
+       clrbits_le32(&clkrst->crc_cpu_softrst_ctrl2, 0xFFF);
+       setbits_le32(&clkrst->crc_cpu_softrst_ctrl2, 408);
+}
+
+static void enable_cpu_clocks(void)
+{
+       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 reg;
+
+       debug("enable_cpu_clocks entry\n");
+
+       /* Wait for PLL-X to lock */
+       do {
+               reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
+       } while ((reg & (1 << 27)) == 0);
+
+       /* Wait until all clocks are stable */
+       udelay(PLL_STABILIZATION_DELAY);
+
+       writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
+       writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
+
+       /* Always enable the main CPU complex clocks */
+       clock_enable(PERIPH_ID_CPU);
+       clock_enable(PERIPH_ID_CPULP);
+       clock_enable(PERIPH_ID_CPUG);
+}
+
+static void remove_cpu_resets(void)
+{
+       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 reg;
+
+       debug("remove_cpu_resets entry\n");
+       /* Take the slow non-CPU partition out of reset */
+       reg = readl(&clkrst->crc_rst_cpulp_cmplx_clr);
+       writel((reg | CLR_NONCPURESET), &clkrst->crc_rst_cpulp_cmplx_clr);
+
+       /* Take the fast non-CPU partition out of reset */
+       reg = readl(&clkrst->crc_rst_cpug_cmplx_clr);
+       writel((reg | CLR_NONCPURESET), &clkrst->crc_rst_cpug_cmplx_clr);
+
+       /* Clear the SW-controlled reset of the slow cluster */
+       reg = readl(&clkrst->crc_rst_cpulp_cmplx_clr);
+       reg |= (CLR_CPURESET0+CLR_DBGRESET0+CLR_CORERESET0+CLR_CXRESET0);
+       writel(reg, &clkrst->crc_rst_cpulp_cmplx_clr);
+
+       /* Clear the SW-controlled reset of the fast cluster */
+       reg = readl(&clkrst->crc_rst_cpug_cmplx_clr);
+       reg |= (CLR_CPURESET0+CLR_DBGRESET0+CLR_CORERESET0+CLR_CXRESET0);
+       reg |= (CLR_CPURESET1+CLR_DBGRESET1+CLR_CORERESET1+CLR_CXRESET1);
+       reg |= (CLR_CPURESET2+CLR_DBGRESET2+CLR_CORERESET2+CLR_CXRESET2);
+       reg |= (CLR_CPURESET3+CLR_DBGRESET3+CLR_CORERESET3+CLR_CXRESET3);
+       writel(reg, &clkrst->crc_rst_cpug_cmplx_clr);
+}
+
+/**
+ * The T114 requires some special clock initialization, including setting up
+ * the DVC I2C, turning on MSELECT and selecting the G CPU cluster
+ */
+void t114_init_clocks(void)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
+       u32 val;
+
+       debug("t114_init_clocks entry\n");
+
+       /* Set active CPU cluster to G */
+       clrbits_le32(&flow->cluster_control, 1);
+
+       /*
+        * Switch system clock to PLLP_OUT4 (108 MHz), AVP will now run
+        * at 108 MHz. This is glitch free as only the source is changed, no
+        * special precaution needed.
+        */
+       val = (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT) |
+               (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IRQ_SOURCE_SHIFT) |
+               (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_RUN_SOURCE_SHIFT) |
+               (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IDLE_SOURCE_SHIFT) |
+               (SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT);
+       writel(val, &clkrst->crc_sclk_brst_pol);
+
+       writel(SUPER_SCLK_ENB_MASK, &clkrst->crc_super_sclk_div);
+
+       debug("Setting up PLLX\n");
+       init_pllx();
+
+       val = (1 << CLK_SYS_RATE_AHB_RATE_SHIFT);
+       writel(val, &clkrst->crc_clk_sys_rate);
+
+       /* Enable clocks to required peripherals. TBD - minimize this list */
+       debug("Enabling clocks\n");
+
+       clock_set_enable(PERIPH_ID_CACHE2, 1);
+       clock_set_enable(PERIPH_ID_GPIO, 1);
+       clock_set_enable(PERIPH_ID_TMR, 1);
+       clock_set_enable(PERIPH_ID_RTC, 1);
+       clock_set_enable(PERIPH_ID_CPU, 1);
+       clock_set_enable(PERIPH_ID_EMC, 1);
+       clock_set_enable(PERIPH_ID_I2C5, 1);
+       clock_set_enable(PERIPH_ID_FUSE, 1);
+       clock_set_enable(PERIPH_ID_PMC, 1);
+       clock_set_enable(PERIPH_ID_APBDMA, 1);
+       clock_set_enable(PERIPH_ID_MEM, 1);
+       clock_set_enable(PERIPH_ID_IRAMA, 1);
+       clock_set_enable(PERIPH_ID_IRAMB, 1);
+       clock_set_enable(PERIPH_ID_IRAMC, 1);
+       clock_set_enable(PERIPH_ID_IRAMD, 1);
+       clock_set_enable(PERIPH_ID_CORESIGHT, 1);
+       clock_set_enable(PERIPH_ID_MSELECT, 1);
+       clock_set_enable(PERIPH_ID_EMC1, 1);
+       clock_set_enable(PERIPH_ID_MC1, 1);
+       clock_set_enable(PERIPH_ID_DVFS, 1);
+
+       /* Switch MSELECT clock to PLLP (00) */
+       clock_ll_set_source(PERIPH_ID_MSELECT, 0);
+
+       /*
+        * Clock divider request for 102MHz would setup MSELECT clock as
+        * 102MHz for PLLP base 408MHz
+        */
+       clock_ll_set_source_divisor(PERIPH_ID_MSELECT, 0,
+               (NVBL_PLLP_KHZ/102000));
+
+       /* I2C5 (DVC) gets CLK_M and a divisor of 17 */
+       clock_ll_set_source_divisor(PERIPH_ID_I2C5, 3, 16);
+
+       /* Give clocks time to stabilize */
+       udelay(1000);
+
+       /* Take required peripherals out of reset */
+       debug("Taking periphs out of reset\n");
+       reset_set_enable(PERIPH_ID_CACHE2, 0);
+       reset_set_enable(PERIPH_ID_GPIO, 0);
+       reset_set_enable(PERIPH_ID_TMR, 0);
+       reset_set_enable(PERIPH_ID_COP, 0);
+       reset_set_enable(PERIPH_ID_EMC, 0);
+       reset_set_enable(PERIPH_ID_I2C5, 0);
+       reset_set_enable(PERIPH_ID_FUSE, 0);
+       reset_set_enable(PERIPH_ID_APBDMA, 0);
+       reset_set_enable(PERIPH_ID_MEM, 0);
+       reset_set_enable(PERIPH_ID_CORESIGHT, 0);
+       reset_set_enable(PERIPH_ID_MSELECT, 0);
+       reset_set_enable(PERIPH_ID_EMC1, 0);
+       reset_set_enable(PERIPH_ID_MC1, 0);
+
+       debug("t114_init_clocks exit\n");
+}
+
+static int is_partition_powered(u32 mask)
+{
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       u32 reg;
+
+       /* Get power gate status */
+       reg = readl(&pmc->pmc_pwrgate_status);
+       return (reg & mask) == mask;
+}
+
+static int is_clamp_enabled(u32 mask)
+{
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       u32 reg;
+
+       /* Get clamp status. TODO: Add pmc_clamp_status alias to pmc.h */
+       reg = readl(&pmc->pmc_pwrgate_timer_on);
+       return (reg & mask) == mask;
+}
+
+static void power_partition(u32 status, u32 partid)
+{
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+
+       debug("%s: status = %08X, part ID = %08X\n", __func__, status, partid);
+       /* Is the partition already on? */
+       if (!is_partition_powered(status)) {
+               /* No, toggle the partition power state (OFF -> ON) */
+               debug("power_partition, toggling state\n");
+               clrbits_le32(&pmc->pmc_pwrgate_toggle, 0x1F);
+               setbits_le32(&pmc->pmc_pwrgate_toggle, partid);
+               setbits_le32(&pmc->pmc_pwrgate_toggle, START_CP);
+
+               /* Wait for the power to come up */
+               while (!is_partition_powered(status))
+                       ;
+
+               /* Wait for the clamp status to be cleared */
+               while (is_clamp_enabled(status))
+                       ;
+
+               /* Give I/O signals time to stabilize */
+               udelay(IO_STABILIZATION_DELAY);
+       }
+}
+
+void powerup_cpus(void)
+{
+       debug("powerup_cpus entry\n");
+
+       /* We boot to the fast cluster */
+       debug("powerup_cpus entry: G cluster\n");
+       /* Power up the fast cluster rail partition */
+       power_partition(CRAIL, CRAILID);
+
+       /* Power up the fast cluster non-CPU partition */
+       power_partition(C0NC, C0NCID);
+
+       /* Power up the fast cluster CPU0 partition */
+       power_partition(CE0, CE0ID);
+}
+
+void start_cpu(u32 reset_vector)
+{
+       debug("start_cpu entry, reset_vector = %x\n", reset_vector);
+
+       t114_init_clocks();
+
+       /* Enable VDD_CPU */
+       enable_cpu_power_rail();
+
+       /* Get the CPU(s) running */
+       enable_cpu_clocks();
+
+       /* Enable CoreSight */
+       clock_enable_coresight(1);
+
+       /* Take CPU(s) out of reset */
+       remove_cpu_resets();
+
+       /*
+        * Set the entry point for CPU execution from reset,
+        *  if it's a non-zero value.
+        */
+       if (reset_vector)
+               writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
+
+       /* If the CPU(s) don't already have power, power 'em up */
+       powerup_cpus();
+}
index ef7f375e79de92a1336d64aed2efc8ab02157964..253389955fb2a7b045c09e08e633c2fed80b9093 100644 (file)
 /*
-* (C) Copyright 2010-2011
-* NVIDIA Corporation <www.nvidia.com>
-*
-* See file CREDITS for list of people who contributed to this
-* project.
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation; either version 2 of
-* the License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-* MA 02111-1307 USA
-*/
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <asm/io.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/pinmux.h>
 #include <asm/arch/tegra.h>
-#include <asm/arch-tegra/clk_rst.h>
 #include <asm/arch-tegra/pmc.h>
-#include <asm/arch-tegra/scu.h>
 #include "../tegra-common/cpu.h"
 
-/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */
-int ap20_cpu_is_cortexa9(void)
-{
-       u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0);
-       return id == (PG_UP_TAG_0_PID_CPU & 0xff);
-}
-
-void init_pllx(void)
-{
-       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-       struct clk_pll *pll = &clkrst->crc_pll[CLOCK_ID_XCPU];
-       u32 reg;
-
-       /* If PLLX is already enabled, just return */
-       if (readl(&pll->pll_base) & PLL_ENABLE_MASK)
-               return;
-
-       /* Set PLLX_MISC */
-       writel(1 << PLL_CPCON_SHIFT, &pll->pll_misc);
-
-       /* Use 12MHz clock here */
-       reg = PLL_BYPASS_MASK | (12 << PLL_DIVM_SHIFT);
-       reg |= 1000 << PLL_DIVN_SHIFT;
-       writel(reg, &pll->pll_base);
-
-       reg |= PLL_ENABLE_MASK;
-       writel(reg, &pll->pll_base);
-
-       reg &= ~PLL_BYPASS_MASK;
-       writel(reg, &pll->pll_base);
-}
-
-static void enable_cpu_clock(int enable)
-{
-       struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-       u32 clk;
-
-       /*
-        * NOTE:
-        * Regardless of whether the request is to enable or disable the CPU
-        * clock, every processor in the CPU complex except the master (CPU 0)
-        * will have it's clock stopped because the AVP only talks to the
-        * master. The AVP does not know (nor does it need to know) that there
-        * are multiple processors in the CPU complex.
-        */
-
-       if (enable) {
-               /* Initialize PLLX */
-               init_pllx();
-
-               /* Wait until all clocks are stable */
-               udelay(PLL_STABILIZATION_DELAY);
-
-               writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol);
-               writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div);
-       }
-
-       /*
-        * Read the register containing the individual CPU clock enables and
-        * always stop the clock to CPU 1.
-        */
-       clk = readl(&clkrst->crc_clk_cpu_cmplx);
-       clk |= 1 << CPU1_CLK_STP_SHIFT;
-
-       /* Stop/Unstop the CPU clock */
-       clk &= ~CPU0_CLK_STP_MASK;
-       clk |= !enable << CPU0_CLK_STP_SHIFT;
-       writel(clk, &clkrst->crc_clk_cpu_cmplx);
-
-       clock_enable(PERIPH_ID_CPU);
-}
-
-static int is_cpu_powered(void)
-{
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
-
-       return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
-}
-
-static void remove_cpu_io_clamps(void)
-{
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
-       u32 reg;
-
-       /* Remove the clamps on the CPU I/O signals */
-       reg = readl(&pmc->pmc_remove_clamping);
-       reg |= CPU_CLMP;
-       writel(reg, &pmc->pmc_remove_clamping);
-
-       /* Give I/O signals time to stabilize */
-       udelay(IO_STABILIZATION_DELAY);
-}
-
-static void powerup_cpu(void)
-{
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
-       u32 reg;
-       int timeout = IO_STABILIZATION_DELAY;
-
-       if (!is_cpu_powered()) {
-               /* Toggle the CPU power state (OFF -> ON) */
-               reg = readl(&pmc->pmc_pwrgate_toggle);
-               reg &= PARTID_CP;
-               reg |= START_CP;
-               writel(reg, &pmc->pmc_pwrgate_toggle);
-
-               /* Wait for the power to come up */
-               while (!is_cpu_powered()) {
-                       if (timeout-- == 0)
-                               printf("CPU failed to power up!\n");
-                       else
-                               udelay(10);
-               }
-
-               /*
-                * Remove the I/O clamps from CPU power partition.
-                * Recommended only on a Warm boot, if the CPU partition gets
-                * power gated. Shouldn't cause any harm when called after a
-                * cold boot according to HW, probably just redundant.
-                */
-               remove_cpu_io_clamps();
-       }
-}
-
 static void enable_cpu_power_rail(void)
 {
        struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
@@ -173,49 +38,6 @@ static void enable_cpu_power_rail(void)
        udelay(3750);
 }
 
-static void reset_A9_cpu(int reset)
-{
-       /*
-       * NOTE:  Regardless of whether the request is to hold the CPU in reset
-       *        or take it out of reset, every processor in the CPU complex
-       *        except the master (CPU 0) will be held in reset because the
-       *        AVP only talks to the master. The AVP does not know that there
-       *        are multiple processors in the CPU complex.
-       */
-
-       /* Hold CPU 1 in reset, and CPU 0 if asked */
-       reset_cmplx_set_enable(1, crc_rst_cpu | crc_rst_de | crc_rst_debug, 1);
-       reset_cmplx_set_enable(0, crc_rst_cpu | crc_rst_de | crc_rst_debug,
-                              reset);
-
-       /* Enable/Disable master CPU reset */
-       reset_set_enable(PERIPH_ID_CPU, reset);
-}
-
-static void clock_enable_coresight(int enable)
-{
-       u32 rst, src;
-
-       clock_set_enable(PERIPH_ID_CORESIGHT, enable);
-       reset_set_enable(PERIPH_ID_CORESIGHT, !enable);
-
-       if (enable) {
-               /*
-                * Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down by
-                *  1.5, giving an effective frequency of 144MHz.
-                * Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor
-                *  (bits 7:0), so 00000001b == 1.5 (n+1 + .5)
-                */
-               src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000);
-               clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src);
-
-               /* Unlock the CPU CoreSight interfaces */
-               rst = 0xC5ACCE55;
-               writel(rst, CSITE_CPU_DBG0_LAR);
-               writel(rst, CSITE_CPU_DBG1_LAR);
-       }
-}
-
 void start_cpu(u32 reset_vector)
 {
        /* Enable VDD_CPU */
@@ -246,13 +68,3 @@ void start_cpu(u32 reset_vector)
        /* Take the CPU out of reset */
        reset_A9_cpu(0);
 }
-
-
-void halt_avp(void)
-{
-       for (;;) {
-               writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \
-                       | HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)),
-                       FLOW_CTLR_HALT_COP_EVENTS);
-       }
-}
diff --git a/arch/arm/cpu/arm720t/tegra30/Makefile b/arch/arm/cpu/arm720t/tegra30/Makefile
new file mode 100644 (file)
index 0000000..bd96997
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope 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 $(TOPDIR)/config.mk
+
+LIB    = $(obj)lib$(SOC).o
+
+COBJS-y        += cpu.o
+
+SRCS   := $(COBJS-y:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS-y))
+
+all:   $(obj).depend $(LIB)
+
+$(LIB):        $(OBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/arm720t/tegra30/config.mk b/arch/arm/cpu/arm720t/tegra30/config.mk
new file mode 100644 (file)
index 0000000..2388c56
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+#
+# (C) Copyright 2002
+# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope 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/>.
+#
+USE_PRIVATE_LIBGCC = yes
diff --git a/arch/arm/cpu/arm720t/tegra30/cpu.c b/arch/arm/cpu/arm720t/tegra30/cpu.c
new file mode 100644 (file)
index 0000000..dedcdd9
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/flow.h>
+#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/pmc.h>
+#include <asm/arch-tegra/tegra_i2c.h>
+#include "../tegra-common/cpu.h"
+
+/* Tegra30-specific CPU init code */
+void tegra_i2c_ll_write_addr(uint addr, uint config)
+{
+       struct i2c_ctlr *reg = (struct i2c_ctlr *)TEGRA_DVC_BASE;
+
+       writel(addr, &reg->cmd_addr0);
+       writel(config, &reg->cnfg);
+}
+
+void tegra_i2c_ll_write_data(uint data, uint config)
+{
+       struct i2c_ctlr *reg = (struct i2c_ctlr *)TEGRA_DVC_BASE;
+
+       writel(data, &reg->cmd_data1);
+       writel(config, &reg->cnfg);
+}
+
+#define TPS65911_I2C_ADDR              0x5A
+#define TPS65911_VDDCTRL_OP_REG                0x28
+#define TPS65911_VDDCTRL_SR_REG                0x27
+#define TPS65911_VDDCTRL_OP_DATA       (0x2300 | TPS65911_VDDCTRL_OP_REG)
+#define TPS65911_VDDCTRL_SR_DATA       (0x0100 | TPS65911_VDDCTRL_SR_REG)
+#define I2C_SEND_2_BYTES               0x0A02
+
+static void enable_cpu_power_rail(void)
+{
+       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       u32 reg;
+
+       debug("enable_cpu_power_rail entry\n");
+       reg = readl(&pmc->pmc_cntrl);
+       reg |= CPUPWRREQ_OE;
+       writel(reg, &pmc->pmc_cntrl);
+
+       /*
+        * Bring up CPU VDD via the TPS65911x PMIC on the DVC I2C bus.
+        * First set VDD to 1.4V, then enable the VDD regulator.
+        */
+       tegra_i2c_ll_write_addr(TPS65911_I2C_ADDR, 2);
+       tegra_i2c_ll_write_data(TPS65911_VDDCTRL_OP_DATA, I2C_SEND_2_BYTES);
+       udelay(1000);
+       tegra_i2c_ll_write_data(TPS65911_VDDCTRL_SR_DATA, I2C_SEND_2_BYTES);
+       udelay(10 * 1000);
+}
+
+/**
+ * The T30 requires some special clock initialization, including setting up
+ * the dvc i2c, turning on mselect and selecting the G CPU cluster
+ */
+void t30_init_clocks(void)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
+       u32 val;
+
+       debug("t30_init_clocks entry\n");
+       /* Set active CPU cluster to G */
+       clrbits_le32(flow->cluster_control, 1 << 0);
+
+       /*
+        * Switch system clock to PLLP_OUT4 (108 MHz), AVP will now run
+        * at 108 MHz. This is glitch free as only the source is changed, no
+        * special precaution needed.
+        */
+       val = (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_FIQ_SOURCE_SHIFT) |
+               (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IRQ_SOURCE_SHIFT) |
+               (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_RUN_SOURCE_SHIFT) |
+               (SCLK_SOURCE_PLLP_OUT4 << SCLK_SWAKEUP_IDLE_SOURCE_SHIFT) |
+               (SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT);
+       writel(val, &clkrst->crc_sclk_brst_pol);
+
+       writel(SUPER_SCLK_ENB_MASK, &clkrst->crc_super_sclk_div);
+
+       val = (0 << CLK_SYS_RATE_HCLK_DISABLE_SHIFT) |
+               (1 << CLK_SYS_RATE_AHB_RATE_SHIFT) |
+               (0 << CLK_SYS_RATE_PCLK_DISABLE_SHIFT) |
+               (0 << CLK_SYS_RATE_APB_RATE_SHIFT);
+       writel(val, &clkrst->crc_clk_sys_rate);
+
+       /* Put i2c, mselect in reset and enable clocks */
+       reset_set_enable(PERIPH_ID_DVC_I2C, 1);
+       clock_set_enable(PERIPH_ID_DVC_I2C, 1);
+       reset_set_enable(PERIPH_ID_MSELECT, 1);
+       clock_set_enable(PERIPH_ID_MSELECT, 1);
+
+       /* Switch MSELECT clock to PLLP (00) */
+       clock_ll_set_source(PERIPH_ID_MSELECT, 0);
+
+       /*
+        * Our high-level clock routines are not available prior to
+        * relocation. We use the low-level functions which require a
+        * hard-coded divisor. Use CLK_M with divide by (n + 1 = 17)
+        */
+       clock_ll_set_source_divisor(PERIPH_ID_DVC_I2C, 3, 16);
+
+       /*
+        * Give clocks time to stabilize, then take i2c and mselect out of
+        * reset
+        */
+       udelay(1000);
+       reset_set_enable(PERIPH_ID_DVC_I2C, 0);
+       reset_set_enable(PERIPH_ID_MSELECT, 0);
+}
+
+static void set_cpu_running(int run)
+{
+       struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
+
+       debug("set_cpu_running entry, run = %d\n", run);
+       writel(run ? FLOW_MODE_NONE : FLOW_MODE_STOP, &flow->halt_cpu_events);
+}
+
+void start_cpu(u32 reset_vector)
+{
+       debug("start_cpu entry, reset_vector = %x\n", reset_vector);
+       t30_init_clocks();
+
+       /* Enable VDD_CPU */
+       enable_cpu_power_rail();
+
+       set_cpu_running(0);
+
+       /* Hold the CPUs in reset */
+       reset_A9_cpu(1);
+
+       /* Disable the CPU clock */
+       enable_cpu_clock(0);
+
+       /* Enable CoreSight */
+       clock_enable_coresight(1);
+
+       /*
+        * Set the entry point for CPU execution from reset,
+        *  if it's a non-zero value.
+        */
+       if (reset_vector)
+               writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
+
+       /* Enable the CPU clock */
+       enable_cpu_clock(1);
+
+       /* If the CPU doesn't already have power, power it up */
+       powerup_cpu();
+
+       /* Take the CPU out of reset */
+       reset_A9_cpu(0);
+
+       set_cpu_running(1);
+}
index 6a3a1bb354102f967718ef96061e9cfb59c9469a..47f24f580e555b7fa151d4adf44be065ea2cc56a 100644 (file)
@@ -34,6 +34,6 @@ PLATFORM_RELFLAGS += $(PF_RELFLAGS_SLB_AT)
 
 ifneq ($(CONFIG_IMX_CONFIG),)
 
-ALL-y  += $(obj)u-boot.imx
+ALL-y  += $(OBJTREE)/u-boot.imx
 
 endif
index 4ff19c37efe91ac7247f2b48c0d78097de9fd9e1..00b9aba457ed4f9a0e9cb2669bc21fb2bc983b36 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Freescale i.MX28 clock setup code
+ * Freescale i.MX23/i.MX28 clock setup code
  *
  * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
  * on behalf of DENX Software Engineering GmbH
 #include <asm/arch/clock.h>
 #include <asm/arch/imx-regs.h>
 
-/* The PLL frequency is always 480MHz, see section 10.2 in iMX28 datasheet. */
+/*
+ * 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
-/* The XTAL frequency is always 24MHz, see section 10.2 in iMX28 datasheet. */
 #define        XTAL_FREQ_KHZ   24000
 
 #define        PLL_FREQ_MHZ    (PLL_FREQ_KHZ / 1000)
 #define        XTAL_FREQ_MHZ   (XTAL_FREQ_KHZ / 1000)
 
-static uint32_t mx28_get_pclk(void)
+#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;
@@ -73,7 +82,7 @@ static uint32_t mx28_get_pclk(void)
        return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
 }
 
-static uint32_t mx28_get_hclk(void)
+static uint32_t mxs_get_hclk(void)
 {
        struct mxs_clkctrl_regs *clkctrl_regs =
                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
@@ -88,10 +97,10 @@ static uint32_t mx28_get_hclk(void)
                return 0;
 
        div = clkctrl & CLKCTRL_HBUS_DIV_MASK;
-       return mx28_get_pclk() / div;
+       return mxs_get_pclk() / div;
 }
 
-static uint32_t mx28_get_emiclk(void)
+static uint32_t mxs_get_emiclk(void)
 {
        struct mxs_clkctrl_regs *clkctrl_regs =
                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
@@ -116,11 +125,17 @@ static uint32_t mx28_get_emiclk(void)
        return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
 }
 
-static uint32_t mx28_get_gpmiclk(void)
+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;
 
@@ -134,7 +149,7 @@ static uint32_t mx28_get_gpmiclk(void)
        }
 
        /* REF Path */
-       clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_GPMI]);
+       clkfrac = readb(reg);
        frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK;
        div = clkctrl & CLKCTRL_GPMI_DIV_MASK;
        return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div;
@@ -143,7 +158,7 @@ static uint32_t mx28_get_gpmiclk(void)
 /*
  * Set IO clock frequency, in kHz
  */
-void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
+void mxs_set_ioclk(enum mxs_ioclock io, uint32_t freq)
 {
        struct mxs_clkctrl_regs *clkctrl_regs =
                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
@@ -176,7 +191,7 @@ void mx28_set_ioclk(enum mxs_ioclock io, uint32_t freq)
 /*
  * Get IO clock, returns IO clock in kHz
  */
-static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
+static uint32_t mxs_get_ioclk(enum mxs_ioclock io)
 {
        struct mxs_clkctrl_regs *clkctrl_regs =
                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
@@ -197,13 +212,13 @@ static uint32_t mx28_get_ioclk(enum mxs_ioclock io)
 /*
  * Configure SSP clock frequency, in kHz
  */
-void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
+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_SSPCLK3)
+       if (ssp > MXC_SSPCLK_MAX)
                return;
 
        clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) +
@@ -216,7 +231,7 @@ void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
        if (xtal)
                clk = XTAL_FREQ_KHZ;
        else
-               clk = mx28_get_ioclk(ssp >> 1);
+               clk = mxs_get_ioclk(ssp >> 1);
 
        if (freq > clk)
                return;
@@ -241,14 +256,14 @@ void mx28_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal)
 /*
  * Return SSP frequency, in kHz
  */
-static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
+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_SSPCLK3)
+       if (ssp > MXC_SSPCLK_MAX)
                return 0;
 
        tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq);
@@ -263,7 +278,7 @@ static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
        if (tmp == 0)
                return 0;
 
-       clk = mx28_get_ioclk(ssp >> 1);
+       clk = mxs_get_ioclk(ssp >> 1);
 
        return clk / tmp;
 }
@@ -271,14 +286,14 @@ static uint32_t mx28_get_sspclk(enum mxs_sspclock ssp)
 /*
  * Set SSP/MMC bus frequency, in kHz)
  */
-void mx28_set_ssp_busclock(unsigned int bus, uint32_t freq)
+void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq)
 {
        struct mxs_ssp_regs *ssp_regs;
-       const uint32_t sspclk = mx28_get_sspclk(bus);
+       const uint32_t sspclk = mxs_get_sspclk(bus);
        uint32_t reg;
        uint32_t divide, rate, tgtclk;
 
-       ssp_regs = (struct mxs_ssp_regs *)(MXS_SSP0_BASE + (bus * 0x2000));
+       ssp_regs = mxs_ssp_regs_by_bus(bus);
 
        /*
         * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
@@ -313,28 +328,30 @@ uint32_t mxc_get_clock(enum mxc_clock clk)
 {
        switch (clk) {
        case MXC_ARM_CLK:
-               return mx28_get_pclk() * 1000000;
+               return mxs_get_pclk() * 1000000;
        case MXC_GPMI_CLK:
-               return mx28_get_gpmiclk() * 1000000;
+               return mxs_get_gpmiclk() * 1000000;
        case MXC_AHB_CLK:
        case MXC_IPG_CLK:
-               return mx28_get_hclk() * 1000000;
+               return mxs_get_hclk() * 1000000;
        case MXC_EMI_CLK:
-               return mx28_get_emiclk();
+               return mxs_get_emiclk();
        case MXC_IO0_CLK:
-               return mx28_get_ioclk(MXC_IOCLK0);
+               return mxs_get_ioclk(MXC_IOCLK0);
        case MXC_IO1_CLK:
-               return mx28_get_ioclk(MXC_IOCLK1);
+               return mxs_get_ioclk(MXC_IOCLK1);
+       case MXC_XTAL_CLK:
+               return XTAL_FREQ_KHZ * 1000;
        case MXC_SSP0_CLK:
-               return mx28_get_sspclk(MXC_SSPCLK0);
+               return mxs_get_sspclk(MXC_SSPCLK0);
+#ifdef CONFIG_MX28
        case MXC_SSP1_CLK:
-               return mx28_get_sspclk(MXC_SSPCLK1);
+               return mxs_get_sspclk(MXC_SSPCLK1);
        case MXC_SSP2_CLK:
-               return mx28_get_sspclk(MXC_SSPCLK2);
+               return mxs_get_sspclk(MXC_SSPCLK2);
        case MXC_SSP3_CLK:
-               return mx28_get_sspclk(MXC_SSPCLK3);
-       case MXC_XTAL_CLK:
-               return XTAL_FREQ_KHZ * 1000;
+               return mxs_get_sspclk(MXC_SSPCLK3);
+#endif
        }
 
        return 0;
index 6ce8019b835ef832a2dfdab056f8bc7215b73aec..e2b41965db5d8b3c98b12ef984962fd06106b9b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Freescale i.MX28 common code
+ * Freescale i.MX23/i.MX28 common code
  *
  * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
  * on behalf of DENX Software Engineering GmbH
@@ -35,6 +35,7 @@
 #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;
 
@@ -196,6 +197,8 @@ static const char *get_cpu_type(void)
                (struct mxs_digctl_regs *)MXS_DIGCTL_BASE;
 
        switch (readl(&digctl_regs->hw_digctl_chipid) & HW_DIGCTL_CHIPID_MASK) {
+       case HW_DIGCTL_CHIPID_MX23:
+               return "23";
        case HW_DIGCTL_CHIPID_MX28:
                return "28";
        default:
@@ -210,6 +213,21 @@ static const char *get_cpu_rev(void)
        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:
+                       return "1.0";
+               case 0x1:
+                       return "1.1";
+               case 0x2:
+                       return "1.2";
+               case 0x3:
+                       return "1.3";
+               case 0x4:
+                       return "1.4";
+               default:
+                       return "??";
+               }
        case HW_DIGCTL_CHIPID_MX28:
                switch (rev) {
                case 0x1:
@@ -276,7 +294,7 @@ int cpu_eth_init(bd_t *bis)
 }
 #endif
 
-static void __mx28_adjust_mac(int dev_id, unsigned char *mac)
+__weak void mx28_adjust_mac(int dev_id, unsigned char *mac)
 {
        mac[0] = 0x00;
        mac[1] = 0x04; /* Use FSL vendor MAC address by default */
@@ -285,9 +303,6 @@ static void __mx28_adjust_mac(int dev_id, unsigned char *mac)
                mac[5] += 1;
 }
 
-void mx28_adjust_mac(int dev_id, unsigned char *mac)
-       __attribute__((weak, alias("__mx28_adjust_mac")));
-
 #ifdef CONFIG_MX28_FEC_MAC_IN_OCOTP
 
 #define        MXS_OCOTP_MAX_TIMEOUT   1000000
index 1b8502eb9dc03bf3e4edcc1914830db5dc2ed3ef..7e7044033ec8dc5e62a2c4df9c27c64d517044ab 100644 (file)
@@ -51,12 +51,21 @@ void early_delay(int delay)
 
 #define        MUX_CONFIG_BOOTMODE_PAD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
 static const iomux_cfg_t iomux_boot[] = {
+#if defined(CONFIG_MX23)
+       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,
+#elif defined(CONFIG_MX28)
        MX28_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_BOOTMODE_PAD,
        MX28_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_BOOTMODE_PAD,
        MX28_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_BOOTMODE_PAD,
        MX28_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_BOOTMODE_PAD,
        MX28_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_BOOTMODE_PAD,
        MX28_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_BOOTMODE_PAD,
+#endif
 };
 
 static uint8_t mxs_get_bootmode_index(void)
@@ -68,6 +77,21 @@ static uint8_t mxs_get_bootmode_index(void)
        /* Setup IOMUX of bootmode pads to GPIO */
        mxs_iomux_setup_multiple_pads(iomux_boot, ARRAY_SIZE(iomux_boot));
 
+#if defined(CONFIG_MX23)
+       /* 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)
        /* Setup bootmode pins as GPIO input */
        gpio_direction_input(MX28_PAD_LCD_D00__GPIO_1_0);
        gpio_direction_input(MX28_PAD_LCD_D01__GPIO_1_1);
@@ -83,6 +107,7 @@ static uint8_t mxs_get_bootmode_index(void)
        bootmode |= (gpio_get_value(MX28_PAD_LCD_D03__GPIO_1_3) ? 1 : 0) << 3;
        bootmode |= (gpio_get_value(MX28_PAD_LCD_D04__GPIO_1_4) ? 1 : 0) << 4;
        bootmode |= (gpio_get_value(MX28_PAD_LCD_D05__GPIO_1_5) ? 1 : 0) << 5;
+#endif
 
        for (i = 0; i < ARRAY_SIZE(mxs_boot_modes); i++) {
                masked = bootmode & mxs_boot_modes[i].boot_mask;
index 401c51362bfd6bf6c0c04a68dce15973adcfe20a..f8392f6398a20d48379efca2041fdcb349cb5197 100644 (file)
@@ -27,6 +27,7 @@
 #include <config.h>
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
+#include <linux/compiler.h>
 
 #include "mxs_init.h"
 
@@ -83,16 +84,30 @@ static uint32_t dram_vals[] = {
        0x06120612, 0x04320432, 0x04320432, 0x00040004,
        0x00040004, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00010001
+
+/*
+ * 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
 };
 
-void __mxs_adjust_memory_params(uint32_t *dram_vals)
+__weak void mxs_adjust_memory_params(uint32_t *dram_vals)
 {
 }
-void mxs_adjust_memory_params(uint32_t *dram_vals)
-       __attribute__((weak, alias("__mxs_adjust_memory_params")));
 
 static void initialize_dram_values(void)
 {
@@ -102,19 +117,30 @@ static void initialize_dram_values(void)
 
        for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
                writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
+
+#ifdef CONFIG_MX23
+       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
 
        /* Gate EMI clock */
        writeb(CLKCTRL_FRAC_CLKGATE,
                &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]);
 
-       /* Set fractional divider for ref_emi to 480 * 18 / 21 = 411MHz */
-       writeb(CLKCTRL_FRAC_CLKGATE | (21 & CLKCTRL_FRAC_FRAC_MASK),
+       /* 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 */
@@ -197,10 +223,60 @@ uint32_t mxs_mem_get_size(void)
        return sz;
 }
 
-void mxs_mem_init(void)
+#ifdef CONFIG_MX23
+static void mx23_mem_setup_vddmem(void)
+{
+       struct mxs_power_regs *power_regs =
+               (struct mxs_power_regs *)MXS_POWER_BASE;
+
+       writel((0x12 << POWER_VDDMEMCTRL_TRG_OFFSET) |
+               POWER_VDDMEMCTRL_ENABLE_ILIMIT |
+               POWER_VDDMEMCTRL_ENABLE_LINREG |
+               POWER_VDDMEMCTRL_PULLDOWN_ACTIVE,
+               &power_regs->hw_power_vddmemctrl);
+
+       early_delay(10000);
+
+       writel((0x12 << POWER_VDDMEMCTRL_TRG_OFFSET) |
+               POWER_VDDMEMCTRL_ENABLE_LINREG,
+               &power_regs->hw_power_vddmemctrl);
+}
+
+static void mx23_mem_init(void)
+{
+       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_CTL16 */
+       setbits_le32(MXS_DRAM_BASE + 0x20, 1 << 16);
+
+       clrbits_le32(MXS_DRAM_BASE + 0x40, 1 << 17);
+       early_delay(20000);
+
+       /* Adjust EMI port priority. */
+       clrsetbits_le32(0x80020000, 0x1f << 16, 0x8);
+       early_delay(20000);
+
+       setbits_le32(MXS_DRAM_BASE + 0x40, 1 << 19);
+       setbits_le32(MXS_DRAM_BASE + 0x40, 1 << 11);
+
+       /* Wait for bit 10 (DRAM init complete) in DRAM_CTL18 */
+       while (!(readl(MXS_DRAM_BASE + 0x48) & (1 << 10)))
+               ;
+}
+#endif
+
+#ifdef CONFIG_MX28
+static void mx28_mem_init(void)
 {
-       struct mxs_clkctrl_regs *clkctrl_regs =
-               (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
        struct mxs_pinctrl_regs *pinctrl_regs =
                (struct mxs_pinctrl_regs *)MXS_PINCTRL_BASE;
 
@@ -208,16 +284,6 @@ void mxs_mem_init(void)
        writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
                &pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
 
-       /* Power up PLL0 */
-       writel(CLKCTRL_PLL0CTRL0_POWER,
-               &clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
-
-       early_delay(11000);
-
-       mxs_mem_init_clock();
-
-       mxs_mem_setup_vdda();
-
        /*
         * Configure the DRAM registers
         */
@@ -236,6 +302,22 @@ void mxs_mem_init(void)
        /* 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);
 
index be44c22976352fdfec2e193acd6d8402b12484c0..e9d6302b7a7af2a0c8ad4e12b366fb582e6bc037 100644 (file)
@@ -881,11 +881,23 @@ static void mxs_setup_batt_detect(void)
        early_delay(10);
 }
 
+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
+}
+
 void mxs_power_init(void)
 {
        struct mxs_power_regs *power_regs =
                (struct mxs_power_regs *)MXS_POWER_BASE;
 
+       mxs_ungate_power();
+
        mxs_power_clock2xtal();
        mxs_power_clear_auto_restart();
        mxs_power_set_linreg();
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 (file)
index 0000000..3a51879
--- /dev/null
@@ -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;
+}
index 4fdbee4bc0e90767f05b4150f5db52046f30e3b7..ee8c2b3fa573e2f138b2bcaa3a6823c0f9a61cc8 100644 (file)
@@ -32,7 +32,7 @@ COBJS += cache_v7.o
 COBJS  += cpu.o
 COBJS  += syslib.o
 
-ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA20),)
+ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA),)
 SOBJS  += lowlevel_init.o
 endif
 
index 9c3e2f3ce421e3e24013f013dac85085d74286a1..350e94639260016411f16cf78704fc4d8073f041 100644 (file)
@@ -40,5 +40,5 @@ PF_NO_UNALIGNED := $(call cc-option, -mno-unaligned-access,)
 PLATFORM_NO_UNALIGNED := $(PF_NO_UNALIGNED)
 
 ifneq ($(CONFIG_IMX_CONFIG),)
-ALL-y  += $(obj)u-boot.imx
+ALL-y  += $(OBJTREE)/u-boot.imx
 endif
index dcc1f831bc814a2b47fd034815091561859b7000..6b59529d5dd9c4e5092e7213ef22da911accd472 100644 (file)
@@ -251,12 +251,12 @@ ENTRY(c_runtime_cpu_setup)
 /*
  * Move vector table
  */
-#if !defined(CONFIG_TEGRA20)
+#if !defined(CONFIG_TEGRA)
        /* Set vector address in CP15 VBAR register */
        ldr     r0, =_start
        add     r0, r0, r9
        mcr     p15, 0, r0, c12, c0, 0  @Set VBAR
-#endif /* !Tegra20 */
+#endif /* !Tegra */
 
        bx      lr
 
diff --git a/arch/arm/cpu/armv7/tegra114/Makefile b/arch/arm/cpu/armv7/tegra114/Makefile
new file mode 100644 (file)
index 0000000..eb98c8e
--- /dev/null
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope 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 $(TOPDIR)/config.mk
+
+LIB    = $(obj)lib$(SOC).o
+
+COBJS  := $(COBJS-y)
+SRCS   := $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+
+all:   $(obj).depend $(LIB)
+
+$(LIB):        $(OBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/armv7/tegra114/config.mk b/arch/arm/cpu/armv7/tegra114/config.mk
new file mode 100644 (file)
index 0000000..cb1a19d
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+#
+# (C) Copyright 2002
+# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope 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/>.
+#
+CONFIG_ARCH_DEVICE_TREE := tegra114
diff --git a/arch/arm/cpu/armv7/tegra30/Makefile b/arch/arm/cpu/armv7/tegra30/Makefile
new file mode 100644 (file)
index 0000000..04adb52
--- /dev/null
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope 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 $(TOPDIR)/config.mk
+
+LIB    = $(obj)lib$(SOC).o
+
+COBJS  := $(COBJS-y)
+SRCS   := $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(COBJS))
+
+all:   $(obj).depend $(LIB)
+
+$(LIB):        $(OBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/armv7/tegra30/config.mk b/arch/arm/cpu/armv7/tegra30/config.mk
new file mode 100644 (file)
index 0000000..719ca81
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+#
+# (C) Copyright 2002
+# Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope 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/>.
+#
+CONFIG_ARCH_DEVICE_TREE := tegra30
index 38e90d314390fb3a0092a74dc4562d08b606eaab..8e95c7ee1d367fd03b3dbb650941594fdb08f421 100644 (file)
@@ -28,7 +28,7 @@ include $(TOPDIR)/config.mk
 LIB    = $(obj)libcputegra-common.o
 
 SOBJS += lowlevel_init.o
-COBJS-y        += ap.o board.o sys_info.o timer.o
+COBJS-y        += ap.o board.o sys_info.o timer.o clock.o
 
 SRCS   := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
index c4eb137480340bb660e76ae3abcaca8f6e3bb7eb..236cda8419fc0ce5c4444d201cee35308b35c17a 100644 (file)
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */
+
+/* Tegra AP (Application Processor) code */
+
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/gp_padctrl.h>
 #include <asm/arch-tegra/ap.h>
+#include <asm/arch-tegra/clock.h>
 #include <asm/arch-tegra/fuse.h>
 #include <asm/arch-tegra/pmc.h>
 #include <asm/arch-tegra/scu.h>
+#include <asm/arch-tegra/tegra.h>
 #include <asm/arch-tegra/warmboot.h>
 
 int tegra_get_chip_type(void)
@@ -38,7 +43,7 @@ int tegra_get_chip_type(void)
        /*
         * This is undocumented, Chip ID is bits 15:8 of the register
         * APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for
-        * Tegra30
+        * Tegra30, and 0x35 for T114.
         */
        gp = (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
        rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT;
@@ -58,6 +63,18 @@ int tegra_get_chip_type(void)
                        return TEGRA_SOC_T25;
                }
                break;
+       case CHIPID_TEGRA30:
+               switch (tegra_sku_id) {
+               case SKU_ID_T30:
+                       return TEGRA_SOC_T30;
+               }
+               break;
+       case CHIPID_TEGRA114:
+               switch (tegra_sku_id) {
+               case SKU_ID_T114_ENG:
+                       return TEGRA_SOC_T114;
+               }
+               break;
        }
        /* unknown sku id */
        return TEGRA_SOC_UNKNOWN;
@@ -93,7 +110,7 @@ static u32 get_odmdata(void)
 
        u32 bct_start, odmdata;
 
-       bct_start = readl(AP20_BASE_PA_SRAM + NVBOOTINFOTABLE_BCTPTR);
+       bct_start = readl(NV_PA_BASE_SRAM + NVBOOTINFOTABLE_BCTPTR);
        odmdata = readl(bct_start + BCT_ODMDATA_OFFSET);
 
        return odmdata;
@@ -127,5 +144,5 @@ void s_init(void)
                "orr    r0, r0, #0x41\n"
                "mcr    p15, 0, r0, c1, c0, 1\n");
 
-       /* FIXME: should have ap20's L2 disabled too? */
+       /* FIXME: should have SoC's L2 disabled too? */
 }
index b2e10c6db875a9cc12b74ddb27c6bd9c783c3b0f..58ea6289d37bc6a1f039e11ce9c869449b634d23 100644 (file)
@@ -37,8 +37,10 @@ enum {
        /* UARTs which we can enable */
        UARTA   = 1 << 0,
        UARTB   = 1 << 1,
+       UARTC   = 1 << 2,
        UARTD   = 1 << 3,
-       UART_COUNT = 4,
+       UARTE   = 1 << 4,
+       UART_COUNT = 5,
 };
 
 /*
@@ -54,16 +56,37 @@ unsigned int query_sdram_size(void)
        reg = readl(&pmc->pmc_scratch20);
        debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg);
 
-       /* bits 31:28 in OdmData are used for RAM size  */
+#if defined(CONFIG_TEGRA20)
+       /* bits 30:28 in OdmData are used for RAM size on T20  */
+       reg &= 0x70000000;
+
        switch ((reg) >> 28) {
        case 1:
                return 0x10000000;      /* 256 MB */
+       case 0:
        case 2:
        default:
                return 0x20000000;      /* 512 MB */
        case 3:
                return 0x40000000;      /* 1GB */
        }
+#else  /* Tegra30/Tegra114 */
+       /* bits 31:28 in OdmData are used for RAM size on T30  */
+       switch ((reg) >> 28) {
+       case 0:
+       case 1:
+       default:
+               return 0x10000000;      /* 256 MB */
+       case 2:
+               return 0x20000000;      /* 512 MB */
+       case 3:
+               return 0x30000000;      /* 768 MB */
+       case 4:
+               return 0x40000000;      /* 1GB */
+       case 8:
+               return 0x7ff00000;      /* 2GB - 1MB */
+       }
+#endif
 }
 
 int dram_init(void)
@@ -82,19 +105,33 @@ int checkboard(void)
 #endif /* CONFIG_DISPLAY_BOARDINFO */
 
 static int uart_configs[] = {
-#if defined(CONFIG_TEGRA_UARTA_UAA_UAB)
+#if defined(CONFIG_TEGRA20)
+ #if defined(CONFIG_TEGRA_UARTA_UAA_UAB)
        FUNCMUX_UART1_UAA_UAB,
-#elif defined(CONFIG_TEGRA_UARTA_GPU)
+ #elif defined(CONFIG_TEGRA_UARTA_GPU)
        FUNCMUX_UART1_GPU,
-#elif defined(CONFIG_TEGRA_UARTA_SDIO1)
+ #elif defined(CONFIG_TEGRA_UARTA_SDIO1)
        FUNCMUX_UART1_SDIO1,
-#else
+ #else
        FUNCMUX_UART1_IRRX_IRTX,
 #endif
-       FUNCMUX_UART2_IRDA,
+       FUNCMUX_UART2_UAD,
        -1,
        FUNCMUX_UART4_GMC,
        -1,
+#elif defined(CONFIG_TEGRA30)
+       FUNCMUX_UART1_ULPI,     /* UARTA */
+       -1,
+       -1,
+       -1,
+       -1,
+#else  /* Tegra114 */
+       -1,
+       -1,
+       -1,
+       FUNCMUX_UART4_GMI,      /* UARTD */
+       -1,
+#endif
 };
 
 /**
@@ -109,6 +146,7 @@ static void setup_uarts(int uart_ids)
                PERIPH_ID_UART2,
                PERIPH_ID_UART3,
                PERIPH_ID_UART4,
+               PERIPH_ID_UART5,
        };
        size_t i;
 
@@ -132,8 +170,14 @@ void board_init_uart_f(void)
 #ifdef CONFIG_TEGRA_ENABLE_UARTB
        uart_ids |= UARTB;
 #endif
+#ifdef CONFIG_TEGRA_ENABLE_UARTC
+       uart_ids |= UARTC;
+#endif
 #ifdef CONFIG_TEGRA_ENABLE_UARTD
        uart_ids |= UARTD;
+#endif
+#ifdef CONFIG_TEGRA_ENABLE_UARTE
+       uart_ids |= UARTE;
 #endif
        setup_uarts(uart_ids);
 }
diff --git a/arch/arm/cpu/tegra-common/clock.c b/arch/arm/cpu/tegra-common/clock.c
new file mode 100644 (file)
index 0000000..49a0633
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/>.
+ */
+
+/* Tegra SoC common clock control functions */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/timer.h>
+#include <div64.h>
+#include <fdtdec.h>
+
+/*
+ * This is our record of the current clock rate of each clock. We don't
+ * fill all of these in since we are only really interested in clocks which
+ * we use as parents.
+ */
+static unsigned pll_rate[CLOCK_ID_COUNT];
+
+/*
+ * The oscillator frequency is fixed to one of four set values. Based on this
+ * the other clocks are set up appropriately.
+ */
+static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = {
+       13000000,
+       19200000,
+       12000000,
+       26000000,
+};
+
+/* return 1 if a peripheral ID is in range */
+#define clock_type_id_isvalid(id) ((id) >= 0 && \
+               (id) < CLOCK_TYPE_COUNT)
+
+char pllp_valid = 1;   /* PLLP is set up correctly */
+
+/* return 1 if a periphc_internal_id is in range */
+#define periphc_internal_id_isvalid(id) ((id) >= 0 && \
+               (id) < PERIPHC_COUNT)
+
+/* number of clock outputs of a PLL */
+static const u8 pll_num_clkouts[] = {
+       1,      /* PLLC */
+       1,      /* PLLM */
+       4,      /* PLLP */
+       1,      /* PLLA */
+       0,      /* PLLU */
+       0,      /* PLLD */
+};
+
+int clock_get_osc_bypass(void)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 reg;
+
+       reg = readl(&clkrst->crc_osc_ctrl);
+       return (reg & OSC_XOBP_MASK) >> OSC_XOBP_SHIFT;
+}
+
+/* Returns a pointer to the registers of the given pll */
+static struct clk_pll *get_pll(enum clock_id clkid)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+
+       assert(clock_id_is_pll(clkid));
+       return &clkrst->crc_pll[clkid];
+}
+
+int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
+               u32 *divp, u32 *cpcon, u32 *lfcon)
+{
+       struct clk_pll *pll = get_pll(clkid);
+       u32 data;
+
+       assert(clkid != CLOCK_ID_USB);
+
+       /* Safety check, adds to code size but is small */
+       if (!clock_id_is_pll(clkid) || clkid == CLOCK_ID_USB)
+               return -1;
+       data = readl(&pll->pll_base);
+       *divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
+       *divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT;
+       *divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
+       data = readl(&pll->pll_misc);
+       *cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT;
+       *lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT;
+
+       return 0;
+}
+
+unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
+               u32 divp, u32 cpcon, u32 lfcon)
+{
+       struct clk_pll *pll = get_pll(clkid);
+       u32 data;
+
+       /*
+        * We cheat by treating all PLL (except PLLU) in the same fashion.
+        * This works only because:
+        * - same fields are always mapped at same offsets, except DCCON
+        * - DCCON is always 0, doesn't conflict
+        * - M,N, P of PLLP values are ignored for PLLP
+        */
+       data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT);
+       writel(data, &pll->pll_misc);
+
+       data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) |
+                       (0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT);
+
+       if (clkid == CLOCK_ID_USB)
+               data |= divp << PLLU_VCO_FREQ_SHIFT;
+       else
+               data |= divp << PLL_DIVP_SHIFT;
+       writel(data, &pll->pll_base);
+
+       /* calculate the stable time */
+       return timer_get_us() + CLOCK_PLL_STABLE_DELAY_US;
+}
+
+void clock_ll_set_source_divisor(enum periph_id periph_id, unsigned source,
+                       unsigned divisor)
+{
+       u32 *reg = get_periph_source_reg(periph_id);
+       u32 value;
+
+       value = readl(reg);
+
+       value &= ~OUT_CLK_SOURCE_MASK;
+       value |= source << OUT_CLK_SOURCE_SHIFT;
+
+       value &= ~OUT_CLK_DIVISOR_MASK;
+       value |= divisor << OUT_CLK_DIVISOR_SHIFT;
+
+       writel(value, reg);
+}
+
+void clock_ll_set_source(enum periph_id periph_id, unsigned source)
+{
+       u32 *reg = get_periph_source_reg(periph_id);
+
+       clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
+                       source << OUT_CLK_SOURCE_SHIFT);
+}
+
+/**
+ * Given the parent's rate and the required rate for the children, this works
+ * out the peripheral clock divider to use, in 7.1 binary format.
+ *
+ * @param divider_bits number of divider bits (8 or 16)
+ * @param parent_rate  clock rate of parent clock in Hz
+ * @param rate         required clock rate for this clock
+ * @return divider which should be used
+ */
+static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate,
+                          unsigned long rate)
+{
+       u64 divider = parent_rate * 2;
+       unsigned max_divider = 1 << divider_bits;
+
+       divider += rate - 1;
+       do_div(divider, rate);
+
+       if ((s64)divider - 2 < 0)
+               return 0;
+
+       if ((s64)divider - 2 >= max_divider)
+               return -1;
+
+       return divider - 2;
+}
+
+int clock_set_pllout(enum clock_id clkid, enum pll_out_id pllout, unsigned rate)
+{
+       struct clk_pll *pll = get_pll(clkid);
+       int data = 0, div = 0, offset = 0;
+
+       if (!clock_id_is_pll(clkid))
+               return -1;
+
+       if (pllout + 1 > pll_num_clkouts[clkid])
+               return -1;
+
+       div = clk_get_divider(8, pll_rate[clkid], rate);
+
+       if (div < 0)
+               return -1;
+
+       /* out2 and out4 are in the high part of the register */
+       if (pllout == PLL_OUT2 || pllout == PLL_OUT4)
+               offset = 16;
+
+       data = (div << PLL_OUT_RATIO_SHIFT) |
+                       PLL_OUT_OVRRIDE | PLL_OUT_CLKEN | PLL_OUT_RSTN;
+       clrsetbits_le32(&pll->pll_out[pllout >> 1],
+                       PLL_OUT_RATIO_MASK << offset, data << offset);
+
+       return 0;
+}
+
+/**
+ * Given the parent's rate and the divider in 7.1 format, this works out the
+ * resulting peripheral clock rate.
+ *
+ * @param parent_rate  clock rate of parent clock in Hz
+ * @param divider which should be used in 7.1 format
+ * @return effective clock rate of peripheral
+ */
+static unsigned long get_rate_from_divider(unsigned long parent_rate,
+                                          int divider)
+{
+       u64 rate;
+
+       rate = (u64)parent_rate * 2;
+       do_div(rate, divider + 2);
+       return rate;
+}
+
+unsigned long clock_get_periph_rate(enum periph_id periph_id,
+               enum clock_id parent)
+{
+       u32 *reg = get_periph_source_reg(periph_id);
+
+       return get_rate_from_divider(pll_rate[parent],
+               (readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT);
+}
+
+/**
+ * Find the best available 7.1 format divisor given a parent clock rate and
+ * required child clock rate. This function assumes that a second-stage
+ * divisor is available which can divide by powers of 2 from 1 to 256.
+ *
+ * @param divider_bits number of divider bits (8 or 16)
+ * @param parent_rate  clock rate of parent clock in Hz
+ * @param rate         required clock rate for this clock
+ * @param extra_div    value for the second-stage divisor (not set if this
+ *                     function returns -1.
+ * @return divider which should be used, or -1 if nothing is valid
+ *
+ */
+static int find_best_divider(unsigned divider_bits, unsigned long parent_rate,
+                               unsigned long rate, int *extra_div)
+{
+       int shift;
+       int best_divider = -1;
+       int best_error = rate;
+
+       /* try dividers from 1 to 256 and find closest match */
+       for (shift = 0; shift <= 8 && best_error > 0; shift++) {
+               unsigned divided_parent = parent_rate >> shift;
+               int divider = clk_get_divider(divider_bits, divided_parent,
+                                               rate);
+               unsigned effective_rate = get_rate_from_divider(divided_parent,
+                                               divider);
+               int error = rate - effective_rate;
+
+               /* Given a valid divider, look for the lowest error */
+               if (divider != -1 && error < best_error) {
+                       best_error = error;
+                       *extra_div = 1 << shift;
+                       best_divider = divider;
+               }
+       }
+
+       /* return what we found - *extra_div will already be set */
+       return best_divider;
+}
+
+/**
+ * Adjust peripheral PLL to use the given divider and source.
+ *
+ * @param periph_id    peripheral to adjust
+ * @param source       Source number (0-3 or 0-7)
+ * @param mux_bits     Number of mux bits (2 or 4)
+ * @param divider      Required divider in 7.1 or 15.1 format
+ * @return 0 if ok, -1 on error (requesting a parent clock which is not valid
+ *             for this peripheral)
+ */
+static int adjust_periph_pll(enum periph_id periph_id, int source,
+                               int mux_bits, unsigned divider)
+{
+       u32 *reg = get_periph_source_reg(periph_id);
+
+       clrsetbits_le32(reg, OUT_CLK_DIVISOR_MASK,
+                       divider << OUT_CLK_DIVISOR_SHIFT);
+       udelay(1);
+
+       /* work out the source clock and set it */
+       if (source < 0)
+               return -1;
+       if (mux_bits == 4) {
+               clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
+                       source << OUT_CLK_SOURCE4_SHIFT);
+       } else {
+               clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
+                       source << OUT_CLK_SOURCE_SHIFT);
+       }
+       udelay(2);
+       return 0;
+}
+
+unsigned clock_adjust_periph_pll_div(enum periph_id periph_id,
+               enum clock_id parent, unsigned rate, int *extra_div)
+{
+       unsigned effective_rate;
+       int mux_bits, divider_bits, source;
+       int divider;
+
+       /* work out the source clock and set it */
+       source = get_periph_clock_source(periph_id, parent, &mux_bits,
+                                        &divider_bits);
+
+       if (extra_div)
+               divider = find_best_divider(divider_bits, pll_rate[parent],
+                                               rate, extra_div);
+       else
+               divider = clk_get_divider(divider_bits, pll_rate[parent],
+                                         rate);
+       assert(divider >= 0);
+       if (adjust_periph_pll(periph_id, source, mux_bits, divider))
+               return -1U;
+       debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate,
+               get_periph_source_reg(periph_id),
+               readl(get_periph_source_reg(periph_id)));
+
+       /* Check what we ended up with. This shouldn't matter though */
+       effective_rate = clock_get_periph_rate(periph_id, parent);
+       if (extra_div)
+               effective_rate /= *extra_div;
+       if (rate != effective_rate)
+               debug("Requested clock rate %u not honored (got %u)\n",
+                       rate, effective_rate);
+       return effective_rate;
+}
+
+unsigned clock_start_periph_pll(enum periph_id periph_id,
+               enum clock_id parent, unsigned rate)
+{
+       unsigned effective_rate;
+
+       reset_set_enable(periph_id, 1);
+       clock_enable(periph_id);
+
+       effective_rate = clock_adjust_periph_pll_div(periph_id, parent, rate,
+                                                NULL);
+
+       reset_set_enable(periph_id, 0);
+       return effective_rate;
+}
+
+void clock_enable(enum periph_id clkid)
+{
+       clock_set_enable(clkid, 1);
+}
+
+void clock_disable(enum periph_id clkid)
+{
+       clock_set_enable(clkid, 0);
+}
+
+void reset_periph(enum periph_id periph_id, int us_delay)
+{
+       /* Put peripheral into reset */
+       reset_set_enable(periph_id, 1);
+       udelay(us_delay);
+
+       /* Remove reset */
+       reset_set_enable(periph_id, 0);
+
+       udelay(us_delay);
+}
+
+void reset_cmplx_set_enable(int cpu, int which, int reset)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 mask;
+
+       /* Form the mask, which depends on the cpu chosen (2 or 4) */
+       assert(cpu >= 0 && cpu < MAX_NUM_CPU);
+       mask = which << cpu;
+
+       /* either enable or disable those reset for that CPU */
+       if (reset)
+               writel(mask, &clkrst->crc_cpu_cmplx_set);
+       else
+               writel(mask, &clkrst->crc_cpu_cmplx_clr);
+}
+
+unsigned clock_get_rate(enum clock_id clkid)
+{
+       struct clk_pll *pll;
+       u32 base;
+       u32 divm;
+       u64 parent_rate;
+       u64 rate;
+
+       parent_rate = osc_freq[clock_get_osc_freq()];
+       if (clkid == CLOCK_ID_OSC)
+               return parent_rate;
+
+       pll = get_pll(clkid);
+       base = readl(&pll->pll_base);
+
+       /* Oh for bf_unpack()... */
+       rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT);
+       divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
+       if (clkid == CLOCK_ID_USB)
+               divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT;
+       else
+               divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
+       do_div(rate, divm);
+       return rate;
+}
+
+/**
+ * Set the output frequency you want for each PLL clock.
+ * PLL output frequencies are programmed by setting their N, M and P values.
+ * The governing equations are:
+ *     VCO = (Fi / m) * n, Fo = VCO / (2^p)
+ *     where Fo is the output frequency from the PLL.
+ * Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi)
+ *     216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1
+ * Please see Tegra TRM section 5.3 to get the detail for PLL Programming
+ *
+ * @param n PLL feedback divider(DIVN)
+ * @param m PLL input divider(DIVN)
+ * @param p post divider(DIVP)
+ * @param cpcon base PLL charge pump(CPCON)
+ * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
+ *             be overriden), 1 if PLL is already correct
+ */
+int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon)
+{
+       u32 base_reg;
+       u32 misc_reg;
+       struct clk_pll *pll;
+
+       pll = get_pll(clkid);
+
+       base_reg = readl(&pll->pll_base);
+
+       /* Set BYPASS, m, n and p to PLL_BASE */
+       base_reg &= ~PLL_DIVM_MASK;
+       base_reg |= m << PLL_DIVM_SHIFT;
+
+       base_reg &= ~PLL_DIVN_MASK;
+       base_reg |= n << PLL_DIVN_SHIFT;
+
+       base_reg &= ~PLL_DIVP_MASK;
+       base_reg |= p << PLL_DIVP_SHIFT;
+
+       if (clkid == CLOCK_ID_PERIPH) {
+               /*
+                * If the PLL is already set up, check that it is correct
+                * and record this info for clock_verify() to check.
+                */
+               if (base_reg & PLL_BASE_OVRRIDE_MASK) {
+                       base_reg |= PLL_ENABLE_MASK;
+                       if (base_reg != readl(&pll->pll_base))
+                               pllp_valid = 0;
+                       return pllp_valid ? 1 : -1;
+               }
+               base_reg |= PLL_BASE_OVRRIDE_MASK;
+       }
+
+       base_reg |= PLL_BYPASS_MASK;
+       writel(base_reg, &pll->pll_base);
+
+       /* Set cpcon to PLL_MISC */
+       misc_reg = readl(&pll->pll_misc);
+       misc_reg &= ~PLL_CPCON_MASK;
+       misc_reg |= cpcon << PLL_CPCON_SHIFT;
+       writel(misc_reg, &pll->pll_misc);
+
+       /* Enable PLL */
+       base_reg |= PLL_ENABLE_MASK;
+       writel(base_reg, &pll->pll_base);
+
+       /* Disable BYPASS */
+       base_reg &= ~PLL_BYPASS_MASK;
+       writel(base_reg, &pll->pll_base);
+
+       return 0;
+}
+
+void clock_ll_start_uart(enum periph_id periph_id)
+{
+       /* Assert UART reset and enable clock */
+       reset_set_enable(periph_id, 1);
+       clock_enable(periph_id);
+       clock_ll_set_source(periph_id, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */
+
+       /* wait for 2us */
+       udelay(2);
+
+       /* De-assert reset to UART */
+       reset_set_enable(periph_id, 0);
+}
+
+#ifdef CONFIG_OF_CONTROL
+int clock_decode_periph_id(const void *blob, int node)
+{
+       enum periph_id id;
+       u32 cell[2];
+       int err;
+
+       err = fdtdec_get_int_array(blob, node, "clocks", cell,
+                                  ARRAY_SIZE(cell));
+       if (err)
+               return -1;
+       id = clk_id_to_periph_id(cell[1]);
+       assert(clock_periph_id_isvalid(id));
+       return id;
+}
+#endif /* CONFIG_OF_CONTROL */
+
+int clock_verify(void)
+{
+       struct clk_pll *pll = get_pll(CLOCK_ID_PERIPH);
+       u32 reg = readl(&pll->pll_base);
+
+       if (!pllp_valid) {
+               printf("Warning: PLLP %x is not correct\n", reg);
+               return -1;
+       }
+       debug("PLLP %x is correct\n", reg);
+       return 0;
+}
+
+void clock_init(void)
+{
+       pll_rate[CLOCK_ID_MEMORY] = clock_get_rate(CLOCK_ID_MEMORY);
+       pll_rate[CLOCK_ID_PERIPH] = clock_get_rate(CLOCK_ID_PERIPH);
+       pll_rate[CLOCK_ID_CGENERAL] = clock_get_rate(CLOCK_ID_CGENERAL);
+       pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC);
+       pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
+       pll_rate[CLOCK_ID_XCPU] = clock_get_rate(CLOCK_ID_XCPU);
+       debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]);
+       debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
+       debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);
+       debug("PLLC = %d\n", pll_rate[CLOCK_ID_CGENERAL]);
+       debug("PLLX = %d\n", pll_rate[CLOCK_ID_XCPU]);
+}
index 1a0bb561a7fee91c0585fd5a1f272cc42b78765a..4632f15d5b446a6beab4528665cfb91f5cb89e4d 100644 (file)
  */
 
 #include <common.h>
+#include <linux/ctype.h>
 
 #ifdef CONFIG_DISPLAY_CPUINFO
+void upstring(char *s)
+{
+       while (*s) {
+               *s = toupper(*s);
+               s++;
+       }
+}
+
 /* Print CPU information */
 int print_cpuinfo(void)
 {
-       puts("TEGRA20\n");
+       char soc_name[10];
+
+       strncpy(soc_name, CONFIG_SYS_SOC, 10);
+       upstring(soc_name);
+       puts(soc_name);
+       puts("\n");
 
        /* TBD: Add printf of major/minor rev info, stepping, etc. */
        return 0;
diff --git a/arch/arm/cpu/tegra114-common/Makefile b/arch/arm/cpu/tegra114-common/Makefile
new file mode 100644 (file)
index 0000000..5b53a71
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope 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 $(TOPDIR)/config.mk
+
+LIB    = $(obj)lib$(SOC)-common.o
+
+COBJS-y        += clock.o funcmux.o pinmux.o
+
+SRCS   := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
+
+all:   $(obj).depend $(LIB)
+
+$(LIB):        $(OBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/tegra114-common/clock.c b/arch/arm/cpu/tegra114-common/clock.c
new file mode 100644 (file)
index 0000000..9b29ce1
--- /dev/null
@@ -0,0 +1,655 @@
+/*
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/>.
+ */
+
+/* Tegra114 Clock control functions */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/timer.h>
+#include <div64.h>
+#include <fdtdec.h>
+
+/*
+ * Clock types that we can use as a source. The Tegra114 has muxes for the
+ * peripheral clocks, and in most cases there are four options for the clock
+ * source. This gives us a clock 'type' and exploits what commonality exists
+ * in the device.
+ *
+ * Letters are obvious, except for T which means CLK_M, and S which means the
+ * clock derived from 32KHz. Beware that CLK_M (also called OSC in the
+ * datasheet) and PLL_M are different things. The former is the basic
+ * clock supplied to the SOC from an external oscillator. The latter is the
+ * memory clock PLL.
+ *
+ * See definitions in clock_id in the header file.
+ */
+enum clock_type_id {
+       CLOCK_TYPE_AXPT,        /* PLL_A, PLL_X, PLL_P, CLK_M */
+       CLOCK_TYPE_MCPA,        /* and so on */
+       CLOCK_TYPE_MCPT,
+       CLOCK_TYPE_PCM,
+       CLOCK_TYPE_PCMT,
+       CLOCK_TYPE_PCMT16,
+       CLOCK_TYPE_PDCT,
+       CLOCK_TYPE_ACPT,
+       CLOCK_TYPE_ASPTE,
+       CLOCK_TYPE_PMDACD2T,
+       CLOCK_TYPE_PCST,
+
+       CLOCK_TYPE_COUNT,
+       CLOCK_TYPE_NONE = -1,   /* invalid clock type */
+};
+
+enum {
+       CLOCK_MAX_MUX   = 8     /* number of source options for each clock */
+};
+
+enum {
+       MASK_BITS_31_30 = 2,    /* num of bits used to specify clock source */
+       MASK_BITS_31_29,
+       MASK_BITS_29_28,
+};
+
+/*
+ * Clock source mux for each clock type. This just converts our enum into
+ * a list of mux sources for use by the code.
+ *
+ * Note:
+ *  The extra column in each clock source array is used to store the mask
+ *  bits in its register for the source.
+ */
+#define CLK(x) CLOCK_ID_ ## x
+static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX+1] = {
+       { CLK(AUDIO),   CLK(XCPU),      CLK(PERIPH),    CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(MEMORY),  CLK(CGENERAL),  CLK(PERIPH),    CLK(AUDIO),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(MEMORY),  CLK(CGENERAL),  CLK(PERIPH),    CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),    CLK(NONE),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),    CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),    CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(PERIPH),  CLK(DISPLAY),   CLK(CGENERAL),  CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(AUDIO),   CLK(CGENERAL),  CLK(PERIPH),    CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(AUDIO),   CLK(SFROM32KHZ),        CLK(PERIPH),    CLK(OSC),
+               CLK(EPCI),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_29},
+       { CLK(PERIPH),  CLK(MEMORY),    CLK(DISPLAY),   CLK(AUDIO),
+               CLK(CGENERAL),  CLK(DISPLAY2),  CLK(OSC),       CLK(NONE),
+               MASK_BITS_31_29},
+       { CLK(PERIPH),  CLK(CGENERAL),  CLK(SFROM32KHZ),        CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_29_28}
+};
+
+/*
+ * Clock type for each peripheral clock source. We put the name in each
+ * record just so it is easy to match things up
+ */
+#define TYPE(name, type) type
+static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {
+       /* 0x00 */
+       TYPE(PERIPHC_I2S1,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_I2S2,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_SPDIF_IN,  CLOCK_TYPE_PCM),
+       TYPE(PERIPHC_PWM,       CLOCK_TYPE_PCST),  /* only PWM uses b29:28 */
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SBC2,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_SBC3,      CLOCK_TYPE_PCMT),
+
+       /* 0x08 */
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_I2C1,      CLOCK_TYPE_PCMT16),
+       TYPE(PERIPHC_I2C5,      CLOCK_TYPE_PCMT16),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SBC1,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_DISP1,     CLOCK_TYPE_PMDACD2T),
+       TYPE(PERIPHC_DISP2,     CLOCK_TYPE_PMDACD2T),
+
+       /* 0x10 */
+       TYPE(PERIPHC_CVE,       CLOCK_TYPE_PDCT),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_VI,        CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SDMMC1,    CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_SDMMC2,    CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_G3D,       CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_G2D,       CLOCK_TYPE_MCPA),
+
+       /* 0x18 */
+       TYPE(PERIPHC_NDFLASH,   CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_SDMMC4,    CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_VFIR,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_EPP,       CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_MPE,       CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_MIPI,      CLOCK_TYPE_PCMT),       /* MIPI base-band HSI */
+       TYPE(PERIPHC_UART1,     CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_UART2,     CLOCK_TYPE_PCMT),
+
+       /* 0x20 */
+       TYPE(PERIPHC_HOST1X,    CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_TVO,       CLOCK_TYPE_PDCT),
+       TYPE(PERIPHC_HDMI,      CLOCK_TYPE_PMDACD2T),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_TVDAC,     CLOCK_TYPE_PDCT),
+       TYPE(PERIPHC_I2C2,      CLOCK_TYPE_PCMT16),
+       TYPE(PERIPHC_EMC,       CLOCK_TYPE_MCPT),
+
+       /* 0x28 */
+       TYPE(PERIPHC_UART3,     CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_VI,        CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SBC4,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_I2C3,      CLOCK_TYPE_PCMT16),
+       TYPE(PERIPHC_SDMMC3,    CLOCK_TYPE_PCMT),
+
+       /* 0x30 */
+       TYPE(PERIPHC_UART4,     CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_UART5,     CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_VDE,       CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_OWR,       CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_NOR,       CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_CSITE,     CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_I2S0,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+
+       /* 0x38h */  /* Jumps to reg offset 0x3B0h */
+       TYPE(PERIPHC_G3D2,      CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_MSELECT,   CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_TSENSOR,   CLOCK_TYPE_PCST),       /* s/b PCTS */
+       TYPE(PERIPHC_I2S3,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_I2S4,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_I2C4,      CLOCK_TYPE_PCMT16),
+       TYPE(PERIPHC_SBC5,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_SBC6,      CLOCK_TYPE_PCMT),
+
+       /* 0x40 */
+       TYPE(PERIPHC_AUDIO,     CLOCK_TYPE_ACPT),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_DAM0,      CLOCK_TYPE_ACPT),
+       TYPE(PERIPHC_DAM1,      CLOCK_TYPE_ACPT),
+       TYPE(PERIPHC_DAM2,      CLOCK_TYPE_ACPT),
+       TYPE(PERIPHC_HDA2CODEC2X, CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_ACTMON,    CLOCK_TYPE_PCST),       /* MASK 31:30 */
+       TYPE(PERIPHC_EXTPERIPH1, CLOCK_TYPE_ASPTE),
+
+       /* 0x48 */
+       TYPE(PERIPHC_EXTPERIPH2, CLOCK_TYPE_ASPTE),
+       TYPE(PERIPHC_EXTPERIPH3, CLOCK_TYPE_ASPTE),
+       TYPE(PERIPHC_NANDSPEED, CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_I2CSLOW,   CLOCK_TYPE_PCST),       /* MASK 31:30 */
+       TYPE(PERIPHC_SYS,       CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SPEEDO,    CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+
+       /* 0x50 */
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SATAOOB,   CLOCK_TYPE_PCMT),       /* offset 0x420h */
+       TYPE(PERIPHC_SATA,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_HDA,       CLOCK_TYPE_PCMT),
+};
+
+/*
+ * This array translates a periph_id to a periphc_internal_id
+ *
+ * Not present/matched up:
+ *     uint vi_sensor;  _VI_SENSOR_0,          0x1A8
+ *     SPDIF - which is both 0x08 and 0x0c
+ *
+ */
+#define NONE(name) (-1)
+#define OFFSET(name, value) PERIPHC_ ## name
+static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
+       /* Low word: 31:0 */
+       NONE(CPU),
+       NONE(COP),
+       NONE(TRIGSYS),
+       NONE(RESERVED3),
+       NONE(RTC),
+       NONE(TMR),
+       PERIPHC_UART1,
+       PERIPHC_UART2,  /* and vfir 0x68 */
+
+       /* 8 */
+       NONE(GPIO),
+       PERIPHC_SDMMC2,
+       NONE(SPDIF),            /* 0x08 and 0x0c, unclear which to use */
+       PERIPHC_I2S1,
+       PERIPHC_I2C1,
+       PERIPHC_NDFLASH,
+       PERIPHC_SDMMC1,
+       PERIPHC_SDMMC4,
+
+       /* 16 */
+       NONE(RESERVED16),
+       PERIPHC_PWM,
+       PERIPHC_I2S2,
+       PERIPHC_EPP,
+       PERIPHC_VI,
+       PERIPHC_G2D,
+       NONE(USBD),
+       NONE(ISP),
+
+       /* 24 */
+       PERIPHC_G3D,
+       NONE(RESERVED25),
+       PERIPHC_DISP2,
+       PERIPHC_DISP1,
+       PERIPHC_HOST1X,
+       NONE(VCP),
+       PERIPHC_I2S0,
+       NONE(CACHE2),
+
+       /* Middle word: 63:32 */
+       NONE(MEM),
+       NONE(AHBDMA),
+       NONE(APBDMA),
+       NONE(RESERVED35),
+       NONE(RESERVED36),
+       NONE(STAT_MON),
+       NONE(RESERVED38),
+       NONE(RESERVED39),
+
+       /* 40 */
+       NONE(KFUSE),
+       NONE(SBC1),     /* SBC1, 0x34, is this SPI1? */
+       PERIPHC_NOR,
+       NONE(RESERVED43),
+       PERIPHC_SBC2,
+       NONE(RESERVED45),
+       PERIPHC_SBC3,
+       PERIPHC_I2C5,
+
+       /* 48 */
+       NONE(DSI),
+       PERIPHC_TVO,    /* also CVE 0x40 */
+       PERIPHC_MIPI,
+       PERIPHC_HDMI,
+       NONE(CSI),
+       PERIPHC_TVDAC,
+       PERIPHC_I2C2,
+       PERIPHC_UART3,
+
+       /* 56 */
+       NONE(RESERVED56),
+       PERIPHC_EMC,
+       NONE(USB2),
+       NONE(USB3),
+       PERIPHC_MPE,
+       PERIPHC_VDE,
+       NONE(BSEA),
+       NONE(BSEV),
+
+       /* Upper word 95:64 */
+       PERIPHC_SPEEDO,
+       PERIPHC_UART4,
+       PERIPHC_UART5,
+       PERIPHC_I2C3,
+       PERIPHC_SBC4,
+       PERIPHC_SDMMC3,
+       NONE(PCIE),
+       PERIPHC_OWR,
+
+       /* 72 */
+       NONE(AFI),
+       PERIPHC_CSITE,
+       NONE(PCIEXCLK),
+       NONE(AVPUCQ),
+       NONE(RESERVED76),
+       NONE(RESERVED77),
+       NONE(RESERVED78),
+       NONE(DTV),
+
+       /* 80 */
+       PERIPHC_NANDSPEED,
+       PERIPHC_I2CSLOW,
+       NONE(DSIB),
+       NONE(RESERVED83),
+       NONE(IRAMA),
+       NONE(IRAMB),
+       NONE(IRAMC),
+       NONE(IRAMD),
+
+       /* 88 */
+       NONE(CRAM2),
+       NONE(RESERVED89),
+       NONE(MDOUBLER),
+       NONE(RESERVED91),
+       NONE(SUSOUT),
+       NONE(RESERVED93),
+       NONE(RESERVED94),
+       NONE(RESERVED95),
+
+       /* V word: 31:0 */
+       NONE(CPUG),
+       NONE(CPULP),
+       PERIPHC_G3D2,
+       PERIPHC_MSELECT,
+       PERIPHC_TSENSOR,
+       PERIPHC_I2S3,
+       PERIPHC_I2S4,
+       PERIPHC_I2C4,
+
+       /* 08 */
+       PERIPHC_SBC5,
+       PERIPHC_SBC6,
+       PERIPHC_AUDIO,
+       NONE(APBIF),
+       PERIPHC_DAM0,
+       PERIPHC_DAM1,
+       PERIPHC_DAM2,
+       PERIPHC_HDA2CODEC2X,
+
+       /* 16 */
+       NONE(ATOMICS),
+       NONE(RESERVED17),
+       NONE(RESERVED18),
+       NONE(RESERVED19),
+       NONE(RESERVED20),
+       NONE(RESERVED21),
+       NONE(RESERVED22),
+       PERIPHC_ACTMON,
+
+       /* 24 */
+       NONE(RESERVED24),
+       NONE(RESERVED25),
+       NONE(RESERVED26),
+       NONE(RESERVED27),
+       PERIPHC_SATA,
+       PERIPHC_HDA,
+       NONE(RESERVED30),
+       NONE(RESERVED31),
+
+       /* W word: 31:0 */
+       NONE(HDA2HDMICODEC),
+       NONE(RESERVED1_SATACOLD),
+       NONE(RESERVED2_PCIERX0),
+       NONE(RESERVED3_PCIERX1),
+       NONE(RESERVED4_PCIERX2),
+       NONE(RESERVED5_PCIERX3),
+       NONE(RESERVED6_PCIERX4),
+       NONE(RESERVED7_PCIERX5),
+
+       /* 40 */
+       NONE(CEC),
+       NONE(PCIE2_IOBIST),
+       NONE(EMC_IOBIST),
+       NONE(HDMI_IOBIST),
+       NONE(SATA_IOBIST),
+       NONE(MIPI_IOBIST),
+       NONE(EMC1_IOBIST),
+       NONE(XUSB),
+
+       /* 48 */
+       NONE(CILAB),
+       NONE(CILCD),
+       NONE(CILE),
+       NONE(DSIA_LP),
+       NONE(DSIB_LP),
+       NONE(RESERVED21_ENTROPY),
+       NONE(RESERVED22_W),
+       NONE(RESERVED23_W),
+
+       /* 56 */
+       NONE(RESERVED24_W),
+       NONE(AMX0),
+       NONE(ADX0),
+       NONE(DVFS),
+       NONE(XUSB_SS),
+       NONE(EMC_DLL),
+       NONE(MC1),
+       NONE(EMC1),
+};
+
+/*
+ * Get the oscillator frequency, from the corresponding hardware configuration
+ * field. Note that T30/T114 support 3 new higher freqs, but we map back
+ * to the old T20 freqs. Support for the higher oscillators is TBD.
+ */
+enum clock_osc_freq clock_get_osc_freq(void)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 reg;
+
+       reg = readl(&clkrst->crc_osc_ctrl);
+       reg = (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
+
+       if (reg & 1)                            /* one of the newer freqs */
+               printf("Warning: OSC_FREQ is unsupported! (%d)\n", reg);
+
+       return reg >> 2;        /* Map to most common (T20) freqs */
+}
+
+/* Returns a pointer to the clock source register for a peripheral */
+u32 *get_periph_source_reg(enum periph_id periph_id)
+{
+       struct clk_rst_ctlr *clkrst =
+               (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       enum periphc_internal_id internal_id;
+
+       /* Coresight is a special case */
+       if (periph_id == PERIPH_ID_CSI)
+               return &clkrst->crc_clk_src[PERIPH_ID_CSI+1];
+
+       assert(periph_id >= PERIPH_ID_FIRST && periph_id < PERIPH_ID_COUNT);
+       internal_id = periph_id_to_internal_id[periph_id];
+       assert(internal_id != -1);
+       if (internal_id >= PERIPHC_VW_FIRST) {
+               internal_id -= PERIPHC_VW_FIRST;
+               return &clkrst->crc_clk_src_vw[internal_id];
+       } else
+               return &clkrst->crc_clk_src[internal_id];
+}
+
+/**
+ * Given a peripheral ID and the required source clock, this returns which
+ * value should be programmed into the source mux for that peripheral.
+ *
+ * There is special code here to handle the one source type with 5 sources.
+ *
+ * @param periph_id    peripheral to start
+ * @param source       PLL id of required parent clock
+ * @param mux_bits     Set to number of bits in mux register: 2 or 4
+ * @param divider_bits Set to number of divider bits (8 or 16)
+ * @return mux value (0-4, or -1 if not found)
+ */
+int get_periph_clock_source(enum periph_id periph_id,
+       enum clock_id parent, int *mux_bits, int *divider_bits)
+{
+       enum clock_type_id type;
+       enum periphc_internal_id internal_id;
+       int mux;
+
+       assert(clock_periph_id_isvalid(periph_id));
+
+       internal_id = periph_id_to_internal_id[periph_id];
+       assert(periphc_internal_id_isvalid(internal_id));
+
+       type = clock_periph_type[internal_id];
+       assert(clock_type_id_isvalid(type));
+
+       *mux_bits = clock_source[type][CLOCK_MAX_MUX];
+
+       if (type == CLOCK_TYPE_PCMT16)
+               *divider_bits = 16;
+       else
+               *divider_bits = 8;
+
+       for (mux = 0; mux < CLOCK_MAX_MUX; mux++)
+               if (clock_source[type][mux] == parent)
+                       return mux;
+
+       /* if we get here, either us or the caller has made a mistake */
+       printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id,
+               parent);
+       return -1;
+}
+
+void clock_set_enable(enum periph_id periph_id, int enable)
+{
+       struct clk_rst_ctlr *clkrst =
+               (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 *clk;
+       u32 reg;
+
+       /* Enable/disable the clock to this peripheral */
+       assert(clock_periph_id_isvalid(periph_id));
+       if ((int)periph_id < (int)PERIPH_ID_VW_FIRST)
+               clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)];
+       else
+               clk = &clkrst->crc_clk_out_enb_vw[PERIPH_REG(periph_id)];
+       reg = readl(clk);
+       if (enable)
+               reg |= PERIPH_MASK(periph_id);
+       else
+               reg &= ~PERIPH_MASK(periph_id);
+       writel(reg, clk);
+}
+
+void reset_set_enable(enum periph_id periph_id, int enable)
+{
+       struct clk_rst_ctlr *clkrst =
+               (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 *reset;
+       u32 reg;
+
+       /* Enable/disable reset to the peripheral */
+       assert(clock_periph_id_isvalid(periph_id));
+       if (periph_id < PERIPH_ID_VW_FIRST)
+               reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)];
+       else
+               reset = &clkrst->crc_rst_dev_vw[PERIPH_REG(periph_id)];
+       reg = readl(reset);
+       if (enable)
+               reg |= PERIPH_MASK(periph_id);
+       else
+               reg &= ~PERIPH_MASK(periph_id);
+       writel(reg, reset);
+}
+
+#ifdef CONFIG_OF_CONTROL
+/*
+ * Convert a device tree clock ID to our peripheral ID. They are mostly
+ * the same but we are very cautious so we check that a valid clock ID is
+ * provided.
+ *
+ * @param clk_id    Clock ID according to tegra114 device tree binding
+ * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
+ */
+enum periph_id clk_id_to_periph_id(int clk_id)
+{
+       if (clk_id > PERIPH_ID_COUNT)
+               return PERIPH_ID_NONE;
+
+       switch (clk_id) {
+       case PERIPH_ID_RESERVED3:
+       case PERIPH_ID_RESERVED16:
+       case PERIPH_ID_RESERVED24:
+       case PERIPH_ID_RESERVED35:
+       case PERIPH_ID_RESERVED43:
+       case PERIPH_ID_RESERVED45:
+       case PERIPH_ID_RESERVED56:
+       case PERIPH_ID_RESERVED76:
+       case PERIPH_ID_RESERVED77:
+       case PERIPH_ID_RESERVED78:
+       case PERIPH_ID_RESERVED83:
+       case PERIPH_ID_RESERVED89:
+       case PERIPH_ID_RESERVED91:
+       case PERIPH_ID_RESERVED93:
+       case PERIPH_ID_RESERVED94:
+       case PERIPH_ID_RESERVED95:
+               return PERIPH_ID_NONE;
+       default:
+               return clk_id;
+       }
+}
+#endif /* CONFIG_OF_CONTROL */
+
+void clock_early_init(void)
+{
+       struct clk_rst_ctlr *clkrst =
+               (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+
+       /*
+        * PLLP output frequency set to 408Mhz
+        * PLLC output frequency set to 600Mhz
+        * PLLD output frequency set to 925Mhz
+        */
+       switch (clock_get_osc_freq()) {
+       case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
+               clock_set_rate(CLOCK_ID_PERIPH, 408, 12, 0, 8);
+               clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8);
+               clock_set_rate(CLOCK_ID_DISPLAY, 925, 12, 0, 12);
+               break;
+
+       case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
+               clock_set_rate(CLOCK_ID_PERIPH, 408, 26, 0, 8);
+               clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
+               clock_set_rate(CLOCK_ID_DISPLAY, 925, 26, 0, 12);
+               break;
+
+       case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */
+               clock_set_rate(CLOCK_ID_PERIPH, 408, 13, 0, 8);
+               clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8);
+               clock_set_rate(CLOCK_ID_DISPLAY, 925, 13, 0, 12);
+               break;
+       case CLOCK_OSC_FREQ_19_2:
+       default:
+               /*
+                * These are not supported. It is too early to print a
+                * message and the UART likely won't work anyway due to the
+                * oscillator being wrong.
+                */
+               break;
+       }
+
+       /* PLLC_MISC2: Set dynramp_stepA/B. MISC2 maps to pll_out[1] */
+       writel(0x00561600, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_out[1]);
+
+       /* PLLC_MISC: Set LOCK_ENABLE */
+       writel(0x01000000, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc);
+       udelay(2);
+
+       /* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1 */
+       writel(0x40000C10, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc);
+       udelay(2);
+}
diff --git a/arch/arm/cpu/tegra114-common/funcmux.c b/arch/arm/cpu/tegra114-common/funcmux.c
new file mode 100644 (file)
index 0000000..5af7550
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/>.
+ */
+
+/* Tegra114 high-level function multiplexing */
+
+#include <common.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/funcmux.h>
+#include <asm/arch/pinmux.h>
+
+int funcmux_select(enum periph_id id, int config)
+{
+       int bad_config = config != FUNCMUX_DEFAULT;
+
+       switch (id) {
+       case PERIPH_ID_UART4:
+               switch (config) {
+               case FUNCMUX_UART4_GMI:
+                       pinmux_set_func(PINGRP_GMI_A16, PMUX_FUNC_UARTD);
+                       pinmux_set_func(PINGRP_GMI_A17, PMUX_FUNC_UARTD);
+                       pinmux_set_func(PINGRP_GMI_A18, PMUX_FUNC_UARTD);
+                       pinmux_set_func(PINGRP_GMI_A19, PMUX_FUNC_UARTD);
+
+                       pinmux_set_io(PINGRP_GMI_A16, PMUX_PIN_OUTPUT);
+                       pinmux_set_io(PINGRP_GMI_A17, PMUX_PIN_INPUT);
+                       pinmux_set_io(PINGRP_GMI_A18, PMUX_PIN_INPUT);
+                       pinmux_set_io(PINGRP_GMI_A19, PMUX_PIN_OUTPUT);
+
+                       pinmux_tristate_disable(PINGRP_GMI_A16);
+                       pinmux_tristate_disable(PINGRP_GMI_A17);
+                       pinmux_tristate_disable(PINGRP_GMI_A18);
+                       pinmux_tristate_disable(PINGRP_GMI_A19);
+                       break;
+               }
+               break;
+
+       /* Add other periph IDs here as needed */
+
+       default:
+               debug("%s: invalid periph_id %d", __func__, id);
+               return -1;
+       }
+
+       if (bad_config) {
+               debug("%s: invalid config %d for periph_id %d", __func__,
+                     config, id);
+               return -1;
+       }
+       return 0;
+}
diff --git a/arch/arm/cpu/tegra114-common/pinmux.c b/arch/arm/cpu/tegra114-common/pinmux.c
new file mode 100644 (file)
index 0000000..52b3ec4
--- /dev/null
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/>.
+ */
+
+/* Tegra114 pin multiplexing functions */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/tegra.h>
+#include <asm/arch/pinmux.h>
+
+struct tegra_pingroup_desc {
+       const char *name;
+       enum pmux_func funcs[4];
+       enum pmux_func func_safe;
+       enum pmux_vddio vddio;
+       enum pmux_pin_io io;
+};
+
+#define PMUX_MUXCTL_SHIFT      0
+#define PMUX_PULL_SHIFT                2
+#define PMUX_TRISTATE_SHIFT    4
+#define PMUX_TRISTATE_MASK     (1 << PMUX_TRISTATE_SHIFT)
+#define PMUX_IO_SHIFT          5
+#define PMUX_OD_SHIFT          6
+#define PMUX_LOCK_SHIFT                7
+#define PMUX_IO_RESET_SHIFT    8
+
+/* Convenient macro for defining pin group properties */
+#define PIN(pg_name, vdd, f0, f1, f2, f3, iod) \
+       {                                               \
+               .vddio = PMUX_VDDIO_ ## vdd,            \
+               .funcs = {                              \
+                       PMUX_FUNC_ ## f0,               \
+                       PMUX_FUNC_ ## f1,               \
+                       PMUX_FUNC_ ## f2,               \
+                       PMUX_FUNC_ ## f3,               \
+               },                                      \
+               .func_safe = PMUX_FUNC_RSVD1,           \
+               .io = PMUX_PIN_ ## iod,                 \
+       }
+
+/* Input and output pins */
+#define PINI(pg_name, vdd, f0, f1, f2, f3) \
+       PIN(pg_name, vdd, f0, f1, f2, f3, INPUT)
+#define PINO(pg_name, vdd, f0, f1, f2, f3) \
+       PIN(pg_name, vdd, f0, f1, f2, f3, OUTPUT)
+
+const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = {
+       /*      NAME      VDD      f0           f1         f2       f3  */
+       PINI(ULPI_DATA0,  BB,      SPI3,       HSI,        UARTA,   ULPI),
+       PINI(ULPI_DATA1,  BB,      SPI3,       HSI,        UARTA,   ULPI),
+       PINI(ULPI_DATA2,  BB,      SPI3,       HSI,        UARTA,   ULPI),
+       PINI(ULPI_DATA3,  BB,      SPI3,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_DATA4,  BB,      SPI2,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_DATA5,  BB,      SPI2,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_DATA6,  BB,      SPI2,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_DATA7,  BB,      SPI2,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_CLK,    BB,      SPI1,       SPI5,       UARTD,   ULPI),
+       PINI(ULPI_DIR,    BB,      SPI1,       SPI5,       UARTD,   ULPI),
+       PINI(ULPI_NXT,    BB,      SPI1,       SPI5,       UARTD,   ULPI),
+       PINI(ULPI_STP,    BB,      SPI1,       SPI5,       UARTD,   ULPI),
+       PINI(DAP3_FS,     BB,      I2S2,       SPI5,       DISPA,   DISPB),
+       PINI(DAP3_DIN,    BB,      I2S2,       SPI5,       DISPA,   DISPB),
+       PINI(DAP3_DOUT,   BB,      I2S2,       SPI5,       DISPA,   DISPB),
+       PINI(DAP3_SCLK,   BB,      I2S2,       SPI5,       DISPA,   DISPB),
+       PINI(GPIO_PV0,    BB,      USB,        RSVD2,      RSVD3,   RSVD4),
+       PINI(GPIO_PV1,    BB,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(SDMMC1_CLK,  SDMMC1,  SDMMC1,     CLK12,      RSVD3,   RSVD4),
+       PINI(SDMMC1_CMD,  SDMMC1,  SDMMC1,     SPDIF,      SPI4,    UARTA),
+       PINI(SDMMC1_DAT3, SDMMC1,  SDMMC1,     SPDIF,      SPI4,    UARTA),
+       PINI(SDMMC1_DAT2, SDMMC1,  SDMMC1,     PWM0,       SPI4,    UARTA),
+       PINI(SDMMC1_DAT1, SDMMC1,  SDMMC1,     PWM1,       SPI4,    UARTA),
+       PINI(SDMMC1_DAT0, SDMMC1,  SDMMC1,     RSVD2,      SPI4,    UARTA),
+       PINI(GPIO_PV2,    BB,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(GPIO_PV3,    BB,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(CLK2_OUT,    SDMMC1,  EXTPERIPH2, RSVD2,      RSVD3,   RSVD4),
+       PINI(CLK2_REQ,    SDMMC1,  DAP,        RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_PWR1,    LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_PWR2,    LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_SDIN,    LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_SDOUT,   LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_WR_N,    LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_CS0_N,   LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_DC0,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_SCK,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_PWR0,    LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_PCLK,    LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_DE,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_HSYNC,   LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_VSYNC,   LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D0,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D1,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D2,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D3,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D4,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D5,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D6,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D7,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D8,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D9,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D10,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D11,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D12,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D13,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D14,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D15,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D16,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D17,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D18,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D19,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D20,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D21,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D22,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_D23,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_CS1_N,   LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_M1,      LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINO(LCD_DC1,     LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(HDMI_INT,    LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(DDC_SCL,     LCD,     I2C4,       RSVD2,      RSVD3,   RSVD4),
+       PINI(DDC_SDA,     LCD,     I2C4,       RSVD2,      RSVD3,   RSVD4),
+       PINI(CRT_HSYNC,   LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(CRT_VSYNC,   LCD,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D0,       VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D1,       VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D2,       VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D3,       VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D4,       VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D5,       VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D6,       VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D7,       VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D8,       VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D9,       VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D10,      VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_D11,      VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_PCLK,     VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_MCLK,     VI,      RSVD1,      RSVD3,      RSVD3,   RSVD4),
+       PINI(VI_VSYNC,    VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(VI_HSYNC,    VI,      RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(UART2_RXD,   UART,    UARTB,      SPDIF,      UARTA,   SPI4),
+       PINI(UART2_TXD,   UART,    UARTB,      SPDIF,      UARTA,   SPI4),
+       PINI(UART2_RTS_N, UART,    UARTA,      UARTB,      RSVD3,   SPI4),
+       PINI(UART2_CTS_N, UART,    UARTA,      UARTB,      RSVD3,   SPI4),
+       PINI(UART3_TXD,   UART,    UARTC,      RSVD2,      RSVD3,   SPI4),
+       PINI(UART3_RXD,   UART,    UARTC,      RSVD2,      RSVD3,   SPI4),
+       PINI(UART3_CTS_N, UART,    UARTC,      SDMMC1,     DTV,     SPI4),
+       PINI(UART3_RTS_N, UART,    UARTC,      PWM0,       DTV,     DISPA),
+       PINI(GPIO_PU0,    UART,    OWR,        UARTA,      RSVD3,   RSVD4),
+       PINI(GPIO_PU1,    UART,    RSVD1,      UARTA,      RSVD3,   RSVD4),
+       PINI(GPIO_PU2,    UART,    RSVD1,      UARTA,      RSVD3,   RSVD4),
+       PINI(GPIO_PU3,    UART,    PWM0,       UARTA,      DISPA,   DISPB),
+       PINI(GPIO_PU4,    UART,    PWM1,       UARTA,      DISPA,   DISPB),
+       PINI(GPIO_PU5,    UART,    PWM2,       UARTA,      DISPA,   DISPB),
+       PINI(GPIO_PU6,    UART,    PWM3,       UARTA,      USB,     DISPB),
+       PINI(GEN1_I2C_SDA, UART,   I2C1,       RSVD2,      RSVD3,   RSVD4),
+       PINI(GEN1_I2C_SCL, UART,   I2C1,       RSVD2,      RSVD3,   RSVD4),
+       PINI(DAP4_FS,     UART,    I2S3,       RSVD2,      DTV,     RSVD4),
+       PINI(DAP4_DIN,    UART,    I2S3,       RSVD2,      RSVD3,   RSVD4),
+       PINI(DAP4_DOUT,   UART,    I2S3,       RSVD2,      DTV,     RSVD4),
+       PINI(DAP4_SCLK,   UART,    I2S3,       RSVD2,      RSVD3,   RSVD4),
+       PINI(CLK3_OUT,    UART,    EXTPERIPH3, RSVD2,      RSVD3,   RSVD4),
+       PINI(CLK3_REQ,    UART,    DEV3,       RSVD2,      RSVD3,   RSVD4),
+       PINI(GMI_WP_N,    GMI,     RSVD1,      NAND,       GMI,     GMI_ALT),
+       PINI(GMI_IORDY,   GMI,     SDMMC2,     RSVD2,      GMI,     TRACE),
+       PINI(GMI_WAIT,    GMI,     SPI4,       NAND,       GMI,     DTV),
+       PINI(GMI_ADV_N,   GMI,     RSVD1,      NAND,       GMI,     TRACE),
+       PINI(GMI_CLK,     GMI,     SDMMC2,     NAND,       GMI,     TRACE),
+       PINI(GMI_CS0_N,   GMI,     RSVD1,      NAND,       GMI,     USB),
+       PINI(GMI_CS1_N,   GMI,     RSVD1,      NAND,       GMI,     SOC),
+       PINI(GMI_CS2_N,   GMI,     SDMMC2,     NAND,       GMI,     TRACE),
+       PINI(GMI_CS3_N,   GMI,     SDMMC2,     NAND,       GMI,     GMI_ALT),
+       PINI(GMI_CS4_N,   GMI,     USB,        NAND,       GMI,     TRACE),
+       PINI(GMI_CS6_N,   GMI,     NAND,       NAND_ALT,   GMI,     SPI4),
+       PINI(GMI_CS7_N,   GMI,     NAND,       NAND_ALT,   GMI,     SDMMC2),
+       PINI(GMI_AD0,     GMI,     RSVD1,      NAND,       GMI,     RSVD4),
+       PINI(GMI_AD1,     GMI,     RSVD1,      NAND,       GMI,     RSVD4),
+       PINI(GMI_AD2,     GMI,     RSVD1,      NAND,       GMI,     RSVD4),
+       PINI(GMI_AD3,     GMI,     RSVD1,      NAND,       GMI,     RSVD4),
+       PINI(GMI_AD4,     GMI,     RSVD1,      NAND,       GMI,     RSVD4),
+       PINI(GMI_AD5,     GMI,     RSVD1,      NAND,       GMI,     SPI4),
+       PINI(GMI_AD6,     GMI,     RSVD1,      NAND,       GMI,     SPI4),
+       PINI(GMI_AD7,     GMI,     RSVD1,      NAND,       GMI,     SPI4),
+       PINI(GMI_AD8,     GMI,     PWM0,       NAND,       GMI,     DTV),
+       PINI(GMI_AD9,     GMI,     PWM1,       NAND,       GMI,     CLDVFS),
+       PINI(GMI_AD10,    GMI,     PWM2,       NAND,       GMI,     CLDVFS),
+       PINI(GMI_AD11,    GMI,     PWM3,       NAND,       GMI,     USB),
+       PINI(GMI_AD12,    GMI,     SDMMC2,     NAND,       GMI,     RSVD4),
+       PINI(GMI_AD13,    GMI,     SDMMC2,     NAND,       GMI,     RSVD4),
+       PINI(GMI_AD14,    GMI,     SDMMC2,     NAND,       GMI,     DTV),
+       PINI(GMI_AD15,    GMI,     SDMMC2,     NAND,       GMI,     DTV),
+       PINI(GMI_A16,     GMI,     UARTD,      TRACE,      GMI,     GMI_ALT),
+       PINI(GMI_A17,     GMI,     UARTD,      RSVD2,      GMI,     TRACE),
+       PINI(GMI_A18,     GMI,     UARTD,      RSVD2,      GMI,     TRACE),
+       PINI(GMI_A19,     GMI,     UARTD,      SPI4,       GMI,     TRACE),
+       PINI(GMI_WR_N,    GMI,     RSVD1,      NAND,       GMI,     SPI4),
+       PINI(GMI_OE_N,    GMI,     RSVD1,      NAND,       GMI,     SOC),
+       PINI(GMI_DQS,     GMI,     SDMMC2,     NAND,       GMI,     TRACE),
+       PINI(GMI_RST_N,   GMI,     NAND,       NAND_ALT,   GMI,     RSVD4),
+       PINI(GEN2_I2C_SCL, GMI,    I2C2,       RSVD2,      GMI,     RSVD4),
+       PINI(GEN2_I2C_SDA, GMI,    I2C2,       RSVD2,      GMI,     RSVD4),
+       PINI(SDMMC4_CLK,  SDMMC4,  SDMMC4,     RSVD2,      GMI,     RSVD4),
+       PINI(SDMMC4_CMD,  SDMMC4,  SDMMC4,     RSVD2,      GMI,     RSVD4),
+       PINI(SDMMC4_DAT0, SDMMC4,  SDMMC4,     SPI3,       GMI,     RSVD4),
+       PINI(SDMMC4_DAT1, SDMMC4,  SDMMC4,     SPI3,       GMI,     RSVD4),
+       PINI(SDMMC4_DAT2, SDMMC4,  SDMMC4,     SPI3,       GMI,     RSVD4),
+       PINI(SDMMC4_DAT3, SDMMC4,  SDMMC4,     SPI3,       GMI,     RSVD4),
+       PINI(SDMMC4_DAT4, SDMMC4,  SDMMC4,     SPI3,       GMI,     RSVD4),
+       PINI(SDMMC4_DAT5, SDMMC4,  SDMMC4,     SPI3,       GMI,     RSVD4),
+       PINI(SDMMC4_DAT6, SDMMC4,  SDMMC4,     SPI3,       GMI,     RSVD4),
+       PINI(SDMMC4_DAT7, SDMMC4,  SDMMC4,     RSVD2,      GMI,     RSVD4),
+       PINI(SDMMC4_RST_N, SDMMC4, RSVD1,      RSVD2,      RSVD3,   SDMMC4),
+       PINI(CAM_MCLK,    CAM,     VI,         VI_ALT1,    VI_ALT2, RSVD4),
+       PINI(GPIO_PCC1,   CAM,     I2S4,       RSVD2,      RSVD3,   RSVD4),
+       PINI(GPIO_PBB0,   CAM,     I2S4,       VI,         VI_ALT1, VI_ALT3),
+       PINI(CAM_I2C_SCL, CAM,     VGP1,       I2C3,       RSVD3,   RSVD4),
+       PINI(CAM_I2C_SDA, CAM,     VGP2,       I2C3,       RSVD3,   RSVD4),
+       PINI(GPIO_PBB3,   CAM,     VGP3,       DISPA,      DISPB,   RSVD4),
+       PINI(GPIO_PBB4,   CAM,     VGP4,       DISPA,      DISPB,   RSVD4),
+       PINI(GPIO_PBB5,   CAM,     VGP5,       DISPA,      DISPB,   RSVD4),
+       PINI(GPIO_PBB6,   CAM,     VGP6,       DISPA,      DISPB,   RSVD4),
+       PINI(GPIO_PBB7,   CAM,     I2S4,       RSVD2,      RSVD3,   RSVD4),
+       PINI(GPIO_PCC2,   CAM,     I2S4,       RSVD2,      RSVD3,   RSVD4),
+       PINI(JTAG_RTCK,   SYS,     RTCK,       RSVD2,      RSVD3,   RSVD4),
+       PINI(PWR_I2C_SCL, SYS,     I2CPWR,     RSVD2,      RSVD3,   RSVD4),
+       PINI(PWR_I2C_SDA, SYS,     I2CPWR,     RSVD2,      RSVD3,   RSVD4),
+       PINI(KB_ROW0,     SYS,     KBC,        RSVD2,      DTV,     RSVD4),
+       PINI(KB_ROW1,     SYS,     KBC,        RSVD2,      DTV,     RSVD4),
+       PINI(KB_ROW2,     SYS,     KBC,        RSVD2,      DTV,     SOC),
+       PINI(KB_ROW3,     SYS,     KBC,        DISPA,      RSVD3,   DISPB),
+       PINI(KB_ROW4,     SYS,     KBC,        DISPA,      SPI2,    DISPB),
+       PINI(KB_ROW5,     SYS,     KBC,        DISPA,      SPI2,    DISPB),
+       PINI(KB_ROW6,     SYS,     KBC,        DISPA,      RSVD3,   DISPB),
+       PINI(KB_ROW7,     SYS,     KBC,        RSVD2,      CLDVFS,  UARTA),
+       PINI(KB_ROW8,     SYS,     KBC,        RSVD2,      RSVD3,   UARTA),
+       PINI(KB_ROW9,     SYS,     KBC,        RSVD2,      RSVD3,   UARTA),
+       PINI(KB_ROW10,    SYS,     KBC,        RSVD2,      RSVD3,   UARTA),
+       PINI(KB_ROW11,    SYS,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(KB_ROW12,    SYS,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(KB_ROW13,    SYS,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(KB_ROW14,    SYS,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(KB_ROW15,    SYS,     RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(KB_COL0,     SYS,     KBC,        USB,        SPI2,    EMC_DLL),
+       PINI(KB_COL1,     SYS,     KBC,        RSVD2,      SPI2,    EMC_DLL),
+       PINI(KB_COL2,     SYS,     KBC,        RSVD2,      SPI2,    RSVD4),
+       PINI(KB_COL3,     SYS,     KBC,        DISPA,      PWM2,    UARTA),
+       PINI(KB_COL4,     SYS,     KBC,        OWR,        SDMMC3,  UARTA),
+       PINI(KB_COL5,     SYS,     KBC,        RSVD2,      SDMMC1,  RSVD4),
+       PINI(KB_COL6,     SYS,     KBC,        RSVD2,      SPI2,    RSVD4),
+       PINI(KB_COL7,     SYS,     KBC,        RSVD2,      SPI2,    RSVD4),
+       PINI(CLK_32K_OUT, SYS,     BLINK,      SOC,        RSVD3,   RSVD4),
+       PINI(SYS_CLK_REQ, SYS,     SYSCLK,     RSVD2,      RSVD3,   RSVD4),
+       PINI(CORE_PWR_REQ, SYS,    PWRON,      RSVD2,      RSVD3,   RSVD4),
+       PINI(CPU_PWR_REQ, SYS,     CPU,        RSVD2,      RSVD3,   RSVD4),
+       PINI(PWR_INT_N,   SYS,     PMI,        RSVD2,      RSVD3,   RSVD4),
+       PINI(CLK_32K_IN,  SYS,     CLK,        RSVD2,      RSVD3,   RSVD4),
+       PINI(OWR,         SYS,     OWR,        RSVD2,      RSVD3,   RSVD4),
+       PINI(DAP1_FS,     AUDIO,   I2S0,       HDA,        GMI,     RSVD4),
+       PINI(DAP1_DIN,    AUDIO,   I2S0,       HDA,        GMI,     RSVD4),
+       PINI(DAP1_DOUT,   AUDIO,   I2S0,       HDA,        GMI,     RSVD4),
+       PINI(DAP1_SCLK,   AUDIO,   I2S0,       HDA,        GMI,     RSVD4),
+       PINI(CLK1_REQ,    AUDIO,   DAP,        DAP1,       RSVD3,   RSVD4),
+       PINI(CLK1_OUT,    AUDIO,   EXTPERIPH1, DAP2,       RSVD3,   RSVD4),
+       PINI(SPDIF_IN,    AUDIO,   SPDIF,      USB,        RSVD3,   RSVD4),
+       PINI(SPDIF_OUT,   AUDIO,   SPDIF,      RSVD2,      RSVD3,   RSVD4),
+       PINI(DAP2_FS,     AUDIO,   I2S1,       HDA,        RSVD3,   RSVD4),
+       PINI(DAP2_DIN,    AUDIO,   I2S1,       HDA,        RSVD3,   RSVD4),
+       PINI(DAP2_DOUT,   AUDIO,   I2S1,       HDA,        RSVD3,   RSVD4),
+       PINI(DAP2_SCLK,   AUDIO,   I2S1,       HDA,        RSVD3,   RSVD4),
+       PINI(SPI2_MOSI,   AUDIO,   SPI6,       CLDVFS,     RSVD3,   RSVD4),
+       PINI(SPI2_MISO,   AUDIO,   SPI6,       RSVD2,      RSVD3,   RSVD4),
+       PINI(SPI2_CS0_N,  AUDIO,   SPI6,       SPI1,       RSVD3,   RSVD4),
+       PINI(SPI2_SCK,    AUDIO,   SPI6,       CLDVFS,     RSVD3,   RSVD4),
+       PINI(SPI1_MOSI,   AUDIO,   RSVD1,      SPI1,       SPI2,    DAP2),
+       PINI(SPI1_SCK,    AUDIO,   RSVD1,      SPI1,       SPI2,    RSVD4),
+       PINI(SPI1_CS0_N,  AUDIO,   SPI6,       SPI1,       SPI2,    RSVD4),
+       PINI(SPI1_MISO,   AUDIO,   RSVD1,      SPI1,       SPI2,    RSVD4),
+       PINI(SPI2_CS1_N,  AUDIO,   RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(SPI2_CS2_N,  AUDIO,   RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(SDMMC3_CLK,  SDMMC3,  SDMMC3,     RSVD2,      RSVD3,   SPI3),
+       PINI(SDMMC3_CMD,  SDMMC3,  SDMMC3,     PWM3,       UARTA,   SPI3),
+       PINI(SDMMC3_DAT0, SDMMC3,  SDMMC3,     RSVD2,      RSVD3,   SPI3),
+       PINI(SDMMC3_DAT1, SDMMC3,  SDMMC3,     PWM2,       UARTA,   SPI3),
+       PINI(SDMMC3_DAT2, SDMMC3,  SDMMC3,     PWM1,       DISPA,   SPI3),
+       PINI(SDMMC3_DAT3, SDMMC3,  SDMMC3,     PWM0,       DISPB,   SPI3),
+       PINI(SDMMC3_DAT4, SDMMC3,  RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(SDMMC3_DAT5, SDMMC3,  RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(SDMMC3_DAT6, SDMMC3,  RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(SDMMC3_DAT7, SDMMC3,  RSVD1,      RSVD2,      RSVD3,   RSVD4),
+       PINI(HDMI_CEC,    SYS,     CEC,        SDMMC3,     RSVD3,   SOC),
+       PINI(SDMMC1_WP_N, SDMMC1,  SDMMC1,     CLK12,      SPI4,    UARTA),
+       PINI(SDMMC3_CD_N, SDMMC3,  SDMMC3,     OWR,        RSVD3,   RSVD4),
+       PINI(SPI1_CS1_N,  AUDIO,   SPI6,       RSVD2,      SPI2,    I2C1),
+       PINI(SPI1_CS2_N,  AUDIO,   SPI6,       SPI1,       SPI2,    I2C1),
+       PINI(USB_VBUS_EN0, SYS,    USB,        RSVD2,      RSVD3,   RSVD4),
+       PINI(USB_VBUS_EN1, SYS,    USB,        RSVD2,      RSVD3,   RSVD4),
+       PINI(SDMMC3_CLK_LB_IN,  SDMMC3, SDMMC3, RSVD2,     RSVD3,   RSVD4),
+       PINO(SDMMC3_CLK_LB_OUT, SDMMC3, SDMMC3, RSVD2,     RSVD3,   RSVD4),
+       PINO(NAND_GMI_CLK_LB,   GMI,    SDMMC2, NAND,      GMI,     RSVD4),
+       PINO(RESET_OUT_N, SYS,     RSVD1,      RSVD2,      RSVD3, RESET_OUT_N),
+};
+
+void pinmux_set_tristate(enum pmux_pingrp pin, int enable)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *tri = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin */
+       assert(pmux_pingrp_isvalid(pin));
+
+       reg = readl(tri);
+       if (enable)
+               reg |= PMUX_TRISTATE_MASK;
+       else
+               reg &= ~PMUX_TRISTATE_MASK;
+       writel(reg, tri);
+}
+
+void pinmux_tristate_enable(enum pmux_pingrp pin)
+{
+       pinmux_set_tristate(pin, 1);
+}
+
+void pinmux_tristate_disable(enum pmux_pingrp pin)
+{
+       pinmux_set_tristate(pin, 0);
+}
+
+void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *pull = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin and pupd */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_pin_pupd_isvalid(pupd));
+
+       reg = readl(pull);
+       reg &= ~(0x3 << PMUX_PULL_SHIFT);
+       reg |= (pupd << PMUX_PULL_SHIFT);
+       writel(reg, pull);
+}
+
+void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *muxctl = &pmt->pmt_ctl[pin];
+       int i, mux = -1;
+       u32 reg;
+
+       /* Error check on pin and func */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_func_isvalid(func));
+
+       /* Handle special values */
+       if (func == PMUX_FUNC_SAFE)
+               func = tegra_soc_pingroups[pin].func_safe;
+
+       if (func & PMUX_FUNC_RSVD1) {
+               mux = func & 0x3;
+       } else {
+               /* Search for the appropriate function */
+               for (i = 0; i < 4; i++) {
+                       if (tegra_soc_pingroups[pin].funcs[i] == func) {
+                               mux = i;
+                               break;
+                       }
+               }
+       }
+       assert(mux != -1);
+
+       reg = readl(muxctl);
+       reg &= ~(0x3 << PMUX_MUXCTL_SHIFT);
+       reg |= (mux << PMUX_MUXCTL_SHIFT);
+       writel(reg, muxctl);
+
+}
+
+void pinmux_set_io(enum pmux_pingrp pin, enum pmux_pin_io io)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *pin_io = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin and io */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_pin_io_isvalid(io));
+
+       reg = readl(pin_io);
+       reg &= ~(0x1 << PMUX_IO_SHIFT);
+       reg |= (io & 0x1) << PMUX_IO_SHIFT;
+       writel(reg, pin_io);
+}
+
+static int pinmux_set_lock(enum pmux_pingrp pin, enum pmux_pin_lock lock)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *pin_lock = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin and lock */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_pin_lock_isvalid(lock));
+
+       if (lock == PMUX_PIN_LOCK_DEFAULT)
+               return 0;
+
+       reg = readl(pin_lock);
+       reg &= ~(0x1 << PMUX_LOCK_SHIFT);
+       if (lock == PMUX_PIN_LOCK_ENABLE)
+               reg |= (0x1 << PMUX_LOCK_SHIFT);
+       else {
+               /* lock == DISABLE, which isn't possible */
+               printf("%s: Warning: lock == %d, DISABLE is not allowed!\n",
+                       __func__, lock);
+       }
+       writel(reg, pin_lock);
+
+       return 0;
+}
+
+static int pinmux_set_od(enum pmux_pingrp pin, enum pmux_pin_od od)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *pin_od = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin and od */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_pin_od_isvalid(od));
+
+       if (od == PMUX_PIN_OD_DEFAULT)
+               return 0;
+
+       reg = readl(pin_od);
+       reg &= ~(0x1 << PMUX_OD_SHIFT);
+       if (od == PMUX_PIN_OD_ENABLE)
+               reg |= (0x1 << PMUX_OD_SHIFT);
+       writel(reg, pin_od);
+
+       return 0;
+}
+
+static int pinmux_set_ioreset(enum pmux_pingrp pin,
+                               enum pmux_pin_ioreset ioreset)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *pin_ioreset = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin and ioreset */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_pin_ioreset_isvalid(ioreset));
+
+       if (ioreset == PMUX_PIN_IO_RESET_DEFAULT)
+               return 0;
+
+       reg = readl(pin_ioreset);
+       reg &= ~(0x1 << PMUX_IO_RESET_SHIFT);
+       if (ioreset == PMUX_PIN_IO_RESET_ENABLE)
+               reg |= (0x1 << PMUX_IO_RESET_SHIFT);
+       writel(reg, pin_ioreset);
+
+       return 0;
+}
+
+void pinmux_config_pingroup(struct pingroup_config *config)
+{
+       enum pmux_pingrp pin = config->pingroup;
+
+       pinmux_set_func(pin, config->func);
+       pinmux_set_pullupdown(pin, config->pull);
+       pinmux_set_tristate(pin, config->tristate);
+       pinmux_set_io(pin, config->io);
+       pinmux_set_lock(pin, config->lock);
+       pinmux_set_od(pin, config->od);
+       pinmux_set_ioreset(pin, config->ioreset);
+}
+
+void pinmux_config_table(struct pingroup_config *config, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               pinmux_config_pingroup(&config[i]);
+}
index 12987a6893691f8646016ac1e242b71519a811da..ec93894f4868f470dabcb7ef66350a999f71d492 100644 (file)
 #include <div64.h>
 #include <fdtdec.h>
 
-/*
- * This is our record of the current clock rate of each clock. We don't
- * fill all of these in since we are only really interested in clocks which
- * we use as parents.
- */
-static unsigned pll_rate[CLOCK_ID_COUNT];
-
-/*
- * The oscillator frequency is fixed to one of four set values. Based on this
- * the other clocks are set up appropriately.
- */
-static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = {
-       13000000,
-       19200000,
-       12000000,
-       26000000,
-};
-
 /*
  * Clock types that we can use as a source. The Tegra20 has muxes for the
  * peripheral clocks, and in most cases there are four options for the clock
@@ -76,12 +58,6 @@ enum clock_type_id {
        CLOCK_TYPE_NONE = -1,   /* invalid clock type */
 };
 
-/* return 1 if a peripheral ID is in range */
-#define clock_type_id_isvalid(id) ((id) >= 0 && \
-               (id) < CLOCK_TYPE_COUNT)
-
-char pllp_valid = 1;   /* PLLP is set up correctly */
-
 enum {
        CLOCK_MAX_MUX   = 4     /* number of source options for each clock */
 };
@@ -192,10 +168,6 @@ enum periphc_internal_id {
        PERIPHC_NONE = -1,
 };
 
-/* return 1 if a periphc_internal_id is in range */
-#define periphc_internal_id_isvalid(id) ((id) >= 0 && \
-               (id) < PERIPHC_COUNT)
-
 /*
  * Clock type for each peripheral clock source. We put the name in each
  * record just so it is easy to match things up
@@ -396,19 +368,9 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
        NONE(CRAM2),
 };
 
-/* number of clock outputs of a PLL */
-static const u8 pll_num_clkouts[] = {
-       1,      /* PLLC */
-       1,      /* PLLM */
-       4,      /* PLLP */
-       1,      /* PLLA */
-       0,      /* PLLU */
-       0,      /* PLLD */
-};
-
 /*
  * Get the oscillator frequency, from the corresponding hardware configuration
- * field.
+ * field. T20 has 4 frequencies that it supports.
  */
 enum clock_osc_freq clock_get_osc_freq(void)
 {
@@ -420,110 +382,8 @@ enum clock_osc_freq clock_get_osc_freq(void)
        return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
 }
 
-int clock_get_osc_bypass(void)
-{
-       struct clk_rst_ctlr *clkrst =
-                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-       u32 reg;
-
-       reg = readl(&clkrst->crc_osc_ctrl);
-       return (reg & OSC_XOBP_MASK) >> OSC_XOBP_SHIFT;
-}
-
-/* Returns a pointer to the registers of the given pll */
-static struct clk_pll *get_pll(enum clock_id clkid)
-{
-       struct clk_rst_ctlr *clkrst =
-                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-
-       assert(clock_id_is_pll(clkid));
-       return &clkrst->crc_pll[clkid];
-}
-
-int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
-               u32 *divp, u32 *cpcon, u32 *lfcon)
-{
-       struct clk_pll *pll = get_pll(clkid);
-       u32 data;
-
-       assert(clkid != CLOCK_ID_USB);
-
-       /* Safety check, adds to code size but is small */
-       if (!clock_id_is_pll(clkid) || clkid == CLOCK_ID_USB)
-               return -1;
-       data = readl(&pll->pll_base);
-       *divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
-       *divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT;
-       *divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
-       data = readl(&pll->pll_misc);
-       *cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT;
-       *lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT;
-
-       return 0;
-}
-
-unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
-               u32 divp, u32 cpcon, u32 lfcon)
-{
-       struct clk_pll *pll = get_pll(clkid);
-       u32 data;
-
-       /*
-        * We cheat by treating all PLL (except PLLU) in the same fashion.
-        * This works only because:
-        * - same fields are always mapped at same offsets, except DCCON
-        * - DCCON is always 0, doesn't conflict
-        * - M,N, P of PLLP values are ignored for PLLP
-        */
-       data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT);
-       writel(data, &pll->pll_misc);
-
-       data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) |
-                       (0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT);
-
-       if (clkid == CLOCK_ID_USB)
-               data |= divp << PLLU_VCO_FREQ_SHIFT;
-       else
-               data |= divp << PLL_DIVP_SHIFT;
-       writel(data, &pll->pll_base);
-
-       /* calculate the stable time */
-       return timer_get_us() + CLOCK_PLL_STABLE_DELAY_US;
-}
-
-/* return 1 if a peripheral ID is in range and valid */
-static int clock_periph_id_isvalid(enum periph_id id)
-{
-       if (id < PERIPH_ID_FIRST || id >= PERIPH_ID_COUNT)
-               printf("Peripheral id %d out of range\n", id);
-       else {
-               switch (id) {
-               case PERIPH_ID_RESERVED1:
-               case PERIPH_ID_RESERVED2:
-               case PERIPH_ID_RESERVED30:
-               case PERIPH_ID_RESERVED35:
-               case PERIPH_ID_RESERVED56:
-               case PERIPH_ID_RESERVED74:
-               case PERIPH_ID_RESERVED76:
-               case PERIPH_ID_RESERVED77:
-               case PERIPH_ID_RESERVED78:
-               case PERIPH_ID_RESERVED79:
-               case PERIPH_ID_RESERVED80:
-               case PERIPH_ID_RESERVED81:
-               case PERIPH_ID_RESERVED82:
-               case PERIPH_ID_RESERVED83:
-               case PERIPH_ID_RESERVED91:
-                       printf("Peripheral id %d is reserved\n", id);
-                       break;
-               default:
-                       return 1;
-               }
-       }
-       return 0;
-}
-
 /* Returns a pointer to the clock source register for a peripheral */
-static u32 *get_periph_source_reg(enum periph_id periph_id)
+u32 *get_periph_source_reg(enum periph_id periph_id)
 {
        struct clk_rst_ctlr *clkrst =
                        (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
@@ -535,154 +395,6 @@ static u32 *get_periph_source_reg(enum periph_id periph_id)
        return &clkrst->crc_clk_src[internal_id];
 }
 
-void clock_ll_set_source_divisor(enum periph_id periph_id, unsigned source,
-                             unsigned divisor)
-{
-       u32 *reg = get_periph_source_reg(periph_id);
-       u32 value;
-
-       value = readl(reg);
-
-       value &= ~OUT_CLK_SOURCE_MASK;
-       value |= source << OUT_CLK_SOURCE_SHIFT;
-
-       value &= ~OUT_CLK_DIVISOR_MASK;
-       value |= divisor << OUT_CLK_DIVISOR_SHIFT;
-
-       writel(value, reg);
-}
-
-void clock_ll_set_source(enum periph_id periph_id, unsigned source)
-{
-       u32 *reg = get_periph_source_reg(periph_id);
-
-       clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
-                       source << OUT_CLK_SOURCE_SHIFT);
-}
-
-/**
- * Given the parent's rate and the required rate for the children, this works
- * out the peripheral clock divider to use, in 7.1 binary format.
- *
- * @param divider_bits number of divider bits (8 or 16)
- * @param parent_rate  clock rate of parent clock in Hz
- * @param rate         required clock rate for this clock
- * @return divider which should be used
- */
-static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate,
-                          unsigned long rate)
-{
-       u64 divider = parent_rate * 2;
-       unsigned max_divider = 1 << divider_bits;
-
-       divider += rate - 1;
-       do_div(divider, rate);
-
-       if ((s64)divider - 2 < 0)
-               return 0;
-
-       if ((s64)divider - 2 >= max_divider)
-               return -1;
-
-       return divider - 2;
-}
-
-/**
- * Given the parent's rate and the divider in 7.1 format, this works out the
- * resulting peripheral clock rate.
- *
- * @param parent_rate  clock rate of parent clock in Hz
- * @param divider which should be used in 7.1 format
- * @return effective clock rate of peripheral
- */
-static unsigned long get_rate_from_divider(unsigned long parent_rate,
-                                          int divider)
-{
-       u64 rate;
-
-       rate = (u64)parent_rate * 2;
-       do_div(rate, divider + 2);
-       return rate;
-}
-
-unsigned long clock_get_periph_rate(enum periph_id periph_id,
-               enum clock_id parent)
-{
-       u32 *reg = get_periph_source_reg(periph_id);
-
-       return get_rate_from_divider(pll_rate[parent],
-               (readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT);
-}
-
-int clock_set_pllout(enum clock_id clkid, enum pll_out_id pllout, unsigned rate)
-{
-       struct clk_pll *pll = get_pll(clkid);
-       int data = 0, div = 0, offset = 0;
-
-       if (!clock_id_is_pll(clkid))
-               return -1;
-
-       if (pllout + 1 > pll_num_clkouts[clkid])
-               return -1;
-
-       div = clk_get_divider(8, pll_rate[clkid], rate);
-
-       if (div < 0)
-               return -1;
-
-       /* out2 and out4 are in the high part of the register */
-       if (pllout == PLL_OUT2 || pllout == PLL_OUT4)
-               offset = 16;
-
-       data = (div << PLL_OUT_RATIO_SHIFT) |
-                       PLL_OUT_OVRRIDE | PLL_OUT_CLKEN | PLL_OUT_RSTN;
-       clrsetbits_le32(&pll->pll_out[pllout >> 1],
-                       PLL_OUT_RATIO_MASK << offset, data << offset);
-
-       return 0;
-}
-
-/**
- * Find the best available 7.1 format divisor given a parent clock rate and
- * required child clock rate. This function assumes that a second-stage
- * divisor is available which can divide by powers of 2 from 1 to 256.
- *
- * @param divider_bits number of divider bits (8 or 16)
- * @param parent_rate  clock rate of parent clock in Hz
- * @param rate         required clock rate for this clock
- * @param extra_div    value for the second-stage divisor (not set if this
- *                     function returns -1.
- * @return divider which should be used, or -1 if nothing is valid
- *
- */
-static int find_best_divider(unsigned divider_bits, unsigned long parent_rate,
-                            unsigned long rate, int *extra_div)
-{
-       int shift;
-       int best_divider = -1;
-       int best_error = rate;
-
-       /* try dividers from 1 to 256 and find closest match */
-       for (shift = 0; shift <= 8 && best_error > 0; shift++) {
-               unsigned divided_parent = parent_rate >> shift;
-               int divider = clk_get_divider(divider_bits, divided_parent,
-                                             rate);
-               unsigned effective_rate = get_rate_from_divider(divided_parent,
-                                                      divider);
-               int error = rate - effective_rate;
-
-               /* Given a valid divider, look for the lowest error */
-               if (divider != -1 && error < best_error) {
-                       best_error = error;
-                       *extra_div = 1 << shift;
-                       best_divider = divider;
-               }
-       }
-
-       /* return what we found - *extra_div will already be set */
-       return best_divider;
-}
-
 /**
  * Given a peripheral ID and the required source clock, this returns which
  * value should be programmed into the source mux for that peripheral.
@@ -695,7 +407,7 @@ static int find_best_divider(unsigned divider_bits, unsigned long parent_rate,
  * @param divider_bits Set to number of divider bits (8 or 16)
  * @return mux value (0-4, or -1 if not found)
  */
-static int get_periph_clock_source(enum periph_id periph_id,
+int get_periph_clock_source(enum periph_id periph_id,
                enum clock_id parent, int *mux_bits, int *divider_bits)
 {
        enum clock_type_id type;
@@ -743,88 +455,6 @@ static int get_periph_clock_source(enum periph_id periph_id,
        return -1;
 }
 
-/**
- * Adjust peripheral PLL to use the given divider and source.
- *
- * @param periph_id    peripheral to adjust
- * @param source       Source number (0-3 or 0-7)
- * @param mux_bits     Number of mux bits (2 or 4)
- * @param divider      Required divider in 7.1 or 15.1 format
- * @return 0 if ok, -1 on error (requesting a parent clock which is not valid
- *             for this peripheral)
- */
-static int adjust_periph_pll(enum periph_id periph_id, int source,
-                            int mux_bits, unsigned divider)
-{
-       u32 *reg = get_periph_source_reg(periph_id);
-
-       clrsetbits_le32(reg, OUT_CLK_DIVISOR_MASK,
-                       divider << OUT_CLK_DIVISOR_SHIFT);
-       udelay(1);
-
-       /* work out the source clock and set it */
-       if (source < 0)
-               return -1;
-       if (mux_bits == 4) {
-               clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
-                       source << OUT_CLK_SOURCE4_SHIFT);
-       } else {
-               clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
-                       source << OUT_CLK_SOURCE_SHIFT);
-       }
-       udelay(2);
-       return 0;
-}
-
-unsigned clock_adjust_periph_pll_div(enum periph_id periph_id,
-               enum clock_id parent, unsigned rate, int *extra_div)
-{
-       unsigned effective_rate;
-       int mux_bits, divider_bits, source;
-       int divider;
-
-       /* work out the source clock and set it */
-       source = get_periph_clock_source(periph_id, parent, &mux_bits,
-                                        &divider_bits);
-
-       if (extra_div)
-               divider = find_best_divider(divider_bits, pll_rate[parent],
-                                           rate, extra_div);
-       else
-               divider = clk_get_divider(divider_bits, pll_rate[parent],
-                                         rate);
-       assert(divider >= 0);
-       if (adjust_periph_pll(periph_id, source, mux_bits, divider))
-               return -1U;
-       debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate,
-               get_periph_source_reg(periph_id),
-               readl(get_periph_source_reg(periph_id)));
-
-       /* Check what we ended up with. This shouldn't matter though */
-       effective_rate = clock_get_periph_rate(periph_id, parent);
-       if (extra_div)
-               effective_rate /= *extra_div;
-       if (rate != effective_rate)
-               debug("Requested clock rate %u not honored (got %u)\n",
-                      rate, effective_rate);
-       return effective_rate;
-}
-
-unsigned clock_start_periph_pll(enum periph_id periph_id,
-               enum clock_id parent, unsigned rate)
-{
-       unsigned effective_rate;
-
-       reset_set_enable(periph_id, 1);
-       clock_enable(periph_id);
-
-       effective_rate = clock_adjust_periph_pll_div(periph_id, parent, rate,
-                                                NULL);
-
-       reset_set_enable(periph_id, 0);
-       return effective_rate;
-}
-
 void clock_set_enable(enum periph_id periph_id, int enable)
 {
        struct clk_rst_ctlr *clkrst =
@@ -842,16 +472,6 @@ void clock_set_enable(enum periph_id periph_id, int enable)
        writel(reg, clk);
 }
 
-void clock_enable(enum periph_id clkid)
-{
-       clock_set_enable(clkid, 1);
-}
-
-void clock_disable(enum periph_id clkid)
-{
-       clock_set_enable(clkid, 0);
-}
-
 void reset_set_enable(enum periph_id periph_id, int enable)
 {
        struct clk_rst_ctlr *clkrst =
@@ -869,146 +489,6 @@ void reset_set_enable(enum periph_id periph_id, int enable)
        writel(reg, reset);
 }
 
-void reset_periph(enum periph_id periph_id, int us_delay)
-{
-       /* Put peripheral into reset */
-       reset_set_enable(periph_id, 1);
-       udelay(us_delay);
-
-       /* Remove reset */
-       reset_set_enable(periph_id, 0);
-
-       udelay(us_delay);
-}
-
-void reset_cmplx_set_enable(int cpu, int which, int reset)
-{
-       struct clk_rst_ctlr *clkrst =
-                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
-       u32 mask;
-
-       /* Form the mask, which depends on the cpu chosen. Tegra20 has 2 */
-       assert(cpu >= 0 && cpu < 2);
-       mask = which << cpu;
-
-       /* either enable or disable those reset for that CPU */
-       if (reset)
-               writel(mask, &clkrst->crc_cpu_cmplx_set);
-       else
-               writel(mask, &clkrst->crc_cpu_cmplx_clr);
-}
-
-unsigned clock_get_rate(enum clock_id clkid)
-{
-       struct clk_pll *pll;
-       u32 base;
-       u32 divm;
-       u64 parent_rate;
-       u64 rate;
-
-       parent_rate = osc_freq[clock_get_osc_freq()];
-       if (clkid == CLOCK_ID_OSC)
-               return parent_rate;
-
-       pll = get_pll(clkid);
-       base = readl(&pll->pll_base);
-
-       /* Oh for bf_unpack()... */
-       rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT);
-       divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
-       if (clkid == CLOCK_ID_USB)
-               divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT;
-       else
-               divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
-       do_div(rate, divm);
-       return rate;
-}
-
-/**
- * Set the output frequency you want for each PLL clock.
- * PLL output frequencies are programmed by setting their N, M and P values.
- * The governing equations are:
- *     VCO = (Fi / m) * n, Fo = VCO / (2^p)
- *     where Fo is the output frequency from the PLL.
- * Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi)
- *     216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1
- * Please see Tegra TRM section 5.3 to get the detail for PLL Programming
- *
- * @param n PLL feedback divider(DIVN)
- * @param m PLL input divider(DIVN)
- * @param p post divider(DIVP)
- * @param cpcon base PLL charge pump(CPCON)
- * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot
- *             be overriden), 1 if PLL is already correct
- */
-static int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon)
-{
-       u32 base_reg;
-       u32 misc_reg;
-       struct clk_pll *pll;
-
-       pll = get_pll(clkid);
-
-       base_reg = readl(&pll->pll_base);
-
-       /* Set BYPASS, m, n and p to PLL_BASE */
-       base_reg &= ~PLL_DIVM_MASK;
-       base_reg |= m << PLL_DIVM_SHIFT;
-
-       base_reg &= ~PLL_DIVN_MASK;
-       base_reg |= n << PLL_DIVN_SHIFT;
-
-       base_reg &= ~PLL_DIVP_MASK;
-       base_reg |= p << PLL_DIVP_SHIFT;
-
-       if (clkid == CLOCK_ID_PERIPH) {
-               /*
-                * If the PLL is already set up, check that it is correct
-                * and record this info for clock_verify() to check.
-                */
-               if (base_reg & PLL_BASE_OVRRIDE_MASK) {
-                       base_reg |= PLL_ENABLE_MASK;
-                       if (base_reg != readl(&pll->pll_base))
-                               pllp_valid = 0;
-                       return pllp_valid ? 1 : -1;
-               }
-               base_reg |= PLL_BASE_OVRRIDE_MASK;
-       }
-
-       base_reg |= PLL_BYPASS_MASK;
-       writel(base_reg, &pll->pll_base);
-
-       /* Set cpcon to PLL_MISC */
-       misc_reg = readl(&pll->pll_misc);
-       misc_reg &= ~PLL_CPCON_MASK;
-       misc_reg |= cpcon << PLL_CPCON_SHIFT;
-       writel(misc_reg, &pll->pll_misc);
-
-       /* Enable PLL */
-       base_reg |= PLL_ENABLE_MASK;
-       writel(base_reg, &pll->pll_base);
-
-       /* Disable BYPASS */
-       base_reg &= ~PLL_BYPASS_MASK;
-       writel(base_reg, &pll->pll_base);
-
-       return 0;
-}
-
-void clock_ll_start_uart(enum periph_id periph_id)
-{
-       /* Assert UART reset and enable clock */
-       reset_set_enable(periph_id, 1);
-       clock_enable(periph_id);
-       clock_ll_set_source(periph_id, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */
-
-       /* wait for 2us */
-       udelay(2);
-
-       /* De-assert reset to UART */
-       reset_set_enable(periph_id, 0);
-}
-
 #ifdef CONFIG_OF_CONTROL
 /*
  * Convert a device tree clock ID to our peripheral ID. They are mostly
@@ -1018,67 +498,34 @@ void clock_ll_start_uart(enum periph_id periph_id)
  * @param clk_id       Clock ID according to tegra20 device tree binding
  * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
  */
-static enum periph_id clk_id_to_periph_id(int clk_id)
+enum periph_id clk_id_to_periph_id(int clk_id)
 {
-       if (clk_id > 95)
+       if (clk_id > PERIPH_ID_COUNT)
                return PERIPH_ID_NONE;
 
        switch (clk_id) {
-       case 1:
-       case 2:
-       case 7:
-       case 10:
-       case 20:
-       case 30:
-       case 35:
-       case 49:
-       case 56:
-       case 74:
-       case 76:
-       case 77:
-       case 78:
-       case 79:
-       case 80:
-       case 81:
-       case 82:
-       case 83:
-       case 91:
-       case 95:
+       case PERIPH_ID_RESERVED1:
+       case PERIPH_ID_RESERVED2:
+       case PERIPH_ID_RESERVED30:
+       case PERIPH_ID_RESERVED35:
+       case PERIPH_ID_RESERVED56:
+       case PERIPH_ID_RESERVED74:
+       case PERIPH_ID_RESERVED76:
+       case PERIPH_ID_RESERVED77:
+       case PERIPH_ID_RESERVED78:
+       case PERIPH_ID_RESERVED79:
+       case PERIPH_ID_RESERVED80:
+       case PERIPH_ID_RESERVED81:
+       case PERIPH_ID_RESERVED82:
+       case PERIPH_ID_RESERVED83:
+       case PERIPH_ID_RESERVED91:
                return PERIPH_ID_NONE;
        default:
                return clk_id;
        }
 }
-
-int clock_decode_periph_id(const void *blob, int node)
-{
-       enum periph_id id;
-       u32 cell[2];
-       int err;
-
-       err = fdtdec_get_int_array(blob, node, "clocks", cell,
-                                  ARRAY_SIZE(cell));
-       if (err)
-               return -1;
-       id = clk_id_to_periph_id(cell[1]);
-       assert(clock_periph_id_isvalid(id));
-       return id;
-}
 #endif /* CONFIG_OF_CONTROL */
 
-int clock_verify(void)
-{
-       struct clk_pll *pll = get_pll(CLOCK_ID_PERIPH);
-       u32 reg = readl(&pll->pll_base);
-
-       if (!pllp_valid) {
-               printf("Warning: PLLP %x is not correct\n", reg);
-               return -1;
-       }
-       debug("PLLX %x is correct\n", reg);
-       return 0;
-}
-
 void clock_early_init(void)
 {
        /*
@@ -1112,15 +559,3 @@ void clock_early_init(void)
                break;
        }
 }
-
-void clock_init(void)
-{
-       pll_rate[CLOCK_ID_MEMORY] = clock_get_rate(CLOCK_ID_MEMORY);
-       pll_rate[CLOCK_ID_PERIPH] = clock_get_rate(CLOCK_ID_PERIPH);
-       pll_rate[CLOCK_ID_CGENERAL] = clock_get_rate(CLOCK_ID_CGENERAL);
-       pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC);
-       pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
-       debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]);
-       debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
-       debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);
-}
index ece7ad9ec954333a9bc9a85769adc97d82b2fe08..80a9bd9e28463edf774a783387769371ff341f15 100644 (file)
@@ -98,8 +98,8 @@ int funcmux_select(enum periph_id id, int config)
                break;
 
        case PERIPH_ID_UART2:
-               if (config == FUNCMUX_UART2_IRDA) {
-                       pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA);
+               if (config == FUNCMUX_UART2_UAD) {
+                       pinmux_set_func(PINGRP_UAD, PMUX_FUNC_UARTB);
                        pinmux_tristate_disable(PINGRP_UAD);
                }
                break;
index a2a09169e54bc46acbdc0b2bc5f89478a775b2be..5ad2121c5d08753759064c04385696d95c7a156e 100644 (file)
@@ -390,7 +390,7 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = {
        PIN(UAA,  BB,    SPI3,   MIPI_HS, UARTA,    ULPI,        MIPI_HS),
        PIN(UAB,  BB,    SPI2,   MIPI_HS, UARTA,    ULPI,        MIPI_HS),
        PIN(UAC,  BB,    OWR,    RSVD,   RSVD,      RSVD,        RSVD4),
-       PIN(UAD,  UART,  IRDA,   SPDIF,  UARTA,     SPI4,        SPDIF),
+       PIN(UAD,  UART,  UARTB,  SPDIF,  UARTA,     SPI4,        SPDIF),
        PIN(UCA,  UART,  UARTC,  RSVD,   GMI,       RSVD,        RSVD4),
        PIN(UCB,  UART,  UARTC,  PWM,    GMI,       RSVD,        RSVD4),
 
index 157b9abc4597b1fbaebb788dc2732e35dbfee3ef..0d472cfe33c7f1ae246071f200531117b1b495a7 100644 (file)
@@ -46,7 +46,7 @@ DECLARE_GLOBAL_DATA_PTR;
  * This is the place in SRAM where the SDRAM parameters are stored. There
  * are 4 blocks, one for each RAM code
  */
-#define SDRAM_PARAMS_BASE      (AP20_BASE_PA_SRAM + 0x188)
+#define SDRAM_PARAMS_BASE      (NV_PA_BASE_SRAM + 0x188)
 
 /* TODO: If we later add support for the Misc GP controller, refactor this */
 union xm2cfga_reg {
diff --git a/arch/arm/cpu/tegra30-common/Makefile b/arch/arm/cpu/tegra30-common/Makefile
new file mode 100644 (file)
index 0000000..75fef32
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope 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 $(TOPDIR)/config.mk
+
+# The AVP is ARMv4T architecture so we must use special compiler
+# flags for any startup files it might use.
+
+LIB    = $(obj)lib$(SOC)-common.o
+
+COBJS-y        += clock.o funcmux.o pinmux.o
+
+SRCS   := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
+
+all:   $(obj).depend $(LIB)
+
+$(LIB):        $(OBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/tegra30-common/clock.c b/arch/arm/cpu/tegra30-common/clock.c
new file mode 100644 (file)
index 0000000..a93f2c9
--- /dev/null
@@ -0,0 +1,618 @@
+/*
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/>.
+ */
+
+/* Tegra30 Clock control functions */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/timer.h>
+#include <div64.h>
+#include <fdtdec.h>
+
+/*
+ * Clock types that we can use as a source. The Tegra30 has muxes for the
+ * peripheral clocks, and in most cases there are four options for the clock
+ * source. This gives us a clock 'type' and exploits what commonality exists
+ * in the device.
+ *
+ * Letters are obvious, except for T which means CLK_M, and S which means the
+ * clock derived from 32KHz. Beware that CLK_M (also called OSC in the
+ * datasheet) and PLL_M are different things. The former is the basic
+ * clock supplied to the SOC from an external oscillator. The latter is the
+ * memory clock PLL.
+ *
+ * See definitions in clock_id in the header file.
+ */
+enum clock_type_id {
+       CLOCK_TYPE_AXPT,        /* PLL_A, PLL_X, PLL_P, CLK_M */
+       CLOCK_TYPE_MCPA,        /* and so on */
+       CLOCK_TYPE_MCPT,
+       CLOCK_TYPE_PCM,
+       CLOCK_TYPE_PCMT,
+       CLOCK_TYPE_PCMT16,
+       CLOCK_TYPE_PDCT,
+       CLOCK_TYPE_ACPT,
+       CLOCK_TYPE_ASPTE,
+       CLOCK_TYPE_PMDACD2T,
+       CLOCK_TYPE_PCST,
+
+       CLOCK_TYPE_COUNT,
+       CLOCK_TYPE_NONE = -1,   /* invalid clock type */
+};
+
+enum {
+       CLOCK_MAX_MUX   = 8     /* number of source options for each clock */
+};
+
+enum {
+       MASK_BITS_31_30 = 2,    /* num of bits used to specify clock source */
+       MASK_BITS_31_29,
+       MASK_BITS_29_28,
+};
+
+/*
+ * Clock source mux for each clock type. This just converts our enum into
+ * a list of mux sources for use by the code.
+ *
+ * Note:
+ *  The extra column in each clock source array is used to store the mask
+ *  bits in its register for the source.
+ */
+#define CLK(x) CLOCK_ID_ ## x
+static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX+1] = {
+       { CLK(AUDIO),   CLK(XCPU),      CLK(PERIPH),    CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(MEMORY),  CLK(CGENERAL),  CLK(PERIPH),    CLK(AUDIO),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(MEMORY),  CLK(CGENERAL),  CLK(PERIPH),    CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),    CLK(NONE),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),    CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(PERIPH),  CLK(CGENERAL),  CLK(MEMORY),    CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(PERIPH),  CLK(DISPLAY),   CLK(CGENERAL),  CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(AUDIO),   CLK(CGENERAL),  CLK(PERIPH),    CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_30},
+       { CLK(AUDIO),   CLK(SFROM32KHZ),        CLK(PERIPH),   CLK(OSC),
+               CLK(EPCI),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_31_29},
+       { CLK(PERIPH),  CLK(MEMORY),    CLK(DISPLAY),   CLK(AUDIO),
+               CLK(CGENERAL),  CLK(DISPLAY2),  CLK(OSC),       CLK(NONE),
+               MASK_BITS_31_29},
+       { CLK(PERIPH),  CLK(CGENERAL),  CLK(SFROM32KHZ), CLK(OSC),
+               CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
+               MASK_BITS_29_28}
+};
+
+/*
+ * Clock type for each peripheral clock source. We put the name in each
+ * record just so it is easy to match things up
+ */
+#define TYPE(name, type) type
+static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {
+       /* 0x00 */
+       TYPE(PERIPHC_I2S1,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_I2S2,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_SPDIF_IN,  CLOCK_TYPE_PCM),
+       TYPE(PERIPHC_PWM,       CLOCK_TYPE_PCST),  /* only PWM uses b29:28 */
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SBC2,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_SBC3,      CLOCK_TYPE_PCMT),
+
+       /* 0x08 */
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_I2C1,      CLOCK_TYPE_PCMT16),
+       TYPE(PERIPHC_DVC_I2C,   CLOCK_TYPE_PCMT16),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SBC1,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_DISP1,     CLOCK_TYPE_PMDACD2T),
+       TYPE(PERIPHC_DISP2,     CLOCK_TYPE_PMDACD2T),
+
+       /* 0x10 */
+       TYPE(PERIPHC_CVE,       CLOCK_TYPE_PDCT),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_VI,        CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SDMMC1,    CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_SDMMC2,    CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_G3D,       CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_G2D,       CLOCK_TYPE_MCPA),
+
+       /* 0x18 */
+       TYPE(PERIPHC_NDFLASH,   CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_SDMMC4,    CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_VFIR,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_EPP,       CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_MPE,       CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_MIPI,      CLOCK_TYPE_PCMT),       /* MIPI base-band HSI */
+       TYPE(PERIPHC_UART1,     CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_UART2,     CLOCK_TYPE_PCMT),
+
+       /* 0x20 */
+       TYPE(PERIPHC_HOST1X,    CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_TVO,       CLOCK_TYPE_PDCT),
+       TYPE(PERIPHC_HDMI,      CLOCK_TYPE_PMDACD2T),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_TVDAC,     CLOCK_TYPE_PDCT),
+       TYPE(PERIPHC_I2C2,      CLOCK_TYPE_PCMT16),
+       TYPE(PERIPHC_EMC,       CLOCK_TYPE_MCPT),
+
+       /* 0x28 */
+       TYPE(PERIPHC_UART3,     CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_VI,        CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SBC4,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_I2C3,      CLOCK_TYPE_PCMT16),
+       TYPE(PERIPHC_SDMMC3,    CLOCK_TYPE_PCMT),
+
+       /* 0x30 */
+       TYPE(PERIPHC_UART4,     CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_UART5,     CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_VDE,       CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_OWR,       CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_NOR,       CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_CSITE,     CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_I2S0,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+
+       /* 0x38h */          /* Jumps to reg offset 0x3B0h - new for T30 */
+       TYPE(PERIPHC_G3D2,      CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_MSELECT,   CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_TSENSOR,   CLOCK_TYPE_PCST),       /* s/b PCTS */
+       TYPE(PERIPHC_I2S3,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_I2S4,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_I2C4,      CLOCK_TYPE_PCMT16),
+       TYPE(PERIPHC_SBC5,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_SBC6,      CLOCK_TYPE_PCMT),
+
+       /* 0x40 */
+       TYPE(PERIPHC_AUDIO,     CLOCK_TYPE_ACPT),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_DAM0,      CLOCK_TYPE_ACPT),
+       TYPE(PERIPHC_DAM1,      CLOCK_TYPE_ACPT),
+       TYPE(PERIPHC_DAM2,      CLOCK_TYPE_ACPT),
+       TYPE(PERIPHC_HDA2CODEC2X, CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_ACTMON,    CLOCK_TYPE_PCST),       /* MASK 31:30 */
+       TYPE(PERIPHC_EXTPERIPH1, CLOCK_TYPE_ASPTE),
+
+       /* 0x48 */
+       TYPE(PERIPHC_EXTPERIPH2, CLOCK_TYPE_ASPTE),
+       TYPE(PERIPHC_EXTPERIPH3, CLOCK_TYPE_ASPTE),
+       TYPE(PERIPHC_NANDSPEED, CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_I2CSLOW,   CLOCK_TYPE_PCST),       /* MASK 31:30 */
+       TYPE(PERIPHC_SYS,       CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SPEEDO,    CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+
+       /* 0x50 */
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_NONE,      CLOCK_TYPE_NONE),
+       TYPE(PERIPHC_SATAOOB,   CLOCK_TYPE_PCMT),       /* offset 0x420h */
+       TYPE(PERIPHC_SATA,      CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_HDA,       CLOCK_TYPE_PCMT),
+};
+
+/*
+ * This array translates a periph_id to a periphc_internal_id
+ *
+ * Not present/matched up:
+ *     uint vi_sensor;  _VI_SENSOR_0,          0x1A8
+ *     SPDIF - which is both 0x08 and 0x0c
+ *
+ */
+#define NONE(name) (-1)
+#define OFFSET(name, value) PERIPHC_ ## name
+static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
+       /* Low word: 31:0 */
+       NONE(CPU),
+       NONE(COP),
+       NONE(TRIGSYS),
+       NONE(RESERVED3),
+       NONE(RESERVED4),
+       NONE(TMR),
+       PERIPHC_UART1,
+       PERIPHC_UART2,  /* and vfir 0x68 */
+
+       /* 8 */
+       NONE(GPIO),
+       PERIPHC_SDMMC2,
+       NONE(SPDIF),        /* 0x08 and 0x0c, unclear which to use */
+       PERIPHC_I2S1,
+       PERIPHC_I2C1,
+       PERIPHC_NDFLASH,
+       PERIPHC_SDMMC1,
+       PERIPHC_SDMMC4,
+
+       /* 16 */
+       NONE(RESERVED16),
+       PERIPHC_PWM,
+       PERIPHC_I2S2,
+       PERIPHC_EPP,
+       PERIPHC_VI,
+       PERIPHC_G2D,
+       NONE(USBD),
+       NONE(ISP),
+
+       /* 24 */
+       PERIPHC_G3D,
+       NONE(RESERVED25),
+       PERIPHC_DISP2,
+       PERIPHC_DISP1,
+       PERIPHC_HOST1X,
+       NONE(VCP),
+       PERIPHC_I2S0,
+       NONE(CACHE2),
+
+       /* Middle word: 63:32 */
+       NONE(MEM),
+       NONE(AHBDMA),
+       NONE(APBDMA),
+       NONE(RESERVED35),
+       NONE(RESERVED36),
+       NONE(STAT_MON),
+       NONE(RESERVED38),
+       NONE(RESERVED39),
+
+       /* 40 */
+       NONE(KFUSE),
+       PERIPHC_SBC1,
+       PERIPHC_NOR,
+       NONE(RESERVED43),
+       PERIPHC_SBC2,
+       NONE(RESERVED45),
+       PERIPHC_SBC3,
+       PERIPHC_DVC_I2C,
+
+       /* 48 */
+       NONE(DSI),
+       PERIPHC_TVO,    /* also CVE 0x40 */
+       PERIPHC_MIPI,
+       PERIPHC_HDMI,
+       NONE(CSI),
+       PERIPHC_TVDAC,
+       PERIPHC_I2C2,
+       PERIPHC_UART3,
+
+       /* 56 */
+       NONE(RESERVED56),
+       PERIPHC_EMC,
+       NONE(USB2),
+       NONE(USB3),
+       PERIPHC_MPE,
+       PERIPHC_VDE,
+       NONE(BSEA),
+       NONE(BSEV),
+
+       /* Upper word 95:64 */
+       PERIPHC_SPEEDO,
+       PERIPHC_UART4,
+       PERIPHC_UART5,
+       PERIPHC_I2C3,
+       PERIPHC_SBC4,
+       PERIPHC_SDMMC3,
+       NONE(PCIE),
+       PERIPHC_OWR,
+
+       /* 72 */
+       NONE(AFI),
+       PERIPHC_CSITE,
+       NONE(PCIEXCLK),
+       NONE(AVPUCQ),
+       NONE(RESERVED76),
+       NONE(RESERVED77),
+       NONE(RESERVED78),
+       NONE(DTV),
+
+       /* 80 */
+       PERIPHC_NANDSPEED,
+       PERIPHC_I2CSLOW,
+       NONE(DSIB),
+       NONE(RESERVED83),
+       NONE(IRAMA),
+       NONE(IRAMB),
+       NONE(IRAMC),
+       NONE(IRAMD),
+
+       /* 88 */
+       NONE(CRAM2),
+       NONE(RESERVED89),
+       NONE(MDOUBLER),
+       NONE(RESERVED91),
+       NONE(SUSOUT),
+       NONE(RESERVED93),
+       NONE(RESERVED94),
+       NONE(RESERVED95),
+
+       /* V word: 31:0 */
+       NONE(CPUG),
+       NONE(CPULP),
+       PERIPHC_G3D2,
+       PERIPHC_MSELECT,
+       PERIPHC_TSENSOR,
+       PERIPHC_I2S3,
+       PERIPHC_I2S4,
+       PERIPHC_I2C4,
+
+       /* 08 */
+       PERIPHC_SBC5,
+       PERIPHC_SBC6,
+       PERIPHC_AUDIO,
+       NONE(APBIF),
+       PERIPHC_DAM0,
+       PERIPHC_DAM1,
+       PERIPHC_DAM2,
+       PERIPHC_HDA2CODEC2X,
+
+       /* 16 */
+       NONE(ATOMICS),
+       NONE(RESERVED17),
+       NONE(RESERVED18),
+       NONE(RESERVED19),
+       NONE(RESERVED20),
+       NONE(RESERVED21),
+       NONE(RESERVED22),
+       PERIPHC_ACTMON,
+
+       /* 24 */
+       NONE(RESERVED24),
+       NONE(RESERVED25),
+       NONE(RESERVED26),
+       NONE(RESERVED27),
+       PERIPHC_SATA,
+       PERIPHC_HDA,
+       NONE(RESERVED30),
+       NONE(RESERVED31),
+
+       /* W word: 31:0 */
+       NONE(HDA2HDMICODEC),
+       NONE(SATACOLD),
+       NONE(RESERVED0_PCIERX0),
+       NONE(RESERVED1_PCIERX1),
+       NONE(RESERVED2_PCIERX2),
+       NONE(RESERVED3_PCIERX3),
+       NONE(RESERVED4_PCIERX4),
+       NONE(RESERVED5_PCIERX5),
+
+       /* 40 */
+       NONE(CEC),
+       NONE(RESERVED6_PCIE2),
+       NONE(RESERVED7_EMC),
+       NONE(RESERVED8_HDMI),
+       NONE(RESERVED9_SATA),
+       NONE(RESERVED10_MIPI),
+       NONE(EX_RESERVED46),
+       NONE(EX_RESERVED47),
+};
+
+/*
+ * Get the oscillator frequency, from the corresponding hardware configuration
+ * field. Note that T30 supports 3 new higher freqs, but we map back
+ * to the old T20 freqs. Support for the higher oscillators is TBD.
+ */
+enum clock_osc_freq clock_get_osc_freq(void)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 reg;
+
+       reg = readl(&clkrst->crc_osc_ctrl);
+       reg = (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT;
+
+       if (reg & 1)                    /* one of the newer freqs */
+               printf("Warning: OSC_FREQ is unsupported! (%d)\n", reg);
+
+       return reg >> 2;        /* Map to most common (T20) freqs */
+}
+
+/* Returns a pointer to the clock source register for a peripheral */
+u32 *get_periph_source_reg(enum periph_id periph_id)
+{
+       struct clk_rst_ctlr *clkrst =
+               (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       enum periphc_internal_id internal_id;
+
+       /* Coresight is a special case */
+       if (periph_id == PERIPH_ID_CSI)
+               return &clkrst->crc_clk_src[PERIPH_ID_CSI+1];
+
+       assert(periph_id >= PERIPH_ID_FIRST && periph_id < PERIPH_ID_COUNT);
+       internal_id = periph_id_to_internal_id[periph_id];
+       assert(internal_id != -1);
+       if (internal_id >= PERIPHC_VW_FIRST) {
+               internal_id -= PERIPHC_VW_FIRST;
+               return &clkrst->crc_clk_src_vw[internal_id];
+       } else
+               return &clkrst->crc_clk_src[internal_id];
+}
+
+/**
+ * Given a peripheral ID and the required source clock, this returns which
+ * value should be programmed into the source mux for that peripheral.
+ *
+ * There is special code here to handle the one source type with 5 sources.
+ *
+ * @param periph_id    peripheral to start
+ * @param source       PLL id of required parent clock
+ * @param mux_bits     Set to number of bits in mux register: 2 or 4
+ * @param divider_bits  Set to number of divider bits (8 or 16)
+ * @return mux value (0-4, or -1 if not found)
+ */
+int get_periph_clock_source(enum periph_id periph_id,
+       enum clock_id parent, int *mux_bits, int *divider_bits)
+{
+       enum clock_type_id type;
+       enum periphc_internal_id internal_id;
+       int mux;
+
+       assert(clock_periph_id_isvalid(periph_id));
+
+       internal_id = periph_id_to_internal_id[periph_id];
+       assert(periphc_internal_id_isvalid(internal_id));
+
+       type = clock_periph_type[internal_id];
+       assert(clock_type_id_isvalid(type));
+
+       *mux_bits = clock_source[type][CLOCK_MAX_MUX];
+
+       if (type == CLOCK_TYPE_PCMT16)
+               *divider_bits = 16;
+       else
+               *divider_bits = 8;
+
+       for (mux = 0; mux < CLOCK_MAX_MUX; mux++)
+               if (clock_source[type][mux] == parent)
+                       return mux;
+
+       /* if we get here, either us or the caller has made a mistake */
+       printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id,
+               parent);
+       return -1;
+}
+
+void clock_set_enable(enum periph_id periph_id, int enable)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 *clk;
+       u32 reg;
+
+       /* Enable/disable the clock to this peripheral */
+       assert(clock_periph_id_isvalid(periph_id));
+       if ((int)periph_id < (int)PERIPH_ID_VW_FIRST)
+               clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)];
+       else
+               clk = &clkrst->crc_clk_out_enb_vw[PERIPH_REG(periph_id)];
+       reg = readl(clk);
+       if (enable)
+               reg |= PERIPH_MASK(periph_id);
+       else
+               reg &= ~PERIPH_MASK(periph_id);
+       writel(reg, clk);
+}
+
+void reset_set_enable(enum periph_id periph_id, int enable)
+{
+       struct clk_rst_ctlr *clkrst =
+                       (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       u32 *reset;
+       u32 reg;
+
+       /* Enable/disable reset to the peripheral */
+       assert(clock_periph_id_isvalid(periph_id));
+       if (periph_id < PERIPH_ID_VW_FIRST)
+               reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)];
+       else
+               reset = &clkrst->crc_rst_dev_vw[PERIPH_REG(periph_id)];
+       reg = readl(reset);
+       if (enable)
+               reg |= PERIPH_MASK(periph_id);
+       else
+               reg &= ~PERIPH_MASK(periph_id);
+       writel(reg, reset);
+}
+
+#ifdef CONFIG_OF_CONTROL
+/*
+ * Convert a device tree clock ID to our peripheral ID. They are mostly
+ * the same but we are very cautious so we check that a valid clock ID is
+ * provided.
+ *
+ * @param clk_id       Clock ID according to tegra30 device tree binding
+ * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid
+ */
+enum periph_id clk_id_to_periph_id(int clk_id)
+{
+       if (clk_id > PERIPH_ID_COUNT)
+               return PERIPH_ID_NONE;
+
+       switch (clk_id) {
+       case PERIPH_ID_RESERVED3:
+       case PERIPH_ID_RESERVED4:
+       case PERIPH_ID_RESERVED16:
+       case PERIPH_ID_RESERVED24:
+       case PERIPH_ID_RESERVED35:
+       case PERIPH_ID_RESERVED43:
+       case PERIPH_ID_RESERVED45:
+       case PERIPH_ID_RESERVED56:
+       case PERIPH_ID_RESERVED76:
+       case PERIPH_ID_RESERVED77:
+       case PERIPH_ID_RESERVED78:
+       case PERIPH_ID_RESERVED83:
+       case PERIPH_ID_RESERVED89:
+       case PERIPH_ID_RESERVED91:
+       case PERIPH_ID_RESERVED93:
+       case PERIPH_ID_RESERVED94:
+       case PERIPH_ID_RESERVED95:
+               return PERIPH_ID_NONE;
+       default:
+               return clk_id;
+       }
+}
+#endif /* CONFIG_OF_CONTROL */
+
+void clock_early_init(void)
+{
+       /*
+        * PLLP output frequency set to 408Mhz
+        * PLLC output frequency set to 228Mhz
+        */
+       switch (clock_get_osc_freq()) {
+       case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */
+               clock_set_rate(CLOCK_ID_PERIPH, 408, 12, 0, 8);
+               clock_set_rate(CLOCK_ID_CGENERAL, 456, 12, 1, 8);
+               break;
+
+       case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */
+               clock_set_rate(CLOCK_ID_PERIPH, 408, 26, 0, 8);
+               clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8);
+               break;
+
+       case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */
+               clock_set_rate(CLOCK_ID_PERIPH, 408, 13, 0, 8);
+               clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8);
+               break;
+       case CLOCK_OSC_FREQ_19_2:
+       default:
+               /*
+                * These are not supported. It is too early to print a
+                * message and the UART likely won't work anyway due to the
+                * oscillator being wrong.
+                */
+               break;
+       }
+}
diff --git a/arch/arm/cpu/tegra30-common/funcmux.c b/arch/arm/cpu/tegra30-common/funcmux.c
new file mode 100644 (file)
index 0000000..e24c57e
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/>.
+ */
+
+/* Tegra30 high-level function multiplexing */
+
+#include <common.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/funcmux.h>
+#include <asm/arch/pinmux.h>
+
+int funcmux_select(enum periph_id id, int config)
+{
+       int bad_config = config != FUNCMUX_DEFAULT;
+
+       switch (id) {
+       case PERIPH_ID_UART1:
+               switch (config) {
+               case FUNCMUX_UART1_ULPI:
+                       pinmux_set_func(PINGRP_ULPI_DATA0, PMUX_FUNC_UARTA);
+                       pinmux_set_func(PINGRP_ULPI_DATA1, PMUX_FUNC_UARTA);
+                       pinmux_set_func(PINGRP_ULPI_DATA2, PMUX_FUNC_UARTA);
+                       pinmux_set_func(PINGRP_ULPI_DATA3, PMUX_FUNC_UARTA);
+                       pinmux_tristate_disable(PINGRP_ULPI_DATA0);
+                       pinmux_tristate_disable(PINGRP_ULPI_DATA1);
+                       pinmux_tristate_disable(PINGRP_ULPI_DATA2);
+                       pinmux_tristate_disable(PINGRP_ULPI_DATA3);
+                       break;
+               }
+               break;
+
+       /* Add other periph IDs here as needed */
+
+       default:
+               debug("%s: invalid periph_id %d", __func__, id);
+               return -1;
+       }
+
+       if (bad_config) {
+               debug("%s: invalid config %d for periph_id %d", __func__,
+                     config, id);
+               return -1;
+       }
+       return 0;
+}
diff --git a/arch/arm/cpu/tegra30-common/pinmux.c b/arch/arm/cpu/tegra30-common/pinmux.c
new file mode 100644 (file)
index 0000000..122665f
--- /dev/null
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/>.
+ */
+
+/* Tegra30 pin multiplexing functions */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/tegra.h>
+#include <asm/arch/pinmux.h>
+
+struct tegra_pingroup_desc {
+       const char *name;
+       enum pmux_func funcs[4];
+       enum pmux_func func_safe;
+       enum pmux_vddio vddio;
+       enum pmux_pin_io io;
+};
+
+#define PMUX_MUXCTL_SHIFT      0
+#define PMUX_PULL_SHIFT                2
+#define PMUX_TRISTATE_SHIFT    4
+#define PMUX_TRISTATE_MASK     (1 << PMUX_TRISTATE_SHIFT)
+#define PMUX_IO_SHIFT          5
+#define PMUX_OD_SHIFT          6
+#define PMUX_LOCK_SHIFT                7
+#define PMUX_IO_RESET_SHIFT    8
+
+/* Convenient macro for defining pin group properties */
+#define PIN(pg_name, vdd, f0, f1, f2, f3, iod) \
+       {                                               \
+               .vddio = PMUX_VDDIO_ ## vdd,            \
+               .funcs = {                              \
+                       PMUX_FUNC_ ## f0,               \
+                       PMUX_FUNC_ ## f1,               \
+                       PMUX_FUNC_ ## f2,               \
+                       PMUX_FUNC_ ## f3,               \
+               },                                      \
+               .func_safe = PMUX_FUNC_RSVD1,           \
+               .io = PMUX_PIN_ ## iod,                 \
+       }
+
+/* Input and output pins */
+#define PINI(pg_name, vdd, f0, f1, f2, f3) \
+       PIN(pg_name, vdd, f0, f1, f2, f3, INPUT)
+#define PINO(pg_name, vdd, f0, f1, f2, f3) \
+       PIN(pg_name, vdd, f0, f1, f2, f3, OUTPUT)
+
+const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = {
+       /*      NAME      VDD      f0           f1         f2       f3  */
+       PINI(ULPI_DATA0,  BB,      SPI3,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_DATA1,  BB,      SPI3,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_DATA2,  BB,      SPI3,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_DATA3,  BB,      SPI3,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_DATA4,  BB,      SPI2,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_DATA5,  BB,      SPI2,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_DATA6,  BB,      SPI2,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_DATA7,  BB,      SPI2,        HSI,       UARTA,   ULPI),
+       PINI(ULPI_CLK,    BB,      SPI1,        RSVD2,     UARTD,   ULPI),
+       PINI(ULPI_DIR,    BB,      SPI1,        RSVD2,     UARTD,   ULPI),
+       PINI(ULPI_NXT,    BB,      SPI1,        RSVD2,     UARTD,   ULPI),
+       PINI(ULPI_STP,    BB,      SPI1,        RSVD2,     UARTD,   ULPI),
+       PINI(DAP3_FS,     BB,      I2S2,        RSVD2,     DISPA,   DISPB),
+       PINI(DAP3_DIN,    BB,      I2S2,        RSVD2,     DISPA,   DISPB),
+       PINI(DAP3_DOUT,   BB,      I2S2,        RSVD2,     DISPA,   DISPB),
+       PINI(DAP3_SCLK,   BB,      I2S2,        RSVD2,     DISPA,   DISPB),
+       PINI(GPIO_PV0,    BB,      RSVD1,       RSVD2,     RSVD3,   RSVD4),
+       PINI(GPIO_PV1,    BB,      RSVD1,       RSVD2,     RSVD3,   RSVD4),
+       PINI(SDMMC1_CLK,  SDMMC1,  SDMMC1,      RSVD2,     RSVD3,   UARTA),
+       PINI(SDMMC1_CMD,  SDMMC1,  SDMMC1,      RSVD2,     RSVD3,   UARTA),
+       PINI(SDMMC1_DAT3, SDMMC1,  SDMMC1,      RSVD2,     UARTE,   UARTA),
+       PINI(SDMMC1_DAT2, SDMMC1,  SDMMC1,      RSVD2,     UARTE,   UARTA),
+       PINI(SDMMC1_DAT1, SDMMC1,  SDMMC1,      RSVD2,     UARTE,   UARTA),
+       PINI(SDMMC1_DAT0, SDMMC1,  SDMMC1,      RSVD2,     UARTE,   UARTA),
+       PINI(GPIO_PV2,    SDMMC1,  OWR,         RSVD2,     RSVD3,   RSVD4),
+       PINI(GPIO_PV3,    SDMMC1,  CLK_12M_OUT, RSVD2,     RSVD3,   RSVD4),
+       PINI(CLK2_OUT,    SDMMC1,  EXTPERIPH2,  RSVD2,     RSVD3,   RSVD4),
+       PINI(CLK2_REQ,    SDMMC1,  DAP,         RSVD2,     RSVD3,   RSVD4),
+       PINO(LCD_PWR1,    LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_PWR2,    LCD,     DISPA,       DISPB,     SPI5,    HDCP),
+       PINO(LCD_SDIN,    LCD,     DISPA,       DISPB,     SPI5,    RSVD4),
+       PINO(LCD_SDOUT,   LCD,     DISPA,       DISPB,     SPI5,    HDCP),
+       PINO(LCD_WR_N,    LCD,     DISPA,       DISPB,     SPI5,    HDCP),
+       PINO(LCD_CS0_N,   LCD,     DISPA,       DISPB,     SPI5,    RSVD4),
+       PINO(LCD_DC0,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_SCK,     LCD,     DISPA,       DISPB,     SPI5,    HDCP),
+       PINO(LCD_PWR0,    LCD,     DISPA,       DISPB,     SPI5,    HDCP),
+       PINO(LCD_PCLK,    LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_DE,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_HSYNC,   LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_VSYNC,   LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D0,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D1,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D2,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D3,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D4,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D5,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D6,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D7,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D8,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D9,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D10,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D11,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D12,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D13,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D14,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D15,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D16,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D17,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D18,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D19,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D20,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D21,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D22,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_D23,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_CS1_N,   LCD,     DISPA,       DISPB,     SPI5,    RSVD4),
+       PINO(LCD_M1,      LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINO(LCD_DC1,     LCD,     DISPA,       DISPB,     RSVD3,   RSVD4),
+       PINI(HDMI_INT,    LCD,     HDMI,        RSVD2,     RSVD3,   RSVD4),
+       PINI(DDC_SCL,     LCD,     I2C4,        RSVD2,     RSVD3,   RSVD4),
+       PINI(DDC_SDA,     LCD,     I2C4,        RSVD2,     RSVD3,   RSVD4),
+       PINI(CRT_HSYNC,   LCD,     CRT,         RSVD2,     RSVD3,   RSVD4),
+       PINI(CRT_VSYNC,   LCD,     CRT,         RSVD2,     RSVD3,   RSVD4),
+       PINI(VI_D0,       VI,      DDR,         RSVD2,     VI,      RSVD4),
+       PINI(VI_D1,       VI,      DDR,         SDMMC2,    VI,      RSVD4),
+       PINI(VI_D2,       VI,      DDR,         SDMMC2,    VI,      RSVD4),
+       PINI(VI_D3,       VI,      DDR,         SDMMC2,    VI,      RSVD4),
+       PINI(VI_D4,       VI,      DDR,         SDMMC2,    VI,      RSVD4),
+       PINI(VI_D5,       VI,      DDR,         SDMMC2,    VI,      RSVD4),
+       PINI(VI_D6,       VI,      DDR,         SDMMC2,    VI,      RSVD4),
+       PINI(VI_D7,       VI,      DDR,         SDMMC2,    VI,      RSVD4),
+       PINI(VI_D8,       VI,      DDR,         SDMMC2,    VI,      RSVD4),
+       PINI(VI_D9,       VI,      DDR,         SDMMC2,    VI,      RSVD4),
+       PINI(VI_D10,      VI,      DDR,         RSVD2,     VI,      RSVD4),
+       PINI(VI_D11,      VI,      DDR,         RSVD2,     VI,      RSVD4),
+       PINI(VI_PCLK,     VI,      RSVD1,       SDMMC2,    VI,      RSVD4),
+       PINI(VI_MCLK,     VI,      VI,          VI,        VI,      VI),
+       PINI(VI_VSYNC,    VI,      DDR,         RSVD2,     VI,      RSVD4),
+       PINI(VI_HSYNC,    VI,      DDR,         RSVD2,     VI,      RSVD4),
+       PINI(UART2_RXD,   UART,    UARTB,       SPDIF,     UARTA,   SPI4),
+       PINI(UART2_TXD,   UART,    UARTB,       SPDIF,     UARTA,   SPI4),
+       PINI(UART2_RTS_N, UART,    UARTA,       UARTB,     GMI,     SPI4),
+       PINI(UART2_CTS_N, UART,    UARTA,       UARTB,     GMI,     SPI4),
+       PINI(UART3_TXD,   UART,    UARTC,       RSVD2,     GMI,     RSVD4),
+       PINI(UART3_RXD,   UART,    UARTC,       RSVD2,     GMI,     RSVD4),
+       PINI(UART3_CTS_N, UART,    UARTC,       RSVD2,     GMI,     RSVD4),
+       PINI(UART3_RTS_N, UART,    UARTC,       PWM0,      GMI,     RSVD4),
+       PINI(GPIO_PU0,    UART,    OWR,         UARTA,     GMI,     RSVD4),
+       PINI(GPIO_PU1,    UART,    RSVD1,       UARTA,     GMI,     RSVD4),
+       PINI(GPIO_PU2,    UART,    RSVD1,       UARTA,     GMI,     RSVD4),
+       PINI(GPIO_PU3,    UART,    PWM0,        UARTA,     GMI,     RSVD4),
+       PINI(GPIO_PU4,    UART,    PWM1,        UARTA,     GMI,     RSVD4),
+       PINI(GPIO_PU5,    UART,    PWM2,        UARTA,     GMI,     RSVD4),
+       PINI(GPIO_PU6,    UART,    PWM3,        UARTA,     GMI,     RSVD4),
+       PINI(GEN1_I2C_SDA, UART,   I2C1,        RSVD2,     RSVD3,   RSVD4),
+       PINI(GEN1_I2C_SCL, UART,   I2C1,        RSVD2,     RSVD3,   RSVD4),
+       PINI(DAP4_FS,     UART,    I2S3,        RSVD2,     GMI,     RSVD4),
+       PINI(DAP4_DIN,    UART,    I2S3,        RSVD2,     GMI,     RSVD4),
+       PINI(DAP4_DOUT,   UART,    I2S3,        RSVD2,     GMI,     RSVD4),
+       PINI(DAP4_SCLK,   UART,    I2S3,        RSVD2,     GMI,     RSVD4),
+       PINI(CLK3_OUT,    UART,    EXTPERIPH3,  RSVD2,     RSVD3,   RSVD4),
+       PINI(CLK3_REQ,    UART,    DEV3,        RSVD2,     RSVD3,   RSVD4),
+       PINI(GMI_WP_N,    GMI,     RSVD1,       NAND,      GMI,     GMI_ALT),
+       PINI(GMI_IORDY,   GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_WAIT,    GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_ADV_N,   GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_CLK,     GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_CS0_N,   GMI,     RSVD1,       NAND,      GMI,     DTV),
+       PINI(GMI_CS1_N,   GMI,     RSVD1,       NAND,      GMI,     DTV),
+       PINI(GMI_CS2_N,   GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_CS3_N,   GMI,     RSVD1,       NAND,      GMI,     GMI_ALT),
+       PINI(GMI_CS4_N,   GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_CS6_N,   GMI,     NAND,        NAND_ALT,  GMI,     SATA),
+       PINI(GMI_CS7_N,   GMI,     NAND,        NAND_ALT,  GMI,     GMI_ALT),
+       PINI(GMI_AD0,     GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_AD1,     GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_AD2,     GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_AD3,     GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_AD4,     GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_AD5,     GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_AD6,     GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_AD7,     GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_AD8,     GMI,     PWM0,        NAND,      GMI,     RSVD4),
+       PINI(GMI_AD9,     GMI,     PWM1,        NAND,      GMI,     RSVD4),
+       PINI(GMI_AD10,    GMI,     PWM2,        NAND,      GMI,     RSVD4),
+       PINI(GMI_AD11,    GMI,     PWM3,        NAND,      GMI,     RSVD4),
+       PINI(GMI_AD12,    GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_AD13,    GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_AD14,    GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_AD15,    GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_A16,     GMI,     UARTD,       SPI4,      GMI,     GMI_ALT),
+       PINI(GMI_A17,     GMI,     UARTD,       SPI4,      GMI,     DTV),
+       PINI(GMI_A18,     GMI,     UARTD,       SPI4,      GMI,     DTV),
+       PINI(GMI_A19,     GMI,     UARTD,       SPI4,      GMI,     RSVD4),
+       PINI(GMI_WR_N,    GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_OE_N,    GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_DQS,     GMI,     RSVD1,       NAND,      GMI,     RSVD4),
+       PINI(GMI_RST_N,   GMI,     NAND,        NAND_ALT,  GMI,     RSVD4),
+       PINI(GEN2_I2C_SCL, GMI,    I2C2,        HDCP,      GMI,     RSVD4),
+       PINI(GEN2_I2C_SDA, GMI,    I2C2,        HDCP,      GMI,     RSVD4),
+       PINI(SDMMC4_CLK,  SDMMC4,   RSVD1,      NAND,      GMI,     SDMMC4),
+       PINI(SDMMC4_CMD,  SDMMC4,   I2C3,       NAND,      GMI,     SDMMC4),
+       PINI(SDMMC4_DAT0, SDMMC4,   UARTE,      SPI3,      GMI,     SDMMC4),
+       PINI(SDMMC4_DAT1, SDMMC4,   UARTE,      SPI3,      GMI,     SDMMC4),
+       PINI(SDMMC4_DAT2, SDMMC4,   UARTE,      SPI3,      GMI,     SDMMC4),
+       PINI(SDMMC4_DAT3, SDMMC4,   UARTE,      SPI3,      GMI,     SDMMC4),
+       PINI(SDMMC4_DAT4, SDMMC4,   I2C3,       I2S4,      GMI,     SDMMC4),
+       PINI(SDMMC4_DAT5, SDMMC4,   VGP3,       I2S4,      GMI,     SDMMC4),
+       PINI(SDMMC4_DAT6, SDMMC4,   VGP4,       I2S4,      GMI,     SDMMC4),
+       PINI(SDMMC4_DAT7, SDMMC4,   VGP5,       I2S4,      GMI,     SDMMC4),
+       PINI(SDMMC4_RST_N, SDMMC4,  VGP6,       RSVD2,     RSVD3,   SDMMC4),
+       PINI(CAM_MCLK,    CAM,     VI,          RSVD2,     VI_ALT2, SDMMC4),
+       PINI(GPIO_PCC1,   CAM,     I2S4,        RSVD2,     RSVD3,   SDMMC4),
+       PINI(GPIO_PBB0,   CAM,     I2S4,        RSVD2,     RSVD3,   SDMMC4),
+       PINI(CAM_I2C_SCL, CAM,     VGP1,        I2C3,      RSVD3,   SDMMC4),
+       PINI(CAM_I2C_SDA, CAM,     VGP2,        I2C3,      RSVD3,   SDMMC4),
+       PINI(GPIO_PBB3,   CAM,     VGP3,        DISPA,     DISPB,   SDMMC4),
+       PINI(GPIO_PBB4,   CAM,     VGP4,        DISPA,     DISPB,   SDMMC4),
+       PINI(GPIO_PBB5,   CAM,     VGP5,        DISPA,     DISPB,   SDMMC4),
+       PINI(GPIO_PBB6,   CAM,     VGP6,        DISPA,     DISPB,   SDMMC4),
+       PINI(GPIO_PBB7,   CAM,     I2S4,        RSVD2,     RSVD3,   SDMMC4),
+       PINI(GPIO_PCC2,   CAM,     I2S4,        RSVD2,     RSVD3,   RSVD4),
+       PINI(JTAG_RTCK,   SYS,     RTCK,        RSVD2,     RSVD3,   RSVD4),
+       PINI(PWR_I2C_SCL, SYS,     I2CPWR,      RSVD2,     RSVD3,   RSVD4),
+       PINI(PWR_I2C_SDA, SYS,     I2CPWR,      RSVD2,     RSVD3,   RSVD4),
+       PINI(KB_ROW0,     SYS,     KBC,         NAND,      RSVD3,   RSVD4),
+       PINI(KB_ROW1,     SYS,     KBC,         NAND,      RSVD3,   RSVD4),
+       PINI(KB_ROW2,     SYS,     KBC,         NAND,      RSVD3,   RSVD4),
+       PINI(KB_ROW3,     SYS,     KBC,         NAND,      RSVD3,   RSVD4),
+       PINI(KB_ROW4,     SYS,     KBC,         NAND,      TRACE,   RSVD4),
+       PINI(KB_ROW5,     SYS,     KBC,         NAND,      TRACE,   OWR),
+       PINI(KB_ROW6,     SYS,     KBC,         NAND,      SDMMC2,  MIO),
+       PINI(KB_ROW7,     SYS,     KBC,         NAND,      SDMMC2,  MIO),
+       PINI(KB_ROW8,     SYS,     KBC,         NAND,      SDMMC2,  MIO),
+       PINI(KB_ROW9,     SYS,     KBC,         NAND,      SDMMC2,  MIO),
+       PINI(KB_ROW10,    SYS,     KBC,         NAND,      SDMMC2,  MIO),
+       PINI(KB_ROW11,    SYS,     KBC,         NAND,      SDMMC2,  MIO),
+       PINI(KB_ROW12,    SYS,     KBC,         NAND,      SDMMC2,  MIO),
+       PINI(KB_ROW13,    SYS,     KBC,         NAND,      SDMMC2,  MIO),
+       PINI(KB_ROW14,    SYS,     KBC,         NAND,      SDMMC2,  MIO),
+       PINI(KB_ROW15,    SYS,     KBC,         NAND,      SDMMC2,  MIO),
+       PINI(KB_COL0,     SYS,     KBC,         NAND,      TRACE,   TEST),
+       PINI(KB_COL1,     SYS,     KBC,         NAND,      TRACE,   TEST),
+       PINI(KB_COL2,     SYS,     KBC,         NAND,      TRACE,   RSVD4),
+       PINI(KB_COL3,     SYS,     KBC,         NAND,      TRACE,   RSVD4),
+       PINI(KB_COL4,     SYS,     KBC,         NAND,      TRACE,   RSVD4),
+       PINI(KB_COL5,     SYS,     KBC,         NAND,      TRACE,   RSVD4),
+       PINI(KB_COL6,     SYS,     KBC,         NAND,      TRACE,   MIO),
+       PINI(KB_COL7,     SYS,     KBC,         NAND,      TRACE,   MIO),
+       PINI(CLK_32K_OUT, SYS,     BLINK,       RSVD2,     RSVD3,   RSVD4),
+       PINI(SYS_CLK_REQ, SYS,     SYSCLK,      RSVD2,     RSVD3,   RSVD4),
+       PINI(CORE_PWR_REQ, SYS,    CORE_PWR_REQ, RSVD2,    RSVD3,   RSVD4),
+       PINI(CPU_PWR_REQ, SYS,     CPU_PWR_REQ, RSVD2,     RSVD3,   RSVD4),
+       PINI(PWR_INT_N,   SYS,     PWR_INT_N,   RSVD2,     RSVD3,   RSVD4),
+       PINI(CLK_32K_IN,  SYS,     CLK_32K_IN,  RSVD2,     RSVD3,   RSVD4),
+       PINI(OWR,         SYS,     OWR,         CEC,       RSVD3,   RSVD4),
+       PINI(DAP1_FS,     AUDIO,   I2S0,        HDA,       GMI,     SDMMC2),
+       PINI(DAP1_DIN,    AUDIO,   I2S0,        HDA,       GMI,     SDMMC2),
+       PINI(DAP1_DOUT,   AUDIO,   I2S0,        HDA,       GMI,     SDMMC2),
+       PINI(DAP1_SCLK,   AUDIO,   I2S0,        HDA,       GMI,     SDMMC2),
+       PINI(CLK1_REQ,    AUDIO,   DAP,         HDA,       RSVD3,   RSVD4),
+       PINI(CLK1_OUT,    AUDIO,   EXTPERIPH1,  RSVD2,     RSVD3,   RSVD4),
+       PINI(SPDIF_IN,    AUDIO,   SPDIF,       HDA,       I2C1,    SDMMC2),
+       PINI(SPDIF_OUT,   AUDIO,   SPDIF,       RSVD2,     I2C1,    SDMMC2),
+       PINI(DAP2_FS,     AUDIO,   I2S1,        HDA,       RSVD3,   GMI),
+       PINI(DAP2_DIN,    AUDIO,   I2S1,        HDA,       RSVD3,   GMI),
+       PINI(DAP2_DOUT,   AUDIO,   I2S1,        HDA,       RSVD3,   GMI),
+       PINI(DAP2_SCLK,   AUDIO,   I2S1,        HDA,       RSVD3,   GMI),
+       PINI(SPI2_MOSI,   AUDIO,   SPI6,        SPI2,      GMI,     GMI),
+       PINI(SPI2_MISO,   AUDIO,   SPI6,        SPI2,      GMI,     GMI),
+       PINI(SPI2_CS0_N,  AUDIO,   SPI6,        SPI2,      GMI,     GMI),
+       PINI(SPI2_SCK,    AUDIO,   SPI6,        SPI2,      GMI,     GMI),
+       PINI(SPI1_MOSI,   AUDIO,   SPI2,        SPI1,      SPI2_ALT, GMI),
+       PINI(SPI1_SCK,    AUDIO,   SPI2,        SPI1,      SPI2_ALT, GMI),
+       PINI(SPI1_CS0_N,  AUDIO,   SPI2,        SPI1,      SPI2_ALT, GMI),
+       PINI(SPI1_MISO,   AUDIO,   SPI3,        SPI1,      SPI2_ALT, RSVD4),
+       PINI(SPI2_CS1_N,  AUDIO,   SPI3,        SPI2,      SPI2_ALT, I2C1),
+       PINI(SPI2_CS2_N,  AUDIO,   SPI3,        SPI2,      SPI2_ALT, I2C1),
+       PINI(SDMMC3_CLK,  SDMMC3,  UARTA,       PWM2,      SDMMC3,  SPI3),
+       PINI(SDMMC3_CMD,  SDMMC3,  UARTA,       PWM3,      SDMMC3,  SPI2),
+       PINI(SDMMC3_DAT0, SDMMC3,  RSVD1,       RSVD2,     SDMMC3,  SPI3),
+       PINI(SDMMC3_DAT1, SDMMC3,  RSVD1,       RSVD2,     SDMMC3,  SPI3),
+       PINI(SDMMC3_DAT2, SDMMC3,  RSVD1,       PWM1,      SDMMC3,  SPI3),
+       PINI(SDMMC3_DAT3, SDMMC3,  RSVD1,       PWM0,      SDMMC3,  SPI3),
+       PINI(SDMMC3_DAT4, SDMMC3,  PWM1,        SPI4,      SDMMC3,  SPI2),
+       PINI(SDMMC3_DAT5, SDMMC3,  PWM0,        SPI4,      SDMMC3,  SPI2),
+       PINI(SDMMC3_DAT6, SDMMC3,  SPDIF,       SPI4,      SDMMC3,  SPI2),
+       PINI(SDMMC3_DAT7, SDMMC3,  SPDIF,       SPI4,      SDMMC3,  SPI2),
+       PINI(PEX_L0_PRSNT_N,    PEXCTL,   PCIE, HDA,       RSVD3,   RSVD4),
+       PINI(PEX_L0_RST_N,      PEXCTL,   PCIE, HDA,       RSVD3,   RSVD4),
+       PINI(PEX_L0_CLKREQ_N,   PEXCTL,   PCIE, HDA,       RSVD3,   RSVD4),
+       PINI(PEX_WAKE_N,        PEXCTL,   PCIE, HDA,       RSVD3,   RSVD4),
+       PINI(PEX_L1_PRSNT_N,    PEXCTL,   PCIE, HDA,       RSVD3,   RSVD4),
+       PINI(PEX_L1_RST_N,      PEXCTL,   PCIE, HDA,       RSVD3,   RSVD4),
+       PINI(PEX_L1_CLKREQ_N,   PEXCTL,   PCIE, HDA,       RSVD3,   RSVD4),
+       PINI(PEX_L2_PRSNT_N,    PEXCTL,   PCIE, HDA,       RSVD3,   RSVD4),
+       PINI(PEX_L2_RST_N,      PEXCTL,   PCIE, HDA,       RSVD3,   RSVD4),
+       PINI(PEX_L2_CLKREQ_N,   PEXCTL,   PCIE, HDA,       RSVD3,   RSVD4),
+       PINI(HDMI_CEC,          SYS,      CEC,  RSVD2,     RSVD3,   RSVD4),
+};
+
+void pinmux_set_tristate(enum pmux_pingrp pin, int enable)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *tri = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin */
+       assert(pmux_pingrp_isvalid(pin));
+
+       reg = readl(tri);
+       if (enable)
+               reg |= PMUX_TRISTATE_MASK;
+       else
+               reg &= ~PMUX_TRISTATE_MASK;
+       writel(reg, tri);
+}
+
+void pinmux_tristate_enable(enum pmux_pingrp pin)
+{
+       pinmux_set_tristate(pin, 1);
+}
+
+void pinmux_tristate_disable(enum pmux_pingrp pin)
+{
+       pinmux_set_tristate(pin, 0);
+}
+
+void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *pull = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin and pupd */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_pin_pupd_isvalid(pupd));
+
+       reg = readl(pull);
+       reg &= ~(0x3 << PMUX_PULL_SHIFT);
+       reg |= (pupd << PMUX_PULL_SHIFT);
+       writel(reg, pull);
+}
+
+void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *muxctl = &pmt->pmt_ctl[pin];
+       int i, mux = -1;
+       u32 reg;
+
+       /* Error check on pin and func */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_func_isvalid(func));
+
+       /* Handle special values */
+       if (func == PMUX_FUNC_SAFE)
+               func = tegra_soc_pingroups[pin].func_safe;
+
+       if (func & PMUX_FUNC_RSVD1) {
+               mux = func & 0x3;
+       } else {
+               /* Search for the appropriate function */
+               for (i = 0; i < 4; i++) {
+                       if (tegra_soc_pingroups[pin].funcs[i] == func) {
+                               mux = i;
+                               break;
+                       }
+               }
+       }
+       assert(mux != -1);
+
+       reg = readl(muxctl);
+       reg &= ~(0x3 << PMUX_MUXCTL_SHIFT);
+       reg |= (mux << PMUX_MUXCTL_SHIFT);
+       writel(reg, muxctl);
+
+}
+
+void pinmux_set_io(enum pmux_pingrp pin, enum pmux_pin_io io)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *pin_io = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin and io */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_pin_io_isvalid(io));
+
+       reg = readl(pin_io);
+       reg &= ~(0x1 << PMUX_IO_SHIFT);
+       reg |= (io & 0x1) << PMUX_IO_SHIFT;
+       writel(reg, pin_io);
+}
+
+static int pinmux_set_lock(enum pmux_pingrp pin, enum pmux_pin_lock lock)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *pin_lock = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin and lock */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_pin_lock_isvalid(lock));
+
+       if (lock == PMUX_PIN_LOCK_DEFAULT)
+               return 0;
+
+       reg = readl(pin_lock);
+       reg &= ~(0x1 << PMUX_LOCK_SHIFT);
+       if (lock == PMUX_PIN_LOCK_ENABLE)
+               reg |= (0x1 << PMUX_LOCK_SHIFT);
+       else {
+               /* lock == DISABLE, which isn't possible */
+               printf("%s: Warning: lock == %d, DISABLE is not allowed!\n",
+                       __func__, lock);
+       }
+       writel(reg, pin_lock);
+
+       return 0;
+}
+
+static int pinmux_set_od(enum pmux_pingrp pin, enum pmux_pin_od od)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *pin_od = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin and od */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_pin_od_isvalid(od));
+
+       if (od == PMUX_PIN_OD_DEFAULT)
+               return 0;
+
+       reg = readl(pin_od);
+       reg &= ~(0x1 << PMUX_OD_SHIFT);
+       if (od == PMUX_PIN_OD_ENABLE)
+               reg |= (0x1 << PMUX_OD_SHIFT);
+       writel(reg, pin_od);
+
+       return 0;
+}
+
+static int pinmux_set_ioreset(enum pmux_pingrp pin,
+                               enum pmux_pin_ioreset ioreset)
+{
+       struct pmux_tri_ctlr *pmt =
+                       (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE;
+       u32 *pin_ioreset = &pmt->pmt_ctl[pin];
+       u32 reg;
+
+       /* Error check on pin and ioreset */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_pin_ioreset_isvalid(ioreset));
+
+       if (ioreset == PMUX_PIN_IO_RESET_DEFAULT)
+               return 0;
+
+       reg = readl(pin_ioreset);
+       reg &= ~(0x1 << PMUX_IO_RESET_SHIFT);
+       if (ioreset == PMUX_PIN_IO_RESET_ENABLE)
+               reg |= (0x1 << PMUX_IO_RESET_SHIFT);
+       writel(reg, pin_ioreset);
+
+       return 0;
+}
+
+void pinmux_config_pingroup(struct pingroup_config *config)
+{
+       enum pmux_pingrp pin = config->pingroup;
+
+       pinmux_set_func(pin, config->func);
+       pinmux_set_pullupdown(pin, config->pull);
+       pinmux_set_tristate(pin, config->tristate);
+       pinmux_set_io(pin, config->io);
+       pinmux_set_lock(pin, config->lock);
+       pinmux_set_od(pin, config->od);
+       pinmux_set_ioreset(pin, config->ioreset);
+}
+
+void pinmux_config_table(struct pingroup_config *config, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               pinmux_config_pingroup(&config[i]);
+}
diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi
new file mode 100644 (file)
index 0000000..d06cd12
--- /dev/null
@@ -0,0 +1,5 @@
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "nvidia,tegra114";
+};
index 636ec2c1fe7da999c29542bee5b0089f5e6081ba..9a8968522e47702f3736b1f38f65dbf021943161 100644 (file)
        compatible = "nvidia,tegra20";
        interrupt-parent = <&intc>;
 
-       tegra_car: clock@60006000 {
-               compatible = "nvidia,tegra20-car";
-               reg = <0x60006000 0x1000>;
-               #clock-cells = <1>;
-       };
+       host1x {
+               compatible = "nvidia,tegra20-host1x", "simple-bus";
+               reg = <0x50000000 0x00024000>;
+               interrupts = <0 65 0x04   /* mpcore syncpt */
+                             0 67 0x04>; /* mpcore general */
+               status = "disabled";
 
-       clocks {
                #address-cells = <1>;
-               #size-cells = <0>;
+               #size-cells = <1>;
+
+               ranges = <0x54000000 0x54000000 0x04000000>;
+
+               /* video-encoding/decoding */
+               mpe {
+                       reg = <0x54040000 0x00040000>;
+                       interrupts = <0 68 0x04>;
+                       status = "disabled";
+               };
+
+               /* video input */
+               vi {
+                       reg = <0x54080000 0x00040000>;
+                       interrupts = <0 69 0x04>;
+                       status = "disabled";
+               };
+
+               /* EPP */
+               epp {
+                       reg = <0x540c0000 0x00040000>;
+                       interrupts = <0 70 0x04>;
+                       status = "disabled";
+               };
+
+               /* ISP */
+               isp {
+                       reg = <0x54100000 0x00040000>;
+                       interrupts = <0 71 0x04>;
+                       status = "disabled";
+               };
+
+               /* 2D engine */
+               gr2d {
+                       reg = <0x54140000 0x00040000>;
+                       interrupts = <0 72 0x04>;
+                       status = "disabled";
+               };
+
+               /* 3D engine */
+               gr3d {
+                       reg = <0x54180000 0x00040000>;
+                       status = "disabled";
+               };
+
+               /* display controllers */
+               dc@54200000 {
+                       compatible = "nvidia,tegra20-dc";
+                       reg = <0x54200000 0x00040000>;
+                       interrupts = <0 73 0x04>;
+                       status = "disabled";
+
+                       rgb {
+                               status = "disabled";
+                       };
+               };
+
+               dc@54240000 {
+                       compatible = "nvidia,tegra20-dc";
+                       reg = <0x54240000 0x00040000>;
+                       interrupts = <0 74 0x04>;
+                       status = "disabled";
+
+                       rgb {
+                               status = "disabled";
+                       };
+               };
+
+               /* outputs */
+               hdmi {
+                       compatible = "nvidia,tegra20-hdmi";
+                       reg = <0x54280000 0x00040000>;
+                       interrupts = <0 75 0x04>;
+                       status = "disabled";
+               };
 
-               osc: clock {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
+               tvo {
+                       compatible = "nvidia,tegra20-tvo";
+                       reg = <0x542c0000 0x00040000>;
+                       interrupts = <0 76 0x04>;
+                       status = "disabled";
+               };
+
+               dsi {
+                       compatible = "nvidia,tegra20-dsi";
+                       reg = <0x54300000 0x00040000>;
+                       status = "disabled";
                };
        };
 
                      < 0x50040100 0x0100 >;
        };
 
-       i2c@7000c000 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "nvidia,tegra20-i2c";
-               reg = <0x7000C000 0x100>;
-               interrupts = < 70 >;
-               /* PERIPH_ID_I2C1, PLL_P_OUT3 */
-               clocks = <&tegra_car 12>, <&tegra_car 124>;
+       tegra_car: clock@60006000 {
+               compatible = "nvidia,tegra20-car";
+               reg = <0x60006000 0x1000>;
+               #clock-cells = <1>;
        };
 
-       i2c@7000c400 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "nvidia,tegra20-i2c";
-               reg = <0x7000C400 0x100>;
-               interrupts = < 116 >;
-               /* PERIPH_ID_I2C2, PLL_P_OUT3 */
-               clocks = <&tegra_car 54>, <&tegra_car 124>;
+       apbdma: dma {
+               compatible = "nvidia,tegra20-apbdma";
+               reg = <0x6000a000 0x1200>;
+               interrupts = <0 104 0x04
+                             0 105 0x04
+                             0 106 0x04
+                             0 107 0x04
+                             0 108 0x04
+                             0 109 0x04
+                             0 110 0x04
+                             0 111 0x04
+                             0 112 0x04
+                             0 113 0x04
+                             0 114 0x04
+                             0 115 0x04
+                             0 116 0x04
+                             0 117 0x04
+                             0 118 0x04
+                             0 119 0x04>;
        };
 
-       i2c@7000c500 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "nvidia,tegra20-i2c";
-               reg = <0x7000C500 0x100>;
-               interrupts = < 124 >;
-               /* PERIPH_ID_I2C3, PLL_P_OUT3 */
-               clocks = <&tegra_car 67>, <&tegra_car 124>;
+       gpio: gpio@6000d000 {
+               compatible = "nvidia,tegra20-gpio";
+               reg = < 0x6000d000 0x1000 >;
+               interrupts = < 64 65 66 67 87 119 121 >;
+               #gpio-cells = <2>;
+               gpio-controller;
        };
 
-       i2c@7000d000 {
+       pinmux: pinmux@70000000 {
+               compatible = "nvidia,tegra20-pinmux";
+               reg = < 0x70000014 0x10    /* Tri-state registers */
+                       0x70000080 0x20    /* Mux registers */
+                       0x700000a0 0x14    /* Pull-up/down registers */
+                       0x70000868 0xa8 >; /* Pad control registers */
+       };
+
+       das@70000c00 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "nvidia,tegra20-i2c-dvc";
-               reg = <0x7000D000 0x200>;
-               interrupts = < 85 >;
-               /* PERIPH_ID_DVC_I2C, PLL_P_OUT3 */
-               clocks = <&tegra_car 47>, <&tegra_car 124>;
+               compatible = "nvidia,tegra20-das";
+               reg = <0x70000c00 0x80>;
        };
 
        i2s@70002800 {
                dma-channel = < 1 >;
        };
 
-       das@70000c00 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "nvidia,tegra20-das";
-               reg = <0x70000c00 0x80>;
-       };
-
-       gpio: gpio@6000d000 {
-               compatible = "nvidia,tegra20-gpio";
-               reg = < 0x6000d000 0x1000 >;
-               interrupts = < 64 65 66 67 87 119 121 >;
-               #gpio-cells = <2>;
-               gpio-controller;
-       };
-
-       pinmux: pinmux@70000000 {
-               compatible = "nvidia,tegra20-pinmux";
-               reg = < 0x70000014 0x10    /* Tri-state registers */
-                       0x70000080 0x20    /* Mux registers */
-                       0x700000a0 0x14    /* Pull-up/down registers */
-                       0x70000868 0xa8 >; /* Pad control registers */
-       };
-
        serial@70006000 {
                compatible = "nvidia,tegra20-uart";
                reg = <0x70006000 0x40>;
                interrupts = < 123 >;
        };
 
-       sdhci@c8000000 {
-               compatible = "nvidia,tegra20-sdhci";
-               reg = <0xc8000000 0x200>;
-               interrupts = < 46 >;
+       nand: nand-controller@70008000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-nand";
+               reg = <0x70008000 0x100>;
        };
 
-       sdhci@c8000200 {
-               compatible = "nvidia,tegra20-sdhci";
-               reg = <0xc8000200 0x200>;
-               interrupts = < 47 >;
+       pwm: pwm@7000a000 {
+               compatible = "nvidia,tegra20-pwm";
+               reg = <0x7000a000 0x100>;
+               #pwm-cells = <2>;
        };
 
-       sdhci@c8000400 {
-               compatible = "nvidia,tegra20-sdhci";
-               reg = <0xc8000400 0x200>;
-               interrupts = < 51 >;
+       i2c@7000c000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-i2c";
+               reg = <0x7000C000 0x100>;
+               interrupts = < 70 >;
+               /* PERIPH_ID_I2C1, PLL_P_OUT3 */
+               clocks = <&tegra_car 12>, <&tegra_car 124>;
        };
 
-       sdhci@c8000600 {
-               compatible = "nvidia,tegra20-sdhci";
-               reg = <0xc8000600 0x200>;
-               interrupts = < 63 >;
+       spi@7000c380 {
+               compatible = "nvidia,tegra20-sflash";
+               reg = <0x7000c380 0x80>;
+               interrupts = <0 39 0x04>;
+               nvidia,dma-request-selector = <&apbdma 11>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+               /* PERIPH_ID_SPI1, PLLP_OUT0 */
+               clocks = <&tegra_car 43>;
+       };
+
+       i2c@7000c400 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-i2c";
+               reg = <0x7000C400 0x100>;
+               interrupts = < 116 >;
+               /* PERIPH_ID_I2C2, PLL_P_OUT3 */
+               clocks = <&tegra_car 54>, <&tegra_car 124>;
+       };
+
+       i2c@7000c500 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-i2c";
+               reg = <0x7000C500 0x100>;
+               interrupts = < 124 >;
+               /* PERIPH_ID_I2C3, PLL_P_OUT3 */
+               clocks = <&tegra_car 67>, <&tegra_car 124>;
+       };
+
+       i2c@7000d000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra20-i2c-dvc";
+               reg = <0x7000D000 0x200>;
+               interrupts = < 85 >;
+               /* PERIPH_ID_DVC_I2C, PLL_P_OUT3 */
+               clocks = <&tegra_car 47>, <&tegra_car 124>;
+       };
+
+       kbc@7000e200 {
+               compatible = "nvidia,tegra20-kbc";
+               reg = <0x7000e200 0x0078>;
+       };
+
+       emc@7000f400 {
+               #address-cells = < 1 >;
+               #size-cells = < 0 >;
+               compatible = "nvidia,tegra20-emc";
+               reg = <0x7000f400 0x200>;
        };
 
        usb@c5000000 {
                clocks = <&tegra_car 59>;       /* PERIPH_ID_USB3 */
        };
 
-       emc@7000f400 {
-               #address-cells = < 1 >;
-               #size-cells = < 0 >;
-               compatible = "nvidia,tegra20-emc";
-               reg = <0x7000f400 0x200>;
-       };
-
-       kbc@7000e200 {
-               compatible = "nvidia,tegra20-kbc";
-               reg = <0x7000e200 0x0078>;
+       sdhci@c8000000 {
+               compatible = "nvidia,tegra20-sdhci";
+               reg = <0xc8000000 0x200>;
+               interrupts = < 46 >;
        };
 
-       nand: nand-controller@70008000 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "nvidia,tegra20-nand";
-               reg = <0x70008000 0x100>;
+       sdhci@c8000200 {
+               compatible = "nvidia,tegra20-sdhci";
+               reg = <0xc8000200 0x200>;
+               interrupts = < 47 >;
        };
 
-       pwm: pwm@7000a000 {
-               compatible = "nvidia,tegra20-pwm";
-               reg = <0x7000a000 0x100>;
-               #pwm-cells = <2>;
+       sdhci@c8000400 {
+               compatible = "nvidia,tegra20-sdhci";
+               reg = <0xc8000400 0x200>;
+               interrupts = < 51 >;
        };
 
-       host1x {
-               compatible = "nvidia,tegra20-host1x", "simple-bus";
-               reg = <0x50000000 0x00024000>;
-               interrupts = <0 65 0x04   /* mpcore syncpt */
-                             0 67 0x04>; /* mpcore general */
-               status = "disabled";
-
-               #address-cells = <1>;
-               #size-cells = <1>;
-
-               ranges = <0x54000000 0x54000000 0x04000000>;
-
-               /* video-encoding/decoding */
-               mpe {
-                       reg = <0x54040000 0x00040000>;
-                       interrupts = <0 68 0x04>;
-                       status = "disabled";
-               };
-
-               /* video input */
-               vi {
-                       reg = <0x54080000 0x00040000>;
-                       interrupts = <0 69 0x04>;
-                       status = "disabled";
-               };
-
-               /* EPP */
-               epp {
-                       reg = <0x540c0000 0x00040000>;
-                       interrupts = <0 70 0x04>;
-                       status = "disabled";
-               };
-
-               /* ISP */
-               isp {
-                       reg = <0x54100000 0x00040000>;
-                       interrupts = <0 71 0x04>;
-                       status = "disabled";
-               };
-
-               /* 2D engine */
-               gr2d {
-                       reg = <0x54140000 0x00040000>;
-                       interrupts = <0 72 0x04>;
-                       status = "disabled";
-               };
-
-               /* 3D engine */
-               gr3d {
-                       reg = <0x54180000 0x00040000>;
-                       status = "disabled";
-               };
-
-               /* display controllers */
-               dc@54200000 {
-                       compatible = "nvidia,tegra20-dc";
-                       reg = <0x54200000 0x00040000>;
-                       interrupts = <0 73 0x04>;
-                       status = "disabled";
-
-                       rgb {
-                               status = "disabled";
-                       };
-               };
-
-               dc@54240000 {
-                       compatible = "nvidia,tegra20-dc";
-                       reg = <0x54240000 0x00040000>;
-                       interrupts = <0 74 0x04>;
-                       status = "disabled";
-
-                       rgb {
-                               status = "disabled";
-                       };
-               };
-
-               /* outputs */
-               hdmi {
-                       compatible = "nvidia,tegra20-hdmi";
-                       reg = <0x54280000 0x00040000>;
-                       interrupts = <0 75 0x04>;
-                       status = "disabled";
-               };
-
-               tvo {
-                       compatible = "nvidia,tegra20-tvo";
-                       reg = <0x542c0000 0x00040000>;
-                       interrupts = <0 76 0x04>;
-                       status = "disabled";
-               };
-
-               dsi {
-                       compatible = "nvidia,tegra20-dsi";
-                       reg = <0x54300000 0x00040000>;
-                       status = "disabled";
-               };
+       sdhci@c8000600 {
+               compatible = "nvidia,tegra20-sdhci";
+               reg = <0xc8000600 0x200>;
+               interrupts = < 63 >;
        };
-
 };
diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi
new file mode 100644 (file)
index 0000000..7b8126f
--- /dev/null
@@ -0,0 +1,165 @@
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "nvidia,tegra30";
+
+       tegra_car: clock@60006000 {
+               compatible = "nvidia,tegra30-car", "nvidia,tegra20-car";
+               reg = <0x60006000 0x1000>;
+               #clock-cells = <1>;
+       };
+
+       apbdma: dma {
+               compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";
+               reg = <0x6000a000 0x1400>;
+               interrupts = <0 104 0x04
+                             0 105 0x04
+                             0 106 0x04
+                             0 107 0x04
+                             0 108 0x04
+                             0 109 0x04
+                             0 110 0x04
+                             0 111 0x04
+                             0 112 0x04
+                             0 113 0x04
+                             0 114 0x04
+                             0 115 0x04
+                             0 116 0x04
+                             0 117 0x04
+                             0 118 0x04
+                             0 119 0x04
+                             0 128 0x04
+                             0 129 0x04
+                             0 130 0x04
+                             0 131 0x04
+                             0 132 0x04
+                             0 133 0x04
+                             0 134 0x04
+                             0 135 0x04
+                             0 136 0x04
+                             0 137 0x04
+                             0 138 0x04
+                             0 139 0x04
+                             0 140 0x04
+                             0 141 0x04
+                             0 142 0x04
+                             0 143 0x04>;
+       };
+
+       i2c@7000c000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
+               reg = <0x7000C000 0x100>;
+               /* PERIPH_ID_I2C1, CLK_M */
+               clocks = <&tegra_car 12>;
+       };
+
+       i2c@7000c400 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
+               reg = <0x7000C400 0x100>;
+               /* PERIPH_ID_I2C2, CLK_M */
+               clocks = <&tegra_car 54>;
+       };
+
+       i2c@7000c500 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
+               reg = <0x7000C500 0x100>;
+               /* PERIPH_ID_I2C3, CLK_M */
+               clocks = <&tegra_car 67>;
+       };
+
+       i2c@7000c700 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c";
+               reg = <0x7000C700 0x100>;
+               /* PERIPH_ID_I2C4, CLK_M */
+               clocks = <&tegra_car 103>;
+       };
+
+       i2c@7000d000 {
+               #address-cells = <1>;
+               #size-cells = <0>;