Skip to content

Commit 481262c

Browse files
committed
drivers: flash_nxp_s32: create common source code
Create common source code to use for supporting HyperFlash. Rename 'FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME' to 'FLASH_NXP_S32_QSPI_SFDP_RUNTIME' as a common kconfig. Add the 'max-program-buffer-size' property to use for setting memory pageSize, instead of using 'CONFIG_FLASH_NXP_S32_QSPI_LAYOUT_PAGE_SIZE' for setting. Add the 'write-block-size' propertyto use for setting the number of bytes used in write operations, it also uses to instead of the 'memory-alignment' property. Signed-off-by: Cong Nguyen Huu <[email protected]>
1 parent 17ad016 commit 481262c

File tree

8 files changed

+420
-355
lines changed

8 files changed

+420
-355
lines changed

boards/nxp/mr_canhubk3/mr_canhubk3.dts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 NXP
2+
* Copyright 2023-2024 NXP
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -344,6 +344,8 @@
344344
readoc = "1-4-4";
345345
writeoc = "1-4-4";
346346
has-32k-erase;
347+
max-program-buffer-size = <256>;
348+
write-block-size = <1>;
347349
status = "okay";
348350

349351
partitions {

drivers/flash/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ zephyr_library_include_directories_ifdef(
149149
)
150150

151151
zephyr_library_sources_ifdef(CONFIG_FLASH_NXP_S32_QSPI_NOR flash_nxp_s32_qspi_nor.c)
152+
zephyr_library_sources_ifdef(CONFIG_FLASH_NXP_S32_QSPI_NOR flash_nxp_s32_qspi.c)
152153
zephyr_library_include_directories_ifdef(
153154
CONFIG_FLASH_NXP_S32_QSPI_NOR
154155
${ZEPHYR_BASE}/drivers/memc

drivers/flash/Kconfig.nxp_s32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ config FLASH_NXP_S32_QSPI_NOR
1616

1717
if FLASH_NXP_S32_QSPI_NOR
1818

19-
config FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME
19+
config FLASH_NXP_S32_QSPI_SFDP_RUNTIME
2020
bool "Read flash parameters at runtime"
2121
help
2222
Read flash device characteristics from the device at runtime.

drivers/flash/flash_nxp_s32_qspi.c

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
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+
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+
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 */
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+
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+
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+
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+
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+
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)
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)
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 */

0 commit comments

Comments
 (0)