Merge branch 'for-linus' of git://android.kernel.org/kernel/tegra
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Aug 2010 17:05:57 +0000 (10:05 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Aug 2010 17:05:57 +0000 (10:05 -0700)
* 'for-linus' of git://android.kernel.org/kernel/tegra:
  [ARM] tegra: add MAINTAINERS entry
  [ARM] tegra: harmony: Add harmony board file
  [ARM] tegra: add pinmux support
  [ARM] tegra: add GPIO support
  [ARM] tegra: Add timer support
  [ARM] tegra: SMP support
  [ARM] tegra: Add clock support
  [ARM] tegra: Add IRQ support
  [ARM] tegra: initial tegra support

42 files changed:
MAINTAINERS
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/mach-tegra/Kconfig [new file with mode: 0644]
arch/arm/mach-tegra/Makefile [new file with mode: 0644]
arch/arm/mach-tegra/Makefile.boot [new file with mode: 0644]
arch/arm/mach-tegra/board-harmony-pinmux.c [new file with mode: 0644]
arch/arm/mach-tegra/board-harmony.c [new file with mode: 0644]
arch/arm/mach-tegra/board-harmony.h [new file with mode: 0644]
arch/arm/mach-tegra/board.h [new file with mode: 0644]
arch/arm/mach-tegra/clock.c [new file with mode: 0644]
arch/arm/mach-tegra/clock.h [new file with mode: 0644]
arch/arm/mach-tegra/common.c [new file with mode: 0644]
arch/arm/mach-tegra/gpio-names.h [new file with mode: 0644]
arch/arm/mach-tegra/gpio.c [new file with mode: 0644]
arch/arm/mach-tegra/headsmp.S [new file with mode: 0644]
arch/arm/mach-tegra/hotplug.c [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/barriers.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/clk.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/clkdev.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/debug-macro.S [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/entry-macro.S [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/gpio.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/hardware.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/io.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/iomap.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/irqs.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/memory.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/pinmux.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/smp.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/system.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/timex.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/uncompress.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/vmalloc.h [new file with mode: 0644]
arch/arm/mach-tegra/io.c [new file with mode: 0644]
arch/arm/mach-tegra/irq.c [new file with mode: 0644]
arch/arm/mach-tegra/localtimer.c [new file with mode: 0644]
arch/arm/mach-tegra/pinmux.c [new file with mode: 0644]
arch/arm/mach-tegra/platsmp.c [new file with mode: 0644]
arch/arm/mach-tegra/tegra2_clocks.c [new file with mode: 0644]
arch/arm/mach-tegra/timer.c [new file with mode: 0644]
arch/arm/mm/Kconfig

index d4242846e7afbc64588adedd2e9e8e7cd04804d0..54d94ca9d6e8376a2a0f579e98dae44ba6fc904b 100644 (file)
@@ -5565,6 +5565,15 @@ W:       http://tcp-lp-mod.sourceforge.net/
 S:     Maintained
 F:     net/ipv4/tcp_lp.c
 
+TEGRA SUPPORT
+M:     Colin Cross <ccross@android.com>
+M:     Erik Gilling <konkers@android.com>
+M:     Olof Johansson <olof@lixom.net>
+L:     linux-tegra@vger.kernel.org
+T:     git git://android.git.kernel.org/kernel/tegra.git
+S:     Supported
+F:     arch/arm/mach-tegra
+
 TEHUTI ETHERNET DRIVER
 M:     Alexander Indenbaum <baum@tehutinetworks.net>
 M:     Andy Gospodarek <andy@greyhouse.net>
index 9e10882c81d7746e06f0908cb5ce0198e2d2654d..232f0c7582520e97b4d7779bf760d1df69a3cfbe 100644 (file)
@@ -558,6 +558,18 @@ config ARCH_NUC93X
          Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
          low-power and high performance MPEG-4/JPEG multimedia controller chip.
 
+config ARCH_TEGRA
+       bool "NVIDIA Tegra"
+       select GENERIC_TIME
+       select GENERIC_CLOCKEVENTS
+       select GENERIC_GPIO
+       select HAVE_CLK
+       select COMMON_CLKDEV
+       select ARCH_HAS_BARRIERS if CACHE_L2X0
+       help
+         This enables support for NVIDIA Tegra based systems (Tegra APX,
+         Tegra 6xx and Tegra 2 series).
+
 config ARCH_PNX4008
        bool "Philips Nexperia PNX4008 Mobile"
        select CPU_ARM926T
@@ -907,6 +919,8 @@ source "arch/arm/mach-shmobile/Kconfig"
 
 source "arch/arm/plat-stmp3xxx/Kconfig"
 
+source "arch/arm/mach-tegra/Kconfig"
+
 source "arch/arm/mach-u300/Kconfig"
 
 source "arch/arm/mach-ux500/Kconfig"
@@ -1094,10 +1108,11 @@ config SMP
        bool "Symmetric Multi-Processing (EXPERIMENTAL)"
        depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\
                 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
-                ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+                ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_TEGRA)
        depends on GENERIC_CLOCKEVENTS
        select USE_GENERIC_SMP_HELPERS
-       select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+       select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || \
+                ARCH_VEXPRESS_CA9X4 || ARCH_TEGRA)
        help
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
@@ -1167,9 +1182,10 @@ config LOCAL_TIMERS
        bool "Use local timer interrupts"
        depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
                REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
-               ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
+               ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_TEGRA)
        default y
-       select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_OMAP4 || ARCH_U8500)
+       select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_OMAP4 || \\
+               ARCH_U8500 || ARCH_TEGRA
        help
          Enable support for local timers on SMP platforms, rather then the
          legacy IPI broadcast method.  Local timers allows the system
index 63d998e8c672ef4488eb72df2cfdcce2f7ae502f..a8d4dca9da35a4310ee9a65ff08856957629f0f0 100644 (file)
@@ -179,6 +179,7 @@ machine-$(CONFIG_ARCH_SHARK)                := shark
 machine-$(CONFIG_ARCH_SHMOBILE)        := shmobile
 machine-$(CONFIG_ARCH_STMP378X)                := stmp378x
 machine-$(CONFIG_ARCH_STMP37XX)                := stmp37xx
