Skip to content

Commit 4eb2da8

Browse files
Lei WenDavid Woodhouse
authored andcommitted
mtd: pxa3xx_nand: unify prepare command
Make the interface simpler which could make both debug and enhancement easier. Signed-off-by: Lei Wen <[email protected]> Signed-off-by: Haojian Zhuang <[email protected]> Signed-off-by: David Woodhouse <[email protected]>
1 parent 38caf7f commit 4eb2da8

File tree

1 file changed

+139
-110
lines changed

1 file changed

+139
-110
lines changed

drivers/mtd/nand/pxa3xx_nand.c

Lines changed: 139 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#define CHIP_DELAY_TIMEOUT (2 * HZ/10)
3030
#define NAND_STOP_DELAY (2 * HZ/50)
31+
#define PAGE_CHUNK_SIZE (2048)
3132

3233
/* registers and bit definitions */
3334
#define NDCR (0x00) /* Control register */
@@ -77,6 +78,7 @@
7778
#define NDSR_RDDREQ (0x1 << 1)
7879
#define NDSR_WRCMDREQ (0x1)
7980

81+
#define NDCB0_ST_ROW_EN (0x1 << 26)
8082
#define NDCB0_AUTO_RS (0x1 << 25)
8183
#define NDCB0_CSEL (0x1 << 24)
8284
#define NDCB0_CMD_TYPE_MASK (0x7 << 21)
@@ -319,66 +321,6 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
319321
nand_writel(info, NDSR, NDSR_MASK);
320322
}
321323

322-
static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
323-
uint16_t cmd, int column, int page_addr)
324-
{
325-
const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
326-
pxa3xx_set_datasize(info);
327-
328-
/* generate values for NDCBx registers */
329-
info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
330-
info->ndcb1 = 0;
331-
info->ndcb2 = 0;
332-
info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles);
333-
334-
if (info->col_addr_cycles == 2) {
335-
/* large block, 2 cycles for column address
336-
* row address starts from 3rd cycle
337-
*/
338-
info->ndcb1 |= page_addr << 16;
339-
if (info->row_addr_cycles == 3)
340-
info->ndcb2 = (page_addr >> 16) & 0xff;
341-
} else
342-
/* small block, 1 cycles for column address
343-
* row address starts from 2nd cycle
344-
*/
345-
info->ndcb1 = page_addr << 8;
346-
347-
if (cmd == cmdset->program)
348-
info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
349-
}
350-
351-
static void prepare_erase_cmd(struct pxa3xx_nand_info *info,
352-
uint16_t cmd, int page_addr)
353-
{
354-
info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
355-
info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
356-
info->ndcb1 = page_addr;
357-
info->ndcb2 = 0;
358-
}
359-
360-
static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
361-
{
362-
const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
363-
364-
info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
365-
info->ndcb1 = 0;
366-
info->ndcb2 = 0;
367-
368-
info->oob_size = 0;
369-
if (cmd == cmdset->read_id) {
370-
info->ndcb0 |= NDCB0_CMD_TYPE(3) | NDCB0_ADDR_CYC(1);
371-
info->data_size = 8;
372-
} else if (cmd == cmdset->read_status) {
373-
info->ndcb0 |= NDCB0_CMD_TYPE(4);
374-
info->data_size = 8;
375-
} else if (cmd == cmdset->reset || cmd == cmdset->lock ||
376-
cmd == cmdset->unlock) {
377-
info->ndcb0 |= NDCB0_CMD_TYPE(5);
378-
} else
379-
BUG();
380-
}
381-
382324
static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
383325
{
384326
uint32_t ndcr;
@@ -529,81 +471,167 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
529471
return 1;
530472
}
531473

