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