1 /*
2 * Copyright (c) 2022 Renesas Electronics Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT renesas_smartbond_flash_controller
8 #define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash)
9 #define QSPIF_NODE DT_NODELABEL(qspif)
10
11 #include <stddef.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/device.h>
16 #include <zephyr/drivers/flash.h>
17 #include <zephyr/sys/byteorder.h>
18 #include <DA1469xAB.h>
19
20 #define FLASH_ERASE_SIZE DT_PROP(SOC_NV_FLASH_NODE, erase_block_size)
21 #define FLASH_PAGE_SIZE 256
22
23 struct flash_smartbond_config {
24 uint32_t qspif_base_address;
25 };
26
27 static const struct flash_parameters flash_smartbond_parameters = {
28 .write_block_size = DT_PROP(SOC_NV_FLASH_NODE, write_block_size),
29 .erase_value = 0xff,
30 };
31
range_is_valid(off_t offset,uint32_t size)32 static bool range_is_valid(off_t offset, uint32_t size)
33 {
34 return (offset + size) <= (CONFIG_FLASH_SIZE * 1024);
35 }
36
qspic_data_write8(uint8_t data)37 static ALWAYS_INLINE void qspic_data_write8(uint8_t data)
38 {
39 volatile uint8_t *reg8 = (uint8_t *)&QSPIC->QSPIC_WRITEDATA_REG;
40
41 *reg8 = data;
42 }
43
qspic_data_write32(uint32_t data)44 static ALWAYS_INLINE void qspic_data_write32(uint32_t data)
45 {
46 volatile uint32_t *reg32 = (uint32_t *)&QSPIC->QSPIC_WRITEDATA_REG;
47
48 *reg32 = data;
49 }
50
qspic_data_read8(void)51 static ALWAYS_INLINE uint8_t qspic_data_read8(void)
52 {
53 volatile uint8_t *reg8 = (uint8_t *)&QSPIC->QSPIC_READDATA_REG;
54
55 return *reg8;
56 }
57
qspic_read_status(void)58 static __ramfunc uint8_t qspic_read_status(void)
59 {
60 uint8_t status;
61
62 QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_EN_CS_Msk;
63 qspic_data_write8(0x05);
64 status = qspic_data_read8();
65 QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_DIS_CS_Msk;
66
67 return status;
68 }
69
70
qspic_wait_busy(void)71 static __ramfunc void qspic_wait_busy(void)
72 {
73 do {
74 } while (qspic_read_status() & 0x01);
75 }
76
qspic_automode_exit(void)77 static __ramfunc void qspic_automode_exit(void)
78 {
79 QSPIC->QSPIC_CTRLMODE_REG &= ~QSPIC_QSPIC_CTRLMODE_REG_QSPIC_AUTO_MD_Msk;
80 QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_SET_SINGLE_Msk;
81 QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_EN_CS_Msk;
82 qspic_data_write8(0xff);
83 qspic_data_write8(0xff);
84 QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_DIS_CS_Msk;
85 }
86
qspic_write_enable(void)87 static __ramfunc void qspic_write_enable(void)
88 {
89 uint8_t status;
90
91 do {
92 QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_EN_CS_Msk;
93 qspic_data_write8(0x06);
94 QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_DIS_CS_Msk;
95
96 do {
97 status = qspic_read_status();
98 } while (status & 0x01);
99 } while (!(status & 0x02));
100 }
101
qspic_write_page(uint32_t address,const uint8_t * data,size_t size)102 static __ramfunc size_t qspic_write_page(uint32_t address, const uint8_t *data, size_t size)
103 {
104 size_t written;
105
106 /* Make sure we write up to page boundary */
107 size = MIN(size, FLASH_PAGE_SIZE - (address & (FLASH_PAGE_SIZE - 1)));
108 written = size;
109
110 QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_EN_CS_Msk;
111
112 address = sys_cpu_to_be32(address);
113 qspic_data_write32(address | 0x02);
114
115 while (size >= 4) {
116 qspic_data_write32(*(uint32_t *) data);
117 data += 4;
118 size -= 4;
119 }
120
121 while (size) {
122 qspic_data_write8(*data);
123 data++;
124 size--;
125 }
126
127 QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_DIS_CS_Msk;
128
129 return written;
130 }
131
qspic_write(uint32_t address,const uint8_t * data,size_t size)132 static __ramfunc void qspic_write(uint32_t address, const uint8_t *data, size_t size)
133 {
134 size_t written;
135
136 while (size) {
137 qspic_write_enable();
138
139 written = qspic_write_page(address, data, size);
140 address += written;
141 data += written;
142 size -= written;
143
144 qspic_wait_busy();
145 }
146 }
147
flash_smartbond_read(const struct device * dev,off_t offset,void * data,size_t size)148 static int flash_smartbond_read(const struct device *dev, off_t offset,
149 void *data, size_t size)
150 {
151 const struct flash_smartbond_config *config = dev->config;
152
153 if (!range_is_valid(offset, size)) {
154 return -EINVAL;
155 }
156
157 if (!size) {
158 return 0;
159 }
160
161 memcpy(data, (uint8_t *)(config->qspif_base_address + offset), size);
162
163 return 0;
164 }
165
flash_smartbond_write(const struct device * dev,off_t offset,const void * data,size_t size)166 static __ramfunc int flash_smartbond_write(const struct device *dev,
167 off_t offset, const void *data,
168 size_t size)
169 {
170 unsigned int key;
171 uint32_t ctrlmode;
172
173 if (!range_is_valid(offset, size)) {
174 return -EINVAL;
175 }
176
177 if (!size) {
178 return 0;
179 }
180
181 key = irq_lock();
182
183 ctrlmode = QSPIC->QSPIC_CTRLMODE_REG;
184 qspic_automode_exit();
185 qspic_wait_busy();
186
187 qspic_write(offset, data, size);
188
189 QSPIC->QSPIC_CTRLMODE_REG = ctrlmode;
190 CACHE->CACHE_CTRL1_REG |= CACHE_CACHE_CTRL1_REG_CACHE_FLUSH_Msk;
191
192 irq_unlock(key);
193
194 return 0;
195 }
196
flash_smartbond_erase(const struct device * dev,off_t offset,size_t size)197 static __ramfunc int flash_smartbond_erase(const struct device *dev, off_t offset,
198 size_t size)
199 {
200 unsigned int key;
201 uint32_t ctrlmode;
202 uint32_t address;
203
204 if (!range_is_valid(offset, size)) {
205 return -EINVAL;
206 }
207
208 if ((offset % FLASH_ERASE_SIZE) != 0) {
209 return -EINVAL;
210 }
211
212 if ((size % FLASH_ERASE_SIZE) != 0) {
213 return -EINVAL;
214 }
215
216 if (!size) {
217 return 0;
218 }
219
220 key = irq_lock();
221
222 ctrlmode = QSPIC->QSPIC_CTRLMODE_REG;
223 qspic_automode_exit();
224 qspic_wait_busy();
225
226 while (size) {
227 qspic_write_enable();
228
229 QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_EN_CS_Msk;
230
231 address = sys_cpu_to_be32(offset);
232 qspic_data_write32(address | 0x20);
233 QSPIC->QSPIC_CTRLBUS_REG = QSPIC_QSPIC_CTRLBUS_REG_QSPIC_DIS_CS_Msk;
234
235 qspic_wait_busy();
236
237 offset += FLASH_ERASE_SIZE;
238 size -= FLASH_ERASE_SIZE;
239 }
240
241 QSPIC->QSPIC_CTRLMODE_REG = ctrlmode;
242 CACHE->CACHE_CTRL1_REG |= CACHE_CACHE_CTRL1_REG_CACHE_FLUSH_Msk;
243
244 irq_unlock(key);
245
246 return 0;
247 }
248
249 static const struct flash_parameters *
flash_smartbond_get_parameters(const struct device * dev)250 flash_smartbond_get_parameters(const struct device *dev)
251 {
252 ARG_UNUSED(dev);
253
254 return &flash_smartbond_parameters;
255 }
256
257 #if CONFIG_FLASH_PAGE_LAYOUT
258 static const struct flash_pages_layout flash_smartbond_0_pages_layout = {
259 .pages_count = DT_REG_SIZE(SOC_NV_FLASH_NODE) /
260 DT_PROP(SOC_NV_FLASH_NODE, erase_block_size),
261 .pages_size = DT_PROP(SOC_NV_FLASH_NODE, erase_block_size),
262 };
263
flash_smartbond_page_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)264 void flash_smartbond_page_layout(const struct device *dev,
265 const struct flash_pages_layout **layout,
266 size_t *layout_size)
267 {
268 *layout = &flash_smartbond_0_pages_layout;
269 *layout_size = 1;
270 }
271 #endif /* CONFIG_FLASH_PAGE_LAYOUT */
272
273 static const struct flash_driver_api flash_smartbond_driver_api = {
274 .read = flash_smartbond_read,
275 .write = flash_smartbond_write,
276 .erase = flash_smartbond_erase,
277 .get_parameters = flash_smartbond_get_parameters,
278 #ifdef CONFIG_FLASH_PAGE_LAYOUT
279 .page_layout = flash_smartbond_page_layout,
280 #endif
281 };
282
283 static const struct flash_smartbond_config flash_smartbond_0_config = {
284 .qspif_base_address = DT_REG_ADDR(QSPIF_NODE),
285 };
286
287 DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, &flash_smartbond_0_config,
288 POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY, &flash_smartbond_driver_api);
289