Skip to content

Commit 91f3c43

Browse files
Kuwano-sanambarus
authored andcommitted
mtd: spi-nor: spansion: Add a new ->ready() hook for multi-chip device
For multi-chip devices, we need to make sure the all dice in the device are ready. The cypress_nor_sr_ready_and_clear() reads SR in each die and returns true only when all dice are ready. This function also takes care for program or erase error handling by reusing spansion_nor_clear_sr(). To do that, spansion_nor_clear_sr() is moved to top. Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com> Link: https://lore.kernel.org/r/3e4a64613ee733e002279349c75083433be45bf5.1680849425.git.Takahiro.Kuwano@infineon.com Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
1 parent f24d423 commit 91f3c43

1 file changed

Lines changed: 85 additions & 24 deletions

File tree

drivers/mtd/spi-nor/spansion.c

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,84 @@
6363
SPI_MEM_OP_NO_DUMMY, \
6464
SPI_MEM_OP_NO_DATA)
6565

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+
66144
static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
67145
{
68146
struct spi_mem_op op;
@@ -506,10 +584,16 @@ static int s25hx_t_post_sfdp_fixup(struct spi_nor *nor)
506584

507585
static void s25hx_t_late_init(struct spi_nor *nor)
508586
{
587+
struct spi_nor_flash_parameter *params = nor->params;
588+
509589
/* 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;
511591

512592
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;
513597
}
514598

515599
static struct spi_nor_fixups s25hx_t_fixups = {
@@ -741,29 +825,6 @@ static const struct flash_info spansion_nor_parts[] = {
741825
},
742826
};
743827

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-
767828
/**
768829
* spansion_nor_sr_ready_and_clear() - Query the Status Register to see if the
769830
* flash is ready for new commands and clear it if there are any errors.

0 commit comments

Comments
 (0)