Skip to content

Commit d534fd9

Browse files
Kuwano-sanambarus
authored andcommitted
mtd: spi-nor: spansion: use CLPEF as an alternative to CLSR
Infineon S28Hx (SEMPER Octal) and S25FS256T (SEMPER Nano) support Clear Program and Erase Failure Flags (CLPEF, 82h) instead of CLSR(30h). Introduce a new mfr_flag together with the infrastructure to allow manufacturer private data in the core. With this we remove the need to have if checks in the code at runtime and instead set the correct opcodes at probe time. S25Hx (SEMPER QSPI) supports CLSR but it may be disabled by CFR3x[2] while CLPEF is always available. Therefore, the mfr_flag is also applied to S25Hx for safety. Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com> Link: https://lore.kernel.org/r/20230726075257.12985-2-tudor.ambarus@linaro.org Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
1 parent abfac0f commit d534fd9

File tree

10 files changed

+103
-32
lines changed

10 files changed

+103
-32
lines changed

drivers/mtd/spi-nor/atmel.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@ static const struct spi_nor_locking_ops at25fs_nor_locking_ops = {
4848
.is_locked = at25fs_nor_is_locked,
4949
};
5050

51-
static void at25fs_nor_late_init(struct spi_nor *nor)
51+
static int at25fs_nor_late_init(struct spi_nor *nor)
5252
{
5353
nor->params->locking_ops = &at25fs_nor_locking_ops;
54+
55+
return 0;
5456
}
5557

