Commit 4039974f authored by Linus Torvalds's avatar Linus Torvalds

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

Pull spi fixes from Mark Brown:
 "A bunch of driver specific fixes, plus a fix for spi-mem's status
  polling for devices that use GPIO chip selects and a DT bindings
  examples fix that helps with the validation work"

* tag 'spi-fix-v5.19-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
  spi: rockchip: Unmask IRQ at the final to avoid preemption
  spi: dt-bindings: Fix unevaluatedProperties warnings in examples
  spi: spi-mem: Fix spi_mem_poll_status()
  spi: cadence: Detect transmit FIFO depth
  spi: spi-cadence: Fix SPI CS gets toggling sporadically
parents bed05181 419bc8f6
...@@ -47,6 +47,5 @@ examples: ...@@ -47,6 +47,5 @@ examples:
clocks = <&clkcfg CLK_SPI0>; clocks = <&clkcfg CLK_SPI0>;
interrupt-parent = <&plic>; interrupt-parent = <&plic>;
interrupts = <54>; interrupts = <54>;
spi-max-frequency = <25000000>;
}; };
... ...
...@@ -110,7 +110,6 @@ examples: ...@@ -110,7 +110,6 @@ examples:
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&qup_spi1_default>; pinctrl-0 = <&qup_spi1_default>;
interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
spi-max-frequency = <50000000>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
}; };
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
#define CDNS_SPI_BAUD_DIV_SHIFT 3 /* Baud rate divisor shift in CR */ #define CDNS_SPI_BAUD_DIV_SHIFT 3 /* Baud rate divisor shift in CR */
#define CDNS_SPI_SS_SHIFT 10 /* Slave Select field shift in CR */ #define CDNS_SPI_SS_SHIFT 10 /* Slave Select field shift in CR */
#define CDNS_SPI_SS0 0x1 /* Slave Select zero */ #define CDNS_SPI_SS0 0x1 /* Slave Select zero */
#define CDNS_SPI_NOSS 0x3C /* No Slave select */
/* /*
* SPI Interrupt Registers bit Masks * SPI Interrupt Registers bit Masks
...@@ -92,9 +93,6 @@ ...@@ -92,9 +93,6 @@
#define CDNS_SPI_ER_ENABLE 0x00000001 /* SPI Enable Bit Mask */ #define CDNS_SPI_ER_ENABLE 0x00000001 /* SPI Enable Bit Mask */
#define CDNS_SPI_ER_DISABLE 0x0 /* SPI Disable Bit Mask */ #define CDNS_SPI_ER_DISABLE 0x0 /* SPI Disable Bit Mask */
/* SPI FIFO depth in bytes */
#define CDNS_SPI_FIFO_DEPTH 128
/* Default number of chip select lines */ /* Default number of chip select lines */
#define CDNS_SPI_DEFAULT_NUM_CS 4 #define CDNS_SPI_DEFAULT_NUM_CS 4
...@@ -110,6 +108,7 @@ ...@@ -110,6 +108,7 @@
* @rx_bytes: Number of bytes requested * @rx_bytes: Number of bytes requested
* @dev_busy: Device busy flag * @dev_busy: Device busy flag
* @is_decoded_cs: Flag for decoder property set or not * @is_decoded_cs: Flag for decoder property set or not
* @tx_fifo_depth: Depth of the TX FIFO
*/ */
struct cdns_spi { struct cdns_spi {
void __iomem *regs; void __iomem *regs;
...@@ -123,6 +122,7 @@ struct cdns_spi { ...@@ -123,6 +122,7 @@ struct cdns_spi {
int rx_bytes; int rx_bytes;
u8 dev_busy; u8 dev_busy;
u32 is_decoded_cs; u32 is_decoded_cs;
unsigned int tx_fifo_depth;
}; };
/* Macros for the SPI controller read/write */ /* Macros for the SPI controller read/write */
...@@ -304,7 +304,7 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) ...@@ -304,7 +304,7 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi)
{ {
unsigned long trans_cnt = 0; unsigned long trans_cnt = 0;
while ((trans_cnt < CDNS_SPI_FIFO_DEPTH) && while ((trans_cnt < xspi->tx_fifo_depth) &&
(xspi->tx_bytes > 0)) { (xspi->tx_bytes > 0)) {
/* When xspi in busy condition, bytes may send failed, /* When xspi in busy condition, bytes may send failed,
...@@ -450,19 +450,42 @@ static int cdns_prepare_transfer_hardware(struct spi_master *master) ...@@ -450,19 +450,42 @@ static int cdns_prepare_transfer_hardware(struct spi_master *master)
* @master: Pointer to the spi_master structure which provides * @master: Pointer to the spi_master structure which provides
* information about the controller. * information about the controller.
* *
* This function disables the SPI master controller. * This function disables the SPI master controller when no slave selected.
* *
* Return: 0 always * Return: 0 always
*/ */
static int cdns_unprepare_transfer_hardware(struct spi_master *master) static int cdns_unprepare_transfer_hardware(struct spi_master *master)
{ {
struct cdns_spi *xspi = spi_master_get_devdata(master); struct cdns_spi *xspi = spi_master_get_devdata(master);
u32 ctrl_reg;
/* Disable the SPI if slave is deselected */
ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
ctrl_reg = (ctrl_reg & CDNS_SPI_CR_SSCTRL) >> CDNS_SPI_SS_SHIFT;
if (ctrl_reg == CDNS_SPI_NOSS)
cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE);
return 0; return 0;
} }
/**
* cdns_spi_detect_fifo_depth - Detect the FIFO depth of the hardware
* @xspi: Pointer to the cdns_spi structure
*
* The depth of the TX FIFO is a synthesis configuration parameter of the SPI
* IP. The FIFO threshold register is sized so that its maximum value can be the
* FIFO size - 1. This is used to detect the size of the FIFO.
*/
static void cdns_spi_detect_fifo_depth(struct cdns_spi *xspi)
{
/* The MSBs will get truncated giving us the size of the FIFO */
cdns_spi_write(xspi, CDNS_SPI_THLD, 0xffff);
xspi->tx_fifo_depth = cdns_spi_read(xspi, CDNS_SPI_THLD) + 1;
/* Reset to default */
cdns_spi_write(xspi, CDNS_SPI_THLD, 0x1);
}
/** /**
* cdns_spi_probe - Probe method for the SPI driver * cdns_spi_probe - Probe method for the SPI driver
* @pdev: Pointer to the platform_device structure * @pdev: Pointer to the platform_device structure
...@@ -535,6 +558,8 @@ static int cdns_spi_probe(struct platform_device *pdev) ...@@ -535,6 +558,8 @@ static int cdns_spi_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
xspi->is_decoded_cs = 0; xspi->is_decoded_cs = 0;
cdns_spi_detect_fifo_depth(xspi);
/* SPI controller initializations */ /* SPI controller initializations */
cdns_spi_init_hw(xspi); cdns_spi_init_hw(xspi);
......
...@@ -808,7 +808,7 @@ int spi_mem_poll_status(struct spi_mem *mem, ...@@ -808,7 +808,7 @@ int spi_mem_poll_status(struct spi_mem *mem,
op->data.dir != SPI_MEM_DATA_IN) op->data.dir != SPI_MEM_DATA_IN)
return -EINVAL; return -EINVAL;
if (ctlr->mem_ops && ctlr->mem_ops->poll_status) { if (ctlr->mem_ops && ctlr->mem_ops->poll_status && !mem->spi->cs_gpiod) {
ret = spi_mem_access_start(mem); ret = spi_mem_access_start(mem);
if (ret) if (ret)
return ret; return ret;
......
...@@ -381,15 +381,18 @@ static int rockchip_spi_prepare_irq(struct rockchip_spi *rs, ...@@ -381,15 +381,18 @@ static int rockchip_spi_prepare_irq(struct rockchip_spi *rs,
rs->tx_left = rs->tx ? xfer->len / rs->n_bytes : 0; rs->tx_left = rs->tx ? xfer->len / rs->n_bytes : 0;
rs->rx_left = xfer->len / rs->n_bytes; rs->rx_left = xfer->len / rs->n_bytes;
if (rs->cs_inactive) writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);
writel_relaxed(INT_RF_FULL | INT_CS_INACTIVE, rs->regs + ROCKCHIP_SPI_IMR);
else
writel_relaxed(INT_RF_FULL, rs->regs + ROCKCHIP_SPI_IMR);
spi_enable_chip(rs, true); spi_enable_chip(rs, true);
if (rs->tx_left) if (rs->tx_left)
rockchip_spi_pio_writer(rs); rockchip_spi_pio_writer(rs);
if (rs->cs_inactive)
writel_relaxed(INT_RF_FULL | INT_CS_INACTIVE, rs->regs + ROCKCHIP_SPI_IMR);
else
writel_relaxed(INT_RF_FULL, rs->regs + ROCKCHIP_SPI_IMR);
/* 1 means the transfer is in progress */ /* 1 means the transfer is in progress */
return 1; return 1;
} }
......
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