Commit db2261b6 authored by Benedikt Schmidt's avatar Benedikt Schmidt Committed by Anas Nashif
Browse files

drivers: flash: reduce redundancy in RDP implementation on STM32



Reduce the redundancy in the readout protection implementation
on STM32 MCUs.

Signed-off-by: default avatarBenedikt Schmidt <benedikt.schmidt@embedded-solutions.at>
parent 2f088fab
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -311,12 +311,9 @@ int flash_stm32_get_wp_sectors(const struct device *dev,
			       uint32_t *protected_sectors);
#endif
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
uint8_t flash_stm32_get_rdp_level(const struct device *dev);

int flash_stm32_update_rdp(const struct device *dev, bool enable,
			   bool permanent);

int flash_stm32_get_rdp(const struct device *dev, bool *enabled,
			bool *permanent);
void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level);
#endif

/* Flash extended operations */
+90 −5
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <zephyr/device.h>
#include <zephyr/drivers/flash/stm32_flash_api_extensions.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>

#ifdef CONFIG_USERSPACE
#include <zephyr/syscall.h>
@@ -17,6 +18,8 @@
#include <soc.h>
#include "flash_stm32.h"

LOG_MODULE_REGISTER(flash_stm32_ex_op, CONFIG_FLASH_LOG_LEVEL);

#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
int flash_stm32_ex_op_sector_wp(const struct device *dev, const uintptr_t in,
				void *out)
@@ -85,6 +88,71 @@ int flash_stm32_ex_op_sector_wp(const struct device *dev, const uintptr_t in,
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */

#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
int flash_stm32_ex_op_update_rdp(const struct device *dev, bool enable,
			   bool permanent)
{
	uint8_t current_level, target_level;

	current_level = flash_stm32_get_rdp_level(dev);
	target_level = current_level;

	/*
	 * 0xAA = RDP level 0 (no protection)
	 * 0xCC = RDP level 2 (permanent protection)
	 * others = RDP level 1 (protection active)
	 */
	switch (current_level) {
	case FLASH_STM32_RDP2:
		if (!enable || !permanent) {
			LOG_DBG("RDP level 2 is permanent and can't be changed!");
			return -ENOTSUP;
		}
		break;
	case FLASH_STM32_RDP0:
		if (enable) {
			target_level = FLASH_STM32_RDP1;
			if (permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
				target_level = FLASH_STM32_RDP2;
#else
				LOG_DBG("Permanent readout protection (RDP "
					"level 0 -> 2) not allowed");
				return -ENOTSUP;
#endif
			}
		}
		break;
	default: /* FLASH_STM32_RDP1 */
		if (enable && permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
			target_level = FLASH_STM32_RDP2;
#else
			LOG_DBG("Permanent readout protection (RDP "
				"level 1 -> 2) not allowed");
			return -ENOTSUP;
#endif
		}
		if (!enable) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW)
			target_level = FLASH_STM32_RDP0;
#else
			LOG_DBG("Disabling readout protection (RDP "
				"level 1 -> 0) not allowed");
			return -EACCES;
#endif
		}
	}

	/* Update RDP level if needed */
	if (current_level != target_level) {
		LOG_INF("RDP changed from 0x%02x to 0x%02x", current_level,
			target_level);

		flash_stm32_set_rdp_level(dev, target_level);
	}
	return 0;
}

