11cea7326b3fff97d17d33fb8f33163409a84431bColin Cross/*
21cea7326b3fff97d17d33fb8f33163409a84431bColin Cross *  Copyright (C) 2002 ARM Ltd.
31cea7326b3fff97d17d33fb8f33163409a84431bColin Cross *  All Rights Reserved
47469688e832e340a84a1f6d4c290d8680c723256Hiroshi Doyu *  Copyright (c) 2010, 2012-2013, NVIDIA Corporation. All rights reserved.
51cea7326b3fff97d17d33fb8f33163409a84431bColin Cross *
61cea7326b3fff97d17d33fb8f33163409a84431bColin Cross * This program is free software; you can redistribute it and/or modify
71cea7326b3fff97d17d33fb8f33163409a84431bColin Cross * it under the terms of the GNU General Public License version 2 as
81cea7326b3fff97d17d33fb8f33163409a84431bColin Cross * published by the Free Software Foundation.
91cea7326b3fff97d17d33fb8f33163409a84431bColin Cross */
10a0524acc94c91c72c2968a76eddc6f3afe82f9f2Thierry Reding
11a0524acc94c91c72c2968a76eddc6f3afe82f9f2Thierry Reding#include <linux/clk/tegra.h>
121cea7326b3fff97d17d33fb8f33163409a84431bColin Cross#include <linux/kernel.h>
131cea7326b3fff97d17d33fb8f33163409a84431bColin Cross#include <linux/smp.h>
141cea7326b3fff97d17d33fb8f33163409a84431bColin Cross
1505ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding#include <soc/tegra/common.h>
16304664eab93f9e95a8d28fbd9702ede88bb10cc5Thierry Reding#include <soc/tegra/fuse.h>
17304664eab93f9e95a8d28fbd9702ede88bb10cc5Thierry Reding
1859b0f6825c15d24859e22b1024440ae2a094983eJoseph Lo#include <asm/smp_plat.h>
191cea7326b3fff97d17d33fb8f33163409a84431bColin Cross
2059b0f6825c15d24859e22b1024440ae2a094983eJoseph Lo#include "sleep.h"
211cea7326b3fff97d17d33fb8f33163409a84431bColin Cross
2259b0f6825c15d24859e22b1024440ae2a094983eJoseph Lostatic void (*tegra_hotplug_shutdown)(void);
231cea7326b3fff97d17d33fb8f33163409a84431bColin Cross
24b811943160cf3b040341c50d23440cf6d68ae079Joseph Loint tegra_cpu_kill(unsigned cpu)
25b811943160cf3b040341c50d23440cf6d68ae079Joseph Lo{
26b811943160cf3b040341c50d23440cf6d68ae079Joseph Lo	cpu = cpu_logical_map(cpu);
27b811943160cf3b040341c50d23440cf6d68ae079Joseph Lo
28b811943160cf3b040341c50d23440cf6d68ae079Joseph Lo	/* Clock gate the CPU */
29b811943160cf3b040341c50d23440cf6d68ae079Joseph Lo	tegra_wait_cpu_in_reset(cpu);
30b811943160cf3b040341c50d23440cf6d68ae079Joseph Lo	tegra_disable_cpu_clock(cpu);
31b811943160cf3b040341c50d23440cf6d68ae079Joseph Lo
32b811943160cf3b040341c50d23440cf6d68ae079Joseph Lo	return 1;
33b811943160cf3b040341c50d23440cf6d68ae079Joseph Lo}
34b811943160cf3b040341c50d23440cf6d68ae079Joseph Lo
351cea7326b3fff97d17d33fb8f33163409a84431bColin Cross/*
361cea7326b3fff97d17d33fb8f33163409a84431bColin Cross * platform-specific code to shutdown a CPU
371cea7326b3fff97d17d33fb8f33163409a84431bColin Cross *
381cea7326b3fff97d17d33fb8f33163409a84431bColin Cross * Called with IRQs disabled
391cea7326b3fff97d17d33fb8f33163409a84431bColin Cross */
40a17257322f5e6ca376c15908b55423369274fcadMarc Zyngiervoid __ref tegra_cpu_die(unsigned int cpu)
411cea7326b3fff97d17d33fb8f33163409a84431bColin Cross{
4205ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding	if (!tegra_hotplug_shutdown) {
4305ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding		WARN(1, "hotplug is not yet initialized\n");
4405ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding		return;
4505ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding	}
4605ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding
4757886616ca7bff844a6427436d0c8faf74653f73Joseph Lo	/* Clean L1 data cache */
48ac2527bfc21739b77d687df1bfc4e973103fef7bJoseph Lo	tegra_disable_clean_inv_dcache(TEGRA_FLUSH_CACHE_LOUIS);
491cea7326b3fff97d17d33fb8f33163409a84431bColin Cross
5059b0f6825c15d24859e22b1024440ae2a094983eJoseph Lo	/* Shut down the current CPU. */
5159b0f6825c15d24859e22b1024440ae2a094983eJoseph Lo	tegra_hotplug_shutdown();
5259b0f6825c15d24859e22b1024440ae2a094983eJoseph Lo
5359b0f6825c15d24859e22b1024440ae2a094983eJoseph Lo	/* Should never return here. */
5459b0f6825c15d24859e22b1024440ae2a094983eJoseph Lo	BUG();
551cea7326b3fff97d17d33fb8f33163409a84431bColin Cross}
561cea7326b3fff97d17d33fb8f33163409a84431bColin Cross
5705ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Redingstatic int __init tegra_hotplug_init(void)
58453689e407f2b7c0a72a2e6fb2ef84c20475773bJoseph Lo{
597469688e832e340a84a1f6d4c290d8680c723256Hiroshi Doyu	if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
6005ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding		return 0;
6105ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding
6205ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding	if (!soc_is_tegra())
6305ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding		return 0;
64453689e407f2b7c0a72a2e6fb2ef84c20475773bJoseph Lo
65304664eab93f9e95a8d28fbd9702ede88bb10cc5Thierry Reding	if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20)
667469688e832e340a84a1f6d4c290d8680c723256Hiroshi Doyu		tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
67304664eab93f9e95a8d28fbd9702ede88bb10cc5Thierry Reding	if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30)
687469688e832e340a84a1f6d4c290d8680c723256Hiroshi Doyu		tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
69304664eab93f9e95a8d28fbd9702ede88bb10cc5Thierry Reding	if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114)
7033d5c01915ccca298a5fda7e0cb33199d225e03aJoseph Lo		tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
71304664eab93f9e95a8d28fbd9702ede88bb10cc5Thierry Reding	if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124)
729997e62682e0fe68566c88f70ed320ded4e16529Joseph Lo		tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
7305ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding
7405ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Reding	return 0;
7559b0f6825c15d24859e22b1024440ae2a094983eJoseph Lo}
7605ccf19602cc16fc96401b4f2617d1b8e20e642dThierry Redingpure_initcall(tegra_hotplug_init);
77