linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/3] spi: dw: refactor to use SPI core message handling
@ 2015-02-27 16:36 Andy Shevchenko
       [not found] ` <1425054977-9859-1-git-send-email-andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
  0 siblings, 1 reply; 5+ messages in thread
From: Andy Shevchenko @ 2015-02-27 16:36 UTC (permalink / raw)
  To: Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA; +Cc: Andy Shevchenko

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(-)

-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v3 1/3] spi: dw: make sure SPI controller is enabled
       [not found] ` <1425054977-9859-1-git-send-email-andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
@ 2015-02-27 16:36   ` Andy Shevchenko
  2015-02-27 16:36   ` [PATCH v3 2/3] spi: dw: program registers as soon as possible Andy Shevchenko
  2015-02-27 16:36   ` [PATCH v3 3/3] spi: dw: move to SPI core message handling Andy Shevchenko
  2 siblings, 0 replies; 5+ messages in thread
From: Andy Shevchenko @ 2015-02-27 16:36 UTC (permalink / raw)
  To: Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA; +Cc: Andy Shevchenko

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.

Signed-off-by: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
 drivers/spi/spi-dw.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 05af817..24aaaf98 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -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,
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v3 2/3] spi: dw: program registers as soon as possible
       [not found] ` <1425054977-9859-1-git-send-email-andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
  2015-02-27 16:36   ` [PATCH v3 1/3] spi: dw: make sure SPI controller is enabled Andy Shevchenko
@ 2015-02-27 16:36   ` Andy Shevchenko
       [not found]     ` <1425054977-9859-3-git-send-email-andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
  2015-02-27 16:36   ` [PATCH v3 3/3] spi: dw: move to SPI core message handling Andy Shevchenko
  2 siblings, 1 reply; 5+ messages in thread
From: Andy Shevchenko @ 2015-02-27 16:36 UTC (permalink / raw)
  To: Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA; +Cc: 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 reprogrammed

This change allows to do a further refactoring and simplier conversion to use
SPI core DMA routines in the future.

Signed-off-by: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
 drivers/spi/spi-dw.c | 42 ++++++++++++++++++------------------------
 1 file changed, 18 insertions(+), 24 deletions(-)

diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 24aaaf98..9bc9c13 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -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;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v3 3/3] spi: dw: move to SPI core message handling
       [not found] ` <1425054977-9859-1-git-send-email-andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
  2015-02-27 16:36   ` [PATCH v3 1/3] spi: dw: make sure SPI controller is enabled Andy Shevchenko
  2015-02-27 16:36   ` [PATCH v3 2/3] spi: dw: program registers as soon as possible Andy Shevchenko
@ 2015-02-27 16:36   ` Andy Shevchenko
  2 siblings, 0 replies; 5+ messages in thread
From: Andy Shevchenko @ 2015-02-27 16:36 UTC (permalink / raw)
  To: Mark Brown, linux-spi-u79uwXL29TY76Z2rM5mHXA; +Cc: Andy Shevchenko

This patch removes a lot of duplicate code since SPI core provides a nice
message handling.

Signed-off-by: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
 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(-)

diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
index a0197fd..8f68e82 100644
--- a/drivers/spi/spi-dw-mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -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)
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 9bc9c13..74ef109 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -28,11 +28,6 @@
 #include <linux/debugfs.h>
 #endif
 
-#define START_STATE	((void *)0)
-#define RUNNING_STATE	((void *)1)
-#define DONE_STATE	((void *)2)
-#define ERROR_STATE	((void *)-1)
-
 /* Slave spi_dev related */
 struct chip_data {
 	u16 cr0;
@@ -143,6 +138,19 @@ static inline void dw_spi_debugfs_remove(struct dw_spi *dws)
 }
 #endif /* CONFIG_DEBUG_FS */
 
