1 /*
2 * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT espressif_esp32_flash_controller
8 #define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash)
9
10 #define FLASH_WRITE_BLK_SZ DT_PROP(SOC_NV_FLASH_NODE, write_block_size)
11 #define FLASH_ERASE_BLK_SZ DT_PROP(SOC_NV_FLASH_NODE, erase_block_size)
12
13 /*
14 * HAL includes go first to
15 * avoid BIT macro redefinition
16 */
17 #include <esp_flash.h>
18 #include <spi_flash_mmap.h>
19 #include <soc/spi_struct.h>
20 #include <esp_flash_encrypt.h>
21 #include <esp_flash_internal.h>
22
23 #include <zephyr/kernel.h>
24 #include <zephyr/device.h>
25 #include <stddef.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <zephyr/drivers/flash.h>
29 #include <soc.h>
30
31 #include <zephyr/logging/log.h>
32 LOG_MODULE_REGISTER(flash_esp32, CONFIG_FLASH_LOG_LEVEL);
33
34 #define FLASH_SEM_TIMEOUT (k_is_in_isr() ? K_NO_WAIT : K_FOREVER)
35
36 struct flash_esp32_dev_config {
37 spi_dev_t *controller;
38 };
39
40 struct flash_esp32_dev_data {
41 #ifdef CONFIG_MULTITHREADING
42 struct k_sem sem;
43 #endif
44 };
45
46 static const struct flash_parameters flash_esp32_parameters = {
47 .write_block_size = FLASH_WRITE_BLK_SZ,
48 .erase_value = 0xff,
49 };
50
51 #ifdef CONFIG_MULTITHREADING
flash_esp32_sem_take(const struct device * dev)52 static inline void flash_esp32_sem_take(const struct device *dev)
53 {
54 struct flash_esp32_dev_data *data = dev->data;
55
56 k_sem_take(&data->sem, FLASH_SEM_TIMEOUT);
57 }
58
flash_esp32_sem_give(const struct device * dev)59 static inline void flash_esp32_sem_give(const struct device *dev)
60 {
61 struct flash_esp32_dev_data *data = dev->data;
62
63 k_sem_give(&data->sem);
64 }
65 #else
66
67 #define flash_esp32_sem_take(dev) do {} while (0)
68 #define flash_esp32_sem_give(dev) do {} while (0)
69
70 #endif /* CONFIG_MULTITHREADING */
71
flash_esp32_read(const struct device * dev,off_t address,void * buffer,size_t length)72 static int flash_esp32_read(const struct device *dev, off_t address, void *buffer, size_t length)
73 {
74 int ret = 0;
75
76 flash_esp32_sem_take(dev);
77 if (!esp_flash_encryption_enabled()) {
78 ret = esp_flash_read(NULL, buffer, address, length);
79 } else {
80 ret = esp_flash_read_encrypted(NULL, address, buffer, length);
81 }
82 flash_esp32_sem_give(dev);
83 if (ret != 0) {
84 LOG_ERR("esp_flash_read failed %d", ret);
85 return -EIO;
86 }
87 return 0;
88 }
89
flash_esp32_write(const struct device * dev,off_t address,const void * buffer,size_t length)90 static int flash_esp32_write(const struct device *dev,
91 off_t address,
92 const void *buffer,
93 size_t length)
94 {
95 int ret = 0;
96
97 flash_esp32_sem_take(dev);
98 if (!esp_flash_encryption_enabled()) {
99 ret = esp_flash_write(NULL, buffer, address, length);
100 } else {
101 ret = esp_flash_write_encrypted(NULL, address, buffer, length);
102 }
103 flash_esp32_sem_give(dev);
104
105 if (ret != 0) {
106 LOG_ERR("esp_flash_write failed %d", ret);
107 return -EIO;
108 }
109 return 0;
110 }
111
flash_esp32_erase(const struct device * dev,off_t start,size_t len)112 static int flash_esp32_erase(const struct device *dev, off_t start, size_t len)
113 {
114 flash_esp32_sem_take(dev);
115 int ret = esp_flash_erase_region(NULL, start, len);
116 flash_esp32_sem_give(dev);
117 if (ret != 0) {
118 LOG_ERR("esp_flash_erase_region failed %d", ret);
119 return -EIO;
120 }
121 return 0;
122 }
123
124 #if CONFIG_FLASH_PAGE_LAYOUT
125 static const struct flash_pages_layout flash_esp32_pages_layout = {
126 .pages_count = DT_REG_SIZE(SOC_NV_FLASH_NODE) / FLASH_ERASE_BLK_SZ,
127 .pages_size = DT_PROP(SOC_NV_FLASH_NODE, erase_block_size),
128 };
129
flash_esp32_page_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)130 void flash_esp32_page_layout(const struct device *dev,
131 const struct flash_pages_layout **layout,
132 size_t *layout_size)
133 {
134 *layout = &flash_esp32_pages_layout;
135 *layout_size = 1;
136 }
137 #endif /* CONFIG_FLASH_PAGE_LAYOUT */
138
139 static const struct flash_parameters *
flash_esp32_get_parameters(const struct device * dev)140 flash_esp32_get_parameters(const struct device *dev)
141 {
142 ARG_UNUSED(dev);
143
144 return &flash_esp32_parameters;
145 }
146
flash_esp32_init(const struct device * dev)147 static int flash_esp32_init(const struct device *dev)
148 {
149 struct flash_esp32_dev_data *const dev_data = dev->data;
150 uint32_t ret = 0;
151
152 #ifdef CONFIG_MULTITHREADING
153 k_sem_init(&dev_data->sem, 1, 1);
154 #endif /* CONFIG_MULTITHREADING */
155 ret = esp_flash_init_default_chip();
156 if (ret != 0) {
157 LOG_ERR("esp_flash_init_default_chip failed %d", ret);
158 return 0;
159 }
160 return 0;
161 }
162
163 static const struct flash_driver_api flash_esp32_driver_api = {
164 .read = flash_esp32_read,
165 .write = flash_esp32_write,
166 .erase = flash_esp32_erase,
167 .get_parameters = flash_esp32_get_parameters,
168 #ifdef CONFIG_FLASH_PAGE_LAYOUT
169 .page_layout = flash_esp32_page_layout,
170 #endif
171 };
172
173 static struct flash_esp32_dev_data flash_esp32_data;
174
175 static const struct flash_esp32_dev_config flash_esp32_config = {
176 .controller = (spi_dev_t *) DT_INST_REG_ADDR(0),
177 };
178
179 DEVICE_DT_INST_DEFINE(0, flash_esp32_init,
180 NULL,
181 &flash_esp32_data, &flash_esp32_config,
182 POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY,
183 &flash_esp32_driver_api);
184