Commit 2019295c authored by Linus Torvalds's avatar Linus Torvalds

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

Pull spi updates from Mark Brown:
 "This is quite a quiet release for SPI, there's been a bit of cleanup
  to the core from Uwe but nothing functionality wise.

  We have added several new drivers, Cadence XSPI, Ingenic JZ47xx,
  Qualcomm SC7280 and SC7180 and Xilinx Versal OSPI"

* tag 'spi-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (41 commits)
  spi: Convert NXP flexspi to json schema
  spi: spi-geni-qcom: Add support for GPI dma
  spi: fsi: Fix contention in the FSI2SPI engine
  spi: spi-rpc-if: Check return value of rpcif_sw_init()
  spi: tegra210-quad: Put device into suspend on driver removal
  spi: tegra20-slink: Put device into suspend on driver removal
  spi: bcm-qspi: Fix missing clk_disable_unprepare() on error in bcm_qspi_probe()
  spi: at91-usart: replacing legacy gpio interface for gpiod
  spi: replace snprintf in show functions with sysfs_emit
  spi: cadence: Add of_node_put() before return
  spi: orion: Add of_node_put() before goto
  spi: cadence-quadspi: fix dma_unmap_single() call
  spi: tegra20: fix build with CONFIG_PM_SLEEP=n
  spi: bcm-qspi: add support for 3-wire mode for half duplex transfer
  spi: bcm-qspi: Add mspi spcr3 32/64-bits xfer mode
  spi: Make several public functions private to spi.c
  spi: Reorder functions to simplify the next commit
  spi: Remove unused function spi_busnum_to_master()
  spi: Move comment about chipselect check to the right place
  spi: fsi: Print status on error
  ...