532-
static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
533-
int column, int page_addr)
474+
static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
475+
uint16_t column, int page_addr)
534476
{
535-
struct pxa3xx_nand_info *info = mtd->priv;
536-
const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
537-
int ret, exec_cmd = 0;
477+
uint16_t cmd;
478+
int addr_cycle, exec_cmd, ndcb0;
479+
struct mtd_info *mtd = info->mtd;
480+
481+
ndcb0 = 0;
482+
addr_cycle = 0;
483+
exec_cmd = 1;
538484

539-
info->use_dma = (use_dma) ? 1 : 0;
540-
info->use_ecc = 0;
541-
info->data_size = 0;
542-
info->state = 0;
543-
info->retcode = ERR_NONE;
485+
/* reset data and oob column point to handle data */
486+
info->buf_start = 0;
487+
info->buf_count = 0;
488+
info->oob_size = 0;
489+
info->use_ecc = 0;
490+
info->retcode = ERR_NONE;
544491

545492
switch (command) {
493+
case NAND_CMD_READ0:
494+
case NAND_CMD_PAGEPROG:
495+
info->use_ecc = 1;
546496
case NAND_CMD_READOOB:
547-
/* disable HW ECC to get all the OOB data */
548-
info->buf_count = mtd->writesize + mtd->oobsize;
549-
info->buf_start = mtd->writesize + column;
550-
memset(info->data_buff, 0xFF, info->buf_count);
551-
552-
prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
553-
exec_cmd = 1;
497+
pxa3xx_set_datasize(info);
498+
break;
499+
case NAND_CMD_SEQIN:
500+
exec_cmd = 0;
501+
break;
502+
default:
503+
info->ndcb1 = 0;
504+
info->ndcb2 = 0;
554505
break;
506+
}
507+
508+
info->ndcb0 = ndcb0;
509+
addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
510+
+ info->col_addr_cycles);
555511

512+
switch (command) {
513+
case NAND_CMD_READOOB:
556514
case NAND_CMD_READ0:
557-
info->use_ecc = 1;
558-
info->buf_start = column;
559-
info->buf_count = mtd->writesize + mtd->oobsize;
560-
memset(info->data_buff, 0xFF, info->buf_count);
515+
cmd = info->cmdset->read1;
516+
if (command == NAND_CMD_READOOB)
517+
info->buf_start = mtd->writesize + column;
518+
else
519+
info->buf_start = column;
520+
521+
if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
522+
info->ndcb0 |= NDCB0_CMD_TYPE(0)
523+
| addr_cycle
524+
| (cmd & NDCB0_CMD1_MASK);
525+
else
526+
info->ndcb0 |= NDCB0_CMD_TYPE(0)
527+
| NDCB0_DBC
528+
| addr_cycle
529+
| cmd;
561530

562-
prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
563-
exec_cmd = 1;
564-
break;
565531
case NAND_CMD_SEQIN:
566-
info->buf_start = column;
532+
/* small page addr setting */
533+
if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
534+
info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
535+
| (column & 0xFF);
536+
537+
info->ndcb2 = 0;
538+
} else {
539+
info->ndcb1 = ((page_addr & 0xFFFF) << 16)
540+
| (column & 0xFFFF);
541+
542+
if (page_addr & 0xFF0000)
543+
info->ndcb2 = (page_addr & 0xFF0000) >> 16;
544+
else
545+
info->ndcb2 = 0;
546+
}
547+
567548
info->buf_count = mtd->writesize + mtd->oobsize;
568-
memset(info->data_buff, 0xff, info->buf_count);
549+
memset(info->data_buff, 0xFF, info->buf_count);
569550

570-
/* save column/page_addr for next CMD_PAGEPROG */
571-
info->seqin_column = column;
572-
info->seqin_page_addr = page_addr;
573551
break;
552+
574553
case NAND_CMD_PAGEPROG:
575-
info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
554+
if (is_buf_blank(info->data_buff,
555+
(mtd->writesize + mtd->oobsize))) {
556+
exec_cmd = 0;
557+
break;
558+
}
576559

