xref: /linux/arch/powerpc/platforms/ps3/repository.c (revision 0be3ff0c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  PS3 repository routines.
4  *
5  *  Copyright (C) 2006 Sony Computer Entertainment Inc.
6  *  Copyright 2006 Sony Corp.
7  */
8 
9 #include <asm/lv1call.h>
10 
11 #include "platform.h"
12 
13 enum ps3_vendor_id {
14 	PS3_VENDOR_ID_NONE = 0,
15 	PS3_VENDOR_ID_SONY = 0x8000000000000000UL,
16 };
17 
18 enum ps3_lpar_id {
19 	PS3_LPAR_ID_CURRENT = 0,
20 	PS3_LPAR_ID_PME = 1,
21 };
22 
23 #define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__)
24 static void _dump_field(const char *hdr, u64 n, const char *func, int line)
25 {
26 #if defined(DEBUG)
27 	char s[16];
28 	const char *const in = (const char *)&n;
29 	unsigned int i;
30 
31 	for (i = 0; i < 8; i++)
32 		s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.';
33 	s[i] = 0;
34 
35 	pr_devel("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s);
36 #endif
37 }
38 
39 #define dump_node_name(_a, _b, _c, _d, _e) \
40 	_dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__)
41 static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3,
42 	u64 n4, const char *func, int line)
43 {
44 	pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);
45 	_dump_field("n1: ", n1, func, line);
46 	_dump_field("n2: ", n2, func, line);
47 	_dump_field("n3: ", n3, func, line);
48 	_dump_field("n4: ", n4, func, line);
49 }
50 
51 #define dump_node(_a, _b, _c, _d, _e, _f, _g) \
52 	_dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
53 static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
54 	u64 v1, u64 v2, const char *func, int line)
55 {
56 	pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);
57 	_dump_field("n1: ", n1, func, line);
58 	_dump_field("n2: ", n2, func, line);
59 	_dump_field("n3: ", n3, func, line);
60 	_dump_field("n4: ", n4, func, line);
61 	pr_devel("%s:%d: v1: %016llx\n", func, line, v1);
62 	pr_devel("%s:%d: v2: %016llx\n", func, line, v2);
63 }
64 
65 /**
66  * make_first_field - Make the first field of a repository node name.
67  * @text: Text portion of the field.
68  * @index: Numeric index portion of the field.  Use zero for 'don't care'.
69  *
70  * This routine sets the vendor id to zero (non-vendor specific).
71  * Returns field value.
72  */
73 
74 static u64 make_first_field(const char *text, u64 index)
75 {
76 	u64 n;
77 
78 	strncpy((char *)&n, text, 8);
79 	return PS3_VENDOR_ID_NONE + (n >> 32) + index;
80 }
81 
82 /**
83  * make_field - Make subsequent fields of a repository node name.
84  * @text: Text portion of the field.  Use "" for 'don't care'.
85  * @index: Numeric index portion of the field.  Use zero for 'don't care'.
86  *
87  * Returns field value.
88  */
89 
90 static u64 make_field(const char *text, u64 index)
91 {
92 	u64 n = 0;
93 
94 	memcpy((char *)&n, text, strnlen(text, sizeof(n)));
95 	return n + index;
96 }
97 
98 /**
99  * read_node - Read a repository node from raw fields.
100  * @n1: First field of node name.
101  * @n2: Second field of node name.  Use zero for 'don't care'.
102  * @n3: Third field of node name.  Use zero for 'don't care'.
103  * @n4: Fourth field of node name.  Use zero for 'don't care'.
104  * @v1: First repository value (high word).
105  * @v2: Second repository value (low word).  Optional parameter, use zero
106  *      for 'don't care'.
107  */
108 
109 static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
110 	u64 *_v1, u64 *_v2)
111 {
112 	int result;
113 	u64 v1;
114 	u64 v2;
115 
116 	if (lpar_id == PS3_LPAR_ID_CURRENT) {
117 		u64 id;
118 		lv1_get_logical_partition_id(&id);
119 		lpar_id = id;
120 	}
121 
122 	result = lv1_read_repository_node(lpar_id, n1, n2, n3, n4, &v1,
123 		&v2);
124 
125 	if (result) {
126 		pr_warn("%s:%d: lv1_read_repository_node failed: %s\n",
127 			__func__, __LINE__, ps3_result(result));
128 		dump_node_name(lpar_id, n1, n2, n3, n4);
129 		return -ENOENT;
130 	}
131 
132 	dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
133 
134 	if (_v1)
135 		*_v1 = v1;
136 	if (_v2)
137 		*_v2 = v2;
138 
139 	if (v1 && !_v1)
140 		pr_devel("%s:%d: warning: discarding non-zero v1: %016llx\n",
141 			__func__, __LINE__, v1);
142 	if (v2 && !_v2)
143 		pr_devel("%s:%d: warning: discarding non-zero v2: %016llx\n",
144 			__func__, __LINE__, v2);
145 
146 	return 0;
147 }
148 
149 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
150 	u64 *value)
151 {
152 	return read_node(PS3_LPAR_ID_PME,
153 		make_first_field("bus", bus_index),
154 		make_field(bus_str, 0),
155 		0, 0,
156 		value, NULL);
157 }
158 
159 int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id)
160 {
161 	return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index),
162 			 make_field("id", 0), 0, 0, bus_id, NULL);
163 }
164 
165 int ps3_repository_read_bus_type(unsigned int bus_index,
166 	enum ps3_bus_type *bus_type)
167 {
168 	int result;
169 	u64 v1 = 0;
170 
171 	result = read_node(PS3_LPAR_ID_PME,
172 		make_first_field("bus", bus_index),
173 		make_field("type", 0),
174 		0, 0,
175 		&v1, NULL);
176 	*bus_type = v1;
177 	return result;
178 }
179 
180 int ps3_repository_read_bus_num_dev(unsigned int bus_index,
181 	unsigned int *num_dev)
182 {
183 	int result;
184 	u64 v1 = 0;
185 
186 	result = read_node(PS3_LPAR_ID_PME,
187 		make_first_field("bus", bus_index),
188 		make_field("num_dev", 0),
189 		0, 0,
190 		&v1, NULL);
191 	*num_dev = v1;
192 	return result;
193 }
194 
195 int ps3_repository_read_dev_str(unsigned int bus_index,
196 	unsigned int dev_index, const char *dev_str, u64 *value)
197 {
198 	return read_node(PS3_LPAR_ID_PME,
199 		make_first_field("bus", bus_index),
200 		make_field("dev", dev_index),
201 		make_field(dev_str, 0),
202 		0,
203 		value, NULL);
204 }
205 
206 int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,
207 	u64 *dev_id)
208 {
209 	return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index),
210 			 make_field("dev", dev_index), make_field("id", 0), 0,
211 			 dev_id, NULL);
212 }
213 
214 int ps3_repository_read_dev_type(unsigned int bus_index,
215 	unsigned int dev_index, enum ps3_dev_type *dev_type)
216 {
217 	int result;
218 	u64 v1 = 0;
219 
220 	result = read_node(PS3_LPAR_ID_PME,
221 		make_first_field("bus", bus_index),
222 		make_field("dev", dev_index),
223 		make_field("type", 0),
224 		0,
225 		&v1, NULL);
226 	*dev_type = v1;
227 	return result;
228 }
229 
230 int ps3_repository_read_dev_intr(unsigned int bus_index,
231 	unsigned int dev_index, unsigned int intr_index,
232 	enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id)
233 {
234 	int result;
235 	u64 v1 = 0;
236 	u64 v2 = 0;
237 
238 	result = read_node(PS3_LPAR_ID_PME,
239 		make_first_field("bus", bus_index),
240 		make_field("dev", dev_index),
241 		make_field("intr", intr_index),
242 		0,
243 		&v1, &v2);
244 	*intr_type = v1;
245 	*interrupt_id = v2;
246 	return result;
247 }
248 
249 int ps3_repository_read_dev_reg_type(unsigned int bus_index,
250 	unsigned int dev_index, unsigned int reg_index,
251 	enum ps3_reg_type *reg_type)
252 {
253 	int result;
254 	u64 v1 = 0;
255 
256 	result = read_node(PS3_LPAR_ID_PME,
257 		make_first_field("bus", bus_index),
258 		make_field("dev", dev_index),
259 		make_field("reg", reg_index),
260 		make_field("type", 0),
261 		&v1, NULL);
262 	*reg_type = v1;
263 	return result;
264 }
265 
266 int ps3_repository_read_dev_reg_addr(unsigned int bus_index,
267 	unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len)
268 {
269 	return read_node(PS3_LPAR_ID_PME,
270 		make_first_field("bus", bus_index),
271 		make_field("dev", dev_index),
272 		make_field("reg", reg_index),
273 		make_field("data", 0),
274 		bus_addr, len);
275 }
276 
277 int ps3_repository_read_dev_reg(unsigned int bus_index,
278 	unsigned int dev_index, unsigned int reg_index,
279 	enum ps3_reg_type *reg_type, u64 *bus_addr, u64 *len)
280 {
281 	int result = ps3_repository_read_dev_reg_type(bus_index, dev_index,
282 		reg_index, reg_type);
283 	return result ? result
284 		: ps3_repository_read_dev_reg_addr(bus_index, dev_index,
285 		reg_index, bus_addr, len);
286 }
287 
288 
289 
290 int ps3_repository_find_device(struct ps3_repository_device *repo)
291 {
292 	int result;
293 	struct ps3_repository_device tmp = *repo;
294 	unsigned int num_dev;
295 
296 	BUG_ON(repo->bus_index > 10);
297 	BUG_ON(repo->dev_index > 10);
298 
299 	result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
300 
301 	if (result) {
302 		pr_devel("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);
303 		return result;
304 	}
305 
306 	pr_devel("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n",
307 		__func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
308 		num_dev);
309 
310 	if (tmp.dev_index >= num_dev) {
311 		pr_devel("%s:%d: no device found\n", __func__, __LINE__);
312 		return -ENODEV;
313 	}
314 
315 	result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
316 		&tmp.dev_type);
317 
318 	if (result) {
319 		pr_devel("%s:%d read_dev_type failed\n", __func__, __LINE__);
320 		return result;
321 	}
322 
323 	result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,
324 		&tmp.dev_id);
325 
326 	if (result) {
327 		pr_devel("%s:%d ps3_repository_read_dev_id failed\n", __func__,
328 		__LINE__);
329 		return result;
330 	}
331 
332 	pr_devel("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n",
333 		__func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
334 
335 	*repo = tmp;
336 	return 0;
337 }
338 
339 int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
340 				     u64 bus_id, u64 dev_id)
341 {
342 	int result = -ENODEV;
343 	struct ps3_repository_device tmp;
344 	unsigned int num_dev;
345 
346 	pr_devel(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__,
347 		 bus_id, dev_id);
348 
349 	for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) {
350 		result = ps3_repository_read_bus_id(tmp.bus_index,
351 						    &tmp.bus_id);
352 		if (result) {
353 			pr_devel("%s:%u read_bus_id(%u) failed\n", __func__,
354 				 __LINE__, tmp.bus_index);
355 			return result;
356 		}
357 
358 		if (tmp.bus_id == bus_id)
359 			goto found_bus;
360 
361 		pr_devel("%s:%u: skip, bus_id %llu\n", __func__, __LINE__,
362 			 tmp.bus_id);
363 	}
364 	pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);
365 	return result;
366 
367 found_bus:
368 	result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type);
369 	if (result) {
370 		pr_devel("%s:%u read_bus_type(%u) failed\n", __func__,
371 			 __LINE__, tmp.bus_index);
372 		return result;
373 	}
374 
375 	result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
376 	if (result) {
377 		pr_devel("%s:%u read_bus_num_dev failed\n", __func__,
378 			 __LINE__);
379 		return result;
380 	}
381 
382 	for (tmp.dev_index = 0; tmp.dev_index < num_dev; tmp.dev_index++) {
383 		result = ps3_repository_read_dev_id(tmp.bus_index,
384 						    tmp.dev_index,
385 						    &tmp.dev_id);
386 		if (result) {
387 			pr_devel("%s:%u read_dev_id(%u:%u) failed\n", __func__,
388 				 __LINE__, tmp.bus_index, tmp.dev_index);
389 			return result;
390 		}
391 
392 		if (tmp.dev_id == dev_id)
393 			goto found_dev;
394 
395 		pr_devel("%s:%u: skip, dev_id %llu\n", __func__, __LINE__,
396 			 tmp.dev_id);
397 	}
398 	pr_devel(" <- %s:%u: dev not found\n", __func__, __LINE__);
399 	return result;
400 
401 found_dev:
402 	result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
403 					      &tmp.dev_type);
404 	if (result) {
405 		pr_devel("%s:%u read_dev_type failed\n", __func__, __LINE__);
406 		return result;
407 	}
408 
409 	pr_devel(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n",
410 		 __func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index,
411 		 tmp.dev_index, tmp.bus_id, tmp.dev_id);
412 	*repo = tmp;
413 	return 0;
414 }
415 
416 int __init ps3_repository_find_devices(enum ps3_bus_type bus_type,
417 	int (*callback)(const struct ps3_repository_device *repo))
418 {
419 	int result = 0;
420 	struct ps3_repository_device repo;
421 
422 	pr_devel(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
423 
424 	repo.bus_type = bus_type;
425 	result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
426 	if (result) {
427 		pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);
428 		return result;
429 	}
430 
431 	result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
432 	if (result) {
433 		pr_devel("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__,
434 			 repo.bus_index);
435 		return result;
436 	}
437 
438 	for (repo.dev_index = 0; ; repo.dev_index++) {
439 		result = ps3_repository_find_device(&repo);
440 		if (result == -ENODEV) {
441 			result = 0;
442 			break;
443 		} else if (result)
444 			break;
445 
446 		result = callback(&repo);
447 		if (result) {
448 			pr_devel("%s:%d: abort at callback\n", __func__,
449 				__LINE__);
450 			break;
451 		}
452 	}
453 
454 	pr_devel(" <- %s:%d\n", __func__, __LINE__);
455 	return result;
456 }
457 
458 int __init ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
459 	unsigned int *bus_index)
460 {
461 	unsigned int i;
462 	enum ps3_bus_type type;
463 	int error;
464 
465 	for (i = from; i < 10; i++) {
466 		error = ps3_repository_read_bus_type(i, &type);
467 		if (error) {
468 			pr_devel("%s:%d read_bus_type failed\n",
469 				__func__, __LINE__);
470 			*bus_index = UINT_MAX;
471 			return error;
472 		}
473 		if (type == bus_type) {
474 			*bus_index = i;
475 			return 0;
476 		}
477 	}
478 	*bus_index = UINT_MAX;
479 	return -ENODEV;
480 }
481 
482 int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
483 	enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
484 {
485 	int result = 0;
486 	unsigned int res_index;
487 
488 	pr_devel("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type);
489 
490 	*interrupt_id = UINT_MAX;
491 
492 	for (res_index = 0; res_index < 10; res_index++) {
493 		enum ps3_interrupt_type t;
494 		unsigned int id;
495 
496 		result = ps3_repository_read_dev_intr(repo->bus_index,
497 			repo->dev_index, res_index, &t, &id);
498 
499 		if (result) {
500 			pr_devel("%s:%d read_dev_intr failed\n",
501 				__func__, __LINE__);
502 			return result;
503 		}
504 
505 		if (t == intr_type) {
506 			*interrupt_id = id;
507 			break;
508 		}
509 	}
510 
511 	if (res_index == 10)
512 		return -ENODEV;
513 
514 	pr_devel("%s:%d: found intr_type %u at res_index %u\n",
515 		__func__, __LINE__, intr_type, res_index);
516 
517 	return result;
518 }
519 
520 int ps3_repository_find_reg(const struct ps3_repository_device *repo,
521 	enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len)
522 {
523 	int result = 0;
524 	unsigned int res_index;
525 
526 	pr_devel("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type);
527 
528 	*bus_addr = *len = 0;
529 
530 	for (res_index = 0; res_index < 10; res_index++) {
531 		enum ps3_reg_type t;
532 		u64 a;
533 		u64 l;
534 
535 		result = ps3_repository_read_dev_reg(repo->bus_index,
536 			repo->dev_index, res_index, &t, &a, &l);
537 
538 		if (result) {
539 			pr_devel("%s:%d read_dev_reg failed\n",
540 				__func__, __LINE__);
541 			return result;
542 		}
543 
544 		if (t == reg_type) {
545 			*bus_addr = a;
546 			*len = l;
547 			break;
548 		}
549 	}
550 
551 	if (res_index == 10)
552 		return -ENODEV;
553 
554 	pr_devel("%s:%d: found reg_type %u at res_index %u\n",
555 		__func__, __LINE__, reg_type, res_index);
556 
557 	return result;
558 }
559 
560 int ps3_repository_read_stor_dev_port(unsigned int bus_index,
561 	unsigned int dev_index, u64 *port)
562 {
563 	return read_node(PS3_LPAR_ID_PME,
564 		make_first_field("bus", bus_index),
565 		make_field("dev", dev_index),
566 		make_field("port", 0),
567 		0, port, NULL);
568 }
569 
570 int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index,
571 	unsigned int dev_index, u64 *blk_size)
572 {
573 	return read_node(PS3_LPAR_ID_PME,
574 		make_first_field("bus", bus_index),
575 		make_field("dev", dev_index),
576 		make_field("blk_size", 0),
577 		0, blk_size, NULL);
578 }
579 
580 int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index,
581 	unsigned int dev_index, u64 *num_blocks)
582 {
583 	return read_node(PS3_LPAR_ID_PME,
584 		make_first_field("bus", bus_index),
585 		make_field("dev", dev_index),
586 		make_field("n_blocks", 0),
587 		0, num_blocks, NULL);
588 }
589 
590 int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index,
591 	unsigned int dev_index, unsigned int *num_regions)
592 {
593 	int result;
594 	u64 v1 = 0;
595 
596 	result = read_node(PS3_LPAR_ID_PME,
597 		make_first_field("bus", bus_index),
598 		make_field("dev", dev_index),
599 		make_field("n_regs", 0),
600 		0, &v1, NULL);
601 	*num_regions = v1;
602 	return result;
603 }
604 
605 int ps3_repository_read_stor_dev_region_id(unsigned int bus_index,
606 	unsigned int dev_index, unsigned int region_index,
607 	unsigned int *region_id)
608 {
609 	int result;
610 	u64 v1 = 0;
611 
612 	result = read_node(PS3_LPAR_ID_PME,
613 	    make_first_field("bus", bus_index),
614 	    make_field("dev", dev_index),
615 	    make_field("region", region_index),
616 	    make_field("id", 0),
617 	    &v1, NULL);
618 	*region_id = v1;
619 	return result;
620 }
621 
622 int ps3_repository_read_stor_dev_region_size(unsigned int bus_index,
623 	unsigned int dev_index,	unsigned int region_index, u64 *region_size)
624 {
625 	return read_node(PS3_LPAR_ID_PME,
626 	    make_first_field("bus", bus_index),
627 	    make_field("dev", dev_index),
628 	    make_field("region", region_index),
629 	    make_field("size", 0),
630 	    region_size, NULL);
631 }
632 
633 int ps3_repository_read_stor_dev_region_start(unsigned int bus_index,
634 	unsigned int dev_index, unsigned int region_index, u64 *region_start)
635 {
636 	return read_node(PS3_LPAR_ID_PME,
637 	    make_first_field("bus", bus_index),
638 	    make_field("dev", dev_index),
639 	    make_field("region", region_index),
640 	    make_field("start", 0),
641 	    region_start, NULL);
642 }
643 
644 int ps3_repository_read_stor_dev_info(unsigned int bus_index,
645 	unsigned int dev_index, u64 *port, u64 *blk_size,
646 	u64 *num_blocks, unsigned int *num_regions)
647 {
648 	int result;
649 
650 	result = ps3_repository_read_stor_dev_port(bus_index, dev_index, port);
651 	if (result)
652 	    return result;
653 
654 	result = ps3_repository_read_stor_dev_blk_size(bus_index, dev_index,
655 		blk_size);
656 	if (result)
657 	    return result;
658 
659 	result = ps3_repository_read_stor_dev_num_blocks(bus_index, dev_index,
660 		num_blocks);
661 	if (result)
662 	    return result;
663 
664 	result = ps3_repository_read_stor_dev_num_regions(bus_index, dev_index,
665 		num_regions);
666 	return result;
667 }
668 
669 int ps3_repository_read_stor_dev_region(unsigned int bus_index,
670 	unsigned int dev_index, unsigned int region_index,
671 	unsigned int *region_id, u64 *region_start, u64 *region_size)
672 {
673 	int result;
674 
675 	result = ps3_repository_read_stor_dev_region_id(bus_index, dev_index,
676 		region_index, region_id);
677 	if (result)
678 	    return result;
679 
680 	result = ps3_repository_read_stor_dev_region_start(bus_index, dev_index,
681 		region_index, region_start);
682 	if (result)
683 	    return result;
684 
685 	result = ps3_repository_read_stor_dev_region_size(bus_index, dev_index,
686 		region_index, region_size);
687 	return result;
688 }
689 
690 /**
691  * ps3_repository_read_num_pu - Number of logical PU processors for this lpar.
692  */
693 
694 int ps3_repository_read_num_pu(u64 *num_pu)
695 {
696 	*num_pu = 0;
697 	return read_node(PS3_LPAR_ID_CURRENT,
698 			   make_first_field("bi", 0),
699 			   make_field("pun", 0),
700 			   0, 0,
701 			   num_pu, NULL);
702 }
703 
704 /**
705  * ps3_repository_read_pu_id - Read the logical PU id.
706  * @pu_index: Zero based index.
707  * @pu_id: The logical PU id.
708  */
709 
710 int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id)
711 {
712 	return read_node(PS3_LPAR_ID_CURRENT,
713 		make_first_field("bi", 0),
714 		make_field("pu", pu_index),
715 		0, 0,
716 		pu_id, NULL);
717 }
718 
719 int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size)
720 {
721 	return read_node(PS3_LPAR_ID_CURRENT,
722 		make_first_field("bi", 0),
723 		make_field("pu", 0),
724 		ppe_id,
725 		make_field("rm_size", 0),
726 		rm_size, NULL);
727 }
728 
729 int ps3_repository_read_region_total(u64 *region_total)
730 {
731 	return read_node(PS3_LPAR_ID_CURRENT,
732 		make_first_field("bi", 0),
733 		make_field("rgntotal", 0),
734 		0, 0,
735 		region_total, NULL);
736 }
737 
738 /**
739  * ps3_repository_read_mm_info - Read mm info for single pu system.
740  * @rm_base: Real mode memory base address.
741  * @rm_size: Real mode memory size.
742  * @region_total: Maximum memory region size.
743  */
744 
745 int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
746 {
747 	int result;
748 	u64 ppe_id;
749 
750 	lv1_get_logical_ppe_id(&ppe_id);
751 	*rm_base = 0;
752 	result = ps3_repository_read_rm_size(ppe_id, rm_size);
753 	return result ? result
754 		: ps3_repository_read_region_total(region_total);
755 }
756 
757 /**
758  * ps3_repository_read_highmem_region_count - Read the number of highmem regions
759  *
760  * Bootloaders must arrange the repository nodes such that regions are indexed
761  * with a region_index from 0 to region_count-1.
762  */
763 
764 int ps3_repository_read_highmem_region_count(unsigned int *region_count)
765 {
766 	int result;
767 	u64 v1 = 0;
768 
769 	result = read_node(PS3_LPAR_ID_CURRENT,
770 		make_first_field("highmem", 0),
771 		make_field("region", 0),
772 		make_field("count", 0),
773 		0,
774 		&v1, NULL);
775 	*region_count = v1;
776 	return result;
777 }
778 
779 
780 int ps3_repository_read_highmem_base(unsigned int region_index,
781 	u64 *highmem_base)
782 {
783 	return read_node(PS3_LPAR_ID_CURRENT,
784 		make_first_field("highmem", 0),
785 		make_field("region", region_index),
786 		make_field("base", 0),
787 		0,
788 		highmem_base, NULL);
789 }
790 
791 int ps3_repository_read_highmem_size(unsigned int region_index,
792 	u64 *highmem_size)
793 {
794 	return read_node(PS3_LPAR_ID_CURRENT,
795 		make_first_field("highmem", 0),
796 		make_field("region", region_index),
797 		make_field("size", 0),
798 		0,
799 		highmem_size, NULL);
800 }
801 
802 /**
803  * ps3_repository_read_highmem_info - Read high memory region info
804  * @region_index: Region index, {0,..,region_count-1}.
805  * @highmem_base: High memory base address.
806  * @highmem_size: High memory size.
807  *
808  * Bootloaders that preallocate highmem regions must place the
809  * region info into the repository at these well known nodes.
810  */
811 
812 int ps3_repository_read_highmem_info(unsigned int region_index,
813 	u64 *highmem_base, u64 *highmem_size)
814 {
815 	int result;
816 
817 	*highmem_base = 0;
818 	result = ps3_repository_read_highmem_base(region_index, highmem_base);
819 	return result ? result
820 		: ps3_repository_read_highmem_size(region_index, highmem_size);
821 }
822 
823 /**
824  * ps3_repository_read_num_spu_reserved - Number of physical spus reserved.
825  * @num_spu: Number of physical spus.
826  */
827 
828 int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
829 {
830 	int result;
831 	u64 v1 = 0;
832 
833 	result = read_node(PS3_LPAR_ID_CURRENT,
834 		make_first_field("bi", 0),
835 		make_field("spun", 0),
836 		0, 0,
837 		&v1, NULL);
838 	*num_spu_reserved = v1;
839 	return result;
840 }
841 
842 /**
843  * ps3_repository_read_num_spu_resource_id - Number of spu resource reservations.
844  * @num_resource_id: Number of spu resource ids.
845  */
846 
847 int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
848 {
849 	int result;
850 	u64 v1 = 0;
851 
852 	result = read_node(PS3_LPAR_ID_CURRENT,
853 		make_first_field("bi", 0),
854 		make_field("spursvn", 0),
855 		0, 0,
856 		&v1, NULL);
857 	*num_resource_id = v1;
858 	return result;
859 }
860 
861 /**
862  * ps3_repository_read_spu_resource_id - spu resource reservation id value.
863  * @res_index: Resource reservation index.
864  * @resource_type: Resource reservation type.
865  * @resource_id: Resource reservation id.
866  */
867 
868 int ps3_repository_read_spu_resource_id(unsigned int res_index,
869 	enum ps3_spu_resource_type *resource_type, unsigned int *resource_id)
870 {
871 	int result;
872 	u64 v1 = 0;
873 	u64 v2 = 0;
874 
875 	result = read_node(PS3_LPAR_ID_CURRENT,
876 		make_first_field("bi", 0),
877 		make_field("spursv", 0),
878 		res_index,
879 		0,
880 		&v1, &v2);
881 	*resource_type = v1;
882 	*resource_id = v2;
883 	return result;
884 }
885 
886 static int ps3_repository_read_boot_dat_address(u64 *address)
887 {
888 	return read_node(PS3_LPAR_ID_CURRENT,
889 		make_first_field("bi", 0),
890 		make_field("boot_dat", 0),
891 		make_field("address", 0),
892 		0,
893 		address, NULL);
894 }
895 
896 int ps3_repository_read_boot_dat_size(unsigned int *size)
897 {
898 	int result;
899 	u64 v1 = 0;
900 
901 	result = read_node(PS3_LPAR_ID_CURRENT,
902 		make_first_field("bi", 0),
903 		make_field("boot_dat", 0),
904 		make_field("size", 0),
905 		0,
906 		&v1, NULL);
907 	*size = v1;
908 	return result;
909 }
910 
911 int __init ps3_repository_read_vuart_av_port(unsigned int *port)
912 {
913 	int result;
914 	u64 v1 = 0;
915 
916 	result = read_node(PS3_LPAR_ID_CURRENT,
917 		make_first_field("bi", 0),
918 		make_field("vir_uart", 0),
919 		make_field("port", 0),
920 		make_field("avset", 0),
921 		&v1, NULL);
922 	*port = v1;
923 	return result;
924 }
925 
926 int __init ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
927 {
928 	int result;
929 	u64 v1 = 0;
930 
931 	result = read_node(PS3_LPAR_ID_CURRENT,
932 		make_first_field("bi", 0),
933 		make_field("vir_uart", 0),
934 		make_field("port", 0),
935 		make_field("sysmgr", 0),
936 		&v1, NULL);
937 	*port = v1;
938 	return result;
939 }
940 
941 /**
942   * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
943   * address: lpar address of cell_ext_os_area
944   * @size: size of cell_ext_os_area
945   */
946 
947 int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size)
948 {
949 	int result;
950 
951 	*size = 0;
952 	result = ps3_repository_read_boot_dat_address(lpar_addr);
953 	return result ? result
954 		: ps3_repository_read_boot_dat_size(size);
955 }
956 
957 /**
958  * ps3_repository_read_num_be - Number of physical BE processors in the system.
959  */
960 
961 int ps3_repository_read_num_be(unsigned int *num_be)
962 {
963 	int result;
964 	u64 v1 = 0;
965 
966 	result = read_node(PS3_LPAR_ID_PME,
967 		make_first_field("ben", 0),
968 		0,
969 		0,
970 		0,
971 		&v1, NULL);
972 	*num_be = v1;
973 	return result;
974 }
975 
976 /**
977  * ps3_repository_read_be_node_id - Read the physical BE processor node id.
978  * @be_index: Zero based index.
979  * @node_id: The BE processor node id.
980  */
981 
982 int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id)
983 {
984 	return read_node(PS3_LPAR_ID_PME,
985 		make_first_field("be", be_index),
986 		0,
987 		0,
988 		0,
989 		node_id, NULL);
990 }
991 
992 /**
993  * ps3_repository_read_be_id - Read the physical BE processor id.
994  * @node_id: The BE processor node id.
995  * @be_id: The BE processor id.
996  */
997 
998 int ps3_repository_read_be_id(u64 node_id, u64 *be_id)
999 {
1000 	return read_node(PS3_LPAR_ID_PME,
1001 		make_first_field("be", 0),
1002 		node_id,
1003 		0,
1004 		0,
1005 		be_id, NULL);
1006 }
1007 
1008 int __init ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq)
1009 {
1010 	return read_node(PS3_LPAR_ID_PME,
1011 		make_first_field("be", 0),
1012 		node_id,
1013 		make_field("clock", 0),
1014 		0,
1015 		tb_freq, NULL);
1016 }
1017 
1018 int __init ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq)
1019 {
1020 	int result;
1021 	u64 node_id;
1022 
1023 	*tb_freq = 0;
1024 	result = ps3_repository_read_be_node_id(be_index, &node_id);
1025 	return result ? result
1026 		: ps3_repository_read_tb_freq(node_id, tb_freq);
1027 }
1028 
1029 int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar,
1030 	u64 *rights)
1031 {
1032 	int result;
1033 	u64 node_id;
1034 
1035 	*lpar = 0;
1036 	*rights = 0;
1037 	result = ps3_repository_read_be_node_id(be_index, &node_id);
1038 	return result ? result
1039 		: read_node(PS3_LPAR_ID_PME,
1040 			    make_first_field("be", 0),
1041 			    node_id,
1042 			    make_field("lpm", 0),
1043 			    make_field("priv", 0),
1044 			    lpar, rights);
1045 }
1046 
1047 #if defined(CONFIG_PS3_REPOSITORY_WRITE)
1048 
1049 static int create_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)
1050 {
1051 	int result;
1052 
1053 	dump_node(0, n1, n2, n3, n4, v1, v2);
1054 
1055 	result = lv1_create_repository_node(n1, n2, n3, n4, v1, v2);
1056 
1057 	if (result) {
1058 		pr_devel("%s:%d: lv1_create_repository_node failed: %s\n",
1059 			__func__, __LINE__, ps3_result(result));
1060 		return -ENOENT;
1061 	}
1062 
1063 	return 0;
1064 }
1065 
1066 static int delete_node(u64 n1, u64 n2, u64 n3, u64 n4)
1067 {
1068 	int result;
1069 
1070 	dump_node(0, n1, n2, n3, n4, 0, 0);
1071 
1072 	result = lv1_delete_repository_node(n1, n2, n3, n4);
1073 
1074 	if (result) {
1075 		pr_devel("%s:%d: lv1_delete_repository_node failed: %s\n",
1076 			__func__, __LINE__, ps3_result(result));
1077 		return -ENOENT;
1078 	}
1079 
1080 	return 0;
1081 }
1082 
1083 static int write_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)
1084 {
1085 	int result;
1086 
1087 	result = create_node(n1, n2, n3, n4, v1, v2);
1088 
1089 	if (!result)
1090 		return 0;
1091 
1092 	result = lv1_write_repository_node(n1, n2, n3, n4, v1, v2);
1093 
1094 	if (result) {
1095 		pr_devel("%s:%d: lv1_write_repository_node failed: %s\n",
1096 			__func__, __LINE__, ps3_result(result));
1097 		return -ENOENT;
1098 	}
1099 
1100 	return 0;
1101 }
1102 
1103 int ps3_repository_write_highmem_region_count(unsigned int region_count)
1104 {
1105 	int result;
1106 	u64 v1 = (u64)region_count;
1107 
1108 	result = write_node(
1109 		make_first_field("highmem", 0),
1110 		make_field("region", 0),
1111 		make_field("count", 0),
1112 		0,
1113 		v1, 0);
1114 	return result;
1115 }
1116 
1117 int ps3_repository_write_highmem_base(unsigned int region_index,
1118 	u64 highmem_base)
1119 {
1120 	return write_node(
1121 		make_first_field("highmem", 0),
1122 		make_field("region", region_index),
1123 		make_field("base", 0),
1124 		0,
1125 		highmem_base, 0);
1126 }
1127 
1128 int ps3_repository_write_highmem_size(unsigned int region_index,
1129 	u64 highmem_size)
1130 {
1131 	return write_node(
1132 		make_first_field("highmem", 0),
1133 		make_field("region", region_index),
1134 		make_field("size", 0),
1135 		0,
1136 		highmem_size, 0);
1137 }
1138 
1139 int ps3_repository_write_highmem_info(unsigned int region_index,
1140 	u64 highmem_base, u64 highmem_size)
1141 {
1142 	int result;
1143 
1144 	result = ps3_repository_write_highmem_base(region_index, highmem_base);
1145 	return result ? result
1146 		: ps3_repository_write_highmem_size(region_index, highmem_size);
1147 }
1148 
1149 static int ps3_repository_delete_highmem_base(unsigned int region_index)
1150 {
1151 	return delete_node(
1152 		make_first_field("highmem", 0),
1153 		make_field("region", region_index),
1154 		make_field("base", 0),
1155 		0);
1156 }
1157 
1158 static int ps3_repository_delete_highmem_size(unsigned int region_index)
1159 {
1160 	return delete_node(
1161 		make_first_field("highmem", 0),
1162 		make_field("region", region_index),
1163 		make_field("size", 0),
1164 		0);
1165 }
1166 
1167 int ps3_repository_delete_highmem_info(unsigned int region_index)
1168 {
1169 	int result;
1170 
1171 	result = ps3_repository_delete_highmem_base(region_index);
1172 	result += ps3_repository_delete_highmem_size(region_index);
1173 
1174 	return result ? -1 : 0;
1175 }
1176 
1177 #endif /* defined(CONFIG_PS3_REPOSITORY_WRITE) */
1178 
1179 #if defined(DEBUG)
1180 
1181 int __init ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
1182 {
1183 	int result = 0;
1184 	unsigned int res_index;
1185 
1186 	pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
1187 		repo->bus_index, repo->dev_index);
1188 
1189 	for (res_index = 0; res_index < 10; res_index++) {
1190 		enum ps3_interrupt_type intr_type;
1191 		unsigned int interrupt_id;
1192 
1193 		result = ps3_repository_read_dev_intr(repo->bus_index,
1194 			repo->dev_index, res_index, &intr_type, &interrupt_id);
1195 
1196 		if (result) {
1197 			if (result !=  LV1_NO_ENTRY)
1198 				pr_devel("%s:%d ps3_repository_read_dev_intr"
1199 					" (%u:%u) failed\n", __func__, __LINE__,
1200 					repo->bus_index, repo->dev_index);
1201 			break;
1202 		}
1203 
1204 		pr_devel("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
1205 			__func__, __LINE__, repo->bus_index, repo->dev_index,
1206 			intr_type, interrupt_id);
1207 	}
1208 
1209 	for (res_index = 0; res_index < 10; res_index++) {
1210 		enum ps3_reg_type reg_type;
1211 		u64 bus_addr;
1212 		u64 len;
1213 
1214 		result = ps3_repository_read_dev_reg(repo->bus_index,
1215 			repo->dev_index, res_index, &reg_type, &bus_addr, &len);
1216 
1217 		if (result) {
1218 			if (result !=  LV1_NO_ENTRY)
1219 				pr_devel("%s:%d ps3_repository_read_dev_reg"
1220 					" (%u:%u) failed\n", __func__, __LINE__,
1221 					repo->bus_index, repo->dev_index);
1222 			break;
1223 		}
1224 
1225 		pr_devel("%s:%d (%u:%u) reg_type %u, bus_addr %llxh, len %llxh\n",
1226 			__func__, __LINE__, repo->bus_index, repo->dev_index,
1227 			reg_type, bus_addr, len);
1228 	}
1229 
1230 	pr_devel(" <- %s:%d\n", __func__, __LINE__);
1231 	return result;
1232 }
1233 
1234 static int __init dump_stor_dev_info(struct ps3_repository_device *repo)
1235 {
1236 	int result = 0;
1237 	unsigned int num_regions, region_index;
1238 	u64 port, blk_size, num_blocks;
1239 
1240 	pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
1241 		repo->bus_index, repo->dev_index);
1242 
1243 	result = ps3_repository_read_stor_dev_info(repo->bus_index,
1244 		repo->dev_index, &port, &blk_size, &num_blocks, &num_regions);
1245 	if (result) {
1246 		pr_devel("%s:%d ps3_repository_read_stor_dev_info"
1247 			" (%u:%u) failed\n", __func__, __LINE__,
1248 			repo->bus_index, repo->dev_index);
1249 		goto out;
1250 	}
1251 
1252 	pr_devel("%s:%d  (%u:%u): port %llu, blk_size %llu, num_blocks "
1253 		 "%llu, num_regions %u\n",
1254 		 __func__, __LINE__, repo->bus_index, repo->dev_index,
1255 		port, blk_size, num_blocks, num_regions);
1256 
1257 	for (region_index = 0; region_index < num_regions; region_index++) {
1258 		unsigned int region_id;
1259 		u64 region_start, region_size;
1260 
1261 		result = ps3_repository_read_stor_dev_region(repo->bus_index,
1262 			repo->dev_index, region_index, &region_id,
1263 			&region_start, &region_size);
1264 		if (result) {
1265 			 pr_devel("%s:%d ps3_repository_read_stor_dev_region"
1266 				  " (%u:%u) failed\n", __func__, __LINE__,
1267 				  repo->bus_index, repo->dev_index);
1268 			break;
1269 		}
1270 
1271 		pr_devel("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
1272 			__func__, __LINE__, repo->bus_index, repo->dev_index,
1273 			region_id, (unsigned long)region_start,
1274 			(unsigned long)region_size);
1275 	}
1276 
1277 out:
1278 	pr_devel(" <- %s:%d\n", __func__, __LINE__);
1279 	return result;
1280 }
1281 
1282 static int __init dump_device_info(struct ps3_repository_device *repo,
1283 	unsigned int num_dev)
1284 {
1285 	int result = 0;
1286 
1287 	pr_devel(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index);
1288 
1289 	for (repo->dev_index = 0; repo->dev_index < num_dev;
1290 		repo->dev_index++) {
1291 
1292 		result = ps3_repository_read_dev_type(repo->bus_index,
1293 			repo->dev_index, &repo->dev_type);
1294 
1295 		if (result) {
1296 			pr_devel("%s:%d ps3_repository_read_dev_type"
1297 				" (%u:%u) failed\n", __func__, __LINE__,
1298 				repo->bus_index, repo->dev_index);
1299 			break;
1300 		}
1301 
1302 		result = ps3_repository_read_dev_id(repo->bus_index,
1303 			repo->dev_index, &repo->dev_id);
1304 
1305 		if (result) {
1306 			pr_devel("%s:%d ps3_repository_read_dev_id"
1307 				" (%u:%u) failed\n", __func__, __LINE__,
1308 				repo->bus_index, repo->dev_index);
1309 			continue;
1310 		}
1311 
1312 		pr_devel("%s:%d  (%u:%u): dev_type %u, dev_id %lu\n", __func__,
1313 			__LINE__, repo->bus_index, repo->dev_index,
1314 			repo->dev_type, (unsigned long)repo->dev_id);
1315 
1316 		ps3_repository_dump_resource_info(repo);
1317 
1318 		if (repo->bus_type == PS3_BUS_TYPE_STORAGE)
1319 			dump_stor_dev_info(repo);
1320 	}
1321 
1322 	pr_devel(" <- %s:%d\n", __func__, __LINE__);
1323 	return result;
1324 }
1325 
1326 int __init ps3_repository_dump_bus_info(void)
1327 {
1328 	int result = 0;
1329 	struct ps3_repository_device repo;
1330 
1331 	pr_devel(" -> %s:%d\n", __func__, __LINE__);
1332 
1333 	memset(&repo, 0, sizeof(repo));
1334 
1335 	for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {
1336 		unsigned int num_dev;
1337 
1338 		result = ps3_repository_read_bus_type(repo.bus_index,
1339 			&repo.bus_type);
1340 
1341 		if (result) {
1342 			pr_devel("%s:%d read_bus_type(%u) failed\n",
1343 				__func__, __LINE__, repo.bus_index);
1344 			break;
1345 		}
1346 
1347 		result = ps3_repository_read_bus_id(repo.bus_index,
1348 			&repo.bus_id);
1349 
1350 		if (result) {
1351 			pr_devel("%s:%d read_bus_id(%u) failed\n",
1352 				__func__, __LINE__, repo.bus_index);
1353 			continue;
1354 		}
1355 
1356 		if (repo.bus_index != repo.bus_id)
1357 			pr_devel("%s:%d bus_index != bus_id\n",
1358 				__func__, __LINE__);
1359 
1360 		result = ps3_repository_read_bus_num_dev(repo.bus_index,
1361 			&num_dev);
1362 
1363 		if (result) {
1364 			pr_devel("%s:%d read_bus_num_dev(%u) failed\n",
1365 				__func__, __LINE__, repo.bus_index);
1366 			continue;
1367 		}
1368 
1369 		pr_devel("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n",
1370 			__func__, __LINE__, repo.bus_index, repo.bus_type,
1371 			(unsigned long)repo.bus_id, num_dev);
1372 
1373 		dump_device_info(&repo, num_dev);
1374 	}
1375 
1376 	pr_devel(" <- %s:%d\n", __func__, __LINE__);
1377 	return result;
1378 }
1379 
1380 #endif /* defined(DEBUG) */
1381