return err;
 }
 
+static struct regmap *felix_request_regmap_by_name(struct felix *felix,
+                                                  const char *resource_name)
+{
+       struct ocelot *ocelot = &felix->ocelot;
+       struct resource res;
+       int i;
+
+       for (i = 0; i < felix->info->num_resources; i++) {
+               if (strcmp(resource_name, felix->info->resources[i].name))
+                       continue;
+
+               memcpy(&res, &felix->info->resources[i], sizeof(res));
+               res.start += felix->switch_base;
+               res.end += felix->switch_base;
+
+               return ocelot_regmap_init(ocelot, &res);
+       }
+
+       return ERR_PTR(-ENOENT);
+}
+
+static struct regmap *felix_request_regmap(struct felix *felix,
+                                          enum ocelot_target target)
+{
+       const char *resource_name = felix->info->resource_names[target];
+
+       /* If the driver didn't provide a resource name for the target,
+        * the resource is optional.
+        */
+       if (!resource_name)
+               return NULL;
+
+       return felix_request_regmap_by_name(felix, resource_name);
+}
+
+static struct regmap *felix_request_port_regmap(struct felix *felix, int port)
+{
+       char resource_name[32];
+
+       sprintf(resource_name, "port%d", port);
+
+       return felix_request_regmap_by_name(felix, resource_name);
+}
+
 static int felix_init_structs(struct felix *felix, int num_phys_ports)
 {
        struct ocelot *ocelot = &felix->ocelot;
        phy_interface_t *port_phy_modes;
-       struct resource res;
+       struct regmap *target;
        int port, i, err;
 
        ocelot->num_phys_ports = num_phys_ports;
        }
 
        for (i = 0; i < TARGET_MAX; i++) {
-               struct regmap *target;
-
-               if (!felix->info->target_io_res[i].name)
-                       continue;
-
-               memcpy(&res, &felix->info->target_io_res[i], sizeof(res));
-               res.start += felix->switch_base;
-               res.end += felix->switch_base;
-
-               target = ocelot_regmap_init(ocelot, &res);
+               target = felix_request_regmap(felix, i);
                if (IS_ERR(target)) {
                        dev_err(ocelot->dev,
-                               "Failed to map device memory space\n");
+                               "Failed to map device memory space: %pe\n",
+                               target);
                        kfree(port_phy_modes);
                        return PTR_ERR(target);
                }
 
        for (port = 0; port < num_phys_ports; port++) {
                struct ocelot_port *ocelot_port;
-               struct regmap *target;
 
                ocelot_port = devm_kzalloc(ocelot->dev,
                                           sizeof(struct ocelot_port),
                        return -ENOMEM;
                }
 
-               memcpy(&res, &felix->info->port_io_res[port], sizeof(res));
-               res.start += felix->switch_base;
-               res.end += felix->switch_base;
-
-               target = ocelot_regmap_init(ocelot, &res);
+               target = felix_request_port_regmap(felix, port);
                if (IS_ERR(target)) {
                        dev_err(ocelot->dev,
-                               "Failed to map memory space for port %d\n",
-                               port);
+                               "Failed to map memory space for port %d: %pe\n",
+                               port, target);
                        kfree(port_phy_modes);
                        return PTR_ERR(target);
                }
 
 
 /* Platform-specific information */
 struct felix_info {
-       const struct resource           *target_io_res;
-       const struct resource           *port_io_res;
+       /* Hardcoded resources provided by the hardware instantiation. */
+       const struct resource           *resources;
+       size_t                          num_resources;
+       /* Names of the mandatory resources that will be requested during
+        * probe. Must have TARGET_MAX elements, since it is indexed by target.
+        */
+       const char *const               *resource_names;
        const struct reg_field          *regfields;
        const u32 *const                *map;
        const struct ocelot_ops         *ops;
 
 };
 
 /* Addresses are relative to the PCI device's base address */
