1 /*
2  * Copyright 2023-2024 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/flash.h>
9 #include <zephyr/logging/log.h>
10 
11 #include <Qspi_Ip.h>
12 
13 #include "flash_nxp_s32_qspi.h"
14 
15 LOG_MODULE_REGISTER(flash_nxp_s32_qspi, CONFIG_FLASH_LOG_LEVEL);
16 
area_is_subregion(const struct device * dev,off_t offset,size_t size)17 static ALWAYS_INLINE bool area_is_subregion(const struct device *dev, off_t offset, size_t size)
18 {
19 	Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev);
20 
21 	return ((offset >= 0) && (offset < memory_cfg->memSize) &&
22 		((memory_cfg->memSize - offset) >= size));
23 }
24 
nxp_s32_qspi_register_device(void)25 uint8_t nxp_s32_qspi_register_device(void)
26 {
27 	static uint8_t instance_cnt;
28 
29 	return instance_cnt++;
30 }
31 
32 /* Must be called with lock */
nxp_s32_qspi_wait_until_ready(const struct device * dev)33 int nxp_s32_qspi_wait_until_ready(const struct device *dev)
34 {
35 	struct nxp_s32_qspi_data *data = dev->data;
36 	Qspi_Ip_StatusType status;
37 	uint32_t timeout = 0xFFFFFF;
38 	int ret = 0;
39 
40 	do {
41 		status = Qspi_Ip_GetMemoryStatus(data->instance);
42 		timeout--;
43 	} while ((status == STATUS_QSPI_IP_BUSY) && (timeout > 0));
44 
45 	if (status != STATUS_QSPI_IP_SUCCESS) {
46 		LOG_ERR("Failed to read memory status (%d)", status);
47 		ret = -EIO;
48 	} else if (timeout == 0) {
49 		LOG_ERR("Timeout, memory is busy");
50 		ret = -ETIMEDOUT;
51 	}
52 
53 	return ret;
54 }
55 
nxp_s32_qspi_read(const struct device * dev,off_t offset,void * dest,size_t size)56 int nxp_s32_qspi_read(const struct device *dev, off_t offset, void *dest, size_t size)
57 {
58 	struct nxp_s32_qspi_data *data = dev->data;
59 	Qspi_Ip_StatusType status;
60 	int ret = 0;
61 
62 	if (!dest) {
63 		return -EINVAL;
64 	}
65 
66 	if (!area_is_subregion(dev, offset, size)) {
67 		return -EINVAL;
68 	}
69 
70 	if (size) {
71 		nxp_s32_qspi_lock(dev);
72 
73 		status = Qspi_Ip_Read(data->instance, (uint32_t)offset, (uint8_t *)dest,
74 				      (uint32_t)size);
75 		if (status != STATUS_QSPI_IP_SUCCESS) {
76 			LOG_ERR("Failed to read %zu bytes at 0x%lx (%d)", size, offset, status);
77 			ret = -EIO;
78 		}
79 
80 		nxp_s32_qspi_unlock(dev);
81 	}
82 
83 	return ret;
84 }
85 
nxp_s32_qspi_write(const struct device * dev,off_t offset,const void * src,size_t size)86 int nxp_s32_qspi_write(const struct device *dev, off_t offset, const void *src, size_t size)
87 {
88 	const struct nxp_s32_qspi_config *config = dev->config;
89 	struct nxp_s32_qspi_data *data = dev->data;
90 	Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev);
91 	Qspi_Ip_StatusType status;
92 	size_t max_write = (size_t)MIN(QSPI_IP_MAX_WRITE_SIZE, memory_cfg->pageSize);
93 	size_t len;
94 	int ret = 0;
95 
96 	if (!src || !size) {
97 		return -EINVAL;
98 	}
99 
100 	if (!area_is_subregion(dev, offset, size) ||
101 	    (offset % config->flash_parameters.write_block_size) ||
102 	    (size % config->flash_parameters.write_block_size)) {
103 		return -EINVAL;
104 	}
105 
106 	nxp_s32_qspi_lock(dev);
107 
108 	while (size) {
109 		len = MIN(max_write - (offset % max_write), size);
110 		status = Qspi_Ip_Program(data->instance, (uint32_t)offset, (const uint8_t *)src,
111 					 (uint32_t)len);
112 		if (status != STATUS_QSPI_IP_SUCCESS) {
113 			LOG_ERR("Failed to write %zu bytes at 0x%lx (%d)", len, offset, status);
114 			ret = -EIO;
115 			break;
116 		}
117 
118 		ret = nxp_s32_qspi_wait_until_ready(dev);
119 		if (ret != 0) {
120 			break;
121 		}
122 
123 		if (IS_ENABLED(CONFIG_FLASH_NXP_S32_QSPI_VERIFY_WRITE)) {
124 			status = Qspi_Ip_ProgramVerify(data->instance, (uint32_t)offset,
125 						       (const uint8_t *)src, (uint32_t)len);
126 			if (status != STATUS_QSPI_IP_SUCCESS) {
127 				LOG_ERR("Write verification failed at 0x%lx (%d)", offset, status);
128 				ret = -EIO;
129 				break;
130 			}
131 		}
132 
133 		size -= len;
134 		src = (const uint8_t *)src + len;
135 		offset += len;
136 	}
137 
138 	nxp_s32_qspi_unlock(dev);
139 
140 	return ret;
141 }
142 
nxp_s32_qspi_erase_block(const struct device * dev,off_t offset,size_t size,size_t * erase_size)143 static int nxp_s32_qspi_erase_block(const struct device *dev, off_t offset, size_t size,
144 				    size_t *erase_size)
145 {
146 	struct nxp_s32_qspi_data *data = dev->data;
147 	Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev);
148 	Qspi_Ip_EraseVarConfigType *etp = NULL;
149 	Qspi_Ip_EraseVarConfigType *etp_tmp;
150 	Qspi_Ip_StatusType status;
151 	int ret = 0;
152 
153 	/*
154 	 * Find the erase type with bigger size that can erase all or part of the
155 	 * requested memory size
156 	 */
157 	for (uint8_t i = 0; i < QSPI_IP_ERASE_TYPES; i++) {
158 		etp_tmp = (Qspi_Ip_EraseVarConfigType *)&(memory_cfg->eraseSettings.eraseTypes[i]);
159 		if ((etp_tmp->eraseLut != QSPI_IP_LUT_INVALID) &&
160 		    QSPI_IS_ALIGNED(offset, etp_tmp->size) && (BIT(etp_tmp->size) <= size) &&
161 		    ((etp == NULL) || (etp_tmp->size > etp->size))) {
162 
163 			etp = etp_tmp;
164 		}
165 	}
166 	if (etp != NULL) {
167 		*erase_size = BIT(etp->size);
168 		status = Qspi_Ip_EraseBlock(data->instance, (uint32_t)offset, *erase_size);
169 		if (status != STATUS_QSPI_IP_SUCCESS) {
170 			LOG_ERR("Failed to erase %zu bytes at 0x%lx (%d)", *erase_size,
171 				(long)offset, status);
172 			ret = -EIO;
173 		}
174 	} else {
175 		LOG_ERR("Can't find erase size to erase %zu bytes", size);
176 		ret = -EINVAL;
177 	}
178 
179 	return ret;
180 }
181 
nxp_s32_qspi_erase(const struct device * dev,off_t offset,size_t size)182 int nxp_s32_qspi_erase(const struct device *dev, off_t offset, size_t size)
183 {
184 	struct nxp_s32_qspi_data *data = dev->data;
185 	Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev);
186 	Qspi_Ip_StatusType status;
187 	size_t erase_size;
188 	int ret = 0;
189 
190 	if (!area_is_subregion(dev, offset, size) || !size) {
191 		return -EINVAL;
192 	}
193 
194 	nxp_s32_qspi_lock(dev);
195 
196 	if (size == memory_cfg->memSize) {
197 		status = Qspi_Ip_EraseChip(data->instance);
198 		if (status != STATUS_QSPI_IP_SUCCESS) {
199 			LOG_ERR("Failed to erase chip (%d)", status);
200 			ret = -EIO;
201 		}
202 	} else {
203 		while (size > 0) {
204 			erase_size = 0;
205 
206 			ret = nxp_s32_qspi_erase_block(dev, offset, size, &erase_size);
207 			if (ret != 0) {
208 				break;
209 			}
210 
211 			ret = nxp_s32_qspi_wait_until_ready(dev);
212 			if (ret != 0) {
213 				break;
214 			}
215 
216 			if (IS_ENABLED(CONFIG_FLASH_NXP_S32_QSPI_VERIFY_ERASE)) {
217 				status = Qspi_Ip_EraseVerify(data->instance, (uint32_t)offset,
218 							     erase_size);
219 				if (status != STATUS_QSPI_IP_SUCCESS) {
220 					LOG_ERR("Erase verification failed at 0x%lx (%d)", offset,
221 						status);
222 					ret = -EIO;
223 					break;
224 				}
225 			}
226 
227 			offset += erase_size;
228 			size -= erase_size;
229 		}
230 	}
231 
232 	nxp_s32_qspi_unlock(dev);
233 
234 	return ret;
235 }
236 
nxp_s32_qspi_get_parameters(const struct device * dev)237 const struct flash_parameters *nxp_s32_qspi_get_parameters(const struct device *dev)
238 {
239 	const struct nxp_s32_qspi_config *config = dev->config;
240 
241 	return &config->flash_parameters;
242 }
243 
244 #if defined(CONFIG_FLASH_PAGE_LAYOUT)
nxp_s32_qspi_pages_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)245 void nxp_s32_qspi_pages_layout(const struct device *dev, const struct flash_pages_layout **layout,
246 			       size_t *layout_size)
247 {
248 	const struct nxp_s32_qspi_config *config = dev->config;
249 
250 	*layout = &config->layout;
251 	*layout_size = 1;
252 }
253 #endif /* CONFIG_FLASH_PAGE_LAYOUT */
254 
255 #if defined(CONFIG_FLASH_JESD216_API) || !defined(CONFIG_FLASH_NXP_S32_QSPI_SFDP_RUNTIME)
nxp_s32_qspi_read_id(const struct device * dev,uint8_t * id)256 int nxp_s32_qspi_read_id(const struct device *dev, uint8_t *id)
257 {
258 	struct nxp_s32_qspi_data *data = dev->data;
259 	Qspi_Ip_StatusType status;
260 	int ret = 0;
261 
262 	nxp_s32_qspi_lock(dev);
263 
264 	status = Qspi_Ip_ReadId(data->instance, id);
265 	if (status != STATUS_QSPI_IP_SUCCESS) {
266 		LOG_ERR("Failed to read device ID (%d)", status);
267 		ret = -EIO;
268 	}
269 
270 	nxp_s32_qspi_unlock(dev);
271 
272 	return ret;
273 }
274 #endif /* CONFIG_FLASH_JESD216_API || !CONFIG_FLASH_NXP_S32_QSPI_SFDP_RUNTIME */
275