spi: Updates for v6.1

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 o
 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.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmM62YIACgkQJNaLcl1U
 h9CvPAf+MF1AzJJWH9DkR846KQh7Zt1rrujRuj5SGwvHewqjJcDtDmipAbM7mRFa
 VPk6fCzfRE4btVywCDMEQX2ToB9VKBNUeP8ihVLddWrTddbkQ7hOKlTrz31dJ+6W
 F9kwXkWcqWEpMYD/wr/25eT/kkNfv27oCyPU4dRQKoGGeF+zb9jYoj0+gPDl9Om8
 ok7D1XAwY1wOqYqdPfl2thcUrBfoKtFvkTj+NNhqwuzWwIqfQHM2skwAjmD3fliQ
 lLdRc54erCOqukDddIoWr348TyJIT4v1IXnkqY3cd7da6+kpixWae73o/7WIcQUR
 4MrtPply0WWcapgU/46sCbHpjJNjjg==
 =PDCv
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Linus Torvalds 2022-10-04 19:36:53 -07:00
commit 2bca25eaeb
51 changed files with 1434 additions and 420 deletions

View file

@ -23,6 +23,8 @@ properties:
reg: true
reset-gpios: true
spi-3wire: true
required:
- compatible
- power-supply

View file

@ -24,6 +24,8 @@ properties:
reg: true
reset-gpios: true
spi-3wire: true
required:
- compatible
- power-supply

View file

@ -24,6 +24,10 @@ properties:
default-brightness: true
max-brightness: true
spi-3wire: true
spi-cpha: true
spi-cpol: true
vdd3-supply:
description: VDD regulator

View file

@ -4,7 +4,11 @@
$id: http://devicetree.org/schemas/spi/microchip,mpfs-spi.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:
- Conor Dooley <conor.dooley@microchip.com>
@ -14,9 +18,12 @@ allOf:
properties:
compatible:
enum:
- microchip,mpfs-spi
- microchip,mpfs-qspi
oneOf:
- items:
- const: microchip,mpfs-qspi
- const: microchip,coreqspi-rtl-v2
- const: microchip,coreqspi-rtl-v2 #FPGA QSPI
- const: microchip,mpfs-spi
reg:
maxItems: 1

View file

@ -3,7 +3,8 @@ Nuvoton NPCM Peripheral Serial Peripheral Interface(PSPI) controller driver
Nuvoton NPCM7xx SOC support two PSPI channels.
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
- #size-cells : should be 0. see spi-bus.txt
- specifies physical base address and size of the register.

View file

@ -29,5 +29,4 @@ properties:
minimum: 0
maximum: 255
unevaluatedProperties: true
additionalProperties: true

View file

@ -0,0 +1,61 @@
# 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>;
};

View file

@ -47,9 +47,15 @@ properties:
- renesas,msiof-r8a77980 # R-Car V3H
- renesas,msiof-r8a77990 # R-Car E3
- renesas,msiof-r8a77995 # R-Car D3
- renesas,msiof-r8a779a0 # R-Car V3U
- const: renesas,rcar-gen3-msiof # generic R-Car Gen3 and RZ/G2
# 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:
- const: renesas,sh-msiof # deprecated
@ -69,6 +75,12 @@ properties:
clocks:
maxItems: 1
power-domains:
maxItems: 1
resets:
maxItems: 1
num-cs:
description: |
Total number of chip selects (default is 1).

View file

@ -104,7 +104,6 @@ properties:
const: spi
reg-io-width:
$ref: /schemas/types.yaml#/definitions/uint32
description: I/O register width (in bytes) implemented by this device
default: 4
enum: [ 2, 4 ]

View file

@ -96,6 +96,11 @@ patternProperties:
$ref: spi-peripheral-props.yaml
properties:
spi-3wire:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires 3-wire mode.
spi-cpha:
$ref: /schemas/types.yaml#/definitions/flag
description:

View file

@ -19,7 +19,9 @@ properties:
- fsl,imx7ulp-spi
- fsl,imx8qxp-spi
- items:
- const: fsl,imx8ulp-spi
- enum:
- fsl,imx8ulp-spi
- fsl,imx93-spi
- const: fsl,imx7ulp-spi
reg:
maxItems: 1
@ -37,6 +39,16 @@ properties:
- const: per
- 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:
description:
spi common code does not support use of CS signals discontinuously.

View file

@ -1,26 +0,0 @@
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";
};

View file

@ -29,11 +29,6 @@ properties:
description:
Chip select used by the device.
spi-3wire:
$ref: /schemas/types.yaml#/definitions/flag
description:
The device requires 3-wire mode.
spi-cs-high:
$ref: /schemas/types.yaml#/definitions/flag
description:

View file

@ -27,6 +27,7 @@ properties:
- items:
- enum:
- rockchip,px30-spi
- rockchip,rk3128-spi
- rockchip,rk3188-spi
- rockchip,rk3288-spi
- rockchip,rk3308-spi
@ -34,6 +35,7 @@ properties:
- rockchip,rk3368-spi
- rockchip,rk3399-spi
- rockchip,rk3568-spi
- rockchip,rk3588-spi
- rockchip,rv1126-spi
- const: rockchip,rk3066-spi
@ -80,6 +82,9 @@ properties:
where the "sleep" configuration may describe the state
the pins should be in during system suspend.
power-domains:
maxItems: 1
required:
- compatible
- reg

View file

@ -17568,6 +17568,7 @@ F: drivers/mailbox/mailbox-mpfs.c
F: drivers/pci/controller/pcie-microchip-host.c
F: drivers/rtc/rtc-mpfs.c
F: drivers/soc/microchip/
F: drivers/spi/spi-microchip-core-qspi.c
F: drivers/spi/spi-microchip-core.c
F: drivers/usb/musb/mpfs.c
F: include/soc/microchip/mpfs.h

View file

@ -591,6 +591,15 @@ config SPI_MICROCHIP_CORE
PolarFire SoC.
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
tristate "MediaTek SPI controller"
depends on ARCH_MEDIATEK || COMPILE_TEST

View file

@ -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_SPIFC) += spi-meson-spifc.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_MPC52xx_PSC) += spi-mpc52xx-psc.o
obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o

View file

@ -36,9 +36,17 @@
#define AMD_SPI_FIFO_SIZE 70
#define AMD_SPI_MEM_SIZE 200
/* M_CMD OP codes for SPI */
#define AMD_SPI_XFER_TX 1
#define AMD_SPI_XFER_RX 2
#define AMD_SPI_ENA_REG 0x20
#define AMD_SPI_ALT_SPD_SHIFT 20
#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
@ -50,14 +58,41 @@ enum amd_spi_versions {
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
* @io_remap_addr: Start address of the SPI controller registers
* @version: SPI controller hardware version
* @speed_hz: Device frequency
*/
struct amd_spi {
void __iomem *io_remap_addr;
enum amd_spi_versions version;
unsigned int speed_hz;
};
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)
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,
struct spi_master *master,
struct spi_message *message)
{
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;
u32 m_cmd = 0;
u32 i = 0;
u32 tx_len = 0, rx_len = 0;
list_for_each_entry(xfer, &message->transfers,
transfer_list) {
if (xfer->rx_buf)
m_cmd = AMD_SPI_XFER_RX;
if (xfer->tx_buf)
m_cmd = AMD_SPI_XFER_TX;
if (xfer->speed_hz)
amd_set_spi_freq(amd_spi, xfer->speed_hz);
else
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;
tx_len = xfer->len - 1;
cmd_opcode = *(u8 *)xfer->tx_buf;
buf++;
amd_spi_set_opcode(amd_spi, cmd_opcode);
if (!tx_len) {
cmd_opcode = *(u8 *)xfer->tx_buf;
buf++;
xfer->len--;
}
tx_len += xfer->len;
/* Write data into the FIFO. */
for (i = 0; i < tx_len; i++) {
iowrite8(buf[i], ((u8 __iomem *)amd_spi->io_remap_addr +
AMD_SPI_FIFO_BASE + i));
}
for (i = 0; i < xfer->len; i++)
amd_spi_writereg8(amd_spi, fifo_pos + i, buf[i]);
amd_spi_set_tx_count(amd_spi, tx_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);
fifo_pos += xfer->len;
}
/* 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 */
message->actual_length = tx_len + rx_len + 1;
/* complete the transaction */
message->status = 0;
fin_msg:
switch (amd_spi->version) {
case AMD_SPI_V1:
break;
@ -260,7 +355,7 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
spi_finalize_current_message(master);
return 0;
return message->status;
}
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
* program the controller.
*/
amd_spi_fifo_xfer(amd_spi, master, msg);
return 0;
return amd_spi_fifo_xfer(amd_spi, master, msg);
}
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)
master->num_chipselect = 4;
master->mode_bits = 0;
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->transfer_one_message = amd_spi_master_transfer;
master->max_transfer_size = amd_spi_max_transfer_size;

