spi: zynqmp-gqspi: Clean up the driver a bit
Subsystems (2)
cover spi: zynqmp-gqspi: Clean up the driver a bit
Here are a few mostly independent cleanups I came up with while writing some other patches. Feel free to apply them in piecemeal if you like.
Sean Anderson (5):
spi: zynqmp-gqspi: Reformat long line
spi: zynqmp-gqspi: Add some more debug prints
spi: zynqmp-gqspi: Add helpers for enabling/disabling DMA
spi: zynqmp-gqspi: Clean up fillgenfifo
spi: zynqmp-gqspi: Always acknowledge interrupts
drivers/spi/spi-zynqmp-gqspi.c | 167 +++++++++++++++------------------ 1 file changed, 76 insertions(+), 91 deletions(-)
Signature · 1 line
2.35.1.1320.gc452695387.dirty
PATCH 1/5 spi: zynqmp-gqspi: Reformat long line
This long line is broken in an unusual place. Reformat it to better match the kernel style.
---
drivers/spi/spi-zynqmp-gqspi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/spi/spi-zynqmp-gqspi.c +2 -2
@@ -1059,8 +1059,8 @@ static unsigned long zynqmp_qspi_timeout(struct zynqmp_qspi *xqspi, u8 bits,static int zynqmp_qspi_exec_op (struct spi_mem *mem,const struct spi_mem_op *op) { -struct zynqmp_qspi *xqspi =spi_controller_get_devdata - (mem->spi->controller); +struct zynqmp_qspi *xqspi = +spi_controller_get_devdata (mem->spi->controller);unsigned long timeout;int err =0 , i;u32 genfifoentry =0 ;
Signature · 1 line
2.35.1.1320.gc452695387.dirty
PATCH 2/5 spi: zynqmp-gqspi: Add some more debug prints
In reply to Sean AndersonAdd a few more debug prints to make it easier to determine how the device is programmed.
---
drivers/spi/spi-zynqmp-gqspi.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/spi/spi-zynqmp-gqspi.c +4 -0
@@ -580,6 +580,8 @@ static int zynqmp_qspi_config_op(struct zynqmp_qspi *xqspi,zynqmp_gqspi_write (xqspi,GQSPI_CONFIG_OFST , config_reg);zynqmp_qspi_set_tapdelay (xqspi, baud_rate_val); } + +dev_dbg (xqspi->dev,"config speed %u\n" , req_speed_hz);return 0 ; }
@@ -693,6 +695,8 @@ static void zynqmp_qspi_fillgenfifo(struct zynqmp_qspi *xqspi, u8 nbits, } genfifoentry |=zynqmp_qspi_selectspimode (xqspi, nbits); xqspi->genfifoentry = genfifoentry; +dev_dbg (xqspi->dev,"genfifo %05x transfer_len %u\n" , + genfifoentry, transfer_len);if ((transfer_len) <GQSPI_GENFIFO_IMM_DATA_MASK ) { genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK ;
Signature · 1 line
2.35.1.1320.gc452695387.dirty
PATCH 3/5 spi: zynqmp-gqspi: Add helpers for enabling/disabling DMA
In reply to Sean AndersonDMA is enabled and disabled several times in the driver. Add some helper functions for this task.
---
drivers/spi/spi-zynqmp-gqspi.c | 61 +++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 27 deletions(-)
drivers/spi/spi-zynqmp-gqspi.c +34 -27
@@ -739,6 +739,33 @@ static void zynqmp_qspi_fillgenfifo(struct zynqmp_qspi *xqspi, u8 nbits, } } +/** +* zynqmp_qspi_disable_dma() - Disable DMA mode +* @xqspi: GQSPI instance +*/ +static void zynqmp_qspi_disable_dma (struct zynqmp_qspi *xqspi) +{ +u32 config_reg =zynqmp_gqspi_read (xqspi,GQSPI_CONFIG_OFST ); + + config_reg &= ~GQSPI_CFG_MODE_EN_MASK ; +zynqmp_gqspi_write (xqspi,GQSPI_CONFIG_OFST , config_reg); + xqspi->mode =GQSPI_MODE_IO ; +} + +/** +* zynqmp_qspi_enable_dma() - Enable DMA mode +* @xqspi: GQSPI instance +*/ +static void zynqmp_qspi_enable_dma (struct zynqmp_qspi *xqspi) +{ +u32 config_reg =zynqmp_gqspi_read (xqspi,GQSPI_CONFIG_OFST ); + + config_reg &= ~GQSPI_CFG_MODE_EN_MASK ; + config_reg |=GQSPI_CFG_MODE_EN_DMA_MASK ; +zynqmp_gqspi_write (xqspi,GQSPI_CONFIG_OFST , config_reg); + xqspi->mode =GQSPI_MODE_DMA ; +} +/** * zynqmp_process_dma_irq - Handler for DMA done interrupt of QSPI * controller
@@ -748,7 +775,7 @@ static void zynqmp_qspi_fillgenfifo(struct zynqmp_qspi *xqspi, u8 nbits,*/ static void zynqmp_process_dma_irq (struct zynqmp_qspi *xqspi) { -u32 config_reg, genfifoentry; +u32 genfifoentry;dma_unmap_single (xqspi->dev, xqspi->dma_addr, xqspi->dma_rx_bytes,DMA_FROM_DEVICE );
@@ -762,9 +789,7 @@ static void zynqmp_process_dma_irq(struct zynqmp_qspi *xqspi)if (xqspi->bytes_to_receive >0 ) {/* Switch to IO mode,for remaining bytes to receive */ - config_reg =zynqmp_gqspi_read (xqspi,GQSPI_CONFIG_OFST ); - config_reg &= ~GQSPI_CFG_MODE_EN_MASK ; -zynqmp_gqspi_write (xqspi,GQSPI_CONFIG_OFST , config_reg); +zynqmp_qspi_disable_dma (xqspi);/* Initiate the transfer of remaining bytes */ genfifoentry = xqspi->genfifoentry;
@@ -849,17 +874,14 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id)*/ static int zynqmp_qspi_setuprxdma (struct zynqmp_qspi *xqspi) { -u32 rx_bytes, rx_rem, config_reg; +u32 rx_bytes, rx_rem;dma_addr_t addr;u64 dma_align = (u64 )(uintptr_t )xqspi->rxbuf;if (xqspi->bytes_to_receive <8 || ((dma_align &GQSPI_DMA_UNALIGN ) !=0x0 )) {/* Setting to IO mode */ - config_reg =zynqmp_gqspi_read (xqspi,GQSPI_CONFIG_OFST ); - config_reg &= ~GQSPI_CFG_MODE_EN_MASK ; -zynqmp_gqspi_write (xqspi,GQSPI_CONFIG_OFST , config_reg); - xqspi->mode =GQSPI_MODE_IO ; +zynqmp_qspi_disable_dma (xqspi); xqspi->dma_rx_bytes =0 ;return 0 ; }
@@ -882,14 +904,7 @@ static int zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi)zynqmp_gqspi_write (xqspi,GQSPI_QSPIDMA_DST_ADDR_MSB_OFST , ((u32 )addr) &0xfff ); -/* Enabling the DMA mode */ - config_reg =zynqmp_gqspi_read (xqspi,GQSPI_CONFIG_OFST ); - config_reg &= ~GQSPI_CFG_MODE_EN_MASK ; - config_reg |=GQSPI_CFG_MODE_EN_DMA_MASK ; -zynqmp_gqspi_write (xqspi,GQSPI_CONFIG_OFST , config_reg); - -/* Switch to DMA mode */ - xqspi->mode =GQSPI_MODE_DMA ; +zynqmp_qspi_enable_dma (xqspi);/* Write the number of bytes to transfer */ zynqmp_gqspi_write (xqspi,GQSPI_QSPIDMA_DST_SIZE_OFST , rx_bytes);
@@ -909,18 +924,10 @@ static int zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi)static void zynqmp_qspi_write_op (struct zynqmp_qspi *xqspi,u8 tx_nbits,u32 genfifoentry) { -u32 config_reg; -zynqmp_qspi_fillgenfifo (xqspi, tx_nbits, genfifoentry);zynqmp_qspi_filltxfifo (xqspi,GQSPI_TXD_DEPTH ); -if (xqspi->mode ==GQSPI_MODE_DMA ) { - config_reg =zynqmp_gqspi_read (xqspi, -GQSPI_CONFIG_OFST ); - config_reg &= ~GQSPI_CFG_MODE_EN_MASK ; -zynqmp_gqspi_write (xqspi,GQSPI_CONFIG_OFST , - config_reg); - xqspi->mode =GQSPI_MODE_IO ; - } +if (xqspi->mode ==GQSPI_MODE_DMA ) +zynqmp_qspi_disable_dma (xqspi); }/**
Signature · 1 line
2.35.1.1320.gc452695387.dirty
PATCH 4/5 spi: zynqmp-gqspi: Clean up fillgenfifo
In reply to Sean AndersonThis function does a lot more work (assigning things multiple times, masking unnecessarily, comparing to zero, using superfluous parentheses) than it needs to. This makes it difficult to understand and modify. Clean it up. No functional change intended.
---
drivers/spi/spi-zynqmp-gqspi.c | 78 ++++++++++++---------------------- 1 file changed, 28 insertions(+), 50 deletions(-)
drivers/spi/spi-zynqmp-gqspi.c +28 -50
@@ -82,7 +82,6 @@#define GQSPI_GENFIFO_RX 0x00020000#define GQSPI_GENFIFO_STRIPE 0x00040000#define GQSPI_GENFIFO_POLL 0x00080000 -#define GQSPI_GENFIFO_EXP_START 0x00000100#define GQSPI_FIFO_CTRL_RST_RX_FIFO_MASK 0x00000004#define GQSPI_FIFO_CTRL_RST_TX_FIFO_MASK 0x00000002#define GQSPI_FIFO_CTRL_RST_GEN_FIFO_MASK 0x00000001
@@ -672,71 +671,50 @@ static void zynqmp_qspi_readrxfifo(struct zynqmp_qspi *xqspi, u32 size)static void zynqmp_qspi_fillgenfifo (struct zynqmp_qspi *xqspi,u8 nbits,u32 genfifoentry) { -u32 transfer_len =0 ; +u32 transfer_len, tempcount, exponent; +u8 imm_data; -if (xqspi->txbuf) { - genfifoentry &= ~GQSPI_GENFIFO_RX ; - genfifoentry |=GQSPI_GENFIFO_DATA_XFER ; - genfifoentry |=GQSPI_GENFIFO_TX ; - transfer_len = xqspi->bytes_to_transfer; - }else if (xqspi->rxbuf) { - genfifoentry &= ~GQSPI_GENFIFO_TX ; - genfifoentry |=GQSPI_GENFIFO_DATA_XFER ; + genfifoentry |=GQSPI_GENFIFO_DATA_XFER ; +if (xqspi->rxbuf) { genfifoentry |=GQSPI_GENFIFO_RX ;if (xqspi->mode ==GQSPI_MODE_DMA ) transfer_len = xqspi->dma_rx_bytes;else transfer_len = xqspi->bytes_to_receive; }else { -/* Sending dummy circles here */ - genfifoentry &= ~(GQSPI_GENFIFO_TX |GQSPI_GENFIFO_RX ); - genfifoentry |=GQSPI_GENFIFO_DATA_XFER ; transfer_len = xqspi->bytes_to_transfer; } + +if (xqspi->txbuf) + genfifoentry |=GQSPI_GENFIFO_TX ; + genfifoentry |=zynqmp_qspi_selectspimode (xqspi, nbits); xqspi->genfifoentry = genfifoentry;dev_dbg (xqspi->dev,"genfifo %05x transfer_len %u\n" , genfifoentry, transfer_len); -if ((transfer_len) <GQSPI_GENFIFO_IMM_DATA_MASK ) { - genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK ; - genfifoentry |= transfer_len; -zynqmp_gqspi_write (xqspi,GQSPI_GEN_FIFO_OFST , genfifoentry); - }else { -int tempcount = transfer_len; -u32 exponent =8 ;/* 2^8 = 256 */ -u8 imm_data = tempcount &0xFF ; - - tempcount &= ~(tempcount &0xFF ); -/* Immediate entry */ -if (tempcount !=0 ) { -/* Exponent entries */ - genfifoentry |=GQSPI_GENFIFO_EXP ; -while (tempcount !=0 ) { -if (tempcount &GQSPI_GENFIFO_EXP_START ) { - genfifoentry &= - ~GQSPI_GENFIFO_IMM_DATA_MASK ; - genfifoentry |= exponent; -zynqmp_gqspi_write (xqspi, -GQSPI_GEN_FIFO_OFST , - genfifoentry); - } - tempcount = tempcount >>1 ; - exponent++; - } - } -if (imm_data !=0 ) { - genfifoentry &= ~GQSPI_GENFIFO_EXP ; - genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK ; - genfifoentry |= (u8)(imm_data &0xFF ); +/* Exponent entries */ + imm_data = transfer_len; + tempcount = transfer_len >>8 ; + exponent =8 ; + genfifoentry |=GQSPI_GENFIFO_EXP ; +while (tempcount) { +if (tempcount &1 )zynqmp_gqspi_write (xqspi,GQSPI_GEN_FIFO_OFST , - genfifoentry); - } - } -if (xqspi->mode ==GQSPI_MODE_IO && xqspi->rxbuf) { -/* Dummy generic FIFO entry */ -zynqmp_gqspi_write (xqspi,GQSPI_GEN_FIFO_OFST ,0x0 ); + genfifoentry | exponent); + tempcount >>=1 ; + exponent++; } + +/* Immediate entry */ + genfifoentry &= ~GQSPI_GENFIFO_EXP ; +if (imm_data) +zynqmp_gqspi_write (xqspi,GQSPI_GEN_FIFO_OFST , + genfifoentry | imm_data); + +/* Dummy generic FIFO entry */ +if (xqspi->mode ==GQSPI_MODE_IO && xqspi->rxbuf) +zynqmp_gqspi_write (xqspi,GQSPI_GEN_FIFO_OFST ,0 ); }/**
Signature · 1 line
2.35.1.1320.gc452695387.dirty
PATCH 5/5 spi: zynqmp-gqspi: Always acknowledge interrupts
In reply to Sean AndersonRXEMPTY can cause an IRQ, even though we may not do anything about it (such as if we are waiting for more received data). We must still handle these IRQs because we can tell they were caused by the device.
---
drivers/spi/spi-zynqmp-gqspi.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-)
drivers/spi/spi-zynqmp-gqspi.c +8 -12
@@ -806,7 +806,6 @@ static void zynqmp_process_dma_irq(struct zynqmp_qspi *xqspi)static irqreturn_t zynqmp_qspi_irq (int irq,void *dev_id) {struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_id; -irqreturn_t ret =IRQ_NONE ;u32 status, mask, dma_status =0 ; status =zynqmp_gqspi_read (xqspi,GQSPI_ISR_OFST );
@@ -821,27 +820,24 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id) dma_status); } -if (mask &GQSPI_ISR_TXNOT_FULL_MASK ) { +if (!mask && !dma_status) +return IRQ_NONE ; + +if (mask &GQSPI_ISR_TXNOT_FULL_MASK )zynqmp_qspi_filltxfifo (xqspi,GQSPI_TX_FIFO_FILL ); - ret =IRQ_HANDLED ; - } -if (dma_status &GQSPI_QSPIDMA_DST_I_STS_DONE_MASK ) { +if (dma_status &GQSPI_QSPIDMA_DST_I_STS_DONE_MASK )zynqmp_process_dma_irq (xqspi); - ret =IRQ_HANDLED ; - }else if (!(mask &GQSPI_IER_RXEMPTY_MASK ) && - (mask &GQSPI_IER_GENFIFOEMPTY_MASK )) { +else if (!(mask &GQSPI_IER_RXEMPTY_MASK ) && + (mask &GQSPI_IER_GENFIFOEMPTY_MASK ))zynqmp_qspi_readrxfifo (xqspi,GQSPI_RX_FIFO_FILL ); - ret =IRQ_HANDLED ; - }if (xqspi->bytes_to_receive ==0 && xqspi->bytes_to_transfer ==0 && ((status &GQSPI_IRQ_MASK ) ==GQSPI_IRQ_MASK )) {zynqmp_gqspi_write (xqspi,GQSPI_IDR_OFST ,GQSPI_ISR_IDR_MASK );complete (&xqspi->data_completion); - ret =IRQ_HANDLED ; } -return ret; +return IRQ_HANDLED ; }/**
Signature · 1 line
2.35.1.1320.gc452695387.dirty
Mark Brown
maintainerQuoted 4 lines · Sean Anderson
Here are a few mostly independent cleanups I came up with while writing some other patches. Feel free to apply them in piecemeal if you like.
Quoted 8 lines
Sean Anderson (5):
spi: zynqmp-gqspi: Reformat long line
spi: zynqmp-gqspi: Add some more debug prints
spi: zynqmp-gqspi: Add helpers for enabling/disabling DMA
spi: zynqmp-gqspi: Clean up fillgenfifo
spi: zynqmp-gqspi: Always acknowledge interrupts[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
Thanks!
[1/5] spi: zynqmp-gqspi: Reformat long line
commit: d61009bd578ee7381a3cce5c506190ecb8f9d6e8
[2/5] spi: zynqmp-gqspi: Add some more debug prints
commit: ba54629287f58b22c1d37f80f1875373e4b51ea6
[3/5] spi: zynqmp-gqspi: Add helpers for enabling/disabling DMA
commit: d2ead60d853189f8e5ec6b301fac1e60e0b4b47d
[4/5] spi: zynqmp-gqspi: Clean up fillgenfifo
commit: 9b32c86e40da792544c53076f5ec43f115e56687
[5/5] spi: zynqmp-gqspi: Always acknowledge interrupts
commit: 89785306453ce6d949e783f6936821a0b7649ee2All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark