Root/target/linux/xburst/patches-3.2/0006-MTD-NAND-JZ4740-Multi-bank-support-with-autodetectio.patch

1From d5814bdb661d3dac61422f8f69e459be884c9a9d Mon Sep 17 00:00:00 2001
2From: Maarten ter Huurne <maarten@treewalker.org>
3Date: Tue, 2 Aug 2011 10:49:28 +0200
4Subject: [PATCH 06/28] MTD: NAND: JZ4740: Multi-bank support with
5 autodetection
6
7The platform data can now specify which external memory banks to probe
8for NAND chips, and in which order. Banks that contain a NAND are used
9and the other banks are freed.
10
11Squashed version of development done in jz-2.6.38 branch.
12Original patch by Lars-Peter Clausen with some bug fixes from me.
13Thanks to Paul Cercueil for the initial autodetection patch.
14---
15 arch/mips/include/asm/mach-jz4740/jz4740_nand.h | 4 +
16 arch/mips/jz4740/platform.c | 20 ++-
17 drivers/mtd/nand/jz4740_nand.c | 228 +++++++++++++++++++----
18 3 files changed, 215 insertions(+), 37 deletions(-)
19
20diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
21index bb5b9a4..986982d 100644
22--- a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
23+++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
24@@ -19,6 +19,8 @@
25 #include <linux/mtd/nand.h>
26 #include <linux/mtd/partitions.h>
27 
28+#define JZ_NAND_NUM_BANKS 4
29+
30 struct jz_nand_platform_data {
31     int num_partitions;
32     struct mtd_partition *partitions;
33@@ -27,6 +29,8 @@ struct jz_nand_platform_data {
34 
35     unsigned int busy_gpio;
36 
37+ unsigned char banks[JZ_NAND_NUM_BANKS];
38+
39     void (*ident_callback)(struct platform_device *, struct nand_chip *,
40                 struct mtd_partition **, int *num_partitions);
41 };
42diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
43index 10929e2..e342ed4 100644
44--- a/arch/mips/jz4740/platform.c
45+++ b/arch/mips/jz4740/platform.c
46@@ -157,11 +157,29 @@ static struct resource jz4740_nand_resources[] = {
47         .flags = IORESOURCE_MEM,
48     },
49     {
50- .name = "bank",
51+ .name = "bank1",
52         .start = 0x18000000,
53         .end = 0x180C0000 - 1,
54         .flags = IORESOURCE_MEM,
55     },
56+ {
57+ .name = "bank2",
58+ .start = 0x14000000,
59+ .end = 0x140C0000 - 1,
60+ .flags = IORESOURCE_MEM,
61+ },
62+ {
63+ .name = "bank3",
64+ .start = 0x0C000000,
65+ .end = 0x0C0C0000 - 1,
66+ .flags = IORESOURCE_MEM,
67+ },
68+ {
69+ .name = "bank4",
70+ .start = 0x08000000,
71+ .end = 0x080C0000 - 1,
72+ .flags = IORESOURCE_MEM,
73+ },
74 };
75 
76 struct platform_device jz4740_nand_device = {
77diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
78index e266407..b254b99 100644
79--- a/drivers/mtd/nand/jz4740_nand.c
80+++ b/drivers/mtd/nand/jz4740_nand.c
81@@ -52,9 +52,10 @@
82 
83 #define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1)
84 #define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1)
85+#define JZ_NAND_CTRL_ASSERT_CHIP_MASK 0xaa
86 
87-#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
88 #define JZ_NAND_MEM_CMD_OFFSET 0x08000
89+#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
90 
91 struct jz_nand {
92     struct mtd_info mtd;
93@@ -62,8 +63,11 @@ struct jz_nand {
94     void __iomem *base;
95     struct resource *mem;
96 
97- void __iomem *bank_base;
98- struct resource *bank_mem;
99+ unsigned char banks[JZ_NAND_NUM_BANKS];
100+ void __iomem *bank_base[JZ_NAND_NUM_BANKS];
101+ struct resource *bank_mem[JZ_NAND_NUM_BANKS];
102+
103+ int selected_bank;
104 
105     struct jz_nand_platform_data *pdata;
106     bool is_reading;
107@@ -74,26 +78,50 @@ static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
108     return container_of(mtd, struct jz_nand, mtd);
109 }
110 
111+static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
112+{
113+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
114+ struct nand_chip *chip = mtd->priv;
115+ uint32_t ctrl;
116+ int banknr;
117+
118+ ctrl = readl(nand->base + JZ_REG_NAND_CTRL);
119+ ctrl &= ~JZ_NAND_CTRL_ASSERT_CHIP_MASK;
120+
121+ if (chipnr == -1) {
122+ banknr = -1;
123+ } else {
124+ banknr = nand->banks[chipnr] - 1;
125+ chip->IO_ADDR_R = nand->bank_base[banknr];
126+ chip->IO_ADDR_W = nand->bank_base[banknr];
127+ }
128+ writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
129+
130+ nand->selected_bank = banknr;
131+}
132+
133 static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
134 {
135     struct jz_nand *nand = mtd_to_jz_nand(mtd);
136     struct nand_chip *chip = mtd->priv;
137     uint32_t reg;
138+ void __iomem *bank_base = nand->bank_base[nand->selected_bank];
139+
140+ BUG_ON(nand->selected_bank < 0);
141 
142     if (ctrl & NAND_CTRL_CHANGE) {
143         BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
144         if (ctrl & NAND_ALE)
145- chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_ADDR_OFFSET;
146+ bank_base += JZ_NAND_MEM_ADDR_OFFSET;
147         else if (ctrl & NAND_CLE)
148- chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_CMD_OFFSET;
149- else
150- chip->IO_ADDR_W = nand->bank_base;
151+ bank_base += JZ_NAND_MEM_CMD_OFFSET;
152+ chip->IO_ADDR_W = bank_base;
153 
154         reg = readl(nand->base + JZ_REG_NAND_CTRL);
155         if (ctrl & NAND_NCE)
156- reg |= JZ_NAND_CTRL_ASSERT_CHIP(0);
157+ reg |= JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank);
158         else
159- reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0);
160+ reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank);
161         writel(reg, nand->base + JZ_REG_NAND_CTRL);
162     }
163     if (dat != NAND_CMD_NONE)
164@@ -252,7 +280,7 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
165 }
166 
167 static int jz_nand_ioremap_resource(struct platform_device *pdev,
168- const char *name, struct resource **res, void __iomem **base)
169+ const char *name, struct resource **res, void *__iomem *base)
170 {
171     int ret;
172 
173@@ -288,6 +316,90 @@ err:
174     return ret;
175 }
176 
177+static inline void jz_nand_iounmap_resource(struct resource *res, void __iomem *base)
178+{
179+ iounmap(base);
180+ release_mem_region(res->start, resource_size(res));
181+}
182+
183+static int __devinit jz_nand_detect_bank(struct platform_device *pdev, struct jz_nand *nand, unsigned char bank, size_t chipnr, uint8_t *nand_maf_id, uint8_t *nand_dev_id) {
184+ int ret;
185+ int gpio;
186+ char gpio_name[9];
187+ char res_name[6];
188+ uint32_t ctrl;
189+ struct mtd_info *mtd = &nand->mtd;
190+ struct nand_chip *chip = &nand->chip;
191+
192+ /* Request GPIO port. */
193+ gpio = JZ_GPIO_MEM_CS0 + bank - 1;
194+ sprintf(gpio_name, "NAND CS%d", bank);
195+ ret = gpio_request(gpio, gpio_name);
196+ if (ret) {
197+ dev_warn(&pdev->dev,
198+ "Failed to request %s gpio %d: %d\n",
199+ gpio_name, gpio, ret);
200+ goto notfound_gpio;
201+ }
202+
203+ /* Request I/O resource. */
204+ sprintf(res_name, "bank%d", bank);
205+ ret = jz_nand_ioremap_resource(pdev, res_name,
206+ &nand->bank_mem[bank - 1],
207+ &nand->bank_base[bank - 1]);
208+ if (ret)
209+ goto notfound_resource;
210+
211+ /* Enable chip in bank. */
212+ jz_gpio_set_function(gpio, JZ_GPIO_FUNC_MEM_CS0);
213+ ctrl = readl(nand->base + JZ_REG_NAND_CTRL);
214+ ctrl |= JZ_NAND_CTRL_ENABLE_CHIP(bank - 1);
215+ writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
216+
217+ if (chipnr == 0) {
218+ /* Detect first chip. */
219+ ret = nand_scan_ident(mtd, 1, NULL);
220+ if (ret)
221+ goto notfound_id;
222+
223+ /* Retrieve the IDs from the first chip. */
224+ chip->select_chip(mtd, 0);
225+ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
226+ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
227+ *nand_maf_id = chip->read_byte(mtd);
228+ *nand_dev_id = chip->read_byte(mtd);
229+ } else {
230+ /* Detect additional chip. */
231+ chip->select_chip(mtd, chipnr);
232+ chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
233+ chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
234+ if (*nand_maf_id != chip->read_byte(mtd)
235+ || *nand_dev_id != chip->read_byte(mtd)) {
236+ ret = -ENODEV;
237+ goto notfound_id;
238+ }
239+
240+ /* Update size of the MTD. */
241+ chip->numchips++;
242+ mtd->size += chip->chipsize;
243+ }
244+
245+ dev_info(&pdev->dev, "Found chip %i on bank %i\n", chipnr, bank);
246+ return 0;
247+
248+notfound_id:
249+ dev_info(&pdev->dev, "No chip found on bank %i\n", bank);
250+ ctrl &= ~(JZ_NAND_CTRL_ENABLE_CHIP(bank - 1));
251+ writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
252+ jz_gpio_set_function(gpio, JZ_GPIO_FUNC_NONE);
253+ jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
254+ nand->bank_base[bank - 1]);
255+notfound_resource:
256+ gpio_free(gpio);
257+notfound_gpio:
258+ return ret;
259+}
260+
261 static int __devinit jz_nand_probe(struct platform_device *pdev)
262 {
263     int ret;
264@@ -295,6 +407,8 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
265     struct nand_chip *chip;
266     struct mtd_info *mtd;
267     struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
268+ size_t chipnr, bank_idx;
269+ uint8_t nand_maf_id = 0, nand_dev_id = 0;
270 
271     nand = kzalloc(sizeof(*nand), GFP_KERNEL);
272     if (!nand) {
273@@ -305,10 +419,6 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
274     ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base);
275     if (ret)
276         goto err_free;
277- ret = jz_nand_ioremap_resource(pdev, "bank", &nand->bank_mem,
278- &nand->bank_base);
279- if (ret)
280- goto err_iounmap_mmio;
281 
282     if (pdata && gpio_is_valid(pdata->busy_gpio)) {
283         ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
284@@ -316,7 +426,7 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
285             dev_err(&pdev->dev,
286                 "Failed to request busy gpio %d: %d\n",
287                 pdata->busy_gpio, ret);
288- goto err_iounmap_mem;
289+ goto err_iounmap_mmio;
290         }
291     }
292 
293@@ -338,22 +448,51 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
294 
295     chip->chip_delay = 50;
296     chip->cmd_ctrl = jz_nand_cmd_ctrl;
297+ chip->select_chip = jz_nand_select_chip;
298 
299     if (pdata && gpio_is_valid(pdata->busy_gpio))
300         chip->dev_ready = jz_nand_dev_ready;
301 
302- chip->IO_ADDR_R = nand->bank_base;
303- chip->IO_ADDR_W = nand->bank_base;
304-
305     nand->pdata = pdata;
306     platform_set_drvdata(pdev, nand);
307 
308- writel(JZ_NAND_CTRL_ENABLE_CHIP(0), nand->base + JZ_REG_NAND_CTRL);
309-
310- ret = nand_scan_ident(mtd, 1, NULL);
311- if (ret) {
312- dev_err(&pdev->dev, "Failed to scan nand\n");
313- goto err_gpio_free;
314+ /* We are going to autodetect NAND chips in the banks specified in the
315+ * platform data. Although nand_scan_ident() can detect multiple chips,
316+ * it requires those chips to be numbered consecuitively, which is not
317+ * always the case for external memory banks. And a fixed chip-to-bank
318+ * mapping is not practical either, since for example Dingoo units
319+ * produced at different times have NAND chips in different banks.
320+ */
321+ chipnr = 0;
322+ for (bank_idx = 0; bank_idx < JZ_NAND_NUM_BANKS; bank_idx++) {
323+ unsigned char bank;
324+
325+ /* If there is no platform data, look for NAND in bank 1,
326+ * which is the most likely bank since it is the only one
327+ * that can be booted from.
328+ */
329+ bank = pdata ? pdata->banks[bank_idx] : bank_idx ^ 1;
330+ if (bank == 0)
331+ break;
332+ if (bank > JZ_NAND_NUM_BANKS) {
333+ dev_warn(&pdev->dev,
334+ "Skipping non-existing bank: %d\n", bank);
335+ continue;
336+ }
337+ /* The detection routine will directly or indirectly call
338+ * jz_nand_select_chip(), so nand->banks has to contain the
339+ * bank we're checking.
340+ */
341+ nand->banks[chipnr] = bank;
342+ if (jz_nand_detect_bank(pdev, nand, bank, chipnr,
343+ &nand_maf_id, &nand_dev_id) == 0)
344+ chipnr++;
345+ else
346+ nand->banks[chipnr] = 0;
347+ }
348+ if (chipnr == 0) {
349+ dev_err(&pdev->dev, "No NAND chips found\n");
350+ goto err_gpio_busy;
351     }
352 
353     if (pdata && pdata->ident_callback) {
354@@ -363,8 +502,8 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
355 
356     ret = nand_scan_tail(mtd);
357     if (ret) {
358- dev_err(&pdev->dev, "Failed to scan nand\n");
359- goto err_gpio_free;
360+ dev_err(&pdev->dev, "Failed to scan NAND\n");
361+ goto err_unclaim_banks;
362     }
363 
364     ret = mtd_device_parse_register(mtd, NULL, 0,
365@@ -381,14 +520,21 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
366     return 0;
367 
368 err_nand_release:
369- nand_release(&nand->mtd);
370-err_gpio_free:
371+ nand_release(mtd);
372+err_unclaim_banks:
373+ while (chipnr--) {
374+ unsigned char bank = nand->banks[chipnr];
375+ gpio_free(JZ_GPIO_MEM_CS0 + bank - 1);
376+ jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
377+ nand->bank_base[bank - 1]);
378+ }
379+ writel(0, nand->base + JZ_REG_NAND_CTRL);
380+err_gpio_busy:
381+ if (pdata && gpio_is_valid(pdata->busy_gpio))
382+ gpio_free(pdata->busy_gpio);
383     platform_set_drvdata(pdev, NULL);
384- gpio_free(pdata->busy_gpio);
385-err_iounmap_mem:
386- iounmap(nand->bank_base);
387 err_iounmap_mmio:
388- iounmap(nand->base);
389+ jz_nand_iounmap_resource(nand->mem, nand->base);
390 err_free:
391     kfree(nand);
392     return ret;
393@@ -397,16 +543,26 @@ err_free:
394 static int __devexit jz_nand_remove(struct platform_device *pdev)
395 {
396     struct jz_nand *nand = platform_get_drvdata(pdev);
397+ struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
398+ size_t i;
399 
400     nand_release(&nand->mtd);
401 
402     /* Deassert and disable all chips */
403     writel(0, nand->base + JZ_REG_NAND_CTRL);
404 
405- iounmap(nand->bank_base);
406- release_mem_region(nand->bank_mem->start, resource_size(nand->bank_mem));
407- iounmap(nand->base);
408- release_mem_region(nand->mem->start, resource_size(nand->mem));
409+ for (i = 0; i < JZ_NAND_NUM_BANKS; ++i) {
410+ unsigned char bank = nand->banks[i];
411+ if (bank != 0) {
412+ jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
413+ nand->bank_base[bank - 1]);
414+ gpio_free(JZ_GPIO_MEM_CS0 + bank - 1);
415+ }
416+ }
417+ if (pdata && gpio_is_valid(pdata->busy_gpio))
418+ gpio_free(pdata->busy_gpio);
419+
420+ jz_nand_iounmap_resource(nand->mem, nand->base);
421 
422     platform_set_drvdata(pdev, NULL);
423     kfree(nand);
424--
4251.7.5.4
426
427

Archive Download this file



interactive