From 019aab9ba84363efb808c2f42cfd922c58ad1461 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Thu, 14 Mar 2019 14:53:18 +0100 Subject: [PATCH 1/2] flash: sam0: Add support for SAME54 This adds support for the flash peripheral found in the SAME5x/SAMD5x line of MCUs. The peripheral is very simmilar to the one found on SAMD2x with only a few register names changed. Signed-off-by: Benjamin Valentin --- drivers/flash/flash_sam0.c | 58 +++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/drivers/flash/flash_sam0.c b/drivers/flash/flash_sam0.c index 6bd1b0437f21d..1fb974bbbbf45 100644 --- a/drivers/flash/flash_sam0.c +++ b/drivers/flash/flash_sam0.c @@ -33,8 +33,13 @@ LOG_MODULE_REGISTER(flash_sam0); #define LOCK_REGIONS 16 #define LOCK_REGION_SIZE (FLASH_SIZE / LOCK_REGIONS) -#define PAGES_PER_ROW 4 -#define ROW_SIZE (FLASH_PAGE_SIZE * PAGES_PER_ROW) +#if defined(NVMCTRL_BLOCK_SIZE) +#define ROW_SIZE NVMCTRL_BLOCK_SIZE +#elif defined(NVMCTRL_ROW_SIZE) +#define ROW_SIZE NVMCTRL_ROW_SIZE +#endif + +#define PAGES_PER_ROW (ROW_SIZE / FLASH_PAGE_SIZE) #define FLASH_MEM(_a) ((u32_t *)((u8_t *)((_a) + CONFIG_FLASH_BASE_ADDRESS))) @@ -84,19 +89,30 @@ static int flash_sam0_valid_range(off_t offset, size_t len) static void flash_sam0_wait_ready(void) { +#ifdef NVMCTRL_STATUS_READY + while (NVMCTRL->STATUS.bit.READY == 0) { + } +#else while (NVMCTRL->INTFLAG.bit.READY == 0) { } +#endif } static int flash_sam0_check_status(off_t offset) { - NVMCTRL_STATUS_Type status; - flash_sam0_wait_ready(); - status = NVMCTRL->STATUS; +#ifdef NVMCTRL_INTFLAG_PROGE + NVMCTRL_INTFLAG_Type status = NVMCTRL->INTFLAG; + + /* Clear any flags */ + NVMCTRL->INTFLAG.reg = status.reg; +#else + NVMCTRL_STATUS_Type status = NVMCTRL->STATUS; + /* Clear any flags */ NVMCTRL->STATUS = status; +#endif if (status.bit.PROGE) { LOG_ERR("programming error at 0x%lx", (long)offset); @@ -120,7 +136,11 @@ static int flash_sam0_write_page(struct device *dev, off_t offset, u32_t *dst = FLASH_MEM(offset); int err; +#ifdef NVMCTRL_CTRLA_CMD_PBC NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_PBC | NVMCTRL_CTRLA_CMDEX_KEY; +#else + NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMD_PBC | NVMCTRL_CTRLB_CMDEX_KEY; +#endif flash_sam0_wait_ready(); /* Ensure writes happen 32 bits at a time. */ @@ -128,7 +148,11 @@ static int flash_sam0_write_page(struct device *dev, off_t offset, *dst = *src; } +#ifdef NVMCTRL_CTRLA_CMD_WP NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_WP | NVMCTRL_CTRLA_CMDEX_KEY; +#else + NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMD_WP | NVMCTRL_CTRLB_CMDEX_KEY; +#endif err = flash_sam0_check_status(offset); if (err != 0) { @@ -146,8 +170,11 @@ static int flash_sam0_write_page(struct device *dev, off_t offset, static int flash_sam0_erase_row(struct device *dev, off_t offset) { *FLASH_MEM(offset) = 0U; +#ifdef NVMCTRL_CTRLA_CMD_ER NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_ER | NVMCTRL_CTRLA_CMDEX_KEY; - +#else + NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMD_EB | NVMCTRL_CTRLB_CMDEX_KEY; +#endif return flash_sam0_check_status(offset); } @@ -318,8 +345,9 @@ static int flash_sam0_write_protection(struct device *dev, bool enable) for (offset = 0; offset < CONFIG_FLASH_SIZE * 1024; offset += LOCK_REGION_SIZE) { - *FLASH_MEM(offset) = 0U; + NVMCTRL->ADDR.reg = offset + CONFIG_FLASH_BASE_ADDRESS; +#ifdef NVMCTRL_CTRLA_CMD_LR if (enable) { NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_LR | NVMCTRL_CTRLA_CMDEX_KEY; @@ -327,6 +355,15 @@ static int flash_sam0_write_protection(struct device *dev, bool enable) NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_UR | NVMCTRL_CTRLA_CMDEX_KEY; } +#else + if (enable) { + NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMD_LR | + NVMCTRL_CTRLB_CMDEX_KEY; + } else { + NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMD_UR | + NVMCTRL_CTRLB_CMDEX_KEY; + } +#endif err = flash_sam0_check_status(offset); if (err != 0) { goto done; @@ -355,10 +392,17 @@ static int flash_sam0_init(struct device *dev) k_sem_init(&ctx->sem, 1, 1); +#ifdef PM_APBBMASK_NVMCTRL /* Ensure the clock is on. */ PM->APBBMASK.bit.NVMCTRL_ = 1; +#else + MCLK->APBBMASK.reg |= MCLK_APBBMASK_NVMCTRL; +#endif + +#ifdef NVMCTRL_CTRLB_MANW /* Require an explicit write command */ NVMCTRL->CTRLB.bit.MANW = 1; +#endif return flash_sam0_write_protection(dev, false); } From 8ccdf970dde57cafb93482fc146bf3e28a8d6554 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Thu, 16 May 2019 17:16:24 +0200 Subject: [PATCH 2/2] flash: sam0: Define LOCK_REGIONS in dts The amount of lock regions differs between different sam0 MCUs. saml10: 2 saml11: 4 samd2x: 16 saml2x: 16 samd5x: 32 ASF does not provide a definition for this, so create a new one in dts. Signed-off-by: Benjamin Valentin --- drivers/flash/flash_sam0.c | 2 +- dts/arm/atmel/samd.dtsi | 1 + dts/bindings/flash_controller/atmel,sam0-nvmctrl.yaml | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/flash/flash_sam0.c b/drivers/flash/flash_sam0.c index 1fb974bbbbf45..4cfc2e5db36eb 100644 --- a/drivers/flash/flash_sam0.c +++ b/drivers/flash/flash_sam0.c @@ -30,7 +30,7 @@ LOG_MODULE_REGISTER(flash_sam0); * Number of lock regions. The number is fixed and the region size * grows with the flash size. */ -#define LOCK_REGIONS 16 +#define LOCK_REGIONS DT_ATMEL_SAM0_NVMCTRL_0_LOCK_REGIONS #define LOCK_REGION_SIZE (FLASH_SIZE / LOCK_REGIONS) #if defined(NVMCTRL_BLOCK_SIZE) diff --git a/dts/arm/atmel/samd.dtsi b/dts/arm/atmel/samd.dtsi index ec8dc22dbd785..e865bd81e968f 100644 --- a/dts/arm/atmel/samd.dtsi +++ b/dts/arm/atmel/samd.dtsi @@ -56,6 +56,7 @@ label = "FLASH_CTRL"; reg = <0x41004000 0x22>; interrupts = <5 0>; + lock-regions = <16>; #address-cells = <1>; #size-cells = <1>; diff --git a/dts/bindings/flash_controller/atmel,sam0-nvmctrl.yaml b/dts/bindings/flash_controller/atmel,sam0-nvmctrl.yaml index 89278f6f9dedb..fb5e4ab561a2f 100644 --- a/dts/bindings/flash_controller/atmel,sam0-nvmctrl.yaml +++ b/dts/bindings/flash_controller/atmel,sam0-nvmctrl.yaml @@ -6,3 +6,9 @@ description: > compatible: "atmel,sam0-nvmctrl" include: flash-controller.yaml + +properties: + lock-regions: + type: int + required: true + description: Number of lock regions