diff mbox series

[v3,net-next,11/14] mfd: ocelot: add regmaps for ocelot_ext

Message ID 20220926002928.2744638-12-colin.foster@in-advantage.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series add support for the the vsc7512 internal copper phys | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers success CCed 2 of 2 maintainers
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch warning WARNING: line length of 83 exceeds 80 columns WARNING: line length of 84 exceeds 80 columns WARNING: line length of 85 exceeds 80 columns WARNING: line length of 87 exceeds 80 columns WARNING: line length of 89 exceeds 80 columns WARNING: line length of 93 exceeds 80 columns WARNING: line length of 95 exceeds 80 columns WARNING: line length of 96 exceeds 80 columns WARNING: line length of 97 exceeds 80 columns WARNING: line length of 98 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Colin Foster Sept. 26, 2022, 12:29 a.m. UTC
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@in-advantage.com>
---

v3
    * No change

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(+)

Comments

Vladimir Oltean Sept. 27, 2022, 9:04 p.m. UTC | #1
On Sun, Sep 25, 2022 at 05:29:25PM -0700, Colin Foster wrote:
> 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@in-advantage.com>
> ---
> 
> v3
>     * No change
> 
> 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

I don't think you should give the HSIO resource to the switching driver.
In drivers/net/ethernet/mscc/ocelot_vsc7514.c, there is this comment:

static void ocelot_pll5_init(struct ocelot *ocelot)
{
	/* Configure PLL5. This will need a proper CCF driver
	 * The values are coming from the VTSS API for Ocelot
	 */

I believe CCF stands for Common Clock Framework.

> +
> +#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

VCAP_RES_SIZE?

> +
> +#define VSC7512_GCB_RES_START		0x71070000
> +#define VSC7512_GCB_RES_SIZE		0x0000022c

Again, I don't think devcpu_gcb should be given to a switching-only
driver. There's nothing switching-related about it.

> +#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[] = {

I hope you will merge these 2 arrays now.

> +	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);
> +

Will need to be updated.

>  	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>
> +

Is this the problematic include that makes it necessary to have the
pinctrl hack? Can we drop the #undef REG now?

>  struct resource;
>  
> +extern const struct resource vsc7512_target_io_res[TARGET_MAX];
> +extern const struct resource vsc7512_port_io_res[];
> +

Will need to be removed.

>  static inline struct regmap *
>  ocelot_regmap_from_resource_optional(struct platform_device *pdev,
>  				     unsigned int index,
> -- 
> 2.25.1
>
Colin Foster Sept. 27, 2022, 11:01 p.m. UTC | #2
On Wed, Sep 28, 2022 at 12:04:11AM +0300, Vladimir Oltean wrote:
> On Sun, Sep 25, 2022 at 05:29:25PM -0700, Colin Foster wrote:
> > 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@in-advantage.com>
> > ---
> > 
> > v3
> >     * No change
> > 
> > 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
> 
> I don't think you should give the HSIO resource to the switching driver.
> In drivers/net/ethernet/mscc/ocelot_vsc7514.c, there is this comment:
> 
> static void ocelot_pll5_init(struct ocelot *ocelot)
> {
> 	/* Configure PLL5. This will need a proper CCF driver
> 	 * The values are coming from the VTSS API for Ocelot
> 	 */
> 
> I believe CCF stands for Common Clock Framework.

It does stand for common clock framework. And this function / comment
keeps me up at night.

Agreed that the HSIO resource isn't currently used, and should be
dropped from this set. The resource will be brought back in as soon as I
add in phy-ocelot-serdes support during the third and final (?) patch
set of adding 7512 copper ethernet support.

My fear is that the lines:

if (ocelot->targets[HSIO])
    ocelot_pll5_init(ocelot);

won't fly inside felix_setup(), and I'm not sure how far that scope will
creep. Maybe it is easier than I suspect.


But I'm getting ahead of myself. I'll remove this for now.

> 
> > +
> > +#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
> 
> VCAP_RES_SIZE?

I'll change this name to VCAP_RES_SIZE.

> 
> > +
> > +#define VSC7512_GCB_RES_START		0x71070000
> > +#define VSC7512_GCB_RES_SIZE		0x0000022c
> 
> Again, I don't think devcpu_gcb should be given to a switching-only
> driver. There's nothing switching-related about it.

Yes, this is no longer necessary and I missed this. I think you caught
them all, but I'll do another sweep just in case.

> > +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[] = {
> 
> I hope you will merge these 2 arrays now.

Yep. And with that I should be able to add them via the standard
.num_resources, .resources method all the other drivers use. As
mentioned, without the GCB and HSIO entries.

> >  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);
> > +
> 
> Will need to be updated.

Yep. I think it can all go away for the above
ocelot_core_try_add_regmaps() call now.

> 
> >  	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>
> > +
> 
> Is this the problematic include that makes it necessary to have the
> pinctrl hack? Can we drop the #undef REG now?

Yes, this include was specifically for TARGET_MAX below. That undef REG
should not be necessary anymore. I'll drop it.

> 
> >  struct resource;
> >  
> > +extern const struct resource vsc7512_target_io_res[TARGET_MAX];
> > +extern const struct resource vsc7512_port_io_res[];
> > +
> 
> Will need to be removed.

Gladly :-)

> 
> >  static inline struct regmap *
> >  ocelot_regmap_from_resource_optional(struct platform_device *pdev,
> >  				     unsigned int index,
> > -- 
> > 2.25.1
> >
diff mbox series

Patch

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,