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