5658
static const struct spi_nor_fixups at25fs_nor_fixups = {
@@ -149,9 +151,11 @@ static const struct spi_nor_locking_ops atmel_nor_global_protection_ops = {
149151
.is_locked = atmel_nor_is_global_protected,
150152
};
151153

152-
static void atmel_nor_global_protection_late_init(struct spi_nor *nor)
154+
static int atmel_nor_global_protection_late_init(struct spi_nor *nor)
153155
{
154156
nor->params->locking_ops = &atmel_nor_global_protection_ops;
157+
158+
return 0;
155159
}
156160

157161
static const struct spi_nor_fixups atmel_nor_global_protection_fixups = {

drivers/mtd/spi-nor/core.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2900,16 +2900,23 @@ static void spi_nor_init_fixup_flags(struct spi_nor *nor)
29002900
* SFDP standard, or where SFDP tables are not defined at all.
29012901
* Will replace the spi_nor_manufacturer_init_params() method.
29022902
*/
2903-
static void spi_nor_late_init_params(struct spi_nor *nor)
2903+
static int spi_nor_late_init_params(struct spi_nor *nor)
29042904
{
29052905
struct spi_nor_flash_parameter *params = nor->params;
2906+
int ret;
29062907

29072908
if (nor->manufacturer && nor->manufacturer->fixups &&
2908-
nor->manufacturer->fixups->late_init)
2909-
nor->manufacturer->fixups->late_init(nor);
2909+
nor->manufacturer->fixups->late_init) {
2910+
ret = nor->manufacturer->fixups->late_init(nor);
2911+
if (ret)
2912+
return ret;
2913+
}
29102914

2911-
if (nor->info->fixups && nor->info->fixups->late_init)
2912-
nor->info->fixups->late_init(nor);
2915+
if (nor->info->fixups && nor->info->fixups->late_init) {
2916+
ret = nor->info->fixups->late_init(nor);
2917+
if (ret)
2918+
return ret;
2919+
}
29132920

29142921
/* Default method kept for backward compatibility. */
29152922
if (!params->set_4byte_addr_mode)
@@ -2927,6 +2934,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
29272934

29282935
if (nor->info->n_banks > 1)
29292936
params->bank_size = div64_u64(params->size, nor->info->n_banks);
2937+
2938+
return 0;
29302939
}
29312940

29322941
/**
@@ -3085,9 +3094,7 @@ static int spi_nor_init_params(struct spi_nor *nor)
30853094
spi_nor_init_params_deprecated(nor);
30863095
}
30873096

3088-
spi_nor_late_init_params(nor);
3089-
3090-
return 0;
3097+
return spi_nor_late_init_params(nor);
30913098
}
30923099

30933100
/** spi_nor_set_octal_dtr() - enable or disable Octal DTR I/O.

drivers/mtd/spi-nor/core.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ struct spi_nor_otp {
378378
* than reading the status register to indicate they
379379
* are ready for a new command
380380
* @locking_ops: SPI NOR locking methods.
381+
* @priv: flash's private data.
381382
*/
382383
struct spi_nor_flash_parameter {
383384
u64 bank_size;
@@ -406,6 +407,7 @@ struct spi_nor_flash_parameter {
406407
int (*ready)(struct spi_nor *nor);
407408

408409
const struct spi_nor_locking_ops *locking_ops;
410+
void *priv;
409411
};
410412

411413
/**
@@ -432,7 +434,7 @@ struct spi_nor_fixups {
432434
const struct sfdp_parameter_header *bfpt_header,
433435
const struct sfdp_bfpt *bfpt);
434436
int (*post_sfdp)(struct spi_nor *nor);
435-
void (*late_init)(struct spi_nor *nor);
437+
int (*late_init)(struct spi_nor *nor);
436438
};
437439

438440
/**

drivers/mtd/spi-nor/issi.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static const struct spi_nor_fixups is25lp256_fixups = {
2929
.post_bfpt = is25lp256_post_bfpt_fixups,
3030
};
3131

32-
static void pm25lv_nor_late_init(struct spi_nor *nor)
32+
static int pm25lv_nor_late_init(struct spi_nor *nor)
3333
{
3434
struct spi_nor_erase_map *map = &nor->params->erase_map;
3535
int i;
@@ -38,6 +38,8 @@ static void pm25lv_nor_late_init(struct spi_nor *nor)
3838
for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
3939
if (map->erase_type[i].size == 4096)
4040
map->erase_type[i].opcode = SPINOR_OP_BE_4K_PMC;
41+
42+
return 0;
4143
}
4244

4345
static const struct spi_nor_fixups pm25lv_nor_fixups = {

drivers/mtd/spi-nor/macronix.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,12 @@ static void macronix_nor_default_init(struct spi_nor *nor)
110110
nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
111111
}
112112

113-
static void macronix_nor_late_init(struct spi_nor *nor)
113+
static int macronix_nor_late_init(struct spi_nor *nor)
114114
{
115115
if (!nor->params->set_4byte_addr_mode)
116116
nor->params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_en4b_ex4b;
117+
118+
return 0;
117119
}
118120

119121
static const struct spi_nor_fixups macronix_nor_fixups = {

drivers/mtd/spi-nor/micron-st.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ static void micron_st_nor_default_init(struct spi_nor *nor)
429429
nor->params->quad_enable = NULL;
430430
}
431431

432-
static void micron_st_nor_late_init(struct spi_nor *nor)
432+
static int micron_st_nor_late_init(struct spi_nor *nor)
433433
{
434434
struct spi_nor_flash_parameter *params = nor->params;
435435

@@ -438,6 +438,8 @@ static void micron_st_nor_late_init(struct spi_nor *nor)
438438

439439
if (!params->set_4byte_addr_mode)
440440
params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_wren_en4b_ex4b;
441+
442+
return 0;
441443
}
442444

443445
static const struct spi_nor_fixups micron_st_nor_fixups = {

drivers/mtd/spi-nor/spansion.c

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44
* Copyright (C) 2014, Freescale Semiconductor, Inc.
55
*/
66

7+
#include <linux/device.h>
78
#include <linux/mtd/spi-nor.h>
89

910
#include "core.h"
1011

1112
/* flash_info mfr_flag. Used to clear sticky prorietary SR bits. */
1213
#define USE_CLSR BIT(0)
14+
#define USE_CLPEF BIT(1)
1315

1416
#define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */
17+
#define SPINOR_OP_CLPEF 0x82 /* Clear program/erase failure flags */
1518
#define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */
1619
#define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */
1720
#define SPINOR_REG_CYPRESS_VREG 0x00800000
@@ -57,22 +60,32 @@
5760
SPI_MEM_OP_DUMMY(ndummy, 0), \
5861
SPI_MEM_OP_DATA_IN(1, buf, 0))
5962

60-
#define SPANSION_CLSR_OP \
61-
SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0), \
63+
#define SPANSION_OP(opcode) \
64+
SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0), \
6265
SPI_MEM_OP_NO_ADDR, \
6366
SPI_MEM_OP_NO_DUMMY, \
6467
SPI_MEM_OP_NO_DATA)
6568

