Tegra30: Add common CPU (shared) files
authorTom Warren <twarren.nvidia@gmail.com>
Tue, 11 Dec 2012 13:34:15 +0000 (13:34 +0000)
committerTom Warren <twarren@nvidia.com>
Wed, 16 Jan 2013 20:40:07 +0000 (13:40 -0700)
These files are used by both SPL and main U-Boot.
Also made minor changes to shared Tegra code to support
T30 differences.

Signed-off-by: Tom Warren <twarren@nvidia.com>
Reviewed-by: Stephen Warren <swarren@nvidia.com>
arch/arm/cpu/tegra-common/ap.c
arch/arm/cpu/tegra-common/board.c
arch/arm/cpu/tegra-common/sys_info.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/include/asm/arch-tegra/ap.h

index c4eb137480340bb660e76ae3abcaca8f6e3bb7eb..aebe29e4b797c36a2a16eb8765c2ad3fbe22e409 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>
@@ -58,6 +62,12 @@ 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;
        }
        /* unknown sku id */
        return TEGRA_SOC_UNKNOWN;
@@ -93,7 +103,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 +137,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..af1879c50189792f2ed37d6b05224b81db539b5b 100644 (file)
@@ -54,16 +54,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 */
+       /* 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 +103,27 @@ 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
+ #endif
        FUNCMUX_UART2_IRDA,
        -1,
        FUNCMUX_UART4_GMC,
        -1,
+#else  /* Tegra30 */
+       FUNCMUX_UART1_ULPI,     /* UARTA */
+       -1,
+       -1,
+       -1,
+       -1,
+#endif
 };
 
 /**
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;
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..5db9d20
--- /dev/null
@@ -0,0 +1,1092 @@
+/*
+ * 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 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,
+};
+
+/*
+ * Clock types that we can use as a source. The Tegra3 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_PDCT,
+       CLOCK_TYPE_ACPT,
+       CLOCK_TYPE_ASPTE,
+       CLOCK_TYPE_PMDACD2T,
+       CLOCK_TYPE_PCST,
+
+       CLOCK_TYPE_COUNT,
+       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   = 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(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}
+};
+
+/* 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
+ */
+#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),
+       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_PCMT),
+       TYPE(PERIPHC_DVC_I2C,   CLOCK_TYPE_PCMT),
+       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),
+       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_PCMT),
+       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_PCMT),
+       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 */
+       TYPE(PERIPHC_G3D2,      CLOCK_TYPE_MCPA),
+       TYPE(PERIPHC_MSELECT,   CLOCK_TYPE_PCMT),
+       TYPE(PERIPHC_TSENSOR,   CLOCK_TYPE_PCM),
+       TYPE(PERIPHC_I2S3,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_I2S4,      CLOCK_TYPE_AXPT),
+       TYPE(PERIPHC_I2C4,      CLOCK_TYPE_PCMT),
+       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_PCM),
+       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_PCMT),
+       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_SATAOOB,   CLOCK_TYPE_PCMT),
+       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),
+       NONE(SBC1),     /* SBC1, 0x34, is this SPI1? */
+       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.
+ */
+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);
+       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;
+}
+
+/* Returns a pointer to the clock source register for a peripheral */
+static 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];
+}
+
+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);
+}
+
+/**
+ * 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.
+ *
+ * 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)
+ */
+static 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];
+
+       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;
+}
+
+/**
+ * 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, source;
+       int divider, divider_bits = 0;
+
+       /* 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 =
+                       (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 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 =
+                       (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);
+}
+
+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. Tegra3 has 4 */
+       assert(cpu >= 0 && cpu < 4);
+       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
+ * the same but we are very cautious so we check that a valid clock ID is
+ * provided.
+ *
+ * @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)
+{
+       if (clk_id > 95)
+               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:
+               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("PLLP %x is correct\n", reg);
+       return 0;
+}
+
+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;
+       }
+}
+
+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]);
+}
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]);
+}
index 70d94c50417390c6ad8705c0c3d480edb89c27ec..73dfd394d8284a66f0f378f2795bb1656c24ea98 100644 (file)
 #include <asm/types.h>
 
 /* Stabilization delays, in usec */
-#define PLL_STABILIZATION_DELAY (300)
+#define PLL_STABILIZATION_DELAY        (300)
 #define IO_STABILIZATION_DELAY (1000)
 
-#define NVBL_PLLP_KHZ  (216000)
-
 #define PLLX_ENABLED           (1 << 30)
 #define CCLK_BURST_POLICY      0x20008888
 #define SUPER_CCLK_DIVIDER     0x80000000
 
 /* Calculate clock fractional divider value from ref and target frequencies */
-#define CLK_DIVIDER(REF, FREQ)  ((((REF) * 2) / FREQ) - 2)
+#define CLK_DIVIDER(REF, FREQ) ((((REF) * 2) / FREQ) - 2)
 
 /* Calculate clock frequency value from reference and clock divider value */
-#define CLK_FREQUENCY(REF, REG)  (((REF) * 2) / (REG + 2))
+#define CLK_FREQUENCY(REF, REG)        (((REF) * 2) / (REG + 2))
 
 /* AVP/CPU ID */
 #define PG_UP_TAG_0_PID_CPU    0x55555555      /* CPU aka "a9" aka "mpcore" */
-#define PG_UP_TAG_0             0x0
+#define PG_UP_TAG_0            0x0
 
 #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
+/* AP base physical address of internal SRAM */
+#define NV_PA_BASE_SRAM                0x40000000
 
 #define EXCEP_VECTOR_CPU_RESET_VECTOR  (NV_PA_EVP_BASE + 0x100)
 #define CSITE_CPU_DBG0_LAR             (NV_PA_CSITE_BASE + 0x10FB0)