Loading drivers/spi/spi-mxs.c +80 −109 Original line number Diff line number Diff line Loading @@ -57,31 +57,50 @@ #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; unsigned int sck; /* Rate requested (vs actual) */ }; static int mxs_spi_setup_transfer(struct spi_device *dev, struct spi_transfer *t) const struct spi_transfer *t) { struct mxs_spi *spi = spi_master_get_devdata(dev->master); struct mxs_ssp *ssp = &spi->ssp; uint32_t hz = 0; const unsigned int hz = min(dev->max_speed_hz, t->speed_hz); hz = dev->max_speed_hz; if (t && t->speed_hz) hz = min(hz, t->speed_hz); if (hz == 0) { dev_err(&dev->dev, "Cannot continue with zero clock\n"); dev_err(&dev->dev, "SPI clock rate of zero not allowed\n"); return -EINVAL; } if (hz != spi->sck) { mxs_ssp_set_clk_rate(ssp, hz); /* * Save requested rate, hz, rather than the actual rate, * ssp->clk_rate. Otherwise we would set the rate every trasfer * when the actual rate is not quite the same as requested rate. */ spi->sck = hz; /* * Perhaps we should return an error if the actual clock is * nowhere close to what was requested? */ } writel(BM_SSP_CTRL0_LOCK_CS, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); writel(BF_SSP_CTRL1_SSP_MODE(BV_SSP_CTRL1_SSP_MODE__SPI) | BF_SSP_CTRL1_WORD_LENGTH (BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) | BF_SSP_CTRL1_WORD_LENGTH(BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) | ((dev->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) | ((dev->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0), ssp->base + HW_SSP_CTRL1(ssp)); Loading @@ -94,26 +113,15 @@ static int mxs_spi_setup_transfer(struct spi_device *dev, static int mxs_spi_setup(struct spi_device *dev) { int err = 0; if (!dev->bits_per_word) dev->bits_per_word = 8; if (dev->mode & ~(SPI_CPOL | SPI_CPHA)) return -EINVAL; err = mxs_spi_setup_transfer(dev, NULL); if (err) { dev_err(&dev->dev, "Failed to setup transfer, error = %d\n", err); } return err; return 0; } static uint32_t mxs_spi_cs_to_reg(unsigned cs) static u32 mxs_spi_cs_to_reg(unsigned cs) { uint32_t select = 0; u32 select = 0; /* * i.MX28 Datasheet: 17.10.1: HW_SSP_CTRL0 Loading @@ -131,43 +139,11 @@ static uint32_t mxs_spi_cs_to_reg(unsigned cs) return select; } static void mxs_spi_set_cs(struct mxs_spi *spi, unsigned cs) { const uint32_t mask = BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ; uint32_t select; struct mxs_ssp *ssp = &spi->ssp; writel(mask, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); select = mxs_spi_cs_to_reg(cs); writel(select, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); } static inline void mxs_spi_enable(struct mxs_spi *spi) { struct mxs_ssp *ssp = &spi->ssp; writel(BM_SSP_CTRL0_LOCK_CS, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); } static inline void mxs_spi_disable(struct mxs_spi *spi) { struct mxs_ssp *ssp = &spi->ssp; writel(BM_SSP_CTRL0_LOCK_CS, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); } static int mxs_ssp_wait(struct mxs_spi *spi, int offset, int mask, bool set) { const unsigned long timeout = jiffies + msecs_to_jiffies(SSP_TIMEOUT); struct mxs_ssp *ssp = &spi->ssp; uint32_t reg; u32 reg; do { reg = readl_relaxed(ssp->base + offset); Loading Loading @@ -200,9 +176,9 @@ static irqreturn_t mxs_ssp_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, static int mxs_spi_txrx_dma(struct mxs_spi *spi, 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; Loading @@ -211,11 +187,11 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, const int sgs = DIV_ROUND_UP(len, desc_len); int sg_count; int min, ret; uint32_t ctrl0; u32 ctrl0; struct page *vm_page; void *sg_buf; struct { uint32_t pio[4]; u32 pio[4]; struct scatterlist sg; } *dma_xfer; Loading @@ -228,21 +204,25 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, INIT_COMPLETION(spi->c); /* Chip select was already programmed into CTRL0 */ ctrl0 = readl(ssp->base + HW_SSP_CTRL0); ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT; ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs); ctrl0 &= ~(BM_SSP_CTRL0_XFER_COUNT | BM_SSP_CTRL0_IGNORE_CRC | BM_SSP_CTRL0_READ); ctrl0 |= BM_SSP_CTRL0_DATA_XFER; if (*first) ctrl0 |= BM_SSP_CTRL0_LOCK_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) { Loading @@ -267,7 +247,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, 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; Loading @@ -287,7 +267,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, 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) { Loading Loading @@ -324,7 +304,7 @@ err_vmalloc: 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); Loading @@ -332,20 +312,19 @@ err_mapped: return ret; } static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, static int mxs_spi_txrx_pio(struct mxs_spi *spi, unsigned char *buf, int len, int *first, int *last, int write) unsigned int flags) { struct mxs_ssp *ssp = &spi->ssp; if (*first) mxs_spi_enable(spi); mxs_spi_set_cs(spi, cs); writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); while (len--) { if (*last && len == 0) mxs_spi_disable(spi); if (len == 0 && (flags & TXRX_DEASSERT_CS)) writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); if (ssp->devid == IMX23_SSP) { writel(BM_SSP_CTRL0_XFER_COUNT, Loading @@ -356,7 +335,7 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, 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 Loading @@ -369,13 +348,13 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, 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; Loading @@ -400,14 +379,15 @@ static int mxs_spi_transfer_one(struct spi_master *master, { 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; /* Program CS register bits here, it will be used for all transfers. */ writel(BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); writel(mxs_spi_cs_to_reg(m->spi->chip_select), ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) { Loading @@ -415,16 +395,9 @@ static int mxs_spi_transfer_one(struct spi_master *master, if (status) break; if (&t->transfer_list == m->transfers.next) first = 1; if (&t->transfer_list == m->transfers.prev) last = 1; if ((t->rx_buf && t->tx_buf) || (t->rx_dma && t->tx_dma)) { dev_err(ssp->dev, "Cannot send and receive simultaneously\n"); status = -EINVAL; break; } /* De-assert on last transfer, inverted by cs_change flag */ flag = (&t->transfer_list == m->transfers.prev) ^ t->cs_change ? TXRX_DEASSERT_CS : 0; /* * Small blocks can be transfered via PIO. Loading @@ -441,26 +414,26 @@ static int mxs_spi_transfer_one(struct spi_master *master, STMP_OFFSET_REG_CLR); if (t->tx_buf) status = mxs_spi_txrx_pio(spi, cs, status = mxs_spi_txrx_pio(spi, (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, status = mxs_spi_txrx_pio(spi, t->rx_buf, t->len, &first, &last, 0); flag); } else { writel(BM_SSP_CTRL1_DMA_ENABLE, ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_SET); if (t->tx_buf) status = mxs_spi_txrx_dma(spi, cs, status = mxs_spi_txrx_dma(spi, (void *)t->tx_buf, t->len, &first, &last, 1); flag | TXRX_WRITE); if (t->rx_buf) status = mxs_spi_txrx_dma(spi, cs, status = mxs_spi_txrx_dma(spi, t->rx_buf, t->len, &first, &last, 0); flag); } if (status) { Loading @@ -469,7 +442,6 @@ static int mxs_spi_transfer_one(struct spi_master *master, } m->actual_length += t->len; first = last = 0; } m->status = status; Loading Loading @@ -563,7 +535,6 @@ static int mxs_spi_probe(struct platform_device *pdev) goto out_dma_release; clk_set_rate(ssp->clk, clk_freq); ssp->clk_rate = clk_get_rate(ssp->clk) / 1000; ret = stmp_reset_block(ssp->base); if (ret) Loading Loading
drivers/spi/spi-mxs.c +80 −109 Original line number Diff line number Diff line Loading @@ -57,31 +57,50 @@ #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; unsigned int sck; /* Rate requested (vs actual) */ }; static int mxs_spi_setup_transfer(struct spi_device *dev, struct spi_transfer *t) const struct spi_transfer *t) { struct mxs_spi *spi = spi_master_get_devdata(dev->master); struct mxs_ssp *ssp = &spi->ssp; uint32_t hz = 0; const unsigned int hz = min(dev->max_speed_hz, t->speed_hz); hz = dev->max_speed_hz; if (t && t->speed_hz) hz = min(hz, t->speed_hz); if (hz == 0) { dev_err(&dev->dev, "Cannot continue with zero clock\n"); dev_err(&dev->dev, "SPI clock rate of zero not allowed\n"); return -EINVAL; } if (hz != spi->sck) { mxs_ssp_set_clk_rate(ssp, hz); /* * Save requested rate, hz, rather than the actual rate, * ssp->clk_rate. Otherwise we would set the rate every trasfer * when the actual rate is not quite the same as requested rate. */ spi->sck = hz; /* * Perhaps we should return an error if the actual clock is * nowhere close to what was requested? */ } writel(BM_SSP_CTRL0_LOCK_CS, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); writel(BF_SSP_CTRL1_SSP_MODE(BV_SSP_CTRL1_SSP_MODE__SPI) | BF_SSP_CTRL1_WORD_LENGTH (BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) | BF_SSP_CTRL1_WORD_LENGTH(BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) | ((dev->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) | ((dev->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0), ssp->base + HW_SSP_CTRL1(ssp)); Loading @@ -94,26 +113,15 @@ static int mxs_spi_setup_transfer(struct spi_device *dev, static int mxs_spi_setup(struct spi_device *dev) { int err = 0; if (!dev->bits_per_word) dev->bits_per_word = 8; if (dev->mode & ~(SPI_CPOL | SPI_CPHA)) return -EINVAL; err = mxs_spi_setup_transfer(dev, NULL); if (err) { dev_err(&dev->dev, "Failed to setup transfer, error = %d\n", err); } return err; return 0; } static uint32_t mxs_spi_cs_to_reg(unsigned cs) static u32 mxs_spi_cs_to_reg(unsigned cs) { uint32_t select = 0; u32 select = 0; /* * i.MX28 Datasheet: 17.10.1: HW_SSP_CTRL0 Loading @@ -131,43 +139,11 @@ static uint32_t mxs_spi_cs_to_reg(unsigned cs) return select; } static void mxs_spi_set_cs(struct mxs_spi *spi, unsigned cs) { const uint32_t mask = BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ; uint32_t select; struct mxs_ssp *ssp = &spi->ssp; writel(mask, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); select = mxs_spi_cs_to_reg(cs); writel(select, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); } static inline void mxs_spi_enable(struct mxs_spi *spi) { struct mxs_ssp *ssp = &spi->ssp; writel(BM_SSP_CTRL0_LOCK_CS, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); } static inline void mxs_spi_disable(struct mxs_spi *spi) { struct mxs_ssp *ssp = &spi->ssp; writel(BM_SSP_CTRL0_LOCK_CS, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); } static int mxs_ssp_wait(struct mxs_spi *spi, int offset, int mask, bool set) { const unsigned long timeout = jiffies + msecs_to_jiffies(SSP_TIMEOUT); struct mxs_ssp *ssp = &spi->ssp; uint32_t reg; u32 reg; do { reg = readl_relaxed(ssp->base + offset); Loading Loading @@ -200,9 +176,9 @@ static irqreturn_t mxs_ssp_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, static int mxs_spi_txrx_dma(struct mxs_spi *spi, 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; Loading @@ -211,11 +187,11 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, const int sgs = DIV_ROUND_UP(len, desc_len); int sg_count; int min, ret; uint32_t ctrl0; u32 ctrl0; struct page *vm_page; void *sg_buf; struct { uint32_t pio[4]; u32 pio[4]; struct scatterlist sg; } *dma_xfer; Loading @@ -228,21 +204,25 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, INIT_COMPLETION(spi->c); /* Chip select was already programmed into CTRL0 */ ctrl0 = readl(ssp->base + HW_SSP_CTRL0); ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT; ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs); ctrl0 &= ~(BM_SSP_CTRL0_XFER_COUNT | BM_SSP_CTRL0_IGNORE_CRC | BM_SSP_CTRL0_READ); ctrl0 |= BM_SSP_CTRL0_DATA_XFER; if (*first) ctrl0 |= BM_SSP_CTRL0_LOCK_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) { Loading @@ -267,7 +247,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, 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; Loading @@ -287,7 +267,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, 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) { Loading Loading @@ -324,7 +304,7 @@ err_vmalloc: 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); Loading @@ -332,20 +312,19 @@ err_mapped: return ret; } static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, static int mxs_spi_txrx_pio(struct mxs_spi *spi, unsigned char *buf, int len, int *first, int *last, int write) unsigned int flags) { struct mxs_ssp *ssp = &spi->ssp; if (*first) mxs_spi_enable(spi); mxs_spi_set_cs(spi, cs); writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); while (len--) { if (*last && len == 0) mxs_spi_disable(spi); if (len == 0 && (flags & TXRX_DEASSERT_CS)) writel(BM_SSP_CTRL0_IGNORE_CRC, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); if (ssp->devid == IMX23_SSP) { writel(BM_SSP_CTRL0_XFER_COUNT, Loading @@ -356,7 +335,7 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, 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 Loading @@ -369,13 +348,13 @@ static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs, 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; Loading @@ -400,14 +379,15 @@ static int mxs_spi_transfer_one(struct spi_master *master, { 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; /* Program CS register bits here, it will be used for all transfers. */ writel(BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); writel(mxs_spi_cs_to_reg(m->spi->chip_select), ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) { Loading @@ -415,16 +395,9 @@ static int mxs_spi_transfer_one(struct spi_master *master, if (status) break; if (&t->transfer_list == m->transfers.next) first = 1; if (&t->transfer_list == m->transfers.prev) last = 1; if ((t->rx_buf && t->tx_buf) || (t->rx_dma && t->tx_dma)) { dev_err(ssp->dev, "Cannot send and receive simultaneously\n"); status = -EINVAL; break; } /* De-assert on last transfer, inverted by cs_change flag */ flag = (&t->transfer_list == m->transfers.prev) ^ t->cs_change ? TXRX_DEASSERT_CS : 0; /* * Small blocks can be transfered via PIO. Loading @@ -441,26 +414,26 @@ static int mxs_spi_transfer_one(struct spi_master *master, STMP_OFFSET_REG_CLR); if (t->tx_buf) status = mxs_spi_txrx_pio(spi, cs, status = mxs_spi_txrx_pio(spi, (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, status = mxs_spi_txrx_pio(spi, t->rx_buf, t->len, &first, &last, 0); flag); } else { writel(BM_SSP_CTRL1_DMA_ENABLE, ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_SET); if (t->tx_buf) status = mxs_spi_txrx_dma(spi, cs, status = mxs_spi_txrx_dma(spi, (void *)t->tx_buf, t->len, &first, &last, 1); flag | TXRX_WRITE); if (t->rx_buf) status = mxs_spi_txrx_dma(spi, cs, status = mxs_spi_txrx_dma(spi, t->rx_buf, t->len, &first, &last, 0); flag); } if (status) { Loading @@ -469,7 +442,6 @@ static int mxs_spi_transfer_one(struct spi_master *master, } m->actual_length += t->len; first = last = 0; } m->status = status; Loading Loading @@ -563,7 +535,6 @@ static int mxs_spi_probe(struct platform_device *pdev) goto out_dma_release; clk_set_rate(ssp->clk, clk_freq); ssp->clk_rate = clk_get_rate(ssp->clk) / 1000; ret = stmp_reset_block(ssp->base); if (ret) Loading