diff options
Diffstat (limited to 'target/linux/bcm53xx/patches-4.4/083-0008-spi-iproc-qspi-Add-Broadcom-iProc-SoCs-support.patch')
-rw-r--r-- | target/linux/bcm53xx/patches-4.4/083-0008-spi-iproc-qspi-Add-Broadcom-iProc-SoCs-support.patch | 452 |
1 files changed, 0 insertions, 452 deletions
diff --git a/target/linux/bcm53xx/patches-4.4/083-0008-spi-iproc-qspi-Add-Broadcom-iProc-SoCs-support.patch b/target/linux/bcm53xx/patches-4.4/083-0008-spi-iproc-qspi-Add-Broadcom-iProc-SoCs-support.patch deleted file mode 100644 index 836d629c15..0000000000 --- a/target/linux/bcm53xx/patches-4.4/083-0008-spi-iproc-qspi-Add-Broadcom-iProc-SoCs-support.patch +++ /dev/null @@ -1,452 +0,0 @@ -From cc20a38612dbc87dc7396affc9758e3bfbe92340 Mon Sep 17 00:00:00 2001 -From: Kamal Dasu <kdasu.kdev@gmail.com> -Date: Wed, 24 Aug 2016 18:04:29 -0400 -Subject: [PATCH] spi: iproc-qspi: Add Broadcom iProc SoCs support - -This spi driver uses the common spi-bcm-qspi driver and implements iProc -SoCs specific interrupt controller. The common driver now calls the SoC -handlers when present. Adding support for both muxed l1 and unmuxed interrupt -sources. - -Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com> -Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> -Signed-off-by: Mark Brown <broonie@kernel.org> ---- - drivers/spi/Makefile | 2 +- - drivers/spi/spi-bcm-qspi.c | 97 ++++++++++++++++++++++++- - drivers/spi/spi-bcm-qspi.h | 34 ++++++++- - drivers/spi/spi-iproc-qspi.c | 163 +++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 291 insertions(+), 5 deletions(-) - create mode 100644 drivers/spi/spi-iproc-qspi.c - ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -19,7 +19,7 @@ obj-$(CONFIG_SPI_BCM2835AUX) += spi-bcm - obj-$(CONFIG_SPI_BCM53XX) += spi-bcm53xx.o - obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o - obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o --obj-$(CONFIG_SPI_BCM_QSPI) += spi-brcmstb-qspi.o spi-bcm-qspi.o -+obj-$(CONFIG_SPI_BCM_QSPI) += spi-iproc-qspi.o spi-brcmstb-qspi.o spi-bcm-qspi.o - obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o - obj-$(CONFIG_SPI_ADI_V3) += spi-adi-v3.o - obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o ---- a/drivers/spi/spi-bcm-qspi.c -+++ b/drivers/spi/spi-bcm-qspi.c -@@ -175,9 +175,15 @@ enum base_type { - BASEMAX, - }; - -+enum irq_source { -+ SINGLE_L2, -+ MUXED_L1, -+}; -+ - struct bcm_qspi_irq { - const char *irq_name; - const irq_handler_t irq_handler; -+ int irq_source; - u32 mask; - }; - -@@ -198,6 +204,10 @@ struct bcm_qspi { - u32 base_clk; - u32 max_speed_hz; - void __iomem *base[BASEMAX]; -+ -+ /* Some SoCs provide custom interrupt status register(s) */ -+ struct bcm_qspi_soc_intc *soc_intc; -+ - struct bcm_qspi_parms last_parms; - struct qspi_trans trans_pos; - int curr_cs; -@@ -806,6 +816,7 @@ static int bcm_qspi_bspi_flash_read(stru - u32 addr = 0, len, len_words; - int ret = 0; - unsigned long timeo = msecs_to_jiffies(100); -+ struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc; - - if (bcm_qspi_bspi_ver_three(qspi)) - if (msg->addr_width == BSPI_ADDRLEN_4BYTES) -@@ -850,6 +861,15 @@ static int bcm_qspi_bspi_flash_read(stru - bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words); - bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0); - -+ if (qspi->soc_intc) { -+ /* -+ * clear soc MSPI and BSPI interrupts and enable -+ * BSPI interrupts. -+ */ -+ soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_BSPI_DONE); -+ soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, true); -+ } -+ - /* Must flush previous writes before starting BSPI operation */ - mb(); - -@@ -952,9 +972,12 @@ static irqreturn_t bcm_qspi_mspi_l2_isr( - u32 status = bcm_qspi_read(qspi, MSPI, MSPI_MSPI_STATUS); - - if (status & MSPI_MSPI_STATUS_SPIF) { -+ struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc; - /* clear interrupt */ - status &= ~MSPI_MSPI_STATUS_SPIF; - bcm_qspi_write(qspi, MSPI, MSPI_MSPI_STATUS, status); -+ if (qspi->soc_intc) -+ soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_DONE); - complete(&qspi->mspi_done); - return IRQ_HANDLED; - } -@@ -966,20 +989,33 @@ static irqreturn_t bcm_qspi_bspi_lr_l2_i - { - struct bcm_qspi_dev_id *qspi_dev_id = dev_id; - struct bcm_qspi *qspi = qspi_dev_id->dev; -- u32 status; -+ struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc; -+ u32 status = qspi_dev_id->irqp->mask; - - if (qspi->bspi_enabled && qspi->bspi_rf_msg) { - bcm_qspi_bspi_lr_data_read(qspi); - if (qspi->bspi_rf_msg_len == 0) { - qspi->bspi_rf_msg = NULL; -+ if (qspi->soc_intc) { -+ /* disable soc BSPI interrupt */ -+ soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, -+ false); -+ /* indicate done */ -+ status = INTR_BSPI_LR_SESSION_DONE_MASK; -+ } -+ - if (qspi->bspi_rf_msg_status) - bcm_qspi_bspi_lr_clear(qspi); - else - bcm_qspi_bspi_flush_prefetch_buffers(qspi); - } -+ -+ if (qspi->soc_intc) -+ /* clear soc BSPI interrupt */ -+ soc_intc->bcm_qspi_int_ack(soc_intc, BSPI_DONE); - } - -- status = (qspi_dev_id->irqp->mask & INTR_BSPI_LR_SESSION_DONE_MASK); -+ status &= INTR_BSPI_LR_SESSION_DONE_MASK; - if (qspi->bspi_enabled && status && qspi->bspi_rf_msg_len == 0) - complete(&qspi->bspi_done); - -@@ -990,13 +1026,39 @@ static irqreturn_t bcm_qspi_bspi_lr_err_ - { - struct bcm_qspi_dev_id *qspi_dev_id = dev_id; - struct bcm_qspi *qspi = qspi_dev_id->dev; -+ struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc; - - dev_err(&qspi->pdev->dev, "BSPI INT error\n"); - qspi->bspi_rf_msg_status = -EIO; -+ if (qspi->soc_intc) -+ /* clear soc interrupt */ -+ soc_intc->bcm_qspi_int_ack(soc_intc, BSPI_ERR); -+ - complete(&qspi->bspi_done); - return IRQ_HANDLED; - } - -+static irqreturn_t bcm_qspi_l1_isr(int irq, void *dev_id) -+{ -+ struct bcm_qspi_dev_id *qspi_dev_id = dev_id; -+ struct bcm_qspi *qspi = qspi_dev_id->dev; -+ struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc; -+ irqreturn_t ret = IRQ_NONE; -+ -+ if (soc_intc) { -+ u32 status = soc_intc->bcm_qspi_get_int_status(soc_intc); -+ -+ if (status & MSPI_DONE) -+ ret = bcm_qspi_mspi_l2_isr(irq, dev_id); -+ else if (status & BSPI_DONE) -+ ret = bcm_qspi_bspi_lr_l2_isr(irq, dev_id); -+ else if (status & BSPI_ERR) -+ ret = bcm_qspi_bspi_lr_err_l2_isr(irq, dev_id); -+ } -+ -+ return ret; -+} -+ - static const struct bcm_qspi_irq qspi_irq_tab[] = { - { - .irq_name = "spi_lr_fullness_reached", -@@ -1036,6 +1098,13 @@ static const struct bcm_qspi_irq qspi_ir - .irq_handler = bcm_qspi_mspi_l2_isr, - .mask = INTR_MSPI_HALTED_MASK, - }, -+ { -+ /* single muxed L1 interrupt source */ -+ .irq_name = "spi_l1_intr", -+ .irq_handler = bcm_qspi_l1_isr, -+ .irq_source = MUXED_L1, -+ .mask = QSPI_INTERRUPTS_ALL, -+ }, - }; - - static void bcm_qspi_bspi_init(struct bcm_qspi *qspi) -@@ -1182,7 +1251,13 @@ int bcm_qspi_probe(struct platform_devic - for (val = 0; val < num_irqs; val++) { - irq = -1; - name = qspi_irq_tab[val].irq_name; -- irq = platform_get_irq_byname(pdev, name); -+ if (qspi_irq_tab[val].irq_source == SINGLE_L2) { -+ /* get the l2 interrupts */ -+ irq = platform_get_irq_byname(pdev, name); -+ } else if (!num_ints && soc_intc) { -+ /* all mspi, bspi intrs muxed to one L1 intr */ -+ irq = platform_get_irq(pdev, 0); -+ } - - if (irq >= 0) { - ret = devm_request_irq(&pdev->dev, irq, -@@ -1209,6 +1284,17 @@ int bcm_qspi_probe(struct platform_devic - goto qspi_probe_err; - } - -+ /* -+ * Some SoCs integrate spi controller (e.g., its interrupt bits) -+ * in specific ways -+ */ -+ if (soc_intc) { -+ qspi->soc_intc = soc_intc; -+ soc_intc->bcm_qspi_int_set(soc_intc, MSPI_DONE, true); -+ } else { -+ qspi->soc_intc = NULL; -+ } -+ - qspi->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(qspi->clk)) { - dev_warn(dev, "unable to get clock\n"); -@@ -1288,6 +1374,11 @@ static int __maybe_unused bcm_qspi_resum - - bcm_qspi_hw_init(qspi); - bcm_qspi_chip_select(qspi, qspi->curr_cs); -+ if (qspi->soc_intc) -+ /* enable MSPI interrupt */ -+ qspi->soc_intc->bcm_qspi_int_set(qspi->soc_intc, MSPI_DONE, -+ true); -+ - ret = clk_enable(qspi->clk); - if (!ret) - spi_master_resume(qspi->master); ---- a/drivers/spi/spi-bcm-qspi.h -+++ b/drivers/spi/spi-bcm-qspi.h -@@ -48,10 +48,26 @@ - (INTR_MSPI_DONE_MASK | \ - INTR_MSPI_HALTED_MASK) - -+#define QSPI_INTERRUPTS_ALL \ -+ (MSPI_INTERRUPTS_ALL | \ -+ BSPI_LR_INTERRUPTS_ALL) -+ - struct platform_device; - struct dev_pm_ops; - --struct bcm_qspi_soc_intc; -+enum { -+ MSPI_DONE = 0x1, -+ BSPI_DONE = 0x2, -+ BSPI_ERR = 0x4, -+ MSPI_BSPI_DONE = 0x7 -+}; -+ -+struct bcm_qspi_soc_intc { -+ void (*bcm_qspi_int_ack)(struct bcm_qspi_soc_intc *soc_intc, int type); -+ void (*bcm_qspi_int_set)(struct bcm_qspi_soc_intc *soc_intc, int type, -+ bool en); -+ u32 (*bcm_qspi_get_int_status)(struct bcm_qspi_soc_intc *soc_intc); -+}; - - /* Read controller register*/ - static inline u32 bcm_qspi_readl(bool be, void __iomem *addr) -@@ -72,6 +88,22 @@ static inline void bcm_qspi_writel(bool - writel_relaxed(data, addr); - } - -+static inline u32 get_qspi_mask(int type) -+{ -+ switch (type) { -+ case MSPI_DONE: -+ return INTR_MSPI_DONE_MASK; -+ case BSPI_DONE: -+ return BSPI_LR_INTERRUPTS_ALL; -+ case MSPI_BSPI_DONE: -+ return QSPI_INTERRUPTS_ALL; -+ case BSPI_ERR: -+ return BSPI_LR_INTERRUPTS_ERROR; -+ } -+ -+ return 0; -+} -+ - /* The common driver functions to be called by the SoC platform driver */ - int bcm_qspi_probe(struct platform_device *pdev, - struct bcm_qspi_soc_intc *soc_intc); ---- /dev/null -+++ b/drivers/spi/spi-iproc-qspi.c -@@ -0,0 +1,163 @@ -+/* -+ * Copyright 2016 Broadcom Limited -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include <linux/device.h> -+#include <linux/io.h> -+#include <linux/ioport.h> -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/of_address.h> -+#include <linux/platform_device.h> -+#include <linux/slab.h> -+ -+#include "spi-bcm-qspi.h" -+ -+#define INTR_BASE_BIT_SHIFT 0x02 -+#define INTR_COUNT 0x07 -+ -+struct bcm_iproc_intc { -+ struct bcm_qspi_soc_intc soc_intc; -+ struct platform_device *pdev; -+ void __iomem *int_reg; -+ void __iomem *int_status_reg; -+ spinlock_t soclock; -+ bool big_endian; -+}; -+ -+static u32 bcm_iproc_qspi_get_l2_int_status(struct bcm_qspi_soc_intc *soc_intc) -+{ -+ struct bcm_iproc_intc *priv = -+ container_of(soc_intc, struct bcm_iproc_intc, soc_intc); -+ void __iomem *mmio = priv->int_status_reg; -+ int i; -+ u32 val = 0, sts = 0; -+ -+ for (i = 0; i < INTR_COUNT; i++) { -+ if (bcm_qspi_readl(priv->big_endian, mmio + (i * 4))) -+ val |= 1UL << i; -+ } -+ -+ if (val & INTR_MSPI_DONE_MASK) -+ sts |= MSPI_DONE; -+ -+ if (val & BSPI_LR_INTERRUPTS_ALL) -+ sts |= BSPI_DONE; -+ -+ if (val & BSPI_LR_INTERRUPTS_ERROR) -+ sts |= BSPI_ERR; -+ -+ return sts; -+} -+ -+static void bcm_iproc_qspi_int_ack(struct bcm_qspi_soc_intc *soc_intc, int type) -+{ -+ struct bcm_iproc_intc *priv = -+ container_of(soc_intc, struct bcm_iproc_intc, soc_intc); -+ void __iomem *mmio = priv->int_status_reg; -+ u32 mask = get_qspi_mask(type); -+ int i; -+ -+ for (i = 0; i < INTR_COUNT; i++) { -+ if (mask & (1UL << i)) -+ bcm_qspi_writel(priv->big_endian, 1, mmio + (i * 4)); -+ } -+} -+ -+static void bcm_iproc_qspi_int_set(struct bcm_qspi_soc_intc *soc_intc, int type, -+ bool en) -+{ -+ struct bcm_iproc_intc *priv = -+ container_of(soc_intc, struct bcm_iproc_intc, soc_intc); -+ void __iomem *mmio = priv->int_reg; -+ u32 mask = get_qspi_mask(type); -+ u32 val; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->soclock, flags); -+ -+ val = bcm_qspi_readl(priv->big_endian, mmio); -+ -+ if (en) -+ val = val | (mask << INTR_BASE_BIT_SHIFT); -+ else -+ val = val & ~(mask << INTR_BASE_BIT_SHIFT); -+ -+ bcm_qspi_writel(priv->big_endian, val, mmio); -+ -+ spin_unlock_irqrestore(&priv->soclock, flags); -+} -+ -+static int bcm_iproc_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct bcm_iproc_intc *priv; -+ struct bcm_qspi_soc_intc *soc_intc; -+ struct resource *res; -+ -+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ soc_intc = &priv->soc_intc; -+ priv->pdev = pdev; -+ -+ spin_lock_init(&priv->soclock); -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr_regs"); -+ priv->int_reg = devm_ioremap_resource(dev, res); -+ if (IS_ERR(priv->int_reg)) -+ return PTR_ERR(priv->int_reg); -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -+ "intr_status_reg"); -+ priv->int_status_reg = devm_ioremap_resource(dev, res); -+ if (IS_ERR(priv->int_status_reg)) -+ return PTR_ERR(priv->int_status_reg); -+ -+ priv->big_endian = of_device_is_big_endian(dev->of_node); -+ -+ bcm_iproc_qspi_int_ack(soc_intc, MSPI_BSPI_DONE); -+ bcm_iproc_qspi_int_set(soc_intc, MSPI_BSPI_DONE, false); -+ -+ soc_intc->bcm_qspi_int_ack = bcm_iproc_qspi_int_ack; -+ soc_intc->bcm_qspi_int_set = bcm_iproc_qspi_int_set; -+ soc_intc->bcm_qspi_get_int_status = bcm_iproc_qspi_get_l2_int_status; -+ -+ return bcm_qspi_probe(pdev, soc_intc); -+} -+ -+static int bcm_iproc_remove(struct platform_device *pdev) -+{ -+ return bcm_qspi_remove(pdev); -+} -+ -+static const struct of_device_id bcm_iproc_of_match[] = { -+ { .compatible = "brcm,spi-nsp-qspi" }, -+ { .compatible = "brcm,spi-ns2-qspi" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, bcm_iproc_of_match); -+ -+static struct platform_driver bcm_iproc_driver = { -+ .probe = bcm_iproc_probe, -+ .remove = bcm_iproc_remove, -+ .driver = { -+ .name = "bcm_iproc", -+ .pm = &bcm_qspi_pm_ops, -+ .of_match_table = bcm_iproc_of_match, -+ } -+}; -+module_platform_driver(bcm_iproc_driver); -+ -+MODULE_LICENSE("GPL v2"); -+MODULE_AUTHOR("Kamal Dasu"); -+MODULE_DESCRIPTION("SPI flash driver for Broadcom iProc SoCs"); |