Commit 303ba85c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'spi-v6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi

Pull spi updates from Mark Brown:
 "This is quite a quiet release for SPI. The one new core feature here
  is support for configuring the state of the MOSI pin when the bus is
  idle, there are some devices which are very fragile in this regard
  even when the chip select signal is not asserted. Otherwise we have
  some new driver support, a bunch of small fixes and some general
  cleanup work.

   - Support for configuring the state of the MOSI pin when the the bus
     is idle

   - Add the Elgin JG0309-01 in spidev

   - Support for Marvell xSPI, Mediatek MTK7981, Microchip PIC64GX, NXP
     i.MX8ULP, and Rockchip RK3576 controllers

  I also accidentally pulled in an IIO DT bindings update due to a typo
  when applying the MOSI idle state patches"

* tag 'spi-v6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (65 commits)
  spi: geni-qcom: Use devm functions to simplify code
  spi: remove spi_controller_is_slave() and spi_slave_abort()
  platform/olpc: olpc-xo175-ec: switch to use spi_target_abort().
  spi: slave-mt27xx: switch to use target_abort
  spi: spidev: switch to use spi_target_abort()
  spi: slave-system-control: switch to use spi_target_abort()
  spi: slave-time: switch to use spi_target_abort()
  spi: switch to use spi_controller_is_target()
  spi: fspi: add support for imx8ulp
  spi: fspi: involve lut_num for struct nxp_fspi_devtype_data
  dt-bindings: spi: nxp-fspi: add imx8ulp support
  spi: spidev_fdx: Fix the wrong format specifier
  spi: mxs: Switch to RUNTIME/SYSTEM_SLEEP_PM_OPS()
  spi: dt-bindings: Add rockchip,rk3576-spi compatible
  spi: Revert "spi: Insert the missing pci_dev_put()before return"
  spi: zynq-qspi: Replace kzalloc with kmalloc for buffer allocation
  spi: ppc4xx: Sort headers
  spi: ppc4xx: Revert "handle irq_of_parse_and_map() errors"
  spi: zynqmp-gqspi: Simplify with dev_err_probe()
  spi: zynqmp-gqspi: Use devm_spi_alloc_host()
  ...
