include: Add log2 and fls64 header files
Subsystems (8)
PATCH v7 1/4 include: Add log2 and fls64 header files
From: Fabio Estevam <[email protected]>
Use the log2 and fls64 header files from the kernel.
---
Changes since v6:
- Newly introduced in this series
include/asm-generic/bitops/fls64.h | 36 +++++++ include/linux/bitops.h | 9 ++ include/linux/log2.h | 208 +++++++++++++++++++++++++++++++++++++ 3 files changed, 253 insertions(+) create mode 100644 include/asm-generic/bitops/fls64.h create mode 100644 include/linux/log2.h
include/asm-generic/bitops/fls64.h new file +36 -0
@@ -0,0 +1,36 @@ +#ifndef _ASM_GENERIC_BITOPS_FLS64_H_ +#define _ASM_GENERIC_BITOPS_FLS64_H_ + +#include <asm/types.h> + +/** +* fls64 - find last set bit in a 64-bit word +* @x: the word to search +* +* This is defined in a similar way as the libc and compiler builtin +* ffsll, but returns the position of the most significant set bit. +* +* fls64(value) returns 0 if value is 0 or the position of the last +* set bit if value is nonzero. The last (most significant) bit is +* at position 64. +*/ +#if BITS_PER_LONG ==32 +static inline int fls64 (__u64 x) +{ +__u32 h = x >>32 ; +if (h) +return fls (h) +32 ; +return fls (x); +} +#elif BITS_PER_LONG ==64 +static inline int fls64 (__u64 x) +{ +if (x ==0 ) +return 0 ; +return __fls (x) +1 ; +} +#else +#error BITS_PER_LONG not 32 or 64 +#endif + +#endif /* _ASM_GENERIC_BITOPS_FLS64_H_ */
include/linux/bitops.h +9 -0
@@ -129,6 +129,15 @@ static inline unsigned int generic_hweight8(unsigned int w)# define fls generic_fls#endif +#include <asm-generic/bitops/fls64.h> + +static inline unsigned fls_long (unsigned long l) +{ +if (sizeof (l) ==4 ) +return fls (l); +return fls64 (l); +} +/** * __set_bit - Set a bit in memory * @nr: the bit to set
include/linux/log2.h new file +208 -0
208 lines not on this page · raw message
Signature · 1 line
1.9.1
PATCH v7 2/4 compat: Remove is_power_of_2() definition
From: Fabio Estevam <[email protected]>
Use the is_power_of_2() definition from log2.h to align with the kernel implementation.
Remove the is_power_of_2() definition from compat.h.
---
Changes since v6:
- Newly introduced in this series
arch/arm/mach-mvebu/mbus.c | 2 +- drivers/mtd/mtdcore.c | 2 +- drivers/mtd/ubi/build.c | 2 +- fs/ubifs/super.c | 2 +- include/linux/compat.h | 6 ------ 5 files changed, 4 insertions(+), 10 deletions(-)
arch/arm/mach-mvebu/mbus.c +1 -1
@@ -52,7 +52,7 @@#include <asm/io.h> #include <asm/arch/cpu.h> #include <asm/arch/soc.h> -#include <linux/compat.h> +#include <linux/log2.h> #include <linux/mbus.h> /* DDR target is the same on all platforms */
drivers/mtd/mtdcore.c +1 -1
@@ -27,8 +27,8 @@#include <linux/gfp.h> #include <linux/slab.h> #else -#include <linux/compat.h> #include <linux/err.h> +#include <linux/log2.h> #include <ubi_uboot.h> #endif
drivers/mtd/ubi/build.c +1 -1
@@ -30,7 +30,7 @@#include <linux/slab.h> #include <linux/major.h> #else -#include <linux/compat.h> +#include <linux/log2.h> #endif #include <linux/err.h> #include <ubi_uboot.h>
fs/ubifs/super.c +1 -1
@@ -31,7 +31,7 @@#include <common.h> #include <malloc.h> #include <memalign.h> -#include <linux/compat.h> +#include <linux/log2.h> #include <linux/stat.h> #include <linux/err.h> #include "ubifs.h"
include/linux/compat.h +0 -6
@@ -104,12 +104,6 @@ static inline void led_trigger_unregister_simple(struct led_trigger *trigger) {}static inline void led_trigger_event (struct led_trigger *trigger,enum led_brightness event) {} -/* include/linux/log2.h */ -static inline int is_power_of_2 (unsigned long n) -{ -return (n !=0 && ((n & (n -1 )) ==0 )); -} -/* uapi/linux/limits.h */ #define XATTR_LIST_MAX 65536/* size of extended attribute namelist (64k) */
Signature · 1 line
1.9.1
PATCH v7 3/4 spi: sf_ops: Add SPI protection mechanism from the kernel
In reply to Fabio EstevamFrom: Fabio Estevam <[email protected]>
Add the SPI NOR protection mechanism from the kernel.
This code is based on the work from Brian Norris <[email protected]>
---
Changes since v6:
-Point the original patch location from the kernel
drivers/mtd/spi/sf_ops.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+)
drivers/mtd/spi/sf_ops.c +189 -0
@@ -15,6 +15,7 @@#include <spi_flash.h> #include <watchdog.h> #include <linux/compiler.h> +#include <linux/log2.h> #include "sf_internal.h"
@@ -573,3 +574,191 @@ int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,return ret; }#endif + +#ifdef CONFIG_SPI_FLASH_STMICRO +#define SR_BP0 BIT(2)/* Block protect 0 */ +#define SR_BP1 BIT(3)/* Block protect 1 */ +#define SR_BP2 BIT(4)/* Block protect 2 */ + +static void stm_get_locked_range (struct spi_flash *nor,u8 sr,loff_t *ofs, +u32 *len) +{ +u8 mask =SR_BP2 |SR_BP1 |SR_BP0 ; +int shift =ffs (mask) -1 ; +int pow; + +if (!(sr & mask)) { +/* No protection */ + *ofs =0 ; + *len =0 ; + }else { + pow = ((sr & mask) ^ mask) >> shift; + *len = nor->size >> pow; + *ofs = nor->size - *len; + } +} + +/* +* Return 1 if the entire region is locked, 0 otherwise +*/ +static int stm_is_locked_sr (struct spi_flash *nor,loff_t ofs,u32 len, +u8 sr) +{ +loff_t lock_offs; +u32 lock_len; + +stm_get_locked_range (nor, sr, &lock_offs, &lock_len); + +return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); +} + +/* +* Check if a region of the flash is (completely) locked. See stm_lock() for +* more info. +* +* Returns 1 if entire region is locked, 0 if any portion is unlocked, and +* negative on errors. +*/ +int stm_is_locked (struct spi_flash *nor,loff_t ofs,u32 len) +{ +int status; +u8 sr; + + status =spi_flash_cmd_read_status (nor, &sr); +if (status <0 ) +return status; + +return stm_is_locked_sr (nor, ofs, len, sr); +} + +/* +* Lock a region of the flash. Compatible with ST Micro and similar flash. +* Supports only the block protection bits BP{0,1,2} in the status register +* (SR). Does not support these features found in newer SR bitfields: +* - TB: top/bottom protect - only handle TB=0 (top protect) +* - SEC: sector/block protect - only handle SEC=0 (block protect) +* - CMP: complement protect - only support CMP=0 (range is not complemented) +* +* Sample table portion for 8MB flash (Winbond w25q64fw): +* +* SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion +* -------------------------------------------------------------------------- +* X | X | 0 | 0 | 0 | NONE | NONE +* 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 +* 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 +* 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 +* 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 +* 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 +* 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 +* X | X | 1 | 1 | 1 | 8 MB | ALL +* +* Returns negative on errors, 0 on success. +*/ +int stm_lock (struct spi_flash *nor,u32 ofs,u32 len) +{ +u8 status_old, status_new; +u8 mask =SR_BP2 |SR_BP1 |SR_BP0 ; +u8 shift =ffs (mask) -1 , pow, val; + +spi_flash_cmd_read_status (nor, &status_old); + +/* SPI NOR always locks to the end */ +if (ofs + len != nor->size) { +/* Does combined region extend to end? */ +if (!stm_is_locked_sr (nor, ofs + len, nor->size - ofs - len, + status_old)) +return -EINVAL ; + len = nor->size - ofs; + } + +/* +* Need smallest pow such that: +* +* 1 / (2^pow) <= (len / size) +* +* so (assuming power-of-2 size) we do: +* +* pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) +*/ + pow =ilog2 (nor->size) -ilog2 (len); + val = mask - (pow << shift); +if (val & ~mask) +return -EINVAL ; + +/* Don't "lock" with no region! */ +if (!(val & mask)) +return -EINVAL ; + + status_new = (status_old & ~mask) | val; + +/* Only modify protection if it will not unlock other areas */ +if ((status_new & mask) <= (status_old & mask)) +return -EINVAL ; + +spi_flash_cmd_write_status (nor, status_new); + +return 0 ; +} + +/* +* Unlock a region of the flash. See stm_lock() for more info +* +* Returns negative on errors, 0 on success. +*/ +int stm_unlock (struct spi_flash *nor,u32 ofs,u32 len) +{ +uint8_t status_old, status_new; +u8 mask =SR_BP2 |SR_BP1 |SR_BP0 ; +u8 shift =ffs (mask) -1 , pow, val; + +spi_flash_cmd_read_status (nor, &status_old); + +/* Cannot unlock; would unlock larger region than requested */ +if (stm_is_locked_sr (nor, status_old, ofs - nor->erase_size, + nor->erase_size)) +return -EINVAL ; +/* +* Need largest pow such that: +* +* 1 / (2^pow) >= (len / size) +* +* so (assuming power-of-2 size) we do: +* +* pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) +*/ + pow =ilog2 (nor->size) -order_base_2 (nor->size - (ofs + len)); +if (ofs + len == nor->size) { + val =0 ;/* fully unlocked */ + }else { + val = mask - (pow << shift); +/* Some power-of-two sizes are not supported */ +if (val & ~mask) +return -EINVAL ; + } + + status_new = (status_old & ~mask) | val; + +/* Only modify protection if it will not lock other areas */ +if ((status_new & mask) >= (status_old & mask)) +return -EINVAL ; + +spi_flash_cmd_write_status (nor, status_new); + +return 0 ; +} +#else +int stm_is_locked (struct spi_flash *nor,loff_t ofs,u32 len) +{ +return 0 ; +} + +int stm_lock (struct spi_flash *nor,u32 ofs,u32 len) +{ +return 0 ; +} + +int stm_unlock (struct spi_flash *nor,u32 ofs,u32 len) +{ +return 0 ; +} +#endif /* CONFIG_SPI_FLASH_STMICRO */
Signature · 1 line
1.9.1
PATCH v7 3/4 spi: sf_ops: Add SPI protection mechanism from the kernel
Quoted 29 lines · Fabio Estevam
From: Fabio Estevam <[email protected]>
Add the SPI NOR protection mechanism from the kernel.
This code is based on the work from Brian Norris <[email protected]>
Signed-off-by Fabio Estevam <[email protected]>---
Changes since v6:(quoted diff) +0
-1-Point the original patch location from the kernel drivers/mtd/spi/sf_ops.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+)drivers/mtd/spi/sf_ops.c +1
-0@@ -15,6 +15,7 @@#include <spi_flash.h> #include <watchdog.h> #include <linux/compiler.h> +#include <linux/log2.h> #include "sf_internal.h"
drivers/mtd/spi/sf_ops.c int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, · line 581
Quoted 8 lines
drivers/mtd/spi/sf_ops.c +5
-0@@ -573,3 +574,191 @@ int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, return ret; }#endif + +#ifdef CONFIG_SPI_FLASH_STMICRO +#define SR_BP0 BIT(2)/* Block protect 0 */ +#define SR_BP1 BIT(3)/* Block protect 1 */ +#define SR_BP2 BIT(4)/* Block protect 2 */
Move these macros to header.
drivers/mtd/spi/sf_ops.c int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, · line 583
Quoted 2 lines
drivers/mtd/spi/sf_ops.c +2
-0+ +static void stm_get_locked_range(struct spi_flash *nor, u8 sr, loff_t *ofs,
Already point this "*nor' notation in previous versions, please use flash.
And also don't post next level patches until the current version discussion on ends.
Quoted 155 lines
drivers/mtd/spi/sf_ops.c +155
-0+ u32 *len) +{ +u8 mask =SR_BP2 |SR_BP1 |SR_BP0 ; +int shift =ffs (mask) -1 ; +int pow; + +if (!(sr & mask)) { +/* No protection */ + *ofs =0 ; + *len =0 ; + }else { + pow = ((sr & mask) ^ mask) >> shift; + *len = nor->size >> pow; + *ofs = nor->size - *len; + } +} + +/* +* Return 1 if the entire region is locked, 0 otherwise +*/ +static int stm_is_locked_sr (struct spi_flash *nor,loff_t ofs,u32 len, +u8 sr) +{ +loff_t lock_offs; +u32 lock_len; + +stm_get_locked_range (nor, sr, &lock_offs, &lock_len); + +return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); +} + +/* +* Check if a region of the flash is (completely) locked. See stm_lock() for +* more info. +* +* Returns 1 if entire region is locked, 0 if any portion is unlocked, and +* negative on errors. +*/ +int stm_is_locked (struct spi_flash *nor,loff_t ofs,u32 len) +{ +int status; +u8 sr; + + status =spi_flash_cmd_read_status (nor, &sr); +if (status <0 ) +return status; + +return stm_is_locked_sr (nor, ofs, len, sr); +} + +/* +* Lock a region of the flash. Compatible with ST Micro and similar flash. +* Supports only the block protection bits BP{0,1,2} in the status register +* (SR). Does not support these features found in newer SR bitfields: +* - TB: top/bottom protect - only handle TB=0 (top protect) +* - SEC: sector/block protect - only handle SEC=0 (block protect) +* - CMP: complement protect - only support CMP=0 (range is not complemented) +* +* Sample table portion for 8MB flash (Winbond w25q64fw): +* +* SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion +* -------------------------------------------------------------------------- +* X | X | 0 | 0 | 0 | NONE | NONE +* 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 +* 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 +* 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 +* 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 +* 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 +* 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 +* X | X | 1 | 1 | 1 | 8 MB | ALL +* +* Returns negative on errors, 0 on success. +*/ +int stm_lock (struct spi_flash *nor,u32 ofs,u32 len) +{ +u8 status_old, status_new; +u8 mask =SR_BP2 |SR_BP1 |SR_BP0 ; +u8 shift =ffs (mask) -1 , pow, val; + +spi_flash_cmd_read_status (nor, &status_old); + +/* SPI NOR always locks to the end */ +if (ofs + len != nor->size) { +/* Does combined region extend to end? */ +if (!stm_is_locked_sr (nor, ofs + len, nor->size - ofs - len, + status_old)) +return -EINVAL ; + len = nor->size - ofs; + } + +/* +* Need smallest pow such that: +* +* 1 / (2^pow) <= (len / size) +* +* so (assuming power-of-2 size) we do: +* +* pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) +*/ + pow =ilog2 (nor->size) -ilog2 (len); + val = mask - (pow << shift); +if (val & ~mask) +return -EINVAL ; + +/* Don't "lock" with no region! */ +if (!(val & mask)) +return -EINVAL ; + + status_new = (status_old & ~mask) | val; + +/* Only modify protection if it will not unlock other areas */ +if ((status_new & mask) <= (status_old & mask)) +return -EINVAL ; + +spi_flash_cmd_write_status (nor, status_new); + +return 0 ; +} + +/* +* Unlock a region of the flash. See stm_lock() for more info +* +* Returns negative on errors, 0 on success. +*/ +int stm_unlock (struct spi_flash *nor,u32 ofs,u32 len) +{ +uint8_t status_old, status_new; +u8 mask =SR_BP2 |SR_BP1 |SR_BP0 ; +u8 shift =ffs (mask) -1 , pow, val; + +spi_flash_cmd_read_status (nor, &status_old); + +/* Cannot unlock; would unlock larger region than requested */ +if (stm_is_locked_sr (nor, status_old, ofs - nor->erase_size, + nor->erase_size)) +return -EINVAL ; +/* +* Need largest pow such that: +* +* 1 / (2^pow) >= (len / size) +* +* so (assuming power-of-2 size) we do: +* +* pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) +*/ + pow =ilog2 (nor->size) -order_base_2 (nor->size - (ofs + len)); +if (ofs + len == nor->size) { + val =0 ;/* fully unlocked */ + }else { + val = mask - (pow << shift); +/* Some power-of-two sizes are not supported */ +if (val & ~mask) +return -EINVAL ; + } +
drivers/mtd/spi/sf_ops.c int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, · line 748
Quoted 10 lines
drivers/mtd/spi/sf_ops.c +10
-0+ status_new = (status_old & ~mask) | val; + +/* Only modify protection if it will not lock other areas */ +if ((status_new & mask) >= (status_old & mask)) +return -EINVAL ; + +spi_flash_cmd_write_status (nor, status_new); + +return 0 ; +}
Removed this else part based on the function_ptr checking in spi_flash.
Quoted 19 lines
drivers/mtd/spi/sf_ops.c +16
-1+#else +int stm_is_locked (struct spi_flash *nor,loff_t ofs,u32 len) +{ +return 0 ; +} + +int stm_lock (struct spi_flash *nor,u32 ofs,u32 len) +{ +return 0 ; +} + +int stm_unlock (struct spi_flash *nor,u32 ofs,u32 len) +{ +return 0 ; +} +#endif /* CONFIG_SPI_FLASH_STMICRO */ --1.9.1
Quoted 4 lines
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
thanks!
Signature · 1 line
Jagan.
PATCH v7 4/4 spi: Add SPI NOR protection mechanism
In reply to Fabio EstevamFrom: Fabio Estevam <[email protected]>
Many SPI flashes have protection bits (BP2, BP1 and BP0) in the status register that can protect selected regions of the SPI NOR.
Take these bits into account when performing erase operations, making sure that the protected areas are skipped.
Tested on a mx6qsabresd:
=> sf probe
SF: Detected M25P32 with page size 256 Bytes, erase size 64 KiB, total 4 MiB => sf protect lock 0x3f0000 0x10000
=> sf erase 0x3f0000 0x10000
offset 0x3f0000 is protected and cannot be erased
SF: 65536 bytes @ 0x3f0000 Erased: ERROR
=> sf protect unlock 0x3f0000 0x10000
=> sf erase 0x3f0000 0x10000
SF: 65536 bytes @ 0x3f0000 Erased: OK
---
Changes since v6:
- Fixed some build issues reported by buildman
common/cmd_sf.c | 35 +++++++++++++++++++++++++++++++++++ drivers/mtd/spi/sf-uclass.c | 8 ++++++++ drivers/mtd/spi/sf_internal.h | 8 ++++++++ drivers/mtd/spi/sf_ops.c | 25 +++++++++++++++++++++++++ drivers/mtd/spi/sf_probe.c | 27 +++++++++++++++++++++++++++ include/spi_flash.h | 35 +++++++++++++++++++++++++++++++++++ 6 files changed, 138 insertions(+)
common/cmd_sf.c +35 -0
@@ -348,6 +348,37 @@ static int do_spi_flash_erase(int argc, char * const argv[])return ret ==0 ?0 :1 ; } +static int do_spi_protect (int argc,char *const argv[]) +{ +int ret =0 ; +loff_t start, len; +bool prot = false; + +if (argc !=4 ) +return -1 ; + +if (!str2off (argv[2 ], &start)) { +puts ("start sector is not a valid number\n" ); +return 1 ; + } + +if (!str2off (argv[3 ], &len)) { +puts ("len is not a valid number\n" ); +return 1 ; + } + +if (strcmp (argv[1 ],"lock" ) ==0 ) + prot = true; +else if (strcmp (argv[1 ],"unlock" ) ==0 ) + prot = false; +else +return -1 ;/* Unknown parameter */ + + ret =spi_flash_protect (flash, start, len, prot); + +return ret ==0 ?0 :1 ; +} +#ifdef CONFIG_CMD_SF_TEST enum { STAGE_ERASE,
@@ -540,6 +571,8 @@ static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, ret =do_spi_flash_read_write (argc, argv); else if (strcmp(cmd, "erase") == 0) ret =do_spi_flash_erase (argc, argv); + else if (strcmp(cmd, "protect") == 0) + ret =do_spi_protect (argc, argv);#ifdef CONFIG_CMD_SF_TEST else if (!strcmp(cmd, "test")) ret =do_spi_flash_test (argc, argv);
@@ -579,5 +612,7 @@ U_BOOT_CMD("sf update addr offset|partition len - erase and write `len' bytes from memory\n" " at `addr' to flash at `offset'\n" " or to start of mtd `partition'\n" +"sf protect lock/unlock sector len - protect/unprotect 'len' bytes starting\n" +" at address 'sector'\n" SF_TEST_HELP );
drivers/mtd/spi/sf-uclass.c +8 -0
@@ -27,6 +27,14 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len)return sf_get_ops (dev)->erase (dev, offset, len); } +int spi_flash_protect_dm (struct udevice *dev,u32 offset,size_t len,bool prot) +{ +if (prot) +return sf_get_ops (dev)->lock (dev, offset, len); +else +return sf_get_ops (dev)->unlock (dev, offset, len); +} +/* * TODO(sjg at chromium.org): This is an old-style function. We should remove * it when all SPI flash drivers use dm
drivers/mtd/spi/sf_internal.h +8 -0
@@ -168,6 +168,10 @@ int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs);/* Program the status register */ int spi_flash_cmd_write_status (struct spi_flash *flash,u8 ws); +int stm_is_locked (struct spi_flash *nor,loff_t ofs,u32 len); +int stm_lock (struct spi_flash *nor,u32 ofs,u32 len); +int stm_unlock (struct spi_flash *nor,u32 ofs,u32 len); +/* Read the config register */ int spi_flash_cmd_read_config (struct spi_flash *flash,u8 *rc);
@@ -222,6 +226,10 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,int spi_flash_cmd_read_ops (struct spi_flash *flash,u32 offset,size_t len,void *data); +int spi_flash_cmd_lock_ops (struct spi_flash *flash,u32 offset,size_t len); +int spi_flash_cmd_unlock_ops (struct spi_flash *flash,u32 offset,size_t len); +int spi_flash_cmd_is_locked_ops (struct spi_flash *flash,u32 offset,size_t len); +#ifdef CONFIG_SPI_FLASH_MTD int spi_flash_mtd_register (struct spi_flash *flash);void spi_flash_mtd_unregister (void );
drivers/mtd/spi/sf_ops.c +25 -0
@@ -277,6 +277,11 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)return -1 ; } +if (flash->is_locked (flash, offset, len) >0 ) { +printf ("offset 0x%x is protected and cannot be erased\n" , offset); +return -EINVAL ; + } + cmd[0 ] = flash->erase_cmd;while (len) { erase_addr = offset;
@@ -319,6 +324,11 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, page_size = flash->page_size; +if (flash->is_locked (flash, offset, len) >0 ) { +printf ("offset 0x%x is protected and cannot be written\n" , offset); +return -EINVAL ; + } + cmd[0 ] = flash->write_cmd;for (actual =0 ; actual < len; actual += chunk_len) { write_addr = offset;
@@ -357,6 +367,21 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,return ret; } +int spi_flash_cmd_lock_ops (struct spi_flash *flash,u32 offset,size_t len) +{ +return stm_lock (flash, offset, len); +} + +int spi_flash_cmd_unlock_ops (struct spi_flash *flash,u32 offset,size_t len) +{ +return stm_unlock (flash, offset, len); +} + +int spi_flash_cmd_is_locked_ops (struct spi_flash *flash,u32 offset,size_t len) +{ +return stm_is_locked (flash, offset, len); +} +int spi_flash_read_common (struct spi_flash *flash,const u8 *cmd,size_t cmd_len,void *data,size_t data_len) {
drivers/mtd/spi/sf_probe.c +27 -0
@@ -149,6 +149,9 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,#endif flash->erase = spi_flash_cmd_erase_ops; flash->read = spi_flash_cmd_read_ops; + flash->lock = spi_flash_cmd_lock_ops; + flash->unlock = spi_flash_cmd_unlock_ops; + flash->is_locked = spi_flash_cmd_is_locked_ops;#endif /* Compute the flash size */
@@ -469,6 +472,27 @@ int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)return spi_flash_cmd_erase_ops (flash, offset, len); } +int spi_flash_std_lock (struct udevice *dev,u32 offset,size_t len) +{ +struct spi_flash *flash =dev_get_uclass_priv (dev); + +return spi_flash_cmd_lock_ops (flash, offset, len); +} + +int spi_flash_std_unlock (struct udevice *dev,u32 offset,size_t len) +{ +struct spi_flash *flash =dev_get_uclass_priv (dev); + +return spi_flash_cmd_unlock_ops (flash, offset, len); +} + +int spi_flash_std_is_locked (struct udevice *dev,u32 offset,size_t len) +{ +struct spi_flash *flash =dev_get_uclass_priv (dev); + +return spi_flash_cmd_is_locked_ops (flash, offset, len); +} +int spi_flash_std_probe (struct udevice *dev) {struct spi_slave *slave =dev_get_parentdata (dev);
@@ -485,6 +509,9 @@ static const struct dm_spi_flash_ops spi_flash_std_ops = { .read = spi_flash_std_read, .write = spi_flash_std_write, .erase = spi_flash_std_erase, + .lock = spi_flash_std_lock, + .unlock = spi_flash_std_unlock, + .is_locked = spi_flash_std_is_locked, };static const struct udevice_id spi_flash_std_ids[] = {
include/spi_flash.h +35 -0
@@ -105,6 +105,9 @@ struct spi_flash {int (*write)(struct spi_flash *flash,u32 offset,size_t len,const void *buf);int (*erase)(struct spi_flash *flash,u32 offset,size_t len); +int (*lock)(struct spi_flash *flash,u32 offset,size_t len); +int (*unlock)(struct spi_flash *flash,u32 offset,size_t len); +int (*is_locked)(struct spi_flash *flash,u32 offset,size_t len);#endif };
@@ -113,6 +116,9 @@ struct dm_spi_flash_ops {int (*write)(struct udevice *dev,u32 offset,size_t len,const void *buf);int (*erase)(struct udevice *dev,u32 offset,size_t len); +int (*lock)(struct udevice *dev,u32 offset,size_t len); +int (*unlock)(struct udevice *dev,u32 offset,size_t len); +int (*is_locked)(struct udevice *dev,u32 offset,size_t len); };/* Access the serial operations for a device */
@@ -154,6 +160,20 @@ int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len,*/ int spi_flash_erase_dm (struct udevice *dev,u32 offset,size_t len); +/** +* spi_flash_protect_dm() - Protect/unprotect blocks of the SPI flash +* +* Note that @len must be a muiltiple of the flash sector size. +* +* @dev: SPI flash device +* @offset: Offset into device in bytes to start erasing +* @len: Number of bytes to erase +* @prot: True: lock the block or False: unlock the block +* @return 0 if OK, -ve on error +*/ +int spi_flash_protect_dm (struct udevice *dev,u32 offset,size_t len, +bool prot); +int spi_flash_probe_bus_cs (unsigned int busnum,unsigned int cs,unsigned int max_hz,unsigned int spi_mode,struct udevice **devp);
@@ -185,6 +205,12 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,return spi_flash_erase_dm (flash->dev, offset, len); } +static inline int spi_flash_protect (struct spi_flash *flash,loff_t ofs, +u32 len,bool prot) +{ +return spi_flash_protect_dm (flash->dev, ofs, len, prot); +} +struct sandbox_state ; int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs,
@@ -227,6 +253,15 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, {return flash->erase (flash, offset, len); } + +static inline int spi_flash_protect (struct spi_flash *flash,u32 ofs,u32 len, +bool prot) +{ +if (prot) +return flash->lock (flash, ofs, len); +else +return flash->unlock (flash, ofs, len); +}#endif void spi_boot (void )__noreturn ;
Signature · 1 line
1.9.1
PATCH v7 4/4 spi: Add SPI NOR protection mechanism
Quoted 10 lines · Fabio Estevam
From: Fabio Estevam <[email protected]>
Many SPI flashes have protection bits (BP2, BP1 and BP0) in the status register that can protect selected regions of the SPI NOR.
Take these bits into account when performing erase operations, making sure that the protected areas are skipped.
Tested on a mx6qsabresd:
Quoted 9 lines
=> sf probe
SF: Detected M25P32 with page size 256 Bytes, erase size 64 KiB, total 4 MiB => sf protect lock0x3f00000x10000
=> sf erase0x3f00000x10000
offset0x3f0000is protected and cannot be erased
SF: 65536 bytes @0x3f0000Erased: ERROR
=> sf protect unlock0x3f00000x10000
=> sf erase0x3f00000x10000
SF: 65536 bytes @0x3f0000Erased: OK
Build error with DM_SPI_FLASH:
CC drivers/mtd/spi/sf_ops.odrivers/mtd/spi/sf_ops.c: In function 'spi_flash_cmd_erase_ops':drivers/mtd/spi/sf_ops.c:280:11: error: 'struct spi_flash' has no member named 'is_locked'drivers/mtd/spi/sf_ops.c: In function 'spi_flash_cmd_write_ops':drivers/mtd/spi/sf_ops.c:327:11: error: 'struct spi_flash' has no member named 'is_locked'
make[1]: *** [drivers/mtd/spi/sf_ops.o] Error 1
make: *** [drivers/mtd/spi] Error 2
Quoted 279 lines
Signed-off-by Fabio Estevam <[email protected]>---
Changes since v6:
- Fixed some build issues reported by buildmancommon/cmd_sf.c | 35 +++++++++++++++++++++++++++++++++++ drivers/mtd/spi/sf-uclass.c | 8 ++++++++ drivers/mtd/spi/sf_internal.h | 8 ++++++++ drivers/mtd/spi/sf_ops.c | 25 +++++++++++++++++++++++++ drivers/mtd/spi/sf_probe.c | 27 +++++++++++++++++++++++++++ include/spi_flash.h | 35 +++++++++++++++++++++++++++++++++++ 6 files changed, 138 insertions(+)common/cmd_sf.c +35
-0@@ -348,6 +348,37 @@ static int do_spi_flash_erase(int argc, char * const argv[])return ret ==0 ?0 :1 ; } +static int do_spi_protect (int argc,char *const argv[]) +{ +int ret =0 ; +loff_t start, len; +bool prot = false; + +if (argc !=4 ) +return -1 ; + +if (!str2off (argv[2 ], &start)) { +puts ("start sector is not a valid number\n" ); +return 1 ; + } + +if (!str2off (argv[3 ], &len)) { +puts ("len is not a valid number\n" ); +return 1 ; + } + +if (strcmp (argv[1 ],"lock" ) ==0 ) + prot = true; +else if (strcmp (argv[1 ],"unlock" ) ==0 ) + prot = false; +else +return -1 ;/* Unknown parameter */ + + ret =spi_flash_protect (flash, start, len, prot); + +return ret ==0 ?0 :1 ; +} +#ifdef CONFIG_CMD_SF_TEST enum { STAGE_ERASE,@@ -540,6 +571,8 @@ static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, ret =do_spi_flash_read_write (argc, argv); else if (strcmp(cmd, "erase") == 0) ret =do_spi_flash_erase (argc, argv); + else if (strcmp(cmd, "protect") == 0) + ret =do_spi_protect (argc, argv);#ifdef CONFIG_CMD_SF_TEST else if (!strcmp(cmd, "test")) ret =do_spi_flash_test (argc, argv);@@ -579,5 +612,7 @@ U_BOOT_CMD("sf update addr offset|partition len - erase and write `len' bytes from memory\n" " at `addr' to flash at `offset'\n" " or to start of mtd `partition'\n" +"sf protect lock/unlock sector len - protect/unprotect 'len' bytes starting\n" +" at address 'sector'\n" SF_TEST_HELP );drivers/mtd/spi/sf-uclass.c +8
-0@@ -27,6 +27,14 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len)return sf_get_ops (dev)->erase (dev, offset, len); } +int spi_flash_protect_dm (struct udevice *dev,u32 offset,size_t len,bool prot) +{ +if (prot) +return sf_get_ops (dev)->lock (dev, offset, len); +else +return sf_get_ops (dev)->unlock (dev, offset, len); +} +/* * TODO(sjg at chromium.org): This is an old-style function. We should remove * it when all SPI flash drivers use dm drivers/mtd/spi/sf_internal.h +8
-0@@ -168,6 +168,10 @@ int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs);/* Program the status register */ int spi_flash_cmd_write_status (struct spi_flash *flash,u8 ws); +int stm_is_locked (struct spi_flash *nor,loff_t ofs,u32 len); +int stm_lock (struct spi_flash *nor,u32 ofs,u32 len); +int stm_unlock (struct spi_flash *nor,u32 ofs,u32 len); +/* Read the config register */ int spi_flash_cmd_read_config (struct spi_flash *flash,u8 *rc);@@ -222,6 +226,10 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,int spi_flash_cmd_read_ops (struct spi_flash *flash,u32 offset,size_t len,void *data); +int spi_flash_cmd_lock_ops (struct spi_flash *flash,u32 offset,size_t len); +int spi_flash_cmd_unlock_ops (struct spi_flash *flash,u32 offset,size_t len); +int spi_flash_cmd_is_locked_ops (struct spi_flash *flash,u32 offset,size_t len); +#ifdef CONFIG_SPI_FLASH_MTD int spi_flash_mtd_register (struct spi_flash *flash);void spi_flash_mtd_unregister (void );drivers/mtd/spi/sf_ops.c +25
-0@@ -277,6 +277,11 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)return -1 ; } +if (flash->is_locked (flash, offset, len) >0 ) { +printf ("offset 0x%x is protected and cannot be erased\n" , offset); +return -EINVAL ; + } + cmd[0 ] = flash->erase_cmd;while (len) { erase_addr = offset;@@ -319,6 +324,11 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, page_size = flash->page_size; +if (flash->is_locked (flash, offset, len) >0 ) { +printf ("offset 0x%x is protected and cannot be written\n" , offset); +return -EINVAL ; + } + cmd[0 ] = flash->write_cmd;for (actual =0 ; actual < len; actual += chunk_len) { write_addr = offset;@@ -357,6 +367,21 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,return ret; } +int spi_flash_cmd_lock_ops (struct spi_flash *flash,u32 offset,size_t len) +{ +return stm_lock (flash, offset, len); +} + +int spi_flash_cmd_unlock_ops (struct spi_flash *flash,u32 offset,size_t len) +{ +return stm_unlock (flash, offset, len); +} + +int spi_flash_cmd_is_locked_ops (struct spi_flash *flash,u32 offset,size_t len) +{ +return stm_is_locked (flash, offset, len); +} +int spi_flash_read_common (struct spi_flash *flash,const u8 *cmd,size_t cmd_len,void *data,size_t data_len) {drivers/mtd/spi/sf_probe.c +27
-0@@ -149,6 +149,9 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,#endif flash->erase = spi_flash_cmd_erase_ops; flash->read = spi_flash_cmd_read_ops; + flash->lock = spi_flash_cmd_lock_ops; + flash->unlock = spi_flash_cmd_unlock_ops; + flash->is_locked = spi_flash_cmd_is_locked_ops;#endif /* Compute the flash size */ @@ -469,6 +472,27 @@ int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)return spi_flash_cmd_erase_ops (flash, offset, len); } +int spi_flash_std_lock (struct udevice *dev,u32 offset,size_t len) +{ +struct spi_flash *flash =dev_get_uclass_priv (dev); + +return spi_flash_cmd_lock_ops (flash, offset, len); +} + +int spi_flash_std_unlock (struct udevice *dev,u32 offset,size_t len) +{ +struct spi_flash *flash =dev_get_uclass_priv (dev); + +return spi_flash_cmd_unlock_ops (flash, offset, len); +} + +int spi_flash_std_is_locked (struct udevice *dev,u32 offset,size_t len) +{ +struct spi_flash *flash =dev_get_uclass_priv (dev); + +return spi_flash_cmd_is_locked_ops (flash, offset, len); +} +int spi_flash_std_probe (struct udevice *dev) {struct spi_slave *slave =dev_get_parentdata (dev);@@ -485,6 +509,9 @@ static const struct dm_spi_flash_ops spi_flash_std_ops = { .read = spi_flash_std_read, .write = spi_flash_std_write, .erase = spi_flash_std_erase, + .lock = spi_flash_std_lock, + .unlock = spi_flash_std_unlock, + .is_locked = spi_flash_std_is_locked, };static const struct udevice_id spi_flash_std_ids[] = {include/spi_flash.h +26
-0@@ -105,6 +105,9 @@ struct spi_flash {int (*write)(struct spi_flash *flash,u32 offset,size_t len,const void *buf);int (*erase)(struct spi_flash *flash,u32 offset,size_t len); +int (*lock)(struct spi_flash *flash,u32 offset,size_t len); +int (*unlock)(struct spi_flash *flash,u32 offset,size_t len); +int (*is_locked)(struct spi_flash *flash,u32 offset,size_t len);#endif };@@ -113,6 +116,9 @@ struct dm_spi_flash_ops {int (*write)(struct udevice *dev,u32 offset,size_t len,const void *buf);int (*erase)(struct udevice *dev,u32 offset,size_t len); +int (*lock)(struct udevice *dev,u32 offset,size_t len); +int (*unlock)(struct udevice *dev,u32 offset,size_t len); +int (*is_locked)(struct udevice *dev,u32 offset,size_t len); };/* Access the serial operations for a device */ @@ -154,6 +160,20 @@ int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len,*/ int spi_flash_erase_dm (struct udevice *dev,u32 offset,size_t len); +/** +* spi_flash_protect_dm() - Protect/unprotect blocks of the SPI flash +* +* Note that @len must be a muiltiple of the flash sector size. +* +* @dev: SPI flash device +* @offset: Offset into device in bytes to start erasing +* @len: Number of bytes to erase +* @prot: True: lock the block or False: unlock the block +* @return 0 if OK, -ve on error +*/ +int spi_flash_protect_dm (struct udevice *dev,u32 offset,size_t len, +bool prot); +int spi_flash_probe_bus_cs (unsigned int busnum,unsigned int cs,unsigned int max_hz,unsigned int spi_mode,struct udevice **devp);@@ -185,6 +205,12 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,return spi_flash_erase_dm (flash->dev, offset, len); } +static inline int spi_flash_protect (struct spi_flash *flash,loff_t ofs, +u32 len,bool prot) +{ +return spi_flash_protect_dm (flash->dev, ofs, len, prot); +} +struct sandbox_state ; int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs,
include/spi_flash.h static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, · line 259
Quoted 7 lines
include/spi_flash.h +4
-0@@ -227,6 +253,15 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, {return flash->erase (flash, offset, len); } + +static inline int spi_flash_protect (struct spi_flash *flash,u32 ofs,u32 len, +bool prot) +{
Add something like this-
if (!spi_flash->lock)
return -EOPNOTSUPP;
Same for dm case as well.
Quoted 15 lines
include/spi_flash.h +5
-1+if (prot) +return flash->lock (flash, ofs, len); +else + return flash->unlock(flash, ofs, len); +}#endif void spi_boot (void )__noreturn ; --1.9.1
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
Signature · 1 line
Jagan | openedev.
PATCH v7 4/4 spi: Add SPI NOR protection mechanism
Quoted 202 lines · Jagan Teki
Quoted 10 lines · Fabio Estevam
From: Fabio Estevam <[email protected]>
Many SPI flashes have protection bits (BP2, BP1 and BP0) in the status register that can protect selected regions of the SPI NOR.
Take these bits into account when performing erase operations, making sure that the protected areas are skipped.
Tested on a mx6qsabresd:
Quoted 9 lines
=> sf probe
SF: Detected M25P32 with page size 256 Bytes, erase size 64 KiB, total 4 MiB => sf protect lock0x3f00000x10000
=> sf erase0x3f00000x10000
offset0x3f0000is protected and cannot be erased
SF: 65536 bytes @0x3f0000Erased: ERROR
=> sf protect unlock0x3f00000x10000
=> sf erase0x3f00000x10000
SF: 65536 bytes @0x3f0000Erased: OKBuild error with
DM_SPI_FLASH:CC
drivers/mtd/spi/sf_ops.odrivers/mtd/spi/sf_ops.c: In function 'spi_flash_cmd_erase_ops':drivers/mtd/spi/sf_ops.c:280:11: error: 'structspi_flash' has no member named 'is_locked'drivers/mtd/spi/sf_ops.c: In function 'spi_flash_cmd_write_ops':drivers/mtd/spi/sf_ops.c:327:11: error: 'structspi_flash' has no member named 'is_locked'
make[1]: *** [drivers/mtd/spi/sf_ops.o] Error 1
make: *** [drivers/mtd/spi] Error 2Quoted 168 lines
Signed-off-by Fabio Estevam <[email protected]>---
Changes since v6:
- Fixed some build issues reported by buildmancommon/cmd_sf.c | 35 +++++++++++++++++++++++++++++++++++ drivers/mtd/spi/sf-uclass.c | 8 ++++++++ drivers/mtd/spi/sf_internal.h | 8 ++++++++ drivers/mtd/spi/sf_ops.c | 25 +++++++++++++++++++++++++ drivers/mtd/spi/sf_probe.c | 27 +++++++++++++++++++++++++++ include/spi_flash.h | 35 +++++++++++++++++++++++++++++++++++ 6 files changed, 138 insertions(+)common/cmd_sf.c +35
-0@@ -348,6 +348,37 @@ static int do_spi_flash_erase(int argc, char * const argv[])return ret ==0 ?0 :1 ; } +static int do_spi_protect (int argc,char *const argv[]) +{ +int ret =0 ; +loff_t start, len; +bool prot = false; + +if (argc !=4 ) +return -1 ; + +if (!str2off (argv[2 ], &start)) { +puts ("start sector is not a valid number\n" ); +return 1 ; + } + +if (!str2off (argv[3 ], &len)) { +puts ("len is not a valid number\n" ); +return 1 ; + } + +if (strcmp (argv[1 ],"lock" ) ==0 ) + prot = true; +else if (strcmp (argv[1 ],"unlock" ) ==0 ) + prot = false; +else +return -1 ;/* Unknown parameter */ + + ret =spi_flash_protect (flash, start, len, prot); + +return ret ==0 ?0 :1 ; +} +#ifdef CONFIG_CMD_SF_TEST enum { STAGE_ERASE,@@ -540,6 +571,8 @@ static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, ret =do_spi_flash_read_write (argc, argv); else if (strcmp(cmd, "erase") == 0) ret =do_spi_flash_erase (argc, argv); + else if (strcmp(cmd, "protect") == 0) + ret =do_spi_protect (argc, argv);#ifdef CONFIG_CMD_SF_TEST else if (!strcmp(cmd, "test")) ret =do_spi_flash_test (argc, argv);@@ -579,5 +612,7 @@ U_BOOT_CMD("sf update addr offset|partition len - erase and write `len' bytes from memory\n" " at `addr' to flash at `offset'\n" " or to start of mtd `partition'\n" +"sf protect lock/unlock sector len - protect/unprotect 'len' bytes starting\n" +" at address 'sector'\n" SF_TEST_HELP );drivers/mtd/spi/sf-uclass.c +8
-0@@ -27,6 +27,14 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len)return sf_get_ops (dev)->erase (dev, offset, len); } +int spi_flash_protect_dm (struct udevice *dev,u32 offset,size_t len,bool prot) +{ +if (prot) +return sf_get_ops (dev)->lock (dev, offset, len); +else +return sf_get_ops (dev)->unlock (dev, offset, len); +} +/* * TODO(sjg at chromium.org): This is an old-style function. We should remove * it when all SPI flash drivers use dm drivers/mtd/spi/sf_internal.h +8
-0@@ -168,6 +168,10 @@ int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs);/* Program the status register */ int spi_flash_cmd_write_status (struct spi_flash *flash,u8 ws); +int stm_is_locked (struct spi_flash *nor,loff_t ofs,u32 len); +int stm_lock (struct spi_flash *nor,u32 ofs,u32 len); +int stm_unlock (struct spi_flash *nor,u32 ofs,u32 len); +/* Read the config register */ int spi_flash_cmd_read_config (struct spi_flash *flash,u8 *rc);@@ -222,6 +226,10 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,int spi_flash_cmd_read_ops (struct spi_flash *flash,u32 offset,size_t len,void *data); +int spi_flash_cmd_lock_ops (struct spi_flash *flash,u32 offset,size_t len); +int spi_flash_cmd_unlock_ops (struct spi_flash *flash,u32 offset,size_t len); +int spi_flash_cmd_is_locked_ops (struct spi_flash *flash,u32 offset,size_t len); +#ifdef CONFIG_SPI_FLASH_MTD int spi_flash_mtd_register (struct spi_flash *flash);void spi_flash_mtd_unregister (void );drivers/mtd/spi/sf_ops.c +25
-0@@ -277,6 +277,11 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)return -1 ; } +if (flash->is_locked (flash, offset, len) >0 ) { +printf ("offset 0x%x is protected and cannot be erased\n" , offset); +return -EINVAL ; + } + cmd[0 ] = flash->erase_cmd;while (len) { erase_addr = offset;@@ -319,6 +324,11 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, page_size = flash->page_size; +if (flash->is_locked (flash, offset, len) >0 ) { +printf ("offset 0x%x is protected and cannot be written\n" , offset); +return -EINVAL ; + } + cmd[0 ] = flash->write_cmd;for (actual =0 ; actual < len; actual += chunk_len) { write_addr = offset;@@ -357,6 +367,21 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,return ret; } +int spi_flash_cmd_lock_ops (struct spi_flash *flash,u32 offset,size_t len) +{ +return stm_lock (flash, offset, len); +} + +int spi_flash_cmd_unlock_ops (struct spi_flash *flash,u32 offset,size_t len) +{ +return stm_unlock (flash, offset, len); +} + +int spi_flash_cmd_is_locked_ops (struct spi_flash *flash,u32 offset,size_t len) +{ +return stm_is_locked (flash, offset, len); +} +int spi_flash_read_common (struct spi_flash *flash,const u8 *cmd,size_t cmd_len,void *data,size_t data_len) {
Quoted 8 lines
drivers/mtd/spi/sf_probe.c static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, · line 151
Quoted 8 lines
drivers/mtd/spi/sf_probe.c +0
-0@@ -149,6 +149,9 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,#endif flash->erase = spi_flash_cmd_erase_ops; flash->read = spi_flash_cmd_read_ops;
Assign these hooks only for STMICRO, do the same for dm-spi-flash as well.
Quoted 138 lines
Quoted 103 lines
drivers/mtd/spi/sf_probe.c +27
-0+ flash->lock = spi_flash_cmd_lock_ops; + flash->unlock = spi_flash_cmd_unlock_ops; + flash->is_locked = spi_flash_cmd_is_locked_ops;#endif /* Compute the flash size */ @@ -469,6 +472,27 @@ int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)return spi_flash_cmd_erase_ops (flash, offset, len); } +int spi_flash_std_lock (struct udevice *dev,u32 offset,size_t len) +{ +struct spi_flash *flash =dev_get_uclass_priv (dev); + +return spi_flash_cmd_lock_ops (flash, offset, len); +} + +int spi_flash_std_unlock (struct udevice *dev,u32 offset,size_t len) +{ +struct spi_flash *flash =dev_get_uclass_priv (dev); + +return spi_flash_cmd_unlock_ops (flash, offset, len); +} + +int spi_flash_std_is_locked (struct udevice *dev,u32 offset,size_t len) +{ +struct spi_flash *flash =dev_get_uclass_priv (dev); + +return spi_flash_cmd_is_locked_ops (flash, offset, len); +} +int spi_flash_std_probe (struct udevice *dev) {struct spi_slave *slave =dev_get_parentdata (dev);@@ -485,6 +509,9 @@ static const struct dm_spi_flash_ops spi_flash_std_ops = { .read = spi_flash_std_read, .write = spi_flash_std_write, .erase = spi_flash_std_erase, + .lock = spi_flash_std_lock, + .unlock = spi_flash_std_unlock, + .is_locked = spi_flash_std_is_locked, };static const struct udevice_id spi_flash_std_ids[] = {include/spi_flash.h +26
-0@@ -105,6 +105,9 @@ struct spi_flash {int (*write)(struct spi_flash *flash,u32 offset,size_t len,const void *buf);int (*erase)(struct spi_flash *flash,u32 offset,size_t len); +int (*lock)(struct spi_flash *flash,u32 offset,size_t len); +int (*unlock)(struct spi_flash *flash,u32 offset,size_t len); +int (*is_locked)(struct spi_flash *flash,u32 offset,size_t len);#endif };@@ -113,6 +116,9 @@ struct dm_spi_flash_ops {int (*write)(struct udevice *dev,u32 offset,size_t len,const void *buf);int (*erase)(struct udevice *dev,u32 offset,size_t len); +int (*lock)(struct udevice *dev,u32 offset,size_t len); +int (*unlock)(struct udevice *dev,u32 offset,size_t len); +int (*is_locked)(struct udevice *dev,u32 offset,size_t len); };/* Access the serial operations for a device */ @@ -154,6 +160,20 @@ int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len,*/ int spi_flash_erase_dm (struct udevice *dev,u32 offset,size_t len); +/** +* spi_flash_protect_dm() - Protect/unprotect blocks of the SPI flash +* +* Note that @len must be a muiltiple of the flash sector size. +* +* @dev: SPI flash device +* @offset: Offset into device in bytes to start erasing +* @len: Number of bytes to erase +* @prot: True: lock the block or False: unlock the block +* @return 0 if OK, -ve on error +*/ +int spi_flash_protect_dm (struct udevice *dev,u32 offset,size_t len, +bool prot); +int spi_flash_probe_bus_cs (unsigned int busnum,unsigned int cs,unsigned int max_hz,unsigned int spi_mode,struct udevice **devp);@@ -185,6 +205,12 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,return spi_flash_erase_dm (flash->dev, offset, len); } +static inline int spi_flash_protect (struct spi_flash *flash,loff_t ofs, +u32 len,bool prot) +{ +return spi_flash_protect_dm (flash->dev, ofs, len, prot); +} +struct sandbox_state ; int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs,include/spi_flash.h static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, · line 259
Quoted 7 lines
include/spi_flash.h +4
-0@@ -227,6 +253,15 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset, {return flash->erase (flash, offset, len); } + +static inline int spi_flash_protect (struct spi_flash *flash,u32 ofs,u32 len, +bool prot) +{Add something like this-
if (!spi_flash->lock)
return -EOPNOTSUPP;Same for dm case as well.
Quoted 11 lines
include/spi_flash.h +5
-1+if (prot) +return flash->lock (flash, ofs, len); +else + return flash->unlock(flash, ofs, len); +}#endif void spi_boot (void )__noreturn ; --1.9.1
Quoted 4 lines
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot--
Jagan | openedev.
Signature · 1 line
Jagan | openedev.