From: Lars Povlsen <lars.povlsen@microchip.com> To: Mark Brown <broonie@kernel.org>, SoC Team <soc@kernel.org> Cc: Lars Povlsen <lars.povlsen@microchip.com>, 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: [PATCH 05/10] spi: spi-dw-mmio: Spin off MSCC platforms into spi-dw-mchp Date: Wed, 13 May 2020 16:00:26 +0200 [thread overview] Message-ID: <20200513140031.25633-6-lars.povlsen@microchip.com> (raw) In-Reply-To: <20200513140031.25633-1-lars.povlsen@microchip.com> 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 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 */} -- 2.26.2
WARNING: multiple messages have this Message-ID (diff)
From: Lars Povlsen <lars.povlsen@microchip.com> To: Mark Brown <broonie@kernel.org>, SoC Team <soc@kernel.org> Cc: devicetree@vger.kernel.org, Alexandre Belloni <alexandre.belloni@bootlin.com>, linux-kernel@vger.kernel.org, linux-spi@vger.kernel.org, Lars Povlsen <lars.povlsen@microchip.com>, Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>, linux-arm-kernel@lists.infradead.org Subject: [PATCH 05/10] spi: spi-dw-mmio: Spin off MSCC platforms into spi-dw-mchp Date: Wed, 13 May 2020 16:00:26 +0200 [thread overview] Message-ID: <20200513140031.25633-6-lars.povlsen@microchip.com> (raw) In-Reply-To: <20200513140031.25633-1-lars.povlsen@microchip.com> 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 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 */} -- 2.26.2 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2020-05-13 14:01 UTC|newest] Thread overview: 78+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-05-13 14:00 [PATCH 00/10] spi: Adding support for Microchip Sparx5 SoC Lars Povlsen 2020-05-13 14:00 ` Lars Povlsen 2020-05-13 14:00 ` [PATCH 01/10] spi: dw: Add support for polled operation via no IRQ specified in DT Lars Povlsen 2020-05-13 14:00 ` Lars Povlsen 2020-05-13 14:20 ` Mark Brown 2020-05-14 13:04 ` Serge Semin 2020-05-14 13:04 ` Serge Semin 2020-05-15 9:11 ` Lars Povlsen 2020-05-15 9:11 ` Lars Povlsen 2020-05-13 14:37 ` Mark Brown 2020-05-19 10:21 ` Lars Povlsen 2020-05-19 10:21 ` Lars Povlsen 2020-05-13 14:55 ` Andy Shevchenko 2020-05-13 14:55 ` Andy Shevchenko 2020-05-19 10:25 ` Lars Povlsen 2020-05-19 10:25 ` Lars Povlsen 2020-06-02 19:10 ` Serge Semin 2020-06-02 19:10 ` Serge Semin 2020-06-09 9:13 ` Lars Povlsen 2020-06-09 9:13 ` Lars Povlsen 2020-05-13 14:00 ` [PATCH 02/10] spi: dw: Add support for RX sample delay register Lars Povlsen 2020-05-13 14:00 ` Lars Povlsen 2020-06-02 19:39 ` Serge Semin 2020-06-02 19:39 ` Serge Semin 2020-06-09 10:04 ` Lars Povlsen 2020-06-09 10:04 ` Lars Povlsen 2020-05-13 14:00 ` [PATCH 03/10] spi: dw: Add support for client driver memory operations Lars Povlsen 2020-05-13 14:00 ` Lars Povlsen 2020-05-13 14:00 ` [PATCH 04/10] dt-bindings: spi: Add bindings for spi-dw-mchp Lars Povlsen 2020-05-13 14:00 ` Lars Povlsen 2020-05-13 14:52 ` Mark Brown 2020-05-19 11:47 ` Lars Povlsen 2020-05-19 11:47 ` Lars Povlsen 2020-05-19 11:58 ` Mark Brown 2020-05-19 12:10 ` Lars Povlsen 2020-05-19 12:10 ` Lars Povlsen 2020-06-02 19:49 ` Serge Semin 2020-06-02 19:49 ` Serge Semin 2020-06-09 10:27 ` Lars Povlsen 2020-06-09 10:27 ` Lars Povlsen 2020-05-13 14:00 ` Lars Povlsen [this message] 2020-05-13 14:00 ` [PATCH 05/10] spi: spi-dw-mmio: Spin off MSCC platforms into spi-dw-mchp Lars Povlsen 2020-05-13 15:18 ` Mark Brown 2020-05-19 12:05 ` Lars Povlsen 2020-05-19 12:05 ` Lars Povlsen 2020-06-02 21:12 ` Serge Semin 2020-06-02 21:12 ` Serge Semin 2020-06-10 14:28 ` Lars Povlsen 2020-06-10 14:28 ` Lars Povlsen 2020-05-13 14:00 ` [PATCH 06/10] dt-bindings: spi: spi-dw-mchp: Add Sparx5 support Lars Povlsen 2020-05-13 14:00 ` Lars Povlsen 2020-05-13 15:25 ` Mark Brown 2020-06-02 23:07 ` Serge Semin 2020-06-02 23:07 ` Serge Semin 2020-06-10 12:27 ` Lars Povlsen 2020-06-10 12:27 ` Lars Povlsen 2020-05-13 14:00 ` [PATCH 07/10] " Lars Povlsen 2020-05-13 14:00 ` Lars Povlsen 2020-05-14 10:25 ` Mark Brown 2020-05-19 9:29 ` Lars Povlsen 2020-05-19 9:29 ` Lars Povlsen 2020-06-02 23:22 ` Serge Semin 2020-06-02 23:22 ` Serge Semin 2020-05-13 14:00 ` [PATCH 08/10] arm64: dts: sparx5: Add SPI controller Lars Povlsen 2020-05-13 14:00 ` Lars Povlsen 2020-05-13 14:00 ` [PATCH 09/10] arm64: dts: sparx5: Add spi-nor support Lars Povlsen 2020-05-13 14:00 ` Lars Povlsen 2020-05-13 14:00 ` [PATCH 10/10] arm64: dts: sparx5: Add spi-nand devices Lars Povlsen 2020-05-13 14:00 ` Lars Povlsen 2020-05-29 16:21 ` [PATCH 00/10] spi: Adding support for Microchip Sparx5 SoC Serge Semin 2020-05-29 16:21 ` Serge Semin 2020-06-02 8:18 ` Lars Povlsen 2020-06-02 8:18 ` Lars Povlsen 2020-06-02 8:21 ` Serge Semin 2020-06-02 8:21 ` Serge Semin 2020-06-02 9:56 ` Mark Brown 2020-06-02 23:44 ` Serge Semin 2020-06-02 23:44 ` Serge Semin
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200513140031.25633-6-lars.povlsen@microchip.com \ --to=lars.povlsen@microchip.com \ --cc=UNGLinuxDriver@microchip.com \ --cc=alexandre.belloni@bootlin.com \ --cc=broonie@kernel.org \ --cc=devicetree@vger.kernel.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-spi@vger.kernel.org \ --cc=soc@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.