Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 52 additions & 8 deletions drivers/flash/flash_sam0.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@ 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)

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

Expand Down Expand Up @@ -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);
Expand All @@ -120,15 +136,23 @@ 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. */
for (; src != end; src++, dst++) {
*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) {
Expand All @@ -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);
}

Expand Down Expand Up @@ -318,15 +345,25 @@ 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;
} else {
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;
Expand Down Expand Up @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions dts/arm/atmel/samd.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
label = "FLASH_CTRL";
reg = <0x41004000 0x22>;
interrupts = <5 0>;
lock-regions = <16>;

#address-cells = <1>;
#size-cells = <1>;
Expand Down
6 changes: 6 additions & 0 deletions dts/bindings/flash_controller/atmel,sam0-nvmctrl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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