6565
6666#define TSC_MAX_NUM 5
6767
68- /* Structure for thermal temperature calculation */
69- struct equation_coefs {
70- int a1 ;
71- int b1 ;
72- int a2 ;
73- int b2 ;
74- };
75-
7668struct rcar_gen3_thermal_priv ;
7769
7870struct rcar_thermal_info {
79- int ths_tj_1 ;
71+ int scale ;
72+ int adj_below ;
73+ int adj_above ;
8074 void (* read_fuses )(struct rcar_gen3_thermal_priv * priv );
8175};
8276
77+ struct equation_set_coef {
78+ int a ;
79+ int b ;
80+ };
81+
8382struct rcar_gen3_thermal_tsc {
8483 struct rcar_gen3_thermal_priv * priv ;
8584 void __iomem * base ;
8685 struct thermal_zone_device * zone ;
87- struct equation_coefs coef ;
86+ /* Different coefficients are used depending on a threshold. */
87+ struct {
88+ struct equation_set_coef below ;
89+ struct equation_set_coef above ;
90+ } coef ;
8891 int thcode [3 ];
8992};
9093
@@ -112,90 +115,75 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
112115/*
113116 * Linear approximation for temperature
114117 *
115- * [reg] = [temp] * a + b => [temp] = ([reg] - b) / a
118+ * [temp] = ((thadj - [reg]) * a) / b + adj
119+ * [reg] = thadj - ([temp] - adj) * b / a
116120 *
117121 * The constants a and b are calculated using two triplets of int values PTAT
118122 * and THCODE. PTAT and THCODE can either be read from hardware or use hard
119- * coded values from driver. The formula to calculate a and b are taken from
120- * BSP and sparsely documented and understood.
123+ * coded values from the driver. The formula to calculate a and b are taken from
124+ * the datasheet. Different calculations are needed for a and b depending on
125+ * if the input variables ([temp] or [reg]) are above or below a threshold. The
126+ * threshold is also calculated from PTAT and THCODE using formulas from the
127+ * datasheet.
128+ *
129+ * The constant thadj is one of the THCODE values, which one to use depends on
130+ * the threshold and input value.
121131 *
122- * Examining the linear formula and the formula used to calculate constants a
123- * and b while knowing that the span for PTAT and THCODE values are between
124- * 0x000 and 0xfff the largest integer possible is 0xfff * 0xfff == 0xffe001.
125- * Integer also needs to be signed so that leaves 7 bits for binary
126- * fixed point scaling.
132+ * The constants adj is taken verbatim from the datasheet. Two values exists,
133+ * which one to use depends on the input value and the calculated threshold.
134+ * Furthermore different SoC models supported by the driver have different sets
135+ * of values. The values for each model are stored in the device match data.
127136 */
128137
129- #define FIXPT_SHIFT 7
130- #define FIXPT_INT (_x ) ((_x) << FIXPT_SHIFT)
131- #define INT_FIXPT (_x ) ((_x) >> FIXPT_SHIFT)
132- #define FIXPT_DIV (_a , _b ) DIV_ROUND_CLOSEST(((_a) << FIXPT_SHIFT), (_b))
133- #define FIXPT_TO_MCELSIUS (_x ) ((_x) * 1000 >> FIXPT_SHIFT)
134-
135- #define RCAR3_THERMAL_GRAN 500 /* mili Celsius */
136-
137- /* no idea where these constants come from */
138- #define TJ_3 -41
139-
140138static void rcar_gen3_thermal_shared_coefs (struct rcar_gen3_thermal_priv * priv )
141139{
142- int tj1 = priv -> info -> ths_tj_1 ;
143-
144- priv -> tj_t = ( FIXPT_INT (( priv -> ptat [1 ] - priv -> ptat [2 ]) * ( tj1 - TJ_3 ) )
145- / ( priv -> ptat [ 0 ] - priv -> ptat [ 2 ])) + FIXPT_INT ( TJ_3 ) ;
140+ priv -> tj_t =
141+ DIV_ROUND_CLOSEST (( priv -> ptat [ 1 ] - priv -> ptat [ 2 ]) * priv -> info -> scale ,
142+ priv -> ptat [0 ] - priv -> ptat [2 ])
143+ + priv -> info -> adj_below ;
146144}
147-
148145static void rcar_gen3_thermal_tsc_coefs (struct rcar_gen3_thermal_priv * priv ,
149146 struct rcar_gen3_thermal_tsc * tsc )
150147{
151- int tj1 = priv -> info -> ths_tj_1 ;
152-
153- /* TODO: Find documentation and document constant calculation formula */
154-
155- /*
156- * Division is not scaled in BSP and if scaled it might overflow
157- * the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled
158- */
159- tsc -> coef .a1 = FIXPT_DIV (FIXPT_INT (tsc -> thcode [1 ] - tsc -> thcode [2 ]),
160- priv -> tj_t - FIXPT_INT (TJ_3 ));
161- tsc -> coef .b1 = FIXPT_INT (tsc -> thcode [2 ]) - tsc -> coef .a1 * TJ_3 ;
162-
163- tsc -> coef .a2 = FIXPT_DIV (FIXPT_INT (tsc -> thcode [1 ] - tsc -> thcode [0 ]),
164- priv -> tj_t - FIXPT_INT (tj1 ));
165- tsc -> coef .b2 = FIXPT_INT (tsc -> thcode [0 ]) - tsc -> coef .a2 * tj1 ;
166- }
167-
168- static int rcar_gen3_thermal_round (int temp )
169- {
170- int result , round_offs ;
148+ tsc -> coef .below .a = priv -> info -> scale * (priv -> ptat [2 ] - priv -> ptat [1 ]);
149+ tsc -> coef .above .a = priv -> info -> scale * (priv -> ptat [0 ] - priv -> ptat [1 ]);
171150
172- round_offs = temp >= 0 ? RCAR3_THERMAL_GRAN / 2 :
173- - RCAR3_THERMAL_GRAN / 2 ;
174- result = (temp + round_offs ) / RCAR3_THERMAL_GRAN ;
175- return result * RCAR3_THERMAL_GRAN ;
151+ tsc -> coef .below .b = (priv -> ptat [2 ] - priv -> ptat [0 ]) * (tsc -> thcode [2 ] - tsc -> thcode [1 ]);
152+ tsc -> coef .above .b = (priv -> ptat [0 ] - priv -> ptat [2 ]) * (tsc -> thcode [1 ] - tsc -> thcode [0 ]);
176153}
177154
178155static int rcar_gen3_thermal_get_temp (struct thermal_zone_device * tz , int * temp )
179156{
180157 struct rcar_gen3_thermal_tsc * tsc = thermal_zone_device_priv (tz );
181- int mcelsius , val ;
182- int reg ;
158+ struct rcar_gen3_thermal_priv * priv = tsc -> priv ;
159+ const struct equation_set_coef * coef ;
160+ int adj , decicelsius , reg , thcode ;
183161
184162 /* Read register and convert to mili Celsius */
185163 reg = rcar_gen3_thermal_read (tsc , REG_GEN3_TEMP ) & CTEMP_MASK ;
186164
187- if (reg <= tsc -> thcode [1 ])
188- val = FIXPT_DIV (FIXPT_INT (reg ) - tsc -> coef .b1 ,
189- tsc -> coef .a1 );
190- else
191- val = FIXPT_DIV (FIXPT_INT (reg ) - tsc -> coef .b2 ,
192- tsc -> coef .a2 );
193- mcelsius = FIXPT_TO_MCELSIUS (val );
165+ if (reg < tsc -> thcode [1 ]) {
166+ adj = priv -> info -> adj_below ;
167+ coef = & tsc -> coef .below ;
168+ thcode = tsc -> thcode [2 ];
169+ } else {
170+ adj = priv -> info -> adj_above ;
171+ coef = & tsc -> coef .above ;
172+ thcode = tsc -> thcode [0 ];
173+ }
174+
175+ /*
176+ * The dividend can't be grown as it might overflow, instead shorten the
177+ * divisor to convert to decidegree Celsius. If we convert after the
178+ * division precision is lost as we will scale up from whole degrees
179+ * Celsius.
180+ */
181+ decicelsius = DIV_ROUND_CLOSEST (coef -> a * (thcode - reg ), coef -> b / 10 );
194182
195183 /* Guaranteed operating range is -40C to 125C. */
196184
197- /* Round value to device granularity setting */
198- * temp = rcar_gen3_thermal_round ( mcelsius ) ;
185+ /* Reporting is done in millidegree Celsius */
186+ * temp = decicelsius * 100 + adj * 1000 ;
199187
200188 return 0 ;
201189}
@@ -204,15 +192,21 @@ static int rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc *tsc,
204192 int mcelsius )
205193{
206194 struct rcar_gen3_thermal_priv * priv = tsc -> priv ;
207- int celsius , val ;
195+ const struct equation_set_coef * coef ;
196+ int adj , celsius , thcode ;
208197
209198 celsius = DIV_ROUND_CLOSEST (mcelsius , 1000 );
210- if (celsius <= INT_FIXPT (priv -> tj_t ))
211- val = celsius * tsc -> coef .a1 + tsc -> coef .b1 ;
212- else
213- val = celsius * tsc -> coef .a2 + tsc -> coef .b2 ;
199+ if (celsius < priv -> tj_t ) {
200+ coef = & tsc -> coef .below ;
201+ adj = priv -> info -> adj_below ;
202+ thcode = tsc -> thcode [2 ];
203+ } else {
204+ coef = & tsc -> coef .above ;
205+ adj = priv -> info -> adj_above ;
206+ thcode = tsc -> thcode [0 ];
207+ }
214208
215- return INT_FIXPT ( val );
209+ return thcode - DIV_ROUND_CLOSEST (( celsius - adj ) * coef -> b , coef -> a );
216210}
217211
218212static int rcar_gen3_thermal_set_trips (struct thermal_zone_device * tz , int low , int high )
@@ -377,17 +371,23 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv *priv,
377371}
378372
379373static const struct rcar_thermal_info rcar_m3w_thermal_info = {
380- .ths_tj_1 = 116 ,
374+ .scale = 157 ,
375+ .adj_below = -41 ,
376+ .adj_above = 116 ,
381377 .read_fuses = rcar_gen3_thermal_read_fuses_gen3 ,
382378};
383379
384380static const struct rcar_thermal_info rcar_gen3_thermal_info = {
385- .ths_tj_1 = 126 ,
381+ .scale = 167 ,
382+ .adj_below = -41 ,
383+ .adj_above = 126 ,
386384 .read_fuses = rcar_gen3_thermal_read_fuses_gen3 ,
387385};
388386
389387static const struct rcar_thermal_info rcar_gen4_thermal_info = {
390- .ths_tj_1 = 126 ,
388+ .scale = 167 ,
389+ .adj_below = -41 ,
390+ .adj_above = 126 ,
391391 .read_fuses = rcar_gen3_thermal_read_fuses_gen4 ,
392392};
393393
0 commit comments