1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) STMicroelectronics 2020 |
4 | */ |
5 | |
6 | #include <linux/bitfield.h> |
7 | #include <linux/clk.h> |
8 | #include <linux/mfd/syscon.h> |
9 | #include <linux/module.h> |
10 | #include <linux/of.h> |
11 | #include <linux/of_platform.h> |
12 | #include <linux/pinctrl/consumer.h> |
13 | #include <linux/platform_device.h> |
14 | #include <linux/regmap.h> |
15 | #include <linux/reset.h> |
16 | |
17 | /* FMC2 Controller Registers */ |
18 | #define FMC2_BCR1 0x0 |
19 | #define FMC2_BTR1 0x4 |
20 | #define FMC2_BCR(x) ((x) * 0x8 + FMC2_BCR1) |
21 | #define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1) |
22 | #define FMC2_PCSCNTR 0x20 |
23 | #define FMC2_BWTR1 0x104 |
24 | #define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1) |
25 | |
26 | /* Register: FMC2_BCR1 */ |
27 | #define FMC2_BCR1_CCLKEN BIT(20) |
28 | #define FMC2_BCR1_FMC2EN BIT(31) |
29 | |
30 | /* Register: FMC2_BCRx */ |
31 | #define FMC2_BCR_MBKEN BIT(0) |
32 | #define FMC2_BCR_MUXEN BIT(1) |
33 | #define FMC2_BCR_MTYP GENMASK(3, 2) |
34 | #define FMC2_BCR_MWID GENMASK(5, 4) |
35 | #define FMC2_BCR_FACCEN BIT(6) |
36 | #define FMC2_BCR_BURSTEN BIT(8) |
37 | #define FMC2_BCR_WAITPOL BIT(9) |
38 | #define FMC2_BCR_WAITCFG BIT(11) |
39 | #define FMC2_BCR_WREN BIT(12) |
40 | #define FMC2_BCR_WAITEN BIT(13) |
41 | #define FMC2_BCR_EXTMOD BIT(14) |
42 | #define FMC2_BCR_ASYNCWAIT BIT(15) |
43 | #define FMC2_BCR_CPSIZE GENMASK(18, 16) |
44 | #define FMC2_BCR_CBURSTRW BIT(19) |
45 | #define FMC2_BCR_NBLSET GENMASK(23, 22) |
46 | |
47 | /* Register: FMC2_BTRx/FMC2_BWTRx */ |
48 | #define FMC2_BXTR_ADDSET GENMASK(3, 0) |
49 | #define FMC2_BXTR_ADDHLD GENMASK(7, 4) |
50 | #define FMC2_BXTR_DATAST GENMASK(15, 8) |
51 | #define FMC2_BXTR_BUSTURN GENMASK(19, 16) |
52 | #define FMC2_BTR_CLKDIV GENMASK(23, 20) |
53 | #define FMC2_BTR_DATLAT GENMASK(27, 24) |
54 | #define FMC2_BXTR_ACCMOD GENMASK(29, 28) |
55 | #define FMC2_BXTR_DATAHLD GENMASK(31, 30) |
56 | |
57 | /* Register: FMC2_PCSCNTR */ |
58 | #define FMC2_PCSCNTR_CSCOUNT GENMASK(15, 0) |
59 | #define FMC2_PCSCNTR_CNTBEN(x) BIT((x) + 16) |
60 | |
61 | #define FMC2_MAX_EBI_CE 4 |
62 | #define FMC2_MAX_BANKS 5 |
63 | |
64 | #define FMC2_BCR_CPSIZE_0 0x0 |
65 | #define FMC2_BCR_CPSIZE_128 0x1 |
66 | #define FMC2_BCR_CPSIZE_256 0x2 |
67 | #define FMC2_BCR_CPSIZE_512 0x3 |
68 | #define FMC2_BCR_CPSIZE_1024 0x4 |
69 | |
70 | #define FMC2_BCR_MWID_8 0x0 |
71 | #define FMC2_BCR_MWID_16 0x1 |
72 | |
73 | #define FMC2_BCR_MTYP_SRAM 0x0 |
74 | #define FMC2_BCR_MTYP_PSRAM 0x1 |
75 | #define FMC2_BCR_MTYP_NOR 0x2 |
76 | |
77 | #define FMC2_BXTR_EXTMOD_A 0x0 |
78 | #define FMC2_BXTR_EXTMOD_B 0x1 |
79 | #define FMC2_BXTR_EXTMOD_C 0x2 |
80 | #define FMC2_BXTR_EXTMOD_D 0x3 |
81 | |
82 | #define FMC2_BCR_NBLSET_MAX 0x3 |
83 | #define FMC2_BXTR_ADDSET_MAX 0xf |
84 | #define FMC2_BXTR_ADDHLD_MAX 0xf |
85 | #define FMC2_BXTR_DATAST_MAX 0xff |
86 | #define FMC2_BXTR_BUSTURN_MAX 0xf |
87 | #define FMC2_BXTR_DATAHLD_MAX 0x3 |
88 | #define FMC2_BTR_CLKDIV_MAX 0xf |
89 | #define FMC2_BTR_DATLAT_MAX 0xf |
90 | #define FMC2_PCSCNTR_CSCOUNT_MAX 0xff |
91 | |
92 | enum stm32_fmc2_ebi_bank { |
93 | FMC2_EBI1 = 0, |
94 | FMC2_EBI2, |
95 | FMC2_EBI3, |
96 | FMC2_EBI4, |
97 | FMC2_NAND |
98 | }; |
99 | |
100 | enum stm32_fmc2_ebi_register_type { |
101 | FMC2_REG_BCR = 1, |
102 | FMC2_REG_BTR, |
103 | FMC2_REG_BWTR, |
104 | FMC2_REG_PCSCNTR |
105 | }; |
106 | |
107 | enum stm32_fmc2_ebi_transaction_type { |
108 | FMC2_ASYNC_MODE_1_SRAM = 0, |
109 | FMC2_ASYNC_MODE_1_PSRAM, |
110 | FMC2_ASYNC_MODE_A_SRAM, |
111 | FMC2_ASYNC_MODE_A_PSRAM, |
112 | FMC2_ASYNC_MODE_2_NOR, |
113 | FMC2_ASYNC_MODE_B_NOR, |
114 | FMC2_ASYNC_MODE_C_NOR, |
115 | FMC2_ASYNC_MODE_D_NOR, |
116 | FMC2_SYNC_READ_SYNC_WRITE_PSRAM, |
117 | FMC2_SYNC_READ_ASYNC_WRITE_PSRAM, |
118 | FMC2_SYNC_READ_SYNC_WRITE_NOR, |
119 | FMC2_SYNC_READ_ASYNC_WRITE_NOR |
120 | }; |
121 | |
122 | enum stm32_fmc2_ebi_buswidth { |
123 | FMC2_BUSWIDTH_8 = 8, |
124 | FMC2_BUSWIDTH_16 = 16 |
125 | }; |
126 | |
127 | enum stm32_fmc2_ebi_cpsize { |
128 | FMC2_CPSIZE_0 = 0, |
129 | FMC2_CPSIZE_128 = 128, |
130 | FMC2_CPSIZE_256 = 256, |
131 | FMC2_CPSIZE_512 = 512, |
132 | FMC2_CPSIZE_1024 = 1024 |
133 | }; |
134 | |
135 | struct stm32_fmc2_ebi { |
136 | struct device *dev; |
137 | struct clk *clk; |
138 | struct regmap *regmap; |
139 | u8 bank_assigned; |
140 | |
141 | u32 bcr[FMC2_MAX_EBI_CE]; |
142 | u32 btr[FMC2_MAX_EBI_CE]; |
143 | u32 bwtr[FMC2_MAX_EBI_CE]; |
144 | u32 pcscntr; |
145 | }; |
146 | |
147 | /* |
148 | * struct stm32_fmc2_prop - STM32 FMC2 EBI property |
149 | * @name: the device tree binding name of the property |
150 | * @bprop: indicate that it is a boolean property |
151 | * @mprop: indicate that it is a mandatory property |
152 | * @reg_type: the register that have to be modified |
153 | * @reg_mask: the bit that have to be modified in the selected register |
154 | * in case of it is a boolean property |
155 | * @reset_val: the default value that have to be set in case the property |
156 | * has not been defined in the device tree |
157 | * @check: this callback ckecks that the property is compliant with the |
158 | * transaction type selected |
159 | * @calculate: this callback is called to calculate for exemple a timing |
160 | * set in nanoseconds in the device tree in clock cycles or in |
161 | * clock period |
162 | * @set: this callback applies the values in the registers |
163 | */ |
164 | struct stm32_fmc2_prop { |
165 | const char *name; |
166 | bool bprop; |
167 | bool mprop; |
168 | int reg_type; |
169 | u32 reg_mask; |
170 | u32 reset_val; |
171 | int (*check)(struct stm32_fmc2_ebi *ebi, |
172 | const struct stm32_fmc2_prop *prop, int cs); |
173 | u32 (*calculate)(struct stm32_fmc2_ebi *ebi, int cs, u32 setup); |
174 | int (*set)(struct stm32_fmc2_ebi *ebi, |
175 | const struct stm32_fmc2_prop *prop, |
176 | int cs, u32 setup); |
177 | }; |
178 | |
179 | static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi, |
180 | const struct stm32_fmc2_prop *prop, |
181 | int cs) |
182 | { |
183 | u32 bcr; |
184 | |
185 | regmap_read(map: ebi->regmap, FMC2_BCR(cs), val: &bcr); |
186 | |
187 | if (bcr & FMC2_BCR_MTYP) |
188 | return 0; |
189 | |
190 | return -EINVAL; |
191 | } |
192 | |
193 | static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi, |
194 | const struct stm32_fmc2_prop *prop, |
195 | int cs) |
196 | { |
197 | u32 bcr, val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); |
198 | |
199 | regmap_read(map: ebi->regmap, FMC2_BCR(cs), val: &bcr); |
200 | |
201 | if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN) |
202 | return 0; |
203 | |
204 | return -EINVAL; |
205 | } |
206 | |
207 | static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi, |
208 | const struct stm32_fmc2_prop *prop, |
209 | int cs) |
210 | { |
211 | u32 bcr; |
212 | |
213 | regmap_read(map: ebi->regmap, FMC2_BCR(cs), val: &bcr); |
214 | |
215 | if (bcr & FMC2_BCR_BURSTEN) |
216 | return 0; |
217 | |
218 | return -EINVAL; |
219 | } |
220 | |
221 | static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi, |
222 | const struct stm32_fmc2_prop *prop, |
223 | int cs) |
224 | { |
225 | u32 bcr; |
226 | |
227 | regmap_read(map: ebi->regmap, FMC2_BCR(cs), val: &bcr); |
228 | |
229 | if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) |
230 | return 0; |
231 | |
232 | return -EINVAL; |
233 | } |
234 | |
235 | static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi, |
236 | const struct stm32_fmc2_prop *prop, |
237 | int cs) |
238 | { |
239 | u32 bcr, val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM); |
240 | |
241 | regmap_read(map: ebi->regmap, FMC2_BCR(cs), val: &bcr); |
242 | |
243 | if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN) |
244 | return 0; |
245 | |
246 | return -EINVAL; |
247 | } |
248 | |
249 | static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi, |
250 | const struct stm32_fmc2_prop *prop, |
251 | int cs) |
252 | { |
253 | u32 bcr, bxtr, val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D); |
254 | |
255 | regmap_read(map: ebi->regmap, FMC2_BCR(cs), val: &bcr); |
256 | if (prop->reg_type == FMC2_REG_BWTR) |
257 | regmap_read(map: ebi->regmap, FMC2_BWTR(cs), val: &bxtr); |
258 | else |
259 | regmap_read(map: ebi->regmap, FMC2_BTR(cs), val: &bxtr); |
260 | |
261 | if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) && |
262 | ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN)) |
263 | return 0; |
264 | |
265 | return -EINVAL; |
266 | } |
267 | |
268 | static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi, |
269 | const struct stm32_fmc2_prop *prop, |
270 | int cs) |
271 | { |
272 | u32 bcr, bcr1; |
273 | |
274 | regmap_read(map: ebi->regmap, FMC2_BCR(cs), val: &bcr); |
275 | if (cs) |
276 | regmap_read(map: ebi->regmap, FMC2_BCR1, val: &bcr1); |
277 | else |
278 | bcr1 = bcr; |
279 | |
280 | if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN))) |
281 | return 0; |
282 | |
283 | return -EINVAL; |
284 | } |
285 | |
286 | static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2_ebi *ebi, |
287 | const struct stm32_fmc2_prop *prop, |
288 | int cs) |
289 | { |
290 | if (cs) |
291 | return -EINVAL; |
292 | |
293 | return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs); |
294 | } |
295 | |
296 | static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi, |
297 | int cs, u32 setup) |
298 | { |
299 | unsigned long hclk = clk_get_rate(clk: ebi->clk); |
300 | unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000); |
301 | |
302 | return DIV_ROUND_UP(setup * 1000, hclkp); |
303 | } |
304 | |
305 | static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi, |
306 | int cs, u32 setup) |
307 | { |
308 | u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup); |
309 | u32 bcr, btr, clk_period; |
310 | |
311 | regmap_read(map: ebi->regmap, FMC2_BCR1, val: &bcr); |
312 | if (bcr & FMC2_BCR1_CCLKEN || !cs) |
313 | regmap_read(map: ebi->regmap, FMC2_BTR1, val: &btr); |
314 | else |
315 | regmap_read(map: ebi->regmap, FMC2_BTR(cs), val: &btr); |
316 | |
317 | clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1; |
318 | |
319 | return DIV_ROUND_UP(nb_clk_cycles, clk_period); |
320 | } |
321 | |
322 | static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg) |
323 | { |
324 | switch (reg_type) { |
325 | case FMC2_REG_BCR: |
326 | *reg = FMC2_BCR(cs); |
327 | break; |
328 | case FMC2_REG_BTR: |
329 | *reg = FMC2_BTR(cs); |
330 | break; |
331 | case FMC2_REG_BWTR: |
332 | *reg = FMC2_BWTR(cs); |
333 | break; |
334 | case FMC2_REG_PCSCNTR: |
335 | *reg = FMC2_PCSCNTR; |
336 | break; |
337 | default: |
338 | return -EINVAL; |
339 | } |
340 | |
341 | return 0; |
342 | } |
343 | |
344 | static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2_ebi *ebi, |
345 | const struct stm32_fmc2_prop *prop, |
346 | int cs, u32 setup) |
347 | { |
348 | u32 reg; |
349 | int ret; |
350 | |
351 | ret = stm32_fmc2_ebi_get_reg(reg_type: prop->reg_type, cs, reg: ®); |
352 | if (ret) |
353 | return ret; |
354 | |
355 | regmap_update_bits(map: ebi->regmap, reg, mask: prop->reg_mask, |
356 | val: setup ? prop->reg_mask : 0); |
357 | |
358 | return 0; |
359 | } |
360 | |
361 | static int stm32_fmc2_ebi_set_trans_type(struct stm32_fmc2_ebi *ebi, |
362 | const struct stm32_fmc2_prop *prop, |
363 | int cs, u32 setup) |
364 | { |
365 | u32 bcr_mask, bcr = FMC2_BCR_WREN; |
366 | u32 btr_mask, btr = 0; |
367 | u32 bwtr_mask, bwtr = 0; |
368 | |
369 | bwtr_mask = FMC2_BXTR_ACCMOD; |
370 | btr_mask = FMC2_BXTR_ACCMOD; |
371 | bcr_mask = FMC2_BCR_MUXEN | FMC2_BCR_MTYP | FMC2_BCR_FACCEN | |
372 | FMC2_BCR_WREN | FMC2_BCR_WAITEN | FMC2_BCR_BURSTEN | |
373 | FMC2_BCR_EXTMOD | FMC2_BCR_CBURSTRW; |
374 | |
375 | switch (setup) { |
376 | case FMC2_ASYNC_MODE_1_SRAM: |
377 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM); |
378 | /* |
379 | * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0, |
380 | * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0 |
381 | */ |
382 | break; |
383 | case FMC2_ASYNC_MODE_1_PSRAM: |
384 | /* |
385 | * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0, |
386 | * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0 |
387 | */ |
388 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM); |
389 | break; |
390 | case FMC2_ASYNC_MODE_A_SRAM: |
391 | /* |
392 | * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0, |
393 | * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0 |
394 | */ |
395 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM); |
396 | bcr |= FMC2_BCR_EXTMOD; |
397 | btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A); |
398 | bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A); |
399 | break; |
400 | case FMC2_ASYNC_MODE_A_PSRAM: |
401 | /* |
402 | * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0, |
403 | * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0 |
404 | */ |
405 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM); |
406 | bcr |= FMC2_BCR_EXTMOD; |
407 | btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A); |
408 | bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A); |
409 | break; |
410 | case FMC2_ASYNC_MODE_2_NOR: |
411 | /* |
412 | * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0, |
413 | * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0 |
414 | */ |
415 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); |
416 | bcr |= FMC2_BCR_FACCEN; |
417 | break; |
418 | case FMC2_ASYNC_MODE_B_NOR: |
419 | /* |
420 | * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0, |
421 | * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 1 |
422 | */ |
423 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); |
424 | bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD; |
425 | btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B); |
426 | bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B); |
427 | break; |
428 | case FMC2_ASYNC_MODE_C_NOR: |
429 | /* |
430 | * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0, |
431 | * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 2 |
432 | */ |
433 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); |
434 | bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD; |
435 | btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C); |
436 | bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C); |
437 | break; |
438 | case FMC2_ASYNC_MODE_D_NOR: |
439 | /* |
440 | * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0, |
441 | * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 3 |
442 | */ |
443 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); |
444 | bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD; |
445 | btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D); |
446 | bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D); |
447 | break; |
448 | case FMC2_SYNC_READ_SYNC_WRITE_PSRAM: |
449 | /* |
450 | * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0, |
451 | * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0 |
452 | */ |
453 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM); |
454 | bcr |= FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW; |
455 | break; |
456 | case FMC2_SYNC_READ_ASYNC_WRITE_PSRAM: |
457 | /* |
458 | * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0, |
459 | * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0 |
460 | */ |
461 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM); |
462 | bcr |= FMC2_BCR_BURSTEN; |
463 | break; |
464 | case FMC2_SYNC_READ_SYNC_WRITE_NOR: |
465 | /* |
466 | * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0, |
467 | * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0 |
468 | */ |
469 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); |
470 | bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW; |
471 | break; |
472 | case FMC2_SYNC_READ_ASYNC_WRITE_NOR: |
473 | /* |
474 | * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0, |
475 | * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0 |
476 | */ |
477 | bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR); |
478 | bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN; |
479 | break; |
480 | default: |
481 | /* Type of transaction not supported */ |
482 | return -EINVAL; |
483 | } |
484 | |
485 | if (bcr & FMC2_BCR_EXTMOD) |
486 | regmap_update_bits(map: ebi->regmap, FMC2_BWTR(cs), |
487 | mask: bwtr_mask, val: bwtr); |
488 | regmap_update_bits(map: ebi->regmap, FMC2_BTR(cs), mask: btr_mask, val: btr); |
489 | regmap_update_bits(map: ebi->regmap, FMC2_BCR(cs), mask: bcr_mask, val: bcr); |
490 | |
491 | return 0; |
492 | } |
493 | |
494 | static int stm32_fmc2_ebi_set_buswidth(struct stm32_fmc2_ebi *ebi, |
495 | const struct stm32_fmc2_prop *prop, |
496 | int cs, u32 setup) |
497 | { |
498 | u32 val; |
499 | |
500 | switch (setup) { |
501 | case FMC2_BUSWIDTH_8: |
502 | val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_8); |
503 | break; |
504 | case FMC2_BUSWIDTH_16: |
505 | val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_16); |
506 | break; |
507 | default: |
508 | /* Buswidth not supported */ |
509 | return -EINVAL; |
510 | } |
511 | |
512 | regmap_update_bits(map: ebi->regmap, FMC2_BCR(cs), FMC2_BCR_MWID, val); |
513 | |
514 | return 0; |
515 | } |
516 | |
517 | static int stm32_fmc2_ebi_set_cpsize(struct stm32_fmc2_ebi *ebi, |
518 | const struct stm32_fmc2_prop *prop, |
519 | int cs, u32 setup) |
520 | { |
521 | u32 val; |
522 | |
523 | switch (setup) { |
524 | case FMC2_CPSIZE_0: |
525 | val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_0); |
526 | break; |
527 | case FMC2_CPSIZE_128: |
528 | val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_128); |
529 | break; |
530 | case FMC2_CPSIZE_256: |
531 | val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_256); |
532 | break; |
533 | case FMC2_CPSIZE_512: |
534 | val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_512); |
535 | break; |
536 | case FMC2_CPSIZE_1024: |
537 | val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_1024); |
538 | break; |
539 | default: |
540 | /* Cpsize not supported */ |
541 | return -EINVAL; |
542 | } |
543 | |
544 | regmap_update_bits(map: ebi->regmap, FMC2_BCR(cs), FMC2_BCR_CPSIZE, val); |
545 | |
546 | return 0; |
547 | } |
548 | |
549 | static int stm32_fmc2_ebi_set_bl_setup(struct stm32_fmc2_ebi *ebi, |
550 | const struct stm32_fmc2_prop *prop, |
551 | int cs, u32 setup) |
552 | { |
553 | u32 val; |
554 | |
555 | val = min_t(u32, setup, FMC2_BCR_NBLSET_MAX); |
556 | val = FIELD_PREP(FMC2_BCR_NBLSET, val); |
557 | regmap_update_bits(map: ebi->regmap, FMC2_BCR(cs), FMC2_BCR_NBLSET, val); |
558 | |
559 | return 0; |
560 | } |
561 | |
562 | static int stm32_fmc2_ebi_set_address_setup(struct stm32_fmc2_ebi *ebi, |
563 | const struct stm32_fmc2_prop *prop, |
564 | int cs, u32 setup) |
565 | { |
566 | u32 bcr, bxtr, reg; |
567 | u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D); |
568 | int ret; |
569 | |
570 | ret = stm32_fmc2_ebi_get_reg(reg_type: prop->reg_type, cs, reg: ®); |
571 | if (ret) |
572 | return ret; |
573 | |
574 | regmap_read(map: ebi->regmap, FMC2_BCR(cs), val: &bcr); |
575 | if (prop->reg_type == FMC2_REG_BWTR) |
576 | regmap_read(map: ebi->regmap, FMC2_BWTR(cs), val: &bxtr); |
577 | else |
578 | regmap_read(map: ebi->regmap, FMC2_BTR(cs), val: &bxtr); |
579 | |
580 | if ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN) |
581 | val = clamp_val(setup, 1, FMC2_BXTR_ADDSET_MAX); |
582 | else |
583 | val = min_t(u32, setup, FMC2_BXTR_ADDSET_MAX); |
584 | val = FIELD_PREP(FMC2_BXTR_ADDSET, val); |
585 | regmap_update_bits(map: ebi->regmap, reg, FMC2_BXTR_ADDSET, val); |
586 | |
587 | return 0; |
588 | } |
589 | |
590 | static int stm32_fmc2_ebi_set_address_hold(struct stm32_fmc2_ebi *ebi, |
591 | const struct stm32_fmc2_prop *prop, |
592 | int cs, u32 setup) |
593 | { |
594 | u32 val, reg; |
595 | int ret; |
596 | |
597 | ret = stm32_fmc2_ebi_get_reg(reg_type: prop->reg_type, cs, reg: ®); |
598 | if (ret) |
599 | return ret; |
600 | |
601 | val = clamp_val(setup, 1, FMC2_BXTR_ADDHLD_MAX); |
602 | val = FIELD_PREP(FMC2_BXTR_ADDHLD, val); |
603 | regmap_update_bits(map: ebi->regmap, reg, FMC2_BXTR_ADDHLD, val); |
604 | |
605 | return 0; |
606 | } |
607 | |
608 | static int stm32_fmc2_ebi_set_data_setup(struct stm32_fmc2_ebi *ebi, |
609 | const struct stm32_fmc2_prop *prop, |
610 | int cs, u32 setup) |
611 | { |
612 | u32 val, reg; |
613 | int ret; |
614 | |
615 | ret = stm32_fmc2_ebi_get_reg(reg_type: prop->reg_type, cs, reg: ®); |
616 | if (ret) |
617 | return ret; |
618 | |
619 | val = clamp_val(setup, 1, FMC2_BXTR_DATAST_MAX); |
620 | val = FIELD_PREP(FMC2_BXTR_DATAST, val); |
621 | regmap_update_bits(map: ebi->regmap, reg, FMC2_BXTR_DATAST, val); |
622 | |
623 | return 0; |
624 | } |
625 | |
626 | static int stm32_fmc2_ebi_set_bus_turnaround(struct stm32_fmc2_ebi *ebi, |
627 | const struct stm32_fmc2_prop *prop, |
628 | int cs, u32 setup) |
629 | { |
630 | u32 val, reg; |
631 | int ret; |
632 | |
633 | ret = stm32_fmc2_ebi_get_reg(reg_type: prop->reg_type, cs, reg: ®); |
634 | if (ret) |
635 | return ret; |
636 | |
637 | val = setup ? min_t(u32, setup - 1, FMC2_BXTR_BUSTURN_MAX) : 0; |
638 | val = FIELD_PREP(FMC2_BXTR_BUSTURN, val); |
639 | regmap_update_bits(map: ebi->regmap, reg, FMC2_BXTR_BUSTURN, val); |
640 | |
641 | return 0; |
642 | } |
643 | |
644 | static int stm32_fmc2_ebi_set_data_hold(struct stm32_fmc2_ebi *ebi, |
645 | const struct stm32_fmc2_prop *prop, |
646 | int cs, u32 setup) |
647 | { |
648 | u32 val, reg; |
649 | int ret; |
650 | |
651 | ret = stm32_fmc2_ebi_get_reg(reg_type: prop->reg_type, cs, reg: ®); |
652 | if (ret) |
653 | return ret; |
654 | |
655 | if (prop->reg_type == FMC2_REG_BWTR) |
656 | val = setup ? min_t(u32, setup - 1, FMC2_BXTR_DATAHLD_MAX) : 0; |
657 | else |
658 | val = min_t(u32, setup, FMC2_BXTR_DATAHLD_MAX); |
659 | val = FIELD_PREP(FMC2_BXTR_DATAHLD, val); |
660 | regmap_update_bits(map: ebi->regmap, reg, FMC2_BXTR_DATAHLD, val); |
661 | |
662 | return 0; |
663 | } |
664 | |
665 | static int stm32_fmc2_ebi_set_clk_period(struct stm32_fmc2_ebi *ebi, |
666 | const struct stm32_fmc2_prop *prop, |
667 | int cs, u32 setup) |
668 | { |
669 | u32 val; |
670 | |
671 | val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1; |
672 | val = FIELD_PREP(FMC2_BTR_CLKDIV, val); |
673 | regmap_update_bits(map: ebi->regmap, FMC2_BTR(cs), FMC2_BTR_CLKDIV, val); |
674 | |
675 | return 0; |
676 | } |
677 | |
678 | static int stm32_fmc2_ebi_set_data_latency(struct stm32_fmc2_ebi *ebi, |
679 | const struct stm32_fmc2_prop *prop, |
680 | int cs, u32 setup) |
681 | { |
682 | u32 val; |
683 | |
684 | val = setup > 1 ? min_t(u32, setup - 2, FMC2_BTR_DATLAT_MAX) : 0; |
685 | val = FIELD_PREP(FMC2_BTR_DATLAT, val); |
686 | regmap_update_bits(map: ebi->regmap, FMC2_BTR(cs), FMC2_BTR_DATLAT, val); |
687 | |
688 | return 0; |
689 | } |
690 | |
691 | static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi, |
692 | const struct stm32_fmc2_prop *prop, |
693 | int cs, u32 setup) |
694 | { |
695 | u32 old_val, new_val, pcscntr; |
696 | |
697 | if (setup < 1) |
698 | return 0; |
699 | |
700 | regmap_read(map: ebi->regmap, FMC2_PCSCNTR, val: &pcscntr); |
701 | |
702 | /* Enable counter for the bank */ |
703 | regmap_update_bits(map: ebi->regmap, FMC2_PCSCNTR, |
704 | FMC2_PCSCNTR_CNTBEN(cs), |
705 | FMC2_PCSCNTR_CNTBEN(cs)); |
706 | |
707 | new_val = min_t(u32, setup - 1, FMC2_PCSCNTR_CSCOUNT_MAX); |
708 | old_val = FIELD_GET(FMC2_PCSCNTR_CSCOUNT, pcscntr); |
709 | if (old_val && new_val > old_val) |
710 | /* Keep current counter value */ |
711 | return 0; |
712 | |
713 | new_val = FIELD_PREP(FMC2_PCSCNTR_CSCOUNT, new_val); |
714 | regmap_update_bits(map: ebi->regmap, FMC2_PCSCNTR, |
715 | FMC2_PCSCNTR_CSCOUNT, val: new_val); |
716 | |
717 | return 0; |
718 | } |
719 | |
720 | static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = { |
721 | /* st,fmc2-ebi-cs-trans-type must be the first property */ |
722 | { |
723 | .name = "st,fmc2-ebi-cs-transaction-type" , |
724 | .mprop = true, |
725 | .set = stm32_fmc2_ebi_set_trans_type, |
726 | }, |
727 | { |
728 | .name = "st,fmc2-ebi-cs-cclk-enable" , |
729 | .bprop = true, |
730 | .reg_type = FMC2_REG_BCR, |
731 | .reg_mask = FMC2_BCR1_CCLKEN, |
732 | .check = stm32_fmc2_ebi_check_cclk, |
733 | .set = stm32_fmc2_ebi_set_bit_field, |
734 | }, |
735 | { |
736 | .name = "st,fmc2-ebi-cs-mux-enable" , |
737 | .bprop = true, |
738 | .reg_type = FMC2_REG_BCR, |
739 | .reg_mask = FMC2_BCR_MUXEN, |
740 | .check = stm32_fmc2_ebi_check_mux, |
741 | .set = stm32_fmc2_ebi_set_bit_field, |
742 | }, |
743 | { |
744 | .name = "st,fmc2-ebi-cs-buswidth" , |
745 | .reset_val = FMC2_BUSWIDTH_16, |
746 | .set = stm32_fmc2_ebi_set_buswidth, |
747 | }, |
748 | { |
749 | .name = "st,fmc2-ebi-cs-waitpol-high" , |
750 | .bprop = true, |
751 | .reg_type = FMC2_REG_BCR, |
752 | .reg_mask = FMC2_BCR_WAITPOL, |
753 | .set = stm32_fmc2_ebi_set_bit_field, |
754 | }, |
755 | { |
756 | .name = "st,fmc2-ebi-cs-waitcfg-enable" , |
757 | .bprop = true, |
758 | .reg_type = FMC2_REG_BCR, |
759 | .reg_mask = FMC2_BCR_WAITCFG, |
760 | .check = stm32_fmc2_ebi_check_waitcfg, |
761 | .set = stm32_fmc2_ebi_set_bit_field, |
762 | }, |
763 | { |
764 | .name = "st,fmc2-ebi-cs-wait-enable" , |
765 | .bprop = true, |
766 | .reg_type = FMC2_REG_BCR, |
767 | .reg_mask = FMC2_BCR_WAITEN, |
768 | .check = stm32_fmc2_ebi_check_sync_trans, |
769 | .set = stm32_fmc2_ebi_set_bit_field, |
770 | }, |
771 | { |
772 | .name = "st,fmc2-ebi-cs-asyncwait-enable" , |
773 | .bprop = true, |
774 | .reg_type = FMC2_REG_BCR, |
775 | .reg_mask = FMC2_BCR_ASYNCWAIT, |
776 | .check = stm32_fmc2_ebi_check_async_trans, |
777 | .set = stm32_fmc2_ebi_set_bit_field, |
778 | }, |
779 | { |
780 | .name = "st,fmc2-ebi-cs-cpsize" , |
781 | .check = stm32_fmc2_ebi_check_cpsize, |
782 | .set = stm32_fmc2_ebi_set_cpsize, |
783 | }, |
784 | { |
785 | .name = "st,fmc2-ebi-cs-byte-lane-setup-ns" , |
786 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
787 | .set = stm32_fmc2_ebi_set_bl_setup, |
788 | }, |
789 | { |
790 | .name = "st,fmc2-ebi-cs-address-setup-ns" , |
791 | .reg_type = FMC2_REG_BTR, |
792 | .reset_val = FMC2_BXTR_ADDSET_MAX, |
793 | .check = stm32_fmc2_ebi_check_async_trans, |
794 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
795 | .set = stm32_fmc2_ebi_set_address_setup, |
796 | }, |
797 | { |
798 | .name = "st,fmc2-ebi-cs-address-hold-ns" , |
799 | .reg_type = FMC2_REG_BTR, |
800 | .reset_val = FMC2_BXTR_ADDHLD_MAX, |
801 | .check = stm32_fmc2_ebi_check_address_hold, |
802 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
803 | .set = stm32_fmc2_ebi_set_address_hold, |
804 | }, |
805 | { |
806 | .name = "st,fmc2-ebi-cs-data-setup-ns" , |
807 | .reg_type = FMC2_REG_BTR, |
808 | .reset_val = FMC2_BXTR_DATAST_MAX, |
809 | .check = stm32_fmc2_ebi_check_async_trans, |
810 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
811 | .set = stm32_fmc2_ebi_set_data_setup, |
812 | }, |
813 | { |
814 | .name = "st,fmc2-ebi-cs-bus-turnaround-ns" , |
815 | .reg_type = FMC2_REG_BTR, |
816 | .reset_val = FMC2_BXTR_BUSTURN_MAX + 1, |
817 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
818 | .set = stm32_fmc2_ebi_set_bus_turnaround, |
819 | }, |
820 | { |
821 | .name = "st,fmc2-ebi-cs-data-hold-ns" , |
822 | .reg_type = FMC2_REG_BTR, |
823 | .check = stm32_fmc2_ebi_check_async_trans, |
824 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
825 | .set = stm32_fmc2_ebi_set_data_hold, |
826 | }, |
827 | { |
828 | .name = "st,fmc2-ebi-cs-clk-period-ns" , |
829 | .reset_val = FMC2_BTR_CLKDIV_MAX + 1, |
830 | .check = stm32_fmc2_ebi_check_clk_period, |
831 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
832 | .set = stm32_fmc2_ebi_set_clk_period, |
833 | }, |
834 | { |
835 | .name = "st,fmc2-ebi-cs-data-latency-ns" , |
836 | .check = stm32_fmc2_ebi_check_sync_trans, |
837 | .calculate = stm32_fmc2_ebi_ns_to_clk_period, |
838 | .set = stm32_fmc2_ebi_set_data_latency, |
839 | }, |
840 | { |
841 | .name = "st,fmc2-ebi-cs-write-address-setup-ns" , |
842 | .reg_type = FMC2_REG_BWTR, |
843 | .reset_val = FMC2_BXTR_ADDSET_MAX, |
844 | .check = stm32_fmc2_ebi_check_async_trans, |
845 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
846 | .set = stm32_fmc2_ebi_set_address_setup, |
847 | }, |
848 | { |
849 | .name = "st,fmc2-ebi-cs-write-address-hold-ns" , |
850 | .reg_type = FMC2_REG_BWTR, |
851 | .reset_val = FMC2_BXTR_ADDHLD_MAX, |
852 | .check = stm32_fmc2_ebi_check_address_hold, |
853 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
854 | .set = stm32_fmc2_ebi_set_address_hold, |
855 | }, |
856 | { |
857 | .name = "st,fmc2-ebi-cs-write-data-setup-ns" , |
858 | .reg_type = FMC2_REG_BWTR, |
859 | .reset_val = FMC2_BXTR_DATAST_MAX, |
860 | .check = stm32_fmc2_ebi_check_async_trans, |
861 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
862 | .set = stm32_fmc2_ebi_set_data_setup, |
863 | }, |
864 | { |
865 | .name = "st,fmc2-ebi-cs-write-bus-turnaround-ns" , |
866 | .reg_type = FMC2_REG_BWTR, |
867 | .reset_val = FMC2_BXTR_BUSTURN_MAX + 1, |
868 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
869 | .set = stm32_fmc2_ebi_set_bus_turnaround, |
870 | }, |
871 | { |
872 | .name = "st,fmc2-ebi-cs-write-data-hold-ns" , |
873 | .reg_type = FMC2_REG_BWTR, |
874 | .check = stm32_fmc2_ebi_check_async_trans, |
875 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
876 | .set = stm32_fmc2_ebi_set_data_hold, |
877 | }, |
878 | { |
879 | .name = "st,fmc2-ebi-cs-max-low-pulse-ns" , |
880 | .calculate = stm32_fmc2_ebi_ns_to_clock_cycles, |
881 | .set = stm32_fmc2_ebi_set_max_low_pulse, |
882 | }, |
883 | }; |
884 | |
885 | static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi, |
886 | struct device_node *dev_node, |
887 | const struct stm32_fmc2_prop *prop, |
888 | int cs) |
889 | { |
890 | struct device *dev = ebi->dev; |
891 | u32 setup = 0; |
892 | |
893 | if (!prop->set) { |
894 | dev_err(dev, "property %s is not well defined\n" , prop->name); |
895 | return -EINVAL; |
896 | } |
897 | |
898 | if (prop->check && prop->check(ebi, prop, cs)) |
899 | /* Skeep this property */ |
900 | return 0; |
901 | |
902 | if (prop->bprop) { |
903 | bool bprop; |
904 | |
905 | bprop = of_property_read_bool(np: dev_node, propname: prop->name); |
906 | if (prop->mprop && !bprop) { |
907 | dev_err(dev, "mandatory property %s not defined in the device tree\n" , |
908 | prop->name); |
909 | return -EINVAL; |
910 | } |
911 | |
912 | if (bprop) |
913 | setup = 1; |
914 | } else { |
915 | u32 val; |
916 | int ret; |
917 | |
918 | ret = of_property_read_u32(np: dev_node, propname: prop->name, out_value: &val); |
919 | if (prop->mprop && ret) { |
920 | dev_err(dev, "mandatory property %s not defined in the device tree\n" , |
921 | prop->name); |
922 | return ret; |
923 | } |
924 | |
925 | if (ret) |
926 | setup = prop->reset_val; |
927 | else if (prop->calculate) |
928 | setup = prop->calculate(ebi, cs, val); |
929 | else |
930 | setup = val; |
931 | } |
932 | |
933 | return prop->set(ebi, prop, cs, setup); |
934 | } |
935 | |
936 | static void stm32_fmc2_ebi_enable_bank(struct stm32_fmc2_ebi *ebi, int cs) |
937 | { |
938 | regmap_update_bits(map: ebi->regmap, FMC2_BCR(cs), |
939 | FMC2_BCR_MBKEN, FMC2_BCR_MBKEN); |
940 | } |
941 | |
942 | static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs) |
943 | { |
944 | regmap_update_bits(map: ebi->regmap, FMC2_BCR(cs), FMC2_BCR_MBKEN, val: 0); |
945 | } |
946 | |
947 | static void stm32_fmc2_ebi_save_setup(struct stm32_fmc2_ebi *ebi) |
948 | { |
949 | unsigned int cs; |
950 | |
951 | for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) { |
952 | regmap_read(map: ebi->regmap, FMC2_BCR(cs), val: &ebi->bcr[cs]); |
953 | regmap_read(map: ebi->regmap, FMC2_BTR(cs), val: &ebi->btr[cs]); |
954 | regmap_read(map: ebi->regmap, FMC2_BWTR(cs), val: &ebi->bwtr[cs]); |
955 | } |
956 | |
957 | regmap_read(map: ebi->regmap, FMC2_PCSCNTR, val: &ebi->pcscntr); |
958 | } |
959 | |
960 | static void stm32_fmc2_ebi_set_setup(struct stm32_fmc2_ebi *ebi) |
961 | { |
962 | unsigned int cs; |
963 | |
964 | for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) { |
965 | regmap_write(map: ebi->regmap, FMC2_BCR(cs), val: ebi->bcr[cs]); |
966 | regmap_write(map: ebi->regmap, FMC2_BTR(cs), val: ebi->btr[cs]); |
967 | regmap_write(map: ebi->regmap, FMC2_BWTR(cs), val: ebi->bwtr[cs]); |
968 | } |
969 | |
970 | regmap_write(map: ebi->regmap, FMC2_PCSCNTR, val: ebi->pcscntr); |
971 | } |
972 | |
973 | static void stm32_fmc2_ebi_disable_banks(struct stm32_fmc2_ebi *ebi) |
974 | { |
975 | unsigned int cs; |
976 | |
977 | for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) { |
978 | if (!(ebi->bank_assigned & BIT(cs))) |
979 | continue; |
980 | |
981 | stm32_fmc2_ebi_disable_bank(ebi, cs); |
982 | } |
983 | } |
984 | |
985 | /* NWAIT signal can not be connected to EBI controller and NAND controller */ |
986 | static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi) |
987 | { |
988 | unsigned int cs; |
989 | u32 bcr; |
990 | |
991 | for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) { |
992 | if (!(ebi->bank_assigned & BIT(cs))) |
993 | continue; |
994 | |
995 | regmap_read(map: ebi->regmap, FMC2_BCR(cs), val: &bcr); |
996 | if ((bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT) && |
997 | ebi->bank_assigned & BIT(FMC2_NAND)) |
998 | return true; |
999 | } |
1000 | |
1001 | return false; |
1002 | } |
1003 | |
1004 | static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi) |
1005 | { |
1006 | regmap_update_bits(map: ebi->regmap, FMC2_BCR1, |
1007 | FMC2_BCR1_FMC2EN, FMC2_BCR1_FMC2EN); |
1008 | } |
1009 | |
1010 | static void stm32_fmc2_ebi_disable(struct stm32_fmc2_ebi *ebi) |
1011 | { |
1012 | regmap_update_bits(map: ebi->regmap, FMC2_BCR1, FMC2_BCR1_FMC2EN, val: 0); |
1013 | } |
1014 | |
1015 | static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi, |
1016 | struct device_node *dev_node, |
1017 | u32 cs) |
1018 | { |
1019 | unsigned int i; |
1020 | int ret; |
1021 | |
1022 | stm32_fmc2_ebi_disable_bank(ebi, cs); |
1023 | |
1024 | for (i = 0; i < ARRAY_SIZE(stm32_fmc2_child_props); i++) { |
1025 | const struct stm32_fmc2_prop *p = &stm32_fmc2_child_props[i]; |
1026 | |
1027 | ret = stm32_fmc2_ebi_parse_prop(ebi, dev_node, prop: p, cs); |
1028 | if (ret) { |
1029 | dev_err(ebi->dev, "property %s could not be set: %d\n" , |
1030 | p->name, ret); |
1031 | return ret; |
1032 | } |
1033 | } |
1034 | |
1035 | stm32_fmc2_ebi_enable_bank(ebi, cs); |
1036 | |
1037 | return 0; |
1038 | } |
1039 | |
1040 | static int stm32_fmc2_ebi_parse_dt(struct stm32_fmc2_ebi *ebi) |
1041 | { |
1042 | struct device *dev = ebi->dev; |
1043 | struct device_node *child; |
1044 | bool child_found = false; |
1045 | u32 bank; |
1046 | int ret; |
1047 | |
1048 | for_each_available_child_of_node(dev->of_node, child) { |
1049 | ret = of_property_read_u32(np: child, propname: "reg" , out_value: &bank); |
1050 | if (ret) { |
1051 | dev_err(dev, "could not retrieve reg property: %d\n" , |
1052 | ret); |
1053 | of_node_put(node: child); |
1054 | return ret; |
1055 | } |
1056 | |
1057 | if (bank >= FMC2_MAX_BANKS) { |
1058 | dev_err(dev, "invalid reg value: %d\n" , bank); |
1059 | of_node_put(node: child); |
1060 | return -EINVAL; |
1061 | } |
1062 | |
1063 | if (ebi->bank_assigned & BIT(bank)) { |
1064 | dev_err(dev, "bank already assigned: %d\n" , bank); |
1065 | of_node_put(node: child); |
1066 | return -EINVAL; |
1067 | } |
1068 | |
1069 | if (bank < FMC2_MAX_EBI_CE) { |
1070 | ret = stm32_fmc2_ebi_setup_cs(ebi, dev_node: child, cs: bank); |
1071 | if (ret) { |
1072 | dev_err(dev, "setup chip select %d failed: %d\n" , |
1073 | bank, ret); |
1074 | of_node_put(node: child); |
1075 | return ret; |
1076 | } |
1077 | } |
1078 | |
1079 | ebi->bank_assigned |= BIT(bank); |
1080 | child_found = true; |
1081 | } |
1082 | |
1083 | if (!child_found) { |
1084 | dev_warn(dev, "no subnodes found, disable the driver.\n" ); |
1085 | return -ENODEV; |
1086 | } |
1087 | |
1088 | if (stm32_fmc2_ebi_nwait_used_by_ctrls(ebi)) { |
1089 | dev_err(dev, "NWAIT signal connected to EBI and NAND controllers\n" ); |
1090 | return -EINVAL; |
1091 | } |
1092 | |
1093 | stm32_fmc2_ebi_enable(ebi); |
1094 | |
1095 | return of_platform_populate(root: dev->of_node, NULL, NULL, parent: dev); |
1096 | } |
1097 | |
1098 | static int stm32_fmc2_ebi_probe(struct platform_device *pdev) |
1099 | { |
1100 | struct device *dev = &pdev->dev; |
1101 | struct stm32_fmc2_ebi *ebi; |
1102 | struct reset_control *rstc; |
1103 | int ret; |
1104 | |
1105 | ebi = devm_kzalloc(dev: &pdev->dev, size: sizeof(*ebi), GFP_KERNEL); |
1106 | if (!ebi) |
1107 | return -ENOMEM; |
1108 | |
1109 | ebi->dev = dev; |
1110 | |
1111 | ebi->regmap = device_node_to_regmap(np: dev->of_node); |
1112 | if (IS_ERR(ptr: ebi->regmap)) |
1113 | return PTR_ERR(ptr: ebi->regmap); |
1114 | |
1115 | ebi->clk = devm_clk_get(dev, NULL); |
1116 | if (IS_ERR(ptr: ebi->clk)) |
1117 | return PTR_ERR(ptr: ebi->clk); |
1118 | |
1119 | rstc = devm_reset_control_get(dev, NULL); |
1120 | if (PTR_ERR(ptr: rstc) == -EPROBE_DEFER) |
1121 | return -EPROBE_DEFER; |
1122 | |
1123 | ret = clk_prepare_enable(clk: ebi->clk); |
1124 | if (ret) |
1125 | return ret; |
1126 | |
1127 | if (!IS_ERR(ptr: rstc)) { |
1128 | reset_control_assert(rstc); |
1129 | reset_control_deassert(rstc); |
1130 | } |
1131 | |
1132 | ret = stm32_fmc2_ebi_parse_dt(ebi); |
1133 | if (ret) |
1134 | goto err_release; |
1135 | |
1136 | stm32_fmc2_ebi_save_setup(ebi); |
1137 | platform_set_drvdata(pdev, data: ebi); |
1138 | |
1139 | return 0; |
1140 | |
1141 | err_release: |
1142 | stm32_fmc2_ebi_disable_banks(ebi); |
1143 | stm32_fmc2_ebi_disable(ebi); |
1144 | clk_disable_unprepare(clk: ebi->clk); |
1145 | |
1146 | return ret; |
1147 | } |
1148 | |
1149 | static int stm32_fmc2_ebi_remove(struct platform_device *pdev) |
1150 | { |
1151 | struct stm32_fmc2_ebi *ebi = platform_get_drvdata(pdev); |
1152 | |
1153 | of_platform_depopulate(parent: &pdev->dev); |
1154 | stm32_fmc2_ebi_disable_banks(ebi); |
1155 | stm32_fmc2_ebi_disable(ebi); |
1156 | clk_disable_unprepare(clk: ebi->clk); |
1157 | |
1158 | return 0; |
1159 | } |
1160 | |
1161 | static int __maybe_unused stm32_fmc2_ebi_suspend(struct device *dev) |
1162 | { |
1163 | struct stm32_fmc2_ebi *ebi = dev_get_drvdata(dev); |
1164 | |
1165 | stm32_fmc2_ebi_disable(ebi); |
1166 | clk_disable_unprepare(clk: ebi->clk); |
1167 | pinctrl_pm_select_sleep_state(dev); |
1168 | |
1169 | return 0; |
1170 | } |
1171 | |
1172 | static int __maybe_unused stm32_fmc2_ebi_resume(struct device *dev) |
1173 | { |
1174 | struct stm32_fmc2_ebi *ebi = dev_get_drvdata(dev); |
1175 | int ret; |
1176 | |
1177 | pinctrl_pm_select_default_state(dev); |
1178 | |
1179 | ret = clk_prepare_enable(clk: ebi->clk); |
1180 | if (ret) |
1181 | return ret; |
1182 | |
1183 | stm32_fmc2_ebi_set_setup(ebi); |
1184 | stm32_fmc2_ebi_enable(ebi); |
1185 | |
1186 | return 0; |
1187 | } |
1188 | |
1189 | static SIMPLE_DEV_PM_OPS(stm32_fmc2_ebi_pm_ops, stm32_fmc2_ebi_suspend, |
1190 | stm32_fmc2_ebi_resume); |
1191 | |
1192 | static const struct of_device_id stm32_fmc2_ebi_match[] = { |
1193 | {.compatible = "st,stm32mp1-fmc2-ebi" }, |
1194 | {} |
1195 | }; |
1196 | MODULE_DEVICE_TABLE(of, stm32_fmc2_ebi_match); |
1197 | |
1198 | static struct platform_driver stm32_fmc2_ebi_driver = { |
1199 | .probe = stm32_fmc2_ebi_probe, |
1200 | .remove = stm32_fmc2_ebi_remove, |
1201 | .driver = { |
1202 | .name = "stm32_fmc2_ebi" , |
1203 | .of_match_table = stm32_fmc2_ebi_match, |
1204 | .pm = &stm32_fmc2_ebi_pm_ops, |
1205 | }, |
1206 | }; |
1207 | module_platform_driver(stm32_fmc2_ebi_driver); |
1208 | |
1209 | MODULE_ALIAS("platform:stm32_fmc2_ebi" ); |
1210 | MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>" ); |
1211 | MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 ebi driver" ); |
1212 | MODULE_LICENSE("GPL v2" ); |
1213 | |