577-
prepare_read_prog_cmd(info, cmdset->program,
578-
info->seqin_column, info->seqin_page_addr);
579-
exec_cmd = 1;
580-
break;
581-
case NAND_CMD_ERASE1:
582-
prepare_erase_cmd(info, cmdset->erase, page_addr);
583-
exec_cmd = 1;
584-
break;
585-
case NAND_CMD_ERASE2:
560+
cmd = info->cmdset->program;
561+
info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
562+
| NDCB0_AUTO_RS
563+
| NDCB0_ST_ROW_EN
564+
| NDCB0_DBC
565+
| cmd
566+
| addr_cycle;
586567
break;
568+
587569
case NAND_CMD_READID:
570+
cmd = info->cmdset->read_id;
571+
info->buf_count = info->read_id_bytes;
572+
info->ndcb0 |= NDCB0_CMD_TYPE(3)
573+
| NDCB0_ADDR_CYC(1)
574+
| cmd;
575+
576+
info->data_size = 8;
577+
break;
588578
case NAND_CMD_STATUS:
589-
info->use_dma = 0; /* force PIO read */
590-
info->buf_start = 0;
591-
info->buf_count = (command == NAND_CMD_READID) ?
592-
info->read_id_bytes : 1;
593-
594-
prepare_other_cmd(info, (command == NAND_CMD_READID) ?
595-
cmdset->read_id : cmdset->read_status);
596-
exec_cmd = 1;
579+
cmd = info->cmdset->read_status;
580+
info->buf_count = 1;
581+
info->ndcb0 |= NDCB0_CMD_TYPE(4)
582+
| NDCB0_ADDR_CYC(1)
583+
| cmd;
584+
585+
info->data_size = 8;
586+
break;
587+
588+
case NAND_CMD_ERASE1:
589+
cmd = info->cmdset->erase;
590+
info->ndcb0 |= NDCB0_CMD_TYPE(2)
591+
| NDCB0_AUTO_RS
592+
| NDCB0_ADDR_CYC(3)
593+
| NDCB0_DBC
594+
| cmd;
595+
info->ndcb1 = page_addr;
596+
info->ndcb2 = 0;
597+
597598
break;
598599
case NAND_CMD_RESET:
599-
prepare_other_cmd(info, cmdset->reset);
600-
exec_cmd = 1;
600+
cmd = info->cmdset->reset;
601+
info->ndcb0 |= NDCB0_CMD_TYPE(5)
602+
| cmd;
603+
604+
break;
605+
606+
case NAND_CMD_ERASE2:
607+
exec_cmd = 0;
601608
break;
609+
602610
default:
603-
printk(KERN_ERR "non-supported command.\n");
611+
exec_cmd = 0;
612+
printk(KERN_ERR "pxa3xx-nand: non-supported"
613+
" command %x\n", command);
604614
break;
605615
}
606616

617+
return exec_cmd;
618+
}
619+
620+
static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
621+
int column, int page_addr)
622+
{
623+
struct pxa3xx_nand_info *info = mtd->priv;
624+
int ret, exec_cmd;
625+
626+
/*
627+
* if this is a x16 device ,then convert the input
628+
* "byte" address into a "word" address appropriate
629+
* for indexing a word-oriented device
630+
*/
631+
if (info->reg_ndcr & NDCR_DWIDTH_M)
632+
column /= 2;
633+
634+
exec_cmd = prepare_command_pool(info, command, column, page_addr);
607635
if (exec_cmd) {
608636
init_completion(&info->cmd_complete);
609637
pxa3xx_nand_start(info);
@@ -919,6 +947,7 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
919947
struct nand_chip *this = &info->nand_chip;
920948

921949
this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;
950+
this->options |= NAND_NO_AUTOINCR;
922951

923952
this->waitfunc = pxa3xx_nand_waitfunc;
924953
this->select_chip = pxa3xx_nand_select_chip;

0 commit comments

Comments
 (0)