1d4363baaSMichael Kurz /*
2d4363baaSMichael Kurz * (C) Copyright 2016
3d4363baaSMichael Kurz *
4d4363baaSMichael Kurz * Michael Kurz, <michi.kurz@gmail.com>
5d4363baaSMichael Kurz *
6d4363baaSMichael Kurz * STM32 QSPI driver
7d4363baaSMichael Kurz *
8d4363baaSMichael Kurz * SPDX-License-Identifier: GPL-2.0+
9d4363baaSMichael Kurz */
10d4363baaSMichael Kurz
11d4363baaSMichael Kurz #include <common.h>
12d4363baaSMichael Kurz #include <malloc.h>
13d4363baaSMichael Kurz #include <spi.h>
14d4363baaSMichael Kurz #include <spi_flash.h>
15d4363baaSMichael Kurz #include <asm/io.h>
16d4363baaSMichael Kurz #include <dm.h>
17d4363baaSMichael Kurz #include <errno.h>
18d4363baaSMichael Kurz #include <asm/arch/stm32.h>
19d4363baaSMichael Kurz #include <asm/arch/stm32_defs.h>
20890bafd7SVikas Manocha #include <clk.h>
21d4363baaSMichael Kurz
22d4363baaSMichael Kurz DECLARE_GLOBAL_DATA_PTR;
23d4363baaSMichael Kurz
24d4363baaSMichael Kurz struct stm32_qspi_regs {
25d4363baaSMichael Kurz u32 cr; /* 0x00 */
26d4363baaSMichael Kurz u32 dcr; /* 0x04 */
27d4363baaSMichael Kurz u32 sr; /* 0x08 */
28d4363baaSMichael Kurz u32 fcr; /* 0x0C */
29d4363baaSMichael Kurz u32 dlr; /* 0x10 */
30d4363baaSMichael Kurz u32 ccr; /* 0x14 */
31d4363baaSMichael Kurz u32 ar; /* 0x18 */
32d4363baaSMichael Kurz u32 abr; /* 0x1C */
33d4363baaSMichael Kurz u32 dr; /* 0x20 */
34d4363baaSMichael Kurz u32 psmkr; /* 0x24 */
35d4363baaSMichael Kurz u32 psmar; /* 0x28 */
36d4363baaSMichael Kurz u32 pir; /* 0x2C */
37d4363baaSMichael Kurz u32 lptr; /* 0x30 */
38d4363baaSMichael Kurz };
39d4363baaSMichael Kurz
40d4363baaSMichael Kurz /*
41d4363baaSMichael Kurz * QUADSPI control register
42d4363baaSMichael Kurz */
43d4363baaSMichael Kurz #define STM32_QSPI_CR_EN BIT(0)
44d4363baaSMichael Kurz #define STM32_QSPI_CR_ABORT BIT(1)
45d4363baaSMichael Kurz #define STM32_QSPI_CR_DMAEN BIT(2)
46d4363baaSMichael Kurz #define STM32_QSPI_CR_TCEN BIT(3)
47d4363baaSMichael Kurz #define STM32_QSPI_CR_SSHIFT BIT(4)
48d4363baaSMichael Kurz #define STM32_QSPI_CR_DFM BIT(6)
49d4363baaSMichael Kurz #define STM32_QSPI_CR_FSEL BIT(7)
50d4363baaSMichael Kurz #define STM32_QSPI_CR_FTHRES_MASK GENMASK(4, 0)
51d4363baaSMichael Kurz #define STM32_QSPI_CR_FTHRES_SHIFT (8)
52d4363baaSMichael Kurz #define STM32_QSPI_CR_TEIE BIT(16)
53d4363baaSMichael Kurz #define STM32_QSPI_CR_TCIE BIT(17)
54d4363baaSMichael Kurz #define STM32_QSPI_CR_FTIE BIT(18)
55d4363baaSMichael Kurz #define STM32_QSPI_CR_SMIE BIT(19)
56d4363baaSMichael Kurz #define STM32_QSPI_CR_TOIE BIT(20)
57d4363baaSMichael Kurz #define STM32_QSPI_CR_APMS BIT(22)
58d4363baaSMichael Kurz #define STM32_QSPI_CR_PMM BIT(23)
59d4363baaSMichael Kurz #define STM32_QSPI_CR_PRESCALER_MASK GENMASK(7, 0)
60d4363baaSMichael Kurz #define STM32_QSPI_CR_PRESCALER_SHIFT (24)
61d4363baaSMichael Kurz
62d4363baaSMichael Kurz /*
63d4363baaSMichael Kurz * QUADSPI device configuration register
64d4363baaSMichael Kurz */
65d4363baaSMichael Kurz #define STM32_QSPI_DCR_CKMODE BIT(0)
66d4363baaSMichael Kurz #define STM32_QSPI_DCR_CSHT_MASK GENMASK(2, 0)
67d4363baaSMichael Kurz #define STM32_QSPI_DCR_CSHT_SHIFT (8)
68d4363baaSMichael Kurz #define STM32_QSPI_DCR_FSIZE_MASK GENMASK(4, 0)
69d4363baaSMichael Kurz #define STM32_QSPI_DCR_FSIZE_SHIFT (16)
70d4363baaSMichael Kurz
71d4363baaSMichael Kurz /*
72d4363baaSMichael Kurz * QUADSPI status register
73d4363baaSMichael Kurz */
74d4363baaSMichael Kurz #define STM32_QSPI_SR_TEF BIT(0)
75d4363baaSMichael Kurz #define STM32_QSPI_SR_TCF BIT(1)
76d4363baaSMichael Kurz #define STM32_QSPI_SR_FTF BIT(2)
77d4363baaSMichael Kurz #define STM32_QSPI_SR_SMF BIT(3)
78d4363baaSMichael Kurz #define STM32_QSPI_SR_TOF BIT(4)
79d4363baaSMichael Kurz #define STM32_QSPI_SR_BUSY BIT(5)
80d4363baaSMichael Kurz #define STM32_QSPI_SR_FLEVEL_MASK GENMASK(5, 0)
81d4363baaSMichael Kurz #define STM32_QSPI_SR_FLEVEL_SHIFT (8)
82d4363baaSMichael Kurz
83d4363baaSMichael Kurz /*
84d4363baaSMichael Kurz * QUADSPI flag clear register
85d4363baaSMichael Kurz */
86d4363baaSMichael Kurz #define STM32_QSPI_FCR_CTEF BIT(0)
87d4363baaSMichael Kurz #define STM32_QSPI_FCR_CTCF BIT(1)
88d4363baaSMichael Kurz #define STM32_QSPI_FCR_CSMF BIT(3)
89d4363baaSMichael Kurz #define STM32_QSPI_FCR_CTOF BIT(4)
90d4363baaSMichael Kurz
91d4363baaSMichael Kurz /*
92d4363baaSMichael Kurz * QUADSPI communication configuration register
93d4363baaSMichael Kurz */
94d4363baaSMichael Kurz #define STM32_QSPI_CCR_DDRM BIT(31)
95d4363baaSMichael Kurz #define STM32_QSPI_CCR_DHHC BIT(30)
96d4363baaSMichael Kurz #define STM32_QSPI_CCR_SIOO BIT(28)
97d4363baaSMichael Kurz #define STM32_QSPI_CCR_FMODE_SHIFT (26)
98d4363baaSMichael Kurz #define STM32_QSPI_CCR_DMODE_SHIFT (24)
99d4363baaSMichael Kurz #define STM32_QSPI_CCR_DCYC_SHIFT (18)
100d4363baaSMichael Kurz #define STM32_QSPI_CCR_DCYC_MASK GENMASK(4, 0)
101d4363baaSMichael Kurz #define STM32_QSPI_CCR_ABSIZE_SHIFT (16)
102d4363baaSMichael Kurz #define STM32_QSPI_CCR_ABMODE_SHIFT (14)
103d4363baaSMichael Kurz #define STM32_QSPI_CCR_ADSIZE_SHIFT (12)
104d4363baaSMichael Kurz #define STM32_QSPI_CCR_ADMODE_SHIFT (10)
105d4363baaSMichael Kurz #define STM32_QSPI_CCR_IMODE_SHIFT (8)
106d4363baaSMichael Kurz #define STM32_QSPI_CCR_INSTRUCTION_MASK GENMASK(7, 0)
107d4363baaSMichael Kurz
108d4363baaSMichael Kurz enum STM32_QSPI_CCR_IMODE {
109d4363baaSMichael Kurz STM32_QSPI_CCR_IMODE_NONE = 0,
110d4363baaSMichael Kurz STM32_QSPI_CCR_IMODE_ONE_LINE = 1,
111d4363baaSMichael Kurz STM32_QSPI_CCR_IMODE_TWO_LINE = 2,
112d4363baaSMichael Kurz STM32_QSPI_CCR_IMODE_FOUR_LINE = 3,
113d4363baaSMichael Kurz };
114d4363baaSMichael Kurz
115d4363baaSMichael Kurz enum STM32_QSPI_CCR_ADMODE {
116d4363baaSMichael Kurz STM32_QSPI_CCR_ADMODE_NONE = 0,
117d4363baaSMichael Kurz STM32_QSPI_CCR_ADMODE_ONE_LINE = 1,
118d4363baaSMichael Kurz STM32_QSPI_CCR_ADMODE_TWO_LINE = 2,
119d4363baaSMichael Kurz STM32_QSPI_CCR_ADMODE_FOUR_LINE = 3,
120d4363baaSMichael Kurz };
121d4363baaSMichael Kurz
122d4363baaSMichael Kurz enum STM32_QSPI_CCR_ADSIZE {
123d4363baaSMichael Kurz STM32_QSPI_CCR_ADSIZE_8BIT = 0,
124d4363baaSMichael Kurz STM32_QSPI_CCR_ADSIZE_16BIT = 1,
125d4363baaSMichael Kurz STM32_QSPI_CCR_ADSIZE_24BIT = 2,
126d4363baaSMichael Kurz STM32_QSPI_CCR_ADSIZE_32BIT = 3,
127d4363baaSMichael Kurz };
128d4363baaSMichael Kurz
129d4363baaSMichael Kurz enum STM32_QSPI_CCR_ABMODE {
130d4363baaSMichael Kurz STM32_QSPI_CCR_ABMODE_NONE = 0,
131d4363baaSMichael Kurz STM32_QSPI_CCR_ABMODE_ONE_LINE = 1,
132d4363baaSMichael Kurz STM32_QSPI_CCR_ABMODE_TWO_LINE = 2,
133d4363baaSMichael Kurz STM32_QSPI_CCR_ABMODE_FOUR_LINE = 3,
134d4363baaSMichael Kurz };
135d4363baaSMichael Kurz
136d4363baaSMichael Kurz enum STM32_QSPI_CCR_ABSIZE {
137d4363baaSMichael Kurz STM32_QSPI_CCR_ABSIZE_8BIT = 0,
138d4363baaSMichael Kurz STM32_QSPI_CCR_ABSIZE_16BIT = 1,
139d4363baaSMichael Kurz STM32_QSPI_CCR_ABSIZE_24BIT = 2,
140d4363baaSMichael Kurz STM32_QSPI_CCR_ABSIZE_32BIT = 3,
141d4363baaSMichael Kurz };
142d4363baaSMichael Kurz
143d4363baaSMichael Kurz enum STM32_QSPI_CCR_DMODE {
144d4363baaSMichael Kurz STM32_QSPI_CCR_DMODE_NONE = 0,
145d4363baaSMichael Kurz STM32_QSPI_CCR_DMODE_ONE_LINE = 1,
146d4363baaSMichael Kurz STM32_QSPI_CCR_DMODE_TWO_LINE = 2,
147d4363baaSMichael Kurz STM32_QSPI_CCR_DMODE_FOUR_LINE = 3,
148d4363baaSMichael Kurz };
149d4363baaSMichael Kurz
150d4363baaSMichael Kurz enum STM32_QSPI_CCR_FMODE {
151d4363baaSMichael Kurz STM32_QSPI_CCR_IND_WRITE = 0,
152d4363baaSMichael Kurz STM32_QSPI_CCR_IND_READ = 1,
153d4363baaSMichael Kurz STM32_QSPI_CCR_AUTO_POLL = 2,
154d4363baaSMichael Kurz STM32_QSPI_CCR_MEM_MAP = 3,
155d4363baaSMichael Kurz };
156d4363baaSMichael Kurz
157d4363baaSMichael Kurz /* default SCK frequency, unit: HZ */
158d4363baaSMichael Kurz #define STM32_QSPI_DEFAULT_SCK_FREQ 108000000
159d4363baaSMichael Kurz
160d4363baaSMichael Kurz struct stm32_qspi_platdata {
161d4363baaSMichael Kurz u32 base;
162d4363baaSMichael Kurz u32 memory_map;
163d4363baaSMichael Kurz u32 max_hz;
164d4363baaSMichael Kurz };
165d4363baaSMichael Kurz
166d4363baaSMichael Kurz struct stm32_qspi_priv {
167d4363baaSMichael Kurz struct stm32_qspi_regs *regs;
168541cd6e5SPatrice Chotard ulong clock_rate;
169d4363baaSMichael Kurz u32 max_hz;
170d4363baaSMichael Kurz u32 mode;
171d4363baaSMichael Kurz
172d4363baaSMichael Kurz u32 command;
173d4363baaSMichael Kurz u32 address;
174d4363baaSMichael Kurz u32 dummycycles;
175d4363baaSMichael Kurz #define CMD_HAS_ADR BIT(24)
176d4363baaSMichael Kurz #define CMD_HAS_DUMMY BIT(25)
177d4363baaSMichael Kurz #define CMD_HAS_DATA BIT(26)
178d4363baaSMichael Kurz };
179d4363baaSMichael Kurz
_stm32_qspi_disable(struct stm32_qspi_priv * priv)180d4363baaSMichael Kurz static void _stm32_qspi_disable(struct stm32_qspi_priv *priv)
181d4363baaSMichael Kurz {
182d4363baaSMichael Kurz clrbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN);
183d4363baaSMichael Kurz }
184d4363baaSMichael Kurz
_stm32_qspi_enable(struct stm32_qspi_priv * priv)185d4363baaSMichael Kurz static void _stm32_qspi_enable(struct stm32_qspi_priv *priv)
186d4363baaSMichael Kurz {
187d4363baaSMichael Kurz setbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN);
188d4363baaSMichael Kurz }
189d4363baaSMichael Kurz
_stm32_qspi_wait_for_not_busy(struct stm32_qspi_priv * priv)190d4363baaSMichael Kurz static void _stm32_qspi_wait_for_not_busy(struct stm32_qspi_priv *priv)
191d4363baaSMichael Kurz {
192d4363baaSMichael Kurz while (readl(&priv->regs->sr) & STM32_QSPI_SR_BUSY)
193d4363baaSMichael Kurz ;
194d4363baaSMichael Kurz }
195d4363baaSMichael Kurz
_stm32_qspi_wait_for_complete(struct stm32_qspi_priv * priv)196d4363baaSMichael Kurz static void _stm32_qspi_wait_for_complete(struct stm32_qspi_priv *priv)
197d4363baaSMichael Kurz {
198d4363baaSMichael Kurz while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_TCF))
199d4363baaSMichael Kurz ;
200d4363baaSMichael Kurz }
201d4363baaSMichael Kurz
_stm32_qspi_wait_for_ftf(struct stm32_qspi_priv * priv)202d4363baaSMichael Kurz static void _stm32_qspi_wait_for_ftf(struct stm32_qspi_priv *priv)
203d4363baaSMichael Kurz {
204d4363baaSMichael Kurz while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_FTF))
205d4363baaSMichael Kurz ;
206d4363baaSMichael Kurz }
207d4363baaSMichael Kurz
_stm32_qspi_set_flash_size(struct stm32_qspi_priv * priv,u32 size)208d4363baaSMichael Kurz static void _stm32_qspi_set_flash_size(struct stm32_qspi_priv *priv, u32 size)
209d4363baaSMichael Kurz {
210d4363baaSMichael Kurz u32 fsize = fls(size) - 1;
211d4363baaSMichael Kurz clrsetbits_le32(&priv->regs->dcr,
212d4363baaSMichael Kurz STM32_QSPI_DCR_FSIZE_MASK << STM32_QSPI_DCR_FSIZE_SHIFT,
213d4363baaSMichael Kurz fsize << STM32_QSPI_DCR_FSIZE_SHIFT);
214d4363baaSMichael Kurz }
215d4363baaSMichael Kurz
_stm32_qspi_gen_ccr(struct stm32_qspi_priv * priv)216d4363baaSMichael Kurz static unsigned int _stm32_qspi_gen_ccr(struct stm32_qspi_priv *priv)
217d4363baaSMichael Kurz {
218d4363baaSMichael Kurz unsigned int ccr_reg = 0;
219d4363baaSMichael Kurz u8 imode, admode, dmode;
220d4363baaSMichael Kurz u32 mode = priv->mode;
221d4363baaSMichael Kurz u32 cmd = (priv->command & STM32_QSPI_CCR_INSTRUCTION_MASK);
222d4363baaSMichael Kurz
223d4363baaSMichael Kurz imode = STM32_QSPI_CCR_IMODE_ONE_LINE;
224d4363baaSMichael Kurz admode = STM32_QSPI_CCR_ADMODE_ONE_LINE;
225d4363baaSMichael Kurz
226d4363baaSMichael Kurz if (mode & SPI_RX_QUAD) {
227d4363baaSMichael Kurz dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE;
228d4363baaSMichael Kurz if (mode & SPI_TX_QUAD) {
229d4363baaSMichael Kurz imode = STM32_QSPI_CCR_IMODE_FOUR_LINE;
230d4363baaSMichael Kurz admode = STM32_QSPI_CCR_ADMODE_FOUR_LINE;
231d4363baaSMichael Kurz }
232d4363baaSMichael Kurz } else if (mode & SPI_RX_DUAL) {
233d4363baaSMichael Kurz dmode = STM32_QSPI_CCR_DMODE_TWO_LINE;
234d4363baaSMichael Kurz if (mode & SPI_TX_DUAL) {
235d4363baaSMichael Kurz imode = STM32_QSPI_CCR_IMODE_TWO_LINE;
236d4363baaSMichael Kurz admode = STM32_QSPI_CCR_ADMODE_TWO_LINE;
237d4363baaSMichael Kurz }
238d4363baaSMichael Kurz } else {
239d4363baaSMichael Kurz dmode = STM32_QSPI_CCR_DMODE_ONE_LINE;
240d4363baaSMichael Kurz }
241d4363baaSMichael Kurz
242d4363baaSMichael Kurz if (priv->command & CMD_HAS_DATA)
243d4363baaSMichael Kurz ccr_reg |= (dmode << STM32_QSPI_CCR_DMODE_SHIFT);
244d4363baaSMichael Kurz
245d4363baaSMichael Kurz if (priv->command & CMD_HAS_DUMMY)
246d4363baaSMichael Kurz ccr_reg |= ((priv->dummycycles & STM32_QSPI_CCR_DCYC_MASK)
247d4363baaSMichael Kurz << STM32_QSPI_CCR_DCYC_SHIFT);
248d4363baaSMichael Kurz
249d4363baaSMichael Kurz if (priv->command & CMD_HAS_ADR) {
250d4363baaSMichael Kurz ccr_reg |= (STM32_QSPI_CCR_ADSIZE_24BIT
251d4363baaSMichael Kurz << STM32_QSPI_CCR_ADSIZE_SHIFT);
252d4363baaSMichael Kurz ccr_reg |= (admode << STM32_QSPI_CCR_ADMODE_SHIFT);
253d4363baaSMichael Kurz }
254d4363baaSMichael Kurz ccr_reg |= (imode << STM32_QSPI_CCR_IMODE_SHIFT);
255d4363baaSMichael Kurz ccr_reg |= cmd;
256d4363baaSMichael Kurz return ccr_reg;
257d4363baaSMichael Kurz }
258d4363baaSMichael Kurz
_stm32_qspi_enable_mmap(struct stm32_qspi_priv * priv,struct spi_flash * flash)259d4363baaSMichael Kurz static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv,
260d4363baaSMichael Kurz struct spi_flash *flash)
261d4363baaSMichael Kurz {
262*f2313133SVignesh R unsigned int ccr_reg;
263*f2313133SVignesh R
264*f2313133SVignesh R priv->command = flash->read_opcode | CMD_HAS_ADR | CMD_HAS_DATA
265d4363baaSMichael Kurz | CMD_HAS_DUMMY;
266*f2313133SVignesh R priv->dummycycles = flash->read_dummy;
267d4363baaSMichael Kurz
268d4363baaSMichael Kurz unsigned int ccr_reg = _stm32_qspi_gen_ccr(priv);
269d4363baaSMichael Kurz ccr_reg |= (STM32_QSPI_CCR_MEM_MAP << STM32_QSPI_CCR_FMODE_SHIFT);
270d4363baaSMichael Kurz
271d4363baaSMichael Kurz _stm32_qspi_wait_for_not_busy(priv);
272d4363baaSMichael Kurz
273d4363baaSMichael Kurz writel(ccr_reg, &priv->regs->ccr);
274d4363baaSMichael Kurz
275d4363baaSMichael Kurz priv->dummycycles = 0;
276d4363baaSMichael Kurz }
277d4363baaSMichael Kurz
_stm32_qspi_disable_mmap(struct stm32_qspi_priv * priv)278d4363baaSMichael Kurz static void _stm32_qspi_disable_mmap(struct stm32_qspi_priv *priv)
279d4363baaSMichael Kurz {
280d4363baaSMichael Kurz setbits_le32(&priv->regs->cr, STM32_QSPI_CR_ABORT);
281d4363baaSMichael Kurz }
282d4363baaSMichael Kurz
_stm32_qspi_set_xfer_length(struct stm32_qspi_priv * priv,u32 length)283d4363baaSMichael Kurz static void _stm32_qspi_set_xfer_length(struct stm32_qspi_priv *priv,
284d4363baaSMichael Kurz u32 length)
285d4363baaSMichael Kurz {
286d4363baaSMichael Kurz writel(length - 1, &priv->regs->dlr);
287d4363baaSMichael Kurz }
288d4363baaSMichael Kurz
_stm32_qspi_start_xfer(struct stm32_qspi_priv * priv,u32 cr_reg)289d4363baaSMichael Kurz static void _stm32_qspi_start_xfer(struct stm32_qspi_priv *priv, u32 cr_reg)
290d4363baaSMichael Kurz {
291d4363baaSMichael Kurz writel(cr_reg, &priv->regs->ccr);
292d4363baaSMichael Kurz
293d4363baaSMichael Kurz if (priv->command & CMD_HAS_ADR)
294d4363baaSMichael Kurz writel(priv->address, &priv->regs->ar);
295d4363baaSMichael Kurz }
296d4363baaSMichael Kurz
_stm32_qspi_xfer(struct stm32_qspi_priv * priv,struct spi_flash * flash,unsigned int bitlen,const u8 * dout,u8 * din,unsigned long flags)297d4363baaSMichael Kurz static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv,
298d4363baaSMichael Kurz struct spi_flash *flash, unsigned int bitlen,
299d4363baaSMichael Kurz const u8 *dout, u8 *din, unsigned long flags)
300d4363baaSMichael Kurz {
301d4363baaSMichael Kurz unsigned int words = bitlen / 8;
302d4363baaSMichael Kurz
303d4363baaSMichael Kurz if (flags & SPI_XFER_MMAP) {
304d4363baaSMichael Kurz _stm32_qspi_enable_mmap(priv, flash);
305d4363baaSMichael Kurz return 0;
306d4363baaSMichael Kurz } else if (flags & SPI_XFER_MMAP_END) {
307d4363baaSMichael Kurz _stm32_qspi_disable_mmap(priv);
308d4363baaSMichael Kurz return 0;
309d4363baaSMichael Kurz }
310d4363baaSMichael Kurz
311d4363baaSMichael Kurz if (bitlen == 0)
312d4363baaSMichael Kurz return -1;
313d4363baaSMichael Kurz
314d4363baaSMichael Kurz if (bitlen % 8) {
315d4363baaSMichael Kurz debug("spi_xfer: Non byte aligned SPI transfer\n");
316d4363baaSMichael Kurz return -1;
317d4363baaSMichael Kurz }
318d4363baaSMichael Kurz
319d4363baaSMichael Kurz if (dout && din) {
320d4363baaSMichael Kurz debug("spi_xfer: QSPI cannot have data in and data out set\n");
321d4363baaSMichael Kurz return -1;
322d4363baaSMichael Kurz }
323d4363baaSMichael Kurz
324d4363baaSMichael Kurz if (!dout && (flags & SPI_XFER_BEGIN)) {
325d4363baaSMichael Kurz debug("spi_xfer: QSPI transfer must begin with command\n");
326d4363baaSMichael Kurz return -1;
327d4363baaSMichael Kurz }
328d4363baaSMichael Kurz
329d4363baaSMichael Kurz if (dout) {
330d4363baaSMichael Kurz if (flags & SPI_XFER_BEGIN) {
331d4363baaSMichael Kurz /* data is command */
332d4363baaSMichael Kurz priv->command = dout[0] | CMD_HAS_DATA;
333d4363baaSMichael Kurz if (words >= 4) {
334d4363baaSMichael Kurz /* address is here too */
335d4363baaSMichael Kurz priv->address = (dout[1] << 16) |
336d4363baaSMichael Kurz (dout[2] << 8) | dout[3];
337d4363baaSMichael Kurz priv->command |= CMD_HAS_ADR;
338d4363baaSMichael Kurz }
339d4363baaSMichael Kurz
340d4363baaSMichael Kurz if (words > 4) {
341d4363baaSMichael Kurz /* rest is dummy bytes */
342d4363baaSMichael Kurz priv->dummycycles = (words - 4) * 8;
343d4363baaSMichael Kurz priv->command |= CMD_HAS_DUMMY;
344d4363baaSMichael Kurz }
345d4363baaSMichael Kurz
346d4363baaSMichael Kurz if (flags & SPI_XFER_END) {
347d4363baaSMichael Kurz /* command without data */
348d4363baaSMichael Kurz priv->command &= ~(CMD_HAS_DATA);
349d4363baaSMichael Kurz }
350d4363baaSMichael Kurz }
351d4363baaSMichael Kurz
352d4363baaSMichael Kurz if (flags & SPI_XFER_END) {
353d4363baaSMichael Kurz u32 ccr_reg = _stm32_qspi_gen_ccr(priv);
354d4363baaSMichael Kurz ccr_reg |= STM32_QSPI_CCR_IND_WRITE
355d4363baaSMichael Kurz << STM32_QSPI_CCR_FMODE_SHIFT;
356d4363baaSMichael Kurz
357d4363baaSMichael Kurz _stm32_qspi_wait_for_not_busy(priv);
358d4363baaSMichael Kurz
359d4363baaSMichael Kurz if (priv->command & CMD_HAS_DATA)
360d4363baaSMichael Kurz _stm32_qspi_set_xfer_length(priv, words);
361d4363baaSMichael Kurz
362d4363baaSMichael Kurz _stm32_qspi_start_xfer(priv, ccr_reg);
363d4363baaSMichael Kurz
364d4363baaSMichael Kurz debug("%s: write: ccr:0x%08x adr:0x%08x\n",
365d4363baaSMichael Kurz __func__, priv->regs->ccr, priv->regs->ar);
366d4363baaSMichael Kurz
367d4363baaSMichael Kurz if (priv->command & CMD_HAS_DATA) {
368d4363baaSMichael Kurz _stm32_qspi_wait_for_ftf(priv);
369d4363baaSMichael Kurz
370d4363baaSMichael Kurz debug("%s: words:%d data:", __func__, words);
371d4363baaSMichael Kurz
372d4363baaSMichael Kurz int i = 0;
373d4363baaSMichael Kurz while (words > i) {
374d4363baaSMichael Kurz writeb(dout[i], &priv->regs->dr);
375d4363baaSMichael Kurz debug("%02x ", dout[i]);
376d4363baaSMichael Kurz i++;
377d4363baaSMichael Kurz }
378d4363baaSMichael Kurz debug("\n");
379d4363baaSMichael Kurz
380d4363baaSMichael Kurz _stm32_qspi_wait_for_complete(priv);
381d4363baaSMichael Kurz } else {
382d4363baaSMichael Kurz _stm32_qspi_wait_for_not_busy(priv);
383d4363baaSMichael Kurz }
384d4363baaSMichael Kurz }
385d4363baaSMichael Kurz } else if (din) {
386d4363baaSMichael Kurz u32 ccr_reg = _stm32_qspi_gen_ccr(priv);
387d4363baaSMichael Kurz ccr_reg |= STM32_QSPI_CCR_IND_READ
388d4363baaSMichael Kurz << STM32_QSPI_CCR_FMODE_SHIFT;
389d4363baaSMichael Kurz
390d4363baaSMichael Kurz _stm32_qspi_wait_for_not_busy(priv);
391d4363baaSMichael Kurz
392d4363baaSMichael Kurz _stm32_qspi_set_xfer_length(priv, words);
393d4363baaSMichael Kurz
394d4363baaSMichael Kurz _stm32_qspi_start_xfer(priv, ccr_reg);
395d4363baaSMichael Kurz
396d4363baaSMichael Kurz debug("%s: read: ccr:0x%08x adr:0x%08x len:%d\n", __func__,
397d4363baaSMichael Kurz priv->regs->ccr, priv->regs->ar, priv->regs->dlr);
398d4363baaSMichael Kurz
399d4363baaSMichael Kurz debug("%s: data:", __func__);
400d4363baaSMichael Kurz
401d4363baaSMichael Kurz int i = 0;
402d4363baaSMichael Kurz while (words > i) {
403d4363baaSMichael Kurz din[i] = readb(&priv->regs->dr);
404d4363baaSMichael Kurz debug("%02x ", din[i]);
405d4363baaSMichael Kurz i++;
406d4363baaSMichael Kurz }
407d4363baaSMichael Kurz debug("\n");
408d4363baaSMichael Kurz }
409d4363baaSMichael Kurz
410d4363baaSMichael Kurz return 0;
411d4363baaSMichael Kurz }
412d4363baaSMichael Kurz
stm32_qspi_ofdata_to_platdata(struct udevice * bus)413d4363baaSMichael Kurz static int stm32_qspi_ofdata_to_platdata(struct udevice *bus)
414d4363baaSMichael Kurz {
415d4363baaSMichael Kurz struct fdt_resource res_regs, res_mem;
416d4363baaSMichael Kurz struct stm32_qspi_platdata *plat = bus->platdata;
417d4363baaSMichael Kurz const void *blob = gd->fdt_blob;
418e160f7d4SSimon Glass int node = dev_of_offset(bus);
419d4363baaSMichael Kurz int ret;
420d4363baaSMichael Kurz
421d4363baaSMichael Kurz ret = fdt_get_named_resource(blob, node, "reg", "reg-names",
422d4363baaSMichael Kurz "QuadSPI", &res_regs);
423d4363baaSMichael Kurz if (ret) {
424d4363baaSMichael Kurz debug("Error: can't get regs base addresses(ret = %d)!\n", ret);
425d4363baaSMichael Kurz return -ENOMEM;
426d4363baaSMichael Kurz }
427d4363baaSMichael Kurz ret = fdt_get_named_resource(blob, node, "reg", "reg-names",
428d4363baaSMichael Kurz "QuadSPI-memory", &res_mem);
429d4363baaSMichael Kurz if (ret) {
430d4363baaSMichael Kurz debug("Error: can't get mmap base address(ret = %d)!\n", ret);
431d4363baaSMichael Kurz return -ENOMEM;
432d4363baaSMichael Kurz }
433d4363baaSMichael Kurz
434d4363baaSMichael Kurz plat->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency",
435d4363baaSMichael Kurz STM32_QSPI_DEFAULT_SCK_FREQ);
436d4363baaSMichael Kurz
437d4363baaSMichael Kurz plat->base = res_regs.start;
438d4363baaSMichael Kurz plat->memory_map = res_mem.start;
439d4363baaSMichael Kurz
440d4363baaSMichael Kurz debug("%s: regs=<0x%x> mapped=<0x%x>, max-frequency=%d\n",
441d4363baaSMichael Kurz __func__,
442d4363baaSMichael Kurz plat->base,
443d4363baaSMichael Kurz plat->memory_map,
444d4363baaSMichael Kurz plat->max_hz
445d4363baaSMichael Kurz );
446d4363baaSMichael Kurz
447d4363baaSMichael Kurz return 0;
448d4363baaSMichael Kurz }
449d4363baaSMichael Kurz
stm32_qspi_probe(struct udevice * bus)450d4363baaSMichael Kurz static int stm32_qspi_probe(struct udevice *bus)
451d4363baaSMichael Kurz {
452d4363baaSMichael Kurz struct stm32_qspi_platdata *plat = dev_get_platdata(bus);
453d4363baaSMichael Kurz struct stm32_qspi_priv *priv = dev_get_priv(bus);
454d4363baaSMichael Kurz struct dm_spi_bus *dm_spi_bus;
455d4363baaSMichael Kurz
456d4363baaSMichael Kurz dm_spi_bus = bus->uclass_priv;
457d4363baaSMichael Kurz
458d4363baaSMichael Kurz dm_spi_bus->max_hz = plat->max_hz;
459d4363baaSMichael Kurz
460d4363baaSMichael Kurz priv->regs = (struct stm32_qspi_regs *)(uintptr_t)plat->base;
461d4363baaSMichael Kurz
462d4363baaSMichael Kurz priv->max_hz = plat->max_hz;
463d4363baaSMichael Kurz
464890bafd7SVikas Manocha #ifdef CONFIG_CLK
465890bafd7SVikas Manocha int ret;
466890bafd7SVikas Manocha struct clk clk;
467890bafd7SVikas Manocha ret = clk_get_by_index(bus, 0, &clk);
468890bafd7SVikas Manocha if (ret < 0)
469890bafd7SVikas Manocha return ret;
470890bafd7SVikas Manocha
471890bafd7SVikas Manocha ret = clk_enable(&clk);
472890bafd7SVikas Manocha
473890bafd7SVikas Manocha if (ret) {
474890bafd7SVikas Manocha dev_err(bus, "failed to enable clock\n");
475890bafd7SVikas Manocha return ret;
476890bafd7SVikas Manocha }
477541cd6e5SPatrice Chotard
478541cd6e5SPatrice Chotard priv->clock_rate = clk_get_rate(&clk);
479541cd6e5SPatrice Chotard if (priv->clock_rate < 0) {
480541cd6e5SPatrice Chotard clk_disable(&clk);
481541cd6e5SPatrice Chotard return priv->clock_rate;
482541cd6e5SPatrice Chotard }
483541cd6e5SPatrice Chotard
484890bafd7SVikas Manocha #endif
485d4363baaSMichael Kurz
486d4363baaSMichael Kurz setbits_le32(&priv->regs->cr, STM32_QSPI_CR_SSHIFT);
487d4363baaSMichael Kurz
488d4363baaSMichael Kurz return 0;
489d4363baaSMichael Kurz }
490d4363baaSMichael Kurz
stm32_qspi_remove(struct udevice * bus)491d4363baaSMichael Kurz static int stm32_qspi_remove(struct udevice *bus)
492d4363baaSMichael Kurz {
493d4363baaSMichael Kurz return 0;
494d4363baaSMichael Kurz }
495d4363baaSMichael Kurz
stm32_qspi_claim_bus(struct udevice * dev)496d4363baaSMichael Kurz static int stm32_qspi_claim_bus(struct udevice *dev)
497d4363baaSMichael Kurz {
498d4363baaSMichael Kurz struct stm32_qspi_priv *priv;
499d4363baaSMichael Kurz struct udevice *bus;
500d4363baaSMichael Kurz struct spi_flash *flash;
501d4363baaSMichael Kurz
502d4363baaSMichael Kurz bus = dev->parent;
503d4363baaSMichael Kurz priv = dev_get_priv(bus);
504d4363baaSMichael Kurz flash = dev_get_uclass_priv(dev);
505d4363baaSMichael Kurz
506d4363baaSMichael Kurz _stm32_qspi_set_flash_size(priv, flash->size);
507d4363baaSMichael Kurz
508d4363baaSMichael Kurz _stm32_qspi_enable(priv);
509d4363baaSMichael Kurz
510d4363baaSMichael Kurz return 0;
511d4363baaSMichael Kurz }
512d4363baaSMichael Kurz
stm32_qspi_release_bus(struct udevice * dev)513d4363baaSMichael Kurz static int stm32_qspi_release_bus(struct udevice *dev)
514d4363baaSMichael Kurz {
515d4363baaSMichael Kurz struct stm32_qspi_priv *priv;
516d4363baaSMichael Kurz struct udevice *bus;
517d4363baaSMichael Kurz
518d4363baaSMichael Kurz bus = dev->parent;
519d4363baaSMichael Kurz priv = dev_get_priv(bus);
520d4363baaSMichael Kurz
521d4363baaSMichael Kurz _stm32_qspi_disable(priv);
522d4363baaSMichael Kurz
523d4363baaSMichael Kurz return 0;
524d4363baaSMichael Kurz }
525d4363baaSMichael Kurz
stm32_qspi_xfer(struct udevice * dev,unsigned int bitlen,const void * dout,void * din,unsigned long flags)526d4363baaSMichael Kurz static int stm32_qspi_xfer(struct udevice *dev, unsigned int bitlen,
527d4363baaSMichael Kurz const void *dout, void *din, unsigned long flags)
528d4363baaSMichael Kurz {
529d4363baaSMichael Kurz struct stm32_qspi_priv *priv;
530d4363baaSMichael Kurz struct udevice *bus;
531d4363baaSMichael Kurz struct spi_flash *flash;
532d4363baaSMichael Kurz
533d4363baaSMichael Kurz bus = dev->parent;
534d4363baaSMichael Kurz priv = dev_get_priv(bus);
535d4363baaSMichael Kurz flash = dev_get_uclass_priv(dev);
536d4363baaSMichael Kurz
537d4363baaSMichael Kurz return _stm32_qspi_xfer(priv, flash, bitlen, (const u8 *)dout,
538d4363baaSMichael Kurz (u8 *)din, flags);
539d4363baaSMichael Kurz }
540d4363baaSMichael Kurz
stm32_qspi_set_speed(struct udevice * bus,uint speed)541d4363baaSMichael Kurz static int stm32_qspi_set_speed(struct udevice *bus, uint speed)
542d4363baaSMichael Kurz {
543d4363baaSMichael Kurz struct stm32_qspi_platdata *plat = bus->platdata;
544d4363baaSMichael Kurz struct stm32_qspi_priv *priv = dev_get_priv(bus);
545d4363baaSMichael Kurz
546d4363baaSMichael Kurz if (speed > plat->max_hz)
547d4363baaSMichael Kurz speed = plat->max_hz;
548d4363baaSMichael Kurz
549541cd6e5SPatrice Chotard u32 qspi_clk = priv->clock_rate;
550d4363baaSMichael Kurz u32 prescaler = 255;
551d4363baaSMichael Kurz if (speed > 0) {
552d4363baaSMichael Kurz prescaler = DIV_ROUND_UP(qspi_clk, speed) - 1;
553d4363baaSMichael Kurz if (prescaler > 255)
554d4363baaSMichael Kurz prescaler = 255;
555d4363baaSMichael Kurz else if (prescaler < 0)
556d4363baaSMichael Kurz prescaler = 0;
557d4363baaSMichael Kurz }
558d4363baaSMichael Kurz
559d4363baaSMichael Kurz u32 csht = DIV_ROUND_UP((5 * qspi_clk) / (prescaler + 1), 100000000);
560d4363baaSMichael Kurz csht = (csht - 1) & STM32_QSPI_DCR_CSHT_MASK;
561d4363baaSMichael Kurz
562d4363baaSMichael Kurz _stm32_qspi_wait_for_not_busy(priv);
563d4363baaSMichael Kurz
564d4363baaSMichael Kurz clrsetbits_le32(&priv->regs->cr,
565d4363baaSMichael Kurz STM32_QSPI_CR_PRESCALER_MASK <<
566d4363baaSMichael Kurz STM32_QSPI_CR_PRESCALER_SHIFT,
567d4363baaSMichael Kurz prescaler << STM32_QSPI_CR_PRESCALER_SHIFT);
568d4363baaSMichael Kurz
569d4363baaSMichael Kurz
570d4363baaSMichael Kurz clrsetbits_le32(&priv->regs->dcr,
571d4363baaSMichael Kurz STM32_QSPI_DCR_CSHT_MASK << STM32_QSPI_DCR_CSHT_SHIFT,
572d4363baaSMichael Kurz csht << STM32_QSPI_DCR_CSHT_SHIFT);
573d4363baaSMichael Kurz
574d4363baaSMichael Kurz debug("%s: regs=%p, speed=%d\n", __func__, priv->regs,
575d4363baaSMichael Kurz (qspi_clk / (prescaler + 1)));
576d4363baaSMichael Kurz
577d4363baaSMichael Kurz return 0;
578d4363baaSMichael Kurz }
579d4363baaSMichael Kurz
stm32_qspi_set_mode(struct udevice * bus,uint mode)580d4363baaSMichael Kurz static int stm32_qspi_set_mode(struct udevice *bus, uint mode)
581d4363baaSMichael Kurz {
582d4363baaSMichael Kurz struct stm32_qspi_priv *priv = dev_get_priv(bus);
583d4363baaSMichael Kurz
584d4363baaSMichael Kurz _stm32_qspi_wait_for_not_busy(priv);
585d4363baaSMichael Kurz
586d4363baaSMichael Kurz if ((mode & SPI_CPHA) && (mode & SPI_CPOL))
587d4363baaSMichael Kurz setbits_le32(&priv->regs->dcr, STM32_QSPI_DCR_CKMODE);
588d4363baaSMichael Kurz else if (!(mode & SPI_CPHA) && !(mode & SPI_CPOL))
589d4363baaSMichael Kurz clrbits_le32(&priv->regs->dcr, STM32_QSPI_DCR_CKMODE);
590d4363baaSMichael Kurz else
591d4363baaSMichael Kurz return -ENODEV;
592d4363baaSMichael Kurz
593d4363baaSMichael Kurz if (mode & SPI_CS_HIGH)
594d4363baaSMichael Kurz return -ENODEV;
595d4363baaSMichael Kurz
596d4363baaSMichael Kurz if (mode & SPI_RX_QUAD)
597d4363baaSMichael Kurz priv->mode |= SPI_RX_QUAD;
598d4363baaSMichael Kurz else if (mode & SPI_RX_DUAL)
599d4363baaSMichael Kurz priv->mode |= SPI_RX_DUAL;
600d4363baaSMichael Kurz else
601d4363baaSMichael Kurz priv->mode &= ~(SPI_RX_QUAD | SPI_RX_DUAL);
602d4363baaSMichael Kurz
603d4363baaSMichael Kurz if (mode & SPI_TX_QUAD)
604d4363baaSMichael Kurz priv->mode |= SPI_TX_QUAD;
605d4363baaSMichael Kurz else if (mode & SPI_TX_DUAL)
606d4363baaSMichael Kurz priv->mode |= SPI_TX_DUAL;
607d4363baaSMichael Kurz else
608d4363baaSMichael Kurz priv->mode &= ~(SPI_TX_QUAD | SPI_TX_DUAL);
609d4363baaSMichael Kurz
610d4363baaSMichael Kurz debug("%s: regs=%p, mode=%d rx: ", __func__, priv->regs, mode);
611d4363baaSMichael Kurz
612d4363baaSMichael Kurz if (mode & SPI_RX_QUAD)
613d4363baaSMichael Kurz debug("quad, tx: ");
614d4363baaSMichael Kurz else if (mode & SPI_RX_DUAL)
615d4363baaSMichael Kurz debug("dual, tx: ");
616d4363baaSMichael Kurz else
617d4363baaSMichael Kurz debug("single, tx: ");
618d4363baaSMichael Kurz
619d4363baaSMichael Kurz if (mode & SPI_TX_QUAD)
620d4363baaSMichael Kurz debug("quad\n");
621d4363baaSMichael Kurz else if (mode & SPI_TX_DUAL)
622d4363baaSMichael Kurz debug("dual\n");
623d4363baaSMichael Kurz else
624d4363baaSMichael Kurz debug("single\n");
625d4363baaSMichael Kurz
626d4363baaSMichael Kurz return 0;
627d4363baaSMichael Kurz }
628d4363baaSMichael Kurz
629d4363baaSMichael Kurz static const struct dm_spi_ops stm32_qspi_ops = {
630d4363baaSMichael Kurz .claim_bus = stm32_qspi_claim_bus,
631d4363baaSMichael Kurz .release_bus = stm32_qspi_release_bus,
632d4363baaSMichael Kurz .xfer = stm32_qspi_xfer,
633d4363baaSMichael Kurz .set_speed = stm32_qspi_set_speed,
634d4363baaSMichael Kurz .set_mode = stm32_qspi_set_mode,
635d4363baaSMichael Kurz };
636d4363baaSMichael Kurz
637d4363baaSMichael Kurz static const struct udevice_id stm32_qspi_ids[] = {
638d4363baaSMichael Kurz { .compatible = "st,stm32-qspi" },
639d4363baaSMichael Kurz { }
640d4363baaSMichael Kurz };
641d4363baaSMichael Kurz
642d4363baaSMichael Kurz U_BOOT_DRIVER(stm32_qspi) = {
643d4363baaSMichael Kurz .name = "stm32_qspi",
644d4363baaSMichael Kurz .id = UCLASS_SPI,
645d4363baaSMichael Kurz .of_match = stm32_qspi_ids,
646d4363baaSMichael Kurz .ops = &stm32_qspi_ops,
647d4363baaSMichael Kurz .ofdata_to_platdata = stm32_qspi_ofdata_to_platdata,
648d4363baaSMichael Kurz .platdata_auto_alloc_size = sizeof(struct stm32_qspi_platdata),
649d4363baaSMichael Kurz .priv_auto_alloc_size = sizeof(struct stm32_qspi_priv),
650d4363baaSMichael Kurz .probe = stm32_qspi_probe,
651d4363baaSMichael Kurz .remove = stm32_qspi_remove,
652d4363baaSMichael Kurz };
653