Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart
[linux-drm-fsl-dcu.git] / arch / powerpc / platforms / ps3 / repository.c
index 273a0d621bdd6bbc7bbffd8ec980ac9ac313494f..ae586a0e5d3f9c75771058b7c22b9279fc8cb237 100644 (file)
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <asm/ps3.h>
 #include <asm/lv1call.h>
 
+#include "platform.h"
+
 enum ps3_vendor_id {
        PS3_VENDOR_ID_NONE = 0,
        PS3_VENDOR_ID_SONY = 0x8000000000000000UL,
@@ -257,7 +258,7 @@ int ps3_repository_read_dev_type(unsigned int bus_index,
 
 int ps3_repository_read_dev_intr(unsigned int bus_index,
        unsigned int dev_index, unsigned int intr_index,
-       unsigned int *intr_type, unsigned int* interrupt_id)
+       enum ps3_interrupt_type *intr_type, unsigned int* interrupt_id)
 {
        int result;
        u64 v1;
@@ -275,7 +276,8 @@ int ps3_repository_read_dev_intr(unsigned int bus_index,
 }
 
 int ps3_repository_read_dev_reg_type(unsigned int bus_index,
-       unsigned int dev_index, unsigned int reg_index, unsigned int *reg_type)
+       unsigned int dev_index, unsigned int reg_index,
+       enum ps3_reg_type *reg_type)
 {
        int result;
        u64 v1;
@@ -302,8 +304,8 @@ int ps3_repository_read_dev_reg_addr(unsigned int bus_index,
 }
 
 int ps3_repository_read_dev_reg(unsigned int bus_index,
-       unsigned int dev_index, unsigned int reg_index, unsigned int *reg_type,
-       u64 *bus_addr, u64 *len)
+       unsigned int dev_index, unsigned int reg_index,
+       enum ps3_reg_type *reg_type, u64 *bus_addr, u64 *len)
 {
        int result = ps3_repository_read_dev_reg_type(bus_index, dev_index,
                reg_index, reg_type);
@@ -343,7 +345,7 @@ int ps3_repository_dump_resource_info(unsigned int bus_index,
        }
 
        for (res_index = 0; res_index < 10; res_index++) {
-               enum ps3_region_type reg_type;
+               enum ps3_reg_type reg_type;
                u64 bus_addr;
                u64 len;
 
@@ -367,7 +369,55 @@ int ps3_repository_dump_resource_info(unsigned int bus_index,
        return result;
 }
 
-static int dump_device_info(unsigned int bus_index, unsigned int num_dev)
+static int dump_stor_dev_info(unsigned int bus_index, unsigned int dev_index)
+{
+       int result = 0;
+       unsigned int num_regions, region_index;
+       u64 port, blk_size, num_blocks;
+
+       pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__,
+               bus_index, dev_index);
+
+       result = ps3_repository_read_stor_dev_info(bus_index, dev_index, &port,
+               &blk_size, &num_blocks, &num_regions);
+       if (result) {
+               pr_debug("%s:%d ps3_repository_read_stor_dev_info"
+                       " (%u:%u) failed\n", __func__, __LINE__,
+                       bus_index, dev_index);
+               goto out;
+       }
+
+       pr_debug("%s:%d  (%u:%u): port %lu, blk_size %lu, num_blocks "
+                "%lu, num_regions %u\n",
+                __func__, __LINE__, bus_index, dev_index, port,
+                blk_size, num_blocks, num_regions);
+
+       for (region_index = 0; region_index < num_regions; region_index++) {
+               unsigned int region_id;
+               u64 region_start, region_size;
+
+               result = ps3_repository_read_stor_dev_region(bus_index,
+                       dev_index, region_index, &region_id, &region_start,
+                       &region_size);
+               if (result) {
+                        pr_debug("%s:%d ps3_repository_read_stor_dev_region"
+                                 " (%u:%u) failed\n", __func__, __LINE__,
+                                 bus_index, dev_index);
+                       break;
+               }
+
+               pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n",
+                        __func__, __LINE__, bus_index, dev_index, region_id,
+                        region_start, region_size);
+       }
+
+out:
+       pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return result;
+}
+
+static int dump_device_info(unsigned int bus_index, enum ps3_bus_type bus_type,
+                           unsigned int num_dev)
 {
        int result = 0;
        unsigned int dev_index;
@@ -402,6 +452,9 @@ static int dump_device_info(unsigned int bus_index, unsigned int num_dev)
                        __LINE__, bus_index, dev_index, dev_type, dev_id);
 
                ps3_repository_dump_resource_info(bus_index, dev_index);
+
+               if (bus_type == PS3_BUS_TYPE_STORAGE)
+                       dump_stor_dev_info(bus_index, dev_index);
        }
 
        pr_debug(" <- %s:%d\n", __func__, __LINE__);
