Skip to content

Commit cc1266a

Browse files
davidmissaelnashif
authored andcommitted
drivers: memc: add memc_mcux_flexspi_aps6404l driver
Add driver for aps6404l PSRAM, using FlexSPI MEMC driver interface. Signed-off-by: David Missael Maciel <[email protected]>
1 parent e8d9dec commit cc1266a

File tree

4 files changed

+283
-0
lines changed

4 files changed

+283
-0
lines changed

drivers/memc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI memc_mcux_flexspi.c)
1111
zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_W956A8MBYA memc_mcux_flexspi_w956a8mbya.c)
1212
zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_S27KS0641 memc_mcux_flexspi_s27ks0641.c)
1313
zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_APS6408L memc_mcux_flexspi_aps6408l.c)
14+
zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_APS6404L memc_mcux_flexspi_aps6404l.c)
1415
zephyr_library_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_IS66WVQ8M4 memc_mcux_flexspi_is66wvq8m4.c)
1516
zephyr_library_sources_ifdef(CONFIG_MEMC_NXP_FLEXRAM memc_nxp_flexram.c)
1617

drivers/memc/Kconfig.mcux

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ config MEMC_MCUX_FLEXSPI_IS66WVQ8M4
3030
depends on DT_HAS_NXP_IMX_FLEXSPI_IS66WVQ8M4_ENABLED
3131
select MEMC_MCUX_FLEXSPI
3232

