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

Commit 5a670445 authored by Florian Fainelli's avatar Florian Fainelli Committed by Ralf Baechle
Browse files

MIPS: BCM63xx: Fix SPI message control register handling for BCM6338/6348.



BCM6338 and BCM6348 have a message control register width of 8 bits, instead
of 16-bits like what the SPI driver assumes right now. Also the SPI message
type shift value of 14 is actually 6 for these SoCs.
This resulted in transmit FIFO corruption because we were writing 16-bits
to an 8-bits wide register, thus spanning on the first byte of the transmit
FIFO, which had already been filed in bcm63xx_spi_fill_txrx_fifo().

Fix this by passing the message control register width and message type
shift through platform data back to the SPI driver so that it can use
it properly.

Signed-off-by: default avatarFlorian Fainelli <florian@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: grant.likely@secretlab.ca
Cc: spi-devel-general@lists.sourceforge.net
Cc: jonas.gorski@gmail.com
Patchwork: https://patchwork.linux-mips.org/patch/3983/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent c54de490
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -106,11 +106,15 @@ int __init bcm63xx_spi_register(void)
	if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
		spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1;
		spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE;
		spi_pdata.msg_type_shift = SPI_6338_MSG_TYPE_SHIFT;
		spi_pdata.msg_ctl_width = SPI_6338_MSG_CTL_WIDTH;
	}

	if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
		spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
		spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
		spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT;
		spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH;
	}

	bcm63xx_spi_regs_init();
+2 −0
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@ int __init bcm63xx_spi_register(void);

struct bcm63xx_spi_pdata {
	unsigned int	fifo_size;
	unsigned int	msg_type_shift;
	unsigned int	msg_ctl_width;
	int		bus_num;
	int		num_chipselect;
	u32		speed_hz;
+10 −3
Original line number Diff line number Diff line
@@ -1054,7 +1054,8 @@
#define SPI_6338_FILL_BYTE		0x07
#define SPI_6338_MSG_TAIL		0x09
#define SPI_6338_RX_TAIL		0x0b
#define SPI_6338_MSG_CTL		0x40
#define SPI_6338_MSG_CTL		0x40	/* 8-bits register */
#define SPI_6338_MSG_CTL_WIDTH		8
#define SPI_6338_MSG_DATA		0x41
#define SPI_6338_MSG_DATA_SIZE		0x3f
#define SPI_6338_RX_DATA		0x80
@@ -1070,7 +1071,8 @@
#define SPI_6348_FILL_BYTE		0x07
#define SPI_6348_MSG_TAIL		0x09
#define SPI_6348_RX_TAIL		0x0b
#define SPI_6348_MSG_CTL		0x40
#define SPI_6348_MSG_CTL		0x40	/* 8-bits register */
#define SPI_6348_MSG_CTL_WIDTH		8
#define SPI_6348_MSG_DATA		0x41
#define SPI_6348_MSG_DATA_SIZE		0x3f
#define SPI_6348_RX_DATA		0x80
@@ -1078,6 +1080,7 @@

/* BCM 6358 SPI core */
#define SPI_6358_MSG_CTL		0x00	/* 16-bits register */
#define SPI_6358_MSG_CTL_WIDTH		16
#define SPI_6358_MSG_DATA		0x02
#define SPI_6358_MSG_DATA_SIZE		0x21e
#define SPI_6358_RX_DATA		0x400
@@ -1094,6 +1097,7 @@

/* BCM 6358 SPI core */
#define SPI_6368_MSG_CTL		0x00	/* 16-bits register */
#define SPI_6368_MSG_CTL_WIDTH		16
#define SPI_6368_MSG_DATA		0x02
#define SPI_6368_MSG_DATA_SIZE		0x21e
#define SPI_6368_RX_DATA		0x400
@@ -1115,7 +1119,10 @@
#define SPI_HD_W			0x01
#define SPI_HD_R			0x02
#define SPI_BYTE_CNT_SHIFT		0
#define SPI_MSG_TYPE_SHIFT		14
#define SPI_6338_MSG_TYPE_SHIFT		6
#define SPI_6348_MSG_TYPE_SHIFT		6
#define SPI_6358_MSG_TYPE_SHIFT		14
#define SPI_6368_MSG_TYPE_SHIFT		14

/* Command */
#define SPI_CMD_NOOP			0x00
+26 −5
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ struct bcm63xx_spi {
	/* Platform data */
	u32			speed_hz;
	unsigned		fifo_size;
	unsigned int		msg_type_shift;
	unsigned int		msg_ctl_width;

	/* Data buffers */
	const unsigned char	*tx_ptr;
@@ -221,13 +223,20 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
	msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);

	if (t->rx_buf && t->tx_buf)
		msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT);
		msg_ctl |= (SPI_FD_RW << bs->msg_type_shift);
	else if (t->rx_buf)
		msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT);
		msg_ctl |= (SPI_HD_R << bs->msg_type_shift);
	else if (t->tx_buf)
		msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT);
		msg_ctl |= (SPI_HD_W << bs->msg_type_shift);

	switch (bs->msg_ctl_width) {
	case 8:
		bcm_spi_writeb(bs, msg_ctl, SPI_MSG_CTL);
		break;
	case 16:
		bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
		break;
	}

	/* Issue the transfer */
	cmd = SPI_CMD_START_IMMEDIATE;
@@ -406,9 +415,21 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
	master->transfer_one_message = bcm63xx_spi_transfer_one;
	master->mode_bits = MODEBITS;
	bs->speed_hz = pdata->speed_hz;
	bs->msg_type_shift = pdata->msg_type_shift;
	bs->msg_ctl_width = pdata->msg_ctl_width;
	bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
	bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));

	switch (bs->msg_ctl_width) {
	case 8:
	case 16:
		break;
	default:
		dev_err(dev, "unsupported MSG_CTL width: %d\n",
			 bs->msg_ctl_width);
		goto out_clk_disable;
	}

	/* Initialize hardware */
	clk_enable(bs->clk);
	bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);