View file

@ -736,10 +736,8 @@ static int aspeed_spi_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
aspi->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(aspi->regs)) {
dev_err(dev, "missing AHB register window\n");
if (IS_ERR(aspi->regs))
return PTR_ERR(aspi->regs);
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
aspi->ahb_base = devm_ioremap_resource(dev, res);

View file

@ -1645,7 +1645,7 @@ static int cqspi_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
return ret;
goto probe_pm_failed;
ret = clk_prepare_enable(cqspi->clk);
if (ret) {
@ -1740,6 +1740,7 @@ static int cqspi_probe(struct platform_device *pdev)
clk_disable_unprepare(cqspi->clk);
probe_clk_failed:
pm_runtime_put_sync(dev);
probe_pm_failed:
pm_runtime_disable(dev);
return ret;
}

View file

@ -565,10 +565,8 @@ static int cdns_xspi_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sdma");
cdns_xspi->sdmabase = devm_ioremap_resource(dev, res);
if (IS_ERR(cdns_xspi->sdmabase)) {
dev_err(dev, "Failed to remap SDMA address\n");
if (IS_ERR(cdns_xspi->sdmabase))
return PTR_ERR(cdns_xspi->sdmabase);
}
cdns_xspi->sdmasize = resource_size(res);
cdns_xspi->auxbase = devm_platform_ioremap_resource_byname(pdev, "aux");

View file

@ -293,8 +293,10 @@ static int dw_spi_bt1_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
ret = dw_spi_add_host(&pdev->dev, dws);
if (ret)
if (ret) {
pm_runtime_disable(&pdev->dev);
goto err_disable_clk;
}
platform_set_drvdata(pdev, dwsbt1);

View file

@ -955,7 +955,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
ret = spi_register_controller(master);
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;
}

View file

@ -1294,8 +1294,7 @@ static int dspi_probe(struct platform_device *pdev)
else
ctlr->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(base)) {
ret = PTR_ERR(base);
goto out_ctlr_put;

View file

@ -855,8 +855,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
init_completion(&fsl_lpspi->xfer_done);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
fsl_lpspi->base = devm_ioremap_resource(&pdev->dev, res);
fsl_lpspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(fsl_lpspi->base)) {
ret = PTR_ERR(fsl_lpspi->base);
goto out_controller_put;
@ -912,7 +911,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
ret = devm_spi_register_controller(&pdev->dev, controller);
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;
}
@ -947,11 +946,8 @@ static int fsl_lpspi_remove(struct platform_device *pdev)
static int __maybe_unused fsl_lpspi_suspend(struct device *dev)
{
int ret;
pinctrl_pm_select_sleep_state(dev);
ret = pm_runtime_force_suspend(dev);
return ret;
return pm_runtime_force_suspend(dev);
}
static int __maybe_unused fsl_lpspi_resume(struct device *dev)

View file

@ -867,8 +867,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, q);
/* find the resources */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI");
q->iobase = devm_ioremap_resource(dev, res);
q->iobase = devm_platform_ioremap_resource_byname(pdev, "QuadSPI");
if (IS_ERR(q->iobase)) {
ret = PTR_ERR(q->iobase);
goto err_put_ctrl;

View file

@ -111,32 +111,6 @@ static void fsl_spi_change_mode(struct spi_device *spi)
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,
int bits_per_word, int msb_first)
{
@ -354,15 +328,11 @@ static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
return mpc8xxx_spi->count;
}
static int fsl_spi_do_one_msg(struct spi_master *master,
struct spi_message *m)
static int fsl_spi_prepare_message(struct spi_controller *ctlr,
struct spi_message *m)
{
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct spi_device *spi = m->spi;
struct spi_transfer *t, *first;
unsigned int cs_change;
const int nsecs = 50;
int status, last_bpw;
struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(ctlr);
struct spi_transfer *t;
/*
* In CPU mode, optimize large byte transfers to use larger
@ -378,64 +348,32 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
t->bits_per_word = 16;
}
}
/* Don't allow changes if CS is active */
cs_change = 1;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (cs_change)
first = t;
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;
if (status || !cs_change) {
ndelay(nsecs);
fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
}
fsl_spi_setup_transfer(spi, NULL);
spi_finalize_current_message(master);
return 0;
}
static int fsl_spi_transfer_one(struct spi_controller *controller,
struct spi_device *spi,
struct spi_transfer *t)
{
int 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;
return status;
}
static int fsl_spi_unprepare_message(struct spi_controller *controller,
struct spi_message *msg)
{
return fsl_spi_setup_transfer(msg->spi, NULL);
}
static int fsl_spi_setup(struct spi_device *spi)
{
struct mpc8xxx_spi *mpc8xxx_spi;
@ -482,9 +420,6 @@ static int fsl_spi_setup(struct spi_device *spi)
return retval;
}
/* Initialize chipselect - might be active for SPI_CS_HIGH mode */
fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
return 0;
}
@ -557,9 +492,7 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
u32 slvsel;
u16 cs = spi->chip_select;
if (spi->cs_gpiod) {
gpiod_set_value(spi->cs_gpiod, on);
} else if (cs < mpc8xxx_spi->native_chipselects) {
if (cs < mpc8xxx_spi->native_chipselects) {
slvsel = mpc8xxx_spi_read_reg(&reg_base->slvsel);
slvsel = on ? (slvsel | (1 << cs)) : (slvsel & ~(1 << cs));
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)
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 mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base;
@ -588,7 +520,18 @@ static void fsl_spi_grlib_probe(struct device *dev)
mpc8xxx_spi_write_reg(&reg_base->slvsel, 0xffffffff);
}
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,
@ -613,8 +556,11 @@ static struct spi_master *fsl_spi_probe(struct device *dev,
master->setup = fsl_spi_setup;
master->cleanup = fsl_spi_cleanup;
master->transfer_one_message = fsl_spi_do_one_msg;
master->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->set_cs = fsl_spi_cs_control;
mpc8xxx_spi = spi_master_get_devdata(master);
mpc8xxx_spi->max_bits_per_word = 32;
@ -688,21 +634,6 @@ static struct spi_master *fsl_spi_probe(struct device *dev,
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)
{
struct device *dev = &ofdev->dev;
@ -744,12 +675,10 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
ret = gpiod_count(dev, "cs");
if (ret < 0)
ret = 0;
if (ret == 0 && !spisel_boot) {
if (ret == 0 && !spisel_boot)
pdata->max_chipselect = 1;
} else {
else
pdata->max_chipselect = ret + spisel_boot;
pdata->cs_control = fsl_spi_cs_control;
}
}
ret = of_address_to_resource(np, 0, &mem);

View file

@ -254,7 +254,6 @@ static int gxp_spifi_probe(struct platform_device *pdev)
const struct gxp_spi_data *data;
struct spi_controller *ctlr;
struct gxp_spi *spifi;
struct resource *res;
int ret;
data = of_device_get_match_data(&pdev->dev);
@ -269,18 +268,15 @@ static int gxp_spifi_probe(struct platform_device *pdev)
spifi->data = data;
spifi->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spifi->reg_base = devm_ioremap_resource(&pdev->dev, res);
spifi->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(spifi->reg_base))
return PTR_ERR(spifi->reg_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
spifi->dat_base = devm_ioremap_resource(&pdev->dev, res);
spifi->dat_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(spifi->dat_base))
return PTR_ERR(spifi->dat_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
spifi->dir_base = devm_ioremap_resource(&pdev->dev, res);
spifi->dir_base = devm_platform_ioremap_resource(pdev, 2);
if (IS_ERR(spifi->dir_base))
return PTR_ERR(spifi->dir_base);

View file

@ -730,11 +730,9 @@ static int img_spfi_resume(struct device *dev)
struct img_spfi *spfi = spi_master_get_devdata(master);
int ret;
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
pm_runtime_put_noidle(dev);
ret = pm_runtime_resume_and_get(dev);
if (ret < 0)
return ret;
}
spfi_reset(spfi);
pm_runtime_put(dev);

