Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi: mediatek: fix spi incorrect endian usage

TX_ENDIAN/RX_ENDIAN bits define whether to reverse the endian
order of the data DMA from/to memory. The endian order should
keep the same with cpu endian.

Signed-off-by: Leilk Liu <leilk.liu@mediatek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Leilk Liu and committed by
Mark Brown
44f636da c5e5cd28

+16 -24
+16 -22
drivers/spi/spi-mt65xx.c
··· 122 122 static const struct mtk_chip_config mtk_default_chip_info = { 123 123 .rx_mlsb = 1, 124 124 .tx_mlsb = 1, 125 - .tx_endian = 0, 126 - .rx_endian = 0, 127 125 }; 128 126 129 127 static const struct of_device_id mtk_spi_of_match[] = { ··· 159 161 reg_val |= (chip_config->rx_mlsb << SPI_CMD_RXMSBF_OFFSET); 160 162 161 163 /* set the tx/rx endian */ 162 - reg_val &= ~(SPI_CMD_TX_ENDIAN | SPI_CMD_RX_ENDIAN); 163 - reg_val |= (chip_config->tx_endian << SPI_CMD_TX_ENDIAN_OFFSET); 164 - reg_val |= (chip_config->rx_endian << SPI_CMD_RX_ENDIAN_OFFSET); 164 + #ifdef __LITTLE_ENDIAN 165 + reg_val &= ~SPI_CMD_TX_ENDIAN; 166 + reg_val &= ~SPI_CMD_RX_ENDIAN; 167 + #else 168 + reg_val |= SPI_CMD_TX_ENDIAN; 169 + reg_val |= SPI_CMD_RX_ENDIAN; 170 + #endif 165 171 166 172 /* set finish and pause interrupt always enable */ 167 173 reg_val |= SPI_CMD_FINISH_IE | SPI_CMD_PAUSE_EN; ··· 354 352 struct spi_device *spi, 355 353 struct spi_transfer *xfer) 356 354 { 357 - int cnt, i; 355 + int cnt; 358 356 struct mtk_spi *mdata = spi_master_get_devdata(master); 359 357 360 358 mdata->cur_transfer = xfer; ··· 366 364 cnt = xfer->len / 4 + 1; 367 365 else 368 366 cnt = xfer->len / 4; 369 - 370 - for (i = 0; i < cnt; i++) 371 - writel(*((u32 *)xfer->tx_buf + i), 372 - mdata->base + SPI_TX_DATA_REG); 367 + iowrite32_rep(mdata->base + SPI_TX_DATA_REG, xfer->tx_buf, cnt); 373 368 374 369 mtk_spi_enable_transfer(master); 375 370 ··· 436 437 437 438 static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id) 438 439 { 439 - u32 cmd, reg_val, i; 440 + u32 cmd, reg_val, cnt; 440 441 struct spi_master *master = dev_id; 441 442 struct mtk_spi *mdata = spi_master_get_devdata(master); 442 443 struct spi_transfer *trans = mdata->cur_transfer; ··· 448 449 mdata->state = MTK_SPI_IDLE; 449 450 450 451 if (!master->can_dma(master, master->cur_msg->spi, trans)) { 451 - /* xfer len is not N*4 bytes every time in a transfer, 452 - * but SPI_RX_DATA_REG must reads 4 bytes once, 453 - * so rx buffer byte by byte. 454 - */ 455 452 if (trans->rx_buf) { 456 - for (i = 0; i < mdata->xfer_len; i++) { 457 - if (i % 4 == 0) 458 - reg_val = 459 - readl(mdata->base + SPI_RX_DATA_REG); 460 - *((u8 *)(trans->rx_buf + i)) = 461 - (reg_val >> ((i % 4) * 8)) & 0xff; 462 - } 453 + if (mdata->xfer_len % 4) 454 + cnt = mdata->xfer_len / 4 + 1; 455 + else 456 + cnt = mdata->xfer_len / 4; 457 + ioread32_rep(mdata->base + SPI_RX_DATA_REG, 458 + trans->rx_buf, cnt); 463 459 } 464 460 spi_finalize_current_transfer(master); 465 461 return IRQ_HANDLED;
-2
include/linux/platform_data/spi-mt65xx.h
··· 16 16 struct mtk_chip_config { 17 17 u32 tx_mlsb; 18 18 u32 rx_mlsb; 19 - u32 tx_endian; 20 - u32 rx_endian; 21 19 }; 22 20 #endif