Commit 84fccbba authored by Linus Torvalds's avatar Linus Torvalds

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

Pull spi updates from Mark Brown:
 "One small core feature this time around but mostly driver improvements
  and additions for SPI:

   - Add support for controlling the idle state of MOSI, some systems
     can support this and depending on the system integration may need
     it to avoid glitching in some situations

   - Support for polling mode in the S3C64xx driver and DMA on the
     Qualcomm QSPI driver

   - Support for several Allwinner SoCs, AMD Pensando Elba, Intel Mount
     Evans, Renesas RZ/V2M, and ST STM32H7"

* tag 'spi-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (66 commits)
  spi: dt-bindings: atmel,at91rm9200-spi: fix broken sam9x7 compatible
  spi: dt-bindings: atmel,at91rm9200-spi: add sam9x7 compatible
  spi: Add support for Renesas CSI
  spi: dt-bindings: Add bindings for RZ/V2M CSI
  spi: sun6i: Use the new helper to derive the xfer timeout value
  spi: atmel: Prevent false timeouts on long transfers
  spi: dt-bindings: stm32: do not disable spi-slave property for stm32f4-f7
  spi: Create a helper to derive adaptive timeouts
  spi: spi-geni-qcom: correctly handle -EPROBE_DEFER from dma_request_chan()
  spi: stm32: disable spi-slave property for stm32f4-f7
  spi: stm32: introduction of stm32h7 SPI device mode support
  spi: stm32: use dmaengine_terminate_{a}sync instead of _all
  spi: stm32: renaming of spi_master into spi_controller
  spi: dw: Remove misleading comment for Mount Evans SoC
  spi: dt-bindings: snps,dw-apb-ssi: Add compatible for Intel Mount Evans SoC
  spi: dw: Add compatible for Intel Mount Evans SoC
  spi: s3c64xx: Use dev_err_probe()
  spi: s3c64xx: Use the managed spi master allocation function
  spi: spl022: Probe defer is no error
  spi: spi-imx: fix mixing of native and gpio chipselects for imx51/imx53/imx6 variants
  ...