View file

@ -116,6 +116,22 @@
#define ERASE_64K_OPCODE_SHIFT 16
#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_FIFO_SZ 64
@ -129,6 +145,7 @@
* @master: Pointer to the SPI controller structure
* @nregions: Maximum number of regions
* @pr_num: Maximum number of protected range registers
* @chip0_size: Size of the first flash chip in bytes
* @locked: Is SPI setting locked
* @swseq_reg: Use SW sequencer in register reads/writes
* @swseq_erase: Use SW sequencer in erase operation
@ -146,6 +163,7 @@ struct intel_spi {
struct spi_controller *master;
size_t nregions;
size_t pr_num;
size_t chip0_size;
bool locked;
bool swseq_reg;
bool swseq_erase;
@ -158,6 +176,7 @@ struct intel_spi_mem_op {
struct spi_mem_op mem_op;
u32 replacement_op;
int (*exec_op)(struct intel_spi *ispi,
const struct spi_mem *mem,
const struct intel_spi_mem_op *iop,
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,
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 spi_mem_op *op)
{
@ -449,8 +477,7 @@ static int intel_spi_read_reg(struct intel_spi *ispi,
u8 opcode = op->cmd.opcode;
int ret;
/* Address of the first chip */
writel(0, ispi->base + FADDR);
writel(intel_spi_chip_addr(ispi, mem), ispi->base + FADDR);
if (ispi->swseq_reg)
ret = intel_spi_sw_cycle(ispi, opcode, nbytes,
@ -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);
}
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 spi_mem_op *op)
{
@ -511,7 +538,7 @@ static int intel_spi_write_reg(struct intel_spi *ispi,
if (opcode == SPINOR_OP_WRDI)
return 0;
writel(0, ispi->base + FADDR);
writel(intel_spi_chip_addr(ispi, mem), ispi->base + FADDR);
/* Write the value beforehand */
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,
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 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;
u32 addr = op->addr.val;
void *read_buf = op->data.buf.in;
u32 val, status;
int ret;
@ -585,13 +612,13 @@ static int intel_spi_read(struct intel_spi *ispi,
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 spi_mem_op *op)
{
u32 addr = intel_spi_chip_addr(ispi, mem) + op->addr.val;
size_t block_size, nbytes = op->data.nbytes;
const void *write_buf = op->data.buf.out;
u32 addr = op->addr.val;
u32 val, status;
int ret;
@ -648,12 +675,12 @@ static int intel_spi_write(struct intel_spi *ispi,
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 spi_mem_op *op)
{
u32 addr = intel_spi_chip_addr(ispi, mem) + op->addr.val;
u8 opcode = op->cmd.opcode;
u32 addr = op->addr.val;
u32 val, status;
int ret;
@ -765,7 +792,7 @@ static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *o
if (!iop)
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)
@ -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.buf.in = buf;
ret = iop->exec_op(ispi, iop, &op);
ret = iop->exec_op(ispi, desc->mem, iop, &op);
return ret ? ret : len;
}
@ -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.buf.out = buf;
ret = iop->exec_op(ispi, iop, &op);
ret = iop->exec_op(ispi, desc->mem, iop, &op);
return ret ? ret : len;
}
@ -1073,6 +1100,7 @@ static int intel_spi_init(struct intel_spi *ispi)
ispi->pregs = ispi->base + CNL_PR;
ispi->nregions = CNL_FREG_NUM;
ispi->pr_num = CNL_PR_NUM;
erase_64k = true;
break;
default:
@ -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)
{
struct flash_platform_data *pdata;
struct spi_board_info chip;
int ret;
pdata = devm_kzalloc(ispi->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@ -1247,7 +1363,23 @@ static int intel_spi_populate_chip(struct intel_spi *ispi)
snprintf(chip.modalias, 8, "spi-nor");
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;
}
/**

View file

@ -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 */ }
};

View file

@ -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 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 clk_divider_ops.recalc_rate(hw, parent_rate);
@ -549,7 +549,7 @@ static int meson_spicc_pow2_determine_rate(struct clk_hw *hw,
struct clk_divider *divider = to_clk_divider(hw);
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 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,
struct clk_divider *divider = to_clk_divider(hw);
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 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,
.determine_rate = meson_spicc_pow2_determine_rate,
.set_rate = meson_spicc_pow2_set_rate,

View file

@ -0,0 +1,600 @@
// SPDX-License-Identifier: (GPL-2.0)
/*
* Microchip coreQSPI QSPI controller driver
*
* Copyright (C) 2018-2022 Microchip Technology Inc. and its subsidiaries
*
* Author: Naga Sureshkumar Relli <nagasuresh.relli@microchip.com>
*
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>
/*
* QSPI Control register mask defines
*/
#define CONTROL_ENABLE BIT(0)
#define CONTROL_MASTER BIT(1)
#define CONTROL_XIP BIT(2)
#define CONTROL_XIPADDR BIT(3)
#define CONTROL_CLKIDLE BIT(10)
#define CONTROL_SAMPLE_MASK GENMASK(12, 11)
#define CONTROL_MODE0 BIT(13)
#define CONTROL_MODE12_MASK GENMASK(15, 14)
#define CONTROL_MODE12_EX_RO BIT(14)
#define CONTROL_MODE12_EX_RW BIT(15)
#define CONTROL_MODE12_FULL GENMASK(15, 14)
#define CONTROL_FLAGSX4 BIT(16)
#define CONTROL_CLKRATE_MASK GENMASK(27, 24)
#define CONTROL_CLKRATE_SHIFT 24
/*
* QSPI Frames register mask defines
*/
#define FRAMES_TOTALBYTES_MASK GENMASK(15, 0)
#define FRAMES_CMDBYTES_MASK GENMASK(24, 16)
#define FRAMES_CMDBYTES_SHIFT 16
#define FRAMES_SHIFT 25
#define FRAMES_IDLE_MASK GENMASK(29, 26)
#define FRAMES_IDLE_SHIFT 26
#define FRAMES_FLAGBYTE BIT(30)
#define FRAMES_FLAGWORD BIT(31)
/*
* QSPI Interrupt Enable register mask defines
*/
#define IEN_TXDONE BIT(0)
#define IEN_RXDONE BIT(1)
#define IEN_RXAVAILABLE BIT(2)
#define IEN_TXAVAILABLE BIT(3)
#define IEN_RXFIFOEMPTY BIT(4)
#define IEN_TXFIFOFULL BIT(5)
/*
* QSPI Status register mask defines
*/
#define STATUS_TXDONE BIT(0)
#define STATUS_RXDONE BIT(1)
#define STATUS_RXAVAILABLE BIT(2)
#define STATUS_TXAVAILABLE BIT(3)
#define STATUS_RXFIFOEMPTY BIT(4)
#define STATUS_TXFIFOFULL BIT(5)
#define STATUS_READY BIT(7)
#define STATUS_FLAGSX4 BIT(8)
#define STATUS_MASK GENMASK(8, 0)
#define BYTESUPPER_MASK GENMASK(31, 16)
#define BYTESLOWER_MASK GENMASK(15, 0)
#define MAX_DIVIDER 16
#define MIN_DIVIDER 0
#define MAX_DATA_CMD_LEN 256
/* QSPI ready time out value */
#define TIMEOUT_MS 500
/*
* QSPI Register offsets.
*/
#define REG_CONTROL (0x00)
#define REG_FRAMES (0x04)
#define REG_IEN (0x0c)
#define REG_STATUS (0x10)
#define REG_DIRECT_ACCESS (0x14)
#define REG_UPPER_ACCESS (0x18)
#define REG_RX_DATA (0x40)
#define REG_TX_DATA (0x44)
#define REG_X4_RX_DATA (0x48)
#define REG_X4_TX_DATA (0x4c)
#define REG_FRAMESUP (0x50)
/**
* struct mchp_coreqspi - Defines qspi driver instance
* @regs: Virtual address of the QSPI controller registers
* @clk: QSPI Operating clock
* @data_completion: completion structure
* @op_lock: lock access to the device
* @txbuf: TX buffer
* @rxbuf: RX buffer
* @irq: IRQ number
* @tx_len: Number of bytes left to transfer
* @rx_len: Number of bytes left to receive
*/
struct mchp_coreqspi {
void __iomem *regs;
struct clk *clk;
struct completion data_completion;
struct mutex op_lock; /* lock access to the device */
u8 *txbuf;
u8 *rxbuf;
int irq;
int tx_len;
int rx_len;
};
static int mchp_coreqspi_set_mode(struct mchp_coreqspi *qspi, const struct spi_mem_op *op)
{
u32 control = readl_relaxed(qspi->regs + REG_CONTROL);
/*
* The operating mode can be configured based on the command that needs to be send.
* bits[15:14]: Sets whether multiple bit SPI operates in normal, extended or full modes.
* 00: Normal (single DQ0 TX and single DQ1 RX lines)
* 01: Extended RO (command and address bytes on DQ0 only)
* 10: Extended RW (command byte on DQ0 only)
* 11: Full. (command and address are on all DQ lines)
* bit[13]: Sets whether multiple bit SPI uses 2 or 4 bits of data
* 0: 2-bits (BSPI)
* 1: 4-bits (QSPI)
*/
if (op->data.buswidth == 4 || op->data.buswidth == 2) {
control &= ~CONTROL_MODE12_MASK;
if (op->cmd.buswidth == 1 && (op->addr.buswidth == 1 || op->addr.buswidth == 0))
control |= CONTROL_MODE12_EX_RO;
else if (op->cmd.buswidth == 1)
control |= CONTROL_MODE12_EX_RW;
else
control |= CONTROL_MODE12_FULL;
control |= CONTROL_MODE0;
} else {
control &= ~(CONTROL_MODE12_MASK |
CONTROL_MODE0);
}
writel_relaxed(control, qspi->regs + REG_CONTROL);
return 0;
}
static inline void mchp_coreqspi_read_op(struct mchp_coreqspi *qspi)
{
u32 control, data;
if (!qspi->rx_len)
return;
control = readl_relaxed(qspi->regs + REG_CONTROL);
/*
* Read 4-bytes from the SPI FIFO in single transaction and then read
* the reamaining data byte wise.
*/
control |= CONTROL_FLAGSX4;
writel_relaxed(control, qspi->regs + REG_CONTROL);
while (qspi->rx_len >= 4) {
while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_RXFIFOEMPTY)
;
data = readl_relaxed(qspi->regs + REG_X4_RX_DATA);
*(u32 *)qspi->rxbuf = data;
qspi->rxbuf += 4;
qspi->rx_len -= 4;
}
control &= ~CONTROL_FLAGSX4;
writel_relaxed(control, qspi->regs + REG_CONTROL);
while (qspi->rx_len--) {
while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_RXFIFOEMPTY)
;
data = readl_relaxed(qspi->regs + REG_RX_DATA);
*qspi->rxbuf++ = (data & 0xFF);
}
}
static inline void mchp_coreqspi_write_op(struct mchp_coreqspi *qspi, bool word)
{
u32 control, data;
control = readl_relaxed(qspi->regs + REG_CONTROL);
control |= CONTROL_FLAGSX4;
writel_relaxed(control, qspi->regs + REG_CONTROL);
while (qspi->tx_len >= 4) {
while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_TXFIFOFULL)
;
data = *(u32 *)qspi->txbuf;
qspi->txbuf += 4;
qspi->tx_len -= 4;
writel_relaxed(data, qspi->regs + REG_X4_TX_DATA);
}
control &= ~CONTROL_FLAGSX4;
writel_relaxed(control, qspi->regs + REG_CONTROL);
while (qspi->tx_len--) {
while (readl_relaxed(qspi->regs + REG_STATUS) & STATUS_TXFIFOFULL)
;
data = *qspi->txbuf++;
writel_relaxed(data, qspi->regs + REG_TX_DATA);
}
}
static void mchp_coreqspi_enable_ints(struct mchp_coreqspi *qspi)
{
u32 mask = IEN_TXDONE |
IEN_RXDONE |
IEN_RXAVAILABLE;
writel_relaxed(mask, qspi->regs + REG_IEN);
}
static void mchp_coreqspi_disable_ints(struct mchp_coreqspi *qspi)
{
writel_relaxed(0, qspi->regs + REG_IEN);
}
static irqreturn_t mchp_coreqspi_isr(int irq, void *dev_id)
{
struct mchp_coreqspi *qspi = (struct mchp_coreqspi *)dev_id;
irqreturn_t ret = IRQ_NONE;
int intfield = readl_relaxed(qspi->regs + REG_STATUS) & STATUS_MASK;
if (intfield == 0)
return ret;
if (intfield & IEN_TXDONE) {
writel_relaxed(IEN_TXDONE, qspi->regs + REG_STATUS);
ret = IRQ_HANDLED;
}
if (intfield & IEN_RXAVAILABLE) {
writel_relaxed(IEN_RXAVAILABLE, qspi->regs + REG_STATUS);
mchp_coreqspi_read_op(qspi);
ret = IRQ_HANDLED;
}
if (intfield & IEN_RXDONE) {
writel_relaxed(IEN_RXDONE, qspi->regs + REG_STATUS);
complete(&qspi->data_completion);
ret = IRQ_HANDLED;
}
return ret;
}
static int mchp_coreqspi_setup_clock(struct mchp_coreqspi *qspi, struct spi_device *spi)
{
unsigned long clk_hz;
u32 control, baud_rate_val = 0;
clk_hz = clk_get_rate(qspi->clk);
if (!clk_hz)
return -EINVAL;
baud_rate_val = DIV_ROUND_UP(clk_hz, 2 * spi->max_speed_hz);
if (baud_rate_val > MAX_DIVIDER || baud_rate_val < MIN_DIVIDER) {
dev_err(&spi->dev,
"could not configure the clock for spi clock %d Hz & system clock %ld Hz\n",
spi->max_speed_hz, clk_hz);
return -EINVAL;
}
control = readl_relaxed(qspi->regs + REG_CONTROL);
control |= baud_rate_val << CONTROL_CLKRATE_SHIFT;
writel_relaxed(control, qspi->regs + REG_CONTROL);
control = readl_relaxed(qspi->regs + REG_CONTROL);
if ((spi->mode & SPI_CPOL) && (spi->mode & SPI_CPHA))
control |= CONTROL_CLKIDLE;
else
control &= ~CONTROL_CLKIDLE;
writel_relaxed(control, qspi->regs + REG_CONTROL);
return 0;
}
static int mchp_coreqspi_setup_op(struct spi_device *spi_dev)
{
struct spi_controller *ctlr = spi_dev->master;
struct mchp_coreqspi *qspi = spi_controller_get_devdata(ctlr);
u32 control = readl_relaxed(qspi->regs + REG_CONTROL);
control |= (CONTROL_MASTER | CONTROL_ENABLE);
control &= ~CONTROL_CLKIDLE;
writel_relaxed(control, qspi->regs + REG_CONTROL);
return 0;
}
static inline void mchp_coreqspi_config_op(struct mchp_coreqspi *qspi, const struct spi_mem_op *op)
{
u32 idle_cycles = 0;
int total_bytes, cmd_bytes, frames, ctrl;
cmd_bytes = op->cmd.nbytes + op->addr.nbytes;
total_bytes = cmd_bytes + op->data.nbytes;
/*
* As per the coreQSPI IP spec,the number of command and data bytes are
* controlled by the frames register for each SPI sequence. This supports
* the SPI flash memory read and writes sequences as below. so configure
* the cmd and total bytes accordingly.
* ---------------------------------------------------------------------
* TOTAL BYTES | CMD BYTES | What happens |
* ______________________________________________________________________
* | | |
* 1 | 1 | The SPI core will transmit a single byte |
* | | and receive data is discarded |
* | | |
* 1 | 0 | The SPI core will transmit a single byte |
* | | and return a single byte |
* | | |
* 10 | 4 | The SPI core will transmit 4 command |
* | | bytes discarding the receive data and |
* | | transmits 6 dummy bytes returning the 6 |
* | | received bytes and return a single byte |
* | | |
* 10 | 10 | The SPI core will transmit 10 command |
* | | |
* 10 | 0 | The SPI core will transmit 10 command |
* | | bytes and returning 10 received bytes |
* ______________________________________________________________________
*/
if (!(op->data.dir == SPI_MEM_DATA_IN))
cmd_bytes = total_bytes;
frames = total_bytes & BYTESUPPER_MASK;
writel_relaxed(frames, qspi->regs + REG_FRAMESUP);
frames = total_bytes & BYTESLOWER_MASK;
frames |= cmd_bytes << FRAMES_CMDBYTES_SHIFT;
if (op->dummy.buswidth)
idle_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth;
frames |= idle_cycles << FRAMES_IDLE_SHIFT;
ctrl = readl_relaxed(qspi->regs + REG_CONTROL);
if (ctrl & CONTROL_MODE12_MASK)
frames |= (1 << FRAMES_SHIFT);
frames |= FRAMES_FLAGWORD;
writel_relaxed(frames, qspi->regs + REG_FRAMES);
}
static int mchp_qspi_wait_for_ready(struct spi_mem *mem)
{
struct mchp_coreqspi *qspi = spi_controller_get_devdata
(mem->spi->master);
u32 status;
int ret;
ret = readl_poll_timeout(qspi->regs + REG_STATUS, status,
(status & STATUS_READY), 0,
TIMEOUT_MS);
if (ret) {
dev_err(&mem->spi->dev,
"Timeout waiting on QSPI ready.\n");
return -ETIMEDOUT;
}
return ret;
}
static int mchp_coreqspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
{
struct mchp_coreqspi *qspi = spi_controller_get_devdata
(mem->spi->master);
u32 address = op->addr.val;
u8 opcode = op->cmd.opcode;
u8 opaddr[5];
int err, i;
mutex_lock(&qspi->op_lock);
err = mchp_qspi_wait_for_ready(mem);
if (err)
goto error;
err = mchp_coreqspi_setup_clock(qspi, mem->spi);
if (err)
goto error;
err = mchp_coreqspi_set_mode(qspi, op);
if (err)
goto error;
reinit_completion(&qspi->data_completion);
mchp_coreqspi_config_op(qspi, op);
if (op->cmd.opcode) {
qspi->txbuf = &opcode;
qspi->rxbuf = NULL;
qspi->tx_len = op->cmd.nbytes;
qspi->rx_len = 0;
mchp_coreqspi_write_op(qspi, false);
}
qspi->txbuf = &opaddr[0];
if (op->addr.nbytes) {
for (i = 0; i < op->addr.nbytes; i++)
qspi->txbuf[i] = address >> (8 * (op->addr.nbytes - i - 1));
qspi->rxbuf = NULL;
qspi->tx_len = op->addr.nbytes;
qspi->rx_len = 0;
mchp_coreqspi_write_op(qspi, false);
}
if (op->data.nbytes) {
if (op->data.dir == SPI_MEM_DATA_OUT) {
qspi->txbuf = (u8 *)op->data.buf.out;
qspi->rxbuf = NULL;
qspi->rx_len = 0;
qspi->tx_len = op->data.nbytes;
mchp_coreqspi_write_op(qspi, true);
} else {
qspi->txbuf = NULL;
qspi->rxbuf = (u8 *)op->data.buf.in;
qspi->rx_len = op->data.nbytes;
qspi->tx_len = 0;
}
}
mchp_coreqspi_enable_ints(qspi);
if (!wait_for_completion_timeout(&qspi->data_completion, msecs_to_jiffies(1000)))
err = -ETIMEDOUT;
error:
mutex_unlock(&qspi->op_lock);
mchp_coreqspi_disable_ints(qspi);
return err;
}
static bool mchp_coreqspi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op)
{
if (!spi_mem_default_supports_op(mem, op))
return false;
if ((op->data.buswidth == 4 || op->data.buswidth == 2) &&
(op->cmd.buswidth == 1 && (op->addr.buswidth == 1 || op->addr.buswidth == 0))) {
/*
* If the command and address are on DQ0 only, then this
* controller doesn't support sending data on dual and
* quad lines. but it supports reading data on dual and
* quad lines with same configuration as command and
* address on DQ0.
* i.e. The control register[15:13] :EX_RO(read only) is
* meant only for the command and address are on DQ0 but
* not to write data, it is just to read.
* Ex: 0x34h is Quad Load Program Data which is not
* supported. Then the spi-mem layer will iterate over
* each command and it will chose the supported one.
*/
if (op->data.dir == SPI_MEM_DATA_OUT)
return false;
}
return true;
}
static int mchp_coreqspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
{
if (op->data.dir == SPI_MEM_DATA_OUT || op->data.dir == SPI_MEM_DATA_IN) {
if (op->data.nbytes > MAX_DATA_CMD_LEN)
op->data.nbytes = MAX_DATA_CMD_LEN;
}
return 0;
}
static const struct spi_controller_mem_ops mchp_coreqspi_mem_ops = {
.adjust_op_size = mchp_coreqspi_adjust_op_size,
.supports_op = mchp_coreqspi_supports_op,
.exec_op = mchp_coreqspi_exec_op,
};
static int mchp_coreqspi_probe(struct platform_device *pdev)
{
struct spi_controller *ctlr;
struct mchp_coreqspi *qspi;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
int ret;
ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*qspi));
if (!ctlr)
return dev_err_probe(&pdev->dev, -ENOMEM,
"unable to allocate master for QSPI controller\n");
qspi = spi_controller_get_devdata(ctlr);
platform_set_drvdata(pdev, qspi);
qspi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(qspi->regs))
return dev_err_probe(&pdev->dev, PTR_ERR(qspi->regs),
"failed to map registers\n");
qspi->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(qspi->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(qspi->clk),
"could not get clock\n");
ret = clk_prepare_enable(qspi->clk);
if (ret)
return dev_err_probe(&pdev->dev, ret,
"failed to enable clock\n");
init_completion(&qspi->data_completion);
mutex_init(&qspi->op_lock);
qspi->irq = platform_get_irq(pdev, 0);
if (qspi->irq < 0) {
ret = qspi->irq;
goto out;
}
ret = devm_request_irq(&pdev->dev, qspi->irq, mchp_coreqspi_isr,
IRQF_SHARED, pdev->name, qspi);
if (ret) {
dev_err(&pdev->dev, "request_irq failed %d\n", ret);
goto out;
}
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
ctlr->mem_ops = &mchp_coreqspi_mem_ops;
ctlr->setup = mchp_coreqspi_setup_op;
ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD |
SPI_TX_DUAL | SPI_TX_QUAD;
ctlr->dev.of_node = np;
ret = devm_spi_register_controller(&pdev->dev, ctlr);
if (ret) {
dev_err_probe(&pdev->dev, ret,
"spi_register_controller failed\n");
goto out;
}
return 0;
out:
clk_disable_unprepare(qspi->clk);
return ret;
}
static int mchp_coreqspi_remove(struct platform_device *pdev)
{
struct mchp_coreqspi *qspi = platform_get_drvdata(pdev);
u32 control = readl_relaxed(qspi->regs + REG_CONTROL);
mchp_coreqspi_disable_ints(qspi);
control &= ~CONTROL_ENABLE;
writel_relaxed(control, qspi->regs + REG_CONTROL);
clk_disable_unprepare(qspi->clk);
return 0;
}
static const struct of_device_id mchp_coreqspi_of_match[] = {
{ .compatible = "microchip,coreqspi-rtl-v2" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mchp_coreqspi_of_match);
static struct platform_driver mchp_coreqspi_driver = {
.probe = mchp_coreqspi_probe,
.driver = {
.name = "microchip,coreqspi",
.of_match_table = mchp_coreqspi_of_match,
},
.remove = mchp_coreqspi_remove,
};
module_platform_driver(mchp_coreqspi_driver);
MODULE_AUTHOR("Naga Sureshkumar Relli <nagasuresh.relli@microchip.com");
MODULE_DESCRIPTION("Microchip coreQSPI QSPI controller driver");
MODULE_LICENSE("GPL");

View file

@ -548,12 +548,12 @@ static int mchp_corespi_probe(struct platform_device *pdev)
IRQF_SHARED, dev_name(&pdev->dev), master);
if (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);
if (IS_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);
if (ret)

