This source file includes following definitions.
- div64_s64_precise
- tegra_calc_shared_calib
- tegra_calc_tsensor_calib
1
2
3
4
5
6 #include <linux/module.h>
7 #include <linux/platform_device.h>
8 #include <soc/tegra/fuse.h>
9
10 #include "soctherm.h"
11
12 #define NOMINAL_CALIB_FT 105
13 #define NOMINAL_CALIB_CP 25
14
15 #define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK 0x1fff
16 #define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK (0x1fff << 13)
17 #define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13
18
19 #define FUSE_TSENSOR_COMMON 0x180
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 #define CALIB_COEFFICIENT 1000000LL
50
51
52
53
54
55
56
57
58
59
60
61
62 static s64 div64_s64_precise(s64 a, s32 b)
63 {
64 s64 r, al;
65
66
67 al = a << 16;
68
69 r = div64_s64(al * 2 + 1, 2 * b);
70 return r >> 16;
71 }
72
73 int tegra_calc_shared_calib(const struct tegra_soctherm_fuse *tfuse,
74 struct tsensor_shared_calib *shared)
75 {
76 u32 val;
77 s32 shifted_cp, shifted_ft;
78 int err;
79
80 err = tegra_fuse_readl(FUSE_TSENSOR_COMMON, &val);
81 if (err)
82 return err;
83
84 shared->base_cp = (val & tfuse->fuse_base_cp_mask) >>
85 tfuse->fuse_base_cp_shift;
86 shared->base_ft = (val & tfuse->fuse_base_ft_mask) >>
87 tfuse->fuse_base_ft_shift;
88
89 shifted_ft = (val & tfuse->fuse_shift_ft_mask) >>
90 tfuse->fuse_shift_ft_shift;
91 shifted_ft = sign_extend32(shifted_ft, 4);
92
93 if (tfuse->fuse_spare_realignment) {
94 err = tegra_fuse_readl(tfuse->fuse_spare_realignment, &val);
95 if (err)
96 return err;
97 }
98
99 shifted_cp = sign_extend32(val, 5);
100
101 shared->actual_temp_cp = 2 * NOMINAL_CALIB_CP + shifted_cp;
102 shared->actual_temp_ft = 2 * NOMINAL_CALIB_FT + shifted_ft;
103
104 return 0;
105 }
106
107 int tegra_calc_tsensor_calib(const struct tegra_tsensor *sensor,
108 const struct tsensor_shared_calib *shared,
109 u32 *calibration)
110 {
111 const struct tegra_tsensor_group *sensor_group;
112 u32 val, calib;
113 s32 actual_tsensor_ft, actual_tsensor_cp;
114 s32 delta_sens, delta_temp;
115 s32 mult, div;
116 s16 therma, thermb;
117 s64 temp;
118 int err;
119
120 sensor_group = sensor->group;
121
122 err = tegra_fuse_readl(sensor->calib_fuse_offset, &val);
123 if (err)
124 return err;
125
126 actual_tsensor_cp = (shared->base_cp * 64) + sign_extend32(val, 12);
127 val = (val & FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK) >>
128 FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT;
129 actual_tsensor_ft = (shared->base_ft * 32) + sign_extend32(val, 12);
130
131 delta_sens = actual_tsensor_ft - actual_tsensor_cp;
132 delta_temp = shared->actual_temp_ft - shared->actual_temp_cp;
133
134 mult = sensor_group->pdiv * sensor->config->tsample_ate;
135 div = sensor->config->tsample * sensor_group->pdiv_ate;
136
137 temp = (s64)delta_temp * (1LL << 13) * mult;
138 therma = div64_s64_precise(temp, (s64)delta_sens * div);
139
140 temp = ((s64)actual_tsensor_ft * shared->actual_temp_cp) -
141 ((s64)actual_tsensor_cp * shared->actual_temp_ft);
142 thermb = div64_s64_precise(temp, delta_sens);
143
144 temp = (s64)therma * sensor->fuse_corr_alpha;
145 therma = div64_s64_precise(temp, CALIB_COEFFICIENT);
146
147 temp = (s64)thermb * sensor->fuse_corr_alpha + sensor->fuse_corr_beta;
148 thermb = div64_s64_precise(temp, CALIB_COEFFICIENT);
149
150 calib = ((u16)therma << SENSOR_CONFIG2_THERMA_SHIFT) |
151 ((u16)thermb << SENSOR_CONFIG2_THERMB_SHIFT);
152
153 *calibration = calib;
154
155 return 0;
156 }
157
158 MODULE_AUTHOR("Wei Ni <wni@nvidia.com>");
159 MODULE_DESCRIPTION("Tegra SOCTHERM fuse management");
160 MODULE_LICENSE("GPL v2");