These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / spi / spi-bcm63xx.c
index e73e2b0..bf9a610 100644 (file)
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
 
-#include <bcm63xx_dev_spi.h>
+/* BCM 6338/6348 SPI core */
+#define SPI_6348_RSET_SIZE             64
+#define SPI_6348_CMD                   0x00    /* 16-bits register */
+#define SPI_6348_INT_STATUS            0x02
+#define SPI_6348_INT_MASK_ST           0x03
+#define SPI_6348_INT_MASK              0x04
+#define SPI_6348_ST                    0x05
+#define SPI_6348_CLK_CFG               0x06
+#define SPI_6348_FILL_BYTE             0x07
+#define SPI_6348_MSG_TAIL              0x09
+#define SPI_6348_RX_TAIL               0x0b
+#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
+#define SPI_6348_RX_DATA_SIZE          0x3f
+
+/* BCM 3368/6358/6262/6368 SPI core */
+#define SPI_6358_RSET_SIZE             1804
+#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
+#define SPI_6358_RX_DATA_SIZE          0x220
+#define SPI_6358_CMD                   0x700   /* 16-bits register */
+#define SPI_6358_INT_STATUS            0x702
+#define SPI_6358_INT_MASK_ST           0x703
+#define SPI_6358_INT_MASK              0x704
+#define SPI_6358_ST                    0x705
+#define SPI_6358_CLK_CFG               0x706
+#define SPI_6358_FILL_BYTE             0x707
+#define SPI_6358_MSG_TAIL              0x709
+#define SPI_6358_RX_TAIL               0x70B
+
+/* Shared SPI definitions */
+
+/* Message configuration */
+#define SPI_FD_RW                      0x00
+#define SPI_HD_W                       0x01
+#define SPI_HD_R                       0x02
+#define SPI_BYTE_CNT_SHIFT             0
+#define SPI_6348_MSG_TYPE_SHIFT                6
+#define SPI_6358_MSG_TYPE_SHIFT                14
+
+/* Command */
+#define SPI_CMD_NOOP                   0x00
+#define SPI_CMD_SOFT_RESET             0x01
+#define SPI_CMD_HARD_RESET             0x02
+#define SPI_CMD_START_IMMEDIATE                0x03
+#define SPI_CMD_COMMAND_SHIFT          0
+#define SPI_CMD_COMMAND_MASK           0x000f
+#define SPI_CMD_DEVICE_ID_SHIFT                4
+#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT 8
+#define SPI_CMD_ONE_BYTE_SHIFT         11
+#define SPI_CMD_ONE_WIRE_SHIFT         12
+#define SPI_DEV_ID_0                   0
+#define SPI_DEV_ID_1                   1
+#define SPI_DEV_ID_2                   2
+#define SPI_DEV_ID_3                   3
+
+/* Interrupt mask */
+#define SPI_INTR_CMD_DONE              0x01
+#define SPI_INTR_RX_OVERFLOW           0x02
+#define SPI_INTR_TX_UNDERFLOW          0x04
+#define SPI_INTR_TX_OVERFLOW           0x08
+#define SPI_INTR_RX_UNDERFLOW          0x10
+#define SPI_INTR_CLEAR_ALL             0x1f
+
+/* Status */
+#define SPI_RX_EMPTY                   0x02
+#define SPI_CMD_BUSY                   0x04
+#define SPI_SERIAL_BUSY                        0x08
+
+/* Clock configuration */
+#define SPI_CLK_20MHZ                  0x00
+#define SPI_CLK_0_391MHZ               0x01
+#define SPI_CLK_0_781MHZ               0x02    /* default */
+#define SPI_CLK_1_563MHZ               0x03
+#define SPI_CLK_3_125MHZ               0x04
+#define SPI_CLK_6_250MHZ               0x05
+#define SPI_CLK_12_50MHZ               0x06
+#define SPI_CLK_MASK                   0x07
+#define SPI_SSOFFTIME_MASK             0x38
+#define SPI_SSOFFTIME_SHIFT            3
+#define SPI_BYTE_SWAP                  0x80
+
+enum bcm63xx_regs_spi {
+       SPI_CMD,
+       SPI_INT_STATUS,
+       SPI_INT_MASK_ST,
+       SPI_INT_MASK,
+       SPI_ST,
+       SPI_CLK_CFG,
+       SPI_FILL_BYTE,
+       SPI_MSG_TAIL,
+       SPI_RX_TAIL,
+       SPI_MSG_CTL,
+       SPI_MSG_DATA,
+       SPI_RX_DATA,
+       SPI_MSG_TYPE_SHIFT,
+       SPI_MSG_CTL_WIDTH,
+       SPI_MSG_DATA_SIZE,
+};
 
 #define BCM63XX_SPI_MAX_PREPEND                15
 
