diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-08 13:05:57 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-08 13:05:57 -0400 |
| commit | 4fd6c6bf83cb16321e9902b00e2af79054f4e0d6 (patch) | |
| tree | 7153f611af0125336ac0ec22c5cb430fe520edcc | |
| parent | c5f347579a661c9506e794315f0798b75ef71d35 (diff) | |
| parent | 84b9414babdc303dde1d3f44cd2a54dffb67ab97 (diff) | |
Merge branch 'for-linus' of git://android.kernel.org/kernel/tegra
* '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, 6061 insertions, 5 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index d4242846e7af..54d94ca9d6e8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -5565,6 +5565,15 @@ W: http://tcp-lp-mod.sourceforge.net/ | |||
| 5565 | S: Maintained | 5565 | S: Maintained |
| 5566 | F: net/ipv4/tcp_lp.c | 5566 | F: net/ipv4/tcp_lp.c |
| 5567 | 5567 | ||
| 5568 | TEGRA SUPPORT | ||
| 5569 | M: Colin Cross <ccross@android.com> | ||
| 5570 | M: Erik Gilling <konkers@android.com> | ||
| 5571 | M: Olof Johansson <olof@lixom.net> | ||
| 5572 | L: linux-tegra@vger.kernel.org | ||
| 5573 | T: git git://android.git.kernel.org/kernel/tegra.git | ||
| 5574 | S: Supported | ||
| 5575 | F: arch/arm/mach-tegra | ||
| 5576 | |||
| 5568 | TEHUTI ETHERNET DRIVER | 5577 | TEHUTI ETHERNET DRIVER |
| 5569 | M: Alexander Indenbaum <baum@tehutinetworks.net> | 5578 | M: Alexander Indenbaum <baum@tehutinetworks.net> |
| 5570 | M: Andy Gospodarek <andy@greyhouse.net> | 5579 | M: Andy Gospodarek <andy@greyhouse.net> |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9e10882c81d7..232f0c758252 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -558,6 +558,18 @@ config ARCH_NUC93X | |||
| 558 | Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a | 558 | Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a |
| 559 | low-power and high performance MPEG-4/JPEG multimedia controller chip. | 559 | low-power and high performance MPEG-4/JPEG multimedia controller chip. |
| 560 | 560 | ||
| 561 | config ARCH_TEGRA | ||
| 562 | bool "NVIDIA Tegra" | ||
| 563 | select GENERIC_TIME | ||
| 564 | select GENERIC_CLOCKEVENTS | ||
| 565 | select GENERIC_GPIO | ||
| 566 | select HAVE_CLK | ||
| 567 | select COMMON_CLKDEV | ||
| 568 | select ARCH_HAS_BARRIERS if CACHE_L2X0 | ||
| 569 | help | ||
| 570 | This enables support for NVIDIA Tegra based systems (Tegra APX, | ||
| 571 | Tegra 6xx and Tegra 2 series). | ||
| 572 | |||
| 561 | config ARCH_PNX4008 | 573 | config ARCH_PNX4008 |
| 562 | bool "Philips Nexperia PNX4008 Mobile" | 574 | bool "Philips Nexperia PNX4008 Mobile" |
| 563 | select CPU_ARM926T | 575 | select CPU_ARM926T |
| @@ -907,6 +919,8 @@ source "arch/arm/mach-shmobile/Kconfig" | |||
| 907 | 919 | ||
| 908 | source "arch/arm/plat-stmp3xxx/Kconfig" | 920 | source "arch/arm/plat-stmp3xxx/Kconfig" |
| 909 | 921 | ||
| 922 | source "arch/arm/mach-tegra/Kconfig" | ||
| 923 | |||
| 910 | source "arch/arm/mach-u300/Kconfig" | 924 | source "arch/arm/mach-u300/Kconfig" |
| 911 | 925 | ||
| 912 | source "arch/arm/mach-ux500/Kconfig" | 926 | source "arch/arm/mach-ux500/Kconfig" |
| @@ -1094,10 +1108,11 @@ config SMP | |||
| 1094 | bool "Symmetric Multi-Processing (EXPERIMENTAL)" | 1108 | bool "Symmetric Multi-Processing (EXPERIMENTAL)" |
| 1095 | depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\ | 1109 | depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\ |
| 1096 | MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\ | 1110 | MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\ |
| 1097 | ARCH_U8500 || ARCH_VEXPRESS_CA9X4) | 1111 | ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_TEGRA) |
| 1098 | depends on GENERIC_CLOCKEVENTS | 1112 | depends on GENERIC_CLOCKEVENTS |
| 1099 | select USE_GENERIC_SMP_HELPERS | 1113 | select USE_GENERIC_SMP_HELPERS |
| 1100 | select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4) | 1114 | select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || \ |
| 1115 | ARCH_VEXPRESS_CA9X4 || ARCH_TEGRA) | ||
| 1101 | help | 1116 | help |
| 1102 | This enables support for systems with more than one CPU. If you have | 1117 | This enables support for systems with more than one CPU. If you have |
| 1103 | a system with only one CPU, like most personal computers, say N. If | 1118 | a system with only one CPU, like most personal computers, say N. If |
| @@ -1167,9 +1182,10 @@ config LOCAL_TIMERS | |||
| 1167 | bool "Use local timer interrupts" | 1182 | bool "Use local timer interrupts" |
| 1168 | depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \ | 1183 | depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \ |
| 1169 | REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ | 1184 | REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ |
| 1170 | ARCH_U8500 || ARCH_VEXPRESS_CA9X4) | 1185 | ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_TEGRA) |
| 1171 | default y | 1186 | default y |
| 1172 | select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_OMAP4 || ARCH_U8500) | 1187 | select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_OMAP4 || \\ |
| 1188 | ARCH_U8500 || ARCH_TEGRA | ||
| 1173 | help | 1189 | help |
| 1174 | Enable support for local timers on SMP platforms, rather then the | 1190 | Enable support for local timers on SMP platforms, rather then the |
| 1175 | legacy IPI broadcast method. Local timers allows the system | 1191 | legacy IPI broadcast method. Local timers allows the system |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 63d998e8c672..a8d4dca9da35 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
| @@ -179,6 +179,7 @@ machine-$(CONFIG_ARCH_SHARK) := shark | |||
| 179 | machine-$(CONFIG_ARCH_SHMOBILE) := shmobile | 179 | machine-$(CONFIG_ARCH_SHMOBILE) := shmobile |
| 180 | machine-$(CONFIG_ARCH_STMP378X) := stmp378x | 180 | machine-$(CONFIG_ARCH_STMP378X) := stmp378x |
| 181 | machine-$(CONFIG_ARCH_STMP37XX) := stmp37xx | 181 | machine-$(CONFIG_ARCH_STMP37XX) := stmp37xx |
| 182 | machine-$(CONFIG_ARCH_TEGRA) := tegra | ||
| 182 | machine-$(CONFIG_ARCH_U300) := u300 | 183 | machine-$(CONFIG_ARCH_U300) := u300 |
| 183 | machine-$(CONFIG_ARCH_U8500) := ux500 | 184 | machine-$(CONFIG_ARCH_U8500) := ux500 |
| 184 | machine-$(CONFIG_ARCH_VERSATILE) := versatile | 185 | machine-$(CONFIG_ARCH_VERSATILE) := versatile |
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig new file mode 100644 index 000000000000..a57713c1954a --- /dev/null +++ b/arch/arm/mach-tegra/Kconfig | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | if ARCH_TEGRA | ||
| 2 | |||
| 3 | comment "NVIDIA Tegra options" | ||
| 4 | |||
| 5 | choice | ||
| 6 | prompt "Select Tegra processor family for target system" | ||
| 7 | |||
| 8 | config ARCH_TEGRA_2x_SOC | ||
| 9 | bool "Tegra 2 family" | ||
| 10 | select CPU_V7 | ||
| 11 | select ARM_GIC | ||
| 12 | select ARCH_REQUIRE_GPIOLIB | ||
| 13 | help | ||
| 14 | Support for NVIDIA Tegra AP20 and T20 processors, based on the | ||
| 15 | ARM CortexA9MP CPU and the ARM PL310 L2 cache controller | ||
| 16 | |||
| 17 | endchoice | ||
| 18 | |||
| 19 | comment "Tegra board type" | ||
| 20 | |||
| 21 | config MACH_HARMONY | ||
| 22 | bool "Harmony board" | ||
| 23 | help | ||
| 24 | Support for nVidia Harmony development platform | ||
| 25 | |||
| 26 | choice | ||
| 27 | prompt "Low-level debug console UART" | ||
| 28 | default TEGRA_DEBUG_UART_NONE | ||
| 29 | |||
| 30 | config TEGRA_DEBUG_UART_NONE | ||
| 31 | bool "None" | ||
| 32 | |||
| 33 | config TEGRA_DEBUG_UARTA | ||
| 34 | bool "UART-A" | ||
| 35 | |||
| 36 | config TEGRA_DEBUG_UARTB | ||
| 37 | bool "UART-B" | ||
| 38 | |||
| 39 | config TEGRA_DEBUG_UARTC | ||
| 40 | bool "UART-C" | ||
| 41 | |||
| 42 | config TEGRA_DEBUG_UARTD | ||
| 43 | bool "UART-D" | ||
| 44 | |||
| 45 | config TEGRA_DEBUG_UARTE | ||
| 46 | bool "UART-E" | ||
| 47 | |||
| 48 | endchoice | ||
| 49 | |||
| 50 | endif | ||
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile new file mode 100644 index 000000000000..51e9370eed99 --- /dev/null +++ b/arch/arm/mach-tegra/Makefile | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | obj-y += common.o | ||
| 2 | obj-y += io.o | ||
| 3 | obj-y += irq.o | ||
| 4 | obj-y += clock.o | ||
| 5 | obj-y += timer.o | ||
| 6 | obj-y += gpio.o | ||
| 7 | obj-y += pinmux.o | ||
| 8 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o | ||
| 9 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o | ||
| 10 | obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o | ||
| 11 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | ||
| 12 | |||
| 13 | obj-${CONFIG_MACH_HARMONY} += board-harmony.o | ||
| 14 | 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 index 000000000000..db52d61a7386 --- /dev/null +++ b/arch/arm/mach-tegra/Makefile.boot | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00008000 | ||
| 2 | params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC) := 0x00000100 | ||
| 3 | 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 index 000000000000..50b15d500cac --- /dev/null +++ b/arch/arm/mach-tegra/board-harmony-pinmux.c | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/board-harmony-pinmux.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * This software is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2, as published by the Free Software Foundation, and | ||
| 8 | * may be copied, distributed, and modified under those terms. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <mach/pinmux.h> | ||
| 19 | |||
| 20 | #include "board-harmony.h" | ||
| 21 | |||
| 22 | static struct tegra_pingroup_config harmony_pinmux[] = { | ||
| 23 | {TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 24 | {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 25 | {TEGRA_PINGROUP_ATC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 26 | {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 27 | {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 28 | {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
| 29 | {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
| 30 | {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 31 | {TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
| 32 | {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 33 | {TEGRA_PINGROUP_DAP2, TEGRA_MUX_DAP2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 34 | {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 35 | {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 36 | {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 37 | {TEGRA_PINGROUP_DTA, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 38 | {TEGRA_PINGROUP_DTB, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 39 | {TEGRA_PINGROUP_DTC, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 40 | {TEGRA_PINGROUP_DTD, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 41 | {TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 42 | {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 43 | {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 44 | {TEGRA_PINGROUP_GMB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 45 | {TEGRA_PINGROUP_GMC, TEGRA_MUX_UARTD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 46 | {TEGRA_PINGROUP_GMD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 47 | {TEGRA_PINGROUP_GME, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 48 | {TEGRA_PINGROUP_GPU, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 49 | {TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 50 | {TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 51 | {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 52 | {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 53 | {TEGRA_PINGROUP_IRRX, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 54 | {TEGRA_PINGROUP_IRTX, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 55 | {TEGRA_PINGROUP_KBCA, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 56 | {TEGRA_PINGROUP_KBCB, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 57 | {TEGRA_PINGROUP_KBCC, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 58 | {TEGRA_PINGROUP_KBCD, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 59 | {TEGRA_PINGROUP_KBCE, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 60 | {TEGRA_PINGROUP_KBCF, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 61 | {TEGRA_PINGROUP_LCSN, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 62 | {TEGRA_PINGROUP_LD0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 63 | {TEGRA_PINGROUP_LD1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 64 | {TEGRA_PINGROUP_LD10, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 65 | {TEGRA_PINGROUP_LD11, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 66 | {TEGRA_PINGROUP_LD12, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 67 | {TEGRA_PINGROUP_LD13, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 68 | {TEGRA_PINGROUP_LD14, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 69 | {TEGRA_PINGROUP_LD15, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 70 | {TEGRA_PINGROUP_LD16, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 71 | {TEGRA_PINGROUP_LD17, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 72 | {TEGRA_PINGROUP_LD2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 73 | {TEGRA_PINGROUP_LD3, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 74 | {TEGRA_PINGROUP_LD4, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 75 | {TEGRA_PINGROUP_LD5, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 76 | {TEGRA_PINGROUP_LD6, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 77 | {TEGRA_PINGROUP_LD7, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 78 | {TEGRA_PINGROUP_LD8, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 79 | {TEGRA_PINGROUP_LD9, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 80 | {TEGRA_PINGROUP_LDC, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 81 | {TEGRA_PINGROUP_LDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 82 | {TEGRA_PINGROUP_LHP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 83 | {TEGRA_PINGROUP_LHP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 84 | {TEGRA_PINGROUP_LHP2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 85 | {TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 86 | {TEGRA_PINGROUP_LM0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 87 | {TEGRA_PINGROUP_LM1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 88 | {TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 89 | {TEGRA_PINGROUP_LPW0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 90 | {TEGRA_PINGROUP_LPW1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 91 | {TEGRA_PINGROUP_LPW2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 92 | {TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 93 | {TEGRA_PINGROUP_LSC1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 94 | {TEGRA_PINGROUP_LSCK, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 95 | {TEGRA_PINGROUP_LSDA, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 96 | {TEGRA_PINGROUP_LSDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 97 | {TEGRA_PINGROUP_LSPI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 98 | {TEGRA_PINGROUP_LVP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 99 | {TEGRA_PINGROUP_LVP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
| 100 | {TEGRA_PINGROUP_LVS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 101 | {TEGRA_PINGROUP_OWC, TEGRA_MUX_RSVD2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 102 | {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 103 | {TEGRA_PINGROUP_PTA, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 104 | {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 105 | {TEGRA_PINGROUP_SDB, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 106 | {TEGRA_PINGROUP_SDC, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 107 | {TEGRA_PINGROUP_SDD, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 108 | {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 109 | {TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 110 | {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 111 | {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 112 | {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 113 | {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 114 | {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 115 | {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
| 116 | {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
| 117 | {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
| 118 | {TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
| 119 | {TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 120 | {TEGRA_PINGROUP_SPIF, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
| 121 | {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 122 | {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 123 | {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 124 | {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 125 | {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 126 | {TEGRA_PINGROUP_UAD, TEGRA_MUX_IRDA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 127 | {TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 128 | {TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
| 129 | {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
| 130 | {TEGRA_PINGROUP_CK32, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 131 | {TEGRA_PINGROUP_DDRC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 132 | {TEGRA_PINGROUP_PMCA, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 133 | {TEGRA_PINGROUP_PMCB, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 134 | {TEGRA_PINGROUP_PMCC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 135 | {TEGRA_PINGROUP_PMCD, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 136 | {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 137 | {TEGRA_PINGROUP_XM2C, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 138 | {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
| 139 | }; | ||
| 140 | |||
| 141 | void harmony_pinmux_init(void) | ||
| 142 | { | ||
| 143 | tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux)); | ||
| 144 | } | ||
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c new file mode 100644 index 000000000000..05e78dd9b50c --- /dev/null +++ b/arch/arm/mach-tegra/board-harmony.c | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/board-harmony.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * This software is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2, as published by the Free Software Foundation, and | ||
| 8 | * may be copied, distributed, and modified under those terms. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | #include <linux/serial_8250.h> | ||
| 21 | #include <linux/clk.h> | ||
| 22 | #include <linux/dma-mapping.h> | ||
| 23 | #include <linux/pda_power.h> | ||
| 24 | #include <linux/io.h> | ||
| 25 | |||
| 26 | #include <asm/mach-types.h> | ||
| 27 | #include <asm/mach/arch.h> | ||
| 28 | #include <asm/mach/time.h> | ||
| 29 | #include <asm/setup.h> | ||
| 30 | |||
| 31 | #include <mach/iomap.h> | ||
| 32 | #include <mach/irqs.h> | ||
| 33 | |||
| 34 | #include "board.h" | ||
| 35 | #include "board-harmony.h" | ||
| 36 | #include "clock.h" | ||
| 37 | |||
| 38 | /* NVidia bootloader tags */ | ||
| 39 | #define ATAG_NVIDIA 0x41000801 | ||
| 40 | |||
| 41 | #define ATAG_NVIDIA_RM 0x1 | ||
| 42 | #define ATAG_NVIDIA_DISPLAY 0x2 | ||
| 43 | #define ATAG_NVIDIA_FRAMEBUFFER 0x3 | ||
| 44 | #define ATAG_NVIDIA_CHIPSHMOO 0x4 | ||
| 45 | #define ATAG_NVIDIA_CHIPSHMOOPHYS 0x5 | ||
| 46 | #define ATAG_NVIDIA_PRESERVED_MEM_0 0x10000 | ||
| 47 | #define ATAG_NVIDIA_PRESERVED_MEM_N 2 | ||
| 48 | #define ATAG_NVIDIA_FORCE_32 0x7fffffff | ||
| 49 | |||
| 50 | struct tag_tegra { | ||
| 51 | __u32 bootarg_key; | ||
| 52 | __u32 bootarg_len; | ||
| 53 | char bootarg[1]; | ||
| 54 | }; | ||
| 55 | |||
| 56 | static int __init parse_tag_nvidia(const struct tag *tag) | ||
| 57 | { | ||
| 58 | |||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | __tagtable(ATAG_NVIDIA, parse_tag_nvidia); | ||
| 62 | |||
| 63 | static struct plat_serial8250_port debug_uart_platform_data[] = { | ||
| 64 | { | ||
| 65 | .membase = IO_ADDRESS(TEGRA_UARTD_BASE), | ||
| 66 | .mapbase = TEGRA_UARTD_BASE, | ||
| 67 | .irq = INT_UARTD, | ||
| 68 | .flags = UPF_BOOT_AUTOCONF, | ||
| 69 | .iotype = UPIO_MEM, | ||
| 70 | .regshift = 2, | ||
| 71 | .uartclk = 216000000, | ||
| 72 | }, { | ||
| 73 | .flags = 0 | ||
| 74 | } | ||
| 75 | }; | ||
| 76 | |||
| 77 | static struct platform_device debug_uart = { | ||
| 78 | .name = "serial8250", | ||
| 79 | .id = PLAT8250_DEV_PLATFORM, | ||
| 80 | .dev = { | ||
| 81 | .platform_data = debug_uart_platform_data, | ||
| 82 | }, | ||
| 83 | }; | ||
| 84 | |||
| 85 | static struct platform_device *harmony_devices[] __initdata = { | ||
| 86 | &debug_uart, | ||
| 87 | }; | ||
| 88 | |||
| 89 | static void __init tegra_harmony_fixup(struct machine_desc *desc, | ||
| 90 | struct tag *tags, char **cmdline, struct meminfo *mi) | ||
| 91 | { | ||
| 92 | mi->nr_banks = 2; | ||
| 93 | mi->bank[0].start = PHYS_OFFSET; | ||
| 94 | mi->bank[0].node = PHYS_TO_NID(PHYS_OFFSET); | ||
| 95 | mi->bank[0].size = 448 * SZ_1M; | ||
| 96 | mi->bank[1].start = SZ_512M; | ||
| 97 | mi->bank[1].node = PHYS_TO_NID(SZ_512M); | ||
| 98 | mi->bank[1].size = SZ_512M; | ||
| 99 | } | ||
| 100 | |||
| 101 | static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = { | ||
| 102 | /* name parent rate enabled */ | ||
| 103 | { "uartd", "pll_p", 216000000, true }, | ||
| 104 | { NULL, NULL, 0, 0}, | ||
| 105 | }; | ||
| 106 | |||
| 107 | static void __init tegra_harmony_init(void) | ||
| 108 | { | ||
| 109 | tegra_common_init(); | ||
| 110 | |||
| 111 | tegra_clk_init_from_table(harmony_clk_init_table); | ||
| 112 | |||
| 113 | harmony_pinmux_init(); | ||
| 114 | |||
| 115 | platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices)); | ||
| 116 | } | ||
| 117 | |||
| 118 | MACHINE_START(HARMONY, "harmony") | ||
| 119 | .boot_params = 0x00000100, | ||
| 120 | .phys_io = IO_APB_PHYS, | ||
| 121 | .io_pg_offst = ((IO_APB_VIRT) >> 18) & 0xfffc, | ||
| 122 | .fixup = tegra_harmony_fixup, | ||
| 123 | .init_irq = tegra_init_irq, | ||
| 124 | .init_machine = tegra_harmony_init, | ||
| 125 | .map_io = tegra_map_common_io, | ||
| 126 | .timer = &tegra_timer, | ||
| 127 | MACHINE_END | ||
diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h new file mode 100644 index 000000000000..09ca7755dd55 --- /dev/null +++ b/arch/arm/mach-tegra/board-harmony.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/board-harmony.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * This software is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2, as published by the Free Software Foundation, and | ||
| 8 | * may be copied, distributed, and modified under those terms. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _MACH_TEGRA_BOARD_HARMONY_H | ||
| 18 | #define _MACH_TEGRA_BOARD_HARMONY_H | ||
| 19 | |||
| 20 | void harmony_pinmux_init(void); | ||
| 21 | |||
| 22 | #endif | ||
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h new file mode 100644 index 000000000000..3d06354136f2 --- /dev/null +++ b/arch/arm/mach-tegra/board.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/board.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __MACH_TEGRA_BOARD_H | ||
| 22 | #define __MACH_TEGRA_BOARD_H | ||
| 23 | |||
| 24 | #include <linux/types.h> | ||
| 25 | |||
| 26 | void __init tegra_common_init(void); | ||
| 27 | void __init tegra_map_common_io(void); | ||
| 28 | void __init tegra_init_irq(void); | ||
| 29 | void __init tegra_init_clock(void); | ||
| 30 | |||
| 31 | extern struct sys_timer tegra_timer; | ||
| 32 | #endif | ||
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c new file mode 100644 index 000000000000..03ad578349b9 --- /dev/null +++ b/arch/arm/mach-tegra/clock.c | |||
| @@ -0,0 +1,488 @@ | |||
| 1 | /* | ||
| 2 | * | ||
| 3 | * Copyright (C) 2010 Google, Inc. | ||
| 4 | * | ||
| 5 | * Author: | ||
| 6 | * Colin Cross <ccross@google.com> | ||
| 7 | * | ||
| 8 | * This software is licensed under the terms of the GNU General Public | ||
| 9 | * License version 2, as published by the Free Software Foundation, and | ||
| 10 | * may be copied, distributed, and modified under those terms. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/clk.h> | ||
| 21 | #include <linux/list.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/debugfs.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | #include <linux/seq_file.h> | ||
| 27 | #include <asm/clkdev.h> | ||
| 28 | |||
| 29 | #include "clock.h" | ||
| 30 | |||
| 31 | static LIST_HEAD(clocks); | ||
| 32 | |||
| 33 | static DEFINE_SPINLOCK(clock_lock); | ||
| 34 | |||
| 35 | struct clk *tegra_get_clock_by_name(const char *name) | ||
| 36 | { | ||
| 37 | struct clk *c; | ||
| 38 | struct clk *ret = NULL; | ||
| 39 | unsigned long flags; | ||
| 40 | spin_lock_irqsave(&clock_lock, flags); | ||
| 41 | list_for_each_entry(c, &clocks, node) { | ||
| 42 | if (strcmp(c->name, name) == 0) { | ||
| 43 | ret = c; | ||
| 44 | break; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 48 | return ret; | ||
| 49 | } | ||
| 50 | |||
| 51 | int clk_reparent(struct clk *c, struct clk *parent) | ||
| 52 | { | ||
| 53 | pr_debug("%s: %s\n", __func__, c->name); | ||
| 54 | if (c->refcnt && c->parent) | ||
| 55 | clk_disable_locked(c->parent); | ||
| 56 | c->parent = parent; | ||
| 57 | if (c->refcnt && c->parent) | ||
| 58 | clk_enable_locked(c->parent); | ||
| 59 | list_del(&c->sibling); | ||
| 60 | list_add_tail(&c->sibling, &parent->children); | ||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | static void propagate_rate(struct clk *c) | ||
| 65 | { | ||
| 66 | struct clk *clkp; | ||
| 67 | pr_debug("%s: %s\n", __func__, c->name); | ||
| 68 | list_for_each_entry(clkp, &c->children, sibling) { | ||
| 69 | pr_debug(" %s\n", clkp->name); | ||
| 70 | if (clkp->ops->recalculate_rate) | ||
| 71 | clkp->ops->recalculate_rate(clkp); | ||
| 72 | propagate_rate(clkp); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | void clk_init(struct clk *c) | ||
| 77 | { | ||
| 78 | unsigned long flags; | ||
| 79 | |||
| 80 | spin_lock_irqsave(&clock_lock, flags); | ||
| 81 | |||
| 82 | INIT_LIST_HEAD(&c->children); | ||
| 83 | INIT_LIST_HEAD(&c->sibling); | ||
| 84 | |||
| 85 | if (c->ops && c->ops->init) | ||
| 86 | c->ops->init(c); | ||
| 87 | |||
| 88 | list_add(&c->node, &clocks); | ||
| 89 | |||
| 90 | if (c->parent) | ||
| 91 | list_add_tail(&c->sibling, &c->parent->children); | ||
| 92 | |||
| 93 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 94 | } | ||
| 95 | |||
| 96 | int clk_enable_locked(struct clk *c) | ||
| 97 | { | ||
| 98 | int ret; | ||
| 99 | pr_debug("%s: %s\n", __func__, c->name); | ||
| 100 | if (c->refcnt == 0) { | ||
| 101 | if (c->parent) { | ||
| 102 | ret = clk_enable_locked(c->parent); | ||
| 103 | if (ret) | ||
| 104 | return ret; | ||
| 105 | } | ||
| 106 | |||
| 107 | if (c->ops && c->ops->enable) { | ||
| 108 | ret = c->ops->enable(c); | ||
| 109 | if (ret) { | ||
| 110 | if (c->parent) | ||
| 111 | clk_disable_locked(c->parent); | ||
| 112 | return ret; | ||
| 113 | } | ||
| 114 | c->state = ON; | ||
| 115 | #ifdef CONFIG_DEBUG_FS | ||
| 116 | c->set = 1; | ||
| 117 | #endif | ||
| 118 | } | ||
| 119 | } | ||
| 120 | c->refcnt++; | ||
| 121 | |||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | int clk_enable(struct clk *c) | ||
| 126 | { | ||
| 127 | int ret; | ||
| 128 | unsigned long flags; | ||
| 129 | spin_lock_irqsave(&clock_lock, flags); | ||
| 130 | ret = clk_enable_locked(c); | ||
| 131 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 132 | return ret; | ||
| 133 | } | ||
| 134 | EXPORT_SYMBOL(clk_enable); | ||
| 135 | |||
| 136 | void clk_disable_locked(struct clk *c) | ||
| 137 | { | ||
| 138 | pr_debug("%s: %s\n", __func__, c->name); | ||
| 139 | if (c->refcnt == 0) { | ||
| 140 | WARN(1, "Attempting to disable clock %s with refcnt 0", c->name); | ||
| 141 | return; | ||
| 142 | } | ||
| 143 | if (c->refcnt == 1) { | ||
| 144 | if (c->ops && c->ops->disable) | ||
| 145 | c->ops->disable(c); | ||
| 146 | |||
| 147 | if (c->parent) | ||
| 148 | clk_disable_locked(c->parent); | ||
| 149 | |||
| 150 | c->state = OFF; | ||
| 151 | } | ||
| 152 | c->refcnt--; | ||
| 153 | } | ||
| 154 | |||
| 155 | void clk_disable(struct clk *c) | ||
| 156 | { | ||
| 157 | unsigned long flags; | ||
| 158 | spin_lock_irqsave(&clock_lock, flags); | ||
| 159 | clk_disable_locked(c); | ||
| 160 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 161 | } | ||
| 162 | EXPORT_SYMBOL(clk_disable); | ||
| 163 | |||
| 164 | int clk_set_parent_locked(struct clk *c, struct clk *parent) | ||
| 165 | { | ||
| 166 | int ret; | ||
| 167 | |||
| 168 | pr_debug("%s: %s\n", __func__, c->name); | ||
| 169 | |||
| 170 | if (!c->ops || !c->ops->set_parent) | ||
| 171 | return -ENOSYS; | ||
| 172 | |||
| 173 | ret = c->ops->set_parent(c, parent); | ||
| 174 | |||
| 175 | if (ret) | ||
| 176 | return ret; | ||
| 177 | |||
| 178 | propagate_rate(c); | ||
| 179 | |||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | int clk_set_parent(struct clk *c, struct clk *parent) | ||
| 184 | { | ||
| 185 | int ret; | ||
| 186 | unsigned long flags; | ||
| 187 | spin_lock_irqsave(&clock_lock, flags); | ||
| 188 | ret = clk_set_parent_locked(c, parent); | ||
| 189 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 190 | return ret; | ||
| 191 | } | ||
| 192 | EXPORT_SYMBOL(clk_set_parent); | ||
| 193 | |||
| 194 | struct clk *clk_get_parent(struct clk *c) | ||
| 195 | { | ||
| 196 | return c->parent; | ||
| 197 | } | ||
| 198 | EXPORT_SYMBOL(clk_get_parent); | ||
| 199 | |||
| 200 | int clk_set_rate(struct clk *c, unsigned long rate) | ||
| 201 | { | ||
| 202 | int ret = 0; | ||
| 203 | unsigned long flags; | ||
| 204 | |||
| 205 | spin_lock_irqsave(&clock_lock, flags); | ||
| 206 | |||
| 207 | pr_debug("%s: %s\n", __func__, c->name); | ||
| 208 | |||
| 209 | if (c->ops && c->ops->set_rate) | ||
| 210 | ret = c->ops->set_rate(c, rate); | ||
| 211 | else | ||
| 212 | ret = -ENOSYS; | ||
| 213 | |||
| 214 | propagate_rate(c); | ||
| 215 | |||
| 216 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 217 | |||
| 218 | return ret; | ||
| 219 | } | ||
| 220 | EXPORT_SYMBOL(clk_set_rate); | ||
| 221 | |||
| 222 | unsigned long clk_get_rate(struct clk *c) | ||
| 223 | { | ||
| 224 | unsigned long flags; | ||
| 225 | unsigned long ret; | ||
| 226 | |||
| 227 | spin_lock_irqsave(&clock_lock, flags); | ||
| 228 | |||
| 229 | pr_debug("%s: %s\n", __func__, c->name); | ||
| 230 | |||
| 231 | ret = c->rate; | ||
| 232 | |||
| 233 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 234 | return ret; | ||
| 235 | } | ||
| 236 | EXPORT_SYMBOL(clk_get_rate); | ||
| 237 | |||
| 238 | static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) | ||
| 239 | { | ||
| 240 | struct clk *c; | ||
| 241 | struct clk *p; | ||
| 242 | |||
| 243 | int ret = 0; | ||
| 244 | |||
| 245 | c = tegra_get_clock_by_name(table->name); | ||
| 246 | |||
| 247 | if (!c) { | ||
| 248 | pr_warning("Unable to initialize clock %s\n", | ||
| 249 | table->name); | ||
| 250 | return -ENODEV; | ||
| 251 | } | ||
| 252 | |||
| 253 | if (table->parent) { | ||
| 254 | p = tegra_get_clock_by_name(table->parent); | ||
| 255 | if (!p) { | ||
| 256 | pr_warning("Unable to find parent %s of clock %s\n", | ||
| 257 | table->parent, table->name); | ||
| 258 | return -ENODEV; | ||
| 259 | } | ||
| 260 | |||
| 261 | if (c->parent != p) { | ||
| 262 | ret = clk_set_parent(c, p); | ||
| 263 | if (ret) { | ||
| 264 | pr_warning("Unable to set parent %s of clock %s: %d\n", | ||
| 265 | table->parent, table->name, ret); | ||
| 266 | return -EINVAL; | ||
| 267 | } | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | if (table->rate && table->rate != clk_get_rate(c)) { | ||
| 272 | ret = clk_set_rate(c, table->rate); | ||
| 273 | if (ret) { | ||
| 274 | pr_warning("Unable to set clock %s to rate %lu: %d\n", | ||
| 275 | table->name, table->rate, ret); | ||
| 276 | return -EINVAL; | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | if (table->enabled) { | ||
| 281 | ret = clk_enable(c); | ||
| 282 | if (ret) { | ||
| 283 | pr_warning("Unable to enable clock %s: %d\n", | ||
| 284 | table->name, ret); | ||
| 285 | return -EINVAL; | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | return 0; | ||
| 290 | } | ||
| 291 | |||
| 292 | void tegra_clk_init_from_table(struct tegra_clk_init_table *table) | ||
| 293 | { | ||
| 294 | for (; table->name; table++) | ||
| 295 | tegra_clk_init_one_from_table(table); | ||
| 296 | } | ||
| 297 | EXPORT_SYMBOL(tegra_clk_init_from_table); | ||
| 298 | |||
| 299 | void tegra_periph_reset_deassert(struct clk *c) | ||
| 300 | { | ||
| 301 | tegra2_periph_reset_deassert(c); | ||
| 302 | } | ||
| 303 | EXPORT_SYMBOL(tegra_periph_reset_deassert); | ||
| 304 | |||
| 305 | void tegra_periph_reset_assert(struct clk *c) | ||
| 306 | { | ||
| 307 | tegra2_periph_reset_assert(c); | ||
| 308 | } | ||
| 309 | EXPORT_SYMBOL(tegra_periph_reset_assert); | ||
| 310 | |||
| 311 | int __init tegra_init_clock(void) | ||
| 312 | { | ||
| 313 | tegra2_init_clocks(); | ||
| 314 | |||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | #ifdef CONFIG_DEBUG_FS | ||
| 319 | static struct dentry *clk_debugfs_root; | ||
| 320 | |||
| 321 | |||
| 322 | static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) | ||
| 323 | { | ||
| 324 | struct clk *child; | ||
| 325 | struct clk *safe; | ||
| 326 | const char *state = "uninit"; | ||
| 327 | char div[5] = {0}; | ||
| 328 | |||
| 329 | if (c->state == ON) | ||
| 330 | state = "on"; | ||
| 331 | else if (c->state == OFF) | ||
| 332 | state = "off"; | ||
| 333 | |||
| 334 | if (c->mul != 0 && c->div != 0) { | ||
| 335 | BUG_ON(c->mul > 2); | ||
| 336 | if (c->mul > c->div) | ||
| 337 | snprintf(div, sizeof(div), "x%d", c->mul / c->div); | ||
| 338 | else | ||
| 339 | snprintf(div, sizeof(div), "%d%s", c->div / c->mul, | ||
| 340 | (c->div % c->mul) ? ".5" : ""); | ||
| 341 | } | ||
| 342 | |||
| 343 | seq_printf(s, "%*s%-*s %-6s %-3d %-5s %-10lu\n", | ||
| 344 | level * 3 + 1, c->set ? "" : "*", | ||
| 345 | 30 - level * 3, c->name, | ||
| 346 | state, c->refcnt, div, c->rate); | ||
| 347 | list_for_each_entry_safe(child, safe, &c->children, sibling) { | ||
| 348 | clock_tree_show_one(s, child, level + 1); | ||
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | static int clock_tree_show(struct seq_file *s, void *data) | ||
| 353 | { | ||
| 354 | struct clk *c; | ||
| 355 | unsigned long flags; | ||
| 356 | seq_printf(s, " clock state ref div rate \n"); | ||
| 357 | seq_printf(s, "-----------------------------------------------------------\n"); | ||
| 358 | spin_lock_irqsave(&clock_lock, flags); | ||
| 359 | list_for_each_entry(c, &clocks, node) | ||
| 360 | if (c->parent == NULL) | ||
| 361 | clock_tree_show_one(s, c, 0); | ||
| 362 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | static int clock_tree_open(struct inode *inode, struct file *file) | ||
| 367 | { | ||
| 368 | return single_open(file, clock_tree_show, inode->i_private); | ||
| 369 | } | ||
| 370 | |||
| 371 | static const struct file_operations clock_tree_fops = { | ||
| 372 | .open = clock_tree_open, | ||
| 373 | .read = seq_read, | ||
| 374 | .llseek = seq_lseek, | ||
| 375 | .release = single_release, | ||
| 376 | }; | ||
| 377 | |||
| 378 | static int possible_parents_show(struct seq_file *s, void *data) | ||
| 379 | { | ||
| 380 | struct clk *c = s->private; | ||
| 381 | int i; | ||
| 382 | |||
| 383 | for (i = 0; c->inputs[i].input; i++) { | ||
| 384 | char *first = (i == 0) ? "" : " "; | ||
| 385 | seq_printf(s, "%s%s", first, c->inputs[i].input->name); | ||
| 386 | } | ||
| 387 | seq_printf(s, "\n"); | ||
| 388 | return 0; | ||
| 389 | } | ||
| 390 | |||
| 391 | static int possible_parents_open(struct inode *inode, struct file *file) | ||
| 392 | { | ||
| 393 | return single_open(file, possible_parents_show, inode->i_private); | ||
| 394 | } | ||
| 395 | |||
| 396 | static const struct file_operations possible_parents_fops = { | ||
| 397 | .open = possible_parents_open, | ||
| 398 | .read = seq_read, | ||
| 399 | .llseek = seq_lseek, | ||
| 400 | .release = single_release, | ||
| 401 | }; | ||
| 402 | |||
| 403 | static int clk_debugfs_register_one(struct clk *c) | ||
| 404 | { | ||
| 405 | struct dentry *d, *child, *child_tmp; | ||
| 406 | |||
| 407 | d = debugfs_create_dir(c->name, clk_debugfs_root); | ||
| 408 | if (!d) | ||
| 409 | return -ENOMEM; | ||
| 410 | c->dent = d; | ||
| 411 | |||
| 412 | d = debugfs_create_u8("refcnt", S_IRUGO, c->dent, (u8 *)&c->refcnt); | ||
| 413 | if (!d) | ||
| 414 | goto err_out; | ||
| 415 | |||
| 416 | d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); | ||
| 417 | if (!d) | ||
| 418 | goto err_out; | ||
| 419 | |||
| 420 | d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); | ||
| 421 | if (!d) | ||
| 422 | goto err_out; | ||
| 423 | |||
| 424 | if (c->inputs) { | ||
| 425 | d = debugfs_create_file("possible_parents", S_IRUGO, c->dent, | ||
| 426 | c, &possible_parents_fops); | ||
| 427 | if (!d) | ||
| 428 | goto err_out; | ||
| 429 | } | ||
| 430 | |||
| 431 | return 0; | ||
| 432 | |||
| 433 | err_out: | ||
| 434 | d = c->dent; | ||
| 435 | list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) | ||
| 436 | debugfs_remove(child); | ||
| 437 | debugfs_remove(c->dent); | ||
| 438 | return -ENOMEM; | ||
| 439 | } | ||
| 440 | |||
| 441 | static int clk_debugfs_register(struct clk *c) | ||
| 442 | { | ||
| 443 | int err; | ||
| 444 | struct clk *pa = c->parent; | ||
| 445 | |||
| 446 | if (pa && !pa->dent) { | ||
| 447 | err = clk_debugfs_register(pa); | ||
| 448 | if (err) | ||
| 449 | return err; | ||
| 450 | } | ||
| 451 | |||
| 452 | if (!c->dent) { | ||
| 453 | err = clk_debugfs_register_one(c); | ||
| 454 | if (err) | ||
| 455 | return err; | ||
| 456 | } | ||
| 457 | return 0; | ||
| 458 | } | ||
| 459 | |||
| 460 | static int __init clk_debugfs_init(void) | ||
| 461 | { | ||
| 462 | struct clk *c; | ||
| 463 | struct dentry *d; | ||
| 464 | int err = -ENOMEM; | ||
| 465 | |||
| 466 | d = debugfs_create_dir("clock", NULL); | ||
| 467 | if (!d) | ||
| 468 | return -ENOMEM; | ||
| 469 | clk_debugfs_root = d; | ||
| 470 | |||
| 471 | d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL, | ||
| 472 | &clock_tree_fops); | ||
| 473 | if (!d) | ||
| 474 | goto err_out; | ||
| 475 | |||
| 476 | list_for_each_entry(c, &clocks, node) { | ||
| 477 | err = clk_debugfs_register(c); | ||
| 478 | if (err) | ||
| 479 | goto err_out; | ||
| 480 | } | ||
| 481 | return 0; | ||
| 482 | err_out: | ||
| 483 | debugfs_remove_recursive(clk_debugfs_root); | ||
| 484 | return err; | ||
| 485 | } | ||
| 486 | |||
| 487 | late_initcall(clk_debugfs_init); | ||
| 488 | #endif | ||
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h new file mode 100644 index 000000000000..af7c70e2a3ba --- /dev/null +++ b/arch/arm/mach-tegra/clock.h | |||
| @@ -0,0 +1,147 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/clock.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * | ||
| 9 | * This software is licensed under the terms of the GNU General Public | ||
| 10 | * License version 2, as published by the Free Software Foundation, and | ||
| 11 | * may be copied, distributed, and modified under those terms. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef __MACH_TEGRA_CLOCK_H | ||
| 21 | #define __MACH_TEGRA_CLOCK_H | ||
| 22 | |||
| 23 | #include <linux/list.h> | ||
| 24 | #include <asm/clkdev.h> | ||
| 25 | |||
| 26 | #define DIV_BUS (1 << 0) | ||
| 27 | #define DIV_U71 (1 << 1) | ||
| 28 | #define DIV_U71_FIXED (1 << 2) | ||
| 29 | #define DIV_2 (1 << 3) | ||
| 30 | #define PLL_FIXED (1 << 4) | ||
| 31 | #define PLL_HAS_CPCON (1 << 5) | ||
| 32 | #define MUX (1 << 6) | ||
| 33 | #define PLLD (1 << 7) | ||
| 34 | #define PERIPH_NO_RESET (1 << 8) | ||
| 35 | #define PERIPH_NO_ENB (1 << 9) | ||
| 36 | #define PERIPH_EMC_ENB (1 << 10) | ||
| 37 | #define PERIPH_MANUAL_RESET (1 << 11) | ||
| 38 | #define PLL_ALT_MISC_REG (1 << 12) | ||
| 39 | #define ENABLE_ON_INIT (1 << 28) | ||
| 40 | |||
| 41 | struct clk; | ||
| 42 | |||
| 43 | struct clk_mux_sel { | ||
| 44 | struct clk *input; | ||
| 45 | u32 value; | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct clk_pll_table { | ||
| 49 | unsigned long input_rate; | ||
| 50 | unsigned long output_rate; | ||
| 51 | u16 n; | ||
| 52 | u16 m; | ||
| 53 | u8 p; | ||
| 54 | u8 cpcon; | ||
| 55 | }; | ||
| 56 | |||
| 57 | struct clk_ops { | ||
| 58 | void (*init)(struct clk *); | ||
| 59 | int (*enable)(struct clk *); | ||
| 60 | void (*disable)(struct clk *); | ||
| 61 | void (*recalc)(struct clk *); | ||
| 62 | int (*set_parent)(struct clk *, struct clk *); | ||
| 63 | int (*set_rate)(struct clk *, unsigned long); | ||
| 64 | unsigned long (*get_rate)(struct clk *); | ||
| 65 | long (*round_rate)(struct clk *, unsigned long); | ||
| 66 | unsigned long (*recalculate_rate)(struct clk *); | ||
| 67 | }; | ||
| 68 | |||
| 69 | enum clk_state { | ||
| 70 | UNINITIALIZED = 0, | ||
| 71 | ON, | ||
| 72 | OFF, | ||
| 73 | }; | ||
| 74 | |||
| 75 | struct clk { | ||
| 76 | /* node for master clocks list */ | ||
| 77 | struct list_head node; | ||
| 78 | struct list_head children; /* list of children */ | ||
| 79 | struct list_head sibling; /* node for children */ | ||
| 80 | #ifdef CONFIG_DEBUG_FS | ||
| 81 | struct dentry *dent; | ||
| 82 | struct dentry *parent_dent; | ||
| 83 | #endif | ||
| 84 | struct clk_ops *ops; | ||
| 85 | struct clk *parent; | ||
| 86 | struct clk_lookup lookup; | ||
| 87 | unsigned long rate; | ||
| 88 | u32 flags; | ||
| 89 | u32 refcnt; | ||
| 90 | const char *name; | ||
| 91 | u32 reg; | ||
| 92 | u32 reg_shift; | ||
| 93 | unsigned int clk_num; | ||
| 94 | enum clk_state state; | ||
| 95 | #ifdef CONFIG_DEBUG_FS | ||
| 96 | bool set; | ||
| 97 | #endif | ||
| 98 | |||
| 99 | /* PLL */ | ||
| 100 | unsigned long input_min; | ||
| 101 | unsigned long input_max; | ||
| 102 | unsigned long cf_min; | ||
| 103 | unsigned long cf_max; | ||
| 104 | unsigned long vco_min; | ||
| 105 | unsigned long vco_max; | ||
| 106 | u32 m; | ||
| 107 | u32 n; | ||
| 108 | u32 p; | ||
| 109 | u32 cpcon; | ||
| 110 | const struct clk_pll_table *pll_table; | ||
| 111 | |||
| 112 | /* DIV */ | ||
| 113 | u32 div; | ||
| 114 | u32 mul; | ||
| 115 | |||
| 116 | /* MUX */ | ||
| 117 | const struct clk_mux_sel *inputs; | ||
| 118 | u32 sel; | ||
| 119 | u32 reg_mask; | ||
| 120 | }; | ||
| 121 | |||
| 122 | |||
| 123 | struct clk_duplicate { | ||
| 124 | const char *name; | ||
| 125 | struct clk_lookup lookup; | ||
| 126 | }; | ||
| 127 | |||
| 128 | struct tegra_clk_init_table { | ||
| 129 | const char *name; | ||
| 130 | const char *parent; | ||
| 131 | unsigned long rate; | ||
| 132 | bool enabled; | ||
| 133 | }; | ||
| 134 | |||
| 135 | void tegra2_init_clocks(void); | ||
| 136 | void tegra2_periph_reset_deassert(struct clk *c); | ||
| 137 | void tegra2_periph_reset_assert(struct clk *c); | ||
| 138 | void clk_init(struct clk *clk); | ||
| 139 | struct clk *tegra_get_clock_by_name(const char *name); | ||
| 140 | unsigned long clk_measure_input_freq(void); | ||
| 141 | void clk_disable_locked(struct clk *c); | ||
| 142 | int clk_enable_locked(struct clk *c); | ||
| 143 | int clk_set_parent_locked(struct clk *c, struct clk *parent); | ||
| 144 | int clk_reparent(struct clk *c, struct clk *parent); | ||
| 145 | void tegra_clk_init_from_table(struct tegra_clk_init_table *table); | ||
| 146 | |||
| 147 | #endif | ||
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c new file mode 100644 index 000000000000..039a514b61ef --- /dev/null +++ b/arch/arm/mach-tegra/common.c | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/board-harmony.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@android.com> | ||
| 8 | * | ||
| 9 | * This software is licensed under the terms of the GNU General Public | ||
| 10 | * License version 2, as published by the Free Software Foundation, and | ||
| 11 | * may be copied, distributed, and modified under those terms. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | |||
| 23 | #include <asm/hardware/cache-l2x0.h> | ||
| 24 | |||
| 25 | #include <mach/iomap.h> | ||
| 26 | |||
| 27 | #include "board.h" | ||
| 28 | #include "clock.h" | ||
| 29 | |||
| 30 | static __initdata struct tegra_clk_init_table common_clk_init_table[] = { | ||
| 31 | /* name parent rate enabled */ | ||
| 32 | { "clk_m", NULL, 0, true }, | ||
| 33 | { "pll_p", "clk_m", 216000000, true }, | ||
| 34 | { "pll_p_out1", "pll_p", 28800000, true }, | ||
| 35 | { "pll_p_out2", "pll_p", 48000000, true }, | ||
| 36 | { "pll_p_out3", "pll_p", 72000000, true }, | ||
| 37 | { "pll_p_out4", "pll_p", 108000000, true }, | ||
| 38 | { "sys", "pll_p_out4", 108000000, true }, | ||
| 39 | { "hclk", "sys", 108000000, true }, | ||
| 40 | { "pclk", "hclk", 54000000, true }, | ||
| 41 | { NULL, NULL, 0, 0}, | ||
| 42 | }; | ||
| 43 | |||
| 44 | void __init tegra_init_cache(void) | ||
| 45 | { | ||
| 46 | #ifdef CONFIG_CACHE_L2X0 | ||
| 47 | void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; | ||
| 48 | |||
| 49 | writel(0x331, p + L2X0_TAG_LATENCY_CTRL); | ||
| 50 | writel(0x441, p + L2X0_DATA_LATENCY_CTRL); | ||
| 51 | |||
| 52 | l2x0_init(p, 0x6C080001, 0x8200c3fe); | ||
| 53 | #endif | ||
| 54 | } | ||
| 55 | |||
| 56 | void __init tegra_common_init(void) | ||
| 57 | { | ||
| 58 | tegra_init_clock(); | ||
| 59 | tegra_clk_init_from_table(common_clk_init_table); | ||
| 60 | tegra_init_cache(); | ||
| 61 | } | ||
diff --git a/arch/arm/mach-tegra/gpio-names.h b/arch/arm/mach-tegra/gpio-names.h new file mode 100644 index 000000000000..f28220a641b2 --- /dev/null +++ b/arch/arm/mach-tegra/gpio-names.h | |||
| @@ -0,0 +1,247 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/gpio-names.h | ||
| 3 | * | ||
| 4 | * Copyright (c) 2010 Google, Inc | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Erik Gilling <konkers@google.com> | ||
| 8 | * | ||
| 9 | * This software is licensed under the terms of the GNU General Public | ||
| 10 | * License version 2, as published by the Free Software Foundation, and | ||
| 11 | * may be copied, distributed, and modified under those terms. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef __MACH_TEGRA_GPIO_NAMES_H | ||
| 20 | #define __MACH_TEGRA_GPIO_NAMES_H | ||
| 21 | |||
| 22 | #define TEGRA_GPIO_PA0 0 | ||
| 23 | #define TEGRA_GPIO_PA1 1 | ||
| 24 | #define TEGRA_GPIO_PA2 2 | ||
| 25 | #define TEGRA_GPIO_PA3 3 | ||
| 26 | #define TEGRA_GPIO_PA4 4 | ||
| 27 | #define TEGRA_GPIO_PA5 5 | ||
| 28 | #define TEGRA_GPIO_PA6 6 | ||
| 29 | #define TEGRA_GPIO_PA7 7 | ||
| 30 | #define TEGRA_GPIO_PB0 8 | ||
| 31 | #define TEGRA_GPIO_PB1 9 | ||
| 32 | #define TEGRA_GPIO_PB2 10 | ||
| 33 | #define TEGRA_GPIO_PB3 11 | ||
| 34 | #define TEGRA_GPIO_PB4 12 | ||
| 35 | #define TEGRA_GPIO_PB5 13 | ||
| 36 | #define TEGRA_GPIO_PB6 14 | ||
| 37 | #define TEGRA_GPIO_PB7 15 | ||
| 38 | #define TEGRA_GPIO_PC0 16 | ||
| 39 | #define TEGRA_GPIO_PC1 17 | ||
| 40 | #define TEGRA_GPIO_PC2 18 | ||
| 41 | #define TEGRA_GPIO_PC3 19 | ||
| 42 | #define TEGRA_GPIO_PC4 20 | ||
| 43 | #define TEGRA_GPIO_PC5 21 | ||
| 44 | #define TEGRA_GPIO_PC6 22 | ||
| 45 | #define TEGRA_GPIO_PC7 23 | ||
| 46 | #define TEGRA_GPIO_PD0 24 | ||
| 47 | #define TEGRA_GPIO_PD1 25 | ||
| 48 | #define TEGRA_GPIO_PD2 26 | ||
| 49 | #define TEGRA_GPIO_PD3 27 | ||
| 50 | #define TEGRA_GPIO_PD4 28 | ||
| 51 | #define TEGRA_GPIO_PD5 29 | ||
| 52 | #define TEGRA_GPIO_PD6 30 | ||
| 53 | #define TEGRA_GPIO_PD7 31 | ||
| 54 | #define TEGRA_GPIO_PE0 32 | ||
| 55 | #define TEGRA_GPIO_PE1 33 | ||
| 56 | #define TEGRA_GPIO_PE2 34 | ||
| 57 | #define TEGRA_GPIO_PE3 35 | ||
| 58 | #define TEGRA_GPIO_PE4 36 | ||
| 59 | #define TEGRA_GPIO_PE5 37 | ||
| 60 | #define TEGRA_GPIO_PE6 38 | ||
| 61 | #define TEGRA_GPIO_PE7 39 | ||
| 62 | #define TEGRA_GPIO_PF0 40 | ||
| 63 | #define TEGRA_GPIO_PF1 41 | ||
| 64 | #define TEGRA_GPIO_PF2 42 | ||
| 65 | #define TEGRA_GPIO_PF3 43 | ||
| 66 | #define TEGRA_GPIO_PF4 44 | ||
| 67 | #define TEGRA_GPIO_PF5 45 | ||
| 68 | #define TEGRA_GPIO_PF6 46 | ||
| 69 | #define TEGRA_GPIO_PF7 47 | ||
| 70 | #define TEGRA_GPIO_PG0 48 | ||
| 71 | #define TEGRA_GPIO_PG1 49 | ||
| 72 | #define TEGRA_GPIO_PG2 50 | ||
| 73 | #define TEGRA_GPIO_PG3 51 | ||
| 74 | #define TEGRA_GPIO_PG4 52 | ||
| 75 | #define TEGRA_GPIO_PG5 53 | ||
| 76 | #define TEGRA_GPIO_PG6 54 | ||
| 77 | #define TEGRA_GPIO_PG7 55 | ||
| 78 | #define TEGRA_GPIO_PH0 56 | ||
| 79 | #define TEGRA_GPIO_PH1 57 | ||
| 80 | #define TEGRA_GPIO_PH2 58 | ||
| 81 | #define TEGRA_GPIO_PH3 59 | ||
| 82 | #define TEGRA_GPIO_PH4 60 | ||
| 83 | #define TEGRA_GPIO_PH5 61 | ||
| 84 | #define TEGRA_GPIO_PH6 62 | ||
| 85 | #define TEGRA_GPIO_PH7 63 | ||
| 86 | #define TEGRA_GPIO_PI0 64 | ||
| 87 | #define TEGRA_GPIO_PI1 65 | ||
| 88 | #define TEGRA_GPIO_PI2 66 | ||
| 89 | #define TEGRA_GPIO_PI3 67 | ||
| 90 | #define TEGRA_GPIO_PI4 68 | ||
| 91 | #define TEGRA_GPIO_PI5 69 | ||
| 92 | #define TEGRA_GPIO_PI6 70 | ||
| 93 | #define TEGRA_GPIO_PI7 71 | ||
| 94 | #define TEGRA_GPIO_PJ0 72 | ||
| 95 | #define TEGRA_GPIO_PJ1 73 | ||
| 96 | #define TEGRA_GPIO_PJ2 74 | ||
| 97 | #define TEGRA_GPIO_PJ3 75 | ||
| 98 | #define TEGRA_GPIO_PJ4 76 | ||
| 99 | #define TEGRA_GPIO_PJ5 77 | ||
| 100 | #define TEGRA_GPIO_PJ6 78 | ||
| 101 | #define TEGRA_GPIO_PJ7 79 | ||
| 102 | #define TEGRA_GPIO_PK0 80 | ||
| 103 | #define TEGRA_GPIO_PK1 81 | ||
| 104 | #define TEGRA_GPIO_PK2 82 | ||
| 105 | #define TEGRA_GPIO_PK3 83 | ||
| 106 | #define TEGRA_GPIO_PK4 84 | ||
| 107 | #define TEGRA_GPIO_PK5 85 | ||
| 108 | #define TEGRA_GPIO_PK6 86 | ||
| 109 | #define TEGRA_GPIO_PK7 87 | ||
| 110 | #define TEGRA_GPIO_PL0 88 | ||
| 111 | #define TEGRA_GPIO_PL1 89 | ||
| 112 | #define TEGRA_GPIO_PL2 90 | ||
| 113 | #define TEGRA_GPIO_PL3 91 | ||
| 114 | #define TEGRA_GPIO_PL4 92 | ||
| 115 | #define TEGRA_GPIO_PL5 93 | ||
| 116 | #define TEGRA_GPIO_PL6 94 | ||
| 117 | #define TEGRA_GPIO_PL7 95 | ||
| 118 | #define TEGRA_GPIO_PM0 96 | ||
| 119 | #define TEGRA_GPIO_PM1 97 | ||
| 120 | #define TEGRA_GPIO_PM2 98 | ||
| 121 | #define TEGRA_GPIO_PM3 99 | ||
| 122 | #define TEGRA_GPIO_PM4 100 | ||
| 123 | #define TEGRA_GPIO_PM5 101 | ||
| 124 | #define TEGRA_GPIO_PM6 102 | ||
| 125 | #define TEGRA_GPIO_PM7 103 | ||
| 126 | #define TEGRA_GPIO_PN0 104 | ||
| 127 | #define TEGRA_GPIO_PN1 105 | ||
| 128 | #define TEGRA_GPIO_PN2 106 | ||
| 129 | #define TEGRA_GPIO_PN3 107 | ||
| 130 | #define TEGRA_GPIO_PN4 108 | ||
| 131 | #define TEGRA_GPIO_PN5 109 | ||
| 132 | #define TEGRA_GPIO_PN6 110 | ||
| 133 | #define TEGRA_GPIO_PN7 111 | ||
| 134 | #define TEGRA_GPIO_PO0 112 | ||
| 135 | #define TEGRA_GPIO_PO1 113 | ||
| 136 | #define TEGRA_GPIO_PO2 114 | ||
| 137 | #define TEGRA_GPIO_PO3 115 | ||
| 138 | #define TEGRA_GPIO_PO4 116 | ||
| 139 | #define TEGRA_GPIO_PO5 117 | ||
| 140 | #define TEGRA_GPIO_PO6 118 | ||
| 141 | #define TEGRA_GPIO_PO7 119 | ||
| 142 | #define TEGRA_GPIO_PP0 120 | ||
| 143 | #define TEGRA_GPIO_PP1 121 | ||
| 144 | #define TEGRA_GPIO_PP2 122 | ||
| 145 | #define TEGRA_GPIO_PP3 123 | ||
| 146 | #define TEGRA_GPIO_PP4 124 | ||
| 147 | #define TEGRA_GPIO_PP5 125 | ||
| 148 | #define TEGRA_GPIO_PP6 126 | ||
| 149 | #define TEGRA_GPIO_PP7 127 | ||
| 150 | #define TEGRA_GPIO_PQ0 128 | ||
| 151 | #define TEGRA_GPIO_PQ1 129 | ||
| 152 | #define TEGRA_GPIO_PQ2 130 | ||
| 153 | #define TEGRA_GPIO_PQ3 131 | ||
| 154 | #define TEGRA_GPIO_PQ4 132 | ||
| 155 | #define TEGRA_GPIO_PQ5 133 | ||
| 156 | #define TEGRA_GPIO_PQ6 134 | ||
| 157 | #define TEGRA_GPIO_PQ7 135 | ||
| 158 | #define TEGRA_GPIO_PR0 136 | ||
| 159 | #define TEGRA_GPIO_PR1 137 | ||
| 160 | #define TEGRA_GPIO_PR2 138 | ||
| 161 | #define TEGRA_GPIO_PR3 139 | ||
| 162 | #define TEGRA_GPIO_PR4 140 | ||
| 163 | #define TEGRA_GPIO_PR5 141 | ||
| 164 | #define TEGRA_GPIO_PR6 142 | ||
| 165 | #define TEGRA_GPIO_PR7 143 | ||
| 166 | #define TEGRA_GPIO_PS0 144 | ||
| 167 | #define TEGRA_GPIO_PS1 145 | ||
| 168 | #define TEGRA_GPIO_PS2 146 | ||
| 169 | #define TEGRA_GPIO_PS3 147 | ||
| 170 | #define TEGRA_GPIO_PS4 148 | ||
| 171 | #define TEGRA_GPIO_PS5 149 | ||
| 172 | #define TEGRA_GPIO_PS6 150 | ||
| 173 | #define TEGRA_GPIO_PS7 151 | ||
| 174 | #define TEGRA_GPIO_PT0 152 | ||
| 175 | #define TEGRA_GPIO_PT1 153 | ||
| 176 | #define TEGRA_GPIO_PT2 154 | ||
| 177 | #define TEGRA_GPIO_PT3 155 | ||
| 178 | #define TEGRA_GPIO_PT4 156 | ||
| 179 | #define TEGRA_GPIO_PT5 157 | ||
| 180 | #define TEGRA_GPIO_PT6 158 | ||
| 181 | #define TEGRA_GPIO_PT7 159 | ||
| 182 | #define TEGRA_GPIO_PU0 160 | ||
| 183 | #define TEGRA_GPIO_PU1 161 | ||
| 184 | #define TEGRA_GPIO_PU2 162 | ||
| 185 | #define TEGRA_GPIO_PU3 163 | ||
| 186 | #define TEGRA_GPIO_PU4 164 | ||
| 187 | #define TEGRA_GPIO_PU5 165 | ||
| 188 | #define TEGRA_GPIO_PU6 166 | ||
| 189 | #define TEGRA_GPIO_PU7 167 | ||
| 190 | #define TEGRA_GPIO_PV0 168 | ||
| 191 | #define TEGRA_GPIO_PV1 169 | ||
| 192 | #define TEGRA_GPIO_PV2 170 | ||
| 193 | #define TEGRA_GPIO_PV3 171 | ||
| 194 | #define TEGRA_GPIO_PV4 172 | ||
| 195 | #define TEGRA_GPIO_PV5 173 | ||
| 196 | #define TEGRA_GPIO_PV6 174 | ||
| 197 | #define TEGRA_GPIO_PV7 175 | ||
| 198 | #define TEGRA_GPIO_PW0 176 | ||
| 199 | #define TEGRA_GPIO_PW1 177 | ||
| 200 | #define TEGRA_GPIO_PW2 178 | ||
| 201 | #define TEGRA_GPIO_PW3 179 | ||
| 202 | #define TEGRA_GPIO_PW4 180 | ||
| 203 | #define TEGRA_GPIO_PW5 181 | ||
| 204 | #define TEGRA_GPIO_PW6 182 | ||
| 205 | #define TEGRA_GPIO_PW7 183 | ||
| 206 | #define TEGRA_GPIO_PX0 184 | ||
| 207 | #define TEGRA_GPIO_PX1 185 | ||
| 208 | #define TEGRA_GPIO_PX2 186 | ||
| 209 | #define TEGRA_GPIO_PX3 187 | ||
| 210 | #define TEGRA_GPIO_PX4 188 | ||
| 211 | #define TEGRA_GPIO_PX5 189 | ||
| 212 | #define TEGRA_GPIO_PX6 190 | ||
| 213 | #define TEGRA_GPIO_PX7 191 | ||
| 214 | #define TEGRA_GPIO_PY0 192 | ||
| 215 | #define TEGRA_GPIO_PY1 193 | ||
| 216 | #define TEGRA_GPIO_PY2 194 | ||
| 217 | #define TEGRA_GPIO_PY3 195 | ||
| 218 | #define TEGRA_GPIO_PY4 196 | ||
| 219 | #define TEGRA_GPIO_PY5 197 | ||
| 220 | #define TEGRA_GPIO_PY6 198 | ||
| 221 | #define TEGRA_GPIO_PY7 199 | ||
| 222 | #define TEGRA_GPIO_PZ0 200 | ||
| 223 | #define TEGRA_GPIO_PZ1 201 | ||
| 224 | #define TEGRA_GPIO_PZ2 202 | ||
| 225 | #define TEGRA_GPIO_PZ3 203 | ||
| 226 | #define TEGRA_GPIO_PZ4 204 | ||
| 227 | #define TEGRA_GPIO_PZ5 205 | ||
| 228 | #define TEGRA_GPIO_PZ6 206 | ||
| 229 | #define TEGRA_GPIO_PZ7 207 | ||
| 230 | #define TEGRA_GPIO_PAA0 208 | ||
| 231 | #define TEGRA_GPIO_PAA1 209 | ||
| 232 | #define TEGRA_GPIO_PAA2 210 | ||
| 233 | #define TEGRA_GPIO_PAA3 211 | ||
| 234 | #define TEGRA_GPIO_PAA4 212 | ||
| 235 | #define TEGRA_GPIO_PAA5 213 | ||
| 236 | #define TEGRA_GPIO_PAA6 214 | ||
| 237 | #define TEGRA_GPIO_PAA7 215 | ||
| 238 | #define TEGRA_GPIO_PBB0 216 | ||
| 239 | #define TEGRA_GPIO_PBB1 217 | ||
| 240 | #define TEGRA_GPIO_PBB2 218 | ||
| 241 | #define TEGRA_GPIO_PBB3 219 | ||
| 242 | #define TEGRA_GPIO_PBB4 220 | ||
| 243 | #define TEGRA_GPIO_PBB5 221 | ||
| 244 | #define TEGRA_GPIO_PBB6 222 | ||
| 245 | #define TEGRA_GPIO_PBB7 223 | ||
| 246 | |||
| 247 | #endif | ||
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c new file mode 100644 index 000000000000..fe78fba25f3c --- /dev/null +++ b/arch/arm/mach-tegra/gpio.c | |||
| @@ -0,0 +1,348 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/gpio.c | ||
| 3 | * | ||
| 4 | * Copyright (c) 2010 Google, Inc | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Erik Gilling <konkers@google.com> | ||
| 8 | * | ||
| 9 | * This software is licensed under the terms of the GNU General Public | ||
| 10 | * License version 2, as published by the Free Software Foundation, and | ||
| 11 | * may be copied, distributed, and modified under those terms. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/irq.h> | ||
| 22 | |||
| 23 | #include <linux/io.h> | ||
| 24 | #include <linux/gpio.h> | ||
| 25 | |||
| 26 | #include <mach/iomap.h> | ||
| 27 | |||
| 28 | #define GPIO_BANK(x) ((x) >> 5) | ||
| 29 | #define GPIO_PORT(x) (((x) >> 3) & 0x3) | ||
| 30 | #define GPIO_BIT(x) ((x) & 0x7) | ||
| 31 | |||
| 32 | #define GPIO_REG(x) (IO_TO_VIRT(TEGRA_GPIO_BASE) + \ | ||
| 33 | GPIO_BANK(x) * 0x80 + \ | ||
| 34 | GPIO_PORT(x) * 4) | ||
| 35 | |||
| 36 | #define GPIO_CNF(x) (GPIO_REG(x) + 0x00) | ||
| 37 | #define GPIO_OE(x) (GPIO_REG(x) + 0x10) | ||
| 38 | #define GPIO_OUT(x) (GPIO_REG(x) + 0X20) | ||
| 39 | #define GPIO_IN(x) (GPIO_REG(x) + 0x30) | ||
| 40 | #define GPIO_INT_STA(x) (GPIO_REG(x) + 0x40) | ||
| 41 | #define GPIO_INT_ENB(x) (GPIO_REG(x) + 0x50) | ||
| 42 | #define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60) | ||
| 43 | #define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70) | ||
| 44 | |||
| 45 | #define GPIO_MSK_CNF(x) (GPIO_REG(x) + 0x800) | ||
| 46 | #define GPIO_MSK_OE(x) (GPIO_REG(x) + 0x810) | ||
| 47 | #define GPIO_MSK_OUT(x) (GPIO_REG(x) + 0X820) | ||
| 48 | #define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + 0x840) | ||
| 49 | #define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + 0x850) | ||
| 50 | #define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + 0x860) | ||
| 51 | |||
| 52 | #define GPIO_INT_LVL_MASK 0x010101 | ||
| 53 | #define GPIO_INT_LVL_EDGE_RISING 0x000101 | ||
| 54 | #define GPIO_INT_LVL_EDGE_FALLING 0x000100 | ||
| 55 | #define GPIO_INT_LVL_EDGE_BOTH 0x010100 | ||
| 56 | #define GPIO_INT_LVL_LEVEL_HIGH 0x000001 | ||
| 57 | #define GPIO_INT_LVL_LEVEL_LOW 0x000000 | ||
| 58 | |||
| 59 | struct tegra_gpio_bank { | ||
| 60 | int bank; | ||
| 61 | int irq; | ||
| 62 | spinlock_t lvl_lock[4]; | ||
| 63 | }; | ||
| 64 | |||
| 65 | |||
| 66 | static struct tegra_gpio_bank tegra_gpio_banks[] = { | ||
| 67 | {.bank = 0, .irq = INT_GPIO1}, | ||
| 68 | {.bank = 1, .irq = INT_GPIO2}, | ||
| 69 | {.bank = 2, .irq = INT_GPIO3}, | ||
| 70 | {.bank = 3, .irq = INT_GPIO4}, | ||
| 71 | {.bank = 4, .irq = INT_GPIO5}, | ||
| 72 | {.bank = 5, .irq = INT_GPIO6}, | ||
| 73 | {.bank = 6, .irq = INT_GPIO7}, | ||
| 74 | }; | ||
| 75 | |||
| 76 | static int tegra_gpio_compose(int bank, int port, int bit) | ||
| 77 | { | ||
| 78 | return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7); | ||
| 79 | } | ||
| 80 | |||
| 81 | static void tegra_gpio_mask_write(u32 reg, int gpio, int value) | ||
| 82 | { | ||
| 83 | u32 val; | ||
| 84 | |||
| 85 | val = 0x100 << GPIO_BIT(gpio); | ||
| 86 | if (value) | ||
| 87 | val |= 1 << GPIO_BIT(gpio); | ||
| 88 | __raw_writel(val, reg); | ||
| 89 | } | ||
| 90 | |||
| 91 | void tegra_gpio_enable(int gpio) | ||
| 92 | { | ||
| 93 | tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1); | ||
| 94 | } | ||
| 95 | |||
| 96 | void tegra_gpio_disable(int gpio) | ||
| 97 | { | ||
| 98 | tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0); | ||
| 99 | } | ||
| 100 | |||
| 101 | static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
| 102 | { | ||
| 103 | tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value); | ||
| 104 | } | ||
| 105 | |||
| 106 | static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
| 107 | { | ||
| 108 | return (__raw_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1; | ||
| 109 | } | ||
| 110 | |||
| 111 | static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
| 112 | { | ||
| 113 | tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0); | ||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
| 118 | int value) | ||
| 119 | { | ||
| 120 | tegra_gpio_set(chip, offset, value); | ||
| 121 | tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1); | ||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | |||
| 126 | |||
| 127 | static struct gpio_chip tegra_gpio_chip = { | ||
| 128 | .label = "tegra-gpio", | ||
| 129 | .direction_input = tegra_gpio_direction_input, | ||
| 130 | .get = tegra_gpio_get, | ||
| 131 | .direction_output = tegra_gpio_direction_output, | ||
| 132 | .set = tegra_gpio_set, | ||
| 133 | .base = 0, | ||
| 134 | .ngpio = ARCH_NR_GPIOS, | ||
| 135 | }; | ||
| 136 | |||
| 137 | static void tegra_gpio_irq_ack(unsigned int irq) | ||
| 138 | { | ||
| 139 | int gpio = irq - INT_GPIO_BASE; | ||
| 140 | |||
| 141 | __raw_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio)); | ||
| 142 | } | ||
| 143 | |||
| 144 | static void tegra_gpio_irq_mask(unsigned int irq) | ||
| 145 | { | ||
| 146 | int gpio = irq - INT_GPIO_BASE; | ||
| 147 | |||
| 148 | tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0); | ||
| 149 | } | ||
| 150 | |||
| 151 | static void tegra_gpio_irq_unmask(unsigned int irq) | ||
| 152 | { | ||
| 153 | int gpio = irq - INT_GPIO_BASE; | ||
| 154 | |||
| 155 | tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1); | ||
| 156 | } | ||
| 157 | |||
| 158 | static int tegra_gpio_irq_set_type(unsigned int irq, unsigned int type) | ||
| 159 | { | ||
| 160 | int gpio = irq - INT_GPIO_BASE; | ||
| 161 | struct tegra_gpio_bank *bank = get_irq_chip_data(irq); | ||
| 162 | int port = GPIO_PORT(gpio); | ||
| 163 | int lvl_type; | ||
| 164 | int val; | ||
| 165 | unsigned long flags; | ||
| 166 | |||
| 167 | switch (type & IRQ_TYPE_SENSE_MASK) { | ||
| 168 | case IRQ_TYPE_EDGE_RISING: | ||
| 169 | lvl_type = GPIO_INT_LVL_EDGE_RISING; | ||
| 170 | break; | ||
| 171 | |||
| 172 | case IRQ_TYPE_EDGE_FALLING: | ||
| 173 | lvl_type = GPIO_INT_LVL_EDGE_FALLING; | ||
| 174 | break; | ||
| 175 | |||
| 176 | case IRQ_TYPE_EDGE_BOTH: | ||
| 177 | lvl_type = GPIO_INT_LVL_EDGE_BOTH; | ||
| 178 | break; | ||
| 179 | |||
| 180 | case IRQ_TYPE_LEVEL_HIGH: | ||
| 181 | lvl_type = GPIO_INT_LVL_LEVEL_HIGH; | ||
| 182 | break; | ||
| 183 | |||
| 184 | case IRQ_TYPE_LEVEL_LOW: | ||
| 185 | lvl_type = GPIO_INT_LVL_LEVEL_LOW; | ||
| 186 | break; | ||
| 187 | |||
| 188 | default: | ||
| 189 | return -EINVAL; | ||
| 190 | } | ||
| 191 | |||
| 192 | spin_lock_irqsave(&bank->lvl_lock[port], flags); | ||
| 193 | |||
| 194 | val = __raw_readl(GPIO_INT_LVL(gpio)); | ||
| 195 | val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio)); | ||
| 196 | val |= lvl_type << GPIO_BIT(gpio); | ||
| 197 | __raw_writel(val, GPIO_INT_LVL(gpio)); | ||
| 198 | |||
| 199 | spin_unlock_irqrestore(&bank->lvl_lock[port], flags); | ||
| 200 | |||
| 201 | if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) | ||
| 202 | __set_irq_handler_unlocked(irq, handle_level_irq); | ||
| 203 | else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) | ||
| 204 | __set_irq_handler_unlocked(irq, handle_edge_irq); | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
| 210 | { | ||
| 211 | struct tegra_gpio_bank *bank; | ||
| 212 | int port; | ||
| 213 | int pin; | ||
| 214 | int unmasked = 0; | ||
| 215 | |||
| 216 | desc->chip->ack(irq); | ||
| 217 | |||
| 218 | bank = get_irq_data(irq); | ||
| 219 | |||
| 220 | for (port = 0; port < 4; port++) { | ||
| 221 | int gpio = tegra_gpio_compose(bank->bank, port, 0); | ||
| 222 | unsigned long sta = __raw_readl(GPIO_INT_STA(gpio)) & | ||
| 223 | __raw_readl(GPIO_INT_ENB(gpio)); | ||
| 224 | u32 lvl = __raw_readl(GPIO_INT_LVL(gpio)); | ||
| 225 | |||
| 226 | for_each_set_bit(pin, &sta, 8) { | ||
| 227 | __raw_writel(1 << pin, GPIO_INT_CLR(gpio)); | ||
| 228 | |||
| 229 | /* if gpio is edge triggered, clear condition | ||
| 230 | * before executing the hander so that we don't | ||
| 231 | * miss edges | ||
| 232 | */ | ||
| 233 | if (lvl & (0x100 << pin)) { | ||
| 234 | unmasked = 1; | ||
| 235 | desc->chip->unmask(irq); | ||
| 236 | } | ||
| 237 | |||
| 238 | generic_handle_irq(gpio_to_irq(gpio + pin)); | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | if (!unmasked) | ||
| 243 | desc->chip->unmask(irq); | ||
| 244 | |||
| 245 | } | ||
| 246 | |||
| 247 | |||
| 248 | static struct irq_chip tegra_gpio_irq_chip = { | ||
| 249 | .name = "GPIO", | ||
| 250 | .ack = tegra_gpio_irq_ack, | ||
| 251 | .mask = tegra_gpio_irq_mask, | ||
| 252 | .unmask = tegra_gpio_irq_unmask, | ||
| 253 | .set_type = tegra_gpio_irq_set_type, | ||
| 254 | }; | ||
| 255 | |||
| 256 | |||
| 257 | /* This lock class tells lockdep that GPIO irqs are in a different | ||
| 258 | * category than their parents, so it won't report false recursion. | ||
| 259 | */ | ||
| 260 | static struct lock_class_key gpio_lock_class; | ||
| 261 | |||
| 262 | static int __init tegra_gpio_init(void) | ||
| 263 | { | ||
| 264 | struct tegra_gpio_bank *bank; | ||
| 265 | int i; | ||
| 266 | int j; | ||
| 267 | |||
| 268 | for (i = 0; i < 7; i++) { | ||
| 269 | for (j = 0; j < 4; j++) { | ||
| 270 | int gpio = tegra_gpio_compose(i, j, 0); | ||
| 271 | __raw_writel(0x00, GPIO_INT_ENB(gpio)); | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | gpiochip_add(&tegra_gpio_chip); | ||
| 276 | |||
| 277 | for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) { | ||
| 278 | bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))]; | ||
| 279 | |||
| 280 | lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class); | ||
| 281 | set_irq_chip_data(i, bank); | ||
| 282 | set_irq_chip(i, &tegra_gpio_irq_chip); | ||
| 283 | set_irq_handler(i, handle_simple_irq); | ||
| 284 | set_irq_flags(i, IRQF_VALID); | ||
| 285 | } | ||
| 286 | |||
| 287 | for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) { | ||
| 288 | bank = &tegra_gpio_banks[i]; | ||
| 289 | |||
| 290 | set_irq_chained_handler(bank->irq, tegra_gpio_irq_handler); | ||
| 291 | set_irq_data(bank->irq, bank); | ||
| 292 | |||
| 293 | for (j = 0; j < 4; j++) | ||
| 294 | spin_lock_init(&bank->lvl_lock[j]); | ||
| 295 | } | ||
| 296 | |||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | |||
| 300 | postcore_initcall(tegra_gpio_init); | ||
| 301 | |||
| 302 | #ifdef CONFIG_DEBUG_FS | ||
| 303 | |||
| 304 | #include <linux/debugfs.h> | ||
| 305 | #include <linux/seq_file.h> | ||
| 306 | |||
| 307 | static int dbg_gpio_show(struct seq_file *s, void *unused) | ||
| 308 | { | ||
| 309 | int i; | ||
| 310 | int j; | ||
| 311 | |||
| 312 | for (i = 0; i < 7; i++) { | ||
| 313 | for (j = 0; j < 4; j++) { | ||
| 314 | int gpio = tegra_gpio_compose(i, j, 0); | ||
| 315 | seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n", | ||
| 316 | i, j, | ||
| 317 | __raw_readl(GPIO_CNF(gpio)), | ||
| 318 | __raw_readl(GPIO_OE(gpio)), | ||
| 319 | __raw_readl(GPIO_OUT(gpio)), | ||
| 320 | __raw_readl(GPIO_IN(gpio)), | ||
| 321 | __raw_readl(GPIO_INT_STA(gpio)), | ||
| 322 | __raw_readl(GPIO_INT_ENB(gpio)), | ||
| 323 | __raw_readl(GPIO_INT_LVL(gpio))); | ||
| 324 | } | ||
| 325 | } | ||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | |||
| 329 | static int dbg_gpio_open(struct inode *inode, struct file *file) | ||
| 330 | { | ||
| 331 | return single_open(file, dbg_gpio_show, &inode->i_private); | ||
| 332 | } | ||
| 333 | |||
| 334 | static const struct file_operations debug_fops = { | ||
| 335 | .open = dbg_gpio_open, | ||
| 336 | .read = seq_read, | ||
| 337 | .llseek = seq_lseek, | ||
| 338 | .release = single_release, | ||
| 339 | }; | ||
| 340 | |||
| 341 | static int __init tegra_gpio_debuginit(void) | ||
| 342 | { | ||
| 343 | (void) debugfs_create_file("tegra_gpio", S_IRUGO, | ||
| 344 | NULL, NULL, &debug_fops); | ||
| 345 | return 0; | ||
| 346 | } | ||
| 347 | late_initcall(tegra_gpio_debuginit); | ||
| 348 | #endif | ||
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S new file mode 100644 index 000000000000..b5349b2f13d2 --- /dev/null +++ b/arch/arm/mach-tegra/headsmp.S | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | #include <linux/linkage.h> | ||
| 2 | #include <linux/init.h> | ||
| 3 | |||
| 4 | .section ".text.head", "ax" | ||
| 5 | __CPUINIT | ||
| 6 | |||
| 7 | /* | ||
| 8 | * Tegra specific entry point for secondary CPUs. | ||
| 9 | * The secondary kernel init calls v7_flush_dcache_all before it enables | ||
| 10 | * the L1; however, the L1 comes out of reset in an undefined state, so | ||
| 11 | * the clean + invalidate performed by v7_flush_dcache_all causes a bunch | ||
| 12 | * of cache lines with uninitialized data and uninitialized tags to get | ||
| 13 | * written out to memory, which does really unpleasant things to the main | ||
| 14 | * processor. We fix this by performing an invalidate, rather than a | ||
| 15 | * clean + invalidate, before jumping into the kernel. | ||
| 16 | */ | ||
| 17 | ENTRY(v7_invalidate_l1) | ||
| 18 | mov r0, #0 | ||
| 19 | mcr p15, 2, r0, c0, c0, 0 | ||
| 20 | mrc p15, 1, r0, c0, c0, 0 | ||
| 21 | |||
| 22 | ldr r1, =0x7fff | ||
| 23 | and r2, r1, r0, lsr #13 | ||
| 24 | |||
| 25 | ldr r1, =0x3ff | ||
| 26 | |||
| 27 | and r3, r1, r0, lsr #3 @ NumWays - 1 | ||
| 28 | add r2, r2, #1 @ NumSets | ||
| 29 | |||
| 30 | and r0, r0, #0x7 | ||
| 31 | add r0, r0, #4 @ SetShift | ||
| 32 | |||
| 33 | clz r1, r3 @ WayShift | ||
| 34 | add r4, r3, #1 @ NumWays | ||
| 35 | 1: sub r2, r2, #1 @ NumSets-- | ||
| 36 | mov r3, r4 @ Temp = NumWays | ||
| 37 | 2: subs r3, r3, #1 @ Temp-- | ||
| 38 | mov r5, r3, lsl r1 | ||
| 39 | mov r6, r2, lsl r0 | ||
| 40 | orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift) | ||
| 41 | mcr p15, 0, r5, c7, c6, 2 | ||
| 42 | bgt 2b | ||
| 43 | cmp r2, #0 | ||
| 44 | bgt 1b | ||
| 45 | dsb | ||
| 46 | isb | ||
| 47 | mov pc, lr | ||
| 48 | ENDPROC(v7_invalidate_l1) | ||
| 49 | |||
| 50 | ENTRY(tegra_secondary_startup) | ||
| 51 | msr cpsr_fsxc, #0xd3 | ||
| 52 | bl v7_invalidate_l1 | ||
| 53 | mrc p15, 0, r0, c0, c0, 5 | ||
| 54 | and r0, r0, #15 | ||
| 55 | ldr r1, =0x6000f100 | ||
| 56 | str r0, [r1] | ||
| 57 | 1: ldr r2, [r1] | ||
| 58 | cmp r0, r2 | ||
| 59 | beq 1b | ||
| 60 | b secondary_startup | ||
| 61 | ENDPROC(tegra_secondary_startup) | ||
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c new file mode 100644 index 000000000000..8e7f115aa21e --- /dev/null +++ b/arch/arm/mach-tegra/hotplug.c | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | /* | ||
| 2 | * linux/arch/arm/mach-realview/hotplug.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002 ARM Ltd. | ||
| 5 | * All Rights Reserved | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/errno.h> | ||
| 13 | #include <linux/smp.h> | ||
| 14 | #include <linux/completion.h> | ||
| 15 | |||
| 16 | #include <asm/cacheflush.h> | ||
| 17 | |||
| 18 | static DECLARE_COMPLETION(cpu_killed); | ||
| 19 | |||
| 20 | static inline void cpu_enter_lowpower(void) | ||
| 21 | { | ||
| 22 | unsigned int v; | ||
| 23 | |||
| 24 | flush_cache_all(); | ||
| 25 | asm volatile( | ||
| 26 | " mcr p15, 0, %1, c7, c5, 0\n" | ||
| 27 | " mcr p15, 0, %1, c7, c10, 4\n" | ||
| 28 | /* | ||
| 29 | * Turn off coherency | ||
| 30 | */ | ||
| 31 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
| 32 | " bic %0, %0, #0x20\n" | ||
| 33 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
| 34 | " mrc p15, 0, %0, c1, c0, 0\n" | ||
| 35 | " bic %0, %0, #0x04\n" | ||
| 36 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
| 37 | : "=&r" (v) | ||
| 38 | : "r" (0) | ||
| 39 | : "cc"); | ||
| 40 | } | ||
| 41 | |||
| 42 | static inline void cpu_leave_lowpower(void) | ||
| 43 | { | ||
| 44 | unsigned int v; | ||
| 45 | |||
| 46 | asm volatile( | ||
| 47 | "mrc p15, 0, %0, c1, c0, 0\n" | ||
| 48 | " orr %0, %0, #0x04\n" | ||
| 49 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
| 50 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
| 51 | " orr %0, %0, #0x20\n" | ||
| 52 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
| 53 | : "=&r" (v) | ||
| 54 | : | ||
| 55 | : "cc"); | ||
| 56 | } | ||
| 57 | |||
| 58 | static inline void platform_do_lowpower(unsigned int cpu) | ||
| 59 | { | ||
| 60 | /* | ||
| 61 | * there is no power-control hardware on this platform, so all | ||
| 62 | * we can do is put the core into WFI; this is safe as the calling | ||
| 63 | * code will have already disabled interrupts | ||
| 64 | */ | ||
| 65 | for (;;) { | ||
| 66 | /* | ||
| 67 | * here's the WFI | ||
| 68 | */ | ||
| 69 | asm(".word 0xe320f003\n" | ||
| 70 | : | ||
| 71 | : | ||
| 72 | : "memory", "cc"); | ||
| 73 | |||
| 74 | /*if (pen_release == cpu) {*/ | ||
| 75 | /* | ||
| 76 | * OK, proper wakeup, we're done | ||
| 77 | */ | ||
| 78 | break; | ||
| 79 | /*}*/ | ||
| 80 | |||
| 81 | /* | ||
| 82 | * getting here, means that we have come out of WFI without | ||
| 83 | * having been woken up - this shouldn't happen | ||
| 84 | * | ||
| 85 | * The trouble is, letting people know about this is not really | ||
| 86 | * possible, since we are currently running incoherently, and | ||
| 87 | * therefore cannot safely call printk() or anything else | ||
| 88 | */ | ||
| 89 | #ifdef DEBUG | ||
| 90 | printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu); | ||
| 91 | #endif | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | int platform_cpu_kill(unsigned int cpu) | ||
| 96 | { | ||
| 97 | return wait_for_completion_timeout(&cpu_killed, 5000); | ||
| 98 | } | ||
| 99 | |||
| 100 | /* | ||
| 101 | * platform-specific code to shutdown a CPU | ||
| 102 | * | ||
| 103 | * Called with IRQs disabled | ||
| 104 | */ | ||
| 105 | void platform_cpu_die(unsigned int cpu) | ||
| 106 | { | ||
| 107 | #ifdef DEBUG | ||
| 108 | unsigned int this_cpu = hard_smp_processor_id(); | ||
| 109 | |||
| 110 | if (cpu != this_cpu) { | ||
| 111 | printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", | ||
| 112 | this_cpu, cpu); | ||
| 113 | BUG(); | ||
| 114 | } | ||
| 115 | #endif | ||
| 116 | |||
| 117 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
| 118 | complete(&cpu_killed); | ||
| 119 | |||
| 120 | /* | ||
| 121 | * we're ready for shutdown now, so do it | ||
| 122 | */ | ||
| 123 | cpu_enter_lowpower(); | ||
| 124 | platform_do_lowpower(cpu); | ||
| 125 | |||
| 126 | /* | ||
| 127 | * bring this CPU back into the world of cache | ||
| 128 | * coherency, and then restore interrupts | ||
| 129 | */ | ||
| 130 | cpu_leave_lowpower(); | ||
| 131 | } | ||
| 132 | |||
| 133 | int platform_cpu_disable(unsigned int cpu) | ||
| 134 | { | ||
| 135 | /* | ||
| 136 | * we don't allow CPU 0 to be shutdown (it is still too special | ||
| 137 | * e.g. clock tick interrupts) | ||
| 138 | */ | ||
| 139 | return cpu == 0 ? -EPERM : 0; | ||
| 140 | } | ||
diff --git a/arch/arm/mach-tegra/include/mach/barriers.h b/arch/arm/mach-tegra/include/mach/barriers.h new file mode 100644 index 000000000000..cc115174899b --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/barriers.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-realview/include/mach/barriers.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 ARM Ltd. | ||
| 5 | * Written by Catalin Marinas <catalin.marinas@arm.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __MACH_BARRIERS_H | ||
| 22 | #define __MACH_BARRIERS_H | ||
| 23 | |||
| 24 | #include <asm/outercache.h> | ||
| 25 | |||
| 26 | #define rmb() dmb() | ||
| 27 | #define wmb() do { dsb(); outer_sync(); } while (0) | ||
| 28 | #define mb() wmb() | ||
| 29 | |||
| 30 | #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 index 000000000000..2896f25ebfb5 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/clk.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/clk.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Erik Gilling <konkers@google.com> | ||
| 8 | * | ||
| 9 | * This software is licensed under the terms of the GNU General Public | ||
| 10 | * License version 2, as published by the Free Software Foundation, and | ||
| 11 | * may be copied, distributed, and modified under those terms. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef __MACH_CLK_H | ||
| 21 | #define __MACH_CLK_H | ||
| 22 | |||
| 23 | void tegra_periph_reset_deassert(struct clk *c); | ||
| 24 | void tegra_periph_reset_assert(struct clk *c); | ||
| 25 | |||
| 26 | #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 index 000000000000..412f5c63e65a --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/clkdev.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/clkdev.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * | ||
| 9 | * This software is licensed under the terms of the GNU General Public | ||
| 10 | * License version 2, as published by the Free Software Foundation, and | ||
| 11 | * may be copied, distributed, and modified under those terms. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef __MACH_CLKDEV_H | ||
| 21 | #define __MACH_CLKDEV_H | ||
| 22 | |||
| 23 | static inline int __clk_get(struct clk *clk) | ||
| 24 | { | ||
| 25 | return 1; | ||
| 26 | } | ||
| 27 | |||
| 28 | static inline void __clk_put(struct clk *clk) | ||
| 29 | { | ||
| 30 | } | ||
| 31 | |||
| 32 | #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 index 000000000000..55a39564b43c --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/debug-macro.S | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/debug-macro.S | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <mach/io.h> | ||
| 22 | |||
| 23 | .macro addruart,rx, tmp | ||
| 24 | mrc p15, 0, \rx, c1, c0 | ||
| 25 | tst \rx, #1 @ MMU enabled? | ||
| 26 | ldreq \rx, =IO_APB_PHYS @ physical | ||
| 27 | ldrne \rx, =IO_APB_VIRT @ virtual | ||
| 28 | #if defined(CONFIG_TEGRA_DEBUG_UART_NONE) | ||
| 29 | #error "A debug UART must be selected in the kernel config to use DEBUG_LL" | ||
| 30 | #elif defined(CONFIG_TEGRA_DEBUG_UARTA) | ||
| 31 | orr \rx, \rx, #0x6000 | ||
| 32 | #elif defined(CONFIG_TEGRA_DEBUG_UARTB) | ||
| 33 | ldr \tmp, =0x6040 | ||
| 34 | orr \rx, \rx, \tmp | ||
| 35 | #elif defined(CONFIG_TEGRA_DEBUG_UARTC) | ||
| 36 | orr \rx, \rx, #0x6200 | ||
| 37 | #elif defined(CONFIG_TEGRA_DEBUG_UARTD) | ||
| 38 | orr \rx, \rx, #0x6300 | ||
| 39 | #elif defined(CONFIG_TEGRA_DEBUG_UARTE) | ||
| 40 | orr \rx, \rx, #0x6400 | ||
| 41 | #endif | ||
| 42 | .endm | ||
| 43 | |||
| 44 | #define UART_SHIFT 2 | ||
| 45 | #include <asm/hardware/debug-8250.S> | ||
| 46 | |||
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 index 000000000000..2ba9e5c9d2f6 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/entry-macro.S | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | /* arch/arm/mach-tegra/include/mach/entry-macro.S | ||
| 2 | * | ||
| 3 | * Copyright (C) 2009 Palm, Inc. | ||
| 4 | * | ||
| 5 | * This software is licensed under the terms of the GNU General Public | ||
| 6 | * License version 2, as published by the Free Software Foundation, and | ||
| 7 | * may be copied, distributed, and modified under those terms. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | #include <mach/iomap.h> | ||
| 16 | #include <mach/io.h> | ||
| 17 | |||
| 18 | #if defined(CONFIG_ARM_GIC) | ||
| 19 | |||
| 20 | #include <asm/hardware/gic.h> | ||
| 21 | |||
| 22 | /* Uses the GIC interrupt controller built into the cpu */ | ||
| 23 | #define ICTRL_BASE (IO_CPU_VIRT + 0x100) | ||
| 24 | |||
| 25 | .macro disable_fiq | ||
| 26 | .endm | ||
| 27 | |||
| 28 | .macro get_irqnr_preamble, base, tmp | ||
| 29 | movw \base, #(ICTRL_BASE & 0x0000ffff) | ||
| 30 | movt \base, #((ICTRL_BASE & 0xffff0000) >> 16) | ||
| 31 | .endm | ||
| 32 | |||
| 33 | .macro arch_ret_to_user, tmp1, tmp2 | ||
| 34 | .endm | ||
| 35 | |||
| 36 | /* | ||
| 37 | * The interrupt numbering scheme is defined in the | ||
| 38 | * interrupt controller spec. To wit: | ||
| 39 | * | ||
| 40 | * Interrupts 0-15 are IPI | ||
| 41 | * 16-28 are reserved | ||
| 42 | * 29-31 are local. We allow 30 to be used for the watchdog. | ||
| 43 | * 32-1020 are global | ||
| 44 | * 1021-1022 are reserved | ||
| 45 | * 1023 is "spurious" (no interrupt) | ||
| 46 | * | ||
| 47 | * For now, we ignore all local interrupts so only return an interrupt | ||
| 48 | * if it's between 30 and 1020. The test_for_ipi routine below will | ||
| 49 | * pick up on IPIs. | ||
| 50 | * | ||
| 51 | * A simple read from the controller will tell us the number of the | ||
| 52 | * highest priority enabled interrupt. We then just need to check | ||
| 53 | * whether it is in the valid range for an IRQ (30-1020 inclusive). | ||
| 54 | */ | ||
| 55 | |||
| 56 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
| 57 | |||
| 58 | /* bits 12-10 = src CPU, 9-0 = int # */ | ||
| 59 | ldr \irqstat, [\base, #GIC_CPU_INTACK] | ||
| 60 | |||
| 61 | ldr \tmp, =1021 | ||
| 62 | |||
| 63 | bic \irqnr, \irqstat, #0x1c00 | ||
| 64 | |||
| 65 | cmp \irqnr, #29 | ||
| 66 | cmpcc \irqnr, \irqnr | ||
| 67 | cmpne \irqnr, \tmp | ||
| 68 | cmpcs \irqnr, \irqnr | ||
| 69 | |||
| 70 | .endm | ||
| 71 | |||
| 72 | /* We assume that irqstat (the raw value of the IRQ acknowledge | ||
| 73 | * register) is preserved from the macro above. | ||
| 74 | * If there is an IPI, we immediately signal end of interrupt on the | ||
| 75 | * controller, since this requires the original irqstat value which | ||
| 76 | * we won't easily be able to recreate later. | ||
| 77 | */ | ||
| 78 | |||
| 79 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
| 80 | bic \irqnr, \irqstat, #0x1c00 | ||
| 81 | cmp \irqnr, #16 | ||
| 82 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
| 83 | cmpcs \irqnr, \irqnr | ||
| 84 | .endm | ||
| 85 | |||
| 86 | /* As above, this assumes that irqstat and base are preserved.. */ | ||
| 87 | |||
| 88 | .macro test_for_ltirq, irqnr, irqstat, base, tmp | ||
| 89 | bic \irqnr, \irqstat, #0x1c00 | ||
| 90 | mov \tmp, #0 | ||
| 91 | cmp \irqnr, #29 | ||
| 92 | moveq \tmp, #1 | ||
| 93 | streq \irqstat, [\base, #GIC_CPU_EOI] | ||
| 94 | cmp \tmp, #0 | ||
| 95 | .endm | ||
| 96 | |||
| 97 | #else | ||
| 98 | /* legacy interrupt controller for AP16 */ | ||
| 99 | .macro disable_fiq | ||
| 100 | .endm | ||
| 101 | |||
| 102 | .macro get_irqnr_preamble, base, tmp | ||
| 103 | @ enable imprecise aborts | ||
| 104 | cpsie a | ||
| 105 | @ EVP base at 0xf010f000 | ||
| 106 | mov \base, #0xf0000000 | ||
| 107 | orr \base, #0x00100000 | ||
| 108 | orr \base, #0x0000f000 | ||
| 109 | .endm | ||
| 110 | |||
| 111 | .macro arch_ret_to_user, tmp1, tmp2 | ||
| 112 | .endm | ||
| 113 | |||
| 114 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
| 115 | ldr \irqnr, [\base, #0x20] @ EVT_IRQ_STS | ||
| 116 | cmp \irqnr, #0x80 | ||
| 117 | .endm | ||
| 118 | #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 index 000000000000..540e822e50f7 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/gpio.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/gpio.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Erik Gilling <konkers@google.com> | ||
| 8 | * | ||
| 9 | * This software is licensed under the terms of the GNU General Public | ||
| 10 | * License version 2, as published by the Free Software Foundation, and | ||
| 11 | * may be copied, distributed, and modified under those terms. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef __MACH_TEGRA_GPIO_H | ||
| 21 | #define __MACH_TEGRA_GPIO_H | ||
| 22 | |||
| 23 | #include <mach/irqs.h> | ||
| 24 | |||
| 25 | #define ARCH_NR_GPIOS INT_GPIO_NR | ||
| 26 | |||
| 27 | #include <asm-generic/gpio.h> | ||
| 28 | |||
| 29 | #define gpio_get_value __gpio_get_value | ||
| 30 | #define gpio_set_value __gpio_set_value | ||
| 31 | #define gpio_cansleep __gpio_cansleep | ||
| 32 | |||
| 33 | #define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio)) | ||
| 34 | #define TEGRA_IRQ_TO_GPIO(irq) ((gpio) - INT_GPIO_BASE) | ||
| 35 | |||
| 36 | static inline int gpio_to_irq(unsigned int gpio) | ||
| 37 | { | ||
| 38 | if (gpio < ARCH_NR_GPIOS) | ||
| 39 | return INT_GPIO_BASE + gpio; | ||
| 40 | return -EINVAL; | ||
| 41 | } | ||
| 42 | |||
| 43 | static inline int irq_to_gpio(unsigned int irq) | ||
| 44 | { | ||
| 45 | if ((irq >= INT_GPIO_BASE) && (irq < INT_GPIO_BASE + INT_GPIO_NR)) | ||
| 46 | return irq - INT_GPIO_BASE; | ||
| 47 | return -EINVAL; | ||
| 48 | } | ||
| 49 | |||
| 50 | void tegra_gpio_enable(int gpio); | ||
| 51 | void tegra_gpio_disable(int gpio); | ||
| 52 | |||
| 53 | #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 index 000000000000..6014edf60d93 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/hardware.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/hardware.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __MACH_TEGRA_HARDWARE_H | ||
| 22 | #define __MACH_TEGRA_HARDWARE_H | ||
| 23 | |||
| 24 | #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 index 000000000000..35edfc32ffc9 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/io.h | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/io.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __MACH_TEGRA_IO_H | ||
| 22 | #define __MACH_TEGRA_IO_H | ||
| 23 | |||
| 24 | #define IO_SPACE_LIMIT 0xffffffff | ||
| 25 | |||
| 26 | /* On TEGRA, many peripherals are very closely packed in | ||
| 27 | * two 256MB io windows (that actually only use about 64KB | ||
| 28 | * at the start of each). | ||
| 29 | * | ||
| 30 | * We will just map the first 1MB of each window (to minimize | ||
| 31 | * pt entries needed) and provide a macro to transform physical | ||
| 32 | * io addresses to an appropriate void __iomem *. | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | #define IO_CPU_PHYS 0x50040000 | ||
| 37 | #define IO_CPU_VIRT 0xFE000000 | ||
| 38 | #define IO_CPU_SIZE SZ_16K | ||
| 39 | |||
| 40 | #define IO_PPSB_PHYS 0x60000000 | ||
| 41 | #define IO_PPSB_VIRT 0xFE200000 | ||
| 42 | #define IO_PPSB_SIZE SZ_1M | ||
| 43 | |||
| 44 | #define IO_APB_PHYS 0x70000000 | ||
| 45 | #define IO_APB_VIRT 0xFE300000 | ||
| 46 | #define IO_APB_SIZE SZ_1M | ||
| 47 | |||
| 48 | #define IO_TO_VIRT_BETWEEN(p, st, sz) ((p) >= (st) && (p) < ((st) + (sz))) | ||
| 49 | #define IO_TO_VIRT_XLATE(p, pst, vst) (((p) - (pst) + (vst))) | ||
| 50 | |||
| 51 | #define IO_TO_VIRT(n) ( \ | ||
| 52 | IO_TO_VIRT_BETWEEN((n), IO_PPSB_PHYS, IO_PPSB_SIZE) ? \ | ||
| 53 | IO_TO_VIRT_XLATE((n), IO_PPSB_PHYS, IO_PPSB_VIRT) : \ | ||
| 54 | IO_TO_VIRT_BETWEEN((n), IO_APB_PHYS, IO_APB_SIZE) ? \ | ||
| 55 | IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) : \ | ||
| 56 | IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ? \ | ||
| 57 | IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) : \ | ||
| 58 | 0) | ||
| 59 | |||
| 60 | #ifndef __ASSEMBLER__ | ||
| 61 | |||
| 62 | #define __arch_ioremap(p, s, t) tegra_ioremap(p, s, t) | ||
| 63 | #define __arch_iounmap(v) tegra_iounmap(v) | ||
| 64 | |||
| 65 | void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type); | ||
| 66 | void tegra_iounmap(volatile void __iomem *addr); | ||
| 67 | |||
| 68 | #define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n)) | ||
| 69 | |||
| 70 | static inline void __iomem *__io(unsigned long addr) | ||
| 71 | { | ||
| 72 | return (void __iomem *)addr; | ||
| 73 | } | ||
| 74 | #define __io(a) __io(a) | ||
| 75 | #define __mem_pci(a) (a) | ||
| 76 | |||
| 77 | #endif | ||
| 78 | |||
| 79 | #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 index 000000000000..1741f7dd7a9b --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/iomap.h | |||
| @@ -0,0 +1,203 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/iomap.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __MACH_TEGRA_IOMAP_H | ||
| 22 | #define __MACH_TEGRA_IOMAP_H | ||
| 23 | |||
| 24 | #include <asm/sizes.h> | ||
| 25 | |||
| 26 | #define TEGRA_ARM_PERIF_BASE 0x50040000 | ||
| 27 | #define TEGRA_ARM_PERIF_SIZE SZ_8K | ||
| 28 | |||
| 29 | #define TEGRA_ARM_INT_DIST_BASE 0x50041000 | ||
| 30 | #define TEGRA_ARM_INT_DIST_SIZE SZ_4K | ||
| 31 | |||
| 32 | #define TEGRA_DISPLAY_BASE 0x54200000 | ||
| 33 | #define TEGRA_DISPLAY_SIZE SZ_256K | ||
| 34 | |||
| 35 | #define TEGRA_DISPLAY2_BASE 0x54240000 | ||
| 36 | #define TEGRA_DISPLAY2_SIZE SZ_256K | ||
| 37 | |||
| 38 | #define TEGRA_PRIMARY_ICTLR_BASE 0x60004000 | ||
| 39 | #define TEGRA_PRIMARY_ICTLR_SIZE SZ_64 | ||
| 40 | |||
| 41 | #define TEGRA_SECONDARY_ICTLR_BASE 0x60004100 | ||
| 42 | #define TEGRA_SECONDARY_ICTLR_SIZE SZ_64 | ||
| 43 | |||
| 44 | #define TEGRA_TERTIARY_ICTLR_BASE 0x60004200 | ||
| 45 | #define TEGRA_TERTIARY_ICTLR_SIZE SZ_64 | ||
| 46 | |||
| 47 | #define TEGRA_QUATERNARY_ICTLR_BASE 0x60004300 | ||
| 48 | #define TEGRA_QUATERNARY_ICTLR_SIZE SZ_64 | ||
| 49 | |||
| 50 | #define TEGRA_TMR1_BASE 0x60005000 | ||
| 51 | #define TEGRA_TMR1_SIZE SZ_8 | ||
| 52 | |||
| 53 | #define TEGRA_TMR2_BASE 0x60005008 | ||
| 54 | #define TEGRA_TMR2_SIZE SZ_8 | ||
| 55 | |||
| 56 | #define TEGRA_TMRUS_BASE 0x60005010 | ||
| 57 | #define TEGRA_TMRUS_SIZE SZ_64 | ||
| 58 | |||
| 59 | #define TEGRA_TMR3_BASE 0x60005050 | ||
| 60 | #define TEGRA_TMR3_SIZE SZ_8 | ||
| 61 | |||
| 62 | #define TEGRA_TMR4_BASE 0x60005058 | ||
| 63 | #define TEGRA_TMR4_SIZE SZ_8 | ||
| 64 | |||
| 65 | #define TEGRA_CLK_RESET_BASE 0x60006000 | ||
| 66 | #define TEGRA_CLK_RESET_SIZE SZ_4K | ||
| 67 | |||
| 68 | #define TEGRA_FLOW_CTRL_BASE 0x60007000 | ||
| 69 | #define TEGRA_FLOW_CTRL_SIZE 20 | ||
| 70 | |||
| 71 | #define TEGRA_STATMON_BASE 0x6000C4000 | ||
| 72 | #define TEGRA_STATMON_SIZE SZ_1K | ||
| 73 | |||
| 74 | #define TEGRA_GPIO_BASE 0x6000D000 | ||
| 75 | #define TEGRA_GPIO_SIZE SZ_4K | ||
| 76 | |||
| 77 | #define TEGRA_EXCEPTION_VECTORS_BASE 0x6000F000 | ||
| 78 | #define TEGRA_EXCEPTION_VECTORS_SIZE SZ_4K | ||
| 79 | |||
| 80 | #define TEGRA_APB_MISC_BASE 0x70000000 | ||
| 81 | #define TEGRA_APB_MISC_SIZE SZ_4K | ||
| 82 | |||
| 83 | #define TEGRA_AC97_BASE 0x70002000 | ||
| 84 | #define TEGRA_AC97_SIZE SZ_512 | ||
| 85 | |||
| 86 | #define TEGRA_SPDIF_BASE 0x70002400 | ||
| 87 | #define TEGRA_SPDIF_SIZE SZ_512 | ||
| 88 | |||
| 89 | #define TEGRA_I2S1_BASE 0x70002800 | ||
| 90 | #define TEGRA_I2S1_SIZE SZ_256 | ||
| 91 | |||
| 92 | #define TEGRA_I2S2_BASE 0x70002A00 | ||
| 93 | #define TEGRA_I2S2_SIZE SZ_256 | ||
| 94 | |||
| 95 | #define TEGRA_UARTA_BASE 0x70006000 | ||
| 96 | #define TEGRA_UARTA_SIZE SZ_64 | ||
| 97 | |||
| 98 | #define TEGRA_UARTB_BASE 0x70006040 | ||
| 99 | #define TEGRA_UARTB_SIZE SZ_64 | ||
| 100 | |||
| 101 | #define TEGRA_UARTC_BASE 0x70006200 | ||
| 102 | #define TEGRA_UARTC_SIZE SZ_256 | ||
| 103 | |||
| 104 | #define TEGRA_UARTD_BASE 0x70006300 | ||
| 105 | #define TEGRA_UARTD_SIZE SZ_256 | ||
| 106 | |||
| 107 | #define TEGRA_UARTE_BASE 0x70006400 | ||
| 108 | #define TEGRA_UARTE_SIZE SZ_256 | ||
| 109 | |||
| 110 | #define TEGRA_NAND_BASE 0x70008000 | ||
| 111 | #define TEGRA_NAND_SIZE SZ_256 | ||
| 112 | |||
| 113 | #define TEGRA_HSMMC_BASE 0x70008500 | ||
| 114 | #define TEGRA_HSMMC_SIZE SZ_256 | ||
| 115 | |||
| 116 | #define TEGRA_SNOR_BASE 0x70009000 | ||
| 117 | #define TEGRA_SNOR_SIZE SZ_4K | ||
| 118 | |||
| 119 | #define TEGRA_PWFM_BASE 0x7000A000 | ||
| 120 | #define TEGRA_PWFM_SIZE SZ_256 | ||
| 121 | |||
| 122 | #define TEGRA_MIPI_BASE 0x7000B000 | ||
| 123 | #define TEGRA_MIPI_SIZE SZ_256 | ||
| 124 | |||
| 125 | #define TEGRA_I2C_BASE 0x7000C000 | ||
| 126 | #define TEGRA_I2C_SIZE SZ_256 | ||
| 127 | |||
| 128 | #define TEGRA_TWC_BASE 0x7000C100 | ||
| 129 | #define TEGRA_TWC_SIZE SZ_256 | ||
| 130 | |||
| 131 | #define TEGRA_SPI_BASE 0x7000C380 | ||
| 132 | #define TEGRA_SPI_SIZE 48 | ||
| 133 | |||
| 134 | #define TEGRA_I2C2_BASE 0x7000C400 | ||
| 135 | #define TEGRA_I2C2_SIZE SZ_256 | ||
| 136 | |||
| 137 | #define TEGRA_I2C3_BASE 0x7000C500 | ||
| 138 | #define TEGRA_I2C3_SIZE SZ_256 | ||
| 139 | |||
| 140 | #define TEGRA_OWR_BASE 0x7000D000 | ||
| 141 | #define TEGRA_OWR_SIZE 80 | ||
| 142 | |||
| 143 | #define TEGRA_DVC_BASE 0x7000D000 | ||
| 144 | #define TEGRA_DVC_SIZE SZ_512 | ||
| 145 | |||
| 146 | #define TEGRA_SPI1_BASE 0x7000D400 | ||
| 147 | #define TEGRA_SPI1_SIZE SZ_512 | ||
| 148 | |||
| 149 | #define TEGRA_SPI2_BASE 0x7000D600 | ||
| 150 | #define TEGRA_SPI2_SIZE SZ_512 | ||
| 151 | |||
| 152 | #define TEGRA_SPI3_BASE 0x7000D800 | ||
| 153 | #define TEGRA_SPI3_SIZE SZ_512 | ||
| 154 | |||
| 155 | #define TEGRA_SPI4_BASE 0x7000DA00 | ||
| 156 | #define TEGRA_SPI4_SIZE SZ_512 | ||
| 157 | |||
| 158 | #define TEGRA_RTC_BASE 0x7000E000 | ||
| 159 | #define TEGRA_RTC_SIZE SZ_256 | ||
| 160 | |||
| 161 | #define TEGRA_KBC_BASE 0x7000E200 | ||
| 162 | #define TEGRA_KBC_SIZE SZ_256 | ||
| 163 | |||
| 164 | #define TEGRA_PMC_BASE 0x7000E400 | ||
| 165 | #define TEGRA_PMC_SIZE SZ_256 | ||
| 166 | |||
| 167 | #define TEGRA_MC_BASE 0x7000F000 | ||
| 168 | #define TEGRA_MC_SIZE SZ_1K | ||
| 169 | |||
| 170 | #define TEGRA_EMC_BASE 0x7000F400 | ||
| 171 | #define TEGRA_EMC_SIZE SZ_1K | ||
| 172 | |||
| 173 | #define TEGRA_FUSE_BASE 0x7000F800 | ||
| 174 | #define TEGRA_FUSE_SIZE SZ_1K | ||
| 175 | |||
| 176 | #define TEGRA_KFUSE_BASE 0x7000FC00 | ||
| 177 | #define TEGRA_KFUSE_SIZE SZ_1K | ||
| 178 | |||
| 179 | #define TEGRA_CSITE_BASE 0x70040000 | ||
| 180 | #define TEGRA_CSITE_SIZE SZ_256K | ||
| 181 | |||
| 182 | #define TEGRA_USB_BASE 0xC5000000 | ||
| 183 | #define TEGRA_USB_SIZE SZ_16K | ||
| 184 | |||
| 185 | #define TEGRA_USB1_BASE 0xC5004000 | ||
| 186 | #define TEGRA_USB1_SIZE SZ_16K | ||
| 187 | |||
| 188 | #define TEGRA_USB2_BASE 0xC5008000 | ||
| 189 | #define TEGRA_USB2_SIZE SZ_16K | ||
| 190 | |||
| 191 | #define TEGRA_SDMMC1_BASE 0xC8000000 | ||
| 192 | #define TEGRA_SDMMC1_SIZE SZ_512 | ||
| 193 | |||
| 194 | #define TEGRA_SDMMC2_BASE 0xC8000200 | ||
| 195 | #define TEGRA_SDMMC2_SIZE SZ_512 | ||
| 196 | |||
| 197 | #define TEGRA_SDMMC3_BASE 0xC8000400 | ||
| 198 | #define TEGRA_SDMMC3_SIZE SZ_512 | ||
| 199 | |||
| 200 | #define TEGRA_SDMMC4_BASE 0xC8000600 | ||
| 201 | #define TEGRA_SDMMC4_SIZE SZ_512 | ||
| 202 | |||
| 203 | #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 index 000000000000..20f640edaa0d --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/irqs.h | |||
| @@ -0,0 +1,173 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/irqs.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __MACH_TEGRA_IRQS_H | ||
| 22 | #define __MACH_TEGRA_IRQS_H | ||
| 23 | |||
| 24 | #define INT_GIC_BASE 0 | ||
| 25 | |||
| 26 | #define IRQ_LOCALTIMER 29 | ||
| 27 | |||
| 28 | /* Primary Interrupt Controller */ | ||
| 29 | #define INT_PRI_BASE (INT_GIC_BASE + 32) | ||
| 30 | #define INT_TMR1 (INT_PRI_BASE + 0) | ||
| 31 | #define INT_TMR2 (INT_PRI_BASE + 1) | ||
| 32 | #define INT_RTC (INT_PRI_BASE + 2) | ||
| 33 | #define INT_I2S2 (INT_PRI_BASE + 3) | ||
| 34 | #define INT_SHR_SEM_INBOX_IBF (INT_PRI_BASE + 4) | ||
| 35 | #define INT_SHR_SEM_INBOX_IBE (INT_PRI_BASE + 5) | ||
| 36 | #define INT_SHR_SEM_OUTBOX_IBF (INT_PRI_BASE + 6) | ||
| 37 | #define INT_SHR_SEM_OUTBOX_IBE (INT_PRI_BASE + 7) | ||
| 38 | #define INT_VDE_UCQ_ERROR (INT_PRI_BASE + 8) | ||
| 39 | #define INT_VDE_SYNC_TOKEN (INT_PRI_BASE + 9) | ||
| 40 | #define INT_VDE_BSE_V (INT_PRI_BASE + 10) | ||
| 41 | #define INT_VDE_BSE_A (INT_PRI_BASE + 11) | ||
| 42 | #define INT_VDE_SXE (INT_PRI_BASE + 12) | ||
| 43 | #define INT_I2S1 (INT_PRI_BASE + 13) | ||
| 44 | #define INT_SDMMC1 (INT_PRI_BASE + 14) | ||
| 45 | #define INT_SDMMC2 (INT_PRI_BASE + 15) | ||
| 46 | #define INT_XIO (INT_PRI_BASE + 16) | ||
| 47 | #define INT_VDE (INT_PRI_BASE + 17) | ||
| 48 | #define INT_AVP_UCQ (INT_PRI_BASE + 18) | ||
| 49 | #define INT_SDMMC3 (INT_PRI_BASE + 19) | ||
| 50 | #define INT_USB (INT_PRI_BASE + 20) | ||
| 51 | #define INT_USB2 (INT_PRI_BASE + 21) | ||
| 52 | #define INT_PRI_RES_22 (INT_PRI_BASE + 22) | ||
| 53 | #define INT_EIDE (INT_PRI_BASE + 23) | ||
| 54 | #define INT_NANDFLASH (INT_PRI_BASE + 24) | ||
| 55 | #define INT_VCP (INT_PRI_BASE + 25) | ||
| 56 | #define INT_APB_DMA (INT_PRI_BASE + 26) | ||
| 57 | #define INT_AHB_DMA (INT_PRI_BASE + 27) | ||
| 58 | #define INT_GNT_0 (INT_PRI_BASE + 28) | ||
| 59 | #define INT_GNT_1 (INT_PRI_BASE + 29) | ||
| 60 | #define INT_OWR (INT_PRI_BASE + 30) | ||
| 61 | #define INT_SDMMC4 (INT_PRI_BASE + 31) | ||
| 62 | |||
| 63 | /* Secondary Interrupt Controller */ | ||
| 64 | #define INT_SEC_BASE (INT_PRI_BASE + 32) | ||
| 65 | #define INT_GPIO1 (INT_SEC_BASE + 0) | ||
| 66 | #define INT_GPIO2 (INT_SEC_BASE + 1) | ||
| 67 | #define INT_GPIO3 (INT_SEC_BASE + 2) | ||
| 68 | #define INT_GPIO4 (INT_SEC_BASE + 3) | ||
| 69 | #define INT_UARTA (INT_SEC_BASE + 4) | ||
| 70 | #define INT_UARTB (INT_SEC_BASE + 5) | ||
| 71 | #define INT_I2C (INT_SEC_BASE + 6) | ||
| 72 | #define INT_SPI (INT_SEC_BASE + 7) | ||
| 73 | #define INT_TWC (INT_SEC_BASE + 8) | ||
| 74 | #define INT_TMR3 (INT_SEC_BASE + 9) | ||
| 75 | #define INT_TMR4 (INT_SEC_BASE + 10) | ||
| 76 | #define INT_FLOW_RSM0 (INT_SEC_BASE + 11) | ||
| 77 | #define INT_FLOW_RSM1 (INT_SEC_BASE + 12) | ||
| 78 | #define INT_SPDIF (INT_SEC_BASE + 13) | ||
| 79 | #define INT_UARTC (INT_SEC_BASE + 14) | ||
| 80 | #define INT_MIPI (INT_SEC_BASE + 15) | ||
| 81 | #define INT_EVENTA (INT_SEC_BASE + 16) | ||
| 82 | #define INT_EVENTB (INT_SEC_BASE + 17) | ||
| 83 | #define INT_EVENTC (INT_SEC_BASE + 18) | ||
| 84 | #define INT_EVENTD (INT_SEC_BASE + 19) | ||
| 85 | #define INT_VFIR (INT_SEC_BASE + 20) | ||
| 86 | #define INT_DVC (INT_SEC_BASE + 21) | ||
| 87 | #define INT_SYS_STATS_MON (INT_SEC_BASE + 22) | ||
| 88 | #define INT_GPIO5 (INT_SEC_BASE + 23) | ||
| 89 | #define INT_CPU0_PMU_INTR (INT_SEC_BASE + 24) | ||
| 90 | #define INT_CPU2_PMU_INTR (INT_SEC_BASE + 25) | ||
| 91 | #define INT_SEC_RES_26 (INT_SEC_BASE + 26) | ||
| 92 | #define INT_S_LINK1 (INT_SEC_BASE + 27) | ||
| 93 | #define INT_APB_DMA_COP (INT_SEC_BASE + 28) | ||
| 94 | #define INT_AHB_DMA_COP (INT_SEC_BASE + 29) | ||
| 95 | #define INT_DMA_TX (INT_SEC_BASE + 30) | ||
| 96 | #define INT_DMA_RX (INT_SEC_BASE + 31) | ||
| 97 | |||
| 98 | /* Tertiary Interrupt Controller */ | ||
| 99 | #define INT_TRI_BASE (INT_SEC_BASE + 32) | ||
| 100 | #define INT_HOST1X_COP_SYNCPT (INT_TRI_BASE + 0) | ||
| 101 | #define INT_HOST1X_MPCORE_SYNCPT (INT_TRI_BASE + 1) | ||
| 102 | #define INT_HOST1X_COP_GENERAL (INT_TRI_BASE + 2) | ||
| 103 | #define INT_HOST1X_MPCORE_GENERAL (INT_TRI_BASE + 3) | ||
| 104 | #define INT_MPE_GENERAL (INT_TRI_BASE + 4) | ||
| 105 | #define INT_VI_GENERAL (INT_TRI_BASE + 5) | ||
| 106 | #define INT_EPP_GENERAL (INT_TRI_BASE + 6) | ||
| 107 | #define INT_ISP_GENERAL (INT_TRI_BASE + 7) | ||
| 108 | #define INT_2D_GENERAL (INT_TRI_BASE + 8) | ||
| 109 | #define INT_DISPLAY_GENERAL (INT_TRI_BASE + 9) | ||
| 110 | #define INT_DISPLAY_B_GENERAL (INT_TRI_BASE + 10) | ||
| 111 | #define INT_HDMI (INT_TRI_BASE + 11) | ||
| 112 | #define INT_TVO_GENERAL (INT_TRI_BASE + 12) | ||
| 113 | #define INT_MC_GENERAL (INT_TRI_BASE + 13) | ||
| 114 | #define INT_EMC_GENERAL (INT_TRI_BASE + 14) | ||
| 115 | #define INT_TRI_RES_15 (INT_TRI_BASE + 15) | ||
| 116 | #define INT_TRI_RES_16 (INT_TRI_BASE + 16) | ||
| 117 | #define INT_AC97 (INT_TRI_BASE + 17) | ||
| 118 | #define INT_SPI_2 (INT_TRI_BASE + 18) | ||
| 119 | #define INT_SPI_3 (INT_TRI_BASE + 19) | ||
| 120 | #define INT_I2C2 (INT_TRI_BASE + 20) | ||
| 121 | #define INT_KBC (INT_TRI_BASE + 21) | ||
| 122 | #define INT_EXTERNAL_PMU (INT_TRI_BASE + 22) | ||
| 123 | #define INT_GPIO6 (INT_TRI_BASE + 23) | ||
| 124 | #define INT_TVDAC (INT_TRI_BASE + 24) | ||
| 125 | #define INT_GPIO7 (INT_TRI_BASE + 25) | ||
| 126 | #define INT_UARTD (INT_TRI_BASE + 26) | ||
| 127 | #define INT_UARTE (INT_TRI_BASE + 27) | ||
| 128 | #define INT_I2C3 (INT_TRI_BASE + 28) | ||
| 129 | #define INT_SPI_4 (INT_TRI_BASE + 29) | ||
| 130 | #define INT_TRI_RES_30 (INT_TRI_BASE + 30) | ||
| 131 | #define INT_SW_RESERVED (INT_TRI_BASE + 31) | ||
| 132 | |||
| 133 | /* Quaternary Interrupt Controller */ | ||
| 134 | #define INT_QUAD_BASE (INT_TRI_BASE + 32) | ||
| 135 | #define INT_SNOR (INT_QUAD_BASE + 0) | ||
| 136 | #define INT_USB3 (INT_QUAD_BASE + 1) | ||
| 137 | #define INT_PCIE_INTR (INT_QUAD_BASE + 2) | ||
| 138 | #define INT_PCIE_MSI (INT_QUAD_BASE + 3) | ||
| 139 | #define INT_QUAD_RES_4 (INT_QUAD_BASE + 4) | ||
| 140 | #define INT_QUAD_RES_5 (INT_QUAD_BASE + 5) | ||
| 141 | #define INT_QUAD_RES_6 (INT_QUAD_BASE + 6) | ||
| 142 | #define INT_QUAD_RES_7 (INT_QUAD_BASE + 7) | ||
| 143 | #define INT_APB_DMA_CH0 (INT_QUAD_BASE + 8) | ||
| 144 | #define INT_APB_DMA_CH1 (INT_QUAD_BASE + 9) | ||
| 145 | #define INT_APB_DMA_CH2 (INT_QUAD_BASE + 10) | ||
| 146 | #define INT_APB_DMA_CH3 (INT_QUAD_BASE + 11) | ||
| 147 | #define INT_APB_DMA_CH4 (INT_QUAD_BASE + 12) | ||
| 148 | #define INT_APB_DMA_CH5 (INT_QUAD_BASE + 13) | ||
| 149 | #define INT_APB_DMA_CH6 (INT_QUAD_BASE + 14) | ||
| 150 | #define INT_APB_DMA_CH7 (INT_QUAD_BASE + 15) | ||
| 151 | #define INT_APB_DMA_CH8 (INT_QUAD_BASE + 16) | ||
| 152 | #define INT_APB_DMA_CH9 (INT_QUAD_BASE + 17) | ||
| 153 | #define INT_APB_DMA_CH10 (INT_QUAD_BASE + 18) | ||
| 154 | #define INT_APB_DMA_CH11 (INT_QUAD_BASE + 19) | ||
| 155 | #define INT_APB_DMA_CH12 (INT_QUAD_BASE + 20) | ||
| 156 | #define INT_APB_DMA_CH13 (INT_QUAD_BASE + 21) | ||
| 157 | #define INT_APB_DMA_CH14 (INT_QUAD_BASE + 22) | ||
| 158 | #define INT_APB_DMA_CH15 (INT_QUAD_BASE + 23) | ||
| 159 | #define INT_QUAD_RES_24 (INT_QUAD_BASE + 24) | ||
| 160 | #define INT_QUAD_RES_25 (INT_QUAD_BASE + 25) | ||
| 161 | #define INT_QUAD_RES_26 (INT_QUAD_BASE + 26) | ||
| 162 | #define INT_QUAD_RES_27 (INT_QUAD_BASE + 27) | ||
| 163 | #define INT_QUAD_RES_28 (INT_QUAD_BASE + 28) | ||
| 164 | #define INT_QUAD_RES_29 (INT_QUAD_BASE + 29) | ||
| 165 | #define INT_QUAD_RES_30 (INT_QUAD_BASE + 30) | ||
| 166 | #define INT_QUAD_RES_31 (INT_QUAD_BASE + 31) | ||
| 167 | |||
| 168 | #define INT_GPIO_BASE (INT_QUAD_BASE + 32) | ||
| 169 | #define INT_GPIO_NR (28 * 8) | ||
| 170 | |||
| 171 | #define NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR) | ||
| 172 | |||
| 173 | #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 index 000000000000..6151bab62af2 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/memory.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/memory.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __MACH_TEGRA_MEMORY_H | ||
| 22 | #define __MACH_TEGRA_MEMORY_H | ||
| 23 | |||
| 24 | /* physical offset of RAM */ | ||
| 25 | #define PHYS_OFFSET UL(0) | ||
| 26 | |||
| 27 | #endif | ||
| 28 | |||
diff --git a/arch/arm/mach-tegra/include/mach/pinmux.h b/arch/arm/mach-tegra/include/mach/pinmux.h new file mode 100644 index 000000000000..41c8ce5b7c27 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/pinmux.h | |||
| @@ -0,0 +1,348 @@ | |||
| 1 | /* | ||
| 2 | * linux/arch/arm/mach-tegra/include/mach/pinmux.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * This software is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2, as published by the Free Software Foundation, and | ||
| 8 | * may be copied, distributed, and modified under those terms. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef __MACH_TEGRA_PINMUX_H | ||
| 18 | #define __MACH_TEGRA_PINMUX_H | ||
| 19 | |||
| 20 | enum tegra_pingroup { | ||
| 21 | TEGRA_PINGROUP_ATA = 0, | ||
| 22 | TEGRA_PINGROUP_ATB, | ||
| 23 | TEGRA_PINGROUP_ATC, | ||
| 24 | TEGRA_PINGROUP_ATD, | ||
| 25 | TEGRA_PINGROUP_ATE, | ||
| 26 | TEGRA_PINGROUP_CDEV1, | ||
| 27 | TEGRA_PINGROUP_CDEV2, | ||
| 28 | TEGRA_PINGROUP_CRTP, | ||
| 29 | TEGRA_PINGROUP_CSUS, | ||
| 30 | TEGRA_PINGROUP_DAP1, | ||
| 31 | TEGRA_PINGROUP_DAP2, | ||
| 32 | TEGRA_PINGROUP_DAP3, | ||
| 33 | TEGRA_PINGROUP_DAP4, | ||
| 34 | TEGRA_PINGROUP_DDC, | ||
| 35 | TEGRA_PINGROUP_DTA, | ||
| 36 | TEGRA_PINGROUP_DTB, | ||
| 37 | TEGRA_PINGROUP_DTC, | ||
| 38 | TEGRA_PINGROUP_DTD, | ||
| 39 | TEGRA_PINGROUP_DTE, | ||
| 40 | TEGRA_PINGROUP_DTF, | ||
| 41 | TEGRA_PINGROUP_GMA, | ||
| 42 | TEGRA_PINGROUP_GMB, | ||
| 43 | TEGRA_PINGROUP_GMC, | ||
| 44 | TEGRA_PINGROUP_GMD, | ||
| 45 | TEGRA_PINGROUP_GME, | ||
| 46 | TEGRA_PINGROUP_GPU, | ||
| 47 | TEGRA_PINGROUP_GPU7, | ||
| 48 | TEGRA_PINGROUP_GPV, | ||
| 49 | TEGRA_PINGROUP_HDINT, | ||
| 50 | TEGRA_PINGROUP_I2CP, | ||
| 51 | TEGRA_PINGROUP_IRRX, | ||
| 52 | TEGRA_PINGROUP_IRTX, | ||
| 53 | TEGRA_PINGROUP_KBCA, | ||
| 54 | TEGRA_PINGROUP_KBCB, | ||
| 55 | TEGRA_PINGROUP_KBCC, | ||
| 56 | TEGRA_PINGROUP_KBCD, | ||
| 57 | TEGRA_PINGROUP_KBCE, | ||
| 58 | TEGRA_PINGROUP_KBCF, | ||
| 59 | TEGRA_PINGROUP_LCSN, | ||
| 60 | TEGRA_PINGROUP_LD0, | ||
| 61 | TEGRA_PINGROUP_LD1, | ||
| 62 | TEGRA_PINGROUP_LD10, | ||
| 63 | TEGRA_PINGROUP_LD11, | ||
| 64 | TEGRA_PINGROUP_LD12, | ||
| 65 | TEGRA_PINGROUP_LD13, | ||
| 66 | TEGRA_PINGROUP_LD14, | ||
| 67 | TEGRA_PINGROUP_LD15, | ||
| 68 | TEGRA_PINGROUP_LD16, | ||
| 69 | TEGRA_PINGROUP_LD17, | ||
| 70 | TEGRA_PINGROUP_LD2, | ||
| 71 | TEGRA_PINGROUP_LD3, | ||
| 72 | TEGRA_PINGROUP_LD4, | ||
| 73 | TEGRA_PINGROUP_LD5, | ||
| 74 | TEGRA_PINGROUP_LD6, | ||
| 75 | TEGRA_PINGROUP_LD7, | ||
| 76 | TEGRA_PINGROUP_LD8, | ||
| 77 | TEGRA_PINGROUP_LD9, | ||
| 78 | TEGRA_PINGROUP_LDC, | ||
| 79 | TEGRA_PINGROUP_LDI, | ||
| 80 | TEGRA_PINGROUP_LHP0, | ||
| 81 | TEGRA_PINGROUP_LHP1, | ||
| 82 | TEGRA_PINGROUP_LHP2, | ||
| 83 | TEGRA_PINGROUP_LHS, | ||
| 84 | TEGRA_PINGROUP_LM0, | ||
| 85 | TEGRA_PINGROUP_LM1, | ||
| 86 | TEGRA_PINGROUP_LPP, | ||
| 87 | TEGRA_PINGROUP_LPW0, | ||
| 88 | TEGRA_PINGROUP_LPW1, | ||
| 89 | TEGRA_PINGROUP_LPW2, | ||
| 90 | TEGRA_PINGROUP_LSC0, | ||
| 91 | TEGRA_PINGROUP_LSC1, | ||
| 92 | TEGRA_PINGROUP_LSCK, | ||
| 93 | TEGRA_PINGROUP_LSDA, | ||
| 94 | TEGRA_PINGROUP_LSDI, | ||
| 95 | TEGRA_PINGROUP_LSPI, | ||
| 96 | TEGRA_PINGROUP_LVP0, | ||
| 97 | TEGRA_PINGROUP_LVP1, | ||
| 98 | TEGRA_PINGROUP_LVS, | ||
| 99 | TEGRA_PINGROUP_OWC, | ||
| 100 | TEGRA_PINGROUP_PMC, | ||
| 101 | TEGRA_PINGROUP_PTA, | ||
| 102 | TEGRA_PINGROUP_RM, | ||
| 103 | TEGRA_PINGROUP_SDB, | ||
| 104 | TEGRA_PINGROUP_SDC, | ||
| 105 | TEGRA_PINGROUP_SDD, | ||
| 106 | TEGRA_PINGROUP_SDIO1, | ||
| 107 | TEGRA_PINGROUP_SLXA, | ||
| 108 | TEGRA_PINGROUP_SLXC, | ||
| 109 | TEGRA_PINGROUP_SLXD, | ||
| 110 | TEGRA_PINGROUP_SLXK, | ||
| 111 | TEGRA_PINGROUP_SPDI, | ||
| 112 | TEGRA_PINGROUP_SPDO, | ||
| 113 | TEGRA_PINGROUP_SPIA, | ||
| 114 | TEGRA_PINGROUP_SPIB, | ||
| 115 | TEGRA_PINGROUP_SPIC, | ||
| 116 | TEGRA_PINGROUP_SPID, | ||
| 117 | TEGRA_PINGROUP_SPIE, | ||
| 118 | TEGRA_PINGROUP_SPIF, | ||
| 119 | TEGRA_PINGROUP_SPIG, | ||
| 120 | TEGRA_PINGROUP_SPIH, | ||
| 121 | TEGRA_PINGROUP_UAA, | ||
| 122 | TEGRA_PINGROUP_UAB, | ||
| 123 | TEGRA_PINGROUP_UAC, | ||
| 124 | TEGRA_PINGROUP_UAD, | ||
| 125 | TEGRA_PINGROUP_UCA, | ||
| 126 | TEGRA_PINGROUP_UCB, | ||
| 127 | TEGRA_PINGROUP_UDA, | ||
| 128 | /* these pin groups only have pullup and pull down control */ | ||
| 129 | TEGRA_PINGROUP_CK32, | ||
| 130 | TEGRA_PINGROUP_DDRC, | ||
| 131 | TEGRA_PINGROUP_PMCA, | ||
| 132 | TEGRA_PINGROUP_PMCB, | ||
| 133 | TEGRA_PINGROUP_PMCC, | ||
| 134 | TEGRA_PINGROUP_PMCD, | ||
| 135 | TEGRA_PINGROUP_PMCE, | ||
| 136 | TEGRA_PINGROUP_XM2C, | ||
| 137 | TEGRA_PINGROUP_XM2D, | ||
| 138 | TEGRA_MAX_PINGROUP, | ||
| 139 | }; | ||
| 140 | |||
| 141 | enum tegra_mux_func { | ||
| 142 | TEGRA_MUX_RSVD = 0x8000, | ||
| 143 | TEGRA_MUX_RSVD1 = 0x8000, | ||
| 144 | TEGRA_MUX_RSVD2 = 0x8001, | ||
| 145 | TEGRA_MUX_RSVD3 = 0x8002, | ||
| 146 | TEGRA_MUX_RSVD4 = 0x8003, | ||
| 147 | TEGRA_MUX_NONE = -1, | ||
| 148 | TEGRA_MUX_AHB_CLK, | ||
| 149 | TEGRA_MUX_APB_CLK, | ||
| 150 | TEGRA_MUX_AUDIO_SYNC, | ||
| 151 | TEGRA_MUX_CRT, | ||
| 152 | TEGRA_MUX_DAP1, | ||
| 153 | TEGRA_MUX_DAP2, | ||
| 154 | TEGRA_MUX_DAP3, | ||
| 155 | TEGRA_MUX_DAP4, | ||
| 156 | TEGRA_MUX_DAP5, | ||
| 157 | TEGRA_MUX_DISPLAYA, | ||
| 158 | TEGRA_MUX_DISPLAYB, | ||
| 159 | TEGRA_MUX_EMC_TEST0_DLL, | ||
| 160 | TEGRA_MUX_EMC_TEST1_DLL, | ||
| 161 | TEGRA_MUX_GMI, | ||
| 162 | TEGRA_MUX_GMI_INT, | ||
| 163 | TEGRA_MUX_HDMI, | ||
| 164 | TEGRA_MUX_I2C, | ||
| 165 | TEGRA_MUX_I2C2, | ||
| 166 | TEGRA_MUX_I2C3, | ||
| 167 | TEGRA_MUX_IDE, | ||
| 168 | TEGRA_MUX_IRDA, | ||
| 169 | TEGRA_MUX_KBC, | ||
| 170 | TEGRA_MUX_MIO, | ||
| 171 | TEGRA_MUX_MIPI_HS, | ||
| 172 | TEGRA_MUX_NAND, | ||
| 173 | TEGRA_MUX_OSC, | ||
| 174 | TEGRA_MUX_OWR, | ||
| 175 | TEGRA_MUX_PCIE, | ||
| 176 | TEGRA_MUX_PLLA_OUT, | ||
| 177 | TEGRA_MUX_PLLC_OUT1, | ||
| 178 | TEGRA_MUX_PLLM_OUT1, | ||
| 179 | TEGRA_MUX_PLLP_OUT2, | ||
| 180 | TEGRA_MUX_PLLP_OUT3, | ||
| 181 | TEGRA_MUX_PLLP_OUT4, | ||
| 182 | TEGRA_MUX_PWM, | ||
| 183 | TEGRA_MUX_PWR_INTR, | ||
| 184 | TEGRA_MUX_PWR_ON, | ||
| 185 | TEGRA_MUX_RTCK, | ||
| 186 | TEGRA_MUX_SDIO1, | ||
| 187 | TEGRA_MUX_SDIO2, | ||
| 188 | TEGRA_MUX_SDIO3, | ||
| 189 | TEGRA_MUX_SDIO4, | ||
| 190 | TEGRA_MUX_SFLASH, | ||
| 191 | TEGRA_MUX_SPDIF, | ||
| 192 | TEGRA_MUX_SPI1, | ||
| 193 | TEGRA_MUX_SPI2, | ||
| 194 | TEGRA_MUX_SPI2_ALT, | ||
| 195 | TEGRA_MUX_SPI3, | ||
| 196 | TEGRA_MUX_SPI4, | ||
| 197 | TEGRA_MUX_TRACE, | ||
| 198 | TEGRA_MUX_TWC, | ||
| 199 | TEGRA_MUX_UARTA, | ||
| 200 | TEGRA_MUX_UARTB, | ||
| 201 | TEGRA_MUX_UARTC, | ||
| 202 | TEGRA_MUX_UARTD, | ||
| 203 | TEGRA_MUX_UARTE, | ||
| 204 | TEGRA_MUX_ULPI, | ||
| 205 | TEGRA_MUX_VI, | ||
| 206 | TEGRA_MUX_VI_SENSOR_CLK, | ||
| 207 | TEGRA_MUX_XIO, | ||
| 208 | TEGRA_MAX_MUX, | ||
| 209 | }; | ||
| 210 | |||
| 211 | enum tegra_pullupdown { | ||
| 212 | TEGRA_PUPD_NORMAL = 0, | ||
| 213 | TEGRA_PUPD_PULL_DOWN, | ||
| 214 | TEGRA_PUPD_PULL_UP, | ||
| 215 | }; | ||
| 216 | |||
| 217 | enum tegra_tristate { | ||
| 218 | TEGRA_TRI_NORMAL = 0, | ||
| 219 | TEGRA_TRI_TRISTATE = 1, | ||
| 220 | }; | ||
| 221 | |||
| 222 | struct tegra_pingroup_config { | ||
| 223 | enum tegra_pingroup pingroup; | ||
| 224 | enum tegra_mux_func func; | ||
| 225 | enum tegra_pullupdown pupd; | ||
| 226 | enum tegra_tristate tristate; | ||
| 227 | }; | ||
| 228 | |||
| 229 | enum tegra_slew { | ||
| 230 | TEGRA_SLEW_FASTEST = 0, | ||
| 231 | TEGRA_SLEW_FAST, | ||
| 232 | TEGRA_SLEW_SLOW, | ||
| 233 | TEGRA_SLEW_SLOWEST, | ||
| 234 | TEGRA_MAX_SLEW, | ||
| 235 | }; | ||
| 236 | |||
| 237 | enum tegra_pull_strength { | ||
| 238 | TEGRA_PULL_0 = 0, | ||
| 239 | TEGRA_PULL_1, | ||
| 240 | TEGRA_PULL_2, | ||
| 241 | TEGRA_PULL_3, | ||
| 242 | TEGRA_PULL_4, | ||
| 243 | TEGRA_PULL_5, | ||
| 244 | TEGRA_PULL_6, | ||
| 245 | TEGRA_PULL_7, | ||
| 246 | TEGRA_PULL_8, | ||
| 247 | TEGRA_PULL_9, | ||
| 248 | TEGRA_PULL_10, | ||
| 249 | TEGRA_PULL_11, | ||
| 250 | TEGRA_PULL_12, | ||
| 251 | TEGRA_PULL_13, | ||
| 252 | TEGRA_PULL_14, | ||
| 253 | TEGRA_PULL_15, | ||
| 254 | TEGRA_PULL_16, | ||
| 255 | TEGRA_PULL_17, | ||
| 256 | TEGRA_PULL_18, | ||
| 257 | TEGRA_PULL_19, | ||
| 258 | TEGRA_PULL_20, | ||
| 259 | TEGRA_PULL_21, | ||
| 260 | TEGRA_PULL_22, | ||
| 261 | TEGRA_PULL_23, | ||
| 262 | TEGRA_PULL_24, | ||
| 263 | TEGRA_PULL_25, | ||
| 264 | TEGRA_PULL_26, | ||
| 265 | TEGRA_PULL_27, | ||
| 266 | TEGRA_PULL_28, | ||
| 267 | TEGRA_PULL_29, | ||
| 268 | TEGRA_PULL_30, | ||
| 269 | TEGRA_PULL_31, | ||
| 270 | TEGRA_MAX_PULL, | ||
| 271 | }; | ||
| 272 | |||
| 273 | enum tegra_drive_pingroup { | ||
| 274 | TEGRA_DRIVE_PINGROUP_AO1 = 0, | ||
| 275 | TEGRA_DRIVE_PINGROUP_AO2, | ||
| 276 | TEGRA_DRIVE_PINGROUP_AT1, | ||
| 277 | TEGRA_DRIVE_PINGROUP_AT2, | ||
| 278 | TEGRA_DRIVE_PINGROUP_CDEV1, | ||
| 279 | TEGRA_DRIVE_PINGROUP_CDEV2, | ||
| 280 | TEGRA_DRIVE_PINGROUP_CSUS, | ||
| 281 | TEGRA_DRIVE_PINGROUP_DAP1, | ||
| 282 | TEGRA_DRIVE_PINGROUP_DAP2, | ||
| 283 | TEGRA_DRIVE_PINGROUP_DAP3, | ||
| 284 | TEGRA_DRIVE_PINGROUP_DAP4, | ||
| 285 | TEGRA_DRIVE_PINGROUP_DBG, | ||
| 286 | TEGRA_DRIVE_PINGROUP_LCD1, | ||
| 287 | TEGRA_DRIVE_PINGROUP_LCD2, | ||
| 288 | TEGRA_DRIVE_PINGROUP_SDMMC2, | ||
| 289 | TEGRA_DRIVE_PINGROUP_SDMMC3, | ||
| 290 | TEGRA_DRIVE_PINGROUP_SPI, | ||
| 291 | TEGRA_DRIVE_PINGROUP_UAA, | ||
| 292 | TEGRA_DRIVE_PINGROUP_UAB, | ||
| 293 | TEGRA_DRIVE_PINGROUP_UART2, | ||
| 294 | TEGRA_DRIVE_PINGROUP_UART3, | ||
| 295 | TEGRA_DRIVE_PINGROUP_VI1, | ||
| 296 | TEGRA_DRIVE_PINGROUP_VI2, | ||
| 297 | TEGRA_DRIVE_PINGROUP_XM2A, | ||
| 298 | TEGRA_DRIVE_PINGROUP_XM2C, | ||
| 299 | TEGRA_DRIVE_PINGROUP_XM2D, | ||
| 300 | TEGRA_DRIVE_PINGROUP_XM2CLK, | ||
| 301 | TEGRA_DRIVE_PINGROUP_MEMCOMP, | ||
| 302 | TEGRA_MAX_DRIVE_PINGROUP, | ||
| 303 | }; | ||
| 304 | |||
| 305 | enum tegra_drive { | ||
| 306 | TEGRA_DRIVE_DIV_8 = 0, | ||
| 307 | TEGRA_DRIVE_DIV_4, | ||
| 308 | TEGRA_DRIVE_DIV_2, | ||
| 309 | TEGRA_DRIVE_DIV_1, | ||
| 310 | TEGRA_MAX_DRIVE, | ||
| 311 | }; | ||
| 312 | |||
| 313 | enum tegra_hsm { | ||
| 314 | TEGRA_HSM_DISABLE = 0, | ||
| 315 | TEGRA_HSM_ENABLE, | ||
| 316 | }; | ||
| 317 | |||
| 318 | enum tegra_schmitt { | ||
| 319 | TEGRA_SCHMITT_DISABLE = 0, | ||
| 320 | TEGRA_SCHMITT_ENABLE, | ||
| 321 | }; | ||
| 322 | |||
| 323 | struct tegra_drive_pingroup_config { | ||
| 324 | enum tegra_drive_pingroup pingroup; | ||
| 325 | enum tegra_hsm hsm; | ||
| 326 | enum tegra_schmitt schmitt; | ||
| 327 | enum tegra_drive drive; | ||
| 328 | enum tegra_pull_strength pull_down; | ||
| 329 | enum tegra_pull_strength pull_up; | ||
| 330 | enum tegra_slew slew_rising; | ||
| 331 | enum tegra_slew slew_falling; | ||
| 332 | }; | ||
| 333 | |||
| 334 | int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func); | ||
| 335 | int tegra_pinmux_set_tristate(enum tegra_pingroup pg, enum tegra_tristate tristate); | ||
| 336 | int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, enum tegra_pullupdown pupd); | ||
| 337 | |||
| 338 | void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup, | ||
| 339 | enum tegra_mux_func func, enum tegra_pullupdown pupd, | ||
| 340 | enum tegra_tristate tristate); | ||
| 341 | |||
| 342 | void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len); | ||
| 343 | |||
| 344 | void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config, | ||
| 345 | int len); | ||
| 346 | |||
| 347 | #endif | ||
| 348 | |||
diff --git a/arch/arm/mach-tegra/include/mach/smp.h b/arch/arm/mach-tegra/include/mach/smp.h new file mode 100644 index 000000000000..8b42dab79a70 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/smp.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #ifndef ASMARM_ARCH_SMP_H | ||
| 2 | #define ASMARM_ARCH_SMP_H | ||
| 3 | |||
| 4 | |||
| 5 | #include <asm/hardware/gic.h> | ||
| 6 | |||
| 7 | #define hard_smp_processor_id() \ | ||
| 8 | ({ \ | ||
| 9 | unsigned int cpunum; \ | ||
| 10 | __asm__("mrc p15, 0, %0, c0, c0, 5" \ | ||
| 11 | : "=r" (cpunum)); \ | ||
| 12 | cpunum &= 0x0F; \ | ||
| 13 | }) | ||
| 14 | |||
| 15 | /* | ||
| 16 | * We use IRQ1 as the IPI | ||
| 17 | */ | ||
| 18 | static inline void smp_cross_call(const struct cpumask *mask) | ||
| 19 | { | ||
| 20 | gic_raise_softirq(mask, 1); | ||
| 21 | } | ||
| 22 | |||
| 23 | /* | ||
| 24 | * Do nothing on MPcore. | ||
| 25 | */ | ||
| 26 | static inline void smp_cross_call_done(cpumask_t callmap) | ||
| 27 | { | ||
| 28 | } | ||
| 29 | |||
| 30 | #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 index 000000000000..84d5d46113f7 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/system.h | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/system.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __MACH_TEGRA_SYSTEM_H | ||
| 22 | #define __MACH_TEGRA_SYSTEM_H | ||
| 23 | |||
| 24 | #include <mach/hardware.h> | ||
| 25 | #include <mach/iomap.h> | ||
| 26 | |||
| 27 | static inline void arch_idle(void) | ||
| 28 | { | ||
| 29 | } | ||
| 30 | |||
| 31 | static inline void arch_reset(char mode, const char *cmd) | ||
| 32 | { | ||
| 33 | void __iomem *reset = IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x04); | ||
| 34 | u32 reg = readl(reset); | ||
| 35 | reg |= 0x04; | ||
| 36 | writel(reg, reset); | ||
| 37 | } | ||
| 38 | |||
| 39 | #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 index 000000000000..a44ccbdb7dbf --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/timex.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/timex.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __MACH_TEGRA_TIMEX_H | ||
| 22 | #define __MACH_TEGRA_TIMEX_H | ||
| 23 | |||
| 24 | #define CLOCK_TICK_RATE 1000000 | ||
| 25 | |||
| 26 | #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 index 000000000000..6c4dd815abd7 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/uncompress.h | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/uncompress.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __MACH_TEGRA_UNCOMPRESS_H | ||
| 22 | #define __MACH_TEGRA_UNCOMPRESS_H | ||
| 23 | |||
| 24 | #include <linux/types.h> | ||
| 25 | #include <linux/serial_reg.h> | ||
| 26 | |||
| 27 | #include <mach/iomap.h> | ||
| 28 | |||
| 29 | #if defined(CONFIG_TEGRA_DEBUG_UARTA) | ||
| 30 | #define DEBUG_UART_BASE TEGRA_UARTA_BASE | ||
| 31 | #elif defined(CONFIG_TEGRA_DEBUG_UARTB) | ||
| 32 | #define DEBUG_UART_BASE TEGRA_UARTB_BASE | ||
| 33 | #elif defined(CONFIG_TEGRA_DEBUG_UARTC) | ||
| 34 | #define DEBUG_UART_BASE TEGRA_UARTC_BASE | ||
| 35 | #elif defined(CONFIG_TEGRA_DEBUG_UARTD) | ||
| 36 | #define DEBUG_UART_BASE TEGRA_UARTD_BASE | ||
| 37 | #elif defined(CONFIG_TEGRA_DEBUG_UARTE) | ||
| 38 | #define DEBUG_UART_BASE TEGRA_UARTE_BASE | ||
| 39 | #else | ||
| 40 | #define DEBUG_UART_BASE NULL | ||
| 41 | #endif | ||
| 42 | |||
| 43 | static void putc(int c) | ||
| 44 | { | ||
| 45 | volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE; | ||
| 46 | int shift = 2; | ||
| 47 | |||
| 48 | if (uart == NULL) | ||
| 49 | return; | ||
| 50 | |||
| 51 | while (!(uart[UART_LSR << shift] & UART_LSR_THRE)) | ||
| 52 | barrier(); | ||
| 53 | uart[UART_TX << shift] = c; | ||
| 54 | } | ||
| 55 | |||
| 56 | static inline void flush(void) | ||
| 57 | { | ||
| 58 | } | ||
| 59 | |||
| 60 | static inline void arch_decomp_setup(void) | ||
| 61 | { | ||
| 62 | volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE; | ||
| 63 | int shift = 2; | ||
| 64 | |||
| 65 | if (uart == NULL) | ||
| 66 | return; | ||
| 67 | |||
| 68 | uart[UART_LCR << shift] |= UART_LCR_DLAB; | ||
| 69 | uart[UART_DLL << shift] = 0x75; | ||
| 70 | uart[UART_DLM << shift] = 0x0; | ||
| 71 | uart[UART_LCR << shift] = 3; | ||
| 72 | } | ||
| 73 | |||
| 74 | static inline void arch_decomp_wdog(void) | ||
| 75 | { | ||
| 76 | } | ||
| 77 | |||
| 78 | #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 index 000000000000..267a141730d9 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/vmalloc.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/include/mach/vmalloc.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef __MACH_TEGRA_VMALLOC_H | ||
| 22 | #define __MACH_TEGRA_VMALLOC_H | ||
| 23 | |||
| 24 | #include <asm/sizes.h> | ||
| 25 | |||
| 26 | #define VMALLOC_END 0xFE000000 | ||
| 27 | |||
| 28 | #endif | ||
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c new file mode 100644 index 000000000000..9fe2c5c683d4 --- /dev/null +++ b/arch/arm/mach-tegra/io.c | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/io.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * Erik Gilling <konkers@google.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/init.h> | ||
| 24 | #include <linux/mm.h> | ||
| 25 | #include <linux/io.h> | ||
| 26 | |||
| 27 | #include <mach/hardware.h> | ||
| 28 | #include <asm/page.h> | ||
| 29 | #include <asm/mach/map.h> | ||
| 30 | |||
| 31 | #include "board.h" | ||
| 32 | |||
| 33 | static struct map_desc tegra_io_desc[] __initdata = { | ||
| 34 | { | ||
| 35 | .virtual = IO_PPSB_VIRT, | ||
| 36 | .pfn = __phys_to_pfn(IO_PPSB_PHYS), | ||
| 37 | .length = IO_PPSB_SIZE, | ||
| 38 | .type = MT_DEVICE, | ||
| 39 | }, | ||
| 40 | { | ||
| 41 | .virtual = IO_APB_VIRT, | ||
| 42 | .pfn = __phys_to_pfn(IO_APB_PHYS), | ||
| 43 | .length = IO_APB_SIZE, | ||
| 44 | .type = MT_DEVICE, | ||
| 45 | }, | ||
| 46 | { | ||
| 47 | .virtual = IO_CPU_VIRT, | ||
| 48 | .pfn = __phys_to_pfn(IO_CPU_PHYS), | ||
| 49 | .length = IO_CPU_SIZE, | ||
| 50 | .type = MT_DEVICE, | ||
| 51 | }, | ||
| 52 | }; | ||
| 53 | |||
| 54 | void __init tegra_map_common_io(void) | ||
| 55 | { | ||
| 56 | iotable_init(tegra_io_desc, ARRAY_SIZE(tegra_io_desc)); | ||
| 57 | } | ||
| 58 | |||
| 59 | /* | ||
| 60 | * Intercept ioremap() requests for addresses in our fixed mapping regions. | ||
| 61 | */ | ||
| 62 | void __iomem *tegra_ioremap(unsigned long p, size_t size, unsigned int type) | ||
| 63 | { | ||
| 64 | void __iomem *v = IO_ADDRESS(p); | ||
| 65 | if (v == NULL) | ||
| 66 | v = __arm_ioremap(p, size, type); | ||
| 67 | return v; | ||
| 68 | } | ||
| 69 | EXPORT_SYMBOL(tegra_ioremap); | ||
| 70 | |||
| 71 | void tegra_iounmap(volatile void __iomem *addr) | ||
| 72 | { | ||
| 73 | unsigned long virt = (unsigned long)addr; | ||
| 74 | |||
| 75 | if (virt >= VMALLOC_START && virt < VMALLOC_END) | ||
| 76 | __iounmap(addr); | ||
| 77 | } | ||
| 78 | EXPORT_SYMBOL(tegra_iounmap); | ||
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c new file mode 100644 index 000000000000..1fdbe708d43d --- /dev/null +++ b/arch/arm/mach-tegra/irq.c | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2010 Google, Inc. | ||
| 3 | * | ||
| 4 | * Author: | ||
| 5 | * Colin Cross <ccross@google.com> | ||
| 6 | * | ||
| 7 | * This software is licensed under the terms of the GNU General Public | ||
| 8 | * License version 2, as published by the Free Software Foundation, and | ||
| 9 | * may be copied, distributed, and modified under those terms. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/irq.h> | ||
| 22 | #include <linux/io.h> | ||
| 23 | |||
| 24 | #include <asm/hardware/gic.h> | ||
| 25 | |||
| 26 | #include <mach/iomap.h> | ||
| 27 | |||
| 28 | #include "board.h" | ||
| 29 | |||
| 30 | void __init tegra_init_irq(void) | ||
| 31 | { | ||
| 32 | gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29); | ||
| 33 | gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); | ||
| 34 | } | ||
diff --git a/arch/arm/mach-tegra/localtimer.c b/arch/arm/mach-tegra/localtimer.c new file mode 100644 index 000000000000..f81ca7cbbc1f --- /dev/null +++ b/arch/arm/mach-tegra/localtimer.c | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/localtimer.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002 ARM Ltd. | ||
| 5 | * All Rights Reserved | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/smp.h> | ||
| 13 | #include <linux/clockchips.h> | ||
| 14 | #include <asm/irq.h> | ||
| 15 | #include <asm/smp_twd.h> | ||
| 16 | #include <asm/localtimer.h> | ||
| 17 | |||
| 18 | /* | ||
| 19 | * Setup the local clock events for a CPU. | ||
| 20 | */ | ||
| 21 | void __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
| 22 | { | ||
| 23 | evt->irq = IRQ_LOCALTIMER; | ||
| 24 | twd_timer_setup(evt); | ||
| 25 | } | ||
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c new file mode 100644 index 000000000000..13ae10237e84 --- /dev/null +++ b/arch/arm/mach-tegra/pinmux.c | |||
| @@ -0,0 +1,945 @@ | |||
| 1 | /* | ||
| 2 | * linux/arch/arm/mach-tegra/pinmux.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * This software is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2, as published by the Free Software Foundation, and | ||
| 8 | * may be copied, distributed, and modified under those terms. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/errno.h> | ||
| 20 | #include <linux/spinlock.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | |||
| 23 | #include <mach/iomap.h> | ||
| 24 | #include <mach/pinmux.h> | ||
| 25 | |||
| 26 | |||
| 27 | #define TEGRA_TRI_STATE(x) (0x14 + (4 * (x))) | ||
| 28 | #define TEGRA_PP_MUX_CTL(x) (0x80 + (4 * (x))) | ||
| 29 | #define TEGRA_PP_PU_PD(x) (0xa0 + (4 * (x))) | ||
| 30 | |||
| 31 | #define REG_A 0 | ||
| 32 | #define REG_B 1 | ||
| 33 | #define REG_C 2 | ||
| 34 | #define REG_D 3 | ||
| 35 | #define REG_E 4 | ||
| 36 | #define REG_F 5 | ||
| 37 | #define REG_G 6 | ||
| 38 | |||
| 39 | #define REG_N -1 | ||
| 40 | |||
| 41 | #define HSM_EN(reg) (((reg) >> 2) & 0x1) | ||
| 42 | #define SCHMT_EN(reg) (((reg) >> 3) & 0x1) | ||
| 43 | #define LPMD(reg) (((reg) >> 4) & 0x3) | ||
| 44 | #define DRVDN(reg) (((reg) >> 12) & 0x1f) | ||
| 45 | #define DRVUP(reg) (((reg) >> 20) & 0x1f) | ||
| 46 | #define SLWR(reg) (((reg) >> 28) & 0x3) | ||
| 47 | #define SLWF(reg) (((reg) >> 30) & 0x3) | ||
| 48 | |||
| 49 | struct tegra_pingroup_desc { | ||
| 50 | const char *name; | ||
| 51 | int funcs[4]; | ||
| 52 | s8 tri_reg; /* offset into the TRISTATE_REG_* register bank */ | ||
| 53 | s8 tri_bit; /* offset into the TRISTATE_REG_* register bit */ | ||
| 54 | s8 mux_reg; /* offset into the PIN_MUX_CTL_* register bank */ | ||
| 55 | s8 mux_bit; /* offset into the PIN_MUX_CTL_* register bit */ | ||
| 56 | s8 pupd_reg; /* offset into the PULL_UPDOWN_REG_* register bank */ | ||
| 57 | s8 pupd_bit; /* offset into the PULL_UPDOWN_REG_* register bit */ | ||
| 58 | }; | ||
| 59 | |||
| 60 | #define PINGROUP(pg_name, f0, f1, f2, f3, \ | ||
| 61 | tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b) \ | ||
| 62 | [TEGRA_PINGROUP_ ## pg_name] = { \ | ||
| 63 | .name = #pg_name, \ | ||
| 64 | .funcs = { \ | ||
| 65 | TEGRA_MUX_ ## f0, \ | ||
| 66 | TEGRA_MUX_ ## f1, \ | ||
| 67 | TEGRA_MUX_ ## f2, \ | ||
| 68 | TEGRA_MUX_ ## f3, \ | ||
| 69 | }, \ | ||
| 70 | .tri_reg = REG_ ## tri_r, \ | ||
| 71 | .tri_bit = tri_b, \ | ||
| 72 | .mux_reg = REG_ ## mux_r, \ | ||
| 73 | .mux_bit = mux_b, \ | ||
| 74 | .pupd_reg = REG_ ## pupd_r, \ | ||
| 75 | .pupd_bit = pupd_b, \ | ||
| 76 | } | ||
| 77 | |||
| 78 | static const struct tegra_pingroup_desc pingroups[TEGRA_MAX_PINGROUP] = { | ||
| 79 | PINGROUP(ATA, IDE, NAND, GMI, RSVD, A, 0, A, 24, A, 0), | ||
| 80 | PINGROUP(ATB, IDE, NAND, GMI, SDIO4, A, 1, A, 16, A, 2), | ||
| 81 | PINGROUP(ATC, IDE, NAND, GMI, SDIO4, A, 2, A, 22, A, 4), | ||
| 82 | PINGROUP(ATD, IDE, NAND, GMI, SDIO4, A, 3, A, 20, A, 6), | ||
| 83 | PINGROUP(ATE, IDE, NAND, GMI, RSVD, B, 25, A, 12, A, 8), | ||
| 84 | PINGROUP(CDEV1, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, A, 4, C, 2, C, 0), | ||
| 85 | PINGROUP(CDEV2, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, A, 5, C, 4, C, 2), | ||
| 86 | PINGROUP(CRTP, CRT, RSVD, RSVD, RSVD, D, 14, G, 20, B, 24), | ||
| 87 | PINGROUP(CSUS, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, A, 6, C, 6, D, 24), | ||
| 88 | PINGROUP(DAP1, DAP1, RSVD, GMI, SDIO2, A, 7, C, 20, A, 10), | ||
| 89 | PINGROUP(DAP2, DAP2, TWC, RSVD, GMI, A, 8, C, 22, A, 12), | ||
| 90 | PINGROUP(DAP3, DAP3, RSVD, RSVD, RSVD, A, 9, C, 24, A, 14), | ||
| 91 | PINGROUP(DAP4, DAP4, RSVD, GMI, RSVD, A, 10, C, 26, A, 16), | ||
| 92 | PINGROUP(DDC, I2C2, RSVD, RSVD, RSVD, B, 31, C, 0, E, 28), | ||
| 93 | PINGROUP(DTA, RSVD, SDIO2, VI, RSVD, A, 11, B, 20, A, 18), | ||
| 94 | PINGROUP(DTB, RSVD, RSVD, VI, SPI1, A, 12, B, 22, A, 20), | ||
| 95 | PINGROUP(DTC, RSVD, RSVD, VI, RSVD, A, 13, B, 26, A, 22), | ||
| 96 | PINGROUP(DTD, RSVD, SDIO2, VI, RSVD, A, 14, B, 28, A, 24), | ||
| 97 | PINGROUP(DTE, RSVD, RSVD, VI, SPI1, A, 15, B, 30, A, 26), | ||
| 98 | PINGROUP(DTF, I2C3, RSVD, VI, RSVD, D, 12, G, 30, A, 28), | ||
| 99 | PINGROUP(GMA, UARTE, SPI3, GMI, SDIO4, A, 28, B, 0, E, 20), | ||
| 100 | PINGROUP(GMB, IDE, NAND, GMI, GMI_INT, B, 29, C, 28, E, 22), | ||
| 101 | PINGROUP(GMC, UARTD, SPI4, GMI, SFLASH, A, 29, B, 2, E, 24), | ||
| 102 | PINGROUP(GMD, RSVD, NAND, GMI, SFLASH, B, 30, C, 30, E, 26), | ||
| 103 | PINGROUP(GME, RSVD, DAP5, GMI, SDIO4, B, 0, D, 0, C, 24), | ||
| 104 | PINGROUP(GPU, PWM, UARTA, GMI, RSVD, A, 16, D, 4, B, 20), | ||
| 105 | PINGROUP(GPU7, RTCK, RSVD, RSVD, RSVD, D, 11, G, 28, B, 6), | ||
| 106 | PINGROUP(GPV, PCIE, RSVD, RSVD, RSVD, A, 17, D, 2, A, 30), | ||
| 107 | PINGROUP(HDINT, HDMI, RSVD, RSVD, RSVD, C, 23, B, 4, D, 22), | ||
| 108 | PINGROUP(I2CP, I2C, RSVD, RSVD, RSVD, A, 18, C, 8, B, 2), | ||
| 109 | PINGROUP(IRRX, UARTA, UARTB, GMI, SPI4, A, 20, C, 18, C, 22), | ||
| 110 | PINGROUP(IRTX, UARTA, UARTB, GMI, SPI4, A, 19, C, 16, C, 20), | ||
| 111 | PINGROUP(KBCA, KBC, NAND, SDIO2, EMC_TEST0_DLL, A, 22, C, 10, B, 8), | ||
| 112 | PINGROUP(KBCB, KBC, NAND, SDIO2, MIO, A, 21, C, 12, B, 10), | ||
| 113 | PINGROUP(KBCC, KBC, NAND, TRACE, EMC_TEST1_DLL, B, 26, C, 14, B, 12), | ||
| 114 | PINGROUP(KBCD, KBC, NAND, SDIO2, MIO, D, 10, G, 26, B, 14), | ||
| 115 | PINGROUP(KBCE, KBC, NAND, OWR, RSVD, A, 26, A, 28, E, 2), | ||
| 116 | PINGROUP(KBCF, KBC, NAND, TRACE, MIO, A, 27, A, 26, E, 0), | ||
| 117 | PINGROUP(LCSN, DISPLAYA, DISPLAYB, SPI3, RSVD, C, 31, E, 12, D, 20), | ||
| 118 | PINGROUP(LD0, DISPLAYA, DISPLAYB, XIO, RSVD, C, 0, F, 0, D, 12), | ||
| 119 | PINGROUP(LD1, DISPLAYA, DISPLAYB, XIO, RSVD, C, 1, F, 2, D, 12), | ||
| 120 | PINGROUP(LD10, DISPLAYA, DISPLAYB, XIO, RSVD, C, 10, F, 20, D, 12), | ||
| 121 | PINGROUP(LD11, DISPLAYA, DISPLAYB, XIO, RSVD, C, 11, F, 22, D, 12), | ||
| 122 | PINGROUP(LD12, DISPLAYA, DISPLAYB, XIO, RSVD, C, 12, F, 24, D, 12), | ||
| 123 | PINGROUP(LD13, DISPLAYA, DISPLAYB, XIO, RSVD, C, 13, F, 26, D, 12), | ||
| 124 | PINGROUP(LD14, DISPLAYA, DISPLAYB, XIO, RSVD, C, 14, F, 28, D, 12), | ||
| 125 | PINGROUP(LD15, DISPLAYA, DISPLAYB, XIO, RSVD, C, 15, F, 30, D, 12), | ||
| 126 | PINGROUP(LD16, DISPLAYA, DISPLAYB, XIO, RSVD, C, 16, G, 0, D, 12), | ||
| 127 | PINGROUP(LD17, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 17, G, 2, D, 12), | ||
| 128 | PINGROUP(LD2, DISPLAYA, DISPLAYB, XIO, RSVD, C, 2, F, 4, D, 12), | ||
| 129 | PINGROUP(LD3, DISPLAYA, DISPLAYB, XIO, RSVD, C, 3, F, 6, D, 12), | ||
| 130 | PINGROUP(LD4, DISPLAYA, DISPLAYB, XIO, RSVD, C, 4, F, 8, D, 12), | ||
| 131 | PINGROUP(LD5, DISPLAYA, DISPLAYB, XIO, RSVD, C, 5, F, 10, D, 12), | ||
| 132 | PINGROUP(LD6, DISPLAYA, DISPLAYB, XIO, RSVD, C, 6, F, 12, D, 12), | ||
| 133 | PINGROUP(LD7, DISPLAYA, DISPLAYB, XIO, RSVD, C, 7, F, 14, D, 12), | ||
| 134 | PINGROUP(LD8, DISPLAYA, DISPLAYB, XIO, RSVD, C, 8, F, 16, D, 12), | ||
| 135 | PINGROUP(LD9, DISPLAYA, DISPLAYB, XIO, RSVD, C, 9, F, 18, D, 12), | ||
| 136 | PINGROUP(LDC, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 30, E, 14, D, 20), | ||
| 137 | PINGROUP(LDI, DISPLAYA, DISPLAYB, RSVD, RSVD, D, 6, G, 16, D, 18), | ||
| 138 | PINGROUP(LHP0, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 18, G, 10, D, 16), | ||
| 139 | PINGROUP(LHP1, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 19, G, 4, D, 14), | ||
| 140 | PINGROUP(LHP2, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 20, G, 6, D, 14), | ||
| 141 | PINGROUP(LHS, DISPLAYA, DISPLAYB, XIO, RSVD, D, 7, E, 22, D, 22), | ||
| 142 | PINGROUP(LM0, DISPLAYA, DISPLAYB, SPI3, RSVD, C, 24, E, 26, D, 22), | ||
| 143 | PINGROUP(LM1, DISPLAYA, DISPLAYB, RSVD, CRT, C, 25, E, 28, D, 22), | ||
| 144 | PINGROUP(LPP, DISPLAYA, DISPLAYB, RSVD, RSVD, D, 8, G, 14, D, 18), | ||
| 145 | PINGROUP(LPW0, DISPLAYA, DISPLAYB, SPI3, HDMI, D, 3, E, 0, D, 20), | ||
| 146 | PINGROUP(LPW1, DISPLAYA, DISPLAYB, RSVD, RSVD, D, 4, E, 2, D, 20), | ||
| 147 | PINGROUP(LPW2, DISPLAYA, DISPLAYB, SPI3, HDMI, D, 5, E, 4, D, 20), | ||
| 148 | PINGROUP(LSC0, DISPLAYA, DISPLAYB, XIO, RSVD, C, 27, E, 18, D, 22), | ||
| 149 | PINGROUP(LSC1, DISPLAYA, DISPLAYB, SPI3, HDMI, C, 28, E, 20, D, 20), | ||
| 150 | PINGROUP(LSCK, DISPLAYA, DISPLAYB, SPI3, HDMI, C, 29, E, 16, D, 20), | ||
| 151 | PINGROUP(LSDA, DISPLAYA, DISPLAYB, SPI3, HDMI, D, 1, E, 8, D, 20), | ||
| 152 | PINGROUP(LSDI, DISPLAYA, DISPLAYB, SPI3, RSVD, D, 2, E, 6, D, 20), | ||
| 153 | PINGROUP(LSPI, DISPLAYA, DISPLAYB, XIO, HDMI, D, 0, E, 10, D, 22), | ||
| 154 | PINGROUP(LVP0, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 21, E, 30, D, 22), | ||
| 155 | PINGROUP(LVP1, DISPLAYA, DISPLAYB, RSVD, RSVD, C, 22, G, 8, D, 16), | ||
| 156 | PINGROUP(LVS, DISPLAYA, DISPLAYB, XIO, RSVD, C, 26, E, 24, D, 22), | ||
| 157 | PINGROUP(OWC, OWR, RSVD, RSVD, RSVD, A, 31, B, 8, E, 30), | ||
| 158 | PINGROUP(PMC, PWR_ON, PWR_INTR, RSVD, RSVD, A, 23, G, 18, N, -1), | ||
| 159 | PINGROUP(PTA, I2C2, HDMI, GMI, RSVD, A, 24, G, 22, B, 4), | ||
| 160 | PINGROUP(RM, I2C, RSVD, RSVD, RSVD, A, 25, A, 14, B, 0), | ||
| 161 | PINGROUP(SDB, UARTA, PWM, SDIO3, SPI2, D, 15, D, 10, N, -1), | ||
| 162 | PINGROUP(SDC, PWM, TWC, SDIO3, SPI3, B, 1, D, 12, D, 28), | ||
| 163 | PINGROUP(SDD, UARTA, PWM, SDIO3, SPI3, B, 2, D, 14, D, 30), | ||
| 164 | PINGROUP(SDIO1, SDIO1, RSVD, UARTE, UARTA, A, 30, A, 30, E, 18), | ||
| 165 | PINGROUP(SLXA, PCIE, SPI4, SDIO3, SPI2, B, 3, B, 6, B, 22), | ||
| 166 | PINGROUP(SLXC, SPDIF, SPI4, SDIO3, SPI2, B, 5, B, 10, B, 26), | ||
| 167 | PINGROUP(SLXD, SPDIF, SPI4, SDIO3, SPI2, B, 6, B, 12, B, 28), | ||
| 168 | PINGROUP(SLXK, PCIE, SPI4, SDIO3, SPI2, B, 7, B, 14, B, 30), | ||
| 169 | PINGROUP(SPDI, SPDIF, RSVD, I2C, SDIO2, B, 8, D, 8, B, 16), | ||
| 170 | PINGROUP(SPDO, SPDIF, RSVD, I2C, SDIO2, B, 9, D, 6, B, 18), | ||
| 171 | PINGROUP(SPIA, SPI1, SPI2, SPI3, GMI, B, 10, D, 30, C, 4), | ||
| 172 | PINGROUP(SPIB, SPI1, SPI2, SPI3, GMI, B, 11, D, 28, C, 6), | ||
| 173 | PINGROUP(SPIC, SPI1, SPI2, SPI3, GMI, B, 12, D, 26, C, 8), | ||
| 174 | PINGROUP(SPID, SPI2, SPI1, SPI2_ALT, GMI, B, 13, D, 24, C, 10), | ||
| 175 | PINGROUP(SPIE, SPI2, SPI1, SPI2_ALT, GMI, B, 14, D, 22, C, 12), | ||
| 176 | PINGROUP(SPIF, SPI3, SPI1, SPI2, RSVD, B, 15, D, 20, C, 14), | ||
| 177 | PINGROUP(SPIG, SPI3, SPI2, SPI2_ALT, I2C, B, 16, D, 18, C, 16), | ||
| 178 | PINGROUP(SPIH, SPI3, SPI2, SPI2_ALT, I2C, B, 17, D, 16, C, 18), | ||
| 179 | PINGROUP(UAA, SPI3, MIPI_HS, UARTA, ULPI, B, 18, A, 0, D, 0), | ||
| 180 | PINGROUP(UAB, SPI2, MIPI_HS, UARTA, ULPI, B, 19, A, 2, D, 2), | ||
| 181 | PINGROUP(UAC, OWR, RSVD, RSVD, RSVD, B, 20, A, 4, D, 4), | ||
| 182 | PINGROUP(UAD, IRDA, SPDIF, UARTA, SPI4, B, 21, A, 6, D, 6), | ||
| 183 | PINGROUP(UCA, UARTC, RSVD, GMI, RSVD, B, 22, B, 16, D, 8), | ||
| 184 | PINGROUP(UCB, UARTC, PWM, GMI, RSVD, B, 23, B, 18, D, 10), | ||
| 185 | PINGROUP(UDA, SPI1, RSVD, UARTD, ULPI, D, 13, A, 8, E, 16), | ||
| 186 | /* these pin groups only have pullup and pull down control */ | ||
| 187 | PINGROUP(CK32, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 14), | ||
| 188 | PINGROUP(DDRC, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, D, 26), | ||
| 189 | PINGROUP(PMCA, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 4), | ||
| 190 | PINGROUP(PMCB, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 6), | ||
| 191 | PINGROUP(PMCC, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 8), | ||
| 192 | PINGROUP(PMCD, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 10), | ||
| 193 | PINGROUP(PMCE, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, E, 12), | ||
| 194 | PINGROUP(XM2C, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, C, 30), | ||
| 195 | PINGROUP(XM2D, RSVD, RSVD, RSVD, RSVD, N, -1, N, -1, C, 28), | ||
| 196 | }; | ||
| 197 | |||
| 198 | static char *tegra_mux_names[TEGRA_MAX_MUX] = { | ||
| 199 | [TEGRA_MUX_AHB_CLK] = "AHB_CLK", | ||
| 200 | [TEGRA_MUX_APB_CLK] = "APB_CLK", | ||
| 201 | [TEGRA_MUX_AUDIO_SYNC] = "AUDIO_SYNC", | ||
| 202 | [TEGRA_MUX_CRT] = "CRT", | ||
| 203 | [TEGRA_MUX_DAP1] = "DAP1", | ||
| 204 | [TEGRA_MUX_DAP2] = "DAP2", | ||
| 205 | [TEGRA_MUX_DAP3] = "DAP3", | ||
| 206 | [TEGRA_MUX_DAP4] = "DAP4", | ||
| 207 | [TEGRA_MUX_DAP5] = "DAP5", | ||
| 208 | [TEGRA_MUX_DISPLAYA] = "DISPLAYA", | ||
| 209 | [TEGRA_MUX_DISPLAYB] = "DISPLAYB", | ||
| 210 | [TEGRA_MUX_EMC_TEST0_DLL] = "EMC_TEST0_DLL", | ||
| 211 | [TEGRA_MUX_EMC_TEST1_DLL] = "EMC_TEST1_DLL", | ||
| 212 | [TEGRA_MUX_GMI] = "GMI", | ||
| 213 | [TEGRA_MUX_GMI_INT] = "GMI_INT", | ||
| 214 | [TEGRA_MUX_HDMI] = "HDMI", | ||
| 215 | [TEGRA_MUX_I2C] = "I2C", | ||
| 216 | [TEGRA_MUX_I2C2] = "I2C2", | ||
| 217 | [TEGRA_MUX_I2C3] = "I2C3", | ||
| 218 | [TEGRA_MUX_IDE] = "IDE", | ||
| 219 | [TEGRA_MUX_IRDA] = "IRDA", | ||
| 220 | [TEGRA_MUX_KBC] = "KBC", | ||
| 221 | [TEGRA_MUX_MIO] = "MIO", | ||
| 222 | [TEGRA_MUX_MIPI_HS] = "MIPI_HS", | ||
| 223 | [TEGRA_MUX_NAND] = "NAND", | ||
| 224 | [TEGRA_MUX_OSC] = "OSC", | ||
| 225 | [TEGRA_MUX_OWR] = "OWR", | ||
| 226 | [TEGRA_MUX_PCIE] = "PCIE", | ||
| 227 | [TEGRA_MUX_PLLA_OUT] = "PLLA_OUT", | ||
| 228 | [TEGRA_MUX_PLLC_OUT1] = "PLLC_OUT1", | ||
| 229 | [TEGRA_MUX_PLLM_OUT1] = "PLLM_OUT1", | ||
| 230 | [TEGRA_MUX_PLLP_OUT2] = "PLLP_OUT2", | ||
| 231 | [TEGRA_MUX_PLLP_OUT3] = "PLLP_OUT3", | ||
| 232 | [TEGRA_MUX_PLLP_OUT4] = "PLLP_OUT4", | ||
| 233 | [TEGRA_MUX_PWM] = "PWM", | ||
| 234 | [TEGRA_MUX_PWR_INTR] = "PWR_INTR", | ||
| 235 | [TEGRA_MUX_PWR_ON] = "PWR_ON", | ||
| 236 | [TEGRA_MUX_RTCK] = "RTCK", | ||
| 237 | [TEGRA_MUX_SDIO1] = "SDIO1", | ||
| 238 | [TEGRA_MUX_SDIO2] = "SDIO2", | ||
| 239 | [TEGRA_MUX_SDIO3] = "SDIO3", | ||
| 240 | [TEGRA_MUX_SDIO4] = "SDIO4", | ||
| 241 | [TEGRA_MUX_SFLASH] = "SFLASH", | ||
| 242 | [TEGRA_MUX_SPDIF] = "SPDIF", | ||
| 243 | [TEGRA_MUX_SPI1] = "SPI1", | ||
| 244 | [TEGRA_MUX_SPI2] = "SPI2", | ||
| 245 | [TEGRA_MUX_SPI2_ALT] = "SPI2_ALT", | ||
| 246 | [TEGRA_MUX_SPI3] = "SPI3", | ||
| 247 | [TEGRA_MUX_SPI4] = "SPI4", | ||
| 248 | [TEGRA_MUX_TRACE] = "TRACE", | ||
| 249 | [TEGRA_MUX_TWC] = "TWC", | ||
| 250 | [TEGRA_MUX_UARTA] = "UARTA", | ||
| 251 | [TEGRA_MUX_UARTB] = "UARTB", | ||
| 252 | [TEGRA_MUX_UARTC] = "UARTC", | ||
| 253 | [TEGRA_MUX_UARTD] = "UARTD", | ||
| 254 | [TEGRA_MUX_UARTE] = "UARTE", | ||
| 255 | [TEGRA_MUX_ULPI] = "ULPI", | ||
| 256 | [TEGRA_MUX_VI] = "VI", | ||
| 257 | [TEGRA_MUX_VI_SENSOR_CLK] = "VI_SENSOR_CLK", | ||
| 258 | [TEGRA_MUX_XIO] = "XIO", | ||
| 259 | }; | ||
| 260 | |||
| 261 | struct tegra_drive_pingroup_desc { | ||
| 262 | const char *name; | ||
| 263 | s16 reg; | ||
| 264 | }; | ||
| 265 | |||
| 266 | #define DRIVE_PINGROUP(pg_name, r) \ | ||
| 267 | [TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \ | ||
| 268 | .name = #pg_name, \ | ||
| 269 | .reg = r \ | ||
| 270 | } | ||
| 271 | |||
| 272 | static const struct tegra_drive_pingroup_desc drive_pingroups[TEGRA_MAX_PINGROUP] = { | ||
| 273 | DRIVE_PINGROUP(AO1, 0x868), | ||
| 274 | DRIVE_PINGROUP(AO2, 0x86c), | ||
| 275 | DRIVE_PINGROUP(AT1, 0x870), | ||
| 276 | DRIVE_PINGROUP(AT2, 0x874), | ||
| 277 | DRIVE_PINGROUP(CDEV1, 0x878), | ||
| 278 | DRIVE_PINGROUP(CDEV2, 0x87c), | ||
| 279 | DRIVE_PINGROUP(CSUS, 0x880), | ||
| 280 | DRIVE_PINGROUP(DAP1, 0x884), | ||
| 281 | DRIVE_PINGROUP(DAP2, 0x888), | ||
| 282 | DRIVE_PINGROUP(DAP3, 0x88c), | ||
| 283 | DRIVE_PINGROUP(DAP4, 0x890), | ||
| 284 | DRIVE_PINGROUP(DBG, 0x894), | ||
| 285 | DRIVE_PINGROUP(LCD1, 0x898), | ||
| 286 | DRIVE_PINGROUP(LCD2, 0x89c), | ||
| 287 | DRIVE_PINGROUP(SDMMC2, 0x8a0), | ||
| 288 | DRIVE_PINGROUP(SDMMC3, 0x8a4), | ||
| 289 | DRIVE_PINGROUP(SPI, 0x8a8), | ||
| 290 | DRIVE_PINGROUP(UAA, 0x8ac), | ||
| 291 | DRIVE_PINGROUP(UAB, 0x8b0), | ||
| 292 | DRIVE_PINGROUP(UART2, 0x8b4), | ||
| 293 | DRIVE_PINGROUP(UART3, 0x8b8), | ||
| 294 | DRIVE_PINGROUP(VI1, 0x8bc), | ||
| 295 | DRIVE_PINGROUP(VI2, 0x8c0), | ||
| 296 | DRIVE_PINGROUP(XM2A, 0x8c4), | ||
| 297 | DRIVE_PINGROUP(XM2C, 0x8c8), | ||
| 298 | DRIVE_PINGROUP(XM2D, 0x8cc), | ||
| 299 | DRIVE_PINGROUP(XM2CLK, 0x8d0), | ||
| 300 | DRIVE_PINGROUP(MEMCOMP, 0x8d4), | ||
| 301 | }; | ||
| 302 | |||
| 303 | static const char *tegra_drive_names[TEGRA_MAX_DRIVE] = { | ||
| 304 | [TEGRA_DRIVE_DIV_8] = "DIV_8", | ||
| 305 | [TEGRA_DRIVE_DIV_4] = "DIV_4", | ||
| 306 | [TEGRA_DRIVE_DIV_2] = "DIV_2", | ||
| 307 | [TEGRA_DRIVE_DIV_1] = "DIV_1", | ||
| 308 | }; | ||
| 309 | |||
| 310 | static const char *tegra_slew_names[TEGRA_MAX_SLEW] = { | ||
| 311 | [TEGRA_SLEW_FASTEST] = "FASTEST", | ||
| 312 | [TEGRA_SLEW_FAST] = "FAST", | ||
| 313 | [TEGRA_SLEW_SLOW] = "SLOW", | ||
| 314 | [TEGRA_SLEW_SLOWEST] = "SLOWEST", | ||
| 315 | }; | ||
| 316 | |||
| 317 | static DEFINE_SPINLOCK(mux_lock); | ||
| 318 | |||
| 319 | static const char *pingroup_name(enum tegra_pingroup pg) | ||
| 320 | { | ||
| 321 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | ||
| 322 | return "<UNKNOWN>"; | ||
| 323 | |||
| 324 | return pingroups[pg].name; | ||
| 325 | } | ||
| 326 | |||
| 327 | static const char *func_name(enum tegra_mux_func func) | ||
| 328 | { | ||
| 329 | if (func == TEGRA_MUX_RSVD1) | ||
| 330 | return "RSVD1"; | ||
| 331 | |||
| 332 | if (func == TEGRA_MUX_RSVD2) | ||
| 333 | return "RSVD2"; | ||
| 334 | |||
| 335 | if (func == TEGRA_MUX_RSVD3) | ||
| 336 | return "RSVD3"; | ||
| 337 | |||
| 338 | if (func == TEGRA_MUX_RSVD4) | ||
| 339 | return "RSVD4"; | ||
| 340 | |||
| 341 | if (func == TEGRA_MUX_NONE) | ||
| 342 | return "NONE"; | ||
| 343 | |||
| 344 | if (func < 0 || func >= TEGRA_MAX_MUX) | ||
| 345 | return "<UNKNOWN>"; | ||
| 346 | |||
| 347 | return tegra_mux_names[func]; | ||
| 348 | } | ||
| 349 | |||
| 350 | |||
| 351 | static const char *tri_name(unsigned long val) | ||
| 352 | { | ||
| 353 | return val ? "TRISTATE" : "NORMAL"; | ||
| 354 | } | ||
| 355 | |||
| 356 | static const char *pupd_name(unsigned long val) | ||
| 357 | { | ||
| 358 | switch (val) { | ||
| 359 | case 0: | ||
| 360 | return "NORMAL"; | ||
| 361 | |||
| 362 | case 1: | ||
| 363 | return "PULL_DOWN"; | ||
| 364 | |||
| 365 | case 2: | ||
| 366 | return "PULL_UP"; | ||
| 367 | |||
| 368 | default: | ||
| 369 | return "RSVD"; | ||
| 370 | } | ||
| 371 | } | ||
| 372 | |||
| 373 | |||
| 374 | static inline unsigned long pg_readl(unsigned long offset) | ||
| 375 | { | ||
| 376 | return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset)); | ||
| 377 | } | ||
| 378 | |||
| 379 | static inline void pg_writel(unsigned long value, unsigned long offset) | ||
| 380 | { | ||
| 381 | writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset)); | ||
| 382 | } | ||
| 383 | |||
| 384 | int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func) | ||
| 385 | { | ||
| 386 | int mux = -1; | ||
| 387 | int i; | ||
| 388 | unsigned long reg; | ||
| 389 | unsigned long flags; | ||
| 390 | |||
| 391 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | ||
| 392 | return -ERANGE; | ||
| 393 | |||
| 394 | if (pingroups[pg].mux_reg == REG_N) | ||
| 395 | return -EINVAL; | ||
| 396 | |||
| 397 | if (func < 0) | ||
| 398 | return -ERANGE; | ||
| 399 | |||
| 400 | if (func & TEGRA_MUX_RSVD) { | ||
| 401 | mux = func & 0x3; | ||
| 402 | } else { | ||
| 403 | for (i = 0; i < 4; i++) { | ||
| 404 | if (pingroups[pg].funcs[i] == func) { | ||
| 405 | mux = i; | ||
| 406 | break; | ||
| 407 | } | ||
| 408 | } | ||
| 409 | } | ||
| 410 | |||
| 411 | if (mux < 0) | ||
| 412 | return -EINVAL; | ||
| 413 | |||
| 414 | spin_lock_irqsave(&mux_lock, flags); | ||
| 415 | |||
| 416 | reg = pg_readl(TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg)); | ||
| 417 | reg &= ~(0x3 << pingroups[pg].mux_bit); | ||
| 418 | reg |= mux << pingroups[pg].mux_bit; | ||
| 419 | pg_writel(reg, TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg)); | ||
| 420 | |||
| 421 | spin_unlock_irqrestore(&mux_lock, flags); | ||
| 422 | |||
| 423 | return 0; | ||
| 424 | } | ||
| 425 | |||
| 426 | int tegra_pinmux_set_tristate(enum tegra_pingroup pg, | ||
| 427 | enum tegra_tristate tristate) | ||
| 428 | { | ||
| 429 | unsigned long reg; | ||
| 430 | unsigned long flags; | ||
| 431 | |||
| 432 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | ||
| 433 | return -ERANGE; | ||
| 434 | |||
| 435 | if (pingroups[pg].tri_reg == REG_N) | ||
| 436 | return -EINVAL; | ||
| 437 | |||
| 438 | spin_lock_irqsave(&mux_lock, flags); | ||
| 439 | |||
| 440 | reg = pg_readl(TEGRA_TRI_STATE(pingroups[pg].tri_reg)); | ||
| 441 | reg &= ~(0x1 << pingroups[pg].tri_bit); | ||
| 442 | if (tristate) | ||
| 443 | reg |= 1 << pingroups[pg].tri_bit; | ||
| 444 | pg_writel(reg, TEGRA_TRI_STATE(pingroups[pg].tri_reg)); | ||
| 445 | |||
| 446 | spin_unlock_irqrestore(&mux_lock, flags); | ||
| 447 | |||
| 448 | return 0; | ||
| 449 | } | ||
| 450 | |||
| 451 | int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, | ||
| 452 | enum tegra_pullupdown pupd) | ||
| 453 | { | ||
| 454 | unsigned long reg; | ||
| 455 | unsigned long flags; | ||
| 456 | |||
| 457 | if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) | ||
| 458 | return -ERANGE; | ||
| 459 | |||
| 460 | if (pingroups[pg].pupd_reg == REG_N) | ||
| 461 | return -EINVAL; | ||
| 462 | |||
| 463 | if (pupd != TEGRA_PUPD_NORMAL && | ||
| 464 | pupd != TEGRA_PUPD_PULL_DOWN && | ||
| 465 | pupd != TEGRA_PUPD_PULL_UP) | ||
| 466 | return -EINVAL; | ||
| 467 | |||
| 468 | |||
| 469 | spin_lock_irqsave(&mux_lock, flags); | ||
| 470 | |||
| 471 | reg = pg_readl(TEGRA_PP_PU_PD(pingroups[pg].pupd_reg)); | ||
| 472 | reg &= ~(0x3 << pingroups[pg].pupd_bit); | ||
| 473 | reg |= pupd << pingroups[pg].pupd_bit; | ||
| 474 | pg_writel(reg, TEGRA_PP_PU_PD(pingroups[pg].pupd_reg)); | ||
| 475 | |||
| 476 | spin_unlock_irqrestore(&mux_lock, flags); | ||
| 477 | |||
| 478 | return 0; | ||
| 479 | } | ||
| 480 | |||
| 481 | void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup, | ||
| 482 | enum tegra_mux_func func, | ||
| 483 | enum tegra_pullupdown pupd, | ||
| 484 | enum tegra_tristate tristate) | ||
| 485 | { | ||
| 486 | int err; | ||
| 487 | |||
| 488 | if (pingroups[pingroup].mux_reg != REG_N) { | ||
| 489 | err = tegra_pinmux_set_func(pingroup, func); | ||
| 490 | if (err < 0) | ||
| 491 | pr_err("pinmux: can't set pingroup %s func to %s: %d\n", | ||
| 492 | pingroup_name(pingroup), func_name(func), err); | ||
| 493 | } | ||
| 494 | |||
| 495 | if (pingroups[pingroup].pupd_reg != REG_N) { | ||
| 496 | err = tegra_pinmux_set_pullupdown(pingroup, pupd); | ||
| 497 | if (err < 0) | ||
| 498 | pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n", | ||
| 499 | pingroup_name(pingroup), pupd_name(pupd), err); | ||
| 500 | } | ||
| 501 | |||
| 502 | if (pingroups[pingroup].tri_reg != REG_N) { | ||
| 503 | err = tegra_pinmux_set_tristate(pingroup, tristate); | ||
| 504 | if (err < 0) | ||
| 505 | pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n", | ||
| 506 | pingroup_name(pingroup), tri_name(func), err); | ||
| 507 | } | ||
| 508 | } | ||
| 509 | |||
| 510 | |||
| 511 | |||
| 512 | void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len) | ||
| 513 | { | ||
| 514 | int i; | ||
| 515 | |||
| 516 | for (i = 0; i < len; i++) | ||
| 517 | tegra_pinmux_config_pingroup(config[i].pingroup, | ||
| 518 | config[i].func, | ||
| 519 | config[i].pupd, | ||
| 520 | config[i].tristate); | ||
| 521 | } | ||
| 522 | |||
| 523 | static const char *drive_pinmux_name(enum tegra_drive_pingroup pg) | ||
| 524 | { | ||
| 525 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) | ||
| 526 | return "<UNKNOWN>"; | ||
| 527 | |||
| 528 | return drive_pingroups[pg].name; | ||
| 529 | } | ||
| 530 | |||
| 531 | static const char *enable_name(unsigned long val) | ||
| 532 | { | ||
| 533 | return val ? "ENABLE" : "DISABLE"; | ||
| 534 | } | ||
| 535 | |||
| 536 | static const char *drive_name(unsigned long val) | ||
| 537 | { | ||
| 538 | if (val >= TEGRA_MAX_DRIVE) | ||
| 539 | return "<UNKNOWN>"; | ||
| 540 | |||
| 541 | return tegra_drive_names[val]; | ||
| 542 | } | ||
| 543 | |||
| 544 | static const char *slew_name(unsigned long val) | ||
| 545 | { | ||
| 546 | if (val >= TEGRA_MAX_SLEW) | ||
| 547 | return "<UNKNOWN>"; | ||
| 548 | |||
| 549 | return tegra_slew_names[val]; | ||
| 550 | } | ||
| 551 | |||
| 552 | static int tegra_drive_pinmux_set_hsm(enum tegra_drive_pingroup pg, | ||
| 553 | enum tegra_hsm hsm) | ||
| 554 | { | ||
| 555 | unsigned long flags; | ||
| 556 | u32 reg; | ||
| 557 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) | ||
| 558 | return -ERANGE; | ||
| 559 | |||
| 560 | if (hsm != TEGRA_HSM_ENABLE && hsm != TEGRA_HSM_DISABLE) | ||
| 561 | return -EINVAL; | ||
| 562 | |||
| 563 | spin_lock_irqsave(&mux_lock, flags); | ||
| 564 | |||
| 565 | reg = pg_readl(drive_pingroups[pg].reg); | ||
| 566 | if (hsm == TEGRA_HSM_ENABLE) | ||
| 567 | reg |= (1 << 2); | ||
| 568 | else | ||
| 569 | reg &= ~(1 << 2); | ||
| 570 | pg_writel(reg, drive_pingroups[pg].reg); | ||
| 571 | |||
| 572 | spin_unlock_irqrestore(&mux_lock, flags); | ||
| 573 | |||
| 574 | return 0; | ||
| 575 | } | ||
| 576 | |||
| 577 | static int tegra_drive_pinmux_set_schmitt(enum tegra_drive_pingroup pg, | ||
| 578 | enum tegra_schmitt schmitt) | ||
| 579 | { | ||
| 580 | unsigned long flags; | ||
| 581 | u32 reg; | ||
| 582 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) | ||
| 583 | return -ERANGE; | ||
| 584 | |||
| 585 | if (schmitt != TEGRA_SCHMITT_ENABLE && schmitt != TEGRA_SCHMITT_DISABLE) | ||
| 586 | return -EINVAL; | ||
| 587 | |||
| 588 | spin_lock_irqsave(&mux_lock, flags); | ||
| 589 | |||
| 590 | reg = pg_readl(drive_pingroups[pg].reg); | ||
| 591 | if (schmitt == TEGRA_SCHMITT_ENABLE) | ||
| 592 | reg |= (1 << 3); | ||
| 593 | else | ||
| 594 | reg &= ~(1 << 3); | ||
| 595 | pg_writel(reg, drive_pingroups[pg].reg); | ||
| 596 | |||
| 597 | spin_unlock_irqrestore(&mux_lock, flags); | ||
| 598 | |||
| 599 | return 0; | ||
| 600 | } | ||
| 601 | |||
| 602 | static int tegra_drive_pinmux_set_drive(enum tegra_drive_pingroup pg, | ||
| 603 | enum tegra_drive drive) | ||
| 604 | { | ||
| 605 | unsigned long flags; | ||
| 606 | u32 reg; | ||
| 607 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) | ||
| 608 | return -ERANGE; | ||
| 609 | |||
| 610 | if (drive < 0 || drive >= TEGRA_MAX_DRIVE) | ||
| 611 | return -EINVAL; | ||
| 612 | |||
| 613 | spin_lock_irqsave(&mux_lock, flags); | ||
| 614 | |||
| 615 | reg = pg_readl(drive_pingroups[pg].reg); | ||
| 616 | reg &= ~(0x3 << 4); | ||
| 617 | reg |= drive << 4; | ||
| 618 | pg_writel(reg, drive_pingroups[pg].reg); | ||
| 619 | |||
| 620 | spin_unlock_irqrestore(&mux_lock, flags); | ||
| 621 | |||
| 622 | return 0; | ||
| 623 | } | ||
| 624 | |||
| 625 | static int tegra_drive_pinmux_set_pull_down(enum tegra_drive_pingroup pg, | ||
| 626 | enum tegra_pull_strength pull_down) | ||
| 627 | { | ||
| 628 | unsigned long flags; | ||
| 629 | u32 reg; | ||
| 630 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) | ||
| 631 | return -ERANGE; | ||
| 632 | |||
| 633 | if (pull_down < 0 || pull_down >= TEGRA_MAX_PULL) | ||
| 634 | return -EINVAL; | ||
| 635 | |||
| 636 | spin_lock_irqsave(&mux_lock, flags); | ||
| 637 | |||
| 638 | reg = pg_readl(drive_pingroups[pg].reg); | ||
| 639 | reg &= ~(0x1f << 12); | ||
| 640 | reg |= pull_down << 12; | ||
| 641 | pg_writel(reg, drive_pingroups[pg].reg); | ||
| 642 | |||
| 643 | spin_unlock_irqrestore(&mux_lock, flags); | ||
| 644 | |||
| 645 | return 0; | ||
| 646 | } | ||
| 647 | |||
| 648 | static int tegra_drive_pinmux_set_pull_up(enum tegra_drive_pingroup pg, | ||
| 649 | enum tegra_pull_strength pull_up) | ||
| 650 | { | ||
| 651 | unsigned long flags; | ||
| 652 | u32 reg; | ||
| 653 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) | ||
| 654 | return -ERANGE; | ||
| 655 | |||
| 656 | if (pull_up < 0 || pull_up >= TEGRA_MAX_PULL) | ||
| 657 | return -EINVAL; | ||
| 658 | |||
| 659 | spin_lock_irqsave(&mux_lock, flags); | ||
| 660 | |||
| 661 | reg = pg_readl(drive_pingroups[pg].reg); | ||
| 662 | reg &= ~(0x1f << 12); | ||
| 663 | reg |= pull_up << 12; | ||
| 664 | pg_writel(reg, drive_pingroups[pg].reg); | ||
| 665 | |||
| 666 | spin_unlock_irqrestore(&mux_lock, flags); | ||
| 667 | |||
| 668 | return 0; | ||
| 669 | } | ||
| 670 | |||
| 671 | static int tegra_drive_pinmux_set_slew_rising(enum tegra_drive_pingroup pg, | ||
| 672 | enum tegra_slew slew_rising) | ||
| 673 | { | ||
| 674 | unsigned long flags; | ||
| 675 | u32 reg; | ||
| 676 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) | ||
| 677 | return -ERANGE; | ||
| 678 | |||
| 679 | if (slew_rising < 0 || slew_rising >= TEGRA_MAX_SLEW) | ||
| 680 | return -EINVAL; | ||
| 681 | |||
| 682 | spin_lock_irqsave(&mux_lock, flags); | ||
| 683 | |||
| 684 | reg = pg_readl(drive_pingroups[pg].reg); | ||
| 685 | reg &= ~(0x3 << 28); | ||
| 686 | reg |= slew_rising << 28; | ||
| 687 | pg_writel(reg, drive_pingroups[pg].reg); | ||
| 688 | |||
| 689 | spin_unlock_irqrestore(&mux_lock, flags); | ||
| 690 | |||
| 691 | return 0; | ||
| 692 | } | ||
| 693 | |||
| 694 | static int tegra_drive_pinmux_set_slew_falling(enum tegra_drive_pingroup pg, | ||
| 695 | enum tegra_slew slew_falling) | ||
| 696 | { | ||
| 697 | unsigned long flags; | ||
| 698 | u32 reg; | ||
| 699 | if (pg < 0 || pg >= TEGRA_MAX_DRIVE_PINGROUP) | ||
| 700 | return -ERANGE; | ||
| 701 | |||
| 702 | if (slew_falling < 0 || slew_falling >= TEGRA_MAX_SLEW) | ||
| 703 | return -EINVAL; | ||
| 704 | |||
| 705 | spin_lock_irqsave(&mux_lock, flags); | ||
| 706 | |||
| 707 | reg = pg_readl(drive_pingroups[pg].reg); | ||
| 708 | reg &= ~(0x3 << 30); | ||
| 709 | reg |= slew_falling << 30; | ||
| 710 | pg_writel(reg, drive_pingroups[pg].reg); | ||
| 711 | |||
| 712 | spin_unlock_irqrestore(&mux_lock, flags); | ||
| 713 | |||
| 714 | return 0; | ||
| 715 | } | ||
| 716 | |||
| 717 | static void tegra_drive_pinmux_config_pingroup(enum tegra_drive_pingroup pingroup, | ||
| 718 | enum tegra_hsm hsm, | ||
| 719 | enum tegra_schmitt schmitt, | ||
| 720 | enum tegra_drive drive, | ||
| 721 | enum tegra_pull_strength pull_down, | ||
| 722 | enum tegra_pull_strength pull_up, | ||
| 723 | enum tegra_slew slew_rising, | ||
| 724 | enum tegra_slew slew_falling) | ||
| 725 | { | ||
| 726 | int err; | ||
| 727 | |||
| 728 | err = tegra_drive_pinmux_set_hsm(pingroup, hsm); | ||
| 729 | if (err < 0) | ||
| 730 | pr_err("pinmux: can't set pingroup %s hsm to %s: %d\n", | ||
| 731 | drive_pinmux_name(pingroup), | ||
| 732 | enable_name(hsm), err); | ||
| 733 | |||
| 734 | err = tegra_drive_pinmux_set_schmitt(pingroup, schmitt); | ||
| 735 | if (err < 0) | ||
| 736 | pr_err("pinmux: can't set pingroup %s schmitt to %s: %d\n", | ||
| 737 | drive_pinmux_name(pingroup), | ||
| 738 | enable_name(schmitt), err); | ||
| 739 | |||
| 740 | err = tegra_drive_pinmux_set_drive(pingroup, drive); | ||
| 741 | if (err < 0) | ||
| 742 | pr_err("pinmux: can't set pingroup %s drive to %s: %d\n", | ||
| 743 | drive_pinmux_name(pingroup), | ||
| 744 | drive_name(drive), err); | ||
| 745 | |||
| 746 | err = tegra_drive_pinmux_set_pull_down(pingroup, pull_down); | ||
| 747 | if (err < 0) | ||
| 748 | pr_err("pinmux: can't set pingroup %s pull down to %d: %d\n", | ||
| 749 | drive_pinmux_name(pingroup), | ||
| 750 | pull_down, err); | ||
| 751 | |||
| 752 | err = tegra_drive_pinmux_set_pull_up(pingroup, pull_up); | ||
| 753 | if (err < 0) | ||
| 754 | pr_err("pinmux: can't set pingroup %s pull up to %d: %d\n", | ||
| 755 | drive_pinmux_name(pingroup), | ||
| 756 | pull_up, err); | ||
| 757 | |||
| 758 | err = tegra_drive_pinmux_set_slew_rising(pingroup, slew_rising); | ||
| 759 | if (err < 0) | ||
| 760 | pr_err("pinmux: can't set pingroup %s rising slew to %s: %d\n", | ||
| 761 | drive_pinmux_name(pingroup), | ||
| 762 | slew_name(slew_rising), err); | ||
| 763 | |||
| 764 | err = tegra_drive_pinmux_set_slew_falling(pingroup, slew_falling); | ||
| 765 | if (err < 0) | ||
| 766 | pr_err("pinmux: can't set pingroup %s falling slew to %s: %d\n", | ||
| 767 | drive_pinmux_name(pingroup), | ||
| 768 | slew_name(slew_falling), err); | ||
| 769 | } | ||
| 770 | |||
| 771 | void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config, | ||
| 772 | int len) | ||
| 773 | { | ||
| 774 | int i; | ||
| 775 | |||
| 776 | for (i = 0; i < len; i++) | ||
| 777 | tegra_drive_pinmux_config_pingroup(config[i].pingroup, | ||
| 778 | config[i].hsm, | ||
| 779 | config[i].schmitt, | ||
| 780 | config[i].drive, | ||
| 781 | config[i].pull_down, | ||
| 782 | config[i].pull_up, | ||
| 783 | config[i].slew_rising, | ||
| 784 | config[i].slew_falling); | ||
| 785 | } | ||
| 786 | |||
| 787 | |||
| 788 | #ifdef CONFIG_DEBUG_FS | ||
| 789 | |||
| 790 | #include <linux/debugfs.h> | ||
| 791 | #include <linux/seq_file.h> | ||
| 792 | |||
| 793 | static void dbg_pad_field(struct seq_file *s, int len) | ||
| 794 | { | ||
| 795 | seq_putc(s, ','); | ||
| 796 | |||
| 797 | while (len-- > -1) | ||
| 798 | seq_putc(s, ' '); | ||
| 799 | } | ||
| 800 | |||
| 801 | static int dbg_pinmux_show(struct seq_file *s, void *unused) | ||
| 802 | { | ||
| 803 | int i; | ||
| 804 | int len; | ||
| 805 | |||
| 806 | for (i = 0; i < TEGRA_MAX_PINGROUP; i++) { | ||
| 807 | unsigned long tri; | ||
| 808 | unsigned long mux; | ||
| 809 | unsigned long pupd; | ||
| 810 | |||
| 811 | seq_printf(s, "\t{TEGRA_PINGROUP_%s", pingroups[i].name); | ||
| 812 | len = strlen(pingroups[i].name); | ||
| 813 | dbg_pad_field(s, 5 - len); | ||
| 814 | |||
| 815 | if (pingroups[i].mux_reg == REG_N) { | ||
| 816 | seq_printf(s, "TEGRA_MUX_NONE"); | ||
| 817 | len = strlen("NONE"); | ||
| 818 | } else { | ||
| 819 | mux = (pg_readl(TEGRA_PP_MUX_CTL(pingroups[i].mux_reg)) >> | ||
| 820 | pingroups[i].mux_bit) & 0x3; | ||
| 821 | if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) { | ||
| 822 | seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1); | ||
| 823 | len = 5; | ||
| 824 | } else { | ||
| 825 | seq_printf(s, "TEGRA_MUX_%s", | ||
| 826 | tegra_mux_names[pingroups[i].funcs[mux]]); | ||
| 827 | len = strlen(tegra_mux_names[pingroups[i].funcs[mux]]); | ||
| 828 | } | ||
| 829 | } | ||
| 830 | dbg_pad_field(s, 13-len); | ||
| 831 | |||
| 832 | if (pingroups[i].mux_reg == REG_N) { | ||
| 833 | seq_printf(s, "TEGRA_PUPD_NORMAL"); | ||
| 834 | len = strlen("NORMAL"); | ||
| 835 | } else { | ||
| 836 | pupd = (pg_readl(TEGRA_PP_PU_PD(pingroups[i].pupd_reg)) >> | ||
| 837 | pingroups[i].pupd_bit) & 0x3; | ||
| 838 | seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd)); | ||
| 839 | len = strlen(pupd_name(pupd)); | ||
| 840 | } | ||
| 841 | dbg_pad_field(s, 9 - len); | ||
| 842 | |||
| 843 | if (pingroups[i].tri_reg == REG_N) { | ||
| 844 | seq_printf(s, "TEGRA_TRI_NORMAL"); | ||
| 845 | } else { | ||
| 846 | tri = (pg_readl(TEGRA_TRI_STATE(pingroups[i].tri_reg)) >> | ||
| 847 | pingroups[i].tri_bit) & 0x1; | ||
| 848 | |||
| 849 | seq_printf(s, "TEGRA_TRI_%s", tri_name(tri)); | ||
| 850 | } | ||
| 851 | seq_printf(s, "},\n"); | ||
| 852 | } | ||
| 853 | return 0; | ||
| 854 | } | ||
| 855 | |||
| 856 | static int dbg_pinmux_open(struct inode *inode, struct file *file) | ||
| 857 | { | ||
| 858 | return single_open(file, dbg_pinmux_show, &inode->i_private); | ||
| 859 | } | ||
| 860 | |||
| 861 | static const struct file_operations debug_fops = { | ||
| 862 | .open = dbg_pinmux_open, | ||
| 863 | .read = seq_read, | ||
| 864 | .llseek = seq_lseek, | ||
| 865 | .release = single_release, | ||
| 866 | }; | ||
| 867 | |||
| 868 | static int dbg_drive_pinmux_show(struct seq_file *s, void *unused) | ||
| 869 | { | ||
| 870 | int i; | ||
| 871 | int len; | ||
| 872 | |||
| 873 | for (i = 0; i < TEGRA_MAX_DRIVE_PINGROUP; i++) { | ||
| 874 | u32 reg; | ||
| 875 | |||
| 876 | seq_printf(s, "\t{TEGRA_DRIVE_PINGROUP_%s", | ||
| 877 | drive_pingroups[i].name); | ||
| 878 | len = strlen(drive_pingroups[i].name); | ||
| 879 | dbg_pad_field(s, 7 - len); | ||
| 880 | |||
| 881 | |||
| 882 | reg = pg_readl(drive_pingroups[i].reg); | ||
| 883 | if (HSM_EN(reg)) { | ||
| 884 | seq_printf(s, "TEGRA_HSM_ENABLE"); | ||
| 885 | len = 16; | ||
| 886 | } else { | ||
| 887 | seq_printf(s, "TEGRA_HSM_DISABLE"); | ||
| 888 | len = 17; | ||
| 889 | } | ||
| 890 | dbg_pad_field(s, 17 - len); | ||
| 891 | |||
| 892 | if (SCHMT_EN(reg)) { | ||
| 893 | seq_printf(s, "TEGRA_SCHMITT_ENABLE"); | ||
| 894 | len = 21; | ||
| 895 | } else { | ||
| 896 | seq_printf(s, "TEGRA_SCHMITT_DISABLE"); | ||
| 897 | len = 22; | ||
| 898 | } | ||
| 899 | dbg_pad_field(s, 22 - len); | ||
| 900 | |||
| 901 | seq_printf(s, "TEGRA_DRIVE_%s", drive_name(LPMD(reg))); | ||
| 902 | len = strlen(drive_name(LPMD(reg))); | ||
| 903 | dbg_pad_field(s, 5 - len); | ||
| 904 | |||
| 905 | seq_printf(s, "TEGRA_PULL_%d", DRVDN(reg)); | ||
| 906 | len = DRVDN(reg) < 10 ? 1 : 2; | ||
| 907 | dbg_pad_field(s, 2 - len); | ||
| 908 | |||
| 909 | seq_printf(s, "TEGRA_PULL_%d", DRVUP(reg)); | ||
| 910 | len = DRVUP(reg) < 10 ? 1 : 2; | ||
| 911 | dbg_pad_field(s, 2 - len); | ||
| 912 | |||
| 913 | seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWR(reg))); | ||
| 914 | len = strlen(slew_name(SLWR(reg))); | ||
| 915 | dbg_pad_field(s, 7 - len); | ||
| 916 | |||
| 917 | seq_printf(s, "TEGRA_SLEW_%s", slew_name(SLWF(reg))); | ||
| 918 | |||
| 919 | seq_printf(s, "},\n"); | ||
| 920 | } | ||
| 921 | return 0; | ||
| 922 | } | ||
| 923 | |||
| 924 | static int dbg_drive_pinmux_open(struct inode *inode, struct file *file) | ||
| 925 | { | ||
| 926 | return single_open(file, dbg_drive_pinmux_show, &inode->i_private); | ||
| 927 | } | ||
| 928 | |||
| 929 | static const struct file_operations debug_drive_fops = { | ||
| 930 | .open = dbg_drive_pinmux_open, | ||
| 931 | .read = seq_read, | ||
| 932 | .llseek = seq_lseek, | ||
| 933 | .release = single_release, | ||
| 934 | }; | ||
| 935 | |||
| 936 | static int __init tegra_pinmux_debuginit(void) | ||
| 937 | { | ||
| 938 | (void) debugfs_create_file("tegra_pinmux", S_IRUGO, | ||
| 939 | NULL, NULL, &debug_fops); | ||
| 940 | (void) debugfs_create_file("tegra_pinmux_drive", S_IRUGO, | ||
| 941 | NULL, NULL, &debug_drive_fops); | ||
| 942 | return 0; | ||
| 943 | } | ||
| 944 | late_initcall(tegra_pinmux_debuginit); | ||
| 945 | #endif | ||
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c new file mode 100644 index 000000000000..1c0fd92cab39 --- /dev/null +++ b/arch/arm/mach-tegra/platsmp.c | |||
| @@ -0,0 +1,156 @@ | |||
| 1 | /* | ||
| 2 | * linux/arch/arm/mach-tegra/platsmp.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002 ARM Ltd. | ||
| 5 | * All Rights Reserved | ||
| 6 | * | ||
| 7 | * Copyright (C) 2009 Palm | ||
| 8 | * All Rights Reserved | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/errno.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/jiffies.h> | ||
| 19 | #include <linux/smp.h> | ||
| 20 | #include <linux/io.h> | ||
| 21 | |||
| 22 | #include <asm/cacheflush.h> | ||
| 23 | #include <mach/hardware.h> | ||
| 24 | #include <asm/mach-types.h> | ||
| 25 | #include <asm/localtimer.h> | ||
| 26 | #include <asm/smp_scu.h> | ||
| 27 | |||
| 28 | #include <mach/iomap.h> | ||
| 29 | |||
| 30 | extern void tegra_secondary_startup(void); | ||
| 31 | |||
| 32 | static DEFINE_SPINLOCK(boot_lock); | ||
| 33 | static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE); | ||
| 34 | |||
| 35 | #define EVP_CPU_RESET_VECTOR \ | ||
| 36 | (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100) | ||
| 37 | #define CLK_RST_CONTROLLER_CLK_CPU_CMPLX \ | ||
| 38 | (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x4c) | ||
| 39 | #define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \ | ||
| 40 | (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344) | ||
| 41 | |||
| 42 | void __cpuinit platform_secondary_init(unsigned int cpu) | ||
| 43 | { | ||
| 44 | trace_hardirqs_off(); | ||
| 45 | |||
| 46 | /* | ||
| 47 | * if any interrupts are already enabled for the primary | ||
| 48 | * core (e.g. timer irq), then they will not have been enabled | ||
| 49 | * for us: do so | ||
| 50 | */ | ||
| 51 | gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x100); | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Synchronise with the boot thread. | ||
| 55 | */ | ||
| 56 | spin_lock(&boot_lock); | ||
| 57 | spin_unlock(&boot_lock); | ||
| 58 | } | ||
| 59 | |||
| 60 | int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
| 61 | { | ||
| 62 | unsigned long old_boot_vector; | ||
| 63 | unsigned long boot_vector; | ||
| 64 | unsigned long timeout; | ||
| 65 | u32 reg; | ||
| 66 | |||
| 67 | /* | ||
| 68 | * set synchronisation state between this boot processor | ||
| 69 | * and the secondary one | ||
| 70 | */ | ||
| 71 | spin_lock(&boot_lock); | ||
| 72 | |||
| 73 | |||
| 74 | /* set the reset vector to point to the secondary_startup routine */ | ||
| 75 | |||
| 76 | boot_vector = virt_to_phys(tegra_secondary_startup); | ||
| 77 | old_boot_vector = readl(EVP_CPU_RESET_VECTOR); | ||
| 78 | writel(boot_vector, EVP_CPU_RESET_VECTOR); | ||
| 79 | |||
| 80 | /* enable cpu clock on cpu1 */ | ||
| 81 | reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX); | ||
| 82 | writel(reg & ~(1<<9), CLK_RST_CONTROLLER_CLK_CPU_CMPLX); | ||
| 83 | |||
| 84 | reg = (1<<13) | (1<<9) | (1<<5) | (1<<1); | ||
| 85 | writel(reg, CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR); | ||
| 86 | |||
| 87 | smp_wmb(); | ||
| 88 | flush_cache_all(); | ||
| 89 | |||
| 90 | /* unhalt the cpu */ | ||
| 91 | writel(0, IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + 0x14); | ||
| 92 | |||
| 93 | timeout = jiffies + (1 * HZ); | ||
| 94 | while (time_before(jiffies, timeout)) { | ||
| 95 | if (readl(EVP_CPU_RESET_VECTOR) != boot_vector) | ||
| 96 | break; | ||
| 97 | udelay(10); | ||
| 98 | } | ||
| 99 | |||
| 100 | /* put the old boot vector back */ | ||
| 101 | writel(old_boot_vector, EVP_CPU_RESET_VECTOR); | ||
| 102 | |||
| 103 | /* | ||
| 104 | * now the secondary core is starting up let it run its | ||
| 105 | * calibrations, then wait for it to finish | ||
| 106 | */ | ||
| 107 | spin_unlock(&boot_lock); | ||
| 108 | |||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | /* | ||
| 113 | * Initialise the CPU possible map early - this describes the CPUs | ||
| 114 | * which may be present or become present in the system. | ||
| 115 | */ | ||
| 116 | void __init smp_init_cpus(void) | ||
| 117 | { | ||
| 118 | unsigned int i, ncores = scu_get_core_count(scu_base); | ||
| 119 | |||
| 120 | for (i = 0; i < ncores; i++) | ||
| 121 | cpu_set(i, cpu_possible_map); | ||
| 122 | } | ||
| 123 | |||
| 124 | void __init smp_prepare_cpus(unsigned int max_cpus) | ||
| 125 | { | ||
| 126 | unsigned int ncores = scu_get_core_count(scu_base); | ||
| 127 | unsigned int cpu = smp_processor_id(); | ||
| 128 | int i; | ||
| 129 | |||
| 130 | smp_store_cpu_info(cpu); | ||
| 131 | |||
| 132 | /* | ||
| 133 | * are we trying to boot more cores than exist? | ||
| 134 | */ | ||
| 135 | if (max_cpus > ncores) | ||
| 136 | max_cpus = ncores; | ||
| 137 | |||
| 138 | /* | ||
| 139 | * Initialise the present map, which describes the set of CPUs | ||
| 140 | * actually populated at the present time. | ||
| 141 | */ | ||
| 142 | for (i = 0; i < max_cpus; i++) | ||
| 143 | set_cpu_present(i, true); | ||
| 144 | |||
| 145 | /* | ||
| 146 | * Initialise the SCU if there are more than one CPU and let | ||
| 147 | * them know where to start. Note that, on modern versions of | ||
| 148 | * MILO, the "poke" doesn't actually do anything until each | ||
| 149 | * individual core is sent a soft interrupt to get it out of | ||
| 150 | * WFI | ||
| 151 | */ | ||
| 152 | if (max_cpus > 1) { | ||
| 153 | percpu_timer_setup(); | ||
| 154 | scu_enable(scu_base); | ||
| 155 | } | ||
| 156 | } | ||
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c new file mode 100644 index 000000000000..426163231fff --- /dev/null +++ b/arch/arm/mach-tegra/tegra2_clocks.c | |||
| @@ -0,0 +1,1359 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-tegra/tegra2_clocks.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * | ||
| 9 | * This software is licensed under the terms of the GNU General Public | ||
| 10 | * License version 2, as published by the Free Software Foundation, and | ||
| 11 | * may be copied, distributed, and modified under those terms. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/list.h> | ||
| 23 | #include <linux/spinlock.h> | ||
| 24 | #include <linux/delay.h> | ||
| 25 | #include <linux/io.h> | ||
| 26 | #include <linux/hrtimer.h> | ||
| 27 | |||
| 28 | #include <asm/clkdev.h> | ||
| 29 | |||
| 30 | #include <mach/iomap.h> | ||
| 31 | |||
| 32 | #include "clock.h" | ||
| 33 | |||
| 34 | #define RST_DEVICES 0x004 | ||
| 35 | #define RST_DEVICES_SET 0x300 | ||
| 36 | #define RST_DEVICES_CLR 0x304 | ||
| 37 | |||
| 38 | #define CLK_OUT_ENB 0x010 | ||
| 39 | #define CLK_OUT_ENB_SET 0x320 | ||
| 40 | #define CLK_OUT_ENB_CLR 0x324 | ||
| 41 | |||
| 42 | #define OSC_CTRL 0x50 | ||
| 43 | #define OSC_CTRL_OSC_FREQ_MASK (3<<30) | ||
| 44 | #define OSC_CTRL_OSC_FREQ_13MHZ (0<<30) | ||
| 45 | #define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30) | ||
| 46 | #define OSC_CTRL_OSC_FREQ_12MHZ (2<<30) | ||
| 47 | #define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) | ||
| 48 | |||
| 49 | #define OSC_FREQ_DET 0x58 | ||
| 50 | #define OSC_FREQ_DET_TRIG (1<<31) | ||
| 51 | |||
| 52 | #define OSC_FREQ_DET_STATUS 0x5C | ||
| 53 | #define OSC_FREQ_DET_BUSY (1<<31) | ||
| 54 | #define OSC_FREQ_DET_CNT_MASK 0xFFFF | ||
| 55 | |||
| 56 | #define PERIPH_CLK_SOURCE_MASK (3<<30) | ||
| 57 | #define PERIPH_CLK_SOURCE_SHIFT 30 | ||
| 58 | #define PERIPH_CLK_SOURCE_ENABLE (1<<28) | ||
| 59 | #define PERIPH_CLK_SOURCE_DIV_MASK 0xFF | ||
| 60 | #define PERIPH_CLK_SOURCE_DIV_SHIFT 0 | ||
| 61 | |||
| 62 | #define PLL_BASE 0x0 | ||
| 63 | #define PLL_BASE_BYPASS (1<<31) | ||
| 64 | #define PLL_BASE_ENABLE (1<<30) | ||
| 65 | #define PLL_BASE_REF_ENABLE (1<<29) | ||
| 66 | #define PLL_BASE_OVERRIDE (1<<28) | ||
| 67 | #define PLL_BASE_LOCK (1<<27) | ||
| 68 | #define PLL_BASE_DIVP_MASK (0x7<<20) | ||
| 69 | #define PLL_BASE_DIVP_SHIFT 20 | ||
| 70 | #define PLL_BASE_DIVN_MASK (0x3FF<<8) | ||
| 71 | #define PLL_BASE_DIVN_SHIFT 8 | ||
| 72 | #define PLL_BASE_DIVM_MASK (0x1F) | ||
| 73 | #define PLL_BASE_DIVM_SHIFT 0 | ||
| 74 | |||
| 75 | #define PLL_OUT_RATIO_MASK (0xFF<<8) | ||
| 76 | #define PLL_OUT_RATIO_SHIFT 8 | ||
| 77 | #define PLL_OUT_OVERRIDE (1<<2) | ||
| 78 | #define PLL_OUT_CLKEN (1<<1) | ||
| 79 | #define PLL_OUT_RESET_DISABLE (1<<0) | ||
| 80 | |||
| 81 | #define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc) | ||
| 82 | #define PLL_MISC_DCCON_SHIFT 20 | ||
| 83 | #define PLL_MISC_LOCK_ENABLE (1<<18) | ||
| 84 | #define PLL_MISC_CPCON_SHIFT 8 | ||
| 85 | #define PLL_MISC_CPCON_MASK (0xF<<PLL_MISC_CPCON_SHIFT) | ||
| 86 | #define PLL_MISC_LFCON_SHIFT 4 | ||
| 87 | #define PLL_MISC_LFCON_MASK (0xF<<PLL_MISC_LFCON_SHIFT) | ||
| 88 | #define PLL_MISC_VCOCON_SHIFT 0 | ||
| 89 | #define PLL_MISC_VCOCON_MASK (0xF<<PLL_MISC_VCOCON_SHIFT) | ||
| 90 | |||
| 91 | #define PLLD_MISC_CLKENABLE (1<<30) | ||
| 92 | #define PLLD_MISC_DIV_RST (1<<23) | ||
| 93 | #define PLLD_MISC_DCCON_SHIFT 12 | ||
| 94 | |||
| 95 | #define PERIPH_CLK_TO_ENB_REG(c) ((c->clk_num / 32) * 4) | ||
| 96 | #define PERIPH_CLK_TO_ENB_SET_REG(c) ((c->clk_num / 32) * 8) | ||
| 97 | #define PERIPH_CLK_TO_ENB_BIT(c) (1 << (c->clk_num % 32)) | ||
| 98 | |||
| 99 | #define SUPER_CLK_MUX 0x00 | ||
| 100 | #define SUPER_STATE_SHIFT 28 | ||
| 101 | #define SUPER_STATE_MASK (0xF << SUPER_STATE_SHIFT) | ||
| 102 | #define SUPER_STATE_STANDBY (0x0 << SUPER_STATE_SHIFT) | ||
| 103 | #define SUPER_STATE_IDLE (0x1 << SUPER_STATE_SHIFT) | ||
| 104 | #define SUPER_STATE_RUN (0x2 << SUPER_STATE_SHIFT) | ||
| 105 | #define SUPER_STATE_IRQ (0x3 << SUPER_STATE_SHIFT) | ||
| 106 | #define SUPER_STATE_FIQ (0x4 << SUPER_STATE_SHIFT) | ||
| 107 | #define SUPER_SOURCE_MASK 0xF | ||
| 108 | #define SUPER_FIQ_SOURCE_SHIFT 12 | ||
| 109 | #define SUPER_IRQ_SOURCE_SHIFT 8 | ||
| 110 | #define SUPER_RUN_SOURCE_SHIFT 4 | ||
| 111 | #define SUPER_IDLE_SOURCE_SHIFT 0 | ||
| 112 | |||
| 113 | #define SUPER_CLK_DIVIDER 0x04 | ||
| 114 | |||
| 115 | #define BUS_CLK_DISABLE (1<<3) | ||
| 116 | #define BUS_CLK_DIV_MASK 0x3 | ||
| 117 | |||
| 118 | static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE); | ||
| 119 | |||
| 120 | #define clk_writel(value, reg) \ | ||
| 121 | __raw_writel(value, (u32)reg_clk_base + (reg)) | ||
| 122 | #define clk_readl(reg) \ | ||
| 123 | __raw_readl((u32)reg_clk_base + (reg)) | ||
| 124 | |||
| 125 | unsigned long clk_measure_input_freq(void) | ||
| 126 | { | ||
| 127 | u32 clock_autodetect; | ||
| 128 | clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET); | ||
| 129 | do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY); | ||
| 130 | clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS); | ||
| 131 | if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) { | ||
| 132 | return 12000000; | ||
| 133 | } else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) { | ||
| 134 | return 13000000; | ||
| 135 | } else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) { | ||
| 136 | return 19200000; | ||
| 137 | } else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) { | ||
| 138 | return 26000000; | ||
| 139 | } else { | ||
| 140 | pr_err("%s: Unexpected clock autodetect value %d", __func__, clock_autodetect); | ||
| 141 | BUG(); | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | static int clk_div71_get_divider(struct clk *c, unsigned long rate) | ||
| 147 | { | ||
| 148 | unsigned long divider_u71; | ||
| 149 | |||
| 150 | divider_u71 = DIV_ROUND_UP(c->rate * 2, rate); | ||
| 151 | |||
| 152 | if (divider_u71 - 2 > 255 || divider_u71 - 2 < 0) | ||
| 153 | return -EINVAL; | ||
| 154 | |||
| 155 | return divider_u71 - 2; | ||
| 156 | } | ||
| 157 | |||
| 158 | static unsigned long tegra2_clk_recalculate_rate(struct clk *c) | ||
| 159 | { | ||
| 160 | unsigned long rate; | ||
| 161 | rate = c->parent->rate; | ||
| 162 | |||
| 163 | if (c->mul != 0 && c->div != 0) | ||
| 164 | c->rate = rate * c->mul / c->div; | ||
| 165 | else | ||
| 166 | c->rate = rate; | ||
| 167 | return c->rate; | ||
| 168 | } | ||
| 169 | |||
| 170 | |||
| 171 | /* clk_m functions */ | ||
| 172 | static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c) | ||
| 173 | { | ||
| 174 | u32 auto_clock_control = clk_readl(OSC_CTRL) & ~OSC_CTRL_OSC_FREQ_MASK; | ||
| 175 | |||
| 176 | c->rate = clk_measure_input_freq(); | ||
| 177 | switch (c->rate) { | ||
| 178 | case 12000000: | ||
| 179 | auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ; | ||
| 180 | break; | ||
| 181 | case 13000000: | ||
| 182 | auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ; | ||
| 183 | break; | ||
| 184 | case 19200000: | ||
| 185 | auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ; | ||
| 186 | break; | ||
| 187 | case 26000000: | ||
| 188 | auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ; | ||
| 189 | break; | ||
| 190 | default: | ||
| 191 | pr_err("%s: Unexpected clock rate %ld", __func__, c->rate); | ||
| 192 | BUG(); | ||
| 193 | } | ||
| 194 | clk_writel(auto_clock_control, OSC_CTRL); | ||
| 195 | return c->rate; | ||
| 196 | } | ||
| 197 | |||
| 198 | static void tegra2_clk_m_init(struct clk *c) | ||
| 199 | { | ||
| 200 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
| 201 | tegra2_clk_m_autodetect_rate(c); | ||
| 202 | } | ||
| 203 | |||
| 204 | static int tegra2_clk_m_enable(struct clk *c) | ||
| 205 | { | ||
| 206 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | static void tegra2_clk_m_disable(struct clk *c) | ||
| 211 | { | ||
| 212 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
| 213 | BUG(); | ||
| 214 | } | ||
| 215 | |||
| 216 | static struct clk_ops tegra_clk_m_ops = { | ||
| 217 | .init = tegra2_clk_m_init, | ||
| 218 | .enable = tegra2_clk_m_enable, | ||
| 219 | .disable = tegra2_clk_m_disable, | ||
| 220 | }; | ||
| 221 | |||
| 222 | /* super clock functions */ | ||
| 223 | /* "super clocks" on tegra have two-stage muxes and a clock skipping | ||
| 224 | * super divider. We will ignore the clock skipping divider, since we | ||
| 225 | * can't lower the voltage when using the clock skip, but we can if we | ||
| 226 | * lower the PLL frequency. | ||
| 227 | */ | ||
| 228 | static void tegra2_super_clk_init(struct clk *c) | ||
| 229 | { | ||
| 230 | u32 val; | ||
| 231 | int source; | ||
| 232 | int shift; | ||
| 233 | const struct clk_mux_sel *sel; | ||
| 234 | val = clk_readl(c->reg + SUPER_CLK_MUX); | ||
| 235 | c->state = ON; | ||
| 236 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && | ||
| 237 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); | ||
| 238 | shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ? | ||
| 239 | SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; | ||
| 240 | source = (val >> shift) & SUPER_SOURCE_MASK; | ||
| 241 | for (sel = c->inputs; sel->input != NULL; sel++) { | ||
| 242 | if (sel->value == source) | ||
| 243 | break; | ||
| 244 | } | ||
| 245 | BUG_ON(sel->input == NULL); | ||
| 246 | c->parent = sel->input; | ||
| 247 | tegra2_clk_recalculate_rate(c); | ||
| 248 | } | ||
| 249 | |||
| 250 | static int tegra2_super_clk_enable(struct clk *c) | ||
| 251 | { | ||
| 252 | clk_writel(0, c->reg + SUPER_CLK_DIVIDER); | ||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | static void tegra2_super_clk_disable(struct clk *c) | ||
| 257 | { | ||
| 258 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
| 259 | |||
| 260 | /* oops - don't disable the CPU clock! */ | ||
| 261 | BUG(); | ||
| 262 | } | ||
| 263 | |||
| 264 | static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p) | ||
| 265 | { | ||
| 266 | u32 val; | ||
| 267 | const struct clk_mux_sel *sel; | ||
| 268 | int shift; | ||
| 269 | val = clk_readl(c->reg + SUPER_CLK_MUX);; | ||
| 270 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && | ||
| 271 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); | ||
| 272 | shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ? | ||
| 273 | SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; | ||
| 274 | for (sel = c->inputs; sel->input != NULL; sel++) { | ||
| 275 | if (sel->input == p) { | ||
| 276 | clk_reparent(c, p); | ||
| 277 | val &= ~(SUPER_SOURCE_MASK << shift); | ||
| 278 | val |= sel->value << shift; | ||
| 279 | clk_writel(val, c->reg); | ||
| 280 | c->rate = c->parent->rate; | ||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | } | ||
| 284 | return -EINVAL; | ||
| 285 | } | ||
| 286 | |||
| 287 | static struct clk_ops tegra_super_ops = { | ||
| 288 | .init = tegra2_super_clk_init, | ||
| 289 | .enable = tegra2_super_clk_enable, | ||
| 290 | .disable = tegra2_super_clk_disable, | ||
| 291 | .set_parent = tegra2_super_clk_set_parent, | ||
| 292 | .recalculate_rate = tegra2_clk_recalculate_rate, | ||
| 293 | }; | ||
| 294 | |||
| 295 | /* bus clock functions */ | ||
| 296 | static void tegra2_bus_clk_init(struct clk *c) | ||
| 297 | { | ||
| 298 | u32 val = clk_readl(c->reg); | ||
| 299 | c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; | ||
| 300 | c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1; | ||
| 301 | c->mul = 1; | ||
| 302 | tegra2_clk_recalculate_rate(c); | ||
| 303 | } | ||
| 304 | |||
| 305 | static int tegra2_bus_clk_enable(struct clk *c) | ||
| 306 | { | ||
| 307 | u32 val = clk_readl(c->reg); | ||
| 308 | val &= ~(BUS_CLK_DISABLE << c->reg_shift); | ||
| 309 | clk_writel(val, c->reg); | ||
| 310 | return 0; | ||
| 311 | } | ||
| 312 | |||
| 313 | static void tegra2_bus_clk_disable(struct clk *c) | ||
| 314 | { | ||
| 315 | u32 val = clk_readl(c->reg); | ||
| 316 | val |= BUS_CLK_DISABLE << c->reg_shift; | ||
| 317 | clk_writel(val, c->reg); | ||
| 318 | } | ||
| 319 | |||
| 320 | static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate) | ||
| 321 | { | ||
| 322 | u32 val = clk_readl(c->reg); | ||
| 323 | unsigned long parent_rate = c->parent->rate; | ||
| 324 | int i; | ||
| 325 | for (i = 1; i <= 4; i++) { | ||
| 326 | if (rate == parent_rate / i) { | ||
| 327 | val &= ~(BUS_CLK_DIV_MASK << c->reg_shift); | ||
| 328 | val |= (i - 1) << c->reg_shift; | ||
| 329 | clk_writel(val, c->reg); | ||
| 330 | c->div = i; | ||
| 331 | c->mul = 1; | ||
| 332 | return 0; | ||
| 333 | } | ||
| 334 | } | ||
| 335 | return -EINVAL; | ||
| 336 | } | ||
| 337 | |||
| 338 | static struct clk_ops tegra_bus_ops = { | ||
| 339 | .init = tegra2_bus_clk_init, | ||
| 340 | .enable = tegra2_bus_clk_enable, | ||
| 341 | .disable = tegra2_bus_clk_disable, | ||
| 342 | .set_rate = tegra2_bus_clk_set_rate, | ||
| 343 | .recalculate_rate = tegra2_clk_recalculate_rate, | ||
| 344 | }; | ||
| 345 | |||
| 346 | /* PLL Functions */ | ||
| 347 | static unsigned long tegra2_pll_clk_recalculate_rate(struct clk *c) | ||
| 348 | { | ||
| 349 | u64 rate; | ||
| 350 | rate = c->parent->rate; | ||
| 351 | rate *= c->n; | ||
| 352 | do_div(rate, c->m); | ||
| 353 | if (c->p == 2) | ||
| 354 | rate >>= 1; | ||
| 355 | c->rate = rate; | ||
| 356 | return c->rate; | ||
| 357 | } | ||
| 358 | |||
| 359 | static int tegra2_pll_clk_wait_for_lock(struct clk *c) | ||
| 360 | { | ||
| 361 | ktime_t before; | ||
| 362 | |||
| 363 | before = ktime_get(); | ||
| 364 | while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) { | ||
| 365 | if (ktime_us_delta(ktime_get(), before) > 5000) { | ||
| 366 | pr_err("Timed out waiting for lock bit on pll %s", | ||
| 367 | c->name); | ||
| 368 | return -1; | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | |||
| 375 | static void tegra2_pll_clk_init(struct clk *c) | ||
| 376 | { | ||
| 377 | u32 val = clk_readl(c->reg + PLL_BASE); | ||
| 378 | |||
| 379 | c->state = (val & PLL_BASE_ENABLE) ? ON : OFF; | ||
| 380 | |||
| 381 | if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) { | ||
| 382 | pr_warning("Clock %s has unknown fixed frequency\n", c->name); | ||
| 383 | c->n = 1; | ||
| 384 | c->m = 0; | ||
| 385 | c->p = 1; | ||
| 386 | } else if (val & PLL_BASE_BYPASS) { | ||
| 387 | c->n = 1; | ||
| 388 | c->m = 1; | ||
| 389 | c->p = 1; | ||
| 390 | } else { | ||
| 391 | c->n = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT; | ||
| 392 | c->m = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT; | ||
| 393 | c->p = (val & PLL_BASE_DIVP_MASK) ? 2 : 1; | ||
| 394 | } | ||
| 395 | |||
| 396 | val = clk_readl(c->reg + PLL_MISC(c)); | ||
| 397 | if (c->flags & PLL_HAS_CPCON) | ||
| 398 | c->cpcon = (val & PLL_MISC_CPCON_MASK) >> PLL_MISC_CPCON_SHIFT; | ||
| 399 | |||
| 400 | tegra2_pll_clk_recalculate_rate(c); | ||
| 401 | } | ||
| 402 | |||
| 403 | static int tegra2_pll_clk_enable(struct clk *c) | ||
| 404 | { | ||
| 405 | u32 val; | ||
| 406 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
| 407 | |||
| 408 | val = clk_readl(c->reg + PLL_BASE); | ||
| 409 | val &= ~PLL_BASE_BYPASS; | ||
| 410 | val |= PLL_BASE_ENABLE; | ||
| 411 | clk_writel(val, c->reg + PLL_BASE); | ||
| 412 | |||
| 413 | val = clk_readl(c->reg + PLL_MISC(c)); | ||
| 414 | val |= PLL_MISC_LOCK_ENABLE; | ||
| 415 | clk_writel(val, c->reg + PLL_MISC(c)); | ||
| 416 | |||
| 417 | tegra2_pll_clk_wait_for_lock(c); | ||
| 418 | |||
| 419 | return 0; | ||
| 420 | } | ||
| 421 | |||
| 422 | static void tegra2_pll_clk_disable(struct clk *c) | ||
| 423 | { | ||
| 424 | u32 val; | ||
| 425 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
| 426 | |||
| 427 | val = clk_readl(c->reg); | ||
| 428 | val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE); | ||
| 429 | clk_writel(val, c->reg); | ||
| 430 | } | ||
| 431 | |||
| 432 | static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate) | ||
| 433 | { | ||
| 434 | u32 val; | ||
| 435 | unsigned long input_rate; | ||
| 436 | const struct clk_pll_table *sel; | ||
| 437 | |||
| 438 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | ||
| 439 | BUG_ON(c->refcnt != 0); | ||
| 440 | |||
| 441 | input_rate = c->parent->rate; | ||
| 442 | for (sel = c->pll_table; sel->input_rate != 0; sel++) { | ||
| 443 | if (sel->input_rate == input_rate && sel->output_rate == rate) { | ||
| 444 | c->n = sel->n; | ||
| 445 | c->m = sel->m; | ||
| 446 | c->p = sel->p; | ||
| 447 | c->cpcon = sel->cpcon; | ||
| 448 | |||
| 449 | val = clk_readl(c->reg + PLL_BASE); | ||
| 450 | if (c->flags & PLL_FIXED) | ||
| 451 | val |= PLL_BASE_OVERRIDE; | ||
| 452 | val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK | | ||
| 453 | PLL_BASE_DIVM_MASK); | ||
| 454 | val |= (c->m << PLL_BASE_DIVM_SHIFT) | | ||
| 455 | (c->n << PLL_BASE_DIVN_SHIFT); | ||
| 456 | BUG_ON(c->p > 2); | ||
| 457 | if (c->p == 2) | ||
| 458 | val |= 1 << PLL_BASE_DIVP_SHIFT; | ||
| 459 | clk_writel(val, c->reg + PLL_BASE); | ||
| 460 | |||
| 461 | if (c->flags & PLL_HAS_CPCON) { | ||
| 462 | val = c->cpcon << PLL_MISC_CPCON_SHIFT; | ||
| 463 | val |= PLL_MISC_LOCK_ENABLE; | ||
| 464 | clk_writel(val, c->reg + PLL_MISC(c)); | ||
| 465 | } | ||
| 466 | |||
| 467 | if (c->state == ON) | ||
| 468 | tegra2_pll_clk_enable(c); | ||
| 469 | |||
| 470 | c->rate = rate; | ||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | return -EINVAL; | ||
| 475 | } | ||
| 476 | |||
| 477 | static struct clk_ops tegra_pll_ops = { | ||
| 478 | .init = tegra2_pll_clk_init, | ||
| 479 | .enable = tegra2_pll_clk_enable, | ||
| 480 | .disable = tegra2_pll_clk_disable, | ||
| 481 | .set_rate = tegra2_pll_clk_set_rate, | ||
| 482 | .recalculate_rate = tegra2_pll_clk_recalculate_rate, | ||
| 483 | }; | ||
| 484 | |||
| 485 | /* Clock divider ops */ | ||
| 486 | static void tegra2_pll_div_clk_init(struct clk *c) | ||
| 487 | { | ||
| 488 | u32 val = clk_readl(c->reg); | ||
| 489 | u32 divu71; | ||
| 490 | val >>= c->reg_shift; | ||
| 491 | c->state = (val & PLL_OUT_CLKEN) ? ON : OFF; | ||
| 492 | if (!(val & PLL_OUT_RESET_DISABLE)) | ||
| 493 | c->state = OFF; | ||
| 494 | |||
| 495 | if (c->flags & DIV_U71) { | ||
| 496 | divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT; | ||
| 497 | c->div = (divu71 + 2); | ||
| 498 | c->mul = 2; | ||
| 499 | } else if (c->flags & DIV_2) { | ||
| 500 | c->div = 2; | ||
| 501 | c->mul = 1; | ||
| 502 | } else { | ||
| 503 | c->div = 1; | ||
| 504 | c->mul = 1; | ||
| 505 | } | ||
| 506 | |||
| 507 | tegra2_clk_recalculate_rate(c); | ||
| 508 | } | ||
| 509 | |||
| 510 | static int tegra2_pll_div_clk_enable(struct clk *c) | ||
| 511 | { | ||
| 512 | u32 val; | ||
| 513 | u32 new_val; | ||
| 514 | |||
| 515 | pr_debug("%s: %s\n", __func__, c->name); | ||
| 516 | if (c->flags & DIV_U71) { | ||
| 517 | val = clk_readl(c->reg); | ||
| 518 | new_val = val >> c->reg_shift; | ||
| 519 | new_val &= 0xFFFF; | ||
| 520 | |||
| 521 | new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE; | ||
| 522 | |||
| 523 | val &= ~(0xFFFF << c->reg_shift); | ||
| 524 | val |= new_val << c->reg_shift; | ||
| 525 | clk_writel(val, c->reg); | ||
| 526 | return 0; | ||
| 527 | } else if (c->flags & DIV_2) { | ||
| 528 | BUG_ON(!(c->flags & PLLD)); | ||
| 529 | val = clk_readl(c->reg); | ||
| 530 | val &= ~PLLD_MISC_DIV_RST; | ||
| 531 | clk_writel(val, c->reg); | ||
| 532 | return 0; | ||
| 533 | } | ||
| 534 | return -EINVAL; | ||
| 535 | } | ||
| 536 | |||
| 537 | static void tegra2_pll_div_clk_disable(struct clk *c) | ||
| 538 | { | ||
| 539 | u32 val; | ||
| 540 | u32 new_val; | ||
| 541 | |||
| 542 | pr_debug("%s: %s\n", __func__, c->name); | ||
| 543 | if (c->flags & DIV_U71) { | ||
| 544 | val = clk_readl(c->reg); | ||
| 545 | new_val = val >> c->reg_shift; | ||
| 546 | new_val &= 0xFFFF; | ||
| 547 | |||
| 548 | new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE); | ||
| 549 | |||
| 550 | val &= ~(0xFFFF << c->reg_shift); | ||
| 551 | val |= new_val << c->reg_shift; | ||
| 552 | clk_writel(val, c->reg); | ||
| 553 | } else if (c->flags & DIV_2) { | ||
| 554 | BUG_ON(!(c->flags & PLLD)); | ||
| 555 | val = clk_readl(c->reg); | ||
| 556 | val |= PLLD_MISC_DIV_RST; | ||
| 557 | clk_writel(val, c->reg); | ||
| 558 | } | ||
| 559 | } | ||
| 560 | |||
| 561 | static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | ||
| 562 | { | ||
| 563 | u32 val; | ||
| 564 | u32 new_val; | ||
| 565 | int divider_u71; | ||
| 566 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | ||
| 567 | if (c->flags & DIV_U71) { | ||
| 568 | divider_u71 = clk_div71_get_divider(c->parent, rate); | ||
| 569 | if (divider_u71 >= 0) { | ||
| 570 | val = clk_readl(c->reg); | ||
| 571 | new_val = val >> c->reg_shift; | ||
| 572 | new_val &= 0xFFFF; | ||
| 573 | if (c->flags & DIV_U71_FIXED) | ||
| 574 | new_val |= PLL_OUT_OVERRIDE; | ||
| 575 | new_val &= ~PLL_OUT_RATIO_MASK; | ||
| 576 | new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT; | ||
| 577 | |||
| 578 | val &= ~(0xFFFF << c->reg_shift); | ||
| 579 | val |= new_val << c->reg_shift; | ||
| 580 | clk_writel(val, c->reg); | ||
| 581 | c->div = divider_u71 + 2; | ||
| 582 | c->mul = 2; | ||
| 583 | tegra2_clk_recalculate_rate(c); | ||
| 584 | return 0; | ||
| 585 | } | ||
| 586 | } else if (c->flags & DIV_2) { | ||
| 587 | if (c->parent->rate == rate * 2) { | ||
| 588 | c->rate = rate; | ||
| 589 | return 0; | ||
| 590 | } | ||
| 591 | } | ||
| 592 | return -EINVAL; | ||
| 593 | } | ||
| 594 | |||
| 595 | |||
| 596 | static struct clk_ops tegra_pll_div_ops = { | ||
| 597 | .init = tegra2_pll_div_clk_init, | ||
| 598 | .enable = tegra2_pll_div_clk_enable, | ||
| 599 | .disable = tegra2_pll_div_clk_disable, | ||
| 600 | .set_rate = tegra2_pll_div_clk_set_rate, | ||
| 601 | .recalculate_rate = tegra2_clk_recalculate_rate, | ||
| 602 | }; | ||
| 603 | |||
| 604 | /* Periph clk ops */ | ||
| 605 | |||
| 606 | static void tegra2_periph_clk_init(struct clk *c) | ||
| 607 | { | ||
| 608 | u32 val = clk_readl(c->reg); | ||
| 609 | const struct clk_mux_sel *mux = 0; | ||
| 610 | const struct clk_mux_sel *sel; | ||
| 611 | if (c->flags & MUX) { | ||
| 612 | for (sel = c->inputs; sel->input != NULL; sel++) { | ||
| 613 | if (val >> PERIPH_CLK_SOURCE_SHIFT == sel->value) | ||
| 614 | mux = sel; | ||
| 615 | } | ||
| 616 | BUG_ON(!mux); | ||
| 617 | |||
| 618 | c->parent = mux->input; | ||
| 619 | } else { | ||
| 620 | c->parent = c->inputs[0].input; | ||
| 621 | } | ||
| 622 | |||
| 623 | if (c->flags & DIV_U71) { | ||
| 624 | u32 divu71 = val & PERIPH_CLK_SOURCE_DIV_MASK; | ||
| 625 | c->div = divu71 + 2; | ||
| 626 | c->mul = 2; | ||
| 627 | } else { | ||
| 628 | c->div = 1; | ||
| 629 | c->mul = 1; | ||
| 630 | } | ||
| 631 | |||
| 632 | c->state = ON; | ||
| 633 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & | ||
| 634 | PERIPH_CLK_TO_ENB_BIT(c))) | ||
| 635 | c->state = OFF; | ||
| 636 | if (!(c->flags & PERIPH_NO_RESET)) | ||
| 637 | if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & | ||
| 638 | PERIPH_CLK_TO_ENB_BIT(c)) | ||
| 639 | c->state = OFF; | ||
| 640 | tegra2_clk_recalculate_rate(c); | ||
| 641 | } | ||
| 642 | |||
| 643 | static int tegra2_periph_clk_enable(struct clk *c) | ||
| 644 | { | ||
| 645 | u32 val; | ||
| 646 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
| 647 | |||
| 648 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | ||
| 649 | CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); | ||
| 650 | if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET)) | ||
| 651 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | ||
| 652 | RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); | ||
| 653 | if (c->flags & PERIPH_EMC_ENB) { | ||
| 654 | /* The EMC peripheral clock has 2 extra enable bits */ | ||
| 655 | /* FIXME: Do they need to be disabled? */ | ||
| 656 | val = clk_readl(c->reg); | ||
| 657 | val |= 0x3 << 24; | ||
| 658 | clk_writel(val, c->reg); | ||
| 659 | } | ||
| 660 | return 0; | ||
| 661 | } | ||
| 662 | |||
| 663 | static void tegra2_periph_clk_disable(struct clk *c) | ||
| 664 | { | ||
| 665 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
| 666 | |||
| 667 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | ||
| 668 | CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); | ||
| 669 | } | ||
| 670 | |||
| 671 | void tegra2_periph_reset_deassert(struct clk *c) | ||
| 672 | { | ||
| 673 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
| 674 | if (!(c->flags & PERIPH_NO_RESET)) | ||
| 675 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | ||
| 676 | RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); | ||
| 677 | } | ||
| 678 | |||
| 679 | void tegra2_periph_reset_assert(struct clk *c) | ||
| 680 | { | ||
| 681 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
| 682 | if (!(c->flags & PERIPH_NO_RESET)) | ||
| 683 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | ||
| 684 | RST_DEVICES_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); | ||
| 685 | } | ||
| 686 | |||
| 687 | |||
| 688 | static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p) | ||
| 689 | { | ||
| 690 | u32 val; | ||
| 691 | const struct clk_mux_sel *sel; | ||
| 692 | pr_debug("%s: %s %s\n", __func__, c->name, p->name); | ||
| 693 | for (sel = c->inputs; sel->input != NULL; sel++) { | ||
| 694 | if (sel->input == p) { | ||
| 695 | clk_reparent(c, p); | ||
| 696 | val = clk_readl(c->reg); | ||
| 697 | val &= ~PERIPH_CLK_SOURCE_MASK; | ||
| 698 | val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT; | ||
| 699 | clk_writel(val, c->reg); | ||
| 700 | c->rate = c->parent->rate; | ||
| 701 | return 0; | ||
| 702 | } | ||
| 703 | } | ||
| 704 | |||
| 705 | return -EINVAL; | ||
| 706 | } | ||
| 707 | |||
| 708 | static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate) | ||
| 709 | { | ||
| 710 | u32 val; | ||
| 711 | int divider_u71; | ||
| 712 | pr_debug("%s: %lu\n", __func__, rate); | ||
| 713 | if (c->flags & DIV_U71) { | ||
| 714 | divider_u71 = clk_div71_get_divider(c->parent, rate); | ||
| 715 | if (divider_u71 >= 0) { | ||
| 716 | val = clk_readl(c->reg); | ||
| 717 | val &= ~PERIPH_CLK_SOURCE_DIV_MASK; | ||
| 718 | val |= divider_u71; | ||
| 719 | clk_writel(val, c->reg); | ||
| 720 | c->div = divider_u71 + 2; | ||
| 721 | c->mul = 2; | ||
| 722 | tegra2_clk_recalculate_rate(c); | ||
| 723 | return 0; | ||
| 724 | } | ||
| 725 | } | ||
| 726 | return -EINVAL; | ||
| 727 | } | ||
| 728 | |||
| 729 | static struct clk_ops tegra_periph_clk_ops = { | ||
| 730 | .init = &tegra2_periph_clk_init, | ||
| 731 | .enable = &tegra2_periph_clk_enable, | ||
| 732 | .disable = &tegra2_periph_clk_disable, | ||
| 733 | .set_parent = &tegra2_periph_clk_set_parent, | ||
| 734 | .set_rate = &tegra2_periph_clk_set_rate, | ||
| 735 | .recalculate_rate = &tegra2_clk_recalculate_rate, | ||
| 736 | }; | ||
| 737 | |||
| 738 | /* Clock doubler ops */ | ||
| 739 | static void tegra2_clk_double_init(struct clk *c) | ||
| 740 | { | ||
| 741 | c->mul = 2; | ||
| 742 | c->div = 1; | ||
| 743 | c->state = ON; | ||
| 744 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & | ||
| 745 | PERIPH_CLK_TO_ENB_BIT(c))) | ||
| 746 | c->state = OFF; | ||
| 747 | tegra2_clk_recalculate_rate(c); | ||
| 748 | }; | ||
| 749 | |||
| 750 | static struct clk_ops tegra_clk_double_ops = { | ||
| 751 | .init = &tegra2_clk_double_init, | ||
| 752 | .enable = &tegra2_periph_clk_enable, | ||
| 753 | .disable = &tegra2_periph_clk_disable, | ||
| 754 | .recalculate_rate = &tegra2_clk_recalculate_rate, | ||
| 755 | }; | ||
| 756 | |||
| 757 | /* Clock definitions */ | ||
| 758 | static struct clk tegra_clk_32k = { | ||
| 759 | .name = "clk_32k", | ||
| 760 | .rate = 32678, | ||
| 761 | .ops = NULL, | ||
| 762 | }; | ||
| 763 | |||
| 764 | static struct clk_pll_table tegra_pll_s_table[] = { | ||
| 765 | {32768, 12000000, 366, 1, 1, 0}, | ||
| 766 | {32768, 13000000, 397, 1, 1, 0}, | ||
| 767 | {32768, 19200000, 586, 1, 1, 0}, | ||
| 768 | {32768, 26000000, 793, 1, 1, 0}, | ||
| 769 | {0, 0, 0, 0, 0, 0}, | ||
| 770 | }; | ||
| 771 | |||
| 772 | static struct clk tegra_pll_s = { | ||
| 773 | .name = "pll_s", | ||
| 774 | .flags = PLL_ALT_MISC_REG, | ||
| 775 | .ops = &tegra_pll_ops, | ||
| 776 | .reg = 0xf0, | ||
| 777 | .input_min = 32768, | ||
| 778 | .input_max = 32768, | ||
| 779 | .parent = &tegra_clk_32k, | ||
| 780 | .cf_min = 0, /* FIXME */ | ||
| 781 | .cf_max = 0, /* FIXME */ | ||
| 782 | .vco_min = 12000000, | ||
| 783 | .vco_max = 26000000, | ||
| 784 | .pll_table = tegra_pll_s_table, | ||
| 785 | }; | ||
| 786 | |||
| 787 | static struct clk_mux_sel tegra_clk_m_sel[] = { | ||
| 788 | { .input = &tegra_clk_32k, .value = 0}, | ||
| 789 | { .input = &tegra_pll_s, .value = 1}, | ||
| 790 | { 0, 0}, | ||
| 791 | }; | ||
| 792 | static struct clk tegra_clk_m = { | ||
| 793 | .name = "clk_m", | ||
| 794 | .flags = ENABLE_ON_INIT, | ||
| 795 | .ops = &tegra_clk_m_ops, | ||
| 796 | .inputs = tegra_clk_m_sel, | ||
| 797 | .reg = 0x1fc, | ||
| 798 | .reg_mask = (1<<28), | ||
| 799 | .reg_shift = 28, | ||
| 800 | }; | ||
| 801 | |||
| 802 | static struct clk_pll_table tegra_pll_c_table[] = { | ||
| 803 | { 0, 0, 0, 0, 0, 0 }, | ||
| 804 | }; | ||
| 805 | |||
| 806 | static struct clk tegra_pll_c = { | ||
| 807 | .name = "pll_c", | ||
| 808 | .flags = PLL_HAS_CPCON, | ||
| 809 | .ops = &tegra_pll_ops, | ||
| 810 | .reg = 0x80, | ||
| 811 | .input_min = 2000000, | ||
| 812 | .input_max = 31000000, | ||
| 813 | .parent = &tegra_clk_m, | ||
| 814 | .cf_min = 1000000, | ||
| 815 | .cf_max = 6000000, | ||
| 816 | .vco_min = 20000000, | ||
| 817 | .vco_max = 1400000000, | ||
| 818 | .pll_table = tegra_pll_c_table, | ||
| 819 | }; | ||
| 820 | |||
| 821 | static struct clk tegra_pll_c_out1 = { | ||
| 822 | .name = "pll_c_out1", | ||
| 823 | .ops = &tegra_pll_div_ops, | ||
| 824 | .flags = DIV_U71, | ||
| 825 | .parent = &tegra_pll_c, | ||
| 826 | .reg = 0x84, | ||
| 827 | .reg_shift = 0, | ||
| 828 | }; | ||
| 829 | |||
| 830 | static struct clk_pll_table tegra_pll_m_table[] = { | ||
| 831 | { 0, 0, 0, 0, 0, 0 }, | ||
| 832 | }; | ||
| 833 | |||
| 834 | static struct clk tegra_pll_m = { | ||
| 835 | .name = "pll_m", | ||
| 836 | .flags = PLL_HAS_CPCON, | ||
| 837 | .ops = &tegra_pll_ops, | ||
| 838 | .reg = 0x90, | ||
| 839 | .input_min = 2000000, | ||
| 840 | .input_max = 31000000, | ||
| 841 | .parent = &tegra_clk_m, | ||
| 842 | .cf_min = 1000000, | ||
| 843 | .cf_max = 6000000, | ||
| 844 | .vco_min = 20000000, | ||
| 845 | .vco_max = 1200000000, | ||
| 846 | .pll_table = tegra_pll_m_table, | ||
| 847 | }; | ||
| 848 | |||
| 849 | static struct clk tegra_pll_m_out1 = { | ||
| 850 | .name = "pll_m_out1", | ||
| 851 | .ops = &tegra_pll_div_ops, | ||
| 852 | .flags = DIV_U71, | ||
| 853 | .parent = &tegra_pll_m, | ||
| 854 | .reg = 0x94, | ||
| 855 | .reg_shift = 0, | ||
| 856 | }; | ||
| 857 | |||
| 858 | static struct clk_pll_table tegra_pll_p_table[] = { | ||
| 859 | { 12000000, 216000000, 432, 12, 2, 8}, | ||
| 860 | { 13000000, 216000000, 432, 13, 2, 8}, | ||
| 861 | { 19200000, 216000000, 90, 4, 2, 1}, | ||
| 862 | { 26000000, 216000000, 432, 26, 2, 8}, | ||
| 863 | { 12000000, 432000000, 432, 12, 1, 8}, | ||
| 864 | { 13000000, 432000000, 432, 13, 1, 8}, | ||
| 865 | { 19200000, 432000000, 90, 4, 1, 1}, | ||
| 866 | { 26000000, 432000000, 432, 26, 1, 8}, | ||
| 867 | { 0, 0, 0, 0, 0, 0 }, | ||
| 868 | }; | ||
| 869 | |||
| 870 | static struct clk tegra_pll_p = { | ||
| 871 | .name = "pll_p", | ||
| 872 | .flags = ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON, | ||
| 873 | .ops = &tegra_pll_ops, | ||
| 874 | .reg = 0xa0, | ||
| 875 | .input_min = 2000000, | ||
| 876 | .input_max = 31000000, | ||
| 877 | .parent = &tegra_clk_m, | ||
| 878 | .cf_min = 1000000, | ||
| 879 | .cf_max = 6000000, | ||
| 880 | .vco_min = 20000000, | ||
| 881 | .vco_max = 1400000000, | ||
| 882 | .pll_table = tegra_pll_p_table, | ||
| 883 | }; | ||
| 884 | |||
| 885 | static struct clk tegra_pll_p_out1 = { | ||
| 886 | .name = "pll_p_out1", | ||
| 887 | .ops = &tegra_pll_div_ops, | ||
| 888 | .flags = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, | ||
| 889 | .parent = &tegra_pll_p, | ||
| 890 | .reg = 0xa4, | ||
| 891 | .reg_shift = 0, | ||
| 892 | }; | ||
| 893 | |||
| 894 | static struct clk tegra_pll_p_out2 = { | ||
| 895 | .name = "pll_p_out2", | ||
| 896 | .ops = &tegra_pll_div_ops, | ||
| 897 | .flags = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, | ||
| 898 | .parent = &tegra_pll_p, | ||
| 899 | .reg = 0xa4, | ||
| 900 | .reg_shift = 16, | ||
| 901 | }; | ||
| 902 | |||
| 903 | static struct clk tegra_pll_p_out3 = { | ||
| 904 | .name = "pll_p_out3", | ||
| 905 | .ops = &tegra_pll_div_ops, | ||
| 906 | .flags = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, | ||
| 907 | .parent = &tegra_pll_p, | ||
| 908 | .reg = 0xa8, | ||
| 909 | .reg_shift = 0, | ||
| 910 | }; | ||
| 911 | |||
| 912 | static struct clk tegra_pll_p_out4 = { | ||
| 913 | .name = "pll_p_out4", | ||
| 914 | .ops = &tegra_pll_div_ops, | ||
| 915 | .flags = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, | ||
| 916 | .parent = &tegra_pll_p, | ||
| 917 | .reg = 0xa8, | ||
| 918 | .reg_shift = 16, | ||
| 919 | }; | ||
| 920 | |||
| 921 | static struct clk_pll_table tegra_pll_a_table[] = { | ||
| 922 | { 28800000, 56448000, 49, 25, 1, 1}, | ||
| 923 | { 28800000, 73728000, 64, 25, 1, 1}, | ||
| 924 | { 28800000, 11289600, 49, 25, 1, 1}, | ||
| 925 | { 28800000, 12288000, 64, 25, 1, 1}, | ||
| 926 | { 0, 0, 0, 0, 0, 0 }, | ||
| 927 | }; | ||
| 928 | |||
| 929 | static struct clk tegra_pll_a = { | ||
| 930 | .name = "pll_a", | ||
| 931 | .flags = PLL_HAS_CPCON, | ||
| 932 | .ops = &tegra_pll_ops, | ||
| 933 | .reg = 0xb0, | ||
| 934 | .input_min = 2000000, | ||
| 935 | .input_max = 31000000, | ||
| 936 | .parent = &tegra_pll_p_out1, | ||
| 937 | .cf_min = 1000000, | ||
| 938 | .cf_max = 6000000, | ||
| 939 | .vco_min = 20000000, | ||
| 940 | .vco_max = 1400000000, | ||
| 941 | .pll_table = tegra_pll_a_table, | ||
| 942 | }; | ||
| 943 | |||
| 944 | static struct clk tegra_pll_a_out0 = { | ||
| 945 | .name = "pll_a_out0", | ||
| 946 | .ops = &tegra_pll_div_ops, | ||
| 947 | .flags = DIV_U71, | ||
| 948 | .parent = &tegra_pll_a, | ||
| 949 | .reg = 0xb4, | ||
| 950 | .reg_shift = 0, | ||
| 951 | }; | ||
| 952 | |||
| 953 | static struct clk_pll_table tegra_pll_d_table[] = { | ||
| 954 | { 12000000, 1000000000, 1000, 12, 1, 12}, | ||
| 955 | { 13000000, 1000000000, 1000, 13, 1, 12}, | ||
| 956 | { 19200000, 1000000000, 625, 12, 1, 8}, | ||
| 957 | { 26000000, 1000000000, 1000, 26, 1, 12}, | ||
| 958 | { 0, 0, 0, 0, 0, 0 }, | ||
| 959 | }; | ||
| 960 | |||
| 961 | static struct clk tegra_pll_d = { | ||
| 962 | .name = "pll_d", | ||
| 963 | .flags = PLL_HAS_CPCON | PLLD, | ||
| 964 | .ops = &tegra_pll_ops, | ||
| 965 | .reg = 0xd0, | ||
| 966 | .input_min = 2000000, | ||
| 967 | .input_max = 40000000, | ||
| 968 | .parent = &tegra_clk_m, | ||
| 969 | .cf_min = 1000000, | ||
| 970 | .cf_max = 6000000, | ||
| 971 | .vco_min = 40000000, | ||
| 972 | .vco_max = 1000000000, | ||
| 973 | .pll_table = tegra_pll_d_table, | ||
| 974 | }; | ||
| 975 | |||
| 976 | static struct clk tegra_pll_d_out0 = { | ||
| 977 | .name = "pll_d_out0", | ||
| 978 | .ops = &tegra_pll_div_ops, | ||
| 979 | .flags = DIV_2 | PLLD, | ||
| 980 | .parent = &tegra_pll_d, | ||
| 981 | }; | ||
| 982 | |||
| 983 | static struct clk_pll_table tegra_pll_u_table[] = { | ||
| 984 | { 12000000, 480000000, 960, 12, 1, 0}, | ||
| 985 | { 13000000, 480000000, 960, 13, 1, 0}, | ||
| 986 | { 19200000, 480000000, 200, 4, 1, 0}, | ||
| 987 | { 26000000, 480000000, 960, 26, 1, 0}, | ||
| 988 | { 0, 0, 0, 0, 0, 0 }, | ||
| 989 | }; | ||
| 990 | |||
| 991 | static struct clk tegra_pll_u = { | ||
| 992 | .name = "pll_u", | ||
| 993 | .flags = 0, | ||
| 994 | .ops = &tegra_pll_ops, | ||
| 995 | .reg = 0xc0, | ||
| 996 | .input_min = 2000000, | ||
| 997 | .input_max = 40000000, | ||
| 998 | .parent = &tegra_clk_m, | ||
| 999 | .cf_min = 1000000, | ||
| 1000 | .cf_max = 6000000, | ||
| 1001 | .vco_min = 480000000, | ||
| 1002 | .vco_max = 960000000, | ||
| 1003 | .pll_table = tegra_pll_u_table, | ||
| 1004 | }; | ||
| 1005 | |||
| 1006 | static struct clk_pll_table tegra_pll_x_table[] = { | ||
| 1007 | { 12000000, 1000000000, 1000, 12, 1, 12}, | ||
| 1008 | { 13000000, 1000000000, 1000, 13, 1, 12}, | ||
| 1009 | { 19200000, 1000000000, 625, 12, 1, 8}, | ||
| 1010 | { 26000000, 1000000000, 1000, 26, 1, 12}, | ||
| 1011 | { 12000000, 750000000, 750, 12, 1, 12}, | ||
| 1012 | { 13000000, 750000000, 750, 13, 1, 12}, | ||
| 1013 | { 19200000, 750000000, 625, 16, 1, 8}, | ||
| 1014 | { 26000000, 750000000, 750, 26, 1, 12}, | ||
| 1015 | { 0, 0, 0, 0, 0, 0 }, | ||
| 1016 | }; | ||
| 1017 | |||
| 1018 | static struct clk tegra_pll_x = { | ||
| 1019 | .name = "pll_x", | ||
| 1020 | .flags = PLL_HAS_CPCON | PLL_ALT_MISC_REG, | ||
| 1021 | .ops = &tegra_pll_ops, | ||
| 1022 | .reg = 0xe0, | ||
| 1023 | .input_min = 2000000, | ||
| 1024 | .input_max = 31000000, | ||
| 1025 | .parent = &tegra_clk_m, | ||
| 1026 | .cf_min = 1000000, | ||
| 1027 | .cf_max = 6000000, | ||
| 1028 | .vco_min = 20000000, | ||
| 1029 | .vco_max = 1200000000, | ||
| 1030 | .pll_table = tegra_pll_x_table, | ||
| 1031 | }; | ||
| 1032 | |||
| 1033 | static struct clk tegra_clk_d = { | ||
| 1034 | .name = "clk_d", | ||
| 1035 | .flags = PERIPH_NO_RESET, | ||
| 1036 | .ops = &tegra_clk_double_ops, | ||
| 1037 | .clk_num = 90, | ||
| 1038 | .reg = 0x34, | ||
| 1039 | .reg_shift = 12, | ||
| 1040 | .parent = &tegra_clk_m, | ||
| 1041 | }; | ||
| 1042 | |||
| 1043 | /* FIXME: need tegra_audio | ||
| 1044 | static struct clk tegra_clk_audio_2x = { | ||
| 1045 | .name = "clk_d", | ||
| 1046 | .flags = PERIPH_NO_RESET, | ||
| 1047 | .ops = &tegra_clk_double_ops, | ||
| 1048 | .clk_num = 89, | ||
| 1049 | .reg = 0x34, | ||
| 1050 | .reg_shift = 8, | ||
| 1051 | .parent = &tegra_audio, | ||
| 1052 | } | ||
| 1053 | */ | ||
| 1054 | |||
| 1055 | static struct clk_mux_sel mux_cclk[] = { | ||
| 1056 | { .input = &tegra_clk_m, .value = 0}, | ||
| 1057 | { .input = &tegra_pll_c, .value = 1}, | ||
| 1058 | { .input = &tegra_clk_32k, .value = 2}, | ||
| 1059 | { .input = &tegra_pll_m, .value = 3}, | ||
| 1060 | { .input = &tegra_pll_p, .value = 4}, | ||
| 1061 | { .input = &tegra_pll_p_out4, .value = 5}, | ||
| 1062 | { .input = &tegra_pll_p_out3, .value = 6}, | ||
| 1063 | { .input = &tegra_clk_d, .value = 7}, | ||
| 1064 | { .input = &tegra_pll_x, .value = 8}, | ||
| 1065 | { 0, 0}, | ||
| 1066 | }; | ||
| 1067 | |||
| 1068 | static struct clk_mux_sel mux_sclk[] = { | ||
| 1069 | { .input = &tegra_clk_m, .value = 0}, | ||
| 1070 | { .input = &tegra_pll_c_out1, .value = 1}, | ||
| 1071 | { .input = &tegra_pll_p_out4, .value = 2}, | ||
| 1072 | { .input = &tegra_pll_p_out3, .value = 3}, | ||
| 1073 | { .input = &tegra_pll_p_out2, .value = 4}, | ||
| 1074 | { .input = &tegra_clk_d, .value = 5}, | ||
| 1075 | { .input = &tegra_clk_32k, .value = 6}, | ||
| 1076 | { .input = &tegra_pll_m_out1, .value = 7}, | ||
| 1077 | { 0, 0}, | ||
| 1078 | }; | ||
| 1079 | |||
| 1080 | static struct clk tegra_clk_cpu = { | ||
| 1081 | .name = "cpu", | ||
| 1082 | .inputs = mux_cclk, | ||
| 1083 | .reg = 0x20, | ||
| 1084 | .ops = &tegra_super_ops, | ||
| 1085 | }; | ||
| 1086 | |||
| 1087 | static struct clk tegra_clk_sys = { | ||
| 1088 | .name = "sys", | ||
| 1089 | .inputs = mux_sclk, | ||
| 1090 | .reg = 0x28, | ||
| 1091 | .ops = &tegra_super_ops, | ||
| 1092 | }; | ||
| 1093 | |||
| 1094 | static struct clk tegra_clk_hclk = { | ||
| 1095 | .name = "hclk", | ||
| 1096 | .flags = DIV_BUS, | ||
| 1097 | .parent = &tegra_clk_sys, | ||
| 1098 | .reg = 0x30, | ||
| 1099 | .reg_shift = 4, | ||
| 1100 | .ops = &tegra_bus_ops, | ||
| 1101 | }; | ||
| 1102 | |||
| 1103 | static struct clk tegra_clk_pclk = { | ||
| 1104 | .name = "pclk", | ||
| 1105 | .flags = DIV_BUS, | ||
| 1106 | .parent = &tegra_clk_hclk, | ||
| 1107 | .reg = 0x30, | ||
| 1108 | .reg_shift = 0, | ||
| 1109 | .ops = &tegra_bus_ops, | ||
| 1110 | }; | ||
| 1111 | |||
| 1112 | static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { | ||
| 1113 | { .input = &tegra_pll_m, .value = 0}, | ||
| 1114 | { .input = &tegra_pll_c, .value = 1}, | ||
| 1115 | { .input = &tegra_pll_p, .value = 2}, | ||
| 1116 | { .input = &tegra_pll_a_out0, .value = 3}, | ||
| 1117 | { 0, 0}, | ||
| 1118 | }; | ||
| 1119 | |||
| 1120 | static struct clk_mux_sel mux_pllm_pllc_pllp_clkm[] = { | ||
| 1121 | { .input = &tegra_pll_m, .value = 0}, | ||
| 1122 | { .input = &tegra_pll_c, .value = 1}, | ||
| 1123 | { .input = &tegra_pll_p, .value = 2}, | ||
| 1124 | { .input = &tegra_clk_m, .value = 3}, | ||
| 1125 | { 0, 0}, | ||
| 1126 | }; | ||
| 1127 | |||
| 1128 | static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = { | ||
| 1129 | { .input = &tegra_pll_p, .value = 0}, | ||
| 1130 | { .input = &tegra_pll_c, .value = 1}, | ||
| 1131 | { .input = &tegra_pll_m, .value = 2}, | ||
| 1132 | { .input = &tegra_clk_m, .value = 3}, | ||
| 1133 | { 0, 0}, | ||
| 1134 | }; | ||
| 1135 | |||
| 1136 | static struct clk_mux_sel mux_plla_audio_pllp_clkm[] = { | ||
| 1137 | {.input = &tegra_pll_a, .value = 0}, | ||
| 1138 | /* FIXME: no mux defined for tegra_audio | ||
| 1139 | {.input = &tegra_audio, .value = 1},*/ | ||
| 1140 | {.input = &tegra_pll_p, .value = 2}, | ||
| 1141 | {.input = &tegra_clk_m, .value = 3}, | ||
| 1142 | { 0, 0}, | ||
| 1143 | }; | ||
| 1144 | |||
| 1145 | static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = { | ||
| 1146 | {.input = &tegra_pll_p, .value = 0}, | ||
| 1147 | {.input = &tegra_pll_d_out0, .value = 1}, | ||
| 1148 | {.input = &tegra_pll_c, .value = 2}, | ||
| 1149 | {.input = &tegra_clk_m, .value = 3}, | ||
| 1150 | { 0, 0}, | ||
| 1151 | }; | ||
| 1152 | |||
| 1153 | static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = { | ||
| 1154 | {.input = &tegra_pll_p, .value = 0}, | ||
| 1155 | {.input = &tegra_pll_c, .value = 1}, | ||
| 1156 | /* FIXME: no mux defined for tegra_audio | ||
| 1157 | {.input = &tegra_audio, .value = 2},*/ | ||
| 1158 | {.input = &tegra_clk_m, .value = 3}, | ||
| 1159 | {.input = &tegra_clk_32k, .value = 4}, | ||
| 1160 | { 0, 0}, | ||
| 1161 | }; | ||
| 1162 | |||
| 1163 | static struct clk_mux_sel mux_pllp_pllc_pllm[] = { | ||
| 1164 | {.input = &tegra_pll_p, .value = 0}, | ||
| 1165 | {.input = &tegra_pll_c, .value = 1}, | ||
| 1166 | {.input = &tegra_pll_m, .value = 2}, | ||
| 1167 | { 0, 0}, | ||
| 1168 | }; | ||
| 1169 | |||
| 1170 | static struct clk_mux_sel mux_clk_m[] = { | ||
| 1171 | { .input = &tegra_clk_m, .value = 0}, | ||
| 1172 | { 0, 0}, | ||
| 1173 | }; | ||
| 1174 | |||
| 1175 | static struct clk_mux_sel mux_pllp_out3[] = { | ||
| 1176 | { .input = &tegra_pll_p_out3, .value = 0}, | ||
| 1177 | { 0, 0}, | ||
| 1178 | }; | ||
| 1179 | |||
| 1180 | static struct clk_mux_sel mux_plld[] = { | ||
| 1181 | { .input = &tegra_pll_d, .value = 0}, | ||
| 1182 | { 0, 0}, | ||
| 1183 | }; | ||
| 1184 | |||
| 1185 | static struct clk_mux_sel mux_clk_32k[] = { | ||
| 1186 | { .input = &tegra_clk_32k, .value = 0}, | ||
| 1187 | { 0, 0}, | ||
| 1188 | }; | ||
| 1189 | |||
| 1190 | #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _inputs, _flags) \ | ||
| 1191 | { \ | ||
| 1192 | .name = _name, \ | ||
| 1193 | .lookup = { \ | ||
| 1194 | .dev_id = _dev, \ | ||
| 1195 | .con_id = _con, \ | ||
| 1196 | }, \ | ||
| 1197 | .ops = &tegra_periph_clk_ops, \ | ||
| 1198 | .clk_num = _clk_num, \ | ||
| 1199 | .reg = _reg, \ | ||
| 1200 | .inputs = _inputs, \ | ||
| 1201 | .flags = _flags, \ | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | struct clk tegra_periph_clks[] = { | ||
| 1205 | PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, mux_clk_32k, PERIPH_NO_RESET), | ||
| 1206 | PERIPH_CLK("timer", "timer", NULL, 5, 0, mux_clk_m, 0), | ||
| 1207 | PERIPH_CLK("i2s1", "i2s.0", NULL, 11, 0x100, mux_plla_audio_pllp_clkm, MUX | DIV_U71), | ||
| 1208 | PERIPH_CLK("i2s2", "i2s.1", NULL, 18, 0x104, mux_plla_audio_pllp_clkm, MUX | DIV_U71), | ||
| 1209 | /* FIXME: spdif has 2 clocks but 1 enable */ | ||
| 1210 | PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, mux_plla_audio_pllp_clkm, MUX | DIV_U71), | ||
| 1211 | PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, mux_pllp_pllc_pllm, MUX | DIV_U71), | ||
| 1212 | PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71), | ||
| 1213 | PERIPH_CLK("spi", "spi", NULL, 43, 0x114, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1214 | PERIPH_CLK("xio", "xio", NULL, 45, 0x120, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1215 | PERIPH_CLK("twc", "twc", NULL, 16, 0x12c, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1216 | PERIPH_CLK("sbc1", "spi_tegra.0", NULL, 41, 0x134, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1217 | PERIPH_CLK("sbc2", "spi_tegra.1", NULL, 44, 0x118, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1218 | PERIPH_CLK("sbc3", "spi_tegra.2", NULL, 46, 0x11c, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1219 | PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1220 | PERIPH_CLK("ide", "ide", NULL, 25, 0x144, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1221 | PERIPH_CLK("ndflash", "tegra_nand", NULL, 13, 0x160, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1222 | /* FIXME: vfir shares an enable with uartb */ | ||
| 1223 | PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1224 | PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1225 | PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1226 | PERIPH_CLK("sdmmc3", "sdhci-tegra.2", NULL, 69, 0x1bc, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1227 | PERIPH_CLK("sdmmc4", "sdhci-tegra.3", NULL, 15, 0x160, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1228 | PERIPH_CLK("vde", "vde", NULL, 61, 0x1c8, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1229 | PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1230 | /* FIXME: what is la? */ | ||
| 1231 | PERIPH_CLK("la", "la", NULL, 76, 0x1f8, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1232 | PERIPH_CLK("owr", "owr", NULL, 71, 0x1cc, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1233 | PERIPH_CLK("nor", "nor", NULL, 42, 0x1d0, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1234 | PERIPH_CLK("mipi", "mipi", NULL, 50, 0x174, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1235 | PERIPH_CLK("i2c1", "tegra-i2c.0", NULL, 12, 0x124, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1236 | PERIPH_CLK("i2c2", "tegra-i2c.1", NULL, 54, 0x198, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1237 | PERIPH_CLK("i2c3", "tegra-i2c.2", NULL, 67, 0x1b8, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1238 | PERIPH_CLK("dvc", "tegra-i2c.3", NULL, 47, 0x128, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1239 | PERIPH_CLK("i2c1_i2c", "tegra-i2c.0", "i2c", 0, 0, mux_pllp_out3, 0), | ||
| 1240 | PERIPH_CLK("i2c2_i2c", "tegra-i2c.1", "i2c", 0, 0, mux_pllp_out3, 0), | ||
| 1241 | PERIPH_CLK("i2c3_i2c", "tegra-i2c.2", "i2c", 0, 0, mux_pllp_out3, 0), | ||
| 1242 | PERIPH_CLK("dvc_i2c", "tegra-i2c.3", "i2c", 0, 0, mux_pllp_out3, 0), | ||
| 1243 | PERIPH_CLK("uarta", "uart.0", NULL, 6, 0x178, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1244 | PERIPH_CLK("uartb", "uart.1", NULL, 7, 0x17c, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1245 | PERIPH_CLK("uartc", "uart.2", NULL, 55, 0x1a0, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1246 | PERIPH_CLK("uartd", "uart.3", NULL, 65, 0x1c0, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1247 | PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | ||
| 1248 | PERIPH_CLK("3d", "3d", NULL, 24, 0x158, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), | ||
| 1249 | PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | ||
| 1250 | /* FIXME: vi and vi_sensor share an enable */ | ||
| 1251 | PERIPH_CLK("vi", "vi", NULL, 20, 0x148, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | ||
| 1252 | PERIPH_CLK("vi_sensor", "vi_sensor", NULL, 20, 0x1a8, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | ||
| 1253 | PERIPH_CLK("epp", "epp", NULL, 19, 0x16c, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | ||
| 1254 | PERIPH_CLK("mpe", "mpe", NULL, 60, 0x170, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | ||
| 1255 | PERIPH_CLK("host1x", "host1x", NULL, 28, 0x180, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | ||
| 1256 | /* FIXME: cve and tvo share an enable */ | ||
| 1257 | PERIPH_CLK("cve", "cve", NULL, 49, 0x140, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | ||
| 1258 | PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | ||
| 1259 | PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | ||
| 1260 | PERIPH_CLK("tvdac", "tvdac", NULL, 53, 0x194, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | ||
| 1261 | PERIPH_CLK("disp1", "tegrafb.0", NULL, 27, 0x138, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | ||
| 1262 | PERIPH_CLK("disp2", "tegrafb.1", NULL, 26, 0x13c, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | ||
| 1263 | PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, mux_clk_m, 0), | ||
| 1264 | PERIPH_CLK("usb2", "usb.1", NULL, 58, 0, mux_clk_m, 0), | ||
| 1265 | PERIPH_CLK("usb3", "usb.2", NULL, 59, 0, mux_clk_m, 0), | ||
| 1266 | PERIPH_CLK("emc", "emc", NULL, 57, 0x19c, mux_pllm_pllc_pllp_clkm, MUX | DIV_U71 | PERIPH_EMC_ENB), | ||
| 1267 | PERIPH_CLK("dsi", "dsi", NULL, 48, 0, mux_plld, 0), | ||
| 1268 | }; | ||
| 1269 | |||
| 1270 | #define CLK_DUPLICATE(_name, _dev, _con) \ | ||
| 1271 | { \ | ||
| 1272 | .name = _name, \ | ||
| 1273 | .lookup = { \ | ||
| 1274 | .dev_id = _dev, \ | ||
| 1275 | .con_id = _con, \ | ||
| 1276 | }, \ | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | /* Some clocks may be used by different drivers depending on the board | ||
| 1280 | * configuration. List those here to register them twice in the clock lookup | ||
| 1281 | * table under two names. | ||
| 1282 | */ | ||
| 1283 | struct clk_duplicate tegra_clk_duplicates[] = { | ||
| 1284 | CLK_DUPLICATE("uarta", "tegra_uart.0", NULL), | ||
| 1285 | CLK_DUPLICATE("uartb", "tegra_uart.1", NULL), | ||
| 1286 | CLK_DUPLICATE("uartc", "tegra_uart.2", NULL), | ||
| 1287 | CLK_DUPLICATE("uartd", "tegra_uart.3", NULL), | ||
| 1288 | CLK_DUPLICATE("uarte", "tegra_uart.4", NULL), | ||
| 1289 | }; | ||
| 1290 | |||
| 1291 | #define CLK(dev, con, ck) \ | ||
| 1292 | { \ | ||
| 1293 | .dev_id = dev, \ | ||
| 1294 | .con_id = con, \ | ||
| 1295 | .clk = ck, \ | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | struct clk_lookup tegra_clk_lookups[] = { | ||
| 1299 | /* external root sources */ | ||
| 1300 | CLK(NULL, "32k_clk", &tegra_clk_32k), | ||
| 1301 | CLK(NULL, "pll_s", &tegra_pll_s), | ||
| 1302 | CLK(NULL, "clk_m", &tegra_clk_m), | ||
| 1303 | CLK(NULL, "pll_m", &tegra_pll_m), | ||
| 1304 | CLK(NULL, "pll_m_out1", &tegra_pll_m_out1), | ||
| 1305 | CLK(NULL, "pll_c", &tegra_pll_c), | ||
| 1306 | CLK(NULL, "pll_c_out1", &tegra_pll_c_out1), | ||
| 1307 | CLK(NULL, "pll_p", &tegra_pll_p), | ||
| 1308 | CLK(NULL, "pll_p_out1", &tegra_pll_p_out1), | ||
| 1309 | CLK(NULL, "pll_p_out2", &tegra_pll_p_out2), | ||
| 1310 | CLK(NULL, "pll_p_out3", &tegra_pll_p_out3), | ||
| 1311 | CLK(NULL, "pll_p_out4", &tegra_pll_p_out4), | ||
| 1312 | CLK(NULL, "pll_a", &tegra_pll_a), | ||
| 1313 | CLK(NULL, "pll_a_out0", &tegra_pll_a_out0), | ||
| 1314 | CLK(NULL, "pll_d", &tegra_pll_d), | ||
| 1315 | CLK(NULL, "pll_d_out0", &tegra_pll_d_out0), | ||
| 1316 | CLK(NULL, "pll_u", &tegra_pll_u), | ||
| 1317 | CLK(NULL, "pll_x", &tegra_pll_x), | ||
| 1318 | CLK(NULL, "cpu", &tegra_clk_cpu), | ||
| 1319 | CLK(NULL, "sys", &tegra_clk_sys), | ||
| 1320 | CLK(NULL, "hclk", &tegra_clk_hclk), | ||
| 1321 | CLK(NULL, "pclk", &tegra_clk_pclk), | ||
| 1322 | CLK(NULL, "clk_d", &tegra_clk_d), | ||
| 1323 | }; | ||
| 1324 | |||
| 1325 | void __init tegra2_init_clocks(void) | ||
| 1326 | { | ||
| 1327 | int i; | ||
| 1328 | struct clk_lookup *cl; | ||
| 1329 | struct clk *c; | ||
| 1330 | struct clk_duplicate *cd; | ||
| 1331 | |||
| 1332 | for (i = 0; i < ARRAY_SIZE(tegra_clk_lookups); i++) { | ||
| 1333 | cl = &tegra_clk_lookups[i]; | ||
| 1334 | clk_init(cl->clk); | ||
| 1335 | clkdev_add(cl); | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | for (i = 0; i < ARRAY_SIZE(tegra_periph_clks); i++) { | ||
| 1339 | c = &tegra_periph_clks[i]; | ||
| 1340 | cl = &c->lookup; | ||
| 1341 | cl->clk = c; | ||
| 1342 | |||
| 1343 | clk_init(cl->clk); | ||
| 1344 | clkdev_add(cl); | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) { | ||
| 1348 | cd = &tegra_clk_duplicates[i]; | ||
| 1349 | c = tegra_get_clock_by_name(cd->name); | ||
| 1350 | if (c) { | ||
| 1351 | cl = &cd->lookup; | ||
| 1352 | cl->clk = c; | ||
| 1353 | clkdev_add(cl); | ||
| 1354 | } else { | ||
| 1355 | pr_err("%s: Unknown duplicate clock %s\n", __func__, | ||
| 1356 | cd->name); | ||
| 1357 | } | ||
| 1358 | } | ||
| 1359 | } | ||
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c new file mode 100644 index 000000000000..2f420210d406 --- /dev/null +++ b/arch/arm/mach-tegra/timer.c | |||
| @@ -0,0 +1,187 @@ | |||
| 1 | /* | ||
| 2 | * arch/arch/mach-tegra/timer.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Google, Inc. | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Colin Cross <ccross@google.com> | ||
| 8 | * | ||
| 9 | * This software is licensed under the terms of the GNU General Public | ||
| 10 | * License version 2, as published by the Free Software Foundation, and | ||
| 11 | * may be copied, distributed, and modified under those terms. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/time.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/irq.h> | ||
| 24 | #include <linux/clockchips.h> | ||
| 25 | #include <linux/clocksource.h> | ||
| 26 | #include <linux/clk.h> | ||
| 27 | #include <linux/io.h> | ||
| 28 | #include <linux/cnt32_to_63.h> | ||
| 29 | |||
| 30 | #include <asm/mach/time.h> | ||
| 31 | #include <asm/mach/time.h> | ||
| 32 | #include <asm/localtimer.h> | ||
| 33 | |||
| 34 | #include <mach/iomap.h> | ||
| 35 | #include <mach/irqs.h> | ||
| 36 | |||
| 37 | #include "board.h" | ||
| 38 | #include "clock.h" | ||
| 39 | |||
| 40 | #define TIMERUS_CNTR_1US 0x10 | ||
| 41 | #define TIMERUS_USEC_CFG 0x14 | ||
| 42 | #define TIMERUS_CNTR_FREEZE 0x4c | ||
| 43 | |||
| 44 | #define TIMER1_BASE 0x0 | ||
| 45 | #define TIMER2_BASE 0x8 | ||
| 46 | #define TIMER3_BASE 0x50 | ||
| 47 | #define TIMER4_BASE 0x58 | ||
| 48 | |||
| 49 | #define TIMER_PTV 0x0 | ||
| 50 | #define TIMER_PCR 0x4 | ||
| 51 | |||
| 52 | struct tegra_timer; | ||
| 53 | |||
| 54 | static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE); | ||
| 55 | |||
| 56 | #define timer_writel(value, reg) \ | ||
| 57 | __raw_writel(value, (u32)timer_reg_base + (reg)) | ||
| 58 | #define timer_readl(reg) \ | ||
| 59 | __raw_readl((u32)timer_reg_base + (reg)) | ||
| 60 | |||
| 61 | static int tegra_timer_set_next_event(unsigned long cycles, | ||
| 62 | struct clock_event_device *evt) | ||
| 63 | { | ||
| 64 | u32 reg; | ||
| 65 | |||
| 66 | reg = 0x80000000 | ((cycles > 1) ? (cycles-1) : 0); | ||
| 67 | timer_writel(reg, TIMER3_BASE + TIMER_PTV); | ||
| 68 | |||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | static void tegra_timer_set_mode(enum clock_event_mode mode, | ||
| 73 | struct clock_event_device *evt) | ||
| 74 | { | ||
| 75 | u32 reg; | ||
| 76 | |||
| 77 | timer_writel(0, TIMER3_BASE + TIMER_PTV); | ||
| 78 | |||
| 79 | switch (mode) { | ||
| 80 | case CLOCK_EVT_MODE_PERIODIC: | ||
| 81 | reg = 0xC0000000 | ((1000000/HZ)-1); | ||
| 82 | timer_writel(reg, TIMER3_BASE + TIMER_PTV); | ||
| 83 | break; | ||
| 84 | case CLOCK_EVT_MODE_ONESHOT: | ||
| 85 | break; | ||
| 86 | case CLOCK_EVT_MODE_UNUSED: | ||
| 87 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
| 88 | case CLOCK_EVT_MODE_RESUME: | ||
| 89 | break; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | static cycle_t tegra_clocksource_read(struct clocksource *cs) | ||
| 94 | { | ||
| 95 | return cnt32_to_63(timer_readl(TIMERUS_CNTR_1US)); | ||
| 96 | } | ||
| 97 | |||
| 98 | static struct clock_event_device tegra_clockevent = { | ||
| 99 | .name = "timer0", | ||
| 100 | .rating = 300, | ||
| 101 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, | ||
| 102 | .set_next_event = tegra_timer_set_next_event, | ||
| 103 | .set_mode = tegra_timer_set_mode, | ||
| 104 | }; | ||
| 105 | |||
| 106 | static struct clocksource tegra_clocksource = { | ||
| 107 | .name = "timer_us", | ||
| 108 | .rating = 300, | ||
| 109 | .read = tegra_clocksource_read, | ||
| 110 | .mask = 0x7FFFFFFFFFFFFFFFULL, | ||
| 111 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
| 112 | }; | ||
| 113 | |||
| 114 | unsigned long long sched_clock(void) | ||
| 115 | { | ||
| 116 | return clocksource_cyc2ns(tegra_clocksource.read(&tegra_clocksource), | ||
| 117 | tegra_clocksource.mult, tegra_clocksource.shift); | ||
| 118 | } | ||
| 119 | |||
| 120 | static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) | ||
| 121 | { | ||
| 122 | struct clock_event_device *evt = (struct clock_event_device *)dev_id; | ||
| 123 | timer_writel(1<<30, TIMER3_BASE + TIMER_PCR); | ||
| 124 | evt->event_handler(evt); | ||
| 125 | return IRQ_HANDLED; | ||
| 126 | } | ||
| 127 | |||
| 128 | static struct irqaction tegra_timer_irq = { | ||
| 129 | .name = "timer0", | ||
| 130 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH, | ||
| 131 | .handler = tegra_timer_interrupt, | ||
| 132 | .dev_id = &tegra_clockevent, | ||
| 133 | .irq = INT_TMR3, | ||
| 134 | }; | ||
| 135 | |||
| 136 | static void __init tegra_init_timer(void) | ||
| 137 | { | ||
| 138 | unsigned long rate = clk_measure_input_freq(); | ||
| 139 | int ret; | ||
| 140 | |||
| 141 | #ifdef CONFIG_HAVE_ARM_TWD | ||
| 142 | twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600); | ||
| 143 | #endif | ||
| 144 | |||
| 145 | switch (rate) { | ||
| 146 | case 12000000: | ||
| 147 | timer_writel(0x000b, TIMERUS_USEC_CFG); | ||
| 148 | break; | ||
| 149 | case 13000000: | ||
| 150 | timer_writel(0x000c, TIMERUS_USEC_CFG); | ||
| 151 | break; | ||
| 152 | case 19200000: | ||
| 153 | timer_writel(0x045f, TIMERUS_USEC_CFG); | ||
| 154 | break; | ||
| 155 | case 26000000: | ||
| 156 | timer_writel(0x0019, TIMERUS_USEC_CFG); | ||
| 157 | break; | ||
| 158 | default: | ||
| 159 | WARN(1, "Unknown clock rate"); | ||
| 160 | } | ||
| 161 | |||
| 162 | if (clocksource_register_hz(&tegra_clocksource, 1000000)) { | ||
| 163 | printk(KERN_ERR "Failed to register clocksource\n"); | ||
| 164 | BUG(); | ||
| 165 | } | ||
| 166 | |||
| 167 | ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq); | ||
| 168 | if (ret) { | ||
| 169 | printk(KERN_ERR "Failed to register timer IRQ: %d\n", ret); | ||
| 170 | BUG(); | ||
| 171 | } | ||
| 172 | |||
| 173 | clockevents_calc_mult_shift(&tegra_clockevent, 1000000, 5); | ||
| 174 | tegra_clockevent.max_delta_ns = | ||
| 175 | clockevent_delta2ns(0x1fffffff, &tegra_clockevent); | ||
| 176 | tegra_clockevent.min_delta_ns = | ||
| 177 | clockevent_delta2ns(0x1, &tegra_clockevent); | ||
| 178 | tegra_clockevent.cpumask = cpu_all_mask; | ||
| 179 | tegra_clockevent.irq = tegra_timer_irq.irq; | ||
| 180 | clockevents_register_device(&tegra_clockevent); | ||
| 181 | |||
| 182 | return; | ||
| 183 | } | ||
| 184 | |||
| 185 | struct sys_timer tegra_timer = { | ||
| 186 | .init = tegra_init_timer, | ||
| 187 | }; | ||
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 87ec141fcaa6..e1fd98fff8fa 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
| @@ -771,7 +771,8 @@ config CACHE_L2X0 | |||
| 771 | bool "Enable the L2x0 outer cache controller" | 771 | bool "Enable the L2x0 outer cache controller" |
| 772 | depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ | 772 | depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ |
| 773 | REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \ | 773 | REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \ |
| 774 | ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 | 774 | ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \ |
| 775 | ARCH_TEGRA | ||
| 775 | default y | 776 | default y |
| 776 | select OUTER_CACHE | 777 | select OUTER_CACHE |
| 777 | select OUTER_CACHE_SYNC | 778 | select OUTER_CACHE_SYNC |
