1 /**************************************************************************//**
2 *
3 * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date Author Notes
9 * 2021-6-1 Wayne First version
10 *
11 ******************************************************************************/
12
13 #include <rtthread.h>
14 #include <rtdevice.h>
15 #include "drv_gpio.h"
16 #include "drv_sys.h"
17 #include "drv_sspcc.h"
18
19 #include "board.h"
20
21
22 #if defined(BOARD_USING_STORAGE_SPIFLASH)
23 #if defined(RT_USING_SFUD)
24 #include "dev_spi_flash.h"
25 #include "dev_spi_flash_sfud.h"
26 #endif
27
28 #include "drv_qspi.h"
29
30 #define W25X_REG_READSTATUS (0x05)
31 #define W25X_REG_READSTATUS2 (0x35)
32 #define W25X_REG_WRITEENABLE (0x06)
33 #define W25X_REG_WRITESTATUS (0x01)
34 #define W25X_REG_QUADENABLE (0x02)
35
SpiFlash_ReadStatusReg(struct rt_qspi_device * qspi_device)36 static rt_uint8_t SpiFlash_ReadStatusReg(struct rt_qspi_device *qspi_device)
37 {
38 rt_uint8_t u8Val;
39 rt_err_t result = RT_EOK;
40 rt_uint8_t w25x_txCMD1 = W25X_REG_READSTATUS;
41
42 result = rt_qspi_send_then_recv(qspi_device, &w25x_txCMD1, 1, &u8Val, 1);
43 RT_ASSERT(result > 0);
44
45 return u8Val;
46 }
47
SpiFlash_ReadStatusReg2(struct rt_qspi_device * qspi_device)48 static rt_uint8_t SpiFlash_ReadStatusReg2(struct rt_qspi_device *qspi_device)
49 {
50 rt_uint8_t u8Val;
51 rt_err_t result = RT_EOK;
52 rt_uint8_t w25x_txCMD1 = W25X_REG_READSTATUS2;
53
54 result = rt_qspi_send_then_recv(qspi_device, &w25x_txCMD1, 1, &u8Val, 1);
55 RT_ASSERT(result > 0);
56
57 return u8Val;
58 }
59
SpiFlash_WriteStatusReg(struct rt_qspi_device * qspi_device,uint8_t u8Value1,uint8_t u8Value2)60 static rt_err_t SpiFlash_WriteStatusReg(struct rt_qspi_device *qspi_device, uint8_t u8Value1, uint8_t u8Value2)
61 {
62 rt_uint8_t w25x_txCMD1;
63 rt_uint8_t au8Val[2];
64 rt_err_t result;
65 struct rt_qspi_message qspi_message = {0};
66
67 /* Enable WE */
68 w25x_txCMD1 = W25X_REG_WRITEENABLE;
69 result = rt_qspi_send(qspi_device, &w25x_txCMD1, sizeof(w25x_txCMD1));
70 if (result != sizeof(w25x_txCMD1))
71 goto exit_SpiFlash_WriteStatusReg;
72
73 /* Prepare status-1, 2 data */
74 au8Val[0] = u8Value1;
75 au8Val[1] = u8Value2;
76
77 /* 1-bit mode: Instruction+payload */
78 qspi_message.instruction.content = W25X_REG_WRITESTATUS;
79 qspi_message.instruction.qspi_lines = 1;
80
81 qspi_message.qspi_data_lines = 1;
82 qspi_message.parent.cs_take = 1;
83 qspi_message.parent.cs_release = 1;
84 qspi_message.parent.send_buf = &au8Val[0];
85 qspi_message.parent.length = sizeof(au8Val);
86 qspi_message.parent.next = RT_NULL;
87
88 if (rt_qspi_transfer_message(qspi_device, &qspi_message) != sizeof(au8Val))
89 {
90 result = -RT_ERROR;
91 }
92
93 result = RT_EOK;
94
95 exit_SpiFlash_WriteStatusReg:
96
97 return result;
98 }
99
SpiFlash_WaitReady(struct rt_qspi_device * qspi_device)100 static void SpiFlash_WaitReady(struct rt_qspi_device *qspi_device)
101 {
102 volatile uint8_t u8ReturnValue;
103
104 do
105 {
106 u8ReturnValue = SpiFlash_ReadStatusReg(qspi_device);
107 u8ReturnValue = u8ReturnValue & 1;
108 }
109 while (u8ReturnValue != 0); // check the BUSY bit
110 }
111
SpiFlash_EnterQspiMode(struct rt_qspi_device * qspi_device)112 static void SpiFlash_EnterQspiMode(struct rt_qspi_device *qspi_device)
113 {
114 rt_err_t result = RT_EOK;
115
116 uint8_t u8Status1 = SpiFlash_ReadStatusReg(qspi_device);
117 uint8_t u8Status2 = SpiFlash_ReadStatusReg2(qspi_device);
118
119 u8Status2 |= W25X_REG_QUADENABLE;
120
121 result = SpiFlash_WriteStatusReg(qspi_device, u8Status1, u8Status2);
122 RT_ASSERT(result == RT_EOK);
123
124 SpiFlash_WaitReady(qspi_device);
125 }
126
SpiFlash_ExitQspiMode(struct rt_qspi_device * qspi_device)127 static void SpiFlash_ExitQspiMode(struct rt_qspi_device *qspi_device)
128 {
129 rt_err_t result = RT_EOK;
130 uint8_t u8Status1 = SpiFlash_ReadStatusReg(qspi_device);
131 uint8_t u8Status2 = SpiFlash_ReadStatusReg2(qspi_device);
132
133 u8Status2 &= ~W25X_REG_QUADENABLE;
134
135 result = SpiFlash_WriteStatusReg(qspi_device, u8Status1, u8Status2);
136 RT_ASSERT(result == RT_EOK);
137
138 SpiFlash_WaitReady(qspi_device);
139 }
140
rt_hw_spiflash_init(void)141 static int rt_hw_spiflash_init(void)
142 {
143 if (nu_qspi_bus_attach_device("qspi0", "qspi01", 4, SpiFlash_EnterQspiMode, SpiFlash_ExitQspiMode) != RT_EOK)
144 return -1;
145
146 #if defined(RT_USING_SFUD)
147 if (rt_sfud_flash_probe(FAL_USING_NOR_FLASH_DEV_NAME, "qspi01") == RT_NULL)
148 {
149 return -(RT_ERROR);
150 }
151 #endif
152 return 0;
153 }
154 INIT_DEVICE_EXPORT(rt_hw_spiflash_init);
155 #endif /* BOARD_USING_STORAGE_SPIFLASH */
156
157 #if defined(BOARD_USING_STORAGE_SPINAND) && defined(NU_PKG_USING_SPINAND)
158
159 #include "drv_qspi.h"
160 #include "spinand.h"
161
162 struct rt_mtd_nand_device mtd_partitions[MTD_SPINAND_PARTITION_NUM] =
163 {
164 [0] =
165 {
166 /*nand0: U-boot, env, rtthread*/
167 .block_start = 0,
168 .block_end = 63,
169 .block_total = 64,
170 },
171 [1] =
172 {
173 /*nand1: for filesystem mounting*/
174 .block_start = 64,
175 .block_end = 4095,
176 .block_total = 4032,
177 },
178 [2] =
179 {
180 /*nand2: Whole blocks size, overlay*/
181 .block_start = 0,
182 .block_end = 4095,
183 .block_total = 4096,
184 }
185 };
186
rt_hw_spinand_init(void)187 static int rt_hw_spinand_init(void)
188 {
189 if (nu_qspi_bus_attach_device("qspi0", "qspi01", 4, RT_NULL, RT_NULL) != RT_EOK)
190 return -1;
191
192 if (rt_hw_mtd_spinand_register("qspi01") != RT_EOK)
193 return -1;
194
195 return 0;
196 }
197
198 INIT_DEVICE_EXPORT(rt_hw_spinand_init);
199 #endif
200
201 #if defined(BOARD_USING_STORAGE_RAWNAND) && defined(BSP_USING_NFI)
202 struct rt_mtd_nand_device mtd_partitions_nfi[MTD_NFI_PARTITION_NUM] =
203 {
204 [0] =
205 {
206 /*nand0: rtthread*/
207 .block_start = 0,
208 .block_end = 63,
209 .block_total = 64,
210 },
211 [1] =
212 {
213 /*nand1: for filesystem mounting*/
214 .block_start = 64,
215 .block_end = 8191,
216 .block_total = 8128,
217 },
218 [2] =
219 {
220 /*nand2: Whole blocks size, overlay*/
221 .block_start = 0,
222 .block_end = 8191,
223 .block_total = 8192,
224 }
225 };
226 #endif
227
228 #if defined(BOARD_USING_NAU8822) && defined(NU_PKG_USING_NAU8822)
229 #include <acodec_nau8822.h>
230 S_NU_NAU8822_CONFIG sCodecConfig =
231 {
232 .i2c_bus_name = "i2c1",
233
234 .i2s_bus_name = "sound0",
235
236 .pin_phonejack_en = NU_GET_PININDEX(NU_PC, 2),
237
238 .pin_phonejack_det = NU_GET_PININDEX(NU_PC, 3),
239 };
240
rt_hw_nau8822_port(void)241 int rt_hw_nau8822_port(void)
242 {
243 if (nu_hw_nau8822_init(&sCodecConfig) != RT_EOK)
244 return -1;
245
246 return 0;
247 }
248 INIT_COMPONENT_EXPORT(rt_hw_nau8822_port);
249 #endif /* BOARD_USING_NAU8822 */
250
251
252 #if defined(BOARD_USING_SENSOR0)
253 #include "ccap_sensor.h"
254
255 #define SENSOR0_RST_PIN NU_GET_PININDEX(NU_PM, 1)
256 #define SENSOR0_PD_PIN NU_GET_PININDEX(NU_PC, 12)
257
258 ccap_sensor_io sIo_sensor0 =
259 {
260 .RstPin = SENSOR0_RST_PIN,
261 .PwrDwnPin = SENSOR0_PD_PIN,
262 .I2cName = "i2c2"
263 };
264 #endif /* BOARD_USING_SENSOR0 */
rt_hw_sensors_port(void)265 int rt_hw_sensors_port(void)
266 {
267 #if defined(BOARD_USING_SENSOR0)
268 nu_ccap_sensor_create(&sIo_sensor0, (ccap_sensor_id)BOARD_USING_SENSON0_ID, "sensor0");
269 #endif
270 return 0;
271 }
272 INIT_COMPONENT_EXPORT(rt_hw_sensors_port);
nu_rtp_sspcc_setup(void)273 void nu_rtp_sspcc_setup(void)
274 {
275 /* PDMA2/3 */
276 SSPCC_SET_REALM(SSPCC_PDMA2, SSPCC_SSET_SUBM);
277 SSPCC_SET_REALM(SSPCC_PDMA3, SSPCC_SSET_SUBM);
278 }
279
280 static S_NU_REG s_NuReg_arr[] =
281 {
282 /* QSPI0 */
283 NUREG_EXPORT(CLK_CLKSEL4, CLK_CLKSEL4_QSPI0SEL_Msk, CLK_CLKSEL4_QSPI0SEL_PCLK0),
284 NUREG_EXPORT(CLK_APBCLK1, CLK_APBCLK1_QSPI0CKEN_Msk, CLK_APBCLK1_QSPI0CKEN_Msk),
285 NUREG_EXPORT(SYS_GPD_MFPL, SYS_GPD_MFPL_PD5MFP_Msk, SYS_GPD_MFPL_PD5MFP_QSPI0_MISO1),
286 NUREG_EXPORT(SYS_GPD_MFPL, SYS_GPD_MFPL_PD4MFP_Msk, SYS_GPD_MFPL_PD4MFP_QSPI0_MOSI1),
287 NUREG_EXPORT(SYS_GPD_MFPL, SYS_GPD_MFPL_PD3MFP_Msk, SYS_GPD_MFPL_PD3MFP_QSPI0_MISO0),
288 NUREG_EXPORT(SYS_GPD_MFPL, SYS_GPD_MFPL_PD2MFP_Msk, SYS_GPD_MFPL_PD2MFP_QSPI0_MOSI0),
289 NUREG_EXPORT(SYS_GPD_MFPL, SYS_GPD_MFPL_PD1MFP_Msk, SYS_GPD_MFPL_PD1MFP_QSPI0_CLK),
290 NUREG_EXPORT(SYS_GPD_MFPL, SYS_GPD_MFPL_PD0MFP_Msk, SYS_GPD_MFPL_PD0MFP_QSPI0_SS0),
291
292 /* TIMERn */
293 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR0CKEN_Msk, CLK_APBCLK0_TMR0CKEN_Msk),
294 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR1CKEN_Msk, CLK_APBCLK0_TMR1CKEN_Msk),
295 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR2CKEN_Msk, CLK_APBCLK0_TMR2CKEN_Msk),
296 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR3CKEN_Msk, CLK_APBCLK0_TMR3CKEN_Msk),
297 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR4CKEN_Msk, CLK_APBCLK0_TMR4CKEN_Msk),
298 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR5CKEN_Msk, CLK_APBCLK0_TMR5CKEN_Msk),
299 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR6CKEN_Msk, CLK_APBCLK0_TMR6CKEN_Msk),
300 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR7CKEN_Msk, CLK_APBCLK0_TMR7CKEN_Msk),
301 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR8CKEN_Msk, CLK_APBCLK0_TMR8CKEN_Msk),
302 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR9CKEN_Msk, CLK_APBCLK0_TMR9CKEN_Msk),
303 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR10CKEN_Msk, CLK_APBCLK0_TMR10CKEN_Msk),
304 NUREG_EXPORT(CLK_APBCLK0, CLK_APBCLK0_TMR11CKEN_Msk, CLK_APBCLK0_TMR11CKEN_Msk),
305 {0}
306 };
307
nu_check_register(void)308 void nu_check_register(void)
309 {
310 nu_sys_check_register(&s_NuReg_arr[0]);
311 }
312 MSH_CMD_EXPORT(nu_check_register, Check registers);
313