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
obj-y += io.o
obj-y += irq.o
obj-y += pmc.o
obj-y += flowctrl.o
obj-y += powergate.o
obj-y += pm.o
obj-y += reset.o
obj-y += reset-handler.o
......
......@@ -28,13 +28,6 @@
void __init tegra_map_common_io(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);
#endif
......@@ -22,6 +22,7 @@
#include <linux/smp.h>
#include <soc/tegra/fuse.h>
#include <soc/tegra/pmc.h>
#include <asm/cacheflush.h>
#include <asm/mach-types.h>
......@@ -31,7 +32,6 @@
#include "common.h"
#include "flowctrl.h"
#include "iomap.h"
#include "pmc.h"
#include "reset.h"
static cpumask_t tegra_cpu_init_mask;
......
......@@ -28,6 +28,8 @@
#include <linux/suspend.h>
#include <soc/tegra/fuse.h>
#include <soc/tegra/pm.h>
#include <soc/tegra/pmc.h>
#include <asm/cacheflush.h>
#include <asm/idmap.h>
......@@ -38,7 +40,6 @@
#include "flowctrl.h"
#include "iomap.h"
#include "pmc.h"
#include "pm.h"
#include "reset.h"
#include "sleep.h"
......@@ -167,9 +168,29 @@ static int tegra_sleep_cpu(unsigned long v2p)
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)
{
tegra_pmc_pm_set(TEGRA_SUSPEND_LP2);
tegra_pm_set(TEGRA_SUSPEND_LP2);
cpu_cluster_pm_enter();
suspend_cpu_complex();
......@@ -268,8 +289,6 @@ static bool tegra_sleep_core_init(void)
static void tegra_suspend_enter_lp1(void)
{
tegra_pmc_suspend();
/* copy the reset vector & SDRAM shutdown code into IRAM */
memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
iram_save_size);
......@@ -281,8 +300,6 @@ static void tegra_suspend_enter_lp1(void)
static void tegra_suspend_exit_lp1(void)
{
tegra_pmc_resume();
/* restore IRAM */
memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr,
iram_save_size);
......@@ -307,7 +324,7 @@ static int tegra_suspend_enter(suspend_state_t state)
pr_info("Entering suspend state %s\n", lp_state[mode]);
tegra_pmc_pm_set(mode);
tegra_pm_set(mode);
local_fiq_disable();
......@@ -355,7 +372,6 @@ void __init tegra_init_suspend(void)
return;
tegra_tear_down_cpu_init();
tegra_pmc_suspend_init();
if (mode >= TEGRA_SUSPEND_LP1) {
if (!tegra_lp1_iram_hook() || !tegra_sleep_core_init()) {
......
......@@ -21,12 +21,11 @@
#ifndef _MACH_TEGRA_PM_H_
#define _MACH_TEGRA_PM_H_
#include "pmc.h"
struct tegra_lp1_iram {
void *start_addr;
void *end_addr;
};
extern struct tegra_lp1_iram tegra_lp1_iram;
extern void (*tegra_sleep_core_finish)(unsigned long v2p);
......@@ -42,15 +41,8 @@ void tegra_idle_lp2_last(void);
extern void (*tegra_tear_down_cpu)(void);
#ifdef CONFIG_PM_SLEEP
enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
enum tegra_suspend_mode mode);
void tegra_init_suspend(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_init_suspend(void) {}
#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 @@
#include <linux/usb/tegra_usb_phy.h>
#include <soc/tegra/fuse.h>
#include <soc/tegra/pmc.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/mach/arch.h>
......@@ -49,7 +50,6 @@
#include "cpuidle.h"
#include "iomap.h"
#include "irq.h"
#include "pmc.h"
#include "pm.h"
#include "reset.h"
#include "sleep.h"
......@@ -74,12 +74,10 @@ static void __init tegra_init_early(void)
{
of_register_trusted_foundations();
tegra_cpu_reset_handler_init();
tegra_powergate_init();
}
static void __init tegra_dt_init_irq(void)
{
tegra_pmc_init_irq();
tegra_init_irq();
irqchip_init();
tegra_legacy_irq_syscore_init();
......@@ -91,8 +89,6 @@ static void __init tegra_dt_init(void)
struct soc_device *soc_dev;
struct device *parent = NULL;
tegra_pmc_init();
tegra_clocks_apply_init_table();
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
......@@ -142,7 +138,6 @@ static void __init tegra_dt_init_late(void)
tegra_init_suspend();
tegra_cpuidle_init();
tegra_powergate_debugfs_init();
for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
if (of_machine_is_compatible(board_init_funcs[i].machine)) {
......
......@@ -23,7 +23,7 @@
#include <linux/of_address.h>
#include <linux/clk/tegra.h>
#include <soc/tegra/powergate.h>
#include <soc/tegra/pmc.h>
#include <dt-bindings/clock/tegra30-car.h>
......
......@@ -13,7 +13,7 @@
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <soc/tegra/powergate.h>
#include <soc/tegra/pmc.h>
#include "drm.h"
#include "gem.h"
......
......@@ -12,7 +12,7 @@
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <soc/tegra/powergate.h>
#include <soc/tegra/pmc.h>
#include <drm/drm_dp_helper.h>
......
......@@ -45,7 +45,7 @@
#include <linux/regulator/consumer.h>
#include <soc/tegra/cpuidle.h>
#include <soc/tegra/powergate.h>
#include <soc/tegra/pmc.h>
#include <asm/mach/irq.h>
#include <asm/mach/map.h>
......
obj-$(CONFIG_ARCH_TEGRA) += fuse/
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) 2014 NVIDIA Corporation
*
* Author:
* Colin Cross <ccross@google.com>
......@@ -15,12 +16,34 @@
*
*/
#ifndef __SOC_TEGRA_POWERGATE_H__
#define __SOC_TEGRA_POWERGATE_H__
#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);
#endif /* CONFIG_SMP */
/*
* powergate and I/O rail APIs
*/
#define TEGRA_POWERGATE_CPU 0
#define TEGRA_POWERGATE_3D 1
#define TEGRA_POWERGATE_VENC 2
......@@ -129,6 +152,6 @@ static inline int tegra_io_rail_power_off(int id)
{
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