Date:2010-07-14 22:58:40 (13 years 4 months ago)
Author:Lars C.
Commit:d6e96efcb6163fb63b01f9ee861ffdee1f666e2e
Message:MTD: nand: jz4740: Experimental multi-chip support

Files: drivers/mtd/nand/jz4740_nand.c (12 diffs)

Change Details

drivers/mtd/nand/jz4740_nand.c
5151
5252#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1)
5353#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1)
54#define JZ_NAND_CTRL_ASSERT_CHIP_MASK 0xaa
5455
55#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
5656#define JZ_NAND_MEM_CMD_OFFSET 0x08000
57#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
5758
5859struct jz_nand {
5960    struct mtd_info mtd;
...... 
6162    void __iomem *base;
6263    struct resource *mem;
6364
64    void __iomem *bank_base;
65    struct resource *bank_mem;
65    void __iomem *bank_base[4];
66    struct resource *bank_mem[4];
67
68    int selected_chip;
6669
6770    struct jz_nand_platform_data *pdata;
6871    bool is_reading;
...... 
7376    return container_of(mtd, struct jz_nand, mtd);
7477}
7578
79static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
80{
81    struct jz_nand *nand = mtd_to_jz_nand(mtd);
82    struct nand_chip *chip = mtd->priv;
83    uint32_t ctrl;
84
85    ctrl = readl(nand->base + JZ_REG_NAND_CTRL);
86    ctrl &= ~JZ_NAND_CTRL_ASSERT_CHIP_MASK;
87
88    if (chipnr != -1) {
89        chipnr = nand->pdata->banks[chipnr] - 1;
90        chip->IO_ADDR_R = nand->bank_base[chipnr];
91        chip->IO_ADDR_W = nand->bank_base[chipnr];
92    }
93    writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
94
95    nand->selected_chip = chipnr;
96}
97
7698static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
7799{
78100    struct jz_nand *nand = mtd_to_jz_nand(mtd);
79101    struct nand_chip *chip = mtd->priv;
80102    uint32_t reg;
103    void __iomem *bank_base = nand->bank_base[nand->selected_chip];
104
105    BUG_ON(nand->selected_chip < 0);
81106
82107    if (ctrl & NAND_CTRL_CHANGE) {
83108        BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
84109        if (ctrl & NAND_ALE)
85            chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_ADDR_OFFSET;
110            bank_base += JZ_NAND_MEM_ADDR_OFFSET;
86111        else if (ctrl & NAND_CLE)
87            chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_CMD_OFFSET;
88        else
89            chip->IO_ADDR_W = nand->bank_base;
112            bank_base += JZ_NAND_MEM_CMD_OFFSET;
113        chip->IO_ADDR_W = bank_base;
90114
91115        reg = readl(nand->base + JZ_REG_NAND_CTRL);
92116        if (ctrl & NAND_NCE)
93            reg |= JZ_NAND_CTRL_ASSERT_CHIP(0);
117            reg |= JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_chip);
94118        else
95            reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0);
119            reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_chip);
96120        writel(reg, nand->base + JZ_REG_NAND_CTRL);
97121    }
98122    if (dat != NAND_CMD_NONE)
...... 
299323#endif
300324
301325static int jz_nand_ioremap_resource(struct platform_device *pdev,
302    const char *name, struct resource **res, void __iomem **base)
326    const char *name, struct resource **res, void *__iomem *base)
303327{
304328    int ret;
305329
...... 
335359    return ret;
336360}
337361
362static inline void jz_nand_iounmap_resource(struct resource *res, void __iomem *base)
363{
364    iounmap(base);
365    release_mem_region(res->start, resource_size(res));
366}
367
368static int jz_nand_ioremap_banks(struct platform_device *pdev,
369    struct jz_nand *nand, unsigned char *banks, size_t num_banks)
370{
371    int ret;
372    char name[6];
373    int i;
374
375    for (i = 0; i < num_banks; ++i) {
376        sprintf(name, "bank%d", banks[i]);
377
378        ret = jz_nand_ioremap_resource(pdev, name, &nand->bank_mem[i],
379            &nand->bank_base[i]);
380
381        if (ret)
382            goto err;
383    }
384
385    return 0;
386err:
387    for (--i; i >= 0; --i)
388        jz_nand_iounmap_resource(nand->bank_mem[i], nand->bank_base[i]);
389
390    return ret;
391}
392
338393static int __devinit jz_nand_probe(struct platform_device *pdev)
339394{
340395    int ret;
...... 
346401    struct mtd_partition *partition_info;
347402    int num_partitions = 0;
348403#endif
404    size_t num_banks, i;
405    unsigned char bank;
406    uint32_t ctrl;
349407
350408    nand = kzalloc(sizeof(*nand), GFP_KERNEL);
351409    if (!nand) {
...... 
356414    ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base);
357415    if (ret)
358416        goto err_free;
359    ret = jz_nand_ioremap_resource(pdev, "bank", &nand->bank_mem,
360            &nand->bank_base);
361    if (ret)
362        goto err_iounmap_mmio;
363417
364418    if (pdata && gpio_is_valid(pdata->busy_gpio)) {
365419        ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
...... 
367421            dev_err(&pdev->dev,
368422                "Failed to request busy gpio %d: %d\n",
369423                pdata->busy_gpio, ret);
370            goto err_iounmap_mem;
424            goto err_iounmap_mmio;
371425        }
372426    }
373427
...... 
392446
393447    chip->chip_delay = 50;
394448    chip->cmd_ctrl = jz_nand_cmd_ctrl;
449    chip->select_chip = jz_nand_select_chip;
395450
396451    if (pdata && gpio_is_valid(pdata->busy_gpio))
397452        chip->dev_ready = jz_nand_dev_ready;
398453
399    chip->IO_ADDR_R = nand->bank_base;
400    chip->IO_ADDR_W = nand->bank_base;
401
402454    nand->pdata = pdata;
403455    platform_set_drvdata(pdev, nand);
404456
405    writel(JZ_NAND_CTRL_ENABLE_CHIP(0), nand->base + JZ_REG_NAND_CTRL);
457    if (pdata->banks[0] == 0)
458        pdata->banks[0] = 1;
459
460    ctrl = 0;
461    for (num_banks = 0; num_banks < 4 ; ++num_banks) {
462        bank = pdata->banks[num_banks];
463        if (bank == 0)
464            break;
465        if (bank > 4) {
466            ret = -EINVAL;
467            goto err_gpio_free;
468        }
469
470        ctrl |= JZ_NAND_CTRL_ENABLE_CHIP(bank - 1);
471    }
406472
407    ret = nand_scan_ident(mtd, 1);
473    ret = jz_nand_ioremap_banks(pdev, nand, pdata->banks, num_banks);
474    if (ret)
475        goto err_gpio_free;
476
477    chip->IO_ADDR_R = nand->bank_base[pdata->banks[0] - 1];
478    chip->IO_ADDR_W = nand->bank_base[pdata->banks[0] - 1];
479
480    writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
481
482    ret = nand_scan_ident(mtd, num_banks);
408483    if (ret) {
409484        dev_err(&pdev->dev, "Failed to scan nand\n");
410        goto err_gpio_free;
485        goto err_iounmap_banks;
411486    }
412487
413488    if (pdata && pdata->ident_callback) {
...... 
418493    ret = nand_scan_tail(mtd);
419494    if (ret) {
420495        dev_err(&pdev->dev, "Failed to scan nand\n");
421        goto err_gpio_free;
496        goto err_iounmap_banks;
422497    }
423498
424499#ifdef CONFIG_MTD_PARTITIONS
...... 
448523
449524err_nand_release:
450525    nand_release(&nand->mtd);
526err_iounmap_banks:
527    for (i = 0; i < num_banks; ++i)
528        jz_nand_iounmap_resource(nand->bank_mem[i], nand->bank_base[i]);
451529err_gpio_free:
452530    platform_set_drvdata(pdev, NULL);
453531    gpio_free(pdata->busy_gpio);
454err_iounmap_mem:
455    iounmap(nand->bank_base);
456532err_iounmap_mmio:
457533    iounmap(nand->base);
458534err_free:
...... 
463539static int __devexit jz_nand_remove(struct platform_device *pdev)
464540{
465541    struct jz_nand *nand = platform_get_drvdata(pdev);
542    int i;
466543
467544    nand_release(&nand->mtd);
468545
469546    /* Deassert and disable all chips */
470547    writel(0, nand->base + JZ_REG_NAND_CTRL);
471548
472    iounmap(nand->bank_base);
473    release_mem_region(nand->bank_mem->start, resource_size(nand->bank_mem));
474    iounmap(nand->base);
475    release_mem_region(nand->mem->start, resource_size(nand->mem));
549    i = 0;
550    do {
551        jz_nand_iounmap_resource(nand->bank_mem[i], nand->bank_base[i]);
552        ++i;
553    } while (nand->bank_base[i] != 0 && i < 4);
554
555    jz_nand_iounmap_resource(nand->mem, nand->base);
476556
477557    platform_set_drvdata(pdev, NULL);
478558    kfree(nand);

Archive Download the corresponding diff file



interactive