@@ -452,7 +505,7 @@ int ps3_repository_dump_bus_info(void)
                        __func__, __LINE__, bus_index, bus_type, bus_id,
                        num_dev);
 
-               dump_device_info(bus_index, num_dev);
+               dump_device_info(bus_index, bus_type, num_dev);
        }
 
        pr_debug(" <- %s:%d\n", __func__, __LINE__);
@@ -487,7 +540,8 @@ static int find_device(unsigned int bus_index, unsigned int num_dev,
                        break;
        }
 
-       BUG_ON(dev_index == num_dev);
+       if (dev_index == num_dev)
+               return -1;
 
        pr_debug("%s:%d: found dev_type %u at dev_index %u\n",
                __func__, __LINE__, dev_type, dev_index);
@@ -521,7 +575,7 @@ int ps3_repository_find_device (enum ps3_bus_type bus_type,
        pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__,
                bus_type, dev_type);
 
-       dev->bus_index = UINT_MAX;
+       BUG_ON(start_dev && start_dev->bus_index > 10);
 
        for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10;
                bus_index++) {
@@ -532,13 +586,15 @@ int ps3_repository_find_device (enum ps3_bus_type bus_type,
                if (result) {
                        pr_debug("%s:%d read_bus_type failed\n",
                                __func__, __LINE__);
+                       dev->bus_index = UINT_MAX;
                        return result;
                }
                if (x == bus_type)
                        break;
        }
 
-       BUG_ON(bus_index == 10);
+       if (bus_index >= 10)
+               return -ENODEV;
 
        pr_debug("%s:%d: found bus_type %u at bus_index %u\n",
                __func__, __LINE__, bus_type, bus_index);
@@ -604,7 +660,8 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
                }
        }
 
-       BUG_ON(res_index == 10);
+       if (res_index == 10)
+               return -ENODEV;
 
        pr_debug("%s:%d: found intr_type %u at res_index %u\n",
                __func__, __LINE__, intr_type, res_index);
@@ -612,8 +669,8 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *dev,
        return result;
 }
 
