diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
index ff5893d..9f73fe5 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
@@ -14,9 +14,10 @@ Required properties:
 - spi-num-chipselects : the number of the chipselect signals.
 - bus-num : the slave chip chipselect signal number.
 
-Optional property:
+Optional properties:
 - big-endian: If present the dspi device's registers are implemented
   in big endian mode.
+- spi-slave-mode: if present, controller runs in slave mode.
 
 Optional SPI slave node properties:
 - fsl,spi-cs-sck-delay: a delay in nanoseconds between activating chip
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 9e9dadb..425b068 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -39,13 +39,12 @@
 #define TRAN_STATE_TX_VOID		0x02
 #define TRAN_STATE_WORD_ODD_NUM	0x04
 
-#define DSPI_FIFO_SIZE			4
-
 #define SPI_MCR		0x00
 #define SPI_MCR_MASTER		(1 << 31)
 #define SPI_MCR_PCSIS		(0x3F << 16)
 #define SPI_MCR_CLR_TXF	(1 << 11)
 #define SPI_MCR_CLR_RXF	(1 << 10)
+#define SPI_MCR_HALT	(1 << 0)
 
 #define SPI_TCR			0x08
 #define SPI_TCR_GET_TCNT(x)	(((x) & 0xffff0000) >> 16)
@@ -66,14 +65,21 @@
 #define SPI_CTAR_SCALE_BITS	0xf
 
 #define SPI_CTAR0_SLAVE	0x0c
+#define SPI_CTAR0_SLAVE_FMSZ(x)	(((x) & 0x00000001f) << 27)
+#define SPI_CTAR0_SLAVE_CPOL(x)	((x) << 26)
+#define SPI_CTAR0_SLAVE_CPHA(x)	((x) << 25)
 
 #define SPI_SR			0x2c
+#define SPI_SR_TXRXS		0x40000000
 #define SPI_SR_EOQF		0x10000000
 #define SPI_SR_TCFQF		0x80000000
+#define SPI_SR_TFFF		0x02000000
+#define SPI_SR_RFDF		0x00020000
 
 #define SPI_RSER		0x30
 #define SPI_RSER_EOQFE		0x10000000
 #define SPI_RSER_TCFQE		0x80000000
+#define SPI_RSER_RFDFE		0x00020000
 
 #define SPI_PUSHR		0x34
 #define SPI_PUSHR_CONT		(1 << 31)
@@ -114,28 +120,19 @@ struct chip_data {
 	u16 void_write_data;
 };
 
-enum dspi_trans_mode {
-	DSPI_EOQ_MODE = 0,
-	DSPI_TCFQ_MODE,
-};
-
 struct fsl_dspi_devtype_data {
-	enum dspi_trans_mode trans_mode;
 	u8 max_clock_factor;
 };
 
 static const struct fsl_dspi_devtype_data vf610_data = {
-	.trans_mode = DSPI_EOQ_MODE,
 	.max_clock_factor = 2,
 };
 
 static const struct fsl_dspi_devtype_data ls1021a_v1_data = {
-	.trans_mode = DSPI_TCFQ_MODE,
 	.max_clock_factor = 8,
 };
 
 static const struct fsl_dspi_devtype_data ls2085a_data = {
-	.trans_mode = DSPI_TCFQ_MODE,
 	.max_clock_factor = 8,
 };
 
