static void set_bit_mode(struct fsl_dspi *dspi, unsigned char bits) { u32 temp; temp = readl(dspi->base + SPI_CTAR(dspi->cs)); temp &= ~SPI_FRAME_BITS_MASK; temp |= SPI_FRAME_BITS(bits); writel(temp, dspi->base + SPI_CTAR(dspi->cs)); }
static inline int is_double_byte_mode(struct fsl_dspi *dspi) { unsigned int val; regmap_read(dspi->regmap, SPI_CTAR(dspi->cs), &val); return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1; }
static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t) { struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); dspi->cur_transfer = t; dspi->cur_chip = spi_get_ctldata(spi); dspi->cs = spi->chip_select; dspi->void_write_data = dspi->cur_chip->void_write_data; dspi->dataflags = 0; dspi->tx = (void *)t->tx_buf; dspi->tx_end = dspi->tx + t->len; dspi->rx = t->rx_buf; dspi->rx_end = dspi->rx + t->len; dspi->len = t->len; if (!dspi->rx) dspi->dataflags |= TRAN_STATE_RX_VOID; if (!dspi->tx) dspi->dataflags |= TRAN_STATE_TX_VOID; writel(dspi->cur_chip->mcr_val, dspi->base + SPI_MCR); writel(dspi->cur_chip->ctar_val, dspi->base + SPI_CTAR(dspi->cs)); writel(SPI_RSER_EOQFE, dspi->base + SPI_RSER); if (t->speed_hz) writel(dspi->cur_chip->ctar_val, dspi->base + SPI_CTAR(dspi->cs)); dspi_transfer_write(dspi); if (wait_event_interruptible(dspi->waitq, dspi->waitflags)) dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n"); dspi->waitflags = 0; return t->len - dspi->len; }
static irqreturn_t dspi_interrupt(int irq, void *dev_id) { struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF); dspi_transfer_read(dspi); if (!dspi->len) { if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16)); dspi->waitflags = 1; wake_up_interruptible(&dspi->waitq); } else { dspi_transfer_write(dspi); return IRQ_HANDLED; } return IRQ_HANDLED; }
static inline int is_double_byte_mode(struct fsl_dspi *dspi) { return ((readl(dspi->base + SPI_CTAR(dspi->cs)) & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1; }
static int dspi_transfer_write(struct fsl_dspi *dspi) { int tx_count = 0; int tx_word; u16 d16; u8 d8; u32 dspi_pushr = 0; int first = 1; tx_word = is_double_byte_mode(dspi); /* If we are in word mode, but only have a single byte to transfer * then 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(dspi->cs), SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8)); tx_word = 0; } while (dspi->len && (tx_count < DSPI_FIFO_SIZE)) { if (tx_word) { if (dspi->len == 1) break; if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) { d16 = *(u16 *)dspi->tx; dspi->tx += 2; } else { d16 = dspi->void_write_data; } dspi_pushr = SPI_PUSHR_TXDATA(d16) | SPI_PUSHR_PCS(dspi->cs) | SPI_PUSHR_CTAS(dspi->cs) | SPI_PUSHR_CONT; dspi->len -= 2; } else { if (!(dspi->dataflags & TRAN_STATE_TX_VOID)) { d8 = *(u8 *)dspi->tx; dspi->tx++; } else { d8 = (u8)dspi->void_write_data; } dspi_pushr = SPI_PUSHR_TXDATA(d8) | SPI_PUSHR_PCS(dspi->cs) | SPI_PUSHR_CTAS(dspi->cs) | SPI_PUSHR_CONT; dspi->len--; } if (dspi->len == 0 || tx_count == DSPI_FIFO_SIZE - 1) { /* last transfer in the transfer */ dspi_pushr |= SPI_PUSHR_EOQ; } else if (tx_word && (dspi->len == 1)) dspi_pushr |= SPI_PUSHR_EOQ; if (first) { first = 0; dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */ } regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr); tx_count++; } return tx_count * (tx_word + 1); }