int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in,
			  void *out)
{
@@ -92,6 +160,7 @@ int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in,
		(const struct flash_stm32_ex_op_rdp *)in;
	struct flash_stm32_ex_op_rdp *result =
		(struct flash_stm32_ex_op_rdp *)out;
	uint8_t current_level;

#ifdef CONFIG_USERSPACE
	struct flash_stm32_ex_op_rdp copy;
@@ -108,7 +177,7 @@ int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in,
#endif
		rc = flash_stm32_option_bytes_lock(dev, false);
		if (rc == 0) {
			rc = flash_stm32_update_rdp(dev, request->enable,
			rc = flash_stm32_ex_op_update_rdp(dev, request->enable,
						    request->permanent);
		}

@@ -124,10 +193,26 @@ int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in,
			result = &copy;
		}
#endif
		rc2 = flash_stm32_get_rdp(dev, &result->enable,
					  &result->permanent);
		if (!rc) {
			rc = rc2;

		current_level = flash_stm32_get_rdp_level(dev);

		/*
		 * 0xAA = RDP level 0 (no protection)
		 * 0xCC = RDP level 2 (permanent protection)
		 * others = RDP level 1 (protection active)
		 */
		switch (current_level) {
		case FLASH_STM32_RDP2:
			result->enable = true;
			result->permanent = true;
			break;
		case FLASH_STM32_RDP0:
			result->enable = false;
			result->permanent = false;
			break;
		default: /* FLASH_STM32_RDP1 */
			result->enable = true;
			result->permanent = false;
		}

#ifdef CONFIG_USERSPACE
+5 −90
Original line number Diff line number Diff line
@@ -295,102 +295,17 @@ int flash_stm32_get_wp_sectors(const struct device *dev,
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */

#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
int flash_stm32_update_rdp(const struct device *dev, bool enable,
			   bool permanent)
uint8_t flash_stm32_get_rdp_level(const struct device *dev)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
	uint8_t current_level, target_level;

	current_level =
		(regs->OPTCR & FLASH_OPTCR_RDP_Msk) >> FLASH_OPTCR_RDP_Pos;
	target_level = current_level;

	/*
	 * 0xAA = RDP level 0 (no protection)
	 * 0xCC = RDP level 2 (permanent protection)
	 * others = RDP level 1 (protection active)
	 */
	switch (current_level) {
	case FLASH_STM32_RDP2:
		if (!enable || !permanent) {
			LOG_ERR("RDP level 2 is permanent and can't be changed!");
			return -ENOTSUP;
		}
		break;
	case FLASH_STM32_RDP0:
		if (enable) {
			target_level = FLASH_STM32_RDP1;
			if (permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
				target_level = FLASH_STM32_RDP2;
#else
				LOG_ERR("Permanent readout protection (RDP "
					"level 0 -> 2) not allowed");
				return -ENOTSUP;
#endif
			}
		}
		break;
	default: /* FLASH_STM32_RDP1 */
		if (enable && permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
			target_level = FLASH_STM32_RDP2;
#else
			LOG_ERR("Permanent readout protection (RDP "
				"level 1 -> 2) not allowed");
			return -ENOTSUP;
#endif
		}
		if (!enable) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW)
			target_level = FLASH_STM32_RDP0;
#else
			LOG_ERR("Disabling readout protection (RDP "
				"level 1 -> 0) not allowed");
			return -EACCES;
#endif
		}
	return (regs->OPTCR & FLASH_OPTCR_RDP_Msk) >> FLASH_OPTCR_RDP_Pos;
}

	/* Update RDP level if needed */
	if (current_level != target_level) {
		LOG_INF("RDP changed from 0x%02x to 0x%02x", current_level,
			target_level);

		write_optb(dev, FLASH_OPTCR_RDP_Msk,
			   (uint32_t)target_level << FLASH_OPTCR_RDP_Pos);
	}
	return 0;
}

int flash_stm32_get_rdp(const struct device *dev, bool *enabled,
			bool *permanent)
