Skip to content

Commit 633e9c7

Browse files
besmarshjhedberg
authored andcommitted
drivers: flash: stm32_{o|x}spi: Add ULBPR support
Commits 72370b2 and ff34d57 added the requires-ulbpr (Unlock Block Protection Register) property to the devicetree binding for devices controlled by the STM32 QSPI peripheral, and support for this property to the STM32 QSPI driver. Some QSPI flash ICs (e.g. Microchip SST26VF series) require this command to be sent before writing/erasing is possible. This commit adds the same support to the STM32 OSPI and XSPI drivers. Signed-off-by: Ben Marsh <[email protected]>
1 parent a96a4e7 commit 633e9c7

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

drivers/flash/flash_stm32_ospi.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,32 @@ static int stm32_ospi_write_enable(struct flash_stm32_ospi_data *dev_data,
707707
return stm32_ospi_wait_auto_polling(dev_data, &s_config, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);
708708
}
709709

710+
static int ospi_write_unprotect(const struct device *dev)
711+
{
712+
struct flash_stm32_ospi_data *dev_data = dev->data;
713+
int ret = 0;
714+
715+
/* This is a SPI/STR command to issue to the external Flash device */
716+
OSPI_RegularCmdTypeDef cmd_unprotect = ospi_prepare_cmd(OSPI_SPI_MODE, OSPI_STR_TRANSFER);
717+
718+
cmd_unprotect.Instruction = SPI_NOR_CMD_ULBPR;
719+
cmd_unprotect.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
720+
cmd_unprotect.AddressMode = HAL_OSPI_ADDRESS_NONE;
721+
cmd_unprotect.DataMode = HAL_OSPI_DATA_NONE;
722+
723+
if (IS_ENABLED(DT_INST_PROP(0, requires_ulbpr))) {
724+
ret = stm32_ospi_write_enable(dev_data, OSPI_SPI_MODE, OSPI_STR_TRANSFER);
725+
726+
if (ret != 0) {
727+
return ret;
728+
}
729+
730+
ret = ospi_send_cmd(dev, &cmd_unprotect);
731+
}
732+
733+
return ret;
734+
}
735+
710736
/* Write Flash configuration register 2 with new dummy cycles */
711737
static int stm32_ospi_write_cfg2reg_dummy(OSPI_HandleTypeDef *hospi,
712738
uint8_t nor_mode, uint8_t nor_rate)
@@ -2569,6 +2595,13 @@ static int flash_stm32_ospi_init(const struct device *dev)
25692595
}
25702596
#endif /* CONFIG_FLASH_PAGE_LAYOUT */
25712597

2598+
ret = ospi_write_unprotect(dev);
2599+
if (ret != 0) {
2600+
LOG_ERR("write unprotect failed: %d", ret);
2601+
return -ENODEV;
2602+
}
2603+
LOG_DBG("Write Un-protected");
2604+
25722605
#ifdef CONFIG_STM32_MEMMAP
25732606
/* Now configure the octo Flash in MemoryMapped (access by address) */
25742607
ret = stm32_ospi_set_memorymap(dev);

drivers/flash/flash_stm32_xspi.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,31 @@ static int stm32_xspi_write_enable(const struct device *dev,
567567
return stm32_xspi_wait_auto_polling(dev, &s_config, HAL_XSPI_TIMEOUT_DEFAULT_VALUE);
568568
}
569569

570+
static int xspi_write_unprotect(const struct device *dev)
571+
{
572+
int ret = 0;
573+
574+
/* This is a SPI/STR command to issue to the external Flash device */
575+
XSPI_RegularCmdTypeDef cmd_unprotect = xspi_prepare_cmd(XSPI_SPI_MODE, XSPI_STR_TRANSFER);
576+
577+
cmd_unprotect.Instruction = SPI_NOR_CMD_ULBPR;
578+
cmd_unprotect.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE;
579+
cmd_unprotect.AddressMode = HAL_XSPI_ADDRESS_NONE;
580+
cmd_unprotect.DataMode = HAL_XSPI_DATA_NONE;
581+
582+
if (IS_ENABLED(DT_INST_PROP(0, requires_ulbpr))) {
583+
ret = stm32_xspi_write_enable(dev, XSPI_SPI_MODE, XSPI_STR_TRANSFER);
584+
585+
if (ret != 0) {
586+
return ret;
587+
}
588+
589+
ret = xspi_send_cmd(dev, &cmd_unprotect);
590+
}
591+
592+
return ret;
593+
}
594+
570595
/* Write Flash configuration register 2 with new dummy cycles */
571596
static int stm32_xspi_write_cfg2reg_dummy(const struct device *dev,
572597
uint8_t nor_mode, uint8_t nor_rate)
@@ -2372,6 +2397,13 @@ static int flash_stm32_xspi_init(const struct device *dev)
23722397
}
23732398
#endif /* CONFIG_FLASH_PAGE_LAYOUT */
23742399

2400+
ret = xspi_write_unprotect(dev);
2401+
if (ret != 0) {
2402+
LOG_ERR("write unprotect failed: %d", ret);
2403+
return -ENODEV;
2404+
}
2405+
LOG_DBG("Write Un-protected");
2406+
23752407
#ifdef CONFIG_STM32_MEMMAP
23762408
ret = stm32_xspi_set_memorymap(dev);
23772409
if (ret != 0) {

dts/bindings/flash_controller/st,stm32-ospi-nor.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,12 @@ properties:
109109
* 2READ 1-2-2 (0xBB) -> 2READ 1-2-2 4B (0xBC)
110110
* QREAD 1-1-4 (0x6B) -> QREAD 1-1-4 4B (0x6C)
111111
* 4READ 1-4-4 (0xEB) -> 4READ 1-4-4 4B (0xEC)
112+
requires-ulbpr:
113+
type: boolean
114+
description: |
115+
Indicates the device requires the ULBPR (0x98) command.
116+
117+
Some flash chips such as the Microchip SST26VF series have a block
118+
protection register that initializes to write-protected. Use this
119+
property to indicate that the BPR must be unlocked before write
120+
operations can proceed.

0 commit comments

Comments
 (0)