-static const struct resource vsc9959_target_io_res[TARGET_MAX] = {
-       [SYS]  = DEFINE_RES_MEM_NAMED(0x0010000, 0x0010000, "sys"),
-       [REW]  = DEFINE_RES_MEM_NAMED(0x0030000, 0x0010000, "rew"),
-       [S0]   = DEFINE_RES_MEM_NAMED(0x0040000, 0x0000400, "s0"),
-       [S1]   = DEFINE_RES_MEM_NAMED(0x0050000, 0x0000400, "s1"),
-       [S2]   = DEFINE_RES_MEM_NAMED(0x0060000, 0x0000400, "s2"),
-       [GCB]  = DEFINE_RES_MEM_NAMED(0x0070000, 0x0000200, "devcpu_gcb"),
-       [QS]   = DEFINE_RES_MEM_NAMED(0x0080000, 0x0000100, "qs"),
-       [PTP]  = DEFINE_RES_MEM_NAMED(0x0090000, 0x00000cc, "ptp"),
-       [QSYS] = DEFINE_RES_MEM_NAMED(0x0200000, 0x0020000, "qsys"),
-       [ANA]  = DEFINE_RES_MEM_NAMED(0x0280000, 0x0010000, "ana"),
-};
-
-static const struct resource vsc9959_port_io_res[] = {
+static const struct resource vsc9959_resources[] = {
+       DEFINE_RES_MEM_NAMED(0x0010000, 0x0010000, "sys"),
+       DEFINE_RES_MEM_NAMED(0x0030000, 0x0010000, "rew"),
+       DEFINE_RES_MEM_NAMED(0x0040000, 0x0000400, "s0"),
+       DEFINE_RES_MEM_NAMED(0x0050000, 0x0000400, "s1"),
+       DEFINE_RES_MEM_NAMED(0x0060000, 0x0000400, "s2"),
+       DEFINE_RES_MEM_NAMED(0x0070000, 0x0000200, "devcpu_gcb"),
+       DEFINE_RES_MEM_NAMED(0x0080000, 0x0000100, "qs"),
+       DEFINE_RES_MEM_NAMED(0x0090000, 0x00000cc, "ptp"),
        DEFINE_RES_MEM_NAMED(0x0100000, 0x0010000, "port0"),
        DEFINE_RES_MEM_NAMED(0x0110000, 0x0010000, "port1"),
        DEFINE_RES_MEM_NAMED(0x0120000, 0x0010000, "port2"),
        DEFINE_RES_MEM_NAMED(0x0130000, 0x0010000, "port3"),
        DEFINE_RES_MEM_NAMED(0x0140000, 0x0010000, "port4"),
        DEFINE_RES_MEM_NAMED(0x0150000, 0x0010000, "port5"),
+       DEFINE_RES_MEM_NAMED(0x0200000, 0x0020000, "qsys"),
+       DEFINE_RES_MEM_NAMED(0x0280000, 0x0010000, "ana"),
+};
+
+static const char * const vsc9959_resource_names[TARGET_MAX] = {
+       [SYS] = "sys",
+       [REW] = "rew",
+       [S0] = "s0",
+       [S1] = "s1",
+       [S2] = "s2",
+       [GCB] = "devcpu_gcb",
+       [QS] = "qs",
+       [PTP] = "ptp",
+       [QSYS] = "qsys",
+       [ANA] = "ana",
 };
 
 /* Port MAC 0 Internal MDIO bus through which the SerDes acting as an
 };
 
 static const struct felix_info felix_info_vsc9959 = {
-       .target_io_res          = vsc9959_target_io_res,
-       .port_io_res            = vsc9959_port_io_res,
+       .resources              = vsc9959_resources,
+       .num_resources          = ARRAY_SIZE(vsc9959_resources),
+       .resource_names         = vsc9959_resource_names,
        .regfields              = vsc9959_regfields,
        .map                    = vsc9959_regmap,
        .ops                    = &vsc9959_ops,
 
 };
 
 /* Addresses are relative to the device's base address */
-static const struct resource vsc9953_target_io_res[TARGET_MAX] = {
-       [SYS]  = DEFINE_RES_MEM_NAMED(0x0010000, 0x0010000, "sys"),
-       [REW]  = DEFINE_RES_MEM_NAMED(0x0030000, 0x0010000, "rew"),
-       [S0]   = DEFINE_RES_MEM_NAMED(0x0040000, 0x0000400, "s0"),
-       [S1]   = DEFINE_RES_MEM_NAMED(0x0050000, 0x0000400, "s1"),
-       [S2]   = DEFINE_RES_MEM_NAMED(0x0060000, 0x0000400, "s2"),
-       [GCB]  = DEFINE_RES_MEM_NAMED(0x0070000, 0x0000200, "devcpu_gcb"),
-       [QS]   = DEFINE_RES_MEM_NAMED(0x0080000, 0x0000100, "qs"),
-       [PTP]  = DEFINE_RES_MEM_NAMED(0x0090000, 0x00000cc, "ptp"),
-       [QSYS] = DEFINE_RES_MEM_NAMED(0x0200000, 0x0020000, "qsys"),
-       [ANA]  = DEFINE_RES_MEM_NAMED(0x0280000, 0x0010000, "ana"),
-};
-
-static const struct resource vsc9953_port_io_res[] = {
+static const struct resource vsc9953_resources[] = {
+       DEFINE_RES_MEM_NAMED(0x0010000, 0x0010000, "sys"),
+       DEFINE_RES_MEM_NAMED(0x0030000, 0x0010000, "rew"),
+       DEFINE_RES_MEM_NAMED(0x0040000, 0x0000400, "s0"),
+       DEFINE_RES_MEM_NAMED(0x0050000, 0x0000400, "s1"),
+       DEFINE_RES_MEM_NAMED(0x0060000, 0x0000400, "s2"),
+       DEFINE_RES_MEM_NAMED(0x0070000, 0x0000200, "devcpu_gcb"),
+       DEFINE_RES_MEM_NAMED(0x0080000, 0x0000100, "qs"),
+       DEFINE_RES_MEM_NAMED(0x0090000, 0x00000cc, "ptp"),
        DEFINE_RES_MEM_NAMED(0x0100000, 0x0010000, "port0"),
        DEFINE_RES_MEM_NAMED(0x0110000, 0x0010000, "port1"),
        DEFINE_RES_MEM_NAMED(0x0120000, 0x0010000, "port2"),
        DEFINE_RES_MEM_NAMED(0x0170000, 0x0010000, "port7"),
        DEFINE_RES_MEM_NAMED(0x0180000, 0x0010000, "port8"),
        DEFINE_RES_MEM_NAMED(0x0190000, 0x0010000, "port9"),
+       DEFINE_RES_MEM_NAMED(0x0200000, 0x0020000, "qsys"),
+       DEFINE_RES_MEM_NAMED(0x0280000, 0x0010000, "ana"),
+};
+
+static const char * const vsc9953_resource_names[TARGET_MAX] = {
+       [SYS] = "sys",
+       [REW] = "rew",
+       [S0] = "s0",
+       [S1] = "s1",
+       [S2] = "s2",
+       [GCB] = "devcpu_gcb",
+       [QS] = "qs",
+       [PTP] = "ptp",
+       [QSYS] = "qsys",
+       [ANA] = "ana",
 };
 
 static const struct reg_field vsc9953_regfields[REGFIELD_MAX] = {
 }
 
 static const struct felix_info seville_info_vsc9953 = {
-       .target_io_res          = vsc9953_target_io_res,
-       .port_io_res            = vsc9953_port_io_res,
+       .resources              = vsc9953_resources,
+       .num_resources          = ARRAY_SIZE(vsc9953_resources),
+       .resource_names         = vsc9953_resource_names,
        .regfields              = vsc9953_regfields,
        .map                    = vsc9953_regmap,
        .ops                    = &vsc9953_ops,