View file

@ -11,13 +11,14 @@
*/
#include <linux/module.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/of_platform.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/io.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
@ -89,7 +90,7 @@ struct mpc52xx_spi {
const u8 *tx_buf;
int cs_change;
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)
if (ms->gpio_cs_count > 0) {
cs = ms->message->spi->chip_select;
gpio_set_value(ms->gpio_cs[cs], value ? 0 : 1);
} else
gpiod_set_value(ms->gpio_cs[cs], value);
} else {
out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08);
}
}
/*
@ -385,10 +387,10 @@ static int mpc52xx_spi_probe(struct platform_device *op)
{
struct spi_master *master;
struct mpc52xx_spi *ms;
struct gpio_desc *gpio_cs;
void __iomem *regs;
u8 ctrl1;
int rc, i = 0;
int gpio_cs;
/* MMIO registers */
dev_dbg(&op->dev, "probing mpc5200 SPI device\n");
@ -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->state = mpc52xx_spi_fsmstate_idle;
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) {
master->num_chipselect = 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)
}
for (i = 0; i < ms->gpio_cs_count; i++) {
gpio_cs = of_get_gpio(op->dev.of_node, i);
if (!gpio_is_valid(gpio_cs)) {
dev_err(&op->dev,
"could not parse the gpio field in oftree\n");
rc = -ENODEV;
goto err_gpio;
}
rc = gpio_request(gpio_cs, dev_name(&op->dev));
gpio_cs = gpiod_get_index(&op->dev,
NULL, i, GPIOD_OUT_LOW);
rc = PTR_ERR_OR_ZERO(gpio_cs);
if (rc) {
dev_err(&op->dev,
"can't request spi cs gpio #%d on gpio line %d\n",
i, gpio_cs);
"failed to get spi cs gpio #%d: %d\n",
i, rc);
goto err_gpio;
}
gpio_direction_output(gpio_cs, 1);
ms->gpio_cs[i] = gpio_cs;
}
}
@ -507,7 +502,7 @@ static int mpc52xx_spi_probe(struct platform_device *op)
dev_err(&ms->master->dev, "initialization failed\n");
err_gpio:
while (i-- > 0)
gpio_free(ms->gpio_cs[i]);
gpiod_put(ms->gpio_cs[i]);
kfree(ms->gpio_cs);
err_alloc_gpio:
@ -528,7 +523,7 @@ static int mpc52xx_spi_remove(struct platform_device *op)
free_irq(ms->irq1, ms);
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);
spi_unregister_master(master);

