diff options
author | Alex Frid <afrid@nvidia.com> | 2010-12-13 11:57:12 -0800 |
---|---|---|
committer | Bharat Nihalani <bnihalani@nvidia.com> | 2010-12-16 02:05:56 -0800 |
commit | 59d05a32b0c86672259dbb0f8eefce6d663d6bfc (patch) | |
tree | 417a38ab906501376ee6f05331e59984713b64f7 /arch | |
parent | 51137becfb544f2569d6cc9130f395f7f1aef93c (diff) |
ARM: tegra: Add speedo-based process identification
Change-Id: If6cd2914551331bd49b128ad3143a0d7adf0f120
Reviewed-on: http://git-master/r/13396
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/fuse.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-tegra/fuse.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_speedo.c | 140 |
4 files changed, 144 insertions, 20 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 347445b24d80..f0f46267ccc8 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_dvfs.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_fuse.o +obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_speedo.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += suspend-t2.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_save.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c index c2b348c53b25..c016127cbaea 100644 --- a/arch/arm/mach-tegra/fuse.c +++ b/arch/arm/mach-tegra/fuse.c @@ -141,10 +141,7 @@ void tegra_init_fuse(void) u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); reg |= 1 << 28; writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48)); - - pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n", - tegra_sku_id(), tegra_cpu_process_id(), - tegra_core_process_id()); + tegra_init_speedo_data(); } void tegra_init_fuse_dma(void) @@ -190,19 +187,3 @@ int tegra_sku_id(void) sku_id = reg & 0xFF; return sku_id; } - -int tegra_cpu_process_id(void) -{ - int cpu_process_id; - u32 reg = fuse_readl(FUSE_SPARE_BIT); - cpu_process_id = (reg >> 6) & 3; - return cpu_process_id; -} - -int tegra_core_process_id(void) -{ - int core_process_id; - u32 reg = fuse_readl(FUSE_SPARE_BIT); - core_process_id = (reg >> 12) & 3; - return core_process_id; -} diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h index 4e6947a7b8ae..1ea70b956a33 100644 --- a/arch/arm/mach-tegra/fuse.h +++ b/arch/arm/mach-tegra/fuse.h @@ -22,7 +22,9 @@ unsigned int tegra_spare_fuse(int bit); int tegra_sku_id(void); int tegra_cpu_process_id(void); int tegra_core_process_id(void); +int tegra_soc_speedo_id(void); void tegra_init_fuse(void); void tegra_init_fuse_dma(void); +void tegra_init_speedo_data(void); u32 tegra_fuse_readl(unsigned long offset); void tegra_fuse_writel(u32 value, unsigned long offset); diff --git a/arch/arm/mach-tegra/tegra2_speedo.c b/arch/arm/mach-tegra/tegra2_speedo.c new file mode 100644 index 000000000000..1e5fa26a5c41 --- /dev/null +++ b/arch/arm/mach-tegra/tegra2_speedo.c @@ -0,0 +1,140 @@ +/* + * arch/arm/mach-tegra/tegra2_speedo.c + * + * Copyright (c) 2010, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/err.h> + +#include <mach/iomap.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 CHIP_ID 0x804 +#define CHIP_MINOR_SHIFT 16 +#define CHIP_MINOR_MASK (0xF << CHIP_MINOR_SHIFT) + +#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)) + +/* Maximum speedo levels for each CPU process corner */ +static const u32 cpu_process_speedos[][PROCESS_CORNERS_NUM] = { +/* proc_id 0 1 2 3 */ + {315, 366, 420, UINT_MAX}, /* speedo_id 0 */ + {303, 368, 419, UINT_MAX}, /* speedo_id 1 */ + {316, 331, 383, UINT_MAX}, /* speedo_id 2 */ +}; + +/* Maximum speedo levels for each core process corner */ +static const u32 core_process_speedos[][PROCESS_CORNERS_NUM] = { +/* proc_id 0 1 2 3 */ + {165, 195, 224, UINT_MAX}, /* speedo_id 0 */ + {165, 195, 224, UINT_MAX}, /* speedo_id 1 */ + {165, 195, 224, UINT_MAX}, /* speedo_id 2 */ +}; + +static int cpu_process_id; +static int core_process_id; +static int soc_speedo_id; + +void tegra_init_speedo_data(void) +{ + u32 reg, val; + int i, bit, rev; + int sku = tegra_sku_id(); + void __iomem *apb_misc = IO_ADDRESS(TEGRA_APB_MISC_BASE); + + reg = readl(apb_misc + CHIP_ID); + rev = (reg & CHIP_MINOR_MASK) >> CHIP_MINOR_SHIFT; + if (SPEEDO_ID_SELECT_0(rev)) + soc_speedo_id = 0; + else if (SPEEDO_ID_SELECT_1(sku)) + soc_speedo_id = 1; + else + soc_speedo_id = 2; + BUG_ON(soc_speedo_id >= ARRAY_SIZE(cpu_process_speedos)); + BUG_ON(soc_speedo_id >= ARRAY_SIZE(core_process_speedos)); + + val = 0; + for (bit = CPU_SPEEDO_MSBIT; bit >= CPU_SPEEDO_LSBIT; bit--) { + reg = tegra_spare_fuse(bit) | + tegra_spare_fuse(bit + CPU_SPEEDO_REDUND_OFFS); + val = (val << 1) | (reg & 0x1); + } + val = val * SPEEDO_MULT; + pr_debug("%s CPU speedo level %u\n", __func__, val); + + for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) { + if (val <= cpu_process_speedos[soc_speedo_id][i]) + break; + } + cpu_process_id = i; + + val = 0; + for (bit = CORE_SPEEDO_MSBIT; bit >= CORE_SPEEDO_LSBIT; bit--) { + reg = tegra_spare_fuse(bit) | + tegra_spare_fuse(bit + CORE_SPEEDO_REDUND_OFFS); + val = (val << 1) | (reg & 0x1); + } + val = val * SPEEDO_MULT; + pr_debug("%s Core speedo level %u\n", __func__, val); + + for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) { + if (val <= core_process_speedos[soc_speedo_id][i]) + break; + } + core_process_id = i; + + pr_info("Tegra SKU: %d Rev: A%.2d CPU Process: %d Core Process: %d" + " Speedo ID: %d\n", sku, rev, cpu_process_id, core_process_id, + soc_speedo_id); +} + +int tegra_cpu_process_id(void) +{ + return cpu_process_id; +} + +int tegra_core_process_id(void) +{ + return core_process_id; +} + +int tegra_soc_speedo_id(void) +{ + return soc_speedo_id; +} |