|
38 | 38 | #define NFC_CMD_SCRAMBLER_DISABLE 0 |
39 | 39 | #define NFC_CMD_SHORTMODE_DISABLE 0 |
40 | 40 | #define NFC_CMD_RB_INT BIT(14) |
| 41 | +#define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16)) |
41 | 42 |
|
42 | 43 | #define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) |
43 | 44 |
|
@@ -182,6 +183,7 @@ struct meson_nfc { |
182 | 183 | u32 info_bytes; |
183 | 184 |
|
184 | 185 | unsigned long assigned_cs; |
| 186 | + bool no_rb_pin; |
185 | 187 | }; |
186 | 188 |
|
187 | 189 | enum { |
@@ -395,7 +397,42 @@ static void meson_nfc_set_data_oob(struct nand_chip *nand, |
395 | 397 | } |
396 | 398 | } |
397 | 399 |
|
398 | | -static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) |
| 400 | +static int meson_nfc_wait_no_rb_pin(struct meson_nfc *nfc, int timeout_ms, |
| 401 | + bool need_cmd_read0) |
| 402 | +{ |
| 403 | + u32 cmd, cfg; |
| 404 | + |
| 405 | + meson_nfc_cmd_idle(nfc, nfc->timing.twb); |
| 406 | + meson_nfc_drain_cmd(nfc); |
| 407 | + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); |
| 408 | + |
| 409 | + cfg = readl(nfc->reg_base + NFC_REG_CFG); |
| 410 | + cfg |= NFC_RB_IRQ_EN; |
| 411 | + writel(cfg, nfc->reg_base + NFC_REG_CFG); |
| 412 | + |
| 413 | + reinit_completion(&nfc->completion); |
| 414 | + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_STATUS; |
| 415 | + writel(cmd, nfc->reg_base + NFC_REG_CMD); |
| 416 | + |
| 417 | + /* use the max erase time as the maximum clock for waiting R/B */ |
| 418 | + cmd = NFC_CMD_RB | NFC_CMD_RB_INT_NO_PIN | nfc->timing.tbers_max; |
| 419 | + writel(cmd, nfc->reg_base + NFC_REG_CMD); |
| 420 | + |
| 421 | + if (!wait_for_completion_timeout(&nfc->completion, |
| 422 | + msecs_to_jiffies(timeout_ms))) |
| 423 | + return -ETIMEDOUT; |
| 424 | + |
| 425 | + if (need_cmd_read0) { |
| 426 | + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_READ0; |
| 427 | + writel(cmd, nfc->reg_base + NFC_REG_CMD); |
| 428 | + meson_nfc_drain_cmd(nfc); |
| 429 | + meson_nfc_wait_cmd_finish(nfc, CMD_FIFO_EMPTY_TIMEOUT); |
| 430 | + } |
| 431 | + |
| 432 | + return 0; |
| 433 | +} |
| 434 | + |
| 435 | +static int meson_nfc_wait_rb_pin(struct meson_nfc *nfc, int timeout_ms) |
399 | 436 | { |
400 | 437 | u32 cmd, cfg; |
401 | 438 | int ret = 0; |
@@ -423,6 +460,27 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms) |
423 | 460 | return ret; |
424 | 461 | } |
425 | 462 |
|
| 463 | +static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms, |
| 464 | + bool need_cmd_read0) |
| 465 | +{ |
| 466 | + if (nfc->no_rb_pin) { |
| 467 | + /* This mode is used when there is no wired R/B pin. |
| 468 | + * It works like 'nand_soft_waitrdy()', but instead of |
| 469 | + * polling NAND_CMD_STATUS bit in the software loop, |
| 470 | + * it will wait for interrupt - controllers checks IO |
| 471 | + * bus and when it detects NAND_CMD_STATUS on it, it |
| 472 | + * raises interrupt. After interrupt, NAND_CMD_READ0 is |
| 473 | + * sent as terminator of the ready waiting procedure if |
| 474 | + * needed (for all cases except page programming - this |
| 475 | + * is reason of 'need_cmd_read0' flag). |
| 476 | + */ |
| 477 | + return meson_nfc_wait_no_rb_pin(nfc, timeout_ms, |
| 478 | + need_cmd_read0); |
| 479 | + } else { |
| 480 | + return meson_nfc_wait_rb_pin(nfc, timeout_ms); |
| 481 | + } |
| 482 | +} |
| 483 | + |
426 | 484 | static void meson_nfc_set_user_byte(struct nand_chip *nand, u8 *oob_buf) |
427 | 485 | { |
428 | 486 | struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); |
@@ -626,7 +684,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, |
626 | 684 | if (in) { |
627 | 685 | nfc->cmdfifo.rw.cmd1 = cs | NFC_CMD_CLE | NAND_CMD_READSTART; |
628 | 686 | writel(nfc->cmdfifo.rw.cmd1, nfc->reg_base + NFC_REG_CMD); |
629 | | - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max)); |
| 687 | + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tR_max), true); |
630 | 688 | } else { |
631 | 689 | meson_nfc_cmd_idle(nfc, nfc->timing.tadl); |
632 | 690 | } |
@@ -672,7 +730,7 @@ static int meson_nfc_write_page_sub(struct nand_chip *nand, |
672 | 730 |
|
673 | 731 | cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG; |
674 | 732 | writel(cmd, nfc->reg_base + NFC_REG_CMD); |
675 | | - meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max)); |
| 733 | + meson_nfc_queue_rb(nfc, PSEC_TO_MSEC(sdr->tPROG_max), false); |
676 | 734 |
|
677 | 735 | meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE); |
678 | 736 |
|
@@ -955,7 +1013,8 @@ static int meson_nfc_exec_op(struct nand_chip *nand, |
955 | 1013 | break; |
956 | 1014 |
|
957 | 1015 | case NAND_OP_WAITRDY_INSTR: |
958 | | - meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms); |
| 1016 | + meson_nfc_queue_rb(nfc, instr->ctx.waitrdy.timeout_ms, |
| 1017 | + true); |
959 | 1018 | if (instr->delay_ns) |
960 | 1019 | meson_nfc_cmd_idle(nfc, delay_idle); |
961 | 1020 | break; |
@@ -1251,6 +1310,7 @@ meson_nfc_nand_chip_init(struct device *dev, |
1251 | 1310 | struct mtd_info *mtd; |
1252 | 1311 | int ret, i; |
1253 | 1312 | u32 tmp, nsels; |
| 1313 | + u32 nand_rb_val = 0; |
1254 | 1314 |
|
1255 | 1315 | nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32)); |
1256 | 1316 | if (!nsels || nsels > MAX_CE_NUM) { |
@@ -1290,6 +1350,15 @@ meson_nfc_nand_chip_init(struct device *dev, |
1290 | 1350 | mtd->owner = THIS_MODULE; |
1291 | 1351 | mtd->dev.parent = dev; |
1292 | 1352 |
|
| 1353 | + ret = of_property_read_u32(np, "nand-rb", &nand_rb_val); |
| 1354 | + if (ret == -EINVAL) |
| 1355 | + nfc->no_rb_pin = true; |
| 1356 | + else if (ret) |
| 1357 | + return ret; |
| 1358 | + |
| 1359 | + if (nand_rb_val) |
| 1360 | + return -EINVAL; |
| 1361 | + |
1293 | 1362 | ret = nand_scan(nand, nsels); |
1294 | 1363 | if (ret) |
1295 | 1364 | return ret; |
|
0 commit comments