View file

@ -1184,6 +1184,11 @@ static int mtk_spi_probe(struct platform_device *pdev)
if (!dev->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,
IRQF_TRIGGER_NONE, dev_name(dev), master);
if (ret)

View file

@ -55,7 +55,6 @@ struct mt7621_spi {
void __iomem *base;
unsigned int sys_freq;
unsigned int speed;
struct clk *clk;
int pending_write;
};
@ -327,7 +326,6 @@ static int mt7621_spi_probe(struct platform_device *pdev)
struct spi_controller *master;
struct mt7621_spi *rs;
void __iomem *base;
int status = 0;
struct clk *clk;
int ret;
@ -339,21 +337,14 @@ static int mt7621_spi_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n",
status);
return PTR_ERR(clk);
}
status = clk_prepare_enable(clk);
if (status)
return status;
clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(clk))
return dev_err_probe(&pdev->dev, PTR_ERR(clk),
"unable to get SYS clock\n");
master = devm_spi_alloc_master(&pdev->dev, sizeof(*rs));
if (!master) {
dev_info(&pdev->dev, "master allocation failed\n");
clk_disable_unprepare(clk);
return -ENOMEM;
}
@ -369,38 +360,18 @@ static int mt7621_spi_probe(struct platform_device *pdev)
rs = spi_controller_get_devdata(master);
rs->base = base;
rs->clk = clk;
rs->master = master;
rs->sys_freq = clk_get_rate(rs->clk);
rs->sys_freq = clk_get_rate(clk);
rs->pending_write = 0;
dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq);
ret = device_reset(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "SPI reset failed!\n");
clk_disable_unprepare(clk);
return ret;
}
ret = spi_register_controller(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;
return devm_spi_register_controller(&pdev->dev, master);
}
MODULE_ALIAS("platform:" DRIVER_NAME);
@ -411,7 +382,6 @@ static struct platform_driver mt7621_spi_driver = {
.of_match_table = mt7621_spi_match,
},
.probe = mt7621_spi_probe,
.remove = mt7621_spi_remove,
};
module_platform_driver(mt7621_spi_driver);

