aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLudovic Barre <ludovic.barre@st.com>2017-04-13 13:15:57 -0400
committerCyrille Pitchen <cyrille.pitchen@wedev4u.fr>2017-05-01 10:45:32 -0400
commit0d43d7ab277a048c4b1455ee00030933e1bd5fa3 (patch)
treed96da317b19ab41d1d8255b052b0933737170fbd
parentb0fcb4b413028376894feaaaf62bcb09ab1b52f2 (diff)
mtd: spi-nor: add driver for STM32 quad spi flash controller
The quadspi is a specialized communication interface targeting single, dual or quad SPI Flash memories. It can operate in any of the following modes: -indirect mode: all the operations are performed using the quadspi registers -read memory-mapped mode: the external Flash memory is mapped to the microcontroller address space and is seen by the system as if it was an internal memory Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Reviewed-by: Marek Vasut <marek.vasut@gmail.com> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
-rw-r--r--drivers/mtd/spi-nor/Kconfig7
-rw-r--r--drivers/mtd/spi-nor/Makefile1
-rw-r--r--drivers/mtd/spi-nor/stm32-quadspi.c693
3 files changed, 701 insertions, 0 deletions
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 7252087ef407..bfdfb1e72b38 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -106,4 +106,11 @@ config SPI_INTEL_SPI_PLATFORM
106 To compile this driver as a module, choose M here: the module 106 To compile this driver as a module, choose M here: the module
107 will be called intel-spi-platform. 107 will be called intel-spi-platform.
108 108
109config SPI_STM32_QUADSPI
110 tristate "STM32 Quad SPI controller"
111 depends on ARCH_STM32
112 help
113 This enables support for the STM32 Quad SPI controller.
114 We only connect the NOR to this controller.
115
109endif # MTD_SPI_NOR 116endif # MTD_SPI_NOR
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 72238a793198..285aab86c7ca 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o
8obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o 8obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
9obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o 9obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o
10obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM) += intel-spi-platform.o 10obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM) += intel-spi-platform.o
11obj-$(CONFIG_SPI_STM32_QUADSPI) += stm32-quadspi.o \ No newline at end of file
diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c b/drivers/mtd/spi-nor/stm32-quadspi.c
new file mode 100644
index 000000000000..ae45f81b8cd3
--- /dev/null
+++ b/drivers/mtd/spi-nor/stm32-quadspi.c
@@ -0,0 +1,693 @@
1/*
2 * stm32_quadspi.c
3 *
4 * Copyright (C) 2017, Ludovic Barre
5 *
6 * License terms: GNU General Public License (GPL), version 2
7 */
8#include <linux/clk.h>
9#include <linux/errno.h>
10#include <linux/io.h>
11#include <linux/iopoll.h>
12#include <linux/interrupt.h>
13#include <linux/module.h>
14#include <linux/mtd/mtd.h>
15#include <linux/mtd/partitions.h>
16#include <linux/mtd/spi-nor.h>
17#include <linux/mutex.h>
18#include <linux/of.h>
19#include <linux/of_device.h>
20#include <linux/platform_device.h>
21#include <linux/reset.h>
22
23#define QUADSPI_CR 0x00
24#define CR_EN BIT(0)
25#define CR_ABORT BIT(1)
26#define CR_DMAEN BIT(2)
27#define CR_TCEN BIT(3)
28#define CR_SSHIFT BIT(4)
29#define CR_DFM BIT(6)
30#define CR_FSEL BIT(7)
31#define CR_FTHRES_SHIFT 8
32#define CR_FTHRES_MASK GENMASK(12, 8)
33#define CR_FTHRES(n) (((n) << CR_FTHRES_SHIFT) & CR_FTHRES_MASK)
34#define CR_TEIE BIT(16)
35#define CR_TCIE BIT(17)
36#define CR_FTIE BIT(18)
37#define CR_SMIE BIT(19)
38#define CR_TOIE BIT(20)
39#define CR_PRESC_SHIFT 24
40#define CR_PRESC_MASK GENMASK(31, 24)
41#define CR_PRESC(n) (((n) << CR_PRESC_SHIFT) & CR_PRESC_MASK)
42
43#define QUADSPI_DCR 0x04
44#define DCR_CSHT_SHIFT 8
45#define DCR_CSHT_MASK GENMASK(10, 8)
46#define DCR_CSHT(n) (((n) << DCR_CSHT_SHIFT) & DCR_CSHT_MASK)
47#define DCR_FSIZE_SHIFT 16
48#define DCR_FSIZE_MASK GENMASK(20, 16)
49#define DCR_FSIZE(n) (((n) << DCR_FSIZE_SHIFT) & DCR_FSIZE_MASK)
50
51#define QUADSPI_SR 0x08
52#define SR_TEF BIT(0)
53#define SR_TCF BIT(1)
54#define SR_FTF BIT(2)
55#define SR_SMF BIT(3)
56#define SR_TOF BIT(4)
57#define SR_BUSY BIT(5)
58#define SR_FLEVEL_SHIFT 8
59#define SR_FLEVEL_MASK GENMASK(13, 8)
60
61#define QUADSPI_FCR 0x0c
62#define FCR_CTCF BIT(1)
63
64#define QUADSPI_DLR 0x10
65
66#define QUADSPI_CCR 0x14
67#define CCR_INST_SHIFT 0
68#define CCR_INST_MASK GENMASK(7, 0)
69#define CCR_INST(n) (((n) << CCR_INST_SHIFT) & CCR_INST_MASK)
70#define CCR_IMODE_NONE (0U << 8)
71#define CCR_IMODE_1 (1U << 8)
72#define CCR_IMODE_2 (2U << 8)
73#define CCR_IMODE_4 (3U << 8)
74#define CCR_ADMODE_NONE (0U << 10)
75#define CCR_ADMODE_1 (1U << 10)
76#define CCR_ADMODE_2 (2U << 10)
77#define CCR_ADMODE_4 (3U << 10)
78#define CCR_ADSIZE_SHIFT 12
79#define CCR_ADSIZE_MASK GENMASK(13, 12)
80#define CCR_ADSIZE(n) (((n) << CCR_ADSIZE_SHIFT) & CCR_ADSIZE_MASK)
81#define CCR_ABMODE_NONE (0U << 14)
82#define CCR_ABMODE_1 (1U << 14)
83#define CCR_ABMODE_2 (2U << 14)
84#define CCR_ABMODE_4 (3U << 14)
85#define CCR_ABSIZE_8 (0U << 16)
86#define CCR_ABSIZE_16 (1U << 16)
87#define CCR_ABSIZE_24 (2U << 16)
88#define CCR_ABSIZE_32 (3U << 16)
89#define CCR_DCYC_SHIFT 18
90#define CCR_DCYC_MASK GENMASK(22, 18)
91#define CCR_DCYC(n) (((n) << CCR_DCYC_SHIFT) & CCR_DCYC_MASK)
92#define CCR_DMODE_NONE (0U << 24)
93#define CCR_DMODE_1 (1U << 24)
94#define CCR_DMODE_2 (2U << 24)
95#define CCR_DMODE_4 (3U << 24)
96#define CCR_FMODE_INDW (0U << 26)
97#define CCR_FMODE_INDR (1U << 26)
98#define CCR_FMODE_APM (2U << 26)
99#define CCR_FMODE_MM (3U << 26)
100
101#define QUADSPI_AR 0x18
102#define QUADSPI_ABR 0x1c
103#define QUADSPI_DR 0x20
104#define QUADSPI_PSMKR 0x24
105#define QUADSPI_PSMAR 0x28
106#define QUADSPI_PIR 0x2c
107#define QUADSPI_LPTR 0x30
108#define LPTR_DFT_TIMEOUT 0x10
109
110#define FSIZE_VAL(size) (__fls(size) - 1)
111
112#define STM32_MAX_MMAP_SZ SZ_256M
113#define STM32_MAX_NORCHIP 2
114
115#define STM32_QSPI_FIFO_TIMEOUT_US 30000
116#define STM32_QSPI_BUSY_TIMEOUT_US 100000
117
118struct stm32_qspi_flash {
119 struct spi_nor nor;
120 struct stm32_qspi *qspi;
121 u32 cs;
122 u32 fsize;
123 u32 presc;
124 u32 read_mode;
125 bool registered;
126};
127
128struct stm32_qspi {
129 struct device *dev;
130 void __iomem *io_base;
131 void __iomem *mm_base;
132 resource_size_t mm_size;
133 u32 nor_num;
134 struct clk *clk;
135 u32 clk_rate;
136 struct stm32_qspi_flash flash[STM32_MAX_NORCHIP];
137 struct completion cmd_completion;
138
139 /*
140 * to protect device configuration, could be different between
141 * 2 flash access (bk1, bk2)
142 */
143 struct mutex lock;
144};
145
146struct stm32_qspi_cmd {
147 u8 addr_width;
148 u8 dummy;
149 bool tx_data;
150 u8 opcode;
151 u32 framemode;
152 u32 qspimode;
153 u32 addr;
154 size_t len;
155 void *buf;
156};
157
158static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi)
159{
160 u32 cr;
161 int err = 0;
162
163 if (readl_relaxed(qspi->io_base + QUADSPI_SR) & SR_TCF)
164 return 0;
165
166 reinit_completion(&qspi->cmd_completion);
167 cr = readl_relaxed(qspi->io_base + QUADSPI_CR);
168 writel_relaxed(cr | CR_TCIE, qspi->io_base + QUADSPI_CR);
169
170 if (!wait_for_completion_interruptible_timeout(&qspi->cmd_completion,
171 msecs_to_jiffies(1000)))
172 err = -ETIMEDOUT;
173
174 writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
175 return err;
176}
177