1 /* Copyright 2013-2017 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 <skiboot.h>
18 #include <xscom.h>
19 #include <io.h>
20 #include <processor.h>
21 #include <device.h>
22 #include <chip.h>
23 #include <centaur.h>
24 #include <errorlog.h>
25 #include <opal-api.h>
26 #include <timebase.h>
27 #include <nvram.h>
28 
29 /* Mask of bits to clear in HMER before an access */
30 #define HMER_CLR_MASK	(~(SPR_HMER_XSCOM_FAIL | \
31 			   SPR_HMER_XSCOM_DONE | \
32 			   SPR_HMER_XSCOM_STATUS))
33 
34 DEFINE_LOG_ENTRY(OPAL_RC_XSCOM_RW, OPAL_PLATFORM_ERR_EVT, OPAL_XSCOM,
35 		OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL,
36 		OPAL_NA);
37 
38 DEFINE_LOG_ENTRY(OPAL_RC_XSCOM_INDIRECT_RW, OPAL_PLATFORM_ERR_EVT, OPAL_XSCOM,
39 		OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL,
40 		OPAL_NA);
41 
42 DEFINE_LOG_ENTRY(OPAL_RC_XSCOM_RESET, OPAL_PLATFORM_ERR_EVT, OPAL_XSCOM,
43 		OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL,
44 		OPAL_NA);
45 
46 DEFINE_LOG_ENTRY(OPAL_RC_XSCOM_BUSY, OPAL_PLATFORM_ERR_EVT, OPAL_XSCOM,
47 		OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL,
48 		OPAL_NA);
49 
50 /* xscom details to trigger xstop */
51 static struct {
52 	uint64_t addr;
53 	uint64_t fir_bit;
54 } xstop_xscom;
55 
56 /*
57  * Locking notes:
58  *
59  * We used to have a per-target lock. However due to errata HW822317
60  * we can have issues on the issuer side if multiple threads try to
61  * send XSCOMs simultaneously (HMER responses get mixed up), so just
62  * use a global lock instead
63  */
64 static struct lock xscom_lock = LOCK_UNLOCKED;
65 
xscom_addr(uint32_t gcid,uint32_t pcb_addr)66 static inline void *xscom_addr(uint32_t gcid, uint32_t pcb_addr)
67 {
68 	struct proc_chip *chip = get_chip(gcid);
69 	uint64_t addr;
70 
71 	assert(chip);
72 	addr  = chip->xscom_base;
73 	if (proc_gen <= proc_gen_p8) {
74 		addr |= ((uint64_t)pcb_addr << 4) & ~0xfful;
75 		addr |= (pcb_addr << 3) & 0x78;
76 	} else
77 		addr |= ((uint64_t)pcb_addr << 3);
78 	return (void *)addr;
79 }
80 
xscom_wait_done(void)81 static uint64_t xscom_wait_done(void)
82 {
83 	uint64_t hmer;
84 
85 	do
86 		hmer = mfspr(SPR_HMER);
87 	while(!(hmer & SPR_HMER_XSCOM_DONE));
88 
89 	/*
90 	 * HW822317: We need to read a second time as the actual
91 	 * status can be delayed by 1 cycle after DONE
92 	 */
93 	return mfspr(SPR_HMER);
94 }
95 
xscom_reset(uint32_t gcid,bool need_delay)96 static void xscom_reset(uint32_t gcid, bool need_delay)
97 {
98 	u64 hmer;
99 	uint32_t recv_status_reg, log_reg, err_reg;
100 	struct timespec ts;
101 
102 	/* Clear errors in HMER */
103 	mtspr(SPR_HMER, HMER_CLR_MASK);
104 
105 	/* Setup local and target scom addresses */
106 	if (proc_gen == proc_gen_p9) {
107 		recv_status_reg = 0x00090018;
108 		log_reg = 0x0090012;
109 		err_reg = 0x0090013;
110 	} else {
111 		recv_status_reg = 0x202000f;
112 		log_reg = 0x2020007;
113 		err_reg = 0x2020009;
114 	}
115 
116 	/* First we need to write 0 to a register on our chip */
117 	out_be64(xscom_addr(this_cpu()->chip_id, recv_status_reg), 0);
118 	hmer = xscom_wait_done();
119 	if (hmer & SPR_HMER_XSCOM_FAIL)
120 		goto fail;
121 
122 	/* Then we need to clear those two other registers on the target */
123 	out_be64(xscom_addr(gcid, log_reg), 0);
124 	hmer = xscom_wait_done();
125 	if (hmer & SPR_HMER_XSCOM_FAIL)
126 		goto fail;
127 	out_be64(xscom_addr(gcid, err_reg), 0);
128 	hmer = xscom_wait_done();
129 	if (hmer & SPR_HMER_XSCOM_FAIL)
130 		goto fail;
131 
132 	if (need_delay) {
133 		/*
134 		 * Its observed that sometimes immediate retry of
135 		 * XSCOM operation returns wrong data. Adding a
136 		 * delay for XSCOM reset to be effective. Delay of
137 		 * 10 ms is found to be working fine experimentally.
138 		 * FIXME: Replace 10ms delay by exact delay needed
139 		 * or other alternate method to confirm XSCOM reset
140 		 * completion, after checking from HW folks.
141 		 */
142 		ts.tv_sec = 0;
143 		ts.tv_nsec = 10 * 1000;
144 		nanosleep_nopoll(&ts, NULL);
145 	}
146 	return;
147  fail:
148 	/* Fatal error resetting XSCOM */
149 	log_simple_error(&e_info(OPAL_RC_XSCOM_RESET),
150 		"XSCOM: Fatal error resetting engine after failed access !\n");
151 
152 	/* XXX Generate error log ? attn ? panic ?
153 	 * If we decide to panic, change the above severity to PANIC
154 	 */
155 }
156 
xscom_clear_error(uint32_t gcid,uint32_t pcb_addr)157 static int xscom_clear_error(uint32_t gcid, uint32_t pcb_addr)
158 {
159 	u64 hmer;
160 	uint32_t base_xscom_addr;
161 	uint32_t xscom_clear_reg = 0x20010800;
162 
163 	/* only in case of p9 */
164 	if (proc_gen != proc_gen_p9)
165 		return 0;
166 
167 /* xscom clear address range/mask */
168 #define XSCOM_CLEAR_RANGE_START		0x20010A00
169 #define XSCOM_CLEAR_RANGE_END		0x20010ABF
170 #define XSCOM_CLEAR_RANGE_MASK		0x200FFBFF
171 
172 	/*
173 	 * Due to a hardware issue where core responding to scom was delayed
174 	 * due to thread reconfiguration, leaves the scom logic in a state
175 	 * where the subsequent scom to that core can get errors. This is
176 	 * affected for Core PC scom registers in the range of
177 	 * 20010A80-20010ABF.
178 	 *
179 	 * The solution is if a xscom timeout occurs to one of Core PC scom
180 	 * registers in the range of 20010A80-20010ABF, a clearing scom
181 	 * write is done to 0x20010800 with data of '0x00000000' which will
182 	 * also get a timeout but clears the scom logic errors. After the
183 	 * clearing write is done the original scom operation can be retried.
184 	 *
185 	 * The scom timeout is reported as status 0x4 (Invalid address)
186 	 * in HMER[21-23].
187 	 */
188 
189 	base_xscom_addr = pcb_addr & XSCOM_CLEAR_RANGE_MASK;
190 	if (!((base_xscom_addr >= XSCOM_CLEAR_RANGE_START) &&
191 				(base_xscom_addr <= XSCOM_CLEAR_RANGE_END)))
192 		return 0;
193 
194 	/*
195 	 * Reset the XSCOM or next scom operation will fail.
196 	 * We also need a small delay before we go ahead with clearing write.
197 	 * We have observed that without a delay the clearing write has reported
198 	 * a wrong status.
199 	 */
200 	xscom_reset(gcid, true);
201 
202 	/* Clear errors in HMER */
203 	mtspr(SPR_HMER, HMER_CLR_MASK);
204 
205 	/* Write 0 to clear the xscom logic errors on target chip */
206 	out_be64(xscom_addr(gcid, xscom_clear_reg), 0);
207 	hmer = xscom_wait_done();
208 
209 	/*
210 	 * Above clearing xscom write will timeout and error out with
211 	 * invalid access as there is no register at that address. This
212 	 * xscom operation just helps to clear the xscom logic error.
213 	 *
214 	 * On failure, reset the XSCOM or we'll hang on the next access
215 	 */
216 	if (hmer & SPR_HMER_XSCOM_FAIL)
217 		xscom_reset(gcid, true);
218 
219 	return 1;
220 }
221 
xscom_handle_error(uint64_t hmer,uint32_t gcid,uint32_t pcb_addr,bool is_write,int64_t retries,int64_t * xscom_clear_retries)222 static int64_t xscom_handle_error(uint64_t hmer, uint32_t gcid, uint32_t pcb_addr,
223 			      bool is_write, int64_t retries,
224 			      int64_t *xscom_clear_retries)
225 {
226 	unsigned int stat = GETFIELD(SPR_HMER_XSCOM_STATUS, hmer);
227 	int64_t rc = OPAL_HARDWARE;
228 
229 	/* XXX Figure out error codes from doc and error
230 	 * recovery procedures
231 	 */
232 	switch(stat) {
233 	case 1:
234 		/*
235 		 * XSCOM engine is blocked, need to retry. Reset XSCOM
236 		 * engine after crossing retry threshold before
237 		 * retrying again.
238 		 */
239 		if (retries && !(retries  % XSCOM_BUSY_RESET_THRESHOLD)) {
240 			prlog(PR_NOTICE, "XSCOM: Busy even after %d retries, "
241 				"resetting XSCOM now. Total retries  = %lld\n",
242 				XSCOM_BUSY_RESET_THRESHOLD, retries);
243 			xscom_reset(gcid, true);
244 
245 		}
246 
247 		/* Log error if we have retried enough and its still busy */
248 		if (retries == XSCOM_BUSY_MAX_RETRIES)
249 			log_simple_error(&e_info(OPAL_RC_XSCOM_BUSY),
250 				"XSCOM: %s-busy error gcid=0x%x pcb_addr=0x%x "
251 				"stat=0x%x\n", is_write ? "write" : "read",
252 				gcid, pcb_addr, stat);
253 		return OPAL_XSCOM_BUSY;
254 
255 	case 2: /* CPU is asleep, reset XSCOM engine and return */
256 		xscom_reset(gcid, false);
257 		return OPAL_XSCOM_CHIPLET_OFF;
258 	case 3: /* Partial good */
259 		rc = OPAL_XSCOM_PARTIAL_GOOD;
260 		break;
261 	case 4: /* Invalid address / address error */
262 		rc = OPAL_XSCOM_ADDR_ERROR;
263 		if (xscom_clear_error(gcid, pcb_addr)) {
264 			/* return busy if retries still pending. */
265 			if ((*xscom_clear_retries)--)
266 				return OPAL_XSCOM_BUSY;
267 
268 			prlog(PR_DEBUG, "XSCOM: error recovery failed for "
269 				"gcid=0x%x pcb_addr=0x%x\n", gcid, pcb_addr);
270 
271 		}
272 		break;
273 	case 5: /* Clock error */
274 		rc = OPAL_XSCOM_CLOCK_ERROR;
275 		break;
276 	case 6: /* Parity error  */
277 		rc = OPAL_XSCOM_PARITY_ERROR;
278 		break;
279 	case 7: /* Time out */
280 		rc = OPAL_XSCOM_TIMEOUT;
281 		break;
282 	}
283 
284 	/* XXX: Create error log entry ? */
285 	log_simple_error(&e_info(OPAL_RC_XSCOM_RW),
286 		"XSCOM: %s error gcid=0x%x pcb_addr=0x%x stat=0x%x\n",
287 		is_write ? "write" : "read", gcid, pcb_addr, stat);
288 
289 	/* We need to reset the XSCOM or we'll hang on the next access */
290 	xscom_reset(gcid, false);
291 
292 	/* Non recovered ... just fail */
293 	return rc;
294 }
295 
xscom_handle_ind_error(uint64_t data,uint32_t gcid,uint64_t pcb_addr,bool is_write)296 static void xscom_handle_ind_error(uint64_t data, uint32_t gcid,
297 				   uint64_t pcb_addr, bool is_write)
298 {
299 	unsigned int stat = GETFIELD(XSCOM_DATA_IND_ERR, data);
300 	bool timeout = !(data & XSCOM_DATA_IND_COMPLETE);
301 
302 	/* XXX: Create error log entry ? */
303 	if (timeout)
304 		log_simple_error(&e_info(OPAL_RC_XSCOM_INDIRECT_RW),
305 			"XSCOM: indirect %s timeout, gcid=0x%x pcb_addr=0x%llx"
306 			" stat=0x%x\n",
307 			is_write ? "write" : "read", gcid, pcb_addr, stat);
308 	else
309 		log_simple_error(&e_info(OPAL_RC_XSCOM_INDIRECT_RW),
310 			"XSCOM: indirect %s error, gcid=0x%x pcb_addr=0x%llx"
311 			" stat=0x%x\n",
312 			is_write ? "write" : "read", gcid, pcb_addr, stat);
313 }
314 
xscom_gcid_ok(uint32_t gcid)315 static bool xscom_gcid_ok(uint32_t gcid)
316 {
317 	return get_chip(gcid) != NULL;
318 }
319 
320 /* Determine if SCOM address is multicast */
xscom_is_multicast_addr(uint32_t addr)321 static inline bool xscom_is_multicast_addr(uint32_t addr)
322 {
323 	return (((addr >> 30) & 0x1) == 0x1);
324 }
325 
326 /*
327  * Low level XSCOM access functions, perform a single direct xscom
328  * access via MMIO
329  */
__xscom_read(uint32_t gcid,uint32_t pcb_addr,uint64_t * val)330 static int __xscom_read(uint32_t gcid, uint32_t pcb_addr, uint64_t *val)
331 {
332 	uint64_t hmer;
333 	int64_t ret, retries;
334 	int64_t xscom_clear_retries = XSCOM_CLEAR_MAX_RETRIES;
335 
336 	if (!xscom_gcid_ok(gcid)) {
337 		prerror("%s: invalid XSCOM gcid 0x%x\n", __func__, gcid);
338 		return OPAL_PARAMETER;
339 	}
340 
341 	for (retries = 0; retries <= XSCOM_BUSY_MAX_RETRIES; retries++) {
342 		/* Clear status bits in HMER (HMER is special
343 		 * writing to it *ands* bits
344 		 */
345 		mtspr(SPR_HMER, HMER_CLR_MASK);
346 
347 		/* Read value from SCOM */
348 		*val = in_be64(xscom_addr(gcid, pcb_addr));
349 
350 		/* Wait for done bit */
351 		hmer = xscom_wait_done();
352 
353 		/* Check for error */
354 		if (!(hmer & SPR_HMER_XSCOM_FAIL))
355 			return OPAL_SUCCESS;
356 
357 		/* Handle error and possibly eventually retry */
358 		ret = xscom_handle_error(hmer, gcid, pcb_addr, false, retries,
359 				&xscom_clear_retries);
360 		if (ret != OPAL_BUSY)
361 			break;
362 	}
363 
364 	/* Do not print error message for multicast SCOMS */
365 	if (xscom_is_multicast_addr(pcb_addr) && ret == OPAL_XSCOM_CHIPLET_OFF)
366 		return ret;
367 
368 	/*
369 	 * Workaround on P9: PRD does operations it *knows* will fail with this
370 	 * error to work around a hardware issue where accesses via the PIB
371 	 * (FSI or OCC) work as expected, accesses via the ADU (what xscom goes
372 	 * through) do not. The chip logic will always return all FFs if there
373 	 * is any error on the scom.
374 	 */
375 	if (proc_gen == proc_gen_p9 && ret == OPAL_XSCOM_CHIPLET_OFF)
376 		return ret;
377 
378 	prerror("XSCOM: Read failed, ret =  %lld\n", ret);
379 	return ret;
380 }
381 
__xscom_write(uint32_t gcid,uint32_t pcb_addr,uint64_t val)382 static int __xscom_write(uint32_t gcid, uint32_t pcb_addr, uint64_t val)
383 {
384 	uint64_t hmer;
385 	int64_t ret, retries = 0;
386 	int64_t xscom_clear_retries = XSCOM_CLEAR_MAX_RETRIES;
387 
388 	if (!xscom_gcid_ok(gcid)) {
389 		prerror("%s: invalid XSCOM gcid 0x%x\n", __func__, gcid);
390 		return OPAL_PARAMETER;
391 	}
392 
393 	for (retries = 0; retries <= XSCOM_BUSY_MAX_RETRIES; retries++) {
394 		/* Clear status bits in HMER (HMER is special
395 		 * writing to it *ands* bits
396 		 */
397 		mtspr(SPR_HMER, HMER_CLR_MASK);
398 
399 		/* Write value to SCOM */
400 		out_be64(xscom_addr(gcid, pcb_addr), val);
401 
402 		/* Wait for done bit */
403 		hmer = xscom_wait_done();
404 
405 		/* Check for error */
406 		if (!(hmer & SPR_HMER_XSCOM_FAIL))
407 			return OPAL_SUCCESS;
408 
409 		/* Handle error and possibly eventually retry */
410 		ret = xscom_handle_error(hmer, gcid, pcb_addr, true, retries,
411 				&xscom_clear_retries);
412 		if (ret != OPAL_BUSY)
413 			break;
414 	}
415 
416 	/* Do not print error message for multicast SCOMS */
417 	if (xscom_is_multicast_addr(pcb_addr) && ret == OPAL_XSCOM_CHIPLET_OFF)
418 		return ret;
419 
420 	/*
421 	 * Workaround on P9: PRD does operations it *knows* will fail with this
422 	 * error to work around a hardware issue where accesses via the PIB
423 	 * (FSI or OCC) work as expected, accesses via the ADU (what xscom goes
424 	 * through) do not. The chip logic will always return all FFs if there
425 	 * is any error on the scom.
426 	 */
427 	if (proc_gen == proc_gen_p9 && ret == OPAL_XSCOM_CHIPLET_OFF)
428 		return ret;
429 
430 	prerror("XSCOM: Write failed, ret =  %lld\n", ret);
431 	return ret;
432 }
433 
434 /*
435  * Indirect XSCOM access functions
436  */
xscom_indirect_read_form0(uint32_t gcid,uint64_t pcb_addr,uint64_t * val)437 static int xscom_indirect_read_form0(uint32_t gcid, uint64_t pcb_addr,
438 				     uint64_t *val)
439 {
440 	uint32_t addr;
441 	uint64_t data;
442 	int rc, retries;
443 
444 	if (proc_gen < proc_gen_p8) {
445 		*val = (uint64_t)-1;
446 		return OPAL_UNSUPPORTED;
447 	}
448 
449 	/* Write indirect address */
450 	addr = pcb_addr & 0x7fffffff;
451 	data = XSCOM_DATA_IND_READ |
452 		(pcb_addr & XSCOM_ADDR_IND_ADDR);
453 	rc = __xscom_write(gcid, addr, data);
454 	if (rc)
455 		goto bail;
456 
457 	/* Wait for completion */
458 	for (retries = 0; retries < XSCOM_IND_MAX_RETRIES; retries++) {
459 		rc = __xscom_read(gcid, addr, &data);
460 		if (rc)
461 			goto bail;
462 		if ((data & XSCOM_DATA_IND_COMPLETE) &&
463 		    ((data & XSCOM_DATA_IND_ERR) == 0)) {
464 			*val = data & XSCOM_DATA_IND_DATA;
465 			break;
466 		}
467 		if ((data & XSCOM_DATA_IND_COMPLETE) ||
468 		    (retries >= XSCOM_IND_MAX_RETRIES)) {
469 			xscom_handle_ind_error(data, gcid, pcb_addr,
470 					       false);
471 			rc = OPAL_HARDWARE;
472 			goto bail;
473 		}
474 	}
475  bail:
476 	if (rc)
477 		*val = (uint64_t)-1;
478 	return rc;
479 }
480 
xscom_indirect_form(uint64_t pcb_addr)481 static int xscom_indirect_form(uint64_t pcb_addr)
482 {
483 	return (pcb_addr >> 60) & 1;
484 }
485 
xscom_indirect_read(uint32_t gcid,uint64_t pcb_addr,uint64_t * val)486 static int xscom_indirect_read(uint32_t gcid, uint64_t pcb_addr, uint64_t *val)
487 {
488 	uint64_t form = xscom_indirect_form(pcb_addr);
489 
490 	if ((proc_gen == proc_gen_p9) && (form == 1))
491 		return OPAL_UNSUPPORTED;
492 
493 	return xscom_indirect_read_form0(gcid, pcb_addr, val);
494 }
495 
xscom_indirect_write_form0(uint32_t gcid,uint64_t pcb_addr,uint64_t val)496 static int xscom_indirect_write_form0(uint32_t gcid, uint64_t pcb_addr,
497 				      uint64_t val)
498 {
499 	uint32_t addr;
500 	uint64_t data;
501 	int rc, retries;
502 
503 	if (proc_gen < proc_gen_p8)
504 		return OPAL_UNSUPPORTED;
505 
506 	/* Only 16 bit data with indirect */
507 	if (val & ~(XSCOM_ADDR_IND_DATA))
508 		return OPAL_PARAMETER;
509 
510 	/* Write indirect address & data */
511 	addr = pcb_addr & 0x7fffffff;
512 	data = pcb_addr & XSCOM_ADDR_IND_ADDR;
513 	data |= val & XSCOM_ADDR_IND_DATA;
514 
515 	rc = __xscom_write(gcid, addr, data);
516 	if (rc)
517 		goto bail;
518 
519 	/* Wait for completion */
520 	for (retries = 0; retries < XSCOM_IND_MAX_RETRIES; retries++) {
521 		rc = __xscom_read(gcid, addr, &data);
522 		if (rc)
523 			goto bail;
524 		if ((data & XSCOM_DATA_IND_COMPLETE) &&
525 		    ((data & XSCOM_DATA_IND_ERR) == 0))
526 			break;
527 		if ((data & XSCOM_DATA_IND_COMPLETE) ||
528 		    (retries >= XSCOM_IND_MAX_RETRIES)) {
529 			xscom_handle_ind_error(data, gcid, pcb_addr,
530 					       true);
531 			rc = OPAL_HARDWARE;
532 			goto bail;
533 		}
534 	}
535  bail:
536 	return rc;
537 }
538 
xscom_indirect_write_form1(uint32_t gcid,uint64_t pcb_addr,uint64_t val)539 static int xscom_indirect_write_form1(uint32_t gcid, uint64_t pcb_addr,
540 				      uint64_t val)
541 {
542 	uint32_t addr;
543 	uint64_t data;
544 
545 	if (proc_gen < proc_gen_p9)
546 		return OPAL_UNSUPPORTED;
547 	if (val & ~(XSCOM_DATA_IND_FORM1_DATA))
548 		return OPAL_PARAMETER;
549 
550 	/* Mangle address and data for form1 */
551 	addr = (pcb_addr & 0x000ffffffffUL);
552 	data = (pcb_addr & 0xfff00000000UL) << 20;
553 	data |= val;
554 	return __xscom_write(gcid, addr, data);
555 }
556 
xscom_indirect_write(uint32_t gcid,uint64_t pcb_addr,uint64_t val)557 static int xscom_indirect_write(uint32_t gcid, uint64_t pcb_addr, uint64_t val)
558 {
559 	uint64_t form = xscom_indirect_form(pcb_addr);
560 
561 	if ((proc_gen == proc_gen_p9) && (form == 1))
562 		return xscom_indirect_write_form1(gcid, pcb_addr, val);
563 
564 	return xscom_indirect_write_form0(gcid, pcb_addr, val);
565 }
566 
xscom_decode_chiplet(uint32_t partid,uint64_t * pcb_addr)567 static uint32_t xscom_decode_chiplet(uint32_t partid, uint64_t *pcb_addr)
568 {
569 	uint32_t gcid = (partid & 0x0fffffff) >> 4;
570 	uint32_t core = partid & 0xf;
571 
572 	if (proc_gen == proc_gen_p9) {
573 		/* XXX Not supported */
574 		*pcb_addr = 0;
575 	} else {
576 		*pcb_addr |= P8_EX_PCB_SLAVE_BASE;
577 		*pcb_addr |= core << 24;
578 	}
579 
580 	return gcid;
581 }
582 
_xscom_lock(void)583 void _xscom_lock(void)
584 {
585 	lock(&xscom_lock);
586 }
587 
_xscom_unlock(void)588 void _xscom_unlock(void)
589 {
590 	unlock(&xscom_lock);
591 }
592 
593 /*
594  * External API
595  */
_xscom_read(uint32_t partid,uint64_t pcb_addr,uint64_t * val,bool take_lock)596 int _xscom_read(uint32_t partid, uint64_t pcb_addr, uint64_t *val, bool take_lock)
597 {
598 	uint32_t gcid;
599 	int rc;
600 
601 	if (!opal_addr_valid(val))
602 		return OPAL_PARAMETER;
603 
604 	/* Due to a bug in some versions of the PRD wrapper app, errors
605 	 * might not be properly forwarded to PRD, in which case the data
606 	 * set here will be used. Rather than a random value let's thus
607 	 * initialize the data to a known clean state.
608 	 */
609 	*val = 0xdeadbeefdeadbeefull;
610 
611 	/* Handle part ID decoding */
612 	switch(partid >> 28) {
613 	case 0: /* Normal processor chip */
614 		gcid = partid;
615 		break;
616 	case 8: /* Centaur */
617 		return centaur_xscom_read(partid, pcb_addr, val);
618 	case 4: /* EX chiplet */
619 		gcid = xscom_decode_chiplet(partid, &pcb_addr);
620 		if (pcb_addr == 0)
621 			return OPAL_UNSUPPORTED;
622 		break;
623 	default:
624 		/**
625 		 * @fwts-label XSCOMReadInvalidPartID
626 		 * @fwts-advice xscom_read was called with an invalid partid.
627 		 * There's likely a bug somewhere in the stack that's causing
628 		 * someone to try an xscom_read on something that isn't a
629 		 * processor, Centaur or EX chiplet.
630 		 */
631 		prerror("%s: invalid XSCOM partid 0x%x\n", __func__, partid);
632 		return OPAL_PARAMETER;
633 	}
634 
635 	/* HW822317 requires us to do global locking */
636 	if (take_lock)
637 		lock(&xscom_lock);
638 
639 	/* Direct vs indirect access */
640 	if (pcb_addr & XSCOM_ADDR_IND_FLAG)
641 		rc = xscom_indirect_read(gcid, pcb_addr, val);
642 	else
643 		rc = __xscom_read(gcid, pcb_addr & 0x7fffffff, val);
644 
645 	/* Unlock it */
646 	if (take_lock)
647 		unlock(&xscom_lock);
648 	return rc;
649 }
650 
651 opal_call(OPAL_XSCOM_READ, xscom_read, 3);
652 
_xscom_write(uint32_t partid,uint64_t pcb_addr,uint64_t val,bool take_lock)653 int _xscom_write(uint32_t partid, uint64_t pcb_addr, uint64_t val, bool take_lock)
654 {
655 	uint32_t gcid;
656 	int rc;
657 
658 	/* Handle part ID decoding */
659 	switch(partid >> 28) {
660 	case 0: /* Normal processor chip */
661 		gcid = partid;
662 		break;
663 	case 8: /* Centaur */
664 		return centaur_xscom_write(partid, pcb_addr, val);
665 	case 4: /* EX chiplet */
666 		gcid = xscom_decode_chiplet(partid, &pcb_addr);
667 		break;
668 	default:
669 		/**
670 		 * @fwts-label XSCOMWriteInvalidPartID
671 		 * @fwts-advice xscom_write was called with an invalid partid.
672 		 * There's likely a bug somewhere in the stack that's causing
673 		 * someone to try an xscom_write on something that isn't a
674 		 * processor, Centaur or EX chiplet.
675 		 */
676 		prerror("%s: invalid XSCOM partid 0x%x\n", __func__, partid);
677 		return OPAL_PARAMETER;
678 	}
679 
680 	/* HW822317 requires us to do global locking */
681 	if (take_lock)
682 		lock(&xscom_lock);
683 
684 	/* Direct vs indirect access */
685 	if (pcb_addr & XSCOM_ADDR_IND_FLAG)
686 		rc = xscom_indirect_write(gcid, pcb_addr, val);
687 	else
688 		rc = __xscom_write(gcid, pcb_addr & 0x7fffffff, val);
689 
690 	/* Unlock it */
691 	if (take_lock)
692 		unlock(&xscom_lock);
693 	return rc;
694 }
695 opal_call(OPAL_XSCOM_WRITE, xscom_write, 3);
696 
697 /*
698  * Perform a xscom read-modify-write.
699  */
xscom_write_mask(uint32_t partid,uint64_t pcb_addr,uint64_t val,uint64_t mask)700 int xscom_write_mask(uint32_t partid, uint64_t pcb_addr, uint64_t val, uint64_t mask)
701 {
702 	int rc;
703 	uint64_t old_val;
704 
705 	rc = xscom_read(partid, pcb_addr, &old_val);
706 	if (rc)
707 		return rc;
708 	val = (old_val & ~mask) | (val & mask);
709 	return xscom_write(partid, pcb_addr, val);
710 }
711 
xscom_readme(uint64_t pcb_addr,uint64_t * val)712 int xscom_readme(uint64_t pcb_addr, uint64_t *val)
713 {
714 	return xscom_read(this_cpu()->chip_id, pcb_addr, val);
715 }
716 
xscom_writeme(uint64_t pcb_addr,uint64_t val)717 int xscom_writeme(uint64_t pcb_addr, uint64_t val)
718 {
719 	return xscom_write(this_cpu()->chip_id, pcb_addr, val);
720 }
721 
xscom_read_cfam_chipid(uint32_t partid,uint32_t * chip_id)722 int64_t xscom_read_cfam_chipid(uint32_t partid, uint32_t *chip_id)
723 {
724 	uint64_t val;
725 	int64_t rc = OPAL_SUCCESS;
726 
727 	/* Mambo chip model lacks the f000f register, just make
728 	 * something up
729 	 */
730 	if (chip_quirk(QUIRK_NO_F000F)) {
731 		if (proc_gen == proc_gen_p9)
732 			val = 0x203D104980000000UL; /* P9 Nimbus DD2.3 */
733 		else
734 			val = 0x221EF04980000000UL; /* P8 Murano DD2.1 */
735 	} else
736 		rc = xscom_read(partid, 0xf000f, &val);
737 
738 	/* Extract CFAM id */
739 	if (rc == OPAL_SUCCESS)
740 		*chip_id = (uint32_t)(val >> 44);
741 
742 	return rc;
743 }
744 
xscom_init_chip_info(struct proc_chip * chip)745 static void xscom_init_chip_info(struct proc_chip *chip)
746 {
747 	uint32_t val;
748 	int64_t rc;
749 
750 	rc = xscom_read_cfam_chipid(chip->id, &val);
751 	if (rc) {
752 		prerror("XSCOM: Error %lld reading 0xf000f register\n", rc);
753 		/* We leave chip type to UNKNOWN */
754 		return;
755 	}
756 
757 	/* Identify chip */
758 	switch(val & 0xff) {
759 	case 0xef:
760 		chip->type = PROC_CHIP_P8_MURANO;
761 		assert(proc_gen == proc_gen_p8);
762 		break;
763 	case 0xea:
764 		chip->type = PROC_CHIP_P8_VENICE;
765 		assert(proc_gen == proc_gen_p8);
766 		break;
767 	case 0xd3:
768 		chip->type = PROC_CHIP_P8_NAPLES;
769 		assert(proc_gen == proc_gen_p8);
770 		break;
771 	case 0xd1:
772 		chip->type = PROC_CHIP_P9_NIMBUS;
773 		assert(proc_gen == proc_gen_p9);
774 		break;
775 	case 0xd4:
776 		chip->type = PROC_CHIP_P9_CUMULUS;
777 		assert(proc_gen == proc_gen_p9);
778 		break;
779 	case 0xd9:
780 		chip->type = PROC_CHIP_P9P;
781 		assert(proc_gen == proc_gen_p9);
782 		break;
783 	default:
784 		printf("CHIP: Unknown chip type 0x%02x !!!\n",
785 		       (unsigned char)(val & 0xff));
786 	}
787 
788 	/* Get EC level from CFAM ID */
789 	chip->ec_level = ((val >> 16) & 0xf) << 4;
790 	chip->ec_level |= (val >> 8) & 0xf;
791 
792 	/*
793 	 * On P9, grab the ECID bits to differenciate
794 	 * DD1.01, 1.02, 2.00, etc...
795 	 */
796 	if (chip_quirk(QUIRK_MAMBO_CALLOUTS)) {
797 		chip->ec_rev = 0;
798 	} else if (proc_gen == proc_gen_p9) {
799 		uint64_t ecid2 = 0;
800 		uint8_t rev;
801 		xscom_read(chip->id, 0x18002, &ecid2);
802 		switch((ecid2 >> 45) & 7) {
803 		case 0:
804 			rev = 0;
805 			break;
806 		case 1:
807 			rev = 1;
808 			break;
809 		case 3:
810 			rev = 2;
811 			break;
812 		case 7:
813 			rev = 3;
814 			break;
815 		default:
816 			rev = 0;
817 		}
818 		prlog(PR_INFO,"P9 DD%i.%i%d detected\n", 0xf & (chip->ec_level >> 4),
819 		       chip->ec_level & 0xf, rev);
820 		chip->ec_rev = rev;
821 	}
822 }
823 
824 /*
825 * This function triggers xstop by writing to XSCOM.
826 * Machine would enter xstop state post completion of this.
827 */
xscom_trigger_xstop(void)828 int64_t xscom_trigger_xstop(void)
829 {
830 	int rc = OPAL_UNSUPPORTED;
831 	bool xstop_disabled = false;
832 
833 	if (nvram_query_eq_dangerous("opal-sw-xstop", "disable"))
834 		xstop_disabled = true;
835 
836 	if (xstop_disabled) {
837 		prlog(PR_NOTICE, "Software initiated checkstop disabled.\n");
838 		return rc;
839 	}
840 
841 	if (xstop_xscom.addr)
842 		rc = xscom_writeme(xstop_xscom.addr,
843 				PPC_BIT(xstop_xscom.fir_bit));
844 
845 	return rc;
846 }
847 
xscom_init(void)848 void xscom_init(void)
849 {
850 	struct dt_node *xn;
851 	const struct dt_property *p;
852 
853 	dt_for_each_compatible(dt_root, xn, "ibm,xscom") {
854 		uint32_t gcid = dt_get_chip_id(xn);
855 		const struct dt_property *reg;
856 		struct proc_chip *chip;
857 		const char *chip_name;
858 		static const char *chip_names[] = {
859 			"UNKNOWN", "P8E", "P8", "P8NVL", "P9N", "P9C", "P9P"
860 		};
861 
862 		chip = get_chip(gcid);
863 		assert(chip);
864 
865 		/* XXX We need a proper address parsing. For now, we just
866 		 * "know" that we are looking at a u64
867 		 */
868 		reg = dt_find_property(xn, "reg");
869 		assert(reg);
870 
871 		chip->xscom_base = dt_translate_address(xn, 0, NULL);
872 
873 		/* Grab processor type and EC level */
874 		xscom_init_chip_info(chip);
875 
876 		if (chip->type >= ARRAY_SIZE(chip_names))
877 			chip_name = "INVALID";
878 		else
879 			chip_name = chip_names[chip->type];
880 
881 		/* We keep a "CHIP" prefix to make the log more user-friendly */
882 		prlog(PR_NOTICE, "CHIP: Chip ID %04x type: %s DD%x.%x%d\n",
883 		      gcid, chip_name, chip->ec_level >> 4,
884 		      chip->ec_level & 0xf, chip->ec_rev);
885 		prlog(PR_DEBUG, "XSCOM: Base address: 0x%llx\n", chip->xscom_base);
886 	}
887 
888 	/* Collect details to trigger xstop via XSCOM write */
889 	p = dt_find_property(dt_root, "ibm,sw-checkstop-fir");
890 	if (p) {
891 		xstop_xscom.addr = dt_property_get_cell(p, 0);
892 		xstop_xscom.fir_bit = dt_property_get_cell(p, 1);
893 		prlog(PR_DEBUG, "XSTOP: XSCOM addr = 0x%llx, FIR bit = %lld\n",
894 		      xstop_xscom.addr, xstop_xscom.fir_bit);
895 	} else
896 		prlog(PR_DEBUG, "XSTOP: ibm,sw-checkstop-fir prop not found\n");
897 }
898 
xscom_used_by_console(void)899 void xscom_used_by_console(void)
900 {
901 	xscom_lock.in_con_path = true;
902 
903 	/*
904 	 * Some other processor might hold it without having
905 	 * disabled the console locally so let's make sure that
906 	 * is over by taking/releasing the lock ourselves
907 	 */
908 	lock(&xscom_lock);
909 	unlock(&xscom_lock);
910 }
911 
xscom_ok(void)912 bool xscom_ok(void)
913 {
914 	return !lock_held_by_me(&xscom_lock);
915 }
916