Commit 2f4975b6 authored by Kuo-Lang Tseng's avatar Kuo-Lang Tseng Committed by Andrew Boie
Browse files

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: default avatarKuo-Lang Tseng <kuo-lang.tseng@intel.com>
parent 93b9196a
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -131,3 +131,11 @@ config SOC_FLASH_NRF5_DEV_NAME
	default "NRF5_FLASH"
	help
	  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.
+58 −1
Original line number Diff line number Diff line
@@ -25,6 +25,54 @@
#include "qm_flash.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)
{
	return (data & 0x3) ? false : true;
@@ -136,7 +184,9 @@ static int flash_qmsi_write(struct device *dev, off_t addr,
		}
#endif

		flash_critical_region_start(dev);
		qm_flash_word_write(flash, reg, offset, data_word);
		flash_critical_region_end(dev);
	}

	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));
		}
#endif
		flash_critical_region_start(dev);
		qm_flash_page_erase(flash, reg, page);
		flash_critical_region_end(dev);
	}

	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;
	}

	flash_critical_region_start(dev);
	qm_flash_set_config(QM_FLASH_0, &qm_cfg);

#if defined(CONFIG_SOC_QUARK_SE)
	qm_flash_set_config(QM_FLASH_1, &qm_cfg);
#endif

	flash_critical_region_end(dev);

	return 0;
}

@@ -229,9 +284,11 @@ static int quark_flash_init(struct device *dev)
	qm_flash_set_config(QM_FLASH_1, &qm_cfg);
#endif

	flash_reentrancy_init(dev);

	return 0;
}

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);