e45d2635fd1ebc18d5979dcbc7304679cb784380
[openwrt/staging/hauke.git] / target / linux / layerscape / patches-4.9 / 402-mtd-support-layerscape.patch
1 From c0e4767d3b26f21e5043fe2d15a24a1958de766e Mon Sep 17 00:00:00 2001
2 From: Yangbo Lu <yangbo.lu@nxp.com>
3 Date: Mon, 25 Sep 2017 10:17:28 +0800
4 Subject: [PATCH] mtd: support layerscape
5
6 This is a integrated patch for layerscape ifc-nor-nand support.
7
8 Signed-off-by: Alison Wang <b18965@freescale.com>
9 Signed-off-by: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>
10 Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
11 ---
12 drivers/memory/Kconfig | 2 +-
13 drivers/memory/fsl_ifc.c | 263 ++++++++++++++++++++++++++++++++++++++++
14 drivers/mtd/maps/physmap_of.c | 4 +
15 drivers/mtd/nand/Kconfig | 2 +-
16 drivers/mtd/nand/fsl_ifc_nand.c | 5 +-
17 include/linux/fsl_ifc.h | 7 ++
18 6 files changed, 280 insertions(+), 3 deletions(-)
19
20 diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
21 index 4b4c0c3c..820f5590 100644
22 --- a/drivers/memory/Kconfig
23 +++ b/drivers/memory/Kconfig
24 @@ -115,7 +115,7 @@ config FSL_CORENET_CF
25
26 config FSL_IFC
27 bool
28 - depends on FSL_SOC || ARCH_LAYERSCAPE
29 + depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A
30
31 config JZ4780_NEMC
32 bool "Ingenic JZ4780 SoC NEMC driver"
33 diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c
34 index 1b182b11..10d2a5f8 100644
35 --- a/drivers/memory/fsl_ifc.c
36 +++ b/drivers/memory/fsl_ifc.c
37 @@ -24,6 +24,7 @@
38 #include <linux/compiler.h>
39 #include <linux/sched.h>
40 #include <linux/spinlock.h>
41 +#include <linux/delay.h>
42 #include <linux/types.h>
43 #include <linux/slab.h>
44 #include <linux/io.h>
45 @@ -37,6 +38,8 @@
46
47 struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev;
48 EXPORT_SYMBOL(fsl_ifc_ctrl_dev);
49 +#define FSL_IFC_V1_3_0 0x01030000
50 +#define IFC_TIMEOUT_MSECS 1000 /* 1000ms */
51
52 /*
53 * convert_ifc_address - convert the base address
54 @@ -311,6 +314,261 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev)
55 return ret;
56 }
57
58 +#ifdef CONFIG_PM_SLEEP
59 +/* save ifc registers */
60 +static int fsl_ifc_suspend(struct device *dev)
61 +{
62 + struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(dev);
63 + struct fsl_ifc_global __iomem *fcm = ctrl->gregs;
64 + struct fsl_ifc_runtime __iomem *runtime = ctrl->rregs;
65 + __be32 nand_evter_intr_en, cm_evter_intr_en, nor_evter_intr_en,
66 + gpcm_evter_intr_en;
67 + uint32_t ifc_bank, i;
68 +
69 + ctrl->saved_gregs = kzalloc(sizeof(struct fsl_ifc_global), GFP_KERNEL);
70 + if (!ctrl->saved_gregs)
71 + return -ENOMEM;
72 + ctrl->saved_rregs = kzalloc(sizeof(struct fsl_ifc_runtime), GFP_KERNEL);
73 + if (!ctrl->saved_rregs)
74 + return -ENOMEM;
75 +
76 + cm_evter_intr_en = ifc_in32(&fcm->cm_evter_intr_en);
77 + nand_evter_intr_en = ifc_in32(&runtime->ifc_nand.nand_evter_intr_en);
78 + nor_evter_intr_en = ifc_in32(&runtime->ifc_nor.nor_evter_intr_en);
79 + gpcm_evter_intr_en = ifc_in32(&runtime->ifc_gpcm.gpcm_evter_intr_en);
80 +
81 +/* IFC interrupts disabled */
82 +
83 + ifc_out32(0x0, &fcm->cm_evter_intr_en);
84 + ifc_out32(0x0, &runtime->ifc_nand.nand_evter_intr_en);
85 + ifc_out32(0x0, &runtime->ifc_nor.nor_evter_intr_en);
86 + ifc_out32(0x0, &runtime->ifc_gpcm.gpcm_evter_intr_en);
87 +
88 + if (ctrl->saved_gregs) {
89 + for (ifc_bank = 0; ifc_bank < FSL_IFC_BANK_COUNT; ifc_bank++) {
90 + ctrl->saved_gregs->cspr_cs[ifc_bank].cspr_ext =
91 + ifc_in32(&fcm->cspr_cs[ifc_bank].cspr_ext);
92 + ctrl->saved_gregs->cspr_cs[ifc_bank].cspr =
93 + ifc_in32(&fcm->cspr_cs[ifc_bank].cspr);
94 + ctrl->saved_gregs->amask_cs[ifc_bank].amask =
95 + ifc_in32(&fcm->amask_cs[ifc_bank].amask);
96 + ctrl->saved_gregs->csor_cs[ifc_bank].csor_ext =
97 + ifc_in32(&fcm->csor_cs[ifc_bank].csor_ext);
98 + ctrl->saved_gregs->csor_cs[ifc_bank].csor =
99 + ifc_in32(&fcm->csor_cs[ifc_bank].csor);
100 + for (i = 0; i < 4; i++) {
101 + ctrl->saved_gregs->ftim_cs[ifc_bank].ftim[i] =
102 + ifc_in32(
103 + &fcm->ftim_cs[ifc_bank].ftim[i]);
104 + }
105 + }
106 +
107 + ctrl->saved_gregs->rb_map = ifc_in32(&fcm->rb_map);
108 + ctrl->saved_gregs->wb_map = ifc_in32(&fcm->wb_map);
109 + ctrl->saved_gregs->ifc_gcr = ifc_in32(&fcm->ifc_gcr);
110 + ctrl->saved_gregs->ddr_ccr_low = ifc_in32(&fcm->ddr_ccr_low);
111 + ctrl->saved_gregs->cm_evter_en = ifc_in32(&fcm->cm_evter_en);
112 + }
113 +
114 + if (ctrl->saved_rregs) {
115 + /* IFC controller NAND machine registers */
116 + ctrl->saved_rregs->ifc_nand.ncfgr =
117 + ifc_in32(&runtime->ifc_nand.ncfgr);
118 + ctrl->saved_rregs->ifc_nand.nand_fcr0 =
119 + ifc_in32(&runtime->ifc_nand.nand_fcr0);
120 + ctrl->saved_rregs->ifc_nand.nand_fcr1 =
121 + ifc_in32(&runtime->ifc_nand.nand_fcr1);
122 + ctrl->saved_rregs->ifc_nand.row0 =
123 + ifc_in32(&runtime->ifc_nand.row0);
124 + ctrl->saved_rregs->ifc_nand.row1 =
125 + ifc_in32(&runtime->ifc_nand.row1);
126 + ctrl->saved_rregs->ifc_nand.col0 =
127 + ifc_in32(&runtime->ifc_nand.col0);
128 + ctrl->saved_rregs->ifc_nand.col1 =
129 + ifc_in32(&runtime->ifc_nand.col1);
130 + ctrl->saved_rregs->ifc_nand.row2 =
131 + ifc_in32(&runtime->ifc_nand.row2);
132 + ctrl->saved_rregs->ifc_nand.col2 =
133 + ifc_in32(&runtime->ifc_nand.col2);
134 + ctrl->saved_rregs->ifc_nand.row3 =
135 + ifc_in32(&runtime->ifc_nand.row3);
136 + ctrl->saved_rregs->ifc_nand.col3 =
137 + ifc_in32(&runtime->ifc_nand.col3);
138 +
139 + ctrl->saved_rregs->ifc_nand.nand_fbcr =
140 + ifc_in32(&runtime->ifc_nand.nand_fbcr);
141 + ctrl->saved_rregs->ifc_nand.nand_fir0 =
142 + ifc_in32(&runtime->ifc_nand.nand_fir0);
143 + ctrl->saved_rregs->ifc_nand.nand_fir1 =
144 + ifc_in32(&runtime->ifc_nand.nand_fir1);
145 + ctrl->saved_rregs->ifc_nand.nand_fir2 =
146 + ifc_in32(&runtime->ifc_nand.nand_fir2);
147 + ctrl->saved_rregs->ifc_nand.nand_csel =
148 + ifc_in32(&runtime->ifc_nand.nand_csel);
149 + ctrl->saved_rregs->ifc_nand.nandseq_strt =
150 + ifc_in32(
151 + &runtime->ifc_nand.nandseq_strt);
152 + ctrl->saved_rregs->ifc_nand.nand_evter_en =
153 + ifc_in32(
154 + &runtime->ifc_nand.nand_evter_en);
155 + ctrl->saved_rregs->ifc_nand.nanndcr =
156 + ifc_in32(&runtime->ifc_nand.nanndcr);
157 + ctrl->saved_rregs->ifc_nand.nand_dll_lowcfg0 =
158 + ifc_in32(
159 + &runtime->ifc_nand.nand_dll_lowcfg0);
160 + ctrl->saved_rregs->ifc_nand.nand_dll_lowcfg1 =
161 + ifc_in32(
162 + &runtime->ifc_nand.nand_dll_lowcfg1);
163 +
164 + /* IFC controller NOR machine registers */
165 + ctrl->saved_rregs->ifc_nor.nor_evter_en =
166 + ifc_in32(
167 + &runtime->ifc_nor.nor_evter_en);
168 + ctrl->saved_rregs->ifc_nor.norcr =
169 + ifc_in32(&runtime->ifc_nor.norcr);
170 +
171 + /* IFC controller GPCM Machine registers */
172 + ctrl->saved_rregs->ifc_gpcm.gpcm_evter_en =
173 + ifc_in32(
174 + &runtime->ifc_gpcm.gpcm_evter_en);
175 + }
176 +
177 +/* save the interrupt values */
178 + ctrl->saved_gregs->cm_evter_intr_en = cm_evter_intr_en;
179 + ctrl->saved_rregs->ifc_nand.nand_evter_intr_en = nand_evter_intr_en;
180 + ctrl->saved_rregs->ifc_nor.nor_evter_intr_en = nor_evter_intr_en;
181 + ctrl->saved_rregs->ifc_gpcm.gpcm_evter_intr_en = gpcm_evter_intr_en;
182 +
183 + return 0;
184 +}
185 +
186 +/* restore ifc registers */
187 +static int fsl_ifc_resume(struct device *dev)
188 +{
189 + struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(dev);
190 + struct fsl_ifc_global __iomem *fcm = ctrl->gregs;
191 + struct fsl_ifc_runtime __iomem *runtime = ctrl->rregs;
192 + struct fsl_ifc_global *savd_gregs = ctrl->saved_gregs;
193 + struct fsl_ifc_runtime *savd_rregs = ctrl->saved_rregs;
194 + uint32_t ver = 0, ncfgr, timeout, ifc_bank, i;
195 +
196 +/*
197 + * IFC interrupts disabled
198 + */
199 + ifc_out32(0x0, &fcm->cm_evter_intr_en);
200 + ifc_out32(0x0, &runtime->ifc_nand.nand_evter_intr_en);
201 + ifc_out32(0x0, &runtime->ifc_nor.nor_evter_intr_en);
202 + ifc_out32(0x0, &runtime->ifc_gpcm.gpcm_evter_intr_en);
203 +
204 +
205 + if (ctrl->saved_gregs) {
206 + for (ifc_bank = 0; ifc_bank < FSL_IFC_BANK_COUNT; ifc_bank++) {
207 + ifc_out32(savd_gregs->cspr_cs[ifc_bank].cspr_ext,
208 + &fcm->cspr_cs[ifc_bank].cspr_ext);
209 + ifc_out32(savd_gregs->cspr_cs[ifc_bank].cspr,
210 + &fcm->cspr_cs[ifc_bank].cspr);
211 + ifc_out32(savd_gregs->amask_cs[ifc_bank].amask,
212 + &fcm->amask_cs[ifc_bank].amask);
213 + ifc_out32(savd_gregs->csor_cs[ifc_bank].csor_ext,
214 + &fcm->csor_cs[ifc_bank].csor_ext);
215 + ifc_out32(savd_gregs->csor_cs[ifc_bank].csor,
216 + &fcm->csor_cs[ifc_bank].csor);
217 + for (i = 0; i < 4; i++) {
218 + ifc_out32(savd_gregs->ftim_cs[ifc_bank].ftim[i],
219 + &fcm->ftim_cs[ifc_bank].ftim[i]);
220 + }
221 + }
222 + ifc_out32(savd_gregs->rb_map, &fcm->rb_map);
223 + ifc_out32(savd_gregs->wb_map, &fcm->wb_map);
224 + ifc_out32(savd_gregs->ifc_gcr, &fcm->ifc_gcr);
225 + ifc_out32(savd_gregs->ddr_ccr_low, &fcm->ddr_ccr_low);
226 + ifc_out32(savd_gregs->cm_evter_en, &fcm->cm_evter_en);
227 + }
228 +
229 + if (ctrl->saved_rregs) {
230 + /* IFC controller NAND machine registers */
231 + ifc_out32(savd_rregs->ifc_nand.ncfgr,
232 + &runtime->ifc_nand.ncfgr);
233 + ifc_out32(savd_rregs->ifc_nand.nand_fcr0,
234 + &runtime->ifc_nand.nand_fcr0);
235 + ifc_out32(savd_rregs->ifc_nand.nand_fcr1,
236 + &runtime->ifc_nand.nand_fcr1);
237 + ifc_out32(savd_rregs->ifc_nand.row0, &runtime->ifc_nand.row0);
238 + ifc_out32(savd_rregs->ifc_nand.row1, &runtime->ifc_nand.row1);
239 + ifc_out32(savd_rregs->ifc_nand.col0, &runtime->ifc_nand.col0);
240 + ifc_out32(savd_rregs->ifc_nand.col1, &runtime->ifc_nand.col1);
241 + ifc_out32(savd_rregs->ifc_nand.row2, &runtime->ifc_nand.row2);
242 + ifc_out32(savd_rregs->ifc_nand.col2, &runtime->ifc_nand.col2);
243 + ifc_out32(savd_rregs->ifc_nand.row3, &runtime->ifc_nand.row3);
244 + ifc_out32(savd_rregs->ifc_nand.col3, &runtime->ifc_nand.col3);
245 + ifc_out32(savd_rregs->ifc_nand.nand_fbcr,
246 + &runtime->ifc_nand.nand_fbcr);
247 + ifc_out32(savd_rregs->ifc_nand.nand_fir0,
248 + &runtime->ifc_nand.nand_fir0);
249 + ifc_out32(savd_rregs->ifc_nand.nand_fir1,
250 + &runtime->ifc_nand.nand_fir1);
251 + ifc_out32(savd_rregs->ifc_nand.nand_fir2,
252 + &runtime->ifc_nand.nand_fir2);
253 + ifc_out32(savd_rregs->ifc_nand.nand_csel,
254 + &runtime->ifc_nand.nand_csel);
255 + ifc_out32(savd_rregs->ifc_nand.nandseq_strt,
256 + &runtime->ifc_nand.nandseq_strt);
257 + ifc_out32(savd_rregs->ifc_nand.nand_evter_en,
258 + &runtime->ifc_nand.nand_evter_en);
259 + ifc_out32(savd_rregs->ifc_nand.nanndcr,
260 + &runtime->ifc_nand.nanndcr);
261 + ifc_out32(savd_rregs->ifc_nand.nand_dll_lowcfg0,
262 + &runtime->ifc_nand.nand_dll_lowcfg0);
263 + ifc_out32(savd_rregs->ifc_nand.nand_dll_lowcfg1,
264 + &runtime->ifc_nand.nand_dll_lowcfg1);
265 +
266 + /* IFC controller NOR machine registers */
267 + ifc_out32(savd_rregs->ifc_nor.nor_evter_en,
268 + &runtime->ifc_nor.nor_evter_en);
269 + ifc_out32(savd_rregs->ifc_nor.norcr, &runtime->ifc_nor.norcr);
270 +
271 + /* IFC controller GPCM Machine registers */
272 + ifc_out32(savd_rregs->ifc_gpcm.gpcm_evter_en,
273 + &runtime->ifc_gpcm.gpcm_evter_en);
274 +
275 + /* IFC interrupts enabled */
276 + ifc_out32(ctrl->saved_gregs->cm_evter_intr_en,
277 + &fcm->cm_evter_intr_en);
278 + ifc_out32(ctrl->saved_rregs->ifc_nand.nand_evter_intr_en,
279 + &runtime->ifc_nand.nand_evter_intr_en);
280 + ifc_out32(ctrl->saved_rregs->ifc_nor.nor_evter_intr_en,
281 + &runtime->ifc_nor.nor_evter_intr_en);
282 + ifc_out32(ctrl->saved_rregs->ifc_gpcm.gpcm_evter_intr_en,
283 + &runtime->ifc_gpcm.gpcm_evter_intr_en);
284 +
285 + kfree(ctrl->saved_gregs);
286 + kfree(ctrl->saved_rregs);
287 + ctrl->saved_gregs = NULL;
288 + ctrl->saved_rregs = NULL;
289 + }
290 +
291 + ver = ifc_in32(&fcm->ifc_rev);
292 + ncfgr = ifc_in32(&runtime->ifc_nand.ncfgr);
293 + if (ver >= FSL_IFC_V1_3_0) {
294 +
295 + ifc_out32(ncfgr | IFC_NAND_SRAM_INIT_EN,
296 + &runtime->ifc_nand.ncfgr);
297 + /* wait for SRAM_INIT bit to be clear or timeout */
298 + timeout = 10;
299 + while ((ifc_in32(&runtime->ifc_nand.ncfgr) &
300 + IFC_NAND_SRAM_INIT_EN) && timeout) {
301 + mdelay(IFC_TIMEOUT_MSECS);
302 + timeout--;
303 + }
304 +
305 + if (!timeout)
306 + dev_err(ctrl->dev, "Timeout waiting for IFC SRAM INIT");
307 + }
308 +
309 + return 0;
310 +}
311 +#endif /* CONFIG_PM_SLEEP */
312 +
313 static const struct of_device_id fsl_ifc_match[] = {
314 {
315 .compatible = "fsl,ifc",
316 @@ -318,10 +576,15 @@ static const struct of_device_id fsl_ifc_match[] = {
317 {},
318 };
319
320 +static const struct dev_pm_ops ifc_pm_ops = {
321 + SET_SYSTEM_SLEEP_PM_OPS(fsl_ifc_suspend, fsl_ifc_resume)
322 +};
323 +
324 static struct platform_driver fsl_ifc_ctrl_driver = {
325 .driver = {
326 .name = "fsl-ifc",
327 .of_match_table = fsl_ifc_match,
328 + .pm = &ifc_pm_ops,
329 },
330 .probe = fsl_ifc_ctrl_probe,
331 .remove = fsl_ifc_ctrl_remove,
332 diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
333 index 11d63046..38b90301 100644
334 --- a/drivers/mtd/maps/physmap_of.c
335 +++ b/drivers/mtd/maps/physmap_of.c
336 @@ -20,6 +20,7 @@
337 #include <linux/mtd/map.h>
338 #include <linux/mtd/partitions.h>
339 #include <linux/mtd/concat.h>
340 +#include <linux/mtd/cfi_endian.h>
341 #include <linux/of.h>
342 #include <linux/of_address.h>
343 #include <linux/of_platform.h>
344 @@ -209,6 +210,9 @@ static int of_flash_probe(struct platform_device *dev)
345 return err;
346 }
347
348 + if (of_property_read_bool(dp->parent, "big-endian"))
349 + info->list[i].map.swap = CFI_BIG_ENDIAN;
350 +
351 err = -ENOMEM;
352 info->list[i].map.virt = ioremap(info->list[i].map.phys,
353 info->list[i].map.size);
354 diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
355 index b254090b..961f1aa1 100644
356 --- a/drivers/mtd/nand/Kconfig
357 +++ b/drivers/mtd/nand/Kconfig
358 @@ -438,7 +438,7 @@ config MTD_NAND_FSL_ELBC
359
360 config MTD_NAND_FSL_IFC
361 tristate "NAND support for Freescale IFC controller"
362 - depends on FSL_SOC || ARCH_LAYERSCAPE
363 + depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A
364 select FSL_IFC
365 select MEMORY
366 help
367 diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
368 index d1570f51..785e9ee0 100644
369 --- a/drivers/mtd/nand/fsl_ifc_nand.c
370 +++ b/drivers/mtd/nand/fsl_ifc_nand.c
371 @@ -904,9 +904,12 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
372 chip->ecc.algo = NAND_ECC_HAMMING;
373 }
374
375 - if (ctrl->version == FSL_IFC_VERSION_1_1_0)
376 + if (ctrl->version >= FSL_IFC_VERSION_1_1_0)
377 fsl_ifc_sram_init(priv);
378
379 + if (ctrl->version >= FSL_IFC_VERSION_2_0_0)
380 + priv->bufnum_mask = (priv->bufnum_mask * 2) + 1;
381 +
382 return 0;
383 }
384
385 diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h
386 index c332f0a4..a41d21b6 100644
387 --- a/include/linux/fsl_ifc.h
388 +++ b/include/linux/fsl_ifc.h
389 @@ -274,6 +274,8 @@
390 */
391 /* Auto Boot Mode */
392 #define IFC_NAND_NCFGR_BOOT 0x80000000
393 +/* SRAM INIT EN */
394 +#define IFC_NAND_SRAM_INIT_EN 0x20000000
395 /* Addressing Mode-ROW0+n/COL0 */
396 #define IFC_NAND_NCFGR_ADDR_MODE_RC0 0x00000000
397 /* Addressing Mode-ROW0+n/COL0+n */
398 @@ -861,6 +863,11 @@ struct fsl_ifc_ctrl {
399 u32 nand_stat;
400 wait_queue_head_t nand_wait;
401 bool little_endian;
402 +#ifdef CONFIG_PM_SLEEP
403 + /*save regs when system goes to deep sleep*/
404 + struct fsl_ifc_global *saved_gregs;
405 + struct fsl_ifc_runtime *saved_rregs;
406 +#endif
407 };
408
409 extern struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev;
410 --
411 2.14.1
412