+static void dw_spi_set_cs(struct spi_device *spi, bool enable)
+{
+	struct dw_spi *dws = spi_master_get_devdata(spi->master);
+	struct chip_data *chip = spi_get_ctldata(spi);
+
+	/* Chip select logic is inverted from spi_set_cs() */
+	if (chip->cs_control)
+		chip->cs_control(!enable);
+
+	if (!enable)
+		dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select));
+}
+
 /* Return the max entries we can fill into tx fifo */
 static inline u32 tx_max(struct dw_spi *dws)
 {
@@ -209,67 +217,32 @@ static void dw_reader(struct dw_spi *dws)
 	}
 }
 
-static void *next_transfer(struct dw_spi *dws)
-{
-	struct spi_message *msg = dws->cur_msg;
-	struct spi_transfer *trans = dws->cur_transfer;
-
-	/* Move to next transfer */
-	if (trans->transfer_list.next != &msg->transfers) {
-		dws->cur_transfer =
-			list_entry(trans->transfer_list.next,
-					struct spi_transfer,
-					transfer_list);
-		return RUNNING_STATE;
-	}
-
-	return DONE_STATE;
-}
-
 /*
  * Note: first step is the protocol driver prepares
  * a dma-capable memory, and this func just need translate
  * the virt addr to physical
  */
