diff options
author | Diwakar Tundlam <dtundlam@nvidia.com> | 2011-04-29 14:47:54 -0700 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-05-11 15:12:37 -0700 |
commit | 8633e7c09f6a701765607d98e4dbcdf4528b16bb (patch) | |
tree | d632e505590ea991d49d61fb33033f2ed3fa84ad /arch/arm/mach-tegra/tegra3_speedo.c | |
parent | 568f5b9eb55afed6ec48bddb3d14e807bc0e8d05 (diff) |
ARM: tegra: power: speedo, cpu, core process ids for tegra3
Change-Id: If206f26e0f10f666fd7839c1ebb839eeb4899e21
Reviewed-on: http://git-master/r/29879
Reviewed-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Tested-by: Diwakar Tundlam <dtundlam@nvidia.com>
Reviewed-by: Scott Williams <scwilliams@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra3_speedo.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra3_speedo.c | 132 |
1 files changed, 126 insertions, 6 deletions
diff --git a/arch/arm/mach-tegra/tegra3_speedo.c b/arch/arm/mach-tegra/tegra3_speedo.c index c5544d6d3ec1..6377b9347dd9 100644 --- a/arch/arm/mach-tegra/tegra3_speedo.c +++ b/arch/arm/mach-tegra/tegra3_speedo.c @@ -21,30 +21,150 @@ #include <linux/kernel.h> #include <linux/io.h> #include <linux/err.h> - #include <mach/iomap.h> #include "fuse.h" +#define PROCESS_CORNERS_NUM 4 + +#define FUSE_SPEEDO_CALIB_0 0x114 + +/* Maximum speedo levels for each core process corner */ +static const u32 core_process_speedos[][PROCESS_CORNERS_NUM] = { +// proc_id 0 1 + {180, 240}, // soc_speedo_id 0 + {180, 240}, // soc_speedo_id 1 + {200, 240}, // soc_speedo_id 2 +}; + +/* Maximum speedo levels for each CPU process corner */ +static const u32 cpu_process_speedos[][PROCESS_CORNERS_NUM] = { +// proc_id 0 1 2 3 + {305, 337, 360, 376}, // soc_speedo_id 0 + {337, 337, 360, 376}, // soc_speedo_id 1 + {305, 337, 360, 376}, // soc_speedo_id 2 +}; + static int cpu_process_id; static int core_process_id; static int soc_speedo_id; +static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp) +{ + u32 reg; + + BUG_ON(!speedo_g || !speedo_lp); + reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0); + + // Speedo LP = Lower 16-bits Multiplied by 4 + *speedo_lp = (reg & 0xFFFF) * 4; + + // Speedo G = Upper 16-bits Multiplied by 4 + *speedo_g = ((reg >> 16) & 0xFFFF) * 4; +} + +static int rev_sku_to_soc_speedo(int rev, int sku) +{ + int soc_speedo; + + switch (rev) { + case TEGRA_REVISION_A01: + soc_speedo = 0; + break; + case TEGRA_REVISION_A02: + switch (sku) { + case 0: // AP30 + soc_speedo = 1; + break; + case 1: // T30 + soc_speedo = 2; + break; + default: + BUG(); + break; + } + break; + default: + BUG(); + break; + } + + pr_debug("Tegra3 SKU: %d Rev: %s Speedo: %d ", + sku, tegra_get_revision_name(), soc_speedo); + return soc_speedo; +} + void tegra_init_speedo_data(void) { - cpu_process_id = 0; - core_process_id = 0; - soc_speedo_id = 0; + u32 cpu_speedo_val, core_speedo_val; + int iv; + + soc_speedo_id = rev_sku_to_soc_speedo(tegra_get_revision(), + tegra_sku_id()); + BUG_ON(soc_speedo_id >= ARRAY_SIZE(cpu_process_speedos)); + + 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); + + cpu_process_id = -1; // out of range for valid cpu-speedo + for (iv = 0; iv < PROCESS_CORNERS_NUM; iv++) { + if (cpu_speedo_val < cpu_process_speedos[soc_speedo_id][iv]) { + cpu_process_id = iv -1; + break; + } + } + if (cpu_process_id == -1) { + pr_err("****************************************************"); + pr_err("****************************************************"); + pr_err("* tegra3_speedo: CPU speedo value %3d out of range *", + cpu_speedo_val); + pr_err("****************************************************"); + pr_err("****************************************************"); + + cpu_process_id = INVALID_PROCESS_ID; + } + + core_process_id = -1; // out of range for valid core-speedo + for (iv = 0; iv < PROCESS_CORNERS_NUM; iv++) { + if (core_speedo_val < core_process_speedos[soc_speedo_id][iv]) { + core_process_id = iv -1; + break; + } + } + if (core_process_id == -1) { + pr_err("*****************************************************"); + pr_err("*****************************************************"); + pr_err("* tegra3_speedo: CORE speedo value %3d out of range *", + core_speedo_val); + pr_err("*****************************************************"); + pr_err("*****************************************************"); + + core_process_id = INVALID_PROCESS_ID; + } + + pr_info("Tegra3 SKU: %d Rev: %s CPU Process: %d CORE Process: %d " + "Speedo ID: %d", + tegra_sku_id(), tegra_get_revision_name(), + cpu_process_id, core_process_id, soc_speedo_id); } int tegra_cpu_process_id(void) { - return cpu_process_id; + // FIXME: remove this when ready to deprecate invalid process-id boards + if (cpu_process_id == INVALID_PROCESS_ID) + return 0; + else + return cpu_process_id; } int tegra_core_process_id(void) { - return core_process_id; + // FIXME: remove this when ready to deprecate invalid process-id boards + if (core_process_id == INVALID_PROCESS_ID) + return 0; + else + return core_process_id; } int tegra_soc_speedo_id(void) |