+#define BCM63XX_SPI_MAX_CS             8
+#define BCM63XX_SPI_BUS_NUM            0
+
 struct bcm63xx_spi {
        struct completion       done;
 
@@ -38,6 +145,7 @@ struct bcm63xx_spi {
        int                     irq;
 
        /* Platform data */
+       const unsigned long     *reg_offsets;
        unsigned                fifo_size;
        unsigned int            msg_type_shift;
        unsigned int            msg_ctl_width;
@@ -51,27 +159,35 @@ struct bcm63xx_spi {
 };
 
 static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs,
-                               unsigned int offset)
+                              unsigned int offset)
 {
-       return bcm_readb(bs->regs + bcm63xx_spireg(offset));
+       return readb(bs->regs + bs->reg_offsets[offset]);
 }
 
 static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs,
                                unsigned int offset)
 {
-       return bcm_readw(bs->regs + bcm63xx_spireg(offset));
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       return ioread16be(bs->regs + bs->reg_offsets[offset]);
+#else
+       return readw(bs->regs + bs->reg_offsets[offset]);
+#endif
 }
 
 static inline void bcm_spi_writeb(struct bcm63xx_spi *bs,
                                  u8 value, unsigned int offset)
 {
-       bcm_writeb(value, bs->regs + bcm63xx_spireg(offset));
+       writeb(value, bs->regs + bs->reg_offsets[offset]);
 }
 
 static inline void bcm_spi_writew(struct bcm63xx_spi *bs,
                                  u16 value, unsigned int offset)
 {
-       bcm_writew(value, bs->regs + bcm63xx_spireg(offset));
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       iowrite16be(value, bs->regs + bs->reg_offsets[offset]);
+#else
+       writew(value, bs->regs + bs->reg_offsets[offset]);
+#endif
 }
 
 static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
@@ -122,7 +238,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
        struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
        u16 msg_ctl;
        u16 cmd;
-       u8 rx_tail;
        unsigned int i, timeout = 0, prepend_len = 0, len = 0;
        struct spi_transfer *t = first;
        bool do_rx = false;
