|
63 | 63 | SPI_MEM_OP_NO_DUMMY, \ |
64 | 64 | SPI_MEM_OP_NO_DATA) |
65 | 65 |
|
| 66 | +/** |
| 67 | + * spansion_nor_clear_sr() - Clear the Status Register. |
| 68 | + * @nor: pointer to 'struct spi_nor'. |
| 69 | + */ |
| 70 | +static void spansion_nor_clear_sr(struct spi_nor *nor) |
| 71 | +{ |
| 72 | + int ret; |
| 73 | + |
| 74 | + if (nor->spimem) { |
| 75 | + struct spi_mem_op op = SPANSION_CLSR_OP; |
| 76 | + |
| 77 | + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); |
| 78 | + |
| 79 | + ret = spi_mem_exec_op(nor->spimem, &op); |
| 80 | + } else { |
| 81 | + ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_CLSR, |
| 82 | + NULL, 0); |
| 83 | + } |
| 84 | + |
| 85 | + if (ret) |
| 86 | + dev_dbg(nor->dev, "error %d clearing SR\n", ret); |
| 87 | +} |
| 88 | + |
| 89 | +static int cypress_nor_sr_ready_and_clear_reg(struct spi_nor *nor, u64 addr) |
| 90 | +{ |
| 91 | + struct spi_mem_op op = |
| 92 | + CYPRESS_NOR_RD_ANY_REG_OP(nor->params->addr_mode_nbytes, addr, |
| 93 | + 0, nor->bouncebuf); |
| 94 | + int ret; |
| 95 | + |
| 96 | + ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto); |
| 97 | + if (ret) |
| 98 | + return ret; |
| 99 | + |
| 100 | + if (nor->bouncebuf[0] & (SR_E_ERR | SR_P_ERR)) { |
| 101 | + if (nor->bouncebuf[0] & SR_E_ERR) |
| 102 | + dev_err(nor->dev, "Erase Error occurred\n"); |
| 103 | + else |
| 104 | + dev_err(nor->dev, "Programming Error occurred\n"); |
| 105 | + |
| 106 | + spansion_nor_clear_sr(nor); |
| 107 | + |
| 108 | + ret = spi_nor_write_disable(nor); |
| 109 | + if (ret) |
| 110 | + return ret; |
| 111 | + |
| 112 | + return -EIO; |
| 113 | + } |
| 114 | + |
| 115 | + return !(nor->bouncebuf[0] & SR_WIP); |
| 116 | +} |
| 117 | +/** |
| 118 | + * cypress_nor_sr_ready_and_clear() - Query the Status Register of each die by |
| 119 | + * using Read Any Register command to see if the whole flash is ready for new |
| 120 | + * commands and clear it if there are any errors. |
| 121 | + * @nor: pointer to 'struct spi_nor'. |
| 122 | + * |
| 123 | + * Return: 1 if ready, 0 if not ready, -errno on errors. |
| 124 | + */ |
| 125 | +static int cypress_nor_sr_ready_and_clear(struct spi_nor *nor) |
| 126 | +{ |
| 127 | + struct spi_nor_flash_parameter *params = nor->params; |
| 128 | + u64 addr; |
| 129 | + int ret; |
| 130 | + u8 i; |
| 131 | + |
| 132 | + for (i = 0; i < params->n_dice; i++) { |
| 133 | + addr = params->vreg_offset[i] + SPINOR_REG_CYPRESS_STR1; |
| 134 | + ret = cypress_nor_sr_ready_and_clear_reg(nor, addr); |
| 135 | + if (ret < 0) |
| 136 | + return ret; |
| 137 | + else if (ret == 0) |
| 138 | + return 0; |
| 139 | + } |
| 140 | + |
| 141 | + return 1; |
| 142 | +} |
| 143 | + |
66 | 144 | static int cypress_nor_octal_dtr_en(struct spi_nor *nor) |
67 | 145 | { |
68 | 146 | struct spi_mem_op op; |
@@ -506,10 +584,16 @@ static int s25hx_t_post_sfdp_fixup(struct spi_nor *nor) |
506 | 584 |
|
507 | 585 | static void s25hx_t_late_init(struct spi_nor *nor) |
508 | 586 | { |
| 587 | + struct spi_nor_flash_parameter *params = nor->params; |
| 588 | + |
509 | 589 | /* Fast Read 4B requires mode cycles */ |
510 | | - nor->params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8; |
| 590 | + params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8; |
511 | 591 |
|
512 | 592 | cypress_nor_ecc_init(nor); |
| 593 | + |
| 594 | + /* Replace ready() with multi die version */ |
| 595 | + if (params->n_dice) |
| 596 | + params->ready = cypress_nor_sr_ready_and_clear; |
513 | 597 | } |
514 | 598 |
|
515 | 599 | static struct spi_nor_fixups s25hx_t_fixups = { |
@@ -741,29 +825,6 @@ static const struct flash_info spansion_nor_parts[] = { |
741 | 825 | }, |
742 | 826 | }; |
743 | 827 |
|
744 | | -/** |
745 | | - * spansion_nor_clear_sr() - Clear the Status Register. |
746 | | - * @nor: pointer to 'struct spi_nor'. |
747 | | - */ |
748 | | -static void spansion_nor_clear_sr(struct spi_nor *nor) |
749 | | -{ |
750 | | - int ret; |
751 | | - |
752 | | - if (nor->spimem) { |
753 | | - struct spi_mem_op op = SPANSION_CLSR_OP; |
754 | | - |
755 | | - spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); |
756 | | - |
757 | | - ret = spi_mem_exec_op(nor->spimem, &op); |
758 | | - } else { |
759 | | - ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_CLSR, |
760 | | - NULL, 0); |
761 | | - } |
762 | | - |
763 | | - if (ret) |
764 | | - dev_dbg(nor->dev, "error %d clearing SR\n", ret); |
765 | | -} |
766 | | - |
767 | 828 | /** |
768 | 829 | * spansion_nor_sr_ready_and_clear() - Query the Status Register to see if the |
769 | 830 | * flash is ready for new commands and clear it if there are any errors. |
|
0 commit comments