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 	uint32_t ret = 0;
150 
151 #ifdef CONFIG_MULTITHREADING
152 	struct flash_esp32_dev_data *const dev_data = dev->data;
153 
154 	k_sem_init(&dev_data->sem, 1, 1);
155 #endif /* CONFIG_MULTITHREADING */
156 	ret = esp_flash_init_default_chip();
157 	if (ret != 0) {
158 		LOG_ERR("esp_flash_init_default_chip failed %d", ret);
159 		return 0;
160 	}
161 	return 0;
162 }
163 
164 static DEVICE_API(flash, flash_esp32_driver_api) = {
165 	.read = flash_esp32_read,
166 	.write = flash_esp32_write,
167 	.erase = flash_esp32_erase,
168 	.get_parameters = flash_esp32_get_parameters,
169 #ifdef CONFIG_FLASH_PAGE_LAYOUT
170 	.page_layout = flash_esp32_page_layout,
171 #endif
172 };
173 
174 static struct flash_esp32_dev_data flash_esp32_data;
175 
176 static const struct flash_esp32_dev_config flash_esp32_config = {
177 	.controller = (spi_dev_t *) DT_INST_REG_ADDR(0),
178 };
179 
180 DEVICE_DT_INST_DEFINE(0, flash_esp32_init,
181 		      NULL,
182 		      &flash_esp32_data, &flash_esp32_config,
183 		      POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY,
184 		      &flash_esp32_driver_api);
185