diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 16a533a78edd..959cb9b70310 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
| @@ -1081,6 +1081,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1081 | int first, last, marker_pos; | 1081 | int first, last, marker_pos; |
| 1082 | int ecc_parity_size; | 1082 | int ecc_parity_size; |
| 1083 | int col = 0; | 1083 | int col = 0; |
| 1084 | int old_swap_block_mark = this->swap_block_mark; | ||
| 1084 | 1085 | ||
| 1085 | /* The size of ECC parity */ | 1086 | /* The size of ECC parity */ |
| 1086 | ecc_parity_size = geo->gf_len * geo->ecc_strength / 8; | 1087 | ecc_parity_size = geo->gf_len * geo->ecc_strength / 8; |
| @@ -1089,17 +1090,21 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1089 | first = offs / size; | 1090 | first = offs / size; |
| 1090 | last = (offs + len - 1) / size; | 1091 | last = (offs + len - 1) / size; |
| 1091 | 1092 | ||
| 1092 | /* | 1093 | if (this->swap_block_mark) { |
| 1093 | * Find the chunk which contains the Block Marker. If this chunk is | 1094 | /* |
| 1094 | * in the range of [first, last], we have to read out the whole page. | 1095 | * Find the chunk which contains the Block Marker. |
| 1095 | * Why? since we had swapped the data at the position of Block Marker | 1096 | * If this chunk is in the range of [first, last], |
| 1096 | * to the metadata which is bound with the chunk 0. | 1097 | * we have to read out the whole page. |
| 1097 | */ | 1098 | * Why? since we had swapped the data at the position of Block |
| 1098 | marker_pos = geo->block_mark_byte_offset / size; | 1099 | * Marker to the metadata which is bound with the chunk 0. |
| 1099 | if (last >= marker_pos && first <= marker_pos) { | 1100 | */ |
| 1100 | dev_dbg(this->dev, "page:%d, first:%d, last:%d, marker at:%d\n", | 1101 | marker_pos = geo->block_mark_byte_offset / size; |
| 1102 | if (last >= marker_pos && first <= marker_pos) { | ||
| 1103 | dev_dbg(this->dev, | ||
| 1104 | "page:%d, first:%d, last:%d, marker at:%d\n", | ||
| 1101 | page, first, last, marker_pos); | 1105 | page, first, last, marker_pos); |
| 1102 | return gpmi_ecc_read_page(mtd, chip, buf, 0, page); | 1106 | return gpmi_ecc_read_page(mtd, chip, buf, 0, page); |
| 1107 | } | ||
| 1103 | } | 1108 | } |
| 1104 | 1109 | ||
| 1105 | meta = geo->metadata_size; | 1110 | meta = geo->metadata_size; |
| @@ -1145,7 +1150,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1145 | writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0); | 1150 | writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0); |
| 1146 | writel(r2_old, bch_regs + HW_BCH_FLASH0LAYOUT1); | 1151 | writel(r2_old, bch_regs + HW_BCH_FLASH0LAYOUT1); |
| 1147 | this->bch_geometry = old_geo; | 1152 | this->bch_geometry = old_geo; |
| 1148 | this->swap_block_mark = true; | 1153 | this->swap_block_mark = old_swap_block_mark; |
| 1149 | 1154 | ||
| 1150 | return max_bitflips; | 1155 | return max_bitflips; |
| 1151 | } | 1156 | } |
| @@ -1309,10 +1314,10 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, | |||
| 1309 | 1314 | ||
| 1310 | /* | 1315 | /* |
| 1311 | * Now, we want to make sure the block mark is correct. In the | 1316 | * Now, we want to make sure the block mark is correct. In the |
| 1312 | * Swapping/Raw case, we already have it. Otherwise, we need to | 1317 | * non-transcribing case (!GPMI_IS_MX23()), we already have it. |
| 1313 | * explicitly read it. | 1318 | * Otherwise, we need to explicitly read it. |
| 1314 | */ | 1319 | */ |
| 1315 | if (!this->swap_block_mark) { | 1320 | if (GPMI_IS_MX23(this)) { |
| 1316 | /* Read the block mark into the first byte of the OOB buffer. */ | 1321 | /* Read the block mark into the first byte of the OOB buffer. */ |
| 1317 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); | 1322 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); |
| 1318 | chip->oob_poi[0] = chip->read_byte(mtd); | 1323 | chip->oob_poi[0] = chip->read_byte(mtd); |
| @@ -1353,7 +1358,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
| 1353 | chipnr = (int)(ofs >> chip->chip_shift); | 1358 | chipnr = (int)(ofs >> chip->chip_shift); |
| 1354 | chip->select_chip(mtd, chipnr); | 1359 | chip->select_chip(mtd, chipnr); |
| 1355 | 1360 | ||
| 1356 | column = this->swap_block_mark ? mtd->writesize : 0; | 1361 | column = !GPMI_IS_MX23(this) ? mtd->writesize : 0; |
| 1357 | 1362 | ||
| 1358 | /* Write the block mark. */ | 1363 | /* Write the block mark. */ |
| 1359 | block_mark = this->data_buffer_dma; | 1364 | block_mark = this->data_buffer_dma; |
| @@ -1649,9 +1654,6 @@ static int gpmi_init_last(struct gpmi_nand_data *this) | |||
| 1649 | struct bch_geometry *bch_geo = &this->bch_geometry; | 1654 | struct bch_geometry *bch_geo = &this->bch_geometry; |
| 1650 | int ret; | 1655 | int ret; |
| 1651 | 1656 | ||
| 1652 | /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */ | ||
| 1653 | this->swap_block_mark = !GPMI_IS_MX23(this); | ||
| 1654 | |||
| 1655 | /* Set up the medium geometry */ | 1657 | /* Set up the medium geometry */ |
| 1656 | ret = gpmi_set_geometry(this); | 1658 | ret = gpmi_set_geometry(this); |
| 1657 | if (ret) | 1659 | if (ret) |
| @@ -1715,9 +1717,20 @@ static int gpmi_nand_init(struct gpmi_nand_data *this) | |||
| 1715 | chip->badblock_pattern = &gpmi_bbt_descr; | 1717 | chip->badblock_pattern = &gpmi_bbt_descr; |
| 1716 | chip->block_markbad = gpmi_block_markbad; | 1718 | chip->block_markbad = gpmi_block_markbad; |
| 1717 | chip->options |= NAND_NO_SUBPAGE_WRITE; | 1719 | chip->options |= NAND_NO_SUBPAGE_WRITE; |
| 1718 | if (of_get_nand_on_flash_bbt(this->dev->of_node)) | 1720 | |
| 1721 | /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */ | ||
| 1722 | this->swap_block_mark = !GPMI_IS_MX23(this); | ||
| 1723 | |||
| 1724 | if (of_get_nand_on_flash_bbt(this->dev->of_node)) { | ||
| 1719 | chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; | 1725 | chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; |
| 1720 | 1726 | ||
| 1727 | if (of_property_read_bool(this->dev->of_node, | ||
| 1728 | "fsl,no-blockmark-swap")) | ||
| 1729 | this->swap_block_mark = false; | ||
| 1730 | } | ||
| 1731 | dev_dbg(this->dev, "Blockmark swapping %sabled\n", | ||
| 1732 | this->swap_block_mark ? "en" : "dis"); | ||
| 1733 | |||
| 1721 | /* | 1734 | /* |
| 1722 | * Allocate a temporary DMA buffer for reading ID in the | 1735 | * Allocate a temporary DMA buffer for reading ID in the |
| 1723 | * nand_scan_ident(). | 1736 | * nand_scan_ident(). |