View file

@ -443,6 +443,7 @@ static int npcm_pspi_remove(struct platform_device *pdev)
static const struct of_device_id npcm_pspi_match[] = {
{ .compatible = "nuvoton,npcm750-pspi", .data = NULL },
{ .compatible = "nuvoton,npcm845-pspi", .data = NULL },
{}
};
MODULE_DEVICE_TABLE(of, npcm_pspi_match);

View file

@ -588,7 +588,7 @@ static int nxp_fspi_clk_prep_enable(struct nxp_fspi *f)
{
int ret;
if (is_acpi_node(f->dev->fwnode))
if (is_acpi_node(dev_fwnode(f->dev)))
return 0;
ret = clk_prepare_enable(f->clk_en);
@ -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)
{
if (is_acpi_node(f->dev->fwnode))
if (is_acpi_node(dev_fwnode(f->dev)))
return 0;
clk_disable_unprepare(f->clk);
@ -1100,7 +1100,7 @@ static int nxp_fspi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, f);
/* 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);
else
res = platform_get_resource_byname(pdev,
@ -1113,7 +1113,7 @@ static int nxp_fspi_probe(struct platform_device *pdev)
}
/* 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);
else
res = platform_get_resource_byname(pdev,

View file

@ -412,6 +412,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
return status;
err_fck:
pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(spi100k->fck);
err_ick:
clk_disable_unprepare(spi100k->ick);

View file

@ -1509,10 +1509,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
}
status = platform_get_irq(pdev, 0);
if (status == -EPROBE_DEFER)
goto free_master;
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;
}
init_completion(&mcspi->txdone);

View file

@ -1856,10 +1856,8 @@ static int pxa2xx_spi_runtime_suspend(struct device *dev)
static int pxa2xx_spi_runtime_resume(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);
int status;
status = clk_prepare_enable(drv_data->ssp->clk);
return status;
return clk_prepare_enable(drv_data->ssp->clk);
}
#endif

View file

@ -1198,8 +1198,10 @@ static int spi_qup_pm_resume_runtime(struct device *device)
return ret;
ret = clk_prepare_enable(controller->cclk);
if (ret)
if (ret) {
clk_disable_unprepare(controller->iclk);
return ret;
}
/* Disable clocks auto gaiting */
config = readl_relaxed(controller->base + QUP_CONFIG);
@ -1245,14 +1247,25 @@ static int spi_qup_resume(struct device *device)
return ret;
ret = clk_prepare_enable(controller->cclk);
if (ret)
if (ret) {
clk_disable_unprepare(controller->iclk);
return ret;
}
ret = spi_qup_set_state(controller, QUP_STATE_RESET);
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 */

