Commit 7232398a authored by Thierry Reding's avatar Thierry Reding

ARM: tegra: Convert PMC to a driver

This commit converts the PMC support code to a platform driver. Because
the boot process needs to call into this driver very early, also set up
a minimal environment via an early initcall.
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 24fa5af8
...@@ -2,9 +2,7 @@ asflags-y += -march=armv7-a ...@@ -2,9 +2,7 @@ asflags-y += -march=armv7-a
obj-y += io.o obj-y += io.o
obj-y += irq.o obj-y += irq.o
obj-y += pmc.o
obj-y += flowctrl.o obj-y += flowctrl.o
obj-y += powergate.o
obj-y += pm.o obj-y += pm.o
obj-y += reset.o obj-y += reset.o
obj-y += reset-handler.o obj-y += reset-handler.o
......
...@@ -28,13 +28,6 @@ ...@@ -28,13 +28,6 @@
void __init tegra_map_common_io(void); void __init tegra_map_common_io(void);
void __init tegra_init_irq(void); void __init tegra_init_irq(void);
int __init tegra_powergate_init(void);
#if defined(CONFIG_ARCH_TEGRA_2x_SOC) && defined(CONFIG_DEBUG_FS)
int __init tegra_powergate_debugfs_init(void);
#else
static inline int tegra_powergate_debugfs_init(void) { return 0; }
#endif
void __init tegra_paz00_wifikill_init(void); void __init tegra_paz00_wifikill_init(void);
#endif #endif
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <soc/tegra/fuse.h> #include <soc/tegra/fuse.h>
#include <soc/tegra/pmc.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
...@@ -31,7 +32,6 @@ ...@@ -31,7 +32,6 @@
#include "common.h" #include "common.h"
#include "flowctrl.h" #include "flowctrl.h"
#include "iomap.h" #include "iomap.h"
#include "pmc.h"
#include "reset.h" #include "reset.h"
static cpumask_t tegra_cpu_init_mask; static cpumask_t tegra_cpu_init_mask;
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include <linux/suspend.h> #include <linux/suspend.h>
#include <soc/tegra/fuse.h> #include <soc/tegra/fuse.h>
#include <soc/tegra/pm.h>
#include <soc/tegra/pmc.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/idmap.h> #include <asm/idmap.h>
...@@ -38,7 +40,6 @@ ...@@ -38,7 +40,6 @@
#include "flowctrl.h" #include "flowctrl.h"
#include "iomap.h" #include "iomap.h"
#include "pmc.h"
#include "pm.h" #include "pm.h"
#include "reset.h" #include "reset.h"
#include "sleep.h" #include "sleep.h"
...@@ -167,9 +168,29 @@ static int tegra_sleep_cpu(unsigned long v2p) ...@@ -167,9 +168,29 @@ static int tegra_sleep_cpu(unsigned long v2p)
return 0; return 0;
} }
static void tegra_pm_set(enum tegra_suspend_mode mode)
{
u32 value;
switch (tegra_get_chip_id()) {
case TEGRA20:
case TEGRA30:
break;
default:
/* Turn off CRAIL */
value = flowctrl_read_cpu_csr(0);
value &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK;
value |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL;
flowctrl_write_cpu_csr(0, value);
break;
}
tegra_pmc_enter_suspend_mode(mode);
}
void tegra_idle_lp2_last(void) void tegra_idle_lp2_last(void)
{ {
tegra_pmc_pm_set(TEGRA_SUSPEND_LP2); tegra_pm_set(TEGRA_SUSPEND_LP2);
cpu_cluster_pm_enter(); cpu_cluster_pm_enter();
suspend_cpu_complex(); suspend_cpu_complex();
...@@ -268,8 +289,6 @@ static bool tegra_sleep_core_init(void) ...@@ -268,8 +289,6 @@ static bool tegra_sleep_core_init(void)
static void tegra_suspend_enter_lp1(void) static void tegra_suspend_enter_lp1(void)
{ {
tegra_pmc_suspend();
/* copy the reset vector & SDRAM shutdown code into IRAM */ /* copy the reset vector & SDRAM shutdown code into IRAM */
memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
iram_save_size); iram_save_size);
...@@ -281,8 +300,6 @@ static void tegra_suspend_enter_lp1(void) ...@@ -281,8 +300,6 @@ static void tegra_suspend_enter_lp1(void)
static void tegra_suspend_exit_lp1(void) static void tegra_suspend_exit_lp1(void)
{ {
tegra_pmc_resume();
/* restore IRAM */ /* restore IRAM */
memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr, memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr,
iram_save_size); iram_save_size);
...@@ -307,7 +324,7 @@ static int tegra_suspend_enter(suspend_state_t state) ...@@ -307,7 +324,7 @@ static int tegra_suspend_enter(suspend_state_t state)
pr_info("Entering suspend state %s\n", lp_state[mode]); pr_info("Entering suspend state %s\n", lp_state[mode]);
tegra_pmc_pm_set(mode); tegra_pm_set(mode);
local_fiq_disable(); local_fiq_disable();
...@@ -355,7 +372,6 @@ void __init tegra_init_suspend(void) ...@@ -355,7 +372,6 @@ void __init tegra_init_suspend(void)
return; return;
tegra_tear_down_cpu_init(); tegra_tear_down_cpu_init();
tegra_pmc_suspend_init();
if (mode >= TEGRA_SUSPEND_LP1) { if (mode >= TEGRA_SUSPEND_LP1) {
if (!tegra_lp1_iram_hook() || !tegra_sleep_core_init()) { if (!tegra_lp1_iram_hook() || !tegra_sleep_core_init()) {
......
...@@ -21,12 +21,11 @@ ...@@ -21,12 +21,11 @@
#ifndef _MACH_TEGRA_PM_H_ #ifndef _MACH_TEGRA_PM_H_
#define _MACH_TEGRA_PM_H_ #define _MACH_TEGRA_PM_H_
#include "pmc.h"
struct tegra_lp1_iram { struct tegra_lp1_iram {
void *start_addr; void *start_addr;
void *end_addr; void *end_addr;
}; };
extern struct tegra_lp1_iram tegra_lp1_iram; extern struct tegra_lp1_iram tegra_lp1_iram;
extern void (*tegra_sleep_core_finish)(unsigned long v2p); extern void (*tegra_sleep_core_finish)(unsigned long v2p);
...@@ -42,15 +41,8 @@ void tegra_idle_lp2_last(void); ...@@ -42,15 +41,8 @@ void tegra_idle_lp2_last(void);
extern void (*tegra_tear_down_cpu)(void); extern void (*tegra_tear_down_cpu)(void);
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
enum tegra_suspend_mode mode);
void tegra_init_suspend(void); void tegra_init_suspend(void);
#else #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_init_suspend(void) {} static inline void tegra_init_suspend(void) {}
#endif #endif
......
This diff is collapsed.
/*
* 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 __MACH_TEGRA_PMC_H
#define __MACH_TEGRA_PMC_H
#include <linux/reboot.h>
enum tegra_suspend_mode {
TEGRA_SUSPEND_NONE = 0,
TEGRA_SUSPEND_LP2, /* CPU voltage off */
TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */
TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */
TEGRA_MAX_SUSPEND_MODE,
};
#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_suspend(void);
void tegra_pmc_resume(void);
void tegra_pmc_pm_set(enum tegra_suspend_mode mode);
void tegra_pmc_suspend_init(void);
#endif
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);
void tegra_pmc_init_irq(void);
void tegra_pmc_init(void);
#endif
This diff is collapsed.
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/usb/tegra_usb_phy.h> #include <linux/usb/tegra_usb_phy.h>
#include <soc/tegra/fuse.h> #include <soc/tegra/fuse.h>
#include <soc/tegra/pmc.h>
#include <asm/hardware/cache-l2x0.h> #include <asm/hardware/cache-l2x0.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -49,7 +50,6 @@ ...@@ -49,7 +50,6 @@
#include "cpuidle.h" #include "cpuidle.h"
#include "iomap.h" #include "iomap.h"
#include "irq.h" #include "irq.h"
#include "pmc.h"
#include "pm.h" #include "pm.h"
#include "reset.h" #include "reset.h"
#include "sleep.h" #include "sleep.h"
...@@ -74,12 +74,10 @@ static void __init tegra_init_early(void) ...@@ -74,12 +74,10 @@ static void __init tegra_init_early(void)
{ {
of_register_trusted_foundations(); of_register_trusted_foundations();
tegra_cpu_reset_handler_init(); tegra_cpu_reset_handler_init();
tegra_powergate_init();
} }
static void __init tegra_dt_init_irq(void) static void __init tegra_dt_init_irq(void)
{ {
tegra_pmc_init_irq();
tegra_init_irq(); tegra_init_irq();
irqchip_init(); irqchip_init();
tegra_legacy_irq_syscore_init(); tegra_legacy_irq_syscore_init();
...@@ -91,8 +89,6 @@ static void __init tegra_dt_init(void) ...@@ -91,8 +89,6 @@ static void __init tegra_dt_init(void)
struct soc_device *soc_dev; struct soc_device *soc_dev;
struct device *parent = NULL; struct device *parent = NULL;
tegra_pmc_init();
tegra_clocks_apply_init_table(); tegra_clocks_apply_init_table();
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
...@@ -142,7 +138,6 @@ static void __init tegra_dt_init_late(void) ...@@ -142,7 +138,6 @@ static void __init tegra_dt_init_late(void)
tegra_init_suspend(); tegra_init_suspend();
tegra_cpuidle_init(); tegra_cpuidle_init();
tegra_powergate_debugfs_init();
for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) { for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
if (of_machine_is_compatible(board_init_funcs[i].machine)) { if (of_machine_is_compatible(board_init_funcs[i].machine)) {
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/clk/tegra.h> #include <linux/clk/tegra.h>
#include <soc/tegra/powergate.h> #include <soc/tegra/pmc.h>
#include <dt-bindings/clock/tegra30-car.h> #include <dt-bindings/clock/tegra30-car.h>
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reset.h> #include <linux/reset.h>
#include <soc/tegra/powergate.h> #include <soc/tegra/pmc.h>
#include "drm.h" #include "drm.h"
#include "gem.h" #include "gem.h"
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reset.h> #include <linux/reset.h>
#include <soc/tegra/powergate.h> #include <soc/tegra/pmc.h>
#include <drm/drm_dp_helper.h> #include <drm/drm_dp_helper.h>
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <soc/tegra/cpuidle.h> #include <soc/tegra/cpuidle.h>
#include <soc/tegra/powergate.h> #include <soc/tegra/pmc.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
......
obj-$(CONFIG_ARCH_TEGRA) += fuse/ obj-$(CONFIG_ARCH_TEGRA) += fuse/
obj-$(CONFIG_ARCH_TEGRA) += common.o obj-$(CONFIG_ARCH_TEGRA) += common.o
obj-$(CONFIG_ARCH_TEGRA) += pmc.o
This diff is collapsed.
/*
* 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 */
TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */
TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */
TEGRA_MAX_SUSPEND_MODE,
};
#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__ */
/* /*
* Copyright (c) 2010 Google, Inc * Copyright (c) 2010 Google, Inc
* Copyright (c) 2014 NVIDIA Corporation
* *
* Author: * Author:
* Colin Cross <ccross@google.com> * Colin Cross <ccross@google.com>
...@@ -15,12 +16,34 @@ ...@@ -15,12 +16,34 @@
* *
*/ */
#ifndef __SOC_TEGRA_POWERGATE_H__ #ifndef __SOC_TEGRA_PMC_H__
#define __SOC_TEGRA_POWERGATE_H__ #define __SOC_TEGRA_PMC_H__
#include <linux/reboot.h>
#include <soc/tegra/pm.h>
struct clk; struct clk;
struct reset_control; 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);
#endif /* CONFIG_SMP */
/*
* powergate and I/O rail APIs
*/
#define TEGRA_POWERGATE_CPU 0 #define TEGRA_POWERGATE_CPU 0
#define TEGRA_POWERGATE_3D 1 #define TEGRA_POWERGATE_3D 1
#define TEGRA_POWERGATE_VENC 2 #define TEGRA_POWERGATE_VENC 2
...@@ -129,6 +152,6 @@ static inline int tegra_io_rail_power_off(int id) ...@@ -129,6 +152,6 @@ static inline int tegra_io_rail_power_off(int id)
{ {
return -ENOSYS; return -ENOSYS;
} }
#endif #endif /* CONFIG_ARCH_TEGRA */
#endif /* __SOC_TEGRA_POWERGATE_H__ */ #endif /* __SOC_TEGRA_PMC_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment