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