The Broadcom MSPI controller is used on various chips. The driver only
supported BCM53xx chips with BCMA (an AMBA bus variant). It now supports
both BCMA MSPI and non-BCMA MSPI. To do this the following changes were
made:

  - A new config for non-BCMA chips has been added.
  - Common code between the BCMA and non BCMA version are shared.
  - Function pointers to set read/write functions to abstract bcma
    and non-bcma versions are provided.
  - DT is now mandatory. Hard coded SPI devices are removed and must be
    set in DT.
  - Remove function was unnecessary and removed.

Signed-off-by: Jonathan Richardson <jonat...@broadcom.com>
---
 drivers/spi/Kconfig        |    5 +
 drivers/spi/Makefile       |    1 +
 drivers/spi/spi-bcm-mspi.c |  228 ++++++++++++++++++++++++++++++++------------
 3 files changed, 171 insertions(+), 63 deletions(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 766e08d..23f2357 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -120,6 +120,11 @@ config SPI_BCMA_MSPI
        help
          Enable support for the Broadcom BCMA MSPI controller.
 
+config SPI_BCM_MSPI
+       tristate "Broadcom MSPI controller"
+       help
+         Enable support for the Broadcom MSPI controller.
+
 config SPI_BCM63XX
        tristate "Broadcom BCM63xx SPI controller"
        depends on BCM63XX
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 6b58100..36872d2 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_ATH79)                       += spi-ath79.o
 obj-$(CONFIG_SPI_AU1550)               += spi-au1550.o
 obj-$(CONFIG_SPI_BCM2835)              += spi-bcm2835.o
 obj-$(CONFIG_SPI_BCMA_MSPI)            += spi-bcm-mspi.o
+obj-$(CONFIG_SPI_BCM_MSPI)             += spi-bcm-mspi.o
 obj-$(CONFIG_SPI_BCM63XX)              += spi-bcm63xx.o
 obj-$(CONFIG_SPI_BCM63XX_HSSPI)                += spi-bcm63xx-hsspi.o
 obj-$(CONFIG_SPI_BFIN5XX)              += spi-bfin5xx.o
diff --git a/drivers/spi/spi-bcm-mspi.c b/drivers/spi/spi-bcm-mspi.c
index 502227d..32bb1f0 100644
--- a/drivers/spi/spi-bcm-mspi.c
+++ b/drivers/spi/spi-bcm-mspi.c
@@ -11,11 +11,13 @@
  * GNU General Public License for more details.
  */
 #include <linux/kernel.h>
+#include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/bcma/bcma.h>
 #include <linux/spi/spi.h>
+#include <linux/of.h>
 
 #include "spi-bcm-mspi.h"
 
@@ -25,22 +27,17 @@
 #define BCM_MSPI_SPE_TIMEOUT_MS 80
 
 struct bcm_mspi {
+#ifdef CONFIG_SPI_BCMA_MSPI
        struct bcma_device *core;
-       struct spi_master *master;
+#endif
 
+       void __iomem *base;
+       struct spi_master *master;
        size_t read_offset;
-};
-
-static inline u32 bcm_mspi_read(struct bcm_mspi *mspi, u16 offset)
-{
-       return bcma_read32(mspi->core, offset);
-}
 
