#define SG_MAXLEN              0xff00
 
+/*
+ * Flags for txrx functions.  More efficient that using an argument register for
+ * each one.
+ */
+#define TXRX_WRITE             (1<<0)  /* This is a write */
+#define TXRX_DEASSERT_CS       (1<<1)  /* De-assert CS at end of txrx */
+
 struct mxs_spi {
        struct mxs_ssp          ssp;
        struct completion       c;
 
 static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
                            unsigned char *buf, int len,
-                           int *first, int *last, int write)
+                           unsigned int flags)
 {
        struct mxs_ssp *ssp = &spi->ssp;
        struct dma_async_tx_descriptor *desc = NULL;
        ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT;
        ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs);
 
-       if (!write)
+       if (!(flags & TXRX_WRITE))
                ctrl0 |= BM_SSP_CTRL0_READ;
 
        /* Queue the DMA data transfer. */
        for (sg_count = 0; sg_count < sgs; sg_count++) {
+               /* Prepare the transfer descriptor. */
                min = min(len, desc_len);
 
-               /* Prepare the transfer descriptor. */
-               if ((sg_count + 1 == sgs) && *last)
+               /*
+                * De-assert CS on last segment if flag is set (i.e., no more
+                * transfers will follow)
+                */
+               if ((sg_count + 1 == sgs) && (flags & TXRX_DEASSERT_CS))
                        ctrl0 |= BM_SSP_CTRL0_IGNORE_CRC;
 
                if (ssp->devid == IMX23_SSP) {
 
                sg_init_one(&dma_xfer[sg_count].sg, sg_buf, min);
                ret = dma_map_sg(ssp->dev, &dma_xfer[sg_count].sg, 1,
-                       write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+                       (flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 
                len -= min;
                buf += min;
 
                desc = dmaengine_prep_slave_sg(ssp->dmach,
                                &dma_xfer[sg_count].sg, 1,
-                               write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
+                               (flags & TXRX_WRITE) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
                if (!desc) {
        while (--sg_count >= 0) {
 err_mapped:
                dma_unmap_sg(ssp->dev, &dma_xfer[sg_count].sg, 1,
-                       write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+                       (flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
        }
 
        kfree(dma_xfer);
 
 static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs,
                            unsigned char *buf, int len,
-                           int *first, int *last, int write)
+                           unsigned int flags)
 {
        struct mxs_ssp *ssp = &spi->ssp;
 
        mxs_spi_set_cs(spi, cs);
 
        while (len--) {
-               if (*last && len == 0)
+               if (len == 0 && (flags & TXRX_DEASSERT_CS))
                        writel(BM_SSP_CTRL0_IGNORE_CRC,
                               ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
 
                        writel(1, ssp->base + HW_SSP_XFER_SIZE);
                }
 
-               if (write)
+               if (flags & TXRX_WRITE)
                        writel(BM_SSP_CTRL0_READ,
                                ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
                else
                if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 1))
                        return -ETIMEDOUT;
 
-               if (write)
+               if (flags & TXRX_WRITE)
                        writel(*buf, ssp->base + HW_SSP_DATA(ssp));
 
                writel(BM_SSP_CTRL0_DATA_XFER,
                             ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
 
-               if (!write) {
+               if (!(flags & TXRX_WRITE)) {
                        if (mxs_ssp_wait(spi, HW_SSP_STATUS(ssp),
                                                BM_SSP_STATUS_FIFO_EMPTY, 0))
                                return -ETIMEDOUT;
 {
        struct mxs_spi *spi = spi_master_get_devdata(master);
        struct mxs_ssp *ssp = &spi->ssp;
-       int first, last;
        struct spi_transfer *t, *tmp_t;
+       unsigned int flag;
        int status = 0;
        int cs;
 
-       first = last = 0;
-
        cs = m->spi->chip_select;
 
        list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) {
                if (status)
                        break;
 
-               if (&t->transfer_list == m->transfers.next)
-                       first = 1;
-               if (&t->transfer_list == m->transfers.prev)
-                       last = 1;
+               /* De-assert on last transfer, inverted by cs_change flag */
+               flag = (&t->transfer_list == m->transfers.prev) ^ t->cs_change ?
+                      TXRX_DEASSERT_CS : 0;
                if ((t->rx_buf && t->tx_buf) || (t->rx_dma && t->tx_dma)) {
                        dev_err(ssp->dev,
                                "Cannot send and receive simultaneously\n");
                        if (t->tx_buf)
                                status = mxs_spi_txrx_pio(spi, cs,
                                                (void *)t->tx_buf,
-                                               t->len, &first, &last, 1);
+                                               t->len, flag | TXRX_WRITE);
                        if (t->rx_buf)
                                status = mxs_spi_txrx_pio(spi, cs,
                                                t->rx_buf, t->len,
-                                               &first, &last, 0);
+                                               flag);
                } else {
                        writel(BM_SSP_CTRL1_DMA_ENABLE,
                                ssp->base + HW_SSP_CTRL1(ssp) +
                        if (t->tx_buf)
                                status = mxs_spi_txrx_dma(spi, cs,
                                                (void *)t->tx_buf, t->len,
-                                               &first, &last, 1);
+                                               flag | TXRX_WRITE);
                        if (t->rx_buf)
                                status = mxs_spi_txrx_dma(spi, cs,
                                                t->rx_buf, t->len,
-                                               &first, &last, 0);
+                                               flag);
                }
 
                if (status) {
                }
 
                m->actual_length += t->len;
-               first = last = 0;
        }
 
        m->status = status;