summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Chauvet <kwizart@gmail.com>2014-07-21 21:22:15 +0200
committerNicolas Chauvet <kwizart@gmail.com>2014-08-09 22:11:39 +0200
commitbd19a3898abf2154a55448d07418b8edff094be2 (patch)
tree6ea6b0694ca9069d56a61f1a5bacccc20195536b
parent186a708bb62ba479c094d3f2ba5dd5199ebfb657 (diff)
downloadkernel-bd19a3898abf2154a55448d07418b8edff094be2.tar.gz
kernel-bd19a3898abf2154a55448d07418b8edff094be2.tar.xz
kernel-bd19a3898abf2154a55448d07418b8edff094be2.zip
Fixup tegra-bp-next-3.17.patch
-rw-r--r--tegra-bp-next-3.17.patch2904
1 files changed, 1823 insertions, 1081 deletions
diff --git a/tegra-bp-next-3.17.patch b/tegra-bp-next-3.17.patch
index 05f1dd20..f91381ee 100644
--- a/tegra-bp-next-3.17.patch
+++ b/tegra-bp-next-3.17.patch
@@ -2546,10 +2546,10 @@ index 5306de3..312d43e 100644
+ delay_calibrated = true;
+}
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
-index 6fbfbb7..34c05b7 100644
+index 6fbfbb7..e48a744 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
-@@ -2,24 +2,19 @@ asflags-y += -march=armv7-a
+@@ -2,24 +2,18 @@ asflags-y += -march=armv7-a
obj-y += io.o
obj-y += irq.o
@@ -2563,7 +2563,6 @@ index 6fbfbb7..34c05b7 100644
obj-y += reset-handler.o
obj-y += sleep.o
obj-y += tegra.o
-+obj-y += tegra-pmc.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-tegra20.o
@@ -2575,7 +2574,7 @@ index 6fbfbb7..34c05b7 100644
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pm-tegra30.o
ifeq ($(CONFIG_CPU_IDLE),y)
-@@ -28,7 +23,6 @@ endif
+@@ -28,7 +22,6 @@ endif
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
@@ -2947,16 +2946,16 @@ index ed2a2a7..3556127 100644
#include "pm.h"
#include "sleep.h"
diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
-index 7bc5d8d..b27330c 100644
+index 7bc5d8d..3165631 100644
--- a/arch/arm/mach-tegra/cpuidle.c
+++ b/arch/arm/mach-tegra/cpuidle.c
-@@ -23,13 +23,13 @@
-
+@@ -24,12 +24,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
-+#include <linux/tegra-soc.h>
-#include "fuse.h"
++#include <soc/tegra/fuse.h>
++
#include "cpuidle.h"
void __init tegra_cpuidle_init(void)
@@ -2966,7 +2965,7 @@ index 7bc5d8d..b27330c 100644
case TEGRA20:
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
tegra20_cpuidle_init();
-@@ -49,7 +49,7 @@ void __init tegra_cpuidle_init(void)
+@@ -49,7 +50,7 @@ void __init tegra_cpuidle_init(void)
void tegra_cpuidle_pcie_irqs_in_use(void)
{
@@ -2976,10 +2975,10 @@ index 7bc5d8d..b27330c 100644
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
tegra20_cpuidle_pcie_irqs_in_use();
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
-index ce8ab8a..2106b3d 100644
+index ce8ab8a..ec55d1d 100644
--- a/arch/arm/mach-tegra/flowctrl.c
+++ b/arch/arm/mach-tegra/flowctrl.c
-@@ -18,14 +18,14 @@
+@@ -18,14 +18,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -2989,7 +2988,8 @@ index ce8ab8a..2106b3d 100644
#include <linux/io.h>
-#include <linux/cpumask.h>
+#include <linux/kernel.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
#include "flowctrl.h"
#include "iomap.h"
@@ -2997,7 +2997,7 @@ index ce8ab8a..2106b3d 100644
static u8 flowctrl_offset_halt_cpu[] = {
FLOW_CTRL_HALT_CPU0_EVENTS,
-@@ -76,7 +76,7 @@ void flowctrl_cpu_suspend_enter(unsigned int cpuid)
+@@ -76,7 +77,7 @@ void flowctrl_cpu_suspend_enter(unsigned int cpuid)
int i;
reg = flowctrl_read_cpu_csr(cpuid);
@@ -3006,7 +3006,7 @@ index ce8ab8a..2106b3d 100644
case TEGRA20:
/* clear wfe bitmap */
reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
-@@ -117,7 +117,7 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
+@@ -117,7 +118,7 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
/* Disable powergating via flow controller for CPU0 */
reg = flowctrl_read_cpu_csr(cpuid);
@@ -3359,10 +3359,10 @@ index c01d047..0000000
-
-#endif
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
-index ff26af2..e2ea4aa 100644
+index ff26af2..6fc71f1 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
-@@ -7,13 +7,14 @@
+@@ -7,13 +7,16 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
@@ -3371,7 +3371,9 @@ index ff26af2..e2ea4aa 100644
#include <linux/kernel.h>
#include <linux/smp.h>
-#include <linux/clk/tegra.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/common.h>
++#include <soc/tegra/fuse.h>
#include <asm/smp_plat.h>
@@ -3379,7 +3381,7 @@ index ff26af2..e2ea4aa 100644
#include "sleep.h"
static void (*tegra_hotplug_shutdown)(void);
-@@ -36,6 +37,11 @@ int tegra_cpu_kill(unsigned cpu)
+@@ -36,6 +39,11 @@ int tegra_cpu_kill(unsigned cpu)
*/
void __ref tegra_cpu_die(unsigned int cpu)
{
@@ -3391,7 +3393,7 @@ index ff26af2..e2ea4aa 100644
/* Clean L1 data cache */
tegra_disable_clean_inv_dcache(TEGRA_FLUSH_CACHE_LOUIS);
-@@ -46,17 +52,20 @@ void __ref tegra_cpu_die(unsigned int cpu)
+@@ -46,17 +54,23 @@ void __ref tegra_cpu_die(unsigned int cpu)
BUG();
}
@@ -3403,6 +3405,9 @@ index ff26af2..e2ea4aa 100644
+ return 0;
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
++ if (!soc_is_tegra())
++ return 0;
++
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
- if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
@@ -3465,10 +3470,10 @@ index 1a74d56..da7be13 100644
#include "board.h"
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
-index 929d104..53e8442 100644
+index 929d104..b450866 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
-@@ -11,27 +11,26 @@
+@@ -11,27 +11,28 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
@@ -3485,7 +3490,9 @@ index 929d104..53e8442 100644
#include <linux/smp.h>
-#include <linux/io.h>
-#include <linux/clk/tegra.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
++#include <soc/tegra/pmc.h>
#include <asm/cacheflush.h>
#include <asm/mach-types.h>
@@ -3505,7 +3512,7 @@ index 929d104..53e8442 100644
static cpumask_t tegra_cpu_init_mask;
-@@ -170,13 +169,13 @@ static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
+@@ -170,13 +171,13 @@ static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
static int tegra_boot_secondary(unsigned int cpu,
struct task_struct *idle)
{
@@ -3548,10 +3555,10 @@ index 8fa326d..46cc19d 100644
#include "pm.h"
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
-index f55b05a..d9637d8 100644
+index f55b05a..b0f48a3 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
-@@ -16,30 +16,29 @@
+@@ -16,30 +16,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -3571,7 +3578,10 @@ index f55b05a..d9637d8 100644
-#include <linux/clk/tegra.h>
+#include <linux/spinlock.h>
+#include <linux/suspend.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
++#include <soc/tegra/pm.h>
++#include <soc/tegra/pmc.h>
-#include <asm/smp_plat.h>
#include <asm/cacheflush.h>
@@ -3593,7 +3603,7 @@ index f55b05a..d9637d8 100644
#include "sleep.h"
#ifdef CONFIG_PM_SLEEP
-@@ -53,7 +52,7 @@ static int (*tegra_sleep_func)(unsigned long v2p);
+@@ -53,7 +55,7 @@ static int (*tegra_sleep_func)(unsigned long v2p);
static void tegra_tear_down_cpu_init(void)
{
@@ -3602,7 +3612,7 @@ index f55b05a..d9637d8 100644
case TEGRA20:
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
tegra_tear_down_cpu = tegra20_tear_down_cpu;
-@@ -143,7 +142,7 @@ bool tegra_set_cpu_in_lp2(void)
+@@ -143,7 +145,7 @@ bool tegra_set_cpu_in_lp2(void)
if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
last_cpu = true;
@@ -3611,7 +3621,7 @@ index f55b05a..d9637d8 100644
tegra20_cpu_set_resettable_soon();
spin_unlock(&tegra_lp2_lock);
-@@ -166,9 +165,29 @@ static int tegra_sleep_cpu(unsigned long v2p)
+@@ -166,9 +168,29 @@ static int tegra_sleep_cpu(unsigned long v2p)
return 0;
}
@@ -3642,7 +3652,7 @@ index f55b05a..d9637d8 100644
cpu_cluster_pm_enter();
suspend_cpu_complex();
-@@ -212,7 +231,7 @@ static int tegra_sleep_core(unsigned long v2p)
+@@ -212,7 +234,7 @@ static int tegra_sleep_core(unsigned long v2p)
*/
static bool tegra_lp1_iram_hook(void)
{
@@ -3651,7 +3661,7 @@ index f55b05a..d9637d8 100644
case TEGRA20:
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
tegra20_lp1_iram_hook();
-@@ -242,7 +261,7 @@ static bool tegra_lp1_iram_hook(void)
+@@ -242,7 +264,7 @@ static bool tegra_lp1_iram_hook(void)
static bool tegra_sleep_core_init(void)
{
@@ -3660,7 +3670,7 @@ index f55b05a..d9637d8 100644
case TEGRA20:
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
tegra20_sleep_core_init();
-@@ -267,8 +286,6 @@ static bool tegra_sleep_core_init(void)
+@@ -267,8 +289,6 @@ static bool tegra_sleep_core_init(void)
static void tegra_suspend_enter_lp1(void)
{
@@ -3669,7 +3679,7 @@ index f55b05a..d9637d8 100644
/* copy the reset vector & SDRAM shutdown code into IRAM */
memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
iram_save_size);
-@@ -280,8 +297,6 @@ static void tegra_suspend_enter_lp1(void)
+@@ -280,8 +300,6 @@ static void tegra_suspend_enter_lp1(void)
static void tegra_suspend_exit_lp1(void)
{
@@ -3678,7 +3688,7 @@ index f55b05a..d9637d8 100644
/* restore IRAM */
memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr,
iram_save_size);
-@@ -306,7 +321,7 @@ static int tegra_suspend_enter(suspend_state_t state)
+@@ -306,7 +324,7 @@ static int tegra_suspend_enter(suspend_state_t state)
pr_info("Entering suspend state %s\n", lp_state[mode]);
@@ -3687,7 +3697,7 @@ index f55b05a..d9637d8 100644
local_fiq_disable();
-@@ -354,7 +369,6 @@ void __init tegra_init_suspend(void)
+@@ -354,7 +372,6 @@ void __init tegra_init_suspend(void)
return;
tegra_tear_down_cpu_init();
@@ -4725,17 +4735,18 @@ index 4cefc5c..0000000
-}
-EXPORT_SYMBOL(tegra_io_rail_power_off);
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
-index 578d4d1..be2eaa8 100644
+index 578d4d1..7b2baab 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
-@@ -14,14 +14,14 @@
+@@ -14,14 +14,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <linux/linkage.h>
#include <linux/init.h>
+#include <linux/linkage.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
-#include <asm/cache.h>
#include <asm/asm-offsets.h>
@@ -4747,10 +4758,10 @@ index 578d4d1..be2eaa8 100644
#include "reset.h"
#include "sleep.h"
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
-index 146fe8e..96cafc4 100644
+index 146fe8e..894c5c4 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
-@@ -14,20 +14,20 @@
+@@ -14,20 +14,21 @@
*
*/
@@ -4760,7 +4771,8 @@ index 146fe8e..96cafc4 100644
#include <linux/io.h>
-#include <linux/cpumask.h>
-#include <linux/bitops.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
#include <asm/cacheflush.h>
-#include <asm/hardware/cache-l2x0.h>
@@ -4775,7 +4787,7 @@ index 146fe8e..96cafc4 100644
#define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
TEGRA_IRAM_RESET_HANDLER_OFFSET)
-@@ -53,12 +53,10 @@ static void __init tegra_cpu_reset_handler_set(const u32 reset_address)
+@@ -53,12 +54,10 @@ static void __init tegra_cpu_reset_handler_set(const u32 reset_address)
* Prevent further modifications to the physical reset vector.
* NOTE: Has no effect on chips prior to Tegra30.
*/
@@ -4793,16 +4805,16 @@ index 146fe8e..96cafc4 100644
static void __init tegra_cpu_reset_handler_enable(void)
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
-index b16d4a57..3700fe9 100644
+index b16d4a57..8ea699b 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
-@@ -15,15 +15,15 @@
- */
+@@ -16,14 +16,15 @@
#include <linux/linkage.h>
-+#include <linux/tegra-soc.h>
-#include <asm/assembler.h>
++#include <soc/tegra/fuse.h>
++
#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
#include <asm/cache.h>
@@ -4829,965 +4841,11 @@ index 339fe42..92d46ec 100644
#endif
void tegra20_cpu_shutdown(int cpu);
-diff --git a/arch/arm/mach-tegra/tegra-pmc.c b/arch/arm/mach-tegra/tegra-pmc.c
-new file mode 100644
-index 0000000..b6bc758
---- /dev/null
-+++ b/arch/arm/mach-tegra/tegra-pmc.c
-@@ -0,0 +1,948 @@
-+/*
-+ * drivers/soc/tegra/pmc.c
-+ *
-+ * Copyright (c) 2010 Google, Inc
-+ *
-+ * Author:
-+ * Colin Cross <ccross@google.com>
-+ *
-+ * This software is licensed under the terms of the GNU General Public
-+ * License version 2, as published by the Free Software Foundation, and
-+ * may be copied, distributed, and modified under those terms.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/clk.h>
-+#include <linux/clk/tegra.h>
-+#include <linux/debugfs.h>
-+#include <linux/delay.h>
-+#include <linux/err.h>
-+#include <linux/export.h>
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/of.h>
-+#include <linux/of_address.h>
-+#include <linux/platform_device.h>
-+#include <linux/reboot.h>
-+#include <linux/reset.h>
-+#include <linux/seq_file.h>
-+#include <linux/spinlock.h>
-+#include <linux/tegra-powergate.h>
-+#include <linux/tegra-soc.h>
-+
-+#define PMC_CNTRL 0x0
-+#define PMC_CNTRL_SYSCLK_POLARITY (1 << 10) /* sys clk polarity */
-+#define PMC_CNTRL_SYSCLK_OE (1 << 11) /* system clock enable */
-+#define PMC_CNTRL_SIDE_EFFECT_LP0 (1 << 14) /* LP0 when CPU pwr gated */
-+#define PMC_CNTRL_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */
-+#define PMC_CNTRL_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
-+#define PMC_CNTRL_INTR_POLARITY (1 << 17) /* inverts INTR polarity */
-+
-+#define DPD_SAMPLE 0x020
-+#define DPD_SAMPLE_ENABLE (1 << 0)
-+#define DPD_SAMPLE_DISABLE (0 << 0)
-+
-+#define PWRGATE_TOGGLE 0x30
-+#define PWRGATE_TOGGLE_START (1 << 8)
-+
-+#define REMOVE_CLAMPING 0x34
-+
-+#define PWRGATE_STATUS 0x38
-+
-+#define PMC_SCRATCH0 0x50
-+#define PMC_SCRATCH0_MODE_RECOVERY (1 << 31)
-+#define PMC_SCRATCH0_MODE_BOOTLOADER (1 << 30)
-+#define PMC_SCRATCH0_MODE_RCM (1 << 1)
-+#define PMC_SCRATCH0_MODE_MASK (PMC_SCRATCH0_MODE_RECOVERY | \
-+ PMC_SCRATCH0_MODE_BOOTLOADER | \
-+ PMC_SCRATCH0_MODE_RCM)
-+
-+#define PMC_CPUPWRGOOD_TIMER 0xc8
-+#define PMC_CPUPWROFF_TIMER 0xcc
-+
-+#define PMC_SCRATCH41 0x140
-+
-+#define IO_DPD_REQ 0x1b8
-+#define IO_DPD_REQ_CODE_IDLE (0 << 30)
-+#define IO_DPD_REQ_CODE_OFF (1 << 30)
-+#define IO_DPD_REQ_CODE_ON (2 << 30)
-+#define IO_DPD_REQ_CODE_MASK (3 << 30)
-+
-+#define IO_DPD_STATUS 0x1bc
-+#define IO_DPD2_REQ 0x1c0
-+#define IO_DPD2_STATUS 0x1c4
-+#define SEL_DPD_TIM 0x1c8
-+
-+#define GPU_RG_CNTRL 0x2d4
-+
-+struct tegra_pmc_soc {
-+ unsigned int num_powergates;
-+ const char *const *powergates;
-+ unsigned int num_cpu_powergates;
-+ const u8 *cpu_powergates;
-+};
-+
-+/**
-+ * struct tegra_pmc - NVIDIA Tegra PMC
-+ * @base: pointer to I/O remapped register region
-+ * @clk: pointer to pclk clock
-+ * @rate: currently configured rate of pclk
-+ * @suspend_mode: lowest suspend mode available
-+ * @cpu_good_time: CPU power good time (in microseconds)
-+ * @cpu_off_time: CPU power off time (in microsecends)
-+ * @core_osc_time: core power good OSC time (in microseconds)
-+ * @core_pmu_time: core power good PMU time (in microseconds)
-+ * @core_off_time: core power off time (in microseconds)
-+ * @corereq_high: core power request is active-high
-+ * @sysclkreq_high: system clock request is active-high
-+ * @combined_req: combined power request for CPU & core
-+ * @cpu_pwr_good_en: CPU power good signal is enabled
-+ * @lp0_vec_phys: physical base address of the LP0 warm boot code
-+ * @lp0_vec_size: size of the LP0 warm boot code
-+ * @powergates_lock: mutex for power gate register access
-+ */
-+struct tegra_pmc {
-+ void __iomem *base;
-+ struct clk *clk;
-+
-+ const struct tegra_pmc_soc *soc;
-+
-+ unsigned long rate;
-+
-+ enum tegra_suspend_mode suspend_mode;
-+ u32 cpu_good_time;
-+ u32 cpu_off_time;
-+ u32 core_osc_time;
-+ u32 core_pmu_time;
-+ u32 core_off_time;
-+ bool corereq_high;
-+ bool sysclkreq_high;
-+ bool combined_req;
-+ bool cpu_pwr_good_en;
-+ u32 lp0_vec_phys;
-+ u32 lp0_vec_size;
-+
-+ struct mutex powergates_lock;
-+};
-+
-+static struct tegra_pmc *pmc = &(struct tegra_pmc) {
-+ .base = NULL,
-+ .suspend_mode = TEGRA_SUSPEND_NONE,
-+};
-+
-+static u32 tegra_pmc_readl(unsigned long offset)
-+{
-+ return readl(pmc->base + offset);
-+}
-+
-+static void tegra_pmc_writel(u32 value, unsigned long offset)
-+{
-+ writel(value, pmc->base + offset);
-+}
-+
-+/**
-+ * tegra_powergate_set() - set the state of a partition
-+ * @id: partition ID
-+ * @new_state: new state of the partition
-+ */
-+static int tegra_powergate_set(int id, bool new_state)
-+{
-+ bool status;
-+
-+ mutex_lock(&pmc->powergates_lock);
-+
-+ status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
-+
-+ if (status == new_state) {
-+ mutex_unlock(&pmc->powergates_lock);
-+ return 0;
-+ }
-+
-+ tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
-+
-+ mutex_unlock(&pmc->powergates_lock);
-+
-+ return 0;
-+}
-+
-+/**
-+ * tegra_powergate_power_on() - power on partition
-+ * @id: partition ID
-+ */
-+int tegra_powergate_power_on(int id)
-+{
-+ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
-+ return -EINVAL;
-+
-+ return tegra_powergate_set(id, true);
-+}
-+
-+/**
-+ * tegra_powergate_power_off() - power off partition
-+ * @id: partition ID
-+ */
-+int tegra_powergate_power_off(int id)
-+{
-+ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
-+ return -EINVAL;
-+
-+ return tegra_powergate_set(id, false);
-+}
-+EXPORT_SYMBOL(tegra_powergate_power_off);
-+
-+/**
-+ * tegra_powergate_is_powered() - check if partition is powered
-+ * @id: partition ID
-+ */
-+int tegra_powergate_is_powered(int id)
-+{
-+ u32 status;
-+
-+ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
-+ return -EINVAL;
-+
-+ status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
-+ return !!status;
-+}
-+
-+/**
-+ * tegra_powergate_remove_clamping() - remove power clamps for partition
-+ * @id: partition ID
-+ */
-+int tegra_powergate_remove_clamping(int id)
-+{
-+ u32 mask;
-+
-+ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
-+ return -EINVAL;
-+
-+ /*
-+ * The Tegra124 GPU has a separate register (with different semantics)
-+ * to remove clamps.
-+ */
-+ if (tegra_get_chip_id() == TEGRA124) {
-+ if (id == TEGRA_POWERGATE_3D) {
-+ tegra_pmc_writel(0, GPU_RG_CNTRL);
-+ return 0;
-+ }
-+ }
-+
-+ /*
-+ * Tegra 2 has a bug where PCIE and VDE clamping masks are
-+ * swapped relatively to the partition ids
-+ */
-+ if (id == TEGRA_POWERGATE_VDEC)
-+ mask = (1 << TEGRA_POWERGATE_PCIE);
-+ else if (id == TEGRA_POWERGATE_PCIE)
-+ mask = (1 << TEGRA_POWERGATE_VDEC);
-+ else
-+ mask = (1 << id);
-+
-+ tegra_pmc_writel(mask, REMOVE_CLAMPING);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(tegra_powergate_remove_clamping);
-+
-+/**
-+ * tegra_powergate_sequence_power_up() - power up partition
-+ * @id: partition ID
-+ * @clk: clock for partition
-+ * @rst: reset for partition
-+ *
-+ * Must be called with clk disabled, and returns with clk enabled.
-+ */
-+int tegra_powergate_sequence_power_up(int id, struct clk *clk,
-+ struct reset_control *rst)
-+{
-+ int ret;
-+
-+ reset_control_assert(rst);
-+
-+ ret = tegra_powergate_power_on(id);
-+ if (ret)
-+ goto err_power;
-+
-+ ret = clk_prepare_enable(clk);
-+ if (ret)
-+ goto err_clk;
-+
-+ usleep_range(10, 20);
-+
-+ ret = tegra_powergate_remove_clamping(id);
-+ if (ret)
-+ goto err_clamp;
-+
-+ usleep_range(10, 20);
-+ reset_control_deassert(rst);
-+
-+ return 0;
-+
-+err_clamp:
-+ clk_disable_unprepare(clk);
-+err_clk:
-+ tegra_powergate_power_off(id);
-+err_power:
-+ return ret;
-+}
-+EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
-+
-+/**
-+ * tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
-+ * @cpuid: CPU partition ID
-+ *
-+ * Returns the partition ID corresponding to the CPU partition ID or a
-+ * negative error code on failure.
-+ */
-+static int tegra_get_cpu_powergate_id(int cpuid)
-+{
-+ if (pmc->soc && cpuid > 0 && cpuid < pmc->soc->num_cpu_powergates)
-+ return pmc->soc->cpu_powergates[cpuid];
-+
-+ return -EINVAL;
-+}
-+
-+/**
-+ * tegra_pmc_cpu_is_powered() - check if CPU partition is powered
-+ * @cpuid: CPU partition ID
-+ */
-+bool tegra_pmc_cpu_is_powered(int cpuid)
-+{
-+ int id;
-+
-+ id = tegra_get_cpu_powergate_id(cpuid);
-+ if (id < 0)
-+ return false;
-+
-+ return tegra_powergate_is_powered(id);
-+}
-+
-+/**
-+ * tegra_pmc_cpu_power_on() - power on CPU partition
-+ * @cpuid: CPU partition ID
-+ */
-+int tegra_pmc_cpu_power_on(int cpuid)
-+{
-+ int id;
-+
-+ id = tegra_get_cpu_powergate_id(cpuid);
-+ if (id < 0)
-+ return id;
-+
-+ return tegra_powergate_set(id, true);
-+}
-+
-+/**
-+ * tegra_pmc_cpu_remove_clamping() - remove power clamps for CPU partition
-+ * @cpuid: CPU partition ID
-+ */
-+int tegra_pmc_cpu_remove_clamping(int cpuid)
-+{
-+ int id;
-+
-+ id = tegra_get_cpu_powergate_id(cpuid);
-+ if (id < 0)
-+ return id;
-+
-+ return tegra_powergate_remove_clamping(id);
-+}
-+
-+/**
-+ * tegra_pmc_restart() - reboot the system
-+ * @mode: which mode to reboot in
-+ * @cmd: reboot command
-+ */
-+void tegra_pmc_restart(enum reboot_mode mode, const char *cmd)
-+{
-+ u32 value;
-+
-+ value = tegra_pmc_readl(PMC_SCRATCH0);
-+ value &= ~PMC_SCRATCH0_MODE_MASK;
-+
-+ if (cmd) {
-+ if (strcmp(cmd, "recovery") == 0)
-+ value |= PMC_SCRATCH0_MODE_RECOVERY;
-+
-+ if (strcmp(cmd, "bootloader") == 0)
-+ value |= PMC_SCRATCH0_MODE_BOOTLOADER;
-+
-+ if (strcmp(cmd, "forced-recovery") == 0)
-+ value |= PMC_SCRATCH0_MODE_RCM;
-+ }
-+
-+ tegra_pmc_writel(value, PMC_SCRATCH0);
-+
-+ value = tegra_pmc_readl(0);
-+ value |= 0x10;
-+ tegra_pmc_writel(value, 0);
-+}
-+
-+static int powergate_show(struct seq_file *s, void *data)
-+{
-+ unsigned int i;
-+
-+ seq_printf(s, " powergate powered\n");
-+ seq_printf(s, "------------------\n");
-+
-+ for (i = 0; i < pmc->soc->num_powergates; i++) {
-+ if (!pmc->soc->powergates[i])
-+ continue;
-+
-+ seq_printf(s, " %9s %7s\n", pmc->soc->powergates[i],
-+ tegra_powergate_is_powered(i) ? "yes" : "no");
-+ }
-+
-+ return 0;
-+}
-+
-+static int powergate_open(struct inode *inode, struct file *file)
-+{
-+ return single_open(file, powergate_show, inode->i_private);
-+}
-+
-+static const struct file_operations powergate_fops = {
-+ .open = powergate_open,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
-+
-+static int tegra_powergate_debugfs_init(void)
-+{
-+ struct dentry *d;
-+
-+ d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
-+ &powergate_fops);
-+ if (!d)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+static int tegra_io_rail_prepare(int id, unsigned long *request,
-+ unsigned long *status, unsigned int *bit)
-+{
-+ unsigned long rate, value;
-+ struct clk *clk;
-+
-+ *bit = id % 32;
-+
-+ /*
-+ * There are two sets of 30 bits to select IO rails, but bits 30 and
-+ * 31 are control bits rather than IO rail selection bits.
-+ */
-+ if (id > 63 || *bit == 30 || *bit == 31)
-+ return -EINVAL;
-+
-+ if (id < 32) {
-+ *status = IO_DPD_STATUS;
-+ *request = IO_DPD_REQ;
-+ } else {
-+ *status = IO_DPD2_STATUS;
-+ *request = IO_DPD2_REQ;
-+ }
-+
-+ clk = clk_get_sys(NULL, "pclk");
-+ if (IS_ERR(clk))
-+ return PTR_ERR(clk);
-+
-+ rate = clk_get_rate(clk);
-+ clk_put(clk);
-+
-+ tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
-+
-+ /* must be at least 200 ns, in APB (PCLK) clock cycles */
-+ value = DIV_ROUND_UP(1000000000, rate);
-+ value = DIV_ROUND_UP(200, value);
-+ tegra_pmc_writel(value, SEL_DPD_TIM);
-+
-+ return 0;
-+}
-+
-+static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
-+ unsigned long val, unsigned long timeout)
-+{
-+ unsigned long value;
-+
-+ timeout = jiffies + msecs_to_jiffies(timeout);
-+
-+ while (time_after(timeout, jiffies)) {
-+ value = tegra_pmc_readl(offset);
-+ if ((value & mask) == val)
-+ return 0;
-+
-+ usleep_range(250, 1000);
-+ }
-+
-+ return -ETIMEDOUT;
-+}
-+
-+static void tegra_io_rail_unprepare(void)
-+{
-+ tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
-+}
-+
-+int tegra_io_rail_power_on(int id)
-+{
-+ unsigned long request, status, value;
-+ unsigned int bit, mask;
-+ int err;
-+
-+ err = tegra_io_rail_prepare(id, &request, &status, &bit);
-+ if (err < 0)
-+ return err;
-+
-+ mask = 1 << bit;
-+
-+ value = tegra_pmc_readl(request);
-+ value |= mask;
-+ value &= ~IO_DPD_REQ_CODE_MASK;
-+ value |= IO_DPD_REQ_CODE_OFF;
-+ tegra_pmc_writel(value, request);
-+
-+ err = tegra_io_rail_poll(status, mask, 0, 250);
-+ if (err < 0)
-+ return err;
-+
-+ tegra_io_rail_unprepare();
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(tegra_io_rail_power_on);
-+
-+int tegra_io_rail_power_off(int id)
-+{
-+ unsigned long request, status, value;
-+ unsigned int bit, mask;
-+ int err;
-+
-+ err = tegra_io_rail_prepare(id, &request, &status, &bit);
-+ if (err < 0)
-+ return err;
-+
-+ mask = 1 << bit;
-+
-+ value = tegra_pmc_readl(request);
-+ value |= mask;
-+ value &= ~IO_DPD_REQ_CODE_MASK;
-+ value |= IO_DPD_REQ_CODE_ON;
-+ tegra_pmc_writel(value, request);
-+
-+ err = tegra_io_rail_poll(status, mask, mask, 250);
-+ if (err < 0)
-+ return err;
-+
-+ tegra_io_rail_unprepare();
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(tegra_io_rail_power_off);
-+
-+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
-+{
-+ return pmc->suspend_mode;
-+}
-+
-+void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
-+{
-+ if (mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)
-+ return;
-+
-+ pmc->suspend_mode = mode;
-+}
-+
-+void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
-+{
-+ unsigned long long rate = 0;
-+ u32 value;
-+
-+ switch (mode) {
-+ case TEGRA_SUSPEND_LP1:
-+ rate = 32768;
-+ break;
-+
-+ case TEGRA_SUSPEND_LP2:
-+ rate = clk_get_rate(pmc->clk);
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ if (WARN_ON_ONCE(rate == 0))
-+ rate = 100000000;
-+
-+ if (rate != pmc->rate) {
-+ u64 ticks;
-+
-+ ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1;
-+ do_div(ticks, USEC_PER_SEC);
-+ tegra_pmc_writel(ticks, PMC_CPUPWRGOOD_TIMER);
-+
-+ ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1;
-+ do_div(ticks, USEC_PER_SEC);
-+ tegra_pmc_writel(ticks, PMC_CPUPWROFF_TIMER);
-+
-+ wmb();
-+
-+ pmc->rate = rate;
-+ }
-+
-+ value = tegra_pmc_readl(PMC_CNTRL);
-+ value &= ~PMC_CNTRL_SIDE_EFFECT_LP0;
-+ value |= PMC_CNTRL_CPU_PWRREQ_OE;
-+ tegra_pmc_writel(value, PMC_CNTRL);
-+}
-+
-+static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np)
-+{
-+ u32 value, values[2];
-+
-+ if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) {
-+ } else {
-+ switch (value) {
-+ case 0:
-+ pmc->suspend_mode = TEGRA_SUSPEND_LP0;
-+ break;
-+
-+ case 1:
-+ pmc->suspend_mode = TEGRA_SUSPEND_LP1;
-+ break;
-+
-+ case 2:
-+ pmc->suspend_mode = TEGRA_SUSPEND_LP2;
-+ break;
-+
-+ default:
-+ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
-+ break;
-+ }
-+ }
-+
-+ pmc->suspend_mode = tegra_pm_validate_suspend_mode(pmc->suspend_mode);
-+
-+ if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &value))
-+ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
-+
-+ pmc->cpu_good_time = value;
-+
-+ if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &value))
-+ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
-+
-+ pmc->cpu_off_time = value;
-+
-+ if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
-+ values, ARRAY_SIZE(values)))
-+ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
-+
-+ pmc->core_osc_time = values[0];
-+ pmc->core_pmu_time = values[1];
-+
-+ if (of_property_read_u32(np, "nvidia,core-pwr-off-time", &value))
-+ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
-+
-+ pmc->core_off_time = value;
-+
-+ pmc->corereq_high = of_property_read_bool(np,
-+ "nvidia,core-power-req-active-high");
-+
-+ pmc->sysclkreq_high = of_property_read_bool(np,
-+ "nvidia,sys-clock-req-active-high");
-+
-+ pmc->combined_req = of_property_read_bool(np,
-+ "nvidia,combined-power-req");
-+
-+ pmc->cpu_pwr_good_en = of_property_read_bool(np,
-+ "nvidia,cpu-pwr-good-en");
-+
-+ if (of_property_read_u32_array(np, "nvidia,lp0-vec", values,
-+ ARRAY_SIZE(values)))
-+ if (pmc->suspend_mode == TEGRA_SUSPEND_LP0)
-+ pmc->suspend_mode = TEGRA_SUSPEND_LP1;
-+
-+ pmc->lp0_vec_phys = values[0];
-+ pmc->lp0_vec_size = values[1];
-+
-+ return 0;
-+}
-+
-+static void tegra_pmc_init(struct tegra_pmc *pmc)
-+{
-+ u32 value;
-+
-+ /* Always enable CPU power request */
-+ value = tegra_pmc_readl(PMC_CNTRL);
-+ value |= PMC_CNTRL_CPU_PWRREQ_OE;
-+ tegra_pmc_writel(value, PMC_CNTRL);
-+
-+ value = tegra_pmc_readl(PMC_CNTRL);
-+
-+ if (pmc->sysclkreq_high)
-+ value &= ~PMC_CNTRL_SYSCLK_POLARITY;
-+ else
-+ value |= PMC_CNTRL_SYSCLK_POLARITY;
-+
-+ /* configure the output polarity while the request is tristated */
-+ tegra_pmc_writel(value, PMC_CNTRL);
-+
-+ /* now enable the request */
-+ value = tegra_pmc_readl(PMC_CNTRL);
-+ value |= PMC_CNTRL_SYSCLK_OE;
-+ tegra_pmc_writel(value, PMC_CNTRL);
-+}
-+
-+static int tegra_pmc_probe(struct platform_device *pdev)
-+{
-+ void __iomem *base = pmc->base;
-+ struct resource *res;
-+ int err;
-+
-+ err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node);
-+ if (err < 0)
-+ return err;
-+
-+ /* take over the memory region from the early initialization */
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ pmc->base = devm_ioremap_resource(&pdev->dev, res);
-+ if (IS_ERR(pmc->base))
-+ return PTR_ERR(pmc->base);
-+
-+ iounmap(base);
-+
-+ pmc->clk = devm_clk_get(&pdev->dev, "pclk");
-+ if (IS_ERR(pmc->clk)) {
-+ err = PTR_ERR(pmc->clk);
-+ dev_err(&pdev->dev, "failed to get pclk: %d\n", err);
-+ return err;
-+ }
-+
-+ tegra_pmc_init(pmc);
-+
-+ if (IS_ENABLED(CONFIG_DEBUG_FS)) {
-+ err = tegra_powergate_debugfs_init();
-+ if (err < 0)
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int tegra_pmc_suspend(struct device *dev)
-+{
-+ tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
-+
-+ return 0;
-+}
-+
-+static int tegra_pmc_resume(struct device *dev)
-+{
-+ tegra_pmc_writel(0x0, PMC_SCRATCH41);
-+
-+ return 0;
-+}
-+#endif
-+
-+static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume);
-+
-+static const char * const tegra20_powergates[] = {
-+ [TEGRA_POWERGATE_CPU] = "cpu",
-+ [TEGRA_POWERGATE_3D] = "3d",
-+ [TEGRA_POWERGATE_VENC] = "venc",
-+ [TEGRA_POWERGATE_VDEC] = "vdec",
-+ [TEGRA_POWERGATE_PCIE] = "pcie",
-+ [TEGRA_POWERGATE_L2] = "l2",
-+ [TEGRA_POWERGATE_MPE] = "mpe",
-+};
-+
-+static const struct tegra_pmc_soc tegra20_pmc_soc = {
-+ .num_powergates = ARRAY_SIZE(tegra20_powergates),
-+ .powergates = tegra20_powergates,
-+ .num_cpu_powergates = 0,
-+ .cpu_powergates = NULL,
-+};
-+
-+static const char * const tegra30_powergates[] = {
-+ [TEGRA_POWERGATE_CPU] = "cpu0",
-+ [TEGRA_POWERGATE_3D] = "3d0",
-+ [TEGRA_POWERGATE_VENC] = "venc",
-+ [TEGRA_POWERGATE_VDEC] = "vdec",
-+ [TEGRA_POWERGATE_PCIE] = "pcie",
-+ [TEGRA_POWERGATE_L2] = "l2",
-+ [TEGRA_POWERGATE_MPE] = "mpe",
-+ [TEGRA_POWERGATE_HEG] = "heg",
-+ [TEGRA_POWERGATE_SATA] = "sata",
-+ [TEGRA_POWERGATE_CPU1] = "cpu1",
-+ [TEGRA_POWERGATE_CPU2] = "cpu2",
-+ [TEGRA_POWERGATE_CPU3] = "cpu3",
-+ [TEGRA_POWERGATE_CELP] = "celp",
-+ [TEGRA_POWERGATE_3D1] = "3d1",
-+};
-+
-+static const u8 tegra30_cpu_powergates[] = {
-+ TEGRA_POWERGATE_CPU,
-+ TEGRA_POWERGATE_CPU1,
-+ TEGRA_POWERGATE_CPU2,
-+ TEGRA_POWERGATE_CPU3,
-+};
-+
-+static const struct tegra_pmc_soc tegra30_pmc_soc = {
-+ .num_powergates = ARRAY_SIZE(tegra30_powergates),
-+ .powergates = tegra30_powergates,
-+ .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
-+ .cpu_powergates = tegra30_cpu_powergates,
-+};
-+
-+static const char * const tegra114_powergates[] = {
-+ [TEGRA_POWERGATE_CPU] = "crail",
-+ [TEGRA_POWERGATE_3D] = "3d",
-+ [TEGRA_POWERGATE_VENC] = "venc",
-+ [TEGRA_POWERGATE_VDEC] = "vdec",
-+ [TEGRA_POWERGATE_MPE] = "mpe",
-+ [TEGRA_POWERGATE_HEG] = "heg",
-+ [TEGRA_POWERGATE_CPU1] = "cpu1",
-+ [TEGRA_POWERGATE_CPU2] = "cpu2",
-+ [TEGRA_POWERGATE_CPU3] = "cpu3",
-+ [TEGRA_POWERGATE_CELP] = "celp",
-+ [TEGRA_POWERGATE_CPU0] = "cpu0",
-+ [TEGRA_POWERGATE_C0NC] = "c0nc",
-+ [TEGRA_POWERGATE_C1NC] = "c1nc",
-+ [TEGRA_POWERGATE_DIS] = "dis",
-+ [TEGRA_POWERGATE_DISB] = "disb",
-+ [TEGRA_POWERGATE_XUSBA] = "xusba",
-+ [TEGRA_POWERGATE_XUSBB] = "xusbb",
-+ [TEGRA_POWERGATE_XUSBC] = "xusbc",
-+};
-+
-+static const u8 tegra114_cpu_powergates[] = {
-+ TEGRA_POWERGATE_CPU0,
-+ TEGRA_POWERGATE_CPU1,
-+ TEGRA_POWERGATE_CPU2,
-+ TEGRA_POWERGATE_CPU3,
-+};
-+
-+static const struct tegra_pmc_soc tegra114_pmc_soc = {
-+ .num_powergates = ARRAY_SIZE(tegra114_powergates),
-+ .powergates = tegra114_powergates,
-+ .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates),
-+ .cpu_powergates = tegra114_cpu_powergates,
-+};
-+
-+static const char * const tegra124_powergates[] = {
-+ [TEGRA_POWERGATE_CPU] = "crail",
-+ [TEGRA_POWERGATE_3D] = "3d",
-+ [TEGRA_POWERGATE_VENC] = "venc",
-+ [TEGRA_POWERGATE_PCIE] = "pcie",
-+ [TEGRA_POWERGATE_VDEC] = "vdec",
-+ [TEGRA_POWERGATE_L2] = "l2",
-+ [TEGRA_POWERGATE_MPE] = "mpe",
-+ [TEGRA_POWERGATE_HEG] = "heg",
-+ [TEGRA_POWERGATE_SATA] = "sata",
-+ [TEGRA_POWERGATE_CPU1] = "cpu1",
-+ [TEGRA_POWERGATE_CPU2] = "cpu2",
-+ [TEGRA_POWERGATE_CPU3] = "cpu3",
-+ [TEGRA_POWERGATE_CELP] = "celp",
-+ [TEGRA_POWERGATE_CPU0] = "cpu0",
-+ [TEGRA_POWERGATE_C0NC] = "c0nc",
-+ [TEGRA_POWERGATE_C1NC] = "c1nc",
-+ [TEGRA_POWERGATE_SOR] = "sor",
-+ [TEGRA_POWERGATE_DIS] = "dis",
-+ [TEGRA_POWERGATE_DISB] = "disb",
-+ [TEGRA_POWERGATE_XUSBA] = "xusba",
-+ [TEGRA_POWERGATE_XUSBB] = "xusbb",
-+ [TEGRA_POWERGATE_XUSBC] = "xusbc",
-+ [TEGRA_POWERGATE_VIC] = "vic",
-+ [TEGRA_POWERGATE_IRAM] = "iram",
-+};
-+
-+static const u8 tegra124_cpu_powergates[] = {
-+ TEGRA_POWERGATE_CPU0,
-+ TEGRA_POWERGATE_CPU1,
-+ TEGRA_POWERGATE_CPU2,
-+ TEGRA_POWERGATE_CPU3,
-+};
-+
-+static const struct tegra_pmc_soc tegra124_pmc_soc = {
-+ .num_powergates = ARRAY_SIZE(tegra124_powergates),
-+ .powergates = tegra124_powergates,
-+ .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates),
-+ .cpu_powergates = tegra124_cpu_powergates,
-+};
-+
-+static const struct of_device_id tegra_pmc_match[] = {
-+ { .compatible = "nvidia,tegra124-pmc", .data = &tegra124_pmc_soc },
-+ { .compatible = "nvidia,tegra114-pmc", .data = &tegra114_pmc_soc },
-+ { .compatible = "nvidia,tegra30-pmc", .data = &tegra30_pmc_soc },
-+ { .compatible = "nvidia,tegra20-pmc", .data = &tegra20_pmc_soc },
-+ { }
-+};
-+
-+static struct platform_driver tegra_pmc_driver = {
-+ .driver = {
-+ .name = "tegra-pmc",
-+ .suppress_bind_attrs = true,
-+ .of_match_table = tegra_pmc_match,
-+ .pm = &tegra_pmc_pm_ops,
-+ },
-+ .probe = tegra_pmc_probe,
-+};
-+module_platform_driver(tegra_pmc_driver);
-+
-+/*
-+ * Early initialization to allow access to registers in the very early boot
-+ * process.
-+ */
-+static int __init tegra_pmc_early_init(void)
-+{
-+ const struct of_device_id *match;
-+ struct device_node *np;
-+ struct resource regs;
-+ bool invert;
-+ u32 value;
-+
-+ np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
-+ if (!np) {
-+ pr_warn("PMC device node not found, disabling powergating\n");
-+
-+ regs.start = 0x7000e400;
-+ regs.end = 0x7000e7ff;
-+ regs.flags = IORESOURCE_MEM;
-+
-+ pr_warn("Using memory region %pR\n", &regs);
-+ } else {
-+ pmc->soc = match->data;
-+ }
-+
-+ if (of_address_to_resource(np, 0, &regs) < 0) {
-+ pr_err("failed to get PMC registers\n");
-+ return -ENXIO;
-+ }
-+
-+ pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
-+ if (!pmc->base) {
-+ pr_err("failed to map PMC registers\n");
-+ return -ENXIO;
-+ }
-+
-+ mutex_init(&pmc->powergates_lock);
-+
-+ invert = of_property_read_bool(np, "nvidia,invert-interrupt");
-+
-+ value = tegra_pmc_readl(PMC_CNTRL);
-+
-+ if (invert)
-+ value |= PMC_CNTRL_INTR_POLARITY;
-+ else
-+ value &= ~PMC_CNTRL_INTR_POLARITY;
-+
-+ tegra_pmc_writel(value, PMC_CNTRL);
-+
-+ return 0;
-+}
-+early_initcall(tegra_pmc_early_init);
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
-index 15ac9fc..4482ad8 100644
+index 15ac9fc..5ef5173 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
-@@ -16,40 +16,38 @@
+@@ -16,40 +16,40 @@
*
*/
@@ -5814,10 +4872,12 @@ index 15ac9fc..4482ad8 100644
+#include <linux/serial_8250.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
-+#include <linux/tegra-soc.h>
#include <linux/usb/tegra_usb_phy.h>
-#include <linux/clk/tegra.h>
-#include <linux/irqchip.h>
++
++#include <soc/tegra/fuse.h>
++#include <soc/tegra/pmc.h>
#include <asm/hardware/cache-l2x0.h>
-#include <asm/mach-types.h>
@@ -5838,7 +4898,7 @@ index 15ac9fc..4482ad8 100644
#include "pm.h"
#include "reset.h"
#include "sleep.h"
-@@ -73,16 +71,11 @@ u32 tegra_uart_config[3] = {
+@@ -73,16 +73,11 @@ u32 tegra_uart_config[3] = {
static void __init tegra_init_early(void)
{
of_register_trusted_foundations();
@@ -5855,7 +4915,7 @@ index 15ac9fc..4482ad8 100644
tegra_init_irq();
irqchip_init();
tegra_legacy_irq_syscore_init();
-@@ -94,8 +87,6 @@ static void __init tegra_dt_init(void)
+@@ -94,8 +89,6 @@ static void __init tegra_dt_init(void)
struct soc_device *soc_dev;
struct device *parent = NULL;
@@ -5864,7 +4924,7 @@ index 15ac9fc..4482ad8 100644
tegra_clocks_apply_init_table();
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
-@@ -103,8 +94,9 @@ static void __init tegra_dt_init(void)
+@@ -103,8 +96,9 @@ static void __init tegra_dt_init(void)
goto out;
soc_dev_attr->family = kasprintf(GFP_KERNEL, "Tegra");
@@ -5876,7 +4936,7 @@ index 15ac9fc..4482ad8 100644
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
-@@ -144,7 +136,6 @@ static void __init tegra_dt_init_late(void)
+@@ -144,7 +138,6 @@ static void __init tegra_dt_init_late(void)
tegra_init_suspend();
tegra_cpuidle_init();
@@ -6407,6 +5467,65 @@ index 125cb16..0000000
- pr_info("Tegra30: CPU Speedo ID %d, Soc Speedo ID %d",
- tegra_cpu_speedo_id, tegra_soc_speedo_id);
-}
+diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c
+index 558a239..d8961ef 100644
+--- a/drivers/amba/tegra-ahb.c
++++ b/drivers/amba/tegra-ahb.c
+@@ -25,7 +25,8 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+-#include <linux/tegra-ahb.h>
++
++#include <soc/tegra/ahb.h>
+
+ #define DRV_NAME "tegra-ahb"
+
+diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c
+index 5070153..0aa8830 100644
+--- a/drivers/clk/tegra/clk-periph-gate.c
++++ b/drivers/clk/tegra/clk-periph-gate.c
+@@ -20,7 +20,8 @@
+ #include <linux/io.h>
+ #include <linux/delay.h>
+ #include <linux/err.h>
+-#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
+
+ #include "clk.h"
+
+diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
+index 8b10c38..5bbacd0 100644
+--- a/drivers/clk/tegra/clk-tegra30.c
++++ b/drivers/clk/tegra/clk-tegra30.c
+@@ -22,8 +22,11 @@
+ #include <linux/of.h>
+ #include <linux/of_address.h>
+ #include <linux/clk/tegra.h>
+-#include <linux/tegra-powergate.h>
++
++#include <soc/tegra/pmc.h>
++
+ #include <dt-bindings/clock/tegra30-car.h>
++
+ #include "clk.h"
+ #include "clk-id.h"
+
+diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
+index c0a7d77..f4503ba 100644
+--- a/drivers/clk/tegra/clk.c
++++ b/drivers/clk/tegra/clk.c
+@@ -19,7 +19,8 @@
+ #include <linux/of.h>
+ #include <linux/clk/tegra.h>
+ #include <linux/reset-controller.h>
+-#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
+
+ #include "clk.h"
+
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index d1869f0..d2616ef 100644
--- a/drivers/clocksource/tegra20_timer.c
@@ -6452,6 +5571,48 @@ index d1869f0..d2616ef 100644
ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq);
if (ret) {
pr_err("Failed to register timer IRQ: %d\n", ret);
+diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
+index 30f5ba9..2d07616 100644
+--- a/drivers/gpu/drm/tegra/gr3d.c
++++ b/drivers/gpu/drm/tegra/gr3d.c
+@@ -12,7 +12,8 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/reset.h>
+-#include <linux/tegra-powergate.h>
++
++#include <soc/tegra/pmc.h>
+
+ #include "drm.h"
+ #include "gem.h"
+diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
+index 27c979b..7f8ca5d 100644
+--- a/drivers/gpu/drm/tegra/sor.c
++++ b/drivers/gpu/drm/tegra/sor.c
+@@ -11,7 +11,8 @@
+ #include <linux/io.h>
+ #include <linux/platform_device.h>
+ #include <linux/reset.h>
+-#include <linux/tegra-powergate.h>
++
++#include <soc/tegra/pmc.h>
+
+ #include <drm/drm_dp_helper.h>
+
+diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
+index 605b5b4..230d06c 100644
+--- a/drivers/iommu/tegra-smmu.c
++++ b/drivers/iommu/tegra-smmu.c
+@@ -35,7 +35,8 @@
+ #include <linux/of_iommu.h>
+ #include <linux/debugfs.h>
+ #include <linux/seq_file.h>
+-#include <linux/tegra-ahb.h>
++
++#include <soc/tegra/ahb.h>
+
+ #include <asm/page.h>
+ #include <asm/cacheflush.h>
diff --git a/drivers/misc/fuse/Makefile b/drivers/misc/fuse/Makefile
new file mode 100644
index 0000000..0679c4f
@@ -6460,10 +5621,25 @@ index 0000000..0679c4f
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_TEGRA) += tegra/
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
-index 083cf37..7df5aaf 100644
+index 083cf37..0e2b8cc 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
-@@ -233,7 +233,6 @@ struct tegra_pcie_soc_data {
+@@ -41,11 +41,12 @@
+ #include <linux/reset.h>
+ #include <linux/sizes.h>
+ #include <linux/slab.h>
+-#include <linux/tegra-cpuidle.h>
+-#include <linux/tegra-powergate.h>
+ #include <linux/vmalloc.h>
+ #include <linux/regulator/consumer.h>
+
++#include <soc/tegra/cpuidle.h>
++#include <soc/tegra/pmc.h>
++
+ #include <asm/mach/irq.h>
+ #include <asm/mach/map.h>
+ #include <asm/mach/pci.h>
+@@ -233,7 +234,6 @@ struct tegra_pcie_soc_data {
bool has_pex_clkreq_en;
bool has_pex_bias_ctrl;
bool has_intr_prsnt_sense;
@@ -6471,7 +5647,7 @@ index 083cf37..7df5aaf 100644
bool has_cml_clk;
};
-@@ -272,9 +271,8 @@ struct tegra_pcie {
+@@ -272,9 +272,8 @@ struct tegra_pcie {
unsigned int num_ports;
u32 xbar_config;
@@ -6483,7 +5659,7 @@ index 083cf37..7df5aaf 100644
const struct tegra_pcie_soc_data *soc_data;
};
-@@ -894,7 +892,6 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
+@@ -894,7 +893,6 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)
static void tegra_pcie_power_off(struct tegra_pcie *pcie)
{
@@ -6491,7 +5667,7 @@ index 083cf37..7df5aaf 100644
int err;
/* TODO: disable and unprepare clocks? */
-@@ -905,23 +902,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie)
+@@ -905,23 +903,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie)
tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
@@ -6504,20 +5680,20 @@ index 083cf37..7df5aaf 100644
- }
-
- err = regulator_disable(pcie->pex_clk_supply);
-+ err = regulator_bulk_disable(pcie->num_supplies, pcie->supplies);
- if (err < 0)
+- if (err < 0)
- dev_warn(pcie->dev, "failed to disable pex-clk regulator: %d\n",
- err);
-
- err = regulator_disable(pcie->vdd_supply);
-- if (err < 0)
++ err = regulator_bulk_disable(pcie->num_supplies, pcie->supplies);
+ if (err < 0)
- dev_warn(pcie->dev, "failed to disable VDD regulator: %d\n",
- err);
+ dev_warn(pcie->dev, "failed to disable regulators: %d\n", err);
}
static int tegra_pcie_power_on(struct tegra_pcie *pcie)
-@@ -936,28 +919,9 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
+@@ -936,28 +920,9 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
/* enable regulators */
@@ -6549,11 +5725,71 @@ index 083cf37..7df5aaf 100644
err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
pcie->pex_clk,
-@@ -1394,14 +1358,83 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
+@@ -1394,14 +1359,157 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes,
return -EINVAL;
}
+/*
++ * Check whether a given set of supplies is available in a device tree node.
++ * This is used to check whether the new or the legacy device tree bindings
++ * should be used.
++ */
++static bool of_regulator_bulk_available(struct device_node *np,
++ struct regulator_bulk_data *supplies,
++ unsigned int num_supplies)
++{
++ char property[32];
++ unsigned int i;
++
++ for (i = 0; i < num_supplies; i++) {
++ snprintf(property, 32, "%s-supply", supplies[i].supply);
++
++ if (of_find_property(np, property, NULL) == NULL)
++ return false;
++ }
++
++ return true;
++}
++
++/*
++ * Old versions of the device tree binding for this device used a set of power
++ * supplies that didn't match the hardware inputs. This happened to work for a
++ * number of cases but is not future proof. However to preserve backwards-
++ * compatibility with old device trees, this function will try to use the old
++ * set of supplies.
++ */
++static int tegra_pcie_get_legacy_regulators(struct tegra_pcie *pcie)
++{
++ struct device_node *np = pcie->dev->of_node;
++
++ if (of_device_is_compatible(np, "nvidia,tegra30-pcie"))
++ pcie->num_supplies = 3;
++ else if (of_device_is_compatible(np, "nvidia,tegra20-pcie"))
++ pcie->num_supplies = 2;
++
++ if (pcie->num_supplies == 0) {
++ dev_err(pcie->dev, "device %s not supported in legacy mode\n",
++ np->full_name);
++ return -ENODEV;
++ }
++
++ pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies,
++ sizeof(*pcie->supplies),
++ GFP_KERNEL);
++ if (!pcie->supplies)
++ return -ENOMEM;
++
++ pcie->supplies[0].supply = "pex-clk";
++ pcie->supplies[1].supply = "vdd";
++
++ if (pcie->num_supplies > 2)
++ pcie->supplies[2].supply = "avdd";
++
++ return devm_regulator_bulk_get(pcie->dev, pcie->num_supplies,
++ pcie->supplies);
++}
++
++/*
+ * Obtains the list of regulators required for a particular generation of the
+ * IP block.
+ *
@@ -6617,8 +5853,22 @@ index 083cf37..7df5aaf 100644
+ pcie->supplies[4].supply = "vddio-pex-clk";
+ }
+
-+ return devm_regulator_bulk_get(pcie->dev, pcie->num_supplies,
-+ pcie->supplies);
++ if (of_regulator_bulk_available(pcie->dev->of_node, pcie->supplies,
++ pcie->num_supplies))
++ return devm_regulator_bulk_get(pcie->dev, pcie->num_supplies,
++ pcie->supplies);
++
++ /*
++ * If not all regulators are available for this new scheme, assume
++ * that the device tree complies with an older version of the device
++ * tree binding.
++ */
++ dev_info(pcie->dev, "using legacy DT binding for power supplies\n");
++
++ devm_kfree(pcie->dev, pcie->supplies);
++ pcie->num_supplies = 0;
++
++ return tegra_pcie_get_legacy_regulators(pcie);
+}
+
static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
@@ -6634,7 +5884,7 @@ index 083cf37..7df5aaf 100644
int err;
if (of_pci_range_parser_init(&parser, np)) {
-@@ -1409,20 +1442,6 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
+@@ -1409,20 +1517,6 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
return -EINVAL;
}
@@ -6655,7 +5905,7 @@ index 083cf37..7df5aaf 100644
for_each_of_pci_range(&parser, &range) {
of_pci_range_to_resource(&range, np, &res);
-@@ -1490,8 +1509,13 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
+@@ -1490,8 +1584,13 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
lanes |= value << (index << 3);
@@ -6670,7 +5920,7 @@ index 083cf37..7df5aaf 100644
rp = devm_kzalloc(pcie->dev, sizeof(*rp), GFP_KERNEL);
if (!rp)
-@@ -1522,6 +1546,10 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
+@@ -1522,6 +1621,10 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
return err;
}
@@ -6681,7 +5931,7 @@ index 083cf37..7df5aaf 100644
return 0;
}
-@@ -1615,7 +1643,6 @@ static const struct tegra_pcie_soc_data tegra20_pcie_data = {
+@@ -1615,7 +1718,6 @@ static const struct tegra_pcie_soc_data tegra20_pcie_data = {
.has_pex_clkreq_en = false,
.has_pex_bias_ctrl = false,
.has_intr_prsnt_sense = false,
@@ -6689,7 +5939,7 @@ index 083cf37..7df5aaf 100644
.has_cml_clk = false,
};
-@@ -1627,7 +1654,6 @@ static const struct tegra_pcie_soc_data tegra30_pcie_data = {
+@@ -1627,7 +1729,6 @@ static const struct tegra_pcie_soc_data tegra30_pcie_data = {
.has_pex_clkreq_en = true,
.has_pex_bias_ctrl = true,
.has_intr_prsnt_sense = true,
@@ -7716,11 +6966,50 @@ index 0f7c447..3b1b95d 100644
+obj-$(CONFIG_ARCH_TEGRA) += tegra/
diff --git a/drivers/soc/tegra/Makefile b/drivers/soc/tegra/Makefile
new file mode 100644
-index 0000000..236600f
+index 0000000..cdaad9d
--- /dev/null
+++ b/drivers/soc/tegra/Makefile
-@@ -0,0 +1 @@
+@@ -0,0 +1,4 @@
+obj-$(CONFIG_ARCH_TEGRA) += fuse/
++
++obj-$(CONFIG_ARCH_TEGRA) += common.o
++obj-$(CONFIG_ARCH_TEGRA) += pmc.o
+diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
+new file mode 100644
+index 0000000..a71cb74
+--- /dev/null
++++ b/drivers/soc/tegra/common.c
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/of.h>
++
++#include <soc/tegra/common.h>
++
++static const struct of_device_id tegra_machine_match[] = {
++ { .compatible = "nvidia,tegra20", },
++ { .compatible = "nvidia,tegra30", },
++ { .compatible = "nvidia,tegra114", },
++ { .compatible = "nvidia,tegra124", },
++ { }
++};
++
++bool soc_is_tegra(void)
++{
++ struct device_node *root;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return false;
++
++ return of_match_node(tegra_machine_match, root) != NULL;
++}
diff --git a/drivers/soc/tegra/fuse/Makefile b/drivers/soc/tegra/fuse/Makefile
new file mode 100644
index 0000000..3af357d
@@ -7737,10 +7026,10 @@ index 0000000..3af357d
+obj-$(CONFIG_ARCH_TEGRA_124_SOC) += speedo-tegra124.o
diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
new file mode 100644
-index 0000000..7cf83dd
+index 0000000..11a5043
--- /dev/null
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
-@@ -0,0 +1,158 @@
+@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
+ *
@@ -7765,7 +7054,9 @@ index 0000000..7cf83dd
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/common.h>
++#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
@@ -7872,6 +7163,9 @@ index 0000000..7cf83dd
+ struct device_node *np;
+ void __iomem *car_base;
+
++ if (!soc_is_tegra())
++ return 0;
++
+ tegra_init_apbmisc();
+
+ np = of_find_matching_node(NULL, car_match);
@@ -7901,10 +7195,10 @@ index 0000000..7cf83dd
+early_initcall(tegra_init_fuse);
diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c b/drivers/soc/tegra/fuse/fuse-tegra20.c
new file mode 100644
-index 0000000..c3dcf11
+index 0000000..7cb63ab
--- /dev/null
+++ b/drivers/soc/tegra/fuse/fuse-tegra20.c
-@@ -0,0 +1,214 @@
+@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
+ *
@@ -7935,7 +7229,8 @@ index 0000000..c3dcf11
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
@@ -8121,10 +7416,10 @@ index 0000000..c3dcf11
+}
diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c
new file mode 100644
-index 0000000..a4cfb11
+index 0000000..5999cf3
--- /dev/null
+++ b/drivers/soc/tegra/fuse/fuse-tegra30.c
-@@ -0,0 +1,223 @@
+@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
+ *
@@ -8151,7 +7446,8 @@ index 0000000..a4cfb11
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
@@ -8427,10 +7723,10 @@ index 0000000..3a398bf3
+#endif
diff --git a/drivers/soc/tegra/fuse/speedo-tegra114.c b/drivers/soc/tegra/fuse/speedo-tegra114.c
new file mode 100644
-index 0000000..98d6cde
+index 0000000..2a6ca03
--- /dev/null
+++ b/drivers/soc/tegra/fuse/speedo-tegra114.c
-@@ -0,0 +1,109 @@
+@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
+ *
@@ -8447,10 +7743,11 @@ index 0000000..98d6cde
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
++#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
-+#include <linux/bug.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
@@ -8542,10 +7839,10 @@ index 0000000..98d6cde
+}
diff --git a/drivers/soc/tegra/fuse/speedo-tegra124.c b/drivers/soc/tegra/fuse/speedo-tegra124.c
new file mode 100644
-index 0000000..a15dd53
+index 0000000..4636238
--- /dev/null
+++ b/drivers/soc/tegra/fuse/speedo-tegra124.c
-@@ -0,0 +1,167 @@
+@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
+ *
@@ -8565,7 +7862,8 @@ index 0000000..a15dd53
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
@@ -8715,10 +8013,10 @@ index 0000000..a15dd53
+}
diff --git a/drivers/soc/tegra/fuse/speedo-tegra20.c b/drivers/soc/tegra/fuse/speedo-tegra20.c
new file mode 100644
-index 0000000..c951fa4
+index 0000000..eff1b63
--- /dev/null
+++ b/drivers/soc/tegra/fuse/speedo-tegra20.c
-@@ -0,0 +1,109 @@
+@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
+ *
@@ -8735,10 +8033,11 @@ index 0000000..c951fa4
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
-+#include <linux/kernel.h>
-+#include <linux/device.h>
+#include <linux/bug.h>
-+#include <linux/tegra-soc.h>
++#include <linux/device.h>
++#include <linux/kernel.h>
++
++#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
@@ -8830,10 +8129,10 @@ index 0000000..c951fa4
+}
diff --git a/drivers/soc/tegra/fuse/speedo-tegra30.c b/drivers/soc/tegra/fuse/speedo-tegra30.c
new file mode 100644
-index 0000000..1a85ad8
+index 0000000..b17f0dc
--- /dev/null
+++ b/drivers/soc/tegra/fuse/speedo-tegra30.c
-@@ -0,0 +1,287 @@
+@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
+ *
@@ -8850,10 +8149,11 @@ index 0000000..1a85ad8
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
++#include <linux/bug.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
-+#include <linux/bug.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
@@ -9123,10 +8423,10 @@ index 0000000..1a85ad8
+}
diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
new file mode 100644
-index 0000000..30126e6
+index 0000000..3bf5aba
--- /dev/null
+++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
-@@ -0,0 +1,114 @@
+@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
@@ -9148,7 +8448,8 @@ index 0000000..30126e6
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
-+#include <linux/tegra-soc.h>
++
++#include <soc/tegra/fuse.h>
+
+#include "fuse.h"
+
@@ -9241,6 +8542,969 @@ index 0000000..30126e6
+ if (!strapping_base)
+ pr_err("ioremap tegra strapping_base failed\n");
+}
+diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
+new file mode 100644
+index 0000000..a2c0ceb
+--- /dev/null
++++ b/drivers/soc/tegra/pmc.c
+@@ -0,0 +1,957 @@
++/*
++ * drivers/soc/tegra/pmc.c
++ *
++ * Copyright (c) 2010 Google, Inc
++ *
++ * Author:
++ * Colin Cross <ccross@google.com>
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/clk.h>
++#include <linux/clk/tegra.h>
++#include <linux/debugfs.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/export.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/platform_device.h>
++#include <linux/reboot.h>
++#include <linux/reset.h>
++#include <linux/seq_file.h>
++#include <linux/spinlock.h>
++
++#include <soc/tegra/common.h>
++#include <soc/tegra/fuse.h>
++#include <soc/tegra/pmc.h>
++
++#define PMC_CNTRL 0x0
++#define PMC_CNTRL_SYSCLK_POLARITY (1 << 10) /* sys clk polarity */
++#define PMC_CNTRL_SYSCLK_OE (1 << 11) /* system clock enable */
++#define PMC_CNTRL_SIDE_EFFECT_LP0 (1 << 14) /* LP0 when CPU pwr gated */
++#define PMC_CNTRL_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */
++#define PMC_CNTRL_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
++#define PMC_CNTRL_INTR_POLARITY (1 << 17) /* inverts INTR polarity */
++
++#define DPD_SAMPLE 0x020
++#define DPD_SAMPLE_ENABLE (1 << 0)
++#define DPD_SAMPLE_DISABLE (0 << 0)
++
++#define PWRGATE_TOGGLE 0x30
++#define PWRGATE_TOGGLE_START (1 << 8)
++
++#define REMOVE_CLAMPING 0x34
++
++#define PWRGATE_STATUS 0x38
++
++#define PMC_SCRATCH0 0x50
++#define PMC_SCRATCH0_MODE_RECOVERY (1 << 31)
++#define PMC_SCRATCH0_MODE_BOOTLOADER (1 << 30)
++#define PMC_SCRATCH0_MODE_RCM (1 << 1)
++#define PMC_SCRATCH0_MODE_MASK (PMC_SCRATCH0_MODE_RECOVERY | \
++ PMC_SCRATCH0_MODE_BOOTLOADER | \
++ PMC_SCRATCH0_MODE_RCM)
++
++#define PMC_CPUPWRGOOD_TIMER 0xc8
++#define PMC_CPUPWROFF_TIMER 0xcc
++
++#define PMC_SCRATCH41 0x140
++
++#define IO_DPD_REQ 0x1b8
++#define IO_DPD_REQ_CODE_IDLE (0 << 30)
++#define IO_DPD_REQ_CODE_OFF (1 << 30)
++#define IO_DPD_REQ_CODE_ON (2 << 30)
++#define IO_DPD_REQ_CODE_MASK (3 << 30)
++
++#define IO_DPD_STATUS 0x1bc
++#define IO_DPD2_REQ 0x1c0
++#define IO_DPD2_STATUS 0x1c4
++#define SEL_DPD_TIM 0x1c8
++
++#define GPU_RG_CNTRL 0x2d4
++
++struct tegra_pmc_soc {
++ unsigned int num_powergates;
++ const char *const *powergates;
++ unsigned int num_cpu_powergates;
++ const u8 *cpu_powergates;
++};
++
++/**
++ * struct tegra_pmc - NVIDIA Tegra PMC
++ * @base: pointer to I/O remapped register region
++ * @clk: pointer to pclk clock
++ * @rate: currently configured rate of pclk
++ * @suspend_mode: lowest suspend mode available
++ * @cpu_good_time: CPU power good time (in microseconds)
++ * @cpu_off_time: CPU power off time (in microsecends)
++ * @core_osc_time: core power good OSC time (in microseconds)
++ * @core_pmu_time: core power good PMU time (in microseconds)
++ * @core_off_time: core power off time (in microseconds)
++ * @corereq_high: core power request is active-high
++ * @sysclkreq_high: system clock request is active-high
++ * @combined_req: combined power request for CPU & core
++ * @cpu_pwr_good_en: CPU power good signal is enabled
++ * @lp0_vec_phys: physical base address of the LP0 warm boot code
++ * @lp0_vec_size: size of the LP0 warm boot code
++ * @powergates_lock: mutex for power gate register access
++ */
++struct tegra_pmc {
++ void __iomem *base;
++ struct clk *clk;
++
++ const struct tegra_pmc_soc *soc;
++
++ unsigned long rate;
++
++ enum tegra_suspend_mode suspend_mode;
++ u32 cpu_good_time;
++ u32 cpu_off_time;
++ u32 core_osc_time;
++ u32 core_pmu_time;
++ u32 core_off_time;
++ bool corereq_high;
++ bool sysclkreq_high;
++ bool combined_req;
++ bool cpu_pwr_good_en;
++ u32 lp0_vec_phys;
++ u32 lp0_vec_size;
++
++ struct mutex powergates_lock;
++};
++
++static struct tegra_pmc *pmc = &(struct tegra_pmc) {
++ .base = NULL,
++ .suspend_mode = TEGRA_SUSPEND_NONE,
++};
++
++static u32 tegra_pmc_readl(unsigned long offset)
++{
++ return readl(pmc->base + offset);
++}
++
++static void tegra_pmc_writel(u32 value, unsigned long offset)
++{
++ writel(value, pmc->base + offset);
++}
++
++/**
++ * tegra_powergate_set() - set the state of a partition
++ * @id: partition ID
++ * @new_state: new state of the partition
++ */
++static int tegra_powergate_set(int id, bool new_state)
++{
++ bool status;
++
++ mutex_lock(&pmc->powergates_lock);
++
++ status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
++
++ if (status == new_state) {
++ mutex_unlock(&pmc->powergates_lock);
++ return 0;
++ }
++
++ tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
++
++ mutex_unlock(&pmc->powergates_lock);
++
++ return 0;
++}
++
++/**
++ * tegra_powergate_power_on() - power on partition
++ * @id: partition ID
++ */
++int tegra_powergate_power_on(int id)
++{
++ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
++ return -EINVAL;
++
++ return tegra_powergate_set(id, true);
++}
++
++/**
++ * tegra_powergate_power_off() - power off partition
++ * @id: partition ID
++ */
++int tegra_powergate_power_off(int id)
++{
++ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
++ return -EINVAL;
++
++ return tegra_powergate_set(id, false);
++}
++EXPORT_SYMBOL(tegra_powergate_power_off);
++
++/**
++ * tegra_powergate_is_powered() - check if partition is powered
++ * @id: partition ID
++ */
++int tegra_powergate_is_powered(int id)
++{
++ u32 status;
++
++ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
++ return -EINVAL;
++
++ status = tegra_pmc_readl(PWRGATE_STATUS) & (1 << id);
++ return !!status;
++}
++
++/**
++ * tegra_powergate_remove_clamping() - remove power clamps for partition
++ * @id: partition ID
++ */
++int tegra_powergate_remove_clamping(int id)
++{
++ u32 mask;
++
++ if (!pmc->soc || id < 0 || id >= pmc->soc->num_powergates)
++ return -EINVAL;
++
++ /*
++ * The Tegra124 GPU has a separate register (with different semantics)
++ * to remove clamps.
++ */
++ if (tegra_get_chip_id() == TEGRA124) {
++ if (id == TEGRA_POWERGATE_3D) {
++ tegra_pmc_writel(0, GPU_RG_CNTRL);
++ return 0;
++ }
++ }
++
++ /*
++ * Tegra 2 has a bug where PCIE and VDE clamping masks are
++ * swapped relatively to the partition ids
++ */
++ if (id == TEGRA_POWERGATE_VDEC)
++ mask = (1 << TEGRA_POWERGATE_PCIE);
++ else if (id == TEGRA_POWERGATE_PCIE)
++ mask = (1 << TEGRA_POWERGATE_VDEC);
++ else
++ mask = (1 << id);
++
++ tegra_pmc_writel(mask, REMOVE_CLAMPING);
++
++ return 0;
++}
++EXPORT_SYMBOL(tegra_powergate_remove_clamping);
++
++/**
++ * tegra_powergate_sequence_power_up() - power up partition
++ * @id: partition ID
++ * @clk: clock for partition
++ * @rst: reset for partition
++ *
++ * Must be called with clk disabled, and returns with clk enabled.
++ */
++int tegra_powergate_sequence_power_up(int id, struct clk *clk,
++ struct reset_control *rst)
++{
++ int ret;
++
++ reset_control_assert(rst);
++
++ ret = tegra_powergate_power_on(id);
++ if (ret)
++ goto err_power;
++
++ ret = clk_prepare_enable(clk);
++ if (ret)
++ goto err_clk;
++
++ usleep_range(10, 20);
++
++ ret = tegra_powergate_remove_clamping(id);
++ if (ret)
++ goto err_clamp;
++
++ usleep_range(10, 20);
++ reset_control_deassert(rst);
++
++ return 0;
++
++err_clamp:
++ clk_disable_unprepare(clk);
++err_clk:
++ tegra_powergate_power_off(id);
++err_power:
++ return ret;
++}
++EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
++
++#ifdef CONFIG_SMP
++/**
++ * tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
++ * @cpuid: CPU partition ID
++ *
++ * Returns the partition ID corresponding to the CPU partition ID or a
++ * negative error code on failure.
++ */
++static int tegra_get_cpu_powergate_id(int cpuid)
++{
++ if (pmc->soc && cpuid > 0 && cpuid < pmc->soc->num_cpu_powergates)
++ return pmc->soc->cpu_powergates[cpuid];
++
++ return -EINVAL;
++}
++
++/**
++ * tegra_pmc_cpu_is_powered() - check if CPU partition is powered
++ * @cpuid: CPU partition ID
++ */
++bool tegra_pmc_cpu_is_powered(int cpuid)
++{
++ int id;
++
++ id = tegra_get_cpu_powergate_id(cpuid);
++ if (id < 0)
++ return false;
++
++ return tegra_powergate_is_powered(id);
++}
++
++/**
++ * tegra_pmc_cpu_power_on() - power on CPU partition
++ * @cpuid: CPU partition ID
++ */
++int tegra_pmc_cpu_power_on(int cpuid)
++{
++ int id;
++
++ id = tegra_get_cpu_powergate_id(cpuid);
++ if (id < 0)
++ return id;
++
++ return tegra_powergate_set(id, true);
++}
++
++/**
++ * tegra_pmc_cpu_remove_clamping() - remove power clamps for CPU partition
++ * @cpuid: CPU partition ID
++ */
++int tegra_pmc_cpu_remove_clamping(int cpuid)
++{
++ int id;
++
++ id = tegra_get_cpu_powergate_id(cpuid);
++ if (id < 0)
++ return id;
++
++ return tegra_powergate_remove_clamping(id);
++}
++#endif /* CONFIG_SMP */
++
++/**
++ * tegra_pmc_restart() - reboot the system
++ * @mode: which mode to reboot in
++ * @cmd: reboot command
++ */
++void tegra_pmc_restart(enum reboot_mode mode, const char *cmd)
++{
++ u32 value;
++
++ value = tegra_pmc_readl(PMC_SCRATCH0);
++ value &= ~PMC_SCRATCH0_MODE_MASK;
++
++ if (cmd) {
++ if (strcmp(cmd, "recovery") == 0)
++ value |= PMC_SCRATCH0_MODE_RECOVERY;
++
++ if (strcmp(cmd, "bootloader") == 0)
++ value |= PMC_SCRATCH0_MODE_BOOTLOADER;
++
++ if (strcmp(cmd, "forced-recovery") == 0)
++ value |= PMC_SCRATCH0_MODE_RCM;
++ }
++
++ tegra_pmc_writel(value, PMC_SCRATCH0);
++
++ value = tegra_pmc_readl(0);
++ value |= 0x10;
++ tegra_pmc_writel(value, 0);
++}
++
++static int powergate_show(struct seq_file *s, void *data)
++{
++ unsigned int i;
++
++ seq_printf(s, " powergate powered\n");
++ seq_printf(s, "------------------\n");
++
++ for (i = 0; i < pmc->soc->num_powergates; i++) {
++ if (!pmc->soc->powergates[i])
++ continue;
++
++ seq_printf(s, " %9s %7s\n", pmc->soc->powergates[i],
++ tegra_powergate_is_powered(i) ? "yes" : "no");
++ }
++
++ return 0;
++}
++
++static int powergate_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, powergate_show, inode->i_private);
++}
++
++static const struct file_operations powergate_fops = {
++ .open = powergate_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int tegra_powergate_debugfs_init(void)
++{
++ struct dentry *d;
++
++ d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
++ &powergate_fops);
++ if (!d)
++ return -ENOMEM;
++
++ return 0;
++}
++
++static int tegra_io_rail_prepare(int id, unsigned long *request,
++ unsigned long *status, unsigned int *bit)
++{
++ unsigned long rate, value;
++ struct clk *clk;
++
++ *bit = id % 32;
++
++ /*
++ * There are two sets of 30 bits to select IO rails, but bits 30 and
++ * 31 are control bits rather than IO rail selection bits.
++ */
++ if (id > 63 || *bit == 30 || *bit == 31)
++ return -EINVAL;
++
++ if (id < 32) {
++ *status = IO_DPD_STATUS;
++ *request = IO_DPD_REQ;
++ } else {
++ *status = IO_DPD2_STATUS;
++ *request = IO_DPD2_REQ;
++ }
++
++ clk = clk_get_sys(NULL, "pclk");
++ if (IS_ERR(clk))
++ return PTR_ERR(clk);
++
++ rate = clk_get_rate(clk);
++ clk_put(clk);
++
++ tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
++
++ /* must be at least 200 ns, in APB (PCLK) clock cycles */
++ value = DIV_ROUND_UP(1000000000, rate);
++ value = DIV_ROUND_UP(200, value);
++ tegra_pmc_writel(value, SEL_DPD_TIM);
++
++ return 0;
++}
++
++static int tegra_io_rail_poll(unsigned long offset, unsigned long mask,
++ unsigned long val, unsigned long timeout)
++{
++ unsigned long value;
++
++ timeout = jiffies + msecs_to_jiffies(timeout);
++
++ while (time_after(timeout, jiffies)) {
++ value = tegra_pmc_readl(offset);
++ if ((value & mask) == val)
++ return 0;
++
++ usleep_range(250, 1000);
++ }
++
++ return -ETIMEDOUT;
++}
++
++static void tegra_io_rail_unprepare(void)
++{
++ tegra_pmc_writel(DPD_SAMPLE_DISABLE, DPD_SAMPLE);
++}
++
++int tegra_io_rail_power_on(int id)
++{
++ unsigned long request, status, value;
++ unsigned int bit, mask;
++ int err;
++
++ err = tegra_io_rail_prepare(id, &request, &status, &bit);
++ if (err < 0)
++ return err;
++
++ mask = 1 << bit;
++
++ value = tegra_pmc_readl(request);
++ value |= mask;
++ value &= ~IO_DPD_REQ_CODE_MASK;
++ value |= IO_DPD_REQ_CODE_OFF;
++ tegra_pmc_writel(value, request);
++
++ err = tegra_io_rail_poll(status, mask, 0, 250);
++ if (err < 0)
++ return err;
++
++ tegra_io_rail_unprepare();
++
++ return 0;
++}
++EXPORT_SYMBOL(tegra_io_rail_power_on);
++
++int tegra_io_rail_power_off(int id)
++{
++ unsigned long request, status, value;
++ unsigned int bit, mask;
++ int err;
++
++ err = tegra_io_rail_prepare(id, &request, &status, &bit);
++ if (err < 0)
++ return err;
++
++ mask = 1 << bit;
++
++ value = tegra_pmc_readl(request);
++ value |= mask;
++ value &= ~IO_DPD_REQ_CODE_MASK;
++ value |= IO_DPD_REQ_CODE_ON;
++ tegra_pmc_writel(value, request);
++
++ err = tegra_io_rail_poll(status, mask, mask, 250);
++ if (err < 0)
++ return err;
++
++ tegra_io_rail_unprepare();
++
++ return 0;
++}
++EXPORT_SYMBOL(tegra_io_rail_power_off);
++
++#ifdef CONFIG_PM_SLEEP
++enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
++{
++ return pmc->suspend_mode;
++}
++
++void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
++{
++ if (mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)
++ return;
++
++ pmc->suspend_mode = mode;
++}
++
++void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
++{
++ unsigned long long rate = 0;
++ u32 value;
++
++ switch (mode) {
++ case TEGRA_SUSPEND_LP1:
++ rate = 32768;
++ break;
++
++ case TEGRA_SUSPEND_LP2:
++ rate = clk_get_rate(pmc->clk);
++ break;
++
++ default:
++ break;
++ }
++
++ if (WARN_ON_ONCE(rate == 0))
++ rate = 100000000;
++
++ if (rate != pmc->rate) {
++ u64 ticks;
++
++ ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1;
++ do_div(ticks, USEC_PER_SEC);
++ tegra_pmc_writel(ticks, PMC_CPUPWRGOOD_TIMER);
++
++ ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1;
++ do_div(ticks, USEC_PER_SEC);
++ tegra_pmc_writel(ticks, PMC_CPUPWROFF_TIMER);
++
++ wmb();
++
++ pmc->rate = rate;
++ }
++
++ value = tegra_pmc_readl(PMC_CNTRL);
++ value &= ~PMC_CNTRL_SIDE_EFFECT_LP0;
++ value |= PMC_CNTRL_CPU_PWRREQ_OE;
++ tegra_pmc_writel(value, PMC_CNTRL);
++}
++#endif
++
++static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np)
++{
++ u32 value, values[2];
++
++ if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) {
++ } else {
++ switch (value) {
++ case 0:
++ pmc->suspend_mode = TEGRA_SUSPEND_LP0;
++ break;
++
++ case 1:
++ pmc->suspend_mode = TEGRA_SUSPEND_LP1;
++ break;
++
++ case 2:
++ pmc->suspend_mode = TEGRA_SUSPEND_LP2;
++ break;
++
++ default:
++ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
++ break;
++ }
++ }
++
++ pmc->suspend_mode = tegra_pm_validate_suspend_mode(pmc->suspend_mode);
++
++ if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &value))
++ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
++
++ pmc->cpu_good_time = value;
++
++ if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &value))
++ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
++
++ pmc->cpu_off_time = value;
++
++ if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
++ values, ARRAY_SIZE(values)))
++ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
++
++ pmc->core_osc_time = values[0];
++ pmc->core_pmu_time = values[1];
++
++ if (of_property_read_u32(np, "nvidia,core-pwr-off-time", &value))
++ pmc->suspend_mode = TEGRA_SUSPEND_NONE;
++
++ pmc->core_off_time = value;
++
++ pmc->corereq_high = of_property_read_bool(np,
++ "nvidia,core-power-req-active-high");
++
++ pmc->sysclkreq_high = of_property_read_bool(np,
++ "nvidia,sys-clock-req-active-high");
++
++ pmc->combined_req = of_property_read_bool(np,
++ "nvidia,combined-power-req");
++
++ pmc->cpu_pwr_good_en = of_property_read_bool(np,
++ "nvidia,cpu-pwr-good-en");
++
++ if (of_property_read_u32_array(np, "nvidia,lp0-vec", values,
++ ARRAY_SIZE(values)))
++ if (pmc->suspend_mode == TEGRA_SUSPEND_LP0)
++ pmc->suspend_mode = TEGRA_SUSPEND_LP1;
++
++ pmc->lp0_vec_phys = values[0];
++ pmc->lp0_vec_size = values[1];
++
++ return 0;
++}
++
++static void tegra_pmc_init(struct tegra_pmc *pmc)
++{
++ u32 value;
++
++ /* Always enable CPU power request */
++ value = tegra_pmc_readl(PMC_CNTRL);
++ value |= PMC_CNTRL_CPU_PWRREQ_OE;
++ tegra_pmc_writel(value, PMC_CNTRL);
++
++ value = tegra_pmc_readl(PMC_CNTRL);
++
++ if (pmc->sysclkreq_high)
++ value &= ~PMC_CNTRL_SYSCLK_POLARITY;
++ else
++ value |= PMC_CNTRL_SYSCLK_POLARITY;
++
++ /* configure the output polarity while the request is tristated */
++ tegra_pmc_writel(value, PMC_CNTRL);
++
++ /* now enable the request */
++ value = tegra_pmc_readl(PMC_CNTRL);
++ value |= PMC_CNTRL_SYSCLK_OE;
++ tegra_pmc_writel(value, PMC_CNTRL);
++}
++
++static int tegra_pmc_probe(struct platform_device *pdev)
++{
++ void __iomem *base = pmc->base;
++ struct resource *res;
++ int err;
++
++ err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node);
++ if (err < 0)
++ return err;
++
++ /* take over the memory region from the early initialization */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ pmc->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(pmc->base))
++ return PTR_ERR(pmc->base);
++
++ iounmap(base);
++
++ pmc->clk = devm_clk_get(&pdev->dev, "pclk");
++ if (IS_ERR(pmc->clk)) {
++ err = PTR_ERR(pmc->clk);
++ dev_err(&pdev->dev, "failed to get pclk: %d\n", err);
++ return err;
++ }
++
++ tegra_pmc_init(pmc);
++
++ if (IS_ENABLED(CONFIG_DEBUG_FS)) {
++ err = tegra_powergate_debugfs_init();
++ if (err < 0)
++ return err;
++ }
++
++ return 0;
++}
++
++#ifdef CONFIG_PM_SLEEP
++static int tegra_pmc_suspend(struct device *dev)
++{
++ tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
++
++ return 0;
++}
++
++static int tegra_pmc_resume(struct device *dev)
++{
++ tegra_pmc_writel(0x0, PMC_SCRATCH41);
++
++ return 0;
++}
++#endif
++
++static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume);
++
++static const char * const tegra20_powergates[] = {
++ [TEGRA_POWERGATE_CPU] = "cpu",
++ [TEGRA_POWERGATE_3D] = "3d",
++ [TEGRA_POWERGATE_VENC] = "venc",
++ [TEGRA_POWERGATE_VDEC] = "vdec",
++ [TEGRA_POWERGATE_PCIE] = "pcie",
++ [TEGRA_POWERGATE_L2] = "l2",
++ [TEGRA_POWERGATE_MPE] = "mpe",
++};
++
++static const struct tegra_pmc_soc tegra20_pmc_soc = {
++ .num_powergates = ARRAY_SIZE(tegra20_powergates),
++ .powergates = tegra20_powergates,
++ .num_cpu_powergates = 0,
++ .cpu_powergates = NULL,
++};
++
++static const char * const tegra30_powergates[] = {
++ [TEGRA_POWERGATE_CPU] = "cpu0",
++ [TEGRA_POWERGATE_3D] = "3d0",
++ [TEGRA_POWERGATE_VENC] = "venc",
++ [TEGRA_POWERGATE_VDEC] = "vdec",
++ [TEGRA_POWERGATE_PCIE] = "pcie",
++ [TEGRA_POWERGATE_L2] = "l2",
++ [TEGRA_POWERGATE_MPE] = "mpe",
++ [TEGRA_POWERGATE_HEG] = "heg",
++ [TEGRA_POWERGATE_SATA] = "sata",
++ [TEGRA_POWERGATE_CPU1] = "cpu1",
++ [TEGRA_POWERGATE_CPU2] = "cpu2",
++ [TEGRA_POWERGATE_CPU3] = "cpu3",
++ [TEGRA_POWERGATE_CELP] = "celp",
++ [TEGRA_POWERGATE_3D1] = "3d1",
++};
++
++static const u8 tegra30_cpu_powergates[] = {
++ TEGRA_POWERGATE_CPU,
++ TEGRA_POWERGATE_CPU1,
++ TEGRA_POWERGATE_CPU2,
++ TEGRA_POWERGATE_CPU3,
++};
++
++static const struct tegra_pmc_soc tegra30_pmc_soc = {
++ .num_powergates = ARRAY_SIZE(tegra30_powergates),
++ .powergates = tegra30_powergates,
++ .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
++ .cpu_powergates = tegra30_cpu_powergates,
++};
++
++static const char * const tegra114_powergates[] = {
++ [TEGRA_POWERGATE_CPU] = "crail",
++ [TEGRA_POWERGATE_3D] = "3d",
++ [TEGRA_POWERGATE_VENC] = "venc",
++ [TEGRA_POWERGATE_VDEC] = "vdec",
++ [TEGRA_POWERGATE_MPE] = "mpe",
++ [TEGRA_POWERGATE_HEG] = "heg",
++ [TEGRA_POWERGATE_CPU1] = "cpu1",
++ [TEGRA_POWERGATE_CPU2] = "cpu2",
++ [TEGRA_POWERGATE_CPU3] = "cpu3",
++ [TEGRA_POWERGATE_CELP] = "celp",
++ [TEGRA_POWERGATE_CPU0] = "cpu0",
++ [TEGRA_POWERGATE_C0NC] = "c0nc",
++ [TEGRA_POWERGATE_C1NC] = "c1nc",
++ [TEGRA_POWERGATE_DIS] = "dis",
++ [TEGRA_POWERGATE_DISB] = "disb",
++ [TEGRA_POWERGATE_XUSBA] = "xusba",
++ [TEGRA_POWERGATE_XUSBB] = "xusbb",
++ [TEGRA_POWERGATE_XUSBC] = "xusbc",
++};
++
++static const u8 tegra114_cpu_powergates[] = {
++ TEGRA_POWERGATE_CPU0,
++ TEGRA_POWERGATE_CPU1,
++ TEGRA_POWERGATE_CPU2,
++ TEGRA_POWERGATE_CPU3,
++};
++
++static const struct tegra_pmc_soc tegra114_pmc_soc = {
++ .num_powergates = ARRAY_SIZE(tegra114_powergates),
++ .powergates = tegra114_powergates,
++ .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates),
++ .cpu_powergates = tegra114_cpu_powergates,
++};
++
++static const char * const tegra124_powergates[] = {
++ [TEGRA_POWERGATE_CPU] = "crail",
++ [TEGRA_POWERGATE_3D] = "3d",
++ [TEGRA_POWERGATE_VENC] = "venc",
++ [TEGRA_POWERGATE_PCIE] = "pcie",
++ [TEGRA_POWERGATE_VDEC] = "vdec",
++ [TEGRA_POWERGATE_L2] = "l2",
++ [TEGRA_POWERGATE_MPE] = "mpe",
++ [TEGRA_POWERGATE_HEG] = "heg",
++ [TEGRA_POWERGATE_SATA] = "sata",
++ [TEGRA_POWERGATE_CPU1] = "cpu1",
++ [TEGRA_POWERGATE_CPU2] = "cpu2",
++ [TEGRA_POWERGATE_CPU3] = "cpu3",
++ [TEGRA_POWERGATE_CELP] = "celp",
++ [TEGRA_POWERGATE_CPU0] = "cpu0",
++ [TEGRA_POWERGATE_C0NC] = "c0nc",
++ [TEGRA_POWERGATE_C1NC] = "c1nc",
++ [TEGRA_POWERGATE_SOR] = "sor",
++ [TEGRA_POWERGATE_DIS] = "dis",
++ [TEGRA_POWERGATE_DISB] = "disb",
++ [TEGRA_POWERGATE_XUSBA] = "xusba",
++ [TEGRA_POWERGATE_XUSBB] = "xusbb",
++ [TEGRA_POWERGATE_XUSBC] = "xusbc",
++ [TEGRA_POWERGATE_VIC] = "vic",
++ [TEGRA_POWERGATE_IRAM] = "iram",
++};
++
++static const u8 tegra124_cpu_powergates[] = {
++ TEGRA_POWERGATE_CPU0,
++ TEGRA_POWERGATE_CPU1,
++ TEGRA_POWERGATE_CPU2,
++ TEGRA_POWERGATE_CPU3,
++};
++
++static const struct tegra_pmc_soc tegra124_pmc_soc = {
++ .num_powergates = ARRAY_SIZE(tegra124_powergates),
++ .powergates = tegra124_powergates,
++ .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates),
++ .cpu_powergates = tegra124_cpu_powergates,
++};
++
++static const struct of_device_id tegra_pmc_match[] = {
++ { .compatible = "nvidia,tegra124-pmc", .data = &tegra124_pmc_soc },
++ { .compatible = "nvidia,tegra114-pmc", .data = &tegra114_pmc_soc },
++ { .compatible = "nvidia,tegra30-pmc", .data = &tegra30_pmc_soc },
++ { .compatible = "nvidia,tegra20-pmc", .data = &tegra20_pmc_soc },
++ { }
++};
++
++static struct platform_driver tegra_pmc_driver = {
++ .driver = {
++ .name = "tegra-pmc",
++ .suppress_bind_attrs = true,
++ .of_match_table = tegra_pmc_match,
++ .pm = &tegra_pmc_pm_ops,
++ },
++ .probe = tegra_pmc_probe,
++};
++module_platform_driver(tegra_pmc_driver);
++
++/*
++ * Early initialization to allow access to registers in the very early boot
++ * process.
++ */
++static int __init tegra_pmc_early_init(void)
++{
++ const struct of_device_id *match;
++ struct device_node *np;
++ struct resource regs;
++ bool invert;
++ u32 value;
++
++ if (!soc_is_tegra())
++ return 0;
++
++ np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
++ if (!np) {
++ pr_warn("PMC device node not found, disabling powergating\n");
++
++ regs.start = 0x7000e400;
++ regs.end = 0x7000e7ff;
++ regs.flags = IORESOURCE_MEM;
++
++ pr_warn("Using memory region %pR\n", &regs);
++ } else {
++ pmc->soc = match->data;
++ }
++
++ if (of_address_to_resource(np, 0, &regs) < 0) {
++ pr_err("failed to get PMC registers\n");
++ return -ENXIO;
++ }
++
++ pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
++ if (!pmc->base) {
++ pr_err("failed to map PMC registers\n");
++ return -ENXIO;
++ }
++
++ mutex_init(&pmc->powergates_lock);
++
++ invert = of_property_read_bool(np, "nvidia,invert-interrupt");
++
++ value = tegra_pmc_readl(PMC_CNTRL);
++
++ if (invert)
++ value |= PMC_CNTRL_INTR_POLARITY;
++ else
++ value &= ~PMC_CNTRL_INTR_POLARITY;
++
++ tegra_pmc_writel(value, PMC_CNTRL);
++
++ return 0;
++}
++early_initcall(tegra_pmc_early_init);
diff --git a/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
new file mode 100644
index 0000000..914d56d
@@ -9254,14 +9518,331 @@ index 0000000..914d56d
+#define TEGRA_XUSB_PADCTL_SATA 1
+
+#endif /* _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H */
+diff --git a/include/linux/tegra-ahb.h b/include/linux/tegra-ahb.h
+deleted file mode 100644
+index f1cd075..0000000
+--- a/include/linux/tegra-ahb.h
++++ /dev/null
+@@ -1,19 +0,0 @@
+-/*
+- * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- */
+-
+-#ifndef __LINUX_AHB_H__
+-#define __LINUX_AHB_H__
+-
+-extern int tegra_ahb_enable_smmu(struct device_node *ahb);
+-
+-#endif /* __LINUX_AHB_H__ */
+diff --git a/include/linux/tegra-cpuidle.h b/include/linux/tegra-cpuidle.h
+deleted file mode 100644
+index 9c6286b..0000000
+--- a/include/linux/tegra-cpuidle.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/*
+- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- */
+-
+-#ifndef __LINUX_TEGRA_CPUIDLE_H__
+-#define __LINUX_TEGRA_CPUIDLE_H__
+-
+-#ifdef CONFIG_CPU_IDLE
+-void tegra_cpuidle_pcie_irqs_in_use(void);
+-#else
+-static inline void tegra_cpuidle_pcie_irqs_in_use(void)
+-{
+-}
+-#endif
+-
+-#endif
+diff --git a/include/linux/tegra-powergate.h b/include/linux/tegra-powergate.h
+deleted file mode 100644
+index 46f0a07..0000000
+--- a/include/linux/tegra-powergate.h
++++ /dev/null
+@@ -1,134 +0,0 @@
+-/*
+- * Copyright (c) 2010 Google, Inc
+- *
+- * Author:
+- * Colin Cross <ccross@google.com>
+- *
+- * This software is licensed under the terms of the GNU General Public
+- * License version 2, as published by the Free Software Foundation, and
+- * may be copied, distributed, and modified under those terms.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- */
+-
+-#ifndef _MACH_TEGRA_POWERGATE_H_
+-#define _MACH_TEGRA_POWERGATE_H_
+-
+-struct clk;
+-struct reset_control;
+-
+-#define TEGRA_POWERGATE_CPU 0
+-#define TEGRA_POWERGATE_3D 1
+-#define TEGRA_POWERGATE_VENC 2
+-#define TEGRA_POWERGATE_PCIE 3
+-#define TEGRA_POWERGATE_VDEC 4
+-#define TEGRA_POWERGATE_L2 5
+-#define TEGRA_POWERGATE_MPE 6
+-#define TEGRA_POWERGATE_HEG 7
+-#define TEGRA_POWERGATE_SATA 8
+-#define TEGRA_POWERGATE_CPU1 9
+-#define TEGRA_POWERGATE_CPU2 10
+-#define TEGRA_POWERGATE_CPU3 11
+-#define TEGRA_POWERGATE_CELP 12
+-#define TEGRA_POWERGATE_3D1 13
+-#define TEGRA_POWERGATE_CPU0 14
+-#define TEGRA_POWERGATE_C0NC 15
+-#define TEGRA_POWERGATE_C1NC 16
+-#define TEGRA_POWERGATE_SOR 17
+-#define TEGRA_POWERGATE_DIS 18
+-#define TEGRA_POWERGATE_DISB 19
+-#define TEGRA_POWERGATE_XUSBA 20
+-#define TEGRA_POWERGATE_XUSBB 21
+-#define TEGRA_POWERGATE_XUSBC 22
+-#define TEGRA_POWERGATE_VIC 23
+-#define TEGRA_POWERGATE_IRAM 24
+-
+-#define TEGRA_POWERGATE_3D0 TEGRA_POWERGATE_3D
+-
+-#define TEGRA_IO_RAIL_CSIA 0
+-#define TEGRA_IO_RAIL_CSIB 1
+-#define TEGRA_IO_RAIL_DSI 2
+-#define TEGRA_IO_RAIL_MIPI_BIAS 3
+-#define TEGRA_IO_RAIL_PEX_BIAS 4
+-#define TEGRA_IO_RAIL_PEX_CLK1 5
+-#define TEGRA_IO_RAIL_PEX_CLK2 6
+-#define TEGRA_IO_RAIL_USB0 9
+-#define TEGRA_IO_RAIL_USB1 10
+-#define TEGRA_IO_RAIL_USB2 11
+-#define TEGRA_IO_RAIL_USB_BIAS 12
+-#define TEGRA_IO_RAIL_NAND 13
+-#define TEGRA_IO_RAIL_UART 14
+-#define TEGRA_IO_RAIL_BB 15
+-#define TEGRA_IO_RAIL_AUDIO 17
+-#define TEGRA_IO_RAIL_HSIC 19
+-#define TEGRA_IO_RAIL_COMP 22
+-#define TEGRA_IO_RAIL_HDMI 28
+-#define TEGRA_IO_RAIL_PEX_CNTRL 32
+-#define TEGRA_IO_RAIL_SDMMC1 33
+-#define TEGRA_IO_RAIL_SDMMC3 34
+-#define TEGRA_IO_RAIL_SDMMC4 35
+-#define TEGRA_IO_RAIL_CAM 36
+-#define TEGRA_IO_RAIL_RES 37
+-#define TEGRA_IO_RAIL_HV 38
+-#define TEGRA_IO_RAIL_DSIB 39
+-#define TEGRA_IO_RAIL_DSIC 40
+-#define TEGRA_IO_RAIL_DSID 41
+-#define TEGRA_IO_RAIL_CSIE 44
+-#define TEGRA_IO_RAIL_LVDS 57
+-#define TEGRA_IO_RAIL_SYS_DDC 58
+-
+-#ifdef CONFIG_ARCH_TEGRA
+-int tegra_powergate_is_powered(int id);
+-int tegra_powergate_power_on(int id);
+-int tegra_powergate_power_off(int id);
+-int tegra_powergate_remove_clamping(int id);
+-
+-/* Must be called with clk disabled, and returns with clk enabled */
+-int tegra_powergate_sequence_power_up(int id, struct clk *clk,
+- struct reset_control *rst);
+-
+-int tegra_io_rail_power_on(int id);
+-int tegra_io_rail_power_off(int id);
+-#else
+-static inline int tegra_powergate_is_powered(int id)
+-{
+- return -ENOSYS;
+-}
+-
+-static inline int tegra_powergate_power_on(int id)
+-{
+- return -ENOSYS;
+-}
+-
+-static inline int tegra_powergate_power_off(int id)
+-{
+- return -ENOSYS;
+-}
+-
+-static inline int tegra_powergate_remove_clamping(int id)
+-{
+- return -ENOSYS;
+-}
+-
+-static inline int tegra_powergate_sequence_power_up(int id, struct clk *clk,
+- struct reset_control *rst)
+-{
+- return -ENOSYS;
+-}
+-
+-static inline int tegra_io_rail_power_on(int id)
+-{
+- return -ENOSYS;
+-}
+-
+-static inline int tegra_io_rail_power_off(int id)
+-{
+- return -ENOSYS;
+-}
+-#endif
+-
+-#endif /* _MACH_TEGRA_POWERGATE_H_ */
diff --git a/include/linux/tegra-soc.h b/include/linux/tegra-soc.h
-index 95f611d..70a6124 100644
+deleted file mode 100644
+index 95f611d..0000000
--- a/include/linux/tegra-soc.h
-+++ b/include/linux/tegra-soc.h
-@@ -17,6 +17,95 @@
- #ifndef __LINUX_TEGRA_SOC_H_
- #define __LINUX_TEGRA_SOC_H_
-
++++ /dev/null
+@@ -1,22 +0,0 @@
+-/*
+- * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms and conditions of the GNU General Public License,
+- * version 2, as published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope it will be useful, but WITHOUT
+- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+- * more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+- */
+-
+-#ifndef __LINUX_TEGRA_SOC_H_
+-#define __LINUX_TEGRA_SOC_H_
+-
+-u32 tegra_read_chipid(void);
+-
+-#endif /* __LINUX_TEGRA_SOC_H_ */
+diff --git a/include/soc/tegra/ahb.h b/include/soc/tegra/ahb.h
+new file mode 100644
+index 0000000..504eb6f
+--- /dev/null
++++ b/include/soc/tegra/ahb.h
+@@ -0,0 +1,19 @@
++/*
++ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ */
++
++#ifndef __SOC_TEGRA_AHB_H__
++#define __SOC_TEGRA_AHB_H__
++
++extern int tegra_ahb_enable_smmu(struct device_node *ahb);
++
++#endif /* __SOC_TEGRA_AHB_H__ */
+diff --git a/include/soc/tegra/common.h b/include/soc/tegra/common.h
+new file mode 100644
+index 0000000..fc13a9a
+--- /dev/null
++++ b/include/soc/tegra/common.h
+@@ -0,0 +1,14 @@
++/*
++ * Copyright (C) 2014 NVIDIA Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __SOC_TEGRA_COMMON_H__
++#define __SOC_TEGRA_COMMON_H__
++
++bool soc_is_tegra(void);
++
++#endif /* __SOC_TEGRA_COMMON_H__ */
+diff --git a/include/soc/tegra/cpuidle.h b/include/soc/tegra/cpuidle.h
+new file mode 100644
+index 0000000..ea04f42
+--- /dev/null
++++ b/include/soc/tegra/cpuidle.h
+@@ -0,0 +1,25 @@
++/*
++ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ */
++
++#ifndef __SOC_TEGRA_CPUIDLE_H__
++#define __SOC_TEGRA_CPUIDLE_H__
++
++#ifdef CONFIG_CPU_IDLE
++void tegra_cpuidle_pcie_irqs_in_use(void);
++#else
++static inline void tegra_cpuidle_pcie_irqs_in_use(void)
++{
++}
++#endif
++
++#endif /* __SOC_TEGRA_CPUIDLE_H__ */
+diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h
+new file mode 100644
+index 0000000..8e12494
+--- /dev/null
++++ b/include/soc/tegra/fuse.h
+@@ -0,0 +1,65 @@
++/*
++ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __SOC_TEGRA_FUSE_H__
++#define __SOC_TEGRA_FUSE_H__
++
+#define TEGRA20 0x20
+#define TEGRA30 0x30
+#define TEGRA114 0x35
@@ -9272,9 +9853,7 @@ index 95f611d..70a6124 100644
+
+#ifndef __ASSEMBLY__
+
-+#include <linux/reboot.h>
-+
- u32 tegra_read_chipid(void);
++u32 tegra_read_chipid(void);
+u8 tegra_get_chip_id(void);
+
+enum tegra_revision {
@@ -9307,9 +9886,26 @@ index 95f611d..70a6124 100644
+
+extern struct tegra_sku_info tegra_sku_info;
+
++#endif /* __ASSEMBLY__ */
++
++#endif /* __SOC_TEGRA_FUSE_H__ */
+diff --git a/include/soc/tegra/pm.h b/include/soc/tegra/pm.h
+new file mode 100644
+index 0000000..30fe207
+--- /dev/null
++++ b/include/soc/tegra/pm.h
+@@ -0,0 +1,38 @@
+/*
-+ * PMC
++ * Copyright (C) 2014 NVIDIA Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
+ */
++
++#ifndef __SOC_TEGRA_PM_H__
++#define __SOC_TEGRA_PM_H__
++
+enum tegra_suspend_mode {
+ TEGRA_SUSPEND_NONE = 0,
+ TEGRA_SUSPEND_LP2, /* CPU voltage off */
@@ -9319,41 +9915,187 @@ index 95f611d..70a6124 100644
+};
+
+#ifdef CONFIG_PM_SLEEP
++enum tegra_suspend_mode
++tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode);
++
++/* low-level resume entry point */
++void tegra_resume(void);
++#else
++static inline enum tegra_suspend_mode
++tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
++{
++ return TEGRA_SUSPEND_NONE;
++}
++
++static inline void tegra_resume(void)
++{
++}
++#endif /* CONFIG_PM_SLEEP */
++
++#endif /* __SOC_TEGRA_PM_H__ */
+diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h
+new file mode 100644
+index 0000000..65a9327
+--- /dev/null
++++ b/include/soc/tegra/pmc.h
+@@ -0,0 +1,157 @@
++/*
++ * Copyright (c) 2010 Google, Inc
++ * Copyright (c) 2014 NVIDIA Corporation
++ *
++ * Author:
++ * Colin Cross <ccross@google.com>
++ *
++ * This software is licensed under the terms of the GNU General Public
++ * License version 2, as published by the Free Software Foundation, and
++ * may be copied, distributed, and modified under those terms.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ */
++
++#ifndef __SOC_TEGRA_PMC_H__
++#define __SOC_TEGRA_PMC_H__
++
++#include <linux/reboot.h>
++
++#include <soc/tegra/pm.h>
++
++struct clk;
++struct reset_control;
++
++void tegra_pmc_restart(enum reboot_mode mode, const char *cmd);
++
++#ifdef CONFIG_PM_SLEEP
+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
+void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
+void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
++#endif /* CONFIG_PM_SLEEP */
+
++#ifdef CONFIG_SMP
+bool tegra_pmc_cpu_is_powered(int cpuid);
+int tegra_pmc_cpu_power_on(int cpuid);
+int tegra_pmc_cpu_remove_clamping(int cpuid);
-+
-+void tegra_pmc_restart(enum reboot_mode mode, const char *cmd);
-+#endif
++#endif /* CONFIG_SMP */
+
+/*
-+ * PM
++ * powergate and I/O rail APIs
+ */
-+#ifdef CONFIG_PM_SLEEP
-+enum tegra_suspend_mode
-+tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode);
+
-+/* low-level resume entry point */
-+void tegra_resume(void);
++#define TEGRA_POWERGATE_CPU 0
++#define TEGRA_POWERGATE_3D 1
++#define TEGRA_POWERGATE_VENC 2
++#define TEGRA_POWERGATE_PCIE 3
++#define TEGRA_POWERGATE_VDEC 4
++#define TEGRA_POWERGATE_L2 5
++#define TEGRA_POWERGATE_MPE 6
++#define TEGRA_POWERGATE_HEG 7
++#define TEGRA_POWERGATE_SATA 8
++#define TEGRA_POWERGATE_CPU1 9
++#define TEGRA_POWERGATE_CPU2 10
++#define TEGRA_POWERGATE_CPU3 11
++#define TEGRA_POWERGATE_CELP 12
++#define TEGRA_POWERGATE_3D1 13
++#define TEGRA_POWERGATE_CPU0 14
++#define TEGRA_POWERGATE_C0NC 15
++#define TEGRA_POWERGATE_C1NC 16
++#define TEGRA_POWERGATE_SOR 17
++#define TEGRA_POWERGATE_DIS 18
++#define TEGRA_POWERGATE_DISB 19
++#define TEGRA_POWERGATE_XUSBA 20
++#define TEGRA_POWERGATE_XUSBB 21
++#define TEGRA_POWERGATE_XUSBC 22
++#define TEGRA_POWERGATE_VIC 23
++#define TEGRA_POWERGATE_IRAM 24
++
++#define TEGRA_POWERGATE_3D0 TEGRA_POWERGATE_3D
++
++#define TEGRA_IO_RAIL_CSIA 0
++#define TEGRA_IO_RAIL_CSIB 1
++#define TEGRA_IO_RAIL_DSI 2
++#define TEGRA_IO_RAIL_MIPI_BIAS 3
++#define TEGRA_IO_RAIL_PEX_BIAS 4
++#define TEGRA_IO_RAIL_PEX_CLK1 5
++#define TEGRA_IO_RAIL_PEX_CLK2 6
++#define TEGRA_IO_RAIL_USB0 9
++#define TEGRA_IO_RAIL_USB1 10
++#define TEGRA_IO_RAIL_USB2 11
++#define TEGRA_IO_RAIL_USB_BIAS 12
++#define TEGRA_IO_RAIL_NAND 13
++#define TEGRA_IO_RAIL_UART 14
++#define TEGRA_IO_RAIL_BB 15
++#define TEGRA_IO_RAIL_AUDIO 17
++#define TEGRA_IO_RAIL_HSIC 19
++#define TEGRA_IO_RAIL_COMP 22
++#define TEGRA_IO_RAIL_HDMI 28
++#define TEGRA_IO_RAIL_PEX_CNTRL 32
++#define TEGRA_IO_RAIL_SDMMC1 33
++#define TEGRA_IO_RAIL_SDMMC3 34
++#define TEGRA_IO_RAIL_SDMMC4 35
++#define TEGRA_IO_RAIL_CAM 36
++#define TEGRA_IO_RAIL_RES 37
++#define TEGRA_IO_RAIL_HV 38
++#define TEGRA_IO_RAIL_DSIB 39
++#define TEGRA_IO_RAIL_DSIC 40
++#define TEGRA_IO_RAIL_DSID 41
++#define TEGRA_IO_RAIL_CSIE 44
++#define TEGRA_IO_RAIL_LVDS 57
++#define TEGRA_IO_RAIL_SYS_DDC 58
++
++#ifdef CONFIG_ARCH_TEGRA
++int tegra_powergate_is_powered(int id);
++int tegra_powergate_power_on(int id);
++int tegra_powergate_power_off(int id);
++int tegra_powergate_remove_clamping(int id);
++
++/* Must be called with clk disabled, and returns with clk enabled */
++int tegra_powergate_sequence_power_up(int id, struct clk *clk,
++ struct reset_control *rst);
++
++int tegra_io_rail_power_on(int id);
++int tegra_io_rail_power_off(int id);
+#else
-+static inline enum tegra_suspend_mode
-+tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode)
++static inline int tegra_powergate_is_powered(int id)
+{
-+ return TEGRA_SUSPEND_NONE;
++ return -ENOSYS;
+}
+
-+static inline void tegra_resume(void)
++static inline int tegra_powergate_power_on(int id)
+{
++ return -ENOSYS;
+}
-+#endif /* CONFIG_PM_SLEEP */
+
-+#endif /* __ASSEMBLY__ */
-
- #endif /* __LINUX_TEGRA_SOC_H_ */
++static inline int tegra_powergate_power_off(int id)
++{
++ return -ENOSYS;
++}
++
++static inline int tegra_powergate_remove_clamping(int id)
++{
++ return -ENOSYS;
++}
++
++static inline int tegra_powergate_sequence_power_up(int id, struct clk *clk,
++ struct reset_control *rst)
++{
++ return -ENOSYS;
++}
++
++static inline int tegra_io_rail_power_on(int id)
++{
++ return -ENOSYS;
++}
++
++static inline int tegra_io_rail_power_off(int id)
++{
++ return -ENOSYS;
++}
++#endif /* CONFIG_ARCH_TEGRA */
++
++#endif /* __SOC_TEGRA_PMC_H__ */
diff --git a/init/calibrate.c b/init/calibrate.c
index 520702d..ce635dc 100644
--- a/init/calibrate.c