diff options
author | Chuanxiao Dong <chuanxiao.dong@intel.com> | 2010-08-05 12:48:49 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-08-05 13:13:12 -0400 |
commit | ef41e1bb11fc21acad35c8c3b673fe9f2f29d819 (patch) | |
tree | 404b6e50710d3d2d7796eb1854aee0f0547c12ae /drivers/mtd/nand/denali.c | |
parent | eda936ef17b921e56239ab4db2027d76abf8bebc (diff) |
mtd: denali: update get nand para functions
In denali driver, wTotalBlocks variable is useless, so just
remove them in get_toshiba_nand_para and get_hynix_nand_para
first. Other wTotalBlocks in denali.c and other variables in
dev_info struct are also useless, will remove them later.
Also add a parameter in get_hynix_nand_para to prepare to
remove dev_info struct. This parameter comes by reading NAND
ID directly. Reading register will report wrong value for
some NAND chips, e.g. some Micron MT29F32G08QAA chips.
So update NAND_CMD_READID method as well.
Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand/denali.c')
-rw-r--r-- | drivers/mtd/nand/denali.c | 107 |
1 files changed, 35 insertions, 72 deletions
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 0c76a16774c9..0f9fc5e7a520 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -549,7 +549,6 @@ static void get_samsung_nand_para(struct denali_nand_info *denali) | |||
549 | 549 | ||
550 | static void get_toshiba_nand_para(struct denali_nand_info *denali) | 550 | static void get_toshiba_nand_para(struct denali_nand_info *denali) |
551 | { | 551 | { |
552 | void __iomem *scratch_reg; | ||
553 | uint32_t tmp; | 552 | uint32_t tmp; |
554 | 553 | ||
555 | /* Workaround to fix a controller bug which reports a wrong */ | 554 | /* Workaround to fix a controller bug which reports a wrong */ |
@@ -567,33 +566,14 @@ static void get_toshiba_nand_para(struct denali_nand_info *denali) | |||
567 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); | 566 | denali_write32(8, denali->flash_reg + ECC_CORRECTION); |
568 | #endif | 567 | #endif |
569 | } | 568 | } |
570 | |||
571 | /* As Toshiba NAND can not provide it's block number, */ | ||
572 | /* so here we need user to provide the correct block */ | ||
573 | /* number in a scratch register before the Linux NAND */ | ||
574 | /* driver is loaded. If no valid value found in the scratch */ | ||
575 | /* register, then we use default block number value */ | ||
576 | scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); | ||
577 | if (!scratch_reg) { | ||
578 | printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", | ||
579 | __FILE__, __LINE__); | ||
580 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
581 | } else { | ||
582 | nand_dbg_print(NAND_DBG_WARN, | ||
583 | "Spectra: ioremap reg address: 0x%p\n", scratch_reg); | ||
584 | denali->dev_info.wTotalBlocks = 1 << ioread8(scratch_reg); | ||
585 | if (denali->dev_info.wTotalBlocks < 512) | ||
586 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
587 | iounmap(scratch_reg); | ||
588 | } | ||
589 | } | 569 | } |
590 | 570 | ||
591 | static void get_hynix_nand_para(struct denali_nand_info *denali) | 571 | static void get_hynix_nand_para(struct denali_nand_info *denali, |
572 | uint8_t device_id) | ||
592 | { | 573 | { |
593 | void __iomem *scratch_reg; | ||
594 | uint32_t main_size, spare_size; | 574 | uint32_t main_size, spare_size; |
595 | 575 | ||
596 | switch (denali->dev_info.wDeviceID) { | 576 | switch (device_id) { |
597 | case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ | 577 | case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ |
598 | case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ | 578 | case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ |
599 | denali_write32(128, denali->flash_reg + PAGES_PER_BLOCK); | 579 | denali_write32(128, denali->flash_reg + PAGES_PER_BLOCK); |
@@ -621,20 +601,6 @@ static void get_hynix_nand_para(struct denali_nand_info *denali) | |||
621 | "Will use default parameter values instead.\n", | 601 | "Will use default parameter values instead.\n", |
622 | denali->dev_info.wDeviceID); | 602 | denali->dev_info.wDeviceID); |
623 | } | 603 | } |
624 | |||
625 | scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE); | ||
626 | if (!scratch_reg) { | ||
627 | printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d", | ||
628 | __FILE__, __LINE__); | ||
629 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
630 | } else { | ||
631 | nand_dbg_print(NAND_DBG_WARN, | ||
632 | "Spectra: ioremap reg address: 0x%p\n", scratch_reg); | ||
633 | denali->dev_info.wTotalBlocks = 1 << ioread8(scratch_reg); | ||
634 | if (denali->dev_info.wTotalBlocks < 512) | ||
635 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | ||
636 | iounmap(scratch_reg); | ||
637 | } | ||
638 | } | 604 | } |
639 | 605 | ||
640 | /* determines how many NAND chips are connected to the controller. Note for | 606 | /* determines how many NAND chips are connected to the controller. Note for |
@@ -807,34 +773,35 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali) | |||
807 | { | 773 | { |
808 | uint16_t status = PASS; | 774 | uint16_t status = PASS; |
809 | uint8_t no_of_planes; | 775 | uint8_t no_of_planes; |
776 | uint32_t id_bytes[5], addr; | ||
777 | uint8_t i, maf_id, device_id; | ||
810 | 778 | ||
811 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", | 779 | nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", |
812 | __FILE__, __LINE__, __func__); | 780 | __FILE__, __LINE__, __func__); |
813 | 781 | ||
814 | denali->dev_info.wDeviceMaker = | 782 | /* Use read id method to get device ID and other |
815 | ioread32(denali->flash_reg + MANUFACTURER_ID); | 783 | * params. For some NAND chips, controller can't |
816 | denali->dev_info.wDeviceID = | 784 | * report the correct device ID by reading from |
817 | ioread32(denali->flash_reg + DEVICE_ID); | 785 | * DEVICE_ID register |
818 | denali->dev_info.bDeviceParam0 = | 786 | * */ |
819 | ioread32(denali->flash_reg + DEVICE_PARAM_0); | 787 | addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); |
820 | denali->dev_info.bDeviceParam1 = | 788 | index_addr(denali, (uint32_t)addr | 0, 0x90); |
821 | ioread32(denali->flash_reg + DEVICE_PARAM_1); | 789 | index_addr(denali, (uint32_t)addr | 1, 0); |
822 | denali->dev_info.bDeviceParam2 = | 790 | for (i = 0; i < 5; i++) |
823 | ioread32(denali->flash_reg + DEVICE_PARAM_2); | 791 | index_addr_read_data(denali, addr | 2, &id_bytes[i]); |
824 | 792 | maf_id = id_bytes[0]; | |
825 | denali->dev_info.MLCDevice = | 793 | device_id = id_bytes[1]; |
826 | ioread32(denali->flash_reg + DEVICE_PARAM_0) & 0x0c; | ||
827 | 794 | ||
828 | if (ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) & | 795 | if (ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) & |
829 | ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */ | 796 | ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */ |
830 | if (FAIL == get_onfi_nand_para(denali)) | 797 | if (FAIL == get_onfi_nand_para(denali)) |
831 | return FAIL; | 798 | return FAIL; |
832 | } else if (denali->dev_info.wDeviceMaker == 0xEC) { /* Samsung NAND */ | 799 | } else if (maf_id == 0xEC) { /* Samsung NAND */ |
833 | get_samsung_nand_para(denali); | 800 | get_samsung_nand_para(denali); |
834 | } else if (denali->dev_info.wDeviceMaker == 0x98) { /* Toshiba NAND */ | 801 | } else if (maf_id == 0x98) { /* Toshiba NAND */ |
835 | get_toshiba_nand_para(denali); | 802 | get_toshiba_nand_para(denali); |
836 | } else if (denali->dev_info.wDeviceMaker == 0xAD) { /* Hynix NAND */ | 803 | } else if (maf_id == 0xAD) { /* Hynix NAND */ |
837 | get_hynix_nand_para(denali); | 804 | get_hynix_nand_para(denali, device_id); |
838 | } else { | 805 | } else { |
839 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; | 806 | denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; |
840 | } | 807 | } |
@@ -1720,6 +1687,8 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | |||
1720 | int page) | 1687 | int page) |
1721 | { | 1688 | { |
1722 | struct denali_nand_info *denali = mtd_to_denali(mtd); | 1689 | struct denali_nand_info *denali = mtd_to_denali(mtd); |
1690 | uint32_t addr, id; | ||
1691 | int i; | ||
1723 | 1692 | ||
1724 | #if DEBUG_DENALI | 1693 | #if DEBUG_DENALI |
1725 | printk(KERN_INFO "cmdfunc: 0x%x %d %d\n", cmd, col, page); | 1694 | printk(KERN_INFO "cmdfunc: 0x%x %d %d\n", cmd, col, page); |
@@ -1732,24 +1701,18 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | |||
1732 | break; | 1701 | break; |
1733 | case NAND_CMD_READID: | 1702 | case NAND_CMD_READID: |
1734 | reset_buf(denali); | 1703 | reset_buf(denali); |
1735 | if (denali->flash_bank < denali->total_used_banks) { | 1704 | /*sometimes ManufactureId read from register is not right |
1736 | /* write manufacturer information into nand | 1705 | * e.g. some of Micron MT29F32G08QAA MLC NAND chips |
1737 | buffer for NAND subsystem to fetch. | 1706 | * So here we send READID cmd to NAND insteand |
1738 | */ | 1707 | * */ |
1739 | write_byte_to_buf(denali, | 1708 | addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); |
1740 | denali->dev_info.wDeviceMaker); | 1709 | index_addr(denali, (uint32_t)addr | 0, 0x90); |
1741 | write_byte_to_buf(denali, | 1710 | index_addr(denali, (uint32_t)addr | 1, 0); |
1742 | denali->dev_info.wDeviceID); | 1711 | for (i = 0; i < 5; i++) { |
1743 | write_byte_to_buf(denali, | 1712 | index_addr_read_data(denali, |
1744 | denali->dev_info.bDeviceParam0); | 1713 | (uint32_t)addr | 2, |
1745 | write_byte_to_buf(denali, | 1714 | &id); |
1746 | denali->dev_info.bDeviceParam1); | 1715 | write_byte_to_buf(denali, id); |
1747 | write_byte_to_buf(denali, | ||
1748 | denali->dev_info.bDeviceParam2); | ||
1749 | } else { | ||
1750 | int i; | ||
1751 | for (i = 0; i < 5; i++) | ||
1752 | write_byte_to_buf(denali, 0xff); | ||
1753 | } | 1716 | } |
1754 | break; | 1717 | break; |
1755 | case NAND_CMD_READ0: | 1718 | case NAND_CMD_READ0: |