diff options
| author | Mark Brown <broonie@kernel.org> | 2019-03-04 15:32:51 +0000 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2019-03-04 15:32:51 +0000 |
| commit | 14dbfb417bd80c96ec700c7a8414bb6f5db7ecd2 (patch) | |
| tree | f79fb71b6206ef40aa34c52649053a2aaa493a3c /drivers/spi | |
| parent | b50c6ac8b6fb3e7b5cf843afd789c8553a910254 (diff) | |
| parent | 0e836c3bea7da04cd4e2ed22d8c20654d5a09273 (diff) | |
| download | linux-14dbfb417bd80c96ec700c7a8414bb6f5db7ecd2.tar.gz linux-14dbfb417bd80c96ec700c7a8414bb6f5db7ecd2.tar.bz2 linux-14dbfb417bd80c96ec700c7a8414bb6f5db7ecd2.zip | |
Merge branch 'spi-5.1' into spi-next
Diffstat (limited to 'drivers/spi')
30 files changed, 4799 insertions, 1141 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9f89cb134549..f761655e2a36 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -63,7 +63,7 @@ config SPI_ALTERA config SPI_ATH79 tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver" - depends on ATH79 && GPIOLIB + depends on ATH79 || COMPILE_TEST select SPI_BITBANG help This enables support for the SPI controller present on the @@ -268,6 +268,27 @@ config SPI_FSL_LPSPI help This enables Freescale i.MX LPSPI controllers in master mode. +config SPI_FSL_QUADSPI + tristate "Freescale QSPI controller" + depends on ARCH_MXC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST + depends on HAS_IOMEM + help + This enables support for the Quad SPI controller in master mode. + Up to four flash chips can be connected on two buses with two + chipselects each. + This controller does not support generic SPI messages. It only + supports the high-level SPI memory interface. + +config SPI_NXP_FLEXSPI + tristate "NXP Flex SPI controller" + depends on ARCH_LAYERSCAPE || HAS_IOMEM + help + This enables support for the Flex SPI controller in master mode. + Up to four slave devices can be connected on two buses with two + chipselects each. + This controller does not support generic SPI messages and only + supports the high-level SPI memory interface. + config SPI_GPIO tristate "GPIO-based bitbanging SPI Master" depends on GPIOLIB || COMPILE_TEST @@ -296,8 +317,7 @@ config SPI_IMX depends on ARCH_MXC || COMPILE_TEST select SPI_BITBANG help - This enables using the Freescale i.MX SPI controllers in master - mode. + This enables support for the Freescale i.MX SPI controllers. config SPI_JCORE tristate "J-Core SPI Master" @@ -372,7 +392,7 @@ config SPI_FSL_DSPI depends on SOC_VF610 || SOC_LS1021A || ARCH_LAYERSCAPE || M5441x || COMPILE_TEST help This enables support for the Freescale DSPI controller in master - mode. VF610 platform uses the controller. + mode. VF610, LS1021A and ColdFire platforms uses the controller. config SPI_FSL_ESPI tristate "Freescale eSPI controller" @@ -631,6 +651,12 @@ config SPI_SH_HSPI help SPI driver for SuperH HSPI blocks. +config SPI_SIFIVE + tristate "SiFive SPI controller" + depends on HAS_IOMEM + help + This exposes the SPI controller IP from SiFive. + config SPI_SIRF tristate "CSR SiRFprimaII SPI controller" depends on SIRF_DMA @@ -665,7 +691,7 @@ config SPI_STM32 tristate "STMicroelectronics STM32 SPI controller" depends on ARCH_STM32 || COMPILE_TEST help - SPI driver for STMicroelectonics STM32 SoCs. + SPI driver for STMicroelectronics STM32 SoCs. STM32 SPI controller supports DMA and PIO modes. When DMA is not available, the driver automatically falls back to diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index f29627040dfb..d8fc03c9faa2 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_LPSPI) += spi-fsl-lpspi.o +obj-$(CONFIG_SPI_FSL_QUADSPI) += spi-fsl-qspi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_GPIO) += spi-gpio.o obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o @@ -63,6 +64,7 @@ obj-$(CONFIG_SPI_MXIC) += spi-mxic.o obj-$(CONFIG_SPI_MXS) += spi-mxs.o obj-$(CONFIG_SPI_NPCM_PSPI) += spi-npcm-pspi.o obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o +obj-$(CONFIG_SPI_NXP_FLEXSPI) += spi-nxp-fspi.o obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o spi-octeon-objs := spi-cavium.o spi-cavium-octeon.o obj-$(CONFIG_SPI_OCTEON) += spi-octeon.o @@ -93,6 +95,7 @@ obj-$(CONFIG_SPI_SH) += spi-sh.o obj-$(CONFIG_SPI_SH_HSPI) += spi-sh-hspi.o obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o +obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o obj-$(CONFIG_SPI_SIRF) += spi-sirf.o obj-$(CONFIG_SPI_SLAVE_MT27XX) += spi-slave-mt27xx.o obj-$(CONFIG_SPI_SPRD) += spi-sprd.o diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index ddc712410812..fffc21cd5f79 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for Atmel QSPI Controller * @@ -7,31 +8,19 @@ * Author: Cyrille Pitchen <cyrille.pitchen@atmel.com> * Author: Piotr Bugalski <bugalski.piotr@gmail.com> * - * 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. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - * * This driver is based on drivers/mtd/spi-nor/fsl-quadspi.c from Freescale. */ -#include <linux/kernel.h> #include <linux/clk.h> -#include <linux/module.h> -#include <linux/platform_device.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/interrupt.h> -#include <linux/of.h> - #include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/spi/spi-mem.h> /* QSPI register offsets */ @@ -47,7 +36,9 @@ #define QSPI_IAR 0x0030 /* Instruction Address Register */ #define QSPI_ICR 0x0034 /* Instruction Code Register */ +#define QSPI_WICR 0x0034 /* Write Instruction Code Register */ #define QSPI_IFR 0x0038 /* Instruction Frame Register */ +#define QSPI_RICR 0x003C /* Read Instruction Code Register */ #define QSPI_SMR 0x0040 /* Scrambling Mode Register */ #define QSPI_SKR 0x0044 /* Scrambling Key Register */ @@ -100,7 +91,7 @@ #define QSPI_SCR_DLYBS_MASK GENMASK(23, 16) #define QSPI_SCR_DLYBS(n) (((n) << 16) & QSPI_SCR_DLYBS_MASK) -/* Bitfields in QSPI_ICR (Instruction Code Register) */ +/* Bitfields in QSPI_ICR (Read/Write Instruction Code Register) */ #define QSPI_ICR_INST_MASK GENMASK(7, 0) #define QSPI_ICR_INST(inst) (((inst) << 0) & QSPI_ICR_INST_MASK) #define QSPI_ICR_OPT_MASK GENMASK(23, 16) @@ -125,14 +116,12 @@ #define QSPI_IFR_OPTL_4BIT (2 << 8) #define QSPI_IFR_OPTL_8BIT (3 << 8) #define QSPI_IFR_ADDRL BIT(10) -#define QSPI_IFR_TFRTYP_MASK GENMASK(13, 12) -#define QSPI_IFR_TFRTYP_TRSFR_READ (0 << 12) -#define QSPI_IFR_TFRTYP_TRSFR_READ_MEM (1 << 12) -#define QSPI_IFR_TFRTYP_TRSFR_WRITE (2 << 12) -#define QSPI_IFR_TFRTYP_TRSFR_WRITE_MEM (3 << 13) +#define QSPI_IFR_TFRTYP_MEM BIT(12) +#define QSPI_IFR_SAMA5D2_WRITE_TRSFR BIT(13) #define QSPI_IFR_CRM BIT(14) #define QSPI_IFR_NBDUM_MASK GENMASK(20, 16) #define QSPI_IFR_NBDUM(n) (((n) << 16) & QSPI_IFR_NBDUM_MASK) +#define QSPI_IFR_APBTFRTYP_READ BIT(24) /* Defined in SAM9X60 */ /* Bitfields in QSPI_SMR (Scrambling Mode Register) */ #define QSPI_SMR_SCREN BIT(0) @@ -148,24 +137,31 @@ #define QSPI_WPSR_WPVSRC_MASK GENMASK(15, 8) #define QSPI_WPSR_WPVSRC(src) (((src) << 8) & QSPI_WPSR_WPVSRC) +struct atmel_qspi_caps { + bool has_qspick; + bool has_ricr; +}; struct atmel_qspi { void __iomem *regs; void __iomem *mem; - struct clk *clk; + struct clk *pclk; + struct clk *qspick; struct platform_device *pdev; + const struct atmel_qspi_caps *caps; u32 pending; + u32 mr; struct completion cmd_completion; }; -struct qspi_mode { +struct atmel_qspi_mode { u8 cmd_buswidth; u8 addr_buswidth; u8 data_buswidth; u32 config; }; -static const struct qspi_mode sama5d2_qspi_modes[] = { +static const struct atmel_qspi_mode atmel_qspi_modes[] = { { 1, 1, 1, QSPI_IFR_WIDTH_SINGLE_BIT_SPI }, { 1, 1, 2, QSPI_IFR_WIDTH_DUAL_OUTPUT }, { 1, 1, 4, QSPI_IFR_WIDTH_QUAD_OUTPUT }, @@ -175,19 +171,8 @@ static const struct qspi_mode sama5d2_qspi_modes[] = { { 4, 4, 4, QSPI_IFR_WIDTH_QUAD_CMD }, }; -/* Register access functions */ -static inline u32 qspi_readl(struct atmel_qspi *aq, u32 reg) -{ - return readl_relaxed(aq->regs + reg); -} - -static inline void qspi_writel(struct atmel_qspi *aq, u32 reg, u32 value) -{ - writel_relaxed(value, aq->regs + reg); -} - -static inline bool is_compatible(const struct spi_mem_op *op, - const struct qspi_mode *mode) +static inline bool atmel_qspi_is_compatible(const struct spi_mem_op *op, + const struct atmel_qspi_mode *mode) { if (op->cmd.buswidth != mode->cmd_buswidth) return false; @@ -201,21 +186,21 @@ static inline bool is_compatible(const struct spi_mem_op *op, return true; } -static int find_mode(const struct spi_mem_op *op) +static int atmel_qspi_find_mode(const struct spi_mem_op *op) { u32 i; - for (i = 0; i < ARRAY_SIZE(sama5d2_qspi_modes); i++) - if (is_compatible(op, &sama5d2_qspi_modes[i])) + for (i = 0; i < ARRAY_SIZE(atmel_qspi_modes); i++) + if (atmel_qspi_is_compatible(op, &atmel_qspi_modes[i])) return i; - return -1; + return -ENOTSUPP; } static bool atmel_qspi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) { - if (find_mode(op) < 0) + if (atmel_qspi_find_mode(op) < 0) return false; /* special case not supported by hardware */ @@ -226,29 +211,37 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem, return true; } -static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) +static int atmel_qspi_set_cfg(struct atmel_qspi *aq, + const struct spi_mem_op *op, u32 *offset) { - struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->master); - int mode; + u32 iar, icr, ifr; u32 dummy_cycles = 0; - u32 iar, icr, ifr, sr; - int err = 0; + int mode; iar = 0; icr = QSPI_ICR_INST(op->cmd.opcode); ifr = QSPI_IFR_INSTEN; - qspi_writel(aq, QSPI_MR, QSPI_MR_SMM); - - mode = find_mode(op); + mode = atmel_qspi_find_mode(op); if (mode < 0) - return -ENOTSUPP; - - ifr |= sama5d2_qspi_modes[mode].config; + return mode; + ifr |= atmel_qspi_modes[mode].config; if (op->dummy.buswidth && op->dummy.nbytes) dummy_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth; + /* + * The controller allows 24 and 32-bit addressing while NAND-flash + * requires 16-bit long. Handling 8-bit long addresses is done using + * the option field. For the 16-bit addresses, the workaround depends + * of the number of requested dummy bits. If there are 8 or more dummy + * cycles, the address is shifted and sent with the first dummy byte. + * Otherwise opcode is disabled and the first byte of the address + * contains the command opcode (works only if the opcode and address + * use the same buswidth). The limitation is when the 16-bit address is + * used without enough dummy cycles and the opcode is using a different + * buswidth than the address. + */ if (op->addr.buswidth) { switch (op->addr.nbytes) { case 0: @@ -282,6 +275,9 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) } } + /* offset of the data access in the QSPI memory space */ + *offset = iar; + /* Set number of dummy cycles */ if (dummy_cycles) ifr |= QSPI_IFR_NBDUM(dummy_cycles); @@ -290,49 +286,82 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) if (op->data.nbytes) ifr |= QSPI_IFR_DATAEN; - if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes) - ifr |= QSPI_IFR_TFRTYP_TRSFR_READ; - else - ifr |= QSPI_IFR_TFRTYP_TRSFR_WRITE; + /* + * If the QSPI controller is set in regular SPI mode, set it in + * Serial Memory Mode (SMM). + */ + if (aq->mr != QSPI_MR_SMM) { + writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR); + aq->mr = QSPI_MR_SMM; + } /* Clear pending interrupts */ - (void)qspi_readl(aq, QSPI_SR); + (void)readl_relaxed(aq->regs + QSPI_SR); + + if (aq->caps->has_ricr) { + if (!op->addr.nbytes && op->data.dir == SPI_MEM_DATA_IN) + ifr |= QSPI_IFR_APBTFRTYP_READ; - /* Set QSPI Instruction Frame registers */ - qspi_writel(aq, QSPI_IAR, iar); - qspi_writel(aq, QSPI_ICR, icr); - qspi_writel(aq, QSPI_IFR, ifr); + /* Set QSPI Instruction Frame registers */ + writel_relaxed(iar, aq->regs + QSPI_IAR); + if (op->data.dir == SPI_MEM_DATA_IN) + writel_relaxed(icr, aq->regs + QSPI_RICR); + else + writel_relaxed(icr, aq->regs + QSPI_WICR); + writel_relaxed(ifr, aq->regs + QSPI_IFR); + } else { + if (op->data.dir == SPI_MEM_DATA_OUT) + ifr |= QSPI_IFR_SAMA5D2_WRITE_TRSFR; + + /* Set QSPI Instruction Frame registers */ + writel_relaxed(iar, aq->regs + QSPI_IAR); + writel_relaxed(icr, aq->regs + QSPI_ICR); + writel_relaxed(ifr, aq->regs + QSPI_IFR); + } + + return 0; +} + +static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) +{ + struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->master); + u32 sr, offset; + int err; + + err = atmel_qspi_set_cfg(aq, op, &offset); + if (err) + return err; /* Skip to the final steps if there is no data */ if (op->data.nbytes) { /* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */ - (void)qspi_readl(aq, QSPI_IFR); + (void)readl_relaxed(aq->regs + QSPI_IFR); /* Send/Receive data */ if (op->data.dir == SPI_MEM_DATA_IN) - _memcpy_fromio(op->data.buf.in, - aq->mem + iar, op->data.nbytes); + _memcpy_fromio(op->data.buf.in, aq->mem + offset, + op->data.nbytes); else - _memcpy_toio(aq->mem + iar, - op->data.buf.out, op->data.nbytes); + _memcpy_toio(aq->mem + offset, op->data.buf.out, + op->data.nbytes); /* Release the chip-select */ - qspi_writel(aq, QSPI_CR, QSPI_CR_LASTXFER); + writel_relaxed(QSPI_CR_LASTXFER, aq->regs + QSPI_CR); } /* Poll INSTRuction End status */ - sr = qspi_readl(aq, QSPI_SR); + sr = readl_relaxed(aq->regs + QSPI_SR); if ((sr & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED) return err; /* Wait for INSTRuction End interrupt */ reinit_completion(&aq->cmd_completion); aq->pending = sr & QSPI_SR_CMD_COMPLETED; - qspi_writel(aq, QSPI_IER, QSPI_SR_CMD_COMPLETED); + writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IER); if (!wait_for_completion_timeout(&aq->cmd_completion, msecs_to_jiffies(1000))) err = -ETIMEDOUT; - qspi_writel(aq, QSPI_IDR, QSPI_SR_CMD_COMPLETED); + writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IDR); return err; } @@ -361,7 +390,7 @@ static int atmel_qspi_setup(struct spi_device *spi) if (!spi->max_speed_hz) return -EINVAL; - src_rate = clk_get_rate(aq->clk); + src_rate = clk_get_rate(aq->pclk); if (!src_rate) return -EINVAL; @@ -371,7 +400,7 @@ static int atmel_qspi_setup(struct spi_device *spi) scbr--; scr = QSPI_SCR_SCBR(scbr); - qspi_writel(aq, QSPI_SCR, scr); + writel_relaxed(scr, aq->regs + QSPI_SCR); return 0; } @@ -379,21 +408,25 @@ static int atmel_qspi_setup(struct spi_device *spi) static int atmel_qspi_init(struct atmel_qspi *aq) { /* Reset the QSPI controller */ - qspi_writel(aq, QSPI_CR, QSPI_CR_SWRST); + writel_relaxed(QSPI_CR_SWRST, aq->regs + QSPI_CR); + + /* Set the QSPI controller by default in Serial Memory Mode */ + writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR); + aq->mr = QSPI_MR_SMM; /* Enable the QSPI controller */ - qspi_writel(aq, QSPI_CR, QSPI_CR_QSPIEN); + writel_relaxed(QSPI_CR_QSPIEN, aq->regs + QSPI_CR); return 0; } static irqreturn_t atmel_qspi_interrupt(int irq, void *dev_id) { - struct atmel_qspi *aq = (struct atmel_qspi *)dev_id; + struct atmel_qspi *aq = dev_id; u32 status, mask, pending; - status = qspi_readl(aq, QSPI_SR); - mask = qspi_readl(aq, QSPI_IMR); + status = readl_relaxed(aq->regs + QSPI_SR); + mask = readl_relaxed(aq->regs + QSPI_IMR); pending = status & mask; if (!pending) @@ -449,44 +482,74 @@ static int atmel_qspi_probe(struct platform_device *pdev) } /* Get the peripheral clock */ - aq->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(aq->clk)) { + aq->pclk = devm_clk_get(&pdev->dev, "pclk"); + if (IS_ERR(aq->pclk)) + aq->pclk = devm_clk_get(&pdev->dev, NULL); + + if (IS_ERR(aq->pclk)) { dev_err(&pdev->dev, "missing peripheral clock\n"); - err = PTR_ERR(aq->clk); + err = PTR_ERR(aq->pclk); goto exit; } /* Enable the peripheral clock */ - err = clk_prepare_enable(aq->clk); + err = clk_prepare_enable(aq->pclk); if (err) { dev_err(&pdev->dev, "failed to enable the peripheral clock\n"); goto exit; } + aq->caps = of_device_get_match_data(&pdev->dev); + if (!aq->caps) { + dev_err(&pdev->dev, "Could not retrieve QSPI caps\n"); + err = -EINVAL; + goto exit; + } + + if (aq->caps->has_qspick) { + /* Get the QSPI system clock */ + aq->qspick = devm_clk_get(&pdev->dev, "qspick"); + if (IS_ERR(aq->qspick)) { + dev_err(&pdev->dev, "missing system clock\n"); + err = PTR_ERR(aq->qspick); + goto disable_pclk; + } + + /* Enable the QSPI system clock */ + err = clk_prepare_enable(aq->qspick); + if (err) { + dev_err(&pdev->dev, + "failed to enable the QSPI system clock\n"); + goto disable_pclk; + } + } + /* Request the IRQ */ irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "missing IRQ\n"); err = irq; - goto disable_clk; + goto disable_qspick; } err = devm_request_irq(&pdev->dev, irq, atmel_qspi_interrupt, 0, dev_name(&pdev->dev), aq); if (err) - goto disable_clk; + goto disable_qspick; err = atmel_qspi_init(aq); if (err) - goto disable_clk; + goto disable_qspick; err = spi_register_controller(ctrl); if (err) - goto disable_clk; + goto disable_qspick; return 0; -disable_clk: - clk_disable_unprepare(aq->clk); +disable_qspick: + clk_disable_unprepare(aq->qspick); +disable_pclk: + clk_disable_unprepare(aq->pclk); exit: spi_controller_put(ctrl); @@ -499,8 +562,9 @@ static int atmel_qspi_remove(struct platform_device *pdev) struct atmel_qspi *aq = spi_controller_get_devdata(ctrl); spi_unregister_controller(ctrl); - qspi_writel(aq, QSPI_CR, QSPI_CR_QSPIDIS); - clk_disable_unprepare(aq->clk); + writel_relaxed(QSPI_CR_QSPIDIS, aq->regs + QSPI_CR); + clk_disable_unprepare(aq->qspick); + clk_disable_unprepare(aq->pclk); return 0; } @@ -508,7 +572,8 @@ static int __maybe_unused atmel_qspi_suspend(struct device *dev) { struct atmel_qspi *aq = dev_get_drvdata(dev); - clk_disable_unprepare(aq->clk); + clk_disable_unprepare(aq->qspick); + clk_disable_unprepare(aq->pclk); return 0; } @@ -517,7 +582,8 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev) { struct atmel_qspi *aq = dev_get_drvdata(dev); - clk_prepare_enable(aq->clk); + clk_prepare_enable(aq->pclk); + clk_prepare_enable(aq->qspick); return atmel_qspi_init(aq); } @@ -525,8 +591,22 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(atmel_qspi_pm_ops, atmel_qspi_suspend, atmel_qspi_resume); +static const struct atmel_qspi_caps atmel_sama5d2_qspi_caps = {}; + +static const struct atmel_qspi_caps atmel_sam9x60_qspi_caps = { + .has_qspick = true, + .has_ricr = true, +}; + static const struct of_device_id atmel_qspi_dt_ids[] = { - { .compatible = "atmel,sama5d2-qspi" }, + { + .compatible = "atmel,sama5d2-qspi", + .data = &atmel_sama5d2_qspi_caps, + }, + { + .compatible = "microchip,sam9x60-qspi", + .data = &atmel_sam9x60_qspi_caps, + }, { /* sentinel */ } }; diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index 3f6b657394de..847f354ebef1 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -21,18 +21,26 @@ #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> #include <linux/bitops.h> -#include <linux/gpio.h> #include <linux/clk.h> #include <linux/err.h> - -#include <asm/mach-ath79/ar71xx_regs.h> -#include <asm/mach-ath79/ath79_spi_platform.h> +#include <linux/platform_data/spi-ath79.h> #define DRV_NAME "ath79-spi" #define ATH79_SPI_RRW_DELAY_FACTOR 12000 #define MHZ (1000 * 1000) +#define AR71XX_SPI_REG_FS 0x00 /* Function Select */ +#define AR71XX_SPI_REG_CTRL 0x04 /* SPI Control */ +#define AR71XX_SPI_REG_IOC 0x08 /* SPI I/O Control */ +#define AR71XX_SPI_REG_RDS 0x0c /* Read Data Shift */ + +#define AR71XX_SPI_FS_GPIO BIT(0) /* Enable GPIO mode */ + +#define AR71XX_SPI_IOC_DO BIT(0) /* Data Out pin */ +#define AR71XX_SPI_IOC_CLK BIT(8) /* CLK pin */ +#define AR71XX_SPI_IOC_CS(n) BIT(16 + (n)) + struct ath79_spi { struct spi_bitbang bitbang; u32 ioc_base; @@ -67,31 +75,14 @@ static void ath79_spi_chipselect(struct spi_device *spi, int is_active) { struct ath79_spi *sp = ath79_spidev_to_sp(spi); int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active; + u32 cs_bit = AR71XX_SPI_IOC_CS(spi->chip_select); - if (is_active) { - /* set initial clock polarity */ - if (spi->mode & SPI_CPOL) - sp->ioc_base |= AR71XX_SPI_IOC_CLK; - else - sp->ioc_base &= ~AR71XX_SPI_IOC_CLK; - - ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); - } - - if (gpio_is_valid(spi->cs_gpio)) { - /* SPI is normally active-low */ - 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 |= cs_bit; - else - sp->ioc_base &= ~cs_bit; - - ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); - } + if (cs_high) + sp->ioc_base |= cs_bit; + else + sp->ioc_base &= ~cs_bit; + ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); } static void ath79_spi_enable(struct ath79_spi *sp) @@ -103,6 +94,9 @@ static void ath79_spi_enable(struct ath79_spi *sp) sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL); sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC); + /* clear clk and mosi in the base state */ + sp->ioc_base &= ~(AR71XX_SPI_IOC_DO | AR71XX_SPI_IOC_CLK); + /* TODO: setup speed? */ ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43); } @@ -115,66 +109,6 @@ static void ath79_spi_disable(struct ath79_spi *sp) ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); } -static int ath79_spi_setup_cs(struct spi_device *spi) -{ - struct ath79_spi *sp = ath79_spidev_to_sp(spi); - int status; - - status = 0; - if (gpio_is_valid(spi->cs_gpio)) { - unsigned long flags; - - flags = GPIOF_DIR_OUT; - if (spi->mode & SPI_CS_HIGH) - flags |= GPIOF_INIT_LOW; - else - flags |= GPIOF_INIT_HIGH; - - 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 &= ~cs_bit; - else - sp->ioc_base |= cs_bit; - - ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); - } - - return status; -} - -static void ath79_spi_cleanup_cs(struct spi_device *spi) -{ - if (gpio_is_valid(spi->cs_gpio)) - gpio_free(spi->cs_gpio); -} - -static int ath79_spi_setup(struct spi_device *spi) -{ - int status = 0; - - if (!spi->controller_state) { - status = ath79_spi_setup_cs(spi); - if (status) - return status; - } - - status = spi_bitbang_setup(spi); - if (status && !spi->controller_state) - ath79_spi_cleanup_cs(spi); - - return status; -} - -static void ath79_spi_cleanup(struct spi_device *spi) -{ - ath79_spi_cleanup_cs(spi); - spi_bitbang_cleanup(spi); -} - static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs, u32 word, u8 bits, unsigned flags) { @@ -225,9 +159,10 @@ static int ath79_spi_probe(struct platform_device *pdev) pdata = dev_get_platdata(&pdev->dev); + master->use_gpio_descriptors = true; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); - master->setup = ath79_spi_setup; - master->cleanup = ath79_spi_cleanup; + master->setup = spi_bitbang_setup; + master->cleanup = spi_bitbang_cleanup; if (pdata) { master->bus_num = pdata->bus_num; master->num_chipselect = pdata->num_chipselect; @@ -236,7 +171,6 @@ static int ath79_spi_probe(struct platform_device *pdev) sp->bitbang.master = master; sp->bitbang.chipselect = ath79_spi_chipselect; sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0; - sp->bitbang.setup_transfer = spi_bitbang_setup_transfer; sp->bitbang.flags = SPI_CS_HIGH; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 74fddcd3282b..4954f0ab1606 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -23,8 +23,7 @@ #include <linux/of.h> #include <linux/io.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> @@ -312,7 +311,7 @@ struct atmel_spi { /* Controller-specific per-slave state */ struct atmel_spi_device { - unsigned int npcs_pin; + struct gpio_desc *npcs_pin; u32 csr; }; @@ -355,7 +354,6 @@ static bool atmel_spi_is_v2(struct atmel_spi *as) static void cs_activate(struct atmel_spi *as, struct spi_device *spi) { struct atmel_spi_device *asd = spi->controller_state; - unsigned active = spi->mod |
