mtd: denali: Remove set_ecc_config function
Subsystems (2)
PATCH 3/4 mtd: denali: Remove set_ecc_config function
From 397bc9a8e7f007343c28c301dc4bf2f7f0174cf5 Mon Sep 17 00:00:00 2001
From: Chuanxiao Dong <[email protected]>
Date: Fri, 6 Aug 2010 18:02:03 +0800
Subject: [PATCH 3/4] mtd: denali: Remove set_ecc_config function
set_ecc_config function only set ECC_CORRECTION register, so move register setting to probe function.
Since controller only support 15bit and 8bit ecc correction, updated nand ecc layout information.
Signed-off-by Chuanxiao Dong <[email protected]>
--- drivers/mtd/nand/denali.c | 87 ++++++++++++++++++++++++-------------------- drivers/mtd/nand/denali.h | 1 + 2 files changed, 48 insertions(+), 40 deletions(-)
drivers/mtd/nand/denali.c +47 -40
@@ -354,17 +354,6 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,denali_write32 (cs_cnt, denali->flash_reg +CS_SETUP_CNT ); } -/* configures the initial ECC settings for the controller */ -static void set_ecc_config (struct denali_nand_info *denali) -{ -#if SUPPORT_8BITECC -if ((ioread32 (denali->flash_reg +DEVICE_MAIN_AREA_SIZE ) <4096 ) || - (ioread32 (denali->flash_reg +DEVICE_SPARE_AREA_SIZE ) <=128 )) -denali_write32 (8 , denali->flash_reg +ECC_CORRECTION ); -#endif - -} -/* queries the NAND device to see what ONFI modes it supports. */ static uint16_t get_onfi_nand_para (struct denali_nand_info *denali) {
@@ -576,8 +565,6 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)ioread32 (denali->flash_reg +RDWR_EN_HI_CNT ), ioread32(denali->flash_reg + CS_SETUP_CNT)); -set_ecc_config (denali); -find_valid_banks (denali);detect_partition_feature (denali);
@@ -1450,6 +1437,13 @@ static void denali_ecc_hwctl(struct mtd_info *mtd, int mode)/* Initialization code to bring the device up to a known good state */ static void denali_hw_init (struct denali_nand_info *denali) { +/* tell driver how many bit controller will skip before +* writing ECC code in OOB, this register may be already +* set by firmware. So we read this value out. +* if this value is 0, just let it be. +* */ + denali->bbtskipbytes =ioread32 (denali->flash_reg + +SPARE_AREA_SKIP_BYTES );denali_irq_init (denali);denali_nand_reset (denali);denali_write32 (0x0F , denali->flash_reg +RB_PIN_ENABLED );
@@ -1464,29 +1458,18 @@ static void denali_hw_init(struct denali_nand_info *denali)denali_write32 (1 , denali->flash_reg +ECC_ENABLE ); } -/* ECC layout for SLC devices. Denali spec indicates SLC fixed at 4 bytes */ -#define ECC_BYTES_SLC (4 * (2048 / ECC_SECTOR_SIZE)) -static struct nand_ecclayout nand_oob_slc = { - .eccbytes =4 , - .eccpos = {0 ,1 ,2 ,3 },/* not used */ - .oobfree = { - { - .offset =ECC_BYTES_SLC , - .length =64 -ECC_BYTES_SLC - } - } +/* Althogh controller spec said SLC ECC is forceb to be 4bit, +* but denali controller in MRST only support 15bit and 8bit ECC +* correction +* */ +#define ECC_8BITS 14 +static struct nand_ecclayout nand_8bit_oob = { + .eccbytes =14 , }; -#define ECC_BYTES_MLC (14 * (2048 / ECC_SECTOR_SIZE)) -static struct nand_ecclayout nand_oob_mlc_14bit = { - .eccbytes =14 , - .eccpos = {0 ,1 ,2 ,3 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 },/* not used */ - .oobfree = { - { - .offset =ECC_BYTES_MLC , - .length =64 -ECC_BYTES_MLC - } - } +#define ECC_15BITS 26 +static struct nand_ecclayout nand_15bit_oob = { + .eccbytes =26 , };static uint8_t bbt_pattern[] = {'B' ,'b' ,'t' ,'0' };
@@ -1705,14 +1688,38 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) denali->nand.options |=NAND_USE_FLASH_BBT |NAND_SKIP_BBTSCAN ; denali->nand.ecc.mode =NAND_ECC_HW_SYNDROME ; -if (denali->nand.cellinfo &0xc ) { - denali->nand.ecc.layout = &nand_oob_mlc_14bit; - denali->nand.ecc.bytes =ECC_BYTES_MLC ; - }else {/* SLC */ - denali->nand.ecc.layout = &nand_oob_slc; - denali->nand.ecc.bytes =ECC_BYTES_SLC ; +/* Denali Controller only support 15bit and 8bit ECC in MRST, +* so just let controller do 15bit ECC for MLC and 8bit ECC for +* SLC if possible. +* */ +if (denali->nand.cellinfo &0xc && + (denali->mtd.oobsize > (denali->bbtskipbytes + +ECC_15BITS * (denali->mtd.writesize / +ECC_SECTOR_SIZE )))) { +/* if MLC OOB size is large enough, use 15bit ECC*/ + denali->nand.ecc.layout = &nand_15bit_oob; + denali->nand.ecc.bytes =ECC_15BITS ; +denali_write32 (15 , denali->flash_reg +ECC_CORRECTION ); + }else if (denali->mtd.oobsize < (denali->bbtskipbytes + +ECC_8BITS * (denali->mtd.writesize / +ECC_SECTOR_SIZE ))) { +printk (KERN_ERR "Your NAND chip OOB is not large enough to" +" contain 8bit ECC correction codes" ); + goto failed_nand; + }else { + denali->nand.ecc.layout = &nand_8bit_oob; + denali->nand.ecc.bytes =ECC_8BITS ; +denali_write32 (8 , denali->flash_reg +ECC_CORRECTION ); } + denali->nand.ecc.layout->eccbytes *= + denali->mtd.writesize /ECC_SECTOR_SIZE ; + denali->nand.ecc.layout->oobfree[0 ].offset = + denali->bbtskipbytes + denali->nand.ecc.layout->eccbytes; + denali->nand.ecc.layout->oobfree[0 ].length = + denali->mtd.oobsize - denali->nand.ecc.layout->eccbytes - + denali->bbtskipbytes; +/* Let driver know the total blocks number and * how many blocks contained by each nand chip. * blksperchip will help driver to know how many
drivers/mtd/nand/denali.h +1 -0
@@ -767,6 +767,7 @@ struct denali_nand_info {uint32_t fwblks;/* represent how many blocks FW used */ uint32_t totalblks;uint32_t blksperchip; + uint32_t bbtskipbytes; };#endif /*_LLD_NAND_*/
Signature · 1 line
1.6.6.1