1/*
2 *  PS3 repository routines.
3 *
4 *  Copyright (C) 2006 Sony Computer Entertainment Inc.
5 *  Copyright 2006 Sony Corp.
6 *
7 *  This program is free software; you can redistribute it and/or modify
8 *  it under the terms of the GNU General Public License as published by
9 *  the Free Software Foundation; version 2 of the License.
10 *
11 *  This program is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with this program; if not, write to the Free Software
18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#include <asm/lv1call.h>
22
23#include "platform.h"
24
25enum ps3_vendor_id {
26	PS3_VENDOR_ID_NONE = 0,
27	PS3_VENDOR_ID_SONY = 0x8000000000000000UL,
28};
29
30enum ps3_lpar_id {
31	PS3_LPAR_ID_CURRENT = 0,
32	PS3_LPAR_ID_PME = 1,
33};
34
35#define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__)
36static void _dump_field(const char *hdr, u64 n, const char* func, int line)
37{
38#if defined(DEBUG)
39	char s[16];
40	const char *const in = (const char *)&n;
41	unsigned int i;
42
43	for (i = 0; i < 8; i++)
44		s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.';
45	s[i] = 0;
46
47	pr_debug("%s:%d: %s%016lx : %s\n", func, line, hdr, n, s);
48#endif
49}
50
51#define dump_node_name(_a, _b, _c, _d, _e) \
52	_dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__)
53static void _dump_node_name (unsigned int lpar_id, u64 n1, u64 n2, u64 n3,
54	u64 n4, const char* func, int line)
55{
56	pr_debug("%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}
62
63#define dump_node(_a, _b, _c, _d, _e, _f, _g) \
64	_dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
65static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
66	u64 v1, u64 v2, const char* func, int line)
67{
68	pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id);
69	_dump_field("n1: ", n1, func, line);
70	_dump_field("n2: ", n2, func, line);
71	_dump_field("n3: ", n3, func, line);
72	_dump_field("n4: ", n4, func, line);
73	pr_debug("%s:%d: v1: %016lx\n", func, line, v1);
74	pr_debug("%s:%d: v2: %016lx\n", func, line, v2);
75}
76
77/**
78 * make_first_field - Make the first field of a repository node name.
79 * @text: Text portion of the field.
80 * @index: Numeric index portion of the field.  Use zero for 'don't care'.
81 *
82 * This routine sets the vendor id to zero (non-vendor specific).
83 * Returns field value.
84 */
85
86static u64 make_first_field(const char *text, u64 index)
87{
88	u64 n;
89
90	strncpy((char *)&n, text, 8);
91	return PS3_VENDOR_ID_NONE + (n >> 32) + index;
92}
93
94/**
95 * make_field - Make subsequent fields of a repository node name.
96 * @text: Text portion of the field.  Use "" for 'don't care'.
97 * @index: Numeric index portion of the field.  Use zero for 'don't care'.
98 *
99 * Returns field value.
100 */
101
102static u64 make_field(const char *text, u64 index)
103{
104	u64 n;
105
106	strncpy((char *)&n, text, 8);
107	return n + index;
108}
109
110/**
111 * read_node - Read a repository node from raw fields.
112 * @n1: First field of node name.
113 * @n2: Second field of node name.  Use zero for 'don't care'.
114 * @n3: Third field of node name.  Use zero for 'don't care'.
115 * @n4: Fourth field of node name.  Use zero for 'don't care'.
116 * @v1: First repository value (high word).
117 * @v2: Second repository value (low word).  Optional parameter, use zero
118 *      for 'don't care'.
119 */
120
121static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
122	u64 *_v1, u64 *_v2)
123{
124	int result;
125	u64 v1;
126	u64 v2;
127
128	if (lpar_id == PS3_LPAR_ID_CURRENT) {
129		u64 id;
130		lv1_get_logical_partition_id(&id);
131		lpar_id = id;
132	}
133
134	result = lv1_get_repository_node_value(lpar_id, n1, n2, n3, n4, &v1,
135		&v2);
136
137	if (result) {
138		pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n",
139			__func__, __LINE__, ps3_result(result));
140		dump_node_name(lpar_id, n1, n2, n3, n4);
141		return result;
142	}
143
144	dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
145
146	if (_v1)
147		*_v1 = v1;
148	if (_v2)
149		*_v2 = v2;
150
151	if (v1 && !_v1)
152		pr_debug("%s:%d: warning: discarding non-zero v1: %016lx\n",
153			__func__, __LINE__, v1);
154	if (v2 && !_v2)
155		pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n",
156			__func__, __LINE__, v2);
157
158	return result;
159}
160
161int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
162	u64 *value)
163{
164	return read_node(PS3_LPAR_ID_PME,
165		make_first_field("bus", bus_index),
166		make_field(bus_str, 0),
167		0, 0,
168		value, 0);
169}
170
171int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id)
172{
173	int result;
174	u64 v1;
175	u64 v2; /* unused */
176
177	result = read_node(PS3_LPAR_ID_PME,
178		make_first_field("bus", bus_index),
179		make_field("id", 0),
180		0, 0,
181		&v1, &v2);
182	*bus_id = v1;
183	return result;
184}
185
186int ps3_repository_read_bus_type(unsigned int bus_index,
187	enum ps3_bus_type *bus_type)
188{
189	int result;
190	u64 v1;
191
192	result = read_node(PS3_LPAR_ID_PME,
193		make_first_field("bus", bus_index),
194		make_field("type", 0),
195		0, 0,
196		&v1, 0);
197	*bus_type = v1;
198	return result;
199}
200
201int ps3_repository_read_bus_num_dev(unsigned int bus_index,
202	unsigned int *num_dev)
203{
204	int result;
205	u64 v1;
206
207	result = read_node(PS3_LPAR_ID_PME,
208		make_first_field("bus", bus_index),
209		make_field("num_dev", 0),
210		0, 0,
211		&v1, 0);
212	*num_dev = v1;
213	return result;
214}
215
216int ps3_repository_read_dev_str(unsigned int bus_index,
217	unsigned int dev_index, const char *dev_str, u64 *value)
218{
219	return read_node(PS3_LPAR_ID_PME,
220		make_first_field("bus", bus_index),
221		make_field("dev", dev_index),
222		make_field(dev_str, 0),
223		0,
224		value, 0);
225}
226
227int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,
228	unsigned int *dev_id)
229{
230	int result;
231	u64 v1;
232
233	result = read_node(PS3_LPAR_ID_PME,
234		make_first_field("bus", bus_index),
235		make_field("dev", dev_index),
236		make_field("id", 0),
237		0,
238		&v1, 0);
239	*dev_id = v1;
240	return result;
241}
242
243int ps3_repository_read_dev_type(unsigned int bus_index,
244	unsigned int dev_index, enum ps3_dev_type *dev_type)
245{
246	int result;
247	u64 v1;
248
249	result = read_node(PS3_LPAR_ID_PME,
250		make_first_field("bus", bus_index),
251		make_field("dev", dev_index),
252		make_field("type", 0),
253		0,
254		&v1, 0);
255	*dev_type = v1;
256	return result;
257}
258
259int ps3_repository_read_dev_intr(unsigned int bus_index,
260	unsigned int dev_index, unsigned int intr_index,
261	enum ps3_interrupt_type *intr_type, unsigned int* interrupt_id)
262{
263	int result;
264	u64 v1;
265	u64 v2;
266
267	result = read_node(PS3_LPAR_ID_PME,
268		make_first_field("bus", bus_index),
269		make_field("dev", dev_index),
270		make_field("intr", intr_index),
271		0,
272		&v1, &v2);
273	*intr_type = v1;
274	*interrupt_id = v2;
275	return result;
276}
277
278int ps3_repository_read_dev_reg_type(unsigned int bus_index,
279	unsigned int dev_index, unsigned int reg_index,
280	enum ps3_reg_type *reg_type)
281{
282	int result;
283	u64 v1;
284
285	result = read_node(PS3_LPAR_ID_PME,
286		make_first_field("bus", bus_index),
287		make_field("dev", dev_index),
288		make_field("reg", reg_index),
289		make_field("type", 0),
290		&v1, 0);
291	*reg_type = v1;
292	return result;
293}
294
295int ps3_repository_read_dev_reg_addr(unsigned int bus_index,
296	unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len)
297{
298	return read_node(PS3_LPAR_ID_PME,
299		make_first_field("bus", bus_index),
300		make_field("dev", dev_index),
301		make_field("reg", reg_index),
302		make_field("data", 0),
303		bus_addr, len);
304}
305
306int ps3_repository_read_dev_reg(unsigned int bus_index,
307	unsigned int dev_index, unsigned int reg_index,
308	enum ps3_reg_type *reg_type, u64 *bus_addr, u64 *len)
309{
310	int result = ps3_repository_read_dev_reg_type(bus_index, dev_index,
311		reg_index, reg_type);
312	return result ? result
313		: ps3_repository_read_dev_reg_addr(bus_index, dev_index,
314		reg_index, bus_addr, len);
315}
316
317#if defined(DEBUG)
318int ps3_repository_dump_resource_info(unsigned int bus_index,
319	unsigned int dev_index)
320{
321	int result = 0;
322	unsigned int res_index;
323
324	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
325		bus_index, dev_index);
326
327	for (res_index = 0; res_index < 10; res_index++) {
328		enum ps3_interrupt_type intr_type;
329		unsigned int interrupt_id;
330
331		result = ps3_repository_read_dev_intr(bus_index, dev_index,
332			res_index, &intr_type, &interrupt_id);
333
334		if (result) {
335			if (result !=  LV1_NO_ENTRY)
336				pr_debug("%s:%d ps3_repository_read_dev_intr"
337					" (%u:%u) failed\n", __func__, __LINE__,
338					bus_index, dev_index);
339			break;
340		}
341
342		pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n",
343			__func__, __LINE__, bus_index, dev_index, intr_type,
344			interrupt_id);
345	}
346
347	for (res_index = 0; res_index < 10; res_index++) {
348		enum ps3_reg_type reg_type;
349		u64 bus_addr;
350		u64 len;
351
352		result = ps3_repository_read_dev_reg(bus_index, dev_index,
353			res_index, &reg_type, &bus_addr, &len);
354
355		if (result) {
356			if (result !=  LV1_NO_ENTRY)
357				pr_debug("%s:%d ps3_repository_read_dev_reg"
358					" (%u:%u) failed\n", __func__, __LINE__,
359					bus_index, dev_index);
360			break;
361		}
362
363		pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n",
364			__func__, __LINE__, bus_index, dev_index, reg_type,
365			bus_addr, len);
366	}
367
368	pr_debug(" <- %s:%d\n", __func__, __LINE__);
369	return result;
370}
371
372static int dump_stor_dev_info(unsigned int bus_index, unsigned int dev_index)
373{
374	int result = 0;
375	unsigned int num_regions, region_index;
376	u64 port, blk_size, num_blocks;
377
378	pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
379		bus_index, dev_index);
380
381	result = ps3_repository_read_stor_dev_info(bus_index, dev_index, &port,
382		&blk_size, &num_blocks, &num_regions);
383	if (result) {
384		pr_debug("%s:%d ps3_repository_read_stor_dev_info"
385			" (%u:%u) failed\n", __func__, __LINE__,
386			bus_index, dev_index);
387		goto out;
388	}
389
390	pr_debug("%s:%d  (%u:%u): port %lu, blk_size %lu, num_blocks "
391		 "%lu, num_regions %u\n",
392		 __func__, __LINE__, bus_index, dev_index, port,
393		 blk_size, num_blocks, num_regions);
394
395	for (region_index = 0; region_index < num_regions; region_index++) {
396		unsigned int region_id;
397		u64 region_start, region_size;
398
399		result = ps3_repository_read_stor_dev_region(bus_index,
400			dev_index, region_index, &region_id, &region_start,
401			&region_size);
402		if (result) {
403			 pr_debug("%s:%d ps3_repository_read_stor_dev_region"
404				  " (%u:%u) failed\n", __func__, __LINE__,
405				  bus_index, dev_index);
406			break;
407		}
408
409		pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
410			 __func__, __LINE__, bus_index, dev_index, region_id,
411			 region_start, region_size);
412	}
413
414out:
415	pr_debug(" <- %s:%d\n", __func__, __LINE__);
416	return result;
417}
418
419static int dump_device_info(unsigned int bus_index, enum ps3_bus_type bus_type,
420			    unsigned int num_dev)
421{
422	int result = 0;
423	unsigned int dev_index;
424
425	pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index);
426
427	for (dev_index = 0; dev_index < num_dev; dev_index++) {
428		enum ps3_dev_type dev_type;
429		unsigned int dev_id;
430
431		result = ps3_repository_read_dev_type(bus_index, dev_index,
432			&dev_type);
433
434		if (result) {
435			pr_debug("%s:%d ps3_repository_read_dev_type"
436				" (%u:%u) failed\n", __func__, __LINE__,
437				bus_index, dev_index);
438			break;
439		}
440
441		result = ps3_repository_read_dev_id(bus_index, dev_index,
442			&dev_id);
443
444		if (result) {
445			pr_debug("%s:%d ps3_repository_read_dev_id"
446				" (%u:%u) failed\n", __func__, __LINE__,
447				bus_index, dev_index);
448			continue;
449		}
450
451		pr_debug("%s:%d  (%u:%u): dev_type %u, dev_id %u\n", __func__,
452			__LINE__, bus_index, dev_index, dev_type, dev_id);
453
454		ps3_repository_dump_resource_info(bus_index, dev_index);
455
456		if (bus_type == PS3_BUS_TYPE_STORAGE)
457			dump_stor_dev_info(bus_index, dev_index);
458	}
459
460	pr_debug(" <- %s:%d\n", __func__, __LINE__);
461	return result;
462}
463
464int ps3_repository_dump_bus_info(void)
465{
466	int result = 0;
467	unsigned int bus_index;
468
469	pr_debug(" -> %s:%d\n", __func__, __LINE__);
470
471	for (bus_index = 0; bus_index < 10; bus_index++) {
472		enum ps3_bus_type bus_type;
473		unsigned int bus_id;
474		unsigned int num_dev;
475
476		result = ps3_repository_read_bus_type(bus_index, &bus_type);
477
478		if (result) {
479			pr_debug("%s:%d read_bus_type(%u) failed\n",
480				__func__, __LINE__, bus_index);
481			break;
482		}
483
484		result = ps3_repository_read_bus_id(bus_index, &bus_id);
485
486		if (result) {
487			pr_debug("%s:%d read_bus_id(%u) failed\n",
488				__func__, __LINE__, bus_index);
489			continue;
490		}
491
492		if (bus_index != bus_id)
493			pr_debug("%s:%d bus_index != bus_id\n",
494				__func__, __LINE__);
495
496		result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
497
498		if (result) {
499			pr_debug("%s:%d read_bus_num_dev(%u) failed\n",
500				__func__, __LINE__, bus_index);
501			continue;
502		}
503
504		pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n",
505			__func__, __LINE__, bus_index, bus_type, bus_id,
506			num_dev);
507
508		dump_device_info(bus_index, bus_type, num_dev);
509	}
510
511	pr_debug(" <- %s:%d\n", __func__, __LINE__);
512	return result;
513}
514#endif /* defined(DEBUG) */
515
516static int find_device(unsigned int bus_index, unsigned int num_dev,
517	unsigned int start_dev_index, enum ps3_dev_type dev_type,
518	struct ps3_repository_device *dev)
519{
520	int result = 0;
521	unsigned int dev_index;
522
523	pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type);
524
525	dev->dev_index = UINT_MAX;
526
527	for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) {
528		enum ps3_dev_type x;
529
530		result = ps3_repository_read_dev_type(bus_index, dev_index,
531			&x);
532
533		if (result) {
534			pr_debug("%s:%d read_dev_type failed\n",
535				__func__, __LINE__);
536			return result;
537		}
538
539		if (x == dev_type)
540			break;
541	}
542
543	if (dev_index == num_dev)
544		return -1;
545
546	pr_debug("%s:%d: found dev_type %u at dev_index %u\n",
547		__func__, __LINE__, dev_type, dev_index);
548
549	result = ps3_repository_read_dev_id(bus_index, dev_index,
550		&dev->did.dev_id);
551
552	if (result) {
553		pr_debug("%s:%d read_dev_id failed\n",
554			__func__, __LINE__);
555		return result;
556	}
557
558	dev->dev_index = dev_index;
559
560	pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__,
561		dev->did.dev_id);
562
563	return result;
564}
565
566int ps3_repository_find_device (enum ps3_bus_type bus_type,
567	enum ps3_dev_type dev_type,
568	const struct ps3_repository_device *start_dev,
569	struct ps3_repository_device *dev)
570{
571	int result = 0;
572	unsigned int bus_index;
573	unsigned int num_dev;
574
575	pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__,
576		bus_type, dev_type);
577
578	BUG_ON(start_dev && start_dev->bus_index > 10);
579
580	for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10;
581		bus_index++) {
582		enum ps3_bus_type x;
583
584		result = ps3_repository_read_bus_type(bus_index, &x);
585
586		if (result) {
587			pr_debug("%s:%d read_bus_type failed\n",
588				__func__, __LINE__);
589			dev->bus_index = UINT_MAX;
590			return result;
591		}
592		if (x == bus_type)
593			break;
594	}
595
596	if (bus_index >= 10)
597		return -ENODEV;
598
599	pr_debug("%s:%d: found bus_type %u at bus_index %u\n",
600		__func__, __LINE__, bus_type, bus_index);
601
602	result = ps3_repository_read_bus_num_dev(bus_index, &num_dev);
603
604	if (result) {
605		pr_debug("%s:%d read_bus_num_dev failed\n",
606			__func__, __LINE__);
607		return result;
608	}
609
610	result = find_device(bus_index, num_dev, start_dev
611		? start_dev->dev_index + 1 : 0, dev_type, dev);
612
613	if (result) {
614		pr_debug("%s:%d get_did failed\n", __func__, __LINE__);
615		return result;
616	}
617
618	result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id);
619
620	if (result) {
621		pr_debug("%s:%d read_bus_id failed\n",
622			__func__, __LINE__);
623		return result;
624	}
625
626	dev->bus_index = bus_index;
627
628	pr_debug("%s:%d found: bus_id %u, dev_id %u\n",
629		__func__, __LINE__, dev->did.bus_id, dev->did.dev_id);
630
631	return result;
632}
633
634int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
635	enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
636{
637	int result = 0;
638	unsigned int res_index;
639
640	pr_debug("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type);
641
642	*interrupt_id = UINT_MAX;
643
644	for (res_index = 0; res_index < 10; res_index++) {
645		enum ps3_interrupt_type t;
646		unsigned int id;
647
648		result = ps3_repository_read_dev_intr(dev->bus_index,
649			dev->dev_index, res_index, &t, &id);
650
651		if (result) {
652			pr_debug("%s:%d read_dev_intr failed\n",
653				__func__, __LINE__);
654			return result;
655		}
656
657		if (t == intr_type) {
658			*interrupt_id = id;
659			break;
660		}
661	}
662
663	if (res_index == 10)
664		return -ENODEV;
665
666	pr_debug("%s:%d: found intr_type %u at res_index %u\n",
667		__func__, __LINE__, intr_type, res_index);
668
669	return result;
670}
671
672int ps3_repository_find_reg(const struct ps3_repository_device *dev,
673	enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len)
674{
675	int result = 0;
676	unsigned int res_index;
677
678	pr_debug("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type);
679
680	*bus_addr = *len = 0;
681
682	for (res_index = 0; res_index < 10; res_index++) {
683		enum ps3_reg_type t;
684		u64 a;
685		u64 l;
686
687		result = ps3_repository_read_dev_reg(dev->bus_index,
688			dev->dev_index, res_index, &t, &a, &l);
689
690		if (result) {
691			pr_debug("%s:%d read_dev_reg failed\n",
692				__func__, __LINE__);
693			return result;
694		}
695
696		if (t == reg_type) {
697			*bus_addr = a;
698			*len = l;
699			break;
700		}
701	}
702
703	if (res_index == 10)
704		return -ENODEV;
705
706	pr_debug("%s:%d: found reg_type %u at res_index %u\n",
707		__func__, __LINE__, reg_type, res_index);
708
709	return result;
710}
711
712int ps3_repository_read_stor_dev_port(unsigned int bus_index,
713	unsigned int dev_index, u64 *port)
714{
715	return read_node(PS3_LPAR_ID_PME,
716		make_first_field("bus", bus_index),
717		make_field("dev", dev_index),
718		make_field("port", 0),
719		0, port, 0);
720}
721
722int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index,
723	unsigned int dev_index, u64 *blk_size)
724{
725	return read_node(PS3_LPAR_ID_PME,
726		make_first_field("bus", bus_index),
727		make_field("dev", dev_index),
728		make_field("blk_size", 0),
729		0, blk_size, 0);
730}
731
732int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index,
733	unsigned int dev_index, u64 *num_blocks)
734{
735	return read_node(PS3_LPAR_ID_PME,
736		make_first_field("bus", bus_index),
737		make_field("dev", dev_index),
738		make_field("n_blocks", 0),
739		0, num_blocks, 0);
740}
741
742int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index,
743	unsigned int dev_index, unsigned int *num_regions)
744{
745	int result;
746	u64 v1;
747
748	result = read_node(PS3_LPAR_ID_PME,
749		make_first_field("bus", bus_index),
750		make_field("dev", dev_index),
751		make_field("n_regs", 0),
752		0, &v1, 0);
753	*num_regions = v1;
754	return result;
755}
756
757int ps3_repository_read_stor_dev_region_id(unsigned int bus_index,
758	unsigned int dev_index, unsigned int region_index,
759	unsigned int *region_id)
760{
761	int result;
762	u64 v1;
763
764	result = read_node(PS3_LPAR_ID_PME,
765	    make_first_field("bus", bus_index),
766	    make_field("dev", dev_index),
767	    make_field("region", region_index),
768	    make_field("id", 0),
769	    &v1, 0);
770	*region_id = v1;
771	return result;
772}
773
774int ps3_repository_read_stor_dev_region_size(unsigned int bus_index,
775	unsigned int dev_index,	unsigned int region_index, u64 *region_size)
776{
777	return read_node(PS3_LPAR_ID_PME,
778	    make_first_field("bus", bus_index),
779	    make_field("dev", dev_index),
780	    make_field("region", region_index),
781	    make_field("size", 0),
782	    region_size, 0);
783}
784
785int ps3_repository_read_stor_dev_region_start(unsigned int bus_index,
786	unsigned int dev_index, unsigned int region_index, u64 *region_start)
787{
788	return read_node(PS3_LPAR_ID_PME,
789	    make_first_field("bus", bus_index),
790	    make_field("dev", dev_index),
791	    make_field("region", region_index),
792	    make_field("start", 0),
793	    region_start, 0);
794}
795
796int ps3_repository_read_stor_dev_info(unsigned int bus_index,
797	unsigned int dev_index, u64 *port, u64 *blk_size,
798	u64 *num_blocks, unsigned int *num_regions)
799{
800	int result;
801
802	result = ps3_repository_read_stor_dev_port(bus_index, dev_index, port);
803	if (result)
804	    return result;
805
806	result = ps3_repository_read_stor_dev_blk_size(bus_index, dev_index,
807		blk_size);
808	if (result)
809	    return result;
810
811	result = ps3_repository_read_stor_dev_num_blocks(bus_index, dev_index,
812		num_blocks);
813	if (result)
814	    return result;
815
816	result = ps3_repository_read_stor_dev_num_regions(bus_index, dev_index,
817		num_regions);
818	return result;
819}
820
821int ps3_repository_read_stor_dev_region(unsigned int bus_index,
822	unsigned int dev_index, unsigned int region_index,
823	unsigned int *region_id, u64 *region_start, u64 *region_size)
824{
825	int result;
826
827	result = ps3_repository_read_stor_dev_region_id(bus_index, dev_index,
828		region_index, region_id);
829	if (result)
830	    return result;
831
832	result = ps3_repository_read_stor_dev_region_start(bus_index, dev_index,
833		region_index, region_start);
834	if (result)
835	    return result;
836
837	result = ps3_repository_read_stor_dev_region_size(bus_index, dev_index,
838		region_index, region_size);
839	return result;
840}
841
842int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size)
843{
844	return read_node(PS3_LPAR_ID_CURRENT,
845		make_first_field("bi", 0),
846		make_field("pu", 0),
847		ppe_id,
848		make_field("rm_size", 0),
849		rm_size, 0);
850}
851
852int ps3_repository_read_region_total(u64 *region_total)
853{
854	return read_node(PS3_LPAR_ID_CURRENT,
855		make_first_field("bi", 0),
856		make_field("rgntotal", 0),
857		0, 0,
858		region_total, 0);
859}
860
861/**
862 * ps3_repository_read_mm_info - Read mm info for single pu system.
863 * @rm_base: Real mode memory base address.
864 * @rm_size: Real mode memory size.
865 * @region_total: Maximum memory region size.
866 */
867
868int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
869{
870	int result;
871	u64 ppe_id;
872
873	lv1_get_logical_ppe_id(&ppe_id);
874	*rm_base = 0;
875	result = ps3_repository_read_rm_size(ppe_id, rm_size);
876	return result ? result
877		: ps3_repository_read_region_total(region_total);
878}
879
880/**
881 * ps3_repository_read_num_spu_reserved - Number of physical spus reserved.
882 * @num_spu: Number of physical spus.
883 */
884
885int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
886{
887	int result;
888	u64 v1;
889
890	result = read_node(PS3_LPAR_ID_CURRENT,
891		make_first_field("bi", 0),
892		make_field("spun", 0),
893		0, 0,
894		&v1, 0);
895	*num_spu_reserved = v1;
896	return result;
897}
898
899/**
900 * ps3_repository_read_num_spu_resource_id - Number of spu resource reservations.
901 * @num_resource_id: Number of spu resource ids.
902 */
903
904int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
905{
906	int result;
907	u64 v1;
908
909	result = read_node(PS3_LPAR_ID_CURRENT,
910		make_first_field("bi", 0),
911		make_field("spursvn", 0),
912		0, 0,
913		&v1, 0);
914	*num_resource_id = v1;
915	return result;
916}
917
918/**
919 * ps3_repository_read_spu_resource_id - spu resource reservation id value.
920 * @res_index: Resource reservation index.
921 * @resource_type: Resource reservation type.
922 * @resource_id: Resource reservation id.
923 */
924
925int ps3_repository_read_spu_resource_id(unsigned int res_index,
926	enum ps3_spu_resource_type* resource_type, unsigned int *resource_id)
927{
928	int result;
929	u64 v1;
930	u64 v2;
931
932	result = read_node(PS3_LPAR_ID_CURRENT,
933		make_first_field("bi", 0),
934		make_field("spursv", 0),
935		res_index,
936		0,
937		&v1, &v2);
938	*resource_type = v1;
939	*resource_id = v2;
940	return result;
941}
942
943int ps3_repository_read_boot_dat_address(u64 *address)
944{
945	return read_node(PS3_LPAR_ID_CURRENT,
946		make_first_field("bi", 0),
947		make_field("boot_dat", 0),
948		make_field("address", 0),
949		0,
950		address, 0);
951}
952
953int ps3_repository_read_boot_dat_size(unsigned int *size)
954{
955	int result;
956	u64 v1;
957
958	result = read_node(PS3_LPAR_ID_CURRENT,
959		make_first_field("bi", 0),
960		make_field("boot_dat", 0),
961		make_field("size", 0),
962		0,
963		&v1, 0);
964	*size = v1;
965	return result;
966}
967
968/**
969  * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
970  * address: lpar address of cell_ext_os_area
971  * @size: size of cell_ext_os_area
972  */
973
974int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size)
975{
976	int result;
977
978	*size = 0;
979	result = ps3_repository_read_boot_dat_address(lpar_addr);
980	return result ? result
981		: ps3_repository_read_boot_dat_size(size);
982}
983
984int ps3_repository_read_num_be(unsigned int *num_be)
985{
986	int result;
987	u64 v1;
988
989	result = read_node(PS3_LPAR_ID_PME,
990		make_first_field("ben", 0),
991		0,
992		0,
993		0,
994		&v1, 0);
995	*num_be = v1;
996	return result;
997}
998
999int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id)
1000{
1001	return read_node(PS3_LPAR_ID_PME,
1002		make_first_field("be", be_index),
1003		0,
1004		0,
1005		0,
1006		node_id, 0);
1007}
1008
1009int ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq)
1010{
1011	return read_node(PS3_LPAR_ID_PME,
1012		make_first_field("be", 0),
1013		node_id,
1014		make_field("clock", 0),
1015		0,
1016		tb_freq, 0);
1017}
1018
1019int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq)
1020{
1021	int result;
1022	u64 node_id;
1023
1024	*tb_freq = 0;
1025	result = ps3_repository_read_be_node_id(0, &node_id);
1026	return result ? result
1027		: ps3_repository_read_tb_freq(node_id, tb_freq);
1028}
1029