-static int map_dma_buffers(struct dw_spi *dws)
+static int map_dma_buffers(struct spi_master *master,
+		struct spi_device *spi, struct spi_transfer *transfer)
 {
-	if (!dws->cur_msg->is_dma_mapped
+	struct dw_spi *dws = spi_master_get_devdata(master);
+	struct chip_data *chip = spi_get_ctldata(spi);
+
+	if (!master->cur_msg->is_dma_mapped
 		|| !dws->dma_inited
-		|| !dws->cur_chip->enable_dma
+		|| !chip->enable_dma
 		|| !dws->dma_ops)
 		return 0;
 
-	if (dws->cur_transfer->tx_dma)
-		dws->tx_dma = dws->cur_transfer->tx_dma;
+	if (transfer->tx_dma)
+		dws->tx_dma = transfer->tx_dma;
 
-	if (dws->cur_transfer->rx_dma)
-		dws->rx_dma = dws->cur_transfer->rx_dma;
+	if (transfer->rx_dma)
+		dws->rx_dma = transfer->rx_dma;
 
 	return 1;
 }
 
-/* Caller already set message->status; dma and pio irqs are blocked */
-static void giveback(struct dw_spi *dws)
-{
-	struct spi_transfer *last_transfer;
-	struct spi_message *msg;
-
-	msg = dws->cur_msg;
-	dws->cur_msg = NULL;
-	dws->cur_transfer = NULL;
-	dws->prev_chip = dws->cur_chip;
-	dws->cur_chip = NULL;
-	dws->dma_mapped = 0;
-
-	last_transfer = list_last_entry(&msg->transfers, struct spi_transfer,
-					transfer_list);
-
-	if (!last_transfer->cs_change)
-		spi_chip_sel(dws, msg->spi, 0);
-
-	spi_finalize_current_message(dws->master);
-}
-
 /*
  * This does disable the SPI controller, interrupts, and re-enable the
  * controller back. Transmit and receive FIFO buffers are cleared when the
@@ -287,27 +260,10 @@ 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;
-	tasklet_schedule(&dws->pump_transfers);
+	dws->master->cur_msg->status = -EIO;
+	spi_finalize_current_transfer(dws->master);
 }
 
-void dw_spi_xfer_done(struct dw_spi *dws)
-{
-	/* Update total byte transferred return count actual bytes read */
-	dws->cur_msg->actual_length += dws->len;
-
-	/* Move to next transfer */
-	dws->cur_msg->state = next_transfer(dws);
-
-	/* Handle end of message */
-	if (dws->cur_msg->state == DONE_STATE) {
-		dws->cur_msg->status = 0;
-		giveback(dws);
-	} else
-		tasklet_schedule(&dws->pump_transfers);
-}
-EXPORT_SYMBOL_GPL(dw_spi_xfer_done);
-
 static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 {
 	u16 irq_status = dw_readw(dws, DW_SPI_ISR);
@@ -324,7 +280,7 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 	dw_reader(dws);
 	if (dws->rx_end == dws->rx) {
 		spi_mask_intr(dws, SPI_INT_TXEI);
-		dw_spi_xfer_done(dws);
+		spi_finalize_current_transfer(dws->master);
 		return IRQ_HANDLED;
 	}
 	if (irq_status & SPI_INT_TXEI) {
@@ -339,13 +295,14 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws)
 
 static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 {
-	struct dw_spi *dws = dev_id;
+	struct spi_master *master = dev_id;
+	struct dw_spi *dws = spi_master_get_devdata(master);
 	u16 irq_status = dw_readw(dws, DW_SPI_ISR) & 0x3f;
 
 	if (!irq_status)
 		return IRQ_NONE;
 
-	if (!dws->cur_msg) {
+	if (!master->cur_msg) {
 		spi_mask_intr(dws, SPI_INT_TXEI);
 		return IRQ_HANDLED;
 	}
@@ -354,7 +311,7 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
 }
 
 /* Must be called inside pump_transfers() */
-static void poll_transfer(struct dw_spi *dws)
+static int poll_transfer(struct dw_spi *dws)
 {
 	do {
 		dw_writer(dws);
@@ -362,17 +319,14 @@ static void poll_transfer(struct dw_spi *dws)
 		cpu_relax();
 	} while (dws->rx_end > dws->rx);
 
-	dw_spi_xfer_done(dws);
+	return 0;
 }
 
-static void pump_transfers(unsigned long data)
+static int dw_spi_transfer_one(struct spi_master *master,
+		struct spi_device *spi, struct spi_transfer *transfer)
 {
-	struct dw_spi *dws = (struct dw_spi *)data;
-	struct spi_message *message = NULL;
-	struct spi_transfer *transfer = NULL;
-	struct spi_transfer *previous = NULL;
-	struct spi_device *spi = NULL;
-	struct chip_data *chip = NULL;
+	struct dw_spi *dws = spi_master_get_devdata(master);
+	struct chip_data *chip = spi_get_ctldata(spi);
 	u8 bits = 0;
 	u8 imask = 0;
 	u8 cs_change = 0;
@@ -381,35 +335,8 @@ static void pump_transfers(unsigned long data)
 	u32 speed = 0;
 	u32 cr0 = 0;
 
-	/* Get current state information */
-	message = dws->cur_msg;
-	transfer = dws->cur_transfer;
-	chip = dws->cur_chip;
-	spi = message->spi;
-
-	if (message->state == ERROR_STATE) {
-		message->status = -EIO;
-		goto early_exit;
-	}
-
-	/* Handle end of message */
-	if (message->state == DONE_STATE) {
-		message->status = 0;
-		goto early_exit;
-	}
-
-	/* Delay if requested at end of transfer */
-	if (message->state == RUNNING_STATE) {
-		previous = list_entry(transfer->transfer_list.prev,
-					struct spi_transfer,
-					transfer_list);
-		if (previous->delay_usecs)
-			udelay(previous->delay_usecs);
-	}
-
 	dws->n_bytes = chip->n_bytes;
 	dws->dma_width = chip->dma_width;
-	dws->cs_control = chip->cs_control;
 
 	dws->rx_dma = transfer->rx_dma;
 	dws->tx_dma = transfer->tx_dma;
@@ -417,7 +344,7 @@ static void pump_transfers(unsigned long data)
 	dws->tx_end = dws->tx + transfer->len;
 	dws->rx = transfer->rx_buf;
 	dws->rx_end = dws->rx + transfer->len;
-	dws->len = dws->cur_transfer->len;
+	dws->len = transfer->len;
 	if (chip != dws->prev_chip)
 		cs_change = 1;
 
@@ -449,13 +376,12 @@ static void pump_transfers(unsigned long data)
 			| (spi->mode << SPI_MODE_OFFSET)
 			| (chip->tmode << SPI_TMOD_OFFSET);
 	}
-	message->state = RUNNING_STATE;
 
 	/*
 	 * Adjust transfer mode if necessary. Requires platform dependent
 	 * chipselect mechanism.
 	 */
-	if (dws->cs_control) {
+	if (chip->cs_control) {
 		if (dws->rx && dws->tx)
 			chip->tmode = SPI_TMOD_TR;
 		else if (dws->rx)
@@ -468,10 +394,9 @@ static void pump_transfers(unsigned long data)
 	}
 
 	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);
+	dws->dma_mapped = map_dma_buffers(master, spi, transfer);
 
 	/*
 	 * Interrupt mode
@@ -503,31 +428,17 @@ static void pump_transfers(unsigned long data)
 		dws->dma_ops->dma_transfer(dws, cs_change);
 
 	if (chip->poll_mode)
-		poll_transfer(dws);
+		return poll_transfer(dws);
 
-	return;
-
-early_exit:
-	giveback(dws);
+	return 1;
 }
 
-static int dw_spi_transfer_one_message(struct spi_master *master,
+static void dw_spi_handle_err(struct spi_master *master,
 		struct spi_message *msg)
 {
 	struct dw_spi *dws = spi_master_get_devdata(master);
 
-	dws->cur_msg = msg;
-	/* Initial message state */
-	dws->cur_msg->state = START_STATE;
-	dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,
-						struct spi_transfer,
-						transfer_list);
-	dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);
-
-	/* Launch transfers */
-	tasklet_schedule(&dws->pump_transfers);
-
-	return 0;
+	spi_disable_intr(dws);
 }
 
 /* This may be called twice for each spi dev */
