Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Kamal Dasu and committed by
Cyrille Pitchen
46dde01f 90d4fa45

+48 -18
+38 -18
drivers/mtd/spi-nor/spi-nor.c
··· 2629 2629 /* Enable Quad I/O if needed. */ 2630 2630 enable_quad_io = (spi_nor_get_protocol_width(nor->read_proto) == 4 || 2631 2631 spi_nor_get_protocol_width(nor->write_proto) == 4); 2632 - if (enable_quad_io && params->quad_enable) { 2633 - err = params->quad_enable(nor); 2632 + if (enable_quad_io && params->quad_enable) 2633 + nor->quad_enable = params->quad_enable; 2634 + else 2635 + nor->quad_enable = NULL; 2636 + 2637 + return 0; 2638 + } 2639 + 2640 + static int spi_nor_init(struct spi_nor *nor) 2641 + { 2642 + int err; 2643 + 2644 + /* 2645 + * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up 2646 + * with the software protection bits set 2647 + */ 2648 + if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL || 2649 + JEDEC_MFR(nor->info) == SNOR_MFR_INTEL || 2650 + JEDEC_MFR(nor->info) == SNOR_MFR_SST || 2651 + nor->info->flags & SPI_NOR_HAS_LOCK) { 2652 + write_enable(nor); 2653 + write_sr(nor, 0); 2654 + spi_nor_wait_till_ready(nor); 2655 + } 2656 + 2657 + if (nor->quad_enable) { 2658 + err = nor->quad_enable(nor); 2634 2659 if (err) { 2635 2660 dev_err(nor->dev, "quad mode not supported\n"); 2636 2661 return err; 2637 2662 } 2638 2663 } 2664 + 2665 + if ((nor->addr_width == 4) && 2666 + (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) && 2667 + !(nor->info->flags & SPI_NOR_4B_OPCODES)) 2668 + set_4byte(nor, nor->info, 1); 2639 2669 2640 2670 return 0; 2641 2671 } ··· 2736 2706 ret = spi_nor_init_params(nor, info, &params); 2737 2707 if (ret) 2738 2708 return ret; 2739 - 2740 - /* 2741 - * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up 2742 - * with the software protection bits set 2743 - */ 2744 - 2745 - if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || 2746 - JEDEC_MFR(info) == SNOR_MFR_INTEL || 2747 - JEDEC_MFR(info) == SNOR_MFR_SST || 2748 - info->flags & SPI_NOR_HAS_LOCK) { 2749 - write_enable(nor); 2750 - write_sr(nor, 0); 2751 - spi_nor_wait_till_ready(nor); 2752 - } 2753 2709 2754 2710 if (!mtd->name) 2755 2711 mtd->name = dev_name(dev); ··· 2819 2803 if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || 2820 2804 info->flags & SPI_NOR_4B_OPCODES) 2821 2805 spi_nor_set_4byte_opcodes(nor, info); 2822 - else 2823 - set_4byte(nor, info, 1); 2824 2806 } else { 2825 2807 nor->addr_width = 3; 2826 2808 } ··· 2834 2820 if (ret) 2835 2821 return ret; 2836 2822 } 2823 + 2824 + /* Send all the required SPI flash commands to initialize device */ 2825 + nor->info = info; 2826 + ret = spi_nor_init(nor); 2827 + if (ret) 2828 + return ret; 2837 2829 2838 2830 dev_info(dev, "%s (%lld Kbytes)\n", info->name, 2839 2831 (long long)mtd->size >> 10);
+10
include/linux/mtd/spi-nor.h
··· 232 232 }; 233 233 234 234 /** 235 + * struct flash_info - Forward declaration of a structure used internally by 236 + * spi_nor_scan() 237 + */ 238 + struct flash_info; 239 + 240 + /** 235 241 * struct spi_nor - Structure for defining a the SPI NOR layer 236 242 * @mtd: point to a mtd_info structure 237 243 * @lock: the lock for the read/write/erase/lock/unlock operations 238 244 * @dev: point to a spi device, or a spi nor controller device. 245 + * @info: spi-nor part JDEC MFR id and other info 239 246 * @page_size: the page size of the SPI NOR 240 247 * @addr_width: number of address bytes 241 248 * @erase_opcode: the opcode for erasing a sector ··· 269 262 * @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR 270 263 * @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR 271 264 * @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is 265 + * @quad_enable: [FLASH-SPECIFIC] enables SPI NOR quad mode 272 266 * completely locked 273 267 * @priv: the private data 274 268 */ ··· 277 269 struct mtd_info mtd; 278 270 struct mutex lock; 279 271 struct device *dev; 272 + const struct flash_info *info; 280 273 u32 page_size; 281 274 u8 addr_width; 282 275 u8 erase_opcode; ··· 305 296 int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); 306 297 int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); 307 298 int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); 299 + int (*quad_enable)(struct spi_nor *nor); 308 300 309 301 void *priv; 310 302 };