diff options
Diffstat (limited to 'drivers/spi')
104 files changed, 3954 insertions, 2421 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3a1d8f1170de..d6ed0c355954 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -80,6 +80,7 @@ config SPI_ARMADA_3700 config SPI_ATMEL tristate "Atmel SPI Controller" depends on ARCH_AT91 || COMPILE_TEST + depends on OF help This selects a driver for the Atmel SPI Controller, present on many AT91 ARM chips. @@ -143,7 +144,7 @@ config SPI_BCM63XX tristate "Broadcom BCM63xx SPI controller" depends on BCM63XX || COMPILE_TEST help - Enable support for the SPI controller on the Broadcom BCM63xx SoCs. + Enable support for the SPI controller on the Broadcom BCM63xx SoCs. config SPI_BCM63XX_HSSPI tristate "Broadcom BCM63XX HS SPI controller driver" @@ -234,11 +235,11 @@ config SPI_DLN2 tristate "Diolan DLN-2 USB SPI adapter" depends on MFD_DLN2 help - If you say yes to this option, support will be included for Diolan - DLN2, a USB to SPI interface. + If you say yes to this option, support will be included for Diolan + DLN2, a USB to SPI interface. - This driver can also be built as a module. If so, the module - will be called spi-dln2. + This driver can also be built as a module. If so, the module + will be called spi-dln2. config SPI_EFM32 tristate "EFM32 SPI controller" @@ -280,6 +281,15 @@ config SPI_FSL_QUADSPI This controller does not support generic SPI messages. It only supports the high-level SPI memory interface. +config SPI_HISI_SFC_V3XX + tristate "HiSilicon SPI-NOR Flash Controller for Hi16XX chipsets" + depends on (ARM64 && ACPI) || COMPILE_TEST + depends on HAS_IOMEM + select CONFIG_MTD_SPI_NOR + help + This enables support for HiSilicon v3xx SPI-NOR flash controller + found in hi16xx chipsets. + config SPI_NXP_FLEXSPI tristate "NXP Flex SPI controller" depends on ARCH_LAYERSCAPE || HAS_IOMEM @@ -433,6 +443,16 @@ config SPI_MT7621 help This selects a driver for the MediaTek MT7621 SPI Controller. +config SPI_NPCM_FIU + tristate "Nuvoton NPCM FLASH Interface Unit" + depends on ARCH_NPCM || COMPILE_TEST + depends on OF && HAS_IOMEM + help + This enables support for the Flash Interface Unit SPI controller + in master mode. + This driver does not support generic SPI. The implementation only + supports spi-mem interface. + config SPI_NPCM_PSPI tristate "Nuvoton NPCM PSPI Controller" depends on ARCH_NPCM || COMPILE_TEST @@ -440,13 +460,6 @@ config SPI_NPCM_PSPI This driver provides support for Nuvoton NPCM BMC Peripheral SPI controller in master mode. -config SPI_NUC900 - tristate "Nuvoton NUC900 series SPI" - depends on ARCH_W90X900 - select SPI_BITBANG - help - SPI driver for Nuvoton NUC900 series ARM SoCs - config SPI_LANTIQ_SSC tristate "Lantiq SSC SPI controller" depends on LANTIQ || COMPILE_TEST @@ -543,7 +556,7 @@ config SPI_PXA2XX help This enables using a PXA2xx or Sodaville SSP port as a SPI master controller. The driver can be configured to use any SSP port and - additional documentation can be found a Documentation/spi/pxa2xx. + additional documentation can be found a Documentation/spi/pxa2xx.rst. config SPI_PXA2XX_PCI def_tristate SPI_PXA2XX && PCI && COMMON_CLK @@ -744,10 +757,10 @@ config SPI_SYNQUACER It also supports the new dual-bit and quad-bit SPI protocol. config SPI_MXIC - tristate "Macronix MX25F0A SPI controller" - depends on SPI_MASTER - help - This selects the Macronix MX25F0A SPI controller driver. + tristate "Macronix MX25F0A SPI controller" + depends on SPI_MASTER + help + This selects the Macronix MX25F0A SPI controller driver. config SPI_MXS tristate "Freescale MXS SPI controller" diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 63dcab552bcb..9b65ec5afc5e 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_FSL_LPSPI) += spi-fsl-lpspi.o obj-$(CONFIG_SPI_FSL_QUADSPI) += spi-fsl-qspi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o +obj-$(CONFIG_SPI_HISI_SFC_V3XX) += spi-hisi-sfc-v3xx.o obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o obj-$(CONFIG_SPI_IMX) += spi-imx.o obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o @@ -63,8 +64,8 @@ obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o obj-$(CONFIG_SPI_MXIC) += spi-mxic.o obj-$(CONFIG_SPI_MXS) += spi-mxs.o +obj-$(CONFIG_SPI_NPCM_FIU) += spi-npcm-fiu.o obj-$(CONFIG_SPI_NPCM_PSPI) += spi-npcm-pspi.o -obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o obj-$(CONFIG_SPI_NXP_FLEXSPI) += spi-nxp-fspi.o obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o spi-octeon-objs := spi-cavium.o spi-cavium-octeon.o diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index 6a7d7b553d95..fd8007ebb145 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -526,7 +526,6 @@ static int atmel_qspi_probe(struct platform_device *pdev) /* Request the IRQ */ irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "missing IRQ\n"); err = irq; goto disable_qspick; } diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c index ea160f117f88..41d71ba7fd32 100644 --- a/drivers/spi/spi-altera.c +++ b/drivers/spi/spi-altera.c @@ -170,7 +170,6 @@ static int altera_spi_probe(struct platform_device *pdev) { struct altera_spi *hw; struct spi_master *master; - struct resource *res; int err = -ENODEV; master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi)); @@ -189,8 +188,7 @@ static int altera_spi_probe(struct platform_device *pdev) hw = spi_master_get_devdata(master); /* find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hw->base = devm_ioremap_resource(&pdev->dev, res); + hw->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hw->base)) { err = PTR_ERR(hw->base); goto exit; diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index 032888344822..e450ee17787f 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -817,7 +817,6 @@ static int a3700_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *of_node = dev->of_node; - struct resource *res; struct spi_master *master; struct a3700_spi *spi; u32 num_cs = 0; @@ -855,8 +854,7 @@ static int a3700_spi_probe(struct platform_device *pdev) spi->master = master; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi->base = devm_ioremap_resource(dev, res); + spi->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi->base)) { ret = PTR_ERR(spi->base); goto error; @@ -864,7 +862,6 @@ static int a3700_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "could not get irq: %d\n", irq); ret = -ENXIO; goto error; } diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index a40bb2ef89dc..88033422a42a 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -132,7 +132,7 @@ static int at91_usart_spi_configure_dma(struct spi_controller *ctlr, dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - ctlr->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + ctlr->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR_OR_NULL(ctlr->dma_tx)) { if (IS_ERR(ctlr->dma_tx)) { err = PTR_ERR(ctlr->dma_tx); @@ -145,7 +145,7 @@ static int at91_usart_spi_configure_dma(struct spi_controller *ctlr, goto at91_usart_spi_error_clear; } - ctlr->dma_rx = dma_request_slave_channel_reason(dev, "rx"); + ctlr->dma_rx = dma_request_chan(dev, "rx"); if (IS_ERR_OR_NULL(ctlr->dma_rx)) { if (IS_ERR(ctlr->dma_rx)) { err = PTR_ERR(ctlr->dma_rx); diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 032a615e4ccd..eb9a243e9526 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -139,7 +139,6 @@ static int ath79_spi_probe(struct platform_device *pdev) struct spi_master *master; struct ath79_spi *sp; struct ath79_spi_platform_data *pdata; - struct resource *r; unsigned long rate; int ret; @@ -169,8 +168,7 @@ static int ath79_spi_probe(struct platform_device *pdev) sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0; sp->bitbang.flags = SPI_CS_HIGH; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sp->base = devm_ioremap_resource(&pdev->dev, r); + sp->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sp->base)) { ret = PTR_ERR(sp->base); goto err_put_master; diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index f00b367523cd..013458cabe3c 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -23,6 +23,7 @@ #include <linux/gpio/consumer.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> +#include <trace/events/spi.h> /* SPI register offsets */ #define SPI_CR 0x0000 @@ -221,37 +222,13 @@ | SPI_BF(name, value)) /* Register access macros */ -#ifdef CONFIG_AVR32 -#define spi_readl(port, reg) \ - __raw_readl((port)->regs + SPI_##reg) -#define spi_writel(port, reg, value) \ - __raw_writel((value), (port)->regs + SPI_##reg) - -#define spi_readw(port, reg) \ - __raw_readw((port)->regs + SPI_##reg) -#define spi_writew(port, reg, value) \ - __raw_writew((value), (port)->regs + SPI_##reg) - -#define spi_readb(port, reg) \ - __raw_readb((port)->regs + SPI_##reg) -#define spi_writeb(port, reg, value) \ - __raw_writeb((value), (port)->regs + SPI_##reg) -#else #define spi_readl(port, reg) \ readl_relaxed((port)->regs + SPI_##reg) #define spi_writel(port, reg, value) \ writel_relaxed((value), (port)->regs + SPI_##reg) - -#define spi_readw(port, reg) \ - readw_relaxed((port)->regs + SPI_##reg) #define spi_writew(port, reg, value) \ writew_relaxed((value), (port)->regs + SPI_##reg) -#define spi_readb(port, reg) \ - readb_relaxed((port)->regs + SPI_##reg) -#define spi_writeb(port, reg, value) \ - writeb_relaxed((value), (port)->regs + SPI_##reg) -#endif /* use PIO for small transfers, avoiding DMA setup/teardown overhead and * cache operations; better heuristics consider wordsize and bitrate. */ @@ -298,17 +275,16 @@ struct atmel_spi { bool use_dma; bool use_pdc; - bool use_cs_gpios; bool keep_cs; - bool cs_active; u32 fifo_size; + u8 native_cs_free; + u8 native_cs_for_gpio; }; /* Controller-specific per-slave state */ struct atmel_spi_device { - struct gpio_desc *npcs_pin; u32 csr; }; @@ -335,11 +311,9 @@ static bool atmel_spi_is_v2(struct atmel_spi *as) * transmitted") Not so! Workaround uses nCSx pins as GPIOs; or newer * controllers have CSAAT and friends. * - * Since the CSAAT functionality is a bit weird on newer controllers as - * well, we use GPIO to control nCSx pins on all controllers, updating - * MR.PCS to avoid confusing the controller. Using GPIOs also lets us - * support active-high chipselects despite the controller's belief that - * only active-low devices/systems exists. + * Even controller newer than ar91rm9200, using GPIOs can make sens as + * it lets us support active-high chipselects despite the controller's + * belief that only active-low devices/systems exists. * * However, at91rm9200 has a second erratum whereby nCS0 doesn't work * right when driven with GPIO. ("Mode Fault does not allow more than one @@ -351,30 +325,36 @@ static bool atmel_spi_is_v2(struct atmel_spi *as) static void cs_activate(struct atmel_spi *as, struct spi_device *spi) { struct atmel_spi_device *asd = spi->controller_state; + int chip_select; u32 mr; + if (spi->cs_gpiod) + chip_select = as->native_cs_for_gpio; + else + chip_select = spi->chip_select; + if (atmel_spi_is_v2(as)) { - spi_writel(as, CSR0 + 4 * spi->chip_select, asd->csr); + spi_writel(as, CSR0 + 4 * chip_select, asd->csr); /* For the low SPI version, there is a issue that PDC transfer * on CS1,2,3 needs SPI_CSR0.BITS config as SPI_CSR1,2,3.BITS */ spi_writel(as, CSR0, asd->csr); if (as->caps.has_wdrbt) { spi_writel(as, MR, - SPI_BF(PCS, ~(0x01 << spi->chip_select)) + SPI_BF(PCS, ~(0x01 << chip_select)) | SPI_BIT(WDRBT) | SPI_BIT(MODFDIS) | SPI_BIT(MSTR)); } else { spi_writel(as, MR, - SPI_BF(PCS, ~(0x01 << spi->chip_select)) + SPI_BF(PCS, ~(0x01 << chip_select)) | SPI_BIT(MODFDIS) | SPI_BIT(MSTR)); } mr = spi_readl(as, MR); - if (as->use_cs_gpios) - gpiod_set_value(asd->npcs_pin, 1); + if (spi->cs_gpiod) + gpiod_set_value(spi->cs_gpiod, 1); } else { u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0; int i; @@ -389,9 +369,9 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi) } mr = spi_readl(as, MR); - mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr); - if (as->use_cs_gpios && spi->chip_select != 0) - gpiod_set_value(asd->npcs_pin, 1); + mr = SPI_BFINS(PCS, ~(1 << chip_select), mr); + if (spi->cs_gpiod) + gpiod_set_value(spi->cs_gpiod, 1); spi_writel(as, MR, mr); } @@ -400,24 +380,29 @@ static void cs_activate(struct atmel_spi *as, struct spi_device *spi) static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) { - struct atmel_spi_device *asd = spi->controller_state; + int chip_select; u32 mr; + if (spi->cs_gpiod) + chip_select = as->native_cs_for_gpio; + else + chip_select = spi->chip_select; + /* only deactivate *this* device; sometimes transfers to * another device may be active when this routine is called. */ mr = spi_readl(as, MR); - if (~SPI_BFEXT(PCS, mr) & (1 << spi->chip_select)) { + if (~SPI_BFEXT(PCS, mr) & (1 << chip_select)) { mr = SPI_BFINS(PCS, 0xf, mr); spi_writel(as, MR, mr); } dev_dbg(&spi->dev, "DEactivate NPCS, mr %08x\n", mr); - if (!as->use_cs_gpios) + if (!spi->cs_gpiod) spi_writel(as, CR, SPI_BIT(LASTXFER)); - else if (atmel_spi_is_v2(as) || spi->chip_select != 0) - gpiod_set_value(asd->npcs_pin, 0); + else + gpiod_set_value(spi->cs_gpiod, 0); } static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock) @@ -526,29 +511,22 @@ static int atmel_spi_configure_dma(struct spi_master *master, dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - master->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + master->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR(master->dma_tx)) { err = PTR_ERR(master->dma_tx); - if (err == -EPROBE_DEFER) { - dev_warn(dev, "no DMA channel available at the moment\n"); - goto error_clear; - } - dev_err(dev, - "DMA TX channel not available, SPI unable to use DMA\n"); - err = -EBUSY; + if (err != -EPROBE_DEFER) + dev_err(dev, "No TX DMA channel, DMA is disabled\n"); goto error_clear; } - /* - * No reason to check EPROBE_DEFER here since we have already requested - * tx channel. If it fails here, it's for another reason. - */ - master->dma_rx = dma_request_slave_channel(dev, "rx"); - - if (!master->dma_rx) { - dev_err(dev, - "DMA RX channel not available, SPI unable to use DMA\n"); - err = -EBUSY; + master->dma_rx = dma_request_chan(dev, "rx"); + if (IS_ERR(master->dma_rx)) { + err = PTR_ERR(master->dma_rx); + /* + * No reason to check EPROBE_DEFER here since we have already + * requested tx channel. + */ + dev_err(dev, "No RX DMA channel, DMA is disabled\n"); goto error; } @@ -563,7 +541,7 @@ static int atmel_spi_configure_dma(struct spi_master *master, return 0; error: - if (master->dma_rx) + if (!IS_ERR(master->dma_rx)) dma_release_channel(master->dma_rx); if (!IS_ERR(master->dma_tx)) dma_release_channel(master->dma_tx); @@ -843,6 +821,12 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as, { u32 scbr, csr; unsigned long bus_hz; + int chip_select; + + if (spi->cs_gpiod) + chip_select = as->native_cs_for_gpio; + else + chip_select = spi->chip_select; /* v1 chips start out at half the peripheral bus speed. */ bus_hz = as->spi_clk; @@ -871,9 +855,9 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as, xfer->speed_hz, scbr, bus_hz); return -EINVAL; } - csr = spi_readl(as, CSR0 + 4 * spi->chip_select); + csr = spi_readl(as, CSR0 + 4 * chip_select); csr = SPI_BFINS(SCBR, scbr, csr); - spi_writel(as, CSR0 + 4 * spi->chip_select, csr); + spi_writel(as, CSR0 + 4 * chip_select, csr); return 0; } @@ -1172,40 +1156,105 @@ atmel_spi_pdc_interrupt(int irq, void *dev_id) return ret; } +static int atmel_word_delay_csr(struct spi_device *spi, struct atmel_spi *as) +{ + struct spi_delay *delay = &spi->word_delay; + u32 value = delay->value; + + switch (delay->unit) { + case SPI_DELAY_UNIT_NSECS: + value /= 1000; + break; + case SPI_DELAY_UNIT_USECS: + break; + default: + return -EINVAL; + } + + return (as->spi_clk / 1000000 * value) >> 5; +} + +static void initialize_native_cs_for_gpio(struct atmel_spi *as) +{ + int i; + struct spi_master *master = platform_get_drvdata(as->pdev); + + if (!as->native_cs_free) + return; /* already initialized */ + + if (!master->cs_gpiods) + return; /* No CS GPIO */ + + /* + * On the first version of the controller (AT91RM9200), CS0 + * can't be used associated with GPIO + */ + if (atmel_spi_is_v2(as)) + i = 0; + else + i = 1; + + for (; i < 4; i++) + if (master->cs_gpiods[i]) + as->native_cs_free |= BIT(i); + + if (as->native_cs_free) + as->native_cs_for_gpio = ffs(as->native_cs_free); +} + static int atmel_spi_setup(struct spi_device *spi) { struct atmel_spi *as; struct atmel_spi_device *asd; u32 csr; unsigned int bits = spi->bits_per_word; + int chip_select; + int word_delay_csr; as = spi_master_get_devdata(spi->master); /* see notes above re chipselect */ - if (!atmel_spi_is_v2(as) - && spi->chip_select == 0 - && (spi->mode & SPI_CS_HIGH)) { - dev_dbg(&spi->dev, "setup: can't be active-high\n"); + if (!spi->cs_gpiod && (spi->mode & SPI_CS_HIGH)) { + dev_warn(&spi->dev, "setup: non GPIO CS can't be active-high\n"); return -EINVAL; } + /* Setup() is called during spi_register_controller(aka + * spi_register_master) but after all membmers of the cs_gpiod + * array have been filled, so we can looked for which native + * CS will be free for using with GPIO + */ + initialize_native_cs_for_gpio(as); + + if (spi->cs_gpiod && as->native_cs_free) { + dev_err(&spi->dev, + "No native CS available to support this GPIO CS\n"); + return -EBUSY; + } + + if (spi->cs_gpiod) + chip_select = as->native_cs_for_gpio; + else + chip_select = spi->chip_select; + csr = SPI_BF(BITS, bits - 8); if (spi->mode & SPI_CPOL) csr |= SPI_BIT(CPOL); if (!(spi->mode & SPI_CPHA)) csr |= SPI_BIT(NCPHA); - if (!as->use_cs_gpios) - csr |= SPI_BIT(CSAAT); - /* DLYBS is mostly irrelevant since we manage chipselect using GPIOs. - */ + if (!spi->cs_gpiod) + csr |= SPI_BIT(CSAAT); csr |= SPI_BF(DLYBS, 0); + word_delay_csr = atmel_word_delay_csr(spi, as); + if (word_delay_csr < 0) + return word_delay_csr; + /* DLYBCT adds delays between words. This is useful for slow devices * that need a bit of time to setup the next transfer. */ - csr |= SPI_BF(DLYBCT, - (as->spi_clk / 1000000 * spi->word_delay_usecs) >> 5); + csr |= SPI_BF(DLYBCT, word_delay_csr); asd = spi->controller_state; if (!asd) { @@ -1213,21 +1262,6 @@ static int atmel_spi_setup(struct spi_device *spi) if (!asd) return -ENOMEM; - /* - * If use_cs_gpios is true this means that we have "cs-gpios" - * defined in the device tree node so we should have - * gotten the GPIO lines from the device tree inside the - * SPI core. Warn if this is not the case but continue since - * CS GPIOs are after all optional. - */ - if (as->use_cs_gpios) { - if (!spi->cs_gpiod) { - dev_err(&spi->dev, - "host claims to use CS GPIOs but no CS found in DT by the SPI core\n"); - } - asd->npcs_pin = spi->cs_gpiod; - } - spi->controller_state = asd; } @@ -1238,7 +1272,7 @@ static int atmel_spi_setup(struct spi_device *spi) bits, spi->mode, spi->chip_select, csr); if (!atmel_spi_is_v2(as)) - spi_writel(as, CSR0 + 4 * spi->chip_select, csr); + spi_writel(as, CSR0 + 4 * chip_select, csr); return 0; } @@ -1367,19 +1401,16 @@ static int atmel_spi_one_transfer(struct spi_master *master, && as->use_pdc) atmel_spi_dma_unmap_xfer(master, xfer); - if (xfer->delay_usecs) - udelay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); if (xfer->cs_change) { if (list_is_last(&xfer->transfer_list, &msg->transfers)) { as->keep_cs = true; } else { - as->cs_active = !as->cs_active; - if (as->cs_active) - cs_activate(as, msg->spi); - else - cs_deactivate(as, msg->spi); + cs_deactivate(as, msg->spi); + udelay(10); + cs_activate(as, msg->spi); } } @@ -1402,16 +1433,19 @@ static int atmel_spi_transfer_one_message(struct spi_master *master, atmel_spi_lock(as); cs_activate(as, spi); - as->cs_active = true; as->keep_cs = false; msg->status = 0; msg->actual_length = 0; list_for_each_entry(xfer, &msg->transfers, transfer_list) { + trace_spi_transfer_start(msg, xfer); + ret = atmel_spi_one_transfer(master, msg, xfer); if (ret) goto msg_done; + + trace_spi_transfer_stop(msg, xfer); } if (as->use_pdc) @@ -1522,7 +1556,7 @@ static int atmel_spi_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16); master->dev.of_node = pdev->dev.of_node; master->bus_num = pdev->id; - master->num_chipselect = master->dev.of_node ? 0 : 4; + master->num_chipselect = 4; master->setup = atmel_spi_setup; master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX); master->transfer_one_message = atmel_spi_transfer_one_message; @@ -1550,19 +1584,6 @@ static int atmel_spi_probe(struct platform_device *pdev) atmel_get_caps(as); - /* - * If there are chip selects in the device tree, those will be - * discovered by the SPI core when registering the SPI master - * and assigned to each SPI device. - */ - as->use_cs_gpios = true; - if (atmel_spi_is_v2(as) && - pdev->dev.of_node && - !of_get_property(pdev->dev.of_node, "cs-gpios", NULL)) { - as->use_cs_gpios = false; - master->num_chipselect = 4; - } - as->use_dma = false; as->use_pdc = false; if (as->caps.has_dma_support) { @@ -1770,20 +1791,18 @@ static const struct dev_pm_ops atmel_spi_pm_ops = { #define ATMEL_SPI_PM_OPS NULL #endif -#if defined(CONFIG_OF) static const struct of_device_id atmel_spi_dt_ids[] = { { .compatible = "atmel,at91rm9200-spi" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_spi_dt_ids); -#endif static struct platform_driver atmel_spi_driver = { .driver = { .name = "atmel_spi", .pm = ATMEL_SPI_PM_OPS, - .of_match_table = of_match_ptr(atmel_spi_dt_ids), + .of_match_table = atmel_spi_dt_ids, }, .probe = atmel_spi_probe, .remove = atmel_spi_remove, diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 3b1833e6c7ad..eb9b78a90dcf 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -163,10 +163,21 @@ static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry, } static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry, - struct spi_engine *spi_engine, unsigned int clk_div, unsigned int delay) + struct spi_engine *spi_engine, unsigned int clk_div, + struct spi_transfer *xfer) { unsigned int spi_clk = clk_get_rate(spi_engine->ref_clk); unsigned int t; + int delay; + + if (xfer->delay_usecs) { + delay = xfer->delay_usecs; + } else { + delay = spi_delay_to_ns(&xfer->delay, xfer); + if (delay < 0) + return; + delay /= 1000; + } if (delay == 0) return; @@ -218,8 +229,7 @@ static int spi_engine_compile_message(struct spi_engine *spi_engine, spi_engine_gen_cs(p, dry, spi, true); spi_engine_gen_xfer(p, dry, xfer); - spi_engine_gen_sleep(p, dry, spi_engine, clk_div, - xfer->delay_usecs); + spi_engine_gen_sleep(p, dry, spi_engine, clk_div, xfer); cs_change = xfer->cs_change; if (list_is_last(&xfer->transfer_list, &msg->transfers)) @@ -460,7 +470,6 @@ static int spi_engine_probe(struct platform_device *pdev) struct spi_engine *spi_engine; struct spi_master *master; unsigned int version; - struct resource *res; int irq; int ret; @@ -480,8 +489,7 @@ static int spi_engine_probe(struct platform_device *pdev) spin_lock_init(&spi_engine->lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi_engine->base = devm_ioremap_resource(&pdev->dev, res); + spi_engine->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi_engine->base)) { ret = PTR_ERR(spi_engine->base); goto err_put_master; diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 902bdbfedea8..23d295f36c80 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -343,7 +343,7 @@ static int bcm_qspi_bspi_set_flex_mode(struct bcm_qspi *qspi, { int bpc = 0, bpp = 0; u8 command = op->cmd.opcode; - int width = op->cmd.buswidth ? op->cmd.buswidth : SPI_NBITS_SINGLE; + int width = op->data.buswidth ? op->data.buswidth : SPI_NBITS_SINGLE; int addrlen = op->addr.nbytes; int flex_mode = 1; @@ -803,7 +803,8 @@ static int bcm_qspi_bspi_exec_mem_op(struct spi_device *spi, return -EIO; from = op->addr.val; - bcm_qspi_chip_select(qspi, spi->chip_select); + if (!spi->cs_gpiod) + bcm_qspi_chip_select(qspi, spi->chip_select); bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0); /* @@ -882,7 +883,8 @@ static int bcm_qspi_transfer_one(struct spi_master *master, int slots; unsigned long timeo = msecs_to_jiffies(100); - bcm_qspi_chip_select(qspi, spi->chip_select); + if (!spi->cs_gpiod) + bcm_qspi_chip_select(qspi, spi->chip_select); qspi->trans_pos.trans = trans; qspi->trans_pos.byte = 0; @@ -897,6 +899,7 @@ static int bcm_qspi_transfer_one(struct spi_master *master, read_from_hw(qspi, slots); } + bcm_qspi_enable_bspi(qspi); return 0; } @@ -981,7 +984,7 @@ static int bcm_qspi_exec_mem_op(struct spi_mem *mem, if (mspi_read) return bcm_qspi_mspi_exec_mem_op(spi, op); - ret = bcm_qspi_bspi_set_mode(qspi, op, -1); + ret = bcm_qspi_bspi_set_mode(qspi, op, 0); if (!ret) ret = bcm_qspi_bspi_exec_mem_op(spi, op); @@ -1233,6 +1236,7 @@ int bcm_qspi_probe(struct platform_device *pdev, master->cleanup = bcm_qspi_cleanup; master->dev.of_node = dev->of_node; master->num_chipselect = NUM_CHIPSELECT; + master->use_gpio_descriptors = true; qspi->big_endian = of_device_is_big_endian(dev->of_node); @@ -1289,7 +1293,7 @@ int bcm_qspi_probe(struct platform_device *pdev, name = qspi_irq_tab[val].irq_name; if (qspi_irq_tab[val].irq_source == SINGLE_L2) { /* get the l2 interrupts */ - irq = platform_get_irq_byname(pdev, name); + irq = platform_get_irq_byname_optional(pdev, name); } else if (!num_ints && soc_intc) { /* all mspi, bspi intrs muxed to one L1 intr */ irq = platform_get_irq(pdev, 0); diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 840b1b8ff3dc..11c235879bb7 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -25,7 +25,9 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_device.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio/machine.h> /* FIXME: using chip internals */ +#include <linux/gpio/driver.h> /* FIXME: using chip internals */ #include <linux/of_irq.h> #include <linux/spi/spi.h> @@ -66,6 +68,7 @@ #define BCM2835_SPI_FIFO_SIZE 64 #define BCM2835_SPI_FIFO_SIZE_3_4 48 #define BCM2835_SPI_DMA_MIN_LENGTH 96 +#define BCM2835_SPI_NUM_CS 4 /* raise as necessary */ #define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ | SPI_NO_CS | SPI_3WIRE) @@ -92,7 +95,8 @@ MODULE_PARM_DESC(polling_limit_us, * @rx_prologue: bytes received without DMA if first RX sglist entry's * length is not a multiple of 4 (to overcome hardware limitation) * @tx_spillover: whether @tx_prologue spills over to second TX sglist entry - * @dma_pending: whether a DMA transfer is in progress + * @prepare_cs: precalculated CS register value for ->prepare_message() + * (uses slave-specific clock polarity and phase settings) * @debugfs_dir: the debugfs directory - neede to remove debugfs when * unloading the module * @count_transfer_polling: count of how often polling mode is used @@ -102,6 +106,19 @@ MODULE_PARM_DESC(polling_limit_us, * These are counted as well in @count_transfer_polling and * @count_transfer_irq * @count_transfer_dma: count how often dma mode is used + * @chip_select: SPI slave currently selected + * (used by bcm2835_spi_dma_tx_done() to write @clear_rx_cs) + * @tx_dma_active: whether a TX DMA descriptor is in progress + * @rx_dma_active: whether a RX DMA descriptor is in progress + * (used by bcm2835_spi_dma_tx_done() to handle a race) + * @fill_tx_desc: preallocated TX DMA descriptor used for RX-only transfers + * (cyclically copies from zero page to TX FIFO) + * @fill_tx_addr: bus address of zero page + * @clear_rx_desc: preallocated RX DMA descriptor used for TX-only transfers + * (cyclically clears RX FIFO by writing @clear_rx_cs to CS register) + * @clear_rx_addr: bus address of @clear_rx_cs + * @clear_rx_cs: precalculated CS register value to clear RX FIFO + * (uses slave-specific clock polarity and phase settings) */ struct bcm2835_spi { void __iomem *regs; @@ -115,13 +132,22 @@ struct bcm2835_spi { int tx_prologue; int rx_prologue; unsigned int tx_spillover; - unsigned int dma_pending; + u32 prepare_cs[BCM2835_SPI_NUM_CS]; struct dentry *debugfs_dir; u64 count_transfer_polling; u64 count_transfer_irq; u64 count_transfer_irq_after_polling; u64 count_transfer_dma; + + u8 chip_select; + unsigned int tx_dma_active; + unsigned int rx_dma_active; + struct dma_async_tx_descriptor *fill_tx_desc; + dma_addr_t fill_tx_addr; + struct dma_async_tx_descriptor *clear_rx_desc[BCM2835_SPI_NUM_CS]; + dma_addr_t clear_rx_addr; + u32 clear_rx_cs[BCM2835_SPI_NUM_CS] ____cacheline_aligned; }; #if defined(CONFIG_DEBUG_FS) @@ -319,6 +345,13 @@ static void bcm2835_spi_reset_hw(struct spi_controller *ctlr) BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_DMAEN | BCM2835_SPI_CS_TA); + /* + * Transmission sometimes breaks unless the DONE bit is written at the + * end of every transfer. The spec says it's a RO bit. Either the + * spec is wrong and the bit is actually of type RW1C, or it's a + * hardware erratum. + */ + cs |= BCM2835_SPI_CS_DONE; /* and reset RX/TX FIFOS */ cs |= BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX; @@ -448,14 +481,14 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr, bs->rx_prologue = 0; bs->tx_spillover = false; - if (!sg_is_last(&tfr->tx_sg.sgl[0])) + if (bs->tx_buf && !sg_is_last(&tfr->tx_sg.sgl[0])) bs->tx_prologue = sg_dma_len(&tfr->tx_sg.sgl[0]) & 3; - if (!sg_is_last(&tfr->rx_sg.sgl[0])) { + if (bs->rx_buf && !sg_is_last(&tfr->rx_sg.sgl[0])) { bs->rx_prologue = sg_dma_len(&tfr->rx_sg.sgl[0]) & 3; if (bs->rx_prologue > bs->tx_prologue) { - if (sg_is_last(&tfr->tx_sg.sgl[0])) { + if (!bs->tx_buf || sg_is_last(&tfr->tx_sg.sgl[0])) { bs->tx_prologue = bs->rx_prologue; } else { bs->tx_prologue += 4; @@ -477,7 +510,9 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr, bcm2835_wr_fifo_count(bs, bs->rx_prologue); bcm2835_wait_tx_fifo_empty(bs); bcm2835_rd_fifo_count(bs, bs->rx_prologue); - bcm2835_spi_reset_hw(ctlr); + bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_RX + | BCM2835_SPI_CS_CLEAR_TX + | BCM2835_SPI_CS_DONE); dma_sync_single_for_device(ctlr->dma_rx->device->dev, sg_dma_address(&tfr->rx_sg.sgl[0]), @@ -487,6 +522,9 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr, sg_dma_len(&tfr->rx_sg.sgl[0]) -= bs->rx_prologue; } + if (!bs->tx_buf) + return; + /* * Write remaining TX prologue. Adjust first entry in TX sglist. * Also adjust second entry if prologue spills over to it. @@ -498,7 +536,8 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr, | BCM2835_SPI_CS_DMAEN); bcm2835_wr_fifo_count(bs, tx_remaining); bcm2835_wait_tx_fifo_empty(bs); - bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_TX); + bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_TX + | BCM2835_SPI_CS_DONE); } if (likely(!bs->tx_spillover)) { @@ -531,6 +570,9 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs) sg_dma_len(&tfr->rx_sg.sgl[0]) += bs->rx_prologue; } + if (!bs->tx_buf) + goto out; + if (likely(!bs->tx_spillover)) { sg_dma_address(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue; sg_dma_len(&tfr->tx_sg.sgl[0]) += bs->tx_prologue; @@ -539,32 +581,85 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs) sg_dma_address(&tfr->tx_sg.sgl[1]) -= 4; sg_dma_len(&tfr->tx_sg.sgl[1]) += 4; } +out: + bs->tx_prologue = 0; } -static void bcm2835_spi_dma_done(void *data) +/** + * bcm2835_spi_dma_rx_done() - callback for DMA RX channel + * @data: SPI master controller + * + * Used for bidirectional and RX-only transfers. + */ +static void bcm2835_spi_dma_rx_done(void *data) { struct spi_controller *ctlr = data; struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); - /* reset fifo and HW */ - bcm2835_spi_reset_hw(ctlr); - - /* and terminate tx-dma as we do not have an irq for it + /* terminate tx-dma as we do not have an irq for it * because when the rx dma will terminate and this callback * is called the tx-dma must have finished - can't get to this * situation otherwise... */ - if (cmpxchg(&bs->dma_pending, true, false)) { - dmaengine_terminate_async(ctlr->dma_tx); - bcm2835_spi_undo_prologue(bs); - } + dmaengine_terminate_async(ctlr->dma_tx); + bs->tx_dma_active = false; + bs->rx_dma_active = false; + bcm2835_spi_undo_prologue(bs); + + /* reset fifo and HW */ + bcm2835_spi_reset_hw(ctlr); /* and mark as completed */; complete(&ctlr->xfer_completion); } +/** + * bcm2835_spi_dma_tx_done() - callback for DMA TX channel + * @data: SPI master controller + * + * Used for TX-only transfers. + */ +static void bcm2835_spi_dma_tx_done(void *data) +{ + struct spi_controller *ctlr = data; + struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); + + /* busy-wait for TX FIFO to empty */ + while (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE)) + bcm2835_wr(bs, BCM2835_SPI_CS, + bs->clear_rx_cs[bs->chip_select]); + + bs->tx_dma_active = false; + smp_wmb(); + + /* + * In case of a very short transfer, RX DMA may not have been + * issued yet. The onus is then on bcm2835_spi_transfer_one_dma() + * to terminate it immediately after issuing. + */ + if (cmpxchg(&bs->rx_dma_active, true, false)) + dmaengine_terminate_async(ctlr->dma_rx); + + bcm2835_spi_undo_prologue(bs); + bcm2835_spi_reset_hw(ctlr); + complete(&ctlr->xfer_completion); +} + +/** + * bcm2835_spi_prepare_sg() - prepare and submit DMA descriptor for sglist + * @ctlr: SPI master controller + * @spi: SPI slave + * @tfr: SPI transfer + * @bs: BCM2835 SPI controller + * @is_tx: whether to submit DMA descriptor for TX or RX sglist + * + * Prepare and submit a DMA descriptor for the TX or RX sglist of @tfr. + * Return 0 on success or a negative error number. + */ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, + struct spi_device *spi, struct spi_transfer *tfr, + struct bcm2835_spi *bs, bool is_tx) { struct dma_chan *chan; @@ -581,8 +676,7 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, chan = ctlr->dma_tx; nents = tfr->tx_sg.nents; sgl = tfr->tx_sg.sgl; - flags = 0 /* no tx interrupt */; - + flags = tfr->rx_buf ? 0 : DMA_PREP_INTERRUPT; } else { dir = DMA_DEV_TO_MEM; chan = ctlr->dma_rx; @@ -595,10 +689,17 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, if (!desc) return -EINVAL; - /* set callback for rx */ + /* + * Completion is signaled by the RX channel for bidirectional and + * RX-only transfers; else by the TX channel for TX-only transfers. + */ if (!is_tx) { - desc->callback = bcm2835_spi_dma_done; + desc->callback = bcm2835_spi_dma_rx_done; desc->callback_param = ctlr; + } else if (!tfr->rx_buf) { + desc->callback = bcm2835_spi_dma_tx_done; + desc->callback_param = ctlr; + bs->chip_select = spi->chip_select; } /* submit it to DMA-engine */ @@ -607,12 +708,60 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, return dma_submit_error(cookie); } +/** + * bcm2835_spi_transfer_one_dma() - perform SPI transfer using DMA engine + * @ctlr: SPI master controller + * @spi: SPI slave + * @tfr: SPI transfer + * @cs: CS register + * + * For *bidirectional* transfers (both tx_buf and rx_buf are non-%NULL), set up + * the TX and RX DMA channel to copy between memory and FIFO register. + * + * For *TX-only* transfers (rx_buf is %NULL), copying the RX FIFO's contents to + * memory is pointless. However not reading the RX FIFO isn't an option either + * because transmission is halted once it's full. As a workaround, cyclically + * clear the RX FIFO by setting the CLEAR_RX bit in the CS register. + * + * The CS register value is precalculated in bcm2835_spi_setup(). Normally + * this is called only once, on slave registration. A DMA descriptor to write + * this value is preallocated in bcm2835_dma_init(). All that's left to do + * when performing a TX-only transfer is to submit this descriptor to the RX + * DMA channel. Latency is thereby minimized. The descriptor does not + * generate any interrupts while running. It must be terminated once the + * TX DMA channel is done. + * + * Clearing the RX FIFO is paced by the DREQ signal. The signal is asserted + * when the RX FIFO becomes half full, i.e. 32 bytes. (Tuneable with the DC + * register.) Reading 32 bytes from the RX FIFO would normally require 8 bus + * accesses, whereas clearing it requires only 1 bus access. So an 8-fold + * reduction in bus traffic and thus energy consumption is achieved. + * + * For *RX-only* transfers (tx_buf is %NULL), fill the TX FIFO by cyclically + * copying from the zero page. The DMA descriptor to do this is preallocated + * in bcm2835_dma_init(). It must be terminated once the RX DMA channel is + * done and can then be reused. + * + * The BCM2835 DMA driver autodetects when a transaction copies from the zero + * page and utilizes the DMA controller's ability to synthesize zeroes instead + * of copying them from memory. This reduces traffic on the memory bus. The + * feature is not available on so-called "lite" channels, but normally TX DMA + * is backed by a full-featured channel. + * + * Zero-filling the TX FIFO is paced by the DREQ signal. Unfortunately the + * BCM2835 SPI controller continues to assert DREQ even after the DLEN register + * has been counted down to zero (hardware erratum). Thus, when the transfer + * has finished, the DMA engine zero-fills the TX FIFO until it is half full. + * (Tuneable with the DC register.) So up to 9 gratuitous bus accesses are + * performed at the end of an RX-only transfer. + */ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, struct spi_device *spi, struct spi_transfer *tfr, u32 cs) { struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); + dma_cookie_t cookie; int ret; /* update usage statistics */ @@ -625,16 +774,15 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, bcm2835_spi_transfer_prologue(ctlr, tfr, bs, cs); /* setup tx-DMA */ - ret = bcm2835_spi_prepare_sg(ctlr, tfr, true); + if (bs->tx_buf) { + ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, true); + } else { + cookie = dmaengine_submit(bs->fill_tx_desc); + ret = dma_submit_error(cookie); + } if (ret) goto err_reset_hw; - /* start TX early */ - dma_async_issue_pending(ctlr->dma_tx); - - /* mark as dma pending */ - bs->dma_pending = 1; - /* set the DMA length */ bcm2835_wr(bs, BCM2835_SPI_DLEN, bs->tx_len); @@ -642,20 +790,43 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA | BCM2835_SPI_CS_DMAEN); + bs->tx_dma_active = true; + smp_wmb(); + + /* start TX early */ + dma_async_issue_pending(ctlr->dma_tx); + /* setup rx-DMA late - to run transfers while * mapping of the rx buffers still takes place * this saves 10us or more. */ - ret = bcm2835_spi_prepare_sg(ctlr, tfr, false); + if (bs->rx_buf) { + ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, false); + } else { + cookie = dmaengine_submit(bs->clear_rx_desc[spi->chip_select]); + ret = dma_submit_error(cookie); + } if (ret) { /* need to reset on errors */ dmaengine_terminate_sync(ctlr->dma_tx); - bs->dma_pending = false; + bs->tx_dma_active = false; goto err_reset_hw; } /* start rx dma late */ dma_async_issue_pending(ctlr->dma_rx); + bs->rx_dma_active = true; + smp_mb(); + + /* + * In case of a very short TX-only transfer, bcm2835_spi_dma_tx_done() + * may run before RX DMA is issued. Terminate RX DMA if so. + */ + if (!bs->rx_buf && !bs->tx_dma_active && + cmpxchg(&bs->rx_dma_active, true, false)) { + dmaengine_terminate_async(ctlr->dma_rx); + bcm2835_spi_reset_hw(ctlr); + } /* wait for wakeup in framework */ return 1; @@ -678,48 +849,83 @@ static bool bcm2835_spi_can_dma(struct spi_controller *ctlr, return true; } -static void bcm2835_dma_release(struct spi_controller *ctlr) +static void bcm2835_dma_release(struct spi_controller *ctlr, + struct bcm2835_spi *bs) { + int i; + if (ctlr->dma_tx) { dmaengine_terminate_sync(ctlr->dma_tx); + + if (bs->fill_tx_desc) + dmaengine_desc_free(bs->fill_tx_desc); + + if (bs->fill_tx_addr) + dma_unmap_page_attrs(ctlr->dma_tx->device->dev, + bs->fill_tx_addr, sizeof(u32), + DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + dma_release_channel(ctlr->dma_tx); ctlr->dma_tx = NULL; } + if (ctlr->dma_rx) { dmaengine_terminate_sync(ctlr->dma_rx); + + for (i = 0; i < BCM2835_SPI_NUM_CS; i++) + if (bs->clear_rx_desc[i]) + dmaengine_desc_free(bs->clear_rx_desc[i]); + + if (bs->clear_rx_addr) + dma_unmap_single(ctlr->dma_rx->device->dev, + bs->clear_rx_addr, + sizeof(bs->clear_rx_cs), + DMA_TO_DEVICE); + dma_release_channel(ctlr->dma_rx); ctlr->dma_rx = NULL; } } -static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev) +static int bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, + struct bcm2835_spi *bs) { struct dma_slave_config slave_config; const __be32 *addr; dma_addr_t dma_reg_base; - int ret; + int ret, i; /* base address in dma-space */ addr = of_get_address(ctlr->dev.of_node, 0, NULL, NULL); if (!addr) { dev_err(dev, "could not get DMA-register address - not using dma mode\n"); - goto err; + /* Fall back to interrupt mode */ + return 0; } dma_reg_base = be32_to_cpup(addr); /* get tx/rx dma */ - ctlr->dma_tx = dma_request_slave_channel(dev, "tx"); - if (!ctlr->dma_tx) { + ctlr->dma_tx = dma_request_chan(dev, "tx"); + if (IS_ERR(ctlr->dma_tx)) { dev_err(dev, "no tx-dma configuration found - not using dma mode\n"); + ret = PTR_ERR(ctlr->dma_tx); + ctlr->dma_tx = NULL; goto err; } - ctlr->dma_rx = dma_request_slave_channel(dev, "rx"); - if (!ctlr->dma_rx) { + ctlr->dma_rx = dma_request_chan(dev, "rx"); + if (IS_ERR(ctlr->dma_rx)) { dev_err(dev, "no rx-dma configuration found - not using dma mode\n"); + ret = PTR_ERR(ctlr->dma_rx); + ctlr->dma_rx = NULL; goto err_release; } - /* configure DMAs */ + /* + * The TX DMA channel either copies a transfer's TX buffer to the FIFO + * or, in case of an RX-only transfer, cyclically copies from the zero + * page to the FIFO using a preallocated, reusable descriptor. + */ slave_config.dst_addr = (u32)(dma_reg_base + BCM2835_SPI_FIFO); slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; @@ -727,27 +933,91 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev) if (ret) goto err_config; + bs->fill_tx_addr = dma_map_page_attrs(ctlr->dma_tx->device->dev, + ZERO_PAGE(0), 0, sizeof(u32), + DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + if (dma_mapping_error(ctlr->dma_tx->device->dev, bs->fill_tx_addr)) { + dev_err(dev, "cannot map zero page - not using DMA mode\n"); + bs->fill_tx_addr = 0; + goto err_release; + } + + bs->fill_tx_desc = dmaengine_prep_dma_cyclic(ctlr->dma_tx, + bs->fill_tx_addr, + sizeof(u32), 0, + DMA_MEM_TO_DEV, 0); + if (!bs->fill_tx_desc) { + dev_err(dev, "cannot prepare fill_tx_desc - not using DMA mode\n"); + goto err_release; + } + + ret = dmaengine_desc_set_reuse(bs->fill_tx_desc); + if (ret) { + dev_err(dev, "cannot reuse fill_tx_desc - not using DMA mode\n"); + goto err_release; + } + + /* + * The RX DMA channel is used bidirectionally: It either reads the + * RX FIFO or, in case of a TX-only transfer, cyclically writes a + * precalculated value to the CS register to clear the RX FIFO. + */ slave_config.src_addr = (u32)(dma_reg_base + BCM2835_SPI_FIFO); slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.dst_addr = (u32)(dma_reg_base + BCM2835_SPI_CS); + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ret = dmaengine_slave_config(ctlr->dma_rx, &slave_config); if (ret) goto err_config; + bs->clear_rx_addr = dma_map_single(ctlr->dma_rx->device->dev, + bs->clear_rx_cs, + sizeof(bs->clear_rx_cs), + DMA_TO_DEVICE); + if (dma_mapping_error(ctlr->dma_rx->device->dev, bs->clear_rx_addr)) { + dev_err(dev, "cannot map clear_rx_cs - not using DMA mode\n"); + bs->clear_rx_addr = 0; + goto err_release; + } + + for (i = 0; i < BCM2835_SPI_NUM_CS; i++) { + bs->clear_rx_desc[i] = dmaengine_prep_dma_cyclic(ctlr->dma_rx, + bs->clear_rx_addr + i * sizeof(u32), + sizeof(u32), 0, + DMA_MEM_TO_DEV, 0); + if (!bs->clear_rx_desc[i]) { + dev_err(dev, "cannot prepare clear_rx_desc - not using DMA mode\n"); + goto err_release; + } + + ret = dmaengine_desc_set_reuse(bs->clear_rx_desc[i]); + if (ret) { + dev_err(dev, "cannot reuse clear_rx_desc - not using DMA mode\n"); + goto err_release; + } + } + /* all went well, so set can_dma */ ctlr->can_dma = bcm2835_spi_can_dma; - /* need to do TX AND RX DMA, so we need dummy buffers */ - ctlr->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; - return; + return 0; err_config: dev_err(dev, "issue configuring dma: %d - not using DMA mode\n", ret); err_release: - bcm2835_dma_release(ctlr); + bcm2835_dma_release(ctlr, bs); err: - return; + /* + * Only report error for deferred probing, otherwise fall back to + * interrupt mode + */ + if (ret != -EPROBE_DEFER) + ret = 0; + + return ret; } static int bcm2835_spi_transfer_one_poll(struct spi_controller *ctlr, @@ -812,7 +1082,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); unsigned long spi_hz, clk_hz, cdiv, spi_used_hz; unsigned long hz_per_byte, byte_limit; - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); + u32 cs = bs->prepare_cs[spi->chip_select]; /* set clock */ spi_hz = tfr->speed_hz; @@ -834,18 +1104,8 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); /* handle all the 3-wire mode */ - if (spi->mode & SPI_3WIRE && tfr->rx_buf && - tfr->rx_buf != ctlr->dummy_rx) + if (spi->mode & SPI_3WIRE && tfr->rx_buf) cs |= BCM2835_SPI_CS_REN; - else - cs &= ~BCM2835_SPI_CS_REN; - - /* - * The driver always uses software-controlled GPIO Chip Select. - * Set the hardware-controlled native Chip Select to an invalid - * value to prevent it from interfering. - */ - cs |= BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; /* set transmit buffers and length */ bs->tx_buf = tfr->tx_buf; @@ -882,7 +1142,6 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr, { struct spi_device *spi = msg->spi; struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); - u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); int ret; if (ctlr->can_dma) { @@ -897,14 +1156,11 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr, return ret; } - cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA); - - if (spi->mode & SPI_CPOL) - cs |= BCM2835_SPI_CS_CPOL; - if (spi->mode & SPI_CPHA) - cs |= BCM2835_SPI_CS_CPHA; - - bcm2835_wr(bs, BCM2835_SPI_CS, cs); + /* + * Set up clock polarity before spi_transfer_one_message() asserts + * chip select to avoid a gratuitous clock signal edge. + */ + bcm2835_wr(bs, BCM2835_SPI_CS, bs->prepare_cs[spi->chip_select]); return 0; } @@ -915,11 +1171,12 @@ static void bcm2835_spi_handle_err(struct spi_controller *ctlr, struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); /* if an error occurred and we have an active dma, then terminate */ - if (cmpxchg(&bs->dma_pending, true, false)) { - dmaengine_terminate_sync(ctlr->dma_tx); - dmaengine_terminate_sync(ctlr->dma_rx); - bcm2835_spi_undo_prologue(bs); - } + dmaengine_terminate_sync(ctlr->dma_tx); + bs->tx_dma_active = false; + dmaengine_terminate_sync(ctlr->dma_rx); + bs->rx_dma_active = false; + bcm2835_spi_undo_prologue(bs); + /* and reset */ bcm2835_spi_reset_hw(ctlr); } @@ -931,14 +1188,50 @@ static int chip_match_name(struct gpio_chip *chip, void *data) static int bcm2835_spi_setup(struct spi_device *spi) { - int err; + struct spi_controller *ctlr = spi->controller; + struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); struct gpio_chip *chip; + enum gpio_lookup_flags lflags; + u32 cs; + + /* + * Precalculate SPI slave's CS register value for ->prepare_message(): + * The driver always uses software-controlled GPIO chip select, hence + * set the hardware-controlled native chip select to an invalid value + * to prevent it from interfering. + */ + cs = BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; + if (spi->mode & SPI_CPOL) + cs |= BCM2835_SPI_CS_CPOL; + if (spi->mode & SPI_CPHA) + cs |= BCM2835_SPI_CS_CPHA; + bs->prepare_cs[spi->chip_select] = cs; + + /* + * Precalculate SPI slave's CS register value to clear RX FIFO + * in case of a TX-only DMA transfer. + */ + if (ctlr->dma_rx) { + bs->clear_rx_cs[spi->chip_select] = cs | + BCM2835_SPI_CS_TA | + BCM2835_SPI_CS_DMAEN | + BCM2835_SPI_CS_CLEAR_RX; + dma_sync_single_for_device(ctlr->dma_rx->device->dev, + bs->clear_rx_addr, + sizeof(bs->clear_rx_cs), + DMA_TO_DEVICE); + } + /* * sanity checking the native-chipselects */ if (spi->mode & SPI_NO_CS) return 0; - if (gpio_is_valid(spi->cs_gpio)) + /* + * The SPI core has successfully requested the CS GPIO line from the + * device tree, so we are done. + */ + if (spi->cs_gpiod) return 0; if (spi->chip_select > 1) { /* error in the case of native CS requested with CS > 1 @@ -949,29 +1242,43 @@ static int bcm2835_spi_setup(struct spi_device *spi) "setup: only two native chip-selects are supported\n"); return -EINVAL; } - /* now translate native cs to GPIO */ + + /* + * Translate native CS to GPIO + * + * FIXME: poking around in the gpiolib internals like this is + * not very good practice. Find a way to locate the real problem + * and fix it. Why is the GPIO descriptor in spi->cs_gpiod + * sometimes not assigned correctly? Erroneous device trees? + */ /* get the gpio chip for the base */ chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); if (!chip) return 0; - /* and calculate the real CS */ - spi->cs_gpio = chip->base + 8 - spi->chip_select; + /* + * Retrieve the corresponding GPIO line used for CS. + * The inversion semantics will be handled by the GPIO core + * code, so we pass GPIOD_OUT_LOW for "unasserted" and + * the correct flag for inversion semantics. The SPI_CS_HIGH + * on spi->mode cannot be checked for polarity in this case + * as the flag use_gpio_descriptors enforces SPI_CS_HIGH. + */ + if (of_property_read_bool(spi->dev.of_node, "spi-cs-high")) + lflags = GPIO_ACTIVE_HIGH; + else + lflags = GPIO_ACTIVE_LOW; + spi->cs_gpiod = gpiochip_request_own_desc(chip, 8 - spi->chip_select, + DRV_NAME, + lflags, + GPIOD_OUT_LOW); + if (IS_ERR(spi->cs_gpiod)) + return PTR_ERR(spi->cs_gpiod); /* and set up the "mode" and level */ - dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", - spi->chip_select, spi->cs_gpio); - - /* set up GPIO as output and pull to the correct level */ - err = gpio_direction_output(spi->cs_gpio, - (spi->mode & SPI_CS_HIGH) ? 0 : 1); - if (err) { - dev_err(&spi->dev, - "could not set CS%i gpio %i as output: %i", - spi->chip_select, spi->cs_gpio, err); - return err; - } + dev_info(&spi->dev, "setting up native-CS%i to use GPIO\n", + spi->chip_select); return 0; } @@ -980,18 +1287,19 @@ static int bcm2835_spi_probe(struct platform_device *pdev) { struct spi_controller *ctlr; struct bcm2835_spi *bs; - struct resource *res; int err; - ctlr = spi_alloc_master(&pdev->dev, sizeof(*bs)); + ctlr = spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs), + dma_get_cache_alignment())); if (!ctlr) return -ENOMEM; platform_set_drvdata(pdev, ctlr); + ctlr->use_gpio_descriptors = true; ctlr->mode_bits = BCM2835_SPI_MODE_BITS; ctlr->bits_per_word_mask = SPI_BPW_MASK(8); - ctlr->num_chipselect = 3; + ctlr->num_chipselect = BCM2835_SPI_NUM_CS; ctlr->setup = bcm2835_spi_setup; ctlr->transfer_one = bcm2835_spi_transfer_one; ctlr->handle_err = bcm2835_spi_handle_err; @@ -1000,8 +1308,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) bs = spi_controller_get_devdata(ctlr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - bs->regs = devm_ioremap_resource(&pdev->dev, res); + bs->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(bs->regs)) { err = PTR_ERR(bs->regs); goto out_controller_put; @@ -1010,20 +1317,24 @@ static int bcm2835_spi_probe(struct platform_device *pdev) bs->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(bs->clk)) { err = PTR_ERR(bs->clk); - dev_err(&pdev->dev, "could not get clk: %d\n", err); + if (err == -EPROBE_DEFER) + dev_dbg(&pdev->dev, "could not get clk: %d\n", err); + else + dev_err(&pdev->dev, "could not get clk: %d\n", err); goto out_controller_put; } bs->irq = platform_get_irq(pdev, 0); if (bs->irq <= 0) { - dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq); err = bs->irq ? bs->irq : -ENODEV; goto out_controller_put; } clk_prepare_enable(bs->clk); - bcm2835_dma_init(ctlr, &pdev->dev); + err = bcm2835_dma_init(ctlr, &pdev->dev, bs); + if (err) + goto out_clk_disable; /* initialise the hardware with the default polarities */ bcm2835_wr(bs, BCM2835_SPI_CS, @@ -1033,20 +1344,22 @@ static int bcm2835_spi_probe(struct platform_device *pdev) dev_name(&pdev->dev), ctlr); if (err) { dev_err(&pdev->dev, "could not request IRQ: %d\n", err); - goto out_clk_disable; + goto out_dma_release; } err = devm_spi_register_controller(&pdev->dev, ctlr); if (err) { dev_err(&pdev->dev, "could not register SPI controller: %d\n", err); - goto out_clk_disable; + goto out_dma_release; } bcm2835_debugfs_create(bs, dev_name(&pdev->dev)); return 0; +out_dma_release: + bcm2835_dma_release(ctlr, bs); out_clk_disable: clk_disable_unprepare(bs->clk); out_controller_put: @@ -1067,7 +1380,7 @@ static int bcm2835_spi_remove(struct platform_device *pdev) clk_disable_unprepare(bs->clk); - bcm2835_dma_release(ctlr); + bcm2835_dma_release(ctlr, bs); return 0; } diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index bb57035c5770..a2162ff56a12 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -491,7 +491,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) { struct spi_master *master; struct bcm2835aux_spi *bs; - struct resource *res; unsigned long clk_hz; int err; @@ -524,8 +523,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) bs = spi_master_get_devdata(master); /* the main area */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - bs->regs = devm_ioremap_resource(&pdev->dev, res); + bs->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(bs->regs)) { err = PTR_ERR(bs->regs); goto out_master_put; @@ -540,7 +538,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) bs->irq = platform_get_irq(pdev, 0); if (bs->irq <= 0) { - dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq); err = bs->irq ? bs->irq : -ENODEV; goto out_master_put; } diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 9a06ffdb73b8..7327309ea3d5 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -291,8 +291,7 @@ static int bcm63xx_hsspi_transfer_one(struct spi_master *master, msg->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (t->cs_change) bcm63xx_hsspi_set_cs(bs, spi->chip_select, false); @@ -330,7 +329,6 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) { struct spi_master *master; struct bcm63xx_hsspi *bs; - struct resource *res_mem; void __iomem *regs; struct device *dev = &pdev->dev; struct clk *clk, *pll_clk = NULL; @@ -338,13 +336,10 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) u32 reg, rate, num_cs = HSSPI_SPI_MAX_CS; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "no irq: %d\n", irq); + if (irq < 0) return irq; - } - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(dev, res_mem); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index df1c94a131e6..0f1b10a4ef0c 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -368,7 +368,7 @@ static int bcm63xx_spi_transfer_one(struct spi_master *master, } /* CS will be deasserted directly after transfer */ - if (t->delay_usecs) { + if (t->delay_usecs || t->delay.value) { dev_err(&spi->dev, "unable to keep CS asserted after transfer\n"); status = -EINVAL; goto exit; @@ -520,10 +520,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "no irq: %d\n", irq); + if (irq < 0) return irq; - } clk = devm_clk_get(dev, "spi"); if (IS_ERR(clk)) { diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index d84e22dd6f9f..68491a8bf7b5 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -329,8 +329,20 @@ static void spi_bitbang_set_cs(struct spi_device *spi, bool enable) int spi_bitbang_init(struct spi_bitbang *bitbang) { struct spi_master *master = bitbang->master; + bool custom_cs; - if (!master || !bitbang->chipselect) + if (!master) + return -EINVAL; + /* + * We only need the chipselect callback if we are actually using it. + * If we just use GPIO descriptors, it is surplus. If the + * SPI_MASTER_GPIO_SS flag is set, we always need to call the + * driver-specific chipselect routine. + */ + custom_cs = (!master->use_gpio_descriptors || + (master->flags & SPI_MASTER_GPIO_SS)); + + if (custom_cs && !bitbang->chipselect) return -EINVAL; mutex_init(&bitbang->lock); @@ -344,7 +356,12 @@ int spi_bitbang_init(struct spi_bitbang *bitbang) master->prepare_transfer_hardware = spi_bitbang_prepare_hardware; master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware; master->transfer_one = spi_bitbang_transfer_one; - master->set_cs = spi_bitbang_set_cs; + /* + * When using GPIO descriptors, the ->set_cs() callback doesn't even + * get called unless SPI_MASTER_GPIO_SS is set. + */ + if (custom_cs) + master->set_cs = spi_bitbang_set_cs; if (!bitbang->txrx_bufs) { bitbang->use_dma = 0; diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c index 8c77d1114ad3..7e71a351f3b7 100644 --- a/drivers/spi/spi-butterfly.c +++ b/drivers/spi/spi-butterfly.c @@ -23,7 +23,7 @@ * with a battery powered AVR microcontroller and lots of goodies. You * can use GCC to develop firmware for this. * - * See Documentation/spi/butterfly for information about how to build + * See Documentation/spi/butterfly.rst for information about how to build * and use this custom parallel port cable. */ diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 7c41e4e82849..82a0ee09cbe1 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -168,16 +168,16 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi) /** * cdns_spi_chipselect - Select or deselect the chip select line * @spi: Pointer to the spi_device structure - * @enable: Select (1) or deselect (0) the chip select line + * @is_high: Select(0) or deselect (1) the chip select line */ -static void cdns_spi_chipselect(struct spi_device *spi, bool enable) +static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) { struct cdns_spi *xspi = spi_master_get_devdata(spi->master); u32 ctrl_reg; ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); - if (!enable) { + if (is_high) { /* Deselect the slave */ ctrl_reg |= CDNS_SPI_CR_SSCTRL; } else { @@ -474,7 +474,6 @@ static int cdns_spi_probe(struct platform_device *pdev) int ret = 0, irq; struct spi_master *master; struct cdns_spi *xspi; - struct resource *res; u32 num_cs; master = spi_alloc_master(&pdev->dev, sizeof(*xspi)); @@ -485,8 +484,7 @@ static int cdns_spi_probe(struct platform_device *pdev) master->dev.of_node = pdev->dev.of_node; platform_set_drvdata(pdev, master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - xspi->regs = devm_ioremap_resource(&pdev->dev, res); + xspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xspi->regs)) { ret = PTR_ERR(xspi->regs); goto remove_master; @@ -540,7 +538,6 @@ static int cdns_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { ret = -ENXIO; - dev_err(&pdev->dev, "irq number is invalid\n"); goto clk_dis_all; } diff --git a/drivers/spi/spi-cavium-octeon.c b/drivers/spi/spi-cavium-octeon.c index ee4703e84622..1a2de6ce9064 100644 --- a/drivers/spi/spi-cavium-octeon.c +++ b/drivers/spi/spi-cavium-octeon.c @@ -18,7 +18,6 @@ static int octeon_spi_probe(struct platform_device *pdev) { - struct resource *res_mem; void __iomem *reg_base; struct spi_master *master; struct octeon_spi *p; @@ -30,8 +29,7 @@ static int octeon_spi_probe(struct platform_device *pdev) p = spi_master_get_devdata(master); platform_set_drvdata(pdev, master); - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(&pdev->dev, res_mem); + reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) { err = PTR_ERR(reg_base); goto fail; diff --git a/drivers/spi/spi-cavium-thunderx.c b/drivers/spi/spi-cavium-thunderx.c index d12e149f1a41..fd6b9caffaf0 100644 --- a/drivers/spi/spi-cavium-thunderx.c +++ b/drivers/spi/spi-cavium-thunderx.c @@ -82,6 +82,7 @@ static int thunderx_spi_probe(struct pci_dev *pdev, error: clk_disable_unprepare(p->clk); + pci_release_regions(pdev); spi_master_put(master); return ret; } @@ -96,6 +97,7 @@ static void thunderx_spi_remove(struct pci_dev *pdev) return; clk_disable_unprepare(p->clk); + pci_release_regions(pdev); /* Put everything in a known state. */ writeq(0, p->register_base + OCTEON_SPI_CFG(p)); } diff --git a/drivers/spi/spi-cavium.c b/drivers/spi/spi-cavium.c index 5aaf21582cb5..6854c3ce423b 100644 --- a/drivers/spi/spi-cavium.c +++ b/drivers/spi/spi-cavium.c @@ -119,8 +119,7 @@ static int octeon_spi_do_transfer(struct octeon_spi *p, *rx_buf++ = (u8)v; } - if (xfer->delay_usecs) - udelay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); return xfer->len; } diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index 4daba12ec843..5e900f228919 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -91,7 +91,6 @@ static int spi_clps711x_probe(struct platform_device *pdev) { struct spi_clps711x_data *hw; struct spi_master *master; - struct resource *res; int irq, ret; irq = platform_get_irq(pdev, 0); @@ -125,8 +124,7 @@ static int spi_clps711x_probe(struct platform_device *pdev) goto err_out; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hw->syncio = devm_ioremap_resource(&pdev->dev, res); + hw->syncio = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hw->syncio)) { ret = PTR_ERR(hw->syncio); goto err_out; diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index 5ff48ab2f534..f80e06c87fbe 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -339,7 +339,6 @@ static int mcfqspi_probe(struct platform_device *pdev) { struct spi_master *master; struct mcfqspi *mcfqspi; - struct resource *res; struct mcfqspi_platform_data *pdata; int status; @@ -362,8 +361,7 @@ static int mcfqspi_probe(struct platform_device *pdev) mcfqspi = spi_master_get_devdata(master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mcfqspi->iobase = devm_ioremap_resource(&pdev->dev, res); + mcfqspi->iobase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mcfqspi->iobase)) { status = PTR_ERR(mcfqspi->iobase); goto fail0; diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index 2663bb12d9ce..0d86c37e0aeb 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -301,7 +301,7 @@ int dw_spi_mid_init(struct dw_spi *dws) void __iomem *clk_reg; u32 clk_cdiv; - clk_reg = ioremap_nocache(MRST_CLK_SPI_REG, 16); + clk_reg = ioremap(MRST_CLK_SPI_REG, 16); if (!clk_reg) return -ENOMEM; diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 18c06568805e..384a3ab6dc2d 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -9,6 +9,7 @@ #include <linux/err.h> #include <linux/interrupt.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/spi/spi.h> #include <linux/scatterlist.h> @@ -79,14 +80,12 @@ static int dw_spi_mscc_init(struct platform_device *pdev, const char *cpu_syscon, u32 if_si_owner_offset) { struct dw_spi_mscc *dwsmscc; - struct resource *res; dwsmscc = devm_kzalloc(&pdev->dev, sizeof(*dwsmscc), GFP_KERNEL); if (!dwsmscc) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - dwsmscc->spi_mst = devm_ioremap_resource(&pdev->dev, res); + 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); @@ -138,7 +137,6 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) struct dw_spi_mmio *dwsmmio); struct dw_spi_mmio *dwsmmio; struct dw_spi *dws; - struct resource *mem; int ret; int num_cs; @@ -150,18 +148,15 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) dws = &dwsmmio->dws; /* Get basic io resource and map it */ - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dws->regs = devm_ioremap_resource(&pdev->dev, mem); + 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 = platform_get_irq(pdev, 0); - if (dws->irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (dws->irq < 0) return dws->irq; /* -ENXIO */ - } dwsmmio->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dwsmmio->clk)) @@ -172,8 +167,10 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) /* Optional clock needed to access the registers */ dwsmmio->pclk = devm_clk_get_optional(&pdev->dev, "pclk"); - if (IS_ERR(dwsmmio->pclk)) - return PTR_ERR(dwsmmio->pclk); + if (IS_ERR(dwsmmio->pclk)) { + ret = PTR_ERR(dwsmmio->pclk); + goto out_clk; + } ret = clk_prepare_enable(dwsmmio->pclk); if (ret) goto out_clk; @@ -197,6 +194,8 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) goto out; } + pm_runtime_enable(&pdev->dev); + ret = dw_spi_add_host(&pdev->dev, dws); if (ret) goto out; @@ -205,6 +204,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) return 0; out: + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(dwsmmio->pclk); out_clk: clk_disable_unprepare(dwsmmio->clk); @@ -216,6 +216,7 @@ static int dw_spi_mmio_remove(struct platform_device *pdev) struct dw_spi_mmio *dwsmmio = platform_get_drvdata(pdev); dw_spi_remove_host(&dwsmmio->dws); + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(dwsmmio->pclk); clk_disable_unprepare(dwsmmio->clk); @@ -227,6 +228,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = { { .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 */} }; MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match); diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c index 9651679ee7f7..12c131b5fb4e 100644 --- a/drivers/spi/spi-dw-pci.c +++ b/drivers/spi/spi-dw-pci.c @@ -7,6 +7,7 @@ #include <linux/interrupt.h> #include <linux/pci.h> +#include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/spi/spi.h> #include <linux/module.h> @@ -19,6 +20,7 @@ struct spi_pci_desc { int (*setup)(struct dw_spi *); u16 num_cs; u16 bus_num; + u32 max_freq; }; static struct spi_pci_desc spi_pci_mid_desc_1 = { @@ -33,6 +35,12 @@ static struct spi_pci_desc spi_pci_mid_desc_2 = { .bus_num = 1, }; +static struct spi_pci_desc spi_pci_ehl_desc = { + .num_cs = 2, + .bus_num = -1, + .max_freq = 100000000, +}; + static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct dw_spi *dws; @@ -50,13 +58,18 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Get basic io resource and map it */ dws->paddr = pci_resource_start(pdev, pci_bar); + pci_set_master(pdev); ret = pcim_iomap_regions(pdev, 1 << pci_bar, pci_name(pdev)); if (ret) return ret; + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) + return ret; + dws->regs = pcim_iomap_table(pdev)[pci_bar]; - dws->irq = pdev->irq; + dws->irq = pci_irq_vector(pdev, 0); /* * Specific handling for platforms, like dma setup, @@ -65,6 +78,7 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (desc) { dws->num_cs = desc->num_cs; dws->bus_num = desc->bus_num; + dws->max_freq = desc->max_freq; if (desc->setup) { ret = desc->setup(dws); @@ -72,12 +86,15 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return ret; } } else { + pci_free_irq_vectors(pdev); return -ENODEV; } ret = dw_spi_add_host(&pdev->dev, dws); - if (ret) + if (ret) { + pci_free_irq_vectors(pdev); return ret; + } /* PCI hook and SPI hook use the same drv data */ pci_set_drvdata(pdev, dws); @@ -85,6 +102,11 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&pdev->dev, "found PCI SPI controller(ID: %04x:%04x)\n", pdev->vendor, pdev->device); + pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + pm_runtime_allow(&pdev->dev); + return 0; } @@ -92,22 +114,24 @@ static void spi_pci_remove(struct pci_dev *pdev) { struct dw_spi *dws = pci_get_drvdata(pdev); + pm_runtime_forbid(&pdev->dev); + pm_runtime_get_noresume(&pdev->dev); + dw_spi_remove_host(dws); + pci_free_irq_vectors(pdev); } #ifdef CONFIG_PM_SLEEP static int spi_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct dw_spi *dws = pci_get_drvdata(pdev); + struct dw_spi *dws = dev_get_drvdata(dev); return dw_spi_suspend_host(dws); } static int spi_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct dw_spi *dws = pci_get_drvdata(pdev); + struct dw_spi *dws = dev_get_drvdata(dev); return dw_spi_resume_host(dws); } @@ -125,8 +149,14 @@ static const struct pci_device_id pci_ids[] = { { PCI_VDEVICE(INTEL, 0x0800), (kernel_ulong_t)&spi_pci_mid_desc_1}, /* Intel MID platform SPI controller 2 */ { PCI_VDEVICE(INTEL, 0x0812), (kernel_ulong_t)&spi_pci_mid_desc_2}, + /* Intel Elkhart Lake PSE SPI controllers */ + { PCI_VDEVICE(INTEL, 0x4b84), (kernel_ulong_t)&spi_pci_ehl_desc}, + { PCI_VDEVICE(INTEL, 0x4b85), (kernel_ulong_t)&spi_pci_ehl_desc}, + { PCI_VDEVICE(INTEL, 0x4b86), (kernel_ulong_t)&spi_pci_ehl_desc}, + { PCI_VDEVICE(INTEL, 0x4b87), (kernel_ulong_t)&spi_pci_ehl_desc}, {}, }; +MODULE_DEVICE_TABLE(pci, pci_ids); static struct pci_driver dw_spi_driver = { .name = DRIVER_NAME, diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 9a49e073e8b7..31e3f866d11a 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -129,10 +129,11 @@ void dw_spi_set_cs(struct spi_device *spi, bool enable) struct dw_spi *dws = spi_controller_get_devdata(spi->controller); struct chip_data *chip = spi_get_ctldata(spi); + /* Chip select logic is inverted from spi_set_cs() */ if (chip && chip->cs_control) - chip->cs_control(enable); + chip->cs_control(!enable); - if (enable) + if (!enable) dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select)); else if (dws->cs_override) dw_writel(dws, DW_SPI_SER, 0); @@ -171,9 +172,11 @@ static inline u32 rx_max(struct dw_spi *dws) static void dw_writer(struct dw_spi *dws) { - u32 max = tx_max(dws); + u32 max; u16 txw = 0; + spin_lock(&dws->buf_lock); + max = tx_max(dws); while (max--) { /* Set the tx word if the transfer's original "tx" is not null */ if (dws->tx_end - dws->len) { @@ -185,13 +188,16 @@ static void dw_writer(struct dw_spi *dws) dw_write_io_reg(dws, DW_SPI_DR, txw); dws->tx += dws->n_bytes; } + spin_unlock(&dws->buf_lock); } static void dw_reader(struct dw_spi *dws) { - u32 max = rx_max(dws); + u32 max; u16 rxw; + spin_lock(&dws->buf_lock); + max = rx_max(dws); while (max--) { rxw = dw_read_io_reg(dws, DW_SPI_DR); /* Care rx only if the transfer's original "rx" is not null */ @@ -203,6 +209,7 @@ static void dw_reader(struct dw_spi *dws) } dws->rx += dws->n_bytes; } + spin_unlock(&dws->buf_lock); } static void int_error_stop(struct dw_spi *dws, const char *msg) @@ -275,18 +282,23 @@ static int dw_spi_transfer_one(struct spi_controller *master, { struct dw_spi *dws = spi_controller_get_devdata(master); struct chip_data *chip = spi_get_ctldata(spi); + unsigned long flags; u8 imask = 0; u16 txlevel = 0; u32 cr0; int ret; dws->dma_mapped = 0; - + spin_lock_irqsave(&dws->buf_lock, flags); dws->tx = (void *)transfer->tx_buf; dws->tx_end = dws->tx + transfer->len; dws->rx = transfer->rx_buf; dws->rx_end = dws->rx + transfer->len; dws->len = transfer->len; + spin_unlock_irqrestore(&dws->buf_lock, flags); + + /* Ensure dw->rx and dw->rx_end are visible */ + smp_mb(); spi_enable_chip(dws, 0); @@ -308,7 +320,8 @@ static int dw_spi_transfer_one(struct spi_controller *master, cr0 = (transfer->bits_per_word - 1) | (chip->type << SPI_FRF_OFFSET) | ((((spi->mode & SPI_CPOL) ? 1 : 0) << SPI_SCOL_OFFSET) | - (((spi->mode & SPI_CPHA) ? 1 : 0) << SPI_SCPH_OFFSET)) + (((spi->mode & SPI_CPHA) ? 1 : 0) << SPI_SCPH_OFFSET) | + (((spi->mode & SPI_LOOP) ? 1 : 0) << SPI_SRL_OFFSET)) | (chip->tmode << SPI_TMOD_OFFSET); /* @@ -459,7 +472,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) struct spi_controller *master; int ret; - BUG_ON(dws == NULL); + if (!dws) + return -EINVAL; master = spi_alloc_master(dev, 0); if (!master) @@ -469,6 +483,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) dws->type = SSI_MOTO_SPI; dws->dma_inited = 0; dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR); + spin_lock_init(&dws->buf_lock); spi_controller_set_devdata(master, dws); @@ -493,6 +508,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) master->dev.of_node = dev->of_node; master->dev.fwnode = dev->fwnode; master->flags = SPI_MASTER_GPIO_SS; + master->auto_runtime_pm = true; if (dws->set_cs) master->set_cs = dws->set_cs; diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index c9c15881e982..1bf5713e047d 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -4,7 +4,6 @@ #include <linux/io.h> #include <linux/scatterlist.h> -#include <linux/gpio.h> /* Register offsets */ #define DW_SPI_CTRL0 0x00 @@ -120,6 +119,7 @@ struct dw_spi { size_t len; void *tx; void *tx_end; + spinlock_t buf_lock; void *rx; void *rx_end; int dma_mapped; diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c index eb1f2142a335..64d4c441b641 100644 --- a/drivers/spi/spi-efm32.c +++ b/drivers/spi/spi-efm32.c @@ -400,10 +400,8 @@ static int efm32_spi_probe(struct platform_device *pdev) } ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - dev_err(&pdev->dev, "failed to get rx irq (%d)\n", ret); + if (ret <= 0) goto err; - } ddata->rxirq = ret; diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 4034e3ec0ba2..4e1ccd4e52b6 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -656,10 +656,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq resources\n"); + if (irq < 0) return -EBUSY; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c index 00f46c816a56..d3336a63f462 100644 --- a/drivers/spi/spi-falcon.c +++ b/drivers/spi/spi-falcon.c @@ -377,7 +377,7 @@ static int falcon_sflash_xfer_one(struct spi_master *master, m->actual_length += t->len; - WARN_ON(t->delay_usecs || t->cs_change); + WARN_ON(t->delay_usecs || t->delay.value || t->cs_change); spi_flags = 0; } diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c index e967ac564761..54ad0ac121e5 100644 --- a/drivers/spi/spi-fsl-cpm.c +++ b/drivers/spi/spi-fsl-cpm.c @@ -305,12 +305,10 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) } if (mspi->flags & SPI_CPM1) { - struct resource *res; void *pram; - res = platform_get_resource(to_platform_device(dev), - IORESOURCE_MEM, 1); - pram = devm_ioremap_resource(dev, res); + pram = devm_platform_ioremap_resource(to_platform_device(dev), + 1); if (IS_ERR(pram)) mspi->pram = NULL; else @@ -394,7 +392,8 @@ void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi) dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE); dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE); cpm_muram_free(cpm_muram_offset(mspi->tx_bd)); - cpm_muram_free(cpm_muram_offset(mspi->pram)); + if (!(mspi->flags & SPI_CPM1)) + cpm_muram_free(cpm_muram_offset(mspi->pram)); fsl_spi_free_dummy_rx(); } EXPORT_SYMBOL_GPL(fsl_spi_cpm_free); diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 53335ccc98f6..6ec2dcb8c57a 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -9,26 +9,16 @@ #include <linux/delay.h> #include <linux/dmaengine.h> #include <linux/dma-mapping.h> -#include <linux/err.h> -#include <linux/errno.h> #include <linux/interrupt.h> -#include <linux/io.h> #include <linux/kernel.h> -#include <linux/math64.h> #include <linux/module.h> -#include <linux/of.h> #include <linux/of_device.h> #include <linux/pinctrl/consumer.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> #include <linux/regmap.h> -#include <linux/sched.h> #include <linux/spi/spi.h> #include <linux/spi/spi-fsl-dspi.h> -#include <linux/spi/spi_bitbang.h> -#include <linux/time.h> -#define DRIVER_NAME "fsl-dspi" +#define DRIVER_NAME "fsl-dspi" #ifdef CONFIG_M5441x #define DSPI_FIFO_SIZE 16 @@ -37,101 +27,97 @@ #endif #define DSPI_DMA_BUFSIZE (DSPI_FIFO_SIZE * 1024) -#define SPI_MCR 0x00 -#define SPI_MCR_MASTER (1 << 31) -#define SPI_MCR_PCSIS (0x3F << 16) -#define SPI_MCR_CLR_TXF (1 << 11) -#define SPI_MCR_CLR_RXF (1 << 10) -#define SPI_MCR_XSPI (1 << 3) - -#define SPI_TCR 0x08 -#define SPI_TCR_GET_TCNT(x) (((x) & 0xffff0000) >> 16) - -#define SPI_CTAR(x) (0x0c + (((x) & 0x3) * 4)) -#define SPI_CTAR_FMSZ(x) (((x) & 0x0000000f) << 27) -#define SPI_CTAR_CPOL(x) ((x) << 26) -#define SPI_CTAR_CPHA(x) ((x) << 25) -#define SPI_CTAR_LSBFE(x) ((x) << 24) -#define SPI_CTAR_PCSSCK(x) (((x) & 0x00000003) << 22) -#define SPI_CTAR_PASC(x) (((x) & 0x00000003) << 20) -#define SPI_CTAR_PDT(x) (((x) & 0x00000003) << 18) -#define SPI_CTAR_PBR(x) (((x) & 0x00000003) << 16) -#define SPI_CTAR_CSSCK(x) (((x) & 0x0000000f) << 12) -#define SPI_CTAR_ASC(x) (((x) & 0x0000000f) << 8) -#define SPI_CTAR_DT(x) (((x) & 0x0000000f) << 4) -#define SPI_CTAR_BR(x) ((x) & 0x0000000f) -#define SPI_CTAR_SCALE_BITS 0xf - -#define SPI_CTAR0_SLAVE 0x0c - -#define SPI_SR 0x2c -#define SPI_SR_EOQF 0x10000000 -#define SPI_SR_TCFQF 0x80000000 -#define SPI_SR_CLEAR 0x9aaf0000 - -#define SPI_RSER_TFFFE BIT(25) -#define SPI_RSER_TFFFD BIT(24) -#define SPI_RSER_RFDFE BIT(17) -#define SPI_RSER_RFDFD BIT(16) - -#define SPI_RSER 0x30 -#define SPI_RSER_EOQFE 0x10000000 -#define SPI_RSER_TCFQE 0x80000000 - -#define SPI_PUSHR 0x34 -#define SPI_PUSHR_CMD_CONT (1 << 15) -#define SPI_PUSHR_CONT (SPI_PUSHR_CMD_CONT << 16) -#define SPI_PUSHR_CMD_CTAS(x) (((x) & 0x0003) << 12) -#define SPI_PUSHR_CTAS(x) (SPI_PUSHR_CMD_CTAS(x) << 16) -#define SPI_PUSHR_CMD_EOQ (1 << 11) -#define SPI_PUSHR_EOQ (SPI_PUSHR_CMD_EOQ << 16) -#define SPI_PUSHR_CMD_CTCNT (1 << 10) -#define SPI_PUSHR_CTCNT (SPI_PUSHR_CMD_CTCNT << 16) -#define SPI_PUSHR_CMD_PCS(x) ((1 << x) & 0x003f) -#define SPI_PUSHR_PCS(x) (SPI_PUSHR_CMD_PCS(x) << 16) -#define SPI_PUSHR_TXDATA(x) ((x) & 0x0000ffff) - -#define SPI_PUSHR_SLAVE 0x34 - -#define SPI_POPR 0x38 -#define SPI_POPR_RXDATA(x) ((x) & 0x0000ffff) - -#define SPI_TXFR0 0x3c -#define SPI_TXFR1 0x40 -#define SPI_TXFR2 0x44 -#define SPI_TXFR3 0x48 -#define SPI_RXFR0 0x7c -#define SPI_RXFR1 0x80 -#define SPI_RXFR2 0x84 -#define SPI_RXFR3 0x88 - -#define SPI_CTARE(x) (0x11c + (((x) & 0x3) * 4)) -#define SPI_CTARE_FMSZE(x) (((x) & 0x1) << 16) -#define SPI_CTARE_DTCP(x) ((x) & 0x7ff) - -#define SPI_SREX 0x13c - -#define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1) -#define SPI_FRAME_BITS_MASK SPI_CTAR_FMSZ(0xf) -#define SPI_FRAME_BITS_16 SPI_CTAR_FMSZ(0xf) -#define SPI_FRAME_BITS_8 SPI_CTAR_FMSZ(0x7) - -#define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4) -#define SPI_FRAME_EBITS_MASK SPI_CTARE_FMSZE(1) +#define SPI_MCR 0x00 +#define SPI_MCR_MASTER BIT(31) +#define SPI_MCR_PCSIS (0x3F << 16) +#define SPI_MCR_CLR_TXF BIT(11) +#define SPI_MCR_CLR_RXF BIT(10) +#define SPI_MCR_XSPI BIT(3) + +#define SPI_TCR 0x08 +#define SPI_TCR_GET_TCNT(x) (((x) & GENMASK(31, 16)) >> 16) + +#define SPI_CTAR(x) (0x0c + (((x) & GENMASK(1, 0)) * 4)) +#define SPI_CTAR_FMSZ(x) (((x) << 27) & GENMASK(30, 27)) +#define SPI_CTAR_CPOL BIT(26) +#define SPI_CTAR_CPHA BIT(25) +#define SPI_CTAR_LSBFE BIT(24) +#define SPI_CTAR_PCSSCK(x) (((x) << 22) & GENMASK(23, 22)) +#define SPI_CTAR_PASC(x) (((x) << 20) & GENMASK(21, 20)) +#define SPI_CTAR_PDT(x) (((x) << 18) & GENMASK(19, 18)) +#define SPI_CTAR_PBR(x) (((x) << 16) & GENMASK(17, 16)) +#define SPI_CTAR_CSSCK(x) (((x) << 12) & GENMASK(15, 12)) +#define SPI_CTAR_ASC(x) (((x) << 8) & GENMASK(11, 8)) +#define SPI_CTAR_DT(x) (((x) << 4) & GENMASK(7, 4)) +#define SPI_CTAR_BR(x) ((x) & GENMASK(3, 0)) +#define SPI_CTAR_SCALE_BITS 0xf + +#define SPI_CTAR0_SLAVE 0x0c + +#define SPI_SR 0x2c +#define SPI_SR_TCFQF BIT(31) +#define SPI_SR_EOQF BIT(28) +#define SPI_SR_TFUF BIT(27) +#define SPI_SR_TFFF BIT(25) +#define SPI_SR_CMDTCF BIT(23) +#define SPI_SR_SPEF BIT(21) +#define SPI_SR_RFOF BIT(19) +#define SPI_SR_TFIWF BIT(18) +#define SPI_SR_RFDF BIT(17) +#define SPI_SR_CMDFFF BIT(16) +#define SPI_SR_CLEAR (SPI_SR_TCFQF | SPI_SR_EOQF | \ + SPI_SR_TFUF | SPI_SR_TFFF | \ + SPI_SR_CMDTCF | SPI_SR_SPEF | \ + SPI_SR_RFOF | SPI_SR_TFIWF | \ + SPI_SR_RFDF | SPI_SR_CMDFFF) + +#define SPI_RSER_TFFFE BIT(25) +#define SPI_RSER_TFFFD BIT(24) +#define SPI_RSER_RFDFE BIT(17) +#define SPI_RSER_RFDFD BIT(16) + +#define SPI_RSER 0x30 +#define SPI_RSER_TCFQE BIT(31) +#define SPI_RSER_EOQFE BIT(28) + +#define SPI_PUSHR 0x34 +#define SPI_PUSHR_CMD_CONT BIT(15) +#define SPI_PUSHR_CMD_CTAS(x) (((x) << 12 & GENMASK(14, 12))) +#define SPI_PUSHR_CMD_EOQ BIT(11) +#define SPI_PUSHR_CMD_CTCNT BIT(10) +#define SPI_PUSHR_CMD_PCS(x) (BIT(x) & GENMASK(5, 0)) + +#define SPI_PUSHR_SLAVE 0x34 + +#define SPI_POPR 0x38 + +#define SPI_TXFR0 0x3c +#define SPI_TXFR1 0x40 +#define SPI_TXFR2 0x44 +#define SPI_TXFR3 0x48 +#define SPI_RXFR0 0x7c +#define SPI_RXFR1 0x80 +#define SPI_RXFR2 0x84 +#define SPI_RXFR3 0x88 + +#define SPI_CTARE(x) (0x11c + (((x) & GENMASK(1, 0)) * 4)) +#define SPI_CTARE_FMSZE(x) (((x) & 0x1) << 16) +#define SPI_CTARE_DTCP(x) ((x) & 0x7ff) + +#define SPI_SREX 0x13c + +#define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1) +#define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4) /* Register offsets for regmap_pushr */ -#define PUSHR_CMD 0x0 -#define PUSHR_TX 0x2 +#define PUSHR_CMD 0x0 +#define PUSHR_TX 0x2 -#define SPI_CS_INIT 0x01 -#define SPI_CS_ASSERT 0x02 -#define SPI_CS_DROP 0x04 - -#define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000) +#define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000) struct chip_data { - u32 ctar_val; - u16 void_write_data; + u32 ctar_val; + u16 void_write_data; }; enum dspi_trans_mode { @@ -141,75 +127,79 @@ enum dspi_trans_mode { }; struct fsl_dspi_devtype_data { - enum dspi_trans_mode trans_mode; - u8 max_clock_factor; - bool xspi_mode; + enum dspi_trans_mode trans_mode; + u8 max_clock_factor; + bool ptp_sts_supported; + bool xspi_mode; }; static const struct fsl_dspi_devtype_data vf610_data = { - .trans_mode = DSPI_DMA_MODE, - .max_clock_factor = 2, + .trans_mode = DSPI_DMA_MODE, + .max_clock_factor = 2, }; static const struct fsl_dspi_devtype_data ls1021a_v1_data = { - .trans_mode = DSPI_TCFQ_MODE, - .max_clock_factor = 8, - .xspi_mode = true, + .trans_mode = DSPI_TCFQ_MODE, + .max_clock_factor = 8, + .ptp_sts_supported = true, + .xspi_mode = true, }; static const struct fsl_dspi_devtype_data ls2085a_data = { - .trans_mode = DSPI_TCFQ_MODE, - .max_clock_factor = 8, + .trans_mode = DSPI_TCFQ_MODE, + .max_clock_factor = 8, + .ptp_sts_supported = true, }; static const struct fsl_dspi_devtype_data coldfire_data = { - .trans_mode = DSPI_EOQ_MODE, - .max_clock_factor = 8, + .trans_mode = DSPI_EOQ_MODE, + .max_clock_factor = 8, }; struct fsl_dspi_dma { /* Length of transfer in words of DSPI_FIFO_SIZE */ - u32 curr_xfer_len; - - u32 *tx_dma_buf; - struct dma_chan *chan_tx; - dma_addr_t tx_dma_phys; - struct completion cmd_tx_complete; - struct dma_async_tx_descriptor *tx_desc; - - u32 *rx_dma_buf; - struct dma_chan *chan_rx; - dma_addr_t rx_dma_phys; - struct completion cmd_rx_complete; - struct dma_async_tx_descriptor *rx_desc; + u32 curr_xfer_len; + + u32 *tx_dma_buf; + struct dma_chan *chan_tx; + dma_addr_t tx_dma_phys; + struct completion cmd_tx_complete; + struct dma_async_tx_descriptor *tx_desc; + + u32 *rx_dma_buf; + struct dma_chan *chan_rx; + dma_addr_t rx_dma_phys; + struct completion cmd_rx_complete; + struct dma_async_tx_descriptor *rx_desc; }; struct fsl_dspi { - struct spi_master *master; - struct platform_device *pdev; - - struct regmap *regmap; - struct regmap *regmap_pushr; - int irq; - struct clk *clk; - - struct spi_transfer *cur_transfer; - struct spi_message *cur_msg; - struct chip_data *cur_chip; - size_t len; - const void *tx; - void *rx; - void *rx_end; - u16 void_write_data; - u16 tx_cmd; - u8 bits_per_word; - u8 bytes_per_word; - const struct fsl_dspi_devtype_data *devtype_data; - - wait_queue_head_t waitq; - u32 waitflags; - - struct fsl_dspi_dma *dma; + struct spi_controller *ctlr; + struct platform_device *pdev; + + struct regmap *regmap; + struct regmap *regmap_pushr; + int irq; + struct clk *clk; + + struct spi_transfer *cur_transfer; + struct spi_message *cur_msg; + struct chip_data *cur_chip; + size_t progress; + size_t len; + const void *tx; + void *rx; + void *rx_end; + u16 void_write_data; + u16 tx_cmd; + u8 bits_per_word; + u8 bytes_per_word; + const struct fsl_dspi_devtype_data *devtype_data; + + wait_queue_head_t waitq; + u32 waitflags; + + struct fsl_dspi_dma *dma; }; static u32 dspi_pop_tx(struct fsl_dspi *dspi) @@ -233,7 +223,7 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi) { u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi); - if (spi_controller_is_slave(dspi->master)) + if (spi_controller_is_slave(dspi->ctlr)) return data; if (dspi->len > 0) @@ -246,7 +236,7 @@ static void dspi_push_rx(struct fsl_dspi *dspi, u32 rxdata) if (!dspi->rx) return; - /* Mask of undefined bits */ + /* Mask off undefined bits */ rxdata &= (1 << dspi->bits_per_word) - 1; if (dspi->bytes_per_word == 1) @@ -282,8 +272,8 @@ static void dspi_rx_dma_callback(void *arg) static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) { - struct fsl_dspi_dma *dma = dspi->dma; struct device *dev = &dspi->pdev->dev; + struct fsl_dspi_dma *dma = dspi->dma; int time_left; int i; @@ -332,13 +322,13 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) dma_async_issue_pending(dma->chan_rx); dma_async_issue_pending(dma->chan_tx); - if (spi_controller_is_slave(dspi->master)) { + if (spi_controller_is_slave(dspi->ctlr)) { wait_for_completion_interruptible(&dspi->dma->cmd_rx_complete); return 0; } time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete, - DMA_COMPLETION_TIMEOUT); + DMA_COMPLETION_TIMEOUT); if (time_left == 0) { dev_err(dev, "DMA tx timeout\n"); dmaengine_terminate_all(dma->chan_tx); @@ -347,7 +337,7 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) } time_left = wait_for_completion_timeout(&dspi->dma->cmd_rx_complete, - DMA_COMPLETION_TIMEOUT); + DMA_COMPLETION_TIMEOUT); if (time_left == 0) { dev_err(dev, "DMA rx timeout\n"); dmaengine_terminate_all(dma->chan_tx); @@ -360,9 +350,9 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) static int dspi_dma_xfer(struct fsl_dspi *dspi) { - struct fsl_dspi_dma *dma = dspi->dma; - struct device *dev = &dspi->pdev->dev; struct spi_message *message = dspi->cur_msg; + struct device *dev = &dspi->pdev->dev; + struct fsl_dspi_dma *dma = dspi->dma; int curr_remaining_bytes; int bytes_per_buffer; int ret = 0; @@ -397,38 +387,38 @@ exit: static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr) { - struct fsl_dspi_dma *dma; - struct dma_slave_config cfg; struct device *dev = &dspi->pdev->dev; + struct dma_slave_config cfg; + struct fsl_dspi_dma *dma; int ret; dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); if (!dma) return -ENOMEM; - dma->chan_rx = dma_request_slave_channel(dev, "rx"); - if (!dma->chan_rx) { + dma->chan_rx = dma_request_chan(dev, "rx"); + if (IS_ERR(dma->chan_rx)) { dev_err(dev, "rx dma channel not available\n"); - ret = -ENODEV; + ret = PTR_ERR(dma->chan_rx); return ret; } - dma->chan_tx = dma_request_slave_channel(dev, "tx"); - if (!dma->chan_tx) { + dma->chan_tx = dma_request_chan(dev, "tx"); + if (IS_ERR(dma->chan_tx)) { dev_err(dev, "tx dma channel not available\n"); - ret = -ENODEV; + ret = PTR_ERR(dma->chan_tx); goto err_tx_channel; } dma->tx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE, - &dma->tx_dma_phys, GFP_KERNEL); + &dma->tx_dma_phys, GFP_KERNEL); if (!dma->tx_dma_buf) { ret = -ENOMEM; goto err_tx_dma_buf; } dma->rx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE, - &dma->rx_dma_phys, GFP_KERNEL); + &dma->rx_dma_phys, GFP_KERNEL); if (!dma->rx_dma_buf) { ret = -ENOMEM; goto err_rx_dma_buf; @@ -485,30 +475,31 @@ static void dspi_release_dma(struct fsl_dspi *dspi) struct fsl_dspi_dma *dma = dspi->dma; struct device *dev = &dspi->pdev->dev; - if (dma) { - if (dma->chan_tx) { - dma_unmap_single(dev, dma->tx_dma_phys, - DSPI_DMA_BUFSIZE, DMA_TO_DEVICE); - dma_release_channel(dma->chan_tx); - } + if (!dma) + return; - if (dma->chan_rx) { - dma_unmap_single(dev, dma->rx_dma_phys, - DSPI_DMA_BUFSIZE, DMA_FROM_DEVICE); - dma_release_channel(dma->chan_rx); - } + if (dma->chan_tx) { + dma_unmap_single(dev, dma->tx_dma_phys, + DSPI_DMA_BUFSIZE, DMA_TO_DEVICE); + dma_release_channel(dma->chan_tx); + } + + if (dma->chan_rx) { + dma_unmap_single(dev, dma->rx_dma_phys, + DSPI_DMA_BUFSIZE, DMA_FROM_DEVICE); + dma_release_channel(dma->chan_rx); } } static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, - unsigned long clkrate) + unsigned long clkrate) { /* Valid baud rate pre-scaler values */ int pbr_tbl[4] = {2, 3, 5, 7}; int brs[16] = { 2, 4, 6, 8, - 16, 32, 64, 128, - 256, 512, 1024, 2048, - 4096, 8192, 16384, 32768 }; + 16, 32, 64, 128, + 256, 512, 1024, 2048, + 4096, 8192, 16384, 32768 }; int scale_needed, scale, minscale = INT_MAX; int i, j; @@ -538,15 +529,15 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, } static void ns_delay_scale(char *psc, char *sc, int delay_ns, - unsigned long clkrate) + unsigned long clkrate) { - int pscale_tbl[4] = {1, 3, 5, 7}; int scale_needed, scale, minscale = INT_MAX; - int i, j; + int pscale_tbl[4] = {1, 3, 5, 7}; u32 remainder; + int i, j; scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC, - &remainder); + &remainder); if (remainder) scale_needed++; @@ -596,21 +587,14 @@ static void dspi_tcfq_write(struct fsl_dspi *dspi) dspi->tx_cmd |= SPI_PUSHR_CMD_CTCNT; if (dspi->devtype_data->xspi_mode && dspi->bits_per_word > 16) { - /* Write two TX FIFO entries first, and then the corresponding - * CMD FIFO entry. + /* Write the CMD FIFO entry first, and then the two + * corresponding TX FIFO entries. */ u32 data = dspi_pop_tx(dspi); - if (dspi->cur_chip->ctar_val & SPI_CTAR_LSBFE(1)) { - /* LSB */ - tx_fifo_write(dspi, data & 0xFFFF); - tx_fifo_write(dspi, data >> 16); - } else { - /* MSB */ - tx_fifo_write(dspi, data >> 16); - tx_fifo_write(dspi, data & 0xFFFF); - } cmd_fifo_write(dspi); + tx_fifo_write(dspi, data & 0xFFFF); + tx_fifo_write(dspi, data >> 16); } else { /* Write one entry to both TX FIFO and CMD FIFO * simultaneously. @@ -655,19 +639,97 @@ static void dspi_eoq_read(struct fsl_dspi *dspi) { int fifo_size = DSPI_FIFO_SIZE; - /* Read one FIFO entry at and push to rx buffer */ + /* Read one FIFO entry and push to rx buffer */ while ((dspi->rx < dspi->rx_end) && fifo_size--) dspi_push_rx(dspi, fifo_read(dspi)); } -static int dspi_transfer_one_message(struct spi_master *master, - struct spi_message *message) +static int dspi_rxtx(struct fsl_dspi *dspi) { - struct fsl_dspi *dspi = spi_master_get_devdata(master); + struct spi_message *msg = dspi->cur_msg; + enum dspi_trans_mode trans_mode; + u16 spi_tcnt; + u32 spi_tcr; + + spi_take_timestamp_post(dspi->ctlr, dspi->cur_transfer, + dspi->progress, !dspi->irq); + + /* Get transfer counter (in number of SPI transfers). It was + * reset to 0 when transfer(s) were started. + */ + regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); + spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); + /* Update total number of bytes that were transferred */ + msg->actual_length += spi_tcnt * dspi->bytes_per_word; + dspi->progress += spi_tcnt; + + trans_mode = dspi->devtype_data->trans_mode; + if (trans_mode == DSPI_EOQ_MODE) + dspi_eoq_read(dspi); + else if (trans_mode == DSPI_TCFQ_MODE) + dspi_tcfq_read(dspi); + + if (!dspi->len) + /* Success! */ + return 0; + + spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer, + dspi->progress, !dspi->irq); + + if (trans_mode == DSPI_EOQ_MODE) + dspi_eoq_write(dspi); + else if (trans_mode == DSPI_TCFQ_MODE) + dspi_tcfq_write(dspi); + + return -EINPROGRESS; +} + +static int dspi_poll(struct fsl_dspi *dspi) +{ + int tries = 1000; + u32 spi_sr; + + do { + regmap_read(dspi->regmap, SPI_SR, &spi_sr); + regmap_write(dspi->regmap, SPI_SR, spi_sr); + + if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) + break; + } while (--tries); + + if (!tries) + return -ETIMEDOUT; + + return dspi_rxtx(dspi); +} + +static irqreturn_t dspi_interrupt(int irq, void *dev_id) +{ + struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; + u32 spi_sr; + + regmap_read(dspi->regmap, SPI_SR, &spi_sr); + regmap_write(dspi->regmap, SPI_SR, spi_sr); + + if (!(spi_sr & SPI_SR_EOQF)) + return IRQ_NONE; + + if (dspi_rxtx(dspi) == 0) { + dspi->waitflags = 1; + wake_up_interruptible(&dspi->waitq); + } + + return IRQ_HANDLED; +} + +static int dspi_transfer_one_message(struct spi_controller *ctlr, + struct spi_message *message) +{ + struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr); struct spi_device *spi = message->spi; + enum dspi_trans_mode trans_mode; struct spi_transfer *transfer; int status = 0; - enum dspi_trans_mode trans_mode; message->actual_length = 0; @@ -677,7 +739,7 @@ static int dspi_transfer_one_message(struct spi_master *master, dspi->cur_chip = spi_get_ctldata(spi); /* Prepare command word for CMD FIFO */ dspi->tx_cmd = SPI_PUSHR_CMD_CTAS(0) | - SPI_PUSHR_CMD_PCS(spi->chip_select); + SPI_PUSHR_CMD_PCS(spi->chip_select); if (list_is_last(&dspi->cur_transfer->transfer_list, &dspi->cur_msg->transfers)) { /* Leave PCS activated after last transfer when @@ -701,6 +763,7 @@ static int dspi_transfer_one_message(struct spi_master *master, dspi->rx = transfer->rx_buf; dspi->rx_end = dspi->rx + transfer->len; dspi->len = transfer->len; + dspi->progress = 0; /* Validated transfer specific frame size (defaults applied) */ dspi->bits_per_word = transfer->bits_per_word; if (transfer->bits_per_word <= 8) @@ -718,8 +781,11 @@ static int dspi_transfer_one_message(struct spi_master *master, SPI_FRAME_BITS(transfer->bits_per_word)); if (dspi->devtype_data->xspi_mode) regmap_write(dspi->regmap, SPI_CTARE(0), - SPI_FRAME_EBITS(transfer->bits_per_word) - | SPI_CTARE_DTCP(1)); + SPI_FRAME_EBITS(transfer->bits_per_word) | + SPI_CTARE_DTCP(1)); + + spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer, + dspi->progress, !dspi->irq); trans_mode = dspi->devtype_data->trans_mode; switch (trans_mode) { @@ -733,8 +799,8 @@ static int dspi_transfer_one_message(struct spi_master *master, break; case DSPI_DMA_MODE: regmap_write(dspi->regmap, SPI_RSER, - SPI_RSER_TFFFE | SPI_RSER_TFFFD | - SPI_RSER_RFDFE | SPI_RSER_RFDFD); + SPI_RSER_TFFFE | SPI_RSER_TFFFD | + SPI_RSER_RFDFE | SPI_RSER_RFDFD); status = dspi_dma_xfer(dspi); break; default: @@ -744,33 +810,37 @@ static int dspi_transfer_one_message(struct spi_master *master, goto out; } - if (trans_mode != DSPI_DMA_MODE) { - if (wait_event_interruptible(dspi->waitq, - dspi->waitflags)) - dev_err(&dspi->pdev->dev, - "wait transfer complete fail!\n"); + if (!dspi->irq) { + do { + status = dspi_poll(dspi); + } while (status == -EINPROGRESS); + } else if (trans_mode != DSPI_DMA_MODE) { + status = wait_event_interruptible(dspi->waitq, + dspi->waitflags); dspi->waitflags = 0; } + if (status) + dev_err(&dspi->pdev->dev, + "Waiting for transfer to complete failed!\n"); - if (transfer->delay_usecs) - udelay(transfer->delay_usecs); + spi_transfer_delay_exec(transfer); } out: message->status = status; - spi_finalize_current_message(master); + spi_finalize_current_message(ctlr); return status; } static int dspi_setup(struct spi_device *spi) { - struct chip_data *chip; - struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); - struct fsl_dspi_platform_data *pdata; - u32 cs_sck_delay = 0, sck_cs_delay = 0; + struct fsl_dspi *dspi = spi_controller_get_devdata(spi->controller); unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0; + u32 cs_sck_delay = 0, sck_cs_delay = 0; + struct fsl_dspi_platform_data *pdata; unsigned char pasc = 0, asc = 0; + struct chip_data *chip; unsigned long clkrate; /* Only alloc on first setup */ @@ -785,10 +855,10 @@ static int dspi_setup(struct spi_device *spi) if (!pdata) { of_property_read_u32(spi->dev.of_node, "fsl,spi-cs-sck-delay", - &cs_sck_delay); + &cs_sck_delay); of_property_read_u32(spi->dev.of_node, "fsl,spi-sck-cs-delay", - &sck_cs_delay); + &sck_cs_delay); } else { cs_sck_delay = pdata->cs_sck_delay; sck_cs_delay = pdata->sck_cs_delay; @@ -805,18 +875,22 @@ static int dspi_setup(struct spi_device *spi) /* Set After SCK delay scale values */ ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate); - chip->ctar_val = SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0) - | SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0); - - if (!spi_controller_is_slave(dspi->master)) { - chip->ctar_val |= SPI_CTAR_LSBFE(spi->mode & - SPI_LSB_FIRST ? 1 : 0) - | SPI_CTAR_PCSSCK(pcssck) - | SPI_CTAR_CSSCK(cssck) - | SPI_CTAR_PASC(pasc) - | SPI_CTAR_ASC(asc) - | SPI_CTAR_PBR(pbr) - | SPI_CTAR_BR(br); + chip->ctar_val = 0; + if (spi->mode & SPI_CPOL) + chip->ctar_val |= SPI_CTAR_CPOL; + if (spi->mode & SPI_CPHA) + chip->ctar_val |= SPI_CTAR_CPHA; + + if (!spi_controller_is_slave(dspi->ctlr)) { + chip->ctar_val |= SPI_CTAR_PCSSCK(pcssck) | + SPI_CTAR_CSSCK(cssck) | + SPI_CTAR_PASC(pasc) | + SPI_CTAR_ASC(asc) | + SPI_CTAR_PBR(pbr) | + SPI_CTAR_BR(br); + + if (spi->mode & SPI_LSB_FIRST) + chip->ctar_val |= SPI_CTAR_LSBFE; } spi_set_ctldata(spi, chip); @@ -829,68 +903,11 @@ static void dspi_cleanup(struct spi_device *spi) struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi); dev_dbg(&spi->dev, "spi_device %u.%u cleanup\n", - spi->master->bus_num, spi->chip_select); + spi->controller->bus_num, spi->chip_select); kfree(chip); } -static irqreturn_t dspi_interrupt(int irq, void *dev_id) -{ - struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; - struct spi_message *msg = dspi->cur_msg; - enum dspi_trans_mode trans_mode; - u32 spi_sr, spi_tcr; - u16 spi_tcnt; - - regmap_read(dspi->regmap, SPI_SR, &spi_sr); - regmap_write(dspi->regmap, SPI_SR, spi_sr); - - - if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) { - /* Get transfer counter (in number of SPI transfers). It was - * reset to 0 when transfer(s) were started. - */ - regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); - spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); - /* Update total number of bytes that were transferred */ - msg->actual_length += spi_tcnt * dspi->bytes_per_word; - - trans_mode = dspi->devtype_data->trans_mode; - switch (trans_mode) { - case DSPI_EOQ_MODE: - dspi_eoq_read(dspi); - break; - case DSPI_TCFQ_MODE: - dspi_tcfq_read(dspi); - break; - default: - dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", - trans_mode); - return IRQ_HANDLED; - } - - if (!dspi->len) { - dspi->waitflags = 1; - wake_up_interruptible(&dspi->waitq); - } else { - switch (trans_mode) { - case DSPI_EOQ_MODE: - dspi_eoq_write(dspi); - break; - case DSPI_TCFQ_MODE: - dspi_tcfq_write(dspi); - break; - default: - dev_err(&dspi->pdev->dev, - "unsupported trans_mode %u\n", - trans_mode); - } - } - } - - return IRQ_HANDLED; -} - static const struct of_device_id fsl_dspi_dt_ids[] = { { .compatible = "fsl,vf610-dspi", .data = &vf610_data, }, { .compatible = "fsl,ls1021a-v1.0-dspi", .data = &ls1021a_v1_data, }, @@ -902,10 +919,10 @@ MODULE_DEVICE_TABLE(of, fsl_dspi_dt_ids); #ifdef CONFIG_PM_SLEEP static int dspi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct fsl_dspi *dspi = spi_master_get_devdata(master); + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr); - spi_master_suspend(master); + spi_controller_suspend(ctlr); clk_disable_unprepare(dspi->clk); pinctrl_pm_select_sleep_state(dev); @@ -915,8 +932,8 @@ static int dspi_suspend(struct device *dev) static int dspi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct fsl_dspi *dspi = spi_master_get_devdata(master); + struct spi_controller *ctlr = dev_get_drvdata(dev); + struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr); int ret; pinctrl_pm_select_default_state(dev); @@ -924,7 +941,7 @@ static int dspi_resume(struct device *dev) ret = clk_prepare_enable(dspi->clk); if (ret) return ret; - spi_master_resume(master); + spi_controller_resume(ctlr); return 0; } @@ -939,16 +956,16 @@ static const struct regmap_range dspi_volatile_ranges[] = { }; static const struct regmap_access_table dspi_volatile_table = { - .yes_ranges = dspi_volatile_ranges, - .n_yes_ranges = ARRAY_SIZE(dspi_volatile_ranges), + .yes_ranges = dspi_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(dspi_volatile_ranges), }; static const struct regmap_config dspi_regmap_config = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .max_register = 0x88, - .volatile_table = &dspi_volatile_table, + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x88, + .volatile_table = &dspi_volatile_table, }; static const struct regmap_range dspi_xspi_volatile_ranges[] = { @@ -959,33 +976,34 @@ static const struct regmap_range dspi_xspi_volatile_ranges[] = { }; static const struct regmap_access_table dspi_xspi_volatile_table = { - .yes_ranges = dspi_xspi_volatile_ranges, - .n_yes_ranges = ARRAY_SIZE(dspi_xspi_volatile_ranges), + .yes_ranges = dspi_xspi_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(dspi_xspi_volatile_ranges), }; static const struct regmap_config dspi_xspi_regmap_config[] = { { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .max_register = 0x13c, - .volatile_table = &dspi_xspi_volatile_table, + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x13c, + .volatile_table = &dspi_xspi_volatile_table, }, { - .name = "pushr", - .reg_bits = 16, - .val_bits = 16, - .reg_stride = 2, - .max_register = 0x2, + .name = "pushr", + .reg_bits = 16, + .val_bits = 16, + .reg_stride = 2, + .max_register = 0x2, }, }; static void dspi_init(struct fsl_dspi *dspi) { - unsigned int mcr = SPI_MCR_PCSIS | - (dspi->devtype_data->xspi_mode ? SPI_MCR_XSPI : 0); + unsigned int mcr = SPI_MCR_PCSIS; - if (!spi_controller_is_slave(dspi->master)) + if (dspi->devtype_data->xspi_mode) + mcr |= SPI_MCR_XSPI; + if (!spi_controller_is_slave(dspi->ctlr)) mcr |= SPI_MCR_MASTER; regmap_write(dspi->regmap, SPI_MCR, mcr); @@ -995,37 +1013,56 @@ static void dspi_init(struct fsl_dspi *dspi) SPI_CTARE_FMSZE(0) | SPI_CTARE_DTCP(1)); } +static int dspi_slave_abort(struct spi_master *master) +{ + struct fsl_dspi *dspi = spi_master_get_devdata(master); + + /* + * Terminate all pending DMA transactions for the SPI working + * in SLAVE mode. + */ + dmaengine_terminate_sync(dspi->dma->chan_rx); + dmaengine_terminate_sync(dspi->dma->chan_tx); + + /* Clear the internal DSPI RX and TX FIFO buffers */ + regmap_update_bits(dspi->regmap, SPI_MCR, + SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF, + SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF); + + return 0; +} + static int dspi_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct spi_master *master; + const struct regmap_config *regmap_config; + struct fsl_dspi_platform_data *pdata; + struct spi_controller *ctlr; + int ret, cs_num, bus_num; struct fsl_dspi *dspi; struct resource *res; - const struct regmap_config *regmap_config; void __iomem *base; - struct fsl_dspi_platform_data *pdata; - int ret = 0, cs_num, bus_num; - master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); - if (!master) + ctlr = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); + if (!ctlr) return -ENOMEM; - dspi = spi_master_get_devdata(master); + dspi = spi_controller_get_devdata(ctlr); dspi->pdev = pdev; - dspi->master = master; + dspi->ctlr = ctlr; - master->transfer = NULL; - master->setup = dspi_setup; - master->transfer_one_message = dspi_transfer_one_message; - master->dev.of_node = pdev->dev.of_node; + ctlr->setup = dspi_setup; + ctlr->transfer_one_message = dspi_transfer_one_message; + ctlr->dev.of_node = pdev->dev.of_node; - master->cleanup = dspi_cleanup; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + ctlr->cleanup = dspi_cleanup; + ctlr->slave_abort = dspi_slave_abort; + ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; pdata = dev_get_platdata(&pdev->dev); if (pdata) { - master->num_chipselect = pdata->cs_num; - master->bus_num = pdata->bus_num; + ctlr->num_chipselect = pdata->cs_num; + ctlr->bus_num = pdata->bus_num; dspi->devtype_data = &coldfire_data; } else { @@ -1033,38 +1070,38 @@ static int dspi_probe(struct platform_device *pdev) ret = of_property_read_u32(np, "spi-num-chipselects", &cs_num); if (ret < 0) { dev_err(&pdev->dev, "can't get spi-num-chipselects\n"); - goto out_master_put; + goto out_ctlr_put; } - master->num_chipselect = cs_num; + ctlr->num_chipselect = cs_num; ret = of_property_read_u32(np, "bus-num", &bus_num); if (ret < 0) { dev_err(&pdev->dev, "can't get bus-num\n"); - goto out_master_put; + goto out_ctlr_put; } - master->bus_num = bus_num; + ctlr->bus_num = bus_num; if (of_property_read_bool(np, "spi-slave")) - master->slave = true; + ctlr->slave = true; dspi->devtype_data = of_device_get_match_data(&pdev->dev); if (!dspi->devtype_data) { dev_err(&pdev->dev, "can't get devtype_data\n"); ret = -EFAULT; - goto out_master_put; + goto out_ctlr_put; } } if (dspi->devtype_data->xspi_mode) - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); + ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); else - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); + ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) { ret = PTR_ERR(base); - goto out_master_put; + goto out_ctlr_put; } if (dspi->devtype_data->xspi_mode) @@ -1076,7 +1113,7 @@ static int dspi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to init regmap: %ld\n", PTR_ERR(dspi->regmap)); ret = PTR_ERR(dspi->regmap); - goto out_master_put; + goto out_ctlr_put; } if (dspi->devtype_data->xspi_mode) { @@ -1088,7 +1125,7 @@ static int dspi_probe(struct platform_device *pdev) "failed to init pushr regmap: %ld\n", PTR_ERR(dspi->regmap_pushr)); ret = PTR_ERR(dspi->regmap_pushr); - goto out_master_put; + goto out_ctlr_put; } } @@ -1096,18 +1133,23 @@ static int dspi_probe(struct platform_device *pdev) if (IS_ERR(dspi->clk)) { ret = PTR_ERR(dspi->clk); dev_err(&pdev->dev, "unable to get clock\n"); - goto out_master_put; + goto out_ctlr_put; } ret = clk_prepare_enable(dspi->clk); if (ret) - goto out_master_put; + goto out_ctlr_put; dspi_init(dspi); + + if (dspi->devtype_data->trans_mode == DSPI_TCFQ_MODE) + goto poll_mode; + dspi->irq = platform_get_irq(pdev, 0); - if (dspi->irq < 0) { - dev_err(&pdev->dev, "can't get platform irq\n"); - ret = dspi->irq; - goto out_clk_put; + if (dspi->irq <= 0) { + dev_info(&pdev->dev, + "can't get platform irq, using poll mode\n"); + dspi->irq = 0; + goto poll_mode; } ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt, @@ -1117,6 +1159,10 @@ static int dspi_probe(struct platform_device *pdev) goto out_clk_put; } + init_waitqueue_head(&dspi->waitq); + +poll_mode: + if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) { ret = dspi_request_dma(dspi, res->start); if (ret < 0) { @@ -1125,15 +1171,16 @@ static int dspi_probe(struct platform_device *pdev) } } - master->max_speed_hz = + ctlr->max_speed_hz = clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor; - init_waitqueue_head(&dspi->waitq); - platform_set_drvdata(pdev, master); + ctlr->ptp_sts_supported = dspi->devtype_data->ptp_sts_supported; - ret = spi_register_master(master); + platform_set_drvdata(pdev, ctlr); + + ret = spi_register_controller(ctlr); if (ret != 0) { - dev_err(&pdev->dev, "Problem registering DSPI master\n"); + dev_err(&pdev->dev, "Problem registering DSPI ctlr\n"); goto out_clk_put; } @@ -1141,32 +1188,32 @@ static int dspi_probe(struct platform_device *pdev) out_clk_put: clk_disable_unprepare(dspi->clk); -out_master_put: - spi_master_put(master); +out_ctlr_put: + spi_controller_put(ctlr); return ret; } static int dspi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct fsl_dspi *dspi = spi_master_get_devdata(master); + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr); /* Disconnect from the SPI framework */ dspi_release_dma(dspi); clk_disable_unprepare(dspi->clk); - spi_unregister_master(dspi->master); + spi_unregister_controller(dspi->ctlr); return 0; } static struct platform_driver fsl_dspi_driver = { - .driver.name = DRIVER_NAME, - .driver.of_match_table = fsl_dspi_dt_ids, - .driver.owner = THIS_MODULE, - .driver.pm = &dspi_pm, - .probe = dspi_probe, - .remove = dspi_remove, + .driver.name = DRIVER_NAME, + .driver.of_match_table = fsl_dspi_dt_ids, + .driver.owner = THIS_MODULE, + .driver.pm = &dspi_pm, + .probe = dspi_probe, + .remove = dspi_remove, }; module_platform_driver(fsl_dspi_driver); diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index f20326714b9d..e60581283a24 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -427,8 +427,7 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans) ret = fsl_espi_bufs(spi, trans); - if (trans->delay_usecs) - udelay(trans->delay_usecs); + spi_transfer_delay_exec(trans); return ret; } @@ -437,6 +436,7 @@ static int fsl_espi_do_one_msg(struct spi_master *master, struct spi_message *m) { unsigned int delay_usecs = 0, rx_nbits = 0; + unsigned int delay_nsecs = 0, delay_nsecs1 = 0; struct spi_transfer *t, trans = {}; int ret; @@ -445,8 +445,16 @@ static int fsl_espi_do_one_msg(struct spi_master *master, goto out; list_for_each_entry(t, &m->transfers, transfer_list) { - if (t->delay_usecs > delay_usecs) - delay_usecs = t->delay_usecs; + if (t->delay_usecs) { + if (t->delay_usecs > delay_usecs) { + delay_usecs = t->delay_usecs; + delay_nsecs = delay_usecs * 1000; + } + } else { + delay_nsecs1 = spi_delay_to_ns(&t->delay, t); + if (delay_nsecs1 > delay_nsecs) + delay_nsecs = delay_nsecs1; + } if (t->rx_nbits > rx_nbits) rx_nbits = t->rx_nbits; } @@ -457,7 +465,8 @@ static int fsl_espi_do_one_msg(struct spi_master *master, trans.len = m->frame_length; trans.speed_hz = t->speed_hz; trans.bits_per_word = t->bits_per_word; - trans.delay_usecs = delay_usecs; + trans.delay.value = delay_nsecs; + trans.delay.unit = SPI_DELAY_UNIT_NSECS; trans.rx_nbits = rx_nbits; if (trans.len) diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h index 3576167283dc..015a1abb6a84 100644 --- a/drivers/spi/spi-fsl-lib.h +++ b/drivers/spi/spi-fsl-lib.h @@ -91,9 +91,6 @@ static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg) struct mpc8xxx_spi_probe_info { struct fsl_spi_platform_data pdata; - int ngpios; - int *gpios; - bool *alow_flags; __be32 __iomem *immr_spi_cs; }; diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index d08e9324140e..d0b8cc741a24 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -469,9 +469,9 @@ static int fsl_lpspi_setup_transfer(struct spi_controller *controller, fsl_lpspi->watermark = fsl_lpspi->txfifosize; if (fsl_lpspi_can_dma(controller, spi, t)) - fsl_lpspi->usedma = 1; + fsl_lpspi->usedma = true; else - fsl_lpspi->usedma = 0; + fsl_lpspi->usedma = false; return fsl_lpspi_config(fsl_lpspi); } @@ -675,7 +675,7 @@ static int fsl_lpspi_dma_init(struct device *dev, int ret; /* Prepare for TX DMA: */ - controller->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + controller->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR(controller->dma_tx)) { ret = PTR_ERR(controller->dma_tx); dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret); @@ -684,7 +684,7 @@ static int fsl_lpspi_dma_init(struct device *dev, } /* Prepare for RX DMA: */ - controller->dma_rx = dma_request_slave_channel_reason(dev, "rx"); + controller->dma_rx = dma_request_chan(dev, "rx"); if (IS_ERR(controller->dma_rx)) { ret = PTR_ERR(controller->dma_rx); dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret); @@ -779,7 +779,7 @@ static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id) if (temp_SR & SR_FCF && (temp_IER & IER_FCIE)) { writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR); - complete(&fsl_lpspi->xfer_done); + complete(&fsl_lpspi->xfer_done); return IRQ_HANDLED; } @@ -862,6 +862,22 @@ static int fsl_lpspi_probe(struct platform_device *pdev) fsl_lpspi->dev = &pdev->dev; fsl_lpspi->is_slave = is_slave; + controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); + controller->transfer_one = fsl_lpspi_transfer_one; + controller->prepare_transfer_hardware = lpspi_prepare_xfer_hardware; + controller->unprepare_transfer_hardware = lpspi_unprepare_xfer_hardware; + controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; + controller->dev.of_node = pdev->dev.of_node; + controller->bus_num = pdev->id; + controller->slave_abort = fsl_lpspi_slave_abort; + + ret = devm_spi_register_controller(&pdev->dev, controller); + if (ret < 0) { + dev_err(&pdev->dev, "spi_register_controller error.\n"); + goto out_controller_put; + } + if (!fsl_lpspi->is_slave) { for (i = 0; i < controller->num_chipselect; i++) { int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); @@ -885,16 +901,6 @@ static int fsl_lpspi_probe(struct platform_device *pdev) controller->prepare_message = fsl_lpspi_prepare_message; } - controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); - controller->transfer_one = fsl_lpspi_transfer_one; - controller->prepare_transfer_hardware = lpspi_prepare_xfer_hardware; - controller->unprepare_transfer_hardware = lpspi_unprepare_xfer_hardware; - controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; - controller->dev.of_node = pdev->dev.of_node; - controller->bus_num = pdev->id; - controller->slave_abort = fsl_lpspi_slave_abort; - init_completion(&fsl_lpspi->xfer_done); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -938,7 +944,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ret = pm_runtime_get_sync(fsl_lpspi->dev); if (ret < 0) { dev_err(fsl_lpspi->dev, "failed to enable clock\n"); - return ret; + goto out_controller_put; } temp = readl(fsl_lpspi->base + IMX7ULP_PARAM); @@ -952,12 +958,6 @@ static int fsl_lpspi_probe(struct platform_device *pdev) if (ret < 0) dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret); - ret = devm_spi_register_controller(&pdev->dev, controller); - if (ret < 0) { - dev_err(&pdev->dev, "spi_register_controller error.\n"); - goto out_controller_put; - } - return 0; out_controller_put: diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c index 448c00e4065b..e8a499cd1f13 100644 --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c @@ -63,6 +63,16 @@ #define QUADSPI_IPCR 0x08 #define QUADSPI_IPCR_SEQID(x) ((x) << 24) +#define QUADSPI_FLSHCR 0x0c +#define QUADSPI_FLSHCR_TCSS_MASK GENMASK(3, 0) +#define QUADSPI_FLSHCR_TCSH_MASK GENMASK(11, 8) +#define QUADSPI_FLSHCR_TDH_MASK GENMASK(17, 16) + +#define QUADSPI_BUF0CR 0x10 +#define QUADSPI_BUF1CR 0x14 +#define QUADSPI_BUF2CR 0x18 +#define QUADSPI_BUFXCR_INVALID_MSTRID 0xe + #define QUADSPI_BUF3CR 0x1c #define QUADSPI_BUF3CR_ALLMST_MASK BIT(31) #define QUADSPI_BUF3CR_ADATSZ(x) ((x) << 8) @@ -95,6 +105,9 @@ #define QUADSPI_FR 0x160 #define QUADSPI_FR_TFF_MASK BIT(0) +#define QUADSPI_RSER 0x164 +#define QUADSPI_RSER_TFIE BIT(0) + #define QUADSPI_SPTRCLR 0x16c #define QUADSPI_SPTRCLR_IPPTRC BIT(8) #define QUADSPI_SPTRCLR_BFPTRC BIT(0) @@ -112,9 +125,6 @@ #define QUADSPI_LCKER_LOCK BIT(0) #define QUADSPI_LCKER_UNLOCK BIT(1) -#define QUADSPI_RSER 0x164 -#define QUADSPI_RSER_TFIE BIT(0) - #define QUADSPI_LUT_BASE 0x310 #define QUADSPI_LUT_OFFSET (SEQID_LUT * 4 * 4) #define QUADSPI_LUT_REG(idx) \ @@ -181,9 +191,16 @@ */ #define QUADSPI_QUIRK_BASE_INTERNAL BIT(4) +/* + * Controller uses TDH bits in register QUADSPI_FLSHCR. + * They need to be set in accordance with the DDR/SDR mode. + */ +#define QUADSPI_QUIRK_USE_TDH_SETTING BIT(5) + struct fsl_qspi_devtype_data { unsigned int rxfifo; unsigned int txfifo; + int invalid_mstrid; unsigned int ahb_buf_size; unsigned int quirks; bool little_endian; @@ -192,6 +209,7 @@ struct fsl_qspi_devtype_data { static const struct fsl_qspi_devtype_data vybrid_data = { .rxfifo = SZ_128, .txfifo = SZ_64, + .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, .quirks = QUADSPI_QUIRK_SWAP_ENDIAN, .little_endian = true, @@ -200,6 +218,7 @@ static const struct fsl_qspi_devtype_data vybrid_data = { static const struct fsl_qspi_devtype_data imx6sx_data = { .rxfifo = SZ_128, .txfifo = SZ_512, + .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, .quirks = QUADSPI_QUIRK_4X_INT_CLK | QUADSPI_QUIRK_TKT245618, .little_endian = true, @@ -208,22 +227,27 @@ static const struct fsl_qspi_devtype_data imx6sx_data = { static const struct fsl_qspi_devtype_data imx7d_data = { .rxfifo = SZ_128, .txfifo = SZ_512, + .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, - .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK, + .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK | + QUADSPI_QUIRK_USE_TDH_SETTING, .little_endian = true, }; static const struct fsl_qspi_devtype_data imx6ul_data = { .rxfifo = SZ_128, .txfifo = SZ_512, + .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, - .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK, + .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK | + QUADSPI_QUIRK_USE_TDH_SETTING, .little_endian = true, }; static const struct fsl_qspi_devtype_data ls1021a_data = { .rxfifo = SZ_128, .txfifo = SZ_64, + .invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID, .ahb_buf_size = SZ_1K, .quirks = 0, .little_endian = false, @@ -233,6 +257,7 @@ static const struct fsl_qspi_devtype_data ls2080a_data = { .rxfifo = SZ_128, .txfifo = SZ_64, .ahb_buf_size = SZ_1K, + .invalid_mstrid = 0x0, .quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_BASE_INTERNAL, .little_endian = true, }; @@ -275,6 +300,11 @@ static inline int needs_amba_base_offset(struct fsl_qspi *q) return !(q->devtype_data->quirks & QUADSPI_QUIRK_BASE_INTERNAL); } +static inline int needs_tdh_setting(struct fsl_qspi *q) +{ + return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING; +} + /* * An IC bug makes it necessary to rearrange the 32-bit data. * Later chips, such as IMX6SLX, have fixed this bug. @@ -380,7 +410,7 @@ static bool fsl_qspi_supports_op(struct spi_mem *mem, op->data.nbytes > q->devtype_data->txfifo) return false; - return true; + return spi_mem_default_supports_op(mem, op); } static void fsl_qspi_prepare_lut(struct fsl_qspi *q, @@ -615,6 +645,7 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) void __iomem *base = q->iobase; u32 addr_offset = 0; int err = 0; + int invalid_mstrid = q->devtype_data->invalid_mstrid; mutex_lock(&q->lock); @@ -638,6 +669,10 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) qspi_writel(q, QUADSPI_SPTRCLR_BFPTRC | QUADSPI_SPTRCLR_IPPTRC, base + QUADSPI_SPTRCLR); + qspi_writel(q, invalid_mstrid, base + QUADSPI_BUF0CR); + qspi_writel(q, invalid_mstrid, base + QUADSPI_BUF1CR); + qspi_writel(q, invalid_mstrid, base + QUADSPI_BUF2CR); + fsl_qspi_prepare_lut(q, op); /* @@ -710,6 +745,16 @@ static int fsl_qspi_default_setup(struct fsl_qspi *q) qspi_writel(q, QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK, base + QUADSPI_MCR); + /* + * Previous boot stages (BootROM, bootloader) might have used DDR + * mode and did not clear the TDH bits. As we currently use SDR mode + * only, clear the TDH bits if necessary. + */ + if (needs_tdh_setting(q)) + qspi_writel(q, qspi_readl(q, base + QUADSPI_FLSHCR) & + ~QUADSPI_FLSHCR_TDH_MASK, + base + QUADSPI_FLSHCR); + reg = qspi_readl(q, base + QUADSPI_SMPR); qspi_writel(q, reg & ~(QUADSPI_SMPR_FSDLY_MASK | QUADSPI_SMPR_FSPHS_MASK @@ -860,10 +905,8 @@ static int fsl_qspi_probe(struct platform_device *pdev) /* find the irq */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "failed to get the irq: %d\n", ret); + if (ret < 0) goto err_disable_clk; - } ret = devm_request_irq(dev, ret, fsl_qspi_irq_handler, 0, pdev->name, q); diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 1d9b33aa1a3b..3b81772fea0d 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -18,7 +18,7 @@ #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/fsl_devices.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/kernel.h> @@ -28,7 +28,6 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_gpio.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> @@ -417,8 +416,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master, } m->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (cs_change) { ndelay(nsecs); @@ -481,32 +479,6 @@ static int fsl_spi_setup(struct spi_device *spi) return retval; } - if (mpc8xxx_spi->type == TYPE_GRLIB) { - if (gpio_is_valid(spi->cs_gpio)) { - int desel; - - retval = gpio_request(spi->cs_gpio, - dev_name(&spi->dev)); - if (retval) - return retval; - - desel = !(spi->mode & SPI_CS_HIGH); - retval = gpio_direction_output(spi->cs_gpio, desel); - if (retval) { - gpio_free(spi->cs_gpio); - return retval; - } - } else if (spi->cs_gpio != -ENOENT) { - if (spi->cs_gpio < 0) - return spi->cs_gpio; - return -EINVAL; - } - /* When spi->cs_gpio == -ENOENT, a hole in the phandle list - * indicates to use native chipselect if present, or allow for - * an always selected chip - */ - } - /* Initialize chipselect - might be active for SPI_CS_HIGH mode */ fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE); @@ -515,12 +487,8 @@ static int fsl_spi_setup(struct spi_device *spi) static void fsl_spi_cleanup(struct spi_device *spi) { - struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi); - if (mpc8xxx_spi->type == TYPE_GRLIB && gpio_is_valid(spi->cs_gpio)) - gpio_free(spi->cs_gpio); - kfree(cs); spi_set_ctldata(spi, NULL); } @@ -586,8 +554,8 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) u32 slvsel; u16 cs = spi->chip_select; - if (gpio_is_valid(spi->cs_gpio)) { - gpio_set_value(spi->cs_gpio, on); + if (spi->cs_gpiod) { + gpiod_set_value(spi->cs_gpiod, on); } else if (cs < mpc8xxx_spi->native_chipselects) { slvsel = mpc8xxx_spi_read_reg(®_base->slvsel); slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs)); @@ -643,6 +611,7 @@ static struct spi_master * fsl_spi_probe(struct device *dev, master->setup = fsl_spi_setup; master->cleanup = fsl_spi_cleanup; master->transfer_one_message = fsl_spi_do_one_msg; + master->use_gpio_descriptors = true; mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi->max_bits_per_word = 32; @@ -718,147 +687,27 @@ err: static void fsl_spi_cs_control(struct spi_device *spi, bool on) { - struct device *dev = spi->dev.parent->parent; - struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); - struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); - u16 cs = spi->chip_select; - - if (cs < pinfo->ngpios) { - int gpio = pinfo->gpios[cs]; - bool alow = pinfo->alow_flags[cs]; - - gpio_set_value(gpio, on ^ alow); + if (spi->cs_gpiod) { + gpiod_set_value(spi->cs_gpiod, on); } else { - if (WARN_ON_ONCE(cs > pinfo->ngpios || !pinfo->immr_spi_cs)) + struct device *dev = spi->dev.parent->parent; + struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); + struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); + + if (WARN_ON_ONCE(!pinfo->immr_spi_cs)) return; iowrite32be(on ? SPI_BOOT_SEL_BIT : 0, pinfo->immr_spi_cs); } } -static int of_fsl_spi_get_chipselects(struct device *dev) -{ - struct device_node *np = dev->of_node; - struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); - struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); - bool spisel_boot = IS_ENABLED(CONFIG_FSL_SOC) && - of_property_read_bool(np, "fsl,spisel_boot"); - int ngpios; - int i = 0; - int ret; - - ngpios = of_gpio_count(np); - ngpios = max(ngpios, 0); - if (ngpios == 0 && !spisel_boot) { - /* - * SPI w/o chip-select line. One SPI device is still permitted - * though. - */ - pdata->max_chipselect = 1; - return 0; - } - - pinfo->ngpios = ngpios; - pinfo->gpios = kmalloc_array(ngpios, sizeof(*pinfo->gpios), - GFP_KERNEL); - if (!pinfo->gpios) - return -ENOMEM; - memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios)); - - pinfo->alow_flags = kcalloc(ngpios, sizeof(*pinfo->alow_flags), - GFP_KERNEL); - if (!pinfo->alow_flags) { - ret = -ENOMEM; - goto err_alloc_flags; - } - - for (; i < ngpios; i++) { - int gpio; - enum of_gpio_flags flags; - - gpio = of_get_gpio_flags(np, i, &flags); - if (!gpio_is_valid(gpio)) { - dev_err(dev, "invalid gpio #%d: %d\n", i, gpio); - ret = gpio; - goto err_loop; - } - - ret = gpio_request(gpio, dev_name(dev)); - if (ret) { - dev_err(dev, "can't request gpio #%d: %d\n", i, ret); - goto err_loop; - } - - pinfo->gpios[i] = gpio; - pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW; - - ret = gpio_direction_output(pinfo->gpios[i], - pinfo->alow_flags[i]); - if (ret) { - dev_err(dev, - "can't set output direction for gpio #%d: %d\n", - i, ret); - goto err_loop; - } - } - -#if IS_ENABLED(CONFIG_FSL_SOC) - if (spisel_boot) { - pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4); - if (!pinfo->immr_spi_cs) { - ret = -ENOMEM; - i = ngpios - 1; - goto err_loop; - } - } -#endif - - pdata->max_chipselect = ngpios + spisel_boot; - pdata->cs_control = fsl_spi_cs_control; - - return 0; - -err_loop: - while (i >= 0) { - if (gpio_is_valid(pinfo->gpios[i])) - gpio_free(pinfo->gpios[i]); - i--; - } - - kfree(pinfo->alow_flags); - pinfo->alow_flags = NULL; -err_alloc_flags: - kfree(pinfo->gpios); - pinfo->gpios = NULL; - return ret; -} - -static int of_fsl_spi_free_chipselects(struct device *dev) -{ - struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); - struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); - int i; - - if (!pinfo->gpios) - return 0; - - for (i = 0; i < pdata->max_chipselect; i++) { - if (gpio_is_valid(pinfo->gpios[i])) - gpio_free(pinfo->gpios[i]); - } - - kfree(pinfo->gpios); - kfree(pinfo->alow_flags); - return 0; -} - static int of_fsl_spi_probe(struct platform_device *ofdev) { struct device *dev = &ofdev->dev; struct device_node *np = ofdev->dev.of_node; struct spi_master *master; struct resource mem; - int irq = 0, type; - int ret = -ENOMEM; + int irq, type; + int ret; ret = of_mpc8xxx_spi_probe(ofdev); if (ret) @@ -866,34 +715,42 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) type = fsl_spi_get_type(&ofdev->dev); if (type == TYPE_FSL) { - ret = of_fsl_spi_get_chipselects(dev); - if (ret) - goto err; + struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); +#if IS_ENABLED(CONFIG_FSL_SOC) + struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata); + bool spisel_boot = of_property_read_bool(np, "fsl,spisel_boot"); + + if (spisel_boot) { + pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4); + if (!pinfo->immr_spi_cs) + return -ENOMEM; + } +#endif + /* + * Handle the case where we have one hardwired (always selected) + * device on the first "chipselect". Else we let the core code + * handle any GPIOs or native chip selects and assign the + * appropriate callback for dealing with the CS lines. This isn't + * supported on the GRLIB variant. + */ + ret = gpiod_count(dev, "cs"); + if (ret <= 0) + pdata->max_chipselect = 1; + else + pdata->cs_control = fsl_spi_cs_control; } ret = of_address_to_resource(np, 0, &mem); if (ret) - goto err; + return ret; - irq = irq_of_parse_and_map(np, 0); - if (!irq) { - ret = -EINVAL; - goto err; - } + irq = platform_get_irq(ofdev, 0); + if (irq < 0) + return irq; master = fsl_spi_probe(dev, &mem, irq); - if (IS_ERR(master)) { - ret = PTR_ERR(master); - goto err; - } - return 0; - -err: - irq_dispose_mapping(irq); - if (type == TYPE_FSL) - of_fsl_spi_free_chipselects(dev); - return ret; + return PTR_ERR_OR_ZERO(master); } static int of_fsl_spi_remove(struct platform_device *ofdev) @@ -902,8 +759,6 @@ static int of_fsl_spi_remove(struct platform_device *ofdev) struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); fsl_spi_cpm_free(mpc8xxx_spi); - if (mpc8xxx_spi->type == TYPE_FSL) - of_fsl_spi_free_chipselects(&ofdev->dev); return 0; } diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 5f0b0d5bfef4..6f3d64a1a2b3 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -534,18 +534,14 @@ static int spi_geni_probe(struct platform_device *pdev) int ret, irq; struct spi_master *spi; struct spi_geni_master *mas; - struct resource *res; void __iomem *base; struct clk *clk; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Err getting IRQ %d\n", irq); + if (irq < 0) return irq; - } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 9eb82150666e..7ceb0ba27b75 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -290,10 +290,7 @@ static int spi_gpio_request(struct device *dev, struct spi_gpio *spi_gpio) return PTR_ERR(spi_gpio->miso); spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW); - if (IS_ERR(spi_gpio->sck)) - return PTR_ERR(spi_gpio->sck); - - return 0; + return PTR_ERR_OR_ZERO(spi_gpio->sck); } #ifdef CONFIG_OF @@ -365,19 +362,18 @@ static int spi_gpio_probe(struct platform_device *pdev) struct spi_gpio *spi_gpio; struct device *dev = &pdev->dev; struct spi_bitbang *bb; - const struct of_device_id *of_id; - - of_id = of_match_device(spi_gpio_dt_ids, &pdev->dev); master = spi_alloc_master(dev, sizeof(*spi_gpio)); if (!master) return -ENOMEM; status = devm_add_action_or_reset(&pdev->dev, spi_gpio_put, master); - if (status) + if (status) { + spi_master_put(master); return status; + } - if (of_id) + if (pdev->dev.of_node) status = spi_gpio_probe_dt(pdev, master); else status = spi_gpio_probe_pdata(pdev, master); diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c new file mode 100644 index 000000000000..4cf8fc80a7b7 --- /dev/null +++ b/drivers/spi/spi-hisi-sfc-v3xx.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// HiSilicon SPI NOR V3XX Flash Controller Driver for hi16xx chipsets +// +// Copyright (c) 2019 HiSilicon Technologies Co., Ltd. +// Author: John Garry <john.garry@huawei.com> + +#include <linux/acpi.h> +#include <linux/bitops.h> +#include <linux/iopoll.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/spi/spi.h> +#include <linux/spi/spi-mem.h> + +#define HISI_SFC_V3XX_VERSION (0x1f8) + +#define HISI_SFC_V3XX_CMD_CFG (0x300) +#define HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF 9 +#define HISI_SFC_V3XX_CMD_CFG_RW_MSK BIT(8) +#define HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK BIT(7) +#define HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF 4 +#define HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK BIT(3) +#define HISI_SFC_V3XX_CMD_CFG_CS_SEL_OFF 1 +#define HISI_SFC_V3XX_CMD_CFG_START_MSK BIT(0) +#define HISI_SFC_V3XX_CMD_INS (0x308) +#define HISI_SFC_V3XX_CMD_ADDR (0x30c) +#define HISI_SFC_V3XX_CMD_DATABUF0 (0x400) + +struct hisi_sfc_v3xx_host { + struct device *dev; + void __iomem *regbase; + int max_cmd_dword; +}; + +#define HISI_SFC_V3XX_WAIT_TIMEOUT_US 1000000 +#define HISI_SFC_V3XX_WAIT_POLL_INTERVAL_US 10 + +static int hisi_sfc_v3xx_wait_cmd_idle(struct hisi_sfc_v3xx_host *host) +{ + u32 reg; + + return readl_poll_timeout(host->regbase + HISI_SFC_V3XX_CMD_CFG, reg, + !(reg & HISI_SFC_V3XX_CMD_CFG_START_MSK), + HISI_SFC_V3XX_WAIT_POLL_INTERVAL_US, + HISI_SFC_V3XX_WAIT_TIMEOUT_US); +} + +static int hisi_sfc_v3xx_adjust_op_size(struct spi_mem *mem, + struct spi_mem_op *op) +{ + struct spi_device *spi = mem->spi; + struct hisi_sfc_v3xx_host *host; + uintptr_t addr = (uintptr_t)op->data.buf.in; + int max_byte_count; + + host = spi_controller_get_devdata(spi->master); + + max_byte_count = host->max_cmd_dword * 4; + + if (!IS_ALIGNED(addr, 4) && op->data.nbytes >= 4) + op->data.nbytes = 4 - (addr % 4); + else if (op->data.nbytes > max_byte_count) + op->data.nbytes = max_byte_count; + + return 0; +} + +/* + * memcpy_{to,from}io doesn't gurantee 32b accesses - which we require for the + * DATABUF registers -so use __io{read,write}32_copy when possible. For + * trailing bytes, copy them byte-by-byte from the DATABUF register, as we + * can't clobber outside the source/dest buffer. + * + * For efficient data read/write, we try to put any start 32b unaligned data + * into a separate transaction in hisi_sfc_v3xx_adjust_op_size(). + */ +static void hisi_sfc_v3xx_read_databuf(struct hisi_sfc_v3xx_host *host, + u8 *to, unsigned int len) +{ + void __iomem *from; + int i; + + from = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0; + + if (IS_ALIGNED((uintptr_t)to, 4)) { + int words = len / 4; + + __ioread32_copy(to, from, words); + + len -= words * 4; + if (len) { + u32 val; + + to += words * 4; + from += words * 4; + + val = __raw_readl(from); + + for (i = 0; i < len; i++, val >>= 8, to++) + *to = (u8)val; + } + } else { + for (i = 0; i < DIV_ROUND_UP(len, 4); i++, from += 4) { + u32 val = __raw_readl(from); + int j; + + for (j = 0; j < 4 && (j + (i * 4) < len); + to++, val >>= 8, j++) + *to = (u8)val; + } + } +} + +static void hisi_sfc_v3xx_write_databuf(struct hisi_sfc_v3xx_host *host, + const u8 *from, unsigned int len) +{ + void __iomem *to; + int i; + + to = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0; + + if (IS_ALIGNED((uintptr_t)from, 4)) { + int words = len / 4; + + __iowrite32_copy(to, from, words); + + len -= words * 4; + if (len) { + u32 val = 0; + + to += words * 4; + from += words * 4; + + for (i = 0; i < len; i++, from++) + val |= *from << i * 8; + __raw_writel(val, to); + } + + } else { + for (i = 0; i < DIV_ROUND_UP(len, 4); i++, to += 4) { + u32 val = 0; + int j; + + for (j = 0; j < 4 && (j + (i * 4) < len); + from++, j++) + val |= *from << j * 8; + __raw_writel(val, to); + } + } +} + +static int hisi_sfc_v3xx_generic_exec_op(struct hisi_sfc_v3xx_host *host, + const struct spi_mem_op *op, + u8 chip_select) +{ + int ret, len = op->data.nbytes; + u32 config = 0; + + if (op->addr.nbytes) + config |= HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK; + + if (op->data.dir != SPI_MEM_NO_DATA) { + config |= (len - 1) << HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF; + config |= HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK; + } + + if (op->data.dir == SPI_MEM_DATA_OUT) + hisi_sfc_v3xx_write_databuf(host, op->data.buf.out, len); + else if (op->data.dir == SPI_MEM_DATA_IN) + config |= HISI_SFC_V3XX_CMD_CFG_RW_MSK; + + config |= op->dummy.nbytes << HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF | + chip_select << HISI_SFC_V3XX_CMD_CFG_CS_SEL_OFF | + HISI_SFC_V3XX_CMD_CFG_START_MSK; + + writel(op->addr.val, host->regbase + HISI_SFC_V3XX_CMD_ADDR); + writel(op->cmd.opcode, host->regbase + HISI_SFC_V3XX_CMD_INS); + + writel(config, host->regbase + HISI_SFC_V3XX_CMD_CFG); + + ret = hisi_sfc_v3xx_wait_cmd_idle(host); + if (ret) + return ret; + + if (op->data.dir == SPI_MEM_DATA_IN) + hisi_sfc_v3xx_read_databuf(host, op->data.buf.in, len); + + return 0; +} + +static int hisi_sfc_v3xx_exec_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + struct hisi_sfc_v3xx_host *host; + struct spi_device *spi = mem->spi; + u8 chip_select = spi->chip_select; + + host = spi_controller_get_devdata(spi->master); + + return hisi_sfc_v3xx_generic_exec_op(host, op, chip_select); +} + +static const struct spi_controller_mem_ops hisi_sfc_v3xx_mem_ops = { + .adjust_op_size = hisi_sfc_v3xx_adjust_op_size, + .exec_op = hisi_sfc_v3xx_exec_op, +}; + +static int hisi_sfc_v3xx_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct hisi_sfc_v3xx_host *host; + struct spi_controller *ctlr; + u32 version; + int ret; + + ctlr = spi_alloc_master(&pdev->dev, sizeof(*host)); + if (!ctlr) + return -ENOMEM; + + ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | + SPI_TX_DUAL | SPI_TX_QUAD; + + host = spi_controller_get_devdata(ctlr); + host->dev = dev; + + platform_set_drvdata(pdev, host); + + host->regbase = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(host->regbase)) { + ret = PTR_ERR(host->regbase); + goto err_put_master; + } + + ctlr->bus_num = -1; + ctlr->num_chipselect = 1; + ctlr->mem_ops = &hisi_sfc_v3xx_mem_ops; + + version = readl(host->regbase + HISI_SFC_V3XX_VERSION); + + switch (version) { + case 0x351: + host->max_cmd_dword = 64; + break; + default: + host->max_cmd_dword = 16; + break; + } + + ret = devm_spi_register_controller(dev, ctlr); + if (ret) + goto err_put_master; + + dev_info(&pdev->dev, "hw version 0x%x\n", version); + + return 0; + +err_put_master: + spi_master_put(ctlr); + return ret; +} + +#if IS_ENABLED(CONFIG_ACPI) +static const struct acpi_device_id hisi_sfc_v3xx_acpi_ids[] = { + {"HISI0341", 0}, + {} +}; +MODULE_DEVICE_TABLE(acpi, hisi_sfc_v3xx_acpi_ids); +#endif + +static struct platform_driver hisi_sfc_v3xx_spi_driver = { + .driver = { + .name = "hisi-sfc-v3xx", + .acpi_match_table = ACPI_PTR(hisi_sfc_v3xx_acpi_ids), + }, + .probe = hisi_sfc_v3xx_probe, +}; + +module_platform_driver(hisi_sfc_v3xx_spi_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("John Garry <john.garry@huawei.com>"); +MODULE_DESCRIPTION("HiSilicon SPI NOR V3XX Flash Controller Driver for hi16xx chipsets"); diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 439b01e4a2c8..8543f5ed1099 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -666,13 +666,29 @@ static int img_spfi_probe(struct platform_device *pdev) master->unprepare_message = img_spfi_unprepare; master->handle_err = img_spfi_handle_err; - spfi->tx_ch = dma_request_slave_channel(spfi->dev, "tx"); - spfi->rx_ch = dma_request_slave_channel(spfi->dev, "rx"); + spfi->tx_ch = dma_request_chan(spfi->dev, "tx"); + if (IS_ERR(spfi->tx_ch)) { + ret = PTR_ERR(spfi->tx_ch); + spfi->tx_ch = NULL; + if (ret == -EPROBE_DEFER) + goto disable_pm; + } + + spfi->rx_ch = dma_request_chan(spfi->dev, "rx"); + if (IS_ERR(spfi->rx_ch)) { + ret = PTR_ERR(spfi->rx_ch); + spfi->rx_ch = NULL; + if (ret == -EPROBE_DEFER) + goto disable_pm; + } + if (!spfi->tx_ch || !spfi->rx_ch) { if (spfi->tx_ch) dma_release_channel(spfi->tx_ch); if (spfi->rx_ch) dma_release_channel(spfi->rx_ch); + spfi->tx_ch = NULL; + spfi->rx_ch = NULL; dev_warn(spfi->dev, "Failed to get DMA channels, falling back to PIO mode\n"); } else { master->dma_tx = spfi->tx_ch; diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 09c9a1edb2c6..f4f28a400a96 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1230,9 +1230,9 @@ static int spi_imx_setupxfer(struct spi_device *spi, } if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t)) - spi_imx->usedma = 1; + spi_imx->usedma = true; else - spi_imx->usedma = 0; + spi_imx->usedma = false; if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) { spi_imx->rx = mx53_ecspi_rx_slave; @@ -1272,7 +1272,7 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, spi_imx->wml = spi_imx->devtype_data->fifo_size / 2; /* Prepare for TX DMA: */ - master->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + master->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR(master->dma_tx)) { ret = PTR_ERR(master->dma_tx); dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret); @@ -1281,7 +1281,7 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, } /* Prepare for RX : */ - master->dma_rx = dma_request_slave_channel_reason(dev, "rx"); + master->dma_rx = dma_request_chan(dev, "rx"); if (IS_ERR(master->dma_rx)) { ret = PTR_ERR(master->dma_rx); dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret); diff --git a/drivers/spi/spi-jcore.c b/drivers/spi/spi-jcore.c index cc49fa41fbab..bba10f030e33 100644 --- a/drivers/spi/spi-jcore.c +++ b/drivers/spi/spi-jcore.c @@ -170,7 +170,7 @@ static int jcore_spi_probe(struct platform_device *pdev) if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), pdev->name)) goto exit_busy; - hw->base = devm_ioremap_nocache(&pdev->dev, res->start, + hw->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!hw->base) goto exit_busy; diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index 8f01858c0ae6..1fd7ee53d451 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -797,7 +797,6 @@ static int lantiq_ssc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct spi_master *master; - struct resource *res; struct lantiq_ssc_spi *spi; const struct lantiq_ssc_hwcfg *hwcfg; const struct of_device_id *match; @@ -812,29 +811,17 @@ static int lantiq_ssc_probe(struct platform_device *pdev) } hwcfg = match->data; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "failed to get resources\n"); - return -ENXIO; - } - rx_irq = platform_get_irq_byname(pdev, LTQ_SPI_RX_IRQ_NAME); - if (rx_irq < 0) { - dev_err(dev, "failed to get %s\n", LTQ_SPI_RX_IRQ_NAME); + if (rx_irq < 0) return -ENXIO; - } tx_irq = platform_get_irq_byname(pdev, LTQ_SPI_TX_IRQ_NAME); - if (tx_irq < 0) { - dev_err(dev, "failed to get %s\n", LTQ_SPI_TX_IRQ_NAME); + if (tx_irq < 0) return -ENXIO; - } err_irq = platform_get_irq_byname(pdev, LTQ_SPI_ERR_IRQ_NAME); - if (err_irq < 0) { - dev_err(dev, "failed to get %s\n", LTQ_SPI_ERR_IRQ_NAME); + if (err_irq < 0) return -ENXIO; - } master = spi_alloc_master(dev, sizeof(struct lantiq_ssc_spi)); if (!master) @@ -845,8 +832,7 @@ static int lantiq_ssc_probe(struct platform_device *pdev) spi->dev = dev; spi->hwcfg = hwcfg; platform_set_drvdata(pdev, spi); - - spi->regbase = devm_ioremap_resource(dev, res); + spi->regbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi->regbase)) { err = PTR_ERR(spi->regbase); goto err_master_put; diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c index f18f912c9dea..174dba29b1dd 100644 --- a/drivers/spi/spi-lm70llp.c +++ b/drivers/spi/spi-lm70llp.c @@ -34,7 +34,7 @@ * available (on page 4) here: * http://www.national.com/appinfo/tempsensors/files/LM70LLPEVALmanual.pdf * - * Also see Documentation/spi/spi-lm70llp. The SPI<->parport code here is + * Also see Documentation/spi/spi-lm70llp.rst. The SPI<->parport code here is * (heavily) based on spi-butterfly by David Brownell. * * The LM70 LLP connects to the PC parallel port in the following manner: diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c index 6f18d4952767..b6d79cd156fb 100644 --- a/drivers/spi/spi-loopback-test.c +++ b/drivers/spi/spi-loopback-test.c @@ -298,12 +298,18 @@ static struct spi_test spi_tests[] = { { .tx_buf = TX(0), .rx_buf = RX(0), - .delay_usecs = 1000, + .delay = { + .value = 1000, + .unit = SPI_DELAY_UNIT_USECS, + }, }, { .tx_buf = TX(0), .rx_buf = RX(0), - .delay_usecs = 1000, + .delay = { + .value = 1000, + .unit = SPI_DELAY_UNIT_USECS, + }, }, }, }, @@ -537,7 +543,7 @@ static int spi_test_check_elapsed_time(struct spi_device *spi, unsigned long long nbits = (unsigned long long)BITS_PER_BYTE * xfer->len; - delay_usecs += xfer->delay_usecs; + delay_usecs += xfer->delay.value; if (!xfer->speed_hz) continue; estimated_time += div_u64(nbits * NSEC_PER_SEC, xfer->speed_hz); diff --git a/drivers/spi/spi-lp8841-rtc.c b/drivers/spi/spi-lp8841-rtc.c index f50779fd329c..2d436541d6c2 100644 --- a/drivers/spi/spi-lp8841-rtc.c +++ b/drivers/spi/spi-lp8841-rtc.c @@ -185,7 +185,6 @@ spi_lp8841_rtc_probe(struct platform_device *pdev) int ret; struct spi_master *master; struct spi_lp8841_rtc *data; - void *iomem; master = spi_alloc_master(&pdev->dev, sizeof(*data)); if (!master) @@ -207,8 +206,7 @@ spi_lp8841_rtc_probe(struct platform_device *pdev) data = spi_master_get_devdata(master); - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->iomem = devm_ioremap_resource(&pdev->dev, iomem); + data->iomem = devm_platform_ioremap_resource(pdev, 0); ret = PTR_ERR_OR_ZERO(data->iomem); if (ret) { dev_err(&pdev->dev, "failed to get IO address\n"); diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 9f0fa9f3116d..e5a46f0eb93b 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -286,7 +286,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) if (!spi_mem_internal_supports_op(mem, op)) return -ENOTSUPP; - if (ctlr->mem_ops) { + if (ctlr->mem_ops && !mem->spi->cs_gpiod) { ret = spi_mem_access_start(mem); if (ret) return ret; diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index 7fe4488ace57..7f5680fe2568 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -19,7 +19,6 @@ #include <linux/types.h> #include <linux/interrupt.h> #include <linux/reset.h> -#include <linux/gpio.h> /* * The Meson SPICC controller could support DMA based transfers, but is not @@ -467,35 +466,14 @@ static int meson_spicc_unprepare_transfer(struct spi_master *master) static int meson_spicc_setup(struct spi_device *spi) { - int ret = 0; - if (!spi->controller_state) spi->controller_state = spi_master_get_devdata(spi->master); - else if (gpio_is_valid(spi->cs_gpio)) - goto out_gpio; - else if (spi->cs_gpio == -ENOENT) - return 0; - - if (gpio_is_valid(spi->cs_gpio)) { - ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev)); - if (ret) { - dev_err(&spi->dev, "failed to request cs gpio\n"); - return ret; - } - } - -out_gpio: - ret = gpio_direction_output(spi->cs_gpio, - !(spi->mode & SPI_CS_HIGH)); - return ret; + return 0; } static void meson_spicc_cleanup(struct spi_device *spi) { - if (gpio_is_valid(spi->cs_gpio)) - gpio_free(spi->cs_gpio); - spi->controller_state = NULL; } @@ -503,7 +481,6 @@ static int meson_spicc_probe(struct platform_device *pdev) { struct spi_master *master; struct meson_spicc_device *spicc; - struct resource *res; int ret, irq, rate; master = spi_alloc_master(&pdev->dev, sizeof(*spicc)); @@ -517,8 +494,7 @@ static int meson_spicc_probe(struct platform_device *pdev) spicc->pdev = pdev; platform_set_drvdata(pdev, spicc); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spicc->base = devm_ioremap_resource(&pdev->dev, res); + spicc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spicc->base)) { dev_err(&pdev->dev, "io resource mapping failed\n"); ret = PTR_ERR(spicc->base); @@ -566,6 +542,7 @@ static int meson_spicc_probe(struct platform_device *pdev) master->prepare_message = meson_spicc_prepare_message; master->unprepare_transfer_hardware = meson_spicc_unprepare_transfer; master->transfer_one = meson_spicc_transfer_one; + master->use_gpio_descriptors = true; /* Setup max rate according to the Meson GX datasheet */ if ((rate >> 2) > SPICC_MAX_FREQ) diff --git a/drivers/spi/spi-meson-spifc.c b/drivers/spi/spi-meson-spifc.c index f7fe9b13d122..c7b039980291 100644 --- a/drivers/spi/spi-meson-spifc.c +++ b/drivers/spi/spi-meson-spifc.c @@ -286,7 +286,6 @@ static int meson_spifc_probe(struct platform_device *pdev) { struct spi_master *master; struct meson_spifc *spifc; - struct resource *res; void __iomem *base; unsigned int rate; int ret = 0; @@ -300,8 +299,7 @@ static int meson_spifc_probe(struct platform_device *pdev) spifc = spi_master_get_devdata(master); spifc->dev = &pdev->dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(spifc->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) { ret = PTR_ERR(base); goto out_err; diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index a337b842ae8c..ea1b07953d38 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -311,8 +311,7 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master, break; m->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (cs_change) mpc512x_psc_spi_deactivate_cs(spi); diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c index c7e478b9b586..17935e71b02f 100644 --- a/drivers/spi/spi-mpc52xx-psc.c +++ b/drivers/spi/spi-mpc52xx-psc.c @@ -234,8 +234,7 @@ static void mpc52xx_psc_spi_work(struct work_struct *work) break; m->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (cs_change) mpc52xx_psc_spi_deactivate_cs(spi); diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 45d8a7048b6c..6783e12c40c2 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -17,6 +17,7 @@ #include <linux/platform_data/spi-mt65xx.h> #include <linux/pm_runtime.h> #include <linux/spi/spi.h> +#include <linux/dma-mapping.h> #define SPI_CFG0_REG 0x0000 #define SPI_CFG1_REG 0x0004 @@ -28,6 +29,8 @@ #define SPI_STATUS0_REG 0x001c #define SPI_PAD_SEL_REG 0x0024 #define SPI_CFG2_REG 0x0028 +#define SPI_TX_SRC_REG_64 0x002c +#define SPI_RX_DST_REG_64 0x0030 #define SPI_CFG0_SCK_HIGH_OFFSET 0 #define SPI_CFG0_SCK_LOW_OFFSET 8 @@ -73,6 +76,10 @@ #define MTK_SPI_MAX_FIFO_SIZE 32U #define MTK_SPI_PACKET_SIZE 1024 +#define MTK_SPI_32BITS_MASK (0xffffffff) + +#define DMA_ADDR_EXT_BITS (36) +#define DMA_ADDR_DEF_BITS (32) struct mtk_spi_compatible { bool need_pad_sel; @@ -80,6 +87,8 @@ struct mtk_spi_compatible { bool must_tx; /* some IC design adjust cfg register to enhance time accuracy */ bool enhance_timing; + /* some IC support DMA addr extension */ + bool dma_ext; }; struct mtk_spi { @@ -102,6 +111,13 @@ static const struct mtk_spi_compatible mt2712_compat = { .must_tx = true, }; +static const struct mtk_spi_compatible mt6765_compat = { + .need_pad_sel = true, + .must_tx = true, + .enhance_timing = true, + .dma_ext = true, +}; + static const struct mtk_spi_compatible mt7622_compat = { .must_tx = true, .enhance_timing = true, @@ -123,7 +139,6 @@ static const struct mtk_spi_compatible mt8183_compat = { * supplies it. */ static const struct mtk_chip_config mtk_default_chip_info = { - .cs_pol = 0, .sample_sel = 0, }; @@ -137,6 +152,9 @@ static const struct of_device_id mtk_spi_of_match[] = { { .compatible = "mediatek,mt6589-spi", .data = (void *)&mtk_common_compat, }, + { .compatible = "mediatek,mt6765-spi", + .data = (void *)&mt6765_compat, + }, { .compatible = "mediatek,mt7622-spi", .data = (void *)&mt7622_compat, }, @@ -211,10 +229,12 @@ static int mtk_spi_prepare_message(struct spi_master *master, #endif if (mdata->dev_comp->enhance_timing) { - if (chip_config->cs_pol) + /* set CS polarity */ + if (spi->mode & SPI_CS_HIGH) reg_val |= SPI_CMD_CS_POL; else reg_val &= ~SPI_CMD_CS_POL; + if (chip_config->sample_sel) reg_val |= SPI_CMD_SAMPLE_SEL; else @@ -245,6 +265,9 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable) u32 reg_val; struct mtk_spi *mdata = spi_master_get_devdata(spi->master); + if (spi->mode & SPI_CS_HIGH) + enable = !enable; + reg_val = readl(mdata->base + SPI_CMD_REG); if (!enable) { reg_val |= SPI_CMD_PAUSE_EN; @@ -371,10 +394,25 @@ static void mtk_spi_setup_dma_addr(struct spi_master *master, { struct mtk_spi *mdata = spi_master_get_devdata(master); - if (mdata->tx_sgl) - writel(xfer->tx_dma, mdata->base + SPI_TX_SRC_REG); - if (mdata->rx_sgl) - writel(xfer->rx_dma, mdata->base + SPI_RX_DST_REG); + if (mdata->tx_sgl) { + writel((u32)(xfer->tx_dma & MTK_SPI_32BITS_MASK), + mdata->base + SPI_TX_SRC_REG); +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + if (mdata->dev_comp->dma_ext) + writel((u32)(xfer->tx_dma >> 32), + mdata->base + SPI_TX_SRC_REG_64); +#endif + } + + if (mdata->rx_sgl) { + writel((u32)(xfer->rx_dma & MTK_SPI_32BITS_MASK), + mdata->base + SPI_RX_DST_REG); +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT + if (mdata->dev_comp->dma_ext) + writel((u32)(xfer->rx_dma >> 32), + mdata->base + SPI_RX_DST_REG_64); +#endif + } } static int mtk_spi_fifo_transfer(struct spi_master *master, @@ -585,8 +623,7 @@ static int mtk_spi_probe(struct platform_device *pdev) struct spi_master *master; struct mtk_spi *mdata; const struct of_device_id *of_id; - struct resource *res; - int i, irq, ret; + int i, irq, ret, addr_bits; master = spi_alloc_master(&pdev->dev, sizeof(*mdata)); if (!master) { @@ -613,6 +650,10 @@ static int mtk_spi_probe(struct platform_device *pdev) mdata = spi_master_get_devdata(master); mdata->dev_comp = of_id->data; + + if (mdata->dev_comp->enhance_timing) + master->mode_bits |= SPI_CS_HIGH; + if (mdata->dev_comp->must_tx) master->flags = SPI_MASTER_MUST_TX; @@ -648,15 +689,7 @@ static int mtk_spi_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, master); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENODEV; - dev_err(&pdev->dev, "failed to determine base address\n"); - goto err_put_master; - } - - mdata->base = devm_ioremap_resource(&pdev->dev, res); + mdata->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mdata->base)) { ret = PTR_ERR(mdata->base); goto err_put_master; @@ -664,7 +697,6 @@ static int mtk_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq (%d)\n", irq); ret = irq; goto err_put_master; } @@ -753,6 +785,15 @@ static int mtk_spi_probe(struct platform_device *pdev) } } + if (mdata->dev_comp->dma_ext) + addr_bits = DMA_ADDR_EXT_BITS; + else + addr_bits = DMA_ADDR_DEF_BITS; + ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(addr_bits)); + if (ret) + dev_notice(&pdev->dev, "SPI dma_set_mask(%d) failed, ret:%d\n", + addr_bits, ret); + return 0; err_disable_runtime_pm: diff --git a/drivers/spi/spi-mt7621.c b/drivers/spi/spi-mt7621.c index ff85982464d2..2c3b7a2a1ec7 100644 --- a/drivers/spi/spi-mt7621.c +++ b/drivers/spi/spi-mt7621.c @@ -327,7 +327,6 @@ static int mt7621_spi_probe(struct platform_device *pdev) struct spi_controller *master; struct mt7621_spi *rs; void __iomem *base; - struct resource *r; int status = 0; struct clk *clk; int ret; @@ -336,8 +335,7 @@ static int mt7621_spi_probe(struct platform_device *pdev) if (!match) return -EINVAL; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, r); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c index f48563c09b97..69491f3a515d 100644 --- a/drivers/spi/spi-mxic.c +++ b/drivers/spi/spi-mxic.c @@ -145,8 +145,8 @@ #define LWR_SUSP_CTRL_EN BIT(31) #define DMAS_CTRL 0x9c -#define DMAS_CTRL_DIR_READ BIT(31) -#define DMAS_CTRL_EN BIT(30) +#define DMAS_CTRL_EN BIT(31) +#define DMAS_CTRL_DIR_READ BIT(30) #define DATA_STROB 0xa0 #define DATA_STROB_EDO_EN BIT(2) @@ -275,7 +275,7 @@ static void mxic_spi_hw_init(struct mxic_spi *mxic) writel(0, mxic->regs + HC_EN); writel(0, mxic->regs + LRD_CFG); writel(0, mxic->regs + LRD_CTRL); - writel(HC_CFG_NIO(1) | HC_CFG_TYPE(0, HC_CFG_TYPE_SPI_NAND) | + writel(HC_CFG_NIO(1) | HC_CFG_TYPE(0, HC_CFG_TYPE_SPI_NOR) | HC_CFG_SLV_ACT(0) | HC_CFG_MAN_CS_EN | HC_CFG_IDLE_SIO_LVL(1), mxic->regs + HC_CFG); } @@ -346,7 +346,7 @@ static bool mxic_spi_mem_supports_op(struct spi_mem *mem, if (op->addr.nbytes > 7) return false; - return true; + return spi_mem_default_supports_op(mem, op); } static int mxic_spi_mem_exec_op(struct spi_mem *mem, diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 7bf53cfc25d6..dce85ee07cd0 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -532,7 +532,6 @@ static int mxs_spi_probe(struct platform_device *pdev) struct spi_master *master; struct mxs_spi *spi; struct mxs_ssp *ssp; - struct resource *iores; struct clk *clk; void __iomem *base; int devid, clk_freq; @@ -545,12 +544,11 @@ static int mxs_spi_probe(struct platform_device *pdev) */ const int clk_freq_default = 160000000; - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq_err = platform_get_irq(pdev, 0); if (irq_err < 0) return irq_err; - base = devm_ioremap_resource(&pdev->dev, iores); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); @@ -592,10 +590,10 @@ static int mxs_spi_probe(struct platform_device *pdev) if (ret) goto out_master_free; - ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx"); - if (!ssp->dmach) { + ssp->dmach = dma_request_chan(&pdev->dev, "rx-tx"); + if (IS_ERR(ssp->dmach)) { dev_err(ssp->dev, "Failed to request DMA\n"); - ret = -ENODEV; + ret = PTR_ERR(ssp->dmach); goto out_master_free; } diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c new file mode 100644 index 000000000000..d25ee32862e0 --- /dev/null +++ b/drivers/spi/spi-npcm-fiu.c @@ -0,0 +1,769 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Nuvoton Technology corporation. + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/vmalloc.h> +#include <linux/regmap.h> +#include <linux/of_device.h> +#include <linux/spi/spi-mem.h> +#include <linux/mfd/syscon.h> + +/* NPCM7xx GCR module */ +#define NPCM7XX_INTCR3_OFFSET 0x9C +#define NPCM7XX_INTCR3_FIU_FIX BIT(6) + +/* Flash Interface Unit (FIU) Registers */ +#define NPCM_FIU_DRD_CFG 0x00 +#define NPCM_FIU_DWR_CFG 0x04 +#define NPCM_FIU_UMA_CFG 0x08 +#define NPCM_FIU_UMA_CTS 0x0C +#define NPCM_FIU_UMA_CMD 0x10 +#define NPCM_FIU_UMA_ADDR 0x14 +#define NPCM_FIU_PRT_CFG 0x18 +#define NPCM_FIU_UMA_DW0 0x20 +#define NPCM_FIU_UMA_DW1 0x24 +#define NPCM_FIU_UMA_DW2 0x28 +#define NPCM_FIU_UMA_DW3 0x2C +#define NPCM_FIU_UMA_DR0 0x30 +#define NPCM_FIU_UMA_DR1 0x34 +#define NPCM_FIU_UMA_DR2 0x38 +#define NPCM_FIU_UMA_DR3 0x3C +#define NPCM_FIU_MAX_REG_LIMIT 0x80 + +/* FIU Direct Read Configuration Register */ +#define NPCM_FIU_DRD_CFG_LCK BIT(31) +#define NPCM_FIU_DRD_CFG_R_BURST GENMASK(25, 24) +#define NPCM_FIU_DRD_CFG_ADDSIZ GENMASK(17, 16) +#define NPCM_FIU_DRD_CFG_DBW GENMASK(13, 12) +#define NPCM_FIU_DRD_CFG_ACCTYPE GENMASK(9, 8) +#define NPCM_FIU_DRD_CFG_RDCMD GENMASK(7, 0) +#define NPCM_FIU_DRD_ADDSIZ_SHIFT 16 +#define NPCM_FIU_DRD_DBW_SHIFT 12 +#define NPCM_FIU_DRD_ACCTYPE_SHIFT 8 + +/* FIU Direct Write Configuration Register */ +#define NPCM_FIU_DWR_CFG_LCK BIT(31) +#define NPCM_FIU_DWR_CFG_W_BURST GENMASK(25, 24) +#define NPCM_FIU_DWR_CFG_ADDSIZ GENMASK(17, 16) +#define NPCM_FIU_DWR_CFG_ABPCK GENMASK(11, 10) +#define NPCM_FIU_DWR_CFG_DBPCK GENMASK(9, 8) +#define NPCM_FIU_DWR_CFG_WRCMD GENMASK(7, 0) +#define NPCM_FIU_DWR_ADDSIZ_SHIFT 16 +#define NPCM_FIU_DWR_ABPCK_SHIFT 10 +#define NPCM_FIU_DWR_DBPCK_SHIFT 8 + +/* FIU UMA Configuration Register */ +#define NPCM_FIU_UMA_CFG_LCK BIT(31) +#define NPCM_FIU_UMA_CFG_CMMLCK BIT(30) +#define NPCM_FIU_UMA_CFG_RDATSIZ GENMASK(28, 24) +#define NPCM_FIU_UMA_CFG_DBSIZ GENMASK(23, 21) +#define NPCM_FIU_UMA_CFG_WDATSIZ GENMASK(20, 16) +#define NPCM_FIU_UMA_CFG_ADDSIZ GENMASK(13, 11) +#define NPCM_FIU_UMA_CFG_CMDSIZ BIT(10) +#define NPCM_FIU_UMA_CFG_RDBPCK GENMASK(9, 8) +#define NPCM_FIU_UMA_CFG_DBPCK GENMASK(7, 6) +#define NPCM_FIU_UMA_CFG_WDBPCK GENMASK(5, 4) +#define NPCM_FIU_UMA_CFG_ADBPCK GENMASK(3, 2) +#define NPCM_FIU_UMA_CFG_CMBPCK GENMASK(1, 0) +#define NPCM_FIU_UMA_CFG_ADBPCK_SHIFT 2 +#define NPCM_FIU_UMA_CFG_WDBPCK_SHIFT 4 +#define NPCM_FIU_UMA_CFG_DBPCK_SHIFT 6 +#define NPCM_FIU_UMA_CFG_RDBPCK_SHIFT 8 +#define NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT 11 +#define NPCM_FIU_UMA_CFG_WDATSIZ_SHIFT 16 +#define NPCM_FIU_UMA_CFG_DBSIZ_SHIFT 21 +#define NPCM_FIU_UMA_CFG_RDATSIZ_SHIFT 24 + +/* FIU UMA Control and Status Register */ +#define NPCM_FIU_UMA_CTS_RDYIE BIT(25) +#define NPCM_FIU_UMA_CTS_RDYST BIT(24) +#define NPCM_FIU_UMA_CTS_SW_CS BIT(16) +#define NPCM_FIU_UMA_CTS_DEV_NUM GENMASK(9, 8) +#define NPCM_FIU_UMA_CTS_EXEC_DONE BIT(0) +#define NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT 8 + +/* FIU UMA Command Register */ +#define NPCM_FIU_UMA_CMD_DUM3 GENMASK(31, 24) +#define NPCM_FIU_UMA_CMD_DUM2 GENMASK(23, 16) +#define NPCM_FIU_UMA_CMD_DUM1 GENMASK(15, 8) +#define NPCM_FIU_UMA_CMD_CMD GENMASK(7, 0) + +/* FIU UMA Address Register */ +#define NPCM_FIU_UMA_ADDR_UMA_ADDR GENMASK(31, 0) +#define NPCM_FIU_UMA_ADDR_AB3 GENMASK(31, 24) +#define NPCM_FIU_UMA_ADDR_AB2 GENMASK(23, 16) +#define NPCM_FIU_UMA_ADDR_AB1 GENMASK(15, 8) +#define NPCM_FIU_UMA_ADDR_AB0 GENMASK(7, 0) + +/* FIU UMA Write Data Bytes 0-3 Register */ +#define NPCM_FIU_UMA_DW0_WB3 GENMASK(31, 24) +#define NPCM_FIU_UMA_DW0_WB2 GENMASK(23, 16) +#define NPCM_FIU_UMA_DW0_WB1 GENMASK(15, 8) +#define NPCM_FIU_UMA_DW0_WB0 GENMASK(7, 0) + +/* FIU UMA Write Data Bytes 4-7 Register */ +#define NPCM_FIU_UMA_DW1_WB7 GENMASK(31, 24) +#define NPCM_FIU_UMA_DW1_WB6 GENMASK(23, 16) +#define NPCM_FIU_UMA_DW1_WB5 GENMASK(15, 8) +#define NPCM_FIU_UMA_DW1_WB4 GENMASK(7, 0) + +/* FIU UMA Write Data Bytes 8-11 Register */ +#define NPCM_FIU_UMA_DW2_WB11 GENMASK(31, 24) +#define NPCM_FIU_UMA_DW2_WB10 GENMASK(23, 16) +#define NPCM_FIU_UMA_DW2_WB9 GENMASK(15, 8) +#define NPCM_FIU_UMA_DW2_WB8 GENMASK(7, 0) + +/* FIU UMA Write Data Bytes 12-15 Register */ +#define NPCM_FIU_UMA_DW3_WB15 GENMASK(31, 24) +#define NPCM_FIU_UMA_DW3_WB14 GENMASK(23, 16) +#define NPCM_FIU_UMA_DW3_WB13 GENMASK(15, 8) +#define NPCM_FIU_UMA_DW3_WB12 GENMASK(7, 0) + +/* FIU UMA Read Data Bytes 0-3 Register */ +#define NPCM_FIU_UMA_DR0_RB3 GENMASK(31, 24) +#define NPCM_FIU_UMA_DR0_RB2 GENMASK(23, 16) +#define NPCM_FIU_UMA_DR0_RB1 GENMASK(15, 8) +#define NPCM_FIU_UMA_DR0_RB0 GENMASK(7, 0) + +/* FIU UMA Read Data Bytes 4-7 Register */ +#define NPCM_FIU_UMA_DR1_RB15 GENMASK(31, 24) +#define NPCM_FIU_UMA_DR1_RB14 GENMASK(23, 16) +#define NPCM_FIU_UMA_DR1_RB13 GENMASK(15, 8) +#define NPCM_FIU_UMA_DR1_RB12 GENMASK(7, 0) + +/* FIU UMA Read Data Bytes 8-11 Register */ +#define NPCM_FIU_UMA_DR2_RB15 GENMASK(31, 24) +#define NPCM_FIU_UMA_DR2_RB14 GENMASK(23, 16) +#define NPCM_FIU_UMA_DR2_RB13 GENMASK(15, 8) +#define NPCM_FIU_UMA_DR2_RB12 GENMASK(7, 0) + +/* FIU UMA Read Data Bytes 12-15 Register */ +#define NPCM_FIU_UMA_DR3_RB15 GENMASK(31, 24) +#define NPCM_FIU_UMA_DR3_RB14 GENMASK(23, 16) +#define NPCM_FIU_UMA_DR3_RB13 GENMASK(15, 8) +#define NPCM_FIU_UMA_DR3_RB12 GENMASK(7, 0) + +/* FIU Read Mode */ +enum { + DRD_SINGLE_WIRE_MODE = 0, + DRD_DUAL_IO_MODE = 1, + DRD_QUAD_IO_MODE = 2, + DRD_SPI_X_MODE = 3, +}; + +enum { + DWR_ABPCK_BIT_PER_CLK = 0, + DWR_ABPCK_2_BIT_PER_CLK = 1, + DWR_ABPCK_4_BIT_PER_CLK = 2, +}; + +enum { + DWR_DBPCK_BIT_PER_CLK = 0, + DWR_DBPCK_2_BIT_PER_CLK = 1, + DWR_DBPCK_4_BIT_PER_CLK = 2, +}; + +#define NPCM_FIU_DRD_16_BYTE_BURST 0x3000000 +#define NPCM_FIU_DWR_16_BYTE_BURST 0x3000000 + +#define MAP_SIZE_128MB 0x8000000 +#define MAP_SIZE_16MB 0x1000000 +#define MAP_SIZE_8MB 0x800000 + +#define NUM_BITS_IN_BYTE 8 +#define FIU_DRD_MAX_DUMMY_NUMBER 3 +#define NPCM_MAX_CHIP_NUM 4 +#define CHUNK_SIZE 16 +#define UMA_MICRO_SEC_TIMEOUT 150 + +enum { + FIU0 = 0, + FIU3, + FIUX, +}; + +struct npcm_fiu_info { + char *name; + u32 fiu_id; + u32 max_map_size; + u32 max_cs; +}; + +struct fiu_data { + const struct npcm_fiu_info *npcm_fiu_data_info; + int fiu_max; +}; + +static const struct npcm_fiu_info npxm7xx_fiu_info[] = { + {.name = "FIU0", .fiu_id = FIU0, + .max_map_size = MAP_SIZE_128MB, .max_cs = 2}, + {.name = "FIU3", .fiu_id = FIU3, + .max_map_size = MAP_SIZE_128MB, .max_cs = 4}, + {.name = "FIUX", .fiu_id = FIUX, + .max_map_size = MAP_SIZE_16MB, .max_cs = 2} }; + +static const struct fiu_data npxm7xx_fiu_data = { + .npcm_fiu_data_info = npxm7xx_fiu_info, + .fiu_max = 3, +}; + +struct npcm_fiu_spi; + +struct npcm_fiu_chip { + void __iomem *flash_region_mapped_ptr; + struct npcm_fiu_spi *fiu; + unsigned long clkrate; + u32 chipselect; +}; + +struct npcm_fiu_spi { + struct npcm_fiu_chip chip[NPCM_MAX_CHIP_NUM]; + const struct npcm_fiu_info *info; + struct spi_mem_op drd_op; + struct resource *res_mem; + struct regmap *regmap; + unsigned long clkrate; + struct device *dev; + struct clk *clk; + bool spix_mode; +}; + +static const struct regmap_config npcm_mtd_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = NPCM_FIU_MAX_REG_LIMIT, +}; + +static void npcm_fiu_set_drd(struct npcm_fiu_spi *fiu, + const struct spi_mem_op *op) +{ + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_ACCTYPE, + ilog2(op->addr.buswidth) << + NPCM_FIU_DRD_ACCTYPE_SHIFT); + fiu->drd_op.addr.buswidth = op->addr.buswidth; + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_DBW, + ((op->dummy.nbytes * ilog2(op->addr.buswidth)) + / NUM_BITS_IN_BYTE) << NPCM_FIU_DRD_DBW_SHIFT); + fiu->drd_op.dummy.nbytes = op->dummy.nbytes; + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_RDCMD, op->cmd.opcode); + fiu->drd_op.cmd.opcode = op->cmd.opcode; + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_ADDSIZ, + (op->addr.nbytes - 3) << NPCM_FIU_DRD_ADDSIZ_SHIFT); + fiu->drd_op.addr.nbytes = op->addr.nbytes; +} + +static ssize_t npcm_fiu_direct_read(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, void *buf) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(desc->mem->spi->master); + struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select]; + void __iomem *src = (void __iomem *)(chip->flash_region_mapped_ptr + + offs); + u8 *buf_rx = buf; + u32 i; + + if (fiu->spix_mode) { + for (i = 0 ; i < len ; i++) + *(buf_rx + i) = ioread8(src + i); + } else { + if (desc->info.op_tmpl.addr.buswidth != fiu->drd_op.addr.buswidth || + desc->info.op_tmpl.dummy.nbytes != fiu->drd_op.dummy.nbytes || + desc->info.op_tmpl.cmd.opcode != fiu->drd_op.cmd.opcode || + desc->info.op_tmpl.addr.nbytes != fiu->drd_op.addr.nbytes) + npcm_fiu_set_drd(fiu, &desc->info.op_tmpl); + + memcpy_fromio(buf_rx, src, len); + } + + return len; +} + +static ssize_t npcm_fiu_direct_write(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, const void *buf) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(desc->mem->spi->master); + struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select]; + void __iomem *dst = (void __iomem *)(chip->flash_region_mapped_ptr + + offs); + const u8 *buf_tx = buf; + u32 i; + + if (fiu->spix_mode) + for (i = 0 ; i < len ; i++) + iowrite8(*(buf_tx + i), dst + i); + else + memcpy_toio(dst, buf_tx, len); + + return len; +} + +static int npcm_fiu_uma_read(struct spi_mem *mem, + const struct spi_mem_op *op, u32 addr, + bool is_address_size, u8 *data, u32 data_size) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(mem->spi->master); + u32 uma_cfg = BIT(10); + u32 data_reg[4]; + int ret; + u32 val; + u32 i; + + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_DEV_NUM, + (mem->spi->chip_select << + NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT)); + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CMD, + NPCM_FIU_UMA_CMD_CMD, op->cmd.opcode); + + if (is_address_size) { + uma_cfg |= ilog2(op->cmd.buswidth); + uma_cfg |= ilog2(op->addr.buswidth) + << NPCM_FIU_UMA_CFG_ADBPCK_SHIFT; + uma_cfg |= ilog2(op->dummy.buswidth) + << NPCM_FIU_UMA_CFG_DBPCK_SHIFT; + uma_cfg |= ilog2(op->data.buswidth) + << NPCM_FIU_UMA_CFG_RDBPCK_SHIFT; + uma_cfg |= op->dummy.nbytes << NPCM_FIU_UMA_CFG_DBSIZ_SHIFT; + uma_cfg |= op->addr.nbytes << NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT; + regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, addr); + } else { + regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, 0x0); + } + + uma_cfg |= data_size << NPCM_FIU_UMA_CFG_RDATSIZ_SHIFT; + regmap_write(fiu->regmap, NPCM_FIU_UMA_CFG, uma_cfg); + regmap_write_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_EXEC_DONE, + NPCM_FIU_UMA_CTS_EXEC_DONE); + ret = regmap_read_poll_timeout(fiu->regmap, NPCM_FIU_UMA_CTS, val, + (!(val & NPCM_FIU_UMA_CTS_EXEC_DONE)), 0, + UMA_MICRO_SEC_TIMEOUT); + if (ret) + return ret; + + if (data_size) { + for (i = 0; i < DIV_ROUND_UP(data_size, 4); i++) + regmap_read(fiu->regmap, NPCM_FIU_UMA_DR0 + (i * 4), + &data_reg[i]); + memcpy(data, data_reg, data_size); + } + + return 0; +} + +static int npcm_fiu_uma_write(struct spi_mem *mem, + const struct spi_mem_op *op, u8 cmd, + bool is_address_size, u8 *data, u32 data_size) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(mem->spi->master); + u32 uma_cfg = BIT(10); + u32 data_reg[4] = {0}; + u32 val; + u32 i; + + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_DEV_NUM, + (mem->spi->chip_select << + NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT)); + + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CMD, + NPCM_FIU_UMA_CMD_CMD, cmd); + + if (data_size) { + memcpy(data_reg, data, data_size); + for (i = 0; i < DIV_ROUND_UP(data_size, 4); i++) + regmap_write(fiu->regmap, NPCM_FIU_UMA_DW0 + (i * 4), + data_reg[i]); + } + + if (is_address_size) { + uma_cfg |= ilog2(op->cmd.buswidth); + uma_cfg |= ilog2(op->addr.buswidth) << + NPCM_FIU_UMA_CFG_ADBPCK_SHIFT; + uma_cfg |= ilog2(op->data.buswidth) << + NPCM_FIU_UMA_CFG_WDBPCK_SHIFT; + uma_cfg |= op->addr.nbytes << NPCM_FIU_UMA_CFG_ADDSIZ_SHIFT; + regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, op->addr.val); + } else { + regmap_write(fiu->regmap, NPCM_FIU_UMA_ADDR, 0x0); + } + + uma_cfg |= (data_size << NPCM_FIU_UMA_CFG_WDATSIZ_SHIFT); + regmap_write(fiu->regmap, NPCM_FIU_UMA_CFG, uma_cfg); + + regmap_write_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_EXEC_DONE, + NPCM_FIU_UMA_CTS_EXEC_DONE); + + return regmap_read_poll_timeout(fiu->regmap, NPCM_FIU_UMA_CTS, val, + (!(val & NPCM_FIU_UMA_CTS_EXEC_DONE)), 0, + UMA_MICRO_SEC_TIMEOUT); +} + +static int npcm_fiu_manualwrite(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(mem->spi->master); + u8 *data = (u8 *)op->data.buf.out; + u32 num_data_chunks; + u32 remain_data; + u32 idx = 0; + int ret; + + num_data_chunks = op->data.nbytes / CHUNK_SIZE; + remain_data = op->data.nbytes % CHUNK_SIZE; + + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_DEV_NUM, + (mem->spi->chip_select << + NPCM_FIU_UMA_CTS_DEV_NUM_SHIFT)); + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_SW_CS, 0); + + ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, true, NULL, 0); + if (ret) + return ret; + + /* Starting the data writing loop in multiples of 8 */ + for (idx = 0; idx < num_data_chunks; ++idx) { + ret = npcm_fiu_uma_write(mem, op, data[0], false, + &data[1], CHUNK_SIZE - 1); + if (ret) + return ret; + + data += CHUNK_SIZE; + } + + /* Handling chunk remains */ + if (remain_data > 0) { + ret = npcm_fiu_uma_write(mem, op, data[0], false, + &data[1], remain_data - 1); + if (ret) + return ret; + } + + regmap_update_bits(fiu->regmap, NPCM_FIU_UMA_CTS, + NPCM_FIU_UMA_CTS_SW_CS, NPCM_FIU_UMA_CTS_SW_CS); + + return 0; +} + +static int npcm_fiu_read(struct spi_mem *mem, const struct spi_mem_op *op) +{ + u8 *data = op->data.buf.in; + int i, readlen, currlen; + u8 *buf_ptr; + u32 addr; + int ret; + + i = 0; + currlen = op->data.nbytes; + + do { + addr = ((u32)op->addr.val + i); + if (currlen < 16) + readlen = currlen; + else + readlen = 16; + + buf_ptr = data + i; + ret = npcm_fiu_uma_read(mem, op, addr, true, buf_ptr, + readlen); + if (ret) + return ret; + + i += readlen; + currlen -= 16; + } while (currlen > 0); + + return 0; +} + +static void npcm_fiux_set_direct_wr(struct npcm_fiu_spi *fiu) +{ + regmap_write(fiu->regmap, NPCM_FIU_DWR_CFG, + NPCM_FIU_DWR_16_BYTE_BURST); + regmap_update_bits(fiu->regmap, NPCM_FIU_DWR_CFG, + NPCM_FIU_DWR_CFG_ABPCK, + DWR_ABPCK_4_BIT_PER_CLK << NPCM_FIU_DWR_ABPCK_SHIFT); + regmap_update_bits(fiu->regmap, NPCM_FIU_DWR_CFG, + NPCM_FIU_DWR_CFG_DBPCK, + DWR_DBPCK_4_BIT_PER_CLK << NPCM_FIU_DWR_DBPCK_SHIFT); +} + +static void npcm_fiux_set_direct_rd(struct npcm_fiu_spi *fiu) +{ + u32 rx_dummy = 0; + + regmap_write(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_16_BYTE_BURST); + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_ACCTYPE, + DRD_SPI_X_MODE << NPCM_FIU_DRD_ACCTYPE_SHIFT); + regmap_update_bits(fiu->regmap, NPCM_FIU_DRD_CFG, + NPCM_FIU_DRD_CFG_DBW, + rx_dummy << NPCM_FIU_DRD_DBW_SHIFT); +} + +static int npcm_fiu_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(mem->spi->master); + struct npcm_fiu_chip *chip = &fiu->chip[mem->spi->chip_select]; + int ret = 0; + u8 *buf; + + dev_dbg(fiu->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n", + op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, + op->dummy.buswidth, op->data.buswidth, op->addr.val, + op->data.nbytes); + + if (fiu->spix_mode || op->addr.nbytes > 4) + return -ENOTSUPP; + + if (fiu->clkrate != chip->clkrate) { + ret = clk_set_rate(fiu->clk, chip->clkrate); + if (ret < 0) + dev_warn(fiu->dev, "Failed setting %lu frequency, stay at %lu frequency\n", + chip->clkrate, fiu->clkrate); + else + fiu->clkrate = chip->clkrate; + } + + if (op->data.dir == SPI_MEM_DATA_IN) { + if (!op->addr.nbytes) { + buf = op->data.buf.in; + ret = npcm_fiu_uma_read(mem, op, op->addr.val, false, + buf, op->data.nbytes); + } else { + ret = npcm_fiu_read(mem, op); + } + } else { + if (!op->addr.nbytes && !op->data.nbytes) + ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false, + NULL, 0); + if (op->addr.nbytes && !op->data.nbytes) { + int i; + u8 buf_addr[4]; + u32 addr = op->addr.val; + + for (i = op->addr.nbytes - 1; i >= 0; i--) { + buf_addr[i] = addr & 0xff; + addr >>= 8; + } + ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false, + buf_addr, op->addr.nbytes); + } + if (!op->addr.nbytes && op->data.nbytes) + ret = npcm_fiu_uma_write(mem, op, op->cmd.opcode, false, + (u8 *)op->data.buf.out, + op->data.nbytes); + if (op->addr.nbytes && op->data.nbytes) + ret = npcm_fiu_manualwrite(mem, op); + } + + return ret; +} + +static int npcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc) +{ + struct npcm_fiu_spi *fiu = + spi_controller_get_devdata(desc->mem->spi->master); + struct npcm_fiu_chip *chip = &fiu->chip[desc->mem->spi->chip_select]; + struct regmap *gcr_regmap; + + if (!fiu->res_mem) { + dev_warn(fiu->dev, "Reserved memory not defined, direct read disabled\n"); + desc->nodirmap = true; + return 0; + } + + if (!fiu->spix_mode && + desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT) { + desc->nodirmap = true; + return 0; + } + + if (!chip->flash_region_mapped_ptr) { + chip->flash_region_mapped_ptr = + devm_ioremap(fiu->dev, (fiu->res_mem->start + + (fiu->info->max_map_size * + desc->mem->spi->chip_select)), + (u32)desc->info.length); + if (!chip->flash_region_mapped_ptr) { + dev_warn(fiu->dev, "Error mapping memory region, direct read disabled\n"); + desc->nodirmap = true; + return 0; + } + } + + if (of_device_is_compatible(fiu->dev->of_node, "nuvoton,npcm750-fiu")) { + gcr_regmap = + syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr"); + if (IS_ERR(gcr_regmap)) { + dev_warn(fiu->dev, "Didn't find nuvoton,npcm750-gcr, direct read disabled\n"); + desc->nodirmap = true; + return 0; + } + regmap_update_bits(gcr_regmap, NPCM7XX_INTCR3_OFFSET, + NPCM7XX_INTCR3_FIU_FIX, + NPCM7XX_INTCR3_FIU_FIX); + } + + if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN) { + if (!fiu->spix_mode) + npcm_fiu_set_drd(fiu, &desc->info.op_tmpl); + else + npcm_fiux_set_direct_rd(fiu); + + } else { + npcm_fiux_set_direct_wr(fiu); + } + + return 0; +} + +static int npcm_fiu_setup(struct spi_device *spi) +{ + struct spi_controller *ctrl = spi->master; + struct npcm_fiu_spi *fiu = spi_controller_get_devdata(ctrl); + struct npcm_fiu_chip *chip; + + chip = &fiu->chip[spi->chip_select]; + chip->fiu = fiu; + chip->chipselect = spi->chip_select; + chip->clkrate = spi->max_speed_hz; + + fiu->clkrate = clk_get_rate(fiu->clk); + + return 0; +} + +static const struct spi_controller_mem_ops npcm_fiu_mem_ops = { + .exec_op = npcm_fiu_exec_op, + .dirmap_create = npcm_fiu_dirmap_create, + .dirmap_read = npcm_fiu_direct_read, + .dirmap_write = npcm_fiu_direct_write, +}; + +static const struct of_device_id npcm_fiu_dt_ids[] = { + { .compatible = "nuvoton,npcm750-fiu", .data = &npxm7xx_fiu_data }, + { /* sentinel */ } +}; + +static int npcm_fiu_probe(struct platform_device *pdev) +{ + const struct fiu_data *fiu_data_match; + const struct of_device_id *match; + struct device *dev = &pdev->dev; + struct spi_controller *ctrl; + struct npcm_fiu_spi *fiu; + void __iomem *regbase; + struct resource *res; + int ret; + int id; + + ctrl = spi_alloc_master(dev, sizeof(*fiu)); + if (!ctrl) + return -ENOMEM; + + fiu = spi_controller_get_devdata(ctrl); + + match = of_match_device(npcm_fiu_dt_ids, dev); + if (!match || !match->data) { + dev_err(dev, "No compatible OF match\n"); + return -ENODEV; + } + + fiu_data_match = match->data; + id = of_alias_get_id(dev->of_node, "fiu"); + if (id < 0 || id >= fiu_data_match->fiu_max) { + dev_err(dev, "Invalid platform device id: %d\n", id); + return -EINVAL; + } + + fiu->info = &fiu_data_match->npcm_fiu_data_info[id]; + + platform_set_drvdata(pdev, fiu); + fiu->dev = dev; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control"); + regbase = devm_ioremap_resource(dev, res); + if (IS_ERR(regbase)) + return PTR_ERR(regbase); + + fiu->regmap = devm_regmap_init_mmio(dev, regbase, + &npcm_mtd_regmap_config); + if (IS_ERR(fiu->regmap)) { + dev_err(dev, "Failed to create regmap\n"); + return PTR_ERR(fiu->regmap); + } + + fiu->res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "memory"); + fiu->clk = devm_clk_get(dev, NULL); + if (IS_ERR(fiu->clk)) + return PTR_ERR(fiu->clk); + + fiu->spix_mode = of_property_read_bool(dev->of_node, + "nuvoton,spix-mode"); + + platform_set_drvdata(pdev, fiu); + clk_prepare_enable(fiu->clk); + + ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD + | SPI_TX_DUAL | SPI_TX_QUAD; + ctrl->setup = npcm_fiu_setup; + ctrl->bus_num = -1; + ctrl->mem_ops = &npcm_fiu_mem_ops; + ctrl->num_chipselect = fiu->info->max_cs; + ctrl->dev.of_node = dev->of_node; + + ret = devm_spi_register_master(dev, ctrl); + if (ret) + return ret; + + return 0; +} + +static int npcm_fiu_remove(struct platform_device *pdev) +{ + struct npcm_fiu_spi *fiu = platform_get_drvdata(pdev); + + clk_disable_unprepare(fiu->clk); + return 0; +} + +MODULE_DEVICE_TABLE(of, npcm_fiu_dt_ids); + +static struct platform_driver npcm_fiu_driver = { + .driver = { + .name = "NPCM-FIU", + .bus = &platform_bus_type, + .of_match_table = npcm_fiu_dt_ids, + }, + .probe = npcm_fiu_probe, + .remove = npcm_fiu_remove, +}; +module_platform_driver(npcm_fiu_driver); + +MODULE_DESCRIPTION("Nuvoton FLASH Interface Unit SPI Controller Driver"); +MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c index 734a2b956959..87cd0233c60b 100644 --- a/drivers/spi/spi-npcm-pspi.c +++ b/drivers/spi/spi-npcm-pspi.c @@ -12,6 +12,7 @@ #include <linux/spi/spi.h> #include <linux/gpio.h> #include <linux/of_gpio.h> +#include <linux/reset.h> #include <asm/unaligned.h> @@ -20,7 +21,7 @@ struct npcm_pspi { struct completion xfer_done; - struct regmap *rst_regmap; + struct reset_control *reset; struct spi_master *master; unsigned int tx_bytes; unsigned int rx_bytes; @@ -59,12 +60,6 @@ struct npcm_pspi { #define NPCM_PSPI_MIN_CLK_DIVIDER 4 #define NPCM_PSPI_DEFAULT_CLK 25000000 -/* reset register */ -#define NPCM7XX_IPSRST2_OFFSET 0x24 - -#define NPCM7XX_PSPI1_RESET BIT(22) -#define NPCM7XX_PSPI2_RESET BIT(23) - static inline unsigned int bytes_per_word(unsigned int bits) { return bits <= 8 ? 1 : 2; @@ -178,6 +173,13 @@ static void npcm_pspi_setup_transfer(struct spi_device *spi, priv->mode = spi->mode; } + /* + * If transfer is even length, and 8 bits per word transfer, + * then implement 16 bits-per-word transfer. + */ + if (priv->bits_per_word == 8 && !(t->len & 0x1)) + t->bits_per_word = 16; + if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) { npcm_pspi_set_transfer_size(priv, t->bits_per_word); priv->bits_per_word = t->bits_per_word; @@ -195,6 +197,7 @@ static void npcm_pspi_setup_transfer(struct spi_device *spi, static void npcm_pspi_send(struct npcm_pspi *priv) { int wsize; + u16 val; wsize = min(bytes_per_word(priv->bits_per_word), priv->tx_bytes); priv->tx_bytes -= wsize; @@ -204,17 +207,18 @@ static void npcm_pspi_send(struct npcm_pspi *priv) switch (wsize) { case 1: - iowrite8(*priv->tx_buf, NPCM_PSPI_DATA + priv->base); + val = *priv->tx_buf++; + iowrite8(val, NPCM_PSPI_DATA + priv->base); break; case 2: - iowrite16(*priv->tx_buf, NPCM_PSPI_DATA + priv->base); + val = *priv->tx_buf++; + val = *priv->tx_buf++ | (val << 8); + iowrite16(val, NPCM_PSPI_DATA + priv->base); break; default: WARN_ON_ONCE(1); return; } - - priv->tx_buf += wsize; } static void npcm_pspi_recv(struct npcm_pspi *priv) @@ -230,18 +234,17 @@ static void npcm_pspi_recv(struct npcm_pspi *priv) switch (rsize) { case 1: - val = ioread8(priv->base + NPCM_PSPI_DATA); + *priv->rx_buf++ = ioread8(priv->base + NPCM_PSPI_DATA); break; case 2: val = ioread16(priv->base + NPCM_PSPI_DATA); + *priv->rx_buf++ = (val >> 8); + *priv->rx_buf++ = val & 0xff; break; default: WARN_ON_ONCE(1); return; } - - *priv->rx_buf = val; - priv->rx_buf += rsize; } static int npcm_pspi_transfer_one(struct spi_master *master, @@ -285,15 +288,14 @@ static int npcm_pspi_unprepare_transfer_hardware(struct spi_master *master) static void npcm_pspi_reset_hw(struct npcm_pspi *priv) { - regmap_write(priv->rst_regmap, NPCM7XX_IPSRST2_OFFSET, - NPCM7XX_PSPI1_RESET << priv->id); - regmap_write(priv->rst_regmap, NPCM7XX_IPSRST2_OFFSET, 0x0); + reset_control_assert(priv->reset); + udelay(5); + reset_control_deassert(priv->reset); } static irqreturn_t npcm_pspi_handler(int irq, void *dev_id) { struct npcm_pspi *priv = dev_id; - u16 val; u8 stat; stat = ioread8(priv->base + NPCM_PSPI_STAT); @@ -303,7 +305,7 @@ static irqreturn_t npcm_pspi_handler(int irq, void *dev_id) if (priv->tx_buf) { if (stat & NPCM_PSPI_STAT_RBF) { - val = ioread8(NPCM_PSPI_DATA + priv->base); + ioread8(NPCM_PSPI_DATA + priv->base); if (priv->tx_bytes == 0) { npcm_pspi_disable(priv); complete(&priv->xfer_done); @@ -341,7 +343,6 @@ static int npcm_pspi_probe(struct platform_device *pdev) { struct npcm_pspi *priv; struct spi_master *master; - struct resource *res; unsigned long clk_hz; struct device_node *np = pdev->dev.of_node; int num_cs, i; @@ -353,10 +354,6 @@ static int npcm_pspi_probe(struct platform_device *pdev) if (num_cs < 0) return num_cs; - pdev->id = of_alias_get_id(np, "spi"); - if (pdev->id < 0) - pdev->id = 0; - master = spi_alloc_master(&pdev->dev, sizeof(*priv)); if (!master) return -ENOMEM; @@ -366,10 +363,8 @@ static int npcm_pspi_probe(struct platform_device *pdev) priv = spi_master_get_devdata(master); priv->master = master; priv->is_save_param = false; - priv->id = pdev->id; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, res); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) { ret = PTR_ERR(priv->base); goto out_master_put; @@ -388,16 +383,14 @@ static int npcm_pspi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ\n"); ret = irq; goto out_disable_clk; } - priv->rst_regmap = - syscon_regmap_lookup_by_compatible("nuvoton,npcm750-rst"); - if (IS_ERR(priv->rst_regmap)) { - dev_err(&pdev->dev, "failed to find nuvoton,npcm750-rst\n"); - return PTR_ERR(priv->rst_regmap); + priv->reset = devm_reset_control_get(&pdev->dev, NULL); + if (IS_ERR(priv->reset)) { + ret = PTR_ERR(priv->reset); + goto out_disable_clk; } /* reset SPI-HW block */ @@ -418,7 +411,7 @@ static int npcm_pspi_probe(struct platform_device *pdev) master->min_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MAX_CLK_DIVIDER); master->mode_bits = SPI_CPHA | SPI_CPOL; master->dev.of_node = pdev->dev.of_node; - master->bus_num = pdev->id; + master->bus_num = -1; master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); master->transfer_one = npcm_pspi_transfer_one; master->prepare_transfer_hardware = @@ -451,7 +444,7 @@ static int npcm_pspi_probe(struct platform_device *pdev) if (ret) goto out_disable_clk; - pr_info("NPCM Peripheral SPI %d probed\n", pdev->id); + pr_info("NPCM Peripheral SPI %d probed\n", master->bus_num); return 0; diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c deleted file mode 100644 index 37e2034ad4d5..000000000000 --- a/drivers/spi/spi-nuc900.c +++ /dev/null @@ -1,429 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2009 Nuvoton technology. - * Wan ZongShun <mcuos.com@gmail.com> - */ - -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/device.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/io.h> -#include <linux/slab.h> - -#include <linux/spi/spi.h> -#include <linux/spi/spi_bitbang.h> - -#include <linux/platform_data/spi-nuc900.h> - -/* usi registers offset */ -#define USI_CNT 0x00 -#define USI_DIV 0x04 -#define USI_SSR 0x08 -#define USI_RX0 0x10 -#define USI_TX0 0x10 - -/* usi register bit */ -#define ENINT (0x01 << 17) -#define ENFLG (0x01 << 16) -#define SLEEP (0x0f << 12) -#define TXNUM (0x03 << 8) -#define TXBITLEN (0x1f << 3) -#define TXNEG (0x01 << 2) -#define RXNEG (0x01 << 1) -#define LSB (0x01 << 10) -#define SELECTLEV (0x01 << 2) -#define SELECTPOL (0x01 << 31) -#define SELECTSLAVE 0x01 -#define GOBUSY 0x01 - -struct nuc900_spi { - struct spi_bitbang bitbang; - struct completion done; - void __iomem *regs; - int irq; - int len; - int count; - const unsigned char *tx; - unsigned char *rx; - struct clk *clk; - struct spi_master *master; - struct nuc900_spi_info *pdata; - spinlock_t lock; -}; - -static inline struct nuc900_spi *to_hw(struct spi_device *sdev) -{ - return spi_master_get_devdata(sdev->master); -} - -static void nuc900_slave_select(struct spi_device *spi, unsigned int ssr) -{ - struct nuc900_spi *hw = to_hw(spi); - unsigned int val; - unsigned int cs = spi->mode & SPI_CS_HIGH ? 1 : 0; - unsigned int cpol = spi->mode & SPI_CPOL ? 1 : 0; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - - val = __raw_readl(hw->regs + USI_SSR); - - if (!cs) - val &= ~SELECTLEV; - else - val |= SELECTLEV; - - if (!ssr) - val &= ~SELECTSLAVE; - else - val |= SELECTSLAVE; - - __raw_writel(val, hw->regs + USI_SSR); - - val = __raw_readl(hw->regs + USI_CNT); - - if (!cpol) - val &= ~SELECTPOL; - else - val |= SELECTPOL; - - __raw_writel(val, hw->regs + USI_CNT); - - spin_unlock_irqrestore(&hw->lock, flags); -} - -static void nuc900_spi_chipsel(struct spi_device *spi, int value) -{ - switch (value) { - case BITBANG_CS_INACTIVE: - nuc900_slave_select(spi, 0); - break; - - case BITBANG_CS_ACTIVE: - nuc900_slave_select(spi, 1); - break; - } -} - -static void nuc900_spi_setup_txnum(struct nuc900_spi *hw, unsigned int txnum) -{ - unsigned int val; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - - val = __raw_readl(hw->regs + USI_CNT) & ~TXNUM; - - if (txnum) - val |= txnum << 0x08; - - __raw_writel(val, hw->regs + USI_CNT); - - spin_unlock_irqrestore(&hw->lock, flags); - -} - -static void nuc900_spi_setup_txbitlen(struct nuc900_spi *hw, - unsigned int txbitlen) -{ - unsigned int val; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - - val = __raw_readl(hw->regs + USI_CNT) & ~TXBITLEN; - - val |= (txbitlen << 0x03); - - __raw_writel(val, hw->regs + USI_CNT); - - spin_unlock_irqrestore(&hw->lock, flags); -} - -static void nuc900_spi_gobusy(struct nuc900_spi *hw) -{ - unsigned int val; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - - val = __raw_readl(hw->regs + USI_CNT); - - val |= GOBUSY; - - __raw_writel(val, hw->regs + USI_CNT); - - spin_unlock_irqrestore(&hw->lock, flags); -} - -static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count) -{ - return hw->tx ? hw->tx[count] : 0; -} - -static int nuc900_spi_txrx(struct spi_device *spi, struct spi_transfer *t) -{ - struct nuc900_spi *hw = to_hw(spi); - - hw->tx = t->tx_buf; - hw->rx = t->rx_buf; - hw->len = t->len; - hw->count = 0; - - __raw_writel(hw_txbyte(hw, 0x0), hw->regs + USI_TX0); - - nuc900_spi_gobusy(hw); - - wait_for_completion(&hw->done); - - return hw->count; -} - -static irqreturn_t nuc900_spi_irq(int irq, void *dev) -{ - struct nuc900_spi *hw = dev; - unsigned int status; - unsigned int count = hw->count; - - status = __raw_readl(hw->regs + USI_CNT); - __raw_writel(status, hw->regs + USI_CNT); - - if (status & ENFLG) { - hw->count++; - - if (hw->rx) - hw->rx[count] = __raw_readl(hw->regs + USI_RX0); - count++; - - if (count < hw->len) { - __raw_writel(hw_txbyte(hw, count), hw->regs + USI_TX0); - nuc900_spi_gobusy(hw); - } else { - complete(&hw->done); - } - - return IRQ_HANDLED; - } - - complete(&hw->done); - return IRQ_HANDLED; -} - -static void nuc900_tx_edge(struct nuc900_spi *hw, unsigned int edge) -{ - unsigned int val; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - - val = __raw_readl(hw->regs + USI_CNT); - - if (edge) - val |= TXNEG; - else - val &= ~TXNEG; - __raw_writel(val, hw->regs + USI_CNT); - - spin_unlock_irqrestore(&hw->lock, flags); -} - -static void nuc900_rx_edge(struct nuc900_spi *hw, unsigned int edge) -{ - unsigned int val; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - - val = __raw_readl(hw->regs + USI_CNT); - - if (edge) - val |= RXNEG; - else - val &= ~RXNEG; - __raw_writel(val, hw->regs + USI_CNT); - - spin_unlock_irqrestore(&hw->lock, flags); -} - -static void nuc900_send_first(struct nuc900_spi *hw, unsigned int lsb) -{ - unsigned int val; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - - val = __raw_readl(hw->regs + USI_CNT); - - if (lsb) - val |= LSB; - else - val &= ~LSB; - __raw_writel(val, hw->regs + USI_CNT); - - spin_unlock_irqrestore(&hw->lock, flags); -} - -static void nuc900_set_sleep(struct nuc900_spi *hw, unsigned int sleep) -{ - unsigned int val; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - - val = __raw_readl(hw->regs + USI_CNT) & ~SLEEP; - - if (sleep) - val |= (sleep << 12); - - __raw_writel(val, hw->regs + USI_CNT); - - spin_unlock_irqrestore(&hw->lock, flags); -} - -static void nuc900_enable_int(struct nuc900_spi *hw) -{ - unsigned int val; - unsigned long flags; - - spin_lock_irqsave(&hw->lock, flags); - - val = __raw_readl(hw->regs + USI_CNT); - - val |= ENINT; - - __raw_writel(val, hw->regs + USI_CNT); - - spin_unlock_irqrestore(&hw->lock, flags); -} - -static void nuc900_set_divider(struct nuc900_spi *hw) -{ - __raw_writel(hw->pdata->divider, hw->regs + USI_DIV); -} - -static void nuc900_init_spi(struct nuc900_spi *hw) -{ - clk_enable(hw->clk); - spin_lock_init(&hw->lock); - - nuc900_tx_edge(hw, hw->pdata->txneg); - nuc900_rx_edge(hw, hw->pdata->rxneg); - nuc900_send_first(hw, hw->pdata->lsb); - nuc900_set_sleep(hw, hw->pdata->sleep); - nuc900_spi_setup_txbitlen(hw, hw->pdata->txbitlen); - nuc900_spi_setup_txnum(hw, hw->pdata->txnum); - nuc900_set_divider(hw); - nuc900_enable_int(hw); -} - -static int nuc900_spi_probe(struct platform_device *pdev) -{ - struct nuc900_spi *hw; - struct spi_master *master; - struct resource *res; - int err = 0; - - master = spi_alloc_master(&pdev->dev, sizeof(struct nuc900_spi)); - if (master == NULL) { - dev_err(&pdev->dev, "No memory for spi_master\n"); - return -ENOMEM; - } - - hw = spi_master_get_devdata(master); - hw->master = master; - hw->pdata = dev_get_platdata(&pdev->dev); - - if (hw->pdata == NULL) { - dev_err(&pdev->dev, "No platform data supplied\n"); - err = -ENOENT; - goto err_pdata; - } - - platform_set_drvdata(pdev, hw); - init_completion(&hw->done); - - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - if (hw->pdata->lsb) - master->mode_bits |= SPI_LSB_FIRST; - master->num_chipselect = hw->pdata->num_cs; - master->bus_num = hw->pdata->bus_num; - hw->bitbang.master = hw->master; - hw->bitbang.chipselect = nuc900_spi_chipsel; - hw->bitbang.txrx_bufs = nuc900_spi_txrx; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hw->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(hw->regs)) { - err = PTR_ERR(hw->regs); - goto err_pdata; - } - - hw->irq = platform_get_irq(pdev, 0); - if (hw->irq < 0) { - dev_err(&pdev->dev, "No IRQ specified\n"); - err = -ENOENT; - goto err_pdata; - } - - err = devm_request_irq(&pdev->dev, hw->irq, nuc900_spi_irq, 0, - pdev->name, hw); - if (err) { - dev_err(&pdev->dev, "Cannot claim IRQ\n"); - goto err_pdata; - } - - hw->clk = devm_clk_get(&pdev->dev, "spi"); - if (IS_ERR(hw->clk)) { - dev_err(&pdev->dev, "No clock for device\n"); - err = PTR_ERR(hw->clk); - goto err_pdata; - } - - mfp_set_groupg(&pdev->dev, NULL); - nuc900_init_spi(hw); - - err = spi_bitbang_start(&hw->bitbang); - if (err) { - dev_err(&pdev->dev, "Failed to register SPI master\n"); - goto err_register; - } - - return 0; - -err_register: - clk_disable(hw->clk); -err_pdata: - spi_master_put(hw->master); - return err; -} - -static int nuc900_spi_remove(struct platform_device *dev) -{ - struct nuc900_spi *hw = platform_get_drvdata(dev); - - spi_bitbang_stop(&hw->bitbang); - clk_disable(hw->clk); - spi_master_put(hw->master); - return 0; -} - -static struct platform_driver nuc900_spi_driver = { - .probe = nuc900_spi_probe, - .remove = nuc900_spi_remove, - .driver = { - .name = "nuc900-spi", - }, -}; -module_platform_driver(nuc900_spi_driver); - -MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); -MODULE_DESCRIPTION("nuc900 spi driver!"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:nuc900-spi"); diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index 8894f98cc99c..8c5084a3a617 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -439,7 +439,7 @@ static bool nxp_fspi_supports_op(struct spi_mem *mem, op->data.nbytes > f->devtype_data->txfifo) return false; - return true; + return spi_mem_default_supports_op(mem, op); } /* Instead of busy looping invoke readl_poll_timeout functionality. */ @@ -1007,10 +1007,8 @@ static int nxp_fspi_probe(struct platform_device *pdev) /* find the irq */ ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "failed to get the irq: %d\n", ret); + if (ret < 0) goto err_disable_clk; - } ret = devm_request_irq(dev, ret, nxp_fspi_irq_handler, 0, pdev->name, f); @@ -1029,7 +1027,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) ctlr->dev.of_node = np; - ret = spi_register_controller(ctlr); + ret = devm_spi_register_controller(&pdev->dev, ctlr); if (ret) goto err_destroy_mutex; diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c index bbc4ba66571f..9df7c5979c29 100644 --- a/drivers/spi/spi-oc-tiny.c +++ b/drivers/spi/spi-oc-tiny.c @@ -20,7 +20,6 @@ #include <linux/spi/spi_bitbang.h> #include <linux/spi/spi_oc_tiny.h> #include <linux/io.h> -#include <linux/gpio.h> #include <linux/of.h> #define DRV_NAME "spi_oc_tiny" @@ -50,8 +49,6 @@ struct tiny_spi { unsigned int txc, rxc; const u8 *txp; u8 *rxp; - int gpio_cs_count; - int *gpio_cs; }; static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev) @@ -66,16 +63,6 @@ static unsigned int tiny_spi_baud(struct spi_device *spi, unsigned int hz) return min(DIV_ROUND_UP(hw->freq, hz * 2), (1U << hw->baudwidth)) - 1; } -static void tiny_spi_chipselect(struct spi_device *spi, int is_active) -{ - struct tiny_spi *hw = tiny_spi_to_hw(spi); - - if (hw->gpio_cs_count > 0) { - gpio_set_value(hw->gpio_cs[spi->chip_select], - (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); - } -} - static int tiny_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { @@ -203,24 +190,10 @@ static int tiny_spi_of_probe(struct platform_device *pdev) { struct tiny_spi *hw = platform_get_drvdata(pdev); struct device_node *np = pdev->dev.of_node; - unsigned int i; u32 val; if (!np) return 0; - hw->gpio_cs_count = of_gpio_count(np); - if (hw->gpio_cs_count > 0) { - hw->gpio_cs = devm_kcalloc(&pdev->dev, - hw->gpio_cs_count, sizeof(unsigned int), - GFP_KERNEL); - if (!hw->gpio_cs) - return -ENOMEM; - } - for (i = 0; i < hw->gpio_cs_count; i++) { - hw->gpio_cs[i] = of_get_gpio_flags(np, i, NULL); - if (hw->gpio_cs[i] < 0) - return -ENODEV; - } hw->bitbang.master->dev.of_node = pdev->dev.of_node; if (!of_property_read_u32(np, "clock-frequency", &val)) hw->freq = val; @@ -240,8 +213,6 @@ static int tiny_spi_probe(struct platform_device *pdev) struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev); struct tiny_spi *hw; struct spi_master *master; - struct resource *res; - unsigned int i; int err = -ENODEV; master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi)); @@ -250,9 +221,9 @@ static int tiny_spi_probe(struct platform_device *pdev) /* setup the master state. */ master->bus_num = pdev->id; - master->num_chipselect = 255; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->setup = tiny_spi_setup; + master->use_gpio_descriptors = true; hw = spi_master_get_devdata(master); platform_set_drvdata(pdev, hw); @@ -260,12 +231,10 @@ static int tiny_spi_probe(struct platform_device *pdev) /* setup the state for the bitbang driver */ hw->bitbang.master = master; hw->bitbang.setup_transfer = tiny_spi_setup_transfer; - hw->bitbang.chipselect = tiny_spi_chipselect; hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs; /* find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hw->base = devm_ioremap_resource(&pdev->dev, res); + hw->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hw->base)) { err = PTR_ERR(hw->base); goto exit; @@ -281,12 +250,6 @@ static int tiny_spi_probe(struct platform_device *pdev) } /* find platform data */ if (platp) { - hw->gpio_cs_count = platp->gpio_cs_count; - hw->gpio_cs = platp->gpio_cs; - if (platp->gpio_cs_count && !platp->gpio_cs) { - err = -EBUSY; - goto exit; - } hw->freq = platp->freq; hw->baudwidth = platp->baudwidth; } else { @@ -294,13 +257,6 @@ static int tiny_spi_probe(struct platform_device *pdev) if (err) goto exit; } - for (i = 0; i < hw->gpio_cs_count; i++) { - err = gpio_request(hw->gpio_cs[i], dev_name(&pdev->dev)); - if (err) - goto exit_gpio; - gpio_direction_output(hw->gpio_cs[i], 1); - } - hw->bitbang.master->num_chipselect = max(1, hw->gpio_cs_count); /* register our spi controller */ err = spi_bitbang_start(&hw->bitbang); @@ -310,9 +266,6 @@ static int tiny_spi_probe(struct platform_device *pdev) return 0; -exit_gpio: - while (i-- > 0) - gpio_free(hw->gpio_cs[i]); exit: spi_master_put(master); return err; @@ -322,11 +275,8 @@ static int tiny_spi_remove(struct platform_device *pdev) { struct tiny_spi *hw = platform_get_drvdata(pdev); struct spi_master *master = hw->bitbang.master; - unsigned int i; spi_bitbang_stop(&hw->bitbang); - for (i = 0; i < hw->gpio_cs_count; i++) - gpio_free(hw->gpio_cs[i]); spi_master_put(master); return 0; } diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index b955ca8796d2..5c704ba6d8ea 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -128,7 +128,7 @@ static void spi100k_write_data(struct spi_master *master, int len, int data) static int spi100k_read_data(struct spi_master *master, int len) { - int dataH, dataL; + int dataL; struct omap1_spi100k *spi100k = spi_master_get_devdata(master); /* Always do at least 16 bits */ @@ -146,7 +146,7 @@ static int spi100k_read_data(struct spi_master *master, int len) udelay(1000); dataL = readw(spi100k->base + SPI_RX_LSB); - dataH = readw(spi100k->base + SPI_RX_MSB); + readw(spi100k->base + SPI_RX_MSB); spi100k_disable_clock(master); return dataL; @@ -321,8 +321,7 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master, } } - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); /* ignore the "leave it on after last xfer" hint */ diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 848e03e5f42d..7e2292c11d12 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -397,30 +397,26 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi, { struct omap2_mcspi *mcspi; struct omap2_mcspi_dma *mcspi_dma; + struct dma_async_tx_descriptor *tx; mcspi = spi_master_get_devdata(spi->master); mcspi_dma = &mcspi->dma_channels[spi->chip_select]; - if (mcspi_dma->dma_tx) { - struct dma_async_tx_descriptor *tx; + dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); - dmaengine_slave_config(mcspi_dma->dma_tx, &cfg); - - tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, xfer->tx_sg.sgl, - xfer->tx_sg.nents, - DMA_MEM_TO_DEV, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (tx) { - tx->callback = omap2_mcspi_tx_callback; - tx->callback_param = spi; - dmaengine_submit(tx); - } else { - /* FIXME: fall back to PIO? */ - } + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, xfer->tx_sg.sgl, + xfer->tx_sg.nents, + DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (tx) { + tx->callback = omap2_mcspi_tx_callback; + tx->callback_param = spi; + dmaengine_submit(tx); + } else { + /* FIXME: fall back to PIO? */ } dma_async_issue_pending(mcspi_dma->dma_tx); omap2_mcspi_set_dma_req(spi, 0, 1); - } static unsigned @@ -439,6 +435,7 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, int word_len, element_count; struct omap2_mcspi_cs *cs = spi->controller_state; void __iomem *chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; + struct dma_async_tx_descriptor *tx; mcspi = spi_master_get_devdata(spi->master); mcspi_dma = &mcspi->dma_channels[spi->chip_select]; @@ -462,55 +459,47 @@ omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, else /* word_len <= 32 */ element_count = count >> 2; - if (mcspi_dma->dma_rx) { - struct dma_async_tx_descriptor *tx; - dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); + dmaengine_slave_config(mcspi_dma->dma_rx, &cfg); + /* + * Reduce DMA transfer length by one more if McSPI is + * configured in turbo mode. + */ + if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0) + transfer_reduction += es; + + if (transfer_reduction) { + /* Split sgl into two. The second sgl won't be used. */ + sizes[0] = count - transfer_reduction; + sizes[1] = transfer_reduction; + nb_sizes = 2; + } else { /* - * Reduce DMA transfer length by one more if McSPI is - * configured in turbo mode. + * Don't bother splitting the sgl. This essentially + * clones the original sgl. */ - if ((l & OMAP2_MCSPI_CHCONF_TURBO) && mcspi->fifo_depth == 0) - transfer_reduction += es; - - if (transfer_reduction) { - /* Split sgl into two. The second sgl won't be used. */ - sizes[0] = count - transfer_reduction; - sizes[1] = transfer_reduction; - nb_sizes = 2; - } else { - /* - * Don't bother splitting the sgl. This essentially - * clones the original sgl. - */ - sizes[0] = count; - nb_sizes = 1; - } + sizes[0] = count; + nb_sizes = 1; + } - ret = sg_split(xfer->rx_sg.sgl, xfer->rx_sg.nents, - 0, nb_sizes, - sizes, - sg_out, out_mapped_nents, - GFP_KERNEL); + ret = sg_split(xfer->rx_sg.sgl, xfer->rx_sg.nents, 0, nb_sizes, + sizes, sg_out, out_mapped_nents, GFP_KERNEL); - if (ret < 0) { - dev_err(&spi->dev, "sg_split failed\n"); - return 0; - } + if (ret < 0) { + dev_err(&spi->dev, "sg_split failed\n"); + return 0; + } - tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, - sg_out[0], - out_mapped_nents[0], - DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (tx) { - tx->callback = omap2_mcspi_rx_callback; - tx->callback_param = spi; - dmaengine_submit(tx); - } else { - /* FIXME: fall back to PIO? */ - } + tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, sg_out[0], + out_mapped_nents[0], DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (tx) { + tx->callback = omap2_mcspi_rx_callback; + tx->callback_param = spi; + dmaengine_submit(tx); + } else { + /* FIXME: fall back to PIO? */ } dma_async_issue_pending(mcspi_dma->dma_rx); diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 6643ccdc2508..1f59beb7d27e 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -467,8 +467,7 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) if (orion_spi_write_read_8bit(spi, &tx, &rx) < 0) goto out; count--; - if (xfer->word_delay_usecs) - udelay(xfer->word_delay_usecs); + spi_delay_exec(&xfer->word_delay, xfer); } while (count); } else if (word_len == 16) { const u16 *tx = xfer->tx_buf; @@ -478,8 +477,7 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) if (orion_spi_write_read_16bit(spi, &tx, &rx) < 0) goto out; count -= 2; - if (xfer->word_delay_usecs) - udelay(xfer->word_delay_usecs); + spi_delay_exec(&xfer->word_delay, xfer); } while (count); } @@ -648,8 +646,7 @@ static int orion_spi_probe(struct platform_device *pdev) /* The following clock is only used by some SoCs */ spi->axi_clk = devm_clk_get(&pdev->dev, "axi"); - if (IS_ERR(spi->axi_clk) && - PTR_ERR(spi->axi_clk) == -EPROBE_DEFER) { + if (PTR_ERR(spi->axi_clk) == -EPROBE_DEFER) { status = -EPROBE_DEFER; goto out_rel_clk; } @@ -772,9 +769,6 @@ static int orion_spi_probe(struct platform_device *pdev) if (status < 0) goto out_rel_pm; - pm_runtime_mark_last_busy(&pdev->dev); - pm_runtime_put_autosuspend(&pdev->dev); - master->dev.of_node = pdev->dev.of_node; status = spi_register_master(master); if (status < 0) diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index b635526ad414..86ad17597f5f 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -570,7 +570,6 @@ static int pic32_sqi_probe(struct platform_device *pdev) { struct spi_master *master; struct pic32_sqi *sqi; - struct resource *reg; int ret; master = spi_alloc_master(&pdev->dev, sizeof(*sqi)); @@ -580,8 +579,7 @@ static int pic32_sqi_probe(struct platform_device *pdev) sqi = spi_master_get_devdata(master); sqi->master = master; - reg = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sqi->regs = devm_ioremap_resource(&pdev->dev, reg); + sqi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sqi->regs)) { ret = PTR_ERR(sqi->regs); goto err_free_master; @@ -590,7 +588,6 @@ static int pic32_sqi_probe(struct platform_device *pdev) /* irq */ sqi->irq = platform_get_irq(pdev, 0); if (sqi->irq < 0) { - dev_err(&pdev->dev, "no irq found\n"); ret = sqi->irq; goto err_free_master; } diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index 10cebeaa1e6b..156961b4ca86 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -606,25 +606,30 @@ static void pic32_spi_cleanup(struct spi_device *spi) gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); } -static void pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev) +static int pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev) { struct spi_master *master = pic32s->master; - dma_cap_mask_t mask; + int ret = 0; - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); + master->dma_rx = dma_request_chan(dev, "spi-rx"); + if (IS_ERR(master->dma_rx)) { + if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) + ret = -EPROBE_DEFER; + else + dev_warn(dev, "RX channel not found.\n"); - master->dma_rx = dma_request_slave_channel_compat(mask, NULL, NULL, - dev, "spi-rx"); - if (!master->dma_rx) { - dev_warn(dev, "RX channel not found.\n"); + master->dma_rx = NULL; goto out_err; } - master->dma_tx = dma_request_slave_channel_compat(mask, NULL, NULL, - dev, "spi-tx"); - if (!master->dma_tx) { - dev_warn(dev, "TX channel not found.\n"); + master->dma_tx = dma_request_chan(dev, "spi-tx"); + if (IS_ERR(master->dma_tx)) { + if (PTR_ERR(master->dma_tx) == -EPROBE_DEFER) + ret = -EPROBE_DEFER; + else + dev_warn(dev, "TX channel not found.\n"); + + master->dma_tx = NULL; goto out_err; } @@ -634,14 +639,20 @@ static void pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev) /* DMA chnls allocated and prepared */ set_bit(PIC32F_DMA_PREP, &pic32s->flags); - return; + return 0; out_err: - if (master->dma_rx) + if (master->dma_rx) { dma_release_channel(master->dma_rx); + master->dma_rx = NULL; + } - if (master->dma_tx) + if (master->dma_tx) { dma_release_channel(master->dma_tx); + master->dma_tx = NULL; + } + + return ret; } static void pic32_spi_dma_unprep(struct pic32_spi *pic32s) @@ -711,22 +722,16 @@ static int pic32_spi_hw_probe(struct platform_device *pdev, /* get irq resources: err-irq, rx-irq, tx-irq */ pic32s->fault_irq = platform_get_irq_byname(pdev, "fault"); - if (pic32s->fault_irq < 0) { - dev_err(&pdev->dev, "fault-irq not found\n"); + if (pic32s->fault_irq < 0) return pic32s->fault_irq; - } pic32s->rx_irq = platform_get_irq_byname(pdev, "rx"); - if (pic32s->rx_irq < 0) { - dev_err(&pdev->dev, "rx-irq not found\n"); + if (pic32s->rx_irq < 0) return pic32s->rx_irq; - } pic32s->tx_irq = platform_get_irq_byname(pdev, "tx"); - if (pic32s->tx_irq < 0) { - dev_err(&pdev->dev, "tx-irq not found\n"); + if (pic32s->tx_irq < 0) return pic32s->tx_irq; - } /* get clock */ pic32s->clk = devm_clk_get(&pdev->dev, "mck0"); @@ -782,7 +787,10 @@ static int pic32_spi_probe(struct platform_device *pdev) master->unprepare_transfer_hardware = pic32_spi_unprepare_hardware; /* optional DMA support */ - pic32_spi_dma_prep(pic32s, &pdev->dev); + ret = pic32_spi_dma_prep(pic32s, &pdev->dev); + if (ret) + goto err_bailout; + if (test_bit(PIC32F_DMA_PREP, &pic32s->flags)) master->can_dma = pic32_spi_can_dma; diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 7fedea67159c..66028ebbc336 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -485,12 +485,11 @@ static void giveback(struct pl022 *pl022) struct spi_transfer, transfer_list); /* Delay if requested before any change in chip select */ - if (last_transfer->delay_usecs) - /* - * FIXME: This runs in interrupt context. - * Is this really smart? - */ - udelay(last_transfer->delay_usecs); + /* + * FIXME: This runs in interrupt context. + * Is this really smart? + */ + spi_transfer_delay_exec(last_transfer); if (!last_transfer->cs_change) { struct spi_message *next_msg; @@ -1159,7 +1158,7 @@ static int pl022_dma_autoprobe(struct pl022 *pl022) int err; /* automatically configure DMA channels from platform, normally using DT */ - chan = dma_request_slave_channel_reason(dev, "rx"); + chan = dma_request_chan(dev, "rx"); if (IS_ERR(chan)) { err = PTR_ERR(chan); goto err_no_rxchan; @@ -1167,7 +1166,7 @@ static int pl022_dma_autoprobe(struct pl022 *pl022) pl022->dma_rx_channel = chan; - chan = dma_request_slave_channel_reason(dev, "tx"); + chan = dma_request_chan(dev, "tx"); if (IS_ERR(chan)) { err = PTR_ERR(chan); goto err_no_txchan; @@ -1401,12 +1400,11 @@ static void pump_transfers(unsigned long data) previous = list_entry(transfer->transfer_list.prev, struct spi_transfer, transfer_list); - if (previous->delay_usecs) - /* - * FIXME: This runs in interrupt context. - * Is this really smart? - */ - udelay(previous->delay_usecs); + /* + * FIXME: This runs in interrupt context. + * Is this really smart? + */ + spi_transfer_delay_exec(previous); /* Reselect chip select only if cs_change was requested */ if (previous->cs_change) @@ -1520,8 +1518,7 @@ static void do_polling_transfer(struct pl022 *pl022) previous = list_entry(transfer->transfer_list.prev, struct spi_transfer, transfer_list); - if (previous->delay_usecs) - udelay(previous->delay_usecs); + spi_transfer_delay_exec(previous); if (previous->cs_change) pl022_cs_control(pl022, SSP_CHIP_SELECT); } else { diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index bb6a14d1ab0f..4c7a71f0fb3e 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -4,27 +4,29 @@ * Copyright (C) 2013, Intel Corporation */ +#include <linux/acpi.h> #include <linux/bitops.h> -#include <linux/init.h> -#include <linux/module.h> +#include <linux/clk.h> +#include <linux/delay.h> #include <linux/device.h> -#include <linux/ioport.h> -#include <linux/errno.h> #include <linux/err.h> +#include <linux/errno.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio.h> +#include <linux/init.h> #include <linux/interrupt.h> +#include <linux/ioport.h> #include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/of.h> #include <linux/pci.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/property.h> +#include <linux/slab.h> #include <linux/spi/pxa2xx_spi.h> #include <linux/spi/spi.h> -#include <linux/delay.h> -#include <linux/gpio.h> -#include <linux/gpio/consumer.h> -#include <linux/slab.h> -#include <linux/clk.h> -#include <linux/pm_runtime.h> -#include <linux/acpi.h> -#include <linux/of_device.h> #include "spi-pxa2xx.h" @@ -459,6 +461,16 @@ int pxa2xx_spi_flush(struct driver_data *drv_data) return limit; } +static void pxa2xx_spi_off(struct driver_data *drv_data) +{ + /* On MMP, disabling SSE seems to corrupt the rx fifo */ + if (drv_data->ssp_type == MMP2_SSP) + return; + + pxa2xx_spi_write(drv_data, SSCR0, + pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE); +} + static int null_writer(struct driver_data *drv_data) { u8 n_bytes = drv_data->n_bytes; @@ -585,8 +597,7 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg) if (!pxa25x_ssp_comp(drv_data)) pxa2xx_spi_write(drv_data, SSTO, 0); pxa2xx_spi_flush(drv_data); - pxa2xx_spi_write(drv_data, SSCR0, - pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE); + pxa2xx_spi_off(drv_data); dev_err(&drv_data->pdev->dev, "%s\n", msg); @@ -684,8 +695,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) static void handle_bad_msg(struct driver_data *drv_data) { - pxa2xx_spi_write(drv_data, SSCR0, - pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE); + pxa2xx_spi_off(drv_data); pxa2xx_spi_write(drv_data, SSCR1, pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1); if (!pxa25x_ssp_comp(drv_data)) @@ -1060,7 +1070,8 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller, || (pxa2xx_spi_read(drv_data, SSCR1) & change_mask) != (cr1 & change_mask)) { /* stop the SSP, and update the other bits */ - pxa2xx_spi_write(drv_data, SSCR0, cr0 & ~SSCR0_SSE); + if (drv_data->ssp_type != MMP2_SSP) + pxa2xx_spi_write(drv_data, SSCR0, cr0 & ~SSCR0_SSE); if (!pxa25x_ssp_comp(drv_data)) pxa2xx_spi_write(drv_data, SSTO, chip->timeout); /* first set CR1 without interrupt and service enables */ @@ -1116,8 +1127,7 @@ static int pxa2xx_spi_slave_abort(struct spi_controller *controller) if (!pxa25x_ssp_comp(drv_data)) pxa2xx_spi_write(drv_data, SSTO, 0); pxa2xx_spi_flush(drv_data); - pxa2xx_spi_write(drv_data, SSCR0, - pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE); + pxa2xx_spi_off(drv_data); dev_dbg(&drv_data->pdev->dev, "transfer aborted\n"); @@ -1133,8 +1143,7 @@ static void pxa2xx_spi_handle_err(struct spi_controller *controller, struct driver_data *drv_data = spi_controller_get_devdata(controller); /* Disable the SSP */ - pxa2xx_spi_write(drv_data, SSCR0, - pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE); + pxa2xx_spi_off(drv_data); /* Clear and disable interrupts and service requests */ write_SSSR_CS(drv_data, drv_data->clear_sr); pxa2xx_spi_write(drv_data, SSCR1, @@ -1159,8 +1168,7 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_controller *controller) struct driver_data *drv_data = spi_controller_get_devdata(controller); /* Disable the SSP now */ - pxa2xx_spi_write(drv_data, SSCR0, - pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE); + pxa2xx_spi_off(drv_data); return 0; } @@ -1421,6 +1429,9 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { /* KBL-H */ { PCI_VDEVICE(INTEL, 0xa2a9), LPSS_SPT_SSP }, { PCI_VDEVICE(INTEL, 0xa2aa), LPSS_SPT_SSP }, + /* CML-V */ + { PCI_VDEVICE(INTEL, 0xa3a9), LPSS_SPT_SSP }, + { PCI_VDEVICE(INTEL, 0xa3aa), LPSS_SPT_SSP }, /* BXT A-Step */ { PCI_VDEVICE(INTEL, 0x0ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x0ac4), LPSS_BXT_SSP }, @@ -1441,6 +1452,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { { PCI_VDEVICE(INTEL, 0x4b2a), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x4b2b), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x4b37), LPSS_BXT_SSP }, + /* JSL */ + { PCI_VDEVICE(INTEL, 0x4daa), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x4dab), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x4dfb), LPSS_CNL_SSP }, /* APL */ { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP }, @@ -1457,6 +1472,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { { PCI_VDEVICE(INTEL, 0x02aa), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0x02ab), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0x02fb), LPSS_CNL_SSP }, + /* CML-H */ + { PCI_VDEVICE(INTEL, 0x06aa), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x06ab), LPSS_CNL_SSP }, + { PCI_VDEVICE(INTEL, 0x06fb), LPSS_CNL_SSP }, /* TGL-LP */ { PCI_VDEVICE(INTEL, 0xa0aa), LPSS_CNL_SSP }, { PCI_VDEVICE(INTEL, 0xa0ab), LPSS_CNL_SSP }, @@ -1476,11 +1495,13 @@ MODULE_DEVICE_TABLE(of, pxa2xx_spi_of_match); #ifdef CONFIG_ACPI -static int pxa2xx_spi_get_port_id(struct acpi_device *adev) +static int pxa2xx_spi_get_port_id(struct device *dev) { + struct acpi_device *adev; unsigned int devid; int port_id = -1; + adev = ACPI_COMPANION(dev); if (adev && adev->pnp.unique_id && !kstrtouint(adev->pnp.unique_id, 0, &devid)) port_id = devid; @@ -1489,7 +1510,7 @@ static int pxa2xx_spi_get_port_id(struct acpi_device *adev) #else /* !CONFIG_ACPI */ -static int pxa2xx_spi_get_port_id(struct acpi_device *adev) +static int pxa2xx_spi_get_port_id(struct device *dev) { return -1; } @@ -1510,34 +1531,22 @@ static struct pxa2xx_spi_controller * pxa2xx_spi_init_pdata(struct platform_device *pdev) { struct pxa2xx_spi_controller *pdata; - struct acpi_device *adev; struct ssp_device *ssp; struct resource *res; - const struct acpi_device_id *adev_id = NULL; + struct device *parent = pdev->dev.parent; + struct pci_dev *pcidev = dev_is_pci(parent) ? to_pci_dev(parent) : NULL; const struct pci_device_id *pcidev_id = NULL; - const struct of_device_id *of_id = NULL; enum pxa_ssp_type type; + const void *match; - adev = ACPI_COMPANION(&pdev->dev); - - if (pdev->dev.of_node) - of_id = of_match_device(pdev->dev.driver->of_match_table, - &pdev->dev); - else if (dev_is_pci(pdev->dev.parent)) - pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match, - to_pci_dev(pdev->dev.parent)); - else if (adev) - adev_id = acpi_match_device(pdev->dev.driver->acpi_match_table, - &pdev->dev); - else - return NULL; + if (pcidev) + pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match, pcidev); - if (adev_id) - type = (enum pxa_ssp_type)adev_id->driver_data; + match = device_get_match_data(&pdev->dev); + if (match) + type = (enum pxa_ssp_type)match; else if (pcidev_id) type = (enum pxa_ssp_type)pcidev_id->driver_data; - else if (of_id) - type = (enum pxa_ssp_type)of_id->data; else return NULL; @@ -1545,32 +1554,36 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) if (!pdata) return NULL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return NULL; - ssp = &pdata->ssp; - ssp->phys_base = res->start; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ssp->mmio_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(ssp->mmio_base)) return NULL; + ssp->phys_base = res->start; + #ifdef CONFIG_PCI if (pcidev_id) { - pdata->tx_param = pdev->dev.parent; - pdata->rx_param = pdev->dev.parent; + pdata->tx_param = parent; + pdata->rx_param = parent; pdata->dma_filter = pxa2xx_spi_idma_filter; } #endif ssp->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ssp->clk)) + return NULL; + ssp->irq = platform_get_irq(pdev, 0); + if (ssp->irq < 0) + return NULL; + ssp->type = type; - ssp->pdev = pdev; - ssp->port_id = pxa2xx_spi_get_port_id(adev); + ssp->dev = &pdev->dev; + ssp->port_id = pxa2xx_spi_get_port_id(&pdev->dev); - pdata->is_slave = of_property_read_bool(pdev->dev.of_node, "spi-slave"); + pdata->is_slave = device_property_read_bool(&pdev->dev, "spi-slave"); pdata->num_chipselect = 1; pdata->enable_dma = true; pdata->dma_burst_size = 1; @@ -1602,6 +1615,11 @@ static int pxa2xx_spi_fw_translate_cs(struct spi_controller *controller, return cs; } +static size_t pxa2xx_spi_max_dma_transfer_size(struct spi_device *spi) +{ + return MAX_DMA_LEN; +} + static int pxa2xx_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1707,6 +1725,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) } else { controller->can_dma = pxa2xx_spi_can_dma; controller->max_dma_len = MAX_DMA_LEN; + controller->max_transfer_size = + pxa2xx_spi_max_dma_transfer_size; } } diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c index e0f061139c8f..3c4f83bf7084 100644 --- a/drivers/spi/spi-qcom-qspi.c +++ b/drivers/spi/spi-qcom-qspi.c @@ -137,7 +137,7 @@ enum qspi_clocks { struct qcom_qspi { void __iomem *base; struct device *dev; - struct clk_bulk_data clks[QSPI_NUM_CLKS]; + struct clk_bulk_data *clks; struct qspi_xfer xfer; /* Lock to protect xfer and IRQ accessed registers */ spinlock_t lock; @@ -424,7 +424,6 @@ static int qcom_qspi_probe(struct platform_device *pdev) { int ret; struct device *dev; - struct resource *res; struct spi_master *master; struct qcom_qspi *ctrl; @@ -440,13 +439,19 @@ static int qcom_qspi_probe(struct platform_device *pdev) spin_lock_init(&ctrl->lock); ctrl->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ctrl->base = devm_ioremap_resource(dev, res); + ctrl->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ctrl->base)) { ret = PTR_ERR(ctrl->base); goto exit_probe_master_put; } + ctrl->clks = devm_kcalloc(dev, QSPI_NUM_CLKS, + sizeof(*ctrl->clks), GFP_KERNEL); + if (!ctrl->clks) { + ret = -ENOMEM; + goto exit_probe_master_put; + } + ctrl->clks[QSPI_CLK_CORE].id = "core"; ctrl->clks[QSPI_CLK_IFACE].id = "iface"; ret = devm_clk_bulk_get(dev, QSPI_NUM_CLKS, ctrl->clks); @@ -454,10 +459,8 @@ static int qcom_qspi_probe(struct platform_device *pdev) goto exit_probe_master_put; ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "Failed to get irq %d\n", ret); + if (ret < 0) goto exit_probe_master_put; - } ret = devm_request_irq(dev, ret, qcom_qspi_irq, IRQF_TRIGGER_HIGH, dev_name(dev), ctrl); if (ret) { diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 2f559e531100..dd3434a407ea 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -932,11 +932,11 @@ static int spi_qup_init_dma(struct spi_master *master, resource_size_t base) int ret; /* allocate dma resources, if available */ - master->dma_rx = dma_request_slave_channel_reason(dev, "rx"); + master->dma_rx = dma_request_chan(dev, "rx"); if (IS_ERR(master->dma_rx)) return PTR_ERR(master->dma_rx); - master->dma_tx = dma_request_slave_channel_reason(dev, "tx"); + master->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR(master->dma_tx)) { ret = PTR_ERR(master->dma_tx); goto err_tx; diff --git a/drivers/spi/spi-rb4xx.c b/drivers/spi/spi-rb4xx.c index 51f03d977ad6..4c9620e0d18c 100644 --- a/drivers/spi/spi-rb4xx.c +++ b/drivers/spi/spi-rb4xx.c @@ -135,12 +135,10 @@ static int rb4xx_spi_probe(struct platform_device *pdev) struct spi_master *master; struct clk *ahb_clk; struct rb4xx_spi *rbspi; - struct resource *r; int err; void __iomem *spi_base; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi_base = devm_ioremap_resource(&pdev->dev, r); + spi_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi_base)) return PTR_ERR(spi_base); diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 15f5723d9f95..85575d45901c 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -159,7 +159,7 @@ #define SPCMD_SPIMOD_DUAL SPCMD_SPIMOD0 #define SPCMD_SPIMOD_QUAD SPCMD_SPIMOD1 #define SPCMD_SPRW 0x0010 /* SPI Read/Write Access (Dual/Quad) */ -#define SPCMD_SSLA_MASK 0x0030 /* SSL Assert Signal Setting (RSPI) */ +#define SPCMD_SSLA(i) ((i) << 4) /* SSL Assert Signal Setting */ #define SPCMD_BRDV_MASK 0x000c /* Bit Rate Division Setting */ #define SPCMD_CPOL 0x0002 /* Clock Polarity Setting */ #define SPCMD_CPHA 0x0001 /* Clock Phase Setting */ @@ -242,6 +242,7 @@ struct spi_ops { u16 mode_bits; u16 flags; u16 fifo_size; + u8 num_hw_ss; }; /* @@ -426,8 +427,6 @@ static int qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) return n; } -#define set_config_register(spi, n) spi->ops->set_config_register(spi, n) - static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable) { rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR); @@ -620,9 +619,8 @@ no_dma_tx: dmaengine_terminate_all(rspi->ctlr->dma_rx); no_dma_rx: if (ret == -EAGAIN) { - pr_warn_once("%s %s: DMA not available, falling back to PIO\n", - dev_driver_string(&rspi->ctlr->dev), - dev_name(&rspi->ctlr->dev)); + dev_warn_once(&rspi->ctlr->dev, + "DMA not available, falling back to PIO\n"); } return ret; } @@ -936,12 +934,16 @@ static int rspi_prepare_message(struct spi_controller *ctlr, if (spi->mode & SPI_CPHA) rspi->spcmd |= SPCMD_CPHA; + /* Configure slave signal to assert */ + rspi->spcmd |= SPCMD_SSLA(spi->cs_gpiod ? rspi->ctlr->unused_native_cs + : spi->chip_select); + /* CMOS output mode and MOSI signal from previous transfer */ rspi->sppcr = 0; if (spi->mode & SPI_LOOP) rspi->sppcr |= SPPCR_SPLP; - set_config_register(rspi, 8); + rspi->ops->set_config_register(rspi, 8); if (msg->spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) { @@ -1123,6 +1125,7 @@ static const struct spi_ops rspi_ops = { .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, .flags = SPI_CONTROLLER_MUST_TX, .fifo_size = 8, + .num_hw_ss = 2, }; static const struct spi_ops rspi_rz_ops = { @@ -1131,6 +1134,7 @@ static const struct spi_ops rspi_rz_ops = { .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, .fifo_size = 8, /* 8 for TX, 32 for RX */ + .num_hw_ss = 1, }; static const struct spi_ops qspi_ops = { @@ -1141,6 +1145,7 @@ static const struct spi_ops qspi_ops = { SPI_RX_DUAL | SPI_RX_QUAD, .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, .fifo_size = 32, + .num_hw_ss = 1, }; #ifdef CONFIG_OF @@ -1256,10 +1261,12 @@ static int rspi_probe(struct platform_device *pdev) ctlr->mode_bits = ops->mode_bits; ctlr->flags = ops->flags; ctlr->dev.of_node = pdev->dev.of_node; + ctlr->use_gpio_descriptors = true; + ctlr->max_native_cs = rspi->ops->num_hw_ss; - ret = platform_get_irq_byname(pdev, "rx"); + ret = platform_get_irq_byname_optional(pdev, "rx"); if (ret < 0) { - ret = platform_get_irq_byname(pdev, "mux"); + ret = platform_get_irq_byname_optional(pdev, "mux"); if (ret < 0) ret = platform_get_irq(pdev, 0); if (ret >= 0) @@ -1270,10 +1277,6 @@ static int rspi_probe(struct platform_device *pdev) if (ret >= 0) rspi->tx_irq = ret; } - if (ret < 0) { - dev_err(&pdev->dev, "platform_get_irq error\n"); - goto error2; - } if (rspi->rx_irq == rspi->tx_irq) { /* Single multiplexed interrupt */ @@ -1318,8 +1321,6 @@ error1: static const struct platform_device_id spi_driver_ids[] = { { "rspi", (kernel_ulong_t)&rspi_ops }, - { "rspi-rz", (kernel_ulong_t)&rspi_rz_ops }, - { "qspi", (kernel_ulong_t)&qspi_ops }, {}, }; diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index 48d8dff05a3a..2d6e37f25e2d 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -487,7 +487,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) struct s3c2410_spi_info *pdata; struct s3c24xx_spi *hw; struct spi_master *master; - struct resource *res; int err = 0; master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); @@ -536,8 +535,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang); /* find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hw->regs = devm_ioremap_resource(&pdev->dev, res); + hw->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hw->regs)) { err = PTR_ERR(hw->regs); goto err_no_pdata; @@ -545,7 +543,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) hw->irq = platform_get_irq(pdev, 0); if (hw->irq < 0) { - dev_err(&pdev->dev, "No IRQ specified\n"); err = -ENOENT; goto err_no_pdata; } diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 7b7151ec14c8..cf67ea60dc0e 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1154,15 +1154,13 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) if (!is_polling(sdd)) { /* Acquire DMA channels */ - sdd->rx_dma.ch = dma_request_slave_channel_reason(&pdev->dev, - "rx"); + sdd->rx_dma.ch = dma_request_chan(&pdev->dev, "rx"); if (IS_ERR(sdd->rx_dma.ch)) { dev_err(&pdev->dev, "Failed to get RX DMA channel\n"); ret = PTR_ERR(sdd->rx_dma.ch); goto err_disable_io_clk; } - sdd->tx_dma.ch = dma_request_slave_channel_reason(&pdev->dev, - "tx"); + sdd->tx_dma.ch = dma_request_chan(&pdev->dev, "tx"); if (IS_ERR(sdd->tx_dma.ch)) { dev_err(&pdev->dev, "Failed to get TX DMA channel\n"); ret = PTR_ERR(sdd->tx_dma.ch); diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c index 11acddc83304..5497eeb3bf3e 100644 --- a/drivers/spi/spi-sc18is602.c +++ b/drivers/spi/spi-sc18is602.c @@ -211,8 +211,7 @@ static int sc18is602_transfer_one(struct spi_master *master, } status = 0; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); } m->status = status; spi_finalize_current_message(master); diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index 7f73f91d412a..a62034e2a7cb 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -190,8 +190,7 @@ static int hspi_transfer_one_message(struct spi_controller *ctlr, msg->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (cs_change) { ndelay(nsecs); diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index b50bdbc27e58..1c11a00a2c36 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -14,8 +14,6 @@ #include <linux/dma-mapping.h> #include <linux/dmaengine.h> #include <linux/err.h> -#include <linux/gpio.h> -#include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/iopoll.h> @@ -55,7 +53,6 @@ struct sh_msiof_spi_priv { void *rx_dma_page; dma_addr_t tx_dma_addr; dma_addr_t rx_dma_addr; - unsigned short unused_ss; bool native_cs_inited; bool native_cs_high; bool slave_aborted; @@ -63,140 +60,140 @@ struct sh_msiof_spi_priv { #define MAX_SS 3 /* Maximum number of native chip selects */ -#define TMDR1 0x00 /* Transmit Mode Register 1 */ -#define TMDR2 0x04 /* Transmit Mode Register 2 */ -#define TMDR3 0x08 /* Transmit Mode Register 3 */ -#define RMDR1 0x10 /* Receive Mode Register 1 */ -#define RMDR2 0x14 /* Receive Mode Register 2 */ -#define RMDR3 0x18 /* Receive Mode Register 3 */ -#define TSCR 0x20 /* Transmit Clock Select Register */ -#define RSCR 0x22 /* Receive Clock Select Register (SH, A1, APE6) */ -#define CTR 0x28 /* Control Register */ -#define FCTR 0x30 /* FIFO Control Register */ -#define STR 0x40 /* Status Register */ -#define IER 0x44 /* Interrupt Enable Register */ -#define TDR1 0x48 /* Transmit Control Data Register 1 (SH, A1) */ -#define TDR2 0x4c /* Transmit Control Data Register 2 (SH, A1) */ -#define TFDR 0x50 /* Transmit FIFO Data Register */ -#define RDR1 0x58 /* Receive Control Data Register 1 (SH, A1) */ -#define RDR2 0x5c /* Receive Control Data Register 2 (SH, A1) */ -#define RFDR 0x60 /* Receive FIFO Data Register */ - -/* TMDR1 and RMDR1 */ -#define MDR1_TRMD BIT(31) /* Transfer Mode (1 = Master mode) */ -#define MDR1_SYNCMD_MASK GENMASK(29, 28) /* SYNC Mode */ -#define MDR1_SYNCMD_SPI (2 << 28)/* Level mode/SPI */ -#define MDR1_SYNCMD_LR (3 << 28)/* L/R mode */ -#define MDR1_SYNCAC_SHIFT 25 /* Sync Polarity (1 = Active-low) */ -#define MDR1_BITLSB_SHIFT 24 /* MSB/LSB First (1 = LSB first) */ -#define MDR1_DTDL_SHIFT 20 /* Data Pin Bit Delay for MSIOF_SYNC */ -#define MDR1_SYNCDL_SHIFT 16 /* Frame Sync Signal Timing Delay */ -#define MDR1_FLD_MASK GENMASK(3, 2) /* Frame Sync Signal Interval (0-3) */ -#define MDR1_FLD_SHIFT 2 -#define MDR1_XXSTP BIT(0) /* Transmission/Reception Stop on FIFO */ -/* TMDR1 */ -#define TMDR1_PCON BIT(30) /* Transfer Signal Connection */ -#define TMDR1_SYNCCH_MASK GENMASK(27, 26) /* Sync Signal Channel Select */ -#define TMDR1_SYNCCH_SHIFT 26 /* 0=MSIOF_SYNC, 1=MSIOF_SS1, 2=MSIOF_SS2 */ - -/* TMDR2 and RMDR2 */ -#define MDR2_BITLEN1(i) (((i) - 1) << 24) /* Data Size (8-32 bits) */ -#define MDR2_WDLEN1(i) (((i) - 1) << 16) /* Word Count (1-64/256 (SH, A1))) */ -#define MDR2_GRPMASK1 BIT(0) /* Group Output Mask 1 (SH, A1) */ - -/* TSCR and RSCR */ -#define SCR_BRPS_MASK GENMASK(12, 8) /* Prescaler Setting (1-32) */ -#define SCR_BRPS(i) (((i) - 1) << 8) -#define SCR_BRDV_MASK GENMASK(2, 0) /* Baud Rate Generator's Division Ratio */ -#define SCR_BRDV_DIV_2 0 -#define SCR_BRDV_DIV_4 1 -#define SCR_BRDV_DIV_8 2 -#define SCR_BRDV_DIV_16 3 -#define SCR_BRDV_DIV_32 4 -#define SCR_BRDV_DIV_1 7 - -/* CTR */ -#define CTR_TSCKIZ_MASK GENMASK(31, 30) /* Transmit Clock I/O Polarity Select */ -#define CTR_TSCKIZ_SCK BIT(31) /* Disable SCK when TX disabled */ -#define CTR_TSCKIZ_POL_SHIFT 30 /* Transmit Clock Polarity */ -#define CTR_RSCKIZ_MASK GENMASK(29, 28) /* Receive Clock Polarity Select */ -#define CTR_RSCKIZ_SCK BIT(29) /* Must match CTR_TSCKIZ_SCK */ -#define CTR_RSCKIZ_POL_SHIFT 28 /* Receive Clock Polarity */ -#define CTR_TEDG_SHIFT 27 /* Transmit Timing (1 = falling edge) */ -#define CTR_REDG_SHIFT 26 /* Receive Timing (1 = falling edge) */ -#define CTR_TXDIZ_MASK GENMASK(23, 22) /* Pin Output When TX is Disabled */ -#define CTR_TXDIZ_LOW (0 << 22) /* 0 */ -#define CTR_TXDIZ_HIGH (1 << 22) /* 1 */ -#define CTR_TXDIZ_HIZ (2 << 22) /* High-impedance */ -#define CTR_TSCKE BIT(15) /* Transmit Serial Clock Output Enable */ -#define CTR_TFSE BIT(14) /* Transmit Frame Sync Signal Output Enable */ -#define CTR_TXE BIT(9) /* Transmit Enable */ -#define CTR_RXE BIT(8) /* Receive Enable */ -#define CTR_TXRST BIT(1) /* Transmit Reset */ -#define CTR_RXRST BIT(0) /* Receive Reset */ - -/* FCTR */ -#define FCTR_TFWM_MASK GENMASK(31, 29) /* Transmit FIFO Watermark */ -#define FCTR_TFWM_64 (0 << 29) /* Transfer Request when 64 empty stages */ -#define FCTR_TFWM_32 (1 << 29) /* Transfer Request when 32 empty stages */ -#define FCTR_TFWM_24 (2 << 29) /* Transfer Request when 24 empty stages */ -#define FCTR_TFWM_16 (3 << 29) /* Transfer Request when 16 empty stages */ -#define FCTR_TFWM_12 (4 << 29) /* Transfer Request when 12 empty stages */ -#define FCTR_TFWM_8 (5 << 29) /* Transfer Request when 8 empty stages */ -#define FCTR_TFWM_4 (6 << 29) /* Transfer Request when 4 empty stages */ -#define FCTR_TFWM_1 (7 << 29) /* Transfer Request when 1 empty stage */ -#define FCTR_TFUA_MASK GENMASK(26, 20) /* Transmit FIFO Usable Area */ -#define FCTR_TFUA_SHIFT 20 -#define FCTR_TFUA(i) ((i) << FCTR_TFUA_SHIFT) -#define FCTR_RFWM_MASK GENMASK(15, 13) /* Receive FIFO Watermark */ -#define FCTR_RFWM_1 (0 << 13) /* Transfer Request when 1 valid stages */ -#define FCTR_RFWM_4 (1 << 13) /* Transfer Request when 4 valid stages */ -#define FCTR_RFWM_8 (2 << 13) /* Transfer Request when 8 valid stages */ -#define FCTR_RFWM_16 (3 << 13) /* Transfer Request when 16 valid stages */ -#define FCTR_RFWM_32 (4 << 13) /* Transfer Request when 32 valid stages */ -#define FCTR_RFWM_64 (5 << 13) /* Transfer Request when 64 valid stages */ -#define FCTR_RFWM_128 (6 << 13) /* Transfer Request when 128 valid stages */ -#define FCTR_RFWM_256 (7 << 13) /* Transfer Request when 256 valid stages */ -#define FCTR_RFUA_MASK GENMASK(12, 4) /* Receive FIFO Usable Area (0x40 = full) */ -#define FCTR_RFUA_SHIFT 4 -#define FCTR_RFUA(i) ((i) << FCTR_RFUA_SHIFT) - -/* STR */ -#define STR_TFEMP BIT(29) /* Transmit FIFO Empty */ -#define STR_TDREQ BIT(28) /* Transmit Data Transfer Request */ -#define STR_TEOF BIT(23) /* Frame Transmission End */ -#define STR_TFSERR BIT(21) /* Transmit Frame Synchronization Error */ -#define STR_TFOVF BIT(20) /* Transmit FIFO Overflow */ -#define STR_TFUDF BIT(19) /* Transmit FIFO Underflow */ -#define STR_RFFUL BIT(13) /* Receive FIFO Full */ -#define STR_RDREQ BIT(12) /* Receive Data Transfer Request */ -#define STR_REOF BIT(7) /* Frame Reception End */ -#define STR_RFSERR BIT(5) /* Receive Frame Synchronization Error */ -#define STR_RFUDF BIT(4) /* Receive FIFO Underflow */ -#define STR_RFOVF BIT(3) /* Receive FIFO Overflow */ - -/* IER */ -#define IER_TDMAE BIT(31) /* Transmit Data DMA Transfer Req. Enable */ -#define IER_TFEMPE BIT(29) /* Transmit FIFO Empty Enable */ -#define IER_TDREQE BIT(28) /* Transmit Data Transfer Request Enable */ -#define IER_TEOFE BIT(23) /* Frame Transmission End Enable */ -#define IER_TFSERRE BIT(21) /* Transmit Frame Sync Error Enable */ -#define IER_TFOVFE BIT(20) /* Transmit FIFO Overflow Enable */ -#define IER_TFUDFE BIT(19) /* Transmit FIFO Underflow Enable */ -#define IER_RDMAE BIT(15) /* Receive Data DMA Transfer Req. Enable */ -#define IER_RFFULE BIT(13) /* Receive FIFO Full Enable */ -#define IER_RDREQE BIT(12) /* Receive Data Transfer Request Enable */ -#define IER_REOFE BIT(7) /* Frame Reception End Enable */ -#define IER_RFSERRE BIT(5) /* Receive Frame Sync Error Enable */ -#define IER_RFUDFE BIT(4) /* Receive FIFO Underflow Enable */ -#define IER_RFOVFE BIT(3) /* Receive FIFO Overflow Enable */ +#define SITMDR1 0x00 /* Transmit Mode Register 1 */ +#define SITMDR2 0x04 /* Transmit Mode Register 2 */ +#define SITMDR3 0x08 /* Transmit Mode Register 3 */ +#define SIRMDR1 0x10 /* Receive Mode Register 1 */ +#define SIRMDR2 0x14 /* Receive Mode Register 2 */ +#define SIRMDR3 0x18 /* Receive Mode Register 3 */ +#define SITSCR 0x20 /* Transmit Clock Select Register */ +#define SIRSCR 0x22 /* Receive Clock Select Register (SH, A1, APE6) */ +#define SICTR 0x28 /* Control Register */ +#define SIFCTR 0x30 /* FIFO Control Register */ +#define SISTR 0x40 /* Status Register */ +#define SIIER 0x44 /* Interrupt Enable Register */ +#define SITDR1 0x48 /* Transmit Control Data Register 1 (SH, A1) */ +#define SITDR2 0x4c /* Transmit Control Data Register 2 (SH, A1) */ +#define SITFDR 0x50 /* Transmit FIFO Data Register */ +#define SIRDR1 0x58 /* Receive Control Data Register 1 (SH, A1) */ +#define SIRDR2 0x5c /* Receive Control Data Register 2 (SH, A1) */ +#define SIRFDR 0x60 /* Receive FIFO Data Register */ + +/* SITMDR1 and SIRMDR1 */ +#define SIMDR1_TRMD BIT(31) /* Transfer Mode (1 = Master mode) */ +#define SIMDR1_SYNCMD_MASK GENMASK(29, 28) /* SYNC Mode */ +#define SIMDR1_SYNCMD_SPI (2 << 28) /* Level mode/SPI */ +#define SIMDR1_SYNCMD_LR (3 << 28) /* L/R mode */ +#define SIMDR1_SYNCAC_SHIFT 25 /* Sync Polarity (1 = Active-low) */ +#define SIMDR1_BITLSB_SHIFT 24 /* MSB/LSB First (1 = LSB first) */ +#define SIMDR1_DTDL_SHIFT 20 /* Data Pin Bit Delay for MSIOF_SYNC */ +#define SIMDR1_SYNCDL_SHIFT 16 /* Frame Sync Signal Timing Delay */ +#define SIMDR1_FLD_MASK GENMASK(3, 2) /* Frame Sync Signal Interval (0-3) */ +#define SIMDR1_FLD_SHIFT 2 +#define SIMDR1_XXSTP BIT(0) /* Transmission/Reception Stop on FIFO */ +/* SITMDR1 */ +#define SITMDR1_PCON BIT(30) /* Transfer Signal Connection */ +#define SITMDR1_SYNCCH_MASK GENMASK(27, 26) /* Sync Signal Channel Select */ +#define SITMDR1_SYNCCH_SHIFT 26 /* 0=MSIOF_SYNC, 1=MSIOF_SS1, 2=MSIOF_SS2 */ + +/* SITMDR2 and SIRMDR2 */ +#define SIMDR2_BITLEN1(i) (((i) - 1) << 24) /* Data Size (8-32 bits) */ +#define SIMDR2_WDLEN1(i) (((i) - 1) << 16) /* Word Count (1-64/256 (SH, A1))) */ +#define SIMDR2_GRPMASK1 BIT(0) /* Group Output Mask 1 (SH, A1) */ + +/* SITSCR and SIRSCR */ +#define SISCR_BRPS_MASK GENMASK(12, 8) /* Prescaler Setting (1-32) */ +#define SISCR_BRPS(i) (((i) - 1) << 8) +#define SISCR_BRDV_MASK GENMASK(2, 0) /* Baud Rate Generator's Division Ratio */ +#define SISCR_BRDV_DIV_2 0 +#define SISCR_BRDV_DIV_4 1 +#define SISCR_BRDV_DIV_8 2 +#define SISCR_BRDV_DIV_16 3 +#define SISCR_BRDV_DIV_32 4 +#define SISCR_BRDV_DIV_1 7 + +/* SICTR */ +#define SICTR_TSCKIZ_MASK GENMASK(31, 30) /* Transmit Clock I/O Polarity Select */ +#define SICTR_TSCKIZ_SCK BIT(31) /* Disable SCK when TX disabled */ +#define SICTR_TSCKIZ_POL_SHIFT 30 /* Transmit Clock Polarity */ +#define SICTR_RSCKIZ_MASK GENMASK(29, 28) /* Receive Clock Polarity Select */ +#define SICTR_RSCKIZ_SCK BIT(29) /* Must match CTR_TSCKIZ_SCK */ +#define SICTR_RSCKIZ_POL_SHIFT 28 /* Receive Clock Polarity */ +#define SICTR_TEDG_SHIFT 27 /* Transmit Timing (1 = falling edge) */ +#define SICTR_REDG_SHIFT 26 /* Receive Timing (1 = falling edge) */ +#define SICTR_TXDIZ_MASK GENMASK(23, 22) /* Pin Output When TX is Disabled */ +#define SICTR_TXDIZ_LOW (0 << 22) /* 0 */ +#define SICTR_TXDIZ_HIGH (1 << 22) /* 1 */ +#define SICTR_TXDIZ_HIZ (2 << 22) /* High-impedance */ +#define SICTR_TSCKE BIT(15) /* Transmit Serial Clock Output Enable */ +#define SICTR_TFSE BIT(14) /* Transmit Frame Sync Signal Output Enable */ +#define SICTR_TXE BIT(9) /* Transmit Enable */ +#define SICTR_RXE BIT(8) /* Receive Enable */ +#define SICTR_TXRST BIT(1) /* Transmit Reset */ +#define SICTR_RXRST BIT(0) /* Receive Reset */ + +/* SIFCTR */ +#define SIFCTR_TFWM_MASK GENMASK(31, 29) /* Transmit FIFO Watermark */ +#define SIFCTR_TFWM_64 (0 << 29) /* Transfer Request when 64 empty stages */ +#define SIFCTR_TFWM_32 (1 << 29) /* Transfer Request when 32 empty stages */ +#define SIFCTR_TFWM_24 (2 << 29) /* Transfer Request when 24 empty stages */ +#define SIFCTR_TFWM_16 (3 << 29) /* Transfer Request when 16 empty stages */ +#define SIFCTR_TFWM_12 (4 << 29) /* Transfer Request when 12 empty stages */ +#define SIFCTR_TFWM_8 (5 << 29) /* Transfer Request when 8 empty stages */ +#define SIFCTR_TFWM_4 (6 << 29) /* Transfer Request when 4 empty stages */ +#define SIFCTR_TFWM_1 (7 << 29) /* Transfer Request when 1 empty stage */ +#define SIFCTR_TFUA_MASK GENMASK(26, 20) /* Transmit FIFO Usable Area */ +#define SIFCTR_TFUA_SHIFT 20 +#define SIFCTR_TFUA(i) ((i) << SIFCTR_TFUA_SHIFT) +#define SIFCTR_RFWM_MASK GENMASK(15, 13) /* Receive FIFO Watermark */ +#define SIFCTR_RFWM_1 (0 << 13) /* Transfer Request when 1 valid stages */ +#define SIFCTR_RFWM_4 (1 << 13) /* Transfer Request when 4 valid stages */ +#define SIFCTR_RFWM_8 (2 << 13) /* Transfer Request when 8 valid stages */ +#define SIFCTR_RFWM_16 (3 << 13) /* Transfer Request when 16 valid stages */ +#define SIFCTR_RFWM_32 (4 << 13) /* Transfer Request when 32 valid stages */ +#define SIFCTR_RFWM_64 (5 << 13) /* Transfer Request when 64 valid stages */ +#define SIFCTR_RFWM_128 (6 << 13) /* Transfer Request when 128 valid stages */ +#define SIFCTR_RFWM_256 (7 << 13) /* Transfer Request when 256 valid stages */ +#define SIFCTR_RFUA_MASK GENMASK(12, 4) /* Receive FIFO Usable Area (0x40 = full) */ +#define SIFCTR_RFUA_SHIFT 4 +#define SIFCTR_RFUA(i) ((i) << SIFCTR_RFUA_SHIFT) + +/* SISTR */ +#define SISTR_TFEMP BIT(29) /* Transmit FIFO Empty */ +#define SISTR_TDREQ BIT(28) /* Transmit Data Transfer Request */ +#define SISTR_TEOF BIT(23) /* Frame Transmission End */ +#define SISTR_TFSERR BIT(21) /* Transmit Frame Synchronization Error */ +#define SISTR_TFOVF BIT(20) /* Transmit FIFO Overflow */ +#define SISTR_TFUDF BIT(19) /* Transmit FIFO Underflow */ +#define SISTR_RFFUL BIT(13) /* Receive FIFO Full */ +#define SISTR_RDREQ BIT(12) /* Receive Data Transfer Request */ +#define SISTR_REOF BIT(7) /* Frame Reception End */ +#define SISTR_RFSERR BIT(5) /* Receive Frame Synchronization Error */ +#define SISTR_RFUDF BIT(4) /* Receive FIFO Underflow */ +#define SISTR_RFOVF BIT(3) /* Receive FIFO Overflow */ + +/* SIIER */ +#define SIIER_TDMAE BIT(31) /* Transmit Data DMA Transfer Req. Enable */ +#define SIIER_TFEMPE BIT(29) /* Transmit FIFO Empty Enable */ +#define SIIER_TDREQE BIT(28) /* Transmit Data Transfer Request Enable */ +#define SIIER_TEOFE BIT(23) /* Frame Transmission End Enable */ +#define SIIER_TFSERRE BIT(21) /* Transmit Frame Sync Error Enable */ +#define SIIER_TFOVFE BIT(20) /* Transmit FIFO Overflow Enable */ +#define SIIER_TFUDFE BIT(19) /* Transmit FIFO Underflow Enable */ +#define SIIER_RDMAE BIT(15) /* Receive Data DMA Transfer Req. Enable */ +#define SIIER_RFFULE BIT(13) /* Receive FIFO Full Enable */ +#define SIIER_RDREQE BIT(12) /* Receive Data Transfer Request Enable */ +#define SIIER_REOFE BIT(7) /* Frame Reception End Enable */ +#define SIIER_RFSERRE BIT(5) /* Receive Frame Sync Error Enable */ +#define SIIER_RFUDFE BIT(4) /* Receive FIFO Underflow Enable */ +#define SIIER_RFOVFE BIT(3) /* Receive FIFO Overflow Enable */ static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) { switch (reg_offs) { - case TSCR: - case RSCR: + case SITSCR: + case SIRSCR: return ioread16(p->mapbase + reg_offs); default: return ioread32(p->mapbase + reg_offs); @@ -207,8 +204,8 @@ static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs, u32 value) { switch (reg_offs) { - case TSCR: - case RSCR: + case SITSCR: + case SIRSCR: iowrite16(value, p->mapbase + reg_offs); break; default: @@ -223,12 +220,12 @@ static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p, u32 mask = clr | set; u32 data; - data = sh_msiof_read(p, CTR); + data = sh_msiof_read(p, SICTR); data &= ~clr; data |= set; - sh_msiof_write(p, CTR, data); + sh_msiof_write(p, SICTR, data); - return readl_poll_timeout_atomic(p->mapbase + CTR, data, + return readl_poll_timeout_atomic(p->mapbase + SICTR, data, (data & mask) == set, 1, 100); } @@ -237,7 +234,7 @@ static irqreturn_t sh_msiof_spi_irq(int irq, void *data) struct sh_msiof_spi_priv *p = data; /* just disable the interrupt and wake up */ - sh_msiof_write(p, IER, 0); + sh_msiof_write(p, SIIER, 0); complete(&p->done); return IRQ_HANDLED; @@ -245,20 +242,20 @@ static irqreturn_t sh_msiof_spi_irq(int irq, void *data) static void sh_msiof_spi_reset_regs(struct sh_msiof_spi_priv *p) { - u32 mask = CTR_TXRST | CTR_RXRST; + u32 mask = SICTR_TXRST | SICTR_RXRST; u32 data; - data = sh_msiof_read(p, CTR); + data = sh_msiof_read(p, SICTR); data |= mask; - sh_msiof_write(p, CTR, data); + sh_msiof_write(p, SICTR, data); - readl_poll_timeout_atomic(p->mapbase + CTR, data, !(data & mask), 1, + readl_poll_timeout_atomic(p->mapbase + SICTR, data, !(data & mask), 1, 100); } static const u32 sh_msiof_spi_div_array[] = { - SCR_BRDV_DIV_1, SCR_BRDV_DIV_2, SCR_BRDV_DIV_4, - SCR_BRDV_DIV_8, SCR_BRDV_DIV_16, SCR_BRDV_DIV_32, + SISCR_BRDV_DIV_1, SISCR_BRDV_DIV_2, SISCR_BRDV_DIV_4, + SISCR_BRDV_DIV_8, SISCR_BRDV_DIV_16, SISCR_BRDV_DIV_32, }; static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, @@ -276,7 +273,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, div = DIV_ROUND_UP(parent_rate, spi_hz); if (div <= 1024) { - /* SCR_BRDV_DIV_1 is valid only if BRPS is x 1/1 or x 1/2 */ + /* SISCR_BRDV_DIV_1 is valid only if BRPS is x 1/1 or x 1/2 */ if (!div_pow && div <= 32 && div > 2) div_pow = 1; @@ -295,10 +292,10 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p, brps = 32; } - scr = sh_msiof_spi_div_array[div_pow] | SCR_BRPS(brps); - sh_msiof_write(p, TSCR, scr); + scr = sh_msiof_spi_div_array[div_pow] | SISCR_BRPS(brps); + sh_msiof_write(p, SITSCR, scr); if (!(p->ctlr->flags & SPI_CONTROLLER_MUST_TX)) - sh_msiof_write(p, RSCR, scr); + sh_msiof_write(p, SIRSCR, scr); } static u32 sh_msiof_get_delay_bit(u32 dtdl_or_syncdl) @@ -337,8 +334,8 @@ static u32 sh_msiof_spi_get_dtdl_and_syncdl(struct sh_msiof_spi_priv *p) return 0; } - val = sh_msiof_get_delay_bit(p->info->dtdl) << MDR1_DTDL_SHIFT; - val |= sh_msiof_get_delay_bit(p->info->syncdl) << MDR1_SYNCDL_SHIFT; + val = sh_msiof_get_delay_bit(p->info->dtdl) << SIMDR1_DTDL_SHIFT; + val |= sh_msiof_get_delay_bit(p->info->syncdl) << SIMDR1_SYNCDL_SHIFT; return val; } @@ -357,54 +354,54 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, u32 ss, * 1 0 11 11 0 0 * 1 1 11 11 1 1 */ - tmp = MDR1_SYNCMD_SPI | 1 << MDR1_FLD_SHIFT | MDR1_XXSTP; - tmp |= !cs_high << MDR1_SYNCAC_SHIFT; - tmp |= lsb_first << MDR1_BITLSB_SHIFT; + tmp = SIMDR1_SYNCMD_SPI | 1 << SIMDR1_FLD_SHIFT | SIMDR1_XXSTP; + tmp |= !cs_high << SIMDR1_SYNCAC_SHIFT; + tmp |= lsb_first << SIMDR1_BITLSB_SHIFT; tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p); if (spi_controller_is_slave(p->ctlr)) { - sh_msiof_write(p, TMDR1, tmp | TMDR1_PCON); + sh_msiof_write(p, SITMDR1, tmp | SITMDR1_PCON); } else { - sh_msiof_write(p, TMDR1, - tmp | MDR1_TRMD | TMDR1_PCON | - (ss < MAX_SS ? ss : 0) << TMDR1_SYNCCH_SHIFT); + sh_msiof_write(p, SITMDR1, + tmp | SIMDR1_TRMD | SITMDR1_PCON | + (ss < MAX_SS ? ss : 0) << SITMDR1_SYNCCH_SHIFT); } if (p->ctlr->flags & SPI_CONTROLLER_MUST_TX) { /* These bits are reserved if RX needs TX */ tmp &= ~0x0000ffff; } - sh_msiof_write(p, RMDR1, tmp); + sh_msiof_write(p, SIRMDR1, tmp); tmp = 0; - tmp |= CTR_TSCKIZ_SCK | cpol << CTR_TSCKIZ_POL_SHIFT; - tmp |= CTR_RSCKIZ_SCK | cpol << CTR_RSCKIZ_POL_SHIFT; + tmp |= SICTR_TSCKIZ_SCK | cpol << SICTR_TSCKIZ_POL_SHIFT; + tmp |= SICTR_RSCKIZ_SCK | cpol << SICTR_RSCKIZ_POL_SHIFT; edge = cpol ^ !cpha; - tmp |= edge << CTR_TEDG_SHIFT; - tmp |= edge << CTR_REDG_SHIFT; - tmp |= tx_hi_z ? CTR_TXDIZ_HIZ : CTR_TXDIZ_LOW; - sh_msiof_write(p, CTR, tmp); + tmp |= edge << SICTR_TEDG_SHIFT; + tmp |= edge << SICTR_REDG_SHIFT; + tmp |= tx_hi_z ? SICTR_TXDIZ_HIZ : SICTR_TXDIZ_LOW; + sh_msiof_write(p, SICTR, tmp); } static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p, const void *tx_buf, void *rx_buf, u32 bits, u32 words) { - u32 dr2 = MDR2_BITLEN1(bits) | MDR2_WDLEN1(words); + u32 dr2 = SIMDR2_BITLEN1(bits) | SIMDR2_WDLEN1(words); if (tx_buf || (p->ctlr->flags & SPI_CONTROLLER_MUST_TX)) - sh_msiof_write(p, TMDR2, dr2); + sh_msiof_write(p, SITMDR2, dr2); else - sh_msiof_write(p, TMDR2, dr2 | MDR2_GRPMASK1); + sh_msiof_write(p, SITMDR2, dr2 | SIMDR2_GRPMASK1); if (rx_buf) - sh_msiof_write(p, RMDR2, dr2); + sh_msiof_write(p, SIRMDR2, dr2); } static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p) { - sh_msiof_write(p, STR, - sh_msiof_read(p, STR) & ~(STR_TDREQ | STR_RDREQ)); + sh_msiof_write(p, SISTR, + sh_msiof_read(p, SISTR) & ~(SISTR_TDREQ | SISTR_RDREQ)); } static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p, @@ -414,7 +411,7 @@ static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - sh_msiof_write(p, TFDR, buf_8[k] << fs); + sh_msiof_write(p, SITFDR, buf_8[k] << fs); } static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p, @@ -424,7 +421,7 @@ static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - sh_msiof_write(p, TFDR, buf_16[k] << fs); + sh_msiof_write(p, SITFDR, buf_16[k] << fs); } static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p, @@ -434,7 +431,7 @@ static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - sh_msiof_write(p, TFDR, get_unaligned(&buf_16[k]) << fs); + sh_msiof_write(p, SITFDR, get_unaligned(&buf_16[k]) << fs); } static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p, @@ -444,7 +441,7 @@ static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - sh_msiof_write(p, TFDR, buf_32[k] << fs); + sh_msiof_write(p, SITFDR, buf_32[k] << fs); } static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p, @@ -454,7 +451,7 @@ static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs); + sh_msiof_write(p, SITFDR, get_unaligned(&buf_32[k]) << fs); } static void sh_msiof_spi_write_fifo_s32(struct sh_msiof_spi_priv *p, @@ -464,7 +461,7 @@ static void sh_msiof_spi_write_fifo_s32(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - sh_msiof_write(p, TFDR, swab32(buf_32[k] << fs)); + sh_msiof_write(p, SITFDR, swab32(buf_32[k] << fs)); } static void sh_msiof_spi_write_fifo_s32u(struct sh_msiof_spi_priv *p, @@ -474,7 +471,7 @@ static void sh_msiof_spi_write_fifo_s32u(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - sh_msiof_write(p, TFDR, swab32(get_unaligned(&buf_32[k]) << fs)); + sh_msiof_write(p, SITFDR, swab32(get_unaligned(&buf_32[k]) << fs)); } static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p, @@ -484,7 +481,7 @@ static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - buf_8[k] = sh_msiof_read(p, RFDR) >> fs; + buf_8[k] = sh_msiof_read(p, SIRFDR) >> fs; } static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p, @@ -494,7 +491,7 @@ static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - buf_16[k] = sh_msiof_read(p, RFDR) >> fs; + buf_16[k] = sh_msiof_read(p, SIRFDR) >> fs; } static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p, @@ -504,7 +501,7 @@ static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_16[k]); + put_unaligned(sh_msiof_read(p, SIRFDR) >> fs, &buf_16[k]); } static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p, @@ -514,7 +511,7 @@ static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - buf_32[k] = sh_msiof_read(p, RFDR) >> fs; + buf_32[k] = sh_msiof_read(p, SIRFDR) >> fs; } static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p, @@ -524,7 +521,7 @@ static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]); + put_unaligned(sh_msiof_read(p, SIRFDR) >> fs, &buf_32[k]); } static void sh_msiof_spi_read_fifo_s32(struct sh_msiof_spi_priv *p, @@ -534,7 +531,7 @@ static void sh_msiof_spi_read_fifo_s32(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - buf_32[k] = swab32(sh_msiof_read(p, RFDR) >> fs); + buf_32[k] = swab32(sh_msiof_read(p, SIRFDR) >> fs); } static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p, @@ -544,7 +541,7 @@ static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p, int k; for (k = 0; k < words; k++) - put_unaligned(swab32(sh_msiof_read(p, RFDR) >> fs), &buf_32[k]); + put_unaligned(swab32(sh_msiof_read(p, SIRFDR) >> fs), &buf_32[k]); } static int sh_msiof_spi_setup(struct spi_device *spi) @@ -561,17 +558,17 @@ static int sh_msiof_spi_setup(struct spi_device *spi) return 0; /* Configure native chip select mode/polarity early */ - clr = MDR1_SYNCMD_MASK; - set = MDR1_SYNCMD_SPI; + clr = SIMDR1_SYNCMD_MASK; + set = SIMDR1_SYNCMD_SPI; if (spi->mode & SPI_CS_HIGH) - clr |= BIT(MDR1_SYNCAC_SHIFT); + clr |= BIT(SIMDR1_SYNCAC_SHIFT); else - set |= BIT(MDR1_SYNCAC_SHIFT); + set |= BIT(SIMDR1_SYNCAC_SHIFT); pm_runtime_get_sync(&p->pdev->dev); - tmp = sh_msiof_read(p, TMDR1) & ~clr; - sh_msiof_write(p, TMDR1, tmp | set | MDR1_TRMD | TMDR1_PCON); - tmp = sh_msiof_read(p, RMDR1) & ~clr; - sh_msiof_write(p, RMDR1, tmp | set); + tmp = sh_msiof_read(p, SITMDR1) & ~clr; + sh_msiof_write(p, SITMDR1, tmp | set | SIMDR1_TRMD | SITMDR1_PCON); + tmp = sh_msiof_read(p, SIRMDR1) & ~clr; + sh_msiof_write(p, SIRMDR1, tmp | set); pm_runtime_put(&p->pdev->dev); p->native_cs_high = spi->mode & SPI_CS_HIGH; p->native_cs_inited = true; @@ -587,7 +584,7 @@ static int sh_msiof_prepare_message(struct spi_controller *ctlr, /* Configure pins before asserting CS */ if (spi->cs_gpiod) { - ss = p->unused_ss; + ss = ctlr->unused_native_cs; cs_high = p->native_cs_high; } else { ss = spi->chip_select; @@ -607,15 +604,15 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) /* setup clock and rx/tx signals */ if (!slave) - ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE); + ret = sh_msiof_modify_ctr_wait(p, 0, SICTR_TSCKE); if (rx_buf && !ret) - ret = sh_msiof_modify_ctr_wait(p, 0, CTR_RXE); + ret = sh_msiof_modify_ctr_wait(p, 0, SICTR_RXE); if (!ret) - ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TXE); + ret = sh_msiof_modify_ctr_wait(p, 0, SICTR_TXE); /* start by setting frame bit */ if (!ret && !slave) - ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE); + ret = sh_msiof_modify_ctr_wait(p, 0, SICTR_TFSE); return ret; } @@ -627,13 +624,13 @@ static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf) /* shut down frame, rx/tx and clock signals */ if (!slave) - ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0); + ret = sh_msiof_modify_ctr_wait(p, SICTR_TFSE, 0); if (!ret) - ret = sh_msiof_modify_ctr_wait(p, CTR_TXE, 0); + ret = sh_msiof_modify_ctr_wait(p, SICTR_TXE, 0); if (rx_buf && !ret) - ret = sh_msiof_modify_ctr_wait(p, CTR_RXE, 0); + ret = sh_msiof_modify_ctr_wait(p, SICTR_RXE, 0); if (!ret && !slave) - ret = sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0); + ret = sh_msiof_modify_ctr_wait(p, SICTR_TSCKE, 0); return ret; } @@ -688,11 +685,11 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, fifo_shift = 32 - bits; /* default FIFO watermarks for PIO */ - sh_msiof_write(p, FCTR, 0); + sh_msiof_write(p, SIFCTR, 0); /* setup msiof transfer mode registers */ sh_msiof_spi_set_mode_regs(p, tx_buf, rx_buf, bits, words); - sh_msiof_write(p, IER, IER_TEOFE | IER_REOFE); + sh_msiof_write(p, SIIER, SIIER_TEOFE | SIIER_REOFE); /* write tx fifo */ if (tx_buf) @@ -731,7 +728,7 @@ stop_reset: sh_msiof_reset_str(p); sh_msiof_spi_stop(p, rx_buf); stop_ier: - sh_msiof_write(p, IER, 0); + sh_msiof_write(p, SIIER, 0); return ret; } @@ -750,7 +747,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, /* First prepare and submit the DMA request(s), as this may fail */ if (rx) { - ier_bits |= IER_RDREQE | IER_RDMAE; + ier_bits |= SIIER_RDREQE | SIIER_RDMAE; desc_rx = dmaengine_prep_slave_single(p->ctlr->dma_rx, p->rx_dma_addr, len, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); @@ -765,7 +762,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, } if (tx) { - ier_bits |= IER_TDREQE | IER_TDMAE; + ier_bits |= SIIER_TDREQE | SIIER_TDMAE; dma_sync_single_for_device(p->ctlr->dma_tx->device->dev, p->tx_dma_addr, len, DMA_TO_DEVICE); desc_tx = dmaengine_prep_slave_single(p->ctlr->dma_tx, @@ -786,12 +783,12 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, } /* 1 stage FIFO watermarks for DMA */ - sh_msiof_write(p, FCTR, FCTR_TFWM_1 | FCTR_RFWM_1); + sh_msiof_write(p, SIFCTR, SIFCTR_TFWM_1 | SIFCTR_RFWM_1); /* setup msiof transfer mode registers (32-bit words) */ sh_msiof_spi_set_mode_regs(p, tx, rx, 32, len / 4); - sh_msiof_write(p, IER, ier_bits); + sh_msiof_write(p, SIIER, ier_bits); reinit_completion(&p->done); if (tx) @@ -823,10 +820,10 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, if (ret) goto stop_reset; - sh_msiof_write(p, IER, 0); + sh_msiof_write(p, SIIER, 0); } else { /* wait for tx fifo to be emptied */ - sh_msiof_write(p, IER, IER_TEOFE); + sh_msiof_write(p, SIIER, SIIER_TEOFE); ret = sh_msiof_wait_for_completion(p, &p->done); if (ret) goto stop_reset; @@ -856,7 +853,7 @@ stop_dma: no_dma_tx: if (rx) dmaengine_terminate_all(p->ctlr->dma_rx); - sh_msiof_write(p, IER, 0); + sh_msiof_write(p, SIIER, 0); return ret; } @@ -1124,46 +1121,6 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) } #endif -static int sh_msiof_get_cs_gpios(struct sh_msiof_spi_priv *p) -{ - struct device *dev = &p->pdev->dev; - unsigned int used_ss_mask = 0; - unsigned int cs_gpios = 0; - unsigned int num_cs, i; - int ret; - - ret = gpiod_count(dev, "cs"); - if (ret <= 0) - return 0; - - num_cs = max_t(unsigned int, ret, p->ctlr->num_chipselect); - for (i = 0; i < num_cs; i++) { - struct gpio_desc *gpiod; - - gpiod = devm_gpiod_get_index(dev, "cs", i, GPIOD_ASIS); - if (!IS_ERR(gpiod)) { - devm_gpiod_put(dev, gpiod); - cs_gpios++; - continue; - } - - if (PTR_ERR(gpiod) != -ENOENT) - return PTR_ERR(gpiod); - - if (i >= MAX_SS) { - dev_err(dev, "Invalid native chip select %d\n", i); - return -EINVAL; - } - used_ss_mask |= BIT(i); - } - p->unused_ss = ffz(used_ss_mask); - if (cs_gpios && p->unused_ss >= MAX_SS) { - dev_err(dev, "No unused native chip select available\n"); - return -EINVAL; - } - return 0; -} - static struct dma_chan *sh_msiof_request_dma_chan(struct device *dev, enum dma_transfer_direction dir, unsigned int id, dma_addr_t port_addr) { @@ -1232,12 +1189,12 @@ static int sh_msiof_request_dma(struct sh_msiof_spi_priv *p) ctlr = p->ctlr; ctlr->dma_tx = sh_msiof_request_dma_chan(dev, DMA_MEM_TO_DEV, - dma_tx_id, res->start + TFDR); + dma_tx_id, res->start + SITFDR); if (!ctlr->dma_tx) return -ENODEV; ctlr->dma_rx = sh_msiof_request_dma_chan(dev, DMA_DEV_TO_MEM, - dma_rx_id, res->start + RFDR); + dma_rx_id, res->start + SIRFDR); if (!ctlr->dma_rx) goto free_tx_chan; @@ -1297,7 +1254,6 @@ static void sh_msiof_release_dma(struct sh_msiof_spi_priv *p) static int sh_msiof_spi_probe(struct platform_device *pdev) { - struct resource *r; struct spi_controller *ctlr; const struct sh_msiof_chipdata *chipdata; struct sh_msiof_spi_info *info; @@ -1346,13 +1302,11 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) i = platform_get_irq(pdev, 0); if (i < 0) { - dev_err(&pdev->dev, "cannot get IRQ\n"); ret = i; goto err1; } - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - p->mapbase = devm_ioremap_resource(&pdev->dev, r); + p->mapbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(p->mapbase)) { ret = PTR_ERR(p->mapbase); goto err1; @@ -1376,17 +1330,12 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) if (p->info->rx_fifo_override) p->rx_fifo_size = p->info->rx_fifo_override; - /* Setup GPIO chip selects */ - ctlr->num_chipselect = p->info->num_chipselect; - ret = sh_msiof_get_cs_gpios(p); - if (ret) - goto err1; - /* init controller code */ ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; ctlr->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE; ctlr->flags = chipdata->ctlr_flags; ctlr->bus_num = pdev->id; + ctlr->num_chipselect = p->info->num_chipselect; ctlr->dev.of_node = pdev->dev.of_node; ctlr->setup = sh_msiof_spi_setup; ctlr->prepare_message = sh_msiof_prepare_message; @@ -1395,6 +1344,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) ctlr->auto_runtime_pm = true; ctlr->transfer_one = sh_msiof_transfer_one; ctlr->use_gpio_descriptors = true; + ctlr->max_native_cs = MAX_SS; ret = sh_msiof_request_dma(p); if (ret < 0) diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c index f1ee58208216..20bdae5fdf3b 100644 --- a/drivers/spi/spi-sh.c +++ b/drivers/spi/spi-sh.c @@ -437,10 +437,8 @@ static int spi_sh_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "platform_get_irq error: %d\n", irq); + if (irq < 0) return irq; - } master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); if (master == NULL) { diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c index 93ec2c6cdbfd..f7c1e20432e0 100644 --- a/drivers/spi/spi-sifive.c +++ b/drivers/spi/spi-sifive.c @@ -292,7 +292,6 @@ sifive_spi_transfer_one(struct spi_master *master, struct spi_device *device, static int sifive_spi_probe(struct platform_device *pdev) { struct sifive_spi *spi; - struct resource *res; int ret, irq, num_cs; u32 cs_bits, max_bits_per_word; struct spi_master *master; @@ -307,8 +306,7 @@ static int sifive_spi_probe(struct platform_device *pdev) init_completion(&spi->done); platform_set_drvdata(pdev, master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi->regs = devm_ioremap_resource(&pdev->dev, res); + spi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi->regs)) { ret = PTR_ERR(spi->regs); goto put_master; @@ -323,7 +321,6 @@ static int sifive_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "Unable to find interrupt\n"); ret = irq; goto put_master; } @@ -360,14 +357,14 @@ static int sifive_spi_probe(struct platform_device *pdev) if (!cs_bits) { dev_err(&pdev->dev, "Could not auto probe CS lines\n"); ret = -EINVAL; - goto put_master; + goto disable_clk; } num_cs = ilog2(cs_bits) + 1; if (num_cs > SIFIVE_SPI_MAX_CS) { dev_err(&pdev->dev, "Invalid number of spi slaves\n"); ret = -EINVAL; - goto put_master; + goto disable_clk; } /* Define our master */ @@ -396,7 +393,7 @@ static int sifive_spi_probe(struct platform_device *pdev) dev_name(&pdev->dev), spi); if (ret) { dev_err(&pdev->dev, "Unable to bind to interrupt\n"); - goto put_master; + goto disable_clk; } dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n", @@ -405,11 +402,13 @@ static int sifive_spi_probe(struct platform_device *pdev) ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "spi_register_master failed\n"); - goto put_master; + goto disable_clk; } return 0; +disable_clk: + clk_disable_unprepare(spi->clk); put_master: spi_master_put(master); @@ -423,6 +422,7 @@ static int sifive_spi_remove(struct platform_device *pdev) /* Disable all the interrupts just in case */ sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); + clk_disable_unprepare(spi->clk); return 0; } diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index 71b882ab31b9..8419e6722e17 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -1070,7 +1070,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) { struct sirfsoc_spi *sspi; struct spi_master *master; - struct resource *mem_res; const struct sirf_spi_comp_data *spi_comp_data; int irq; int ret; @@ -1097,8 +1096,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) sspi->fifo_level_chk_mask = (sspi->fifo_size / 4) - 1; sspi->dat_max_frm_len = spi_comp_data->dat_max_frm_len; sspi->fifo_size = spi_comp_data->fifo_size; - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sspi->base = devm_ioremap_resource(&pdev->dev, mem_res); + sspi->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sspi->base)) { ret = PTR_ERR(sspi->base); goto free_master; @@ -1128,16 +1126,16 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) sspi->bitbang.master->dev.of_node = pdev->dev.of_node; /* request DMA channels */ - sspi->rx_chan = dma_request_slave_channel(&pdev->dev, "rx"); - if (!sspi->rx_chan) { + sspi->rx_chan = dma_request_chan(&pdev->dev, "rx"); + if (IS_ERR(sspi->rx_chan)) { dev_err(&pdev->dev, "can not allocate rx dma channel\n"); - ret = -ENODEV; + ret = PTR_ERR(sspi->rx_chan); goto free_master; } - sspi->tx_chan = dma_request_slave_channel(&pdev->dev, "tx"); - if (!sspi->tx_chan) { + sspi->tx_chan = dma_request_chan(&pdev->dev, "tx"); + if (IS_ERR(sspi->tx_chan)) { dev_err(&pdev->dev, "can not allocate tx dma channel\n"); - ret = -ENODEV; + ret = PTR_ERR(sspi->tx_chan); goto free_rx_dma; } diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c index d1075433f6a6..44edaa360405 100644 --- a/drivers/spi/spi-slave-mt27xx.c +++ b/drivers/spi/spi-slave-mt27xx.c @@ -368,7 +368,6 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) { struct spi_controller *ctlr; struct mtk_spi_slave *mdata; - struct resource *res; int irq, ret; ctlr = spi_alloc_slave(&pdev->dev, sizeof(*mdata)); @@ -392,17 +391,8 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ctlr); init_completion(&mdata->xfer_done); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENODEV; - dev_err(&pdev->dev, "failed to determine base address\n"); - goto err_put_ctlr; - } - mdata->dev = &pdev->dev; - - mdata->base = devm_ioremap_resource(&pdev->dev, res); + mdata->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mdata->base)) { ret = PTR_ERR(mdata->base); goto err_put_ctlr; @@ -410,7 +400,6 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq (%d)\n", irq); ret = irq; goto err_put_ctlr; } diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index df5960bddfe6..87dadb6b8ebf 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -77,6 +77,7 @@ /* Bits definitions for register REG_WDG_CTRL */ #define BIT_WDG_RUN BIT(1) +#define BIT_WDG_NEW BIT(2) #define BIT_WDG_RST BIT(3) /* Registers definitions for PMIC */ @@ -86,6 +87,7 @@ #define BIT_WDG_EN BIT(2) /* Definition of PMIC reset status register */ +#define HWRST_STATUS_SECURITY 0x02 #define HWRST_STATUS_RECOVERY 0x20 #define HWRST_STATUS_NORMAL 0x40 #define HWRST_STATUS_ALARM 0x50 @@ -97,6 +99,8 @@ #define HWRST_STATUS_AUTODLOADER 0xa0 #define HWRST_STATUS_IQMODE 0xb0 #define HWRST_STATUS_SPRDISK 0xc0 +#define HWRST_STATUS_FACTORYTEST 0xe0 +#define HWRST_STATUS_WATCHDOG 0xf0 /* Use default timeout 50 ms that converts to watchdog values */ #define WDG_LOAD_VAL ((50 * 1000) / 32768) @@ -162,14 +166,16 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) int read_timeout = ADI_READ_TIMEOUT; unsigned long flags; u32 val, rd_addr; - int ret; - - ret = hwspin_lock_timeout_irqsave(sadi->hwlock, - ADI_HWSPINLOCK_TIMEOUT, - &flags); - if (ret) { - dev_err(sadi->dev, "get the hw lock failed\n"); - return ret; + int ret = 0; + + if (sadi->hwlock) { + ret = hwspin_lock_timeout_irqsave(sadi->hwlock, + ADI_HWSPINLOCK_TIMEOUT, + &flags); + if (ret) { + dev_err(sadi->dev, "get the hw lock failed\n"); + return ret; + } } /* @@ -216,7 +222,8 @@ static int sprd_adi_read(struct sprd_adi *sadi, u32 reg_paddr, u32 *read_val) *read_val = val & RD_VALUE_MASK; out: - hwspin_unlock_irqrestore(sadi->hwlock, &flags); + if (sadi->hwlock) + hwspin_unlock_irqrestore(sadi->hwlock, &flags); return ret; } @@ -227,12 +234,14 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) unsigned long flags; int ret; - ret = hwspin_lock_timeout_irqsave(sadi->hwlock, - ADI_HWSPINLOCK_TIMEOUT, - &flags); - if (ret) { - dev_err(sadi->dev, "get the hw lock failed\n"); - return ret; + if (sadi->hwlock) { + ret = hwspin_lock_timeout_irqsave(sadi->hwlock, + ADI_HWSPINLOCK_TIMEOUT, + &flags); + if (ret) { + dev_err(sadi->dev, "get the hw lock failed\n"); + return ret; + } } ret = sprd_adi_drain_fifo(sadi); @@ -258,7 +267,8 @@ static int sprd_adi_write(struct sprd_adi *sadi, u32 reg_paddr, u32 val) } out: - hwspin_unlock_irqrestore(sadi->hwlock, &flags); + if (sadi->hwlock) + hwspin_unlock_irqrestore(sadi->hwlock, &flags); return ret; } @@ -307,6 +317,18 @@ static int sprd_adi_transfer_one(struct spi_controller *ctlr, return 0; } +static void sprd_adi_set_wdt_rst_mode(struct sprd_adi *sadi) +{ +#ifdef CONFIG_SPRD_WATCHDOG + u32 val; + + /* Set default watchdog reboot mode */ + sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val); + val |= HWRST_STATUS_WATCHDOG; + sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val); +#endif +} + static int sprd_adi_restart_handler(struct notifier_block *this, unsigned long mode, void *cmd) { @@ -336,11 +358,16 @@ static int sprd_adi_restart_handler(struct notifier_block *this, reboot_mode = HWRST_STATUS_IQMODE; else if (!strncmp(cmd, "sprdisk", 7)) reboot_mode = HWRST_STATUS_SPRDISK; + else if (!strncmp(cmd, "tospanic", 8)) + reboot_mode = HWRST_STATUS_SECURITY; + else if (!strncmp(cmd, "factorytest", 11)) + reboot_mode = HWRST_STATUS_FACTORYTEST; else reboot_mode = HWRST_STATUS_NORMAL; /* Record the reboot mode */ sprd_adi_read(sadi, sadi->slave_pbase + PMIC_RST_STATUS, &val); + val &= ~HWRST_STATUS_WATCHDOG; val |= reboot_mode; sprd_adi_write(sadi, sadi->slave_pbase + PMIC_RST_STATUS, val); @@ -357,6 +384,10 @@ static int sprd_adi_restart_handler(struct notifier_block *this, /* Unlock the watchdog */ sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOCK, WDG_UNLOCK_KEY); + sprd_adi_read(sadi, sadi->slave_pbase + REG_WDG_CTRL, &val); + val |= BIT_WDG_NEW; + sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val); + /* Load the watchdog timeout value, 50ms is always enough. */ sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_LOW, WDG_LOAD_VAL & WDG_LOAD_MASK); @@ -367,6 +398,9 @@ static int sprd_adi_restart_handler(struct notifier_block *this, val |= BIT_WDG_RUN | BIT_WDG_RST; sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val); + /* Lock the watchdog */ + sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOCK, ~WDG_UNLOCK_KEY); + mdelay(1000); dev_emerg(sadi->dev, "Unable to restart system\n"); @@ -380,9 +414,6 @@ static void sprd_adi_hw_init(struct sprd_adi *sadi) const __be32 *list; u32 tmp; - /* Address bits select default 12 bits */ - writel_relaxed(0, sadi->base + REG_ADI_CTRL0); - /* Set all channels as default priority */ writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIL); writel_relaxed(0, sadi->base + REG_ADI_CHN_PRIH); @@ -459,19 +490,30 @@ static int sprd_adi_probe(struct platform_device *pdev) sadi->slave_pbase = res->start + ADI_SLAVE_OFFSET; sadi->ctlr = ctlr; sadi->dev = &pdev->dev; - ret = of_hwspin_lock_get_id_byname(np, "adi"); - if (ret < 0) { - dev_err(&pdev->dev, "can not get the hardware spinlock\n"); - goto put_ctlr; - } - - sadi->hwlock = devm_hwspin_lock_request_specific(&pdev->dev, ret); - if (!sadi->hwlock) { - ret = -ENXIO; - goto put_ctlr; + ret = of_hwspin_lock_get_id(np, 0); + if (ret > 0 || (IS_ENABLED(CONFIG_HWSPINLOCK) && ret == 0)) { + sadi->hwlock = + devm_hwspin_lock_request_specific(&pdev->dev, ret); + if (!sadi->hwlock) { + ret = -ENXIO; + goto put_ctlr; + } + } else { + switch (ret) { + case -ENOENT: + dev_info(&pdev->dev, "no hardware spinlock supplied\n"); + break; + default: + dev_err(&pdev->dev, + "failed to find hwlock id, %d\n", ret); + /* fall-through */ + case -EPROBE_DEFER: + goto put_ctlr; + } } sprd_adi_hw_init(sadi); + sprd_adi_set_wdt_rst_mode(sadi); ctlr->dev.of_node = pdev->dev.of_node; ctlr->bus_num = pdev->id; diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c index 1b7eebb72c07..6678f1cbc566 100644 --- a/drivers/spi/spi-sprd.c +++ b/drivers/spi/spi-sprd.c @@ -669,12 +669,16 @@ static void sprd_spi_set_speed(struct sprd_spi *ss, u32 speed_hz) writel_relaxed(clk_div, ss->base + SPRD_SPI_CLKD); } -static void sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t) +static int sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t) { + struct spi_delay *d = &t->word_delay; u16 word_delay, interval; u32 val; - val = readl_relaxed(ss->base + SPRD_SPI_CTL7); + if (d->unit != SPI_DELAY_UNIT_SCK) + return -EINVAL; + + val = readl_relaxed(ss->base + SPRD_SPI_CTL0); val &= ~(SPRD_SPI_SCK_REV | SPRD_SPI_NG_TX | SPRD_SPI_NG_RX); /* Set default chip selection, clock phase and clock polarity */ val |= ss->hw_mode & SPI_CPHA ? SPRD_SPI_NG_RX : SPRD_SPI_NG_TX; @@ -686,7 +690,7 @@ static void sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t) * formula as below per datasheet: * interval time (source clock cycles) = interval * 4 + 10. */ - word_delay = clamp_t(u16, t->word_delay, SPRD_SPI_MIN_DELAY_CYCLE, + word_delay = clamp_t(u16, d->value, SPRD_SPI_MIN_DELAY_CYCLE, SPRD_SPI_MAX_DELAY_CYCLE); interval = DIV_ROUND_UP(word_delay - 10, 4); ss->word_delay = interval * 4 + 10; @@ -711,6 +715,8 @@ static void sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t) val &= ~SPRD_SPI_DATA_LINE2_EN; writel_relaxed(val, ss->base + SPRD_SPI_CTL7); + + return 0; } static int sprd_spi_setup_transfer(struct spi_device *sdev, @@ -719,13 +725,16 @@ static int sprd_spi_setup_transfer(struct spi_device *sdev, struct sprd_spi *ss = spi_controller_get_devdata(sdev->controller); u8 bits_per_word = t->bits_per_word; u32 val, mode = 0; + int ret; ss->len = t->len; ss->tx_buf = t->tx_buf; ss->rx_buf = t->rx_buf; ss->hw_mode = sdev->mode; - sprd_spi_init_hw(ss, t); + ret = sprd_spi_init_hw(ss, t); + if (ret) + return ret; /* Set tansfer speed and valid bits */ sprd_spi_set_speed(ss, t->speed_hz); @@ -843,10 +852,8 @@ static int sprd_spi_irq_init(struct platform_device *pdev, struct sprd_spi *ss) int ret; ss->irq = platform_get_irq(pdev, 0); - if (ss->irq < 0) { - dev_err(&pdev->dev, "failed to get irq resource\n"); + if (ss->irq < 0) return ss->irq; - } ret = devm_request_irq(&pdev->dev, ss->irq, sprd_spi_handle_irq, 0, pdev->name, ss); diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c index 840a6bf81336..77d26d64541a 100644 --- a/drivers/spi/spi-st-ssc4.c +++ b/drivers/spi/spi-st-ssc4.c @@ -298,7 +298,6 @@ static int spi_st_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct spi_master *master; - struct resource *res; struct spi_st *spi_st; int irq, ret = 0; u32 var; @@ -331,8 +330,7 @@ static int spi_st_probe(struct platform_device *pdev) init_completion(&spi_st->done); /* Get resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spi_st->base = devm_ioremap_resource(&pdev->dev, res); + spi_st->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi_st->base)) { ret = PTR_ERR(spi_st->base); goto clk_disable; @@ -383,6 +381,7 @@ static int spi_st_probe(struct platform_device *pdev) return 0; clk_disable: + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(spi_st->clk); put_master: spi_master_put(master); @@ -394,6 +393,8 @@ static int spi_st_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct spi_st *spi_st = spi_master_get_devdata(master); + pm_runtime_disable(&pdev->dev); + clk_disable_unprepare(spi_st->clk); pinctrl_pm_select_sleep_state(&pdev->dev); diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 655e4afbfb2a..4ef569b47aa6 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -470,10 +470,11 @@ static int stm32_qspi_setup(struct spi_device *spi) return 0; } -static void stm32_qspi_dma_setup(struct stm32_qspi *qspi) +static int stm32_qspi_dma_setup(struct stm32_qspi *qspi) { struct dma_slave_config dma_cfg; struct device *dev = qspi->dev; + int ret = 0; memset(&dma_cfg, 0, sizeof(dma_cfg)); @@ -484,8 +485,13 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi) dma_cfg.src_maxburst = 4; dma_cfg.dst_maxburst = 4; - qspi->dma_chrx = dma_request_slave_channel(dev, "rx"); - if (qspi->dma_chrx) { + qspi->dma_chrx = dma_request_chan(dev, "rx"); + if (IS_ERR(qspi->dma_chrx)) { + ret = PTR_ERR(qspi->dma_chrx); + qspi->dma_chrx = NULL; + if (ret == -EPROBE_DEFER) + goto out; + } else { if (dmaengine_slave_config(qspi->dma_chrx, &dma_cfg)) { dev_err(dev, "dma rx config failed\n"); dma_release_channel(qspi->dma_chrx); @@ -493,8 +499,11 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi) } } - qspi->dma_chtx = dma_request_slave_channel(dev, "tx"); - if (qspi->dma_chtx) { + qspi->dma_chtx = dma_request_chan(dev, "tx"); + if (IS_ERR(qspi->dma_chtx)) { + ret = PTR_ERR(qspi->dma_chtx); + qspi->dma_chtx = NULL; + } else { if (dmaengine_slave_config(qspi->dma_chtx, &dma_cfg)) { dev_err(dev, "dma tx config failed\n"); dma_release_channel(qspi->dma_chtx); @@ -502,7 +511,13 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi) } } +out: init_completion(&qspi->dma_completion); + + if (ret != -EPROBE_DEFER) + ret = 0; + + return ret; } static void stm32_qspi_dma_free(struct stm32_qspi *qspi) @@ -528,7 +543,6 @@ static void stm32_qspi_release(struct stm32_qspi *qspi) stm32_qspi_dma_free(qspi); mutex_destroy(&qspi->lock); clk_disable_unprepare(qspi->clk); - spi_master_put(qspi->ctrl); } static int stm32_qspi_probe(struct platform_device *pdev) @@ -570,11 +584,8 @@ static int stm32_qspi_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - if (irq != -EPROBE_DEFER) - dev_err(dev, "IRQ error missing or invalid\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0, dev_name(dev), qspi); @@ -612,7 +623,10 @@ static int stm32_qspi_probe(struct platform_device *pdev) qspi->dev = dev; platform_set_drvdata(pdev, qspi); - stm32_qspi_dma_setup(qspi); + ret = stm32_qspi_dma_setup(qspi); + if (ret) + goto err; + mutex_init(&qspi->lock); ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD @@ -629,6 +643,8 @@ static int stm32_qspi_probe(struct platform_device *pdev) err: stm32_qspi_release(qspi); + spi_master_put(qspi->ctrl); + return ret; } diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index b222ce8d083e..e041f9c4ec47 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -9,7 +9,6 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/dmaengine.h> -#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/iopoll.h> #include <linux/module.h> @@ -974,29 +973,6 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) } /** - * stm32_spi_setup - setup device chip select - */ -static int stm32_spi_setup(struct spi_device *spi_dev) -{ - int ret = 0; - - if (!gpio_is_valid(spi_dev->cs_gpio)) { - dev_err(&spi_dev->dev, "%d is not a valid gpio\n", - spi_dev->cs_gpio); - return -EINVAL; - } - - dev_dbg(&spi_dev->dev, "%s: set gpio%d output %s\n", __func__, - spi_dev->cs_gpio, - (spi_dev->mode & SPI_CS_HIGH) ? "low" : "high"); - - ret = gpio_direction_output(spi_dev->cs_gpio, - !(spi_dev->mode & SPI_CS_HIGH)); - - return ret; -} - -/** * stm32_spi_prepare_msg - set up the controller to transfer a single message */ static int stm32_spi_prepare_msg(struct spi_master *master, @@ -1810,7 +1786,7 @@ static int stm32_spi_probe(struct platform_device *pdev) struct spi_master *master; struct stm32_spi *spi; struct resource *res; - int i, ret; + int ret; master = spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi)); if (!master) { @@ -1898,22 +1874,34 @@ static int stm32_spi_probe(struct platform_device *pdev) master->bits_per_word_mask = spi->cfg->get_bpw_mask(spi); master->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min; master->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max; - master->setup = stm32_spi_setup; + master->use_gpio_descriptors = true; master->prepare_message = stm32_spi_prepare_msg; master->transfer_one = stm32_spi_transfer_one; master->unprepare_message = stm32_spi_unprepare_msg; - spi->dma_tx = dma_request_slave_channel(spi->dev, "tx"); - if (!spi->dma_tx) + spi->dma_tx = dma_request_chan(spi->dev, "tx"); + if (IS_ERR(spi->dma_tx)) { + ret = PTR_ERR(spi->dma_tx); + spi->dma_tx = NULL; + if (ret == -EPROBE_DEFER) + goto err_clk_disable; + dev_warn(&pdev->dev, "failed to request tx dma channel\n"); - else + } else { master->dma_tx = spi->dma_tx; + } + + spi->dma_rx = dma_request_chan(spi->dev, "rx"); + if (IS_ERR(spi->dma_rx)) { + ret = PTR_ERR(spi->dma_rx); + spi->dma_rx = NULL; + if (ret == -EPROBE_DEFER) + goto err_dma_release; - spi->dma_rx = dma_request_slave_channel(spi->dev, "rx"); - if (!spi->dma_rx) dev_warn(&pdev->dev, "failed to request rx dma channel\n"); - else + } else { master->dma_rx = spi->dma_rx; + } if (spi->dma_tx || spi->dma_rx) master->can_dma = stm32_spi_can_dma; @@ -1925,43 +1913,26 @@ static int stm32_spi_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "spi master registration failed: %d\n", ret); - goto err_dma_release; + goto err_pm_disable; } - if (!master->cs_gpios) { + if (!master->cs_gpiods) { dev_err(&pdev->dev, "no CS gpios available\n"); ret = -EINVAL; - goto err_dma_release; - } - - for (i = 0; i < master->num_chipselect; i++) { - if (!gpio_is_valid(master->cs_gpios[i])) { - dev_err(&pdev->dev, "%i is not a valid gpio\n", - master->cs_gpios[i]); - ret = -EINVAL; - goto err_dma_release; - } - - ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i], - DRIVER_NAME); - if (ret) { - dev_err(&pdev->dev, "can't get CS gpio %i\n", - master->cs_gpios[i]); - goto err_dma_release; - } + goto err_pm_disable; } dev_info(&pdev->dev, "driver initialized\n"); return 0; +err_pm_disable: + pm_runtime_disable(&pdev->dev); err_dma_release: if (spi->dma_tx) dma_release_channel(spi->dma_tx); if (spi->dma_rx) dma_release_channel(spi->dma_rx); - - pm_runtime_disable(&pdev->dev); err_clk_disable: clk_disable_unprepare(spi->clk); err_master_put: diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index 5194bc07fd60..cbfac6596fad 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -428,7 +428,6 @@ static int sun4i_spi_probe(struct platform_device *pdev) { struct spi_master *master; struct sun4i_spi *sspi; - struct resource *res; int ret = 0, irq; master = spi_alloc_master(&pdev->dev, sizeof(struct sun4i_spi)); @@ -440,8 +439,7 @@ static int sun4i_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); sspi = spi_master_get_devdata(master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sspi->base_addr = devm_ioremap_resource(&pdev->dev, res); + sspi->base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sspi->base_addr)) { ret = PTR_ERR(sspi->base_addr); goto err_free_master; @@ -449,7 +447,6 @@ static int sun4i_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "No spi IRQ specified\n"); ret = -ENXIO; goto err_free_master; } diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index ee2bdaf5b856..ec7967be9e2f 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -435,7 +435,6 @@ static int sun6i_spi_probe(struct platform_device *pdev) { struct spi_master *master; struct sun6i_spi *sspi; - struct resource *res; int ret = 0, irq; master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi)); @@ -447,8 +446,7 @@ static int sun6i_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); sspi = spi_master_get_devdata(master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sspi->base_addr = devm_ioremap_resource(&pdev->dev, res); + sspi->base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sspi->base_addr)) { ret = PTR_ERR(sspi->base_addr); goto err_free_master; @@ -456,7 +454,6 @@ static int sun6i_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "No spi IRQ specified\n"); ret = -ENXIO; goto err_free_master; } diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c index f99abd85c50a..ae17c99cce03 100644 --- a/drivers/spi/spi-synquacer.c +++ b/drivers/spi/spi-synquacer.c @@ -670,7 +670,6 @@ static int synquacer_spi_probe(struct platform_device *pdev) rx_irq = platform_get_irq(pdev, 0); if (rx_irq <= 0) { - dev_err(&pdev->dev, "get rx_irq failed (%d)\n", rx_irq); ret = rx_irq; goto put_spi; } @@ -685,7 +684,6 @@ static int synquacer_spi_probe(struct platform_device *pdev) tx_irq = platform_get_irq(pdev, 1); if (tx_irq <= 0) { - dev_err(&pdev->dev, "get tx_irq failed (%d)\n", tx_irq); ret = tx_irq; goto put_spi; } diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 39374c2edcf3..83edabdb41ad 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -269,10 +269,10 @@ static unsigned tegra_spi_calculate_curr_xfer_param( if ((bits_per_word == 8 || bits_per_word == 16 || bits_per_word == 32) && t->len > 3) { - tspi->is_packed = 1; + tspi->is_packed = true; tspi->words_per_32bit = 32/bits_per_word; } else { - tspi->is_packed = 0; + tspi->is_packed = false; tspi->words_per_32bit = 1; } @@ -666,8 +666,7 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, dma_addr_t dma_phys; int ret; - dma_chan = dma_request_slave_channel_reason(tspi->dev, - dma_to_memory ? "rx" : "tx"); + dma_chan = dma_request_chan(tspi->dev, dma_to_memory ? "rx" : "tx"); if (IS_ERR(dma_chan)) { ret = PTR_ERR(dma_chan); if (ret != -EPROBE_DEFER) @@ -723,15 +722,31 @@ static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi, dma_release_channel(dma_chan); } -static void tegra_spi_set_hw_cs_timing(struct spi_device *spi, u8 setup_dly, - u8 hold_dly, u8 inactive_dly) +static int tegra_spi_set_hw_cs_timing(struct spi_device *spi, + struct spi_delay *setup, + struct spi_delay *hold, + struct spi_delay *inactive) { struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); + u8 setup_dly, hold_dly, inactive_dly; u32 setup_hold; u32 spi_cs_timing; u32 inactive_cycles; u8 cs_state; + if ((setup && setup->unit != SPI_DELAY_UNIT_SCK) || + (hold && hold->unit != SPI_DELAY_UNIT_SCK) || + (inactive && inactive->unit != SPI_DELAY_UNIT_SCK)) { + dev_err(&spi->dev, + "Invalid delay unit %d, should be SPI_DELAY_UNIT_SCK\n", + SPI_DELAY_UNIT_SCK); + return -EINVAL; + } + + setup_dly = setup ? setup->value : 0; + hold_dly = hold ? hold->value : 0; + inactive_dly = inactive ? inactive->value : 0; + setup_dly = min_t(u8, setup_dly, MAX_SETUP_HOLD_CYCLES); hold_dly = min_t(u8, hold_dly, MAX_SETUP_HOLD_CYCLES); if (setup_dly && hold_dly) { @@ -758,6 +773,8 @@ static void tegra_spi_set_hw_cs_timing(struct spi_device *spi, u8 setup_dly, tspi->spi_cs_timing2 = spi_cs_timing; tegra_spi_writel(tspi, spi_cs_timing, SPI_CS_TIMING2); } + + return 0; } static u32 tegra_spi_setup_transfer_one(struct spi_device *spi, @@ -984,17 +1001,6 @@ static int tegra_spi_setup(struct spi_device *spi) return 0; } -static void tegra_spi_transfer_delay(int delay) -{ - if (!delay) - return; - - if (delay >= 1000) - mdelay(delay / 1000); - - udelay(delay % 1000); -} - static void tegra_spi_transfer_end(struct spi_device *spi) { struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); @@ -1098,7 +1104,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, complete_xfer: if (ret < 0 || skip) { tegra_spi_transfer_end(spi); - tegra_spi_transfer_delay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); goto exit; } else if (list_is_last(&xfer->transfer_list, &msg->transfers)) { @@ -1106,11 +1112,11 @@ complete_xfer: tspi->cs_control = spi; else { tegra_spi_transfer_end(spi); - tegra_spi_transfer_delay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); } } else if (xfer->cs_change) { tegra_spi_transfer_end(spi); - tegra_spi_transfer_delay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); } } diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index cd714a4f52c6..514429379206 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -341,10 +341,11 @@ static int tegra_sflash_transfer_one_message(struct spi_master *master, goto exit; } msg->actual_length += xfer->len; - if (xfer->cs_change && xfer->delay_usecs) { + if (xfer->cs_change && + (xfer->delay_usecs || xfer->delay.value)) { tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND); - udelay(xfer->delay_usecs); + spi_transfer_delay_exec(xfer); } } ret = 0; @@ -419,7 +420,6 @@ static int tegra_sflash_probe(struct platform_device *pdev) { struct spi_master *master; struct tegra_sflash_data *tsd; - struct resource *r; int ret; const struct of_device_id *match; @@ -451,8 +451,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) &master->max_speed_hz)) master->max_speed_hz = 25000000; /* 25MHz */ - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tsd->base = devm_ioremap_resource(&pdev->dev, r); + tsd->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(tsd->base)) { ret = PTR_ERR(tsd->base); goto exit_free_master; diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 111fffc91435..7f4d932dade7 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -599,8 +599,7 @@ static int tegra_slink_init_dma_param(struct tegra_slink_data *tspi, int ret; struct dma_slave_config dma_sconfig; - dma_chan = dma_request_slave_channel_reason(tspi->dev, - dma_to_memory ? "rx" : "tx"); + dma_chan = dma_request_chan(tspi->dev, dma_to_memory ? "rx" : "tx"); if (IS_ERR(dma_chan)) { ret = PTR_ERR(dma_chan); if (ret != -EPROBE_DEFER) @@ -1073,7 +1072,7 @@ static int tegra_slink_probe(struct platform_device *pdev) ret = clk_enable(tspi->clk); if (ret < 0) { dev_err(&pdev->dev, "Clock enable failed %d\n", ret); - goto exit_free_master; + goto exit_clk_unprepare; } spi_irq = platform_get_irq(pdev, 0); @@ -1146,6 +1145,8 @@ exit_free_irq: free_irq(spi_irq, tspi); exit_clk_disable: clk_disable(tspi->clk); +exit_clk_unprepare: + clk_unprepare(tspi->clk); exit_free_master: spi_master_put(master); return ret; @@ -1159,6 +1160,7 @@ static int tegra_slink_remove(struct platform_device *pdev) free_irq(tspi->irq, tspi); clk_disable(tspi->clk); + clk_unprepare(tspi->clk); if (tspi->tx_dma_chan) tegra_slink_deinit_dma_param(tspi, false); diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 6ca600702470..366a3e5cca6b 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -62,6 +62,7 @@ struct ti_qspi { u32 dc; bool mmap_enabled; + int current_cs; }; #define QSPI_PID (0x0) @@ -79,8 +80,6 @@ struct ti_qspi { #define QSPI_COMPLETION_TIMEOUT msecs_to_jiffies(2000) -#define QSPI_FCLK 192000000 - /* Clock Control */ #define QSPI_CLK_EN (1 << 31) #define QSPI_CLK_DIV_MAX 0xffff @@ -315,6 +314,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, { int wlen; unsigned int cmd; + u32 rx; + u8 rxlen, rx_wlen; u8 *rxbuf; rxbuf = t->rx_buf; @@ -331,20 +332,67 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, break; } wlen = t->bits_per_word >> 3; /* in bytes */ + rx_wlen = wlen; while (count) { dev_dbg(qspi->dev, "rx cmd %08x dc %08x\n", cmd, qspi->dc); if (qspi_is_busy(qspi)) return -EBUSY; + switch (wlen) { + case 1: + /* + * Optimize the 8-bit words transfers, as used by + * the SPI flash devices. + */ + if (count >= QSPI_WLEN_MAX_BYTES) { + rxlen = QSPI_WLEN_MAX_BYTES; + } else { + rxlen = min(count, 4); + } + rx_wlen = rxlen << 3; + cmd &= ~QSPI_WLEN_MASK; + cmd |= QSPI_WLEN(rx_wlen); + break; + default: + rxlen = wlen; + break; + } + ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG); if (ti_qspi_poll_wc(qspi)) { dev_err(qspi->dev, "read timed out\n"); return -ETIMEDOUT; } + switch (wlen) { case 1: - *rxbuf = readb(qspi->base + QSPI_SPI_DATA_REG); + /* + * Optimize the 8-bit words transfers, as used by + * the SPI flash devices. + */ + if (count >= QSPI_WLEN_MAX_BYTES) { + u32 *rxp = (u32 *) rxbuf; + rx = readl(qspi->base + QSPI_SPI_DATA_REG_3); + *rxp++ = be32_to_cpu(rx); + rx = readl(qspi->base + QSPI_SPI_DATA_REG_2); + *rxp++ = be32_to_cpu(rx); + rx = readl(qspi->base + QSPI_SPI_DATA_REG_1); + *rxp++ = be32_to_cpu(rx); + rx = readl(qspi->base + QSPI_SPI_DATA_REG); + *rxp++ = be32_to_cpu(rx); + } else { + u8 *rxp = rxbuf; + rx = readl(qspi->base + QSPI_SPI_DATA_REG); + if (rx_wlen >= 8) + *rxp++ = rx >> (rx_wlen - 8); + if (rx_wlen >= 16) + *rxp++ = rx >> (rx_wlen - 16); + if (rx_wlen >= 24) + *rxp++ = rx >> (rx_wlen - 24); + if (rx_wlen >= 32) + *rxp++ = rx; + } break; case 2: *((u16 *)rxbuf) = readw(qspi->base + QSPI_SPI_DATA_REG); @@ -353,8 +401,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, *((u32 *)rxbuf) = readl(qspi->base + QSPI_SPI_DATA_REG); break; } - rxbuf += wlen; - count -= wlen; + rxbuf += rxlen; + count -= rxlen; } return 0; @@ -487,6 +535,7 @@ static void ti_qspi_enable_memory_map(struct spi_device *spi) MEM_CS_EN(spi->chip_select)); } qspi->mmap_enabled = true; + qspi->current_cs = spi->chip_select; } static void ti_qspi_disable_memory_map(struct spi_device *spi) @@ -498,6 +547,7 @@ static void ti_qspi_disable_memory_map(struct spi_device *spi) regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg, MEM_CS_MASK, 0); qspi->mmap_enabled = false; + qspi->current_cs = -1; } static void ti_qspi_setup_mmap_read(struct spi_device *spi, u8 opcode, @@ -524,6 +574,35 @@ static void ti_qspi_setup_mmap_read(struct spi_device *spi, u8 opcode, QSPI_SPI_SETUP_REG(spi->chip_select)); } +static int ti_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) +{ + struct ti_qspi *qspi = spi_controller_get_devdata(mem->spi->master); + size_t max_len; + + if (op->data.dir == SPI_MEM_DATA_IN) { + if (op->addr.val < qspi->mmap_size) { + /* Limit MMIO to the mmaped region */ + if (op->addr.val + op->data.nbytes > qspi->mmap_size) { + max_len = qspi->mmap_size - op->addr.val; + op->data.nbytes = min((size_t) op->data.nbytes, + max_len); + } + } else { + /* + * Use fallback mode (SW generated transfers) above the + * mmaped region. + * Adjust size to comply with the QSPI max frame length. + */ + max_len = QSPI_FRAME; + max_len -= 1 + op->addr.nbytes + op->dummy.nbytes; + op->data.nbytes = min((size_t) op->data.nbytes, + max_len); + } + } + + return 0; +} + static int ti_qspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) { @@ -543,7 +622,7 @@ static int ti_qspi_exec_mem_op(struct spi_mem *mem, mutex_lock(&qspi->list_lock); - if (!qspi->mmap_enabled) + if (!qspi->mmap_enabled || qspi->current_cs != mem->spi->chip_select) ti_qspi_enable_memory_map(mem->spi); ti_qspi_setup_mmap_read(mem->spi, op->cmd.opcode, op->data.buswidth, op->addr.nbytes, op->dummy.nbytes); @@ -574,6 +653,7 @@ static int ti_qspi_exec_mem_op(struct spi_mem *mem, static const struct spi_controller_mem_ops ti_qspi_mem_ops = { .exec_op = ti_qspi_exec_mem_op, + .adjust_op_size = ti_qspi_adjust_op_size, }; static int ti_qspi_start_transfer_one(struct spi_master *master, @@ -717,7 +797,6 @@ static int ti_qspi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); ret = irq; goto free_master; } @@ -800,6 +879,7 @@ no_dma: } } qspi->mmap_enabled = false; + qspi->current_cs = -1; ret = devm_spi_register_master(&pdev->dev, master); if (!ret) diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index f88cbb94ce12..d7ea6af74743 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -863,7 +863,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw) /* Set Tx DMA */ param = &dma->param_tx; param->dma_dev = &dma_dev->dev; - param->chan_id = data->ch * 2; /* Tx = 0, 2 */; + param->chan_id = data->ch * 2; /* Tx = 0, 2 */ param->tx_reg = data->io_base_addr + PCH_SPDWR; param->width = width; chan = dma_request_channel(mask, pch_spi_filter, param); @@ -878,7 +878,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw) /* Set Rx DMA */ param = &dma->param_rx; param->dma_dev = &dma_dev->dev; - param->chan_id = data->ch * 2 + 1; /* Rx = Tx + 1 */; + param->chan_id = data->ch * 2 + 1; /* Rx = Tx + 1 */ param->rx_reg = data->io_base_addr + PCH_SPDRR; param->width = width; chan = dma_request_channel(mask, pch_spi_filter, param); @@ -1229,12 +1229,7 @@ static void pch_spi_process_messages(struct work_struct *pwork) "%s:data->current_msg->actual_length=%d\n", __func__, data->current_msg->actual_length); - /* check for delay */ - if (data->cur_trans->delay_usecs) { - dev_dbg(&data->master->dev, "%s:delay in usec=%d\n", - __func__, data->cur_trans->delay_usecs); - udelay(data->cur_trans->delay_usecs); - } + spi_transfer_delay_exec(data->cur_trans); spin_lock(&data->lock); diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c index 51759d3fd45f..3606232f190f 100644 --- a/drivers/spi/spi-txx9.c +++ b/drivers/spi/spi-txx9.c @@ -26,7 +26,8 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/gpio.h> +#include <linux/gpio/machine.h> +#include <linux/gpio/consumer.h> #define SPI_FIFO_SIZE 4 @@ -79,7 +80,7 @@ struct txx9spi { void __iomem *membase; int baseclk; struct clk *clk; - int last_chipselect; + struct gpio_desc *last_chipselect; int last_chipselect_val; }; @@ -95,20 +96,22 @@ static void txx9spi_wr(struct txx9spi *c, u32 val, int reg) static void txx9spi_cs_func(struct spi_device *spi, struct txx9spi *c, int on, unsigned int cs_delay) { - int val = (spi->mode & SPI_CS_HIGH) ? on : !on; - + /* + * The GPIO descriptor will track polarity inversion inside + * gpiolib. + */ if (on) { /* deselect the chip with cs_change hint in last transfer */ - if (c->last_chipselect >= 0) - gpio_set_value(c->last_chipselect, + if (c->last_chipselect) + gpiod_set_value(c->last_chipselect, !c->last_chipselect_val); - c->last_chipselect = spi->chip_select; - c->last_chipselect_val = val; + c->last_chipselect = spi->cs_gpiod; + c->last_chipselect_val = on; } else { - c->last_chipselect = -1; + c->last_chipselect = NULL; ndelay(cs_delay); /* CS Hold Time */ } - gpio_set_value(spi->chip_select, val); + gpiod_set_value(spi->cs_gpiod, on); ndelay(cs_delay); /* CS Setup Time / CS Recovery Time */ } @@ -119,12 +122,6 @@ static int txx9spi_setup(struct spi_device *spi) if (!spi->max_speed_hz) return -EINVAL; - if (gpio_direction_output(spi->chip_select, - !(spi->mode & SPI_CS_HIGH))) { - dev_err(&spi->dev, "Cannot setup GPIO for chipselect.\n"); - return -EINVAL; - } - /* deselect chip */ spin_lock(&c->lock); txx9spi_cs_func(spi, c, 0, (NSEC_PER_SEC / 2) / spi->max_speed_hz); @@ -248,8 +245,7 @@ static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m) len -= count * wsize; } m->actual_length += t->len; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); if (!cs_change) continue; @@ -320,6 +316,47 @@ static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m) return 0; } +/* + * Chip select uses GPIO only, further the driver is using the chip select + * numer (from the device tree "reg" property, and this can only come from + * device tree since this i MIPS and there is no way to pass platform data) as + * the GPIO number. As the platform has only one GPIO controller (the txx9 GPIO + * chip) it is thus using the chip select number as an offset into that chip. + * This chip has a maximum of 16 GPIOs 0..15 and this is what all platforms + * register. + * + * We modernized this behaviour by explicitly converting that offset to an + * offset on the GPIO chip using a GPIO descriptor machine table of the same + * size as the txx9 GPIO chip with a 1-to-1 mapping of chip select to GPIO + * offset. + * + * This is admittedly a hack, but it is countering the hack of using "reg" to + * contain a GPIO offset when it should be using "cs-gpios" as the SPI bindings + * state. + */ +static struct gpiod_lookup_table txx9spi_cs_gpio_table = { + .dev_id = "spi0", + .table = { + GPIO_LOOKUP_IDX("TXx9", 0, "cs", 0, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 1, "cs", 1, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 2, "cs", 2, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 3, "cs", 3, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 4, "cs", 4, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 5, "cs", 5, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 6, "cs", 6, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 7, "cs", 7, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 8, "cs", 8, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 9, "cs", 9, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 10, "cs", 10, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 11, "cs", 11, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 12, "cs", 12, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 13, "cs", 13, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 14, "cs", 14, GPIO_ACTIVE_LOW), + GPIO_LOOKUP_IDX("TXx9", 15, "cs", 15, GPIO_ACTIVE_LOW), + { }, + }, +}; + static int txx9spi_probe(struct platform_device *dev) { struct spi_master *master; @@ -373,12 +410,14 @@ static int txx9spi_probe(struct platform_device *dev) if (ret) goto exit; - c->last_chipselect = -1; + c->last_chipselect = NULL; dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n", (unsigned long long)res->start, irq, (c->baseclk + 500000) / 1000000); + gpiod_add_lookup_table(&txx9spi_cs_gpio_table); + /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA; @@ -387,6 +426,7 @@ static int txx9spi_probe(struct platform_device *dev) master->transfer = txx9spi_transfer; master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */ master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); + master->use_gpio_descriptors = true; ret = devm_spi_register_master(&dev->dev, master); if (ret) diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c index b32c77df5d49..0fa50979644d 100644 --- a/drivers/spi/spi-uniphier.c +++ b/drivers/spi/spi-uniphier.c @@ -7,6 +7,8 @@ #include <linux/bitfield.h> #include <linux/bitops.h> #include <linux/clk.h> +#include <linux/delay.h> +#include <linux/dmaengine.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> @@ -16,11 +18,13 @@ #include <asm/unaligned.h> #define SSI_TIMEOUT_MS 2000 +#define SSI_POLL_TIMEOUT_US 200 #define SSI_MAX_CLK_DIVIDER 254 #define SSI_MIN_CLK_DIVIDER 4 struct uniphier_spi_priv { void __iomem *base; + dma_addr_t base_dma_addr; struct clk *clk; struct spi_master *master; struct completion xfer_done; @@ -30,6 +34,7 @@ struct uniphier_spi_priv { unsigned int rx_bytes; const u8 *tx_buf; u8 *rx_buf; + atomic_t dma_busy; bool is_save_param; u8 bits_per_word; @@ -59,11 +64,16 @@ struct uniphier_spi_priv { #define SSI_FPS_FSTRT BIT(14) #define SSI_SR 0x14 +#define SSI_SR_BUSY BIT(7) #define SSI_SR_RNE BIT(0) #define SSI_IE 0x18 +#define SSI_IE_TCIE BIT(4) #define SSI_IE_RCIE BIT(3) +#define SSI_IE_TXRE BIT(2) +#define SSI_IE_RXRE BIT(1) #define SSI_IE_RORIE BIT(0) +#define SSI_IE_ALL_MASK GENMASK(4, 0) #define SSI_IS 0x1c #define SSI_IS_RXRS BIT(9) @@ -85,15 +95,19 @@ struct uniphier_spi_priv { #define SSI_RXDR 0x24 #define SSI_FIFO_DEPTH 8U +#define SSI_FIFO_BURST_NUM 1 + +#define SSI_DMA_RX_BUSY BIT(1) +#define SSI_DMA_TX_BUSY BIT(0) static inline unsigned int bytes_per_word(unsigned int bits) { return bits <= 8 ? 1 : (bits <= 16 ? 2 : 4); } -static inline void uniphier_spi_irq_enable(struct spi_device *spi, u32 mask) +static inline void uniphier_spi_irq_enable(struct uniphier_spi_priv *priv, + u32 mask) { - struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master); u32 val; val = readl(priv->base + SSI_IE); @@ -101,9 +115,9 @@ static inline void uniphier_spi_irq_enable(struct spi_device *spi, u32 mask) writel(val, priv->base + SSI_IE); } -static inline void uniphier_spi_irq_disable(struct spi_device *spi, u32 mask) +static inline void uniphier_spi_irq_disable(struct uniphier_spi_priv *priv, + u32 mask) { - struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master); u32 val; val = readl(priv->base + SSI_IE); @@ -214,6 +228,7 @@ static void uniphier_spi_setup_transfer(struct spi_device *spi, if (!priv->is_save_param || priv->mode != spi->mode) { uniphier_spi_set_mode(spi); priv->mode = spi->mode; + priv->is_save_param = false; } if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) { @@ -226,8 +241,7 @@ static void uniphier_spi_setup_transfer(struct spi_device *spi, priv->speed_hz = t->speed_hz; } - if (!priv->is_save_param) - priv->is_save_param = true; + priv->is_save_param = true; /* reset FIFOs */ val = SSI_FC_TXFFL | SSI_FC_RXFFL; @@ -288,23 +302,32 @@ static void uniphier_spi_recv(struct uniphier_spi_priv *priv) } } -static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv) +static void uniphier_spi_set_fifo_threshold(struct uniphier_spi_priv *priv, + unsigned int threshold) { - unsigned int tx_count; u32 val; - tx_count = DIV_ROUND_UP(priv->tx_bytes, - bytes_per_word(priv->bits_per_word)); - tx_count = min(tx_count, SSI_FIFO_DEPTH); - - /* set fifo threshold */ val = readl(priv->base + SSI_FC); val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK); - val |= FIELD_PREP(SSI_FC_TXFTH_MASK, tx_count); - val |= FIELD_PREP(SSI_FC_RXFTH_MASK, tx_count); + val |= FIELD_PREP(SSI_FC_TXFTH_MASK, SSI_FIFO_DEPTH - threshold); + val |= FIELD_PREP(SSI_FC_RXFTH_MASK, threshold); writel(val, priv->base + SSI_FC); +} - while (tx_count--) +static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv) +{ + unsigned int fifo_threshold, fill_words; + unsigned int bpw = bytes_per_word(priv->bits_per_word); + + fifo_threshold = DIV_ROUND_UP(priv->rx_bytes, bpw); + fifo_threshold = min(fifo_threshold, SSI_FIFO_DEPTH); + + uniphier_spi_set_fifo_threshold(priv, fifo_threshold); + + fill_words = fifo_threshold - + DIV_ROUND_UP(priv->rx_bytes - priv->tx_bytes, bpw); + + while (fill_words--) uniphier_spi_send(priv); } @@ -323,30 +346,146 @@ static void uniphier_spi_set_cs(struct spi_device *spi, bool enable) writel(val, priv->base + SSI_FPS); } -static int uniphier_spi_transfer_one(struct spi_master *master, - struct spi_device *spi, - struct spi_transfer *t) +static bool uniphier_spi_can_dma(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *t) { struct uniphier_spi_priv *priv = spi_master_get_devdata(master); - struct device *dev = master->dev.parent; - unsigned long time_left; + unsigned int bpw = bytes_per_word(priv->bits_per_word); - /* Terminate and return success for 0 byte length transfer */ - if (!t->len) - return 0; + if ((!master->dma_tx && !master->dma_rx) + || (!master->dma_tx && t->tx_buf) + || (!master->dma_rx && t->rx_buf)) + return false; - uniphier_spi_setup_transfer(spi, t); + return DIV_ROUND_UP(t->len, bpw) > SSI_FIFO_DEPTH; +} + +static void uniphier_spi_dma_rxcb(void *data) +{ + struct spi_master *master = data; + struct uniphier_spi_priv *priv = spi_master_get_devdata(master); + int state = atomic_fetch_andnot(SSI_DMA_RX_BUSY, &priv->dma_busy); + + uniphier_spi_irq_disable(priv, SSI_IE_RXRE); + + if (!(state & SSI_DMA_TX_BUSY)) + spi_finalize_current_transfer(master); +} + +static void uniphier_spi_dma_txcb(void *data) +{ + struct spi_master *master = data; + struct uniphier_spi_priv *priv = spi_master_get_devdata(master); + int state = atomic_fetch_andnot(SSI_DMA_TX_BUSY, &priv->dma_busy); + + uniphier_spi_irq_disable(priv, SSI_IE_TXRE); + + if (!(state & SSI_DMA_RX_BUSY)) + spi_finalize_current_transfer(master); +} + +static int uniphier_spi_transfer_one_dma(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *t) +{ + struct uniphier_spi_priv *priv = spi_master_get_devdata(master); + struct dma_async_tx_descriptor *rxdesc = NULL, *txdesc = NULL; + int buswidth; + + atomic_set(&priv->dma_busy, 0); + + uniphier_spi_set_fifo_threshold(priv, SSI_FIFO_BURST_NUM); + + if (priv->bits_per_word <= 8) + buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; + else if (priv->bits_per_word <= 16) + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + else + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + + if (priv->rx_buf) { + struct dma_slave_config rxconf = { + .direction = DMA_DEV_TO_MEM, + .src_addr = priv->base_dma_addr + SSI_RXDR, + .src_addr_width = buswidth, + .src_maxburst = SSI_FIFO_BURST_NUM, + }; + + dmaengine_slave_config(master->dma_rx, &rxconf); + + rxdesc = dmaengine_prep_slave_sg( + master->dma_rx, + t->rx_sg.sgl, t->rx_sg.nents, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!rxdesc) + goto out_err_prep; + + rxdesc->callback = uniphier_spi_dma_rxcb; + rxdesc->callback_param = master; + + uniphier_spi_irq_enable(priv, SSI_IE_RXRE); + atomic_or(SSI_DMA_RX_BUSY, &priv->dma_busy); + + dmaengine_submit(rxdesc); + dma_async_issue_pending(master->dma_rx); + } + + if (priv->tx_buf) { + struct dma_slave_config txconf = { + .direction = DMA_MEM_TO_DEV, + .dst_addr = priv->base_dma_addr + SSI_TXDR, + .dst_addr_width = buswidth, + .dst_maxburst = SSI_FIFO_BURST_NUM, + }; + + dmaengine_slave_config(master->dma_tx, &txconf); + + txdesc = dmaengine_prep_slave_sg( + master->dma_tx, + t->tx_sg.sgl, t->tx_sg.nents, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!txdesc) + goto out_err_prep; + + txdesc->callback = uniphier_spi_dma_txcb; + txdesc->callback_param = master; + + uniphier_spi_irq_enable(priv, SSI_IE_TXRE); + atomic_or(SSI_DMA_TX_BUSY, &priv->dma_busy); + + dmaengine_submit(txdesc); + dma_async_issue_pending(master->dma_tx); + } + + /* signal that we need to wait for completion */ + return (priv->tx_buf || priv->rx_buf); + +out_err_prep: + if (rxdesc) + dmaengine_terminate_sync(master->dma_rx); + + return -EINVAL; +} + +static int uniphier_spi_transfer_one_irq(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *t) +{ + struct uniphier_spi_priv *priv = spi_master_get_devdata(master); + struct device *dev = master->dev.parent; + unsigned long time_left; reinit_completion(&priv->xfer_done); uniphier_spi_fill_tx_fifo(priv); - uniphier_spi_irq_enable(spi, SSI_IE_RCIE | SSI_IE_RORIE); + uniphier_spi_irq_enable(priv, SSI_IE_RCIE | SSI_IE_RORIE); time_left = wait_for_completion_timeout(&priv->xfer_done, msecs_to_jiffies(SSI_TIMEOUT_MS)); - uniphier_spi_irq_disable(spi, SSI_IE_RCIE | SSI_IE_RORIE); + uniphier_spi_irq_disable(priv, SSI_IE_RCIE | SSI_IE_RORIE); if (!time_left) { dev_err(dev, "transfer timeout.\n"); @@ -356,6 +495,64 @@ static int uniphier_spi_transfer_one(struct spi_master *master, return priv->error; } +static int uniphier_spi_transfer_one_poll(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *t) +{ + struct uniphier_spi_priv *priv = spi_master_get_devdata(master); + int loop = SSI_POLL_TIMEOUT_US * 10; + + while (priv->tx_bytes) { + uniphier_spi_fill_tx_fifo(priv); + + while ((priv->rx_bytes - priv->tx_bytes) > 0) { + while (!(readl(priv->base + SSI_SR) & SSI_SR_RNE) + && loop--) + ndelay(100); + + if (loop == -1) + goto irq_transfer; + + uniphier_spi_recv(priv); + } + } + + return 0; + +irq_transfer: + return uniphier_spi_transfer_one_irq(master, spi, t); +} + +static int uniphier_spi_transfer_one(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *t) +{ + struct uniphier_spi_priv *priv = spi_master_get_devdata(master); + unsigned long threshold; + bool use_dma; + + /* Terminate and return success for 0 byte length transfer */ + if (!t->len) + return 0; + + uniphier_spi_setup_transfer(spi, t); + + use_dma = master->can_dma ? master->can_dma(master, spi, t) : false; + if (use_dma) + return uniphier_spi_transfer_one_dma(master, spi, t); + + /* + * If the transfer operation will take longer than + * SSI_POLL_TIMEOUT_US, it should use irq. + */ + threshold = DIV_ROUND_UP(SSI_POLL_TIMEOUT_US * priv->speed_hz, + USEC_PER_SEC * BITS_PER_BYTE); + if (t->len > threshold) + return uniphier_spi_transfer_one_irq(master, spi, t); + else + return uniphier_spi_transfer_one_poll(master, spi, t); +} + static int uniphier_spi_prepare_transfer_hardware(struct spi_master *master) { struct uniphier_spi_priv *priv = spi_master_get_devdata(master); @@ -374,6 +571,32 @@ static int uniphier_spi_unprepare_transfer_hardware(struct spi_master *master) return 0; } +static void uniphier_spi_handle_err(struct spi_master *master, + struct spi_message *msg) +{ + struct uniphier_spi_priv *priv = spi_master_get_devdata(master); + u32 val; + + /* stop running spi transfer */ + writel(0, priv->base + SSI_CTL); + + /* reset FIFOs */ + val = SSI_FC_TXFFL | SSI_FC_RXFFL; + writel(val, priv->base + SSI_FC); + + uniphier_spi_irq_disable(priv, SSI_IE_ALL_MASK); + + if (atomic_read(&priv->dma_busy) & SSI_DMA_TX_BUSY) { + dmaengine_terminate_async(master->dma_tx); + atomic_andnot(SSI_DMA_TX_BUSY, &priv->dma_busy); + } + + if (atomic_read(&priv->dma_busy) & SSI_DMA_RX_BUSY) { + dmaengine_terminate_async(master->dma_rx); + atomic_andnot(SSI_DMA_RX_BUSY, &priv->dma_busy); + } +} + static irqreturn_t uniphier_spi_handler(int irq, void *dev_id) { struct uniphier_spi_priv *priv = dev_id; @@ -420,6 +643,8 @@ static int uniphier_spi_probe(struct platform_device *pdev) struct uniphier_spi_priv *priv; struct spi_master *master; struct resource *res; + struct dma_slave_caps caps; + u32 dma_tx_burst = 0, dma_rx_burst = 0; unsigned long clk_rate; int irq; int ret; @@ -440,6 +665,7 @@ static int uniphier_spi_probe(struct platform_device *pdev) ret = PTR_ERR(priv->base); goto out_master_put; } + priv->base_dma_addr = res->start; priv->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(priv->clk)) { @@ -454,7 +680,6 @@ static int uniphier_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ\n"); ret = irq; goto out_disable_clk; } @@ -483,7 +708,45 @@ static int uniphier_spi_probe(struct platform_device *pdev) = uniphier_spi_prepare_transfer_hardware; master->unprepare_transfer_hardware = uniphier_spi_unprepare_transfer_hardware; + master->handle_err = uniphier_spi_handle_err; + master->can_dma = uniphier_spi_can_dma; + master->num_chipselect = 1; + master->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; + + master->dma_tx = dma_request_chan(&pdev->dev, "tx"); + if (IS_ERR_OR_NULL(master->dma_tx)) { + if (PTR_ERR(master->dma_tx) == -EPROBE_DEFER) + goto out_disable_clk; + master->dma_tx = NULL; + dma_tx_burst = INT_MAX; + } else { + ret = dma_get_slave_caps(master->dma_tx, &caps); + if (ret) { + dev_err(&pdev->dev, "failed to get TX DMA capacities: %d\n", + ret); + goto out_disable_clk; + } + dma_tx_burst = caps.max_burst; + } + + master->dma_rx = dma_request_chan(&pdev->dev, "rx"); + if (IS_ERR_OR_NULL(master->dma_rx)) { + if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) + goto out_disable_clk; + master->dma_rx = NULL; + dma_rx_burst = INT_MAX; + } else { + ret = dma_get_slave_caps(master->dma_rx, &caps); + if (ret) { + dev_err(&pdev->dev, "failed to get RX DMA capacities: %d\n", + ret); + goto out_disable_clk; + } + dma_rx_burst = caps.max_burst; + } + + master->max_dma_len = min(dma_tx_burst, dma_rx_burst); ret = devm_spi_register_master(&pdev->dev, master); if (ret) @@ -503,6 +766,11 @@ static int uniphier_spi_remove(struct platform_device *pdev) { struct uniphier_spi_priv *priv = platform_get_drvdata(pdev); + if (priv->master->dma_tx) + dma_release_channel(priv->master->dma_tx); + if (priv->master->dma_rx) + dma_release_channel(priv->master->dma_rx); + clk_disable_unprepare(priv->clk); return 0; diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c index a3496c46cc1b..1d9b3f03d986 100644 --- a/drivers/spi/spi-xcomm.c +++ b/drivers/spi/spi-xcomm.c @@ -188,8 +188,7 @@ static int spi_xcomm_transfer_one(struct spi_master *master, } status = 0; - if (t->delay_usecs) - udelay(t->delay_usecs); + spi_transfer_delay_exec(t); is_first = false; } diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index d5f9d5fbb3e8..8dd2bb99cb4d 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -391,7 +391,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) struct xilinx_spi *xspi; struct xspi_platform_data *pdata; struct resource *res; - int ret, num_cs = 0, bits_per_word = 8; + int ret, num_cs = 0, bits_per_word; struct spi_master *master; u32 tmp; u8 i; @@ -403,6 +403,11 @@ static int xilinx_spi_probe(struct platform_device *pdev) } else { of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits", &num_cs); + ret = of_property_read_u32(pdev->dev.of_node, + "xlnx,num-transfer-bits", + &bits_per_word); + if (ret) + bits_per_word = 8; } if (!num_cs) { diff --git a/drivers/spi/spi-xlp.c b/drivers/spi/spi-xlp.c index 1dc479fab98c..797ac0ea8fa3 100644 --- a/drivers/spi/spi-xlp.c +++ b/drivers/spi/spi-xlp.c @@ -370,7 +370,6 @@ static int xlp_spi_probe(struct platform_device *pdev) { struct spi_master *master; struct xlp_spi_priv *xspi; - struct resource *res; struct clk *clk; int irq, err; @@ -378,16 +377,13 @@ static int xlp_spi_probe(struct platform_device *pdev) if (!xspi) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - xspi->base = devm_ioremap_resource(&pdev->dev, res); + xspi->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xspi->base)) return PTR_ERR(xspi->base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no IRQ resource found: %d\n", irq); + if (irq < 0) return irq; - } err = devm_request_irq(&pdev->dev, irq, xlp_spi_interrupt, 0, pdev->name, xspi); if (err) { diff --git a/drivers/spi/spi-xtensa-xtfpga.c b/drivers/spi/spi-xtensa-xtfpga.c index 86516eb1e143..fc2b5eb7d614 100644 --- a/drivers/spi/spi-xtensa-xtfpga.c +++ b/drivers/spi/spi-xtensa-xtfpga.c @@ -80,7 +80,6 @@ static void xtfpga_spi_chipselect(struct spi_device *spi, int is_on) static int xtfpga_spi_probe(struct platform_device *pdev) { struct xtfpga_spi *xspi; - struct resource *mem; int ret; struct spi_master *master; @@ -97,14 +96,7 @@ static int xtfpga_spi_probe(struct platform_device *pdev) xspi->bitbang.master = master; xspi->bitbang.chipselect = xtfpga_spi_chipselect; xspi->bitbang.txrx_word[SPI_MODE_0] = xtfpga_spi_txrx_word; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "No memory resource\n"); - ret = -ENODEV; - goto err; - } - xspi->regs = devm_ioremap_resource(&pdev->dev, mem); + xspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xspi->regs)) { ret = PTR_ERR(xspi->regs); goto err; diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index c6bee67decb5..17641157354d 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -7,7 +7,6 @@ #include <linux/clk.h> #include <linux/delay.h> -#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> @@ -51,7 +50,6 @@ #define ZYNQ_QSPI_CONFIG_BDRATE_MASK GENMASK(5, 3) /* Baud Rate Mask */ #define ZYNQ_QSPI_CONFIG_CPHA_MASK BIT(2) /* Clock Phase Control */ #define ZYNQ_QSPI_CONFIG_CPOL_MASK BIT(1) /* Clock Polarity Control */ -#define ZYNQ_QSPI_CONFIG_SSCTRL_MASK BIT(10) /* Slave Select Mask */ #define ZYNQ_QSPI_CONFIG_FWIDTH_MASK GENMASK(7, 6) /* FIFO width */ #define ZYNQ_QSPI_CONFIG_MSTREN_MASK BIT(0) /* Master Mode */ @@ -61,9 +59,9 @@ * These are the values used in the calculation of baud rate divisor and * setting the slave select. */ -#define ZYNQ_QSPI_BAUD_DIV_MAX GENMASK(2, 0) /* Baud rate maximum */ -#define ZYNQ_QSPI_BAUD_DIV_SHIFT 3 /* Baud rate divisor shift in CR */ -#define ZYNQ_QSPI_SS_SHIFT 10 /* Slave Select field shift in CR */ +#define ZYNQ_QSPI_CONFIG_BAUD_DIV_MAX GENMASK(2, 0) /* Baud rate maximum */ +#define ZYNQ_QSPI_CONFIG_BAUD_DIV_SHIFT 3 /* Baud rate divisor shift */ +#define ZYNQ_QSPI_CONFIG_PCS BIT(10) /* Peripheral Chip Select */ /* * QSPI Interrupt Registers bit Masks @@ -99,9 +97,9 @@ * It is named Linear Configuration but it controls other modes when not in * linear mode also. */ -#define ZYNQ_QSPI_LCFG_TWO_MEM_MASK BIT(30) /* LQSPI Two memories Mask */ -#define ZYNQ_QSPI_LCFG_SEP_BUS_MASK BIT(29) /* LQSPI Separate bus Mask */ -#define ZYNQ_QSPI_LCFG_U_PAGE_MASK BIT(28) /* LQSPI Upper Page Mask */ +#define ZYNQ_QSPI_LCFG_TWO_MEM BIT(30) /* LQSPI Two memories */ +#define ZYNQ_QSPI_LCFG_SEP_BUS BIT(29) /* LQSPI Separate bus */ +#define ZYNQ_QSPI_LCFG_U_PAGE BIT(28) /* LQSPI Upper Page */ #define ZYNQ_QSPI_LCFG_DUMMY_SHIFT 8 @@ -116,8 +114,8 @@ */ #define ZYNQ_QSPI_MODEBITS (SPI_CPOL | SPI_CPHA) -/* Default number of chip selects */ -#define ZYNQ_QSPI_DEFAULT_NUM_CS 1 +/* Maximum number of chip selects */ +#define ZYNQ_QSPI_MAX_NUM_CS 2 /** * struct zynq_qspi - Defines qspi driver instance @@ -161,6 +159,7 @@ static inline void zynq_qspi_write(struct zynq_qspi *xqspi, u32 offset, /** * zynq_qspi_init_hw - Initialize the hardware * @xqspi: Pointer to the zynq_qspi structure + * @num_cs: Number of connected CS (to enable dual memories if needed) * * The default settings of the QSPI controller's configurable parameters on * reset are @@ -178,7 +177,7 @@ static inline void zynq_qspi_write(struct zynq_qspi *xqspi, u32 offset, * - Set the little endian mode of TX FIFO and * - Enable the QSPI controller */ -static void zynq_qspi_init_hw(struct zynq_qspi *xqspi) +static void zynq_qspi_init_hw(struct zynq_qspi *xqspi, unsigned int num_cs) { u32 config_reg; @@ -186,7 +185,12 @@ static void zynq_qspi_init_hw(struct zynq_qspi *xqspi) zynq_qspi_write(xqspi, ZYNQ_QSPI_IDIS_OFFSET, ZYNQ_QSPI_IXR_ALL_MASK); /* Disable linear mode as the boot loader may have used it */ - zynq_qspi_write(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET, 0); + config_reg = 0; + /* At the same time, enable dual mode if more than 1 CS is available */ + if (num_cs > 1) + config_reg |= ZYNQ_QSPI_LCFG_TWO_MEM; + + zynq_qspi_write(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET, config_reg); /* Clear the RX FIFO */ while (zynq_qspi_read(xqspi, ZYNQ_QSPI_STATUS_OFFSET) & @@ -284,21 +288,28 @@ static void zynq_qspi_txfifo_op(struct zynq_qspi *xqspi, unsigned int size) */ static void zynq_qspi_chipselect(struct spi_device *spi, bool assert) { - struct spi_controller *ctrl = spi->master; - struct zynq_qspi *xqspi = spi_controller_get_devdata(ctrl); + struct spi_controller *ctlr = spi->master; + struct zynq_qspi *xqspi = spi_controller_get_devdata(ctlr); u32 config_reg; - config_reg = zynq_qspi_read(xqspi, ZYNQ_QSPI_CONFIG_OFFSET); - if (assert) { - /* Select the slave */ - config_reg &= ~ZYNQ_QSPI_CONFIG_SSCTRL_MASK; - config_reg |= (((~(BIT(spi->chip_select))) << - ZYNQ_QSPI_SS_SHIFT) & - ZYNQ_QSPI_CONFIG_SSCTRL_MASK); - } else { - config_reg |= ZYNQ_QSPI_CONFIG_SSCTRL_MASK; + /* Select the lower (CS0) or upper (CS1) memory */ + if (ctlr->num_chipselect > 1) { + config_reg = zynq_qspi_read(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET); + if (!spi->chip_select) + config_reg &= ~ZYNQ_QSPI_LCFG_U_PAGE; + else + config_reg |= ZYNQ_QSPI_LCFG_U_PAGE; + + zynq_qspi_write(xqspi, ZYNQ_QSPI_LINEAR_CFG_OFFSET, config_reg); } + /* Ground the line to assert the CS */ + config_reg = zynq_qspi_read(xqspi, ZYNQ_QSPI_CONFIG_OFFSET); + if (assert) + config_reg &= ~ZYNQ_QSPI_CONFIG_PCS; + else + config_reg |= ZYNQ_QSPI_CONFIG_PCS; + zynq_qspi_write(xqspi, ZYNQ_QSPI_CONFIG_OFFSET, config_reg); } @@ -332,7 +343,7 @@ static int zynq_qspi_config_op(struct zynq_qspi *xqspi, struct spi_device *spi) * ---------------- * 111 - divide by 256 */ - while ((baud_rate_val < ZYNQ_QSPI_BAUD_DIV_MAX) && + while ((baud_rate_val < ZYNQ_QSPI_CONFIG_BAUD_DIV_MAX) && (clk_get_rate(xqspi->refclk) / (2 << baud_rate_val)) > spi->max_speed_hz) baud_rate_val++; @@ -348,7 +359,7 @@ static int zynq_qspi_config_op(struct zynq_qspi *xqspi, struct spi_device *spi) config_reg |= ZYNQ_QSPI_CONFIG_CPOL_MASK; config_reg &= ~ZYNQ_QSPI_CONFIG_BDRATE_MASK; - config_reg |= (baud_rate_val << ZYNQ_QSPI_BAUD_DIV_SHIFT); + config_reg |= (baud_rate_val << ZYNQ_QSPI_CONFIG_BAUD_DIV_SHIFT); zynq_qspi_write(xqspi, ZYNQ_QSPI_CONFIG_OFFSET, config_reg); return 0; @@ -365,10 +376,10 @@ static int zynq_qspi_config_op(struct zynq_qspi *xqspi, struct spi_device *spi) */ static int zynq_qspi_setup_op(struct spi_device *spi) { - struct spi_controller *ctrl = spi->master; - struct zynq_qspi *qspi = spi_controller_get_devdata(ctrl); + struct spi_controller *ctlr = spi->master; + struct zynq_qspi *qspi = spi_controller_get_devdata(ctlr); - if (ctrl->busy) + if (ctlr->busy) return -EBUSY; clk_enable(qspi->refclk); @@ -620,7 +631,6 @@ static int zynq_qspi_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct zynq_qspi *xqspi; - struct resource *res; u32 num_cs; ctlr = spi_alloc_master(&pdev->dev, sizeof(*xqspi)); @@ -630,8 +640,7 @@ static int zynq_qspi_probe(struct platform_device *pdev) xqspi = spi_controller_get_devdata(ctlr); xqspi->dev = dev; platform_set_drvdata(pdev, xqspi); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - xqspi->regs = devm_ioremap_resource(&pdev->dev, res); + xqspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xqspi->regs)) { ret = PTR_ERR(xqspi->regs); goto remove_master; @@ -665,13 +674,9 @@ static int zynq_qspi_probe(struct platform_device *pdev) goto clk_dis_pclk; } - /* QSPI controller initializations */ - zynq_qspi_init_hw(xqspi); - xqspi->irq = platform_get_irq(pdev, 0); if (xqspi->irq <= 0) { ret = -ENXIO; - dev_err(&pdev->dev, "irq resource not found\n"); goto remove_master; } ret = devm_request_irq(&pdev->dev, xqspi->irq, zynq_qspi_irq, @@ -684,10 +689,14 @@ static int zynq_qspi_probe(struct platform_device *pdev) ret = of_property_read_u32(np, "num-cs", &num_cs); - if (ret < 0) - ctlr->num_chipselect = ZYNQ_QSPI_DEFAULT_NUM_CS; - else + if (ret < 0) { + ctlr->num_chipselect = 1; + } else if (num_cs > ZYNQ_QSPI_MAX_NUM_CS) { + dev_err(&pdev->dev, "only 2 chip selects are available\n"); + goto remove_master; + } else { ctlr->num_chipselect = num_cs; + } ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; @@ -695,7 +704,11 @@ static int zynq_qspi_probe(struct platform_device *pdev) ctlr->setup = zynq_qspi_setup_op; ctlr->max_speed_hz = clk_get_rate(xqspi->refclk) / 2; ctlr->dev.of_node = np; - ret = spi_register_controller(ctlr); + + /* QSPI controller initializations */ + zynq_qspi_init_hw(xqspi, ctlr->num_chipselect); + + ret = devm_spi_register_controller(&pdev->dev, ctlr); if (ret) { dev_err(&pdev->dev, "spi_register_master failed\n"); goto clk_dis_all; diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 07a83ca164c2..60c4de4e4485 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -1016,7 +1016,6 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) int ret = 0; struct spi_master *master; struct zynqmp_qspi *xqspi; - struct resource *res; struct device *dev = &pdev->dev; eemi_ops = zynqmp_pm_get_eemi_ops(); @@ -1031,8 +1030,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) master->dev.of_node = pdev->dev.of_node; platform_set_drvdata(pdev, master); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - xqspi->regs = devm_ioremap_resource(&pdev->dev, res); + xqspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xqspi->regs)) { ret = PTR_ERR(xqspi->regs); goto remove_master; @@ -1077,7 +1075,6 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) xqspi->irq = platform_get_irq(pdev, 0); if (xqspi->irq <= 0) { ret = -ENXIO; - dev_err(dev, "irq resource not found\n"); goto clk_dis_all; } ret = devm_request_irq(&pdev->dev, xqspi->irq, zynqmp_qspi_irq, diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 75ac046cae52..38b4c78df506 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -92,7 +92,7 @@ static ssize_t driver_override_store(struct device *dev, if (len) { spi->driver_override = driver_override; } else { - /* Emptry string, disable driver override */ + /* Empty string, disable driver override */ spi->driver_override = NULL; kfree(driver_override); } @@ -469,7 +469,7 @@ static LIST_HEAD(board_list); static LIST_HEAD(spi_controller_list); /* - * Used to protect add/del opertion for board_info list and + * Used to protect add/del operation for board_info list and * spi_controller list, and their matching process * also used to protect object of type struct idr */ @@ -775,6 +775,15 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) static void spi_set_cs(struct spi_device *spi, bool enable) { + bool enable1 = enable; + + if (!spi->controller->set_cs_timing) { + if (enable1) + spi_delay_exec(&spi->controller->cs_setup, NULL); + else + spi_delay_exec(&spi->controller->cs_hold, NULL); + } + if (spi->mode & SPI_CS_HIGH) enable = !enable; @@ -800,6 +809,11 @@ static void spi_set_cs(struct spi_device *spi, bool enable) } else if (spi->controller->set_cs) { spi->controller->set_cs(spi, !enable); } + + if (!spi->controller->set_cs_timing) { + if (!enable1) + spi_delay_exec(&spi->controller->cs_inactive, NULL); + } } #ifdef CONFIG_HAS_DMA @@ -1106,42 +1120,79 @@ static void _spi_transfer_delay_ns(u32 ns) } } -static void _spi_transfer_cs_change_delay(struct spi_message *msg, - struct spi_transfer *xfer) +int spi_delay_to_ns(struct spi_delay *_delay, struct spi_transfer *xfer) { - u32 delay = xfer->cs_change_delay; - u32 unit = xfer->cs_change_delay_unit; + u32 delay = _delay->value; + u32 unit = _delay->unit; u32 hz; - /* return early on "fast" mode - for everything but USECS */ - if (!delay && unit != SPI_DELAY_UNIT_USECS) - return; + if (!delay) + return 0; switch (unit) { case SPI_DELAY_UNIT_USECS: - /* for compatibility use default of 10us */ - if (!delay) - delay = 10000; - else - delay *= 1000; + delay *= 1000; break; case SPI_DELAY_UNIT_NSECS: /* nothing to do here */ break; case SPI_DELAY_UNIT_SCK: + /* clock cycles need to be obtained from spi_transfer */ + if (!xfer) + return -EINVAL; /* if there is no effective speed know, then approximate * by underestimating with half the requested hz */ hz = xfer->effective_speed_hz ?: xfer->speed_hz / 2; + if (!hz) + return -EINVAL; delay *= DIV_ROUND_UP(1000000000, hz); break; default: + return -EINVAL; + } + + return delay; +} +EXPORT_SYMBOL_GPL(spi_delay_to_ns); + +int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer) +{ + int delay; + + if (!_delay) + return -EINVAL; + + delay = spi_delay_to_ns(_delay, xfer); + if (delay < 0) + return delay; + + _spi_transfer_delay_ns(delay); + + return 0; +} +EXPORT_SYMBOL_GPL(spi_delay_exec); + +static void _spi_transfer_cs_change_delay(struct spi_message *msg, + struct spi_transfer *xfer) +{ + u32 delay = xfer->cs_change_delay.value; + u32 unit = xfer->cs_change_delay.unit; + int ret; + + /* return early on "fast" mode - for everything but USECS */ + if (!delay) { + if (unit == SPI_DELAY_UNIT_USECS) + _spi_transfer_delay_ns(10000); + return; + } + + ret = spi_delay_exec(&xfer->cs_change_delay, xfer); + if (ret) { dev_err_once(&msg->spi->dev, "Use of unsupported delay unit %i, using default of 10us\n", - xfer->cs_change_delay_unit); - delay = 10000; + unit); + _spi_transfer_delay_ns(10000); } - /* now sleep for the requested amount of time */ - _spi_transfer_delay_ns(delay); } /* @@ -1171,6 +1222,11 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, spi_statistics_add_transfer_stats(statm, xfer, ctlr); spi_statistics_add_transfer_stats(stats, xfer, ctlr); + if (!ctlr->ptp_sts_supported) { + xfer->ptp_sts_word_pre = 0; + ptp_read_system_prets(xfer->ptp_sts); + } + if (xfer->tx_buf || xfer->rx_buf) { reinit_completion(&ctlr->xfer_completion); @@ -1197,13 +1253,17 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, xfer->len); } + if (!ctlr->ptp_sts_supported) { + ptp_read_system_postts(xfer->ptp_sts); + xfer->ptp_sts_word_post = xfer->len; + } + trace_spi_transfer_stop(msg, xfer); if (msg->status != -EINPROGRESS) goto out; - if (xfer->delay_usecs) - _spi_transfer_delay_ns(xfer->delay_usecs * 1000); + spi_transfer_delay_exec(xfer); if (xfer->cs_change) { if (list_is_last(&xfer->transfer_list, @@ -1265,8 +1325,10 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer); */ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread) { - unsigned long flags; + struct spi_transfer *xfer; + struct spi_message *msg; bool was_busy = false; + unsigned long flags; int ret; /* Lock queue */ @@ -1325,10 +1387,10 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread) } /* Extract head of queue */ - ctlr->cur_msg = - list_first_entry(&ctlr->queue, struct spi_message, queue); + msg = list_first_entry(&ctlr->queue, struct spi_message, queue); + ctlr->cur_msg = msg; - list_del_init(&ctlr->cur_msg->queue); + list_del_init(&msg->queue); if (ctlr->busy) was_busy = true; else @@ -1361,7 +1423,7 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread) if (ctlr->auto_runtime_pm) pm_runtime_put(ctlr->dev.parent); - ctlr->cur_msg->status = ret; + msg->status = ret; spi_finalize_current_message(ctlr); mutex_unlock(&ctlr->io_mutex); @@ -1369,28 +1431,35 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread) } } - trace_spi_message_start(ctlr->cur_msg); + trace_spi_message_start(msg); if (ctlr->prepare_message) { - ret = ctlr->prepare_message(ctlr, ctlr->cur_msg); + ret = ctlr->prepare_message(ctlr, msg); if (ret) { dev_err(&ctlr->dev, "failed to prepare message: %d\n", ret); - ctlr->cur_msg->status = ret; + msg->status = ret; spi_finalize_current_message(ctlr); goto out; } ctlr->cur_msg_prepared = true; } - ret = spi_map_msg(ctlr, ctlr->cur_msg); + ret = spi_map_msg(ctlr, msg); if (ret) { - ctlr->cur_msg->status = ret; + msg->status = ret; spi_finalize_current_message(ctlr); goto out; } - ret = ctlr->transfer_one_message(ctlr, ctlr->cur_msg); + if (!ctlr->ptp_sts_supported && !ctlr->transfer_one) { + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + xfer->ptp_sts_word_pre = 0; + ptp_read_system_prets(xfer->ptp_sts); + } + } + + ret = ctlr->transfer_one_message(ctlr, msg); if (ret) { dev_err(&ctlr->dev, "failed to transfer one message from queue\n"); @@ -1418,6 +1487,93 @@ static void spi_pump_messages(struct kthread_work *work) } /** + * spi_take_timestamp_pre - helper for drivers to collect the beginning of the + * TX timestamp for the requested byte from the SPI + * transfer. The frequency with which this function + * must be called (once per word, once for the whole + * transfer, once per batch of words etc) is arbitrary + * as long as the @tx buffer offset is greater than or + * equal to the requested byte at the time of the + * call. The timestamp is only taken once, at the + * first such call. It is assumed that the driver + * advances its @tx buffer pointer monotonically. + * @ctlr: Pointer to the spi_controller structure of the driver + * @xfer: Pointer to the transfer being timestamped + * @progress: How many words (not bytes) have been transferred so far + * @irqs_off: If true, will disable IRQs and preemption for the duration of the + * transfer, for less jitter in time measurement. Only compatible + * with PIO drivers. If true, must follow up with + * spi_take_timestamp_post or otherwise system will crash. + * WARNING: for fully predictable results, the CPU frequency must + * also be under control (governor). + */ +void spi_take_timestamp_pre(struct spi_controller *ctlr, + struct spi_transfer *xfer, + size_t progress, bool irqs_off) +{ + if (!xfer->ptp_sts) + return; + + if (xfer->timestamped_pre) + return; + + if (progress < xfer->ptp_sts_word_pre) + return; + + /* Capture the resolution of the timestamp */ + xfer->ptp_sts_word_pre = progress; + + xfer->timestamped_pre = true; + + if (irqs_off) { + local_irq_save(ctlr->irq_flags); + preempt_disable(); + } + + ptp_read_system_prets(xfer->ptp_sts); +} +EXPORT_SYMBOL_GPL(spi_take_timestamp_pre); + +/** + * spi_take_timestamp_post - helper for drivers to collect the end of the + * TX timestamp for the requested byte from the SPI + * transfer. Can be called with an arbitrary + * frequency: only the first call where @tx exceeds + * or is equal to the requested word will be + * timestamped. + * @ctlr: Pointer to the spi_controller structure of the driver + * @xfer: Pointer to the transfer being timestamped + * @progress: How many words (not bytes) have been transferred so far + * @irqs_off: If true, will re-enable IRQs and preemption for the local CPU. + */ +void spi_take_timestamp_post(struct spi_controller *ctlr, + struct spi_transfer *xfer, + size_t progress, bool irqs_off) +{ + if (!xfer->ptp_sts) + return; + + if (xfer->timestamped_post) + return; + + if (progress < xfer->ptp_sts_word_post) + return; + + ptp_read_system_postts(xfer->ptp_sts); + + if (irqs_off) { + local_irq_restore(ctlr->irq_flags); + preempt_enable(); + } + + /* Capture the resolution of the timestamp */ + xfer->ptp_sts_word_post = progress; + + xfer->timestamped_post = true; +} +EXPORT_SYMBOL_GPL(spi_take_timestamp_post); + +/** * spi_set_thread_rt - set the controller to pump at realtime priority * @ctlr: controller to boost priority of * @@ -1434,7 +1590,7 @@ static void spi_pump_messages(struct kthread_work *work) */ static void spi_set_thread_rt(struct spi_controller *ctlr) { - struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; + struct sched_param param = { .sched_priority = MAX_RT_PRIO / 2 }; dev_info(&ctlr->dev, "will run message pump with realtime priority\n"); @@ -1502,6 +1658,7 @@ EXPORT_SYMBOL_GPL(spi_get_next_queued_message); */ void spi_finalize_current_message(struct spi_controller *ctlr) { + struct spi_transfer *xfer; struct spi_message *mesg; unsigned long flags; int ret; @@ -1510,6 +1667,20 @@ void spi_finalize_current_message(struct spi_controller *ctlr) mesg = ctlr->cur_msg; spin_unlock_irqrestore(&ctlr->queue_lock, flags); + if (!ctlr->ptp_sts_supported && !ctlr->transfer_one) { + list_for_each_entry(xfer, &mesg->transfers, transfer_list) { + ptp_read_system_postts(xfer->ptp_sts); + xfer->ptp_sts_word_post = xfer->len; + } + } + + if (unlikely(ctlr->ptp_sts_supported)) { + list_for_each_entry(xfer, &mesg->transfers, transfer_list) { + WARN_ON_ONCE(xfer->ptp_sts && !xfer->timestamped_pre); + WARN_ON_ONCE(xfer->ptp_sts && !xfer->timestamped_post); + } + } + spi_unmap_msg(ctlr, mesg); if (ctlr->cur_msg_prepared && ctlr->unprepare_message) { @@ -1710,15 +1881,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, spi->mode |= SPI_3WIRE; if (of_property_read_bool(nc, "spi-lsb-first")) spi->mode |= SPI_LSB_FIRST; - - /* - * For descriptors associated with the device, polarity inversion is - * handled in the gpiolib, so all chip selects are "active high" in - * the logical sense, the gpiolib will invert the line if need be. - */ - if (ctlr->use_gpio_descriptors) - spi->mode |= SPI_CS_HIGH; - else if (of_property_read_bool(nc, "spi-cs-high")) + if (of_property_read_bool(nc, "spi-cs-high")) spi->mode |= SPI_CS_HIGH; /* Device DUAL/QUAD mode */ @@ -1782,6 +1945,15 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, } spi->chip_select = value; + /* + * For descriptors associated with the device, polarity inversion is + * handled in the gpiolib, so all gpio chip selects are "active high" + * in the logical sense, the gpiolib will invert the line if need be. + */ + if ((ctlr->use_gpio_descriptors) && ctlr->cs_gpiods && + ctlr->cs_gpiods[spi->chip_select]) + spi->mode |= SPI_CS_HIGH; + /* Device speed */ rc = of_property_read_u32(nc, "spi-max-frequency", &value); if (rc) { @@ -2105,8 +2277,8 @@ static int match_true(struct device *dev, void *data) return 1; } -static ssize_t spi_slave_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t slave_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct spi_controller *ctlr = container_of(dev, struct spi_controller, dev); @@ -2117,9 +2289,8 @@ static ssize_t spi_slave_show(struct device *dev, child ? to_spi_device(child)->modalias : NULL); } -static ssize_t spi_slave_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) +static ssize_t slave_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct spi_controller *ctlr = container_of(dev, struct spi_controller, dev); @@ -2157,7 +2328,7 @@ static ssize_t spi_slave_store(struct device *dev, return count; } -static DEVICE_ATTR(slave, 0644, spi_slave_show, spi_slave_store); +static DEVICE_ATTR_RW(slave); static struct attribute *spi_slave_attrs[] = { &dev_attr_slave.attr, @@ -2188,8 +2359,10 @@ extern struct class spi_slave_class; /* dummy */ * __spi_alloc_controller - allocate an SPI master or slave controller * @dev: the controller, possibly using the platform_bus * @size: how much zeroed driver-private data to allocate; the pointer to this - * memory is in the driver_data field of the returned device, - * accessible with spi_controller_get_devdata(). + * memory is in the driver_data field of the returned device, accessible + * with spi_controller_get_devdata(); the memory is cacheline aligned; + * drivers granting DMA access to portions of their private data need to + * round up @size using ALIGN(size, dma_get_cache_alignment()). * @slave: flag indicating whether to allocate an SPI master (false) or SPI * slave (true) controller * Context: can sleep @@ -2211,11 +2384,12 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, unsigned int size, bool slave) { struct spi_controller *ctlr; + size_t ctlr_size = ALIGN(sizeof(*ctlr), dma_get_cache_alignment()); if (!dev) return NULL; - ctlr = kzalloc(size + sizeof(*ctlr), GFP_KERNEL); + ctlr = kzalloc(size + ctlr_size, GFP_KERNEL); if (!ctlr) return NULL; @@ -2229,14 +2403,14 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, ctlr->dev.class = &spi_master_class; ctlr->dev.parent = dev; pm_suspend_ignore_children(&ctlr->dev, true); - spi_controller_set_devdata(ctlr, &ctlr[1]); + spi_controller_set_devdata(ctlr, (void *)ctlr + ctlr_size); return ctlr; } EXPORT_SYMBOL_GPL(__spi_alloc_controller); #ifdef CONFIG_OF -static int of_spi_register_master(struct spi_controller *ctlr) +static int of_spi_get_gpio_numbers(struct spi_controller *ctlr) { int nb, i, *cs; struct device_node *np = ctlr->dev.of_node; @@ -2269,7 +2443,7 @@ static int of_spi_register_master(struct spi_controller *ctlr) return 0; } #else -static int of_spi_register_master(struct spi_controller *ctlr) +static int of_spi_get_gpio_numbers(struct spi_controller *ctlr) { return 0; } @@ -2284,6 +2458,8 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr) int nb, i; struct gpio_desc **cs; struct device *dev = &ctlr->dev; + unsigned long native_cs_mask = 0; + unsigned int num_cs_gpios = 0; nb = gpiod_count(dev, "cs"); ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect); @@ -2325,7 +2501,22 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr) if (!gpioname) return -ENOMEM; gpiod_set_consumer_name(cs[i], gpioname); + num_cs_gpios++; + continue; + } + + if (ctlr->max_native_cs && i >= ctlr->max_native_cs) { + dev_err(dev, "Invalid native chip select %d\n", i); + return -EINVAL; } + native_cs_mask |= BIT(i); + } + + ctlr->unused_native_cs = ffz(native_cs_mask); + if (num_cs_gpios && ctlr->max_native_cs && + ctlr->unused_native_cs >= ctlr->max_native_cs) { + dev_err(dev, "No unused native chip select available\n"); + return -EINVAL; } return 0; @@ -2456,7 +2647,7 @@ int spi_register_controller(struct spi_controller *ctlr) ctlr->mode_bits |= SPI_CS_HIGH; } else { /* Legacy code path for GPIOs from DT */ - status = of_spi_register_master(ctlr); + status = of_spi_get_gpio_numbers(ctlr); if (status) return status; } @@ -2868,10 +3059,11 @@ struct spi_replaced_transfers *spi_replace_transfers( /* add to list */ list_add(&xfer->transfer_list, rxfer->replaced_after); - /* clear cs_change and delay_usecs for all but the last */ + /* clear cs_change and delay for all but the last */ if (i) { xfer->cs_change = false; xfer->delay_usecs = 0; + xfer->delay.value = 0; } } @@ -3088,7 +3280,29 @@ int spi_setup(struct spi_device *spi) if (spi->controller->setup) status = spi->controller->setup(spi); - spi_set_cs(spi, false); + if (spi->controller->auto_runtime_pm && spi->controller->set_cs) { + status = pm_runtime_get_sync(spi->controller->dev.parent); + if (status < 0) { + pm_runtime_put_noidle(spi->controller->dev.parent); + dev_err(&spi->controller->dev, "Failed to power device: %d\n", + status); + return status; + } + + /* + * We do not want to return positive value from pm_runtime_get, + * there are many instances of devices calling spi_setup() and + * checking for a non-zero return value instead of a negative + * return value. + */ + status = 0; + + spi_set_cs(spi, false); + pm_runtime_mark_last_busy(spi->controller->dev.parent); + pm_runtime_put_autosuspend(spi->controller->dev.parent); + } else { + spi_set_cs(spi, false); + } if (spi->rt && !spi->controller->rt) { spi->controller->rt = true; @@ -3111,18 +3325,71 @@ EXPORT_SYMBOL_GPL(spi_setup); /** * spi_set_cs_timing - configure CS setup, hold, and inactive delays * @spi: the device that requires specific CS timing configuration - * @setup: CS setup time in terms of clock count - * @hold: CS hold time in terms of clock count - * @inactive_dly: CS inactive delay between transfers in terms of clock count + * @setup: CS setup time specified via @spi_delay + * @hold: CS hold time specified via @spi_delay + * @inactive: CS inactive delay between transfers specified via @spi_delay + * + * Return: zero on success, else a negative error code. */ -void spi_set_cs_timing(struct spi_device *spi, u8 setup, u8 hold, - u8 inactive_dly) +int spi_set_cs_timing(struct spi_device *spi, struct spi_delay *setup, + struct spi_delay *hold, struct spi_delay *inactive) { + size_t len; + if (spi->controller->set_cs_timing) - spi->controller->set_cs_timing(spi, setup, hold, inactive_dly); + return spi->controller->set_cs_timing(spi, setup, hold, + inactive); + + if ((setup && setup->unit == SPI_DELAY_UNIT_SCK) || + (hold && hold->unit == SPI_DELAY_UNIT_SCK) || + (inactive && inactive->unit == SPI_DELAY_UNIT_SCK)) { + dev_err(&spi->dev, + "Clock-cycle delays for CS not supported in SW mode\n"); + return -ENOTSUPP; + } + + len = sizeof(struct spi_delay); + + /* copy delays to controller */ + if (setup) + memcpy(&spi->controller->cs_setup, setup, len); + else + memset(&spi->controller->cs_setup, 0, len); + + if (hold) + memcpy(&spi->controller->cs_hold, hold, len); + else + memset(&spi->controller->cs_hold, 0, len); + + if (inactive) + memcpy(&spi->controller->cs_inactive, inactive, len); + else + memset(&spi->controller->cs_inactive, 0, len); + + return 0; } EXPORT_SYMBOL_GPL(spi_set_cs_timing); +static int _spi_xfer_word_delay_update(struct spi_transfer *xfer, + struct spi_device *spi) +{ + int delay1, delay2; + + delay1 = spi_delay_to_ns(&xfer->word_delay, xfer); + if (delay1 < 0) + return delay1; + + delay2 = spi_delay_to_ns(&spi->word_delay, xfer); + if (delay2 < 0) + return delay2; + + if (delay1 < delay2) + memcpy(&xfer->word_delay, &spi->word_delay, + sizeof(xfer->word_delay)); + + return 0; +} + static int __spi_validate(struct spi_device *spi, struct spi_message *message) { struct spi_controller *ctlr = spi->controller; @@ -3258,8 +3525,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) return -EINVAL; } - if (xfer->word_delay_usecs < spi->word_delay_usecs) - xfer->word_delay_usecs = spi->word_delay_usecs; + if (_spi_xfer_word_delay_update(xfer, spi)) + return -EINVAL; } message->status = -EINPROGRESS; @@ -3270,6 +3537,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) static int __spi_async(struct spi_device *spi, struct spi_message *message) { struct spi_controller *ctlr = spi->controller; + struct spi_transfer *xfer; /* * Some controllers do not support doing regular SPI transfers. Return @@ -3285,6 +3553,13 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) trace_spi_message_submit(message); + if (!ctlr->ptp_sts_supported) { + list_for_each_entry(xfer, &message->transfers, transfer_list) { + xfer->ptp_sts_word_pre = 0; + ptp_read_system_prets(xfer->ptp_sts); + } + } + return ctlr->transfer(spi, message); } @@ -3652,37 +3927,25 @@ EXPORT_SYMBOL_GPL(spi_write_then_read); /*-------------------------------------------------------------------------*/ #if IS_ENABLED(CONFIG_OF) -static int __spi_of_device_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - /* must call put_device() when done with returned spi_device device */ struct spi_device *of_find_spi_device_by_node(struct device_node *node) { - struct device *dev = bus_find_device(&spi_bus_type, NULL, node, - __spi_of_device_match); + struct device *dev = bus_find_device_by_of_node(&spi_bus_type, node); + return dev ? to_spi_device(dev) : NULL; } EXPORT_SYMBOL_GPL(of_find_spi_device_by_node); #endif /* IS_ENABLED(CONFIG_OF) */ #if IS_ENABLED(CONFIG_OF_DYNAMIC) -static int __spi_of_controller_match(struct device *dev, const void *data) -{ - return dev->of_node == data; -} - /* the spi controllers are not using spi_bus, so we find it with another way */ static struct spi_controller *of_find_spi_controller_by_node(struct device_node *node) { struct device *dev; - dev = class_find_device(&spi_master_class, NULL, node, - __spi_of_controller_match); + dev = class_find_device_by_of_node(&spi_master_class, node); if (!dev && IS_ENABLED(CONFIG_SPI_SLAVE)) - dev = class_find_device(&spi_slave_class, NULL, node, - __spi_of_controller_match); + dev = class_find_device_by_of_node(&spi_slave_class, node); if (!dev) return NULL; @@ -3753,11 +4016,6 @@ static int spi_acpi_controller_match(struct device *dev, const void *data) return ACPI_COMPANION(dev->parent) == data; } -static int spi_acpi_device_match(struct device *dev, const void *data) -{ - return ACPI_COMPANION(dev) == data; -} - static struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev) { struct device *dev; @@ -3777,8 +4035,7 @@ static struct spi_device *acpi_spi_find_device_by_adev(struct acpi_device *adev) { struct device *dev; - dev = bus_find_device(&spi_bus_type, NULL, adev, spi_acpi_device_match); - + dev = bus_find_device_by_acpi_dev(&spi_bus_type, adev); return dev ? to_spi_device(dev) : NULL; } diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 255786f2e844..1e217e3e9486 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -265,9 +265,11 @@ static int spidev_message(struct spidev_data *spidev, k_tmp->tx_nbits = u_tmp->tx_nbits; k_tmp->rx_nbits = u_tmp->rx_nbits; k_tmp->bits_per_word = u_tmp->bits_per_word; - k_tmp->delay_usecs = u_tmp->delay_usecs; + k_tmp->delay.value = u_tmp->delay_usecs; + k_tmp->delay.unit = SPI_DELAY_UNIT_USECS; k_tmp->speed_hz = u_tmp->speed_hz; - k_tmp->word_delay_usecs = u_tmp->word_delay_usecs; + k_tmp->word_delay.value = u_tmp->word_delay_usecs; + k_tmp->word_delay.unit = SPI_DELAY_UNIT_USECS; if (!k_tmp->speed_hz) k_tmp->speed_hz = spidev->speed_hz; #ifdef VERBOSE @@ -627,6 +629,9 @@ static int spidev_release(struct inode *inode, struct file *filp) if (dofree) kfree(spidev); } +#ifdef CONFIG_SPI_SLAVE + spi_slave_abort(spidev->spi); +#endif mutex_unlock(&device_list_lock); return 0; |