Commit d8e0f976 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull spi updates from Mark Brown:
 "This is quite a quiet release but some new drivers mean that the
  diffstat is fairly large. The new drivers include the aspeed driver
  which is migrated from MTD as part of the ongoing move of controllers
  with specialised support for SPI flashes into the SPI subsystem.

   - Support for devices which flip CPHA during recieve only transfers
     (eg, if MOSI and MISO have inverted polarity).

   - Overhaul of the i.MX driver, including the addition of PIO support
     for better performance on small transfers.

   - Migration of the Aspeed driver from MTD.

   - Support for Aspeed AST2400, Ingenic JZ4775 and X1/2000 and MediaTek
     IPM and SFI"

* tag 'spi-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (84 commits)
  spi: spi-au1550: replace ternary operator with min()
  mtd: spi-nor: aspeed: set the decoding size to at least 2MB for AST2600
  spi: aspeed: Calibrate read timings
  spi: aspeed: Add support for the AST2400 SPI controller
  spi: aspeed: Workaround AST2500 limitations
  spi: aspeed: Adjust direct mapping to device size
  spi: aspeed: Add support for direct mapping
  spi: spi-mem: Convert Aspeed SMC driver to spi-mem
  spi: Convert the Aspeed SMC controllers device tree binding
  spi: spi-cadence: Update ISR status variable type to irqreturn_t
  spi: Doc fix - Describe add_lock and dma_map_dev in spi_controller
  spi: cadence-quadspi: Handle spi_unregister_master() in remove()
  spi: stm32-qspi: Remove SR_BUSY bit check before sending command
  spi: stm32-qspi: Always check SR_TCF flags in stm32_qspi_wait_cmd()
  spi: stm32-qspi: Fix wait_cmd timeout in APM mode
  spi: cadence-quadspi: remove unnecessary (void *) casts
  spi: cadence-quadspi: Add missing blank line in cqspi_request_mmap_dma()
  spi: spi-imx: mx51_ecspi_prepare_message(): skip writing MX51_ECSPI_CONFIG register if unchanged
  spi: spi-imx: add PIO polling support
  spi: spi-imx: replace struct spi_imx_data::bitbang by pointer to struct spi_controller
  ...
