Date:2010-11-21 18:09:56 (11 years 10 months ago)
Author:Maarten ter Huurne
Commit:b2f7fd4df1dd1c30931a25f5fd5bbabc1bec45f4
Message:MTD: NAND: JZ4740: Experimental multi-bank support

Original patch by Lars-Peter Clausen with some bug fixes from me.
Squashed version of development done in jz-2.6.35 branch.
Files: arch/mips/include/asm/mach-jz4740/jz4740_nand.h (1 diff)
arch/mips/jz4740/platform.c (1 diff)
drivers/mtd/nand/jz4740_nand.c (12 diffs)

Change Details

arch/mips/include/asm/mach-jz4740/jz4740_nand.h
2727
2828    unsigned int busy_gpio;
2929
30    unsigned char banks[4];
31
3032    void (*ident_callback)(struct platform_device *, struct nand_chip *,
3133                struct mtd_partition **, int *num_partitions);
3234};
arch/mips/jz4740/platform.c
157157        .flags = IORESOURCE_MEM,
158158    },
159159    {
160        .name = "bank",
160        .name = "bank1",
161161        .start = 0x18000000,
162162        .end = 0x180C0000 - 1,
163163        .flags = IORESOURCE_MEM,
164164    },
165    {
166        .name = "bank2",
167        .start = 0x14000000,
168        .end = 0x140C0000 - 1,
169        .flags = IORESOURCE_MEM,
170    },
171    {
172        .name = "bank3",
173        .start = 0x0C000000,
174        .end = 0x0C0C0000 - 1,
175        .flags = IORESOURCE_MEM,
176    },
177    {
178        .name = "bank4",
179        .start = 0x08000000,
180        .end = 0x080C0000 - 1,
181        .flags = IORESOURCE_MEM,
182    },
165183};
166184
167185struct platform_device jz4740_nand_device = {
drivers/mtd/nand/jz4740_nand.c
5252
5353#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1)
5454#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1)
55#define JZ_NAND_CTRL_ASSERT_CHIP_MASK 0xaa
5556
56#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
5757#define JZ_NAND_MEM_CMD_OFFSET 0x08000
58#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
5859
5960struct jz_nand {
6061    struct mtd_info mtd;
...... 
6263    void __iomem *base;
6364    struct resource *mem;
6465
65    void __iomem *bank_base;
66    struct resource *bank_mem;
66    void __iomem *bank_base[4];
67    struct resource *bank_mem[4];
68
69    int selected_bank;
6770
6871    struct jz_nand_platform_data *pdata;
6972    bool is_reading;
...... 
7477    return container_of(mtd, struct jz_nand, mtd);
7578}
7679
80static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
81{
82    struct jz_nand *nand = mtd_to_jz_nand(mtd);
83    struct nand_chip *chip = mtd->priv;
84    uint32_t ctrl;
85    int banknr;
86
87    ctrl = readl(nand->base + JZ_REG_NAND_CTRL);
88    ctrl &= ~JZ_NAND_CTRL_ASSERT_CHIP_MASK;
89
90    if (chipnr == -1) {
91        banknr = -1;
92    } else {
93        banknr = nand->pdata->banks[chipnr] - 1;
94        chip->IO_ADDR_R = nand->bank_base[banknr];
95        chip->IO_ADDR_W = nand->bank_base[banknr];
96    }
97    writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
98
99    nand->selected_bank = banknr;
100}
101
77102static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
78103{
79104    struct jz_nand *nand = mtd_to_jz_nand(mtd);
80105    struct nand_chip *chip = mtd->priv;
81106    uint32_t reg;
107    void __iomem *bank_base = nand->bank_base[nand->selected_bank];
108
109    BUG_ON(nand->selected_bank < 0);
82110
83111    if (ctrl & NAND_CTRL_CHANGE) {
84112        BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
85113        if (ctrl & NAND_ALE)
86            chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_ADDR_OFFSET;
114            bank_base += JZ_NAND_MEM_ADDR_OFFSET;
87115        else if (ctrl & NAND_CLE)
88            chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_CMD_OFFSET;
89        else
90            chip->IO_ADDR_W = nand->bank_base;
116            bank_base += JZ_NAND_MEM_CMD_OFFSET;
117        chip->IO_ADDR_W = bank_base;
91118
92119        reg = readl(nand->base + JZ_REG_NAND_CTRL);
93120        if (ctrl & NAND_NCE)
94            reg |= JZ_NAND_CTRL_ASSERT_CHIP(0);
121            reg |= JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank);
95122        else
96            reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0);
123            reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank);
97124        writel(reg, nand->base + JZ_REG_NAND_CTRL);
98125    }
126    //printk("write %02X to %p (bank %d)\n",
127    // dat, chip->IO_ADDR_W, nand->selected_bank + 1);
99128    if (dat != NAND_CMD_NONE)
100129        writeb(dat, chip->IO_ADDR_W);
101130}
...... 
256285#endif
257286
258287static int jz_nand_ioremap_resource(struct platform_device *pdev,
259    const char *name, struct resource **res, void __iomem **base)
288    const char *name, struct resource **res, void *__iomem *base)
260289{
261290    int ret;
262291
...... 
292321    return ret;
293322}
294323
324static inline void jz_nand_iounmap_resource(struct resource *res, void __iomem *base)
325{
326    iounmap(base);
327    release_mem_region(res->start, resource_size(res));
328}
329
330static void jz_nand_iounmap_banks(
331    struct jz_nand *nand, unsigned char *banks, size_t num_banks)
332{
333    int i;
334
335    for (i = 0; i < num_banks; ++i) {
336        unsigned char bank = banks[i];
337        jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
338                     nand->bank_base[bank - 1]);
339    }
340}
341
342static int jz_nand_ioremap_banks(struct platform_device *pdev,
343    struct jz_nand *nand, unsigned char *banks, size_t num_banks)
344{
345    int ret;
346    char name[6];
347    int i;
348
349    for (i = 0; i < num_banks; ++i) {
350        unsigned char bank = banks[i];
351        sprintf(name, "bank%d", bank);
352
353        ret = jz_nand_ioremap_resource(pdev, name,
354                           &nand->bank_mem[bank - 1],
355                           &nand->bank_base[bank - 1]);
356        if (ret) {
357            jz_nand_iounmap_banks(nand, banks, i);
358            return ret;
359        }
360    }
361
362    return 0;
363}
364
295365static int __devinit jz_nand_probe(struct platform_device *pdev)
296366{
297367    int ret;
...... 
303373    struct mtd_partition *partition_info;
304374    int num_partitions = 0;
305375#endif
376    size_t num_banks;
377    unsigned char bank;
378    uint32_t ctrl;
306379
307380    nand = kzalloc(sizeof(*nand), GFP_KERNEL);
308381    if (!nand) {
...... 
313386    ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base);
314387    if (ret)
315388        goto err_free;
316    ret = jz_nand_ioremap_resource(pdev, "bank", &nand->bank_mem,
317            &nand->bank_base);
318    if (ret)
319        goto err_iounmap_mmio;
320389
321390    if (pdata && gpio_is_valid(pdata->busy_gpio)) {
322391        ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
...... 
324393            dev_err(&pdev->dev,
325394                "Failed to request busy gpio %d: %d\n",
326395                pdata->busy_gpio, ret);
327            goto err_iounmap_mem;
396            goto err_iounmap_mmio;
328397        }
329398    }
330399
...... 
346415
347416    chip->chip_delay = 50;
348417    chip->cmd_ctrl = jz_nand_cmd_ctrl;
418    chip->select_chip = jz_nand_select_chip;
349419
350420    if (pdata && gpio_is_valid(pdata->busy_gpio))
351421        chip->dev_ready = jz_nand_dev_ready;
352422
353    chip->IO_ADDR_R = nand->bank_base;
354    chip->IO_ADDR_W = nand->bank_base;
355
356423    nand->pdata = pdata;
357424    platform_set_drvdata(pdev, nand);
358425
359    writel(JZ_NAND_CTRL_ENABLE_CHIP(0), nand->base + JZ_REG_NAND_CTRL);
426    if (pdata->banks[0] == 0)
427        pdata->banks[0] = 1;
428
429    ctrl = 0;
430    for (num_banks = 0; num_banks < 4 ; ++num_banks) {
431        int gpio;
432        char name[9];
433
434        bank = pdata->banks[num_banks];
435        if (bank == 0)
436            break;
437        if (bank > 4) {
438            dev_err(&pdev->dev, "Non-existing bank: %d\n", bank);
439            ret = -EINVAL;
440            goto err_gpio_free;
441        }
442
443        sprintf(name, "NAND CS%d", bank);
444        gpio = JZ_GPIO_MEM_CS0 + bank - 1;
445        ret = gpio_request(gpio, name);
446        if (ret) {
447            dev_err(&pdev->dev,
448                "Failed to request %s gpio %d: %d\n",
449                name, gpio, ret);
450            goto err_gpio_free;
451        }
452        jz_gpio_set_function(gpio, JZ_GPIO_FUNC_MEM_CS0);
453
454        ctrl |= JZ_NAND_CTRL_ENABLE_CHIP(bank - 1);
455    }
456
457    ret = jz_nand_ioremap_banks(pdev, nand, pdata->banks, num_banks);
458    if (ret)
459        goto err_gpio_free;
460
461    chip->IO_ADDR_R = nand->bank_base[pdata->banks[0] - 1];
462    chip->IO_ADDR_W = nand->bank_base[pdata->banks[0] - 1];
360463
361    ret = nand_scan_ident(mtd, 1, NULL);
464    writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
465
466    ret = nand_scan_ident(mtd, num_banks, NULL);
362467    if (ret) {
363468        dev_err(&pdev->dev, "Failed to scan nand\n");
364        goto err_gpio_free;
469        goto err_iounmap_banks;
365470    }
366471
367472    if (pdata && pdata->ident_callback) {
...... 
372477    ret = nand_scan_tail(mtd);
373478    if (ret) {
374479        dev_err(&pdev->dev, "Failed to scan nand\n");
375        goto err_gpio_free;
480        goto err_iounmap_banks;
376481    }
377482
378483#ifdef CONFIG_MTD_PARTITIONS
...... 
402507
403508err_nand_release:
404509    nand_release(&nand->mtd);
510err_iounmap_banks:
511    jz_nand_iounmap_banks(nand, pdata->banks, num_banks);
405512err_gpio_free:
406513    platform_set_drvdata(pdev, NULL);
407514    gpio_free(pdata->busy_gpio);
408err_iounmap_mem:
409    iounmap(nand->bank_base);
515    while (num_banks--) {
516        bank = pdata->banks[num_banks];
517        gpio_free(JZ_GPIO_MEM_CS0 + bank - 1);
518    }
410519err_iounmap_mmio:
411520    iounmap(nand->base);
412521err_free:
...... 
417526static int __devexit jz_nand_remove(struct platform_device *pdev)
418527{
419528    struct jz_nand *nand = platform_get_drvdata(pdev);
529    struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
530    int i;
420531
421532    nand_release(&nand->mtd);
422533
423534    /* Deassert and disable all chips */
424535    writel(0, nand->base + JZ_REG_NAND_CTRL);
425536
426    iounmap(nand->bank_base);
427    release_mem_region(nand->bank_mem->start, resource_size(nand->bank_mem));
428    iounmap(nand->base);
429    release_mem_region(nand->mem->start, resource_size(nand->mem));
537    for (i = 0; i < 4; ++i)
538        if (nand->bank_base[i] != 0) {
539            jz_nand_iounmap_resource(nand->bank_mem[i],
540                         nand->bank_base[i]);
541            gpio_free(JZ_GPIO_MEM_CS0 + i);
542        }
543    gpio_free(pdata->busy_gpio);
544
545    jz_nand_iounmap_resource(nand->mem, nand->base);
430546
431547    platform_set_drvdata(pdev, NULL);
432548    kfree(nand);

Archive Download the corresponding diff file



interactive