diff options
Diffstat (limited to 'arch/arm/mach-tegra')
33 files changed, 173 insertions, 2208 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 6fbfbb77dcd9..e48a74458c25 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -2,24 +2,18 @@ asflags-y += -march=armv7-a obj-y += io.o obj-y += irq.o -obj-y += fuse.o -obj-y += pmc.o obj-y += flowctrl.o -obj-y += powergate.o -obj-y += apbio.o obj-y += pm.o obj-y += reset.o obj-y += reset-handler.o obj-y += sleep.o obj-y += tegra.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 obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pm-tegra20.o ifeq ($(CONFIG_CPU_IDLE),y) obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += cpuidle-tegra20.o endif -obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_speedo.o 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 +22,6 @@ endif obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -obj-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114_speedo.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += sleep-tegra30.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += pm-tegra30.o ifeq ($(CONFIG_CPU_IDLE),y) diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c deleted file mode 100644 index bc471973cf04..000000000000 --- a/arch/arm/mach-tegra/apbio.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2010 NVIDIA Corporation. - * Copyright (C) 2010 Google, Inc. - * - * 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/io.h> -#include <linux/of.h> -#include <linux/dmaengine.h> -#include <linux/dma-mapping.h> -#include <linux/spinlock.h> -#include <linux/completion.h> -#include <linux/sched.h> -#include <linux/mutex.h> - -#include "apbio.h" -#include "iomap.h" - -#if defined(CONFIG_TEGRA20_APB_DMA) -static DEFINE_MUTEX(tegra_apb_dma_lock); -static u32 *tegra_apb_bb; -static dma_addr_t tegra_apb_bb_phys; -static DECLARE_COMPLETION(tegra_apb_wait); - -static u32 tegra_apb_readl_direct(unsigned long offset); -static void tegra_apb_writel_direct(u32 value, unsigned long offset); - -static struct dma_chan *tegra_apb_dma_chan; -static struct dma_slave_config dma_sconfig; - -static bool tegra_apb_dma_init(void) -{ - dma_cap_mask_t mask; - - mutex_lock(&tegra_apb_dma_lock); - - /* Check to see if we raced to setup */ - if (tegra_apb_dma_chan) - goto skip_init; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - tegra_apb_dma_chan = dma_request_channel(mask, NULL, NULL); - if (!tegra_apb_dma_chan) { - /* - * This is common until the device is probed, so don't - * shout about it. - */ - pr_debug("%s: can not allocate dma channel\n", __func__); - goto err_dma_alloc; - } - - tegra_apb_bb = dma_alloc_coherent(NULL, sizeof(u32), - &tegra_apb_bb_phys, GFP_KERNEL); - if (!tegra_apb_bb) { - pr_err("%s: can not allocate bounce buffer\n", __func__); - goto err_buff_alloc; - } - - dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - dma_sconfig.src_maxburst = 1; - dma_sconfig.dst_maxburst = 1; - -skip_init: - mutex_unlock(&tegra_apb_dma_lock); - return true; - -err_buff_alloc: - dma_release_channel(tegra_apb_dma_chan); - tegra_apb_dma_chan = NULL; - -err_dma_alloc: - mutex_unlock(&tegra_apb_dma_lock); - return false; -} - -static void apb_dma_complete(void *args) -{ - complete(&tegra_apb_wait); -} - -static int do_dma_transfer(unsigned long apb_add, - enum dma_transfer_direction dir) -{ - struct dma_async_tx_descriptor *dma_desc; - int ret; - - if (dir == DMA_DEV_TO_MEM) - dma_sconfig.src_addr = apb_add; - else - dma_sconfig.dst_addr = apb_add; - - ret = dmaengine_slave_config(tegra_apb_dma_chan, &dma_sconfig); - if (ret) - return ret; - - dma_desc = dmaengine_prep_slave_single(tegra_apb_dma_chan, - tegra_apb_bb_phys, sizeof(u32), dir, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!dma_desc) - return -EINVAL; - - dma_desc->callback = apb_dma_complete; - dma_desc->callback_param = NULL; - - reinit_completion(&tegra_apb_wait); - - dmaengine_submit(dma_desc); - dma_async_issue_pending(tegra_apb_dma_chan); - ret = wait_for_completion_timeout(&tegra_apb_wait, - msecs_to_jiffies(50)); - - if (WARN(ret == 0, "apb read dma timed out")) { - dmaengine_terminate_all(tegra_apb_dma_chan); - return -EFAULT; - } - return 0; -} - -static u32 tegra_apb_readl_using_dma(unsigned long offset) -{ - int ret; - - if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) - return tegra_apb_readl_direct(offset); - - mutex_lock(&tegra_apb_dma_lock); - ret = do_dma_transfer(offset, DMA_DEV_TO_MEM); - if (ret < 0) { - pr_err("error in reading offset 0x%08lx using dma\n", offset); - *(u32 *)tegra_apb_bb = 0; - } - mutex_unlock(&tegra_apb_dma_lock); - return *((u32 *)tegra_apb_bb); -} - -static void tegra_apb_writel_using_dma(u32 value, unsigned long offset) -{ - int ret; - - if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) { - tegra_apb_writel_direct(value, offset); - return; - } - - mutex_lock(&tegra_apb_dma_lock); - *((u32 *)tegra_apb_bb) = value; - ret = do_dma_transfer(offset, DMA_MEM_TO_DEV); - if (ret < 0) - pr_err("error in writing offset 0x%08lx using dma\n", offset); - mutex_unlock(&tegra_apb_dma_lock); -} -#else -#define tegra_apb_readl_using_dma tegra_apb_readl_direct -#define tegra_apb_writel_using_dma tegra_apb_writel_direct -#endif - -typedef u32 (*apbio_read_fptr)(unsigned long offset); -typedef void (*apbio_write_fptr)(u32 value, unsigned long offset); - -static apbio_read_fptr apbio_read; -static apbio_write_fptr apbio_write; - -static u32 tegra_apb_readl_direct(unsigned long offset) -{ - return readl(IO_ADDRESS(offset)); -} - -static void tegra_apb_writel_direct(u32 value, unsigned long offset) -{ - writel(value, IO_ADDRESS(offset)); -} - -void tegra_apb_io_init(void) -{ - /* Need to use dma only when it is Tegra20 based platform */ - if (of_machine_is_compatible("nvidia,tegra20") || - !of_have_populated_dt()) { - apbio_read = tegra_apb_readl_using_dma; - apbio_write = tegra_apb_writel_using_dma; - } else { - apbio_read = tegra_apb_readl_direct; - apbio_write = tegra_apb_writel_direct; - } -} - -u32 tegra_apb_readl(unsigned long offset) -{ - return apbio_read(offset); -} - -void tegra_apb_writel(u32 value, unsigned long offset) -{ - apbio_write(value, offset); -} diff --git a/arch/arm/mach-tegra/apbio.h b/arch/arm/mach-tegra/apbio.h deleted file mode 100644 index f05d71c303c7..000000000000 --- a/arch/arm/mach-tegra/apbio.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2010 NVIDIA Corporation. - * Copyright (C) 2010 Google, Inc. - * - * 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_APBIO_H -#define __MACH_TEGRA_APBIO_H - -void tegra_apb_io_init(void); -u32 tegra_apb_readl(unsigned long offset); -void tegra_apb_writel(u32 value, unsigned long offset); -#endif diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c index 9c6029ba526f..bb4782a32713 100644 --- a/arch/arm/mach-tegra/board-paz00.c +++ b/arch/arm/mach-tegra/board-paz00.c @@ -17,9 +17,10 @@ * */ -#include <linux/platform_device.h> #include <linux/gpio/driver.h> +#include <linux/platform_device.h> #include <linux/rfkill-gpio.h> + #include "board.h" static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = { diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index bcf5dbf69d58..da90c89296b9 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h @@ -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 diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c index b5fb7c110c64..e3ebdce3e71f 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra114.c +++ b/arch/arm/mach-tegra/cpuidle-tegra114.c @@ -14,16 +14,16 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <linux/kernel.h> -#include <linux/module.h> +#include <asm/firmware.h> +#include <linux/clockchips.h> #include <linux/cpuidle.h> #include <linux/cpu_pm.h> -#include <linux/clockchips.h> -#include <asm/firmware.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <asm/cpuidle.h> -#include <asm/suspend.h> #include <asm/smp_plat.h> +#include <asm/suspend.h> #include "pm.h" #include "sleep.h" diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c index b82dcaee2ef4..b30bf5cba65b 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra20.c +++ b/arch/arm/mach-tegra/cpuidle-tegra20.c @@ -19,23 +19,23 @@ * more details. */ -#include <linux/kernel.h> -#include <linux/module.h> +#include <linux/clk/tegra.h> +#include <linux/clockchips.h> #include <linux/cpuidle.h> #include <linux/cpu_pm.h> -#include <linux/clockchips.h> -#include <linux/clk/tegra.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <asm/cpuidle.h> #include <asm/proc-fns.h> -#include <asm/suspend.h> #include <asm/smp_plat.h> +#include <asm/suspend.h> -#include "pm.h" -#include "sleep.h" +#include "flowctrl.h" #include "iomap.h" #include "irq.h" -#include "flowctrl.h" +#include "pm.h" +#include "sleep.h" #ifdef CONFIG_PM_SLEEP static bool abort_flag; diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c index ed2a2a7bae4d..35561274f6cf 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra30.c +++ b/arch/arm/mach-tegra/cpuidle-tegra30.c @@ -19,17 +19,17 @@ * more details. */ -#include <linux/kernel.h> -#include <linux/module.h> +#include <linux/clk/tegra.h> +#include <linux/clockchips.h> #include <linux/cpuidle.h> #include <linux/cpu_pm.h> -#include <linux/clockchips.h> -#include <linux/clk/tegra.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <asm/cpuidle.h> #include <asm/proc-fns.h> -#include <asm/suspend.h> #include <asm/smp_plat.h> +#include <asm/suspend.h> #include "pm.h" #include "sleep.h" diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c index 7bc5d8d667fe..316563141add 100644 --- a/arch/arm/mach-tegra/cpuidle.c +++ b/arch/arm/mach-tegra/cpuidle.c @@ -24,12 +24,13 @@ #include <linux/kernel.h> #include <linux/module.h> -#include "fuse.h" +#include <soc/tegra/fuse.h> + #include "cpuidle.h" void __init tegra_cpuidle_init(void) { - switch (tegra_chip_id) { + switch (tegra_get_chip_id()) { case TEGRA20: if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)) tegra20_cpuidle_init(); @@ -49,7 +50,7 @@ void __init tegra_cpuidle_init(void) void tegra_cpuidle_pcie_irqs_in_use(void) { - switch (tegra_chip_id) { + switch (tegra_get_chip_id()) { case TEGRA20: 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 ce8ab8abf061..ec55d1de1b55 100644 --- a/arch/arm/mach-tegra/flowctrl.c +++ b/arch/arm/mach-tegra/flowctrl.c @@ -18,14 +18,15 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <linux/cpumask.h> #include <linux/init.h> -#include <linux/kernel.h> #include <linux/io.h> -#include <linux/cpumask.h> +#include <linux/kernel.h> + +#include <soc/tegra/fuse.h> #include "flowctrl.h" #include "iomap.h" -#include "fuse.h" static u8 flowctrl_offset_halt_cpu[] = { FLOW_CTRL_HALT_CPU0_EVENTS, @@ -76,7 +77,7 @@ void flowctrl_cpu_suspend_enter(unsigned int cpuid) int i; reg = flowctrl_read_cpu_csr(cpuid); - switch (tegra_chip_id) { + switch (tegra_get_chip_id()) { case TEGRA20: /* clear wfe bitmap */ reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP; @@ -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); - switch (tegra_chip_id) { + switch (tegra_get_chip_id()) { case TEGRA20: /* clear wfe bitmap */ reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP; diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c deleted file mode 100644 index c9ac23b385be..000000000000 --- a/arch/arm/mach-tegra/fuse.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * arch/arm/mach-tegra/fuse.c - * - * Copyright (C) 2010 Google, Inc. - * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. - * - * Author: - * Colin Cross <ccross@android.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/io.h> -#include <linux/export.h> -#include <linux/random.h> -#include <linux/clk.h> -#include <linux/tegra-soc.h> - -#include "fuse.h" -#include "iomap.h" -#include "apbio.h" - -/* Tegra20 only */ -#define FUSE_UID_LOW 0x108 -#define FUSE_UID_HIGH 0x10c - -/* Tegra30 and later */ -#define FUSE_VENDOR_CODE 0x200 -#define FUSE_FAB_CODE 0x204 -#define FUSE_LOT_CODE_0 0x208 -#define FUSE_LOT_CODE_1 0x20c -#define FUSE_WAFER_ID 0x210 -#define FUSE_X_COORDINATE 0x214 -#define FUSE_Y_COORDINATE 0x218 - -#define FUSE_SKU_INFO 0x110 - -#define TEGRA20_FUSE_SPARE_BIT 0x200 -#define TEGRA30_FUSE_SPARE_BIT 0x244 - -int tegra_sku_id; -int tegra_cpu_process_id; -int tegra_core_process_id; -int tegra_chip_id; -int tegra_cpu_speedo_id; /* only exist in Tegra30 and later */ -int tegra_soc_speedo_id; -enum tegra_revision tegra_revision; - -static struct clk *fuse_clk; -static int tegra_fuse_spare_bit; -static void (*tegra_init_speedo_data)(void); - -/* The BCT to use at boot is specified by board straps that can be read - * through a APB misc register and decoded. 2 bits, i.e. 4 possible BCTs. - */ -int tegra_bct_strapping; - -#define STRAP_OPT 0x008 -#define GMI_AD0 (1 << 4) -#define GMI_AD1 (1 << 5) -#define RAM_ID_MASK (GMI_AD0 | GMI_AD1) -#define RAM_CODE_SHIFT 4 - -static const char *tegra_revision_name[TEGRA_REVISION_MAX] = { - [TEGRA_REVISION_UNKNOWN] = "unknown", - [TEGRA_REVISION_A01] = "A01", - [TEGRA_REVISION_A02] = "A02", - [TEGRA_REVISION_A03] = "A03", - [TEGRA_REVISION_A03p] = "A03 prime", - [TEGRA_REVISION_A04] = "A04", -}; - -static void tegra_fuse_enable_clk(void) -{ - if (IS_ERR(fuse_clk)) - fuse_clk = clk_get_sys(NULL, "fuse"); - if (IS_ERR(fuse_clk)) - return; - clk_prepare_enable(fuse_clk); -} - -static void tegra_fuse_disable_clk(void) -{ - if (IS_ERR(fuse_clk)) - return; - clk_disable_unprepare(fuse_clk); -} - -u32 tegra_fuse_readl(unsigned long offset) -{ - return tegra_apb_readl(TEGRA_FUSE_BASE + offset); -} - -bool tegra_spare_fuse(int bit) -{ - bool ret; - - tegra_fuse_enable_clk(); - - ret = tegra_fuse_readl(tegra_fuse_spare_bit + bit * 4); - - tegra_fuse_disable_clk(); - - return ret; -} - -static enum tegra_revision tegra_get_revision(u32 id) -{ - u32 minor_rev = (id >> 16) & 0xf; - - switch (minor_rev) { - case 1: - return TEGRA_REVISION_A01; - case 2: - return TEGRA_REVISION_A02; - case 3: - if (tegra_chip_id == TEGRA20 && - (tegra_spare_fuse(18) || tegra_spare_fuse(19))) - return TEGRA_REVISION_A03p; - else - return TEGRA_REVISION_A03; - case 4: - return TEGRA_REVISION_A04; - default: - return TEGRA_REVISION_UNKNOWN; - } -} - -static void tegra_get_process_id(void) -{ - u32 reg; - - tegra_fuse_enable_clk(); - - reg = tegra_fuse_readl(tegra_fuse_spare_bit); - tegra_cpu_process_id = (reg >> 6) & 3; - reg = tegra_fuse_readl(tegra_fuse_spare_bit); - tegra_core_process_id = (reg >> 12) & 3; - - tegra_fuse_disable_clk(); -} - -u32 tegra_read_chipid(void) -{ - return readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804); -} - -static void __init tegra20_fuse_init_randomness(void) -{ - u32 randomness[2]; - - randomness[0] = tegra_fuse_readl(FUSE_UID_LOW); - randomness[1] = tegra_fuse_readl(FUSE_UID_HIGH); - - add_device_randomness(randomness, sizeof(randomness)); -} - -/* Applies to Tegra30 or later */ -static void __init tegra30_fuse_init_randomness(void) -{ - u32 randomness[7]; - - randomness[0] = tegra_fuse_readl(FUSE_VENDOR_CODE); - randomness[1] = tegra_fuse_readl(FUSE_FAB_CODE); - randomness[2] = tegra_fuse_readl(FUSE_LOT_CODE_0); - randomness[3] = tegra_fuse_readl(FUSE_LOT_CODE_1); - randomness[4] = tegra_fuse_readl(FUSE_WAFER_ID); - randomness[5] = tegra_fuse_readl(FUSE_X_COORDINATE); - randomness[6] = tegra_fuse_readl(FUSE_Y_COORDINATE); - - add_device_randomness(randomness, sizeof(randomness)); -} - -void __init tegra_init_fuse(void) -{ - u32 id; - u32 randomness[5]; - - u32 reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48)); - reg |= 1 << 28; - writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48)); - - /* - * Enable FUSE clock. This needs to be hardcoded because the clock - * subsystem is not active during early boot. - */ - reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x14)); - reg |= 1 << 7; - writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x14)); - fuse_clk = ERR_PTR(-EINVAL); - - reg = tegra_fuse_readl(FUSE_SKU_INFO); - randomness[0] = reg; - tegra_sku_id = reg & 0xFF; - - reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT); - randomness[1] = reg; - tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT; - - id = tegra_read_chipid(); - randomness[2] = id; - tegra_chip_id = (id >> 8) & 0xff; - - switch (tegra_chip_id) { - case TEGRA20: - tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT; - tegra_init_speedo_data = &tegra20_init_speedo_data; - break; - case TEGRA30: - tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT; - tegra_init_speedo_data = &tegra30_init_speedo_data; - break; - case TEGRA114: - tegra_init_speedo_data = &tegra114_init_speedo_data; - break; - default: - pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id); - tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT; - tegra_init_speedo_data = &tegra_get_process_id; - } - - tegra_revision = tegra_get_revision(id); - tegra_init_speedo_data(); - randomness[3] = (tegra_cpu_process_id << 16) | tegra_core_process_id; - randomness[4] = (tegra_cpu_speedo_id << 16) | tegra_soc_speedo_id; - - add_device_randomness(randomness, sizeof(randomness)); - switch (tegra_chip_id) { - case TEGRA20: - tegra20_fuse_init_randomness(); - break; - case TEGRA30: - case TEGRA114: - default: - tegra30_fuse_init_randomness(); - break; - } - - pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n", - tegra_revision_name[tegra_revision], - tegra_sku_id, tegra_cpu_process_id, - tegra_core_process_id); -} diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h deleted file mode 100644 index c01d04785d67..000000000000 --- a/arch/arm/mach-tegra/fuse.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2010 Google, Inc. - * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. - * - * Author: - * Colin Cross <ccross@android.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_FUSE_H -#define __MACH_TEGRA_FUSE_H - -#define SKU_ID_T20 8 -#define SKU_ID_T25SE 20 -#define SKU_ID_AP25 23 -#define SKU_ID_T25 24 -#define SKU_ID_AP25E 27 -#define SKU_ID_T25E 28 - -#define TEGRA20 0x20 -#define TEGRA30 0x30 -#define TEGRA114 0x35 -#define TEGRA124 0x40 - -#ifndef __ASSEMBLY__ -enum tegra_revision { - TEGRA_REVISION_UNKNOWN = 0, - TEGRA_REVISION_A01, - TEGRA_REVISION_A02, - TEGRA_REVISION_A03, - TEGRA_REVISION_A03p, - TEGRA_REVISION_A04, - TEGRA_REVISION_MAX, -}; - -extern int tegra_sku_id; -extern int tegra_cpu_process_id; -extern int tegra_core_process_id; -extern int tegra_chip_id; -extern int tegra_cpu_speedo_id; /* only exist in Tegra30 and later */ -extern int tegra_soc_speedo_id; -extern enum tegra_revision tegra_revision; - -extern int tegra_bct_strapping; - -unsigned long long tegra_chip_uid(void); -void tegra_init_fuse(void); -bool tegra_spare_fuse(int bit); -u32 tegra_fuse_readl(unsigned long offset); - -#ifdef CONFIG_ARCH_TEGRA_2x_SOC -void tegra20_init_speedo_data(void); -#else -static inline void tegra20_init_speedo_data(void) {} -#endif - -#ifdef CONFIG_ARCH_TEGRA_3x_SOC -void tegra30_init_speedo_data(void); -#else -static inline void tegra30_init_speedo_data(void) {} -#endif - -#ifdef CONFIG_ARCH_TEGRA_114_SOC -void tegra114_init_speedo_data(void); -#else -static inline void tegra114_init_speedo_data(void) {} -#endif -#endif /* __ASSEMBLY__ */ - -#endif diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c index ff26af26bd0c..6fc71f1534b0 100644 --- a/arch/arm/mach-tegra/hotplug.c +++ b/arch/arm/mach-tegra/hotplug.c @@ -7,13 +7,16 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ + +#include <linux/clk/tegra.h> #include <linux/kernel.h> #include <linux/smp.h> -#include <linux/clk/tegra.h> + +#include <soc/tegra/common.h> +#include <soc/tegra/fuse.h> #include <asm/smp_plat.h> -#include "fuse.h" #include "sleep.h" static void (*tegra_hotplug_shutdown)(void); @@ -36,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); @@ -46,17 +54,23 @@ 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 (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) + if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30) tegra_hotplug_shutdown = tegra30_hotplug_shutdown; - if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114) + if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114) tegra_hotplug_shutdown = tegra30_hotplug_shutdown; - if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_chip_id == TEGRA124) + 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); diff --git a/arch/arm/mach-tegra/io.c b/arch/arm/mach-tegra/io.c index bb9c9c29d181..352de159d2c5 100644 --- a/arch/arm/mach-tegra/io.c +++ b/arch/arm/mach-tegra/io.c @@ -18,14 +18,14 @@ * */ -#include <linux/kernel.h> -#include <linux/module.h> #include <linux/init.h> -#include <linux/mm.h> #include <linux/io.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/module.h> -#include <asm/page.h> #include <asm/mach/map.h> +#include <asm/page.h> #include "board.h" #include "iomap.h" diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index 1a74d562dca1..da7be13aecce 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c @@ -17,14 +17,14 @@ * */ -#include <linux/kernel.h> #include <linux/cpu_pm.h> #include <linux/interrupt.h> -#include <linux/irq.h> #include <linux/io.h> -#include <linux/of.h> -#include <linux/of_address.h> #include <linux/irqchip/arm-gic.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/of_address.h> +#include <linux/of.h> #include <linux/syscore_ops.h> #include "board.h" diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 929d1046e2b4..b45086666648 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -11,27 +11,28 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include <linux/init.h> -#include <linux/errno.h> + +#include <linux/clk/tegra.h> #include <linux/delay.h> #include <linux/device.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/io.h> #include <linux/jiffies.h> #include <linux/smp.h> -#include <linux/io.h> -#include <linux/clk/tegra.h> + +#include <soc/tegra/fuse.h> +#include <soc/tegra/pmc.h> #include <asm/cacheflush.h> #include <asm/mach-types.h> -#include <asm/smp_scu.h> #include <asm/smp_plat.h> - -#include "fuse.h" -#include "flowctrl.h" -#include "reset.h" -#include "pmc.h" +#include <asm/smp_scu.h> #include "common.h" +#include "flowctrl.h" #include "iomap.h" +#include "reset.h" static cpumask_t tegra_cpu_init_mask; @@ -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) { - if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20) + if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_get_chip_id() == TEGRA20) return tegra20_boot_secondary(cpu, idle); - if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30) + if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_get_chip_id() == TEGRA30) return tegra30_boot_secondary(cpu, idle); - if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114) + if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_get_chip_id() == TEGRA114) return tegra114_boot_secondary(cpu, idle); - if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_chip_id == TEGRA124) + if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_get_chip_id() == TEGRA124) return tegra114_boot_secondary(cpu, idle); return -EINVAL; diff --git a/arch/arm/mach-tegra/pm-tegra20.c b/arch/arm/mach-tegra/pm-tegra20.c index d65e1d786400..39ac2b723f2e 100644 --- a/arch/arm/mach-tegra/pm-tegra20.c +++ b/arch/arm/mach-tegra/pm-tegra20.c @@ -13,6 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + #include <linux/kernel.h> #include "pm.h" diff --git a/arch/arm/mach-tegra/pm-tegra30.c b/arch/arm/mach-tegra/pm-tegra30.c index 8fa326d6ff1a..46cc19de9916 100644 --- a/arch/arm/mach-tegra/pm-tegra30.c +++ b/arch/arm/mach-tegra/pm-tegra30.c @@ -13,6 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + #include <linux/kernel.h> #include "pm.h" diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index f55b05a29b55..b0f48a3946fa 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -16,30 +16,32 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <linux/kernel.h> -#include <linux/spinlock.h> -#include <linux/io.h> +#include <linux/clk/tegra.h> #include <linux/cpumask.h> -#include <linux/delay.h> #include <linux/cpu_pm.h> -#include <linux/suspend.h> +#include <linux/delay.h> #include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> #include <linux/slab.h> -#include <linux/clk/tegra.h> +#include <linux/spinlock.h> +#include <linux/suspend.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> -#include <asm/suspend.h> #include <asm/idmap.h> #include <asm/proc-fns.h> +#include <asm/smp_plat.h> +#include <asm/suspend.h> #include <asm/tlbflush.h> -#include "iomap.h" -#include "reset.h" #include "flowctrl.h" -#include "fuse.h" +#include "iomap.h" #include "pm.h" -#include "pmc.h" +#include "reset.h" #include "sleep.h" #ifdef CONFIG_PM_SLEEP @@ -53,7 +55,7 @@ static int (*tegra_sleep_func)(unsigned long v2p); static void tegra_tear_down_cpu_init(void) { - switch (tegra_chip_id) { + switch (tegra_get_chip_id()) { case TEGRA20: if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)) tegra_tear_down_cpu = tegra20_tear_down_cpu; @@ -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; - else if (tegra_chip_id == TEGRA20 && phy_cpu_id == 1) + else if (tegra_get_chip_id() == TEGRA20 && phy_cpu_id == 1) tegra20_cpu_set_resettable_soon(); spin_unlock(&tegra_lp2_lock); @@ -166,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(); @@ -212,7 +234,7 @@ static int tegra_sleep_core(unsigned long v2p) */ static bool tegra_lp1_iram_hook(void) { - switch (tegra_chip_id) { + switch (tegra_get_chip_id()) { case TEGRA20: if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)) tegra20_lp1_iram_hook(); @@ -242,7 +264,7 @@ static bool tegra_lp1_iram_hook(void) static bool tegra_sleep_core_init(void) { - switch (tegra_chip_id) { + switch (tegra_get_chip_id()) { case TEGRA20: if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)) tegra20_sleep_core_init(); @@ -267,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); @@ -280,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); @@ -306,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(); @@ -354,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()) { diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h index f4a89698e5b0..83bc87583446 100644 --- a/arch/arm/mach-tegra/pm.h +++ b/arch/arm/mach-tegra/pm.h @@ -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 diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c deleted file mode 100644 index 7c7123e7557b..000000000000 --- a/arch/arm/mach-tegra/pmc.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (C) 2012,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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <linux/kernel.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/tegra-powergate.h> - -#include "flowctrl.h" -#include "fuse.h" -#include "pm.h" -#include "pmc.h" -#include "sleep.h" - -#define TEGRA_POWER_SYSCLK_POLARITY (1 << 10) /* sys clk polarity */ -#define TEGRA_POWER_SYSCLK_OE (1 << 11) /* system clock enable */ -#define TEGRA_POWER_EFFECT_LP0 (1 << 14) /* LP0 when CPU pwr gated */ -#define TEGRA_POWER_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */ -#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */ - -#define PMC_CTRL 0x0 -#define PMC_CTRL_INTR_LOW (1 << 17) -#define PMC_PWRGATE_TOGGLE 0x30 -#define PMC_PWRGATE_TOGGLE_START (1 << 8) -#define PMC_REMOVE_CLAMPING 0x34 -#define PMC_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 - -static u8 tegra_cpu_domains[] = { - 0xFF, /* not available for CPU0 */ - TEGRA_POWERGATE_CPU1, - TEGRA_POWERGATE_CPU2, - TEGRA_POWERGATE_CPU3, -}; -static DEFINE_SPINLOCK(tegra_powergate_lock); - -static void __iomem *tegra_pmc_base; -static bool tegra_pmc_invert_interrupt; -static struct clk *tegra_pclk; - -struct pmc_pm_data { - u32 cpu_good_time; /* CPU power good time in uS */ - u32 cpu_off_time; /* CPU power off time in uS */ - u32 core_osc_time; /* Core power good osc time in uS */ - u32 core_pmu_time; /* Core power good pmu time in uS */ - u32 core_off_time; /* Core power off time in uS */ - bool corereq_high; /* Core power request active-high */ - bool sysclkreq_high; /* System clock request active-high */ - bool combined_req; /* Combined pwr req for CPU & Core */ - bool cpu_pwr_good_en; /* CPU power good signal is enabled */ - u32 lp0_vec_phy_addr; /* The phy addr of LP0 warm boot code */ - u32 lp0_vec_size; /* The size of LP0 warm boot code */ - enum tegra_suspend_mode suspend_mode; -}; -static struct pmc_pm_data pmc_pm_data; - -static inline u32 tegra_pmc_readl(u32 reg) -{ - return readl(tegra_pmc_base + reg); -} - -static inline void tegra_pmc_writel(u32 val, u32 reg) -{ - writel(val, tegra_pmc_base + reg); -} - -static int tegra_pmc_get_cpu_powerdomain_id(int cpuid) -{ - if (cpuid <= 0 || cpuid >= num_possible_cpus()) - return -EINVAL; - return tegra_cpu_domains[cpuid]; -} - -static bool tegra_pmc_powergate_is_powered(int id) -{ - return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1; -} - -static int tegra_pmc_powergate_set(int id, bool new_state) -{ - bool old_state; - unsigned long flags; - - spin_lock_irqsave(&tegra_powergate_lock, flags); - - old_state = tegra_pmc_powergate_is_powered(id); - WARN_ON(old_state == new_state); - - tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE); - - spin_unlock_irqrestore(&tegra_powergate_lock, flags); - - return 0; -} - -static int tegra_pmc_powergate_remove_clamping(int id) -{ - u32 mask; - - /* - * Tegra 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, PMC_REMOVE_CLAMPING); - - return 0; -} - -bool tegra_pmc_cpu_is_powered(int cpuid) -{ - int id; - - id = tegra_pmc_get_cpu_powerdomain_id(cpuid); - if (id < 0) - return false; - return tegra_pmc_powergate_is_powered(id); -} - -int tegra_pmc_cpu_power_on(int cpuid) -{ - int id; - - id = tegra_pmc_get_cpu_powerdomain_id(cpuid); - if (id < 0) - return id; - return tegra_pmc_powergate_set(id, true); -} - -int tegra_pmc_cpu_remove_clamping(int cpuid) -{ - int id; - - id = tegra_pmc_get_cpu_powerdomain_id(cpuid); - if (id < 0) - return id; - return tegra_pmc_powergate_remove_clamping(id); -} - -void tegra_pmc_restart(enum reboot_mode mode, const char *cmd) -{ - u32 val; - - val = tegra_pmc_readl(PMC_SCRATCH0); - val &= ~PMC_SCRATCH0_MODE_MASK; - - if (cmd) { - if (strcmp(cmd, "recovery") == 0) - val |= PMC_SCRATCH0_MODE_RECOVERY; - - if (strcmp(cmd, "bootloader") == 0) - val |= PMC_SCRATCH0_MODE_BOOTLOADER; - - if (strcmp(cmd, "forced-recovery") == 0) - val |= PMC_SCRATCH0_MODE_RCM; - } - - tegra_pmc_writel(val, PMC_SCRATCH0); - - val = tegra_pmc_readl(0); - val |= 0x10; - tegra_pmc_writel(val, 0); -} - -#ifdef CONFIG_PM_SLEEP -static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate) -{ - unsigned long long ticks; - unsigned long long pclk; - static unsigned long tegra_last_pclk; - - if (WARN_ON_ONCE(rate <= 0)) - pclk = 100000000; - else - pclk = rate; - - if ((rate != tegra_last_pclk)) { - ticks = (us_on * pclk) + 999999ull; - do_div(ticks, 1000000); - tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWRGOOD_TIMER); - - ticks = (us_off * pclk) + 999999ull; - do_div(ticks, 1000000); - tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWROFF_TIMER); - wmb(); - } - tegra_last_pclk = pclk; -} - -enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void) -{ - return pmc_pm_data.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_pm_data.suspend_mode = mode; -} - -void tegra_pmc_suspend(void) -{ - tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41); -} - -void tegra_pmc_resume(void) -{ - tegra_pmc_writel(0x0, PMC_SCRATCH41); -} - -void tegra_pmc_pm_set(enum tegra_suspend_mode mode) -{ - u32 reg, csr_reg; - unsigned long rate = 0; - - reg = tegra_pmc_readl(PMC_CTRL); - reg |= TEGRA_POWER_CPU_PWRREQ_OE; - reg &= ~TEGRA_POWER_EFFECT_LP0; - - switch (tegra_chip_id) { - case TEGRA20: - case TEGRA30: - break; - default: - /* Turn off CRAIL */ - csr_reg = flowctrl_read_cpu_csr(0); - csr_reg &= ~FLOW_CTRL_CSR_ENABLE_EXT_MASK; - csr_reg |= FLOW_CTRL_CSR_ENABLE_EXT_CRAIL; - flowctrl_write_cpu_csr(0, csr_reg); - break; - } - - switch (mode) { - case TEGRA_SUSPEND_LP1: - rate = 32768; - break; - case TEGRA_SUSPEND_LP2: - rate = clk_get_rate(tegra_pclk); - break; - default: - break; - } - - set_power_timers(pmc_pm_data.cpu_good_time, pmc_pm_data.cpu_off_time, - rate); - - tegra_pmc_writel(reg, PMC_CTRL); -} - -void tegra_pmc_suspend_init(void) -{ - u32 reg; - - /* Always enable CPU power request */ - reg = tegra_pmc_readl(PMC_CTRL); - reg |= TEGRA_POWER_CPU_PWRREQ_OE; - tegra_pmc_writel(reg, PMC_CTRL); - - reg = tegra_pmc_readl(PMC_CTRL); - - if (!pmc_pm_data.sysclkreq_high) - reg |= TEGRA_POWER_SYSCLK_POLARITY; - else - reg &= ~TEGRA_POWER_SYSCLK_POLARITY; - - /* configure the output polarity while the request is tristated */ - tegra_pmc_writel(reg, PMC_CTRL); - - /* now enable the request */ - reg |= TEGRA_POWER_SYSCLK_OE; - tegra_pmc_writel(reg, PMC_CTRL); -} -#endif - -static const struct of_device_id matches[] __initconst = { - { .compatible = "nvidia,tegra124-pmc" }, - { .compatible = "nvidia,tegra114-pmc" }, - { .compatible = "nvidia,tegra30-pmc" }, - { .compatible = "nvidia,tegra20-pmc" }, - { } -}; - -void __init tegra_pmc_init_irq(void) -{ - struct device_node *np; - u32 val; - - np = of_find_matching_node(NULL, matches); - BUG_ON(!np); - - tegra_pmc_base = of_iomap(np, 0); - - tegra_pmc_invert_interrupt = of_property_read_bool(np, - "nvidia,invert-interrupt"); - - val = tegra_pmc_readl(PMC_CTRL); - if (tegra_pmc_invert_interrupt) - val |= PMC_CTRL_INTR_LOW; - else - val &= ~PMC_CTRL_INTR_LOW; - tegra_pmc_writel(val, PMC_CTRL); -} - -void __init tegra_pmc_init(void) -{ - struct device_node *np; - u32 prop; - enum tegra_suspend_mode suspend_mode; - u32 core_good_time[2] = {0, 0}; - u32 lp0_vec[2] = {0, 0}; - - np = of_find_matching_node(NULL, matches); - BUG_ON(!np); - - tegra_pclk = of_clk_get_by_name(np, "pclk"); - WARN_ON(IS_ERR(tegra_pclk)); - - /* Grabbing the power management configurations */ - if (of_property_read_u32(np, "nvidia,suspend-mode", &prop)) { - suspend_mode = TEGRA_SUSPEND_NONE; - } else { - switch (prop) { - case 0: - suspend_mode = TEGRA_SUSPEND_LP0; - break; - case 1: - suspend_mode = TEGRA_SUSPEND_LP1; - break; - case 2: - suspend_mode = TEGRA_SUSPEND_LP2; - break; - default: - suspend_mode = TEGRA_SUSPEND_NONE; - break; - } - } - suspend_mode = tegra_pm_validate_suspend_mode(suspend_mode); - - if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &prop)) - suspend_mode = TEGRA_SUSPEND_NONE; - pmc_pm_data.cpu_good_time = prop; - - if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &prop)) - suspend_mode = TEGRA_SUSPEND_NONE; - pmc_pm_data.cpu_off_time = prop; - - if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time", - core_good_time, ARRAY_SIZE(core_good_time))) - suspend_mode = TEGRA_SUSPEND_NONE; - pmc_pm_data.core_osc_time = core_good_time[0]; - pmc_pm_data.core_pmu_time = core_good_time[1]; - - if (of_property_read_u32(np, "nvidia,core-pwr-off-time", - &prop)) - suspend_mode = TEGRA_SUSPEND_NONE; - pmc_pm_data.core_off_time = prop; - - pmc_pm_data.corereq_high = of_property_read_bool(np, - "nvidia,core-power-req-active-high"); - - pmc_pm_data.sysclkreq_high = of_property_read_bool(np, - "nvidia,sys-clock-req-active-high"); - - pmc_pm_data.combined_req = of_property_read_bool(np, - "nvidia,combined-power-req"); - - pmc_pm_data.cpu_pwr_good_en = of_property_read_bool(np, - "nvidia,cpu-pwr-good-en"); - - if (of_property_read_u32_array(np, "nvidia,lp0-vec", lp0_vec, - ARRAY_SIZE(lp0_vec))) - if (suspend_mode == TEGRA_SUSPEND_LP0) - suspend_mode = TEGRA_SUSPEND_LP1; - - pmc_pm_data.lp0_vec_phy_addr = lp0_vec[0]; - pmc_pm_data.lp0_vec_size = lp0_vec[1]; - - pmc_pm_data.suspend_mode = suspend_mode; -} diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h deleted file mode 100644 index 59e19c344298..000000000000 --- a/arch/arm/mach-tegra/pmc.h +++ /dev/null @@ -1,49 +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 __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 diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c deleted file mode 100644 index 4cefc5cd6bed..000000000000 --- a/arch/arm/mach-tegra/powergate.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - * drivers/powergate/tegra-powergate.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/debugfs.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/export.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/reset.h> -#include <linux/seq_file.h> -#include <linux/spinlock.h> -#include <linux/clk/tegra.h> -#include <linux/tegra-powergate.h> - -#include "fuse.h" -#include "iomap.h" - -#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 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 - -static int tegra_num_powerdomains; -static int tegra_num_cpu_domains; -static const u8 *tegra_cpu_domains; - -static const u8 tegra30_cpu_domains[] = { - TEGRA_POWERGATE_CPU, - TEGRA_POWERGATE_CPU1, - TEGRA_POWERGATE_CPU2, - TEGRA_POWERGATE_CPU3, -}; - -static const u8 tegra114_cpu_domains[] = { - TEGRA_POWERGATE_CPU0, - TEGRA_POWERGATE_CPU1, - TEGRA_POWERGATE_CPU2, - TEGRA_POWERGATE_CPU3, -}; - -static const u8 tegra124_cpu_domains[] = { - TEGRA_POWERGATE_CPU0, - TEGRA_POWERGATE_CPU1, - TEGRA_POWERGATE_CPU2, - TEGRA_POWERGATE_CPU3, -}; - -static DEFINE_SPINLOCK(tegra_powergate_lock); - -static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); - -static u32 pmc_read(unsigned long reg) -{ - return readl(pmc + reg); -} - -static void pmc_write(u32 val, unsigned long reg) -{ - writel(val, pmc + reg); -} - -static int tegra_powergate_set(int id, bool new_state) -{ - bool status; - unsigned long flags; - - spin_lock_irqsave(&tegra_powergate_lock, flags); - - status = pmc_read(PWRGATE_STATUS) & (1 << id); - - if (status == new_state) { - spin_unlock_irqrestore(&tegra_powergate_lock, flags); - return 0; - } - - pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); - - spin_unlock_irqrestore(&tegra_powergate_lock, flags); - - return 0; -} - -int tegra_powergate_power_on(int id) -{ - if (id < 0 || id >= tegra_num_powerdomains) - return -EINVAL; - - return tegra_powergate_set(id, true); -} - -int tegra_powergate_power_off(int id) -{ - if (id < 0 || id >= tegra_num_powerdomains) - return -EINVAL; - - return tegra_powergate_set(id, false); -} -EXPORT_SYMBOL(tegra_powergate_power_off); - -int tegra_powergate_is_powered(int id) -{ - u32 status; - - if (id < 0 || id >= tegra_num_powerdomains) - return -EINVAL; - - status = pmc_read(PWRGATE_STATUS) & (1 << id); - return !!status; -} - -int tegra_powergate_remove_clamping(int id) -{ - u32 mask; - - if (id < 0 || id >= tegra_num_powerdomains) - return -EINVAL; - - /* - * The Tegra124 GPU has a separate register (with different semantics) - * to remove clamps. - */ - if (tegra_chip_id == TEGRA124) { - if (id == TEGRA_POWERGATE_3D) { - pmc_write(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); - - pmc_write(mask, REMOVE_CLAMPING); - - return 0; -} -EXPORT_SYMBOL(tegra_powergate_remove_clamping); - -/* 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; - - udelay(10); - - ret = tegra_powergate_remove_clamping(id); - if (ret) - goto err_clamp; - - udelay(10); - 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); - -int tegra_cpu_powergate_id(int cpuid) -{ - if (cpuid > 0 && cpuid < tegra_num_cpu_domains) - return tegra_cpu_domains[cpuid]; - - return -EINVAL; -} - -int __init tegra_powergate_init(void) -{ - switch (tegra_chip_id) { - case TEGRA20: - tegra_num_powerdomains = 7; - break; - case TEGRA30: - tegra_num_powerdomains = 14; - tegra_num_cpu_domains = 4; - tegra_cpu_domains = tegra30_cpu_domains; - break; - case TEGRA114: - tegra_num_powerdomains = 23; - tegra_num_cpu_domains = 4; - tegra_cpu_domains = tegra114_cpu_domains; - break; - case TEGRA124: - tegra_num_powerdomains = 25; - tegra_num_cpu_domains = 4; - tegra_cpu_domains = tegra124_cpu_domains; - break; - default: - /* Unknown Tegra variant. Disable powergating */ - tegra_num_powerdomains = 0; - break; - } - - return 0; -} - -#ifdef CONFIG_DEBUG_FS - -static const char * const *powergate_name; - -static const char * const powergate_name_t20[] = { - [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 char * const powergate_name_t30[] = { - [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 char * const powergate_name_t114[] = { - [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 char * const powergate_name_t124[] = { - [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 int powergate_show(struct seq_file *s, void *data) -{ - int i; - - seq_printf(s, " powergate powered\n"); - seq_printf(s, "------------------\n"); - - for (i = 0; i < tegra_num_powerdomains; i++) { - if (!powergate_name[i]) - continue; - - seq_printf(s, " %9s %7s\n", powergate_name[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, -}; - -int __init tegra_powergate_debugfs_init(void) -{ - struct dentry *d; - - switch (tegra_chip_id) { - case TEGRA20: - powergate_name = powergate_name_t20; - break; - case TEGRA30: - powergate_name = powergate_name_t30; - break; - case TEGRA114: - powergate_name = powergate_name_t114; - break; - case TEGRA124: - powergate_name = powergate_name_t124; - break; - } - - if (powergate_name) { - d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL, - &powergate_fops); - if (!d) - return -ENOMEM; - } - - return 0; -} - -#endif - -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); - - pmc_write(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); - pmc_write(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 = pmc_read(offset); - if ((value & mask) == val) - return 0; - - usleep_range(250, 1000); - } - - return -ETIMEDOUT; -} - -static void tegra_io_rail_unprepare(void) -{ - pmc_write(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 = pmc_read(request); - value |= mask; - value &= ~IO_DPD_REQ_CODE_MASK; - value |= IO_DPD_REQ_CODE_OFF; - pmc_write(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 = pmc_read(request); - value |= mask; - value &= ~IO_DPD_REQ_CODE_MASK; - value |= IO_DPD_REQ_CODE_ON; - pmc_write(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); diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S index 578d4d1ad648..7b2baab0f0bd 100644 --- a/arch/arm/mach-tegra/reset-handler.S +++ b/arch/arm/mach-tegra/reset-handler.S @@ -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 <soc/tegra/fuse.h> -#include <asm/cache.h> #include <asm/asm-offsets.h> +#include <asm/cache.h> #include "flowctrl.h" -#include "fuse.h" #include "iomap.h" #include "reset.h" #include "sleep.h" diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c index 146fe8e0ae7c..894c5c472184 100644 --- a/arch/arm/mach-tegra/reset.c +++ b/arch/arm/mach-tegra/reset.c @@ -14,20 +14,21 @@ * */ +#include <linux/bitops.h> +#include <linux/cpumask.h> #include <linux/init.h> #include <linux/io.h> -#include <linux/cpumask.h> -#include <linux/bitops.h> + +#include <soc/tegra/fuse.h> #include <asm/cacheflush.h> -#include <asm/hardware/cache-l2x0.h> #include <asm/firmware.h> +#include <asm/hardware/cache-l2x0.h> #include "iomap.h" #include "irammap.h" #include "reset.h" #include "sleep.h" -#include "fuse.h" #define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \ TEGRA_IRAM_RESET_HANDLER_OFFSET) @@ -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. */ - if (tegra_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) diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S index aaaf3abd2688..be4bc5f853f5 100644 --- a/arch/arm/mach-tegra/sleep-tegra20.S +++ b/arch/arm/mach-tegra/sleep-tegra20.S @@ -78,7 +78,7 @@ ENTRY(tegra20_hotplug_shutdown) /* Put this CPU down */ cpu_id r0 bl tegra20_cpu_shutdown - mov pc, lr @ should never get here + ret lr @ should never get here ENDPROC(tegra20_hotplug_shutdown) /* @@ -96,7 +96,7 @@ ENDPROC(tegra20_hotplug_shutdown) */ ENTRY(tegra20_cpu_shutdown) cmp r0, #0 - moveq pc, lr @ must not be called for CPU 0 + reteq lr @ must not be called for CPU 0 mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 mov r12, #CPU_RESETTABLE str r12, [r1] @@ -117,7 +117,7 @@ ENTRY(tegra20_cpu_shutdown) cpu_id r3 cmp r3, r0 beq . - mov pc, lr + ret lr ENDPROC(tegra20_cpu_shutdown) #endif @@ -164,7 +164,7 @@ ENTRY(tegra_pen_lock) cmpeq r12, r0 @ !turn == cpu? beq 1b @ while !turn == cpu && flag[!cpu] == 1 - mov pc, lr @ locked + ret lr @ locked ENDPROC(tegra_pen_lock) ENTRY(tegra_pen_unlock) @@ -176,7 +176,7 @@ ENTRY(tegra_pen_unlock) addne r2, r3, #PMC_SCRATCH39 mov r12, #0 str r12, [r2] - mov pc, lr + ret lr ENDPROC(tegra_pen_unlock) /* @@ -189,7 +189,7 @@ ENTRY(tegra20_cpu_clear_resettable) mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 mov r12, #CPU_NOT_RESETTABLE str r12, [r1] - mov pc, lr + ret lr ENDPROC(tegra20_cpu_clear_resettable) /* @@ -202,7 +202,7 @@ ENTRY(tegra20_cpu_set_resettable_soon) mov32 r1, TEGRA_PMC_VIRT + PMC_SCRATCH41 mov r12, #CPU_RESETTABLE_SOON str r12, [r1] - mov pc, lr + ret lr ENDPROC(tegra20_cpu_set_resettable_soon) /* @@ -217,7 +217,7 @@ ENTRY(tegra20_cpu_is_resettable_soon) cmp r12, #CPU_RESETTABLE_SOON moveq r0, #1 movne r0, #0 - mov pc, lr + ret lr ENDPROC(tegra20_cpu_is_resettable_soon) /* @@ -239,7 +239,7 @@ ENTRY(tegra20_sleep_core_finish) mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA add r0, r0, r1 - mov pc, r3 + ret r3 ENDPROC(tegra20_sleep_core_finish) /* @@ -402,7 +402,7 @@ exit_selfrefresh_loop: mov32 r0, TEGRA_PMC_BASE ldr r0, [r0, #PMC_SCRATCH41] - mov pc, r0 @ jump to tegra_resume + ret r0 @ jump to tegra_resume ENDPROC(tegra20_lp1_reset) /* @@ -455,7 +455,7 @@ tegra20_switch_cpu_to_clk32k: mov r0, #0 /* brust policy = 32KHz */ str r0, [r5, #CLK_RESET_SCLK_BURST] - mov pc, lr + ret lr /* * tegra20_enter_sleep @@ -535,7 +535,7 @@ padsave_done: adr r2, tegra20_sclk_save str r0, [r2] dsb - mov pc, lr + ret lr tegra20_sdram_pad_address: .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S index b16d4a57fa59..5d8d13aeab93 100644 --- a/arch/arm/mach-tegra/sleep-tegra30.S +++ b/arch/arm/mach-tegra/sleep-tegra30.S @@ -16,14 +16,15 @@ #include <linux/linkage.h> -#include <asm/assembler.h> +#include <soc/tegra/fuse.h> + #include <asm/asm-offsets.h> +#include <asm/assembler.h> #include <asm/cache.h> +#include "flowctrl.h" #include "irammap.h" -#include "fuse.h" #include "sleep.h" -#include "flowctrl.h" #define EMC_CFG 0xc #define EMC_ADR_CFG 0x10 @@ -142,7 +143,7 @@ ENTRY(tegra30_hotplug_shutdown) /* Powergate this CPU */ mov r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN bl tegra30_cpu_shutdown - mov pc, lr @ should never get here + ret lr @ should never get here ENDPROC(tegra30_hotplug_shutdown) /* @@ -161,7 +162,7 @@ ENTRY(tegra30_cpu_shutdown) bne _no_cpu0_chk @ It's not Tegra30 cmp r3, #0 - moveq pc, lr @ Must never be called for CPU 0 + reteq lr @ Must never be called for CPU 0 _no_cpu0_chk: ldr r12, =TEGRA_FLOW_CTRL_VIRT @@ -266,7 +267,7 @@ ENTRY(tegra30_sleep_core_finish) mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA add r0, r0, r1 - mov pc, r3 + ret r3 ENDPROC(tegra30_sleep_core_finish) /* @@ -285,7 +286,7 @@ ENTRY(tegra30_sleep_cpu_secondary_finish) mov r0, #0 @ power mode flags (!hotplug) bl tegra30_cpu_shutdown mov r0, #1 @ never return here - mov pc, r7 + ret r7 ENDPROC(tegra30_sleep_cpu_secondary_finish) /* @@ -529,7 +530,7 @@ __no_dual_emc_chanl: mov32 r0, TEGRA_PMC_BASE ldr r0, [r0, #PMC_SCRATCH41] - mov pc, r0 @ jump to tegra_resume + ret r0 @ jump to tegra_resume ENDPROC(tegra30_lp1_reset) .align L1_CACHE_SHIFT @@ -659,7 +660,7 @@ _no_pll_in_iddq: mov r0, #0 /* brust policy = 32KHz */ str r0, [r5, #CLK_RESET_SCLK_BURST] - mov pc, lr + ret lr /* * tegra30_enter_sleep @@ -819,7 +820,7 @@ pmc_io_dpd_skip: dsb - mov pc, lr + ret lr .ltorg /* dummy symbol for end of IRAM */ diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S index 8d06213fbc47..f024a5109e8e 100644 --- a/arch/arm/mach-tegra/sleep.S +++ b/arch/arm/mach-tegra/sleep.S @@ -87,7 +87,7 @@ ENTRY(tegra_init_l2_for_a15) mcrne p15, 0x1, r0, c9, c0, 2 _exit_init_l2_a15: - mov pc, lr + ret lr ENDPROC(tegra_init_l2_for_a15) /* @@ -111,7 +111,7 @@ ENTRY(tegra_sleep_cpu_finish) add r3, r3, r0 mov r0, r1 - mov pc, r3 + ret r3 ENDPROC(tegra_sleep_cpu_finish) /* @@ -139,7 +139,7 @@ ENTRY(tegra_shut_off_mmu) moveq r3, #0 streq r3, [r2, #L2X0_CTRL] #endif - mov pc, r0 + ret r0 ENDPROC(tegra_shut_off_mmu) .popsection @@ -156,6 +156,6 @@ ENTRY(tegra_switch_cpu_to_pllp) str r0, [r5, #CLK_RESET_CCLK_BURST] mov r0, #0 str r0, [r5, #CLK_RESET_CCLK_DIVIDER] - mov pc, lr + ret lr ENDPROC(tegra_switch_cpu_to_pllp) #endif diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h index 339fe42cd6fb..92d46ec1361a 100644 --- a/arch/arm/mach-tegra/sleep.h +++ b/arch/arm/mach-tegra/sleep.h @@ -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); diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 15ac9fcc96b1..5ef5173dec83 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -16,40 +16,40 @@ * */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/serial_8250.h> #include <linux/clk.h> +#include <linux/clk/tegra.h> #include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/irqchip.h> #include <linux/irqdomain.h> -#include <linux/of.h> +#include <linux/kernel.h> #include <linux/of_address.h> #include <linux/of_fdt.h> +#include <linux/of.h> #include <linux/of_platform.h> #include <linux/pda_power.h> -#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/serial_8250.h> #include <linux/slab.h> #include <linux/sys_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> #include <asm/mach/arch.h> #include <asm/mach/time.h> +#include <asm/mach-types.h> #include <asm/setup.h> #include <asm/trusted_foundations.h> -#include "apbio.h" #include "board.h" #include "common.h" #include "cpuidle.h" -#include "fuse.h" #include "iomap.h" #include "irq.h" -#include "pmc.h" #include "pm.h" #include "reset.h" #include "sleep.h" @@ -73,16 +73,11 @@ u32 tegra_uart_config[3] = { static void __init tegra_init_early(void) { of_register_trusted_foundations(); - tegra_apb_io_init(); - 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(); @@ -94,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); @@ -103,8 +96,9 @@ static void __init tegra_dt_init(void) goto out; soc_dev_attr->family = kasprintf(GFP_KERNEL, "Tegra"); - soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_revision); - soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", tegra_chip_id); + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d", + tegra_sku_info.revision); + soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id()); soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR(soc_dev)) { @@ -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)) { diff --git a/arch/arm/mach-tegra/tegra114_speedo.c b/arch/arm/mach-tegra/tegra114_speedo.c deleted file mode 100644 index 5218d4853cd3..000000000000 --- a/arch/arm/mach-tegra/tegra114_speedo.c +++ /dev/null @@ -1,104 +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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/kernel.h> -#include <linux/bug.h> - -#include "fuse.h" - -#define CORE_PROCESS_CORNERS_NUM 2 -#define CPU_PROCESS_CORNERS_NUM 2 - -enum { - THRESHOLD_INDEX_0, - THRESHOLD_INDEX_1, - THRESHOLD_INDEX_COUNT, -}; - -static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = { - {1123, UINT_MAX}, - {0, UINT_MAX}, -}; - -static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = { - {1695, UINT_MAX}, - {0, UINT_MAX}, -}; - -static void rev_sku_to_speedo_ids(int rev, int sku, int *threshold) -{ - u32 tmp; - - switch (sku) { - case 0x00: - case 0x10: - case 0x05: - case 0x06: - tegra_cpu_speedo_id = 1; - tegra_soc_speedo_id = 0; - *threshold = THRESHOLD_INDEX_0; - break; - - case 0x03: - case 0x04: - tegra_cpu_speedo_id = 2; - tegra_soc_speedo_id = 1; - *threshold = THRESHOLD_INDEX_1; - break; - - default: - pr_err("Tegra114 Unknown SKU %d\n", sku); - tegra_cpu_speedo_id = 0; - tegra_soc_speedo_id = 0; - *threshold = THRESHOLD_INDEX_0; - break; - } - - if (rev == TEGRA_REVISION_A01) { - tmp = tegra_fuse_readl(0x270) << 1; - tmp |= tegra_fuse_readl(0x26c); - if (!tmp) - tegra_cpu_speedo_id = 0; - } -} - -void tegra114_init_speedo_data(void) -{ - u32 cpu_speedo_val; - u32 core_speedo_val; - int threshold; - int i; - - BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != - THRESHOLD_INDEX_COUNT); - BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != - THRESHOLD_INDEX_COUNT); - - rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id, &threshold); - - cpu_speedo_val = tegra_fuse_readl(0x12c) + 1024; - core_speedo_val = tegra_fuse_readl(0x134); - - for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) - if (cpu_speedo_val < cpu_process_speedos[threshold][i]) - break; - tegra_cpu_process_id = i; - - for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) - if (core_speedo_val < core_process_speedos[threshold][i]) - break; - tegra_core_process_id = i; -} diff --git a/arch/arm/mach-tegra/tegra20_speedo.c b/arch/arm/mach-tegra/tegra20_speedo.c deleted file mode 100644 index fa6eb570623f..000000000000 --- a/arch/arm/mach-tegra/tegra20_speedo.c +++ /dev/null @@ -1,109 +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/>. - */ - -#include <linux/kernel.h> -#include <linux/bug.h> - -#include "fuse.h" - -#define CPU_SPEEDO_LSBIT 20 -#define CPU_SPEEDO_MSBIT 29 -#define CPU_SPEEDO_REDUND_LSBIT 30 -#define CPU_SPEEDO_REDUND_MSBIT 39 -#define CPU_SPEEDO_REDUND_OFFS (CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT) - -#define CORE_SPEEDO_LSBIT 40 -#define CORE_SPEEDO_MSBIT 47 -#define CORE_SPEEDO_REDUND_LSBIT 48 -#define CORE_SPEEDO_REDUND_MSBIT 55 -#define CORE_SPEEDO_REDUND_OFFS (CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT) - -#define SPEEDO_MULT 4 - -#define PROCESS_CORNERS_NUM 4 - -#define SPEEDO_ID_SELECT_0(rev) ((rev) <= 2) -#define SPEEDO_ID_SELECT_1(sku) \ - (((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \ - ((sku) != 27) && ((sku) != 28)) - -enum { - SPEEDO_ID_0, - SPEEDO_ID_1, - SPEEDO_ID_2, - SPEEDO_ID_COUNT, -}; - -static const u32 cpu_process_speedos[][PROCESS_CORNERS_NUM] = { - {315, 366, 420, UINT_MAX}, - {303, 368, 419, UINT_MAX}, - {316, 331, 383, UINT_MAX}, -}; - -static const u32 core_process_speedos[][PROCESS_CORNERS_NUM] = { - {165, 195, 224, UINT_MAX}, - {165, 195, 224, UINT_MAX}, - {165, 195, 224, UINT_MAX}, -}; - -void tegra20_init_speedo_data(void) -{ - u32 reg; - u32 val; - int i; - - BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT); - BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != SPEEDO_ID_COUNT); - - if (SPEEDO_ID_SELECT_0(tegra_revision)) - tegra_soc_speedo_id = SPEEDO_ID_0; - else if (SPEEDO_ID_SELECT_1(tegra_sku_id)) - tegra_soc_speedo_id = SPEEDO_ID_1; - else - tegra_soc_speedo_id = SPEEDO_ID_2; - - val = 0; - for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) { - reg = tegra_spare_fuse(i) | - tegra_spare_fuse(i + CPU_SPEEDO_REDUND_OFFS); - val = (val << 1) | (reg & 0x1); - } - val = val * SPEEDO_MULT; - pr_debug("%s CPU speedo value %u\n", __func__, val); - - for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) { - if (val <= cpu_process_speedos[tegra_soc_speedo_id][i]) - break; - } - tegra_cpu_process_id = i; - - val = 0; - for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) { - reg = tegra_spare_fuse(i) | - tegra_spare_fuse(i + CORE_SPEEDO_REDUND_OFFS); - val = (val << 1) | (reg & 0x1); - } - val = val * SPEEDO_MULT; - pr_debug("%s Core speedo value %u\n", __func__, val); - - for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) { - if (val <= core_process_speedos[tegra_soc_speedo_id][i]) - break; - } - tegra_core_process_id = i; - - pr_info("Tegra20 Soc Speedo ID %d", tegra_soc_speedo_id); -} diff --git a/arch/arm/mach-tegra/tegra30_speedo.c b/arch/arm/mach-tegra/tegra30_speedo.c deleted file mode 100644 index 125cb16424a6..000000000000 --- a/arch/arm/mach-tegra/tegra30_speedo.c +++ /dev/null @@ -1,292 +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/>. - */ - -#include <linux/kernel.h> -#include <linux/bug.h> - -#include "fuse.h" - -#define CORE_PROCESS_CORNERS_NUM 1 -#define CPU_PROCESS_CORNERS_NUM 6 - -#define FUSE_SPEEDO_CALIB_0 0x114 -#define FUSE_PACKAGE_INFO 0X1FC -#define FUSE_TEST_PROG_VER 0X128 - -#define G_SPEEDO_BIT_MINUS1 58 -#define G_SPEEDO_BIT_MINUS1_R 59 -#define G_SPEEDO_BIT_MINUS2 60 -#define G_SPEEDO_BIT_MINUS2_R 61 -#define LP_SPEEDO_BIT_MINUS1 62 -#define LP_SPEEDO_BIT_MINUS1_R 63 -#define LP_SPEEDO_BIT_MINUS2 64 -#define LP_SPEEDO_BIT_MINUS2_R 65 - -enum { - THRESHOLD_INDEX_0, - THRESHOLD_INDEX_1, - THRESHOLD_INDEX_2, - THRESHOLD_INDEX_3, - THRESHOLD_INDEX_4, - THRESHOLD_INDEX_5, - THRESHOLD_INDEX_6, - THRESHOLD_INDEX_7, - THRESHOLD_INDEX_8, - THRESHOLD_INDEX_9, - THRESHOLD_INDEX_10, - THRESHOLD_INDEX_11, - THRESHOLD_INDEX_COUNT, -}; - -static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = { - {180}, - {170}, - {195}, - {180}, - {168}, - {192}, - {180}, - {170}, - {195}, - {180}, - {180}, - {180}, -}; - -static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = { - {306, 338, 360, 376, UINT_MAX}, - {295, 336, 358, 375, UINT_MAX}, - {325, 325, 358, 375, UINT_MAX}, - {325, 325, 358, 375, UINT_MAX}, - {292, 324, 348, 364, UINT_MAX}, - {324, 324, 348, 364, UINT_MAX}, - {324, 324, 348, 364, UINT_MAX}, - {295, 336, 358, 375, UINT_MAX}, - {358, 358, 358, 358, 397, UINT_MAX}, - {364, 364, 364, 364, 397, UINT_MAX}, - {295, 336, 358, 375, 391, UINT_MAX}, - {295, 336, 358, 375, 391, UINT_MAX}, -}; - -static int threshold_index; -static int package_id; - -static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp) -{ - u32 reg; - int ate_ver; - int bit_minus1; - int bit_minus2; - - reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0); - - *speedo_lp = (reg & 0xFFFF) * 4; - *speedo_g = ((reg >> 16) & 0xFFFF) * 4; - - ate_ver = tegra_fuse_readl(FUSE_TEST_PROG_VER); - pr_info("%s: ATE prog ver %d.%d\n", __func__, ate_ver/10, ate_ver%10); - - if (ate_ver >= 26) { - bit_minus1 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1); - bit_minus1 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1_R); - bit_minus2 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2); - bit_minus2 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2_R); - *speedo_lp |= (bit_minus1 << 1) | bit_minus2; - - bit_minus1 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS1); - bit_minus1 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS1_R); - bit_minus2 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS2); - bit_minus2 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS2_R); - *speedo_g |= (bit_minus1 << 1) | bit_minus2; - } else { - *speedo_lp |= 0x3; - *speedo_g |= 0x3; - } -} - -static void rev_sku_to_speedo_ids(int rev, int sku) -{ - switch (rev) { - case TEGRA_REVISION_A01: - tegra_cpu_speedo_id = 0; - tegra_soc_speedo_id = 0; - threshold_index = THRESHOLD_INDEX_0; - break; - case TEGRA_REVISION_A02: - case TEGRA_REVISION_A03: - switch (sku) { - case 0x87: - case 0x82: - tegra_cpu_speedo_id = 1; - tegra_soc_speedo_id = 1; - threshold_index = THRESHOLD_INDEX_1; - break; - case 0x81: - switch (package_id) { - case 1: - tegra_cpu_speedo_id = 2; - tegra_soc_speedo_id = 2; - threshold_index = THRESHOLD_INDEX_2; - break; - case 2: - tegra_cpu_speedo_id = 4; - tegra_soc_speedo_id = 1; - threshold_index = THRESHOLD_INDEX_7; - break; - default: - pr_err("Tegra30: Unknown pkg %d\n", package_id); - BUG(); - break; - } - break; - case 0x80: - switch (package_id) { - case 1: - tegra_cpu_speedo_id = 5; - tegra_soc_speedo_id = 2; - threshold_index = THRESHOLD_INDEX_8; - break; - case 2: - tegra_cpu_speedo_id = 6; - tegra_soc_speedo_id = 2; - threshold_index = THRESHOLD_INDEX_9; - break; - default: - pr_err("Tegra30: Unknown pkg %d\n", package_id); - BUG(); - break; - } - break; - case 0x83: - switch (package_id) { - case 1: - tegra_cpu_speedo_id = 7; - tegra_soc_speedo_id = 1; - threshold_index = THRESHOLD_INDEX_10; - break; - case 2: - tegra_cpu_speedo_id = 3; - tegra_soc_speedo_id = 2; - threshold_index = THRESHOLD_INDEX_3; - break; - default: - pr_err("Tegra30: Unknown pkg %d\n", package_id); - BUG(); - break; - } - break; - case 0x8F: - tegra_cpu_speedo_id = 8; - tegra_soc_speedo_id = 1; - threshold_index = THRESHOLD_INDEX_11; - break; - case 0x08: - tegra_cpu_speedo_id = 1; - tegra_soc_speedo_id = 1; - threshold_index = THRESHOLD_INDEX_4; - break; - case 0x02: - tegra_cpu_speedo_id = 2; - tegra_soc_speedo_id = 2; - threshold_index = THRESHOLD_INDEX_5; - break; - case 0x04: - tegra_cpu_speedo_id = 3; - tegra_soc_speedo_id = 2; - threshold_index = THRESHOLD_INDEX_6; - break; - case 0: - switch (package_id) { - case 1: - tegra_cpu_speedo_id = 2; - tegra_soc_speedo_id = 2; - threshold_index = THRESHOLD_INDEX_2; - break; - case 2: - tegra_cpu_speedo_id = 3; - tegra_soc_speedo_id = 2; - threshold_index = THRESHOLD_INDEX_3; - break; - default: - pr_err("Tegra30: Unknown pkg %d\n", package_id); - BUG(); - break; - } - break; - default: - pr_warn("Tegra30: Unknown SKU %d\n", sku); - tegra_cpu_speedo_id = 0; - tegra_soc_speedo_id = 0; - threshold_index = THRESHOLD_INDEX_0; - break; - } - break; - default: - pr_warn("Tegra30: Unknown chip rev %d\n", rev); - tegra_cpu_speedo_id = 0; - tegra_soc_speedo_id = 0; - threshold_index = THRESHOLD_INDEX_0; - break; - } -} - -void tegra30_init_speedo_data(void) -{ - u32 cpu_speedo_val; - u32 core_speedo_val; - int i; - - BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != - THRESHOLD_INDEX_COUNT); - BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != - THRESHOLD_INDEX_COUNT); - - package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F; - - rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id); - fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val); - pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val); - pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val); - - for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) { - if (cpu_speedo_val < cpu_process_speedos[threshold_index][i]) - break; - } - tegra_cpu_process_id = i - 1; - - if (tegra_cpu_process_id == -1) { - pr_warn("Tegra30: CPU speedo value %3d out of range", - cpu_speedo_val); - tegra_cpu_process_id = 0; - tegra_cpu_speedo_id = 1; - } - - for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) { - if (core_speedo_val < core_process_speedos[threshold_index][i]) - break; - } - tegra_core_process_id = i - 1; - - if (tegra_core_process_id == -1) { - pr_warn("Tegra30: CORE speedo value %3d out of range", - core_speedo_val); - tegra_core_process_id = 0; - tegra_soc_speedo_id = 1; - } - - pr_info("Tegra30: CPU Speedo ID %d, Soc Speedo ID %d", - tegra_cpu_speedo_id, tegra_soc_speedo_id); -} |