-int ps3_repository_find_region(const struct ps3_repository_device *dev,
-       enum ps3_region_type reg_type, u64 *bus_addr, u64 *len)
+int ps3_repository_find_reg(const struct ps3_repository_device *dev,
+       enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len)
 {
        int result = 0;
        unsigned int res_index;
@@ -623,7 +680,7 @@ int ps3_repository_find_region(const struct ps3_repository_device *dev,
        *bus_addr = *len = 0;
 
        for (res_index = 0; res_index < 10; res_index++) {
-               enum ps3_region_type t;
+               enum ps3_reg_type t;
                u64 a;
                u64 l;
 
@@ -643,7 +700,8 @@ int ps3_repository_find_region(const struct ps3_repository_device *dev,
                }
        }
 
-       BUG_ON(res_index == 10);
+       if (res_index == 10)
+               return -ENODEV;
 
        pr_debug("%s:%d: found reg_type %u at res_index %u\n",
                __func__, __LINE__, reg_type, res_index);
@@ -651,6 +709,136 @@ int ps3_repository_find_region(const struct ps3_repository_device *dev,
        return result;
 }
 
+int ps3_repository_read_stor_dev_port(unsigned int bus_index,
+       unsigned int dev_index, u64 *port)
+{
+       return read_node(PS3_LPAR_ID_PME,
+               make_first_field("bus", bus_index),
+               make_field("dev", dev_index),
+               make_field("port", 0),
+               0, port, 0);
+}
+
+int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index,
+       unsigned int dev_index, u64 *blk_size)
+{
+       return read_node(PS3_LPAR_ID_PME,
+               make_first_field("bus", bus_index),
+               make_field("dev", dev_index),
+               make_field("blk_size", 0),
+               0, blk_size, 0);
+}
+
+int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index,
+       unsigned int dev_index, u64 *num_blocks)
+{
+       return read_node(PS3_LPAR_ID_PME,
+               make_first_field("bus", bus_index),
+               make_field("dev", dev_index),
+               make_field("n_blocks", 0),
+               0, num_blocks, 0);
+}
+
+int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index,
+       unsigned int dev_index, unsigned int *num_regions)
+{
+       int result;
+       u64 v1;
+
+       result = read_node(PS3_LPAR_ID_PME,
+               make_first_field("bus", bus_index),
+               make_field("dev", dev_index),
+               make_field("n_regs", 0),
+               0, &v1, 0);
+       *num_regions = v1;
+       return result;
+}
+
+int ps3_repository_read_stor_dev_region_id(unsigned int bus_index,
+       unsigned int dev_index, unsigned int region_index,
+       unsigned int *region_id)
+{
+       int result;
+       u64 v1;
+
+       result = read_node(PS3_LPAR_ID_PME,
+           make_first_field("bus", bus_index),
+           make_field("dev", dev_index),
+           make_field("region", region_index),
+           make_field("id", 0),
+           &v1, 0);
+       *region_id = v1;
+       return result;
+}
+
+int ps3_repository_read_stor_dev_region_size(unsigned int bus_index,
+       unsigned int dev_index, unsigned int region_index, u64 *region_size)
+{
+       return read_node(PS3_LPAR_ID_PME,
+           make_first_field("bus", bus_index),
+           make_field("dev", dev_index),
+           make_field("region", region_index),
+           make_field("size", 0),
+           region_size, 0);
+}
+
+int ps3_repository_read_stor_dev_region_start(unsigned int bus_index,
+       unsigned int dev_index, unsigned int region_index, u64 *region_start)
+{
+       return read_node(PS3_LPAR_ID_PME,
+           make_first_field("bus", bus_index),
+           make_field("dev", dev_index),
+           make_field("region", region_index),
+           make_field("start", 0),
+           region_start, 0);
+}
+
+int ps3_repository_read_stor_dev_info(unsigned int bus_index,
+       unsigned int dev_index, u64 *port, u64 *blk_size,
+       u64 *num_blocks, unsigned int *num_regions)
+{
+       int result;
+
+       result = ps3_repository_read_stor_dev_port(bus_index, dev_index, port);
+       if (result)
+           return result;
+
+       result = ps3_repository_read_stor_dev_blk_size(bus_index, dev_index,
+               blk_size);
+       if (result)
+           return result;
+
+       result = ps3_repository_read_stor_dev_num_blocks(bus_index, dev_index,
+               num_blocks);
+       if (result)
+           return result;
+
+       result = ps3_repository_read_stor_dev_num_regions(bus_index, dev_index,
+               num_regions);
+       return result;
+}
+
+int ps3_repository_read_stor_dev_region(unsigned int bus_index,
+       unsigned int dev_index, unsigned int region_index,
+       unsigned int *region_id, u64 *region_start, u64 *region_size)
+{
+       int result;
+
+       result = ps3_repository_read_stor_dev_region_id(bus_index, dev_index,
+               region_index, region_id);
+       if (result)
+           return result;
+
+       result = ps3_repository_read_stor_dev_region_start(bus_index, dev_index,
+               region_index, region_start);
+       if (result)
+           return result;
+
+       result = ps3_repository_read_stor_dev_region_size(bus_index, dev_index,
+               region_index, region_size);
+       return result;
+}
+
 int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size)
 {
        return read_node(PS3_LPAR_ID_CURRENT,