| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- /**
- * @file wm_hspi.c
- *
- * @brief High speed spi slave Module
- *
- * @author dave
- *
- * Copyright (c) 2015 Winner Microelectronics Co., Ltd.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "wm_hspi.h"
- #include "wm_regs.h"
- #include "wm_config.h"
- #include "wm_mem.h"
- #include "wm_osal.h"
- #include "wm_irq.h"
- //#include "lwip/mem.h"
- #include "wm_io.h"
- #if 1
- struct tls_slave_hspi g_slave_hspi;
- #define SET_BIT(x) (1UL << (x))
- void hspi_free_rxdesc(struct tls_hspi_rx_desc *rx_desc);
- void hspi_rx_init(struct tls_slave_hspi *hspi)
- {
- struct tls_hspi_rx_desc *hspi_rx_desc;
- int i;
- /* set current availble rx desc pointer */
- hspi_rx_desc = (struct tls_hspi_rx_desc *) HSPI_RX_DESC_BASE_ADDR;
- hspi->curr_rx_desc = hspi_rx_desc;
- /* initialize rx descriptor content */
- for (i = 0; i < HSPI_RX_DESC_NUM; i++)
- {
- /* initialize tx descriptors */
- if (i < HSPI_RXBUF_NUM)
- {
- hspi_rx_desc->valid_ctrl = SET_BIT(31);
- hspi_rx_desc->buf_addr = HSPI_RXBUF_BASE_ADDR + i * HSPI_RXBUF_SIZE;
- }
- else
- {
- /* indicate this descriptor is can't use by hspi */
- hspi_rx_desc->valid_ctrl = 0;
- /* point to null */
- hspi_rx_desc->buf_addr = 0x0;
- }
- if (i == (HSPI_RX_DESC_NUM - 1))
- {
- hspi_rx_desc->next_desc_addr = (u32) HSPI_RX_DESC_BASE_ADDR;
- }
- else
- {
- hspi_rx_desc->next_desc_addr = (u32) (hspi_rx_desc + 1);
- }
- hspi_rx_desc++;
- }
- }
- void hspi_tx_init(struct tls_slave_hspi *hspi)
- {
- struct tls_hspi_tx_desc *hspi_tx_desc;
- int i;
- hspi_tx_desc = (struct tls_hspi_tx_desc *) HSPI_TX_DESC_BASE_ADDR;
- hspi->curr_tx_desc = hspi_tx_desc;
- for (i = 0; i < HSPI_TX_DESC_NUM; i++)
- {
- hspi_tx_desc->valid_ctrl = 0;
- hspi_tx_desc->buf_info = 0;
- #if HSPI_TX_MEM_MALLOC
- hspi_tx_desc->txbuf_addr = NULL;
- hspi_tx_desc->buf_addr[0] = 0;
- #else
- hspi_tx_desc->buf_addr[0] = HSPI_TXBUF_BASE_ADDR + i * HSPI_TXBUF_SIZE;
- #endif
- hspi_tx_desc->buf_addr[1] = 0;
- hspi_tx_desc->buf_addr[2] = 0;
- if (i == (HSPI_TX_DESC_NUM - 1))
- {
- hspi_tx_desc->next_desc_addr = (u32) HSPI_TX_DESC_BASE_ADDR;
- }
- else
- {
- hspi_tx_desc->next_desc_addr = (u32) (hspi_tx_desc + 1);
- }
- hspi_tx_desc++;
- }
- }
- static int slave_spi_rx_data(struct tls_slave_hspi *hspi)
- {
- struct tls_hspi_rx_desc *rx_desc;
- /* get rx descriptor */
- rx_desc = hspi->curr_rx_desc;
- while (!(rx_desc->valid_ctrl & SET_BIT(31)))
- {
- if (hspi->rx_data_callback)
- hspi->rx_data_callback((char *) rx_desc->buf_addr);
- hspi_free_rxdesc(rx_desc);
- rx_desc = (struct tls_hspi_rx_desc *) rx_desc->next_desc_addr;
- hspi->curr_rx_desc = rx_desc;
- }
- return 0;
- }
- void SDIO_RX_IRQHandler(void)
- {
- struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi;
- #if HSPI_TX_MEM_MALLOC
- hspi->txdoneflag = 1;
- #endif
- if (hspi->tx_data_callback)
- hspi->tx_data_callback((char *) hspi->curr_tx_desc->buf_addr);
- /* clear interrupt */
- tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_DATA_UP);
- }
- void SDIO_TX_IRQHandler(void)
- {
- struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi;
- //用户模式下,直接给出数据,链表的操作不对外开放,避免造成链表操作错误
- if (hspi->ifusermode)
- {
- slave_spi_rx_data(hspi);
- }
- else
- {
- if (hspi->rx_data_callback)
- hspi->rx_data_callback((char *) hspi->curr_rx_desc->buf_addr);
- }
- /* clear interrupt */
- tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_DATA_DOWN);
- }
- void SDIO_RX_CMD_IRQHandler(void)
- {
- struct tls_slave_hspi *hspi = (struct tls_slave_hspi *) &g_slave_hspi;
- if (hspi->rx_cmd_callback)
- hspi->rx_cmd_callback((char *) SDIO_CMD_RXBUF_ADDR);
- if (hspi->ifusermode) // 用户模式下,数据给出去之后,寄存器由驱动自己操作
- {
- tls_reg_write32(HR_SDIO_DOWNCMDVALID, 0x1);
- }
- /* clear interrupt */
- tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_CMD_DOWN);
- }
- ATTRIBUTE_ISR void HSPI_IRQHandler(void)
- {
- printf("spi HS irqhandle\n");
- }
- ATTRIBUTE_ISR void SDIOA_IRQHandler(void)
- {
- u32 int_src = tls_reg_read32(HR_SDIO_INT_SRC);
- csi_kernel_intrpt_enter();
- if(int_src & SDIO_WP_INT_SRC_CMD_DOWN)
- {
- SDIO_RX_CMD_IRQHandler();
- }
- else if(int_src & SDIO_WP_INT_SRC_DATA_UP)
- {
- SDIO_RX_IRQHandler();
- }
- else if(int_src & SDIO_WP_INT_SRC_DATA_DOWN)
- {
- SDIO_TX_IRQHandler();
- }
- else if(int_src & SDIO_WP_INT_SRC_CMD_UP)
- {
- tls_reg_write32(HR_SDIO_INT_SRC, SDIO_WP_INT_SRC_CMD_UP);
- }
- csi_kernel_intrpt_exit();
- }
- void hspi_free_rxdesc(struct tls_hspi_rx_desc *rx_desc)
- {
- rx_desc->valid_ctrl = SET_BIT(31);
- /* 设置hspi/sdio tx enable寄存器,让sdio硬件知道有可用的tx descriptor */
- tls_reg_write32(HR_SDIO_TXEN, SET_BIT(0));
- }
- void hspi_regs_cfg(void)
- {
- tls_reg_write32(HR_HSPI_CLEAR_FIFO, 0x1); /* Clear data up&down interrput
- */
- tls_reg_write32(HR_HSPI_SPI_CFG, 0); /* CPOL=0, CPHA=0, Small-Endian */
- tls_reg_write32(HR_HSPI_MODE_CFG, 0x0);
- tls_reg_write32(HR_HSPI_INT_MASK, 0x03);
- tls_reg_write32(HR_HSPI_INT_STTS, 0x03);
- }
- void sdio_init_cis(void)
- {
- tls_reg_write32(FN0_TPL_FUNCID, 0x000C0221);
- tls_reg_write32(FN0_TPL_FUNCE, 0x00000422);
- tls_reg_write32(FN0_TPL_FUNCE_MAXBLK, 0x04203208);
- tls_reg_write32(FN0_TPL_MANFID_MID, 0x53470296);
- tls_reg_write32(FN0_TPL_END, 0x000000ff);
- tls_reg_write32(FN1_TPL_FUNCID, 0x000C0221);
- tls_reg_write32(FN1_TPL_FUNCE, 0x01012a22);
- tls_reg_write32(FN1_TPL_FUNCE_VER, 0x00000011);
- tls_reg_write32(FN1_TPL_FUNCE_NSN, 0x02000000);
- tls_reg_write32(FN1_TPL_FUNCE_CSASIZE, 0x08000300);
- tls_reg_write32(FN1_TPL_FUNCE_OCR, 0x00FF8000);
- tls_reg_write32(FN1_TPL_FUNCE_MINPWR, 0x010f0a08);
- tls_reg_write32(FN1_TPL_FUNCE_STANDBY, 0x00000101);
- tls_reg_write32(FN1_TPL_FUNCE_OPTBW, 0x00000000);
- tls_reg_write32(FN1_TPL_FUNCE_NTIMEOUT, 0x00000000);
- tls_reg_write32(FN1_TPL_FUNCE_AVGPWR, 0x00000000);
- tls_reg_write32(FN1_TPL_FUNCE_AVGPWR + 4, 0x00000000);
- tls_reg_write32(FN1_TPL_END, 0x000000ff);
- }
- void hsdio_regs_cfg(void)
- {
- u32 v;
- sdio_init_cis();
- tls_reg_write32(HR_SDIO_CIS0, SDIO_CIS0_ADDR - 0x1000);
- tls_reg_write32(HR_SDIO_CIS1, SDIO_CIS1_ADDR - 0x2000);
- v = tls_reg_read32(HR_SDIO_CIA);
- tls_reg_write32(HR_SDIO_CIA, (v & 0xFFFFF000) | 0x232);
- /* set sdio ready */
- tls_reg_write32(HR_SDIO_PROG, 0x02FD);
- }
- /**
- * @brief This function is used to initial HSPI register.
- *
- * @param[in] None
- *
- * @retval 0 success
- * @retval other failed
- *
- * @note When the system is initialized, the function has been called, so users can not call the function.
- */
- int tls_slave_spi_init(void)
- {
- struct tls_slave_hspi *hspi;
- hspi = &g_slave_hspi;
- memset(hspi, 0, sizeof(struct tls_slave_hspi));
- hspi_rx_init(hspi);
- hspi_tx_init(hspi);
- // tls_set_high_speed_interface_type(HSPI_INTERFACE_SPI);
- /* regiseter hspi tx rx cmd interrupt handler */
- /* setting hw interrupt module isr enable regiset */
- tls_irq_enable(SDIO_IRQn);
- tls_irq_enable(SPI_HS_IRQn);
- /********************************************
- * setting hspi wrapper registers
- *********************************************/
- /* hspi data down(rx) */
- tls_reg_write32(HR_SDIO_TXBD_ADDR, HSPI_RX_DESC_BASE_ADDR);
- tls_reg_write32(HR_SDIO_TXBD_LINKEN, 1);
- tls_reg_write32(HR_SDIO_TXEN, 1);
- /* hspi data up (tx) */
- tls_reg_write32(HR_SDIO_RXBD_ADDR, HSPI_TX_DESC_BASE_ADDR);
- tls_reg_write32(HR_SDIO_RXBD_LINKEN, 1);
- /* hspi cmd down */
- tls_reg_write32(HR_SDIO_CMD_ADDR, SDIO_CMD_RXBUF_ADDR);
- tls_reg_write32(HR_SDIO_CMD_SIZE, SDIO_CMD_RXBUF_SIZE);
- tls_reg_write32(HR_SDIO_DOWNCMDVALID, 0x1);
- /* enable sdio module register */
- tls_reg_write32(HR_SDIO_INT_MASK, 0x00);
- return 0;
- }
- /**
- * @brief This function is used to set high speed interface type.
- *
- * @param[in] type is the interface type. HSPI_INTERFACE_SPI or HSPI_INTERFACE_SDIO
- *
- * @return None
- *
- * @note None
- */
- void tls_set_high_speed_interface_type(int type)
- {
- if (HSPI_INTERFACE_SPI == type)
- {
- hspi_regs_cfg();
- }
- else if (HSPI_INTERFACE_SDIO == type)
- {
- hsdio_regs_cfg();
- }
- }
- /**
- * @brief This function is used to enable or disable user mode.
- *
- * @param[in] ifenable TRUE or FALSE
- *
- * @return None
- *
- * @note If the user enables the user mode, RICM instruction in the system will not be used by SPI.
- * If the user wants to use the SPI interface as other use, need to enable the user mode.
- * This function must be called before the register function.
- */
- void tls_set_hspi_user_mode(u8 ifenable)
- {
- struct tls_slave_hspi *hspi = &g_slave_hspi;
- hspi->ifusermode = ifenable;
- if (ifenable)
- {
- hspi->rx_cmd_callback = NULL;
- hspi->rx_data_callback = NULL;
- hspi->tx_data_callback = NULL;
- }
- }
- /**
- * @brief This function is used to register hspi rx command interrupt.
- *
- * @param[in] rx_cmd_callback is the hspi rx interrupt call back function.
- *
- * @return None
- *
- * @note None
- */
- void tls_hspi_rx_cmd_callback_register(s16(*rx_cmd_callback) (char *buf))
- {
- g_slave_hspi.rx_cmd_callback = rx_cmd_callback;
- }
- /**
- * @brief This function is used to register hspi rx data interrupt.
- *
- * @param[in] rx_data_callback is the hspi rx interrupt call back function.
- *
- * @return None
- *
- * @note None
- */
- void tls_hspi_rx_data_callback_register(s16(*rx_data_callback) (char *buf))
- {
- g_slave_hspi.rx_data_callback = rx_data_callback;
- }
- /**
- * @brief This function is used to register hspi tx data interrupt.
- *
- * @param[in] tx_data_callback is the hspi tx interrupt call back function.
- *
- * @return None
- *
- * @note None
- */
- void tls_hspi_tx_data_callback_register(s16(*tx_data_callback) (char *buf))
- {
- g_slave_hspi.tx_data_callback = tx_data_callback;
- }
- /**
- * @brief This function is used to transfer data.
- *
- * @param[in] txbuf is a buf for saving user data.
- * @param[in] len is the data length.
- *
- * @retval transfer data len success
- * @retval 0 failed
- *
- * @note None
- */
- int tls_hspi_tx_data(char *txbuf, int len)
- {
- struct tls_hspi_tx_desc *tx_desc;
- int totallen = len;
- int txlen;
- if (NULL == txbuf || len <= 0 || len > (HSPI_TXBUF_SIZE * HSPI_TX_DESC_NUM))
- {
- printf("\nhspi tx param error\n");
- return 0;
- }
- tx_desc = g_slave_hspi.curr_tx_desc;
- while (1)
- {
- if ((tx_desc->valid_ctrl & SET_BIT(31)) == 0)
- break;
- tls_os_time_delay(1);
- }
- while (!(tx_desc->valid_ctrl & SET_BIT(31)))
- {
- txlen = (totallen > HSPI_TXBUF_SIZE) ? HSPI_TXBUF_SIZE : totallen;
- #if HSPI_TX_MEM_MALLOC
- if (tx_desc->txbuf_addr != NULL)
- {
- printf("\nhspi txbuf not null,error %x\n", tx_desc->txbuf_addr);
- if (tx_desc->txbuf_addr == tx_desc->buf_addr[0])
- {
- mem_free((void *) tx_desc->txbuf_addr);
- tx_desc->txbuf_addr = NULL;
- }
- else // 不应该出现
- {
- printf("\nhspi tx mem error\n");
- break;
- }
- }
- tx_desc->txbuf_addr = (u32) mem_malloc(txlen + 1);
- if (NULL == tx_desc->txbuf_addr)
- {
- printf("\nhspi tx data malloc error\n");
- break;
- }
- tx_desc->buf_addr[0] = tx_desc->txbuf_addr;
- #endif
- MEMCPY((char *) tx_desc->buf_addr[0], txbuf, txlen);
- tx_desc->buf_info = txlen << 12;
- tx_desc->valid_ctrl = SET_BIT(31);
- tls_reg_write32(HR_SDIO_RXEN, 0x01);
- tx_desc = (struct tls_hspi_tx_desc *) tx_desc->next_desc_addr;
- g_slave_hspi.curr_tx_desc = tx_desc;
- totallen -= txlen;
- if (totallen <= 0)
- break;
- }
- return (len - totallen);
- }
- #endif
- int tls_hspi_writable(void) {
- struct tls_hspi_tx_desc *tx_desc;
- tx_desc = g_slave_hspi.curr_tx_desc;
- return (tx_desc->valid_ctrl & SET_BIT(31)) == 0;
- }
|