+machine-$(CONFIG_ARCH_TEGRA)           := tegra
 machine-$(CONFIG_ARCH_U300)            := u300
 machine-$(CONFIG_ARCH_U8500)           := ux500
 machine-$(CONFIG_ARCH_VERSATILE)       := versatile
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
new file mode 100644 (file)
index 0000000..a57713c
--- /dev/null
@@ -0,0 +1,50 @@
+if ARCH_TEGRA
+
+comment "NVIDIA Tegra options"
+
+choice
+       prompt "Select Tegra processor family for target system"
+
+config ARCH_TEGRA_2x_SOC
+       bool "Tegra 2 family"
+       select CPU_V7
+       select ARM_GIC
+       select ARCH_REQUIRE_GPIOLIB
+       help
+         Support for NVIDIA Tegra AP20 and T20 processors, based on the
+         ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
+
+endchoice
+
+comment "Tegra board type"
+
+config MACH_HARMONY
+       bool "Harmony board"
+       help
+         Support for nVidia Harmony development platform
+
+choice
+        prompt "Low-level debug console UART"
+        default TEGRA_DEBUG_UART_NONE
+
+config TEGRA_DEBUG_UART_NONE
+        bool "None"
+
+config TEGRA_DEBUG_UARTA
+        bool "UART-A"
+
+config TEGRA_DEBUG_UARTB
+        bool "UART-B"
+
+config TEGRA_DEBUG_UARTC
+        bool "UART-C"
+
+config TEGRA_DEBUG_UARTD
+        bool "UART-D"
+
+config TEGRA_DEBUG_UARTE
+        bool "UART-E"
+
+endchoice
+
+endif
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
new file mode 100644 (file)
index 0000000..51e9370
--- /dev/null
@@ -0,0 +1,14 @@
+obj-y                                   += common.o
+obj-y                                   += io.o
+obj-y                                   += irq.o
+obj-y                                   += clock.o
+obj-y                                   += timer.o
+obj-y                                   += gpio.o
+obj-y                                   += pinmux.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clock.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_clocks.o
+obj-$(CONFIG_SMP)                       += platsmp.o localtimer.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
+
+obj-${CONFIG_MACH_HARMONY}              += board-harmony.o
+obj-${CONFIG_MACH_HARMONY}              += board-harmony-pinmux.o
diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot
new file mode 100644 (file)
index 0000000..db52d61
--- /dev/null
@@ -0,0 +1,3 @@
+zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)   := 0x00008000
+params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)        := 0x00000100
+initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)        := 0x00800000
diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c
new file mode 100644 (file)
index 0000000..50b15d5
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * arch/arm/mach-tegra/board-harmony-pinmux.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <mach/pinmux.h>
+
+#include "board-harmony.h"
+
+static struct tegra_pingroup_config harmony_pinmux[] = {
+       {TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_ATB,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_ATC,   TEGRA_MUX_NAND,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_ATD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_ATE,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4,     TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_CSUS,  TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_DDC,   TEGRA_MUX_I2C2,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_DTA,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_DTB,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_DTC,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_DTD,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_DTE,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_DTF,   TEGRA_MUX_I2C3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_GMA,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_GMB,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_GMC,   TEGRA_MUX_UARTD,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_GMD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_GME,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_GPU,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_GPU7,  TEGRA_MUX_RTCK,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_GPV,   TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_I2CP,  TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_IRRX,  TEGRA_MUX_UARTA,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_IRTX,  TEGRA_MUX_UARTA,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_KBCA,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_KBCB,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_KBCC,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_KBCD,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_KBCE,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_KBCF,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LCSN,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_LD0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD10,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD11,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD12,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD13,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD14,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD15,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD16,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD17,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD2,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD3,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD4,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD5,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD6,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD7,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD8,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LD9,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LDC,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_LDI,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LHP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LHP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LHP2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LHS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LM0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LM1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_LPP,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LPW0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LPW1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_LPW2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LSC0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LSC1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_LSCK,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_LSDA,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_LSDI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_LSPI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LVP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_LVP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_LVS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_OWC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_PMC,   TEGRA_MUX_PWR_ON,        TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_PTA,   TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_RM,    TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_SDB,   TEGRA_MUX_PWM,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SDC,   TEGRA_MUX_PWM,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_SDD,   TEGRA_MUX_PWM,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SLXA,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SLXC,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SLXD,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SLXK,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SPDI,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SPDO,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SPIA,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SPIB,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_SPID,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SPIE,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SPIF,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SPIG,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_SPIH,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_UAA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_UAB,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_UAC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_UAD,   TEGRA_MUX_IRDA,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_UCA,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_UCB,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_UDA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+       {TEGRA_PINGROUP_CK32,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_DDRC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_PMCA,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_PMCB,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_PMCC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_PMCD,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_PMCE,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_XM2C,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+       {TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+};
+
+void harmony_pinmux_init(void)
+{
+       tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
+}
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
new file mode 100644 (file)
index 0000000..05e78dd
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * arch/arm/mach-tegra/board-harmony.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/pda_power.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/setup.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+
+#include "board.h"
+#include "board-harmony.h"
+#include "clock.h"
+
+/* NVidia bootloader tags */
+#define ATAG_NVIDIA            0x41000801
+
+#define ATAG_NVIDIA_RM                 0x1
+#define ATAG_NVIDIA_DISPLAY            0x2
+#define ATAG_NVIDIA_FRAMEBUFFER                0x3
+#define ATAG_NVIDIA_CHIPSHMOO          0x4
+#define ATAG_NVIDIA_CHIPSHMOOPHYS      0x5
+#define ATAG_NVIDIA_PRESERVED_MEM_0    0x10000
+#define ATAG_NVIDIA_PRESERVED_MEM_N    2
+#define ATAG_NVIDIA_FORCE_32           0x7fffffff
+
+struct tag_tegra {
+       __u32 bootarg_key;
+       __u32 bootarg_len;
+       char bootarg[1];
+};
+
+static int __init parse_tag_nvidia(const struct tag *tag)
+{
+
+       return 0;
+}
+__tagtable(ATAG_NVIDIA, parse_tag_nvidia);
+
+static struct plat_serial8250_port debug_uart_platform_data[] = {
+       {
+               .membase        = IO_ADDRESS(TEGRA_UARTD_BASE),
+               .mapbase        = TEGRA_UARTD_BASE,
+               .irq            = INT_UARTD,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = 216000000,
+       }, {
+               .flags          = 0
+       }
+};
+
+static struct platform_device debug_uart = {
+       .name = "serial8250",
+       .id = PLAT8250_DEV_PLATFORM,
+       .dev = {
+               .platform_data = debug_uart_platform_data,
+       },
+};
+
+static struct platform_device *harmony_devices[] __initdata = {
+       &debug_uart,
+};
+
+static void __init tegra_harmony_fixup(struct machine_desc *desc,
+       struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+       mi->nr_banks = 2;
+       mi->bank[0].start = PHYS_OFFSET;
+       mi->bank[0].node = PHYS_TO_NID(PHYS_OFFSET);
+       mi->bank[0].size = 448 * SZ_1M;
+       mi->bank[1].start = SZ_512M;
+       mi->bank[1].node = PHYS_TO_NID(SZ_512M);
+       mi->bank[1].size = SZ_512M;
+}
+
+static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = {
+       /* name         parent          rate            enabled */
+       { "uartd",      "pll_p",        216000000,      true },
+       { NULL,         NULL,           0,              0},
+};
+
+static void __init tegra_harmony_init(void)
+{
+       tegra_common_init();
+
+       tegra_clk_init_from_table(harmony_clk_init_table);
+
+       harmony_pinmux_init();
+
+       platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices));
+}
+
+MACHINE_START(HARMONY, "harmony")
+       .boot_params  = 0x00000100,
+       .phys_io        = IO_APB_PHYS,
+       .io_pg_offst    = ((IO_APB_VIRT) >> 18) & 0xfffc,
+       .fixup          = tegra_harmony_fixup,
+       .init_irq       = tegra_init_irq,
+       .init_machine   = tegra_harmony_init,
+       .map_io         = tegra_map_common_io,
+       .timer          = &tegra_timer,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h
new file mode 100644 (file)
index 0000000..09ca775
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * arch/arm/mach-tegra/board-harmony.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MACH_TEGRA_BOARD_HARMONY_H
+#define _MACH_TEGRA_BOARD_HARMONY_H
+
+void harmony_pinmux_init(void);
+
+#endif
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
new file mode 100644 (file)
index 0000000..3d06354
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-tegra/board.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_BOARD_H
+#define __MACH_TEGRA_BOARD_H
+
+#include <linux/types.h>
+
+void __init tegra_common_init(void);
+void __init tegra_map_common_io(void);
+void __init tegra_init_irq(void);
+void __init tegra_init_clock(void);
+
+extern struct sys_timer tegra_timer;
+#endif
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
new file mode 100644 (file)
index 0000000..03ad578
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <asm/clkdev.h>
+
+#include "clock.h"
+
+static LIST_HEAD(clocks);
+
+static DEFINE_SPINLOCK(clock_lock);
+
+struct clk *tegra_get_clock_by_name(const char *name)
+{
+       struct clk *c;
+       struct clk *ret = NULL;
+       unsigned long flags;
+       spin_lock_irqsave(&clock_lock, flags);
+       list_for_each_entry(c, &clocks, node) {
+               if (strcmp(c->name, name) == 0) {
+                       ret = c;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&clock_lock, flags);
+       return ret;
+}
+
+int clk_reparent(struct clk *c, struct clk *parent)
+{
+       pr_debug("%s: %s\n", __func__, c->name);
+       if (c->refcnt && c->parent)
+               clk_disable_locked(c->parent);
+       c->parent = parent;
+       if (c->refcnt && c->parent)
+               clk_enable_locked(c->parent);
+       list_del(&c->sibling);
+       list_add_tail(&c->sibling, &parent->children);
+       return 0;
+}
+
+static void propagate_rate(struct clk *c)
+{
+       struct clk *clkp;
+       pr_debug("%s: %s\n", __func__, c->name);
+       list_for_each_entry(clkp, &c->children, sibling) {
+               pr_debug("   %s\n", clkp->name);
+               if (clkp->ops->recalculate_rate)
+                       clkp->ops->recalculate_rate(clkp);
+               propagate_rate(clkp);
+       }
+}
+
+void clk_init(struct clk *c)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&clock_lock, flags);
+
+       INIT_LIST_HEAD(&c->children);
+       INIT_LIST_HEAD(&c->sibling);
+
+       if (c->ops && c->ops->init)
+               c->ops->init(c);
+
+       list_add(&c->node, &clocks);
+
+       if (c->parent)
+               list_add_tail(&c->sibling, &c->parent->children);
+
+       spin_unlock_irqrestore(&clock_lock, flags);
+}
+
+int clk_enable_locked(struct clk *c)
+{
+       int ret;
+       pr_debug("%s: %s\n", __func__, c->name);
+       if (c->refcnt == 0) {
+               if (c->parent) {
+                       ret = clk_enable_locked(c->parent);
+                       if (ret)
+                               return ret;
+               }
+
+               if (c->ops && c->ops->enable) {
+                       ret = c->ops->enable(c);
+                       if (ret) {
+                               if (c->parent)
+                                       clk_disable_locked(c->parent);
+                               return ret;
+                       }
+                       c->state = ON;
+#ifdef CONFIG_DEBUG_FS
+                       c->set = 1;
+#endif
+               }
+       }
+       c->refcnt++;
+
+       return 0;
+}
+
+int clk_enable(struct clk *c)
+{
+       int ret;
+       unsigned long flags;
+       spin_lock_irqsave(&clock_lock, flags);
+       ret = clk_enable_locked(c);
+       spin_unlock_irqrestore(&clock_lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable_locked(struct clk *c)
+{
+       pr_debug("%s: %s\n", __func__, c->name);
+       if (c->refcnt == 0) {
+               WARN(1, "Attempting to disable clock %s with refcnt 0", c->name);
+               return;
+       }
+       if (c->refcnt == 1) {
+               if (c->ops && c->ops->disable)
+                       c->ops->disable(c);
+
+               if (c->parent)
+                       clk_disable_locked(c->parent);
+
+               c->state = OFF;
+       }
+       c->refcnt--;
+}
+
+void clk_disable(struct clk *c)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&clock_lock, flags);
+       clk_disable_locked(c);
+       spin_unlock_irqrestore(&clock_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_set_parent_locked(struct clk *c, struct clk *parent)
+{
+       int ret;
+
+       pr_debug("%s: %s\n", __func__, c->name);
+
+       if (!c->ops || !c->ops->set_parent)
+               return -ENOSYS;
+
+       ret = c->ops->set_parent(c, parent);
+
+       if (ret)
+               return ret;
+
+       propagate_rate(c);
+
+       return 0;
+}
+
+int clk_set_parent(struct clk *c, struct clk *parent)
+{
+       int ret;
+       unsigned long flags;
+       spin_lock_irqsave(&clock_lock, flags);
+       ret = clk_set_parent_locked(c, parent);
+       spin_unlock_irqrestore(&clock_lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *c)
+{
+       return c->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+int clk_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&clock_lock, flags);
+
+       pr_debug("%s: %s\n", __func__, c->name);
+
+       if (c->ops && c->ops->set_rate)
+               ret = c->ops->set_rate(c, rate);
+       else
+               ret = -ENOSYS;
+
+       propagate_rate(c);
+
+       spin_unlock_irqrestore(&clock_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+unsigned long clk_get_rate(struct clk *c)
+{
+       unsigned long flags;
+       unsigned long ret;
+
+       spin_lock_irqsave(&clock_lock, flags);
+
+       pr_debug("%s: %s\n", __func__, c->name);
+
+       ret = c->rate;
+
+       spin_unlock_irqrestore(&clock_lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
+{
+       struct clk *c;
+       struct clk *p;
+
+       int ret = 0;
+
+       c = tegra_get_clock_by_name(table->name);
+
+       if (!c) {
+               pr_warning("Unable to initialize clock %s\n",
+                       table->name);
+               return -ENODEV;
+       }
+
+       if (table->parent) {
+               p = tegra_get_clock_by_name(table->parent);
+               if (!p) {
+                       pr_warning("Unable to find parent %s of clock %s\n",
+                               table->parent, table->name);
+                       return -ENODEV;
+               }
+
+               if (c->parent != p) {
+                       ret = clk_set_parent(c, p);
+                       if (ret) {
+                               pr_warning("Unable to set parent %s of clock %s: %d\n",
+                                       table->parent, table->name, ret);
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       if (table->rate && table->rate != clk_get_rate(c)) {
+               ret = clk_set_rate(c, table->rate);
+               if (ret) {
+                       pr_warning("Unable to set clock %s to rate %lu: %d\n",
+                               table->name, table->rate, ret);
+                       return -EINVAL;
+               }
+       }
+
+       if (table->enabled) {
+               ret = clk_enable(c);
+               if (ret) {
+                       pr_warning("Unable to enable clock %s: %d\n",
+                               table->name, ret);
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+void tegra_clk_init_from_table(struct tegra_clk_init_table *table)
+{
+       for (; table->name; table++)
+               tegra_clk_init_one_from_table(table);
+}
+EXPORT_SYMBOL(tegra_clk_init_from_table);
+
+void tegra_periph_reset_deassert(struct clk *c)
+{
+       tegra2_periph_reset_deassert(c);
+}
+EXPORT_SYMBOL(tegra_periph_reset_deassert);
+
+void tegra_periph_reset_assert(struct clk *c)
+{
+       tegra2_periph_reset_assert(c);
+}
+EXPORT_SYMBOL(tegra_periph_reset_assert);
+
+int __init tegra_init_clock(void)
+{
+       tegra2_init_clocks();
+
+       return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *clk_debugfs_root;
+
+
+static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
+{
+       struct clk *child;
+       struct clk *safe;
+       const char *state = "uninit";
+       char div[5] = {0};
+
+       if (c->state == ON)
+               state = "on";
+       else if (c->state == OFF)
+               state = "off";
+
+       if (c->mul != 0 && c->div != 0) {
+               BUG_ON(c->mul > 2);
+               if (c->mul > c->div)
+                       snprintf(div, sizeof(div), "x%d", c->mul / c->div);
+               else
+                       snprintf(div, sizeof(div), "%d%s", c->div / c->mul,
+                               (c->div % c->mul) ? ".5" : "");
+       }
+
+       seq_printf(s, "%*s%-*s %-6s %-3d %-5s %-10lu\n",
+               level * 3 + 1, c->set ? "" : "*",
+               30 - level * 3, c->name,
+               state, c->refcnt, div, c->rate);
+       list_for_each_entry_safe(child, safe, &c->children, sibling) {
+               clock_tree_show_one(s, child, level + 1);
+       }
+}
+
+static int clock_tree_show(struct seq_file *s, void *data)
+{
+       struct clk *c;
+       unsigned long flags;
+       seq_printf(s, " clock                          state  ref div   rate      \n");
+       seq_printf(s, "-----------------------------------------------------------\n");
+       spin_lock_irqsave(&clock_lock, flags);
+       list_for_each_entry(c, &clocks, node)
+               if (c->parent == NULL)
+                       clock_tree_show_one(s, c, 0);
+       spin_unlock_irqrestore(&clock_lock, flags);
+       return 0;
+}
+
+static int clock_tree_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, clock_tree_show, inode->i_private);
+}
+
+static const struct file_operations clock_tree_fops = {
+       .open           = clock_tree_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int possible_parents_show(struct seq_file *s, void *data)
+{
+       struct clk *c = s->private;
+       int i;
+
+       for (i = 0; c->inputs[i].input; i++) {
+               char *first = (i == 0) ? "" : " ";
+               seq_printf(s, "%s%s", first, c->inputs[i].input->name);
+       }
+       seq_printf(s, "\n");
+       return 0;
+}
+
+static int possible_parents_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, possible_parents_show, inode->i_private);
+}
+
+static const struct file_operations possible_parents_fops = {
+       .open           = possible_parents_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int clk_debugfs_register_one(struct clk *c)
+{
+       struct dentry *d, *child, *child_tmp;
+
+       d = debugfs_create_dir(c->name, clk_debugfs_root);
+       if (!d)
+               return -ENOMEM;
+       c->dent = d;
+
+       d = debugfs_create_u8("refcnt", S_IRUGO, c->dent, (u8 *)&c->refcnt);
+       if (!d)
+               goto err_out;
+
+       d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
+       if (!d)
+               goto err_out;
+
+       d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
+       if (!d)
+               goto err_out;
+
+       if (c->inputs) {
+               d = debugfs_create_file("possible_parents", S_IRUGO, c->dent,
+                       c, &possible_parents_fops);
+               if (!d)
+                       goto err_out;
+       }
+
+       return 0;
+
+err_out:
+       d = c->dent;
+       list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
+               debugfs_remove(child);
+       debugfs_remove(c->dent);
+       return -ENOMEM;
+}
+
+static int clk_debugfs_register(struct clk *c)
+{
+       int err;
+       struct clk *pa = c->parent;
+
+       if (pa && !pa->dent) {
+               err = clk_debugfs_register(pa);
+               if (err)
+                       return err;
+       }
+
+       if (!c->dent) {
+               err = clk_debugfs_register_one(c);
+               if (err)
+                       return err;
+       }
+       return 0;
+}
+
+static int __init clk_debugfs_init(void)
+{
+       struct clk *c;
+       struct dentry *d;
+       int err = -ENOMEM;
+
+       d = debugfs_create_dir("clock", NULL);
+       if (!d)
+               return -ENOMEM;
+       clk_debugfs_root = d;
+
+       d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
+               &clock_tree_fops);
+       if (!d)
+               goto err_out;
+
+       list_for_each_entry(c, &clocks, node) {
+               err = clk_debugfs_register(c);
+               if (err)
+                       goto err_out;
+       }
+       return 0;
+err_out:
+       debugfs_remove_recursive(clk_debugfs_root);
+       return err;
+}
+
+late_initcall(clk_debugfs_init);
+#endif
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
new file mode 100644 (file)
index 0000000..af7c70e
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * arch/arm/mach-tegra/include/mach/clock.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_CLOCK_H
+#define __MACH_TEGRA_CLOCK_H
+
+#include <linux/list.h>
+#include <asm/clkdev.h>
+
+#define DIV_BUS                        (1 << 0)
+#define DIV_U71                        (1 << 1)
+#define DIV_U71_FIXED          (1 << 2)
+#define DIV_2                  (1 << 3)
+#define PLL_FIXED              (1 << 4)
+#define PLL_HAS_CPCON          (1 << 5)
+#define MUX                    (1 << 6)
+#define PLLD                   (1 << 7)
+#define PERIPH_NO_RESET                (1 << 8)
+#define PERIPH_NO_ENB          (1 << 9)
+#define PERIPH_EMC_ENB         (1 << 10)
+#define PERIPH_MANUAL_RESET    (1 << 11)
+#define PLL_ALT_MISC_REG       (1 << 12)
+#define ENABLE_ON_INIT         (1 << 28)
+
+struct clk;
+
+struct clk_mux_sel {
+       struct clk      *input;
+       u32             value;
+};
+
+struct clk_pll_table {
+       unsigned long   input_rate;
+       unsigned long   output_rate;
+       u16             n;
+       u16             m;
+       u8              p;
+       u8              cpcon;
+};
+
+struct clk_ops {
+       void            (*init)(struct clk *);
+       int             (*enable)(struct clk *);
+       void            (*disable)(struct clk *);
+       void            (*recalc)(struct clk *);
+       int             (*set_parent)(struct clk *, struct clk *);
+       int             (*set_rate)(struct clk *, unsigned long);
+       unsigned long   (*get_rate)(struct clk *);
+       long            (*round_rate)(struct clk *, unsigned long);
+       unsigned long   (*recalculate_rate)(struct clk *);
+};
+
+enum clk_state {
+       UNINITIALIZED = 0,
+       ON,
+       OFF,
+};
+
+struct clk {
+       /* node for master clocks list */
+       struct list_head                node;
+       struct list_head                children;       /* list of children */
+       struct list_head                sibling;        /* node for children */
+#ifdef CONFIG_DEBUG_FS
+       struct dentry                   *dent;
+       struct dentry                   *parent_dent;
+#endif
+       struct clk_ops                  *ops;
+       struct clk                      *parent;
+       struct clk_lookup               lookup;
+       unsigned long                   rate;
+       u32                             flags;
+       u32                             refcnt;
+       const char                      *name;
+       u32                             reg;
+       u32                             reg_shift;
+       unsigned int                    clk_num;
+       enum clk_state                  state;
+#ifdef CONFIG_DEBUG_FS
+       bool                            set;
+#endif
+
+       /* PLL */
+       unsigned long                   input_min;
+       unsigned long                   input_max;
+       unsigned long                   cf_min;
+       unsigned long                   cf_max;
+       unsigned long                   vco_min;
+       unsigned long                   vco_max;
+       u32                             m;
+       u32                             n;
+       u32                             p;
+       u32                             cpcon;
+       const struct clk_pll_table      *pll_table;
+
+       /* DIV */
+       u32                             div;
+       u32                             mul;
+
+       /* MUX */
+       const struct clk_mux_sel        *inputs;
+       u32                             sel;
+       u32                             reg_mask;
+};
+
+
+struct clk_duplicate {
+       const char *name;
+       struct clk_lookup lookup;
+};
+
+struct tegra_clk_init_table {
+       const char *name;
+       const char *parent;
+       unsigned long rate;
+       bool enabled;
+};
+
+void tegra2_init_clocks(void);
+void tegra2_periph_reset_deassert(struct clk *c);
+void tegra2_periph_reset_assert(struct clk *c);
+void clk_init(struct clk *clk);
+struct clk *tegra_get_clock_by_name(const char *name);
+unsigned long clk_measure_input_freq(void);
+void clk_disable_locked(struct clk *c);
+int clk_enable_locked(struct clk *c);
+int clk_set_parent_locked(struct clk *c, struct clk *parent);
+int clk_reparent(struct clk *c, struct clk *parent);
+void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
+
+#endif
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
new file mode 100644 (file)
index 0000000..039a514
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/mach-tegra/board-harmony.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/hardware/cache-l2x0.h>
+
+#include <mach/iomap.h>
+
+#include "board.h"
+#include "clock.h"
+
+static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
+       /* name         parent          rate            enabled */
+       { "clk_m",      NULL,           0,              true },
+       { "pll_p",      "clk_m",        216000000,      true },
+       { "pll_p_out1", "pll_p",        28800000,       true },
+       { "pll_p_out2", "pll_p",        48000000,       true },
+       { "pll_p_out3", "pll_p",        72000000,       true },
+       { "pll_p_out4", "pll_p",        108000000,      true },
+       { "sys",        "pll_p_out4",   108000000,      true },
+       { "hclk",       "sys",          108000000,      true },
+       { "pclk",       "hclk",         54000000,       true },
+       { NULL,         NULL,           0,              0},
+};
+
+void __init tegra_init_cache(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+       void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
+
+       writel(0x331, p + L2X0_TAG_LATENCY_CTRL);
+       writel(0x441, p + L2X0_DATA_LATENCY_CTRL);
+
+       l2x0_init(p, 0x6C080001, 0x8200c3fe);
+#endif
+}
+
+void __init tegra_common_init(void)
+{
+       tegra_init_clock();
+       tegra_clk_init_from_table(common_clk_init_table);
+       tegra_init_cache();
+}
diff --git a/arch/arm/mach-tegra/gpio-names.h b/arch/arm/mach-tegra/gpio-names.h
new file mode 100644 (file)
index 0000000..f28220a
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * arch/arm/mach-tegra/include/mach/gpio-names.h
+ *
+ * Copyright (c) 2010 Google, Inc
+ *
+ * Author:
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef __MACH_TEGRA_GPIO_NAMES_H
+#define __MACH_TEGRA_GPIO_NAMES_H
+
+#define TEGRA_GPIO_PA0         0
+#define TEGRA_GPIO_PA1         1
+#define TEGRA_GPIO_PA2         2
+#define TEGRA_GPIO_PA3         3
+#define TEGRA_GPIO_PA4         4
+#define TEGRA_GPIO_PA5         5
+#define TEGRA_GPIO_PA6         6
+#define TEGRA_GPIO_PA7         7
+#define TEGRA_GPIO_PB0         8
+#define TEGRA_GPIO_PB1         9
+#define TEGRA_GPIO_PB2         10
+#define TEGRA_GPIO_PB3         11
+#define TEGRA_GPIO_PB4         12
+#define TEGRA_GPIO_PB5         13
+#define TEGRA_GPIO_PB6         14
+#define TEGRA_GPIO_PB7         15
+#define TEGRA_GPIO_PC0         16
+#define TEGRA_GPIO_PC1         17
+#define TEGRA_GPIO_PC2         18
+#define TEGRA_GPIO_PC3         19
+#define TEGRA_GPIO_PC4         20
+#define TEGRA_GPIO_PC5         21
+#define TEGRA_GPIO_PC6         22
+#define TEGRA_GPIO_PC7         23
+#define TEGRA_GPIO_PD0         24
+#define TEGRA_GPIO_PD1         25
+#define TEGRA_GPIO_PD2         26
+#define TEGRA_GPIO_PD3         27
+#define TEGRA_GPIO_PD4         28
+#define TEGRA_GPIO_PD5         29
+#define TEGRA_GPIO_PD6         30
+#define TEGRA_GPIO_PD7         31
+#define TEGRA_GPIO_PE0         32
+#define TEGRA_GPIO_PE1         33
+#define TEGRA_GPIO_PE2         34
+#define TEGRA_GPIO_PE3         35
+#define TEGRA_GPIO_PE4         36
+#define TEGRA_GPIO_PE5         37
+#define TEGRA_GPIO_PE6         38
+#define TEGRA_GPIO_PE7         39
+#define TEGRA_GPIO_PF0         40
+#define TEGRA_GPIO_PF1         41
+#define TEGRA_GPIO_PF2         42
+#define TEGRA_GPIO_PF3         43
+#define TEGRA_GPIO_PF4         44
+#define TEGRA_GPIO_PF5         45
+#define TEGRA_GPIO_PF6         46
+#define TEGRA_GPIO_PF7         47
+#define TEGRA_GPIO_PG0         48
+#define TEGRA_GPIO_PG1         49
+#define TEGRA_GPIO_PG2         50
+#define TEGRA_GPIO_PG3         51
+#define TEGRA_GPIO_PG4         52
+#define TEGRA_GPIO_PG5         53
+#define TEGRA_GPIO_PG6         54
+#define TEGRA_GPIO_PG7         55
+#define TEGRA_GPIO_PH0         56
+#define TEGRA_GPIO_PH1         57
+#define TEGRA_GPIO_PH2         58
+#define TEGRA_GPIO_PH3         59
+#define TEGRA_GPIO_PH4         60
+#define TEGRA_GPIO_PH5         61
+#define TEGRA_GPIO_PH6         62
+#define TEGRA_GPIO_PH7         63
+#define TEGRA_GPIO_PI0         64
+#define TEGRA_GPIO_PI1         65
+#define TEGRA_GPIO_PI2         66
+#define TEGRA_GPIO_PI3         67
+#define TEGRA_GPIO_PI4         68
+#define TEGRA_GPIO_PI5         69
+#define TEGRA_GPIO_PI6         70
+#define TEGRA_GPIO_PI7         71
+#define TEGRA_GPIO_PJ0         72
+#define TEGRA_GPIO_PJ1         73
+#define TEGRA_GPIO_PJ2         74
+#define TEGRA_GPIO_PJ3         75
+#define TEGRA_GPIO_PJ4         76
+#define TEGRA_GPIO_PJ5         77
+#define TEGRA_GPIO_PJ6         78
+#define TEGRA_GPIO_PJ7         79
+#define TEGRA_GPIO_PK0         80
+#define TEGRA_GPIO_PK1         81
+#define TEGRA_GPIO_PK2         82
+#define TEGRA_GPIO_PK3         83
+#define TEGRA_GPIO_PK4         84
+#define TEGRA_GPIO_PK5         85
+#define TEGRA_GPIO_PK6         86
+#define TEGRA_GPIO_PK7         87
+#define TEGRA_GPIO_PL0         88
+#define TEGRA_GPIO_PL1         89
+#define TEGRA_GPIO_PL2         90
+#define TEGRA_GPIO_PL3         91
+#define TEGRA_GPIO_PL4         92
+#define TEGRA_GPIO_PL5         93
+#define TEGRA_GPIO_PL6         94
+#define TEGRA_GPIO_PL7         95
+#define TEGRA_GPIO_PM0         96
+#define TEGRA_GPIO_PM1         97
+#define TEGRA_GPIO_PM2         98
+#define TEGRA_GPIO_PM3         99
+#define TEGRA_GPIO_PM4         100
+#define TEGRA_GPIO_PM5         101
+#define TEGRA_GPIO_PM6         102
+#define TEGRA_GPIO_PM7         103
+#define TEGRA_GPIO_PN0         104
+#define TEGRA_GPIO_PN1         105
+#define TEGRA_GPIO_PN2         106
+#define TEGRA_GPIO_PN3         107
+#define TEGRA_GPIO_PN4         108
+#define TEGRA_GPIO_PN5         109
+#define TEGRA_GPIO_PN6         110
+#define TEGRA_GPIO_PN7         111
+#define TEGRA_GPIO_PO0         112
+#define TEGRA_GPIO_PO1         113
+#define TEGRA_GPIO_PO2         114
+#define TEGRA_GPIO_PO3         115
+#define TEGRA_GPIO_PO4         116
+#define TEGRA_GPIO_PO5         117
+#define TEGRA_GPIO_PO6         118
+#define TEGRA_GPIO_PO7         119
+#define TEGRA_GPIO_PP0         120
+#define TEGRA_GPIO_PP1         121
+#define TEGRA_GPIO_PP2         122
+#define TEGRA_GPIO_PP3         123
+#define TEGRA_GPIO_PP4         124
+#define TEGRA_GPIO_PP5         125
+#define TEGRA_GPIO_PP6         126
+#define TEGRA_GPIO_PP7         127
+#define TEGRA_GPIO_PQ0         128
+#define TEGRA_GPIO_PQ1         129
+#define TEGRA_GPIO_PQ2         130
+#define TEGRA_GPIO_PQ3         131
+#define TEGRA_GPIO_PQ4         132
+#define TEGRA_GPIO_PQ5         133
+#define TEGRA_GPIO_PQ6         134
+#define TEGRA_GPIO_PQ7         135
+#define TEGRA_GPIO_PR0         136
+#define TEGRA_GPIO_PR1         137
+#define TEGRA_GPIO_PR2         138
+#define TEGRA_GPIO_PR3         139
+#define TEGRA_GPIO_PR4         140
+#define TEGRA_GPIO_PR5         141
+#define TEGRA_GPIO_PR6         142
+#define TEGRA_GPIO_PR7         143
+#define TEGRA_GPIO_PS0         144
+#define TEGRA_GPIO_PS1         145
+#define TEGRA_GPIO_PS2         146
+#define TEGRA_GPIO_PS3         147
+#define TEGRA_GPIO_PS4         148
+#define TEGRA_GPIO_PS5         149
+#define TEGRA_GPIO_PS6         150
+#define TEGRA_GPIO_PS7         151
+#define TEGRA_GPIO_PT0         152
+#define TEGRA_GPIO_PT1         153
+#define TEGRA_GPIO_PT2         154
+#define TEGRA_GPIO_PT3         155
+#define TEGRA_GPIO_PT4         156
+#define TEGRA_GPIO_PT5         157
+#define TEGRA_GPIO_PT6         158
+#define TEGRA_GPIO_PT7         159
+#define TEGRA_GPIO_PU0         160
+#define TEGRA_GPIO_PU1         161
+#define TEGRA_GPIO_PU2         162
+#define TEGRA_GPIO_PU3         163
+#define TEGRA_GPIO_PU4         164
+#define TEGRA_GPIO_PU5         165
+#define TEGRA_GPIO_PU6         166
+#define TEGRA_GPIO_PU7         167
+#define TEGRA_GPIO_PV0         168
+#define TEGRA_GPIO_PV1         169
+#define TEGRA_GPIO_PV2         170
+#define TEGRA_GPIO_PV3         171
+#define TEGRA_GPIO_PV4         172
+#define TEGRA_GPIO_PV5         173
+#define TEGRA_GPIO_PV6         174
+#define TEGRA_GPIO_PV7         175
+#define TEGRA_GPIO_PW0         176
+#define TEGRA_GPIO_PW1         177
+#define TEGRA_GPIO_PW2         178
+#define TEGRA_GPIO_PW3         179
+#define TEGRA_GPIO_PW4         180
+#define TEGRA_GPIO_PW5         181
+#define TEGRA_GPIO_PW6         182
+#define TEGRA_GPIO_PW7         183
+#define TEGRA_GPIO_PX0         184
+#define TEGRA_GPIO_PX1         185
+#define TEGRA_GPIO_PX2         186
+#define TEGRA_GPIO_PX3         187
+#define TEGRA_GPIO_PX4         188
+#define TEGRA_GPIO_PX5         189
+#define TEGRA_GPIO_PX6         190
+#define TEGRA_GPIO_PX7         191
+#define TEGRA_GPIO_PY0         192
+#define TEGRA_GPIO_PY1         193
+#define TEGRA_GPIO_PY2         194
+#define TEGRA_GPIO_PY3         195
+#define TEGRA_GPIO_PY4         196
+#define TEGRA_GPIO_PY5         197
+#define TEGRA_GPIO_PY6         198
+#define TEGRA_GPIO_PY7         199
+#define TEGRA_GPIO_PZ0         200
+#define TEGRA_GPIO_PZ1         201
+#define TEGRA_GPIO_PZ2         202
+#define TEGRA_GPIO_PZ3         203
+#define TEGRA_GPIO_PZ4         204
+#define TEGRA_GPIO_PZ5         205
+#define TEGRA_GPIO_PZ6         206
+#define TEGRA_GPIO_PZ7         207
+#define TEGRA_GPIO_PAA0                208
+#define TEGRA_GPIO_PAA1                209
+#define TEGRA_GPIO_PAA2                210
+#define TEGRA_GPIO_PAA3                211
+#define TEGRA_GPIO_PAA4                212
+#define TEGRA_GPIO_PAA5                213
+#define TEGRA_GPIO_PAA6                214
+#define TEGRA_GPIO_PAA7                215
+#define TEGRA_GPIO_PBB0                216
+#define TEGRA_GPIO_PBB1                217
+#define TEGRA_GPIO_PBB2                218
+#define TEGRA_GPIO_PBB3                219
+#define TEGRA_GPIO_PBB4                220
+#define TEGRA_GPIO_PBB5                221
+#define TEGRA_GPIO_PBB6                222
+#define TEGRA_GPIO_PBB7                223
+
+#endif
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c
new file mode 100644 (file)
index 0000000..fe78fba
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * arch/arm/mach-tegra/gpio.c
+ *
+ * Copyright (c) 2010 Google, Inc
+ *
+ * Author:
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/iomap.h>
+
+#define GPIO_BANK(x)           ((x) >> 5)
+#define GPIO_PORT(x)           (((x) >> 3) & 0x3)
+#define GPIO_BIT(x)            ((x) & 0x7)
+
+#define GPIO_REG(x)            (IO_TO_VIRT(TEGRA_GPIO_BASE) +  \
+                                GPIO_BANK(x) * 0x80 +          \
+                                GPIO_PORT(x) * 4)
+
+#define GPIO_CNF(x)            (GPIO_REG(x) + 0x00)
+#define GPIO_OE(x)             (GPIO_REG(x) + 0x10)
+#define GPIO_OUT(x)            (GPIO_REG(x) + 0X20)
+#define GPIO_IN(x)             (GPIO_REG(x) + 0x30)
+#define GPIO_INT_STA(x)                (GPIO_REG(x) + 0x40)
+#define GPIO_INT_ENB(x)                (GPIO_REG(x) + 0x50)
+#define GPIO_INT_LVL(x)                (GPIO_REG(x) + 0x60)
+#define GPIO_INT_CLR(x)                (GPIO_REG(x) + 0x70)
+
+#define GPIO_MSK_CNF(x)                (GPIO_REG(x) + 0x800)
+#define GPIO_MSK_OE(x)         (GPIO_REG(x) + 0x810)
+#define GPIO_MSK_OUT(x)                (GPIO_REG(x) + 0X820)
+#define GPIO_MSK_INT_STA(x)    (GPIO_REG(x) + 0x840)
+#define GPIO_MSK_INT_ENB(x)    (GPIO_REG(x) + 0x850)
+#define GPIO_MSK_INT_LVL(x)    (GPIO_REG(x) + 0x860)
+
+#define GPIO_INT_LVL_MASK              0x010101
+#define GPIO_INT_LVL_EDGE_RISING       0x000101
+#define GPIO_INT_LVL_EDGE_FALLING      0x000100
+#define GPIO_INT_LVL_EDGE_BOTH         0x010100
+#define GPIO_INT_LVL_LEVEL_HIGH                0x000001
+#define GPIO_INT_LVL_LEVEL_LOW         0x000000
+
+struct tegra_gpio_bank {
+       int bank;
+       int irq;
+       spinlock_t lvl_lock[4];
+};
+
+
+static struct tegra_gpio_bank tegra_gpio_banks[] = {
+       {.bank = 0, .irq = INT_GPIO1},
+       {.bank = 1, .irq = INT_GPIO2},
+       {.bank = 2, .irq = INT_GPIO3},
+       {.bank = 3, .irq = INT_GPIO4},
+       {.bank = 4, .irq = INT_GPIO5},
+       {.bank = 5, .irq = INT_GPIO6},
+       {.bank = 6, .irq = INT_GPIO7},
+};
+
+static int tegra_gpio_compose(int bank, int port, int bit)
+{
+       return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
+}
+
+static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
+{
+       u32 val;
+
+       val = 0x100 << GPIO_BIT(gpio);
+       if (value)
+               val |= 1 << GPIO_BIT(gpio);
+       __raw_writel(val, reg);
+}
+
+void tegra_gpio_enable(int gpio)
+{
+       tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
+}
+
+void tegra_gpio_disable(int gpio)
+{
+       tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
+}
+
+static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value);
+}
+
+static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
+}
+
+static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0);
+       return 0;
+}
+
+static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                                       int value)
+{
+       tegra_gpio_set(chip, offset, value);
+       tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1);
+       return 0;
+}
+
+
+
+static struct gpio_chip tegra_gpio_chip = {
+       .label                  = "tegra-gpio",
+       .direction_input        = tegra_gpio_direction_input,
+       .get                    = tegra_gpio_get,
+       .direction_output       = tegra_gpio_direction_output,
+       .set                    = tegra_gpio_set,
+       .base                   = 0,
+       .ngpio                  = ARCH_NR_GPIOS,
+};
+
+static void tegra_gpio_irq_ack(unsigned int irq)
+{
+       int gpio = irq - INT_GPIO_BASE;
+
+       __raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+}
+
+static void tegra_gpio_irq_mask(unsigned int irq)
+{
+       int gpio = irq - INT_GPIO_BASE;
+
+       tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0);
+}
+
+static void tegra_gpio_irq_unmask(unsigned int irq)
+{
+       int gpio = irq - INT_GPIO_BASE;
+
+       tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1);
+}
+
+static int tegra_gpio_irq_set_type(unsigned int irq, unsigned int type)
+{
+       int gpio = irq - INT_GPIO_BASE;
+       struct tegra_gpio_bank *bank = get_irq_chip_data(irq);
+       int port = GPIO_PORT(gpio);
+       int lvl_type;
+       int val;
+       unsigned long flags;
+
+       switch (type & IRQ_TYPE_SENSE_MASK) {
+       case IRQ_TYPE_EDGE_RISING:
+               lvl_type = GPIO_INT_LVL_EDGE_RISING;
+               break;
+
+       case IRQ_TYPE_EDGE_FALLING:
+               lvl_type = GPIO_INT_LVL_EDGE_FALLING;
+               break;
+
+       case IRQ_TYPE_EDGE_BOTH:
+               lvl_type = GPIO_INT_LVL_EDGE_BOTH;
+               break;
+
+       case IRQ_TYPE_LEVEL_HIGH:
+               lvl_type = GPIO_INT_LVL_LEVEL_HIGH;
+               break;
+
+       case IRQ_TYPE_LEVEL_LOW:
+               lvl_type = GPIO_INT_LVL_LEVEL_LOW;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&bank->lvl_lock[port], flags);
+
+       val = __raw_readl(GPIO_INT_LVL(gpio));
+       val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
+       val |= lvl_type << GPIO_BIT(gpio);
+       __raw_writel(val, GPIO_INT_LVL(gpio));
+
+       spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
+
+       if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+               __set_irq_handler_unlocked(irq, handle_level_irq);
+       else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+               __set_irq_handler_unlocked(irq, handle_edge_irq);
+
+       return 0;
+}
+
+static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct tegra_gpio_bank *bank;
+       int port;
+       int pin;
+       int unmasked = 0;
+
+       desc->chip->ack(irq);
+
+       bank = get_irq_data(irq);
+
+       for (port = 0; port < 4; port++) {
+               int gpio = tegra_gpio_compose(bank->bank, port, 0);
+               unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) &
+                       __raw_readl(GPIO_INT_ENB(gpio));
+               u32 lvl = __raw_readl(GPIO_INT_LVL(gpio));
+
+               for_each_set_bit(pin, &sta, 8) {
+                       __raw_writel(1 << pin, GPIO_INT_CLR(gpio));
+
+                       /* if gpio is edge triggered, clear condition
+                        * before executing the hander so that we don't
+                        * miss edges
+                        */
+                       if (lvl & (0x100 << pin)) {
+                               unmasked = 1;
+                               desc->chip->unmask(irq);
+                       }
+
+                       generic_handle_irq(gpio_to_irq(gpio + pin));
+               }
+       }
+
+       if (!unmasked)
+               desc->chip->unmask(irq);
+
+}
+
+
+static struct irq_chip tegra_gpio_irq_chip = {
+       .name           = "GPIO",
+       .ack            = tegra_gpio_irq_ack,
+       .mask           = tegra_gpio_irq_mask,
+       .unmask         = tegra_gpio_irq_unmask,
+       .set_type       = tegra_gpio_irq_set_type,
+};
+
+
+/* This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int __init tegra_gpio_init(void)
+{
+       struct tegra_gpio_bank *bank;
+       int i;
+       int j;
+
+       for (i = 0; i < 7; i++) {
+               for (j = 0; j < 4; j++) {
+                       int gpio = tegra_gpio_compose(i, j, 0);
+                       __raw_writel(0x00, GPIO_INT_ENB(gpio));
+               }
+       }
+
+       gpiochip_add(&tegra_gpio_chip);
+
+       for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) {
+               bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
+
+               lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class);
+               set_irq_chip_data(i, bank);
+               set_irq_chip(i, &tegra_gpio_irq_chip);
+               set_irq_handler(i, handle_simple_irq);
+               set_irq_flags(i, IRQF_VALID);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
+               bank = &tegra_gpio_banks[i];
+
+               set_irq_chained_handler(bank->irq, tegra_gpio_irq_handler);
+               set_irq_data(bank->irq, bank);
+
+               for (j = 0; j < 4; j++)
+                       spin_lock_init(&bank->lvl_lock[j]);
+       }
+
+       return 0;
+}
+
+postcore_initcall(tegra_gpio_init);
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static int dbg_gpio_show(struct seq_file *s, void *unused)
+{
+       int i;
+       int j;
+
+       for (i = 0; i < 7; i++) {
+               for (j = 0; j < 4; j++) {
+                       int gpio = tegra_gpio_compose(i, j, 0);
+                       seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
+                              i, j,
+                              __raw_readl(GPIO_CNF(gpio)),
+                              __raw_readl(GPIO_OE(gpio)),
+                              __raw_readl(GPIO_OUT(gpio)),
+                              __raw_readl(GPIO_IN(gpio)),
+                              __raw_readl(GPIO_INT_STA(gpio)),
+                              __raw_readl(GPIO_INT_ENB(gpio)),
+                              __raw_readl(GPIO_INT_LVL(gpio)));
+               }
+       }
+       return 0;
+}
+
+static int dbg_gpio_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dbg_gpio_show, &inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+       .open           = dbg_gpio_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int __init tegra_gpio_debuginit(void)
+{
+       (void) debugfs_create_file("tegra_gpio", S_IRUGO,
+                                       NULL, NULL, &debug_fops);
+       return 0;
+}
+late_initcall(tegra_gpio_debuginit);
+#endif
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
new file mode 100644 (file)
index 0000000..b5349b2
--- /dev/null
@@ -0,0 +1,61 @@
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+        .section ".text.head", "ax"
+       __CPUINIT
+
+/*
+ * Tegra specific entry point for secondary CPUs.
+ *   The secondary kernel init calls v7_flush_dcache_all before it enables
+ *   the L1; however, the L1 comes out of reset in an undefined state, so
+ *   the clean + invalidate performed by v7_flush_dcache_all causes a bunch
+ *   of cache lines with uninitialized data and uninitialized tags to get
+ *   written out to memory, which does really unpleasant things to the main
+ *   processor.  We fix this by performing an invalidate, rather than a
+ *   clean + invalidate, before jumping into the kernel.
+ */
+ENTRY(v7_invalidate_l1)
+        mov     r0, #0
+        mcr     p15, 2, r0, c0, c0, 0
+        mrc     p15, 1, r0, c0, c0, 0
+
+        ldr     r1, =0x7fff
+        and     r2, r1, r0, lsr #13
+
+        ldr     r1, =0x3ff
+
+        and     r3, r1, r0, lsr #3  @ NumWays - 1
+        add     r2, r2, #1          @ NumSets
+
+        and     r0, r0, #0x7
+        add     r0, r0, #4          @ SetShift
+
+        clz     r1, r3              @ WayShift
+        add     r4, r3, #1          @ NumWays
+1:      sub     r2, r2, #1          @ NumSets--
+        mov     r3, r4              @ Temp = NumWays
+2:      subs    r3, r3, #1          @ Temp--
+        mov     r5, r3, lsl r1
+        mov     r6, r2, lsl r0
+        orr     r5, r5, r6          @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
+        mcr     p15, 0, r5, c7, c6, 2
+        bgt     2b
+        cmp     r2, #0
+        bgt     1b
+        dsb
+        isb
+        mov     pc, lr
+ENDPROC(v7_invalidate_l1)
+
+ENTRY(tegra_secondary_startup)
+       msr     cpsr_fsxc, #0xd3
+        bl      v7_invalidate_l1
+       mrc     p15, 0, r0, c0, c0, 5
+        and    r0, r0, #15
+        ldr     r1, =0x6000f100
+        str     r0, [r1]
+1:      ldr     r2, [r1]
+        cmp     r0, r2
+        beq     1b
+        b       secondary_startup
+ENDPROC(tegra_secondary_startup)
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
new file mode 100644 (file)
index 0000000..8e7f115
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *  linux/arch/arm/mach-realview/hotplug.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/completion.h>
+
+#include <asm/cacheflush.h>
+
+static DECLARE_COMPLETION(cpu_killed);
+
+static inline void cpu_enter_lowpower(void)
+{
+       unsigned int v;
+
+       flush_cache_all();
+       asm volatile(
+       "       mcr     p15, 0, %1, c7, c5, 0\n"
+       "       mcr     p15, 0, %1, c7, c10, 4\n"
+       /*
+        * Turn off coherency
+        */
+       "       mrc     p15, 0, %0, c1, c0, 1\n"
+       "       bic     %0, %0, #0x20\n"
+       "       mcr     p15, 0, %0, c1, c0, 1\n"
+       "       mrc     p15, 0, %0, c1, c0, 0\n"
+       "       bic     %0, %0, #0x04\n"
+       "       mcr     p15, 0, %0, c1, c0, 0\n"
+         : "=&r" (v)
+         : "r" (0)
+         : "cc");
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+       unsigned int v;
+
+       asm volatile(
+       "mrc    p15, 0, %0, c1, c0, 0\n"
+       "       orr     %0, %0, #0x04\n"
+       "       mcr     p15, 0, %0, c1, c0, 0\n"
+       "       mrc     p15, 0, %0, c1, c0, 1\n"
+       "       orr     %0, %0, #0x20\n"
+       "       mcr     p15, 0, %0, c1, c0, 1\n"
+         : "=&r" (v)
+         :
+         : "cc");
+}
+
+static inline void platform_do_lowpower(unsigned int cpu)
+{
+       /*
+        * there is no power-control hardware on this platform, so all
+        * we can do is put the core into WFI; this is safe as the calling
+        * code will have already disabled interrupts
+        */
+       for (;;) {
+               /*
+                * here's the WFI
+                */
+               asm(".word      0xe320f003\n"
+                   :
+                   :
+                   : "memory", "cc");
+
+               /*if (pen_release == cpu) {*/
+                       /*
+                        * OK, proper wakeup, we're done
+                        */
+                       break;
+               /*}*/
+
+               /*
+                * getting here, means that we have come out of WFI without
+                * having been woken up - this shouldn't happen
+                *
+                * The trouble is, letting people know about this is not really
+                * possible, since we are currently running incoherently, and
+                * therefore cannot safely call printk() or anything else
+                */
+#ifdef DEBUG
+               printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
+#endif
+       }
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+       return wait_for_completion_timeout(&cpu_killed, 5000);
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+#ifdef DEBUG
+       unsigned int this_cpu = hard_smp_processor_id();
+
+       if (cpu != this_cpu) {
+               printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
+                          this_cpu, cpu);
+               BUG();
+       }
+#endif
+
+       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
+       complete(&cpu_killed);
+
+       /*
+        * we're ready for shutdown now, so do it
+        */
+       cpu_enter_lowpower();
+       platform_do_lowpower(cpu);
+
+       /*
+        * bring this CPU back into the world of cache
+        * coherency, and then restore interrupts
+        */
+       cpu_leave_lowpower();
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+       /*
+        * we don't allow CPU 0 to be shutdown (it is still too special
+        * e.g. clock tick interrupts)
+        */
+       return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-tegra/include/mach/barriers.h b/arch/arm/mach-tegra/include/mach/barriers.h
new file mode 100644 (file)
index 0000000..cc11517
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * arch/arm/mach-realview/include/mach/barriers.h
+ *
+ * Copyright (C) 2010 ARM Ltd.
+ * Written by Catalin Marinas <catalin.marinas@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __MACH_BARRIERS_H
+#define __MACH_BARRIERS_H
+
+#include <asm/outercache.h>
+
+#define rmb()          dmb()
+#define wmb()          do { dsb(); outer_sync(); } while (0)
+#define mb()           wmb()
+
+#endif /* __MACH_BARRIERS_H */
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h
new file mode 100644 (file)
index 0000000..2896f25
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * arch/arm/mach-tegra/include/mach/clk.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_CLK_H
+#define __MACH_CLK_H
+
+void tegra_periph_reset_deassert(struct clk *c);
+void tegra_periph_reset_assert(struct clk *c);
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/clkdev.h b/arch/arm/mach-tegra/include/mach/clkdev.h
new file mode 100644 (file)
index 0000000..412f5c6
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-tegra/include/mach/clkdev.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_CLKDEV_H
+#define __MACH_CLKDEV_H
+
+static inline int __clk_get(struct clk *clk)
+{
+       return 1;
+}
+
+static inline void __clk_put(struct clk *clk)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S
new file mode 100644 (file)
index 0000000..55a3956
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * arch/arm/mach-tegra/include/mach/debug-macro.S
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <mach/io.h>
+
+       .macro  addruart,rx, tmp
+        mrc     p15, 0, \rx, c1, c0
+        tst     \rx, #1                 @ MMU enabled?
+        ldreq   \rx, =IO_APB_PHYS       @ physical
+        ldrne   \rx, =IO_APB_VIRT        @ virtual
+#if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
+#error "A debug UART must be selected in the kernel config to use DEBUG_LL"
+#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
+        orr     \rx, \rx, #0x6000
+#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
+       ldr     \tmp, =0x6040
+        orr     \rx, \rx, \tmp
+#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
+        orr     \rx, \rx, #0x6200
+#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
+        orr     \rx, \rx, #0x6300
+#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
+        orr     \rx, \rx, #0x6400
+#endif
+       .endm
+
+#define UART_SHIFT     2
+#include <asm/hardware/debug-8250.S>
+
diff --git a/arch/arm/mach-tegra/include/mach/entry-macro.S b/arch/arm/mach-tegra/include/mach/entry-macro.S
new file mode 100644 (file)
index 0000000..2ba9e5c
--- /dev/null
@@ -0,0 +1,118 @@
+/* arch/arm/mach-tegra/include/mach/entry-macro.S
+ *
+ * Copyright (C) 2009 Palm, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+#include <mach/iomap.h>
+#include <mach/io.h>
+
+#if defined(CONFIG_ARM_GIC)
+
+#include <asm/hardware/gic.h>
+
+       /* Uses the GIC interrupt controller built into the cpu */
+#define ICTRL_BASE (IO_CPU_VIRT + 0x100)
+
+       .macro  disable_fiq
+       .endm
+
+       .macro  get_irqnr_preamble, base, tmp
+       movw \base, #(ICTRL_BASE & 0x0000ffff)
+       movt \base, #((ICTRL_BASE & 0xffff0000) >> 16)
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
+       /*
+        * The interrupt numbering scheme is defined in the
+        * interrupt controller spec.  To wit:
+        *
+        * Interrupts 0-15 are IPI
+        * 16-28 are reserved
+        * 29-31 are local.  We allow 30 to be used for the watchdog.
+        * 32-1020 are global
+        * 1021-1022 are reserved
+        * 1023 is "spurious" (no interrupt)
+        *
+        * For now, we ignore all local interrupts so only return an interrupt
+        * if it's between 30 and 1020.  The test_for_ipi routine below will
+        * pick up on IPIs.
+        *
+        * A simple read from the controller will tell us the number of the
+        * highest priority enabled interrupt.  We then just need to check
+        * whether it is in the valid range for an IRQ (30-1020 inclusive).
+        */
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+       /* bits 12-10 = src CPU, 9-0 = int # */
+       ldr     \irqstat, [\base, #GIC_CPU_INTACK]
+
+       ldr             \tmp, =1021
+
+       bic     \irqnr, \irqstat, #0x1c00
+
+       cmp     \irqnr, #29
+       cmpcc   \irqnr, \irqnr
+       cmpne   \irqnr, \tmp
+       cmpcs   \irqnr, \irqnr
+
+       .endm
+
+       /* We assume that irqstat (the raw value of the IRQ acknowledge
+        * register) is preserved from the macro above.
+        * If there is an IPI, we immediately signal end of interrupt on the
+        * controller, since this requires the original irqstat value which
+        * we won't easily be able to recreate later.
+        */
+
+       .macro test_for_ipi, irqnr, irqstat, base, tmp
+       bic     \irqnr, \irqstat, #0x1c00
+       cmp     \irqnr, #16
+       strcc   \irqstat, [\base, #GIC_CPU_EOI]
+       cmpcs   \irqnr, \irqnr
+       .endm
+
+       /* As above, this assumes that irqstat and base are preserved.. */
+
+       .macro test_for_ltirq, irqnr, irqstat, base, tmp
+       bic     \irqnr, \irqstat, #0x1c00
+       mov     \tmp, #0
+       cmp     \irqnr, #29
+       moveq   \tmp, #1
+       streq   \irqstat, [\base, #GIC_CPU_EOI]
+       cmp     \tmp, #0
+       .endm
+
+#else
+       /* legacy interrupt controller for AP16 */
+       .macro  disable_fiq
+       .endm
+
+       .macro  get_irqnr_preamble, base, tmp
+       @ enable imprecise aborts
+       cpsie   a
+       @ EVP base at 0xf010f000
+       mov \base, #0xf0000000
+       orr \base, #0x00100000
+       orr \base, #0x0000f000
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+       ldr \irqnr, [\base, #0x20]      @ EVT_IRQ_STS
+       cmp \irqnr, #0x80
+       .endm
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h
new file mode 100644 (file)
index 0000000..540e822
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * arch/arm/mach-tegra/include/mach/gpio.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_GPIO_H
+#define __MACH_TEGRA_GPIO_H
+
+#include <mach/irqs.h>
+
+#define ARCH_NR_GPIOS          INT_GPIO_NR
+
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value         __gpio_get_value
+#define gpio_set_value         __gpio_set_value
+#define gpio_cansleep          __gpio_cansleep
+
+#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
+#define TEGRA_IRQ_TO_GPIO(irq) ((gpio) - INT_GPIO_BASE)
+
+static inline int gpio_to_irq(unsigned int gpio)
+{
+       if (gpio < ARCH_NR_GPIOS)
+               return INT_GPIO_BASE + gpio;
+       return -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+       if ((irq >= INT_GPIO_BASE) && (irq < INT_GPIO_BASE + INT_GPIO_NR))
+               return irq - INT_GPIO_BASE;
+       return -EINVAL;
+}
+
+void tegra_gpio_enable(int gpio);
+void tegra_gpio_disable(int gpio);
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/hardware.h b/arch/arm/mach-tegra/include/mach/hardware.h
new file mode 100644 (file)
index 0000000..6014edf
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-tegra/include/mach/hardware.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_HARDWARE_H
+#define __MACH_TEGRA_HARDWARE_H
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/io.h b/arch/arm/mach-tegra/include/mach/io.h
new file mode 100644 (file)
index 0000000..35edfc3
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * arch/arm/mach-tegra/include/mach/io.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_IO_H
+#define __MACH_TEGRA_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/* On TEGRA, many peripherals are very closely packed in
+ * two 256MB io windows (that actually only use about 64KB
+ * at the start of each).
+ *
+ * We will just map the first 1MB of each window (to minimize
+ * pt entries needed) and provide a macro to transform physical
+ * io addresses to an appropriate void __iomem *.
+ *
+ */
+
+#define IO_CPU_PHYS     0x50040000
+#define IO_CPU_VIRT     0xFE000000
+#define IO_CPU_SIZE    SZ_16K
+
+#define IO_PPSB_PHYS   0x60000000
+#define IO_PPSB_VIRT   0xFE200000
+#define IO_PPSB_SIZE   SZ_1M
+
+#define IO_APB_PHYS    0x70000000
+#define IO_APB_VIRT    0xFE300000
+#define IO_APB_SIZE    SZ_1M
+
+#define IO_TO_VIRT_BETWEEN(p, st, sz)  ((p) >= (st) && (p) < ((st) + (sz)))
+#define IO_TO_VIRT_XLATE(p, pst, vst)  (((p) - (pst) + (vst)))
+
+#define IO_TO_VIRT(n) ( \
+       IO_TO_VIRT_BETWEEN((n), IO_PPSB_PHYS, IO_PPSB_SIZE) ?           \
+               IO_TO_VIRT_XLATE((n), IO_PPSB_PHYS, IO_PPSB_VIRT) :     \
+       IO_TO_VIRT_BETWEEN((n), IO_APB_PHYS, IO_APB_SIZE) ?             \
+               IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) :       \
+       IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ?             \
+               IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) :       \
+       0)
+
+#ifndef __ASSEMBLER__
+
+#define __arch_ioremap(p, s, t)        tegra_ioremap(p, s, t)
+#define __arch_iounmap(v)      tegra_iounmap(v)
+
+void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
+void tegra_iounmap(volatile void __iomem *addr);
+
+#define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n))
+
+static inline void __iomem *__io(unsigned long addr)
+{
+       return (void __iomem *)addr;
+}
+#define __io(a)         __io(a)
+#define __mem_pci(a)    (a)
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h
new file mode 100644 (file)
index 0000000..1741f7d
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * arch/arm/mach-tegra/include/mach/iomap.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_IOMAP_H
+#define __MACH_TEGRA_IOMAP_H
+
+#include <asm/sizes.h>
+
+#define TEGRA_ARM_PERIF_BASE           0x50040000
+#define TEGRA_ARM_PERIF_SIZE           SZ_8K
+
+#define TEGRA_ARM_INT_DIST_BASE                0x50041000
+#define TEGRA_ARM_INT_DIST_SIZE                SZ_4K
+
+#define TEGRA_DISPLAY_BASE             0x54200000
+#define TEGRA_DISPLAY_SIZE             SZ_256K
+
+#define TEGRA_DISPLAY2_BASE            0x54240000
+#define TEGRA_DISPLAY2_SIZE            SZ_256K
+
+#define TEGRA_PRIMARY_ICTLR_BASE       0x60004000
+#define TEGRA_PRIMARY_ICTLR_SIZE       SZ_64
+
+#define TEGRA_SECONDARY_ICTLR_BASE     0x60004100
+#define TEGRA_SECONDARY_ICTLR_SIZE     SZ_64
+
+#define TEGRA_TERTIARY_ICTLR_BASE      0x60004200
+#define TEGRA_TERTIARY_ICTLR_SIZE      SZ_64
+
+#define TEGRA_QUATERNARY_ICTLR_BASE    0x60004300
+#define TEGRA_QUATERNARY_ICTLR_SIZE    SZ_64
+
+#define TEGRA_TMR1_BASE                        0x60005000
+#define TEGRA_TMR1_SIZE                        SZ_8
+
+#define TEGRA_TMR2_BASE                        0x60005008
+#define TEGRA_TMR2_SIZE                        SZ_8
+
+#define TEGRA_TMRUS_BASE               0x60005010
+#define TEGRA_TMRUS_SIZE               SZ_64
+
+#define TEGRA_TMR3_BASE                        0x60005050
+#define TEGRA_TMR3_SIZE                        SZ_8
+
+#define TEGRA_TMR4_BASE                        0x60005058
+#define TEGRA_TMR4_SIZE                        SZ_8
+
+#define TEGRA_CLK_RESET_BASE           0x60006000
+#define TEGRA_CLK_RESET_SIZE           SZ_4K
+
+#define TEGRA_FLOW_CTRL_BASE           0x60007000
+#define TEGRA_FLOW_CTRL_SIZE           20
+
+#define TEGRA_STATMON_BASE             0x6000C4000
+#define TEGRA_STATMON_SIZE             SZ_1K
+
+#define TEGRA_GPIO_BASE                        0x6000D000
+#define TEGRA_GPIO_SIZE                        SZ_4K
+
+#define TEGRA_EXCEPTION_VECTORS_BASE    0x6000F000
+#define TEGRA_EXCEPTION_VECTORS_SIZE    SZ_4K
+
+#define TEGRA_APB_MISC_BASE            0x70000000
+#define TEGRA_APB_MISC_SIZE            SZ_4K
+
+#define TEGRA_AC97_BASE                        0x70002000
+#define TEGRA_AC97_SIZE                        SZ_512
+
+#define TEGRA_SPDIF_BASE               0x70002400
+#define TEGRA_SPDIF_SIZE               SZ_512
+
+#define TEGRA_I2S1_BASE                        0x70002800
+#define TEGRA_I2S1_SIZE                        SZ_256
+
+#define TEGRA_I2S2_BASE                        0x70002A00
+#define TEGRA_I2S2_SIZE                        SZ_256
+
+#define TEGRA_UARTA_BASE               0x70006000
+#define TEGRA_UARTA_SIZE               SZ_64
+
+#define TEGRA_UARTB_BASE               0x70006040
+#define TEGRA_UARTB_SIZE               SZ_64
+
+#define TEGRA_UARTC_BASE               0x70006200
+#define TEGRA_UARTC_SIZE               SZ_256
+
+#define TEGRA_UARTD_BASE               0x70006300
+#define TEGRA_UARTD_SIZE               SZ_256
+
+#define TEGRA_UARTE_BASE               0x70006400
+#define TEGRA_UARTE_SIZE               SZ_256
+
+#define TEGRA_NAND_BASE                        0x70008000
+#define TEGRA_NAND_SIZE                        SZ_256
+
+#define TEGRA_HSMMC_BASE               0x70008500
+#define TEGRA_HSMMC_SIZE               SZ_256
+
+#define TEGRA_SNOR_BASE                        0x70009000
+#define TEGRA_SNOR_SIZE                        SZ_4K
+
+#define TEGRA_PWFM_BASE                        0x7000A000
+#define TEGRA_PWFM_SIZE                        SZ_256
+
+#define TEGRA_MIPI_BASE                        0x7000B000
+#define TEGRA_MIPI_SIZE                        SZ_256
+
+#define TEGRA_I2C_BASE                 0x7000C000
+#define TEGRA_I2C_SIZE                 SZ_256
+
+#define TEGRA_TWC_BASE                 0x7000C100
+#define TEGRA_TWC_SIZE                 SZ_256
+
+#define TEGRA_SPI_BASE                 0x7000C380
+#define TEGRA_SPI_SIZE                 48
+
+#define TEGRA_I2C2_BASE                        0x7000C400
+#define TEGRA_I2C2_SIZE                        SZ_256
+
+#define TEGRA_I2C3_BASE                        0x7000C500
+#define TEGRA_I2C3_SIZE                        SZ_256
+
+#define TEGRA_OWR_BASE                 0x7000D000
+#define TEGRA_OWR_SIZE                 80
+
+#define TEGRA_DVC_BASE                 0x7000D000
+#define TEGRA_DVC_SIZE                 SZ_512
+
+#define TEGRA_SPI1_BASE                        0x7000D400
+#define TEGRA_SPI1_SIZE                        SZ_512
+
+#define TEGRA_SPI2_BASE                        0x7000D600
+#define TEGRA_SPI2_SIZE                        SZ_512
+
+#define TEGRA_SPI3_BASE                        0x7000D800
+#define TEGRA_SPI3_SIZE                        SZ_512
+
+#define TEGRA_SPI4_BASE                        0x7000DA00
+#define TEGRA_SPI4_SIZE                        SZ_512
+
+#define TEGRA_RTC_BASE                 0x7000E000
+#define TEGRA_RTC_SIZE                 SZ_256
+
+#define TEGRA_KBC_BASE                 0x7000E200
+#define TEGRA_KBC_SIZE                 SZ_256
+
+#define TEGRA_PMC_BASE                 0x7000E400
+#define TEGRA_PMC_SIZE                 SZ_256
+
+#define TEGRA_MC_BASE                  0x7000F000
+#define TEGRA_MC_SIZE                  SZ_1K
+
+#define TEGRA_EMC_BASE                 0x7000F400
+#define TEGRA_EMC_SIZE                 SZ_1K
+
+#define TEGRA_FUSE_BASE                        0x7000F800
+#define TEGRA_FUSE_SIZE                        SZ_1K
+
+#define TEGRA_KFUSE_BASE               0x7000FC00
+#define TEGRA_KFUSE_SIZE               SZ_1K
+
+#define TEGRA_CSITE_BASE               0x70040000
+#define TEGRA_CSITE_SIZE               SZ_256K
+
+#define TEGRA_USB_BASE                 0xC5000000
+#define TEGRA_USB_SIZE                 SZ_16K
+
+#define TEGRA_USB1_BASE                        0xC5004000
+#define TEGRA_USB1_SIZE                        SZ_16K
+
+#define TEGRA_USB2_BASE                        0xC5008000
+#define TEGRA_USB2_SIZE                        SZ_16K
+
+#define TEGRA_SDMMC1_BASE              0xC8000000
+#define TEGRA_SDMMC1_SIZE              SZ_512
+
+#define TEGRA_SDMMC2_BASE              0xC8000200
+#define TEGRA_SDMMC2_SIZE              SZ_512
+
+#define TEGRA_SDMMC3_BASE              0xC8000400
+#define TEGRA_SDMMC3_SIZE              SZ_512
+
+#define TEGRA_SDMMC4_BASE              0xC8000600
+#define TEGRA_SDMMC4_SIZE              SZ_512
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h
new file mode 100644 (file)
index 0000000..20f640e
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * arch/arm/mach-tegra/include/mach/irqs.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_IRQS_H
+#define __MACH_TEGRA_IRQS_H
+
+#define INT_GIC_BASE                   0
+
+#define IRQ_LOCALTIMER                  29
+
+/* Primary Interrupt Controller */
+#define INT_PRI_BASE                   (INT_GIC_BASE + 32)
+#define INT_TMR1                       (INT_PRI_BASE + 0)
+#define INT_TMR2                       (INT_PRI_BASE + 1)
+#define INT_RTC                                (INT_PRI_BASE + 2)
+#define INT_I2S2                       (INT_PRI_BASE + 3)
+#define INT_SHR_SEM_INBOX_IBF          (INT_PRI_BASE + 4)
+#define INT_SHR_SEM_INBOX_IBE          (INT_PRI_BASE + 5)
+#define INT_SHR_SEM_OUTBOX_IBF         (INT_PRI_BASE + 6)
+#define INT_SHR_SEM_OUTBOX_IBE         (INT_PRI_BASE + 7)
+#define INT_VDE_UCQ_ERROR              (INT_PRI_BASE + 8)
+#define INT_VDE_SYNC_TOKEN             (INT_PRI_BASE + 9)
+#define INT_VDE_BSE_V                  (INT_PRI_BASE + 10)
+#define INT_VDE_BSE_A                  (INT_PRI_BASE + 11)
+#define INT_VDE_SXE                    (INT_PRI_BASE + 12)
+#define INT_I2S1                       (INT_PRI_BASE + 13)
+#define INT_SDMMC1                     (INT_PRI_BASE + 14)
+#define INT_SDMMC2                     (INT_PRI_BASE + 15)
+#define INT_XIO                                (INT_PRI_BASE + 16)
+#define INT_VDE                                (INT_PRI_BASE + 17)
+#define INT_AVP_UCQ                    (INT_PRI_BASE + 18)
+#define INT_SDMMC3                     (INT_PRI_BASE + 19)
+#define INT_USB                                (INT_PRI_BASE + 20)
+#define INT_USB2                       (INT_PRI_BASE + 21)
+#define INT_PRI_RES_22                 (INT_PRI_BASE + 22)
+#define INT_EIDE                       (INT_PRI_BASE + 23)
+#define INT_NANDFLASH                  (INT_PRI_BASE + 24)
+#define INT_VCP                                (INT_PRI_BASE + 25)
+#define INT_APB_DMA                    (INT_PRI_BASE + 26)
+#define INT_AHB_DMA                    (INT_PRI_BASE + 27)
+#define INT_GNT_0                      (INT_PRI_BASE + 28)
+#define INT_GNT_1                      (INT_PRI_BASE + 29)
+#define INT_OWR                                (INT_PRI_BASE + 30)
+#define INT_SDMMC4                     (INT_PRI_BASE + 31)
+
+/* Secondary Interrupt Controller */
+#define INT_SEC_BASE                   (INT_PRI_BASE + 32)
+#define INT_GPIO1                      (INT_SEC_BASE + 0)
+#define INT_GPIO2                      (INT_SEC_BASE + 1)
+#define INT_GPIO3                      (INT_SEC_BASE + 2)
+#define INT_GPIO4                      (INT_SEC_BASE + 3)
+#define INT_UARTA                      (INT_SEC_BASE + 4)
+#define INT_UARTB                      (INT_SEC_BASE + 5)
+#define INT_I2C                                (INT_SEC_BASE + 6)
+#define INT_SPI                                (INT_SEC_BASE + 7)
+#define INT_TWC                                (INT_SEC_BASE + 8)
+#define INT_TMR3                       (INT_SEC_BASE + 9)
+#define INT_TMR4                       (INT_SEC_BASE + 10)
+#define INT_FLOW_RSM0                  (INT_SEC_BASE + 11)
+#define INT_FLOW_RSM1                  (INT_SEC_BASE + 12)
+#define INT_SPDIF                      (INT_SEC_BASE + 13)
+#define INT_UARTC                      (INT_SEC_BASE + 14)
+#define INT_MIPI                       (INT_SEC_BASE + 15)
+#define INT_EVENTA                     (INT_SEC_BASE + 16)
+#define INT_EVENTB                     (INT_SEC_BASE + 17)
+#define INT_EVENTC                     (INT_SEC_BASE + 18)
+#define INT_EVENTD                     (INT_SEC_BASE + 19)
+#define INT_VFIR                       (INT_SEC_BASE + 20)
+#define INT_DVC                                (INT_SEC_BASE + 21)
+#define INT_SYS_STATS_MON              (INT_SEC_BASE + 22)
+#define INT_GPIO5                      (INT_SEC_BASE + 23)
+#define INT_CPU0_PMU_INTR              (INT_SEC_BASE + 24)
+#define INT_CPU2_PMU_INTR              (INT_SEC_BASE + 25)
+#define INT_SEC_RES_26                 (INT_SEC_BASE + 26)
+#define INT_S_LINK1                    (INT_SEC_BASE + 27)
+#define INT_APB_DMA_COP                        (INT_SEC_BASE + 28)
+#define INT_AHB_DMA_COP                        (INT_SEC_BASE + 29)
+#define INT_DMA_TX                     (INT_SEC_BASE + 30)
+#define INT_DMA_RX                     (INT_SEC_BASE + 31)
+
+/* Tertiary Interrupt Controller */
+#define INT_TRI_BASE                   (INT_SEC_BASE + 32)
+#define INT_HOST1X_COP_SYNCPT          (INT_TRI_BASE + 0)
+#define INT_HOST1X_MPCORE_SYNCPT       (INT_TRI_BASE + 1)
+#define INT_HOST1X_COP_GENERAL         (INT_TRI_BASE + 2)
+#define INT_HOST1X_MPCORE_GENERAL      (INT_TRI_BASE + 3)
+#define INT_MPE_GENERAL                        (INT_TRI_BASE + 4)
+#define INT_VI_GENERAL                 (INT_TRI_BASE + 5)
+#define INT_EPP_GENERAL                        (INT_TRI_BASE + 6)
+#define INT_ISP_GENERAL                        (INT_TRI_BASE + 7)
+#define INT_2D_GENERAL                 (INT_TRI_BASE + 8)
+#define INT_DISPLAY_GENERAL            (INT_TRI_BASE + 9)
+#define INT_DISPLAY_B_GENERAL          (INT_TRI_BASE + 10)
+#define INT_HDMI                       (INT_TRI_BASE + 11)
+#define INT_TVO_GENERAL                        (INT_TRI_BASE + 12)
+#define INT_MC_GENERAL                 (INT_TRI_BASE + 13)
+#define INT_EMC_GENERAL                        (INT_TRI_BASE + 14)
+#define INT_TRI_RES_15                 (INT_TRI_BASE + 15)
+#define INT_TRI_RES_16                 (INT_TRI_BASE + 16)
+#define INT_AC97                       (INT_TRI_BASE + 17)
+#define INT_SPI_2                      (INT_TRI_BASE + 18)
+#define INT_SPI_3                      (INT_TRI_BASE + 19)
+#define INT_I2C2                       (INT_TRI_BASE + 20)
+#define INT_KBC                                (INT_TRI_BASE + 21)
+#define INT_EXTERNAL_PMU               (INT_TRI_BASE + 22)
+#define INT_GPIO6                      (INT_TRI_BASE + 23)
+#define INT_TVDAC                      (INT_TRI_BASE + 24)
+#define INT_GPIO7                      (INT_TRI_BASE + 25)
+#define INT_UARTD                      (INT_TRI_BASE + 26)
+#define INT_UARTE                      (INT_TRI_BASE + 27)
+#define INT_I2C3                       (INT_TRI_BASE + 28)
+#define INT_SPI_4                      (INT_TRI_BASE + 29)
+#define INT_TRI_RES_30                 (INT_TRI_BASE + 30)
+#define INT_SW_RESERVED                        (INT_TRI_BASE + 31)
+
+/* Quaternary Interrupt Controller */
+#define INT_QUAD_BASE                  (INT_TRI_BASE + 32)
+#define INT_SNOR                       (INT_QUAD_BASE + 0)
+#define INT_USB3                       (INT_QUAD_BASE + 1)
+#define INT_PCIE_INTR                  (INT_QUAD_BASE + 2)
+#define INT_PCIE_MSI                   (INT_QUAD_BASE + 3)
+#define INT_QUAD_RES_4                 (INT_QUAD_BASE + 4)
+#define INT_QUAD_RES_5                 (INT_QUAD_BASE + 5)
+#define INT_QUAD_RES_6                 (INT_QUAD_BASE + 6)
+#define INT_QUAD_RES_7                 (INT_QUAD_BASE + 7)
+#define INT_APB_DMA_CH0                        (INT_QUAD_BASE + 8)
+#define INT_APB_DMA_CH1                        (INT_QUAD_BASE + 9)
+#define INT_APB_DMA_CH2                        (INT_QUAD_BASE + 10)
+#define INT_APB_DMA_CH3                        (INT_QUAD_BASE + 11)
+#define INT_APB_DMA_CH4                        (INT_QUAD_BASE + 12)
+#define INT_APB_DMA_CH5                        (INT_QUAD_BASE + 13)
+#define INT_APB_DMA_CH6                        (INT_QUAD_BASE + 14)
+#define INT_APB_DMA_CH7                        (INT_QUAD_BASE + 15)
+#define INT_APB_DMA_CH8                        (INT_QUAD_BASE + 16)
+#define INT_APB_DMA_CH9                        (INT_QUAD_BASE + 17)
+#define INT_APB_DMA_CH10               (INT_QUAD_BASE + 18)
+#define INT_APB_DMA_CH11               (INT_QUAD_BASE + 19)
+#define INT_APB_DMA_CH12               (INT_QUAD_BASE + 20)
+#define INT_APB_DMA_CH13               (INT_QUAD_BASE + 21)
+#define INT_APB_DMA_CH14               (INT_QUAD_BASE + 22)
+#define INT_APB_DMA_CH15               (INT_QUAD_BASE + 23)
+#define INT_QUAD_RES_24                        (INT_QUAD_BASE + 24)
+#define INT_QUAD_RES_25                        (INT_QUAD_BASE + 25)
+#define INT_QUAD_RES_26                        (INT_QUAD_BASE + 26)
+#define INT_QUAD_RES_27                        (INT_QUAD_BASE + 27)
+#define INT_QUAD_RES_28                        (INT_QUAD_BASE + 28)
+#define INT_QUAD_RES_29                        (INT_QUAD_BASE + 29)
+#define INT_QUAD_RES_30                        (INT_QUAD_BASE + 30)
+#define INT_QUAD_RES_31                        (INT_QUAD_BASE + 31)
+
+#define INT_GPIO_BASE                  (INT_QUAD_BASE + 32)
+#define INT_GPIO_NR                    (28 * 8)
+
+#define NR_IRQS                                (INT_GPIO_BASE + INT_GPIO_NR)
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/memory.h b/arch/arm/mach-tegra/include/mach/memory.h
new file mode 100644 (file)
index 0000000..6151bab
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * arch/arm/mach-tegra/include/mach/memory.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_MEMORY_H
+#define __MACH_TEGRA_MEMORY_H
+
+/* physical offset of RAM */
+#define PHYS_OFFSET            UL(0)
+
+#endif
+
diff --git a/arch/arm/mach-tegra/include/mach/pinmux.h b/arch/arm/mach-tegra/include/mach/pinmux.h
new file mode 100644 (file)
index 0000000..41c8ce5
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * linux/arch/arm/mach-tegra/include/mach/pinmux.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_PINMUX_H
+#define __MACH_TEGRA_PINMUX_H
+
+enum tegra_pingroup {
+       TEGRA_PINGROUP_ATA = 0,
+       TEGRA_PINGROUP_ATB,
+       TEGRA_PINGROUP_ATC,
+       TEGRA_PINGROUP_ATD,
+       TEGRA_PINGROUP_ATE,
+       TEGRA_PINGROUP_CDEV1,
+       TEGRA_PINGROUP_CDEV2,
+       TEGRA_PINGROUP_CRTP,
+       TEGRA_PINGROUP_CSUS,
+       TEGRA_PINGROUP_DAP1,
+       TEGRA_PINGROUP_DAP2,
+       TEGRA_PINGROUP_DAP3,
+       TEGRA_PINGROUP_DAP4,
+       TEGRA_PINGROUP_DDC,
+       TEGRA_PINGROUP_DTA,
+       TEGRA_PINGROUP_DTB,
+       TEGRA_PINGROUP_DTC,
+       TEGRA_PINGROUP_DTD,
+       TEGRA_PINGROUP_DTE,
+       TEGRA_PINGROUP_DTF,
+       TEGRA_PINGROUP_GMA,
+       TEGRA_PINGROUP_GMB,
+       TEGRA_PINGROUP_GMC,
+       TEGRA_PINGROUP_GMD,
+       TEGRA_PINGROUP_GME,
+       TEGRA_PINGROUP_GPU,
+       TEGRA_PINGROUP_GPU7,
+       TEGRA_PINGROUP_GPV,
+       TEGRA_PINGROUP_HDINT,
+       TEGRA_PINGROUP_I2CP,
+       TEGRA_PINGROUP_IRRX,
+       TEGRA_PINGROUP_IRTX,
+       TEGRA_PINGROUP_KBCA,
+       TEGRA_PINGROUP_KBCB,
+       TEGRA_PINGROUP_KBCC,
+       TEGRA_PINGROUP_KBCD,
+       TEGRA_PINGROUP_KBCE,
+       TEGRA_PINGROUP_KBCF,
+       TEGRA_PINGROUP_LCSN,
+       TEGRA_PINGROUP_LD0,
+       TEGRA_PINGROUP_LD1,
+       TEGRA_PINGROUP_LD10,
+       TEGRA_PINGROUP_LD11,
+       TEGRA_PINGROUP_LD12,
+       TEGRA_PINGROUP_LD13,
+       TEGRA_PINGROUP_LD14,
+       TEGRA_PINGROUP_LD15,
+       TEGRA_PINGROUP_LD16,
+       TEGRA_PINGROUP_LD17,
+       TEGRA_PINGROUP_LD2,
+       TEGRA_PINGROUP_LD3,
+       TEGRA_PINGROUP_LD4,
+       TEGRA_PINGROUP_LD5,
+       TEGRA_PINGROUP_LD6,
+       TEGRA_PINGROUP_LD7,
+       TEGRA_PINGROUP_LD8,
+       TEGRA_PINGROUP_LD9,
+       TEGRA_PINGROUP_LDC,
+       TEGRA_PINGROUP_LDI,
+       TEGRA_PINGROUP_LHP0,
+       TEGRA_PINGROUP_LHP1,
+       TEGRA_PINGROUP_LHP2,
+       TEGRA_PINGROUP_LHS,
+       TEGRA_PINGROUP_LM0,
+       TEGRA_PINGROUP_LM1,
+       TEGRA_PINGROUP_LPP,
+       TEGRA_PINGROUP_LPW0,
+       TEGRA_PINGROUP_LPW1,
+       TEGRA_PINGROUP_LPW2,
+       TEGRA_PINGROUP_LSC0,
+       TEGRA_PINGROUP_LSC1,
+       TEGRA_PINGROUP_LSCK,
+       TEGRA_PINGROUP_LSDA,
+       TEGRA_PINGROUP_LSDI,
+       TEGRA_PINGROUP_LSPI,
+       TEGRA_PINGROUP_LVP0,
+       TEGRA_PINGROUP_LVP1,
+       TEGRA_PINGROUP_LVS,
+       TEGRA_PINGROUP_OWC,
+       TEGRA_PINGROUP_PMC,
+       TEGRA_PINGROUP_PTA,
+       TEGRA_PINGROUP_RM,
+       TEGRA_PINGROUP_SDB,
+       TEGRA_PINGROUP_SDC,
+       TEGRA_PINGROUP_SDD,
+       TEGRA_PINGROUP_SDIO1,
+       TEGRA_PINGROUP_SLXA,
+       TEGRA_PINGROUP_SLXC,
+       TEGRA_PINGROUP_SLXD,
+       TEGRA_PINGROUP_SLXK,
+       TEGRA_PINGROUP_SPDI,
+       TEGRA_PINGROUP_SPDO,
+       TEGRA_PINGROUP_SPIA,
+       TEGRA_PINGROUP_SPIB,
+       TEGRA_PINGROUP_SPIC,
+       TEGRA_PINGROUP_SPID,
+       TEGRA_PINGROUP_SPIE,
+       TEGRA_PINGROUP_SPIF,
+       TEGRA_PINGROUP_SPIG,
+       TEGRA_PINGROUP_SPIH,
+       TEGRA_PINGROUP_UAA,
+       TEGRA_PINGROUP_UAB,
+       TEGRA_PINGROUP_UAC,
+       TEGRA_PINGROUP_UAD,
+       TEGRA_PINGROUP_UCA,
+       TEGRA_PINGROUP_UCB,
+       TEGRA_PINGROUP_UDA,
+       /* these pin groups only have pullup and pull down control */
+       TEGRA_PINGROUP_CK32,
+       TEGRA_PINGROUP_DDRC,
+       TEGRA_PINGROUP_PMCA,
+       TEGRA_PINGROUP_PMCB,
+       TEGRA_PINGROUP_PMCC,
+       TEGRA_PINGROUP_PMCD,
+       TEGRA_PINGROUP_PMCE,
+       TEGRA_PINGROUP_XM2C,
+       TEGRA_PINGROUP_XM2D,
+       TEGRA_MAX_PINGROUP,
+};
+
+enum tegra_mux_func {
+       TEGRA_MUX_RSVD = 0x8000,
+       TEGRA_MUX_RSVD1 = 0x8000,
+       TEGRA_MUX_RSVD2 = 0x8001,
+       TEGRA_MUX_RSVD3 = 0x8002,
+       TEGRA_MUX_RSVD4 = 0x8003,
+       TEGRA_MUX_NONE = -1,
+       TEGRA_MUX_AHB_CLK,
+       TEGRA_MUX_APB_CLK,
+       TEGRA_MUX_AUDIO_SYNC,
+       TEGRA_MUX_CRT,
+       TEGRA_MUX_DAP1,
+       TEGRA_MUX_DAP2,
+       TEGRA_MUX_DAP3,
+       TEGRA_MUX_DAP4,
+       TEGRA_MUX_DAP5,
+       TEGRA_MUX_DISPLAYA,
+       TEGRA_MUX_DISPLAYB,
+       TEGRA_MUX_EMC_TEST0_DLL,
+       TEGRA_MUX_EMC_TEST1_DLL,
+       TEGRA_MUX_GMI,
+       TEGRA_MUX_GMI_INT,
+       TEGRA_MUX_HDMI,
+       TEGRA_MUX_I2C,
+       TEGRA_MUX_I2C2,
+       TEGRA_MUX_I2C3,
+       TEGRA_MUX_IDE,
+       TEGRA_MUX_IRDA,
+       TEGRA_MUX_KBC,
+       TEGRA_MUX_MIO,
+       TEGRA_MUX_MIPI_HS,
+       TEGRA_MUX_NAND,
+       TEGRA_MUX_OSC,
+       TEGRA_MUX_OWR,
+       TEGRA_MUX_PCIE,
+       TEGRA_MUX_PLLA_OUT,
+       TEGRA_MUX_PLLC_OUT1,
+       TEGRA_MUX_PLLM_OUT1,
+       TEGRA_MUX_PLLP_OUT2,
+       TEGRA_MUX_PLLP_OUT3,
+       TEGRA_MUX_PLLP_OUT4,
+       TEGRA_MUX_PWM,
+       TEGRA_MUX_PWR_INTR,
+       TEGRA_MUX_PWR_ON,
+       TEGRA_MUX_RTCK,
+       TEGRA_MUX_SDIO1,
+       TEGRA_MUX_SDIO2,
+       TEGRA_MUX_SDIO3,
+       TEGRA_MUX_SDIO4,
+       TEGRA_MUX_SFLASH,
+       TEGRA_MUX_SPDIF,
+       TEGRA_MUX_SPI1,
+       TEGRA_MUX_SPI2,
+       TEGRA_MUX_SPI2_ALT,
+       TEGRA_MUX_SPI3,
+       TEGRA_MUX_SPI4,
+       TEGRA_MUX_TRACE,
+       TEGRA_MUX_TWC,
+       TEGRA_MUX_UARTA,
+       TEGRA_MUX_UARTB,
+       TEGRA_MUX_UARTC,
+       TEGRA_MUX_UARTD,
+       TEGRA_MUX_UARTE,
+       TEGRA_MUX_ULPI,
+       TEGRA_MUX_VI,
+       TEGRA_MUX_VI_SENSOR_CLK,
+       TEGRA_MUX_XIO,
+       TEGRA_MAX_MUX,
+};
+
+enum tegra_pullupdown {
+       TEGRA_PUPD_NORMAL = 0,
+       TEGRA_PUPD_PULL_DOWN,
+       TEGRA_PUPD_PULL_UP,
+};
+
+enum tegra_tristate {
+       TEGRA_TRI_NORMAL = 0,
+       TEGRA_TRI_TRISTATE = 1,
+};
+
+struct tegra_pingroup_config {
+       enum tegra_pingroup     pingroup;
+       enum tegra_mux_func     func;
+       enum tegra_pullupdown   pupd;
+       enum tegra_tristate     tristate;
+};
+
+enum tegra_slew {
+       TEGRA_SLEW_FASTEST = 0,
+       TEGRA_SLEW_FAST,
+       TEGRA_SLEW_SLOW,
+       TEGRA_SLEW_SLOWEST,
+       TEGRA_MAX_SLEW,
+};
+
+enum tegra_pull_strength {
+       TEGRA_PULL_0 = 0,
+       TEGRA_PULL_1,
+       TEGRA_PULL_2,
+       TEGRA_PULL_3,
+       TEGRA_PULL_4,
+       TEGRA_PULL_5,
+       TEGRA_PULL_6,
+       TEGRA_PULL_7,
+       TEGRA_PULL_8,
+       TEGRA_PULL_9,
+       TEGRA_PULL_10,
+       TEGRA_PULL_11,
+       TEGRA_PULL_12,
+       TEGRA_PULL_13,
+       TEGRA_PULL_14,
+       TEGRA_PULL_15,
+       TEGRA_PULL_16,
+       TEGRA_PULL_17,
+       TEGRA_PULL_18,
+       TEGRA_PULL_19,
+       TEGRA_PULL_20,
+       TEGRA_PULL_21,
+       TEGRA_PULL_22,
+       TEGRA_PULL_23,
+       TEGRA_PULL_24,
+       TEGRA_PULL_25,
+       TEGRA_PULL_26,
+       TEGRA_PULL_27,
+       TEGRA_PULL_28,
+       TEGRA_PULL_29,
+       TEGRA_PULL_30,
+       TEGRA_PULL_31,
+       TEGRA_MAX_PULL,
+};
+
+enum tegra_drive_pingroup {
+       TEGRA_DRIVE_PINGROUP_AO1 = 0,
+       TEGRA_DRIVE_PINGROUP_AO2,
+       TEGRA_DRIVE_PINGROUP_AT1,
+       TEGRA_DRIVE_PINGROUP_AT2,
+       TEGRA_DRIVE_PINGROUP_CDEV1,
+       TEGRA_DRIVE_PINGROUP_CDEV2,
+       TEGRA_DRIVE_PINGROUP_CSUS,
+       TEGRA_DRIVE_PINGROUP_DAP1,
+       TEGRA_DRIVE_PINGROUP_DAP2,
+       TEGRA_DRIVE_PINGROUP_DAP3,
+       TEGRA_DRIVE_PINGROUP_DAP4,
+       TEGRA_DRIVE_PINGROUP_DBG,
+       TEGRA_DRIVE_PINGROUP_LCD1,
+       TEGRA_DRIVE_PINGROUP_LCD2,
+       TEGRA_DRIVE_PINGROUP_SDMMC2,
+       TEGRA_DRIVE_PINGROUP_SDMMC3,
+       TEGRA_DRIVE_PINGROUP_SPI,
+       TEGRA_DRIVE_PINGROUP_UAA,
+       TEGRA_DRIVE_PINGROUP_UAB,
+       TEGRA_DRIVE_PINGROUP_UART2,
+       TEGRA_DRIVE_PINGROUP_UART3,
+       TEGRA_DRIVE_PINGROUP_VI1,
+       TEGRA_DRIVE_PINGROUP_VI2,
+       TEGRA_DRIVE_PINGROUP_XM2A,
+       TEGRA_DRIVE_PINGROUP_XM2C,
+       TEGRA_DRIVE_PINGROUP_XM2D,
+       TEGRA_DRIVE_PINGROUP_XM2CLK,
+       TEGRA_DRIVE_PINGROUP_MEMCOMP,
+       TEGRA_MAX_DRIVE_PINGROUP,
+};
+
+enum tegra_drive {
+       TEGRA_DRIVE_DIV_8 = 0,
+       TEGRA_DRIVE_DIV_4,
+       TEGRA_DRIVE_DIV_2,
+       TEGRA_DRIVE_DIV_1,
+       TEGRA_MAX_DRIVE,
+};
+
+enum tegra_hsm {
+       TEGRA_HSM_DISABLE = 0,
+       TEGRA_HSM_ENABLE,
+};
+
+enum tegra_schmitt {
+       TEGRA_SCHMITT_DISABLE = 0,
+       TEGRA_SCHMITT_ENABLE,
+};
+
+struct tegra_drive_pingroup_config {
+       enum tegra_drive_pingroup pingroup;
+       enum tegra_hsm hsm;
+       enum tegra_schmitt schmitt;
+       enum tegra_drive drive;
+       enum tegra_pull_strength pull_down;
+       enum tegra_pull_strength pull_up;
+       enum tegra_slew slew_rising;
+       enum tegra_slew slew_falling;
+};
+
+int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func);
+int tegra_pinmux_set_tristate(enum tegra_pingroup pg, enum tegra_tristate tristate);
+int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, enum tegra_pullupdown pupd);
+
+void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
+       enum tegra_mux_func func, enum tegra_pullupdown pupd,
+       enum tegra_tristate tristate);
+
+void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len);
+
+void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
+       int len);
+
+#endif
+
diff --git a/arch/arm/mach-tegra/include/mach/smp.h b/arch/arm/mach-tegra/include/mach/smp.h
new file mode 100644 (file)
index 0000000..8b42dab
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef ASMARM_ARCH_SMP_H
+#define ASMARM_ARCH_SMP_H
+
+
+#include <asm/hardware/gic.h>
+
+#define hard_smp_processor_id()                        \
+       ({                                              \
+               unsigned int cpunum;                    \
+               __asm__("mrc p15, 0, %0, c0, c0, 5"     \
+                       : "=r" (cpunum));               \
+               cpunum &= 0x0F;                         \
+       })
+
+/*
+ * We use IRQ1 as the IPI
+ */
+static inline void smp_cross_call(const struct cpumask *mask)
+{
+       gic_raise_softirq(mask, 1);
+}
+
+/*
+ * Do nothing on MPcore.
+ */
+static inline void smp_cross_call_done(cpumask_t callmap)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/system.h b/arch/arm/mach-tegra/include/mach/system.h
new file mode 100644 (file)
index 0000000..84d5d46
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * arch/arm/mach-tegra/include/mach/system.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_SYSTEM_H
+#define __MACH_TEGRA_SYSTEM_H
+
+#include <mach/hardware.h>
+#include <mach/iomap.h>
+
+static inline void arch_idle(void)
+{
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+       void __iomem *reset = IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x04);
+       u32 reg = readl(reset);
+       reg |= 0x04;
+       writel(reg, reset);
+}
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/timex.h b/arch/arm/mach-tegra/include/mach/timex.h
new file mode 100644 (file)
index 0000000..a44ccbd
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * arch/arm/mach-tegra/include/mach/timex.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_TIMEX_H
+#define __MACH_TEGRA_TIMEX_H
+
+#define CLOCK_TICK_RATE                1000000
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h
new file mode 100644 (file)
index 0000000..6c4dd81
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-tegra/include/mach/uncompress.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_UNCOMPRESS_H
+#define __MACH_TEGRA_UNCOMPRESS_H
+
+#include <linux/types.h>
+#include <linux/serial_reg.h>
+
+#include <mach/iomap.h>
+
+#if defined(CONFIG_TEGRA_DEBUG_UARTA)
+#define DEBUG_UART_BASE TEGRA_UARTA_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
+#define DEBUG_UART_BASE TEGRA_UARTB_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
+#define DEBUG_UART_BASE TEGRA_UARTC_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
+#define DEBUG_UART_BASE TEGRA_UARTD_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
+#define DEBUG_UART_BASE TEGRA_UARTE_BASE
+#else
+#define DEBUG_UART_BASE NULL
+#endif
+
+static void putc(int c)
+{
+       volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE;
+       int shift = 2;
+
+       if (uart == NULL)
+               return;
+
+       while (!(uart[UART_LSR << shift] & UART_LSR_THRE))
+               barrier();
+       uart[UART_TX << shift] = c;
+}
+
+static inline void flush(void)
+{
+}
+
+static inline void arch_decomp_setup(void)
+{
+       volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE;
+       int shift = 2;
+
+       if (uart == NULL)
+               return;
+
+       uart[UART_LCR << shift] |= UART_LCR_DLAB;
+       uart[UART_DLL << shift] = 0x75;
+       uart[UART_DLM << shift] = 0x0;
+       uart[UART_LCR << shift] = 3;
+}
+
+static inline void arch_decomp_wdog(void)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/vmalloc.h b/arch/arm/mach-tegra/include/mach/vmalloc.h
new file mode 100644 (file)
index 0000000..267a141
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * arch/arm/mach-tegra/include/mach/vmalloc.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_VMALLOC_H
+#define __MACH_TEGRA_VMALLOC_H
+
+#include <asm/sizes.h>
+
+#define VMALLOC_END        0xFE000000
+
+#endif
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
new file mode 100644 (file)
index 0000000..9fe2c5c
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * arch/arm/mach-tegra/io.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Erik Gilling <konkers@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+
+#include "board.h"
+
+static struct map_desc tegra_io_desc[] __initdata = {
+       {
+               .virtual = IO_PPSB_VIRT,
+               .pfn = __phys_to_pfn(IO_PPSB_PHYS),
+               .length = IO_PPSB_SIZE,
+               .type = MT_DEVICE,
+       },
+       {
+               .virtual = IO_APB_VIRT,
+               .pfn = __phys_to_pfn(IO_APB_PHYS),
+               .length = IO_APB_SIZE,
+               .type = MT_DEVICE,
+       },
+       {
+               .virtual = IO_CPU_VIRT,
+               .pfn = __phys_to_pfn(IO_CPU_PHYS),
+               .length = IO_CPU_SIZE,
+               .type = MT_DEVICE,
+       },
+};
+
+void __init tegra_map_common_io(void)
+{
+       iotable_init(tegra_io_desc, ARRAY_SIZE(tegra_io_desc));
+}
+
+/*
+ * Intercept ioremap() requests for addresses in our fixed mapping regions.
+ */
+void __iomem *tegra_ioremap(unsigned long p, size_t size, unsigned int type)
+{
+       void __iomem *v = IO_ADDRESS(p);
+       if (v == NULL)
+               v = __arm_ioremap(p, size, type);
+       return v;
+}
+EXPORT_SYMBOL(tegra_ioremap);
+
+void tegra_iounmap(volatile void __iomem *addr)
+{
+       unsigned long virt = (unsigned long)addr;
+
+       if (virt >= VMALLOC_START && virt < VMALLOC_END)
+               __iounmap(addr);
+}
+EXPORT_SYMBOL(tegra_iounmap);
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
new file mode 100644 (file)
index 0000000..1fdbe70
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/hardware/gic.h>
+
+#include <mach/iomap.h>
+
+#include "board.h"
+
+void __init tegra_init_irq(void)
+{
+       gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
+       gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+}
diff --git a/arch/arm/mach-tegra/localtimer.c b/arch/arm/mach-tegra/localtimer.c
new file mode 100644 (file)
index 0000000..f81ca7c
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  arch/arm/mach-tegra/localtimer.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/clockchips.h>
+#include <asm/irq.h>
+#include <asm/smp_twd.h>
+#include <asm/localtimer.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+void __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+       evt->irq = IRQ_LOCALTIMER;
+       twd_timer_setup(evt);
+}
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c
new file mode 100644 (file)
index 0000000..13ae102
--- /dev/null
@@ -0,0 +1,945 @@
+/*
+ * linux/arch/arm/mach-tegra/pinmux.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+
+#include <mach/iomap.h>
+#include <mach/pinmux.h>
+
+
+#define TEGRA_TRI_STATE(x)     (0x14 + (4 * (x)))
+#define TEGRA_PP_MUX_CTL(x)    (0x80 + (4 * (x)))
+#define TEGRA_PP_PU_PD(x)      (0xa0 + (4 * (x)))
+
+#define REG_A 0
+#define REG_B 1
+#define REG_C 2
+#define REG_D 3
+#define REG_E 4
+#define REG_F 5
+#define REG_G 6
+
+#define REG_N -1
+
+#define HSM_EN(reg)    (((reg) >> 2) & 0x1)
+#define SCHMT_EN(reg)  (((reg) >> 3) & 0x1)
+#define LPMD(reg)      (((reg) >> 4) & 0x3)
+#define DRVDN(reg)     (((reg) >> 12) & 0x1f)
+#define DRVUP(reg)     (((reg) >> 20) & 0x1f)
+#define SLWR(reg)      (((reg) >> 28) & 0x3)
+#define SLWF(reg)      (((reg) >> 30) & 0x3)
+
+struct tegra_pingroup_desc {
+       const char *name;
+       int funcs[4];
+       s8 tri_reg;     /* offset into the TRISTATE_REG_* register bank */
+       s8 tri_bit;     /* offset into the TRISTATE_REG_* register bit */
+       s8 mux_reg;     /* offset into the PIN_MUX_CTL_* register bank */
+       s8 mux_bit;     /* offset into the PIN_MUX_CTL_* register bit */
+       s8 pupd_reg;    /* offset into the PULL_UPDOWN_REG_* register bank */
+       s8 pupd_bit;    /* offset into the PULL_UPDOWN_REG_* register bit */
+};
+
+#define PINGROUP(pg_name, f0, f1, f2, f3,                      \
+                tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b)    \
+       [TEGRA_PINGROUP_ ## pg_name] = {                        \
+               .name = #pg_name,                               \
+               .funcs = {                                      \
+                       TEGRA_MUX_ ## f0,                       \
+                       TEGRA_MUX_ ## f1,                       \
+                       TEGRA_MUX_ ## f2,                       \
+                       TEGRA_MUX_ ## f3,                       \
+               },                                              \
+               .tri_reg = REG_ ## tri_r,                       \
+               .tri_bit = tri_b,                               \
+               .mux_reg = REG_ ## mux_r,                       \
+               .mux_bit = mux_b,                               \
+               .pupd_reg = REG_ ## pupd_r,                     \
+               .pupd_bit = pupd_b,                             \
+       }
+
+static const struct tegra_pingroup_desc pingroups[TEGRA_MAX_PINGROUP] = {
+       PINGROUP(ATA,   IDE,       NAND,      GMI,       RSVD,          A, 0,  A, 24, A, 0),
+       PINGROUP(ATB,   IDE,       NAND,      GMI,       SDIO4,         A, 1,  A, 16, A, 2),
+       PINGROUP(ATC,   IDE,       NAND,      GMI,       SDIO4,         A, 2,  A, 22, A, 4),
+       PINGROUP(ATD,   IDE,       NAND,      GMI,       SDIO4,         A, 3,  A, 20, A, 6),
+       PINGROUP(ATE,   IDE,       NAND,      GMI,       RSVD,          B, 25, A, 12, A, 8),
+       PINGROUP(CDEV1, OSC,       PLLA_OUT,  PLLM_OUT1, AUDIO_SYNC,    A, 4,  C, 2,  C, 0),
+       PINGROUP(CDEV2, OSC,       AHB_CLK,   APB_CLK,   PLLP_OUT4,     A, 5,  C, 4,  C, 2),
+       PINGROUP(CRTP,  CRT,       RSVD,      RSVD,      RSVD,          D, 14, G, 20, B, 24),
+       PINGROUP(CSUS,  PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, A, 6,  C, 6,  D, 24),
+       PINGROUP(DAP1,  DAP1,      RSVD,      GMI,       SDIO2,         A, 7,  C, 20, A, 10),
+       PINGROUP(DAP2,  DAP2,      TWC,       RSVD,      GMI,           A, 8,  C, 22, A, 12),
+       PINGROUP(DAP3,  DAP3,      RSVD,      RSVD,      RSVD,          A, 9,  C, 24, A, 14),
+       PINGROUP(DAP4,  DAP4,      RSVD,      GMI,       RSVD,          A, 10, C, 26, A, 16),
+       PINGROUP(DDC,   I2C2,      RSVD,      RSVD,      RSVD,          B, 31, C, 0,  E, 28),
+       PINGROUP(DTA,   RSVD,      SDIO2,     VI,        RSVD,          A, 11, B, 20, A, 18),
+       PINGROUP(DTB,   RSVD,      RSVD,      VI,        SPI1,          A, 12, B, 22, A, 20),
+       PINGROUP(DTC,   RSVD,      RSVD,      VI,        RSVD,          A, 13, B, 26, A, 22),
+       PINGROUP(DTD,   RSVD,      SDIO2,     VI,        RSVD,          A, 14, B, 28, A, 24),
+       PINGROUP(DTE,   RSVD,      RSVD,      VI,        SPI1,          A, 15, B, 30, A, 26),
+       PINGROUP(DTF,   I2C3,      RSVD,      VI,        RSVD,          D, 12, G, 30, A, 28),
+       PINGROUP(GMA,   UARTE,     SPI3,      GMI,       SDIO4,         A, 28, B, 0,  E, 20),
+       PINGROUP(GMB,   IDE,       NAND,      GMI,       GMI_INT,       B, 29, C, 28, E, 22),
+       PINGROUP(GMC,   UARTD,     SPI4,      GMI,       SFLASH,        A, 29, B, 2,  E, 24),
+       PINGROUP(GMD,   RSVD,      NAND,      GMI,       SFLASH,        B, 30, C, 30, E, 26),
+       PINGROUP(GME,   RSVD,      DAP5,      GMI,       SDIO4,         B, 0,  D, 0,  C, 24),
+       PINGROUP(GPU,   PWM,       UARTA,     GMI,       RSVD,          A, 16, D, 4,  B, 20),
+       PINGROUP(GPU7,  RTCK,      RSVD,      RSVD,      RSVD,          D, 11, G, 28, B, 6),
+       PINGROUP(GPV,   PCIE,      RSVD,      RSVD,      RSVD,          A, 17, D, 2,  A, 30),
+       PINGROUP(HDINT, HDMI,      RSVD,      RSVD,      RSVD,          C, 23, B, 4,  D, 22),
+       PINGROUP(I2CP,  I2C,       RSVD,      RSVD,      RSVD,          A, 18, C, 8,  B, 2),
+       PINGROUP(IRRX,  UARTA,     UARTB,     GMI,       SPI4,          A, 20, C, 18, C, 22),
+       PINGROUP(IRTX,  UARTA,     UARTB,     GMI,       SPI4,          A, 19, C, 16, C, 20),
+       PINGROUP(KBCA,  KBC,       NAND,      SDIO2,     EMC_TEST0_DLL, A, 22, C, 10, B, 8),
+       PINGROUP(KBCB,  KBC,       NAND,      SDIO2,     MIO,           A, 21, C, 12, B, 10),
+       PINGROUP(KBCC,  KBC,       NAND,      TRACE,     EMC_TEST1_DLL, B, 26, C, 14, B, 12),
+       PINGROUP(KBCD,  KBC,       NAND,      SDIO2,     MIO,           D, 10, G, 26, B, 14),
+       PINGROUP(KBCE,  KBC,       NAND,      OWR,       RSVD,          A, 26, A, 28, E, 2),
+       PINGROUP(KBCF,  KBC,       NAND,      TRACE,     MIO,           A, 27, A, 26, E, 0),
+       PINGROUP(LCSN,  DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          C, 31, E, 12, D, 20),
+       PINGROUP(LD0,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 0,  F, 0,  D, 12),
+       PINGROUP(LD1,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 1,  F, 2,  D, 12),
+       PINGROUP(LD10,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 10, F, 20, D, 12),
+       PINGROUP(LD11,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 11, F, 22, D, 12),
+       PINGROUP(LD12,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 12, F, 24, D, 12),
+       PINGROUP(LD13,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 13, F, 26, D, 12),
+       PINGROUP(LD14,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 14, F, 28, D, 12),
+       PINGROUP(LD15,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 15, F, 30, D, 12),
+       PINGROUP(LD16,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 16, G, 0,  D, 12),
+       PINGROUP(LD17,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 17, G, 2,  D, 12),
+       PINGROUP(LD2,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 2,  F, 4,  D, 12),
+       PINGROUP(LD3,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 3,  F, 6,  D, 12),
+       PINGROUP(LD4,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 4,  F, 8,  D, 12),
+       PINGROUP(LD5,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 5,  F, 10, D, 12),
+       PINGROUP(LD6,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 6,  F, 12, D, 12),
+       PINGROUP(LD7,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 7,  F, 14, D, 12),
+       PINGROUP(LD8,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 8,  F, 16, D, 12),
+       PINGROUP(LD9,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 9,  F, 18, D, 12),
+       PINGROUP(LDC,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 30, E, 14, D, 20),
+       PINGROUP(LDI,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 6,  G, 16, D, 18),
+       PINGROUP(LHP0,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 18, G, 10, D, 16),
+       PINGROUP(LHP1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 19, G, 4,  D, 14),
+       PINGROUP(LHP2,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 20, G, 6,  D, 14),
+       PINGROUP(LHS,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          D, 7,  E, 22, D, 22),
+       PINGROUP(LM0,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          C, 24, E, 26, D, 22),
+       PINGROUP(LM1,   DISPLAYA,  DISPLAYB,  RSVD,      CRT,           C, 25, E, 28, D, 22),
+       PINGROUP(LPP,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 8,  G, 14, D, 18),
+       PINGROUP(LPW0,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 3,  E, 0,  D, 20),
+       PINGROUP(LPW1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 4,  E, 2,  D, 20),
+       PINGROUP(LPW2,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 5,  E, 4,  D, 20),
+       PINGROUP(LSC0,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 27, E, 18, D, 22),
+       PINGROUP(LSC1,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          C, 28, E, 20, D, 20),
+       PINGROUP(LSCK,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          C, 29, E, 16, D, 20),
+       PINGROUP(LSDA,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 1,  E, 8,  D, 20),
+       PINGROUP(LSDI,  DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          D, 2,  E, 6,  D, 20),
+       PINGROUP(LSPI,  DISPLAYA,  DISPLAYB,  XIO,       HDMI,          D, 0,  E, 10, D, 22),
+       PINGROUP(LVP0,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 21, E, 30, D, 22),
+       PINGROUP(LVP1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 22, G, 8,  D, 16),
+       PINGROUP(LVS,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 26, E, 24, D, 22),
+       PINGROUP(OWC,   OWR,       RSVD,      RSVD,      RSVD,          A, 31, B, 8,  E, 30),
+       PINGROUP(PMC,   PWR_ON,    PWR_INTR,  RSVD,      RSVD,          A, 23, G, 18, N, -1),
+       PINGROUP(PTA,   I2C2,      HDMI,      GMI,       RSVD,          A, 24, G, 22, B, 4),
+       PINGROUP(RM,    I2C,       RSVD,      RSVD,      RSVD,          A, 25, A, 14, B, 0),
+       PINGROUP(SDB,   UARTA,     PWM,       SDIO3,     SPI2,          D, 15, D, 10, N, -1),
+       PINGROUP(SDC,   PWM,       TWC,       SDIO3,     SPI3,          B, 1,  D, 12, D, 28),
+       PINGROUP(SDD,   UARTA,     PWM,       SDIO3,     SPI3,          B, 2,  D, 14, D, 30),
+       PINGROUP(SDIO1, SDIO1,     RSVD,      UARTE,     UARTA,         A, 30, A, 30, E, 18),
+       PINGROUP(SLXA,  PCIE,      SPI4,      SDIO3,     SPI2,          B, 3,  B, 6,  B, 22),
+       PINGROUP(SLXC,  SPDIF,     SPI4,      SDIO3,     SPI2,          B, 5,  B, 10, B, 26),
+       PINGROUP(SLXD,  SPDIF,     SPI4,      SDIO3,     SPI2,          B, 6,  B, 12, B, 28),
+       PINGROUP(SLXK,  PCIE,      SPI4,      SDIO3,     SPI2,          B, 7,  B, 14, B, 30),
+       PINGROUP(SPDI,  SPDIF,     RSVD,      I2C,       SDIO2,         B, 8,  D, 8,  B, 16),
+       PINGROUP(SPDO,  SPDIF,     RSVD,      I2C,       SDIO2,         B, 9,  D, 6,  B, 18),
+       PINGROUP(SPIA,  SPI1,      SPI2,      SPI3,      GMI,           B, 10, D, 30, C, 4),
+       PINGROUP(SPIB,  SPI1,      SPI2,      SPI3,      GMI,           B, 11, D, 28, C, 6),
+       PINGROUP(SPIC,  SPI1,      SPI2,      SPI3,      GMI,           B, 12, D, 26, C, 8),
+       PINGROUP(SPID,  SPI2,      SPI1,      SPI2_ALT,  GMI,           B, 13, D, 24, C, 10),
+       PINGROUP(SPIE,  SPI2,      SPI1,      SPI2_ALT,  GMI,           B, 14, D, 22, C, 12),
+       PINGROUP(SPIF,  SPI3,      SPI1,      SPI2,      RSVD,          B, 15, D, 20, C, 14),
+       PINGROUP(SPIG,  SPI3,      SPI2,      SPI2_ALT,  I2C,           B, 16, D, 18, C, 16),
+       PINGROUP(SPIH,  SPI3,      SPI2,      SPI2_ALT,  I2C,           B, 17, D, 16, C, 18),
+       PINGROUP(UAA,   SPI3,      MIPI_HS,   UARTA,     ULPI,          B, 18, A, 0,  D, 0),
+       PINGROUP(UAB,   SPI2,      MIPI_HS,   UARTA,     ULPI,          B, 19, A, 2,  D, 2),
+       PINGROUP(UAC,   OWR,       RSVD,      RSVD,      RSVD,          B, 20, A, 4,  D, 4),
+       PINGROUP(UAD,   IRDA,      SPDIF,     UARTA,     SPI4,          B, 21, A, 6,  D, 6),
+       PINGROUP(UCA,   UARTC,     RSVD,      GMI,       RSVD,          B, 22, B, 16, D, 8),
+       PINGROUP(UCB,   UARTC,     PWM,       GMI,       RSVD,          B, 23, B, 18, D, 10),
+       PINGROUP(UDA,   SPI1,      RSVD,      UARTD,     ULPI,          D, 13, A, 8,  E, 16),
+       /* these pin groups only have pullup and pull down control */
+       PINGROUP(CK32,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 14),
+       PINGROUP(DDRC,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  D, 26),
+       PINGROUP(PMCA,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 4),
+       PINGROUP(PMCB,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 6),
+       PINGROUP(PMCC,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 8),
+       PINGROUP(PMCD,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 10),
+       PINGROUP(PMCE,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 12),
+       PINGROUP(XM2C,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  C, 30),
+       PINGROUP(XM2D,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  C, 28),
+};
+
+static char *tegra_mux_names[TEGRA_MAX_MUX] = {
+       [TEGRA_MUX_AHB_CLK] = "AHB_CLK",
+       [TEGRA_MUX_APB_CLK] = "APB_CLK",
+       [TEGRA_MUX_AUDIO_SYNC] = "AUDIO_SYNC",
+       [TEGRA_MUX_CRT] = "CRT",
+       [TEGRA_MUX_DAP1] = "DAP1",
+       [TEGRA_MUX_DAP2] = "DAP2",
+       [TEGRA_MUX_DAP3] = "DAP3",
+       [TEGRA_MUX_DAP4] = "DAP4",
+       [TEGRA_MUX_DAP5] = "DAP5",
+       [TEGRA_MUX_DISPLAYA] = "DISPLAYA",
+       [TEGRA_MUX_DISPLAYB] = "DISPLAYB",
+       [TEGRA_MUX_EMC_TEST0_DLL] = "EMC_TEST0_DLL",
+       [TEGRA_MUX_EMC_TEST1_DLL] = "EMC_TEST1_DLL",
+       [TEGRA_MUX_GMI] = "GMI",
+       [TEGRA_MUX_GMI_INT] = "GMI_INT",
+       [TEGRA_MUX_HDMI] = "HDMI",
+       [TEGRA_MUX_I2C] = "I2C",
+       [TEGRA_MUX_I2C2] = "I2C2",
+       [TEGRA_MUX_I2C3] = "I2C3",
+       [TEGRA_MUX_IDE] = "IDE",
+       [TEGRA_MUX_IRDA] = "IRDA",
+       [TEGRA_MUX_KBC] = "KBC",
+       [TEGRA_MUX_MIO] = "MIO",
+       [TEGRA_MUX_MIPI_HS] = "MIPI_HS",
+       [TEGRA_MUX_NAND] = "NAND",
+       [TEGRA_MUX_OSC] = "OSC",
+       [TEGRA_MUX_OWR] = "OWR",
+       [TEGRA_MUX_PCIE] = "PCIE",
+       [TEGRA_MUX_PLLA_OUT] = "PLLA_OUT",
+       [TEGRA_MUX_PLLC_OUT1] = "PLLC_OUT1",
+       [TEGRA_MUX_PLLM_OUT1] = "PLLM_OUT1",
+       [TEGRA_MUX_PLLP_OUT2] = "PLLP_OUT2",
+       [TEGRA_MUX_PLLP_OUT3] = "PLLP_OUT3",
+       [TEGRA_MUX_PLLP_OUT4] = "PLLP_OUT4",
+       [TEGRA_MUX_PWM] = "PWM",
+       [TEGRA_MUX_PWR_INTR] = "PWR_INTR",
+       [TEGRA_MUX_PWR_ON] = "PWR_ON",
+       [TEGRA_MUX_RTCK] = "RTCK",
+       [TEGRA_MUX_SDIO1] = "SDIO1",
+       [TEGRA_MUX_SDIO2] = "SDIO2",
+       [TEGRA_MUX_SDIO3] = "SDIO3",
+       [TEGRA_MUX_SDIO4] = "SDIO4",
+       [TEGRA_MUX_SFLASH] = "SFLASH",
+       [TEGRA_MUX_SPDIF] = "SPDIF",
+       [TEGRA_MUX_SPI1] = "SPI1",
+       [TEGRA_MUX_SPI2] = "SPI2",
+       [TEGRA_MUX_SPI2_ALT] = "SPI2_ALT",
+       [TEGRA_MUX_SPI3] = "SPI3",
+       [TEGRA_MUX_SPI4] = "SPI4",
+       [TEGRA_MUX_TRACE] = "TRACE",
+       [TEGRA_MUX_TWC] = "TWC",
+       [TEGRA_MUX_UARTA] = "UARTA",
+       [TEGRA_MUX_UARTB] = "UARTB",
+       [TEGRA_MUX_UARTC] = "UARTC",
+       [TEGRA_MUX_UARTD] = "UARTD",
+       [TEGRA_MUX_UARTE] = "UARTE",
+       [TEGRA_MUX_ULPI] = "ULPI",
+       [TEGRA_MUX_VI] = "VI",
+       [TEGRA_MUX_VI_SENSOR_CLK] = "VI_SENSOR_CLK",
+       [TEGRA_MUX_XIO] = "XIO",
+};
+
+struct tegra_drive_pingroup_desc {
+       const char *name;
+       s16 reg;
+};
+
+#define DRIVE_PINGROUP(pg_name, r)                             \
+       [TEGRA_DRIVE_PINGROUP_ ## pg_name] = {                  \
+               .name = #pg_name,                               \
+               .reg = r                                        \
+       }
+
+static const struct tegra_drive_pingroup_desc drive_pingroups[TEGRA_MAX_PINGROUP] = {
+       DRIVE_PINGROUP(AO1,             0x868),
+       DRIVE_PINGROUP(AO2,             0x86c),
+       DRIVE_PINGROUP(AT1,             0x870),
+       DRIVE_PINGROUP(AT2,             0x874),
+       DRIVE_PINGROUP(CDEV1,           0x878),
+       DRIVE_PINGROUP(CDEV2,           0x87c),
+       DRIVE_PINGROUP(CSUS,            0x880),
+       DRIVE_PINGROUP(DAP1,            0x884),
+       DRIVE_PINGROUP(DAP2,            0x888),
+       DRIVE_PINGROUP(DAP3,            0x88c),
+       DRIVE_PINGROUP(DAP4,            0x890),
+       DRIVE_PINGROUP(DBG,             0x894),
+       DRIVE_PINGROUP(LCD1,            0x898),
+       DRIVE_PINGROUP(LCD2,            0x89c),
+       DRIVE_PINGROUP(SDMMC2,  0x8a0),
+       DRIVE_PINGROUP(SDMMC3,  0x8a4),
+       DRIVE_PINGROUP(SPI,             0x8a8),
+       DRIVE_PINGROUP(UAA,             0x8ac),
+       DRIVE_PINGROUP(UAB,             0x8b0),
+       DRIVE_PINGROUP(UART2,           0x8b4),
+       DRIVE_PINGROUP(UART3,           0x8b8),
+       DRIVE_PINGROUP(VI1,             0x8bc),
+       DRIVE_PINGROUP(VI2,             0x8c0),
+       DRIVE_PINGROUP(XM2A,            0x8c4),
+       DRIVE_PINGROUP(XM2C,            0x8c8),
+       DRIVE_PINGROUP(XM2D,            0x8cc),
+       DRIVE_PINGROUP(XM2CLK,  0x8d0),
+       DRIVE_PINGROUP(MEMCOMP, 0x8d4),
+};
+
+static const char *tegra_drive_names[TEGRA_MAX_DRIVE] = {
+       [TEGRA_DRIVE_DIV_8] = "DIV_8",
+       [TEGRA_DRIVE_DIV_4] = "DIV_4",
+       [TEGRA_DRIVE_DIV_2] = "DIV_2",
+       [TEGRA_DRIVE_DIV_1] = "DIV_1",
+};
+
+static const char *tegra_slew_names[TEGRA_MAX_SLEW] = {
+       [TEGRA_SLEW_FASTEST] = "FASTEST",
+       [TEGRA_SLEW_FAST] = "FAST",
+       [TEGRA_SLEW_SLOW] = "SLOW",
+       [TEGRA_SLEW_SLOWEST] = "SLOWEST",
+};
+
+static DEFINE_SPINLOCK(mux_lock);
+
+static const char *pingroup_name(enum tegra_pingroup pg)
+{
+       if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
+               return "<UNKNOWN>";
+
+       return pingroups[pg].name;
+}
+
+static const char *func_name(enum tegra_mux_func func)
+{
+       if (func == TEGRA_MUX_RSVD1)
+               return "RSVD1";
+
+       if (func == TEGRA_MUX_RSVD2)
+               return "RSVD2";
+
+       if (func == TEGRA_MUX_RSVD3)
+               return "RSVD3";
+
+       if (func == TEGRA_MUX_RSVD4)
+               return "RSVD4";
+
+       if (func == TEGRA_MUX_NONE)
+               return "NONE";
+
+       if (func < 0 || func >=  TEGRA_MAX_MUX)
+               return "<UNKNOWN>";
+
+       return tegra_mux_names[func];
+}
+
+
+static const char *tri_name(unsigned long val)
+{
+       return val ? "TRISTATE" : "NORMAL";
+}
+
+static const char *pupd_name(unsigned long val)
+{
+       switch (val) {
+       case 0:
+               return "NORMAL";
+
+       case 1:
+               return "PULL_DOWN";
+
+       case 2:
+               return "PULL_UP";
+
+       default:
+               return "RSVD";
+       }
+}
+
+
+static inline unsigned long pg_readl(unsigned long offset)
+{
+       return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+}
+
+static inline void pg_writel(unsigned long value, unsigned long offset)
+{
+       writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+}
+
+int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func)
+{
+       int mux = -1;
+       int i;
+       unsigned long reg;
+       unsigned long flags;
+
+       if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
+               return -ERANGE;
+
+       if (pingroups[pg].mux_reg == REG_N)
+               return -EINVAL;
+
+       if (func < 0)
+               return -ERANGE;
+
+       if (func & TEGRA_MUX_RSVD) {
+               mux = func & 0x3;
+       } else {
+               for (i = 0; i < 4; i++) {
+                       if (pingroups[pg].funcs[i] == func) {
+                               mux = i;
+                               break;
+                       }
+               }
+       }
+
+       if (mux < 0)
+               return -EINVAL;
+
+       spin_lock_irqsave(&mux_lock, flags);
+
+       reg = pg_readl(TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg));
+       reg &= ~(0x3 << pingroups[pg].mux_bit);
+       reg |= mux << pingroups[pg].mux_bit;
+       pg_writel(reg, TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg));
+
+       spin_unlock_irqrestore(&mux_lock, flags);
+
+       return 0;
+}
+
+int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
+       enum tegra_tristate tristate)
+{
+       unsigned long reg;
+       unsigned long flags;
+
+       if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
+               return -ERANGE;
+
+       if (pingroups[pg].tri_reg == REG_N)
+               return -EINVAL;
+
+       spin_lock_irqsave(&mux_lock, flags);
+
+       reg = pg_readl(TEGRA_TRI_STATE(pingroups[pg].tri_reg));
+       reg &= ~(0x1 << pingroups[pg].tri_bit);
+       if (tristate)
+               reg |= 1 << pingroups[pg].tri_bit;
+       pg_writel(reg, TEGRA_TRI_STATE(pingroups[pg].tri_reg));
+
+       spin_unlock_irqrestore(&mux_lock, flags);
+
+       return 0;
+}
+
+int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
+       enum tegra_pullupdown pupd)
+{
+       unsigned long reg;
+       unsigned long flags;
+
+       if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
+               return -ERANGE;
+
+       if (pingroups[pg].pupd_reg == REG_N)
+               return -EINVAL;
+
+       if (pupd != TEGRA_PUPD_NORMAL &&
+           pupd != TEGRA_PUPD_PULL_DOWN &&
+           pupd != TEGRA_PUPD_PULL_UP)
+               return -EINVAL;
+
+
+       spin_lock_irqsave(&mux_lock, flags);
+
+       reg = pg_readl(TEGRA_PP_PU_PD(pingroups[pg].pupd_reg));
+       reg &= ~(0x3 << pingroups[pg].pupd_bit);
+       reg |= pupd << pingroups[pg].pupd_bit;
+       pg_writel(reg, TEGRA_PP_PU_PD(pingroups[pg].pupd_reg));
+
+       spin_unlock_irqrestore(&mux_lock, flags);
+
+       return 0;
+}
+
+void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
+                                enum tegra_mux_func func,
+                                enum tegra_pullupdown pupd,
+                                enum tegra_tristate tristate)
+{
+       int err;
+
+       if (pingroups[pingroup].mux_reg != REG_N) {
+               err = tegra_pinmux_set_func(pingroup, func);
+               if (err < 0)
+                       pr_err("pinmux: can't set pingroup %s func to %s: %d\n",
+                              pingroup_name(pingroup), func_name(func), err);
+       }
+
+       if (pingroups[pingroup].pupd_reg != REG_N) {
+               err = tegra_pinmux_set_pullupdown(pingroup, pupd);
+               if (err < 0)
+                       pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n",
+                              pingroup_name(pingroup), pupd_name(pupd), err);
+       }
+
+       if (pingroups[pingroup].tri_reg != REG_N) {
+               err = tegra_pinmux_set_tristate(pingroup, tristate);
+               if (err < 0)
+                       pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n",
+                              pingroup_name(pingroup), tri_name(func), err);
+       }
+}
+
+
+
+void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               tegra_pinmux_config_pingroup(config[i].pingroup,
+                                            config[i].func,
+                                            config[i].pupd,
+                                            config[i].tristate);
+}
+
+static const char *drive_pinmux_name(enum tegra_drive_pingroup pg)
+{
+       if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+               return "<UNKNOWN>";
+
+       return drive_pingroups[pg].name;
+}
+
+static const char *enable_name(unsigned long val)
+{
+       return val ? "ENABLE" : "DISABLE";
+}
+
+static const char *drive_name(unsigned long val)
+{
+       if (val >= TEGRA_MAX_DRIVE)
+               return "<UNKNOWN>";
+
+       return tegra_drive_names[val];
+}
+
+static const char *slew_name(unsigned long val)
+{
+       if (val >= TEGRA_MAX_SLEW)
+               return "<UNKNOWN>";
+
+       return tegra_slew_names[val];
+}
+
+static int tegra_drive_pinmux_set_hsm(enum tegra_drive_pingroup pg,
+       enum tegra_hsm hsm)
+{
+       unsigned long flags;
+       u32 reg;
+       if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+               return -ERANGE;
+
+       if (hsm != TEGRA_HSM_ENABLE && hsm != TEGRA_HSM_DISABLE)
+               return -EINVAL;
+
+       spin_lock_irqsave(&mux_lock, flags);
+
+       reg = pg_readl(drive_pingroups[pg].reg);
+       if (hsm == TEGRA_HSM_ENABLE)
+               reg |= (1 << 2);
+       else
+               reg &= ~(1 << 2);
+       pg_writel(reg, drive_pingroups[pg].reg);
+
+       spin_unlock_irqrestore(&mux_lock, flags);
+
+       return 0;
+}
+
+static int tegra_drive_pinmux_set_schmitt(enum tegra_drive_pingroup pg,
+       enum tegra_schmitt schmitt)
+{
+       unsigned long flags;
+       u32 reg;
+       if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+               return -ERANGE;
+
+       if (schmitt != TEGRA_SCHMITT_ENABLE && schmitt != TEGRA_SCHMITT_DISABLE)
+               return -EINVAL;
+
+       spin_lock_irqsave(&mux_lock, flags);
+
+       reg = pg_readl(drive_pingroups[pg].reg);
+       if (schmitt == TEGRA_SCHMITT_ENABLE)
+               reg |= (1 << 3);
+       else
+               reg &= ~(1 << 3);
+       pg_writel(reg, drive_pingroups[pg].reg);
+
+       spin_unlock_irqrestore(&mux_lock, flags);
+
+       return 0;
+}
+
+static int tegra_drive_pinmux_set_drive(enum tegra_drive_pingroup pg,
+       enum tegra_drive drive)
+{
+       unsigned long flags;
+       u32 reg;
+       if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+               return -ERANGE;
+
+       if (drive < 0 || drive >= TEGRA_MAX_DRIVE)
+               return -EINVAL;
+
+       spin_lock_irqsave(&mux_lock, flags);
+
+       reg = pg_readl(drive_pingroups[pg].reg);
+       reg &= ~(0x3 << 4);
+       reg |= drive << 4;
+       pg_writel(reg, drive_pingroups[pg].reg);
+
+       spin_unlock_irqrestore(&mux_lock, flags);
+
+       return 0;
+}
+
+static int tegra_drive_pinmux_set_pull_down(enum tegra_drive_pingroup pg,
+       enum tegra_pull_strength pull_down)
+{
+       unsigned long flags;
+       u32 reg;
+       if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+               return -ERANGE;
+
+       if (pull_down < 0 || pull_down >= TEGRA_MAX_PULL)
+               return -EINVAL;
+
+       spin_lock_irqsave(&mux_lock, flags);
+
+       reg = pg_readl(drive_pingroups[pg].reg);
+       reg &= ~(0x1f << 12);
+       reg |= pull_down << 12;
+       pg_writel(reg, drive_pingroups[pg].reg);
+
+       spin_unlock_irqrestore(&mux_lock, flags);
+
+       return 0;
+}
+
+static int tegra_drive_pinmux_set_pull_up(enum tegra_drive_pingroup pg,
+       enum tegra_pull_strength pull_up)
+{
+       unsigned long flags;
+       u32 reg;
+       if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+               return -ERANGE;
+
+       if (pull_up < 0 || pull_up >= TEGRA_MAX_PULL)
+               return -EINVAL;
+
+       spin_lock_irqsave(&mux_lock, flags);
+
+       reg = pg_readl(drive_pingroups[pg].reg);
+       reg &= ~(0x1f << 12);
+       reg |= pull_up << 12;
+       pg_writel(reg, drive_pingroups[pg].reg);
+
+       spin_unlock_irqrestore(&mux_lock, flags);
+
+       return 0;
+}
+
+static int tegra_drive_pinmux_set_slew_rising(enum tegra_drive_pingroup pg,
+       enum tegra_slew slew_rising)
+{
+       unsigned long flags;
+       u32 reg;
+       if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+               return -ERANGE;
+
+       if (slew_rising < 0 || slew_rising >= TEGRA_MAX_SLEW)
+               return -EINVAL;
+
+       spin_lock_irqsave(&mux_lock, flags);
+
+       reg = pg_readl(drive_pingroups[pg].reg);
+       reg &= ~(0x3 << 28);
+       reg |= slew_rising << 28;
+       pg_writel(reg, drive_pingroups[pg].reg);
+
+       spin_unlock_irqrestore(&mux_lock, flags);
+
+       return 0;
+}
+
+static int tegra_drive_pinmux_set_slew_falling(enum tegra_drive_pingroup pg,
+       enum tegra_slew slew_falling)
+{
+       unsigned long flags;
+       u32 reg;
+       if (pg < 0 || pg >=  TEGRA_MAX_DRIVE_PINGROUP)
+               return -ERANGE;
+
+       if (slew_falling < 0 || slew_falling >= TEGRA_MAX_SLEW)
+               return -EINVAL;
+
+       spin_lock_irqsave(&mux_lock, flags);
+
+       reg = pg_readl(drive_pingroups[pg].reg);
+       reg &= ~(0x3 << 30);
+       reg |= slew_falling << 30;
+       pg_writel(reg, drive_pingroups[pg].reg);
+
+       spin_unlock_irqrestore(&mux_lock, flags);
+
+       return 0;
+}
+
+static void tegra_drive_pinmux_config_pingroup(enum tegra_drive_pingroup pingroup,
+                                         enum tegra_hsm hsm,
+                                         enum tegra_schmitt schmitt,
+                                         enum tegra_drive drive,
+                                         enum tegra_pull_strength pull_down,
+                                         enum tegra_pull_strength pull_up,
+                                         enum tegra_slew slew_rising,
+                                         enum tegra_slew slew_falling)
+{
+       int err;
+
+       err = tegra_drive_pinmux_set_hsm(pingroup, hsm);
+       if (err < 0)
+               pr_err("pinmux: can't set pingroup %s hsm to %s: %d\n",
+                       drive_pinmux_name(pingroup),
+                       enable_name(hsm), err);
+
+       err = tegra_drive_pinmux_set_schmitt(pingroup, schmitt);
+       if (err < 0)
+               pr_err("pinmux: can't set pingroup %s schmitt to %s: %d\n",
+                       drive_pinmux_name(pingroup),
+                       enable_name(schmitt), err);
+
+       err = tegra_drive_pinmux_set_drive(pingroup, drive);
+       if (err < 0)
+               pr_err("pinmux: can't set pingroup %s drive to %s: %d\n",
+                       drive_pinmux_name(pingroup),
+                       drive_name(drive), err);
+
+       err = tegra_drive_pinmux_set_pull_down(pingroup, pull_down);
+       if (err < 0)
+               pr_err("pinmux: can't set pingroup %s pull down to %d: %d\n",
+                       drive_pinmux_name(pingroup),
+                       pull_down, err);
+
+       err = tegra_drive_pinmux_set_pull_up(pingroup, pull_up);
+       if (err < 0)
+               pr_err("pinmux: can't set pingroup %s pull up to %d: %d\n",
+                       drive_pinmux_name(pingroup),
+                       pull_up, err);
+
+       err = tegra_drive_pinmux_set_slew_rising(pingroup, slew_rising);
+       if (err < 0)
+               pr_err("pinmux: can't set pingroup %s rising slew to %s: %d\n",
+                       drive_pinmux_name(pingroup),
+                       slew_name(slew_rising), err);
+
+       err = tegra_drive_pinmux_set_slew_falling(pingroup, slew_falling);
+       if (err < 0)
+               pr_err("pinmux: can't set pingroup %s falling slew to %s: %d\n",
+                       drive_pinmux_name(pingroup),
+                       slew_name(slew_falling), err);
+}
+
+void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
+       int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               tegra_drive_pinmux_config_pingroup(config[i].pingroup,
+                                                    config[i].hsm,
+                                                    config[i].schmitt,
+                                                    config[i].drive,
+                                                    config[i].pull_down,
+                                                    config[i].pull_up,
+                                                    config[i].slew_rising,
+                                                    config[i].slew_falling);
+}
+
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static void dbg_pad_field(struct seq_file *s, int len)
+{
+       seq_putc(s, ',');
+
+       while (len-- > -1)
+               seq_putc(s, ' ');
+}
+
+static int dbg_pinmux_show(struct seq_file *s, void *unused)
+{
+       int i;
+       int len;
+
+       for (i = 0; i < TEGRA_MAX_PINGROUP; i++) {
+               unsigned long tri;
+               unsigned long mux;
+               unsigned long pupd;
+
+               seq_printf(s, "\t{TEGRA_PINGROUP_%s", pingroups[i].name);
+               len = strlen(pingroups[i].name);
+               dbg_pad_field(s, 5 - len);
+
+               if (pingroups[i].mux_reg == REG_N) {
+                       seq_printf(s, "TEGRA_MUX_NONE");
+                       len = strlen("NONE");
+               } else {
+                       mux = (pg_readl(TEGRA_PP_MUX_CTL(pingroups[i].mux_reg)) >>
+                              pingroups[i].mux_bit) & 0x3;
+                       if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
+                               seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
+                               len = 5;
+                       } else {
+                               seq_printf(s, "TEGRA_MUX_%s",
+                                          tegra_mux_names[pingroups[i].funcs[mux]]);
+                               len = strlen(tegra_mux_names[pingroups[i].funcs[mux]]);
+                       }
+               }
+               dbg_pad_field(s, 13-len);
+
+               if (pingroups[i].mux_reg == REG_N) {
+                       seq_printf(s, "TEGRA_PUPD_NORMAL");
+                       len = strlen("NORMAL");
+               } else {
+                       pupd = (pg_readl(TEGRA_PP_PU_PD(pingroups[i].pupd_reg)) >>
+                               pingroups[i].pupd_bit) & 0x3;
+                       seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
+                       len = strlen(pupd_name(pupd));
+               }
+               dbg_pad_field(s, 9 - len);
+
+               if (pingroups[i].tri_reg == REG_N) {
+                       seq_printf(s, "TEGRA_TRI_NORMAL");
+               } else {
+                       tri = (pg_readl(TEGRA_TRI_STATE(pingroups[i].tri_reg)) >>
+                              pingroups[i].tri_bit) & 0x1;
+
+                       seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
+               }
+               seq_printf(s, "},\n");
+       }
+       return 0;
+}
+
+static int dbg_pinmux_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dbg_pinmux_show, &inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+       .open           = dbg_pinmux_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int dbg_drive_pinmux_show(struct seq_file *s, void *unused)
+{
+       int i;
+       int len;
+
+       for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) {
+               u32 reg;
+
+               seq_printf(s, "\t{TEGRA_DRIVE_PINGROUP_%s",
+                       drive_pingroups[i].name);
+               len = strlen(drive_pingroups[i].name);
+               dbg_pad_field(s, 7 - len);
+
+
+               reg = pg_readl(drive_pingroups[i].reg);
+               if (HSM_EN(reg)) {
+                       seq_printf(s, "TEGRA_HSM_ENABLE");
+                       len = 16;
+               } else {
+                       seq_printf(s, "TEGRA_HSM_DISABLE");
+                       len = 17;
+               }
+               dbg_pad_field(s, 17 - len);
+
+               if (SCHMT_EN(reg)) {
+                       seq_printf(s, "TEGRA_SCHMITT_ENABLE");
+                       len = 21;
+               } else {
+                       seq_printf(s, "TEGRA_SCHMITT_DISABLE");
+                       len = 22;
+               }
+               dbg_pad_field(s, 22 - len);
+
+               seq_printf(s, "TEGRA_DRIVE_%s", drive_name(LPMD(reg)));
+               len = strlen(drive_name(LPMD(reg)));
+               dbg_pad_field(s, 5 - len);
+
+               seq_printf(s, "TEGRA_PULL_%d", DRVDN(reg));
+               len = DRVDN(reg) < 10 ? 1 : 2;
+               dbg_pad_field(s, 2 - len);
+
+               seq_printf(s, "TEGRA_PULL_%d", DRVUP(reg));
+               len = DRVUP(reg) < 10 ? 1 : 2;
+               dbg_pad_field(s, 2 - len);
+
+               seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWR(reg)));
+               len = strlen(slew_name(SLWR(reg)));
+               dbg_pad_field(s, 7 - len);
+
+               seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWF(reg)));
+
+               seq_printf(s, "},\n");
+       }
+       return 0;
+}
+
+static int dbg_drive_pinmux_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dbg_drive_pinmux_show, &inode->i_private);
+}
+
+static const struct file_operations debug_drive_fops = {
+       .open           = dbg_drive_pinmux_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int __init tegra_pinmux_debuginit(void)
+{
+       (void) debugfs_create_file("tegra_pinmux", S_IRUGO,
+                                       NULL, NULL, &debug_fops);
+       (void) debugfs_create_file("tegra_pinmux_drive", S_IRUGO,
+                                       NULL, NULL, &debug_drive_fops);
+       return 0;
+}
+late_initcall(tegra_pinmux_debuginit);
+#endif
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
new file mode 100644 (file)
index 0000000..1c0fd92
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ *  linux/arch/arm/mach-tegra/platsmp.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ *  Copyright (C) 2009 Palm
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/localtimer.h>
+#include <asm/smp_scu.h>
+
+#include <mach/iomap.h>
+
+extern void tegra_secondary_startup(void);
+
+static DEFINE_SPINLOCK(boot_lock);
+static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
+
+#define EVP_CPU_RESET_VECTOR \
+       (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
+#define CLK_RST_CONTROLLER_CLK_CPU_CMPLX \
+       (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x4c)
+#define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \
+       (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344)
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+       trace_hardirqs_off();
+
+       /*
+        * if any interrupts are already enabled for the primary
+        * core (e.g. timer irq), then they will not have been enabled
+        * for us: do so
+        */
+       gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x100);
+
+       /*
+        * Synchronise with the boot thread.
+        */
+       spin_lock(&boot_lock);
+       spin_unlock(&boot_lock);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+       unsigned long old_boot_vector;
+       unsigned long boot_vector;
+       unsigned long timeout;
+       u32 reg;
+
+       /*
+        * set synchronisation state between this boot processor
+        * and the secondary one
+        */
+       spin_lock(&boot_lock);
+
+
+       /* set the reset vector to point to the secondary_startup routine */
+
+       boot_vector = virt_to_phys(tegra_secondary_startup);
+       old_boot_vector = readl(EVP_CPU_RESET_VECTOR);
+       writel(boot_vector, EVP_CPU_RESET_VECTOR);
+
+       /* enable cpu clock on cpu1 */
+       reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+       writel(reg & ~(1<<9), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+
+       reg = (1<<13) | (1<<9) | (1<<5) | (1<<1);
+       writel(reg, CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+
+       smp_wmb();
+       flush_cache_all();
+
+       /* unhalt the cpu */
+       writel(0, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x14);
+
+       timeout = jiffies + (1 * HZ);
+       while (time_before(jiffies, timeout)) {
+               if (readl(EVP_CPU_RESET_VECTOR) != boot_vector)
+                       break;
+               udelay(10);
+       }
+
+       /* put the old boot vector back */
+       writel(old_boot_vector, EVP_CPU_RESET_VECTOR);
+
+       /*
+        * now the secondary core is starting up let it run its
+        * calibrations, then wait for it to finish
+        */
+       spin_unlock(&boot_lock);
+
+       return 0;
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+       unsigned int i, ncores = scu_get_core_count(scu_base);
+
+       for (i = 0; i < ncores; i++)
+               cpu_set(i, cpu_possible_map);
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+       unsigned int ncores = scu_get_core_count(scu_base);
+       unsigned int cpu = smp_processor_id();
+       int i;
+
+       smp_store_cpu_info(cpu);
+
+       /*
+        * are we trying to boot more cores than exist?
+        */
+       if (max_cpus > ncores)
+               max_cpus = ncores;
+
+       /*
+        * Initialise the present map, which describes the set of CPUs
+        * actually populated at the present time.
+        */
+       for (i = 0; i < max_cpus; i++)
+               set_cpu_present(i, true);
+
+       /*
+        * Initialise the SCU if there are more than one CPU and let
+        * them know where to start. Note that, on modern versions of
+        * MILO, the "poke" doesn't actually do anything until each
+        * individual core is sent a soft interrupt to get it out of
+        * WFI
+        */
+       if (max_cpus > 1) {
+               percpu_timer_setup();
+               scu_enable(scu_base);
+       }
+}
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
new file mode 100644 (file)
index 0000000..4261632
--- /dev/null
@@ -0,0 +1,1359 @@
+/*
+ * arch/arm/mach-tegra/tegra2_clocks.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/hrtimer.h>
+
+#include <asm/clkdev.h>
+
+#include <mach/iomap.h>
+
+#include "clock.h"
+
+#define RST_DEVICES                    0x004
+#define RST_DEVICES_SET                        0x300
+#define RST_DEVICES_CLR                        0x304
+
+#define CLK_OUT_ENB                    0x010
+#define CLK_OUT_ENB_SET                        0x320
+#define CLK_OUT_ENB_CLR                        0x324
+
+#define OSC_CTRL                       0x50
+#define OSC_CTRL_OSC_FREQ_MASK         (3<<30)
+#define OSC_CTRL_OSC_FREQ_13MHZ                (0<<30)
+#define OSC_CTRL_OSC_FREQ_19_2MHZ      (1<<30)
+#define OSC_CTRL_OSC_FREQ_12MHZ                (2<<30)
+#define OSC_CTRL_OSC_FREQ_26MHZ                (3<<30)
+
+#define OSC_FREQ_DET                   0x58
+#define OSC_FREQ_DET_TRIG              (1<<31)
+
+#define OSC_FREQ_DET_STATUS            0x5C
+#define OSC_FREQ_DET_BUSY              (1<<31)
+#define OSC_FREQ_DET_CNT_MASK          0xFFFF
+
+#define PERIPH_CLK_SOURCE_MASK         (3<<30)
+#define PERIPH_CLK_SOURCE_SHIFT                30
+#define PERIPH_CLK_SOURCE_ENABLE       (1<<28)
+#define PERIPH_CLK_SOURCE_DIV_MASK     0xFF
+#define PERIPH_CLK_SOURCE_DIV_SHIFT    0
+
+#define PLL_BASE                       0x0
+#define PLL_BASE_BYPASS                        (1<<31)
+#define PLL_BASE_ENABLE                        (1<<30)
+#define PLL_BASE_REF_ENABLE            (1<<29)
+#define PLL_BASE_OVERRIDE              (1<<28)
+#define PLL_BASE_LOCK                  (1<<27)
+#define PLL_BASE_DIVP_MASK             (0x7<<20)
+#define PLL_BASE_DIVP_SHIFT            20
+#define PLL_BASE_DIVN_MASK             (0x3FF<<8)
+#define PLL_BASE_DIVN_SHIFT            8
+#define PLL_BASE_DIVM_MASK             (0x1F)
+#define PLL_BASE_DIVM_SHIFT            0
+
+#define PLL_OUT_RATIO_MASK             (0xFF<<8)
+#define PLL_OUT_RATIO_SHIFT            8
+#define PLL_OUT_OVERRIDE               (1<<2)
+#define PLL_OUT_CLKEN                  (1<<1)
+#define PLL_OUT_RESET_DISABLE          (1<<0)
+
+#define PLL_MISC(c)                    (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
+#define PLL_MISC_DCCON_SHIFT           20
+#define PLL_MISC_LOCK_ENABLE           (1<<18)
+#define PLL_MISC_CPCON_SHIFT           8
+#define PLL_MISC_CPCON_MASK            (0xF<<PLL_MISC_CPCON_SHIFT)
+#define PLL_MISC_LFCON_SHIFT           4
+#define PLL_MISC_LFCON_MASK            (0xF<<PLL_MISC_LFCON_SHIFT)
+#define PLL_MISC_VCOCON_SHIFT          0
+#define PLL_MISC_VCOCON_MASK           (0xF<<PLL_MISC_VCOCON_SHIFT)
+
+#define PLLD_MISC_CLKENABLE            (1<<30)
+#define PLLD_MISC_DIV_RST              (1<<23)
+#define PLLD_MISC_DCCON_SHIFT          12
+
+#define PERIPH_CLK_TO_ENB_REG(c)       ((c->clk_num / 32) * 4)
+#define PERIPH_CLK_TO_ENB_SET_REG(c)   ((c->clk_num / 32) * 8)
+#define PERIPH_CLK_TO_ENB_BIT(c)       (1 << (c->clk_num % 32))
+
+#define SUPER_CLK_MUX                  0x00
+#define SUPER_STATE_SHIFT              28
+#define SUPER_STATE_MASK               (0xF << SUPER_STATE_SHIFT)
+#define SUPER_STATE_STANDBY            (0x0 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_IDLE               (0x1 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_RUN                        (0x2 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_IRQ                        (0x3 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_FIQ                        (0x4 << SUPER_STATE_SHIFT)
+#define SUPER_SOURCE_MASK              0xF
+#define        SUPER_FIQ_SOURCE_SHIFT          12
+#define        SUPER_IRQ_SOURCE_SHIFT          8
+#define        SUPER_RUN_SOURCE_SHIFT          4
+#define        SUPER_IDLE_SOURCE_SHIFT         0
+
+#define SUPER_CLK_DIVIDER              0x04
+
+#define BUS_CLK_DISABLE                        (1<<3)
+#define BUS_CLK_DIV_MASK               0x3
+
+static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
+
+#define clk_writel(value, reg) \
+       __raw_writel(value, (u32)reg_clk_base + (reg))
+#define clk_readl(reg) \
+       __raw_readl((u32)reg_clk_base + (reg))
+
+unsigned long clk_measure_input_freq(void)
+{
+       u32 clock_autodetect;
+       clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
+       do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
+       clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);
+       if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) {
+               return 12000000;
+       } else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) {
+               return 13000000;
+       } else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) {
+               return 19200000;
+       } else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) {
+               return 26000000;
+       } else {
+               pr_err("%s: Unexpected clock autodetect value %d", __func__, clock_autodetect);
+               BUG();
+               return 0;
+       }
+}
+
+static int clk_div71_get_divider(struct clk *c, unsigned long rate)
+{
+       unsigned long divider_u71;
+
+       divider_u71 = DIV_ROUND_UP(c->rate * 2, rate);
+
+       if (divider_u71 - 2 > 255 || divider_u71 - 2 < 0)
+               return -EINVAL;
+
+       return divider_u71 - 2;
+}
+
+static unsigned long tegra2_clk_recalculate_rate(struct clk *c)
+{
+       unsigned long rate;
+       rate = c->parent->rate;
+
+       if (c->mul != 0 && c->div != 0)
+               c->rate = rate * c->mul / c->div;
+       else
+               c->rate = rate;
+       return c->rate;
+}
+
+
+/* clk_m functions */
+static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c)
+{
+       u32 auto_clock_control = clk_readl(OSC_CTRL) & ~OSC_CTRL_OSC_FREQ_MASK;
+
+       c->rate = clk_measure_input_freq();
+       switch (c->rate) {
+       case 12000000:
+               auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
+               break;
+       case 13000000:
+               auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ;
+               break;
+       case 19200000:
+               auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ;
+               break;
+       case 26000000:
+               auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ;
+               break;
+       default:
+               pr_err("%s: Unexpected clock rate %ld", __func__, c->rate);
+               BUG();
+       }
+       clk_writel(auto_clock_control, OSC_CTRL);
+       return c->rate;
+}
+
+static void tegra2_clk_m_init(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+       tegra2_clk_m_autodetect_rate(c);
+}
+
+static int tegra2_clk_m_enable(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+       return 0;
+}
+
+static void tegra2_clk_m_disable(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+       BUG();
+}
+
+static struct clk_ops tegra_clk_m_ops = {
+       .init           = tegra2_clk_m_init,
+       .enable         = tegra2_clk_m_enable,
+       .disable        = tegra2_clk_m_disable,
+};
+
+/* super clock functions */
+/* "super clocks" on tegra have two-stage muxes and a clock skipping
+ * super divider.  We will ignore the clock skipping divider, since we
+ * can't lower the voltage when using the clock skip, but we can if we
+ * lower the PLL frequency.
+ */
+static void tegra2_super_clk_init(struct clk *c)
+{
+       u32 val;
+       int source;
+       int shift;
+       const struct clk_mux_sel *sel;
+       val = clk_readl(c->reg + SUPER_CLK_MUX);
+       c->state = ON;
+       BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
+               ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
+       shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
+               SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
+       source = (val >> shift) & SUPER_SOURCE_MASK;
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->value == source)
+                       break;
+       }
+       BUG_ON(sel->input == NULL);
+       c->parent = sel->input;
+       tegra2_clk_recalculate_rate(c);
+}
+
+static int tegra2_super_clk_enable(struct clk *c)
+{
+       clk_writel(0, c->reg + SUPER_CLK_DIVIDER);
+       return 0;
+}
+
+static void tegra2_super_clk_disable(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       /* oops - don't disable the CPU clock! */
+       BUG();
+}
+
+static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p)
+{
+       u32 val;
+       const struct clk_mux_sel *sel;
+       int shift;
+       val = clk_readl(c->reg + SUPER_CLK_MUX);;
+       BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
+               ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
+       shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
+               SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->input == p) {
+                       clk_reparent(c, p);
+                       val &= ~(SUPER_SOURCE_MASK << shift);
+                       val |= sel->value << shift;
+                       clk_writel(val, c->reg);
+                       c->rate = c->parent->rate;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_super_ops = {
+       .init                   = tegra2_super_clk_init,
+       .enable                 = tegra2_super_clk_enable,
+       .disable                = tegra2_super_clk_disable,
+       .set_parent             = tegra2_super_clk_set_parent,
+       .recalculate_rate       = tegra2_clk_recalculate_rate,
+};
+
+/* bus clock functions */
+static void tegra2_bus_clk_init(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
+       c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
+       c->mul = 1;
+       tegra2_clk_recalculate_rate(c);
+}
+
+static int tegra2_bus_clk_enable(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       val &= ~(BUS_CLK_DISABLE << c->reg_shift);
+       clk_writel(val, c->reg);
+       return 0;
+}
+
+static void tegra2_bus_clk_disable(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       val |= BUS_CLK_DISABLE << c->reg_shift;
+       clk_writel(val, c->reg);
+}
+
+static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       u32 val = clk_readl(c->reg);
+       unsigned long parent_rate = c->parent->rate;
+       int i;
+       for (i = 1; i <= 4; i++) {
+               if (rate == parent_rate / i) {
+                       val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
+                       val |= (i - 1) << c->reg_shift;
+                       clk_writel(val, c->reg);
+                       c->div = i;
+                       c->mul = 1;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_bus_ops = {
+       .init                   = tegra2_bus_clk_init,
+       .enable                 = tegra2_bus_clk_enable,
+       .disable                = tegra2_bus_clk_disable,
+       .set_rate               = tegra2_bus_clk_set_rate,
+       .recalculate_rate       = tegra2_clk_recalculate_rate,
+};
+
+/* PLL Functions */
+static unsigned long tegra2_pll_clk_recalculate_rate(struct clk *c)
+{
+       u64 rate;
+       rate = c->parent->rate;
+       rate *= c->n;
+       do_div(rate, c->m);
+       if (c->p == 2)
+               rate >>= 1;
+       c->rate = rate;
+       return c->rate;
+}
+
+static int tegra2_pll_clk_wait_for_lock(struct clk *c)
+{
+       ktime_t before;
+
+       before = ktime_get();
+       while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) {
+               if (ktime_us_delta(ktime_get(), before) > 5000) {
+                       pr_err("Timed out waiting for lock bit on pll %s",
+                               c->name);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static void tegra2_pll_clk_init(struct clk *c)
+{
+       u32 val = clk_readl(c->reg + PLL_BASE);
+
+       c->state = (val & PLL_BASE_ENABLE) ? ON : OFF;
+
+       if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
+               pr_warning("Clock %s has unknown fixed frequency\n", c->name);
+               c->n = 1;
+               c->m = 0;
+               c->p = 1;
+       } else if (val & PLL_BASE_BYPASS) {
+               c->n = 1;
+               c->m = 1;
+               c->p = 1;
+       } else {
+               c->n = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
+               c->m = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
+               c->p = (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
+       }
+
+       val = clk_readl(c->reg + PLL_MISC(c));
+       if (c->flags & PLL_HAS_CPCON)
+               c->cpcon = (val & PLL_MISC_CPCON_MASK) >> PLL_MISC_CPCON_SHIFT;
+
+       tegra2_pll_clk_recalculate_rate(c);
+}
+
+static int tegra2_pll_clk_enable(struct clk *c)
+{
+       u32 val;
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       val = clk_readl(c->reg + PLL_BASE);
+       val &= ~PLL_BASE_BYPASS;
+       val |= PLL_BASE_ENABLE;
+       clk_writel(val, c->reg + PLL_BASE);
+
+       val = clk_readl(c->reg + PLL_MISC(c));
+       val |= PLL_MISC_LOCK_ENABLE;
+       clk_writel(val, c->reg + PLL_MISC(c));
+
+       tegra2_pll_clk_wait_for_lock(c);
+
+       return 0;
+}
+
+static void tegra2_pll_clk_disable(struct clk *c)
+{
+       u32 val;
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       val = clk_readl(c->reg);
+       val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+       clk_writel(val, c->reg);
+}
+
+static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       u32 val;
+       unsigned long input_rate;
+       const struct clk_pll_table *sel;
+
+       pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+       BUG_ON(c->refcnt != 0);
+
+       input_rate = c->parent->rate;
+       for (sel = c->pll_table; sel->input_rate != 0; sel++) {
+               if (sel->input_rate == input_rate && sel->output_rate == rate) {
+                       c->n = sel->n;
+                       c->m = sel->m;
+                       c->p = sel->p;
+                       c->cpcon = sel->cpcon;
+
+                       val = clk_readl(c->reg + PLL_BASE);
+                       if (c->flags & PLL_FIXED)
+                               val |= PLL_BASE_OVERRIDE;
+                       val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK |
+                                PLL_BASE_DIVM_MASK);
+                       val |= (c->m << PLL_BASE_DIVM_SHIFT) |
+                               (c->n << PLL_BASE_DIVN_SHIFT);
+                       BUG_ON(c->p > 2);
+                       if (c->p == 2)
+                               val |= 1 << PLL_BASE_DIVP_SHIFT;
+                       clk_writel(val, c->reg + PLL_BASE);
+
+                       if (c->flags & PLL_HAS_CPCON) {
+                               val = c->cpcon << PLL_MISC_CPCON_SHIFT;
+                               val |= PLL_MISC_LOCK_ENABLE;
+                               clk_writel(val, c->reg + PLL_MISC(c));
+                       }
+
+                       if (c->state == ON)
+                               tegra2_pll_clk_enable(c);
+
+                       c->rate = rate;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_pll_ops = {
+       .init                   = tegra2_pll_clk_init,
+       .enable                 = tegra2_pll_clk_enable,
+       .disable                = tegra2_pll_clk_disable,
+       .set_rate               = tegra2_pll_clk_set_rate,
+       .recalculate_rate       = tegra2_pll_clk_recalculate_rate,
+};
+
+/* Clock divider ops */
+static void tegra2_pll_div_clk_init(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       u32 divu71;
+       val >>= c->reg_shift;
+       c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
+       if (!(val & PLL_OUT_RESET_DISABLE))
+               c->state = OFF;
+
+       if (c->flags & DIV_U71) {
+               divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
+               c->div = (divu71 + 2);
+               c->mul = 2;
+       } else if (c->flags & DIV_2) {
+               c->div = 2;
+               c->mul = 1;
+       } else {
+               c->div = 1;
+               c->mul = 1;
+       }
+
+       tegra2_clk_recalculate_rate(c);
+}
+
+static int tegra2_pll_div_clk_enable(struct clk *c)
+{
+       u32 val;
+       u32 new_val;
+
+       pr_debug("%s: %s\n", __func__, c->name);
+       if (c->flags & DIV_U71) {
+               val = clk_readl(c->reg);
+               new_val = val >> c->reg_shift;
+               new_val &= 0xFFFF;
+
+               new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
+
+               val &= ~(0xFFFF << c->reg_shift);
+               val |= new_val << c->reg_shift;
+               clk_writel(val, c->reg);
+               return 0;
+       } else if (c->flags & DIV_2) {
+               BUG_ON(!(c->flags & PLLD));
+               val = clk_readl(c->reg);
+               val &= ~PLLD_MISC_DIV_RST;
+               clk_writel(val, c->reg);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static void tegra2_pll_div_clk_disable(struct clk *c)
+{
+       u32 val;
+       u32 new_val;
+
+       pr_debug("%s: %s\n", __func__, c->name);
+       if (c->flags & DIV_U71) {
+               val = clk_readl(c->reg);
+               new_val = val >> c->reg_shift;
+               new_val &= 0xFFFF;
+
+               new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE);
+
+               val &= ~(0xFFFF << c->reg_shift);
+               val |= new_val << c->reg_shift;
+               clk_writel(val, c->reg);
+       } else if (c->flags & DIV_2) {
+               BUG_ON(!(c->flags & PLLD));
+               val = clk_readl(c->reg);
+               val |= PLLD_MISC_DIV_RST;
+               clk_writel(val, c->reg);
+       }
+}
+
+static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       u32 val;
+       u32 new_val;
+       int divider_u71;
+       pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+       if (c->flags & DIV_U71) {
+               divider_u71 = clk_div71_get_divider(c->parent, rate);
+               if (divider_u71 >= 0) {
+                       val = clk_readl(c->reg);
+                       new_val = val >> c->reg_shift;
+                       new_val &= 0xFFFF;
+                       if (c->flags & DIV_U71_FIXED)
+                               new_val |= PLL_OUT_OVERRIDE;
+                       new_val &= ~PLL_OUT_RATIO_MASK;
+                       new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT;
+
+                       val &= ~(0xFFFF << c->reg_shift);
+                       val |= new_val << c->reg_shift;
+                       clk_writel(val, c->reg);
+                       c->div = divider_u71 + 2;
+                       c->mul = 2;
+                       tegra2_clk_recalculate_rate(c);
+                       return 0;
+               }
+       } else if (c->flags & DIV_2) {
+               if (c->parent->rate == rate * 2) {
+                       c->rate = rate;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+
+static struct clk_ops tegra_pll_div_ops = {
+       .init                   = tegra2_pll_div_clk_init,
+       .enable                 = tegra2_pll_div_clk_enable,
+       .disable                = tegra2_pll_div_clk_disable,
+       .set_rate               = tegra2_pll_div_clk_set_rate,
+       .recalculate_rate       = tegra2_clk_recalculate_rate,
+};
+
+/* Periph clk ops */
+
+static void tegra2_periph_clk_init(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+       const struct clk_mux_sel *mux = 0;
+       const struct clk_mux_sel *sel;
+       if (c->flags & MUX) {
+               for (sel = c->inputs; sel->input != NULL; sel++) {
+                       if (val >> PERIPH_CLK_SOURCE_SHIFT == sel->value)
+                               mux = sel;
+               }
+               BUG_ON(!mux);
+
+               c->parent = mux->input;
+       } else {
+               c->parent = c->inputs[0].input;
+       }
+
+       if (c->flags & DIV_U71) {
+               u32 divu71 = val & PERIPH_CLK_SOURCE_DIV_MASK;
+               c->div = divu71 + 2;
+               c->mul = 2;
+       } else {
+               c->div = 1;
+               c->mul = 1;
+       }
+
+       c->state = ON;
+       if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
+                       PERIPH_CLK_TO_ENB_BIT(c)))
+               c->state = OFF;
+       if (!(c->flags & PERIPH_NO_RESET))
+               if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
+                               PERIPH_CLK_TO_ENB_BIT(c))
+                       c->state = OFF;
+       tegra2_clk_recalculate_rate(c);
+}
+
+static int tegra2_periph_clk_enable(struct clk *c)
+{
+       u32 val;
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+               CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
+       if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
+               clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+                       RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+       if (c->flags & PERIPH_EMC_ENB) {
+               /* The EMC peripheral clock has 2 extra enable bits */
+               /* FIXME: Do they need to be disabled? */
+               val = clk_readl(c->reg);
+               val |= 0x3 << 24;
+               clk_writel(val, c->reg);
+       }
+       return 0;
+}
+
+static void tegra2_periph_clk_disable(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+               CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+}
+
+void tegra2_periph_reset_deassert(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+       if (!(c->flags & PERIPH_NO_RESET))
+               clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+                       RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+}
+
+void tegra2_periph_reset_assert(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+       if (!(c->flags & PERIPH_NO_RESET))
+               clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+                       RST_DEVICES_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
+}
+
+
+static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
+{
+       u32 val;
+       const struct clk_mux_sel *sel;
+       pr_debug("%s: %s %s\n", __func__, c->name, p->name);
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->input == p) {
+                       clk_reparent(c, p);
+                       val = clk_readl(c->reg);
+                       val &= ~PERIPH_CLK_SOURCE_MASK;
+                       val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT;
+                       clk_writel(val, c->reg);
+                       c->rate = c->parent->rate;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       u32 val;
+       int divider_u71;
+       pr_debug("%s: %lu\n", __func__, rate);
+       if (c->flags & DIV_U71) {
+               divider_u71 = clk_div71_get_divider(c->parent, rate);
+               if (divider_u71 >= 0) {
+                       val = clk_readl(c->reg);
+                       val &= ~PERIPH_CLK_SOURCE_DIV_MASK;
+                       val |= divider_u71;
+                       clk_writel(val, c->reg);
+                       c->div = divider_u71 + 2;
+                       c->mul = 2;
+                       tegra2_clk_recalculate_rate(c);
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_periph_clk_ops = {
+       .init                   = &tegra2_periph_clk_init,
+       .enable                 = &tegra2_periph_clk_enable,
+       .disable                = &tegra2_periph_clk_disable,
+       .set_parent             = &tegra2_periph_clk_set_parent,
+       .set_rate               = &tegra2_periph_clk_set_rate,
+       .recalculate_rate       = &tegra2_clk_recalculate_rate,
+};
+
+/* Clock doubler ops */
+static void tegra2_clk_double_init(struct clk *c)
+{
+       c->mul = 2;
+       c->div = 1;
+       c->state = ON;
+       if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
+                       PERIPH_CLK_TO_ENB_BIT(c)))
+               c->state = OFF;
+       tegra2_clk_recalculate_rate(c);
+};
+
+static struct clk_ops tegra_clk_double_ops = {
+       .init                   = &tegra2_clk_double_init,
+       .enable                 = &tegra2_periph_clk_enable,
+       .disable                = &tegra2_periph_clk_disable,
+       .recalculate_rate       = &tegra2_clk_recalculate_rate,
+};
+
+/* Clock definitions */
+static struct clk tegra_clk_32k = {
+       .name = "clk_32k",
+       .rate = 32678,
+       .ops  = NULL,
+};
+
+static struct clk_pll_table tegra_pll_s_table[] = {
+       {32768, 12000000, 366, 1, 1, 0},
+       {32768, 13000000, 397, 1, 1, 0},
+       {32768, 19200000, 586, 1, 1, 0},
+       {32768, 26000000, 793, 1, 1, 0},
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct clk tegra_pll_s = {
+       .name      = "pll_s",
+       .flags     = PLL_ALT_MISC_REG,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0xf0,
+       .input_min = 32768,
+       .input_max = 32768,
+       .parent    = &tegra_clk_32k,
+       .cf_min    = 0, /* FIXME */
+       .cf_max    = 0, /* FIXME */
+       .vco_min   = 12000000,
+       .vco_max   = 26000000,
+       .pll_table = tegra_pll_s_table,
+};
+
+static struct clk_mux_sel tegra_clk_m_sel[] = {
+       { .input = &tegra_clk_32k, .value = 0},
+       { .input = &tegra_pll_s,  .value = 1},
+       { 0, 0},
+};
+static struct clk tegra_clk_m = {
+       .name      = "clk_m",
+       .flags     = ENABLE_ON_INIT,
+       .ops       = &tegra_clk_m_ops,
+       .inputs    = tegra_clk_m_sel,
+       .reg       = 0x1fc,
+       .reg_mask  = (1<<28),
+       .reg_shift = 28,
+};
+
+static struct clk_pll_table tegra_pll_c_table[] = {
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_c = {
+       .name      = "pll_c",
+       .flags     = PLL_HAS_CPCON,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0x80,
+       .input_min = 2000000,
+       .input_max = 31000000,
+       .parent    = &tegra_clk_m,
+       .cf_min    = 1000000,
+       .cf_max    = 6000000,
+       .vco_min   = 20000000,
+       .vco_max   = 1400000000,
+       .pll_table = tegra_pll_c_table,
+};
+
+static struct clk tegra_pll_c_out1 = {
+       .name      = "pll_c_out1",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = DIV_U71,
+       .parent    = &tegra_pll_c,
+       .reg       = 0x84,
+       .reg_shift = 0,
+};
+
+static struct clk_pll_table tegra_pll_m_table[] = {
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_m = {
+       .name      = "pll_m",
+       .flags     = PLL_HAS_CPCON,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0x90,
+       .input_min = 2000000,
+       .input_max = 31000000,
+       .parent    = &tegra_clk_m,
+       .cf_min    = 1000000,
+       .cf_max    = 6000000,
+       .vco_min   = 20000000,
+       .vco_max   = 1200000000,
+       .pll_table = tegra_pll_m_table,
+};
+
+static struct clk tegra_pll_m_out1 = {
+       .name      = "pll_m_out1",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = DIV_U71,
+       .parent    = &tegra_pll_m,
+       .reg       = 0x94,
+       .reg_shift = 0,
+};
+
+static struct clk_pll_table tegra_pll_p_table[] = {
+       { 12000000, 216000000, 432, 12, 2, 8},
+       { 13000000, 216000000, 432, 13, 2, 8},
+       { 19200000, 216000000, 90,   4, 2, 1},
+       { 26000000, 216000000, 432, 26, 2, 8},
+       { 12000000, 432000000, 432, 12, 1, 8},
+       { 13000000, 432000000, 432, 13, 1, 8},
+       { 19200000, 432000000, 90,   4, 1, 1},
+       { 26000000, 432000000, 432, 26, 1, 8},
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_p = {
+       .name      = "pll_p",
+       .flags     = ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0xa0,
+       .input_min = 2000000,
+       .input_max = 31000000,
+       .parent    = &tegra_clk_m,
+       .cf_min    = 1000000,
+       .cf_max    = 6000000,
+       .vco_min   = 20000000,
+       .vco_max   = 1400000000,
+       .pll_table = tegra_pll_p_table,
+};
+
+static struct clk tegra_pll_p_out1 = {
+       .name      = "pll_p_out1",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+       .parent    = &tegra_pll_p,
+       .reg       = 0xa4,
+       .reg_shift = 0,
+};
+
+static struct clk tegra_pll_p_out2 = {
+       .name      = "pll_p_out2",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+       .parent    = &tegra_pll_p,
+       .reg       = 0xa4,
+       .reg_shift = 16,
+};
+
+static struct clk tegra_pll_p_out3 = {
+       .name      = "pll_p_out3",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+       .parent    = &tegra_pll_p,
+       .reg       = 0xa8,
+       .reg_shift = 0,
+};
+
+static struct clk tegra_pll_p_out4 = {
+       .name      = "pll_p_out4",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
+       .parent    = &tegra_pll_p,
+       .reg       = 0xa8,
+       .reg_shift = 16,
+};
+
+static struct clk_pll_table tegra_pll_a_table[] = {
+       { 28800000, 56448000, 49, 25, 1, 1},
+       { 28800000, 73728000, 64, 25, 1, 1},
+       { 28800000, 11289600, 49, 25, 1, 1},
+       { 28800000, 12288000, 64, 25, 1, 1},
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_a = {
+       .name      = "pll_a",
+       .flags     = PLL_HAS_CPCON,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0xb0,
+       .input_min = 2000000,
+       .input_max = 31000000,
+       .parent    = &tegra_pll_p_out1,
+       .cf_min    = 1000000,
+       .cf_max    = 6000000,
+       .vco_min   = 20000000,
+       .vco_max   = 1400000000,
+       .pll_table = tegra_pll_a_table,
+};
+
+static struct clk tegra_pll_a_out0 = {
+       .name      = "pll_a_out0",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = DIV_U71,
+       .parent    = &tegra_pll_a,
+       .reg       = 0xb4,
+       .reg_shift = 0,
+};
+
+static struct clk_pll_table tegra_pll_d_table[] = {
+       { 12000000, 1000000000, 1000, 12, 1, 12},
+       { 13000000, 1000000000, 1000, 13, 1, 12},
+       { 19200000, 1000000000, 625,  12, 1, 8},
+       { 26000000, 1000000000, 1000, 26, 1, 12},
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_d = {
+       .name      = "pll_d",
+       .flags     = PLL_HAS_CPCON | PLLD,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0xd0,
+       .input_min = 2000000,
+       .input_max = 40000000,
+       .parent    = &tegra_clk_m,
+       .cf_min    = 1000000,
+       .cf_max    = 6000000,
+       .vco_min   = 40000000,
+       .vco_max   = 1000000000,
+       .pll_table = tegra_pll_d_table,
+};
+
+static struct clk tegra_pll_d_out0 = {
+       .name      = "pll_d_out0",
+       .ops       = &tegra_pll_div_ops,
+       .flags     = DIV_2 | PLLD,
+       .parent    = &tegra_pll_d,
+};
+
+static struct clk_pll_table tegra_pll_u_table[] = {
+       { 12000000, 480000000, 960, 12, 1, 0},
+       { 13000000, 480000000, 960, 13, 1, 0},
+       { 19200000, 480000000, 200, 4,  1, 0},
+       { 26000000, 480000000, 960, 26, 1, 0},
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_u = {
+       .name      = "pll_u",
+       .flags     = 0,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0xc0,
+       .input_min = 2000000,
+       .input_max = 40000000,
+       .parent    = &tegra_clk_m,
+       .cf_min    = 1000000,
+       .cf_max    = 6000000,
+       .vco_min   = 480000000,
+       .vco_max   = 960000000,
+       .pll_table = tegra_pll_u_table,
+};
+
+static struct clk_pll_table tegra_pll_x_table[] = {
+       { 12000000, 1000000000, 1000, 12, 1, 12},
+       { 13000000, 1000000000, 1000, 13, 1, 12},
+       { 19200000, 1000000000, 625,  12, 1, 8},
+       { 26000000, 1000000000, 1000, 26, 1, 12},
+       { 12000000, 750000000,  750,  12, 1, 12},
+       { 13000000, 750000000,  750,  13, 1, 12},
+       { 19200000, 750000000,  625,  16, 1, 8},
+       { 26000000, 750000000,  750,  26, 1, 12},
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_x = {
+       .name      = "pll_x",
+       .flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG,
+       .ops       = &tegra_pll_ops,
+       .reg       = 0xe0,
+       .input_min = 2000000,
+       .input_max = 31000000,
+       .parent    = &tegra_clk_m,
+       .cf_min    = 1000000,
+       .cf_max    = 6000000,
+       .vco_min   = 20000000,
+       .vco_max   = 1200000000,
+       .pll_table = tegra_pll_x_table,
+};
+
+static struct clk tegra_clk_d = {
+       .name      = "clk_d",
+       .flags     = PERIPH_NO_RESET,
+       .ops       = &tegra_clk_double_ops,
+       .clk_num   = 90,
+       .reg       = 0x34,
+       .reg_shift = 12,
+       .parent    = &tegra_clk_m,
+};
+
+/* FIXME: need tegra_audio
+static struct clk tegra_clk_audio_2x = {
+       .name      = "clk_d",
+       .flags     = PERIPH_NO_RESET,
+       .ops       = &tegra_clk_double_ops,
+       .clk_num   = 89,
+       .reg       = 0x34,
+       .reg_shift = 8,
+       .parent    = &tegra_audio,
+}
+*/
+
+static struct clk_mux_sel mux_cclk[] = {
+       { .input = &tegra_clk_m,        .value = 0},
+       { .input = &tegra_pll_c,        .value = 1},
+       { .input = &tegra_clk_32k,      .value = 2},
+       { .input = &tegra_pll_m,        .value = 3},
+       { .input = &tegra_pll_p,        .value = 4},
+       { .input = &tegra_pll_p_out4,   .value = 5},
+       { .input = &tegra_pll_p_out3,   .value = 6},
+       { .input = &tegra_clk_d,        .value = 7},
+       { .input = &tegra_pll_x,        .value = 8},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_sclk[] = {
+       { .input = &tegra_clk_m,        .value = 0},
+       { .input = &tegra_pll_c_out1,   .value = 1},
+       { .input = &tegra_pll_p_out4,   .value = 2},
+       { .input = &tegra_pll_p_out3,   .value = 3},
+       { .input = &tegra_pll_p_out2,   .value = 4},
+       { .input = &tegra_clk_d,        .value = 5},
+       { .input = &tegra_clk_32k,      .value = 6},
+       { .input = &tegra_pll_m_out1,   .value = 7},
+       { 0, 0},
+};
+
+static struct clk tegra_clk_cpu = {
+       .name   = "cpu",
+       .inputs = mux_cclk,
+       .reg    = 0x20,
+       .ops    = &tegra_super_ops,
+};
+
+static struct clk tegra_clk_sys = {
+       .name   = "sys",
+       .inputs = mux_sclk,
+       .reg    = 0x28,
+       .ops    = &tegra_super_ops,
+};
+
+static struct clk tegra_clk_hclk = {
+       .name           = "hclk",
+       .flags          = DIV_BUS,
+       .parent         = &tegra_clk_sys,
+       .reg            = 0x30,
+       .reg_shift      = 4,
+       .ops            = &tegra_bus_ops,
+};
+
+static struct clk tegra_clk_pclk = {
+       .name           = "pclk",
+       .flags          = DIV_BUS,
+       .parent         = &tegra_clk_hclk,
+       .reg            = 0x30,
+       .reg_shift      = 0,
+       .ops            = &tegra_bus_ops,
+};
+
+static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
+       { .input = &tegra_pll_m, .value = 0},
+       { .input = &tegra_pll_c, .value = 1},
+       { .input = &tegra_pll_p, .value = 2},
+       { .input = &tegra_pll_a_out0, .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllm_pllc_pllp_clkm[] = {
+       { .input = &tegra_pll_m, .value = 0},
+       { .input = &tegra_pll_c, .value = 1},
+       { .input = &tegra_pll_p, .value = 2},
+       { .input = &tegra_clk_m, .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
+       { .input = &tegra_pll_p, .value = 0},
+       { .input = &tegra_pll_c, .value = 1},
+       { .input = &tegra_pll_m, .value = 2},
+       { .input = &tegra_clk_m, .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_plla_audio_pllp_clkm[] = {
+       {.input = &tegra_pll_a, .value = 0},
+       /* FIXME: no mux defined for tegra_audio
+       {.input = &tegra_audio, .value = 1},*/
+       {.input = &tegra_pll_p, .value = 2},
+       {.input = &tegra_clk_m, .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
+       {.input = &tegra_pll_p, .value = 0},
+       {.input = &tegra_pll_d_out0, .value = 1},
+       {.input = &tegra_pll_c, .value = 2},
+       {.input = &tegra_clk_m, .value = 3},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
+       {.input = &tegra_pll_p,     .value = 0},
+       {.input = &tegra_pll_c,     .value = 1},
+       /* FIXME: no mux defined for tegra_audio
+       {.input = &tegra_audio,     .value = 2},*/
+       {.input = &tegra_clk_m,     .value = 3},
+       {.input = &tegra_clk_32k,   .value = 4},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_pllc_pllm[] = {
+       {.input = &tegra_pll_p,     .value = 0},
+       {.input = &tegra_pll_c,     .value = 1},
+       {.input = &tegra_pll_m,     .value = 2},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_clk_m[] = {
+       { .input = &tegra_clk_m, .value = 0},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_pllp_out3[] = {
+       { .input = &tegra_pll_p_out3, .value = 0},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_plld[] = {
+       { .input = &tegra_pll_d, .value = 0},
+       { 0, 0},
+};
+
+static struct clk_mux_sel mux_clk_32k[] = {
+       { .input = &tegra_clk_32k, .value = 0},
+       { 0, 0},
+};
+
+#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _inputs, _flags) \
+       {                                               \
+               .name      = _name,                     \
+               .lookup    = {                          \
+                       .dev_id    = _dev,              \
+                       .con_id    = _con,              \
+               },                                      \
+               .ops       = &tegra_periph_clk_ops,     \
+               .clk_num   = _clk_num,                  \
+               .reg       = _reg,                      \
+               .inputs    = _inputs,                   \
+               .flags     = _flags,                    \
+       }
+
+struct clk tegra_periph_clks[] = {
+       PERIPH_CLK("rtc",       "rtc-tegra",            NULL,   4,      0,      mux_clk_32k,                    PERIPH_NO_RESET),
+       PERIPH_CLK("timer",     "timer",                NULL,   5,      0,      mux_clk_m,                      0),
+       PERIPH_CLK("i2s1",      "i2s.0",                NULL,   11,     0x100,  mux_plla_audio_pllp_clkm,       MUX | DIV_U71),
+       PERIPH_CLK("i2s2",      "i2s.1",                NULL,   18,     0x104,  mux_plla_audio_pllp_clkm,       MUX | DIV_U71),
+       /* FIXME: spdif has 2 clocks but 1 enable */
+       PERIPH_CLK("spdif_out", "spdif_out",            NULL,   10,     0x108,  mux_plla_audio_pllp_clkm,       MUX | DIV_U71),
+       PERIPH_CLK("spdif_in",  "spdif_in",             NULL,   10,     0x10c,  mux_pllp_pllc_pllm,             MUX | DIV_U71),
+       PERIPH_CLK("pwm",       "pwm",                  NULL,   17,     0x110,  mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71),
+       PERIPH_CLK("spi",       "spi",                  NULL,   43,     0x114,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("xio",       "xio",                  NULL,   45,     0x120,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("twc",       "twc",                  NULL,   16,     0x12c,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("sbc1",      "spi_tegra.0",          NULL,   41,     0x134,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("sbc2",      "spi_tegra.1",          NULL,   44,     0x118,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("sbc3",      "spi_tegra.2",          NULL,   46,     0x11c,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("sbc4",      "spi_tegra.3",          NULL,   68,     0x1b4,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("ide",       "ide",                  NULL,   25,     0x144,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("ndflash",   "tegra_nand",           NULL,   13,     0x160,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       /* FIXME: vfir shares an enable with uartb */
+       PERIPH_CLK("vfir",      "vfir",                 NULL,   7,      0x168,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("sdmmc1",    "sdhci-tegra.0",        NULL,   14,     0x150,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("sdmmc2",    "sdhci-tegra.1",        NULL,   9,      0x154,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("sdmmc3",    "sdhci-tegra.2",        NULL,   69,     0x1bc,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("sdmmc4",    "sdhci-tegra.3",        NULL,   15,     0x160,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("vde",       "vde",                  NULL,   61,     0x1c8,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("csite",     "csite",                NULL,   73,     0x1d4,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       /* FIXME: what is la? */
+       PERIPH_CLK("la",        "la",                   NULL,   76,     0x1f8,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("owr",       "owr",                  NULL,   71,     0x1cc,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("nor",       "nor",                  NULL,   42,     0x1d0,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("mipi",      "mipi",                 NULL,   50,     0x174,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("i2c1",      "tegra-i2c.0",          NULL,   12,     0x124,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("i2c2",      "tegra-i2c.1",          NULL,   54,     0x198,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("i2c3",      "tegra-i2c.2",          NULL,   67,     0x1b8,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("dvc",       "tegra-i2c.3",          NULL,   47,     0x128,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("i2c1_i2c",  "tegra-i2c.0",          "i2c",  0,      0,      mux_pllp_out3,                  0),
+       PERIPH_CLK("i2c2_i2c",  "tegra-i2c.1",          "i2c",  0,      0,      mux_pllp_out3,                  0),
+       PERIPH_CLK("i2c3_i2c",  "tegra-i2c.2",          "i2c",  0,      0,      mux_pllp_out3,                  0),
+       PERIPH_CLK("dvc_i2c",   "tegra-i2c.3",          "i2c",  0,      0,      mux_pllp_out3,                  0),
+       PERIPH_CLK("uarta",     "uart.0",               NULL,   6,      0x178,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("uartb",     "uart.1",               NULL,   7,      0x17c,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("uartc",     "uart.2",               NULL,   55,     0x1a0,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("uartd",     "uart.3",               NULL,   65,     0x1c0,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("uarte",     "uart.4",               NULL,   66,     0x1c4,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("3d",        "3d",                   NULL,   24,     0x158,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71 | PERIPH_MANUAL_RESET),
+       PERIPH_CLK("2d",        "2d",                   NULL,   21,     0x15c,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
+       /* FIXME: vi and vi_sensor share an enable */
+       PERIPH_CLK("vi",        "vi",                   NULL,   20,     0x148,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
+       PERIPH_CLK("vi_sensor", "vi_sensor",            NULL,   20,     0x1a8,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
+       PERIPH_CLK("epp",       "epp",                  NULL,   19,     0x16c,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
+       PERIPH_CLK("mpe",       "mpe",                  NULL,   60,     0x170,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
+       PERIPH_CLK("host1x",    "host1x",               NULL,   28,     0x180,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
+       /* FIXME: cve and tvo share an enable   */
+       PERIPH_CLK("cve",       "cve",                  NULL,   49,     0x140,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("tvo",       "tvo",                  NULL,   49,     0x188,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("hdmi",      "hdmi",                 NULL,   51,     0x18c,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("tvdac",     "tvdac",                NULL,   53,     0x194,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("disp1",     "tegrafb.0",            NULL,   27,     0x138,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("disp2",     "tegrafb.1",            NULL,   26,     0x13c,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("usbd",      "fsl-tegra-udc",        NULL,   22,     0,      mux_clk_m,                      0),
+       PERIPH_CLK("usb2",      "usb.1",                NULL,   58,     0,      mux_clk_m,                      0),
+       PERIPH_CLK("usb3",      "usb.2",                NULL,   59,     0,      mux_clk_m,                      0),
+       PERIPH_CLK("emc",       "emc",                  NULL,   57,     0x19c,  mux_pllm_pllc_pllp_clkm,        MUX | DIV_U71 | PERIPH_EMC_ENB),
+       PERIPH_CLK("dsi",       "dsi",                  NULL,   48,     0,      mux_plld,                       0),
+};
+
+#define CLK_DUPLICATE(_name, _dev, _con)               \
+       {                                               \
+               .name   = _name,                        \
+               .lookup = {                             \
+                       .dev_id = _dev,                 \
+                       .con_id         = _con,         \
+               },                                      \
+       }
+
+/* Some clocks may be used by different drivers depending on the board
+ * configuration.  List those here to register them twice in the clock lookup
+ * table under two names.
+ */
+struct clk_duplicate tegra_clk_duplicates[] = {
+       CLK_DUPLICATE("uarta",  "tegra_uart.0", NULL),
+       CLK_DUPLICATE("uartb",  "tegra_uart.1", NULL),
+       CLK_DUPLICATE("uartc",  "tegra_uart.2", NULL),
+       CLK_DUPLICATE("uartd",  "tegra_uart.3", NULL),
+       CLK_DUPLICATE("uarte",  "tegra_uart.4", NULL),
+};
+
+#define CLK(dev, con, ck)      \
+       {                       \
+               .dev_id = dev,  \
+               .con_id = con,  \
+               .clk = ck,      \
+       }
+
+struct clk_lookup tegra_clk_lookups[] = {
+       /* external root sources */
+       CLK(NULL,       "32k_clk",      &tegra_clk_32k),
+       CLK(NULL,       "pll_s",        &tegra_pll_s),
+       CLK(NULL,       "clk_m",        &tegra_clk_m),
+       CLK(NULL,       "pll_m",        &tegra_pll_m),
+       CLK(NULL,       "pll_m_out1",   &tegra_pll_m_out1),
+       CLK(NULL,       "pll_c",        &tegra_pll_c),
+       CLK(NULL,       "pll_c_out1",   &tegra_pll_c_out1),
+       CLK(NULL,       "pll_p",        &tegra_pll_p),
+       CLK(NULL,       "pll_p_out1",   &tegra_pll_p_out1),
+       CLK(NULL,       "pll_p_out2",   &tegra_pll_p_out2),
+       CLK(NULL,       "pll_p_out3",   &tegra_pll_p_out3),
+       CLK(NULL,       "pll_p_out4",   &tegra_pll_p_out4),
+       CLK(NULL,       "pll_a",        &tegra_pll_a),
+       CLK(NULL,       "pll_a_out0",   &tegra_pll_a_out0),
+       CLK(NULL,       "pll_d",        &tegra_pll_d),
+       CLK(NULL,       "pll_d_out0",   &tegra_pll_d_out0),
+       CLK(NULL,       "pll_u",        &tegra_pll_u),
+       CLK(NULL,       "pll_x",        &tegra_pll_x),
+       CLK(NULL,       "cpu",          &tegra_clk_cpu),
+       CLK(NULL,       "sys",          &tegra_clk_sys),
+       CLK(NULL,       "hclk",         &tegra_clk_hclk),
+       CLK(NULL,       "pclk",         &tegra_clk_pclk),
+       CLK(NULL,       "clk_d",        &tegra_clk_d),
+};
+
+void __init tegra2_init_clocks(void)
+{
+       int i;
+       struct clk_lookup *cl;
+       struct clk *c;
+       struct clk_duplicate *cd;
+
+       for (i = 0; i < ARRAY_SIZE(tegra_clk_lookups); i++) {
+               cl = &tegra_clk_lookups[i];
+               clk_init(cl->clk);
+               clkdev_add(cl);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(tegra_periph_clks); i++) {
+               c = &tegra_periph_clks[i];
+               cl = &c->lookup;
+               cl->clk = c;
+
+               clk_init(cl->clk);
+               clkdev_add(cl);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
+               cd = &tegra_clk_duplicates[i];
+               c = tegra_get_clock_by_name(cd->name);
+               if (c) {
+                       cl = &cd->lookup;
+                       cl->clk = c;
+                       clkdev_add(cl);
+               } else {
+                       pr_err("%s: Unknown duplicate clock %s\n", __func__,
+                               cd->name);
+               }
+       }
+}
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
new file mode 100644 (file)
index 0000000..2f42021
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * arch/arch/mach-tegra/timer.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/cnt32_to_63.h>
+
+#include <asm/mach/time.h>
+#include <asm/mach/time.h>
+#include <asm/localtimer.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+
+#include "board.h"
+#include "clock.h"
+
+#define TIMERUS_CNTR_1US 0x10
+#define TIMERUS_USEC_CFG 0x14
+#define TIMERUS_CNTR_FREEZE 0x4c
+
+#define TIMER1_BASE 0x0
+#define TIMER2_BASE 0x8
+#define TIMER3_BASE 0x50
+#define TIMER4_BASE 0x58
+
+#define TIMER_PTV 0x0
+#define TIMER_PCR 0x4
+
+struct tegra_timer;
+
+static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
+
+#define timer_writel(value, reg) \
+       __raw_writel(value, (u32)timer_reg_base + (reg))
+#define timer_readl(reg) \
+       __raw_readl((u32)timer_reg_base + (reg))
+
+static int tegra_timer_set_next_event(unsigned long cycles,
+                                        struct clock_event_device *evt)
+{
+       u32 reg;
+
+       reg = 0x80000000 | ((cycles > 1) ? (cycles-1) : 0);
+       timer_writel(reg, TIMER3_BASE + TIMER_PTV);
+
+       return 0;
+}
+
+static void tegra_timer_set_mode(enum clock_event_mode mode,
+                                   struct clock_event_device *evt)
+{
+       u32 reg;
+
+       timer_writel(0, TIMER3_BASE + TIMER_PTV);
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               reg = 0xC0000000 | ((1000000/HZ)-1);
+               timer_writel(reg, TIMER3_BASE + TIMER_PTV);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_RESUME:
+               break;
+       }
+}
+
+static cycle_t tegra_clocksource_read(struct clocksource *cs)
+{
+       return cnt32_to_63(timer_readl(TIMERUS_CNTR_1US));
+}
+
+static struct clock_event_device tegra_clockevent = {
+       .name           = "timer0",
+       .rating         = 300,
+       .features       = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
+       .set_next_event = tegra_timer_set_next_event,
+       .set_mode       = tegra_timer_set_mode,
+};
+
+static struct clocksource tegra_clocksource = {
+       .name   = "timer_us",
+       .rating = 300,
+       .read   = tegra_clocksource_read,
+       .mask   = 0x7FFFFFFFFFFFFFFFULL,
+       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+unsigned long long sched_clock(void)
+{
+       return clocksource_cyc2ns(tegra_clocksource.read(&tegra_clocksource),
+               tegra_clocksource.mult, tegra_clocksource.shift);
+}
+
+static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = (struct clock_event_device *)dev_id;
+       timer_writel(1<<30, TIMER3_BASE + TIMER_PCR);
+       evt->event_handler(evt);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction tegra_timer_irq = {
+       .name           = "timer0",
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH,
+       .handler        = tegra_timer_interrupt,
+       .dev_id         = &tegra_clockevent,
+       .irq            = INT_TMR3,
+};
+
+static void __init tegra_init_timer(void)
+{
+       unsigned long rate = clk_measure_input_freq();
+       int ret;
+
+#ifdef CONFIG_HAVE_ARM_TWD
+       twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600);
+#endif
+
+       switch (rate) {
+       case 12000000:
+               timer_writel(0x000b, TIMERUS_USEC_CFG);
+               break;
+       case 13000000:
+               timer_writel(0x000c, TIMERUS_USEC_CFG);
+               break;
+       case 19200000:
+               timer_writel(0x045f, TIMERUS_USEC_CFG);
+               break;
+       case 26000000:
+               timer_writel(0x0019, TIMERUS_USEC_CFG);
+               break;
+       default:
+               WARN(1, "Unknown clock rate");
+       }
+
+       if (clocksource_register_hz(&tegra_clocksource, 1000000)) {
+               printk(KERN_ERR "Failed to register clocksource\n");
+               BUG();
+       }
+
+       ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
+       if (ret) {
+               printk(KERN_ERR "Failed to register timer IRQ: %d\n", ret);
+               BUG();
+       }
+
+       clockevents_calc_mult_shift(&tegra_clockevent, 1000000, 5);
+       tegra_clockevent.max_delta_ns =
+               clockevent_delta2ns(0x1fffffff, &tegra_clockevent);
+       tegra_clockevent.min_delta_ns =
+               clockevent_delta2ns(0x1, &tegra_clockevent);
+       tegra_clockevent.cpumask = cpu_all_mask;
+       tegra_clockevent.irq = tegra_timer_irq.irq;
+       clockevents_register_device(&tegra_clockevent);
+
+       return;
+}
+
+struct sys_timer tegra_timer = {
+       .init = tegra_init_timer,
+};
index 87ec141fcaa6e5ad0d5d7eef0e1a8249ac2bdcc3..e1fd98fff8fac03c58282841191b8e7cff03e807 100644 (file)
@@ -771,7 +771,8 @@ config CACHE_L2X0
        bool "Enable the L2x0 outer cache controller"
        depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
                   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \
-                  ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
+                  ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
+                  ARCH_TEGRA
        default y
        select OUTER_CACHE
        select OUTER_CACHE_SYNC