Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  PS3 repository routines.
0004  *
0005  *  Copyright (C) 2006 Sony Computer Entertainment Inc.
0006  *  Copyright 2006 Sony Corp.
0007  */
0008 
0009 #include <asm/lv1call.h>
0010 
0011 #include "platform.h"
0012 
0013 enum ps3_vendor_id {
0014     PS3_VENDOR_ID_NONE = 0,
0015     PS3_VENDOR_ID_SONY = 0x8000000000000000UL,
0016 };
0017 
0018 enum ps3_lpar_id {
0019     PS3_LPAR_ID_CURRENT = 0,
0020     PS3_LPAR_ID_PME = 1,
0021 };
0022 
0023 #define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__)
0024 static void _dump_field(const char *hdr, u64 n, const char *func, int line)
0025 {
0026 #if defined(DEBUG)
0027     char s[16];
0028     const char *const in = (const char *)&n;
0029     unsigned int i;
0030 
0031     for (i = 0; i < 8; i++)
0032         s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.';
0033     s[i] = 0;
0034 
0035     pr_devel("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s);
0036 #endif
0037 }
0038 
0039 #define dump_node_name(_a, _b, _c, _d, _e) \
0040     _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__)
0041 static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3,
0042     u64 n4, const char *func, int line)
0043 {
0044     pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);
0045     _dump_field("n1: ", n1, func, line);
0046     _dump_field("n2: ", n2, func, line);
0047     _dump_field("n3: ", n3, func, line);
0048     _dump_field("n4: ", n4, func, line);
0049 }
0050 
0051 #define dump_node(_a, _b, _c, _d, _e, _f, _g) \
0052     _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)
0053 static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
0054     u64 v1, u64 v2, const char *func, int line)
0055 {
0056     pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id);
0057     _dump_field("n1: ", n1, func, line);
0058     _dump_field("n2: ", n2, func, line);
0059     _dump_field("n3: ", n3, func, line);
0060     _dump_field("n4: ", n4, func, line);
0061     pr_devel("%s:%d: v1: %016llx\n", func, line, v1);
0062     pr_devel("%s:%d: v2: %016llx\n", func, line, v2);
0063 }
0064 
0065 /**
0066  * make_first_field - Make the first field of a repository node name.
0067  * @text: Text portion of the field.
0068  * @index: Numeric index portion of the field.  Use zero for 'don't care'.
0069  *
0070  * This routine sets the vendor id to zero (non-vendor specific).
0071  * Returns field value.
0072  */
0073 
0074 static u64 make_first_field(const char *text, u64 index)
0075 {
0076     u64 n;
0077 
0078     strncpy((char *)&n, text, 8);
0079     return PS3_VENDOR_ID_NONE + (n >> 32) + index;
0080 }
0081 
0082 /**
0083  * make_field - Make subsequent fields of a repository node name.
0084  * @text: Text portion of the field.  Use "" for 'don't care'.
0085  * @index: Numeric index portion of the field.  Use zero for 'don't care'.
0086  *
0087  * Returns field value.
0088  */
0089 
0090 static u64 make_field(const char *text, u64 index)
0091 {
0092     u64 n = 0;
0093 
0094     memcpy((char *)&n, text, strnlen(text, sizeof(n)));
0095     return n + index;
0096 }
0097 
0098 /**
0099  * read_node - Read a repository node from raw fields.
0100  * @n1: First field of node name.
0101  * @n2: Second field of node name.  Use zero for 'don't care'.
0102  * @n3: Third field of node name.  Use zero for 'don't care'.
0103  * @n4: Fourth field of node name.  Use zero for 'don't care'.
0104  * @v1: First repository value (high word).
0105  * @v2: Second repository value (low word).  Optional parameter, use zero
0106  *      for 'don't care'.
0107  */
0108 
0109 static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
0110     u64 *_v1, u64 *_v2)
0111 {
0112     int result;
0113     u64 v1;
0114     u64 v2;
0115 
0116     if (lpar_id == PS3_LPAR_ID_CURRENT) {
0117         u64 id;
0118         lv1_get_logical_partition_id(&id);
0119         lpar_id = id;
0120     }
0121 
0122     result = lv1_read_repository_node(lpar_id, n1, n2, n3, n4, &v1,
0123         &v2);
0124 
0125     if (result) {
0126         pr_warn("%s:%d: lv1_read_repository_node failed: %s\n",
0127             __func__, __LINE__, ps3_result(result));
0128         dump_node_name(lpar_id, n1, n2, n3, n4);
0129         return -ENOENT;
0130     }
0131 
0132     dump_node(lpar_id, n1, n2, n3, n4, v1, v2);
0133 
0134     if (_v1)
0135         *_v1 = v1;
0136     if (_v2)
0137         *_v2 = v2;
0138 
0139     if (v1 && !_v1)
0140         pr_devel("%s:%d: warning: discarding non-zero v1: %016llx\n",
0141             __func__, __LINE__, v1);
0142     if (v2 && !_v2)
0143         pr_devel("%s:%d: warning: discarding non-zero v2: %016llx\n",
0144             __func__, __LINE__, v2);
0145 
0146     return 0;
0147 }
0148 
0149 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,
0150     u64 *value)
0151 {
0152     return read_node(PS3_LPAR_ID_PME,
0153         make_first_field("bus", bus_index),
0154         make_field(bus_str, 0),
0155         0, 0,
0156         value, NULL);
0157 }
0158 
0159 int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id)
0160 {
0161     return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index),
0162              make_field("id", 0), 0, 0, bus_id, NULL);
0163 }
0164 
0165 int ps3_repository_read_bus_type(unsigned int bus_index,
0166     enum ps3_bus_type *bus_type)
0167 {
0168     int result;
0169     u64 v1 = 0;
0170 
0171     result = read_node(PS3_LPAR_ID_PME,
0172         make_first_field("bus", bus_index),
0173         make_field("type", 0),
0174         0, 0,
0175         &v1, NULL);
0176     *bus_type = v1;
0177     return result;
0178 }
0179 
0180 int ps3_repository_read_bus_num_dev(unsigned int bus_index,
0181     unsigned int *num_dev)
0182 {
0183     int result;
0184     u64 v1 = 0;
0185 
0186     result = read_node(PS3_LPAR_ID_PME,
0187         make_first_field("bus", bus_index),
0188         make_field("num_dev", 0),
0189         0, 0,
0190         &v1, NULL);
0191     *num_dev = v1;
0192     return result;
0193 }
0194 
0195 int ps3_repository_read_dev_str(unsigned int bus_index,
0196     unsigned int dev_index, const char *dev_str, u64 *value)
0197 {
0198     return read_node(PS3_LPAR_ID_PME,
0199         make_first_field("bus", bus_index),
0200         make_field("dev", dev_index),
0201         make_field(dev_str, 0),
0202         0,
0203         value, NULL);
0204 }
0205 
0206 int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,
0207     u64 *dev_id)
0208 {
0209     return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index),
0210              make_field("dev", dev_index), make_field("id", 0), 0,
0211              dev_id, NULL);
0212 }
0213 
0214 int ps3_repository_read_dev_type(unsigned int bus_index,
0215     unsigned int dev_index, enum ps3_dev_type *dev_type)
0216 {
0217     int result;
0218     u64 v1 = 0;
0219 
0220     result = read_node(PS3_LPAR_ID_PME,
0221         make_first_field("bus", bus_index),
0222         make_field("dev", dev_index),
0223         make_field("type", 0),
0224         0,
0225         &v1, NULL);
0226     *dev_type = v1;
0227     return result;
0228 }
0229 
0230 int ps3_repository_read_dev_intr(unsigned int bus_index,
0231     unsigned int dev_index, unsigned int intr_index,
0232     enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id)
0233 {
0234     int result;
0235     u64 v1 = 0;
0236     u64 v2 = 0;
0237 
0238     result = read_node(PS3_LPAR_ID_PME,
0239         make_first_field("bus", bus_index),
0240         make_field("dev", dev_index),
0241         make_field("intr", intr_index),
0242         0,
0243         &v1, &v2);
0244     *intr_type = v1;
0245     *interrupt_id = v2;
0246     return result;
0247 }
0248 
0249 int ps3_repository_read_dev_reg_type(unsigned int bus_index,
0250     unsigned int dev_index, unsigned int reg_index,
0251     enum ps3_reg_type *reg_type)
0252 {
0253     int result;
0254     u64 v1 = 0;
0255 
0256     result = read_node(PS3_LPAR_ID_PME,
0257         make_first_field("bus", bus_index),
0258         make_field("dev", dev_index),
0259         make_field("reg", reg_index),
0260         make_field("type", 0),
0261         &v1, NULL);
0262     *reg_type = v1;
0263     return result;
0264 }
0265 
0266 int ps3_repository_read_dev_reg_addr(unsigned int bus_index,
0267     unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len)
0268 {
0269     return read_node(PS3_LPAR_ID_PME,
0270         make_first_field("bus", bus_index),
0271         make_field("dev", dev_index),
0272         make_field("reg", reg_index),
0273         make_field("data", 0),
0274         bus_addr, len);
0275 }
0276 
0277 int ps3_repository_read_dev_reg(unsigned int bus_index,
0278     unsigned int dev_index, unsigned int reg_index,
0279     enum ps3_reg_type *reg_type, u64 *bus_addr, u64 *len)
0280 {
0281     int result = ps3_repository_read_dev_reg_type(bus_index, dev_index,
0282         reg_index, reg_type);
0283     return result ? result
0284         : ps3_repository_read_dev_reg_addr(bus_index, dev_index,
0285         reg_index, bus_addr, len);
0286 }
0287 
0288 
0289 
0290 int ps3_repository_find_device(struct ps3_repository_device *repo)
0291 {
0292     int result;
0293     struct ps3_repository_device tmp = *repo;
0294     unsigned int num_dev;
0295 
0296     BUG_ON(repo->bus_index > 10);
0297     BUG_ON(repo->dev_index > 10);
0298 
0299     result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
0300 
0301     if (result) {
0302         pr_devel("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);
0303         return result;
0304     }
0305 
0306     pr_devel("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n",
0307         __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
0308         num_dev);
0309 
0310     if (tmp.dev_index >= num_dev) {
0311         pr_devel("%s:%d: no device found\n", __func__, __LINE__);
0312         return -ENODEV;
0313     }
0314 
0315     result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
0316         &tmp.dev_type);
0317 
0318     if (result) {
0319         pr_devel("%s:%d read_dev_type failed\n", __func__, __LINE__);
0320         return result;
0321     }
0322 
0323     result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,
0324         &tmp.dev_id);
0325 
0326     if (result) {
0327         pr_devel("%s:%d ps3_repository_read_dev_id failed\n", __func__,
0328         __LINE__);
0329         return result;
0330     }
0331 
0332     pr_devel("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n",
0333         __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
0334 
0335     *repo = tmp;
0336     return 0;
0337 }
0338 
0339 int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
0340                      u64 bus_id, u64 dev_id)
0341 {
0342     int result = -ENODEV;
0343     struct ps3_repository_device tmp;
0344     unsigned int num_dev;
0345 
0346     pr_devel(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__,
0347          bus_id, dev_id);
0348 
0349     for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) {
0350         result = ps3_repository_read_bus_id(tmp.bus_index,
0351                             &tmp.bus_id);
0352         if (result) {
0353             pr_devel("%s:%u read_bus_id(%u) failed\n", __func__,
0354                  __LINE__, tmp.bus_index);
0355             return result;
0356         }
0357 
0358         if (tmp.bus_id == bus_id)
0359             goto found_bus;
0360 
0361         pr_devel("%s:%u: skip, bus_id %llu\n", __func__, __LINE__,
0362              tmp.bus_id);
0363     }
0364     pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);
0365     return result;
0366 
0367 found_bus:
0368     result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type);
0369     if (result) {
0370         pr_devel("%s:%u read_bus_type(%u) failed\n", __func__,
0371              __LINE__, tmp.bus_index);
0372         return result;
0373     }
0374 
0375     result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);
0376     if (result) {
0377         pr_devel("%s:%u read_bus_num_dev failed\n", __func__,
0378              __LINE__);
0379         return result;
0380     }
0381 
0382     for (tmp.dev_index = 0; tmp.dev_index < num_dev; tmp.dev_index++) {
0383         result = ps3_repository_read_dev_id(tmp.bus_index,
0384                             tmp.dev_index,
0385                             &tmp.dev_id);
0386         if (result) {
0387             pr_devel("%s:%u read_dev_id(%u:%u) failed\n", __func__,
0388                  __LINE__, tmp.bus_index, tmp.dev_index);
0389             return result;
0390         }
0391 
0392         if (tmp.dev_id == dev_id)
0393             goto found_dev;
0394 
0395         pr_devel("%s:%u: skip, dev_id %llu\n", __func__, __LINE__,
0396              tmp.dev_id);
0397     }
0398     pr_devel(" <- %s:%u: dev not found\n", __func__, __LINE__);
0399     return result;
0400 
0401 found_dev:
0402     result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,
0403                           &tmp.dev_type);
0404     if (result) {
0405         pr_devel("%s:%u read_dev_type failed\n", __func__, __LINE__);
0406         return result;
0407     }
0408 
0409     pr_devel(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n",
0410          __func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index,
0411          tmp.dev_index, tmp.bus_id, tmp.dev_id);
0412     *repo = tmp;
0413     return 0;
0414 }
0415 
0416 int __init ps3_repository_find_devices(enum ps3_bus_type bus_type,
0417     int (*callback)(const struct ps3_repository_device *repo))
0418 {
0419     int result = 0;
0420     struct ps3_repository_device repo;
0421 
0422     pr_devel(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);
0423 
0424     repo.bus_type = bus_type;
0425     result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index);
0426     if (result) {
0427         pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__);
0428         return result;
0429     }
0430 
0431     result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id);
0432     if (result) {
0433         pr_devel("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__,
0434              repo.bus_index);
0435         return result;
0436     }
0437 
0438     for (repo.dev_index = 0; ; repo.dev_index++) {
0439         result = ps3_repository_find_device(&repo);
0440         if (result == -ENODEV) {
0441             result = 0;
0442             break;
0443         } else if (result)
0444             break;
0445 
0446         result = callback(&repo);
0447         if (result) {
0448             pr_devel("%s:%d: abort at callback\n", __func__,
0449                 __LINE__);
0450             break;
0451         }
0452     }
0453 
0454     pr_devel(" <- %s:%d\n", __func__, __LINE__);
0455     return result;
0456 }
0457 
0458 int __init ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,
0459     unsigned int *bus_index)
0460 {
0461     unsigned int i;
0462     enum ps3_bus_type type;
0463     int error;
0464 
0465     for (i = from; i < 10; i++) {
0466         error = ps3_repository_read_bus_type(i, &type);
0467         if (error) {
0468             pr_devel("%s:%d read_bus_type failed\n",
0469                 __func__, __LINE__);
0470             *bus_index = UINT_MAX;
0471             return error;
0472         }
0473         if (type == bus_type) {
0474             *bus_index = i;
0475             return 0;
0476         }
0477     }
0478     *bus_index = UINT_MAX;
0479     return -ENODEV;
0480 }
0481 
0482 int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,
0483     enum ps3_interrupt_type intr_type, unsigned int *interrupt_id)
0484 {
0485     int result = 0;
0486     unsigned int res_index;
0487 
0488     pr_devel("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type);
0489 
0490     *interrupt_id = UINT_MAX;
0491 
0492     for (res_index = 0; res_index < 10; res_index++) {
0493         enum ps3_interrupt_type t;
0494         unsigned int id;
0495 
0496         result = ps3_repository_read_dev_intr(repo->bus_index,
0497             repo->dev_index, res_index, &t, &id);
0498 
0499         if (result) {
0500             pr_devel("%s:%d read_dev_intr failed\n",
0501                 __func__, __LINE__);
0502             return result;
0503         }
0504 
0505         if (t == intr_type) {
0506             *interrupt_id = id;
0507             break;
0508         }
0509     }
0510 
0511     if (res_index == 10)
0512         return -ENODEV;
0513 
0514     pr_devel("%s:%d: found intr_type %u at res_index %u\n",
0515         __func__, __LINE__, intr_type, res_index);
0516 
0517     return result;
0518 }
0519 
0520 int ps3_repository_find_reg(const struct ps3_repository_device *repo,
0521     enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len)
0522 {
0523     int result = 0;
0524     unsigned int res_index;
0525 
0526     pr_devel("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type);
0527 
0528     *bus_addr = *len = 0;
0529 
0530     for (res_index = 0; res_index < 10; res_index++) {
0531         enum ps3_reg_type t;
0532         u64 a;
0533         u64 l;
0534 
0535         result = ps3_repository_read_dev_reg(repo->bus_index,
0536             repo->dev_index, res_index, &t, &a, &l);
0537 
0538         if (result) {
0539             pr_devel("%s:%d read_dev_reg failed\n",
0540                 __func__, __LINE__);
0541             return result;
0542         }
0543 
0544         if (t == reg_type) {
0545             *bus_addr = a;
0546             *len = l;
0547             break;
0548         }
0549     }
0550 
0551     if (res_index == 10)
0552         return -ENODEV;
0553 
0554     pr_devel("%s:%d: found reg_type %u at res_index %u\n",
0555         __func__, __LINE__, reg_type, res_index);
0556 
0557     return result;
0558 }
0559 
0560 int ps3_repository_read_stor_dev_port(unsigned int bus_index,
0561     unsigned int dev_index, u64 *port)
0562 {
0563     return read_node(PS3_LPAR_ID_PME,
0564         make_first_field("bus", bus_index),
0565         make_field("dev", dev_index),
0566         make_field("port", 0),
0567         0, port, NULL);
0568 }
0569 
0570 int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index,
0571     unsigned int dev_index, u64 *blk_size)
0572 {
0573     return read_node(PS3_LPAR_ID_PME,
0574         make_first_field("bus", bus_index),
0575         make_field("dev", dev_index),
0576         make_field("blk_size", 0),
0577         0, blk_size, NULL);
0578 }
0579 
0580 int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index,
0581     unsigned int dev_index, u64 *num_blocks)
0582 {
0583     return read_node(PS3_LPAR_ID_PME,
0584         make_first_field("bus", bus_index),
0585         make_field("dev", dev_index),
0586         make_field("n_blocks", 0),
0587         0, num_blocks, NULL);
0588 }
0589 
0590 int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index,
0591     unsigned int dev_index, unsigned int *num_regions)
0592 {
0593     int result;
0594     u64 v1 = 0;
0595 
0596     result = read_node(PS3_LPAR_ID_PME,
0597         make_first_field("bus", bus_index),
0598         make_field("dev", dev_index),
0599         make_field("n_regs", 0),
0600         0, &v1, NULL);
0601     *num_regions = v1;
0602     return result;
0603 }
0604 
0605 int ps3_repository_read_stor_dev_region_id(unsigned int bus_index,
0606     unsigned int dev_index, unsigned int region_index,
0607     unsigned int *region_id)
0608 {
0609     int result;
0610     u64 v1 = 0;
0611 
0612     result = read_node(PS3_LPAR_ID_PME,
0613         make_first_field("bus", bus_index),
0614         make_field("dev", dev_index),
0615         make_field("region", region_index),
0616         make_field("id", 0),
0617         &v1, NULL);
0618     *region_id = v1;
0619     return result;
0620 }
0621 
0622 int ps3_repository_read_stor_dev_region_size(unsigned int bus_index,
0623     unsigned int dev_index, unsigned int region_index, u64 *region_size)
0624 {
0625     return read_node(PS3_LPAR_ID_PME,
0626         make_first_field("bus", bus_index),
0627         make_field("dev", dev_index),
0628         make_field("region", region_index),
0629         make_field("size", 0),
0630         region_size, NULL);
0631 }
0632 
0633 int ps3_repository_read_stor_dev_region_start(unsigned int bus_index,
0634     unsigned int dev_index, unsigned int region_index, u64 *region_start)
0635 {
0636     return read_node(PS3_LPAR_ID_PME,
0637         make_first_field("bus", bus_index),
0638         make_field("dev", dev_index),
0639         make_field("region", region_index),
0640         make_field("start", 0),
0641         region_start, NULL);
0642 }
0643 
0644 int ps3_repository_read_stor_dev_info(unsigned int bus_index,
0645     unsigned int dev_index, u64 *port, u64 *blk_size,
0646     u64 *num_blocks, unsigned int *num_regions)
0647 {
0648     int result;
0649 
0650     result = ps3_repository_read_stor_dev_port(bus_index, dev_index, port);
0651     if (result)
0652         return result;
0653 
0654     result = ps3_repository_read_stor_dev_blk_size(bus_index, dev_index,
0655         blk_size);
0656     if (result)
0657         return result;
0658 
0659     result = ps3_repository_read_stor_dev_num_blocks(bus_index, dev_index,
0660         num_blocks);
0661     if (result)
0662         return result;
0663 
0664     result = ps3_repository_read_stor_dev_num_regions(bus_index, dev_index,
0665         num_regions);
0666     return result;
0667 }
0668 
0669 int ps3_repository_read_stor_dev_region(unsigned int bus_index,
0670     unsigned int dev_index, unsigned int region_index,
0671     unsigned int *region_id, u64 *region_start, u64 *region_size)
0672 {
0673     int result;
0674 
0675     result = ps3_repository_read_stor_dev_region_id(bus_index, dev_index,
0676         region_index, region_id);
0677     if (result)
0678         return result;
0679 
0680     result = ps3_repository_read_stor_dev_region_start(bus_index, dev_index,
0681         region_index, region_start);
0682     if (result)
0683         return result;
0684 
0685     result = ps3_repository_read_stor_dev_region_size(bus_index, dev_index,
0686         region_index, region_size);
0687     return result;
0688 }
0689 
0690 /**
0691  * ps3_repository_read_num_pu - Number of logical PU processors for this lpar.
0692  */
0693 
0694 int ps3_repository_read_num_pu(u64 *num_pu)
0695 {
0696     *num_pu = 0;
0697     return read_node(PS3_LPAR_ID_CURRENT,
0698                make_first_field("bi", 0),
0699                make_field("pun", 0),
0700                0, 0,
0701                num_pu, NULL);
0702 }
0703 
0704 /**
0705  * ps3_repository_read_pu_id - Read the logical PU id.
0706  * @pu_index: Zero based index.
0707  * @pu_id: The logical PU id.
0708  */
0709 
0710 int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id)
0711 {
0712     return read_node(PS3_LPAR_ID_CURRENT,
0713         make_first_field("bi", 0),
0714         make_field("pu", pu_index),
0715         0, 0,
0716         pu_id, NULL);
0717 }
0718 
0719 int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size)
0720 {
0721     return read_node(PS3_LPAR_ID_CURRENT,
0722         make_first_field("bi", 0),
0723         make_field("pu", 0),
0724         ppe_id,
0725         make_field("rm_size", 0),
0726         rm_size, NULL);
0727 }
0728 
0729 int ps3_repository_read_region_total(u64 *region_total)
0730 {
0731     return read_node(PS3_LPAR_ID_CURRENT,
0732         make_first_field("bi", 0),
0733         make_field("rgntotal", 0),
0734         0, 0,
0735         region_total, NULL);
0736 }
0737 
0738 /**
0739  * ps3_repository_read_mm_info - Read mm info for single pu system.
0740  * @rm_base: Real mode memory base address.
0741  * @rm_size: Real mode memory size.
0742  * @region_total: Maximum memory region size.
0743  */
0744 
0745 int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
0746 {
0747     int result;
0748     u64 ppe_id;
0749 
0750     lv1_get_logical_ppe_id(&ppe_id);
0751     *rm_base = 0;
0752     result = ps3_repository_read_rm_size(ppe_id, rm_size);
0753     return result ? result
0754         : ps3_repository_read_region_total(region_total);
0755 }
0756 
0757 /**
0758  * ps3_repository_read_highmem_region_count - Read the number of highmem regions
0759  *
0760  * Bootloaders must arrange the repository nodes such that regions are indexed
0761  * with a region_index from 0 to region_count-1.
0762  */
0763 
0764 int ps3_repository_read_highmem_region_count(unsigned int *region_count)
0765 {
0766     int result;
0767     u64 v1 = 0;
0768 
0769     result = read_node(PS3_LPAR_ID_CURRENT,
0770         make_first_field("highmem", 0),
0771         make_field("region", 0),
0772         make_field("count", 0),
0773         0,
0774         &v1, NULL);
0775     *region_count = v1;
0776     return result;
0777 }
0778 
0779 
0780 int ps3_repository_read_highmem_base(unsigned int region_index,
0781     u64 *highmem_base)
0782 {
0783     return read_node(PS3_LPAR_ID_CURRENT,
0784         make_first_field("highmem", 0),
0785         make_field("region", region_index),
0786         make_field("base", 0),
0787         0,
0788         highmem_base, NULL);
0789 }
0790 
0791 int ps3_repository_read_highmem_size(unsigned int region_index,
0792     u64 *highmem_size)
0793 {
0794     return read_node(PS3_LPAR_ID_CURRENT,
0795         make_first_field("highmem", 0),
0796         make_field("region", region_index),
0797         make_field("size", 0),
0798         0,
0799         highmem_size, NULL);
0800 }
0801 
0802 /**
0803  * ps3_repository_read_highmem_info - Read high memory region info
0804  * @region_index: Region index, {0,..,region_count-1}.
0805  * @highmem_base: High memory base address.
0806  * @highmem_size: High memory size.
0807  *
0808  * Bootloaders that preallocate highmem regions must place the
0809  * region info into the repository at these well known nodes.
0810  */
0811 
0812 int ps3_repository_read_highmem_info(unsigned int region_index,
0813     u64 *highmem_base, u64 *highmem_size)
0814 {
0815     int result;
0816 
0817     *highmem_base = 0;
0818     result = ps3_repository_read_highmem_base(region_index, highmem_base);
0819     return result ? result
0820         : ps3_repository_read_highmem_size(region_index, highmem_size);
0821 }
0822 
0823 /**
0824  * ps3_repository_read_num_spu_reserved - Number of physical spus reserved.
0825  * @num_spu: Number of physical spus.
0826  */
0827 
0828 int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
0829 {
0830     int result;
0831     u64 v1 = 0;
0832 
0833     result = read_node(PS3_LPAR_ID_CURRENT,
0834         make_first_field("bi", 0),
0835         make_field("spun", 0),
0836         0, 0,
0837         &v1, NULL);
0838     *num_spu_reserved = v1;
0839     return result;
0840 }
0841 
0842 /**
0843  * ps3_repository_read_num_spu_resource_id - Number of spu resource reservations.
0844  * @num_resource_id: Number of spu resource ids.
0845  */
0846 
0847 int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
0848 {
0849     int result;
0850     u64 v1 = 0;
0851 
0852     result = read_node(PS3_LPAR_ID_CURRENT,
0853         make_first_field("bi", 0),
0854         make_field("spursvn", 0),
0855         0, 0,
0856         &v1, NULL);
0857     *num_resource_id = v1;
0858     return result;
0859 }
0860 
0861 /**
0862  * ps3_repository_read_spu_resource_id - spu resource reservation id value.
0863  * @res_index: Resource reservation index.
0864  * @resource_type: Resource reservation type.
0865  * @resource_id: Resource reservation id.
0866  */
0867 
0868 int ps3_repository_read_spu_resource_id(unsigned int res_index,
0869     enum ps3_spu_resource_type *resource_type, unsigned int *resource_id)
0870 {
0871     int result;
0872     u64 v1 = 0;
0873     u64 v2 = 0;
0874 
0875     result = read_node(PS3_LPAR_ID_CURRENT,
0876         make_first_field("bi", 0),
0877         make_field("spursv", 0),
0878         res_index,
0879         0,
0880         &v1, &v2);
0881     *resource_type = v1;
0882     *resource_id = v2;
0883     return result;
0884 }
0885 
0886 static int ps3_repository_read_boot_dat_address(u64 *address)
0887 {
0888     return read_node(PS3_LPAR_ID_CURRENT,
0889         make_first_field("bi", 0),
0890         make_field("boot_dat", 0),
0891         make_field("address", 0),
0892         0,
0893         address, NULL);
0894 }
0895 
0896 int ps3_repository_read_boot_dat_size(unsigned int *size)
0897 {
0898     int result;
0899     u64 v1 = 0;
0900 
0901     result = read_node(PS3_LPAR_ID_CURRENT,
0902         make_first_field("bi", 0),
0903         make_field("boot_dat", 0),
0904         make_field("size", 0),
0905         0,
0906         &v1, NULL);
0907     *size = v1;
0908     return result;
0909 }
0910 
0911 int __init ps3_repository_read_vuart_av_port(unsigned int *port)
0912 {
0913     int result;
0914     u64 v1 = 0;
0915 
0916     result = read_node(PS3_LPAR_ID_CURRENT,
0917         make_first_field("bi", 0),
0918         make_field("vir_uart", 0),
0919         make_field("port", 0),
0920         make_field("avset", 0),
0921         &v1, NULL);
0922     *port = v1;
0923     return result;
0924 }
0925 
0926 int __init ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
0927 {
0928     int result;
0929     u64 v1 = 0;
0930 
0931     result = read_node(PS3_LPAR_ID_CURRENT,
0932         make_first_field("bi", 0),
0933         make_field("vir_uart", 0),
0934         make_field("port", 0),
0935         make_field("sysmgr", 0),
0936         &v1, NULL);
0937     *port = v1;
0938     return result;
0939 }
0940 
0941 /**
0942   * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area.
0943   * address: lpar address of cell_ext_os_area
0944   * @size: size of cell_ext_os_area
0945   */
0946 
0947 int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size)
0948 {
0949     int result;
0950 
0951     *size = 0;
0952     result = ps3_repository_read_boot_dat_address(lpar_addr);
0953     return result ? result
0954         : ps3_repository_read_boot_dat_size(size);
0955 }
0956 
0957 /**
0958  * ps3_repository_read_num_be - Number of physical BE processors in the system.
0959  */
0960 
0961 int ps3_repository_read_num_be(unsigned int *num_be)
0962 {
0963     int result;
0964     u64 v1 = 0;
0965 
0966     result = read_node(PS3_LPAR_ID_PME,
0967         make_first_field("ben", 0),
0968         0,
0969         0,
0970         0,
0971         &v1, NULL);
0972     *num_be = v1;
0973     return result;
0974 }
0975 
0976 /**
0977  * ps3_repository_read_be_node_id - Read the physical BE processor node id.
0978  * @be_index: Zero based index.
0979  * @node_id: The BE processor node id.
0980  */
0981 
0982 int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id)
0983 {
0984     return read_node(PS3_LPAR_ID_PME,
0985         make_first_field("be", be_index),
0986         0,
0987         0,
0988         0,
0989         node_id, NULL);
0990 }
0991 
0992 /**
0993  * ps3_repository_read_be_id - Read the physical BE processor id.
0994  * @node_id: The BE processor node id.
0995  * @be_id: The BE processor id.
0996  */
0997 
0998 int ps3_repository_read_be_id(u64 node_id, u64 *be_id)
0999 {
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) */