aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorLothar Waßmann <LW@KARO-electronics.de>2014-03-28 06:35:06 -0400
committerBrian Norris <computersforpeace@gmail.com>2014-07-28 01:06:31 -0400
commit2a500afe1e0e84c7a126df693dbd01353756dcfa (patch)
tree278caaa0a91938c570c217f0b64d954724b1747d /drivers/mtd
parentd8c0372baadb29e60668c2bddfcf39294f3d4581 (diff)
mtd: gpmi: make blockmark swapping optional
With a flash-based BBT there is no reason to move the Factory Bad Block Marker from the data area buffer (to where it is mapped by the GPMI NAND controller) to the OOB buffer. Thus, make this feature configurable via DT. This is required for the Ka-Ro electronics platforms. In the original code 'this->swap_block_mark' was synonymous with '!GPMI_IS_MX23()', so use the latter at the relevant places. Signed-off-by: Lothar Waßmann <LW@KARO-electronics.de> Acked-by: Huang Shijie <b32955@freescale.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c51
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().