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