33+
config MEMC_MCUX_FLEXSPI_APS6404L
34+
bool "MCUX FlexSPI AP Memory APS6404L pSRAM driver"
35+
default y
36+
depends on DT_HAS_NXP_IMX_FLEXSPI_APS6404L_ENABLED
37+
select MEMC_MCUX_FLEXSPI
38+
3339
config MEMC_MCUX_FLEXSPI_INIT_PRIORITY
3440
int "MCUX FLEXSPI MEMC driver initialization priority"
3541
default MEMC_INIT_PRIORITY
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
/*
2+
* Copyright 2024 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/*
8+
* Based on memc_mcux_flexspi_s27ks0641, which is: Copyright 2021 Basalte bv
9+
*/
10+
11+
#define DT_DRV_COMPAT nxp_imx_flexspi_aps6404l
12+
13+
#include <zephyr/kernel.h>
14+
#include <zephyr/logging/log.h>
15+
#include <zephyr/sys/util.h>
16+
17+
#include "memc_mcux_flexspi.h"
18+
19+
20+
/*
21+
* NOTE: If CONFIG_FLASH_MCUX_FLEXSPI_XIP is selected, Any external functions
22+
* called while interacting with the flexspi MUST be relocated to SRAM or ITCM
23+
* at runtime, so that the chip does not access the flexspi to read program
24+
* instructions while it is being written to
25+
*/
26+
#if defined(CONFIG_FLASH_MCUX_FLEXSPI_XIP) && (CONFIG_MEMC_LOG_LEVEL > 0)
27+
#warning "Enabling memc driver logging and XIP mode simultaneously can cause \
28+
read-while-write hazards. This configuration is not recommended."
29+
#endif
30+
31+
LOG_MODULE_REGISTER(memc_flexspi_aps6404l, CONFIG_MEMC_LOG_LEVEL);
32+
33+
#define APM_VENDOR_ID 0xD
34+
35+
enum {
36+
READ_DATA = 0,
37+
WRITE_DATA,
38+
RESET_EN,
39+
RESET,
40+
READ_ID
41+
};
42+
43+
struct memc_flexspi_aps6404l_config {
44+
flexspi_port_t port;
45+
flexspi_device_config_t config;
46+
};
47+
48+
/* Device variables used in critical sections should be in this structure */
49+
struct memc_flexspi_aps6404l_data {
50+
const struct device *controller;
51+
};
52+
53+
54+
static const uint32_t memc_flexspi_aps6404l_lut[][4] = {
55+
/* Read Data (Sync read, linear burst) */
56+
[READ_DATA] = {
57+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xEB,
58+
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_4PAD, 0x18),
59+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_4PAD,
60+
0x06, kFLEXSPI_Command_READ_SDR, kFLEXSPI_4PAD, 0x04),
61+
},
62+
/* Write Data (Sync write, linear burst) */
63+
[WRITE_DATA] = {
64+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x38,
65+
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_4PAD, 0x18),
66+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD,
67+
0x00, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),
68+
},
69+
70+
[RESET_EN] = {
71+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x66,
72+
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),
73+
},
74+
/* Reset (Global reset) */
75+
[RESET] = {
76+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x99,
77+
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),
78+
},
79+
80+
[READ_ID] = {
81+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x9F,
82+
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
83+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x08,
84+
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
85+
},
86+
};
87+
88+
89+
static int memc_flexspi_aps6404l_get_vendor_id(const struct device *dev,
90+
uint8_t *vendor_id)
91+
{
92+
const struct memc_flexspi_aps6404l_config *config = dev->config;
93+
struct memc_flexspi_aps6404l_data *data = dev->data;
94+
uint32_t buffer = 0;
95+
int ret;
96+
97+
flexspi_transfer_t transfer = {
98+
.deviceAddress = 0x0,
99+
.port = config->port,
100+
.cmdType = kFLEXSPI_Read,
101+
.SeqNumber = 1,
102+
.seqIndex = READ_ID,
103+
.data = &buffer,
104+
.dataSize = 1,
105+
};
106+
107+
ret = memc_flexspi_transfer(data->controller, &transfer);
108+
*vendor_id = buffer & 0x1f;
109+
110+
return ret;
111+
}
112+
113+
static int memc_flexspi_aps6404l_reset_enable(const struct device *dev)
114+
{
115+
const struct memc_flexspi_aps6404l_config *config = dev->config;
116+
struct memc_flexspi_aps6404l_data *data = dev->data;
117+
int ret;
118+
119+
flexspi_transfer_t transfer = {
120+
.deviceAddress = 0x0,
121+
.port = config->port,
122+
.cmdType = kFLEXSPI_Command,
123+
.SeqNumber = 1,
124+
.seqIndex = RESET_EN,
125+
.data = NULL,
126+
.dataSize = 0,
127+
};
128+
129+
LOG_DBG("Enabling reset ram");
130+
ret = memc_flexspi_transfer(data->controller, &transfer);
131+
if (ret < 0) {
132+
return ret;
133+
}
134+
/* We need to delay 5 ms to allow APS6404L pSRAM to reinitialize */
135+
k_msleep(5);
136+
137+
return ret;
138+
}
139+
140+
141+
static int memc_flexspi_aps6404l_reset(const struct device *dev)
142+
{
143+
const struct memc_flexspi_aps6404l_config *config = dev->config;
144+
struct memc_flexspi_aps6404l_data *data = dev->data;
145+
int ret;
146+
147+
flexspi_transfer_t transfer = {
148+
.deviceAddress = 0x0,
149+
.port = config->port,
150+
.cmdType = kFLEXSPI_Command,
151+
.SeqNumber = 1,
152+
.seqIndex = RESET,
153+
.data = NULL,
154+
.dataSize = 0,
155+
};
156+
157+
LOG_DBG("Resetting ram");
158+
ret = memc_flexspi_transfer(data->controller, &transfer);
159+
if (ret < 0) {
160+
return ret;
161+
}
162+
/* We need to delay 5 ms to allow APS6404L pSRAM to reinitialize */
163+
k_msleep(5);
164+
165+
return ret;
166+
}
167+
168+
static int memc_flexspi_aps6404l_init(const struct device *dev)
169+
{
170+
const struct memc_flexspi_aps6404l_config *config = dev->config;
171+
struct memc_flexspi_aps6404l_data *data = dev->data;
172+
uint8_t vendor_id;
173+
174+
if (!device_is_ready(data->controller)) {
175+
LOG_ERR("Controller device not ready");
176+
return -ENODEV;
177+
}
178+
179+
if (memc_flexspi_set_device_config(data->controller, &config->config,
180+
(const uint32_t *) memc_flexspi_aps6404l_lut,
181+
sizeof(memc_flexspi_aps6404l_lut) / MEMC_FLEXSPI_CMD_SIZE,
182+
config->port)) {
183+
LOG_ERR("Could not set device configuration");
184+
return -EINVAL;
185+
}
186+
187+
memc_flexspi_reset(data->controller);
188+
189+
if (memc_flexspi_aps6404l_reset_enable(dev)) {
190+
LOG_ERR("Could not enable reset pSRAM");
191+
return -EIO;
192+
}
193+
194+
if (memc_flexspi_aps6404l_reset(dev)) {
195+
LOG_ERR("Could not reset pSRAM");
196+
return -EIO;
197+
}
198+
199+
if (memc_flexspi_aps6404l_get_vendor_id(dev, &vendor_id)) {
200+
LOG_ERR("Could not read vendor id");
201+
return -EIO;
202+
}
203+
LOG_DBG("Vendor id: 0x%0x", vendor_id);
204+
if (vendor_id != APM_VENDOR_ID) {
205+
LOG_WRN("Vendor ID does not match expected value of 0x%0x",
206+
APM_VENDOR_ID);
207+
}
208+
209+
return 0;
210+
}
211+
212+
#define CONCAT3(x, y, z) x ## y ## z
213+
214+
#define CS_INTERVAL_UNIT(unit) \
215+
CONCAT3(kFLEXSPI_CsIntervalUnit, unit, SckCycle)
216+
217+
#define AHB_WRITE_WAIT_UNIT(unit) \
218+
CONCAT3(kFLEXSPI_AhbWriteWaitUnit, unit, AhbCycle)
219+
220+
#define MEMC_FLEXSPI_DEVICE_CONFIG(n) \
221+
{ \
222+
.flexspiRootClk = DT_INST_PROP(n, spi_max_frequency), \
223+
.isSck2Enabled = false, \
224+
.flashSize = DT_INST_PROP(n, size) / 8 / KB(1), \
225+
.addressShift = false, \
226+
.CSIntervalUnit = \
227+
CS_INTERVAL_UNIT( \
228+
DT_INST_PROP(n, cs_interval_unit)), \
229+
.CSInterval = DT_INST_PROP(n, cs_interval), \
230+
.CSHoldTime = DT_INST_PROP(n, cs_hold_time), \
231+
.CSSetupTime = DT_INST_PROP(n, cs_setup_time), \
232+
.dataValidTime = DT_INST_PROP(n, data_valid_time), \
233+
.columnspace = DT_INST_PROP(n, column_space), \
234+
.enableWordAddress = DT_INST_PROP(n, word_addressable), \
235+
.AWRSeqIndex = WRITE_DATA, \
236+
.AWRSeqNumber = 1, \
237+
.ARDSeqIndex = READ_DATA, \
238+
.ARDSeqNumber = 1, \
239+
.AHBWriteWaitUnit = \
240+
AHB_WRITE_WAIT_UNIT( \
241+
DT_INST_PROP(n, ahb_write_wait_unit)), \
242+
.AHBWriteWaitInterval = \
243+
DT_INST_PROP(n, ahb_write_wait_interval), \
244+
.enableWriteMask = false, \
245+
} \
246+
247+
#define MEMC_FLEXSPI_APS6404L(n) \
248+
static const struct memc_flexspi_aps6404l_config \
249+
memc_flexspi_aps6404l_config_##n = { \
250+
.port = DT_INST_REG_ADDR(n), \
251+
.config = MEMC_FLEXSPI_DEVICE_CONFIG(n), \
252+
}; \
253+
\
254+
static struct memc_flexspi_aps6404l_data \
255+
memc_flexspi_aps6404l_data_##n = { \
256+
.controller = DEVICE_DT_GET(DT_INST_BUS(n)), \
257+
}; \
258+
\
259+
DEVICE_DT_INST_DEFINE(n, \
260+
memc_flexspi_aps6404l_init, \
261+
NULL, \
262+
&memc_flexspi_aps6404l_data_##n, \
263+
&memc_flexspi_aps6404l_config_##n, \
264+
POST_KERNEL, \
265+
CONFIG_MEMC_INIT_PRIORITY, \
266+
NULL);
267+
268+
DT_INST_FOREACH_STATUS_OKAY(MEMC_FLEXSPI_APS6404L)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright 2022 NXP
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: AP Memory APS6404L pSRAM on NXP FlexSPI bus
5+
6+
compatible: "nxp,imx-flexspi-aps6404l"
7+
8+
include: nxp,imx-flexspi-device.yaml

0 commit comments

Comments
 (0)