Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c92ecf1 authored by Jassi Brar's avatar Jassi Brar Committed by Grant Likely
Browse files

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: default avatarJassi Brar <jassi.brar@samsung.com>
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parent b42a81ca
Loading
Loading
Loading
Loading
+41 −15
Original line number Original line Diff line number Diff line
@@ -261,15 +261,25 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
		if (dma_mode) {
		if (dma_mode) {
			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
			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,
			s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
						xfer->tx_dma, xfer->len);
						xfer->tx_dma, xfer->len);
			s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
			s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
		} else {
		} else {
			unsigned char *buf = (unsigned char *) xfer->tx_buf;
			switch (sdd->cur_bpw) {
			int i = 0;
			case 32:
			while (i < xfer->len)
				iowrite32_rep(regs + S3C64XX_SPI_TX_DATA,
				writeb(buf[i++], 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)
			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
					| S3C64XX_SPI_PACKET_CNT_EN,
					| S3C64XX_SPI_PACKET_CNT_EN,
					regs + S3C64XX_SPI_PACKET_CNT);
					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,
			s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
						xfer->rx_dma, xfer->len);
						xfer->rx_dma, xfer->len);
			s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
			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;
				return -EIO;
		}
		}
	} else {
	} else {
		unsigned char *buf;
		int i;

		/* If it was only Tx */
		/* If it was only Tx */
		if (xfer->rx_buf == NULL) {
		if (xfer->rx_buf == NULL) {
			sdd->state &= ~TXBUSY;
			sdd->state &= ~TXBUSY;
			return 0;
			return 0;
		}
		}


		i = 0;
		switch (sdd->cur_bpw) {
		buf = xfer->rx_buf;
		case 32:
		while (i < xfer->len)
			ioread32_rep(regs + S3C64XX_SPI_RX_DATA,
			buf[i++] = readb(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;
		sdd->state &= ~RXBUSY;
	}
	}


@@ -434,15 +450,17 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
	switch (sdd->cur_bpw) {
	switch (sdd->cur_bpw) {
	case 32:
	case 32:
		val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
		val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
		val |= S3C64XX_SPI_MODE_CH_TSZ_WORD;
		break;
		break;
	case 16:
	case 16:
		val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
		val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
		val |= S3C64XX_SPI_MODE_CH_TSZ_HALFWORD;
		break;
		break;
	default:
	default:
		val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
		val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
		val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE;
		break;
		break;
	}
	}
	val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */


	writel(val, regs + S3C64XX_SPI_MODE_CFG);
	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;
		bpw = xfer->bits_per_word ? : spi->bits_per_word;
		speed = xfer->speed_hz ? : spi->max_speed_hz;
		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) {
		if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
			sdd->cur_bpw = bpw;
			sdd->cur_bpw = bpw;
			sdd->cur_speed = speed;
			sdd->cur_speed = speed;