]> rtime.felk.cvut.cz Git - linux-imx.git/commitdiff
MIPS: BCM63xx: Fix SPI message control register handling for BCM6338/6348.
authorFlorian Fainelli <florian@openwrt.org>
Mon, 18 Jun 2012 10:07:51 +0000 (12:07 +0200)
committerRalf Baechle <ralf@linux-mips.org>
Fri, 17 Aug 2012 08:57:28 +0000 (10:57 +0200)
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: Florian 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: Ralf Baechle <ralf@linux-mips.org>
arch/mips/bcm63xx/dev-spi.c
arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
drivers/spi/spi-bcm63xx.c

index e39f73048d4f653c48ba3b52a31976f290699bae..f1c9c3e2f678146e83772f3c7cb05a0989743fce 100644 (file)
@@ -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();
index 7d98dbe5d4b5ef9de38b25717747436e08e6179e..c9bae1362606aac10d79c921f3c8b7374cfc1ba5 100644 (file)
@@ -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;
index 4ccc2a748aff2db6913dab0e8b67e1eb6fbceeb8..61f2a2a5099d02ad281290c675604a4e897e9bf9 100644 (file)
 #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
 #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
 
 /* 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
 
 /* 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
 #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
index 6e25ef1bce91f98549e5b514c051fd065deb6fbc..b7d61e7b873782b5005b4d9e4cfcd2c3d1b8e9cb 100644 (file)
@@ -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);
-
-       bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
+               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);