Commit 1e1ab4ba authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents e83a0ed2 754a36a5
...@@ -12,6 +12,7 @@ Required properties: ...@@ -12,6 +12,7 @@ Required properties:
- clock-names: Should be "clk_apb5". - clock-names: Should be "clk_apb5".
- pinctrl-names : a pinctrl state named "default" must be defined. - pinctrl-names : a pinctrl state named "default" must be defined.
- pinctrl-0 : phandle referencing pin configuration of the device. - 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. - cs-gpios: Specifies the gpio pins to be used for chipselects.
See: Documentation/devicetree/bindings/spi/spi-bus.txt See: Documentation/devicetree/bindings/spi/spi-bus.txt
...@@ -19,16 +20,6 @@ Optional properties: ...@@ -19,16 +20,6 @@ Optional properties:
- clock-frequency : Input clock frequency to the PSPI block in Hz. - clock-frequency : Input clock frequency to the PSPI block in Hz.
Default is 25000000 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 { spi0: spi@f0200000 {
compatible = "nuvoton,npcm750-pspi"; compatible = "nuvoton,npcm750-pspi";
reg = <0xf0200000 0x1000>; reg = <0xf0200000 0x1000>;
...@@ -39,5 +30,6 @@ spi0: spi@f0200000 { ...@@ -39,5 +30,6 @@ spi0: spi@f0200000 {
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk NPCM7XX_CLK_APB5>; clocks = <&clk NPCM7XX_CLK_APB5>;
clock-names = "clk_apb5"; clock-names = "clk_apb5";
resets = <&rstc NPCM7XX_RESET_IPSRST2 NPCM7XX_RESET_PSPI1>
cs-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>; cs-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
}; };
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>;
};
};
Atmel SPI device Atmel SPI device
Required properties: 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 - reg: Address and length of the register set for the device
- interrupts: Should contain spi interrupt - interrupts: Should contain spi interrupt
- cs-gpios: chipselects (optional for SPI controller version >= 2 with the - cs-gpios: chipselects (optional for SPI controller version >= 2 with the
......
# 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>;
};
};
...
...@@ -7509,6 +7509,12 @@ S: Supported ...@@ -7509,6 +7509,12 @@ S: Supported
F: drivers/scsi/hisi_sas/ F: drivers/scsi/hisi_sas/
F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt 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 HISILICON QM AND ZIP Controller DRIVER
M: Zhou Wang <wangzhou1@hisilicon.com> M: Zhou Wang <wangzhou1@hisilicon.com>
L: linux-crypto@vger.kernel.org L: linux-crypto@vger.kernel.org
......
...@@ -281,6 +281,15 @@ config SPI_FSL_QUADSPI ...@@ -281,6 +281,15 @@ config SPI_FSL_QUADSPI
This controller does not support generic SPI messages. It only This controller does not support generic SPI messages. It only
supports the high-level SPI memory interface. 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 config SPI_NXP_FLEXSPI
tristate "NXP Flex SPI controller" tristate "NXP Flex SPI controller"
depends on ARCH_LAYERSCAPE || HAS_IOMEM depends on ARCH_LAYERSCAPE || HAS_IOMEM
......
...@@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_FSL_LPSPI) += spi-fsl-lpspi.o ...@@ -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_QUADSPI) += spi-fsl-qspi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
obj-$(CONFIG_SPI_GPIO) += spi-gpio.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_IMG_SPFI) += spi-img-spfi.o
obj-$(CONFIG_SPI_IMX) += spi-imx.o obj-$(CONFIG_SPI_IMX) += spi-imx.o
obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o
......
...@@ -514,26 +514,19 @@ static int atmel_spi_configure_dma(struct spi_master *master, ...@@ -514,26 +514,19 @@ static int atmel_spi_configure_dma(struct spi_master *master,
master->dma_tx = dma_request_chan(dev, "tx"); master->dma_tx = dma_request_chan(dev, "tx");
if (IS_ERR(master->dma_tx)) { if (IS_ERR(master->dma_tx)) {
err = PTR_ERR(master->dma_tx); err = PTR_ERR(master->dma_tx);
if (err == -EPROBE_DEFER) { if (err != -EPROBE_DEFER)
dev_warn(dev, "no DMA channel available at the moment\n"); dev_err(dev, "No TX DMA channel, DMA is disabled\n");
goto error_clear;
}
dev_err(dev,
"DMA TX channel not available, SPI unable to use DMA\n");
err = -EBUSY;
goto error_clear; goto error_clear;
} }
/* master->dma_rx = dma_request_chan(dev, "rx");
* No reason to check EPROBE_DEFER here since we have already requested if (IS_ERR(master->dma_rx)) {
* tx channel. If it fails here, it's for another reason. err = PTR_ERR(master->dma_rx);
*/ /*
master->dma_rx = dma_request_slave_channel(dev, "rx"); * No reason to check EPROBE_DEFER here since we have already
* requested tx channel.
if (!master->dma_rx) { */
dev_err(dev, dev_err(dev, "No RX DMA channel, DMA is disabled\n");
"DMA RX channel not available, SPI unable to use DMA\n");
err = -EBUSY;
goto error; goto error;
} }
...@@ -548,7 +541,7 @@ static int atmel_spi_configure_dma(struct spi_master *master, ...@@ -548,7 +541,7 @@ static int atmel_spi_configure_dma(struct spi_master *master,
return 0; return 0;
error: error:
if (master->dma_rx) if (!IS_ERR(master->dma_rx))
dma_release_channel(master->dma_rx); dma_release_channel(master->dma_rx);
if (!IS_ERR(master->dma_tx)) if (!IS_ERR(master->dma_tx))
dma_release_channel(master->dma_tx); dma_release_channel(master->dma_tx);
......
...@@ -1293,7 +1293,7 @@ int bcm_qspi_probe(struct platform_device *pdev, ...@@ -1293,7 +1293,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
name = qspi_irq_tab[val].irq_name; name = qspi_irq_tab[val].irq_name;
if (qspi_irq_tab[val].irq_source == SINGLE_L2) { if (qspi_irq_tab[val].irq_source == SINGLE_L2) {
/* get the l2 interrupts */ /* 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) { } else if (!num_ints && soc_intc) {
/* all mspi, bspi intrs muxed to one L1 intr */ /* all mspi, bspi intrs muxed to one L1 intr */
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
#define BCM2835_SPI_FIFO_SIZE 64 #define BCM2835_SPI_FIFO_SIZE 64
#define BCM2835_SPI_FIFO_SIZE_3_4 48 #define BCM2835_SPI_FIFO_SIZE_3_4 48
#define BCM2835_SPI_DMA_MIN_LENGTH 96 #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 \ #define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
| SPI_NO_CS | SPI_3WIRE) | SPI_NO_CS | SPI_3WIRE)
...@@ -888,8 +888,8 @@ static void bcm2835_dma_release(struct spi_controller *ctlr, ...@@ -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, static int bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev,
struct bcm2835_spi *bs) struct bcm2835_spi *bs)
{ {
struct dma_slave_config slave_config; struct dma_slave_config slave_config;
const __be32 *addr; const __be32 *addr;
...@@ -900,19 +900,24 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, ...@@ -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); addr = of_get_address(ctlr->dev.of_node, 0, NULL, NULL);
if (!addr) { if (!addr) {
dev_err(dev, "could not get DMA-register address - not using dma mode\n"); 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); dma_reg_base = be32_to_cpup(addr);
/* get tx/rx dma */ /* get tx/rx dma */
ctlr->dma_tx = dma_request_slave_channel(dev, "tx"); ctlr->dma_tx = dma_request_chan(dev, "tx");
if (!ctlr->dma_tx) { if (IS_ERR(ctlr->dma_tx)) {
dev_err(dev, "no tx-dma configuration found - not using dma mode\n"); 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; goto err;
} }
ctlr->dma_rx = dma_request_slave_channel(dev, "rx"); ctlr->dma_rx = dma_request_chan(dev, "rx");
if (!ctlr->dma_rx) { if (IS_ERR(ctlr->dma_rx)) {
dev_err(dev, "no rx-dma configuration found - not using dma mode\n"); 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; goto err_release;
} }
...@@ -997,7 +1002,7 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, ...@@ -997,7 +1002,7 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev,
/* all went well, so set can_dma */ /* all went well, so set can_dma */
ctlr->can_dma = bcm2835_spi_can_dma; ctlr->can_dma = bcm2835_spi_can_dma;
return; return 0;
err_config: err_config:
dev_err(dev, "issue configuring dma: %d - not using DMA mode\n", dev_err(dev, "issue configuring dma: %d - not using DMA mode\n",
...@@ -1005,7 +1010,14 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, ...@@ -1005,7 +1010,14 @@ static void bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev,
err_release: err_release:
bcm2835_dma_release(ctlr, bs); bcm2835_dma_release(ctlr, bs);
err: 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, static int bcm2835_spi_transfer_one_poll(struct spi_controller *ctlr,
...@@ -1305,7 +1317,10 @@ static int bcm2835_spi_probe(struct platform_device *pdev) ...@@ -1305,7 +1317,10 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
bs->clk = devm_clk_get(&pdev->dev, NULL); bs->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(bs->clk)) { if (IS_ERR(bs->clk)) {
err = PTR_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; goto out_controller_put;
} }
...@@ -1317,7 +1332,9 @@ static int bcm2835_spi_probe(struct platform_device *pdev) ...@@ -1317,7 +1332,9 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
clk_prepare_enable(bs->clk); 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 */ /* initialise the hardware with the default polarities */
bcm2835_wr(bs, BCM2835_SPI_CS, bcm2835_wr(bs, BCM2835_SPI_CS,
...@@ -1327,20 +1344,22 @@ static int bcm2835_spi_probe(struct platform_device *pdev) ...@@ -1327,20 +1344,22 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
dev_name(&pdev->dev), ctlr); dev_name(&pdev->dev), ctlr);
if (err) { if (err) {
dev_err(&pdev->dev, "could not request IRQ: %d\n", 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); err = devm_spi_register_controller(&pdev->dev, ctlr);
if (err) { if (err) {
dev_err(&pdev->dev, "could not register SPI controller: %d\n", dev_err(&pdev->dev, "could not register SPI controller: %d\n",
err); err);
goto out_clk_disable; goto out_dma_release;
} }
bcm2835_debugfs_create(bs, dev_name(&pdev->dev)); bcm2835_debugfs_create(bs, dev_name(&pdev->dev));
return 0; return 0;
out_dma_release:
bcm2835_dma_release(ctlr, bs);
out_clk_disable: out_clk_disable:
clk_disable_unprepare(bs->clk); clk_disable_unprepare(bs->clk);
out_controller_put: out_controller_put:
......
...@@ -329,8 +329,20 @@ static void spi_bitbang_set_cs(struct spi_device *spi, bool enable) ...@@ -329,8 +329,20 @@ static void spi_bitbang_set_cs(struct spi_device *spi, bool enable)
int spi_bitbang_init(struct spi_bitbang *bitbang) int spi_bitbang_init(struct spi_bitbang *bitbang)
{ {
struct spi_master *master = bitbang->master; 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; return -EINVAL;
mutex_init(&bitbang->lock); mutex_init(&bitbang->lock);
...@@ -344,7 +356,12 @@ int spi_bitbang_init(struct spi_bitbang *bitbang) ...@@ -344,7 +356,12 @@ int spi_bitbang_init(struct spi_bitbang *bitbang)
master->prepare_transfer_hardware = spi_bitbang_prepare_hardware; master->prepare_transfer_hardware = spi_bitbang_prepare_hardware;
master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware; master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware;
master->transfer_one = spi_bitbang_transfer_one; 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) { if (!bitbang->txrx_bufs) {
bitbang->use_dma = 0; bitbang->use_dma = 0;
......
...@@ -297,6 +297,9 @@ static int dw_spi_transfer_one(struct spi_controller *master, ...@@ -297,6 +297,9 @@ static int dw_spi_transfer_one(struct spi_controller *master,
dws->len = transfer->len; dws->len = transfer->len;
spin_unlock_irqrestore(&dws->buf_lock, flags); spin_unlock_irqrestore(&dws->buf_lock, flags);
/* Ensure dw->rx and dw->rx_end are visible */
smp_mb();
spi_enable_chip(dws, 0); spi_enable_chip(dws, 0);
/* Handle per transfer options for bpw and speed */ /* Handle per transfer options for bpw and speed */
...@@ -469,7 +472,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -469,7 +472,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
struct spi_controller *master; struct spi_controller *master;
int ret; int ret;
BUG_ON(dws == NULL); if (!dws)
return -EINVAL;
master = spi_alloc_master(dev, 0); master = spi_alloc_master(dev, 0);
if (!master) if (!master)
......
...@@ -396,17 +396,17 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr) ...@@ -396,17 +396,17 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
if (!dma) if (!dma)
return -ENOMEM; return -ENOMEM;
dma->chan_rx = dma_request_slave_channel(dev, "rx"); dma->chan_rx = dma_request_chan(dev, "rx");
if (!dma->chan_rx) { if (IS_ERR(dma->chan_rx)) {
dev_err(dev, "rx dma channel not available\n"); dev_err(dev, "rx dma channel not available\n");
ret = -ENODEV; ret = PTR_ERR(dma->chan_rx);
return ret; return ret;
} }
dma->chan_tx = dma_request_slave_channel(dev, "tx"); dma->chan_tx = dma_request_chan(dev, "tx");
if (!dma->chan_tx) { if (IS_ERR(dma->chan_tx)) {
dev_err(dev, "tx dma channel not available\n"); dev_err(dev, "tx dma channel not available\n");
ret = -ENODEV; ret = PTR_ERR(dma->chan_tx);
goto err_tx_channel; goto err_tx_channel;
} }
......
...@@ -469,9 +469,9 @@ static int fsl_lpspi_setup_transfer(struct spi_controller *controller, ...@@ -469,9 +469,9 @@ static int fsl_lpspi_setup_transfer(struct spi_controller *controller,
fsl_lpspi->watermark = fsl_lpspi->txfifosize; fsl_lpspi->watermark = fsl_lpspi->txfifosize;
if (fsl_lpspi_can_dma(controller, spi, t)) if (fsl_lpspi_can_dma(controller, spi, t))
fsl_lpspi->usedma = 1; fsl_lpspi->usedma = true;
else else
fsl_lpspi->usedma = 0; fsl_lpspi->usedma = false;
return fsl_lpspi_config(fsl_lpspi); return fsl_lpspi_config(fsl_lpspi);
} }
...@@ -862,6 +862,22 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ...@@ -862,6 +862,22 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
fsl_lpspi->dev = &pdev->dev; fsl_lpspi->dev = &pdev->dev;
fsl_lpspi->is_slave = is_slave; 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) { if (!fsl_lpspi->is_slave) {
for (i = 0; i < controller->num_chipselect; i++) { for (i = 0; i < controller->num_chipselect; i++) {
int cs_gpio = of_get_named_gpio(np, "cs-gpios", 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) ...@@ -885,16 +901,6 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
controller->prepare_message = fsl_lpspi_prepare_message; 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); init_completion(&fsl_lpspi->xfer_done);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -952,12 +958,6 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ...@@ -952,12 +958,6 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret); 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; return 0;
out_controller_put: out_controller_put:
......
...@@ -410,7 +410,7 @@ static bool fsl_qspi_supports_op(struct spi_mem *mem, ...@@ -410,7 +410,7 @@ static bool fsl_qspi_supports_op(struct spi_mem *mem,
op->data.nbytes > q->devtype_data->txfifo) op->data.nbytes > q->devtype_data->txfifo)
return false; return false;
return true; return spi_mem_default_supports_op(mem, op);
} }
static void fsl_qspi_prepare_lut(struct fsl_qspi *q, static void fsl_qspi_prepare_lut(struct fsl_qspi *q,
......
...@@ -706,8 +706,8 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) ...@@ -706,8 +706,8 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
struct device_node *np = ofdev->dev.of_node; struct device_node *np = ofdev->dev.of_node;
struct spi_master *master; struct spi_master *master;
struct resource mem; struct resource mem;
int irq = 0, type; int irq, type;
int ret = -ENOMEM; int ret;
ret = of_mpc8xxx_spi_probe(ofdev); ret = of_mpc8xxx_spi_probe(ofdev);
if (ret) if (ret)
...@@ -722,10 +722,8 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) ...@@ -722,10 +722,8 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
if (spisel_boot) { if (spisel_boot) {
pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4); pinfo->immr_spi_cs = ioremap(get_immrbase() + IMMR_SPI_CS_OFFSET, 4);
if (!pinfo->immr_spi_cs) { if (!pinfo->immr_spi_cs)
ret = -ENOMEM; return -ENOMEM;
goto err;
}
} }
#endif #endif
/* /*
...@@ -744,24 +742,15 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) ...@@ -744,24 +742,15 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
ret = of_address_to_resource(np, 0, &mem); ret = of_address_to_resource(np, 0, &mem);
if (ret) if (ret)
goto err; return ret;
irq = platform_get_irq(ofdev, 0); irq = platform_get_irq(ofdev, 0);
if (irq < 0) { if (irq < 0)
ret = irq; return irq;
goto err;
}
master = fsl_spi_probe(dev, &mem, irq); master = fsl_spi_probe(dev, &mem, irq);
if (IS_ERR(master)) {
ret = PTR_ERR(master);
goto err;
}
return 0;
err: return PTR_ERR_OR_ZERO(master);
return ret;
} }
static int of_fsl_spi_remove(struct platform_device *ofdev) static int of_fsl_spi_remove(struct platform_device *ofdev)
......
// 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");
...@@ -666,8 +666,22 @@ static int img_spfi_probe(struct platform_device *pdev) ...@@ -666,8 +666,22 @@ static int img_spfi_probe(struct platform_device *pdev)
master->unprepare_message = img_spfi_unprepare; master->unprepare_message = img_spfi_unprepare;
master->handle_err = img_spfi_handle_err; master->handle_err = img_spfi_handle_err;
spfi->tx_ch = dma_request_slave_channel(spfi->dev, "tx"); spfi->tx_ch = dma_request_chan(spfi->dev, "tx");
spfi->rx_ch = dma_request_slave_channel(spfi->dev, "rx"); 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 || !spfi->rx_ch) {
if (spfi->tx_ch) if (spfi->tx_ch)
dma_release_channel(spfi->tx_ch); dma_release_channel(spfi->tx_ch);
......
...@@ -1230,9 +1230,9 @@ static int spi_imx_setupxfer(struct spi_device *spi, ...@@ -1230,9 +1230,9 @@ static int spi_imx_setupxfer(struct spi_device *spi,
} }
if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t)) if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t))
spi_imx->usedma = 1; spi_imx->usedma = true;
else else
spi_imx->usedma = 0; spi_imx->usedma = false;
if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) { if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) {
spi_imx->rx = mx53_ecspi_rx_slave; spi_imx->rx = mx53_ecspi_rx_slave;
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/reset.h> #include <linux/reset.h>
#include <linux/gpio.h>
/* /*
* The Meson SPICC controller could support DMA based transfers, but is not * 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) ...@@ -467,35 +466,14 @@ static int meson_spicc_unprepare_transfer(struct spi_master *master)
static int meson_spicc_setup(struct spi_device *spi) static int meson_spicc_setup(struct spi_device *spi)
{ {
int ret = 0;
if (!spi->controller_state) if (!spi->controller_state)
spi->controller_state = spi_master_get_devdata(spi->master); 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) 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; spi->controller_state = NULL;
} }
...@@ -564,6 +542,7 @@ static int meson_spicc_probe(struct platform_device *pdev) ...@@ -564,6 +542,7 @@ static int meson_spicc_probe(struct platform_device *pdev)
master->prepare_message = meson_spicc_prepare_message; master->prepare_message = meson_spicc_prepare_message;
master->unprepare_transfer_hardware = meson_spicc_unprepare_transfer; master->unprepare_transfer_hardware = meson_spicc_unprepare_transfer;
master->transfer_one = meson_spicc_transfer_one; master->transfer_one = meson_spicc_transfer_one;
master->use_gpio_descriptors = true;
/* Setup max rate according to the Meson GX datasheet */ /* Setup max rate according to the Meson GX datasheet */
if ((rate >> 2) > SPICC_MAX_FREQ) if ((rate >> 2) > SPICC_MAX_FREQ)
......
...@@ -590,10 +590,10 @@ static int mxs_spi_probe(struct platform_device *pdev) ...@@ -590,10 +590,10 @@ static int mxs_spi_probe(struct platform_device *pdev)
if (ret) if (ret)
goto out_master_free; goto out_master_free;
ssp->dmach = dma_request_slave_channel(&pdev->dev, "rx-tx"); ssp->dmach = dma_request_chan(&pdev->dev, "rx-tx");
if (!ssp->dmach) { if (IS_ERR(ssp->dmach)) {
dev_err(ssp->dev, "Failed to request DMA\n"); dev_err(ssp->dev, "Failed to request DMA\n");
ret = -ENODEV; ret = PTR_ERR(ssp->dmach);
goto out_master_free; goto out_master_free;
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/reset.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -20,7 +21,7 @@ ...@@ -20,7 +21,7 @@
struct npcm_pspi { struct npcm_pspi {
struct completion xfer_done; struct completion xfer_done;
struct regmap *rst_regmap; struct reset_control *reset;
struct spi_master *master; struct spi_master *master;
unsigned int tx_bytes; unsigned int tx_bytes;
unsigned int rx_bytes; unsigned int rx_bytes;
...@@ -59,12 +60,6 @@ struct npcm_pspi { ...@@ -59,12 +60,6 @@ struct npcm_pspi {
#define NPCM_PSPI_MIN_CLK_DIVIDER 4 #define NPCM_PSPI_MIN_CLK_DIVIDER 4
#define NPCM_PSPI_DEFAULT_CLK 25000000 #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) static inline unsigned int bytes_per_word(unsigned int bits)
{ {
return bits <= 8 ? 1 : 2; return bits <= 8 ? 1 : 2;
...@@ -178,6 +173,13 @@ static void npcm_pspi_setup_transfer(struct spi_device *spi, ...@@ -178,6 +173,13 @@ static void npcm_pspi_setup_transfer(struct spi_device *spi,
priv->mode = spi->mode; 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) { if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) {
npcm_pspi_set_transfer_size(priv, t->bits_per_word); npcm_pspi_set_transfer_size(priv, t->bits_per_word);
priv->bits_per_word = 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, ...@@ -195,6 +197,7 @@ static void npcm_pspi_setup_transfer(struct spi_device *spi,
static void npcm_pspi_send(struct npcm_pspi *priv) static void npcm_pspi_send(struct npcm_pspi *priv)
{ {
int wsize; int wsize;
u16 val;
wsize = min(bytes_per_word(priv->bits_per_word), priv->tx_bytes); wsize = min(bytes_per_word(priv->bits_per_word), priv->tx_bytes);
priv->tx_bytes -= wsize; priv->tx_bytes -= wsize;
...@@ -204,17 +207,18 @@ static void npcm_pspi_send(struct npcm_pspi *priv) ...@@ -204,17 +207,18 @@ static void npcm_pspi_send(struct npcm_pspi *priv)
switch (wsize) { switch (wsize) {
case 1: case 1:
iowrite8(*priv->tx_buf, NPCM_PSPI_DATA + priv->base); val = *priv->tx_buf++;
iowrite8(val, NPCM_PSPI_DATA + priv->base);
break; break;
case 2: 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; break;
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
return; return;
} }
priv->tx_buf += wsize;
} }
static void npcm_pspi_recv(struct npcm_pspi *priv) static void npcm_pspi_recv(struct npcm_pspi *priv)
...@@ -230,18 +234,17 @@ static void npcm_pspi_recv(struct npcm_pspi *priv) ...@@ -230,18 +234,17 @@ static void npcm_pspi_recv(struct npcm_pspi *priv)
switch (rsize) { switch (rsize) {
case 1: case 1:
val = ioread8(priv->base + NPCM_PSPI_DATA); *priv->rx_buf++ = ioread8(priv->base + NPCM_PSPI_DATA);
break; break;
case 2: case 2:
val = ioread16(priv->base + NPCM_PSPI_DATA); val = ioread16(priv->base + NPCM_PSPI_DATA);
*priv->rx_buf++ = (val >> 8);
*priv->rx_buf++ = val & 0xff;
break; break;
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
return; return;
} }
*priv->rx_buf = val;
priv->rx_buf += rsize;
} }
static int npcm_pspi_transfer_one(struct spi_master *master, static int npcm_pspi_transfer_one(struct spi_master *master,
...@@ -285,9 +288,9 @@ static int npcm_pspi_unprepare_transfer_hardware(struct spi_master *master) ...@@ -285,9 +288,9 @@ static int npcm_pspi_unprepare_transfer_hardware(struct spi_master *master)
static void npcm_pspi_reset_hw(struct npcm_pspi *priv) static void npcm_pspi_reset_hw(struct npcm_pspi *priv)
{ {
regmap_write(priv->rst_regmap, NPCM7XX_IPSRST2_OFFSET, reset_control_assert(priv->reset);
NPCM7XX_PSPI1_RESET << priv->id); udelay(5);
regmap_write(priv->rst_regmap, NPCM7XX_IPSRST2_OFFSET, 0x0); reset_control_deassert(priv->reset);
} }
static irqreturn_t npcm_pspi_handler(int irq, void *dev_id) static irqreturn_t npcm_pspi_handler(int irq, void *dev_id)
...@@ -351,10 +354,6 @@ static int npcm_pspi_probe(struct platform_device *pdev) ...@@ -351,10 +354,6 @@ static int npcm_pspi_probe(struct platform_device *pdev)
if (num_cs < 0) if (num_cs < 0)
return num_cs; 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)); master = spi_alloc_master(&pdev->dev, sizeof(*priv));
if (!master) if (!master)
return -ENOMEM; return -ENOMEM;
...@@ -364,7 +363,6 @@ static int npcm_pspi_probe(struct platform_device *pdev) ...@@ -364,7 +363,6 @@ static int npcm_pspi_probe(struct platform_device *pdev)
priv = spi_master_get_devdata(master); priv = spi_master_get_devdata(master);
priv->master = master; priv->master = master;
priv->is_save_param = false; priv->is_save_param = false;
priv->id = pdev->id;
priv->base = devm_platform_ioremap_resource(pdev, 0); priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base)) { if (IS_ERR(priv->base)) {
...@@ -389,11 +387,10 @@ static int npcm_pspi_probe(struct platform_device *pdev) ...@@ -389,11 +387,10 @@ static int npcm_pspi_probe(struct platform_device *pdev)
goto out_disable_clk; goto out_disable_clk;
} }
priv->rst_regmap = priv->reset = devm_reset_control_get(&pdev->dev, NULL);
syscon_regmap_lookup_by_compatible("nuvoton,npcm750-rst"); if (IS_ERR(priv->reset)) {
if (IS_ERR(priv->rst_regmap)) { ret = PTR_ERR(priv->reset);
dev_err(&pdev->dev, "failed to find nuvoton,npcm750-rst\n"); goto out_disable_clk;
return PTR_ERR(priv->rst_regmap);
} }
/* reset SPI-HW block */ /* reset SPI-HW block */
...@@ -414,7 +411,7 @@ static int npcm_pspi_probe(struct platform_device *pdev) ...@@ -414,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->min_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MAX_CLK_DIVIDER);
master->mode_bits = SPI_CPHA | SPI_CPOL; master->mode_bits = SPI_CPHA | SPI_CPOL;
master->dev.of_node = pdev->dev.of_node; 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->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
master->transfer_one = npcm_pspi_transfer_one; master->transfer_one = npcm_pspi_transfer_one;
master->prepare_transfer_hardware = master->prepare_transfer_hardware =
...@@ -447,7 +444,7 @@ static int npcm_pspi_probe(struct platform_device *pdev) ...@@ -447,7 +444,7 @@ static int npcm_pspi_probe(struct platform_device *pdev)
if (ret) if (ret)
goto out_disable_clk; 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; return 0;
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include <linux/spi/spi_bitbang.h> #include <linux/spi/spi_bitbang.h>
#include <linux/spi/spi_oc_tiny.h> #include <linux/spi/spi_oc_tiny.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of.h> #include <linux/of.h>
#define DRV_NAME "spi_oc_tiny" #define DRV_NAME "spi_oc_tiny"
...@@ -50,8 +49,6 @@ struct tiny_spi { ...@@ -50,8 +49,6 @@ struct tiny_spi {
unsigned int txc, rxc; unsigned int txc, rxc;
const u8 *txp; const u8 *txp;
u8 *rxp; u8 *rxp;
int gpio_cs_count;
int *gpio_cs;
}; };
static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev) 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) ...@@ -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; 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, static int tiny_spi_setup_transfer(struct spi_device *spi,
struct spi_transfer *t) struct spi_transfer *t)
{ {
...@@ -203,24 +190,10 @@ static int tiny_spi_of_probe(struct platform_device *pdev) ...@@ -203,24 +190,10 @@ static int tiny_spi_of_probe(struct platform_device *pdev)
{ {
struct tiny_spi *hw = platform_get_drvdata(pdev); struct tiny_spi *hw = platform_get_drvdata(pdev);
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
unsigned int i;
u32 val; u32 val;
if (!np) if (!np)
return 0; 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; hw->bitbang.master->dev.of_node = pdev->dev.of_node;
if (!of_property_read_u32(np, "clock-frequency", &val)) if (!of_property_read_u32(np, "clock-frequency", &val))
hw->freq = val; hw->freq = val;
...@@ -240,7 +213,6 @@ static int tiny_spi_probe(struct platform_device *pdev) ...@@ -240,7 +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_platform_data *platp = dev_get_platdata(&pdev->dev);
struct tiny_spi *hw; struct tiny_spi *hw;
struct spi_master *master; struct spi_master *master;
unsigned int i;
int err = -ENODEV; int err = -ENODEV;
master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi)); master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi));
...@@ -249,9 +221,9 @@ static int tiny_spi_probe(struct platform_device *pdev) ...@@ -249,9 +221,9 @@ static int tiny_spi_probe(struct platform_device *pdev)
/* setup the master state. */ /* setup the master state. */
master->bus_num = pdev->id; master->bus_num = pdev->id;
master->num_chipselect = 255;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
master->setup = tiny_spi_setup; master->setup = tiny_spi_setup;
master->use_gpio_descriptors = true;
hw = spi_master_get_devdata(master); hw = spi_master_get_devdata(master);
platform_set_drvdata(pdev, hw); platform_set_drvdata(pdev, hw);
...@@ -259,7 +231,6 @@ static int tiny_spi_probe(struct platform_device *pdev) ...@@ -259,7 +231,6 @@ static int tiny_spi_probe(struct platform_device *pdev)
/* setup the state for the bitbang driver */ /* setup the state for the bitbang driver */
hw->bitbang.master = master; hw->bitbang.master = master;
hw->bitbang.setup_transfer = tiny_spi_setup_transfer; hw->bitbang.setup_transfer = tiny_spi_setup_transfer;
hw->bitbang.chipselect = tiny_spi_chipselect;
hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs; hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs;
/* find and map our resources */ /* find and map our resources */
...@@ -279,12 +250,6 @@ static int tiny_spi_probe(struct platform_device *pdev) ...@@ -279,12 +250,6 @@ static int tiny_spi_probe(struct platform_device *pdev)
} }
/* find platform data */ /* find platform data */
if (platp) { 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->freq = platp->freq;
hw->baudwidth = platp->baudwidth; hw->baudwidth = platp->baudwidth;
} else { } else {
...@@ -292,13 +257,6 @@ static int tiny_spi_probe(struct platform_device *pdev) ...@@ -292,13 +257,6 @@ static int tiny_spi_probe(struct platform_device *pdev)
if (err) if (err)
goto exit; 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 */ /* register our spi controller */
err = spi_bitbang_start(&hw->bitbang); err = spi_bitbang_start(&hw->bitbang);
...@@ -308,9 +266,6 @@ static int tiny_spi_probe(struct platform_device *pdev) ...@@ -308,9 +266,6 @@ static int tiny_spi_probe(struct platform_device *pdev)
return 0; return 0;
exit_gpio:
while (i-- > 0)
gpio_free(hw->gpio_cs[i]);
exit: exit:
spi_master_put(master); spi_master_put(master);
return err; return err;
...@@ -320,11 +275,8 @@ static int tiny_spi_remove(struct platform_device *pdev) ...@@ -320,11 +275,8 @@ static int tiny_spi_remove(struct platform_device *pdev)
{ {
struct tiny_spi *hw = platform_get_drvdata(pdev); struct tiny_spi *hw = platform_get_drvdata(pdev);
struct spi_master *master = hw->bitbang.master; struct spi_master *master = hw->bitbang.master;
unsigned int i;
spi_bitbang_stop(&hw->bitbang); spi_bitbang_stop(&hw->bitbang);
for (i = 0; i < hw->gpio_cs_count; i++)
gpio_free(hw->gpio_cs[i]);
spi_master_put(master); spi_master_put(master);
return 0; return 0;
} }
......
...@@ -461,6 +461,16 @@ int pxa2xx_spi_flush(struct driver_data *drv_data) ...@@ -461,6 +461,16 @@ int pxa2xx_spi_flush(struct driver_data *drv_data)
return limit; 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) static int null_writer(struct driver_data *drv_data)
{ {
u8 n_bytes = drv_data->n_bytes; u8 n_bytes = drv_data->n_bytes;
...@@ -587,8 +597,7 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg) ...@@ -587,8 +597,7 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg)
if (!pxa25x_ssp_comp(drv_data)) if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, 0); pxa2xx_spi_write(drv_data, SSTO, 0);
pxa2xx_spi_flush(drv_data); pxa2xx_spi_flush(drv_data);
pxa2xx_spi_write(drv_data, SSCR0, pxa2xx_spi_off(drv_data);
pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE);
dev_err(&drv_data->pdev->dev, "%s\n", msg); dev_err(&drv_data->pdev->dev, "%s\n", msg);
...@@ -686,8 +695,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) ...@@ -686,8 +695,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
static void handle_bad_msg(struct driver_data *drv_data) static void handle_bad_msg(struct driver_data *drv_data)
{ {
pxa2xx_spi_write(drv_data, SSCR0, pxa2xx_spi_off(drv_data);
pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE);
pxa2xx_spi_write(drv_data, SSCR1, pxa2xx_spi_write(drv_data, SSCR1,
pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1); pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1);
if (!pxa25x_ssp_comp(drv_data)) if (!pxa25x_ssp_comp(drv_data))
...@@ -1062,7 +1070,8 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller, ...@@ -1062,7 +1070,8 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller,
|| (pxa2xx_spi_read(drv_data, SSCR1) & change_mask) || (pxa2xx_spi_read(drv_data, SSCR1) & change_mask)
!= (cr1 & change_mask)) { != (cr1 & change_mask)) {
/* stop the SSP, and update the other bits */ /* 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)) if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, chip->timeout); pxa2xx_spi_write(drv_data, SSTO, chip->timeout);
/* first set CR1 without interrupt and service enables */ /* first set CR1 without interrupt and service enables */
...@@ -1118,8 +1127,7 @@ static int pxa2xx_spi_slave_abort(struct spi_controller *controller) ...@@ -1118,8 +1127,7 @@ static int pxa2xx_spi_slave_abort(struct spi_controller *controller)
if (!pxa25x_ssp_comp(drv_data)) if (!pxa25x_ssp_comp(drv_data))
pxa2xx_spi_write(drv_data, SSTO, 0); pxa2xx_spi_write(drv_data, SSTO, 0);
pxa2xx_spi_flush(drv_data); pxa2xx_spi_flush(drv_data);
pxa2xx_spi_write(drv_data, SSCR0, pxa2xx_spi_off(drv_data);
pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE);
dev_dbg(&drv_data->pdev->dev, "transfer aborted\n"); dev_dbg(&drv_data->pdev->dev, "transfer aborted\n");
...@@ -1135,8 +1143,7 @@ static void pxa2xx_spi_handle_err(struct spi_controller *controller, ...@@ -1135,8 +1143,7 @@ static void pxa2xx_spi_handle_err(struct spi_controller *controller,
struct driver_data *drv_data = spi_controller_get_devdata(controller); struct driver_data *drv_data = spi_controller_get_devdata(controller);
/* Disable the SSP */ /* Disable the SSP */
pxa2xx_spi_write(drv_data, SSCR0, pxa2xx_spi_off(drv_data);
pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE);
/* Clear and disable interrupts and service requests */ /* Clear and disable interrupts and service requests */
write_SSSR_CS(drv_data, drv_data->clear_sr); write_SSSR_CS(drv_data, drv_data->clear_sr);
pxa2xx_spi_write(drv_data, SSCR1, pxa2xx_spi_write(drv_data, SSCR1,
...@@ -1161,8 +1168,7 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_controller *controller) ...@@ -1161,8 +1168,7 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_controller *controller)
struct driver_data *drv_data = spi_controller_get_devdata(controller); struct driver_data *drv_data = spi_controller_get_devdata(controller);
/* Disable the SSP now */ /* Disable the SSP now */
pxa2xx_spi_write(drv_data, SSCR0, pxa2xx_spi_off(drv_data);
pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE);
return 0; return 0;
} }
...@@ -1423,6 +1429,9 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { ...@@ -1423,6 +1429,9 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
/* KBL-H */ /* KBL-H */
{ PCI_VDEVICE(INTEL, 0xa2a9), LPSS_SPT_SSP }, { PCI_VDEVICE(INTEL, 0xa2a9), LPSS_SPT_SSP },
{ PCI_VDEVICE(INTEL, 0xa2aa), 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 */ /* BXT A-Step */
{ PCI_VDEVICE(INTEL, 0x0ac2), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x0ac2), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x0ac4), LPSS_BXT_SSP }, { PCI_VDEVICE(INTEL, 0x0ac4), LPSS_BXT_SSP },
......
...@@ -137,7 +137,7 @@ enum qspi_clocks { ...@@ -137,7 +137,7 @@ enum qspi_clocks {
struct qcom_qspi { struct qcom_qspi {
void __iomem *base; void __iomem *base;
struct device *dev; struct device *dev;
struct clk_bulk_data clks[QSPI_NUM_CLKS]; struct clk_bulk_data *clks;
struct qspi_xfer xfer; struct qspi_xfer xfer;
/* Lock to protect xfer and IRQ accessed registers */ /* Lock to protect xfer and IRQ accessed registers */
spinlock_t lock; spinlock_t lock;
...@@ -445,6 +445,13 @@ static int qcom_qspi_probe(struct platform_device *pdev) ...@@ -445,6 +445,13 @@ static int qcom_qspi_probe(struct platform_device *pdev)
goto exit_probe_master_put; 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_CORE].id = "core";
ctrl->clks[QSPI_CLK_IFACE].id = "iface"; ctrl->clks[QSPI_CLK_IFACE].id = "iface";
ret = devm_clk_bulk_get(dev, QSPI_NUM_CLKS, ctrl->clks); ret = devm_clk_bulk_get(dev, QSPI_NUM_CLKS, ctrl->clks);
......
...@@ -159,7 +159,7 @@ ...@@ -159,7 +159,7 @@
#define SPCMD_SPIMOD_DUAL SPCMD_SPIMOD0 #define SPCMD_SPIMOD_DUAL SPCMD_SPIMOD0
#define SPCMD_SPIMOD_QUAD SPCMD_SPIMOD1 #define SPCMD_SPIMOD_QUAD SPCMD_SPIMOD1
#define SPCMD_SPRW 0x0010 /* SPI Read/Write Access (Dual/Quad) */ #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_BRDV_MASK 0x000c /* Bit Rate Division Setting */
#define SPCMD_CPOL 0x0002 /* Clock Polarity Setting */ #define SPCMD_CPOL 0x0002 /* Clock Polarity Setting */
#define SPCMD_CPHA 0x0001 /* Clock Phase Setting */ #define SPCMD_CPHA 0x0001 /* Clock Phase Setting */
...@@ -242,6 +242,7 @@ struct spi_ops { ...@@ -242,6 +242,7 @@ struct spi_ops {
u16 mode_bits; u16 mode_bits;
u16 flags; u16 flags;
u16 fifo_size; u16 fifo_size;
u8 num_hw_ss;
}; };
/* /*
...@@ -426,8 +427,6 @@ static int qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len) ...@@ -426,8 +427,6 @@ static int qspi_set_receive_trigger(struct rspi_data *rspi, unsigned int len)
return n; 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) static void rspi_enable_irq(const struct rspi_data *rspi, u8 enable)
{ {
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR); rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
...@@ -620,9 +619,8 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx, ...@@ -620,9 +619,8 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
dmaengine_terminate_all(rspi->ctlr->dma_rx); dmaengine_terminate_all(rspi->ctlr->dma_rx);
no_dma_rx: no_dma_rx:
if (ret == -EAGAIN) { if (ret == -EAGAIN) {
pr_warn_once("%s %s: DMA not available, falling back to PIO\n", dev_warn_once(&rspi->ctlr->dev,
dev_driver_string(&rspi->ctlr->dev), "DMA not available, falling back to PIO\n");
dev_name(&rspi->ctlr->dev));
} }
return ret; return ret;
} }
...@@ -936,12 +934,16 @@ static int rspi_prepare_message(struct spi_controller *ctlr, ...@@ -936,12 +934,16 @@ static int rspi_prepare_message(struct spi_controller *ctlr,
if (spi->mode & SPI_CPHA) if (spi->mode & SPI_CPHA)
rspi->spcmd |= SPCMD_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 */ /* CMOS output mode and MOSI signal from previous transfer */
rspi->sppcr = 0; rspi->sppcr = 0;
if (spi->mode & SPI_LOOP) if (spi->mode & SPI_LOOP)
rspi->sppcr |= SPPCR_SPLP; rspi->sppcr |= SPPCR_SPLP;
set_config_register(rspi, 8); rspi->ops->set_config_register(rspi, 8);
if (msg->spi->mode & if (msg->spi->mode &
(SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) { (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) {
...@@ -1123,6 +1125,7 @@ static const struct spi_ops rspi_ops = { ...@@ -1123,6 +1125,7 @@ static const struct spi_ops rspi_ops = {
.mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP, .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP,
.flags = SPI_CONTROLLER_MUST_TX, .flags = SPI_CONTROLLER_MUST_TX,
.fifo_size = 8, .fifo_size = 8,
.num_hw_ss = 2,
}; };
static const struct spi_ops rspi_rz_ops = { static const struct spi_ops rspi_rz_ops = {
...@@ -1131,6 +1134,7 @@ 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, .mode_bits = SPI_CPHA | SPI_CPOL | SPI_LOOP,
.flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX,
.fifo_size = 8, /* 8 for TX, 32 for RX */ .fifo_size = 8, /* 8 for TX, 32 for RX */
.num_hw_ss = 1,
}; };
static const struct spi_ops qspi_ops = { static const struct spi_ops qspi_ops = {
...@@ -1141,6 +1145,7 @@ static const struct spi_ops qspi_ops = { ...@@ -1141,6 +1145,7 @@ static const struct spi_ops qspi_ops = {
SPI_RX_DUAL | SPI_RX_QUAD, SPI_RX_DUAL | SPI_RX_QUAD,
.flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX, .flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX,
.fifo_size = 32, .fifo_size = 32,
.num_hw_ss = 1,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -1256,6 +1261,8 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -1256,6 +1261,8 @@ static int rspi_probe(struct platform_device *pdev)
ctlr->mode_bits = ops->mode_bits; ctlr->mode_bits = ops->mode_bits;
ctlr->flags = ops->flags; ctlr->flags = ops->flags;
ctlr->dev.of_node = pdev->dev.of_node; 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_optional(pdev, "rx"); ret = platform_get_irq_byname_optional(pdev, "rx");
if (ret < 0) { if (ret < 0) {
...@@ -1314,8 +1321,6 @@ static int rspi_probe(struct platform_device *pdev) ...@@ -1314,8 +1321,6 @@ static int rspi_probe(struct platform_device *pdev)
static const struct platform_device_id spi_driver_ids[] = { static const struct platform_device_id spi_driver_ids[] = {
{ "rspi", (kernel_ulong_t)&rspi_ops }, { "rspi", (kernel_ulong_t)&rspi_ops },
{ "rspi-rz", (kernel_ulong_t)&rspi_rz_ops },
{ "qspi", (kernel_ulong_t)&qspi_ops },
{}, {},
}; };
......
This diff is collapsed.
...@@ -1126,16 +1126,16 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) ...@@ -1126,16 +1126,16 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
sspi->bitbang.master->dev.of_node = pdev->dev.of_node; sspi->bitbang.master->dev.of_node = pdev->dev.of_node;
/* request DMA channels */ /* request DMA channels */
sspi->rx_chan = dma_request_slave_channel(&pdev->dev, "rx"); sspi->rx_chan = dma_request_chan(&pdev->dev, "rx");
if (!sspi->rx_chan) { if (IS_ERR(sspi->rx_chan)) {
dev_err(&pdev->dev, "can not allocate rx dma channel\n"); dev_err(&pdev->dev, "can not allocate rx dma channel\n");
ret = -ENODEV; ret = PTR_ERR(sspi->rx_chan);
goto free_master; goto free_master;
} }
sspi->tx_chan = dma_request_slave_channel(&pdev->dev, "tx"); sspi->tx_chan = dma_request_chan(&pdev->dev, "tx");
if (!sspi->tx_chan) { if (IS_ERR(sspi->tx_chan)) {
dev_err(&pdev->dev, "can not allocate tx dma channel\n"); dev_err(&pdev->dev, "can not allocate tx dma channel\n");
ret = -ENODEV; ret = PTR_ERR(sspi->tx_chan);
goto free_rx_dma; goto free_rx_dma;
} }
......
...@@ -470,10 +470,11 @@ static int stm32_qspi_setup(struct spi_device *spi) ...@@ -470,10 +470,11 @@ static int stm32_qspi_setup(struct spi_device *spi)
return 0; 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 dma_slave_config dma_cfg;
struct device *dev = qspi->dev; struct device *dev = qspi->dev;
int ret = 0;
memset(&dma_cfg, 0, sizeof(dma_cfg)); memset(&dma_cfg, 0, sizeof(dma_cfg));
...@@ -484,8 +485,13 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi) ...@@ -484,8 +485,13 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi)
dma_cfg.src_maxburst = 4; dma_cfg.src_maxburst = 4;
dma_cfg.dst_maxburst = 4; dma_cfg.dst_maxburst = 4;
qspi->dma_chrx = dma_request_slave_channel(dev, "rx"); qspi->dma_chrx = dma_request_chan(dev, "rx");
if (qspi->dma_chrx) { 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)) { if (dmaengine_slave_config(qspi->dma_chrx, &dma_cfg)) {
dev_err(dev, "dma rx config failed\n"); dev_err(dev, "dma rx config failed\n");
dma_release_channel(qspi->dma_chrx); dma_release_channel(qspi->dma_chrx);
...@@ -493,8 +499,11 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi) ...@@ -493,8 +499,11 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi)
} }
} }
qspi->dma_chtx = dma_request_slave_channel(dev, "tx"); qspi->dma_chtx = dma_request_chan(dev, "tx");
if (qspi->dma_chtx) { 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)) { if (dmaengine_slave_config(qspi->dma_chtx, &dma_cfg)) {
dev_err(dev, "dma tx config failed\n"); dev_err(dev, "dma tx config failed\n");
dma_release_channel(qspi->dma_chtx); dma_release_channel(qspi->dma_chtx);
...@@ -502,7 +511,13 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi) ...@@ -502,7 +511,13 @@ static void stm32_qspi_dma_setup(struct stm32_qspi *qspi)
} }
} }
out:
init_completion(&qspi->dma_completion); init_completion(&qspi->dma_completion);
if (ret != -EPROBE_DEFER)
ret = 0;
return ret;
} }
static void stm32_qspi_dma_free(struct stm32_qspi *qspi) static void stm32_qspi_dma_free(struct stm32_qspi *qspi)
...@@ -608,7 +623,10 @@ static int stm32_qspi_probe(struct platform_device *pdev) ...@@ -608,7 +623,10 @@ static int stm32_qspi_probe(struct platform_device *pdev)
qspi->dev = dev; qspi->dev = dev;
platform_set_drvdata(pdev, qspi); platform_set_drvdata(pdev, qspi);
stm32_qspi_dma_setup(qspi); ret = stm32_qspi_dma_setup(qspi);
if (ret)
goto err;
mutex_init(&qspi->lock); mutex_init(&qspi->lock);
ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/gpio.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -973,29 +972,6 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) ...@@ -973,29 +972,6 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/**
* 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 * stm32_spi_prepare_msg - set up the controller to transfer a single message
*/ */
...@@ -1810,7 +1786,7 @@ static int stm32_spi_probe(struct platform_device *pdev) ...@@ -1810,7 +1786,7 @@ static int stm32_spi_probe(struct platform_device *pdev)
struct spi_master *master; struct spi_master *master;
struct stm32_spi *spi; struct stm32_spi *spi;
struct resource *res; struct resource *res;
int i, ret; int ret;
master = spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi)); master = spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi));
if (!master) { if (!master) {
...@@ -1898,22 +1874,34 @@ static int stm32_spi_probe(struct platform_device *pdev) ...@@ -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->bits_per_word_mask = spi->cfg->get_bpw_mask(spi);
master->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min; 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->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->prepare_message = stm32_spi_prepare_msg;
master->transfer_one = stm32_spi_transfer_one; master->transfer_one = stm32_spi_transfer_one;
master->unprepare_message = stm32_spi_unprepare_msg; master->unprepare_message = stm32_spi_unprepare_msg;
spi->dma_tx = dma_request_slave_channel(spi->dev, "tx"); spi->dma_tx = dma_request_chan(spi->dev, "tx");
if (!spi->dma_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"); dev_warn(&pdev->dev, "failed to request tx dma channel\n");
else } else {
master->dma_tx = spi->dma_tx; 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"); dev_warn(&pdev->dev, "failed to request rx dma channel\n");
else } else {
master->dma_rx = spi->dma_rx; master->dma_rx = spi->dma_rx;
}
if (spi->dma_tx || spi->dma_rx) if (spi->dma_tx || spi->dma_rx)
master->can_dma = stm32_spi_can_dma; master->can_dma = stm32_spi_can_dma;
...@@ -1925,43 +1913,26 @@ static int stm32_spi_probe(struct platform_device *pdev) ...@@ -1925,43 +1913,26 @@ static int stm32_spi_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(&pdev->dev, "spi master registration failed: %d\n", dev_err(&pdev->dev, "spi master registration failed: %d\n",
ret); 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"); dev_err(&pdev->dev, "no CS gpios available\n");
ret = -EINVAL; ret = -EINVAL;
goto err_dma_release; goto err_pm_disable;
}
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;
}
} }
dev_info(&pdev->dev, "driver initialized\n"); dev_info(&pdev->dev, "driver initialized\n");
return 0; return 0;
err_pm_disable:
pm_runtime_disable(&pdev->dev);
err_dma_release: err_dma_release:
if (spi->dma_tx) if (spi->dma_tx)
dma_release_channel(spi->dma_tx); dma_release_channel(spi->dma_tx);
if (spi->dma_rx) if (spi->dma_rx)
dma_release_channel(spi->dma_rx); dma_release_channel(spi->dma_rx);
pm_runtime_disable(&pdev->dev);
err_clk_disable: err_clk_disable:
clk_disable_unprepare(spi->clk); clk_disable_unprepare(spi->clk);
err_master_put: err_master_put:
......
...@@ -269,10 +269,10 @@ static unsigned tegra_spi_calculate_curr_xfer_param( ...@@ -269,10 +269,10 @@ static unsigned tegra_spi_calculate_curr_xfer_param(
if ((bits_per_word == 8 || bits_per_word == 16 || if ((bits_per_word == 8 || bits_per_word == 16 ||
bits_per_word == 32) && t->len > 3) { bits_per_word == 32) && t->len > 3) {
tspi->is_packed = 1; tspi->is_packed = true;
tspi->words_per_32bit = 32/bits_per_word; tspi->words_per_32bit = 32/bits_per_word;
} else { } else {
tspi->is_packed = 0; tspi->is_packed = false;
tspi->words_per_32bit = 1; tspi->words_per_32bit = 1;
} }
......
...@@ -80,8 +80,6 @@ struct ti_qspi { ...@@ -80,8 +80,6 @@ struct ti_qspi {
#define QSPI_COMPLETION_TIMEOUT msecs_to_jiffies(2000) #define QSPI_COMPLETION_TIMEOUT msecs_to_jiffies(2000)
#define QSPI_FCLK 192000000
/* Clock Control */ /* Clock Control */
#define QSPI_CLK_EN (1 << 31) #define QSPI_CLK_EN (1 << 31)
#define QSPI_CLK_DIV_MAX 0xffff #define QSPI_CLK_DIV_MAX 0xffff
...@@ -316,6 +314,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, ...@@ -316,6 +314,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
{ {
int wlen; int wlen;
unsigned int cmd; unsigned int cmd;
u32 rx;
u8 rxlen, rx_wlen;
u8 *rxbuf; u8 *rxbuf;
rxbuf = t->rx_buf; rxbuf = t->rx_buf;
...@@ -332,20 +332,67 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, ...@@ -332,20 +332,67 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t,
break; break;
} }
wlen = t->bits_per_word >> 3; /* in bytes */ wlen = t->bits_per_word >> 3; /* in bytes */
rx_wlen = wlen;
while (count) { while (count) {
dev_dbg(qspi->dev, "rx cmd %08x dc %08x\n", cmd, qspi->dc); dev_dbg(qspi->dev, "rx cmd %08x dc %08x\n", cmd, qspi->dc);
if (qspi_is_busy(qspi)) if (qspi_is_busy(qspi))
return -EBUSY; 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); ti_qspi_write(qspi, cmd, QSPI_SPI_CMD_REG);
if (ti_qspi_poll_wc(qspi)) { if (ti_qspi_poll_wc(qspi)) {
dev_err(qspi->dev, "read timed out\n"); dev_err(qspi->dev, "read timed out\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
switch (wlen) { switch (wlen) {
case 1: 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; break;
case 2: case 2:
*((u16 *)rxbuf) = readw(qspi->base + QSPI_SPI_DATA_REG); *((u16 *)rxbuf) = readw(qspi->base + QSPI_SPI_DATA_REG);
...@@ -354,8 +401,8 @@ static int qspi_read_msg(struct ti_qspi *qspi, struct spi_transfer *t, ...@@ -354,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); *((u32 *)rxbuf) = readl(qspi->base + QSPI_SPI_DATA_REG);
break; break;
} }
rxbuf += wlen; rxbuf += rxlen;
count -= wlen; count -= rxlen;
} }
return 0; return 0;
...@@ -527,6 +574,35 @@ static void ti_qspi_setup_mmap_read(struct spi_device *spi, u8 opcode, ...@@ -527,6 +574,35 @@ static void ti_qspi_setup_mmap_read(struct spi_device *spi, u8 opcode,
QSPI_SPI_SETUP_REG(spi->chip_select)); 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, static int ti_qspi_exec_mem_op(struct spi_mem *mem,
const struct spi_mem_op *op) const struct spi_mem_op *op)
{ {
...@@ -577,6 +653,7 @@ static int ti_qspi_exec_mem_op(struct spi_mem *mem, ...@@ -577,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 = { static const struct spi_controller_mem_ops ti_qspi_mem_ops = {
.exec_op = ti_qspi_exec_mem_op, .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, static int ti_qspi_start_transfer_one(struct spi_master *master,
......
...@@ -863,7 +863,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw) ...@@ -863,7 +863,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
/* Set Tx DMA */ /* Set Tx DMA */
param = &dma->param_tx; param = &dma->param_tx;
param->dma_dev = &dma_dev->dev; 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->tx_reg = data->io_base_addr + PCH_SPDWR;
param->width = width; param->width = width;
chan = dma_request_channel(mask, pch_spi_filter, param); 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) ...@@ -878,7 +878,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)
/* Set Rx DMA */ /* Set Rx DMA */
param = &dma->param_rx; param = &dma->param_rx;
param->dma_dev = &dma_dev->dev; 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->rx_reg = data->io_base_addr + PCH_SPDRR;
param->width = width; param->width = width;
chan = dma_request_channel(mask, pch_spi_filter, param); chan = dma_request_channel(mask, pch_spi_filter, param);
......
This diff is collapsed.
...@@ -1674,6 +1674,13 @@ void spi_finalize_current_message(struct spi_controller *ctlr) ...@@ -1674,6 +1674,13 @@ void spi_finalize_current_message(struct spi_controller *ctlr)
} }
} }
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); spi_unmap_msg(ctlr, mesg);
if (ctlr->cur_msg_prepared && ctlr->unprepare_message) { if (ctlr->cur_msg_prepared && ctlr->unprepare_message) {
...@@ -2451,6 +2458,8 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr) ...@@ -2451,6 +2458,8 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr)
int nb, i; int nb, i;
struct gpio_desc **cs; struct gpio_desc **cs;
struct device *dev = &ctlr->dev; struct device *dev = &ctlr->dev;
unsigned long native_cs_mask = 0;
unsigned int num_cs_gpios = 0;
nb = gpiod_count(dev, "cs"); nb = gpiod_count(dev, "cs");
ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect); ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect);
...@@ -2492,7 +2501,22 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr) ...@@ -2492,7 +2501,22 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr)
if (!gpioname) if (!gpioname)
return -ENOMEM; return -ENOMEM;
gpiod_set_consumer_name(cs[i], gpioname); 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; return 0;
......
...@@ -423,6 +423,12 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) ...@@ -423,6 +423,12 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* GPIO descriptors rather than using global GPIO numbers grabbed by the * GPIO descriptors rather than using global GPIO numbers grabbed by the
* driver. This will fill in @cs_gpiods and @cs_gpios should not be used, * driver. This will fill in @cs_gpiods and @cs_gpios should not be used,
* and SPI devices will have the cs_gpiod assigned rather than cs_gpio. * and SPI devices will have the cs_gpiod assigned rather than cs_gpio.
* @unused_native_cs: When cs_gpiods is used, spi_register_controller() will
* fill in this field with the first unused native CS, to be used by SPI
* controller drivers that need to drive a native CS when using GPIO CS.
* @max_native_cs: When cs_gpiods is used, and this field is filled in,
* spi_register_controller() will validate all native CS (including the
* unused native CS) against this value.
* @statistics: statistics for the spi_controller * @statistics: statistics for the spi_controller
* @dma_tx: DMA transmit channel * @dma_tx: DMA transmit channel
* @dma_rx: DMA receive channel * @dma_rx: DMA receive channel
...@@ -624,6 +630,8 @@ struct spi_controller { ...@@ -624,6 +630,8 @@ struct spi_controller {
int *cs_gpios; int *cs_gpios;
struct gpio_desc **cs_gpiods; struct gpio_desc **cs_gpiods;
bool use_gpio_descriptors; bool use_gpio_descriptors;
u8 unused_native_cs;
u8 max_native_cs;
/* statistics */ /* statistics */
struct spi_statistics statistics; struct spi_statistics statistics;
......
...@@ -6,16 +6,12 @@ ...@@ -6,16 +6,12 @@
* struct tiny_spi_platform_data - platform data of the OpenCores tiny SPI * struct tiny_spi_platform_data - platform data of the OpenCores tiny SPI
* @freq: input clock freq to the core. * @freq: input clock freq to the core.
* @baudwidth: baud rate divider width of the core. * @baudwidth: baud rate divider width of the core.
* @gpio_cs_count: number of gpio pins used for chipselect.
* @gpio_cs: array of gpio pins used for chipselect.
* *
* freq and baudwidth are used only if the divider is programmable. * freq and baudwidth are used only if the divider is programmable.
*/ */
struct tiny_spi_platform_data { struct tiny_spi_platform_data {
unsigned int freq; unsigned int freq;
unsigned int baudwidth; unsigned int baudwidth;
unsigned int gpio_cs_count;
int *gpio_cs;
}; };
#endif /* _LINUX_SPI_SPI_OC_TINY_H */ #endif /* _LINUX_SPI_SPI_OC_TINY_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment