diff options
-rw-r--r-- | drivers/net/dsa/ocelot/felix.c | 71 | ||||
-rw-r--r-- | drivers/net/dsa/ocelot/felix.h | 9 | ||||
-rw-r--r-- | drivers/net/dsa/ocelot/felix_vsc9959.c | 43 | ||||
-rw-r--r-- | drivers/net/dsa/ocelot/seville_vsc9953.c | 43 |
4 files changed, 112 insertions, 54 deletions
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 6a7643c31c46..dd3a18cc89dd 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1312,11 +1312,55 @@ static int felix_parse_dt(struct felix *felix, phy_interface_t *port_phy_modes) 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; @@ -1350,19 +1394,11 @@ static int felix_init_structs(struct felix *felix, int 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); } @@ -1379,7 +1415,6 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) 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), @@ -1391,15 +1426,11 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) 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); } diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 54322d0398fd..c9c29999c336 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -16,8 +16,13 @@ /* 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; diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 1872727e80df..12810fea2075 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -477,26 +477,36 @@ static const u32 *vsc9959_regmap[TARGET_MAX] = { }; /* 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 @@ -2526,8 +2536,9 @@ static const struct ocelot_ops vsc9959_ops = { }; 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, diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index 66237c4385ac..7af33b2c685d 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -458,20 +458,15 @@ static const u32 *vsc9953_regmap[TARGET_MAX] = { }; /* 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"), @@ -482,6 +477,21 @@ static const struct resource vsc9953_port_io_res[] = { 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] = { @@ -980,8 +990,9 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot) } 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, |