diff mbox series

[05/10] spi: spi-dw-mmio: Spin off MSCC platforms into spi-dw-mchp

Message ID 20200513140031.25633-6-lars.povlsen@microchip.com (mailing list archive)
State Superseded
Headers show
Series spi: Adding support for Microchip Sparx5 SoC | expand

Commit Message

Lars Povlsen May 13, 2020, 2 p.m. UTC
This patch spins off the MSCC platforms into a separate driver, as
adding new platforms from the MSCC/Microchip product lines will
further complicate (clutter) the original driver.

The new 'spi-dw-mchp' driver still builds on the dw-spi foundation.

Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
---
 MAINTAINERS                                   |   1 +
 arch/mips/configs/generic/board-ocelot.config |   2 +-
 drivers/spi/Kconfig                           |   7 +
 drivers/spi/Makefile                          |   1 +
 drivers/spi/spi-dw-mchp.c                     | 232 ++++++++++++++++++
 drivers/spi/spi-dw-mmio.c                     |  93 -------
 6 files changed, 242 insertions(+), 94 deletions(-)
 create mode 100644 drivers/spi/spi-dw-mchp.c

--
2.26.2

Comments

Mark Brown May 13, 2020, 3:18 p.m. UTC | #1
On Wed, May 13, 2020 at 04:00:26PM +0200, Lars Povlsen wrote:

> +config SPI_DW_MCHP
> +	tristate "Memory-mapped io interface driver using DW SPI core of MSCC SoCs"
> +	default y if ARCH_SPARX5
> +	default y if SOC_VCOREIII

Why the default ys?

> +++ b/drivers/spi/Makefile
> @@ -37,6 +37,7 @@ obj-$(CONFIG_SPI_DAVINCI)		+= spi-davinci.o
>  obj-$(CONFIG_SPI_DLN2)			+= spi-dln2.o
>  obj-$(CONFIG_SPI_DESIGNWARE)		+= spi-dw.o
>  obj-$(CONFIG_SPI_DW_MMIO)		+= spi-dw-mmio.o
> +obj-$(CONFIG_SPI_DW_MCHP)		+= spi-dw-mchp.o
>  obj-$(CONFIG_SPI_DW_PCI)		+= spi-dw-midpci.o
>  spi-dw-midpci-objs			:= spi-dw-pci.o spi-dw-mid.o
>  obj-$(CONFIG_SPI_EFM32)			+= spi-efm32.o

Please keep the file alphabetically sorted.

> +++ b/drivers/spi/spi-dw-mchp.c
> @@ -0,0 +1,232 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Memory-mapped interface driver for MSCC SoCs
> + *

Please make the entire comment a C++ one so things look more
intentional.

> +#define MAX_CS		4

This should be namespaced.

> +	rx_sample_dly = 0;
> +	device_property_read_u32(&pdev->dev, "spi-rx-delay-us", &rx_sample_dly);
> +	dws->rx_sample_dly = DIV_ROUND_UP(rx_sample_dly,
> +					  (dws->max_freq / 1000000));

If this is a standard feature of the DesignWare IP why parse it here and
not in the generic code?
Lars Povlsen May 19, 2020, 12:05 p.m. UTC | #2
On 13/05/20 16:18, Mark Brown wrote:
> Date: Wed, 13 May 2020 16:18:11 +0100
> From: Mark Brown <broonie@kernel.org>
> To: Lars Povlsen <lars.povlsen@microchip.com>
> Cc: SoC Team <soc@kernel.org>, Microchip Linux Driver Support
>  <UNGLinuxDriver@microchip.com>, linux-spi@vger.kernel.org,
>  devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
>  linux-arm-kernel@lists.infradead.org, Alexandre Belloni
>  <alexandre.belloni@bootlin.com>
> Subject: Re: [PATCH 05/10] spi: spi-dw-mmio: Spin off MSCC platforms into
>  spi-dw-mchp
> User-Agent: Mutt/1.10.1 (2018-07-13)
> 
> On Wed, May 13, 2020 at 04:00:26PM +0200, Lars Povlsen wrote:
> 
> > +config SPI_DW_MCHP
> > +	tristate "Memory-mapped io interface driver using DW SPI core of MSCC SoCs"
> > +	default y if ARCH_SPARX5
> > +	default y if SOC_VCOREIII
> 
> Why the default ys?

The SoC will typically boot from SPI... But its not a requirement per
se. I will remove it.

