/* * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. * * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT espressif_esp32_flash_controller #define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) #define FLASH_WRITE_BLK_SZ DT_PROP(SOC_NV_FLASH_NODE, write_block_size) #define FLASH_ERASE_BLK_SZ DT_PROP(SOC_NV_FLASH_NODE, erase_block_size) /* * HAL includes go first to * avoid BIT macro redefinition */ #include #include #include #include #include #include #include #include #include #include #include #include #include LOG_MODULE_REGISTER(flash_esp32, CONFIG_FLASH_LOG_LEVEL); #define FLASH_SEM_TIMEOUT (k_is_in_isr() ? K_NO_WAIT : K_FOREVER) struct flash_esp32_dev_config { spi_dev_t *controller; }; struct flash_esp32_dev_data { #ifdef CONFIG_MULTITHREADING struct k_sem sem; #endif }; static const struct flash_parameters flash_esp32_parameters = { .write_block_size = FLASH_WRITE_BLK_SZ, .erase_value = 0xff, }; #ifdef CONFIG_MULTITHREADING static inline void flash_esp32_sem_take(const struct device *dev) { struct flash_esp32_dev_data *data = dev->data; k_sem_take(&data->sem, FLASH_SEM_TIMEOUT); } static inline void flash_esp32_sem_give(const struct device *dev) { struct flash_esp32_dev_data *data = dev->data; k_sem_give(&data->sem); } #else #define flash_esp32_sem_take(dev) do {} while (0) #define flash_esp32_sem_give(dev) do {} while (0) #endif /* CONFIG_MULTITHREADING */ static int flash_esp32_read(const struct device *dev, off_t address, void *buffer, size_t length) { int ret = 0; flash_esp32_sem_take(dev); if (!esp_flash_encryption_enabled()) { ret = esp_flash_read(NULL, buffer, address, length); } else { ret = esp_flash_read_encrypted(NULL, address, buffer, length); } flash_esp32_sem_give(dev); if (ret != 0) { LOG_ERR("esp_flash_read failed %d", ret); return -EIO; } return 0; } static int flash_esp32_write(const struct device *dev, off_t address, const void *buffer, size_t length) { int ret = 0; flash_esp32_sem_take(dev); if (!esp_flash_encryption_enabled()) { ret = esp_flash_write(NULL, buffer, address, length); } else { ret = esp_flash_write_encrypted(NULL, address, buffer, length); } flash_esp32_sem_give(dev); if (ret != 0) { LOG_ERR("esp_flash_write failed %d", ret); return -EIO; } return 0; } static int flash_esp32_erase(const struct device *dev, off_t start, size_t len) { flash_esp32_sem_take(dev); int ret = esp_flash_erase_region(NULL, start, len); flash_esp32_sem_give(dev); if (ret != 0) { LOG_ERR("esp_flash_erase_region failed %d", ret); return -EIO; } return 0; } #if CONFIG_FLASH_PAGE_LAYOUT static const struct flash_pages_layout flash_esp32_pages_layout = { .pages_count = DT_REG_SIZE(SOC_NV_FLASH_NODE) / FLASH_ERASE_BLK_SZ, .pages_size = DT_PROP(SOC_NV_FLASH_NODE, erase_block_size), }; void flash_esp32_page_layout(const struct device *dev, const struct flash_pages_layout **layout, size_t *layout_size) { *layout = &flash_esp32_pages_layout; *layout_size = 1; } #endif /* CONFIG_FLASH_PAGE_LAYOUT */ static const struct flash_parameters * flash_esp32_get_parameters(const struct device *dev) { ARG_UNUSED(dev); return &flash_esp32_parameters; } static int flash_esp32_init(const struct device *dev) { uint32_t ret = 0; #ifdef CONFIG_MULTITHREADING struct flash_esp32_dev_data *const dev_data = dev->data; k_sem_init(&dev_data->sem, 1, 1); #endif /* CONFIG_MULTITHREADING */ ret = esp_flash_init_default_chip(); if (ret != 0) { LOG_ERR("esp_flash_init_default_chip failed %d", ret); return 0; } return 0; } static const struct flash_driver_api flash_esp32_driver_api = { .read = flash_esp32_read, .write = flash_esp32_write, .erase = flash_esp32_erase, .get_parameters = flash_esp32_get_parameters, #ifdef CONFIG_FLASH_PAGE_LAYOUT .page_layout = flash_esp32_page_layout, #endif }; static struct flash_esp32_dev_data flash_esp32_data; static const struct flash_esp32_dev_config flash_esp32_config = { .controller = (spi_dev_t *) DT_INST_REG_ADDR(0), }; DEVICE_DT_INST_DEFINE(0, flash_esp32_init, NULL, &flash_esp32_data, &flash_esp32_config, POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY, &flash_esp32_driver_api);