From: Jonathan Richardson <jonathar-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
To: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
Dmitry Torokhov <dtor-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>,
Anatol Pomazau <anatol-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Cc: Jonathan Richardson
<jonathar-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>,
Scott Branden <sbranden-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>,
Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>,
Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>,
Ian Campbell
<ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org>,
Kumar Gala <galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
bcm-kernel-feedback-list
<bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Rafal Milecki <zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Subject: [PATCH v2 4/5] spi: bcm-mspi: Make BCMA optional to support non-BCMA chips
Date: Wed, 8 Apr 2015 11:04:34 -0700 [thread overview]
Message-ID: <1428516275-12819-5-git-send-email-jonathar@broadcom.com> (raw)
In-Reply-To: <1428516275-12819-1-git-send-email-jonathar-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
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 <jonathar-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
---
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 <zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2015-04-08 18:04 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-08 18:04 [PATCH v2 0/5] Add MSPI support for Cygnus Jonathan Richardson
2015-04-08 18:04 ` [PATCH v2 2/5] spi: bcm53xx: Refactor driver to make nonspecific to 53xx SoCs Jonathan Richardson
[not found] ` <1428516275-12819-3-git-send-email-jonathar-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
2015-04-08 19:49 ` Mark Brown
[not found] ` <1428516275-12819-1-git-send-email-jonathar-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
2015-04-08 18:04 ` [PATCH v2 1/5] ARM: dts: Add binding for Broadcom MSPI driver Jonathan Richardson
2015-04-08 18:04 ` [PATCH v2 3/5] spi: bcm-mspi: Refactor to make driver nonspecific to 53xx SoCs Jonathan Richardson
2015-04-08 18:04 ` Jonathan Richardson [this message]
[not found] ` <1428516275-12819-5-git-send-email-jonathar-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
2015-04-08 19:27 ` [PATCH v2 4/5] spi: bcm-mspi: Make BCMA optional to support non-BCMA chips Jonas Gorski
[not found] ` <CAOiHx==NCAOqFf2gzEX+fmFq=TRjq9hHDbpBt4Dpdg1HC6qjuQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-04-08 22:26 ` Jonathan Richardson
2015-04-08 20:03 ` Mark Brown
[not found] ` <20150408200306.GM6023-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
2015-04-09 22:26 ` Jonathan Richardson
2015-04-08 18:04 ` [PATCH v2 5/5] spi: bcm-mspi: Add support to set serial baud clock rate Jonathan Richardson
[not found] ` <1428516275-12819-6-git-send-email-jonathar-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>
2015-04-08 19:32 ` Jonas Gorski
2015-04-08 19:53 ` Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1428516275-12819-5-git-send-email-jonathar@broadcom.com \
--to=jonathar-dy08kvg/lbpwk0htik3j/w@public.gmane.org \
--cc=anatol-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
--cc=bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w@public.gmane.org \
--cc=broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=dtor-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
--cc=galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org \
--cc=ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=mark.rutland-5wv7dgnIgG8@public.gmane.org \
--cc=pawel.moll-5wv7dgnIgG8@public.gmane.org \
--cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=sbranden-dY08KVG/lbpWk0Htik3J/w@public.gmane.org \
--cc=zajec5-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).