diff options
Diffstat (limited to 'drivers/spi/spi-rockchip.c')
| -rw-r--r-- | drivers/spi/spi-rockchip.c | 62 | 
1 files changed, 22 insertions, 40 deletions
| diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index fdcf3076681b..51ef632bca52 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -164,7 +164,6 @@ enum rockchip_ssi_type {  struct rockchip_spi_dma_data {  	struct dma_chan *ch; -	enum dma_transfer_direction direction;  	dma_addr_t addr;  }; @@ -202,12 +201,11 @@ struct rockchip_spi {  	bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM]; -	u32 use_dma; +	bool use_dma;  	struct sg_table tx_sg;  	struct sg_table rx_sg;  	struct rockchip_spi_dma_data dma_rx;  	struct rockchip_spi_dma_data dma_tx; -	struct dma_slave_caps dma_caps;  };  static inline void spi_enable_chip(struct rockchip_spi *rs, int enable) @@ -381,6 +379,8 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi *rs)  {  	int remain = 0; +	spi_enable_chip(rs, 1); +  	do {  		if (rs->tx) {  			remain = rs->tx_end - rs->tx; @@ -445,6 +445,9 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)  	struct dma_slave_config rxconf, txconf;  	struct dma_async_tx_descriptor *rxdesc, *txdesc; +	memset(&rxconf, 0, sizeof(rxconf)); +	memset(&txconf, 0, sizeof(txconf)); +  	spin_lock_irqsave(&rs->lock, flags);  	rs->state &= ~RXBUSY;  	rs->state &= ~TXBUSY; @@ -452,19 +455,16 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)  	rxdesc = NULL;  	if (rs->rx) { -		rxconf.direction = rs->dma_rx.direction; +		rxconf.direction = DMA_DEV_TO_MEM;  		rxconf.src_addr = rs->dma_rx.addr;  		rxconf.src_addr_width = rs->n_bytes; -		if (rs->dma_caps.max_burst > 4) -			rxconf.src_maxburst = 4; -		else -			rxconf.src_maxburst = 1; +		rxconf.src_maxburst = 1;  		dmaengine_slave_config(rs->dma_rx.ch, &rxconf);  		rxdesc = dmaengine_prep_slave_sg(  				rs->dma_rx.ch,  				rs->rx_sg.sgl, rs->rx_sg.nents, -				rs->dma_rx.direction, DMA_PREP_INTERRUPT); +				DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);  		if (!rxdesc)  			return -EINVAL; @@ -474,19 +474,16 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)  	txdesc = NULL;  	if (rs->tx) { -		txconf.direction = rs->dma_tx.direction; +		txconf.direction = DMA_MEM_TO_DEV;  		txconf.dst_addr = rs->dma_tx.addr;  		txconf.dst_addr_width = rs->n_bytes; -		if (rs->dma_caps.max_burst > 4) -			txconf.dst_maxburst = 4; -		else -			txconf.dst_maxburst = 1; +		txconf.dst_maxburst = rs->fifo_len / 2;  		dmaengine_slave_config(rs->dma_tx.ch, &txconf);  		txdesc = dmaengine_prep_slave_sg(  				rs->dma_tx.ch,  				rs->tx_sg.sgl, rs->tx_sg.nents, -				rs->dma_tx.direction, DMA_PREP_INTERRUPT); +				DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);  		if (!txdesc) {  			if (rxdesc)  				dmaengine_terminate_sync(rs->dma_rx.ch); @@ -506,6 +503,8 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)  		dma_async_issue_pending(rs->dma_rx.ch);  	} +	spi_enable_chip(rs, 1); +  	if (txdesc) {  		spin_lock_irqsave(&rs->lock, flags);  		rs->state |= TXBUSY; @@ -514,7 +513,8 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)  		dma_async_issue_pending(rs->dma_tx.ch);  	} -	return 0; +	/* 1 means the transfer is in progress */ +	return 1;  }  static void rockchip_spi_config(struct rockchip_spi *rs) @@ -578,7 +578,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs)  	writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_TXFTLR);  	writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_RXFTLR); -	writel_relaxed(0, rs->regs + ROCKCHIP_SPI_DMATDLR); +	writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_DMATDLR);  	writel_relaxed(0, rs->regs + ROCKCHIP_SPI_DMARDLR);  	writel_relaxed(dmacr, rs->regs + ROCKCHIP_SPI_DMACR); @@ -597,7 +597,6 @@ static int rockchip_spi_transfer_one(  		struct spi_device *spi,  		struct spi_transfer *xfer)  { -	int ret = 0;  	struct rockchip_spi *rs = spi_master_get_devdata(master);  	WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) && @@ -635,30 +634,16 @@ static int rockchip_spi_transfer_one(  	/* we need prepare dma before spi was enabled */  	if (master->can_dma && master->can_dma(master, spi, xfer)) -		rs->use_dma = 1; +		rs->use_dma = true;  	else -		rs->use_dma = 0; +		rs->use_dma = false;  	rockchip_spi_config(rs); -	if (rs->use_dma) { -		if (rs->tmode == CR0_XFM_RO) { -			/* rx: dma must be prepared first */ -			ret = rockchip_spi_prepare_dma(rs); -			spi_enable_chip(rs, 1); -		} else { -			/* tx or tr: spi must be enabled first */ -			spi_enable_chip(rs, 1); -			ret = rockchip_spi_prepare_dma(rs); -		} -		/* successful DMA prepare means the transfer is in progress */ -		ret = ret ? ret : 1; -	} else { -		spi_enable_chip(rs, 1); -		ret = rockchip_spi_pio_transfer(rs); -	} +	if (rs->use_dma) +		return rockchip_spi_prepare_dma(rs); -	return ret; +	return rockchip_spi_pio_transfer(rs);  }  static bool rockchip_spi_can_dma(struct spi_master *master, @@ -780,11 +765,8 @@ static int rockchip_spi_probe(struct platform_device *pdev)  	}  	if (rs->dma_tx.ch && rs->dma_rx.ch) { -		dma_get_slave_caps(rs->dma_rx.ch, &(rs->dma_caps));  		rs->dma_tx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_TXDR);  		rs->dma_rx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_RXDR); -		rs->dma_tx.direction = DMA_MEM_TO_DEV; -		rs->dma_rx.direction = DMA_DEV_TO_MEM;  		master->can_dma = rockchip_spi_can_dma;  		master->dma_tx = rs->dma_tx.ch; |