> 
> > +++ b/drivers/spi/Makefile
> > @@ -37,6 +37,7 @@ obj-$(CONFIG_SPI_DAVINCI)		+= spi-davinci.o
> >  obj-$(CONFIG_SPI_DLN2)			+= spi-dln2.o
> >  obj-$(CONFIG_SPI_DESIGNWARE)		+= spi-dw.o
> >  obj-$(CONFIG_SPI_DW_MMIO)		+= spi-dw-mmio.o
> > +obj-$(CONFIG_SPI_DW_MCHP)		+= spi-dw-mchp.o
> >  obj-$(CONFIG_SPI_DW_PCI)		+= spi-dw-midpci.o
> >  spi-dw-midpci-objs			:= spi-dw-pci.o spi-dw-mid.o
> >  obj-$(CONFIG_SPI_EFM32)			+= spi-efm32.o
> 
> Please keep the file alphabetically sorted.
> 

Noted.

> > +++ b/drivers/spi/spi-dw-mchp.c
> > @@ -0,0 +1,232 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Memory-mapped interface driver for MSCC SoCs
> > + *
> 
> Please make the entire comment a C++ one so things look more
> intentional.

Sure, I can do that. The presented form matches that of the other
spi-dw-* drivers, but I can see other using // blocks. Ack.

> 
> > +#define MAX_CS		4
> 
> This should be namespaced.

Ack.

> 
> > +	rx_sample_dly = 0;
> > +	device_property_read_u32(&pdev->dev, "spi-rx-delay-us", &rx_sample_dly);
> > +	dws->rx_sample_dly = DIV_ROUND_UP(rx_sample_dly,
> > +					  (dws->max_freq / 1000000));
> 
> If this is a standard feature of the DesignWare IP why parse it here and
> not in the generic code?

This is a standard feature of the DesignWare IP, so good suggestion. I
will arrange with Serge.

Thank you for your comments!

