qmsi: flash: Improved reentrancy of the soc flash driver
Calls to flash write or erase operations can get preempted in the middle of the API call if a concurrent call (from other fiber or task) to the same API is made. The patch ensures concurrent API calls from other fiber/task is put on hold until the current operation is completed. The mechanism is by default not activated. To enable it, the following flag needs to be defined: CONFIG_SOC_FLASH_QMSI_API_REENTRANCY Jira: ZEP-414 Change-Id: I39429e40cb6ed446123dd1a1d7c7acc1b12417aa Signed-off-by: Kuo-Lang Tseng <kuo-lang.tseng@intel.com>
This commit is contained in:
parent
93b9196ab9
commit
2f4975b625
2 changed files with 66 additions and 1 deletions
|
@ -131,3 +131,11 @@ config SOC_FLASH_NRF5_DEV_NAME
|
||||||
default "NRF5_FLASH"
|
default "NRF5_FLASH"
|
||||||
help
|
help
|
||||||
Specify the device name for the flash driver.
|
Specify the device name for the flash driver.
|
||||||
|
|
||||||
|
config SOC_FLASH_QMSI_API_REENTRANCY
|
||||||
|
bool
|
||||||
|
prompt "flash driver API reentrancy for QMSI shim driver"
|
||||||
|
depends on SOC_FLASH_QMSI
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable support for QMSI flash driver API reentrancy.
|
||||||
|
|
|
@ -25,6 +25,54 @@
|
||||||
#include "qm_flash.h"
|
#include "qm_flash.h"
|
||||||
#include "qm_soc_regs.h"
|
#include "qm_soc_regs.h"
|
||||||
|
|
||||||
|
struct soc_flash_data {
|
||||||
|
struct nano_sem sem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_SOC_FLASH_QMSI_API_REENTRANCY
|
||||||
|
static struct soc_flash_data soc_flash_context;
|
||||||
|
#define FLASH_CONTEXT (&soc_flash_context)
|
||||||
|
static const int reentrancy_protection = 1;
|
||||||
|
#else
|
||||||
|
#define FLASH_CONTEXT (NULL)
|
||||||
|
static const int reentrancy_protection;
|
||||||
|
#endif /* CONFIG_SOC_FLASH_QMSI_API_REENTRANCY */
|
||||||
|
|
||||||
|
|
||||||
|
static void flash_reentrancy_init(struct device *dev)
|
||||||
|
{
|
||||||
|
struct soc_flash_data *context = dev->driver_data;
|
||||||
|
|
||||||
|
if (!reentrancy_protection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nano_sem_init(&context->sem);
|
||||||
|
nano_sem_give(&context->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flash_critical_region_start(struct device *dev)
|
||||||
|
{
|
||||||
|
struct soc_flash_data *context = dev->driver_data;
|
||||||
|
|
||||||
|
if (!reentrancy_protection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nano_sem_take(&context->sem, TICKS_UNLIMITED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flash_critical_region_end(struct device *dev)
|
||||||
|
{
|
||||||
|
struct soc_flash_data *context = dev->driver_data;
|
||||||
|
|
||||||
|
if (!reentrancy_protection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nano_sem_give(&context->sem);
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool is_aligned_32(uint32_t data)
|
static inline bool is_aligned_32(uint32_t data)
|
||||||
{
|
{
|
||||||
return (data & 0x3) ? false : true;
|
return (data & 0x3) ? false : true;
|
||||||
|
@ -136,7 +184,9 @@ static int flash_qmsi_write(struct device *dev, off_t addr,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
flash_critical_region_start(dev);
|
||||||
qm_flash_word_write(flash, reg, offset, data_word);
|
qm_flash_word_write(flash, reg, offset, data_word);
|
||||||
|
flash_critical_region_end(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -178,7 +228,9 @@ static int flash_qmsi_erase(struct device *dev, off_t addr, size_t size)
|
||||||
(QM_FLASH_PAGE_SIZE_BITS + 1));
|
(QM_FLASH_PAGE_SIZE_BITS + 1));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
flash_critical_region_start(dev);
|
||||||
qm_flash_page_erase(flash, reg, page);
|
qm_flash_page_erase(flash, reg, page);
|
||||||
|
flash_critical_region_end(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -197,12 +249,15 @@ static int flash_qmsi_write_protection(struct device *dev, bool enable)
|
||||||
qm_cfg.write_disable = QM_FLASH_WRITE_ENABLE;
|
qm_cfg.write_disable = QM_FLASH_WRITE_ENABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flash_critical_region_start(dev);
|
||||||
qm_flash_set_config(QM_FLASH_0, &qm_cfg);
|
qm_flash_set_config(QM_FLASH_0, &qm_cfg);
|
||||||
|
|
||||||
#if defined(CONFIG_SOC_QUARK_SE)
|
#if defined(CONFIG_SOC_QUARK_SE)
|
||||||
qm_flash_set_config(QM_FLASH_1, &qm_cfg);
|
qm_flash_set_config(QM_FLASH_1, &qm_cfg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
flash_critical_region_end(dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,9 +284,11 @@ static int quark_flash_init(struct device *dev)
|
||||||
qm_flash_set_config(QM_FLASH_1, &qm_cfg);
|
qm_flash_set_config(QM_FLASH_1, &qm_cfg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
flash_reentrancy_init(dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE_INIT(quark_flash, CONFIG_SOC_FLASH_QMSI_DEV_NAME,
|
DEVICE_INIT(quark_flash, CONFIG_SOC_FLASH_QMSI_DEV_NAME,
|
||||||
quark_flash_init, NULL, NULL, SECONDARY,
|
quark_flash_init, FLASH_CONTEXT, NULL, SECONDARY,
|
||||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue