From 22c76326bff810d220fffdbaab949d09e2564067 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 9 Dec 2016 20:48:52 +0100 Subject: [PATCH 01/13] spi: spi-ath79: support multiple internal chip select lines Several devices with multiple flash chips use the internal chip select lines. Don't assume that chip select 1 and above are GPIO lines. Signed-off-by: Felix Fietkau Signed-off-by: Mark Brown --- drivers/spi/spi-ath79.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index f369174fbd88..3e9b928b563b 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -78,14 +78,16 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active) ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); } - if (spi->chip_select) { + if (gpio_is_valid(spi->cs_gpio)) { /* SPI is normally active-low */ gpio_set_value(spi->cs_gpio, cs_high); } else { + u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); + if (cs_high) - sp->ioc_base |= AR71XX_SPI_IOC_CS0; + sp->ioc_base |= cs_bit; else - sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; + sp->ioc_base &= ~cs_bit; ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); } @@ -118,11 +120,8 @@ static int ath79_spi_setup_cs(struct spi_device *spi) struct ath79_spi *sp = ath79_spidev_to_sp(spi); int status; - if (spi->chip_select && !gpio_is_valid(spi->cs_gpio)) - return -EINVAL; - status = 0; - if (spi->chip_select) { + if (gpio_is_valid(spi->cs_gpio)) { unsigned long flags; flags = GPIOF_DIR_OUT; @@ -134,10 +133,12 @@ static int ath79_spi_setup_cs(struct spi_device *spi) status = gpio_request_one(spi->cs_gpio, flags, dev_name(&spi->dev)); } else { + u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); + if (spi->mode & SPI_CS_HIGH) - sp->ioc_base &= ~AR71XX_SPI_IOC_CS0; + sp->ioc_base &= ~cs_bit; else - sp->ioc_base |= AR71XX_SPI_IOC_CS0; + sp->ioc_base |= cs_bit; ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); } @@ -147,7 +148,7 @@ static int ath79_spi_setup_cs(struct spi_device *spi) static void ath79_spi_cleanup_cs(struct spi_device *spi) { - if (spi->chip_select) { + if (gpio_is_valid(spi->cs_gpio)) { gpio_free(spi->cs_gpio); } } From 91829a9a25cc931b76b01aa091a52e0edd649a72 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 9 Dec 2016 20:48:53 +0100 Subject: [PATCH 02/13] spi: spi-ath79: use gpio_set_value_cansleep for GPIO chip select Signed-off-by: Felix Fietkau Signed-off-by: Mark Brown --- drivers/spi/spi-ath79.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 3e9b928b563b..b89cee11f418 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -80,7 +80,7 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active) if (gpio_is_valid(spi->cs_gpio)) { /* SPI is normally active-low */ - gpio_set_value(spi->cs_gpio, cs_high); + gpio_set_value_cansleep(spi->cs_gpio, cs_high); } else { u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); From 0cc059abac0dc687dc714f3ec2c8d8a134132f56 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 16 Dec 2016 12:33:59 +0300 Subject: [PATCH 03/13] spi: armada-3700: Remove unnecessary condition We checked that "a3700_spi->wait_mask & cause" was set at the beginning of the function so we don't need to check again here. Signed-off-by: Dan Carpenter Acked-by: Romain Perier Signed-off-by: Mark Brown --- drivers/spi/spi-armada-3700.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index 4e921782652f..4e68f34957cc 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -340,8 +340,7 @@ static irqreturn_t a3700_spi_interrupt(int irq, void *dev_id) spireg_write(a3700_spi, A3700_SPI_INT_STAT_REG, cause); /* Wake up the transfer */ - if (a3700_spi->wait_mask & cause) - complete(&a3700_spi->done); + complete(&a3700_spi->done); return IRQ_HANDLED; } From 279e4af7b4bebc6a5bf2d0e5b3209f3dcea94a19 Mon Sep 17 00:00:00 2001 From: Jaedon Shin Date: Fri, 30 Dec 2016 15:30:00 +0900 Subject: [PATCH 04/13] spi: bcm-qspi: Enable the driver on BMIPS_GENERIC The Broadcom BCM7XXX ARM and MIPS based SoCs share a similar hardware block for SPI. Signed-off-by: Jaedon Shin Acked-by: Florian Fainelli Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ec4aa252d6e8..c982a01022ba 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -162,7 +162,8 @@ config SPI_BCM63XX_HSSPI config SPI_BCM_QSPI tristate "Broadcom BSPI and MSPI controller support" - depends on ARCH_BRCMSTB || ARCH_BCM || ARCH_BCM_IPROC || COMPILE_TEST + depends on ARCH_BRCMSTB || ARCH_BCM || ARCH_BCM_IPROC || \ + BMIPS_GENERIC || COMPILE_TEST default ARCH_BCM_IPROC help Enables support for the Broadcom SPI flash and MSPI controller. From 78d759daceaf0a7058f37c4142bdca9948b6d987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 29 Dec 2016 17:27:55 +0100 Subject: [PATCH 05/13] spi: bcm53xx: set of_node to let DT specify device(s) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting of_node of master's dev seems to be a common way of letting it work nicely with DT. This allows specifying device there instead of hardcoding one in the driver code. This was successfully tested with commit 1b47b98acce2 ("ARM: BCM5301X: Add DT entry for SPI controller and NOR flash") Signed-off-by: Rafał Miłecki Signed-off-by: Mark Brown --- drivers/spi/spi-bcm53xx.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/spi/spi-bcm53xx.c b/drivers/spi/spi-bcm53xx.c index afb51699dbb5..0c61ad4edb1a 100644 --- a/drivers/spi/spi-bcm53xx.c +++ b/drivers/spi/spi-bcm53xx.c @@ -275,10 +275,6 @@ static int bcm53xxspi_flash_read(struct spi_device *spi, * BCMA **************************************************/ -static struct spi_board_info bcm53xx_info = { - .modalias = "bcm53xxspiflash", -}; - static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = { BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS), {}, @@ -311,6 +307,7 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core) b53spi->bspi = true; bcm53xxspi_disable_bspi(b53spi); + master->dev.of_node = dev->of_node; master->transfer_one = bcm53xxspi_transfer_one; if (b53spi->mmio_base) master->spi_flash_read = bcm53xxspi_flash_read; @@ -324,9 +321,6 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core) return err; } - /* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */ - spi_new_device(master, &bcm53xx_info); - return 0; } From cfd6693c06324174ceeac7aed570a0df67db7c4f Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Wed, 21 Dec 2016 11:10:30 +0100 Subject: [PATCH 06/13] spi: armada-3700: Replaced raw values for nbits by the SPI macros Currently, function a3700_spi_pin_mode_set() configures the SPI transfer mode according to the value passed as second argument. This value is detected using the raw values from a switch case. This commit replaces these raw values by the corresponding macro constants in linux/spi/spi.h Signed-off-by: Romain Perier Signed-off-by: Mark Brown --- drivers/spi/spi-armada-3700.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index 4e68f34957cc..9bee56ddff39 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -170,12 +170,12 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, val &= ~(A3700_SPI_DATA_PIN0 | A3700_SPI_DATA_PIN1); switch (pin_mode) { - case 1: + case SPI_NBITS_SINGLE: break; - case 2: + case SPI_NBITS_DUAL: val |= A3700_SPI_DATA_PIN0; break; - case 4: + case SPI_NBITS_QUAD: val |= A3700_SPI_DATA_PIN1; break; default: From 85798e153e6c3834ab2d69ee9d4db7d85f13809d Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Wed, 21 Dec 2016 11:10:29 +0100 Subject: [PATCH 07/13] spi: armada-3700: Coding style fixes The following warning are reported by checkpatch.pl: CHECK: Alignment should match open parenthesis +static void a3700_spi_transfer_setup(struct spi_device *spi, + struct spi_transfer *xfer) WARNING: Missing a blank line after declarations + u32 data = le32_to_cpu(val); + memcpy(a3700_spi->rx_buf, &data, 4); total: 0 errors, 1 warnings, 1 checks, 923 lines checked Signed-off-by: Romain Perier Signed-off-by: Mark Brown --- drivers/spi/spi-armada-3700.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index 9bee56ddff39..0baa69325e78 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -420,7 +420,7 @@ static void a3700_spi_fifo_thres_set(struct a3700_spi *a3700_spi, } static void a3700_spi_transfer_setup(struct spi_device *spi, - struct spi_transfer *xfer) + struct spi_transfer *xfer) { struct a3700_spi *a3700_spi; unsigned int byte_len; @@ -561,6 +561,7 @@ static int a3700_spi_fifo_read(struct a3700_spi *a3700_spi) val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG); if (a3700_spi->buf_len >= 4) { u32 data = le32_to_cpu(val); + memcpy(a3700_spi->rx_buf, &data, 4); a3700_spi->buf_len -= 4; From e360e72e715f228e426edf0fc99ffa34027ab0ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 29 Dec 2016 20:13:13 +0100 Subject: [PATCH 08/13] spi: bcm53xx: (re)license code to the GPL v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit My intention was to release this code under GPL v2 license. For some reason my initial commit 0fc6a323e191 ("spi: bcm53xx: driver for SPI controller on Broadcom bcma SoC") totally missed licensing info. MODULE_LICENSE was later added by Axel specifying "GNU Public License v2 or later". This patch clarifies situation by adding a proper header (with Copyright line) and adjusting MODULE_LICENSE. It should be acked by every driver contributor. Signed-off-by: Rafał Miłecki Acked-by: Nicholas Mc Guire Reviewed-by: Jingoo Han Acked-by: Jingoo Han Acked-by: Joe Perches Acked-by: Axel Lin Acked-by: Vaishali Thakkar Signed-off-by: Mark Brown --- drivers/spi/spi-bcm53xx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-bcm53xx.c b/drivers/spi/spi-bcm53xx.c index 0c61ad4edb1a..6e409eabe1c9 100644 --- a/drivers/spi/spi-bcm53xx.c +++ b/drivers/spi/spi-bcm53xx.c @@ -1,3 +1,11 @@ +/* + * Copyright (C) 2014-2016 Rafał Miłecki + * + * 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. + */ + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include @@ -355,4 +363,4 @@ module_exit(bcm53xxspi_module_exit); MODULE_DESCRIPTION("Broadcom BCM53xx SPI Controller driver"); MODULE_AUTHOR("Rafał Miłecki "); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); From 81ab52fd94f32aaa8a9c27b41934e4ae932ca106 Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Mon, 30 Jan 2017 16:11:16 -0500 Subject: [PATCH 09/13] spi: bcm-qspi: Added mspi read fallback in bcm_qspi_flash_read() Added mspi read fallback under certain circumstances like unaligned buffer, address on short reads. Also takes care of version 3.0 spi controller where flash address crosses 4MB boundary on transfers the driver resorts to mspi reads. Signed-off-by: Kamal Dasu Signed-off-by: Mark Brown --- drivers/spi/spi-bcm-qspi.c | 116 +++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 31 deletions(-) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 14f9dea3173f..b50b6dfc8c48 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -192,9 +192,11 @@ struct bcm_qspi_dev_id { void *dev; }; + struct qspi_trans { struct spi_transfer *trans; int byte; + bool mspi_last_trans; }; struct bcm_qspi { @@ -616,6 +618,16 @@ static int bcm_qspi_setup(struct spi_device *spi) return 0; } +static bool bcm_qspi_mspi_transfer_is_last(struct bcm_qspi *qspi, + struct qspi_trans *qt) +{ + if (qt->mspi_last_trans && + spi_transfer_is_last(qspi->master, qt->trans)) + return true; + else + return false; +} + static int update_qspi_trans_byte_count(struct bcm_qspi *qspi, struct qspi_trans *qt, int flags) { @@ -629,7 +641,6 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi, if (qt->byte >= qt->trans->len) { /* we're at the end of the spi_transfer */ - /* in TX mode, need to pause for a delay or CS change */ if (qt->trans->delay_usecs && (flags & TRANS_STATUS_BREAK_DELAY)) @@ -641,7 +652,7 @@ static int update_qspi_trans_byte_count(struct bcm_qspi *qspi, goto done; dev_dbg(&qspi->pdev->dev, "advance msg exit\n"); - if (spi_transfer_is_last(qspi->master, qt->trans)) + if (bcm_qspi_mspi_transfer_is_last(qspi, qt)) ret = TRANS_STATUS_BREAK_EOM; else ret = TRANS_STATUS_BREAK_NO_BYTES; @@ -885,6 +896,76 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, return ret; } +static int bcm_qspi_transfer_one(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *trans) +{ + struct bcm_qspi *qspi = spi_master_get_devdata(master); + int slots; + unsigned long timeo = msecs_to_jiffies(100); + + bcm_qspi_chip_select(qspi, spi->chip_select); + qspi->trans_pos.trans = trans; + qspi->trans_pos.byte = 0; + + while (qspi->trans_pos.byte < trans->len) { + reinit_completion(&qspi->mspi_done); + + slots = write_to_hw(qspi, spi); + if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) { + dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n"); + return -ETIMEDOUT; + } + + read_from_hw(qspi, slots); + } + + return 0; +} + +static int bcm_qspi_mspi_flash_read(struct spi_device *spi, + struct spi_flash_read_message *msg) +{ + struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); + struct spi_transfer t[2]; + u8 cmd[6]; + int ret; + + memset(cmd, 0, sizeof(cmd)); + memset(t, 0, sizeof(t)); + + /* tx */ + /* opcode is in cmd[0] */ + cmd[0] = msg->read_opcode; + cmd[1] = msg->from >> (msg->addr_width * 8 - 8); + cmd[2] = msg->from >> (msg->addr_width * 8 - 16); + cmd[3] = msg->from >> (msg->addr_width * 8 - 24); + cmd[4] = msg->from >> (msg->addr_width * 8 - 32); + t[0].tx_buf = cmd; + t[0].len = msg->addr_width + msg->dummy_bytes + 1; + t[0].bits_per_word = spi->bits_per_word; + t[0].tx_nbits = msg->opcode_nbits; + /* lets mspi know that this is not last transfer */ + qspi->trans_pos.mspi_last_trans = false; + ret = bcm_qspi_transfer_one(spi->master, spi, &t[0]); + + /* rx */ + qspi->trans_pos.mspi_last_trans = true; + if (!ret) { + /* rx */ + t[1].rx_buf = msg->buf; + t[1].len = msg->len; + t[1].rx_nbits = msg->data_nbits; + t[1].bits_per_word = spi->bits_per_word; + ret = bcm_qspi_transfer_one(spi->master, spi, &t[1]); + } + + if (!ret) + msg->retlen = msg->len; + + return ret; +} + static int bcm_qspi_flash_read(struct spi_device *spi, struct spi_flash_read_message *msg) { @@ -918,8 +999,7 @@ static int bcm_qspi_flash_read(struct spi_device *spi, mspi_read = true; if (mspi_read) - /* this will make the m25p80 read to fallback to mspi read */ - return -EAGAIN; + return bcm_qspi_mspi_flash_read(spi, msg); io_width = msg->data_nbits ? msg->data_nbits : SPI_NBITS_SINGLE; addrlen = msg->addr_width; @@ -931,33 +1011,6 @@ static int bcm_qspi_flash_read(struct spi_device *spi, return ret; } -static int bcm_qspi_transfer_one(struct spi_master *master, - struct spi_device *spi, - struct spi_transfer *trans) -{ - struct bcm_qspi *qspi = spi_master_get_devdata(master); - int slots; - unsigned long timeo = msecs_to_jiffies(100); - - bcm_qspi_chip_select(qspi, spi->chip_select); - qspi->trans_pos.trans = trans; - qspi->trans_pos.byte = 0; - - while (qspi->trans_pos.byte < trans->len) { - reinit_completion(&qspi->mspi_done); - - slots = write_to_hw(qspi, spi); - if (!wait_for_completion_timeout(&qspi->mspi_done, timeo)) { - dev_err(&qspi->pdev->dev, "timeout waiting for MSPI\n"); - return -ETIMEDOUT; - } - - read_from_hw(qspi, slots); - } - - return 0; -} - static void bcm_qspi_cleanup(struct spi_device *spi) { struct bcm_qspi_parms *xp = spi_get_ctldata(spi); @@ -1187,6 +1240,7 @@ int bcm_qspi_probe(struct platform_device *pdev, qspi->pdev = pdev; qspi->trans_pos.trans = NULL; qspi->trans_pos.byte = 0; + qspi->trans_pos.mspi_last_trans = true; qspi->master = master; master->bus_num = -1; From d9928b4c48a804cf4e4f5695855282bddf7e2c3b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 7 Feb 2017 14:30:03 +0000 Subject: [PATCH 10/13] spi: armada-3700: Remove .owner field for driver Remove .owner field if calls are used which set it automatically. Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- drivers/spi/spi-armada-3700.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index 0baa69325e78..3155ab7ad970 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -909,7 +909,6 @@ static int a3700_spi_remove(struct platform_device *pdev) static struct platform_driver a3700_spi_driver = { .driver = { .name = DRIVER_NAME, - .owner = THIS_MODULE, .of_match_table = of_match_ptr(a3700_spi_dt_ids), }, .probe = a3700_spi_probe, From 345309fa7c0c9206a5344d379b174499952d79d9 Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Wed, 8 Feb 2017 15:15:04 -0500 Subject: [PATCH 11/13] spi: bcm-qspi: Fix bcm_qspi_bspi_read() performance Let bcm_qspi_bspi_flash_read() return all the requested bytes by breaking up the reads for BSPI block into optimal chunks size that a BSPI block can handle. Signed-off-by: Kamal Dasu Signed-off-by: Mark Brown --- drivers/spi/spi-bcm-qspi.c | 81 +++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index b50b6dfc8c48..99b3057531a5 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -89,7 +89,7 @@ #define BSPI_BPP_MODE_SELECT_MASK BIT(8) #define BSPI_BPP_ADDR_SELECT_MASK BIT(16) -#define BSPI_READ_LENGTH 256 +#define BSPI_READ_LENGTH 512 /* MSPI register offsets */ #define MSPI_SPCR0_LSB 0x000 @@ -824,7 +824,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, struct spi_flash_read_message *msg) { struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); - u32 addr = 0, len, len_words; + u32 addr = 0, len, rdlen, len_words; int ret = 0; unsigned long timeo = msecs_to_jiffies(100); struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc; @@ -837,7 +837,7 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0); /* - * when using flex mode mode we need to send + * when using flex mode we need to send * the upper address byte to bspi */ if (bcm_qspi_bspi_ver_three(qspi) == false) { @@ -851,47 +851,56 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, else addr = msg->from & 0x00ffffff; - /* set BSPI RAF buffer max read length */ - len = msg->len; - if (len > BSPI_READ_LENGTH) - len = BSPI_READ_LENGTH; - if (bcm_qspi_bspi_ver_three(qspi) == true) addr = (addr + 0xc00000) & 0xffffff; - reinit_completion(&qspi->bspi_done); - bcm_qspi_enable_bspi(qspi); - len_words = (len + 3) >> 2; - qspi->bspi_rf_msg = msg; - qspi->bspi_rf_msg_status = 0; + /* + * read into the entire buffer by breaking the reads + * into RAF buffer read lengths + */ + len = msg->len; qspi->bspi_rf_msg_idx = 0; - qspi->bspi_rf_msg_len = len; - dev_dbg(&qspi->pdev->dev, "bspi xfr addr 0x%x len 0x%x", addr, len); - bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr); - bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words); - bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0); + do { + if (len > BSPI_READ_LENGTH) + rdlen = BSPI_READ_LENGTH; + else + rdlen = len; - 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); - } + reinit_completion(&qspi->bspi_done); + bcm_qspi_enable_bspi(qspi); + len_words = (rdlen + 3) >> 2; + qspi->bspi_rf_msg = msg; + qspi->bspi_rf_msg_status = 0; + qspi->bspi_rf_msg_len = rdlen; + dev_dbg(&qspi->pdev->dev, + "bspi xfr addr 0x%x len 0x%x", addr, rdlen); + bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr); + 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(); + /* Must flush previous writes before starting BSPI operation */ + mb(); + bcm_qspi_bspi_lr_start(qspi); + if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) { + dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n"); + ret = -ETIMEDOUT; + break; + } - bcm_qspi_bspi_lr_start(qspi); - if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) { - dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n"); - ret = -ETIMEDOUT; - } else { - /* set the return length for the caller */ - msg->retlen = len; - } + /* set msg return length */ + msg->retlen += rdlen; + addr += rdlen; + len -= rdlen; + } while (len); return ret; } From 973f7dd575891d0e67469861b47f43175553f30a Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 9 Feb 2017 15:32:21 +0000 Subject: [PATCH 12/13] spi: bcm-qspi: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure. Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- drivers/spi/spi-bcm-qspi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 99b3057531a5..958fb4ee972d 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -1408,7 +1408,6 @@ int bcm_qspi_remove(struct platform_device *pdev) { struct bcm_qspi *qspi = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); bcm_qspi_hw_uninit(qspi); clk_disable_unprepare(qspi->clk); kfree(qspi->dev_ids); From e92f0051c0c65d7bee989884a233cfcd80303bdf Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 5 Feb 2017 15:49:40 +0000 Subject: [PATCH 13/13] spi: armada-3700: Remove spi_master_put in a3700_spi_remove() The call to spi_master_put() in a3700_spi_remove() is redundant since the master is registered using devm_spi_register_master() and no reference hold by using spi_master_get() in a3700_spi_remove(). This is detected by Coccinelle semantic patch. Fixes: 5762ab71eb24 ("spi: Add support for Armada 3700 SPI Controller") Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- drivers/spi/spi-armada-3700.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index 3155ab7ad970..56acd3511f73 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -901,7 +901,6 @@ static int a3700_spi_remove(struct platform_device *pdev) struct a3700_spi *spi = spi_master_get_devdata(master); clk_unprepare(spi->clk); - spi_master_put(master); return 0; }