spi: dw: refactor to use SPI core message handling
v3 cover spi: dw: refactor to use SPI core message handling
This patch series is dedicated to refactoring of spi-dw driver to use SPI core message handling. The driver has been tested in PIO mode on Intel Medfield device in loopback mode.
Note, the patch 3/3 depends on [1].
[1] http://www.spinics.net/lists/linux-spi/msg02982.html
Changelog v3:
- introduce patch 1/3 and 2/3 to make state of the SPI controller consistent
- return 1 instead of transfer length from transfer_one()
- use newly introduced handle_err()
Changelog v2:
- remove leftovers from spi-dw.h
- remove unused members of dw_spi, i.e. cur_dev, max_bits_per_word
- reuse chip->cs_control directly
Andy Shevchenko (3):
spi: dw: make sure SPI controller is enabled
spi: dw: program registers as soon as possible
spi: dw: move to SPI core message handling
drivers/spi/spi-dw-mid.c | 4 +- drivers/spi/spi-dw.c | 236 +++++++++++++++-------------------------------- drivers/spi/spi-dw.h | 26 ------ 3 files changed, 77 insertions(+), 189 deletions(-)
Signature · 6 lines
2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 1425054977-9859-1-git-send-email-andriy.shevchenko-VuQAYsv1563Yd54FQh9/[email protected]
PATCH v3 1/3 spi: dw: make sure SPI controller is enabled
The error handling is partially broken since the controller is disabled on error and is not re-enabled until condition occurs, i.e. mode (poll, PIO/DMA), chip (cs_change), or speed (clk_div) is changed. In the result of these changes we will have a predictable state of the SPi controller independently on how successfull a previous transfer was.
The patch disables interrupts and re-enables the SPI controller wherever it needs to be done. Thus most of the time the SPI controller is kept enabled. The runtime PM, when it will be implemented, must take care of the controller disabling and re-enabling.
--- drivers/spi/spi-dw.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
drivers/spi/spi-dw.c +14 -5
@@ -270,10 +270,21 @@ static void giveback(struct dw_spi *dws)spi_finalize_current_message (dws->master); } -static void int_error_stop (struct dw_spi *dws,const char *msg) +/* +* This does disable the SPI controller, interrupts, and re-enable the +* controller back. Transmit and receive FIFO buffers are cleared when the +* device is disabled. +*/ +static void spi_disable_intr (struct dw_spi *dws) { -/* Stop the hw */ spi_enable_chip (dws,0 ); +spi_mask_intr (dws,0xff ); +spi_enable_chip (dws,1 ); +} + +static void int_error_stop (struct dw_spi *dws,const char *msg) +{ +spi_disable_intr (dws);dev_err (&dws->master->dev,"%s\n" , msg); dws->cur_msg->state =ERROR_STATE ;
@@ -606,9 +617,7 @@ static void dw_spi_cleanup(struct spi_device *spi)/* Restart the controller, disable all interrupts, clean rx fifo */ static void spi_hw_init (struct device *dev,struct dw_spi *dws) { -spi_enable_chip (dws,0 ); -spi_mask_intr (dws,0xff ); -spi_enable_chip (dws,1 ); +spi_disable_intr (dws);/* * Try to detect the FIFO depth if not set by interface driver,
Signature · 6 lines
2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v3 2/3 spi: dw: program registers as soon as possible
In reply to a message not in the archiveThis patch refactors the code in pump_transfers() to reprogram the registers immediately when we have a new configuration data. The behaviour is slightly modified:
- chip is always disabled and reenabled
- CTRL0 is always reprogrammed
This change allows to do a further refactoring and simplier conversion to use SPI core DMA routines in the future.
--- drivers/spi/spi-dw.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-)
drivers/spi/spi-dw.c +18 -24
@@ -421,6 +421,8 @@ static void pump_transfers(unsigned long data)if (chip != dws->prev_chip) cs_change =1 ; +spi_enable_chip (dws,0 ); + cr0 = chip->cr0;/* Handle per transfer options for bpw and speed */
@@ -435,6 +437,8 @@ static void pump_transfers(unsigned long data) chip->speed_hz = speed; chip->clk_div = clk_div; + +spi_set_clk (dws, chip->clk_div); } }if (transfer->bits_per_word) {
@@ -463,44 +467,34 @@ static void pump_transfers(unsigned long data) cr0 |= (chip->tmode <<SPI_TMOD_OFFSET ); } +dw_writew (dws,DW_SPI_CTRL0 , cr0); +spi_chip_sel (dws, spi,1 ); +/* Check if current transfer is a DMA transaction */ dws->dma_mapped =map_dma_buffers (dws);/* * Interrupt mode * we only need set the TXEI IRQ, as TX/RX always happen syncronizely +* Set the interrupt mask, for poll mode just disable all interrupts. */ -if (!dws->dma_mapped && !chip->poll_mode) { +if (chip->poll_mode) { +spi_mask_intr (dws,0xff ); + }else if (dws->dma_mapped) { +spi_mask_intr (dws,0xff ); + }else { txlevel =min_t (u16, dws->fifo_len /2 , dws->len / dws->n_bytes); +dw_writew (dws,DW_SPI_TXFLTR , txlevel); +spi_mask_intr (dws,0xff ); imask |=SPI_INT_TXEI |SPI_INT_TXOI |SPI_INT_RXUI |SPI_INT_RXOI ; +spi_umask_intr (dws, imask); + dws->transfer_handler = interrupt_transfer; } -/* -* Reprogram registers only if -* 1. chip select changes -* 2. clk_div is changed -* 3. control value changes -*/ -if (dw_readw (dws,DW_SPI_CTRL0 ) != cr0 || cs_change || clk_div || imask) { -spi_enable_chip (dws,0 ); - -dw_writew (dws,DW_SPI_CTRL0 , cr0); - -spi_set_clk (dws, chip->clk_div); -spi_chip_sel (dws, spi,1 ); - -/* Set the interrupt mask, for poll mode just disable all int */ -spi_mask_intr (dws,0xff ); -if (imask) -spi_umask_intr (dws, imask); -if (txlevel) -dw_writew (dws,DW_SPI_TXFLTR , txlevel); - -spi_enable_chip (dws,1 ); - } +spi_enable_chip (dws,1 );if (cs_change) dws->prev_chip = chip;
Signature · 6 lines
2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 1425054977-9859-3-git-send-email-andriy.shevchenko-VuQAYsv1563Yd54FQh9/[email protected]
Re: [PATCH v3 2/3] spi: dw: program registers as soon as possible
Quoted 22 lines · Andy Shevchenko
This patch refactors the code in
pump_transfers()to reprogram the registers immediately when we have a new configuration data. The behaviour is slightly modified:
- chip is always disabled and reenabled
- CTRL0 is always reprogrammedThis change allows to do a further refactoring and simplier conversion to use SPI core DMA routines in the future.
drivers/spi/spi-dw.c +6
-1/* * Interrupt mode * we only need set the TXEI IRQ, as TX/RX always happen syncronizely +* Set the interrupt mask, for poll mode just disable all interrupts. */ -if (!dws->dma_mapped && !chip->poll_mode) { +if (chip->poll_mode) { +spi_mask_intr (dws,0xff ); + }else if (dws->dma_mapped) { +spi_mask_intr (dws,0xff ); + }else {
drivers/spi/spi-dw.c static void pump_transfers(unsigned long data) · line 495
Quoted 10 lines
drivers/spi/spi-dw.c +4
-0txlevel =min_t (u16, dws->fifo_len /2 , dws->len / dws->n_bytes); +dw_writew (dws,DW_SPI_TXFLTR , txlevel); +spi_mask_intr (dws,0xff ); imask |=SPI_INT_TXEI |SPI_INT_TXOI |SPI_INT_RXUI |SPI_INT_RXOI ; +spi_umask_intr (dws, imask); + dws->transfer_handler = interrupt_transfer; }
Perhaps I have to revisit this piece of code.
Signature · 7 lines
Andy Shevchenko <[email protected]> Intel Finland Oy -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v3 3/3 spi: dw: move to SPI core message handling
In reply to a message not in the archiveThis patch removes a lot of duplicate code since SPI core provides a nice message handling.
--- drivers/spi/spi-dw-mid.c | 4 +- drivers/spi/spi-dw.c | 183 ++++++++++++----------------------------------- drivers/spi/spi-dw.h | 26 ------- 3 files changed, 49 insertions(+), 164 deletions(-)
drivers/spi/spi-dw-mid.c +2 -2
@@ -110,7 +110,7 @@ static void dw_spi_dma_tx_done(void *arg)if (test_and_clear_bit (TX_BUSY , &dws->dma_chan_busy) &BIT (RX_BUSY ))return ; -dw_spi_xfer_done (dws); +spi_finalize_current_transfer (dws->master); }static struct dma_async_tx_descriptor *dw_spi_dma_prepare_tx (struct dw_spi *dws)
@@ -155,7 +155,7 @@ static void dw_spi_dma_rx_done(void *arg)if (test_and_clear_bit (RX_BUSY , &dws->dma_chan_busy) &BIT (TX_BUSY ))return ; -dw_spi_xfer_done (dws); +spi_finalize_current_transfer (dws->master); }static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx (struct dw_spi *dws)
drivers/spi/spi-dw.c +47 -136
320 lines not on this page · raw message
drivers/spi/spi-dw.h +0 -26
@@ -96,7 +96,6 @@ struct dw_spi_dma_ops {struct dw_spi {struct spi_master *master; -struct spi_device *cur_dev;enum dw_ssi_type type;char name[16 ];
@@ -109,13 +108,7 @@ struct dw_spi {u16 bus_num;u16 num_cs;/* supported slave numbers */ -/* Message Transfer pump */ -struct tasklet_struct pump_transfers; -/* Current message transfer state info */ -struct spi_message *cur_msg; -struct spi_transfer *cur_transfer; -struct chip_data *cur_chip;struct chip_data *prev_chip;size_t len;void *tx;
@@ -128,10 +121,8 @@ struct dw_spi {size_t rx_map_len;size_t tx_map_len;u8 n_bytes;/* current is a 1/2 bytes op */ -u8 max_bits_per_word;/* maxim is 16b */ u32 dma_width;irqreturn_t (*transfer_handler)(struct dw_spi *dws); -void (*cs_control)(u32 command);/* Dma info */ int dma_inited;
@@ -182,22 +173,6 @@ static inline void spi_set_clk(struct dw_spi *dws, u16 div)dw_writel (dws,DW_SPI_BAUDR , div); } -static inline void spi_chip_sel (struct dw_spi *dws,struct spi_device *spi, -int active) -{ -u16 cs = spi->chip_select; -int gpio_val = active ? (spi->mode &SPI_CS_HIGH ) : - !(spi->mode &SPI_CS_HIGH ); - -if (dws->cs_control) - dws->cs_control (active); -if (gpio_is_valid (spi->cs_gpio)) -gpio_set_value (spi->cs_gpio, gpio_val); - -if (active) -dw_writel (dws,DW_SPI_SER ,1 << cs); -} -/* Disable IRQ bits */ static inline void spi_mask_intr (struct dw_spi *dws,u32 mask) {
@@ -233,7 +208,6 @@ extern int dw_spi_add_host(struct device *dev, struct dw_spi *dws);extern void dw_spi_remove_host (struct dw_spi *dws);extern int dw_spi_suspend_host (struct dw_spi *dws);extern int dw_spi_resume_host (struct dw_spi *dws); -extern void dw_spi_xfer_done (struct dw_spi *dws);/* platform related setup */ extern int dw_spi_mid_init (struct dw_spi *dws);/* Intel MID platforms */
Signature · 6 lines
2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html