|
35 | 35 | #define NFC_CMD_RB BIT(20)
|
36 | 36 | #define NFC_CMD_SCRAMBLER_ENABLE BIT(19)
|
37 | 37 | #define NFC_CMD_SCRAMBLER_DISABLE 0
|
| 38 | +#define NFC_CMD_SHORTMODE_ENABLE 1 |
38 | 39 | #define NFC_CMD_SHORTMODE_DISABLE 0
|
39 | 40 | #define NFC_CMD_RB_INT BIT(14)
|
40 | 41 | #define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16))
|
|
78 | 79 | #define DMA_DIR(dir) ((dir) ? NFC_CMD_N2M : NFC_CMD_M2N)
|
79 | 80 | #define DMA_ADDR_ALIGN 8
|
80 | 81 |
|
| 82 | +#define NFC_SHORT_MODE_ECC_SZ 384 |
| 83 | + |
81 | 84 | #define ECC_CHECK_RETURN_FF (-1)
|
82 | 85 |
|
83 | 86 | #define NAND_CE0 (0xe << 10)
|
@@ -125,6 +128,8 @@ struct meson_nfc_nand_chip {
|
125 | 128 | u32 twb;
|
126 | 129 | u32 tadl;
|
127 | 130 | u32 tbers_max;
|
| 131 | + u32 boot_pages; |
| 132 | + u32 boot_page_step; |
128 | 133 |
|
129 | 134 | u32 bch_mode;
|
130 | 135 | u8 *data_buf;
|
@@ -298,33 +303,46 @@ static void meson_nfc_cmd_seed(struct meson_nfc *nfc, u32 seed)
|
298 | 303 | nfc->reg_base + NFC_REG_CMD);
|
299 | 304 | }
|
300 | 305 |
|
| 306 | +static int meson_nfc_is_boot_page(struct nand_chip *nand, int page) |
| 307 | +{ |
| 308 | + const struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); |
| 309 | + |
| 310 | + return (nand->options & NAND_IS_BOOT_MEDIUM) && |
| 311 | + !(page % meson_chip->boot_page_step) && |
| 312 | + (page < meson_chip->boot_pages); |
| 313 | +} |
| 314 | + |
301 | 315 | static void meson_nfc_cmd_access(struct nand_chip *nand, int raw, bool dir, int page)
|
302 | 316 | {
|
| 317 | + const struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); |
303 | 318 | struct mtd_info *mtd = nand_to_mtd(nand);
|
304 | 319 | struct meson_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
|
305 |
| - struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); |
306 |
| - u32 bch = meson_chip->bch_mode, cmd; |
307 | 320 | int len = mtd->writesize, pagesize, pages;
|
308 | 321 | int scrambler;
|
| 322 | + u32 cmd; |
309 | 323 |
|
310 | 324 | if (nand->options & NAND_NEED_SCRAMBLING)
|
311 | 325 | scrambler = NFC_CMD_SCRAMBLER_ENABLE;
|
312 | 326 | else
|
313 | 327 | scrambler = NFC_CMD_SCRAMBLER_DISABLE;
|
314 | 328 |
|
315 |
| - pagesize = nand->ecc.size; |
316 |
| - |
317 | 329 | if (raw) {
|
318 | 330 | len = mtd->writesize + mtd->oobsize;
|
319 | 331 | cmd = len | scrambler | DMA_DIR(dir);
|
320 |
| - writel(cmd, nfc->reg_base + NFC_REG_CMD); |
321 |
| - return; |
322 |
| - } |
| 332 | + } else if (meson_nfc_is_boot_page(nand, page)) { |
| 333 | + pagesize = NFC_SHORT_MODE_ECC_SZ >> 3; |
| 334 | + pages = mtd->writesize / 512; |
323 | 335 |
|
324 |
| - pages = len / nand->ecc.size; |
| 336 | + scrambler = NFC_CMD_SCRAMBLER_ENABLE; |
| 337 | + cmd = CMDRWGEN(DMA_DIR(dir), scrambler, NFC_ECC_BCH8_1K, |
| 338 | + NFC_CMD_SHORTMODE_ENABLE, pagesize, pages); |
| 339 | + } else { |
| 340 | + pagesize = nand->ecc.size >> 3; |
| 341 | + pages = len / nand->ecc.size; |
325 | 342 |
|
326 |
| - cmd = CMDRWGEN(DMA_DIR(dir), scrambler, bch, |
327 |
| - NFC_CMD_SHORTMODE_DISABLE, pagesize, pages); |
| 343 | + cmd = CMDRWGEN(DMA_DIR(dir), scrambler, meson_chip->bch_mode, |
| 344 | + NFC_CMD_SHORTMODE_DISABLE, pagesize, pages); |
| 345 | + } |
328 | 346 |
|
329 | 347 | if (scrambler == NFC_CMD_SCRAMBLER_ENABLE)
|
330 | 348 | meson_nfc_cmd_seed(nfc, page);
|
@@ -1425,6 +1443,26 @@ meson_nfc_nand_chip_init(struct device *dev,
|
1425 | 1443 | if (ret)
|
1426 | 1444 | return ret;
|
1427 | 1445 |
|
| 1446 | + if (nand->options & NAND_IS_BOOT_MEDIUM) { |
| 1447 | + ret = of_property_read_u32(np, "amlogic,boot-pages", |
| 1448 | + &meson_chip->boot_pages); |
| 1449 | + if (ret) { |
| 1450 | + dev_err(dev, "could not retrieve 'amlogic,boot-pages' property: %d", |
| 1451 | + ret); |
| 1452 | + nand_cleanup(nand); |
| 1453 | + return ret; |
| 1454 | + } |
| 1455 | + |
| 1456 | + ret = of_property_read_u32(np, "amlogic,boot-page-step", |
| 1457 | + &meson_chip->boot_page_step); |
| 1458 | + if (ret) { |
| 1459 | + dev_err(dev, "could not retrieve 'amlogic,boot-page-step' property: %d", |
| 1460 | + ret); |
| 1461 | + nand_cleanup(nand); |
| 1462 | + return ret; |
| 1463 | + } |
| 1464 | + } |
| 1465 | + |
1428 | 1466 | ret = mtd_device_register(mtd, NULL, 0);
|
1429 | 1467 | if (ret) {
|
1430 | 1468 | dev_err(dev, "failed to register MTD device: %d\n", ret);
|
|
0 commit comments