Commit 2bca25ea authored by Linus Torvalds's avatar Linus Torvalds

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

Pull spi updates from Mark Brown:
 "With the exception of some refactoring to fix long standing issues
  where we weren't handling cache syncs properly for messages which had
  PIO and DMA transfers going to the same page correctly there has been
  no work on the core this time around, and it's also been quite a quiet
  release for the drivers too:

   - Fix cache syncs for cases where we have DMA and PIO transfers in
     the same message going to the same page

   - Update the fsl_spi driver to use transfer_one() rather than a
     custom transfer function

   - Support for configuring transfer speeds with the AMD SPI controller

   - Support for a second chip select and 64K erase on Intel SPI

   - Support for Microchip coreQSPI, Nuvoton NPCM845, NXP i.MX93, and
     Rockchip RK3128 and RK3588"

* tag 'spi-v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (73 commits)
  spi: Ensure that sg_table won't be used after being freed
  spi: spi-gxp: Use devm_platform_ioremap_resource()
  spi: s3c64xx: Fix large transfers with DMA
  spi: Split transfers larger than max size
  spi: Fix cache corruption due to DMA/PIO overlap
  spi: Save current RX and TX DMA devices
  spi: mt65xx: Add dma max segment size declaration
  spi: migrate mt7621 text bindings to YAML
  spi: renesas,sh-msiof: Add r8a779g0 support
  spi: spi-fsl-qspi: Use devm_platform_ioremap_resource_byname()
  spi: spi-fsl-lpspi: Use devm_platform_get_and_ioremap_resource()
  spi: spi-fsl-dspi: Use devm_platform_get_and_ioremap_resource()
  spi/omap100k:Fix PM disable depth imbalance in omap1_spi100k_probe
  spi: dw: Fix PM disable depth imbalance in dw_spi_bt1_probe
  spi: cadence-quadspi: Fix PM disable depth imbalance in cqspi_probe
  spi: s3c24xx: Switch to use devm_spi_alloc_master()
  spi: xilinx: Switch to use devm_spi_alloc_master()
  spi: img-spfi: using pm_runtime_resume_and_get instead of pm_runtime_get_sync
  spi: aspeed: Remove redundant dev_err call
  spi: spi-mpc52xx: switch to using gpiod API
  ...