69+
/**
70+
* struct spansion_nor_params - Spansion private parameters.
71+
* @clsr: Clear Status Register or Clear Program and Erase Failure Flag
72+
* opcode.
73+
*/
74+
struct spansion_nor_params {
75+
u8 clsr;
76+
};
77+
6678
/**
6779
* spansion_nor_clear_sr() - Clear the Status Register.
6880
* @nor: pointer to 'struct spi_nor'.
6981
*/
7082
static void spansion_nor_clear_sr(struct spi_nor *nor)
7183
{
84+
const struct spansion_nor_params *priv_params = nor->params->priv;
7285
int ret;
7386

7487
if (nor->spimem) {
75-
struct spi_mem_op op = SPANSION_CLSR_OP;
88+
struct spi_mem_op op = SPANSION_OP(priv_params->clsr);
7689

7790
spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
7891

@@ -528,9 +541,11 @@ static int s25fs256t_post_sfdp_fixup(struct spi_nor *nor)
528541
return 0;
529542
}
530543

531-
static void s25fs256t_late_init(struct spi_nor *nor)
544+
static int s25fs256t_late_init(struct spi_nor *nor)
532545
{
533546
cypress_nor_ecc_init(nor);
547+
548+
return 0;
534549
}
535550

536551
static struct spi_nor_fixups s25fs256t_fixups = {
@@ -586,7 +601,7 @@ static int s25hx_t_post_sfdp_fixup(struct spi_nor *nor)
586601
return cypress_nor_get_page_size(nor);
587602
}
588603

589-
static void s25hx_t_late_init(struct spi_nor *nor)
604+
static int s25hx_t_late_init(struct spi_nor *nor)
590605
{
591606
struct spi_nor_flash_parameter *params = nor->params;
592607

@@ -598,6 +613,8 @@ static void s25hx_t_late_init(struct spi_nor *nor)
598613
/* Replace ready() with multi die version */
599614
if (params->n_dice)
600615
params->ready = cypress_nor_sr_ready_and_clear;
616+
617+
return 0;
601618
}
602619

603620
static struct spi_nor_fixups s25hx_t_fixups = {
@@ -659,10 +676,12 @@ static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
659676
return cypress_nor_set_addr_mode_nbytes(nor);
660677
}
661678

662-
static void s28hx_t_late_init(struct spi_nor *nor)
679+
static int s28hx_t_late_init(struct spi_nor *nor)
663680
{
664681
nor->params->set_octal_dtr = cypress_nor_set_octal_dtr;
665682
cypress_nor_ecc_init(nor);
683+
684+
return 0;
666685
}
667686

668687
static const struct spi_nor_fixups s28hx_t_fixups = {
@@ -786,47 +805,54 @@ static const struct flash_info spansion_nor_parts[] = {
786805
FIXUP_FLAGS(SPI_NOR_4B_OPCODES) },
787806
{ "s25fs256t", INFO6(0x342b19, 0x0f0890, 0, 0)
788807
PARSE_SFDP
808+
MFR_FLAGS(USE_CLPEF)
789809
.fixups = &s25fs256t_fixups },
790810
{ "s25hl512t", INFO6(0x342a1a, 0x0f0390, 256 * 1024, 256)
791811
PARSE_SFDP
792-
MFR_FLAGS(USE_CLSR)
812+
MFR_FLAGS(USE_CLPEF)
793813
.fixups = &s25hx_t_fixups },
794814
{ "s25hl01gt", INFO6(0x342a1b, 0x0f0390, 256 * 1024, 512)
795815
PARSE_SFDP
796-
MFR_FLAGS(USE_CLSR)
816+
MFR_FLAGS(USE_CLPEF)
797817
.fixups = &s25hx_t_fixups },
798818
{ "s25hl02gt", INFO6(0x342a1c, 0x0f0090, 0, 0)
799819
PARSE_SFDP
820+
MFR_FLAGS(USE_CLPEF)
800821
FLAGS(NO_CHIP_ERASE)
801822
.fixups = &s25hx_t_fixups },
802823
{ "s25hs512t", INFO6(0x342b1a, 0x0f0390, 256 * 1024, 256)
803824
PARSE_SFDP
804-
MFR_FLAGS(USE_CLSR)
825+
MFR_FLAGS(USE_CLPEF)
805826
.fixups = &s25hx_t_fixups },
806827
{ "s25hs01gt", INFO6(0x342b1b, 0x0f0390, 256 * 1024, 512)
807828
PARSE_SFDP
808-
MFR_FLAGS(USE_CLSR)
829+
MFR_FLAGS(USE_CLPEF)
809830
.fixups = &s25hx_t_fixups },
810831
{ "s25hs02gt", INFO6(0x342b1c, 0x0f0090, 0, 0)
811832
PARSE_SFDP
833+
MFR_FLAGS(USE_CLPEF)
812834
FLAGS(NO_CHIP_ERASE)
813835
.fixups = &s25hx_t_fixups },
814836
{ "cy15x104q", INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1)
815837
FLAGS(SPI_NOR_NO_ERASE) },
816838
{ "s28hl512t", INFO(0x345a1a, 0, 256 * 1024, 256)
817839
PARSE_SFDP
840+
MFR_FLAGS(USE_CLPEF)
818841
.fixups = &s28hx_t_fixups,
819842
},
820843
{ "s28hl01gt", INFO(0x345a1b, 0, 256 * 1024, 512)
821844
PARSE_SFDP
845+
MFR_FLAGS(USE_CLPEF)
822846
.fixups = &s28hx_t_fixups,
823847
},
824848
{ "s28hs512t", INFO(0x345b1a, 0, 256 * 1024, 256)
825849
PARSE_SFDP
850+
MFR_FLAGS(USE_CLPEF)
826851
.fixups = &s28hx_t_fixups,
827852
},
828853
{ "s28hs01gt", INFO(0x345b1b, 0, 256 * 1024, 512)
829854
PARSE_SFDP
855+
MFR_FLAGS(USE_CLPEF)
830856
.fixups = &s28hx_t_fixups,
831857
},
832858
};
@@ -870,17 +896,35 @@ static int spansion_nor_sr_ready_and_clear(struct spi_nor *nor)
870896
return !(nor->bouncebuf[0] & SR_WIP);
871897
}
872898

