1 /*
2  * Copyright 2024 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_s32_qspi_hyperflash
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/flash.h>
11 #include <zephyr/logging/log.h>
12 
13 #include <Qspi_Ip.h>
14 
15 #include "memc_nxp_s32_qspi.h"
16 #include "flash_nxp_s32_qspi.h"
17 
18 LOG_MODULE_REGISTER(nxp_s32_qspi_hyperflash, CONFIG_FLASH_LOG_LEVEL);
19 
20 /* Use the fixed command sets from Qspi_Ip_Hyperflash.c */
21 extern Qspi_Ip_InstrOpType QSPI_IP_HF_LUT_NAME[QSPI_IP_HF_LUT_SIZE];
22 
nxp_s32_qspi_init(const struct device * dev)23 static int nxp_s32_qspi_init(const struct device *dev)
24 {
25 	struct nxp_s32_qspi_data *data = dev->data;
26 	const struct nxp_s32_qspi_config *config = dev->config;
27 	Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev);
28 	uint8_t dev_id[memory_cfg->readIdSettings.readIdSize];
29 	Qspi_Ip_StatusType status;
30 	int ret = 0;
31 
32 	/* Used by the HAL to retrieve the internal driver state */
33 	data->instance = nxp_s32_qspi_register_device();
34 	__ASSERT_NO_MSG(data->instance < QSPI_IP_MEM_INSTANCE_COUNT);
35 	data->memory_conn_cfg.qspiInstance = memc_nxp_s32_qspi_get_instance(config->controller);
36 
37 #if defined(CONFIG_MULTITHREADING)
38 	k_sem_init(&data->sem, 1, 1);
39 #endif
40 
41 	if (!device_is_ready(config->controller)) {
42 		LOG_ERR("Memory control device not ready");
43 		return -ENODEV;
44 	}
45 
46 	status = Qspi_Ip_Init(data->instance, (const Qspi_Ip_MemoryConfigType *)memory_cfg,
47 			      (const Qspi_Ip_MemoryConnectionType *)&data->memory_conn_cfg);
48 	if (status != STATUS_QSPI_IP_SUCCESS) {
49 		LOG_ERR("Fail to init memory device %d (%d)", data->instance, status);
50 		return -EIO;
51 	}
52 
53 	/* Verify connectivity by reading the device ID */
54 	ret = nxp_s32_qspi_read_id(dev, dev_id);
55 	if (ret != 0) {
56 		LOG_ERR("Device ID read failed (%d)", ret);
57 		return -ENODEV;
58 	}
59 
60 	if (memcmp(dev_id, memory_cfg->readIdSettings.readIdExpected, sizeof(dev_id))) {
61 		LOG_ERR("Device id does not match config");
62 		return -EINVAL;
63 	}
64 
65 	return ret;
66 }
67 
68 static DEVICE_API(flash, nxp_s32_qspi_api) = {
69 	.erase = nxp_s32_qspi_erase,
70 	.write = nxp_s32_qspi_write,
71 	.read = nxp_s32_qspi_read,
72 	.get_parameters = nxp_s32_qspi_get_parameters,
73 #if defined(CONFIG_FLASH_PAGE_LAYOUT)
74 	.page_layout = nxp_s32_qspi_pages_layout,
75 #endif /* CONFIG_FLASH_PAGE_LAYOUT */
76 };
77 
78 #define QSPI_PAGE_LAYOUT(n)							\
79 	.layout = {								\
80 		.pages_count = (DT_INST_PROP(n, size) / 8)			\
81 			/ CONFIG_FLASH_NXP_S32_QSPI_LAYOUT_PAGE_SIZE,		\
82 		.pages_size = CONFIG_FLASH_NXP_S32_QSPI_LAYOUT_PAGE_SIZE,	\
83 	}
84 
85 #define QSPI_READ_ID_CFG(n)							\
86 	{									\
87 		.readIdLut = QSPI_IP_HF_LUT_READ,				\
88 		.readIdSize = DT_INST_PROP_LEN(n, jedec_id),			\
89 		.readIdExpected = DT_INST_PROP(n, jedec_id),			\
90 	}
91 
92 #define QSPI_MEMORY_CONN_CFG(n)							\
93 	{									\
94 		.connectionType = (Qspi_Ip_ConnectionType)DT_INST_REG_ADDR(n),	\
95 		.memAlignment = DT_INST_PROP(n, write_block_size)		\
96 	}
97 
98 #define QSPI_ERASE_CFG(n)							\
99 	{									\
100 		.eraseTypes = {							\
101 			{							\
102 				.eraseLut = QSPI_IP_HF_LUT_SE,			\
103 				.size = 12, /* 4 KB */				\
104 			},							\
105 			{							\
106 				.eraseLut = QSPI_IP_HF_LUT_SE,			\
107 				.size = 18, /* 256 KB */			\
108 			},							\
109 			{							\
110 				.eraseLut = QSPI_IP_LUT_INVALID,		\
111 				.size = 0,					\
112 			},							\
113 			{							\
114 				.eraseLut = QSPI_IP_LUT_INVALID,		\
115 				.size = 0,					\
116 			},							\
117 		},								\
118 		.chipEraseLut = QSPI_IP_HF_LUT_CE,				\
119 	}
120 
121 #define QSPI_RESET_CFG(n)							\
122 	{									\
123 		.resetCmdLut = QSPI_IP_HF_LUT_RST,				\
124 		.resetCmdCount = QSPI_IP_HF_RST_CNT,				\
125 	}
126 
127 #define QSPI_STATUS_REG_CFG(n)							\
128 	{									\
129 		.statusRegInitReadLut = QSPI_IP_HF_LUT_RDSR,			\
130 		.statusRegReadLut = QSPI_IP_HF_LUT_RDSR,			\
131 		.statusRegWriteLut = QSPI_IP_LUT_INVALID,			\
132 		.writeEnableSRLut = QSPI_IP_LUT_INVALID,			\
133 		.writeEnableLut = QSPI_IP_LUT_INVALID,				\
134 		.regSize = 1U,							\
135 		.busyOffset = 0U,						\
136 		.busyValue = 1U,						\
137 		.writeEnableOffset = 1U,					\
138 	}
139 
140 #define QSPI_INIT_CFG(n)							\
141 	{									\
142 		.opCount = 0U,							\
143 		.operations = NULL,						\
144 	}
145 
146 #define QSPI_LUT_CFG(n)								\
147 	{									\
148 		.opCount = QSPI_IP_HF_LUT_SIZE,					\
149 		.lutOps = (Qspi_Ip_InstrOpType *)QSPI_IP_HF_LUT_NAME,		\
150 	}
151 
152 #define QSPI_SUSPEND_CFG(n)							\
153 	{									\
154 		.eraseSuspendLut = QSPI_IP_HF_LUT_ES,				\
155 		.eraseResumeLut = QSPI_IP_HF_LUT_ER,				\
156 		.programSuspendLut = QSPI_IP_HF_LUT_PS,				\
157 		.programResumeLut = QSPI_IP_HF_LUT_PR,				\
158 	}
159 
160 #define QSPI_MEMORY_CFG(n)							\
161 	{									\
162 		.memType = QSPI_IP_HYPER_FLASH,					\
163 		.hfConfig = &hyperflash_config_##n,				\
164 		.memSize = DT_INST_PROP(n, size) / 8,				\
165 		.pageSize = DT_INST_PROP(n, max_program_buffer_size),		\
166 		.writeLut = QSPI_IP_HF_LUT_WRITE,				\
167 		.readLut = QSPI_IP_HF_LUT_READ,					\
168 		.read0xxLut = QSPI_IP_LUT_INVALID,				\
169 		.read0xxLutAHB = QSPI_IP_LUT_INVALID,				\
170 		.eraseSettings = QSPI_ERASE_CFG(n),				\
171 		.statusConfig = QSPI_STATUS_REG_CFG(n),				\
172 		.resetSettings = QSPI_RESET_CFG(n),				\
173 		.initResetSettings = QSPI_RESET_CFG(n),				\
174 		.initConfiguration = QSPI_INIT_CFG(n),				\
175 		.lutSequences = QSPI_LUT_CFG(n),				\
176 		.readIdSettings = QSPI_READ_ID_CFG(n),				\
177 		.suspendSettings = QSPI_SUSPEND_CFG(n),				\
178 		.initCallout = NULL,						\
179 		.resetCallout = NULL,						\
180 		.errorCheckCallout = NULL,					\
181 		.eccCheckCallout = NULL,					\
182 		.ctrlAutoCfgPtr = NULL,						\
183 	}
184 
185 #define FLASH_NXP_S32_QSPI_DRV_STRENGTH(n)							\
186 	COND_CODE_1(DT_INST_ENUM_IDX(n, vcc_mv),						\
187 		(DT_INST_PROP(n, drive_strength_ohm) == 12 ? QSPI_IP_HF_DRV_STRENGTH_007 :	\
188 		(DT_INST_PROP(n, drive_strength_ohm) == 14 ? QSPI_IP_HF_DRV_STRENGTH_006 :	\
189 		(DT_INST_PROP(n, drive_strength_ohm) == 16 ? QSPI_IP_HF_DRV_STRENGTH_005 :	\
190 		(DT_INST_PROP(n, drive_strength_ohm) == 20 ? QSPI_IP_HF_DRV_STRENGTH_000 :	\
191 		(DT_INST_PROP(n, drive_strength_ohm) == 27 ? QSPI_IP_HF_DRV_STRENGTH_003 :	\
192 		(DT_INST_PROP(n, drive_strength_ohm) == 40 ? QSPI_IP_HF_DRV_STRENGTH_002 :	\
193 		(DT_INST_PROP(n, drive_strength_ohm) == 71 ? QSPI_IP_HF_DRV_STRENGTH_001 :	\
194 		QSPI_IP_HF_DRV_STRENGTH_000))))))),						\
195 		(DT_INST_PROP(n, drive_strength_ohm) == 20 ? QSPI_IP_HF_DRV_STRENGTH_007 :	\
196 		(DT_INST_PROP(n, drive_strength_ohm) == 24 ? QSPI_IP_HF_DRV_STRENGTH_006 :	\
197 		(DT_INST_PROP(n, drive_strength_ohm) == 27 ? QSPI_IP_HF_DRV_STRENGTH_000 :	\
198 		(DT_INST_PROP(n, drive_strength_ohm) == 34 ? QSPI_IP_HF_DRV_STRENGTH_004 :	\
199 		(DT_INST_PROP(n, drive_strength_ohm) == 45 ? QSPI_IP_HF_DRV_STRENGTH_003 :	\
200 		(DT_INST_PROP(n, drive_strength_ohm) == 68 ? QSPI_IP_HF_DRV_STRENGTH_002 :	\
201 		(DT_INST_PROP(n, drive_strength_ohm) == 117 ? QSPI_IP_HF_DRV_STRENGTH_001 :	\
202 		QSPI_IP_HF_DRV_STRENGTH_000))))))))
203 
204 #define FLASH_NXP_S32_QSPI_SECTOR_MAP(n)							\
205 	COND_CODE_1(DT_INST_PROP(n, support_only_uniform_sectors),				\
206 		(DT_INST_ENUM_IDX(n, ppw_sectors_addr_mapping) ?				\
207 			QSPI_IP_HF_UNIFORM_SECTORS_READ_PASSWORD_HIGH :				\
208 			QSPI_IP_HF_UNIFORM_SECTORS_READ_PASSWORD_LOW),				\
209 		(DT_INST_ENUM_IDX(n, ppw_sectors_addr_mapping) ?				\
210 			QSPI_IP_HF_PARAM_AND_PASSWORD_MAP_HIGH :				\
211 			QSPI_IP_HF_PARAM_AND_PASSWORD_MAP_LOW))
212 
213 #define FLASH_NXP_S32_QSPI_INIT_DEVICE(n)					\
214 	static Qspi_Ip_HyperFlashConfigType hyperflash_config_##n =		\
215 	{									\
216 		.outputDriverStrength = FLASH_NXP_S32_QSPI_DRV_STRENGTH(n),	\
217 		.RWDSLowOnDualError = DT_INST_PROP(n, rwds_low_dual_error),	\
218 		.secureRegionUnlocked = !DT_INST_PROP(n, secure_region_locked),	\
219 		.readLatency = DT_INST_ENUM_IDX(n, read_latency_cycles),	\
220 		.paramSectorMap = FLASH_NXP_S32_QSPI_SECTOR_MAP(n),		\
221 		.deviceIdWordAddress = DT_INST_PROP(n, device_id_word_addr),	\
222 	};									\
223 	static const struct nxp_s32_qspi_config nxp_s32_qspi_config_##n = {	\
224 		.controller = DEVICE_DT_GET(DT_INST_BUS(n)),			\
225 		.flash_parameters = {						\
226 			.write_block_size = DT_INST_PROP(n, write_block_size),	\
227 			.erase_value = QSPI_ERASE_VALUE,			\
228 		},								\
229 		IF_ENABLED(CONFIG_FLASH_PAGE_LAYOUT,				\
230 			(QSPI_PAGE_LAYOUT(n),))					\
231 		.memory_cfg = QSPI_MEMORY_CFG(n),				\
232 	};									\
233 										\
234 	static struct nxp_s32_qspi_data nxp_s32_qspi_data_##n = {		\
235 		.memory_conn_cfg = QSPI_MEMORY_CONN_CFG(n),			\
236 	};									\
237 										\
238 	DEVICE_DT_INST_DEFINE(n,						\
239 			      nxp_s32_qspi_init,				\
240 			      NULL,						\
241 			      &nxp_s32_qspi_data_##n,				\
242 			      &nxp_s32_qspi_config_##n,				\
243 			      POST_KERNEL,					\
244 			      CONFIG_FLASH_INIT_PRIORITY,			\
245 			      &nxp_s32_qspi_api);
246 
247 DT_INST_FOREACH_STATUS_OKAY(FLASH_NXP_S32_QSPI_INIT_DEVICE)
248