summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4760.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/ata-nand-jz4760.c')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-nand-jz4760.c692
1 files changed, 692 insertions, 0 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4760.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4760.c
new file mode 100644
index 0000000000..b3cc589528
--- /dev/null
+++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4760.c
@@ -0,0 +1,692 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2016 by Roman Stolyarov
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "cpu.h"
24#include "nand.h"
25#include "nand_id.h"
26#include "system.h"
27#include "panic.h"
28#include "kernel.h"
29#include "storage.h"
30#include "string.h"
31/*#define LOGF_ENABLE*/
32#include "logf.h"
33
34//#define USE_DMA
35//#define USE_ECC
36
37/*
38 * Standard NAND flash commands
39 */
40#define NAND_CMD_READ0 0
41#define NAND_CMD_READ1 1
42#define NAND_CMD_RNDOUT 5
43#define NAND_CMD_PAGEPROG 0x10
44#define NAND_CMD_READOOB 0x50
45#define NAND_CMD_ERASE1 0x60
46#define NAND_CMD_STATUS 0x70
47#define NAND_CMD_STATUS_MULTI 0x71
48#define NAND_CMD_SEQIN 0x80
49#define NAND_CMD_RNDIN 0x85
50#define NAND_CMD_READID 0x90
51#define NAND_CMD_ERASE2 0xd0
52#define NAND_CMD_RESET 0xff
53
54/* Extended commands for large page devices */
55#define NAND_CMD_READSTART 0x30
56#define NAND_CMD_RNDOUTSTART 0xE0
57#define NAND_CMD_CACHEDPROG 0x15
58
59/* Status bits */
60#define NAND_STATUS_FAIL 0x01
61#define NAND_STATUS_FAIL_N1 0x02
62#define NAND_STATUS_TRUE_READY 0x20
63#define NAND_STATUS_READY 0x40
64#define NAND_STATUS_WP 0x80
65
66/*
67 * NAND parameter struct
68 */
69struct nand_param {
70 unsigned int bus_width; /* data bus width: 8-bit/16-bit */
71 unsigned int row_cycle; /* row address cycles: 2/3 */
72 unsigned int page_size; /* page size in bytes: 512/2048/4096 */
73 unsigned int oob_size; /* oob size in bytes: 16/64/128 */
74 unsigned int page_per_block; /* pages per block: 32/64/128 */
75 unsigned int bad_block_pos; /* bad block pos in oob: 0/5 */
76};
77
78/*
79 * jz4760_nand.c
80 *
81 * NAND read routine for JZ4760
82 *
83 * Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
84 *
85 */
86
87#define CFG_NAND_BASE 0xBA000000
88#define NAND_ADDR_OFFSET 0x00800000
89#define NAND_CMD_OFFSET 0x00400000
90
91#define CFG_NAND_SMCR1 0x0d444400
92
93#define NAND_DATAPORT CFG_NAND_BASE
94#define NAND_ADDRPORT (CFG_NAND_BASE | NAND_ADDR_OFFSET)
95#define NAND_COMMPORT (CFG_NAND_BASE | NAND_CMD_OFFSET)
96
97#define ECC_BLOCK 512
98#define ECC_POS 24
99#define PAR_SIZE 13
100
101#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n))
102#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
103#define __nand_data8() (REG8(NAND_DATAPORT))
104#define __nand_data16() (REG16(NAND_DATAPORT))
105
106#define __nand_select() (REG_NEMC_NFCSR |= NEMC_NFCSR_NFE1 | NEMC_NFCSR_NFCE1)
107#define __nand_deselect() (REG_NEMC_NFCSR &= ~(NEMC_NFCSR_NFE1 | NEMC_NFCSR_NFCE1))
108
109/*--------------------------------------------------------------*/
110
111static struct nand_info* chip_info = NULL;
112static struct nand_info* bank;
113static unsigned long nand_size;
114static struct nand_param internal_param;
115static struct mutex nand_mtx;
116#ifdef USE_DMA
117static struct mutex nand_dma_mtx;
118static struct semaphore nand_dma_complete;
119#endif
120static unsigned char temp_page[2048]; /* Max page size */
121
122static inline void jz_nand_wait_ready(void)
123{
124 unsigned int timeout = 1000;
125 while ((REG_GPIO_PXPIN(0) & 0x00100000) && timeout--);
126 while (!(REG_GPIO_PXPIN(0) & 0x00100000));
127}
128
129#ifndef USE_DMA
130static inline void jz_nand_read_buf16(void *buf, int count)
131{
132 register int i;
133 register unsigned short *p = (unsigned short *)buf;
134
135 for (i = 0; i < count; i += 2)
136 *p++ = __nand_data16();
137}
138
139static inline void jz_nand_read_buf8(void *buf, int count)
140{
141 register int i;
142 register unsigned char *p = (unsigned char *)buf;
143
144 for (i = 0; i < count; i++)
145 *p++ = __nand_data8();
146}
147#else
148static void jz_nand_write_dma(void *source, unsigned int len, int bw)
149{
150 mutex_lock(&nand_dma_mtx);
151
152 if(((unsigned int)source < 0xa0000000) && len)
153 dma_cache_wback_inv((unsigned long)source, len);
154
155 dma_enable();
156
157 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = DMAC_DCCSR_NDES;
158 REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)source);
159 REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT);
160 REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 16;
161 REG_DMAC_DRSR(DMA_NAND_CHANNEL) = DMAC_DRSR_RS_AUTO;
162 REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DS_16BYTE |
163 (bw == 8 ? DMAC_DCMD_DWDH_8 : DMAC_DCMD_DWDH_16));
164
165 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) |= DMAC_DCCSR_EN; /* Enable DMA channel */
166#if 1
167 while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) )
168 yield();
169#else
170 REG_DMAC_DCMD(DMA_NAND_CHANNEL) |= DMAC_DCMD_TIE; /* Enable DMA interrupt */
171 semaphore_wait(&nand_dma_complete, TIMEOUT_BLOCK);
172#endif
173
174 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) &= ~DMAC_DCCSR_EN; /* Disable DMA channel */
175
176 dma_disable();
177
178 mutex_unlock(&nand_dma_mtx);
179}
180
181static void jz_nand_read_dma(void *target, unsigned int len, int bw)
182{
183 mutex_lock(&nand_dma_mtx);
184
185 if(((unsigned int)target < 0xa0000000) && len)
186 dma_cache_wback_inv((unsigned long)target, len);
187
188 dma_enable();
189
190 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = DMAC_DCCSR_NDES ;
191 REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT);
192 REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)target);
193 REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 4;
194 REG_DMAC_DRSR(DMA_NAND_CHANNEL) = DMAC_DRSR_RS_AUTO;
195 REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT |
196 (bw == 8 ? DMAC_DCMD_SWDH_8 : DMAC_DCMD_SWDH_16));
197 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) |= DMAC_DCCSR_EN; /* Enable DMA channel */
198#if 1
199 while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) )
200 yield();
201#else
202 REG_DMAC_DCMD(DMA_NAND_CHANNEL) |= DMAC_DCMD_TIE; /* Enable DMA interrupt */
203 semaphore_wait(&nand_dma_complete, TIMEOUT_BLOCK);
204#endif
205
206 //REG_DMAC_DCCSR(DMA_NAND_CHANNEL) &= ~DMAC_DCCSR_EN; /* Disable DMA channel */
207
208 dma_disable();
209
210 mutex_unlock(&nand_dma_mtx);
211}
212
213void DMA_CALLBACK(DMA_NAND_CHANNEL)(void)
214{
215 if (REG_DMAC_DCCSR(DMA_NAND_CHANNEL) & DMAC_DCCSR_HLT)
216 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) &= ~DMAC_DCCSR_HLT;
217
218 if (REG_DMAC_DCCSR(DMA_NAND_CHANNEL) & DMAC_DCCSR_AR)
219 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) &= ~DMAC_DCCSR_AR;
220
221 if (REG_DMAC_DCCSR(DMA_NAND_CHANNEL) & DMAC_DCCSR_CT)
222 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) &= ~DMAC_DCCSR_CT;
223
224 if (REG_DMAC_DCCSR(DMA_NAND_CHANNEL) & DMAC_DCCSR_TT)
225 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) &= ~DMAC_DCCSR_TT;
226
227 semaphore_release(&nand_dma_complete);
228}
229#endif /* USE_DMA */
230
231static inline void jz_nand_read_buf(void *buf, int count, int bw)
232{
233#ifdef USE_DMA
234 if (bw == 8)
235 jz_nand_read_dma(buf, count, 8);
236 else
237 jz_nand_read_dma(buf, count, 16);
238#else
239 if (bw == 8)
240 jz_nand_read_buf8(buf, count);
241 else
242 jz_nand_read_buf16(buf, count);
243#endif
244}
245
246#ifdef USE_ECC
247/*
248 * Correct 1~9-bit errors in 512-bytes data
249 */
250static void jz_rs_correct(unsigned char *dat, int idx, int mask)
251{
252 int i, j;
253 unsigned short d, d1, dm;
254
255 i = (idx * 9) >> 3;
256 j = (idx * 9) & 0x7;
257
258 i = (j == 0) ? (i - 1) : i;
259 j = (j == 0) ? 7 : (j - 1);
260
261 if (i > 512)
262 return;
263
264 if (i == 512)
265 d = dat[i - 1];
266 else
267 d = (dat[i] << 8) | dat[i - 1];
268
269 d1 = (d >> j) & 0x1ff;
270 d1 ^= mask;
271
272 dm = ~(0x1ff << j);
273 d = (d & dm) | (d1 << j);
274
275 dat[i - 1] = d & 0xff;
276 if (i < 512)
277 dat[i] = (d >> 8) & 0xff;
278}
279#endif
280
281/*
282 * Read oob
283 */
284static int jz_nand_read_oob(unsigned long page_addr, unsigned char *buf, int size)
285{
286 struct nand_param *nandp = &internal_param;
287 int page_size, row_cycle, bus_width;
288 int col_addr;
289
290 page_size = nandp->page_size;
291 row_cycle = nandp->row_cycle;
292 bus_width = nandp->bus_width;
293
294 if (page_size >= 2048)
295 col_addr = page_size;
296 else
297 col_addr = 0;
298
299 if (page_size >= 2048)
300 /* Send READ0 command */
301 __nand_cmd(NAND_CMD_READ0);
302 else
303 /* Send READOOB command */
304 __nand_cmd(NAND_CMD_READOOB);
305
306 /* Send column address */
307 __nand_addr(col_addr & 0xff);
308 if (page_size >= 2048)
309 __nand_addr((col_addr >> 8) & 0xff);
310
311 /* Send page address */
312 __nand_addr(page_addr & 0xff);
313 __nand_addr((page_addr >> 8) & 0xff);
314 if (row_cycle == 3)
315 __nand_addr((page_addr >> 16) & 0xff);
316
317 /* Send READSTART command for 2048 ps NAND */
318 if (page_size >= 2048)
319 __nand_cmd(NAND_CMD_READSTART);
320
321 /* Wait for device ready */
322 jz_nand_wait_ready();
323
324 /* Read oob data */
325 jz_nand_read_buf(buf, size, bus_width);
326
327 return 0;
328}
329
330
331/*
332 * nand_read_page()
333 *
334 * Input:
335 *
336 * block - block number: 0, 1, 2, ...
337 * page - page number within a block: 0, 1, 2, ...
338 * dst - pointer to target buffer
339 */
340static int jz_nand_read_page(unsigned long page_addr, unsigned char *dst)
341{
342 struct nand_param *nandp = &internal_param;
343 int page_size, oob_size, page_per_block;
344 int row_cycle, bus_width, ecc_count;
345 int i;
346#ifdef USE_ECC
347 int j;
348#endif
349 unsigned char *data_buf;
350 unsigned char oob_buf[nandp->oob_size];
351
352 page_size = nandp->page_size;
353 oob_size = nandp->oob_size;
354 page_per_block = nandp->page_per_block;
355 row_cycle = nandp->row_cycle;
356 bus_width = nandp->bus_width;
357
358 /*
359 * Read oob data
360 */
361 jz_nand_read_oob(page_addr, oob_buf, oob_size);
362
363 /*
364 * Read page data
365 */
366
367 /* Send READ0 command */
368 __nand_cmd(NAND_CMD_READ0);
369
370 /* Send column address */
371 __nand_addr(0);
372 if (page_size >= 2048)
373 __nand_addr(0);
374
375 /* Send page address */
376 __nand_addr(page_addr & 0xff);
377 __nand_addr((page_addr >> 8) & 0xff);
378 if (row_cycle >= 3)
379 __nand_addr((page_addr >> 16) & 0xff);
380
381 /* Send READSTART command for 2048 ps NAND */
382 if (page_size >= 2048)
383 __nand_cmd(NAND_CMD_READSTART);
384
385 /* Wait for device ready */
386 jz_nand_wait_ready();
387
388 /* Read page data */
389 data_buf = dst;
390
391 ecc_count = page_size / ECC_BLOCK;
392
393 for (i = 0; i < ecc_count; i++)
394 {
395#ifdef USE_ECC
396 volatile unsigned char *paraddr = (volatile unsigned char *)EMC_NFPAR0;
397 unsigned int stat;
398
399 /* Enable RS decoding */
400 REG_EMC_NFINTS = 0x0;
401 __ecc_decoding_4bit();
402#endif
403
404 /* Read data */
405 jz_nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width);
406
407#ifdef USE_ECC
408 /* Set PAR values */
409 for (j = 0; j < PAR_SIZE; j++)
410 *paraddr++ = oob_buf[ECC_POS + i*PAR_SIZE + j];
411
412 /* Set PRDY */
413 REG_EMC_NFECR |= EMC_NFECR_PRDY;
414
415 /* Wait for completion */
416 __ecc_decode_sync();
417
418 /* Disable decoding */
419 __ecc_disable();
420
421 /* Check result of decoding */
422 stat = REG_EMC_NFINTS;
423 if (stat & EMC_NFINTS_ERR)
424 {
425 /* Error occurred */
426 if (stat & EMC_NFINTS_UNCOR)
427 {
428 /* Uncorrectable error occurred */
429 logf("Uncorrectable ECC error at NAND page address 0x%lx", page_addr);
430 return -1;
431 }
432 else
433 {
434 unsigned int errcnt, index, mask;
435
436 errcnt = (stat & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
437 switch (errcnt)
438 {
439 case 4:
440 index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
441 mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
442 jz_rs_correct(data_buf, index, mask);
443 case 3:
444 index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
445 mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
446 jz_rs_correct(data_buf, index, mask);
447 case 2:
448 index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
449 mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
450 jz_rs_correct(data_buf, index, mask);
451 case 1:
452 index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
453 mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
454 jz_rs_correct(data_buf, index, mask);
455 break;
456 default:
457 break;
458 }
459 }
460 }
461#endif
462
463 data_buf += ECC_BLOCK;
464 }
465
466 return 0;
467}
468
469static int jz_nand_init(void)
470{
471 unsigned char cData[5];
472
473 __gpio_as_nand_16bit(1);
474
475 REG_NEMC_SMCR1 = CFG_NAND_SMCR1 | 0x40;
476
477 __nand_select();
478
479 __nand_cmd(NAND_CMD_READID);
480 __nand_addr(NAND_CMD_READ0);
481 cData[0] = __nand_data8();
482 cData[1] = __nand_data8();
483 cData[2] = __nand_data8();
484 cData[3] = __nand_data8();
485 cData[4] = __nand_data8();
486
487 __nand_deselect();
488
489 logf("NAND chip %d: 0x%x 0x%x 0x%x 0x%x 0x%x", i+1, cData[0], cData[1],
490 cData[2], cData[3], cData[4]);
491
492 bank = nand_identify(cData);
493
494 if(bank == NULL)
495 {
496 panicf("Unknown NAND flash chip: 0x%x 0x%x 0x%x 0x%x 0x%x", cData[0],
497 cData[1], cData[2], cData[3], cData[4]);
498 return -1; /* panicf() doesn't return though */
499 }
500
501 chip_info = bank;
502
503 internal_param.bus_width = 16;
504 internal_param.row_cycle = chip_info->row_cycles;
505 internal_param.page_size = chip_info->page_size;
506 internal_param.oob_size = chip_info->spare_size;
507 internal_param.page_per_block = chip_info->pages_per_block;
508 internal_param.bad_block_pos = 0;
509
510 nand_size = ((chip_info->page_size * chip_info->blocks_per_bank * chip_info->pages_per_block) - 0x200000) / 512;
511
512 return 0;
513}
514
515int nand_init(void)
516{
517 int res = 0;
518 static bool inited = false;
519
520 if(!inited)
521 {
522 res = jz_nand_init();
523 mutex_init(&nand_mtx);
524#ifdef USE_DMA
525 mutex_init(&nand_dma_mtx);
526 semaphore_init(&nand_dma_complete, 1, 0);
527 system_enable_irq(DMA_IRQ(DMA_NAND_CHANNEL));
528#endif
529
530 inited = true;
531 }
532
533 return res;
534}
535
536static inline int read_sector(unsigned long start, unsigned int count,
537 void* buf, unsigned int chip_size)
538{
539 register int ret;
540
541 if(UNLIKELY(start % chip_size == 0 && count == chip_size))
542 ret = jz_nand_read_page(start / chip_size, buf);
543 else
544 {
545 ret = jz_nand_read_page(start / chip_size, temp_page);
546 memcpy(buf, temp_page + (start % chip_size), count);
547 }
548
549 return ret;
550}
551
552static inline int write_sector(unsigned long start, unsigned int count,
553 const void* buf, unsigned int chip_size)
554{
555 int ret = 0;
556
557 (void)start;
558 (void)count;
559 (void)buf;
560 (void)chip_size;
561
562 /* TODO */
563
564 return ret;
565}
566
567int nand_read_sectors(IF_MV(int drive,) unsigned long start, int count, void* buf)
568{
569#ifdef HAVE_MULTIVOLUME
570 (void)drive;
571#endif
572 int ret = 0;
573 unsigned int _count, chip_size = chip_info->page_size;
574 unsigned long _start;
575
576 logf("start");
577 mutex_lock(&nand_mtx);
578
579 _start = start << 9;
580 _start += 0x200000; /* skip BL */
581 _count = count << 9;
582
583 __nand_select();
584 ret = read_sector(_start, _count, buf, chip_size);
585 __nand_deselect();
586
587 mutex_unlock(&nand_mtx);
588
589 logf("nand_read_sectors(%ld, %d, 0x%x): %d", start, count, (int)buf, ret);
590
591 return ret;
592}
593
594int nand_write_sectors(IF_MV(int drive,) unsigned long start, int count, const void* buf)
595{
596#ifdef HAVE_MULTIVOLUME
597 (void)drive;
598#endif
599 int ret = 0;
600 unsigned int _count, chip_size = chip_info->page_size;
601 unsigned long _start;
602
603 logf("start");
604 mutex_lock(&nand_mtx);
605
606 _start = start << 9;
607 _start += chip_info->page_size * chip_info->pages_per_block; /* skip BL */
608 _count = count << 9;
609
610 __nand_select();
611 ret = write_sector(_start, _count, buf, chip_size);
612 __nand_deselect();
613
614 mutex_unlock(&nand_mtx);
615
616 logf("nand_write_sectors(%ld, %d, 0x%x): %d", start, count, (int)buf, ret);
617
618 return ret;
619}
620
621#ifdef HAVE_STORAGE_FLUSH
622int nand_flush(void)
623{
624 return 0;
625}
626#endif
627
628void nand_spindown(int seconds)
629{
630 /* null */
631 (void)seconds;
632}
633
634void nand_sleep(void)
635{
636 /* null */
637}
638
639void nand_spin(void)
640{
641 /* null */
642}
643
644void nand_enable(bool on)
645{
646 /* null - flash controller is enabled/disabled as needed. */
647 (void)on;
648}
649
650/* TODO */
651long nand_last_disk_activity(void)
652{
653 return 0;
654}
655
656int nand_spinup_time(void)
657{
658 return 0;
659}
660
661void nand_sleepnow(void)
662{
663}
664
665#ifdef STORAGE_GET_INFO
666void nand_get_info(IF_MV(int drive,) struct storage_info *info)
667{
668#ifdef HAVE_MULTIVOLUME
669 (void)drive;
670#endif
671
672 /* firmware version */
673 info->revision="0.00";
674
675 info->vendor="Rockbox";
676 info->product="NAND Storage";
677
678 /* blocks count */
679 info->num_sectors = nand_size;
680 info->sector_size = 512;
681}
682#endif
683
684#ifdef CONFIG_STORAGE_MULTI
685int nand_num_drives(int first_drive)
686{
687 /* We don't care which logical drive number(s) we have been assigned */
688 (void)first_drive;
689
690 return 1;
691}
692#endif