Skip to content

Commit ef26b7d

Browse files
KamalDasuambarus
authored andcommitted
mtd: spi-nor: add spi_nor_init() function
This patch extracts some chunks from spi_nor_init_params and spi_nor_scan() and moves them into a new spi_nor_init() function. Indeed, spi_nor_init() regroups all the required SPI flash commands to be sent to the SPI flash memory before performing any runtime operations (Fast Read, Page Program, Sector Erase, ...). Hence spi_nor_init(): 1) removes the flash protection if applicable for certain vendors. 2) sets the Quad Enable bit, if needed, before using Quad SPI protocols. 3) makes the memory enter its (stateful) 4-byte address mode, if needed, for SPI flash memory > 128Mbits not supporting the 4-byte address instruction set. spi_nor_scan() now ends by calling spi_nor_init() once the probe phase has completed. Further patches could also use spi_nor_init() to implement the mtd->_resume() handler for the spi-nor framework. Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr> (cherry picked from commit 46dde01)
1 parent a16134b commit ef26b7d

2 files changed

Lines changed: 48 additions & 18 deletions

File tree

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

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2630,14 +2630,44 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
26302630
/* Enable Quad I/O if needed. */
26312631
enable_quad_io = (spi_nor_get_protocol_width(nor->read_proto) == 4 ||
26322632
spi_nor_get_protocol_width(nor->write_proto) == 4);
2633-
if (enable_quad_io && params->quad_enable) {
2634-
err = params->quad_enable(nor);
2633+
if (enable_quad_io && params->quad_enable)
2634+
nor->quad_enable = params->quad_enable;
2635+
else
2636+
nor->quad_enable = NULL;
2637+
2638+
return 0;
2639+
}
2640+
2641+
static int spi_nor_init(struct spi_nor *nor)
2642+
{
2643+
int err;
2644+
2645+
/*
2646+
* Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
2647+
* with the software protection bits set
2648+
*/
2649+
if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
2650+
JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
2651+
JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
2652+
nor->info->flags & SPI_NOR_HAS_LOCK) {
2653+
write_enable(nor);
2654+
write_sr(nor, 0);
2655+
spi_nor_wait_till_ready(nor);
2656+
}
2657+
2658+
if (nor->quad_enable) {
2659+
err = nor->quad_enable(nor);
26352660
if (err) {
26362661
dev_err(nor->dev, "quad mode not supported\n");
26372662
return err;
26382663
}
26392664
}
26402665

2666+
if ((nor->addr_width == 4) &&
2667+
(JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) &&
2668+
!(nor->info->flags & SPI_NOR_4B_OPCODES))
2669+
set_4byte(nor, nor->info, 1);
2670+
26412671
return 0;
26422672
}
26432673

@@ -2708,20 +2738,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
27082738
if (ret)
27092739
return ret;
27102740

2711-
/*
2712-
* Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
2713-
* with the software protection bits set
2714-
*/
2715-
2716-
if (JEDEC_MFR(info) == SNOR_MFR_ATMEL ||
2717-
JEDEC_MFR(info) == SNOR_MFR_INTEL ||
2718-
JEDEC_MFR(info) == SNOR_MFR_SST ||
2719-
info->flags & SPI_NOR_HAS_LOCK) {
2720-
write_enable(nor);
2721-
write_sr(nor, 0);
2722-
spi_nor_wait_till_ready(nor);
2723-
}
2724-
27252741
if (!mtd->name)
27262742
mtd->name = dev_name(dev);
27272743
mtd->priv = nor;
@@ -2804,8 +2820,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
28042820
if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
28052821
info->flags & SPI_NOR_4B_OPCODES)
28062822
spi_nor_set_4byte_opcodes(nor, info);
2807-
else
2808-
set_4byte(nor, info, 1);
28092823
} else {
28102824
nor->addr_width = 3;
28112825
}
@@ -2822,6 +2836,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
28222836
return ret;
28232837
}
28242838

2839+
/* Send all the required SPI flash commands to initialize device */
2840+
nor->info = info;
2841+
ret = spi_nor_init(nor);
2842+
if (ret)
2843+
return ret;
2844+
28252845
dev_info(dev, "%s (%lld Kbytes)\n", info->name,
28262846
(long long)mtd->size >> 10);
28272847

include/linux/mtd/spi-nor.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,11 +231,18 @@ enum spi_nor_option_flags {
231231
SNOR_F_USE_CLSR = BIT(5),
232232
};
233233

234+
/**
235+
* struct flash_info - Forward declaration of a structure used internally by
236+
* spi_nor_scan()
237+
*/
238+
struct flash_info;
239+
234240
/**
235241
* struct spi_nor - Structure for defining a the SPI NOR layer
236242
* @mtd: point to a mtd_info structure
237243
* @lock: the lock for the read/write/erase/lock/unlock operations
238244
* @dev: point to a spi device, or a spi nor controller device.
245+
* @info: spi-nor part JDEC MFR id and other info
239246
* @page_size: the page size of the SPI NOR
240247
* @addr_width: number of address bytes
241248
* @erase_opcode: the opcode for erasing a sector
@@ -262,13 +269,15 @@ enum spi_nor_option_flags {
262269
* @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR
263270
* @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR
264271
* @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is
272+
* @quad_enable: [FLASH-SPECIFIC] enables SPI NOR quad mode
265273
* completely locked
266274
* @priv: the private data
267275
*/
268276
struct spi_nor {
269277
struct mtd_info mtd;
270278
struct mutex lock;
271279
struct device *dev;
280+
const struct flash_info *info;
272281
u32 page_size;
273282
u8 addr_width;
274283
u8 erase_opcode;
@@ -296,6 +305,7 @@ struct spi_nor {
296305
int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
297306
int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
298307
int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
308+
int (*quad_enable)(struct spi_nor *nor);
299309

300310
void *priv;
301311
};

0 commit comments

Comments
 (0)