diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-01-27 11:15:34 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-01-27 11:15:34 -0800 |
commit | 1e1ab4ba4747afad3e44a77dded1bab4cb77049e (patch) | |
tree | eebb31be37d25b5d875d70b2fe908df1b412471c | |
parent | e83a0ed2a6a3f6e67630d1580f1ade97a54c524f (diff) | |
parent | 754a36a58c29718bf5e28b8789b17bffbb60e8a6 (diff) |
Merge tag 'spi-v5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"Not much going on in the core for SPI this time but a reasonable
amount of change in the drivers:
- Removal of dmal_request_slave_channel() from Peter Ujfalusi.
- More conversions of drivers to GPIO descriptors from Linus Walleij.
- A big rework of the sh-msiof driver from Geert Uytterhoeven moving
it over to the generic native chipselect support.
- DMA support for the uniphier driver from Kunihiko Hayashi.
- New driver support for HiSilcon v3xx SPI NOR controllers from John
Garry"
* tag 'spi-v5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (52 commits)
dt-binding: spi: add NPCM PSPI reset binding
spi: pxa2xx: Avoid touching SSCR0_SSE on MMP2
spi: spi-fsl-qspi: Ensure width is respected in spi-mem operations
spi: npcm-pspi: modify reset support
spi: npcm-pspi: improve spi transfer performance
spi: spi-ti-qspi: fix warning
spi: npcm-pspi: fix 16 bit send and receive support
spi: pxa2xx: Add support for Intel Comet Lake PCH-V
spi: fsl: simplify error path in of_fsl_spi_probe()
spi: fsl-lpspi: fix only one cs-gpio working
spi: spi-ti-qspi: optimize byte-transfers
spi: spi-ti-qspi: support large flash devices
spi: spi-qcom-qspi: Use device managed memory for clk_bulk_data
MAINTAINERS: Add a maintainer for the HiSilicon v3xx SFC driver
spi: Add HiSilicon v3xx SPI NOR flash controller driver
dt-bindings: spi_atmel: add microchip,sam9x60-spi
spi: bcm2835: Raise maximum number of slaves to 4
spi: sh-msiof: Do not redefine STR while compile testing
spi: rspi: Add support for GPIO chip selects
spi: rspi: Add support for multiple native chip selects
...
37 files changed, 1208 insertions, 628 deletions
diff --git a/Documentation/devicetree/bindings/spi/nuvoton,npcm-pspi.txt b/Documentation/devicetree/bindings/spi/nuvoton,npcm-pspi.txt index 1fd9a4406a1d..b98203ca656d 100644 --- a/Documentation/devicetree/bindings/spi/nuvoton,npcm-pspi.txt +++ b/Documentation/devicetree/bindings/spi/nuvoton,npcm-pspi.txt @@ -12,6 +12,7 @@ Required properties: - clock-names: Should be "clk_apb5". - pinctrl-names : a pinctrl state named "default" must be defined. - pinctrl-0 : phandle referencing pin configuration of the device. + - resets : phandle to the reset control for this device. - cs-gpios: Specifies the gpio pins to be used for chipselects. See: Documentation/devicetree/bindings/spi/spi-bus.txt @@ -19,16 +20,6 @@ Optional properties: - clock-frequency : Input clock frequency to the PSPI block in Hz. Default is 25000000 Hz. -Aliases: -- All the SPI controller nodes should be represented in the aliases node using - the following format 'spi{n}' withe the correct numbered in "aliases" node. - -Example: - -aliases { - spi0 = &spi0; -}; - spi0: spi@f0200000 { compatible = "nuvoton,npcm750-pspi"; reg = <0xf0200000 0x1000>; @@ -39,5 +30,6 @@ spi0: spi@f0200000 { interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk NPCM7XX_CLK_APB5>; clock-names = "clk_apb5"; + resets = <&rstc NPCM7XX_RESET_IPSRST2 NPCM7XX_RESET_PSPI1> cs-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>; }; diff --git a/Documentation/devicetree/bindings/spi/spi-stm32.txt b/Documentation/devicetree/bindings/spi/spi-stm32.txt deleted file mode 100644 index d82755c63eaf..000000000000 --- a/Documentation/devicetree/bindings/spi/spi-stm32.txt +++ /dev/null @@ -1,62 +0,0 @@ -STMicroelectronics STM32 SPI Controller - -The STM32 SPI controller is used to communicate with external devices using -the Serial Peripheral Interface. It supports full-duplex, half-duplex and -simplex synchronous serial communication with external devices. It supports -from 4 to 32-bit data size. Although it can be configured as master or slave, -only master is supported by the driver. - -Required properties: -- compatible: Should be one of: - "st,stm32h7-spi" - "st,stm32f4-spi" -- reg: Offset and length of the device's register set. -- interrupts: Must contain the interrupt id. -- clocks: Must contain an entry for spiclk (which feeds the internal clock - generator). -- #address-cells: Number of cells required to define a chip select address. -- #size-cells: Should be zero. - -Optional properties: -- resets: Must contain the phandle to the reset controller. -- A pinctrl state named "default" may be defined to set pins in mode of - operation for SPI transfer. -- dmas: DMA specifiers for tx and rx dma. DMA fifo mode must be used. See the - STM32 DMA bindings, Documentation/devicetree/bindings/dma/stm32-dma.txt. -- dma-names: DMA request names should include "tx" and "rx" if present. -- cs-gpios: list of GPIO chip selects. See the SPI bus bindings, - Documentation/devicetree/bindings/spi/spi-bus.txt - - -Child nodes represent devices on the SPI bus - See ../spi/spi-bus.txt - -Optional properties: -- st,spi-midi-ns: Only for STM32H7, (Master Inter-Data Idleness) minimum time - delay in nanoseconds inserted between two consecutive data - frames. - - -Example: - spi2: spi@40003800 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "st,stm32h7-spi"; - reg = <0x40003800 0x400>; - interrupts = <36>; - clocks = <&rcc SPI2_CK>; - resets = <&rcc 1166>; - dmas = <&dmamux1 0 39 0x400 0x01>, - <&dmamux1 1 40 0x400 0x01>; - dma-names = "rx", "tx"; - pinctrl-0 = <&spi2_pins_b>; - pinctrl-names = "default"; - cs-gpios = <&gpioa 11 0>; - - aardvark@0 { - compatible = "totalphase,aardvark"; - reg = <0>; - spi-max-frequency = <4000000>; - st,spi-midi-ns = <4000>; - }; - }; diff --git a/Documentation/devicetree/bindings/spi/spi_atmel.txt b/Documentation/devicetree/bindings/spi/spi_atmel.txt index f99c733d75c1..5bb4a8f1df7a 100644 --- a/Documentation/devicetree/bindings/spi/spi_atmel.txt +++ b/Documentation/devicetree/bindings/spi/spi_atmel.txt @@ -1,7 +1,7 @@ Atmel SPI device Required properties: -- compatible : should be "atmel,at91rm9200-spi". +- compatible : should be "atmel,at91rm9200-spi" or "microchip,sam9x60-spi". - reg: Address and length of the register set for the device - interrupts: Should contain spi interrupt - cs-gpios: chipselects (optional for SPI controller version >= 2 with the diff --git a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml new file mode 100644 index 000000000000..f0d979664f07 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/st,stm32-spi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 SPI Controller bindings + +description: | + The STM32 SPI controller is used to communicate with external devices using + the Serial Peripheral Interface. It supports full-duplex, half-duplex and + simplex synchronous serial communication with external devices. It supports + from 4 to 32-bit data size. + +maintainers: + - Erwan Leray <erwan.leray@st.com> + - Fabrice Gasnier <fabrice.gasnier@st.com> + +allOf: + - $ref: "spi-controller.yaml#" + - if: + properties: + compatible: + contains: + const: st,stm32f4-spi + + then: + properties: + st,spi-midi-ns: false + +properties: + compatible: + enum: + - st,stm32f4-spi + - st,stm32h7-spi + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + + resets: + maxItems: 1 + + dmas: + description: | + DMA specifiers for tx and rx dma. DMA fifo mode must be used. See + the STM32 DMA bindings Documentation/devicetree/bindings/dma/stm32-dma.txt. + items: + - description: rx DMA channel + - description: tx DMA channel + + dma-names: + items: + - const: rx + - const: tx + +patternProperties: + "^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$": + type: object + # SPI slave nodes must be children of the SPI master node and can + # contain the following properties. + properties: + st,spi-midi-ns: + description: | + Only for STM32H7, (Master Inter-Data Idleness) minimum time + delay in nanoseconds inserted between two consecutive data frames. + +required: + - compatible + - reg + - clocks + - interrupts + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/clock/stm32mp1-clks.h> + #include <dt-bindings/reset/stm32mp1-resets.h> + spi@4000b000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x4000b000 0x400>; + interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc SPI2_K>; + resets = <&rcc SPI2_R>; + dmas = <&dmamux1 0 39 0x400 0x05>, + <&dmamux1 1 40 0x400 0x05>; + dma-names = "rx", "tx"; + cs-gpios = <&gpioa 11 0>; + + aardvark@0 { + compatible = "totalphase,aardvark"; + reg = <0>; + spi-max-frequency = <4000000>; + st,spi-midi-ns = <4000>; + }; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index a7ce7bfcb4e9..1575d416f2db 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7509,6 +7509,12 @@ S: Supported F: drivers/scsi/hisi_sas/ F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt +HISILICON V3XX SPI NOR FLASH Controller Driver +M: John Garry <john.garry@huawei.com> +W: http://www.hisilicon.com +S: Maintained +F: drivers/spi/spi-hisi-sfc-v3xx.c + HISILICON QM AND ZIP Controller DRIVER M: Zhou Wang <wangzhou1@hisilicon.com> L: linux-crypto@vger.kernel.org diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 870f7797b56b..d6ed0c355954 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -281,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 diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index bb49c9e6d0a0..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 diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 56f0ca361deb..013458cabe3c 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -514,26 +514,19 @@ static int atmel_spi_configure_dma(struct spi_master *master, 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; } @@ -548,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); diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 85bad70f59e3..23d295f36c80 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -1293,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 fb61a620effc..11c235879bb7 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -68,7 +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 3 /* raise as necessary */ +#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) @@ -888,8 +888,8 @@ static void bcm2835_dma_release(struct spi_controller *ctlr, } } -static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, - struct bcm2835_spi *bs) +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; @@ -900,19 +900,24 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, 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; } @@ -997,7 +1002,7 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, /* all went well, so set can_dma */ ctlr->can_dma = bcm2835_spi_can_dma; - return; + return 0; err_config: dev_err(dev, "issue configuring dma: %d - not using DMA mode\n", @@ -1005,7 +1010,14 @@ err_config: err_release: 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, @@ -1305,7 +1317,10 @@ 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; } @@ -1317,7 +1332,9 @@ static int bcm2835_spi_probe(struct platform_device *pdev) clk_prepare_enable(bs->clk); - bcm2835_dma_init(ctlr, &pdev->dev, bs); + 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, @@ -1327,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: 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-dw.c b/drivers/spi/spi-dw.c index 5a25da377119..31e3f866d11a 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c @@ -297,6 +297,9 @@ static int dw_spi_transfer_one(struct spi_controller *master, 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); /* Handle per transfer options for bpw and speed */ @@ -469,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) diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 8428b69c858b..6ec2dcb8c57a 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -396,17 +396,17 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr) 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; } diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index 2cc0ddb4a988..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); } @@ -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); @@ -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 79b1558b74b8..e8a499cd1f13 100644 --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c @@ -410,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, diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index fb4159ad6bf6..3b81772fea0d 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -706,8 +706,8 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) 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) @@ -722,10 +722,8 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) if (spisel_boot) { pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4); - if (!pinfo->immr_spi_cs) { - ret = -ENOMEM; - goto err; - } + if (!pinfo->immr_spi_cs) + return -ENOMEM; } #endif /* @@ -744,24 +742,15 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) ret = of_address_to_resource(np, 0, &mem); if (ret) - goto err; + return ret; irq = platform_get_irq(ofdev, 0); - if (irq < 0) { - ret = irq; - goto err; - } + 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: - return ret; + return PTR_ERR_OR_ZERO(master); } static int of_fsl_spi_remove(struct platform_device *ofdev) 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_CM |