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 /arch/arm | |
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
Diffstat (limited to 'arch/arm')
41 files changed, 6052 insertions, 5 deletions
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 |