void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
	uint8_t current_level;

	current_level =
		(regs->OPTCR & FLASH_OPTCR_RDP_Msk) >> FLASH_OPTCR_RDP_Pos;

	/*
	 * 0xAA = RDP level 0 (no protection)
	 * 0xCC = RDP level 2 (permanent protection)
	 * others = RDP level 1 (protection active)
	 */
	switch (current_level) {
	case FLASH_STM32_RDP2:
		*enabled = true;
		*permanent = true;
		break;
	case FLASH_STM32_RDP0:
		*enabled = false;
		*permanent = false;
		break;
	default: /* FLASH_STM32_RDP1 */
		*enabled = true;
		*permanent = false;
	}
	return 0;
	write_optb(dev, FLASH_OPTCR_RDP_Msk,
		(uint32_t)level << FLASH_OPTCR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

+5 −90
Original line number Diff line number Diff line
@@ -305,102 +305,17 @@ static __unused int write_optb(const struct device *dev, uint32_t mask,
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */

#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
int flash_stm32_update_rdp(const struct device *dev, bool enable,
			   bool permanent)
uint8_t flash_stm32_get_rdp_level(const struct device *dev)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
	uint8_t current_level, target_level;

	current_level =
		(regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;
	target_level = current_level;

	/*
	 * 0xAA = RDP level 0 (no protection)
	 * 0xCC = RDP level 2 (permanent protection)
	 * others = RDP level 1 (protection active)
	 */
	switch (current_level) {
	case FLASH_STM32_RDP2:
		if (!enable || !permanent) {
			LOG_ERR("RDP level 2 is permanent and can't be changed!");
			return -ENOTSUP;
		}
		break;
	case FLASH_STM32_RDP0:
		if (enable) {
			target_level = FLASH_STM32_RDP1;
			if (permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
				target_level = FLASH_STM32_RDP2;
#else
				LOG_ERR("Permanent readout protection (RDP "
					"level 0 -> 2) not allowed");
				return -ENOTSUP;
#endif
			}
		}
		break;
	default: /* FLASH_STM32_RDP1 */
		if (enable && permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
			target_level = FLASH_STM32_RDP2;
#else
			LOG_ERR("Permanent readout protection (RDP "
				"level 1 -> 2) not allowed");
			return -ENOTSUP;
#endif
		}
		if (!enable) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW)
			target_level = FLASH_STM32_RDP0;
#else
			LOG_ERR("Disabling readout protection (RDP "
				"level 1 -> 0) not allowed");
			return -EACCES;
#endif
	return (regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;
}
	}

	/* Update RDP level if needed */
	if (current_level != target_level) {
		LOG_INF("RDP changed from 0x%02x to 0x%02x", current_level,
			target_level);

		write_optb(dev, FLASH_OPTR_RDP_Msk,
			   (uint32_t)target_level << FLASH_OPTR_RDP_Pos);
	}
	return 0;
}

int flash_stm32_get_rdp(const struct device *dev, bool *enabled,
			bool *permanent)
void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
	uint8_t current_level;

	current_level =
		(regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;

	/*
	 * 0xAA = RDP level 0 (no protection)
	 * 0xCC = RDP level 2 (permanent protection)
	 * others = RDP level 1 (protection active)
	 */
	switch (current_level) {
	case FLASH_STM32_RDP2:
		*enabled = true;
		*permanent = true;
		break;
	case FLASH_STM32_RDP0:
		*enabled = false;
		*permanent = false;
		break;
	default: /* FLASH_STM32_RDP1 */
		*enabled = true;
		*permanent = false;
	}
	return 0;
	write_optb(dev, FLASH_OPTR_RDP_Msk,
		(uint32_t)level << FLASH_OPTR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

+5 −92
Original line number Diff line number Diff line
@@ -295,107 +295,20 @@ static __unused int write_optb(const struct device *dev, uint32_t mask,
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */

#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
int flash_stm32_update_rdp(const struct device *dev, bool enable,
			   bool permanent)
uint8_t flash_stm32_get_rdp_level(const struct device *dev)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
	uint8_t current_level, target_level;

	current_level =
		(regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;
	target_level = current_level;

	/*
	 * 0xAA = RDP level 0 (no protection)
	 * 0xCC = RDP level 2 (permanent protection)
	 * others = RDP level 1 (protection active)
	 */
	switch (current_level) {
	case FLASH_STM32_RDP2:
		if (!enable || !permanent) {
			LOG_ERR("RDP level 2 is permanent and can't be changed!");
			return -ENOTSUP;
		}
		break;
	case FLASH_STM32_RDP0:
		if (enable) {
			target_level = FLASH_STM32_RDP1;
			if (permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
				target_level = FLASH_STM32_RDP2;
#else
				LOG_ERR("Permanent readout protection (RDP "
					"level 0 -> 2) not allowed");
				return -ENOTSUP;
#endif
			}
		}
		break;
	default: /* FLASH_STM32_RDP1 */
		if (enable && permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
			target_level = FLASH_STM32_RDP2;
#else
			LOG_ERR("Permanent readout protection (RDP "
				"level 1 -> 2) not allowed");
			return -ENOTSUP;
#endif
		}
		if (!enable) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW)
			target_level = FLASH_STM32_RDP0;
#else
			LOG_ERR("Disabling readout protection (RDP "
				"level 1 -> 0) not allowed");
			return -EACCES;
#endif
		}
	return (regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;
}

	/* Update RDP level if needed */
	if (current_level != target_level) {
		LOG_INF("RDP changed from 0x%02x to 0x%02x", current_level,
			target_level);

		write_optb(dev, FLASH_OPTR_RDP_Msk,
			   (uint32_t)target_level << FLASH_OPTR_RDP_Pos);
	}
	return 0;
}

int flash_stm32_get_rdp(const struct device *dev, bool *enabled,
			bool *permanent)
void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
	FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
	uint8_t current_level;

	current_level =
		(regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;

	/*
	 * 0xAA = RDP level 0 (no protection)
	 * 0xCC = RDP level 2 (permanent protection)
	 * others = RDP level 1 (protection active)
	 */
	switch (current_level) {
	case FLASH_STM32_RDP2:
		*enabled = true;
		*permanent = true;
		break;
	case FLASH_STM32_RDP0:
		*enabled = false;
		*permanent = false;
		break;
	default: /* FLASH_STM32_RDP1 */
		*enabled = true;
		*permanent = false;
	}
	return 0;
	write_optb(dev, FLASH_OPTR_RDP_Msk,
		(uint32_t)level << FLASH_OPTR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */



void flash_stm32_page_layout(const struct device *dev,
			     const struct flash_pages_layout **layout,
			     size_t *layout_size)