parents d40c8745 8e9204cd
...@@ -23,6 +23,8 @@ properties: ...@@ -23,6 +23,8 @@ properties:
reg: true reg: true
reset-gpios: true reset-gpios: true
spi-3wire: true
required: required:
- compatible - compatible
- power-supply - power-supply
......
...@@ -24,6 +24,8 @@ properties: ...@@ -24,6 +24,8 @@ properties:
reg: true reg: true
reset-gpios: true reset-gpios: true
spi-3wire: true
required: required:
- compatible - compatible
- power-supply - power-supply
......
...@@ -24,6 +24,10 @@ properties: ...@@ -24,6 +24,10 @@ properties:
default-brightness: true default-brightness: true
max-brightness: true max-brightness: true
spi-3wire: true
spi-cpha: true
spi-cpol: true
vdd3-supply: vdd3-supply:
description: VDD regulator description: VDD regulator
......
...@@ -4,7 +4,11 @@ ...@@ -4,7 +4,11 @@
$id: http://devicetree.org/schemas/spi/microchip,mpfs-spi.yaml# $id: http://devicetree.org/schemas/spi/microchip,mpfs-spi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip MPFS {Q,}SPI Controller Device Tree Bindings title: Microchip FPGA {Q,}SPI Controllers
description:
SPI and QSPI controllers on Microchip PolarFire SoC and the "soft"/
fabric IP cores they are based on
maintainers: maintainers:
- Conor Dooley <conor.dooley@microchip.com> - Conor Dooley <conor.dooley@microchip.com>
...@@ -14,9 +18,12 @@ allOf: ...@@ -14,9 +18,12 @@ allOf:
properties: properties:
compatible: compatible:
enum: oneOf:
- microchip,mpfs-spi - items:
- microchip,mpfs-qspi - const: microchip,mpfs-qspi
- const: microchip,coreqspi-rtl-v2
- const: microchip,coreqspi-rtl-v2 #FPGA QSPI
- const: microchip,mpfs-spi
reg: reg:
maxItems: 1 maxItems: 1
......
...@@ -3,7 +3,8 @@ Nuvoton NPCM Peripheral Serial Peripheral Interface(PSPI) controller driver ...@@ -3,7 +3,8 @@ Nuvoton NPCM Peripheral Serial Peripheral Interface(PSPI) controller driver
Nuvoton NPCM7xx SOC support two PSPI channels. Nuvoton NPCM7xx SOC support two PSPI channels.
Required properties: Required properties:
- compatible : "nuvoton,npcm750-pspi" for NPCM7XX BMC - compatible : "nuvoton,npcm750-pspi" for Poleg NPCM7XX.
"nuvoton,npcm845-pspi" for Arbel NPCM8XX.
- #address-cells : should be 1. see spi-bus.txt - #address-cells : should be 1. see spi-bus.txt
- #size-cells : should be 0. see spi-bus.txt - #size-cells : should be 0. see spi-bus.txt
- specifies physical base address and size of the register. - specifies physical base address and size of the register.
......
...@@ -29,5 +29,4 @@ properties: ...@@ -29,5 +29,4 @@ properties:
minimum: 0 minimum: 0
maximum: 255 maximum: 255
unevaluatedProperties: true additionalProperties: true
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/ralink,mt7621-spi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
maintainers:
- Sergio Paracuellos <sergio.paracuellos@gmail.com>
title: Mediatek MT7621/MT7628 SPI controller
allOf:
- $ref: /schemas/spi/spi-controller.yaml#
properties:
compatible:
const: ralink,mt7621-spi
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: spi
resets:
maxItems: 1
reset-names:
const: spi
required:
- compatible
- reg
- resets
- "#address-cells"
- "#size-cells"
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/mt7621-clk.h>
#include <dt-bindings/reset/mt7621-reset.h>
spi@b00 {
compatible = "ralink,mt7621-spi";
reg = <0xb00 0x100>;
clocks = <&sysc MT7621_CLK_SPI>;
clock-names = "spi";
resets = <&sysc MT7621_RST_SPI>;
reset-names = "spi";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&spi_pins>;
};
...@@ -47,9 +47,15 @@ properties: ...@@ -47,9 +47,15 @@ properties:
- renesas,msiof-r8a77980 # R-Car V3H - renesas,msiof-r8a77980 # R-Car V3H
- renesas,msiof-r8a77990 # R-Car E3 - renesas,msiof-r8a77990 # R-Car E3
- renesas,msiof-r8a77995 # R-Car D3 - renesas,msiof-r8a77995 # R-Car D3
- renesas,msiof-r8a779a0 # R-Car V3U
- const: renesas,rcar-gen3-msiof # generic R-Car Gen3 and RZ/G2 - const: renesas,rcar-gen3-msiof # generic R-Car Gen3 and RZ/G2
# compatible device # compatible device
- items:
- enum:
- renesas,msiof-r8a779a0 # R-Car V3U
- renesas,msiof-r8a779f0 # R-Car S4-8
- renesas,msiof-r8a779g0 # R-Car V4H
- const: renesas,rcar-gen4-msiof # generic R-Car Gen4
# compatible device
- items: - items:
- const: renesas,sh-msiof # deprecated - const: renesas,sh-msiof # deprecated
...@@ -69,6 +75,12 @@ properties: ...@@ -69,6 +75,12 @@ properties:
clocks: clocks:
maxItems: 1 maxItems: 1
power-domains:
maxItems: 1
resets:
maxItems: 1
num-cs: num-cs:
description: | description: |
Total number of chip selects (default is 1). Total number of chip selects (default is 1).
......
...@@ -104,7 +104,6 @@ properties: ...@@ -104,7 +104,6 @@ properties:
const: spi const: spi
reg-io-width: reg-io-width:
$ref: /schemas/types.yaml#/definitions/uint32
description: I/O register width (in bytes) implemented by this device description: I/O register width (in bytes) implemented by this device
default: 4 default: 4
enum: [ 2, 4 ] enum: [ 2, 4 ]
......
...@@ -96,6 +96,11 @@ patternProperties: ...@@ -96,6 +96,11 @@ patternProperties:
$ref: spi-peripheral-props.yaml $ref: spi-peripheral-props.yaml
properties: properties:
spi-3wire:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires 3-wire mode.
spi-cpha: spi-cpha:
$ref: /schemas/types.yaml#/definitions/flag $ref: /schemas/types.yaml#/definitions/flag
description: description:
......
...@@ -19,7 +19,9 @@ properties: ...@@ -19,7 +19,9 @@ properties:
- fsl,imx7ulp-spi - fsl,imx7ulp-spi
- fsl,imx8qxp-spi - fsl,imx8qxp-spi
- items: - items:
- const: fsl,imx8ulp-spi - enum:
- fsl,imx8ulp-spi
- fsl,imx93-spi
- const: fsl,imx7ulp-spi - const: fsl,imx7ulp-spi
reg: reg:
maxItems: 1 maxItems: 1
...@@ -37,6 +39,16 @@ properties: ...@@ -37,6 +39,16 @@ properties:
- const: per - const: per
- const: ipg - const: ipg
dmas:
items:
- description: TX DMA Channel
- description: RX DMA Channel
dma-names:
items:
- const: tx
- const: rx
fsl,spi-only-use-cs1-sel: fsl,spi-only-use-cs1-sel:
description: description:
spi common code does not support use of CS signals discontinuously. spi common code does not support use of CS signals discontinuously.
......
Binding for MTK SPI controller (MT7621 MIPS)
Required properties:
- compatible: Should be one of the following:
- "ralink,mt7621-spi": for mt7621/mt7628/mt7688 platforms
- #address-cells: should be 1.
- #size-cells: should be 0.
- reg: Address and length of the register set for the device
- resets: phandle to the reset controller asserting this device in
reset
See ../reset/reset.txt for details.
Optional properties:
- cs-gpios: see spi-bus.txt.
Example:
- SoC Specific Portion:
spi0: spi@b00 {
compatible = "ralink,mt7621-spi";
reg = <0xb00 0x100>;
#address-cells = <1>;
#size-cells = <0>;
resets = <&rstctrl 18>;
reset-names = "spi";
};
...@@ -29,11 +29,6 @@ properties: ...@@ -29,11 +29,6 @@ properties:
description: description:
Chip select used by the device. Chip select used by the device.
spi-3wire:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires 3-wire mode.
spi-cs-high: spi-cs-high:
$ref: /schemas/types.yaml#/definitions/flag $ref: /schemas/types.yaml#/definitions/flag
description: description:
......
...@@ -27,6 +27,7 @@ properties: ...@@ -27,6 +27,7 @@ properties:
- items: - items:
- enum: - enum:
- rockchip,px30-spi - rockchip,px30-spi
- rockchip,rk3128-spi
- rockchip,rk3188-spi - rockchip,rk3188-spi
- rockchip,rk3288-spi - rockchip,rk3288-spi
- rockchip,rk3308-spi - rockchip,rk3308-spi
...@@ -34,6 +35,7 @@ properties: ...@@ -34,6 +35,7 @@ properties:
- rockchip,rk3368-spi - rockchip,rk3368-spi
- rockchip,rk3399-spi - rockchip,rk3399-spi
- rockchip,rk3568-spi - rockchip,rk3568-spi
- rockchip,rk3588-spi
- rockchip,rv1126-spi - rockchip,rv1126-spi
- const: rockchip,rk3066-spi - const: rockchip,rk3066-spi
...@@ -80,6 +82,9 @@ properties: ...@@ -80,6 +82,9 @@ properties:
where the "sleep" configuration may describe the state where the "sleep" configuration may describe the state
the pins should be in during system suspend. the pins should be in during system suspend.
power-domains:
maxItems: 1
required: required:
- compatible - compatible
- reg - reg
......
...@@ -17568,6 +17568,7 @@ F: drivers/mailbox/mailbox-mpfs.c ...@@ -17568,6 +17568,7 @@ F: drivers/mailbox/mailbox-mpfs.c
F: drivers/pci/controller/pcie-microchip-host.c F: drivers/pci/controller/pcie-microchip-host.c
F: drivers/rtc/rtc-mpfs.c F: drivers/rtc/rtc-mpfs.c
F: drivers/soc/microchip/ F: drivers/soc/microchip/
F: drivers/spi/spi-microchip-core-qspi.c
F: drivers/spi/spi-microchip-core.c F: drivers/spi/spi-microchip-core.c
F: drivers/usb/musb/mpfs.c F: drivers/usb/musb/mpfs.c
F: include/soc/microchip/mpfs.h F: include/soc/microchip/mpfs.h
......
...@@ -591,6 +591,15 @@ config SPI_MICROCHIP_CORE ...@@ -591,6 +591,15 @@ config SPI_MICROCHIP_CORE
PolarFire SoC. PolarFire SoC.
If built as a module, it will be called spi-microchip-core. If built as a module, it will be called spi-microchip-core.
config SPI_MICROCHIP_CORE_QSPI
tristate "Microchip FPGA QSPI controllers"
depends on SPI_MASTER
help
This enables the QSPI driver for Microchip FPGA QSPI controllers.
Say Y or M here if you want to use the QSPI controllers on
PolarFire SoC.
If built as a module, it will be called spi-microchip-core-qspi.
config SPI_MT65XX config SPI_MT65XX
tristate "MediaTek SPI controller" tristate "MediaTek SPI controller"
depends on ARCH_MEDIATEK || COMPILE_TEST depends on ARCH_MEDIATEK || COMPILE_TEST
......
...@@ -73,6 +73,7 @@ obj-$(CONFIG_SPI_LP8841_RTC) += spi-lp8841-rtc.o ...@@ -73,6 +73,7 @@ obj-$(CONFIG_SPI_LP8841_RTC) += spi-lp8841-rtc.o
obj-$(CONFIG_SPI_MESON_SPICC) += spi-meson-spicc.o obj-$(CONFIG_SPI_MESON_SPICC) += spi-meson-spicc.o
obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o
obj-$(CONFIG_SPI_MICROCHIP_CORE) += spi-microchip-core.o obj-$(CONFIG_SPI_MICROCHIP_CORE) += spi-microchip-core.o
obj-$(CONFIG_SPI_MICROCHIP_CORE_QSPI) += spi-microchip-core-qspi.o
obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
......
...@@ -36,9 +36,17 @@ ...@@ -36,9 +36,17 @@
#define AMD_SPI_FIFO_SIZE 70 #define AMD_SPI_FIFO_SIZE 70
#define AMD_SPI_MEM_SIZE 200 #define AMD_SPI_MEM_SIZE 200
/* M_CMD OP codes for SPI */ #define AMD_SPI_ENA_REG 0x20
#define AMD_SPI_XFER_TX 1 #define AMD_SPI_ALT_SPD_SHIFT 20
#define AMD_SPI_XFER_RX 2 #define AMD_SPI_ALT_SPD_MASK GENMASK(23, AMD_SPI_ALT_SPD_SHIFT)
#define AMD_SPI_SPI100_SHIFT 0
#define AMD_SPI_SPI100_MASK GENMASK(AMD_SPI_SPI100_SHIFT, AMD_SPI_SPI100_SHIFT)
#define AMD_SPI_SPEED_REG 0x6C
#define AMD_SPI_SPD7_SHIFT 8
#define AMD_SPI_SPD7_MASK GENMASK(13, AMD_SPI_SPD7_SHIFT)
#define AMD_SPI_MAX_HZ 100000000
#define AMD_SPI_MIN_HZ 800000
/** /**
* enum amd_spi_versions - SPI controller versions * enum amd_spi_versions - SPI controller versions
...@@ -50,14 +58,41 @@ enum amd_spi_versions { ...@@ -50,14 +58,41 @@ enum amd_spi_versions {
AMD_SPI_V2, AMD_SPI_V2,
}; };
enum amd_spi_speed {
F_66_66MHz,
F_33_33MHz,
F_22_22MHz,
F_16_66MHz,
F_100MHz,
F_800KHz,
SPI_SPD7,
F_50MHz = 0x4,
F_4MHz = 0x32,
F_3_17MHz = 0x3F
};
/**
* struct amd_spi_freq - Matches device speed with values to write in regs
* @speed_hz: Device frequency
* @enable_val: Value to be written to "enable register"
* @spd7_val: Some frequencies requires to have a value written at SPISPEED register
*/
struct amd_spi_freq {
u32 speed_hz;
u32 enable_val;
u32 spd7_val;
};
/** /**
* struct amd_spi - SPI driver instance * struct amd_spi - SPI driver instance
* @io_remap_addr: Start address of the SPI controller registers * @io_remap_addr: Start address of the SPI controller registers
* @version: SPI controller hardware version * @version: SPI controller hardware version
* @speed_hz: Device frequency
*/ */
struct amd_spi { struct amd_spi {
void __iomem *io_remap_addr; void __iomem *io_remap_addr;
enum amd_spi_versions version; enum amd_spi_versions version;
unsigned int speed_hz;
}; };
static inline u8 amd_spi_readreg8(struct amd_spi *amd_spi, int idx) static inline u8 amd_spi_readreg8(struct amd_spi *amd_spi, int idx)
...@@ -189,65 +224,125 @@ static int amd_spi_master_setup(struct spi_device *spi) ...@@ -189,65 +224,125 @@ static int amd_spi_master_setup(struct spi_device *spi)
return 0; return 0;
} }
static const struct amd_spi_freq amd_spi_freq[] = {
{ AMD_SPI_MAX_HZ, F_100MHz, 0},
{ 66660000, F_66_66MHz, 0},
{ 50000000, SPI_SPD7, F_50MHz},
{ 33330000, F_33_33MHz, 0},
{ 22220000, F_22_22MHz, 0},
{ 16660000, F_16_66MHz, 0},
{ 4000000, SPI_SPD7, F_4MHz},
{ 3170000, SPI_SPD7, F_3_17MHz},
{ AMD_SPI_MIN_HZ, F_800KHz, 0},
};
static int amd_set_spi_freq(struct amd_spi *amd_spi, u32 speed_hz)
{
unsigned int i, spd7_val, alt_spd;
if (speed_hz < AMD_SPI_MIN_HZ)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(amd_spi_freq); i++)
if (speed_hz >= amd_spi_freq[i].speed_hz)
break;
if (amd_spi->speed_hz == amd_spi_freq[i].speed_hz)
return 0;
amd_spi->speed_hz = amd_spi_freq[i].speed_hz;
alt_spd = (amd_spi_freq[i].enable_val << AMD_SPI_ALT_SPD_SHIFT)
& AMD_SPI_ALT_SPD_MASK;
amd_spi_setclear_reg32(amd_spi, AMD_SPI_ENA_REG, alt_spd,
AMD_SPI_ALT_SPD_MASK);
if (amd_spi->speed_hz == AMD_SPI_MAX_HZ)
amd_spi_setclear_reg32(amd_spi, AMD_SPI_ENA_REG, 1,
AMD_SPI_SPI100_MASK);
if (amd_spi_freq[i].spd7_val) {
spd7_val = (amd_spi_freq[i].spd7_val << AMD_SPI_SPD7_SHIFT)
& AMD_SPI_SPD7_MASK;
amd_spi_setclear_reg32(amd_spi, AMD_SPI_SPEED_REG, spd7_val,
AMD_SPI_SPD7_MASK);
}
return 0;
}
static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi, static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
struct spi_master *master, struct spi_master *master,
struct spi_message *message) struct spi_message *message)
{ {
struct spi_transfer *xfer = NULL; struct spi_transfer *xfer = NULL;
u8 cmd_opcode; struct spi_device *spi = message->spi;
u8 cmd_opcode = 0, fifo_pos = AMD_SPI_FIFO_BASE;
u8 *buf = NULL; u8 *buf = NULL;
u32 m_cmd = 0;
u32 i = 0; u32 i = 0;
u32 tx_len = 0, rx_len = 0; u32 tx_len = 0, rx_len = 0;
list_for_each_entry(xfer, &message->transfers, list_for_each_entry(xfer, &message->transfers,
transfer_list) { transfer_list) {
if (xfer->rx_buf) if (xfer->speed_hz)
m_cmd = AMD_SPI_XFER_RX; amd_set_spi_freq(amd_spi, xfer->speed_hz);
if (xfer->tx_buf) else
m_cmd = AMD_SPI_XFER_TX; amd_set_spi_freq(amd_spi, spi->max_speed_hz);
if (m_cmd & AMD_SPI_XFER_TX) { if (xfer->tx_buf) {
buf = (u8 *)xfer->tx_buf; buf = (u8 *)xfer->tx_buf;
tx_len = xfer->len - 1; if (!tx_len) {
cmd_opcode = *(u8 *)xfer->tx_buf; cmd_opcode = *(u8 *)xfer->tx_buf;
buf++; buf++;
amd_spi_set_opcode(amd_spi, cmd_opcode); xfer->len--;
}
tx_len += xfer->len;
/* Write data into the FIFO. */ /* Write data into the FIFO. */
for (i = 0; i < tx_len; i++) { for (i = 0; i < xfer->len; i++)
iowrite8(buf[i], ((u8 __iomem *)amd_spi->io_remap_addr + amd_spi_writereg8(amd_spi, fifo_pos + i, buf[i]);
AMD_SPI_FIFO_BASE + i));
}
amd_spi_set_tx_count(amd_spi, tx_len); fifo_pos += xfer->len;
amd_spi_clear_fifo_ptr(amd_spi);
/* Execute command */
amd_spi_execute_opcode(amd_spi);
}
if (m_cmd & AMD_SPI_XFER_RX) {
/*
* Store no. of bytes to be received from
* FIFO
*/
rx_len = xfer->len;
buf = (u8 *)xfer->rx_buf;
amd_spi_set_rx_count(amd_spi, rx_len);
amd_spi_clear_fifo_ptr(amd_spi);
/* Execute command */
amd_spi_execute_opcode(amd_spi);
amd_spi_busy_wait(amd_spi);
/* Read data from FIFO to receive buffer */
for (i = 0; i < rx_len; i++)
buf[i] = amd_spi_readreg8(amd_spi, AMD_SPI_FIFO_BASE + tx_len + i);
} }
/* Store no. of bytes to be received from FIFO */
if (xfer->rx_buf)
rx_len += xfer->len;
}
if (!buf) {
message->status = -EINVAL;
goto fin_msg;
}
amd_spi_set_opcode(amd_spi, cmd_opcode);
amd_spi_set_tx_count(amd_spi, tx_len);
amd_spi_set_rx_count(amd_spi, rx_len);
/* Execute command */
message->status = amd_spi_execute_opcode(amd_spi);
if (message->status)
goto fin_msg;
if (rx_len) {
message->status = amd_spi_busy_wait(amd_spi);
if (message->status)
goto fin_msg;
list_for_each_entry(xfer, &message->transfers, transfer_list)
if (xfer->rx_buf) {
buf = (u8 *)xfer->rx_buf;
/* Read data from FIFO to receive buffer */
for (i = 0; i < xfer->len; i++)
buf[i] = amd_spi_readreg8(amd_spi, fifo_pos + i);
fifo_pos += xfer->len;
}
} }
/* Update statistics */ /* Update statistics */
message->actual_length = tx_len + rx_len + 1; message->actual_length = tx_len + rx_len + 1;
/* complete the transaction */
message->status = 0;
fin_msg:
switch (amd_spi->version) { switch (amd_spi->version) {
case AMD_SPI_V1: case AMD_SPI_V1:
break; break;
...@@ -260,7 +355,7 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi, ...@@ -260,7 +355,7 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
spi_finalize_current_message(master); spi_finalize_current_message(master);
return 0; return message->status;
} }
static int amd_spi_master_transfer(struct spi_master *master, static int amd_spi_master_transfer(struct spi_master *master,
...@@ -275,9 +370,7 @@ static int amd_spi_master_transfer(struct spi_master *master, ...@@ -275,9 +370,7 @@ static int amd_spi_master_transfer(struct spi_master *master,
* Extract spi_transfers from the spi message and * Extract spi_transfers from the spi message and
* program the controller. * program the controller.
*/ */
amd_spi_fifo_xfer(amd_spi, master, msg); return amd_spi_fifo_xfer(amd_spi, master, msg);
return 0;
} }
static size_t amd_spi_max_transfer_size(struct spi_device *spi) static size_t amd_spi_max_transfer_size(struct spi_device *spi)
...@@ -312,6 +405,8 @@ static int amd_spi_probe(struct platform_device *pdev) ...@@ -312,6 +405,8 @@ static int amd_spi_probe(struct platform_device *pdev)
master->num_chipselect = 4; master->num_chipselect = 4;
master->mode_bits = 0; master->mode_bits = 0;
master->flags = SPI_MASTER_HALF_DUPLEX; master->flags = SPI_MASTER_HALF_DUPLEX;
master->max_speed_hz = AMD_SPI_MAX_HZ;
master->min_speed_hz = AMD_SPI_MIN_HZ;
master->setup = amd_spi_master_setup; master->setup = amd_spi_master_setup;
master->transfer_one_message = amd_spi_master_transfer; master->transfer_one_message = amd_spi_master_transfer;
master->max_transfer_size = amd_spi_max_transfer_size; master->max_transfer_size = amd_spi_max_transfer_size;
......
...@@ -736,10 +736,8 @@ static int aspeed_spi_probe(struct platform_device *pdev) ...@@ -736,10 +736,8 @@ static int aspeed_spi_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
aspi->regs = devm_ioremap_resource(dev, res); aspi->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(aspi->regs)) { if (IS_ERR(aspi->regs))
dev_err(dev, "missing AHB register window\n");
return PTR_ERR(aspi->regs); return PTR_ERR(aspi->regs);
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
aspi->ahb_base = devm_ioremap_resource(dev, res); aspi->ahb_base = devm_ioremap_resource(dev, res);
......
...@@ -1645,7 +1645,7 @@ static int cqspi_probe(struct platform_device *pdev) ...@@ -1645,7 +1645,7 @@ static int cqspi_probe(struct platform_device *pdev)
pm_runtime_enable(dev); pm_runtime_enable(dev);
ret = pm_runtime_resume_and_get(dev); ret = pm_runtime_resume_and_get(dev);
if (ret < 0) if (ret < 0)
return ret; goto probe_pm_failed;
ret = clk_prepare_enable(cqspi->clk); ret = clk_prepare_enable(cqspi->clk);
if (ret) { if (ret) {
...@@ -1740,6 +1740,7 @@ static int cqspi_probe(struct platform_device *pdev) ...@@ -1740,6 +1740,7 @@ static int cqspi_probe(struct platform_device *pdev)
clk_disable_unprepare(cqspi->clk); clk_disable_unprepare(cqspi->clk);
probe_clk_failed: probe_clk_failed:
pm_runtime_put_sync(dev); pm_runtime_put_sync(dev);
probe_pm_failed:
pm_runtime_disable(dev); pm_runtime_disable(dev);
return ret; return ret;
} }
......
...@@ -565,10 +565,8 @@ static int cdns_xspi_probe(struct platform_device *pdev) ...@@ -565,10 +565,8 @@ static int cdns_xspi_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sdma"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sdma");
cdns_xspi->sdmabase = devm_ioremap_resource(dev, res); cdns_xspi->sdmabase = devm_ioremap_resource(dev, res);
if (IS_ERR(cdns_xspi->sdmabase)) { if (IS_ERR(cdns_xspi->sdmabase))
dev_err(dev, "Failed to remap SDMA address\n");
return PTR_ERR(cdns_xspi->sdmabase); return PTR_ERR(cdns_xspi->sdmabase);
}
cdns_xspi->sdmasize = resource_size(res); cdns_xspi->sdmasize = resource_size(res);
cdns_xspi->auxbase = devm_platform_ioremap_resource_byname(pdev, "aux"); cdns_xspi->auxbase = devm_platform_ioremap_resource_byname(pdev, "aux");
......
...@@ -293,8 +293,10 @@ static int dw_spi_bt1_probe(struct platform_device *pdev) ...@@ -293,8 +293,10 @@ static int dw_spi_bt1_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
ret = dw_spi_add_host(&pdev->dev, dws); ret = dw_spi_add_host(&pdev->dev, dws);
if (ret) if (ret) {
pm_runtime_disable(&pdev->dev);
goto err_disable_clk; goto err_disable_clk;
}
platform_set_drvdata(pdev, dwsbt1); platform_set_drvdata(pdev, dwsbt1);
......
...@@ -955,7 +955,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -955,7 +955,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
ret = spi_register_controller(master); ret = spi_register_controller(master);
if (ret) { if (ret) {
dev_err(&master->dev, "problem registering spi master\n"); dev_err_probe(dev, ret, "problem registering spi master\n");
goto err_dma_exit; goto err_dma_exit;
} }
......
...@@ -1294,8 +1294,7 @@ static int dspi_probe(struct platform_device *pdev) ...@@ -1294,8 +1294,7 @@ static int dspi_probe(struct platform_device *pdev)
else else
ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base)) { if (IS_ERR(base)) {
ret = PTR_ERR(base); ret = PTR_ERR(base);
goto out_ctlr_put; goto out_ctlr_put;
......
...@@ -855,8 +855,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ...@@ -855,8 +855,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
init_completion(&fsl_lpspi->xfer_done); init_completion(&fsl_lpspi->xfer_done);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); fsl_lpspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
fsl_lpspi->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(fsl_lpspi->base)) { if (IS_ERR(fsl_lpspi->base)) {
ret = PTR_ERR(fsl_lpspi->base); ret = PTR_ERR(fsl_lpspi->base);
goto out_controller_put; goto out_controller_put;
...@@ -912,7 +911,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ...@@ -912,7 +911,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
ret = devm_spi_register_controller(&pdev->dev, controller); ret = devm_spi_register_controller(&pdev->dev, controller);
if (ret < 0) { if (ret < 0) {
dev_err_probe(&pdev->dev, ret, "spi_register_controller error: %i\n", ret); dev_err_probe(&pdev->dev, ret, "spi_register_controller error\n");
goto free_dma; goto free_dma;
} }
...@@ -947,11 +946,8 @@ static int fsl_lpspi_remove(struct platform_device *pdev) ...@@ -947,11 +946,8 @@ static int fsl_lpspi_remove(struct platform_device *pdev)
static int __maybe_unused fsl_lpspi_suspend(struct device *dev) static int __maybe_unused fsl_lpspi_suspend(struct device *dev)
{ {
int ret;
pinctrl_pm_select_sleep_state(dev); pinctrl_pm_select_sleep_state(dev);
ret = pm_runtime_force_suspend(dev); return pm_runtime_force_suspend(dev);
return ret;
} }
static int __maybe_unused fsl_lpspi_resume(struct device *dev) static int __maybe_unused fsl_lpspi_resume(struct device *dev)
......
...@@ -867,8 +867,7 @@ static int fsl_qspi_probe(struct platform_device *pdev) ...@@ -867,8 +867,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, q); platform_set_drvdata(pdev, q);
/* find the resources */ /* find the resources */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI"); q->iobase = devm_platform_ioremap_resource_byname(pdev, "QuadSPI");
q->iobase = devm_ioremap_resource(dev, res);
if (IS_ERR(q->iobase)) { if (IS_ERR(q->iobase)) {
ret = PTR_ERR(q->iobase); ret = PTR_ERR(q->iobase);
goto err_put_ctrl; goto err_put_ctrl;
......
...@@ -111,32 +111,6 @@ static void fsl_spi_change_mode(struct spi_device *spi) ...@@ -111,32 +111,6 @@ static void fsl_spi_change_mode(struct spi_device *spi)
local_irq_restore(flags); local_irq_restore(flags);
} }
static void fsl_spi_chipselect(struct spi_device *spi, int value)
{
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
struct fsl_spi_platform_data *pdata;
struct spi_mpc8xxx_cs *cs = spi->controller_state;
pdata = spi->dev.parent->parent->platform_data;
if (value == BITBANG_CS_INACTIVE) {
if (pdata->cs_control)
pdata->cs_control(spi, false);
}
if (value == BITBANG_CS_ACTIVE) {
mpc8xxx_spi->rx_shift = cs->rx_shift;
mpc8xxx_spi->tx_shift = cs->tx_shift;
mpc8xxx_spi->get_rx = cs->get_rx;
mpc8xxx_spi->get_tx = cs->get_tx;
fsl_spi_change_mode(spi);
if (pdata->cs_control)
pdata->cs_control(spi, true);
}
}
static void fsl_spi_qe_cpu_set_shifts(u32 *rx_shift, u32 *tx_shift, static void fsl_spi_qe_cpu_set_shifts(u32 *rx_shift, u32 *tx_shift,
int bits_per_word, int msb_first) int bits_per_word, int msb_first)
{ {
...@@ -354,15 +328,11 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t, ...@@ -354,15 +328,11 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
return mpc8xxx_spi->count; return mpc8xxx_spi->count;
} }
static int fsl_spi_do_one_msg(struct spi_master *master, static int fsl_spi_prepare_message(struct spi_controller *ctlr,
struct spi_message *m) struct spi_message *m)
{ {
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(ctlr);
struct spi_device *spi = m->spi; struct spi_transfer *t;
struct spi_transfer *t, *first;
unsigned int cs_change;
const int nsecs = 50;
int status, last_bpw;
/* /*
* In CPU mode, optimize large byte transfers to use larger * In CPU mode, optimize large byte transfers to use larger
...@@ -378,62 +348,30 @@ static int fsl_spi_do_one_msg(struct spi_master *master, ...@@ -378,62 +348,30 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
t->bits_per_word = 16; t->bits_per_word = 16;
} }
} }
return 0;
}
/* Don't allow changes if CS is active */ static int fsl_spi_transfer_one(struct spi_controller *controller,
cs_change = 1; struct spi_device *spi,
list_for_each_entry(t, &m->transfers, transfer_list) { struct spi_transfer *t)
if (cs_change) {
first = t; int status;
cs_change = t->cs_change;
if (first->speed_hz != t->speed_hz) {
dev_err(&spi->dev,
"speed_hz cannot change while CS is active\n");
return -EINVAL;
}
}
last_bpw = -1;
cs_change = 1;
status = -EINVAL;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (cs_change || last_bpw != t->bits_per_word)
status = fsl_spi_setup_transfer(spi, t);
if (status < 0)
break;
last_bpw = t->bits_per_word;
if (cs_change) {
fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
ndelay(nsecs);
}
cs_change = t->cs_change;
if (t->len)
status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
if (status) {
status = -EMSGSIZE;
break;
}
m->actual_length += t->len;
spi_transfer_delay_exec(t);
if (cs_change) {
ndelay(nsecs);
fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
ndelay(nsecs);
}
}
m->status = status; status = fsl_spi_setup_transfer(spi, t);
if (status < 0)
return status;
if (t->len)
status = fsl_spi_bufs(spi, t, !!t->tx_dma || !!t->rx_dma);
if (status > 0)
return -EMSGSIZE;
if (status || !cs_change) { return status;
ndelay(nsecs); }
fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
}
fsl_spi_setup_transfer(spi, NULL); static int fsl_spi_unprepare_message(struct spi_controller *controller,
spi_finalize_current_message(master); struct spi_message *msg)
return 0; {
return fsl_spi_setup_transfer(msg->spi, NULL);
} }
static int fsl_spi_setup(struct spi_device *spi) static int fsl_spi_setup(struct spi_device *spi)
...@@ -482,9 +420,6 @@ static int fsl_spi_setup(struct spi_device *spi) ...@@ -482,9 +420,6 @@ static int fsl_spi_setup(struct spi_device *spi)
return retval; return retval;
} }
/* Initialize chipselect - might be active for SPI_CS_HIGH mode */
fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
return 0; return 0;
} }
...@@ -557,9 +492,7 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) ...@@ -557,9 +492,7 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
u32 slvsel; u32 slvsel;
u16 cs = spi->chip_select; u16 cs = spi->chip_select;
if (spi->cs_gpiod) { if (cs < mpc8xxx_spi->native_chipselects) {
gpiod_set_value(spi->cs_gpiod, on);
} else if (cs < mpc8xxx_spi->native_chipselects) {
slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel); slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel);
slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs)); slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs));
mpc8xxx_spi_write_reg(&reg_base->slvsel, slvsel); mpc8xxx_spi_write_reg(&reg_base->slvsel, slvsel);
...@@ -568,7 +501,6 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) ...@@ -568,7 +501,6 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
static void fsl_spi_grlib_probe(struct device *dev) static void fsl_spi_grlib_probe(struct device *dev)
{ {
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base; struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
...@@ -588,7 +520,18 @@ static void fsl_spi_grlib_probe(struct device *dev) ...@@ -588,7 +520,18 @@ static void fsl_spi_grlib_probe(struct device *dev)
mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff); mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff);
} }
master->num_chipselect = mpc8xxx_spi->native_chipselects; master->num_chipselect = mpc8xxx_spi->native_chipselects;
pdata->cs_control = fsl_spi_grlib_cs_control; master->set_cs = fsl_spi_grlib_cs_control;
}
static void fsl_spi_cs_control(struct spi_device *spi, bool on)
{
struct device *dev = spi->dev.parent->parent;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
if (WARN_ON_ONCE(!pinfo->immr_spi_cs))
return;
iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs);
} }
static struct spi_master *fsl_spi_probe(struct device *dev, static struct spi_master *fsl_spi_probe(struct device *dev,
...@@ -613,8 +556,11 @@ static struct spi_master *fsl_spi_probe(struct device *dev, ...@@ -613,8 +556,11 @@ static struct spi_master *fsl_spi_probe(struct device *dev,
master->setup = fsl_spi_setup; master->setup = fsl_spi_setup;
master->cleanup = fsl_spi_cleanup; master->cleanup = fsl_spi_cleanup;
master->transfer_one_message = fsl_spi_do_one_msg; master->prepare_message = fsl_spi_prepare_message;
master->transfer_one = fsl_spi_transfer_one;
master->unprepare_message = fsl_spi_unprepare_message;
master->use_gpio_descriptors = true; master->use_gpio_descriptors = true;
master->set_cs = fsl_spi_cs_control;
mpc8xxx_spi = spi_master_get_devdata(master); mpc8xxx_spi = spi_master_get_devdata(master);
mpc8xxx_spi->max_bits_per_word = 32; mpc8xxx_spi->max_bits_per_word = 32;
...@@ -688,21 +634,6 @@ static struct spi_master *fsl_spi_probe(struct device *dev, ...@@ -688,21 +634,6 @@ static struct spi_master *fsl_spi_probe(struct device *dev,
return ERR_PTR(ret); return ERR_PTR(ret);
} }
static void fsl_spi_cs_control(struct spi_device *spi, bool on)
{
if (spi->cs_gpiod) {
gpiod_set_value(spi->cs_gpiod, on);
} else {
struct device *dev = spi->dev.parent->parent;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
if (WARN_ON_ONCE(!pinfo->immr_spi_cs))
return;
iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs);
}
}
static int of_fsl_spi_probe(struct platform_device *ofdev) static int of_fsl_spi_probe(struct platform_device *ofdev)
{ {
struct device *dev = &ofdev->dev; struct device *dev = &ofdev->dev;
...@@ -744,12 +675,10 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) ...@@ -744,12 +675,10 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
ret = gpiod_count(dev, "cs"); ret = gpiod_count(dev, "cs");
if (ret < 0) if (ret < 0)
ret = 0; ret = 0;
if (ret == 0 && !spisel_boot) { if (ret == 0 && !spisel_boot)
pdata->max_chipselect = 1; pdata->max_chipselect = 1;
} else { else
pdata->max_chipselect = ret + spisel_boot; pdata->max_chipselect = ret + spisel_boot;
pdata->cs_control = fsl_spi_cs_control;
}
} }
ret = of_address_to_resource(np, 0, &mem); ret = of_address_to_resource(np, 0, &mem);
......
...@@ -254,7 +254,6 @@ static int gxp_spifi_probe(struct platform_device *pdev) ...@@ -254,7 +254,6 @@ static int gxp_spifi_probe(struct platform_device *pdev)
const struct gxp_spi_data *data; const struct gxp_spi_data *data;
struct spi_controller *ctlr; struct spi_controller *ctlr;
struct gxp_spi *spifi; struct gxp_spi *spifi;
struct resource *res;
int ret; int ret;
data = of_device_get_match_data(&pdev->dev); data = of_device_get_match_data(&pdev->dev);
...@@ -269,18 +268,15 @@ static int gxp_spifi_probe(struct platform_device *pdev) ...@@ -269,18 +268,15 @@ static int gxp_spifi_probe(struct platform_device *pdev)
spifi->data = data; spifi->data = data;
spifi->dev = dev; spifi->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); spifi->reg_base = devm_platform_ioremap_resource(pdev, 0);
spifi->reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(spifi->reg_base)) if (IS_ERR(spifi->reg_base))
return PTR_ERR(spifi->reg_base); return PTR_ERR(spifi->reg_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); spifi->dat_base = devm_platform_ioremap_resource(pdev, 1);
spifi->dat_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(spifi->dat_base)) if (IS_ERR(spifi->dat_base))
return PTR_ERR(spifi->dat_base); return PTR_ERR(spifi->dat_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2); spifi->dir_base = devm_platform_ioremap_resource(pdev, 2);
spifi->dir_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(spifi->dir_base)) if (IS_ERR(spifi->dir_base))
return PTR_ERR(spifi->dir_base); return PTR_ERR(spifi->dir_base);
......
...@@ -730,11 +730,9 @@ static int img_spfi_resume(struct device *dev) ...@@ -730,11 +730,9 @@ static int img_spfi_resume(struct device *dev)
struct img_spfi *spfi = spi_master_get_devdata(master); struct img_spfi *spfi = spi_master_get_devdata(master);
int ret; int ret;
ret = pm_runtime_get_sync(dev); ret = pm_runtime_resume_and_get(dev);
if (ret < 0) { if (ret < 0)
pm_runtime_put_noidle(dev);
return ret; return ret;
}
spfi_reset(spfi); spfi_reset(spfi);
pm_runtime_put(dev); pm_runtime_put(dev);
......
...@@ -116,6 +116,22 @@ ...@@ -116,6 +116,22 @@
#define ERASE_64K_OPCODE_SHIFT 16 #define ERASE_64K_OPCODE_SHIFT 16
#define ERASE_64K_OPCODE_MASK (0xff << ERASE_OPCODE_SHIFT) #define ERASE_64K_OPCODE_MASK (0xff << ERASE_OPCODE_SHIFT)
/* Flash descriptor fields */
#define FLVALSIG_MAGIC 0x0ff0a55a
#define FLMAP0_NC_MASK GENMASK(9, 8)
#define FLMAP0_NC_SHIFT 8
#define FLMAP0_FCBA_MASK GENMASK(7, 0)
#define FLCOMP_C0DEN_MASK GENMASK(3, 0)
#define FLCOMP_C0DEN_512K 0x00
#define FLCOMP_C0DEN_1M 0x01
#define FLCOMP_C0DEN_2M 0x02
#define FLCOMP_C0DEN_4M 0x03
#define FLCOMP_C0DEN_8M 0x04
#define FLCOMP_C0DEN_16M 0x05
#define FLCOMP_C0DEN_32M 0x06
#define FLCOMP_C0DEN_64M 0x07
#define INTEL_SPI_TIMEOUT 5000 /* ms */ #define INTEL_SPI_TIMEOUT 5000 /* ms */
#define INTEL_SPI_FIFO_SZ 64 #define INTEL_SPI_FIFO_SZ 64
...@@ -129,6 +145,7 @@ ...@@ -129,6 +145,7 @@
* @master: Pointer to the SPI controller structure * @master: Pointer to the SPI controller structure
* @nregions: Maximum number of regions * @nregions: Maximum number of regions
* @pr_num: Maximum number of protected range registers * @pr_num: Maximum number of protected range registers
* @chip0_size: Size of the first flash chip in bytes
* @locked: Is SPI setting locked * @locked: Is SPI setting locked
* @swseq_reg: Use SW sequencer in register reads/writes * @swseq_reg: Use SW sequencer in register reads/writes
* @swseq_erase: Use SW sequencer in erase operation * @swseq_erase: Use SW sequencer in erase operation
...@@ -146,6 +163,7 @@ struct intel_spi { ...@@ -146,6 +163,7 @@ struct intel_spi {
struct spi_controller *master; struct spi_controller *master;
size_t nregions; size_t nregions;
size_t pr_num; size_t pr_num;
size_t chip0_size;
bool locked; bool locked;
bool swseq_reg; bool swseq_reg;
bool swseq_erase; bool swseq_erase;
...@@ -158,6 +176,7 @@ struct intel_spi_mem_op { ...@@ -158,6 +176,7 @@ struct intel_spi_mem_op {
struct spi_mem_op mem_op; struct spi_mem_op mem_op;
u32 replacement_op; u32 replacement_op;
int (*exec_op)(struct intel_spi *ispi, int (*exec_op)(struct intel_spi *ispi,
const struct spi_mem *mem,
const struct intel_spi_mem_op *iop, const struct intel_spi_mem_op *iop,
const struct spi_mem_op *op); const struct spi_mem_op *op);
}; };
...@@ -441,7 +460,16 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len, ...@@ -441,7 +460,16 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len,
return 0; return 0;
} }
static int intel_spi_read_reg(struct intel_spi *ispi, static u32 intel_spi_chip_addr(const struct intel_spi *ispi,
const struct spi_mem *mem)
{
/* Pick up the correct start address */
if (!mem)
return 0;
return mem->spi->chip_select == 1 ? ispi->chip0_size : 0;
}
static int intel_spi_read_reg(struct intel_spi *ispi, const struct spi_mem *mem,
const struct intel_spi_mem_op *iop, const struct intel_spi_mem_op *iop,
const struct spi_mem_op *op) const struct spi_mem_op *op)
{ {
...@@ -449,8 +477,7 @@ static int intel_spi_read_reg(struct intel_spi *ispi, ...@@ -449,8 +477,7 @@ static int intel_spi_read_reg(struct intel_spi *ispi,
u8 opcode = op->cmd.opcode; u8 opcode = op->cmd.opcode;
int ret; int ret;
/* Address of the first chip */ writel(intel_spi_chip_addr(ispi, mem), ispi->base + FADDR);
writel(0, ispi->base + FADDR);
if (ispi->swseq_reg) if (ispi->swseq_reg)
ret = intel_spi_sw_cycle(ispi, opcode, nbytes, ret = intel_spi_sw_cycle(ispi, opcode, nbytes,
...@@ -464,7 +491,7 @@ static int intel_spi_read_reg(struct intel_spi *ispi, ...@@ -464,7 +491,7 @@ static int intel_spi_read_reg(struct intel_spi *ispi,
return intel_spi_read_block(ispi, op->data.buf.in, nbytes); return intel_spi_read_block(ispi, op->data.buf.in, nbytes);
} }
static int intel_spi_write_reg(struct intel_spi *ispi, static int intel_spi_write_reg(struct intel_spi *ispi, const struct spi_mem *mem,
const struct intel_spi_mem_op *iop, const struct intel_spi_mem_op *iop,
const struct spi_mem_op *op) const struct spi_mem_op *op)
{ {
...@@ -511,7 +538,7 @@ static int intel_spi_write_reg(struct intel_spi *ispi, ...@@ -511,7 +538,7 @@ static int intel_spi_write_reg(struct intel_spi *ispi,
if (opcode == SPINOR_OP_WRDI) if (opcode == SPINOR_OP_WRDI)
return 0; return 0;
writel(0, ispi->base + FADDR); writel(intel_spi_chip_addr(ispi, mem), ispi->base + FADDR);
/* Write the value beforehand */ /* Write the value beforehand */
ret = intel_spi_write_block(ispi, op->data.buf.out, nbytes); ret = intel_spi_write_block(ispi, op->data.buf.out, nbytes);
...@@ -524,13 +551,13 @@ static int intel_spi_write_reg(struct intel_spi *ispi, ...@@ -524,13 +551,13 @@ static int intel_spi_write_reg(struct intel_spi *ispi,
return intel_spi_hw_cycle(ispi, opcode, nbytes); return intel_spi_hw_cycle(ispi, opcode, nbytes);
} }
static int intel_spi_read(struct intel_spi *ispi, static int intel_spi_read(struct intel_spi *ispi, const struct spi_mem *mem,
const struct intel_spi_mem_op *iop, const struct intel_spi_mem_op *iop,
const struct spi_mem_op *op) const struct spi_mem_op *op)
{ {
void *read_buf = op->data.buf.in; u32 addr = intel_spi_chip_addr(ispi, mem) + op->addr.val;
size_t block_size, nbytes = op->data.nbytes; size_t block_size, nbytes = op->data.nbytes;
u32 addr = op->addr.val; void *read_buf = op->data.buf.in;
u32 val, status; u32 val, status;
int ret; int ret;
...@@ -585,13 +612,13 @@ static int intel_spi_read(struct intel_spi *ispi, ...@@ -585,13 +612,13 @@ static int intel_spi_read(struct intel_spi *ispi,
return 0; return 0;
} }
static int intel_spi_write(struct intel_spi *ispi, static int intel_spi_write(struct intel_spi *ispi, const struct spi_mem *mem,
const struct intel_spi_mem_op *iop, const struct intel_spi_mem_op *iop,
const struct spi_mem_op *op) const struct spi_mem_op *op)
{ {
u32 addr = intel_spi_chip_addr(ispi, mem) + op->addr.val;
size_t block_size, nbytes = op->data.nbytes; size_t block_size, nbytes = op->data.nbytes;
const void *write_buf = op->data.buf.out; const void *write_buf = op->data.buf.out;
u32 addr = op->addr.val;
u32 val, status; u32 val, status;
int ret; int ret;
...@@ -648,12 +675,12 @@ static int intel_spi_write(struct intel_spi *ispi, ...@@ -648,12 +675,12 @@ static int intel_spi_write(struct intel_spi *ispi,
return 0; return 0;
} }
static int intel_spi_erase(struct intel_spi *ispi, static int intel_spi_erase(struct intel_spi *ispi, const struct spi_mem *mem,
const struct intel_spi_mem_op *iop, const struct intel_spi_mem_op *iop,
const struct spi_mem_op *op) const struct spi_mem_op *op)
{ {
u32 addr = intel_spi_chip_addr(ispi, mem) + op->addr.val;
u8 opcode = op->cmd.opcode; u8 opcode = op->cmd.opcode;
u32 addr = op->addr.val;
u32 val, status; u32 val, status;
int ret; int ret;
...@@ -765,7 +792,7 @@ static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *o ...@@ -765,7 +792,7 @@ static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *o
if (!iop) if (!iop)
return -EOPNOTSUPP; return -EOPNOTSUPP;
return iop->exec_op(ispi, iop, op); return iop->exec_op(ispi, mem, iop, op);
} }
static const char *intel_spi_get_name(struct spi_mem *mem) static const char *intel_spi_get_name(struct spi_mem *mem)
...@@ -805,7 +832,7 @@ static ssize_t intel_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs, ...@@ -805,7 +832,7 @@ static ssize_t intel_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs,
op.data.nbytes = len; op.data.nbytes = len;
op.data.buf.in = buf; op.data.buf.in = buf;
ret = iop->exec_op(ispi, iop, &op); ret = iop->exec_op(ispi, desc->mem, iop, &op);
return ret ? ret : len; return ret ? ret : len;
} }
...@@ -821,7 +848,7 @@ static ssize_t intel_spi_dirmap_write(struct spi_mem_dirmap_desc *desc, u64 offs ...@@ -821,7 +848,7 @@ static ssize_t intel_spi_dirmap_write(struct spi_mem_dirmap_desc *desc, u64 offs
op.data.nbytes = len; op.data.nbytes = len;
op.data.buf.out = buf; op.data.buf.out = buf;
ret = iop->exec_op(ispi, iop, &op); ret = iop->exec_op(ispi, desc->mem, iop, &op);
return ret ? ret : len; return ret ? ret : len;
} }
...@@ -1073,6 +1100,7 @@ static int intel_spi_init(struct intel_spi *ispi) ...@@ -1073,6 +1100,7 @@ static int intel_spi_init(struct intel_spi *ispi)
ispi->pregs = ispi->base + CNL_PR; ispi->pregs = ispi->base + CNL_PR;
ispi->nregions = CNL_FREG_NUM; ispi->nregions = CNL_FREG_NUM;
ispi->pr_num = CNL_PR_NUM; ispi->pr_num = CNL_PR_NUM;
erase_64k = true;
break; break;
default: default:
...@@ -1226,10 +1254,98 @@ static void intel_spi_fill_partition(struct intel_spi *ispi, ...@@ -1226,10 +1254,98 @@ static void intel_spi_fill_partition(struct intel_spi *ispi,
} }
} }
static int intel_spi_read_desc(struct intel_spi *ispi)
{
struct spi_mem_op op =
SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 0),
SPI_MEM_OP_ADDR(3, 0, 0),
SPI_MEM_OP_NO_DUMMY,
SPI_MEM_OP_DATA_IN(0, NULL, 0));
u32 buf[2], nc, fcba, flcomp;
ssize_t ret;
op.addr.val = 0x10;
op.data.buf.in = buf;
op.data.nbytes = sizeof(buf);
ret = intel_spi_read(ispi, NULL, NULL, &op);
if (ret) {
dev_warn(ispi->dev, "failed to read descriptor\n");
return ret;
}
dev_dbg(ispi->dev, "FLVALSIG=0x%08x\n", buf[0]);
dev_dbg(ispi->dev, "FLMAP0=0x%08x\n", buf[1]);
if (buf[0] != FLVALSIG_MAGIC) {
dev_warn(ispi->dev, "descriptor signature not valid\n");
return -ENODEV;
}
fcba = (buf[1] & FLMAP0_FCBA_MASK) << 4;
dev_dbg(ispi->dev, "FCBA=%#x\n", fcba);
op.addr.val = fcba;
op.data.buf.in = &flcomp;
op.data.nbytes = sizeof(flcomp);
ret = intel_spi_read(ispi, NULL, NULL, &op);
if (ret) {
dev_warn(ispi->dev, "failed to read FLCOMP\n");
return -ENODEV;
}
dev_dbg(ispi->dev, "FLCOMP=0x%08x\n", flcomp);
switch (flcomp & FLCOMP_C0DEN_MASK) {
case FLCOMP_C0DEN_512K:
ispi->chip0_size = SZ_512K;
break;
case FLCOMP_C0DEN_1M:
ispi->chip0_size = SZ_1M;
break;
case FLCOMP_C0DEN_2M:
ispi->chip0_size = SZ_2M;
break;
case FLCOMP_C0DEN_4M:
ispi->chip0_size = SZ_4M;
break;
case FLCOMP_C0DEN_8M:
ispi->chip0_size = SZ_8M;
break;
case FLCOMP_C0DEN_16M:
ispi->chip0_size = SZ_16M;
break;
case FLCOMP_C0DEN_32M:
ispi->chip0_size = SZ_32M;
break;
case FLCOMP_C0DEN_64M:
ispi->chip0_size = SZ_64M;
break;
default:
return -EINVAL;
}
dev_dbg(ispi->dev, "chip0 size %zd KB\n", ispi->chip0_size / SZ_1K);
nc = (buf[1] & FLMAP0_NC_MASK) >> FLMAP0_NC_SHIFT;
if (!nc)
ispi->master->num_chipselect = 1;
else if (nc == 1)
ispi->master->num_chipselect = 2;
else
return -EINVAL;
dev_dbg(ispi->dev, "%u flash components found\n",
ispi->master->num_chipselect);
return 0;
}
static int intel_spi_populate_chip(struct intel_spi *ispi) static int intel_spi_populate_chip(struct intel_spi *ispi)
{ {
struct flash_platform_data *pdata; struct flash_platform_data *pdata;
struct spi_board_info chip; struct spi_board_info chip;
int ret;
pdata = devm_kzalloc(ispi->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(ispi->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
...@@ -1247,7 +1363,23 @@ static int intel_spi_populate_chip(struct intel_spi *ispi) ...@@ -1247,7 +1363,23 @@ static int intel_spi_populate_chip(struct intel_spi *ispi)
snprintf(chip.modalias, 8, "spi-nor"); snprintf(chip.modalias, 8, "spi-nor");
chip.platform_data = pdata; chip.platform_data = pdata;
return spi_new_device(ispi->master, &chip) ? 0 : -ENODEV; if (!spi_new_device(ispi->master, &chip))
return -ENODEV;
/* Add the second chip if present */
if (ispi->master->num_chipselect < 2)
return 0;
ret = intel_spi_read_desc(ispi);
if (ret)
return ret;
chip.platform_data = NULL;
chip.chip_select = 1;
if (!spi_new_device(ispi->master, &chip))
return -ENODEV;
return 0;
} }
/** /**
......
...@@ -313,6 +313,33 @@ static struct spi_test spi_tests[] = { ...@@ -313,6 +313,33 @@ static struct spi_test spi_tests[] = {
}, },
}, },
}, },
{
.description = "three tx+rx transfers with overlapping cache lines",
.fill_option = FILL_COUNT_8,
/*
* This should be large enough for the controller driver to
* choose to transfer it with DMA.
*/
.iterate_len = { 512, -1 },
.iterate_transfer_mask = BIT(1),
.transfer_count = 3,
.transfers = {
{
.len = 1,
.tx_buf = TX(0),
.rx_buf = RX(0),
},
{
.tx_buf = TX(1),
.rx_buf = RX(1),
},
{
.len = 1,
.tx_buf = TX(513),
.rx_buf = RX(513),
},
},
},
{ /* end of tests sequence */ } { /* end of tests sequence */ }
}; };
......
...@@ -537,7 +537,7 @@ static unsigned long meson_spicc_pow2_recalc_rate(struct clk_hw *hw, ...@@ -537,7 +537,7 @@ static unsigned long meson_spicc_pow2_recalc_rate(struct clk_hw *hw,
struct clk_divider *divider = to_clk_divider(hw); struct clk_divider *divider = to_clk_divider(hw);
struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
if (!spicc->master->cur_msg || !spicc->master->busy) if (!spicc->master->cur_msg)
return 0; return 0;
return clk_divider_ops.recalc_rate(hw, parent_rate); return clk_divider_ops.recalc_rate(hw, parent_rate);
...@@ -549,7 +549,7 @@ static int meson_spicc_pow2_determine_rate(struct clk_hw *hw, ...@@ -549,7 +549,7 @@ static int meson_spicc_pow2_determine_rate(struct clk_hw *hw,
struct clk_divider *divider = to_clk_divider(hw); struct clk_divider *divider = to_clk_divider(hw);
struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
if (!spicc->master->cur_msg || !spicc->master->busy) if (!spicc->master->cur_msg)
return -EINVAL; return -EINVAL;
return clk_divider_ops.determine_rate(hw, req); return clk_divider_ops.determine_rate(hw, req);
...@@ -561,13 +561,13 @@ static int meson_spicc_pow2_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -561,13 +561,13 @@ static int meson_spicc_pow2_set_rate(struct clk_hw *hw, unsigned long rate,
struct clk_divider *divider = to_clk_divider(hw); struct clk_divider *divider = to_clk_divider(hw);
struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
if (!spicc->master->cur_msg || !spicc->master->busy) if (!spicc->master->cur_msg)
return -EINVAL; return -EINVAL;
return clk_divider_ops.set_rate(hw, rate, parent_rate); return clk_divider_ops.set_rate(hw, rate, parent_rate);
} }
const struct clk_ops meson_spicc_pow2_clk_ops = { static const struct clk_ops meson_spicc_pow2_clk_ops = {
.recalc_rate = meson_spicc_pow2_recalc_rate, .recalc_rate = meson_spicc_pow2_recalc_rate,
.determine_rate = meson_spicc_pow2_determine_rate, .determine_rate = meson_spicc_pow2_determine_rate,
.set_rate = meson_spicc_pow2_set_rate, .set_rate = meson_spicc_pow2_set_rate,
......
This diff is collapsed.
...@@ -548,12 +548,12 @@ static int mchp_corespi_probe(struct platform_device *pdev) ...@@ -548,12 +548,12 @@ static int mchp_corespi_probe(struct platform_device *pdev)
IRQF_SHARED, dev_name(&pdev->dev), master); IRQF_SHARED, dev_name(&pdev->dev), master);
if (ret) if (ret)
return dev_err_probe(&pdev->dev, ret, return dev_err_probe(&pdev->dev, ret,
"could not request irq: %d\n", ret); "could not request irq\n");
spi->clk = devm_clk_get(&pdev->dev, NULL); spi->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(spi->clk)) if (IS_ERR(spi->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk), return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk),
"could not get clk: %d\n", ret); "could not get clk\n");
ret = clk_prepare_enable(spi->clk); ret = clk_prepare_enable(spi->clk);
if (ret) if (ret)
......
...@@ -11,13 +11,14 @@ ...@@ -11,13 +11,14 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/err.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
...@@ -89,7 +90,7 @@ struct mpc52xx_spi { ...@@ -89,7 +90,7 @@ struct mpc52xx_spi {
const u8 *tx_buf; const u8 *tx_buf;
int cs_change; int cs_change;
int gpio_cs_count; int gpio_cs_count;
unsigned int *gpio_cs; struct gpio_desc **gpio_cs;
}; };
/* /*
...@@ -101,9 +102,10 @@ static void mpc52xx_spi_chipsel(struct mpc52xx_spi *ms, int value) ...@@ -101,9 +102,10 @@ static void mpc52xx_spi_chipsel(struct mpc52xx_spi *ms, int value)
if (ms->gpio_cs_count > 0) { if (ms->gpio_cs_count > 0) {
cs = ms->message->spi->chip_select; cs = ms->message->spi->chip_select;
gpio_set_value(ms->gpio_cs[cs], value ? 0 : 1); gpiod_set_value(ms->gpio_cs[cs], value);
} else } else {
out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08); out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08);
}
} }
/* /*
...@@ -385,10 +387,10 @@ static int mpc52xx_spi_probe(struct platform_device *op) ...@@ -385,10 +387,10 @@ static int mpc52xx_spi_probe(struct platform_device *op)
{ {
struct spi_master *master; struct spi_master *master;
struct mpc52xx_spi *ms; struct mpc52xx_spi *ms;
struct gpio_desc *gpio_cs;
void __iomem *regs; void __iomem *regs;
u8 ctrl1; u8 ctrl1;
int rc, i = 0; int rc, i = 0;
int gpio_cs;
/* MMIO registers */ /* MMIO registers */
dev_dbg(&op->dev, "probing mpc5200 SPI device\n"); dev_dbg(&op->dev, "probing mpc5200 SPI device\n");
...@@ -438,7 +440,7 @@ static int mpc52xx_spi_probe(struct platform_device *op) ...@@ -438,7 +440,7 @@ static int mpc52xx_spi_probe(struct platform_device *op)
ms->irq1 = irq_of_parse_and_map(op->dev.of_node, 1); ms->irq1 = irq_of_parse_and_map(op->dev.of_node, 1);
ms->state = mpc52xx_spi_fsmstate_idle; ms->state = mpc52xx_spi_fsmstate_idle;
ms->ipb_freq = mpc5xxx_get_bus_frequency(&op->dev); ms->ipb_freq = mpc5xxx_get_bus_frequency(&op->dev);
ms->gpio_cs_count = of_gpio_count(op->dev.of_node); ms->gpio_cs_count = gpiod_count(&op->dev, NULL);
if (ms->gpio_cs_count > 0) { if (ms->gpio_cs_count > 0) {
master->num_chipselect = ms->gpio_cs_count; master->num_chipselect = ms->gpio_cs_count;
ms->gpio_cs = kmalloc_array(ms->gpio_cs_count, ms->gpio_cs = kmalloc_array(ms->gpio_cs_count,
...@@ -450,23 +452,16 @@ static int mpc52xx_spi_probe(struct platform_device *op) ...@@ -450,23 +452,16 @@ static int mpc52xx_spi_probe(struct platform_device *op)
} }
for (i = 0; i < ms->gpio_cs_count; i++) { for (i = 0; i < ms->gpio_cs_count; i++) {
gpio_cs = of_get_gpio(op->dev.of_node, i); gpio_cs = gpiod_get_index(&op->dev,
if (!gpio_is_valid(gpio_cs)) { NULL, i, GPIOD_OUT_LOW);
dev_err(&op->dev, rc = PTR_ERR_OR_ZERO(gpio_cs);
"could not parse the gpio field in oftree\n");
rc = -ENODEV;
goto err_gpio;
}
rc = gpio_request(gpio_cs, dev_name(&op->dev));
if (rc) { if (rc) {
dev_err(&op->dev, dev_err(&op->dev,
"can't request spi cs gpio #%d on gpio line %d\n", "failed to get spi cs gpio #%d: %d\n",
i, gpio_cs); i, rc);
goto err_gpio; goto err_gpio;
} }
gpio_direction_output(gpio_cs, 1);
ms->gpio_cs[i] = gpio_cs; ms->gpio_cs[i] = gpio_cs;
} }
} }
...@@ -507,7 +502,7 @@ static int mpc52xx_spi_probe(struct platform_device *op) ...@@ -507,7 +502,7 @@ static int mpc52xx_spi_probe(struct platform_device *op)
dev_err(&ms->master->dev, "initialization failed\n"); dev_err(&ms->master->dev, "initialization failed\n");
err_gpio: err_gpio:
while (i-- > 0) while (i-- > 0)
gpio_free(ms->gpio_cs[i]); gpiod_put(ms->gpio_cs[i]);
kfree(ms->gpio_cs); kfree(ms->gpio_cs);
err_alloc_gpio: err_alloc_gpio:
...@@ -528,7 +523,7 @@ static int mpc52xx_spi_remove(struct platform_device *op) ...@@ -528,7 +523,7 @@ static int mpc52xx_spi_remove(struct platform_device *op)
free_irq(ms->irq1, ms); free_irq(ms->irq1, ms);
for (i = 0; i < ms->gpio_cs_count; i++) for (i = 0; i < ms->gpio_cs_count; i++)
gpio_free(ms->gpio_cs[i]); gpiod_put(ms->gpio_cs[i]);
kfree(ms->gpio_cs); kfree(ms->gpio_cs);
spi_unregister_master(master); spi_unregister_master(master);
......
...@@ -1184,6 +1184,11 @@ static int mtk_spi_probe(struct platform_device *pdev) ...@@ -1184,6 +1184,11 @@ static int mtk_spi_probe(struct platform_device *pdev)
if (!dev->dma_mask) if (!dev->dma_mask)
dev->dma_mask = &dev->coherent_dma_mask; dev->dma_mask = &dev->coherent_dma_mask;
if (mdata->dev_comp->ipm_design)
dma_set_max_seg_size(dev, SZ_16M);
else
dma_set_max_seg_size(dev, SZ_256K);
ret = devm_request_irq(dev, irq, mtk_spi_interrupt, ret = devm_request_irq(dev, irq, mtk_spi_interrupt,
IRQF_TRIGGER_NONE, dev_name(dev), master); IRQF_TRIGGER_NONE, dev_name(dev), master);
if (ret) if (ret)
......
...@@ -55,7 +55,6 @@ struct mt7621_spi { ...@@ -55,7 +55,6 @@ struct mt7621_spi {
void __iomem *base; void __iomem *base;
unsigned int sys_freq; unsigned int sys_freq;
unsigned int speed; unsigned int speed;
struct clk *clk;
int pending_write; int pending_write;
}; };
...@@ -327,7 +326,6 @@ static int mt7621_spi_probe(struct platform_device *pdev) ...@@ -327,7 +326,6 @@ static int mt7621_spi_probe(struct platform_device *pdev)
struct spi_controller *master; struct spi_controller *master;
struct mt7621_spi *rs; struct mt7621_spi *rs;
void __iomem *base; void __iomem *base;
int status = 0;
struct clk *clk; struct clk *clk;
int ret; int ret;
...@@ -339,21 +337,14 @@ static int mt7621_spi_probe(struct platform_device *pdev) ...@@ -339,21 +337,14 @@ static int mt7621_spi_probe(struct platform_device *pdev)
if (IS_ERR(base)) if (IS_ERR(base))
return PTR_ERR(base); return PTR_ERR(base);
clk = devm_clk_get(&pdev->dev, NULL); clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(clk)) { if (IS_ERR(clk))
dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n", return dev_err_probe(&pdev->dev, PTR_ERR(clk),
status); "unable to get SYS clock\n");
return PTR_ERR(clk);
}
status = clk_prepare_enable(clk);
if (status)
return status;
master = devm_spi_alloc_master(&pdev->dev, sizeof(*rs)); master = devm_spi_alloc_master(&pdev->dev, sizeof(*rs));
if (!master) { if (!master) {
dev_info(&pdev->dev, "master allocation failed\n"); dev_info(&pdev->dev, "master allocation failed\n");
clk_disable_unprepare(clk);
return -ENOMEM; return -ENOMEM;
} }
...@@ -369,38 +360,18 @@ static int mt7621_spi_probe(struct platform_device *pdev) ...@@ -369,38 +360,18 @@ static int mt7621_spi_probe(struct platform_device *pdev)
rs = spi_controller_get_devdata(master); rs = spi_controller_get_devdata(master);
rs->base = base; rs->base = base;
rs->clk = clk;
rs->master = master; rs->master = master;
rs->sys_freq = clk_get_rate(rs->clk); rs->sys_freq = clk_get_rate(clk);
rs->pending_write = 0; rs->pending_write = 0;
dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq); dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq);
ret = device_reset(&pdev->dev); ret = device_reset(&pdev->dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "SPI reset failed!\n"); dev_err(&pdev->dev, "SPI reset failed!\n");
clk_disable_unprepare(clk);
return ret; return ret;
} }
ret = spi_register_controller(master); return devm_spi_register_controller(&pdev->dev, master);
if (ret)
clk_disable_unprepare(clk);
return ret;
}
static int mt7621_spi_remove(struct platform_device *pdev)
{
struct spi_controller *master;
struct mt7621_spi *rs;
master = dev_get_drvdata(&pdev->dev);
rs = spi_controller_get_devdata(master);
spi_unregister_controller(master);
clk_disable_unprepare(rs->clk);
return 0;
} }
MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_ALIAS("platform:" DRIVER_NAME);
...@@ -411,7 +382,6 @@ static struct platform_driver mt7621_spi_driver = { ...@@ -411,7 +382,6 @@ static struct platform_driver mt7621_spi_driver = {
.of_match_table = mt7621_spi_match, .of_match_table = mt7621_spi_match,
}, },
.probe = mt7621_spi_probe, .probe = mt7621_spi_probe,
.remove = mt7621_spi_remove,
}; };
module_platform_driver(mt7621_spi_driver); module_platform_driver(mt7621_spi_driver);
......
...@@ -443,6 +443,7 @@ static int npcm_pspi_remove(struct platform_device *pdev) ...@@ -443,6 +443,7 @@ static int npcm_pspi_remove(struct platform_device *pdev)
static const struct of_device_id npcm_pspi_match[] = { static const struct of_device_id npcm_pspi_match[] = {
{ .compatible = "nuvoton,npcm750-pspi", .data = NULL }, { .compatible = "nuvoton,npcm750-pspi", .data = NULL },
{ .compatible = "nuvoton,npcm845-pspi", .data = NULL },
{} {}
}; };
MODULE_DEVICE_TABLE(of, npcm_pspi_match); MODULE_DEVICE_TABLE(of, npcm_pspi_match);
......
...@@ -588,7 +588,7 @@ static int nxp_fspi_clk_prep_enable(struct nxp_fspi *f) ...@@ -588,7 +588,7 @@ static int nxp_fspi_clk_prep_enable(struct nxp_fspi *f)
{ {
int ret; int ret;
if (is_acpi_node(f->dev->fwnode)) if (is_acpi_node(dev_fwnode(f->dev)))
return 0; return 0;
ret = clk_prepare_enable(f->clk_en); ret = clk_prepare_enable(f->clk_en);
...@@ -606,7 +606,7 @@ static int nxp_fspi_clk_prep_enable(struct nxp_fspi *f) ...@@ -606,7 +606,7 @@ static int nxp_fspi_clk_prep_enable(struct nxp_fspi *f)
static int nxp_fspi_clk_disable_unprep(struct nxp_fspi *f) static int nxp_fspi_clk_disable_unprep(struct nxp_fspi *f)
{ {
if (is_acpi_node(f->dev->fwnode)) if (is_acpi_node(dev_fwnode(f->dev)))
return 0; return 0;
clk_disable_unprepare(f->clk); clk_disable_unprepare(f->clk);
...@@ -1100,7 +1100,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) ...@@ -1100,7 +1100,7 @@ static int nxp_fspi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, f); platform_set_drvdata(pdev, f);
/* find the resources - configuration register address space */ /* find the resources - configuration register address space */
if (is_acpi_node(f->dev->fwnode)) if (is_acpi_node(dev_fwnode(f->dev)))
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
else else
res = platform_get_resource_byname(pdev, res = platform_get_resource_byname(pdev,
...@@ -1113,7 +1113,7 @@ static int nxp_fspi_probe(struct platform_device *pdev) ...@@ -1113,7 +1113,7 @@ static int nxp_fspi_probe(struct platform_device *pdev)
} }
/* find the resources - controller memory mapped space */ /* find the resources - controller memory mapped space */
if (is_acpi_node(f->dev->fwnode)) if (is_acpi_node(dev_fwnode(f->dev)))
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
else else
res = platform_get_resource_byname(pdev, res = platform_get_resource_byname(pdev,
......
...@@ -412,6 +412,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev) ...@@ -412,6 +412,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
return status; return status;
err_fck: err_fck:
pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(spi100k->fck); clk_disable_unprepare(spi100k->fck);
err_ick: err_ick:
clk_disable_unprepare(spi100k->ick); clk_disable_unprepare(spi100k->ick);
......
...@@ -1509,10 +1509,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev) ...@@ -1509,10 +1509,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
} }
status = platform_get_irq(pdev, 0); status = platform_get_irq(pdev, 0);
if (status == -EPROBE_DEFER)
goto free_master;
if (status < 0) { if (status < 0) {
dev_err(&pdev->dev, "no irq resource found\n"); dev_err_probe(&pdev->dev, status, "no irq resource found\n");
goto free_master; goto free_master;
} }
init_completion(&mcspi->txdone); init_completion(&mcspi->txdone);
......
...@@ -1856,10 +1856,8 @@ static int pxa2xx_spi_runtime_suspend(struct device *dev) ...@@ -1856,10 +1856,8 @@ static int pxa2xx_spi_runtime_suspend(struct device *dev)
static int pxa2xx_spi_runtime_resume(struct device *dev) static int pxa2xx_spi_runtime_resume(struct device *dev)
{ {
struct driver_data *drv_data = dev_get_drvdata(dev); struct driver_data *drv_data = dev_get_drvdata(dev);
int status;
status = clk_prepare_enable(drv_data->ssp->clk); return clk_prepare_enable(drv_data->ssp->clk);
return status;
} }
#endif #endif
......
...@@ -1198,8 +1198,10 @@ static int spi_qup_pm_resume_runtime(struct device *device) ...@@ -1198,8 +1198,10 @@ static int spi_qup_pm_resume_runtime(struct device *device)
return ret; return ret;
ret = clk_prepare_enable(controller->cclk); ret = clk_prepare_enable(controller->cclk);
if (ret) if (ret) {
clk_disable_unprepare(controller->iclk);
return ret; return ret;
}
/* Disable clocks auto gaiting */ /* Disable clocks auto gaiting */
config = readl_relaxed(controller->base + QUP_CONFIG); config = readl_relaxed(controller->base + QUP_CONFIG);
...@@ -1245,14 +1247,25 @@ static int spi_qup_resume(struct device *device) ...@@ -1245,14 +1247,25 @@ static int spi_qup_resume(struct device *device)
return ret; return ret;
ret = clk_prepare_enable(controller->cclk); ret = clk_prepare_enable(controller->cclk);
if (ret) if (ret) {
clk_disable_unprepare(controller->iclk);
return ret; return ret;
}
ret = spi_qup_set_state(controller, QUP_STATE_RESET); ret = spi_qup_set_state(controller, QUP_STATE_RESET);
if (ret) if (ret)
return ret; goto disable_clk;
return spi_master_resume(master); ret = spi_master_resume(master);
if (ret)
goto disable_clk;
return 0;
disable_clk:
clk_disable_unprepare(controller->cclk);
clk_disable_unprepare(controller->iclk);
return ret;
} }
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
......
...@@ -449,7 +449,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) ...@@ -449,7 +449,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
struct spi_master *master; struct spi_master *master;
int err = 0; int err = 0;
master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); master = devm_spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
if (master == NULL) { if (master == NULL) {
dev_err(&pdev->dev, "No memory for spi_master\n"); dev_err(&pdev->dev, "No memory for spi_master\n");
return -ENOMEM; return -ENOMEM;
...@@ -463,8 +463,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) ...@@ -463,8 +463,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
if (pdata == NULL) { if (pdata == NULL) {
dev_err(&pdev->dev, "No platform data supplied\n"); dev_err(&pdev->dev, "No platform data supplied\n");
err = -ENOENT; return -ENOENT;
goto err_no_pdata;
} }
platform_set_drvdata(pdev, hw); platform_set_drvdata(pdev, hw);
...@@ -499,29 +498,24 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) ...@@ -499,29 +498,24 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
/* find and map our resources */ /* find and map our resources */
hw->regs = devm_platform_ioremap_resource(pdev, 0); hw->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hw->regs)) { if (IS_ERR(hw->regs))
err = PTR_ERR(hw->regs); return PTR_ERR(hw->regs);
goto err_no_pdata;
}
hw->irq = platform_get_irq(pdev, 0); hw->irq = platform_get_irq(pdev, 0);
if (hw->irq < 0) { if (hw->irq < 0)
err = -ENOENT; return -ENOENT;
goto err_no_pdata;
}
err = devm_request_irq(&pdev->dev, hw->irq, s3c24xx_spi_irq, 0, err = devm_request_irq(&pdev->dev, hw->irq, s3c24xx_spi_irq, 0,
pdev->name, hw); pdev->name, hw);
if (err) { if (err) {
dev_err(&pdev->dev, "Cannot claim IRQ\n"); dev_err(&pdev->dev, "Cannot claim IRQ\n");
goto err_no_pdata; return err;
} }
hw->clk = devm_clk_get(&pdev->dev, "spi"); hw->clk = devm_clk_get(&pdev->dev, "spi");
if (IS_ERR(hw->clk)) { if (IS_ERR(hw->clk)) {
dev_err(&pdev->dev, "No clock for device\n"); dev_err(&pdev->dev, "No clock for device\n");
err = PTR_ERR(hw->clk); return PTR_ERR(hw->clk);
goto err_no_pdata;
} }
s3c24xx_spi_initialsetup(hw); s3c24xx_spi_initialsetup(hw);
...@@ -539,8 +533,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) ...@@ -539,8 +533,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
err_register: err_register:
clk_disable(hw->clk); clk_disable(hw->clk);
err_no_pdata:
spi_master_put(hw->master);
return err; return err;
} }
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
#define S3C64XX_SPI_ST_TX_FIFORDY (1<<0) #define S3C64XX_SPI_ST_TX_FIFORDY (1<<0)
#define S3C64XX_SPI_PACKET_CNT_EN (1<<16) #define S3C64XX_SPI_PACKET_CNT_EN (1<<16)
#define S3C64XX_SPI_PACKET_CNT_MASK GENMASK(15, 0)
#define S3C64XX_SPI_PND_TX_UNDERRUN_CLR (1<<4) #define S3C64XX_SPI_PND_TX_UNDERRUN_CLR (1<<4)
#define S3C64XX_SPI_PND_TX_OVERRUN_CLR (1<<3) #define S3C64XX_SPI_PND_TX_OVERRUN_CLR (1<<3)
...@@ -389,8 +390,8 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi) ...@@ -389,8 +390,8 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
if (sdd->rx_dma.ch && sdd->tx_dma.ch) { if (sdd->rx_dma.ch && sdd->tx_dma.ch) {
dma_release_channel(sdd->rx_dma.ch); dma_release_channel(sdd->rx_dma.ch);
dma_release_channel(sdd->tx_dma.ch); dma_release_channel(sdd->tx_dma.ch);
sdd->rx_dma.ch = 0; sdd->rx_dma.ch = NULL;
sdd->tx_dma.ch = 0; sdd->tx_dma.ch = NULL;
} }
return 0; return 0;
...@@ -711,6 +712,13 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master, ...@@ -711,6 +712,13 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master,
return 0; return 0;
} }
static size_t s3c64xx_spi_max_transfer_size(struct spi_device *spi)
{
struct spi_controller *ctlr = spi->controller;
return ctlr->can_dma ? S3C64XX_SPI_PACKET_CNT_MASK : SIZE_MAX;
}
static int s3c64xx_spi_transfer_one(struct spi_master *master, static int s3c64xx_spi_transfer_one(struct spi_master *master,
struct spi_device *spi, struct spi_device *spi,
struct spi_transfer *xfer) struct spi_transfer *xfer)
...@@ -1152,6 +1160,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) ...@@ -1152,6 +1160,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
master->prepare_message = s3c64xx_spi_prepare_message; master->prepare_message = s3c64xx_spi_prepare_message;
master->transfer_one = s3c64xx_spi_transfer_one; master->transfer_one = s3c64xx_spi_transfer_one;
master->max_transfer_size = s3c64xx_spi_max_transfer_size;
master->num_chipselect = sci->num_cs; master->num_chipselect = sci->num_cs;
master->use_gpio_descriptors = true; master->use_gpio_descriptors = true;
master->dma_alignment = 8; master->dma_alignment = 8;
......
...@@ -1085,6 +1085,7 @@ static const struct of_device_id sh_msiof_match[] = { ...@@ -1085,6 +1085,7 @@ static const struct of_device_id sh_msiof_match[] = {
{ .compatible = "renesas,rcar-gen2-msiof", .data = &rcar_gen2_data }, { .compatible = "renesas,rcar-gen2-msiof", .data = &rcar_gen2_data },
{ .compatible = "renesas,msiof-r8a7796", .data = &rcar_gen3_data }, { .compatible = "renesas,msiof-r8a7796", .data = &rcar_gen3_data },
{ .compatible = "renesas,rcar-gen3-msiof", .data = &rcar_gen3_data }, { .compatible = "renesas,rcar-gen3-msiof", .data = &rcar_gen3_data },
{ .compatible = "renesas,rcar-gen4-msiof", .data = &rcar_gen3_data },
{ .compatible = "renesas,sh-msiof", .data = &sh_data }, /* Deprecated */ { .compatible = "renesas,sh-msiof", .data = &sh_data }, /* Deprecated */
{}, {},
}; };
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -355,10 +356,10 @@ static int stm32_qspi_get_mode(u8 buswidth) ...@@ -355,10 +356,10 @@ static int stm32_qspi_get_mode(u8 buswidth)
return buswidth; return buswidth;
} }
static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op) static int stm32_qspi_send(struct spi_device *spi, const struct spi_mem_op *op)
{ {
struct stm32_qspi *qspi = spi_controller_get_devdata(mem->spi->master); struct stm32_qspi *qspi = spi_controller_get_devdata(spi->master);
struct stm32_qspi_flash *flash = &qspi->flash[mem->spi->chip_select]; struct stm32_qspi_flash *flash = &qspi->flash[spi->chip_select];
u32 ccr, cr; u32 ccr, cr;
int timeout, err = 0, err_poll_status = 0; int timeout, err = 0, err_poll_status = 0;
...@@ -465,7 +466,7 @@ static int stm32_qspi_poll_status(struct spi_mem *mem, const struct spi_mem_op * ...@@ -465,7 +466,7 @@ static int stm32_qspi_poll_status(struct spi_mem *mem, const struct spi_mem_op *
qspi->fmode = CCR_FMODE_APM; qspi->fmode = CCR_FMODE_APM;
qspi->status_timeout = timeout_ms; qspi->status_timeout = timeout_ms;
ret = stm32_qspi_send(mem, op); ret = stm32_qspi_send(mem->spi, op);
mutex_unlock(&qspi->lock); mutex_unlock(&qspi->lock);
pm_runtime_mark_last_busy(qspi->dev); pm_runtime_mark_last_busy(qspi->dev);
...@@ -489,7 +490,7 @@ static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) ...@@ -489,7 +490,7 @@ static int stm32_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
else else
qspi->fmode = CCR_FMODE_INDW; qspi->fmode = CCR_FMODE_INDW;
ret = stm32_qspi_send(mem, op); ret = stm32_qspi_send(mem->spi, op);
mutex_unlock(&qspi->lock); mutex_unlock(&qspi->lock);
pm_runtime_mark_last_busy(qspi->dev); pm_runtime_mark_last_busy(qspi->dev);
...@@ -545,7 +546,7 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc, ...@@ -545,7 +546,7 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc,
else else
qspi->fmode = CCR_FMODE_INDR; qspi->fmode = CCR_FMODE_INDR;
ret = stm32_qspi_send(desc->mem, &op); ret = stm32_qspi_send(desc->mem->spi, &op);
mutex_unlock(&qspi->lock); mutex_unlock(&qspi->lock);
pm_runtime_mark_last_busy(qspi->dev); pm_runtime_mark_last_busy(qspi->dev);
...@@ -554,12 +555,96 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc, ...@@ -554,12 +555,96 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc,
return ret ?: len; return ret ?: len;
} }
static int stm32_qspi_transfer_one_message(struct spi_controller *ctrl,
struct spi_message *msg)
{
struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl);
struct spi_transfer *transfer;
struct spi_device *spi = msg->spi;
struct spi_mem_op op;
int ret = 0;
if (!spi->cs_gpiod)
return -EOPNOTSUPP;
ret = pm_runtime_resume_and_get(qspi->dev);
if (ret < 0)
return ret;
mutex_lock(&qspi->lock);
gpiod_set_value_cansleep(spi->cs_gpiod, true);
list_for_each_entry(transfer, &msg->transfers, transfer_list) {
u8 dummy_bytes = 0;
memset(&op, 0, sizeof(op));
dev_dbg(qspi->dev, "tx_buf:%p tx_nbits:%d rx_buf:%p rx_nbits:%d len:%d dummy_data:%d\n",
transfer->tx_buf, transfer->tx_nbits,
transfer->rx_buf, transfer->rx_nbits,
transfer->len, transfer->dummy_data);
/*
* QSPI hardware supports dummy bytes transfer.
* If current transfer is dummy byte, merge it with the next
* transfer in order to take into account QSPI block constraint
*/
if (transfer->dummy_data) {
op.dummy.buswidth = transfer->tx_nbits;
op.dummy.nbytes = transfer->len;
dummy_bytes = transfer->len;
/* if happens, means that message is not correctly built */
if (list_is_last(&transfer->transfer_list, &msg->transfers)) {
ret = -EINVAL;
goto end_of_transfer;
}
transfer = list_next_entry(transfer, transfer_list);
}
op.data.nbytes = transfer->len;
if (transfer->rx_buf) {
qspi->fmode = CCR_FMODE_INDR;
op.data.buswidth = transfer->rx_nbits;
op.data.dir = SPI_MEM_DATA_IN;
op.data.buf.in = transfer->rx_buf;
} else {
qspi->fmode = CCR_FMODE_INDW;
op.data.buswidth = transfer->tx_nbits;
op.data.dir = SPI_MEM_DATA_OUT;
op.data.buf.out = transfer->tx_buf;
}
ret = stm32_qspi_send(spi, &op);
if (ret)
goto end_of_transfer;
msg->actual_length += transfer->len + dummy_bytes;
}
end_of_transfer:
gpiod_set_value_cansleep(spi->cs_gpiod, false);
mutex_unlock(&qspi->lock);
msg->status = ret;
spi_finalize_current_message(ctrl);
pm_runtime_mark_last_busy(qspi->dev);
pm_runtime_put_autosuspend(qspi->dev);
return ret;
}
static int stm32_qspi_setup(struct spi_device *spi) static int stm32_qspi_setup(struct spi_device *spi)
{ {
struct spi_controller *ctrl = spi->master; struct spi_controller *ctrl = spi->master;
struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl); struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl);
struct stm32_qspi_flash *flash; struct stm32_qspi_flash *flash;
u32 presc; u32 presc, mode;
int ret; int ret;
if (ctrl->busy) if (ctrl->busy)
...@@ -568,6 +653,16 @@ static int stm32_qspi_setup(struct spi_device *spi) ...@@ -568,6 +653,16 @@ static int stm32_qspi_setup(struct spi_device *spi)
if (!spi->max_speed_hz) if (!spi->max_speed_hz)
return -EINVAL; return -EINVAL;
mode = spi->mode & (SPI_TX_OCTAL | SPI_RX_OCTAL);
if ((mode == SPI_TX_OCTAL || mode == SPI_RX_OCTAL) ||
((mode == (SPI_TX_OCTAL | SPI_RX_OCTAL)) &&
gpiod_count(qspi->dev, "cs") == -ENOENT)) {
dev_err(qspi->dev, "spi-rx-bus-width\\/spi-tx-bus-width\\/cs-gpios\n");
dev_err(qspi->dev, "configuration not supported\n");
return -EINVAL;
}
ret = pm_runtime_resume_and_get(qspi->dev); ret = pm_runtime_resume_and_get(qspi->dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -580,6 +675,16 @@ static int stm32_qspi_setup(struct spi_device *spi) ...@@ -580,6 +675,16 @@ static int stm32_qspi_setup(struct spi_device *spi)
mutex_lock(&qspi->lock); mutex_lock(&qspi->lock);
qspi->cr_reg = CR_APMS | 3 << CR_FTHRES_SHIFT | CR_SSHIFT | CR_EN; qspi->cr_reg = CR_APMS | 3 << CR_FTHRES_SHIFT | CR_SSHIFT | CR_EN;
/*
* Dual flash mode is only enable in case SPI_TX_OCTAL and SPI_TX_OCTAL
* are both set in spi->mode and "cs-gpios" properties is found in DT
*/
if (mode == (SPI_TX_OCTAL | SPI_RX_OCTAL)) {
qspi->cr_reg |= CR_DFM;
dev_dbg(qspi->dev, "Dual flash mode enable");
}
writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR); writel_relaxed(qspi->cr_reg, qspi->io_base + QSPI_CR);
/* set dcr fsize to max address */ /* set dcr fsize to max address */
...@@ -741,11 +846,13 @@ static int stm32_qspi_probe(struct platform_device *pdev) ...@@ -741,11 +846,13 @@ static int stm32_qspi_probe(struct platform_device *pdev)
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 | SPI_TX_OCTAL
| SPI_TX_DUAL | SPI_TX_QUAD; | SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_OCTAL;
ctrl->setup = stm32_qspi_setup; ctrl->setup = stm32_qspi_setup;
ctrl->bus_num = -1; ctrl->bus_num = -1;
ctrl->mem_ops = &stm32_qspi_mem_ops; ctrl->mem_ops = &stm32_qspi_mem_ops;
ctrl->use_gpio_descriptors = true;
ctrl->transfer_one_message = stm32_qspi_transfer_one_message;
ctrl->num_chipselect = STM32_QSPI_MAX_NORCHIP; ctrl->num_chipselect = STM32_QSPI_MAX_NORCHIP;
ctrl->dev.of_node = dev->of_node; ctrl->dev.of_node = dev->of_node;
......
...@@ -421,7 +421,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) ...@@ -421,7 +421,7 @@ static int xilinx_spi_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
master = spi_alloc_master(&pdev->dev, sizeof(struct xilinx_spi)); master = devm_spi_alloc_master(&pdev->dev, sizeof(struct xilinx_spi));
if (!master) if (!master)
return -ENODEV; return -ENODEV;
...@@ -439,10 +439,8 @@ static int xilinx_spi_probe(struct platform_device *pdev) ...@@ -439,10 +439,8 @@ static int xilinx_spi_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
xspi->regs = devm_ioremap_resource(&pdev->dev, res); xspi->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(xspi->regs)) { if (IS_ERR(xspi->regs))
ret = PTR_ERR(xspi->regs); return PTR_ERR(xspi->regs);
goto put_master;
}
master->bus_num = pdev->id; master->bus_num = pdev->id;
master->num_chipselect = num_cs; master->num_chipselect = num_cs;
...@@ -472,14 +470,13 @@ static int xilinx_spi_probe(struct platform_device *pdev) ...@@ -472,14 +470,13 @@ static int xilinx_spi_probe(struct platform_device *pdev)
xspi->irq = platform_get_irq(pdev, 0); xspi->irq = platform_get_irq(pdev, 0);
if (xspi->irq < 0 && xspi->irq != -ENXIO) { if (xspi->irq < 0 && xspi->irq != -ENXIO) {
ret = xspi->irq; return xspi->irq;
goto put_master;
} else if (xspi->irq >= 0) { } else if (xspi->irq >= 0) {
/* Register for SPI Interrupt */ /* Register for SPI Interrupt */
ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0, ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0,
dev_name(&pdev->dev), xspi); dev_name(&pdev->dev), xspi);
if (ret) if (ret)
goto put_master; return ret;
} }
/* SPI controller initializations */ /* SPI controller initializations */
...@@ -488,7 +485,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) ...@@ -488,7 +485,7 @@ static int xilinx_spi_probe(struct platform_device *pdev)
ret = spi_bitbang_start(&xspi->bitbang); ret = spi_bitbang_start(&xspi->bitbang);
if (ret) { if (ret) {
dev_err(&pdev->dev, "spi_bitbang_start FAILED\n"); dev_err(&pdev->dev, "spi_bitbang_start FAILED\n");
goto put_master; return ret;
} }
dev_info(&pdev->dev, "at %pR, irq=%d\n", res, xspi->irq); dev_info(&pdev->dev, "at %pR, irq=%d\n", res, xspi->irq);
...@@ -500,11 +497,6 @@ static int xilinx_spi_probe(struct platform_device *pdev) ...@@ -500,11 +497,6 @@ static int xilinx_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
return 0; return 0;
put_master:
spi_master_put(master);
return ret;
} }
static int xilinx_spi_remove(struct platform_device *pdev) static int xilinx_spi_remove(struct platform_device *pdev)
......
...@@ -83,7 +83,7 @@ static int xtfpga_spi_probe(struct platform_device *pdev) ...@@ -83,7 +83,7 @@ static int xtfpga_spi_probe(struct platform_device *pdev)
int ret; int ret;
struct spi_master *master; struct spi_master *master;
master = spi_alloc_master(&pdev->dev, sizeof(struct xtfpga_spi)); master = devm_spi_alloc_master(&pdev->dev, sizeof(struct xtfpga_spi));
if (!master) if (!master)
return -ENOMEM; return -ENOMEM;
...@@ -97,30 +97,24 @@ static int xtfpga_spi_probe(struct platform_device *pdev) ...@@ -97,30 +97,24 @@ static int xtfpga_spi_probe(struct platform_device *pdev)
xspi->bitbang.chipselect = xtfpga_spi_chipselect; xspi->bitbang.chipselect = xtfpga_spi_chipselect;
xspi->bitbang.txrx_word[SPI_MODE_0] = xtfpga_spi_txrx_word; xspi->bitbang.txrx_word[SPI_MODE_0] = xtfpga_spi_txrx_word;
xspi->regs = devm_platform_ioremap_resource(pdev, 0); xspi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(xspi->regs)) { if (IS_ERR(xspi->regs))
ret = PTR_ERR(xspi->regs); return PTR_ERR(xspi->regs);
goto err;
}
xtfpga_spi_write32(xspi, XTFPGA_SPI_START, 0); xtfpga_spi_write32(xspi, XTFPGA_SPI_START, 0);
usleep_range(1000, 2000); usleep_range(1000, 2000);
if (xtfpga_spi_read32(xspi, XTFPGA_SPI_BUSY)) { if (xtfpga_spi_read32(xspi, XTFPGA_SPI_BUSY)) {
dev_err(&pdev->dev, "Device stuck in busy state\n"); dev_err(&pdev->dev, "Device stuck in busy state\n");
ret = -EBUSY; return -EBUSY;
goto err;
} }
ret = spi_bitbang_start(&xspi->bitbang); ret = spi_bitbang_start(&xspi->bitbang);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "spi_bitbang_start failed\n"); dev_err(&pdev->dev, "spi_bitbang_start failed\n");
goto err; return ret;
} }
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
return 0; return 0;
err:
spi_master_put(master);
return ret;
} }
static int xtfpga_spi_remove(struct platform_device *pdev) static int xtfpga_spi_remove(struct platform_device *pdev)
......
...@@ -753,7 +753,7 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr, ...@@ -753,7 +753,7 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr,
proxy->max_speed_hz = chip->max_speed_hz; proxy->max_speed_hz = chip->max_speed_hz;
proxy->mode = chip->mode; proxy->mode = chip->mode;
proxy->irq = chip->irq; proxy->irq = chip->irq;
strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias)); strscpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
proxy->dev.platform_data = (void *) chip->platform_data; proxy->dev.platform_data = (void *) chip->platform_data;
proxy->controller_data = chip->controller_data; proxy->controller_data = chip->controller_data;
proxy->controller_state = NULL; proxy->controller_state = NULL;
...@@ -1010,9 +1010,9 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) ...@@ -1010,9 +1010,9 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
} }
#ifdef CONFIG_HAS_DMA #ifdef CONFIG_HAS_DMA
int spi_map_buf(struct spi_controller *ctlr, struct device *dev, static int spi_map_buf_attrs(struct spi_controller *ctlr, struct device *dev,
struct sg_table *sgt, void *buf, size_t len, struct sg_table *sgt, void *buf, size_t len,
enum dma_data_direction dir) enum dma_data_direction dir, unsigned long attrs)
{ {
const bool vmalloced_buf = is_vmalloc_addr(buf); const bool vmalloced_buf = is_vmalloc_addr(buf);
unsigned int max_seg_size = dma_get_max_seg_size(dev); unsigned int max_seg_size = dma_get_max_seg_size(dev);
...@@ -1078,28 +1078,41 @@ int spi_map_buf(struct spi_controller *ctlr, struct device *dev, ...@@ -1078,28 +1078,41 @@ int spi_map_buf(struct spi_controller *ctlr, struct device *dev,
sg = sg_next(sg); sg = sg_next(sg);
} }
ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir); ret = dma_map_sgtable(dev, sgt, dir, attrs);
if (!ret)
ret = -ENOMEM;
if (ret < 0) { if (ret < 0) {
sg_free_table(sgt); sg_free_table(sgt);
return ret; return ret;
} }
sgt->nents = ret;
return 0; return 0;
} }
void spi_unmap_buf(struct spi_controller *ctlr, struct device *dev, int spi_map_buf(struct spi_controller *ctlr, struct device *dev,
struct sg_table *sgt, enum dma_data_direction dir) struct sg_table *sgt, void *buf, size_t len,
enum dma_data_direction dir)
{
return spi_map_buf_attrs(ctlr, dev, sgt, buf, len, dir, 0);
}
static void spi_unmap_buf_attrs(struct spi_controller *ctlr,
struct device *dev, struct sg_table *sgt,
enum dma_data_direction dir,
unsigned long attrs)
{ {
if (sgt->orig_nents) { if (sgt->orig_nents) {
dma_unmap_sg(dev, sgt->sgl, sgt->orig_nents, dir); dma_unmap_sgtable(dev, sgt, dir, attrs);
sg_free_table(sgt); sg_free_table(sgt);
sgt->orig_nents = 0;
sgt->nents = 0;
} }
} }
void spi_unmap_buf(struct spi_controller *ctlr, struct device *dev,
struct sg_table *sgt, enum dma_data_direction dir)
{
spi_unmap_buf_attrs(ctlr, dev, sgt, dir, 0);
}
static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
{ {
struct device *tx_dev, *rx_dev; struct device *tx_dev, *rx_dev;
...@@ -1124,29 +1137,37 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) ...@@ -1124,29 +1137,37 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
rx_dev = ctlr->dev.parent; rx_dev = ctlr->dev.parent;
list_for_each_entry(xfer, &msg->transfers, transfer_list) { list_for_each_entry(xfer, &msg->transfers, transfer_list) {
/* The sync is done before each transfer. */
unsigned long attrs = DMA_ATTR_SKIP_CPU_SYNC;
if (!ctlr->can_dma(ctlr, msg->spi, xfer)) if (!ctlr->can_dma(ctlr, msg->spi, xfer))
continue; continue;
if (xfer->tx_buf != NULL) { if (xfer->tx_buf != NULL) {
ret = spi_map_buf(ctlr, tx_dev, &xfer->tx_sg, ret = spi_map_buf_attrs(ctlr, tx_dev, &xfer->tx_sg,
(void *)xfer->tx_buf, xfer->len, (void *)xfer->tx_buf,
DMA_TO_DEVICE); xfer->len, DMA_TO_DEVICE,
attrs);
if (ret != 0) if (ret != 0)
return ret; return ret;
} }
if (xfer->rx_buf != NULL) { if (xfer->rx_buf != NULL) {
ret = spi_map_buf(ctlr, rx_dev, &xfer->rx_sg, ret = spi_map_buf_attrs(ctlr, rx_dev, &xfer->rx_sg,
xfer->rx_buf, xfer->len, xfer->rx_buf, xfer->len,
DMA_FROM_DEVICE); DMA_FROM_DEVICE, attrs);
if (ret != 0) { if (ret != 0) {
spi_unmap_buf(ctlr, tx_dev, &xfer->tx_sg, spi_unmap_buf_attrs(ctlr, tx_dev,
DMA_TO_DEVICE); &xfer->tx_sg, DMA_TO_DEVICE,
attrs);
return ret; return ret;
} }
} }
} }
ctlr->cur_rx_dma_dev = rx_dev;
ctlr->cur_tx_dma_dev = tx_dev;
ctlr->cur_msg_mapped = true; ctlr->cur_msg_mapped = true;
return 0; return 0;
...@@ -1154,38 +1175,60 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) ...@@ -1154,38 +1175,60 @@ static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg)
static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg) static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg)
{ {
struct device *rx_dev = ctlr->cur_rx_dma_dev;
struct device *tx_dev = ctlr->cur_tx_dma_dev;
struct spi_transfer *xfer; struct spi_transfer *xfer;
struct device *tx_dev, *rx_dev;
if (!ctlr->cur_msg_mapped || !ctlr->can_dma) if (!ctlr->cur_msg_mapped || !ctlr->can_dma)
return 0; return 0;
if (ctlr->dma_tx)
tx_dev = ctlr->dma_tx->device->dev;
else if (ctlr->dma_map_dev)
tx_dev = ctlr->dma_map_dev;
else
tx_dev = ctlr->dev.parent;
if (ctlr->dma_rx)
rx_dev = ctlr->dma_rx->device->dev;
else if (ctlr->dma_map_dev)
rx_dev = ctlr->dma_map_dev;
else
rx_dev = ctlr->dev.parent;
list_for_each_entry(xfer, &msg->transfers, transfer_list) { list_for_each_entry(xfer, &msg->transfers, transfer_list) {
/* The sync has already been done after each transfer. */
unsigned long attrs = DMA_ATTR_SKIP_CPU_SYNC;
if (!ctlr->can_dma(ctlr, msg->spi, xfer)) if (!ctlr->can_dma(ctlr, msg->spi, xfer))
continue; continue;
spi_unmap_buf(ctlr, rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE); spi_unmap_buf_attrs(ctlr, rx_dev, &xfer->rx_sg,
spi_unmap_buf(ctlr, tx_dev, &xfer->tx_sg, DMA_TO_DEVICE); DMA_FROM_DEVICE, attrs);
spi_unmap_buf_attrs(ctlr, tx_dev, &xfer->tx_sg,
DMA_TO_DEVICE, attrs);
} }
ctlr->cur_msg_mapped = false; ctlr->cur_msg_mapped = false;
return 0; return 0;
} }
static void spi_dma_sync_for_device(struct spi_controller *ctlr,
struct spi_transfer *xfer)
{
struct device *rx_dev = ctlr->cur_rx_dma_dev;
struct device *tx_dev = ctlr->cur_tx_dma_dev;
if (!ctlr->cur_msg_mapped)
return;
if (xfer->tx_sg.orig_nents)
dma_sync_sgtable_for_device(tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
if (xfer->rx_sg.orig_nents)
dma_sync_sgtable_for_device(rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
}
static void spi_dma_sync_for_cpu(struct spi_controller *ctlr,
struct spi_transfer *xfer)
{
struct device *rx_dev = ctlr->cur_rx_dma_dev;
struct device *tx_dev = ctlr->cur_tx_dma_dev;
if (!ctlr->cur_msg_mapped)
return;
if (xfer->rx_sg.orig_nents)
dma_sync_sgtable_for_cpu(rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
if (xfer->tx_sg.orig_nents)
dma_sync_sgtable_for_cpu(tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
}
#else /* !CONFIG_HAS_DMA */ #else /* !CONFIG_HAS_DMA */
static inline int __spi_map_msg(struct spi_controller *ctlr, static inline int __spi_map_msg(struct spi_controller *ctlr,
struct spi_message *msg) struct spi_message *msg)
...@@ -1198,6 +1241,16 @@ static inline int __spi_unmap_msg(struct spi_controller *ctlr, ...@@ -1198,6 +1241,16 @@ static inline int __spi_unmap_msg(struct spi_controller *ctlr,
{ {
return 0; return 0;
} }
static void spi_dma_sync_for_device(struct spi_controller *ctrl,
struct spi_transfer *xfer)
{
}
static void spi_dma_sync_for_cpu(struct spi_controller *ctrl,
struct spi_transfer *xfer)
{
}
#endif /* !CONFIG_HAS_DMA */ #endif /* !CONFIG_HAS_DMA */
static inline int spi_unmap_msg(struct spi_controller *ctlr, static inline int spi_unmap_msg(struct spi_controller *ctlr,
...@@ -1435,7 +1488,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, ...@@ -1435,7 +1488,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
struct spi_statistics __percpu *statm = ctlr->pcpu_statistics; struct spi_statistics __percpu *statm = ctlr->pcpu_statistics;
struct spi_statistics __percpu *stats = msg->spi->pcpu_statistics; struct spi_statistics __percpu *stats = msg->spi->pcpu_statistics;
spi_set_cs(msg->spi, true, false); xfer = list_first_entry(&msg->transfers, struct spi_transfer, transfer_list);
spi_set_cs(msg->spi, !xfer->cs_off, false);
SPI_STATISTICS_INCREMENT_FIELD(statm, messages); SPI_STATISTICS_INCREMENT_FIELD(statm, messages);
SPI_STATISTICS_INCREMENT_FIELD(stats, messages); SPI_STATISTICS_INCREMENT_FIELD(stats, messages);
...@@ -1455,8 +1509,11 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, ...@@ -1455,8 +1509,11 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
reinit_completion(&ctlr->xfer_completion); reinit_completion(&ctlr->xfer_completion);
fallback_pio: fallback_pio:
spi_dma_sync_for_device(ctlr, xfer);
ret = ctlr->transfer_one(ctlr, msg->spi, xfer); ret = ctlr->transfer_one(ctlr, msg->spi, xfer);
if (ret < 0) { if (ret < 0) {
spi_dma_sync_for_cpu(ctlr, xfer);
if (ctlr->cur_msg_mapped && if (ctlr->cur_msg_mapped &&
(xfer->error & SPI_TRANS_FAIL_NO_START)) { (xfer->error & SPI_TRANS_FAIL_NO_START)) {
__spi_unmap_msg(ctlr, msg); __spi_unmap_msg(ctlr, msg);
...@@ -1479,6 +1536,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, ...@@ -1479,6 +1536,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
if (ret < 0) if (ret < 0)
msg->status = ret; msg->status = ret;
} }
spi_dma_sync_for_cpu(ctlr, xfer);
} else { } else {
if (xfer->len) if (xfer->len)
dev_err(&msg->spi->dev, dev_err(&msg->spi->dev,
...@@ -1503,10 +1562,15 @@ static int spi_transfer_one_message(struct spi_controller *ctlr, ...@@ -1503,10 +1562,15 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
&msg->transfers)) { &msg->transfers)) {
keep_cs = true; keep_cs = true;
} else { } else {
spi_set_cs(msg->spi, false, false); if (!xfer->cs_off)
spi_set_cs(msg->spi, false, false);
_spi_transfer_cs_change_delay(msg, xfer); _spi_transfer_cs_change_delay(msg, xfer);
spi_set_cs(msg->spi, true, false); if (!list_next_entry(xfer, transfer_list)->cs_off)
spi_set_cs(msg->spi, true, false);
} }
} else if (!list_is_last(&xfer->transfer_list, &msg->transfers) &&
xfer->cs_off != list_next_entry(xfer, transfer_list)->cs_off) {
spi_set_cs(msg->spi, xfer->cs_off, false);
} }
msg->actual_length += xfer->len; msg->actual_length += xfer->len;
...@@ -1587,6 +1651,15 @@ static int __spi_pump_transfer_message(struct spi_controller *ctlr, ...@@ -1587,6 +1651,15 @@ static int __spi_pump_transfer_message(struct spi_controller *ctlr,
trace_spi_message_start(msg); trace_spi_message_start(msg);
ret = spi_split_transfers_maxsize(ctlr, msg,
spi_max_transfer_size(msg->spi),
GFP_KERNEL | GFP_DMA);
if (ret) {
msg->status = ret;
spi_finalize_current_message(ctlr);
return ret;
}
if (ctlr->prepare_message) { if (ctlr->prepare_message) {
ret = ctlr->prepare_message(ctlr, msg); ret = ctlr->prepare_message(ctlr, msg);
if (ret) { if (ret) {
...@@ -2329,7 +2402,7 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi, ...@@ -2329,7 +2402,7 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi,
goto err_out; goto err_out;
} }
strlcpy(ancillary->modalias, "dummy", sizeof(ancillary->modalias)); strscpy(ancillary->modalias, "dummy", sizeof(ancillary->modalias));
/* Use provided chip-select for ancillary device */ /* Use provided chip-select for ancillary device */
ancillary->chip_select = chip_select; ancillary->chip_select = chip_select;
...@@ -2725,7 +2798,7 @@ static ssize_t slave_store(struct device *dev, struct device_attribute *attr, ...@@ -2725,7 +2798,7 @@ static ssize_t slave_store(struct device *dev, struct device_attribute *attr,
if (!spi) if (!spi)
return -ENOMEM; return -ENOMEM;
strlcpy(spi->modalias, name, sizeof(spi->modalias)); strscpy(spi->modalias, name, sizeof(spi->modalias));
rc = spi_add_device(spi); rc = spi_add_device(spi);
if (rc) { if (rc) {
......
...@@ -378,6 +378,8 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch ...@@ -378,6 +378,8 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
* @cleanup: frees controller-specific state * @cleanup: frees controller-specific state
* @can_dma: determine whether this controller supports DMA * @can_dma: determine whether this controller supports DMA
* @dma_map_dev: device which can be used for DMA mapping * @dma_map_dev: device which can be used for DMA mapping
* @cur_rx_dma_dev: device which is currently used for RX DMA mapping
* @cur_tx_dma_dev: device which is currently used for TX DMA mapping
* @queued: whether this controller is providing an internal message queue * @queued: whether this controller is providing an internal message queue
* @kworker: pointer to thread struct for message pump * @kworker: pointer to thread struct for message pump
* @pump_messages: work struct for scheduling work to the message pump * @pump_messages: work struct for scheduling work to the message pump
...@@ -610,6 +612,8 @@ struct spi_controller { ...@@ -610,6 +612,8 @@ struct spi_controller {
struct spi_device *spi, struct spi_device *spi,
struct spi_transfer *xfer); struct spi_transfer *xfer);
struct device *dma_map_dev; struct device *dma_map_dev;
struct device *cur_rx_dma_dev;
struct device *cur_tx_dma_dev;
/* /*
* These hooks are for drivers that want to use the generic * These hooks are for drivers that want to use the generic
...@@ -848,6 +852,7 @@ struct spi_res { ...@@ -848,6 +852,7 @@ struct spi_res {
* @bits_per_word: select a bits_per_word other than the device default * @bits_per_word: select a bits_per_word other than the device default
* for this transfer. If 0 the default (from @spi_device) is used. * for this transfer. If 0 the default (from @spi_device) is used.
* @dummy_data: indicates transfer is dummy bytes transfer. * @dummy_data: indicates transfer is dummy bytes transfer.
* @cs_off: performs the transfer with chipselect off.
* @cs_change: affects chipselect after this transfer completes * @cs_change: affects chipselect after this transfer completes
* @cs_change_delay: delay between cs deassert and assert when * @cs_change_delay: delay between cs deassert and assert when
* @cs_change is set and @spi_transfer is not the last in @spi_message * @cs_change is set and @spi_transfer is not the last in @spi_message
...@@ -958,6 +963,7 @@ struct spi_transfer { ...@@ -958,6 +963,7 @@ struct spi_transfer {
struct sg_table rx_sg; struct sg_table rx_sg;
unsigned dummy_data:1; unsigned dummy_data:1;
unsigned cs_off:1;
unsigned cs_change:1; unsigned cs_change:1;
unsigned tx_nbits:3; unsigned tx_nbits:3;
unsigned rx_nbits:3; unsigned rx_nbits:3;
......
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