873-
static void spansion_nor_late_init(struct spi_nor *nor)
899+
static int spansion_nor_late_init(struct spi_nor *nor)
874900
{
875-
if (nor->params->size > SZ_16M) {
901+
struct spi_nor_flash_parameter *params = nor->params;
902+
struct spansion_nor_params *priv_params;
903+
u8 mfr_flags = nor->info->mfr_flags;
904+
905+
if (params->size > SZ_16M) {
876906
nor->flags |= SNOR_F_4B_OPCODES;
877907
/* No small sector erase for 4-byte command set */
878908
nor->erase_opcode = SPINOR_OP_SE;
879909
nor->mtd.erasesize = nor->info->sector_size;
880910
}
881911

882-
if (nor->info->mfr_flags & USE_CLSR)
883-
nor->params->ready = spansion_nor_sr_ready_and_clear;
912+
if (mfr_flags & (USE_CLSR | USE_CLPEF)) {
913+
priv_params = devm_kmalloc(nor->dev, sizeof(*priv_params),
914+
GFP_KERNEL);
915+
if (!priv_params)
916+
return -ENOMEM;
917+
918+
if (mfr_flags & USE_CLSR)
919+
priv_params->clsr = SPINOR_OP_CLSR;
920+
else if (mfr_flags & USE_CLPEF)
921+
priv_params->clsr = SPINOR_OP_CLPEF;
922+
923+
params->priv = priv_params;
924+
params->ready = spansion_nor_sr_ready_and_clear;
925+
}
926+
927+
return 0;
884928
}
885929

886930
static const struct spi_nor_fixups spansion_nor_fixups = {

drivers/mtd/spi-nor/sst.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,11 @@ static const struct spi_nor_locking_ops sst26vf_nor_locking_ops = {
4949
.is_locked = sst26vf_nor_is_locked,
5050
};
5151

52-
static void sst26vf_nor_late_init(struct spi_nor *nor)
52+
static int sst26vf_nor_late_init(struct spi_nor *nor)
5353
{
5454
nor->params->locking_ops = &sst26vf_nor_locking_ops;
55+
56+
return 0;
5557
}
5658

5759
static const struct spi_nor_fixups sst26vf_nor_fixups = {
@@ -203,10 +205,12 @@ static int sst_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
203205
return ret;
204206
}
205207

206-
static void sst_nor_late_init(struct spi_nor *nor)
208+
static int sst_nor_late_init(struct spi_nor *nor)
207209
{
208210
if (nor->info->mfr_flags & SST_WRITE)
209211
nor->mtd._write = sst_nor_write;
212+
213+
return 0;
210214
}
211215

212216
static const struct spi_nor_fixups sst_nor_fixups = {

drivers/mtd/spi-nor/winbond.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ static const struct spi_nor_otp_ops winbond_nor_otp_ops = {
217217
.is_locked = spi_nor_otp_is_locked_sr2,
218218
};
219219

220-
static void winbond_nor_late_init(struct spi_nor *nor)
220+
static int winbond_nor_late_init(struct spi_nor *nor)
221221
{
222222
struct spi_nor_flash_parameter *params = nor->params;
223223

@@ -233,6 +233,8 @@ static void winbond_nor_late_init(struct spi_nor *nor)
233233
* from BFPT, if any.
234234
*/
235235
params->set_4byte_addr_mode = winbond_nor_set_4byte_addr_mode;
236+
237+
return 0;
236238
}
237239

238240
static const struct spi_nor_fixups winbond_nor_fixups = {

0 commit comments

Comments
 (0)