@@ -150,9 +147,10 @@ struct fsl_dspi {
 	struct spi_transfer	*cur_transfer;
 	struct spi_message	*cur_msg;
 	struct chip_data	*cur_chip;
-	size_t			len;
+	size_t			tx_len;
 	void			*tx;
 	void			*tx_end;
+	size_t			rx_len;
 	void			*rx;
 	void			*rx_end;
 	char			dataflags;
@@ -251,18 +249,21 @@ static u32 dspi_data_to_pushr(struct fsl_dspi *dspi, int tx_word)
 {
 	u16 d16;
 
-	if (!(dspi->dataflags & TRAN_STATE_TX_VOID))
+	if ( (dspi->tx_len) && !(dspi->dataflags & TRAN_STATE_TX_VOID) ) {
 		d16 = tx_word ? *(u16 *)dspi->tx : *(u8 *)dspi->tx;
+		dspi->tx += tx_word + 1;
+		dspi->tx_len -= tx_word + 1;
+	}
 	else
 		d16 = dspi->void_write_data;
 
-	dspi->tx += tx_word + 1;
-	dspi->len -= tx_word + 1;
-
-	return	SPI_PUSHR_TXDATA(d16) |
-		SPI_PUSHR_PCS(dspi->cs) |
-		SPI_PUSHR_CTAS(0) |
-		SPI_PUSHR_CONT;
+	if (dspi->cur_chip->mcr_val & SPI_MCR_MASTER)
+		return	SPI_PUSHR_TXDATA(d16) |
+			SPI_PUSHR_PCS(dspi->cs) |
+			SPI_PUSHR_CTAS(0) |
+			SPI_PUSHR_CONT;
+	else
+		return	SPI_PUSHR_TXDATA(d16);
 }
 
 static void dspi_data_from_popr(struct fsl_dspi *dspi, int rx_word)
@@ -273,99 +274,78 @@ static void dspi_data_from_popr(struct fsl_dspi *dspi, int rx_word)
 	regmap_read(dspi->regmap, SPI_POPR, &val);
 	d = SPI_POPR_RXDATA(val);
 
-	if (!(dspi->dataflags & TRAN_STATE_RX_VOID))
+	if ((dspi->rx_len) && !(dspi->dataflags & TRAN_STATE_RX_VOID)) {
 		rx_word ? (*(u16 *)dspi->rx = d) : (*(u8 *)dspi->rx = d);
+		dspi->rx += rx_word + 1;
+		dspi->rx_len -= rx_word + 1;
+	}
 
-	dspi->rx += rx_word + 1;
 }
 
-static int dspi_eoq_write(struct fsl_dspi *dspi)
+static int dspi_write(struct fsl_dspi *dspi)
 {
-	int tx_count = 0;
 	int tx_word;
 	u32 dspi_pushr = 0;
+	int tx_count = 0;
+	u32 spi_mcr, spi_sr;
 
 	tx_word = is_double_byte_mode(dspi);
 
-	while (dspi->len && (tx_count < DSPI_FIFO_SIZE)) {
-		/* If we are in word mode, only have a single byte to transfer
-		 * switch to byte mode temporarily.  Will switch back at the
-		 * end of the transfer.
-		 */
-		if (tx_word && (dspi->len == 1)) {
-			dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
-			regmap_update_bits(dspi->regmap, SPI_CTAR(0),
-					SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));
-			tx_word = 0;
-		}
+	if (tx_word && (dspi->tx_len == 1)) {
+		dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
+		regmap_update_bits(dspi->regmap, SPI_CTAR(0),
+				SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));
+		tx_word = 0;
+	}
+
+	regmap_read(dspi->regmap, SPI_MCR, &spi_mcr);
+	while (dspi->tx_len) {
 
 		dspi_pushr = dspi_data_to_pushr(dspi, tx_word);
 
-		if (dspi->len == 0 || tx_count == DSPI_FIFO_SIZE - 1) {
-			/* last transfer in the transfer */
-			dspi_pushr |= SPI_PUSHR_EOQ;
-			if ((dspi->cs_change) && (!dspi->len))
-				dspi_pushr &= ~SPI_PUSHR_CONT;
-		} else if (tx_word && (dspi->len == 1))
-			dspi_pushr |= SPI_PUSHR_EOQ;
+		if (spi_mcr & SPI_MCR_MASTER) {
+			if (!dspi->tx_len) {
+				dspi_pushr |= SPI_PUSHR_EOQ;
+				if (dspi->cs_change)
+					dspi_pushr &= ~SPI_PUSHR_CONT;
+			}
+			regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr);
+		}
+		else
+			regmap_write(dspi->regmap, SPI_PUSHR_SLAVE, dspi_pushr);
 
-		regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr);
+		regmap_write(dspi->regmap, SPI_SR, SPI_SR_TFFF);
+		regmap_read(dspi->regmap, SPI_SR, &spi_sr);
+		if (!(spi_sr & SPI_SR_TFFF))
+			break;
 
 		tx_count++;
 	}
 
-	return tx_count * (tx_word + 1);
+	return tx_count * (tx_word+1);
 }
 