---Lars
Serge Semin June 2, 2020, 9:12 p.m. UTC | #3
On Tue, May 19, 2020 at 02:05:19PM +0200, Lars Povlsen wrote:
> On 13/05/20 16:18, Mark Brown wrote:
> > Date: Wed, 13 May 2020 16:18:11 +0100
> > From: Mark Brown <broonie@kernel.org>
> > To: Lars Povlsen <lars.povlsen@microchip.com>
> > Cc: SoC Team <soc@kernel.org>, Microchip Linux Driver Support
> >  <UNGLinuxDriver@microchip.com>, linux-spi@vger.kernel.org,
> >  devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
> >  linux-arm-kernel@lists.infradead.org, Alexandre Belloni
> >  <alexandre.belloni@bootlin.com>
> > Subject: Re: [PATCH 05/10] spi: spi-dw-mmio: Spin off MSCC platforms into
> >  spi-dw-mchp
> > User-Agent: Mutt/1.10.1 (2018-07-13)
> > 
> > On Wed, May 13, 2020 at 04:00:26PM +0200, Lars Povlsen wrote:
> > 
> > > +config SPI_DW_MCHP
> > > +	tristate "Memory-mapped io interface driver using DW SPI core of MSCC SoCs"
> > > +	default y if ARCH_SPARX5
> > > +	default y if SOC_VCOREIII
> > 
> > Why the default ys?
> 
> The SoC will typically boot from SPI... But its not a requirement per
> se. I will remove it.
> 
> > 
> > > +++ b/drivers/spi/Makefile
> > > @@ -37,6 +37,7 @@ obj-$(CONFIG_SPI_DAVINCI)		+= spi-davinci.o
> > >  obj-$(CONFIG_SPI_DLN2)			+= spi-dln2.o
> > >  obj-$(CONFIG_SPI_DESIGNWARE)		+= spi-dw.o
> > >  obj-$(CONFIG_SPI_DW_MMIO)		+= spi-dw-mmio.o
> > > +obj-$(CONFIG_SPI_DW_MCHP)		+= spi-dw-mchp.o
> > >  obj-$(CONFIG_SPI_DW_PCI)		+= spi-dw-midpci.o
> > >  spi-dw-midpci-objs			:= spi-dw-pci.o spi-dw-mid.o
> > >  obj-$(CONFIG_SPI_EFM32)			+= spi-efm32.o
> > 
> > Please keep the file alphabetically sorted.
> > 
> 
> Noted.
> 
> > > +++ b/drivers/spi/spi-dw-mchp.c
> > > @@ -0,0 +1,232 @@
> > > +// SPDX-License-Identifier: GPL-2.0-only
> > > +/*
> > > + * Memory-mapped interface driver for MSCC SoCs
> > > + *
> > 
> > Please make the entire comment a C++ one so things look more
> > intentional.
> 
> Sure, I can do that. The presented form matches that of the other
> spi-dw-* drivers, but I can see other using // blocks. Ack.
> 
> > 
> > > +#define MAX_CS		4
> > 
> > This should be namespaced.
> 
> Ack.
> 

> > 
> > > +	rx_sample_dly = 0;
> > > +	device_property_read_u32(&pdev->dev, "spi-rx-delay-us", &rx_sample_dly);
> > > +	dws->rx_sample_dly = DIV_ROUND_UP(rx_sample_dly,
> > > +					  (dws->max_freq / 1000000));

Perhaps 100000 is better to be replace with macro USEC_PER_SEC...

Moreover are you sure the formulae is correct?
dws->rx_sample_dly - a number of ssi_clk periods/cycles to delay the Rx-data sample,
dws->max_freq - ssi_clk frequency (not period).

In real math the formulae would look like:
S = d * P [s], where d - number of delay cycles, P - ssi_clk period in seconds,
S - requested delay in seconds.
In the driver notation: d = dws->rx_sample_dly, P = 1 / dws->max_freq,
S = rx_sample_dly ("spi-rx-delay-us" property value).

dws->rx_sample_dly * (1 / dws->max_freq) = rx_sample_dly <=>
dws->rx_sample_dly = rx_sample_dly * dws->max_freq.

Though that's represented in seconds, so if rx_sample_dly is specified in usec,
then you'd need to scale it down dividing by USEC_PER_SEC.

For example, imagine we need a delay of 1 usec with ssi_clk of 50MHz.
By your formulae we'd have: 1 / (50000000 / 1000000) = 0 cycles (actually 1 due
to DIV_ROUND_UP, but incorrect anyway),
By mine: 1 * (500000000 / 1000000) = 50 cycles. Seems closer to reality.

Am I missing something?

> > 
> > If this is a standard feature of the DesignWare IP why parse it here and
> > not in the generic code?
> 
> This is a standard feature of the DesignWare IP, so good suggestion. I
> will arrange with Serge.

Regarding "spi-rx-delay-us" and the sampling delay the IP supports. Here is what
documentation says regarding the register, which is then initialized with this
parameter "This register controls the number of ssi_clk cycles that are
delayed from the default sample time before the actual sample of the rxd input
signal occurs." While the "spi-rx-delay-us" property is described as: "Delay, in
microseconds, after a read transfer." I may misunderstand something, but IMO
these descriptions don't refer to the same values. The only real use of the
"spi-rx-delay-us" property I've found in "./drivers/input/rmi4/rmi_spi.c".
That driver gets the value of the property and just sets the delay_usecs
of some transfers, which isn't even close to the functionality the RX_SAMPLE_DLY
register provides. 

To be clear the RX_SAMPLE_DLY register can be used to delay the RX-bits sample
with respect to the normal Rx sampling timing. The delay is measured in the 
numbers of the ssi_clk periods. (Note also that the maximum delay is limited
with a constant parameter pre-initialized at the IP-core synthesis stage. It can
be defined within a range [4, 255]. In our IP it's limited with just 4 periods.)

As I see it, a better way would be to either define a new vendor-specific
property like "snps,rx-sample-delay-ns" (note NS here, since normally the
ssi_clk is much higher than 1MHz), or define a new generic SPI property.
Mark, Andy?

-Sergey

> 
> Thank you for your comments!
> 
> ---Lars
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Lars Povlsen June 10, 2020, 2:28 p.m. UTC | #4
Serge Semin writes:

> On Tue, May 19, 2020 at 02:05:19PM +0200, Lars Povlsen wrote:
>> On 13/05/20 16:18, Mark Brown wrote:
>> > Date: Wed, 13 May 2020 16:18:11 +0100
>> > From: Mark Brown <broonie@kernel.org>
>> > To: Lars Povlsen <lars.povlsen@microchip.com>
>> > Cc: SoC Team <soc@kernel.org>, Microchip Linux Driver Support
>> >  <UNGLinuxDriver@microchip.com>, linux-spi@vger.kernel.org,
>> >  devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
>> >  linux-arm-kernel@lists.infradead.org, Alexandre Belloni
>> >  <alexandre.belloni@bootlin.com>
>> > Subject: Re: [PATCH 05/10] spi: spi-dw-mmio: Spin off MSCC platforms into
>> >  spi-dw-mchp
>> > User-Agent: Mutt/1.10.1 (2018-07-13)
>> >
>> > On Wed, May 13, 2020 at 04:00:26PM +0200, Lars Povlsen wrote:
>> >
>> > > +config SPI_DW_MCHP
>> > > + tristate "Memory-mapped io interface driver using DW SPI core of MSCC SoCs"
>> > > + default y if ARCH_SPARX5
>> > > + default y if SOC_VCOREIII
>> >
>> > Why the default ys?
>>
>> The SoC will typically boot from SPI... But its not a requirement per
>> se. I will remove it.
>>
>> >
>> > > +++ b/drivers/spi/Makefile
>> > > @@ -37,6 +37,7 @@ obj-$(CONFIG_SPI_DAVINCI)               += spi-davinci.o
>> > >  obj-$(CONFIG_SPI_DLN2)                   += spi-dln2.o
>> > >  obj-$(CONFIG_SPI_DESIGNWARE)             += spi-dw.o
>> > >  obj-$(CONFIG_SPI_DW_MMIO)                += spi-dw-mmio.o
>> > > +obj-$(CONFIG_SPI_DW_MCHP)                += spi-dw-mchp.o
>> > >  obj-$(CONFIG_SPI_DW_PCI)         += spi-dw-midpci.o
>> > >  spi-dw-midpci-objs                       := spi-dw-pci.o spi-dw-mid.o
>> > >  obj-$(CONFIG_SPI_EFM32)                  += spi-efm32.o
>> >
>> > Please keep the file alphabetically sorted.
>> >
>>
>> Noted.
>>
>> > > +++ b/drivers/spi/spi-dw-mchp.c
>> > > @@ -0,0 +1,232 @@
>> > > +// SPDX-License-Identifier: GPL-2.0-only
>> > > +/*
>> > > + * Memory-mapped interface driver for MSCC SoCs
>> > > + *
>> >
>> > Please make the entire comment a C++ one so things look more
>> > intentional.
>>
>> Sure, I can do that. The presented form matches that of the other
>> spi-dw-* drivers, but I can see other using // blocks. Ack.
>>
>> >
>> > > +#define MAX_CS           4
>> >
>> > This should be namespaced.
>>
>> Ack.
>>
>
>> >
>> > > + rx_sample_dly = 0;
>> > > + device_property_read_u32(&pdev->dev, "spi-rx-delay-us", &rx_sample_dly);
>> > > + dws->rx_sample_dly = DIV_ROUND_UP(rx_sample_dly,
>> > > +                                   (dws->max_freq / 1000000));
>
> Perhaps 100000 is better to be replace with macro USEC_PER_SEC...
>
> Moreover are you sure the formulae is correct?
> dws->rx_sample_dly - a number of ssi_clk periods/cycles to delay the Rx-data sample,
> dws->max_freq - ssi_clk frequency (not period).
>
> In real math the formulae would look like:
> S = d * P [s], where d - number of delay cycles, P - ssi_clk period in seconds,
> S - requested delay in seconds.
> In the driver notation: d = dws->rx_sample_dly, P = 1 / dws->max_freq,
> S = rx_sample_dly ("spi-rx-delay-us" property value).
>
> dws->rx_sample_dly * (1 / dws->max_freq) = rx_sample_dly <=>
> dws->rx_sample_dly = rx_sample_dly * dws->max_freq.
>
> Though that's represented in seconds, so if rx_sample_dly is specified in usec,
> then you'd need to scale it down dividing by USEC_PER_SEC.
>
> For example, imagine we need a delay of 1 usec with ssi_clk of 50MHz.
> By your formulae we'd have: 1 / (50000000 / 1000000) = 0 cycles (actually 1 due
> to DIV_ROUND_UP, but incorrect anyway),
> By mine: 1 * (500000000 / 1000000) = 50 cycles. Seems closer to reality.
>
> Am I missing something?

No, you are perfectly right, the calculation was wrong - and I concur
the unit should be NS.

(your example threw me off, you are using 500Mhz, typo I guess)

I believe the calculation should be:

  device_property_read_u32(&pdev->dev, "snps,rx-sample-delay-ns", &rx_sample_dly);
  dws->rx_sample_dly = DIV_ROUND_CLOSEST(rx_sample_dly, NSEC_PER_SEC / dws->max_freq);
        
So for your example of 1us = 1000ns, we have a cycle time of 20 ns => 50 cycles.

And I assume DIV_ROUND_CLOSEST() is the better instead of explicit
rounding up/down. And I assume its fair to assume that the cycle time is
not a fraction.

Ok?

>
>> >
>> > If this is a standard feature of the DesignWare IP why parse it here and
>> > not in the generic code?
>>
>> This is a standard feature of the DesignWare IP, so good suggestion. I
>> will arrange with Serge.
>
> Regarding "spi-rx-delay-us" and the sampling delay the IP supports. Here is what
> documentation says regarding the register, which is then initialized with this
> parameter "This register controls the number of ssi_clk cycles that are
> delayed from the default sample time before the actual sample of the rxd input
> signal occurs." While the "spi-rx-delay-us" property is described as: "Delay, in
> microseconds, after a read transfer." I may misunderstand something, but IMO
> these descriptions don't refer to the same values. The only real use of the
> "spi-rx-delay-us" property I've found in "./drivers/input/rmi4/rmi_spi.c".
> That driver gets the value of the property and just sets the delay_usecs
> of some transfers, which isn't even close to the functionality the RX_SAMPLE_DLY
> register provides.
>
> To be clear the RX_SAMPLE_DLY register can be used to delay the RX-bits sample
> with respect to the normal Rx sampling timing. The delay is measured in the
> numbers of the ssi_clk periods. (Note also that the maximum delay is limited
> with a constant parameter pre-initialized at the IP-core synthesis stage. It can
> be defined within a range [4, 255]. In our IP it's limited with just 4 periods.)
>

Yes - I was not aware of the instantiation incurred limit before. Turned
our IP has up to 100ns worth of fifo depth - 25 cycles.

> As I see it, a better way would be to either define a new vendor-specific
> property like "snps,rx-sample-delay-ns" (note NS here, since normally the
> ssi_clk is much higher than 1MHz), or define a new generic SPI property.
> Mark, Andy?

I'll assume "snps,rx-sample-delay-ns" for now, its easy to rename if you
decide so.

Thanks again!

---Lars

>
> -Sergey
>
>>
>> Thank you for your comments!
>>
>> ---Lars
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 6472240b8391b..de64fd4548697 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2085,6 +2085,7 @@  M:	Steen Hegelund <Steen.Hegelund@microchip.com>
 M:	Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 F:	arch/arm64/boot/dts/microchip/
+F:	drivers/spi/spi-dw-mchp.c
 N:	sparx5
 S:	Supported

diff --git a/arch/mips/configs/generic/board-ocelot.config b/arch/mips/configs/generic/board-ocelot.config
index 7626f2a75b03f..6dbae76268a49 100644
--- a/arch/mips/configs/generic/board-ocelot.config
+++ b/arch/mips/configs/generic/board-ocelot.config
@@ -38,7 +38,7 @@  CONFIG_I2C_DESIGNWARE_PLATFORM=y
 CONFIG_SPI=y
 CONFIG_SPI_BITBANG=y
 CONFIG_SPI_DESIGNWARE=y
-CONFIG_SPI_DW_MMIO=y
+CONFIG_SPI_DW_MCHP=y
 CONFIG_SPI_SPIDEV=y

 CONFIG_PINCTRL=y
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 741b9140992a8..77eb580b9f51f 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -238,6 +238,13 @@  config SPI_DW_MMIO
 	tristate "Memory-mapped io interface driver for DW SPI core"
 	depends on SPI_DESIGNWARE

+config SPI_DW_MCHP
+	tristate "Memory-mapped io interface driver using DW SPI core of MSCC SoCs"
+	default y if ARCH_SPARX5
+	default y if SOC_VCOREIII
+	select SPI_DESIGNWARE
+	select SPI_DW_MMIO
+
 config SPI_DLN2
        tristate "Diolan DLN-2 USB SPI adapter"
        depends on MFD_DLN2
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 28f601327f8c7..be8a52d90721b 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -37,6 +37,7 @@  obj-$(CONFIG_SPI_DAVINCI)		+= spi-davinci.o
 obj-$(CONFIG_SPI_DLN2)			+= spi-dln2.o
 obj-$(CONFIG_SPI_DESIGNWARE)		+= spi-dw.o
 obj-$(CONFIG_SPI_DW_MMIO)		+= spi-dw-mmio.o
+obj-$(CONFIG_SPI_DW_MCHP)		+= spi-dw-mchp.o
 obj-$(CONFIG_SPI_DW_PCI)		+= spi-dw-midpci.o
 spi-dw-midpci-objs			:= spi-dw-pci.o spi-dw-mid.o
 obj-$(CONFIG_SPI_EFM32)			+= spi-efm32.o
diff --git a/drivers/spi/spi-dw-mchp.c b/drivers/spi/spi-dw-mchp.c
new file mode 100644
index 0000000000000..0828a7616d9ab
--- /dev/null
+++ b/drivers/spi/spi-dw-mchp.c
@@ -0,0 +1,232 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Memory-mapped interface driver for MSCC SoCs
+ *
+ * Copyright (c) 2020 Microchip Technology Inc. and its subsidiaries.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/spi/spi-mem.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+
+#include "spi-dw.h"
+
+#define DRIVER_NAME "dw_spi_mchp"
+
+#define MAX_CS		4
+
+#define MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL	0x24
+#define OCELOT_IF_SI_OWNER_OFFSET		4
+#define JAGUAR2_IF_SI_OWNER_OFFSET		6
+#define MSCC_IF_SI_OWNER_MASK			GENMASK(1, 0)
+#define MSCC_IF_SI_OWNER_SISL			0
+#define MSCC_IF_SI_OWNER_SIBM			1
+#define MSCC_IF_SI_OWNER_SIMC			2
+
+#define MSCC_SPI_MST_SW_MODE			0x14
+#define MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE	BIT(13)
+#define MSCC_SPI_MST_SW_MODE_SW_SPI_CS(x)	(x << 5)
+
+struct dw_spi_mchp_props {
+	const char *syscon_name;
+	u32 si_owner_bit;
+};
+
+struct dw_spi_mchp {
+	struct dw_spi  dws;
+	struct clk     *clk;
+	void __iomem   *read_map;
+	struct regmap			*syscon;
+	void __iomem			*spi_mst;
+	const struct dw_spi_mchp_props	*props;
+	u32				gen_owner;
+};
+
+static const struct dw_spi_mchp_props dw_spi_mchp_props_ocelot = {
+	.syscon_name		= "mscc,ocelot-cpu-syscon",
+	.si_owner_bit		= 4,
+};
+
+static const struct dw_spi_mchp_props dw_spi_mchp_props_jaguar2 = {
+	.syscon_name		= "mscc,ocelot-cpu-syscon",
+	.si_owner_bit		= 6,
+};
+
+/*
+ * The Designware SPI controller (referred to as master in the documentation)
+ * automatically deasserts chip select when the tx fifo is empty. The chip
+ * selects then needs to be either driven as GPIOs or, for the first 4 using the
+ * the SPI boot controller registers. the final chip select is an OR gate
+ * between the Designware SPI controller and the SPI boot controller.
+ */
+static void dw_spi_mchp_set_cs(struct spi_device *spi, bool enable)
+{
+	struct dw_spi *dws = spi_master_get_devdata(spi->master);
+	struct dw_spi_mchp *dwsmchp = container_of(dws, struct dw_spi_mchp,
+						   dws);
+	u32 cs = spi->chip_select;
+
+	if (cs < 4) {
+		u32 sw_mode = MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE;
+
+		if (!enable)
+			sw_mode |= MSCC_SPI_MST_SW_MODE_SW_SPI_CS(BIT(cs));
+
+		writel(sw_mode, dwsmchp->spi_mst + MSCC_SPI_MST_SW_MODE);
+	}
+
+	dw_spi_set_cs(spi, enable);
+}
+
+static int dw_spi_mchp_init(struct platform_device *pdev,
+			    struct dw_spi *dws,
+			    struct dw_spi_mchp *dwsmchp,
+			    const struct dw_spi_mchp_props *props)
+{
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res && resource_size(res) > 0) {
+		dwsmchp->spi_mst = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(dwsmchp->spi_mst)) {
+			dev_err(&pdev->dev, "SPI_MST region map failed\n");
+			return PTR_ERR(dwsmchp->spi_mst);
+		}
+	}
+
+	dwsmchp->syscon =
+		syscon_regmap_lookup_by_compatible(props->syscon_name);
+	if (IS_ERR(dwsmchp->syscon)) {
+		dev_err(&pdev->dev, "No syscon map %s\n", props->syscon_name);
+		return PTR_ERR(dwsmchp->syscon);
+	}
+	dwsmchp->props = props;
+
+	/* Deassert all CS */
+	if (dwsmchp->spi_mst)
+		writel(0, dwsmchp->spi_mst + MSCC_SPI_MST_SW_MODE);
+
+	/* Select the owner of the SI interface */
+	regmap_update_bits(dwsmchp->syscon, MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL,
+			   MSCC_IF_SI_OWNER_MASK << props->si_owner_bit,
+			   MSCC_IF_SI_OWNER_SIMC << props->si_owner_bit);
+
+	dwsmchp->dws.set_cs = dw_spi_mchp_set_cs;
+
+	return 0;
+}
+
+static int dw_spi_mchp_probe(struct platform_device *pdev)
+{
+	const struct dw_spi_mchp_props *props;
+	struct dw_spi_mchp *dwsmchp;
+	struct dw_spi *dws;
+	int ret;
+	int num_cs, rx_sample_dly;
+
+	dwsmchp = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_mchp),
+			GFP_KERNEL);
+	if (!dwsmchp)
+		return -ENOMEM;
+
+	dws = &dwsmchp->dws;
+
+	/* Get basic io resource and map it */
+	dws->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(dws->regs)) {
+		dev_err(&pdev->dev, "SPI region map failed\n");
+		return PTR_ERR(dws->regs);
+	}
+
+	dws->irq = of_irq_get(pdev->dev.of_node, 0);
+	if (dws->irq < 0)
+		dev_info(&pdev->dev, "no irq, using polled mode\n");
+
+	dwsmchp->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dwsmchp->clk))
+		return PTR_ERR(dwsmchp->clk);
+	ret = clk_prepare_enable(dwsmchp->clk);
+	if (ret)
+		return ret;
+
+	dws->bus_num = pdev->id;
+
+	dws->max_freq = clk_get_rate(dwsmchp->clk);
+
+	device_property_read_u32(&pdev->dev, "reg-io-width",
+				 &dws->reg_io_width);
+
+	num_cs = MAX_CS;
+
+	device_property_read_u32(&pdev->dev, "num-cs", &num_cs);
+
+	dws->num_cs = num_cs;
+
+	rx_sample_dly = 0;
+	device_property_read_u32(&pdev->dev, "spi-rx-delay-us", &rx_sample_dly);
+	dws->rx_sample_dly = DIV_ROUND_UP(rx_sample_dly,
+					  (dws->max_freq / 1000000));
+
+	props = device_get_match_data(&pdev->dev);
+	if (props)
+		ret = dw_spi_mchp_init(pdev, dws, dwsmchp, props);
+	else
+		ret = -EINVAL;
+	if (ret)
+		goto out;
+
+	ret = dw_spi_add_host(&pdev->dev, dws);
+	if (ret)
+		goto out;
+
+	platform_set_drvdata(pdev, dwsmchp);
+	return 0;
+
+out:
+	clk_disable_unprepare(dwsmchp->clk);
+	return ret;
+}
+
+static int dw_spi_mchp_remove(struct platform_device *pdev)
+{
+	struct dw_spi_mchp *dwsmchp = platform_get_drvdata(pdev);
+
+	dw_spi_remove_host(&dwsmchp->dws);
+	clk_disable_unprepare(dwsmchp->clk);
+
+	return 0;
+}
+
+static const struct of_device_id dw_spi_mchp_of_match[] = {
+	{ .compatible = "mscc,ocelot-spi", .data = &dw_spi_mchp_props_ocelot},
+	{ .compatible = "mscc,jaguar2-spi", .data = &dw_spi_mchp_props_jaguar2},
+	{ /* end of table */}
+};
+MODULE_DEVICE_TABLE(of, dw_spi_mchp_of_match);
+
+static struct platform_driver dw_spi_mchp_driver = {
+	.probe		= dw_spi_mchp_probe,
+	.remove		= dw_spi_mchp_remove,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.of_match_table = dw_spi_mchp_of_match,
+	},
+};
+module_platform_driver(dw_spi_mchp_driver);
+
+MODULE_AUTHOR("Lars Povlsen <lars.povlsen@microchip.com>");
+MODULE_DESCRIPTION("Memory-mapped I/O interface DW SPI driver for MSCC SoCs");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 384a3ab6dc2d0..dc5db548fbcbc 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -32,97 +32,6 @@  struct dw_spi_mmio {
 	void           *priv;
 };

