• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 /**
17  * @file    wm_hspi.c
18  *
19  * @brief   High speed spi slave Module
20  *
21  * @author  dave
22  *
23  * Copyright (c) 2015 Winner Microelectronics Co., Ltd.
24  */
25 
26 #include "wm_regs.h"
27 #include "wm_config.h"
28 #include "wm_mem.h"
29 #include "wm_osal.h"
30 #include "wm_irq.h"
31 #include "wm_io.h"
32 #include "wm_hspi.h"
33 
34 #if TLS_CONFIG_HS_SPI
35 
36 struct tls_slave_hspi g_slave_hspi;
37 #define SET_BIT(x) (1UL << (x))
38 void hspi_free_rxdesc(struct tls_hspi_rx_desc *rx_desc);
39 
hspi_rx_init(struct tls_slave_hspi * hspi)40 void hspi_rx_init(struct tls_slave_hspi *hspi)
41 {
42     struct tls_hspi_rx_desc *hspi_rx_desc;
43     int i;
44 
45 /* set current availble rx desc pointer */
46     hspi_rx_desc = (struct tls_hspi_rx_desc *) HSPI_RX_DESC_BASE_ADDR;
47     hspi->curr_rx_desc = hspi_rx_desc;
48 
49 /* initialize rx descriptor content */
50     for (i = 0; i < HSPI_RX_DESC_NUM; i++) {
51     /* initialize tx descriptors */
52         if (i < HSPI_RXBUF_NUM) {
53             hspi_rx_desc->valid_ctrl = SET_BIT(31);
54             hspi_rx_desc->buf_addr = HSPI_RXBUF_BASE_ADDR + i * HSPI_RXBUF_SIZE;
55         } else {
56         /* indicate this descriptor is can't use by hspi */
57             hspi_rx_desc->valid_ctrl = 0;
58         /* point to null */
59             hspi_rx_desc->buf_addr = 0x0;
60         }
61 
62         if (i == (HSPI_RX_DESC_NUM - 1)) {
63             hspi_rx_desc->next_desc_addr = (u32) HSPI_RX_DESC_BASE_ADDR;
64         } else {
65             hspi_rx_desc->next_desc_addr = (u32) (hspi_rx_desc + 1);
66         }
67         hspi_rx_desc++;
68     }
69 }
70 
hspi_tx_init(struct tls_slave_hspi * hspi)71 void hspi_tx_init(struct tls_slave_hspi *hspi)
72 {
73     struct tls_hspi_tx_desc *hspi_tx_desc;
74     int i;
75 
76     hspi_tx_desc = (struct tls_hspi_tx_desc *) HSPI_TX_DESC_BASE_ADDR;
77 
78     hspi->curr_tx_desc = hspi_tx_desc;
79 
80     for (i = 0; i < HSPI_TX_DESC_NUM; i++) {
81         hspi_tx_desc->valid_ctrl = 0;
82         hspi_tx_desc->buf_info = 0;
83 #if HSPI_TX_MEM_MALLOC
84         hspi_tx_desc->txbuf_addr = NULL;
85         hspi_tx_desc->buf_addr[0] = 0;
86 #else
87         hspi_tx_desc->buf_addr[0] = HSPI_TXBUF_BASE_ADDR + i * HSPI_TXBUF_SIZE;
88 #endif
89         hspi_tx_desc->buf_addr[1] = 0;
90         hspi_tx_desc->buf_addr[2] = 0;
91         if (i == (HSPI_TX_DESC_NUM - 1)) {
92             hspi_tx_desc->next_desc_addr = (u32) HSPI_TX_DESC_BASE_ADDR;
93         } else {
94             hspi_tx_desc->next_desc_addr = (u32) (hspi_tx_desc + 1);
95         }
96         hspi_tx_desc++;
97     }
98 }
99 
slave_spi_rx_data(struct tls_slave_hspi * hspi)100 static int slave_spi_rx_data(struct tls_slave_hspi *hspi)
101 {
102     struct tls_hspi_rx_desc *rx_desc;
103 
104 /* get rx descriptor */
105     rx_desc = hspi->curr_rx_desc;
106 
107     while (!(rx_desc->valid_ctrl & SET_BIT(31))) {
108         if (hspi->rx_data_callback)
109             hspi->rx_data_callback((char *) rx_desc->buf_addr);
110         hspi_free_rxdesc(rx_desc);
111 
112         rx_desc = (struct tls_hspi_rx_desc *) rx_desc->next_desc_addr;
113         hspi->curr_rx_desc = rx_desc;
114     }
115 
116     return 0;
117 }
118 
SDIO_RX_IRQHandler(void)119 void SDIO_RX_IRQHandler(void)
120 {
121     struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi;
122 
123 #if HSPI_TX_MEM_MALLOC
124     hspi->txdoneflag = 1;
125 #endif
126     if (hspi->tx_data_callback)
127         hspi->tx_data_callback((char *) hspi->curr_tx_desc->buf_addr);
128 /* clear interrupt */
129     tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_DATA_UP);
130 }
131 
SDIO_TX_IRQHandler(void)132 void SDIO_TX_IRQHandler(void)
133 {
134     struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi;
135 
136 // �û�ģʽ�£�ֱ�Ӹ������ݣ������IJ��������⿪�ţ��������������������
137     if (hspi->ifusermode) {
138         slave_spi_rx_data(hspi);
139     } else {
140         if (hspi->rx_data_callback)
141             hspi->rx_data_callback((char *) hspi->curr_rx_desc->buf_addr);
142     }
143 
144 /* clear interrupt */
145     tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_DATA_DOWN);
146 }
147 
SDIO_RX_CMD_IRQHandler(void)148 void SDIO_RX_CMD_IRQHandler(void)
149 {
150     struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi;
151 
152     if (hspi->rx_cmd_callback)
153         hspi->rx_cmd_callback((char *) SDIO_CMD_RXBUF_ADDR);
154 
155     if (hspi->ifusermode) {      // �û�ģʽ�£����ݸ���ȥ֮���Ĵ����������Լ�����
156         tls_reg_write32(HR_SDIO_DOWNCMDVALID, 0x1);
157     }
158 
159 /* clear interrupt */
160     tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_CMD_DOWN);
161 }
162 
HSPI_IRQHandler(void)163 ATTRIBUTE_ISR void HSPI_IRQHandler(void)
164 {
165     printf("spi HS irqhandle\n");
166 }
167 
SDIOA_IRQHandler(void)168 ATTRIBUTE_ISR void SDIOA_IRQHandler(void)
169 {
170     u32 int_src = tls_reg_read32(HR_SDIO_INT_SRC);
171     csi_kernel_intrpt_enter();
172     if (int_src & SDIO_WP_INT_SRC_CMD_DOWN) {
173         SDIO_RX_CMD_IRQHandler();
174     } else if (int_src & SDIO_WP_INT_SRC_DATA_UP) {
175         SDIO_RX_IRQHandler();
176     } else if (int_src & SDIO_WP_INT_SRC_DATA_DOWN) {
177         SDIO_TX_IRQHandler();
178     } else if (int_src & SDIO_WP_INT_SRC_CMD_UP) {
179         tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_CMD_UP);
180     }
181     csi_kernel_intrpt_exit();
182 }
183 
hspi_free_rxdesc(struct tls_hspi_rx_desc * rx_desc)184 void hspi_free_rxdesc(struct tls_hspi_rx_desc *rx_desc)
185 {
186     rx_desc->valid_ctrl = SET_BIT(31);
187 /* ����hspi/sdio tx enable�Ĵ�������sdioӲ��֪���п��õ�tx descriptor */
188     tls_reg_write32(HR_SDIO_TXEN, SET_BIT(0));
189 }
190 
hspi_regs_cfg(void)191 void hspi_regs_cfg(void)
192 {
193     tls_reg_write32(HR_HSPI_CLEAR_FIFO, 0x1);   /* Clear data up&down interrput
194                                                  */
195     tls_reg_write32(HR_HSPI_SPI_CFG, 0);    /* CPOL=0, CPHA=0, Small-Endian */
196     tls_reg_write32(HR_HSPI_MODE_CFG, 0x0);
197     tls_reg_write32(HR_HSPI_INT_MASK, 0x03);
198     tls_reg_write32(HR_HSPI_INT_STTS, 0x03);
199 }
200 
sdio_init_cis(void)201 void sdio_init_cis(void)
202 {
203     tls_reg_write32(FN0_TPL_FUNCID, 0x000C0221);
204     tls_reg_write32(FN0_TPL_FUNCE, 0x00000422);
205     tls_reg_write32(FN0_TPL_FUNCE_MAXBLK, 0x04203208);
206     tls_reg_write32(FN0_TPL_MANFID_MID, 0x53470296);
207     tls_reg_write32(FN0_TPL_END, 0x000000ff);
208 
209     tls_reg_write32(FN1_TPL_FUNCID, 0x000C0221);
210     tls_reg_write32(FN1_TPL_FUNCE, 0x01012a22);
211     tls_reg_write32(FN1_TPL_FUNCE_VER, 0x00000011);
212     tls_reg_write32(FN1_TPL_FUNCE_NSN, 0x02000000);
213     tls_reg_write32(FN1_TPL_FUNCE_CSASIZE, 0x08000300);
214     tls_reg_write32(FN1_TPL_FUNCE_OCR, 0x00FF8000);
215     tls_reg_write32(FN1_TPL_FUNCE_MINPWR, 0x010f0a08);
216     tls_reg_write32(FN1_TPL_FUNCE_STANDBY, 0x00000101);
217     tls_reg_write32(FN1_TPL_FUNCE_OPTBW, 0x00000000);
218     tls_reg_write32(FN1_TPL_FUNCE_NTIMEOUT, 0x00000000);
219     tls_reg_write32(FN1_TPL_FUNCE_AVGPWR, 0x00000000);
220     tls_reg_write32(FN1_TPL_FUNCE_AVGPWR + 4, 0x00000000);
221     tls_reg_write32(FN1_TPL_END, 0x000000ff);
222 }
223 
hsdio_regs_cfg(void)224 void hsdio_regs_cfg(void)
225 {
226     u32 v;
227 
228     sdio_init_cis();
229     tls_reg_write32(HR_SDIO_CIS0, SDIO_CIS0_ADDR - 0x1000);
230     tls_reg_write32(HR_SDIO_CIS1, SDIO_CIS1_ADDR - 0x2000);
231 
232     v = tls_reg_read32(HR_SDIO_CIA);
233     tls_reg_write32(HR_SDIO_CIA, (v & 0xFFFFF000) | 0x232);
234 
235 /* set sdio ready */
236     tls_reg_write32(HR_SDIO_PROG, 0x02FD);
237 }
238 
239 /**
240  * @brief              This function is used to initial HSPI register.
241  *
242  * @param[in]          None
243  *
244  * @retval             0     success
245  * @retval             other failed
246  *
247  * @note               When the system is initialized, the function has been called, so users can not call the function.
248  */
tls_slave_spi_init(void)249 int tls_slave_spi_init(void)
250 {
251     struct tls_slave_hspi *hspi;
252 
253     hspi = &g_slave_hspi;
254     memset_s(hspi, sizeof(hspi), 0, sizeof(struct tls_slave_hspi));
255 
256     hspi_rx_init(hspi);
257     hspi_tx_init(hspi);
258 /* regiseter hspi tx rx cmd interrupt handler */
259 
260 /* setting hw interrupt module isr enable regiset */
261     tls_irq_enable(SDIO_IRQn);
262     tls_irq_enable(SPI_HS_IRQn);
263 
264     /********************************************
265      * setting hspi wrapper registers
266      *********************************************/
267 /* hspi data down(rx) */
268     tls_reg_write32(HR_SDIO_TXBD_ADDR, HSPI_RX_DESC_BASE_ADDR);
269     tls_reg_write32(HR_SDIO_TXBD_LINKEN, 1);
270     tls_reg_write32(HR_SDIO_TXEN, 1);
271 /* hspi data up (tx) */
272     tls_reg_write32(HR_SDIO_RXBD_ADDR, HSPI_TX_DESC_BASE_ADDR);
273     tls_reg_write32(HR_SDIO_RXBD_LINKEN, 1);
274 
275 /* hspi cmd down */
276     tls_reg_write32(HR_SDIO_CMD_ADDR, SDIO_CMD_RXBUF_ADDR);
277     tls_reg_write32(HR_SDIO_CMD_SIZE, SDIO_CMD_RXBUF_SIZE);
278     tls_reg_write32(HR_SDIO_DOWNCMDVALID, 0x1);
279 
280 /* enable sdio module register */
281     tls_reg_write32(HR_SDIO_INT_MASK, 0x00);
282 
283     return 0;
284 }
285 
286 /**
287  * @brief             This function is used to set high speed interface type.
288  *
289  * @param[in]         type    is the interface type. HSPI_INTERFACE_SPI or HSPI_INTERFACE_SDIO
290  *
291  * @return            None
292  *
293  * @note               None
294  */
tls_set_high_speed_interface_type(int type)295 void tls_set_high_speed_interface_type(int type)
296 {
297     if (HSPI_INTERFACE_SPI == type) {
298         hspi_regs_cfg();
299     } else if (HSPI_INTERFACE_SDIO == type) {
300         hsdio_regs_cfg();
301     }
302 }
303 
304 /**
305  * @brief              This function is used to enable or disable user mode.
306  *
307  * @param[in]          ifenable     TRUE or FALSE
308  *
309  * @return             None
310  *
311  * @note               If the user enables the user mode, RICM instruction in the system will not be used by SPI.
312  *                    If the user wants to use the SPI interface as other use, need to enable the user mode.
313  *                    This function must be called before the register function.
314  */
tls_set_hspi_user_mode(u8 ifenable)315 void tls_set_hspi_user_mode(u8 ifenable)
316 {
317     struct tls_slave_hspi *hspi = &g_slave_hspi;
318 
319     hspi->ifusermode = ifenable;
320 
321     if (ifenable) {
322         hspi->rx_cmd_callback = NULL;
323         hspi->rx_data_callback = NULL;
324         hspi->tx_data_callback = NULL;
325     }
326 }
327 
328 /**
329  * @brief              This function is used to register hspi rx command interrupt.
330  *
331  * @param[in]          rx_cmd_callback        is the hspi rx interrupt call back function.
332  *
333  * @return             None
334  *
335  * @note               None
336  */
tls_hspi_rx_cmd_callback_register(s16 (* rx_cmd_callback)(char * buf))337 void tls_hspi_rx_cmd_callback_register(s16(*rx_cmd_callback) (char *buf))
338 {
339     g_slave_hspi.rx_cmd_callback = rx_cmd_callback;
340 }
341 
342 /**
343  * @brief              This function is used to register hspi rx data interrupt.
344  *
345  * @param[in]          rx_data_callback        is the hspi rx interrupt call back function.
346  *
347  * @return             None
348  *
349  * @note               None
350  */
tls_hspi_rx_data_callback_register(s16 (* rx_data_callback)(char * buf))351 void tls_hspi_rx_data_callback_register(s16(*rx_data_callback) (char *buf))
352 {
353     g_slave_hspi.rx_data_callback = rx_data_callback;
354 }
355 
356 /**
357  * @brief              This function is used to register hspi tx data interrupt.
358  *
359  * @param[in]         tx_data_callback        is the hspi tx interrupt call back function.
360  *
361  * @return             None
362  *
363  * @note               None
364  */
tls_hspi_tx_data_callback_register(s16 (* tx_data_callback)(char * buf))365 void tls_hspi_tx_data_callback_register(s16(*tx_data_callback) (char *buf))
366 {
367     g_slave_hspi.tx_data_callback = tx_data_callback;
368 }
369 
370 /**
371  * @brief              This function is used to transfer data.
372  *
373  * @param[in]          txbuf            is a buf for saving user data.
374  * @param[in]          len                     is the data length.
375  *
376  * @retval             transfer data len    success
377  * @retval             0                              failed
378  *
379  * @note               None
380  */
tls_hspi_tx_data(char * txbuf,int len)381 int tls_hspi_tx_data(char *txbuf, int len)
382 {
383     struct tls_hspi_tx_desc *tx_desc;
384     int totallen = len;
385 
386     if (txbuf || len <= 0 || len > (HSPI_TXBUF_SIZE * HSPI_TX_DESC_NUM) == NULL) {
387         printf("\nhspi tx param error\n");
388         return 0;
389     }
390     tx_desc = g_slave_hspi.curr_tx_desc;
391     while (1) {
392         if ((tx_desc->valid_ctrl & SET_BIT(31)) == 0)
393             break;
394         tls_os_time_delay(1);
395     }
396     while (!(tx_desc->valid_ctrl & SET_BIT(31))) {
397         int txlen = (totallen > HSPI_TXBUF_SIZE) ? HSPI_TXBUF_SIZE : totallen;
398 #if HSPI_TX_MEM_MALLOC
399         if (tx_desc->txbuf_addr != NULL) {
400             printf("\nhspi txbuf not null,error %x\n", tx_desc->txbuf_addr);
401             if (tx_desc->txbuf_addr == tx_desc->buf_addr[0]) {
402                 mem_free((void *) tx_desc->txbuf_addr);
403                 tx_desc->txbuf_addr = NULL;
404             } else {               // ��Ӧ�ó���
405                 printf("\nhspi tx mem error\n");
406                 break;
407             }
408         }
409 
410         tx_desc->txbuf_addr = (u32) mem_malloc(txlen + 1);
411         if (tx_desc->txbuf_addr == NULL) {
412             printf("\nhspi tx data malloc error\n");
413             break;
414         }
415         tx_desc->buf_addr[0] = tx_desc->txbuf_addr;
416 #endif
417         MEMCPY((char *) tx_desc->buf_addr[0], txbuf, txlen);
418         tx_desc->buf_info = txlen << 12;
419         tx_desc->valid_ctrl = SET_BIT(31);
420         tls_reg_write32(HR_SDIO_RXEN, 0x01);
421         tx_desc = (struct tls_hspi_tx_desc *) tx_desc->next_desc_addr;
422         g_slave_hspi.curr_tx_desc = tx_desc;
423         totallen -= txlen;
424         if (totallen <= 0)
425             break;
426     }
427     return (len - totallen);
428 }
429 
430 #endif
431 
432