-static int dspi_eoq_read(struct fsl_dspi *dspi)
+static int dspi_read(struct fsl_dspi *dspi)
 {
 	int rx_count = 0;
 	int rx_word = is_double_byte_mode(dspi);
+	u32 spi_sr;
 
-	while ((dspi->rx < dspi->rx_end)
-			&& (rx_count < DSPI_FIFO_SIZE)) {
-		if (rx_word && (dspi->rx_end - dspi->rx) == 1)
-			rx_word = 0;
-
-		dspi_data_from_popr(dspi, rx_word);
-		rx_count++;
-	}
+	if (rx_word && (dspi->rx_end - dspi->rx) == 1)
+		rx_word = 0;
 
-	return rx_count;
-}
+	while (dspi->rx_len) {
 
-static int dspi_tcfq_write(struct fsl_dspi *dspi)
-{
-	int tx_word;
-	u32 dspi_pushr = 0;
+		regmap_read(dspi->regmap, SPI_SR, &spi_sr);
+		if (!(spi_sr & SPI_SR_RFDF))
+			break;
 
-	tx_word = is_double_byte_mode(dspi);
+		dspi_data_from_popr(dspi, rx_word);
 
-	if (tx_word && (dspi->len == 1)) {
-		dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
-		regmap_update_bits(dspi->regmap, SPI_CTAR(0),
-				SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));
-		tx_word = 0;
+		rx_count++;
 	}
 
-	dspi_pushr = dspi_data_to_pushr(dspi, tx_word);
-
-	if ((dspi->cs_change) && (!dspi->len))
-		dspi_pushr &= ~SPI_PUSHR_CONT;
-
-	regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr);
-
-	return tx_word + 1;
-}
-
-static void dspi_tcfq_read(struct fsl_dspi *dspi)
-{
-	int rx_word = is_double_byte_mode(dspi);
-
-	if (rx_word && (dspi->rx_end - dspi->rx) == 1)
-		rx_word = 0;
-
-	dspi_data_from_popr(dspi, rx_word);
+	return rx_count * (rx_word+1);
 }
 
 static int dspi_transfer_one_message(struct spi_master *master,
@@ -375,8 +355,8 @@ static int dspi_transfer_one_message(struct spi_master *master,
 	struct spi_device *spi = message->spi;
 	struct spi_transfer *transfer;
 	int status = 0;
-	enum dspi_trans_mode trans_mode;
 	u32 spi_tcr;
+	u32 spi_sr;
 
 	regmap_read(dspi->regmap, SPI_TCR, &spi_tcr);
 	dspi->spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr);
@@ -396,50 +376,68 @@ static int dspi_transfer_one_message(struct spi_master *master,
 
 		dspi->dataflags = 0;
 		dspi->tx = (void *)transfer->tx_buf;
+		dspi->tx_len = transfer->len;
 		dspi->tx_end = dspi->tx + transfer->len;
 		dspi->rx = transfer->rx_buf;
+		dspi->rx_len = transfer->len;
 		dspi->rx_end = dspi->rx + transfer->len;
-		dspi->len = transfer->len;
 
 		if (!dspi->rx)
 			dspi->dataflags |= TRAN_STATE_RX_VOID;
 
 		if (!dspi->tx)
 			dspi->dataflags |= TRAN_STATE_TX_VOID;
-
-		regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val);
+		/* stop module */
+		regmap_write(dspi->regmap, SPI_MCR,
+			dspi->cur_chip->mcr_val | SPI_MCR_HALT);
+		do
+			regmap_read(dspi->regmap, SPI_SR, &spi_sr);
+		while (spi_sr & SPI_SR_TXRXS);
+
+		/* clear fifos */
 		regmap_update_bits(dspi->regmap, SPI_MCR,
 				SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF,
 				SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF);
-		regmap_write(dspi->regmap, SPI_CTAR(0),
-				dspi->cur_chip->ctar_val);
-
-		trans_mode = dspi->devtype_data->trans_mode;
-		switch (trans_mode) {
-		case DSPI_EOQ_MODE:
-			regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE);
-			dspi_eoq_write(dspi);
-			break;
-		case DSPI_TCFQ_MODE:
-			regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE);
-			dspi_tcfq_write(dspi);
-			break;
-		default:
-			dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n",
-				trans_mode);
-			status = -EINVAL;
-			goto out;
-		}
 