-#define MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL	0x24
-#define OCELOT_IF_SI_OWNER_OFFSET		4
-#define JAGUAR2_IF_SI_OWNER_OFFSET		6
-#define MSCC_IF_SI_OWNER_MASK			GENMASK(1, 0)
-#define MSCC_IF_SI_OWNER_SISL			0
-#define MSCC_IF_SI_OWNER_SIBM			1
-#define MSCC_IF_SI_OWNER_SIMC			2
-
-#define MSCC_SPI_MST_SW_MODE			0x14
-#define MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE	BIT(13)
-#define MSCC_SPI_MST_SW_MODE_SW_SPI_CS(x)	(x << 5)
-
-struct dw_spi_mscc {
-	struct regmap       *syscon;
-	void __iomem        *spi_mst;
-};
-
-/*
- * The Designware SPI controller (referred to as master in the documentation)
- * automatically deasserts chip select when the tx fifo is empty. The chip
- * selects then needs to be either driven as GPIOs or, for the first 4 using the
- * the SPI boot controller registers. the final chip select is an OR gate
- * between the Designware SPI controller and the SPI boot controller.
- */
-static void dw_spi_mscc_set_cs(struct spi_device *spi, bool enable)
-{
-	struct dw_spi *dws = spi_master_get_devdata(spi->master);
-	struct dw_spi_mmio *dwsmmio = container_of(dws, struct dw_spi_mmio, dws);
-	struct dw_spi_mscc *dwsmscc = dwsmmio->priv;
-	u32 cs = spi->chip_select;
-
-	if (cs < 4) {
-		u32 sw_mode = MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE;
-
-		if (!enable)
-			sw_mode |= MSCC_SPI_MST_SW_MODE_SW_SPI_CS(BIT(cs));
-
-		writel(sw_mode, dwsmscc->spi_mst + MSCC_SPI_MST_SW_MODE);
-	}
-
-	dw_spi_set_cs(spi, enable);
-}
-
-static int dw_spi_mscc_init(struct platform_device *pdev,
-			    struct dw_spi_mmio *dwsmmio,
-			    const char *cpu_syscon, u32 if_si_owner_offset)
-{
-	struct dw_spi_mscc *dwsmscc;
-
-	dwsmscc = devm_kzalloc(&pdev->dev, sizeof(*dwsmscc), GFP_KERNEL);
-	if (!dwsmscc)
-		return -ENOMEM;
-
-	dwsmscc->spi_mst = devm_platform_ioremap_resource(pdev, 1);
-	if (IS_ERR(dwsmscc->spi_mst)) {
-		dev_err(&pdev->dev, "SPI_MST region map failed\n");
-		return PTR_ERR(dwsmscc->spi_mst);
-	}
-
-	dwsmscc->syscon = syscon_regmap_lookup_by_compatible(cpu_syscon);
-	if (IS_ERR(dwsmscc->syscon))
-		return PTR_ERR(dwsmscc->syscon);
-
-	/* Deassert all CS */
-	writel(0, dwsmscc->spi_mst + MSCC_SPI_MST_SW_MODE);
-
-	/* Select the owner of the SI interface */
-	regmap_update_bits(dwsmscc->syscon, MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL,
-			   MSCC_IF_SI_OWNER_MASK << if_si_owner_offset,
-			   MSCC_IF_SI_OWNER_SIMC << if_si_owner_offset);
-
-	dwsmmio->dws.set_cs = dw_spi_mscc_set_cs;
-	dwsmmio->priv = dwsmscc;
-
-	return 0;
-}
-
-static int dw_spi_mscc_ocelot_init(struct platform_device *pdev,
-				   struct dw_spi_mmio *dwsmmio)
-{
-	return dw_spi_mscc_init(pdev, dwsmmio, "mscc,ocelot-cpu-syscon",
-				OCELOT_IF_SI_OWNER_OFFSET);
-}
-
-static int dw_spi_mscc_jaguar2_init(struct platform_device *pdev,
-				    struct dw_spi_mmio *dwsmmio)
-{
-	return dw_spi_mscc_init(pdev, dwsmmio, "mscc,jaguar2-cpu-syscon",
-				JAGUAR2_IF_SI_OWNER_OFFSET);
-}
-
 static int dw_spi_alpine_init(struct platform_device *pdev,
 			      struct dw_spi_mmio *dwsmmio)
 {
@@ -225,8 +134,6 @@  static int dw_spi_mmio_remove(struct platform_device *pdev)

 static const struct of_device_id dw_spi_mmio_of_match[] = {
 	{ .compatible = "snps,dw-apb-ssi", },
-	{ .compatible = "mscc,ocelot-spi", .data = dw_spi_mscc_ocelot_init},
-	{ .compatible = "mscc,jaguar2-spi", .data = dw_spi_mscc_jaguar2_init},
 	{ .compatible = "amazon,alpine-dw-apb-ssi", .data = dw_spi_alpine_init},
 	{ .compatible = "renesas,rzn1-spi", },
 	{ /* end of table */}