diff options
author | Nicolas Chauvet <kwizart@gmail.com> | 2014-07-21 21:22:15 +0200 |
---|---|---|
committer | Nicolas Chauvet <kwizart@gmail.com> | 2014-08-09 22:11:39 +0200 |
commit | bd19a3898abf2154a55448d07418b8edff094be2 (patch) | |
tree | 6ea6b0694ca9069d56a61f1a5bacccc20195536b | |
parent | 186a708bb62ba479c094d3f2ba5dd5199ebfb657 (diff) | |
download | kernel-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.patch | 2904 |
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", ®s); -+ } else { -+ pmc->soc = match->data; -+ } -+ -+ if (of_address_to_resource(np, 0, ®s) < 0) { -+ pr_err("failed to get PMC registers\n"); -+ return -ENXIO; -+ } -+ -+ pmc->base = ioremap_nocache(regs.start, resource_size(®s)); -+ 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", ®s); ++ } else { ++ pmc->soc = match->data; ++ } ++ ++ if (of_address_to_resource(np, 0, ®s) < 0) { ++ pr_err("failed to get PMC registers\n"); ++ return -ENXIO; ++ } ++ ++ pmc->base = ioremap_nocache(regs.start, resource_size(®s)); ++ 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 |