Skip to content

Commit 2a500af

Browse files
lw-karocomputersforpeace
authored andcommitted
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 <[email protected]> Acked-by: Huang Shijie <[email protected]> Signed-off-by: Brian Norris <[email protected]>
1 parent d8c0372 commit 2a500af

File tree

2 files changed

+42
-19
lines changed

2 files changed

+42
-19
lines changed

Documentation/devicetree/bindings/mtd/gpmi-nand.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ Optional properties:
2525
discoverable or this property is not enabled,
2626
the software may chooses an implementation-defined
2727
ECC scheme.
28+
- fsl,no-blockmark-swap: Don't swap the bad block marker from the OOB
29+
area with the byte in the data area but rely on the
30+
flash based BBT for identifying bad blocks.
31+
NOTE: this is only valid in conjunction with
32+
'nand-on-flash-bbt'.
33+
WARNING: on i.MX28 blockmark swapping cannot be
34+
disabled for the BootROM in the FCB. Thus,
35+
partitions written from Linux with this feature
36+
turned on may not be accessible by the BootROM
37+
code.
2838

2939
The device tree may optionally contain sub-nodes describing partitions of the
3040
address space. See partition.txt for more detail.

drivers/mtd/nand/gpmi-nand/gpmi-nand.c

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
10811081
int first, last, marker_pos;
10821082
int ecc_parity_size;
10831083
int col = 0;
1084+
int old_swap_block_mark = this->swap_block_mark;
10841085

10851086
/* The size of ECC parity */
10861087
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,
10891090
first = offs / size;
10901091
last = (offs + len - 1) / size;
10911092

1092-
/*
1093-
* Find the chunk which contains the Block Marker. If this chunk is
1094-
* in the range of [first, last], we have to read out the whole page.
1095-
* Why? since we had swapped the data at the position of Block Marker
1096-
* to the metadata which is bound with the chunk 0.
1097-
*/
1098-
marker_pos = geo->block_mark_byte_offset / size;
1099-
if (last >= marker_pos && first <= marker_pos) {
1100-
dev_dbg(this->dev, "page:%d, first:%d, last:%d, marker at:%d\n",
1093+
if (this->swap_block_mark) {
1094+
/*
1095+
* Find the chunk which contains the Block Marker.
1096+
* If this chunk is in the range of [first, last],
1097+
* we have to read out the whole page.
1098+
* Why? since we had swapped the data at the position of Block
1099+
* Marker to the metadata which is bound with the chunk 0.
1100+
*/
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",
11011105
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+
}
11031108
}
11041109

11051110
meta = geo->metadata_size;
@@ -1145,7 +1150,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
11451150
writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0);
11461151
writel(r2_old, bch_regs + HW_BCH_FLASH0LAYOUT1);
11471152
this->bch_geometry = old_geo;
1148-
this->swap_block_mark = true;
1153+
this->swap_block_mark = old_swap_block_mark;
11491154

11501155
return max_bitflips;
11511156
}
@@ -1309,10 +1314,10 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
13091314

13101315
/*
13111316
* 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
1313-
* explicitly read it.
1317+
* non-transcribing case (!GPMI_IS_MX23()), we already have it.
1318+
* Otherwise, we need to explicitly read it.
13141319
*/
1315-
if (!this->swap_block_mark) {
1320+
if (GPMI_IS_MX23(this)) {
13161321
/* Read the block mark into the first byte of the OOB buffer. */
13171322
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
13181323
chip->oob_poi[0] = chip->read_byte(mtd);
@@ -1353,7 +1358,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
13531358
chipnr = (int)(ofs >> chip->chip_shift);
13541359
chip->select_chip(mtd, chipnr);
13551360

1356-
column = this->swap_block_mark ? mtd->writesize : 0;
1361+
column = !GPMI_IS_MX23(this) ? mtd->writesize : 0;
13571362

13581363
/* Write the block mark. */
13591364
block_mark = this->data_buffer_dma;
@@ -1649,9 +1654,6 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
16491654
struct bch_geometry *bch_geo = &this->bch_geometry;
16501655
int ret;
16511656

1652-
/* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
1653-
this->swap_block_mark = !GPMI_IS_MX23(this);
1654-
16551657
/* Set up the medium geometry */
16561658
ret = gpmi_set_geometry(this);
16571659
if (ret)
@@ -1715,9 +1717,20 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
17151717
chip->badblock_pattern = &gpmi_bbt_descr;
17161718
chip->block_markbad = gpmi_block_markbad;
17171719
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)) {
17191725
chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
17201726

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+
17211734
/*
17221735
* Allocate a temporary DMA buffer for reading ID in the
17231736
* nand_scan_ident().

0 commit comments

Comments
 (0)