1 /* Copyright 2013-2015 IBM Corp.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 * implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <xscom.h>
18 #include <chip.h>
19 #include <sensor.h>
20 #include <dts.h>
21 #include <skiboot.h>
22 #include <opal-api.h>
23 #include <opal-msg.h>
24 #include <timer.h>
25 #include <timebase.h>
26
27 struct dts {
28 uint8_t valid;
29 uint8_t trip;
30 int16_t temp;
31 };
32
33 /*
34 * Attributes for the core temperature sensor
35 */
36 enum {
37 SENSOR_DTS_ATTR_TEMP_MAX,
38 SENSOR_DTS_ATTR_TEMP_TRIP
39 };
40
41
42 /* Therm mac result masking for DTS (result(0:15)
43 * 0:3 - 0x0
44 * 4:11 - Temperature in degrees C
45 * 12:13 - trip bits: 00 - no trip; 01 - warning; 10 - critical; 11 - fatal
46 * 14 - spare
47 * 15 - valid
48 */
dts_decode_one_dts(uint16_t raw,struct dts * dts)49 static void dts_decode_one_dts(uint16_t raw, struct dts *dts)
50 {
51 /*
52 * The value is both signed and unsigned :-) 0xff could be
53 * either 255C or -1C, so for now we treat this as unsigned
54 * which is sufficient for our purpose. We could try to be
55 * a bit smarter and treat it as signed for values between
56 * -10 and 0 and unsigned to 239 or something like that...
57 */
58 dts->valid = raw & 1;
59 if (dts->valid) {
60 dts->temp = (raw >> 4) & 0xff;
61 dts->trip = (raw >> 2) & 0x3;
62 } else {
63 dts->temp = 0;
64 dts->trip = 0;
65 }
66 }
67
dts_keep_max(struct dts * temps,int n,struct dts * dts)68 static void dts_keep_max(struct dts *temps, int n, struct dts *dts)
69 {
70 int i;
71
72 for (i = 0; i < n; i++) {
73 int16_t t = temps[i].temp;
74
75 if (!temps[i].valid)
76 continue;
77
78 if (t > dts->temp)
79 dts->temp = t;
80
81 dts->valid++;
82 dts->trip |= temps[i].trip;
83 }
84 }
85
86 /* Per core Digital Thermal Sensors */
87 #define EX_THERM_DTS_RESULT0 0x10050000
88 #define EX_THERM_DTS_RESULT1 0x10050001
89
90 /* Different sensor locations */
91 #define P8_CT_ZONE_LSU 0
92 #define P8_CT_ZONE_ISU 1
93 #define P8_CT_ZONE_FXU 2
94 #define P8_CT_ZONE_L3C 3
95 #define P8_CT_ZONES 4
96
97 /*
98 * Returns the temperature as the max of all 4 zones and a global trip
99 * attribute.
100 */
dts_read_core_temp_p8(uint32_t pir,struct dts * dts)101 static int dts_read_core_temp_p8(uint32_t pir, struct dts *dts)
102 {
103 int32_t chip_id = pir_to_chip_id(pir);
104 int32_t core = pir_to_core_id(pir);
105 uint64_t dts0, dts1;
106 struct dts temps[P8_CT_ZONES];
107 int rc;
108
109 rc = xscom_read(chip_id, XSCOM_ADDR_P8_EX(core, EX_THERM_DTS_RESULT0),
110 &dts0);
111 if (rc)
112 return rc;
113
114 rc = xscom_read(chip_id, XSCOM_ADDR_P8_EX(core, EX_THERM_DTS_RESULT1),
115 &dts1);
116 if (rc)
117 return rc;
118
119 dts_decode_one_dts(dts0 >> 48, &temps[P8_CT_ZONE_LSU]);
120 dts_decode_one_dts(dts0 >> 32, &temps[P8_CT_ZONE_ISU]);
121 dts_decode_one_dts(dts0 >> 16, &temps[P8_CT_ZONE_FXU]);
122 dts_decode_one_dts(dts1 >> 48, &temps[P8_CT_ZONE_L3C]);
123
124 dts_keep_max(temps, P8_CT_ZONES, dts);
125
126 prlog(PR_TRACE, "DTS: Chip %x Core %x temp:%dC trip:%x\n",
127 chip_id, core, dts->temp, dts->trip);
128
129 /*
130 * FIXME: The trip bits are always set ?! Just discard
131 * them for the moment until we understand why.
132 */
133 dts->trip = 0;
134 return 0;
135 }
136
137 /* Per core Digital Thermal Sensors */
138 #define EC_THERM_P9_DTS_RESULT0 0x050000
139
140 /* Different sensor locations */
141 #define P9_CORE_DTS0 0
142 #define P9_CORE_DTS1 1
143 #define P9_CORE_ZONES 2
144
145 /*
146 * Returns the temperature as the max of all zones and a global trip
147 * attribute.
148 */
dts_read_core_temp_p9(uint32_t pir,struct dts * dts)149 static int dts_read_core_temp_p9(uint32_t pir, struct dts *dts)
150 {
151 int32_t chip_id = pir_to_chip_id(pir);
152 int32_t core = pir_to_core_id(pir);
153 uint64_t dts0;
154 struct dts temps[P9_CORE_ZONES];
155 int rc;
156
157 rc = xscom_read(chip_id, XSCOM_ADDR_P9_EC(core, EC_THERM_P9_DTS_RESULT0),
158 &dts0);
159 if (rc)
160 return rc;
161
162 dts_decode_one_dts(dts0 >> 48, &temps[P9_CORE_DTS0]);
163 dts_decode_one_dts(dts0 >> 32, &temps[P9_CORE_DTS1]);
164
165 dts_keep_max(temps, P9_CORE_ZONES, dts);
166
167 prlog(PR_TRACE, "DTS: Chip %x Core %x temp:%dC trip:%x\n",
168 chip_id, core, dts->temp, dts->trip);
169
170 /*
171 * FIXME: The trip bits are always set ?! Just discard
172 * them for the moment until we understand why.
173 */
174 dts->trip = 0;
175 return 0;
176 }
177
dts_async_read_temp(struct timer * t __unused,void * data,u64 now __unused)178 static void dts_async_read_temp(struct timer *t __unused, void *data,
179 u64 now __unused)
180 {
181 struct dts dts = {0};
182 int rc, swkup_rc;
183 struct cpu_thread *cpu = data;
184
185 swkup_rc = dctl_set_special_wakeup(cpu);
186
187 rc = dts_read_core_temp_p9(cpu->pir, &dts);
188 if (!rc) {
189 if (cpu->sensor_attr == SENSOR_DTS_ATTR_TEMP_MAX)
190 *cpu->sensor_data = dts.temp;
191 else if (cpu->sensor_attr == SENSOR_DTS_ATTR_TEMP_TRIP)
192 *cpu->sensor_data = dts.trip;
193 }
194
195 if (!swkup_rc)
196 dctl_clear_special_wakeup(cpu);
197
198 check_sensor_read(cpu->token);
199 rc = opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL, cpu->token, rc);
200 if (rc)
201 prerror("Failed to queue async message\n");
202
203 cpu->dts_read_in_progress = false;
204 }
205
dts_read_core_temp(u32 pir,struct dts * dts,u8 attr,int token,u64 * sensor_data)206 static int dts_read_core_temp(u32 pir, struct dts *dts, u8 attr,
207 int token, u64 *sensor_data)
208 {
209 struct cpu_thread *cpu;
210 int rc;
211
212 switch (proc_gen) {
213 case proc_gen_p8:
214 rc = dts_read_core_temp_p8(pir, dts);
215 break;
216 case proc_gen_p9: /* Asynchronus read */
217 cpu = find_cpu_by_pir(pir);
218 if (!cpu)
219 return OPAL_PARAMETER;
220 lock(&cpu->dts_lock);
221 if (cpu->dts_read_in_progress) {
222 unlock(&cpu->dts_lock);
223 return OPAL_BUSY;
224 }
225 cpu->dts_read_in_progress = true;
226 cpu->sensor_attr = attr;
227 cpu->sensor_data = sensor_data;
228 cpu->token = token;
229 schedule_timer(&cpu->dts_timer, 0);
230 rc = OPAL_ASYNC_COMPLETION;
231 unlock(&cpu->dts_lock);
232 break;
233 default:
234 rc = OPAL_UNSUPPORTED;
235 }
236 return rc;
237 }
238
239 /* Per memory controller Digital Thermal Sensors */
240 #define THERM_MEM_DTS_RESULT0 0x2050000
241
242 /* Different sensor locations */
243 #define P8_MEM_DTS0 0
244 #define P8_MEM_DTS1 1
245 #define P8_MEM_ZONES 2
246
dts_read_mem_temp(uint32_t chip_id,struct dts * dts)247 static int dts_read_mem_temp(uint32_t chip_id, struct dts *dts)
248 {
249 uint64_t dts0;
250 struct dts temps[P8_MEM_ZONES];
251 int i;
252 int rc;
253
254 rc = xscom_read(chip_id, THERM_MEM_DTS_RESULT0, &dts0);
255 if (rc)
256 return rc;
257
258 dts_decode_one_dts(dts0 >> 48, &temps[P8_MEM_DTS0]);
259 dts_decode_one_dts(dts0 >> 32, &temps[P8_MEM_DTS1]);
260
261 for (i = 0; i < P8_MEM_ZONES; i++) {
262 int16_t t = temps[i].temp;
263
264 if (!temps[i].valid)
265 continue;
266
267 /* keep the max temperature of all 4 sensors */
268 if (t > dts->temp)
269 dts->temp = t;
270
271 dts->valid++;
272 dts->trip |= temps[i].trip;
273 }
274
275 prlog(PR_TRACE, "DTS: Chip %x temp:%dC trip:%x\n",
276 chip_id, dts->temp, dts->trip);
277
278 /*
279 * FIXME: The trip bits are always set ?! Just discard
280 * them for the moment until we understand why.
281 */
282 dts->trip = 0;
283 return 0;
284 }
285
286 /*
287 * DTS sensor class ids. Only one for the moment: the core
288 * temperature.
289 */
290 enum sensor_dts_class {
291 SENSOR_DTS_CORE_TEMP,
292 SENSOR_DTS_MEM_TEMP,
293 /* To be continued */
294 };
295
296 /*
297 * Extract the centaur chip id which was truncated to fit in the
298 * resource identifier field of the sensor handler
299 */
300 #define centaur_get_id(rid) (0x80000000 | ((rid) & 0x3ff))
301
dts_sensor_read(u32 sensor_hndl,int token,u64 * sensor_data)302 int64_t dts_sensor_read(u32 sensor_hndl, int token, u64 *sensor_data)
303 {
304 uint8_t attr = sensor_get_attr(sensor_hndl);
305 uint32_t rid = sensor_get_rid(sensor_hndl);
306 struct dts dts = {0};
307 int64_t rc;
308
309 if (attr > SENSOR_DTS_ATTR_TEMP_TRIP)
310 return OPAL_PARAMETER;
311
312 memset(&dts, 0, sizeof(struct dts));
313
314 switch (sensor_get_frc(sensor_hndl)) {
315 case SENSOR_DTS_CORE_TEMP:
316 rc = dts_read_core_temp(rid, &dts, attr, token, sensor_data);
317 break;
318 case SENSOR_DTS_MEM_TEMP:
319 rc = dts_read_mem_temp(centaur_get_id(rid), &dts);
320 break;
321 default:
322 rc = OPAL_PARAMETER;
323 break;
324 }
325 if (rc)
326 return rc;
327
328 if (attr == SENSOR_DTS_ATTR_TEMP_MAX)
329 *sensor_data = dts.temp;
330 else if (attr == SENSOR_DTS_ATTR_TEMP_TRIP)
331 *sensor_data = dts.trip;
332
333 return 0;
334 }
335
336 /*
337 * We only have two bytes for the resource identifier in the sensor
338 * handler. Let's trunctate the centaur chip id to squeeze it in.
339 *
340 * Centaur chip IDs are using the XSCOM "partID" encoding described in
341 * xscom.h. recap:
342 *
343 * 0b1000.0000.0000.0000.0000.00NN.NCCC.MMMM
344 * N=Node, C=Chip, M=Memory Channel
345 */
346 #define centaur_make_id(cen_id, dimm_id) \
347 (((chip_id) & 0x3ff) | ((dimm_id) << 10))
348
349 #define core_handler(core_id, attr_id) \
350 sensor_make_handler(SENSOR_DTS, SENSOR_DTS_CORE_TEMP, \
351 core_id, attr_id)
352
353 #define cen_handler(cen_id, attr_id) \
354 sensor_make_handler(SENSOR_DTS, SENSOR_DTS_MEM_TEMP, \
355 centaur_make_id(chip_id, 0), attr_id)
356
dts_sensor_create_nodes(struct dt_node * sensors)357 bool dts_sensor_create_nodes(struct dt_node *sensors)
358 {
359 struct proc_chip *chip;
360 struct dt_node *cn;
361 char name[64];
362
363 /* build the device tree nodes :
364 *
365 * sensors/core-temp@pir
366 *
367 * The core is identified by its PIR, is stored in the resource
368 * number of the sensor handler.
369 */
370 for_each_chip(chip) {
371 struct cpu_thread *c;
372
373 for_each_available_core_in_chip(c, chip->id) {
374 struct dt_node *node;
375 uint32_t handler;
376
377 snprintf(name, sizeof(name), "core-temp@%x", c->pir);
378
379 handler = core_handler(c->pir, SENSOR_DTS_ATTR_TEMP_MAX);
380 node = dt_new(sensors, name);
381 dt_add_property_string(node, "compatible",
382 "ibm,opal-sensor");
383 dt_add_property_cells(node, "sensor-data", handler);
384 handler = core_handler(c->pir, SENSOR_DTS_ATTR_TEMP_TRIP);
385 dt_add_property_cells(node, "sensor-status", handler);
386 dt_add_property_string(node, "sensor-type", "temp");
387 dt_add_property_cells(node, "ibm,pir", c->pir);
388 dt_add_property_cells(node, "reg", handler);
389 dt_add_property_string(node, "label", "Core");
390 init_timer(&c->dts_timer, dts_async_read_temp, c);
391 c->dts_read_in_progress = false;
392 }
393 }
394
395 /*
396 * sensors/mem-temp@chip for Centaurs
397 */
398 dt_for_each_compatible(dt_root, cn, "ibm,centaur") {
399 uint32_t chip_id;
400 struct dt_node *node;
401 uint32_t handler;
402
403 chip_id = dt_prop_get_u32(cn, "ibm,chip-id");
404
405 snprintf(name, sizeof(name), "mem-temp@%x", chip_id);
406
407 handler = cen_handler(chip_id, SENSOR_DTS_ATTR_TEMP_MAX);
408 node = dt_new(sensors, name);
409 dt_add_property_string(node, "compatible",
410 "ibm,opal-sensor");
411 dt_add_property_cells(node, "sensor-data", handler);
412
413 handler = cen_handler(chip_id, SENSOR_DTS_ATTR_TEMP_TRIP);
414 dt_add_property_cells(node, "sensor-status", handler);
415 dt_add_property_string(node, "sensor-type", "temp");
416 dt_add_property_cells(node, "ibm,chip-id", chip_id);
417 dt_add_property_cells(node, "reg", handler);
418 dt_add_property_string(node, "label", "Centaur");
419 }
420
421 return true;
422 }
423