ARM: tegra: soctherm: THERM_A/B based on fuses
Joshua Primero [Sat, 20 Oct 2012 19:50:58 +0000 (12:50 -0700)]
Read fuses to acquire THERM_A and THERM_B.

bug 1169070

Change-Id: I4a6fbb3ffee7f06f2cf69c9258d332301f689461
Signed-off-by: Joshua Primero <jprimero@nvidia.com>
Reviewed-on: http://git-master/r/162488
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

arch/arm/mach-tegra/board-dalmore-power.c
arch/arm/mach-tegra/board-pluto-power.c
arch/arm/mach-tegra/include/mach/tegra_fuse.h
arch/arm/mach-tegra/tegra11_soctherm.c
arch/arm/mach-tegra/tegra11_soctherm.h
arch/arm/mach-tegra/tegra_fuse.c

index cb57624..f87e424 100644 (file)
@@ -1152,8 +1152,6 @@ static struct soctherm_platform_data dalmore_soctherm_data = {
        .sensor_data = {
                [TSENSE_CPU0] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
@@ -1162,8 +1160,6 @@ static struct soctherm_platform_data dalmore_soctherm_data = {
                },
                [TSENSE_CPU1] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
@@ -1172,8 +1168,6 @@ static struct soctherm_platform_data dalmore_soctherm_data = {
                },
                [TSENSE_CPU2] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
@@ -1182,38 +1176,21 @@ static struct soctherm_platform_data dalmore_soctherm_data = {
                },
                [TSENSE_CPU3] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
                        .tsample = 163,
                        .pdiv = 10,
                },
+               /* MEM0/MEM1 won't be used */
                [TSENSE_MEM0] = {
-                       .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
-                       .tall = 16300,
-                       .tiddq = 1,
-                       .ten_count = 1,
-                       .tsample = 163,
-                       .pdiv = 10,
+                       .enable = false,
                },
                [TSENSE_MEM1] = {
-                       .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
-                       .tall = 16300,
-                       .tiddq = 1,
-                       .ten_count = 1,
-                       .tsample = 163,
-                       .pdiv = 10,
+                       .enable = false,
                },
                [TSENSE_GPU] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
@@ -1222,8 +1199,6 @@ static struct soctherm_platform_data dalmore_soctherm_data = {
                },
                [TSENSE_PLLX] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
index 0057715..ea025a4 100644 (file)
@@ -728,8 +728,6 @@ static struct soctherm_platform_data pluto_soctherm_data = {
        .sensor_data = {
                [TSENSE_CPU0] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
@@ -738,8 +736,6 @@ static struct soctherm_platform_data pluto_soctherm_data = {
                },
                [TSENSE_CPU1] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
@@ -748,8 +744,6 @@ static struct soctherm_platform_data pluto_soctherm_data = {
                },
                [TSENSE_CPU2] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
@@ -758,38 +752,21 @@ static struct soctherm_platform_data pluto_soctherm_data = {
                },
                [TSENSE_CPU3] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
                        .tsample = 163,
                        .pdiv = 10,
                },
+               /* MEM0/MEM1 won't be used */
                [TSENSE_MEM0] = {
-                       .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
-                       .tall = 16300,
-                       .tiddq = 1,
-                       .ten_count = 1,
-                       .tsample = 163,
-                       .pdiv = 10,
+                       .enable = false,
                },
                [TSENSE_MEM1] = {
-                       .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
-                       .tall = 16300,
-                       .tiddq = 1,
-                       .ten_count = 1,
-                       .tsample = 163,
-                       .pdiv = 10,
+                       .enable = false,
                },
                [TSENSE_GPU] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
@@ -798,8 +775,6 @@ static struct soctherm_platform_data pluto_soctherm_data = {
                },
                [TSENSE_PLLX] = {
                        .enable = true,
-                       .therm_a = 570,
-                       .therm_b = -744,
                        .tall = 16300,
                        .tiddq = 1,
                        .ten_count = 1,
index d264745..b77acf9 100644 (file)
 int tegra_fuse_get_revision(u32 *rev);
 int tegra_fuse_get_tsensor_calibration_data(u32 *calib);
 int tegra_fuse_get_tsensor_spare_bits(u32 *spare_bits);
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+int tegra_fuse_get_vsensor_calib(u32 *calib);
+int tegra_fuse_get_tsensor_calib(int index, u32 *calib);
+#endif
 
 #endif /* _MACH_TEGRA_PUBLIC_FUSE_H_*/
 
index eb420f5..b3ff4af 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/suspend.h>
 
+#include <mach/tegra_fuse.h>
 #include <mach/iomap.h>
 
 #include "tegra11_soctherm.h"
 
 #define THROT_OFFSET                           0x30
 
+#define FUSE_BASE_CP_SHIFT     0
+#define FUSE_BASE_CP_MASK      0x3ff
+#define FUSE_BASE_FT_SHIFT     16
+#define FUSE_BASE_FT_MASK      0x7ff
+#define FUSE_SHIFT_CP_SHIFT    10
+#define FUSE_SHIFT_CP_MASK     0x3f
+#define FUSE_SHIFT_FT_SHIFT    27
+#define FUSE_SHIFT_FT_MASK     0x1f
+
+#define FUSE_TSENSOR_CALIB_FT_SHIFT    13
+#define FUSE_TSENSOR_CALIB_FT_MASK     0x1fff
+#define FUSE_TSENSOR_CALIB_CP_SHIFT    0
+#define FUSE_TSENSOR_CALIB_CP_MASK     0x1fff
+
 #define THROT_PSKIP_CTRL(throt, dev)           (THROT_PSKIP_CTRL_LITE_CPU + \
                                                (THROT_OFFSET * throt) + \
                                                (8 * dev))
@@ -288,6 +303,17 @@ static char *sensor_names[] = {
        [TSENSE_PLLX] = "pllx",
 };
 
+static int sensor2tsensorcalib[] = {
+       [TSENSE_CPU0] = 0,
+       [TSENSE_CPU1] = 1,
+       [TSENSE_CPU2] = 2,
+       [TSENSE_CPU3] = 3,
+       [TSENSE_MEM0] = 5,
+       [TSENSE_MEM1] = 6,
+       [TSENSE_GPU] = 4,
+       [TSENSE_PLLX] = 7,
+};
+
 static inline long temp_translate(int readback)
 {
        int abs = readback >> 8;
@@ -551,10 +577,6 @@ static void __init soctherm_tsense_program(enum soctherm_sense sensor,
        r = REG_SET(r, TS_CPU0_CONFIG1_TEN_COUNT, data->ten_count);
        r = REG_SET(r, TS_CPU0_CONFIG1_TSAMPLE, data->tsample);
        soctherm_writel(r, TS_CPU0_CONFIG1 + offset);
-
-       r = REG_SET(0, TS_CPU0_CONFIG2_THERM_A, data->therm_a);
-       r = REG_SET(r, TS_CPU0_CONFIG2_THERM_B, data->therm_b);
-       soctherm_writel(r, TS_CPU0_CONFIG2 + offset);
 }
 
 static int soctherm_clk_enable(bool enable)
@@ -609,6 +631,80 @@ static int soctherm_clk_enable(bool enable)
        return 0;
 }
 
+static int __init soctherm_fuse_read_tsensor(enum soctherm_sense sensor)
+{
+       u32 calib;
+       u32 fuse_base_cp;
+       u32 fuse_base_ft;
+       s32 fuse_shift_cp;
+       s32 fuse_shift_ft;
+       s32 actual_cp;
+       s32 actual_ft;
+       s32 delta_T;
+
+       s32 fuse_tsensor_ft;
+       s32 fuse_tsensor_cp;
+       s32 actual_tsensor_ft;
+       s32 actual_tsensor_cp;
+       s32 delta_count;
+       s16 therm_a;
+       s16 therm_b;
+
+       u8 pdiv;
+       int tsample;
+
+       u32 r;
+
+       tegra_fuse_get_vsensor_calib(&calib);
+       fuse_base_cp = REG_GET(calib, FUSE_BASE_CP);
+       fuse_base_ft = REG_GET(calib, FUSE_BASE_FT);
+       fuse_shift_cp = REG_GET(calib, FUSE_SHIFT_CP);
+       fuse_shift_ft = REG_GET(calib, FUSE_SHIFT_FT);
+
+       /* Make signed */
+       fuse_shift_cp <<= 26;
+       fuse_shift_cp >>= 26;
+       fuse_shift_ft <<= 27;
+       fuse_shift_ft >>= 27;
+
+       actual_cp = 25000 + (fuse_shift_cp * 500);
+       actual_ft = 90000 + (fuse_shift_ft * 500);
+       actual_cp /= 500;
+       actual_ft /= 500;
+       delta_T = actual_ft - actual_cp;
+
+       tegra_fuse_get_tsensor_calib(sensor2tsensorcalib[sensor], &calib);
+       fuse_tsensor_ft = REG_GET(calib, FUSE_TSENSOR_CALIB_FT);
+       fuse_tsensor_cp = REG_GET(calib, FUSE_TSENSOR_CALIB_CP);
+
+       /* Make signed */
+       fuse_tsensor_ft <<= 19;
+       fuse_tsensor_ft >>= 19;
+       fuse_tsensor_cp <<= 19;
+       fuse_tsensor_cp >>= 19;
+
+       actual_tsensor_ft = fuse_base_ft * 32 + fuse_tsensor_ft;
+       actual_tsensor_cp = fuse_base_cp * 64 + fuse_tsensor_cp;
+
+       pdiv = plat_data.sensor_data[sensor].pdiv;
+       tsample = plat_data.sensor_data[sensor].tsample;
+
+       actual_tsensor_ft = actual_tsensor_ft / pdiv * 10 / 5 * tsample / 131;
+       actual_tsensor_cp = actual_tsensor_cp / pdiv * 10 / 5 * tsample / 131;
+
+       delta_count = actual_tsensor_ft - actual_tsensor_cp;
+
+       therm_a = ((delta_T << 8) / delta_count) << 5;
+       therm_b = (actual_tsensor_ft / delta_count * actual_cp) -
+                       (actual_tsensor_cp / delta_count * actual_ft);
+
+       r = REG_SET(0, TS_CPU0_CONFIG2_THERM_A, therm_a);
+       r = REG_SET(r, TS_CPU0_CONFIG2_THERM_B, therm_b);
+       soctherm_writel(r, TS_CPU0_CONFIG2 + sensor * TS_CONFIG_STATUS_OFFSET);
+
+       return 0;
+}
+
 static int soctherm_init_platform_data(void)
 {
        struct soctherm_therm *therm;
@@ -622,19 +718,25 @@ static int soctherm_init_platform_data(void)
        if (therm[THERM_GPU].thermtrip && therm[THERM_MEM].thermtrip)
                return -EINVAL;
 
-       /* Thermal Sensing programming */
-       for (i = 0; i < TSENSE_SIZE; i++)
-               if (plat_data.sensor_data[i].enable)
-                       soctherm_tsense_program(i, &plat_data.sensor_data[i]);
+       if (soctherm_clk_enable(true) < 0)
+               BUG();
 
        /* Pdiv */
        r = soctherm_readl(TS_PDIV);
        r = REG_SET(r, TS_PDIV_CPU, plat_data.sensor_data[TSENSE_CPU0].pdiv);
        r = REG_SET(r, TS_PDIV_GPU, plat_data.sensor_data[TSENSE_GPU].pdiv);
-       r = REG_SET(r, TS_PDIV_CPU, plat_data.sensor_data[TSENSE_MEM0].pdiv);
-       r = REG_SET(r, TS_PDIV_CPU, plat_data.sensor_data[TSENSE_PLLX].pdiv);
+       r = REG_SET(r, TS_PDIV_MEM, plat_data.sensor_data[TSENSE_MEM0].pdiv);
+       r = REG_SET(r, TS_PDIV_PLLX, plat_data.sensor_data[TSENSE_PLLX].pdiv);
        soctherm_writel(r, TS_PDIV);
 
+       /* Thermal Sensing programming */
+       for (i = 0; i < TSENSE_SIZE; i++) {
+               if (plat_data.sensor_data[i].enable) {
+                       soctherm_tsense_program(i, &plat_data.sensor_data[i]);
+                       soctherm_fuse_read_tsensor(i);
+               }
+       }
+
        for (i = 0; i < THERM_SIZE; i++) {
                if (plat_data.therm[i].hw_backstop) {
                        reg_off = CTL_LVL_CPU0(1) + i * 4;
@@ -750,14 +852,14 @@ int __init tegra11_soctherm_init(struct soctherm_platform_data *data)
 #ifdef CONFIG_DEBUG_FS
 static int cpu0_show(struct seq_file *s, void *data)
 {
-       u32 r, state;
-       r = soctherm_readl(TS_CPU0_STATUS0);
-       state = REG_GET(r, TS_CPU0_STATUS0_CAPTURE);
-       seq_printf(s, "%d,", state);
-
-       r = soctherm_readl(TS_CPU0_STATUS1);
-       state = REG_GET(r, TS_CPU0_STATUS1_TEMP);
-       seq_printf(s, "%ld\n", temp_translate(state));
+       u32 r;
+       int offset = TSENSE_PLLX * TS_CONFIG_STATUS_OFFSET;
+
+       r = soctherm_readl(TS_CPU0_CONFIG0 + offset);
+       r = REG_SET(r, TS_CPU0_CONFIG0_TCALC_OVER, 1);
+       r = REG_SET(r, TS_CPU0_CONFIG0_OVER, 1);
+       r = REG_SET(r, TS_CPU0_CONFIG0_CPTR_OVER, 1);
+       soctherm_writel(r, TS_CPU0_CONFIG0 + offset);
 
        return 0;
 }
index f7e6e37..6922a59 100644 (file)
@@ -47,8 +47,6 @@ struct soctherm_sensor {
        int tiddq;
        int ten_count;
        int tsample;
-       s16 therm_a;
-       s16 therm_b;
        u8 pdiv;
 };
 
index bf32714..55369b5 100644 (file)
 /* tsensor calibration register */
 #define FUSE_TSENSOR_CALIB_0   0x198
 
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+#define FUSE_VSENSOR_CALIB_0   0x18c
+#endif
+
 #endif
 
 #define TEGRA_AGE_0_6 0x2cc /*Spare bit 34*/
@@ -160,6 +164,33 @@ EXPORT_SYMBOL(tegra_fuse_get_tsensor_spare_bits);
 
 #else
 
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+int tegra_fuse_get_vsensor_calib(u32 *calib)
+{
+       *calib = tegra_fuse_readl(FUSE_VSENSOR_CALIB_0);
+       return 0;
+}
+
+static int tsensor_calib_offset[] = {
+       [0] = 0x198,
+       [1] = 0x184,
+       [2] = 0x188,
+       [3] = 0x22c,
+       [4] = 0x254,
+       [5] = 0x258,
+       [6] = 0x25c,
+       [7] = 0x260,
+};
+
+int tegra_fuse_get_tsensor_calib(int index, u32 *calib)
+{
+       if (index < 0 || index > 7)
+               return -EINVAL;
+       *calib = tegra_fuse_readl(tsensor_calib_offset[index]);
+       return 0;
+}
+#endif
+
 int tegra_fuse_get_revision(u32 *rev)
 {
        /* fuse revision */