bitops: Add support for order_base_2()
Subsystems (3)
PATCH 1/2 bitops: Add support for order_base_2()
From: Fabio Estevam <[email protected]>
Add support for the order_base_2() macro from the Linux kernel.
This is useful for the SPI NOR unlock function.
--- arch/arm/include/asm/bitops.h | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)
arch/arm/include/asm/bitops.h +56 -0
@@ -108,6 +108,62 @@ static inline int __ilog2(unsigned int x)return generic_fls (x) -1 ; } +static inline int fls64 (__u64 x) +{ +if (x ==0 ) +return 0 ; +return generic_fls (x) +1 ; +} + +static inline unsigned fls_long (unsigned long l) +{ +if (sizeof (l) ==4 ) +return generic_fls (l); +return fls64 (l); +} + +/* +* round up to nearest power of two +*/ +static inline __attribute__((const)) +unsigned long __roundup_pow_of_two (unsigned long n) +{ +return 1UL <<fls_long (n -1 ); +} + +/** +* roundup_pow_of_two - round the given value up to nearest power of two +* @n - parameter +* +* round the given value up to the nearest power of two +* - the result is undefined when n == 0 +* - this can be used to initialise global variables from constant data +*/ +#define roundup_pow_of_two (n) \ +( \ + __builtin_constant_p(n) ? ( \ + (n == 1) ? 1 : \ + (1UL << (__ilog2((n) - 1) + 1)) \ + ) : \ + __roundup_pow_of_two(n) \ +) + +/** +* order_base_2 - calculate the (rounded up) base 2 order of the argument +* @n: parameter +* +* The first few values calculated by this routine: +* ob2(0) = 0 +* ob2(1) = 0 +* ob2(2) = 1 +* ob2(3) = 2 +* ob2(4) = 2 +* ob2(5) = 3 +* ... and so on. +*/ + +#define order_base_2 (n) __ilog2(roundup_pow_of_two(n)) +/* * ffz = Find First Zero in word. Undefined if no zero exists, * so code should check against ~0UL first..
Signature · 1 line
1.9.1
PATCH 2/2 spi: Add SPI NOR protection mechanism
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.
Introduce the CONFIG_SF_STM_PROTECT option that can be selected by systems that want to protect regions of SPI NOR flash using the same programming model as in the ST Micro SPI NOR flashes, like for example the M25P32.
Based on the implementation from Brian Norris <[email protected]> for the Linux kernel:
https://patchwork.ozlabs.org/patch/513041/
Tested on a mx6qsabresd:
=> sf probe
SF: Detected M25P32 with page size 256 Bytes, erase size 64 KiB, total 4 MiB => sf protect on 0x3f0000 0x10000
=> sf erase 0x3f0000 0x10000
offset 0x3f0000 is protected and cannot be erased
SF: 65536 bytes @ 0x3f0000 Erased: ERROR
=> sf protect off 0x3f0000 0x10000
=> sf erase 0x3f0000 0x10000
SF: 65536 bytes @ 0x3f0000 Erased: OK
---
README | 12 +++ common/cmd_sf.c | 30 +++++++ drivers/mtd/spi/sf_internal.h | 6 -- drivers/mtd/spi/sf_ops.c | 188 ++++++++++++++++++++++++++++++++++++++++++ include/spi_flash.h | 25 +++++- 5 files changed, 253 insertions(+), 8 deletions(-)
README +12 -0
@@ -3068,6 +3068,18 @@ CBFS (Coreboot Filesystem) support memories can be connected with a given cs line. Currently Xilinx Zynq qspi supports these type of connections. + CONFIG_SF_STM_PROTECT + + Enable the built-in protection mechanism provided by the + BP2, BP1 and BP0 bits from the status register present + on ST-Micro flashes such as M25P32. Please refer to the + M25P32 datasheet to understand how to program these bits + in order to protect a selected region of the SPI NOR flash. + This same bit protection programming model applies to SPI + NOR flashes from other manufacturers such as: + - Micron M25P32 + - SST SST25V32B + - SystemACE Support: CONFIG_SYSTEMACE
common/cmd_sf.c +30 -0
@@ -348,6 +348,28 @@ static int do_spi_flash_erase(int argc, char * const argv[])return ret ==0 ?0 :1 ; } +#ifdef CONFIG_SF_STM_PROTECT +static int do_spi_protect (int argc,char *const argv[]) +{ +int start, len, ret =0 ; + +if (argc !=4 ) +return -1 ; + + start =simple_strtoull (argv[2 ],NULL ,16 ); + len =simple_strtoull (argv[3 ],NULL ,16 ); + +if (strcmp (argv[1 ],"on" ) ==0 ) + ret =stm_lock (flash, start, len); +else if (strcmp (argv[1 ],"off" ) ==0 ) + ret =stm_unlock (flash, start, len); +else +return -1 ;/* Unknown parameter */ + +return ret ==0 ?0 :1 ; +} +#endif +#ifdef CONFIG_CMD_SF_TEST enum { STAGE_ERASE,
@@ -540,6 +562,10 @@ 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); +#ifdef CONFIG_SF_STM_PROTECT + else if (strcmp(cmd, "protect") == 0) + ret =do_spi_protect (argc, argv); +#endif #ifdef CONFIG_CMD_SF_TEST else if (!strcmp(cmd, "test")) ret =do_spi_flash_test (argc, argv);
@@ -579,5 +605,9 @@ 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" +#ifdef CONFIG_SF_STM_PROTECT +"sf protect on/off sector len - protect/unprotect 'len' bytes starting\n" +" at address 'sector'\n" +#endif SF_TEST_HELP );
drivers/mtd/spi/sf_internal.h +0 -6
@@ -162,12 +162,6 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,/* Flash erase(sectors) operation, support all possible erase commands */ int spi_flash_cmd_erase_ops (struct spi_flash *flash,u32 offset,size_t len); -/* Read the status register */ -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); -/* Read the config register */ int spi_flash_cmd_read_config (struct spi_flash *flash,u8 *rc);
drivers/mtd/spi/sf_ops.c +188 -0
191 lines not on this page · raw message
include/spi_flash.h +23 -2
@@ -115,6 +115,17 @@ struct dm_spi_flash_ops {int (*erase)(struct udevice *dev,u32 offset,size_t len); }; + +/* Read the status register */ +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); +/* Access the serial operations for a device */ #define sf_get_ops (dev) ((struct dm_spi_flash_ops *)(dev)->driver->ops)
@@ -219,13 +230,23 @@ static inline int spi_flash_read(struct spi_flash *flash, u32 offset,static inline int spi_flash_write (struct spi_flash *flash,u32 offset,size_t len,const void *buf) { -return flash->write (flash, offset, len, buf); +if (stm_is_locked (flash, offset, len) >0 ) { +printf ("offset 0x%x is protected and cannot be written\n" , offset); +return -EINVAL ; + }else { +return flash->write (flash, offset, len, buf); + } }static inline int spi_flash_erase (struct spi_flash *flash,u32 offset,size_t len) { -return flash->erase (flash, offset, len); +if (stm_is_locked (flash, offset, len) >0 ) { +printf ("offset 0x%x is protected and cannot be erased\n" , offset); +return -EINVAL ; + }else { +return flash->erase (flash, offset, len); + } }#endif
Signature · 1 line
1.9.1
PATCH 2/2 spi: Add SPI NOR protection mechanism
Hi Fabio,
Quoted 48 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.
Introduce the
CONFIG_SF_STM_PROTECToption that can be selected by systems that want to protect regions of SPI NOR flash using the same programming model as in the ST Micro SPI NOR flashes, like for example the M25P32.Based on the implementation from Brian Norris <[email protected]> for the Linux kernel:
https://patchwork.ozlabs.org/patch/513041/Tested on a mx6qsabresd:
=> sf probe
SF: Detected M25P32 with page size 256 Bytes, erase size 64 KiB, total 4 MiB => sf protect on0x3f00000x10000
=> sf erase0x3f00000x10000
offset0x3f0000is protected and cannot be erased
SF: 65536 bytes @0x3f0000Erased: ERROR
=> sf protect off0x3f00000x10000
=> sf erase0x3f00000x10000
SF: 65536 bytes @0x3f0000Erased: OKSigned-off-by Fabio Estevam <[email protected]>---
README | 12 +++ common/cmd_sf.c | 30 +++++++ drivers/mtd/spi/sf_internal.h | 6 -- drivers/mtd/spi/sf_ops.c | 188 ++++++++++++++++++++++++++++++++++++++++++ include/spi_flash.h | 25 +++++- 5 files changed, 253 insertions(+), 8 deletions(-)README +1
-0@@ -3068,6 +3068,18 @@ CBFS (Coreboot Filesystem) support memories can be connected with a given cs line. Currently Xilinx Zynq qspi supports these type of connections. + CONFIG_SF_STM_PROTECT
README CBFS (Coreboot Filesystem) support · line 3081
Quoted 10 lines
README +10
-0+ + Enable the built-in protection mechanism provided by the + BP2, BP1 and BP0 bits from the status register present + on ST-Micro flashes such as M25P32. Please refer to the + M25P32 datasheet to understand how to program these bits + in order to protect a selected region of the SPI NOR flash. + This same bit protection programming model applies to SPI + NOR flashes from other manufacturers such as: + - Micron M25P32 + - SST SST25V32B
We should not add more CONFIG_ descriptions to this README. Please add this option via Kconfig (in drivers/mtd/spi/Kconfig) and add its description there as well.
Thanks,
Stefan