Root/target/linux/ar71xx/files/drivers/mtd/nand/rb750_nand.c

1/*
2 * NAND flash driver for the MikroTik RouterBOARD 750
3 *
4 * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 */
10
11#include <linux/init.h>
12#include <linux/mtd/nand.h>
13#include <linux/mtd/mtd.h>
14#include <linux/mtd/partitions.h>
15#include <linux/platform_device.h>
16#include <linux/io.h>
17
18#include <asm/mach-ar71xx/ar71xx.h>
19#include <asm/mach-ar71xx/mach-rb750.h>
20
21#define DRV_NAME "rb750-nand"
22#define DRV_VERSION "0.1.0"
23#define DRV_DESC "NAND flash driver for the RouterBOARD 750"
24
25#define RB750_NAND_IO0 BIT(RB750_GPIO_NAND_IO0)
26#define RB750_NAND_ALE BIT(RB750_GPIO_NAND_ALE)
27#define RB750_NAND_CLE BIT(RB750_GPIO_NAND_CLE)
28#define RB750_NAND_NRE BIT(RB750_GPIO_NAND_NRE)
29#define RB750_NAND_NWE BIT(RB750_GPIO_NAND_NWE)
30#define RB750_NAND_RDY BIT(RB750_GPIO_NAND_RDY)
31#define RB750_NAND_NCE BIT(RB750_GPIO_NAND_NCE)
32
33#define RB750_NAND_DATA_SHIFT 1
34#define RB750_NAND_DATA_BITS (0xff << RB750_NAND_DATA_SHIFT)
35#define RB750_NAND_INPUT_BITS (RB750_NAND_DATA_BITS | RB750_NAND_RDY)
36#define RB750_NAND_OUTPUT_BITS (RB750_NAND_ALE | RB750_NAND_CLE | \
37                 RB750_NAND_NRE | RB750_NAND_NWE | \
38                 RB750_NAND_NCE)
39
40struct rb750_nand_info {
41    struct nand_chip chip;
42    struct mtd_info mtd;
43};
44
45/*
46 * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader
47 * will not be able to find the kernel that we load.
48 */
49static struct nand_ecclayout rb750_nand_ecclayout = {
50    .eccbytes = 6,
51    .eccpos = { 8, 9, 10, 13, 14, 15 },
52    .oobavail = 9,
53    .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
54};
55
56static struct mtd_partition rb750_nand_partitions[] = {
57    {
58        .name = "booter",
59        .offset = 0,
60        .size = (256 * 1024),
61        .mask_flags = MTD_WRITEABLE,
62    }, {
63        .name = "kernel",
64        .offset = (256 * 1024),
65        .size = (4 * 1024 * 1024) - (256 * 1024),
66    }, {
67        .name = "rootfs",
68        .offset = MTDPART_OFS_NXTBLK,
69        .size = MTDPART_SIZ_FULL,
70    },
71};
72
73static void rb750_nand_write(const u8 *buf, unsigned len)
74{
75    void __iomem *base = ar71xx_gpio_base;
76    u32 out;
77    unsigned i;
78
79    /* set data lines to output mode */
80    __raw_writel(__raw_readl(base + GPIO_REG_OE) | RB750_NAND_DATA_BITS,
81             base + GPIO_REG_OE);
82
83    out = __raw_readl(base + GPIO_REG_OUT);
84    out &= ~(RB750_NAND_DATA_BITS | RB750_NAND_NWE);
85    for (i = 0; i != len; i++) {
86        u32 data;
87
88        data = buf[i];
89        data <<= RB750_NAND_DATA_SHIFT;
90        data |= out;
91        __raw_writel(data, base + GPIO_REG_OUT);
92
93        __raw_writel(data | RB750_NAND_NWE, base + GPIO_REG_OUT);
94        /* flush write */
95        __raw_readl(base + GPIO_REG_OUT);
96    }
97
98    /* set data lines to input mode */
99    __raw_writel(__raw_readl(base + GPIO_REG_OE) & ~RB750_NAND_DATA_BITS,
100             base + GPIO_REG_OE);
101    /* flush write */
102    __raw_readl(base + GPIO_REG_OE);
103}
104
105static int rb750_nand_read_verify(u8 *read_buf, unsigned len,
106                  const u8 *verify_buf)
107{
108    void __iomem *base = ar71xx_gpio_base;
109    unsigned i;
110
111    for (i = 0; i < len; i++) {
112        u8 data;
113
114        /* activate RE line */
115        __raw_writel(RB750_NAND_NRE, base + GPIO_REG_CLEAR);
116        /* flush write */
117        __raw_readl(base + GPIO_REG_CLEAR);
118
119        /* read input lines */
120        data = __raw_readl(base + GPIO_REG_IN) >> RB750_NAND_DATA_SHIFT;
121
122        /* deactivate RE line */
123        __raw_writel(RB750_NAND_NRE, base + GPIO_REG_SET);
124
125        if (read_buf)
126            read_buf[i] = data;
127        else if (verify_buf && verify_buf[i] != data)
128            return -EFAULT;
129    }
130
131    return 0;
132}
133
134static void rb750_nand_select_chip(struct mtd_info *mtd, int chip)
135{
136    void __iomem *base = ar71xx_gpio_base;
137    u32 func;
138
139    func = __raw_readl(base + GPIO_REG_FUNC);
140    if (chip >= 0) {
141        /* disable latch */
142        rb750_latch_change(RB750_LVC573_LE, 0);
143
144        /* disable alternate functions */
145        ar71xx_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE,
146                       AR724X_GPIO_FUNC_SPI_EN);
147
148        /* set input mode for data lines */
149        __raw_writel(__raw_readl(base + GPIO_REG_OE) &
150                 ~RB750_NAND_INPUT_BITS,
151                 base + GPIO_REG_OE);
152
153        /* deactivate RE and WE lines */
154        __raw_writel(RB750_NAND_NRE | RB750_NAND_NWE,
155                 base + GPIO_REG_SET);
156        /* flush write */
157        (void) __raw_readl(base + GPIO_REG_SET);
158
159        /* activate CE line */
160        __raw_writel(RB750_NAND_NCE, base + GPIO_REG_CLEAR);
161    } else {
162        /* deactivate CE line */
163        __raw_writel(RB750_NAND_NCE, base + GPIO_REG_SET);
164        /* flush write */
165        (void) __raw_readl(base + GPIO_REG_SET);
166
167        __raw_writel(__raw_readl(base + GPIO_REG_OE) |
168                 RB750_NAND_IO0 | RB750_NAND_RDY,
169                 base + GPIO_REG_OE);
170
171        /* restore alternate functions */
172        ar71xx_gpio_function_setup(AR724X_GPIO_FUNC_SPI_EN,
173                       AR724X_GPIO_FUNC_JTAG_DISABLE);
174
175        /* enable latch */
176        rb750_latch_change(0, RB750_LVC573_LE);
177    }
178}
179
180static int rb750_nand_dev_ready(struct mtd_info *mtd)
181{
182    void __iomem *base = ar71xx_gpio_base;
183
184    return !!(__raw_readl(base + GPIO_REG_IN) & RB750_NAND_RDY);
185}
186
187static void rb750_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
188                unsigned int ctrl)
189{
190    if (ctrl & NAND_CTRL_CHANGE) {
191        void __iomem *base = ar71xx_gpio_base;
192        u32 t;
193
194        t = __raw_readl(base + GPIO_REG_OUT);
195
196        t &= ~(RB750_NAND_CLE | RB750_NAND_ALE);
197        t |= (ctrl & NAND_CLE) ? RB750_NAND_CLE : 0;
198        t |= (ctrl & NAND_ALE) ? RB750_NAND_ALE : 0;
199
200        __raw_writel(t, base + GPIO_REG_OUT);
201        /* flush write */
202        __raw_readl(base + GPIO_REG_OUT);
203    }
204
205    if (cmd != NAND_CMD_NONE) {
206        u8 t = cmd;
207        rb750_nand_write(&t, 1);
208    }
209}
210
211static u8 rb750_nand_read_byte(struct mtd_info *mtd)
212{
213    u8 data = 0;
214    rb750_nand_read_verify(&data, 1, NULL);
215    return data;
216}
217
218static void rb750_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
219{
220    rb750_nand_read_verify(buf, len, NULL);
221}
222
223static void rb750_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
224{
225    rb750_nand_write(buf, len);
226}
227
228static int rb750_nand_verify_buf(struct mtd_info *mtd, const u8 *buf, int len)
229{
230    return rb750_nand_read_verify(NULL, len, buf);
231}
232
233static void __init rb750_nand_gpio_init(void)
234{
235    void __iomem *base = ar71xx_gpio_base;
236    u32 out;
237
238    out = __raw_readl(base + GPIO_REG_OUT);
239
240    /* setup output levels */
241    __raw_writel(RB750_NAND_NCE | RB750_NAND_NRE | RB750_NAND_NWE,
242             base + GPIO_REG_SET);
243
244    __raw_writel(RB750_NAND_ALE | RB750_NAND_CLE,
245             base + GPIO_REG_CLEAR);
246
247    /* setup input lines */
248    __raw_writel(__raw_readl(base + GPIO_REG_OE) & ~(RB750_NAND_INPUT_BITS),
249             base + GPIO_REG_OE);
250
251    /* setup output lines */
252    __raw_writel(__raw_readl(base + GPIO_REG_OE) | RB750_NAND_OUTPUT_BITS,
253             base + GPIO_REG_OE);
254
255    rb750_latch_change(~out & RB750_NAND_IO0, out & RB750_NAND_IO0);
256}
257
258static int __init rb750_nand_probe(struct platform_device *pdev)
259{
260    struct rb750_nand_info *info;
261    int ret;
262
263    printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n");
264
265    rb750_nand_gpio_init();
266
267    info = kzalloc(sizeof(*info), GFP_KERNEL);
268    if (!info)
269        return -ENOMEM;
270
271    info->chip.priv = &info;
272    info->mtd.priv = &info->chip;
273    info->mtd.owner = THIS_MODULE;
274
275    info->chip.select_chip = rb750_nand_select_chip;
276    info->chip.cmd_ctrl = rb750_nand_cmd_ctrl;
277    info->chip.dev_ready = rb750_nand_dev_ready;
278    info->chip.read_byte = rb750_nand_read_byte;
279    info->chip.write_buf = rb750_nand_write_buf;
280    info->chip.read_buf = rb750_nand_read_buf;
281    info->chip.verify_buf = rb750_nand_verify_buf;
282
283    info->chip.chip_delay = 25;
284    info->chip.ecc.mode = NAND_ECC_SOFT;
285    info->chip.options |= NAND_NO_AUTOINCR;
286
287    platform_set_drvdata(pdev, info);
288
289    ret = nand_scan_ident(&info->mtd, 1);
290    if (ret) {
291        ret = -ENXIO;
292        goto err_free_info;
293    }
294
295    if (info->mtd.writesize == 512)
296        info->chip.ecc.layout = &rb750_nand_ecclayout;
297
298    ret = nand_scan_tail(&info->mtd);
299    if (ret) {
300        return -ENXIO;
301        goto err_set_drvdata;
302    }
303
304#ifdef CONFIG_MTD_PARTITIONS
305    ret = add_mtd_partitions(&info->mtd, rb750_nand_partitions,
306                 ARRAY_SIZE(rb750_nand_partitions));
307#else
308    ret = add_mtd_device(&info->mtd);
309#endif
310    if (ret)
311        goto err_release_nand;
312
313    return 0;
314
315 err_release_nand:
316    nand_release(&info->mtd);
317 err_set_drvdata:
318    platform_set_drvdata(pdev, NULL);
319 err_free_info:
320    kfree(info);
321    return ret;
322}
323
324static int __devexit rb750_nand_remove(struct platform_device *pdev)
325{
326    struct rb750_nand_info *info = platform_get_drvdata(pdev);
327
328    nand_release(&info->mtd);
329    platform_set_drvdata(pdev, NULL);
330    kfree(info);
331
332    return 0;
333}
334
335static struct platform_driver rb750_nand_driver = {
336    .probe = rb750_nand_probe,
337    .remove = __devexit_p(rb750_nand_remove),
338    .driver = {
339        .name = DRV_NAME,
340        .owner = THIS_MODULE,
341    },
342};
343
344static int __init rb750_nand_init(void)
345{
346    return platform_driver_register(&rb750_nand_driver);
347}
348
349static void __exit rb750_nand_exit(void)
350{
351    platform_driver_unregister(&rb750_nand_driver);
352}
353
354module_init(rb750_nand_init);
355module_exit(rb750_nand_exit);
356
357MODULE_DESCRIPTION(DRV_DESC);
358MODULE_VERSION(DRV_VERSION);
359MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
360MODULE_LICENSE("GPL v2");
361

Archive Download this file



interactive