parents 362067b6 e884a133
......@@ -14,9 +14,6 @@ maintainers:
- Maxime Ripard <mripard@kernel.org>
properties:
"#address-cells": true
"#size-cells": true
compatible:
const: allwinner,sun4i-a10-spi
......@@ -46,12 +43,9 @@ properties:
- const: rx
- const: tx
num-cs: true
patternProperties:
"^.*@[0-9a-f]+":
type: object
additionalProperties: true
properties:
reg:
items:
......@@ -71,7 +65,7 @@ required:
- clocks
- clock-names
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -14,11 +14,9 @@ maintainers:
- Maxime Ripard <mripard@kernel.org>
properties:
"#address-cells": true
"#size-cells": true
compatible:
oneOf:
- const: allwinner,sun50i-r329-spi
- const: allwinner,sun6i-a31-spi
- const: allwinner,sun8i-h3-spi
- items:
......@@ -28,6 +26,15 @@ properties:
- allwinner,sun50i-h616-spi
- allwinner,suniv-f1c100s-spi
- const: allwinner,sun8i-h3-spi
- items:
- enum:
- allwinner,sun20i-d1-spi
- allwinner,sun50i-r329-spi-dbi
- const: allwinner,sun50i-r329-spi
- items:
- const: allwinner,sun20i-d1-spi-dbi
- const: allwinner,sun50i-r329-spi-dbi
- const: allwinner,sun50i-r329-spi
reg:
maxItems: 1
......@@ -58,12 +65,9 @@ properties:
- const: rx
- const: tx
num-cs: true
patternProperties:
"^.*@[0-9a-f]+":
type: object
additionalProperties: true
properties:
reg:
items:
......@@ -83,7 +87,7 @@ required:
- clocks
- clock-names
additionalProperties: false
unevaluatedProperties: false
examples:
- |
......
......@@ -20,6 +20,10 @@ properties:
- items:
- const: microchip,sam9x60-spi
- const: atmel,at91rm9200-spi
- items:
- const: microchip,sam9x7-spi
- const: microchip,sam9x60-spi
- const: atmel,at91rm9200-spi
reg:
maxItems: 1
......
......@@ -46,12 +46,28 @@ allOf:
maxItems: 2
items:
enum: [ qspi, qspi-ocp ]
- if:
properties:
compatible:
contains:
const: amd,pensando-elba-qspi
then:
properties:
cdns,fifo-depth:
enum: [ 128, 256, 1024 ]
default: 1024
else:
properties:
cdns,fifo-depth:
enum: [ 128, 256 ]
default: 128
properties:
compatible:
oneOf:
- items:
- enum:
- amd,pensando-elba-qspi
- ti,k2g-qspi
- ti,am654-ospi
- intel,lgm-qspi
......@@ -76,8 +92,6 @@ properties:
description:
Size of the data FIFO in words.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [ 128, 256 ]
default: 128
cdns,fifo-width:
$ref: /schemas/types.yaml#/definitions/uint32
......
......@@ -29,6 +29,9 @@ properties:
reg:
maxItems: 1
iommus:
maxItems: 1
interrupts:
maxItems: 1
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spi/renesas,rzv2m-csi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas RZ/V2M Clocked Serial Interface (CSI)
maintainers:
- Fabrizio Castro <fabrizio.castro.jz@renesas.com>
- Geert Uytterhoeven <geert+renesas@glider.be>
allOf:
- $ref: spi-controller.yaml#
properties:
compatible:
const: renesas,rzv2m-csi
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: The clock used to generate the output clock (CSICLK)
- description: Internal clock to access the registers (PCLK)
clock-names:
items:
- const: csiclk
- const: pclk
resets:
maxItems: 1
power-domains:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
- power-domains
- '#address-cells'
- '#size-cells'
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/r9a09g011-cpg.h>
csi4: spi@a4020200 {
compatible = "renesas,rzv2m-csi";
reg = <0xa4020200 0x80>;
interrupts = <GIC_SPI 230 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD R9A09G011_CSI4_CLK>,
<&cpg CPG_MOD R9A09G011_CPERI_GRPH_PCLK>;
clock-names = "csiclk", "pclk";
resets = <&cpg R9A09G011_CSI_GPH_PRESETN>;
power-domains = <&cpg>;
#address-cells = <1>;
#size-cells = <0>;
};
......@@ -35,8 +35,6 @@ properties:
minItems: 2
maxItems: 3
cs-gpios: true
dmas:
minItems: 2
maxItems: 2
......
......@@ -74,6 +74,8 @@ properties:
const: intel,keembay-ssi
- description: Intel Thunder Bay SPI Controller
const: intel,thunderbay-ssi
- description: Intel Mount Evans Integrated Management Complex SPI Controller
const: intel,mountevans-imc-ssi
- description: AMD Pensando Elba SoC SPI Controller
const: amd,pensando-elba-spi
- description: Baikal-T1 SPI Controller
......
......@@ -17,9 +17,6 @@ allOf:
- $ref: spi-controller.yaml#
properties:
"#address-cells": true
"#size-cells": true
compatible:
const: socionext,uniphier-scssi
......
......@@ -17,7 +17,7 @@ description: |
properties:
$nodename:
pattern: "^spi(@.*|-[0-9a-f])*$"
pattern: "^spi(@.*|-([0-9]|[1-9][0-9]+))?$"
"#address-cells":
enum: [0, 1]
......
......@@ -32,6 +32,12 @@ properties:
clocks:
maxItems: 2
iommus:
maxItems: 1
power-domains:
maxItems: 1
required:
- compatible
- reg
......
......@@ -825,6 +825,12 @@ config SPI_RSPI
help
SPI driver for Renesas RSPI and QSPI blocks.
config SPI_RZV2M_CSI
tristate "Renesas RZV2M CSI controller"
depends on ARCH_RENESAS || COMPILE_TEST
help
SPI driver for Renesas RZ/V2M Clocked Serial Interface (CSI)
config SPI_QCOM_QSPI
tristate "QTI QSPI controller"
depends on ARCH_QCOM || COMPILE_TEST
......@@ -936,6 +942,7 @@ config SPI_SPRD_ADI
config SPI_STM32
tristate "STMicroelectronics STM32 SPI controller"
depends on ARCH_STM32 || COMPILE_TEST
select SPI_SLAVE
help
SPI driver for STMicroelectronics STM32 SoCs.
......
......@@ -113,6 +113,7 @@ obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o
obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o
obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
obj-$(CONFIG_SPI_RZV2M_CSI) += spi-rzv2m-csi.o
obj-$(CONFIG_SPI_S3C64XX) += spi-s3c64xx.o
obj-$(CONFIG_SPI_SC18IS602) += spi-sc18is602.o
obj-$(CONFIG_SPI_SH) += spi-sh.o
......
......@@ -233,7 +233,8 @@
*/
#define DMA_MIN_BYTES 16
#define SPI_DMA_TIMEOUT (msecs_to_jiffies(1000))
#define SPI_DMA_MIN_TIMEOUT (msecs_to_jiffies(1000))
#define SPI_DMA_TIMEOUT_PER_10K (msecs_to_jiffies(4))
#define AUTOSUSPEND_TIMEOUT 2000
......@@ -1279,7 +1280,8 @@ static int atmel_spi_one_transfer(struct spi_controller *host,
struct atmel_spi_device *asd;
int timeout;
int ret;
unsigned long dma_timeout;
unsigned int dma_timeout;
long ret_timeout;
as = spi_controller_get_devdata(host);
......@@ -1333,11 +1335,13 @@ static int atmel_spi_one_transfer(struct spi_controller *host,
atmel_spi_unlock(as);
}
dma_timeout = wait_for_completion_timeout(&as->xfer_completion,
SPI_DMA_TIMEOUT);
if (WARN_ON(dma_timeout == 0)) {
dev_err(&spi->dev, "spi transfer timeout\n");
as->done_status = -EIO;
dma_timeout = msecs_to_jiffies(spi_controller_xfer_timeout(host, xfer));
ret_timeout = wait_for_completion_interruptible_timeout(&as->xfer_completion,
dma_timeout);
if (ret_timeout <= 0) {
dev_err(&spi->dev, "spi transfer %s\n",
!ret_timeout ? "timeout" : "canceled");
as->done_status = ret_timeout < 0 ? ret_timeout : -EIO;
}
if (as->done_status)
......
......@@ -40,6 +40,7 @@
#define CQSPI_SUPPORT_EXTERNAL_DMA BIT(2)
#define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(3)
#define CQSPI_SLOW_SRAM BIT(4)
#define CQSPI_NEEDS_APB_AHB_HAZARD_WAR BIT(5)
/* Capabilities */
#define CQSPI_SUPPORTS_OCTAL BIT(0)
......@@ -90,6 +91,7 @@ struct cqspi_st {
u32 pd_dev_id;
bool wr_completion;
bool slow_sram;
bool apb_ahb_hazard;
};
struct cqspi_driver_platdata {
......@@ -1027,6 +1029,13 @@ static int cqspi_indirect_write_execute(struct cqspi_flash_pdata *f_pdata,
if (cqspi->wr_delay)
ndelay(cqspi->wr_delay);
/*
* If a hazard exists between the APB and AHB interfaces, perform a
* dummy readback from the controller to ensure synchronization.
*/
if (cqspi->apb_ahb_hazard)
readl(reg_base + CQSPI_REG_INDIRECTWR);
while (remaining > 0) {
size_t write_words, mod_bytes;
......@@ -1754,6 +1763,8 @@ static int cqspi_probe(struct platform_device *pdev)
cqspi->wr_completion = false;
if (ddata->quirks & CQSPI_SLOW_SRAM)
cqspi->slow_sram = true;
if (ddata->quirks & CQSPI_NEEDS_APB_AHB_HAZARD_WAR)
cqspi->apb_ahb_hazard = true;
if (of_device_is_compatible(pdev->dev.of_node,
"xlnx,versal-ospi-1.0")) {
......@@ -1888,6 +1899,10 @@ static const struct cqspi_driver_platdata jh7110_qspi = {
.quirks = CQSPI_DISABLE_DAC_MODE,
};
static const struct cqspi_driver_platdata pensando_cdns_qspi = {
.quirks = CQSPI_NEEDS_APB_AHB_HAZARD_WAR | CQSPI_DISABLE_DAC_MODE,
};
static const struct of_device_id cqspi_dt_ids[] = {
{
.compatible = "cdns,qspi-nor",
......@@ -1917,6 +1932,10 @@ static const struct of_device_id cqspi_dt_ids[] = {
.compatible = "starfive,jh7110-qspi",
.data = &jh7110_qspi,
},
{
.compatible = "amd,pensando-elba-qspi",
.data = &pensando_cdns_qspi,
},
{ /* end of table */ }
};
......
......@@ -102,6 +102,7 @@
* @regs: Virtual address of the SPI controller registers
* @ref_clk: Pointer to the peripheral clock
* @pclk: Pointer to the APB clock
* @clk_rate: Reference clock frequency, taken from @ref_clk
* @speed_hz: Current SPI bus clock speed in Hz
* @txbuf: Pointer to the TX buffer
* @rxbuf: Pointer to the RX buffer
......
......@@ -57,21 +57,17 @@ static const struct debugfs_reg32 dw_spi_dbgfs_regs[] = {
DW_SPI_DBGFS_REG("RX_SAMPLE_DLY", DW_SPI_RX_SAMPLE_DLY),
};
static int dw_spi_debugfs_init(struct dw_spi *dws)
static void dw_spi_debugfs_init(struct dw_spi *dws)
{
char name[32];
snprintf(name, 32, "dw_spi%d", dws->master->bus_num);
dws->debugfs = debugfs_create_dir(name, NULL);
if (!dws->debugfs)
return -ENOMEM;
dws->regset.regs = dw_spi_dbgfs_regs;
dws->regset.nregs = ARRAY_SIZE(dw_spi_dbgfs_regs);
dws->regset.base = dws->regs;
debugfs_create_regset32("registers", 0400, dws->debugfs, &dws->regset);
return 0;
}
static void dw_spi_debugfs_remove(struct dw_spi *dws)
......@@ -80,9 +76,8 @@ static void dw_spi_debugfs_remove(struct dw_spi *dws)
}
#else
static inline int dw_spi_debugfs_init(struct dw_spi *dws)
static inline void dw_spi_debugfs_init(struct dw_spi *dws)
{
return 0;
}
static inline void dw_spi_debugfs_remove(struct dw_spi *dws)
......@@ -426,7 +421,10 @@ static int dw_spi_transfer_one(struct spi_controller *master,
int ret;
dws->dma_mapped = 0;
dws->n_bytes = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE);
dws->n_bytes =
roundup_pow_of_two(DIV_ROUND_UP(transfer->bits_per_word,
BITS_PER_BYTE));
dws->tx = (void *)transfer->tx_buf;
dws->tx_len = transfer->len / dws->n_bytes;
dws->rx = transfer->rx_buf;
......
......@@ -72,12 +72,22 @@ static void dw_spi_dma_maxburst_init(struct dw_spi *dws)
dw_writel(dws, DW_SPI_DMATDLR, dws->txburst);
}
static void dw_spi_dma_sg_burst_init(struct dw_spi *dws)
static int dw_spi_dma_caps_init(struct dw_spi *dws)
{
struct dma_slave_caps tx = {0}, rx = {0};
struct dma_slave_caps tx, rx;
int ret;
ret = dma_get_slave_caps(dws->txchan, &tx);
if (ret)
return ret;
dma_get_slave_caps(dws->txchan, &tx);
dma_get_slave_caps(dws->rxchan, &rx);
ret = dma_get_slave_caps(dws->rxchan, &rx);
if (ret)
return ret;
if (!(tx.directions & BIT(DMA_MEM_TO_DEV) &&
rx.directions & BIT(DMA_DEV_TO_MEM)))
return -ENXIO;
if (tx.max_sg_burst > 0 && rx.max_sg_burst > 0)
dws->dma_sg_burst = min(tx.max_sg_burst, rx.max_sg_burst);
......@@ -87,6 +97,15 @@ static void dw_spi_dma_sg_burst_init(struct dw_spi *dws)
dws->dma_sg_burst = rx.max_sg_burst;
else
dws->dma_sg_burst = 0;
/*
* Assuming both channels belong to the same DMA controller hence the
* peripheral side address width capabilities most likely would be
* the same.
*/
dws->dma_addr_widths = tx.dst_addr_widths & rx.src_addr_widths;
return 0;
}
static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
......@@ -95,6 +114,7 @@ static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
struct dw_dma_slave dma_rx = { .src_id = 0 }, *rx = &dma_rx;
struct pci_dev *dma_dev;
dma_cap_mask_t mask;
int ret = -EBUSY;
/*
* Get pci device for DMA controller, currently it could only
......@@ -124,20 +144,25 @@ static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
init_completion(&dws->dma_completion);
dw_spi_dma_maxburst_init(dws);
ret = dw_spi_dma_caps_init(dws);
if (ret)
goto free_txchan;
dw_spi_dma_sg_burst_init(dws);
dw_spi_dma_maxburst_init(dws);
pci_dev_put(dma_dev);
return 0;
free_txchan:
dma_release_channel(dws->txchan);
dws->txchan = NULL;
free_rxchan:
dma_release_channel(dws->rxchan);
dws->rxchan = NULL;
err_exit:
pci_dev_put(dma_dev);
return -EBUSY;
return ret;
}
static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws)
......@@ -163,12 +188,17 @@ static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws)
init_completion(&dws->dma_completion);
dw_spi_dma_maxburst_init(dws);
ret = dw_spi_dma_caps_init(dws);
if (ret)
goto free_txchan;
dw_spi_dma_sg_burst_init(dws);
dw_spi_dma_maxburst_init(dws);
return 0;
free_txchan:
dma_release_channel(dws->txchan);
dws->txchan = NULL;
free_rxchan:
dma_release_channel(dws->rxchan);
dws->rxchan = NULL;
......@@ -198,22 +228,32 @@ static irqreturn_t dw_spi_dma_transfer_handler(struct dw_spi *dws)
return IRQ_HANDLED;
}
static enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes)
{
switch (n_bytes) {
case 1:
return DMA_SLAVE_BUSWIDTH_1_BYTE;
case 2:
return DMA_SLAVE_BUSWIDTH_2_BYTES;
case 4:
return DMA_SLAVE_BUSWIDTH_4_BYTES;
default:
return DMA_SLAVE_BUSWIDTH_UNDEFINED;
}
}
static bool dw_spi_can_dma(struct spi_controller *master,
struct spi_device *spi, struct spi_transfer *xfer)
{
struct dw_spi *dws = spi_controller_get_devdata(master);
enum dma_slave_buswidth dma_bus_width;
return xfer->len > dws->fifo_len;
}
if (xfer->len <= dws->fifo_len)
return false;
static enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes)
{
if (n_bytes == 1)
return DMA_SLAVE_BUSWIDTH_1_BYTE;
else if (n_bytes == 2)
return DMA_SLAVE_BUSWIDTH_2_BYTES;
dma_bus_width = dw_spi_dma_convert_width(dws->n_bytes);
return DMA_SLAVE_BUSWIDTH_UNDEFINED;
return dws->dma_addr_widths & BIT(dma_bus_width);
}
static int dw_spi_dma_wait(struct dw_spi *dws, unsigned int len, u32 speed)
......
......@@ -236,6 +236,24 @@ static int dw_spi_intel_init(struct platform_device *pdev,
return 0;
}
/*
* DMA-based mem ops are not configured for this device and are not tested.
*/
static int dw_spi_mountevans_imc_init(struct platform_device *pdev,
struct dw_spi_mmio *dwsmmio)
{
/*
* The Intel Mount Evans SoC's Integrated Management Complex DW
* apb_ssi_v4.02a controller has an errata where a full TX FIFO can
* result in data corruption. The suggested workaround is to never
* completely fill the FIFO. The TX FIFO has a size of 32 so the
* fifo_len is set to 31.
*/
dwsmmio->dws.fifo_len = 31;
return 0;
}
static int dw_spi_canaan_k210_init(struct platform_device *pdev,
struct dw_spi_mmio *dwsmmio)
{
......@@ -405,6 +423,10 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_hssi_init},
{ .compatible = "intel,keembay-ssi", .data = dw_spi_intel_init},
{ .compatible = "intel,thunderbay-ssi", .data = dw_spi_intel_init},
{
.compatible = "intel,mountevans-imc-ssi",
.data = dw_spi_mountevans_imc_init,
},
{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
{ .compatible = "canaan,k210-spi", dw_spi_canaan_k210_init},
{ .compatible = "amd,pensando-elba-spi", .data = dw_spi_elba_init},
......
......@@ -190,6 +190,7 @@ struct dw_spi {
struct dma_chan *rxchan;
u32 rxburst;
u32 dma_sg_burst;
u32 dma_addr_widths;
unsigned long dma_chan_busy;
dma_addr_t dma_addr; /* phy address of the Data register */
const struct dw_spi_dma_ops *dma_ops;
......
......@@ -303,6 +303,12 @@ static int fsl_lpspi_set_bitrate(struct fsl_lpspi_data *fsl_lpspi)
perclk_rate = clk_get_rate(fsl_lpspi->clk_per);
if (!config.speed_hz) {
dev_err(fsl_lpspi->dev,
"error: the transmission speed provided is 0!\n");
return -EINVAL;
}
if (config.speed_hz > perclk_rate / 2) {
dev_err(fsl_lpspi->dev,
"per-clk should be at least two times of transfer speed");
......@@ -911,7 +917,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
if (ret == -EPROBE_DEFER)
goto out_pm_get;
if (ret < 0)
dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret);
dev_warn(&pdev->dev, "dma setup error %d, use pio\n", ret);
else
/*
* disable LPSPI module IRQ when enable DMA mode successfully,
......
......@@ -35,7 +35,7 @@
#define CS_DEMUX_OUTPUT_SEL GENMASK(3, 0)
#define SE_SPI_TRANS_CFG 0x25c
#define CS_TOGGLE BIT(0)
#define CS_TOGGLE BIT(1)
#define SE_SPI_WORD_LEN 0x268
#define WORD_LEN_MSK GENMASK(9, 0)
......
......@@ -169,7 +169,7 @@ static int hisi_spi_debugfs_init(struct hisi_spi *hs)
master = container_of(hs->dev, struct spi_controller, dev);
snprintf(name, 32, "hisi_spi%d", master->bus_num);
hs->debugfs = debugfs_create_dir(name, NULL);
if (!hs->debugfs)
if (IS_ERR(hs->debugfs))
return -ENOMEM;
hs->regset.regs = hisi_spi_regs;
......
......@@ -281,6 +281,7 @@ static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device
#define MX51_ECSPI_CONFIG_SCLKPOL(cs) (1 << ((cs & 3) + 4))
#define MX51_ECSPI_CONFIG_SBBCTRL(cs) (1 << ((cs & 3) + 8))
#define MX51_ECSPI_CONFIG_SSBPOL(cs) (1 << ((cs & 3) + 12))
#define MX51_ECSPI_CONFIG_DATACTL(cs) (1 << ((cs & 3) + 16))
#define MX51_ECSPI_CONFIG_SCLKCTL(cs) (1 << ((cs & 3) + 20))
#define MX51_ECSPI_INT 0x10
......@@ -516,6 +517,13 @@ static void mx51_ecspi_disable(struct spi_imx_data *spi_imx)
writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
}
static int mx51_ecspi_channel(const struct spi_device *spi)
{
if (!spi_get_csgpiod(spi, 0))
return spi_get_chipselect(spi, 0);
return spi->controller->unused_native_cs;
}
static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
struct spi_message *msg)
{
......@@ -526,6 +534,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
u32 testreg, delay;
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
u32 current_cfg = cfg;
int channel = mx51_ecspi_channel(spi);
/* set Master or Slave mode */
if (spi_imx->slave_mode)
......@@ -540,7 +549,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl);
/* set chip select to use */
ctrl |= MX51_ECSPI_CTRL_CS(spi_get_chipselect(spi, 0));
ctrl |= MX51_ECSPI_CTRL_CS(channel);
/*
* The ctrl register must be written first, with the EN bit set other
......@@ -561,22 +570,27 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
* BURST_LENGTH + 1 bits are received
*/
if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(spi_get_chipselect(spi, 0));
cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(channel);
else
cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi_get_chipselect(spi, 0));
cfg |= MX51_ECSPI_CONFIG_SBBCTRL(channel);
if (spi->mode & SPI_CPOL) {
cfg |= MX51_ECSPI_CONFIG_SCLKPOL(spi_get_chipselect(spi, 0));
cfg |= MX51_ECSPI_CONFIG_SCLKCTL(spi_get_chipselect(spi, 0));
cfg |= MX51_ECSPI_CONFIG_SCLKPOL(channel);
cfg |= MX51_ECSPI_CONFIG_SCLKCTL(channel);
} else {
cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi_get_chipselect(spi, 0));
cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi_get_chipselect(spi, 0));
cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(channel);
cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(channel);
}
if (spi->mode & SPI_MOSI_IDLE_LOW)
cfg |= MX51_ECSPI_CONFIG_DATACTL(channel);
else
cfg &= ~MX51_ECSPI_CONFIG_DATACTL(channel);
if (spi->mode & SPI_CS_HIGH)
cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi_get_chipselect(spi, 0));
cfg |= MX51_ECSPI_CONFIG_SSBPOL(channel);
else
cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi_get_chipselect(spi, 0));
cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(channel);
if (cfg == current_cfg)
return 0;
......@@ -621,14 +635,15 @@ static void mx51_configure_cpha(struct spi_imx_data *spi_imx,
bool cpha = (spi->mode & SPI_CPHA);
bool flip_cpha = (spi->mode & SPI_RX_CPHA_FLIP) && spi_imx->rx_only;
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
int channel = mx51_ecspi_channel(spi);
/* Flip cpha logical value iff flip_cpha */
cpha ^= flip_cpha;
if (cpha)
cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi_get_chipselect(spi, 0));
cfg |= MX51_ECSPI_CONFIG_SCLKPHA(channel);
else
cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(spi_get_chipselect(spi, 0));
cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(channel);
writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
}
......@@ -1737,20 +1752,21 @@ static int spi_imx_probe(struct platform_device *pdev)
else
controller->num_chipselect = 3;
spi_imx->controller->transfer_one = spi_imx_transfer_one;
spi_imx->controller->setup = spi_imx_setup;
spi_imx->controller->cleanup = spi_imx_cleanup;
spi_imx->controller->prepare_message = spi_imx_prepare_message;
spi_imx->controller->unprepare_message = spi_imx_unprepare_message;
spi_imx->controller->slave_abort = spi_imx_slave_abort;
spi_imx->controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
controller->transfer_one = spi_imx_transfer_one;
controller->setup = spi_imx_setup;
controller->cleanup = spi_imx_cleanup;
controller->prepare_message = spi_imx_prepare_message;
controller->unprepare_message = spi_imx_unprepare_message;
controller->slave_abort = spi_imx_slave_abort;
controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS |
SPI_MOSI_IDLE_LOW;
if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
is_imx53_ecspi(spi_imx))
spi_imx->controller->mode_bits |= SPI_LOOP | SPI_READY;
controller->mode_bits |= SPI_LOOP | SPI_READY;
if (is_imx51_ecspi(spi_imx) || is_imx53_ecspi(spi_imx))
spi_imx->controller->mode_bits |= SPI_RX_CPHA_FLIP;
controller->mode_bits |= SPI_RX_CPHA_FLIP;
if (is_imx51_ecspi(spi_imx) &&
device_property_read_u32(&pdev->dev, "cs-gpios", NULL))
......@@ -1759,7 +1775,12 @@ static int spi_imx_probe(struct platform_device *pdev)
* setting the burst length to the word size. This is
* considerably faster than manually controlling the CS.
*/
spi_imx->controller->mode_bits |= SPI_CS_WORD;
controller->mode_bits |= SPI_CS_WORD;
if (is_imx51_ecspi(spi_imx) || is_imx53_ecspi(spi_imx)) {
controller->max_native_cs = 4;
controller->flags |= SPI_MASTER_GPIO_SS;
}
spi_imx->spi_drctl = spi_drctl;
......
......@@ -1144,7 +1144,8 @@ static int mtk_spi_probe(struct platform_device *pdev)
if (mdata->dev_comp->must_tx)
master->flags = SPI_MASTER_MUST_TX;
if (mdata->dev_comp->ipm_design)
master->mode_bits |= SPI_LOOP;
master->mode_bits |= SPI_LOOP | SPI_RX_DUAL | SPI_TX_DUAL |
SPI_RX_QUAD | SPI_TX_QUAD;
if (mdata->dev_comp->ipm_design) {
mdata->dev = dev;
......@@ -1269,7 +1270,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
return 0;
}
static int mtk_spi_remove(struct platform_device *pdev)
static void mtk_spi_remove(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct mtk_spi *mdata = spi_master_get_devdata(master);
......@@ -1278,21 +1279,25 @@ static int mtk_spi_remove(struct platform_device *pdev)
if (mdata->use_spimem && !completion_done(&mdata->spimem_done))
complete(&mdata->spimem_done);
ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0)
return ret;
mtk_spi_reset(mdata);
ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0) {
dev_warn(&pdev->dev, "Failed to resume hardware (%pe)\n", ERR_PTR(ret));
} else {
/*
* If pm runtime resume failed, clks are disabled and
* unprepared. So don't access the hardware and skip clk
* unpreparing.
*/
mtk_spi_reset(mdata);
if (mdata->dev_comp->no_need_unprepare) {
clk_unprepare(mdata->spi_clk);
clk_unprepare(mdata->spi_hclk);
if (mdata->dev_comp->no_need_unprepare) {
clk_unprepare(mdata->spi_clk);
clk_unprepare(mdata->spi_hclk);
}
}
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;
}
#ifdef CONFIG_PM_SLEEP
......@@ -1311,7 +1316,7 @@ static int mtk_spi_suspend(struct device *dev)
clk_disable_unprepare(mdata->spi_hclk);
}
return ret;
return 0;
}
static int mtk_spi_resume(struct device *dev)
......@@ -1412,7 +1417,7 @@ static struct platform_driver mtk_spi_driver = {
.of_match_table = mtk_spi_of_match,
},
.probe = mtk_spi_probe,
.remove = mtk_spi_remove,
.remove_new = mtk_spi_remove,
};
module_platform_driver(mtk_spi_driver);
......
......@@ -2217,8 +2217,8 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
amba_set_drvdata(adev, pl022);
status = devm_spi_register_master(&adev->dev, master);
if (status != 0) {
dev_err(&adev->dev,
"probe - problem registering spi master\n");
dev_err_probe(&adev->dev, status,
"problem registering spi master\n");
goto err_spi_register;
}
dev_dbg(dev, "probe succeeded\n");
......
......@@ -2,6 +2,8 @@
// Copyright (c) 2017-2018, The Linux foundation. All rights reserved.
#include <linux/clk.h>
#include <linux/dmapool.h>
#include <linux/dma-mapping.h>
#include <linux/interconnect.h>
#include <linux/interrupt.h>
#include <linux/io.h>
......@@ -62,6 +64,7 @@
#define WR_FIFO_FULL BIT(10)
#define WR_FIFO_OVERRUN BIT(11)
#define TRANSACTION_DONE BIT(16)
#define DMA_CHAIN_DONE BIT(31)
#define QSPI_ERR_IRQS (RESP_FIFO_UNDERRUN | HRESP_FROM_NOC_ERR | \
WR_FIFO_OVERRUN)
#define QSPI_ALL_IRQS (QSPI_ERR_IRQS | RESP_FIFO_RDY | \
......@@ -108,18 +111,34 @@
#define RD_FIFO_RESET 0x0030
#define RESET_FIFO BIT(0)
#define NEXT_DMA_DESC_ADDR 0x0040
#define CURRENT_DMA_DESC_ADDR 0x0044
#define CURRENT_MEM_ADDR 0x0048
#define CUR_MEM_ADDR 0x0048
#define HW_VERSION 0x004c
#define RD_FIFO 0x0050
#define SAMPLING_CLK_CFG 0x0090
#define SAMPLING_CLK_STATUS 0x0094
#define QSPI_ALIGN_REQ 32
enum qspi_dir {
QSPI_READ,
QSPI_WRITE,
};
struct qspi_cmd_desc {
u32 data_address;
u32 next_descriptor;
u32 direction:1;
u32 multi_io_mode:3;
u32 reserved1:4;
u32 fragment:1;
u32 reserved2:7;
u32 length:16;
};
struct qspi_xfer {
union {
const void *tx_buf;
......@@ -137,11 +156,23 @@ enum qspi_clocks {
QSPI_NUM_CLKS
};
/*
* Number of entries in sgt returned from spi framework that-
* will be supported. Can be modified as required.
* In practice, given max_dma_len is 64KB, the number of
* entries is not expected to exceed 1.
*/
#define QSPI_MAX_SG 5
struct qcom_qspi {
void __iomem *base;
struct device *dev;
struct clk_bulk_data *clks;
struct qspi_xfer xfer;
struct dma_pool *dma_cmd_pool;
dma_addr_t dma_cmd_desc[QSPI_MAX_SG];
void *virt_cmd_desc[QSPI_MAX_SG];
unsigned int n_cmd_desc;
struct icc_path *icc_path_cpu_to_qspi;
unsigned long last_speed;
/* Lock to protect data accessed by IRQs */
......@@ -153,21 +184,22 @@ static u32 qspi_buswidth_to_iomode(struct qcom_qspi *ctrl,
{
switch (buswidth) {
case 1:
return SDR_1BIT << MULTI_IO_MODE_SHFT;
return SDR_1BIT;
case 2:
return SDR_2BIT << MULTI_IO_MODE_SHFT;
return SDR_2BIT;
case 4:
return SDR_4BIT << MULTI_IO_MODE_SHFT;
return SDR_4BIT;
default:
dev_warn_once(ctrl->dev,
"Unexpected bus width: %u\n", buswidth);
return SDR_1BIT << MULTI_IO_MODE_SHFT;
return SDR_1BIT;
}
}
static void qcom_qspi_pio_xfer_cfg(struct qcom_qspi *ctrl)
{
u32 pio_xfer_cfg;
u32 iomode;
const struct qspi_xfer *xfer;
xfer = &ctrl->xfer;
......@@ -179,7 +211,8 @@ static void qcom_qspi_pio_xfer_cfg(struct qcom_qspi *ctrl)
else
pio_xfer_cfg |= TRANSFER_FRAGMENT;
pio_xfer_cfg &= ~MULTI_IO_MODE_MSK;
pio_xfer_cfg |= qspi_buswidth_to_iomode(ctrl, xfer->buswidth);
iomode = qspi_buswidth_to_iomode(ctrl, xfer->buswidth);
pio_xfer_cfg |= iomode << MULTI_IO_MODE_SHFT;
writel(pio_xfer_cfg, ctrl->base + PIO_XFER_CFG);
}
......@@ -217,12 +250,22 @@ static void qcom_qspi_pio_xfer(struct qcom_qspi *ctrl)
static void qcom_qspi_handle_err(struct spi_master *master,
struct spi_message *msg)
{
u32 int_status;
struct qcom_qspi *ctrl = spi_master_get_devdata(master);
unsigned long flags;
int i;
spin_lock_irqsave(&ctrl->lock, flags);
writel(0, ctrl->base + MSTR_INT_EN);
int_status = readl(ctrl->base + MSTR_INT_STATUS);
writel(int_status, ctrl->base + MSTR_INT_STATUS);
ctrl->xfer.rem_bytes = 0;
/* free cmd descriptors if they are around (DMA mode) */
for (i = 0; i < ctrl->n_cmd_desc; i++)
dma_pool_free(ctrl->dma_cmd_pool, ctrl->virt_cmd_desc[i],
ctrl->dma_cmd_desc[i]);
ctrl->n_cmd_desc = 0;
spin_unlock_irqrestore(&ctrl->lock, flags);
}
......@@ -242,7 +285,7 @@ static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz)
}
/*
* Set BW quota for CPU as driver supports FIFO mode only.
* Set BW quota for CPU.
* We don't have explicit peak requirement so keep it equal to avg_bw.
*/
avg_bw_cpu = Bps_to_icc(speed_hz);
......@@ -258,6 +301,102 @@ static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz)
return 0;
}
static int qcom_qspi_alloc_desc(struct qcom_qspi *ctrl, dma_addr_t dma_ptr,
uint32_t n_bytes)
{
struct qspi_cmd_desc *virt_cmd_desc, *prev;
dma_addr_t dma_cmd_desc;
/* allocate for dma cmd descriptor */
virt_cmd_desc = dma_pool_alloc(ctrl->dma_cmd_pool, GFP_KERNEL | __GFP_ZERO, &dma_cmd_desc);
if (!virt_cmd_desc)
return -ENOMEM;
ctrl->virt_cmd_desc[ctrl->n_cmd_desc] = virt_cmd_desc;
ctrl->dma_cmd_desc[ctrl->n_cmd_desc] = dma_cmd_desc;
ctrl->n_cmd_desc++;
/* setup cmd descriptor */
virt_cmd_desc->data_address = dma_ptr;
virt_cmd_desc->direction = ctrl->xfer.dir;
virt_cmd_desc->multi_io_mode = qspi_buswidth_to_iomode(ctrl, ctrl->xfer.buswidth);
virt_cmd_desc->fragment = !ctrl->xfer.is_last;
virt_cmd_desc->length = n_bytes;
/* update previous descriptor */
if (ctrl->n_cmd_desc >= 2) {
prev = (ctrl->virt_cmd_desc)[ctrl->n_cmd_desc - 2];
prev->next_descriptor = dma_cmd_desc;
prev->fragment = 1;
}
return 0;
}
static int qcom_qspi_setup_dma_desc(struct qcom_qspi *ctrl,
struct spi_transfer *xfer)
{
int ret;
struct sg_table *sgt;
dma_addr_t dma_ptr_sg;
unsigned int dma_len_sg;
int i;
if (ctrl->n_cmd_desc) {
dev_err(ctrl->dev, "Remnant dma buffers n_cmd_desc-%d\n", ctrl->n_cmd_desc);
return -EIO;
}
sgt = (ctrl->xfer.dir == QSPI_READ) ? &xfer->rx_sg : &xfer->tx_sg;
if (!sgt->nents || sgt->nents > QSPI_MAX_SG) {
dev_warn_once(ctrl->dev, "Cannot handle %d entries in scatter list\n", sgt->nents);
return -EAGAIN;
}
for (i = 0; i < sgt->nents; i++) {
dma_ptr_sg = sg_dma_address(sgt->sgl + i);
if (!IS_ALIGNED(dma_ptr_sg, QSPI_ALIGN_REQ)) {
dev_warn_once(ctrl->dev, "dma_address not aligned to %d\n", QSPI_ALIGN_REQ);
return -EAGAIN;
}
}
for (i = 0; i < sgt->nents; i++) {
dma_ptr_sg = sg_dma_address(sgt->sgl + i);
dma_len_sg = sg_dma_len(sgt->sgl + i);
ret = qcom_qspi_alloc_desc(ctrl, dma_ptr_sg, dma_len_sg);
if (ret)
goto cleanup;
}
return 0;
cleanup:
for (i = 0; i < ctrl->n_cmd_desc; i++)
dma_pool_free(ctrl->dma_cmd_pool, ctrl->virt_cmd_desc[i],
ctrl->dma_cmd_desc[i]);
ctrl->n_cmd_desc = 0;
return ret;
}
static void qcom_qspi_dma_xfer(struct qcom_qspi *ctrl)
{
/* Setup new interrupts */
writel(DMA_CHAIN_DONE, ctrl->base + MSTR_INT_EN);
/* kick off transfer */
writel((u32)((ctrl->dma_cmd_desc)[0]), ctrl->base + NEXT_DMA_DESC_ADDR);
}
/* Switch to DMA if transfer length exceeds this */
#define QSPI_MAX_BYTES_FIFO 64
static bool qcom_qspi_can_dma(struct spi_controller *ctlr,
struct spi_device *slv, struct spi_transfer *xfer)
{
return xfer->len > QSPI_MAX_BYTES_FIFO;
}
static int qcom_qspi_transfer_one(struct spi_master *master,
struct spi_device *slv,
struct spi_transfer *xfer)
......@@ -266,6 +405,7 @@ static int qcom_qspi_transfer_one(struct spi_master *master,
int ret;
unsigned long speed_hz;
unsigned long flags;
u32 mstr_cfg;
speed_hz = slv->max_speed_hz;
if (xfer->speed_hz)
......@@ -276,6 +416,7 @@ static int qcom_qspi_transfer_one(struct spi_master *master,
return ret;
spin_lock_irqsave(&ctrl->lock, flags);
mstr_cfg = readl(ctrl->base + MSTR_CONFIG);
/* We are half duplex, so either rx or tx will be set */
if (xfer->rx_buf) {
......@@ -290,10 +431,36 @@ static int qcom_qspi_transfer_one(struct spi_master *master,
ctrl->xfer.is_last = list_is_last(&xfer->transfer_list,
&master->cur_msg->transfers);
ctrl->xfer.rem_bytes = xfer->len;
if (xfer->rx_sg.nents || xfer->tx_sg.nents) {
/* do DMA transfer */
if (!(mstr_cfg & DMA_ENABLE)) {
mstr_cfg |= DMA_ENABLE;
writel(mstr_cfg, ctrl->base + MSTR_CONFIG);
}
ret = qcom_qspi_setup_dma_desc(ctrl, xfer);
if (ret != -EAGAIN) {
if (!ret)
qcom_qspi_dma_xfer(ctrl);
goto exit;
}
dev_warn_once(ctrl->dev, "DMA failure, falling back to PIO\n");
ret = 0; /* We'll retry w/ PIO */
}
if (mstr_cfg & DMA_ENABLE) {
mstr_cfg &= ~DMA_ENABLE;
writel(mstr_cfg, ctrl->base + MSTR_CONFIG);
}
qcom_qspi_pio_xfer(ctrl);
exit:
spin_unlock_irqrestore(&ctrl->lock, flags);
if (ret)
return ret;
/* We'll call spi_finalize_current_transfer() when done */
return 1;
}
......@@ -328,6 +495,16 @@ static int qcom_qspi_prepare_message(struct spi_master *master,
return 0;
}
static int qcom_qspi_alloc_dma(struct qcom_qspi *ctrl)
{
ctrl->dma_cmd_pool = dmam_pool_create("qspi cmd desc pool",
ctrl->dev, sizeof(struct qspi_cmd_desc), 0, 0);
if (!ctrl->dma_cmd_pool)
return -ENOMEM;
return 0;
}
static irqreturn_t pio_read(struct qcom_qspi *ctrl)
{
u32 rd_fifo_status;
......@@ -426,6 +603,7 @@ static irqreturn_t qcom_qspi_irq(int irq, void *dev_id)
int_status = readl(ctrl->base + MSTR_INT_STATUS);
writel(int_status, ctrl->base + MSTR_INT_STATUS);
/* PIO mode handling */
if (ctrl->xfer.dir == QSPI_WRITE) {
if (int_status & WR_FIFO_EMPTY)
ret = pio_write(ctrl);
......@@ -449,6 +627,22 @@ static irqreturn_t qcom_qspi_irq(int irq, void *dev_id)
spi_finalize_current_transfer(dev_get_drvdata(ctrl->dev));
}
/* DMA mode handling */
if (int_status & DMA_CHAIN_DONE) {
int i;
writel(0, ctrl->base + MSTR_INT_EN);
ctrl->xfer.rem_bytes = 0;
for (i = 0; i < ctrl->n_cmd_desc; i++)
dma_pool_free(ctrl->dma_cmd_pool, ctrl->virt_cmd_desc[i],
ctrl->dma_cmd_desc[i]);
ctrl->n_cmd_desc = 0;
ret = IRQ_HANDLED;
spi_finalize_current_transfer(dev_get_drvdata(ctrl->dev));
}
spin_unlock(&ctrl->lock);
return ret;
}
......@@ -517,7 +711,13 @@ static int qcom_qspi_probe(struct platform_device *pdev)
return ret;
}
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret)
return dev_err_probe(dev, ret, "could not set DMA mask\n");
master->max_speed_hz = 300000000;
master->max_dma_len = 65536; /* as per HPG */
master->dma_alignment = QSPI_ALIGN_REQ;
master->num_chipselect = QSPI_NUM_CS;
master->bus_num = -1;
master->dev.of_node = pdev->dev.of_node;
......@@ -528,6 +728,8 @@ static int qcom_qspi_probe(struct platform_device *pdev)
master->prepare_message = qcom_qspi_prepare_message;
master->transfer_one = qcom_qspi_transfer_one;
master->handle_err = qcom_qspi_handle_err;
if (of_property_read_bool(pdev->dev.of_node, "iommus"))
master->can_dma = qcom_qspi_can_dma;
master->auto_runtime_pm = true;
ret = devm_pm_opp_set_clkname(&pdev->dev, "core");
......@@ -540,6 +742,10 @@ static int qcom_qspi_probe(struct platform_device *pdev)
return ret;
}
ret = qcom_qspi_alloc_dma(ctrl);
if (ret)
return ret;
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 250);
pm_runtime_enable(dev);
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Renesas RZ/V2M Clocked Serial Interface (CSI) driver
*
* Copyright (C) 2023 Renesas Electronics Corporation
*/
#include <linux/clk.h>
#include <linux/count_zeros.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/spi/spi.h>
/* Registers */
#define CSI_MODE 0x00 /* CSI mode control */
#define CSI_CLKSEL 0x04 /* CSI clock select */
#define CSI_CNT 0x08 /* CSI control */
#define CSI_INT 0x0C /* CSI interrupt status */
#define CSI_IFIFOL 0x10 /* CSI receive FIFO level display */
#define CSI_OFIFOL 0x14 /* CSI transmit FIFO level display */
#define CSI_IFIFO 0x18 /* CSI receive window */
#define CSI_OFIFO 0x1C /* CSI transmit window */
#define CSI_FIFOTRG 0x20 /* CSI FIFO trigger level */
/* CSI_MODE */
#define CSI_MODE_CSIE BIT(7)
#define CSI_MODE_TRMD BIT(6)
#define CSI_MODE_CCL BIT(5)
#define CSI_MODE_DIR BIT(4)
#define CSI_MODE_CSOT BIT(0)
#define CSI_MODE_SETUP 0x00000040
/* CSI_CLKSEL */
#define CSI_CLKSEL_CKP BIT(17)
#define CSI_CLKSEL_DAP BIT(16)
#define CSI_CLKSEL_SLAVE BIT(15)
#define CSI_CLKSEL_CKS GENMASK(14, 1)
/* CSI_CNT */
#define CSI_CNT_CSIRST BIT(28)
#define CSI_CNT_R_TRGEN BIT(19)
#define CSI_CNT_UNDER_E BIT(13)
#define CSI_CNT_OVERF_E BIT(12)
#define CSI_CNT_TREND_E BIT(9)
#define CSI_CNT_CSIEND_E BIT(8)
#define CSI_CNT_T_TRGR_E BIT(4)
#define CSI_CNT_R_TRGR_E BIT(0)
/* CSI_INT */
#define CSI_INT_UNDER BIT(13)
#define CSI_INT_OVERF BIT(12)
#define CSI_INT_TREND BIT(9)
#define CSI_INT_CSIEND BIT(8)
#define CSI_INT_T_TRGR BIT(4)
#define CSI_INT_R_TRGR BIT(0)
/* CSI_FIFOTRG */
#define CSI_FIFOTRG_R_TRG GENMASK(2, 0)
#define CSI_FIFO_SIZE_BYTES 32
#define CSI_FIFO_HALF_SIZE 16
#define CSI_EN_DIS_TIMEOUT_US 100
#define CSI_CKS_MAX 0x3FFF
#define UNDERRUN_ERROR BIT(0)
#define OVERFLOW_ERROR BIT(1)
#define TX_TIMEOUT_ERROR BIT(2)
#define RX_TIMEOUT_ERROR BIT(3)
#define CSI_MAX_SPI_SCKO 8000000
struct rzv2m_csi_priv {
void __iomem *base;
struct clk *csiclk;
struct clk *pclk;
struct device *dev;
struct spi_controller *controller;
const u8 *txbuf;
u8 *rxbuf;
int buffer_len;
int bytes_sent;
int bytes_received;
int bytes_to_transfer;
int words_to_transfer;
unsigned char bytes_per_word;
wait_queue_head_t wait;
u8 errors;
u32 status;
};
static const unsigned char x_trg[] = {
0, 1, 1, 2, 2, 2, 2, 3,
3, 3, 3, 3, 3, 3, 3, 4,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 5
};
static const unsigned char x_trg_words[] = {
1, 2, 2, 4, 4, 4, 4, 8,
8, 8, 8, 8, 8, 8, 8, 16,
16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 32
};
static void rzv2m_csi_reg_write_bit(const struct rzv2m_csi_priv *csi,
int reg_offs, int bit_mask, u32 value)
{
int nr_zeros;
u32 tmp;
nr_zeros = count_trailing_zeros(bit_mask);
value <<= nr_zeros;
tmp = (readl(csi->base + reg_offs) & ~bit_mask) | value;
writel(tmp, csi->base + reg_offs);
}
static int rzv2m_csi_sw_reset(struct rzv2m_csi_priv *csi, int assert)
{
u32 reg;
rzv2m_csi_reg_write_bit(csi, CSI_CNT, CSI_CNT_CSIRST, assert);
if (assert) {
return readl_poll_timeout(csi->base + CSI_MODE, reg,
!(reg & CSI_MODE_CSOT), 0,
CSI_EN_DIS_TIMEOUT_US);
}
return 0;
}
static int rzv2m_csi_start_stop_operation(const struct rzv2m_csi_priv *csi,
int enable, bool wait)
{
u32 reg;
rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_CSIE, enable);
if (!enable && wait)
return readl_poll_timeout(csi->base + CSI_MODE, reg,
!(reg & CSI_MODE_CSOT), 0,
CSI_EN_DIS_TIMEOUT_US);
return 0;
}
static int rzv2m_csi_fill_txfifo(struct rzv2m_csi_priv *csi)
{
int i;
if (readl(csi->base + CSI_OFIFOL))
return -EIO;
if (csi->bytes_per_word == 2) {
u16 *buf = (u16 *)csi->txbuf;
for (i = 0; i < csi->words_to_transfer; i++)
writel(buf[i], csi->base + CSI_OFIFO);
} else {
u8 *buf = (u8 *)csi->txbuf;
for (i = 0; i < csi->words_to_transfer; i++)
writel(buf[i], csi->base + CSI_OFIFO);
}
csi->txbuf += csi->bytes_to_transfer;
csi->bytes_sent += csi->bytes_to_transfer;
return 0;
}
static int rzv2m_csi_read_rxfifo(struct rzv2m_csi_priv *csi)
{
int i;
if (readl(csi->base + CSI_IFIFOL) != csi->bytes_to_transfer)
return -EIO;
if (csi->bytes_per_word == 2) {
u16 *buf = (u16 *)csi->rxbuf;
for (i = 0; i < csi->words_to_transfer; i++)
buf[i] = (u16)readl(csi->base + CSI_IFIFO);
} else {
u8 *buf = (u8 *)csi->rxbuf;
for (i = 0; i < csi->words_to_transfer; i++)
buf[i] = (u8)readl(csi->base + CSI_IFIFO);
}
csi->rxbuf += csi->bytes_to_transfer;
csi->bytes_received += csi->bytes_to_transfer;
return 0;
}
static inline void rzv2m_csi_calc_current_transfer(struct rzv2m_csi_priv *csi)
{
int bytes_transferred = max_t(int, csi->bytes_received, csi->bytes_sent);
int bytes_remaining = csi->buffer_len - bytes_transferred;
int to_transfer;
if (csi->txbuf)
/*
* Leaving a little bit of headroom in the FIFOs makes it very
* hard to raise an overflow error (which is only possible
* when IP transmits and receives at the same time).
*/
to_transfer = min_t(int, CSI_FIFO_HALF_SIZE, bytes_remaining);
else
to_transfer = min_t(int, CSI_FIFO_SIZE_BYTES, bytes_remaining);
if (csi->bytes_per_word == 2)
to_transfer >>= 1;
/*
* We can only choose a trigger level from a predefined set of values.
* This will pick a value that is the greatest possible integer that's
* less than or equal to the number of bytes we need to transfer.
* This may result in multiple smaller transfers.
*/
csi->words_to_transfer = x_trg_words[to_transfer - 1];
if (csi->bytes_per_word == 2)
csi->bytes_to_transfer = csi->words_to_transfer << 1;
else
csi->bytes_to_transfer = csi->words_to_transfer;
}
static inline void rzv2m_csi_set_rx_fifo_trigger_level(struct rzv2m_csi_priv *csi)
{
rzv2m_csi_reg_write_bit(csi, CSI_FIFOTRG, CSI_FIFOTRG_R_TRG,
x_trg[csi->words_to_transfer - 1]);
}
static inline void rzv2m_csi_enable_rx_trigger(struct rzv2m_csi_priv *csi,
bool enable)
{
rzv2m_csi_reg_write_bit(csi, CSI_CNT, CSI_CNT_R_TRGEN, enable);
}
static void rzv2m_csi_disable_irqs(const struct rzv2m_csi_priv *csi,
u32 enable_bits)
{
u32 cnt = readl(csi->base + CSI_CNT);
writel(cnt & ~enable_bits, csi->base + CSI_CNT);
}
static void rzv2m_csi_disable_all_irqs(struct rzv2m_csi_priv *csi)
{
rzv2m_csi_disable_irqs(csi, CSI_CNT_R_TRGR_E | CSI_CNT_T_TRGR_E |
CSI_CNT_CSIEND_E | CSI_CNT_TREND_E |
CSI_CNT_OVERF_E | CSI_CNT_UNDER_E);
}
static inline void rzv2m_csi_clear_irqs(struct rzv2m_csi_priv *csi, u32 irqs)
{
writel(irqs, csi->base + CSI_INT);
}
static void rzv2m_csi_clear_all_irqs(struct rzv2m_csi_priv *csi)
{
rzv2m_csi_clear_irqs(csi, CSI_INT_UNDER | CSI_INT_OVERF |
CSI_INT_TREND | CSI_INT_CSIEND | CSI_INT_T_TRGR |
CSI_INT_R_TRGR);
}
static void rzv2m_csi_enable_irqs(struct rzv2m_csi_priv *csi, u32 enable_bits)
{
u32 cnt = readl(csi->base + CSI_CNT);
writel(cnt | enable_bits, csi->base + CSI_CNT);
}
static int rzv2m_csi_wait_for_interrupt(struct rzv2m_csi_priv *csi,
u32 wait_mask, u32 enable_bits)
{
int ret;
rzv2m_csi_enable_irqs(csi, enable_bits);
ret = wait_event_timeout(csi->wait,
((csi->status & wait_mask) == wait_mask) ||
csi->errors, HZ);
rzv2m_csi_disable_irqs(csi, enable_bits);
if (csi->errors)
return -EIO;
if (!ret)
return -ETIMEDOUT;
return 0;
}
static int rzv2m_csi_wait_for_tx_empty(struct rzv2m_csi_priv *csi)
{
int ret;
if (readl(csi->base + CSI_OFIFOL) == 0)
return 0;
ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_TREND, CSI_CNT_TREND_E);
if (ret == -ETIMEDOUT)
csi->errors |= TX_TIMEOUT_ERROR;
return ret;
}
static inline int rzv2m_csi_wait_for_rx_ready(struct rzv2m_csi_priv *csi)
{
int ret;
if (readl(csi->base + CSI_IFIFOL) == csi->bytes_to_transfer)
return 0;
ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_R_TRGR,
CSI_CNT_R_TRGR_E);
if (ret == -ETIMEDOUT)
csi->errors |= RX_TIMEOUT_ERROR;
return ret;
}
static irqreturn_t rzv2m_csi_irq_handler(int irq, void *data)
{
struct rzv2m_csi_priv *csi = (struct rzv2m_csi_priv *)data;
csi->status = readl(csi->base + CSI_INT);
rzv2m_csi_disable_irqs(csi, csi->status);
if (csi->status & CSI_INT_OVERF)
csi->errors |= OVERFLOW_ERROR;
if (csi->status & CSI_INT_UNDER)
csi->errors |= UNDERRUN_ERROR;
wake_up(&csi->wait);
return IRQ_HANDLED;
}
static void rzv2m_csi_setup_clock(struct rzv2m_csi_priv *csi, u32 spi_hz)
{
unsigned long csiclk_rate = clk_get_rate(csi->csiclk);
unsigned long pclk_rate = clk_get_rate(csi->pclk);
unsigned long csiclk_rate_limit = pclk_rate >> 1;
u32 cks;
/*
* There is a restriction on the frequency of CSICLK, it has to be <=
* PCLK / 2.
*/
if (csiclk_rate > csiclk_rate_limit) {
clk_set_rate(csi->csiclk, csiclk_rate >> 1);
csiclk_rate = clk_get_rate(csi->csiclk);
} else if ((csiclk_rate << 1) <= csiclk_rate_limit) {
clk_set_rate(csi->csiclk, csiclk_rate << 1);
csiclk_rate = clk_get_rate(csi->csiclk);
}
spi_hz = spi_hz > CSI_MAX_SPI_SCKO ? CSI_MAX_SPI_SCKO : spi_hz;
cks = DIV_ROUND_UP(csiclk_rate, spi_hz << 1);
if (cks > CSI_CKS_MAX)
cks = CSI_CKS_MAX;
dev_dbg(csi->dev, "SPI clk rate is %ldHz\n", csiclk_rate / (cks << 1));
rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_CKS, cks);
}
static void rzv2m_csi_setup_operating_mode(struct rzv2m_csi_priv *csi,
struct spi_transfer *t)
{
if (t->rx_buf && !t->tx_buf)
/* Reception-only mode */
rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_TRMD, 0);
else
/* Send and receive mode */
rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_TRMD, 1);
csi->bytes_per_word = t->bits_per_word / 8;
rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_CCL,
csi->bytes_per_word == 2);
}
static int rzv2m_csi_setup(struct spi_device *spi)
{
struct rzv2m_csi_priv *csi = spi_controller_get_devdata(spi->controller);
int ret;
rzv2m_csi_sw_reset(csi, 0);
writel(CSI_MODE_SETUP, csi->base + CSI_MODE);
/* Setup clock polarity and phase timing */
rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_CKP,
!(spi->mode & SPI_CPOL));
rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_DAP,
!(spi->mode & SPI_CPHA));
/* Setup serial data order */
rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_DIR,
!!(spi->mode & SPI_LSB_FIRST));
/* Set the operation mode as master */
rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_SLAVE, 0);
/* Give the IP a SW reset */
ret = rzv2m_csi_sw_reset(csi, 1);
if (ret)
return ret;
rzv2m_csi_sw_reset(csi, 0);
/*
* We need to enable the communication so that the clock will settle
* for the right polarity before enabling the CS.
*/
rzv2m_csi_start_stop_operation(csi, 1, false);
udelay(10);
rzv2m_csi_start_stop_operation(csi, 0, false);
return 0;
}
static int rzv2m_csi_pio_transfer(struct rzv2m_csi_priv *csi)
{
bool tx_completed = csi->txbuf ? false : true;
bool rx_completed = csi->rxbuf ? false : true;
int ret = 0;
/* Make sure the TX FIFO is empty */
writel(0, csi->base + CSI_OFIFOL);
csi->bytes_sent = 0;
csi->bytes_received = 0;
csi->errors = 0;
rzv2m_csi_disable_all_irqs(csi);
rzv2m_csi_clear_all_irqs(csi);
rzv2m_csi_enable_rx_trigger(csi, true);
while (!tx_completed || !rx_completed) {
/*
* Decide how many words we are going to transfer during
* this cycle (for both TX and RX), then set the RX FIFO trigger
* level accordingly. No need to set a trigger level for the
* TX FIFO, as this IP comes with an interrupt that fires when
* the TX FIFO is empty.
*/
rzv2m_csi_calc_current_transfer(csi);
rzv2m_csi_set_rx_fifo_trigger_level(csi);
rzv2m_csi_enable_irqs(csi, CSI_INT_OVERF | CSI_INT_UNDER);
/* Make sure the RX FIFO is empty */
writel(0, csi->base + CSI_IFIFOL);
writel(readl(csi->base + CSI_INT), csi->base + CSI_INT);
csi->status = 0;
rzv2m_csi_start_stop_operation(csi, 1, false);
/* TX */
if (csi->txbuf) {
ret = rzv2m_csi_fill_txfifo(csi);
if (ret)
break;
ret = rzv2m_csi_wait_for_tx_empty(csi);
if (ret)
break;
if (csi->bytes_sent == csi->buffer_len)
tx_completed = true;
}
/*
* Make sure the RX FIFO contains the desired number of words.
* We then either flush its content, or we copy it onto
* csi->rxbuf.
*/
ret = rzv2m_csi_wait_for_rx_ready(csi);
if (ret)
break;
/* RX */
if (csi->rxbuf) {
rzv2m_csi_start_stop_operation(csi, 0, false);
ret = rzv2m_csi_read_rxfifo(csi);
if (ret)
break;
if (csi->bytes_received == csi->buffer_len)
rx_completed = true;
}
ret = rzv2m_csi_start_stop_operation(csi, 0, true);
if (ret)
goto pio_quit;
if (csi->errors) {
ret = -EIO;
goto pio_quit;
}
}
rzv2m_csi_start_stop_operation(csi, 0, true);
pio_quit:
rzv2m_csi_disable_all_irqs(csi);
rzv2m_csi_enable_rx_trigger(csi, false);
rzv2m_csi_clear_all_irqs(csi);
return ret;
}
static int rzv2m_csi_transfer_one(struct spi_controller *controller,
struct spi_device *spi,
struct spi_transfer *transfer)
{
struct rzv2m_csi_priv *csi = spi_controller_get_devdata(controller);
struct device *dev = csi->dev;
int ret;
csi->txbuf = transfer->tx_buf;
csi->rxbuf = transfer->rx_buf;
csi->buffer_len = transfer->len;
rzv2m_csi_setup_operating_mode(csi, transfer);
rzv2m_csi_setup_clock(csi, transfer->speed_hz);
ret = rzv2m_csi_pio_transfer(csi);
if (ret) {
if (csi->errors & UNDERRUN_ERROR)
dev_err(dev, "Underrun error\n");
if (csi->errors & OVERFLOW_ERROR)
dev_err(dev, "Overflow error\n");
if (csi->errors & TX_TIMEOUT_ERROR)
dev_err(dev, "TX timeout error\n");
if (csi->errors & RX_TIMEOUT_ERROR)
dev_err(dev, "RX timeout error\n");
}
return ret;
}
static int rzv2m_csi_probe(struct platform_device *pdev)
{
struct spi_controller *controller;
struct device *dev = &pdev->dev;
struct rzv2m_csi_priv *csi;
struct reset_control *rstc;
int irq;
int ret;
controller = devm_spi_alloc_master(dev, sizeof(*csi));
if (!controller)
return -ENOMEM;
csi = spi_controller_get_devdata(controller);
platform_set_drvdata(pdev, csi);
csi->dev = dev;
csi->controller = controller;
csi->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(csi->base))
return PTR_ERR(csi->base);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
csi->csiclk = devm_clk_get(dev, "csiclk");
if (IS_ERR(csi->csiclk))
return dev_err_probe(dev, PTR_ERR(csi->csiclk),
"could not get csiclk\n");
csi->pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(csi->pclk))
return dev_err_probe(dev, PTR_ERR(csi->pclk),
"could not get pclk\n");
rstc = devm_reset_control_get_shared(dev, NULL);
if (IS_ERR(rstc))
return dev_err_probe(dev, PTR_ERR(rstc), "Missing reset ctrl\n");
init_waitqueue_head(&csi->wait);
controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
controller->dev.of_node = pdev->dev.of_node;
controller->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
controller->setup = rzv2m_csi_setup;
controller->transfer_one = rzv2m_csi_transfer_one;
controller->use_gpio_descriptors = true;
ret = devm_request_irq(dev, irq, rzv2m_csi_irq_handler, 0,
dev_name(dev), csi);
if (ret)
return dev_err_probe(dev, ret, "cannot request IRQ\n");
/*
* The reset also affects other HW that is not under the control
* of Linux. Therefore, all we can do is make sure the reset is
* deasserted.
*/
reset_control_deassert(rstc);
/* Make sure the IP is in SW reset state */
ret = rzv2m_csi_sw_reset(csi, 1);
if (ret)
return ret;
ret = clk_prepare_enable(csi->csiclk);
if (ret)
return dev_err_probe(dev, ret, "could not enable csiclk\n");
ret = spi_register_controller(controller);
if (ret) {
clk_disable_unprepare(csi->csiclk);
return dev_err_probe(dev, ret, "register controller failed\n");
}
return 0;
}
static int rzv2m_csi_remove(struct platform_device *pdev)
{
struct rzv2m_csi_priv *csi = platform_get_drvdata(pdev);
spi_unregister_controller(csi->controller);
rzv2m_csi_sw_reset(csi, 1);
clk_disable_unprepare(csi->csiclk);
return 0;
}
static const struct of_device_id rzv2m_csi_match[] = {
{ .compatible = "renesas,rzv2m-csi" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rzv2m_csi_match);
static struct platform_driver rzv2m_csi_drv = {
.probe = rzv2m_csi_probe,
.remove = rzv2m_csi_remove,
.driver = {
.name = "rzv2m_csi",
.of_match_table = rzv2m_csi_match,
},
};
module_platform_driver(rzv2m_csi_drv);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Fabrizio Castro <castro.fabrizio.jz@renesas.com>");
MODULE_DESCRIPTION("Clocked Serial Interface Driver");
......@@ -19,7 +19,6 @@
#include <linux/platform_data/spi-s3c64xx.h>
#define MAX_SPI_PORTS 12
#define S3C64XX_SPI_QUIRK_POLL (1 << 0)
#define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1)
#define AUTOSUSPEND_TIMEOUT 2000
......@@ -59,6 +58,8 @@
#define S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD (1<<17)
#define S3C64XX_SPI_MODE_BUS_TSZ_WORD (2<<17)
#define S3C64XX_SPI_MODE_BUS_TSZ_MASK (3<<17)
#define S3C64XX_SPI_MODE_RX_RDY_LVL GENMASK(16, 11)
#define S3C64XX_SPI_MODE_RX_RDY_LVL_SHIFT 11
#define S3C64XX_SPI_MODE_SELF_LOOPBACK (1<<3)
#define S3C64XX_SPI_MODE_RXDMA_ON (1<<2)
#define S3C64XX_SPI_MODE_TXDMA_ON (1<<1)
......@@ -115,8 +116,10 @@
#define S3C64XX_SPI_TRAILCNT S3C64XX_SPI_MAX_TRAILCNT
#define S3C64XX_SPI_POLLING_SIZE 32
#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
#define is_polling(x) (x->port_conf->quirks & S3C64XX_SPI_QUIRK_POLL)
#define is_polling(x) (x->cntrlr_info->polling)
#define RXBUSY (1<<2)
#define TXBUSY (1<<3)
......@@ -553,7 +556,7 @@ static int s3c64xx_wait_for_dma(struct s3c64xx_spi_driver_data *sdd,
}
static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd,
struct spi_transfer *xfer)
struct spi_transfer *xfer, bool use_irq)
{
void __iomem *regs = sdd->regs;
unsigned long val;
......@@ -562,11 +565,24 @@ static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd,
u32 cpy_len;
u8 *buf;
int ms;
unsigned long time_us;
/* millisecs to xfer 'len' bytes @ 'cur_speed' */
ms = xfer->len * 8 * 1000 / sdd->cur_speed;
/* microsecs to xfer 'len' bytes @ 'cur_speed' */
time_us = (xfer->len * 8 * 1000 * 1000) / sdd->cur_speed;
ms = (time_us / 1000);
ms += 10; /* some tolerance */
/* sleep during signal transfer time */
status = readl(regs + S3C64XX_SPI_STATUS);
if (RX_FIFO_LVL(status, sdd) < xfer->len)
usleep_range(time_us / 2, time_us);
if (use_irq) {
val = msecs_to_jiffies(ms);
if (!wait_for_completion_timeout(&sdd->xfer_completion, val))
return -EIO;
}
val = msecs_to_loops(ms);
do {
status = readl(regs + S3C64XX_SPI_STATUS);
......@@ -729,10 +745,13 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
void *rx_buf = NULL;
int target_len = 0, origin_len = 0;
int use_dma = 0;
bool use_irq = false;
int status;
u32 speed;
u8 bpw;
unsigned long flags;
u32 rdy_lv;
u32 val;
reinit_completion(&sdd->xfer_completion);
......@@ -753,17 +772,46 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
sdd->rx_dma.ch && sdd->tx_dma.ch) {
use_dma = 1;
} else if (xfer->len > fifo_len) {
} else if (xfer->len >= fifo_len) {
tx_buf = xfer->tx_buf;
rx_buf = xfer->rx_buf;
origin_len = xfer->len;
target_len = xfer->len;
if (xfer->len > fifo_len)
xfer->len = fifo_len;
xfer->len = fifo_len - 1;
}
do {
/* transfer size is greater than 32, change to IRQ mode */
if (!use_dma && xfer->len > S3C64XX_SPI_POLLING_SIZE)
use_irq = true;
if (use_irq) {
reinit_completion(&sdd->xfer_completion);
rdy_lv = xfer->len;
/* Setup RDY_FIFO trigger Level
* RDY_LVL =
* fifo_lvl up to 64 byte -> N bytes
* 128 byte -> RDY_LVL * 2 bytes
* 256 byte -> RDY_LVL * 4 bytes
*/
if (fifo_len == 128)
rdy_lv /= 2;
else if (fifo_len == 256)
rdy_lv /= 4;
val = readl(sdd->regs + S3C64XX_SPI_MODE_CFG);
val &= ~S3C64XX_SPI_MODE_RX_RDY_LVL;
val |= (rdy_lv << S3C64XX_SPI_MODE_RX_RDY_LVL_SHIFT);
writel(val, sdd->regs + S3C64XX_SPI_MODE_CFG);
/* Enable FIFO_RDY_EN IRQ */
val = readl(sdd->regs + S3C64XX_SPI_INT_EN);
writel((val | S3C64XX_SPI_INT_RX_FIFORDY_EN),
sdd->regs + S3C64XX_SPI_INT_EN);
}
spin_lock_irqsave(&sdd->lock, flags);
/* Pending only which is to be done */
......@@ -785,7 +833,7 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
if (use_dma)
status = s3c64xx_wait_for_dma(sdd, xfer);
else
status = s3c64xx_wait_for_pio(sdd, xfer);
status = s3c64xx_wait_for_pio(sdd, xfer, use_irq);
if (status) {
dev_err(&spi->dev,
......@@ -824,8 +872,8 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master,
if (xfer->rx_buf)
xfer->rx_buf += xfer->len;
if (target_len > fifo_len)
xfer->len = fifo_len;
if (target_len >= fifo_len)
xfer->len = fifo_len - 1;
else
xfer->len = target_len;
}
......@@ -995,6 +1043,14 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
dev_err(&spi->dev, "TX underrun\n");
}
if (val & S3C64XX_SPI_ST_RX_FIFORDY) {
complete(&sdd->xfer_completion);
/* No pending clear irq, turn-off INT_EN_RX_FIFO_RDY */
val = readl(sdd->regs + S3C64XX_SPI_INT_EN);
writel((val & ~S3C64XX_SPI_INT_RX_FIFORDY_EN),
sdd->regs + S3C64XX_SPI_INT_EN);
}
/* Clear the pending irq by setting and then clearing it */
writel(clr, sdd->regs + S3C64XX_SPI_PENDING_CLR);
writel(0, sdd->regs + S3C64XX_SPI_PENDING_CLR);
......@@ -1068,6 +1124,7 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
}
sci->no_cs = of_property_read_bool(dev->of_node, "no-cs-readback");
sci->polling = !of_property_present(dev->of_node, "dmas");
return sci;
}
......@@ -1103,29 +1160,23 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
return PTR_ERR(sci);
}
if (!sci) {
dev_err(&pdev->dev, "platform_data missing!\n");
return -ENODEV;
}
if (!sci)
return dev_err_probe(&pdev->dev, -ENODEV,
"Platform_data missing!\n");
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (mem_res == NULL) {
dev_err(&pdev->dev, "Unable to get SPI MEM resource\n");
return -ENXIO;
}
if (!mem_res)
return dev_err_probe(&pdev->dev, -ENXIO,
"Unable to get SPI MEM resource\n");
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_warn(&pdev->dev, "Failed to get IRQ: %d\n", irq);
return irq;
}
if (irq < 0)
return dev_err_probe(&pdev->dev, irq, "Failed to get IRQ\n");
master = spi_alloc_master(&pdev->dev,
sizeof(struct s3c64xx_spi_driver_data));
if (master == NULL) {
dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
return -ENOMEM;
}
master = devm_spi_alloc_master(&pdev->dev, sizeof(*sdd));
if (!master)
return dev_err_probe(&pdev->dev, -ENOMEM,
"Unable to allocate SPI Master\n");
platform_set_drvdata(pdev, master);
......@@ -1137,11 +1188,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
sdd->sfr_start = mem_res->start;
if (pdev->dev.of_node) {
ret = of_alias_get_id(pdev->dev.of_node, "spi");
if (ret < 0) {
dev_err(&pdev->dev, "failed to get alias id, errno %d\n",
ret);
goto err_deref_master;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"Failed to get alias id\n");
sdd->port_id = ret;
} else {
sdd->port_id = pdev->id;
......@@ -1175,59 +1224,31 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
master->can_dma = s3c64xx_spi_can_dma;
sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res);
if (IS_ERR(sdd->regs)) {
ret = PTR_ERR(sdd->regs);
goto err_deref_master;
}
if (IS_ERR(sdd->regs))
return PTR_ERR(sdd->regs);
if (sci->cfg_gpio && sci->cfg_gpio()) {
dev_err(&pdev->dev, "Unable to config gpio\n");
ret = -EBUSY;
goto err_deref_master;
}
if (sci->cfg_gpio && sci->cfg_gpio())
return dev_err_probe(&pdev->dev, -EBUSY,
"Unable to config gpio\n");
/* Setup clocks */
sdd->clk = devm_clk_get(&pdev->dev, "spi");
if (IS_ERR(sdd->clk)) {
dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
ret = PTR_ERR(sdd->clk);
goto err_deref_master;
}
ret = clk_prepare_enable(sdd->clk);
if (ret) {
dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
goto err_deref_master;
}
sdd->clk = devm_clk_get_enabled(&pdev->dev, "spi");
if (IS_ERR(sdd->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(sdd->clk),
"Unable to acquire clock 'spi'\n");
sprintf(clk_name, "spi_busclk%d", sci->src_clk_nr);
sdd->src_clk = devm_clk_get(&pdev->dev, clk_name);
if (IS_ERR(sdd->src_clk)) {
dev_err(&pdev->dev,
"Unable to acquire clock '%s'\n", clk_name);
ret = PTR_ERR(sdd->src_clk);
goto err_disable_clk;
}
ret = clk_prepare_enable(sdd->src_clk);
if (ret) {
dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name);
goto err_disable_clk;
}
sdd->src_clk = devm_clk_get_enabled(&pdev->dev, clk_name);
if (IS_ERR(sdd->src_clk))
return dev_err_probe(&pdev->dev, PTR_ERR(sdd->src_clk),
"Unable to acquire clock '%s'\n",
clk_name);
if (sdd->port_conf->clk_ioclk) {
sdd->ioclk = devm_clk_get(&pdev->dev, "spi_ioclk");
if (IS_ERR(sdd->ioclk)) {
dev_err(&pdev->dev, "Unable to acquire 'ioclk'\n");
ret = PTR_ERR(sdd->ioclk);
goto err_disable_src_clk;
}
ret = clk_prepare_enable(sdd->ioclk);
if (ret) {
dev_err(&pdev->dev, "Couldn't enable clock 'ioclk'\n");
goto err_disable_src_clk;
}
sdd->ioclk = devm_clk_get_enabled(&pdev->dev, "spi_ioclk");
if (IS_ERR(sdd->ioclk))
return dev_err_probe(&pdev->dev, PTR_ERR(sdd->ioclk),
"Unable to acquire 'ioclk'\n");
}
pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
......@@ -1275,14 +1296,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
clk_disable_unprepare(sdd->ioclk);
err_disable_src_clk:
clk_disable_unprepare(sdd->src_clk);
err_disable_clk:
clk_disable_unprepare(sdd->clk);
err_deref_master:
spi_master_put(master);
return ret;
}
......@@ -1300,12 +1313,6 @@ static void s3c64xx_spi_remove(struct platform_device *pdev)
dma_release_channel(sdd->tx_dma.ch);
}
clk_disable_unprepare(sdd->ioclk);
clk_disable_unprepare(sdd->src_clk);
clk_disable_unprepare(sdd->clk);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
......
......@@ -337,7 +337,7 @@ static struct i2c_driver sc18is602_driver = {
.name = "sc18is602",
.of_match_table = of_match_ptr(sc18is602_of_match),
},
.probe_new = sc18is602_probe,
.probe = sc18is602_probe,
.id_table = sc18is602_id,
};
......
......@@ -526,7 +526,7 @@ static int f_ospi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
static bool f_ospi_supports_op_width(struct spi_mem *mem,
const struct spi_mem_op *op)
{
u8 width_available[] = { 0, 1, 2, 4, 8 };
static const u8 width_available[] = { 0, 1, 2, 4, 8 };
u8 width_op[] = { op->cmd.buswidth, op->addr.buswidth,
op->dummy.buswidth, op->data.buswidth };
bool is_match_found;
......@@ -566,7 +566,7 @@ static bool f_ospi_supports_op(struct spi_mem *mem,
static int f_ospi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
{
op->data.nbytes = min((int)op->data.nbytes, (int)(OSPI_DAT_SIZE_MAX));
op->data.nbytes = min_t(int, op->data.nbytes, OSPI_DAT_SIZE_MAX);
return 0;
}
......@@ -634,18 +634,12 @@ static int f_ospi_probe(struct platform_device *pdev)
goto err_put_ctlr;
}
ospi->clk = devm_clk_get(dev, NULL);
ospi->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(ospi->clk)) {
ret = PTR_ERR(ospi->clk);
goto err_put_ctlr;
}
ret = clk_prepare_enable(ospi->clk);
if (ret) {
dev_err(dev, "Failed to enable the clock\n");
goto err_disable_clk;
}
mutex_init(&ospi->mlock);
ret = f_ospi_init(ospi);
......@@ -661,9 +655,6 @@ static int f_ospi_probe(struct platform_device *pdev)
err_destroy_mutex:
mutex_destroy(&ospi->mlock);
err_disable_clk:
clk_disable_unprepare(ospi->clk);
err_put_ctlr:
spi_controller_put(ctlr);
......@@ -674,8 +665,6 @@ static void f_ospi_remove(struct platform_device *pdev)
{
struct f_ospi *ospi = platform_get_drvdata(pdev);
clk_disable_unprepare(ospi->clk);
mutex_destroy(&ospi->mlock);
}
......
// SPDX-License-Identifier: GPL-2.0
//
// STMicroelectronics STM32 SPI Controller driver (master mode only)
// STMicroelectronics STM32 SPI Controller driver
//
// Copyright (C) 2017, STMicroelectronics - All Rights Reserved
// Author(s): Amelie Delaunay <amelie.delaunay@st.com> for STMicroelectronics.
......@@ -117,6 +117,7 @@
#define STM32H7_SPI_CFG2_CPHA BIT(24)
#define STM32H7_SPI_CFG2_CPOL BIT(25)
#define STM32H7_SPI_CFG2_SSM BIT(26)
#define STM32H7_SPI_CFG2_SSIOP BIT(28)
#define STM32H7_SPI_CFG2_AFCNTR BIT(31)
/* STM32H7_SPI_IER bit fields */
......@@ -170,6 +171,10 @@
*/
#define SPI_DMA_MIN_BYTES 16
/* STM32 SPI driver helpers */
#define STM32_SPI_MASTER_MODE(stm32_spi) (!(stm32_spi)->device_mode)
#define STM32_SPI_DEVICE_MODE(stm32_spi) ((stm32_spi)->device_mode)
/**
* struct stm32_spi_reg - stm32 SPI register & bitfield desc
* @reg: register offset
......@@ -190,6 +195,7 @@ struct stm32_spi_reg {
* @cpol: clock polarity register and polarity bit
* @cpha: clock phase register and phase bit
* @lsb_first: LSB transmitted first register and bit
* @cs_high: chips select active value
* @br: baud rate register and bitfields
* @rx: SPI RX data register
* @tx: SPI TX data register
......@@ -201,6 +207,7 @@ struct stm32_spi_regspec {
const struct stm32_spi_reg cpol;
const struct stm32_spi_reg cpha;
const struct stm32_spi_reg lsb_first;
const struct stm32_spi_reg cs_high;
const struct stm32_spi_reg br;
const struct stm32_spi_reg rx;
const struct stm32_spi_reg tx;
......@@ -258,7 +265,7 @@ struct stm32_spi_cfg {
/**
* struct stm32_spi - private data of the SPI controller
* @dev: driver model representation of the controller
* @master: controller master interface
* @ctrl: controller interface
* @cfg: compatible configuration data
* @base: virtual memory area
* @clk: hw kernel clock feeding the SPI clock generator
......@@ -280,10 +287,11 @@ struct stm32_spi_cfg {
* @dma_tx: dma channel for TX transfer
* @dma_rx: dma channel for RX transfer
* @phys_addr: SPI registers physical base address
* @device_mode: the controller is configured as SPI device
*/
struct stm32_spi {
struct device *dev;
struct spi_master *master;
struct spi_controller *ctrl;
const struct stm32_spi_cfg *cfg;
void __iomem *base;
struct clk *clk;
......@@ -307,6 +315,8 @@ struct stm32_spi {
struct dma_chan *dma_tx;
struct dma_chan *dma_rx;
dma_addr_t phys_addr;
bool device_mode;
};
static const struct stm32_spi_regspec stm32f4_spi_regspec = {
......@@ -318,6 +328,7 @@ static const struct stm32_spi_regspec stm32f4_spi_regspec = {
.cpol = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPOL },
.cpha = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPHA },
.lsb_first = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_LSBFRST },
.cs_high = {},
.br = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_BR, STM32F4_SPI_CR1_BR_SHIFT },
.rx = { STM32F4_SPI_DR },
......@@ -336,6 +347,7 @@ static const struct stm32_spi_regspec stm32h7_spi_regspec = {
.cpol = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPOL },
.cpha = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPHA },
.lsb_first = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_LSBFRST },
.cs_high = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_SSIOP },
.br = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_MBR,
STM32H7_SPI_CFG1_MBR_SHIFT },
......@@ -437,9 +449,9 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz,
div = DIV_ROUND_CLOSEST(spi->clk_rate & ~0x1, speed_hz);
/*
* SPI framework set xfer->speed_hz to master->max_speed_hz if
* xfer->speed_hz is greater than master->max_speed_hz, and it returns
* an error when xfer->speed_hz is lower than master->min_speed_hz, so
* SPI framework set xfer->speed_hz to ctrl->max_speed_hz if
* xfer->speed_hz is greater than ctrl->max_speed_hz, and it returns
* an error when xfer->speed_hz is lower than ctrl->min_speed_hz, so
* no need to check it there.
* However, we need to ensure the following calculations.
*/
......@@ -657,9 +669,9 @@ static void stm32f4_spi_disable(struct stm32_spi *spi)
}
if (spi->cur_usedma && spi->dma_tx)
dmaengine_terminate_all(spi->dma_tx);
dmaengine_terminate_async(spi->dma_tx);
if (spi->cur_usedma && spi->dma_rx)
dmaengine_terminate_all(spi->dma_rx);
dmaengine_terminate_async(spi->dma_rx);
stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE);
......@@ -696,9 +708,9 @@ static void stm32h7_spi_disable(struct stm32_spi *spi)
}
if (spi->cur_usedma && spi->dma_tx)
dmaengine_terminate_all(spi->dma_tx);
dmaengine_terminate_async(spi->dma_tx);
if (spi->cur_usedma && spi->dma_rx)
dmaengine_terminate_all(spi->dma_rx);
dmaengine_terminate_async(spi->dma_rx);
stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE);
......@@ -714,19 +726,19 @@ static void stm32h7_spi_disable(struct stm32_spi *spi)
/**
* stm32_spi_can_dma - Determine if the transfer is eligible for DMA use
* @master: controller master interface
* @ctrl: controller interface
* @spi_dev: pointer to the spi device
* @transfer: pointer to spi transfer
*
* If driver has fifo and the current transfer size is greater than fifo size,
* use DMA. Otherwise use DMA for transfer longer than defined DMA min bytes.
*/
static bool stm32_spi_can_dma(struct spi_master *master,
static bool stm32_spi_can_dma(struct spi_controller *ctrl,
struct spi_device *spi_dev,
struct spi_transfer *transfer)
{
unsigned int dma_size;
struct stm32_spi *spi = spi_master_get_devdata(master);
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
if (spi->cfg->has_fifo)
dma_size = spi->fifo_size;
......@@ -742,12 +754,12 @@ static bool stm32_spi_can_dma(struct spi_master *master,
/**
* stm32f4_spi_irq_event - Interrupt handler for SPI controller events
* @irq: interrupt line
* @dev_id: SPI controller master interface
* @dev_id: SPI controller ctrl interface
*/
static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
{
struct spi_master *master = dev_id;
struct stm32_spi *spi = spi_master_get_devdata(master);
struct spi_controller *ctrl = dev_id;
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
u32 sr, mask = 0;
bool end = false;
......@@ -830,14 +842,14 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
/**
* stm32f4_spi_irq_thread - Thread of interrupt handler for SPI controller
* @irq: interrupt line
* @dev_id: SPI controller master interface
* @dev_id: SPI controller interface
*/
static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id)
{
struct spi_master *master = dev_id;
struct stm32_spi *spi = spi_master_get_devdata(master);
struct spi_controller *ctrl = dev_id;
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
spi_finalize_current_transfer(master);
spi_finalize_current_transfer(ctrl);
stm32f4_spi_disable(spi);
return IRQ_HANDLED;
......@@ -846,12 +858,12 @@ static irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id)
/**
* stm32h7_spi_irq_thread - Thread of interrupt handler for SPI controller
* @irq: interrupt line
* @dev_id: SPI controller master interface
* @dev_id: SPI controller interface
*/
static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
{
struct spi_master *master = dev_id;
struct stm32_spi *spi = spi_master_get_devdata(master);
struct spi_controller *ctrl = dev_id;
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
u32 sr, ier, mask;
unsigned long flags;
bool end = false;
......@@ -931,7 +943,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
if (end) {
stm32h7_spi_disable(spi);
spi_finalize_current_transfer(master);
spi_finalize_current_transfer(ctrl);
}
return IRQ_HANDLED;
......@@ -939,13 +951,13 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)
/**
* stm32_spi_prepare_msg - set up the controller to transfer a single message
* @master: controller master interface
* @ctrl: controller interface
* @msg: pointer to spi message
*/
static int stm32_spi_prepare_msg(struct spi_master *master,
static int stm32_spi_prepare_msg(struct spi_controller *ctrl,
struct spi_message *msg)
{
struct stm32_spi *spi = spi_master_get_devdata(master);
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
struct spi_device *spi_dev = msg->spi;
struct device_node *np = spi_dev->dev.of_node;
unsigned long flags;
......@@ -971,6 +983,11 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
else
clrb |= spi->cfg->regs->lsb_first.mask;
if (STM32_SPI_DEVICE_MODE(spi) && spi_dev->mode & SPI_CS_HIGH)
setb |= spi->cfg->regs->cs_high.mask;
else
clrb |= spi->cfg->regs->cs_high.mask;
dev_dbg(spi->dev, "cpol=%d cpha=%d lsb_first=%d cs_high=%d\n",
!!(spi_dev->mode & SPI_CPOL),
!!(spi_dev->mode & SPI_CPHA),
......@@ -984,9 +1001,9 @@ static int stm32_spi_prepare_msg(struct spi_master *master,
if (spi->cfg->set_number_of_data) {
int ret;
ret = spi_split_transfers_maxwords(master, msg,
STM32H7_SPI_TSIZE_MAX,
GFP_KERNEL | GFP_DMA);
ret = spi_split_transfers_maxsize(ctrl, msg,
STM32H7_SPI_TSIZE_MAX,
GFP_KERNEL | GFP_DMA);
if (ret)
return ret;
}
......@@ -1016,7 +1033,7 @@ static void stm32f4_spi_dma_tx_cb(void *data)
struct stm32_spi *spi = data;
if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) {
spi_finalize_current_transfer(spi->master);
spi_finalize_current_transfer(spi->ctrl);
stm32f4_spi_disable(spi);
}
}
......@@ -1031,7 +1048,7 @@ static void stm32_spi_dma_rx_cb(void *data)
{
struct stm32_spi *spi = data;
spi_finalize_current_transfer(spi->master);
spi_finalize_current_transfer(spi->ctrl);
spi->cfg->disable(spi);
}
......@@ -1161,7 +1178,8 @@ static int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi)
if (spi->tx_buf)
stm32h7_spi_write_txfifo(spi);
stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART);
if (STM32_SPI_MASTER_MODE(spi))
stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART);
writel_relaxed(ier, spi->base + STM32H7_SPI_IER);
......@@ -1208,7 +1226,8 @@ static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi)
stm32_spi_enable(spi);
stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART);
if (STM32_SPI_MASTER_MODE(spi))
stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART);
}
/**
......@@ -1302,7 +1321,7 @@ static int stm32_spi_transfer_one_dma(struct stm32_spi *spi,
dma_submit_error:
if (spi->dma_rx)
dmaengine_terminate_all(spi->dma_rx);
dmaengine_terminate_sync(spi->dma_rx);
dma_desc_error:
stm32_spi_clr_bits(spi, spi->cfg->regs->dma_rx_en.reg,
......@@ -1536,16 +1555,18 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
spi->cfg->set_bpw(spi);
/* Update spi->cur_speed with real clock speed */
mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz,
spi->cfg->baud_rate_div_min,
spi->cfg->baud_rate_div_max);
if (mbr < 0) {
ret = mbr;
goto out;
}
if (STM32_SPI_MASTER_MODE(spi)) {
mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz,
spi->cfg->baud_rate_div_min,
spi->cfg->baud_rate_div_max);
if (mbr < 0) {
ret = mbr;
goto out;
}
transfer->speed_hz = spi->cur_speed;
stm32_spi_set_mbr(spi, mbr);
transfer->speed_hz = spi->cur_speed;
stm32_spi_set_mbr(spi, mbr);
}
comm_type = stm32_spi_communication_type(spi_dev, transfer);
ret = spi->cfg->set_mode(spi, comm_type);
......@@ -1554,7 +1575,7 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
spi->cur_comm = comm_type;
if (spi->cfg->set_data_idleness)
if (STM32_SPI_MASTER_MODE(spi) && spi->cfg->set_data_idleness)
spi->cfg->set_data_idleness(spi, transfer->len);
if (spi->cur_bpw <= 8)
......@@ -1575,7 +1596,8 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
dev_dbg(spi->dev,
"data frame of %d-bit, data packet of %d data frames\n",
spi->cur_bpw, spi->cur_fthlv);
dev_dbg(spi->dev, "speed set to %dHz\n", spi->cur_speed);
if (STM32_SPI_MASTER_MODE(spi))
dev_dbg(spi->dev, "speed set to %dHz\n", spi->cur_speed);
dev_dbg(spi->dev, "transfer of %d bytes (%d data frames)\n",
spi->cur_xferlen, nb_words);
dev_dbg(spi->dev, "dma %s\n",
......@@ -1589,18 +1611,18 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
/**
* stm32_spi_transfer_one - transfer a single spi_transfer
* @master: controller master interface
* @ctrl: controller interface
* @spi_dev: pointer to the spi device
* @transfer: pointer to spi transfer
*
* It must return 0 if the transfer is finished or 1 if the transfer is still
* in progress.
*/
static int stm32_spi_transfer_one(struct spi_master *master,
static int stm32_spi_transfer_one(struct spi_controller *ctrl,
struct spi_device *spi_dev,
struct spi_transfer *transfer)
{
struct stm32_spi *spi = spi_master_get_devdata(master);
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
int ret;
spi->tx_buf = transfer->tx_buf;
......@@ -1608,8 +1630,8 @@ static int stm32_spi_transfer_one(struct spi_master *master,
spi->tx_len = spi->tx_buf ? transfer->len : 0;
spi->rx_len = spi->rx_buf ? transfer->len : 0;
spi->cur_usedma = (master->can_dma &&
master->can_dma(master, spi_dev, transfer));
spi->cur_usedma = (ctrl->can_dma &&
ctrl->can_dma(ctrl, spi_dev, transfer));
ret = stm32_spi_transfer_one_setup(spi, spi_dev, transfer);
if (ret) {
......@@ -1625,13 +1647,13 @@ static int stm32_spi_transfer_one(struct spi_master *master,
/**
* stm32_spi_unprepare_msg - relax the hardware
* @master: controller master interface
* @ctrl: controller interface
* @msg: pointer to the spi message
*/
static int stm32_spi_unprepare_msg(struct spi_master *master,
static int stm32_spi_unprepare_msg(struct spi_controller *ctrl,
struct spi_message *msg)
{
struct stm32_spi *spi = spi_master_get_devdata(master);
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
spi->cfg->disable(spi);
......@@ -1670,12 +1692,13 @@ static int stm32f4_spi_config(struct stm32_spi *spi)
}
/**
* stm32h7_spi_config - Configure SPI controller as SPI master
* stm32h7_spi_config - Configure SPI controller
* @spi: pointer to the spi controller data structure
*/
static int stm32h7_spi_config(struct stm32_spi *spi)
{
unsigned long flags;
u32 cr1 = 0, cfg2 = 0;
spin_lock_irqsave(&spi->lock, flags);
......@@ -1683,24 +1706,28 @@ static int stm32h7_spi_config(struct stm32_spi *spi)
stm32_spi_clr_bits(spi, STM32H7_SPI_I2SCFGR,
STM32H7_SPI_I2SCFGR_I2SMOD);
/*
* - SS input value high
* - transmitter half duplex direction
* - automatic communication suspend when RX-Fifo is full
*/
stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SSI |
STM32H7_SPI_CR1_HDDIR |
STM32H7_SPI_CR1_MASRX);
if (STM32_SPI_DEVICE_MODE(spi)) {
/* Use native device select */
cfg2 &= ~STM32H7_SPI_CFG2_SSM;
} else {
/*
* - Transmitter half duplex direction
* - Automatic communication suspend when RX-Fifo is full
* - SS input value high
*/
cr1 |= STM32H7_SPI_CR1_HDDIR | STM32H7_SPI_CR1_MASRX | STM32H7_SPI_CR1_SSI;
/*
* - Set the master mode (default Motorola mode)
* - Consider 1 master/n slaves configuration and
* SS input value is determined by the SSI bit
* - keep control of all associated GPIOs
*/
stm32_spi_set_bits(spi, STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_MASTER |
STM32H7_SPI_CFG2_SSM |
STM32H7_SPI_CFG2_AFCNTR);
/*
* - Set the master mode (default Motorola mode)
* - Consider 1 master/n devices configuration and
* SS input value is determined by the SSI bit
* - keep control of all associated GPIOs
*/
cfg2 |= STM32H7_SPI_CFG2_MASTER | STM32H7_SPI_CFG2_SSM | STM32H7_SPI_CFG2_AFCNTR;
}
stm32_spi_set_bits(spi, STM32H7_SPI_CR1, cr1);
stm32_spi_set_bits(spi, STM32H7_SPI_CFG2, cfg2);
spin_unlock_irqrestore(&spi->lock, flags);
......@@ -1756,24 +1783,38 @@ static const struct of_device_id stm32_spi_of_match[] = {
};
MODULE_DEVICE_TABLE(of, stm32_spi_of_match);
static int stm32h7_spi_device_abort(struct spi_controller *ctrl)
{
spi_finalize_current_transfer(ctrl);
return 0;
}
static int stm32_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct spi_controller *ctrl;
struct stm32_spi *spi;
struct resource *res;
struct reset_control *rst;
struct device_node *np = pdev->dev.of_node;
bool device_mode;
int ret;
master = devm_spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi));
if (!master) {
dev_err(&pdev->dev, "spi master allocation failed\n");
device_mode = of_property_read_bool(np, "spi-slave");
if (device_mode)
ctrl = devm_spi_alloc_slave(&pdev->dev, sizeof(struct stm32_spi));
else
ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi));
if (!ctrl) {
dev_err(&pdev->dev, "spi controller allocation failed\n");
return -ENOMEM;
}
platform_set_drvdata(pdev, master);
platform_set_drvdata(pdev, ctrl);
spi = spi_master_get_devdata(master);
spi = spi_controller_get_devdata(ctrl);
spi->dev = &pdev->dev;
spi->master = master;
spi->ctrl = ctrl;
spi->device_mode = device_mode;
spin_lock_init(&spi->lock);
spi->cfg = (const struct stm32_spi_cfg *)
......@@ -1794,7 +1835,7 @@ static int stm32_spi_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(&pdev->dev, spi->irq,
spi->cfg->irq_handler_event,
spi->cfg->irq_handler_thread,
IRQF_ONESHOT, pdev->name, master);
IRQF_ONESHOT, pdev->name, ctrl);
if (ret) {
dev_err(&pdev->dev, "irq%d request failed: %d\n", spi->irq,
ret);
......@@ -1843,19 +1884,21 @@ static int stm32_spi_probe(struct platform_device *pdev)
goto err_clk_disable;
}
master->dev.of_node = pdev->dev.of_node;
master->auto_runtime_pm = true;
master->bus_num = pdev->id;
master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST |
SPI_3WIRE;
master->bits_per_word_mask = spi->cfg->get_bpw_mask(spi);
master->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min;
master->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max;
master->use_gpio_descriptors = true;
master->prepare_message = stm32_spi_prepare_msg;
master->transfer_one = stm32_spi_transfer_one;
master->unprepare_message = stm32_spi_unprepare_msg;
master->flags = spi->cfg->flags;
ctrl->dev.of_node = pdev->dev.of_node;
ctrl->auto_runtime_pm = true;
ctrl->bus_num = pdev->id;
ctrl->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST |
SPI_3WIRE;
ctrl->bits_per_word_mask = spi->cfg->get_bpw_mask(spi);
ctrl->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min;
ctrl->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max;
ctrl->use_gpio_descriptors = true;
ctrl->prepare_message = stm32_spi_prepare_msg;
ctrl->transfer_one = stm32_spi_transfer_one;
ctrl->unprepare_message = stm32_spi_unprepare_msg;
ctrl->flags = spi->cfg->flags;
if (STM32_SPI_DEVICE_MODE(spi))
ctrl->slave_abort = stm32h7_spi_device_abort;
spi->dma_tx = dma_request_chan(spi->dev, "tx");
if (IS_ERR(spi->dma_tx)) {
......@@ -1866,7 +1909,7 @@ static int stm32_spi_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "failed to request tx dma channel\n");
} else {
master->dma_tx = spi->dma_tx;
ctrl->dma_tx = spi->dma_tx;
}
spi->dma_rx = dma_request_chan(spi->dev, "rx");
......@@ -1878,11 +1921,11 @@ static int stm32_spi_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "failed to request rx dma channel\n");
} else {
master->dma_rx = spi->dma_rx;
ctrl->dma_rx = spi->dma_rx;
}
if (spi->dma_tx || spi->dma_rx)
master->can_dma = stm32_spi_can_dma;
ctrl->can_dma = stm32_spi_can_dma;
pm_runtime_set_autosuspend_delay(&pdev->dev,
STM32_SPI_AUTOSUSPEND_DELAY);
......@@ -1891,9 +1934,9 @@ static int stm32_spi_probe(struct platform_device *pdev)
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = spi_register_master(master);
ret = spi_register_controller(ctrl);
if (ret) {
dev_err(&pdev->dev, "spi master registration failed: %d\n",
dev_err(&pdev->dev, "spi controller registration failed: %d\n",
ret);
goto err_pm_disable;
}
......@@ -1901,7 +1944,8 @@ static int stm32_spi_probe(struct platform_device *pdev)
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
dev_info(&pdev->dev, "driver initialized\n");
dev_info(&pdev->dev, "driver initialized (%s mode)\n",
STM32_SPI_MASTER_MODE(spi) ? "master" : "device");
return 0;
......@@ -1923,12 +1967,12 @@ static int stm32_spi_probe(struct platform_device *pdev)
static void stm32_spi_remove(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct stm32_spi *spi = spi_master_get_devdata(master);
struct spi_controller *ctrl = platform_get_drvdata(pdev);
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
pm_runtime_get_sync(&pdev->dev);
spi_unregister_master(master);
spi_unregister_controller(ctrl);
spi->cfg->disable(spi);
pm_runtime_disable(&pdev->dev);
......@@ -1936,10 +1980,10 @@ static void stm32_spi_remove(struct platform_device *pdev)
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
if (master->dma_tx)
dma_release_channel(master->dma_tx);
if (master->dma_rx)
dma_release_channel(master->dma_rx);
if (ctrl->dma_tx)
dma_release_channel(ctrl->dma_tx);
if (ctrl->dma_rx)
dma_release_channel(ctrl->dma_rx);
clk_disable_unprepare(spi->clk);
......@@ -1949,8 +1993,8 @@ static void stm32_spi_remove(struct platform_device *pdev)
static int __maybe_unused stm32_spi_runtime_suspend(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct stm32_spi *spi = spi_master_get_devdata(master);
struct spi_controller *ctrl = dev_get_drvdata(dev);
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
clk_disable_unprepare(spi->clk);
......@@ -1959,8 +2003,8 @@ static int __maybe_unused stm32_spi_runtime_suspend(struct device *dev)
static int __maybe_unused stm32_spi_runtime_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct stm32_spi *spi = spi_master_get_devdata(master);
struct spi_controller *ctrl = dev_get_drvdata(dev);
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
int ret;
ret = pinctrl_pm_select_default_state(dev);
......@@ -1972,10 +2016,10 @@ static int __maybe_unused stm32_spi_runtime_resume(struct device *dev)
static int __maybe_unused stm32_spi_suspend(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct spi_controller *ctrl = dev_get_drvdata(dev);
int ret;
ret = spi_master_suspend(master);
ret = spi_controller_suspend(ctrl);
if (ret)
return ret;
......@@ -1984,15 +2028,15 @@ static int __maybe_unused stm32_spi_suspend(struct device *dev)
static int __maybe_unused stm32_spi_resume(struct device *dev)
{
struct spi_master *master = dev_get_drvdata(dev);
struct stm32_spi *spi = spi_master_get_devdata(master);
struct spi_controller *ctrl = dev_get_drvdata(dev);
struct stm32_spi *spi = spi_controller_get_devdata(ctrl);
int ret;
ret = pm_runtime_force_resume(dev);
if (ret)
return ret;
ret = spi_master_resume(master);
ret = spi_controller_resume(ctrl);
if (ret) {
clk_disable_unprepare(spi->clk);
return ret;
......
......@@ -42,7 +42,9 @@
#define SUN6I_TFR_CTL_CS_MANUAL BIT(6)
#define SUN6I_TFR_CTL_CS_LEVEL BIT(7)
#define SUN6I_TFR_CTL_DHB BIT(8)
#define SUN6I_TFR_CTL_SDC BIT(11)
#define SUN6I_TFR_CTL_FBS BIT(12)
#define SUN6I_TFR_CTL_SDM BIT(13)
#define SUN6I_TFR_CTL_XCH BIT(31)
#define SUN6I_INT_CTL_REG 0x10
......@@ -85,6 +87,11 @@
#define SUN6I_TXDATA_REG 0x200
#define SUN6I_RXDATA_REG 0x300
struct sun6i_spi_cfg {
unsigned long fifo_depth;
bool has_clk_ctl;
};
struct sun6i_spi {
struct spi_master *master;
void __iomem *base_addr;
......@@ -99,7 +106,7 @@ struct sun6i_spi {
const u8 *tx_buf;
u8 *rx_buf;
int len;
unsigned long fifo_depth;
const struct sun6i_spi_cfg *cfg;
};
static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
......@@ -156,7 +163,7 @@ static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi)
u8 byte;
/* See how much data we can fit */
cnt = sspi->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi);
cnt = sspi->cfg->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi);
len = min((int)cnt, sspi->len);
......@@ -256,7 +263,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
struct spi_transfer *tfr)
{
struct sun6i_spi *sspi = spi_master_get_devdata(master);
unsigned int mclk_rate, div, div_cdr1, div_cdr2, timeout;
unsigned int div, div_cdr1, div_cdr2, timeout;
unsigned int start, end, tx_time;
unsigned int trig_level;
unsigned int tx_len = 0, rx_len = 0;
......@@ -289,14 +296,14 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
* the hardcoded value used in old generation of Allwinner
* SPI controller. (See spi-sun4i.c)
*/
trig_level = sspi->fifo_depth / 4 * 3;
trig_level = sspi->cfg->fifo_depth / 4 * 3;
} else {
/*
* Setup FIFO DMA request trigger level
* We choose 1/2 of the full fifo depth, that value will
* be used as DMA burst length.
*/
trig_level = sspi->fifo_depth / 2;
trig_level = sspi->cfg->fifo_depth / 2;
if (tfr->tx_buf)
reg |= SUN6I_FIFO_CTL_TF_DRQ_EN;
......@@ -346,39 +353,65 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
/* Ensure that we have a parent clock fast enough */
mclk_rate = clk_get_rate(sspi->mclk);
if (mclk_rate < (2 * tfr->speed_hz)) {
clk_set_rate(sspi->mclk, 2 * tfr->speed_hz);
mclk_rate = clk_get_rate(sspi->mclk);
}
if (sspi->cfg->has_clk_ctl) {
unsigned int mclk_rate = clk_get_rate(sspi->mclk);
/*
* Setup clock divider.
*
* We have two choices there. Either we can use the clock
* divide rate 1, which is calculated thanks to this formula:
* SPI_CLK = MOD_CLK / (2 ^ cdr)
* Or we can use CDR2, which is calculated with the formula:
* SPI_CLK = MOD_CLK / (2 * (cdr + 1))
* Wether we use the former or the latter is set through the
* DRS bit.
*
* First try CDR2, and if we can't reach the expected
* frequency, fall back to CDR1.
*/
div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz);
div_cdr2 = DIV_ROUND_UP(div_cdr1, 2);
if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS;
tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2);
/* Ensure that we have a parent clock fast enough */
if (mclk_rate < (2 * tfr->speed_hz)) {
clk_set_rate(sspi->mclk, 2 * tfr->speed_hz);
mclk_rate = clk_get_rate(sspi->mclk);
}
/*
* Setup clock divider.
*
* We have two choices there. Either we can use the clock
* divide rate 1, which is calculated thanks to this formula:
* SPI_CLK = MOD_CLK / (2 ^ cdr)
* Or we can use CDR2, which is calculated with the formula:
* SPI_CLK = MOD_CLK / (2 * (cdr + 1))
* Wether we use the former or the latter is set through the
* DRS bit.
*
* First try CDR2, and if we can't reach the expected
* frequency, fall back to CDR1.
*/
div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz);
div_cdr2 = DIV_ROUND_UP(div_cdr1, 2);
if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS;
tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2);
} else {
div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1));
reg = SUN6I_CLK_CTL_CDR1(div);
tfr->effective_speed_hz = mclk_rate / (1 << div);
}
sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
} else {
div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1));
reg = SUN6I_CLK_CTL_CDR1(div);
tfr->effective_speed_hz = mclk_rate / (1 << div);
clk_set_rate(sspi->mclk, tfr->speed_hz);
tfr->effective_speed_hz = clk_get_rate(sspi->mclk);
/*
* Configure work mode.
*
* There are three work modes depending on the controller clock
* frequency:
* - normal sample mode : CLK <= 24MHz SDM=1 SDC=0
* - delay half-cycle sample mode : CLK <= 40MHz SDM=0 SDC=0
* - delay one-cycle sample mode : CLK >= 80MHz SDM=0 SDC=1
*/
reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
reg &= ~(SUN6I_TFR_CTL_SDM | SUN6I_TFR_CTL_SDC);
if (tfr->effective_speed_hz <= 24000000)
reg |= SUN6I_TFR_CTL_SDM;
else if (tfr->effective_speed_hz >= 80000000)
reg |= SUN6I_TFR_CTL_SDC;
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg);
}
sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
/* Finally enable the bus - doing so before might raise SCK to HIGH */
reg = sun6i_spi_read(sspi, SUN6I_GBL_CTL_REG);
reg |= SUN6I_GBL_CTL_BUS_ENABLE;
......@@ -410,9 +443,9 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
reg = SUN6I_INT_CTL_TC;
if (!use_dma) {
if (rx_len > sspi->fifo_depth)
if (rx_len > sspi->cfg->fifo_depth)
reg |= SUN6I_INT_CTL_RF_RDY;
if (tx_len > sspi->fifo_depth)
if (tx_len > sspi->cfg->fifo_depth)
reg |= SUN6I_INT_CTL_TF_ERQ;
}
......@@ -422,7 +455,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
tx_time = spi_controller_xfer_timeout(master, tfr);
start = jiffies;
timeout = wait_for_completion_timeout(&sspi->done,
msecs_to_jiffies(tx_time));
......@@ -543,7 +576,7 @@ static bool sun6i_spi_can_dma(struct spi_master *master,
* the fifo length we can just fill the fifo and wait for a single
* irq, so don't bother setting up dma
*/
return xfer->len > sspi->fifo_depth;
return xfer->len > sspi->cfg->fifo_depth;
}
static int sun6i_spi_probe(struct platform_device *pdev)
......@@ -582,7 +615,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
}
sspi->master = master;
sspi->fifo_depth = (unsigned long)of_device_get_match_data(&pdev->dev);
sspi->cfg = of_device_get_match_data(&pdev->dev);
master->max_speed_hz = 100 * 1000 * 1000;
master->min_speed_hz = 3 * 1000;
......@@ -695,9 +728,27 @@ static void sun6i_spi_remove(struct platform_device *pdev)
dma_release_channel(master->dma_rx);
}
static const struct sun6i_spi_cfg sun6i_a31_spi_cfg = {
.fifo_depth = SUN6I_FIFO_DEPTH,
.has_clk_ctl = true,
};
static const struct sun6i_spi_cfg sun8i_h3_spi_cfg = {
.fifo_depth = SUN8I_FIFO_DEPTH,
.has_clk_ctl = true,
};
static const struct sun6i_spi_cfg sun50i_r329_spi_cfg = {
.fifo_depth = SUN8I_FIFO_DEPTH,
};
static const struct of_device_id sun6i_spi_match[] = {
{ .compatible = "allwinner,sun6i-a31-spi", .data = (void *)SUN6I_FIFO_DEPTH },
{ .compatible = "allwinner,sun8i-h3-spi", .data = (void *)SUN8I_FIFO_DEPTH },
{ .compatible = "allwinner,sun6i-a31-spi", .data = &sun6i_a31_spi_cfg },
{ .compatible = "allwinner,sun8i-h3-spi", .data = &sun8i_h3_spi_cfg },
{
.compatible = "allwinner,sun50i-r329-spi",
.data = &sun50i_r329_spi_cfg
},
{}
};
MODULE_DEVICE_TABLE(of, sun6i_spi_match);
......
......@@ -241,7 +241,7 @@ static struct i2c_driver spi_xcomm_driver = {
.name = "spi-xcomm",
},
.id_table = spi_xcomm_ids,
.probe_new = spi_xcomm_probe,
.probe = spi_xcomm_probe,
};
module_i2c_driver(spi_xcomm_driver);
......
......@@ -64,7 +64,8 @@ static_assert(N_SPI_MINORS > 0 && N_SPI_MINORS <= 256);
| SPI_NO_CS | SPI_READY | SPI_TX_DUAL \
| SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL \
| SPI_RX_QUAD | SPI_RX_OCTAL \
| SPI_RX_CPHA_FLIP)
| SPI_RX_CPHA_FLIP | SPI_3WIRE_HIZ \
| SPI_MOSI_IDLE_LOW)
struct spidev_data {
dev_t devt;
......
......@@ -36,6 +36,7 @@ struct s3c64xx_spi_info {
int src_clk_nr;
int num_cs;
bool no_cs;
bool polling;
int (*cfg_gpio)(void);
};
......
......@@ -1261,6 +1261,23 @@ static inline bool spi_is_bpw_supported(struct spi_device *spi, u32 bpw)
return false;
}
/**
* spi_controller_xfer_timeout - Compute a suitable timeout value
* @ctlr: SPI device
* @xfer: Transfer descriptor
*
* Compute a relevant timeout value for the given transfer. We derive the time
* that it would take on a single data line and take twice this amount of time
* with a minimum of 500ms to avoid false positives on loaded systems.
*
* Returns: Transfer timeout value in milliseconds.
*/
static inline unsigned int spi_controller_xfer_timeout(struct spi_controller *ctlr,
struct spi_transfer *xfer)
{
return max(xfer->len * 8 * 2 / (xfer->speed_hz / 1000), 500U);
}
/*---------------------------------------------------------------------------*/
/* SPI transfer replacement methods which make use of spi_res */
......
......@@ -28,6 +28,7 @@
#define SPI_RX_OCTAL _BITUL(14) /* receive with 8 wires */
#define SPI_3WIRE_HIZ _BITUL(15) /* high impedance turnaround */
#define SPI_RX_CPHA_FLIP _BITUL(16) /* flip CPHA on Rx only xfer */
#define SPI_MOSI_IDLE_LOW _BITUL(17) /* leave mosi line low when idle */
/*
* All the bits defined above should be covered by SPI_MODE_USER_MASK.
......@@ -37,6 +38,6 @@
* These bits must not overlap. A static assert check should make sure of that.
* If adding extra bits, make sure to increase the bit index below as well.
*/
#define SPI_MODE_USER_MASK (_BITUL(17) - 1)
#define SPI_MODE_USER_MASK (_BITUL(18) - 1)
#endif /* _UAPI_SPI_H */
......@@ -172,28 +172,37 @@ static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
static void print_usage(const char *prog)
{
printf("Usage: %s [-DsbdlHOLC3vpNR24SI]\n", prog);
puts(" -D --device device to use (default /dev/spidev1.1)\n"
" -s --speed max speed (Hz)\n"
" -d --delay delay (usec)\n"
" -b --bpw bits per word\n"
" -i --input input data from a file (e.g. \"test.bin\")\n"
" -o --output output data to a file (e.g. \"results.bin\")\n"
" -l --loop loopback\n"
" -H --cpha clock phase\n"
" -O --cpol clock polarity\n"
" -L --lsb least significant bit first\n"
" -C --cs-high chip select active high\n"
" -3 --3wire SI/SO signals shared\n"
" -v --verbose Verbose (show tx buffer)\n"
" -p Send data (e.g. \"1234\\xde\\xad\")\n"
" -N --no-cs no chip select\n"
" -R --ready slave pulls low to pause\n"
" -2 --dual dual transfer\n"
" -4 --quad quad transfer\n"
" -8 --octal octal transfer\n"
" -S --size transfer size\n"
" -I --iter iterations\n");
printf("Usage: %s [-2348CDFHILMNORSZbdilopsv]\n", prog);
puts("general device settings:\n"
" -D --device device to use (default /dev/spidev1.1)\n"
" -s --speed max speed (Hz)\n"
" -d --delay delay (usec)\n"
" -l --loop loopback\n"
"spi mode:\n"
" -H --cpha clock phase\n"
" -O --cpol clock polarity\n"
" -F --rx-cpha-flip flip CPHA on Rx only xfer\n"
"number of wires for transmission:\n"
" -2 --dual dual transfer\n"
" -4 --quad quad transfer\n"
" -8 --octal octal transfer\n"
" -3 --3wire SI/SO signals shared\n"
" -Z --3wire-hiz high impedance turnaround\n"
"data:\n"
" -i --input input data from a file (e.g. \"test.bin\")\n"
" -o --output output data to a file (e.g. \"results.bin\")\n"
" -p Send data (e.g. \"1234\\xde\\xad\")\n"
" -S --size transfer size\n"
" -I --iter iterations\n"
"additional parameters:\n"
" -b --bpw bits per word\n"
" -L --lsb least significant bit first\n"
" -C --cs-high chip select active high\n"
" -N --no-cs no chip select\n"
" -R --ready slave pulls low to pause\n"
" -M --mosi-idle-low leave mosi line low when idle\n"
"misc:\n"
" -v --verbose Verbose (show tx buffer)\n");
exit(1);
}
......@@ -201,31 +210,34 @@ static void parse_opts(int argc, char *argv[])
{
while (1) {
static const struct option lopts[] = {
{ "device", 1, 0, 'D' },
{ "speed", 1, 0, 's' },
{ "delay", 1, 0, 'd' },
{ "bpw", 1, 0, 'b' },
{ "input", 1, 0, 'i' },
{ "output", 1, 0, 'o' },
{ "loop", 0, 0, 'l' },
{ "cpha", 0, 0, 'H' },
{ "cpol", 0, 0, 'O' },
{ "lsb", 0, 0, 'L' },
{ "cs-high", 0, 0, 'C' },
{ "3wire", 0, 0, '3' },
{ "no-cs", 0, 0, 'N' },
{ "ready", 0, 0, 'R' },
{ "dual", 0, 0, '2' },
{ "verbose", 0, 0, 'v' },
{ "quad", 0, 0, '4' },
{ "octal", 0, 0, '8' },
{ "size", 1, 0, 'S' },
{ "iter", 1, 0, 'I' },
{ "device", 1, 0, 'D' },
{ "speed", 1, 0, 's' },
{ "delay", 1, 0, 'd' },
{ "loop", 0, 0, 'l' },
{ "cpha", 0, 0, 'H' },
{ "cpol", 0, 0, 'O' },
{ "rx-cpha-flip", 0, 0, 'F' },
{ "dual", 0, 0, '2' },
{ "quad", 0, 0, '4' },
{ "octal", 0, 0, '8' },
{ "3wire", 0, 0, '3' },
{ "3wire-hiz", 0, 0, 'Z' },
{ "input", 1, 0, 'i' },
{ "output", 1, 0, 'o' },
{ "size", 1, 0, 'S' },
{ "iter", 1, 0, 'I' },
{ "bpw", 1, 0, 'b' },
{ "lsb", 0, 0, 'L' },
{ "cs-high", 0, 0, 'C' },
{ "no-cs", 0, 0, 'N' },
{ "ready", 0, 0, 'R' },
{ "mosi-idle-low", 0, 0, 'M' },
{ "verbose", 0, 0, 'v' },
{ NULL, 0, 0, 0 },
};
int c;
c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3NR248p:vS:I:",
c = getopt_long(argc, argv, "D:s:d:b:i:o:lHOLC3ZFMNR248p:vS:I:",
lopts, NULL);
if (c == -1)
......@@ -268,6 +280,15 @@ static void parse_opts(int argc, char *argv[])
case '3':
mode |= SPI_3WIRE;
break;
case 'Z':
mode |= SPI_3WIRE_HIZ;
break;
case 'F':
mode |= SPI_RX_CPHA_FLIP;
break;
case 'M':
mode |= SPI_MOSI_IDLE_LOW;
break;
case 'N':
mode |= SPI_NO_CS;
break;
......
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