1 /*
2  * Copyright (c) 2021 Volvo Construction Equipment
3  * Copyright 2023 NXP
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT nxp_imx_flexspi_hyperflash
9 
10 #include <zephyr/kernel.h>
11 #include <errno.h>
12 #include <zephyr/drivers/flash.h>
13 
14 #include <zephyr/logging/log.h>
15 
16 /*
17  * NOTE: If CONFIG_FLASH_MCUX_FLEXSPI_XIP is selected, Any external functions
18  * called while interacting with the flexspi MUST be relocated to SRAM or ITCM
19  * at runtime, so that the chip does not access the flexspi to read program
20  * instructions while it is being written to
21  *
22  * Additionally, no data used by this driver should be stored in flash.
23  */
24 #if defined(CONFIG_FLASH_MCUX_FLEXSPI_XIP) && (CONFIG_FLASH_LOG_LEVEL > 0)
25 #warning "Enabling flash driver logging and XIP mode simultaneously can cause \
26 	read-while-write hazards. This configuration is not recommended."
27 #endif
28 
29 LOG_MODULE_REGISTER(flexspi_hyperflash, CONFIG_FLASH_LOG_LEVEL);
30 
31 #ifdef CONFIG_HAS_MCUX_CACHE
32 #include <fsl_cache.h>
33 #endif
34 
35 #include <zephyr/sys/util.h>
36 
37 #include "memc_mcux_flexspi.h"
38 
39 #define SPI_HYPERFLASH_SECTOR_SIZE              (0x40000U)
40 #define SPI_HYPERFLASH_PAGE_SIZE                (512U)
41 
42 #define HYPERFLASH_ERASE_VALUE                  (0xFF)
43 
44 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_HYPERFLASH_WRITE_BUFFER
45 static uint8_t hyperflash_write_buf[SPI_HYPERFLASH_PAGE_SIZE];
46 #endif
47 
48 enum {
49 	/* Instructions matching with XIP layout */
50 	READ_DATA = 0,
51 	WRITE_DATA = 1,
52 	READ_STATUS = 2,
53 	WRITE_ENABLE = 4,
54 	ERASE_SECTOR = 6,
55 	PAGE_PROGRAM = 10,
56 	ERASE_CHIP = 12,
57 };
58 
59 #define CUSTOM_LUT_LENGTH                      64
60 
61 static const uint32_t flash_flexspi_hyperflash_lut[CUSTOM_LUT_LENGTH] = {
62 	/* Read Data */
63 	[4 * READ_DATA] =
64 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0xA0,
65 				kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
66 	[4 * READ_DATA + 1] =
67 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10,
68 				kFLEXSPI_Command_READ_DDR,  kFLEXSPI_8PAD, 0x04),
69 	/* Write Data */
70 	[4 * WRITE_DATA] =
71 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0x20,
72 				kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
73 	[4 * WRITE_DATA + 1] =
74 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10,
75 				kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x02),
76 	/* Read Status */
77 	[4 * READ_STATUS] =
78 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
79 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
80 	[4 * READ_STATUS + 1] =
81 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
82 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
83 	[4 * READ_STATUS + 2] =
84 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
85 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
86 	[4 * READ_STATUS + 3] =
87 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
88 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x70),
89 	[4 * READ_STATUS + 4] =
90 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0xA0,
91 				kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
92 	[4 * READ_STATUS + 5] =
93 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR,      kFLEXSPI_8PAD, 0x10,
94 				kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, 0x0B),
95 	[4 * READ_STATUS + 6] =
96 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04,
97 				kFLEXSPI_Command_STOP,     kFLEXSPI_1PAD, 0x0),
98 	/* Write Enable */
99 	[4 * WRITE_ENABLE] =
100 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20,
101 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
102 	[4 * WRITE_ENABLE + 1] =
103 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
104 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
105 	[4 * WRITE_ENABLE + 2] =
106 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
107 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
108 	[4 * WRITE_ENABLE + 3] =
109 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
110 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
111 	[4 * WRITE_ENABLE + 4] =
112 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20,
113 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
114 	[4 * WRITE_ENABLE + 5] =
115 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
116 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
117 	[4 * WRITE_ENABLE + 6] =
118 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
119 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x02),
120 	[4 * WRITE_ENABLE + 7] =
121 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
122 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
123 
124 	/* Erase Sector  */
125 	[4 * ERASE_SECTOR] =
126 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
127 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
128 	[4 * ERASE_SECTOR + 1] =
129 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
130 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
131 	[4 * ERASE_SECTOR + 2] =
132 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
133 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
134 	[4 * ERASE_SECTOR + 3] =
135 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
136 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x80),
137 	[4 * ERASE_SECTOR + 4] =
138 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
139 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
140 	[4 * ERASE_SECTOR + 5] =
141 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
142 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
143 	[4 * ERASE_SECTOR + 6] =
144 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
145 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
146 	[4 * ERASE_SECTOR + 7] =
147 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
148 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
149 	[4 * ERASE_SECTOR + 8] =
150 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
151 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
152 	[4 * ERASE_SECTOR + 9] =
153 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
154 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
155 	[4 * ERASE_SECTOR + 10] =
156 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
157 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x02),
158 	[4 * ERASE_SECTOR + 11] =
159 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
160 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
161 	[4 * ERASE_SECTOR + 12] =
162 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0x00,
163 				kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
164 	[4 * ERASE_SECTOR + 13] =
165 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10,
166 				kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0x00),
167 	[4 * ERASE_SECTOR + 14] =
168 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,  kFLEXSPI_8PAD, 0x30,
169 				kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),
170 
171 	/* program page with word program command sequence */
172 	[4 * PAGE_PROGRAM] =
173 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20,
174 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
175 	[4 * PAGE_PROGRAM + 1] =
176 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
177 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
178 	[4 * PAGE_PROGRAM + 2] =
179 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
180 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
181 	[4 * PAGE_PROGRAM + 3] =
182 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
183 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xA0),
184 	[4 * PAGE_PROGRAM + 4] =
185 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0x20,
186 				kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
187 	[4 * PAGE_PROGRAM + 5] =
188 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10,
189 				kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x80),
190 
191 	/* Erase chip */
192 	[4 * ERASE_CHIP] =
193 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
194 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
195 	[4 * ERASE_CHIP + 1] =
196 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
197 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
198 	[4 * ERASE_CHIP + 2] =
199 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
200 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
201 	[4 * ERASE_CHIP + 3] =
202 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
203 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x80),
204 	/* 1 */
205 	[4 * ERASE_CHIP + 4] =
206 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
207 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
208 	[4 * ERASE_CHIP + 5] =
209 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
210 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
211 	[4 * ERASE_CHIP + 6] =
212 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
213 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
214 	[4 * ERASE_CHIP + 7] =
215 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
216 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
217 	/* 2 */
218 	[4 * ERASE_CHIP + 8] =
219 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
220 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
221 	[4 * ERASE_CHIP + 9] =
222 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
223 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
224 	[4 * ERASE_CHIP + 10] =
225 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
226 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x02),
227 	[4 * ERASE_CHIP + 11] =
228 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
229 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
230 	/* 3 */
231 	[4 * ERASE_CHIP + 12] =
232 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
233 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
234 	[4 * ERASE_CHIP + 13] =
235 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
236 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
237 	[4 * ERASE_CHIP + 14] =
238 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
239 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
240 	[4 * ERASE_CHIP + 15] =
241 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
242 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x10),
243 };
244 
245 
246 struct flash_flexspi_hyperflash_config {
247 	const struct device *controller;
248 };
249 
250 /* Device variables used in critical sections should be in this structure */
251 struct flash_flexspi_hyperflash_data {
252 	struct device controller;
253 	flexspi_device_config_t config;
254 	flexspi_port_t port;
255 	struct flash_pages_layout layout;
256 	struct flash_parameters flash_parameters;
257 };
258 
flash_flexspi_hyperflash_wait_bus_busy(const struct device * dev)259 static int flash_flexspi_hyperflash_wait_bus_busy(const struct device *dev)
260 {
261 	struct flash_flexspi_hyperflash_data *data = dev->data;
262 	flexspi_transfer_t transfer;
263 	int ret;
264 	bool is_busy;
265 	uint32_t read_value;
266 
267 	transfer.deviceAddress = 0;
268 	transfer.port = data->port;
269 	transfer.cmdType = kFLEXSPI_Read;
270 	transfer.SeqNumber = 2;
271 	transfer.seqIndex = READ_STATUS;
272 	transfer.data = &read_value;
273 	transfer.dataSize = 2;
274 
275 	do {
276 		ret = memc_flexspi_transfer(&data->controller, &transfer);
277 		if (ret != 0) {
278 			return ret;
279 		}
280 
281 		is_busy = !(read_value & 0x8000);
282 
283 		if (read_value & 0x3200) {
284 			ret = -EINVAL;
285 			break;
286 		}
287 	} while (is_busy);
288 
289 	return ret;
290 }
291 
flash_flexspi_hyperflash_write_enable(const struct device * dev,uint32_t address)292 static int flash_flexspi_hyperflash_write_enable(const struct device *dev, uint32_t address)
293 {
294 	struct flash_flexspi_hyperflash_data *data = dev->data;
295 	flexspi_transfer_t transfer;
296 	int ret;
297 
298 	transfer.deviceAddress = address;
299 	transfer.port = data->port;
300 	transfer.cmdType = kFLEXSPI_Command;
301 	transfer.SeqNumber = 2;
302 	transfer.seqIndex = WRITE_ENABLE;
303 
304 	ret = memc_flexspi_transfer(&data->controller, &transfer);
305 
306 	return ret;
307 }
308 
flash_flexspi_hyperflash_check_vendor_id(const struct device * dev)309 static int flash_flexspi_hyperflash_check_vendor_id(const struct device *dev)
310 {
311 	struct flash_flexspi_hyperflash_data *data = dev->data;
312 	uint8_t writebuf[4] = {0x00, 0x98};
313 	uint32_t buffer[2];
314 	int ret;
315 	flexspi_transfer_t transfer;
316 
317 	transfer.deviceAddress = (0x555 * 2);
318 	transfer.port = data->port;
319 	transfer.cmdType = kFLEXSPI_Write;
320 	transfer.SeqNumber = 1;
321 	transfer.seqIndex = WRITE_DATA;
322 	transfer.data = (uint32_t *)writebuf;
323 	transfer.dataSize = 2;
324 
325 	LOG_DBG("Reading id");
326 
327 	ret = memc_flexspi_transfer(&data->controller, &transfer);
328 	if (ret != 0) {
329 		LOG_ERR("failed to CFI");
330 		return ret;
331 	}
332 
333 	transfer.deviceAddress = (0x10 * 2);
334 	transfer.port = data->port;
335 	transfer.cmdType = kFLEXSPI_Read;
336 	transfer.SeqNumber = 1;
337 	transfer.seqIndex = READ_DATA;
338 	transfer.data = buffer;
339 	transfer.dataSize = 8;
340 
341 	ret = memc_flexspi_transfer(&data->controller, &transfer);
342 	if (ret != 0) {
343 		LOG_ERR("failed to read id");
344 		return ret;
345 	}
346 	buffer[1] &= 0xFFFF;
347 	/* Check that the data read out is  unicode "QRY" in big-endian order */
348 	if ((buffer[0] != 0x52005100) || (buffer[1] != 0x5900)) {
349 		LOG_ERR("data read out is wrong!");
350 		return -EINVAL;
351 	}
352 
353 	writebuf[1] = 0xF0;
354 	transfer.deviceAddress = 0;
355 	transfer.port = data->port;
356 	transfer.cmdType = kFLEXSPI_Write;
357 	transfer.SeqNumber = 1;
358 	transfer.seqIndex = WRITE_DATA;
359 	transfer.data = (uint32_t *)writebuf;
360 	transfer.dataSize = 2;
361 
362 	ret = memc_flexspi_transfer(&data->controller, &transfer);
363 	if (ret != 0) {
364 		LOG_ERR("failed to exit");
365 		return ret;
366 	}
367 
368 	memc_flexspi_reset(&data->controller);
369 
370 	return ret;
371 }
372 
flash_flexspi_hyperflash_page_program(const struct device * dev,off_t offset,const void * buffer,size_t len)373 static int flash_flexspi_hyperflash_page_program(const struct device *dev, off_t
374 		offset, const void *buffer, size_t len)
375 {
376 	struct flash_flexspi_hyperflash_data *data = dev->data;
377 
378 	flexspi_transfer_t transfer = {
379 		.deviceAddress = offset,
380 		.port = data->port,
381 		.cmdType = kFLEXSPI_Write,
382 		.SeqNumber = 2,
383 		.seqIndex = PAGE_PROGRAM,
384 		.data = (uint32_t *)buffer,
385 		.dataSize = len,
386 	};
387 
388 	LOG_DBG("Page programming %d bytes to 0x%08lx", len, offset);
389 
390 	return memc_flexspi_transfer(&data->controller, &transfer);
391 }
392 
flash_flexspi_hyperflash_read(const struct device * dev,off_t offset,void * buffer,size_t len)393 static int flash_flexspi_hyperflash_read(const struct device *dev, off_t offset,
394 		void *buffer, size_t len)
395 {
396 	struct flash_flexspi_hyperflash_data *data = dev->data;
397 
398 	uint8_t *src = memc_flexspi_get_ahb_address(&data->controller,
399 			data->port,
400 			offset);
401 	if (!src) {
402 		return -EINVAL;
403 	}
404 
405 	memcpy(buffer, src, len);
406 
407 	return 0;
408 }
409 
flash_flexspi_hyperflash_write(const struct device * dev,off_t offset,const void * buffer,size_t len)410 static int flash_flexspi_hyperflash_write(const struct device *dev, off_t offset,
411 		const void *buffer, size_t len)
412 {
413 	struct flash_flexspi_hyperflash_data *data = dev->data;
414 	size_t size = len;
415 	uint8_t *src = (uint8_t *)buffer;
416 	unsigned int key = 0;
417 	int i, j;
418 	int ret = -1;
419 
420 	uint8_t *dst = memc_flexspi_get_ahb_address(&data->controller,
421 			data->port,
422 			offset);
423 	if (!dst) {
424 		return -EINVAL;
425 	}
426 
427 	if (memc_flexspi_is_running_xip(&data->controller)) {
428 		/*
429 		 * ==== ENTER CRITICAL SECTION ====
430 		 * No flash access should be performed in critical section. All
431 		 * code and data accessed must reside in ram.
432 		 */
433 		key = irq_lock();
434 	}
435 
436 	(void)memc_flexspi_update_clock(&data->controller, &data->config,
437 					data->port, MEMC_FLEXSPI_CLOCK_42M);
438 
439 	while (len) {
440 		/* Writing between two page sizes crashes the platform so we
441 		 * have to write the part that fits in the first page and then
442 		 * update the offset.
443 		 */
444 		i = MIN(SPI_HYPERFLASH_PAGE_SIZE - (offset %
445 					SPI_HYPERFLASH_PAGE_SIZE), len);
446 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_HYPERFLASH_WRITE_BUFFER
447 		for (j = 0; j < i; j++) {
448 			hyperflash_write_buf[j] = src[j];
449 		}
450 #endif
451 		ret = flash_flexspi_hyperflash_write_enable(dev, offset);
452 		if (ret != 0) {
453 			LOG_ERR("failed to enable write");
454 			break;
455 		}
456 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_HYPERFLASH_WRITE_BUFFER
457 		ret = flash_flexspi_hyperflash_page_program(dev, offset,
458 				hyperflash_write_buf, i);
459 #else
460 		ret = flash_flexspi_hyperflash_page_program(dev, offset, src, i);
461 #endif
462 		if (ret != 0) {
463 			LOG_ERR("failed to write");
464 			break;
465 		}
466 
467 		ret = flash_flexspi_hyperflash_wait_bus_busy(dev);
468 		if (ret != 0) {
469 			LOG_ERR("failed to wait bus busy");
470 			break;
471 		}
472 
473 		/* Do software reset. */
474 		memc_flexspi_reset(&data->controller);
475 		src += i;
476 		offset += i;
477 		len -= i;
478 	}
479 
480 	(void)memc_flexspi_update_clock(&data->controller, &data->config,
481 					data->port, MEMC_FLEXSPI_CLOCK_166M);
482 
483 #ifdef CONFIG_HAS_MCUX_CACHE
484 	DCACHE_InvalidateByRange((uint32_t) dst, size);
485 #endif
486 
487 	if (memc_flexspi_is_running_xip(&data->controller)) {
488 		/* ==== EXIT CRITICAL SECTION ==== */
489 		irq_unlock(key);
490 	}
491 
492 	return ret;
493 }
494 
flash_flexspi_hyperflash_erase(const struct device * dev,off_t offset,size_t size)495 static int flash_flexspi_hyperflash_erase(const struct device *dev, off_t offset, size_t size)
496 {
497 	struct flash_flexspi_hyperflash_data *data = dev->data;
498 	flexspi_transfer_t transfer;
499 	int ret = -1;
500 	int i;
501 	unsigned int key = 0;
502 	int num_sectors = size / SPI_HYPERFLASH_SECTOR_SIZE;
503 	uint8_t *dst = memc_flexspi_get_ahb_address(&data->controller,
504 			data->port,
505 			offset);
506 
507 	if (!dst) {
508 		return -EINVAL;
509 	}
510 
511 	if (offset % SPI_HYPERFLASH_SECTOR_SIZE) {
512 		LOG_ERR("Invalid offset");
513 		return -EINVAL;
514 	}
515 
516 	if (size % SPI_HYPERFLASH_SECTOR_SIZE) {
517 		LOG_ERR("Invalid offset");
518 		return -EINVAL;
519 	}
520 
521 	if (memc_flexspi_is_running_xip(&data->controller)) {
522 		/*
523 		 * ==== ENTER CRITICAL SECTION ====
524 		 * No flash access should be performed in critical section. All
525 		 * code and data accessed must reside in ram.
526 		 */
527 		key = irq_lock();
528 	}
529 
530 	for (i = 0; i < num_sectors; i++) {
531 		ret = flash_flexspi_hyperflash_write_enable(dev, offset);
532 		if (ret != 0) {
533 			LOG_ERR("failed to write_enable");
534 			break;
535 		}
536 
537 		LOG_DBG("Erasing sector at 0x%08lx", offset);
538 
539 		transfer.deviceAddress = offset;
540 		transfer.port = data->port;
541 		transfer.cmdType = kFLEXSPI_Command;
542 		transfer.SeqNumber = 4;
543 		transfer.seqIndex = ERASE_SECTOR;
544 
545 		ret = memc_flexspi_transfer(&data->controller, &transfer);
546 		if (ret != 0) {
547 			LOG_ERR("failed to erase");
548 			break;
549 		}
550 
551 		/* wait bus busy */
552 		ret = flash_flexspi_hyperflash_wait_bus_busy(dev);
553 		if (ret != 0) {
554 			LOG_ERR("failed to wait bus busy");
555 			break;
556 		}
557 
558 		/* Do software reset. */
559 		memc_flexspi_reset(&data->controller);
560 
561 		offset += SPI_HYPERFLASH_SECTOR_SIZE;
562 	}
563 
564 #ifdef CONFIG_HAS_MCUX_CACHE
565 	DCACHE_InvalidateByRange((uint32_t) dst, size);
566 #endif
567 
568 	if (memc_flexspi_is_running_xip(&data->controller)) {
569 		/* ==== EXIT CRITICAL SECTION ==== */
570 		irq_unlock(key);
571 	}
572 
573 	return ret;
574 }
575 
flash_flexspi_hyperflash_get_parameters(const struct device * dev)576 static const struct flash_parameters *flash_flexspi_hyperflash_get_parameters(
577 		const struct device *dev)
578 {
579 	struct flash_flexspi_hyperflash_data *data = dev->data;
580 
581 	return &data->flash_parameters;
582 }
583 
584 
flash_flexspi_hyperflash_pages_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)585 static void flash_flexspi_hyperflash_pages_layout(const struct device *dev,
586 		const struct flash_pages_layout **layout,
587 		size_t *layout_size)
588 {
589 	struct flash_flexspi_hyperflash_data *data = dev->data;
590 
591 	*layout = &data->layout;
592 	*layout_size = 1;
593 }
594 
flash_flexspi_hyperflash_init(const struct device * dev)595 static int flash_flexspi_hyperflash_init(const struct device *dev)
596 {
597 	const struct flash_flexspi_hyperflash_config *config = dev->config;
598 	struct flash_flexspi_hyperflash_data *data = dev->data;
599 	uint32_t temp_lut[sizeof(flash_flexspi_hyperflash_lut) / sizeof(uint32_t)];
600 
601 	/* Since the controller variable may be used in critical sections,
602 	 * copy the device pointer into a variable stored in RAM
603 	 */
604 	memcpy(&data->controller, config->controller, sizeof(struct device));
605 
606 	if (!device_is_ready(&data->controller)) {
607 		LOG_ERR("Controller device not ready");
608 		return -ENODEV;
609 	}
610 
611 	memc_flexspi_wait_bus_idle(&data->controller);
612 
613 	if (!memc_flexspi_is_running_xip(&data->controller) &&
614 	    memc_flexspi_set_device_config(&data->controller, &data->config,
615 				data->port)) {
616 		LOG_ERR("Could not set device configuration");
617 		return -EINVAL;
618 	}
619 
620 	/*
621 	 * Using the LUT stored in the FlexSPI directly when updating
622 	 * the FlexSPI can result in an invalid LUT entry being stored,
623 	 * as the LUT itself describes how the FlexSPI should access the flash.
624 	 * To resolve this, copy the LUT to a array placed in RAM before
625 	 * updating the FlexSPI.
626 	 */
627 	memcpy(temp_lut, flash_flexspi_hyperflash_lut,
628 		sizeof(flash_flexspi_hyperflash_lut));
629 
630 	if (memc_flexspi_update_lut(&data->controller, 0,
631 				(const uint32_t *) temp_lut,
632 				sizeof(temp_lut) / sizeof(uint32_t))) {
633 		LOG_ERR("Could not update lut");
634 		return -EINVAL;
635 	}
636 
637 	memc_flexspi_reset(&data->controller);
638 
639 	if (flash_flexspi_hyperflash_check_vendor_id(dev)) {
640 		LOG_ERR("Could not read vendor id");
641 		return -EIO;
642 	}
643 
644 	return 0;
645 }
646 
647 static const struct flash_driver_api flash_flexspi_hyperflash_api = {
648 	.read = flash_flexspi_hyperflash_read,
649 	.write = flash_flexspi_hyperflash_write,
650 	.erase = flash_flexspi_hyperflash_erase,
651 	.get_parameters = flash_flexspi_hyperflash_get_parameters,
652 #if defined(CONFIG_FLASH_PAGE_LAYOUT)
653 	.page_layout = flash_flexspi_hyperflash_pages_layout,
654 #endif
655 };
656 
657 #define CONCAT3(x, y, z) x ## y ## z
658 
659 #define CS_INTERVAL_UNIT(unit)						\
660 	CONCAT3(kFLEXSPI_CsIntervalUnit, unit, SckCycle)
661 
662 #define AHB_WRITE_WAIT_UNIT(unit)					\
663 	CONCAT3(kFLEXSPI_AhbWriteWaitUnit, unit, AhbCycle)
664 
665 #define FLASH_FLEXSPI_DEVICE_CONFIG(n)					\
666 	{								\
667 		.flexspiRootClk = MHZ(42),				\
668 		.flashSize = DT_INST_PROP(n, size) / 8 / KB(1),		\
669 		.CSIntervalUnit =					\
670 			CS_INTERVAL_UNIT(				\
671 				DT_INST_PROP(n, cs_interval_unit)),	\
672 		.CSInterval = DT_INST_PROP(n, cs_interval),		\
673 		.CSHoldTime = DT_INST_PROP(n, cs_hold_time),		\
674 		.CSSetupTime = DT_INST_PROP(n, cs_setup_time),		\
675 		.dataValidTime = DT_INST_PROP(n, data_valid_time),	\
676 		.columnspace = DT_INST_PROP(n, column_space),		\
677 		.enableWordAddress = DT_INST_PROP(n, word_addressable),	\
678 		.AWRSeqIndex = WRITE_DATA,					\
679 		.AWRSeqNumber = 1,					\
680 		.ARDSeqIndex = READ_DATA,				\
681 		.ARDSeqNumber = 1,					\
682 		.AHBWriteWaitUnit =					\
683 			AHB_WRITE_WAIT_UNIT(				\
684 				DT_INST_PROP(n, ahb_write_wait_unit)),	\
685 		.AHBWriteWaitInterval =					\
686 			DT_INST_PROP(n, ahb_write_wait_interval),	\
687 	}								\
688 
689 #define FLASH_FLEXSPI_HYPERFLASH(n)					\
690 	static struct flash_flexspi_hyperflash_config			\
691 		flash_flexspi_hyperflash_config_##n = {			\
692 		.controller = DEVICE_DT_GET(DT_INST_BUS(n)),		\
693 	};								\
694 	static struct flash_flexspi_hyperflash_data			\
695 		flash_flexspi_hyperflash_data_##n = {			\
696 		.config = FLASH_FLEXSPI_DEVICE_CONFIG(n),		\
697 		.port = DT_INST_REG_ADDR(n),				\
698 		.layout = {						\
699 			.pages_count = DT_INST_PROP(n, size) / 8	\
700 				/ SPI_HYPERFLASH_SECTOR_SIZE,		\
701 			.pages_size = SPI_HYPERFLASH_SECTOR_SIZE,	\
702 		},							\
703 		.flash_parameters = {					\
704 			.write_block_size = DT_INST_PROP(n, write_block_size), \
705 			.erase_value = HYPERFLASH_ERASE_VALUE,		\
706 		},							\
707 	};								\
708 									\
709 	DEVICE_DT_INST_DEFINE(n,					\
710 			      flash_flexspi_hyperflash_init,		\
711 			      NULL,					\
712 			      &flash_flexspi_hyperflash_data_##n,	\
713 			      &flash_flexspi_hyperflash_config_##n,	\
714 			      POST_KERNEL,				\
715 			      CONFIG_FLASH_INIT_PRIORITY,		\
716 			      &flash_flexspi_hyperflash_api);
717 
718 DT_INST_FOREACH_STATUS_OKAY(FLASH_FLEXSPI_HYPERFLASH)
719