aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/Kconfig53
-rw-r--r--arch/arm/mach-tegra/Makefile13
-rw-r--r--arch/arm/mach-tegra/apbio.c5
-rw-r--r--arch/arm/mach-tegra/board-dt-tegra20.c27
-rw-r--r--arch/arm/mach-tegra/board-dt-tegra30.c28
-rw-r--r--arch/arm/mach-tegra/clock.c2
-rw-r--r--arch/arm/mach-tegra/common.c33
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c3
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra20.c66
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra30.c188
-rw-r--r--arch/arm/mach-tegra/cpuidle.c85
-rw-r--r--arch/arm/mach-tegra/cpuidle.h32
-rw-r--r--arch/arm/mach-tegra/flowctrl.c50
-rw-r--r--arch/arm/mach-tegra/flowctrl.h8
-rw-r--r--arch/arm/mach-tegra/fuse.c52
-rw-r--r--arch/arm/mach-tegra/fuse.h16
-rw-r--r--arch/arm/mach-tegra/headsmp.S74
-rw-r--r--arch/arm/mach-tegra/include/mach/debug-macro.S100
-rw-r--r--arch/arm/mach-tegra/include/mach/dma.h54
-rw-r--r--arch/arm/mach-tegra/include/mach/irqs.h182
-rw-r--r--arch/arm/mach-tegra/include/mach/powergate.h2
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra-ahb.h19
-rw-r--r--arch/arm/mach-tegra/include/mach/uncompress.h67
-rw-r--r--arch/arm/mach-tegra/io.c3
-rw-r--r--arch/arm/mach-tegra/iomap.h (renamed from arch/arm/mach-tegra/include/mach/iomap.h)16
-rw-r--r--arch/arm/mach-tegra/irammap.h (renamed from arch/arm/mach-tegra/include/mach/irammap.h)9
-rw-r--r--arch/arm/mach-tegra/irq.c3
-rw-r--r--arch/arm/mach-tegra/pcie.c5
-rw-r--r--arch/arm/mach-tegra/platsmp.c3
-rw-r--r--arch/arm/mach-tegra/pm.c216
-rw-r--r--arch/arm/mach-tegra/pm.h35
-rw-r--r--arch/arm/mach-tegra/pmc.c2
-rw-r--r--arch/arm/mach-tegra/powergate.c2
-rw-r--r--arch/arm/mach-tegra/reset.c11
-rw-r--r--arch/arm/mach-tegra/reset.h9
-rw-r--r--arch/arm/mach-tegra/sleep-tegra20.S (renamed from arch/arm/mach-tegra/sleep-t20.S)2
-rw-r--r--arch/arm/mach-tegra/sleep-tegra30.S (renamed from arch/arm/mach-tegra/sleep-t30.S)68
-rw-r--r--arch/arm/mach-tegra/sleep.S80
-rw-r--r--arch/arm/mach-tegra/sleep.h39
-rw-r--r--arch/arm/mach-tegra/tegra20_clocks.c3
-rw-r--r--arch/arm/mach-tegra/tegra20_clocks_data.c13
-rw-r--r--arch/arm/mach-tegra/tegra20_speedo.c109
-rw-r--r--arch/arm/mach-tegra/tegra2_emc.c2
-rw-r--r--arch/arm/mach-tegra/tegra30_clocks.c215
-rw-r--r--arch/arm/mach-tegra/tegra30_clocks.h1
-rw-r--r--arch/arm/mach-tegra/tegra30_clocks_data.c51
-rw-r--r--arch/arm/mach-tegra/tegra30_speedo.c292
-rw-r--r--arch/arm/mach-tegra/tegra_cpu_car.h37
-rw-r--r--arch/arm/mach-tegra/timer.c78
49 files changed, 1797 insertions, 666 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 9ff6f6ea3617..b442f15fd01a 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -55,58 +55,7 @@ config TEGRA_AHB
55 help 55 help
56 Adds AHB configuration functionality for NVIDIA Tegra SoCs, 56 Adds AHB configuration functionality for NVIDIA Tegra SoCs,
57 which controls AHB bus master arbitration and some 57 which controls AHB bus master arbitration and some
58 perfomance parameters(priority, prefech size). 58 performance parameters(priority, prefech size).
59
60choice
61 prompt "Default low-level debug console UART"
62 default TEGRA_DEBUG_UART_NONE
63
64config TEGRA_DEBUG_UART_NONE
65 bool "None"
66
67config TEGRA_DEBUG_UARTA
68 bool "UART-A"
69
70config TEGRA_DEBUG_UARTB
71 bool "UART-B"
72
73config TEGRA_DEBUG_UARTC
74 bool "UART-C"
75
76config TEGRA_DEBUG_UARTD
77 bool "UART-D"
78
79config TEGRA_DEBUG_UARTE
80 bool "UART-E"
81
82endchoice
83
84choice
85 prompt "Automatic low-level debug console UART"
86 default TEGRA_DEBUG_UART_AUTO_NONE
87
88config TEGRA_DEBUG_UART_AUTO_NONE
89 bool "None"
90
91config TEGRA_DEBUG_UART_AUTO_ODMDATA
92 bool "Via ODMDATA"
93 help
94 Automatically determines which UART to use for low-level debug based
95 on the ODMDATA value. This value is part of the BCT, and is written
96 to the boot memory device using nvflash, or other flashing tool.
97 When bits 19:18 are 3, then bits 17:15 indicate which UART to use;
98 0/1/2/3/4 are UART A/B/C/D/E.
99
100config TEGRA_DEBUG_UART_AUTO_SCRATCH
101 bool "Via UART scratch register"
102 help
103 Automatically determines which UART to use for low-level debug based
104 on the UART scratch register value. Some bootloaders put ASCII 'D'
105 in this register when they initialize their own console UART output.
106 Using this option allows the kernel to automatically pick the same
107 UART.
108
109endchoice
110 59
111config TEGRA_EMC_SCALING_ENABLE 60config TEGRA_EMC_SCALING_ENABLE
112 bool "Enable scaling the memory frequency" 61 bool "Enable scaling the memory frequency"
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 9aa653b3eb32..0979e8bba78a 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -8,15 +8,24 @@ obj-y += pmc.o
8obj-y += flowctrl.o 8obj-y += flowctrl.o
9obj-y += powergate.o 9obj-y += powergate.o
10obj-y += apbio.o 10obj-y += apbio.o
11obj-y += pm.o
11obj-$(CONFIG_CPU_IDLE) += cpuidle.o 12obj-$(CONFIG_CPU_IDLE) += cpuidle.o
12obj-$(CONFIG_CPU_IDLE) += sleep.o 13obj-$(CONFIG_CPU_IDLE) += sleep.o
13obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks.o 14obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks.o
14obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks_data.o 15obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_clocks_data.o
16obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
15obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o 17obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
16obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-t20.o 18obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-tegra20.o
19ifeq ($(CONFIG_CPU_IDLE),y)
20obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += cpuidle-tegra20.o
21endif
17obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks.o 22obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks.o
18obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks_data.o 23obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_clocks_data.o
19obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += sleep-t30.o 24obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_speedo.o
25obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += sleep-tegra30.o
26ifeq ($(CONFIG_CPU_IDLE),y)
27obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpuidle-tegra30.o
28endif
20obj-$(CONFIG_SMP) += platsmp.o headsmp.o 29obj-$(CONFIG_SMP) += platsmp.o headsmp.o
21obj-$(CONFIG_SMP) += reset.o 30obj-$(CONFIG_SMP) += reset.o
22obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 31obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
index b5015d0f1912..d091675ba376 100644
--- a/arch/arm/mach-tegra/apbio.c
+++ b/arch/arm/mach-tegra/apbio.c
@@ -15,7 +15,6 @@
15 15
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <mach/iomap.h>
19#include <linux/of.h> 18#include <linux/of.h>
20#include <linux/dmaengine.h> 19#include <linux/dmaengine.h>
21#include <linux/dma-mapping.h> 20#include <linux/dma-mapping.h>
@@ -24,9 +23,8 @@
24#include <linux/sched.h> 23#include <linux/sched.h>
25#include <linux/mutex.h> 24#include <linux/mutex.h>
26 25
27#include <mach/dma.h>
28
29#include "apbio.h" 26#include "apbio.h"
27#include "iomap.h"
30 28
31#if defined(CONFIG_TEGRA20_APB_DMA) 29#if defined(CONFIG_TEGRA20_APB_DMA)
32static DEFINE_MUTEX(tegra_apb_dma_lock); 30static DEFINE_MUTEX(tegra_apb_dma_lock);
@@ -71,7 +69,6 @@ bool tegra_apb_dma_init(void)
71 69
72 dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 70 dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
73 dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 71 dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
74 dma_sconfig.slave_id = TEGRA_DMA_REQ_SEL_CNTR;
75 dma_sconfig.src_maxburst = 1; 72 dma_sconfig.src_maxburst = 1;
76 dma_sconfig.dst_maxburst = 1; 73 dma_sconfig.dst_maxburst = 1;
77 74
diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c
index aa5325cd1c42..734d9cc87f2e 100644
--- a/arch/arm/mach-tegra/board-dt-tegra20.c
+++ b/arch/arm/mach-tegra/board-dt-tegra20.c
@@ -40,12 +40,10 @@
40#include <asm/mach/time.h> 40#include <asm/mach/time.h>
41#include <asm/setup.h> 41#include <asm/setup.h>
42 42
43#include <mach/iomap.h>
44#include <mach/irqs.h>
45
46#include "board.h" 43#include "board.h"
47#include "clock.h" 44#include "clock.h"
48#include "common.h" 45#include "common.h"
46#include "iomap.h"
49 47
50struct tegra_ehci_platform_data tegra_ehci1_pdata = { 48struct tegra_ehci_platform_data tegra_ehci1_pdata = {
51 .operating_mode = TEGRA_USB_OTG, 49 .operating_mode = TEGRA_USB_OTG,
@@ -91,6 +89,17 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
91 &tegra_ehci3_pdata), 89 &tegra_ehci3_pdata),
92 OF_DEV_AUXDATA("nvidia,tegra20-apbdma", TEGRA_APB_DMA_BASE, "tegra-apbdma", NULL), 90 OF_DEV_AUXDATA("nvidia,tegra20-apbdma", TEGRA_APB_DMA_BASE, "tegra-apbdma", NULL),
93 OF_DEV_AUXDATA("nvidia,tegra20-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL), 91 OF_DEV_AUXDATA("nvidia,tegra20-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL),
92 OF_DEV_AUXDATA("nvidia,tegra20-sflash", 0x7000c380, "spi", NULL),
93 OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D400, "spi_tegra.0", NULL),
94 OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D600, "spi_tegra.1", NULL),
95 OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D800, "spi_tegra.2", NULL),
96 OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000DA00, "spi_tegra.3", NULL),
97 OF_DEV_AUXDATA("nvidia,tegra20-host1x", 0x50000000, "host1x", NULL),
98 OF_DEV_AUXDATA("nvidia,tegra20-dc", 0x54200000, "tegradc.0", NULL),
99 OF_DEV_AUXDATA("nvidia,tegra20-dc", 0x54240000, "tegradc.1", NULL),
100 OF_DEV_AUXDATA("nvidia,tegra20-hdmi", 0x54280000, "hdmi", NULL),
101 OF_DEV_AUXDATA("nvidia,tegra20-dsi", 0x54300000, "dsi", NULL),
102 OF_DEV_AUXDATA("nvidia,tegra20-tvo", 0x542c0000, "tvo", NULL),
94 {} 103 {}
95}; 104};
96 105
@@ -104,8 +113,20 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
104 { "pll_a", "pll_p_out1", 56448000, true }, 113 { "pll_a", "pll_p_out1", 56448000, true },
105 { "pll_a_out0", "pll_a", 11289600, true }, 114 { "pll_a_out0", "pll_a", 11289600, true },
106 { "cdev1", NULL, 0, true }, 115 { "cdev1", NULL, 0, true },
116 { "blink", "clk_32k", 32768, true },
107 { "i2s1", "pll_a_out0", 11289600, false}, 117 { "i2s1", "pll_a_out0", 11289600, false},
108 { "i2s2", "pll_a_out0", 11289600, false}, 118 { "i2s2", "pll_a_out0", 11289600, false},
119 { "sdmmc1", "pll_p", 48000000, false},
120 { "sdmmc3", "pll_p", 48000000, false},
121 { "sdmmc4", "pll_p", 48000000, false},
122 { "spi", "pll_p", 20000000, false },
123 { "sbc1", "pll_p", 100000000, false },
124 { "sbc2", "pll_p", 100000000, false },
125 { "sbc3", "pll_p", 100000000, false },
126 { "sbc4", "pll_p", 100000000, false },
127 { "host1x", "pll_c", 150000000, false },
128 { "disp1", "pll_p", 600000000, false },
129 { "disp2", "pll_p", 600000000, false },
109 { NULL, NULL, 0, 0}, 130 { NULL, NULL, 0, 0},
110}; 131};
111 132
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
index 5e92a81f9a2e..6497d1236b08 100644
--- a/arch/arm/mach-tegra/board-dt-tegra30.c
+++ b/arch/arm/mach-tegra/board-dt-tegra30.c
@@ -33,11 +33,10 @@
33#include <asm/mach/arch.h> 33#include <asm/mach/arch.h>
34#include <asm/hardware/gic.h> 34#include <asm/hardware/gic.h>
35 35
36#include <mach/iomap.h>
37
38#include "board.h" 36#include "board.h"
39#include "clock.h" 37#include "clock.h"
40#include "common.h" 38#include "common.h"
39#include "iomap.h"
41 40
42struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = { 41struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
43 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL), 42 OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL),
@@ -52,6 +51,18 @@ struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
52 OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL), 51 OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL),
53 OF_DEV_AUXDATA("nvidia,tegra30-apbdma", 0x6000a000, "tegra-apbdma", NULL), 52 OF_DEV_AUXDATA("nvidia,tegra30-apbdma", 0x6000a000, "tegra-apbdma", NULL),
54 OF_DEV_AUXDATA("nvidia,tegra30-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL), 53 OF_DEV_AUXDATA("nvidia,tegra30-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL),
54 OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D400, "spi_tegra.0", NULL),
55 OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D600, "spi_tegra.1", NULL),
56 OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D800, "spi_tegra.2", NULL),
57 OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DA00, "spi_tegra.3", NULL),
58 OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DC00, "spi_tegra.4", NULL),
59 OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DE00, "spi_tegra.5", NULL),
60 OF_DEV_AUXDATA("nvidia,tegra30-host1x", 0x50000000, "host1x", NULL),
61 OF_DEV_AUXDATA("nvidia,tegra30-dc", 0x54200000, "tegradc.0", NULL),
62 OF_DEV_AUXDATA("nvidia,tegra30-dc", 0x54240000, "tegradc.1", NULL),
63 OF_DEV_AUXDATA("nvidia,tegra30-hdmi", 0x54280000, "hdmi", NULL),
64 OF_DEV_AUXDATA("nvidia,tegra30-dsi", 0x54300000, "dsi", NULL),
65 OF_DEV_AUXDATA("nvidia,tegra30-tvo", 0x542c0000, "tvo", NULL),
55 {} 66 {}
56}; 67};
57 68
@@ -62,11 +73,24 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
62 { "pll_a_out0", "pll_a", 11289600, true }, 73 { "pll_a_out0", "pll_a", 11289600, true },
63 { "extern1", "pll_a_out0", 0, true }, 74 { "extern1", "pll_a_out0", 0, true },
64 { "clk_out_1", "extern1", 0, true }, 75 { "clk_out_1", "extern1", 0, true },
76 { "blink", "clk_32k", 32768, true },
65 { "i2s0", "pll_a_out0", 11289600, false}, 77 { "i2s0", "pll_a_out0", 11289600, false},
66 { "i2s1", "pll_a_out0", 11289600, false}, 78 { "i2s1", "pll_a_out0", 11289600, false},
67 { "i2s2", "pll_a_out0", 11289600, false}, 79 { "i2s2", "pll_a_out0", 11289600, false},
68 { "i2s3", "pll_a_out0", 11289600, false}, 80 { "i2s3", "pll_a_out0", 11289600, false},
69 { "i2s4", "pll_a_out0", 11289600, false}, 81 { "i2s4", "pll_a_out0", 11289600, false},
82 { "sdmmc1", "pll_p", 48000000, false},
83 { "sdmmc3", "pll_p", 48000000, false},
84 { "sdmmc4", "pll_p", 48000000, false},
85 { "sbc1", "pll_p", 100000000, false},
86 { "sbc2", "pll_p", 100000000, false},
87 { "sbc3", "pll_p", 100000000, false},
88 { "sbc4", "pll_p", 100000000, false},
89 { "sbc5", "pll_p", 100000000, false},
90 { "sbc6", "pll_p", 100000000, false},
91 { "host1x", "pll_c", 150000000, false},
92 { "disp1", "pll_p", 600000000, false},
93 { "disp2", "pll_p", 600000000, false},
70 { NULL, NULL, 0, 0}, 94 { NULL, NULL, 0, 0},
71}; 95};
72 96
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index fd82085eca5d..867bf8bf5561 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -27,8 +27,6 @@
27#include <linux/seq_file.h> 27#include <linux/seq_file.h>
28#include <linux/slab.h> 28#include <linux/slab.h>
29 29
30#include <mach/clk.h>
31
32#include "board.h" 30#include "board.h"
33#include "clock.h" 31#include "clock.h"
34#include "tegra_cpu_car.h" 32#include "tegra_cpu_car.h"
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 0b0a5f556d34..0816562725f6 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -26,16 +26,17 @@
26#include <asm/hardware/cache-l2x0.h> 26#include <asm/hardware/cache-l2x0.h>
27#include <asm/hardware/gic.h> 27#include <asm/hardware/gic.h>
28 28
29#include <mach/iomap.h>
30#include <mach/powergate.h> 29#include <mach/powergate.h>
31 30
32#include "board.h" 31#include "board.h"
33#include "clock.h" 32#include "clock.h"
34#include "common.h" 33#include "common.h"
35#include "fuse.h" 34#include "fuse.h"
35#include "iomap.h"
36#include "pmc.h" 36#include "pmc.h"
37#include "apbio.h" 37#include "apbio.h"
38#include "sleep.h" 38#include "sleep.h"
39#include "pm.h"
39 40
40/* 41/*
41 * Storage for debug-macro.S's state. 42 * Storage for debug-macro.S's state.
@@ -44,14 +45,15 @@
44 * kernel is loaded. The data is declared here rather than debug-macro.S so 45 * kernel is loaded. The data is declared here rather than debug-macro.S so
45 * that multiple inclusions of debug-macro.S point at the same data. 46 * that multiple inclusions of debug-macro.S point at the same data.
46 */ 47 */
47#define TEGRA_DEBUG_UART_OFFSET (TEGRA_DEBUG_UART_BASE & 0xFFFF) 48u32 tegra_uart_config[4] = {
48u32 tegra_uart_config[3] = {
49 /* Debug UART initialization required */ 49 /* Debug UART initialization required */
50 1, 50 1,
51 /* Debug UART physical address */ 51 /* Debug UART physical address */
52 (u32)(IO_APB_PHYS + TEGRA_DEBUG_UART_OFFSET), 52 0,
53 /* Debug UART virtual address */ 53 /* Debug UART virtual address */
54 (u32)(IO_APB_VIRT + TEGRA_DEBUG_UART_OFFSET), 54 0,
55 /* Scratch space for debug macro */
56 0,
55}; 57};
56 58
57#ifdef CONFIG_OF 59#ifdef CONFIG_OF
@@ -104,25 +106,30 @@ static __initdata struct tegra_clk_init_table tegra30_clk_init_table[] = {
104 { "clk_m", NULL, 0, true }, 106 { "clk_m", NULL, 0, true },
105 { "pll_p", "clk_m", 408000000, true }, 107 { "pll_p", "clk_m", 408000000, true },
106 { "pll_p_out1", "pll_p", 9600000, true }, 108 { "pll_p_out1", "pll_p", 9600000, true },
109 { "pll_p_out4", "pll_p", 102000000, true },
110 { "sclk", "pll_p_out4", 102000000, true },
111 { "hclk", "sclk", 102000000, true },
112 { "pclk", "hclk", 51000000, true },
113 { "csite", NULL, 0, true },
107 { NULL, NULL, 0, 0}, 114 { NULL, NULL, 0, 0},
108}; 115};
109#endif 116#endif
110 117
111 118
112static void __init tegra_init_cache(u32 tag_latency, u32 data_latency) 119static void __init tegra_init_cache(void)
113{ 120{
114#ifdef CONFIG_CACHE_L2X0 121#ifdef CONFIG_CACHE_L2X0
122 int ret;
115 void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; 123 void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
116 u32 aux_ctrl, cache_type; 124 u32 aux_ctrl, cache_type;
117 125
118 writel_relaxed(tag_latency, p + L2X0_TAG_LATENCY_CTRL);
119 writel_relaxed(data_latency, p + L2X0_DATA_LATENCY_CTRL);
120
121 cache_type = readl(p + L2X0_CACHE_TYPE); 126 cache_type = readl(p + L2X0_CACHE_TYPE);
122 aux_ctrl = (cache_type & 0x700) << (17-8); 127 aux_ctrl = (cache_type & 0x700) << (17-8);
123 aux_ctrl |= 0x6C000001; 128 aux_ctrl |= 0x7C400001;
124 129
125 l2x0_init(p, aux_ctrl, 0x8200c3fe); 130 ret = l2x0_of_init(aux_ctrl, 0x8200c3fe);
131 if (!ret)
132 l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs);
126#endif 133#endif
127 134
128} 135}
@@ -134,7 +141,7 @@ void __init tegra20_init_early(void)
134 tegra_init_fuse(); 141 tegra_init_fuse();
135 tegra2_init_clocks(); 142 tegra2_init_clocks();
136 tegra_clk_init_from_table(tegra20_clk_init_table); 143 tegra_clk_init_from_table(tegra20_clk_init_table);
137 tegra_init_cache(0x331, 0x441); 144 tegra_init_cache();
138 tegra_pmc_init(); 145 tegra_pmc_init();
139 tegra_powergate_init(); 146 tegra_powergate_init();
140 tegra20_hotplug_init(); 147 tegra20_hotplug_init();
@@ -147,7 +154,7 @@ void __init tegra30_init_early(void)
147 tegra_init_fuse(); 154 tegra_init_fuse();
148 tegra30_init_clocks(); 155 tegra30_init_clocks();
149 tegra_clk_init_from_table(tegra30_clk_init_table); 156 tegra_clk_init_from_table(tegra30_clk_init_table);
150 tegra_init_cache(0x441, 0x551); 157 tegra_init_cache();
151 tegra_pmc_init(); 158 tegra_pmc_init();
152 tegra_powergate_init(); 159 tegra_powergate_init();
153 tegra30_hotplug_init(); 160 tegra30_hotplug_init();
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index 627bf0f4262e..a74d3c7d2e26 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -30,9 +30,6 @@
30#include <linux/io.h> 30#include <linux/io.h>
31#include <linux/suspend.h> 31#include <linux/suspend.h>
32 32
33
34#include <mach/clk.h>
35
36/* Frequency table index must be sequential starting at 0 */ 33/* Frequency table index must be sequential starting at 0 */
37static struct cpufreq_frequency_table freq_table[] = { 34static struct cpufreq_frequency_table freq_table[] = {
38 { 0, 216000 }, 35 { 0, 216000 },
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
new file mode 100644
index 000000000000..d32e8b0dbd4f
--- /dev/null
+++ b/arch/arm/mach-tegra/cpuidle-tegra20.c
@@ -0,0 +1,66 @@
1/*
2 * CPU idle driver for Tegra CPUs
3 *
4 * Copyright (c) 2010-2012, NVIDIA Corporation.
5 * Copyright (c) 2011 Google, Inc.
6 * Author: Colin Cross <ccross@android.com>
7 * Gary King <gking@nvidia.com>
8 *
9 * Rework for 3.3 by Peter De Schrijver <pdeschrijver@nvidia.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * more details.
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/cpuidle.h>
25
26#include <asm/cpuidle.h>
27
28static struct cpuidle_driver tegra_idle_driver = {
29 .name = "tegra_idle",
30 .owner = THIS_MODULE,
31 .en_core_tk_irqen = 1,
32 .state_count = 1,
33 .states = {
34 [0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
35 },
36};
37
38static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
39
40int __init tegra20_cpuidle_init(void)
41{
42 int ret;
43 unsigned int cpu;
44 struct cpuidle_device *dev;
45 struct cpuidle_driver *drv = &tegra_idle_driver;
46
47 ret = cpuidle_register_driver(&tegra_idle_driver);
48 if (ret) {
49 pr_err("CPUidle driver registration failed\n");
50 return ret;
51 }
52
53 for_each_possible_cpu(cpu) {
54 dev = &per_cpu(tegra_idle_device, cpu);
55 dev->cpu = cpu;
56
57 dev->state_count = drv->state_count;
58 ret = cpuidle_register_device(dev);
59 if (ret) {
60 pr_err("CPU%u: CPUidle device registration failed\n",
61 cpu);
62 return ret;
63 }
64 }
65 return 0;
66}
diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
new file mode 100644
index 000000000000..5e8cbf5b799f
--- /dev/null
+++ b/arch/arm/mach-tegra/cpuidle-tegra30.c
@@ -0,0 +1,188 @@
1/*
2 * CPU idle driver for Tegra CPUs
3 *
4 * Copyright (c) 2010-2012, NVIDIA Corporation.
5 * Copyright (c) 2011 Google, Inc.
6 * Author: Colin Cross <ccross@android.com>
7 * Gary King <gking@nvidia.com>
8 *
9 * Rework for 3.3 by Peter De Schrijver <pdeschrijver@nvidia.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * more details.
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/cpuidle.h>
25#include <linux/cpu_pm.h>
26#include <linux/clockchips.h>
27
28#include <asm/cpuidle.h>
29#include <asm/proc-fns.h>
30#include <asm/suspend.h>
31#include <asm/smp_plat.h>
32
33#include "pm.h"
34#include "sleep.h"
35#include "tegra_cpu_car.h"
36
37#ifdef CONFIG_PM_SLEEP
38static int tegra30_idle_lp2(struct cpuidle_device *dev,
39 struct cpuidle_driver *drv,
40 int index);
41#endif
42
43static struct cpuidle_driver tegra_idle_driver = {
44 .name = "tegra_idle",
45 .owner = THIS_MODULE,
46 .en_core_tk_irqen = 1,
47#ifdef CONFIG_PM_SLEEP
48 .state_count = 2,
49#else
50 .state_count = 1,
51#endif
52 .states = {
53 [0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
54#ifdef CONFIG_PM_SLEEP
55 [1] = {
56 .enter = tegra30_idle_lp2,
57 .exit_latency = 2000,
58 .target_residency = 2200,
59 .power_usage = 0,
60 .flags = CPUIDLE_FLAG_TIME_VALID,
61 .name = "powered-down",
62 .desc = "CPU power gated",
63 },
64#endif
65 },
66};
67
68static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
69
70#ifdef CONFIG_PM_SLEEP
71static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
72 struct cpuidle_driver *drv,
73 int index)
74{
75 struct cpuidle_state *state = &drv->states[index];
76 u32 cpu_on_time = state->exit_latency;
77 u32 cpu_off_time = state->target_residency - state->exit_latency;
78
79 /* All CPUs entering LP2 is not working.
80 * Don't let CPU0 enter LP2 when any secondary CPU is online.
81 */
82 if (num_online_cpus() > 1 || !tegra_cpu_rail_off_ready()) {
83 cpu_do_idle();
84 return false;
85 }
86
87 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
88
89 tegra_idle_lp2_last(cpu_on_time, cpu_off_time);
90
91 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
92
93 return true;
94}
95
96#ifdef CONFIG_SMP
97static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
98 struct cpuidle_driver *drv,
99 int index)
100{
101 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
102
103 smp_wmb();
104
105 save_cpu_arch_register();
106
107 cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
108
109 restore_cpu_arch_register();
110
111 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
112
113 return true;
114}
115#else
116static inline bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
117 struct cpuidle_driver *drv,
118 int index)
119{
120 return true;
121}
122#endif
123
124static int __cpuinit tegra30_idle_lp2(struct cpuidle_device *dev,
125 struct cpuidle_driver *drv,
126 int index)
127{
128 u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu;
129 bool entered_lp2 = false;
130 bool last_cpu;
131
132 local_fiq_disable();
133
134 last_cpu = tegra_set_cpu_in_lp2(cpu);
135 cpu_pm_enter();
136
137 if (cpu == 0) {
138 if (last_cpu)
139 entered_lp2 = tegra30_cpu_cluster_power_down(dev, drv,
140 index);
141 else
142 cpu_do_idle();
143 } else {
144 entered_lp2 = tegra30_cpu_core_power_down(dev, drv, index);
145 }
146
147 cpu_pm_exit();
148 tegra_clear_cpu_in_lp2(cpu);
149
150 local_fiq_enable();
151
152 smp_rmb();
153
154 return (entered_lp2) ? index : 0;
155}
156#endif
157
158int __init tegra30_cpuidle_init(void)
159{
160 int ret;
161 unsigned int cpu;
162 struct cpuidle_device *dev;
163 struct cpuidle_driver *drv = &tegra_idle_driver;
164
165#ifdef CONFIG_PM_SLEEP
166 tegra_tear_down_cpu = tegra30_tear_down_cpu;
167#endif
168
169 ret = cpuidle_register_driver(&tegra_idle_driver);
170 if (ret) {
171 pr_err("CPUidle driver registration failed\n");
172 return ret;
173 }
174
175 for_each_possible_cpu(cpu) {
176 dev = &per_cpu(tegra_idle_device, cpu);
177 dev->cpu = cpu;
178
179 dev->state_count = drv->state_count;
180 ret = cpuidle_register_device(dev);
181 if (ret) {
182 pr_err("CPU%u: CPUidle device registration failed\n",
183 cpu);
184 return ret;
185 }
186 }
187 return 0;
188}
diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
index 566e2f88899b..d0651397aec7 100644
--- a/arch/arm/mach-tegra/cpuidle.c
+++ b/arch/arm/mach-tegra/cpuidle.c
@@ -23,85 +23,26 @@
23 23
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/cpu.h>
27#include <linux/cpuidle.h>
28#include <linux/hrtimer.h>
29 26
30#include <asm/proc-fns.h> 27#include "fuse.h"
31 28#include "cpuidle.h"
32#include <mach/iomap.h>
33
34static int tegra_idle_enter_lp3(struct cpuidle_device *dev,
35 struct cpuidle_driver *drv, int index);
36
37struct cpuidle_driver tegra_idle_driver = {
38 .name = "tegra_idle",
39 .owner = THIS_MODULE,
40 .state_count = 1,
41 .states = {
42 [0] = {
43 .enter = tegra_idle_enter_lp3,
44 .exit_latency = 10,
45 .target_residency = 10,
46 .power_usage = 600,
47 .flags = CPUIDLE_FLAG_TIME_VALID,
48 .name = "LP3",
49 .desc = "CPU flow-controlled",
50 },
51 },
52};
53
54static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
55
56static int tegra_idle_enter_lp3(struct cpuidle_device *dev,
57 struct cpuidle_driver *drv, int index)
58{
59 ktime_t enter, exit;
60 s64 us;
61
62 local_irq_disable();
63 local_fiq_disable();
64
65 enter = ktime_get();
66
67 cpu_do_idle();
68
69 exit = ktime_sub(ktime_get(), enter);
70 us = ktime_to_us(exit);
71
72 local_fiq_enable();
73 local_irq_enable();
74
75 dev->last_residency = us;
76
77 return index;
78}
79 29
80static int __init tegra_cpuidle_init(void) 30static int __init tegra_cpuidle_init(void)
81{ 31{
82 int ret; 32 int ret;
83 unsigned int cpu;
84 struct cpuidle_device *dev;
85 struct cpuidle_driver *drv = &tegra_idle_driver;
86 33
87 ret = cpuidle_register_driver(&tegra_idle_driver); 34 switch (tegra_chip_id) {
88 if (ret) { 35 case TEGRA20:
89 pr_err("CPUidle driver registration failed\n"); 36 ret = tegra20_cpuidle_init();
90 return ret; 37 break;
38 case TEGRA30:
39 ret = tegra30_cpuidle_init();
40 break;
41 default:
42 ret = -ENODEV;
43 break;
91 } 44 }
92 45
93 for_each_possible_cpu(cpu) { 46 return ret;
94 dev = &per_cpu(tegra_idle_device, cpu);
95 dev->cpu = cpu;
96
97 dev->state_count = drv->state_count;
98 ret = cpuidle_register_device(dev);
99 if (ret) {
100 pr_err("CPU%u: CPUidle device registration failed\n",
101 cpu);
102 return ret;
103 }
104 }
105 return 0;
106} 47}
107device_initcall(tegra_cpuidle_init); 48device_initcall(tegra_cpuidle_init);
diff --git a/arch/arm/mach-tegra/cpuidle.h b/arch/arm/mach-tegra/cpuidle.h
new file mode 100644
index 000000000000..496204d34e55
--- /dev/null
+++ b/arch/arm/mach-tegra/cpuidle.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef __MACH_TEGRA_CPUIDLE_H
18#define __MACH_TEGRA_CPUIDLE_H
19
20#ifdef CONFIG_ARCH_TEGRA_2x_SOC
21int tegra20_cpuidle_init(void);
22#else
23static inline int tegra20_cpuidle_init(void) { return -ENODEV; }
24#endif
25
26#ifdef CONFIG_ARCH_TEGRA_3x_SOC
27int tegra30_cpuidle_init(void);
28#else
29static inline int tegra30_cpuidle_init(void) { return -ENODEV; }
30#endif
31
32#endif
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
index f07488e0bd32..a2250ddae797 100644
--- a/arch/arm/mach-tegra/flowctrl.c
+++ b/arch/arm/mach-tegra/flowctrl.c
@@ -21,10 +21,10 @@
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/io.h> 23#include <linux/io.h>
24 24#include <linux/cpumask.h>
25#include <mach/iomap.h>
26 25
27#include "flowctrl.h" 26#include "flowctrl.h"
27#include "iomap.h"
28 28
29u8 flowctrl_offset_halt_cpu[] = { 29u8 flowctrl_offset_halt_cpu[] = {
30 FLOW_CTRL_HALT_CPU0_EVENTS, 30 FLOW_CTRL_HALT_CPU0_EVENTS,
@@ -51,6 +51,14 @@ static void flowctrl_update(u8 offset, u32 value)
51 readl_relaxed(addr); 51 readl_relaxed(addr);
52} 52}
53 53
54u32 flowctrl_read_cpu_csr(unsigned int cpuid)
55{
56 u8 offset = flowctrl_offset_cpu_csr[cpuid];
57 void __iomem *addr = IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + offset;
58
59 return readl(addr);
60}
61
54void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value) 62void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
55{ 63{
56 return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value); 64 return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value);
@@ -60,3 +68,41 @@ void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value)
60{ 68{
61 return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value); 69 return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value);
62} 70}
71
72void flowctrl_cpu_suspend_enter(unsigned int cpuid)
73{
74 unsigned int reg;
75 int i;
76
77 reg = flowctrl_read_cpu_csr(cpuid);
78 reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP; /* clear wfe bitmap */
79 reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP; /* clear wfi bitmap */
80 reg |= FLOW_CTRL_CSR_INTR_FLAG; /* clear intr flag */
81 reg |= FLOW_CTRL_CSR_EVENT_FLAG; /* clear event flag */
82 reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid; /* pwr gating on wfi */
83 reg |= FLOW_CTRL_CSR_ENABLE; /* pwr gating */
84 flowctrl_write_cpu_csr(cpuid, reg);
85
86 for (i = 0; i < num_possible_cpus(); i++) {
87 if (i == cpuid)
88 continue;
89 reg = flowctrl_read_cpu_csr(i);
90 reg |= FLOW_CTRL_CSR_EVENT_FLAG;
91 reg |= FLOW_CTRL_CSR_INTR_FLAG;
92 flowctrl_write_cpu_csr(i, reg);
93 }
94}
95
96void flowctrl_cpu_suspend_exit(unsigned int cpuid)
97{
98 unsigned int reg;
99
100 /* Disable powergating via flow controller for CPU0 */
101 reg = flowctrl_read_cpu_csr(cpuid);
102 reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP; /* clear wfe bitmap */
103 reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP; /* clear wfi bitmap */
104 reg &= ~FLOW_CTRL_CSR_ENABLE; /* clear enable */
105 reg |= FLOW_CTRL_CSR_INTR_FLAG; /* clear intr */
106 reg |= FLOW_CTRL_CSR_EVENT_FLAG; /* clear event */
107 flowctrl_write_cpu_csr(cpuid, reg);
108}
diff --git a/arch/arm/mach-tegra/flowctrl.h b/arch/arm/mach-tegra/flowctrl.h
index 19428173855e..0798dec1832d 100644
--- a/arch/arm/mach-tegra/flowctrl.h
+++ b/arch/arm/mach-tegra/flowctrl.h
@@ -34,9 +34,17 @@
34#define FLOW_CTRL_HALT_CPU1_EVENTS 0x14 34#define FLOW_CTRL_HALT_CPU1_EVENTS 0x14
35#define FLOW_CTRL_CPU1_CSR 0x18 35#define FLOW_CTRL_CPU1_CSR 0x18
36 36
37#define TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 (1 << 8)
38#define TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP (0xF << 4)
39#define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP (0xF << 8)
40
37#ifndef __ASSEMBLY__ 41#ifndef __ASSEMBLY__
42u32 flowctrl_read_cpu_csr(unsigned int cpuid);
38void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value); 43void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value);
39void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value); 44void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value);
45
46void flowctrl_cpu_suspend_enter(unsigned int cpuid);
47void flowctrl_cpu_suspend_exit(unsigned int cpuid);
40#endif 48#endif
41 49
42#endif 50#endif
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index 0b7db174a5de..8121742711fe 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -21,22 +21,28 @@
21#include <linux/io.h> 21#include <linux/io.h>
22#include <linux/export.h> 22#include <linux/export.h>
23 23
24#include <mach/iomap.h>
25
26#include "fuse.h" 24#include "fuse.h"
25#include "iomap.h"
27#include "apbio.h" 26#include "apbio.h"
28 27
29#define FUSE_UID_LOW 0x108 28#define FUSE_UID_LOW 0x108
30#define FUSE_UID_HIGH 0x10c 29#define FUSE_UID_HIGH 0x10c
31#define FUSE_SKU_INFO 0x110 30#define FUSE_SKU_INFO 0x110
32#define FUSE_SPARE_BIT 0x200 31
32#define TEGRA20_FUSE_SPARE_BIT 0x200
33#define TEGRA30_FUSE_SPARE_BIT 0x244
33 34
34int tegra_sku_id; 35int tegra_sku_id;
35int tegra_cpu_process_id; 36int tegra_cpu_process_id;
36int tegra_core_process_id; 37int tegra_core_process_id;
37int tegra_chip_id; 38int tegra_chip_id;
39int tegra_cpu_speedo_id; /* only exist in Tegra30 and later */
40int tegra_soc_speedo_id;
38enum tegra_revision tegra_revision; 41enum tegra_revision tegra_revision;
39 42
43static int tegra_fuse_spare_bit;
44static void (*tegra_init_speedo_data)(void);
45
40/* The BCT to use at boot is specified by board straps that can be read 46/* The BCT to use at boot is specified by board straps that can be read
41 * through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs. 47 * through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs.
42 */ 48 */
@@ -57,14 +63,14 @@ static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
57 [TEGRA_REVISION_A04] = "A04", 63 [TEGRA_REVISION_A04] = "A04",
58}; 64};
59 65
60static inline u32 tegra_fuse_readl(unsigned long offset) 66u32 tegra_fuse_readl(unsigned long offset)
61{ 67{
62 return tegra_apb_readl(TEGRA_FUSE_BASE + offset); 68 return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
63} 69}
64 70
65static inline bool get_spare_fuse(int bit) 71bool tegra_spare_fuse(int bit)
66{ 72{
67 return tegra_fuse_readl(FUSE_SPARE_BIT + bit * 4); 73 return tegra_fuse_readl(tegra_fuse_spare_bit + bit * 4);
68} 74}
69 75
70static enum tegra_revision tegra_get_revision(u32 id) 76static enum tegra_revision tegra_get_revision(u32 id)
@@ -78,7 +84,7 @@ static enum tegra_revision tegra_get_revision(u32 id)
78 return TEGRA_REVISION_A02; 84 return TEGRA_REVISION_A02;
79 case 3: 85 case 3:
80 if (tegra_chip_id == TEGRA20 && 86 if (tegra_chip_id == TEGRA20 &&
81 (get_spare_fuse(18) || get_spare_fuse(19))) 87 (tegra_spare_fuse(18) || tegra_spare_fuse(19)))
82 return TEGRA_REVISION_A03p; 88 return TEGRA_REVISION_A03p;
83 else 89 else
84 return TEGRA_REVISION_A03; 90 return TEGRA_REVISION_A03;
@@ -89,6 +95,16 @@ static enum tegra_revision tegra_get_revision(u32 id)
89 } 95 }
90} 96}
91 97
98static void tegra_get_process_id(void)
99{
100 u32 reg;
101
102 reg = tegra_fuse_readl(tegra_fuse_spare_bit);
103 tegra_cpu_process_id = (reg >> 6) & 3;
104 reg = tegra_fuse_readl(tegra_fuse_spare_bit);
105 tegra_core_process_id = (reg >> 12) & 3;
106}
107
92void tegra_init_fuse(void) 108void tegra_init_fuse(void)
93{ 109{
94 u32 id; 110 u32 id;
@@ -100,19 +116,29 @@ void tegra_init_fuse(void)
100 reg = tegra_fuse_readl(FUSE_SKU_INFO); 116 reg = tegra_fuse_readl(FUSE_SKU_INFO);
101 tegra_sku_id = reg & 0xFF; 117 tegra_sku_id = reg & 0xFF;
102 118
103 reg = tegra_fuse_readl(FUSE_SPARE_BIT);
104 tegra_cpu_process_id = (reg >> 6) & 3;
105
106 reg = tegra_fuse_readl(FUSE_SPARE_BIT);
107 tegra_core_process_id = (reg >> 12) & 3;
108
109 reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT); 119 reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
110 tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT; 120 tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
111 121
112 id = readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804); 122 id = readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804);
113 tegra_chip_id = (id >> 8) & 0xff; 123 tegra_chip_id = (id >> 8) & 0xff;
114 124
125 switch (tegra_chip_id) {
126 case TEGRA20:
127 tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
128 tegra_init_speedo_data = &tegra20_init_speedo_data;
129 break;
130 case TEGRA30:
131 tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT;
132 tegra_init_speedo_data = &tegra30_init_speedo_data;
133 break;
134 default:
135 pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id);
136 tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
137 tegra_init_speedo_data = &tegra_get_process_id;
138 }
139
115 tegra_revision = tegra_get_revision(id); 140 tegra_revision = tegra_get_revision(id);
141 tegra_init_speedo_data();
116 142
117 pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n", 143 pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
118 tegra_revision_name[tegra_revision], 144 tegra_revision_name[tegra_revision],
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
index d2107b2cb85a..ff1383dd61a7 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -42,11 +42,27 @@ extern int tegra_sku_id;
42extern int tegra_cpu_process_id; 42extern int tegra_cpu_process_id;
43extern int tegra_core_process_id; 43extern int tegra_core_process_id;
44extern int tegra_chip_id; 44extern int tegra_chip_id;
45extern int tegra_cpu_speedo_id; /* only exist in Tegra30 and later */
46extern int tegra_soc_speedo_id;
45extern enum tegra_revision tegra_revision; 47extern enum tegra_revision tegra_revision;
46 48
47extern int tegra_bct_strapping; 49extern int tegra_bct_strapping;
48 50
49unsigned long long tegra_chip_uid(void); 51unsigned long long tegra_chip_uid(void);
50void tegra_init_fuse(void); 52void tegra_init_fuse(void);
53bool tegra_spare_fuse(int bit);
54u32 tegra_fuse_readl(unsigned long offset);
55
56#ifdef CONFIG_ARCH_TEGRA_2x_SOC
57void tegra20_init_speedo_data(void);
58#else
59static inline void tegra20_init_speedo_data(void) {}
60#endif
61
62#ifdef CONFIG_ARCH_TEGRA_3x_SOC
63void tegra30_init_speedo_data(void);
64#else
65static inline void tegra30_init_speedo_data(void) {}
66#endif
51 67
52#endif 68#endif
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index 6addc78cb6b2..4a317fae6860 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -2,10 +2,11 @@
2#include <linux/init.h> 2#include <linux/init.h>
3 3
4#include <asm/cache.h> 4#include <asm/cache.h>
5 5#include <asm/asm-offsets.h>
6#include <mach/iomap.h> 6#include <asm/hardware/cache-l2x0.h>
7 7
8#include "flowctrl.h" 8#include "flowctrl.h"
9#include "iomap.h"
9#include "reset.h" 10#include "reset.h"
10#include "sleep.h" 11#include "sleep.h"
11 12
@@ -69,6 +70,64 @@ ENTRY(tegra_secondary_startup)
69 b secondary_startup 70 b secondary_startup
70ENDPROC(tegra_secondary_startup) 71ENDPROC(tegra_secondary_startup)
71 72
73#ifdef CONFIG_PM_SLEEP
74/*
75 * tegra_resume
76 *
77 * CPU boot vector when restarting the a CPU following
78 * an LP2 transition. Also branched to by LP0 and LP1 resume after
79 * re-enabling sdram.
80 */
81ENTRY(tegra_resume)
82 bl v7_invalidate_l1
83 /* Enable coresight */
84 mov32 r0, 0xC5ACCE55
85 mcr p14, 0, r0, c7, c12, 6
86
87 cpu_id r0
88 cmp r0, #0 @ CPU0?
89 bne cpu_resume @ no
90
91#ifdef CONFIG_ARCH_TEGRA_3x_SOC
92 /* Are we on Tegra20? */
93 mov32 r6, TEGRA_APB_MISC_BASE
94 ldr r0, [r6, #APB_MISC_GP_HIDREV]
95 and r0, r0, #0xff00
96 cmp r0, #(0x20 << 8)
97 beq 1f @ Yes
98 /* Clear the flow controller flags for this CPU. */
99 mov32 r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR @ CPU0 CSR
100 ldr r1, [r2]
101 /* Clear event & intr flag */
102 orr r1, r1, \
103 #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
104 movw r0, #0x0FFD @ enable, cluster_switch, immed, & bitmaps
105 bic r1, r1, r0
106 str r1, [r2]
1071:
108#endif
109
110#ifdef CONFIG_HAVE_ARM_SCU
111 /* enable SCU */
112 mov32 r0, TEGRA_ARM_PERIF_BASE
113 ldr r1, [r0]
114 orr r1, r1, #1
115 str r1, [r0]
116#endif
117
118 /* L2 cache resume & re-enable */
119 l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
120
121 b cpu_resume
122ENDPROC(tegra_resume)
123#endif
124
125#ifdef CONFIG_CACHE_L2X0
126 .globl l2x0_saved_regs_addr
127l2x0_saved_regs_addr:
128 .long 0
129#endif
130
72 .align L1_CACHE_SHIFT 131 .align L1_CACHE_SHIFT
73ENTRY(__tegra_cpu_reset_handler_start) 132ENTRY(__tegra_cpu_reset_handler_start)
74 133
@@ -122,6 +181,17 @@ ENTRY(__tegra_cpu_reset_handler)
1221: 1811:
123#endif 182#endif
124 183
184 /* Waking up from LP2? */
185 ldr r9, [r12, #RESET_DATA(MASK_LP2)]
186 tst r9, r11 @ if in_lp2
187 beq __is_not_lp2
188 ldr lr, [r12, #RESET_DATA(STARTUP_LP2)]
189 cmp lr, #0
190 bleq __die @ no LP2 startup handler
191 bx lr
192
193__is_not_lp2:
194
125#ifdef CONFIG_SMP 195#ifdef CONFIG_SMP
126 /* 196 /*
127 * Can only be secondary boot (initial or hotplug) but CPU 0 197 * Can only be secondary boot (initial or hotplug) but CPU 0
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S
deleted file mode 100644
index 8ce0661b8a3d..000000000000
--- a/arch/arm/mach-tegra/include/mach/debug-macro.S
+++ /dev/null
@@ -1,100 +0,0 @@
1/*
2 * arch/arm/mach-tegra/include/mach/debug-macro.S
3 *
4 * Copyright (C) 2010,2011 Google, Inc.
5 * Copyright (C) 2011-2012 NVIDIA CORPORATION. All Rights Reserved.
6 *
7 * Author:
8 * Colin Cross <ccross@google.com>
9 * Erik Gilling <konkers@google.com>
10 * Doug Anderson <dianders@chromium.org>
11 * Stephen Warren <swarren@nvidia.com>
12 *
13 * Portions based on mach-omap2's debug-macro.S
14 * Copyright (C) 1994-1999 Russell King
15 *
16 * This software is licensed under the terms of the GNU General Public
17 * License version 2, as published by the Free Software Foundation, and
18 * may be copied, distributed, and modified under those terms.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 */
26
27#include <linux/serial_reg.h>
28
29#include <mach/iomap.h>
30#include <mach/irammap.h>
31
32 .macro addruart, rp, rv, tmp
33 adr \rp, 99f @ actual addr of 99f
34 ldr \rv, [\rp] @ linked addr is stored there
35 sub \rv, \rv, \rp @ offset between the two
36 ldr \rp, [\rp, #4] @ linked tegra_uart_config
37 sub \tmp, \rp, \rv @ actual tegra_uart_config
38 ldr \rp, [\tmp] @ Load tegra_uart_config
39 cmp \rp, #1 @ needs intitialization?
40 bne 100f @ no; go load the addresses
41 mov \rv, #0 @ yes; record init is done
42 str \rv, [\tmp]
43 mov \rp, #TEGRA_IRAM_BASE @ See if cookie is in IRAM
44 ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET]
45 movw \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE & 0xffff
46 movt \rp, #TEGRA_IRAM_DEBUG_UART_COOKIE >> 16
47 cmp \rv, \rp @ Cookie present?
48 bne 100f @ No, use default UART
49 mov \rp, #TEGRA_IRAM_BASE @ Load UART address from IRAM
50 ldr \rv, [\rp, #TEGRA_IRAM_DEBUG_UART_OFFSET + 4]
51 str \rv, [\tmp, #4] @ Store in tegra_uart_phys
52 sub \rv, \rv, #IO_APB_PHYS @ Calculate virt address
53 add \rv, \rv, #IO_APB_VIRT
54 str \rv, [\tmp, #8] @ Store in tegra_uart_virt
55 b 100f
56
57 .align
5899: .word .
59 .word tegra_uart_config
60 .ltorg
61
62100: ldr \rp, [\tmp, #4] @ Load tegra_uart_phys
63 ldr \rv, [\tmp, #8] @ Load tegra_uart_virt
64 .endm
65
66#define UART_SHIFT 2
67
68/*
69 * Code below is swiped from <asm/hardware/debug-8250.S>, but add an extra
70 * check to make sure that we aren't in the CONFIG_TEGRA_DEBUG_UART_NONE case.
71 * We use the fact that all 5 valid UART addresses all have something in the
72 * 2nd-to-lowest byte.
73 */
74
75 .macro senduart, rd, rx
76 tst \rx, #0x0000ff00
77 strneb \rd, [\rx, #UART_TX << UART_SHIFT]
781001:
79 .endm
80
81 .macro busyuart, rd, rx
82 tst \rx, #0x0000ff00
83 beq 1002f
841001: ldrb \rd, [\rx, #UART_LSR << UART_SHIFT]
85 and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
86 teq \rd, #UART_LSR_TEMT | UART_LSR_THRE
87 bne 1001b
881002:
89 .endm
90
91 .macro waituart, rd, rx
92#ifdef FLOW_CONTROL
93 tst \rx, #0x0000ff00
94 beq 1002f
951001: ldrb \rd, [\rx, #UART_MSR << UART_SHIFT]
96 tst \rd, #UART_MSR_CTS
97 beq 1001b
981002:
99#endif
100 .endm
diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h
deleted file mode 100644
index 3081cc6dda3b..000000000000
--- a/arch/arm/mach-tegra/include/mach/dma.h
+++ /dev/null
@@ -1,54 +0,0 @@
1/*
2 * arch/arm/mach-tegra/include/mach/dma.h
3 *
4 * Copyright (c) 2008-2009, NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#ifndef __MACH_TEGRA_DMA_H
22#define __MACH_TEGRA_DMA_H
23
24#include <linux/list.h>
25
26#define TEGRA_DMA_REQ_SEL_CNTR 0
27#define TEGRA_DMA_REQ_SEL_I2S_2 1
28#define TEGRA_DMA_REQ_SEL_I2S_1 2
29#define TEGRA_DMA_REQ_SEL_SPD_I 3
30#define TEGRA_DMA_REQ_SEL_UI_I 4
31#define TEGRA_DMA_REQ_SEL_MIPI 5
32#define TEGRA_DMA_REQ_SEL_I2S2_2 6
33#define TEGRA_DMA_REQ_SEL_I2S2_1 7
34#define TEGRA_DMA_REQ_SEL_UARTA 8
35#define TEGRA_DMA_REQ_SEL_UARTB 9
36#define TEGRA_DMA_REQ_SEL_UARTC 10
37#define TEGRA_DMA_REQ_SEL_SPI 11
38#define TEGRA_DMA_REQ_SEL_AC97 12
39#define TEGRA_DMA_REQ_SEL_ACMODEM 13
40#define TEGRA_DMA_REQ_SEL_SL4B 14
41#define TEGRA_DMA_REQ_SEL_SL2B1 15
42#define TEGRA_DMA_REQ_SEL_SL2B2 16
43#define TEGRA_DMA_REQ_SEL_SL2B3 17
44#define TEGRA_DMA_REQ_SEL_SL2B4 18
45#define TEGRA_DMA_REQ_SEL_UARTD 19
46#define TEGRA_DMA_REQ_SEL_UARTE 20
47#define TEGRA_DMA_REQ_SEL_I2C 21
48#define TEGRA_DMA_REQ_SEL_I2C2 22
49#define TEGRA_DMA_REQ_SEL_I2C3 23
50#define TEGRA_DMA_REQ_SEL_DVC_I2C 24
51#define TEGRA_DMA_REQ_SEL_OWR 25
52#define TEGRA_DMA_REQ_SEL_INVALID 31
53
54#endif
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h
deleted file mode 100644
index aad1a2c1d714..000000000000
--- a/arch/arm/mach-tegra/include/mach/irqs.h
+++ /dev/null
@@ -1,182 +0,0 @@
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_CPU1_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/* Tegra30 has 5 banks of 32 IRQs */
169#define INT_MAIN_NR (32 * 5)
170#define INT_GPIO_BASE (INT_PRI_BASE + INT_MAIN_NR)
171
172/* Tegra30 has 8 banks of 32 GPIOs */
173#define INT_GPIO_NR (32 * 8)
174
175#define TEGRA_NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR)
176
177#define INT_BOARD_BASE TEGRA_NR_IRQS
178#define NR_BOARD_IRQS 32
179
180#define NR_IRQS (INT_BOARD_BASE + NR_BOARD_IRQS)
181
182#endif
diff --git a/arch/arm/mach-tegra/include/mach/powergate.h b/arch/arm/mach-tegra/include/mach/powergate.h
index 4752b1a68f35..06763fe7529d 100644
--- a/arch/arm/mach-tegra/include/mach/powergate.h
+++ b/arch/arm/mach-tegra/include/mach/powergate.h
@@ -20,6 +20,8 @@
20#ifndef _MACH_TEGRA_POWERGATE_H_ 20#ifndef _MACH_TEGRA_POWERGATE_H_
21#define _MACH_TEGRA_POWERGATE_H_ 21#define _MACH_TEGRA_POWERGATE_H_
22 22
23struct clk;
24
23#define TEGRA_POWERGATE_CPU 0 25#define TEGRA_POWERGATE_CPU 0
24#define TEGRA_POWERGATE_3D 1 26#define TEGRA_POWERGATE_3D 1
25#define TEGRA_POWERGATE_VENC 2 27#define TEGRA_POWERGATE_VENC 2
diff --git a/arch/arm/mach-tegra/include/mach/tegra-ahb.h b/arch/arm/mach-tegra/include/mach/tegra-ahb.h
deleted file mode 100644
index e0f8c84b1d8c..000000000000
--- a/arch/arm/mach-tegra/include/mach/tegra-ahb.h
+++ /dev/null
@@ -1,19 +0,0 @@
1/*
2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#ifndef __MACH_TEGRA_AHB_H__
15#define __MACH_TEGRA_AHB_H__
16
17extern int tegra_ahb_enable_smmu(struct device_node *ahb);
18
19#endif /* __MACH_TEGRA_AHB_H__ */
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h
index 937c4c50219e..485003f9b636 100644
--- a/arch/arm/mach-tegra/include/mach/uncompress.h
+++ b/arch/arm/mach-tegra/include/mach/uncompress.h
@@ -28,8 +28,7 @@
28#include <linux/types.h> 28#include <linux/types.h>
29#include <linux/serial_reg.h> 29#include <linux/serial_reg.h>
30 30
31#include <mach/iomap.h> 31#include "../../iomap.h"
32#include <mach/irammap.h>
33 32
34#define BIT(x) (1 << (x)) 33#define BIT(x) (1 << (x))
35#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 34#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -52,17 +51,6 @@ static inline void flush(void)
52{ 51{
53} 52}
54 53
55static inline void save_uart_address(void)
56{
57 u32 *buf = (u32 *)(TEGRA_IRAM_BASE + TEGRA_IRAM_DEBUG_UART_OFFSET);
58
59 if (uart) {
60 buf[0] = TEGRA_IRAM_DEBUG_UART_COOKIE;
61 buf[1] = (u32)uart;
62 } else
63 buf[0] = 0;
64}
65
66static const struct { 54static const struct {
67 u32 base; 55 u32 base;
68 u32 reset_reg; 56 u32 reset_reg;
@@ -139,51 +127,19 @@ int auto_odmdata(void)
139} 127}
140#endif 128#endif
141 129
142#ifdef CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH
143int auto_scratch(void)
144{
145 int i;
146
147 /*
148 * Look for the first UART that:
149 * a) Is not in reset.
150 * b) Is clocked.
151 * c) Has a 'D' in the scratchpad register.
152 *
153 * Note that on Tegra30, the first two conditions are required, since
154 * if not true, accesses to the UART scratch register will hang.
155 * Tegra20 doesn't have this issue.
156 *
157 * The intent is that the bootloader will tell the kernel which UART
158 * to use by setting up those conditions. If nothing found, we'll fall
159 * back to what's specified in TEGRA_DEBUG_UART_BASE.
160 */
161 for (i = 0; i < ARRAY_SIZE(uarts); i++) {
162 if (!uart_clocked(i))
163 continue;
164
165 uart = (volatile u8 *)uarts[i].base;
166 if (uart[UART_SCR << DEBUG_UART_SHIFT] != 'D')
167 continue;
168
169 return i;
170 }
171
172 return -1;
173}
174#endif
175
176/* 130/*
177 * Setup before decompression. This is where we do UART selection for 131 * Setup before decompression. This is where we do UART selection for
178 * earlyprintk and init the uart_base register. 132 * earlyprintk and init the uart_base register.
179 */ 133 */
180static inline void arch_decomp_setup(void) 134static inline void arch_decomp_setup(void)
181{ 135{
182 int uart_id, auto_uart_id; 136 int uart_id;
183 volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE; 137 volatile u32 *apb_misc = (volatile u32 *)TEGRA_APB_MISC_BASE;
184 u32 chip, div; 138 u32 chip, div;
185 139
186#if defined(CONFIG_TEGRA_DEBUG_UARTA) 140#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
141 uart_id = auto_odmdata();
142#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
187 uart_id = 0; 143 uart_id = 0;
188#elif defined(CONFIG_TEGRA_DEBUG_UARTB) 144#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
189 uart_id = 1; 145 uart_id = 1;
@@ -193,19 +149,7 @@ static inline void arch_decomp_setup(void)
193 uart_id = 3; 149 uart_id = 3;
194#elif defined(CONFIG_TEGRA_DEBUG_UARTE) 150#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
195 uart_id = 4; 151 uart_id = 4;
196#else
197 uart_id = -1;
198#endif
199
200#if defined(CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA)
201 auto_uart_id = auto_odmdata();
202#elif defined(CONFIG_TEGRA_DEBUG_UART_AUTO_SCRATCH)
203 auto_uart_id = auto_scratch();
204#else
205 auto_uart_id = -1;
206#endif 152#endif
207 if (auto_uart_id != -1)
208 uart_id = auto_uart_id;
209 153
210 if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) || 154 if (uart_id < 0 || uart_id >= ARRAY_SIZE(uarts) ||
211 !uart_clocked(uart_id)) 155 !uart_clocked(uart_id))
@@ -213,7 +157,6 @@ static inline void arch_decomp_setup(void)
213 else 157 else
214 uart = (volatile u8 *)uarts[uart_id].base; 158 uart = (volatile u8 *)uarts[uart_id].base;
215 159
216 save_uart_address();
217 if (uart == NULL) 160 if (uart == NULL)
218 return; 161 return;
219 162
diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c
index 58b4baf9c483..bb9c9c29d181 100644
--- a/arch/arm/mach-tegra/io.c
+++ b/arch/arm/mach-tegra/io.c
@@ -26,9 +26,9 @@
26 26
27#include <asm/page.h> 27#include <asm/page.h>
28#include <asm/mach/map.h> 28#include <asm/mach/map.h>
29#include <mach/iomap.h>
30 29
31#include "board.h" 30#include "board.h"
31#include "iomap.h"
32 32
33static struct map_desc tegra_io_desc[] __initdata = { 33static struct map_desc tegra_io_desc[] __initdata = {
34 { 34 {
@@ -59,5 +59,6 @@ static struct map_desc tegra_io_desc[] __initdata = {
59 59
60void __init tegra_map_common_io(void) 60void __init tegra_map_common_io(void)
61{ 61{
62 debug_ll_io_init();
62 iotable_init(tegra_io_desc, ARRAY_SIZE(tegra_io_desc)); 63 iotable_init(tegra_io_desc, ARRAY_SIZE(tegra_io_desc));
63} 64}
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/iomap.h
index fee3a94c4549..db8be51cad80 100644
--- a/arch/arm/mach-tegra/include/mach/iomap.h
+++ b/arch/arm/mach-tegra/iomap.h
@@ -1,6 +1,4 @@
1/* 1/*
2 * arch/arm/mach-tegra/include/mach/iomap.h
3 *
4 * Copyright (C) 2010 Google, Inc. 2 * Copyright (C) 2010 Google, Inc.
5 * 3 *
6 * Author: 4 * Author:
@@ -263,20 +261,6 @@
263#define TEGRA_SDMMC4_BASE 0xC8000600 261#define TEGRA_SDMMC4_BASE 0xC8000600
264#define TEGRA_SDMMC4_SIZE SZ_512 262#define TEGRA_SDMMC4_SIZE SZ_512
265 263
266#if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
267# define TEGRA_DEBUG_UART_BASE 0
268#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
269# define TEGRA_DEBUG_UART_BASE TEGRA_UARTA_BASE
270#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
271# define TEGRA_DEBUG_UART_BASE TEGRA_UARTB_BASE
272#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
273# define TEGRA_DEBUG_UART_BASE TEGRA_UARTC_BASE
274#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
275# define TEGRA_DEBUG_UART_BASE TEGRA_UARTD_BASE
276#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
277# define TEGRA_DEBUG_UART_BASE TEGRA_UARTE_BASE
278#endif
279
280/* On TEGRA, many peripherals are very closely packed in 264/* On TEGRA, many peripherals are very closely packed in
281 * two 256MB io windows (that actually only use about 64KB 265 * two 256MB io windows (that actually only use about 64KB
282 * at the start of each). 266 * at the start of each).
diff --git a/arch/arm/mach-tegra/include/mach/irammap.h b/arch/arm/mach-tegra/irammap.h
index 0cbe63261854..501952a84344 100644
--- a/arch/arm/mach-tegra/include/mach/irammap.h
+++ b/arch/arm/mach-tegra/irammap.h
@@ -23,13 +23,4 @@
23#define TEGRA_IRAM_RESET_HANDLER_OFFSET 0 23#define TEGRA_IRAM_RESET_HANDLER_OFFSET 0
24#define TEGRA_IRAM_RESET_HANDLER_SIZE SZ_1K 24#define TEGRA_IRAM_RESET_HANDLER_SIZE SZ_1K
25 25
26/*
27 * These locations are written to by uncompress.h, and read by debug-macro.S.
28 * The first word holds the cookie value if the data is valid. The second
29 * word holds the UART physical address.
30 */
31#define TEGRA_IRAM_DEBUG_UART_OFFSET SZ_1K
32#define TEGRA_IRAM_DEBUG_UART_SIZE 8
33#define TEGRA_IRAM_DEBUG_UART_COOKIE 0x55415254
34
35#endif 26#endif
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 2f5bd2db8e1f..b7886f183511 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -25,9 +25,8 @@
25 25
26#include <asm/hardware/gic.h> 26#include <asm/hardware/gic.h>
27 27
28#include <mach/iomap.h>
29
30#include "board.h" 28#include "board.h"
29#include "iomap.h"
31 30
32#define ICTLR_CPU_IEP_VFIQ 0x08 31#define ICTLR_CPU_IEP_VFIQ 0x08
33#define ICTLR_CPU_IEP_FIR 0x14 32#define ICTLR_CPU_IEP_FIR 0x14
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index a8dba6489c9b..53d085871798 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -37,11 +37,14 @@
37#include <asm/sizes.h> 37#include <asm/sizes.h>
38#include <asm/mach/pci.h> 38#include <asm/mach/pci.h>
39 39
40#include <mach/iomap.h>
41#include <mach/clk.h> 40#include <mach/clk.h>
42#include <mach/powergate.h> 41#include <mach/powergate.h>
43 42
44#include "board.h" 43#include "board.h"
44#include "iomap.h"
45
46/* Hack - need to parse this from DT */
47#define INT_PCIE_INTR 130
45 48
46/* register definitions */ 49/* register definitions */
47#define AFI_OFFSET 0x3800 50#define AFI_OFFSET 0x3800
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 81cb26591acf..1b926df99c4b 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -24,8 +24,6 @@
24#include <asm/mach-types.h> 24#include <asm/mach-types.h>
25#include <asm/smp_scu.h> 25#include <asm/smp_scu.h>
26 26
27#include <mach/clk.h>
28#include <mach/iomap.h>
29#include <mach/powergate.h> 27#include <mach/powergate.h>
30 28
31#include "fuse.h" 29#include "fuse.h"
@@ -34,6 +32,7 @@
34#include "tegra_cpu_car.h" 32#include "tegra_cpu_car.h"
35 33
36#include "common.h" 34#include "common.h"
35#include "iomap.h"
37 36
38extern void tegra_secondary_startup(void); 37extern void tegra_secondary_startup(void);
39 38
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
new file mode 100644
index 000000000000..1b11707eaca0
--- /dev/null
+++ b/arch/arm/mach-tegra/pm.c
@@ -0,0 +1,216 @@
1/*
2 * CPU complex suspend & resume functions for Tegra SoCs
3 *
4 * Copyright (c) 2009-2012, NVIDIA Corporation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/kernel.h>
20#include <linux/spinlock.h>
21#include <linux/io.h>
22#include <linux/cpumask.h>
23#include <linux/delay.h>
24#include <linux/cpu_pm.h>
25#include <linux/clk.h>
26#include <linux/err.h>
27
28#include <asm/smp_plat.h>
29#include <asm/cacheflush.h>
30#include <asm/suspend.h>
31#include <asm/idmap.h>
32#include <asm/proc-fns.h>
33#include <asm/tlbflush.h>
34
35#include "iomap.h"
36#include "reset.h"
37#include "flowctrl.h"
38#include "sleep.h"
39#include "tegra_cpu_car.h"
40
41#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
42
43#define PMC_CTRL 0x0
44#define PMC_CPUPWRGOOD_TIMER 0xc8
45#define PMC_CPUPWROFF_TIMER 0xcc
46
47#ifdef CONFIG_PM_SLEEP
48static unsigned int g_diag_reg;
49static DEFINE_SPINLOCK(tegra_lp2_lock);
50static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
51static struct clk *tegra_pclk;
52void (*tegra_tear_down_cpu)(void);
53
54void save_cpu_arch_register(void)
55{
56 /* read diagnostic register */
57 asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
58 return;
59}
60
61void restore_cpu_arch_register(void)
62{
63 /* write diagnostic register */
64 asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
65 return;
66}
67
68static void set_power_timers(unsigned long us_on, unsigned long us_off)
69{
70 unsigned long long ticks;
71 unsigned long long pclk;
72 unsigned long rate;
73 static unsigned long tegra_last_pclk;
74
75 if (tegra_pclk == NULL) {
76 tegra_pclk = clk_get_sys(NULL, "pclk");
77 WARN_ON(IS_ERR(tegra_pclk));
78 }
79
80 rate = clk_get_rate(tegra_pclk);
81
82 if (WARN_ON_ONCE(rate <= 0))
83 pclk = 100000000;
84 else
85 pclk = rate;
86
87 if ((rate != tegra_last_pclk)) {
88 ticks = (us_on * pclk) + 999999ull;
89 do_div(ticks, 1000000);
90 writel((unsigned long)ticks, pmc + PMC_CPUPWRGOOD_TIMER);
91
92 ticks = (us_off * pclk) + 999999ull;
93 do_div(ticks, 1000000);
94 writel((unsigned long)ticks, pmc + PMC_CPUPWROFF_TIMER);
95 wmb();
96 }
97 tegra_last_pclk = pclk;
98}
99
100/*
101 * restore_cpu_complex
102 *
103 * restores cpu clock setting, clears flow controller
104 *
105 * Always called on CPU 0.
106 */
107static void restore_cpu_complex(void)
108{
109 int cpu = smp_processor_id();
110
111 BUG_ON(cpu != 0);
112
113#ifdef CONFIG_SMP
114 cpu = cpu_logical_map(cpu);
115#endif
116
117 /* Restore the CPU clock settings */
118 tegra_cpu_clock_resume();
119
120 flowctrl_cpu_suspend_exit(cpu);
121
122 restore_cpu_arch_register();
123}
124
125/*
126 * suspend_cpu_complex
127 *
128 * saves pll state for use by restart_plls, prepares flow controller for
129 * transition to suspend state
130 *
131 * Must always be called on cpu 0.
132 */
133static void suspend_cpu_complex(void)
134{
135 int cpu = smp_processor_id();
136
137 BUG_ON(cpu != 0);
138
139#ifdef CONFIG_SMP
140 cpu = cpu_logical_map(cpu);
141#endif
142
143 /* Save the CPU clock settings */
144 tegra_cpu_clock_suspend();
145
146 flowctrl_cpu_suspend_enter(cpu);
147
148 save_cpu_arch_register();
149}
150
151void __cpuinit tegra_clear_cpu_in_lp2(int phy_cpu_id)
152{
153 u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
154
155 spin_lock(&tegra_lp2_lock);
156
157 BUG_ON(!(*cpu_in_lp2 & BIT(phy_cpu_id)));
158 *cpu_in_lp2 &= ~BIT(phy_cpu_id);
159
160 spin_unlock(&tegra_lp2_lock);
161}
162
163bool __cpuinit tegra_set_cpu_in_lp2(int phy_cpu_id)
164{
165 bool last_cpu = false;
166 cpumask_t *cpu_lp2_mask = tegra_cpu_lp2_mask;
167 u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
168
169 spin_lock(&tegra_lp2_lock);
170
171 BUG_ON((*cpu_in_lp2 & BIT(phy_cpu_id)));
172 *cpu_in_lp2 |= BIT(phy_cpu_id);
173
174 if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
175 last_cpu = true;
176
177 spin_unlock(&tegra_lp2_lock);
178 return last_cpu;
179}
180
181static int tegra_sleep_cpu(unsigned long v2p)
182{
183 /* Switch to the identity mapping. */
184 cpu_switch_mm(idmap_pgd, &init_mm);
185
186 /* Flush the TLB. */
187 local_flush_tlb_all();
188
189 tegra_sleep_cpu_finish(v2p);
190
191 /* should never here */
192 BUG();
193
194 return 0;
195}
196
197void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)
198{
199 u32 mode;
200
201 /* Only the last cpu down does the final suspend steps */
202 mode = readl(pmc + PMC_CTRL);
203 mode |= TEGRA_POWER_CPU_PWRREQ_OE;
204 writel(mode, pmc + PMC_CTRL);
205
206 set_power_timers(cpu_on_time, cpu_off_time);
207
208 cpu_cluster_pm_enter();
209 suspend_cpu_complex();
210
211 cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
212
213 restore_cpu_complex();
214 cpu_cluster_pm_exit();
215}
216#endif
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
new file mode 100644
index 000000000000..787335cc964c
--- /dev/null
+++ b/arch/arm/mach-tegra/pm.h
@@ -0,0 +1,35 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 * Copyright (c) 2010-2012 NVIDIA Corporation. All rights reserved.
4 *
5 * Author:
6 * Colin Cross <ccross@google.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef _MACH_TEGRA_PM_H_
22#define _MACH_TEGRA_PM_H_
23
24extern unsigned long l2x0_saved_regs_addr;
25
26void save_cpu_arch_register(void);
27void restore_cpu_arch_register(void);
28
29void tegra_clear_cpu_in_lp2(int phy_cpu_id);
30bool tegra_set_cpu_in_lp2(int phy_cpu_id);
31
32void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time);
33extern void (*tegra_tear_down_cpu)(void);
34
35#endif /* _MACH_TEGRA_PM_H_ */
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index 7af6a54404be..d4fdb5fcec20 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -19,7 +19,7 @@
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/of.h> 20#include <linux/of.h>
21 21
22#include <mach/iomap.h> 22#include "iomap.h"
23 23
24#define PMC_CTRL 0x0 24#define PMC_CTRL 0x0
25#define PMC_CTRL_INTR_LOW (1 << 17) 25#define PMC_CTRL_INTR_LOW (1 << 17)
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index de0662de28a0..2cc1185d902e 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -28,10 +28,10 @@
28#include <linux/spinlock.h> 28#include <linux/spinlock.h>
29 29
30#include <mach/clk.h> 30#include <mach/clk.h>
31#include <mach/iomap.h>
32#include <mach/powergate.h> 31#include <mach/powergate.h>
33 32
34#include "fuse.h" 33#include "fuse.h"
34#include "iomap.h"
35 35
36#define PWRGATE_TOGGLE 0x30 36#define PWRGATE_TOGGLE 0x30
37#define PWRGATE_TOGGLE_START (1 << 8) 37#define PWRGATE_TOGGLE_START (1 << 8)
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index 5beb7ebe2948..3fd89ecd158e 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -22,10 +22,10 @@
22#include <asm/cacheflush.h> 22#include <asm/cacheflush.h>
23#include <asm/hardware/cache-l2x0.h> 23#include <asm/hardware/cache-l2x0.h>
24 24
25#include <mach/iomap.h> 25#include "iomap.h"
26#include <mach/irammap.h> 26#include "irammap.h"
27
28#include "reset.h" 27#include "reset.h"
28#include "sleep.h"
29#include "fuse.h" 29#include "fuse.h"
30 30
31#define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \ 31#define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
@@ -80,5 +80,10 @@ void __init tegra_cpu_reset_handler_init(void)
80 virt_to_phys((void *)tegra_secondary_startup); 80 virt_to_phys((void *)tegra_secondary_startup);
81#endif 81#endif
82 82
83#ifdef CONFIG_PM_SLEEP
84 __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] =
85 virt_to_phys((void *)tegra_resume);
86#endif
87
83 tegra_cpu_reset_handler_enable(); 88 tegra_cpu_reset_handler_enable();
84} 89}
diff --git a/arch/arm/mach-tegra/reset.h b/arch/arm/mach-tegra/reset.h
index de88bf851dd3..c90d8e9c4ad2 100644
--- a/arch/arm/mach-tegra/reset.h
+++ b/arch/arm/mach-tegra/reset.h
@@ -29,6 +29,8 @@
29 29
30#ifndef __ASSEMBLY__ 30#ifndef __ASSEMBLY__
31 31
32#include "irammap.h"
33
32extern unsigned long __tegra_cpu_reset_handler_data[TEGRA_RESET_DATA_SIZE]; 34extern unsigned long __tegra_cpu_reset_handler_data[TEGRA_RESET_DATA_SIZE];
33 35
34void __tegra_cpu_reset_handler_start(void); 36void __tegra_cpu_reset_handler_start(void);
@@ -36,6 +38,13 @@ void __tegra_cpu_reset_handler(void);
36void __tegra_cpu_reset_handler_end(void); 38void __tegra_cpu_reset_handler_end(void);
37void tegra_secondary_startup(void); 39void tegra_secondary_startup(void);
38 40
41#ifdef CONFIG_PM_SLEEP
42#define tegra_cpu_lp2_mask \
43 (IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
44 ((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_LP2] - \
45 (u32)__tegra_cpu_reset_handler_start)))
46#endif
47
39#define tegra_cpu_reset_handler_offset \ 48#define tegra_cpu_reset_handler_offset \
40 ((u32)__tegra_cpu_reset_handler - \ 49 ((u32)__tegra_cpu_reset_handler - \
41 (u32)__tegra_cpu_reset_handler_start) 50 (u32)__tegra_cpu_reset_handler_start)
diff --git a/arch/arm/mach-tegra/sleep-t20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index a36ae413e2b8..72ce709799da 100644
--- a/arch/arm/mach-tegra/sleep-t20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -22,8 +22,6 @@
22 22
23#include <asm/assembler.h> 23#include <asm/assembler.h>
24 24
25#include <mach/iomap.h>
26
27#include "sleep.h" 25#include "sleep.h"
28#include "flowctrl.h" 26#include "flowctrl.h"
29 27
diff --git a/arch/arm/mach-tegra/sleep-t30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index 777d9cee8b90..562a8e7e413d 100644
--- a/arch/arm/mach-tegra/sleep-t30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -17,8 +17,7 @@
17#include <linux/linkage.h> 17#include <linux/linkage.h>
18 18
19#include <asm/assembler.h> 19#include <asm/assembler.h>
20 20#include <asm/asm-offsets.h>
21#include <mach/iomap.h>
22 21
23#include "sleep.h" 22#include "sleep.h"
24#include "flowctrl.h" 23#include "flowctrl.h"
@@ -82,6 +81,7 @@ delay_1:
82 ldr r3, [r1] @ read CSR 81 ldr r3, [r1] @ read CSR
83 str r3, [r1] @ clear CSR 82 str r3, [r1] @ clear CSR
84 tst r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN 83 tst r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
84 moveq r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT @ For LP2
85 movne r3, #FLOW_CTRL_WAITEVENT @ For hotplug 85 movne r3, #FLOW_CTRL_WAITEVENT @ For hotplug
86 str r3, [r2] 86 str r3, [r2]
87 ldr r0, [r2] 87 ldr r0, [r2]
@@ -105,3 +105,67 @@ wfe_war:
105 105
106ENDPROC(tegra30_cpu_shutdown) 106ENDPROC(tegra30_cpu_shutdown)
107#endif 107#endif
108
109#ifdef CONFIG_PM_SLEEP
110/*
111 * tegra30_sleep_cpu_secondary_finish(unsigned long v2p)
112 *
113 * Enters LP2 on secondary CPU by exiting coherency and powergating the CPU.
114 */
115ENTRY(tegra30_sleep_cpu_secondary_finish)
116 mov r7, lr
117
118 /* Flush and disable the L1 data cache */
119 bl tegra_disable_clean_inv_dcache
120
121 /* Powergate this CPU. */
122 mov r0, #0 @ power mode flags (!hotplug)
123 bl tegra30_cpu_shutdown
124 mov r0, #1 @ never return here
125 mov pc, r7
126ENDPROC(tegra30_sleep_cpu_secondary_finish)
127
128/*
129 * tegra30_tear_down_cpu
130 *
131 * Switches the CPU to enter sleep.
132 */
133ENTRY(tegra30_tear_down_cpu)
134 mov32 r6, TEGRA_FLOW_CTRL_BASE
135
136 b tegra30_enter_sleep
137ENDPROC(tegra30_tear_down_cpu)
138
139/*
140 * tegra30_enter_sleep
141 *
142 * uses flow controller to enter sleep state
143 * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
144 * executes from SDRAM with target state is LP2
145 * r6 = TEGRA_FLOW_CTRL_BASE
146 */
147tegra30_enter_sleep:
148 cpu_id r1
149
150 cpu_to_csr_reg r2, r1
151 ldr r0, [r6, r2]
152 orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
153 orr r0, r0, #FLOW_CTRL_CSR_ENABLE
154 str r0, [r6, r2]
155
156 mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
157 orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
158 cpu_to_halt_reg r2, r1
159 str r0, [r6, r2]
160 dsb
161 ldr r0, [r6, r2] /* memory barrier */
162
163halted:
164 isb
165 dsb
166 wfi /* CPU should be power gated here */
167
168 /* !!!FIXME!!! Implement halt failure handler */
169 b halted
170
171#endif
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index ea81554c4833..26afa7cbed11 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -25,9 +25,87 @@
25#include <linux/linkage.h> 25#include <linux/linkage.h>
26 26
27#include <asm/assembler.h> 27#include <asm/assembler.h>
28#include <asm/cache.h>
29#include <asm/cp15.h>
30#include <asm/hardware/cache-l2x0.h>
28 31
29#include <mach/iomap.h> 32#include "iomap.h"
30 33
31#include "flowctrl.h" 34#include "flowctrl.h"
32#include "sleep.h" 35#include "sleep.h"
33 36
37#ifdef CONFIG_PM_SLEEP
38/*
39 * tegra_disable_clean_inv_dcache
40 *
41 * disable, clean & invalidate the D-cache
42 *
43 * Corrupted registers: r1-r3, r6, r8, r9-r11
44 */
45ENTRY(tegra_disable_clean_inv_dcache)
46 stmfd sp!, {r0, r4-r5, r7, r9-r11, lr}
47 dmb @ ensure ordering
48
49 /* Disable the D-cache */
50 mrc p15, 0, r2, c1, c0, 0
51 bic r2, r2, #CR_C
52 mcr p15, 0, r2, c1, c0, 0
53 isb
54
55 /* Flush the D-cache */
56 bl v7_flush_dcache_louis
57
58 /* Trun off coherency */
59 exit_smp r4, r5
60
61 ldmfd sp!, {r0, r4-r5, r7, r9-r11, pc}
62ENDPROC(tegra_disable_clean_inv_dcache)
63
64/*
65 * tegra_sleep_cpu_finish(unsigned long v2p)
66 *
67 * enters suspend in LP2 by turning off the mmu and jumping to
68 * tegra?_tear_down_cpu
69 */
70ENTRY(tegra_sleep_cpu_finish)
71 /* Flush and disable the L1 data cache */
72 bl tegra_disable_clean_inv_dcache
73
74 mov32 r6, tegra_tear_down_cpu
75 ldr r1, [r6]
76 add r1, r1, r0
77
78 mov32 r3, tegra_shut_off_mmu
79 add r3, r3, r0
80 mov r0, r1
81
82 mov pc, r3
83ENDPROC(tegra_sleep_cpu_finish)
84
85/*
86 * tegra_shut_off_mmu
87 *
88 * r0 = physical address to jump to with mmu off
89 *
90 * called with VA=PA mapping
91 * turns off MMU, icache, dcache and branch prediction
92 */
93 .align L1_CACHE_SHIFT
94 .pushsection .idmap.text, "ax"
95ENTRY(tegra_shut_off_mmu)
96 mrc p15, 0, r3, c1, c0, 0
97 movw r2, #CR_I | CR_Z | CR_C | CR_M
98 bic r3, r3, r2
99 dsb
100 mcr p15, 0, r3, c1, c0, 0
101 isb
102#ifdef CONFIG_CACHE_L2X0
103 /* Disable L2 cache */
104 mov32 r4, TEGRA_ARM_PERIF_BASE + 0x3000
105 mov r5, #0
106 str r5, [r4, #L2X0_CTRL]
107#endif
108 mov pc, r0
109ENDPROC(tegra_shut_off_mmu)
110 .popsection
111#endif
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index e25a7cd703d9..9821ee725420 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -17,7 +17,7 @@
17#ifndef __MACH_TEGRA_SLEEP_H 17#ifndef __MACH_TEGRA_SLEEP_H
18#define __MACH_TEGRA_SLEEP_H 18#define __MACH_TEGRA_SLEEP_H
19 19
20#include <mach/iomap.h> 20#include "iomap.h"
21 21
22#define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \ 22#define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \
23 + IO_CPU_VIRT) 23 + IO_CPU_VIRT)
@@ -71,7 +71,41 @@
71 str \tmp2, [\tmp1] @ invalidate SCU tags for CPU 71 str \tmp2, [\tmp1] @ invalidate SCU tags for CPU
72 dsb 72 dsb
73.endm 73.endm
74
75/* Macro to resume & re-enable L2 cache */
76#ifndef L2X0_CTRL_EN
77#define L2X0_CTRL_EN 1
78#endif
79
80#ifdef CONFIG_CACHE_L2X0
81.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
82 adr \tmp1, \phys_l2x0_saved_regs
83 ldr \tmp1, [\tmp1]
84 ldr \tmp2, [\tmp1, #L2X0_R_PHY_BASE]
85 ldr \tmp3, [\tmp2, #L2X0_CTRL]
86 tst \tmp3, #L2X0_CTRL_EN
87 bne exit_l2_resume
88 ldr \tmp3, [\tmp1, #L2X0_R_TAG_LATENCY]
89 str \tmp3, [\tmp2, #L2X0_TAG_LATENCY_CTRL]
90 ldr \tmp3, [\tmp1, #L2X0_R_DATA_LATENCY]
91 str \tmp3, [\tmp2, #L2X0_DATA_LATENCY_CTRL]
92 ldr \tmp3, [\tmp1, #L2X0_R_PREFETCH_CTRL]
93 str \tmp3, [\tmp2, #L2X0_PREFETCH_CTRL]
94 ldr \tmp3, [\tmp1, #L2X0_R_PWR_CTRL]
95 str \tmp3, [\tmp2, #L2X0_POWER_CTRL]
96 ldr \tmp3, [\tmp1, #L2X0_R_AUX_CTRL]
97 str \tmp3, [\tmp2, #L2X0_AUX_CTRL]
98 mov \tmp3, #L2X0_CTRL_EN
99 str \tmp3, [\tmp2, #L2X0_CTRL]
100exit_l2_resume:
101.endm
102#else /* CONFIG_CACHE_L2X0 */
103.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
104.endm
105#endif /* CONFIG_CACHE_L2X0 */
74#else 106#else
107void tegra_resume(void);
108int tegra_sleep_cpu_finish(unsigned long);
75 109
76#ifdef CONFIG_HOTPLUG_CPU 110#ifdef CONFIG_HOTPLUG_CPU
77void tegra20_hotplug_init(void); 111void tegra20_hotplug_init(void);
@@ -81,5 +115,8 @@ static inline void tegra20_hotplug_init(void) {}
81static inline void tegra30_hotplug_init(void) {} 115static inline void tegra30_hotplug_init(void) {}
82#endif 116#endif
83 117
118int tegra30_sleep_cpu_secondary_finish(unsigned long);
119void tegra30_tear_down_cpu(void);
120
84#endif 121#endif
85#endif 122#endif
diff --git a/arch/arm/mach-tegra/tegra20_clocks.c b/arch/arm/mach-tegra/tegra20_clocks.c
index deb873fb12b6..4eb6bc81a87b 100644
--- a/arch/arm/mach-tegra/tegra20_clocks.c
+++ b/arch/arm/mach-tegra/tegra20_clocks.c
@@ -27,10 +27,9 @@
27#include <linux/clkdev.h> 27#include <linux/clkdev.h>
28#include <linux/clk.h> 28#include <linux/clk.h>
29 29
30#include <mach/iomap.h>
31
32#include "clock.h" 30#include "clock.h"
33#include "fuse.h" 31#include "fuse.h"
32#include "iomap.h"
34#include "tegra2_emc.h" 33#include "tegra2_emc.h"
35#include "tegra_cpu_car.h" 34#include "tegra_cpu_car.h"
36 35
diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c
index 8d398a33adf7..a23a0734e352 100644
--- a/arch/arm/mach-tegra/tegra20_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra20_clocks_data.c
@@ -27,8 +27,6 @@
27#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/clk.h> 28#include <linux/clk.h>
29 29
30#include <mach/iomap.h>
31
32#include "clock.h" 30#include "clock.h"
33#include "fuse.h" 31#include "fuse.h"
34#include "tegra2_emc.h" 32#include "tegra2_emc.h"
@@ -248,11 +246,16 @@ static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
248 { 19200000, 216000000, 135, 12, 1, 3}, 246 { 19200000, 216000000, 135, 12, 1, 3},
249 { 26000000, 216000000, 216, 26, 1, 4}, 247 { 26000000, 216000000, 216, 26, 1, 4},
250 248
249 { 12000000, 297000000, 99, 4, 1, 4 },
250 { 12000000, 339000000, 113, 4, 1, 4 },
251
251 { 12000000, 594000000, 594, 12, 1, 8}, 252 { 12000000, 594000000, 594, 12, 1, 8},
252 { 13000000, 594000000, 594, 13, 1, 8}, 253 { 13000000, 594000000, 594, 13, 1, 8},
253 { 19200000, 594000000, 495, 16, 1, 8}, 254 { 19200000, 594000000, 495, 16, 1, 8},
254 { 26000000, 594000000, 594, 26, 1, 8}, 255 { 26000000, 594000000, 594, 26, 1, 8},
255 256
257 { 12000000, 616000000, 616, 12, 1, 8},
258
256 { 12000000, 1000000000, 1000, 12, 1, 12}, 259 { 12000000, 1000000000, 1000, 12, 1, 12},
257 { 13000000, 1000000000, 1000, 13, 1, 12}, 260 { 13000000, 1000000000, 1000, 13, 1, 12},
258 { 19200000, 1000000000, 625, 12, 1, 8}, 261 { 19200000, 1000000000, 625, 12, 1, 8},
@@ -1038,9 +1041,6 @@ static struct clk_duplicate tegra_clk_duplicates[] = {
1038 CLK_DUPLICATE("usbd", "utmip-pad", NULL), 1041 CLK_DUPLICATE("usbd", "utmip-pad", NULL),
1039 CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL), 1042 CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
1040 CLK_DUPLICATE("usbd", "tegra-otg", NULL), 1043 CLK_DUPLICATE("usbd", "tegra-otg", NULL),
1041 CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
1042 CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
1043 CLK_DUPLICATE("host1x", "tegra_grhost", "host1x"),
1044 CLK_DUPLICATE("2d", "tegra_grhost", "gr2d"), 1044 CLK_DUPLICATE("2d", "tegra_grhost", "gr2d"),
1045 CLK_DUPLICATE("3d", "tegra_grhost", "gr3d"), 1045 CLK_DUPLICATE("3d", "tegra_grhost", "gr3d"),
1046 CLK_DUPLICATE("epp", "tegra_grhost", "epp"), 1046 CLK_DUPLICATE("epp", "tegra_grhost", "epp"),
@@ -1053,6 +1053,9 @@ static struct clk_duplicate tegra_clk_duplicates[] = {
1053 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.1", "fast-clk"), 1053 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.1", "fast-clk"),
1054 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"), 1054 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"),
1055 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"), 1055 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"),
1056 CLK_DUPLICATE("pll_p", "tegradc.0", "parent"),
1057 CLK_DUPLICATE("pll_p", "tegradc.1", "parent"),
1058 CLK_DUPLICATE("pll_d_out0", "hdmi", "parent"),
1056}; 1059};
1057 1060
1058#define CLK(dev, con, ck) \ 1061#define CLK(dev, con, ck) \
diff --git a/arch/arm/mach-tegra/tegra20_speedo.c b/arch/arm/mach-tegra/tegra20_speedo.c
new file mode 100644
index 000000000000..fa6eb570623f
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra20_speedo.c
@@ -0,0 +1,109 @@
1/*
2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/kernel.h>
18#include <linux/bug.h>
19
20#include "fuse.h"
21
22#define CPU_SPEEDO_LSBIT 20
23#define CPU_SPEEDO_MSBIT 29
24#define CPU_SPEEDO_REDUND_LSBIT 30
25#define CPU_SPEEDO_REDUND_MSBIT 39
26#define CPU_SPEEDO_REDUND_OFFS (CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT)
27
28#define CORE_SPEEDO_LSBIT 40
29#define CORE_SPEEDO_MSBIT 47
30#define CORE_SPEEDO_REDUND_LSBIT 48
31#define CORE_SPEEDO_REDUND_MSBIT 55
32#define CORE_SPEEDO_REDUND_OFFS (CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT)
33
34#define SPEEDO_MULT 4
35
36#define PROCESS_CORNERS_NUM 4
37
38#define SPEEDO_ID_SELECT_0(rev) ((rev) <= 2)
39#define SPEEDO_ID_SELECT_1(sku) \
40 (((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \
41 ((sku) != 27) && ((sku) != 28))
42
43enum {
44 SPEEDO_ID_0,
45 SPEEDO_ID_1,
46 SPEEDO_ID_2,
47 SPEEDO_ID_COUNT,
48};
49
50static const u32 cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
51 {315, 366, 420, UINT_MAX},
52 {303, 368, 419, UINT_MAX},
53 {316, 331, 383, UINT_MAX},
54};
55
56static const u32 core_process_speedos[][PROCESS_CORNERS_NUM] = {
57 {165, 195, 224, UINT_MAX},
58 {165, 195, 224, UINT_MAX},
59 {165, 195, 224, UINT_MAX},
60};
61
62void tegra20_init_speedo_data(void)
63{
64 u32 reg;
65 u32 val;
66 int i;
67
68 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT);
69 BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != SPEEDO_ID_COUNT);
70
71 if (SPEEDO_ID_SELECT_0(tegra_revision))
72 tegra_soc_speedo_id = SPEEDO_ID_0;
73 else if (SPEEDO_ID_SELECT_1(tegra_sku_id))
74 tegra_soc_speedo_id = SPEEDO_ID_1;
75 else
76 tegra_soc_speedo_id = SPEEDO_ID_2;
77
78 val = 0;
79 for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
80 reg = tegra_spare_fuse(i) |
81 tegra_spare_fuse(i + CPU_SPEEDO_REDUND_OFFS);
82 val = (val << 1) | (reg & 0x1);
83 }
84 val = val * SPEEDO_MULT;
85 pr_debug("%s CPU speedo value %u\n", __func__, val);
86
87 for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
88 if (val <= cpu_process_speedos[tegra_soc_speedo_id][i])
89 break;
90 }
91 tegra_cpu_process_id = i;
92
93 val = 0;
94 for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) {
95 reg = tegra_spare_fuse(i) |
96 tegra_spare_fuse(i + CORE_SPEEDO_REDUND_OFFS);
97 val = (val << 1) | (reg & 0x1);
98 }
99 val = val * SPEEDO_MULT;
100 pr_debug("%s Core speedo value %u\n", __func__, val);
101
102 for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
103 if (val <= core_process_speedos[tegra_soc_speedo_id][i])
104 break;
105 }
106 tegra_core_process_id = i;
107
108 pr_info("Tegra20 Soc Speedo ID %d", tegra_soc_speedo_id);
109}
diff --git a/arch/arm/mach-tegra/tegra2_emc.c b/arch/arm/mach-tegra/tegra2_emc.c
index 5070d833bdd1..837c7b9ea63b 100644
--- a/arch/arm/mach-tegra/tegra2_emc.c
+++ b/arch/arm/mach-tegra/tegra2_emc.c
@@ -25,8 +25,6 @@
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/platform_data/tegra_emc.h> 26#include <linux/platform_data/tegra_emc.h>
27 27
28#include <mach/iomap.h>
29
30#include "tegra2_emc.h" 28#include "tegra2_emc.h"
31#include "fuse.h" 29#include "fuse.h"
32 30
diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c
index e9de5dfd94ec..efc000e32e1c 100644
--- a/arch/arm/mach-tegra/tegra30_clocks.c
+++ b/arch/arm/mach-tegra/tegra30_clocks.c
@@ -31,10 +31,11 @@
31 31
32#include <asm/clkdev.h> 32#include <asm/clkdev.h>
33 33
34#include <mach/iomap.h> 34#include <mach/powergate.h>
35 35
36#include "clock.h" 36#include "clock.h"
37#include "fuse.h" 37#include "fuse.h"
38#include "iomap.h"
38#include "tegra_cpu_car.h" 39#include "tegra_cpu_car.h"
39 40
40#define USE_PLL_LOCK_BITS 0 41#define USE_PLL_LOCK_BITS 0
@@ -310,6 +311,31 @@
310#define CPU_CLOCK(cpu) (0x1 << (8 + cpu)) 311#define CPU_CLOCK(cpu) (0x1 << (8 + cpu))
311#define CPU_RESET(cpu) (0x1111ul << (cpu)) 312#define CPU_RESET(cpu) (0x1111ul << (cpu))
312 313
314#define CLK_RESET_CCLK_BURST 0x20
315#define CLK_RESET_CCLK_DIVIDER 0x24
316#define CLK_RESET_PLLX_BASE 0xe0
317#define CLK_RESET_PLLX_MISC 0xe4
318
319#define CLK_RESET_SOURCE_CSITE 0x1d4
320
321#define CLK_RESET_CCLK_BURST_POLICY_SHIFT 28
322#define CLK_RESET_CCLK_RUN_POLICY_SHIFT 4
323#define CLK_RESET_CCLK_IDLE_POLICY_SHIFT 0
324#define CLK_RESET_CCLK_IDLE_POLICY 1
325#define CLK_RESET_CCLK_RUN_POLICY 2
326#define CLK_RESET_CCLK_BURST_POLICY_PLLX 8
327
328#ifdef CONFIG_PM_SLEEP
329static struct cpu_clk_suspend_context {
330 u32 pllx_misc;
331 u32 pllx_base;
332
333 u32 cpu_burst;
334 u32 clk_csite_src;
335 u32 cclk_divider;
336} tegra30_cpu_clk_sctx;
337#endif
338
313/** 339/**
314* Structure defining the fields for USB UTMI clocks Parameters. 340* Structure defining the fields for USB UTMI clocks Parameters.
315*/ 341*/
@@ -792,6 +818,112 @@ struct clk_ops tegra30_twd_ops = {
792 .recalc_rate = tegra30_twd_clk_recalc_rate, 818 .recalc_rate = tegra30_twd_clk_recalc_rate,
793}; 819};
794 820
821/* bus clock functions */
822static int tegra30_bus_clk_is_enabled(struct clk_hw *hw)
823{
824 struct clk_tegra *c = to_clk_tegra(hw);
825 u32 val = clk_readl(c->reg);
826
827 c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
828 return c->state;
829}
830
831static int tegra30_bus_clk_enable(struct clk_hw *hw)
832{
833 struct clk_tegra *c = to_clk_tegra(hw);
834 u32 val;
835
836 val = clk_readl(c->reg);
837 val &= ~(BUS_CLK_DISABLE << c->reg_shift);
838 clk_writel(val, c->reg);
839
840 return 0;
841}
842
843static void tegra30_bus_clk_disable(struct clk_hw *hw)
844{
845 struct clk_tegra *c = to_clk_tegra(hw);
846 u32 val;
847
848 val = clk_readl(c->reg);
849 val |= BUS_CLK_DISABLE << c->reg_shift;
850 clk_writel(val, c->reg);
851}
852
853static unsigned long tegra30_bus_clk_recalc_rate(struct clk_hw *hw,
854 unsigned long prate)
855{
856 struct clk_tegra *c = to_clk_tegra(hw);
857 u32 val = clk_readl(c->reg);
858 u64 rate = prate;
859
860 c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
861 c->mul = 1;
862
863 if (c->mul != 0 && c->div != 0) {
864 rate *= c->mul;
865 rate += c->div - 1; /* round up */
866 do_div(rate, c->div);
867 }
868 return rate;
869}
870
871static int tegra30_bus_clk_set_rate(struct clk_hw *hw, unsigned long rate,
872 unsigned long parent_rate)
873{
874 struct clk_tegra *c = to_clk_tegra(hw);
875 int ret = -EINVAL;
876 u32 val;
877 int i;
878
879 val = clk_readl(c->reg);
880 for (i = 1; i <= 4; i++) {
881 if (rate == parent_rate / i) {
882 val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
883 val |= (i - 1) << c->reg_shift;
884 clk_writel(val, c->reg);
885 c->div = i;
886 c->mul = 1;
887 ret = 0;
888 break;
889 }
890 }
891
892 return ret;
893}
894
895static long tegra30_bus_clk_round_rate(struct clk_hw *hw, unsigned long rate,
896 unsigned long *prate)
897{
898 unsigned long parent_rate = *prate;
899 s64 divider;
900
901 if (rate >= parent_rate)
902 return parent_rate;
903
904 divider = parent_rate;
905 divider += rate - 1;
906 do_div(divider, rate);
907
908 if (divider < 0)
909 return divider;
910
911 if (divider > 4)
912 divider = 4;
913 do_div(parent_rate, divider);
914
915 return parent_rate;
916}
917
918struct clk_ops tegra30_bus_ops = {
919 .is_enabled = tegra30_bus_clk_is_enabled,
920 .enable = tegra30_bus_clk_enable,
921 .disable = tegra30_bus_clk_disable,
922 .set_rate = tegra30_bus_clk_set_rate,
923 .round_rate = tegra30_bus_clk_round_rate,
924 .recalc_rate = tegra30_bus_clk_recalc_rate,
925};
926
795/* Blink output functions */ 927/* Blink output functions */
796static int tegra30_blink_clk_is_enabled(struct clk_hw *hw) 928static int tegra30_blink_clk_is_enabled(struct clk_hw *hw)
797{ 929{
@@ -2281,12 +2413,93 @@ static void tegra30_disable_cpu_clock(u32 cpu)
2281 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX); 2413 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
2282} 2414}
2283 2415
2416#ifdef CONFIG_PM_SLEEP
2417static bool tegra30_cpu_rail_off_ready(void)
2418{
2419 unsigned int cpu_rst_status;
2420 int cpu_pwr_status;
2421
2422 cpu_rst_status = readl(reg_clk_base +
2423 TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
2424 cpu_pwr_status = tegra_powergate_is_powered(TEGRA_POWERGATE_CPU1) ||
2425 tegra_powergate_is_powered(TEGRA_POWERGATE_CPU2) ||
2426 tegra_powergate_is_powered(TEGRA_POWERGATE_CPU3);
2427
2428 if (((cpu_rst_status & 0xE) != 0xE) || cpu_pwr_status)
2429 return false;
2430
2431 return true;
2432}
2433
2434static void tegra30_cpu_clock_suspend(void)
2435{
2436 /* switch coresite to clk_m, save off original source */
2437 tegra30_cpu_clk_sctx.clk_csite_src =
2438 readl(reg_clk_base + CLK_RESET_SOURCE_CSITE);
2439 writel(3<<30, reg_clk_base + CLK_RESET_SOURCE_CSITE);
2440
2441 tegra30_cpu_clk_sctx.cpu_burst =
2442 readl(reg_clk_base + CLK_RESET_CCLK_BURST);
2443 tegra30_cpu_clk_sctx.pllx_base =
2444 readl(reg_clk_base + CLK_RESET_PLLX_BASE);
2445 tegra30_cpu_clk_sctx.pllx_misc =
2446 readl(reg_clk_base + CLK_RESET_PLLX_MISC);
2447 tegra30_cpu_clk_sctx.cclk_divider =
2448 readl(reg_clk_base + CLK_RESET_CCLK_DIVIDER);
2449}
2450
2451static void tegra30_cpu_clock_resume(void)
2452{
2453 unsigned int reg, policy;
2454
2455 /* Is CPU complex already running on PLLX? */
2456 reg = readl(reg_clk_base + CLK_RESET_CCLK_BURST);
2457 policy = (reg >> CLK_RESET_CCLK_BURST_POLICY_SHIFT) & 0xF;
2458
2459 if (policy == CLK_RESET_CCLK_IDLE_POLICY)
2460 reg = (reg >> CLK_RESET_CCLK_IDLE_POLICY_SHIFT) & 0xF;
2461 else if (policy == CLK_RESET_CCLK_RUN_POLICY)
2462 reg = (reg >> CLK_RESET_CCLK_RUN_POLICY_SHIFT) & 0xF;
2463 else
2464 BUG();
2465
2466 if (reg != CLK_RESET_CCLK_BURST_POLICY_PLLX) {
2467 /* restore PLLX settings if CPU is on different PLL */
2468 writel(tegra30_cpu_clk_sctx.pllx_misc,
2469 reg_clk_base + CLK_RESET_PLLX_MISC);
2470 writel(tegra30_cpu_clk_sctx.pllx_base,
2471 reg_clk_base + CLK_RESET_PLLX_BASE);
2472
2473 /* wait for PLL stabilization if PLLX was enabled */
2474 if (tegra30_cpu_clk_sctx.pllx_base & (1 << 30))
2475 udelay(300);
2476 }
2477
2478 /*
2479 * Restore original burst policy setting for calls resulting from CPU
2480 * LP2 in idle or system suspend.
2481 */
2482 writel(tegra30_cpu_clk_sctx.cclk_divider,
2483 reg_clk_base + CLK_RESET_CCLK_DIVIDER);
2484 writel(tegra30_cpu_clk_sctx.cpu_burst,
2485 reg_clk_base + CLK_RESET_CCLK_BURST);
2486
2487 writel(tegra30_cpu_clk_sctx.clk_csite_src,
2488 reg_clk_base + CLK_RESET_SOURCE_CSITE);
2489}
2490#endif
2491
2284static struct tegra_cpu_car_ops tegra30_cpu_car_ops = { 2492static struct tegra_cpu_car_ops tegra30_cpu_car_ops = {
2285 .wait_for_reset = tegra30_wait_cpu_in_reset, 2493 .wait_for_reset = tegra30_wait_cpu_in_reset,
2286 .put_in_reset = tegra30_put_cpu_in_reset, 2494 .put_in_reset = tegra30_put_cpu_in_reset,
2287 .out_of_reset = tegra30_cpu_out_of_reset, 2495 .out_of_reset = tegra30_cpu_out_of_reset,
2288 .enable_clock = tegra30_enable_cpu_clock, 2496 .enable_clock = tegra30_enable_cpu_clock,
2289 .disable_clock = tegra30_disable_cpu_clock, 2497 .disable_clock = tegra30_disable_cpu_clock,
2498#ifdef CONFIG_PM_SLEEP
2499 .rail_off_ready = tegra30_cpu_rail_off_ready,
2500 .suspend = tegra30_cpu_clock_suspend,
2501 .resume = tegra30_cpu_clock_resume,
2502#endif
2290}; 2503};
2291 2504
2292void __init tegra30_cpu_car_ops_init(void) 2505void __init tegra30_cpu_car_ops_init(void)
diff --git a/arch/arm/mach-tegra/tegra30_clocks.h b/arch/arm/mach-tegra/tegra30_clocks.h
index f2f88fef6b8b..7a34adb2f72d 100644
--- a/arch/arm/mach-tegra/tegra30_clocks.h
+++ b/arch/arm/mach-tegra/tegra30_clocks.h
@@ -34,6 +34,7 @@ extern struct clk_ops tegra_clk_out_ops;
34extern struct clk_ops tegra30_super_ops; 34extern struct clk_ops tegra30_super_ops;
35extern struct clk_ops tegra30_blink_clk_ops; 35extern struct clk_ops tegra30_blink_clk_ops;
36extern struct clk_ops tegra30_twd_ops; 36extern struct clk_ops tegra30_twd_ops;
37extern struct clk_ops tegra30_bus_ops;
37extern struct clk_ops tegra30_periph_clk_ops; 38extern struct clk_ops tegra30_periph_clk_ops;
38extern struct clk_ops tegra30_dsib_clk_ops; 39extern struct clk_ops tegra30_dsib_clk_ops;
39extern struct clk_ops tegra_nand_clk_ops; 40extern struct clk_ops tegra_nand_clk_ops;
diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c
index 3d2e5532a9ea..6942c7add3bb 100644
--- a/arch/arm/mach-tegra/tegra30_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra30_clocks_data.c
@@ -711,6 +711,50 @@ static struct clk tegra_clk_sclk = {
711 .num_parents = ARRAY_SIZE(mux_sclk), 711 .num_parents = ARRAY_SIZE(mux_sclk),
712}; 712};
713 713
714static const char *tegra_hclk_parent_names[] = {
715 "tegra_sclk",
716};
717
718static struct clk *tegra_hclk_parents[] = {
719 &tegra_clk_sclk,
720};
721
722static struct clk tegra_hclk;
723static struct clk_tegra tegra_hclk_hw = {
724 .hw = {
725 .clk = &tegra_hclk,
726 },
727 .flags = DIV_BUS,
728 .reg = 0x30,
729 .reg_shift = 4,
730 .max_rate = 378000000,
731 .min_rate = 12000000,
732};
733DEFINE_CLK_TEGRA(hclk, 0, &tegra30_bus_ops, 0, tegra_hclk_parent_names,
734 tegra_hclk_parents, &tegra_clk_sclk);
735
736static const char *tegra_pclk_parent_names[] = {
737 "tegra_hclk",
738};
739
740static struct clk *tegra_pclk_parents[] = {
741 &tegra_hclk,
742};
743
744static struct clk tegra_pclk;
745static struct clk_tegra tegra_pclk_hw = {
746 .hw = {
747 .clk = &tegra_pclk,
748 },
749 .flags = DIV_BUS,
750 .reg = 0x30,
751 .reg_shift = 0,
752 .max_rate = 167000000,
753 .min_rate = 12000000,
754};
755DEFINE_CLK_TEGRA(pclk, 0, &tegra30_bus_ops, 0, tegra_pclk_parent_names,
756 tegra_pclk_parents, &tegra_hclk);
757
714static const char *mux_blink[] = { 758static const char *mux_blink[] = {
715 "clk_32k", 759 "clk_32k",
716}; 760};
@@ -1254,8 +1298,6 @@ struct clk_duplicate tegra_clk_duplicates[] = {
1254 CLK_DUPLICATE("usbd", "utmip-pad", NULL), 1298 CLK_DUPLICATE("usbd", "utmip-pad", NULL),
1255 CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL), 1299 CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
1256 CLK_DUPLICATE("usbd", "tegra-otg", NULL), 1300 CLK_DUPLICATE("usbd", "tegra-otg", NULL),
1257 CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
1258 CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
1259 CLK_DUPLICATE("dsib", "tegradc.0", "dsib"), 1301 CLK_DUPLICATE("dsib", "tegradc.0", "dsib"),
1260 CLK_DUPLICATE("dsia", "tegradc.1", "dsia"), 1302 CLK_DUPLICATE("dsia", "tegradc.1", "dsia"),
1261 CLK_DUPLICATE("bsev", "tegra-avp", "bsev"), 1303 CLK_DUPLICATE("bsev", "tegra-avp", "bsev"),
@@ -1293,6 +1335,9 @@ struct clk_duplicate tegra_clk_duplicates[] = {
1293 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"), 1335 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"),
1294 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"), 1336 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"),
1295 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.4", "fast-clk"), 1337 CLK_DUPLICATE("pll_p_out3", "tegra-i2c.4", "fast-clk"),
1338 CLK_DUPLICATE("pll_p", "tegradc.0", "parent"),
1339 CLK_DUPLICATE("pll_p", "tegradc.1", "parent"),
1340 CLK_DUPLICATE("pll_d2_out0", "hdmi", "parent"),
1296}; 1341};
1297 1342
1298struct clk *tegra_ptr_clks[] = { 1343struct clk *tegra_ptr_clks[] = {
@@ -1325,6 +1370,8 @@ struct clk *tegra_ptr_clks[] = {
1325 &tegra_cml1, 1370 &tegra_cml1,
1326 &tegra_pciex, 1371 &tegra_pciex,
1327 &tegra_clk_sclk, 1372 &tegra_clk_sclk,
1373 &tegra_hclk,
1374 &tegra_pclk,
1328 &tegra_clk_blink, 1375 &tegra_clk_blink,
1329 &tegra30_clk_twd, 1376 &tegra30_clk_twd,
1330}; 1377};
diff --git a/arch/arm/mach-tegra/tegra30_speedo.c b/arch/arm/mach-tegra/tegra30_speedo.c
new file mode 100644
index 000000000000..125cb16424a6
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra30_speedo.c
@@ -0,0 +1,292 @@
1/*
2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/kernel.h>
18#include <linux/bug.h>
19
20#include "fuse.h"
21
22#define CORE_PROCESS_CORNERS_NUM 1
23#define CPU_PROCESS_CORNERS_NUM 6
24
25#define FUSE_SPEEDO_CALIB_0 0x114
26#define FUSE_PACKAGE_INFO 0X1FC
27#define FUSE_TEST_PROG_VER 0X128
28
29#define G_SPEEDO_BIT_MINUS1 58
30#define G_SPEEDO_BIT_MINUS1_R 59
31#define G_SPEEDO_BIT_MINUS2 60
32#define G_SPEEDO_BIT_MINUS2_R 61
33#define LP_SPEEDO_BIT_MINUS1 62
34#define LP_SPEEDO_BIT_MINUS1_R 63
35#define LP_SPEEDO_BIT_MINUS2 64
36#define LP_SPEEDO_BIT_MINUS2_R 65
37
38enum {
39 THRESHOLD_INDEX_0,
40 THRESHOLD_INDEX_1,
41 THRESHOLD_INDEX_2,
42 THRESHOLD_INDEX_3,
43 THRESHOLD_INDEX_4,
44 THRESHOLD_INDEX_5,
45 THRESHOLD_INDEX_6,
46 THRESHOLD_INDEX_7,
47 THRESHOLD_INDEX_8,
48 THRESHOLD_INDEX_9,
49 THRESHOLD_INDEX_10,
50 THRESHOLD_INDEX_11,
51 THRESHOLD_INDEX_COUNT,
52};
53
54static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
55 {180},
56 {170},
57 {195},
58 {180},
59 {168},
60 {192},
61 {180},
62 {170},
63 {195},
64 {180},
65 {180},
66 {180},
67};
68
69static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
70 {306, 338, 360, 376, UINT_MAX},
71 {295, 336, 358, 375, UINT_MAX},
72 {325, 325, 358, 375, UINT_MAX},
73 {325, 325, 358, 375, UINT_MAX},
74 {292, 324, 348, 364, UINT_MAX},
75 {324, 324, 348, 364, UINT_MAX},
76 {324, 324, 348, 364, UINT_MAX},
77 {295, 336, 358, 375, UINT_MAX},
78 {358, 358, 358, 358, 397, UINT_MAX},
79 {364, 364, 364, 364, 397, UINT_MAX},
80 {295, 336, 358, 375, 391, UINT_MAX},
81 {295, 336, 358, 375, 391, UINT_MAX},
82};
83
84static int threshold_index;
85static int package_id;
86
87static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
88{
89 u32 reg;
90 int ate_ver;
91 int bit_minus1;
92 int bit_minus2;
93
94 reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
95
96 *speedo_lp = (reg & 0xFFFF) * 4;
97 *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
98
99 ate_ver = tegra_fuse_readl(FUSE_TEST_PROG_VER);
100 pr_info("%s: ATE prog ver %d.%d\n", __func__, ate_ver/10, ate_ver%10);
101
102 if (ate_ver >= 26) {
103 bit_minus1 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1);
104 bit_minus1 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1_R);
105 bit_minus2 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2);
106 bit_minus2 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2_R);
107 *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
108
109 bit_minus1 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS1);
110 bit_minus1 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS1_R);
111 bit_minus2 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS2);
112 bit_minus2 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS2_R);
113 *speedo_g |= (bit_minus1 << 1) | bit_minus2;
114 } else {
115 *speedo_lp |= 0x3;
116 *speedo_g |= 0x3;
117 }
118}
119
120static void rev_sku_to_speedo_ids(int rev, int sku)
121{
122 switch (rev) {
123 case TEGRA_REVISION_A01:
124 tegra_cpu_speedo_id = 0;
125 tegra_soc_speedo_id = 0;
126 threshold_index = THRESHOLD_INDEX_0;
127 break;
128 case TEGRA_REVISION_A02:
129 case TEGRA_REVISION_A03:
130 switch (sku) {
131 case 0x87:
132 case 0x82:
133 tegra_cpu_speedo_id = 1;
134 tegra_soc_speedo_id = 1;
135 threshold_index = THRESHOLD_INDEX_1;
136 break;
137 case 0x81:
138 switch (package_id) {
139 case 1:
140 tegra_cpu_speedo_id = 2;
141 tegra_soc_speedo_id = 2;
142 threshold_index = THRESHOLD_INDEX_2;
143 break;
144 case 2:
145 tegra_cpu_speedo_id = 4;
146 tegra_soc_speedo_id = 1;
147 threshold_index = THRESHOLD_INDEX_7;
148 break;
149 default:
150 pr_err("Tegra30: Unknown pkg %d\n", package_id);
151 BUG();
152 break;
153 }
154 break;
155 case 0x80:
156 switch (package_id) {
157 case 1:
158 tegra_cpu_speedo_id = 5;
159 tegra_soc_speedo_id = 2;
160 threshold_index = THRESHOLD_INDEX_8;
161 break;
162 case 2:
163 tegra_cpu_speedo_id = 6;
164 tegra_soc_speedo_id = 2;
165 threshold_index = THRESHOLD_INDEX_9;
166 break;
167 default:
168 pr_err("Tegra30: Unknown pkg %d\n", package_id);
169 BUG();
170 break;
171 }
172 break;
173 case 0x83:
174 switch (package_id) {
175 case 1:
176 tegra_cpu_speedo_id = 7;
177 tegra_soc_speedo_id = 1;
178 threshold_index = THRESHOLD_INDEX_10;
179 break;
180 case 2:
181 tegra_cpu_speedo_id = 3;
182 tegra_soc_speedo_id = 2;
183 threshold_index = THRESHOLD_INDEX_3;
184 break;
185 default:
186 pr_err("Tegra30: Unknown pkg %d\n", package_id);
187 BUG();
188 break;
189 }
190 break;
191 case 0x8F:
192 tegra_cpu_speedo_id = 8;
193 tegra_soc_speedo_id = 1;
194 threshold_index = THRESHOLD_INDEX_11;
195 break;
196 case 0x08:
197 tegra_cpu_speedo_id = 1;
198 tegra_soc_speedo_id = 1;
199 threshold_index = THRESHOLD_INDEX_4;
200 break;
201 case 0x02:
202 tegra_cpu_speedo_id = 2;
203 tegra_soc_speedo_id = 2;
204 threshold_index = THRESHOLD_INDEX_5;
205 break;
206 case 0x04:
207 tegra_cpu_speedo_id = 3;
208 tegra_soc_speedo_id = 2;
209 threshold_index = THRESHOLD_INDEX_6;
210 break;
211 case 0:
212 switch (package_id) {
213 case 1:
214 tegra_cpu_speedo_id = 2;
215 tegra_soc_speedo_id = 2;
216 threshold_index = THRESHOLD_INDEX_2;
217 break;
218 case 2:
219 tegra_cpu_speedo_id = 3;
220 tegra_soc_speedo_id = 2;
221 threshold_index = THRESHOLD_INDEX_3;
222 break;
223 default:
224 pr_err("Tegra30: Unknown pkg %d\n", package_id);
225 BUG();
226 break;
227 }
228 break;
229 default:
230 pr_warn("Tegra30: Unknown SKU %d\n", sku);
231 tegra_cpu_speedo_id = 0;
232 tegra_soc_speedo_id = 0;
233 threshold_index = THRESHOLD_INDEX_0;
234 break;
235 }
236 break;
237 default:
238 pr_warn("Tegra30: Unknown chip rev %d\n", rev);
239 tegra_cpu_speedo_id = 0;
240 tegra_soc_speedo_id = 0;
241 threshold_index = THRESHOLD_INDEX_0;
242 break;
243 }
244}
245
246void tegra30_init_speedo_data(void)
247{
248 u32 cpu_speedo_val;
249 u32 core_speedo_val;
250 int i;
251
252 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
253 THRESHOLD_INDEX_COUNT);
254 BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
255 THRESHOLD_INDEX_COUNT);
256
257 package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
258
259 rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id);
260 fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
261 pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
262 pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
263
264 for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
265 if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
266 break;
267 }
268 tegra_cpu_process_id = i - 1;
269
270 if (tegra_cpu_process_id == -1) {
271 pr_warn("Tegra30: CPU speedo value %3d out of range",
272 cpu_speedo_val);
273 tegra_cpu_process_id = 0;
274 tegra_cpu_speedo_id = 1;
275 }
276
277 for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
278 if (core_speedo_val < core_process_speedos[threshold_index][i])
279 break;
280 }
281 tegra_core_process_id = i - 1;
282
283 if (tegra_core_process_id == -1) {
284 pr_warn("Tegra30: CORE speedo value %3d out of range",
285 core_speedo_val);
286 tegra_core_process_id = 0;
287 tegra_soc_speedo_id = 1;
288 }
289
290 pr_info("Tegra30: CPU Speedo ID %d, Soc Speedo ID %d",
291 tegra_cpu_speedo_id, tegra_soc_speedo_id);
292}
diff --git a/arch/arm/mach-tegra/tegra_cpu_car.h b/arch/arm/mach-tegra/tegra_cpu_car.h
index 30d063ad2bef..9764d31032b7 100644
--- a/arch/arm/mach-tegra/tegra_cpu_car.h
+++ b/arch/arm/mach-tegra/tegra_cpu_car.h
@@ -30,6 +30,12 @@
30 * CPU clock un-gate 30 * CPU clock un-gate
31 * disable_clock: 31 * disable_clock:
32 * CPU clock gate 32 * CPU clock gate
33 * rail_off_ready:
34 * CPU is ready for rail off
35 * suspend:
36 * save the clock settings when CPU go into low-power state
37 * resume:
38 * restore the clock settings when CPU exit low-power state
33 */ 39 */
34struct tegra_cpu_car_ops { 40struct tegra_cpu_car_ops {
35 void (*wait_for_reset)(u32 cpu); 41 void (*wait_for_reset)(u32 cpu);
@@ -37,6 +43,11 @@ struct tegra_cpu_car_ops {
37 void (*out_of_reset)(u32 cpu); 43 void (*out_of_reset)(u32 cpu);
38 void (*enable_clock)(u32 cpu); 44 void (*enable_clock)(u32 cpu);
39 void (*disable_clock)(u32 cpu); 45 void (*disable_clock)(u32 cpu);
46#ifdef CONFIG_PM_SLEEP
47 bool (*rail_off_ready)(void);
48 void (*suspend)(void);
49 void (*resume)(void);
50#endif
40}; 51};
41 52
42extern struct tegra_cpu_car_ops *tegra_cpu_car_ops; 53extern struct tegra_cpu_car_ops *tegra_cpu_car_ops;
@@ -81,6 +92,32 @@ static inline void tegra_disable_cpu_clock(u32 cpu)
81 tegra_cpu_car_ops->disable_clock(cpu); 92 tegra_cpu_car_ops->disable_clock(cpu);
82} 93}
83 94
95#ifdef CONFIG_PM_SLEEP
96static inline bool tegra_cpu_rail_off_ready(void)
97{
98 if (WARN_ON(!tegra_cpu_car_ops->rail_off_ready))
99 return false;
100
101 return tegra_cpu_car_ops->rail_off_ready();
102}
103
104static inline void tegra_cpu_clock_suspend(void)
105{
106 if (WARN_ON(!tegra_cpu_car_ops->suspend))
107 return;
108
109 tegra_cpu_car_ops->suspend();
110}
111
112static inline void tegra_cpu_clock_resume(void)
113{
114 if (WARN_ON(!tegra_cpu_car_ops->resume))
115 return;
116
117 tegra_cpu_car_ops->resume();
118}
119#endif
120
84void tegra20_cpu_car_ops_init(void); 121void tegra20_cpu_car_ops_init(void);
85void tegra30_cpu_car_ops_init(void); 122void tegra30_cpu_car_ops_init(void);
86 123
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index d3b8c8e7368f..e4863f3e9ee7 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -26,16 +26,14 @@
26#include <linux/clocksource.h> 26#include <linux/clocksource.h>
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/io.h> 28#include <linux/io.h>
29#include <linux/of_address.h>
30#include <linux/of_irq.h>
29 31
30#include <asm/mach/time.h> 32#include <asm/mach/time.h>
31#include <asm/smp_twd.h> 33#include <asm/smp_twd.h>
32#include <asm/sched_clock.h> 34#include <asm/sched_clock.h>
33 35
34#include <mach/iomap.h>
35#include <mach/irqs.h>
36
37#include "board.h" 36#include "board.h"
38#include "clock.h"
39 37
40#define RTC_SECONDS 0x08 38#define RTC_SECONDS 0x08
41#define RTC_SHADOW_SECONDS 0x0c 39#define RTC_SHADOW_SECONDS 0x0c
@@ -53,8 +51,8 @@
53#define TIMER_PTV 0x0 51#define TIMER_PTV 0x0
54#define TIMER_PCR 0x4 52#define TIMER_PCR 0x4
55 53
56static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE); 54static void __iomem *timer_reg_base;
57static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE); 55static void __iomem *rtc_base;
58 56
59static struct timespec persistent_ts; 57static struct timespec persistent_ts;
60static u64 persistent_ms, last_persistent_ms; 58static u64 persistent_ms, last_persistent_ms;
@@ -158,40 +156,66 @@ static struct irqaction tegra_timer_irq = {
158 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH, 156 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH,
159 .handler = tegra_timer_interrupt, 157 .handler = tegra_timer_interrupt,
160 .dev_id = &tegra_clockevent, 158 .dev_id = &tegra_clockevent,
161 .irq = INT_TMR3,
162}; 159};
163 160
164#ifdef CONFIG_HAVE_ARM_TWD 161static const struct of_device_id timer_match[] __initconst = {
165static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 162 { .compatible = "nvidia,tegra20-timer" },
166 TEGRA_ARM_PERIF_BASE + 0x600, 163 {}
167 IRQ_LOCALTIMER); 164};
168 165
169static void __init tegra_twd_init(void) 166static const struct of_device_id rtc_match[] __initconst = {
170{ 167 { .compatible = "nvidia,tegra20-rtc" },
171 int err = twd_local_timer_register(&twd_local_timer); 168 {}
172 if (err) 169};
173 pr_err("twd_local_timer_register failed %d\n", err);
174}
175#else
176#define tegra_twd_init() do {} while(0)
177#endif
178 170
179static void __init tegra_init_timer(void) 171static void __init tegra_init_timer(void)
180{ 172{
173 struct device_node *np;
181 struct clk *clk; 174 struct clk *clk;
182 unsigned long rate; 175 unsigned long rate;
183 int ret; 176 int ret;
184 177
178 np = of_find_matching_node(NULL, timer_match);
179 if (!np) {
180 pr_err("Failed to find timer DT node\n");
181 BUG();
182 }
183
184 timer_reg_base = of_iomap(np, 0);
185 if (!timer_reg_base) {
186 pr_err("Can't map timer registers");
187 BUG();
188 }
189
190 tegra_timer_irq.irq = irq_of_parse_and_map(np, 2);
191 if (tegra_timer_irq.irq <= 0) {
192 pr_err("Failed to map timer IRQ\n");
193 BUG();
194 }
195
185 clk = clk_get_sys("timer", NULL); 196 clk = clk_get_sys("timer", NULL);
186 if (IS_ERR(clk)) { 197 if (IS_ERR(clk)) {
187 pr_warn("Unable to get timer clock." 198 pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n");
188 " Assuming 12Mhz input clock.\n");
189 rate = 12000000; 199 rate = 12000000;
190 } else { 200 } else {
191 clk_prepare_enable(clk); 201 clk_prepare_enable(clk);
192 rate = clk_get_rate(clk); 202 rate = clk_get_rate(clk);
193 } 203 }
194 204
205 of_node_put(np);
206
207 np = of_find_matching_node(NULL, rtc_match);
208 if (!np) {
209 pr_err("Failed to find RTC DT node\n");
210 BUG();
211 }
212
213 rtc_base = of_iomap(np, 0);
214 if (!rtc_base) {
215 pr_err("Can't map RTC registers");
216 BUG();
217 }
218
195 /* 219 /*
196 * rtc registers are used by read_persistent_clock, keep the rtc clock 220 * rtc registers are used by read_persistent_clock, keep the rtc clock
197 * enabled 221 * enabled
@@ -202,6 +226,8 @@ static void __init tegra_init_timer(void)
202 else 226 else
203 clk_prepare_enable(clk); 227 clk_prepare_enable(clk);
204 228
229 of_node_put(np);
230
205 switch (rate) { 231 switch (rate) {
206 case 12000000: 232 case 12000000:
207 timer_writel(0x000b, TIMERUS_USEC_CFG); 233 timer_writel(0x000b, TIMERUS_USEC_CFG);
@@ -223,13 +249,13 @@ static void __init tegra_init_timer(void)
223 249
224 if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, 250 if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US,
225 "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) { 251 "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) {
226 printk(KERN_ERR "Failed to register clocksource\n"); 252 pr_err("Failed to register clocksource\n");
227 BUG(); 253 BUG();
228 } 254 }
229 255
230 ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq); 256 ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
231 if (ret) { 257 if (ret) {
232 printk(KERN_ERR "Failed to register timer IRQ: %d\n", ret); 258 pr_err("Failed to register timer IRQ: %d\n", ret);
233 BUG(); 259 BUG();
234 } 260 }
235 261
@@ -241,7 +267,9 @@ static void __init tegra_init_timer(void)
241 tegra_clockevent.cpumask = cpu_all_mask; 267 tegra_clockevent.cpumask = cpu_all_mask;
242 tegra_clockevent.irq = tegra_timer_irq.irq; 268 tegra_clockevent.irq = tegra_timer_irq.irq;
243 clockevents_register_device(&tegra_clockevent); 269 clockevents_register_device(&tegra_clockevent);
244 tegra_twd_init(); 270#ifdef CONFIG_HAVE_ARM_TWD
271 twd_local_timer_of_register();
272#endif
245 register_persistent_clock(NULL, tegra_read_persistent_clock); 273 register_persistent_clock(NULL, tegra_read_persistent_clock);
246} 274}
247 275