diff options
| -rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 292 |
1 files changed, 160 insertions, 132 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index e55d7f8df978..97b689499119 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
| @@ -110,6 +110,7 @@ enum { | |||
| 110 | 110 | ||
| 111 | enum { | 111 | enum { |
| 112 | STATE_IDLE = 0, | 112 | STATE_IDLE = 0, |
| 113 | STATE_PREPARED, | ||
| 113 | STATE_CMD_HANDLE, | 114 | STATE_CMD_HANDLE, |
| 114 | STATE_DMA_READING, | 115 | STATE_DMA_READING, |
| 115 | STATE_DMA_WRITING, | 116 | STATE_DMA_WRITING, |
| @@ -120,21 +121,39 @@ enum { | |||
| 120 | STATE_READY, | 121 | STATE_READY, |
| 121 | }; | 122 | }; |
| 122 | 123 | ||
| 123 | struct pxa3xx_nand_info { | 124 | struct pxa3xx_nand_host { |
| 124 | struct nand_chip nand_chip; | 125 | struct nand_chip chip; |
| 126 | struct pxa3xx_nand_cmdset *cmdset; | ||
| 127 | struct mtd_info *mtd; | ||
| 128 | void *info_data; | ||
| 129 | |||
| 130 | /* page size of attached chip */ | ||
| 131 | unsigned int page_size; | ||
| 132 | int use_ecc; | ||
| 125 | 133 | ||
| 134 | /* calculated from pxa3xx_nand_flash data */ | ||
| 135 | unsigned int col_addr_cycles; | ||
| 136 | unsigned int row_addr_cycles; | ||
| 137 | size_t read_id_bytes; | ||
| 138 | |||
| 139 | /* cached register value */ | ||
| 140 | uint32_t reg_ndcr; | ||
| 141 | uint32_t ndtr0cs0; | ||
| 142 | uint32_t ndtr1cs0; | ||
| 143 | }; | ||
| 144 | |||
| 145 | struct pxa3xx_nand_info { | ||
| 126 | struct nand_hw_control controller; | 146 | struct nand_hw_control controller; |
| 127 | struct platform_device *pdev; | 147 | struct platform_device *pdev; |
| 128 | struct pxa3xx_nand_cmdset *cmdset; | ||
| 129 | 148 | ||
| 130 | struct clk *clk; | 149 | struct clk *clk; |
| 131 | void __iomem *mmio_base; | 150 | void __iomem *mmio_base; |
| 132 | unsigned long mmio_phys; | 151 | unsigned long mmio_phys; |
| 152 | struct completion cmd_complete; | ||
| 133 | 153 | ||
| 134 | unsigned int buf_start; | 154 | unsigned int buf_start; |
| 135 | unsigned int buf_count; | 155 | unsigned int buf_count; |
| 136 | 156 | ||
| 137 | struct mtd_info *mtd; | ||
| 138 | /* DMA information */ | 157 | /* DMA information */ |
| 139 | int drcmr_dat; | 158 | int drcmr_dat; |
| 140 | int drcmr_cmd; | 159 | int drcmr_cmd; |
| @@ -142,18 +161,11 @@ struct pxa3xx_nand_info { | |||
| 142 | unsigned char *data_buff; | 161 | unsigned char *data_buff; |
| 143 | unsigned char *oob_buff; | 162 | unsigned char *oob_buff; |
| 144 | dma_addr_t data_buff_phys; | 163 | dma_addr_t data_buff_phys; |
| 145 | size_t data_buff_size; | ||
| 146 | int data_dma_ch; | 164 | int data_dma_ch; |
| 147 | struct pxa_dma_desc *data_desc; | 165 | struct pxa_dma_desc *data_desc; |
| 148 | dma_addr_t data_desc_addr; | 166 | dma_addr_t data_desc_addr; |
| 149 | 167 | ||
| 150 | uint32_t reg_ndcr; | 168 | struct pxa3xx_nand_host *host; |
| 151 | |||
| 152 | /* saved column/page_addr during CMD_SEQIN */ | ||
| 153 | int seqin_column; | ||
| 154 | int seqin_page_addr; | ||
| 155 | |||
| 156 | /* relate to the command */ | ||
| 157 | unsigned int state; | 169 | unsigned int state; |
| 158 | 170 | ||
| 159 | int use_ecc; /* use HW ECC ? */ | 171 | int use_ecc; /* use HW ECC ? */ |
| @@ -162,24 +174,13 @@ struct pxa3xx_nand_info { | |||
| 162 | 174 | ||
| 163 | unsigned int page_size; /* page size of attached chip */ | 175 | unsigned int page_size; /* page size of attached chip */ |
| 164 | unsigned int data_size; /* data size in FIFO */ | 176 | unsigned int data_size; /* data size in FIFO */ |
| 177 | unsigned int oob_size; | ||
| 165 | int retcode; | 178 | int retcode; |
| 166 | struct completion cmd_complete; | ||
| 167 | 179 | ||
| 168 | /* generated NDCBx register values */ | 180 | /* generated NDCBx register values */ |
| 169 | uint32_t ndcb0; | 181 | uint32_t ndcb0; |
| 170 | uint32_t ndcb1; | 182 | uint32_t ndcb1; |
| 171 | uint32_t ndcb2; | 183 | uint32_t ndcb2; |
| 172 | |||
| 173 | /* timing calcuted from setting */ | ||
| 174 | uint32_t ndtr0cs0; | ||
| 175 | uint32_t ndtr1cs0; | ||
| 176 | |||
| 177 | /* calculated from pxa3xx_nand_flash data */ | ||
| 178 | size_t oob_size; | ||
| 179 | size_t read_id_bytes; | ||
| 180 | |||
| 181 | unsigned int col_addr_cycles; | ||
| 182 | unsigned int row_addr_cycles; | ||
| 183 | }; | 184 | }; |
| 184 | 185 | ||
| 185 | static int use_dma = 1; | 186 | static int use_dma = 1; |
| @@ -241,9 +242,10 @@ const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; | |||
| 241 | /* convert nano-seconds to nand flash controller clock cycles */ | 242 | /* convert nano-seconds to nand flash controller clock cycles */ |
| 242 | #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) | 243 | #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) |
| 243 | 244 | ||
| 244 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | 245 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host, |
| 245 | const struct pxa3xx_nand_timing *t) | 246 | const struct pxa3xx_nand_timing *t) |
| 246 | { | 247 | { |
| 248 | struct pxa3xx_nand_info *info = host->info_data; | ||
| 247 | unsigned long nand_clk = clk_get_rate(info->clk); | 249 | unsigned long nand_clk = clk_get_rate(info->clk); |
| 248 | uint32_t ndtr0, ndtr1; | 250 | uint32_t ndtr0, ndtr1; |
| 249 | 251 | ||
| @@ -258,23 +260,24 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | |||
| 258 | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | | 260 | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | |
| 259 | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); | 261 | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); |
| 260 | 262 | ||
| 261 | info->ndtr0cs0 = ndtr0; | 263 | host->ndtr0cs0 = ndtr0; |
| 262 | info->ndtr1cs0 = ndtr1; | 264 | host->ndtr1cs0 = ndtr1; |
| 263 | nand_writel(info, NDTR0CS0, ndtr0); | 265 | nand_writel(info, NDTR0CS0, ndtr0); |
| 264 | nand_writel(info, NDTR1CS0, ndtr1); | 266 | nand_writel(info, NDTR1CS0, ndtr1); |
| 265 | } | 267 | } |
| 266 | 268 | ||
| 267 | static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) | 269 | static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) |
| 268 | { | 270 | { |
| 269 | int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; | 271 | struct pxa3xx_nand_host *host = info->host; |
| 272 | int oob_enable = host->reg_ndcr & NDCR_SPARE_EN; | ||
| 270 | 273 | ||
| 271 | info->data_size = info->page_size; | 274 | info->data_size = host->page_size; |
| 272 | if (!oob_enable) { | 275 | if (!oob_enable) { |
| 273 | info->oob_size = 0; | 276 | info->oob_size = 0; |
| 274 | return; | 277 | return; |
| 275 | } | 278 | } |
| 276 | 279 | ||
| 277 | switch (info->page_size) { | 280 | switch (host->page_size) { |
| 278 | case 2048: | 281 | case 2048: |
| 279 | info->oob_size = (info->use_ecc) ? 40 : 64; | 282 | info->oob_size = (info->use_ecc) ? 40 : 64; |
| 280 | break; | 283 | break; |
| @@ -292,9 +295,10 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) | |||
| 292 | */ | 295 | */ |
| 293 | static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) | 296 | static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) |
| 294 | { | 297 | { |
| 298 | struct pxa3xx_nand_host *host = info->host; | ||
| 295 | uint32_t ndcr; | 299 | uint32_t ndcr; |
| 296 | 300 | ||
| 297 | ndcr = info->reg_ndcr; | 301 | ndcr = host->reg_ndcr; |
| 298 | ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; | 302 | ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; |
| 299 | ndcr |= info->use_dma ? NDCR_DMA_EN : 0; | 303 | ndcr |= info->use_dma ? NDCR_DMA_EN : 0; |
| 300 | ndcr |= NDCR_ND_RUN; | 304 | ndcr |= NDCR_ND_RUN; |
| @@ -463,12 +467,6 @@ NORMAL_IRQ_EXIT: | |||
| 463 | return IRQ_HANDLED; | 467 | return IRQ_HANDLED; |
| 464 | } | 468 | } |
| 465 | 469 | ||
| 466 | static int pxa3xx_nand_dev_ready(struct mtd_info *mtd) | ||
| 467 | { | ||
| 468 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 469 | return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0; | ||
| 470 | } | ||
| 471 | |||
| 472 | static inline int is_buf_blank(uint8_t *buf, size_t len) | 470 | static inline int is_buf_blank(uint8_t *buf, size_t len) |
| 473 | { | 471 | { |
| 474 | for (; len > 0; len--) | 472 | for (; len > 0; len--) |
| @@ -481,10 +479,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
| 481 | uint16_t column, int page_addr) | 479 | uint16_t column, int page_addr) |
| 482 | { | 480 | { |
| 483 | uint16_t cmd; | 481 | uint16_t cmd; |
| 484 | int addr_cycle, exec_cmd, ndcb0; | 482 | int addr_cycle, exec_cmd; |
| 485 | struct mtd_info *mtd = info->mtd; | 483 | struct pxa3xx_nand_host *host = info->host; |
| 484 | struct mtd_info *mtd = host->mtd; | ||
| 486 | 485 | ||
| 487 | ndcb0 = 0; | ||
| 488 | addr_cycle = 0; | 486 | addr_cycle = 0; |
| 489 | exec_cmd = 1; | 487 | exec_cmd = 1; |
| 490 | 488 | ||
| @@ -494,6 +492,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
| 494 | info->oob_size = 0; | 492 | info->oob_size = 0; |
| 495 | info->use_ecc = 0; | 493 | info->use_ecc = 0; |
| 496 | info->is_ready = 0; | 494 | info->is_ready = 0; |
| 495 | info->ndcb0 = 0; | ||
| 497 | info->retcode = ERR_NONE; | 496 | info->retcode = ERR_NONE; |
| 498 | 497 | ||
| 499 | switch (command) { | 498 | switch (command) { |
| @@ -512,20 +511,19 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
| 512 | break; | 511 | break; |
| 513 | } | 512 | } |
| 514 | 513 | ||
| 515 | info->ndcb0 = ndcb0; | 514 | addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles |
| 516 | addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles | 515 | + host->col_addr_cycles); |
| 517 | + info->col_addr_cycles); | ||
| 518 | 516 | ||
| 519 | switch (command) { | 517 | switch (command) { |
| 520 | case NAND_CMD_READOOB: | 518 | case NAND_CMD_READOOB: |
| 521 | case NAND_CMD_READ0: | 519 | case NAND_CMD_READ0: |
| 522 | cmd = info->cmdset->read1; | 520 | cmd = host->cmdset->read1; |
| 523 | if (command == NAND_CMD_READOOB) | 521 | if (command == NAND_CMD_READOOB) |
| 524 | info->buf_start = mtd->writesize + column; | 522 | info->buf_start = mtd->writesize + column; |
| 525 | else | 523 | else |
| 526 | info->buf_start = column; | 524 | info->buf_start = column; |
| 527 | 525 | ||
| 528 | if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) | 526 | if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) |
| 529 | info->ndcb0 |= NDCB0_CMD_TYPE(0) | 527 | info->ndcb0 |= NDCB0_CMD_TYPE(0) |
| 530 | | addr_cycle | 528 | | addr_cycle |
| 531 | | (cmd & NDCB0_CMD1_MASK); | 529 | | (cmd & NDCB0_CMD1_MASK); |
| @@ -537,7 +535,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
| 537 | 535 | ||
| 538 | case NAND_CMD_SEQIN: | 536 | case NAND_CMD_SEQIN: |
| 539 | /* small page addr setting */ | 537 | /* small page addr setting */ |
| 540 | if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) { | 538 | if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) { |
| 541 | info->ndcb1 = ((page_addr & 0xFFFFFF) << 8) | 539 | info->ndcb1 = ((page_addr & 0xFFFFFF) << 8) |
| 542 | | (column & 0xFF); | 540 | | (column & 0xFF); |
| 543 | 541 | ||
| @@ -564,7 +562,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
| 564 | break; | 562 | break; |
| 565 | } | 563 | } |
| 566 | 564 | ||
| 567 | cmd = info->cmdset->program; | 565 | cmd = host->cmdset->program; |
| 568 | info->ndcb0 |= NDCB0_CMD_TYPE(0x1) | 566 | info->ndcb0 |= NDCB0_CMD_TYPE(0x1) |
| 569 | | NDCB0_AUTO_RS | 567 | | NDCB0_AUTO_RS |
| 570 | | NDCB0_ST_ROW_EN | 568 | | NDCB0_ST_ROW_EN |
| @@ -574,8 +572,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
| 574 | break; | 572 | break; |
| 575 | 573 | ||
| 576 | case NAND_CMD_READID: | 574 | case NAND_CMD_READID: |
| 577 | cmd = info->cmdset->read_id; | 575 | cmd = host->cmdset->read_id; |
| 578 | info->buf_count = info->read_id_bytes; | 576 | info->buf_count = host->read_id_bytes; |
| 579 | info->ndcb0 |= NDCB0_CMD_TYPE(3) | 577 | info->ndcb0 |= NDCB0_CMD_TYPE(3) |
| 580 | | NDCB0_ADDR_CYC(1) | 578 | | NDCB0_ADDR_CYC(1) |
| 581 | | cmd; | 579 | | cmd; |
| @@ -583,7 +581,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
| 583 | info->data_size = 8; | 581 | info->data_size = 8; |
| 584 | break; | 582 | break; |
| 585 | case NAND_CMD_STATUS: | 583 | case NAND_CMD_STATUS: |
| 586 | cmd = info->cmdset->read_status; | 584 | cmd = host->cmdset->read_status; |
| 587 | info->buf_count = 1; | 585 | info->buf_count = 1; |
| 588 | info->ndcb0 |= NDCB0_CMD_TYPE(4) | 586 | info->ndcb0 |= NDCB0_CMD_TYPE(4) |
| 589 | | NDCB0_ADDR_CYC(1) | 587 | | NDCB0_ADDR_CYC(1) |
| @@ -593,7 +591,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
| 593 | break; | 591 | break; |
| 594 | 592 | ||
| 595 | case NAND_CMD_ERASE1: | 593 | case NAND_CMD_ERASE1: |
| 596 | cmd = info->cmdset->erase; | 594 | cmd = host->cmdset->erase; |
| 597 | info->ndcb0 |= NDCB0_CMD_TYPE(2) | 595 | info->ndcb0 |= NDCB0_CMD_TYPE(2) |
| 598 | | NDCB0_AUTO_RS | 596 | | NDCB0_AUTO_RS |
| 599 | | NDCB0_ADDR_CYC(3) | 597 | | NDCB0_ADDR_CYC(3) |
| @@ -604,7 +602,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
| 604 | 602 | ||
| 605 | break; | 603 | break; |
| 606 | case NAND_CMD_RESET: | 604 | case NAND_CMD_RESET: |
| 607 | cmd = info->cmdset->reset; | 605 | cmd = host->cmdset->reset; |
| 608 | info->ndcb0 |= NDCB0_CMD_TYPE(5) | 606 | info->ndcb0 |= NDCB0_CMD_TYPE(5) |
| 609 | | cmd; | 607 | | cmd; |
| 610 | 608 | ||
| @@ -627,7 +625,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | |||
| 627 | static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | 625 | static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, |
| 628 | int column, int page_addr) | 626 | int column, int page_addr) |
| 629 | { | 627 | { |
| 630 | struct pxa3xx_nand_info *info = mtd->priv; | 628 | struct pxa3xx_nand_host *host = mtd->priv; |
| 629 | struct pxa3xx_nand_info *info = host->info_data; | ||
| 631 | int ret, exec_cmd; | 630 | int ret, exec_cmd; |
| 632 | 631 | ||
| 633 | /* | 632 | /* |
| @@ -635,9 +634,10 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
| 635 | * "byte" address into a "word" address appropriate | 634 | * "byte" address into a "word" address appropriate |
| 636 | * for indexing a word-oriented device | 635 | * for indexing a word-oriented device |
| 637 | */ | 636 | */ |
| 638 | if (info->reg_ndcr & NDCR_DWIDTH_M) | 637 | if (host->reg_ndcr & NDCR_DWIDTH_M) |
| 639 | column /= 2; | 638 | column /= 2; |
| 640 | 639 | ||
| 640 | info->state = STATE_PREPARED; | ||
| 641 | exec_cmd = prepare_command_pool(info, command, column, page_addr); | 641 | exec_cmd = prepare_command_pool(info, command, column, page_addr); |
| 642 | if (exec_cmd) { | 642 | if (exec_cmd) { |
| 643 | init_completion(&info->cmd_complete); | 643 | init_completion(&info->cmd_complete); |
| @@ -650,8 +650,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
| 650 | /* Stop State Machine for next command cycle */ | 650 | /* Stop State Machine for next command cycle */ |
| 651 | pxa3xx_nand_stop(info); | 651 | pxa3xx_nand_stop(info); |
| 652 | } | 652 | } |
| 653 | info->state = STATE_IDLE; | ||
| 654 | } | 653 | } |
| 654 | info->state = STATE_IDLE; | ||
| 655 | } | 655 | } |
| 656 | 656 | ||
| 657 | static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, | 657 | static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, |
| @@ -664,7 +664,8 @@ static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, | |||
| 664 | static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, | 664 | static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, |
| 665 | struct nand_chip *chip, uint8_t *buf, int page) | 665 | struct nand_chip *chip, uint8_t *buf, int page) |
| 666 | { | 666 | { |
| 667 | struct pxa3xx_nand_info *info = mtd->priv; | 667 | struct pxa3xx_nand_host *host = mtd->priv; |
| 668 | struct pxa3xx_nand_info *info = host->info_data; | ||
| 668 | 669 | ||
| 669 | chip->read_buf(mtd, buf, mtd->writesize); | 670 | chip->read_buf(mtd, buf, mtd->writesize); |
| 670 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | 671 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); |
| @@ -695,7 +696,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, | |||
| 695 | 696 | ||
| 696 | static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) | 697 | static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) |
| 697 | { | 698 | { |
| 698 | struct pxa3xx_nand_info *info = mtd->priv; | 699 | struct pxa3xx_nand_host *host = mtd->priv; |
| 700 | struct pxa3xx_nand_info *info = host->info_data; | ||
| 699 | char retval = 0xFF; | 701 | char retval = 0xFF; |
| 700 | 702 | ||
| 701 | if (info->buf_start < info->buf_count) | 703 | if (info->buf_start < info->buf_count) |
| @@ -707,7 +709,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) | |||
| 707 | 709 | ||
| 708 | static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) | 710 | static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) |
| 709 | { | 711 | { |
| 710 | struct pxa3xx_nand_info *info = mtd->priv; | 712 | struct pxa3xx_nand_host *host = mtd->priv; |
| 713 | struct pxa3xx_nand_info *info = host->info_data; | ||
| 711 | u16 retval = 0xFFFF; | 714 | u16 retval = 0xFFFF; |
| 712 | 715 | ||
| 713 | if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) { | 716 | if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) { |
| @@ -719,7 +722,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) | |||
| 719 | 722 | ||
| 720 | static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | 723 | static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
| 721 | { | 724 | { |
| 722 | struct pxa3xx_nand_info *info = mtd->priv; | 725 | struct pxa3xx_nand_host *host = mtd->priv; |
| 726 | struct pxa3xx_nand_info *info = host->info_data; | ||
| 723 | int real_len = min_t(size_t, len, info->buf_count - info->buf_start); | 727 | int real_len = min_t(size_t, len, info->buf_count - info->buf_start); |
| 724 | 728 | ||
| 725 | memcpy(buf, info->data_buff + info->buf_start, real_len); | 729 | memcpy(buf, info->data_buff + info->buf_start, real_len); |
| @@ -729,7 +733,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
| 729 | static void pxa3xx_nand_write_buf(struct mtd_info *mtd, | 733 | static void pxa3xx_nand_write_buf(struct mtd_info *mtd, |
| 730 | const uint8_t *buf, int len) | 734 | const uint8_t *buf, int len) |
| 731 | { | 735 | { |
| 732 | struct pxa3xx_nand_info *info = mtd->priv; | 736 | struct pxa3xx_nand_host *host = mtd->priv; |
| 737 | struct pxa3xx_nand_info *info = host->info_data; | ||
| 733 | int real_len = min_t(size_t, len, info->buf_count - info->buf_start); | 738 | int real_len = min_t(size_t, len, info->buf_count - info->buf_start); |
| 734 | 739 | ||
| 735 | memcpy(info->data_buff + info->buf_start, buf, real_len); | 740 | memcpy(info->data_buff + info->buf_start, buf, real_len); |
| @@ -749,7 +754,8 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip) | |||
| 749 | 754 | ||
| 750 | static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) | 755 | static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) |
| 751 | { | 756 | { |
| 752 | struct pxa3xx_nand_info *info = mtd->priv; | 757 | struct pxa3xx_nand_host *host = mtd->priv; |
| 758 | struct pxa3xx_nand_info *info = host->info_data; | ||
| 753 | 759 | ||
| 754 | /* pxa3xx_nand_send_command has waited for command complete */ | 760 | /* pxa3xx_nand_send_command has waited for command complete */ |
| 755 | if (this->state == FL_WRITING || this->state == FL_ERASING) { | 761 | if (this->state == FL_WRITING || this->state == FL_ERASING) { |
| @@ -772,6 +778,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
| 772 | { | 778 | { |
| 773 | struct platform_device *pdev = info->pdev; | 779 | struct platform_device *pdev = info->pdev; |
| 774 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; | 780 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; |
| 781 | struct pxa3xx_nand_host *host = info->host; | ||
| 775 | uint32_t ndcr = 0x0; /* enable all interrupts */ | 782 | uint32_t ndcr = 0x0; /* enable all interrupts */ |
| 776 | 783 | ||
| 777 | if (f->page_size != 2048 && f->page_size != 512) { | 784 | if (f->page_size != 2048 && f->page_size != 512) { |
| @@ -785,45 +792,52 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
| 785 | } | 792 | } |
| 786 | 793 | ||
| 787 | /* calculate flash information */ | 794 | /* calculate flash information */ |
| 788 | info->cmdset = &default_cmdset; | 795 | host->cmdset = &default_cmdset; |
| 789 | info->page_size = f->page_size; | 796 | host->page_size = f->page_size; |
| 790 | info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; | 797 | host->read_id_bytes = (f->page_size == 2048) ? 4 : 2; |
| 791 | 798 | ||
| 792 | /* calculate addressing information */ | 799 | /* calculate addressing information */ |
| 793 | info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1; | 800 | host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1; |
| 794 | 801 | ||
| 795 | if (f->num_blocks * f->page_per_block > 65536) | 802 | if (f->num_blocks * f->page_per_block > 65536) |
| 796 | info->row_addr_cycles = 3; | 803 | host->row_addr_cycles = 3; |
| 797 | else | 804 | else |
| 798 | info->row_addr_cycles = 2; | 805 | host->row_addr_cycles = 2; |
| 799 | 806 | ||
| 800 | ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; | 807 | ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; |
| 801 | ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0; | 808 | ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0; |
| 802 | ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0; | 809 | ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0; |
| 803 | ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0; | 810 | ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0; |
| 804 | ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0; | 811 | ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0; |
| 805 | ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0; | 812 | ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0; |
| 806 | 813 | ||
| 807 | ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes); | 814 | ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes); |
| 808 | ndcr |= NDCR_SPARE_EN; /* enable spare by default */ | 815 | ndcr |= NDCR_SPARE_EN; /* enable spare by default */ |
| 809 | 816 | ||
| 810 | info->reg_ndcr = ndcr; | 817 | host->reg_ndcr = ndcr; |
| 811 | 818 | ||
| 812 | pxa3xx_nand_set_timing(info, f->timing); | 819 | pxa3xx_nand_set_timing(host, f->timing); |
| 813 | return 0; | 820 | return 0; |
| 814 | } | 821 | } |
| 815 | 822 | ||
| 816 | static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | 823 | static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) |
| 817 | { | 824 | { |
| 825 | struct pxa3xx_nand_host *host = info->host; | ||
| 818 | uint32_t ndcr = nand_readl(info, NDCR); | 826 | uint32_t ndcr = nand_readl(info, NDCR); |
| 819 | info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; | ||
| 820 | /* set info fields needed to read id */ | ||
| 821 | info->read_id_bytes = (info->page_size == 2048) ? 4 : 2; | ||
| 822 | info->reg_ndcr = ndcr & ~NDCR_INT_MASK; | ||
| 823 | info->cmdset = &default_cmdset; | ||
| 824 | 827 | ||
| 825 | info->ndtr0cs0 = nand_readl(info, NDTR0CS0); | 828 | if (ndcr & NDCR_PAGE_SZ) { |
| 826 | info->ndtr1cs0 = nand_readl(info, NDTR1CS0); | 829 | host->page_size = 2048; |
| 830 | host->read_id_bytes = 4; | ||
| 831 | } else { | ||
| 832 | host->page_size = 512; | ||
| 833 | host->read_id_bytes = 2; | ||
| 834 | } | ||
| 835 | |||
| 836 | host->reg_ndcr = ndcr & ~NDCR_INT_MASK; | ||
| 837 | host->cmdset = &default_cmdset; | ||
| 838 | |||
| 839 | host->ndtr0cs0 = nand_readl(info, NDTR0CS0); | ||
| 840 | host->ndtr1cs0 = nand_readl(info, NDTR1CS0); | ||
| 827 | 841 | ||
| 828 | return 0; | 842 | return 0; |
| 829 | } | 843 | } |
| @@ -853,7 +867,6 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | |||
| 853 | return -ENOMEM; | 867 | return -ENOMEM; |
| 854 | } | 868 | } |
| 855 | 869 | ||
| 856 | info->data_buff_size = MAX_BUFF_SIZE; | ||
| 857 | info->data_desc = (void *)info->data_buff + data_desc_offset; | 870 | info->data_desc = (void *)info->data_buff + data_desc_offset; |
| 858 | info->data_desc_addr = info->data_buff_phys + data_desc_offset; | 871 | info->data_desc_addr = info->data_buff_phys + data_desc_offset; |
| 859 | 872 | ||
| @@ -861,7 +874,7 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | |||
| 861 | pxa3xx_nand_data_dma_irq, info); | 874 | pxa3xx_nand_data_dma_irq, info); |
| 862 | if (info->data_dma_ch < 0) { | 875 | if (info->data_dma_ch < 0) { |
| 863 | dev_err(&pdev->dev, "failed to request data dma\n"); | 876 | dev_err(&pdev->dev, "failed to request data dma\n"); |
| 864 | dma_free_coherent(&pdev->dev, info->data_buff_size, | 877 | dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, |
| 865 | info->data_buff, info->data_buff_phys); | 878 | info->data_buff, info->data_buff_phys); |
| 866 | return info->data_dma_ch; | 879 | return info->data_dma_ch; |
| 867 | } | 880 | } |
| @@ -871,21 +884,25 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | |||
| 871 | 884 | ||
| 872 | static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) | 885 | static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) |
| 873 | { | 886 | { |
| 874 | struct mtd_info *mtd = info->mtd; | 887 | struct mtd_info *mtd = info->host->mtd; |
| 875 | struct nand_chip *chip = mtd->priv; | 888 | int ret; |
| 876 | 889 | ||
| 877 | /* use the common timing to make a try */ | 890 | /* use the common timing to make a try */ |
| 878 | pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); | 891 | ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); |
| 879 | chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); | 892 | if (ret) |
| 893 | return ret; | ||
| 894 | |||
| 895 | pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0); | ||
| 880 | if (info->is_ready) | 896 | if (info->is_ready) |
| 881 | return 1; | ||
| 882 | else | ||
| 883 | return 0; | 897 | return 0; |
| 898 | |||
| 899 | return -ENODEV; | ||
| 884 | } | 900 | } |
| 885 | 901 | ||
| 886 | static int pxa3xx_nand_scan(struct mtd_info *mtd) | 902 | static int pxa3xx_nand_scan(struct mtd_info *mtd) |
| 887 | { | 903 | { |
| 888 | struct pxa3xx_nand_info *info = mtd->priv; | 904 | struct pxa3xx_nand_host *host = mtd->priv; |
| 905 | struct pxa3xx_nand_info *info = host->info_data; | ||
| 889 | struct platform_device *pdev = info->pdev; | 906 | struct platform_device *pdev = info->pdev; |
| 890 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; | 907 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; |
| 891 | struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL; | 908 | struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL; |
| @@ -899,12 +916,10 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
| 899 | goto KEEP_CONFIG; | 916 | goto KEEP_CONFIG; |
| 900 | 917 | ||
| 901 | ret = pxa3xx_nand_sensing(info); | 918 | ret = pxa3xx_nand_sensing(info); |
| 902 | if (!ret) { | 919 | if (ret) { |
| 903 | kfree(mtd); | ||
| 904 | info->mtd = NULL; | ||
| 905 | dev_info(&info->pdev->dev, "There is no nand chip on cs 0!\n"); | 920 | dev_info(&info->pdev->dev, "There is no nand chip on cs 0!\n"); |
| 906 | 921 | ||
| 907 | return -EINVAL; | 922 | return ret; |
| 908 | } | 923 | } |
| 909 | 924 | ||
| 910 | chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); | 925 | chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); |
| @@ -912,8 +927,6 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
| 912 | if (id != 0) | 927 | if (id != 0) |
| 913 | dev_info(&info->pdev->dev, "Detect a flash id %x\n", id); | 928 | dev_info(&info->pdev->dev, "Detect a flash id %x\n", id); |
| 914 | else { | 929 | else { |
| 915 | kfree(mtd); | ||
| 916 | info->mtd = NULL; | ||
| 917 | dev_warn(&info->pdev->dev, | 930 | dev_warn(&info->pdev->dev, |
| 918 | "Read out ID 0, potential timing set wrong!!\n"); | 931 | "Read out ID 0, potential timing set wrong!!\n"); |
| 919 | 932 | ||
| @@ -933,14 +946,17 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
| 933 | } | 946 | } |
| 934 | 947 | ||
| 935 | if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) { | 948 | if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) { |
| 936 | kfree(mtd); | ||
| 937 | info->mtd = NULL; | ||
| 938 | dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n"); | 949 | dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n"); |
| 939 | 950 | ||
| 940 | return -EINVAL; | 951 | return -EINVAL; |
| 941 | } | 952 | } |
| 942 | 953 | ||
| 943 | pxa3xx_nand_config_flash(info, f); | 954 | ret = pxa3xx_nand_config_flash(info, f); |
| 955 | if (ret) { | ||
| 956 | dev_err(&info->pdev->dev, "ERROR! Configure failed\n"); | ||
| 957 | return ret; | ||
| 958 | } | ||
| 959 | |||
| 944 | pxa3xx_flash_ids[0].name = f->name; | 960 | pxa3xx_flash_ids[0].name = f->name; |
| 945 | pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff; | 961 | pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff; |
| 946 | pxa3xx_flash_ids[0].pagesize = f->page_size; | 962 | pxa3xx_flash_ids[0].pagesize = f->page_size; |
| @@ -952,47 +968,56 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) | |||
| 952 | pxa3xx_flash_ids[1].name = NULL; | 968 | pxa3xx_flash_ids[1].name = NULL; |
| 953 | def = pxa3xx_flash_ids; | 969 | def = pxa3xx_flash_ids; |
| 954 | KEEP_CONFIG: | 970 | KEEP_CONFIG: |
| 971 | chip->ecc.mode = NAND_ECC_HW; | ||
| 972 | chip->ecc.size = host->page_size; | ||
| 973 | |||
| 974 | chip->options = NAND_NO_AUTOINCR; | ||
| 975 | chip->options |= NAND_NO_READRDY; | ||
| 976 | if (host->reg_ndcr & NDCR_DWIDTH_M) | ||
| 977 | chip->options |= NAND_BUSWIDTH_16; | ||
| 978 | |||
| 955 | if (nand_scan_ident(mtd, 1, def)) | 979 | if (nand_scan_ident(mtd, 1, def)) |
| 956 | return -ENODEV; | 980 | return -ENODEV; |
| 957 | /* calculate addressing information */ | 981 | /* calculate addressing information */ |
| 958 | info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1; | 982 | if (mtd->writesize >= 2048) |
| 983 | host->col_addr_cycles = 2; | ||
| 984 | else | ||
| 985 | host->col_addr_cycles = 1; | ||
| 986 | |||
| 959 | info->oob_buff = info->data_buff + mtd->writesize; | 987 | info->oob_buff = info->data_buff + mtd->writesize; |
| 960 | if ((mtd->size >> chip->page_shift) > 65536) | 988 | if ((mtd->size >> chip->page_shift) > 65536) |
| 961 | info->row_addr_cycles = 3; | 989 | host->row_addr_cycles = 3; |
| 962 | else | 990 | else |
| 963 | info->row_addr_cycles = 2; | 991 | host->row_addr_cycles = 2; |
| 964 | mtd->name = mtd_names[0]; | ||
| 965 | chip->ecc.mode = NAND_ECC_HW; | ||
| 966 | chip->ecc.size = info->page_size; | ||
| 967 | |||
| 968 | chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16 : 0; | ||
| 969 | chip->options |= NAND_NO_AUTOINCR; | ||
| 970 | chip->options |= NAND_NO_READRDY; | ||
| 971 | 992 | ||
| 993 | mtd->name = mtd_names[0]; | ||
| 972 | return nand_scan_tail(mtd); | 994 | return nand_scan_tail(mtd); |
| 973 | } | 995 | } |
| 974 | 996 | ||
| 975 | static | 997 | static int alloc_nand_resource(struct platform_device *pdev) |
| 976 | struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) | ||
| 977 | { | 998 | { |
| 978 | struct pxa3xx_nand_info *info; | 999 | struct pxa3xx_nand_info *info; |
| 1000 | struct pxa3xx_nand_host *host; | ||
| 979 | struct nand_chip *chip; | 1001 | struct nand_chip *chip; |
| 980 | struct mtd_info *mtd; | 1002 | struct mtd_info *mtd; |
| 981 | struct resource *r; | 1003 | struct resource *r; |
| 982 | int ret, irq; | 1004 | int ret, irq; |
| 983 | 1005 | ||
| 984 | mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info), | 1006 | info = kzalloc(sizeof(*info) + sizeof(*mtd) + sizeof(*host), |
| 985 | GFP_KERNEL); | 1007 | GFP_KERNEL); |
| 986 | if (!mtd) { | 1008 | if (!info) { |
| 987 | dev_err(&pdev->dev, "failed to allocate memory\n"); | 1009 | dev_err(&pdev->dev, "failed to allocate memory\n"); |
| 988 | return NULL; | 1010 | return -ENOMEM; |
| 989 | } | 1011 | } |
| 990 | 1012 | ||
| 991 | info = (struct pxa3xx_nand_info *)(&mtd[1]); | 1013 | mtd = (struct mtd_info *)(&info[1]); |
| 992 | chip = (struct nand_chip *)(&mtd[1]); | 1014 | chip = (struct nand_chip *)(&mtd[1]); |
| 1015 | host = (struct pxa3xx_nand_host *)chip; | ||
| 993 | info->pdev = pdev; | 1016 | info->pdev = pdev; |
| 994 | info->mtd = mtd; | 1017 | info->host = host; |
| 995 | mtd->priv = info; | 1018 | host->mtd = mtd; |
| 1019 | host->info_data = info; | ||
| 1020 | mtd->priv = host; | ||
| 996 | mtd->owner = THIS_MODULE; | 1021 | mtd->owner = THIS_MODULE; |
| 997 | 1022 | ||
| 998 | chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; | 1023 | chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; |
| @@ -1000,7 +1025,6 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) | |||
| 1000 | chip->controller = &info->controller; | 1025 | chip->controller = &info->controller; |
| 1001 | chip->waitfunc = pxa3xx_nand_waitfunc; | 1026 | chip->waitfunc = pxa3xx_nand_waitfunc; |
| 1002 | chip->select_chip = pxa3xx_nand_select_chip; | 1027 | chip->select_chip = pxa3xx_nand_select_chip; |
| 1003 | chip->dev_ready = pxa3xx_nand_dev_ready; | ||
| 1004 | chip->cmdfunc = pxa3xx_nand_cmdfunc; | 1028 | chip->cmdfunc = pxa3xx_nand_cmdfunc; |
| 1005 | chip->read_word = pxa3xx_nand_read_word; | 1029 | chip->read_word = pxa3xx_nand_read_word; |
| 1006 | chip->read_byte = pxa3xx_nand_read_byte; | 1030 | chip->read_byte = pxa3xx_nand_read_byte; |
| @@ -1079,13 +1103,13 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev) | |||
| 1079 | 1103 | ||
| 1080 | platform_set_drvdata(pdev, info); | 1104 | platform_set_drvdata(pdev, info); |
| 1081 | 1105 | ||
| 1082 | return info; | 1106 | return 0; |
| 1083 | 1107 | ||
| 1084 | fail_free_buf: | 1108 | fail_free_buf: |
| 1085 | free_irq(irq, info); | 1109 | free_irq(irq, info); |
| 1086 | if (use_dma) { | 1110 | if (use_dma) { |
| 1087 | pxa_free_dma(info->data_dma_ch); | 1111 | pxa_free_dma(info->data_dma_ch); |
| 1088 | dma_free_coherent(&pdev->dev, info->data_buff_size, | 1112 | dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, |
| 1089 | info->data_buff, info->data_buff_phys); | 1113 | info->data_buff, info->data_buff_phys); |
| 1090 | } else | 1114 | } else |
| 1091 | kfree(info->data_buff); | 1115 | kfree(info->data_buff); |
| @@ -1097,17 +1121,19 @@ fail_put_clk: | |||
| 1097 | clk_disable(info->clk); | 1121 | clk_disable(info->clk); |
| 1098 | clk_put(info->clk); | 1122 | clk_put(info->clk); |
| 1099 | fail_free_mtd: | 1123 | fail_free_mtd: |
| 1100 | kfree(mtd); | 1124 | kfree(info); |
| 1101 | return NULL; | 1125 | return ret; |
| 1102 | } | 1126 | } |
| 1103 | 1127 | ||
| 1104 | static int pxa3xx_nand_remove(struct platform_device *pdev) | 1128 | static int pxa3xx_nand_remove(struct platform_device *pdev) |
| 1105 | { | 1129 | { |
| 1106 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); | 1130 | struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); |
| 1107 | struct mtd_info *mtd = info->mtd; | ||
| 1108 | struct resource *r; | 1131 | struct resource *r; |
| 1109 | int irq; | 1132 | int irq; |
| 1110 | 1133 | ||
| 1134 | if (!info) | ||
| 1135 | return 0; | ||
| 1136 | |||
| 1111 | platform_set_drvdata(pdev, NULL); | 1137 | platform_set_drvdata(pdev, NULL); |
| 1112 | 1138 | ||
| 1113 | irq = platform_get_irq(pdev, 0); | 1139 | irq = platform_get_irq(pdev, 0); |
| @@ -1115,7 +1141,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
| 1115 | free_irq(irq, info); | 1141 | free_irq(irq, info); |
| 1116 | if (use_dma) { | 1142 | if (use_dma) { |
| 1117 | pxa_free_dma(info->data_dma_ch); | 1143 | pxa_free_dma(info->data_dma_ch); |
| 1118 | dma_free_writecombine(&pdev->dev, info->data_buff_size, | 1144 | dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE, |
| 1119 | info->data_buff, info->data_buff_phys); | 1145 | info->data_buff, info->data_buff_phys); |
| 1120 | } else | 1146 | } else |
| 1121 | kfree(info->data_buff); | 1147 | kfree(info->data_buff); |
| @@ -1127,10 +1153,8 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
| 1127 | clk_disable(info->clk); | 1153 | clk_disable(info->clk); |
| 1128 | clk_put(info->clk); | 1154 | clk_put(info->clk); |
| 1129 | 1155 | ||
| 1130 | if (mtd) { | 1156 | nand_release(info->host->mtd); |
| 1131 | nand_release(mtd); | 1157 | kfree(info); |
| 1132 | kfree(mtd); | ||
| 1133 | } | ||
| 1134 | return 0; | 1158 | return 0; |
| 1135 | } | 1159 | } |
| 1136 | 1160 | ||
| @@ -1138,6 +1162,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
| 1138 | { | 1162 | { |
| 1139 | struct pxa3xx_nand_platform_data *pdata; | 1163 | struct pxa3xx_nand_platform_data *pdata; |
| 1140 | struct pxa3xx_nand_info *info; | 1164 | struct pxa3xx_nand_info *info; |
| 1165 | int ret; | ||
| 1141 | 1166 | ||
| 1142 | pdata = pdev->dev.platform_data; | 1167 | pdata = pdev->dev.platform_data; |
| 1143 | if (!pdata) { | 1168 | if (!pdata) { |
| @@ -1145,17 +1170,20 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
| 1145 | return -ENODEV; | 1170 | return -ENODEV; |
| 1146 | } | 1171 | } |
| 1147 | 1172 | ||
| 1148 | info = alloc_nand_resource(pdev); | 1173 | ret = alloc_nand_resource(pdev); |
| 1149 | if (info == NULL) | 1174 | if (ret) { |
| 1150 | return -ENOMEM; | 1175 | dev_err(&pdev->dev, "alloc nand resource failed\n"); |
| 1176 | return ret; | ||
| 1177 | } | ||
| 1151 | 1178 | ||
| 1152 | if (pxa3xx_nand_scan(info->mtd)) { | 1179 | info = platform_get_drvdata(pdev); |
| 1180 | if (pxa3xx_nand_scan(info->host->mtd)) { | ||
| 1153 | dev_err(&pdev->dev, "failed to scan nand\n"); | 1181 | dev_err(&pdev->dev, "failed to scan nand\n"); |
| 1154 | pxa3xx_nand_remove(pdev); | 1182 | pxa3xx_nand_remove(pdev); |
| 1155 | return -ENODEV; | 1183 | return -ENODEV; |
| 1156 | } | 1184 | } |
| 1157 | 1185 | ||
| 1158 | return mtd_device_parse_register(info->mtd, NULL, 0, | 1186 | return mtd_device_parse_register(info->host->mtd, NULL, 0, |
| 1159 | pdata->parts, pdata->nr_parts); | 1187 | pdata->parts, pdata->nr_parts); |
| 1160 | } | 1188 | } |
| 1161 | 1189 | ||
| @@ -1182,8 +1210,8 @@ static int pxa3xx_nand_resume(struct platform_device *pdev) | |||
| 1182 | /* We don't want to handle interrupt without calling mtd routine */ | 1210 | /* We don't want to handle interrupt without calling mtd routine */ |
| 1183 | disable_int(info, NDCR_INT_MASK); | 1211 | disable_int(info, NDCR_INT_MASK); |
| 1184 | 1212 | ||
| 1185 | nand_writel(info, NDTR0CS0, info->ndtr0cs0); | 1213 | nand_writel(info, NDTR0CS0, info->host->ndtr0cs0); |
| 1186 | nand_writel(info, NDTR1CS0, info->ndtr1cs0); | 1214 | nand_writel(info, NDTR1CS0, info->host->ndtr1cs0); |
| 1187 | 1215 | ||
| 1188 | /* | 1216 | /* |
| 1189 | * As the spec says, the NDSR would be updated to 0x1800 when | 1217 | * As the spec says, the NDSR would be updated to 0x1800 when |