parents 6df92808 07f1eb71
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/adi,ad4000.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD4000 and similar Analog to Digital Converters
maintainers:
- Marcelo Schmitt <marcelo.schmitt@analog.com>
description: |
Analog Devices AD4000 family of Analog to Digital Converters with SPI support.
Specifications can be found at:
https://www.analog.com/media/en/technical-documentation/data-sheets/ad4000-4004-4008.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/ad4001-4005.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/ad4002-4006-4010.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/ad4003-4007-4011.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/ad4020-4021-4022.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4001.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4003.pdf
$ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
oneOf:
- const: adi,ad4000
- items:
- enum:
- adi,ad4004
- adi,ad4008
- const: adi,ad4000
- const: adi,ad4001
- items:
- enum:
- adi,ad4005
- const: adi,ad4001
- const: adi,ad4002
- items:
- enum:
- adi,ad4006
- adi,ad4010
- const: adi,ad4002
- const: adi,ad4003
- items:
- enum:
- adi,ad4007
- adi,ad4011
- const: adi,ad4003
- const: adi,ad4020
- items:
- enum:
- adi,ad4021
- adi,ad4022
- const: adi,ad4020
- const: adi,adaq4001
- const: adi,adaq4003
reg:
maxItems: 1
spi-max-frequency:
maximum: 102040816 # for VIO > 2.7 V, 81300813 for VIO > 1.7 V
adi,sdi-pin:
$ref: /schemas/types.yaml#/definitions/string
enum: [ high, low, cs, sdi ]
default: sdi
description:
Describes how the ADC SDI pin is wired. A value of "sdi" indicates that
the ADC SDI is connected to host SDO. "high" indicates that the ADC SDI
pin is hard-wired to logic high (VIO). "low" indicates that it is
hard-wired low (GND). "cs" indicates that the ADC SDI pin is connected to
the host CS line.
'#daisy-chained-devices': true
vdd-supply:
description: A 1.8V supply that powers the chip (VDD).
vio-supply:
description:
A 1.8V to 5.5V supply for the digital inputs and outputs (VIO).
ref-supply:
description:
A 2.5 to 5V supply for the external reference voltage (REF).
cnv-gpios:
description:
When provided, this property indicates the GPIO that is connected to the
CNV pin.
maxItems: 1
adi,high-z-input:
type: boolean
description:
High-Z mode allows the amplifier and RC filter in front of the ADC to be
chosen based on the signal bandwidth of interest, rather than the settling
requirements of the switched capacitor SAR ADC inputs.
adi,gain-milli:
description: |
The hardware gain applied to the ADC input (in milli units).
The gain provided by the ADC input scaler is defined by the hardware
connections between chip pins OUT+, R1K-, R1K1-, R1K+, R1K1+, and OUT-.
If not present, default to 1000 (no actual gain applied).
$ref: /schemas/types.yaml#/definitions/uint16
enum: [454, 909, 1000, 1900]
default: 1000
interrupts:
description:
The SDO pin can also function as a busy indicator. This node should be
connected to an interrupt that is triggered when the SDO line goes low
while the SDI line is high and the CNV line is low ("3-wire" mode) or the
SDI line is low and the CNV line is high ("4-wire" mode); or when the SDO
line goes high while the SDI and CNV lines are high (chain mode),
maxItems: 1
required:
- compatible
- reg
- vdd-supply
- vio-supply
- ref-supply
allOf:
# The configuration register can only be accessed if SDI is connected to MOSI
- if:
required:
- adi,sdi-pin
then:
properties:
adi,high-z-input: false
# chain mode has lower SCLK max rate
- if:
required:
- '#daisy-chained-devices'
then:
properties:
spi-max-frequency:
maximum: 50000000 # for VIO > 2.7 V, 40000000 for VIO > 1.7 V
# Gain property only applies to ADAQ devices
- if:
properties:
compatible:
not:
contains:
enum:
- adi,adaq4001
- adi,adaq4003
then:
properties:
adi,gain-milli: false
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "adi,ad4020";
reg = <0>;
spi-max-frequency = <71000000>;
vdd-supply = <&supply_1_8V>;
vio-supply = <&supply_1_8V>;
ref-supply = <&supply_5V>;
adi,sdi-pin = "cs";
cnv-gpios = <&gpio0 88 GPIO_ACTIVE_HIGH>;
};
};
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "adi,adaq4003";
reg = <0>;
spi-max-frequency = <80000000>;
vdd-supply = <&supply_1_8V>;
vio-supply = <&supply_1_8V>;
ref-supply = <&supply_5V>;
adi,high-z-input;
adi,gain-milli = /bits/ 16 <454>;
};
};
......@@ -15,24 +15,27 @@ description: |
single, dual, quad or octal wire transmission modes for
read/write access to slaves such as SPI-NOR flash.
allOf:
- $ref: spi-controller.yaml#
properties:
compatible:
const: cdns,xspi-nor
enum:
- cdns,xspi-nor
- marvell,cn10-xspi-nor
reg:
items:
- description: address and length of the controller register set
- description: address and length of the Slave DMA data port
- description: address and length of the auxiliary registers
- description: address and length of the xfer registers
minItems: 3
reg-names:
items:
- const: io
- const: sdma
- const: aux
- const: xfer
minItems: 3
interrupts:
maxItems: 1
......@@ -42,6 +45,27 @@ required:
- reg
- interrupts
allOf:
- $ref: spi-controller.yaml#
- if:
properties:
compatible:
contains:
enum:
- marvell,cn10-xspi-nor
then:
properties:
reg:
minItems: 4
reg-names:
minItems: 4
else:
properties:
reg:
maxItems: 3
reg-names:
maxItems: 3
unevaluatedProperties: false
examples:
......
......@@ -33,6 +33,7 @@ properties:
- const: mediatek,mt6765-spi
- items:
- enum:
- mediatek,mt7981-spi-ipm
- mediatek,mt7986-spi-ipm
- mediatek,mt8188-spi-ipm
- const: mediatek,spi-ipm
......
......@@ -17,9 +17,14 @@ properties:
compatible:
oneOf:
- items:
- const: microchip,mpfs-qspi
- enum:
- microchip,mpfs-qspi
- microchip,pic64gx-qspi
- const: microchip,coreqspi-rtl-v2
- const: microchip,coreqspi-rtl-v2 # FPGA QSPI
- items:
- const: microchip,pic64gx-spi
- const: microchip,mpfs-spi
- const: microchip,mpfs-spi
reg:
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/nxp,sc18is.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP SC18IS602/SC18IS603 I2C to SPI bridge
maintainers:
- Frank Li <Frank.Li@nxp.com>
properties:
compatible:
enum:
- nxp,sc18is602
- nxp,sc18is602b
- nxp,sc18is603
reg:
maxItems: 1
clock-frequency:
$ref: /schemas/types.yaml#/definitions/uint32
default: 7372000
description:
external oscillator clock frequency. The clock-frequency property is
relevant and needed only if the chip has an external oscillator
(SC18IS603).
allOf:
- $ref: spi-controller.yaml#
unevaluatedProperties: false
required:
- compatible
- reg
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
spi@28 {
compatible = "nxp,sc18is603";
reg = <0x28>;
clock-frequency = <14744000>;
};
};
......@@ -21,6 +21,7 @@ properties:
- nxp,imx8mm-fspi
- nxp,imx8mp-fspi
- nxp,imx8qxp-fspi
- nxp,imx8ulp-fspi
- nxp,lx2160a-fspi
- items:
- enum:
......
......@@ -35,6 +35,7 @@ properties:
- rockchip,rk3368-spi
- rockchip,rk3399-spi
- rockchip,rk3568-spi
- rockchip,rk3576-spi
- rockchip,rk3588-spi
- rockchip,rv1126-spi
- const: rockchip,rk3066-spi
......
NXP SC18IS602/SCIS603
Required properties:
- compatible : Should be one of
"nxp,sc18is602"
"nxp,sc18is602b"
"nxp,sc18is603"
- reg: I2C bus address
Optional properties:
- clock-frequency : external oscillator clock frequency. If not
specified, the SC18IS602 default frequency (7372000) will be used.
The clock-frequency property is relevant and needed only if the chip has an
external oscillator (SC18IS603).
Example:
sc18is603@28 {
compatible = "nxp,sc18is603";
reg = <0x28>;
clock-frequency = <14744000>;
}
......@@ -110,6 +110,8 @@ properties:
- domintech,dmard09
# DMARD10: 3-axis Accelerometer
- domintech,dmard10
# Elgin SPI-controlled LCD
- elgin,jg10309-01
# MMA7660FC: 3-Axis Orientation/Motion Detection Sensor
- fsl,mma7660
# MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
......
......@@ -614,6 +614,89 @@ queue, and then start some asynchronous transfer engine (unless it's
already running).
Extensions to the SPI protocol
------------------------------
The fact that SPI doesn't have a formal specification or standard permits chip
manufacturers to implement the SPI protocol in slightly different ways. In most
cases, SPI protocol implementations from different vendors are compatible among
each other. For example, in SPI mode 0 (CPOL=0, CPHA=0) the bus lines may behave
like the following:
::
nCSx ___ ___
\_________________________________________________________________/
• •
• •
SCLK ___ ___ ___ ___ ___ ___ ___ ___
_______/ \___/ \___/ \___/ \___/ \___/ \___/ \___/ \_____
• : ; : ; : ; : ; : ; : ; : ; : ; •
• : ; : ; : ; : ; : ; : ; : ; : ; •
MOSI XXX__________ _______ _______ ________XXX
0xA5 XXX__/ 1 \_0_____/ 1 \_0_______0_____/ 1 \_0_____/ 1 \_XXX
• ; ; ; ; ; ; ; ; •
• ; ; ; ; ; ; ; ; •
MISO XXX__________ _______________________ _______ XXX
0xBA XXX__/ 1 \_____0_/ 1 1 1 \_____0__/ 1 \____0__XXX
Legend::
• marks the start/end of transmission;
: marks when data is clocked into the peripheral;
; marks when data is clocked into the controller;
X marks when line states are not specified.
In some few cases, chips extend the SPI protocol by specifying line behaviors
that other SPI protocols don't (e.g. data line state for when CS is not
asserted). Those distinct SPI protocols, modes, and configurations are supported
by different SPI mode flags.
MOSI idle state configuration
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Common SPI protocol implementations don't specify any state or behavior for the
MOSI line when the controller is not clocking out data. However, there do exist
peripherals that require specific MOSI line state when data is not being clocked
out. For example, if the peripheral expects the MOSI line to be high when the
controller is not clocking out data (``SPI_MOSI_IDLE_HIGH``), then a transfer in
SPI mode 0 would look like the following:
::
nCSx ___ ___
\_________________________________________________________________/
• •
• •
SCLK ___ ___ ___ ___ ___ ___ ___ ___
_______/ \___/ \___/ \___/ \___/ \___/ \___/ \___/ \_____
• : ; : ; : ; : ; : ; : ; : ; : ; •
• : ; : ; : ; : ; : ; : ; : ; : ; •
MOSI _____ _______ _______ _______________ ___
0x56 \_0_____/ 1 \_0_____/ 1 \_0_____/ 1 1 \_0_____/
• ; ; ; ; ; ; ; ; •
• ; ; ; ; ; ; ; ; •
MISO XXX__________ _______________________ _______ XXX
0xBA XXX__/ 1 \_____0_/ 1 1 1 \_____0__/ 1 \____0__XXX
Legend::
• marks the start/end of transmission;
: marks when data is clocked into the peripheral;
; marks when data is clocked into the controller;
X marks when line states are not specified.
In this extension to the usual SPI protocol, the MOSI line state is specified to
be kept high when CS is asserted but the controller is not clocking out data to
the peripheral and also when CS is not asserted.
Peripherals that require this extension must request it by setting the
``SPI_MOSI_IDLE_HIGH`` bit into the mode attribute of their ``struct
spi_device`` and call spi_setup(). Controllers that support this extension
should indicate it by setting ``SPI_MOSI_IDLE_HIGH`` in the mode_bits attribute
of their ``struct spi_controller``. The configuration to idle MOSI low is
analogous but uses the ``SPI_MOSI_IDLE_LOW`` mode bit.
THANKS TO
---------
Contributors to Linux-SPI discussions include (in alphabetical order,
......
......@@ -1210,6 +1210,13 @@ W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
F: drivers/iio/dac/ad3552r.c
ANALOG DEVICES INC AD4000 DRIVER
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/adc/adi,ad4000.yaml
ANALOG DEVICES INC AD4130 DRIVER
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
L: linux-iio@vger.kernel.org
......
......@@ -536,7 +536,7 @@ static int olpc_xo175_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *resp,
dev_err(dev, "EC cmd error: timeout in STATE %d\n",
priv->cmd_state);
gpiod_set_value_cansleep(priv->gpio_cmd, 0);
spi_slave_abort(priv->spi);
spi_target_abort(priv->spi);
olpc_xo175_ec_read_packet(priv);
return -ETIMEDOUT;
}
......@@ -653,7 +653,7 @@ static void olpc_xo175_ec_remove(struct spi_device *spi)
if (pm_power_off == olpc_xo175_ec_power_off)
pm_power_off = NULL;
spi_slave_abort(spi);
spi_target_abort(spi);
platform_device_unregister(olpc_ec);
olpc_ec = NULL;
......
......@@ -267,7 +267,7 @@ config SPI_CADENCE_QUADSPI
config SPI_CADENCE_XSPI
tristate "Cadence XSPI controller"
depends on OF && HAS_IOMEM
depends on OF && HAS_IOMEM && 64BIT
depends on SPI_MEM
help
Enable support for the Cadence XSPI Flash controller.
......
......@@ -601,20 +601,17 @@ static int atmel_qspi_probe(struct platform_device *pdev)
aq->pdev = pdev;
/* Map the registers */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_base");
aq->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(aq->regs)) {
dev_err(&pdev->dev, "missing registers\n");
return PTR_ERR(aq->regs);
}
aq->regs = devm_platform_ioremap_resource_byname(pdev, "qspi_base");
if (IS_ERR(aq->regs))
return dev_err_probe(&pdev->dev, PTR_ERR(aq->regs),
"missing registers\n");
/* Map the AHB memory */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mmap");
aq->mem = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(aq->mem)) {
dev_err(&pdev->dev, "missing AHB memory\n");
return PTR_ERR(aq->mem);
}
if (IS_ERR(aq->mem))
return dev_err_probe(&pdev->dev, PTR_ERR(aq->mem),
"missing AHB memory\n");
aq->mmap_size = resource_size(res);
......@@ -623,17 +620,15 @@ static int atmel_qspi_probe(struct platform_device *pdev)
if (IS_ERR(aq->pclk))
aq->pclk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(aq->pclk)) {
dev_err(&pdev->dev, "missing peripheral clock\n");
return PTR_ERR(aq->pclk);
}
if (IS_ERR(aq->pclk))
return dev_err_probe(&pdev->dev, PTR_ERR(aq->pclk),
"missing peripheral clock\n");
/* Enable the peripheral clock */
err = clk_prepare_enable(aq->pclk);
if (err) {
dev_err(&pdev->dev, "failed to enable the peripheral clock\n");
return err;
}
if (err)
return dev_err_probe(&pdev->dev, err,
"failed to enable the peripheral clock\n");
aq->caps = of_device_get_match_data(&pdev->dev);
if (!aq->caps) {
......
......@@ -41,6 +41,7 @@
#define SPI_ENGINE_CONFIG_CPHA BIT(0)
#define SPI_ENGINE_CONFIG_CPOL BIT(1)
#define SPI_ENGINE_CONFIG_3WIRE BIT(2)
#define SPI_ENGINE_CONFIG_SDO_IDLE_HIGH BIT(3)
#define SPI_ENGINE_INST_TRANSFER 0x0
#define SPI_ENGINE_INST_ASSERT 0x1
......@@ -137,6 +138,10 @@ static unsigned int spi_engine_get_config(struct spi_device *spi)
config |= SPI_ENGINE_CONFIG_CPHA;
if (spi->mode & SPI_3WIRE)
config |= SPI_ENGINE_CONFIG_3WIRE;
if (spi->mode & SPI_MOSI_IDLE_HIGH)
config |= SPI_ENGINE_CONFIG_SDO_IDLE_HIGH;
if (spi->mode & SPI_MOSI_IDLE_LOW)
config &= ~SPI_ENGINE_CONFIG_SDO_IDLE_HIGH;
return config;
}
......@@ -258,7 +263,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
clk_div - 1));
}
if (bits_per_word != xfer->bits_per_word) {
if (bits_per_word != xfer->bits_per_word && xfer->len) {
bits_per_word = xfer->bits_per_word;
spi_engine_program_add_cmd(p, dry,
SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_XFER_BITS,
......@@ -692,9 +697,13 @@ static int spi_engine_probe(struct platform_device *pdev)
host->num_chipselect = 8;
/* Some features depend of the IP core version. */
if (ADI_AXI_PCORE_VER_MINOR(version) >= 2) {
host->mode_bits |= SPI_CS_HIGH;
host->setup = spi_engine_setup;
if (ADI_AXI_PCORE_VER_MAJOR(version) >= 1) {
if (ADI_AXI_PCORE_VER_MINOR(version) >= 2) {
host->mode_bits |= SPI_CS_HIGH;
host->setup = spi_engine_setup;
}
if (ADI_AXI_PCORE_VER_MINOR(version) >= 3)
host->mode_bits |= SPI_MOSI_IDLE_LOW | SPI_MOSI_IDLE_HIGH;
}
if (host->max_speed_hz == 0)
......
......@@ -466,6 +466,7 @@ static const struct platform_device_id bcm63xx_spi_dev_match[] = {
{
},
};
MODULE_DEVICE_TABLE(platform, bcm63xx_spi_dev_match);
static const struct of_device_id bcm63xx_spi_of_match[] = {
{ .compatible = "brcm,bcm6348-spi", .data = &bcm6348_spi_reg_offsets },
......@@ -583,13 +584,15 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
pm_runtime_enable(&pdev->dev);
ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
goto out_clk_disable;
/* register and we are done */
ret = devm_spi_register_controller(dev, host);
if (ret) {
dev_err(dev, "spi register failed\n");
goto out_pm_disable;
goto out_clk_disable;
}
dev_info(dev, "at %pr (irq %d, FIFOs size %d)\n",
......@@ -597,8 +600,6 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
return 0;
out_pm_disable:
pm_runtime_disable(&pdev->dev);
out_clk_disable:
clk_disable_unprepare(clk);
out_err:
......
......@@ -433,7 +433,6 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev)
{
struct spi_controller *host;
struct bcmbca_hsspi *bs;
struct resource *res_mem;
void __iomem *spim_ctrl;
void __iomem *regs;
struct device *dev = &pdev->dev;
......@@ -445,17 +444,11 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hsspi");
if (!res_mem)
return -EINVAL;
regs = devm_ioremap_resource(dev, res_mem);
regs = devm_platform_ioremap_resource_byname(pdev, "hsspi");
if (IS_ERR(regs))
return PTR_ERR(regs);
res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "spim-ctrl");
if (!res_mem)
return -EINVAL;
spim_ctrl = devm_ioremap_resource(dev, res_mem);
spim_ctrl = devm_platform_ioremap_resource_byname(pdev, "spim-ctrl");
if (IS_ERR(spim_ctrl))
return PTR_ERR(spim_ctrl);
......@@ -487,7 +480,7 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev)
}
}
host = spi_alloc_host(&pdev->dev, sizeof(*bs));
host = devm_spi_alloc_host(&pdev->dev, sizeof(*bs));
if (!host) {
ret = -ENOMEM;
goto out_disable_pll_clk;
......@@ -543,15 +536,17 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, irq, bcmbca_hsspi_interrupt, IRQF_SHARED,
pdev->name, bs);
if (ret)
goto out_put_host;
goto out_disable_pll_clk;
}
pm_runtime_enable(&pdev->dev);
ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
goto out_disable_pll_clk;
ret = sysfs_create_group(&pdev->dev.kobj, &bcmbca_hsspi_group);
if (ret) {
dev_err(&pdev->dev, "couldn't register sysfs group\n");
goto out_pm_disable;
goto out_disable_pll_clk;
}
/* register and we are done */
......@@ -565,10 +560,6 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev)
out_sysgroup_disable:
sysfs_remove_group(&pdev->dev.kobj, &bcmbca_hsspi_group);
out_pm_disable:
pm_runtime_disable(&pdev->dev);
out_put_host:
spi_controller_put(host);
out_disable_pll_clk:
clk_disable_unprepare(pll_clk);
out_disable_clk:
......
......@@ -54,21 +54,28 @@ static unsigned int bitbang_txrx_8(struct spi_device *spi,
struct spi_transfer *t,
unsigned int flags)
{
struct spi_bitbang *bitbang;
unsigned int bits = t->bits_per_word;
unsigned int count = t->len;
const u8 *tx = t->tx_buf;
u8 *rx = t->rx_buf;
bitbang = spi_controller_get_devdata(spi->controller);
while (likely(count > 0)) {
u8 word = 0;
if (tx)
word = *tx++;
else
word = spi->mode & SPI_MOSI_IDLE_HIGH ? 0xFF : 0;
word = txrx_word(spi, ns, word, bits, flags);
if (rx)
*rx++ = word;
count -= 1;
}
if (bitbang->set_mosi_idle)
bitbang->set_mosi_idle(spi);
return t->len - count;
}
......@@ -78,21 +85,28 @@ static unsigned int bitbang_txrx_16(struct spi_device *spi,
struct spi_transfer *t,
unsigned int flags)
{
struct spi_bitbang *bitbang;
unsigned int bits = t->bits_per_word;
unsigned int count = t->len;
const u16 *tx = t->tx_buf;
u16 *rx = t->rx_buf;
bitbang = spi_controller_get_devdata(spi->controller);
while (likely(count > 1)) {
u16 word = 0;
if (tx)
word = *tx++;
else
word = spi->mode & SPI_MOSI_IDLE_HIGH ? 0xFFFF : 0;
word = txrx_word(spi, ns, word, bits, flags);
if (rx)
*rx++ = word;
count -= 2;
}
if (bitbang->set_mosi_idle)
bitbang->set_mosi_idle(spi);
return t->len - count;
}
......@@ -102,21 +116,28 @@ static unsigned int bitbang_txrx_32(struct spi_device *spi,
struct spi_transfer *t,
unsigned int flags)
{
struct spi_bitbang *bitbang;
unsigned int bits = t->bits_per_word;
unsigned int count = t->len;
const u32 *tx = t->tx_buf;
u32 *rx = t->rx_buf;
bitbang = spi_controller_get_devdata(spi->controller);
while (likely(count > 3)) {
u32 word = 0;
if (tx)
word = *tx++;
else
word = spi->mode & SPI_MOSI_IDLE_HIGH ? 0xFFFFFFFF : 0;
word = txrx_word(spi, ns, word, bits, flags);
if (rx)
*rx++ = word;
count -= 4;
}
if (bitbang->set_mosi_idle)
bitbang->set_mosi_idle(spi);
return t->len - count;
}
......@@ -192,6 +213,9 @@ int spi_bitbang_setup(struct spi_device *spi)
goto err_free;
}
if (bitbang->set_mosi_idle)
bitbang->set_mosi_idle(spi);
dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs);
return 0;
......
......@@ -1662,23 +1662,20 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi)
unsigned int max_cs = cqspi->num_chipselect - 1;
struct platform_device *pdev = cqspi->pdev;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct cqspi_flash_pdata *f_pdata;
unsigned int cs;
int ret;
/* Get flash device data */
for_each_available_child_of_node(dev->of_node, np) {
for_each_available_child_of_node_scoped(dev->of_node, np) {
ret = of_property_read_u32(np, "reg", &cs);
if (ret) {
dev_err(dev, "Couldn't determine chip select.\n");
of_node_put(np);
return ret;
}
if (cs >= cqspi->num_chipselect) {
dev_err(dev, "Chip select %d out of range.\n", cs);
of_node_put(np);
return -EINVAL;
} else if (cs < max_cs) {
max_cs = cs;
......@@ -1689,10 +1686,8 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi)
f_pdata->cs = cs;
ret = cqspi_of_get_flash_pdata(pdev, f_pdata, np);
if (ret) {
of_node_put(np);
if (ret)
return ret;
}
}
cqspi->num_chipselect = max_cs + 1;
......
This diff is collapsed.
......@@ -570,6 +570,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
u32 errors = 0;
struct davinci_spi_config *spicfg;
struct davinci_spi_platform_data *pdata;
unsigned long timeout;
dspi = spi_controller_get_devdata(spi->controller);
pdata = &dspi->pdata;
......@@ -661,7 +662,12 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
/* Wait for the transfer to complete */
if (spicfg->io_type != SPI_IO_TYPE_POLL) {
if (wait_for_completion_timeout(&dspi->done, HZ) == 0)
timeout = DIV_ROUND_UP(t->speed_hz, MSEC_PER_SEC);
timeout = DIV_ROUND_UP(t->len * 8, timeout);
/* Assume we are at most 2x slower than the nominal bus speed */
timeout = 2 * msecs_to_jiffies(timeout);
if (wait_for_completion_timeout(&dspi->done, timeout) == 0)
errors = SPIFLG_TIMEOUT_MASK;
} else {
while (dspi->rcount > 0 || dspi->wcount > 0) {
......
......@@ -604,6 +604,21 @@ static int spi_geni_prepare_message(struct spi_controller *spi,
return -EINVAL;
}
static void spi_geni_release_dma_chan(void *data)
{
struct spi_geni_master *mas = data;
if (mas->rx) {
dma_release_channel(mas->rx);
mas->rx = NULL;
}
if (mas->tx) {
dma_release_channel(mas->tx);
mas->tx = NULL;
}
}
static int spi_geni_grab_gpi_chan(struct spi_geni_master *mas)
{
int ret;
......@@ -622,6 +637,12 @@ static int spi_geni_grab_gpi_chan(struct spi_geni_master *mas)
goto err_rx;
}
ret = devm_add_action_or_reset(mas->dev, spi_geni_release_dma_chan, mas);
if (ret) {
dev_err(mas->dev, "Unable to add action.\n");
return ret;
}
return 0;
err_rx:
......@@ -632,19 +653,6 @@ static int spi_geni_grab_gpi_chan(struct spi_geni_master *mas)
return ret;
}
static void spi_geni_release_dma_chan(struct spi_geni_master *mas)
{
if (mas->rx) {
dma_release_channel(mas->rx);
mas->rx = NULL;
}
if (mas->tx) {
dma_release_channel(mas->tx);
mas->tx = NULL;
}
}
static int spi_geni_init(struct spi_geni_master *mas)
{
struct spi_controller *spi = dev_get_drvdata(mas->dev);
......@@ -1146,33 +1154,11 @@ static int spi_geni_probe(struct platform_device *pdev)
if (mas->cur_xfer_mode == GENI_GPI_DMA)
spi->flags = SPI_CONTROLLER_MUST_TX;
ret = request_irq(mas->irq, geni_spi_isr, 0, dev_name(dev), spi);
if (ret)
goto spi_geni_release_dma;
ret = spi_register_controller(spi);
ret = devm_request_irq(dev, mas->irq, geni_spi_isr, 0, dev_name(dev), spi);
if (ret)
goto spi_geni_probe_free_irq;
return 0;
spi_geni_probe_free_irq:
free_irq(mas->irq, spi);
spi_geni_release_dma:
spi_geni_release_dma_chan(mas);
return ret;
}
static void spi_geni_remove(struct platform_device *pdev)
{
struct spi_controller *spi = platform_get_drvdata(pdev);
struct spi_geni_master *mas = spi_controller_get_devdata(spi);
/* Unregister _before_ disabling pm_runtime() so we stop transfers */
spi_unregister_controller(spi);
free_irq(mas->irq, spi);
return ret;
spi_geni_release_dma_chan(mas);
return devm_spi_register_controller(dev, spi);
}
static int __maybe_unused spi_geni_runtime_suspend(struct device *dev)
......@@ -1254,7 +1240,6 @@ MODULE_DEVICE_TABLE(of, spi_geni_dt_match);
static struct platform_driver spi_geni_driver = {
.probe = spi_geni_probe,
.remove_new = spi_geni_remove,
.driver = {
.name = "geni_spi",
.pm = &spi_geni_pm_ops,
......
......@@ -236,6 +236,14 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
}
}
static void spi_gpio_set_mosi_idle(struct spi_device *spi)
{
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
gpiod_set_value_cansleep(spi_gpio->mosi,
!!(spi->mode & SPI_MOSI_IDLE_HIGH));
}
static int spi_gpio_setup(struct spi_device *spi)
{
struct gpio_desc *cs;
......@@ -389,7 +397,8 @@ static int spi_gpio_probe(struct platform_device *pdev)
host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
host->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL |
SPI_CS_HIGH | SPI_LSB_FIRST;
SPI_CS_HIGH | SPI_LSB_FIRST | SPI_MOSI_IDLE_LOW |
SPI_MOSI_IDLE_HIGH;
if (!spi_gpio->mosi) {
/* HW configuration without MOSI pin
*
......@@ -414,6 +423,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
host->flags |= SPI_CONTROLLER_GPIO_SS;
bb->chipselect = spi_gpio_chipselect;
bb->set_line_direction = spi_gpio_set_direction;
bb->set_mosi_idle = spi_gpio_set_mosi_idle;
if (host->flags & SPI_CONTROLLER_NO_TX) {
bb->txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0;
......
......@@ -655,8 +655,8 @@ static int meson_spicc_pow2_clk_init(struct meson_spicc_device *spicc)
}
init.num_parents = 1;
pow2_fixed_div->mult = 1,
pow2_fixed_div->div = 4,
pow2_fixed_div->mult = 1;
pow2_fixed_div->div = 4;
pow2_fixed_div->hw.init = &init;
clk = devm_clk_register(dev, &pow2_fixed_div->hw);
......@@ -674,9 +674,9 @@ static int meson_spicc_pow2_clk_init(struct meson_spicc_device *spicc)
parent_data[0].hw = &pow2_fixed_div->hw;
init.num_parents = 1;
spicc->pow2_div.shift = 16,
spicc->pow2_div.width = 3,
spicc->pow2_div.flags = CLK_DIVIDER_POWER_OF_TWO,
spicc->pow2_div.shift = 16;
spicc->pow2_div.width = 3;
spicc->pow2_div.flags = CLK_DIVIDER_POWER_OF_TWO;
spicc->pow2_div.reg = spicc->base + SPICC_CONREG;
spicc->pow2_div.hw.init = &init;
......@@ -721,8 +721,8 @@ static int meson_spicc_enh_clk_init(struct meson_spicc_device *spicc)
}
init.num_parents = 1;
enh_fixed_div->mult = 1,
enh_fixed_div->div = 2,
enh_fixed_div->mult = 1;
enh_fixed_div->div = 2;
enh_fixed_div->hw.init = &init;
clk = devm_clk_register(dev, &enh_fixed_div->hw);
......@@ -740,8 +740,8 @@ static int meson_spicc_enh_clk_init(struct meson_spicc_device *spicc)
parent_data[0].hw = &enh_fixed_div->hw;
init.num_parents = 1;
enh_div->shift = 16,
enh_div->width = 8,
enh_div->shift = 16;
enh_div->width = 8;
enh_div->reg = spicc->base + SPICC_ENH_CTL0;
enh_div->hw.init = &init;
......@@ -761,8 +761,8 @@ static int meson_spicc_enh_clk_init(struct meson_spicc_device *spicc)
init.num_parents = 2;
init.flags = CLK_SET_RATE_PARENT;
mux->mask = 0x1,
mux->shift = 24,
mux->mask = 0x1;
mux->shift = 24;
mux->reg = spicc->base + SPICC_ENH_CTL0;
mux->hw.init = &init;
......
......@@ -743,25 +743,13 @@ static int mtk_spi_setup(struct spi_device *spi)
return 0;
}
static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
static irqreturn_t mtk_spi_interrupt_thread(int irq, void *dev_id)
{
u32 cmd, reg_val, cnt, remainder, len;
struct spi_controller *host = dev_id;
struct mtk_spi *mdata = spi_controller_get_devdata(host);
struct spi_transfer *xfer = mdata->cur_transfer;
reg_val = readl(mdata->base + SPI_STATUS0_REG);
if (reg_val & MTK_SPI_PAUSE_INT_STATUS)
mdata->state = MTK_SPI_PAUSED;
else
mdata->state = MTK_SPI_IDLE;
/* SPI-MEM ops */
if (mdata->use_spimem) {
complete(&mdata->spimem_done);
return IRQ_HANDLED;
}
if (!host->can_dma(host, NULL, xfer)) {
if (xfer->rx_buf) {
cnt = mdata->xfer_len / 4;
......@@ -845,6 +833,27 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
{
struct spi_controller *host = dev_id;
struct mtk_spi *mdata = spi_controller_get_devdata(host);
u32 reg_val;
reg_val = readl(mdata->base + SPI_STATUS0_REG);
if (reg_val & MTK_SPI_PAUSE_INT_STATUS)
mdata->state = MTK_SPI_PAUSED;
else
mdata->state = MTK_SPI_IDLE;
/* SPI-MEM ops */
if (mdata->use_spimem) {
complete(&mdata->spimem_done);
return IRQ_HANDLED;
}
return IRQ_WAKE_THREAD;
}
static int mtk_spi_mem_adjust_op_size(struct spi_mem *mem,
struct spi_mem_op *op)
{
......@@ -1255,8 +1264,9 @@ static int mtk_spi_probe(struct platform_device *pdev)
dev_notice(dev, "SPI dma_set_mask(%d) failed, ret:%d\n",
addr_bits, ret);
ret = devm_request_irq(dev, irq, mtk_spi_interrupt,
IRQF_TRIGGER_NONE, dev_name(dev), host);
ret = devm_request_threaded_irq(dev, irq, mtk_spi_interrupt,
mtk_spi_interrupt_thread,
IRQF_TRIGGER_NONE, dev_name(dev), host);
if (ret)
return dev_err_probe(dev, ret, "failed to register irq\n");
......
......@@ -477,7 +477,7 @@ static int mxs_spi_runtime_resume(struct device *dev)
return ret;
}
static int __maybe_unused mxs_spi_suspend(struct device *dev)
static int mxs_spi_suspend(struct device *dev)
{
struct spi_controller *host = dev_get_drvdata(dev);
int ret;
......@@ -492,7 +492,7 @@ static int __maybe_unused mxs_spi_suspend(struct device *dev)
return 0;
}
static int __maybe_unused mxs_spi_resume(struct device *dev)
static int mxs_spi_resume(struct device *dev)
{
struct spi_controller *host = dev_get_drvdata(dev);
int ret;
......@@ -512,9 +512,8 @@ static int __maybe_unused mxs_spi_resume(struct device *dev)
}
static const struct dev_pm_ops mxs_spi_pm = {
SET_RUNTIME_PM_OPS(mxs_spi_runtime_suspend,
mxs_spi_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(mxs_spi_suspend, mxs_spi_resume)
RUNTIME_PM_OPS(mxs_spi_runtime_suspend, mxs_spi_runtime_resume, NULL)
SYSTEM_SLEEP_PM_OPS(mxs_spi_suspend, mxs_spi_resume)
};
static const struct of_device_id mxs_spi_dt_ids[] = {
......@@ -662,7 +661,7 @@ static struct platform_driver mxs_spi_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = mxs_spi_dt_ids,
.pm = &mxs_spi_pm,
.pm = pm_ptr(&mxs_spi_pm),
},
};
......
......@@ -57,13 +57,6 @@
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>
/*
* The driver only uses one single LUT entry, that is updated on
* each call of exec_op(). Index 0 is preset at boot with a basic
* read operation, so let's use the last entry (31).
*/
#define SEQID_LUT 31
/* Registers used by the driver */
#define FSPI_MCR0 0x00
#define FSPI_MCR0_AHB_TIMEOUT(x) ((x) << 24)
......@@ -263,9 +256,6 @@
#define FSPI_TFDR 0x180
#define FSPI_LUT_BASE 0x200
#define FSPI_LUT_OFFSET (SEQID_LUT * 4 * 4)
#define FSPI_LUT_REG(idx) \
(FSPI_LUT_BASE + FSPI_LUT_OFFSET + (idx) * 4)
/* register map end */
......@@ -341,6 +331,7 @@ struct nxp_fspi_devtype_data {
unsigned int txfifo;
unsigned int ahb_buf_size;
unsigned int quirks;
unsigned int lut_num;
bool little_endian;
};
......@@ -349,6 +340,7 @@ static struct nxp_fspi_devtype_data lx2160a_data = {
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
.quirks = 0,
.lut_num = 32,
.little_endian = true, /* little-endian */
};
......@@ -357,6 +349,7 @@ static struct nxp_fspi_devtype_data imx8mm_data = {
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
.quirks = 0,
.lut_num = 32,
.little_endian = true, /* little-endian */
};
......@@ -365,6 +358,7 @@ static struct nxp_fspi_devtype_data imx8qxp_data = {
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
.quirks = 0,
.lut_num = 32,
.little_endian = true, /* little-endian */
};
......@@ -373,6 +367,16 @@ static struct nxp_fspi_devtype_data imx8dxl_data = {
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
.quirks = FSPI_QUIRK_USE_IP_ONLY,
.lut_num = 32,
.little_endian = true, /* little-endian */
};
static struct nxp_fspi_devtype_data imx8ulp_data = {
.rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
.quirks = 0,
.lut_num = 16,
.little_endian = true, /* little-endian */
};
......@@ -544,6 +548,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
void __iomem *base = f->iobase;
u32 lutval[4] = {};
int lutidx = 1, i;
u32 lut_offset = (f->devtype_data->lut_num - 1) * 4 * 4;
u32 target_lut_reg;
/* cmd */
lutval[0] |= LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth),
......@@ -588,8 +594,10 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
fspi_writel(f, FSPI_LCKER_UNLOCK, f->iobase + FSPI_LCKCR);
/* fill LUT */
for (i = 0; i < ARRAY_SIZE(lutval); i++)
fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i));
for (i = 0; i < ARRAY_SIZE(lutval); i++) {
target_lut_reg = FSPI_LUT_BASE + lut_offset + i * 4;
fspi_writel(f, lutval[i], base + target_lut_reg);
}
dev_dbg(f->dev, "CMD[%02x] lutval[0:%08x 1:%08x 2:%08x 3:%08x], size: 0x%08x\n",
op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], op->data.nbytes);
......@@ -756,8 +764,7 @@ static int nxp_fspi_read_ahb(struct nxp_fspi *f, const struct spi_mem_op *op)
iounmap(f->ahb_addr);
f->memmap_start = start;
f->memmap_len = len > NXP_FSPI_MIN_IOMAP ?
len : NXP_FSPI_MIN_IOMAP;
f->memmap_len = max_t(u32, len, NXP_FSPI_MIN_IOMAP);
f->ahb_addr = ioremap(f->memmap_phy + f->memmap_start,
f->memmap_len);
......@@ -876,7 +883,7 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op)
void __iomem *base = f->iobase;
int seqnum = 0;
int err = 0;
u32 reg;
u32 reg, seqid_lut;
reg = fspi_readl(f, base + FSPI_IPRXFCR);
/* invalid RXFIFO first */
......@@ -892,8 +899,9 @@ static int nxp_fspi_do_op(struct nxp_fspi *f, const struct spi_mem_op *op)
* the LUT at each exec_op() call. And also specify the DATA
* length, since it's has not been specified in the LUT.
*/
seqid_lut = f->devtype_data->lut_num - 1;
fspi_writel(f, op->data.nbytes |
(SEQID_LUT << FSPI_IPCR1_SEQID_SHIFT) |
(seqid_lut << FSPI_IPCR1_SEQID_SHIFT) |
(seqnum << FSPI_IPCR1_SEQNUM_SHIFT),
base + FSPI_IPCR1);
......@@ -1017,7 +1025,7 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
{
void __iomem *base = f->iobase;
int ret, i;
u32 reg;
u32 reg, seqid_lut;
/* disable and unprepare clock to avoid glitch pass to controller */
nxp_fspi_clk_disable_unprep(f);
......@@ -1092,11 +1100,17 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
fspi_writel(f, reg, base + FSPI_FLSHB1CR1);
fspi_writel(f, reg, base + FSPI_FLSHB2CR1);
/*
* The driver only uses one single LUT entry, that is updated on
* each call of exec_op(). Index 0 is preset at boot with a basic
* read operation, so let's use the last entry.
*/
seqid_lut = f->devtype_data->lut_num - 1;
/* AHB Read - Set lut sequence ID for all CS. */
fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA1CR2);
fspi_writel(f, SEQID_LUT, base + FSPI_FLSHA2CR2);
fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB1CR2);
fspi_writel(f, SEQID_LUT, base + FSPI_FLSHB2CR2);
fspi_writel(f, seqid_lut, base + FSPI_FLSHA1CR2);
fspi_writel(f, seqid_lut, base + FSPI_FLSHA2CR2);
fspi_writel(f, seqid_lut, base + FSPI_FLSHB1CR2);
fspi_writel(f, seqid_lut, base + FSPI_FLSHB2CR2);
f->selected = -1;
......@@ -1291,6 +1305,7 @@ static const struct of_device_id nxp_fspi_dt_ids[] = {
{ .compatible = "nxp,imx8mp-fspi", .data = (void *)&imx8mm_data, },
{ .compatible = "nxp,imx8qxp-fspi", .data = (void *)&imx8qxp_data, },
{ .compatible = "nxp,imx8dxl-fspi", .data = (void *)&imx8dxl_data, },
{ .compatible = "nxp,imx8ulp-fspi", .data = (void *)&imx8ulp_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, nxp_fspi_dt_ids);
......
......@@ -20,23 +20,21 @@
* during SPI transfers by setting max_speed_hz via the device tree.
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/io.h>
#include <asm/dcr.h>
#include <asm/dcr-regs.h>
......@@ -412,7 +410,11 @@ static int spi_ppc4xx_of_probe(struct platform_device *op)
}
/* Request IRQ */
hw->irqnum = irq_of_parse_and_map(np, 0);
ret = platform_get_irq(op, 0);
if (ret < 0)
goto free_host;
hw->irqnum = ret;
ret = request_irq(hw->irqnum, spi_ppc4xx_int,
0, "spi_ppc4xx_of", (void *)hw);
if (ret) {
......
......@@ -198,9 +198,16 @@ static int __maybe_unused rpcif_spi_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(rpcif_spi_pm_ops, rpcif_spi_suspend, rpcif_spi_resume);
static const struct platform_device_id rpc_if_spi_id_table[] = {
{ .name = "rpc-if-spi" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, rpc_if_spi_id_table);
static struct platform_driver rpcif_spi_driver = {
.probe = rpcif_spi_probe,
.remove_new = rpcif_spi_remove,
.id_table = rpc_if_spi_id_table,
.driver = {
.name = "rpc-if-spi",
#ifdef CONFIG_PM_SLEEP
......
......@@ -1637,6 +1637,7 @@ static const struct platform_device_id s3c64xx_spi_driver_ids[] = {
},
{ },
};
MODULE_DEVICE_TABLE(platform, s3c64xx_spi_driver_ids);
static const struct of_device_id s3c64xx_spi_dt_match[] = {
{ .compatible = "google,gs101-spi",
......
......@@ -69,7 +69,7 @@ struct mtk_spi_slave {
struct clk *spi_clk;
struct completion xfer_done;
struct spi_transfer *cur_transfer;
bool slave_aborted;
bool target_aborted;
const struct mtk_spi_compatible *dev_comp;
};
......@@ -118,7 +118,7 @@ static void mtk_spi_slave_disable_xfer(struct mtk_spi_slave *mdata)
static int mtk_spi_slave_wait_for_completion(struct mtk_spi_slave *mdata)
{
if (wait_for_completion_interruptible(&mdata->xfer_done) ||
mdata->slave_aborted) {
mdata->target_aborted) {
dev_err(mdata->dev, "interrupted\n");
return -EINTR;
}
......@@ -286,7 +286,7 @@ static int mtk_spi_slave_transfer_one(struct spi_controller *ctlr,
struct mtk_spi_slave *mdata = spi_controller_get_devdata(ctlr);
reinit_completion(&mdata->xfer_done);
mdata->slave_aborted = false;
mdata->target_aborted = false;
mdata->cur_transfer = xfer;
if (xfer->len > mdata->dev_comp->max_fifo_size)
......@@ -314,11 +314,11 @@ static int mtk_spi_slave_setup(struct spi_device *spi)
return 0;
}
static int mtk_slave_abort(struct spi_controller *ctlr)
static int mtk_target_abort(struct spi_controller *ctlr)
{
struct mtk_spi_slave *mdata = spi_controller_get_devdata(ctlr);
mdata->slave_aborted = true;
mdata->target_aborted = true;
complete(&mdata->xfer_done);
return 0;
......@@ -402,7 +402,7 @@ static int mtk_spi_slave_probe(struct platform_device *pdev)
ctlr->prepare_message = mtk_spi_slave_prepare_message;
ctlr->transfer_one = mtk_spi_slave_transfer_one;
ctlr->setup = mtk_spi_slave_setup;
ctlr->slave_abort = mtk_slave_abort;
ctlr->target_abort = mtk_target_abort;
of_id = of_match_node(mtk_spi_slave_of_match, pdev->dev.of_node);
if (!of_id) {
......
......@@ -136,7 +136,7 @@ static void spi_slave_system_control_remove(struct spi_device *spi)
{
struct spi_slave_system_control_priv *priv = spi_get_drvdata(spi);
spi_slave_abort(spi);
spi_target_abort(spi);
wait_for_completion(&priv->finished);
}
......
......@@ -110,7 +110,7 @@ static void spi_slave_time_remove(struct spi_device *spi)
{
struct spi_slave_time_priv *priv = spi_get_drvdata(spi);
spi_slave_abort(spi);
spi_target_abort(spi);
wait_for_completion(&priv->finished);
}
......
......@@ -448,12 +448,10 @@ static int wpcm_fiu_probe(struct platform_device *pdev)
fiu = spi_controller_get_devdata(ctrl);
fiu->dev = dev;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control");
fiu->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(fiu->regs)) {
dev_err(dev, "Failed to map registers\n");
return PTR_ERR(fiu->regs);
}
fiu->regs = devm_platform_ioremap_resource_byname(pdev, "control");
if (IS_ERR(fiu->regs))
return dev_err_probe(dev, PTR_ERR(fiu->regs),
"Failed to map registers\n");
fiu->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(fiu->clk))
......@@ -462,10 +460,9 @@ static int wpcm_fiu_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory");
fiu->memory = devm_ioremap_resource(dev, res);
fiu->memory_size = min_t(size_t, resource_size(res), MAX_MEMORY_SIZE_TOTAL);
if (IS_ERR(fiu->memory)) {
dev_err(dev, "Failed to map flash memory window\n");
return PTR_ERR(fiu->memory);
}
if (IS_ERR(fiu->memory))
return dev_err_probe(dev, PTR_ERR(fiu->memory),
"Failed to map flash memory window\n");
fiu->shm_regmap = syscon_regmap_lookup_by_phandle_optional(dev->of_node, "nuvoton,shm");
......
......@@ -569,7 +569,7 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem,
}
if (op->dummy.nbytes) {
tmpbuf = kzalloc(op->dummy.nbytes, GFP_KERNEL);
tmpbuf = kmalloc(op->dummy.nbytes, GFP_KERNEL);
if (!tmpbuf)
return -ENOMEM;
......
......@@ -1242,7 +1242,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
u32 num_cs;
const struct qspi_platform_data *p_data;
ctlr = spi_alloc_host(&pdev->dev, sizeof(*xqspi));
ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*xqspi));
if (!ctlr)
return -ENOMEM;
......@@ -1256,30 +1256,22 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
xqspi->has_tapdelay = true;
xqspi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(xqspi->regs)) {
ret = PTR_ERR(xqspi->regs);
goto remove_ctlr;
}
if (IS_ERR(xqspi->regs))
return PTR_ERR(xqspi->regs);
xqspi->pclk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(xqspi->pclk)) {
dev_err(dev, "pclk clock not found.\n");
ret = PTR_ERR(xqspi->pclk);
goto remove_ctlr;
}
if (IS_ERR(xqspi->pclk))
return dev_err_probe(dev, PTR_ERR(xqspi->pclk),
"pclk clock not found.\n");
xqspi->refclk = devm_clk_get(&pdev->dev, "ref_clk");
if (IS_ERR(xqspi->refclk)) {
dev_err(dev, "ref_clk clock not found.\n");
ret = PTR_ERR(xqspi->refclk);
goto remove_ctlr;
}
if (IS_ERR(xqspi->refclk))
return dev_err_probe(dev, PTR_ERR(xqspi->refclk),
"ref_clk clock not found.\n");
ret = clk_prepare_enable(xqspi->pclk);
if (ret) {
dev_err(dev, "Unable to enable APB clock.\n");
goto remove_ctlr;
}
if (ret)
return dev_err_probe(dev, ret, "Unable to enable APB clock.\n");
ret = clk_prepare_enable(xqspi->refclk);
if (ret) {
......@@ -1364,8 +1356,6 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
clk_disable_unprepare(xqspi->refclk);
clk_dis_pclk:
clk_disable_unprepare(xqspi->pclk);
remove_ctlr:
spi_controller_put(ctlr);
return ret;
}
......
......@@ -1440,7 +1440,7 @@ static int spi_transfer_wait(struct spi_controller *ctlr,
u32 speed_hz = xfer->speed_hz;
unsigned long long ms;
if (spi_controller_is_slave(ctlr)) {
if (spi_controller_is_target(ctlr)) {
if (wait_for_completion_interruptible(&ctlr->xfer_completion)) {
dev_dbg(&msg->spi->dev, "SPI transfer interrupted\n");
return -EINTR;
......@@ -2425,7 +2425,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
}
}
if (spi_controller_is_slave(ctlr)) {
if (spi_controller_is_target(ctlr)) {
if (!of_node_name_eq(nc, "slave")) {
dev_err(&ctlr->dev, "%pOF is not called 'slave'\n",
nc);
......@@ -2934,21 +2934,10 @@ static struct class spi_master_class = {
#ifdef CONFIG_SPI_SLAVE
/**
* spi_slave_abort - abort the ongoing transfer request on an SPI slave
* spi_target_abort - abort the ongoing transfer request on an SPI slave
* controller
* @spi: device used for the current transfer
*/
int spi_slave_abort(struct spi_device *spi)
{
struct spi_controller *ctlr = spi->controller;
if (spi_controller_is_slave(ctlr) && ctlr->slave_abort)
return ctlr->slave_abort(ctlr);
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(spi_slave_abort);
int spi_target_abort(struct spi_device *spi)
{
struct spi_controller *ctlr = spi->controller;
......@@ -3321,7 +3310,7 @@ int spi_register_controller(struct spi_controller *ctlr)
*/
dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num);
if (!spi_controller_is_slave(ctlr) && ctlr->use_gpio_descriptors) {
if (!spi_controller_is_target(ctlr) && ctlr->use_gpio_descriptors) {
status = spi_get_gpio_descs(ctlr);
if (status)
goto free_bus_id;
......@@ -3349,7 +3338,7 @@ int spi_register_controller(struct spi_controller *ctlr)
if (status < 0)
goto free_bus_id;
dev_dbg(dev, "registered %s %s\n",
spi_controller_is_slave(ctlr) ? "slave" : "master",
spi_controller_is_target(ctlr) ? "target" : "host",
dev_name(&ctlr->dev));
/*
......@@ -3921,6 +3910,12 @@ int spi_setup(struct spi_device *spi)
(SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL |
SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL)))
return -EINVAL;
/* Check against conflicting MOSI idle configuration */
if ((spi->mode & SPI_MOSI_IDLE_LOW) && (spi->mode & SPI_MOSI_IDLE_HIGH)) {
dev_err(&spi->dev,
"setup: MOSI configured to idle low and high at the same time.\n");
return -EINVAL;
}
/*
* Help drivers fail *cleanly* when they need options
* that aren't supported with their current controller.
......
......@@ -666,7 +666,7 @@ static int spidev_release(struct inode *inode, struct file *filp)
}
#ifdef CONFIG_SPI_SLAVE
if (!dofree)
spi_slave_abort(spidev->spi);
spi_target_abort(spidev->spi);
#endif
mutex_unlock(&device_list_lock);
......
......@@ -498,7 +498,6 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
* controller has native support for memory like operations.
* @mem_caps: controller capabilities for the handling of memory operations.
* @unprepare_message: undo any work done by prepare_message().
* @slave_abort: abort the ongoing transfer request on an SPI slave controller
* @target_abort: abort the ongoing transfer request on an SPI target controller
* @cs_gpiods: Array of GPIO descriptors to use as chip select lines; one per CS
* number. Any individual value may be NULL for CS lines that
......@@ -725,10 +724,7 @@ struct spi_controller {
struct spi_message *message);
int (*unprepare_message)(struct spi_controller *ctlr,
struct spi_message *message);
union {
int (*slave_abort)(struct spi_controller *ctlr);
int (*target_abort)(struct spi_controller *ctlr);
};
int (*target_abort)(struct spi_controller *ctlr);
/*
* These hooks are for drivers that use a generic implementation
......@@ -802,11 +798,6 @@ static inline void spi_controller_put(struct spi_controller *ctlr)
put_device(&ctlr->dev);
}
static inline bool spi_controller_is_slave(struct spi_controller *ctlr)
{
return IS_ENABLED(CONFIG_SPI_SLAVE) && ctlr->slave;
}
static inline bool spi_controller_is_target(struct spi_controller *ctlr)
{
return IS_ENABLED(CONFIG_SPI_SLAVE) && ctlr->target;
......@@ -1296,7 +1287,6 @@ extern int devm_spi_optimize_message(struct device *dev, struct spi_device *spi,
extern int spi_setup(struct spi_device *spi);
extern int spi_async(struct spi_device *spi, struct spi_message *message);
extern int spi_slave_abort(struct spi_device *spi);
extern int spi_target_abort(struct spi_device *spi);
static inline size_t
......
......@@ -24,6 +24,7 @@ struct spi_bitbang {
#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */
#define BITBANG_CS_INACTIVE 0
void (*set_mosi_idle)(struct spi_device *spi);
/* txrx_bufs() may handle dma mapping for transfers that don't
* already have one (transfer.{tx,rx}_dma is zero), or use PIO
*/
......
......@@ -28,7 +28,8 @@
#define SPI_RX_OCTAL _BITUL(14) /* receive with 8 wires */
#define SPI_3WIRE_HIZ _BITUL(15) /* high impedance turnaround */
#define SPI_RX_CPHA_FLIP _BITUL(16) /* flip CPHA on Rx only xfer */
#define SPI_MOSI_IDLE_LOW _BITUL(17) /* leave mosi line low when idle */
#define SPI_MOSI_IDLE_LOW _BITUL(17) /* leave MOSI line low when idle */
#define SPI_MOSI_IDLE_HIGH _BITUL(18) /* leave MOSI line high when idle */
/*
* All the bits defined above should be covered by SPI_MODE_USER_MASK.
......@@ -38,6 +39,6 @@
* These bits must not overlap. A static assert check should make sure of that.
* If adding extra bits, make sure to increase the bit index below as well.
*/
#define SPI_MODE_USER_MASK (_BITUL(18) - 1)
#define SPI_MODE_USER_MASK (_BITUL(19) - 1)
#endif /* _UAPI_SPI_H */
......@@ -99,7 +99,7 @@ static void dumpstat(const char *name, int fd)
return;
}
printf("%s: spi mode 0x%x, %d bits %sper word, %d Hz max\n",
printf("%s: spi mode 0x%x, %d bits %sper word, %u Hz max\n",
name, mode, bits, lsb ? "(lsb first) " : "", speed);
}
......
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