View file

@ -449,7 +449,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
struct spi_master *master;
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) {
dev_err(&pdev->dev, "No memory for spi_master\n");
return -ENOMEM;
@ -463,8 +463,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
if (pdata == NULL) {
dev_err(&pdev->dev, "No platform data supplied\n");
err = -ENOENT;
goto err_no_pdata;
return -ENOENT;
}
platform_set_drvdata(pdev, hw);
@ -499,29 +498,24 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
/* find and map our resources */
hw->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hw->regs)) {
err = PTR_ERR(hw->regs);
goto err_no_pdata;
}
if (IS_ERR(hw->regs))
return PTR_ERR(hw->regs);
hw->irq = platform_get_irq(pdev, 0);
if (hw->irq < 0) {
err = -ENOENT;
goto err_no_pdata;
}
if (hw->irq < 0)
return -ENOENT;
err = devm_request_irq(&pdev->dev, hw->irq, s3c24xx_spi_irq, 0,
pdev->name, hw);
if (err) {
dev_err(&pdev->dev, "Cannot claim IRQ\n");
goto err_no_pdata;
return err;
}
hw->clk = devm_clk_get(&pdev->dev, "spi");
if (IS_ERR(hw->clk)) {
dev_err(&pdev->dev, "No clock for device\n");
err = PTR_ERR(hw->clk);
goto err_no_pdata;
return PTR_ERR(hw->clk);
}
s3c24xx_spi_initialsetup(hw);
@ -539,8 +533,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
err_register:
clk_disable(hw->clk);
err_no_pdata:
spi_master_put(hw->master);
return err;
}

View file

@ -84,6 +84,7 @@
#define S3C64XX_SPI_ST_TX_FIFORDY (1<<0)
#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_OVERRUN_CLR (1<<3)
@ -389,8 +390,8 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
if (sdd->rx_dma.ch && sdd->tx_dma.ch) {
dma_release_channel(sdd->rx_dma.ch);
dma_release_channel(sdd->tx_dma.ch);
sdd->rx_dma.ch = 0;
sdd->tx_dma.ch = 0;
sdd->rx_dma.ch = NULL;
sdd->tx_dma.ch = NULL;
}
return 0;
@ -711,6 +712,13 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master,
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,
struct spi_device *spi,
struct spi_transfer *xfer)
@ -1152,6 +1160,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
master->prepare_message = s3c64xx_spi_prepare_message;
master->transfer_one = s3c64xx_spi_transfer_one;
master->max_transfer_size = s3c64xx_spi_max_transfer_size;
master->num_chipselect = sci->num_cs;
master->use_gpio_descriptors = true;
master->dma_alignment = 8;

View file

@ -1085,6 +1085,7 @@ static const struct of_device_id sh_msiof_match[] = {
{ .compatible = "renesas,rcar-gen2-msiof", .data = &rcar_gen2_data },
{ .compatible = "renesas,msiof-r8a7796", .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 */
{},
};

View file

@ -15,6 +15,7 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
@ -355,10 +356,10 @@ static int stm32_qspi_get_mode(u8 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_flash *flash = &qspi->flash[mem->spi->chip_select];
struct stm32_qspi *qspi = spi_controller_get_devdata(spi->master);
struct stm32_qspi_flash *flash = &qspi->flash[spi->chip_select];
u32 ccr, cr;
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 *
qspi->fmode = CCR_FMODE_APM;
qspi->status_timeout = timeout_ms;
ret = stm32_qspi_send(mem, op);
ret = stm32_qspi_send(mem->spi, op);
mutex_unlock(&qspi->lock);
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)
else
qspi->fmode = CCR_FMODE_INDW;
ret = stm32_qspi_send(mem, op);
ret = stm32_qspi_send(mem->spi, op);
mutex_unlock(&qspi->lock);
pm_runtime_mark_last_busy(qspi->dev);
@ -545,7 +546,7 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc,
else
qspi->fmode = CCR_FMODE_INDR;
ret = stm32_qspi_send(desc->mem, &op);
ret = stm32_qspi_send(desc->mem->spi, &op);
mutex_unlock(&qspi->lock);
pm_runtime_mark_last_busy(qspi->dev);
@ -554,12 +555,96 @@ static ssize_t stm32_qspi_dirmap_read(struct spi_mem_dirmap_desc *desc,
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)
{
struct spi_controller *ctrl = spi->master;
struct stm32_qspi *qspi = spi_controller_get_devdata(ctrl);
struct stm32_qspi_flash *flash;
u32 presc;
u32 presc, mode;
int ret;
if (ctrl->busy)
@ -568,6 +653,16 @@ static int stm32_qspi_setup(struct spi_device *spi)
if (!spi->max_speed_hz)
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);
if (ret < 0)
return ret;
@ -580,6 +675,16 @@ static int stm32_qspi_setup(struct spi_device *spi)
mutex_lock(&qspi->lock);
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);
/* set dcr fsize to max address */
@ -741,11 +846,13 @@ static int stm32_qspi_probe(struct platform_device *pdev)
mutex_init(&qspi->lock);
ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD
| SPI_TX_DUAL | SPI_TX_QUAD;
ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_OCTAL
| SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_OCTAL;
ctrl->setup = stm32_qspi_setup;
ctrl->bus_num = -1;
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->dev.of_node = dev->of_node;

View file

@ -421,7 +421,7 @@ static int xilinx_spi_probe(struct platform_device *pdev)
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)
return -ENODEV;
@ -439,10 +439,8 @@ static int xilinx_spi_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
xspi->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(xspi->regs)) {
ret = PTR_ERR(xspi->regs);
goto put_master;
}
if (IS_ERR(xspi->regs))
return PTR_ERR(xspi->regs);
master->bus_num = pdev->id;
master->num_chipselect = num_cs;
@ -472,14 +470,13 @@ static int xilinx_spi_probe(struct platform_device *pdev)
xspi->irq = platform_get_irq(pdev, 0);
if (xspi->irq < 0 && xspi->irq != -ENXIO) {
ret = xspi->irq;
goto put_master;
return xspi->irq;
} else if (xspi->irq >= 0) {
/* Register for SPI Interrupt */
ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0,
dev_name(&pdev->dev), xspi);
if (ret)
goto put_master;
return ret;
}
/* SPI controller initializations */
@ -488,7 +485,7 @@ static int xilinx_spi_probe(struct platform_device *pdev)
ret = spi_bitbang_start(&xspi->bitbang);
if (ret) {
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);
@ -500,11 +497,6 @@ static int xilinx_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master);
return 0;
put_master:
spi_master_put(master);
return ret;
}
static int xilinx_spi_remove(struct platform_device *pdev)

