spi/s3c64xx: Correction for 16,32 bits bus width
We can't do without setting channel and bus width to same size. In order to do that, use loop read/writes in polling mode and appropriate burst size in DMA mode. Signed-off-by: Jassi Brar <jassi.brar@samsung.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
This commit is contained in:
Родитель
b42a81ca0f
Коммит
0c92ecf10d
|
@ -261,15 +261,25 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
|
|||
chcfg |= S3C64XX_SPI_CH_TXCH_ON;
|
||||
if (dma_mode) {
|
||||
modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
|
||||
s3c2410_dma_config(sdd->tx_dmach, 1);
|
||||
s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
|
||||
s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
|
||||
xfer->tx_dma, xfer->len);
|
||||
s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
|
||||
} else {
|
||||
unsigned char *buf = (unsigned char *) xfer->tx_buf;
|
||||
int i = 0;
|
||||
while (i < xfer->len)
|
||||
writeb(buf[i++], regs + S3C64XX_SPI_TX_DATA);
|
||||
switch (sdd->cur_bpw) {
|
||||
case 32:
|
||||
iowrite32_rep(regs + S3C64XX_SPI_TX_DATA,
|
||||
xfer->tx_buf, xfer->len / 4);
|
||||
break;
|
||||
case 16:
|
||||
iowrite16_rep(regs + S3C64XX_SPI_TX_DATA,
|
||||
xfer->tx_buf, xfer->len / 2);
|
||||
break;
|
||||
default:
|
||||
iowrite8_rep(regs + S3C64XX_SPI_TX_DATA,
|
||||
xfer->tx_buf, xfer->len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,7 +296,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
|
|||
writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
|
||||
| S3C64XX_SPI_PACKET_CNT_EN,
|
||||
regs + S3C64XX_SPI_PACKET_CNT);
|
||||
s3c2410_dma_config(sdd->rx_dmach, 1);
|
||||
s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
|
||||
s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
|
||||
xfer->rx_dma, xfer->len);
|
||||
s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
|
||||
|
@ -366,20 +376,26 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
|
|||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
unsigned char *buf;
|
||||
int i;
|
||||
|
||||
/* If it was only Tx */
|
||||
if (xfer->rx_buf == NULL) {
|
||||
sdd->state &= ~TXBUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
buf = xfer->rx_buf;
|
||||
while (i < xfer->len)
|
||||
buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA);
|
||||
|
||||
switch (sdd->cur_bpw) {
|
||||
case 32:
|
||||
ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
|
||||
xfer->rx_buf, xfer->len / 4);
|
||||
break;
|
||||
case 16:
|
||||
ioread16_rep(regs + S3C64XX_SPI_RX_DATA,
|
||||
xfer->rx_buf, xfer->len / 2);
|
||||
break;
|
||||
default:
|
||||
ioread8_rep(regs + S3C64XX_SPI_RX_DATA,
|
||||
xfer->rx_buf, xfer->len);
|
||||
break;
|
||||
}
|
||||
sdd->state &= ~RXBUSY;
|
||||
}
|
||||
|
||||
|
@ -434,15 +450,17 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
|
|||
switch (sdd->cur_bpw) {
|
||||
case 32:
|
||||
val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
|
||||
val |= S3C64XX_SPI_MODE_CH_TSZ_WORD;
|
||||
break;
|
||||
case 16:
|
||||
val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
|
||||
val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD;
|
||||
break;
|
||||
default:
|
||||
val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
|
||||
val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE;
|
||||
break;
|
||||
}
|
||||
val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */
|
||||
|
||||
writel(val, regs + S3C64XX_SPI_MODE_CFG);
|
||||
|
||||
|
@ -629,6 +647,14 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
|
|||
bpw = xfer->bits_per_word ? : spi->bits_per_word;
|
||||
speed = xfer->speed_hz ? : spi->max_speed_hz;
|
||||
|
||||
if (xfer->len % (bpw / 8)) {
|
||||
dev_err(&spi->dev,
|
||||
"Xfer length(%u) not a multiple of word size(%u)\n",
|
||||
xfer->len, bpw / 8);
|
||||
status = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
|
||||
sdd->cur_bpw = bpw;
|
||||
sdd->cur_speed = speed;
|
||||
|
|
Загрузка…
Ссылка в новой задаче