1 /*
2  * Copyright 2023 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT	nxp_s32_qspi
8 
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(nxp_s32_qspi_memc, CONFIG_MEMC_LOG_LEVEL);
11 
12 #include <zephyr/drivers/pinctrl.h>
13 #include <zephyr/sys/util.h>
14 
15 #include <soc.h>
16 #include "memc_nxp_s32_qspi.h"
17 
18 /* Mapping between QSPI chip select signals and devicetree chip select identifiers */
19 #define QSPI_PCSFA1	0
20 #define QSPI_PCSFA2	1
21 #define QSPI_PCSFB1	2
22 #define QSPI_PCSFB2	3
23 
24 struct memc_nxp_s32_qspi_data {
25 	uint8_t instance;
26 };
27 
28 struct memc_nxp_s32_qspi_config {
29 	QuadSPI_Type *base;
30 	const struct pinctrl_dev_config *pincfg;
31 
32 	const Qspi_Ip_ControllerConfigType *controller_cfg;
33 };
34 
get_instance(QuadSPI_Type * base)35 static inline uint8_t get_instance(QuadSPI_Type *base)
36 {
37 	QuadSPI_Type *const base_ptrs[QuadSPI_INSTANCE_COUNT] = IP_QuadSPI_BASE_PTRS;
38 	uint8_t i;
39 
40 	for (i = 0; i < QuadSPI_INSTANCE_COUNT; i++) {
41 		if (base_ptrs[i] == base) {
42 			break;
43 		}
44 	}
45 	__ASSERT_NO_MSG(i < QuadSPI_INSTANCE_COUNT);
46 
47 	return i;
48 }
49 
memc_nxp_s32_qspi_init(const struct device * dev)50 static int memc_nxp_s32_qspi_init(const struct device *dev)
51 {
52 	const struct memc_nxp_s32_qspi_config *config = dev->config;
53 	struct memc_nxp_s32_qspi_data *data = dev->data;
54 	Qspi_Ip_StatusType status;
55 
56 	data->instance = get_instance(config->base);
57 
58 	if (pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT)) {
59 		return -EIO;
60 	}
61 
62 	status = Qspi_Ip_ControllerInit(data->instance, config->controller_cfg);
63 	if (status != STATUS_QSPI_IP_SUCCESS) {
64 		LOG_ERR("Fail to initialize QSPI controller %d (%d)",
65 			data->instance, status);
66 		return -EIO;
67 	}
68 
69 	return 0;
70 }
71 
memc_nxp_s32_qspi_get_instance(const struct device * dev)72 uint8_t memc_nxp_s32_qspi_get_instance(const struct device *dev)
73 {
74 	struct memc_nxp_s32_qspi_data *data = dev->data;
75 
76 	return data->instance;
77 }
78 
79 #define QSPI_DATA_CFG(n)								\
80 	IF_ENABLED(FEATURE_QSPI_DDR, (							\
81 		.dataRate = _CONCAT(QSPI_IP_DATA_RATE_,					\
82 			DT_INST_STRING_UPPER_TOKEN(n, data_rate)),			\
83 		.dataAlign = COND_CODE_1(DT_INST_PROP(n, hold_time_2x),			\
84 			(QSPI_IP_FLASH_DATA_ALIGN_2X_REFCLK),				\
85 			(QSPI_IP_FLASH_DATA_ALIGN_REFCLK)),				\
86 	))
87 
88 #define QSPI_ADDR_CFG(n) \
89 	IF_ENABLED(FEATURE_QSPI_ADDR_CFG, (						\
90 		.columnAddr = DT_INST_PROP_OR(n, column_space, 0),			\
91 		.wordAddresable = DT_INST_PROP(n, word_addressable),			\
92 	))
93 
94 #define QSPI_BYTES_SWAP_ADDR(n)								\
95 	IF_ENABLED(FEATURE_QSPI_BYTES_SWAP_ADDR,					\
96 		(.byteSwap = DT_INST_PROP(n, byte_swapping),))
97 
98 #define QSPI_SAMPLE_DELAY(n)								\
99 	COND_CODE_1(DT_INST_PROP(n, sample_delay_half_cycle),				\
100 		(QSPI_IP_SAMPLE_DELAY_HALFCYCLE_EARLY_DQS),				\
101 		(QSPI_IP_SAMPLE_DELAY_SAME_DQS))
102 
103 #define QSPI_SAMPLE_PHASE(n)								\
104 	COND_CODE_1(DT_INST_PROP(n, sample_phase_inverted),				\
105 		(QSPI_IP_SAMPLE_PHASE_INVERTED),					\
106 		(QSPI_IP_SAMPLE_PHASE_NON_INVERTED))
107 
108 #define QSPI_AHB_BUFFERS(n)								\
109 	{										\
110 		.masters = DT_INST_PROP(n, ahb_buffers_masters),			\
111 		.sizes = DT_INST_PROP(n, ahb_buffers_sizes),				\
112 		.allMasters = (bool)DT_INST_PROP(n, ahb_buffers_all_masters),		\
113 	}
114 
115 #define QSPI_DLL_CFG(n, side, side_upper)						\
116 	IF_ENABLED(FEATURE_QSPI_HAS_DLL, (						\
117 		.dllSettings##side_upper = {						\
118 			.dllMode = _CONCAT(QSPI_IP_DLL_,				\
119 				DT_INST_STRING_UPPER_TOKEN(n, side##_dll_mode)),	\
120 			.freqEnable = DT_INST_PROP(n, side##_dll_freq_enable),		\
121 			.coarseDelay = DT_INST_PROP(n, side##_dll_coarse_delay),	\
122 			.fineDelay = DT_INST_PROP(n, side##_dll_fine_delay),		\
123 			.tapSelect = DT_INST_PROP(n, side##_dll_tap_select),		\
124 			IF_ENABLED(FEATURE_QSPI_DLL_LOOPCONTROL, (			\
125 			.referenceCounter = DT_INST_PROP(n, side##_dll_ref_counter),	\
126 			.resolution = DT_INST_PROP(n, side##_dll_resolution),		\
127 			))								\
128 		},									\
129 	))
130 
131 #define QSPI_READ_MODE(n, side, side_upper)						\
132 	_CONCAT(QSPI_IP_READ_MODE_, DT_INST_STRING_UPPER_TOKEN(n, side##_rx_clock_source))
133 
134 #define QSPI_IDLE_SIGNAL_DRIVE(n, side, side_upper)					\
135 	IF_ENABLED(FEATURE_QSPI_CONFIGURABLE_ISD, (					\
136 		.io2IdleValue##side_upper = (uint8_t)DT_INST_PROP(n, side##_io2_idle_high),\
137 		.io3IdleValue##side_upper = (uint8_t)DT_INST_PROP(n, side##_io3_idle_high),\
138 	))
139 
140 #define QSPI_PORT_SIZE_FN(node_id, side_upper, port)					\
141 	COND_CODE_1(IS_EQ(DT_REG_ADDR(node_id), QSPI_PCSF##side_upper##port),		\
142 		(COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(node_id),				\
143 			(.memSize##side_upper##port = DT_PROP(node_id, size) / 8,),	\
144 			(.memSize##side_upper##port = 0,))),				\
145 		(EMPTY))
146 
147 #define QSPI_PORT_SIZE(n, side_upper)							\
148 	DT_INST_FOREACH_CHILD_VARGS(n, QSPI_PORT_SIZE_FN, side_upper, 1)		\
149 	DT_INST_FOREACH_CHILD_VARGS(n, QSPI_PORT_SIZE_FN, side_upper, 2)
150 
151 #define QSPI_SIDE_CFG(n, side, side_upper)						\
152 	QSPI_IDLE_SIGNAL_DRIVE(n, side, side_upper)					\
153 	QSPI_DLL_CFG(n, side, side_upper)						\
154 	QSPI_PORT_SIZE(n, side_upper)							\
155 	.readMode##side_upper = QSPI_READ_MODE(n, side, side_upper),
156 
157 #define MEMC_NXP_S32_QSPI_CONTROLLER_CONFIG(n)						\
158 	BUILD_ASSERT(DT_INST_PROP_LEN(n, ahb_buffers_masters) == QSPI_IP_AHB_BUFFERS,	\
159 		"ahb-buffers-masters must be of size QSPI_IP_AHB_BUFFERS");		\
160 	BUILD_ASSERT(DT_INST_PROP_LEN(n, ahb_buffers_sizes) == QSPI_IP_AHB_BUFFERS,	\
161 		"ahb-buffers-sizes must be of size QSPI_IP_AHB_BUFFERS");		\
162 	BUILD_ASSERT(									\
163 		_CONCAT(FEATURE_QSPI_, DT_INST_STRING_UPPER_TOKEN(n, a_rx_clock_source)) == 1,\
164 		"a-rx-clock-source source mode selected is not supported");		\
165 											\
166 	static const Qspi_Ip_ControllerConfigType					\
167 	memc_nxp_s32_qspi_controller_cfg_##n = {					\
168 		.csHoldTime = DT_INST_PROP(n, cs_hold_time),				\
169 		.csSetupTime = DT_INST_PROP(n, cs_setup_time),				\
170 		.sampleDelay = QSPI_SAMPLE_DELAY(n),					\
171 		.samplePhase = QSPI_SAMPLE_PHASE(n),					\
172 		.ahbConfig = QSPI_AHB_BUFFERS(n),					\
173 		QSPI_SIDE_CFG(n, a, A)							\
174 		QSPI_DATA_CFG(n)							\
175 		QSPI_ADDR_CFG(n)							\
176 		QSPI_BYTES_SWAP_ADDR(n)							\
177 	}
178 
179 #define MEMC_NXP_S32_QSPI_INIT_DEVICE(n)						\
180 	PINCTRL_DT_INST_DEFINE(n);							\
181 	MEMC_NXP_S32_QSPI_CONTROLLER_CONFIG(n);						\
182 	static struct memc_nxp_s32_qspi_data memc_nxp_s32_qspi_data_##n;		\
183 	static const struct memc_nxp_s32_qspi_config memc_nxp_s32_qspi_config_##n = {	\
184 		.base = (QuadSPI_Type *)DT_INST_REG_ADDR(n),				\
185 		.controller_cfg = &memc_nxp_s32_qspi_controller_cfg_##n,		\
186 		.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),				\
187 	};										\
188 	DEVICE_DT_INST_DEFINE(n,							\
189 		memc_nxp_s32_qspi_init,							\
190 		NULL,									\
191 		&memc_nxp_s32_qspi_data_##n,						\
192 		&memc_nxp_s32_qspi_config_##n,						\
193 		POST_KERNEL,								\
194 		CONFIG_MEMC_INIT_PRIORITY,						\
195 		NULL);
196 
197 DT_INST_FOREACH_STATUS_OKAY(MEMC_NXP_S32_QSPI_INIT_DEVICE)
198