@@ -651,7 +562,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
 	snprintf(dws->name, sizeof(dws->name), "dw_spi%d", dws->bus_num);
 
 	ret = devm_request_irq(dev, dws->irq, dw_spi_irq, IRQF_SHARED,
-			dws->name, dws);
+			dws->name, master);
 	if (ret < 0) {
 		dev_err(&master->dev, "can not get IRQ\n");
 		goto err_free_master;
@@ -663,7 +574,9 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
 	master->num_chipselect = dws->num_cs;
 	master->setup = dw_spi_setup;
 	master->cleanup = dw_spi_cleanup;
-	master->transfer_one_message = dw_spi_transfer_one_message;
+	master->set_cs = dw_spi_set_cs;
+	master->transfer_one = dw_spi_transfer_one;
+	master->handle_err = dw_spi_handle_err;
 	master->max_speed_hz = dws->max_freq;
 	master->dev.of_node = dev->of_node;
 
@@ -678,8 +591,6 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
 		}
 	}
 
-	tasklet_init(&dws->pump_transfers, pump_transfers, (unsigned long)dws);
-
 	spi_master_set_devdata(master, dws);
 	ret = devm_spi_register_master(dev, master);
 	if (ret) {
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 3d32be6..70cad09 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -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 */
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 2/3] spi: dw: program registers as soon as possible
       [not found]     ` <1425054977-9859-3-git-send-email-andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
@ 2015-02-27 20:11       ` Andy Shevchenko
  0 siblings, 0 replies; 5+ messages in thread
From: Andy Shevchenko @ 2015-02-27 20:11 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA

On Fri, 2015-02-27 at 18:36 +0200, Andy Shevchenko wrote:
> 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 reprogrammed
> 
> This change allows to do a further refactoring and simplier conversion to use
> SPI core DMA routines in the future.
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>

>  	/*
>  	 * 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;
>  	}

Perhaps I have to revisit this piece of code.


-- 
Andy Shevchenko <andriy.shevchenko-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Intel Finland Oy

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-02-27 20:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-27 16:36 [PATCH v3 0/3] spi: dw: refactor to use SPI core message handling Andy Shevchenko
     [not found] ` <1425054977-9859-1-git-send-email-andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2015-02-27 16:36   ` [PATCH v3 1/3] spi: dw: make sure SPI controller is enabled Andy Shevchenko
2015-02-27 16:36   ` [PATCH v3 2/3] spi: dw: program registers as soon as possible Andy Shevchenko
     [not found]     ` <1425054977-9859-3-git-send-email-andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2015-02-27 20:11       ` Andy Shevchenko
2015-02-27 16:36   ` [PATCH v3 3/3] spi: dw: move to SPI core message handling Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).