@@ -314,18 +429,71 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static const unsigned long bcm6348_spi_reg_offsets[] = {
+       [SPI_CMD]               = SPI_6348_CMD,
+       [SPI_INT_STATUS]        = SPI_6348_INT_STATUS,
+       [SPI_INT_MASK_ST]       = SPI_6348_INT_MASK_ST,
+       [SPI_INT_MASK]          = SPI_6348_INT_MASK,
+       [SPI_ST]                = SPI_6348_ST,
+       [SPI_CLK_CFG]           = SPI_6348_CLK_CFG,
+       [SPI_FILL_BYTE]         = SPI_6348_FILL_BYTE,
+       [SPI_MSG_TAIL]          = SPI_6348_MSG_TAIL,
+       [SPI_RX_TAIL]           = SPI_6348_RX_TAIL,
+       [SPI_MSG_CTL]           = SPI_6348_MSG_CTL,
+       [SPI_MSG_DATA]          = SPI_6348_MSG_DATA,
+       [SPI_RX_DATA]           = SPI_6348_RX_DATA,
+       [SPI_MSG_TYPE_SHIFT]    = SPI_6348_MSG_TYPE_SHIFT,
+       [SPI_MSG_CTL_WIDTH]     = SPI_6348_MSG_CTL_WIDTH,
+       [SPI_MSG_DATA_SIZE]     = SPI_6348_MSG_DATA_SIZE,
+};
+
+static const unsigned long bcm6358_spi_reg_offsets[] = {
+       [SPI_CMD]               = SPI_6358_CMD,
+       [SPI_INT_STATUS]        = SPI_6358_INT_STATUS,
+       [SPI_INT_MASK_ST]       = SPI_6358_INT_MASK_ST,
+       [SPI_INT_MASK]          = SPI_6358_INT_MASK,
+       [SPI_ST]                = SPI_6358_ST,
+       [SPI_CLK_CFG]           = SPI_6358_CLK_CFG,
+       [SPI_FILL_BYTE]         = SPI_6358_FILL_BYTE,
+       [SPI_MSG_TAIL]          = SPI_6358_MSG_TAIL,
+       [SPI_RX_TAIL]           = SPI_6358_RX_TAIL,
+       [SPI_MSG_CTL]           = SPI_6358_MSG_CTL,
+       [SPI_MSG_DATA]          = SPI_6358_MSG_DATA,
+       [SPI_RX_DATA]           = SPI_6358_RX_DATA,
+       [SPI_MSG_TYPE_SHIFT]    = SPI_6358_MSG_TYPE_SHIFT,
+       [SPI_MSG_CTL_WIDTH]     = SPI_6358_MSG_CTL_WIDTH,
+       [SPI_MSG_DATA_SIZE]     = SPI_6358_MSG_DATA_SIZE,
+};
+
+static const struct platform_device_id bcm63xx_spi_dev_match[] = {
+       {
+               .name = "bcm6348-spi",
+               .driver_data = (unsigned long)bcm6348_spi_reg_offsets,
+       },
+       {
+               .name = "bcm6358-spi",
+               .driver_data = (unsigned long)bcm6358_spi_reg_offsets,
+       },
+       {
+       },
+};
 
 static int bcm63xx_spi_probe(struct platform_device *pdev)
 {
        struct resource *r;
+       const unsigned long *bcm63xx_spireg;
        struct device *dev = &pdev->dev;
-       struct bcm63xx_spi_pdata *pdata = dev_get_platdata(&pdev->dev);
        int irq;
        struct spi_master *master;
        struct clk *clk;
        struct bcm63xx_spi *bs;
        int ret;
 
+       if (!pdev->id_entry->driver_data)
+               return -EINVAL;
+
+       bcm63xx_spireg = (const unsigned long *)pdev->id_entry->driver_data;
+
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(dev, "no irq\n");
@@ -359,7 +527,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
 
        bs->irq = irq;
        bs->clk = clk;
-       bs->fifo_size = pdata->fifo_size;
+       bs->reg_offsets = bcm63xx_spireg;
+       bs->fifo_size = bs->reg_offsets[SPI_MSG_DATA_SIZE];
 
        ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0,
                                                        pdev->name, master);
@@ -368,26 +537,16 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
                goto out_err;
        }
 
-       master->bus_num = pdata->bus_num;
-       master->num_chipselect = pdata->num_chipselect;
+       master->bus_num = BCM63XX_SPI_BUS_NUM;
+       master->num_chipselect = BCM63XX_SPI_MAX_CS;
        master->transfer_one_message = bcm63xx_spi_transfer_one;
        master->mode_bits = MODEBITS;
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->auto_runtime_pm = true;
-       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_err;
-       }
+       bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT];
+       bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH];
+       bs->tx_io = (u8 *)(bs->regs + bs->reg_offsets[SPI_MSG_DATA]);
+       bs->rx_io = (const u8 *)(bs->regs + bs->reg_offsets[SPI_RX_DATA]);
 
        /* Initialize hardware */
        ret = clk_prepare_enable(bs->clk);
@@ -403,8 +562,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
                goto out_clk_disable;
        }
 
-       dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d)\n",
-                r->start, irq, bs->fifo_size);
+       dev_info(dev, "at %pr (irq %d, FIFOs size %d)\n",
+                r, irq, bs->fifo_size);
 
        return 0;
 
@@ -467,6 +626,7 @@ static struct platform_driver bcm63xx_spi_driver = {
                .name   = "bcm63xx-spi",
                .pm     = &bcm63xx_spi_pm_ops,
        },
+       .id_table       = bcm63xx_spi_dev_match,
        .probe          = bcm63xx_spi_probe,
        .remove         = bcm63xx_spi_remove,
 };