parents 9b18d07b 9c63b846
* Aspeed Firmware Memory controller
* Aspeed SPI Flash Memory Controller
The Firmware Memory Controller in the Aspeed AST2500 SoC supports
three chip selects, two of which are always of SPI type and the third
can be SPI or NOR type flash. These bindings only describe SPI.
The two SPI flash memory controllers in the AST2500 each support two
chip selects.
Required properties:
- compatible : Should be one of
"aspeed,ast2400-fmc" for the AST2400 Firmware Memory Controller
"aspeed,ast2400-spi" for the AST2400 SPI Flash memory Controller
"aspeed,ast2500-fmc" for the AST2500 Firmware Memory Controller
"aspeed,ast2500-spi" for the AST2500 SPI flash memory controllers
- reg : the first contains the control register location and length,
the second contains the memory window mapping address and length
- #address-cells : must be 1 corresponding to chip select child binding
- #size-cells : must be 0 corresponding to chip select child binding
Optional properties:
- interrupts : Should contain the interrupt for the dma device if an
FMC
The child nodes are the SPI flash modules which must have a compatible
property as specified in bindings/mtd/jedec,spi-nor.txt
Optionally, the child node can contain properties for SPI mode (may be
ignored):
- spi-max-frequency - max frequency of spi bus
Example:
fmc: fmc@1e620000 {
compatible = "aspeed,ast2500-fmc";
reg = < 0x1e620000 0x94
0x20000000 0x02000000 >;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <19>;
flash@0 {
reg = < 0 >;
compatible = "jedec,spi-nor";
/* spi-max-frequency = <>; */
/* m25p,fast-read; */
#address-cells = <1>;
#size-cells = <1>;
};
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/aspeed,ast2600-fmc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Aspeed SMC controllers bindings
maintainers:
- Chin-Ting Kuo <chin-ting_kuo@aspeedtech.com>
- Cédric Le Goater <clg@kaod.org>
description: |
This binding describes the Aspeed Static Memory Controllers (FMC and
SPI) of the AST2400, AST2500 and AST2600 SOCs.
allOf:
- $ref: "spi-controller.yaml#"
properties:
compatible:
enum:
- aspeed,ast2600-fmc
- aspeed,ast2600-spi
- aspeed,ast2500-fmc
- aspeed,ast2500-spi
- aspeed,ast2400-fmc
- aspeed,ast2400-spi
reg:
items:
- description: registers
- description: memory mapping
clocks:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- clocks
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/aspeed-scu-ic.h>
#include <dt-bindings/clock/ast2600-clock.h>
spi@1e620000 {
reg = <0x1e620000 0xc4>, <0x20000000 0x10000000>;
#address-cells = <1>;
#size-cells = <0>;
compatible = "aspeed,ast2600-fmc";
clocks = <&syscon ASPEED_CLK_AHB>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
flash@0 {
reg = < 0 >;
compatible = "jedec,spi-nor";
spi-max-frequency = <50000000>;
spi-rx-bus-width = <2>;
};
flash@1 {
reg = < 1 >;
compatible = "jedec,spi-nor";
spi-max-frequency = <50000000>;
spi-rx-bus-width = <2>;
};
flash@2 {
reg = < 2 >;
compatible = "jedec,spi-nor";
spi-max-frequency = <50000000>;
spi-rx-bus-width = <2>;
};
};
......@@ -18,7 +18,10 @@ properties:
oneOf:
- enum:
- ingenic,jz4750-spi
- ingenic,jz4775-spi
- ingenic,jz4780-spi
- ingenic,x1000-spi
- ingenic,x2000-spi
- items:
- enum:
- ingenic,jz4760-spi
......
......@@ -53,16 +53,20 @@ properties:
maxItems: 1
clocks:
minItems: 3
items:
- description: clock used for the parent clock
- description: clock used for the muxes clock
- description: clock used for the clock gate
- description: clock used for the AHB bus, this clock is optional
clock-names:
minItems: 3
items:
- const: parent-clk
- const: sel-clk
- const: spi-clk
- const: hclk
mediatek,pad-select:
$ref: /schemas/types.yaml#/definitions/uint32-array
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/mediatek,spi-mtk-snfi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SPI-NAND flash controller for MediaTek ARM SoCs
maintainers:
- Chuanhong Guo <gch981213@gmail.com>
description: |
The Mediatek SPI-NAND flash controller is an extended version of
the Mediatek NAND flash controller. It can perform standard SPI
instructions with one continuous write and one read for up-to 0xa0
bytes. It also supports typical SPI-NAND page cache operations
in single, dual or quad IO mode with pipelined ECC encoding/decoding
using the accompanying ECC engine. There should be only one spi
slave device following generic spi bindings.
allOf:
- $ref: /schemas/spi/spi-controller.yaml#
properties:
compatible:
enum:
- mediatek,mt7622-snand
- mediatek,mt7629-snand
reg:
items:
- description: core registers
interrupts:
items:
- description: NFI interrupt
clocks:
items:
- description: clock used for the controller
- description: clock used for the SPI bus
clock-names:
items:
- const: nfi_clk
- const: pad_clk
nand-ecc-engine:
description: device-tree node of the accompanying ECC engine.
$ref: /schemas/types.yaml#/definitions/phandle
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- nand-ecc-engine
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/mt7622-clk.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
snfi: spi@1100d000 {
compatible = "mediatek,mt7622-snand";
reg = <0 0x1100d000 0 0x1000>;
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
clocks = <&pericfg CLK_PERI_NFI_PD>, <&pericfg CLK_PERI_SNFI_PD>;
clock-names = "nfi_clk", "pad_clk";
nand-ecc-engine = <&bch>;
#address-cells = <1>;
#size-cells = <0>;
flash@0 {
compatible = "spi-nand";
reg = <0>;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
nand-ecc-engine = <&snfi>;
};
};
};
......@@ -49,6 +49,7 @@ properties:
maxItems: 2
interconnect-names:
minItems: 1
items:
- const: qspi-config
- const: qspi-memory
......
......@@ -21,6 +21,7 @@ properties:
- enum:
- renesas,rspi-r7s72100 # RZ/A1H
- renesas,rspi-r7s9210 # RZ/A2
- renesas,r9a07g043-rspi # RZ/G2UL
- renesas,r9a07g044-rspi # RZ/G2{L,LC}
- renesas,r9a07g054-rspi # RZ/V2L
- const: renesas,rspi-rz
......@@ -124,6 +125,7 @@ allOf:
contains:
enum:
- renesas,qspi
- renesas,r9a07g043-rspi
- renesas,r9a07g044-rspi
- renesas,r9a07g054-rspi
then:
......
......@@ -3102,6 +3102,16 @@ S: Maintained
F: Documentation/devicetree/bindings/mmc/aspeed,sdhci.yaml
F: drivers/mmc/host/sdhci-of-aspeed*
ASPEED SMC SPI DRIVER
M: Chin-Ting Kuo <chin-ting_kuo@aspeedtech.com>
M: Cédric Le Goater <clg@kaod.org>
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
L: linux-spi@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/spi/aspeed,ast2600-fmc.yaml
F: drivers/spi/spi-aspeed-smc.c
ASPEED VIDEO ENGINE DRIVER
M: Eddie James <eajames@linux.ibm.com>
L: linux-media@vger.kernel.org
......
# SPDX-License-Identifier: GPL-2.0-only
config SPI_ASPEED_SMC
tristate "Aspeed flash controllers in SPI mode"
depends on ARCH_ASPEED || COMPILE_TEST
depends on HAS_IOMEM && OF
help
This enables support for the Firmware Memory controller (FMC)
in the Aspeed AST2500/AST2400 SoCs when attached to SPI NOR chips,
and support for the SPI flash memory controller (SPI) for
the host firmware. The implementation only supports SPI NOR.
config SPI_HISI_SFC
tristate "Hisilicon FMC SPI NOR Flash Controller(SFC)"
depends on ARCH_HISI || COMPILE_TEST
......
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_SPI_ASPEED_SMC) += aspeed-smc.o
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
This diff is collapsed.
......@@ -101,6 +101,17 @@ config SPI_ARMADA_3700
This enables support for the SPI controller present on the
Marvell Armada 3700 SoCs.
config SPI_ASPEED_SMC
tristate "Aspeed flash controllers in SPI mode"
depends on ARCH_ASPEED || COMPILE_TEST
depends on OF
help
This enables support for the Firmware Memory controller (FMC)
in the Aspeed AST2600, AST2500 and AST2400 SoCs when attached
to SPI NOR chips, and support for the SPI flash memory
controller (SPI) for the host firmware. The implementation
only supports SPI NOR.
config SPI_ATMEL
tristate "Atmel SPI Controller"
depends on ARCH_AT91 || COMPILE_TEST
......@@ -414,15 +425,14 @@ config SPI_IMG_SPFI
config SPI_IMX
tristate "Freescale i.MX SPI controllers"
depends on ARCH_MXC || COMPILE_TEST
select SPI_BITBANG
help
This enables support for the Freescale i.MX SPI controllers.
config SPI_INGENIC
tristate "Ingenic JZ47xx SoCs SPI controller"
tristate "Ingenic SoCs SPI controller"
depends on MACH_INGENIC || COMPILE_TEST
help
This enables support for the Ingenic JZ47xx SoCs SPI controller.
This enables support for the Ingenic SoCs SPI controller.
To compile this driver as a module, choose M here: the module
will be called spi-ingenic.
......@@ -590,6 +600,16 @@ config SPI_MTK_NOR
SPI interface as well as several SPI NOR specific instructions
via SPI MEM interface.
config SPI_MTK_SNFI
tristate "MediaTek SPI NAND Flash Interface"
depends on ARCH_MEDIATEK || COMPILE_TEST
depends on MTD_NAND_ECC_MEDIATEK
help
This enables support for SPI-NAND mode on the MediaTek NAND
Flash Interface found on MediaTek ARM SoCs. This controller
is implemented as a SPI-MEM controller with pipelined ECC
capcability.
config SPI_NPCM_FIU
tristate "Nuvoton NPCM FLASH Interface Unit"
depends on ARCH_NPCM || COMPILE_TEST
......
......@@ -19,6 +19,7 @@ obj-$(CONFIG_SPI_ALTERA_CORE) += spi-altera-core.o
obj-$(CONFIG_SPI_ALTERA_DFL) += spi-altera-dfl.o
obj-$(CONFIG_SPI_AR934X) += spi-ar934x.o
obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o
obj-$(CONFIG_SPI_ASPEED_SMC) += spi-aspeed-smc.o
obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
obj-$(CONFIG_SPI_ATMEL_QUADSPI) += atmel-quadspi.o
obj-$(CONFIG_SPI_AT91_USART) += spi-at91-usart.o
......@@ -76,6 +77,7 @@ obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o
obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o
obj-$(CONFIG_SPI_MTK_NOR) += spi-mtk-nor.o
obj-$(CONFIG_SPI_MTK_SNFI) += spi-mtk-snfi.o
obj-$(CONFIG_SPI_MXIC) += spi-mxic.o
obj-$(CONFIG_SPI_MXS) += spi-mxs.o
obj-$(CONFIG_SPI_NPCM_FIU) += spi-npcm-fiu.o
......
......@@ -288,12 +288,6 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem,
op->dummy.nbytes == 0)
return false;
/* DTR ops not supported. */
if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
return false;
if (op->cmd.nbytes != 1)
return false;
return true;
}
......
This diff is collapsed.
......@@ -405,7 +405,7 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
dma_unmap_single(hw->dev, dma_tx_addr, t->len,
DMA_TO_DEVICE);
return hw->rx_count < hw->tx_count ? hw->rx_count : hw->tx_count;
return min(hw->rx_count, hw->tx_count);
}
static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw)
......@@ -539,7 +539,7 @@ static int au1550_spi_pio_txrxb(struct spi_device *spi, struct spi_transfer *t)
wait_for_completion(&hw->master_done);
return hw->rx_count < hw->tx_count ? hw->rx_count : hw->tx_count;
return min(hw->rx_count, hw->tx_count);
}
static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw)
......
This diff is collapsed.
......@@ -342,7 +342,8 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)
{
struct spi_master *master = dev_id;
struct cdns_spi *xspi = spi_master_get_devdata(master);
u32 intr_status, status;
irqreturn_t status;
u32 intr_status;
status = IRQ_NONE;
intr_status = cdns_spi_read(xspi, CDNS_SPI_ISR);
......@@ -657,7 +658,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev)
*
* Return: 0 on success and error value on error
*/
static int __maybe_unused cnds_runtime_resume(struct device *dev)
static int __maybe_unused cdns_spi_runtime_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct cdns_spi *xspi = spi_master_get_devdata(master);
......@@ -686,7 +687,7 @@ static int __maybe_unused cnds_runtime_resume(struct device *dev)
*
* Return: Always 0
*/
static int __maybe_unused cnds_runtime_suspend(struct device *dev)
static int __maybe_unused cdns_spi_runtime_suspend(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct cdns_spi *xspi = spi_master_get_devdata(master);
......@@ -698,8 +699,8 @@ static int __maybe_unused cnds_runtime_suspend(struct device *dev)
}
static const struct dev_pm_ops cdns_spi_dev_pm_ops = {
SET_RUNTIME_PM_OPS(cnds_runtime_suspend,
cnds_runtime_resume, NULL)
SET_RUNTIME_PM_OPS(cdns_spi_runtime_suspend,
cdns_spi_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(cdns_spi_suspend, cdns_spi_resume)
};
......
......@@ -9,6 +9,7 @@
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
......@@ -89,6 +90,7 @@ static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
static int spi_clps711x_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct spi_clps711x_data *hw;
struct spi_master *master;
int irq, ret;
......@@ -117,8 +119,7 @@ static int spi_clps711x_probe(struct platform_device *pdev)
goto err_out;
}
hw->syscon =
syscon_regmap_lookup_by_compatible("cirrus,ep7209-syscon3");
hw->syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
if (IS_ERR(hw->syscon)) {
ret = PTR_ERR(hw->syscon);
goto err_out;
......
......@@ -876,6 +876,10 @@ static int fsl_qspi_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"QuadSPI-memory");
if (!res) {
ret = -EINVAL;
goto err_put_ctrl;
}
q->memmap_phy = res->start;
/* Since there are 4 cs, map size required is 4 times ahb_buf_size */
q->ahb_addr = devm_ioremap(dev, q->memmap_phy,
......
......@@ -731,7 +731,7 @@ static int img_spfi_resume(struct device *dev)
int ret;
ret = pm_runtime_get_sync(dev);
if (ret) {
if (ret < 0) {
pm_runtime_put_noidle(dev);
return ret;
}
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
/*
* SPI bus driver for the Ingenic JZ47xx SoCs
* SPI bus driver for the Ingenic SoCs
* Copyright (c) 2017-2021 Artur Rojek <contact@artur-rojek.eu>
* Copyright (c) 2017-2021 Paul Cercueil <paul@crapouillou.net>
* Copyright (c) 2022 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
*/
#include <linux/clk.h>
......@@ -52,6 +53,9 @@ struct jz_soc_info {
u32 bits_per_word_mask;
struct reg_field flen_field;
bool has_trendian;
unsigned int max_speed_hz;
unsigned int max_native_cs;
};
struct ingenic_spi {
......@@ -380,7 +384,7 @@ static int spi_ingenic_probe(struct platform_device *pdev)
struct spi_controller *ctlr;
struct ingenic_spi *priv;
void __iomem *base;
int ret;
int num_cs, ret;
pdata = of_device_get_match_data(dev);
if (!pdata) {
......@@ -416,6 +420,9 @@ static int spi_ingenic_probe(struct platform_device *pdev)
if (IS_ERR(priv->flen_field))
return PTR_ERR(priv->flen_field);
if (device_property_read_u32(dev, "num-cs", &num_cs))
num_cs = pdata->max_native_cs;
platform_set_drvdata(pdev, ctlr);
ctlr->prepare_transfer_hardware = spi_ingenic_prepare_hardware;
......@@ -428,8 +435,10 @@ static int spi_ingenic_probe(struct platform_device *pdev)
ctlr->max_dma_len = SPI_INGENIC_FIFO_SIZE;
ctlr->bits_per_word_mask = pdata->bits_per_word_mask;
ctlr->min_speed_hz = 7200;
ctlr->max_speed_hz = 54000000;
ctlr->num_chipselect = 2;
ctlr->max_speed_hz = pdata->max_speed_hz;
ctlr->use_gpio_descriptors = true;
ctlr->max_native_cs = pdata->max_native_cs;
ctlr->num_chipselect = num_cs;
ctlr->dev.of_node = pdev->dev.of_node;
if (spi_ingenic_request_dma(ctlr, dev))
......@@ -452,17 +461,44 @@ static const struct jz_soc_info jz4750_soc_info = {
.bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 17),
.flen_field = REG_FIELD(REG_SSICR1, 4, 7),
.has_trendian = false,
.max_speed_hz = 54000000,
.max_native_cs = 2,
};
static const struct jz_soc_info jz4780_soc_info = {
.bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 32),
.flen_field = REG_FIELD(REG_SSICR1, 3, 7),
.has_trendian = true,
.max_speed_hz = 54000000,
.max_native_cs = 2,
};
static const struct jz_soc_info x1000_soc_info = {
.bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 32),
.flen_field = REG_FIELD(REG_SSICR1, 3, 7),
.has_trendian = true,
.max_speed_hz = 50000000,
.max_native_cs = 2,
};
static const struct jz_soc_info x2000_soc_info = {
.bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 32),
.flen_field = REG_FIELD(REG_SSICR1, 3, 7),
.has_trendian = true,
.max_speed_hz = 50000000,
.max_native_cs = 1,
};
static const struct of_device_id spi_ingenic_of_match[] = {
{ .compatible = "ingenic,jz4750-spi", .data = &jz4750_soc_info },
{ .compatible = "ingenic,jz4775-spi", .data = &jz4780_soc_info },
{ .compatible = "ingenic,jz4780-spi", .data = &jz4780_soc_info },
{ .compatible = "ingenic,x1000-spi", .data = &x1000_soc_info },
{ .compatible = "ingenic,x2000-spi", .data = &x2000_soc_info },
{}
};
MODULE_DEVICE_TABLE(of, spi_ingenic_of_match);
......@@ -476,7 +512,8 @@ static struct platform_driver spi_ingenic_driver = {
};
module_platform_driver(spi_ingenic_driver);
MODULE_DESCRIPTION("SPI bus driver for the Ingenic JZ47xx SoCs");
MODULE_DESCRIPTION("SPI bus driver for the Ingenic SoCs");
MODULE_AUTHOR("Artur Rojek <contact@artur-rojek.eu>");
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>");
MODULE_LICENSE("GPL");
......@@ -779,10 +779,59 @@ static const char *intel_spi_get_name(struct spi_mem *mem)
return dev_name(ispi->dev);
}
static int intel_spi_dirmap_create(struct spi_mem_dirmap_desc *desc)
{
struct intel_spi *ispi = spi_master_get_devdata(desc->mem->spi->master);
const struct intel_spi_mem_op *iop;
iop = intel_spi_match_mem_op(ispi, &desc->info.op_tmpl);
if (!iop)
return -EOPNOTSUPP;
desc->priv = (void *)iop;
return 0;
}
static ssize_t intel_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs,
size_t len, void *buf)
{
struct intel_spi *ispi = spi_master_get_devdata(desc->mem->spi->master);
const struct intel_spi_mem_op *iop = desc->priv;
struct spi_mem_op op = desc->info.op_tmpl;
int ret;
/* Fill in the gaps */
op.addr.val = offs;
op.data.nbytes = len;
op.data.buf.in = buf;
ret = iop->exec_op(ispi, iop, &op);
return ret ? ret : len;
}
static ssize_t intel_spi_dirmap_write(struct spi_mem_dirmap_desc *desc, u64 offs,
size_t len, const void *buf)
{
struct intel_spi *ispi = spi_master_get_devdata(desc->mem->spi->master);
const struct intel_spi_mem_op *iop = desc->priv;
struct spi_mem_op op = desc->info.op_tmpl;
int ret;
op.addr.val = offs;
op.data.nbytes = len;
op.data.buf.out = buf;
ret = iop->exec_op(ispi, iop, &op);
return ret ? ret : len;
}
static const struct spi_controller_mem_ops intel_spi_mem_ops = {
.supports_op = intel_spi_supports_mem_op,
.exec_op = intel_spi_exec_mem_op,
.get_name = intel_spi_get_name,
.dirmap_create = intel_spi_dirmap_create,
.dirmap_read = intel_spi_dirmap_read,
.dirmap_write = intel_spi_dirmap_write,
};
#define INTEL_SPI_OP_ADDR(__nbytes) \
......@@ -1205,7 +1254,7 @@ static int intel_spi_populate_chip(struct intel_spi *ispi)
* intel_spi_probe() - Probe the Intel SPI flash controller
* @dev: Pointer to the parent device
* @mem: MMIO resource
* @info: Platform spefific information
* @info: Platform specific information
*
* Probes Intel SPI flash controller and creates the flash chip device.
* Returns %0 on success and negative errno in case of failure.
......
......@@ -10,6 +10,7 @@
#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>
#include <linux/sched/task_stack.h>
#include "internals.h"
......@@ -211,6 +212,15 @@ static int spi_mem_check_op(const struct spi_mem_op *op)
!spi_mem_buswidth_is_valid(op->data.buswidth))
return -EINVAL;
/* Buffers must be DMA-able. */
if (WARN_ON_ONCE(op->data.dir == SPI_MEM_DATA_IN &&
object_is_on_stack(op->data.buf.in)))
return -EINVAL;
if (WARN_ON_ONCE(op->data.dir == SPI_MEM_DATA_OUT &&
object_is_on_stack(op->data.buf.out)))
return -EINVAL;
return 0;
}
......@@ -262,9 +272,8 @@ static int spi_mem_access_start(struct spi_mem *mem)
if (ctlr->auto_runtime_pm) {
int ret;
ret = pm_runtime_get_sync(ctlr->dev.parent);
ret = pm_runtime_resume_and_get(ctlr->dev.parent);
if (ret < 0) {
pm_runtime_put_noidle(ctlr->dev.parent);
dev_err(&ctlr->dev, "Failed to power device: %d\n",
ret);
return ret;
......
......@@ -20,6 +20,7 @@
#include <linux/spi/spi.h>
#include <linux/fsl_devices.h>
#include <linux/slab.h>
#include <linux/of_irq.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
......
......@@ -19,6 +19,9 @@
#include <linux/io.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <asm/time.h>
#include <asm/mpc52xx.h>
......
This diff is collapsed.
This diff is collapsed.
......@@ -605,9 +605,8 @@ static int mxs_spi_probe(struct platform_device *pdev)
}
}
ret = pm_runtime_get_sync(ssp->dev);
ret = pm_runtime_resume_and_get(ssp->dev);
if (ret < 0) {
pm_runtime_put_noidle(ssp->dev);
dev_err(ssp->dev, "runtime_get_sync failed\n");
goto out_pm_runtime_disable;
}
......
......@@ -246,9 +246,8 @@ static void omap2_mcspi_set_cs(struct spi_device *spi, bool enable)
enable = !enable;
if (spi->controller_state) {
int err = pm_runtime_get_sync(mcspi->dev);
int err = pm_runtime_resume_and_get(mcspi->dev);
if (err < 0) {
pm_runtime_put_noidle(mcspi->dev);
dev_err(mcspi->dev, "failed to get sync: %d\n", err);
return;
}
......@@ -758,6 +757,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
dev_vdbg(&spi->dev, "read-%d %02x\n",
word_len, *(rx - 1));
}
/* Add word delay between each word */
spi_delay_exec(&xfer->word_delay, xfer);
} while (c);
} else if (word_len <= 16) {
u16 *rx;
......@@ -805,6 +806,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
dev_vdbg(&spi->dev, "read-%d %04x\n",
word_len, *(rx - 1));
}
/* Add word delay between each word */
spi_delay_exec(&xfer->word_delay, xfer);
} while (c >= 2);
} else if (word_len <= 32) {
u32 *rx;
......@@ -852,6 +855,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
dev_vdbg(&spi->dev, "read-%d %08x\n",
word_len, *(rx - 1));
}
/* Add word delay between each word */
spi_delay_exec(&xfer->word_delay, xfer);
} while (c >= 4);
}
......@@ -1068,9 +1073,8 @@ static int omap2_mcspi_setup(struct spi_device *spi)
initial_setup = true;
}
ret = pm_runtime_get_sync(mcspi->dev);
ret = pm_runtime_resume_and_get(mcspi->dev);
if (ret < 0) {
pm_runtime_put_noidle(mcspi->dev);
if (initial_setup)
omap2_mcspi_cleanup(spi);
......@@ -1317,12 +1321,9 @@ static int omap2_mcspi_controller_setup(struct omap2_mcspi *mcspi)
struct omap2_mcspi_regs *ctx = &mcspi->ctx;
int ret = 0;
ret = pm_runtime_get_sync(mcspi->dev);
if (ret < 0) {
pm_runtime_put_noidle(mcspi->dev);
ret = pm_runtime_resume_and_get(mcspi->dev);
if (ret < 0)
return ret;
}
mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE,
OMAP2_MCSPI_WAKEUPENABLE_WKEN);
......
......@@ -196,6 +196,8 @@ struct rockchip_spi {
bool slave_abort;
bool cs_inactive; /* spi slave tansmition stop when cs inactive */
bool cs_high_supported; /* native CS supports active-high polarity */
struct spi_transfer *xfer; /* Store xfer temporarily */
};
......@@ -719,6 +721,11 @@ static int rockchip_spi_setup(struct spi_device *spi)
struct rockchip_spi *rs = spi_controller_get_devdata(spi->controller);
u32 cr0;
if (!spi->cs_gpiod && (spi->mode & SPI_CS_HIGH) && !rs->cs_high_supported) {
dev_warn(&spi->dev, "setup: non GPIO CS can't be active-high\n");
return -EINVAL;
}
pm_runtime_get_sync(rs->dev);
cr0 = readl_relaxed(rs->regs + ROCKCHIP_SPI_CTRLR0);
......@@ -899,6 +906,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
switch (readl_relaxed(rs->regs + ROCKCHIP_SPI_VERSION)) {
case ROCKCHIP_SPI_VER2_TYPE2:
rs->cs_high_supported = true;
ctlr->mode_bits |= SPI_CS_HIGH;
if (ctlr->can_dma && slave_mode)
rs->cs_inactive = true;
......
......@@ -1108,14 +1108,11 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev,
}
memset(&cfg, 0, sizeof(cfg));
cfg.dst_addr = port_addr + RSPI_SPDR;
cfg.src_addr = port_addr + RSPI_SPDR;
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
cfg.direction = dir;
if (dir == DMA_MEM_TO_DEV) {
cfg.dst_addr = port_addr;
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
} else {
cfg.src_addr = port_addr;
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
}
ret = dmaengine_slave_config(chan, &cfg);
if (ret) {
......@@ -1146,12 +1143,12 @@ static int rspi_request_dma(struct device *dev, struct spi_controller *ctlr,
}
ctlr->dma_tx = rspi_request_dma_chan(dev, DMA_MEM_TO_DEV, dma_tx_id,
res->start + RSPI_SPDR);
res->start);
if (!ctlr->dma_tx)
return -ENODEV;
ctlr->dma_rx = rspi_request_dma_chan(dev, DMA_DEV_TO_MEM, dma_rx_id,
res->start + RSPI_SPDR);
res->start);
if (!ctlr->dma_rx) {
dma_release_channel(ctlr->dma_tx);
ctlr->dma_tx = NULL;
......
......@@ -1008,9 +1008,8 @@ static int sprd_spi_remove(struct platform_device *pdev)
struct sprd_spi *ss = spi_controller_get_devdata(sctlr);
int ret;
ret = pm_runtime_get_sync(ss->dev);
ret = pm_runtime_resume_and_get(ss->dev);
if (ret < 0) {
pm_runtime_put_noidle(ss->dev);
dev_err(ss->dev, "failed to resume SPI controller\n");
return ret;
}
......
This diff is collapsed.
......@@ -2000,9 +2000,8 @@ static int __maybe_unused stm32_spi_resume(struct device *dev)
return ret;
}
ret = pm_runtime_get_sync(dev);
ret = pm_runtime_resume_and_get(dev);
if (ret < 0) {
pm_runtime_put_noidle(dev);
dev_err(dev, "Unable to power device:%d\n", ret);
return ret;
}
......
......@@ -85,8 +85,6 @@ struct sp7021_spi_ctlr {
int s_irq;
struct clk *spi_clk;
struct reset_control *rstc;
// irq spin lock
spinlock_t lock;
// data xfer lock
struct mutex buf_lock;
struct completion isr_done;
......@@ -199,8 +197,6 @@ static irqreturn_t sp7021_spi_master_irq(int irq, void *dev)
if (tx_len == 0 && total_len == 0)
return IRQ_NONE;
spin_lock_irq(&pspim->lock);
rx_cnt = FIELD_GET(SP7021_RX_CNT_MASK, fd_status);
if (fd_status & SP7021_RX_FULL_FLAG)
rx_cnt = pspim->data_unit;
......@@ -239,7 +235,6 @@ static irqreturn_t sp7021_spi_master_irq(int irq, void *dev)
if (isrdone)
complete(&pspim->isr_done);
spin_unlock_irq(&pspim->lock);
return IRQ_HANDLED;
}
......@@ -446,7 +441,6 @@ static int sp7021_spi_controller_probe(struct platform_device *pdev)
pspim->mode = mode;
pspim->ctlr = ctlr;
pspim->dev = dev;
spin_lock_init(&pspim->lock);
mutex_init(&pspim->buf_lock);
init_completion(&pspim->isr_done);
init_completion(&pspim->slave_isr);
......
This diff is collapsed.
......@@ -486,10 +486,9 @@ static int tegra_sflash_probe(struct platform_device *pdev)
goto exit_pm_disable;
}
ret = pm_runtime_get_sync(&pdev->dev);
ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
pm_runtime_put_noidle(&pdev->dev);
goto exit_pm_disable;
}
......@@ -549,9 +548,8 @@ static int tegra_sflash_resume(struct device *dev)
struct tegra_sflash_data *tsd = spi_master_get_devdata(master);
int ret;
ret = pm_runtime_get_sync(dev);
ret = pm_runtime_resume_and_get(dev);
if (ret < 0) {
pm_runtime_put_noidle(dev);
dev_err(dev, "pm runtime failed, e = %d\n", ret);
return ret;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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