Commit d0f3ad23 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull spi updates from Mark Brown:
 "A busy enough release, but not for the core which has only seen very
  small updates. The biggest addition is the readdition of support for
  detailed configuration of the timings around chip selects. That had
  been removed for lack of use but there's been applications found for
  it on Atmel systems. Otherwise the updates are mostly feature
  additions and cleanups to existing drivers.

  Summary:

   - Provide a helper for getting device match data in a way that
     abstracts away which firmware interface is being used.

   - Re-add the spi_set_cs_timing() API for detailed configuration of
     the timing around chip select and support it on Atmel.

   - Support for MediaTek MT7986, Microchip PCI1xxxx, Nuvoton WPCM450
     FIU and Socionext F_OSPI"

* tag 'spi-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (66 commits)
  spi: dt-bindings: Convert Synquacer SPI to DT schema
  spi: spi-gpio: Don't set MOSI as an input if not 3WIRE mode
  spi: spi-mtk-nor: Add recovery mechanism for dma read timeout
  spi: spi-fsl-lpspi: add num-cs binding for lpspi
  spi: spi-fsl-lpspi: support multiple cs for lpspi
  spi: mtk-snfi: Add snfi support for MT7986 IC
  spi: spidev: mask SPI_CS_HIGH in SPI_IOC_RD_MODE
  spi: cadence-quadspi: Add minimum operable clock rate warning to baudrate divisor calculation
  spi: microchip: pci1xxxx: Add suspend and resume support for PCI1XXXX SPI driver
  spi: dt-bindings: nuvoton,wpcm450-fiu: Fix warning in example (missing reg property)
  spi: dt-bindings: nuvoton,wpcm450-fiu: Fix error in example (bogus include)
  spi: mediatek: Enable irq when pdata is ready
  spi: spi-mtk-nor: Unify write buffer on/off
  spi: intel: Add support for SFDP opcode
  spi: intel: Take possible chip address into account in intel_spi_read/write_reg()
  spi: intel: Implement adjust_op_size()
  spi: intel: Use ->replacement_op in intel_spi_hw_cycle()
  spi: cadence: Drop obsolete dependency on COMPILE_TEST
  spi: Add Nuvoton WPCM450 Flash Interface Unit (FIU) bindings
  spi: wpcm-fiu: Add direct map support
  ...
