Commit c6b659c0 authored by Olof Johansson's avatar Olof Johansson

Merge tag 'tegra-for-3.17-soc' of...

Merge tag 'tegra-for-3.17-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/cleanup

Merge "ARM: tegra: core code changes for 3.17" from Thierry Reding:

Some of the code that's currently called from the Tegra machine setup
code is moved to regular initcalls. To catch dependency violations, the
various code paths now WARN if they're called to early. Not all of the
potential candidates are converted yet, but those that were have been
verified to work across all supported Tegra generations.

A new function, soc_is_tegra(), is also provided to make sure that the
initcalls can abort early if they aren't run on Tegra, which can happen
for multi-platform builds.

Finally this also moves out the PMC driver to drivers/soc/tegra so that
it can be shared with 64-bit ARM.

This is based on the for-3.17/fuse-move branch. The split is somewhat
arbitrary but allows the dependents of the for-3.17/fuse-move to pull
in as little code as necessary.

* tag 'tegra-for-3.17-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  ARM: tegra: Convert PMC to a driver
  soc/tegra: fuse: Set up in early initcall
  ARM: tegra: Always lock the CPU reset vector
  ARM: tegra: Setup CPU hotplug in a pure initcall
  soc/tegra: Implement runtime check for Tegra SoCs
Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 23e89292 7232398a
......@@ -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
......@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/smp.h>
#include <soc/tegra/common.h>
#include <soc/tegra/fuse.h>
#include <asm/smp_plat.h>
......@@ -38,6 +39,11 @@ int tegra_cpu_kill(unsigned cpu)
*/
void __ref tegra_cpu_die(unsigned int cpu)
{
if (!tegra_hotplug_shutdown) {
WARN(1, "hotplug is not yet initialized\n");
return;
}
/* Clean L1 data cache */
tegra_disable_clean_inv_dcache(TEGRA_FLUSH_CACHE_LOUIS);
......@@ -48,10 +54,13 @@ void __ref tegra_cpu_die(unsigned int cpu)
BUG();
}
void __init tegra_hotplug_init(void)
static int __init tegra_hotplug_init(void)
{
if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
return;
return 0;
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;
......@@ -61,4 +70,7 @@ void __init tegra_hotplug_init(void)
tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
return 0;
}
pure_initcall(tegra_hotplug_init);
......@@ -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.
......@@ -54,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.
*/
if (tegra_get_chip_id() != TEGRA20) {
reg = readl(sb_ctrl);
reg |= 2;
writel(reg, sb_ctrl);
wmb();
}
reg = readl(sb_ctrl);
reg |= 2;
writel(reg, sb_ctrl);
wmb();
}
static void __init tegra_cpu_reset_handler_enable(void)
......
......@@ -130,9 +130,6 @@ void tegra_disable_clean_inv_dcache(u32 flag);
#ifdef CONFIG_HOTPLUG_CPU
void tegra20_hotplug_shutdown(void);
void tegra30_hotplug_shutdown(void);
void tegra_hotplug_init(void);
#else
static inline void tegra_hotplug_init(void) {}
#endif
void tegra20_cpu_shutdown(int cpu);
......
......@@ -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"
......@@ -73,15 +73,11 @@ u32 tegra_uart_config[3] = {
static void __init tegra_init_early(void)
{
of_register_trusted_foundations();
tegra_init_fuse();
tegra_cpu_reset_handler_init();
tegra_powergate_init();
tegra_hotplug_init();
}
static void __init tegra_dt_init_irq(void)
{
tegra_pmc_init_irq();
tegra_init_irq();
irqchip_init();
tegra_legacy_irq_syscore_init();
......@@ -93,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);
......@@ -144,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
/*
* 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;
}
......@@ -23,6 +23,7 @@
#include <linux/of_address.h>
#include <linux/io.h>
#include <soc/tegra/common.h>
#include <soc/tegra/fuse.h>
#include "fuse.h"
......@@ -125,11 +126,14 @@ int tegra_fuse_create_sysfs(struct device *dev, int size,
return device_create_bin_file(dev, &fuse_bin_attr);
}
void __init tegra_init_fuse(void)
static int __init tegra_init_fuse(void)
{
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);
......@@ -139,7 +143,7 @@ void __init tegra_init_fuse(void)
iounmap(car_base);
} else {
pr_err("Could not enable fuse clk. ioremap tegra car failed.\n");
return;
return -ENXIO;
}
if (tegra_get_chip_id() == TEGRA20)
......@@ -153,4 +157,7 @@ void __init tegra_init_fuse(void)
tegra_sku_info.core_process_id);
pr_debug("Tegra CPU Speedo ID %d, Soc Speedo ID %d\n",
tegra_sku_info.cpu_speedo_id, tegra_sku_info.soc_speedo_id);
return 0;
}
early_initcall(tegra_init_fuse);
......@@ -38,9 +38,12 @@ u32 tegra_read_chipid(void)
u8 tegra_get_chip_id(void)
{
u32 id = tegra_read_chipid();
if (!apbmisc_base) {
WARN(1, "Tegra Chip ID not yet available\n");
return 0;
}
return (id >> 8) & 0xff;
return (tegra_read_chipid() >> 8) & 0xff;
}
u32 tegra_read_straps(void)
......
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_COMMON_H__
#define __SOC_TEGRA_COMMON_H__
bool soc_is_tegra(void);
#endif /* __SOC_TEGRA_COMMON_H__ */
......@@ -56,7 +56,6 @@ struct tegra_sku_info {
u32 tegra_read_straps(void);
u32 tegra_read_chipid(void);
void tegra_init_fuse(void);
int tegra_fuse_readl(unsigned long offset, u32 *value);
extern struct tegra_sku_info tegra_sku_info;
......
/*
* 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