bl_iot_sdk/components/hal_drv/bl602_hal/hal_spi.c
2020-10-26 20:35:25 +08:00

795 lines
23 KiB
C

/*
* Copyright (c) 2020 Bouffalolab.
*
* This file is part of
* *** Bouffalolab Software Dev Kit ***
* (see www.bouffalolab.com).
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <stdio.h>
#include <device/vfs_spi.h>
#include <vfs_err.h>
#include <vfs_register.h>
#include <hal/soc/spi.h>
#include <aos/kernel.h>
#include <bl_dma.h>
#include <bl_gpio.h>
#include <bl602_spi.h>
#include <bl602_gpio.h>
#include <bl602_glb.h>
#include <bl602_dma.h>
#include <bl_irq.h>
#include <bl_dma.h>
#include <FreeRTOS.h>
#include <task.h>
#include <timers.h>
#include <event_groups.h>
#include <libfdt.h>
#include <utils_log.h>
#include <blog.h>
#define HAL_SPI_DEBUG (0)
#define HAL_SPI_HARDCS (1)
#define SPI_NUM_MAX 1 /* only support spi0 */
#define LLI_BUFF_SIZE 2048
#define EVT_GROUP_SPI_DMA_TX (1<<0)
#define EVT_GROUP_SPI_DMA_RX (1<<1)
#define EVT_GROUP_SPI_DMA_TR (EVT_GROUP_SPI_DMA_TX | EVT_GROUP_SPI_DMA_RX)
typedef struct _spi_hw {
uint8_t used;
SPI_ID_Type ssp_id;
uint8_t mode;
uint32_t freq;
uint8_t polar_phase;
uint8_t tx_dma_ch;
uint8_t rx_dma_ch;
uint8_t pin_clk;
uint8_t pin_cs;
uint8_t pin_mosi;
uint8_t pin_miso;
EventGroupHandle_t spi_dma_event_group;
} spi_hw_t;
typedef struct spi_priv_data {
spi_hw_t hwspi[SPI_NUM_MAX];
} spi_priv_data_t;
spi_priv_data_t *g_hal_buf = NULL;
void bl_spi0_dma_int_handler_tx(void);
void bl_spi0_dma_int_handler_rx(void);
static void hal_gpio_init(spi_hw_t *arg)
{
uint8_t gpiopins[4];
if (!arg) {
blog_error("arg err.\r\n");
return;
}
gpiopins[0] = arg->pin_cs;
gpiopins[1] = arg->pin_clk;
gpiopins[2] = arg->pin_mosi;
gpiopins[3] = arg->pin_miso;
GLB_GPIO_Func_Init(GPIO_FUN_SPI,gpiopins,sizeof(gpiopins)/sizeof(gpiopins[0]));
if (arg->mode == 0) {
GLB_Set_SPI_0_ACT_MOD_Sel(GLB_SPI_PAD_ACT_AS_MASTER);
} else {
GLB_Set_SPI_0_ACT_MOD_Sel(GLB_SPI_PAD_ACT_AS_SLAVE);
}
return;
}
static int lli_list_init(DMA_LLI_Ctrl_Type **pptxlli, DMA_LLI_Ctrl_Type **pprxlli, uint8_t *ptx_data, uint8_t *prx_data, uint32_t length)
{
uint32_t i = 0;
uint32_t count;
uint32_t remainder;
struct DMA_Control_Reg dmactrl;
count = length / LLI_BUFF_SIZE;
remainder = length % LLI_BUFF_SIZE;
if (remainder != 0) {
count = count + 1;
}
dmactrl.SBSize = DMA_BURST_SIZE_1;
dmactrl.DBSize = DMA_BURST_SIZE_1;
dmactrl.SWidth = DMA_TRNS_WIDTH_8BITS;
dmactrl.DWidth = DMA_TRNS_WIDTH_8BITS;
dmactrl.Prot = 0;
dmactrl.SLargerD = 0;
*pptxlli = pvPortMalloc(sizeof(DMA_LLI_Ctrl_Type) * count);
if (*pptxlli == NULL) {
blog_error("malloc lli failed. \r\n");
return -1;
}
*pprxlli = pvPortMalloc(sizeof(DMA_LLI_Ctrl_Type) * count);
if (*pprxlli == NULL) {
blog_error("malloc lli failed.");
vPortFree(*pptxlli);
return -1;
}
for (i = 0; i < count; i++) {
if (remainder == 0) {
dmactrl.TransferSize = LLI_BUFF_SIZE;
} else {
if (i == count - 1) {
dmactrl.TransferSize = remainder;
} else {
dmactrl.TransferSize = LLI_BUFF_SIZE;
}
}
dmactrl.SI = DMA_MINC_ENABLE;
dmactrl.DI = DMA_MINC_DISABLE;
if (i == count - 1) {
dmactrl.I = 1;
} else {
dmactrl.I = 0;
}
(*pptxlli)[i].srcDmaAddr = (uint32_t)(ptx_data + i * LLI_BUFF_SIZE);
(*pptxlli)[i].destDmaAddr = (uint32_t)(SPI_BASE+SPI_FIFO_WDATA_OFFSET);
(*pptxlli)[i].dmaCtrl = dmactrl;
dmactrl.SI = DMA_MINC_DISABLE;
dmactrl.DI = DMA_MINC_ENABLE;
(*pprxlli)[i].srcDmaAddr = (uint32_t)(SPI_BASE+SPI_FIFO_RDATA_OFFSET);
(*pprxlli)[i].destDmaAddr = (uint32_t)(prx_data + i * LLI_BUFF_SIZE);
(*pprxlli)[i].dmaCtrl = dmactrl;
if (i != 0) {
(*pptxlli)[i-1].nextLLI = (uint32_t)&(*pptxlli)[i];
(*pprxlli)[i-1].nextLLI = (uint32_t)&(*pprxlli)[i];
}
(*pptxlli)[i].nextLLI = 0;
(*pprxlli)[i].nextLLI = 0;
}
return 0;
}
static void hal_spi_dma_init(spi_hw_t *arg)
{
spi_hw_t *hw_arg = arg;
SPI_CFG_Type spicfg;
SPI_ClockCfg_Type clockcfg;
SPI_FifoCfg_Type fifocfg;
SPI_ID_Type spi_id;
uint8_t clk_div;
spi_id = hw_arg->ssp_id;
/* clock */
/*1 ---> 40 Mhz
*2 ---> 20 Mhz
*5 ---> 8 Mhz
*6 ---> 6.66 Mhz
*10 ---> 4 Mhz
* */
clk_div = (uint8_t)(40000000 / hw_arg->freq);
GLB_Set_SPI_CLK(ENABLE,0);
clockcfg.startLen = clk_div;
clockcfg.stopLen = clk_div;
clockcfg.dataPhase0Len = clk_div;
clockcfg.dataPhase1Len = clk_div;
clockcfg.intervalLen = clk_div;
SPI_ClockConfig(spi_id, &clockcfg);
/* spi config */
spicfg.deglitchEnable = DISABLE;
spicfg.continuousEnable = ENABLE;
spicfg.byteSequence = SPI_BYTE_INVERSE_BYTE0_FIRST,
spicfg.bitSequence = SPI_BIT_INVERSE_MSB_FIRST,
spicfg.frameSize = SPI_FRAME_SIZE_8;
if (hw_arg->polar_phase == 0) {
spicfg.clkPhaseInv = SPI_CLK_PHASE_INVERSE_0;
spicfg.clkPolarity = SPI_CLK_POLARITY_LOW;
} else if (hw_arg->polar_phase == 1) {
spicfg.clkPhaseInv = SPI_CLK_PHASE_INVERSE_1;
spicfg.clkPolarity = SPI_CLK_POLARITY_LOW;
} else if (hw_arg->polar_phase == 2) {
spicfg.clkPhaseInv = SPI_CLK_PHASE_INVERSE_0;
spicfg.clkPolarity = SPI_CLK_POLARITY_HIGH;
} else if (hw_arg->polar_phase == 3) {
spicfg.clkPhaseInv = SPI_CLK_PHASE_INVERSE_1;
spicfg.clkPolarity = SPI_CLK_POLARITY_HIGH;
} else {
blog_error("node support polar_phase \r\n");
}
SPI_Init(0,&spicfg);
if (hw_arg->mode == 0)
{
SPI_Disable(spi_id, SPI_WORK_MODE_MASTER);
} else {
SPI_Disable(spi_id, SPI_WORK_MODE_SLAVE);
}
SPI_IntMask(spi_id,SPI_INT_ALL,MASK);
/* fifo */
fifocfg.txFifoThreshold = 1;
fifocfg.rxFifoThreshold = 1;
fifocfg.txFifoDmaEnable = ENABLE;
fifocfg.rxFifoDmaEnable = ENABLE;
SPI_FifoConfig(spi_id,&fifocfg);
DMA_Disable();
DMA_IntMask(hw_arg->tx_dma_ch, DMA_INT_ALL, MASK);
DMA_IntMask(hw_arg->tx_dma_ch, DMA_INT_TCOMPLETED, UNMASK);
DMA_IntMask(hw_arg->tx_dma_ch, DMA_INT_ERR, UNMASK);
DMA_IntMask(hw_arg->rx_dma_ch, DMA_INT_ALL, MASK);
DMA_IntMask(hw_arg->rx_dma_ch, DMA_INT_TCOMPLETED, UNMASK);
DMA_IntMask(hw_arg->rx_dma_ch, DMA_INT_ERR, UNMASK);
bl_irq_enable(DMA_ALL_IRQn);
bl_dma_irq_register(hw_arg->tx_dma_ch, bl_spi0_dma_int_handler_tx, NULL, NULL);
bl_dma_irq_register(hw_arg->rx_dma_ch, bl_spi0_dma_int_handler_rx, NULL, NULL);
return;
}
static void hal_spi_dma_trans(spi_hw_t *arg, uint8_t *TxData, uint8_t *RxData, uint32_t Len)
{
EventBits_t uxBits;
DMA_LLI_Cfg_Type txllicfg;
DMA_LLI_Cfg_Type rxllicfg;
DMA_LLI_Ctrl_Type *ptxlli;
DMA_LLI_Ctrl_Type *prxlli;
int ret;
if (!arg) {
blog_error("arg err.\r\n");
return;
}
txllicfg.dir = DMA_TRNS_M2P;
txllicfg.srcPeriph = DMA_REQ_NONE;
txllicfg.dstPeriph = DMA_REQ_SPI_TX;
rxllicfg.dir = DMA_TRNS_P2M;
rxllicfg.srcPeriph = DMA_REQ_SPI_RX;
rxllicfg.dstPeriph = DMA_REQ_NONE;
xEventGroupClearBits(arg->spi_dma_event_group, EVT_GROUP_SPI_DMA_TR);
DMA_Channel_Disable(arg->tx_dma_ch);
DMA_Channel_Disable(arg->rx_dma_ch);
bl_dma_int_clear(arg->tx_dma_ch);
bl_dma_int_clear(arg->rx_dma_ch);
DMA_Enable();
if (arg->mode == 0) {
SPI_Enable(arg->ssp_id, SPI_WORK_MODE_MASTER);
} else {
SPI_Enable(arg->ssp_id, SPI_WORK_MODE_SLAVE);
}
ret = lli_list_init(&ptxlli, &prxlli, TxData, RxData, Len);
if (ret < 0) {
blog_error("init lli failed. \r\n");
return;
}
DMA_LLI_Init(arg->tx_dma_ch, &txllicfg);
DMA_LLI_Init(arg->rx_dma_ch, &rxllicfg);
DMA_LLI_Update(arg->tx_dma_ch,(uint32_t)ptxlli);
DMA_LLI_Update(arg->rx_dma_ch,(uint32_t)prxlli);
DMA_Channel_Enable(arg->tx_dma_ch);
DMA_Channel_Enable(arg->rx_dma_ch);
uxBits = xEventGroupWaitBits(arg->spi_dma_event_group,
EVT_GROUP_SPI_DMA_TR,
pdTRUE,
pdTRUE,
portMAX_DELAY);
if ((uxBits & EVT_GROUP_SPI_DMA_TR) == EVT_GROUP_SPI_DMA_TR) {
blog_info("recv all event group.\r\n");
}
vPortFree(ptxlli);
vPortFree(prxlli);
}
int32_t hal_spi_init(spi_dev_t *spi)
{
int i;
spi_priv_data_t *data;
if (!spi) {
blog_error("arg err.\r\n");
}
data = (spi_priv_data_t *)spi->priv;
if (data == NULL) {
return -1;
}
for (i = 0; i < SPI_NUM_MAX; i++) {
hal_gpio_init(&data->hwspi[i]);
hal_spi_dma_init(&data->hwspi[i]);
}
#if (HAL_SPI_DEBUG)
blog_info("hal_spi_init.\r\n");
#endif
return 0;
}
int32_t hal_spi_finalize(spi_dev_t *spi)
{
blog_info("not support. hal_spi_finalize.\r\n");
return 0;
}
int32_t hal_spi_send(spi_dev_t *spi, const uint8_t *data, uint16_t size, uint32_t timeout)
{
blog_info("not support. hal_spi_send.\r\n");
return 0;
}
int32_t hal_spi_recv(spi_dev_t *spi, uint8_t *data, uint16_t size, uint32_t timeout)
{
blog_info("not support. hal_spi_recv.\r\n");
return 0;
}
int32_t hal_spi_send_recv(spi_dev_t *spi, uint8_t *tx_data, uint8_t *rx_data, uint16_t size, uint32_t timeout)
{
blog_info("not support. hal_spi_send_recv.\r\n");
return 0;
}
int hal_spi_set_rwmode(spi_dev_t *spi_dev, int mode)
{
spi_priv_data_t *data;
#if (HAL_SPI_DEBUG)
blog_info("set rwmode = %d\r\n", mode);
#endif
if ((mode < 0) || (mode > 3)) {
blog_error("mode is err.\r\n");
return -1;
}
data = (spi_priv_data_t *)spi_dev->priv;
data->hwspi[spi_dev->port].mode = mode;
spi_dev->config.mode = mode;
hal_spi_init(spi_dev);
return 0;
}
int hal_spi_set_rwspeed(spi_dev_t *spi_dev, uint32_t speed)
{
spi_priv_data_t *data;
int i;
uint8_t real_flag = 0;
uint32_t real_speed = 0;
#if (HAL_SPI_DEBUG)
blog_info("set rwspeed = %ld\r\n", speed);
#endif
if (spi_dev->config.freq == speed) {
blog_info("speed not change.\r\n");
return 0;
}
for (i = 0; i < 256; i++) {
if (speed == (40000000/(i+1))) {
real_speed = speed;
real_flag = 1;
} else if (speed < (40000000/(i+1))) {
continue;
} else {
break;
}
}
if (real_flag != 1) {
if (i == 0) {
blog_error("The max speed is 40000000 Hz, please set it smaller.");
return -1;
} else if (i == 256) {
blog_error("The min speed is 156250 Hz, please set it bigger.");
return -1;
} else {
if ( ((40000000/(i+1)) - speed) > (speed - (40000000/i)) ) {
real_speed = (40000000/(i+1));
blog_info("not support speed: %ld, change real_speed = %ld\r\n", speed, real_speed);
} else {
real_speed = (40000000/i);
blog_info("not support speed: %ld, change real_speed = %ld\r\n", speed, real_speed);
}
}
}
data = (spi_priv_data_t *)spi_dev->priv;
data->hwspi[spi_dev->port].freq = real_speed;
spi_dev->config.freq = real_speed;
hal_spi_init(spi_dev);
return 0;
}
int hal_spi_transfer(spi_dev_t *spi_dev, void *xfer, uint8_t size)
{
uint16_t i;
spi_ioc_transfer_t * s_xfer;
spi_priv_data_t *priv_data;
if ((!spi_dev) || (!xfer)) {
blog_error("arg err.\r\n");
return -1;
}
priv_data = (spi_priv_data_t *)spi_dev->priv;
if (priv_data == NULL) {
blog_error("priv_data NULL.\r\n");
return -1;
}
s_xfer = (spi_ioc_transfer_t *)xfer;
#if (HAL_SPI_DEBUG)
blog_info("hal_spi_transfer = %d\r\n", size);
#endif
#if (0 == HAL_SPI_HARDCS)
bl_gpio_output_set(priv_data->hwspi[spi_dev->port].pin_cs, 0);
#endif
for (i = 0; i < size; i++) {
#if (HAL_SPI_DEBUG)
blog_info("transfer xfer[%d].len = %ld\r\n", i, s_xfer[i].len);
#endif
hal_spi_dma_trans(&priv_data->hwspi[spi_dev->port],
(uint8_t *)s_xfer[i].tx_buf, (uint8_t *)s_xfer[i].rx_buf, s_xfer[i].len);
}
#if (0 == HAL_SPI_HARDCS)
bl_gpio_output_set(priv_data->hwspi[spi_dev->port].pin_cs, 1);
#endif
return 0;
}
int vfs_spi_init_fullname(const char *fullname, uint8_t port,
uint8_t mode, uint8_t polar_phase, uint32_t freq, uint8_t tx_dma_ch, uint8_t rx_dma_ch,
uint8_t pin_clk, uint8_t pin_cs, uint8_t pin_mosi, uint8_t pin_miso)
{
int ret, len;
spi_dev_t *spi;
len = strlen(fullname);
if (len + 1 > 32) {
blog_error("arg err.\r\n");
return -EINVAL;
}
//TODO use one bigger mem for these two small struct
if (NULL == g_hal_buf) {
g_hal_buf = (spi_priv_data_t*)aos_malloc(sizeof(spi_priv_data_t));
if (NULL == g_hal_buf) {
blog_error("mem err.\r\n");
return -ENOMEM;
}
memset(g_hal_buf, 0, sizeof(spi_priv_data_t));
}
g_hal_buf->hwspi[port].spi_dma_event_group = xEventGroupCreate();
blog_info("port%d eventloop init = %08lx\r\n", port,
(uint32_t)g_hal_buf->hwspi[port].spi_dma_event_group);
if (NULL == g_hal_buf->hwspi[port].spi_dma_event_group) {
aos_free(g_hal_buf);
return -ENOMEM;
}
spi = (spi_dev_t*)aos_malloc(sizeof(spi_dev_t));
if (NULL == spi) {
blog_error("mem err.\r\n");
vEventGroupDelete(g_hal_buf->hwspi[port].spi_dma_event_group);
aos_free(g_hal_buf);
return -ENOMEM;
}
memset(spi, 0, sizeof(spi_dev_t));
spi->port = port;
spi->config.mode = mode;
spi->config.freq = freq;
g_hal_buf->hwspi[port].ssp_id = port;
g_hal_buf->hwspi[port].mode = mode;
g_hal_buf->hwspi[port].polar_phase = polar_phase;
g_hal_buf->hwspi[port].freq = freq;
g_hal_buf->hwspi[port].tx_dma_ch = tx_dma_ch;
g_hal_buf->hwspi[port].rx_dma_ch = rx_dma_ch;
g_hal_buf->hwspi[port].pin_clk = pin_clk;
g_hal_buf->hwspi[port].pin_cs = pin_cs;
g_hal_buf->hwspi[port].pin_mosi = pin_mosi;
g_hal_buf->hwspi[port].pin_miso = pin_miso;
spi->priv = g_hal_buf;
blog_info("[HAL] [SPI] Register Under %s for :\r\nport=%d, mode=%d, polar_phase = %d, freq=%ld, tx_dma_ch=%d, rx_dma_ch=%d, pin_clk=%d, pin_cs=%d, pin_mosi=%d, pin_miso=%d\r\n",
fullname, port, mode, polar_phase, freq, tx_dma_ch, rx_dma_ch, pin_clk, pin_cs, pin_mosi, pin_miso);
ret = aos_register_driver(fullname, &spi_ops, spi);
if (ret != VFS_SUCCESS) {
aos_free(spi);
vEventGroupDelete(g_hal_buf->hwspi[port].spi_dma_event_group);
aos_free(g_hal_buf);
return ret;
}
return VFS_SUCCESS;
}
#define BL_FDT32_TO_U8(addr, byte_offset) ((uint8_t)fdt32_to_cpu(*(uint32_t *)((uint8_t *)addr + byte_offset)))
#define BL_FDT32_TO_U16(addr, byte_offset) ((uint16_t)fdt32_to_cpu(*(uint32_t *)((uint8_t *)addr + byte_offset)))
#define BL_FDT32_TO_U32(addr, byte_offset) ((uint32_t)fdt32_to_cpu(*(uint32_t *)((uint8_t *)addr + byte_offset)))
int spi_arg_set_fdt2(const void * fdt, uint32_t dtb_spi_offset)
{
#define SPI_MODULE_MAX 1
uint8_t port;
uint8_t mode;
uint8_t polar_phase;
uint32_t freq;
uint8_t tx_dma_ch;
uint8_t rx_dma_ch;
uint8_t pin_clk;
uint8_t pin_cs;
uint8_t pin_mosi;
uint8_t pin_miso;
char *path = NULL;
int offset1 = 0;
int offset2 = 0;
const uint32_t *addr_prop = 0;
int lentmp = 0;
const char *result = 0;
int countindex = 0;
int i;
int ret;
const char *spi_node[SPI_MODULE_MAX] = {
"spi@4000F000"
};
/* spi */
for (i = 0; i < SPI_MODULE_MAX; i++) {
/* get spi0 ? spi1 ? spi2 offset1 */
offset1 = fdt_subnode_offset(fdt, dtb_spi_offset, spi_node[i]);
if (0 >= offset1) {
continue;
}
result = fdt_stringlist_get(fdt, offset1, "status", 0, &lentmp);
if ((lentmp != 4) || (memcmp("okay", result, 4) != 0)) {
blog_info("spi[%d] status != okay\r\n", i);
continue;
}
result = fdt_stringlist_get(fdt, offset1, "mode", 0, &lentmp);
if ((lentmp != 6 && lentmp != 5) || ((memcmp("master", result, 6) != 0) && (memcmp("slave", result, 5)))) {
blog_info("spi[%d] mode != master or slave\r\n", i);
continue;
}
if (memcmp("master", result, 6) == 0) {
mode = 0;
} else {
mode = 1;
}
/* set path */
countindex = fdt_stringlist_count(fdt, offset1, "path");
if (countindex != 1) {
blog_info("spi[%d] path_countindex = %d NULL.\r\n", i, countindex);
continue;
}
result = fdt_stringlist_get(fdt, offset1, "path", 0, &lentmp);
if ((lentmp < 0) || (lentmp > 32)) {
blog_info("spi[%d] path lentmp = %d\r\n", i, lentmp);
}
path = (char *)result;
/* sure port == i */
addr_prop = fdt_getprop(fdt, offset1, "port", &lentmp);
if (addr_prop == NULL) {
blog_info("spi[%d] port NULL.\r\n", i);
continue;
}
port = BL_FDT32_TO_U8(addr_prop, 0);
if (port != i) {
blog_error("fdt err. port[%d] != i[%d].\r\n", port, i);
continue;
}
/* get polar_phase */
addr_prop = fdt_getprop(fdt, offset1, "polar_phase", &lentmp);
if (addr_prop == NULL) {
blog_info("spi[%d] polar_phase NULL.\r\n", i);
continue;
}
polar_phase = BL_FDT32_TO_U8(addr_prop, 0);
/* get freq */
addr_prop = fdt_getprop(fdt, offset1, "freq", &lentmp);
if (addr_prop == NULL) {
blog_info("spi[%d] freq NULL.\r\n", i);
continue;
}
freq = BL_FDT32_TO_U32(addr_prop, 0);
/* set pin */
offset2 = fdt_subnode_offset(fdt, offset1, "pin");
if (0 >= offset1) {
continue;
}
/* get pin_clk */
addr_prop = fdt_getprop(fdt, offset2, "clk", &lentmp);
if (addr_prop == NULL) {
blog_info("spi[%d] clk NULL.\r\n", i);
continue;
}
pin_clk = BL_FDT32_TO_U8(addr_prop, 0);
/* get pin_cs */
addr_prop = fdt_getprop(fdt, offset2, "cs", &lentmp);
if (addr_prop == NULL) {
blog_info("spi[%d] cs NULL.\r\n", i);
continue;
}
pin_cs = BL_FDT32_TO_U8(addr_prop, 0);
/* get pin_mosi */
addr_prop = fdt_getprop(fdt, offset2, "mosi", &lentmp);
if (addr_prop == NULL) {
blog_info("spi[%d] mosi NULL.\r\n", i);
continue;
}
pin_mosi = BL_FDT32_TO_U8(addr_prop, 0);
/* get pin_miso */
addr_prop = fdt_getprop(fdt, offset2, "miso", &lentmp);
if (addr_prop == NULL) {
blog_info("spi[%d] miso NULL.\r\n", i);
continue;
}
pin_miso = BL_FDT32_TO_U8(addr_prop, 0);
/* set dma_cfg */
offset2 = fdt_subnode_offset(fdt, offset1, "dma_cfg");
if (0 >= offset1) {
continue;
}
/* get tx_dma_ch */
addr_prop = fdt_getprop(fdt, offset2, "tx_dma_ch", &lentmp);
if (addr_prop == NULL) {
blog_info("spi[%d] tx_dma_ch NULL.\r\n", i);
continue;
}
tx_dma_ch = BL_FDT32_TO_U8(addr_prop, 0);
/* get rx_dma_ch */
addr_prop = fdt_getprop(fdt, offset2, "rx_dma_ch", &lentmp);
if (addr_prop == NULL) {
blog_info("spi[%d] rx_dma_ch NULL.\r\n", i);
continue;
}
rx_dma_ch = BL_FDT32_TO_U8(addr_prop, 0);
ret = vfs_spi_init_fullname((const char *)path, port, mode, polar_phase, freq, tx_dma_ch, rx_dma_ch, pin_clk, pin_cs, pin_mosi, pin_miso);
if (ret == 0) {
blog_info("init ok and read %08lx\r\n", (uint32_t)g_hal_buf->hwspi[0].spi_dma_event_group);
} else {
blog_info("spi init failed \r\n");
}
}
return 0;
}
int vfs_spi_fdt_init(uint32_t fdt, uint32_t dtb_spi_offset)
{
spi_arg_set_fdt2((const void *)fdt, dtb_spi_offset);
blog_info("vfs_spi_fdt_init ok.\r\n");
return 0;
}
void bl_spi0_dma_int_handler_tx(void)
{
BaseType_t xResult = pdFAIL;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (NULL != g_hal_buf) {
bl_dma_int_clear(g_hal_buf->hwspi[0].tx_dma_ch);
if (g_hal_buf->hwspi[0].spi_dma_event_group != NULL) {
xResult = xEventGroupSetBitsFromISR(g_hal_buf->hwspi[0].spi_dma_event_group,
EVT_GROUP_SPI_DMA_TX,
&xHigherPriorityTaskWoken);
}
if(xResult != pdFAIL) {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
} else {
blog_error("bl_spi0_dma_int_handler_tx no clear isr.\r\n");
}
return;
}
void bl_spi0_dma_int_handler_rx(void)
{
BaseType_t xResult = pdFAIL;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (NULL != g_hal_buf) {
bl_dma_int_clear(g_hal_buf->hwspi[0].rx_dma_ch);
if (g_hal_buf->hwspi[0].spi_dma_event_group != NULL) {
xResult = xEventGroupSetBitsFromISR(g_hal_buf->hwspi[0].spi_dma_event_group,
EVT_GROUP_SPI_DMA_RX,
&xHigherPriorityTaskWoken);
}
if(xResult != pdFAIL) {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
} else {
blog_error("bl_spi0_dma_int_handler_rx no clear isr.\r\n");
}
return;
}