-static inline void bcm_mspi_write(struct bcm_mspi *mspi, u16 offset,
-                                   u32 value)
-{
-       bcma_write32(mspi->core, offset, value);
-}
+       void (*mspi_write)(struct bcm_mspi *mspi, u16 offset, u32 value);
+       u32 (*mspi_read)(struct bcm_mspi *mspi, u16 offset);
+};
 
 static inline unsigned int bcm_mspi_calc_timeout(size_t len)
 {
@@ -56,7 +53,7 @@ static int bcm_mspi_wait(struct bcm_mspi *mspi, unsigned int 
timeout_ms)
        /* SPE bit has to be 0 before we read MSPI STATUS */
        deadline = jiffies + BCM_MSPI_SPE_TIMEOUT_MS * HZ / 1000;
        do {
-               tmp = bcm_mspi_read(mspi, MSPI_SPCR2);
+               tmp = mspi->mspi_read(mspi, MSPI_SPCR2);
                if (!(tmp & MSPI_SPCR2_SPE))
                        break;
                udelay(5);
@@ -68,9 +65,9 @@ static int bcm_mspi_wait(struct bcm_mspi *mspi, unsigned int 
timeout_ms)
        /* Check status */
        deadline = jiffies + timeout_ms * HZ / 1000;
        do {
-               tmp = bcm_mspi_read(mspi, MSPI_STATUS);
+               tmp = mspi->mspi_read(mspi, MSPI_STATUS);
                if (tmp & MSPI_STATUS_SPIF) {
-                       bcm_mspi_write(mspi, MSPI_STATUS, 0);
+                       mspi->mspi_write(mspi, MSPI_STATUS, 0);
                        return 0;
                }
 
@@ -79,7 +76,7 @@ static int bcm_mspi_wait(struct bcm_mspi *mspi, unsigned int 
timeout_ms)
        } while (!time_after_eq(jiffies, deadline));
 
 spi_timeout:
-       bcm_mspi_write(mspi, MSPI_STATUS, 0);
+       mspi->mspi_write(mspi, MSPI_STATUS, 0);
 
        pr_err("Timeout waiting for SPI to be ready!\n");
 
@@ -94,7 +91,7 @@ static void bcm_mspi_buf_write(struct bcm_mspi *mspi, u8 
*w_buf,
 
        for (i = 0; i < len; i++) {
                /* Transmit Register File MSB */
-               bcm_mspi_write(mspi, MSPI_TXRAM + 4 * (i * 2),
+               mspi->mspi_write(mspi, MSPI_TXRAM + 4 * (i * 2),
                                 (unsigned int)w_buf[i]);
        }
 
@@ -105,28 +102,28 @@ static void bcm_mspi_buf_write(struct bcm_mspi *mspi, u8 
*w_buf,
                        tmp &= ~MSPI_CDRAM_CONT;
                tmp &= ~0x1;
                /* Command Register File */
-               bcm_mspi_write(mspi, MSPI_CDRAM + 4 * i, tmp);
+               mspi->mspi_write(mspi, MSPI_CDRAM + 4 * i, tmp);
        }
 
        /* Set queue pointers */
-       bcm_mspi_write(mspi, MSPI_NEWQP, 0);
-       bcm_mspi_write(mspi, MSPI_ENDQP, len - 1);
+       mspi->mspi_write(mspi, MSPI_NEWQP, 0);
+       mspi->mspi_write(mspi, MSPI_ENDQP, len - 1);
 
        if (cont)
-               bcm_mspi_write(mspi, MSPI_WRITE_LOCK, 1);
+               mspi->mspi_write(mspi, MSPI_WRITE_LOCK, 1);
 
        /* Start SPI transfer */
-       tmp = bcm_mspi_read(mspi, MSPI_SPCR2);
+       tmp = mspi->mspi_read(mspi, MSPI_SPCR2);
        tmp |= MSPI_SPCR2_SPE;
        if (cont)
                tmp |= MSPI_SPCR2_CONT_AFTER_CMD;
-       bcm_mspi_write(mspi, MSPI_SPCR2, tmp);
+       mspi->mspi_write(mspi, MSPI_SPCR2, tmp);
 
        /* Wait for SPI to finish */
        bcm_mspi_wait(mspi, bcm_mspi_calc_timeout(len));
 
        if (!cont)
-               bcm_mspi_write(mspi, MSPI_WRITE_LOCK, 0);
+               mspi->mspi_write(mspi, MSPI_WRITE_LOCK, 0);
 
        mspi->read_offset = len;
 }
@@ -144,34 +141,35 @@ static void bcm_mspi_buf_read(struct bcm_mspi *mspi, u8 
*r_buf,
                        tmp &= ~MSPI_CDRAM_CONT;
                tmp &= ~0x1;
                /* Command Register File */
-               bcm_mspi_write(mspi, MSPI_CDRAM + 4 * i, tmp);
+               mspi->mspi_write(mspi, MSPI_CDRAM + 4 * i, tmp);
        }
 
        /* Set queue pointers */
-       bcm_mspi_write(mspi, MSPI_NEWQP, 0);
-       bcm_mspi_write(mspi, MSPI_ENDQP, mspi->read_offset + len - 1);
+       mspi->mspi_write(mspi, MSPI_NEWQP, 0);
+       mspi->mspi_write(mspi, MSPI_ENDQP,
+                        mspi->read_offset + len - 1);
 
        if (cont)
-               bcm_mspi_write(mspi, MSPI_WRITE_LOCK, 1);
+               mspi->mspi_write(mspi, MSPI_WRITE_LOCK, 1);
 
        /* Start SPI transfer */
-       tmp = bcm_mspi_read(mspi, MSPI_SPCR2);
+       tmp = mspi->mspi_read(mspi, MSPI_SPCR2);
        tmp |= MSPI_SPCR2_SPE;
        if (cont)
                tmp |= MSPI_SPCR2_CONT_AFTER_CMD;
-       bcm_mspi_write(mspi, MSPI_SPCR2, tmp);
+       mspi->mspi_write(mspi, MSPI_SPCR2, tmp);
 
        /* Wait for SPI to finish */
        bcm_mspi_wait(mspi, bcm_mspi_calc_timeout(len));
 
        if (!cont)
-               bcm_mspi_write(mspi, MSPI_WRITE_LOCK, 0);
+               mspi->mspi_write(mspi, MSPI_WRITE_LOCK, 0);
 
        for (i = 0; i < len; ++i) {
                int offset = mspi->read_offset + i;
 
                /* Data stored in the transmit register file LSB */
-               r_buf[i] = (u8)bcm_mspi_read(mspi,
+               r_buf[i] = (u8)mspi->mspi_read(mspi,
                        MSPI_RXRAM + 4 * (1 + offset * 2));
        }
 
@@ -216,10 +214,104 @@ static int bcm_mspi_transfer_one(struct spi_master 
*master,
        return 0;
 }
 
-static struct spi_board_info bcm_mspi_info = {
-       .modalias       = "bcm53xxspiflash",
+/*
+ * Allocate SPI master for both bcma and non bcma bus. The SPI device must be
+ * configured in DT.
+ */
+static struct bcm_mspi *bcm_mspi_init(struct device *dev)
+{
+       struct bcm_mspi *data;
+       struct spi_master *master;
+
+       master = spi_alloc_master(dev, sizeof(*data));
+       if (!master) {
+               dev_err(dev, "error allocating spi_master\n");
+               return 0;
+       }
+
+       data = spi_master_get_devdata(master);
+       data->master = master;
+
+       /* SPI master will always use the SPI device(s) from DT. */
+       master->dev.of_node = dev->of_node;
+       master->transfer_one = bcm_mspi_transfer_one;
+
+       return data;
+}
+
+#ifdef CONFIG_SPI_BCM_MSPI
+
+static const struct of_device_id bcm_mspi_dt[] = {
+       { .compatible = "brcm,mspi" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, bcm_mspi_dt);
+
+static inline u32 bcm_mspi_read(struct bcm_mspi *mspi, u16 offset)
+{
+       return readl(mspi->base + offset);
+}
+
+static inline void bcm_mspi_write(struct bcm_mspi *mspi, u16 offset,
+       u32 value)
+{
+       writel(value, mspi->base + offset);
+}
+
+/*
+ * Probe routine for non-bcma devices.
+ */
+static int bcm_mspi_probe(struct platform_device *pdev)
+{
+       struct bcm_mspi *data;
+       struct device *dev = &pdev->dev;
+       int err;
+       struct resource *res;
+
+       dev_info(dev, "BCM MSPI probe\n");
+
+       data = bcm_mspi_init(dev);
+       if (!data)
+               return -ENOMEM;
+
+       /* Map base memory address. */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       data->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(data->base)) {
+               dev_err(&pdev->dev, "unable to map I/O memory\n");
+               err = PTR_ERR(data->base);
+               goto out;
+       }
+
+       data->mspi_read = bcm_mspi_read;
+       data->mspi_write = bcm_mspi_write;
+       platform_set_drvdata(pdev, data);
+
+       err = devm_spi_register_master(dev, data->master);
+       if (err)
+               goto out;
+
+       return 0;
+
+out:
+       spi_master_put(data->master);
+       return err;
+}
+
+static struct platform_driver bcm_mspi_driver = {
+       .driver = {
+               .name = "bcm-mspi",
+               .of_match_table = bcm_mspi_dt,
+       },
+       .probe = bcm_mspi_probe,
 };
 
+module_platform_driver(bcm_mspi_driver);
+
+#endif
+
+#ifdef CONFIG_SPI_BCMA_MSPI
+
 static const struct bcma_device_id bcm_mspi_bcma_tbl[] = {
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV,
                BCMA_ANY_CLASS),
@@ -227,62 +319,70 @@ static const struct bcma_device_id bcm_mspi_bcma_tbl[] = {
 };
 MODULE_DEVICE_TABLE(bcma, bcm_mspi_bcma_tbl);
 
+static const struct of_device_id bcm_bcma_mspi_dt[] = {
+       { .compatible = "brcm,bcma-mspi" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, bcm_mspi_dt);
+
+static inline u32 bcm_bcma_mspi_read(struct bcm_mspi *mspi, u16 offset)
+{
+       return bcma_read32(mspi->core, offset);
+}
+
+static inline void bcm_bcma_mspi_write(struct bcm_mspi *mspi, u16 offset,
+       u32 value)
+{
+       bcma_write32(mspi->core, offset, value);
+}
+
+/*
+ * Probe routine for bcma devices.
+ */
 static int bcm_mspi_bcma_probe(struct bcma_device *core)
 {
        struct bcm_mspi *data;
-       struct spi_master *master;
        int err;
 
        dev_info(&core->dev, "BCM MSPI BCMA probe\n");
 
        if (core->bus->drv_cc.core->id.rev != 42) {
-               pr_err("SPI on SoC with unsupported ChipCommon rev\n");
+               dev_err(&core->dev,
+                       "SPI on SoC with unsupported ChipCommon rev\n");
                return -ENOTSUPP;
        }
 
-       master = spi_alloc_master(&core->dev, sizeof(*data));
-       if (!master)
+       data = bcm_mspi_init(&core->dev);
+       if (!data)
                return -ENOMEM;
 
-       data = spi_master_get_devdata(master);
-       data->master = master;
+       data->mspi_read = bcm_bcma_mspi_read;
+       data->mspi_write = bcm_bcma_mspi_write;
        data->core = core;
 
-       master->transfer_one = bcm_mspi_transfer_one;
-
        bcma_set_drvdata(core, data);
 
        err = devm_spi_register_master(&core->dev, data->master);
        if (err) {
-               spi_master_put(master);
-               bcma_set_drvdata(core, NULL);
-               goto out;
+               spi_master_put(data->master);
+               return err;
        }
 
-       /* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */
-       spi_new_device(master, &bcm_mspi_info);
-
-out:
-       return err;
-}
-
-static void bcm_mspi_bcma_remove(struct bcma_device *core)
-{
-       struct bcm_mspi *mspi = bcma_get_drvdata(core);
-
-       spi_unregister_master(mspi->master);
+       return 0;
 }
 
 static struct bcma_driver bcm_mspi_bcma_driver = {
        .name           = KBUILD_MODNAME,
+       .drv = {
+               .of_match_table = bcm_bcma_mspi_dt,
+       },
        .id_table       = bcm_mspi_bcma_tbl,
        .probe          = bcm_mspi_bcma_probe,
-       .remove         = bcm_mspi_bcma_remove,
 };
 
-static int __init bcm_mspi_module_init(void)
+static int __init bcm_mspi_bcma_module_init(void)
 {
-       int err = 0;
+       int err;
 
        err = bcma_driver_register(&bcm_mspi_bcma_driver);
        if (err)
@@ -291,13 +391,15 @@ static int __init bcm_mspi_module_init(void)
        return err;
 }
 
-static void __exit bcm_mspi_module_exit(void)
+static void __exit bcm_mspi_bcma_module_exit(void)
 {
        bcma_driver_unregister(&bcm_mspi_bcma_driver);
 }
 
-module_init(bcm_mspi_module_init);
-module_exit(bcm_mspi_module_exit);
+module_init(bcm_mspi_bcma_module_init);
+module_exit(bcm_mspi_bcma_module_exit);
+
+#endif
 
 MODULE_DESCRIPTION("Broadcom MSPI SPI Controller driver");
 MODULE_AUTHOR("Rafał Miłecki <zaj...@gmail.com>");
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to