The Ocelot switch core driver relies heavily on a fixed array of resources for both ports and peripherals. This is in contrast to existing peripherals - pinctrl for example - which have a one-to-one mapping of driver <> resource. As such, these regmaps must be created differently so that enumeration-based offsets are preserved. Register the regmaps to the core MFD device unconditionally so they can be referenced by the Ocelot switch / Felix DSA systems. Signed-off-by: Colin Foster <colin.foster@xxxxxxxxxxxxxxxx> --- v2 * Alignment of variables broken out to a separate patch * Structs now correctly use EXPORT_SYMBOL* * Logic moved and comments added to clear up conditionals around vsc7512_target_io_res[i].start v1 from previous RFC: * New patch --- drivers/mfd/ocelot-core.c | 87 ++++++++++++++++++++++++++++++++++++++ include/linux/mfd/ocelot.h | 5 +++ 2 files changed, 92 insertions(+) diff --git a/drivers/mfd/ocelot-core.c b/drivers/mfd/ocelot-core.c index 013e83173062..702555fbdcc5 100644 --- a/drivers/mfd/ocelot-core.c +++ b/drivers/mfd/ocelot-core.c @@ -45,6 +45,45 @@ #define VSC7512_SIO_CTRL_RES_START 0x710700f8 #define VSC7512_SIO_CTRL_RES_SIZE 0x00000100 +#define VSC7512_HSIO_RES_START 0x710d0000 +#define VSC7512_HSIO_RES_SIZE 0x00000128 + +#define VSC7512_ANA_RES_START 0x71880000 +#define VSC7512_ANA_RES_SIZE 0x00010000 + +#define VSC7512_QS_RES_START 0x71080000 +#define VSC7512_QS_RES_SIZE 0x00000100 + +#define VSC7512_QSYS_RES_START 0x71800000 +#define VSC7512_QSYS_RES_SIZE 0x00200000 + +#define VSC7512_REW_RES_START 0x71030000 +#define VSC7512_REW_RES_SIZE 0x00010000 + +#define VSC7512_SYS_RES_START 0x71010000 +#define VSC7512_SYS_RES_SIZE 0x00010000 + +#define VSC7512_S0_RES_START 0x71040000 +#define VSC7512_S1_RES_START 0x71050000 +#define VSC7512_S2_RES_START 0x71060000 +#define VSC7512_S_RES_SIZE 0x00000400 + +#define VSC7512_GCB_RES_START 0x71070000 +#define VSC7512_GCB_RES_SIZE 0x0000022c + +#define VSC7512_PORT_0_RES_START 0x711e0000 +#define VSC7512_PORT_1_RES_START 0x711f0000 +#define VSC7512_PORT_2_RES_START 0x71200000 +#define VSC7512_PORT_3_RES_START 0x71210000 +#define VSC7512_PORT_4_RES_START 0x71220000 +#define VSC7512_PORT_5_RES_START 0x71230000 +#define VSC7512_PORT_6_RES_START 0x71240000 +#define VSC7512_PORT_7_RES_START 0x71250000 +#define VSC7512_PORT_8_RES_START 0x71260000 +#define VSC7512_PORT_9_RES_START 0x71270000 +#define VSC7512_PORT_10_RES_START 0x71280000 +#define VSC7512_PORT_RES_SIZE 0x00010000 + #define VSC7512_GCB_RST_SLEEP_US 100 #define VSC7512_GCB_RST_TIMEOUT_US 100000 @@ -96,6 +135,36 @@ static const struct resource vsc7512_sgpio_resources[] = { DEFINE_RES_REG_NAMED(VSC7512_SIO_CTRL_RES_START, VSC7512_SIO_CTRL_RES_SIZE, "gcb_sio"), }; +const struct resource vsc7512_target_io_res[TARGET_MAX] = { + [ANA] = DEFINE_RES_REG_NAMED(VSC7512_ANA_RES_START, VSC7512_ANA_RES_SIZE, "ana"), + [QS] = DEFINE_RES_REG_NAMED(VSC7512_QS_RES_START, VSC7512_QS_RES_SIZE, "qs"), + [QSYS] = DEFINE_RES_REG_NAMED(VSC7512_QSYS_RES_START, VSC7512_QSYS_RES_SIZE, "qsys"), + [REW] = DEFINE_RES_REG_NAMED(VSC7512_REW_RES_START, VSC7512_REW_RES_SIZE, "rew"), + [SYS] = DEFINE_RES_REG_NAMED(VSC7512_SYS_RES_START, VSC7512_SYS_RES_SIZE, "sys"), + [S0] = DEFINE_RES_REG_NAMED(VSC7512_S0_RES_START, VSC7512_S_RES_SIZE, "s0"), + [S1] = DEFINE_RES_REG_NAMED(VSC7512_S1_RES_START, VSC7512_S_RES_SIZE, "s1"), + [S2] = DEFINE_RES_REG_NAMED(VSC7512_S2_RES_START, VSC7512_S_RES_SIZE, "s2"), + [GCB] = DEFINE_RES_REG_NAMED(VSC7512_GCB_RES_START, VSC7512_GCB_RES_SIZE, "devcpu_gcb"), + [HSIO] = DEFINE_RES_REG_NAMED(VSC7512_HSIO_RES_START, VSC7512_HSIO_RES_SIZE, "hsio"), +}; +EXPORT_SYMBOL_NS(vsc7512_target_io_res, MFD_OCELOT); + +const struct resource vsc7512_port_io_res[] = { + DEFINE_RES_REG_NAMED(VSC7512_PORT_0_RES_START, VSC7512_PORT_RES_SIZE, "port0"), + DEFINE_RES_REG_NAMED(VSC7512_PORT_1_RES_START, VSC7512_PORT_RES_SIZE, "port1"), + DEFINE_RES_REG_NAMED(VSC7512_PORT_2_RES_START, VSC7512_PORT_RES_SIZE, "port2"), + DEFINE_RES_REG_NAMED(VSC7512_PORT_3_RES_START, VSC7512_PORT_RES_SIZE, "port3"), + DEFINE_RES_REG_NAMED(VSC7512_PORT_4_RES_START, VSC7512_PORT_RES_SIZE, "port4"), + DEFINE_RES_REG_NAMED(VSC7512_PORT_5_RES_START, VSC7512_PORT_RES_SIZE, "port5"), + DEFINE_RES_REG_NAMED(VSC7512_PORT_6_RES_START, VSC7512_PORT_RES_SIZE, "port6"), + DEFINE_RES_REG_NAMED(VSC7512_PORT_7_RES_START, VSC7512_PORT_RES_SIZE, "port7"), + DEFINE_RES_REG_NAMED(VSC7512_PORT_8_RES_START, VSC7512_PORT_RES_SIZE, "port8"), + DEFINE_RES_REG_NAMED(VSC7512_PORT_9_RES_START, VSC7512_PORT_RES_SIZE, "port9"), + DEFINE_RES_REG_NAMED(VSC7512_PORT_10_RES_START, VSC7512_PORT_RES_SIZE, "port10"), + {} +}; +EXPORT_SYMBOL_NS(vsc7512_port_io_res, MFD_OCELOT); + static const struct mfd_cell vsc7512_devs[] = { { .name = "ocelot-pinctrl", @@ -144,6 +213,7 @@ static void ocelot_core_try_add_regmaps(struct device *dev, int ocelot_core_init(struct device *dev) { + const struct resource *port_res; int i, ndevs; ndevs = ARRAY_SIZE(vsc7512_devs); @@ -151,6 +221,23 @@ int ocelot_core_init(struct device *dev) for (i = 0; i < ndevs; i++) ocelot_core_try_add_regmaps(dev, &vsc7512_devs[i]); + /* + * Both the target_io_res and the port_io_res structs need to be referenced directly by + * the ocelot_ext driver, so they can't be attached to the dev directly and referenced by + * offset like the rest of the drivers. Instead, create these regmaps always and allow any + * children look these up by name. + */ + for (i = 0; i < TARGET_MAX; i++) + /* + * The target_io_res array is sparsely populated. Use .start as an indication that + * the entry isn't defined + */ + if (vsc7512_target_io_res[i].start) + ocelot_core_try_add_regmap(dev, &vsc7512_target_io_res[i]); + + for (port_res = vsc7512_port_io_res; port_res->start; port_res++) + ocelot_core_try_add_regmap(dev, port_res); + return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, vsc7512_devs, ndevs, NULL, 0, NULL); } EXPORT_SYMBOL_NS(ocelot_core_init, MFD_OCELOT); diff --git a/include/linux/mfd/ocelot.h b/include/linux/mfd/ocelot.h index dd72073d2d4f..439ff5256cf0 100644 --- a/include/linux/mfd/ocelot.h +++ b/include/linux/mfd/ocelot.h @@ -11,8 +11,13 @@ #include <linux/regmap.h> #include <linux/types.h> +#include <soc/mscc/ocelot.h> + struct resource; +extern const struct resource vsc7512_target_io_res[TARGET_MAX]; +extern const struct resource vsc7512_port_io_res[]; + static inline struct regmap * ocelot_regmap_from_resource_optional(struct platform_device *pdev, unsigned int index, -- 2.25.1