提交 ef41e1bb 编写于 作者: C Chuanxiao Dong 提交者: David Woodhouse

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: NChuanxiao Dong <chuanxiao.dong@intel.com>
Signed-off-by: NDavid Woodhouse <David.Woodhouse@intel.com>
上级 eda936ef
...@@ -549,7 +549,6 @@ static void get_samsung_nand_para(struct denali_nand_info *denali) ...@@ -549,7 +549,6 @@ static void get_samsung_nand_para(struct denali_nand_info *denali)
static void get_toshiba_nand_para(struct denali_nand_info *denali) static void get_toshiba_nand_para(struct denali_nand_info *denali)
{ {
void __iomem *scratch_reg;
uint32_t tmp; uint32_t tmp;
/* Workaround to fix a controller bug which reports a wrong */ /* 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,33 +566,14 @@ static void get_toshiba_nand_para(struct denali_nand_info *denali)
denali_write32(8, denali->flash_reg + ECC_CORRECTION); denali_write32(8, denali->flash_reg + ECC_CORRECTION);
#endif #endif
} }
/* As Toshiba NAND can not provide it's block number, */
/* so here we need user to provide the correct block */
/* number in a scratch register before the Linux NAND */
/* driver is loaded. If no valid value found in the scratch */
/* register, then we use default block number value */
scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE);
if (!scratch_reg) {
printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d",
__FILE__, __LINE__);
denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
} else {
nand_dbg_print(NAND_DBG_WARN,
"Spectra: ioremap reg address: 0x%p\n", scratch_reg);
denali->dev_info.wTotalBlocks = 1 << ioread8(scratch_reg);
if (denali->dev_info.wTotalBlocks < 512)
denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
iounmap(scratch_reg);
}
} }
static void get_hynix_nand_para(struct denali_nand_info *denali) static void get_hynix_nand_para(struct denali_nand_info *denali,
uint8_t device_id)
{ {
void __iomem *scratch_reg;
uint32_t main_size, spare_size; uint32_t main_size, spare_size;
switch (denali->dev_info.wDeviceID) { switch (device_id) {
case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */ case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */
case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */ case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */
denali_write32(128, denali->flash_reg + PAGES_PER_BLOCK); 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,20 +601,6 @@ static void get_hynix_nand_para(struct denali_nand_info *denali)
"Will use default parameter values instead.\n", "Will use default parameter values instead.\n",
denali->dev_info.wDeviceID); denali->dev_info.wDeviceID);
} }
scratch_reg = ioremap_nocache(SCRATCH_REG_ADDR, SCRATCH_REG_SIZE);
if (!scratch_reg) {
printk(KERN_ERR "Spectra: ioremap failed in %s, Line %d",
__FILE__, __LINE__);
denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
} else {
nand_dbg_print(NAND_DBG_WARN,
"Spectra: ioremap reg address: 0x%p\n", scratch_reg);
denali->dev_info.wTotalBlocks = 1 << ioread8(scratch_reg);
if (denali->dev_info.wTotalBlocks < 512)
denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
iounmap(scratch_reg);
}
} }
/* determines how many NAND chips are connected to the controller. Note for /* 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,34 +773,35 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
{ {
uint16_t status = PASS; uint16_t status = PASS;
uint8_t no_of_planes; uint8_t no_of_planes;
uint32_t id_bytes[5], addr;
uint8_t i, maf_id, device_id;
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
__FILE__, __LINE__, __func__); __FILE__, __LINE__, __func__);
denali->dev_info.wDeviceMaker = /* Use read id method to get device ID and other
ioread32(denali->flash_reg + MANUFACTURER_ID); * params. For some NAND chips, controller can't
denali->dev_info.wDeviceID = * report the correct device ID by reading from
ioread32(denali->flash_reg + DEVICE_ID); * DEVICE_ID register
denali->dev_info.bDeviceParam0 = * */
ioread32(denali->flash_reg + DEVICE_PARAM_0); addr = (uint32_t)MODE_11 | BANK(denali->flash_bank);
denali->dev_info.bDeviceParam1 = index_addr(denali, (uint32_t)addr | 0, 0x90);
ioread32(denali->flash_reg + DEVICE_PARAM_1); index_addr(denali, (uint32_t)addr | 1, 0);
denali->dev_info.bDeviceParam2 = for (i = 0; i < 5; i++)
ioread32(denali->flash_reg + DEVICE_PARAM_2); index_addr_read_data(denali, addr | 2, &id_bytes[i]);
maf_id = id_bytes[0];
denali->dev_info.MLCDevice = device_id = id_bytes[1];
ioread32(denali->flash_reg + DEVICE_PARAM_0) & 0x0c;
if (ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) & if (ioread32(denali->flash_reg + ONFI_DEVICE_NO_OF_LUNS) &
ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */ ONFI_DEVICE_NO_OF_LUNS__ONFI_DEVICE) { /* ONFI 1.0 NAND */
if (FAIL == get_onfi_nand_para(denali)) if (FAIL == get_onfi_nand_para(denali))
return FAIL; return FAIL;
} else if (denali->dev_info.wDeviceMaker == 0xEC) { /* Samsung NAND */ } else if (maf_id == 0xEC) { /* Samsung NAND */
get_samsung_nand_para(denali); get_samsung_nand_para(denali);
} else if (denali->dev_info.wDeviceMaker == 0x98) { /* Toshiba NAND */ } else if (maf_id == 0x98) { /* Toshiba NAND */
get_toshiba_nand_para(denali); get_toshiba_nand_para(denali);
} else if (denali->dev_info.wDeviceMaker == 0xAD) { /* Hynix NAND */ } else if (maf_id == 0xAD) { /* Hynix NAND */
get_hynix_nand_para(denali); get_hynix_nand_para(denali, device_id);
} else { } else {
denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS; denali->dev_info.wTotalBlocks = GLOB_HWCTL_DEFAULT_BLKS;
} }
...@@ -1720,6 +1687,8 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, ...@@ -1720,6 +1687,8 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
int page) int page)
{ {
struct denali_nand_info *denali = mtd_to_denali(mtd); struct denali_nand_info *denali = mtd_to_denali(mtd);
uint32_t addr, id;
int i;
#if DEBUG_DENALI #if DEBUG_DENALI
printk(KERN_INFO "cmdfunc: 0x%x %d %d\n", cmd, col, page); 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,24 +1701,18 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
break; break;
case NAND_CMD_READID: case NAND_CMD_READID:
reset_buf(denali); reset_buf(denali);
if (denali->flash_bank < denali->total_used_banks) { /*sometimes ManufactureId read from register is not right
/* write manufacturer information into nand * e.g. some of Micron MT29F32G08QAA MLC NAND chips
buffer for NAND subsystem to fetch. * So here we send READID cmd to NAND insteand
*/ * */
write_byte_to_buf(denali, addr = (uint32_t)MODE_11 | BANK(denali->flash_bank);
denali->dev_info.wDeviceMaker); index_addr(denali, (uint32_t)addr | 0, 0x90);
write_byte_to_buf(denali, index_addr(denali, (uint32_t)addr | 1, 0);
denali->dev_info.wDeviceID); for (i = 0; i < 5; i++) {
write_byte_to_buf(denali, index_addr_read_data(denali,
denali->dev_info.bDeviceParam0); (uint32_t)addr | 2,
write_byte_to_buf(denali, &id);
denali->dev_info.bDeviceParam1); write_byte_to_buf(denali, id);
write_byte_to_buf(denali,
denali->dev_info.bDeviceParam2);
} else {
int i;
for (i = 0; i < 5; i++)
write_byte_to_buf(denali, 0xff);
} }
break; break;
case NAND_CMD_READ0: case NAND_CMD_READ0:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册