parents 1260d242 28b5eaf9
......@@ -11,6 +11,14 @@ maintainers:
allOf:
- $ref: spi-controller.yaml#
- if:
properties:
compatible:
contains:
const: xlnx,versal-ospi-1.0
then:
required:
- power-domains
properties:
compatible:
......@@ -20,6 +28,7 @@ properties:
- ti,k2g-qspi
- ti,am654-ospi
- intel,lgm-qspi
- xlnx,versal-ospi-1.0
- const: cdns,qspi-nor
- const: cdns,qspi-nor
......@@ -65,6 +74,9 @@ properties:
data rather than the QSPI clock. Make sure that QSPI return clock
is populated on the board before using this property.
power-domains:
maxItems: 1
resets:
maxItems: 2
......
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2020-21 Cadence
%YAML 1.2
---
$id: "http://devicetree.org/schemas/spi/cdns,xspi.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Cadence XSPI Controller
maintainers:
- Parshuram Thombare <pthombar@cadence.com>
description: |
The XSPI controller allows SPI protocol communication in
single, dual, quad or octal wire transmission modes for
read/write access to slaves such as SPI-NOR flash.
allOf:
- $ref: "spi-controller.yaml#"
properties:
compatible:
const: cdns,xspi-nor
reg:
items:
- description: address and length of the controller register set
- description: address and length of the Slave DMA data port
- description: address and length of the auxiliary registers
reg-names:
items:
- const: io
- const: sdma
- const: aux
interrupts:
maxItems: 1
required:
- compatible
- reg
- interrupts
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
bus {
#address-cells = <2>;
#size-cells = <2>;
xspi: spi@a0010000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "cdns,xspi-nor";
reg = <0x0 0xa0010000 0x0 0x1040>,
<0x0 0xb0000000 0x0 0x1000>,
<0x0 0xa0020000 0x0 0x100>;
reg-names = "io", "sdma", "aux";
interrupts = <0 90 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
flash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <75000000>;
reg = <0>;
};
flash@1 {
compatible = "jedec,spi-nor";
spi-max-frequency = <75000000>;
reg = <1>;
};
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/ingenic,spi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Ingenic SoCs SPI controller devicetree bindings
maintainers:
- Artur Rojek <contact@artur-rojek.eu>
- Paul Cercueil <paul@crapouillou.net>
allOf:
- $ref: /schemas/spi/spi-controller.yaml#
properties:
compatible:
oneOf:
- enum:
- ingenic,jz4750-spi
- ingenic,jz4780-spi
- items:
- enum:
- ingenic,jz4760-spi
- ingenic,jz4770-spi
- const: ingenic,jz4750-spi
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
dmas:
maxItems: 2
minItems: 2
dma-names:
items:
- const: rx
- const: tx
required:
- compatible
- reg
- interrupts
- clocks
- dmas
- dma-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/jz4770-cgu.h>
spi@10043000 {
compatible = "ingenic,jz4770-spi", "ingenic,jz4750-spi";
reg = <0x10043000 0x1c>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&intc>;
interrupts = <8>;
clocks = <&cgu JZ4770_CLK_SSI0>;
dmas = <&dmac1 23 0xffffffff>, <&dmac1 22 0xffffffff>;
dma-names = "rx", "tx";
};
......@@ -21,7 +21,11 @@ allOf:
properties:
compatible:
items:
- const: qcom,sdm845-qspi
- enum:
- qcom,sc7180-qspi
- qcom,sc7280-qspi
- qcom,sdm845-qspi
- const: qcom,qspi-v1
reg:
......
* NXP Flex Serial Peripheral Interface (FSPI)
Required properties:
- compatible : Should be "nxp,lx2160a-fspi"
"nxp,imx8qxp-fspi"
"nxp,imx8mm-fspi"
"nxp,imx8mp-fspi"
"nxp,imx8dxl-fspi"
- reg : First contains the register location and length,
Second contains the memory mapping address and length
- reg-names : Should contain the resource reg names:
- fspi_base: configuration register address space
- fspi_mmap: memory mapped address space
- interrupts : Should contain the interrupt for the device
Required SPI slave node properties:
- reg : There are two buses (A and B) with two chip selects each.
This encodes to which bus and CS the flash is connected:
- <0>: Bus A, CS 0
- <1>: Bus A, CS 1
- <2>: Bus B, CS 0
- <3>: Bus B, CS 1
Example showing the usage of two SPI NOR slave devices on bus A:
fspi0: spi@20c0000 {
compatible = "nxp,lx2160a-fspi";
reg = <0x0 0x20c0000 0x0 0x10000>, <0x0 0x20000000 0x0 0x10000000>;
reg-names = "fspi_base", "fspi_mmap";
interrupts = <0 25 0x4>; /* Level high type */
clocks = <&clockgen 4 3>, <&clockgen 4 3>;
clock-names = "fspi_en", "fspi";
mt35xu512aba0: flash@0 {
reg = <0>;
....
};
mt35xu512aba1: flash@1 {
reg = <1>;
....
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/spi-nxp-fspi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP Flex Serial Peripheral Interface (FSPI)
maintainers:
- Kuldeep Singh <kuldeep.singh@nxp.com>
allOf:
- $ref: "spi-controller.yaml#"
properties:
compatible:
enum:
- nxp,imx8dxl-fspi
- nxp,imx8mm-fspi
- nxp,imx8mp-fspi
- nxp,imx8qxp-fspi
- nxp,lx2160a-fspi
reg:
items:
- description: registers address space
- description: memory mapped address space
reg-names:
items:
- const: fspi_base
- const: fspi_mmap
interrupts:
maxItems: 1
clocks:
items:
- description: SPI bus clock
- description: SPI serial clock
clock-names:
items:
- const: fspi_en
- const: fspi
required:
- compatible
- reg
- reg-names
- interrupts
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/fsl,qoriq-clockgen.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
spi@20c0000 {
compatible = "nxp,lx2160a-fspi";
reg = <0x0 0x20c0000 0x0 0x100000>,
<0x0 0x20000000 0x0 0x10000000>;
reg-names = "fspi_base", "fspi_mmap";
interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL QORIQ_CLK_PLL_DIV(4)>,
<&clockgen QORIQ_CLK_PLATFORM_PLL QORIQ_CLK_PLL_DIV(4)>;
clock-names = "fspi_en", "fspi";
#address-cells = <1>;
#size-cells = <0>;
flash@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <50000000>;
reg = <0>;
spi-rx-bus-width = <8>;
spi-tx-bus-width = <8>;
};
};
};
......@@ -336,14 +336,6 @@ certainly includes SPI devices hooked up through the card connectors!
Non-static Configurations
^^^^^^^^^^^^^^^^^^^^^^^^^
Developer boards often play by different rules than product boards, and one
example is the potential need to hotplug SPI devices and/or controllers.
For those cases you might need to use spi_busnum_to_master() to look
up the spi bus master, and will likely need spi_new_device() to provide the
board info based on the board that was hotplugged. Of course, you'd later
call at least spi_unregister_device() when that board is removed.
When Linux includes support for MMC/SD/SDIO/DataFlash cards through SPI, those
configurations will also be dynamic. Fortunately, such devices all support
basic device identification probes, so they should hotplug normally.
......
......@@ -13488,7 +13488,7 @@ M: Ashish Kumar <ashish.kumar@nxp.com>
R: Yogesh Gaur <yogeshgaur.83@gmail.com>
L: linux-spi@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/spi/spi-nxp-fspi.txt
F: Documentation/devicetree/bindings/spi/spi-nxp-fspi.yaml
F: drivers/spi/spi-nxp-fspi.c
NXP FXAS21002C DRIVER
......
......@@ -113,9 +113,12 @@ &cgu {
* Use the 32.768 kHz oscillator as the parent of the RTC for a higher
* precision.
*/
assigned-clocks = <&cgu JZ4780_CLK_OTGPHY>, <&cgu JZ4780_CLK_RTC>;
assigned-clock-parents = <0>, <&cgu JZ4780_CLK_RTCLK>;
assigned-clock-rates = <48000000>;
assigned-clocks = <&cgu JZ4780_CLK_OTGPHY>, <&cgu JZ4780_CLK_RTC>,
<&cgu JZ4780_CLK_SSIPLL>, <&cgu JZ4780_CLK_SSI>;
assigned-clock-parents = <0>, <&cgu JZ4780_CLK_RTCLK>,
<&cgu JZ4780_CLK_MPLL>,
<&cgu JZ4780_CLK_SSIPLL>;
assigned-clock-rates = <48000000>, <0>, <54000000>;
};
&tcu {
......
......@@ -255,22 +255,23 @@ gpf: gpio@5 {
};
};
spi_gpio {
compatible = "spi-gpio";
spi0: spi@10043000 {
compatible = "ingenic,jz4780-spi";
reg = <0x10043000 0x1c>;
#address-cells = <1>;
#size-cells = <0>;
num-chipselects = <2>;
gpio-miso = <&gpe 14 0>;
gpio-sck = <&gpe 15 0>;
gpio-mosi = <&gpe 17 0>;
cs-gpios = <&gpe 16 0>, <&gpe 18 0>;
interrupt-parent = <&intc>;
interrupts = <8>;
spidev@0 {
compatible = "spidev";
reg = <0>;
spi-max-frequency = <1000000>;
};
clocks = <&cgu JZ4780_CLK_SSI0>;
clock-names = "spi";
dmas = <&dma JZ4780_DMA_SSI0_RX 0xffffffff>,
<&dma JZ4780_DMA_SSI0_TX 0xffffffff>;
dma-names = "rx", "tx";
status = "disabled";
};
uart0: serial@10030000 {
......@@ -338,6 +339,25 @@ uart4: serial@10034000 {
status = "disabled";
};
spi1: spi@10044000 {
compatible = "ingenic,jz4780-spi";
reg = <0x10044000 0x1c>;
#address-cells = <1>;
#size-sells = <0>;
interrupt-parent = <&intc>;
interrupts = <7>;
clocks = <&cgu JZ4780_CLK_SSI1>;
clock-names = "spi";
dmas = <&dma JZ4780_DMA_SSI1_RX 0xffffffff>,
<&dma JZ4780_DMA_SSI1_TX 0xffffffff>;
dma-names = "rx", "tx";
status = "disabled";
};
i2c0: i2c@10050000 {
compatible = "ingenic,jz4780-i2c", "ingenic,jz4770-i2c";
#address-cells = <1>;
......
......@@ -647,6 +647,23 @@ int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
}
EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
/**
* zynqmp_pm_ospi_mux_select() - OSPI Mux selection
*
* @dev_id: Device Id of the OSPI device.
* @select: OSPI Mux select value.
*
* This function select the OSPI Mux.
*
* Return: Returns status, either success or error+reason
*/
int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select)
{
return zynqmp_pm_invoke_fn(PM_IOCTL, dev_id, IOCTL_OSPI_MUX_SELECT,
select, 0, NULL);
}
EXPORT_SYMBOL_GPL(zynqmp_pm_ospi_mux_select);
/**
* zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
* @index: GGS register index
......
......@@ -228,6 +228,18 @@ config SPI_CADENCE_QUADSPI
device with a Cadence QSPI controller and want to access the
Flash as an MTD device.
config SPI_CADENCE_XSPI
tristate "Cadence XSPI controller"
depends on (OF || COMPILE_TEST) && HAS_IOMEM
depends on SPI_MEM
help
Enable support for the Cadence XSPI Flash controller.
Cadence XSPI is a specialized controller for connecting an SPI
Flash over upto 8bit wide bus. Enable this option if you have a
device with a Cadence XSPI controller and want to access the
Flash as an MTD device.
config SPI_CLPS711X
tristate "CLPS711X host SPI controller"
depends on ARCH_CLPS711X || COMPILE_TEST
......@@ -406,6 +418,15 @@ config SPI_IMX
help
This enables support for the Freescale i.MX SPI controllers.
config SPI_INGENIC
tristate "Ingenic JZ47xx SoCs SPI controller"
depends on MACH_INGENIC || COMPILE_TEST
help
This enables support for the Ingenic JZ47xx SoCs SPI controller.
To compile this driver as a module, choose M here: the module
will be called spi-ingenic.
config SPI_JCORE
tristate "J-Core SPI Master"
depends on OF && (SUPERH || COMPILE_TEST)
......@@ -738,10 +759,11 @@ config SPI_S3C24XX_FIQ
TX and RX data paths.
config SPI_S3C64XX
tristate "Samsung S3C64XX series type SPI"
tristate "Samsung S3C64XX/Exynos SoC series type SPI"
depends on (PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST)
help
SPI driver for Samsung S3C64XX and newer SoCs.
SPI driver for Samsung S3C64XX, S5Pv210 and Exynos SoCs.
Choose Y/M here only if you build for such Samsung SoC.
config SPI_SC18IS602
tristate "NXP SC18IS602/602B/603 I2C to SPI bridge"
......
......@@ -34,6 +34,7 @@ obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
obj-$(CONFIG_SPI_CADENCE) += spi-cadence.o
obj-$(CONFIG_SPI_CADENCE_QUADSPI) += spi-cadence-quadspi.o
obj-$(CONFIG_SPI_CADENCE_XSPI) += spi-cadence-xspi.o
obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o
obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o
obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o
......@@ -59,6 +60,7 @@ obj-$(CONFIG_SPI_HISI_KUNPENG) += spi-hisi-kunpeng.o
obj-$(CONFIG_SPI_HISI_SFC_V3XX) += spi-hisi-sfc-v3xx.o
obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o
obj-$(CONFIG_SPI_IMX) += spi-imx.o
obj-$(CONFIG_SPI_INGENIC) += spi-ingenic.o
obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o
obj-$(CONFIG_SPI_JCORE) += spi-jcore.o
obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o
......
......@@ -310,7 +310,7 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
return mode;
ifr |= atmel_qspi_modes[mode].config;
if (op->dummy.buswidth && op->dummy.nbytes)
if (op->dummy.nbytes)
dummy_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth;
/*
......
......@@ -38,126 +38,102 @@ struct amd_spi {
void __iomem *io_remap_addr;
unsigned long io_base_addr;
u32 rom_addr;
u8 chip_select;
};
static inline u8 amd_spi_readreg8(struct spi_master *master, int idx)
static inline u8 amd_spi_readreg8(struct amd_spi *amd_spi, int idx)
{
struct amd_spi *amd_spi = spi_master_get_devdata(master);
return ioread8((u8 __iomem *)amd_spi->io_remap_addr + idx);
}
static inline void amd_spi_writereg8(struct spi_master *master, int idx,
u8 val)
static inline void amd_spi_writereg8(struct amd_spi *amd_spi, int idx, u8 val)
{
struct amd_spi *amd_spi = spi_master_get_devdata(master);
iowrite8(val, ((u8 __iomem *)amd_spi->io_remap_addr + idx));
}
static inline void amd_spi_setclear_reg8(struct spi_master *master, int idx,
u8 set, u8 clear)
static void amd_spi_setclear_reg8(struct amd_spi *amd_spi, int idx, u8 set, u8 clear)
{
u8 tmp = amd_spi_readreg8(master, idx);
u8 tmp = amd_spi_readreg8(amd_spi, idx);
tmp = (tmp & ~clear) | set;
amd_spi_writereg8(master, idx, tmp);
amd_spi_writereg8(amd_spi, idx, tmp);
}
static inline u32 amd_spi_readreg32(struct spi_master *master, int idx)
static inline u32 amd_spi_readreg32(struct amd_spi *amd_spi, int idx)
{
struct amd_spi *amd_spi = spi_master_get_devdata(master);
return ioread32((u8 __iomem *)amd_spi->io_remap_addr + idx);
}
static inline void amd_spi_writereg32(struct spi_master *master, int idx,
u32 val)
static inline void amd_spi_writereg32(struct amd_spi *amd_spi, int idx, u32 val)
{
struct amd_spi *amd_spi = spi_master_get_devdata(master);
iowrite32(val, ((u8 __iomem *)amd_spi->io_remap_addr + idx));
}
static inline void amd_spi_setclear_reg32(struct spi_master *master, int idx,
u32 set, u32 clear)
static inline void amd_spi_setclear_reg32(struct amd_spi *amd_spi, int idx, u32 set, u32 clear)
{
u32 tmp = amd_spi_readreg32(master, idx);
u32 tmp = amd_spi_readreg32(amd_spi, idx);
tmp = (tmp & ~clear) | set;
amd_spi_writereg32(master, idx, tmp);
amd_spi_writereg32(amd_spi, idx, tmp);
}
static void amd_spi_select_chip(struct spi_master *master)
static void amd_spi_select_chip(struct amd_spi *amd_spi, u8 cs)
{
struct amd_spi *amd_spi = spi_master_get_devdata(master);
u8 chip_select = amd_spi->chip_select;
amd_spi_setclear_reg8(master, AMD_SPI_ALT_CS_REG, chip_select,
AMD_SPI_ALT_CS_MASK);
amd_spi_setclear_reg8(amd_spi, AMD_SPI_ALT_CS_REG, cs, AMD_SPI_ALT_CS_MASK);
}
static void amd_spi_clear_fifo_ptr(struct spi_master *master)
static void amd_spi_clear_fifo_ptr(struct amd_spi *amd_spi)
{
amd_spi_setclear_reg32(master, AMD_SPI_CTRL0_REG, AMD_SPI_FIFO_CLEAR,
AMD_SPI_FIFO_CLEAR);
amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_FIFO_CLEAR, AMD_SPI_FIFO_CLEAR);
}
static void amd_spi_set_opcode(struct spi_master *master, u8 cmd_opcode)
static void amd_spi_set_opcode(struct amd_spi *amd_spi, u8 cmd_opcode)
{
amd_spi_setclear_reg32(master, AMD_SPI_CTRL0_REG, cmd_opcode,
AMD_SPI_OPCODE_MASK);
amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, cmd_opcode, AMD_SPI_OPCODE_MASK);
}
static inline void amd_spi_set_rx_count(struct spi_master *master,
u8 rx_count)
static inline void amd_spi_set_rx_count(struct amd_spi *amd_spi, u8 rx_count)
{
amd_spi_setclear_reg8(master, AMD_SPI_RX_COUNT_REG, rx_count, 0xff);
amd_spi_setclear_reg8(amd_spi, AMD_SPI_RX_COUNT_REG, rx_count, 0xff);
}
static inline void amd_spi_set_tx_count(struct spi_master *master,
u8 tx_count)
static inline void amd_spi_set_tx_count(struct amd_spi *amd_spi, u8 tx_count)
{
amd_spi_setclear_reg8(master, AMD_SPI_TX_COUNT_REG, tx_count, 0xff);
amd_spi_setclear_reg8(amd_spi, AMD_SPI_TX_COUNT_REG, tx_count, 0xff);
}
static inline int amd_spi_busy_wait(struct amd_spi *amd_spi)
static int amd_spi_busy_wait(struct amd_spi *amd_spi)
{
bool spi_busy;
int timeout = 100000;
/* poll for SPI bus to become idle */
spi_busy = (ioread32((u8 __iomem *)amd_spi->io_remap_addr +
AMD_SPI_CTRL0_REG) & AMD_SPI_BUSY) == AMD_SPI_BUSY;
while (spi_busy) {
while (amd_spi_readreg32(amd_spi, AMD_SPI_CTRL0_REG) & AMD_SPI_BUSY) {
usleep_range(10, 20);
if (timeout-- < 0)
return -ETIMEDOUT;
spi_busy = (ioread32((u8 __iomem *)amd_spi->io_remap_addr +
AMD_SPI_CTRL0_REG) & AMD_SPI_BUSY) == AMD_SPI_BUSY;
}
return 0;
}
static void amd_spi_execute_opcode(struct spi_master *master)
static int amd_spi_execute_opcode(struct amd_spi *amd_spi)
{
struct amd_spi *amd_spi = spi_master_get_devdata(master);
int ret;
ret = amd_spi_busy_wait(amd_spi);
if (ret)
return ret;
/* Set ExecuteOpCode bit in the CTRL0 register */
amd_spi_setclear_reg32(master, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD,
AMD_SPI_EXEC_CMD);
amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD, AMD_SPI_EXEC_CMD);
amd_spi_busy_wait(amd_spi);
return 0;
}
static int amd_spi_master_setup(struct spi_device *spi)
{
struct spi_master *master = spi->master;
struct amd_spi *amd_spi = spi_master_get_devdata(spi->master);
amd_spi_clear_fifo_ptr(master);
amd_spi_clear_fifo_ptr(amd_spi);
return 0;
}
......@@ -185,19 +161,18 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
tx_len = xfer->len - 1;
cmd_opcode = *(u8 *)xfer->tx_buf;
buf++;
amd_spi_set_opcode(master, cmd_opcode);
amd_spi_set_opcode(amd_spi, cmd_opcode);
/* Write data into the FIFO. */
for (i = 0; i < tx_len; i++) {
iowrite8(buf[i],
((u8 __iomem *)amd_spi->io_remap_addr +
iowrite8(buf[i], ((u8 __iomem *)amd_spi->io_remap_addr +
AMD_SPI_FIFO_BASE + i));
}
amd_spi_set_tx_count(master, tx_len);
amd_spi_clear_fifo_ptr(master);
amd_spi_set_tx_count(amd_spi, tx_len);
amd_spi_clear_fifo_ptr(amd_spi);
/* Execute command */
amd_spi_execute_opcode(master);
amd_spi_execute_opcode(amd_spi);
}
if (m_cmd & AMD_SPI_XFER_RX) {
/*
......@@ -206,15 +181,14 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
*/
rx_len = xfer->len;
buf = (u8 *)xfer->rx_buf;
amd_spi_set_rx_count(master, rx_len);
amd_spi_clear_fifo_ptr(master);
amd_spi_set_rx_count(amd_spi, rx_len);
amd_spi_clear_fifo_ptr(amd_spi);
/* Execute command */
amd_spi_execute_opcode(master);
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(master,
AMD_SPI_FIFO_BASE +
tx_len + i);
buf[i] = amd_spi_readreg8(amd_spi, AMD_SPI_FIFO_BASE + tx_len + i);
}
}
......@@ -233,8 +207,7 @@ static int amd_spi_master_transfer(struct spi_master *master,
struct amd_spi *amd_spi = spi_master_get_devdata(master);
struct spi_device *spi = msg->spi;
amd_spi->chip_select = spi->chip_select;
amd_spi_select_chip(master);
amd_spi_select_chip(amd_spi, spi->chip_select);
/*
* Extract spi_transfers from the spi message and
......
......@@ -14,7 +14,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
......@@ -482,29 +482,12 @@ static void at91_usart_spi_init(struct at91_usart_spi *aus)
static int at91_usart_gpio_setup(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.parent->of_node;
int i;
int ret;
int nb;
if (!np)
return -EINVAL;
nb = of_gpio_named_count(np, "cs-gpios");
for (i = 0; i < nb; i++) {
int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
struct gpio_descs *cs_gpios;
if (cs_gpio < 0)
return cs_gpio;
cs_gpios = devm_gpiod_get_array_optional(&pdev->dev, "cs", GPIOD_OUT_LOW);
if (gpio_is_valid(cs_gpio)) {
ret = devm_gpio_request_one(&pdev->dev, cs_gpio,
GPIOF_DIR_OUT,
dev_name(&pdev->dev));
if (ret)
return ret;
}
}
if (IS_ERR(cs_gpios))
return PTR_ERR(cs_gpios);
return 0;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -67,9 +67,14 @@
SPI_FSI_STATUS_RDR_OVERRUN)
#define SPI_FSI_PORT_CTRL 0x9
struct fsi2spi {
struct fsi_device *fsi; /* FSI2SPI CFAM engine device */
struct mutex lock; /* lock access to the device */
};
struct fsi_spi {
struct device *dev; /* SPI controller device */
struct fsi_device *fsi; /* FSI2SPI CFAM engine device */
struct fsi2spi *bridge; /* FSI2SPI device */
u32 base;
};
......@@ -104,7 +109,7 @@ static int fsi_spi_check_status(struct fsi_spi *ctx)
u32 sts;
__be32 sts_be;
rc = fsi_device_read(ctx->fsi, FSI2SPI_STATUS, &sts_be,
rc = fsi_device_read(ctx->bridge->fsi, FSI2SPI_STATUS, &sts_be,
sizeof(sts_be));
if (rc)
return rc;
......@@ -120,73 +125,91 @@ static int fsi_spi_check_status(struct fsi_spi *ctx)
static int fsi_spi_read_reg(struct fsi_spi *ctx, u32 offset, u64 *value)
{
int rc;
int rc = 0;
__be32 cmd_be;
__be32 data_be;
u32 cmd = offset + ctx->base;
struct fsi2spi *bridge = ctx->bridge;
*value = 0ULL;
if (cmd & FSI2SPI_CMD_WRITE)
return -EINVAL;
cmd_be = cpu_to_be32(cmd);
rc = fsi_device_write(ctx->fsi, FSI2SPI_CMD, &cmd_be, sizeof(cmd_be));
rc = mutex_lock_interruptible(&bridge->lock);
if (rc)
return rc;
cmd_be = cpu_to_be32(cmd);
rc = fsi_device_write(bridge->fsi, FSI2SPI_CMD, &cmd_be,
sizeof(cmd_be));
if (rc)
goto unlock;
rc = fsi_spi_check_status(ctx);
if (rc)
return rc;
goto unlock;
rc = fsi_device_read(ctx->fsi, FSI2SPI_DATA0, &data_be,
rc = fsi_device_read(bridge->fsi, FSI2SPI_DATA0, &data_be,
sizeof(data_be));
if (rc)
return rc;
goto unlock;
*value |= (u64)be32_to_cpu(data_be) << 32;
rc = fsi_device_read(ctx->fsi, FSI2SPI_DATA1, &data_be,
rc = fsi_device_read(bridge->fsi, FSI2SPI_DATA1, &data_be,
sizeof(data_be));
if (rc)
return rc;
goto unlock;
*value |= (u64)be32_to_cpu(data_be);
dev_dbg(ctx->dev, "Read %02x[%016llx].\n", offset, *value);
return 0;
unlock:
mutex_unlock(&bridge->lock);
return rc;
}
static int fsi_spi_write_reg(struct fsi_spi *ctx, u32 offset, u64 value)
{
int rc;
int rc = 0;
__be32 cmd_be;
__be32 data_be;
u32 cmd = offset + ctx->base;
struct fsi2spi *bridge = ctx->bridge;
if (cmd & FSI2SPI_CMD_WRITE)
return -EINVAL;
rc = mutex_lock_interruptible(&bridge->lock);
if (rc)
return rc;
dev_dbg(ctx->dev, "Write %02x[%016llx].\n", offset, value);
data_be = cpu_to_be32(upper_32_bits(value));
rc = fsi_device_write(ctx->fsi, FSI2SPI_DATA0, &data_be,
rc = fsi_device_write(bridge->fsi, FSI2SPI_DATA0, &data_be,
sizeof(data_be));
if (rc)
return rc;
goto unlock;
data_be = cpu_to_be32(lower_32_bits(value));
rc = fsi_device_write(ctx->fsi, FSI2SPI_DATA1, &data_be,
rc = fsi_device_write(bridge->fsi, FSI2SPI_DATA1, &data_be,
sizeof(data_be));
if (rc)
return rc;
goto unlock;
cmd_be = cpu_to_be32(cmd | FSI2SPI_CMD_WRITE);
rc = fsi_device_write(ctx->fsi, FSI2SPI_CMD, &cmd_be, sizeof(cmd_be));
rc = fsi_device_write(bridge->fsi, FSI2SPI_CMD, &cmd_be,
sizeof(cmd_be));
if (rc)
return rc;
goto unlock;
return fsi_spi_check_status(ctx);
rc = fsi_spi_check_status(ctx);
unlock:
mutex_unlock(&bridge->lock);
return rc;
}
static int fsi_spi_data_in(u64 in, u8 *rx, int len)
......@@ -234,6 +257,26 @@ static int fsi_spi_reset(struct fsi_spi *ctx)
return fsi_spi_write_reg(ctx, SPI_FSI_STATUS, 0ULL);
}
static int fsi_spi_status(struct fsi_spi *ctx, u64 *status, const char *dir)
{
int rc = fsi_spi_read_reg(ctx, SPI_FSI_STATUS, status);
if (rc)
return rc;
if (*status & SPI_FSI_STATUS_ANY_ERROR) {
dev_err(ctx->dev, "%s error: %016llx\n", dir, *status);
rc = fsi_spi_reset(ctx);
if (rc)
return rc;
return -EREMOTEIO;
}
return 0;
}
static void fsi_spi_sequence_add(struct fsi_spi_sequence *seq, u8 val)
{
/*
......@@ -273,18 +316,9 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
return rc;
do {
rc = fsi_spi_read_reg(ctx, SPI_FSI_STATUS,
&status);
rc = fsi_spi_status(ctx, &status, "TX");
if (rc)
return rc;
if (status & SPI_FSI_STATUS_ANY_ERROR) {
rc = fsi_spi_reset(ctx);
if (rc)
return rc;
return -EREMOTEIO;
}
} while (status & SPI_FSI_STATUS_TDR_FULL);
sent += nb;
......@@ -296,18 +330,9 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
while (transfer->len > recv) {
do {
rc = fsi_spi_read_reg(ctx, SPI_FSI_STATUS,
&status);
rc = fsi_spi_status(ctx, &status, "RX");
if (rc)
return rc;
if (status & SPI_FSI_STATUS_ANY_ERROR) {
rc = fsi_spi_reset(ctx);
if (rc)
return rc;
return -EREMOTEIO;
}
} while (!(status & SPI_FSI_STATUS_RDR_FULL));
rc = fsi_spi_read_reg(ctx, SPI_FSI_DATA_RX, &in);
......@@ -348,8 +373,12 @@ static int fsi_spi_transfer_init(struct fsi_spi *ctx)
if (status & (SPI_FSI_STATUS_ANY_ERROR |
SPI_FSI_STATUS_TDR_FULL |
SPI_FSI_STATUS_RDR_FULL)) {
if (reset)
if (reset) {
dev_err(ctx->dev,
"Initialization error: %08llx\n",
status);
return -EIO;
}
rc = fsi_spi_reset(ctx);
if (rc)
......@@ -388,7 +417,7 @@ static int fsi_spi_transfer_one_message(struct spi_controller *ctlr,
struct spi_transfer *transfer;
struct fsi_spi *ctx = spi_controller_get_devdata(ctlr);
rc = fsi_spi_check_mux(ctx->fsi, ctx->dev);
rc = fsi_spi_check_mux(ctx->bridge->fsi, ctx->dev);
if (rc)
goto error;
......@@ -478,12 +507,20 @@ static int fsi_spi_probe(struct device *dev)
int rc;
struct device_node *np;
int num_controllers_registered = 0;
struct fsi2spi *bridge;
struct fsi_device *fsi = to_fsi_dev(dev);
rc = fsi_spi_check_mux(fsi, dev);
if (rc)
return -ENODEV;
bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);
if (!bridge)
return -ENOMEM;
bridge->fsi = fsi;
mutex_init(&bridge->lock);
for_each_available_child_of_node(dev->of_node, np) {
u32 base;
struct fsi_spi *ctx;
......@@ -506,7 +543,7 @@ static int fsi_spi_probe(struct device *dev)
ctx = spi_controller_get_devdata(ctlr);
ctx->dev = &ctlr->dev;
ctx->fsi = fsi;
ctx->bridge = bridge;
ctx->base = base + SPI_FSI_BASE;
rc = devm_spi_register_controller(dev, ctlr);
......
......@@ -2,6 +2,9 @@
// Copyright (c) 2017-2018, The Linux foundation. All rights reserved.
#include <linux/clk.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/dma/qcom-gpi-dma.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/log2.h>
......@@ -63,6 +66,15 @@
#define TIMESTAMP_AFTER BIT(3)
#define POST_CMD_DELAY BIT(4)
#define GSI_LOOPBACK_EN BIT(0)
#define GSI_CS_TOGGLE BIT(3)
#define GSI_CPHA BIT(4)
#define GSI_CPOL BIT(5)
#define MAX_TX_SG 3
#define NUM_SPI_XFER 8
#define SPI_XFER_TIMEOUT_MS 250
struct spi_geni_master {
struct geni_se se;
struct device *dev;
......@@ -84,6 +96,9 @@ struct spi_geni_master {
int irq;
bool cs_flag;
bool abort_failed;
struct dma_chan *tx;
struct dma_chan *rx;
int cur_xfer_mode;
};
static int get_spi_clk_cfg(unsigned int speed_hz,
......@@ -330,34 +345,197 @@ static int setup_fifo_params(struct spi_device *spi_slv,
return geni_spi_set_clock_and_bw(mas, spi_slv->max_speed_hz);
}
static void
spi_gsi_callback_result(void *cb, const struct dmaengine_result *result)
{
struct spi_master *spi = cb;
if (result->result != DMA_TRANS_NOERROR) {
dev_err(&spi->dev, "DMA txn failed: %d\n", result->result);
return;
}
if (!result->residue) {
dev_dbg(&spi->dev, "DMA txn completed\n");
spi_finalize_current_transfer(spi);
} else {
dev_err(&spi->dev, "DMA xfer has pending: %d\n", result->residue);
}
}
static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas,
struct spi_device *spi_slv, struct spi_master *spi)
{
unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
struct dma_slave_config config = {};
struct gpi_spi_config peripheral = {};
struct dma_async_tx_descriptor *tx_desc, *rx_desc;
int ret;
config.peripheral_config = &peripheral;
config.peripheral_size = sizeof(peripheral);
peripheral.set_config = true;
if (xfer->bits_per_word != mas->cur_bits_per_word ||
xfer->speed_hz != mas->cur_speed_hz) {
mas->cur_bits_per_word = xfer->bits_per_word;
mas->cur_speed_hz = xfer->speed_hz;
}
if (xfer->tx_buf && xfer->rx_buf) {
peripheral.cmd = SPI_DUPLEX;
} else if (xfer->tx_buf) {
peripheral.cmd = SPI_TX;
peripheral.rx_len = 0;
} else if (xfer->rx_buf) {
peripheral.cmd = SPI_RX;
if (!(mas->cur_bits_per_word % MIN_WORD_LEN)) {
peripheral.rx_len = ((xfer->len << 3) / mas->cur_bits_per_word);
} else {
int bytes_per_word = (mas->cur_bits_per_word / BITS_PER_BYTE) + 1;
peripheral.rx_len = (xfer->len / bytes_per_word);
}
}
peripheral.loopback_en = !!(spi_slv->mode & SPI_LOOP);
peripheral.clock_pol_high = !!(spi_slv->mode & SPI_CPOL);
peripheral.data_pol_high = !!(spi_slv->mode & SPI_CPHA);
peripheral.cs = spi_slv->chip_select;
peripheral.pack_en = true;
peripheral.word_len = xfer->bits_per_word - MIN_WORD_LEN;
ret = get_spi_clk_cfg(mas->cur_speed_hz, mas,
&peripheral.clk_src, &peripheral.clk_div);
if (ret) {
dev_err(mas->dev, "Err in get_spi_clk_cfg() :%d\n", ret);
return ret;
}
if (!xfer->cs_change) {
if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))
peripheral.fragmentation = FRAGMENTATION;
}
if (peripheral.cmd & SPI_RX) {
dmaengine_slave_config(mas->rx, &config);
rx_desc = dmaengine_prep_slave_sg(mas->rx, xfer->rx_sg.sgl, xfer->rx_sg.nents,
DMA_DEV_TO_MEM, flags);
if (!rx_desc) {
dev_err(mas->dev, "Err setting up rx desc\n");
return -EIO;
}
}
/*
* Prepare the TX always, even for RX or tx_buf being null, we would
* need TX to be prepared per GSI spec
*/
dmaengine_slave_config(mas->tx, &config);
tx_desc = dmaengine_prep_slave_sg(mas->tx, xfer->tx_sg.sgl, xfer->tx_sg.nents,
DMA_MEM_TO_DEV, flags);
if (!tx_desc) {
dev_err(mas->dev, "Err setting up tx desc\n");
return -EIO;
}
tx_desc->callback_result = spi_gsi_callback_result;
tx_desc->callback_param = spi;
if (peripheral.cmd & SPI_RX)
dmaengine_submit(rx_desc);
dmaengine_submit(tx_desc);
if (peripheral.cmd & SPI_RX)
dma_async_issue_pending(mas->rx);
dma_async_issue_pending(mas->tx);
return 1;
}
static bool geni_can_dma(struct spi_controller *ctlr,
struct spi_device *slv, struct spi_transfer *xfer)
{
struct spi_geni_master *mas = spi_master_get_devdata(slv->master);
/* check if dma is supported */
return mas->cur_xfer_mode != GENI_SE_FIFO;
}
static int spi_geni_prepare_message(struct spi_master *spi,
struct spi_message *spi_msg)
{
int ret;
struct spi_geni_master *mas = spi_master_get_devdata(spi);
int ret;
if (spi_geni_is_abort_still_pending(mas))
return -EBUSY;
switch (mas->cur_xfer_mode) {
case GENI_SE_FIFO:
if (spi_geni_is_abort_still_pending(mas))
return -EBUSY;
ret = setup_fifo_params(spi_msg->spi, spi);
if (ret)
dev_err(mas->dev, "Couldn't select mode %d\n", ret);
return ret;
ret = setup_fifo_params(spi_msg->spi, spi);
if (ret)
dev_err(mas->dev, "Couldn't select mode %d\n", ret);
case GENI_GPI_DMA:
/* nothing to do for GPI DMA */
return 0;
}
dev_err(mas->dev, "Mode not supported %d", mas->cur_xfer_mode);
return -EINVAL;
}
static int spi_geni_grab_gpi_chan(struct spi_geni_master *mas)
{
int ret;
mas->tx = dma_request_chan(mas->dev, "tx");
ret = dev_err_probe(mas->dev, IS_ERR(mas->tx), "Failed to get tx DMA ch\n");
if (ret < 0)
goto err_tx;
mas->rx = dma_request_chan(mas->dev, "rx");
ret = dev_err_probe(mas->dev, IS_ERR(mas->rx), "Failed to get rx DMA ch\n");
if (ret < 0)
goto err_rx;
return 0;
err_rx:
dma_release_channel(mas->tx);
mas->tx = NULL;
err_tx:
mas->rx = NULL;
return ret;
}
static void spi_geni_release_dma_chan(struct spi_geni_master *mas)
{
if (mas->rx) {
dma_release_channel(mas->rx);
mas->rx = NULL;
}
if (mas->tx) {
dma_release_channel(mas->tx);
mas->tx = NULL;
}
}
static int spi_geni_init(struct spi_geni_master *mas)
{
struct geni_se *se = &mas->se;
unsigned int proto, major, minor, ver;
u32 spi_tx_cfg;
u32 spi_tx_cfg, fifo_disable;
int ret = -ENXIO;
pm_runtime_get_sync(mas->dev);
proto = geni_se_read_proto(se);
if (proto != GENI_SE_SPI) {
dev_err(mas->dev, "Invalid proto %d\n", proto);
pm_runtime_put(mas->dev);
return -ENXIO;
goto out_pm;
}
mas->tx_fifo_depth = geni_se_get_tx_fifo_depth(se);
......@@ -380,15 +558,38 @@ static int spi_geni_init(struct spi_geni_master *mas)
else
mas->oversampling = 1;
geni_se_select_mode(se, GENI_SE_FIFO);
fifo_disable = readl(se->base + GENI_IF_DISABLE_RO) & FIFO_IF_DISABLE;
switch (fifo_disable) {
case 1:
ret = spi_geni_grab_gpi_chan(mas);
if (!ret) { /* success case */
mas->cur_xfer_mode = GENI_GPI_DMA;
geni_se_select_mode(se, GENI_GPI_DMA);
dev_dbg(mas->dev, "Using GPI DMA mode for SPI\n");
break;
}
/*
* in case of failure to get dma channel, we can still do the
* FIFO mode, so fallthrough
*/
dev_warn(mas->dev, "FIFO mode disabled, but couldn't get DMA, fall back to FIFO mode\n");
fallthrough;
case 0:
mas->cur_xfer_mode = GENI_SE_FIFO;
geni_se_select_mode(se, GENI_SE_FIFO);
ret = 0;
break;
}
/* We always control CS manually */
spi_tx_cfg = readl(se->base + SE_SPI_TRANS_CFG);
spi_tx_cfg &= ~CS_TOGGLE;
writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG);
out_pm:
pm_runtime_put(mas->dev);
return 0;
return ret;
}
static unsigned int geni_byte_per_fifo_word(struct spi_geni_master *mas)
......@@ -569,8 +770,11 @@ static int spi_geni_transfer_one(struct spi_master *spi,
if (!xfer->len)
return 0;
setup_fifo_xfer(xfer, mas, slv->mode, spi);
return 1;
if (mas->cur_xfer_mode == GENI_SE_FIFO) {
setup_fifo_xfer(xfer, mas, slv->mode, spi);
return 1;
}
return setup_gsi_xfer(xfer, mas, slv, spi);
}
static irqreturn_t geni_spi_isr(int irq, void *data)
......@@ -665,6 +869,13 @@ static int spi_geni_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
if (ret) {
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret)
return dev_err_probe(dev, ret, "could not set DMA mask\n");
}
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
......@@ -704,9 +915,10 @@ static int spi_geni_probe(struct platform_device *pdev)
spi->max_speed_hz = 50000000;
spi->prepare_message = spi_geni_prepare_message;
spi->transfer_one = spi_geni_transfer_one;
spi->can_dma = geni_can_dma;
spi->dma_map_dev = dev->parent;
spi->auto_runtime_pm = true;
spi->handle_err = handle_fifo_timeout;
spi->set_cs = spi_geni_set_cs;
spi->use_gpio_descriptors = true;
init_completion(&mas->cs_done);
......@@ -732,9 +944,17 @@ static int spi_geni_probe(struct platform_device *pdev)
if (ret)
goto spi_geni_probe_runtime_disable;
/*
* check the mode supported and set_cs for fifo mode only
* for dma (gsi) mode, the gsi will set cs based on params passed in
* TRE
*/
if (mas->cur_xfer_mode == GENI_SE_FIFO)
spi->set_cs = spi_geni_set_cs;
ret = request_irq(mas->irq, geni_spi_isr, 0, dev_name(dev), spi);
if (ret)
goto spi_geni_probe_runtime_disable;
goto spi_geni_release_dma;
ret = spi_register_master(spi);
if (ret)
......@@ -743,6 +963,8 @@ static int spi_geni_probe(struct platform_device *pdev)
return 0;
spi_geni_probe_free_irq:
free_irq(mas->irq, spi);
spi_geni_release_dma:
spi_geni_release_dma_chan(mas);
spi_geni_probe_runtime_disable:
pm_runtime_disable(dev);
return ret;
......@@ -756,6 +978,8 @@ static int spi_geni_remove(struct platform_device *pdev)
/* Unregister _before_ disabling pm_runtime() so we stop transfers */
spi_unregister_master(spi);
spi_geni_release_dma_chan(mas);
free_irq(mas->irq, spi);
pm_runtime_disable(&pdev->dev);
return 0;
......
This diff is collapsed.
......@@ -160,7 +160,7 @@ static bool mtk_nor_match_read(const struct spi_mem_op *op)
{
int dummy = 0;
if (op->dummy.buswidth)
if (op->dummy.nbytes)
dummy = op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth;
if ((op->data.buswidth == 2) || (op->data.buswidth == 4)) {
......
......@@ -769,6 +769,7 @@ static int orion_spi_probe(struct platform_device *pdev)
dir_acc->vaddr = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE);
if (!dir_acc->vaddr) {
status = -ENOMEM;
of_node_put(np);
goto out_rel_axi_clk;
}
dir_acc->size = PAGE_SIZE;
......
......@@ -139,7 +139,9 @@ static int rpcif_spi_probe(struct platform_device *pdev)
return -ENOMEM;
rpc = spi_controller_get_devdata(ctlr);
rpcif_sw_init(rpc, parent);
error = rpcif_sw_init(rpc, parent);
if (error)
return error;
platform_set_drvdata(pdev, ctlr);
......
......@@ -1427,4 +1427,3 @@ module_platform_driver(rspi_driver);
MODULE_DESCRIPTION("Renesas RSPI bus driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Yoshihiro Shimoda");
MODULE_ALIAS("platform:rspi");
......@@ -1426,4 +1426,3 @@ module_platform_driver(sh_msiof_spi_drv);
MODULE_DESCRIPTION("SuperH MSIOF SPI Controller Interface Driver");
MODULE_AUTHOR("Magnus Damm");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:spi_sh_msiof");
......@@ -397,7 +397,7 @@ static int stm32_qspi_send(struct spi_mem *mem, const struct spi_mem_op *op)
ccr |= FIELD_PREP(CCR_ADSIZE_MASK, op->addr.nbytes - 1);
}
if (op->dummy.buswidth && op->dummy.nbytes)
if (op->dummy.nbytes)
ccr |= FIELD_PREP(CCR_DCYC_MASK,
op->dummy.nbytes * 8 / op->dummy.buswidth);
......
......@@ -1124,7 +1124,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
exit_pm_put:
pm_runtime_put(&pdev->dev);
exit_pm_disable:
pm_runtime_disable(&pdev->dev);
pm_runtime_force_suspend(&pdev->dev);
tegra_slink_deinit_dma_param(tspi, false);
exit_rx_dma_free:
......@@ -1143,7 +1143,7 @@ static int tegra_slink_remove(struct platform_device *pdev)
free_irq(tspi->irq, tspi);
pm_runtime_disable(&pdev->dev);
pm_runtime_force_suspend(&pdev->dev);
if (tspi->tx_dma_chan)
tegra_slink_deinit_dma_param(tspi, false);
......
......@@ -1318,7 +1318,7 @@ static int tegra_qspi_probe(struct platform_device *pdev)
exit_free_irq:
free_irq(qspi_irq, tqspi);
exit_pm_disable:
pm_runtime_disable(&pdev->dev);
pm_runtime_force_suspend(&pdev->dev);
tegra_qspi_deinit_dma(tqspi);
return ret;
}
......@@ -1330,7 +1330,7 @@ static int tegra_qspi_remove(struct platform_device *pdev)
spi_unregister_master(master);
free_irq(tqspi->irq, tqspi);
pm_runtime_disable(&pdev->dev);
pm_runtime_force_suspend(&pdev->dev);
tegra_qspi_deinit_dma(tqspi);
return 0;
......
......@@ -141,7 +141,7 @@ static ssize_t tle62x0_gpio_show(struct device *dev,
value = (st->gpio_state >> gpio_num) & 1;
mutex_unlock(&st->lock);
return snprintf(buf, PAGE_SIZE, "%d", value);
return sysfs_emit(buf, "%d", value);
}
static ssize_t tle62x0_gpio_store(struct device *dev,
......
This diff is collapsed.
......@@ -123,6 +123,7 @@ enum pm_ioctl_id {
IOCTL_READ_PGGS = 15,
/* Set healthy bit value */
IOCTL_SET_BOOT_HEALTH_STATUS = 17,
IOCTL_OSPI_MUX_SELECT = 21,
};
enum pm_query_id {
......@@ -351,6 +352,11 @@ enum zynqmp_pm_shutdown_subtype {
ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM = 2,
};
enum ospi_mux_select_type {
PM_OSPI_MUX_SEL_DMA = 0,
PM_OSPI_MUX_SEL_LINEAR = 1,
};
/**
* struct zynqmp_pm_query_data - PM query data
* @qid: query ID
......@@ -387,6 +393,7 @@ int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data);
int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data);
int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value);
int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type);
int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select);
int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
const enum zynqmp_pm_reset_action assert_flag);
int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status);
......@@ -508,6 +515,11 @@ static inline int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
return -ENODEV;
}
static inline int zynqmp_pm_ospi_mux_select(u32 dev_id, u32 select)
{
return -ENODEV;
}
static inline int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
const enum zynqmp_pm_reset_action assert_flag)
{
......
......@@ -78,10 +78,6 @@ struct spi_statistics {
unsigned long transfers_split_maxsize;
};
void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
struct spi_transfer *xfer,
struct spi_controller *ctlr);
#define SPI_STATISTICS_ADD_TO_FIELD(stats, field, count) \
do { \
unsigned long flags; \
......@@ -763,8 +759,6 @@ extern int devm_spi_register_controller(struct device *dev,
struct spi_controller *ctlr);
extern void spi_unregister_controller(struct spi_controller *ctlr);
extern struct spi_controller *spi_busnum_to_master(u16 busnum);
/*
* SPI resource management while processing a SPI message
*/
......@@ -788,15 +782,6 @@ struct spi_res {
unsigned long long data[]; /* guarantee ull alignment */
};
extern void *spi_res_alloc(struct spi_device *spi,
spi_res_release_t release,
size_t size, gfp_t gfp);
extern void spi_res_add(struct spi_message *message, void *res);
extern void spi_res_free(void *res);
extern void spi_res_release(struct spi_controller *ctlr,
struct spi_message *message);
/*---------------------------------------------------------------------------*/
/*
......@@ -1114,8 +1099,6 @@ static inline void spi_message_free(struct spi_message *m)
extern int spi_setup(struct spi_device *spi);
extern int spi_async(struct spi_device *spi, struct spi_message *message);
extern int spi_async_locked(struct spi_device *spi,
struct spi_message *message);
extern int spi_slave_abort(struct spi_device *spi);
static inline size_t
......@@ -1198,15 +1181,6 @@ struct spi_replaced_transfers {
struct spi_transfer inserted_transfers[];
};
extern struct spi_replaced_transfers *spi_replace_transfers(
struct spi_message *msg,
struct spi_transfer *xfer_first,
size_t remove,
size_t insert,
spi_replaced_release_t release,
size_t extradatasize,
gfp_t gfp);
/*---------------------------------------------------------------------------*/
/* SPI transfer transformation methods */
......@@ -1478,19 +1452,7 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
* use spi_new_device() to describe each device. You can also call
* spi_unregister_device() to start making that device vanish, but
* normally that would be handled by spi_unregister_controller().
*
* You can also use spi_alloc_device() and spi_add_device() to use a two
* stage registration sequence for each spi_device. This gives the caller
* some more control over the spi_device structure before it is registered,
* but requires that caller to initialize fields that would otherwise
* be defined using the board info.
*/
extern struct spi_device *
spi_alloc_device(struct spi_controller *ctlr);
extern int
spi_add_device(struct spi_device *spi);
extern struct spi_device *
spi_new_device(struct spi_controller *, struct spi_board_info *);
......@@ -1505,23 +1467,6 @@ spi_transfer_is_last(struct spi_controller *ctlr, struct spi_transfer *xfer)
return list_is_last(&xfer->transfer_list, &ctlr->cur_msg->transfers);
}
/* OF support code */
#if IS_ENABLED(CONFIG_OF)
/* must call put_device() when done with returned spi_device device */
extern struct spi_device *
of_find_spi_device_by_node(struct device_node *node);
#else
static inline struct spi_device *
of_find_spi_device_by_node(struct device_node *node)
{
return NULL;
}
#endif /* IS_ENABLED(CONFIG_OF) */
/* Compatibility layer */
#define spi_master spi_controller
......
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