-		if (wait_event_interruptible(dspi->waitq, dspi->waitflags))
+		/* configure SPI */
+		if (dspi->cur_chip->mcr_val & SPI_MCR_MASTER)
+			regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
+			     dspi->cur_chip->ctar_val);
+		else
+			regmap_write(dspi->regmap, SPI_CTAR0_SLAVE,
+			     dspi->cur_chip->ctar_val);
+
+		/* enable IRQs */
+		regmap_write(dspi->regmap, SPI_RSER,
+			     SPI_RSER_TCFQE | SPI_RSER_RFDFE);
+		/* prime 'frame pump' */
+		dspi_write(dspi);
+		/* start module */
+		regmap_update_bits(dspi->regmap, SPI_MCR, SPI_MCR_HALT, 0);
+
+		/* wait for the 'pump' to empty */
+		if (wait_event_interruptible(dspi->waitq, dspi->waitflags)) {
 			dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n");
+			status = -EIO;
+		}
 		dspi->waitflags = 0;
 
-		if (transfer->delay_usecs)
-			udelay(transfer->delay_usecs);
+		/* stop module */
+		regmap_write(dspi->regmap, SPI_MCR,
+			dspi->cur_chip->mcr_val | SPI_MCR_HALT);
+		do
+			regmap_read(dspi->regmap, SPI_SR, &spi_sr);
+		while (spi_sr & SPI_SR_TXRXS);
+
+		/* disable IRQs */
+		regmap_update_bits(dspi->regmap, SPI_RSER,
+				   SPI_RSER_TCFQE | SPI_RSER_RFDFE,
+				   0);
+		/* wait if required */
+		if ((transfer->delay_usecs) && (status >= 0))
+				udelay(transfer->delay_usecs);
 	}
 
-out:
 	message->status = status;
 	spi_finalize_current_message(master);
 
@@ -476,8 +474,9 @@ static int dspi_setup(struct spi_device *spi)
 	of_property_read_u32(spi->dev.of_node, "fsl,spi-sck-cs-delay",
 			&sck_cs_delay);
 
-	chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS |
-		SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
+	chip->mcr_val = SPI_MCR_PCSIS | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
+	if (!of_property_read_bool(spi->dev.of_node, "spi-slave-mode"))
+		chip->mcr_val |= SPI_MCR_MASTER;
 
 	chip->void_write_data = 0;
 
@@ -490,16 +489,22 @@ static int dspi_setup(struct spi_device *spi)
 	/* Set After SCK delay scale values */
 	ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate);
 
-	chip->ctar_val =  SPI_CTAR_FMSZ(fmsz)
-		| SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
-		| SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
-		| SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
-		| SPI_CTAR_PCSSCK(pcssck)
-		| SPI_CTAR_CSSCK(cssck)
-		| SPI_CTAR_PASC(pasc)
-		| SPI_CTAR_ASC(asc)
-		| SPI_CTAR_PBR(pbr)
-		| SPI_CTAR_BR(br);
+	if (chip->mcr_val & SPI_MCR_MASTER)
+		chip->ctar_val =  SPI_CTAR_FMSZ(fmsz)
+			| SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
+			| SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
+			| SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
+			| SPI_CTAR_PCSSCK(pcssck)
+			| SPI_CTAR_CSSCK(cssck)
+			| SPI_CTAR_PASC(pasc)
+			| SPI_CTAR_ASC(asc)
+			| SPI_CTAR_PBR(pbr)
+			| SPI_CTAR_BR(br);
+	else
+		chip->ctar_val =  SPI_CTAR0_SLAVE_FMSZ(fmsz)
+			| SPI_CTAR0_SLAVE_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
+			| SPI_CTAR0_SLAVE_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
+			;
 
 	spi_set_ctldata(spi, chip);
 