View file

@ -83,7 +83,7 @@ static int xtfpga_spi_probe(struct platform_device *pdev)
int ret;
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)
return -ENOMEM;
@ -97,30 +97,24 @@ static int xtfpga_spi_probe(struct platform_device *pdev)
xspi->bitbang.chipselect = xtfpga_spi_chipselect;
xspi->bitbang.txrx_word[SPI_MODE_0] = xtfpga_spi_txrx_word;
xspi->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(xspi->regs)) {
ret = PTR_ERR(xspi->regs);
goto err;
}
if (IS_ERR(xspi->regs))
return PTR_ERR(xspi->regs);
xtfpga_spi_write32(xspi, XTFPGA_SPI_START, 0);
usleep_range(1000, 2000);
if (xtfpga_spi_read32(xspi, XTFPGA_SPI_BUSY)) {
dev_err(&pdev->dev, "Device stuck in busy state\n");
ret = -EBUSY;
goto err;
return -EBUSY;
}
ret = spi_bitbang_start(&xspi->bitbang);
if (ret < 0) {
dev_err(&pdev->dev, "spi_bitbang_start failed\n");
goto err;
return ret;
}
platform_set_drvdata(pdev, master);
return 0;
err:
spi_master_put(master);
return ret;
}
static int xtfpga_spi_remove(struct platform_device *pdev)

View file

@ -753,7 +753,7 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr,
proxy->max_speed_hz = chip->max_speed_hz;
proxy->mode = chip->mode;
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->controller_data = chip->controller_data;
proxy->controller_state = NULL;
@ -1010,9 +1010,9 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
}
#ifdef CONFIG_HAS_DMA
int spi_map_buf(struct spi_controller *ctlr, struct device *dev,
struct sg_table *sgt, void *buf, size_t len,
enum dma_data_direction dir)
static int spi_map_buf_attrs(struct spi_controller *ctlr, struct device *dev,
struct sg_table *sgt, void *buf, size_t len,
enum dma_data_direction dir, unsigned long attrs)
{
const bool vmalloced_buf = is_vmalloc_addr(buf);
unsigned int max_seg_size = dma_get_max_seg_size(dev);
@ -1078,26 +1078,39 @@ int spi_map_buf(struct spi_controller *ctlr, struct device *dev,
sg = sg_next(sg);
}
ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir);
if (!ret)
ret = -ENOMEM;
ret = dma_map_sgtable(dev, sgt, dir, attrs);
if (ret < 0) {
sg_free_table(sgt);
return ret;
}
sgt->nents = ret;
return 0;
}
int spi_map_buf(struct spi_controller *ctlr, struct device *dev,
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) {
dma_unmap_sgtable(dev, sgt, dir, attrs);
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)
{
if (sgt->orig_nents) {
dma_unmap_sg(dev, sgt->sgl, sgt->orig_nents, dir);
sg_free_table(sgt);
}
spi_unmap_buf_attrs(ctlr, dev, sgt, dir, 0);
}
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;
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))
continue;
if (xfer->tx_buf != NULL) {
ret = spi_map_buf(ctlr, tx_dev, &xfer->tx_sg,
(void *)xfer->tx_buf, xfer->len,
DMA_TO_DEVICE);
ret = spi_map_buf_attrs(ctlr, tx_dev, &xfer->tx_sg,
(void *)xfer->tx_buf,
xfer->len, DMA_TO_DEVICE,
attrs);
if (ret != 0)
return ret;
}
if (xfer->rx_buf != NULL) {
ret = spi_map_buf(ctlr, rx_dev, &xfer->rx_sg,
xfer->rx_buf, xfer->len,
DMA_FROM_DEVICE);
ret = spi_map_buf_attrs(ctlr, rx_dev, &xfer->rx_sg,
xfer->rx_buf, xfer->len,
DMA_FROM_DEVICE, attrs);
if (ret != 0) {
spi_unmap_buf(ctlr, tx_dev, &xfer->tx_sg,
DMA_TO_DEVICE);
spi_unmap_buf_attrs(ctlr, tx_dev,
&xfer->tx_sg, DMA_TO_DEVICE,
attrs);
return ret;
}
}
}
ctlr->cur_rx_dma_dev = rx_dev;
ctlr->cur_tx_dma_dev = tx_dev;
ctlr->cur_msg_mapped = true;
return 0;
@ -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)
{
struct device *rx_dev = ctlr->cur_rx_dma_dev;
struct device *tx_dev = ctlr->cur_tx_dma_dev;
struct spi_transfer *xfer;
struct device *tx_dev, *rx_dev;
if (!ctlr->cur_msg_mapped || !ctlr->can_dma)
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) {
/* 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))
continue;
spi_unmap_buf(ctlr, rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
spi_unmap_buf(ctlr, tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
spi_unmap_buf_attrs(ctlr, rx_dev, &xfer->rx_sg,
DMA_FROM_DEVICE, attrs);
spi_unmap_buf_attrs(ctlr, tx_dev, &xfer->tx_sg,
DMA_TO_DEVICE, attrs);
}
ctlr->cur_msg_mapped = false;
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 */
static inline int __spi_map_msg(struct spi_controller *ctlr,
struct spi_message *msg)
@ -1198,6 +1241,16 @@ static inline int __spi_unmap_msg(struct spi_controller *ctlr,
{
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 */
static inline int spi_unmap_msg(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 *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(stats, messages);
@ -1455,8 +1509,11 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
reinit_completion(&ctlr->xfer_completion);
fallback_pio:
spi_dma_sync_for_device(ctlr, xfer);
ret = ctlr->transfer_one(ctlr, msg->spi, xfer);
if (ret < 0) {
spi_dma_sync_for_cpu(ctlr, xfer);
if (ctlr->cur_msg_mapped &&
(xfer->error & SPI_TRANS_FAIL_NO_START)) {
__spi_unmap_msg(ctlr, msg);
@ -1479,6 +1536,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
if (ret < 0)
msg->status = ret;
}
spi_dma_sync_for_cpu(ctlr, xfer);
} else {
if (xfer->len)
dev_err(&msg->spi->dev,
@ -1503,10 +1562,15 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
&msg->transfers)) {
keep_cs = true;
} 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_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;
@ -1587,6 +1651,15 @@ static int __spi_pump_transfer_message(struct spi_controller *ctlr,
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) {
ret = ctlr->prepare_message(ctlr, msg);
if (ret) {
@ -2329,7 +2402,7 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi,
goto err_out;
}
strlcpy(ancillary->modalias, "dummy", sizeof(ancillary->modalias));
strscpy(ancillary->modalias, "dummy", sizeof(ancillary->modalias));
/* Use provided chip-select for ancillary device */
ancillary->chip_select = chip_select;
@ -2725,7 +2798,7 @@ static ssize_t slave_store(struct device *dev, struct device_attribute *attr,
if (!spi)
return -ENOMEM;
strlcpy(spi->modalias, name, sizeof(spi->modalias));
strscpy(spi->modalias, name, sizeof(spi->modalias));
rc = spi_add_device(spi);
if (rc) {

View file

@ -378,6 +378,8 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
* @cleanup: frees controller-specific state
* @can_dma: determine whether this controller supports DMA
* @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
* @kworker: pointer to thread struct for message pump
* @pump_messages: work struct for scheduling work to the message pump
@ -610,6 +612,8 @@ struct spi_controller {
struct spi_device *spi,
struct spi_transfer *xfer);
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
@ -848,6 +852,7 @@ struct spi_res {
* @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.
* @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_delay: delay between cs deassert and assert when
* @cs_change is set and @spi_transfer is not the last in @spi_message
@ -958,6 +963,7 @@ struct spi_transfer {
struct sg_table rx_sg;
unsigned dummy_data:1;
unsigned cs_off:1;
unsigned cs_change:1;
unsigned tx_nbits:3;
unsigned rx_nbits:3;