source: src/linux/universal/linux-4.9/drivers/mtd/nand/ath_nand.c @ 31646

Last change on this file since 31646 was 31646, checked in by brainslayer, 13 days ago

its big endian

File size: 43.1 KB
Line 
1/*
2 * linux/drivers/mtd/nand/ath_nand.c
3 * vim: tabstop=8 : noexpandtab
4 * Derived from alauda.c
5 */
6#include <linux/module.h>
7#include <linux/types.h>
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/string.h>
11#include <linux/ioport.h>
12#include <linux/platform_device.h>
13#include <linux/delay.h>
14#include <linux/dma-mapping.h>
15#include <linux/err.h>
16#include <linux/slab.h>
17#include <linux/io.h>
18#include <linux/bitops.h>
19#include <linux/jiffies.h>
20
21#include <linux/mtd/mtd.h>
22#include <linux/mtd/nand.h>
23#include <linux/mtd/nand_ecc.h>
24#include <linux/mtd/partitions.h>
25#include <linux/magic.h>
26
27#include <asm/cacheflush.h>
28#include "../mtdcore.h"
29#include "934x.h"
30
31typedef unsigned int ath_reg_t;
32
33#define ath_reg_rd(_phys)       (*(volatile ath_reg_t *)KSEG1ADDR(_phys))
34
35#define ath_reg_wr_nf(_phys, _val) \
36        ((*(volatile ath_reg_t *)KSEG1ADDR(_phys)) = (_val))
37
38#define ath_reg_wr(_phys, _val) do {    \
39        ath_reg_wr_nf(_phys, _val);     \
40        ath_reg_rd(_phys);              \
41} while(0)
42
43#define ath_reg_rmw_set(_reg, _mask)    do {                    \
44        ath_reg_wr((_reg), (ath_reg_rd((_reg)) | (_mask)));     \
45        ath_reg_rd((_reg));                                     \
46} while(0)
47
48#define ath_reg_rmw_clear(_reg, _mask) do {                     \
49        ath_reg_wr((_reg), (ath_reg_rd((_reg)) & ~(_mask)));    \
50        ath_reg_rd((_reg));                                     \
51} while(0)
52
53
54#define DRV_NAME        "ath-nand"
55#define DRV_VERSION     "0.1"
56#define DRV_AUTHOR      "Atheros"
57#define DRV_DESC        "Atheros on-chip NAND FLash Controller Driver"
58
59#define ATH_NF_COMMAND          (ATH_NAND_FLASH_BASE + 0x200u)
60#define ATH_NF_CTRL             (ATH_NAND_FLASH_BASE + 0x204u)
61#define ATH_NF_STATUS           (ATH_NAND_FLASH_BASE + 0x208u)
62#define ATH_NF_INT_MASK         (ATH_NAND_FLASH_BASE + 0x20cu)
63#define ATH_NF_INT_STATUS       (ATH_NAND_FLASH_BASE + 0x210u)
64#define ATH_NF_ECC_CTRL         (ATH_NAND_FLASH_BASE + 0x214u)
65#define ATH_NF_ECC_OFFSET       (ATH_NAND_FLASH_BASE + 0x218u)
66#define ATH_NF_ADDR0_0          (ATH_NAND_FLASH_BASE + 0x21cu)
67#define ATH_NF_ADDR1_0          (ATH_NAND_FLASH_BASE + 0x220u)
68#define ATH_NF_ADDR0_1          (ATH_NAND_FLASH_BASE + 0x224u)
69#define ATH_NF_ADDR1_1          (ATH_NAND_FLASH_BASE + 0x228u)
70#define ATH_NF_SPARE_SIZE       (ATH_NAND_FLASH_BASE + 0x230u)
71#define ATH_NF_PROTECT          (ATH_NAND_FLASH_BASE + 0x238u)
72#define ATH_NF_LOOKUP_EN        (ATH_NAND_FLASH_BASE + 0x240u)
73#define ATH_NF_LOOKUP0          (ATH_NAND_FLASH_BASE + 0x244u)
74#define ATH_NF_LOOKUP1          (ATH_NAND_FLASH_BASE + 0x248u)
75#define ATH_NF_LOOKUP2          (ATH_NAND_FLASH_BASE + 0x24cu)
76#define ATH_NF_LOOKUP3          (ATH_NAND_FLASH_BASE + 0x250u)
77#define ATH_NF_LOOKUP4          (ATH_NAND_FLASH_BASE + 0x254u)
78#define ATH_NF_LOOKUP5          (ATH_NAND_FLASH_BASE + 0x258u)
79#define ATH_NF_LOOKUP6          (ATH_NAND_FLASH_BASE + 0x25cu)
80#define ATH_NF_LOOKUP7          (ATH_NAND_FLASH_BASE + 0x260u)
81#define ATH_NF_DMA_ADDR         (ATH_NAND_FLASH_BASE + 0x264u)
82#define ATH_NF_DMA_COUNT        (ATH_NAND_FLASH_BASE + 0x268u)
83#define ATH_NF_DMA_CTRL         (ATH_NAND_FLASH_BASE + 0x26cu)
84#define ATH_NF_MEM_CTRL         (ATH_NAND_FLASH_BASE + 0x280u)
85#define ATH_NF_PG_SIZE          (ATH_NAND_FLASH_BASE + 0x284u)
86#define ATH_NF_RD_STATUS        (ATH_NAND_FLASH_BASE + 0x288u)
87#define ATH_NF_TIME_SEQ         (ATH_NAND_FLASH_BASE + 0x28cu)
88#define ATH_NF_TIMINGS_ASYN     (ATH_NAND_FLASH_BASE + 0x290u)
89#define ATH_NF_TIMINGS_SYN      (ATH_NAND_FLASH_BASE + 0x294u)
90#define ATH_NF_FIFO_DATA        (ATH_NAND_FLASH_BASE + 0x298u)
91#define ATH_NF_TIME_MODE        (ATH_NAND_FLASH_BASE + 0x29cu)
92#define ATH_NF_DMA_ADDR_OFFSET  (ATH_NAND_FLASH_BASE + 0x2a0u)
93#define ATH_NF_FIFO_INIT        (ATH_NAND_FLASH_BASE + 0x2b0u)
94#define ATH_NF_GENERIC_SEQ_CTRL (ATH_NAND_FLASH_BASE + 0x2b4u)
95
96#define ATH_NF_TIMING_ASYN      0x11
97#define ATH_NF_STATUS_OK        0x40    //0xc0
98#define ATH_NF_RD_STATUS_MASK   0x47    //0xc7
99
100#define ATH_NF_CTRL_SMALL_BLOCK_EN      (1 << 21)
101
102#define ATH_NF_CTRL_ADDR_CYCLE1_0       (0 << 18)
103#define ATH_NF_CTRL_ADDR_CYCLE1_1       (1 << 18)
104#define ATH_NF_CTRL_ADDR_CYCLE1_2       (2 << 18)
105#define ATH_NF_CTRL_ADDR_CYCLE1_3       (3 << 18)
106#define ATH_NF_CTRL_ADDR_CYCLE1_4       (4 << 18)
107#define ATH_NF_CTRL_ADDR_CYCLE1_5       (5 << 18)
108
109#define ATH_NF_CTRL_ADDR1_AUTO_INC_EN   (1 << 17)
110#define ATH_NF_CTRL_ADDR0_AUTO_INC_EN   (1 << 16)
111#define ATH_NF_CTRL_WORK_MODE_SYNC      (1 << 15)
112#define ATH_NF_CTRL_PROT_EN             (1 << 14)
113#define ATH_NF_CTRL_LOOKUP_EN           (1 << 13)
114#define ATH_NF_CTRL_IO_WIDTH_16BIT      (1 << 12)
115#define ATH_NF_CTRL_CUSTOM_SIZE_EN      (1 << 11)
116
117#define ATH_NF_CTRL_PAGE_SIZE_256       (0 <<  8)       /* bytes */
118#define ATH_NF_CTRL_PAGE_SIZE_512       (1 <<  8)
119#define ATH_NF_CTRL_PAGE_SIZE_1024      (2 <<  8)
120#define ATH_NF_CTRL_PAGE_SIZE_2048      (3 <<  8)
121#define ATH_NF_CTRL_PAGE_SIZE_4096      (4 <<  8)
122#define ATH_NF_CTRL_PAGE_SIZE_8192      (5 <<  8)
123#define ATH_NF_CTRL_PAGE_SIZE_16384     (6 <<  8)
124#define ATH_NF_CTRL_PAGE_SIZE_0         (7 <<  8)
125
126#define ATH_NF_CTRL_BLOCK_SIZE_32       (0 <<  6)       /* pages */
127#define ATH_NF_CTRL_BLOCK_SIZE_64       (1 <<  6)
128#define ATH_NF_CTRL_BLOCK_SIZE_128      (2 <<  6)
129#define ATH_NF_CTRL_BLOCK_SIZE_256      (3 <<  6)
130
131#define ATH_NF_CTRL_ECC_EN              (1 <<  5)
132#define ATH_NF_CTRL_INT_EN              (1 <<  4)
133#define ATH_NF_CTRL_SPARE_EN            (1 <<  3)
134
135#define ATH_NF_CTRL_ADDR_CYCLE0_0       (0 <<  0)
136#define ATH_NF_CTRL_ADDR_CYCLE0_1       (1 <<  0)
137#define ATH_NF_CTRL_ADDR_CYCLE0_2       (2 <<  0)
138#define ATH_NF_CTRL_ADDR_CYCLE0_3       (3 <<  0)
139#define ATH_NF_CTRL_ADDR_CYCLE0_4       (4 <<  0)
140#define ATH_NF_CTRL_ADDR_CYCLE0_5       (5 <<  0)
141#define ATH_NF_CTRL_ADDR_CYCLE0(c)      ((c) << 0)
142
143
144#define ATH_NF_DMA_CTRL_DMA_START       (1 << 7)
145#define ATH_NF_DMA_CTRL_DMA_DIR_WRITE   (0 << 6)
146#define ATH_NF_DMA_CTRL_DMA_DIR_READ    (1 << 6)
147#define ATH_NF_DMA_CTRL_DMA_MODE_SG     (1 << 5)
148/*
149 * 000 - incrementing precise burst of precisely four transfers
150 * 001 - stream burst (address const)
151 * 010 - single transfer (address increment)
152 * 011 - burst of unspecified length (address increment)
153 * 100 - incrementing precise burst of precisely eight transfers
154 * 101 - incrementing precise burst of precisely sixteen transfers
155 */
156#define ATH_NF_DMA_CTRL_DMA_BURST_0     (0 << 2)
157#define ATH_NF_DMA_CTRL_DMA_BURST_1     (1 << 2)
158#define ATH_NF_DMA_CTRL_DMA_BURST_2     (2 << 2)
159#define ATH_NF_DMA_CTRL_DMA_BURST_3     (3 << 2)
160#define ATH_NF_DMA_CTRL_DMA_BURST_4     (4 << 2)
161#define ATH_NF_DMA_CTRL_DMA_BURST_5     (5 << 2)
162#define ATH_NF_DMA_CTRL_ERR_FLAG        (1 << 1)
163#define ATH_NF_DMA_CTRL_DMA_READY       (1 << 0)
164
165#define ATH_NF_ECC_CTRL_ERR_THRESH(x)   ((x << 8) & (0x1fu << 8))
166#define ATH_NF_ECC_CTRL_ECC_CAP(x)      ((x << 5) & (0x07u << 5))
167#define ATH_NF_ECC_CTRL_ECC_2_BITS      ATH_NF_ECC_CTRL_ECC_CAP(0)
168#define ATH_NF_ECC_CTRL_ECC_4_BITS      ATH_NF_ECC_CTRL_ECC_CAP(1)
169#define ATH_NF_ECC_CTRL_ECC_6_BITS      ATH_NF_ECC_CTRL_ECC_CAP(2)
170#define ATH_NF_ECC_CTRL_ECC_8_BITS      ATH_NF_ECC_CTRL_ECC_CAP(3)
171#define ATH_NF_ECC_CTRL_ECC_10_BITS     ATH_NF_ECC_CTRL_ECC_CAP(4)
172#define ATH_NF_ECC_CTRL_ECC_12_BITS     ATH_NF_ECC_CTRL_ECC_CAP(5)
173#define ATH_NF_ECC_CTRL_ECC_14_BITS     ATH_NF_ECC_CTRL_ECC_CAP(6)
174#define ATH_NF_ECC_CTRL_ECC_16_BITS     ATH_NF_ECC_CTRL_ECC_CAP(7)
175
176#define ATH_NF_ECC_CTRL_ERR_OVER        (1 << 2)
177#define ATH_NF_ECC_CTRL_ERR_UNCORR      (1 << 1)
178#define ATH_NF_ECC_CTRL_ERR_CORR        (1 << 0)
179#       define ATH_NF_ECC_ERROR         (ATH_NF_ECC_CTRL_ERR_UNCORR | \
180                                         ATH_NF_ECC_CTRL_ERR_OVER)
181
182#define ATH_NF_CMD_END_INT              (1 << 1)
183
184#define ATH_NF_HW_ECC           1
185#define ATH_NF_STATUS_RETRY     1000
186
187#define ath_nand_get_cmd_end_status(void)       \
188        (ath_reg_rd(ATH_NF_INT_STATUS) & ATH_NF_CMD_END_INT)
189
190#define ath_nand_clear_int_status()     ath_reg_wr(ATH_NF_INT_STATUS, 0)
191
192#define ATH_NAND_BLK_DONT_KNOW  0x0
193#define ATH_NAND_BLK_GOOD       0x1
194#define ATH_NAND_BLK_BAD        0x2
195#define ATH_NAND_BLK_ERASED     0x3
196
197/*
198 * Note: The byte positions might not match the spec.
199 * It is to handle the endianness issues.
200 */
201#define ONFI_NUM_ADDR_CYCLES    102     /* see note */
202#define ONFI_DEV_DESC           32
203#define ONFI_DEV_DESC_SZ        32
204#define ONFI_PAGE_SIZE          80
205#define ONFI_SPARE_SIZE         86      /* see note */
206#define ONFI_PAGES_PER_BLOCK    92
207#define ONFI_BLOCKS_PER_LUN     96
208#define ONFI_NUM_LUNS           103     /* see note */
209#define ONFI_RD_PARAM_PAGE_SZ   128
210#define READ_PARAM_STATUS_OK    0x40
211#define READ_PARAM_STATUS_MASK  0x41
212
213#define ATH_NAND_IO_DBG         0
214#define ATH_NAND_OOB_DBG        0
215#define ATH_NAND_IN_DBG         0
216
217#if ATH_NAND_IO_DBG
218#       define iodbg    printk
219#else
220#       define iodbg(...)
221#endif
222
223#if ATH_NAND_OOB_DBG
224#       define oobdbg   printk
225#else
226#       define oobdbg(...)
227#endif
228
229#if ATH_NAND_IN_DBG
230#       define indbg(a, ...)                                    \
231        do {                                                    \
232                printk("--- %s(%d):" a "\n",                    \
233                        __func__, __LINE__, ## __VA_ARGS__);    \
234        } while (0)
235#else
236#       define indbg(...)
237#       define indbg1(a, ...)                                   \
238        do {                                                    \
239                printk("--- %s(%d):" a "\n",                    \
240                        __func__, __LINE__, ## __VA_ARGS__);    \
241        } while (0)
242#endif
243
244/*
245 * Data structures for ath nand flash controller driver
246 */
247
248typedef union {
249        uint8_t                 byte_id[8];
250
251        struct {
252                uint8_t         sa1     : 1,    // Serial access time (bit 1)
253                                org     : 1,    // Organisation
254                                bs      : 2,    // Block size
255                                sa0     : 1,    // Serial access time (bit 0)
256                                ss      : 1,    // Spare size per 512 bytes
257                                ps      : 2,    // Page Size
258
259                                wc      : 1,    // Write Cache
260                                ilp     : 1,    // Interleaved Programming
261                                nsp     : 2,    // No. of simult prog pages
262                                ct      : 2,    // Cell type
263                                dp      : 2,    // Die/Package
264
265                                did,            // Device id
266                                vid,            // Vendor id
267
268                                res1    : 2,    // Reserved
269                                pls     : 2,    // Plane size
270                                pn      : 2,    // Plane number
271                                res2    : 2;    // Reserved
272        } __details;
273} ath_nand_id_t;
274
275uint64_t ath_plane_size[] = {
276        64 << 20,
277         1 << 30,
278         2 << 30,
279         4 << 30,
280         8 << 30
281};
282
283typedef struct {
284        uint8_t vid,
285                did,
286                b3,
287                addrcyc,
288                pgsz,
289                blk,
290                spare;
291} ath_nand_vend_data_t;
292
293ath_nand_vend_data_t ath_nand_arr[] = {
294        { 0x20, 0xda, 0x10, 5, 3, 1, 1 },       // NU2g3B2D
295        { 0x20, 0xf1, 0x00, 4, 3, 1, 1 },       // NU1g3B2C
296        { 0x20, 0xdc, 0x10, 5, 3, 1, 1 },       // NU4g3B2D
297        { 0x20, 0xd3, 0x10, 5, 4, 1, 1 },       // NU8g3F2A
298        { 0x20, 0xd3, 0x14, 5, 3, 2, 1 },       // NU8g3C2B
299        { 0xad, 0xf1, 0x00, 4, 3, 1, 1 },       // HY1g2b
300        { 0xad, 0xda, 0x10, 5, 3, 1, 1 },       // HY2g2b
301        { 0xec, 0xf1, 0x00, 4, 3, 1, 1 },       // Samsung 3,3V 8-bit [128MB]
302        { 0x98, 0xd1, 0x90, 4, 3, 1, 1 },       // Toshiba
303        //{ 0x2c, 0x48, 0x04, 5, 4, 3, 1 },     // Micron 16GBit MLC
304};
305
306#define NUM_ARRAY_ENTRIES(a)    (sizeof((a)) / sizeof((a)[0]))
307#define NUM_ATH_NAND            NUM_ARRAY_ENTRIES(ath_nand_arr)
308
309/* ath nand info */
310typedef struct {
311        /* mtd info */
312        struct mtd_info         mtd;
313
314        /* NAND MTD partition information */
315        int                     nr_partitions;
316        struct mtd_partition    *partitions;
317
318        unsigned                *bbt;
319
320        unsigned                ba0,
321                                ba1,
322                                cmd;    // Current command
323        ath_nand_id_t           __id;   // for readid
324        uint8_t                 onfi[ONFI_RD_PARAM_PAGE_SZ];
325#if ATH_NF_HW_ECC
326        uint32_t                ecc_offset;
327#endif
328        uint32_t                nf_ctrl;
329} ath_nand_sc_t;
330
331ath_nand_sc_t *ath_nand_sc;
332static int ath_nand_hw_init(ath_nand_sc_t *, void *);
333
334#define nid     __id.__details
335#define bid     __id.byte_id
336
337static int ath_nand_block_isbad(struct mtd_info *mtd, loff_t ofs);
338
339static const char *part_probes[] __initdata = { "cmdlinepart", "RedBoot", NULL };
340
341/* max page size (16k) + oob buf size */
342uint8_t ath_nand_io_buf[24 << 10] __attribute__((aligned(4096)));
343#define get_ath_nand_io_buf()   ath_nand_io_buf
344
345void ath_nand_dump_buf(loff_t addr, void *v, unsigned count);
346
347#define micron_debug            0
348
349#if micron_debug
350#define ATH_DEBUG_FS_SIZE       (7 << 20)
351#define ATH_DEBUG_PG_SIZE       (2 << 10)
352#define ATH_DEBUG_SP_SIZE       (64)
353#define ATH_DEBUG_NUM_PAGES     (ATH_DEBUG_FS_SIZE / ATH_DEBUG_PG_SIZE)
354
355#define fs_offset(o)            ((o) - 0xa80000u)
356#define off_to_page(o)          ((fs_offset(o) / ATH_DEBUG_PG_SIZE) * ATH_DEBUG_SP_SIZE)
357uint8_t ath_dbg_fs[ATH_DEBUG_FS_SIZE],
358        ath_dbg_fs_spare[ATH_DEBUG_NUM_PAGES * ATH_DEBUG_SP_SIZE];
359
360loff_t  ath_dbg_last, ath_dbg_last_spare;
361
362static void inline
363ath_dbg_dump_to_fs(loff_t ofs, uint8_t *buf)
364{
365        ath_dbg_last = ofs;
366        memcpy(ath_dbg_fs + fs_offset(ofs), buf, ATH_DEBUG_PG_SIZE);
367        printk(KERN_DEBUG "===== 0x%llx %p %p\n", ofs, ath_dbg_fs + fs_offset(ofs), buf);
368}
369
370static void inline
371ath_dbg_dump_to_fs_spare(loff_t ofs, uint8_t *buf)
372{
373        ath_dbg_last_spare = ofs;
374        memcpy(ath_dbg_fs_spare + off_to_page(ofs), buf, ATH_DEBUG_SP_SIZE);
375        //printk("----- 0x%llx %p %p\n", ofs, ath_dbg_fs_spare + off_to_page(ofs), buf);
376}
377#else
378#define ath_dbg_dump_to_fs(...)         /* nothing */
379#define ath_dbg_dump_to_fs_spare(...)   /* nothing */
380#endif
381
382#define bbt_index       (sizeof(*sc->bbt) * 8 / 2)
383
384inline unsigned
385ath_nand_get_blk_state(struct mtd_info *mtd, loff_t b)
386{
387        unsigned                x, y;
388        ath_nand_sc_t           *sc = mtd->priv;
389
390        if (!sc->bbt)   return ATH_NAND_BLK_DONT_KNOW;
391
392        b = b >> mtd->erasesize_shift;
393
394        x = b / bbt_index;
395        y = b % bbt_index;
396
397        return (sc->bbt[x] >> (y * 2)) & 0x3;
398}
399
400inline void
401ath_nand_set_blk_state(struct mtd_info *mtd, loff_t b, unsigned state)
402{
403        unsigned                x, y;
404        ath_nand_sc_t           *sc = mtd->priv;
405
406        if (!sc->bbt)   return;
407
408        b = b >> mtd->erasesize_shift;
409
410        x = b / bbt_index;
411        y = b % bbt_index;
412
413        sc->bbt[x] = (sc->bbt[x] & ~(3 << (y * 2))) | (state << (y * 2));
414}
415
416static unsigned
417ath_nand_status(ath_nand_sc_t *sc, unsigned *ecc)
418{
419        unsigned        rddata, i, j, dmastatus;
420
421        rddata = ath_reg_rd(ATH_NF_STATUS);
422        for (i = 0; i < ATH_NF_STATUS_RETRY && rddata != 0xff; i++) {
423                udelay(25);
424                rddata = ath_reg_rd(ATH_NF_STATUS);
425        }
426
427        dmastatus = ath_reg_rd(ATH_NF_DMA_CTRL);
428        for (j = 0; j < ATH_NF_STATUS_RETRY && !(dmastatus & 1); j++) {
429                udelay(25);
430                dmastatus = ath_reg_rd(ATH_NF_DMA_CTRL);
431        }
432
433        if ((i == ATH_NF_STATUS_RETRY) || (j == ATH_NF_STATUS_RETRY)) {
434                //printk("ath_nand_status: i = %u j = %u\n", i, j);
435                ath_nand_hw_init(sc, NULL);
436                return -1;
437        }
438        if (ecc) {
439                *ecc = ath_reg_rd(ATH_NF_ECC_CTRL);
440        }
441        ath_nand_clear_int_status();
442        ath_reg_wr(ATH_NF_COMMAND, 0x07024);    // READ STATUS
443        while (ath_nand_get_cmd_end_status() == 0);
444        rddata = ath_reg_rd(ATH_NF_RD_STATUS);
445
446        return rddata;
447}
448
449static unsigned
450ath_check_all_0xff(ath_nand_sc_t *sc, unsigned addr0, unsigned addr1)
451{
452        uint8_t         *pa, *buf = ath_nand_io_buf, *end;
453        struct mtd_info *mtd = &sc->mtd;
454        unsigned        i, count = mtd->writesize + mtd->oobsize;
455
456        /*
457         * The same buf is being dma_(un)map_singled.
458         * Hope that is ok!
459         */
460        ath_nand_clear_int_status();
461        ath_reg_wr(ATH_NF_ADDR0_0, addr0);
462        ath_reg_wr(ATH_NF_ADDR0_1, addr1);
463        ath_reg_wr(ATH_NF_DMA_COUNT, count);
464        ath_reg_wr(ATH_NF_DMA_CTRL, ATH_NF_DMA_CTRL_DMA_START |
465                                ATH_NF_DMA_CTRL_DMA_DIR_READ |
466                                ATH_NF_DMA_CTRL_DMA_BURST_3);
467        ath_reg_wr(ATH_NF_ECC_OFFSET, 0);
468        ath_reg_wr(ATH_NF_ECC_CTRL, 0);
469        ath_reg_wr(ATH_NF_CTRL, sc->nf_ctrl | ATH_NF_CTRL_CUSTOM_SIZE_EN);
470        ath_reg_wr(ATH_NF_PG_SIZE, count);
471        pa = (uint8_t *)dma_map_single(NULL, buf, count, DMA_FROM_DEVICE);
472        ath_reg_wr(ATH_NF_DMA_ADDR, (unsigned)pa);
473        ath_reg_wr(ATH_NF_COMMAND, 0x30006a);   // Read page
474        while (ath_nand_get_cmd_end_status() == 0);
475        udelay(1000);
476        i = ath_nand_status(sc, NULL) & ATH_NF_RD_STATUS_MASK;
477        dma_unmap_single(NULL, (dma_addr_t)pa, count, DMA_FROM_DEVICE);
478        if (i != ATH_NF_STATUS_OK) {
479                return 0;
480        }
481        end = buf + count;
482        for (buf += sc->ecc_offset; (*buf == 0xff) && buf != end; buf ++);
483
484        if (buf == end) {
485                /* This page was read without ECC. From the spare area
486                 * content we see that it a blank page (i.e. full 0xff).
487                 * To take care of bit flips if any, force 0xff on it.
488                 */
489                memset(ath_nand_io_buf, 0xff, mtd->writesize);
490        } else {
491                printk("%p %p %p 0x%x\n", ath_nand_io_buf, buf, end, count);
492                ath_nand_dump_buf(addr0, ath_nand_io_buf, mtd->writesize + mtd->oobsize);
493        }
494        return (buf == end);
495}
496
497static unsigned
498ath_nand_rw_page(ath_nand_sc_t *sc, int rd, unsigned addr0, unsigned addr1, unsigned count, unsigned char *buf, unsigned ecc_needed)
499{
500        unsigned        ecc, i = 0, tmp, rddata, all_0xff = 0;
501#if ATH_NF_HW_ECC
502        unsigned        mlc_retry = 0;
503#endif
504        char            *err[] = { "Write", "Read" };
505#define ATH_MAX_RETRY   25
506#define ATH_MLC_RETRY   3
507retry:
508        ecc = 0;
509        ath_nand_clear_int_status();
510        ath_reg_wr(ATH_NF_ADDR0_0, addr0);
511        ath_reg_wr(ATH_NF_ADDR0_1, addr1);
512        ath_reg_wr(ATH_NF_DMA_ADDR, (unsigned)buf);
513        ath_reg_wr(ATH_NF_DMA_COUNT, count);
514
515        {
516                unsigned x0, x1;
517                x0 = ath_reg_rd(ATH_NF_ADDR0_0);
518                x1 = ath_reg_rd(ATH_NF_ADDR0_1);
519
520                if (x0 != addr0 || x1 != addr1) {
521                        printk("=== reg write failed buf = %p ===\n", buf);
522                        printk("%s: 0x%x 0x%x, 0x%x 0x%x\n", __func__,
523                                        x0, x1, addr0, addr1);
524                        printk("========================\n");
525                        panic("Register writes to NAND failed\n");
526                }
527        }
528#if ATH_NF_HW_ECC
529        if (ecc_needed && sc->ecc_offset && (count & sc->mtd.writesize_mask) == 0) {
530                /*
531                 * ECC can operate only on the device's pages.
532                 * Cannot be used for non-page-sized read/write
533                 */
534                ath_reg_wr(ATH_NF_ECC_OFFSET, sc->ecc_offset);
535                ath_reg_wr(ATH_NF_ECC_CTRL, ATH_NF_ECC_CTRL_ERR_THRESH(4) |
536                                                ATH_NF_ECC_CTRL_ECC_4_BITS);
537                ath_reg_wr(ATH_NF_CTRL, sc->nf_ctrl | ATH_NF_CTRL_ECC_EN);
538                ath_reg_wr(ATH_NF_SPARE_SIZE, sc->mtd.oobsize);
539        } else
540#endif
541        {
542                ath_reg_wr(ATH_NF_ECC_OFFSET, 0);
543                ath_reg_wr(ATH_NF_ECC_CTRL, 0);
544                ath_reg_wr(ATH_NF_CTRL, sc->nf_ctrl | ATH_NF_CTRL_CUSTOM_SIZE_EN);
545                ath_reg_wr(ATH_NF_PG_SIZE, count);
546        }
547
548        if (rd) {       // Read Page
549                ath_reg_wr(ATH_NF_DMA_CTRL,
550                                        ATH_NF_DMA_CTRL_DMA_START |
551                                        ATH_NF_DMA_CTRL_DMA_DIR_READ |
552                                        ATH_NF_DMA_CTRL_DMA_BURST_3);
553                ath_reg_wr(ATH_NF_COMMAND, 0x30006a);
554        } else {        // Write Page
555                ath_reg_wr(ATH_NF_MEM_CTRL, 0xff00);    // Remove write protect
556                ath_reg_wr(ATH_NF_DMA_CTRL,
557                                        ATH_NF_DMA_CTRL_DMA_START |
558                                        ATH_NF_DMA_CTRL_DMA_DIR_WRITE |
559                                        ATH_NF_DMA_CTRL_DMA_BURST_3);
560                ath_reg_wr(ATH_NF_COMMAND, 0x10804c);
561        }
562
563        while (ath_nand_get_cmd_end_status() == 0);
564
565        //printk(KERN_DEBUG "%s(%c): 0x%x 0x%x 0x%x 0x%p\n", __func__,
566        //      rd ? 'r' : 'w', addr0, addr1, count, buf);
567        udelay(1000);
568        rddata = (tmp = ath_nand_status(sc, &ecc)) & ATH_NF_RD_STATUS_MASK;
569        if ((rddata != ATH_NF_STATUS_OK)) { // && (i < ATH_MAX_RETRY))
570                i++;
571                if ((i % 100) == 0) {
572                        printk("%s: retry %u\n", __func__, i);
573                }
574                goto retry;
575        }
576
577        ath_reg_wr(ATH_NF_MEM_CTRL, 0x0000);    // Enable write protect
578        ath_reg_wr(ATH_NF_FIFO_INIT, 1);
579        ath_reg_wr(ATH_NF_FIFO_INIT, 0);
580
581        if (rddata != ATH_NF_STATUS_OK) {
582                printk("%s: %s Failed. tmp = 0x%x, status = 0x%x 0x%x retries = %d\n", __func__,
583                        err[rd], tmp, rddata, ath_reg_rd(ATH_NF_DMA_CTRL), i);
584        }
585#if ATH_NF_HW_ECC
586        else {
587#define DDR_WB_FLUSH_USB_ADDRESS                0x180000a4
588
589                ath_reg_wr(DDR_WB_FLUSH_USB_ADDRESS, 1);
590                while (ath_reg_rd(DDR_WB_FLUSH_USB_ADDRESS) & 1);
591                udelay(50);
592
593                if (ecc_needed && (ecc & ATH_NF_ECC_ERROR)) {
594                        if (rd && all_0xff == 0) {
595                                all_0xff = 1;
596                                //printk("------- ath_check_all_0xff called for 0x%x 0x%x\n", addr1, addr0);
597                                if (ath_check_all_0xff(sc, addr0, addr1)) {
598                                        return ATH_NF_STATUS_OK;
599                                }
600                        }
601
602                        if (mlc_retry < ATH_MLC_RETRY) {
603                                mlc_retry ++;
604                                i = 0;
605                                goto retry;
606                        } else {
607                                printk("%s: %s uncorrectable errors. 0x%x %x ecc = 0x%x\n",
608                                        __func__, err[rd], addr0, addr1, ecc);
609                                return -1;
610                        }
611                }
612        }
613#endif
614        return rddata;
615}
616
617void
618ath_nand_dump_buf(loff_t addr, void *v, unsigned count)
619{
620        unsigned        *buf = v,
621                        *end = buf + (count / sizeof(*buf));
622
623        iodbg("____ Dumping %d bytes at 0x%p 0x%llx_____\n", count, buf, addr);
624
625        for (; buf && buf < end; buf += 4, addr += 16) {
626                iodbg("%08llx: %08x %08x %08x %08x\n",
627                        addr, buf[0], buf[1], buf[2], buf[3]);
628        }
629        iodbg("___________________________________\n");
630        //while(1);
631}
632
633static int
634ath_nand_rw_buff(struct mtd_info *mtd, int rd, uint8_t *buff,
635                loff_t addr, size_t len, size_t *iodone)
636{
637        unsigned        iolen, ret = ATH_NF_STATUS_OK, dir;
638        unsigned char   *pa;
639        ath_nand_sc_t   *sc = mtd->priv;
640        uint8_t         *buf = get_ath_nand_io_buf();
641
642        *iodone = 0;
643
644        dir = rd ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
645
646        while (len) {
647                unsigned c, ba0, ba1;
648
649                if (ath_nand_block_isbad(mtd, addr)) {
650                        //printk("Skipping bad block[0x%x]\n", (unsigned)addr);
651                        addr += mtd->erasesize;
652                        continue;
653                }
654
655                c = (addr & mtd->writesize_mask);
656
657                /*
658                 * addr format:
659                 * a0 - a11 - xxxx - a19 - a27 == 32 bits, will be in ba0
660                 * a28 - a31 - xxxxxxxxxxxxxxxx == 4 bits, will be in ba1 in lsb
661                 */
662
663                ba0 = ((addr >> mtd->writesize_shift) << 16);
664                ba1 = ((addr >> (mtd->writesize_shift + 16)) & 0xf);
665
666                if (c) {
667                        iolen = mtd->writesize - c;
668                } else {
669                        iolen = mtd->writesize;
670                }
671
672                if (len < iolen) {
673                        iolen = len;
674                }
675
676                if (!rd) {
677                        int i;
678
679                        for (i = 0; (i < mtd->writesize) && (buff[i] == 0xff); i++);
680                        if (i == mtd->writesize) {
681                                ret = ATH_NF_STATUS_OK;
682                        //      printk("Skipping write for 0x%llx\n", addr);
683                                goto skip_write_for_all_0xff;
684                        }
685
686                        /* FIXME for writes FIXME */
687                        memcpy(buf, buff, iolen);
688                }
689
690                if (!rd) {
691                        //ath_nand_dump_buf(ATH_NF_COMMAND, (unsigned *)KSEG1ADDR(ATH_NF_COMMAND), 0xb8);
692                        ath_dbg_dump_to_fs(addr, buf);
693                }
694                pa = (unsigned char *)dma_map_single(NULL, buf, mtd->writesize, dir);
695
696                //printk("%s(%c): 0x%x 0x%x 0x%x 0x%p\n", __func__,
697                //      rd ? 'r' : 'w', ba0, ba1, iolen, pa);
698
699                ret = ath_nand_rw_page(sc, rd, ba0, ba1, mtd->writesize, pa, 1);
700
701                dma_unmap_single(NULL, (dma_addr_t)pa, mtd->writesize, dir);
702
703                if (rd) {
704                        memcpy(buff, buf + c, iolen);
705                }
706
707skip_write_for_all_0xff:
708
709                if (ret != ATH_NF_STATUS_OK) {
710                        return 1;
711                }
712
713                len -= iolen;
714                buff += iolen;
715                addr += iolen;
716                *iodone += iolen;
717        }
718
719        return 0;
720}
721
722#define ath_nand_write_verify   0
723
724#if ath_nand_write_verify
725uint8_t ath_nand_rd_buf[4096 + 256] __attribute__((aligned(4096)));
726#endif
727
728#define inject_failure  0
729#if inject_failure
730unsigned ath_nand_inject;
731#endif
732
733static int
734ath_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
735                size_t *retlen, const u_char *buf)
736{
737        int     ret;
738#if ath_nand_write_verify
739        int     r, rl;
740#endif
741
742        if (!len || !retlen) return (0);
743
744        indbg("0x%llx   %u", to, len);
745
746        ret = ath_nand_rw_buff(mtd, 0 /* write */, (u_char *)buf, to, len, retlen);
747#if ath_nand_write_verify
748        //printk("Verifying 0x%llx 0x%x\n", to, len);
749        r = ath_nand_rw_buff(mtd, 1 /* read */, ath_nand_rd_buf, to, len, &rl);
750        if (r || memcmp(ath_nand_rd_buf, buf, len)) {
751                printk("write failed at 0x%llx 0x%x\n", to, len);
752                while (1);
753        }
754#endif
755#if inject_failure
756        if (ath_nand_inject & 2 && ((ath_nand_inject & ~2u) == to)) {
757                retlen = 0;
758                ret = -EIO;
759                printk("Forcing write failure at 0x%llx\n", to);
760        }
761#endif
762
763        return ret;
764}
765
766static int
767ath_nand_read(struct mtd_info *mtd, loff_t from, size_t len,
768                size_t *retlen, u_char *buf)
769{
770        int     ret;
771
772        if (!len || !retlen) return (0);
773
774        indbg("0x%llx   %u", from, len);
775
776        ret = ath_nand_rw_buff(mtd, 1 /* read */, buf, from, len, retlen);
777
778#if inject_failure
779        if (ath_nand_inject & 1 && ((ath_nand_inject & ~1u) == from)) {
780                retlen = 0;
781                ret = -EIO;
782                printk("Forcing read failure at 0x%llx\n", from);
783        }
784#endif
785
786        return ret;
787}
788
789static inline int
790ath_nand_block_erase(ath_nand_sc_t *sc, unsigned addr0, unsigned addr1)
791{
792        unsigned        rddata;
793
794        indbg("0x%x 0x%x", addr1, addr0);
795
796        ath_nand_clear_int_status();
797        ath_reg_wr(ATH_NF_MEM_CTRL, 0xff00);    // Remove write protect
798        ath_reg_wr(ATH_NF_ADDR0_0, addr0);
799        ath_reg_wr(ATH_NF_ADDR0_1, addr1);
800        ath_reg_wr(ATH_NF_COMMAND, 0xd0600e);   // BLOCK ERASE
801
802        while (ath_nand_get_cmd_end_status() == 0);
803
804        rddata = ath_nand_status(sc, NULL) & ATH_NF_RD_STATUS_MASK;
805
806        ath_reg_wr(ATH_NF_MEM_CTRL, 0x0000);    // Enable write protect
807
808        if (rddata != ATH_NF_STATUS_OK) {
809                printk("Erase Failed. status = 0x%x", rddata);
810                return 1;
811        }
812        return 0;
813}
814
815
816static int
817ath_nand_erase(struct mtd_info *mtd, struct erase_info *instr)
818{
819        uint64_t        s_first, i;
820        unsigned        n, j;
821        int             ret = 0, bad = 0;
822        ath_nand_sc_t   *sc = mtd->priv;
823
824        if (instr->addr + instr->len > mtd->size) {
825                return (-EINVAL);
826        }
827
828        s_first = instr->addr;
829        n = instr->len >> mtd->erasesize_shift;
830
831        indbg("0x%llx 0x%llx 0x%x", instr->addr, s_last, mtd->erasesize);
832
833        for (j = 0, i = s_first; j < n; j++, i += mtd->erasesize) {
834                ulong ba0, ba1;
835
836                if (ath_nand_block_isbad(mtd, i)) {
837                        bad ++;
838                        continue;
839                }
840
841                ba0 = ((i >> mtd->writesize_shift) << 16);
842                ba1 = ((i >> (mtd->writesize_shift + 16)) & 0xf);
843
844                if ((ret = ath_nand_block_erase(sc, ba0, ba1)) != 0) {
845                        iodbg("%s: erase failed 0x%llx 0x%llx 0x%x %llu "
846                                "%lx %lx\n", __func__, instr->addr, s_last,
847                                mtd->erasesize, i, ba1, ba0);
848                        break;
849                }
850                ath_nand_set_blk_state(mtd, i, ATH_NAND_BLK_ERASED);
851#if inject_failure
852                if (ath_nand_inject & 4 && ((ath_nand_inject & ~4u) == i)) {
853                        printk("Forcing erase failure at 0x%llx\n", i);
854                        break;
855                }
856#endif
857
858        }
859
860        if (instr->callback) {
861                if ((j < n) || bad) {
862                        instr->state = MTD_ERASE_FAILED;
863                } else {
864                        instr->state = MTD_ERASE_DONE;
865                }
866                mtd_erase_callback(instr);
867        }
868
869        return ret;
870}
871
872static int
873ath_nand_rw_oob(struct mtd_info *mtd, int rd, loff_t addr,
874                struct mtd_oob_ops *ops)
875{
876        unsigned        dir, ret = ATH_NF_STATUS_OK;
877        unsigned char   *pa;
878        unsigned        ba0, ba1;
879        uint8_t         *buf = get_ath_nand_io_buf();
880        uint8_t         *oob = buf + mtd->writesize;
881        ath_nand_sc_t   *sc = mtd->priv;
882
883        ba0 = ((addr >> mtd->writesize_shift) << 16);
884        ba1 = ((addr >> (mtd->writesize_shift + 16)) & 0xf);
885
886        dir = rd ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
887
888        if (!rd) {
889                if (ops->datbuf) {
890                        /*
891                         * XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
892                         * We assume that the caller gives us a full
893                         * page to write. We don't read the page and
894                         * update the changed portions alone.
895                         *
896                         * Hence, not checking for len < or > pgsz etc...
897                         * XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
898                         */
899                        memcpy(buf, ops->datbuf, ops->len);
900                }
901                if (ops->mode == MTD_OPS_PLACE_OOB) {
902                        oob += ops->ooboffs;
903                } else if (ops->mode == MTD_OPS_AUTO_OOB) {
904                        // clean markers
905                        oob[0] = oob[1] = 0xff;
906                        oob += 2;
907                }
908                memcpy(oob, ops->oobbuf, ops->ooblen);
909        }
910
911        if (!rd) {
912                ath_dbg_dump_to_fs(addr, buf);
913                ath_dbg_dump_to_fs_spare(addr, buf + mtd->writesize);
914        }
915
916        pa = (unsigned char *)dma_map_single(NULL, buf,
917                                mtd->writesize + mtd->oobsize, dir);
918
919        //printk("%s(%c): 0x%x 0x%x 0x%x 0x%p\n", __func__,
920        //      rd ? 'r' : 'w', ba0, ba1, mtd->writesize + mtd->oobsize, pa);
921
922        ret = ath_nand_rw_page(sc, rd, ba0, ba1, mtd->writesize + mtd->oobsize, pa, 0);
923
924        dma_unmap_single(NULL, (dma_addr_t)pa, mtd->writesize + mtd->oobsize, dir);
925
926        //ath_nand_dump_buf(addr, buf, iolen);
927
928        if (ret != ATH_NF_STATUS_OK) {
929                return 1;
930        }
931
932        if (rd) {
933                if (ops->datbuf) {
934                        memcpy(ops->datbuf, buf, ops->len);
935                }
936                if (ops->mode == MTD_OPS_PLACE_OOB) {
937                        oob += ops->ooboffs;
938                } else if (ops->mode == MTD_OPS_AUTO_OOB) {
939                        // copy after clean marker
940                        oob += 2;
941                }
942                memcpy(ops->oobbuf, oob, ops->ooblen);
943        }
944
945        //if (rd) {
946        //      ath_nand_dump_buf(addr, ops->datbuf, ops->len);
947        //      ath_nand_dump_buf(addr, ops->oobbuf, ops->ooblen);
948        //}
949
950        if (ops->datbuf) {
951                ops->retlen = ops->len;
952        }
953        ops->oobretlen = ops->ooblen;
954
955        return 0;
956}
957
958static int
959ath_nand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
960{
961        oobdbg( "%s: from: 0x%llx mode: 0x%x len: 0x%x retlen: 0x%x\n"
962                "ooblen: 0x%x oobretlen: 0x%x ooboffs: 0x%x datbuf: %p "
963                "oobbuf: %p\n", __func__, from,
964                ops->mode, ops->len, ops->retlen, ops->ooblen,
965                ops->oobretlen, ops->ooboffs, ops->datbuf,
966                ops->oobbuf);
967
968        indbg("0x%llx %p %p %u", from, ops->oobbuf, ops->datbuf, ops->len);
969
970        return ath_nand_rw_oob(mtd, 1 /* read */, from, ops);
971}
972
973static int
974ath_nand_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
975{
976        int ret;
977        unsigned char oob[128];
978        struct mtd_oob_ops      rops = {
979                .mode   = MTD_OPS_RAW,
980                .ooblen = mtd->oobsize,
981                .oobbuf = oob,
982        };
983
984        if (ops->mode == MTD_OPS_AUTO_OOB) {
985                /* read existing oob */
986                if (ath_nand_read_oob(mtd, to, &rops) ||
987                        rops.oobretlen != rops.ooblen) {
988                        printk("%s: oob read failed at 0x%llx\n", __func__, to);
989                        return 1;
990                }
991                memcpy(oob + 2, ops->oobbuf, ops->ooblen);
992                rops = *ops;
993                ops->oobbuf = oob;
994                ops->ooblen = mtd->oobsize;
995                ops->mode = MTD_OPS_RAW;
996        }
997
998        oobdbg( "%s: from: 0x%llx mode: 0x%x len: 0x%x retlen: 0x%x\n"
999                "ooblen: 0x%x oobretlen: 0x%x ooboffs: 0x%x datbuf: %p "
1000                "oobbuf: %p\n", __func__, to,
1001                ops->mode, ops->len, ops->retlen, ops->ooblen,
1002                ops->oobretlen, ops->ooboffs, ops->datbuf,
1003                ops->oobbuf);
1004
1005        indbg("0x%llx", to);
1006
1007        ret = ath_nand_rw_oob(mtd, 0 /* write */, to, ops);
1008
1009        if (rops.mode == MTD_OPS_AUTO_OOB) {
1010                if (ret == 0) { // rw oob success
1011                        rops.oobretlen = rops.ooblen;
1012                        rops.retlen = rops.len;
1013                }
1014                *ops = rops;
1015        }
1016
1017        return ret;
1018}
1019
1020static int
1021ath_nand_block_isbad(struct mtd_info *mtd, loff_t ofs)
1022{
1023        unsigned char           oob[256];
1024        unsigned                bs, i;
1025        struct mtd_oob_ops      ops = {
1026                .mode   = MTD_OPS_RAW,
1027                .ooblen = mtd->oobsize,
1028                .oobbuf = oob,
1029        };
1030
1031        bs = ath_nand_get_blk_state(mtd, ofs);
1032
1033        if ((bs == ATH_NAND_BLK_ERASED) || (bs == ATH_NAND_BLK_GOOD)) {
1034                return 0;
1035        }
1036
1037        if (bs == ATH_NAND_BLK_BAD) {
1038                return 1;
1039        }
1040
1041        /*
1042         * H27U1G8F2B Series [1 Gbit (128 M x 8 bit) NAND Flash]
1043         *
1044         * The Bad Block Information is written prior to shipping. Any
1045         * block where the 1st Byte in the spare area of the 1st or
1046         * 2nd th page (if the 1st page is Bad) does not contain FFh
1047         * is a Bad Block. The Bad Block Information must be read
1048         * before any erase is attempted as the Bad Block Information
1049         * may be erased. For the system to be able to recognize the
1050         * Bad Blocks based on the original information it is
1051         * recommended to create a Bad Block table following the
1052         * flowchart shown in Figure 24. The 1st block, which is
1053         *                               ^^^^^^^^^^^^^
1054         * placed on 00h block address is guaranteed to be a valid
1055         * block.                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
1056         */
1057
1058        for (i = 0; i < 2; i++, ofs += mtd->writesize) {
1059                if (ath_nand_read_oob(mtd, ofs, &ops) ||
1060                        ops.oobretlen != ops.ooblen) {
1061                        printk("%s: oob read failed at 0x%llx\n", __func__, ofs);
1062                        return 1;
1063                }
1064
1065                /* First two bytes of oob data are clean markers */
1066                if (oob[0] != 0xff || oob[1] != 0xff) {
1067                        oobdbg("%s: block is bad at 0x%llx\n", __func__, ofs);
1068                        oobdbg( "%02x %02x %02x %02x %02x %02x %02x %02x "
1069                                "%02x %02x %02x %02x %02x %02x %02x %02x "
1070                                "%02x %02x %02x %02x %02x %02x %02x %02x "
1071                                "%02x %02x %02x %02x %02x %02x %02x %02x "
1072                                "%02x %02x %02x %02x %02x %02x %02x %02x "
1073                                "%02x %02x %02x %02x %02x %02x %02x %02x "
1074                                "%02x %02x %02x %02x %02x %02x %02x %02x "
1075                                "%02x %02x %02x %02x %02x %02x %02x %02x\n",
1076                                0xff & oob[ 0], 0xff & oob[ 1], 0xff & oob[ 2],
1077                                0xff & oob[ 3], 0xff & oob[ 4], 0xff & oob[ 5],
1078                                0xff & oob[ 6], 0xff & oob[ 7], 0xff & oob[ 8],
1079                                0xff & oob[ 9], 0xff & oob[10], 0xff & oob[11],
1080                                0xff & oob[12], 0xff & oob[13], 0xff & oob[14],
1081                                0xff & oob[15], 0xff & oob[16], 0xff & oob[17],
1082                                0xff & oob[18], 0xff & oob[19], 0xff & oob[20],
1083                                0xff & oob[21], 0xff & oob[22], 0xff & oob[23],
1084                                0xff & oob[24], 0xff & oob[25], 0xff & oob[26],
1085                                0xff & oob[27], 0xff & oob[28], 0xff & oob[29],
1086                                0xff & oob[30], 0xff & oob[31], 0xff & oob[32],
1087                                0xff & oob[33], 0xff & oob[34], 0xff & oob[35],
1088                                0xff & oob[36], 0xff & oob[37], 0xff & oob[38],
1089                                0xff & oob[39], 0xff & oob[40], 0xff & oob[41],
1090                                0xff & oob[42], 0xff & oob[43], 0xff & oob[44],
1091                                0xff & oob[45], 0xff & oob[46], 0xff & oob[47],
1092                                0xff & oob[48], 0xff & oob[49], 0xff & oob[50],
1093                                0xff & oob[51], 0xff & oob[52], 0xff & oob[53],
1094                                0xff & oob[54], 0xff & oob[55], 0xff & oob[56],
1095                                0xff & oob[57], 0xff & oob[58], 0xff & oob[59],
1096                                0xff & oob[60], 0xff & oob[61], 0xff & oob[62],
1097                                0xff & oob[63]);
1098                        ath_nand_set_blk_state(mtd, ofs, ATH_NAND_BLK_BAD);
1099                        return 1;
1100                }
1101        }
1102
1103        for (i = 0; (i < mtd->oobsize) && (oob[i] == 0xff); i++);
1104
1105        if (i == mtd->oobsize) {
1106                ath_nand_set_blk_state(mtd, ofs, ATH_NAND_BLK_ERASED);
1107        } else {
1108                ath_nand_set_blk_state(mtd, ofs, ATH_NAND_BLK_GOOD);
1109        }
1110
1111        return 0;
1112}
1113
1114static int
1115ath_nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
1116{
1117        unsigned char oob[128] = { "bad block" };
1118        struct mtd_oob_ops      ops = {
1119                .mode   = MTD_OPS_RAW,
1120                .ooblen = mtd->oobsize,
1121                .oobbuf = oob,
1122        };
1123
1124        indbg("called 0x%llx", ofs);
1125
1126        if (ath_nand_write_oob(mtd, ofs, &ops) ||
1127                ops.oobretlen != ops.ooblen) {
1128                printk("%s: oob write failed at 0x%llx\n", __func__, ofs);
1129                return 1;
1130        }
1131
1132        return 0;
1133}
1134
1135static uint64_t
1136ath_parse_read_id(ath_nand_sc_t *sc)
1137{
1138        int     i;
1139
1140        extern struct nand_manufacturers nand_manuf_ids[];
1141        extern struct nand_flash_dev nand_flash_ids[];
1142
1143        iodbg(  "____ %s _____\n"
1144                "  vid did wc  ilp nsp ct  dp  sa1 org bs  sa0 ss  "
1145                "ps  res1 pls pn  res2\n"
1146                "0x%3x %3x %3x %3x %3x %3x %3x %3x %3x %3x %3x %3x "
1147                "%3x %3x  %3x %3x %3x\n-------------\n", __func__,
1148                        sc->nid.vid, sc->nid.did, sc->nid.wc, sc->nid.ilp,
1149                        sc->nid.nsp, sc->nid.ct, sc->nid.dp, sc->nid.sa1,
1150                        sc->nid.org, sc->nid.bs, sc->nid.sa0, sc->nid.ss,
1151                        sc->nid.ps, sc->nid.res1, sc->nid.pls, sc->nid.pn,
1152                        sc->nid.res2);
1153
1154        for (i = 0; i < nand_manuf_ids[i].id; i++) {
1155                if (nand_manuf_ids[i].id == sc->nid.vid) {
1156                        printk(nand_manuf_ids[i].name);
1157                        break;
1158                }
1159        }
1160
1161        for (i = 0; i < nand_flash_ids[i].id; i++) {
1162                if (nand_flash_ids[i].id == sc->nid.did) {
1163                        printk(" %s [%luMB]\n", nand_flash_ids[i].name,
1164                                nand_flash_ids[i].chipsize);
1165                        return nand_flash_ids[i].chipsize;
1166                }
1167        }
1168
1169        return 0;
1170}
1171
1172ath_nand_vend_data_t *
1173nand_get_entry(ath_nand_id_t *nand_id, ath_nand_vend_data_t *tbl, int count)
1174{
1175        int     i;
1176
1177        for (i = 0; i < count; i++, tbl ++) {
1178                if ((nand_id->__details.vid == tbl->vid) &&
1179                    (nand_id->__details.did == tbl->did) &&
1180                    (nand_id->byte_id[1] == tbl->b3)) {
1181                        return tbl;
1182                }
1183        }
1184
1185        return NULL;
1186}
1187
1188static inline void
1189ath_nand_onfi_endian_convert(uint8_t *buf)
1190{
1191        uint32_t        i, *u = (uint32_t *)(buf + ONFI_DEV_DESC);
1192
1193        for (i = 0; i < (ONFI_DEV_DESC_SZ / sizeof(*u)); i++) {
1194                u[i] = __le32_to_cpu(u[i]);
1195        }
1196
1197        // Hope nobody has a 20 character device description
1198        buf[ONFI_DEV_DESC + ONFI_DEV_DESC_SZ - 1] = 0;
1199}
1200
1201int
1202nand_param_page(ath_nand_sc_t *sc, uint8_t *buf, unsigned count)
1203{
1204        unsigned int    tries, rddata;
1205        uint8_t         *pa;
1206
1207        pa = (uint8_t *)dma_map_single(NULL, buf, count, DMA_FROM_DEVICE);
1208
1209        for (tries = 3; tries; tries --) {
1210                // ADDR0_0 Reg Settings
1211                ath_reg_wr(ATH_NF_ADDR0_0, 0x0);
1212
1213                // ADDR0_1 Reg Settings
1214                ath_reg_wr(ATH_NF_ADDR0_1, 0x0);
1215
1216                // DMA Start Addr
1217                ath_reg_wr(ATH_NF_DMA_ADDR, (unsigned)pa);
1218
1219                // DMA count
1220                ath_reg_wr(ATH_NF_DMA_COUNT, count);
1221
1222                // Custom Page Size
1223                ath_reg_wr(ATH_NF_PG_SIZE, count);
1224
1225                // DMA Control Reg
1226                ath_reg_wr(ATH_NF_DMA_CTRL, 0xcc);
1227
1228                ath_nand_clear_int_status();
1229                // READ PARAMETER PAGE
1230                ath_reg_wr(ATH_NF_COMMAND, 0xec62);
1231                while (ath_nand_get_cmd_end_status() == 0);
1232
1233                rddata = ath_nand_status(sc, NULL) & READ_PARAM_STATUS_MASK;
1234                if (rddata == READ_PARAM_STATUS_OK) {
1235                        break;
1236                } else {
1237                        printk("\nParam Page Failure: 0x%x", rddata);
1238                        ath_nand_hw_init(sc, NULL);
1239                }
1240        }
1241
1242        dma_unmap_single(NULL, (dma_addr_t)pa, count, DMA_FROM_DEVICE);
1243
1244        if ((rddata == READ_PARAM_STATUS_OK) &&
1245            (buf[3] == 'O' && buf[2] == 'N' && buf[1] == 'F' && buf[0] == 'I')) {
1246                ath_nand_onfi_endian_convert(buf);
1247                printk("ONFI %s\n", buf + ONFI_DEV_DESC);
1248                return 0;
1249        }
1250
1251        return 1;
1252}
1253
1254/*
1255 * System initialization functions
1256 */
1257static int
1258ath_nand_hw_init(ath_nand_sc_t *sc, void *p)
1259{
1260        uint8_t         id[8];
1261        unsigned char   *pa;
1262        unsigned        rddata, i;
1263
1264        // Put into reset
1265        ath_reg_rmw_set(ATH_RESET, RST_RESET_NANDF_RESET_MASK);
1266        udelay(250);
1267
1268        ath_reg_rmw_clear(ATH_RESET, RST_RESET_NANDF_RESET_MASK);
1269        udelay(100);
1270
1271        ath_reg_wr(ATH_NF_INT_MASK, ATH_NF_CMD_END_INT);
1272        ath_nand_clear_int_status();
1273
1274        // TIMINGS_ASYN Reg Settings
1275        ath_reg_wr(ATH_NF_TIMINGS_ASYN, ATH_NF_TIMING_ASYN);
1276
1277        // NAND Mem Control Reg
1278        ath_reg_wr(ATH_NF_MEM_CTRL, 0xff00);
1279        //ath_reg_wr(ATH_NF_MEM_CTRL, 0x0000);
1280
1281        // Reset Command
1282        ath_reg_wr(ATH_NF_COMMAND, 0xff00);
1283
1284        while (ath_nand_get_cmd_end_status() == 0);
1285
1286        udelay(1000);
1287
1288        rddata = ath_reg_rd(ATH_NF_STATUS);
1289        for (i = 0; i < ATH_NF_STATUS_RETRY && rddata != 0xff; i++) {
1290                udelay(25);
1291                rddata = ath_reg_rd(ATH_NF_STATUS);
1292        }
1293
1294        if (i == ATH_NF_STATUS_RETRY) {
1295                printk("device reset failed\n");
1296                while(1);
1297        }
1298
1299        if (p) {
1300                ath_nand_vend_data_t *entry;
1301
1302                ath_nand_clear_int_status();
1303                pa = (unsigned char *)dma_map_single(NULL, p ? p : id,
1304                                                8, DMA_FROM_DEVICE);
1305                ath_reg_wr(ATH_NF_DMA_ADDR, (unsigned)p);
1306                ath_reg_wr(ATH_NF_ADDR0_0, 0x0);
1307                ath_reg_wr(ATH_NF_ADDR0_1, 0x0);
1308                ath_reg_wr(ATH_NF_DMA_COUNT, 0x8);
1309                ath_reg_wr(ATH_NF_PG_SIZE, 0x8);
1310                ath_reg_wr(ATH_NF_DMA_CTRL, 0xcc);
1311                ath_reg_wr(ATH_NF_COMMAND, 0x9061);     // READ ID
1312                while (ath_nand_get_cmd_end_status() == 0);
1313
1314                rddata = ath_nand_status(sc, NULL);
1315                if ((rddata & ATH_NF_RD_STATUS_MASK) != ATH_NF_STATUS_OK) {
1316                        printk("%s: failed\nath nand status = 0x%x\n",
1317                                __func__, rddata);
1318                }
1319                dma_unmap_single(NULL, (dma_addr_t)pa, 8, DMA_FROM_DEVICE);
1320
1321                pa = p;
1322                printk("Ath Nand ID[%p]: %02x:%02x:%02x:%02x:%02x\n",
1323                                pa, pa[3], pa[2], pa[1], pa[0], pa[7]);
1324
1325                sc->onfi[0] = 0;
1326
1327                entry = nand_get_entry((ath_nand_id_t *)p, ath_nand_arr, NUM_ATH_NAND);
1328                if (entry) {
1329                        sc->nf_ctrl = ATH_NF_CTRL_ADDR_CYCLE0(entry->addrcyc);
1330                } else if (nand_param_page(sc, sc->onfi, sizeof(sc->onfi)) == 0) {
1331                        rddata = sc->onfi[ONFI_NUM_ADDR_CYCLES];
1332                        rddata = ((rddata >> 4) & 0xf) + (rddata & 0xf);
1333                        sc->nf_ctrl = ATH_NF_CTRL_ADDR_CYCLE0(rddata);
1334                } else {
1335                        printk("Attempting to use unknown device\n");
1336                        sc->nf_ctrl = ATH_NF_CTRL_ADDR_CYCLE0(5);
1337                }
1338
1339                iodbg("******* %s done ******\n", __func__);
1340        }
1341
1342        return 0;
1343}
1344
1345/*
1346 * Copied from drivers/mtd/nand/nand_base.c
1347 * http://ptgmedia.pearsoncmg.com/images/chap17_9780132396554/elementLinks/17fig04.gif
1348 *
1349 * +---...---+--+----------+---------+
1350 * |  2048   |  |          |         |
1351 * | File    |cm| FS spare | ecc data|
1352 * | data    |  |          |         |
1353 * +---...---+--+----------+---------+
1354 * cm -> clean marker (2 bytes)
1355 * FS Spare -> bytes available for jffs2
1356 */
1357static struct nand_ecclayout ath_nand_oob = {
1358        .oobfree = { {.offset = 2, .length = 18} }
1359};
1360
1361static void
1362ath_nand_ecc_init(struct mtd_info *mtd)
1363{
1364#if ATH_NF_HW_ECC
1365        ath_nand_sc_t           *sc = mtd->priv;
1366        int                     i, off;
1367
1368        for (off = i = 0; ath_nand_oob.oobfree[i].length
1369                        && i < ARRAY_SIZE(ath_nand_oob.oobfree); i++) {
1370                ath_nand_oob.oobavail += ath_nand_oob.oobfree[i].length;
1371                off += ath_nand_oob.oobfree[i].offset;
1372        }
1373        mtd->ecclayout = &ath_nand_oob;
1374        sc->ecc_offset = mtd->writesize + ath_nand_oob.oobavail + off;
1375#else
1376        mtd->ecclayout  = NULL;
1377        sc->ecc_offset = 0;
1378#endif
1379}
1380
1381static struct mtd_partition dir_parts[] = {
1382      {name: "RedBoot", offset: 0x0, size:0x80000,},
1383      {name: "linux", offset: 0x6c0000, size:0x40000,},
1384      {name: "rootfs", offset: 0x0, size:0x2b0000,},
1385      {name: "ddwrt", offset: 0x0, size:0x2b0000,},
1386      {name: "nvram", offset: 0x340000, size:0x80000,},
1387      {name: "board_config", offset: 0x80000, size:0x40000,},
1388      {name: "fullflash", offset: 0x0, size:0x10000,},
1389      {name:NULL,},
1390};
1391
1392
1393/*
1394 * Device management interface
1395 */
1396static int ath_nand_add_partition(ath_nand_sc_t *sc)
1397{
1398        struct mtd_info *mtd = &sc->mtd;
1399#ifdef CONFIG_MTD
1400        struct squashfs_super_block *sb;
1401        uint64_t offset;
1402        char buf[512];
1403        char *bbuf = NULL;
1404        int retlen;
1405        unsigned int rootsize,len;
1406        uint64_t base = offset + mtd->erasesize;
1407        while (base < mtd->size) {
1408                mtd_read(mtd,offset,512,&retlen,&buf[0]);
1409                if (*((__u32 *)buf) == SQUASHFS_MAGIC_SWAP)
1410                    bbuf = buf;
1411                else
1412                if (*((__u32 *)&buf[128]) == SQUASHFS_MAGIC_SWAP)
1413                {
1414                    bbuf = &buf[128];
1415                    offset+=128;
1416                }
1417                else
1418                    bbuf = NULL;
1419                if (bbuf) {
1420                                printk(KERN_EMERG "\nfound squashfs at 0x%llX\n",offset);
1421                                sb = (struct squashfs_super_block *)buf;
1422                                dir_parts[2].offset = offset;
1423                                dir_parts[2].size = sb->bytes_used;
1424                                len = dir_parts[2].offset + dir_parts[2].size;
1425                                len += (mtd->erasesize - 1);
1426                                len &= ~(mtd->erasesize - 1);
1427                                dir_parts[2].size = (len & 0x1ffffff) - dir_parts[2].offset;
1428                                dir_parts[3].offset = dir_parts[2].offset + dir_parts[2].size;
1429                                dir_parts[3].size = mtd->size - dir_parts[3].offset;
1430                                dir_parts[1].size = dir_parts[3].offset + dir_parts[3].size - dir_parts[1].offset;
1431                                dir_parts[6].size = mtd->size;
1432                                break;
1433                }
1434        offset += mtd->erasesize;
1435        base += mtd->erasesize;
1436        }
1437
1438        return add_mtd_partitions(mtd, dir_parts, 7);
1439#else
1440        return add_mtd_device(mtd);
1441#endif
1442}
1443
1444static int ath_nand_remove(void)
1445{
1446#ifdef CONFIG_MTD
1447        /* Deregister partitions */
1448        del_mtd_partitions(&ath_nand_sc->mtd);
1449#endif
1450        kfree(ath_nand_sc);
1451        ath_nand_sc = NULL;
1452        return 0;
1453}
1454
1455extern void nand_postinit(struct mtd_info *mtd);
1456/*
1457 * ath_nand_probe
1458 *
1459 * called by device layer when it finds a device matching
1460 * one our driver can handled. This code checks to see if
1461 * it can allocate all necessary resources then calls the
1462 * nand layer to look for devices
1463 */
1464static int ath_nand_probe(void)
1465{
1466        ath_nand_sc_t   *sc = NULL;
1467        struct mtd_info *mtd = NULL;
1468        int             i, err = 0, bbt_size;
1469        unsigned        nf_ctrl_pg[][2] = {
1470                /* page size in bytes, register val */
1471                {   256, ATH_NF_CTRL_PAGE_SIZE_256      },
1472                {   512, ATH_NF_CTRL_PAGE_SIZE_512      },
1473                {  1024, ATH_NF_CTRL_PAGE_SIZE_1024     },
1474                {  2048, ATH_NF_CTRL_PAGE_SIZE_2048     },
1475                {  4096, ATH_NF_CTRL_PAGE_SIZE_4096     },
1476                {  8192, ATH_NF_CTRL_PAGE_SIZE_8192     },
1477                { 16384, ATH_NF_CTRL_PAGE_SIZE_16384    },
1478                {     0, ATH_NF_CTRL_PAGE_SIZE_0        },
1479                };
1480        unsigned        nf_ctrl_blk[][2] = {
1481                /* no. of pages, register val */
1482                {  32, ATH_NF_CTRL_BLOCK_SIZE_32        },
1483                {  64, ATH_NF_CTRL_BLOCK_SIZE_64        },
1484                { 128, ATH_NF_CTRL_BLOCK_SIZE_128       },
1485                { 256, ATH_NF_CTRL_BLOCK_SIZE_256       },
1486                {   0, 0                                },
1487                };
1488
1489        sc = kzalloc(sizeof(*sc), GFP_KERNEL);
1490        if (sc == NULL) {
1491                printk("%s: no memory for flash sc\n", __func__);
1492                err = -ENOMEM;
1493                goto out_err_kzalloc;
1494        }
1495
1496        /* initialise the hardware */
1497        err = ath_nand_hw_init(sc, &sc->nid);
1498        if (err) {
1499                goto out_err_hw_init;
1500        }
1501
1502        /* initialise mtd sc data struct */
1503        mtd = &sc->mtd;
1504        mtd->size = ath_parse_read_id(sc) << 20;
1505
1506        mtd->name               = DRV_NAME;
1507        mtd->owner              = THIS_MODULE;
1508        if (mtd->size == 0) {
1509                mtd->size       = ath_plane_size[sc->nid.pls] << sc->nid.pn;
1510        }
1511
1512        if (!sc->onfi[0]) {
1513                mtd->writesize_shift    = 10 + sc->nid.ps;
1514                mtd->writesize          = (1 << mtd->writesize_shift);
1515                mtd->writesize_mask     = (mtd->writesize - 1);
1516
1517                mtd->erasesize_shift    = 16 + sc->nid.bs;
1518                mtd->erasesize          = (1 << mtd->erasesize_shift);
1519                mtd->erasesize_mask     = (mtd->erasesize - 1);
1520
1521                mtd->oobsize            = (mtd->writesize / 512) * (8 << sc->nid.ss);
1522                mtd->oobavail           = mtd->oobsize;
1523        } else {
1524                mtd->writesize          = *(uint32_t *)(&sc->onfi[ONFI_PAGE_SIZE]);
1525                mtd->writesize_shift    = ffs(mtd->writesize) - 1;
1526                mtd->writesize_mask     = (mtd->writesize - 1);
1527
1528                mtd->erasesize          = *(uint32_t *)(&sc->onfi[ONFI_PAGES_PER_BLOCK]) *
1529                                          mtd->writesize;
1530                mtd->erasesize_shift    = ffs(mtd->erasesize) - 1;
1531                mtd->erasesize_mask     = (mtd->erasesize - 1);
1532
1533                mtd->oobsize            = *(uint16_t *)(&sc->onfi[ONFI_SPARE_SIZE]);
1534                mtd->oobavail           = mtd->oobsize;
1535
1536                mtd->size               = mtd->erasesize *
1537                                          (*(uint32_t *)(&sc->onfi[ONFI_BLOCKS_PER_LUN])) *
1538                                          sc->onfi[ONFI_NUM_LUNS];
1539        }
1540
1541        for (i = 0; nf_ctrl_pg[i][0]; i++) {
1542                if (nf_ctrl_pg[i][0] == mtd->writesize) {
1543                        sc->nf_ctrl |= nf_ctrl_pg[i][1];
1544                        break;
1545                }
1546        }
1547
1548        for (i = 0; nf_ctrl_blk[i][0]; i++) {
1549                if (nf_ctrl_blk[i][0] == (mtd->erasesize / mtd->writesize)) {
1550                        sc->nf_ctrl |= nf_ctrl_blk[i][1];
1551                        break;
1552                }
1553        }
1554
1555        mtd->type               = MTD_NANDFLASH;
1556        mtd->flags              = MTD_CAP_NANDFLASH;
1557
1558        mtd->_read              = ath_nand_read;
1559        mtd->_write             = ath_nand_write;
1560        mtd->_erase             = ath_nand_erase;
1561
1562        mtd->_read_oob          = ath_nand_read_oob;
1563        mtd->_write_oob         = ath_nand_write_oob;
1564
1565        mtd->_block_isbad       = ath_nand_block_isbad;
1566        mtd->_block_markbad     = ath_nand_block_markbad;
1567
1568        mtd->priv               = sc;
1569
1570        ath_nand_ecc_init(mtd);
1571
1572        /* add NAND partition */
1573        ath_nand_add_partition(sc);
1574
1575        // bbt has 2 bits per block
1576        bbt_size = ((mtd->size >> mtd->erasesize_shift) * 2) / 8;
1577        sc->bbt = kmalloc(bbt_size, GFP_KERNEL);
1578
1579        if (sc->bbt) {
1580                memset(sc->bbt, 0, bbt_size);
1581        }
1582
1583        ath_nand_sc = sc;
1584        printk( "====== NAND Parameters ======\n"
1585                "sc = 0x%p bbt = 0x%p bbt_size = 0x%x nf_ctrl = 0x%x\n"
1586                "page = 0x%x block = 0x%x oob = 0x%x\n", sc, sc->bbt, bbt_size,
1587                sc->nf_ctrl, mtd->writesize, mtd->erasesize, mtd->oobsize);
1588
1589        nand_postinit(mtd);
1590        return 0;
1591
1592out_err_hw_init:
1593        kfree(sc);
1594out_err_kzalloc:
1595
1596        return err;
1597}
1598
1599#if 0
1600static struct platform_driver ath_nand_driver = {
1601        //.probe                = ath_nand_probe,
1602        .remove         = ath_nand_remove,
1603        .driver         = {
1604                .name   = DRV_NAME,
1605                .owner  = THIS_MODULE,
1606        },
1607};
1608#endif
1609
1610static int __init ath_nand_init(void)
1611{
1612        printk(DRV_DESC ", Version " DRV_VERSION
1613                " (c) 2010 Atheros Communications, Ltd.\n");
1614
1615        //return platform_driver_register(&ath_nand_driver);
1616        //return platform_driver_probe(&ath_nand_driver, ath_nand_probe);
1617        return ath_nand_probe();
1618}
1619
1620static void __exit ath_nand_exit(void)
1621{
1622        //platform_driver_unregister(&ath_nand_driver);
1623        ath_nand_remove();
1624}
1625
1626module_init(ath_nand_init);
1627module_exit(ath_nand_exit);
1628
1629MODULE_LICENSE("GPL");
1630MODULE_AUTHOR(DRV_AUTHOR);
1631MODULE_DESCRIPTION(DRV_DESC);
1632MODULE_ALIAS("platform:" DRV_NAME);
Note: See TracBrowser for help on using the repository browser.