parents c5589c43 3cf241c3
......@@ -10,9 +10,6 @@ title: Amlogic Meson SPI Communication Controller
maintainers:
- Neil Armstrong <neil.armstrong@linaro.org>
allOf:
- $ref: "spi-controller.yaml#"
description: |
The Meson SPICC is a generic SPI controller for general purpose Full-Duplex
communications with dedicated 16 words RX/TX PIO FIFOs.
......@@ -43,31 +40,53 @@ properties:
minItems: 1
maxItems: 2
if:
properties:
compatible:
contains:
enum:
- amlogic,meson-g12a-spicc
then:
properties:
clocks:
minItems: 2
clock-names:
items:
- const: core
- const: pclk
else:
properties:
clocks:
maxItems: 1
clock-names:
items:
- const: core
allOf:
- $ref: "spi-controller.yaml#"
- if:
properties:
compatible:
contains:
enum:
- amlogic,meson-g12a-spicc
then:
properties:
clocks:
minItems: 2
clock-names:
items:
- const: core
- const: pclk
else:
properties:
clocks:
maxItems: 1
clock-names:
items:
- const: core
- if:
properties:
compatible:
contains:
enum:
- amlogic,meson-gx-spicc
then:
properties:
pinctrl-0: true
pinctrl-1: true
pinctrl-2: true
pinctrl-names:
minItems: 1
items:
- const: default
- const: idle-high
- const: idle-low
required:
- compatible
......
......@@ -51,7 +51,7 @@ fiu3: spi@c00000000 {
clocks = <&clk NPCM7XX_CLK_AHB>;
pinctrl-names = "default";
pinctrl-0 = <&spi3_pins>;
spi-nor@0 {
flash@0 {
...
};
};
......
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/nuvoton,wpcm450-fiu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Nuvoton WPCM450 Flash Interface Unit (FIU)
maintainers:
- Jonathan Neuschäfer <j.neuschaefer@gmx.net>
allOf:
- $ref: /schemas/spi/spi-controller.yaml#
properties:
compatible:
const: nuvoton,wpcm450-fiu
reg:
items:
- description: FIU registers
- description: Memory-mapped flash contents
reg-names:
items:
- const: control
- const: memory
interrupts:
maxItems: 1
clocks:
maxItems: 1
nuvoton,shm:
$ref: /schemas/types.yaml#/definitions/phandle
description: a phandle to the SHM block (see ../arm/nuvoton,shm.yaml)
required:
- compatible
- reg
- clocks
unevaluatedProperties: false
examples:
- |
spi@c8000000 {
compatible = "nuvoton,wpcm450-fiu";
reg = <0xc8000000 0x1000>, <0xc0000000 0x4000000>;
#address-cells = <1>;
#size-cells = <0>;
reg-names = "control", "memory";
clocks = <&clk 0>;
nuvoton,shm = <&shm>;
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
};
};
shm: syscon@c8001000 {
compatible = "nuvoton,wpcm450-shm", "syscon";
reg = <0xc8001000 0x1000>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/socionext,f-ospi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Socionext F_OSPI controller
description: |
The Socionext F_OSPI is a controller used to interface with flash
memories using the SPI communication interface.
maintainers:
- Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
allOf:
- $ref: spi-controller.yaml#
properties:
compatible:
const: socionext,f-ospi
reg:
maxItems: 1
clocks:
maxItems: 1
num-cs:
minimum: 1
maximum: 4
required:
- compatible
- reg
- clocks
- "#address-cells"
- "#size-cells"
unevaluatedProperties: false
examples:
- |
ospi0: spi@80000000 {
compatible = "socionext,f-ospi";
reg = <0x80000000 0x1000>;
clocks = <&clks 0>;
num-cs = <1>;
#address-cells = <1>;
#size-cells = <0>;
flash@0 {
compatible = "spansion,s25fl128s", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <50000000>;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/socionext,synquacer-spi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Socionext SynQuacer HS-SPI Controller
maintainers:
- Masahisa Kojima <masahisa.kojima@linaro.org>
- Jassi Brar <jaswinder.singh@linaro.org>
allOf:
- $ref: spi-controller.yaml#
properties:
compatible:
const: socionext,synquacer-spi
reg:
maxItems: 1
clocks:
minItems: 1
items:
- description: core clock
- description: rate clock
clock-names:
minItems: 1
items:
- const: iHCLK
- const: iPCLK
interrupts:
items:
- description: Receive Interrupt
- description: Transmit Interrupt
- description: Fault Interrupt
socionext,use-rtm:
type: boolean
description: Enable using "retimed clock" for RX
socionext,set-aces:
type: boolean
description: Enable same active clock edges field to be set
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
spi@ff110000 {
compatible = "socionext,synquacer-spi";
reg = <0xff110000 0x1000>;
interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_hsspi>;
clock-names = "iHCLK";
socionext,use-rtm;
socionext,set-aces;
};
...
......@@ -56,6 +56,13 @@ properties:
this property to re-config the chipselect value in the LPSPI driver.
type: boolean
num-cs:
description:
number of chip selects.
minimum: 1
maximum: 2
default: 1
required:
- compatible
- reg
......@@ -80,4 +87,5 @@ examples:
clock-names = "per", "ipg";
spi-slave;
fsl,spi-only-use-cs1-sel;
num-cs = <2>;
};
......@@ -44,6 +44,11 @@ properties:
description:
Maximum SPI clocking speed of the device in Hz.
spi-cs-setup-ns:
description:
Delay in nanosecods to be introduced by the controller after CS is
asserted.
spi-rx-bus-width:
description:
Bus width to the SPI bus used for read transfers.
......
* Socionext Synquacer HS-SPI bindings
Required Properties:
- compatible: should be "socionext,synquacer-spi"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: should contain the "spi_rx", "spi_tx" and "spi_fault" interrupts.
- clocks: core clock iHCLK. Optional rate clock iPCLK (default is iHCLK)
- clock-names: Shall be "iHCLK" and "iPCLK" respectively
Optional Properties:
- socionext,use-rtm: boolean, if required to use "retimed clock" for RX
- socionext,set-aces: boolean, if same active clock edges field to be set.
Example:
spi0: spi@ff110000 {
compatible = "socionext,synquacer-spi";
reg = <0xff110000 0x1000>;
interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_hsspi>;
clock-names = "iHCLK";
socionext,use-rtm;
socionext,set-aces;
};
......@@ -14,7 +14,9 @@ allOf:
properties:
compatible:
const: xlnx,zynqmp-qspi-1.0
enum:
- xlnx,versal-qspi-1.0
- xlnx,zynqmp-qspi-1.0
reg:
maxItems: 2
......
......@@ -25,8 +25,8 @@ hardware, which may be as simple as a set of GPIO pins or as complex as
a pair of FIFOs connected to dual DMA engines on the other side of the
SPI shift register (maximizing throughput). Such drivers bridge between
whatever bus they sit on (often the platform bus) and SPI, and expose
the SPI side of their device as a :c:type:`struct spi_master
<spi_master>`. SPI devices are children of that master,
the SPI side of their device as a :c:type:`struct spi_controller
<spi_controller>`. SPI devices are children of that master,
represented as a :c:type:`struct spi_device <spi_device>` and
manufactured from :c:type:`struct spi_board_info
<spi_board_info>` descriptors which are usually provided by
......
......@@ -19159,7 +19159,7 @@ M: Masahisa Kojima <masahisa.kojima@linaro.org>
M: Jassi Brar <jaswinder.singh@linaro.org>
L: linux-spi@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/spi/spi-synquacer.txt
F: Documentation/devicetree/bindings/spi/socionext,synquacer-spi.yaml
F: drivers/spi/spi-synquacer.c
SOCIONEXT SYNQUACER I2C DRIVER
......
......@@ -843,6 +843,13 @@ int zynqmp_pm_read_pggs(u32 index, u32 *value)
}
EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value)
{
return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_TAPDELAY_BYPASS,
index, value, NULL);
}
EXPORT_SYMBOL_GPL(zynqmp_pm_set_tapdelay_bypass);
/**
* zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
* @value: Status value to be written
......
......@@ -241,7 +241,7 @@ config SPI_CADENCE_QUADSPI
config SPI_CADENCE_XSPI
tristate "Cadence XSPI controller"
depends on (OF || COMPILE_TEST) && HAS_IOMEM
depends on OF && HAS_IOMEM
depends on SPI_MEM
help
Enable support for the Cadence XSPI Flash controller.
......@@ -635,6 +635,17 @@ config SPI_MTK_SNFI
is implemented as a SPI-MEM controller with pipelined ECC
capcability.
config SPI_WPCM_FIU
tristate "Nuvoton WPCM450 Flash Interface Unit"
depends on ARCH_NPCM || COMPILE_TEST
select REGMAP
help
This enables support got the Flash Interface Unit SPI controller
present in the Nuvoton WPCM450 SoC.
This driver does not support generic SPI. The implementation only
supports the spi-mem interface.
config SPI_NPCM_FIU
tristate "Nuvoton NPCM FLASH Interface Unit"
depends on ARCH_NPCM || COMPILE_TEST
......@@ -710,6 +721,15 @@ config SPI_ORION
This enables using the SPI master controller on the Orion
and MVEBU chips.
config SPI_PCI1XXXX
tristate "PCI1XXXX SPI Bus support"
depends on PCI
help
Say "yes" to Enable the SPI Bus support for the PCI1xxxx card
This is a PCI to SPI Bus driver
This driver can be built as module. If so, the module will be
called as spi-pci1xxxx.
config SPI_PIC32
tristate "Microchip PIC32 series SPI"
depends on MACH_PIC32 || COMPILE_TEST
......@@ -897,6 +917,15 @@ config SPI_SLAVE_MT27XX
say Y or M here.If you are not sure, say N.
SPI slave drivers for Mediatek MT27XX series ARM SoCs.
config SPI_SN_F_OSPI
tristate "Socionext F_OSPI SPI flash controller"
depends on OF && HAS_IOMEM
depends on SPI_MEM
help
This enables support for the Socionext F_OSPI controller
for connecting an SPI Flash memory over up to 8-bit wide bus.
It supports indirect access mode only.
config SPI_SPRD
tristate "Spreadtrum SPI controller"
depends on ARCH_SPRD || COMPILE_TEST
......
......@@ -83,6 +83,7 @@ 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_WPCM_FIU) += spi-wpcm-fiu.o
obj-$(CONFIG_SPI_NPCM_FIU) += spi-npcm-fiu.o
obj-$(CONFIG_SPI_NPCM_PSPI) += spi-npcm-pspi.o
obj-$(CONFIG_SPI_NXP_FLEXSPI) += spi-nxp-fspi.o
......@@ -94,6 +95,7 @@ obj-$(CONFIG_SPI_OMAP_100K) += spi-omap-100k.o
obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o
obj-$(CONFIG_SPI_TI_QSPI) += spi-ti-qspi.o
obj-$(CONFIG_SPI_ORION) += spi-orion.o
obj-$(CONFIG_SPI_PCI1XXXX) += spi-pci1xxxx.o
obj-$(CONFIG_SPI_PIC32) += spi-pic32.o
obj-$(CONFIG_SPI_PIC32_SQI) += spi-pic32-sqi.o
obj-$(CONFIG_SPI_PL022) += spi-pl022.o
......@@ -120,6 +122,7 @@ obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o
obj-$(CONFIG_SPI_SLAVE_MT27XX) += spi-slave-mt27xx.o
obj-$(CONFIG_SPI_SN_F_OSPI) += spi-sn-f-ospi.o
obj-$(CONFIG_SPI_SPRD) += spi-sprd.o
obj-$(CONFIG_SPI_SPRD_ADI) += spi-sprd-adi.o
obj-$(CONFIG_SPI_STM32) += spi-stm32.o
......
......@@ -510,6 +510,39 @@ static int atmel_qspi_setup(struct spi_device *spi)
return 0;
}
static int atmel_qspi_set_cs_timing(struct spi_device *spi)
{
struct spi_controller *ctrl = spi->master;
struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
unsigned long clk_rate;
u32 cs_setup;
int delay;
int ret;
delay = spi_delay_to_ns(&spi->cs_setup, NULL);
if (delay <= 0)
return delay;
clk_rate = clk_get_rate(aq->pclk);
if (!clk_rate)
return -EINVAL;
cs_setup = DIV_ROUND_UP((delay * DIV_ROUND_UP(clk_rate, 1000000)),
1000);
ret = pm_runtime_resume_and_get(ctrl->dev.parent);
if (ret < 0)
return ret;
aq->scr |= QSPI_SCR_DLYBS(cs_setup);
atmel_qspi_write(aq->scr, aq, QSPI_SCR);
pm_runtime_mark_last_busy(ctrl->dev.parent);
pm_runtime_put_autosuspend(ctrl->dev.parent);
return 0;
}
static void atmel_qspi_init(struct atmel_qspi *aq)
{
/* Reset the QSPI controller */
......@@ -555,6 +588,7 @@ static int atmel_qspi_probe(struct platform_device *pdev)
ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD;
ctrl->setup = atmel_qspi_setup;
ctrl->set_cs_timing = atmel_qspi_set_cs_timing;
ctrl->bus_num = -1;
ctrl->mem_ops = &atmel_qspi_mem_ops;
ctrl->num_chipselect = 1;
......
......@@ -734,13 +734,11 @@ static int aspeed_spi_probe(struct platform_device *pdev)
aspi->data = data;
aspi->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
aspi->regs = devm_ioremap_resource(dev, res);
aspi->regs = devm_platform_ioremap_resource(pdev, 0);
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);
aspi->ahb_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
if (IS_ERR(aspi->ahb_base)) {
dev_err(dev, "missing AHB mapping window\n");
return PTR_ERR(aspi->ahb_base);
......
......@@ -1682,7 +1682,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
/* probe function to be called by SoC specific platform driver probe */
EXPORT_SYMBOL_GPL(bcm_qspi_probe);
int bcm_qspi_remove(struct platform_device *pdev)
void bcm_qspi_remove(struct platform_device *pdev)
{
struct bcm_qspi *qspi = platform_get_drvdata(pdev);
......@@ -1690,9 +1690,8 @@ int bcm_qspi_remove(struct platform_device *pdev)
bcm_qspi_hw_uninit(qspi);
clk_disable_unprepare(qspi->clk);
kfree(qspi->dev_ids);
return 0;
}
/* function to be called by SoC specific platform driver remove() */
EXPORT_SYMBOL_GPL(bcm_qspi_remove);
......
......@@ -96,7 +96,7 @@ static inline u32 get_qspi_mask(int type)
/* The common driver functions to be called by the SoC platform driver */
int bcm_qspi_probe(struct platform_device *pdev,
struct bcm_qspi_soc_intc *soc_intc);
int bcm_qspi_remove(struct platform_device *pdev);
void bcm_qspi_remove(struct platform_device *pdev);
/* pm_ops used by the SoC platform driver called on PM suspend/resume */
extern const struct dev_pm_ops bcm_qspi_pm_ops;
......
......@@ -547,8 +547,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, master);
bs->pdev = pdev;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bs->regs = devm_ioremap_resource(&pdev->dev, r);
bs->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
if (IS_ERR(bs->regs)) {
ret = PTR_ERR(bs->regs);
goto out_err;
......
......@@ -23,7 +23,9 @@ static int brcmstb_qspi_probe(struct platform_device *pdev)
static int brcmstb_qspi_remove(struct platform_device *pdev)
{
return bcm_qspi_remove(pdev);
bcm_qspi_remove(pdev);
return 0;
}
static struct platform_driver brcmstb_qspi_driver = {
......
......@@ -1119,6 +1119,14 @@ static void cqspi_config_baudrate_div(struct cqspi_st *cqspi)
/* Recalculate the baudrate divisor based on QSPI specification. */
div = DIV_ROUND_UP(ref_clk_hz, 2 * cqspi->sclk) - 1;
/* Maximum baud divisor */
if (div > CQSPI_REG_CONFIG_BAUD_MASK) {
div = CQSPI_REG_CONFIG_BAUD_MASK;
dev_warn(&cqspi->pdev->dev,
"Unable to adjust clock <= %d hz. Reduced to %d hz\n",
cqspi->sclk, ref_clk_hz/((div+1)*2));
}
reg = readl(reg_base + CQSPI_REG_CONFIG);
reg &= ~(CQSPI_REG_CONFIG_BAUD_MASK << CQSPI_REG_CONFIG_BAUD_LSB);
reg |= (div & CQSPI_REG_CONFIG_BAUD_MASK) << CQSPI_REG_CONFIG_BAUD_LSB;
......@@ -1580,7 +1588,6 @@ static int cqspi_probe(struct platform_device *pdev)
struct spi_master *master;
struct resource *res_ahb;
struct cqspi_st *cqspi;
struct resource *res;
int ret;
int irq;
......@@ -1616,8 +1623,7 @@ static int cqspi_probe(struct platform_device *pdev)
}
/* Obtain and remap controller address. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
cqspi->iobase = devm_ioremap_resource(dev, res);
cqspi->iobase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(cqspi->iobase)) {
dev_err(dev, "Cannot remap controller address.\n");
ret = PTR_ERR(cqspi->iobase);
......@@ -1625,8 +1631,7 @@ static int cqspi_probe(struct platform_device *pdev)
}
/* Obtain and remap AHB address. */
res_ahb = platform_get_resource(pdev, IORESOURCE_MEM, 1);
cqspi->ahb_base = devm_ioremap_resource(dev, res_ahb);
cqspi->ahb_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res_ahb);
if (IS_ERR(cqspi->ahb_base)) {
dev_err(dev, "Cannot remap AHB address.\n");
ret = PTR_ERR(cqspi->ahb_base);
......
......@@ -607,7 +607,6 @@ static int cdns_xspi_probe(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id cdns_xspi_of_match[] = {
{
.compatible = "cdns,xspi-nor",
......@@ -615,9 +614,6 @@ static const struct of_device_id cdns_xspi_of_match[] = {
{ /* end of table */}
};
MODULE_DEVICE_TABLE(of, cdns_xspi_of_match);
#else
#define cdns_xspi_of_match NULL
#endif /* CONFIG_OF */
static struct platform_driver cdns_xspi_platform_driver = {
.probe = cdns_xspi_probe,
......
......@@ -333,7 +333,7 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
goto err_bds;
}
mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
mspi->dma_dummy_tx = dma_map_single(dev, ZERO_PAGE(0), PAGE_SIZE,
DMA_TO_DEVICE);
if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
dev_err(dev, "unable to map dummy tx buffer\n");
......
......@@ -900,12 +900,31 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
static void dspi_assert_cs(struct spi_device *spi, bool *cs)
{
if (!spi->cs_gpiod || *cs)
return;
gpiod_set_value_cansleep(spi->cs_gpiod, true);
*cs = true;
}
static void dspi_deassert_cs(struct spi_device *spi, bool *cs)
{
if (!spi->cs_gpiod || !*cs)
return;
gpiod_set_value_cansleep(spi->cs_gpiod, false);
*cs = false;
}
static int dspi_transfer_one_message(struct spi_controller *ctlr,
struct spi_message *message)
{
struct fsl_dspi *dspi = spi_controller_get_devdata(ctlr);
struct spi_device *spi = message->spi;
struct spi_transfer *transfer;
bool cs = false;
int status = 0;
message->actual_length = 0;
......@@ -914,9 +933,14 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
dspi->cur_transfer = transfer;
dspi->cur_msg = message;
dspi->cur_chip = spi_get_ctldata(spi);
dspi_assert_cs(spi, &cs);
/* Prepare command word for CMD FIFO */
dspi->tx_cmd = SPI_PUSHR_CMD_CTAS(0) |
SPI_PUSHR_CMD_PCS(spi->chip_select);
dspi->tx_cmd = SPI_PUSHR_CMD_CTAS(0);
if (!spi->cs_gpiod)
dspi->tx_cmd |= SPI_PUSHR_CMD_PCS(spi->chip_select);
if (list_is_last(&dspi->cur_transfer->transfer_list,
&dspi->cur_msg->transfers)) {
/* Leave PCS activated after last transfer when
......@@ -964,6 +988,9 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
break;
spi_transfer_delay_exec(transfer);
if (!(dspi->tx_cmd & SPI_PUSHR_CMD_CONT))
dspi_deassert_cs(spi, &cs);
}
message->status = status;
......@@ -981,6 +1008,7 @@ static int dspi_setup(struct spi_device *spi)
unsigned char pasc = 0, asc = 0;
struct chip_data *chip;
unsigned long clkrate;
bool cs = true;
/* Only alloc on first setup */
chip = spi_get_ctldata(spi);
......@@ -1030,6 +1058,9 @@ static int dspi_setup(struct spi_device *spi)
chip->ctar_val |= SPI_CTAR_LSBFE;
}
gpiod_direction_output(spi->cs_gpiod, false);
dspi_deassert_cs(spi, &cs);
spi_set_ctldata(spi, chip);
return 0;
......@@ -1248,6 +1279,7 @@ static int dspi_probe(struct platform_device *pdev)
ctlr->cleanup = dspi_cleanup;
ctlr->slave_abort = dspi_slave_abort;
ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
ctlr->use_gpio_descriptors = true;
pdata = dev_get_platdata(&pdev->dev);
if (pdata) {
......
......@@ -98,6 +98,7 @@ struct fsl_lpspi_data {
struct clk *clk_ipg;
struct clk *clk_per;
bool is_slave;
u32 num_cs;
bool is_only_cs1;
bool is_first_byte;
......@@ -840,6 +841,9 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
fsl_lpspi->is_slave = is_slave;
fsl_lpspi->is_only_cs1 = of_property_read_bool((&pdev->dev)->of_node,
"fsl,spi-only-use-cs1-sel");
if (of_property_read_u32((&pdev->dev)->of_node, "num-cs",
&fsl_lpspi->num_cs))
fsl_lpspi->num_cs = 1;
controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32);
controller->transfer_one = fsl_lpspi_transfer_one;
......@@ -849,6 +853,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX;
controller->dev.of_node = pdev->dev.of_node;
controller->bus_num = pdev->id;
controller->num_chipselect = fsl_lpspi->num_cs;
controller->slave_abort = fsl_lpspi_slave_abort;
if (!fsl_lpspi->is_slave)
controller->use_gpio_descriptors = true;
......
......@@ -268,9 +268,19 @@ static int spi_gpio_set_direction(struct spi_device *spi, bool output)
if (output)
return gpiod_direction_output(spi_gpio->mosi, 1);
ret = gpiod_direction_input(spi_gpio->mosi);
if (ret)
return ret;
/*
* Only change MOSI to an input if using 3WIRE mode.
* Otherwise, MOSI could be left floating if there is
* no pull resistor connected to the I/O pin, or could
* be left logic high if there is a pull-up. Transmitting
* logic high when only clocking MISO data in can put some
* SPI devices in to a bad state.
*/
if (spi->mode & SPI_3WIRE) {
ret = gpiod_direction_input(spi_gpio->mosi);
if (ret)
return ret;
}
/*
* Send a turnaround high impedance cycle when switching
* from output to input. Theoretically there should be
......
......@@ -165,7 +165,7 @@ static int hisi_sfc_v3xx_adjust_op_size(struct spi_mem *mem,
}
/*
* The controller only supports Standard SPI mode, Duall mode and
* The controller only supports Standard SPI mode, Dual mode and
* Quad mode. Double sanitize the ops here to avoid OOB access.
*/
static bool hisi_sfc_v3xx_supports_op(struct spi_mem *mem,
......
......@@ -540,8 +540,7 @@ static int img_spfi_probe(struct platform_device *pdev)
spfi->master = master;
spin_lock_init(&spfi->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
spfi->regs = devm_ioremap_resource(spfi->dev, res);
spfi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(spfi->regs)) {
ret = PTR_ERR(spfi->regs);
goto put_spi;
......
......@@ -77,7 +77,6 @@ struct spi_imx_devtype_data {
void (*reset)(struct spi_imx_data *spi_imx);
void (*setup_wml)(struct spi_imx_data *spi_imx);
void (*disable)(struct spi_imx_data *spi_imx);
void (*disable_dma)(struct spi_imx_data *spi_imx);
bool has_dmamode;
bool has_slavemode;
unsigned int fifo_size;
......@@ -496,11 +495,6 @@ static void mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
}
static void mx51_disable_dma(struct spi_imx_data *spi_imx)
{
writel(0, spi_imx->base + MX51_ECSPI_DMA);
}
static void mx51_ecspi_disable(struct spi_imx_data *spi_imx)
{
u32 ctrl;
......@@ -1042,7 +1036,6 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
.rx_available = mx51_ecspi_rx_available,
.reset = mx51_ecspi_reset,
.setup_wml = mx51_setup_wml,
.disable_dma = mx51_disable_dma,
.fifo_size = 64,
.has_dmamode = true,
.dynamic_burst = true,
......@@ -1057,7 +1050,6 @@ static struct spi_imx_devtype_data imx53_ecspi_devtype_data = {
.prepare_transfer = mx51_ecspi_prepare_transfer,
.trigger = mx51_ecspi_trigger,
.rx_available = mx51_ecspi_rx_available,
.disable_dma = mx51_disable_dma,
.reset = mx51_ecspi_reset,
.fifo_size = 64,
.has_dmamode = true,
......
......@@ -33,6 +33,7 @@
#define HSFSTS_CTL_FCYCLE_WRITE (0x02 << HSFSTS_CTL_FCYCLE_SHIFT)
#define HSFSTS_CTL_FCYCLE_ERASE (0x03 << HSFSTS_CTL_FCYCLE_SHIFT)
#define HSFSTS_CTL_FCYCLE_ERASE_64K (0x04 << HSFSTS_CTL_FCYCLE_SHIFT)
#define HSFSTS_CTL_FCYCLE_RDSFDP (0x05 << HSFSTS_CTL_FCYCLE_SHIFT)
#define HSFSTS_CTL_FCYCLE_RDID (0x06 << HSFSTS_CTL_FCYCLE_SHIFT)
#define HSFSTS_CTL_FCYCLE_WRSR (0x07 << HSFSTS_CTL_FCYCLE_SHIFT)
#define HSFSTS_CTL_FCYCLE_RDSR (0x08 << HSFSTS_CTL_FCYCLE_SHIFT)
......@@ -352,34 +353,21 @@ static int intel_spi_opcode_index(struct intel_spi *ispi, u8 opcode, int optype)
return 0;
}
static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, size_t len)
static int intel_spi_hw_cycle(struct intel_spi *ispi,
const struct intel_spi_mem_op *iop, size_t len)
{
u32 val, status;
int ret;
val = readl(ispi->base + HSFSTS_CTL);
val &= ~(HSFSTS_CTL_FCYCLE_MASK | HSFSTS_CTL_FDBC_MASK);
switch (opcode) {
case SPINOR_OP_RDID:
val |= HSFSTS_CTL_FCYCLE_RDID;
break;
case SPINOR_OP_WRSR:
val |= HSFSTS_CTL_FCYCLE_WRSR;
break;
case SPINOR_OP_RDSR:
val |= HSFSTS_CTL_FCYCLE_RDSR;
break;
default:
return -EINVAL;
}
if (len > INTEL_SPI_FIFO_SZ)
if (!iop->replacement_op)
return -EINVAL;
val = readl(ispi->base + HSFSTS_CTL);
val &= ~(HSFSTS_CTL_FCYCLE_MASK | HSFSTS_CTL_FDBC_MASK);
val |= (len - 1) << HSFSTS_CTL_FDBC_SHIFT;
val |= HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
val |= HSFSTS_CTL_FGO;
val |= iop->replacement_op;
writel(val, ispi->base + HSFSTS_CTL);
ret = intel_spi_wait_hw_busy(ispi);
......@@ -406,9 +394,6 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len,
if (ret < 0)
return ret;
if (len > INTEL_SPI_FIFO_SZ)
return -EINVAL;
/*
* Always clear it after each SW sequencer operation regardless
* of whether it is successful or not.
......@@ -473,17 +458,18 @@ 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)
{
u32 addr = intel_spi_chip_addr(ispi, mem) + op->addr.val;
size_t nbytes = op->data.nbytes;
u8 opcode = op->cmd.opcode;
int ret;
writel(intel_spi_chip_addr(ispi, mem), ispi->base + FADDR);
writel(addr, ispi->base + FADDR);
if (ispi->swseq_reg)
ret = intel_spi_sw_cycle(ispi, opcode, nbytes,
OPTYPE_READ_NO_ADDR);
else
ret = intel_spi_hw_cycle(ispi, opcode, nbytes);
ret = intel_spi_hw_cycle(ispi, iop, nbytes);
if (ret)
return ret;
......@@ -495,6 +481,7 @@ 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)
{
u32 addr = intel_spi_chip_addr(ispi, mem) + op->addr.val;
size_t nbytes = op->data.nbytes;
u8 opcode = op->cmd.opcode;
int ret;
......@@ -538,7 +525,7 @@ static int intel_spi_write_reg(struct intel_spi *ispi, const struct spi_mem *mem
if (opcode == SPINOR_OP_WRDI)
return 0;
writel(intel_spi_chip_addr(ispi, mem), ispi->base + FADDR);
writel(addr, ispi->base + FADDR);
/* Write the value beforehand */
ret = intel_spi_write_block(ispi, op->data.buf.out, nbytes);
......@@ -548,7 +535,7 @@ static int intel_spi_write_reg(struct intel_spi *ispi, const struct spi_mem *mem
if (ispi->swseq_reg)
return intel_spi_sw_cycle(ispi, opcode, nbytes,
OPTYPE_WRITE_NO_ADDR);
return intel_spi_hw_cycle(ispi, opcode, nbytes);
return intel_spi_hw_cycle(ispi, iop, nbytes);
}
static int intel_spi_read(struct intel_spi *ispi, const struct spi_mem *mem,
......@@ -713,6 +700,12 @@ static int intel_spi_erase(struct intel_spi *ispi, const struct spi_mem *mem,
return 0;
}
static int intel_spi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
{
op->data.nbytes = clamp_val(op->data.nbytes, 0, INTEL_SPI_FIFO_SZ);
return 0;
}
static bool intel_spi_cmp_mem_op(const struct intel_spi_mem_op *iop,
const struct spi_mem_op *op)
{
......@@ -853,6 +846,7 @@ static ssize_t intel_spi_dirmap_write(struct spi_mem_dirmap_desc *desc, u64 offs
}
static const struct spi_controller_mem_ops intel_spi_mem_ops = {
.adjust_op_size = intel_spi_adjust_op_size,
.supports_op = intel_spi_supports_mem_op,
.exec_op = intel_spi_exec_mem_op,
.get_name = intel_spi_get_name,
......@@ -912,18 +906,26 @@ static const struct spi_controller_mem_ops intel_spi_mem_ops = {
*/
#define INTEL_SPI_GENERIC_OPS \
/* Status register operations */ \
INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1), \
SPI_MEM_OP_NO_ADDR, \
INTEL_SPI_OP_DATA_IN(1), \
intel_spi_read_reg), \
INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 1), \
SPI_MEM_OP_NO_ADDR, \
INTEL_SPI_OP_DATA_IN(1), \
intel_spi_read_reg), \
INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1), \
SPI_MEM_OP_NO_ADDR, \
INTEL_SPI_OP_DATA_OUT(1), \
intel_spi_write_reg), \
INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1), \
SPI_MEM_OP_NO_ADDR, \
INTEL_SPI_OP_DATA_IN(1), \
intel_spi_read_reg, \
HSFSTS_CTL_FCYCLE_RDID), \
INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 1), \
SPI_MEM_OP_NO_ADDR, \
INTEL_SPI_OP_DATA_IN(1), \
intel_spi_read_reg, \
HSFSTS_CTL_FCYCLE_RDSR), \
INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1), \
SPI_MEM_OP_NO_ADDR, \
INTEL_SPI_OP_DATA_OUT(1), \
intel_spi_write_reg, \
HSFSTS_CTL_FCYCLE_WRSR), \
INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_RDSFDP, 1), \
INTEL_SPI_OP_ADDR(3), \
INTEL_SPI_OP_DATA_IN(1), \
intel_spi_read_reg, \
HSFSTS_CTL_FCYCLE_RDSFDP), \
/* Normal read */ \
INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1), \
INTEL_SPI_OP_ADDR(3), \
......
......@@ -129,7 +129,9 @@ static int bcm_iproc_probe(struct platform_device *pdev)
static int bcm_iproc_remove(struct platform_device *pdev)
{
return bcm_qspi_remove(pdev);
bcm_qspi_remove(pdev);
return 0;
}
static const struct of_device_id bcm_iproc_of_match[] = {
......
......@@ -21,6 +21,7 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/reset.h>
#include <linux/pinctrl/consumer.h>
/*
* The Meson SPICC controller could support DMA based transfers, but is not
......@@ -168,6 +169,9 @@ struct meson_spicc_device {
unsigned long tx_remain;
unsigned long rx_remain;
unsigned long xfer_remain;
struct pinctrl *pinctrl;
struct pinctrl_state *pins_idle_high;
struct pinctrl_state *pins_idle_low;
};
#define pow2_clk_to_spicc(_div) container_of(_div, struct meson_spicc_device, pow2_div)
......@@ -176,8 +180,22 @@ static void meson_spicc_oen_enable(struct meson_spicc_device *spicc)
{
u32 conf;
if (!spicc->data->has_oen)
if (!spicc->data->has_oen) {
/* Try to get pinctrl states for idle high/low */
spicc->pins_idle_high = pinctrl_lookup_state(spicc->pinctrl,
"idle-high");
if (IS_ERR(spicc->pins_idle_high)) {
dev_warn(&spicc->pdev->dev, "can't get idle-high pinctrl\n");
spicc->pins_idle_high = NULL;
}
spicc->pins_idle_low = pinctrl_lookup_state(spicc->pinctrl,
"idle-low");
if (IS_ERR(spicc->pins_idle_low)) {
dev_warn(&spicc->pdev->dev, "can't get idle-low pinctrl\n");
spicc->pins_idle_low = NULL;
}
return;
}
conf = readl_relaxed(spicc->base + SPICC_ENH_CTL0) |
SPICC_ENH_MOSI_OEN | SPICC_ENH_CLK_OEN | SPICC_ENH_CS_OEN;
......@@ -459,6 +477,16 @@ static int meson_spicc_prepare_message(struct spi_master *master,
else
conf &= ~SPICC_POL;
if (!spicc->data->has_oen) {
if (spi->mode & SPI_CPOL) {
if (spicc->pins_idle_high)
pinctrl_select_state(spicc->pinctrl, spicc->pins_idle_high);
} else {
if (spicc->pins_idle_low)
pinctrl_select_state(spicc->pinctrl, spicc->pins_idle_low);
}
}
if (spi->mode & SPI_CPHA)
conf |= SPICC_PHA;
else
......@@ -505,6 +533,9 @@ static int meson_spicc_unprepare_transfer(struct spi_master *master)
/* Set default configuration, keeping datarate field */
writel_relaxed(conf, spicc->base + SPICC_CONREG);
if (!spicc->data->has_oen)
pinctrl_select_default_state(&spicc->pdev->dev);
return 0;
}
......@@ -818,6 +849,12 @@ static int meson_spicc_probe(struct platform_device *pdev)
goto out_core_clk;
}
spicc->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(spicc->pinctrl)) {
ret = PTR_ERR(spicc->pinctrl);
goto out_clk;
}
device_reset_optional(&pdev->dev);
master->num_chipselect = 4;
......
......@@ -119,15 +119,6 @@ static inline void mchp_corespi_write(struct mchp_corespi *spi, unsigned int reg
writel(val, spi->regs + reg);
}
static inline void mchp_corespi_enable(struct mchp_corespi *spi)
{
u32 control = mchp_corespi_read(spi, REG_CONTROL);
control |= CONTROL_ENABLE;
mchp_corespi_write(spi, REG_CONTROL, control);
}
static inline void mchp_corespi_disable(struct mchp_corespi *spi)
{
u32 control = mchp_corespi_read(spi, REG_CONTROL);
......
......@@ -1192,11 +1192,6 @@ static int mtk_spi_probe(struct platform_device *pdev)
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)
return dev_err_probe(dev, ret, "failed to register irq\n");
mdata->parent_clk = devm_clk_get(dev, "parent-clk");
if (IS_ERR(mdata->parent_clk))
return dev_err_probe(dev, PTR_ERR(mdata->parent_clk),
......@@ -1266,6 +1261,13 @@ static int mtk_spi_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret, "failed to register master\n");
}
ret = devm_request_irq(dev, irq, mtk_spi_interrupt,
IRQF_TRIGGER_NONE, dev_name(dev), master);
if (ret) {
pm_runtime_disable(dev);
return dev_err_probe(dev, ret, "failed to register irq\n");
}
return 0;
}
......
......@@ -80,6 +80,9 @@
#define MTK_NOR_REG_DMA_FADR 0x71c
#define MTK_NOR_REG_DMA_DADR 0x720
#define MTK_NOR_REG_DMA_END_DADR 0x724
#define MTK_NOR_REG_CG_DIS 0x728
#define MTK_NOR_SFC_SW_RST BIT(2)
#define MTK_NOR_REG_DMA_DADR_HB 0x738
#define MTK_NOR_REG_DMA_END_DADR_HB 0x73c
......@@ -147,6 +150,15 @@ static inline int mtk_nor_cmd_exec(struct mtk_nor *sp, u32 cmd, ulong clk)
return ret;
}
static void mtk_nor_reset(struct mtk_nor *sp)
{
mtk_nor_rmw(sp, MTK_NOR_REG_CG_DIS, 0, MTK_NOR_SFC_SW_RST);
mb(); /* flush previous writes */
mtk_nor_rmw(sp, MTK_NOR_REG_CG_DIS, MTK_NOR_SFC_SW_RST, 0);
mb(); /* flush previous writes */
writel(MTK_NOR_ENABLE_SF_CMD, sp->base + MTK_NOR_REG_WP);
}
static void mtk_nor_set_addr(struct mtk_nor *sp, const struct spi_mem_op *op)
{
u32 addr = op->addr.val;
......@@ -354,7 +366,7 @@ static int mtk_nor_dma_exec(struct mtk_nor *sp, u32 from, unsigned int length,
dma_addr_t dma_addr)
{
int ret = 0;
ulong delay;
u32 delay, timeout;
u32 reg;
writel(from, sp->base + MTK_NOR_REG_DMA_FADR);
......@@ -376,15 +388,16 @@ static int mtk_nor_dma_exec(struct mtk_nor *sp, u32 from, unsigned int length,
mtk_nor_rmw(sp, MTK_NOR_REG_DMA_CTL, MTK_NOR_DMA_START, 0);
delay = CLK_TO_US(sp, (length + 5) * BITS_PER_BYTE);
timeout = (delay + 1) * 100;
if (sp->has_irq) {
if (!wait_for_completion_timeout(&sp->op_done,
(delay + 1) * 100))
usecs_to_jiffies(max(timeout, 10000U))))
ret = -ETIMEDOUT;
} else {
ret = readl_poll_timeout(sp->base + MTK_NOR_REG_DMA_CTL, reg,
!(reg & MTK_NOR_DMA_START), delay / 3,
(delay + 1) * 100);
timeout);
}
if (ret < 0)
......@@ -443,36 +456,28 @@ static int mtk_nor_read_pio(struct mtk_nor *sp, const struct spi_mem_op *op)
return ret;
}
static int mtk_nor_write_buffer_enable(struct mtk_nor *sp)
static int mtk_nor_setup_write_buffer(struct mtk_nor *sp, bool on)
{
int ret;
u32 val;
if (sp->wbuf_en)
if (!(sp->wbuf_en ^ on))
return 0;
val = readl(sp->base + MTK_NOR_REG_CFG2);
writel(val | MTK_NOR_WR_BUF_EN, sp->base + MTK_NOR_REG_CFG2);
ret = readl_poll_timeout(sp->base + MTK_NOR_REG_CFG2, val,
val & MTK_NOR_WR_BUF_EN, 0, 10000);
if (!ret)
sp->wbuf_en = true;
return ret;
}
static int mtk_nor_write_buffer_disable(struct mtk_nor *sp)
{
int ret;
u32 val;
if (on) {
writel(val | MTK_NOR_WR_BUF_EN, sp->base + MTK_NOR_REG_CFG2);
ret = readl_poll_timeout(sp->base + MTK_NOR_REG_CFG2, val,
val & MTK_NOR_WR_BUF_EN, 0, 10000);
} else {
writel(val & ~MTK_NOR_WR_BUF_EN, sp->base + MTK_NOR_REG_CFG2);
ret = readl_poll_timeout(sp->base + MTK_NOR_REG_CFG2, val,
!(val & MTK_NOR_WR_BUF_EN), 0, 10000);
}
if (!sp->wbuf_en)
return 0;
val = readl(sp->base + MTK_NOR_REG_CFG2);
writel(val & ~MTK_NOR_WR_BUF_EN, sp->base + MTK_NOR_REG_CFG2);
ret = readl_poll_timeout(sp->base + MTK_NOR_REG_CFG2, val,
!(val & MTK_NOR_WR_BUF_EN), 0, 10000);
if (!ret)
sp->wbuf_en = false;
sp->wbuf_en = on;
return ret;
}
......@@ -482,7 +487,7 @@ static int mtk_nor_pp_buffered(struct mtk_nor *sp, const struct spi_mem_op *op)
u32 val;
int ret, i;
ret = mtk_nor_write_buffer_enable(sp);
ret = mtk_nor_setup_write_buffer(sp, true);
if (ret < 0)
return ret;
......@@ -501,7 +506,7 @@ static int mtk_nor_pp_unbuffered(struct mtk_nor *sp,
const u8 *buf = op->data.buf.out;
int ret;
ret = mtk_nor_write_buffer_disable(sp);
ret = mtk_nor_setup_write_buffer(sp, false);
if (ret < 0)
return ret;
writeb(buf[0], sp->base + MTK_NOR_REG_WDATA);
......@@ -608,7 +613,7 @@ static int mtk_nor_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
}
if ((op->data.dir == SPI_MEM_DATA_IN) && mtk_nor_match_read(op)) {
ret = mtk_nor_write_buffer_disable(sp);
ret = mtk_nor_setup_write_buffer(sp, false);
if (ret < 0)
return ret;
mtk_nor_setup_bus(sp, op);
......@@ -616,7 +621,15 @@ static int mtk_nor_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
mtk_nor_set_addr(sp, op);
return mtk_nor_read_pio(sp, op);
} else {
return mtk_nor_read_dma(sp, op);
ret = mtk_nor_read_dma(sp, op);
if (unlikely(ret)) {
/* Handle rare bus glitch */
mtk_nor_reset(sp);
mtk_nor_setup_bus(sp, op);
return mtk_nor_read_dma(sp, op);
}
return ret;
}
}
......
......@@ -126,7 +126,8 @@
#define STR_DATA BIT(0)
#define NFI_STA 0x060
#define NFI_NAND_FSM GENMASK(28, 24)
#define NFI_NAND_FSM_7622 GENMASK(28, 24)
#define NFI_NAND_FSM_7986 GENMASK(29, 23)
#define NFI_FSM GENMASK(19, 16)
#define READ_EMPTY BIT(12)
......@@ -158,6 +159,7 @@
#define MAS_WR GENMASK(5, 3)
#define MAS_RDDLY GENMASK(2, 0)
#define NFI_MASTERSTA_MASK_7622 (MAS_ADDR | MAS_RD | MAS_WR | MAS_RDDLY)
#define NFI_MASTERSTA_MASK_7986 3
// SNFI registers
#define SNF_MAC_CTL 0x500
......@@ -220,6 +222,11 @@
static const u8 mt7622_spare_sizes[] = { 16, 26, 27, 28 };
static const u8 mt7986_spare_sizes[] = {
16, 26, 27, 28, 32, 36, 40, 44, 48, 49, 50, 51, 52, 62, 61, 63, 64, 67,
74
};
struct mtk_snand_caps {
u16 sector_size;
u16 max_sectors;
......@@ -230,6 +237,7 @@ struct mtk_snand_caps {
bool bbm_swap;
bool empty_page_check;
u32 mastersta_mask;
u32 nandfsm_mask;
const u8 *spare_sizes;
u32 num_spare_size;
......@@ -244,6 +252,7 @@ static const struct mtk_snand_caps mt7622_snand_caps = {
.bbm_swap = false,
.empty_page_check = false,
.mastersta_mask = NFI_MASTERSTA_MASK_7622,
.nandfsm_mask = NFI_NAND_FSM_7622,
.spare_sizes = mt7622_spare_sizes,
.num_spare_size = ARRAY_SIZE(mt7622_spare_sizes)
};
......@@ -257,10 +266,25 @@ static const struct mtk_snand_caps mt7629_snand_caps = {
.bbm_swap = true,
.empty_page_check = false,
.mastersta_mask = NFI_MASTERSTA_MASK_7622,
.nandfsm_mask = NFI_NAND_FSM_7622,
.spare_sizes = mt7622_spare_sizes,
.num_spare_size = ARRAY_SIZE(mt7622_spare_sizes)
};
static const struct mtk_snand_caps mt7986_snand_caps = {
.sector_size = 1024,
.max_sectors = 8,
.fdm_size = 8,
.fdm_ecc_size = 1,
.fifo_size = 64,
.bbm_swap = true,
.empty_page_check = true,
.mastersta_mask = NFI_MASTERSTA_MASK_7986,
.nandfsm_mask = NFI_NAND_FSM_7986,
.spare_sizes = mt7986_spare_sizes,
.num_spare_size = ARRAY_SIZE(mt7986_spare_sizes)
};
struct mtk_snand_conf {
size_t page_size;
size_t oob_size;
......@@ -360,7 +384,7 @@ static int mtk_nfi_reset(struct mtk_snand *snf)
}
ret = readl_poll_timeout(snf->nfi_base + NFI_STA, val,
!(val & (NFI_FSM | NFI_NAND_FSM)), 0,
!(val & (NFI_FSM | snf->caps->nandfsm_mask)), 0,
SNFI_POLL_INTERVAL);
if (ret) {
dev_err(snf->dev, "Failed to reset NFI\n");
......@@ -1295,6 +1319,7 @@ static irqreturn_t mtk_snand_irq(int irq, void *id)
static const struct of_device_id mtk_snand_ids[] = {
{ .compatible = "mediatek,mt7622-snand", .data = &mt7622_snand_caps },
{ .compatible = "mediatek,mt7629-snand", .data = &mt7629_snand_caps },
{ .compatible = "mediatek,mt7986-snand", .data = &mt7986_snand_caps },
{},
};
......
......@@ -772,8 +772,7 @@ static int mxic_spi_probe(struct platform_device *pdev)
if (IS_ERR(mxic->send_dly_clk))
return PTR_ERR(mxic->send_dly_clk);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
mxic->regs = devm_ioremap_resource(&pdev->dev, res);
mxic->regs = devm_platform_ioremap_resource_byname(pdev, "regs");
if (IS_ERR(mxic->regs))
return PTR_ERR(mxic->regs);
......
......@@ -699,7 +699,6 @@ static int npcm_fiu_probe(struct platform_device *pdev)
struct spi_controller *ctrl;
struct npcm_fiu_spi *fiu;
void __iomem *regbase;
struct resource *res;
int id, ret;
ctrl = devm_spi_alloc_master(dev, sizeof(*fiu));
......@@ -725,8 +724,7 @@ static int npcm_fiu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, fiu);
fiu->dev = dev;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control");
regbase = devm_ioremap_resource(dev, res);
regbase = devm_platform_ioremap_resource_byname(pdev, "control");
if (IS_ERR(regbase))
return PTR_ERR(regbase);
......
......@@ -924,7 +924,7 @@ static int nxp_fspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
static void erratum_err050568(struct nxp_fspi *f)
{
const struct soc_device_attribute ls1028a_soc_attr[] = {
static const struct soc_device_attribute ls1028a_soc_attr[] = {
{ .family = "QorIQ LS1028A" },
{ /* sentinel */ }
};
......
This diff is collapsed.
......@@ -20,7 +20,6 @@
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
......@@ -1322,134 +1321,11 @@ static void cleanup(struct spi_device *spi)
kfree(chip);
}
#ifdef CONFIG_ACPI
static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
{ "INT33C0", LPSS_LPT_SSP },
{ "INT33C1", LPSS_LPT_SSP },
{ "INT3430", LPSS_LPT_SSP },
{ "INT3431", LPSS_LPT_SSP },
{ "80860F0E", LPSS_BYT_SSP },
{ "8086228E", LPSS_BSW_SSP },
{ },
};
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
#endif
/*
* PCI IDs of compound devices that integrate both host controller and private
* integrated DMA engine. Please note these are not used in module
* autoloading and probing in this module but matching the LPSS SSP type.
*/
static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
/* SPT-LP */
{ PCI_VDEVICE(INTEL, 0x9d29), LPSS_SPT_SSP },
{ PCI_VDEVICE(INTEL, 0x9d2a), LPSS_SPT_SSP },
/* SPT-H */
{ PCI_VDEVICE(INTEL, 0xa129), LPSS_SPT_SSP },
{ PCI_VDEVICE(INTEL, 0xa12a), LPSS_SPT_SSP },
/* KBL-H */
{ PCI_VDEVICE(INTEL, 0xa2a9), LPSS_SPT_SSP },
{ PCI_VDEVICE(INTEL, 0xa2aa), LPSS_SPT_SSP },
/* CML-V */
{ PCI_VDEVICE(INTEL, 0xa3a9), LPSS_SPT_SSP },
{ PCI_VDEVICE(INTEL, 0xa3aa), LPSS_SPT_SSP },
/* BXT A-Step */
{ PCI_VDEVICE(INTEL, 0x0ac2), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x0ac4), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x0ac6), LPSS_BXT_SSP },
/* BXT B-Step */
{ PCI_VDEVICE(INTEL, 0x1ac2), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x1ac4), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x1ac6), LPSS_BXT_SSP },
/* GLK */
{ PCI_VDEVICE(INTEL, 0x31c2), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x31c4), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x31c6), LPSS_BXT_SSP },
/* ICL-LP */
{ PCI_VDEVICE(INTEL, 0x34aa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x34ab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x34fb), LPSS_CNL_SSP },
/* EHL */
{ PCI_VDEVICE(INTEL, 0x4b2a), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x4b2b), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x4b37), LPSS_BXT_SSP },
/* JSL */
{ PCI_VDEVICE(INTEL, 0x4daa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x4dab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x4dfb), LPSS_CNL_SSP },
/* TGL-H */
{ PCI_VDEVICE(INTEL, 0x43aa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x43ab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x43fb), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x43fd), LPSS_CNL_SSP },
/* ADL-P */
{ PCI_VDEVICE(INTEL, 0x51aa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x51ab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x51fb), LPSS_CNL_SSP },
/* ADL-M */
{ PCI_VDEVICE(INTEL, 0x54aa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x54ab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x54fb), LPSS_CNL_SSP },
/* APL */
{ PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP },
{ PCI_VDEVICE(INTEL, 0x5ac6), LPSS_BXT_SSP },
/* RPL-S */
{ PCI_VDEVICE(INTEL, 0x7a2a), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x7a2b), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x7a79), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x7a7b), LPSS_CNL_SSP },
/* ADL-S */
{ PCI_VDEVICE(INTEL, 0x7aaa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x7aab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x7af9), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x7afb), LPSS_CNL_SSP },
/* MTL-P */
{ PCI_VDEVICE(INTEL, 0x7e27), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x7e30), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x7e46), LPSS_CNL_SSP },
/* CNL-LP */
{ PCI_VDEVICE(INTEL, 0x9daa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x9dab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x9dfb), LPSS_CNL_SSP },
/* CNL-H */
{ PCI_VDEVICE(INTEL, 0xa32a), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0xa32b), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0xa37b), LPSS_CNL_SSP },
/* CML-LP */
{ PCI_VDEVICE(INTEL, 0x02aa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x02ab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x02fb), LPSS_CNL_SSP },
/* CML-H */
{ PCI_VDEVICE(INTEL, 0x06aa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x06ab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0x06fb), LPSS_CNL_SSP },
/* TGL-LP */
{ PCI_VDEVICE(INTEL, 0xa0aa), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0xa0ab), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0xa0de), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0xa0df), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0xa0fb), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0xa0fd), LPSS_CNL_SSP },
{ PCI_VDEVICE(INTEL, 0xa0fe), LPSS_CNL_SSP },
{ },
};
static const struct of_device_id pxa2xx_spi_of_match[] = {
{ .compatible = "marvell,mmp2-ssp", .data = (void *)MMP2_SSP },
{},
};
MODULE_DEVICE_TABLE(of, pxa2xx_spi_of_match);
#ifdef CONFIG_PCI
static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
{
return param == chan->device->dev;
}
#endif /* CONFIG_PCI */
static struct pxa2xx_spi_controller *
pxa2xx_spi_init_pdata(struct platform_device *pdev)
{
......@@ -1458,46 +1334,51 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev)
struct device *parent = dev->parent;
struct ssp_device *ssp;
struct resource *res;
struct pci_dev *pcidev = dev_is_pci(parent) ? to_pci_dev(parent) : NULL;
const struct pci_device_id *pcidev_id = NULL;
enum pxa_ssp_type type;
enum pxa_ssp_type type = SSP_UNDEFINED;
const void *match;
bool is_lpss_priv;
int status;
u64 uid;
if (pcidev)
pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match, pcidev);
is_lpss_priv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpss_priv");
match = device_get_match_data(&pdev->dev);
match = device_get_match_data(dev);
if (match)
type = (enum pxa_ssp_type)match;
else if (pcidev_id)
type = (enum pxa_ssp_type)pcidev_id->driver_data;
else
else if (is_lpss_priv) {
u32 value;
status = device_property_read_u32(dev, "intel,spi-pxa2xx-type", &value);
if (status)
return ERR_PTR(status);
type = (enum pxa_ssp_type)value;
}
/* Validate the SSP type correctness */
if (!(type > SSP_UNDEFINED && type < SSP_MAX))
return ERR_PTR(-EINVAL);
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
ssp = &pdata->ssp;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ssp->mmio_base = devm_ioremap_resource(&pdev->dev, res);
ssp->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(ssp->mmio_base))
return ERR_CAST(ssp->mmio_base);
ssp->phys_base = res->start;
#ifdef CONFIG_PCI
if (pcidev_id) {
/* Platforms with iDMA 64-bit */
if (is_lpss_priv) {
pdata->tx_param = parent;
pdata->rx_param = parent;
pdata->dma_filter = pxa2xx_spi_idma_filter;
}
#endif
ssp->clk = devm_clk_get(&pdev->dev, NULL);
ssp->clk = devm_clk_get(dev, NULL);
if (IS_ERR(ssp->clk))
return ERR_CAST(ssp->clk);
......@@ -1506,7 +1387,7 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev)
return ERR_PTR(ssp->irq);
ssp->type = type;
ssp->dev = &pdev->dev;
ssp->dev = dev;
status = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &uid);
if (status)
......@@ -1514,7 +1395,7 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev)
else
ssp->port_id = uid;
pdata->is_slave = device_property_read_bool(&pdev->dev, "spi-slave");
pdata->is_slave = device_property_read_bool(dev, "spi-slave");
pdata->num_chipselect = 1;
pdata->enable_dma = true;
pdata->dma_burst_size = 1;
......@@ -1807,7 +1688,6 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int pxa2xx_spi_suspend(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);
......@@ -1842,9 +1722,7 @@ static int pxa2xx_spi_resume(struct device *dev)
/* Start the queue running */
return spi_controller_resume(drv_data->controller);
}
#endif
#ifdef CONFIG_PM
static int pxa2xx_spi_runtime_suspend(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);
......@@ -1859,18 +1737,35 @@ static int pxa2xx_spi_runtime_resume(struct device *dev)
return clk_prepare_enable(drv_data->ssp->clk);
}
#endif
static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pxa2xx_spi_suspend, pxa2xx_spi_resume)
SET_RUNTIME_PM_OPS(pxa2xx_spi_runtime_suspend,
pxa2xx_spi_runtime_resume, NULL)
SYSTEM_SLEEP_PM_OPS(pxa2xx_spi_suspend, pxa2xx_spi_resume)
RUNTIME_PM_OPS(pxa2xx_spi_runtime_suspend, pxa2xx_spi_runtime_resume, NULL)
};
#ifdef CONFIG_ACPI
static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
{ "80860F0E", LPSS_BYT_SSP },
{ "8086228E", LPSS_BSW_SSP },
{ "INT33C0", LPSS_LPT_SSP },
{ "INT33C1", LPSS_LPT_SSP },
{ "INT3430", LPSS_LPT_SSP },
{ "INT3431", LPSS_LPT_SSP },
{}
};
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
#endif
static const struct of_device_id pxa2xx_spi_of_match[] = {
{ .compatible = "marvell,mmp2-ssp", .data = (void *)MMP2_SSP },
{}
};
MODULE_DEVICE_TABLE(of, pxa2xx_spi_of_match);
static struct platform_driver driver = {
.driver = {
.name = "pxa2xx-spi",
.pm = &pxa2xx_spi_pm_ops,
.pm = pm_ptr(&pxa2xx_spi_pm_ops),
.acpi_match_table = ACPI_PTR(pxa2xx_spi_acpi_match),
.of_match_table = of_match_ptr(pxa2xx_spi_of_match),
},
......
......@@ -235,9 +235,9 @@ static int sc18is602_setup(struct spi_device *spi)
return 0;
}
static int sc18is602_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int sc18is602_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct device *dev = &client->dev;
struct device_node *np = dev->of_node;
struct sc18is602_platform_data *pdata = dev_get_platdata(dev);
......@@ -337,7 +337,7 @@ static struct i2c_driver sc18is602_driver = {
.name = "sc18is602",
.of_match_table = of_match_ptr(sc18is602_of_match),
},
.probe = sc18is602_probe,
.probe_new = sc18is602_probe,
.id_table = sc18is602_id,
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -202,8 +202,7 @@ static int spi_xcomm_transfer_one(struct spi_master *master,
return status;
}
static int spi_xcomm_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
static int spi_xcomm_probe(struct i2c_client *i2c)
{
struct spi_xcomm *spi_xcomm;
struct spi_master *master;
......@@ -242,7 +241,7 @@ static struct i2c_driver spi_xcomm_driver = {
.name = "spi-xcomm",
},
.id_table = spi_xcomm_ids,
.probe = spi_xcomm_probe,
.probe_new = spi_xcomm_probe,
};
module_i2c_driver(spi_xcomm_driver);
......
This diff is collapsed.
......@@ -127,10 +127,10 @@ do { \
unsigned int start; \
pcpu_stats = per_cpu_ptr(in, i); \
do { \
start = u64_stats_fetch_begin_irq( \
start = u64_stats_fetch_begin( \
&pcpu_stats->syncp); \
inc = u64_stats_read(&pcpu_stats->field); \
} while (u64_stats_fetch_retry_irq( \
} while (u64_stats_fetch_retry( \
&pcpu_stats->syncp, start)); \
ret += inc; \
} \
......@@ -360,6 +360,18 @@ const struct spi_device_id *spi_get_device_id(const struct spi_device *sdev)
}
EXPORT_SYMBOL_GPL(spi_get_device_id);
const void *spi_get_device_match_data(const struct spi_device *sdev)
{
const void *match;
match = device_get_match_data(&sdev->dev);
if (match)
return match;
return (const void *)spi_get_device_id(sdev)->driver_data;
}
EXPORT_SYMBOL_GPL(spi_get_device_match_data);
static int spi_match_device(struct device *dev, struct device_driver *drv)
{
const struct spi_device *spi = to_spi_device(dev);
......@@ -2212,6 +2224,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
struct device_node *nc)
{
u32 value;
u16 cs_setup;
int rc;
/* Mode (clock phase/polarity/etc.) */
......@@ -2297,6 +2310,11 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
if (!of_property_read_u32(nc, "spi-max-frequency", &value))
spi->max_speed_hz = value;
if (!of_property_read_u16(nc, "spi-cs-setup-ns", &cs_setup)) {
spi->cs_setup.value = cs_setup;
spi->cs_setup.unit = SPI_DELAY_UNIT_NSECS;
}
return 0;
}
......@@ -2759,6 +2777,17 @@ int spi_slave_abort(struct spi_device *spi)
}
EXPORT_SYMBOL_GPL(spi_slave_abort);
int spi_target_abort(struct spi_device *spi)
{
struct spi_controller *ctlr = spi->controller;
if (spi_controller_is_target(ctlr) && ctlr->target_abort)
return ctlr->target_abort(ctlr);
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(spi_target_abort);
static ssize_t slave_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
......@@ -3592,6 +3621,37 @@ static int __spi_validate_bits_per_word(struct spi_controller *ctlr,
return 0;
}
/**
* spi_set_cs_timing - configure CS setup, hold, and inactive delays
* @spi: the device that requires specific CS timing configuration
*
* Return: zero on success, else a negative error code.
*/
static int spi_set_cs_timing(struct spi_device *spi)
{
struct device *parent = spi->controller->dev.parent;
int status = 0;
if (spi->controller->set_cs_timing && !spi->cs_gpiod) {
if (spi->controller->auto_runtime_pm) {
status = pm_runtime_get_sync(parent);
if (status < 0) {
pm_runtime_put_noidle(parent);
dev_err(&spi->controller->dev, "Failed to power device: %d\n",
status);
return status;
}
status = spi->controller->set_cs_timing(spi);
pm_runtime_mark_last_busy(parent);
pm_runtime_put_autosuspend(parent);
} else {
status = spi->controller->set_cs_timing(spi);
}
}
return status;
}
/**
* spi_setup - setup SPI mode and clock rate
* @spi: the device whose settings are being modified
......@@ -3688,6 +3748,12 @@ int spi_setup(struct spi_device *spi)
}
}
status = spi_set_cs_timing(spi);
if (status) {
mutex_unlock(&spi->controller->io_mutex);
return status;
}
if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
status = pm_runtime_resume_and_get(spi->controller->dev.parent);
if (status < 0) {
......
......@@ -377,12 +377,23 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
switch (cmd) {
/* read requests */
case SPI_IOC_RD_MODE:
retval = put_user(spi->mode & SPI_MODE_MASK,
(__u8 __user *)arg);
break;
case SPI_IOC_RD_MODE32:
retval = put_user(spi->mode & SPI_MODE_MASK,
(__u32 __user *)arg);
tmp = spi->mode;
{
struct spi_controller *ctlr = spi->controller;
if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods &&
ctlr->cs_gpiods[spi->chip_select])
tmp &= ~SPI_CS_HIGH;
}
if (cmd == SPI_IOC_RD_MODE)
retval = put_user(tmp & SPI_MODE_MASK,
(__u8 __user *)arg);
else
retval = put_user(tmp & SPI_MODE_MASK,
(__u32 __user *)arg);
break;
case SPI_IOC_RD_LSB_FIRST:
retval = put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0,
......
......@@ -135,6 +135,7 @@ enum pm_ret_status {
};
enum pm_ioctl_id {
IOCTL_SET_TAPDELAY_BYPASS = 4,
IOCTL_SD_DLL_RESET = 6,
IOCTL_SET_SD_TAPDELAY = 7,
IOCTL_SET_PLL_FRAC_MODE = 8,
......@@ -389,6 +390,18 @@ enum zynqmp_pm_shutdown_subtype {
ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM = 2,
};
enum tap_delay_signal_type {
PM_TAPDELAY_NAND_DQS_IN = 0,
PM_TAPDELAY_NAND_DQS_OUT = 1,
PM_TAPDELAY_QSPI = 2,
PM_TAPDELAY_MAX = 3,
};
enum tap_delay_bypass_ctrl {
PM_TAPDELAY_BYPASS_DISABLE = 0,
PM_TAPDELAY_BYPASS_ENABLE = 1,
};
enum ospi_mux_select_type {
PM_OSPI_MUX_SEL_DMA = 0,
PM_OSPI_MUX_SEL_LINEAR = 1,
......@@ -484,6 +497,7 @@ int zynqmp_pm_write_ggs(u32 index, u32 value);
int zynqmp_pm_read_ggs(u32 index, u32 *value);
int zynqmp_pm_write_pggs(u32 index, u32 value);
int zynqmp_pm_read_pggs(u32 index, u32 *value);
int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value);
int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype);
int zynqmp_pm_set_boot_health_status(u32 value);
int zynqmp_pm_pinctrl_request(const u32 pin);
......@@ -696,6 +710,11 @@ static inline int zynqmp_pm_read_pggs(u32 index, u32 *value)
return -ENODEV;
}
static inline int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value)
{
return -ENODEV;
}
static inline int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
{
return -ENODEV;
......
......@@ -229,6 +229,7 @@ enum pxa_ssp_type {
LPSS_SPT_SSP,
LPSS_BXT_SSP,
LPSS_CNL_SSP,
SSP_MAX
};
struct ssp_device {
......
......@@ -356,6 +356,7 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
* @max_speed_hz: Highest supported transfer speed
* @flags: other constraints relevant to this driver
* @slave: indicates that this is an SPI slave controller
* @target: indicates that this is an SPI target controller
* @devm_allocated: whether the allocation of this struct is devres-managed
* @max_transfer_size: function that returns the max transfer size for
* a &spi_device; may be %NULL, so the default %SIZE_MAX will be used.
......@@ -440,6 +441,7 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
* @mem_caps: controller capabilities for the handling of memory operations.
* @unprepare_message: undo any work done by prepare_message().
* @slave_abort: abort the ongoing transfer request on an SPI slave controller
* @target_abort: abort the ongoing transfer request on an SPI target controller
* @cs_gpiods: Array of GPIO descs to use as chip select lines; one per CS
* number. Any individual value may be NULL for CS lines that
* are not GPIOs (driven by the SPI controller itself).
......@@ -535,8 +537,12 @@ struct spi_controller {
/* Flag indicating if the allocation of this struct is devres-managed */
bool devm_allocated;
/* Flag indicating this is an SPI slave controller */
bool slave;
union {
/* Flag indicating this is an SPI slave controller */
bool slave;
/* Flag indicating this is an SPI target controller */
bool target;
};
/*
* on some hardware transfer / message size may be constrained
......@@ -649,7 +655,10 @@ struct spi_controller {
struct spi_message *message);
int (*unprepare_message)(struct spi_controller *ctlr,
struct spi_message *message);
int (*slave_abort)(struct spi_controller *ctlr);
union {
int (*slave_abort)(struct spi_controller *ctlr);
int (*target_abort)(struct spi_controller *ctlr);
};
/*
* These hooks are for drivers that use a generic implementation
......@@ -727,6 +736,11 @@ static inline bool spi_controller_is_slave(struct spi_controller *ctlr)
return IS_ENABLED(CONFIG_SPI_SLAVE) && ctlr->slave;
}
static inline bool spi_controller_is_target(struct spi_controller *ctlr)
{
return IS_ENABLED(CONFIG_SPI_SLAVE) && ctlr->target;
}
/* PM calls that need to be issued by the driver */
extern int spi_controller_suspend(struct spi_controller *ctlr);
extern int spi_controller_resume(struct spi_controller *ctlr);
......@@ -763,6 +777,21 @@ static inline struct spi_controller *spi_alloc_slave(struct device *host,
return __spi_alloc_controller(host, size, true);
}
static inline struct spi_controller *spi_alloc_host(struct device *dev,
unsigned int size)
{
return __spi_alloc_controller(dev, size, false);
}
static inline struct spi_controller *spi_alloc_target(struct device *dev,
unsigned int size)
{
if (!IS_ENABLED(CONFIG_SPI_SLAVE))
return NULL;
return __spi_alloc_controller(dev, size, true);
}
struct spi_controller *__devm_spi_alloc_controller(struct device *dev,
unsigned int size,
bool slave);
......@@ -782,6 +811,21 @@ static inline struct spi_controller *devm_spi_alloc_slave(struct device *dev,
return __devm_spi_alloc_controller(dev, size, true);
}
static inline struct spi_controller *devm_spi_alloc_host(struct device *dev,
unsigned int size)
{
return __devm_spi_alloc_controller(dev, size, false);
}
static inline struct spi_controller *devm_spi_alloc_target(struct device *dev,
unsigned int size)
{
if (!IS_ENABLED(CONFIG_SPI_SLAVE))
return NULL;
return __devm_spi_alloc_controller(dev, size, true);
}
extern int spi_register_controller(struct spi_controller *ctlr);
extern int devm_spi_register_controller(struct device *dev,
struct spi_controller *ctlr);
......@@ -1141,6 +1185,7 @@ 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_slave_abort(struct spi_device *spi);
extern int spi_target_abort(struct spi_device *spi);
static inline size_t
spi_max_message_size(struct spi_device *spi)
......@@ -1514,6 +1559,9 @@ extern void spi_unregister_device(struct spi_device *spi);
extern const struct spi_device_id *
spi_get_device_id(const struct spi_device *sdev);
extern const void *
spi_get_device_match_data(const struct spi_device *sdev);
static inline bool
spi_transfer_is_last(struct spi_controller *ctlr, struct spi_transfer *xfer)
{
......
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