diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-22 15:00:44 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-22 15:00:44 -0400 |
| commit | a62d016cece2fce1d5e4eedf36b17f03a7a5c78e (patch) | |
| tree | ac37b4835be5f4fe0e04611fdb40c85abb98ec78 /drivers/mtd/nand/mxc_nand.c | |
| parent | 7c034dfd58bbc056280262887acf5b7a98944d0a (diff) | |
| parent | 3e550d2396d9deef77328237ed992e19dcfefca5 (diff) | |
Merge tag 'for-linus-20150422' of git://git.infradead.org/linux-mtd
Pull MTD updates from Brian Norris:
"Common MTD:
- Add Kconfig option for keeping both the 'master' and 'partition'
MTDs registered as devices. This would really make a better
default if we could do it over, as it allows a lot more flexibility
in (1) determining the flash topology of the system from user-space
and (2) adding temporary partitions at runtime (ioctl(BLKPG)).
Unfortunately, this would possibly cause user-space breakage, as it
will cause renumbering of the /dev/mtdX devices. We'll see if we
can change this in the future, as there have already been a few
people looking for this feature, and I know others have just been
working around our current limitations instead of fixing them this
way.
- Along with the previous change, add some additional information to
sysfs, so user-space can read the offset of each partition within
its master device
SPI NOR:
- add new device tree compatible binding to represent the
mostly-compatible class of SPI NOR flash which can be detected by
their extended JEDEC ID bytes, cutting down the duplication of our
ID tables
- misc. new IDs
Various other miscellaneous fixes and changes"
* tag 'for-linus-20150422' of git://git.infradead.org/linux-mtd: (53 commits)
mtd: spi-nor: Add support for Macronix mx25u6435f serial flash
mtd: spi-nor: Add support for Winbond w25q64dw serial flash
mtd: spi-nor: add support for the Winbond W25X05 flash
mtd: spi-nor: support en25s64 device
mtd: m25p80: bind to "nor-jedec" ID, for auto-detection
Documentation: devicetree: m25p80: add "nor-jedec" binding
mtd: Make MTD tests cancelable
mtd: mtd_oobtest: Fix bitflip_limit usage in test case 3
mtd: docg3: remove invalid __exit annotations
mtd: fsl_ifc_nand: use msecs_to_jiffies for time conversion
mtd: atmel_nand: don't map the ROM table if no pmecc table offset in DT
mtd: atmel_nand: add a definition for the oob reserved bytes
mtd: part: Remove partition overlap checks
mtd: part: Add sysfs variable for offset of partition
mtd: part: Create the master device node when partitioned
mtd: ts5500_flash: Fix typo in MODULE_DESCRIPTION in ts5500_flash.c
mtd: denali: Disable sub-page writes in Denali NAND driver
mtd: pxa3xx_nand: cleanup wait_for_completion handling
mtd: nand: gpmi: Check for scan_bbt() error
mtd: nand: gpmi: fixup return type of wait_for_completion_timeout
...
Diffstat (limited to 'drivers/mtd/nand/mxc_nand.c')
| -rw-r--r-- | drivers/mtd/nand/mxc_nand.c | 146 |
1 files changed, 93 insertions, 53 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index a8f550fec35e..372e0e38f59b 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
| @@ -386,26 +386,51 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | |||
| 386 | /* This function polls the NANDFC to wait for the basic operation to | 386 | /* This function polls the NANDFC to wait for the basic operation to |
| 387 | * complete by checking the INT bit of config2 register. | 387 | * complete by checking the INT bit of config2 register. |
| 388 | */ | 388 | */ |
| 389 | static void wait_op_done(struct mxc_nand_host *host, int useirq) | 389 | static int wait_op_done(struct mxc_nand_host *host, int useirq) |
| 390 | { | 390 | { |
| 391 | int max_retries = 8000; | 391 | int ret = 0; |
| 392 | |||
| 393 | /* | ||
| 394 | * If operation is already complete, don't bother to setup an irq or a | ||
| 395 | * loop. | ||
| 396 | */ | ||
| 397 | if (host->devtype_data->check_int(host)) | ||
| 398 | return 0; | ||
| 392 | 399 | ||
| 393 | if (useirq) { | 400 | if (useirq) { |
| 394 | if (!host->devtype_data->check_int(host)) { | 401 | unsigned long timeout; |
| 395 | reinit_completion(&host->op_completion); | 402 | |
| 396 | irq_control(host, 1); | 403 | reinit_completion(&host->op_completion); |
| 397 | wait_for_completion(&host->op_completion); | 404 | |
| 405 | irq_control(host, 1); | ||
| 406 | |||
| 407 | timeout = wait_for_completion_timeout(&host->op_completion, HZ); | ||
| 408 | if (!timeout && !host->devtype_data->check_int(host)) { | ||
| 409 | dev_dbg(host->dev, "timeout waiting for irq\n"); | ||
| 410 | ret = -ETIMEDOUT; | ||
| 398 | } | 411 | } |
| 399 | } else { | 412 | } else { |
| 400 | while (max_retries-- > 0) { | 413 | int max_retries = 8000; |
| 401 | if (host->devtype_data->check_int(host)) | 414 | int done; |
| 402 | break; | ||
| 403 | 415 | ||
| 416 | do { | ||
| 404 | udelay(1); | 417 | udelay(1); |
| 418 | |||
| 419 | done = host->devtype_data->check_int(host); | ||
| 420 | if (done) | ||
| 421 | break; | ||
| 422 | |||
| 423 | } while (--max_retries); | ||
| 424 | |||
| 425 | if (!done) { | ||
| 426 | dev_dbg(host->dev, "timeout polling for completion\n"); | ||
| 427 | ret = -ETIMEDOUT; | ||
| 405 | } | 428 | } |
| 406 | if (max_retries < 0) | ||
| 407 | pr_debug("%s: INT not set\n", __func__); | ||
| 408 | } | 429 | } |
| 430 | |||
| 431 | WARN_ONCE(ret < 0, "timeout! useirq=%d\n", useirq); | ||
| 432 | |||
| 433 | return ret; | ||
| 409 | } | 434 | } |
| 410 | 435 | ||
| 411 | static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq) | 436 | static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq) |
| @@ -527,30 +552,17 @@ static void send_page_v1(struct mtd_info *mtd, unsigned int ops) | |||
| 527 | 552 | ||
| 528 | static void send_read_id_v3(struct mxc_nand_host *host) | 553 | static void send_read_id_v3(struct mxc_nand_host *host) |
| 529 | { | 554 | { |
| 530 | struct nand_chip *this = &host->nand; | ||
| 531 | |||
| 532 | /* Read ID into main buffer */ | 555 | /* Read ID into main buffer */ |
| 533 | writel(NFC_ID, NFC_V3_LAUNCH); | 556 | writel(NFC_ID, NFC_V3_LAUNCH); |
| 534 | 557 | ||
| 535 | wait_op_done(host, true); | 558 | wait_op_done(host, true); |
| 536 | 559 | ||
| 537 | memcpy32_fromio(host->data_buf, host->main_area0, 16); | 560 | memcpy32_fromio(host->data_buf, host->main_area0, 16); |
| 538 | |||
| 539 | if (this->options & NAND_BUSWIDTH_16) { | ||
| 540 | /* compress the ID info */ | ||
| 541 | host->data_buf[1] = host->data_buf[2]; | ||
| 542 | host->data_buf[2] = host->data_buf[4]; | ||
| 543 | host->data_buf[3] = host->data_buf[6]; | ||
| 544 | host->data_buf[4] = host->data_buf[8]; | ||
| 545 | host->data_buf[5] = host->data_buf[10]; | ||
| 546 | } | ||
| 547 | } | 561 | } |
| 548 | 562 | ||
| 549 | /* Request the NANDFC to perform a read of the NAND device ID. */ | 563 | /* Request the NANDFC to perform a read of the NAND device ID. */ |
| 550 | static void send_read_id_v1_v2(struct mxc_nand_host *host) | 564 | static void send_read_id_v1_v2(struct mxc_nand_host *host) |
| 551 | { | 565 | { |
| 552 | struct nand_chip *this = &host->nand; | ||
| 553 | |||
| 554 | /* NANDFC buffer 0 is used for device ID output */ | 566 | /* NANDFC buffer 0 is used for device ID output */ |
| 555 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); | 567 | writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR); |
| 556 | 568 | ||
| @@ -560,15 +572,6 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) | |||
| 560 | wait_op_done(host, true); | 572 | wait_op_done(host, true); |
| 561 | 573 | ||
| 562 | memcpy32_fromio(host->data_buf, host->main_area0, 16); | 574 | memcpy32_fromio(host->data_buf, host->main_area0, 16); |
| 563 | |||
| 564 | if (this->options & NAND_BUSWIDTH_16) { | ||
| 565 | /* compress the ID info */ | ||
| 566 | host->data_buf[1] = host->data_buf[2]; | ||
| 567 | host->data_buf[2] = host->data_buf[4]; | ||
| 568 | host->data_buf[3] = host->data_buf[6]; | ||
| 569 | host->data_buf[4] = host->data_buf[8]; | ||
| 570 | host->data_buf[5] = host->data_buf[10]; | ||
| 571 | } | ||
| 572 | } | 575 | } |
| 573 | 576 | ||
| 574 | static uint16_t get_dev_status_v3(struct mxc_nand_host *host) | 577 | static uint16_t get_dev_status_v3(struct mxc_nand_host *host) |
| @@ -694,9 +697,17 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) | |||
| 694 | if (host->status_request) | 697 | if (host->status_request) |
| 695 | return host->devtype_data->get_dev_status(host) & 0xFF; | 698 | return host->devtype_data->get_dev_status(host) & 0xFF; |
| 696 | 699 | ||
| 697 | ret = *(uint8_t *)(host->data_buf + host->buf_start); | 700 | if (nand_chip->options & NAND_BUSWIDTH_16) { |
| 698 | host->buf_start++; | 701 | /* only take the lower byte of each word */ |
| 702 | ret = *(uint16_t *)(host->data_buf + host->buf_start); | ||
| 703 | |||
| 704 | host->buf_start += 2; | ||
| 705 | } else { | ||
| 706 | ret = *(uint8_t *)(host->data_buf + host->buf_start); | ||
| 707 | host->buf_start++; | ||
| 708 | } | ||
| 699 | 709 | ||
| 710 | pr_debug("%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start); | ||
| 700 | return ret; | 711 | return ret; |
| 701 | } | 712 | } |
| 702 | 713 | ||
| @@ -825,6 +836,12 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom) | |||
| 825 | } | 836 | } |
| 826 | } | 837 | } |
| 827 | 838 | ||
| 839 | /* | ||
| 840 | * MXC NANDFC can only perform full page+spare or spare-only read/write. When | ||
| 841 | * the upper layers perform a read/write buf operation, the saved column address | ||
| 842 | * is used to index into the full page. So usually this function is called with | ||
| 843 | * column == 0 (unless no column cycle is needed indicated by column == -1) | ||
| 844 | */ | ||
| 828 | static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) | 845 | static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) |
| 829 | { | 846 | { |
| 830 | struct nand_chip *nand_chip = mtd->priv; | 847 | struct nand_chip *nand_chip = mtd->priv; |
| @@ -832,16 +849,13 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) | |||
| 832 | 849 | ||
| 833 | /* Write out column address, if necessary */ | 850 | /* Write out column address, if necessary */ |
| 834 | if (column != -1) { | 851 | if (column != -1) { |
| 835 | /* | 852 | host->devtype_data->send_addr(host, column & 0xff, |
| 836 | * MXC NANDFC can only perform full page+spare or | 853 | page_addr == -1); |
| 837 | * spare-only read/write. When the upper layers | ||
| 838 | * perform a read/write buf operation, the saved column | ||
| 839 | * address is used to index into the full page. | ||
| 840 | */ | ||
| 841 | host->devtype_data->send_addr(host, 0, page_addr == -1); | ||
| 842 | if (mtd->writesize > 512) | 854 | if (mtd->writesize > 512) |
| 843 | /* another col addr cycle for 2k page */ | 855 | /* another col addr cycle for 2k page */ |
| 844 | host->devtype_data->send_addr(host, 0, false); | 856 | host->devtype_data->send_addr(host, |
| 857 | (column >> 8) & 0xff, | ||
| 858 | false); | ||
| 845 | } | 859 | } |
| 846 | 860 | ||
| 847 | /* Write out page address, if necessary */ | 861 | /* Write out page address, if necessary */ |
| @@ -903,7 +917,7 @@ static void preset_v1(struct mtd_info *mtd) | |||
| 903 | struct mxc_nand_host *host = nand_chip->priv; | 917 | struct mxc_nand_host *host = nand_chip->priv; |
| 904 | uint16_t config1 = 0; | 918 | uint16_t config1 = 0; |
| 905 | 919 | ||
| 906 | if (nand_chip->ecc.mode == NAND_ECC_HW) | 920 | if (nand_chip->ecc.mode == NAND_ECC_HW && mtd->writesize) |
| 907 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; | 921 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; |
| 908 | 922 | ||
| 909 | if (!host->devtype_data->irqpending_quirk) | 923 | if (!host->devtype_data->irqpending_quirk) |
| @@ -931,9 +945,6 @@ static void preset_v2(struct mtd_info *mtd) | |||
| 931 | struct mxc_nand_host *host = nand_chip->priv; | 945 | struct mxc_nand_host *host = nand_chip->priv; |
| 932 | uint16_t config1 = 0; | 946 | uint16_t config1 = 0; |
| 933 | 947 | ||
| 934 | if (nand_chip->ecc.mode == NAND_ECC_HW) | ||
| 935 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; | ||
| 936 | |||
| 937 | config1 |= NFC_V2_CONFIG1_FP_INT; | 948 | config1 |= NFC_V2_CONFIG1_FP_INT; |
| 938 | 949 | ||
| 939 | if (!host->devtype_data->irqpending_quirk) | 950 | if (!host->devtype_data->irqpending_quirk) |
| @@ -942,6 +953,9 @@ static void preset_v2(struct mtd_info *mtd) | |||
| 942 | if (mtd->writesize) { | 953 | if (mtd->writesize) { |
| 943 | uint16_t pages_per_block = mtd->erasesize / mtd->writesize; | 954 | uint16_t pages_per_block = mtd->erasesize / mtd->writesize; |
| 944 | 955 | ||
| 956 | if (nand_chip->ecc.mode == NAND_ECC_HW) | ||
| 957 | config1 |= NFC_V1_V2_CONFIG1_ECC_EN; | ||
| 958 | |||
| 945 | host->eccsize = get_eccsize(mtd); | 959 | host->eccsize = get_eccsize(mtd); |
| 946 | if (host->eccsize == 4) | 960 | if (host->eccsize == 4) |
| 947 | config1 |= NFC_V2_CONFIG1_ECC_MODE_4; | 961 | config1 |= NFC_V2_CONFIG1_ECC_MODE_4; |
| @@ -999,9 +1013,6 @@ static void preset_v3(struct mtd_info *mtd) | |||
| 999 | NFC_V3_CONFIG2_INT_MSK | | 1013 | NFC_V3_CONFIG2_INT_MSK | |
| 1000 | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; | 1014 | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; |
| 1001 | 1015 | ||
| 1002 | if (chip->ecc.mode == NAND_ECC_HW) | ||
| 1003 | config2 |= NFC_V3_CONFIG2_ECC_EN; | ||
| 1004 | |||
| 1005 | addr_phases = fls(chip->pagemask) >> 3; | 1016 | addr_phases = fls(chip->pagemask) >> 3; |
| 1006 | 1017 | ||
| 1007 | if (mtd->writesize == 2048) { | 1018 | if (mtd->writesize == 2048) { |
| @@ -1016,6 +1027,9 @@ static void preset_v3(struct mtd_info *mtd) | |||
| 1016 | } | 1027 | } |
| 1017 | 1028 | ||
| 1018 | if (mtd->writesize) { | 1029 | if (mtd->writesize) { |
| 1030 | if (chip->ecc.mode == NAND_ECC_HW) | ||
| 1031 | config2 |= NFC_V3_CONFIG2_ECC_EN; | ||
| 1032 | |||
| 1019 | config2 |= NFC_V3_CONFIG2_PPB( | 1033 | config2 |= NFC_V3_CONFIG2_PPB( |
| 1020 | ffs(mtd->erasesize / mtd->writesize) - 6, | 1034 | ffs(mtd->erasesize / mtd->writesize) - 6, |
| 1021 | host->devtype_data->ppb_shift); | 1035 | host->devtype_data->ppb_shift); |
| @@ -1066,6 +1080,9 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
| 1066 | host->status_request = true; | 1080 | host->status_request = true; |
| 1067 | 1081 | ||
| 1068 | host->devtype_data->send_cmd(host, command, true); | 1082 | host->devtype_data->send_cmd(host, command, true); |
| 1083 | WARN_ONCE(column != -1 || page_addr != -1, | ||
| 1084 | "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n", | ||
| 1085 | command, column, page_addr); | ||
| 1069 | mxc_do_addr_cycle(mtd, column, page_addr); | 1086 | mxc_do_addr_cycle(mtd, column, page_addr); |
| 1070 | break; | 1087 | break; |
| 1071 | 1088 | ||
| @@ -1079,7 +1096,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
| 1079 | command = NAND_CMD_READ0; /* only READ0 is valid */ | 1096 | command = NAND_CMD_READ0; /* only READ0 is valid */ |
| 1080 | 1097 | ||
| 1081 | host->devtype_data->send_cmd(host, command, false); | 1098 | host->devtype_data->send_cmd(host, command, false); |
| 1082 | mxc_do_addr_cycle(mtd, column, page_addr); | 1099 | WARN_ONCE(column < 0, |
| 1100 | "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n", | ||
| 1101 | command, column, page_addr); | ||
| 1102 | mxc_do_addr_cycle(mtd, 0, page_addr); | ||
| 1083 | 1103 | ||
| 1084 | if (mtd->writesize > 512) | 1104 | if (mtd->writesize > 512) |
| 1085 | host->devtype_data->send_cmd(host, | 1105 | host->devtype_data->send_cmd(host, |
| @@ -1100,7 +1120,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
| 1100 | host->buf_start = column; | 1120 | host->buf_start = column; |
| 1101 | 1121 | ||
| 1102 | host->devtype_data->send_cmd(host, command, false); | 1122 | host->devtype_data->send_cmd(host, command, false); |
| 1103 | mxc_do_addr_cycle(mtd, column, page_addr); | 1123 | WARN_ONCE(column < -1, |
| 1124 | "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n", | ||
| 1125 | command, column, page_addr); | ||
| 1126 | mxc_do_addr_cycle(mtd, 0, page_addr); | ||
| 1104 | break; | 1127 | break; |
| 1105 | 1128 | ||
| 1106 | case NAND_CMD_PAGEPROG: | 1129 | case NAND_CMD_PAGEPROG: |
| @@ -1108,6 +1131,9 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
| 1108 | copy_spare(mtd, false); | 1131 | copy_spare(mtd, false); |
| 1109 | host->devtype_data->send_page(mtd, NFC_INPUT); | 1132 | host->devtype_data->send_page(mtd, NFC_INPUT); |
| 1110 | host->devtype_data->send_cmd(host, command, true); | 1133 | host->devtype_data->send_cmd(host, command, true); |
| 1134 | WARN_ONCE(column != -1 || page_addr != -1, | ||
| 1135 | "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n", | ||
| 1136 | command, column, page_addr); | ||
| 1111 | mxc_do_addr_cycle(mtd, column, page_addr); | 1137 | mxc_do_addr_cycle(mtd, column, page_addr); |
| 1112 | break; | 1138 | break; |
| 1113 | 1139 | ||
| @@ -1115,15 +1141,29 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
| 1115 | host->devtype_data->send_cmd(host, command, true); | 1141 | host->devtype_data->send_cmd(host, command, true); |
| 1116 | mxc_do_addr_cycle(mtd, column, page_addr); | 1142 | mxc_do_addr_cycle(mtd, column, page_addr); |
| 1117 | host->devtype_data->send_read_id(host); | 1143 | host->devtype_data->send_read_id(host); |
| 1118 | host->buf_start = column; | 1144 | host->buf_start = 0; |
| 1119 | break; | 1145 | break; |
| 1120 | 1146 | ||
| 1121 | case NAND_CMD_ERASE1: | 1147 | case NAND_CMD_ERASE1: |
| 1122 | case NAND_CMD_ERASE2: | 1148 | case NAND_CMD_ERASE2: |
| 1123 | host->devtype_data->send_cmd(host, command, false); | 1149 | host->devtype_data->send_cmd(host, command, false); |
| 1150 | WARN_ONCE(column != -1, | ||
| 1151 | "Unexpected column value (cmd=%u, col=%d)\n", | ||
| 1152 | command, column); | ||
| 1124 | mxc_do_addr_cycle(mtd, column, page_addr); | 1153 | mxc_do_addr_cycle(mtd, column, page_addr); |
| 1125 | 1154 | ||
| 1126 | break; | 1155 | break; |
| 1156 | case NAND_CMD_PARAM: | ||
| 1157 | host->devtype_data->send_cmd(host, command, false); | ||
| 1158 | mxc_do_addr_cycle(mtd, column, page_addr); | ||
| 1159 | host->devtype_data->send_page(mtd, NFC_OUTPUT); | ||
| 1160 | memcpy32_fromio(host->data_buf, host->main_area0, 512); | ||
| 1161 | host->buf_start = 0; | ||
| 1162 | break; | ||
| 1163 | default: | ||
| 1164 | WARN_ONCE(1, "Unimplemented command (cmd=%u)\n", | ||
| 1165 | command); | ||
| 1166 | break; | ||
| 1127 | } | 1167 | } |
| 1128 | } | 1168 | } |
| 1129 | 1169 | ||
