1 /*
2 * Copyright (c) 2023 Renesas Electronics Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT renesas_smartbond_nor_psram
8
9 #include <zephyr/device.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/irq.h>
12 #include <DA1469xAB.h>
13 #include <zephyr/pm/device.h>
14 #include <da1469x_qspic.h>
15 #include <da1469x_pd.h>
16
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(smartbond_nor_psram, CONFIG_MEMC_LOG_LEVEL);
19
20 #define CLK_AMBA_REG_SET_FIELD(_field, _var, _val) \
21 ((_var)) = \
22 ((_var) & ~(CRG_TOP_CLK_AMBA_REG_ ## _field ## _Msk)) | \
23 (((_val) << CRG_TOP_CLK_AMBA_REG_ ## _field ## _Pos) & \
24 CRG_TOP_CLK_AMBA_REG_ ## _field ## _Msk)
25
26 #define QSPIC2_CTRLMODE_REG_SET_FIELD(_field, _var, _val) \
27 ((_var)) = \
28 ((_var) & ~(QSPIC2_QSPIC2_CTRLMODE_REG_ ## _field ## _Msk)) | \
29 (((_val) << QSPIC2_QSPIC2_CTRLMODE_REG_ ## _field ## _Pos) & \
30 QSPIC2_QSPIC2_CTRLMODE_REG_ ## _field ## _Msk)
31
32 #define QSPIC2_BURSTCMDA_REG_SET_FIELD(_field, _var, _val) \
33 ((_var)) = \
34 ((_var) & ~(QSPIC2_QSPIC2_BURSTCMDA_REG_ ## _field ## _Msk)) | \
35 (((_val) << QSPIC2_QSPIC2_BURSTCMDA_REG_ ## _field ## _Pos) & \
36 QSPIC2_QSPIC2_BURSTCMDA_REG_ ## _field ## _Msk)
37
38 #define QSPIC2_BURSTCMDB_REG_SET_FIELD(_field, _var, _val) \
39 ((_var)) = \
40 ((_var) & ~(QSPIC2_QSPIC2_BURSTCMDB_REG_ ## _field ## _Msk)) | \
41 (((_val) << QSPIC2_QSPIC2_BURSTCMDB_REG_ ## _field ## _Pos) & \
42 QSPIC2_QSPIC2_BURSTCMDB_REG_ ## _field ## _Msk)
43
44 #define QSPIC2_AWRITECMD_REG_SET_FIELD(_field, _var, _val) \
45 ((_var)) = \
46 ((_var) & ~(QSPIC2_QSPIC2_AWRITECMD_REG_ ## _field ## _Msk)) | \
47 (((_val) << QSPIC2_QSPIC2_AWRITECMD_REG_ ## _field ## _Pos) & \
48 QSPIC2_QSPIC2_AWRITECMD_REG_ ## _field ## _Msk)
49
memc_set_status(bool status,int clk_div)50 static void memc_set_status(bool status, int clk_div)
51 {
52 unsigned int key;
53 uint32_t clk_amba_reg;
54
55 /* Clock AMBA register might be accessed by multiple driver classes */
56 key = irq_lock();
57 clk_amba_reg = CRG_TOP->CLK_AMBA_REG;
58
59 if (status) {
60 CLK_AMBA_REG_SET_FIELD(QSPI2_ENABLE, clk_amba_reg, 1);
61 CLK_AMBA_REG_SET_FIELD(QSPI2_DIV, clk_amba_reg, clk_div);
62 } else {
63 CLK_AMBA_REG_SET_FIELD(QSPI2_ENABLE, clk_amba_reg, 0);
64 }
65
66 CRG_TOP->CLK_AMBA_REG = clk_amba_reg;
67 irq_unlock(key);
68 }
69
memc_automode_configure(void)70 static void memc_automode_configure(void)
71 {
72 uint32_t reg;
73
74 reg = QSPIC2->QSPIC2_CTRLMODE_REG;
75 QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_SRAM_EN, reg,
76 DT_INST_PROP(0, is_ram));
77 QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_USE_32BA, reg,
78 DT_INST_ENUM_IDX(0, addr_range));
79 QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_CLK_MD, reg,
80 DT_INST_ENUM_IDX(0, clock_mode));
81 QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_AUTO_MD, reg, 1);
82 QSPIC2->QSPIC2_CTRLMODE_REG = reg;
83
84 reg = QSPIC2->QSPIC2_BURSTCMDA_REG;
85 QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_DMY_TX_MD, reg,
86 DT_INST_ENUM_IDX(0, rx_dummy_mode));
87 QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_ADR_TX_MD, reg,
88 DT_INST_ENUM_IDX(0, rx_addr_mode));
89 QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_INST_TX_MD, reg,
90 DT_INST_ENUM_IDX(0, rx_inst_mode));
91 #if DT_INST_PROP(0, extra_byte_enable)
92 QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_EXT_TX_MD, reg,
93 DT_INST_ENUM_IDX(0, rx_extra_mode));
94 #endif
95 QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_INST, reg,
96 DT_INST_PROP(0, read_cmd));
97 #if DT_INST_PROP(0, extra_byte_enable)
98 QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_EXT_BYTE, reg,
99 DT_INST_PROP(0, extra_byte));
100 #endif
101 QSPIC2->QSPIC2_BURSTCMDA_REG = reg;
102
103 reg = QSPIC2->QSPIC2_BURSTCMDB_REG;
104 QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_DMY_NUM, reg,
105 DT_INST_ENUM_IDX(0, dummy_bytes_count));
106 QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_DAT_RX_MD, reg,
107 DT_INST_ENUM_IDX(0, rx_data_mode));
108 QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_INST_MD, reg, 0);
109 QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_EXT_BYTE_EN, reg,
110 DT_INST_PROP(0, extra_byte_enable));
111 QSPIC2->QSPIC2_BURSTCMDB_REG = reg;
112
113 reg = QSPIC2->QSPIC2_AWRITECMD_REG;
114 QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_DAT_TX_MD, reg,
115 DT_INST_ENUM_IDX(0, tx_data_mode));
116 QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_ADR_TX_MD, reg,
117 DT_INST_ENUM_IDX(0, tx_addr_mode));
118 QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_INST_TX_MD, reg,
119 DT_INST_ENUM_IDX(0, tx_inst_mode));
120 QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_INST, reg,
121 DT_INST_PROP(0, write_cmd));
122 QSPIC2->QSPIC2_AWRITECMD_REG = reg;
123 }
124
125 /* Read PSRAM/NOR device ID using JEDEC commands. */
memc_jedec_read_and_verify_id(QSPIC_TYPE qspi_id)126 static bool memc_jedec_read_and_verify_id(QSPIC_TYPE qspi_id)
127 {
128 uint16_t device_density;
129 bool ret = 0;
130 qspi_memory_id_t memory_id;
131
132 da1469x_qspi_memory_jedec_read_id(qspi_id, &memory_id);
133
134 device_density = DT_INST_PROP(0, dev_density);
135 ret |= !(memory_id.id == DT_INST_PROP(0, dev_id));
136 ret |= !(memory_id.type == DT_INST_PROP(0, dev_type));
137 ret |= !((memory_id.density & (device_density >> 8)) == (device_density & 0xFF));
138
139 return ret;
140 }
141
memc_smartbond_init(const struct device * dev)142 static int memc_smartbond_init(const struct device *dev)
143 {
144 uint32_t qspic_ctrlmode_reg;
145
146 /* First QSPI controller is enabled so registers can be accessed */
147 memc_set_status(true, DT_INST_PROP_OR(0, clock_div, 0));
148
149 /* Apply the min. required settings before performing any transaction in manual mode. */
150 qspic_ctrlmode_reg = QSPIC2->QSPIC2_CTRLMODE_REG;
151 QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_CLK_MD, qspic_ctrlmode_reg,
152 DT_INST_ENUM_IDX(0, clock_mode));
153 QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_AUTO_MD, qspic_ctrlmode_reg, 0);
154 QSPIC2->QSPIC2_CTRLMODE_REG = qspic_ctrlmode_reg;
155
156 /* Reset PSRAM/NOR device using JDEC commands */
157 da1469x_qspi_memory_jedec_reset(QSPIC2_ID);
158
159 /* Wait till reset is completed */
160 k_usleep(DT_INST_PROP(0, reset_delay_us));
161
162 if (memc_jedec_read_and_verify_id(QSPIC2_ID)) {
163 LOG_ERR("Device detection failed");
164 memc_set_status(false, 0);
165
166 return -EINVAL;
167 }
168
169 #if DT_INST_PROP(0, enter_qpi_mode)
170 da1469x_qspi_enter_exit_qpi_mode(QSPIC2_ID, true, DT_INST_PROP(0, enter_qpi_cmd));
171 #endif
172
173 /* Should be called prior to switching to auto mode and when the quad bus is selected! */
174 da1469x_qspi_set_bus_mode(QSPIC2_ID, QSPI_BUS_MODE_QUAD);
175
176 da1469x_pd_acquire(MCU_PD_DOMAIN_SYS);
177
178 /* From this point onwards memory device should be seen as memory mapped device. */
179 memc_automode_configure();
180
181 return 0;
182 }
183
184 #ifdef CONFIG_PM_DEVICE
memc_smartbond_pm_action(const struct device * dev,enum pm_device_action action)185 static int memc_smartbond_pm_action(const struct device *dev, enum pm_device_action action)
186 {
187 switch (action) {
188 case PM_DEVICE_ACTION_SUSPEND:
189 /*
190 * CLK_AMBA_REG, that controlls QSPIC2, is retained during sleep
191 * (resides in PD_AON). However, unused blocks should be disabled
192 * to minimize power consumption at sleep.
193 */
194 memc_set_status(false, 0);
195
196 da1469x_pd_release(MCU_PD_DOMAIN_SYS);
197 break;
198 case PM_DEVICE_ACTION_RESUME:
199
200 /*
201 * Mainly, required when in PM runtime mode. When in PM static mode,
202 * the device will block till an ongoing/pending AMBA bus transfer
203 * completes.
204 */
205 da1469x_pd_acquire(MCU_PD_DOMAIN_SYS);
206
207 /*
208 * QSPIC2 is powered by PD_SYS which is turned off during sleep and
209 * so QSPIC2 auto mode re-initialization is required.
210 *
211 * XXX: It's assumed that memory device's power rail, that should
212 * be 1V8P, is not turned off and so the device itsef does not
213 * require re-initialization. Revisit this part if power settings
214 * are changed in the future, that should include:
215 *
216 * 1. Powering off the memory device by turning off 1V8P
217 * (valid for FLASH/PSRAM).
218 * 2. Powering down the memory device so it enters the suspend/low-power
219 * state during sleep (valid for FLASH/NOR devices).
220 */
221 memc_set_status(true, DT_INST_PROP_OR(0, clock_div, 0));
222 memc_automode_configure();
223 default:
224 return -ENOTSUP;
225 }
226
227 return 0;
228 }
229 #endif
230
231 #define SMARTBOND_MEMC_INIT(inst) \
232 BUILD_ASSERT(inst == 0, "multiple instances are not permitted"); \
233 BUILD_ASSERT(DT_INST_PROP(inst, is_ram), \
234 "current driver version suports only PSRAM devices"); \
235 \
236 PM_DEVICE_DT_INST_DEFINE(inst, memc_smartbond_pm_action); \
237 \
238 DEVICE_DT_INST_DEFINE(inst, memc_smartbond_init, PM_DEVICE_DT_INST_GET(inst), \
239 NULL, NULL, \
240 POST_KERNEL, CONFIG_MEMC_INIT_PRIORITY, NULL);
241
242 DT_INST_FOREACH_STATUS_OKAY(SMARTBOND_MEMC_INIT)
243