Loading drivers/spi/Kconfig +2 −1 Original line number Diff line number Diff line Loading @@ -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. Loading drivers/spi/spi-armada-3700.c +6 −8 Original line number Diff line number Diff line Loading @@ -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: Loading Loading @@ -340,7 +340,6 @@ 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); return IRQ_HANDLED; Loading Loading @@ -562,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; Loading Loading @@ -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; } Loading @@ -909,7 +908,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, Loading drivers/spi/spi-ath79.c +12 −11 Original line number Diff line number Diff line Loading @@ -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); gpio_set_value_cansleep(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); } Loading Loading @@ -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; Loading @@ -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); } Loading @@ -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); } } Loading drivers/spi/spi-bcm-qspi.c +128 −66 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 { Loading Loading @@ -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) { Loading @@ -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)) Loading @@ -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; Loading Loading @@ -813,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; Loading @@ -826,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) { Loading @@ -840,27 +851,33 @@ 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; /* * read into the entire buffer by breaking the reads * into RAF buffer read lengths */ len = msg->len; qspi->bspi_rf_msg_idx = 0; do { if (len > BSPI_READ_LENGTH) rdlen = BSPI_READ_LENGTH; else rdlen = len; reinit_completion(&qspi->bspi_done); bcm_qspi_enable_bspi(qspi); len_words = (len + 3) >> 2; len_words = (rdlen + 3) >> 2; qspi->bspi_rf_msg = msg; qspi->bspi_rf_msg_status = 0; 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); 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 Loading @@ -872,16 +889,89 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, /* 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; } else { /* set the return length for the caller */ msg->retlen = len; break; } /* set msg return length */ msg->retlen += rdlen; addr += rdlen; len -= rdlen; } while (len); 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; } Loading Loading @@ -918,8 +1008,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; Loading @@ -931,33 +1020,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); Loading Loading @@ -1187,6 +1249,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; Loading Loading @@ -1345,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); Loading drivers/spi/spi-bcm53xx.c +10 −8 Original line number Diff line number Diff line /* * Copyright (C) 2014-2016 Rafał Miłecki <rafal@milecki.pl> * * 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 <linux/kernel.h> Loading Loading @@ -275,10 +283,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), {}, Loading Loading @@ -311,6 +315,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; Loading @@ -324,9 +329,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; } Loading Loading @@ -361,4 +363,4 @@ module_exit(bcm53xxspi_module_exit); MODULE_DESCRIPTION("Broadcom BCM53xx SPI Controller driver"); MODULE_AUTHOR("Rafał Miłecki <zajec5@gmail.com>"); MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2"); Loading
drivers/spi/Kconfig +2 −1 Original line number Diff line number Diff line Loading @@ -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. Loading
drivers/spi/spi-armada-3700.c +6 −8 Original line number Diff line number Diff line Loading @@ -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: Loading Loading @@ -340,7 +340,6 @@ 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); return IRQ_HANDLED; Loading Loading @@ -562,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; Loading Loading @@ -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; } Loading @@ -909,7 +908,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, Loading
drivers/spi/spi-ath79.c +12 −11 Original line number Diff line number Diff line Loading @@ -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); gpio_set_value_cansleep(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); } Loading Loading @@ -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; Loading @@ -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); } Loading @@ -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); } } Loading
drivers/spi/spi-bcm-qspi.c +128 −66 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 { Loading Loading @@ -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) { Loading @@ -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)) Loading @@ -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; Loading Loading @@ -813,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; Loading @@ -826,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) { Loading @@ -840,27 +851,33 @@ 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; /* * read into the entire buffer by breaking the reads * into RAF buffer read lengths */ len = msg->len; qspi->bspi_rf_msg_idx = 0; do { if (len > BSPI_READ_LENGTH) rdlen = BSPI_READ_LENGTH; else rdlen = len; reinit_completion(&qspi->bspi_done); bcm_qspi_enable_bspi(qspi); len_words = (len + 3) >> 2; len_words = (rdlen + 3) >> 2; qspi->bspi_rf_msg = msg; qspi->bspi_rf_msg_status = 0; 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); 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 Loading @@ -872,16 +889,89 @@ static int bcm_qspi_bspi_flash_read(struct spi_device *spi, /* 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; } else { /* set the return length for the caller */ msg->retlen = len; break; } /* set msg return length */ msg->retlen += rdlen; addr += rdlen; len -= rdlen; } while (len); 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; } Loading Loading @@ -918,8 +1008,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; Loading @@ -931,33 +1020,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); Loading Loading @@ -1187,6 +1249,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; Loading Loading @@ -1345,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); Loading
drivers/spi/spi-bcm53xx.c +10 −8 Original line number Diff line number Diff line /* * Copyright (C) 2014-2016 Rafał Miłecki <rafal@milecki.pl> * * 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 <linux/kernel.h> Loading Loading @@ -275,10 +283,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), {}, Loading Loading @@ -311,6 +315,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; Loading @@ -324,9 +329,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; } Loading Loading @@ -361,4 +363,4 @@ module_exit(bcm53xxspi_module_exit); MODULE_DESCRIPTION("Broadcom BCM53xx SPI Controller driver"); MODULE_AUTHOR("Rafał Miłecki <zajec5@gmail.com>"); MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");