@@ -520,16 +525,21 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
 {
 	struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id;
 	struct spi_message *msg = dspi->cur_msg;
-	enum dspi_trans_mode trans_mode;
 	u32 spi_sr, spi_tcr;
 	u32 spi_tcnt, tcnt_diff;
 	int tx_word;
 
 	regmap_read(dspi->regmap, SPI_SR, &spi_sr);
-	regmap_write(dspi->regmap, SPI_SR, spi_sr);
 
+	/* a transfer happened. Read incoming data and write next one */
+	dspi_write(dspi);
+	dspi_read(dspi);
+
+	/* If a frame was shifted out, update the counter */
+	if (spi_sr & SPI_SR_TCFQF) {
+
+		regmap_write(dspi->regmap, SPI_SR, SPI_SR_TCFQF);
 
-	if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) {
 		tx_word = is_double_byte_mode(dspi);
 
 		regmap_read(dspi->regmap, SPI_TCR, &spi_tcr);
@@ -552,22 +562,15 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
 		msg->actual_length += tcnt_diff;
 
 		dspi->spi_tcnt = spi_tcnt;
+	}
 
-		trans_mode = dspi->devtype_data->trans_mode;
-		switch (trans_mode) {
-		case DSPI_EOQ_MODE:
-			dspi_eoq_read(dspi);
-			break;
-		case DSPI_TCFQ_MODE:
-			dspi_tcfq_read(dspi);
-			break;
-		default:
-			dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n",
-				trans_mode);
-				return IRQ_HANDLED;
-		}
+	/* If EOQ or all was sent and received then wake up */
+	if ((spi_sr & SPI_SR_EOQF) || ((!dspi->tx_len) && (!dspi->rx_len))) {
 
-		if (!dspi->len) {
+		regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF);
+
+		if ((!dspi->tx_len) && (!dspi->rx_len)) {
+			/* reset 'half-word' state if set */
 			if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) {
 				regmap_update_bits(dspi->regmap,
 						   SPI_CTAR(0),
@@ -575,22 +578,9 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
 						   SPI_FRAME_BITS(16));
 				dspi->dataflags &= ~TRAN_STATE_WORD_ODD_NUM;
 			}
-
+			/* wake driver up */
 			dspi->waitflags = 1;
 			wake_up_interruptible(&dspi->waitq);
-		} else {
-			switch (trans_mode) {
-			case DSPI_EOQ_MODE:
-				dspi_eoq_write(dspi);
-				break;
-			case DSPI_TCFQ_MODE:
-				dspi_tcfq_write(dspi);
-				break;
-			default:
-				dev_err(&dspi->pdev->dev,
-					"unsupported trans_mode %u\n",
-					trans_mode);
-			}
 		}
 	}
 
@@ -598,9 +588,9 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
 }
 
 static const struct of_device_id fsl_dspi_dt_ids[] = {
+	{ .compatible = "fsl,vf610-dspi-slave", .data = (void *)&vf610_data, },
 	{ .compatible = "fsl,vf610-dspi", .data = (void *)&vf610_data, },
-	{ .compatible = "fsl,ls1021a-v1.0-dspi",
-		.data = (void *)&ls1021a_v1_data, },
+	{ .compatible = "fsl,ls1021a-v1.0-dspi", .data = (void *)&ls1021a_v1_data, },
 	{ .compatible = "fsl,ls2085a-dspi", .data = (void *)&ls2085a_data, },
 	{ /* sentinel */ }
 };
@@ -679,13 +669,6 @@ static int dspi_probe(struct platform_device *pdev)
 	}
 	master->num_chipselect = cs_num;
 
-	ret = of_property_read_u32(np, "bus-num", &bus_num);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "can't get bus-num\n");
-		goto out_master_put;
-	}
-	master->bus_num = bus_num;
-
 	dspi->devtype_data = (struct fsl_dspi_devtype_data *)of_id->data;
 	if (!dspi->devtype_data) {
 		dev_err(&pdev->dev, "can't get devtype_data\n");
@@ -693,6 +676,13 @@ static int dspi_probe(struct platform_device *pdev)
 		goto out_master_put;
 	}
 
+	ret = of_property_read_u32(np, "bus-num", &bus_num);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "can't get bus-num\n");
+		goto out_master_put;
+	}
+	master->bus_num = bus_num;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(base)) {
@@ -742,6 +732,8 @@ static int dspi_probe(struct platform_device *pdev)
 		goto out_clk_put;
 	}
 
+	dev_info(&pdev->dev, "registered DSPI controller\n");
+
 	return ret;
 
 out_clk_put:
